[SLSR] Fix crash on handling 128-bit integers.
authorJingyue Wu <jingyue@google.com>
Sat, 9 Jul 2016 19:13:18 +0000 (19:13 +0000)
committerJingyue Wu <jingyue@google.com>
Sat, 9 Jul 2016 19:13:18 +0000 (19:13 +0000)
ConstantInt::getSExtValue may fail on >64-bit integers. Add checks to call
getSExtValue only on narrow integers.

As a minor aside, simplify slsr-gep.ll to remove unnecessary load instructions.

llvm-svn: 274982

llvm/lib/Transforms/Scalar/StraightLineStrengthReduce.cpp
llvm/test/Transforms/StraightLineStrengthReduce/slsr-add.ll
llvm/test/Transforms/StraightLineStrengthReduce/slsr-gep.ll

index 411033b..77f0a78 100644 (file)
@@ -246,7 +246,9 @@ static bool isGEPFoldable(GetElementPtrInst *GEP,
 // Returns whether (Base + Index * Stride) can be folded to an addressing mode.
 static bool isAddFoldable(const SCEV *Base, ConstantInt *Index, Value *Stride,
                           TargetTransformInfo *TTI) {
-  return TTI->isLegalAddressingMode(Base->getType(), nullptr, 0, true,
+  // Index->getSExtValue() may crash if Index is wider than 64-bit.
+  return Index->getBitWidth() <= 64 &&
+         TTI->isLegalAddressingMode(Base->getType(), nullptr, 0, true,
                                     Index->getSExtValue(), UnknownAddressSpace);
 }
 
@@ -502,13 +504,23 @@ void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForGEP(
                                           IndexExprs, GEP->isInBounds());
     Value *ArrayIdx = GEP->getOperand(I);
     uint64_t ElementSize = DL->getTypeAllocSize(*GTI);
-    factorArrayIndex(ArrayIdx, BaseExpr, ElementSize, GEP);
+    if (ArrayIdx->getType()->getIntegerBitWidth() <=
+        DL->getPointerSizeInBits()) {
+      // Skip factoring if ArrayIdx is wider than the pointer size, because
+      // ArrayIdx is implicitly truncated to the pointer size.
+      factorArrayIndex(ArrayIdx, BaseExpr, ElementSize, GEP);
+    }
     // When ArrayIdx is the sext of a value, we try to factor that value as
     // well.  Handling this case is important because array indices are
     // typically sign-extended to the pointer size.
     Value *TruncatedArrayIdx = nullptr;
-    if (match(ArrayIdx, m_SExt(m_Value(TruncatedArrayIdx))))
+    if (match(ArrayIdx, m_SExt(m_Value(TruncatedArrayIdx))) &&
+        TruncatedArrayIdx->getType()->getIntegerBitWidth() <=
+            DL->getPointerSizeInBits()) {
+      // Skip factoring if TruncatedArrayIdx is wider than the pointer size,
+      // because TruncatedArrayIdx is implicitly truncated to the pointer size.
       factorArrayIndex(TruncatedArrayIdx, BaseExpr, ElementSize, GEP);
+    }
 
     IndexExprs[I - 1] = OrigIndexExpr;
   }
@@ -535,10 +547,11 @@ Value *StraightLineStrengthReduce::emitBump(const Candidate &Basis,
   if (Basis.CandidateKind == Candidate::GEP) {
     APInt ElementSize(
         IndexOffset.getBitWidth(),
-        DL->getTypeAllocSize(cast<GetElementPtrInst>(Basis.Ins)->getResultElementType()));
+        DL->getTypeAllocSize(
+            cast<GetElementPtrInst>(Basis.Ins)->getResultElementType()));
     APInt Q, R;
     APInt::sdivrem(IndexOffset, ElementSize, Q, R);
-    if (R.getSExtValue() == 0)
+    if (R == 0)
       IndexOffset = Q;
     else
       BumpWithUglyGEP = true;
@@ -546,10 +559,10 @@ Value *StraightLineStrengthReduce::emitBump(const Candidate &Basis,
 
   // Compute Bump = C - Basis = (i' - i) * S.
   // Common case 1: if (i' - i) is 1, Bump = S.
-  if (IndexOffset.getSExtValue() == 1)
+  if (IndexOffset == 1)
     return C.Stride;
   // Common case 2: if (i' - i) is -1, Bump = -S.
-  if (IndexOffset.getSExtValue() == -1)
+  if (IndexOffset.isAllOnesValue())
     return Builder.CreateNeg(C.Stride);
 
   // Otherwise, Bump = (i' - i) * sext/trunc(S). Note that (i' - i) and S may
index e25ddc2..b4f448a 100644 (file)
@@ -98,4 +98,19 @@ define void @simple_enough(i32 %b, i32 %s) {
   ret void
 }
 
+define void @slsr_strided_add_128bit(i128 %b, i128 %s) {
+; CHECK-LABEL: @slsr_strided_add_128bit(
+  %s125 = shl i128 %s, 125
+  %s126 = shl i128 %s, 126
+  %1 = add i128 %b, %s125
+; CHECK: [[t1:%[a-zA-Z0-9]+]] = add i128 %b, %s125
+  call void @bar(i128 %1)
+  %2 = add i128 %b, %s126
+; CHECK: [[t2:%[a-zA-Z0-9]+]] = add i128 [[t1]], %s125
+  call void @bar(i128 %2)
+; CHECK: call void @bar(i128 [[t2]])
+  ret void
+}
+
 declare void @foo(i32)
+declare void @bar(i128)
index bd92780..573c33c 100644 (file)
@@ -16,21 +16,18 @@ define void @slsr_gep(i32* %input, i64 %s) {
 ; CHECK-LABEL: @slsr_gep(
   ; v0 = input[0];
   %p0 = getelementptr inbounds i32, i32* %input, i64 0
-  %v0 = load i32, i32* %p0
-  call void @foo(i32 %v0)
+  call void @foo(i32* %p0)
 
   ; v1 = input[s];
   %p1 = getelementptr inbounds i32, i32* %input, i64 %s
 ; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i64 %s
-  %v1 = load i32, i32* %p1
-  call void @foo(i32 %v1)
+  call void @foo(i32* %p1)
 
   ; v2 = input[s * 2];
   %s2 = shl nsw i64 %s, 1
   %p2 = getelementptr inbounds i32, i32* %input, i64 %s2
 ; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 %s
-  %v2 = load i32, i32* %p2
-  call void @foo(i32 %v2)
+  call void @foo(i32* %p2)
 
   ret void
 }
@@ -49,23 +46,20 @@ define void @slsr_gep_sext(i32* %input, i32 %s) {
 ; CHECK-LABEL: @slsr_gep_sext(
   ; v0 = input[0];
   %p0 = getelementptr inbounds i32, i32* %input, i64 0
-  %v0 = load i32, i32* %p0
-  call void @foo(i32 %v0)
+  call void @foo(i32* %p0)
 
   ; v1 = input[s];
   %t = sext i32 %s to i64
   %p1 = getelementptr inbounds i32, i32* %input, i64 %t
 ; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i64 %t
-  %v1 = load i32, i32* %p1
-  call void @foo(i32 %v1)
+  call void @foo(i32* %p1)
 
   ; v2 = input[s * 2];
   %s2 = shl nsw i32 %s, 1
   %t2 = sext i32 %s2 to i64
   %p2 = getelementptr inbounds i32, i32* %input, i64 %t2
 ; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 %t
-  %v2 = load i32, i32* %p2
-  call void @foo(i32 %v2)
+  call void @foo(i32* %p2)
 
   ret void
 }
@@ -85,23 +79,20 @@ define void @slsr_gep_2d([10 x [5 x i32]]* %input, i64 %s, i64 %t) {
 ; CHECK-LABEL: @slsr_gep_2d(
   ; v0 = input[s][t];
   %p0 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s, i64 %t
-  %v0 = load i32, i32* %p0
-  call void @foo(i32 %v0)
+  call void @foo(i32* %p0)
 
   ; v1 = input[s * 2][t];
   %s2 = shl nsw i64 %s, 1
 ; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = mul i64 %s, 5
   %p1 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s2, i64 %t
 ; CHECK: %p1 = getelementptr inbounds i32, i32* %p0, i64 [[BUMP]]
-  %v1 = load i32, i32* %p1
-  call void @foo(i32 %v1)
+  call void @foo(i32* %p1)
 
   ; v3 = input[s * 3][t];
   %s3 = mul nsw i64 %s, 3
   %p2 = getelementptr inbounds [10 x [5 x i32]], [10 x [5 x i32]]* %input, i64 0, i64 %s3, i64 %t
 ; CHECK: %p2 = getelementptr inbounds i32, i32* %p1, i64 [[BUMP]]
-  %v2 = load i32, i32* %p2
-  call void @foo(i32 %v2)
+  call void @foo(i32* %p2)
 
   ret void
 }
@@ -118,23 +109,20 @@ define void @slsr_gep_uglygep([10 x [5 x %struct.S]]* %input, i64 %s, i64 %t) {
 ; CHECK-LABEL: @slsr_gep_uglygep(
   ; v0 = input[s][t].f1;
   %p0 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s, i64 %t, i32 0
-  %v0 = load i64, i64* %p0
-  call void @bar(i64 %v0)
+  call void @bar(i64* %p0)
 
   ; v1 = input[s * 2][t].f1;
   %s2 = shl nsw i64 %s, 1
 ; CHECK: [[BUMP:%[a-zA-Z0-9]+]] = mul i64 %s, 60
   %p1 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s2, i64 %t, i32 0
 ; CHECK: getelementptr inbounds i8, i8* %{{[0-9]+}}, i64 [[BUMP]]
-  %v1 = load i64, i64* %p1
-  call void @bar(i64 %v1)
+  call void @bar(i64* %p1)
 
   ; v2 = input[s * 3][t].f1;
   %s3 = mul nsw i64 %s, 3
   %p2 = getelementptr inbounds [10 x [5 x %struct.S]], [10 x [5 x %struct.S]]* %input, i64 0, i64 %s3, i64 %t, i32 0
 ; CHECK: getelementptr inbounds i8, i8* %{{[0-9]+}}, i64 [[BUMP]]
-  %v2 = load i64, i64* %p2
-  call void @bar(i64 %v2)
+  call void @bar(i64* %p2)
 
   ret void
 }
@@ -143,26 +131,44 @@ define void @slsr_out_of_bounds_gep(i32* %input, i32 %s) {
 ; CHECK-LABEL: @slsr_out_of_bounds_gep(
   ; v0 = input[0];
   %p0 = getelementptr i32, i32* %input, i64 0
-  %v0 = load i32, i32* %p0
-  call void @foo(i32 %v0)
+  call void @foo(i32* %p0)
 
   ; v1 = input[(long)s];
   %t = sext i32 %s to i64
   %p1 = getelementptr i32, i32* %input, i64 %t
 ; CHECK: %p1 = getelementptr i32, i32* %input, i64 %t
-  %v1 = load i32, i32* %p1
-  call void @foo(i32 %v1)
+  call void @foo(i32* %p1)
 
   ; v2 = input[(long)(s * 2)];
   %s2 = shl nsw i32 %s, 1
   %t2 = sext i32 %s2 to i64
   %p2 = getelementptr i32, i32* %input, i64 %t2
 ; CHECK: %p2 = getelementptr i32, i32* %p1, i64 %t
-  %v2 = load i32, i32* %p2
-  call void @foo(i32 %v2)
+  call void @foo(i32* %p2)
 
   ret void
 }
 
-declare void @foo(i32)
-declare void @bar(i64)
+define void @slsr_gep_128bit(i32* %input, i128 %s) {
+; CHECK-LABEL: @slsr_gep_128bit(
+  ; p0 = &input[0]
+  %p0 = getelementptr inbounds i32, i32* %input, i128 0
+  call void @foo(i32* %p0)
+
+  ; p1 = &input[s << 125]
+  %s125 = shl nsw i128 %s, 125
+  %p1 = getelementptr inbounds i32, i32* %input, i128 %s125
+; CHECK: %p1 = getelementptr inbounds i32, i32* %input, i128 %s125
+  call void @foo(i32* %p1)
+
+  ; p2 = &input[s << 126]
+  %s126 = shl nsw i128 %s, 126
+  %p2 = getelementptr inbounds i32, i32* %input, i128 %s126
+; CHECK: %p2 = getelementptr inbounds i32, i32* %input, i128 %s126
+  call void @foo(i32* %p2)
+
+  ret void
+}
+
+declare void @foo(i32*)
+declare void @bar(i64*)