[llvm] [AArch64] Handle XAR with v1i64 operand types (PR #141754)
David Green via llvm-commits
llvm-commits at lists.llvm.org
Thu May 29 02:01:27 PDT 2025
https://github.com/davemgreen updated https://github.com/llvm/llvm-project/pull/141754
>From 943db8faf60e0978c3a0ee53939ab4154461ff29 Mon Sep 17 00:00:00 2001
From: David Green <david.green at arm.com>
Date: Wed, 28 May 2025 13:41:20 +0100
Subject: [PATCH 1/2] [AArch64] Handle XAR with v1i64 operand types
When converting ROTR(XOR(a, b)) to XAR(a, b), or ROTR(a, a) to XAR(a, zero) we
were not handling v1i64 types, meaning illegal copies get generated. This
addresses that by generating insert_subreg and extract_subreg for v1i64 types
to keep the values with the correct types.
Fixes #141746
---
.../Target/AArch64/AArch64ISelDAGToDAG.cpp | 28 ++++++++++++-
llvm/test/CodeGen/AArch64/xar.ll | 39 +++++++++++++++++++
2 files changed, 65 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 2eb8c6008db0f..0b7a810fd4747 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -4637,15 +4637,39 @@ bool AArch64DAGToDAGISel::trySelectXAR(SDNode *N) {
if (!IsXOROperand) {
SDValue Zero = CurDAG->getTargetConstant(0, DL, MVT::i64);
- SDNode *MOV = CurDAG->getMachineNode(AArch64::MOVIv2d_ns, DL, VT, Zero);
+ SDNode *MOV =
+ CurDAG->getMachineNode(AArch64::MOVIv2d_ns, DL, MVT::v2i64, Zero);
SDValue MOVIV = SDValue(MOV, 0);
R1 = N1->getOperand(0);
R2 = MOVIV;
}
+ // If the input is a v1i64, widen to a v2i64 to use XAR.
+ assert((VT == MVT::v1i64 || VT == MVT::v2i64) && "Unexpected XAR type!");
+ if (VT == MVT::v1i64) {
+ EVT SVT = MVT::v2i64;
+ SDValue Undef =
+ SDValue(CurDAG->getMachineNode(AArch64::IMPLICIT_DEF, DL, SVT), 0);
+ SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub, DL, MVT::i32);
+ R1 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG, DL, SVT, Undef,
+ R1, DSub),
+ 0);
+ if (R2.getValueType() == MVT::v1i64)
+ R2 = SDValue(CurDAG->getMachineNode(AArch64::INSERT_SUBREG, DL, SVT,
+ Undef, R2, DSub),
+ 0);
+ }
+
SDValue Ops[] = {R1, R2, Imm};
- CurDAG->SelectNodeTo(N, AArch64::XAR, N0.getValueType(), Ops);
+ SDNode *XAR =
+ CurDAG->getMachineNode(AArch64::XAR, DL, R1.getValueType(), Ops);
+ if (VT == MVT::v1i64) {
+ SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub, DL, MVT::i32);
+ XAR = CurDAG->getMachineNode(AArch64::EXTRACT_SUBREG, DL, VT,
+ SDValue(XAR, 0), DSub);
+ }
+ ReplaceNode(N, XAR);
return true;
}
diff --git a/llvm/test/CodeGen/AArch64/xar.ll b/llvm/test/CodeGen/AArch64/xar.ll
index e15cb6a696aa5..d682f4f4a1bfb 100644
--- a/llvm/test/CodeGen/AArch64/xar.ll
+++ b/llvm/test/CodeGen/AArch64/xar.ll
@@ -19,6 +19,26 @@ define <2 x i64> @xar(<2 x i64> %x, <2 x i64> %y) {
ret <2 x i64> %b
}
+define <1 x i64> @xar_v1i64(<1 x i64> %a, <1 x i64> %b) {
+; SHA3-LABEL: xar_v1i64:
+; SHA3: // %bb.0:
+; SHA3-NEXT: // kill: def $d0 killed $d0 def $q0
+; SHA3-NEXT: // kill: def $d1 killed $d1 def $q1
+; SHA3-NEXT: xar v0.2d, v0.2d, v1.2d, #63
+; SHA3-NEXT: // kill: def $d0 killed $d0 killed $q0
+; SHA3-NEXT: ret
+;
+; NOSHA3-LABEL: xar_v1i64:
+; NOSHA3: // %bb.0:
+; NOSHA3-NEXT: eor v1.8b, v0.8b, v1.8b
+; NOSHA3-NEXT: shl d0, d1, #1
+; NOSHA3-NEXT: usra d0, d1, #63
+; NOSHA3-NEXT: ret
+ %v.val = xor <1 x i64> %a, %b
+ %fshl = tail call <1 x i64> @llvm.fshl.v1i64(<1 x i64> %v.val, <1 x i64> %v.val, <1 x i64> splat (i64 1))
+ ret <1 x i64> %fshl
+}
+
define <2 x i64> @xar_instead_of_or1(<2 x i64> %r) {
; SHA3-LABEL: xar_instead_of_or1:
; SHA3: // %bb.0: // %entry
@@ -37,6 +57,25 @@ entry:
ret <2 x i64> %or
}
+define <1 x i64> @xar_instead_of_or_v1i64(<1 x i64> %v.val) {
+; SHA3-LABEL: xar_instead_of_or_v1i64:
+; SHA3: // %bb.0:
+; SHA3-NEXT: movi v1.2d, #0000000000000000
+; SHA3-NEXT: // kill: def $d0 killed $d0 def $q0
+; SHA3-NEXT: xar v0.2d, v0.2d, v1.2d, #63
+; SHA3-NEXT: // kill: def $d0 killed $d0 killed $q0
+; SHA3-NEXT: ret
+;
+; NOSHA3-LABEL: xar_instead_of_or_v1i64:
+; NOSHA3: // %bb.0:
+; NOSHA3-NEXT: shl d1, d0, #1
+; NOSHA3-NEXT: usra d1, d0, #63
+; NOSHA3-NEXT: fmov d0, d1
+; NOSHA3-NEXT: ret
+ %fshl = tail call <1 x i64> @llvm.fshl.v1i64(<1 x i64> %v.val, <1 x i64> %v.val, <1 x i64> splat (i64 1))
+ ret <1 x i64> %fshl
+}
+
define <4 x i32> @xar_instead_of_or2(<4 x i32> %r) {
; SHA3-LABEL: xar_instead_of_or2:
; SHA3: // %bb.0: // %entry
>From 410005c71f30de33e380adbfc3951931bd7ec53f Mon Sep 17 00:00:00 2001
From: David Green <dmg862 at gmail.com>
Date: Thu, 29 May 2025 10:01:19 +0100
Subject: [PATCH 2/2] Update llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
Co-authored-by: Cullen Rhodes <cullen.rhodes at arm.com>
---
llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 0b7a810fd4747..9b02208ea7e10 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -4662,7 +4662,7 @@ bool AArch64DAGToDAGISel::trySelectXAR(SDNode *N) {
SDValue Ops[] = {R1, R2, Imm};
SDNode *XAR =
- CurDAG->getMachineNode(AArch64::XAR, DL, R1.getValueType(), Ops);
+ CurDAG->getMachineNode(AArch64::XAR, DL, MVT::v2i64, Ops);
if (VT == MVT::v1i64) {
SDValue DSub = CurDAG->getTargetConstant(AArch64::dsub, DL, MVT::i32);
More information about the llvm-commits
mailing list