diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 5fadbc251b3..86d14912a4d 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 b995a3d2864..63bc03d7872 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(*OI); + ConstantInt *CI = dyn_cast(*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(*OI); - if (!CI) return false; - if (const ArrayType *ATy = dyn_cast(*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 701a195f7fd..da6c8d4f4bc 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 a5b4f289688..54445cd7826 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(*OI); + if (!CI) return false; + if (const ArrayType *ATy = dyn_cast(*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 aa39752c460..444a0ee9389 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 +}