From: Dan Gohman Date: Tue, 28 Jul 2009 01:40:03 +0000 (+0000) Subject: Teach instcombine to respect and preserve inbounds. Add inbounds X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=d6aa02de1076c801ac41295156a2379637976918;p=oota-llvm.git Teach instcombine to respect and preserve inbounds. Add inbounds to a few tests where it is required for the expected transformation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@77290 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Analysis/ScalarEvolutionExpander.cpp b/lib/Analysis/ScalarEvolutionExpander.cpp index eb2236b2d77..e098ea256ff 100644 --- a/lib/Analysis/ScalarEvolutionExpander.cpp +++ b/lib/Analysis/ScalarEvolutionExpander.cpp @@ -349,7 +349,9 @@ Value *SCEVExpander::expandAddToGEP(const SCEV *const *op_begin, return GEP; } - // Insert a pretty getelementptr. + // Insert a pretty getelementptr. Note that this GEP is not marked inbounds, + // because ScalarEvolution may have changed the address arithmetic to + // compute a value which is beyond the end of the allocated object. Value *GEP = Builder.CreateGEP(V, GepIndices.begin(), GepIndices.end(), diff --git a/lib/Transforms/Scalar/InstructionCombining.cpp b/lib/Transforms/Scalar/InstructionCombining.cpp index 9a53ea65024..be43c55d6bc 100644 --- a/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/lib/Transforms/Scalar/InstructionCombining.cpp @@ -213,7 +213,7 @@ namespace { Instruction *FoldICmpDivCst(ICmpInst &ICI, BinaryOperator *DivI, ConstantInt *DivRHS); - Instruction *FoldGEPICmp(User *GEPLHS, Value *RHS, + Instruction *FoldGEPICmp(GEPOperator *GEPLHS, Value *RHS, ICmpInst::Predicate Cond, Instruction &I); Instruction *FoldShiftByConstant(Value *Op0, ConstantInt *Op1, BinaryOperator &I); @@ -5559,20 +5559,19 @@ static Value *EvaluateGEPOffsetExpression(User *GEP, Instruction &I, /// FoldGEPICmp - Fold comparisons between a GEP instruction and something /// else. At this point we know that the GEP is on the LHS of the comparison. -Instruction *InstCombiner::FoldGEPICmp(User *GEPLHS, Value *RHS, +Instruction *InstCombiner::FoldGEPICmp(GEPOperator *GEPLHS, Value *RHS, ICmpInst::Predicate Cond, Instruction &I) { - assert(isa(GEPLHS) && "LHS is not a getelementptr!"); - // Look through bitcasts. if (BitCastInst *BCI = dyn_cast(RHS)) RHS = BCI->getOperand(0); Value *PtrBase = GEPLHS->getOperand(0); - if (TD && PtrBase == RHS) { + if (TD && PtrBase == RHS && GEPLHS->isInBounds()) { // ((gep Ptr, OFFSET) cmp Ptr) ---> (OFFSET cmp 0). // This transformation (ignoring the base and scales) is valid because we - // know pointers can't overflow. See if we can output an optimized form. + // know pointers can't overflow since the gep is inbounds. See if we can + // output an optimized form. Value *Offset = EvaluateGEPOffsetExpression(GEPLHS, I, *this); // If not, synthesize the offset the hard way. @@ -5580,7 +5579,7 @@ Instruction *InstCombiner::FoldGEPICmp(User *GEPLHS, Value *RHS, Offset = EmitGEPOffset(GEPLHS, I, *this); return new ICmpInst(*Context, ICmpInst::getSignedPredicate(Cond), Offset, Context->getNullValue(Offset->getType())); - } else if (User *GEPRHS = dyn_cast(RHS)) { + } else if (GEPOperator *GEPRHS = dyn_cast(RHS)) { // If the base pointers are different, but the indices are the same, just // compare the base pointer. if (PtrBase != GEPRHS->getOperand(0)) { @@ -6345,10 +6344,10 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) { } // If we can optimize a 'icmp GEP, P' or 'icmp P, GEP', do so now. - if (User *GEP = dyn_cast(Op0)) + if (GEPOperator *GEP = dyn_cast(Op0)) if (Instruction *NI = FoldGEPICmp(GEP, Op1, I.getPredicate(), I)) return NI; - if (User *GEP = dyn_cast(Op1)) + if (GEPOperator *GEP = dyn_cast(Op1)) if (Instruction *NI = FoldGEPICmp(GEP, Op0, ICmpInst::getSwappedPredicate(I.getPredicate()), I)) return NI; @@ -8252,6 +8251,8 @@ Instruction *InstCombiner::commonPointerCastTransforms(CastInst &CI) { NewIndices.end(), ""); InsertNewInstBefore(NGEP, CI); NGEP->takeName(GEP); + if (cast(GEP)->isInBounds()) + cast(NGEP)->setIsInBounds(true); if (isa(CI)) return new BitCastInst(NGEP, CI.getType()); @@ -8981,8 +8982,11 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { // If we found a path from the src to dest, create the getelementptr now. if (SrcElTy == DstElTy) { SmallVector Idxs(NumZeros+1, ZeroUInt); - return GetElementPtrInst::Create(Src, Idxs.begin(), Idxs.end(), "", - ((Instruction*) NULL)); + Instruction *GEP = GetElementPtrInst::Create(Src, + Idxs.begin(), Idxs.end(), "", + ((Instruction*) NULL)); + cast(GEP)->setIsInBounds(true); + return GEP; } } @@ -10663,8 +10667,12 @@ Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) { } Value *Base = FixedOperands[0]; - return GetElementPtrInst::Create(Base, FixedOperands.begin()+1, - FixedOperands.end()); + GetElementPtrInst *GEP = + GetElementPtrInst::Create(Base, FixedOperands.begin()+1, + FixedOperands.end()); + if (cast(FirstInst)->isInBounds()) + cast(GEP)->setIsInBounds(true); + return GEP; } @@ -11055,8 +11063,12 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { // getelementptr instructions into a single instruction. // SmallVector SrcGEPOperands; - if (User *Src = dyn_cast(PtrOp)) + bool BothInBounds = cast(&GEP)->isInBounds(); + if (GEPOperator *Src = dyn_cast(PtrOp)) { SrcGEPOperands.append(Src->op_begin(), Src->op_end()); + if (!Src->isInBounds()) + BothInBounds = false; + } if (!SrcGEPOperands.empty()) { // Note that if our source is a gep chain itself that we wait for that @@ -11140,9 +11152,15 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { Indices.insert(Indices.end(), GEP.idx_begin()+1, GEP.idx_end()); } - if (!Indices.empty()) - return GetElementPtrInst::Create(SrcGEPOperands[0], Indices.begin(), - Indices.end(), GEP.getName()); + if (!Indices.empty()) { + GetElementPtrInst *NewGEP = GetElementPtrInst::Create(SrcGEPOperands[0], + Indices.begin(), + Indices.end(), + GEP.getName()); + if (BothInBounds) + cast(NewGEP)->setIsInBounds(true); + return NewGEP; + } } else if (GlobalValue *GV = dyn_cast(PtrOp)) { // GEP of global variable. If all of the indices for this GEP are @@ -11180,8 +11198,12 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { if (CATy->getElementType() == XTy->getElementType()) { // -> GEP i8* X, ... SmallVector Indices(GEP.idx_begin()+1, GEP.idx_end()); - return GetElementPtrInst::Create(X, Indices.begin(), Indices.end(), - GEP.getName()); + GetElementPtrInst *NewGEP = + GetElementPtrInst::Create(X, Indices.begin(), Indices.end(), + GEP.getName()); + if (cast(&GEP)->isInBounds()) + cast(NewGEP)->setIsInBounds(true); + return NewGEP; } else if (const ArrayType *XATy = dyn_cast(XTy->getElementType())) { // GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ... ? @@ -11208,8 +11230,11 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { Value *Idx[2]; Idx[0] = Context->getNullValue(Type::Int32Ty); Idx[1] = GEP.getOperand(1); - Value *V = InsertNewInstBefore( - GetElementPtrInst::Create(X, Idx, Idx + 2, GEP.getName()), GEP); + GetElementPtrInst *NewGEP = + GetElementPtrInst::Create(X, Idx, Idx + 2, GEP.getName()); + if (cast(&GEP)->isInBounds()) + cast(NewGEP)->setIsInBounds(true); + Value *V = InsertNewInstBefore(NewGEP, GEP); // V and GEP are both pointer types --> BitCast return new BitCastInst(V, GEP.getType()); } @@ -11271,6 +11296,8 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { Idx[1] = NewIdx; Instruction *NewGEP = GetElementPtrInst::Create(X, Idx, Idx + 2, GEP.getName()); + if (cast(&GEP)->isInBounds()) + cast(NewGEP)->setIsInBounds(true); NewGEP = InsertNewInstBefore(NewGEP, GEP); // The NewGEP must be pointer typed, so must the old one -> BitCast return new BitCastInst(NewGEP, GEP.getType()); @@ -11323,6 +11350,8 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { GetElementPtrInst::Create(BCI->getOperand(0), NewIndices.begin(), NewIndices.end()); if (NGEP->getType() == GEP.getType()) return NGEP; + if (cast(&GEP)->isInBounds()) + cast(NGEP)->setIsInBounds(true); InsertNewInstBefore(NGEP, GEP); NGEP->takeName(&GEP); return new BitCastInst(NGEP, GEP.getType()); @@ -11366,6 +11395,7 @@ Instruction *InstCombiner::visitAllocationInst(AllocationInst &AI) { Idx[1] = NullIdx; Value *V = GetElementPtrInst::Create(New, Idx, Idx + 2, New->getName()+".sub", It); + cast(V)->setIsInBounds(true); // Now make everything use the getelementptr instead of the original // allocation. @@ -11745,6 +11775,7 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) { CastOp = IC.InsertNewInstBefore( GetElementPtrInst::Create(CastOp, NewGEPIndices.begin(), NewGEPIndices.end()), SI); + cast(CastOp)->setIsInBounds(true); } if (Constant *C = dyn_cast(SIOp0)) @@ -12428,6 +12459,7 @@ Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) { Context->getPointerType(EI.getType(), AS),EI); GetElementPtrInst *GEP = GetElementPtrInst::Create(Ptr, EI.getOperand(1), I->getName()+".gep"); + cast(GEP)->setIsInBounds(true); InsertNewInstBefore(GEP, EI); return new LoadInst(GEP); } diff --git a/test/Transforms/InstCombine/2008-02-04-GEPIdxBug.ll b/test/Transforms/InstCombine/2008-02-04-GEPIdxBug.ll index 6814e2febce..064fbd13f70 100644 --- a/test/Transforms/InstCombine/2008-02-04-GEPIdxBug.ll +++ b/test/Transforms/InstCombine/2008-02-04-GEPIdxBug.ll @@ -10,7 +10,7 @@ define i32 @main() nounwind { entry: %orientations = alloca [1 x [1 x %struct.x]] ; <[1 x [1 x %struct.x]]*> [#uses=2] %tmp3 = call i32 @puts( i8* getelementptr ([6 x i8]* @.str, i32 0, i32 0) ) nounwind ; [#uses=0] - %tmp45 = getelementptr [1 x [1 x %struct.x]]* %orientations, i32 1, i32 0, i32 0 ; <%struct.x*> [#uses=1] + %tmp45 = getelementptr inbounds [1 x [1 x %struct.x]]* %orientations, i32 1, i32 0, i32 0 ; <%struct.x*> [#uses=1] %orientations62 = getelementptr [1 x [1 x %struct.x]]* %orientations, i32 0, i32 0, i32 0 ; <%struct.x*> [#uses=1] br label %bb10 @@ -18,7 +18,7 @@ bb10: ; preds = %bb10, %entry %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb10 ] ; [#uses=2] %tmp.0.reg2mem.0.rec = mul i32 %indvar, -1 ; [#uses=1] %tmp12.rec = add i32 %tmp.0.reg2mem.0.rec, -1 ; [#uses=1] - %tmp12 = getelementptr %struct.x* %tmp45, i32 %tmp12.rec ; <%struct.x*> [#uses=2] + %tmp12 = getelementptr inbounds %struct.x* %tmp45, i32 %tmp12.rec ; <%struct.x*> [#uses=2] %tmp16 = call i32 (i8*, ...)* @printf( i8* getelementptr ([12 x i8]* @.str1, i32 0, i32 0), %struct.x* %tmp12 ) nounwind ; [#uses=0] %tmp84 = icmp eq %struct.x* %tmp12, %orientations62 ; [#uses=1] %indvar.next = add i32 %indvar, 1 ; [#uses=1] diff --git a/test/Transforms/InstCombine/getelementptr-setcc.ll b/test/Transforms/InstCombine/getelementptr-setcc.ll index 0a6d720d74f..c90390ac1e6 100644 --- a/test/Transforms/InstCombine/getelementptr-setcc.ll +++ b/test/Transforms/InstCombine/getelementptr-setcc.ll @@ -2,28 +2,28 @@ ; RUN: not grep getelementptr define i1 @test1(i16* %P, i32 %I, i32 %J) { - %X = getelementptr i16* %P, i32 %I ; [#uses=1] - %Y = getelementptr i16* %P, i32 %J ; [#uses=1] + %X = getelementptr inbounds i16* %P, i32 %I ; [#uses=1] + %Y = getelementptr inbounds i16* %P, i32 %J ; [#uses=1] %C = icmp ult i16* %X, %Y ; [#uses=1] ret i1 %C } define i1 @test2(i16* %P, i32 %I) { - %X = getelementptr i16* %P, i32 %I ; [#uses=1] + %X = getelementptr inbounds i16* %P, i32 %I ; [#uses=1] %C = icmp ult i16* %X, %P ; [#uses=1] ret i1 %C } define i32 @test3(i32* %P, i32 %A, i32 %B) { - %tmp.4 = getelementptr i32* %P, i32 %A ; [#uses=1] - %tmp.9 = getelementptr i32* %P, i32 %B ; [#uses=1] + %tmp.4 = getelementptr inbounds i32* %P, i32 %A ; [#uses=1] + %tmp.9 = getelementptr inbounds i32* %P, i32 %B ; [#uses=1] %tmp.10 = icmp eq i32* %tmp.4, %tmp.9 ; [#uses=1] %tmp.11 = zext i1 %tmp.10 to i32 ; [#uses=1] ret i32 %tmp.11 } define i32 @test4(i32* %P, i32 %A, i32 %B) { - %tmp.4 = getelementptr i32* %P, i32 %A ; [#uses=1] + %tmp.4 = getelementptr inbounds i32* %P, i32 %A ; [#uses=1] %tmp.6 = icmp eq i32* %tmp.4, %P ; [#uses=1] %tmp.7 = zext i1 %tmp.6 to i32 ; [#uses=1] ret i32 %tmp.7 diff --git a/test/Transforms/InstCombine/getelementptr-seteq.ll b/test/Transforms/InstCombine/getelementptr-seteq.ll index 05cec622b2a..2cd6f77b89f 100644 --- a/test/Transforms/InstCombine/getelementptr-seteq.ll +++ b/test/Transforms/InstCombine/getelementptr-seteq.ll @@ -5,8 +5,8 @@ %S = type { i32, [ 100 x i32] } define i1 @test(i64 %X, %S* %P) { - %A = getelementptr %S* %P, i32 0, i32 1, i64 %X - %B = getelementptr %S* %P, i32 0, i32 0 + %A = getelementptr inbounds %S* %P, i32 0, i32 1, i64 %X + %B = getelementptr inbounds %S* %P, i32 0, i32 0 %C = icmp eq i32* %A, %B ret i1 %C }