[llvm] [AArch64] Lower disjoint_or+not to eon. (PR #147279)

Ricardo Jesus via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 8 06:26:17 PDT 2025


https://github.com/rj-jesus updated https://github.com/llvm/llvm-project/pull/147279

>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/4] 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/4] [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

>From 7ee6fab8028adbd0d88b64f7ce296177be85ddd8 Mon Sep 17 00:00:00 2001
From: Ricardo Jesus <rjj at nvidia.com>
Date: Tue, 8 Jul 2025 05:06:09 -0700
Subject: [PATCH 3/4] Add xor_like.

---
 llvm/include/llvm/Target/TargetSelectionDAG.td     | 13 +++++++++++++
 llvm/lib/Target/AArch64/AArch64InstrInfo.td        | 14 +-------------
 .../TableGen/GlobalISelEmitter/CustomPredicate.td  |  1 +
 .../GlobalISelEmitter/GlobalISelEmitter.td         |  1 +
 4 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td
index 9ac228110eb9c..11f1a44302c5b 100644
--- a/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -1140,6 +1140,19 @@ def not  : PatFrag<(ops node:$in), (xor node:$in, -1)>;
 def vnot : PatFrag<(ops node:$in), (xor node:$in, immAllOnesV)>;
 def ineg : PatFrag<(ops node:$in), (sub 0, node:$in)>;
 
+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()));
+  }];
+}
+
+def xor_like : PatFrags<(ops node:$lhs, node:$rhs),
+                        [(xor node:$lhs, node:$rhs),
+                         (or_disjoint node:$lhs, node:$rhs)]>;
+
 def zanyext : PatFrags<(ops node:$op),
                        [(zext node:$op),
                         (anyext node:$op)]>;
diff --git a/llvm/lib/Target/AArch64/AArch64InstrInfo.td b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
index 9e289d3826cd0..b93a864db41d0 100644
--- a/llvm/lib/Target/AArch64/AArch64InstrInfo.td
+++ b/llvm/lib/Target/AArch64/AArch64InstrInfo.td
@@ -1254,16 +1254,6 @@ 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()));
-  }];
-}
-
 //===----------------------------------------------------------------------===//
 
 //===----------------------------------------------------------------------===//
@@ -3128,9 +3118,7 @@ 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",
-                       PatFrags<(ops node:$LHS, node:$RHS),
-                                [(not (xor node:$LHS, node:$RHS)),
-                                 (not (or_disjoint node:$LHS, node:$RHS))]>>;
+                       BinOpFrag<(not (xor_like 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/TableGen/GlobalISelEmitter/CustomPredicate.td b/llvm/test/TableGen/GlobalISelEmitter/CustomPredicate.td
index 56eaa4bdc57de..2dd9286e1cb1d 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/CustomPredicate.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/CustomPredicate.td
@@ -6,6 +6,7 @@
 // CHECK-NEXT: enum {
 // CHECK-NEXT:   GICXXPred_MI_Predicate_and_or_pat = GICXXPred_Invalid + 1,
 // CHECK-NEXT:   GICXXPred_MI_Predicate_mul_pat,
+// CHECK-NEXT:   GICXXPred_MI_Predicate_or_disjoint,
 // CHECK-NEXT:   GICXXPred_MI_Predicate_or_oneuse,
 // CHECK-NEXT:   GICXXPred_MI_Predicate_patfrags_test_pat,
 // CHECK-NEXT:   GICXXPred_MI_Predicate_sub3_pat,
diff --git a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
index 23e22b8b84183..6e5d7de0732f0 100644
--- a/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
+++ b/llvm/test/TableGen/GlobalISelEmitter/GlobalISelEmitter.td
@@ -156,6 +156,7 @@ def HasC : Predicate<"Subtarget->hasC()"> { let RecomputePerFunction = 1; }
 // CHECK-LABEL: // PatFrag predicates.
 // CHECK-NEXT:  enum {
 // CHECK-NEXT:   GICXXPred_MI_Predicate_frag = GICXXPred_Invalid + 1,
+// CHECK-NEXT:   GICXXPred_MI_Predicate_or_disjoint,
 // CHECK-NEXT:  };
 
 // CHECK-LABEL: // PatFrag predicates.

>From 81197a00b6020ffdbcb6dacec54c70c81aeb022d Mon Sep 17 00:00:00 2001
From: Ricardo Jesus <rjj at nvidia.com>
Date: Tue, 8 Jul 2025 06:21:17 -0700
Subject: [PATCH 4/4] Check flags directly.

---
 llvm/include/llvm/Target/TargetSelectionDAG.td | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Target/TargetSelectionDAG.td b/llvm/include/llvm/Target/TargetSelectionDAG.td
index 11f1a44302c5b..7ff8ca9ca559e 100644
--- a/llvm/include/llvm/Target/TargetSelectionDAG.td
+++ b/llvm/include/llvm/Target/TargetSelectionDAG.td
@@ -1145,7 +1145,7 @@ def or_disjoint : PatFrag<(ops node:$lhs, node:$rhs),
   return N->getFlags().hasDisjoint();
 }]> {
   let GISelPredicateCode = [{
-    return mi_match(MI, MRI, m_GDisjointOr(m_Reg(), m_Reg()));
+    return MI.getFlag(MachineInstr::Disjoint);
   }];
 }
 



More information about the llvm-commits mailing list