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

via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 7 04:16:40 PDT 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Ricardo Jesus (rj-jesus)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/147279.diff


2 Files Affected:

- (modified) llvm/lib/Target/AArch64/AArch64InstrInfo.td (+13-1) 
- (modified) llvm/test/CodeGen/AArch64/eon.ll (+21) 


``````````diff
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 3468a0f63436e..8b31cbfe16b1a 100644
--- a/llvm/test/CodeGen/AArch64/eon.ll
+++ b/llvm/test/CodeGen/AArch64/eon.ll
@@ -30,3 +30,24 @@ 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: eon
+; 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
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/147279


More information about the llvm-commits mailing list