Factor out the code for checking that all indices in a getelementptr are
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
diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h
index 5fadbc2..86d1491 100644
--- a/include/llvm/Constants.h
+++ b/include/llvm/Constants.h
@@ -713,6 +713,13 @@
   /// 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) {
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp
index b995a3d..63bc03d 100644
--- a/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/lib/Transforms/IPO/GlobalOpt.cpp
@@ -2045,25 +2045,14 @@
       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);
diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp
index 701a195..da6c8d4 100644
--- a/lib/VMCore/ConstantFold.cpp
+++ b/lib/VMCore/ConstantFold.cpp
@@ -1329,6 +1329,14 @@
             // 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();
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index a5b4f28..54445cd 100644
--- a/lib/VMCore/Constants.cpp
+++ b/lib/VMCore/Constants.cpp
@@ -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 @@
   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;
diff --git a/test/Transforms/InstCombine/getelementptr.ll b/test/Transforms/InstCombine/getelementptr.ll
index aa39752..444a0ee 100644
--- a/test/Transforms/InstCombine/getelementptr.ll
+++ b/test/Transforms/InstCombine/getelementptr.ll
@@ -459,3 +459,12 @@
 ; 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
+}