summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp120
1 files changed, 42 insertions, 78 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index e06ec3945e3..1ecd7aeb549 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -3102,90 +3102,54 @@ bool InstCombiner::replacedSelectWithOperand(SelectInst *SI,
/// If we have an icmp le or icmp ge instruction with a constant operand, turn
/// it into the appropriate icmp lt or icmp gt instruction. This transform
/// allows them to be folded in visitICmpInst.
-static ICmpInst *canonicalizeCmpWithConstant(ICmpInst &I,
- InstCombiner::BuilderTy &Builder) {
+static ICmpInst *canonicalizeCmpWithConstant(ICmpInst &I) {
+ ICmpInst::Predicate Pred = I.getPredicate();
+ if (Pred != ICmpInst::ICMP_SLE && Pred != ICmpInst::ICMP_SGE &&
+ Pred != ICmpInst::ICMP_ULE && Pred != ICmpInst::ICMP_UGE)
+ return nullptr;
+
Value *Op0 = I.getOperand(0);
Value *Op1 = I.getOperand(1);
+ auto *Op1C = dyn_cast<Constant>(Op1);
+ if (!Op1C)
+ return nullptr;
- if (auto *Op1C = dyn_cast<ConstantInt>(Op1)) {
- // For scalars, SimplifyICmpInst has already handled the edge cases for us,
- // so we just assert on them.
- APInt Op1Val = Op1C->getValue();
- switch (I.getPredicate()) {
- case ICmpInst::ICMP_ULE:
- assert(!Op1C->isMaxValue(false)); // A <=u MAX -> TRUE
- return new ICmpInst(ICmpInst::ICMP_ULT, Op0, Builder.getInt(Op1Val + 1));
- case ICmpInst::ICMP_SLE:
- assert(!Op1C->isMaxValue(true)); // A <=s MAX -> TRUE
- return new ICmpInst(ICmpInst::ICMP_SLT, Op0, Builder.getInt(Op1Val + 1));
- case ICmpInst::ICMP_UGE:
- assert(!Op1C->isMinValue(false)); // A >=u MIN -> TRUE
- return new ICmpInst(ICmpInst::ICMP_UGT, Op0, Builder.getInt(Op1Val - 1));
- case ICmpInst::ICMP_SGE:
- assert(!Op1C->isMinValue(true)); // A >=s MIN -> TRUE
- return new ICmpInst(ICmpInst::ICMP_SGT, Op0, Builder.getInt(Op1Val - 1));
- default:
- return nullptr;
- }
- }
-
- // The usual vector types are ConstantDataVector. Exotic vector types are
- // ConstantVector. Zeros are special. They all derive from Constant.
- if (isa<ConstantDataVector>(Op1) || isa<ConstantVector>(Op1) ||
- isa<ConstantAggregateZero>(Op1)) {
- Constant *Op1C = cast<Constant>(Op1);
- Type *Op1Type = Op1->getType();
- unsigned NumElts = Op1Type->getVectorNumElements();
-
- // Set the new comparison predicate and splat a vector of 1 or -1 to
- // increment or decrement the vector constants. But first, check that no
- // elements of the constant vector would overflow/underflow when we
- // increment/decrement the constants.
- //
+ // Check if the constant operand can be safely incremented/decremented without
+ // overflowing/underflowing. For scalars, SimplifyICmpInst has already handled
+ // the edge cases for us, so we just assert on them. For vectors, we must
+ // handle the edge cases.
+ Type *Op1Type = Op1->getType();
+ bool IsSigned = I.isSigned();
+ bool IsLE = (Pred == ICmpInst::ICMP_SLE || Pred == ICmpInst::ICMP_ULE);
+ if (auto *CI = dyn_cast<ConstantInt>(Op1C)) {
+ // A <= MAX -> TRUE ; A >= MIN -> TRUE
+ assert(IsLE ? !CI->isMaxValue(IsSigned) : !CI->isMinValue(IsSigned));
+ } else if (Op1Type->isVectorTy()) {
// TODO? If the edge cases for vectors were guaranteed to be handled as they
- // are for scalar, we could remove the min/max checks here. However, to do
- // that, we would have to use insertelement/shufflevector to replace edge
- // values.
-
- CmpInst::Predicate NewPred;
- Constant *OneOrNegOne = nullptr;
- switch (I.getPredicate()) {
- case ICmpInst::ICMP_ULE:
- for (unsigned i = 0; i != NumElts; ++i)
- if (cast<ConstantInt>(Op1C->getAggregateElement(i))->isMaxValue(false))
- return nullptr;
- NewPred = ICmpInst::ICMP_ULT;
- OneOrNegOne = ConstantInt::get(Op1Type, 1);
- break;
- case ICmpInst::ICMP_SLE:
- for (unsigned i = 0; i != NumElts; ++i)
- if (cast<ConstantInt>(Op1C->getAggregateElement(i))->isMaxValue(true))
- return nullptr;
- NewPred = ICmpInst::ICMP_SLT;
- OneOrNegOne = ConstantInt::get(Op1Type, 1);
- break;
- case ICmpInst::ICMP_UGE:
- for (unsigned i = 0; i != NumElts; ++i)
- if (cast<ConstantInt>(Op1C->getAggregateElement(i))->isMinValue(false))
- return nullptr;
- NewPred = ICmpInst::ICMP_UGT;
- OneOrNegOne = ConstantInt::get(Op1Type, -1);
- break;
- case ICmpInst::ICMP_SGE:
- for (unsigned i = 0; i != NumElts; ++i)
- if (cast<ConstantInt>(Op1C->getAggregateElement(i))->isMinValue(true))
- return nullptr;
- NewPred = ICmpInst::ICMP_SGT;
- OneOrNegOne = ConstantInt::get(Op1Type, -1);
- break;
- default:
- return nullptr;
+ // are for scalar, we could remove the min/max checks. However, to do that,
+ // we would have to use insertelement/shufflevector to replace edge values.
+ unsigned NumElts = Op1Type->getVectorNumElements();
+ for (unsigned i = 0; i != NumElts; ++i) {
+ Constant *Elt = Op1C->getAggregateElement(i);
+ if (isa<UndefValue>(Elt))
+ continue;
+ // Bail out if we can't determine if this constant is min/max or if we
+ // know that this constant is min/max.
+ auto *CI = dyn_cast<ConstantInt>(Elt);
+ if (!CI || (IsLE ? CI->isMaxValue(IsSigned) : CI->isMinValue(IsSigned)))
+ return nullptr;
}
-
- return new ICmpInst(NewPred, Op0, ConstantExpr::getAdd(Op1C, OneOrNegOne));
+ } else {
+ // ConstantExpr?
+ return nullptr;
}
- return nullptr;
+ // Increment or decrement the constant and set the new comparison predicate:
+ // ULE -> ULT ; UGE -> UGT ; SLE -> SLT ; SGE -> SGT
+ Constant *OneOrNegOne = ConstantInt::get(Op1Type, IsLE ? 1 : -1);
+ CmpInst::Predicate NewPred = IsLE ? ICmpInst::ICMP_ULT: ICmpInst::ICMP_UGT;
+ NewPred = IsSigned ? ICmpInst::getSignedPredicate(NewPred) : NewPred;
+ return new ICmpInst(NewPred, Op0, ConstantExpr::getAdd(Op1C, OneOrNegOne));
}
Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
@@ -3271,7 +3235,7 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
}
}
- if (ICmpInst *NewICmp = canonicalizeCmpWithConstant(I, *Builder))
+ if (ICmpInst *NewICmp = canonicalizeCmpWithConstant(I))
return NewICmp;
unsigned BitWidth = 0;
OpenPOWER on IntegriCloud