summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2019-01-29 20:02:45 +0000
committerSanjay Patel <spatel@rotateright.com>2019-01-29 20:02:45 +0000
commit18db56209c8bf07322aa968571a79acb13c437a6 (patch)
tree1776bde7bc7ba788d8dcb7135f0fece7d715f96c /llvm/lib/Transforms
parent3f8b9166989709d1d893524f5590f8064e824554 (diff)
downloadbcm5719-llvm-18db56209c8bf07322aa968571a79acb13c437a6.tar.gz
bcm5719-llvm-18db56209c8bf07322aa968571a79acb13c437a6.zip
[InstCombine] canonicalize cmp/select form of uadd saturate with constant
I'm circling back around to a loose end from D51929. The backend (either CGP or DAG) doesn't recognize this pattern, so we end up with different asm for these IR variants. Regardless of any future changes to canonicalize to saturation/overflow intrinsics, we want to get raw IR variations into the minimal number of raw IR forms. If/when we can canonicalize to intrinsics, that will make that step easier. Pre: C2 == ~C1 %a = add i32 %x, C1 %c = icmp ugt i32 %x, C2 %r = select i1 %c, i32 -1, i32 %a => %a = add i32 %x, C1 %c2 = icmp ult i32 %x, C2 %r = select i1 %c2, i32 %a, i32 -1 https://rise4fun.com/Alive/pkH Differential Revision: https://reviews.llvm.org/D57352 llvm-svn: 352536
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp20
1 files changed, 20 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index e00f68a5445..5922e6f7506 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -675,6 +675,23 @@ static Value *canonicalizeSaturatedSubtract(const ICmpInst *ICI,
return IsNegative ? Builder.CreateSub(B, Max) : Builder.CreateSub(Max, B);
}
+static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal,
+ InstCombiner::BuilderTy &Builder) {
+ // Match an unsigned saturated add with constant.
+ Value *X = Cmp->getOperand(0);
+ const APInt *CmpC, *AddC;
+ if (!Cmp->hasOneUse() || Cmp->getPredicate() != ICmpInst::ICMP_ULT ||
+ !match(Cmp->getOperand(1), m_APInt(CmpC)) || !match(FVal, m_AllOnes()) ||
+ !match(TVal, m_Add(m_Specific(X), m_APInt(AddC))) || ~(*AddC) != *CmpC)
+ return nullptr;
+
+ // Commute compare and select operands:
+ // select (icmp ult X, C), (add X, ~C), -1 -->
+ // select (icmp ugt X, C), -1, (add X, ~C)
+ Value *NewCmp = Builder.CreateICmp(ICmpInst::ICMP_UGT, X, Cmp->getOperand(1));
+ return Builder.CreateSelect(NewCmp, FVal, TVal);
+}
+
/// Attempt to fold a cttz/ctlz followed by a icmp plus select into a single
/// call to cttz/ctlz with flag 'is_zero_undef' cleared.
///
@@ -1048,6 +1065,9 @@ Instruction *InstCombiner::foldSelectInstWithICmp(SelectInst &SI,
if (Value *V = canonicalizeSaturatedSubtract(ICI, TrueVal, FalseVal, Builder))
return replaceInstUsesWith(SI, V);
+ if (Value *V = canonicalizeSaturatedAdd(ICI, TrueVal, FalseVal, Builder))
+ return replaceInstUsesWith(SI, V);
+
return Changed ? &SI : nullptr;
}
OpenPOWER on IntegriCloud