Skip to content

Conversation

@rez5427
Copy link
Contributor

@rez5427 rez5427 commented Aug 19, 2025

Generalize fold (not (neg x)) -> (add X, -1) to fold (not (sub Y, X)) -> (add X, ~Y)

@github-actions
Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot
Copy link
Member

llvmbot commented Aug 19, 2025

@llvm/pr-subscribers-llvm-selectiondag

@llvm/pr-subscribers-backend-powerpc

Author: guan jian (rez5427)

Changes

Generalize fold (not (neg x)) -> (add X, -1) to fold (not (sub Y, X)) -> (add X, ~Y)


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

15 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+8-7)
  • (modified) llvm/test/CodeGen/PowerPC/setcc-to-sub.ll (+5-5)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesigeuc.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesigeui.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesigeus.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesileuc.ll (+4-4)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesileui.ll (+4-4)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesileus.ll (+4-4)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllgeuc.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllgeui.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllgeus.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllleuc.ll (+4-4)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllleui.ll (+4-4)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllleus.ll (+4-4)
  • (modified) llvm/test/CodeGen/X86/pr31045.ll (+4-4)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index c16ccaf926bc7..6f63b85857de2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -9988,13 +9988,14 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
     }
   }
 
-  // fold (not (neg x)) -> (add X, -1)
-  // FIXME: This can be generalized to (not (sub Y, X)) -> (add X, ~Y) if
-  // Y is a constant or the subtract has a single use.
-  if (isAllOnesConstant(N1) && N0.getOpcode() == ISD::SUB &&
-      isNullConstant(N0.getOperand(0))) {
-    return DAG.getNode(ISD::ADD, DL, VT, N0.getOperand(1),
-                       DAG.getAllOnesConstant(DL, VT));
+  // fold (not (sub Y, X)) -> (add X, ~Y) if Y is a constant or the subtract has a single use.
+  if (isAllOnesConstant(N1) && N0.getOpcode() == ISD::SUB) {
+    SDValue Y = N0.getOperand(0);
+    SDValue X = N0.getOperand(1);
+    if (isa<ConstantSDNode>(Y) || N0.hasOneUse()) {
+      SDValue NotY = DAG.getNode(ISD::XOR, DL, VT, Y, DAG.getAllOnesConstant(DL, VT));
+      return DAG.getNode(ISD::ADD, DL, VT, X, NotY);
+    }
   }
 
   // fold (not (add X, -1)) -> (neg X)
diff --git a/llvm/test/CodeGen/PowerPC/setcc-to-sub.ll b/llvm/test/CodeGen/PowerPC/setcc-to-sub.ll
index 20dcb8ccf4908..d2ca198d8fcda 100644
--- a/llvm/test/CodeGen/PowerPC/setcc-to-sub.ll
+++ b/llvm/test/CodeGen/PowerPC/setcc-to-sub.ll
@@ -31,12 +31,12 @@ entry:
 define zeroext i1 @test2(ptr %s_a, ptr %s_b) local_unnamed_addr #0 {
 ; CHECK-LABEL: test2:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    lwz 3, 0(3)
 ; CHECK-NEXT:    lwz 4, 0(4)
-; CHECK-NEXT:    rlwinm 3, 3, 0, 28, 28
+; CHECK-NEXT:    lwz 3, 0(3)
 ; CHECK-NEXT:    rlwinm 4, 4, 0, 28, 28
-; CHECK-NEXT:    sub 3, 4, 3
-; CHECK-NEXT:    not 3, 3
+; CHECK-NEXT:    rlwinm 3, 3, 0, 28, 28
+; CHECK-NEXT:    not 4, 4
+; CHECK-NEXT:    add 3, 3, 4
 ; CHECK-NEXT:    rldicl 3, 3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -76,8 +76,8 @@ define zeroext i1 @test4(ptr %s_a, ptr %s_b) local_unnamed_addr #0 {
 ; CHECK-NEXT:    lwz 4, 0(4)
 ; CHECK-NEXT:    rlwinm 3, 3, 0, 28, 28
 ; CHECK-NEXT:    rlwinm 4, 4, 0, 28, 28
-; CHECK-NEXT:    sub 3, 3, 4
 ; CHECK-NEXT:    not 3, 3
+; CHECK-NEXT:    add 3, 4, 3
 ; CHECK-NEXT:    rldicl 3, 3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
diff --git a/llvm/test/CodeGen/PowerPC/testComparesigeuc.ll b/llvm/test/CodeGen/PowerPC/testComparesigeuc.ll
index 37e589711f2db..6839578d45644 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesigeuc.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesigeuc.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_igeuc(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_igeuc:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -65,9 +65,9 @@ entry:
 define dso_local void @test_igeuc_store(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_igeuc_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stb r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesigeui.ll b/llvm/test/CodeGen/PowerPC/testComparesigeui.ll
index fc951124cf2a3..2d28d2ff94641 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesigeui.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesigeui.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_igeui(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_igeui:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -64,9 +64,9 @@ entry:
 define dso_local void @test_igeui_store(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_igeui_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stw r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesigeus.ll b/llvm/test/CodeGen/PowerPC/testComparesigeus.ll
index 522de14e4798a..e78381d937544 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesigeus.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesigeus.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_igeus(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_igeus:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -64,9 +64,9 @@ entry:
 define dso_local void @test_igeus_store(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_igeus_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    sth r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesileuc.ll b/llvm/test/CodeGen/PowerPC/testComparesileuc.ll
index 1b6d1ae17c9b0..17a332d647b91 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesileuc.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesileuc.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_ileuc(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_ileuc:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_ileuc_store(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_ileuc_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stb r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesileui.ll b/llvm/test/CodeGen/PowerPC/testComparesileui.ll
index 4c1efde742db9..e121bdfbbcc42 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesileui.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesileui.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_ileui(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_ileui:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_ileui_store(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_ileui_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stw r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesileus.ll b/llvm/test/CodeGen/PowerPC/testComparesileus.ll
index 31952081f3db9..14e2a87a95292 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesileus.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesileus.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_ileus(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_ileus:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_ileus_store(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_ileus_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    sth r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllgeuc.ll b/llvm/test/CodeGen/PowerPC/testComparesllgeuc.ll
index 14519472ad01d..464b92e5c9169 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllgeuc.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllgeuc.ll
@@ -12,8 +12,8 @@
 define i64 @test_llgeuc(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_llgeuc:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -64,9 +64,9 @@ entry:
 define dso_local void @test_llgeuc_store(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_llgeuc_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stb r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllgeui.ll b/llvm/test/CodeGen/PowerPC/testComparesllgeui.ll
index 6161109dbf923..31dde3c3f300e 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllgeui.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllgeui.ll
@@ -12,8 +12,8 @@
 define i64 @test_llgeui(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_llgeui:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -64,9 +64,9 @@ entry:
 define dso_local void @test_llgeui_store(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_llgeui_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stw r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllgeus.ll b/llvm/test/CodeGen/PowerPC/testComparesllgeus.ll
index a22def4beaf70..0d46fb9c6bf69 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllgeus.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllgeus.ll
@@ -12,8 +12,8 @@
 define i64 @test_llgeus(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_llgeus:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -64,9 +64,9 @@ entry:
 define dso_local void @test_llgeus_store(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_llgeus_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    sth r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllleuc.ll b/llvm/test/CodeGen/PowerPC/testComparesllleuc.ll
index cfaa6e8fe1d83..a5d74ad1201db 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllleuc.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllleuc.ll
@@ -12,8 +12,8 @@
 define i64 @test_llleuc(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_llleuc:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_llleuc_store(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_llleuc_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stb r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllleui.ll b/llvm/test/CodeGen/PowerPC/testComparesllleui.ll
index e438797cde772..1be2497b77193 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllleui.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllleui.ll
@@ -12,8 +12,8 @@
 define i64 @test_llleui(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_llleui:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_llleui_store(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_llleui_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stw r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllleus.ll b/llvm/test/CodeGen/PowerPC/testComparesllleus.ll
index 53b9b8a16d503..e84e3fbb4707e 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllleus.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllleus.ll
@@ -12,8 +12,8 @@
 define i64 @test_llleus(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_llleus:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_llleus_store(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_llleus_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    sth r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/X86/pr31045.ll b/llvm/test/CodeGen/X86/pr31045.ll
index 4aa73d79d8cfc..a873fc6fd4959 100644
--- a/llvm/test/CodeGen/X86/pr31045.ll
+++ b/llvm/test/CodeGen/X86/pr31045.ll
@@ -21,11 +21,11 @@ define void @_Z1av() local_unnamed_addr #0 {
 ; CHECK-NEXT:    movl struct_obj_3+8(%rip), %eax
 ; CHECK-NEXT:    movzbl var_46(%rip), %ecx
 ; CHECK-NEXT:    movzbl var_49(%rip), %edx
-; CHECK-NEXT:    andl $1, %eax
-; CHECK-NEXT:    addl %eax, %eax
-; CHECK-NEXT:    subl %ecx, %eax
-; CHECK-NEXT:    subl %edx, %eax
+; CHECK-NEXT:    addl %ecx, %edx
 ; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    addl %eax, %eax
+; CHECK-NEXT:    orl $253, %eax
+; CHECK-NEXT:    addl %edx, %eax
 ; CHECK-NEXT:    movzbl %al, %eax
 ; CHECK-NEXT:    movw %ax, struct_obj_12+5(%rip)
 ; CHECK-NEXT:    movb $0, var_163(%rip)

@llvmbot
Copy link
Member

llvmbot commented Aug 19, 2025

@llvm/pr-subscribers-backend-x86

Author: guan jian (rez5427)

Changes

Generalize fold (not (neg x)) -&gt; (add X, -1) to fold (not (sub Y, X)) -&gt; (add X, ~Y)


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

15 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+8-7)
  • (modified) llvm/test/CodeGen/PowerPC/setcc-to-sub.ll (+5-5)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesigeuc.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesigeui.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesigeus.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesileuc.ll (+4-4)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesileui.ll (+4-4)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesileus.ll (+4-4)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllgeuc.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllgeui.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllgeus.ll (+3-3)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllleuc.ll (+4-4)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllleui.ll (+4-4)
  • (modified) llvm/test/CodeGen/PowerPC/testComparesllleus.ll (+4-4)
  • (modified) llvm/test/CodeGen/X86/pr31045.ll (+4-4)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index c16ccaf926bc7..6f63b85857de2 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -9988,13 +9988,14 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
     }
   }
 
-  // fold (not (neg x)) -> (add X, -1)
-  // FIXME: This can be generalized to (not (sub Y, X)) -> (add X, ~Y) if
-  // Y is a constant or the subtract has a single use.
-  if (isAllOnesConstant(N1) && N0.getOpcode() == ISD::SUB &&
-      isNullConstant(N0.getOperand(0))) {
-    return DAG.getNode(ISD::ADD, DL, VT, N0.getOperand(1),
-                       DAG.getAllOnesConstant(DL, VT));
+  // fold (not (sub Y, X)) -> (add X, ~Y) if Y is a constant or the subtract has a single use.
+  if (isAllOnesConstant(N1) && N0.getOpcode() == ISD::SUB) {
+    SDValue Y = N0.getOperand(0);
+    SDValue X = N0.getOperand(1);
+    if (isa<ConstantSDNode>(Y) || N0.hasOneUse()) {
+      SDValue NotY = DAG.getNode(ISD::XOR, DL, VT, Y, DAG.getAllOnesConstant(DL, VT));
+      return DAG.getNode(ISD::ADD, DL, VT, X, NotY);
+    }
   }
 
   // fold (not (add X, -1)) -> (neg X)
diff --git a/llvm/test/CodeGen/PowerPC/setcc-to-sub.ll b/llvm/test/CodeGen/PowerPC/setcc-to-sub.ll
index 20dcb8ccf4908..d2ca198d8fcda 100644
--- a/llvm/test/CodeGen/PowerPC/setcc-to-sub.ll
+++ b/llvm/test/CodeGen/PowerPC/setcc-to-sub.ll
@@ -31,12 +31,12 @@ entry:
 define zeroext i1 @test2(ptr %s_a, ptr %s_b) local_unnamed_addr #0 {
 ; CHECK-LABEL: test2:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    lwz 3, 0(3)
 ; CHECK-NEXT:    lwz 4, 0(4)
-; CHECK-NEXT:    rlwinm 3, 3, 0, 28, 28
+; CHECK-NEXT:    lwz 3, 0(3)
 ; CHECK-NEXT:    rlwinm 4, 4, 0, 28, 28
-; CHECK-NEXT:    sub 3, 4, 3
-; CHECK-NEXT:    not 3, 3
+; CHECK-NEXT:    rlwinm 3, 3, 0, 28, 28
+; CHECK-NEXT:    not 4, 4
+; CHECK-NEXT:    add 3, 3, 4
 ; CHECK-NEXT:    rldicl 3, 3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -76,8 +76,8 @@ define zeroext i1 @test4(ptr %s_a, ptr %s_b) local_unnamed_addr #0 {
 ; CHECK-NEXT:    lwz 4, 0(4)
 ; CHECK-NEXT:    rlwinm 3, 3, 0, 28, 28
 ; CHECK-NEXT:    rlwinm 4, 4, 0, 28, 28
-; CHECK-NEXT:    sub 3, 3, 4
 ; CHECK-NEXT:    not 3, 3
+; CHECK-NEXT:    add 3, 4, 3
 ; CHECK-NEXT:    rldicl 3, 3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
diff --git a/llvm/test/CodeGen/PowerPC/testComparesigeuc.ll b/llvm/test/CodeGen/PowerPC/testComparesigeuc.ll
index 37e589711f2db..6839578d45644 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesigeuc.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesigeuc.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_igeuc(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_igeuc:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -65,9 +65,9 @@ entry:
 define dso_local void @test_igeuc_store(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_igeuc_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stb r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesigeui.ll b/llvm/test/CodeGen/PowerPC/testComparesigeui.ll
index fc951124cf2a3..2d28d2ff94641 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesigeui.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesigeui.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_igeui(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_igeui:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -64,9 +64,9 @@ entry:
 define dso_local void @test_igeui_store(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_igeui_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stw r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesigeus.ll b/llvm/test/CodeGen/PowerPC/testComparesigeus.ll
index 522de14e4798a..e78381d937544 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesigeus.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesigeus.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_igeus(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_igeus:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -64,9 +64,9 @@ entry:
 define dso_local void @test_igeus_store(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_igeus_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    sth r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesileuc.ll b/llvm/test/CodeGen/PowerPC/testComparesileuc.ll
index 1b6d1ae17c9b0..17a332d647b91 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesileuc.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesileuc.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_ileuc(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_ileuc:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_ileuc_store(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_ileuc_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stb r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesileui.ll b/llvm/test/CodeGen/PowerPC/testComparesileui.ll
index 4c1efde742db9..e121bdfbbcc42 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesileui.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesileui.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_ileui(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_ileui:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_ileui_store(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_ileui_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stw r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesileus.ll b/llvm/test/CodeGen/PowerPC/testComparesileus.ll
index 31952081f3db9..14e2a87a95292 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesileus.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesileus.ll
@@ -12,8 +12,8 @@
 define dso_local signext i32 @test_ileus(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_ileus:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_ileus_store(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_ileus_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    sth r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllgeuc.ll b/llvm/test/CodeGen/PowerPC/testComparesllgeuc.ll
index 14519472ad01d..464b92e5c9169 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllgeuc.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllgeuc.ll
@@ -12,8 +12,8 @@
 define i64 @test_llgeuc(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_llgeuc:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -64,9 +64,9 @@ entry:
 define dso_local void @test_llgeuc_store(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_llgeuc_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stb r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllgeui.ll b/llvm/test/CodeGen/PowerPC/testComparesllgeui.ll
index 6161109dbf923..31dde3c3f300e 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllgeui.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllgeui.ll
@@ -12,8 +12,8 @@
 define i64 @test_llgeui(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_llgeui:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -64,9 +64,9 @@ entry:
 define dso_local void @test_llgeui_store(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_llgeui_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stw r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllgeus.ll b/llvm/test/CodeGen/PowerPC/testComparesllgeus.ll
index a22def4beaf70..0d46fb9c6bf69 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllgeus.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllgeus.ll
@@ -12,8 +12,8 @@
 define i64 @test_llgeus(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_llgeus:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -64,9 +64,9 @@ entry:
 define dso_local void @test_llgeus_store(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_llgeus_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r3, r4
-; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    add r3, r4, r3
+; CHECK-NEXT:    addis r4, r2, glob@toc@ha
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    sth r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllleuc.ll b/llvm/test/CodeGen/PowerPC/testComparesllleuc.ll
index cfaa6e8fe1d83..a5d74ad1201db 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllleuc.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllleuc.ll
@@ -12,8 +12,8 @@
 define i64 @test_llleuc(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_llleuc:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_llleuc_store(i8 zeroext %a, i8 zeroext %b) {
 ; CHECK-LABEL: test_llleuc_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stb r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllleui.ll b/llvm/test/CodeGen/PowerPC/testComparesllleui.ll
index e438797cde772..1be2497b77193 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllleui.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllleui.ll
@@ -12,8 +12,8 @@
 define i64 @test_llleui(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_llleui:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_llleui_store(i32 zeroext %a, i32 zeroext %b) {
 ; CHECK-LABEL: test_llleui_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    stw r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/PowerPC/testComparesllleus.ll b/llvm/test/CodeGen/PowerPC/testComparesllleus.ll
index 53b9b8a16d503..e84e3fbb4707e 100644
--- a/llvm/test/CodeGen/PowerPC/testComparesllleus.ll
+++ b/llvm/test/CodeGen/PowerPC/testComparesllleus.ll
@@ -12,8 +12,8 @@
 define i64 @test_llleus(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_llleus:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
-; CHECK-NEXT:    not r3, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    blr
 entry:
@@ -67,9 +67,9 @@ entry:
 define dso_local void @test_llleus_store(i16 zeroext %a, i16 zeroext %b) {
 ; CHECK-LABEL: test_llleus_store:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    sub r3, r4, r3
+; CHECK-NEXT:    not r4, r4
+; CHECK-NEXT:    add r3, r3, r4
 ; CHECK-NEXT:    addis r4, r2, glob@toc@ha
-; CHECK-NEXT:    not r3, r3
 ; CHECK-NEXT:    rldicl r3, r3, 1, 63
 ; CHECK-NEXT:    sth r3, glob@toc@l(r4)
 ; CHECK-NEXT:    blr
diff --git a/llvm/test/CodeGen/X86/pr31045.ll b/llvm/test/CodeGen/X86/pr31045.ll
index 4aa73d79d8cfc..a873fc6fd4959 100644
--- a/llvm/test/CodeGen/X86/pr31045.ll
+++ b/llvm/test/CodeGen/X86/pr31045.ll
@@ -21,11 +21,11 @@ define void @_Z1av() local_unnamed_addr #0 {
 ; CHECK-NEXT:    movl struct_obj_3+8(%rip), %eax
 ; CHECK-NEXT:    movzbl var_46(%rip), %ecx
 ; CHECK-NEXT:    movzbl var_49(%rip), %edx
-; CHECK-NEXT:    andl $1, %eax
-; CHECK-NEXT:    addl %eax, %eax
-; CHECK-NEXT:    subl %ecx, %eax
-; CHECK-NEXT:    subl %edx, %eax
+; CHECK-NEXT:    addl %ecx, %edx
 ; CHECK-NEXT:    notl %eax
+; CHECK-NEXT:    addl %eax, %eax
+; CHECK-NEXT:    orl $253, %eax
+; CHECK-NEXT:    addl %edx, %eax
 ; CHECK-NEXT:    movzbl %al, %eax
 ; CHECK-NEXT:    movw %ax, struct_obj_12+5(%rip)
 ; CHECK-NEXT:    movb $0, var_163(%rip)

@arsenm arsenm changed the title [DAG] Genralize fold (not (neg x)) -> (add X, -1) [DAG] Generalize fold (not (neg x)) -> (add X, -1) Aug 19, 2025
@github-actions
Copy link

github-actions bot commented Aug 20, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@RKSimon RKSimon left a comment

Choose a reason for hiding this comment

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

Infinite loop in AArch64/aarch64-bitwisenot-fold.ll ?

@rez5427
Copy link
Contributor Author

rez5427 commented Aug 20, 2025

Infinite loop in AArch64/aarch64-bitwisenot-fold.ll ?

It seems like is mutual recursion with the code below.

// Fold (and X, (add (not Y), Z)) -> (and X, (not (sub Y, Z)))
// Fold (and X, (sub (not Y), Z)) -> (and X, (not (add Y, Z)))
if (TLI.hasAndNot(SDValue(N, 0)))
  if (SDValue Folded = foldBitwiseOpWithNeg(N, DL, VT))
    return Folded;

fold ( and X, (add (not Y), Z) ) -> (and X, (not (sub Y, Z)))
fold ( and X, (not (sub Y, Z))) -> (and X, (add Z, (not Y)))
same thing appears again

@rez5427
Copy link
Contributor Author

rez5427 commented Aug 21, 2025

Infinite loop in AArch64/aarch64-bitwisenot-fold.ll ?

I guess the problem is fixed, can you guys give a look? @arsenm @RKSimon

@rez5427 rez5427 force-pushed the fixme-dag-not-sub-generalize branch from 9c2c0c9 to c85002d Compare August 21, 2025 10:48
@rez5427 rez5427 force-pushed the fixme-dag-not-sub-generalize branch from 30181d4 to 724bf1f Compare August 22, 2025 05:32
@rez5427 rez5427 requested review from RKSimon, arsenm and topperc August 29, 2025 07:58
@rez5427
Copy link
Contributor Author

rez5427 commented Aug 29, 2025

ping

@rez5427 rez5427 force-pushed the fixme-dag-not-sub-generalize branch from 724bf1f to 72f889c Compare August 29, 2025 08:23
@rez5427
Copy link
Contributor Author

rez5427 commented Sep 4, 2025

ping

@rez5427 rez5427 requested a review from RKSimon September 4, 2025 08:02
@rez5427 rez5427 force-pushed the fixme-dag-not-sub-generalize branch from 5e43dbc to b099b43 Compare September 5, 2025 09:56
@rez5427 rez5427 force-pushed the fixme-dag-not-sub-generalize branch from b099b43 to f0e2a65 Compare September 6, 2025 10:56
@rez5427
Copy link
Contributor Author

rez5427 commented Sep 6, 2025

Well, I reverted the earlier changes and rebased the branch with the latest modifications to llvm/test/CodeGen/X86/shift-i128.ll. This test case had one fewer line due to this fold.

Copy link
Collaborator

@RKSimon RKSimon left a comment

Choose a reason for hiding this comment

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

LGTM - cheers

@rez5427
Copy link
Contributor Author

rez5427 commented Sep 8, 2025

LGTM - cheers

Thanks!

@RKSimon RKSimon enabled auto-merge (squash) September 8, 2025 14:42
@RKSimon RKSimon merged commit 83af24d into llvm:main Sep 8, 2025
9 checks passed
@github-actions
Copy link

github-actions bot commented Sep 8, 2025

@rez5427 Congratulations on having your first Pull Request (PR) merged into the LLVM Project!

Your changes will be combined with recent changes from other authors, then tested by our build bots. If there is a problem with a build, you may receive a report in an email or a comment on this PR.

Please check whether problems have been caused by your change specifically, as the builds can include changes from many authors. It is not uncommon for your change to be included in a build that fails due to someone else's changes, or infrastructure issues.

How to do this, and the rest of the post-merge process, is covered in detail here.

If your change does cause a problem, it may be reverted, or you can revert it yourself. This is a normal part of LLVM development. You can fix your changes and open a new PR to merge them again.

If you don't get any reports, no action is required from you. Your changes are working as expected, well done!

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.

7 participants