From 6cdf2ea98e9952a57768a1fcdce8850089263260 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 10 Feb 2011 07:11:16 +0000 Subject: [PATCH] implement the first part of PR8882: when lowering an inbounds gep to explicit addressing, we know that none of the intermediate computation overflows. This could use review: it seems that the shifts certainly wouldn't overflow, but could the intermediate adds overflow if there is a negative index? Previously the testcase would instcombine to: define i1 @test(i64 %i) { %p1.idx.mask = and i64 %i, 4611686018427387903 %cmp = icmp eq i64 %p1.idx.mask, 1000 ret i1 %cmp } now we get: define i1 @test(i64 %i) { %cmp = icmp eq i64 %i, 1000 ret i1 %cmp } git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@125271 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../InstCombine/InstCombineAddSub.cpp | 23 ++++++++++++------- test/Transforms/InstCombine/icmp.ll | 16 +++++++++++++ test/Transforms/InstCombine/sub.ll | 4 ++-- 3 files changed, 33 insertions(+), 10 deletions(-) diff --git a/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/lib/Transforms/InstCombine/InstCombineAddSub.cpp index 91116ca27ad..b04a05b3b35 100644 --- a/lib/Transforms/InstCombine/InstCombineAddSub.cpp +++ b/lib/Transforms/InstCombine/InstCombineAddSub.cpp @@ -399,6 +399,10 @@ Value *InstCombiner::EmitGEPOffset(User *GEP) { const Type *IntPtrTy = TD.getIntPtrType(GEP->getContext()); 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 = cast(GEP)->isInBounds(); + // Build a mask for high order bits. unsigned IntPtrWidth = TD.getPointerSizeInBits(); uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth); @@ -414,31 +418,34 @@ Value *InstCombiner::EmitGEPOffset(User *GEP) { if (const StructType *STy = dyn_cast(*GTI)) { Size = TD.getStructLayout(STy)->getElementOffset(OpC->getZExtValue()); - Result = Builder->CreateAdd(Result, - ConstantInt::get(IntPtrTy, Size), - GEP->getName()+".offs"); + if (Size) + Result = Builder->CreateAdd(Result, ConstantInt::get(IntPtrTy, Size), + GEP->getName()+".offs", + isInBounds /*NUW*/); continue; } Constant *Scale = ConstantInt::get(IntPtrTy, Size); Constant *OC = ConstantExpr::getIntegerCast(OpC, IntPtrTy, true /*SExt*/); - Scale = ConstantExpr::getMul(OC, Scale); + Scale = ConstantExpr::getMul(OC, Scale, isInBounds/*NUW*/); // Emit an add instruction. - Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs"); + Result = Builder->CreateAdd(Result, Scale, GEP->getName()+".offs", + isInBounds /*NUW*/); continue; } // Convert to correct type. if (Op->getType() != IntPtrTy) Op = Builder->CreateIntCast(Op, IntPtrTy, true, Op->getName()+".c"); if (Size != 1) { - Constant *Scale = ConstantInt::get(IntPtrTy, Size); // We'll let instcombine(mul) convert this to a shl if possible. - Op = Builder->CreateMul(Op, Scale, GEP->getName()+".idx"); + Op = Builder->CreateMul(Op, ConstantInt::get(IntPtrTy, Size), + GEP->getName()+".idx", isInBounds /*NUW*/); } // Emit an add instruction. - Result = Builder->CreateAdd(Op, Result, GEP->getName()+".offs"); + Result = Builder->CreateAdd(Op, Result, GEP->getName()+".offs", + isInBounds /*NUW*/); } return Result; } diff --git a/test/Transforms/InstCombine/icmp.ll b/test/Transforms/InstCombine/icmp.ll index baff2cadded..72ada2476fd 100644 --- a/test/Transforms/InstCombine/icmp.ll +++ b/test/Transforms/InstCombine/icmp.ll @@ -1,5 +1,8 @@ ; RUN: opt < %s -instcombine -S | FileCheck %s +target datalayout = +"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64" + define i32 @test1(i32 %X) { entry: icmp slt i32 %X, 0 ; :0 [#uses=1] @@ -218,3 +221,16 @@ define i1 @test23(i32 %x) nounwind { %i4 = icmp eq i32 %i3, -1 ret i1 %i4 } + +@X = global [1000 x i32] zeroinitializer + +; PR8882 +; CHECK: @test24 +; CHECK: %cmp = icmp eq i64 %i, 1000 +; CHECK: ret i1 %cmp +define i1 @test24(i64 %i) { + %p1 = getelementptr inbounds i32* getelementptr inbounds ([1000 x i32]* @X, i64 0, i64 0), i64 %i + %cmp = icmp eq i32* %p1, getelementptr inbounds ([1000 x i32]* @X, i64 1, i64 0) + ret i1 %cmp +} + diff --git a/test/Transforms/InstCombine/sub.ll b/test/Transforms/InstCombine/sub.ll index 29d96a4d5c3..778a1b9db5d 100644 --- a/test/Transforms/InstCombine/sub.ll +++ b/test/Transforms/InstCombine/sub.ll @@ -256,7 +256,7 @@ define i64 @test24b(i8* %P, i64 %A){ %G = sub i64 %C, ptrtoint ([42 x i16]* @Arr to i64) ret i64 %G ; CHECK: @test24b -; CHECK-NEXT: shl i64 %A, 1 +; CHECK-NEXT: shl nuw i64 %A, 1 ; CHECK-NEXT: ret i64 } @@ -267,7 +267,7 @@ define i64 @test25(i8* %P, i64 %A){ %G = sub i64 %C, ptrtoint (i16* getelementptr ([42 x i16]* @Arr, i64 1, i64 0) to i64) ret i64 %G ; CHECK: @test25 -; CHECK-NEXT: shl i64 %A, 1 +; CHECK-NEXT: shl nuw i64 %A, 1 ; CHECK-NEXT: add i64 {{.*}}, -84 ; CHECK-NEXT: ret i64 } -- 2.34.1