[llvm] [X86]: Reassoc demorgan rule for ANDN (PR #163789)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Oct 16 13:17:18 PDT 2025
https://github.com/kper updated https://github.com/llvm/llvm-project/pull/163789
>From ee35653e45cdfec53652118e9c93f0f12e597fbb Mon Sep 17 00:00:00 2001
From: Kevin Per <kevin.per at protonmail.com>
Date: Thu, 16 Oct 2025 13:53:37 +0000
Subject: [PATCH 1/6] [X86]: Reassoc demorgan rule for ANDN
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 28 ++++++
llvm/test/CodeGen/X86/bmi-reassoc-demorgan.ll | 98 +++++++++++++++++++
2 files changed, 126 insertions(+)
create mode 100644 llvm/test/CodeGen/X86/bmi-reassoc-demorgan.ll
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index a0b64ff370b10..e2632d114ce0b 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -51651,6 +51651,31 @@ static SDValue combineAndXorSubWithBMI(SDNode *And, const SDLoc &DL,
return AndN;
}
+// fold (not (or A, B)) -> nand(A, not(B)) if BMI
+static SDValue
+combineReassocDemorganWithNANDWithBMI(SDNode *Xor, const SDLoc &DL,
+ SelectionDAG &DAG,
+ const X86Subtarget &Subtarget) {
+ using namespace llvm::SDPatternMatch;
+
+ EVT VT = Xor->getValueType(0);
+ // Make sure this node is a candidate for BMI instructions.
+ if (!Subtarget.hasBMI() || (VT != MVT::i32 && VT != MVT::i64))
+ return SDValue();
+
+ SDValue A;
+ SDValue B;
+ APInt Cst;
+ if (!(sd_match(Xor, m_Xor(m_Or(m_Value(A), m_Value(B)), m_ConstInt(Cst))) &&
+ Cst.isAllOnes()))
+ return SDValue();
+
+ auto Opcode =
+ Subtarget.is64Bit() && VT == MVT::i64 ? X86::ANDN64rr : X86::ANDN32rr;
+ auto AndN = DAG.getMachineNode(Opcode, DL, VT, A, DAG.getNOT(DL, B, VT));
+ return SDValue(AndN, 0);
+}
+
static SDValue combineX86SubCmpForFlags(SDNode *N, SDValue Flag,
SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
@@ -55150,6 +55175,9 @@ static SDValue combineXor(SDNode *N, SelectionDAG &DAG,
if (SDValue R = combineBMILogicOp(N, DAG, Subtarget))
return R;
+ if (SDValue R = combineReassocDemorganWithNANDWithBMI(N, DL, DAG, Subtarget))
+ return R;
+
return combineFneg(N, DAG, DCI, Subtarget);
}
diff --git a/llvm/test/CodeGen/X86/bmi-reassoc-demorgan.ll b/llvm/test/CodeGen/X86/bmi-reassoc-demorgan.ll
new file mode 100644
index 0000000000000..ea81d08cd2e6d
--- /dev/null
+++ b/llvm/test/CodeGen/X86/bmi-reassoc-demorgan.ll
@@ -0,0 +1,98 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefix=X86
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefix=X64
+
+define i32 @reassoc_demorgan_i32(i32 %a, i32 %b) nounwind {
+; X86-LABEL: reassoc_demorgan_i32:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT: notl %ecx
+; X86-NEXT: andnl %ecx, %eax, %eax
+; X86-NEXT: retl
+;
+; X64-LABEL: reassoc_demorgan_i32:
+; X64: # %bb.0:
+; X64-NEXT: notl %edi
+; X64-NEXT: andnl %edi, %esi, %eax
+; X64-NEXT: retq
+ %temp = or i32 %b, %a
+ %res = xor i32 %temp, -1
+ ret i32 %res
+}
+
+define i32 @reassoc_demorgan_three_arguments_i32(i32 %a, i32 %b, i32 %c) nounwind {
+; X86-LABEL: reassoc_demorgan_three_arguments_i32:
+; X86: # %bb.0:
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT: orl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT: notl %eax
+; X86-NEXT: andnl %eax, %ecx, %eax
+; X86-NEXT: retl
+;
+; X64-LABEL: reassoc_demorgan_three_arguments_i32:
+; X64: # %bb.0:
+; X64-NEXT: orl %esi, %edi
+; X64-NEXT: notl %edx
+; X64-NEXT: andnl %edx, %edi, %eax
+; X64-NEXT: retq
+ %and.demorgan = or i32 %b, %a
+ %and3.demorgan = or i32 %and.demorgan, %c
+ %and3 = xor i32 %and3.demorgan, -1
+ ret i32 %and3
+}
+
+define i64 @reassoc_demorgan_i64(i64 %a, i64 %b) nounwind {
+; X86-LABEL: reassoc_demorgan_i64:
+; X86: # %bb.0:
+; X86-NEXT: pushl %esi
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT: movl {{[0-9]+}}(%esp), %esi
+; X86-NEXT: notl %edx
+; X86-NEXT: andnl %edx, %eax, %eax
+; X86-NEXT: notl %esi
+; X86-NEXT: andnl %esi, %ecx, %edx
+; X86-NEXT: popl %esi
+; X86-NEXT: retl
+;
+; X64-LABEL: reassoc_demorgan_i64:
+; X64: # %bb.0:
+; X64-NEXT: notq %rdi
+; X64-NEXT: andnq %rdi, %rsi, %rax
+; X64-NEXT: retq
+ %temp = or i64 %b, %a
+ %res = xor i64 %temp, -1
+ ret i64 %res
+}
+
+define i64 @reassoc_demorgan_three_arguments_i64(i64 %a, i64 %b, i64 %c) nounwind {
+; X86-LABEL: reassoc_demorgan_three_arguments_i64:
+; X86: # %bb.0:
+; X86-NEXT: pushl %esi
+; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
+; X86-NEXT: movl {{[0-9]+}}(%esp), %esi
+; X86-NEXT: orl {{[0-9]+}}(%esp), %esi
+; X86-NEXT: orl {{[0-9]+}}(%esp), %edx
+; X86-NEXT: notl %eax
+; X86-NEXT: andnl %eax, %edx, %eax
+; X86-NEXT: notl %ecx
+; X86-NEXT: andnl %ecx, %esi, %edx
+; X86-NEXT: popl %esi
+; X86-NEXT: retl
+;
+; X64-LABEL: reassoc_demorgan_three_arguments_i64:
+; X64: # %bb.0:
+; X64-NEXT: orq %rsi, %rdi
+; X64-NEXT: notq %rdx
+; X64-NEXT: andnq %rdx, %rdi, %rax
+; X64-NEXT: retq
+ %and.demorgan = or i64 %b, %a
+ %and3.demorgan = or i64 %and.demorgan, %c
+ %and3 = xor i64 %and3.demorgan, -1
+ ret i64 %and3
+}
>From deda3383ab0015a23d521f37d44a5714def2346c Mon Sep 17 00:00:00 2001
From: Kevin Per <kevin.per at protonmail.com>
Date: Thu, 16 Oct 2025 18:24:40 +0000
Subject: [PATCH 2/6] [X86]: Removed obsolete code
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 28 -------------------------
1 file changed, 28 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index e2632d114ce0b..a0b64ff370b10 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -51651,31 +51651,6 @@ static SDValue combineAndXorSubWithBMI(SDNode *And, const SDLoc &DL,
return AndN;
}
-// fold (not (or A, B)) -> nand(A, not(B)) if BMI
-static SDValue
-combineReassocDemorganWithNANDWithBMI(SDNode *Xor, const SDLoc &DL,
- SelectionDAG &DAG,
- const X86Subtarget &Subtarget) {
- using namespace llvm::SDPatternMatch;
-
- EVT VT = Xor->getValueType(0);
- // Make sure this node is a candidate for BMI instructions.
- if (!Subtarget.hasBMI() || (VT != MVT::i32 && VT != MVT::i64))
- return SDValue();
-
- SDValue A;
- SDValue B;
- APInt Cst;
- if (!(sd_match(Xor, m_Xor(m_Or(m_Value(A), m_Value(B)), m_ConstInt(Cst))) &&
- Cst.isAllOnes()))
- return SDValue();
-
- auto Opcode =
- Subtarget.is64Bit() && VT == MVT::i64 ? X86::ANDN64rr : X86::ANDN32rr;
- auto AndN = DAG.getMachineNode(Opcode, DL, VT, A, DAG.getNOT(DL, B, VT));
- return SDValue(AndN, 0);
-}
-
static SDValue combineX86SubCmpForFlags(SDNode *N, SDValue Flag,
SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
@@ -55175,9 +55150,6 @@ static SDValue combineXor(SDNode *N, SelectionDAG &DAG,
if (SDValue R = combineBMILogicOp(N, DAG, Subtarget))
return R;
- if (SDValue R = combineReassocDemorganWithNANDWithBMI(N, DL, DAG, Subtarget))
- return R;
-
return combineFneg(N, DAG, DCI, Subtarget);
}
>From cdb57ef348cbd3ac3bd6b361fd6a3b4ddb9ff8fb Mon Sep 17 00:00:00 2001
From: Kevin Per <kevin.per at protonmail.com>
Date: Thu, 16 Oct 2025 18:25:21 +0000
Subject: [PATCH 3/6] [DAG]: Reassoc demorgan rule for ANDN
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index c97300d64d455..0629b75989233 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -10197,6 +10197,22 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
}
}
+ // fold (not (or A, B)) -> and(not(A), not(B))
+ if (TLI.hasAndNot(SDValue(N, 0))) {
+ // If we have AndNot then it is profitable to apply demorgan to make use
+ // of the machine instruction.
+ SDValue A;
+ SDValue B;
+ APInt Cst;
+ if (sd_match(N, m_Xor(m_Or(m_Value(A), m_Value(B)), m_ConstInt(Cst))) &&
+ Cst.isAllOnes()) {
+ return DAG.getNode(
+ ISD::AND, DL, VT,
+ DAG.getNode(ISD::XOR, DL, VT, A, DAG.getConstant(-1, DL, VT)),
+ DAG.getNode(ISD::XOR, DL, VT, B, DAG.getConstant(-1, DL, VT)));
+ }
+ }
+
return SDValue();
}
>From 9e4103d5d49bbc92b1fdfad30e5e52f51f9c70e2 Mon Sep 17 00:00:00 2001
From: Kevin Per <kevin.per at protonmail.com>
Date: Thu, 16 Oct 2025 18:35:14 +0000
Subject: [PATCH 4/6] [DAG]: Fixed type
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 0629b75989233..5b77dc423b66b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -10206,10 +10206,11 @@ SDValue DAGCombiner::visitXOR(SDNode *N) {
APInt Cst;
if (sd_match(N, m_Xor(m_Or(m_Value(A), m_Value(B)), m_ConstInt(Cst))) &&
Cst.isAllOnes()) {
+ auto Ty = N->getValueType(0);
return DAG.getNode(
ISD::AND, DL, VT,
- DAG.getNode(ISD::XOR, DL, VT, A, DAG.getConstant(-1, DL, VT)),
- DAG.getNode(ISD::XOR, DL, VT, B, DAG.getConstant(-1, DL, VT)));
+ DAG.getNode(ISD::XOR, DL, VT, A, DAG.getConstant(Cst, DL, Ty)),
+ DAG.getNode(ISD::XOR, DL, VT, B, DAG.getConstant(Cst, DL, Ty)));
}
}
>From cf6ee582057a42e9ec8f5b81355c2bee8a8067cb Mon Sep 17 00:00:00 2001
From: Kevin Per <kevin.per at protonmail.com>
Date: Thu, 16 Oct 2025 18:45:46 +0000
Subject: [PATCH 5/6] [X86]: Updated tests
---
llvm/test/CodeGen/X86/bmi-reassoc-demorgan.ll | 210 ++++++++++++------
1 file changed, 143 insertions(+), 67 deletions(-)
diff --git a/llvm/test/CodeGen/X86/bmi-reassoc-demorgan.ll b/llvm/test/CodeGen/X86/bmi-reassoc-demorgan.ll
index ea81d08cd2e6d..7f3a376b24b2a 100644
--- a/llvm/test/CodeGen/X86/bmi-reassoc-demorgan.ll
+++ b/llvm/test/CodeGen/X86/bmi-reassoc-demorgan.ll
@@ -1,42 +1,75 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
-; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefix=X86
-; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefix=X64
+; RUN: llc < %s -mtriple=i686-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefix=X86-WITH-BMI
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown -mattr=+bmi | FileCheck %s --check-prefix=X64-WITH-BMI
+; RUN: llc < %s -mtriple=i686-unknown-unknown | FileCheck %s --check-prefix=X86-WITHOUT-BMI
+; RUN: llc < %s -mtriple=x86_64-unknown-unknown | FileCheck %s --check-prefix=X64-WITHOUT-BMI
define i32 @reassoc_demorgan_i32(i32 %a, i32 %b) nounwind {
-; X86-LABEL: reassoc_demorgan_i32:
-; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT: notl %ecx
-; X86-NEXT: andnl %ecx, %eax, %eax
-; X86-NEXT: retl
+; X86-WITH-BMI-LABEL: reassoc_demorgan_i32:
+; X86-WITH-BMI: # %bb.0:
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-WITH-BMI-NEXT: notl %ecx
+; X86-WITH-BMI-NEXT: andnl %ecx, %eax, %eax
+; X86-WITH-BMI-NEXT: retl
;
-; X64-LABEL: reassoc_demorgan_i32:
-; X64: # %bb.0:
-; X64-NEXT: notl %edi
-; X64-NEXT: andnl %edi, %esi, %eax
-; X64-NEXT: retq
+; X64-WITH-BMI-LABEL: reassoc_demorgan_i32:
+; X64-WITH-BMI: # %bb.0:
+; X64-WITH-BMI-NEXT: notl %edi
+; X64-WITH-BMI-NEXT: andnl %edi, %esi, %eax
+; X64-WITH-BMI-NEXT: retq
+;
+; X86-WITHOUT-BMI-LABEL: reassoc_demorgan_i32:
+; X86-WITHOUT-BMI: # %bb.0:
+; X86-WITHOUT-BMI-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-WITHOUT-BMI-NEXT: orl {{[0-9]+}}(%esp), %eax
+; X86-WITHOUT-BMI-NEXT: notl %eax
+; X86-WITHOUT-BMI-NEXT: retl
+;
+; X64-WITHOUT-BMI-LABEL: reassoc_demorgan_i32:
+; X64-WITHOUT-BMI: # %bb.0:
+; X64-WITHOUT-BMI-NEXT: movl %edi, %eax
+; X64-WITHOUT-BMI-NEXT: orl %esi, %eax
+; X64-WITHOUT-BMI-NEXT: notl %eax
+; X64-WITHOUT-BMI-NEXT: retq
%temp = or i32 %b, %a
%res = xor i32 %temp, -1
ret i32 %res
}
define i32 @reassoc_demorgan_three_arguments_i32(i32 %a, i32 %b, i32 %c) nounwind {
-; X86-LABEL: reassoc_demorgan_three_arguments_i32:
-; X86: # %bb.0:
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT: orl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT: notl %eax
-; X86-NEXT: andnl %eax, %ecx, %eax
-; X86-NEXT: retl
+; X86-WITH-BMI-LABEL: reassoc_demorgan_three_arguments_i32:
+; X86-WITH-BMI: # %bb.0:
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %edx
+; X86-WITH-BMI-NEXT: notl %edx
+; X86-WITH-BMI-NEXT: andnl %edx, %ecx, %ecx
+; X86-WITH-BMI-NEXT: andnl %ecx, %eax, %eax
+; X86-WITH-BMI-NEXT: retl
+;
+; X64-WITH-BMI-LABEL: reassoc_demorgan_three_arguments_i32:
+; X64-WITH-BMI: # %bb.0:
+; X64-WITH-BMI-NEXT: notl %edi
+; X64-WITH-BMI-NEXT: andnl %edi, %esi, %eax
+; X64-WITH-BMI-NEXT: andnl %eax, %edx, %eax
+; X64-WITH-BMI-NEXT: retq
+;
+; X86-WITHOUT-BMI-LABEL: reassoc_demorgan_three_arguments_i32:
+; X86-WITHOUT-BMI: # %bb.0:
+; X86-WITHOUT-BMI-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-WITHOUT-BMI-NEXT: orl {{[0-9]+}}(%esp), %eax
+; X86-WITHOUT-BMI-NEXT: orl {{[0-9]+}}(%esp), %eax
+; X86-WITHOUT-BMI-NEXT: notl %eax
+; X86-WITHOUT-BMI-NEXT: retl
;
-; X64-LABEL: reassoc_demorgan_three_arguments_i32:
-; X64: # %bb.0:
-; X64-NEXT: orl %esi, %edi
-; X64-NEXT: notl %edx
-; X64-NEXT: andnl %edx, %edi, %eax
-; X64-NEXT: retq
+; X64-WITHOUT-BMI-LABEL: reassoc_demorgan_three_arguments_i32:
+; X64-WITHOUT-BMI: # %bb.0:
+; X64-WITHOUT-BMI-NEXT: movl %edi, %eax
+; X64-WITHOUT-BMI-NEXT: orl %esi, %eax
+; X64-WITHOUT-BMI-NEXT: orl %edx, %eax
+; X64-WITHOUT-BMI-NEXT: notl %eax
+; X64-WITHOUT-BMI-NEXT: retq
%and.demorgan = or i32 %b, %a
%and3.demorgan = or i32 %and.demorgan, %c
%and3 = xor i32 %and3.demorgan, -1
@@ -44,53 +77,96 @@ define i32 @reassoc_demorgan_three_arguments_i32(i32 %a, i32 %b, i32 %c) nounwin
}
define i64 @reassoc_demorgan_i64(i64 %a, i64 %b) nounwind {
-; X86-LABEL: reassoc_demorgan_i64:
-; X86: # %bb.0:
-; X86-NEXT: pushl %esi
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT: movl {{[0-9]+}}(%esp), %esi
-; X86-NEXT: notl %edx
-; X86-NEXT: andnl %edx, %eax, %eax
-; X86-NEXT: notl %esi
-; X86-NEXT: andnl %esi, %ecx, %edx
-; X86-NEXT: popl %esi
-; X86-NEXT: retl
+; X86-WITH-BMI-LABEL: reassoc_demorgan_i64:
+; X86-WITH-BMI: # %bb.0:
+; X86-WITH-BMI-NEXT: pushl %esi
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %edx
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %esi
+; X86-WITH-BMI-NEXT: notl %edx
+; X86-WITH-BMI-NEXT: andnl %edx, %eax, %eax
+; X86-WITH-BMI-NEXT: notl %esi
+; X86-WITH-BMI-NEXT: andnl %esi, %ecx, %edx
+; X86-WITH-BMI-NEXT: popl %esi
+; X86-WITH-BMI-NEXT: retl
;
-; X64-LABEL: reassoc_demorgan_i64:
-; X64: # %bb.0:
-; X64-NEXT: notq %rdi
-; X64-NEXT: andnq %rdi, %rsi, %rax
-; X64-NEXT: retq
+; X64-WITH-BMI-LABEL: reassoc_demorgan_i64:
+; X64-WITH-BMI: # %bb.0:
+; X64-WITH-BMI-NEXT: notq %rdi
+; X64-WITH-BMI-NEXT: andnq %rdi, %rsi, %rax
+; X64-WITH-BMI-NEXT: retq
+;
+; X86-WITHOUT-BMI-LABEL: reassoc_demorgan_i64:
+; X86-WITHOUT-BMI: # %bb.0:
+; X86-WITHOUT-BMI-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-WITHOUT-BMI-NEXT: movl {{[0-9]+}}(%esp), %edx
+; X86-WITHOUT-BMI-NEXT: orl {{[0-9]+}}(%esp), %edx
+; X86-WITHOUT-BMI-NEXT: orl {{[0-9]+}}(%esp), %eax
+; X86-WITHOUT-BMI-NEXT: notl %eax
+; X86-WITHOUT-BMI-NEXT: notl %edx
+; X86-WITHOUT-BMI-NEXT: retl
+;
+; X64-WITHOUT-BMI-LABEL: reassoc_demorgan_i64:
+; X64-WITHOUT-BMI: # %bb.0:
+; X64-WITHOUT-BMI-NEXT: movq %rdi, %rax
+; X64-WITHOUT-BMI-NEXT: orq %rsi, %rax
+; X64-WITHOUT-BMI-NEXT: notq %rax
+; X64-WITHOUT-BMI-NEXT: retq
%temp = or i64 %b, %a
%res = xor i64 %temp, -1
ret i64 %res
}
define i64 @reassoc_demorgan_three_arguments_i64(i64 %a, i64 %b, i64 %c) nounwind {
-; X86-LABEL: reassoc_demorgan_three_arguments_i64:
-; X86: # %bb.0:
-; X86-NEXT: pushl %esi
-; X86-NEXT: movl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: movl {{[0-9]+}}(%esp), %ecx
-; X86-NEXT: movl {{[0-9]+}}(%esp), %edx
-; X86-NEXT: movl {{[0-9]+}}(%esp), %esi
-; X86-NEXT: orl {{[0-9]+}}(%esp), %esi
-; X86-NEXT: orl {{[0-9]+}}(%esp), %edx
-; X86-NEXT: notl %eax
-; X86-NEXT: andnl %eax, %edx, %eax
-; X86-NEXT: notl %ecx
-; X86-NEXT: andnl %ecx, %esi, %edx
-; X86-NEXT: popl %esi
-; X86-NEXT: retl
+; X86-WITH-BMI-LABEL: reassoc_demorgan_three_arguments_i64:
+; X86-WITH-BMI: # %bb.0:
+; X86-WITH-BMI-NEXT: pushl %ebx
+; X86-WITH-BMI-NEXT: pushl %edi
+; X86-WITH-BMI-NEXT: pushl %esi
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %ecx
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %edx
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %esi
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %edi
+; X86-WITH-BMI-NEXT: movl {{[0-9]+}}(%esp), %ebx
+; X86-WITH-BMI-NEXT: notl %edi
+; X86-WITH-BMI-NEXT: andnl %edi, %edx, %edx
+; X86-WITH-BMI-NEXT: andnl %edx, %eax, %eax
+; X86-WITH-BMI-NEXT: notl %ebx
+; X86-WITH-BMI-NEXT: andnl %ebx, %esi, %edx
+; X86-WITH-BMI-NEXT: andnl %edx, %ecx, %edx
+; X86-WITH-BMI-NEXT: popl %esi
+; X86-WITH-BMI-NEXT: popl %edi
+; X86-WITH-BMI-NEXT: popl %ebx
+; X86-WITH-BMI-NEXT: retl
+;
+; X64-WITH-BMI-LABEL: reassoc_demorgan_three_arguments_i64:
+; X64-WITH-BMI: # %bb.0:
+; X64-WITH-BMI-NEXT: notq %rdi
+; X64-WITH-BMI-NEXT: andnq %rdi, %rsi, %rax
+; X64-WITH-BMI-NEXT: andnq %rax, %rdx, %rax
+; X64-WITH-BMI-NEXT: retq
+;
+; X86-WITHOUT-BMI-LABEL: reassoc_demorgan_three_arguments_i64:
+; X86-WITHOUT-BMI: # %bb.0:
+; X86-WITHOUT-BMI-NEXT: movl {{[0-9]+}}(%esp), %eax
+; X86-WITHOUT-BMI-NEXT: movl {{[0-9]+}}(%esp), %edx
+; X86-WITHOUT-BMI-NEXT: orl {{[0-9]+}}(%esp), %eax
+; X86-WITHOUT-BMI-NEXT: orl {{[0-9]+}}(%esp), %edx
+; X86-WITHOUT-BMI-NEXT: orl {{[0-9]+}}(%esp), %edx
+; X86-WITHOUT-BMI-NEXT: orl {{[0-9]+}}(%esp), %eax
+; X86-WITHOUT-BMI-NEXT: notl %eax
+; X86-WITHOUT-BMI-NEXT: notl %edx
+; X86-WITHOUT-BMI-NEXT: retl
;
-; X64-LABEL: reassoc_demorgan_three_arguments_i64:
-; X64: # %bb.0:
-; X64-NEXT: orq %rsi, %rdi
-; X64-NEXT: notq %rdx
-; X64-NEXT: andnq %rdx, %rdi, %rax
-; X64-NEXT: retq
+; X64-WITHOUT-BMI-LABEL: reassoc_demorgan_three_arguments_i64:
+; X64-WITHOUT-BMI: # %bb.0:
+; X64-WITHOUT-BMI-NEXT: movq %rdi, %rax
+; X64-WITHOUT-BMI-NEXT: orq %rsi, %rax
+; X64-WITHOUT-BMI-NEXT: orq %rdx, %rax
+; X64-WITHOUT-BMI-NEXT: notq %rax
+; X64-WITHOUT-BMI-NEXT: retq
%and.demorgan = or i64 %b, %a
%and3.demorgan = or i64 %and.demorgan, %c
%and3 = xor i64 %and3.demorgan, -1
>From cef0067d84a41aad176352f02d9585dd71355a71 Mon Sep 17 00:00:00 2001
From: Kevin Per <kevin.per at protonmail.com>
Date: Thu, 16 Oct 2025 20:16:46 +0000
Subject: [PATCH 6/6] [DAG]: Updated tests
---
llvm/test/CodeGen/X86/andnot-patterns.ll | 184 ++++++++++++++---------
1 file changed, 116 insertions(+), 68 deletions(-)
diff --git a/llvm/test/CodeGen/X86/andnot-patterns.ll b/llvm/test/CodeGen/X86/andnot-patterns.ll
index fc573fbd4fc99..0701d7046fc35 100644
--- a/llvm/test/CodeGen/X86/andnot-patterns.ll
+++ b/llvm/test/CodeGen/X86/andnot-patterns.ll
@@ -761,6 +761,7 @@ define i64 @andnot_bitreverse_i64(i64 %a0, i64 %a1) nounwind {
;
; X86-BMI-LABEL: andnot_bitreverse_i64:
; X86-BMI: # %bb.0:
+; X86-BMI-NEXT: pushl %esi
; X86-BMI-NEXT: movl {{[0-9]+}}(%esp), %ecx
; X86-BMI-NEXT: movl {{[0-9]+}}(%esp), %eax
; X86-BMI-NEXT: bswapl %eax
@@ -774,13 +775,16 @@ define i64 @andnot_bitreverse_i64(i64 %a0, i64 %a1) nounwind {
; X86-BMI-NEXT: andl $858993459, %edx # imm = 0x33333333
; X86-BMI-NEXT: shrl $2, %eax
; X86-BMI-NEXT: andl $858993459, %eax # imm = 0x33333333
-; X86-BMI-NEXT: leal (%eax,%edx,4), %eax
-; X86-BMI-NEXT: movl %eax, %edx
-; X86-BMI-NEXT: andl $1431655765, %edx # imm = 0x55555555
+; X86-BMI-NEXT: leal (%eax,%edx,4), %esi
+; X86-BMI-NEXT: andl $1431655765, %esi # imm = 0x55555555
+; X86-BMI-NEXT: addl %esi, %esi
+; X86-BMI-NEXT: shll $2, %edx
+; X86-BMI-NEXT: notl %edx
+; X86-BMI-NEXT: andnl %edx, %eax, %eax
; X86-BMI-NEXT: shrl %eax
-; X86-BMI-NEXT: andl $1431655765, %eax # imm = 0x55555555
-; X86-BMI-NEXT: leal (%eax,%edx,2), %eax
-; X86-BMI-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax
+; X86-BMI-NEXT: orl $-1431655766, %eax # imm = 0xAAAAAAAA
+; X86-BMI-NEXT: andnl %eax, %esi, %eax
+; X86-BMI-NEXT: andl {{[0-9]+}}(%esp), %eax
; X86-BMI-NEXT: bswapl %ecx
; X86-BMI-NEXT: movl %ecx, %edx
; X86-BMI-NEXT: andl $252645135, %edx # imm = 0xF0F0F0F
@@ -792,13 +796,17 @@ define i64 @andnot_bitreverse_i64(i64 %a0, i64 %a1) nounwind {
; X86-BMI-NEXT: andl $858993459, %edx # imm = 0x33333333
; X86-BMI-NEXT: shrl $2, %ecx
; X86-BMI-NEXT: andl $858993459, %ecx # imm = 0x33333333
-; X86-BMI-NEXT: leal (%ecx,%edx,4), %ecx
-; X86-BMI-NEXT: movl %ecx, %edx
-; X86-BMI-NEXT: andl $1431655765, %edx # imm = 0x55555555
+; X86-BMI-NEXT: leal (%ecx,%edx,4), %esi
+; X86-BMI-NEXT: andl $1431655765, %esi # imm = 0x55555555
+; X86-BMI-NEXT: addl %esi, %esi
+; X86-BMI-NEXT: shll $2, %edx
+; X86-BMI-NEXT: notl %edx
+; X86-BMI-NEXT: andnl %edx, %ecx, %ecx
; X86-BMI-NEXT: shrl %ecx
-; X86-BMI-NEXT: andl $1431655765, %ecx # imm = 0x55555555
-; X86-BMI-NEXT: leal (%ecx,%edx,2), %ecx
-; X86-BMI-NEXT: andnl {{[0-9]+}}(%esp), %ecx, %edx
+; X86-BMI-NEXT: orl $-1431655766, %ecx # imm = 0xAAAAAAAA
+; X86-BMI-NEXT: andnl %ecx, %esi, %edx
+; X86-BMI-NEXT: andl {{[0-9]+}}(%esp), %edx
+; X86-BMI-NEXT: popl %esi
; X86-BMI-NEXT: retl
;
; X64-NOBMI-LABEL: andnot_bitreverse_i64:
@@ -837,19 +845,23 @@ define i64 @andnot_bitreverse_i64(i64 %a0, i64 %a1) nounwind {
; X64-BMI-NEXT: andq %rcx, %rsi
; X64-BMI-NEXT: shlq $4, %rsi
; X64-BMI-NEXT: orq %rax, %rsi
-; X64-BMI-NEXT: movabsq $3689348814741910323, %rax # imm = 0x3333333333333333
-; X64-BMI-NEXT: movq %rsi, %rcx
-; X64-BMI-NEXT: andq %rax, %rcx
-; X64-BMI-NEXT: shrq $2, %rsi
-; X64-BMI-NEXT: andq %rax, %rsi
-; X64-BMI-NEXT: leaq (%rsi,%rcx,4), %rax
-; X64-BMI-NEXT: movabsq $6148914691236517205, %rcx # imm = 0x5555555555555555
-; X64-BMI-NEXT: movq %rax, %rdx
-; X64-BMI-NEXT: andq %rcx, %rdx
-; X64-BMI-NEXT: shrq %rax
+; X64-BMI-NEXT: movq %rsi, %rax
+; X64-BMI-NEXT: shrq $2, %rax
+; X64-BMI-NEXT: movabsq $3689348814741910323, %rcx # imm = 0x3333333333333333
; X64-BMI-NEXT: andq %rcx, %rax
-; X64-BMI-NEXT: leaq (%rax,%rdx,2), %rax
-; X64-BMI-NEXT: andnq %rdi, %rax, %rax
+; X64-BMI-NEXT: andq %rcx, %rsi
+; X64-BMI-NEXT: leaq (,%rsi,4), %rcx
+; X64-BMI-NEXT: notq %rcx
+; X64-BMI-NEXT: andnq %rcx, %rax, %rcx
+; X64-BMI-NEXT: shrq %rcx
+; X64-BMI-NEXT: movabsq $-6148914691236517206, %rdx # imm = 0xAAAAAAAAAAAAAAAA
+; X64-BMI-NEXT: orq %rcx, %rdx
+; X64-BMI-NEXT: leaq (%rax,%rsi,4), %rax
+; X64-BMI-NEXT: movabsq $6148914691236517205, %rcx # imm = 0x5555555555555555
+; X64-BMI-NEXT: andq %rax, %rcx
+; X64-BMI-NEXT: addq %rcx, %rcx
+; X64-BMI-NEXT: andnq %rdx, %rcx, %rax
+; X64-BMI-NEXT: andq %rdi, %rax
; X64-BMI-NEXT: retq
%not = xor i64 %a1, -1
%bitrev = tail call i64 @llvm.bitreverse.i64(i64 %not)
@@ -896,13 +908,16 @@ define i32 @andnot_bitreverse_i32(i32 %a0, i32 %a1) nounwind {
; X86-BMI-NEXT: andl $858993459, %ecx # imm = 0x33333333
; X86-BMI-NEXT: shrl $2, %eax
; X86-BMI-NEXT: andl $858993459, %eax # imm = 0x33333333
-; X86-BMI-NEXT: leal (%eax,%ecx,4), %eax
-; X86-BMI-NEXT: movl %eax, %ecx
-; X86-BMI-NEXT: andl $1431655765, %ecx # imm = 0x55555555
+; X86-BMI-NEXT: leal (%eax,%ecx,4), %edx
+; X86-BMI-NEXT: andl $1431655765, %edx # imm = 0x55555555
+; X86-BMI-NEXT: addl %edx, %edx
+; X86-BMI-NEXT: shll $2, %ecx
+; X86-BMI-NEXT: notl %ecx
+; X86-BMI-NEXT: andnl %ecx, %eax, %eax
; X86-BMI-NEXT: shrl %eax
-; X86-BMI-NEXT: andl $1431655765, %eax # imm = 0x55555555
-; X86-BMI-NEXT: leal (%eax,%ecx,2), %eax
-; X86-BMI-NEXT: andnl {{[0-9]+}}(%esp), %eax, %eax
+; X86-BMI-NEXT: orl $-1431655766, %eax # imm = 0xAAAAAAAA
+; X86-BMI-NEXT: andnl %eax, %edx, %eax
+; X86-BMI-NEXT: andl {{[0-9]+}}(%esp), %eax
; X86-BMI-NEXT: retl
;
; X64-NOBMI-LABEL: andnot_bitreverse_i32:
@@ -940,16 +955,19 @@ define i32 @andnot_bitreverse_i32(i32 %a0, i32 %a1) nounwind {
; X64-BMI-NEXT: andl $252645135, %esi # imm = 0xF0F0F0F
; X64-BMI-NEXT: orl %eax, %esi
; X64-BMI-NEXT: movl %esi, %eax
+; X64-BMI-NEXT: shrl $2, %eax
; X64-BMI-NEXT: andl $858993459, %eax # imm = 0x33333333
-; X64-BMI-NEXT: shrl $2, %esi
; X64-BMI-NEXT: andl $858993459, %esi # imm = 0x33333333
-; X64-BMI-NEXT: leal (%rsi,%rax,4), %eax
-; X64-BMI-NEXT: movl %eax, %ecx
-; X64-BMI-NEXT: andl $1431655765, %ecx # imm = 0x55555555
-; X64-BMI-NEXT: shrl %eax
+; X64-BMI-NEXT: leal (,%rsi,4), %ecx
+; X64-BMI-NEXT: notl %ecx
+; X64-BMI-NEXT: andnl %ecx, %eax, %ecx
+; X64-BMI-NEXT: shrl %ecx
+; X64-BMI-NEXT: orl $-1431655766, %ecx # imm = 0xAAAAAAAA
+; X64-BMI-NEXT: leal (%rax,%rsi,4), %eax
; X64-BMI-NEXT: andl $1431655765, %eax # imm = 0x55555555
-; X64-BMI-NEXT: leal (%rax,%rcx,2), %eax
-; X64-BMI-NEXT: andnl %edi, %eax, %eax
+; X64-BMI-NEXT: addl %eax, %eax
+; X64-BMI-NEXT: andnl %ecx, %eax, %eax
+; X64-BMI-NEXT: andl %edi, %eax
; X64-BMI-NEXT: retq
%not = xor i32 %a1, -1
%bitrev = tail call i32 @llvm.bitreverse.i32(i32 %not)
@@ -958,30 +976,57 @@ define i32 @andnot_bitreverse_i32(i32 %a0, i32 %a1) nounwind {
}
define i16 @andnot_bitreverse_i16(i16 %a0, i16 %a1) nounwind {
-; X86-LABEL: andnot_bitreverse_i16:
-; X86: # %bb.0:
-; X86-NEXT: movzwl {{[0-9]+}}(%esp), %eax
-; X86-NEXT: rolw $8, %ax
-; X86-NEXT: movl %eax, %ecx
-; X86-NEXT: andl $3855, %ecx # imm = 0xF0F
-; X86-NEXT: shll $4, %ecx
-; X86-NEXT: shrl $4, %eax
-; X86-NEXT: andl $3855, %eax # imm = 0xF0F
-; X86-NEXT: orl %ecx, %eax
-; X86-NEXT: movl %eax, %ecx
-; X86-NEXT: andl $13107, %ecx # imm = 0x3333
-; X86-NEXT: shrl $2, %eax
-; X86-NEXT: andl $13107, %eax # imm = 0x3333
-; X86-NEXT: leal (%eax,%ecx,4), %eax
-; X86-NEXT: movl %eax, %ecx
-; X86-NEXT: andl $21845, %ecx # imm = 0x5555
-; X86-NEXT: shrl %eax
-; X86-NEXT: andl $21845, %eax # imm = 0x5555
-; X86-NEXT: leal (%eax,%ecx,2), %eax
-; X86-NEXT: notl %eax
-; X86-NEXT: andw {{[0-9]+}}(%esp), %ax
-; X86-NEXT: # kill: def $ax killed $ax killed $eax
-; X86-NEXT: retl
+; X86-NOBMI-LABEL: andnot_bitreverse_i16:
+; X86-NOBMI: # %bb.0:
+; X86-NOBMI-NEXT: movzwl {{[0-9]+}}(%esp), %eax
+; X86-NOBMI-NEXT: rolw $8, %ax
+; X86-NOBMI-NEXT: movl %eax, %ecx
+; X86-NOBMI-NEXT: andl $3855, %ecx # imm = 0xF0F
+; X86-NOBMI-NEXT: shll $4, %ecx
+; X86-NOBMI-NEXT: shrl $4, %eax
+; X86-NOBMI-NEXT: andl $3855, %eax # imm = 0xF0F
+; X86-NOBMI-NEXT: orl %ecx, %eax
+; X86-NOBMI-NEXT: movl %eax, %ecx
+; X86-NOBMI-NEXT: andl $13107, %ecx # imm = 0x3333
+; X86-NOBMI-NEXT: shrl $2, %eax
+; X86-NOBMI-NEXT: andl $13107, %eax # imm = 0x3333
+; X86-NOBMI-NEXT: leal (%eax,%ecx,4), %eax
+; X86-NOBMI-NEXT: movl %eax, %ecx
+; X86-NOBMI-NEXT: andl $21845, %ecx # imm = 0x5555
+; X86-NOBMI-NEXT: shrl %eax
+; X86-NOBMI-NEXT: andl $21845, %eax # imm = 0x5555
+; X86-NOBMI-NEXT: leal (%eax,%ecx,2), %eax
+; X86-NOBMI-NEXT: notl %eax
+; X86-NOBMI-NEXT: andw {{[0-9]+}}(%esp), %ax
+; X86-NOBMI-NEXT: # kill: def $ax killed $ax killed $eax
+; X86-NOBMI-NEXT: retl
+;
+; X86-BMI-LABEL: andnot_bitreverse_i16:
+; X86-BMI: # %bb.0:
+; X86-BMI-NEXT: movzwl {{[0-9]+}}(%esp), %eax
+; X86-BMI-NEXT: rolw $8, %ax
+; X86-BMI-NEXT: movl %eax, %ecx
+; X86-BMI-NEXT: andl $3855, %ecx # imm = 0xF0F
+; X86-BMI-NEXT: shll $4, %ecx
+; X86-BMI-NEXT: shrl $4, %eax
+; X86-BMI-NEXT: andl $3855, %eax # imm = 0xF0F
+; X86-BMI-NEXT: orl %ecx, %eax
+; X86-BMI-NEXT: movl %eax, %ecx
+; X86-BMI-NEXT: andl $13107, %ecx # imm = 0x3333
+; X86-BMI-NEXT: shrl $2, %eax
+; X86-BMI-NEXT: andl $13107, %eax # imm = 0x3333
+; X86-BMI-NEXT: leal (%eax,%ecx,4), %edx
+; X86-BMI-NEXT: andl $21845, %edx # imm = 0x5555
+; X86-BMI-NEXT: addl %edx, %edx
+; X86-BMI-NEXT: shll $2, %ecx
+; X86-BMI-NEXT: notl %ecx
+; X86-BMI-NEXT: andnl %ecx, %eax, %eax
+; X86-BMI-NEXT: shrl %eax
+; X86-BMI-NEXT: orl $43690, %eax # imm = 0xAAAA
+; X86-BMI-NEXT: andnl %eax, %edx, %eax
+; X86-BMI-NEXT: andw {{[0-9]+}}(%esp), %ax
+; X86-BMI-NEXT: # kill: def $ax killed $ax killed $eax
+; X86-BMI-NEXT: retl
;
; X64-NOBMI-LABEL: andnot_bitreverse_i16:
; X64-NOBMI: # %bb.0:
@@ -1019,16 +1064,19 @@ define i16 @andnot_bitreverse_i16(i16 %a0, i16 %a1) nounwind {
; X64-BMI-NEXT: andl $3855, %esi # imm = 0xF0F
; X64-BMI-NEXT: orl %eax, %esi
; X64-BMI-NEXT: movl %esi, %eax
+; X64-BMI-NEXT: shrl $2, %eax
; X64-BMI-NEXT: andl $13107, %eax # imm = 0x3333
-; X64-BMI-NEXT: shrl $2, %esi
; X64-BMI-NEXT: andl $13107, %esi # imm = 0x3333
-; X64-BMI-NEXT: leal (%rsi,%rax,4), %eax
-; X64-BMI-NEXT: movl %eax, %ecx
-; X64-BMI-NEXT: andl $21845, %ecx # imm = 0x5555
-; X64-BMI-NEXT: shrl %eax
+; X64-BMI-NEXT: leal (,%rsi,4), %ecx
+; X64-BMI-NEXT: notl %ecx
+; X64-BMI-NEXT: andnl %ecx, %eax, %ecx
+; X64-BMI-NEXT: shrl %ecx
+; X64-BMI-NEXT: orl $-21846, %ecx # imm = 0xAAAA
+; X64-BMI-NEXT: leal (%rax,%rsi,4), %eax
; X64-BMI-NEXT: andl $21845, %eax # imm = 0x5555
-; X64-BMI-NEXT: leal (%rax,%rcx,2), %eax
-; X64-BMI-NEXT: andnl %edi, %eax, %eax
+; X64-BMI-NEXT: addl %eax, %eax
+; X64-BMI-NEXT: andnl %ecx, %eax, %eax
+; X64-BMI-NEXT: andl %edi, %eax
; X64-BMI-NEXT: # kill: def $ax killed $ax killed $eax
; X64-BMI-NEXT: retq
%not = xor i16 %a1, -1
More information about the llvm-commits
mailing list