[llvm-commits] [llvm] r81478 - in /llvm/trunk: include/llvm/Constants.h lib/Transforms/IPO/GlobalOpt.cpp lib/VMCore/ConstantFold.cpp lib/VMCore/Constants.cpp test/Transforms/InstCombine/getelementptr.ll

Dan Gohman gohman at apple.com
Thu Sep 10 16:37:56 PDT 2009


Author: djg
Date: Thu Sep 10 18:37:55 2009
New Revision: 81478

URL: http://llvm.org/viewvc/llvm-project?rev=81478&view=rev
Log:
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.

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

Modified: llvm/trunk/include/llvm/Constants.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Constants.h?rev=81478&r1=81477&r2=81478&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Constants.h (original)
+++ llvm/trunk/include/llvm/Constants.h Thu Sep 10 18:37:55 2009
@@ -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) {

Modified: llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp?rev=81478&r1=81477&r2=81478&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp (original)
+++ llvm/trunk/lib/Transforms/IPO/GlobalOpt.cpp Thu Sep 10 18:37:55 2009
@@ -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);

Modified: llvm/trunk/lib/VMCore/ConstantFold.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/ConstantFold.cpp?rev=81478&r1=81477&r2=81478&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/ConstantFold.cpp (original)
+++ llvm/trunk/lib/VMCore/ConstantFold.cpp Thu Sep 10 18:37:55 2009
@@ -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();

Modified: llvm/trunk/lib/VMCore/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/VMCore/Constants.cpp?rev=81478&r1=81477&r2=81478&view=diff

==============================================================================
--- llvm/trunk/lib/VMCore/Constants.cpp (original)
+++ llvm/trunk/lib/VMCore/Constants.cpp Thu Sep 10 18:37:55 2009
@@ -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;

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

==============================================================================
--- llvm/trunk/test/Transforms/InstCombine/getelementptr.ll (original)
+++ llvm/trunk/test/Transforms/InstCombine/getelementptr.ll Thu Sep 10 18:37:55 2009
@@ -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).
+ at 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
+}





More information about the llvm-commits mailing list