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/interrupt-attr-save-restore-call.ll b/llvm/test/CodeGen/RISCV/interrupt-attr-save-restore-call.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/RISCV/interrupt-attr-save-restore-call.ll @@ -0,0 +1,94 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple riscv32-unknown-elf -mattr=+save-restore -o - %s \ +; RUN: 2>&1 | FileCheck %s -check-prefix CHECK-RV32 +; RUN: llc -mtriple riscv64-unknown-elf -mattr=+save-restore -o - %s \ +; RUN: 2>&1 | FileCheck %s -check-prefix CHECK-RV64 + +; +; Checking save-restore calls not emitted for the handler when save-restore is enabled +; + +declare i32 @otherfoo(...) +define void @foo_with_call() #0 { +; CHECK-RV32-LABEL: foo_with_call: +; CHECK-RV32: # %bb.0: +; CHECK-RV32-NEXT: addi sp, sp, -64 +; CHECK-RV32-NEXT: sw ra, 60(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw t0, 56(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw t1, 52(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw t2, 48(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw a0, 44(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw a1, 40(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw a2, 36(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw a3, 32(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw a4, 28(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw a5, 24(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw a6, 20(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw a7, 16(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw t3, 12(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw t4, 8(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw t5, 4(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: sw t6, 0(sp) # 4-byte Folded Spill +; CHECK-RV32-NEXT: call otherfoo +; CHECK-RV32-NEXT: lw t6, 0(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw t5, 4(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw t4, 8(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw t3, 12(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw a7, 16(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw a6, 20(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw a5, 24(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw a4, 28(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw a3, 32(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw a2, 36(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw a1, 40(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw a0, 44(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw t2, 48(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw t1, 52(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw t0, 56(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: lw ra, 60(sp) # 4-byte Folded Reload +; CHECK-RV32-NEXT: addi sp, sp, 64 +; CHECK-RV32-NEXT: uret +; +; CHECK-RV64-LABEL: foo_with_call: +; CHECK-RV64: # %bb.0: +; CHECK-RV64-NEXT: addi sp, sp, -128 +; CHECK-RV64-NEXT: sd ra, 120(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd t0, 112(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd t1, 104(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd t2, 96(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd a0, 88(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd a1, 80(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd a2, 72(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd a3, 64(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd a4, 56(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd a5, 48(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd a6, 40(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd a7, 32(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd t3, 24(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd t4, 16(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd t5, 8(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: sd t6, 0(sp) # 8-byte Folded Spill +; CHECK-RV64-NEXT: call otherfoo +; CHECK-RV64-NEXT: ld t6, 0(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld t5, 8(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld t4, 16(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld t3, 24(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld a7, 32(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld a6, 40(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld a5, 48(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld a4, 56(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld a3, 64(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld a2, 72(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld a1, 80(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld a0, 88(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld t2, 96(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld t1, 104(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld t0, 112(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: ld ra, 120(sp) # 8-byte Folded Reload +; CHECK-RV64-NEXT: addi sp, sp, 128 +; CHECK-RV64-NEXT: uret + %call = call i32 bitcast (i32 (...)* @otherfoo to i32 ()*)() + ret void +} + +attributes #0 = { nounwind "interrupt"="user" }