summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-05-20 14:23:23 +0000
committerSanjay Patel <spatel@rotateright.com>2018-05-20 14:23:23 +0000
commita003c728a52a77cf585453313b601edaf5a19225 (patch)
tree57287e5cd90f1ea3e89c7d969576c988d52df7dd /llvm/lib/Transforms
parent4a227e582b2f13880ea049b29988a37a0f7c0742 (diff)
downloadbcm5719-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.cpp51
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))
OpenPOWER on IntegriCloud