summaryrefslogtreecommitdiffstats
path: root/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp')
-rw-r--r--llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp18
1 files changed, 18 insertions, 0 deletions
diff --git a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
index 79fafa5497f..76c5425b692 100644
--- a/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
+++ b/llvm/lib/CodeGen/TargetFrameLoweringImpl.cpp
@@ -36,6 +36,12 @@ bool TargetFrameLowering::noFramePointerElim(const MachineFunction &MF) const {
return Attr.getValueAsString() == "true";
}
+bool TargetFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const {
+ assert(MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&
+ MF.getFunction().hasFnAttribute(Attribute::NoUnwind));
+ return false;
+}
+
/// Returns the displacement from the frame register to the stack
/// frame of the specified index, along with the frame register used
/// (in output arg FrameReg). This is the default implementation which
@@ -85,6 +91,18 @@ void TargetFrameLowering::determineCalleeSaves(MachineFunction &MF,
if (MF.getFunction().hasFnAttribute(Attribute::Naked))
return;
+ // Noreturn+nounwind functions never restore CSR, so no saves are needed.
+ // Purely noreturn functions may still return through throws, so those must
+ // save CSR for caller exception handlers.
+ //
+ // If the function uses longjmp to break out of its current path of
+ // execution we do not need the CSR spills either: setjmp stores all CSRs
+ // it was called with into the jmp_buf, which longjmp then restores.
+ if (MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&
+ MF.getFunction().hasFnAttribute(Attribute::NoUnwind) &&
+ enableCalleeSaveSkip(MF))
+ return;
+
// Functions which call __builtin_unwind_init get all their registers saved.
bool CallsUnwindInit = MF.callsUnwindInit();
const MachineRegisterInfo &MRI = MF.getRegInfo();
OpenPOWER on IntegriCloud