ConstantFolding: Fix a crash when encoutering a truncating inttoptr.
authorBenjamin Kramer <benny.kra@googlemail.com>
Tue, 5 Feb 2013 19:04:36 +0000 (19:04 +0000)
committerBenjamin Kramer <benny.kra@googlemail.com>
Tue, 5 Feb 2013 19:04:36 +0000 (19:04 +0000)
This was introduced in r173293.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@174424 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ConstantFolding.cpp
test/Transforms/InstSimplify/ptr_diff.ll

index 400ce72ce6acf52e97e00f2c20b327ecf739080a..91424b22366cada74932e4614d79cf2d9dfe7906 100644 (file)
@@ -545,14 +545,18 @@ static Constant *SymbolicallyEvaluateBinop(unsigned Opc, Constant *Op0,
   // constant.  This happens frequently when iterating over a global array.
   if (Opc == Instruction::Sub && TD) {
     GlobalValue *GV1, *GV2;
-    APInt Offs1(TD->getPointerSizeInBits(), 0),
-          Offs2(TD->getPointerSizeInBits(), 0);
+    unsigned PtrSize = TD->getPointerSizeInBits();
+    unsigned OpSize = TD->getTypeSizeInBits(Op0->getType());
+    APInt Offs1(PtrSize, 0), Offs2(PtrSize, 0);
 
     if (IsConstantOffsetFromGlobal(Op0, GV1, Offs1, *TD))
       if (IsConstantOffsetFromGlobal(Op1, GV2, Offs2, *TD) &&
           GV1 == GV2) {
         // (&GV+C1) - (&GV+C2) -> C1-C2, pointer arithmetic cannot overflow.
-        return ConstantInt::get(Op0->getType(), Offs1-Offs2);
+        // PtrToInt may change the bitwidth so we have convert to the right size
+        // first.
+        return ConstantInt::get(Op0->getType(), Offs1.zextOrTrunc(OpSize) -
+                                                Offs2.zextOrTrunc(OpSize));
       }
   }
 
index 86516280696a93df762ba4afdc7ee4802c5718ad..8b4aa796013bc20175522be46e63843c6f29a948 100644 (file)
@@ -57,3 +57,22 @@ define <4 x i32> @ptrdiff4(<4 x i8*> %arg) nounwind {
   %sub = sub <4 x i32> %p1, %p2
   ret <4 x i32> %sub
 }
+
+%struct.ham = type { i32, [2 x [2 x i32]] }
+
+@global = internal global %struct.ham zeroinitializer, align 4
+
+define i32 @ptrdiff5() nounwind {
+bb:
+  %tmp = getelementptr inbounds %struct.ham* @global, i32 0, i32 1
+  %tmp1 = getelementptr inbounds [2 x [2 x i32]]* %tmp, i32 0, i32 0
+  %tmp2 = bitcast [2 x i32]* %tmp1 to i32*
+  %tmp3 = ptrtoint i32* %tmp2 to i32
+  %tmp4 = getelementptr inbounds %struct.ham* @global, i32 0, i32 1
+  %tmp5 = getelementptr inbounds [2 x [2 x i32]]* %tmp4, i32 0, i32 0
+  %tmp6 = ptrtoint [2 x i32]* %tmp5 to i32
+  %tmp7 = sub i32 %tmp3, %tmp6
+  ret i32 %tmp7
+; CHECK: @ptrdiff5
+; CHECK: ret i32 0
+}