forked from OSchip/llvm-project
[InstCombine] add helper function for ICmp with constant canonicalization; NFCI
As suggested in http://reviews.llvm.org/D17859 , we should enhance this to support vectors. llvm-svn: 268059
This commit is contained in:
parent
7225cd52e7
commit
d5b0e54b49
|
@ -3070,6 +3070,41 @@ bool InstCombiner::replacedSelectWithOperand(SelectInst *SI,
|
|||
return false;
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
Value *Op0 = I.getOperand(0);
|
||||
Value *Op1 = I.getOperand(1);
|
||||
|
||||
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:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Handle vectors.
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
||||
bool Changed = false;
|
||||
Value *Op0 = I.getOperand(0), *Op1 = I.getOperand(1);
|
||||
|
@ -3153,6 +3188,9 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
|||
}
|
||||
}
|
||||
|
||||
if (ICmpInst *NewICmp = canonicalizeCmpWithConstant(I, *Builder))
|
||||
return NewICmp;
|
||||
|
||||
unsigned BitWidth = 0;
|
||||
if (Ty->isIntOrIntVectorTy())
|
||||
BitWidth = Ty->getScalarSizeInBits();
|
||||
|
@ -3227,30 +3265,6 @@ Instruction *InstCombiner::visitICmpInst(ICmpInst &I) {
|
|||
return new ICmpInst(ICmpInst::ICMP_SLE, A, B);
|
||||
}
|
||||
|
||||
// If we have an icmp le or icmp ge instruction, turn it into the
|
||||
// appropriate icmp lt or icmp gt instruction. This allows us to rely on
|
||||
// them being folded in the code below. The SimplifyICmpInst code has
|
||||
// already handled the edge cases for us, so we just assert on them.
|
||||
switch (I.getPredicate()) {
|
||||
default: break;
|
||||
case ICmpInst::ICMP_ULE:
|
||||
assert(!CI->isMaxValue(false)); // A <=u MAX -> TRUE
|
||||
return new ICmpInst(ICmpInst::ICMP_ULT, Op0,
|
||||
Builder->getInt(CI->getValue()+1));
|
||||
case ICmpInst::ICMP_SLE:
|
||||
assert(!CI->isMaxValue(true)); // A <=s MAX -> TRUE
|
||||
return new ICmpInst(ICmpInst::ICMP_SLT, Op0,
|
||||
Builder->getInt(CI->getValue()+1));
|
||||
case ICmpInst::ICMP_UGE:
|
||||
assert(!CI->isMinValue(false)); // A >=u MIN -> TRUE
|
||||
return new ICmpInst(ICmpInst::ICMP_UGT, Op0,
|
||||
Builder->getInt(CI->getValue()-1));
|
||||
case ICmpInst::ICMP_SGE:
|
||||
assert(!CI->isMinValue(true)); // A >=s MIN -> TRUE
|
||||
return new ICmpInst(ICmpInst::ICMP_SGT, Op0,
|
||||
Builder->getInt(CI->getValue()-1));
|
||||
}
|
||||
|
||||
if (I.isEquality()) {
|
||||
ConstantInt *CI2;
|
||||
if (match(Op0, m_AShr(m_ConstantInt(CI2), m_Value(A))) ||
|
||||
|
|
Loading…
Reference in New Issue