Skip to content

[InstCombine] Simplify (add/sub (sub/add) (sub/add)) irrelevant of use-count #105866

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from

Conversation

goldsteinn
Copy link
Contributor

@goldsteinn goldsteinn commented Aug 23, 2024

  • [InstCombine] Add tests for reassosiating (add/sub (sub/add) (sub/add)); NFC
  • [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

@llvmbot
Copy link
Member

llvmbot commented Aug 23, 2024

@llvm/pr-subscribers-llvm-transforms

Author: None (goldsteinn)

Changes
  • [InstCombine] Add tests for reassosiating (add/sub (sub/add) (sub/add)); NFC
  • [InstCombine] Simplify (add/sub (sub/add) (sub/add)) irrelivant of use-count

Full diff: https://github.com/llvm/llvm-project/pull/105866.diff

5 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp (+30)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp (+3)
  • (modified) llvm/lib/Transforms/InstCombine/InstCombineInternal.h (+3)
  • (modified) llvm/lib/Transforms/InstCombine/InstructionCombining.cpp (+26)
  • (added) llvm/test/Transforms/InstCombine/fold-add-sub.ll (+207)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index d7758b5fbf1786..5272bc11865f53 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -1520,6 +1520,9 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
   if (Instruction *R = combineAddSubWithShlAddSub(Builder, I))
     return R;
 
+  if (Instruction *R = foldAddLike(I))
+    return R;
+
   Value *LHS = I.getOperand(0), *RHS = I.getOperand(1);
   Type *Ty = I.getType();
   if (Ty->isIntOrIntVectorTy(1))
@@ -2286,6 +2289,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);
+      if (W == Z)
+        R = BinaryOperator::CreateSub(X, Y);
+      if (X == Y)
+        R = BinaryOperator::CreateSub(W, Z);
+      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,
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index b703bc7d04db58..8a2998e1de6430 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3576,6 +3576,9 @@ Instruction *InstCombinerImpl::visitOr(BinaryOperator &I) {
   if (Instruction *R = tryFoldInstWithCtpopWithNot(&I))
     return R;
 
+  if (Instruction *R = foldAddLike(I))
+    return R;
+
   Value *X, *Y;
   const APInt *CV;
   if (match(&I, m_c_Or(m_OneUse(m_Xor(m_Value(X), m_APInt(CV))), m_Value(Y))) &&
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index a0e846c3b5a566..e94f118ab3808a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -585,6 +585,9 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
                                FPClassTest DemandedMask, KnownFPClass &Known,
                                unsigned Depth = 0);
 
+  /// Common transforms for add / disjoint or
+  Instruction *foldAddLike(BinaryOperator &I);
+
   /// Canonicalize the position of binops relative to shufflevector.
   Instruction *foldVectorBinop(BinaryOperator &Inst);
   Instruction *foldVectorSelect(SelectInst &Sel);
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index c3f79fe4f901ad..3cdf693b66dfd1 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -2008,6 +2008,32 @@ static bool shouldMergeGEPs(GEPOperator &GEP, GEPOperator &Src) {
   return true;
 }
 
+Instruction *InstCombinerImpl::foldAddLike(BinaryOperator &I) {
+  Value *LHS = I.getOperand(0);
+  Value *RHS = I.getOperand(1);
+  Value *A, *B, *C, *D;
+  if (match(LHS, m_Sub(m_Value(A), m_Value(B))) &&
+      match(RHS, m_Sub(m_Value(C), m_Value(D)))) {
+    Instruction *R = nullptr;
+    if (A == D)
+      R = BinaryOperator::CreateSub(C, B);
+    if (C == B)
+      R = BinaryOperator::CreateSub(A, D);
+    if (R) {
+      bool NSW = match(&I, m_NSWAddLike(m_Value(), m_Value())) &&
+                 match(LHS, m_NSWSub(m_Value(), m_Value())) &&
+                 match(RHS, m_NSWSub(m_Value(), m_Value()));
+
+      bool NUW = match(LHS, m_NUWSub(m_Value(), m_Value())) &&
+                 match(RHS, m_NUWSub(m_Value(), m_Value()));
+      R->setHasNoSignedWrap(NSW);
+      R->setHasNoUnsignedWrap(NUW);
+      return R;
+    }
+  }
+  return nullptr;
+}
+
 Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
   if (!isa<VectorType>(Inst.getType()))
     return nullptr;
diff --git a/llvm/test/Transforms/InstCombine/fold-add-sub.ll b/llvm/test/Transforms/InstCombine/fold-add-sub.ll
new file mode 100644
index 00000000000000..bbb7bb67369e7f
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/fold-add-sub.ll
@@ -0,0 +1,207 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+declare void @use.i8(i8)
+define i8 @test_add_nsw(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_add_nsw(
+; CHECK-NEXT:    [[LHS:%.*]] = add nsw i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = add nsw i8 [[X]], [[Z:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = sub nsw i8 [[Y]], [[Z]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = add nsw i8 %x, %y
+  %rhs = add nsw i8 %x, %z
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = sub nsw i8 %lhs, %rhs
+  ret i8 %r
+}
+
+define i8 @test_add_nsw_no_prop(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_add_nsw_no_prop(
+; CHECK-NEXT:    [[LHS:%.*]] = add nsw i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = add nuw i8 [[X]], [[Z:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[Y]], [[Z]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = add nsw i8 %x, %y
+  %rhs = add nuw i8 %x, %z
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = sub nsw i8 %lhs, %rhs
+  ret i8 %r
+}
+
+define i8 @test_add(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_add(
+; CHECK-NEXT:    [[LHS:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = add i8 [[X]], [[Z:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[Y]], [[Z]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = add i8 %x, %y
+  %rhs = add i8 %x, %z
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = sub i8 %lhs, %rhs
+  ret i8 %r
+}
+
+define i8 @test_add_fail(i8 %w, i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_add_fail(
+; CHECK-NEXT:    [[LHS:%.*]] = add i8 [[W:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = add i8 [[X:%.*]], [[Z:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[LHS]], [[RHS]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = add i8 %w, %y
+  %rhs = add i8 %x, %z
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = sub i8 %lhs, %rhs
+  ret i8 %r
+}
+
+define i8 @test_add_nuw(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_add_nuw(
+; CHECK-NEXT:    [[LHS:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = or disjoint i8 [[X]], [[Z:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = sub nuw i8 [[Y]], [[Z]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = add i8 %x, %y
+  %rhs = or disjoint i8 %x, %z
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = sub nuw i8 %lhs, %rhs
+  ret i8 %r
+}
+
+define i8 @test_add_nuw_no_prop(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_add_nuw_no_prop(
+; CHECK-NEXT:    [[LHS:%.*]] = add i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = or disjoint i8 [[X]], [[Z:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[Y]], [[Z]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = add i8 %x, %y
+  %rhs = or disjoint i8 %x, %z
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = sub i8 %lhs, %rhs
+  ret i8 %r
+}
+
+define i8 @test_sub_nuw(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_sub_nuw(
+; CHECK-NEXT:    [[LHS:%.*]] = sub nuw i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = sub nuw i8 [[Y]], [[Z:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = sub nuw i8 [[X]], [[Z]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = sub nuw i8 %x, %y
+  %rhs = sub nuw i8 %y, %z
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = add i8 %lhs, %rhs
+  ret i8 %r
+}
+
+define i8 @test_sub_nuw_no_prop(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_sub_nuw_no_prop(
+; CHECK-NEXT:    [[LHS:%.*]] = sub nuw i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = sub i8 [[Y]], [[Z:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X]], [[Z]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = sub nuw i8 %x, %y
+  %rhs = sub i8 %y, %z
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = add nuw i8 %lhs, %rhs
+  ret i8 %r
+}
+
+define i8 @test_sub_nsw(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_sub_nsw(
+; CHECK-NEXT:    [[LHS:%.*]] = sub nsw i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = sub nsw i8 [[Y]], [[Z:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = sub nsw i8 [[X]], [[Z]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = sub nsw i8 %x, %y
+  %rhs = sub nsw i8 %y, %z
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = or disjoint i8 %lhs, %rhs
+  ret i8 %r
+}
+
+define i8 @test_sub_nsw_no_prop(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_sub_nsw_no_prop(
+; CHECK-NEXT:    [[LHS:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = sub nsw i8 [[Y]], [[Z:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X]], [[Z]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = sub i8 %x, %y
+  %rhs = sub nsw i8 %y, %z
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = or disjoint i8 %lhs, %rhs
+  ret i8 %r
+}
+
+define i8 @test_sub_none(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_sub_none(
+; CHECK-NEXT:    [[LHS:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = sub i8 [[Y]], [[Z:%.*]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = sub i8 [[X]], [[Z]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = sub i8 %x, %y
+  %rhs = sub i8 %y, %z
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = add i8 %lhs, %rhs
+  ret i8 %r
+}
+
+define i8 @test_sub_none_fail(i8 %x, i8 %y, i8 %z) {
+; CHECK-LABEL: @test_sub_none_fail(
+; CHECK-NEXT:    [[LHS:%.*]] = sub i8 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[RHS:%.*]] = sub i8 [[Z:%.*]], [[Y]]
+; CHECK-NEXT:    call void @use.i8(i8 [[LHS]])
+; CHECK-NEXT:    call void @use.i8(i8 [[RHS]])
+; CHECK-NEXT:    [[R:%.*]] = add i8 [[LHS]], [[RHS]]
+; CHECK-NEXT:    ret i8 [[R]]
+;
+  %lhs = sub i8 %x, %y
+  %rhs = sub i8 %z, %y
+  call void @use.i8(i8 %lhs)
+  call void @use.i8(i8 %rhs)
+  %r = add i8 %lhs, %rhs
+  ret i8 %r
+}

@goldsteinn goldsteinn changed the title goldsteinn/add sub reassos [InstCombine] Simplify (add/sub (sub/add) (sub/add)) irrelivant of use-count Aug 23, 2024
@goldsteinn
Copy link
Contributor Author

NB regarding if this patch exists, saw changes in:

./lib/Demangle/MicrosoftDemangle.cpp
./lib/Target/ARM/ARMConstantIslandPass.cpp
./lib/Target/ARM/ARMISelDAGToDAG.cpp
./lib/Target/Mips/MipsConstantIslandPass.cpp
./lib/Transforms/Scalar/DeadStoreElimination.cpp
./lib/Transforms/Vectorize/SLPVectorizer.cpp
./tools/clang/lib/Edit/EditedSource.cpp
./tools/clang/lib/Format/BreakableToken.cpp

when bootstrapping LLVM (changes in final output of O3 pipeline).

dtcxzyw added a commit to dtcxzyw/llvm-opt-benchmark that referenced this pull request Aug 23, 2024
Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This patch causes clang to miscompile lief:
Reproducer:

static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low,
                                                         unsigned char high,
                                                         unsigned char c,
                                                         unsigned char t)
{
    const unsigned char co = (unsigned char) (c);
    const unsigned char to = (unsigned char) (t);

    /* low_mask is: 0 if low <= c, 0x...ff if low > c */
    unsigned low_mask = ((unsigned) co - low) >> 8;
    /* high_mask is: 0 if c <= high, 0x...ff if c > high */
    unsigned high_mask = ((unsigned) high - co) >> 8;

    return (unsigned char) (~(low_mask | high_mask)) & to;
}

unsigned char mbedtls_ct_base64_enc_char(unsigned char value)
{
    unsigned char digit = 0;
    /* For each range of values, if value is in that range, mask digit with
     * the corresponding value. Since value can only be in a single range,
     * only at most one masking will change digit. */
    digit |= mbedtls_ct_uchar_in_range_if(0, 25, value, 'A' + value);
    digit |= mbedtls_ct_uchar_in_range_if(26, 51, value, 'a' + value - 26);
    digit |= mbedtls_ct_uchar_in_range_if(52, 61, value, '0' + value - 52);
    digit |= mbedtls_ct_uchar_in_range_if(62, 62, value, '+');
    digit |= mbedtls_ct_uchar_in_range_if(63, 63, value, '/');
    return digit;
}

int main() {
    return mbedtls_ct_base64_enc_char(0);
}

It should map 0 to 65(ascii 'A'), not -1.

@goldsteinn
Copy link
Contributor Author

This patch causes clang to miscompile lief: Reproducer:

[... snip ...]

It should map 0 to 65(ascii 'A'), not -1.

Fixed... wasnt guarding the foldAddLike in visitOr with a disjoint check...

dtcxzyw added a commit to dtcxzyw/llvm-opt-benchmark that referenced this pull request Aug 24, 2024
@goldsteinn goldsteinn force-pushed the goldsteinn/add-sub-reassos branch from d437f5c to fee4823 Compare August 24, 2024 16:38
Copy link
Member

@dtcxzyw dtcxzyw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG

@@ -2008,6 +2008,30 @@ static bool shouldMergeGEPs(GEPOperator &GEP, GEPOperator &Src) {
return true;
}

Instruction *InstCombinerImpl::foldAddLike(Value *LHS, Value *RHS, bool NSW,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also add foldAddLikeCommutative() which is invoked with both LHS/RHS orders, as most add folds with non-constant RHS will want to check both orders.

Then your pattern here will reduce down to:

if (match(LHS, m_Sub(m_Value(A), m_Value(B))) &&
    match(RHS, m_Sub(m_Value(C), m_Specific(A)))) {

…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
@goldsteinn goldsteinn force-pushed the goldsteinn/add-sub-reassos branch from fee4823 to 6d62821 Compare August 26, 2024 19:31
Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -2008,6 +2008,24 @@ static bool shouldMergeGEPs(GEPOperator &GEP, GEPOperator &Src) {
return true;
}

Instruction *InstCombinerImpl::foldAddLikeCommutative(Value *LHS, Value *RHS,
bool NSW, bool NUW) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this into InstCombineAddSub.cpp. It will make it easier to move folds if necessary.

@antoniofrighetto antoniofrighetto changed the title [InstCombine] Simplify (add/sub (sub/add) (sub/add)) irrelivant of use-count [InstCombine] Simplify (add/sub (sub/add) (sub/add)) irrelevant of use-count Aug 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants