forked from OSchip/llvm-project
[InstCombine] clean up adjustMinMax(); NFCI
1. Change param names for readability 2. Change pointer param to ref 3. Early exit to reduce indent 4. Change switch to if/else llvm-svn: 285718
This commit is contained in:
parent
cf8a59e449
commit
644d7c3b8a
|
@ -416,107 +416,102 @@ static Value *foldSelectCttzCtlz(ICmpInst *ICI, Value *TrueVal, Value *FalseVal,
|
|||
/// Return true if we find and adjust an icmp+select pattern where the compare
|
||||
/// is with a constant that can be incremented or decremented to match the
|
||||
/// minimum or maximum idiom.
|
||||
static bool adjustMinMax(SelectInst &SI, ICmpInst *ICI) {
|
||||
bool Changed = false;
|
||||
ICmpInst::Predicate Pred = ICI->getPredicate();
|
||||
Value *CmpLHS = ICI->getOperand(0);
|
||||
Value *CmpRHS = ICI->getOperand(1);
|
||||
Value *TrueVal = SI.getTrueValue();
|
||||
Value *FalseVal = SI.getFalseValue();
|
||||
static bool adjustMinMax(SelectInst &Sel, ICmpInst &Cmp) {
|
||||
ICmpInst::Predicate Pred = Cmp.getPredicate();
|
||||
Value *CmpLHS = Cmp.getOperand(0);
|
||||
Value *CmpRHS = Cmp.getOperand(1);
|
||||
Value *TrueVal = Sel.getTrueValue();
|
||||
Value *FalseVal = Sel.getFalseValue();
|
||||
|
||||
// We may move or edit ICI here, so make sure the select is the only user.
|
||||
if (ICI->hasOneUse())
|
||||
if (ConstantInt *CI = dyn_cast<ConstantInt>(CmpRHS)) {
|
||||
switch (Pred) {
|
||||
default: break;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_SLT:
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_SGT: {
|
||||
// These transformations only work for selects over integers.
|
||||
IntegerType *SelectTy = dyn_cast<IntegerType>(SI.getType());
|
||||
if (!SelectTy)
|
||||
break;
|
||||
// We may move or edit the compare, so make sure the select is the only user.
|
||||
if (!Cmp.hasOneUse())
|
||||
return false;
|
||||
|
||||
Constant *AdjustedRHS;
|
||||
if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_SGT)
|
||||
AdjustedRHS = ConstantInt::get(CI->getContext(), CI->getValue() + 1);
|
||||
else // (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_SLT)
|
||||
AdjustedRHS = ConstantInt::get(CI->getContext(), CI->getValue() - 1);
|
||||
// FIXME: Use m_APInt to allow vector folds.
|
||||
auto *CI = dyn_cast<ConstantInt>(CmpRHS);
|
||||
if (!CI)
|
||||
return false;
|
||||
|
||||
// X > C ? X : C+1 --> X < C+1 ? C+1 : X
|
||||
// X < C ? X : C-1 --> X > C-1 ? C-1 : X
|
||||
if ((CmpLHS == TrueVal && AdjustedRHS == FalseVal) ||
|
||||
(CmpLHS == FalseVal && AdjustedRHS == TrueVal))
|
||||
; // Nothing to do here. Values match without any sign/zero extension.
|
||||
// These transformations only work for selects over integers.
|
||||
IntegerType *SelectTy = dyn_cast<IntegerType>(Sel.getType());
|
||||
if (!SelectTy)
|
||||
return false;
|
||||
|
||||
// Types do not match. Instead of calculating this with mixed types
|
||||
// promote all to the larger type. This enables scalar evolution to
|
||||
// analyze this expression.
|
||||
else if (CmpRHS->getType()->getScalarSizeInBits() <
|
||||
SelectTy->getBitWidth()) {
|
||||
Constant *SextRHS = ConstantExpr::getSExt(AdjustedRHS, SelectTy);
|
||||
Constant *AdjustedRHS;
|
||||
if (Pred == ICmpInst::ICMP_UGT || Pred == ICmpInst::ICMP_SGT)
|
||||
AdjustedRHS = ConstantInt::get(CI->getContext(), CI->getValue() + 1);
|
||||
else if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_SLT)
|
||||
AdjustedRHS = ConstantInt::get(CI->getContext(), CI->getValue() - 1);
|
||||
else
|
||||
return false;
|
||||
|
||||
// X = sext x; x >s c ? X : C+1 --> X = sext x; X <s C+1 ? C+1 : X
|
||||
// X = sext x; x <s c ? X : C-1 --> X = sext x; X >s C-1 ? C-1 : X
|
||||
// X = sext x; x >u c ? X : C+1 --> X = sext x; X <u C+1 ? C+1 : X
|
||||
// X = sext x; x <u c ? X : C-1 --> X = sext x; X >u C-1 ? C-1 : X
|
||||
if (match(TrueVal, m_SExt(m_Specific(CmpLHS))) &&
|
||||
SextRHS == FalseVal) {
|
||||
CmpLHS = TrueVal;
|
||||
AdjustedRHS = SextRHS;
|
||||
} else if (match(FalseVal, m_SExt(m_Specific(CmpLHS))) &&
|
||||
SextRHS == TrueVal) {
|
||||
CmpLHS = FalseVal;
|
||||
AdjustedRHS = SextRHS;
|
||||
} else if (ICI->isUnsigned()) {
|
||||
Constant *ZextRHS = ConstantExpr::getZExt(AdjustedRHS, SelectTy);
|
||||
// X = zext x; x >u c ? X : C+1 --> X = zext x; X <u C+1 ? C+1 : X
|
||||
// X = zext x; x <u c ? X : C-1 --> X = zext x; X >u C-1 ? C-1 : X
|
||||
// zext + signed compare cannot be changed:
|
||||
// 0xff <s 0x00, but 0x00ff >s 0x0000
|
||||
if (match(TrueVal, m_ZExt(m_Specific(CmpLHS))) &&
|
||||
ZextRHS == FalseVal) {
|
||||
CmpLHS = TrueVal;
|
||||
AdjustedRHS = ZextRHS;
|
||||
} else if (match(FalseVal, m_ZExt(m_Specific(CmpLHS))) &&
|
||||
ZextRHS == TrueVal) {
|
||||
CmpLHS = FalseVal;
|
||||
AdjustedRHS = ZextRHS;
|
||||
} else
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
} else
|
||||
break;
|
||||
// X > C ? X : C+1 --> X < C+1 ? C+1 : X
|
||||
// X < C ? X : C-1 --> X > C-1 ? C-1 : X
|
||||
if ((CmpLHS == TrueVal && AdjustedRHS == FalseVal) ||
|
||||
(CmpLHS == FalseVal && AdjustedRHS == TrueVal)) {
|
||||
; // Nothing to do here. Values match without any sign/zero extension.
|
||||
}
|
||||
// Types do not match. Instead of calculating this with mixed types, promote
|
||||
// all to the larger type. This enables scalar evolution to analyze this
|
||||
// expression.
|
||||
else if (CmpRHS->getType()->getScalarSizeInBits() < SelectTy->getBitWidth()) {
|
||||
Constant *SextRHS = ConstantExpr::getSExt(AdjustedRHS, SelectTy);
|
||||
|
||||
Pred = ICmpInst::getSwappedPredicate(Pred);
|
||||
CmpRHS = AdjustedRHS;
|
||||
std::swap(FalseVal, TrueVal);
|
||||
ICI->setPredicate(Pred);
|
||||
ICI->setOperand(0, CmpLHS);
|
||||
ICI->setOperand(1, CmpRHS);
|
||||
SI.setOperand(1, TrueVal);
|
||||
SI.setOperand(2, FalseVal);
|
||||
SI.swapProfMetadata();
|
||||
|
||||
// Move ICI instruction right before the select instruction. Otherwise
|
||||
// the sext/zext value may be defined after the ICI instruction uses it.
|
||||
ICI->moveBefore(&SI);
|
||||
|
||||
Changed = true;
|
||||
break;
|
||||
}
|
||||
// X = sext x; x >s c ? X : C+1 --> X = sext x; X <s C+1 ? C+1 : X
|
||||
// X = sext x; x <s c ? X : C-1 --> X = sext x; X >s C-1 ? C-1 : X
|
||||
// X = sext x; x >u c ? X : C+1 --> X = sext x; X <u C+1 ? C+1 : X
|
||||
// X = sext x; x <u c ? X : C-1 --> X = sext x; X >u C-1 ? C-1 : X
|
||||
if (match(TrueVal, m_SExt(m_Specific(CmpLHS))) && SextRHS == FalseVal) {
|
||||
CmpLHS = TrueVal;
|
||||
AdjustedRHS = SextRHS;
|
||||
} else if (match(FalseVal, m_SExt(m_Specific(CmpLHS))) &&
|
||||
SextRHS == TrueVal) {
|
||||
CmpLHS = FalseVal;
|
||||
AdjustedRHS = SextRHS;
|
||||
} else if (Cmp.isUnsigned()) {
|
||||
Constant *ZextRHS = ConstantExpr::getZExt(AdjustedRHS, SelectTy);
|
||||
// X = zext x; x >u c ? X : C+1 --> X = zext x; X <u C+1 ? C+1 : X
|
||||
// X = zext x; x <u c ? X : C-1 --> X = zext x; X >u C-1 ? C-1 : X
|
||||
// zext + signed compare cannot be changed:
|
||||
// 0xff <s 0x00, but 0x00ff >s 0x0000
|
||||
if (match(TrueVal, m_ZExt(m_Specific(CmpLHS))) && ZextRHS == FalseVal) {
|
||||
CmpLHS = TrueVal;
|
||||
AdjustedRHS = ZextRHS;
|
||||
} else if (match(FalseVal, m_ZExt(m_Specific(CmpLHS))) &&
|
||||
ZextRHS == TrueVal) {
|
||||
CmpLHS = FalseVal;
|
||||
AdjustedRHS = ZextRHS;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Changed;
|
||||
Pred = ICmpInst::getSwappedPredicate(Pred);
|
||||
CmpRHS = AdjustedRHS;
|
||||
std::swap(FalseVal, TrueVal);
|
||||
Cmp.setPredicate(Pred);
|
||||
Cmp.setOperand(0, CmpLHS);
|
||||
Cmp.setOperand(1, CmpRHS);
|
||||
Sel.setOperand(1, TrueVal);
|
||||
Sel.setOperand(2, FalseVal);
|
||||
Sel.swapProfMetadata();
|
||||
|
||||
// Move the compare instruction right before the select instruction. Otherwise
|
||||
// the sext/zext value may be defined after the compare instruction uses it.
|
||||
Cmp.moveBefore(&Sel);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Visit a SelectInst that has an ICmpInst as its first operand.
|
||||
Instruction *InstCombiner::foldSelectInstWithICmp(SelectInst &SI,
|
||||
ICmpInst *ICI) {
|
||||
bool Changed = adjustMinMax(SI, ICI);
|
||||
bool Changed = adjustMinMax(SI, *ICI);
|
||||
|
||||
ICmpInst::Predicate Pred = ICI->getPredicate();
|
||||
Value *CmpLHS = ICI->getOperand(0);
|
||||
|
|
Loading…
Reference in New Issue