[clang] [llvm] [AArch64] Add -mlr-for-calls-only to replace the now removed -ffixed-x30 flag. (PR #98073)
Amara Emerson via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 8 14:54:40 PDT 2024
https://github.com/aemerson updated https://github.com/llvm/llvm-project/pull/98073
>From d7a8f55b0790b15060f73f188ce97c83fe75f62d Mon Sep 17 00:00:00 2001
From: Amara Emerson <amara at apple.com>
Date: Mon, 8 Jul 2024 10:09:06 -0700
Subject: [PATCH 1/2] [AArch64] Add -mlr-for-calls-only to replace the now
removed -ffixed-x30 flag.
This re-introduces the effective behaviour that was reverted in 7ad481e76c9bee5b9895ebfa0fdb52f31cb7de77.
This time we're not using the same mechanism, exposing another reservation feature
that prevents only regalloc from using the register, but not for other required uses
like ABIs.
This also fixes a consequent issue with reserving LR, which is that frame lowering
was only adding live-in flags for non-reserved regs. This would cause issues later
since the outliner needs accurate flags to determine when LR needs to be preserved.
rdar://131313095
---
clang/include/clang/Driver/Options.td | 3 +
.../clang/Driver/aarch64-mlr-for-calls-only.c | 4 +
clang/lib/Driver/ToolChains/Arch/AArch64.cpp | 3 +
llvm/lib/Target/AArch64/AArch64Features.td | 4 +
.../Target/AArch64/AArch64FrameLowering.cpp | 7 +-
.../Target/AArch64/AArch64RegisterInfo.cpp | 3 +
llvm/lib/Target/AArch64/AArch64Subtarget.h | 1 +
.../CodeGen/AArch64/arm64-platform-reg.ll | 7 +-
.../AArch64/lr-reserved-for-ra-live-in.mir | 110 ++++++++++++++++++
9 files changed, 139 insertions(+), 3 deletions(-)
create mode 100644 clang/include/clang/Driver/aarch64-mlr-for-calls-only.c
create mode 100644 llvm/test/CodeGen/AArch64/lr-reserved-for-ra-live-in.mir
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 58ca6f2bea9e44..714d5de76dd996 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4917,6 +4917,9 @@ foreach i = {1-31} in
def ffixed_x#i : Flag<["-"], "ffixed-x"#i>, Group<m_Group>,
HelpText<"Reserve the x"#i#" register (AArch64/RISC-V only)">;
+def mlr_for_calls_only : Flag<["-"], "mlr-for-calls-only">, Group<m_aarch64_Features_Group>,
+ HelpText<"Do not allocate the LR register for general purpose usage, only for calls. (AArch64 only)">;
+
foreach i = {8-15,18} in
def fcall_saved_x#i : Flag<["-"], "fcall-saved-x"#i>, Group<m_aarch64_Features_Group>,
HelpText<"Make the x"#i#" register call-saved (AArch64 only)">;
diff --git a/clang/include/clang/Driver/aarch64-mlr-for-calls-only.c b/clang/include/clang/Driver/aarch64-mlr-for-calls-only.c
new file mode 100644
index 00000000000000..1fe3bdab4f3e43
--- /dev/null
+++ b/clang/include/clang/Driver/aarch64-mlr-for-calls-only.c
@@ -0,0 +1,4 @@
+
+// RUN: %clang --target=aarch64-none-gnu -mlr-for-calls-only -### %s 2> %t
+// RUN: FileCheck --check-prefix=CHECK < %t %s
+// CHECK: "-target-feature" "+reserve-lr-for-ra"
diff --git a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
index ec248b80251ea3..5fbf38cdda12b1 100644
--- a/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
+++ b/clang/lib/Driver/ToolChains/Arch/AArch64.cpp
@@ -398,6 +398,9 @@ void aarch64::getAArch64TargetFeatures(const Driver &D,
if (Args.hasArg(options::OPT_ffixed_x28))
Features.push_back("+reserve-x28");
+ if (Args.hasArg(options::OPT_mlr_for_calls_only))
+ Features.push_back("+reserve-lr-for-ra");
+
if (Args.hasArg(options::OPT_fcall_saved_x8))
Features.push_back("+call-saved-x8");
diff --git a/llvm/lib/Target/AArch64/AArch64Features.td b/llvm/lib/Target/AArch64/AArch64Features.td
index 8754ea4974999f..50ff25ff1ba0c8 100644
--- a/llvm/lib/Target/AArch64/AArch64Features.td
+++ b/llvm/lib/Target/AArch64/AArch64Features.td
@@ -571,6 +571,10 @@ foreach i = {1-7,9-15,18,20-28} in
"Reserve X"#i#", making it unavailable "
"as a GPR">;
+def FeatureReserveLRForRA : SubtargetFeature<"reserve-lr-for-ra",
+ "ReserveLRForRA", "true",
+ "Reserve LR for call use only">;
+
foreach i = {8-15,18} in
def FeatureCallSavedX#i : SubtargetFeature<"call-saved-x"#i,
"CustomCallSavedXRegs["#i#"]", "true", "Make X"#i#" callee saved.">;
diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
index 75e89e8222ae95..c760d29e9d1385 100644
--- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp
@@ -3267,10 +3267,13 @@ bool AArch64FrameLowering::spillCalleeSavedRegisters(
InsertSEH(MIB, TII, MachineInstr::FrameSetup);
} else { // The code when the pair of ZReg is not present
MachineInstrBuilder MIB = BuildMI(MBB, MI, DL, TII.get(StrOpc));
- if (!MRI.isReserved(Reg1))
+ const AArch64RegisterInfo *RegInfo =
+ static_cast<const AArch64RegisterInfo *>(
+ MF.getSubtarget().getRegisterInfo());
+ if (!RegInfo->isStrictlyReservedReg(MF, Reg1))
MBB.addLiveIn(Reg1);
if (RPI.isPaired()) {
- if (!MRI.isReserved(Reg2))
+ if (!RegInfo->isStrictlyReservedReg(MF, Reg2))
MBB.addLiveIn(Reg2);
MIB.addReg(Reg2, getPrologueDeath(MF, Reg2));
MIB.addMemOperand(MF.getMachineMemOperand(
diff --git a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
index cc50b59dd8d7e1..5408db0e653a49 100644
--- a/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp
@@ -501,6 +501,9 @@ AArch64RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
markSuperRegs(Reserved, AArch64::GPR32commonRegClass.getRegister(i));
}
+ if (MF.getSubtarget<AArch64Subtarget>().isLRReservedForRA())
+ markSuperRegs(Reserved, AArch64::LR);
+
assert(checkAllSuperRegsMarked(Reserved));
return Reserved;
}
diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h
index 5faba09aa67bdc..4b840b24ba134b 100644
--- a/llvm/lib/Target/AArch64/AArch64Subtarget.h
+++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h
@@ -209,6 +209,7 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
AllReservedX |= ReserveXRegisterForRA;
return AllReservedX.count();
}
+ bool isLRReservedForRA() const { return ReserveLRForRA; }
bool isXRegCustomCalleeSaved(size_t i) const {
return CustomCallSavedXRegs[i];
}
diff --git a/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll b/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll
index 3df2ef7aa59fc8..eefc858db27526 100644
--- a/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll
+++ b/llvm/test/CodeGen/AArch64/arm64-platform-reg.ll
@@ -34,6 +34,7 @@
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x26 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X26
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x27 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X27
; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-x28 -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-X28
+; RUN: llc -mtriple=arm64-linux-gnu -mattr=+reserve-lr-for-ra -o - %s | FileCheck %s --check-prefixes=CHECK-RESERVE,CHECK-RESERVE-LR-RA
; Test multiple of reserve-x# options together.
; RUN: llc -mtriple=arm64-linux-gnu \
@@ -72,6 +73,7 @@
; RUN: -mattr=+reserve-x26 \
; RUN: -mattr=+reserve-x27 \
; RUN: -mattr=+reserve-x28 \
+; RUN: -mattr=+reserve-lr-for-ra \
; RUN: -reserve-regs-for-regalloc=X8,X16,X17,X19 \
; RUN: -o - %s | FileCheck %s \
; RUN: --check-prefix=CHECK-RESERVE \
@@ -102,7 +104,8 @@
; RUN: --check-prefix=CHECK-RESERVE-X25 \
; RUN: --check-prefix=CHECK-RESERVE-X26 \
; RUN: --check-prefix=CHECK-RESERVE-X27 \
-; RUN: --check-prefix=CHECK-RESERVE-X28
+; RUN: --check-prefix=CHECK-RESERVE-X28 \
+; RUN: --check-prefix=CHECK-RESERVE-LR-RA
; x18 is reserved as a platform register on Darwin but not on other
; systems. Create loads of register pressure and make sure this is respected.
@@ -149,6 +152,7 @@ define void @keep_live() {
; CHECK-RESERVE-X26-NOT: ldr x26
; CHECK-RESERVE-X27-NOT: ldr x27
; CHECK-RESERVE-X28-NOT: ldr x28
+; CHECK-RESERVE-LR-RA-NOT: ldr x30
; CHECK-RESERVE: Spill
; CHECK-RESERVE-NOT: ldr fp
; CHECK-RESERVE-X1-NOT: ldr x1,
@@ -178,6 +182,7 @@ define void @keep_live() {
; CHECK-RESERVE-X26-NOT: ldr x26
; CHECK-RESERVE-X27-NOT: ldr x27
; CHECK-RESERVE-X28-NOT: ldr x28
+; CHECK-RESERVE-LR-RA-NOT: ldr x30
; CHECK-RESERVE: ret
ret void
}
diff --git a/llvm/test/CodeGen/AArch64/lr-reserved-for-ra-live-in.mir b/llvm/test/CodeGen/AArch64/lr-reserved-for-ra-live-in.mir
new file mode 100644
index 00000000000000..1a53fa1e43dfdf
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/lr-reserved-for-ra-live-in.mir
@@ -0,0 +1,110 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 5
+# RUN: llc -run-pass=prologepilog -o - %s | FileCheck %s
+--- |
+ target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128-Fn32"
+ target triple = "arm64e-apple-ios18.4.0"
+
+ declare void @spam()
+
+ define i32 @check_lr_live(ptr %arg) #0 {
+ bb:
+ %icmp = icmp eq ptr %arg, null
+ %or = or i1 %icmp, false
+ br i1 %or, label %bb2, label %bb1
+
+ bb1: ; preds = %bb
+ call void @spam()
+ br label %bb2
+
+ bb2: ; preds = %bb1, %bb
+ %phi = phi i32 [ -536870206, %bb ], [ 0, %bb1 ]
+ ret i32 %phi
+ }
+
+ attributes #0 = { nounwind "target-features"="+fp-armv8,+fullfp16,+lse,+neon,+ras,+rcpc,+rdm,+reserve-lr-for-ra" }
+
+...
+# This test checks that the live-in flags for LR are correctly set when LR is reserved, but live for a call.
+---
+name: check_lr_live
+alignment: 4
+tracksRegLiveness: true
+tracksDebugUserValues: true
+liveins:
+ - { reg: '$x0' }
+frameInfo:
+ maxAlignment: 1
+ adjustsStack: true
+ hasCalls: true
+ maxCallFrameSize: 0
+ savePoint: '%bb.2'
+ restorePoint: '%bb.2'
+machineFunctionInfo: {}
+body: |
+ ; CHECK-LABEL: name: check_lr_live
+ ; CHECK: bb.0.bb:
+ ; CHECK-NEXT: successors: %bb.1(0x20000000), %bb.2(0x60000000)
+ ; CHECK-NEXT: liveins: $x0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: renamable $x8 = COPY $x0
+ ; CHECK-NEXT: renamable $w0 = MOVi32imm -536870206
+ ; CHECK-NEXT: CBNZX killed renamable $x8, %bb.2
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.1:
+ ; CHECK-NEXT: successors: %bb.4(0x80000000)
+ ; CHECK-NEXT: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: B %bb.4
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.2.bb:
+ ; CHECK-NEXT: successors: %bb.4(0x2aaaaaab), %bb.3(0x55555555)
+ ; CHECK-NEXT: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: CBNZW $wzr, %bb.4
+ ; CHECK-NEXT: B %bb.3
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.3.bb1:
+ ; CHECK-NEXT: successors: %bb.4(0x80000000)
+ ; CHECK-NEXT: liveins: $lr
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: early-clobber $sp = frame-setup STPXpre killed $fp, killed $lr, $sp, -2 :: (store (s64) into %stack.1), (store (s64) into %stack.0)
+ ; CHECK-NEXT: BL @spam, csr_darwin_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp
+ ; CHECK-NEXT: renamable $w0 = COPY $wzr
+ ; CHECK-NEXT: early-clobber $sp, $fp, $lr = frame-destroy LDPXpost $sp, 2 :: (load (s64) from %stack.1), (load (s64) from %stack.0)
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: bb.4.bb2:
+ ; CHECK-NEXT: liveins: $w0
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: RET_ReallyLR implicit $w0
+ bb.0.bb:
+ successors: %bb.4(0x20000000), %bb.1(0x60000000)
+ liveins: $x0
+
+ renamable $x8 = COPY $x0
+ renamable $w0 = MOVi32imm -536870206
+ CBNZX killed renamable $x8, %bb.1
+
+ bb.4:
+ liveins: $w0
+
+ B %bb.3
+
+ bb.1.bb:
+ successors: %bb.3(0x2aaaaaab), %bb.2(0x55555555)
+ liveins: $w0
+
+ CBNZW $wzr, %bb.3
+ B %bb.2
+
+ bb.2.bb1:
+ ADJCALLSTACKDOWN 0, 0, implicit-def dead $sp, implicit $sp
+ BL @spam, csr_darwin_aarch64_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp
+ ADJCALLSTACKUP 0, 0, implicit-def dead $sp, implicit $sp
+ renamable $w0 = COPY $wzr
+
+ bb.3.bb2:
+ liveins: $w0
+
+ RET_ReallyLR implicit $w0
+
+...
>From 2bf70e805667f4d49a013524412adf6b3c301fd6 Mon Sep 17 00:00:00 2001
From: Amara Emerson <amara.emerson at gmail.com>
Date: Mon, 8 Jul 2024 14:54:32 -0700
Subject: [PATCH 2/2] whitespace
Co-authored-by: Francis Visoiu Mistrih <890283+francisvm at users.noreply.github.com>
---
clang/include/clang/Driver/aarch64-mlr-for-calls-only.c | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/include/clang/Driver/aarch64-mlr-for-calls-only.c b/clang/include/clang/Driver/aarch64-mlr-for-calls-only.c
index 1fe3bdab4f3e43..e71a4cdfe0e7fe 100644
--- a/clang/include/clang/Driver/aarch64-mlr-for-calls-only.c
+++ b/clang/include/clang/Driver/aarch64-mlr-for-calls-only.c
@@ -1,4 +1,3 @@
-
// RUN: %clang --target=aarch64-none-gnu -mlr-for-calls-only -### %s 2> %t
// RUN: FileCheck --check-prefix=CHECK < %t %s
// CHECK: "-target-feature" "+reserve-lr-for-ra"
More information about the cfe-commits
mailing list