aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
diff options
context:
space:
mode:
authorNoah Goldstein <goldstein.w.n@gmail.com>2024-08-22 14:42:08 -0700
committerNoah Goldstein <goldstein.w.n@gmail.com>2024-08-27 11:43:17 -0700
commita6edcea211a3d415212adb69b544f853351a7627 (patch)
tree9d77faba1853b5e1bf5843c202856b7eb6042f73 /llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
parent155e3aa0d7ea46dc99672bfe7291ed3084201c5e (diff)
downloadllvm-a6edcea211a3d415212adb69b544f853351a7627.zip
llvm-a6edcea211a3d415212adb69b544f853351a7627.tar.gz
llvm-a6edcea211a3d415212adb69b544f853351a7627.tar.bz2
[InstCombine] Simplify `(add/sub (sub/add) (sub/add))` irrelivant of use-count
Added folds: - `(add (sub X, Y), (sub Z, X))` -> `(sub Z, Y)` - `(sub (add X, Y), (add X, Z))` -> `(sub Y, Z)` The fold typically is handled in the `Reassosiate` pass, but it fails if the inner `sub`/`add` are multi-use. Less importantly, Reassosiate doesn't propagate flags correctly. This patch adds the fold explicitly the InstCombine Proofs: https://alive2.llvm.org/ce/z/p6JyRP Closes #105866
Diffstat (limited to 'llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp')
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index d7758b5..e5c3a20 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -1304,6 +1304,24 @@ static Instruction *foldAddToAshr(BinaryOperator &Add) {
X, ConstantInt::get(Add.getType(), DivC->exactLogBase2()));
}
+Instruction *InstCombinerImpl::foldAddLikeCommutative(Value *LHS, Value *RHS,
+ bool NSW, bool NUW) {
+ Value *A, *B, *C;
+ if (match(LHS, m_Sub(m_Value(A), m_Value(B))) &&
+ match(RHS, m_Sub(m_Value(C), m_Specific(A)))) {
+ Instruction *R = BinaryOperator::CreateSub(C, B);
+ bool NSWOut = NSW && match(LHS, m_NSWSub(m_Value(), m_Value())) &&
+ match(RHS, m_NSWSub(m_Value(), m_Value()));
+
+ bool NUWOut = match(LHS, m_NUWSub(m_Value(), m_Value())) &&
+ match(RHS, m_NUWSub(m_Value(), m_Value()));
+ R->setHasNoSignedWrap(NSWOut);
+ R->setHasNoUnsignedWrap(NUWOut);
+ return R;
+ }
+ return nullptr;
+}
+
Instruction *InstCombinerImpl::
canonicalizeCondSignextOfHighBitExtractToSignextHighBitExtract(
BinaryOperator &I) {
@@ -1521,6 +1539,12 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
return R;
Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
+ if (Instruction *R = foldAddLikeCommutative(LHS, RHS, I.hasNoSignedWrap(),
+ I.hasNoUnsignedWrap()))
+ return R;
+ if (Instruction *R = foldAddLikeCommutative(RHS, LHS, I.hasNoSignedWrap(),
+ I.hasNoUnsignedWrap()))
+ return R;
Type *Ty = I.getType();
if (Ty->isIntOrIntVectorTy(1))
return BinaryOperator::CreateXor(LHS, RHS);
@@ -2286,6 +2310,33 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
}
}
+ {
+ Value *W, *Z;
+ if (match(Op0, m_AddLike(m_Value(W), m_Value(X))) &&
+ match(Op1, m_AddLike(m_Value(Y), m_Value(Z)))) {
+ Instruction *R = nullptr;
+ if (W == Y)
+ R = BinaryOperator::CreateSub(X, Z);
+ else if (W == Z)
+ R = BinaryOperator::CreateSub(X, Y);
+ else if (X == Y)
+ R = BinaryOperator::CreateSub(W, Z);
+ else if (X == Z)
+ R = BinaryOperator::CreateSub(W, Y);
+ if (R) {
+ bool NSW = I.hasNoSignedWrap() &&
+ match(Op0, m_NSWAddLike(m_Value(), m_Value())) &&
+ match(Op1, m_NSWAddLike(m_Value(), m_Value()));
+
+ bool NUW = I.hasNoUnsignedWrap() &&
+ match(Op1, m_NUWAddLike(m_Value(), m_Value()));
+ R->setHasNoSignedWrap(NSW);
+ R->setHasNoUnsignedWrap(NUW);
+ return R;
+ }
+ }
+ }
+
// (~X) - (~Y) --> Y - X
{
// Need to ensure we can consume at least one of the `not` instructions,