Index: llvm/include/llvm/Analysis/Utils/Local.h =================================================================== --- llvm/include/llvm/Analysis/Utils/Local.h +++ llvm/include/llvm/Analysis/Utils/Local.h @@ -22,19 +22,11 @@ /// Given a getelementptr instruction/constantexpr, emit the code necessary to /// compute the offset from the base pointer (without adding in the base /// pointer). Return the result as a signed integer of intptr size. -/// When NoAssumptions is true, no assumptions about index computation not -/// overflowing is made. template -Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP, - bool NoAssumptions = false) { - GEPOperator *GEPOp = cast(GEP); +Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &DL, User *GEP) { Type *IntPtrTy = DL.getIntPtrType(GEP->getType()); Value *Result = Constant::getNullValue(IntPtrTy); - // If the GEP is inbounds, we know that none of the addressing operations will - // overflow in an unsigned sense. - bool isInBounds = GEPOp->isInBounds() && !NoAssumptions; - // Build a mask for high order bits. unsigned IntPtrWidth = IntPtrTy->getScalarType()->getIntegerBitWidth(); uint64_t PtrSizeMask = @@ -66,7 +58,7 @@ Constant *Scale = ConstantInt::get(IntPtrTy, Size); Constant *OC = ConstantExpr::getIntegerCast(OpC, IntPtrTy, true /*SExt*/); - Scale = ConstantExpr::getMul(OC, Scale, isInBounds/*NUW*/); + Scale = ConstantExpr::getMul(OC, Scale); // Emit an add instruction. Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs"); continue; @@ -82,7 +74,7 @@ if (Size != 1) { // We'll let instcombine(mul) convert this to a shl if possible. Op = Builder->CreateMul(Op, ConstantInt::get(IntPtrTy, Size), - GEP->getName()+".idx", isInBounds /*NUW*/); + GEP->getName() + ".idx"); } // Emit an add instruction. Index: llvm/lib/Analysis/MemoryBuiltins.cpp =================================================================== --- llvm/lib/Analysis/MemoryBuiltins.cpp +++ llvm/lib/Analysis/MemoryBuiltins.cpp @@ -972,7 +972,7 @@ if (!bothKnown(PtrData)) return unknown(); - Value *Offset = EmitGEPOffset(&Builder, DL, &GEP, /*NoAssumptions=*/true); + Value *Offset = EmitGEPOffset(&Builder, DL, &GEP); Offset = Builder.CreateAdd(PtrData.second, Offset); return std::make_pair(PtrData.first, Offset); } Index: llvm/test/Transforms/InstCombine/gep-custom-dl.ll =================================================================== --- llvm/test/Transforms/InstCombine/gep-custom-dl.ll +++ llvm/test/Transforms/InstCombine/gep-custom-dl.ll @@ -101,7 +101,8 @@ define <2 x i1> @test6(<2 x i32> %X, <2 x %S*> %P) nounwind { ; CHECK-LABEL: @test6( -; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[A_IDX_MASK:%.*]] = and <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[A_IDX_MASK]], ; CHECK-NEXT: ret <2 x i1> [[C]] ; %A = getelementptr inbounds %S, <2 x %S*> %P, <2 x i32> zeroinitializer, <2 x i32> , <2 x i32> %X @@ -113,7 +114,8 @@ ; Same as above, but indices scalarized. define <2 x i1> @test6b(<2 x i32> %X, <2 x %S*> %P) nounwind { ; CHECK-LABEL: @test6b( -; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[A_IDX_MASK:%.*]] = and <2 x i32> [[X:%.*]], +; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i32> [[A_IDX_MASK]], ; CHECK-NEXT: ret <2 x i1> [[C]] ; %A = getelementptr inbounds %S, <2 x %S*> %P, i32 0, i32 1, <2 x i32> %X Index: llvm/test/Transforms/InstCombine/getelementptr.ll =================================================================== --- llvm/test/Transforms/InstCombine/getelementptr.ll +++ llvm/test/Transforms/InstCombine/getelementptr.ll @@ -175,10 +175,11 @@ ; CHECK: %C = icmp eq i64 %X, -1 } -; This is a test of icmp + shl nuw in disguise - 4611... is 0x3fff... +; This is a test of icmp + shl in disguise - 4611... is 0x3fff... define <2 x i1> @test13_vector(<2 x i64> %X, <2 x %S*> %P) nounwind { ; CHECK-LABEL: @test13_vector( -; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i64> %X, +; CHECK-NEXT: [[M:%.*]] = and <2 x i64> %X, +; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i64> [[M]], ; CHECK-NEXT: ret <2 x i1> [[C]] ; %A = getelementptr inbounds %S, <2 x %S*> %P, <2 x i64> zeroinitializer, <2 x i32> , <2 x i64> %X @@ -187,11 +188,11 @@ ret <2 x i1> %C } -; This is a test of icmp + shl nuw in disguise - 4611... is 0x3fff... +; This is a test of icmp + shl in disguise - 4611... is 0x3fff... define <2 x i1> @test13_vector2(i64 %X, <2 x %S*> %P) nounwind { ; CHECK-LABEL: @test13_vector2( ; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> undef, i64 [[X:%.*]], i32 0 -; CHECK-NEXT: [[TMP1:%.*]] = shl nuw <2 x i64> [[DOTSPLATINSERT]], +; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], ; CHECK-NEXT: [[A_IDX:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> undef, <2 x i32> zeroinitializer ; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], ; CHECK-NEXT: ret <2 x i1> [[C]] @@ -206,7 +207,7 @@ define <2 x i1> @test13_vector3(i64 %X, <2 x %S*> %P) nounwind { ; CHECK-LABEL: @test13_vector3( ; CHECK-NEXT: [[DOTSPLATINSERT:%.*]] = insertelement <2 x i64> undef, i64 [[X:%.*]], i32 0 -; CHECK-NEXT: [[TMP1:%.*]] = shl nuw <2 x i64> [[DOTSPLATINSERT]], +; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i64> [[DOTSPLATINSERT]], ; CHECK-NEXT: [[A_IDX:%.*]] = shufflevector <2 x i64> [[TMP1]], <2 x i64> undef, <2 x i32> zeroinitializer ; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i64> [[A_IDX]], ; CHECK-NEXT: ret <2 x i1> [[C]] @@ -227,10 +228,11 @@ ret i1 %C } -; This is a test of icmp + shl nuw in disguise - 16383 is 0x3fff. +; This is a test of icmp + shl in disguise - 16383 is 0x3fff. define <2 x i1> @test13_vector_as1(<2 x i16> %X, <2 x %S addrspace(1)*> %P) { ; CHECK-LABEL: @test13_vector_as1( -; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i16> %X, +; CHECK-NEXT: [[M:%.*]] = and <2 x i16> %X, +; CHECK-NEXT: [[C:%.*]] = icmp eq <2 x i16> [[M]], ; CHECK-NEXT: ret <2 x i1> [[C]] ; %A = getelementptr inbounds %S, <2 x %S addrspace(1)*> %P, <2 x i16> , <2 x i32> , <2 x i16> %X Index: llvm/test/Transforms/InstCombine/icmp-custom-dl.ll =================================================================== --- llvm/test/Transforms/InstCombine/icmp-custom-dl.ll +++ llvm/test/Transforms/InstCombine/icmp-custom-dl.ll @@ -45,7 +45,7 @@ ; CHECK-LABEL: @test60( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[I:%.*]] to i32 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[J:%.*]] to i32 -; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i32 [[TMP1]], 2 +; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i32 [[TMP1]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i32 [[GEP1_IDX]], [[TMP2]] ; CHECK-NEXT: ret i1 [[TMP3]] ; @@ -61,7 +61,7 @@ ; CHECK-LABEL: @test60_as1( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[I:%.*]] to i16 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[J:%.*]] to i16 -; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i16 [[TMP1]], 2 +; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i16 [[TMP1]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP2]] ; CHECK-NEXT: ret i1 [[TMP3]] ; @@ -93,7 +93,7 @@ define i1 @test60_addrspacecast_smaller(i8* %foo, i16 %i, i64 %j) { ; CHECK-LABEL: @test60_addrspacecast_smaller( -; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i16 [[I:%.*]], 2 +; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i16 [[I:%.*]], 2 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[J:%.*]] to i16 ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP1]] ; CHECK-NEXT: ret i1 [[TMP2]] Index: llvm/test/Transforms/InstCombine/icmp.ll =================================================================== --- llvm/test/Transforms/InstCombine/icmp.ll +++ llvm/test/Transforms/InstCombine/icmp.ll @@ -500,7 +500,8 @@ ; PR8882 define i1 @test24(i64 %i) { ; CHECK-LABEL: @test24( -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[I:%.*]], 1000 +; CHECK-NEXT: [[P1_IDX_MASK:%.*]] = and i64 [[I:%.*]], 4611686018427387903 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[P1_IDX_MASK]], 1000 ; CHECK-NEXT: ret i1 [[CMP]] ; %p1 = getelementptr inbounds i32, i32* getelementptr inbounds ([1000 x i32], [1000 x i32]* @X, i64 0, i64 0), i64 %i @@ -508,12 +509,29 @@ ret i1 %cmp } +; Note: offs can be negative, inbounds does not mean that p points to a single +; i32, it can point to an element of an i32 array. This case must be handled +; correctly. +define i1 @test24_neg_offs(i32* %p, i64 %offs) { +; CHECK-LABEL: @test24_neg_offs( +; CHECK-NEXT: [[P1_IDX_MASK:%.*]] = and i64 [[OFFS:%.*]], 4611686018427387903 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[P1_IDX_MASK]], 4611686018427387902 +; CHECK-NEXT: ret i1 [[CMP]] +; + %p1 = getelementptr inbounds i32, i32* %p, i64 %offs + %conv1 = ptrtoint i32* %p to i64 + %conv2 = ptrtoint i32* %p1 to i64 + %delta = sub i64 %conv1, %conv2 + %cmp = icmp eq i64 %delta, 8 + ret i1 %cmp +} + @X_as1 = addrspace(1) global [1000 x i32] zeroinitializer define i1 @test24_as1(i64 %i) { ; CHECK-LABEL: @test24_as1( -; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[I:%.*]] to i16 -; CHECK-NEXT: [[CMP:%.*]] = icmp eq i16 [[TMP1]], 1000 +; CHECK-NEXT: [[P1_IDX_MASK1:%.*]] = and i64 [[I:%.*]], 16383 +; CHECK-NEXT: [[CMP:%.*]] = icmp eq i64 [[P1_IDX_MASK1]], 1000 ; CHECK-NEXT: ret i1 [[CMP]] ; %p1 = getelementptr inbounds i32, i32 addrspace(1)* getelementptr inbounds ([1000 x i32], [1000 x i32] addrspace(1)* @X_as1, i64 0, i64 0), i64 %i @@ -1122,7 +1140,7 @@ define i1 @test60(i8* %foo, i64 %i, i64 %j) { ; CHECK-LABEL: @test60( -; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[I:%.*]], 2 +; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i64 [[I:%.*]], 2 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]] ; CHECK-NEXT: ret i1 [[TMP1]] ; @@ -1138,7 +1156,7 @@ ; CHECK-LABEL: @test60_as1( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[I:%.*]] to i16 ; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[J:%.*]] to i16 -; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i16 [[TMP1]], 2 +; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i16 [[TMP1]], 2 ; CHECK-NEXT: [[TMP3:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP2]] ; CHECK-NEXT: ret i1 [[TMP3]] ; @@ -1154,7 +1172,7 @@ ; bitcast. This uses the same sized addrspace. define i1 @test60_addrspacecast(i8* %foo, i64 %i, i64 %j) { ; CHECK-LABEL: @test60_addrspacecast( -; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[I:%.*]], 2 +; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i64 [[I:%.*]], 2 ; CHECK-NEXT: [[TMP1:%.*]] = icmp slt i64 [[GEP1_IDX]], [[J:%.*]] ; CHECK-NEXT: ret i1 [[TMP1]] ; @@ -1168,7 +1186,7 @@ define i1 @test60_addrspacecast_smaller(i8* %foo, i16 %i, i64 %j) { ; CHECK-LABEL: @test60_addrspacecast_smaller( -; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i16 [[I:%.*]], 2 +; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i16 [[I:%.*]], 2 ; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[J:%.*]] to i16 ; CHECK-NEXT: [[TMP2:%.*]] = icmp slt i16 [[GEP1_IDX]], [[TMP1]] ; CHECK-NEXT: ret i1 [[TMP2]] Index: llvm/test/Transforms/InstCombine/sub.ll =================================================================== --- llvm/test/Transforms/InstCombine/sub.ll +++ llvm/test/Transforms/InstCombine/sub.ll @@ -494,7 +494,7 @@ define i64 @test24b(i8* %P, i64 %A){ ; CHECK-LABEL: @test24b( -; CHECK-NEXT: [[B_IDX:%.*]] = shl nuw i64 [[A:%.*]], 1 +; CHECK-NEXT: [[B_IDX:%.*]] = shl i64 [[A:%.*]], 1 ; CHECK-NEXT: ret i64 [[B_IDX]] ; %B = getelementptr inbounds [42 x i16], [42 x i16]* @Arr, i64 0, i64 %A @@ -506,7 +506,7 @@ define i64 @test25(i8* %P, i64 %A){ ; CHECK-LABEL: @test25( -; CHECK-NEXT: [[B_IDX:%.*]] = shl nuw i64 [[A:%.*]], 1 +; CHECK-NEXT: [[B_IDX:%.*]] = shl i64 [[A:%.*]], 1 ; CHECK-NEXT: [[TMP1:%.*]] = add i64 [[B_IDX]], -84 ; CHECK-NEXT: ret i64 [[TMP1]] ; @@ -521,7 +521,7 @@ define i16 @test25_as1(i8 addrspace(1)* %P, i64 %A) { ; CHECK-LABEL: @test25_as1( ; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[A:%.*]] to i16 -; CHECK-NEXT: [[B_IDX:%.*]] = shl nuw i16 [[TMP1]], 1 +; CHECK-NEXT: [[B_IDX:%.*]] = shl i16 [[TMP1]], 1 ; CHECK-NEXT: [[TMP2:%.*]] = add i16 [[B_IDX]], -84 ; CHECK-NEXT: ret i16 [[TMP2]] ; @@ -668,7 +668,7 @@ define i64 @test30(i8* %foo, i64 %i, i64 %j) { ; CHECK-LABEL: @test30( -; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i64 [[I:%.*]], 2 +; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i64 [[I:%.*]], 2 ; CHECK-NEXT: [[TMP1:%.*]] = sub i64 [[GEP1_IDX]], [[J:%.*]] ; CHECK-NEXT: ret i64 [[TMP1]] ; @@ -683,7 +683,7 @@ define i16 @test30_as1(i8 addrspace(1)* %foo, i16 %i, i16 %j) { ; CHECK-LABEL: @test30_as1( -; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl nuw i16 [[I:%.*]], 2 +; CHECK-NEXT: [[GEP1_IDX:%.*]] = shl i16 [[I:%.*]], 2 ; CHECK-NEXT: [[TMP1:%.*]] = sub i16 [[GEP1_IDX]], [[J:%.*]] ; CHECK-NEXT: ret i16 [[TMP1]] ;