[llvm] [AArch64] Use the named-register pseudo only for allocatable registers (PR #203037)
Adhemerval Zanella via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 10 09:14:27 PDT 2026
https://github.com/zatrazz created https://github.com/llvm/llvm-project/pull/203037
The READ_REGISTER_GPR64/FPR64 pseudos, and the analogous write handling in tryWriteRegister, perform an immediate-encoded access that is only meaningful for an allocatable register, whose value is otherwise undefined. A reserved register has a well-defined value and is read/written through the normal CopyFromReg/CopyToReg path (getRegisterByName already returns reserved registers).
>From 44327003be5957f39550d7dc7a44bac139bb179d Mon Sep 17 00:00:00 2001
From: Adhemerval Zanella <zatrazz at gmail.com>
Date: Wed, 10 Jun 2026 08:30:10 -0300
Subject: [PATCH] [AArch64] Use the named-register pseudo only for allocatable
registers
The READ_REGISTER_GPR64/FPR64 pseudos, and the analogous write handling in
tryWriteRegister, perform an immediate-encoded access that is only
meaningful for an allocatable register, whose value is otherwise undefined. A
reserved register has a well-defined value and is read/written through the
normal CopyFromReg/CopyToReg path (getRegisterByName already returns reserved
registers).
---
llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp | 13 +++++++++++--
llvm/test/CodeGen/AArch64/read-reg-reserved.ll | 15 +++++++++++++++
2 files changed, 26 insertions(+), 2 deletions(-)
create mode 100644 llvm/test/CodeGen/AArch64/read-reg-reserved.ll
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index 499bb2325186d..822bae3f04fe7 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -4321,7 +4321,12 @@ bool AArch64DAGToDAGISel::tryReadRegister(SDNode *N) {
PseudoOp = AArch64::READ_REGISTER_GPR64;
else if (AArch64::FPR64RegClass.contains(PReg))
PseudoOp = AArch64::READ_REGISTER_FPR64;
- if (!ReadIs128Bit && PseudoOp && N->getValueType(0) == MVT::i64) {
+ // The pseudo performs an opaque read and is only meaningful for an
+ // allocatable register. A reserved register has a well-defined value
+ // and is read through the normal CopyFromReg.
+ const MachineFunction &MF = CurDAG->getMachineFunction();
+ if (!ReadIs128Bit && PseudoOp && N->getValueType(0) == MVT::i64 &&
+ !Subtarget->getRegisterInfo()->isReservedReg(MF, PReg)) {
CurDAG->SelectNodeTo(N, PseudoOp, MVT::i64, MVT::Other,
{CurDAG->getTargetConstant(PReg, DL, MVT::i32),
N->getOperand(0)});
@@ -4420,8 +4425,12 @@ bool AArch64DAGToDAGISel::tryWriteRegister(SDNode *N) {
RegString->getString());
bool IsGPR = AArch64::GPR64RegClass.contains(PReg);
bool IsFPR = AArch64::FPR64RegClass.contains(PReg);
+ // Only allocatable registers are handled here; a reserved register has a
+ // well-defined value and is written through the normal CopyToReg path.
+ const MachineFunction &MF = CurDAG->getMachineFunction();
if (!WriteIs128Bit && (IsGPR || IsFPR) &&
- N->getOperand(2).getValueType() == MVT::i64) {
+ N->getOperand(2).getValueType() == MVT::i64 &&
+ !Subtarget->getRegisterInfo()->isReservedReg(MF, PReg)) {
SDValue Copy =
CurDAG->getCopyToReg(N->getOperand(0), DL, PReg, N->getOperand(2));
SDValue RegOp = CurDAG->getRegister(PReg, MVT::i64);
diff --git a/llvm/test/CodeGen/AArch64/read-reg-reserved.ll b/llvm/test/CodeGen/AArch64/read-reg-reserved.ll
new file mode 100644
index 0000000000000..2e99c21206dcd
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/read-reg-reserved.ll
@@ -0,0 +1,15 @@
+; RUN: llc -mtriple=aarch64 -mattr=+reserve-x18 -fast-isel=0 -global-isel=false \
+; RUN: -stop-after=finalize-isel < %s | FileCheck %s
+
+define i64 @read_reserved_x18() {
+; CHECK-LABEL: name: read_reserved_x18
+; CHECK: COPY $x18
+; CHECK-NOT: READ_REGISTER_GPR64
+entry:
+ %0 = call i64 @llvm.read_volatile_register.i64(metadata !0)
+ ret i64 %0
+}
+
+declare i64 @llvm.read_volatile_register.i64(metadata)
+
+!0 = !{!"x18"}
More information about the llvm-commits
mailing list