mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-13 04:30:23 +00:00
Rip min/max pattern matching out of InstCombine and into
ValueTracking. This matching functionality is useful in more than just InstCombine, so make it available in ValueTracking. NFC. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236998 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
0a62359646
commit
2605531fe8
@ -262,6 +262,21 @@ namespace llvm {
|
||||
AssumptionCache *AC,
|
||||
const Instruction *CxtI,
|
||||
const DominatorTree *DT);
|
||||
|
||||
/// \brief Specific patterns of select instructions we can match.
|
||||
enum SelectPatternFlavor {
|
||||
SPF_UNKNOWN = 0,
|
||||
SPF_SMIN, // Signed minimum
|
||||
SPF_UMIN, // Unsigned minimum
|
||||
SPF_SMAX, // Signed maximum
|
||||
SPF_UMAX, // Unsigned maximum
|
||||
SPF_ABS, // Absolute value
|
||||
SPF_NABS // Negated absolute value
|
||||
};
|
||||
/// Pattern match integer [SU]MIN, [SU]MAX and ABS idioms, returning the kind
|
||||
/// and providing the out parameter results if we successfully match.
|
||||
SelectPatternFlavor matchSelectPattern(Value *V, Value *&LHS, Value *&RHS);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
@ -3204,3 +3204,84 @@ OverflowResult llvm::computeOverflowForUnsignedAdd(Value *LHS, Value *RHS,
|
||||
|
||||
return OverflowResult::MayOverflow;
|
||||
}
|
||||
|
||||
SelectPatternFlavor llvm::matchSelectPattern(Value *V,
|
||||
Value *&LHS, Value *&RHS) {
|
||||
SelectInst *SI = dyn_cast<SelectInst>(V);
|
||||
if (!SI) return SPF_UNKNOWN;
|
||||
|
||||
ICmpInst *ICI = dyn_cast<ICmpInst>(SI->getCondition());
|
||||
if (!ICI) return SPF_UNKNOWN;
|
||||
|
||||
ICmpInst::Predicate Pred = ICI->getPredicate();
|
||||
Value *CmpLHS = ICI->getOperand(0);
|
||||
Value *CmpRHS = ICI->getOperand(1);
|
||||
Value *TrueVal = SI->getTrueValue();
|
||||
Value *FalseVal = SI->getFalseValue();
|
||||
|
||||
LHS = CmpLHS;
|
||||
RHS = CmpRHS;
|
||||
|
||||
// (icmp X, Y) ? X : Y
|
||||
if (TrueVal == CmpLHS && FalseVal == CmpRHS) {
|
||||
switch (Pred) {
|
||||
default: return SPF_UNKNOWN; // Equality.
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_UGE: return SPF_UMAX;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
case ICmpInst::ICMP_SGE: return SPF_SMAX;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_ULE: return SPF_UMIN;
|
||||
case ICmpInst::ICMP_SLT:
|
||||
case ICmpInst::ICMP_SLE: return SPF_SMIN;
|
||||
}
|
||||
}
|
||||
|
||||
// (icmp X, Y) ? Y : X
|
||||
if (TrueVal == CmpRHS && FalseVal == CmpLHS) {
|
||||
switch (Pred) {
|
||||
default: return SPF_UNKNOWN; // Equality.
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_UGE: return SPF_UMIN;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
case ICmpInst::ICMP_SGE: return SPF_SMIN;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_ULE: return SPF_UMAX;
|
||||
case ICmpInst::ICMP_SLT:
|
||||
case ICmpInst::ICMP_SLE: return SPF_SMAX;
|
||||
}
|
||||
}
|
||||
|
||||
if (ConstantInt *C1 = dyn_cast<ConstantInt>(CmpRHS)) {
|
||||
if ((CmpLHS == TrueVal && match(FalseVal, m_Neg(m_Specific(CmpLHS)))) ||
|
||||
(CmpLHS == FalseVal && match(TrueVal, m_Neg(m_Specific(CmpLHS))))) {
|
||||
|
||||
// ABS(X) ==> (X >s 0) ? X : -X and (X >s -1) ? X : -X
|
||||
// NABS(X) ==> (X >s 0) ? -X : X and (X >s -1) ? -X : X
|
||||
if (Pred == ICmpInst::ICMP_SGT && (C1->isZero() || C1->isMinusOne())) {
|
||||
return (CmpLHS == TrueVal) ? SPF_ABS : SPF_NABS;
|
||||
}
|
||||
|
||||
// ABS(X) ==> (X <s 0) ? -X : X and (X <s 1) ? -X : X
|
||||
// NABS(X) ==> (X <s 0) ? X : -X and (X <s 1) ? X : -X
|
||||
if (Pred == ICmpInst::ICMP_SLT && (C1->isZero() || C1->isOne())) {
|
||||
return (CmpLHS == FalseVal) ? SPF_ABS : SPF_NABS;
|
||||
}
|
||||
}
|
||||
|
||||
// Y >s C ? ~Y : ~C == ~Y <s ~C ? ~Y : ~C = SMIN(~Y, ~C)
|
||||
if (const auto *C2 = dyn_cast<ConstantInt>(FalseVal)) {
|
||||
if (C1->getType() == C2->getType() && ~C1->getValue() == C2->getValue() &&
|
||||
(match(TrueVal, m_Not(m_Specific(CmpLHS))) ||
|
||||
match(CmpLHS, m_Not(m_Specific(TrueVal))))) {
|
||||
LHS = TrueVal;
|
||||
RHS = FalseVal;
|
||||
return SPF_SMIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: (X > 4) ? X : 5 --> (X >= 5) ? X : 5 --> MAX(X, 5)
|
||||
|
||||
return SPF_UNKNOWN;
|
||||
}
|
||||
|
@ -39,17 +39,6 @@ class DbgDeclareInst;
|
||||
class MemIntrinsic;
|
||||
class MemSetInst;
|
||||
|
||||
/// \brief Specific patterns of select instructions we can match.
|
||||
enum SelectPatternFlavor {
|
||||
SPF_UNKNOWN = 0,
|
||||
SPF_SMIN,
|
||||
SPF_UMIN,
|
||||
SPF_SMAX,
|
||||
SPF_UMAX,
|
||||
SPF_ABS,
|
||||
SPF_NABS
|
||||
};
|
||||
|
||||
/// \brief Assign a complexity or rank value to LLVM Values.
|
||||
///
|
||||
/// This routine maps IR values to various complexity ranks:
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "InstCombineInternal.h"
|
||||
#include "llvm/Analysis/ConstantFolding.h"
|
||||
#include "llvm/Analysis/InstructionSimplify.h"
|
||||
#include "llvm/Analysis/ValueTracking.h"
|
||||
#include "llvm/IR/PatternMatch.h"
|
||||
using namespace llvm;
|
||||
using namespace PatternMatch;
|
||||
@ -60,91 +61,6 @@ static Value *generateMinMaxSelectPattern(InstCombiner::BuilderTy *Builder,
|
||||
return Builder->CreateSelect(Builder->CreateICmp(Pred, A, B), A, B);
|
||||
}
|
||||
|
||||
/// MatchSelectPattern - Pattern match integer [SU]MIN, [SU]MAX, and ABS idioms,
|
||||
/// returning the kind and providing the out parameter results if we
|
||||
/// successfully match.
|
||||
static SelectPatternFlavor
|
||||
MatchSelectPattern(Value *V, Value *&LHS, Value *&RHS) {
|
||||
SelectInst *SI = dyn_cast<SelectInst>(V);
|
||||
if (!SI) return SPF_UNKNOWN;
|
||||
|
||||
ICmpInst *ICI = dyn_cast<ICmpInst>(SI->getCondition());
|
||||
if (!ICI) return SPF_UNKNOWN;
|
||||
|
||||
ICmpInst::Predicate Pred = ICI->getPredicate();
|
||||
Value *CmpLHS = ICI->getOperand(0);
|
||||
Value *CmpRHS = ICI->getOperand(1);
|
||||
Value *TrueVal = SI->getTrueValue();
|
||||
Value *FalseVal = SI->getFalseValue();
|
||||
|
||||
LHS = CmpLHS;
|
||||
RHS = CmpRHS;
|
||||
|
||||
// (icmp X, Y) ? X : Y
|
||||
if (TrueVal == CmpLHS && FalseVal == CmpRHS) {
|
||||
switch (Pred) {
|
||||
default: return SPF_UNKNOWN; // Equality.
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_UGE: return SPF_UMAX;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
case ICmpInst::ICMP_SGE: return SPF_SMAX;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_ULE: return SPF_UMIN;
|
||||
case ICmpInst::ICMP_SLT:
|
||||
case ICmpInst::ICMP_SLE: return SPF_SMIN;
|
||||
}
|
||||
}
|
||||
|
||||
// (icmp X, Y) ? Y : X
|
||||
if (TrueVal == CmpRHS && FalseVal == CmpLHS) {
|
||||
switch (Pred) {
|
||||
default: return SPF_UNKNOWN; // Equality.
|
||||
case ICmpInst::ICMP_UGT:
|
||||
case ICmpInst::ICMP_UGE: return SPF_UMIN;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
case ICmpInst::ICMP_SGE: return SPF_SMIN;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
case ICmpInst::ICMP_ULE: return SPF_UMAX;
|
||||
case ICmpInst::ICMP_SLT:
|
||||
case ICmpInst::ICMP_SLE: return SPF_SMAX;
|
||||
}
|
||||
}
|
||||
|
||||
if (ConstantInt *C1 = dyn_cast<ConstantInt>(CmpRHS)) {
|
||||
if ((CmpLHS == TrueVal && match(FalseVal, m_Neg(m_Specific(CmpLHS)))) ||
|
||||
(CmpLHS == FalseVal && match(TrueVal, m_Neg(m_Specific(CmpLHS))))) {
|
||||
|
||||
// ABS(X) ==> (X >s 0) ? X : -X and (X >s -1) ? X : -X
|
||||
// NABS(X) ==> (X >s 0) ? -X : X and (X >s -1) ? -X : X
|
||||
if (Pred == ICmpInst::ICMP_SGT && (C1->isZero() || C1->isMinusOne())) {
|
||||
return (CmpLHS == TrueVal) ? SPF_ABS : SPF_NABS;
|
||||
}
|
||||
|
||||
// ABS(X) ==> (X <s 0) ? -X : X and (X <s 1) ? -X : X
|
||||
// NABS(X) ==> (X <s 0) ? X : -X and (X <s 1) ? X : -X
|
||||
if (Pred == ICmpInst::ICMP_SLT && (C1->isZero() || C1->isOne())) {
|
||||
return (CmpLHS == FalseVal) ? SPF_ABS : SPF_NABS;
|
||||
}
|
||||
}
|
||||
|
||||
// Y >s C ? ~Y : ~C == ~Y <s ~C ? ~Y : ~C = SMIN(~Y, ~C)
|
||||
if (const auto *C2 = dyn_cast<ConstantInt>(FalseVal)) {
|
||||
if (C1->getType() == C2->getType() && ~C1->getValue() == C2->getValue() &&
|
||||
(match(TrueVal, m_Not(m_Specific(CmpLHS))) ||
|
||||
match(CmpLHS, m_Not(m_Specific(TrueVal))))) {
|
||||
LHS = TrueVal;
|
||||
RHS = FalseVal;
|
||||
return SPF_SMIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: (X > 4) ? X : 5 --> (X >= 5) ? X : 5 --> MAX(X, 5)
|
||||
|
||||
return SPF_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
/// GetSelectFoldableOperands - We want to turn code that looks like this:
|
||||
/// %C = or %A, %B
|
||||
/// %D = select %cond, %C, %A
|
||||
@ -1243,18 +1159,18 @@ Instruction *InstCombiner::visitSelectInst(SelectInst &SI) {
|
||||
return FoldI;
|
||||
|
||||
Value *LHS, *RHS, *LHS2, *RHS2;
|
||||
SelectPatternFlavor SPF = MatchSelectPattern(&SI, LHS, RHS);
|
||||
SelectPatternFlavor SPF = matchSelectPattern(&SI, LHS, RHS);
|
||||
|
||||
// MAX(MAX(a, b), a) -> MAX(a, b)
|
||||
// MIN(MIN(a, b), a) -> MIN(a, b)
|
||||
// MAX(MIN(a, b), a) -> a
|
||||
// MIN(MAX(a, b), a) -> a
|
||||
if (SPF) {
|
||||
if (SelectPatternFlavor SPF2 = MatchSelectPattern(LHS, LHS2, RHS2))
|
||||
if (SelectPatternFlavor SPF2 = matchSelectPattern(LHS, LHS2, RHS2))
|
||||
if (Instruction *R = FoldSPFofSPF(cast<Instruction>(LHS),SPF2,LHS2,RHS2,
|
||||
SI, SPF, RHS))
|
||||
return R;
|
||||
if (SelectPatternFlavor SPF2 = MatchSelectPattern(RHS, LHS2, RHS2))
|
||||
if (SelectPatternFlavor SPF2 = matchSelectPattern(RHS, LHS2, RHS2))
|
||||
if (Instruction *R = FoldSPFofSPF(cast<Instruction>(RHS),SPF2,LHS2,RHS2,
|
||||
SI, SPF, LHS))
|
||||
return R;
|
||||
|
Loading…
Reference in New Issue
Block a user