diff options
author | Nikita Popov <nikita.ppv@gmail.com> | 2019-03-27 17:56:15 +0000 |
---|---|---|
committer | Nikita Popov <nikita.ppv@gmail.com> | 2019-03-27 17:56:15 +0000 |
commit | 7462303e0680d36ff856c54707489474f717e83f (patch) | |
tree | 33f551363ede878a420ac6f51fcdc2671cf12e8c /llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | |
parent | a69698f45fadefd2cabba8d5aa1a8e93463a6d49 (diff) | |
download | bcm5719-llvm-7462303e0680d36ff856c54707489474f717e83f.tar.gz bcm5719-llvm-7462303e0680d36ff856c54707489474f717e83f.zip |
[InstCombine] Use uadd.sat and usub.sat for canonicalization
Start using the uadd.sat and usub.sat intrinsics for the existing
canonicalizations. These intrinsics should optimize better than
expanded IR, have better handling in the X86 backend and should
be no worse than expanded IR in other backends, as far as we know.
rL357012 already introduced use of uadd.sat for the add+umin pattern.
Differential Revision: https://reviews.llvm.org/D58872
llvm-svn: 357103
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp')
-rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp | 49 |
1 files changed, 21 insertions, 28 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp index 582353eba1c..3fb99bc119a 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -622,11 +622,7 @@ static Value *foldSelectICmpAndOr(const ICmpInst *IC, Value *TrueVal, return Builder.CreateOr(V, Y); } -/// Transform patterns such as: (a > b) ? a - b : 0 -/// into: ((a > b) ? a : b) - b) -/// This produces a canonical max pattern that is more easily recognized by the -/// backend and converted into saturated subtraction instructions if those -/// exist. +/// Transform patterns such as (a > b) ? a - b : 0 into usub.sat(a, b). /// There are 8 commuted/swapped variants of this pattern. /// TODO: Also support a - UMIN(a,b) patterns. static Value *canonicalizeSaturatedSubtract(const ICmpInst *ICI, @@ -668,11 +664,12 @@ static Value *canonicalizeSaturatedSubtract(const ICmpInst *ICI, if (!TrueVal->hasOneUse()) return nullptr; - // All checks passed, convert to canonical unsigned saturated subtraction - // form: sub(max()). - // (a > b) ? a - b : 0 -> ((a > b) ? a : b) - b) - Value *Max = Builder.CreateSelect(Builder.CreateICmp(Pred, A, B), A, B); - return IsNegative ? Builder.CreateSub(B, Max) : Builder.CreateSub(Max, B); + // (a > b) ? a - b : 0 -> usub.sat(a, b) + // (a > b) ? b - a : 0 -> -usub.sat(a, b) + Value *Result = Builder.CreateBinaryIntrinsic(Intrinsic::usub_sat, A, B); + if (IsNegative) + Result = Builder.CreateNeg(Result); + return Result; } static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal, @@ -689,15 +686,16 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal, if (Pred == ICmpInst::ICMP_ULT && match(TVal, m_Add(m_Value(X), m_APInt(C))) && X == Cmp0 && match(FVal, m_AllOnes()) && match(Cmp1, m_APInt(CmpC)) && *CmpC == ~*C) { - // Commute compare predicate and select operands: - // (X u< ~C) ? (X + C) : -1 --> (X u> ~C) ? -1 : (X + C) - Value *NewCmp = Builder.CreateICmp(ICmpInst::ICMP_UGT, X, Cmp1); - return Builder.CreateSelect(NewCmp, FVal, TVal); + // (X u< ~C) ? (X + C) : -1 --> uadd.sat(X, C) + return Builder.CreateBinaryIntrinsic( + Intrinsic::uadd_sat, X, ConstantInt::get(X->getType(), *C)); } // Match unsigned saturated add of 2 variables with an unnecessary 'not'. // There are 8 commuted variants. - // Canonicalize -1 (saturated result) to true value of the select. + // Canonicalize -1 (saturated result) to true value of the select. Just + // swapping the compare operands is legal, because the selected value is the + // same in case of equality, so we can interchange u< and u<=. if (match(FVal, m_AllOnes())) { std::swap(TVal, FVal); std::swap(Cmp0, Cmp1); @@ -717,24 +715,19 @@ static Value *canonicalizeSaturatedAdd(ICmpInst *Cmp, Value *TVal, Value *FVal, Value *Y; if (match(Cmp0, m_Not(m_Value(X))) && match(FVal, m_c_Add(m_Specific(X), m_Value(Y))) && Y == Cmp1) { - // Change the comparison to use the sum (false value of the select). That is - // a canonical pattern match form for uadd.with.overflow and eliminates a - // use of the 'not' op: - // (~X u< Y) ? -1 : (X + Y) --> ((X + Y) u< Y) ? -1 : (X + Y) - // (~X u< Y) ? -1 : (Y + X) --> ((Y + X) u< Y) ? -1 : (Y + X) - Value *NewCmp = Builder.CreateICmp(ICmpInst::ICMP_ULT, FVal, Y); - return Builder.CreateSelect(NewCmp, TVal, FVal); + // (~X u< Y) ? -1 : (X + Y) --> uadd.sat(X, Y) + // (~X u< Y) ? -1 : (Y + X) --> uadd.sat(X, Y) + return Builder.CreateBinaryIntrinsic(Intrinsic::uadd_sat, X, Y); } // The 'not' op may be included in the sum but not the compare. X = Cmp0; Y = Cmp1; if (match(FVal, m_c_Add(m_Not(m_Specific(X)), m_Specific(Y)))) { - // Change the comparison to use the sum (false value of the select). That is - // a canonical pattern match form for uadd.with.overflow: - // (X u< Y) ? -1 : (~X + Y) --> ((~X + Y) u< Y) ? -1 : (~X + Y) - // (X u< Y) ? -1 : (Y + ~X) --> ((Y + ~X) u< Y) ? -1 : (Y + ~X) - Value *NewCmp = Builder.CreateICmp(ICmpInst::ICMP_ULT, FVal, Y); - return Builder.CreateSelect(NewCmp, TVal, FVal); + // (X u< Y) ? -1 : (~X + Y) --> uadd.sat(~X, Y) + // (X u< Y) ? -1 : (Y + ~X) --> uadd.sat(Y, ~X) + BinaryOperator *BO = cast<BinaryOperator>(FVal); + return Builder.CreateBinaryIntrinsic( + Intrinsic::uadd_sat, BO->getOperand(0), BO->getOperand(1)); } return nullptr; |