[PowerPC] Don't apply the PPC64 address-formation peephole for offsets greater than 7
authorHal Finkel <hfinkel@anl.gov>
Fri, 2 Sep 2016 00:28:20 +0000 (00:28 +0000)
committerHal Finkel <hfinkel@anl.gov>
Fri, 2 Sep 2016 00:28:20 +0000 (00:28 +0000)
When applying our address-formation PPC64 peephole, we are reusing the @ha TOC
addis value with the low parts associated with different offsets (i.e.
different effective symbol addends). We were assuming this was okay so long as
the offsets were less than the alignment of the global variable being accessed.
This ignored the fact, however, that the TOC base pointer itself need only be
8-byte aligned. As a result, what we were doing is legal only for offsets less
than 8 regardless of the alignment of the object being accessed.

Fixes PR28727.

llvm-svn: 280441

llvm/lib/Target/PowerPC/PPCISelDAGToDAG.cpp
llvm/test/CodeGen/PowerPC/peephole-align.ll

index f30aecf..23ee3e7 100644 (file)
@@ -4370,10 +4370,15 @@ void PPCDAGToDAGISel::PeepholePPC64() {
     }
 
     SDValue ImmOpnd = Base.getOperand(1);
-    int MaxDisplacement = 0;
+
+    // On PPC64, the TOC base pointer is guaranteed by the ABI only to have
+    // 8-byte alignment, and so we can only use offsets less than 8 (otherwise,
+    // we might have needed different @ha relocation values for the offset
+    // pointers).
+    int MaxDisplacement = 7;
     if (GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(ImmOpnd)) {
       const GlobalValue *GV = GA->getGlobal();
-      MaxDisplacement = GV->getAlignment() - 1;
+      MaxDisplacement = std::min((int) GV->getAlignment() - 1, MaxDisplacement);
     }
 
     int Offset = N->getConstantOperandVal(FirstOp);
index cb0dde9..1be8417 100644 (file)
@@ -208,12 +208,13 @@ entry:
 
 ; CHECK-LABEL: test_d2:
 ; CHECK: addis [[REGSTRUCT:[0-9]+]], 2, d2v@toc@ha
+; CHECK: addi [[BASEV:[0-9]+]], [[REGSTRUCT]], d2v@toc@l
 ; CHECK-DAG: ld [[REG0_0:[0-9]+]], d2v@toc@l([[REGSTRUCT]])
-; CHECK-DAG: ld [[REG1_0:[0-9]+]], d2v@toc@l+8([[REGSTRUCT]])
+; CHECK-DAG: ld [[REG1_0:[0-9]+]], 8([[BASEV]])
 ; CHECK-DAG: addi [[REG0_1:[0-9]+]], [[REG0_0]], 1
 ; CHECK-DAG: addi [[REG1_1:[0-9]+]], [[REG1_0]], 2
 ; CHECK-DAG: std [[REG0_1]], d2v@toc@l([[REGSTRUCT]])
-; CHECK-DAG: std [[REG1_1]], d2v@toc@l+8([[REGSTRUCT]])
+; CHECK-DAG: std [[REG1_1]], 8([[BASEV]])
 
 define void @test_d2() nounwind {
 entry:
@@ -229,7 +230,8 @@ entry:
 ; register 3 is the return value, so it should be chosen
 ; CHECK-LABEL: test_singleuse:
 ; CHECK: addis 3, 2, d2v@toc@ha
-; CHECK: ld 3, d2v@toc@l+8(3)
+; CHECK: addi 3, 3, d2v@toc@l
+; CHECK: ld 3, 8(3)
 define i64 @test_singleuse() nounwind {
 entry:
   %0 = load i64, i64* getelementptr inbounds (%struct.d2, %struct.d2* @d2v, i32 0, i32 1), align 8