[llvm] 83af24d - [DAG] Generalize fold (not (neg x)) -> (add X, -1) (#154348)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 8 08:13:04 PDT 2025
Author: guan jian
Date: 2025-09-08T15:12:59Z
New Revision: 83af24dd85b0a6cf764e69769bf8ab1a49b02cf5
URL: https://github.com/llvm/llvm-project/commit/83af24dd85b0a6cf764e69769bf8ab1a49b02cf5
DIFF: https://github.com/llvm/llvm-project/commit/83af24dd85b0a6cf764e69769bf8ab1a49b02cf5.diff
LOG: [DAG] Generalize fold (not (neg x)) -> (add X, -1) (#154348)
Generalize `fold (not (neg x)) -> (add X, -1)` to `fold (not (sub Y, X)) -> (add X, ~Y)`
---------
Co-authored-by: Yui5427 <785369607 at qq.com>
Co-authored-by: Simon Pilgrim <llvm-dev at redking.me.uk>
Added:
llvm/test/CodeGen/X86/xor-not-combine.ll
Modified:
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
llvm/test/CodeGen/X86/shift-i128.ll
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 1ef2b35952833..d130efe96b56b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -10001,13 +10001,16 @@ 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
+ if (N0.getOpcode() == ISD::SUB && isAllOnesConstant(N1)) {
+ SDValue Y = N0.getOperand(0);
+ SDValue X = N0.getOperand(1);
+
+ if (auto *YConst = dyn_cast<ConstantSDNode>(Y)) {
+ APInt NotYValue = ~YConst->getAPIntValue();
+ SDValue NotY = DAG.getConstant(NotYValue, DL, VT);
+ return DAG.getNode(ISD::ADD, DL, VT, X, NotY, N->getFlags());
+ }
}
// fold (not (add X, -1)) -> (neg X)
diff --git a/llvm/test/CodeGen/X86/shift-i128.ll b/llvm/test/CodeGen/X86/shift-i128.ll
index a82656e4b7147..7462c77482827 100644
--- a/llvm/test/CodeGen/X86/shift-i128.ll
+++ b/llvm/test/CodeGen/X86/shift-i128.ll
@@ -949,21 +949,20 @@ define i128 @shift_i128_limited_shamt(i128 noundef %a, i32 noundef %b) nounwind
; i686-NEXT: pushl %esi
; i686-NEXT: andl $-16, %esp
; i686-NEXT: subl $16, %esp
-; i686-NEXT: movl 28(%ebp), %esi
-; i686-NEXT: movl 32(%ebp), %eax
+; i686-NEXT: movl 32(%ebp), %ebx
+; i686-NEXT: movl 28(%ebp), %edi
+; i686-NEXT: movzbl 40(%ebp), %ecx
; i686-NEXT: movb $6, %dl
-; i686-NEXT: subb 40(%ebp), %dl
+; i686-NEXT: subb %cl, %dl
+; i686-NEXT: addb $-7, %cl
+; i686-NEXT: movl %edi, %eax
+; i686-NEXT: shrl %eax
+; i686-NEXT: shrl %cl, %eax
; i686-NEXT: movl %edx, %ecx
-; i686-NEXT: shll %cl, %eax
-; i686-NEXT: movl %esi, %ebx
-; i686-NEXT: movl %esi, %edi
-; i686-NEXT: shrl %ebx
-; i686-NEXT: notb %cl
-; i686-NEXT: shrl %cl, %ebx
+; i686-NEXT: shll %cl, %ebx
; i686-NEXT: orl %eax, %ebx
; i686-NEXT: movl 24(%ebp), %esi
; i686-NEXT: movl %esi, %eax
-; i686-NEXT: movl %edx, %ecx
; i686-NEXT: shll %cl, %eax
; i686-NEXT: shldl %cl, %esi, %edi
; i686-NEXT: movl %edi, {{[-0-9]+}}(%e{{[sb]}}p) # 4-byte Spill
@@ -972,10 +971,10 @@ define i128 @shift_i128_limited_shamt(i128 noundef %a, i32 noundef %b) nounwind
; i686-NEXT: movl 32(%ebp), %edx
; i686-NEXT: shldl %cl, %edx, %esi
; i686-NEXT: movl %esi, 12(%edi)
+; i686-NEXT: movl %ebx, 8(%edi)
; i686-NEXT: movl {{[-0-9]+}}(%e{{[sb]}}p), %ecx # 4-byte Reload
; i686-NEXT: movl %ecx, 4(%edi)
; i686-NEXT: movl %eax, (%edi)
-; i686-NEXT: movl %ebx, 8(%edi)
; i686-NEXT: movl %edi, %eax
; i686-NEXT: leal -12(%ebp), %esp
; i686-NEXT: popl %esi
diff --git a/llvm/test/CodeGen/X86/xor-not-combine.ll b/llvm/test/CodeGen/X86/xor-not-combine.ll
new file mode 100644
index 0000000000000..af65ade35ce8d
--- /dev/null
+++ b/llvm/test/CodeGen/X86/xor-not-combine.ll
@@ -0,0 +1,29 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=x86_64-unknown-linux-gnu | FileCheck %s
+
+; Test for DAG combine: fold (not (sub Y, X)) -> (add X, ~Y)
+; when Y is a constant.
+
+; Test case 1: Y is a constant - should transform to (add X, ~Y)
+define i32 @test_not_sub_constant(i32 %x) {
+; CHECK-LABEL: test_not_sub_constant:
+; CHECK: # %bb.0:
+; CHECK: leal -101(%rdi), %eax
+; CHECK-NEXT: retq
+ %sub = sub i32 100, %x
+ %not = xor i32 %sub, -1
+ ret i32 %not
+}
+
+; Test case 2: Y is not a constant - should NOT optimize
+define i32 @test_not_sub_non_constant(i32 %x, i32 %y) {
+; CHECK-LABEL: test_not_sub_non_constant:
+; CHECK: # %bb.0:
+; CHECK-NEXT: movl %esi, %eax
+; CHECK-NEXT: subl %edi, %eax
+; CHECK-NEXT: notl %eax
+; CHECK-NEXT: retq
+ %sub = sub i32 %y, %x
+ %not = xor i32 %sub, -1
+ ret i32 %not
+}
More information about the llvm-commits
mailing list