diff options
author | Noah Goldstein <goldstein.w.n@gmail.com> | 2024-08-22 14:42:08 -0700 |
---|---|---|
committer | Noah Goldstein <goldstein.w.n@gmail.com> | 2024-08-27 11:43:17 -0700 |
commit | a6edcea211a3d415212adb69b544f853351a7627 (patch) | |
tree | 9d77faba1853b5e1bf5843c202856b7eb6042f73 /llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | |
parent | 155e3aa0d7ea46dc99672bfe7291ed3084201c5e (diff) | |
download | llvm-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.cpp | 51 |
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, |