[llvm-commits] [llvm] r77290 - in /llvm/trunk: lib/Analysis/ScalarEvolutionExpander.cpp lib/Transforms/Scalar/InstructionCombining.cpp test/Transforms/InstCombine/2008-02-04-GEPIdxBug.ll test/Transforms/InstCombine/getelementptr-setcc.ll test/Transforms/InstCombine/getelementptr-seteq.ll

Dan Gohman gohman at apple.com
Mon Jul 27 18:40:03 PDT 2009


Author: djg
Date: Mon Jul 27 20:40:03 2009
New Revision: 77290

URL: http://llvm.org/viewvc/llvm-project?rev=77290&view=rev
Log:
Teach instcombine to respect and preserve inbounds. Add inbounds
to a few tests where it is required for the expected transformation.

Modified:
    llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
    llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
    llvm/trunk/test/Transforms/InstCombine/2008-02-04-GEPIdxBug.ll
    llvm/trunk/test/Transforms/InstCombine/getelementptr-setcc.ll
    llvm/trunk/test/Transforms/InstCombine/getelementptr-seteq.ll

Modified: llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp?rev=77290&r1=77289&r2=77290&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolutionExpander.cpp Mon Jul 27 20:40:03 2009
@@ -349,7 +349,9 @@
     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(),

Modified: llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp?rev=77290&r1=77289&r2=77290&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/InstructionCombining.cpp Mon Jul 27 20:40:03 2009
@@ -213,7 +213,7 @@
     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 @@
 
 /// 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<GEPOperator>(GEPLHS) && "LHS is not a getelementptr!");
-
   // Look through bitcasts.
   if (BitCastInst *BCI = dyn_cast<BitCastInst>(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 @@
       Offset = EmitGEPOffset(GEPLHS, I, *this);
     return new ICmpInst(*Context, ICmpInst::getSignedPredicate(Cond), Offset,
                         Context->getNullValue(Offset->getType()));
-  } else if (User *GEPRHS = dyn_cast<GEPOperator>(RHS)) {
+  } else if (GEPOperator *GEPRHS = dyn_cast<GEPOperator>(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 @@
   }
 
   // If we can optimize a 'icmp GEP, P' or 'icmp P, GEP', do so now.
-  if (User *GEP = dyn_cast<GEPOperator>(Op0))
+  if (GEPOperator *GEP = dyn_cast<GEPOperator>(Op0))
     if (Instruction *NI = FoldGEPICmp(GEP, Op1, I.getPredicate(), I))
       return NI;
-  if (User *GEP = dyn_cast<GEPOperator>(Op1))
+  if (GEPOperator *GEP = dyn_cast<GEPOperator>(Op1))
     if (Instruction *NI = FoldGEPICmp(GEP, Op0,
                            ICmpInst::getSwappedPredicate(I.getPredicate()), I))
       return NI;
@@ -8252,6 +8251,8 @@
                                                         NewIndices.end(), "");
           InsertNewInstBefore(NGEP, CI);
           NGEP->takeName(GEP);
+          if (cast<GEPOperator>(GEP)->isInBounds())
+            cast<GEPOperator>(NGEP)->setIsInBounds(true);
           
           if (isa<BitCastInst>(CI))
             return new BitCastInst(NGEP, CI.getType());
@@ -8981,8 +8982,11 @@
     // If we found a path from the src to dest, create the getelementptr now.
     if (SrcElTy == DstElTy) {
       SmallVector<Value*, 8> 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<GEPOperator>(GEP)->setIsInBounds(true);
+      return GEP;
     }
   }
 
@@ -10663,8 +10667,12 @@
   }
   
   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<GEPOperator>(FirstInst)->isInBounds())
+    cast<GEPOperator>(GEP)->setIsInBounds(true);
+  return GEP;
 }
 
 
@@ -11055,8 +11063,12 @@
   // getelementptr instructions into a single instruction.
   //
   SmallVector<Value*, 8> SrcGEPOperands;
-  if (User *Src = dyn_cast<GEPOperator>(PtrOp))
+  bool BothInBounds = cast<GEPOperator>(&GEP)->isInBounds();
+  if (GEPOperator *Src = dyn_cast<GEPOperator>(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 @@
       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<GEPOperator>(NewGEP)->setIsInBounds(true);
+      return NewGEP;
+    }
 
   } else if (GlobalValue *GV = dyn_cast<GlobalValue>(PtrOp)) {
     // GEP of global variable.  If all of the indices for this GEP are
@@ -11180,8 +11198,12 @@
         if (CATy->getElementType() == XTy->getElementType()) {
           // -> GEP i8* X, ...
           SmallVector<Value*, 8> 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<GEPOperator>(&GEP)->isInBounds())
+            cast<GEPOperator>(NewGEP)->setIsInBounds(true);
+          return NewGEP;
         } else if (const ArrayType *XATy =
                  dyn_cast<ArrayType>(XTy->getElementType())) {
           // GEP (bitcast [10 x i8]* X to [0 x i8]*), i32 0, ... ?
@@ -11208,8 +11230,11 @@
         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<GEPOperator>(&GEP)->isInBounds())
+          cast<GEPOperator>(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 @@
           Idx[1] = NewIdx;
           Instruction *NewGEP =
             GetElementPtrInst::Create(X, Idx, Idx + 2, GEP.getName());
+          if (cast<GEPOperator>(&GEP)->isInBounds())
+            cast<GEPOperator>(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 @@
            GetElementPtrInst::Create(BCI->getOperand(0), NewIndices.begin(),
                                      NewIndices.end());
         if (NGEP->getType() == GEP.getType()) return NGEP;
+        if (cast<GEPOperator>(&GEP)->isInBounds())
+          cast<GEPOperator>(NGEP)->setIsInBounds(true);
         InsertNewInstBefore(NGEP, GEP);
         NGEP->takeName(&GEP);
         return new BitCastInst(NGEP, GEP.getType());
@@ -11366,6 +11395,7 @@
       Idx[1] = NullIdx;
       Value *V = GetElementPtrInst::Create(New, Idx, Idx + 2,
                                            New->getName()+".sub", It);
+      cast<GEPOperator>(V)->setIsInBounds(true);
 
       // Now make everything use the getelementptr instead of the original
       // allocation.
@@ -11745,6 +11775,7 @@
       CastOp = IC.InsertNewInstBefore(
               GetElementPtrInst::Create(CastOp, NewGEPIndices.begin(),
                                         NewGEPIndices.end()), SI);
+    cast<GEPOperator>(CastOp)->setIsInBounds(true);
   }
   
   if (Constant *C = dyn_cast<Constant>(SIOp0))
@@ -12428,6 +12459,7 @@
                                   Context->getPointerType(EI.getType(), AS),EI);
         GetElementPtrInst *GEP =
           GetElementPtrInst::Create(Ptr, EI.getOperand(1), I->getName()+".gep");
+        cast<GEPOperator>(GEP)->setIsInBounds(true);
         InsertNewInstBefore(GEP, EI);
         return new LoadInst(GEP);
       }

Modified: llvm/trunk/test/Transforms/InstCombine/2008-02-04-GEPIdxBug.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/2008-02-04-GEPIdxBug.ll?rev=77290&r1=77289&r2=77290&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/2008-02-04-GEPIdxBug.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/2008-02-04-GEPIdxBug.ll Mon Jul 27 20:40:03 2009
@@ -10,7 +10,7 @@
 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 		; <i32> [#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 @@
 	%indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb10 ]		; <i32> [#uses=2]
 	%tmp.0.reg2mem.0.rec = mul i32 %indvar, -1		; <i32> [#uses=1]
 	%tmp12.rec = add i32 %tmp.0.reg2mem.0.rec, -1		; <i32> [#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 		; <i32> [#uses=0]
 	%tmp84 = icmp eq %struct.x* %tmp12, %orientations62		; <i1> [#uses=1]
 	%indvar.next = add i32 %indvar, 1		; <i32> [#uses=1]

Modified: llvm/trunk/test/Transforms/InstCombine/getelementptr-setcc.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/getelementptr-setcc.ll?rev=77290&r1=77289&r2=77290&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/getelementptr-setcc.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/getelementptr-setcc.ll Mon Jul 27 20:40:03 2009
@@ -2,28 +2,28 @@
 ; RUN:   not grep getelementptr
 
 define i1 @test1(i16* %P, i32 %I, i32 %J) {
-        %X = getelementptr i16* %P, i32 %I              ; <i16*> [#uses=1]
-        %Y = getelementptr i16* %P, i32 %J              ; <i16*> [#uses=1]
+        %X = getelementptr inbounds i16* %P, i32 %I              ; <i16*> [#uses=1]
+        %Y = getelementptr inbounds i16* %P, i32 %J              ; <i16*> [#uses=1]
         %C = icmp ult i16* %X, %Y               ; <i1> [#uses=1]
         ret i1 %C
 }
 
 define i1 @test2(i16* %P, i32 %I) {
-        %X = getelementptr i16* %P, i32 %I              ; <i16*> [#uses=1]
+        %X = getelementptr inbounds i16* %P, i32 %I              ; <i16*> [#uses=1]
         %C = icmp ult i16* %X, %P               ; <i1> [#uses=1]
         ret i1 %C
 }
 
 define i32 @test3(i32* %P, i32 %A, i32 %B) {
-        %tmp.4 = getelementptr i32* %P, i32 %A          ; <i32*> [#uses=1]
-        %tmp.9 = getelementptr i32* %P, i32 %B          ; <i32*> [#uses=1]
+        %tmp.4 = getelementptr inbounds i32* %P, i32 %A          ; <i32*> [#uses=1]
+        %tmp.9 = getelementptr inbounds i32* %P, i32 %B          ; <i32*> [#uses=1]
         %tmp.10 = icmp eq i32* %tmp.4, %tmp.9           ; <i1> [#uses=1]
         %tmp.11 = zext i1 %tmp.10 to i32                ; <i32> [#uses=1]
         ret i32 %tmp.11
 }
 
 define i32 @test4(i32* %P, i32 %A, i32 %B) {
-        %tmp.4 = getelementptr i32* %P, i32 %A          ; <i32*> [#uses=1]
+        %tmp.4 = getelementptr inbounds i32* %P, i32 %A          ; <i32*> [#uses=1]
         %tmp.6 = icmp eq i32* %tmp.4, %P                ; <i1> [#uses=1]
         %tmp.7 = zext i1 %tmp.6 to i32          ; <i32> [#uses=1]
         ret i32 %tmp.7

Modified: llvm/trunk/test/Transforms/InstCombine/getelementptr-seteq.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/getelementptr-seteq.ll?rev=77290&r1=77289&r2=77290&view=diff

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/getelementptr-seteq.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/getelementptr-seteq.ll Mon Jul 27 20:40:03 2009
@@ -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
 }





More information about the llvm-commits mailing list