From 81758b461c40315d2b9e692cb39053da869f8e2a Mon Sep 17 00:00:00 2001 From: Yui5427 <785369607@qq.com> Date: Tue, 19 Aug 2025 22:34:03 +0800 Subject: [PATCH 1/6] [DAG] genralize not neg x --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 15 ++++++++------- llvm/test/CodeGen/PowerPC/setcc-to-sub.ll | 10 +++++----- llvm/test/CodeGen/PowerPC/testComparesigeuc.ll | 6 +++--- llvm/test/CodeGen/PowerPC/testComparesigeui.ll | 6 +++--- llvm/test/CodeGen/PowerPC/testComparesigeus.ll | 6 +++--- llvm/test/CodeGen/PowerPC/testComparesileuc.ll | 8 ++++---- llvm/test/CodeGen/PowerPC/testComparesileui.ll | 8 ++++---- llvm/test/CodeGen/PowerPC/testComparesileus.ll | 8 ++++---- llvm/test/CodeGen/PowerPC/testComparesllgeuc.ll | 6 +++--- llvm/test/CodeGen/PowerPC/testComparesllgeui.ll | 6 +++--- llvm/test/CodeGen/PowerPC/testComparesllgeus.ll | 6 +++--- llvm/test/CodeGen/PowerPC/testComparesllleuc.ll | 8 ++++---- llvm/test/CodeGen/PowerPC/testComparesllleui.ll | 8 ++++---- llvm/test/CodeGen/PowerPC/testComparesllleus.ll | 8 ++++---- llvm/test/CodeGen/X86/pr31045.ll | 8 ++++---- 15 files changed, 59 insertions(+), 58 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 6310f7270ceaf..f8c59e58cbd1d 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10001,13 +10001,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(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) From d8354bc79eb22c41954822d56cb8e2d0413e256d Mon Sep 17 00:00:00 2001 From: Yui5427 <785369607@qq.com> Date: Wed, 20 Aug 2025 15:21:25 +0800 Subject: [PATCH 2/6] Add xor sub combine test --- llvm/test/CodeGen/X86/xor-not-combine.ll | 44 ++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 llvm/test/CodeGen/X86/xor-not-combine.ll 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..334328bc457bb --- /dev/null +++ b/llvm/test/CodeGen/X86/xor-not-combine.ll @@ -0,0 +1,44 @@ +; 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 or the subtract has a single use. + +; 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: Subtract has single use - should optimize +define i32 @test_not_sub_single_use(i32 %x, i32 %y) { +; CHECK-LABEL: test_not_sub_single_use: +; CHECK: # %bb.0: +; CHECK: notl %esi +; CHECK-NEXT: leal (%rsi,%rdi), %eax +; CHECK-NEXT: retq + %sub = sub i32 %y, %x + %not = xor i32 %sub, -1 + ret i32 %not +} + +; Negative test: Y is not constant AND subtract has multiple uses - should NOT optimize +define i32 @test_not_sub_multiple_uses_non_constant(i32 %x, i32 %y) { +; CHECK-LABEL: test_not_sub_multiple_uses_non_constant: +; CHECK: # %bb.0: +; CHECK: subl %edi, %esi +; CHECK-NEXT: movl %esi, %eax +; CHECK-NEXT: notl %eax +; CHECK-NEXT: leal (%rax,%rsi,2), %eax +; CHECK-NEXT: retq + %sub = sub i32 %y, %x + %not = xor i32 %sub, -1 + %other_use = mul i32 %sub, 2 ; sub is used twice, and Y is not constant + %result = add i32 %not, %other_use + ret i32 %result +} From d871de3d2ffd6bf769faa8ed176004bf127db13f Mon Sep 17 00:00:00 2001 From: Yui5427 <785369607@qq.com> Date: Wed, 20 Aug 2025 16:43:25 +0800 Subject: [PATCH 3/6] Make code formatter satisfied --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index f8c59e58cbd1d..2967edea69099 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10001,12 +10001,14 @@ SDValue DAGCombiner::visitXOR(SDNode *N) { } } - // 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) { + // fold (not (sub Y, X)) -> (add X, ~Y) if Y is a constant or the subtract has + // a single use. + if (N0.getOpcode() == ISD::SUB && isAllOnesConstant(N1)) { SDValue Y = N0.getOperand(0); SDValue X = N0.getOperand(1); if (isa(Y) || N0.hasOneUse()) { - SDValue NotY = DAG.getNode(ISD::XOR, DL, VT, Y, DAG.getAllOnesConstant(DL, VT)); + SDValue NotY = + DAG.getNode(ISD::XOR, DL, VT, Y, DAG.getAllOnesConstant(DL, VT)); return DAG.getNode(ISD::ADD, DL, VT, X, NotY); } } From 67c2a68e6d1e6dc382d6ed8ec98faf9b0e1898bf Mon Sep 17 00:00:00 2001 From: Yui5427 <785369607@qq.com> Date: Thu, 21 Aug 2025 18:38:43 +0800 Subject: [PATCH 4/6] Prevent infinite loop --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 27 ++++++++++++++++--- llvm/test/CodeGen/X86/select_const.ll | 12 ++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 2967edea69099..40864135462d2 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10006,10 +10006,29 @@ SDValue DAGCombiner::visitXOR(SDNode *N) { if (N0.getOpcode() == ISD::SUB && isAllOnesConstant(N1)) { SDValue Y = N0.getOperand(0); SDValue X = N0.getOperand(1); - if (isa(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); + + // Avoid infinite recursion with + // Fold (and X, (add (not Y), Z)) -> (and X, (not (sub Y, Z))) + bool hasAndUsers = false; + for (SDUse &Use : N->uses()) { + SDNode *User = Use.getUser(); + if (User->getOpcode() == ISD::AND) { + hasAndUsers = true; + break; + } + } + if (!hasAndUsers) { + if (isa(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, N->getFlags()); + } + } else { + if (isa(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, N->getFlags()); + } } } diff --git a/llvm/test/CodeGen/X86/select_const.ll b/llvm/test/CodeGen/X86/select_const.ll index 35f4655dd6d7c..2b1c8d0564f0d 100644 --- a/llvm/test/CodeGen/X86/select_const.ll +++ b/llvm/test/CodeGen/X86/select_const.ll @@ -896,12 +896,12 @@ define i64 @opaque_constant(i1 %cond, i64 %x) { ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi ; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax -; X86-NEXT: movl %eax, %edx -; X86-NEXT: andl $1, %edx -; X86-NEXT: negl %edx -; X86-NEXT: andl $1, %edx -; X86-NEXT: decl %eax -; X86-NEXT: andl $1, %eax +; X86-NEXT: andl $1, %eax +; X86-NEXT: negl %eax +; X86-NEXT: movl %eax, %edx +; X86-NEXT: andl $1, %edx +; X86-NEXT: notl %eax +; X86-NEXT: andl $1, %eax ; X86-NEXT: xorl $1, %esi ; X86-NEXT: xorl $1, %ecx ; X86-NEXT: xorl %ebx, %ebx From 381c926d33d3cdcc7a49140caf449f5fce10a49d Mon Sep 17 00:00:00 2001 From: Yui5427 <785369607@qq.com> Date: Fri, 22 Aug 2025 12:53:09 +0800 Subject: [PATCH 5/6] Get rid of for --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 17 ++++------------- llvm/test/CodeGen/X86/select_const.ll | 12 ++++++------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 40864135462d2..d1fc2e8d1d802 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10009,24 +10009,15 @@ SDValue DAGCombiner::visitXOR(SDNode *N) { // Avoid infinite recursion with // Fold (and X, (add (not Y), Z)) -> (and X, (not (sub Y, Z))) - bool hasAndUsers = false; - for (SDUse &Use : N->uses()) { - SDNode *User = Use.getUser(); - if (User->getOpcode() == ISD::AND) { - hasAndUsers = true; - break; - } - } - if (!hasAndUsers) { + if (none_of(N->users(), + [](SDNode *User) { return User->getOpcode() == ISD::AND; })) { if (isa(Y) || N0.hasOneUse()) { - SDValue NotY = - DAG.getNode(ISD::XOR, DL, VT, Y, DAG.getAllOnesConstant(DL, VT)); + SDValue NotY = DAG.getNOT(DL, Y, VT); return DAG.getNode(ISD::ADD, DL, VT, X, NotY, N->getFlags()); } } else { if (isa(Y) && N0.hasOneUse()) { - SDValue NotY = - DAG.getNode(ISD::XOR, DL, VT, Y, DAG.getAllOnesConstant(DL, VT)); + SDValue NotY = DAG.getNOT(DL, Y, VT); return DAG.getNode(ISD::ADD, DL, VT, X, NotY, N->getFlags()); } } diff --git a/llvm/test/CodeGen/X86/select_const.ll b/llvm/test/CodeGen/X86/select_const.ll index 2b1c8d0564f0d..f57ed38101757 100644 --- a/llvm/test/CodeGen/X86/select_const.ll +++ b/llvm/test/CodeGen/X86/select_const.ll @@ -896,12 +896,12 @@ define i64 @opaque_constant(i1 %cond, i64 %x) { ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi ; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax -; X86-NEXT: andl $1, %eax -; X86-NEXT: negl %eax -; X86-NEXT: movl %eax, %edx -; X86-NEXT: andl $1, %edx -; X86-NEXT: notl %eax -; X86-NEXT: andl $1, %eax +; X86-NEXT: andl $1, %eax +; X86-NEXT: negl %eax +; X86-NEXT: movl %eax, %edx +; X86-NEXT: andl $1, %edx +; X86-NEXT: notl %eax +; X86-NEXT: andl $1, %eax ; X86-NEXT: xorl $1, %esi ; X86-NEXT: xorl $1, %ecx ; X86-NEXT: xorl %ebx, %ebx From f0e2a658f2dbee3bdb4b5a86deef29c74e617b6b Mon Sep 17 00:00:00 2001 From: Yui5427 <785369607@qq.com> Date: Thu, 4 Sep 2025 20:09:34 +0800 Subject: [PATCH 6/6] Remove infinite recursion checking --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 20 ++++---------- llvm/test/CodeGen/PowerPC/setcc-to-sub.ll | 10 +++---- .../test/CodeGen/PowerPC/testComparesigeuc.ll | 6 ++--- .../test/CodeGen/PowerPC/testComparesigeui.ll | 6 ++--- .../test/CodeGen/PowerPC/testComparesigeus.ll | 6 ++--- .../test/CodeGen/PowerPC/testComparesileuc.ll | 8 +++--- .../test/CodeGen/PowerPC/testComparesileui.ll | 8 +++--- .../test/CodeGen/PowerPC/testComparesileus.ll | 8 +++--- .../CodeGen/PowerPC/testComparesllgeuc.ll | 6 ++--- .../CodeGen/PowerPC/testComparesllgeui.ll | 6 ++--- .../CodeGen/PowerPC/testComparesllgeus.ll | 6 ++--- .../CodeGen/PowerPC/testComparesllleuc.ll | 8 +++--- .../CodeGen/PowerPC/testComparesllleui.ll | 8 +++--- .../CodeGen/PowerPC/testComparesllleus.ll | 8 +++--- llvm/test/CodeGen/X86/pr31045.ll | 8 +++--- llvm/test/CodeGen/X86/select_const.ll | 6 ++--- llvm/test/CodeGen/X86/shift-i128.ll | 21 +++++++-------- llvm/test/CodeGen/X86/xor-not-combine.ll | 27 +++++-------------- 18 files changed, 75 insertions(+), 101 deletions(-) diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index d1fc2e8d1d802..a7e55516c831e 100644 --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -10001,25 +10001,15 @@ SDValue DAGCombiner::visitXOR(SDNode *N) { } } - // fold (not (sub Y, X)) -> (add X, ~Y) if Y is a constant or the subtract has - // a single use. + // 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); - // Avoid infinite recursion with - // Fold (and X, (add (not Y), Z)) -> (and X, (not (sub Y, Z))) - if (none_of(N->users(), - [](SDNode *User) { return User->getOpcode() == ISD::AND; })) { - if (isa(Y) || N0.hasOneUse()) { - SDValue NotY = DAG.getNOT(DL, Y, VT); - return DAG.getNode(ISD::ADD, DL, VT, X, NotY, N->getFlags()); - } - } else { - if (isa(Y) && N0.hasOneUse()) { - SDValue NotY = DAG.getNOT(DL, Y, VT); - return DAG.getNode(ISD::ADD, DL, VT, X, NotY, N->getFlags()); - } + if (auto *YConst = dyn_cast(Y)) { + APInt NotYValue = ~YConst->getAPIntValue(); + SDValue NotY = DAG.getConstant(NotYValue, DL, VT); + return DAG.getNode(ISD::ADD, DL, VT, X, NotY, N->getFlags()); } } diff --git a/llvm/test/CodeGen/PowerPC/setcc-to-sub.ll b/llvm/test/CodeGen/PowerPC/setcc-to-sub.ll index d2ca198d8fcda..20dcb8ccf4908 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 4, 0(4) ; CHECK-NEXT: lwz 3, 0(3) -; CHECK-NEXT: rlwinm 4, 4, 0, 28, 28 +; CHECK-NEXT: lwz 4, 0(4) ; CHECK-NEXT: rlwinm 3, 3, 0, 28, 28 -; CHECK-NEXT: not 4, 4 -; CHECK-NEXT: add 3, 3, 4 +; CHECK-NEXT: rlwinm 4, 4, 0, 28, 28 +; CHECK-NEXT: sub 3, 4, 3 +; CHECK-NEXT: not 3, 3 ; 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 6839578d45644..37e589711f2db 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: not r3, r3 -; CHECK-NEXT: add r3, r4, r3 +; CHECK-NEXT: sub 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/testComparesigeui.ll b/llvm/test/CodeGen/PowerPC/testComparesigeui.ll index 2d28d2ff94641..fc951124cf2a3 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: not r3, r3 -; CHECK-NEXT: add r3, r4, r3 +; CHECK-NEXT: sub 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/testComparesigeus.ll b/llvm/test/CodeGen/PowerPC/testComparesigeus.ll index e78381d937544..522de14e4798a 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: not r3, r3 -; CHECK-NEXT: add r3, r4, r3 +; CHECK-NEXT: sub 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/testComparesileuc.ll b/llvm/test/CodeGen/PowerPC/testComparesileuc.ll index 17a332d647b91..1b6d1ae17c9b0 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 +; CHECK-NEXT: not r3, r3 ; 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 ; 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 e121bdfbbcc42..4c1efde742db9 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 +; CHECK-NEXT: not r3, r3 ; 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 ; 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 14e2a87a95292..31952081f3db9 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 +; CHECK-NEXT: not r3, r3 ; 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 ; 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 464b92e5c9169..14519472ad01d 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: not r3, r3 -; CHECK-NEXT: add r3, r4, r3 +; CHECK-NEXT: sub 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/testComparesllgeui.ll b/llvm/test/CodeGen/PowerPC/testComparesllgeui.ll index 31dde3c3f300e..6161109dbf923 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: not r3, r3 -; CHECK-NEXT: add r3, r4, r3 +; CHECK-NEXT: sub 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/testComparesllgeus.ll b/llvm/test/CodeGen/PowerPC/testComparesllgeus.ll index 0d46fb9c6bf69..a22def4beaf70 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: not r3, r3 -; CHECK-NEXT: add r3, r4, r3 +; CHECK-NEXT: sub 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/testComparesllleuc.ll b/llvm/test/CodeGen/PowerPC/testComparesllleuc.ll index a5d74ad1201db..cfaa6e8fe1d83 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 +; CHECK-NEXT: not r3, r3 ; 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 ; 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 1be2497b77193..e438797cde772 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 +; CHECK-NEXT: not r3, r3 ; 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 ; 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 e84e3fbb4707e..53b9b8a16d503 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 +; CHECK-NEXT: not r3, r3 ; 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: not r4, r4 -; CHECK-NEXT: add r3, r3, r4 +; CHECK-NEXT: sub r3, r4, r3 ; 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 a873fc6fd4959..4aa73d79d8cfc 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: addl %ecx, %edx -; CHECK-NEXT: notl %eax +; CHECK-NEXT: andl $1, %eax ; CHECK-NEXT: addl %eax, %eax -; CHECK-NEXT: orl $253, %eax -; CHECK-NEXT: addl %edx, %eax +; CHECK-NEXT: subl %ecx, %eax +; CHECK-NEXT: subl %edx, %eax +; CHECK-NEXT: notl %eax ; CHECK-NEXT: movzbl %al, %eax ; CHECK-NEXT: movw %ax, struct_obj_12+5(%rip) ; CHECK-NEXT: movb $0, var_163(%rip) diff --git a/llvm/test/CodeGen/X86/select_const.ll b/llvm/test/CodeGen/X86/select_const.ll index f57ed38101757..35f4655dd6d7c 100644 --- a/llvm/test/CodeGen/X86/select_const.ll +++ b/llvm/test/CodeGen/X86/select_const.ll @@ -896,11 +896,11 @@ define i64 @opaque_constant(i1 %cond, i64 %x) { ; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx ; X86-NEXT: movl {{[0-9]+}}(%esp), %esi ; X86-NEXT: movzbl {{[0-9]+}}(%esp), %eax -; X86-NEXT: andl $1, %eax -; X86-NEXT: negl %eax ; X86-NEXT: movl %eax, %edx ; X86-NEXT: andl $1, %edx -; X86-NEXT: notl %eax +; X86-NEXT: negl %edx +; X86-NEXT: andl $1, %edx +; X86-NEXT: decl %eax ; X86-NEXT: andl $1, %eax ; X86-NEXT: xorl $1, %esi ; X86-NEXT: xorl $1, %ecx 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 index 334328bc457bb..af65ade35ce8d 100644 --- a/llvm/test/CodeGen/X86/xor-not-combine.ll +++ b/llvm/test/CodeGen/X86/xor-not-combine.ll @@ -2,7 +2,7 @@ ; 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 or the subtract has a single use. +; 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) { @@ -15,30 +15,15 @@ define i32 @test_not_sub_constant(i32 %x) { ret i32 %not } -; Test case 2: Subtract has single use - should optimize -define i32 @test_not_sub_single_use(i32 %x, i32 %y) { -; CHECK-LABEL: test_not_sub_single_use: +; 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: notl %esi -; CHECK-NEXT: leal (%rsi,%rdi), %eax -; CHECK-NEXT: retq - %sub = sub i32 %y, %x - %not = xor i32 %sub, -1 - ret i32 %not -} - -; Negative test: Y is not constant AND subtract has multiple uses - should NOT optimize -define i32 @test_not_sub_multiple_uses_non_constant(i32 %x, i32 %y) { -; CHECK-LABEL: test_not_sub_multiple_uses_non_constant: -; CHECK: # %bb.0: -; CHECK: subl %edi, %esi ; CHECK-NEXT: movl %esi, %eax +; CHECK-NEXT: subl %edi, %eax ; CHECK-NEXT: notl %eax -; CHECK-NEXT: leal (%rax,%rsi,2), %eax ; CHECK-NEXT: retq %sub = sub i32 %y, %x %not = xor i32 %sub, -1 - %other_use = mul i32 %sub, 2 ; sub is used twice, and Y is not constant - %result = add i32 %not, %other_use - ret i32 %result + ret i32 %not }