[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