aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/IR/ConstantFold.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/IR/ConstantFold.cpp')
-rw-r--r--llvm/lib/IR/ConstantFold.cpp106
1 files changed, 38 insertions, 68 deletions
diff --git a/llvm/lib/IR/ConstantFold.cpp b/llvm/lib/IR/ConstantFold.cpp
index a4df579..d4bc74e 100644
--- a/llvm/lib/IR/ConstantFold.cpp
+++ b/llvm/lib/IR/ConstantFold.cpp
@@ -1142,57 +1142,51 @@ static ICmpInst::Predicate areGlobalsPotentiallyEqual(const GlobalValue *GV1,
/// If we can determine that the two constants have a particular relation to
/// each other, we should return the corresponding ICmp predicate, otherwise
/// return ICmpInst::BAD_ICMP_PREDICATE.
-///
-/// To simplify this code we canonicalize the relation so that the first
-/// operand is always the most "complex" of the two. We consider simple
-/// constants (like ConstantInt) to be the simplest, followed by
-/// GlobalValues, followed by ConstantExpr's (the most complex).
-///
-static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2,
- bool isSigned) {
+static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2) {
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) &&
- !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 = nullptr;
- ICmpInst::Predicate pred = ICmpInst::ICMP_EQ;
- R = dyn_cast<ConstantInt>(ConstantExpr::getICmp(pred, V1, V2));
- if (R && !R->isZero())
- return pred;
- pred = isSigned ? ICmpInst::ICMP_SLT : ICmpInst::ICMP_ULT;
- R = dyn_cast<ConstantInt>(ConstantExpr::getICmp(pred, V1, V2));
- if (R && !R->isZero())
- return pred;
- pred = isSigned ? ICmpInst::ICMP_SGT : ICmpInst::ICMP_UGT;
- R = dyn_cast<ConstantInt>(ConstantExpr::getICmp(pred, V1, V2));
- if (R && !R->isZero())
- return pred;
-
- // If we couldn't figure it out, bail.
- return ICmpInst::BAD_ICMP_PREDICATE;
- }
-
- // If the first operand is simple, swap operands.
- ICmpInst::Predicate SwappedRelation =
- evaluateICmpRelation(V2, V1, isSigned);
+ // The following folds only apply to pointers.
+ if (!V1->getType()->isPointerTy())
+ return ICmpInst::BAD_ICMP_PREDICATE;
+
+ // To simplify this code we canonicalize the relation so that the first
+ // operand is always the most "complex" of the two. We consider simple
+ // constants (like ConstantPointerNull) to be the simplest, followed by
+ // BlockAddress, GlobalValues, and ConstantExpr's (the most complex).
+ auto GetComplexity = [](Constant *V) {
+ if (isa<ConstantExpr>(V))
+ return 3;
+ if (isa<GlobalValue>(V))
+ return 2;
+ if (isa<BlockAddress>(V))
+ return 1;
+ return 0;
+ };
+ if (GetComplexity(V1) < GetComplexity(V2)) {
+ ICmpInst::Predicate SwappedRelation = evaluateICmpRelation(V2, V1);
if (SwappedRelation != ICmpInst::BAD_ICMP_PREDICATE)
return ICmpInst::getSwappedPredicate(SwappedRelation);
+ return ICmpInst::BAD_ICMP_PREDICATE;
+ }
- } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(V1)) {
- if (isa<ConstantExpr>(V2)) { // Swap as necessary.
- ICmpInst::Predicate SwappedRelation =
- evaluateICmpRelation(V2, V1, isSigned);
- if (SwappedRelation != ICmpInst::BAD_ICMP_PREDICATE)
- return ICmpInst::getSwappedPredicate(SwappedRelation);
- return ICmpInst::BAD_ICMP_PREDICATE;
+ if (const BlockAddress *BA = dyn_cast<BlockAddress>(V1)) {
+ // Now we know that the RHS is a 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.
+ assert(isa<ConstantPointerNull>(V2) && "Canonicalization guarantee!");
+ return ICmpInst::ICMP_NE;
}
-
+ } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(V1)) {
// 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).
@@ -1212,30 +1206,6 @@ static ICmpInst::Predicate evaluateICmpRelation(Constant *V1, Constant *V2,
GV->getType()->getAddressSpace()))
return ICmpInst::ICMP_UGT;
}
- } else if (const BlockAddress *BA = dyn_cast<BlockAddress>(V1)) {
- if (isa<ConstantExpr>(V2)) { // Swap as necessary.
- ICmpInst::Predicate SwappedRelation =
- evaluateICmpRelation(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 global, block address, or a simple constant.
@@ -1429,7 +1399,7 @@ Constant *llvm::ConstantFoldCompareInstruction(CmpInst::Predicate Predicate,
} else {
// Evaluate the relation between the two constants, per the predicate.
int Result = -1; // -1 = unknown, 0 = known false, 1 = known true.
- switch (evaluateICmpRelation(C1, C2, CmpInst::isSigned(Predicate))) {
+ switch (evaluateICmpRelation(C1, C2)) {
default: llvm_unreachable("Unknown relational!");
case ICmpInst::BAD_ICMP_PREDICATE:
break; // Couldn't determine anything about these constants.