summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2009-09-10 23:37:55 +0000
committerDan Gohman <gohman@apple.com>2009-09-10 23:37:55 +0000
commite6992f728a94654e43269580a10a667f18dadba9 (patch)
tree5e6c18363d9917d22eec2a3f54d9c9c24dd37aee
parent83e3c4f9d796a5da223a3ebd5d4ba985c7ecc39d (diff)
downloadllvm-e6992f728a94654e43269580a10a667f18dadba9.tar.gz
llvm-e6992f728a94654e43269580a10a667f18dadba9.tar.bz2
llvm-e6992f728a94654e43269580a10a667f18dadba9.tar.xz
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
-rw-r--r--include/llvm/Constants.h7
-rw-r--r--lib/Transforms/IPO/GlobalOpt.cpp19
-rw-r--r--lib/VMCore/ConstantFold.cpp8
-rw-r--r--lib/VMCore/Constants.cpp26
-rw-r--r--test/Transforms/InstCombine/getelementptr.ll9
5 files changed, 54 insertions, 15 deletions
diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h
index 5fadbc251b..86d14912a4 100644
--- a/include/llvm/Constants.h
+++ b/include/llvm/Constants.h
@@ -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) {
diff --git a/lib/Transforms/IPO/GlobalOpt.cpp b/lib/Transforms/IPO/GlobalOpt.cpp
index b995a3d286..63bc03d787 100644
--- a/lib/Transforms/IPO/GlobalOpt.cpp
+++ b/lib/Transforms/IPO/GlobalOpt.cpp
@@ -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);
diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp
index 701a195f7f..da6c8d4f4b 100644
--- a/lib/VMCore/ConstantFold.cpp
+++ b/lib/VMCore/ConstantFold.cpp
@@ -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();
diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp
index a5b4f28968..54445cd782 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 @@ 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;
diff --git a/test/Transforms/InstCombine/getelementptr.ll b/test/Transforms/InstCombine/getelementptr.ll
index aa39752c46..444a0ee938 100644
--- a/test/Transforms/InstCombine/getelementptr.ll
+++ b/test/Transforms/InstCombine/getelementptr.ll
@@ -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
+}