diff options
author | Sanjay Patel <spatel@rotateright.com> | 2018-11-20 17:20:26 +0000 |
---|---|---|
committer | Sanjay Patel <spatel@rotateright.com> | 2018-11-20 17:20:26 +0000 |
commit | eea21da12a16d6f81a9cf213c988ab058c6b2722 (patch) | |
tree | 471f982deff00dd4dd45d5eda8fe41ef9f14cf56 /llvm/lib/Analysis/InstructionSimplify.cpp | |
parent | 06a9b5a30557698f8eccc920533a5432a56ee8db (diff) | |
download | bcm5719-llvm-eea21da12a16d6f81a9cf213c988ab058c6b2722.tar.gz bcm5719-llvm-eea21da12a16d6f81a9cf213c988ab058c6b2722.zip |
[InstructionSimplify] Add support for saturating add/sub
Add support for saturating add/sub in InstructionSimplify. In particular, the following simplifications are supported:
sat(X + 0) -> X
sat(X + undef) -> -1
sat(X uadd MAX) -> MAX
(and commutative variants)
sat(X - 0) -> X
sat(X - X) -> 0
sat(X - undef) -> 0
sat(undef - X) -> 0
sat(0 usub X) -> 0
sat(X usub MAX) -> 0
Patch by: @nikic (Nikita Popov)
Differential Revision: https://reviews.llvm.org/D54532
llvm-svn: 347330
Diffstat (limited to 'llvm/lib/Analysis/InstructionSimplify.cpp')
-rw-r--r-- | llvm/lib/Analysis/InstructionSimplify.cpp | 34 |
1 files changed, 34 insertions, 0 deletions
diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index 0039d1eebc0..599a2f2ce4c 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -4912,6 +4912,40 @@ static Value *simplifyBinaryIntrinsic(Function *F, Value *Op0, Value *Op1, if (match(Op0, m_Undef()) || match(Op1, m_Undef())) return Constant::getNullValue(ReturnType); break; + case Intrinsic::uadd_sat: + // sat(MAX + X) -> MAX + // sat(X + MAX) -> MAX + if (match(Op0, m_AllOnes()) || match(Op1, m_AllOnes())) + return Constant::getAllOnesValue(ReturnType); + LLVM_FALLTHROUGH; + case Intrinsic::sadd_sat: + // sat(X + undef) -> -1 + // sat(undef + X) -> -1 + // For unsigned: Assume undef is MAX, thus we saturate to MAX (-1). + // For signed: Assume undef is ~X, in which case X + ~X = -1. + if (match(Op0, m_Undef()) || match(Op1, m_Undef())) + return Constant::getAllOnesValue(ReturnType); + + // X + 0 -> X + if (match(Op1, m_Zero())) + return Op0; + // 0 + X -> X + if (match(Op0, m_Zero())) + return Op1; + break; + case Intrinsic::usub_sat: + // sat(0 - X) -> 0, sat(X - MAX) -> 0 + if (match(Op0, m_Zero()) || match(Op1, m_AllOnes())) + return Constant::getNullValue(ReturnType); + LLVM_FALLTHROUGH; + case Intrinsic::ssub_sat: + // X - X -> 0, X - undef -> 0, undef - X -> 0 + if (Op0 == Op1 || match(Op0, m_Undef()) || match(Op1, m_Undef())) + return Constant::getNullValue(ReturnType); + // X - 0 -> X + if (match(Op1, m_Zero())) + return Op0; + break; case Intrinsic::load_relative: if (auto *C0 = dyn_cast<Constant>(Op0)) if (auto *C1 = dyn_cast<Constant>(Op1)) |