forked from OSchip/llvm-project
[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:
parent
022b05941e
commit
fc8946fae7
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue