-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[RISCV][MRI] Account for fixed registers when determining callee saved regs #115756
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RISCV][MRI] Account for fixed registers when determining callee saved regs #115756
Conversation
@llvm/pr-subscribers-backend-m68k @llvm/pr-subscribers-backend-risc-v Author: Michael Maitland (michaelmaitland) ChangesThis fixes https://discourse.llvm.org/t/fixed-register-being-spill-and-restored-in-clang/83058. We need to do it in So to put it in Full diff: https://github.com/llvm/llvm-project/pull/115756.diff 8 Files Affected:
diff --git a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
index bfaa6450779ae0..6b14d1476568f9 100644
--- a/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
+++ b/llvm/include/llvm/CodeGen/TargetSubtargetInfo.h
@@ -339,6 +339,8 @@ class TargetSubtargetInfo : public MCSubtargetInfo {
// Conservatively assume such instructions exist by default.
return true;
}
+
+ virtual bool isRegisterReservedByUser(Register R) const { return false; }
};
} // end namespace llvm
diff --git a/llvm/lib/CodeGen/MachineRegisterInfo.cpp b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
index fcedb302d228c4..6f636a161f5000 100644
--- a/llvm/lib/CodeGen/MachineRegisterInfo.cpp
+++ b/llvm/lib/CodeGen/MachineRegisterInfo.cpp
@@ -635,7 +635,13 @@ const MCPhysReg *MachineRegisterInfo::getCalleeSavedRegs() const {
if (IsUpdatedCSRsInitialized)
return UpdatedCSRs.data();
- return getTargetRegisterInfo()->getCalleeSavedRegs(MF);
+ const MCPhysReg *Regs = getTargetRegisterInfo()->getCalleeSavedRegs(MF);
+
+ for (unsigned I = 0; Regs[I]; ++I)
+ if (MF->getSubtarget().isRegisterReservedByUser(Regs[I]))
+ MF->getRegInfo().disableCalleeSavedRegister(Regs[I]);
+
+ return Regs;
}
void MachineRegisterInfo::setCalleeSavedRegs(ArrayRef<MCPhysReg> CSRs) {
diff --git a/llvm/lib/Target/M68k/M68kRegisterInfo.cpp b/llvm/lib/Target/M68k/M68kRegisterInfo.cpp
index 62fb72ba4fd5e4..0f6b4761f2cb8a 100644
--- a/llvm/lib/Target/M68k/M68kRegisterInfo.cpp
+++ b/llvm/lib/Target/M68k/M68kRegisterInfo.cpp
@@ -136,7 +136,7 @@ BitVector M68kRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
// Registers reserved by users
for (size_t Reg = 0, Total = getNumRegs(); Reg != Total; ++Reg) {
- if (MF.getSubtarget<M68kSubtarget>().isRegisterReservedByUser(Reg))
+ if (MF.getSubtarget().isRegisterReservedByUser(Reg))
setBitVector(Reg);
}
diff --git a/llvm/lib/Target/M68k/M68kSubtarget.h b/llvm/lib/Target/M68k/M68kSubtarget.h
index 3fbec2f72fb861..c08a9786fb27ba 100644
--- a/llvm/lib/Target/M68k/M68kSubtarget.h
+++ b/llvm/lib/Target/M68k/M68kSubtarget.h
@@ -107,7 +107,7 @@ class M68kSubtarget : public M68kGenSubtargetInfo {
bool isPositionIndependent() const;
- bool isRegisterReservedByUser(Register R) const {
+ bool isRegisterReservedByUser(Register R) const override {
assert(R < M68k::NUM_TARGET_REGS && "Register out of range");
return UserReservedRegister[R];
}
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 831b0b30d47fcc..c8c495327c383f 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -19884,8 +19884,7 @@ SDValue RISCVTargetLowering::LowerCall(CallLoweringInfo &CLI,
// reserved, if so report an error. Do the same for the return address if this
// is not a tailcall.
validateCCReservedRegs(RegsToPass, MF);
- if (!IsTailCall &&
- MF.getSubtarget<RISCVSubtarget>().isRegisterReservedByUser(RISCV::X1))
+ if (!IsTailCall && MF.getSubtarget().isRegisterReservedByUser(RISCV::X1))
MF.getFunction().getContext().diagnose(DiagnosticInfoUnsupported{
MF.getFunction(),
"Return address register required, but has been reserved."});
diff --git a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
index 26195ef721db39..4b3b1d5154e9f6 100644
--- a/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVRegisterInfo.cpp
@@ -163,7 +163,7 @@ BitVector RISCVRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
bool RISCVRegisterInfo::isAsmClobberable(const MachineFunction &MF,
MCRegister PhysReg) const {
- return !MF.getSubtarget<RISCVSubtarget>().isRegisterReservedByUser(PhysReg);
+ return !MF.getSubtarget().isRegisterReservedByUser(PhysReg);
}
const uint32_t *RISCVRegisterInfo::getNoPreservedMask() const {
diff --git a/llvm/lib/Target/RISCV/RISCVSubtarget.h b/llvm/lib/Target/RISCV/RISCVSubtarget.h
index f59a3737ae76f9..99edf22eb0791f 100644
--- a/llvm/lib/Target/RISCV/RISCVSubtarget.h
+++ b/llvm/lib/Target/RISCV/RISCVSubtarget.h
@@ -218,7 +218,7 @@ class RISCVSubtarget : public RISCVGenSubtargetInfo {
TargetABI == RISCVABI::ABI_ILP32 ||
TargetABI == RISCVABI::ABI_ILP32E;
}
- bool isRegisterReservedByUser(Register i) const {
+ bool isRegisterReservedByUser(Register i) const override {
assert(i < RISCV::NUM_TARGET_REGS && "Register out of range");
return UserReservedRegister[i];
}
diff --git a/llvm/test/CodeGen/RISCV/fixed-global-regalloc.ll b/llvm/test/CodeGen/RISCV/fixed-global-regalloc.ll
new file mode 100644
index 00000000000000..f1993ae142ae8f
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/fixed-global-regalloc.ll
@@ -0,0 +1,20 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
+; RUN: llc %s -mtriple=riscv64 -mattr=+reserve-x24 | FileCheck %s
+
+define i32 @main() {
+; CHECK-LABEL: main:
+; CHECK: # %bb.0: # %entry
+; CHECK-NEXT: li s8, 123
+; CHECK-NEXT: li a0, 0
+; CHECK-NEXT: ret
+entry:
+ tail call void @llvm.write_register.i64(metadata !0, i64 123)
+ ret i32 0
+}
+
+declare void @llvm.write_register.i64(metadata, i64) #1
+
+!llvm.named.register.x24 = !{!0}
+
+!0 = !{!"x24"}
+
|
Does this change the stack layout of callee saved registers when one is reserved? Does it match gcc stack layout? |
This patch causes us not to spill the reserved register, when we were spilling it before. This by definition changes the stack layout.
I tried with this program with my patch applied:
GCC:
LLVM + this patch:
Looks the same on this example. |
A better test would spill s7 and s9, but not s8. I want to know if s8 still gets allocated a slot in gcc. |
It looks like we are still allocating and spilling a slack slot. I think GCC is over allocating but not spilling?
GCC:
LLVM + this patch:
|
Shouldn't this patch prevent the save/restore of s0? |
Reserving x8 doesn't seem like a sensible thing to do, that's one of the few registers that really should be under the compiler's control, no? |
Sorry, I collected this experiment without this patch (I had built another branch and forgot). I have updated the test cases now with the correct code. And I addressed @jrtc27 concern of using x8. |
|
The behavior differs from GCC for AArch64, ARM, Hexagon, SPARC, M68k and RISC-V. In LLVM, different targets have different interfaces to check whether the register was This patch adds the interface, and migrates RISC-V and M68k to that interface, since they are already using the interface. |
How will this interact with AArch64 or other targets calling setCalleeSavedRegisters which will cause |
If a target calls If a target calls |
The existing AArch64 code that uses I'm just asking questions to make sure you've designed something that covers the use cases of other targets. If you think having AArch64 fix implement their fixed register support in |
I'm interpreting the existing code in AArch64 as copying the call of getTargetRegisterInfo->getCalleeSavedRegs out of Or they could just call MachineRegisterInfo::getCalleeSavedRegs from the start, add some regs to the result, and call setCalleeSavedRegs. Or they could use getCalleeSavedRegs and add a function addCalleeSavedReg instead of using setCalleeSavedRegs. |
ping |
llvm/test/CodeGen/RISCV/fixed-csr.ll
Outdated
|
||
declare void @llvm.write_register.i64(metadata, i64) | ||
|
||
define noundef signext i32 @bar() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could add nounwind
here to remove the .cfi directives from the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This fixes https://discourse.llvm.org/t/fixed-register-being-spill-and-restored-in-clang/83058.
We need to do it in
MachineRegisterInfo::getCalleeSavedRegs
instead ofRISCVRegisterInfo::getCalleeSavedRegs
since the MF argument ofTargetRegisterInfo:::getCalleeSavedRegs
isconst
, so we can't callMF->getRegInfo().disableCalleeSavedRegister
there.So to put it in
MachineRegisterInfo::getCalleeSavedRegs
, we moveisRegisterReservedByUser
intoTargetSubtargetInfo
.