diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-05-20 14:23:23 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-05-20 14:23:23 +0000 |
commit | a003c728a52a77cf585453313b601edaf5a19225 (patch) | |
tree | 57287e5cd90f1ea3e89c7d969576c988d52df7dd /llvm/lib/Transforms | |
parent | 4a227e582b2f13880ea049b29988a37a0f7c0742 (diff) | |
download | bcm5719-llvm-a003c728a52a77cf585453313b601edaf5a19225.tar.gz bcm5719-llvm-a003c728a52a77cf585453313b601edaf5a19225.zip |
[InstCombine] choose 1 form of abs and nabs as canonical
We already do this for min/max (see the blob above the diff),
so we should do the same for abs/nabs.
A sign-bit check (<s 0) is used as a predicate for other IR
transforms and it's likely the best for codegen.
This might solve the motivating cases for D47037 and D47041,
but I think those patches still make sense. We can't guarantee
this canonicalization if the icmp has more than one use.
Differential Revision: https://reviews.llvm.org/D47076
llvm-svn: 332819
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index b7735c43dd7..9fe3c59e5e0 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -794,6 +794,54 @@ canonicalizeMinMaxWithConstant(SelectInst &Sel, ICmpInst &Cmp, return &Sel; } +/// There are 4 select variants for each of ABS/NABS (different compare +/// constants, compare predicates, select operands). Canonicalize to 1 pattern. +/// This makes CSE more likely. +static Instruction *canonicalizeAbsNabs(SelectInst &Sel, ICmpInst &Cmp, + InstCombiner::BuilderTy &Builder) { + if (!Cmp.hasOneUse() || !isa<Constant>(Cmp.getOperand(1))) + return nullptr; + + // Choose a sign-bit check for the compare (likely simpler for codegen). + // ABS: (X <s 0) ? -X : X + // NABS: (X <s 0) ? X : -X + Value *LHS, *RHS; + SelectPatternFlavor SPF = matchSelectPattern(&Sel, LHS, RHS).Flavor; + if (SPF != SelectPatternFlavor::SPF_ABS && + SPF != SelectPatternFlavor::SPF_NABS) + return nullptr; + + // Is this already canonical? + if (match(Cmp.getOperand(1), m_ZeroInt()) && + Cmp.getPredicate() == ICmpInst::ICMP_SLT) + return nullptr; + + // Create the canonical compare. + Cmp.setPredicate(ICmpInst::ICMP_SLT); + Cmp.setOperand(1, ConstantInt::getNullValue(LHS->getType())); + + // If the select operands do not change, we're done. + Value *TVal = Sel.getTrueValue(); + Value *FVal = Sel.getFalseValue(); + if (SPF == SelectPatternFlavor::SPF_NABS) { + if (TVal == LHS && match(FVal, m_Neg(m_Specific(TVal)))) + return &Sel; + assert(FVal == LHS && match(TVal, m_Neg(m_Specific(FVal))) && + "Unexpected results from matchSelectPattern"); + } else { + if (FVal == LHS && match(TVal, m_Neg(m_Specific(FVal)))) + return &Sel; + assert(TVal == LHS && match(FVal, m_Neg(m_Specific(TVal))) && + "Unexpected results from matchSelectPattern"); + } + + // We are swapping the select operands, so swap the metadata too. + Sel.setTrueValue(FVal); + Sel.setFalseValue(TVal); + Sel.swapProfMetadata(); + return &Sel; +} + /// Visit a SelectInst that has an ICmpInst as its first operand. Instruction *InstCombiner::foldSelectInstWithICmp(SelectInst &SI, ICmpInst *ICI) { @@ -803,6 +851,9 @@ Instruction *InstCombiner::foldSelectInstWithICmp(SelectInst &SI, if (Instruction *NewSel = canonicalizeMinMaxWithConstant(SI, *ICI, Builder)) return NewSel; + if (Instruction *NewAbs = canonicalizeAbsNabs(SI, *ICI, Builder)) + return NewAbs; + bool Changed = adjustMinMax(SI, *ICI); if (Value *V = foldSelectICmpAnd(SI, ICI, Builder)) |