Skip to content

[SelectionDAG] fold (not (sub Y, X)) -> (add X, ~Y) #147825

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

AZero13
Copy link
Contributor

@AZero13 AZero13 commented Jul 9, 2025

This replaces (not (neg x)) -> (add X, -1) because that is covered by this.

@AZero13 AZero13 marked this pull request as ready for review July 9, 2025 20:49
@llvmbot llvmbot added the llvm:SelectionDAG SelectionDAGISel as well label Jul 9, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 9, 2025

@llvm/pr-subscribers-backend-x86
@llvm/pr-subscribers-backend-powerpc

@llvm/pr-subscribers-llvm-selectiondag

Author: AZero13 (AZero13)

Changes

This replaces (not (neg x)) -> (add X, -1) because that is covered by this.


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

1 Files Affected:

  • (modified) llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp (+7-7)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 9ffdda28f7899..90c673dd7e83b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -9979,13 +9979,13 @@ 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) is subtract is a single use
+  // or Y is a constant.
+  if (isAllOnesOrAllOnesSplat(N1) && N0.getOpcode() == ISD::SUB) {
+    ConstantSDNode *Const = dyn_cast<ConstantSDNode>(N0.getOperand(0));
+    if (Const || N0.hasOneUse())
+      return DAG.getNode(ISD::ADD, DL, VT, N0.getOperand(1),
+                         DAG.getNOT(DL, N0.getOperand(0), VT));
   }
 
   // fold (not (add X, -1)) -> (neg X)

@AZero13 AZero13 force-pushed the fixmesub branch 3 times, most recently from ec94756 to 37f723a Compare July 9, 2025 21:10
@badumbatish
Copy link
Contributor

has there been a test for this selectiondag folding after & before the TODO? it would be beneficial to add one if not

@AZero13 AZero13 requested a review from topperc July 10, 2025 01:05
@AZero13 AZero13 force-pushed the fixmesub branch 3 times, most recently from c4736a1 to a972c3a Compare July 10, 2025 01:15
This replaces (not (neg x)) -> (add X, -1) because that is covered by this.
Copy link
Contributor

@arsenm arsenm left a comment

Choose a reason for hiding this comment

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

Missing tests. Please never post functional change patches without tests

// fold (not (sub Y, X)) -> (add X, ~Y) if Y is a constant.
// FIXME: We can also do this with single-use sub, but this causes an infinite
// loop
if (isAllOnesConstant(N1) && N0.getOpcode() == ISD::SUB) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
if (isAllOnesConstant(N1) && N0.getOpcode() == ISD::SUB) {
if (N0.getOpcode() == ISD::SUB && isAllOnesConstant(N1)) {

@topperc
Copy link
Collaborator

topperc commented Jul 10, 2025

Stop force pushing patches. I'm tired of repeating this.

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.

5 participants