Factor out the code for checking that all indices in a getelementptr are
authorDan Gohman <gohman@apple.com>
Thu, 10 Sep 2009 23:37:55 +0000 (23:37 +0000)
committerDan Gohman <gohman@apple.com>
Thu, 10 Sep 2009 23:37:55 +0000 (23:37 +0000)
within the notional bounds of the static type of the getelementptr (which
is not the same as "inbounds") from GlobalOpt into a utility routine,
and use it in ConstantFold.cpp to check whether there are any mis-behaved
indices.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@81478 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Constants.h
lib/Transforms/IPO/GlobalOpt.cpp
lib/VMCore/ConstantFold.cpp
lib/VMCore/Constants.cpp
test/Transforms/InstCombine/getelementptr.ll

index 5fadbc251b37972072b31df71c17b6f01ebe8e5c..86d14912a4d486cac4d817705dbc95ef2b9613da 100644 (file)
@@ -713,6 +713,13 @@ public:
   /// and the getIndices() method may be used.
   bool hasIndices() const;
 
+  /// @brief Return true if this is a getelementptr expression and all
+  /// the index operands are compile-time known integers within the
+  /// corresponding notional static array extents. Note that this is
+  /// not equivalant to, a subset of, or a superset of the "inbounds"
+  /// property.
+  bool isGEPWithNoNotionalOverIndexing() const;
+
   /// Select constant expr
   ///
   static Constant *getSelect(Constant *C, Constant *V1, Constant *V2) {
index b995a3d2864da9726a336449dfa994d092a4744c..63bc03d7872bb6a12242e0e34fc5d9eafd3e3e40 100644 (file)
@@ -2045,25 +2045,14 @@ static bool isSimpleEnoughPointerToCommit(Constant *C, LLVMContext &Context) {
       if (!GV->hasDefinitiveInitializer())
         return false;
 
-      gep_type_iterator GEPI = gep_type_begin(CE), E = gep_type_end(CE);
-      User::op_iterator OI = next(CE->op_begin());
-
       // The first index must be zero.
-      ConstantInt *CI = dyn_cast<ConstantInt>(*OI);
+      ConstantInt *CI = dyn_cast<ConstantInt>(*next(CE->op_begin()));
       if (!CI || !CI->isZero()) return false;
-      ++GEPI;
-      ++OI;
 
       // The remaining indices must be compile-time known integers within the
-      // bounds of the corresponding static array types.
-      for (; GEPI != E; ++GEPI, ++OI) {
-        CI = dyn_cast<ConstantInt>(*OI);
-        if (!CI) return false;
-        if (const ArrayType *ATy = dyn_cast<ArrayType>(*GEPI))
-          if (CI->getValue().getActiveBits() > 64 ||
-              CI->getZExtValue() >= ATy->getNumElements())
-            return false;
-      }
+      // notional bounds of the corresponding static array types.
+      if (!CE->isGEPWithNoNotionalOverIndexing())
+        return false;
 
       return ConstantFoldLoadThroughGEPConstantExpr(GV->getInitializer(), CE,
                                                     Context);
index 701a195f7fded11d9703b9bebf30e2d54bf42b53..da6c8d4f4bc1a7245b86d3e17fc98e8c31c255ad 100644 (file)
@@ -1329,6 +1329,14 @@ static ICmpInst::Predicate evaluateICmpRelation(LLVMContext &Context,
             // ordering of the resultant pointers.
             unsigned i = 1;
 
+            // The logic below assumes that the result of the comparison
+            // can be determined by finding the first index that differs.
+            // This doesn't work if there is over-indexing in any
+            // subsequent indices, so check for that case first.
+            if (!CE1->isGEPWithNoNotionalOverIndexing() ||
+                !CE2->isGEPWithNoNotionalOverIndexing())
+               return ICmpInst::BAD_ICMP_PREDICATE; // Might be equal.
+
             // Compare all of the operands the GEP's have in common.
             gep_type_iterator GTI = gep_type_begin(CE1);
             for (;i != CE1->getNumOperands() && i != CE2->getNumOperands();
index a5b4f289688b417473d2c2337c39c694f7372cd4..54445cd782687cb577ea9e8861fc3655d37564cc 100644 (file)
@@ -28,6 +28,7 @@
 #include "llvm/Support/ManagedStatic.h"
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/GetElementPtrTypeIterator.h"
 #include "llvm/System/Mutex.h"
 #include "llvm/System/RWMutex.h"
 #include "llvm/System/Threading.h"
@@ -652,6 +653,31 @@ bool ConstantExpr::isCompare() const {
   return getOpcode() == Instruction::ICmp || getOpcode() == Instruction::FCmp;
 }
 
+bool ConstantExpr::isGEPWithNoNotionalOverIndexing() const {
+  if (getOpcode() != Instruction::GetElementPtr) return false;
+
+  gep_type_iterator GEPI = gep_type_begin(this), E = gep_type_end(this);
+  User::const_op_iterator OI = next(this->op_begin());
+
+  // Skip the first index, as it has no static limit.
+  ++GEPI;
+  ++OI;
+
+  // The remaining indices must be compile-time known integers within the
+  // bounds of the corresponding notional static array types.
+  for (; GEPI != E; ++GEPI, ++OI) {
+    ConstantInt *CI = dyn_cast<ConstantInt>(*OI);
+    if (!CI) return false;
+    if (const ArrayType *ATy = dyn_cast<ArrayType>(*GEPI))
+      if (CI->getValue().getActiveBits() > 64 ||
+          CI->getZExtValue() >= ATy->getNumElements())
+        return false;
+  }
+
+  // All the indices checked out.
+  return true;
+}
+
 bool ConstantExpr::hasIndices() const {
   return getOpcode() == Instruction::ExtractValue ||
          getOpcode() == Instruction::InsertValue;
index aa39752c4602b87ed6d823fe138b5b5bcdcfd8e0..444a0ee9389eb7970c5023c33c392f408d311fb3 100644 (file)
@@ -459,3 +459,12 @@ define i8* @test36() nounwind {
 ; CHECK: ret i8* getelementptr ([11 x i8]* @array, i64 1676976733973595601, i64 4)
 }
 
+; Instcombine shouldn't assume that gep(A,0,1) != gep(A,1,0).
+@A37 = external constant [1 x i8]
+define i1 @test37() nounwind {
+; CHECK: @test37
+; CHECK: ret i1 icmp eq (i8* getelementptr ([1 x i8]* @A37, i64 0, i64 1), i8* getelementptr ([1 x i8]* @A37, i64 1, i64 0))
+  %t = icmp eq i8* getelementptr ([1 x i8]* @A37, i64 0, i64 1),
+                   getelementptr ([1 x i8]* @A37, i64 1, i64 0)
+  ret i1 %t
+}