diff --git a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h --- a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h +++ b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h @@ -60,9 +60,10 @@ bool useSaveRestoreLibCalls(const MachineFunction &MF) const { // We cannot use fixed locations for the callee saved spill slots if the - // function uses a varargs save area. + // function uses a varargs save area, or is an interrupt handler. return MF.getSubtarget().enableSaveRestore() && - VarArgsSaveSize == 0 && !MF.getFrameInfo().hasTailCall(); + VarArgsSaveSize == 0 && !MF.getFrameInfo().hasTailCall() && + !MF.getFunction().hasFnAttribute("interrupt"); } uint64_t getRVVStackSize() const { return RVVStackSize; } diff --git a/llvm/test/CodeGen/RISCV/saverestore.ll b/llvm/test/CodeGen/RISCV/saverestore.ll --- a/llvm/test/CodeGen/RISCV/saverestore.ll +++ b/llvm/test/CodeGen/RISCV/saverestore.ll @@ -297,3 +297,36 @@ call void @llvm.stackrestore(i8* %sp) ret void } + +; Check that functions with interrupt attribute do not use save/restore code + +declare i32 @foo(...) +define void @interrupt() #0 { +; RV32I-LABEL: interrupt: +; RV32I-NOT: call t0, __riscv_save +; RV32I-NOT: tail __riscv_restore +; +; RV64I-LABEL: interrupt: +; RV64I-NOT: call t0, __riscv_save +; RV64I-NOT: tail __riscv_restore +; +; RV32I-SR-LABEL: interrupt: +; RV32I-SR-NOT: call t0, __riscv_save +; RV32I-SR-NOT: tail __riscv_restore +; +; RV64I-SR-LABEL: interrupt: +; RV64I-SR-NOT: call t0, __riscv_save +; RV64I-SR-NOT: tail __riscv_restore +; +; RV32I-FP-SR-LABEL: interrupt: +; RV32I-FP-SR-NOT: call t0, __riscv_save +; RV32I-FP-SR-NOT: tail __riscv_restore +; +; RV64I-FP-SR-LABEL: interrupt: +; RV64I-FP-SR-NOT: call t0, __riscv_save +; RV64I-FP-SR-NOT: tail __riscv_restore + %call = call i32 bitcast (i32 (...)* @foo to i32 ()*)() + ret void +} + +attributes #0 = { nounwind "interrupt"="user" }