diff options
author | Sanjay Patel <spatel@rotateright.com> | 2019-02-24 15:31:27 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2019-02-24 15:31:27 +0000 |
commit | cb04ba032f573fe75fce0e813ba11b0d47f1159e (patch) | |
tree | 4719accf69c48c7cd3df700168b0d34f5329e80a /llvm/lib/CodeGen/CodeGenPrepare.cpp | |
parent | 9b49f36a036a53d2cc600527a8b403cd48f7e411 (diff) | |
download | llvm-cb04ba032f573fe75fce0e813ba11b0d47f1159e.zip llvm-cb04ba032f573fe75fce0e813ba11b0d47f1159e.tar.gz llvm-cb04ba032f573fe75fce0e813ba11b0d47f1159e.tar.bz2 |
[CGP] add special-cases to form unsigned add with overflow (PR40486)
There's likely a missed IR canonicalization for at least 1 of these
patterns. Otherwise, we wouldn't have needed the pattern-matching
enhancement in D57516.
Note that -- unlike usubo added with D57789 -- the TLI hook for
this transform defaults to 'on'. So if there's any perf fallout
from this, targets should look at how they're lowering the uaddo
node in SDAG and/or override that hook.
The x86 diffs suggest that there's some missing pattern-matching
for forming inc/dec.
This should fix the remaining known problems in:
https://bugs.llvm.org/show_bug.cgi?id=40486
https://bugs.llvm.org/show_bug.cgi?id=31754
llvm-svn: 354746
Diffstat (limited to 'llvm/lib/CodeGen/CodeGenPrepare.cpp')
-rw-r--r-- | llvm/lib/CodeGen/CodeGenPrepare.cpp | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/llvm/lib/CodeGen/CodeGenPrepare.cpp b/llvm/lib/CodeGen/CodeGenPrepare.cpp index a6a4ea2..e56bd03 100644 --- a/llvm/lib/CodeGen/CodeGenPrepare.cpp +++ b/llvm/lib/CodeGen/CodeGenPrepare.cpp @@ -1197,6 +1197,31 @@ static bool replaceMathCmpWithIntrinsic(BinaryOperator *BO, CmpInst *Cmp, return true; } +/// Match special-case patterns that check for unsigned add overflow. +static bool matchUAddWithOverflowConstantEdgeCases(CmpInst *Cmp, + BinaryOperator *&Add) { + // Add = add A, 1; Cmp = icmp eq A,-1 (overflow if A is max val) + // Add = add A,-1; Cmp = icmp ne A, 0 (overflow if A is non-zero) + Value *A = Cmp->getOperand(0), *B = Cmp->getOperand(1); + ICmpInst::Predicate Pred = Cmp->getPredicate(); + if (Pred == ICmpInst::ICMP_EQ && match(B, m_AllOnes())) + B = ConstantInt::get(B->getType(), 1); + else if (Pred == ICmpInst::ICMP_NE && match(B, m_ZeroInt())) + B = ConstantInt::get(B->getType(), -1); + else + return false; + + // Check the users of the variable operand of the compare looking for an add + // with the adjusted constant. + for (User *U : A->users()) { + if (match(U, m_Add(m_Specific(A), m_Specific(B)))) { + Add = cast<BinaryOperator>(U); + return true; + } + } + return false; +} + /// Try to combine the compare into a call to the llvm.uadd.with.overflow /// intrinsic. Return true if any changes were made. static bool combineToUAddWithOverflow(CmpInst *Cmp, const TargetLowering &TLI, @@ -1204,7 +1229,8 @@ static bool combineToUAddWithOverflow(CmpInst *Cmp, const TargetLowering &TLI, Value *A, *B; BinaryOperator *Add; if (!match(Cmp, m_UAddWithOverflow(m_Value(A), m_Value(B), m_BinOp(Add)))) - return false; + if (!matchUAddWithOverflowConstantEdgeCases(Cmp, Add)) + return false; if (!TLI.shouldFormOverflowOp(ISD::UADDO, TLI.getValueType(DL, Add->getType()))) @@ -1216,13 +1242,6 @@ static bool combineToUAddWithOverflow(CmpInst *Cmp, const TargetLowering &TLI, if (Add->getParent() != Cmp->getParent() && !Add->hasOneUse()) return false; -#ifndef NDEBUG - // Someday m_UAddWithOverflow may get smarter, but this is a safe assumption - // for now: - if (Add->hasOneUse()) - assert(*Add->user_begin() == Cmp && "expected!"); -#endif - if (!replaceMathCmpWithIntrinsic(Add, Cmp, Intrinsic::uadd_with_overflow)) return false; |