[llvm] [AArch64] Lower disjoint_or+not to eon. (PR #147279)
Ricardo Jesus via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 7 04:16:07 PDT 2025
https://github.com/rj-jesus created https://github.com/llvm/llvm-project/pull/147279
A disjoint OR can be transformed to an EOR.
We already lower EOR+NOT to EON, but not DisjointOR+NOT.
This shows up in scalar NBSL patterns: https://godbolt.org/z/154s8vMMG
https://godbolt.org/z/Efz7jKd6P
>From eeeb91b0a1625dfa856e6f19a0cdbc83d05c2fbc Mon Sep 17 00:00:00 2001
From: Ricardo Jesus <rjj at nvidia.com>
Date: Fri, 4 Jul 2025 01:04:43 -0700
Subject: [PATCH 1/2] Add test.
---
llvm/test/CodeGen/AArch64/eon.ll | 22 ++++++++++++++++++++++
1 file changed, 22 insertions(+)
diff --git a/llvm/test/CodeGen/AArch64/eon.ll b/llvm/test/CodeGen/AArch64/eon.ll
index 3468a0f63436e..666fb48e9e491 100644
--- a/llvm/test/CodeGen/AArch64/eon.ll
+++ b/llvm/test/CodeGen/AArch64/eon.ll
@@ -30,3 +30,25 @@ entry:
%shl2 = shl i64 %xor, %xor1
ret i64 %shl2
}
+
+; Check that eon is generated if the xor is a disjoint or.
+define i64 @disjoint_or(i64 %a, i64 %b) {
+; CHECK-LABEL: disjoint_or:
+; CHECK: orr
+; CHECK: mvn
+; CHECK: ret
+ %or = or disjoint i64 %a, %b
+ %eon = xor i64 %or, -1
+ ret i64 %eon
+}
+
+; Check that eon is *not* generated if the or is not disjoint.
+define i64 @normal_or(i64 %a, i64 %b) {
+; CHECK-LABEL: normal_or:
+; CHECK: orr
+; CHECK: mvn
+; CHECK: ret
+ %or = or i64 %a, %b
+ %not = xor i64 %or, -1
+ ret i64 %not
+}
>From 9d6c30c5d036c753083b1ba13f7c194ad941d85b Mon Sep 17 00:00:00 2001
From: Ricardo Jesus <rjj at nvidia.com>
Date: Fri, 4 Jul 2025 01:05:12 -0700
Subject: [PATCH 2/2] [AArch64] Lower disjoint_or+not to eon.
---
llvm/lib/Target/AArch64/AArch64InstrInfo.td | 14 +++++++++++++-
llvm/test/CodeGen/AArch64/eon.ll | 3 +--
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 0cb7b02d84a6e..9e289d3826cd0 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1254,6 +1254,16 @@ def fminnum_nnan : PatFrag<(ops node:$Rn, node:$Rm),
return N->getFlags().hasNoNaNs();
}]>;
+// Match disjoint or nodes.
+def or_disjoint : PatFrag<(ops node:$lhs, node:$rhs),
+ (or node:$lhs, node:$rhs), [{
+ return N->getFlags().hasDisjoint();
+}]> {
+ let GISelPredicateCode = [{
+ return mi_match(MI, MRI, m_GDisjointOr(m_Reg(), m_Reg()));
+ }];
+}
+
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
@@ -3118,7 +3128,9 @@ defm AND : LogicalReg<0b00, 0, "and", and>;
defm BIC : LogicalReg<0b00, 1, "bic",
BinOpFrag<(and node:$LHS, (not node:$RHS))>, 3>;
defm EON : LogicalReg<0b10, 1, "eon",
- BinOpFrag<(not (xor node:$LHS, node:$RHS))>>;
+ PatFrags<(ops node:$LHS, node:$RHS),
+ [(not (xor node:$LHS, node:$RHS)),
+ (not (or_disjoint node:$LHS, node:$RHS))]>>;
defm EOR : LogicalReg<0b10, 0, "eor", xor>;
defm ORN : LogicalReg<0b01, 1, "orn",
BinOpFrag<(or node:$LHS, (not node:$RHS))>>;
diff --git a/llvm/test/CodeGen/AArch64/eon.ll b/llvm/test/CodeGen/AArch64/eon.ll
index 666fb48e9e491..8b31cbfe16b1a 100644
--- a/llvm/test/CodeGen/AArch64/eon.ll
+++ b/llvm/test/CodeGen/AArch64/eon.ll
@@ -34,8 +34,7 @@ entry:
; Check that eon is generated if the xor is a disjoint or.
define i64 @disjoint_or(i64 %a, i64 %b) {
; CHECK-LABEL: disjoint_or:
-; CHECK: orr
-; CHECK: mvn
+; CHECK: eon
; CHECK: ret
%or = or disjoint i64 %a, %b
%eon = xor i64 %or, -1
More information about the llvm-commits
mailing list