-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[AArch64] Lower disjoint_or+not to eon. #147279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-llvm-selectiondag @llvm/pr-subscribers-backend-aarch64 Author: Ricardo Jesus (rj-jesus) ChangesA 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:
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
+}
|
|
question: does ORN not exist on AArch64? was curious as to why the non-disjoint ors don't fold to that |
ORN does exit, but it doesn't implement |
david-arm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
|
(x | y) + (x & y) = x + y Disjoint or is an or where (x & y) is 0, so I wonder if there's anything else we can use these properties for to optimize |
|
Me when I discover the concept of adders in CPUs |
|
I'm going to copy this to RISCV too. Thanks! |
I am also doing to copy this for selectiondag |
A disjoint OR can be converted to XOR. And a XOR+NOT is XNOR. Idea taken from #147279. I changed the existing xnor pattern to have the not on the outside instead of the inside. These are equivalent for xor since xor is associative. Tablegen was already generating multiple variants of the isel pattern using associativity. There are some issues here. The disjoint flag isn't preserved through type legalization. I was hoping we could recover it manually for the masked merge cases, but that doesn't work either.
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