diff options
author | Chris Lattner <sabre@nondot.org> | 2010-02-01 19:35:08 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2010-02-01 19:35:08 +0000 |
commit | b63127d4359d6a51c35f4ebfabfceac8bbd8364a (patch) | |
tree | 86bcdb0fe5754364ee20fdcc718db311a80bb8f0 | |
parent | c6654ec498698919ae8388c53fe91d0366ac24c7 (diff) |
fix PR6197 - infinite recursion in ipsccp due to block addresses
evaluateICmpRelation wasn't handling blockaddress.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94993 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/VMCore/ConstantFold.cpp | 66 | ||||
-rw-r--r-- | test/Transforms/ConstProp/basictest.ll | 12 |
2 files changed, 59 insertions, 19 deletions
diff --git a/lib/VMCore/ConstantFold.cpp b/lib/VMCore/ConstantFold.cpp index c22c3e975b..5e4b472097 100644 --- a/lib/VMCore/ConstantFold.cpp +++ b/lib/VMCore/ConstantFold.cpp @@ -1506,15 +1506,16 @@ static FCmpInst::Predicate evaluateFCmpRelation(LLVMContext &Context, /// GlobalValues, followed by ConstantExpr's (the most complex). /// static ICmpInst::Predicate evaluateICmpRelation(LLVMContext &Context, - Constant *V1, - Constant *V2, + Constant *V1, Constant *V2, bool isSigned) { assert(V1->getType() == V2->getType() && "Cannot compare different types of values!"); if (V1 == V2) return ICmpInst::ICMP_EQ; - if (!isa<ConstantExpr>(V1) && !isa<GlobalValue>(V1)) { - if (!isa<GlobalValue>(V2) && !isa<ConstantExpr>(V2)) { + if (!isa<ConstantExpr>(V1) && !isa<GlobalValue>(V1) && + !isa<BlockAddress>(V1)) { + if (!isa<GlobalValue>(V2) && !isa<ConstantExpr>(V2) && + !isa<BlockAddress>(V2)) { // We distilled this down to a simple case, use the standard constant // folder. ConstantInt *R = 0; @@ -1541,32 +1542,59 @@ static ICmpInst::Predicate evaluateICmpRelation(LLVMContext &Context, if (SwappedRelation != ICmpInst::BAD_ICMP_PREDICATE) return ICmpInst::getSwappedPredicate(SwappedRelation); - } else if (const GlobalValue *CPR1 = dyn_cast<GlobalValue>(V1)) { + } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(V1)) { if (isa<ConstantExpr>(V2)) { // Swap as necessary. ICmpInst::Predicate SwappedRelation = evaluateICmpRelation(Context, V2, V1, isSigned); if (SwappedRelation != ICmpInst::BAD_ICMP_PREDICATE) return ICmpInst::getSwappedPredicate(SwappedRelation); - else - return ICmpInst::BAD_ICMP_PREDICATE; + return ICmpInst::BAD_ICMP_PREDICATE; } - // Now we know that the RHS is a GlobalValue or simple constant, - // which (since the types must match) means that it's a ConstantPointerNull. - if (const GlobalValue *CPR2 = dyn_cast<GlobalValue>(V2)) { + // Now we know that the RHS is a GlobalValue, BlockAddress or simple + // constant (which, since the types must match, means that it's a + // ConstantPointerNull). + if (const GlobalValue *GV2 = dyn_cast<GlobalValue>(V2)) { // Don't try to decide equality of aliases. - if (!isa<GlobalAlias>(CPR1) && !isa<GlobalAlias>(CPR2)) - if (!CPR1->hasExternalWeakLinkage() || !CPR2->hasExternalWeakLinkage()) + if (!isa<GlobalAlias>(GV) && !isa<GlobalAlias>(GV2)) + if (!GV->hasExternalWeakLinkage() || !GV2->hasExternalWeakLinkage()) return ICmpInst::ICMP_NE; + } else if (isa<BlockAddress>(V2)) { + return ICmpInst::ICMP_NE; // Globals never equal labels. } else { assert(isa<ConstantPointerNull>(V2) && "Canonicalization guarantee!"); - // GlobalVals can never be null. Don't try to evaluate aliases. - if (!CPR1->hasExternalWeakLinkage() && !isa<GlobalAlias>(CPR1)) + // GlobalVals can never be null unless they have external weak linkage. + // We don't try to evaluate aliases here. + if (!GV->hasExternalWeakLinkage() && !isa<GlobalAlias>(GV)) return ICmpInst::ICMP_NE; } + } else if (const BlockAddress *BA = dyn_cast<BlockAddress>(V1)) { + if (isa<ConstantExpr>(V2)) { // Swap as necessary. + ICmpInst::Predicate SwappedRelation = + evaluateICmpRelation(Context, V2, V1, isSigned); + if (SwappedRelation != ICmpInst::BAD_ICMP_PREDICATE) + return ICmpInst::getSwappedPredicate(SwappedRelation); + return ICmpInst::BAD_ICMP_PREDICATE; + } + + // Now we know that the RHS is a GlobalValue, BlockAddress or simple + // constant (which, since the types must match, means that it is a + // ConstantPointerNull). + if (const BlockAddress *BA2 = dyn_cast<BlockAddress>(V2)) { + // Block address in another function can't equal this one, but block + // addresses in the current function might be the same if blocks are + // empty. + if (BA2->getFunction() != BA->getFunction()) + return ICmpInst::ICMP_NE; + } else { + // Block addresses aren't null, don't equal the address of globals. + assert((isa<ConstantPointerNull>(V2) || isa<GlobalValue>(V2)) && + "Canonicalization guarantee!"); + return ICmpInst::ICMP_NE; + } } else { // Ok, the LHS is known to be a constantexpr. The RHS can be any of a - // constantexpr, a CPR, or a simple constant. + // constantexpr, a global, block address, or a simple constant. ConstantExpr *CE1 = cast<ConstantExpr>(V1); Constant *CE1Op0 = CE1->getOperand(0); @@ -1621,9 +1649,9 @@ static ICmpInst::Predicate evaluateICmpRelation(LLVMContext &Context, return ICmpInst::ICMP_EQ; } // Otherwise, we can't really say if the first operand is null or not. - } else if (const GlobalValue *CPR2 = dyn_cast<GlobalValue>(V2)) { + } else if (const GlobalValue *GV2 = dyn_cast<GlobalValue>(V2)) { if (isa<ConstantPointerNull>(CE1Op0)) { - if (CPR2->hasExternalWeakLinkage()) + if (GV2->hasExternalWeakLinkage()) // Weak linkage GVals could be zero or not. We're comparing it to // a null pointer, so its less-or-equal return isSigned ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE; @@ -1631,8 +1659,8 @@ static ICmpInst::Predicate evaluateICmpRelation(LLVMContext &Context, // If its not weak linkage, the GVal must have a non-zero address // so the result is less-than return isSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT; - } else if (const GlobalValue *CPR1 = dyn_cast<GlobalValue>(CE1Op0)) { - if (CPR1 == CPR2) { + } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CE1Op0)) { + if (GV == GV2) { // If this is a getelementptr of the same global, then it must be // different. Because the types must match, the getelementptr could // only have at most one index, and because we fold getelementptr's diff --git a/test/Transforms/ConstProp/basictest.ll b/test/Transforms/ConstProp/basictest.ll index 2edc55dbc1..14580c1eab 100644 --- a/test/Transforms/ConstProp/basictest.ll +++ b/test/Transforms/ConstProp/basictest.ll @@ -19,3 +19,15 @@ BB3: ret i32 %Ret } + +; PR6197 +define i1 @test2(i8* %f) nounwind { +entry: + %V = icmp ne i8* blockaddress(@test2, %bb), null + br label %bb +bb: + ret i1 %V + +; CHECK: @test2 +; CHECK: ret i1 true +} |