[llvm-commits] [llvm] r79485 - in /llvm/trunk: lib/Analysis/ConstantFolding.cpp test/Transforms/InstCombine/constant-fold-gep-overindex.ll

Dan Gohman gohman at apple.com
Wed Aug 19 15:46:59 PDT 2009


Author: djg
Date: Wed Aug 19 17:46:59 2009
New Revision: 79485

URL: http://llvm.org/viewvc/llvm-project?rev=79485&view=rev
Log:
Fix a bug in the over-index constant folding. When over-indexing an
array member of a struct, it's possible to land in an arbitrary position
inside that struct, such that attempting to find further getelementptr
indices will fail. In such cases, folding cannot be done.

Added:
    llvm/trunk/test/Transforms/InstCombine/constant-fold-gep-overindex.ll
Modified:
    llvm/trunk/lib/Analysis/ConstantFolding.cpp

Modified: llvm/trunk/lib/Analysis/ConstantFolding.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ConstantFolding.cpp?rev=79485&r1=79484&r2=79485&view=diff

==============================================================================
--- llvm/trunk/lib/Analysis/ConstantFolding.cpp (original)
+++ llvm/trunk/lib/Analysis/ConstantFolding.cpp Wed Aug 19 17:46:59 2009
@@ -165,8 +165,11 @@
   // Also, this helps GlobalOpt do SROA on GlobalVariables.
   const Type *Ty = Ptr->getType();
   SmallVector<Constant*, 32> NewIdxs;
-  for (unsigned Index = 1; Index != NumOps; ++Index) {
+  do {
     if (const SequentialType *ATy = dyn_cast<SequentialType>(Ty)) {
+      // The only pointer indexing we'll do is on the first index of the GEP.
+      if (isa<PointerType>(ATy) && ATy != Ptr->getType())
+        break;
       // Determine which element of the array the offset points into.
       uint64_t ElemSize = TD->getTypeAllocSize(ATy->getElementType());
       if (ElemSize == 0)
@@ -183,20 +186,33 @@
       Offset -= SL.getElementOffset(ElIdx);
       Ty = STy->getTypeAtIndex(ElIdx);
     } else {
-      return 0;
+      // We've reached some non-indexable type.
+      break;
     }
-  }
+  } while (Ty != cast<PointerType>(ResultTy)->getElementType());
+
+  // If we haven't used up the entire offset by descending the static
+  // type, then the offset is pointing into the middle of an indivisible
+  // member, so we can't simplify it.
+  if (Offset != 0)
+    return 0;
 
   // If the base is the start of a GlobalVariable and all the array indices
   // remain in their static bounds, the GEP is inbounds. We can check that
   // all indices are in bounds by just checking the first index only
   // because we've just normalized all the indices.
-  if (isa<GlobalVariable>(Ptr) && NewIdxs[0]->isNullValue())
-    return ConstantExpr::getInBoundsGetElementPtr(Ptr,
-                                                  &NewIdxs[0], NewIdxs.size());
+  Constant *C = isa<GlobalVariable>(Ptr) && NewIdxs[0]->isNullValue() ?
+    ConstantExpr::getInBoundsGetElementPtr(Ptr, &NewIdxs[0], NewIdxs.size()) :
+    ConstantExpr::getGetElementPtr(Ptr, &NewIdxs[0], NewIdxs.size());
+  assert(cast<PointerType>(C->getType())->getElementType() == Ty &&
+         "Computed GetElementPtr has unexpected type!");
+
+  // If we ended up indexing a member with a type that doesn't match
+  // type type of what the original indices indexed, add a cast.
+  if (Ty != cast<PointerType>(ResultTy)->getElementType())
+    C = ConstantExpr::getBitCast(C, ResultTy);
 
-  // Otherwise it may not be inbounds.
-  return ConstantExpr::getGetElementPtr(Ptr, &NewIdxs[0], NewIdxs.size());
+  return C;
 }
 
 /// FoldBitCast - Constant fold bitcast, symbolically evaluating it with 

Added: llvm/trunk/test/Transforms/InstCombine/constant-fold-gep-overindex.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/InstCombine/constant-fold-gep-overindex.ll?rev=79485&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/constant-fold-gep-overindex.ll (added)
+++ llvm/trunk/test/Transforms/InstCombine/constant-fold-gep-overindex.ll Wed Aug 19 17:46:59 2009
@@ -0,0 +1,17 @@
+; RUN: llvm-as < %s | opt -instcombine
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128"
+target triple = "i386-apple-darwin10.0"
+
+%0 = type { i8*, [19 x i8] }
+%1 = type { i8*, [0 x i8] }
+
+ at s = external global %0                           ; <%0*> [#uses=1]
+@"\01LC8" = external constant [17 x i8]           ; <[17 x i8]*> [#uses=1]
+
+define i32 @main() nounwind {
+entry:
+  %0 = call i32 (i8*, ...)* @printf(i8* getelementptr ([17 x i8]* @"\01LC8", i32 0, i32 0), i8* undef, i8* getelementptr (%1* bitcast (%0* @s to %1*), i32 0, i32 1, i32 0)) nounwind ; <i32> [#uses=0]
+  ret i32 0
+}
+
+declare i32 @printf(i8*, ...) nounwind





More information about the llvm-commits mailing list