[clang] [llvm] [AArch64] Add -mlr-for-calls-only to replace the now removed -ffixed-x30 flag. (PR #98073)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 8 13:30:15 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-driver
Author: Amara Emerson (aemerson)
<details>
<summary>Changes</summary>
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
---
Full diff: https://github.com/llvm/llvm-project/pull/98073.diff
9 Files Affected:
- (modified) clang/include/clang/Driver/Options.td (+3)
- (added) clang/include/clang/Driver/aarch64-mlr-for-calls-only.c (+4)
- (modified) clang/lib/Driver/ToolChains/Arch/AArch64.cpp (+3)
- (modified) llvm/lib/Target/AArch64/AArch64Features.td (+4)
- (modified) llvm/lib/Target/AArch64/AArch64FrameLowering.cpp (+5-2)
- (modified) llvm/lib/Target/AArch64/AArch64RegisterInfo.cpp (+3)
- (modified) llvm/lib/Target/AArch64/AArch64Subtarget.h (+1)
- (modified) llvm/test/CodeGen/AArch64/arm64-platform-reg.ll (+6-1)
- (added) llvm/test/CodeGen/AArch64/lr-reserved-for-ra-live-in.mir (+110)
``````````diff
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
+
+...
``````````
</details>
https://github.com/llvm/llvm-project/pull/98073
More information about the cfe-commits
mailing list