[InstCombine] Remove integer SPF of SPF folds (NFCI)

Now that we canonicalize to intrinsics, these folds should no
longer be needed. Only one fold that also applies to floating-point
min/max is retained.
This commit is contained in:
Nikita Popov 2022-02-24 14:33:57 +01:00
parent 022b05941e
commit fc8946fae7
1 changed files with 0 additions and 115 deletions

View File

@ -49,13 +49,6 @@ using namespace llvm;
using namespace PatternMatch;
static Value *createMinMax(InstCombiner::BuilderTy &Builder,
SelectPatternFlavor SPF, Value *A, Value *B) {
CmpInst::Predicate Pred = getMinMaxPred(SPF);
assert(CmpInst::isIntPredicate(Pred) && "Expected integer predicate");
return Builder.CreateSelect(Builder.CreateICmp(Pred, A, B), A, B);
}
/// Replace a select operand based on an equality comparison with the identity
/// constant of a binop.
static Instruction *foldSelectBinOpIdentity(SelectInst &Sel,
@ -1704,114 +1697,6 @@ Instruction *InstCombinerImpl::foldSPFofSPF(Instruction *Inner,
// TODO: This could be done in instsimplify.
if (SPF1 == SPF2 && SelectPatternResult::isMinOrMax(SPF1))
return replaceInstUsesWith(Outer, Inner);
// MAX(MIN(a, b), a) -> a
// MIN(MAX(a, b), a) -> a
// TODO: This could be done in instsimplify.
if ((SPF1 == SPF_SMIN && SPF2 == SPF_SMAX) ||
(SPF1 == SPF_SMAX && SPF2 == SPF_SMIN) ||
(SPF1 == SPF_UMIN && SPF2 == SPF_UMAX) ||
(SPF1 == SPF_UMAX && SPF2 == SPF_UMIN))
return replaceInstUsesWith(Outer, C);
}
if (SPF1 == SPF2) {
const APInt *CB, *CC;
if (match(B, m_APInt(CB)) && match(C, m_APInt(CC))) {
// MIN(MIN(A, 23), 97) -> MIN(A, 23)
// MAX(MAX(A, 97), 23) -> MAX(A, 97)
// TODO: This could be done in instsimplify.
if ((SPF1 == SPF_UMIN && CB->ule(*CC)) ||
(SPF1 == SPF_SMIN && CB->sle(*CC)) ||
(SPF1 == SPF_UMAX && CB->uge(*CC)) ||
(SPF1 == SPF_SMAX && CB->sge(*CC)))
return replaceInstUsesWith(Outer, Inner);
// MIN(MIN(A, 97), 23) -> MIN(A, 23)
// MAX(MAX(A, 23), 97) -> MAX(A, 97)
if ((SPF1 == SPF_UMIN && CB->ugt(*CC)) ||
(SPF1 == SPF_SMIN && CB->sgt(*CC)) ||
(SPF1 == SPF_UMAX && CB->ult(*CC)) ||
(SPF1 == SPF_SMAX && CB->slt(*CC))) {
Outer.replaceUsesOfWith(Inner, A);
return &Outer;
}
}
}
// max(max(A, B), min(A, B)) --> max(A, B)
// min(min(A, B), max(A, B)) --> min(A, B)
// TODO: This could be done in instsimplify.
if (SPF1 == SPF2 &&
((SPF1 == SPF_UMIN && match(C, m_c_UMax(m_Specific(A), m_Specific(B)))) ||
(SPF1 == SPF_SMIN && match(C, m_c_SMax(m_Specific(A), m_Specific(B)))) ||
(SPF1 == SPF_UMAX && match(C, m_c_UMin(m_Specific(A), m_Specific(B)))) ||
(SPF1 == SPF_SMAX && match(C, m_c_SMin(m_Specific(A), m_Specific(B))))))
return replaceInstUsesWith(Outer, Inner);
// ABS(ABS(X)) -> ABS(X)
// NABS(NABS(X)) -> NABS(X)
// TODO: This could be done in instsimplify.
if (SPF1 == SPF2 && (SPF1 == SPF_ABS || SPF1 == SPF_NABS)) {
return replaceInstUsesWith(Outer, Inner);
}
// ABS(NABS(X)) -> ABS(X)
// NABS(ABS(X)) -> NABS(X)
if ((SPF1 == SPF_ABS && SPF2 == SPF_NABS) ||
(SPF1 == SPF_NABS && SPF2 == SPF_ABS)) {
SelectInst *SI = cast<SelectInst>(Inner);
Value *NewSI =
Builder.CreateSelect(SI->getCondition(), SI->getFalseValue(),
SI->getTrueValue(), SI->getName(), SI);
return replaceInstUsesWith(Outer, NewSI);
}
auto IsFreeOrProfitableToInvert =
[&](Value *V, Value *&NotV, bool &ElidesXor) {
if (match(V, m_Not(m_Value(NotV)))) {
// If V has at most 2 uses then we can get rid of the xor operation
// entirely.
ElidesXor |= !V->hasNUsesOrMore(3);
return true;
}
if (isFreeToInvert(V, !V->hasNUsesOrMore(3))) {
NotV = nullptr;
return true;
}
return false;
};
Value *NotA, *NotB, *NotC;
bool ElidesXor = false;
// MIN(MIN(~A, ~B), ~C) == ~MAX(MAX(A, B), C)
// MIN(MAX(~A, ~B), ~C) == ~MAX(MIN(A, B), C)
// MAX(MIN(~A, ~B), ~C) == ~MIN(MAX(A, B), C)
// MAX(MAX(~A, ~B), ~C) == ~MIN(MIN(A, B), C)
//
// This transform is performance neutral if we can elide at least one xor from
// the set of three operands, since we'll be tacking on an xor at the very
// end.
if (SelectPatternResult::isMinOrMax(SPF1) &&
SelectPatternResult::isMinOrMax(SPF2) &&
IsFreeOrProfitableToInvert(A, NotA, ElidesXor) &&
IsFreeOrProfitableToInvert(B, NotB, ElidesXor) &&
IsFreeOrProfitableToInvert(C, NotC, ElidesXor) && ElidesXor) {
if (!NotA)
NotA = Builder.CreateNot(A);
if (!NotB)
NotB = Builder.CreateNot(B);
if (!NotC)
NotC = Builder.CreateNot(C);
Value *NewInner = createMinMax(Builder, getInverseMinMaxFlavor(SPF1), NotA,
NotB);
Value *NewOuter = Builder.CreateNot(
createMinMax(Builder, getInverseMinMaxFlavor(SPF2), NewInner, NotC));
return replaceInstUsesWith(Outer, NewOuter);
}
return nullptr;