summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Analysis/InstructionSimplify.cpp
diff options
context:
space:
mode:
authorSanjay Patel <spatel@rotateright.com>2018-11-20 17:20:26 +0000
committerSanjay Patel <spatel@rotateright.com>2018-11-20 17:20:26 +0000
commiteea21da12a16d6f81a9cf213c988ab058c6b2722 (patch)
tree471f982deff00dd4dd45d5eda8fe41ef9f14cf56 /llvm/lib/Analysis/InstructionSimplify.cpp
parent06a9b5a30557698f8eccc920533a5432a56ee8db (diff)
downloadbcm5719-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.cpp34
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))
OpenPOWER on IntegriCloud