[llvm] 4880e16 - [RISCV] Support frame pointers in SiFive CLIC preemptible handlers (#221318)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 19:00:20 PDT 2026
Author: Zeyi Xu
Date: 2026-09-25T10:00:10+08:00
New Revision: 4880e16f73dfc25762a857b9c08ad2bd5c14c8e0
URL: https://github.com/llvm/llvm-project/commit/4880e16f73dfc25762a857b9c08ad2bd5c14c8e0
DIFF: https://github.com/llvm/llvm-project/commit/4880e16f73dfc25762a857b9c08ad2bd5c14c8e0.diff
LOG: [RISCV] Support frame pointers in SiFive CLIC preemptible handlers (#221318)
This commit adds frame-pointer support for SiFive CLIC preemptible
handlers by using t0 to save mcause and mepc to dedicated stack slots in
both cases.
Added:
llvm/test/CodeGen/RISCV/sifive-interrupt-frame-pointer.ll
Modified:
clang/docs/ReleaseNotes.md
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
llvm/test/CodeGen/RISCV/sifive-interrupt-attr.ll
llvm/test/CodeGen/RISCV/sifive-interrupt-frame-flags.ll
Removed:
llvm/test/CodeGen/RISCV/sifive-interrupt-attr-err.ll
################################################################################
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 344cfebe166883..f6cdca91cea103 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -872,8 +872,7 @@ features cannot lower the translation-unit ABI level;
- Added a new warning when the same interrupt type is specified more than
once in a RISC-V `interrupt` attribute.
-- SiFive CLIC preemptible interrupt handlers now diagnose unsupported frame
- pointers instead of producing a backend fatal error.
+- SiFive CLIC preemptible interrupt handlers now support frame pointers.
- Added `-march=native` for better compatibility with ARM, AArch64, and X86. This
option will be treated like `-mcpu=native` if `-mcpu` is not present. If
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 4732b4153aae63..648df0690fa20e 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -265,9 +265,7 @@ createSiFivePreemptibleInterruptFrameEntries(MachineFunction &MF,
*MF.getSubtarget<RISCVSubtarget>().getRegisterInfo();
MachineFrameInfo &MFI = MF.getFrameInfo();
- // Create two frame objects for spilling X8 and X9, which will be done in
- // `emitSiFiveCLICPreemptibleSaves`. This is in addition to any other stack
- // objects we might have for X8 and X9, as they might be saved twice.
+ // Create two frame objects for saving `mcause` and `mepc`.
for (int I = 0; I < 2; ++I) {
int FI = MFI.CreateStackObject(TRI.getSpillSize(RC), TRI.getSpillAlign(RC),
true);
@@ -275,6 +273,16 @@ createSiFivePreemptibleInterruptFrameEntries(MachineFunction &MF,
}
}
+// The scratch register retains an ordinary CSI slot, but its save and restore
+// are emitted explicitly as part of the SiFive CLIC interrupt sequence.
+static int getSiFiveCLICScratchFrameIndex(const MachineFunction &MF) {
+ const auto &CSI = MF.getFrameInfo().getCalleeSavedInfo();
+ auto ScratchCS = llvm::find_if(
+ CSI, [](const CalleeSavedInfo &CS) { return CS.getReg() == RISCV::X5; });
+ assert(ScratchCS != CSI.end() && "Missing SiFive CLIC scratch spill slot");
+ return ScratchCS->getFrameIdx();
+}
+
static void emitSiFiveCLICPreemptibleSaves(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
@@ -287,34 +295,30 @@ static void emitSiFiveCLICPreemptibleSaves(MachineFunction &MF,
const auto &STI = MF.getSubtarget<RISCVSubtarget>();
const RISCVInstrInfo *TII = STI.getInstrInfo();
- // FIXME: CFI Information here is nonexistent/wrong.
+ // FIXME: CFI information for `mcause` and `mepc` is missing.
- // X8 and X9 might be stored into the stack twice, initially into the
- // `interruptCSRFrameIndex` here, and then maybe again into their CSI frame
- // index.
- //
- // This is done instead of telling the register allocator that we need two
- // VRegs to store the value of `mcause` and `mepc` through the instruction,
- // which affects other passes.
- TII->storeRegToStackSlot(MBB, MBBI, RISCV::X8, /* IsKill=*/true,
- RVFI->getInterruptCSRFrameIndex(0),
- &RISCV::GPRRegClass, Register(),
- MachineInstr::FrameSetup);
- TII->storeRegToStackSlot(MBB, MBBI, RISCV::X9, /* IsKill=*/true,
- RVFI->getInterruptCSRFrameIndex(1),
+ // Preserve X5 before using it to save the interrupt CSRs. Other GPRs
+ // are saved by the ordinary spill sequence after preemption is enabled.
+ int ScratchFI = getSiFiveCLICScratchFrameIndex(MF);
+ TII->storeRegToStackSlot(MBB, MBBI, RISCV::X5, /*IsKill=*/true, ScratchFI,
&RISCV::GPRRegClass, Register(),
MachineInstr::FrameSetup);
+ if (needsDwarfCFI(MF))
+ CFIInstBuilder(MBB, MBBI, MachineInstr::FrameSetup)
+ .buildOffset(RISCV::X5, MF.getFrameInfo().getObjectOffset(ScratchFI));
- // Put `mcause` into X8 (s0), and `mepc` into X9 (s1). If either of these are
- // used in the function, then they will appear in `getUnmanagedCSI` and will
- // be saved again.
BuildMI(MBB, MBBI, DL, TII->get(RISCV::CSRRS))
- .addReg(RISCV::X8, RegState::Define)
+ .addReg(RISCV::X5, RegState::Define)
.addImm(RISCVSysReg::mcause)
.addReg(RISCV::X0)
.setMIFlag(MachineInstr::FrameSetup);
+ TII->storeRegToStackSlot(MBB, MBBI, RISCV::X5, /* IsKill=*/true,
+ RVFI->getInterruptCSRFrameIndex(0),
+ &RISCV::GPRRegClass, Register(),
+ MachineInstr::FrameSetup);
+
BuildMI(MBB, MBBI, DL, TII->get(RISCV::CSRRS))
- .addReg(RISCV::X9, RegState::Define)
+ .addReg(RISCV::X5, RegState::Define)
.addImm(RISCVSysReg::mepc)
.addReg(RISCV::X0)
.setMIFlag(MachineInstr::FrameSetup);
@@ -325,11 +329,16 @@ static void emitSiFiveCLICPreemptibleSaves(MachineFunction &MF,
.addImm(RISCVSysReg::mstatus)
.addImm(8)
.setMIFlag(MachineInstr::FrameSetup);
+ TII->storeRegToStackSlot(MBB, MBBI, RISCV::X5, /* IsKill=*/true,
+ RVFI->getInterruptCSRFrameIndex(1),
+ &RISCV::GPRRegClass, Register(),
+ MachineInstr::FrameSetup);
}
static void emitSiFiveCLICPreemptibleRestores(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
+ CFIInstBuilder &CFIBuilder,
const DebugLoc &DL) {
auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
@@ -339,7 +348,14 @@ static void emitSiFiveCLICPreemptibleRestores(MachineFunction &MF,
const auto &STI = MF.getSubtarget<RISCVSubtarget>();
const RISCVInstrInfo *TII = STI.getInstrInfo();
- // FIXME: CFI Information here is nonexistent/wrong.
+ // FIXME: CFI information for `mcause` and `mepc` is missing.
+
+ // Load mepc while preemption is still enabled. A nested handler preserves
+ // X5. Interrupts only need to be disabled before writing the CSRs back.
+ TII->loadRegFromStackSlot(MBB, MBBI, RISCV::X5,
+ RVFI->getInterruptCSRFrameIndex(1),
+ &RISCV::GPRRegClass, Register(),
+ RISCV::NoSubRegister, MachineInstr::FrameDestroy);
// Disable interrupts.
BuildMI(MBB, MBBI, DL, TII->get(RISCV::CSRRCI))
@@ -348,30 +364,32 @@ static void emitSiFiveCLICPreemptibleRestores(MachineFunction &MF,
.addImm(8)
.setMIFlag(MachineInstr::FrameDestroy);
- // Restore `mepc` from x9 (s1), and `mcause` from x8 (s0). If either were used
- // in the function, they have already been restored once, so now have the
- // value stored in `emitSiFiveCLICPreemptibleSaves`.
+ // Restore `mepc` and `mcause` through X5, then restore the value X5 held
+ // on entry to the handler.
BuildMI(MBB, MBBI, DL, TII->get(RISCV::CSRRW))
.addReg(RISCV::X0, RegState::Define)
.addImm(RISCVSysReg::mepc)
- .addReg(RISCV::X9, RegState::Kill)
+ .addReg(RISCV::X5, RegState::Kill)
.setMIFlag(MachineInstr::FrameDestroy);
+
+ TII->loadRegFromStackSlot(MBB, MBBI, RISCV::X5,
+ RVFI->getInterruptCSRFrameIndex(0),
+ &RISCV::GPRRegClass, Register(),
+ RISCV::NoSubRegister, MachineInstr::FrameDestroy);
BuildMI(MBB, MBBI, DL, TII->get(RISCV::CSRRW))
.addReg(RISCV::X0, RegState::Define)
.addImm(RISCVSysReg::mcause)
- .addReg(RISCV::X8, RegState::Kill)
+ .addReg(RISCV::X5, RegState::Kill)
.setMIFlag(MachineInstr::FrameDestroy);
- // X8 and X9 need to be restored to their values on function entry, which we
- // saved onto the stack in `emitSiFiveCLICPreemptibleSaves`.
- TII->loadRegFromStackSlot(MBB, MBBI, RISCV::X9,
- RVFI->getInterruptCSRFrameIndex(1),
- &RISCV::GPRRegClass, Register(),
- RISCV::NoSubRegister, MachineInstr::FrameDestroy);
- TII->loadRegFromStackSlot(MBB, MBBI, RISCV::X8,
- RVFI->getInterruptCSRFrameIndex(0),
+ // The ordinary reloads have finished. Recover the interrupted value of X5
+ // only after it has restored both CSRs.
+ TII->loadRegFromStackSlot(MBB, MBBI, RISCV::X5,
+ getSiFiveCLICScratchFrameIndex(MF),
&RISCV::GPRRegClass, Register(),
RISCV::NoSubRegister, MachineInstr::FrameDestroy);
+ if (needsDwarfCFI(MF))
+ CFIBuilder.buildRestore(RISCV::X5);
}
// Get the ID of the libcall used for spilling and restoring callee saved
@@ -593,6 +611,20 @@ getUnmanagedCSI(const MachineFunction &MF,
return NonLibcallCSI;
}
+// Exclude X5 from ordinary spills and restores for SiFive CLIC preemptible
+// handlers, which save and restore it explicitly.
+static SmallVector<CalleeSavedInfo, 8>
+getUnmanagedInterruptCSI(const MachineFunction &MF,
+ const std::vector<CalleeSavedInfo> &CSI,
+ bool ReverseOrder = false) {
+ auto InterruptCSI = getUnmanagedCSI(MF, CSI, ReverseOrder);
+ if (MF.getInfo<RISCVMachineFunctionInfo>()->isSiFivePreemptibleInterrupt(MF))
+ llvm::erase_if(InterruptCSI, [](const CalleeSavedInfo &CS) {
+ return CS.getReg() == RISCV::X5;
+ });
+ return InterruptCSI;
+}
+
static SmallVector<CalleeSavedInfo, 8>
getRVVCalleeSavedInfo(const MachineFunction &MF,
const std::vector<CalleeSavedInfo> &CSI) {
@@ -1025,9 +1057,9 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
// Skip to before the spills of scalar callee-saved registers
// FIXME: assumes exactly one instruction is used to restore each
// callee-saved register.
- MBBI =
- std::prev(MBBI, getRVVCalleeSavedInfo(MF, CSI).size() +
- getUnmanagedCSI(MF, CSI, PreferAscendingLS).size());
+ MBBI = std::prev(
+ MBBI, getRVVCalleeSavedInfo(MF, CSI).size() +
+ getUnmanagedInterruptCSI(MF, CSI, PreferAscendingLS).size());
CFIInstBuilder CFIBuilder(MBB, MBBI, MachineInstr::FrameSetup);
bool NeedsDwarfCFI = needsDwarfCFI(MF);
@@ -1146,14 +1178,15 @@ void RISCVFrameLowering::emitPrologue(MachineFunction &MF,
// to the stack, not before.
// FIXME: assumes exactly one instruction is used to save each callee-saved
// register.
- std::advance(MBBI, getUnmanagedCSI(MF, CSI, PreferAscendingLS).size());
+ std::advance(MBBI,
+ getUnmanagedInterruptCSI(MF, CSI, PreferAscendingLS).size());
CFIBuilder.setInsertPoint(MBBI);
// Iterate over list of callee-saved registers and emit .cfi_offset
// directives.
if (NeedsDwarfCFI) {
for (const CalleeSavedInfo &CS :
- getUnmanagedCSI(MF, CSI, PreferAscendingLS)) {
+ getUnmanagedInterruptCSI(MF, CSI, PreferAscendingLS)) {
MCRegister Reg = CS.getReg();
int64_t Offset = MFI.getObjectOffset(CS.getFrameIdx());
// Emit CFI for both sub-registers. The even register is at the base
@@ -1404,8 +1437,9 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
// FIXME: assumes exactly one instruction is used to restore each
// callee-saved register.
MBBI = std::next(FirstScalarCSRRestoreInsn,
- getUnmanagedCSI(MF, CSI, PreferAscendingLS).size());
+ getUnmanagedInterruptCSI(MF, CSI, PreferAscendingLS).size());
CFIBuilder.setInsertPoint(MBBI);
+ emitSiFiveCLICPreemptibleRestores(MF, MBB, MBBI, CFIBuilder, DL);
if (getLibCallID(MF, CSI) != -1) {
// tail __riscv_restore_[0-12] instruction is considered as a terminator,
@@ -1423,7 +1457,7 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
// Recover callee-saved registers.
if (NeedsDwarfCFI) {
for (const CalleeSavedInfo &CS :
- getUnmanagedCSI(MF, CSI, PreferAscendingLS)) {
+ getUnmanagedInterruptCSI(MF, CSI, PreferAscendingLS)) {
MCRegister Reg = CS.getReg();
// Emit CFI for both sub-registers.
if (RISCV::GPRPairRegClass.contains(Reg)) {
@@ -1468,8 +1502,6 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
}
}
- emitSiFiveCLICPreemptibleRestores(MF, MBB, MBBI, DL);
-
// Deallocate stack if StackSize isn't a zero yet. If this is a QCI interrupt
// function, there will be a leftover offset which is deallocated by
// `QC.C.MILEAVERET`, otherwise getQCIInterruptStackSize() will be 0.
@@ -1650,7 +1682,10 @@ RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
MaxCSFI = std::max(CSI.front().getFrameIdx(), CSI.back().getFrameIdx());
}
- if (FI >= MinCSFI && FI <= MaxCSFI) {
+ bool IsInterruptCSR = RVFI->isSiFivePreemptibleInterrupt(MF) &&
+ (FI == RVFI->getInterruptCSRFrameIndex(0) ||
+ FI == RVFI->getInterruptCSRFrameIndex(1));
+ if ((FI >= MinCSFI && FI <= MaxCSFI) || IsInterruptCSR) {
FrameReg = SPReg;
if (FirstSPAdjustAmount)
@@ -1868,8 +1903,12 @@ void RISCVFrameLowering::determineCalleeSaves(MachineFunction &MF,
if (hasBP(MF))
SavedRegs.set(RISCVABI::getBPReg());
- // When using cm.push/pop we must save X27 if we save X26.
auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
+ // X5 is used as a temporary for saving and restoring `mcause` and `mepc`.
+ if (RVFI->isSiFivePreemptibleInterrupt(MF))
+ SavedRegs.set(RISCV::X5);
+
+ // When using cm.push/pop we must save X27 if we save X26.
if (RVFI->isPushable(MF) && SavedRegs.test(RISCV::X26))
SavedRegs.set(RISCV::X27);
@@ -2491,10 +2530,10 @@ bool RISCVFrameLowering::spillCalleeSavedRegisters(
// Manually spill values not spilled by libcall & Push/Pop.
const auto &UnmanagedCSI =
- getUnmanagedCSI(*MF, CSI, STI.preferAscendingLoadStore());
+ getUnmanagedInterruptCSI(*MF, CSI, STI.preferAscendingLoadStore());
const auto &RVVCSI = getRVVCalleeSavedInfo(*MF, CSI);
- auto storeRegsToStackSlots = [&](decltype(UnmanagedCSI) CSInfo) {
+ auto storeRegsToStackSlots = [&](ArrayRef<CalleeSavedInfo> CSInfo) {
for (auto &CS : CSInfo) {
// Insert the spill to the stack frame.
MCRegister Reg = CS.getReg();
@@ -2585,10 +2624,10 @@ bool RISCVFrameLowering::restoreCalleeSavedRegisters(
// loading RA and return by RA. loadRegFromStackSlot can insert
// multiple instructions.
const auto &UnmanagedCSI =
- getUnmanagedCSI(*MF, CSI, STI.preferAscendingLoadStore());
+ getUnmanagedInterruptCSI(*MF, CSI, STI.preferAscendingLoadStore());
const auto &RVVCSI = getRVVCalleeSavedInfo(*MF, CSI);
- auto loadRegFromStackSlot = [&](decltype(UnmanagedCSI) CSInfo) {
+ auto loadRegFromStackSlot = [&](ArrayRef<CalleeSavedInfo> CSInfo) {
for (auto &CS : CSInfo) {
MCRegister Reg = CS.getReg();
const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 7a5905fc4b3ea5..f408f6da608215 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -27723,12 +27723,6 @@ SDValue RISCVTargetLowering::LowerFormalArguments(
if (Kind == "rnmi" && !Subtarget.hasStdExtSmrnmi())
reportFatalUsageError("'rnmi' interrupt kind requires Srnmi extension");
- const TargetFrameLowering *TFI = Subtarget.getFrameLowering();
- if (Kind.starts_with("SiFive-CLIC-preemptible") && TFI->hasFP(MF))
- Func.getContext().diagnose(DiagnosticInfoUnsupported{
- Func,
- "'SiFive-CLIC-preemptible' interrupt functions cannot have a frame "
- "pointer"});
}
EVT PtrVT = getPointerTy(DAG.getDataLayout());
diff --git a/llvm/test/CodeGen/RISCV/sifive-interrupt-attr-err.ll b/llvm/test/CodeGen/RISCV/sifive-interrupt-attr-err.ll
deleted file mode 100644
index f0e1f16cf6e54b..00000000000000
--- a/llvm/test/CodeGen/RISCV/sifive-interrupt-attr-err.ll
+++ /dev/null
@@ -1,12 +0,0 @@
-; RUN: not llc -mtriple riscv32-unknown-elf -mattr=+experimental-xsfmclic -o - %s 2>&1 \
-; RUN: | FileCheck %s
-; RUN: not llc -mtriple riscv64-unknown-elf -mattr=+experimental-xsfmclic -o - %s 2>&1 \
-; RUN: | FileCheck %s
-
-;; Test that these report regular errors.
-
-; CHECK: error: <unknown>:0:0: in function preemptible void (): 'SiFive-CLIC-preemptible' interrupt functions cannot have a frame pointer
-
-define void @preemptible() "interrupt"="SiFive-CLIC-preemptible" "frame-pointer"="all" {
- ret void
-}
diff --git a/llvm/test/CodeGen/RISCV/sifive-interrupt-attr.ll b/llvm/test/CodeGen/RISCV/sifive-interrupt-attr.ll
index a7dead74716777..7afcc28c1343d8 100644
--- a/llvm/test/CodeGen/RISCV/sifive-interrupt-attr.ll
+++ b/llvm/test/CodeGen/RISCV/sifive-interrupt-attr.ll
@@ -11,7 +11,7 @@
; "preemptible" means that `mcause` and `mepc` should be saved and interrupts
; should be re-enabled by setting a bit in `mstatus`.
-; FIXME: A lot of the CFI information here is wrong.
+; FIXME: CFI information for the stack swap and CSRs is still missing.
define void @stack_swap_empty() "interrupt"="SiFive-CLIC-stack-swap" {
; RV32-LABEL: stack_swap_empty:
@@ -78,35 +78,43 @@ define void @preemptible_empty() "interrupt"="SiFive-CLIC-preemptible" {
; RV32: # %bb.0:
; RV32-NEXT: addi sp, sp, -16
; RV32-NEXT: .cfi_def_cfa_offset 16
-; RV32-NEXT: sw s0, 12(sp) # 4-byte Folded Spill
-; RV32-NEXT: sw s1, 8(sp) # 4-byte Folded Spill
-; RV32-NEXT: csrr s0, mcause
-; RV32-NEXT: csrr s1, mepc
+; RV32-NEXT: sw t0, 4(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -12
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
; RV32-NEXT: csrsi mstatus, 8
+; RV32-NEXT: sw t0, 8(sp) # 4-byte Folded Spill
+; RV32-NEXT: lw t0, 8(sp) # 4-byte Folded Reload
; RV32-NEXT: csrci mstatus, 8
-; RV32-NEXT: csrw mepc, s1
-; RV32-NEXT: csrw mcause, s0
-; RV32-NEXT: lw s1, 8(sp) # 4-byte Folded Reload
-; RV32-NEXT: lw s0, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 4(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore t0
; RV32-NEXT: addi sp, sp, 16
; RV32-NEXT: .cfi_def_cfa_offset 0
; RV32-NEXT: mret
;
; RV64-LABEL: preemptible_empty:
; RV64: # %bb.0:
-; RV64-NEXT: addi sp, sp, -16
-; RV64-NEXT: .cfi_def_cfa_offset 16
-; RV64-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
-; RV64-NEXT: sd s1, 0(sp) # 8-byte Folded Spill
-; RV64-NEXT: csrr s0, mcause
-; RV64-NEXT: csrr s1, mepc
+; RV64-NEXT: addi sp, sp, -32
+; RV64-NEXT: .cfi_def_cfa_offset 32
+; RV64-NEXT: sd t0, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -24
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 24(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
; RV64-NEXT: csrsi mstatus, 8
+; RV64-NEXT: sd t0, 16(sp) # 8-byte Folded Spill
+; RV64-NEXT: ld t0, 16(sp) # 8-byte Folded Reload
; RV64-NEXT: csrci mstatus, 8
-; RV64-NEXT: csrw mepc, s1
-; RV64-NEXT: csrw mcause, s0
-; RV64-NEXT: ld s1, 0(sp) # 8-byte Folded Reload
-; RV64-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
-; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 24(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore t0
+; RV64-NEXT: addi sp, sp, 32
; RV64-NEXT: .cfi_def_cfa_offset 0
; RV64-NEXT: mret
ret void
@@ -118,16 +126,20 @@ define void @both_empty() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV32-NEXT: csrrw sp, sf.mscratchcsw, sp
; RV32-NEXT: addi sp, sp, -16
; RV32-NEXT: .cfi_def_cfa_offset 16
-; RV32-NEXT: sw s0, 12(sp) # 4-byte Folded Spill
-; RV32-NEXT: sw s1, 8(sp) # 4-byte Folded Spill
-; RV32-NEXT: csrr s0, mcause
-; RV32-NEXT: csrr s1, mepc
+; RV32-NEXT: sw t0, 4(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -12
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
; RV32-NEXT: csrsi mstatus, 8
+; RV32-NEXT: sw t0, 8(sp) # 4-byte Folded Spill
+; RV32-NEXT: lw t0, 8(sp) # 4-byte Folded Reload
; RV32-NEXT: csrci mstatus, 8
-; RV32-NEXT: csrw mepc, s1
-; RV32-NEXT: csrw mcause, s0
-; RV32-NEXT: lw s1, 8(sp) # 4-byte Folded Reload
-; RV32-NEXT: lw s0, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 4(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore t0
; RV32-NEXT: addi sp, sp, 16
; RV32-NEXT: .cfi_def_cfa_offset 0
; RV32-NEXT: csrrw sp, sf.mscratchcsw, sp
@@ -136,19 +148,23 @@ define void @both_empty() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV64-LABEL: both_empty:
; RV64: # %bb.0:
; RV64-NEXT: csrrw sp, sf.mscratchcsw, sp
-; RV64-NEXT: addi sp, sp, -16
-; RV64-NEXT: .cfi_def_cfa_offset 16
-; RV64-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
-; RV64-NEXT: sd s1, 0(sp) # 8-byte Folded Spill
-; RV64-NEXT: csrr s0, mcause
-; RV64-NEXT: csrr s1, mepc
+; RV64-NEXT: addi sp, sp, -32
+; RV64-NEXT: .cfi_def_cfa_offset 32
+; RV64-NEXT: sd t0, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -24
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 24(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
; RV64-NEXT: csrsi mstatus, 8
+; RV64-NEXT: sd t0, 16(sp) # 8-byte Folded Spill
+; RV64-NEXT: ld t0, 16(sp) # 8-byte Folded Reload
; RV64-NEXT: csrci mstatus, 8
-; RV64-NEXT: csrw mepc, s1
-; RV64-NEXT: csrw mcause, s0
-; RV64-NEXT: ld s1, 0(sp) # 8-byte Folded Reload
-; RV64-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
-; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 24(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore t0
+; RV64-NEXT: addi sp, sp, 32
; RV64-NEXT: .cfi_def_cfa_offset 0
; RV64-NEXT: csrrw sp, sf.mscratchcsw, sp
; RV64-NEXT: mret
@@ -484,13 +500,14 @@ define void @preeemptible_caller() "interrupt"="SiFive-CLIC-preemptible" {
; RV32: # %bb.0:
; RV32-NEXT: addi sp, sp, -80
; RV32-NEXT: .cfi_def_cfa_offset 80
-; RV32-NEXT: sw s0, 76(sp) # 4-byte Folded Spill
-; RV32-NEXT: sw s1, 72(sp) # 4-byte Folded Spill
-; RV32-NEXT: csrr s0, mcause
-; RV32-NEXT: csrr s1, mepc
+; RV32-NEXT: sw t0, 64(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -16
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 76(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
; RV32-NEXT: csrsi mstatus, 8
+; RV32-NEXT: sw t0, 72(sp) # 4-byte Folded Spill
; RV32-NEXT: sw ra, 68(sp) # 4-byte Folded Spill
-; RV32-NEXT: sw t0, 64(sp) # 4-byte Folded Spill
; RV32-NEXT: sw t1, 60(sp) # 4-byte Folded Spill
; RV32-NEXT: sw t2, 56(sp) # 4-byte Folded Spill
; RV32-NEXT: sw a0, 52(sp) # 4-byte Folded Spill
@@ -506,7 +523,6 @@ define void @preeemptible_caller() "interrupt"="SiFive-CLIC-preemptible" {
; RV32-NEXT: sw t5, 12(sp) # 4-byte Folded Spill
; RV32-NEXT: sw t6, 8(sp) # 4-byte Folded Spill
; RV32-NEXT: .cfi_offset ra, -12
-; RV32-NEXT: .cfi_offset t0, -16
; RV32-NEXT: .cfi_offset t1, -20
; RV32-NEXT: .cfi_offset t2, -24
; RV32-NEXT: .cfi_offset a0, -28
@@ -523,7 +539,6 @@ define void @preeemptible_caller() "interrupt"="SiFive-CLIC-preemptible" {
; RV32-NEXT: .cfi_offset t6, -72
; RV32-NEXT: call callee
; RV32-NEXT: lw ra, 68(sp) # 4-byte Folded Reload
-; RV32-NEXT: lw t0, 64(sp) # 4-byte Folded Reload
; RV32-NEXT: lw t1, 60(sp) # 4-byte Folded Reload
; RV32-NEXT: lw t2, 56(sp) # 4-byte Folded Reload
; RV32-NEXT: lw a0, 52(sp) # 4-byte Folded Reload
@@ -538,8 +553,14 @@ define void @preeemptible_caller() "interrupt"="SiFive-CLIC-preemptible" {
; RV32-NEXT: lw t4, 16(sp) # 4-byte Folded Reload
; RV32-NEXT: lw t5, 12(sp) # 4-byte Folded Reload
; RV32-NEXT: lw t6, 8(sp) # 4-byte Folded Reload
-; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: lw t0, 72(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrci mstatus, 8
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 76(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 64(sp) # 4-byte Folded Reload
; RV32-NEXT: .cfi_restore t0
+; RV32-NEXT: .cfi_restore ra
; RV32-NEXT: .cfi_restore t1
; RV32-NEXT: .cfi_restore t2
; RV32-NEXT: .cfi_restore a0
@@ -554,11 +575,6 @@ define void @preeemptible_caller() "interrupt"="SiFive-CLIC-preemptible" {
; RV32-NEXT: .cfi_restore t4
; RV32-NEXT: .cfi_restore t5
; RV32-NEXT: .cfi_restore t6
-; RV32-NEXT: csrci mstatus, 8
-; RV32-NEXT: csrw mepc, s1
-; RV32-NEXT: csrw mcause, s0
-; RV32-NEXT: lw s1, 72(sp) # 4-byte Folded Reload
-; RV32-NEXT: lw s0, 76(sp) # 4-byte Folded Reload
; RV32-NEXT: addi sp, sp, 80
; RV32-NEXT: .cfi_def_cfa_offset 0
; RV32-NEXT: mret
@@ -567,13 +583,14 @@ define void @preeemptible_caller() "interrupt"="SiFive-CLIC-preemptible" {
; RV64: # %bb.0:
; RV64-NEXT: addi sp, sp, -144
; RV64-NEXT: .cfi_def_cfa_offset 144
-; RV64-NEXT: sd s0, 136(sp) # 8-byte Folded Spill
-; RV64-NEXT: sd s1, 128(sp) # 8-byte Folded Spill
-; RV64-NEXT: csrr s0, mcause
-; RV64-NEXT: csrr s1, mepc
+; RV64-NEXT: sd t0, 112(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -32
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 136(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
; RV64-NEXT: csrsi mstatus, 8
+; RV64-NEXT: sd t0, 128(sp) # 8-byte Folded Spill
; RV64-NEXT: sd ra, 120(sp) # 8-byte Folded Spill
-; RV64-NEXT: sd t0, 112(sp) # 8-byte Folded Spill
; RV64-NEXT: sd t1, 104(sp) # 8-byte Folded Spill
; RV64-NEXT: sd t2, 96(sp) # 8-byte Folded Spill
; RV64-NEXT: sd a0, 88(sp) # 8-byte Folded Spill
@@ -589,7 +606,6 @@ define void @preeemptible_caller() "interrupt"="SiFive-CLIC-preemptible" {
; RV64-NEXT: sd t5, 8(sp) # 8-byte Folded Spill
; RV64-NEXT: sd t6, 0(sp) # 8-byte Folded Spill
; RV64-NEXT: .cfi_offset ra, -24
-; RV64-NEXT: .cfi_offset t0, -32
; RV64-NEXT: .cfi_offset t1, -40
; RV64-NEXT: .cfi_offset t2, -48
; RV64-NEXT: .cfi_offset a0, -56
@@ -606,7 +622,6 @@ define void @preeemptible_caller() "interrupt"="SiFive-CLIC-preemptible" {
; RV64-NEXT: .cfi_offset t6, -144
; RV64-NEXT: call callee
; RV64-NEXT: ld ra, 120(sp) # 8-byte Folded Reload
-; RV64-NEXT: ld t0, 112(sp) # 8-byte Folded Reload
; RV64-NEXT: ld t1, 104(sp) # 8-byte Folded Reload
; RV64-NEXT: ld t2, 96(sp) # 8-byte Folded Reload
; RV64-NEXT: ld a0, 88(sp) # 8-byte Folded Reload
@@ -621,8 +636,14 @@ define void @preeemptible_caller() "interrupt"="SiFive-CLIC-preemptible" {
; RV64-NEXT: ld t4, 16(sp) # 8-byte Folded Reload
; RV64-NEXT: ld t5, 8(sp) # 8-byte Folded Reload
; RV64-NEXT: ld t6, 0(sp) # 8-byte Folded Reload
-; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: ld t0, 128(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrci mstatus, 8
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 136(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 112(sp) # 8-byte Folded Reload
; RV64-NEXT: .cfi_restore t0
+; RV64-NEXT: .cfi_restore ra
; RV64-NEXT: .cfi_restore t1
; RV64-NEXT: .cfi_restore t2
; RV64-NEXT: .cfi_restore a0
@@ -637,11 +658,6 @@ define void @preeemptible_caller() "interrupt"="SiFive-CLIC-preemptible" {
; RV64-NEXT: .cfi_restore t4
; RV64-NEXT: .cfi_restore t5
; RV64-NEXT: .cfi_restore t6
-; RV64-NEXT: csrci mstatus, 8
-; RV64-NEXT: csrw mepc, s1
-; RV64-NEXT: csrw mcause, s0
-; RV64-NEXT: ld s1, 128(sp) # 8-byte Folded Reload
-; RV64-NEXT: ld s0, 136(sp) # 8-byte Folded Reload
; RV64-NEXT: addi sp, sp, 144
; RV64-NEXT: .cfi_def_cfa_offset 0
; RV64-NEXT: mret
@@ -655,13 +671,14 @@ define void @both_caller() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV32-NEXT: csrrw sp, sf.mscratchcsw, sp
; RV32-NEXT: addi sp, sp, -80
; RV32-NEXT: .cfi_def_cfa_offset 80
-; RV32-NEXT: sw s0, 76(sp) # 4-byte Folded Spill
-; RV32-NEXT: sw s1, 72(sp) # 4-byte Folded Spill
-; RV32-NEXT: csrr s0, mcause
-; RV32-NEXT: csrr s1, mepc
+; RV32-NEXT: sw t0, 64(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -16
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 76(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
; RV32-NEXT: csrsi mstatus, 8
+; RV32-NEXT: sw t0, 72(sp) # 4-byte Folded Spill
; RV32-NEXT: sw ra, 68(sp) # 4-byte Folded Spill
-; RV32-NEXT: sw t0, 64(sp) # 4-byte Folded Spill
; RV32-NEXT: sw t1, 60(sp) # 4-byte Folded Spill
; RV32-NEXT: sw t2, 56(sp) # 4-byte Folded Spill
; RV32-NEXT: sw a0, 52(sp) # 4-byte Folded Spill
@@ -677,7 +694,6 @@ define void @both_caller() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV32-NEXT: sw t5, 12(sp) # 4-byte Folded Spill
; RV32-NEXT: sw t6, 8(sp) # 4-byte Folded Spill
; RV32-NEXT: .cfi_offset ra, -12
-; RV32-NEXT: .cfi_offset t0, -16
; RV32-NEXT: .cfi_offset t1, -20
; RV32-NEXT: .cfi_offset t2, -24
; RV32-NEXT: .cfi_offset a0, -28
@@ -694,7 +710,6 @@ define void @both_caller() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV32-NEXT: .cfi_offset t6, -72
; RV32-NEXT: call callee
; RV32-NEXT: lw ra, 68(sp) # 4-byte Folded Reload
-; RV32-NEXT: lw t0, 64(sp) # 4-byte Folded Reload
; RV32-NEXT: lw t1, 60(sp) # 4-byte Folded Reload
; RV32-NEXT: lw t2, 56(sp) # 4-byte Folded Reload
; RV32-NEXT: lw a0, 52(sp) # 4-byte Folded Reload
@@ -709,8 +724,14 @@ define void @both_caller() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV32-NEXT: lw t4, 16(sp) # 4-byte Folded Reload
; RV32-NEXT: lw t5, 12(sp) # 4-byte Folded Reload
; RV32-NEXT: lw t6, 8(sp) # 4-byte Folded Reload
-; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: lw t0, 72(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrci mstatus, 8
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 76(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 64(sp) # 4-byte Folded Reload
; RV32-NEXT: .cfi_restore t0
+; RV32-NEXT: .cfi_restore ra
; RV32-NEXT: .cfi_restore t1
; RV32-NEXT: .cfi_restore t2
; RV32-NEXT: .cfi_restore a0
@@ -725,11 +746,6 @@ define void @both_caller() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV32-NEXT: .cfi_restore t4
; RV32-NEXT: .cfi_restore t5
; RV32-NEXT: .cfi_restore t6
-; RV32-NEXT: csrci mstatus, 8
-; RV32-NEXT: csrw mepc, s1
-; RV32-NEXT: csrw mcause, s0
-; RV32-NEXT: lw s1, 72(sp) # 4-byte Folded Reload
-; RV32-NEXT: lw s0, 76(sp) # 4-byte Folded Reload
; RV32-NEXT: addi sp, sp, 80
; RV32-NEXT: .cfi_def_cfa_offset 0
; RV32-NEXT: csrrw sp, sf.mscratchcsw, sp
@@ -740,13 +756,14 @@ define void @both_caller() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV64-NEXT: csrrw sp, sf.mscratchcsw, sp
; RV64-NEXT: addi sp, sp, -144
; RV64-NEXT: .cfi_def_cfa_offset 144
-; RV64-NEXT: sd s0, 136(sp) # 8-byte Folded Spill
-; RV64-NEXT: sd s1, 128(sp) # 8-byte Folded Spill
-; RV64-NEXT: csrr s0, mcause
-; RV64-NEXT: csrr s1, mepc
+; RV64-NEXT: sd t0, 112(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -32
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 136(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
; RV64-NEXT: csrsi mstatus, 8
+; RV64-NEXT: sd t0, 128(sp) # 8-byte Folded Spill
; RV64-NEXT: sd ra, 120(sp) # 8-byte Folded Spill
-; RV64-NEXT: sd t0, 112(sp) # 8-byte Folded Spill
; RV64-NEXT: sd t1, 104(sp) # 8-byte Folded Spill
; RV64-NEXT: sd t2, 96(sp) # 8-byte Folded Spill
; RV64-NEXT: sd a0, 88(sp) # 8-byte Folded Spill
@@ -762,7 +779,6 @@ define void @both_caller() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV64-NEXT: sd t5, 8(sp) # 8-byte Folded Spill
; RV64-NEXT: sd t6, 0(sp) # 8-byte Folded Spill
; RV64-NEXT: .cfi_offset ra, -24
-; RV64-NEXT: .cfi_offset t0, -32
; RV64-NEXT: .cfi_offset t1, -40
; RV64-NEXT: .cfi_offset t2, -48
; RV64-NEXT: .cfi_offset a0, -56
@@ -779,7 +795,6 @@ define void @both_caller() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV64-NEXT: .cfi_offset t6, -144
; RV64-NEXT: call callee
; RV64-NEXT: ld ra, 120(sp) # 8-byte Folded Reload
-; RV64-NEXT: ld t0, 112(sp) # 8-byte Folded Reload
; RV64-NEXT: ld t1, 104(sp) # 8-byte Folded Reload
; RV64-NEXT: ld t2, 96(sp) # 8-byte Folded Reload
; RV64-NEXT: ld a0, 88(sp) # 8-byte Folded Reload
@@ -794,8 +809,14 @@ define void @both_caller() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV64-NEXT: ld t4, 16(sp) # 8-byte Folded Reload
; RV64-NEXT: ld t5, 8(sp) # 8-byte Folded Reload
; RV64-NEXT: ld t6, 0(sp) # 8-byte Folded Reload
-; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: ld t0, 128(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrci mstatus, 8
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 136(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 112(sp) # 8-byte Folded Reload
; RV64-NEXT: .cfi_restore t0
+; RV64-NEXT: .cfi_restore ra
; RV64-NEXT: .cfi_restore t1
; RV64-NEXT: .cfi_restore t2
; RV64-NEXT: .cfi_restore a0
@@ -810,11 +831,6 @@ define void @both_caller() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV64-NEXT: .cfi_restore t4
; RV64-NEXT: .cfi_restore t5
; RV64-NEXT: .cfi_restore t6
-; RV64-NEXT: csrci mstatus, 8
-; RV64-NEXT: csrw mepc, s1
-; RV64-NEXT: csrw mcause, s0
-; RV64-NEXT: ld s1, 128(sp) # 8-byte Folded Reload
-; RV64-NEXT: ld s0, 136(sp) # 8-byte Folded Reload
; RV64-NEXT: addi sp, sp, 144
; RV64-NEXT: .cfi_def_cfa_offset 0
; RV64-NEXT: csrrw sp, sf.mscratchcsw, sp
@@ -928,57 +944,65 @@ define void @stack_swap_clobber_fp() "interrupt"="SiFive-CLIC-stack-swap" "frame
define void @preemptible_clobber() "interrupt"="SiFive-CLIC-preemptible" {
; RV32-LABEL: preemptible_clobber:
; RV32: # %bb.0:
-; RV32-NEXT: addi sp, sp, -16
-; RV32-NEXT: .cfi_def_cfa_offset 16
-; RV32-NEXT: sw s0, 12(sp) # 4-byte Folded Spill
-; RV32-NEXT: sw s1, 8(sp) # 4-byte Folded Spill
-; RV32-NEXT: csrr s0, mcause
-; RV32-NEXT: csrr s1, mepc
+; RV32-NEXT: addi sp, sp, -32
+; RV32-NEXT: .cfi_def_cfa_offset 32
+; RV32-NEXT: sw t0, 20(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -12
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 28(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
; RV32-NEXT: csrsi mstatus, 8
-; RV32-NEXT: sw s0, 4(sp) # 4-byte Folded Spill
-; RV32-NEXT: sw s1, 0(sp) # 4-byte Folded Spill
-; RV32-NEXT: .cfi_offset s0, -12
-; RV32-NEXT: .cfi_offset s1, -16
+; RV32-NEXT: sw t0, 24(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 16(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s1, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset s0, -16
+; RV32-NEXT: .cfi_offset s1, -20
; RV32-NEXT: #APP
; RV32-NEXT: #NO_APP
-; RV32-NEXT: lw s0, 4(sp) # 4-byte Folded Reload
-; RV32-NEXT: lw s1, 0(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 16(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s1, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t0, 24(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrci mstatus, 8
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 28(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 20(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore t0
; RV32-NEXT: .cfi_restore s0
; RV32-NEXT: .cfi_restore s1
-; RV32-NEXT: csrci mstatus, 8
-; RV32-NEXT: csrw mepc, s1
-; RV32-NEXT: csrw mcause, s0
-; RV32-NEXT: lw s1, 8(sp) # 4-byte Folded Reload
-; RV32-NEXT: lw s0, 12(sp) # 4-byte Folded Reload
-; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: addi sp, sp, 32
; RV32-NEXT: .cfi_def_cfa_offset 0
; RV32-NEXT: mret
;
; RV64-LABEL: preemptible_clobber:
; RV64: # %bb.0:
-; RV64-NEXT: addi sp, sp, -32
-; RV64-NEXT: .cfi_def_cfa_offset 32
-; RV64-NEXT: sd s0, 24(sp) # 8-byte Folded Spill
-; RV64-NEXT: sd s1, 16(sp) # 8-byte Folded Spill
-; RV64-NEXT: csrr s0, mcause
-; RV64-NEXT: csrr s1, mepc
+; RV64-NEXT: addi sp, sp, -48
+; RV64-NEXT: .cfi_def_cfa_offset 48
+; RV64-NEXT: sd t0, 24(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -24
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 40(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
; RV64-NEXT: csrsi mstatus, 8
-; RV64-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
-; RV64-NEXT: sd s1, 0(sp) # 8-byte Folded Spill
-; RV64-NEXT: .cfi_offset s0, -24
-; RV64-NEXT: .cfi_offset s1, -32
+; RV64-NEXT: sd t0, 32(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset s0, -32
+; RV64-NEXT: .cfi_offset s1, -40
; RV64-NEXT: #APP
; RV64-NEXT: #NO_APP
-; RV64-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
-; RV64-NEXT: ld s1, 0(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t0, 32(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrci mstatus, 8
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 40(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 24(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore t0
; RV64-NEXT: .cfi_restore s0
; RV64-NEXT: .cfi_restore s1
-; RV64-NEXT: csrci mstatus, 8
-; RV64-NEXT: csrw mepc, s1
-; RV64-NEXT: csrw mcause, s0
-; RV64-NEXT: ld s1, 16(sp) # 8-byte Folded Reload
-; RV64-NEXT: ld s0, 24(sp) # 8-byte Folded Reload
-; RV64-NEXT: addi sp, sp, 32
+; RV64-NEXT: addi sp, sp, 48
; RV64-NEXT: .cfi_def_cfa_offset 0
; RV64-NEXT: mret
call void asm sideeffect "", "~{x8},~{x9}"() #4
@@ -989,29 +1013,33 @@ define void @both_clobber() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV32-LABEL: both_clobber:
; RV32: # %bb.0:
; RV32-NEXT: csrrw sp, sf.mscratchcsw, sp
-; RV32-NEXT: addi sp, sp, -16
-; RV32-NEXT: .cfi_def_cfa_offset 16
-; RV32-NEXT: sw s0, 12(sp) # 4-byte Folded Spill
-; RV32-NEXT: sw s1, 8(sp) # 4-byte Folded Spill
-; RV32-NEXT: csrr s0, mcause
-; RV32-NEXT: csrr s1, mepc
+; RV32-NEXT: addi sp, sp, -32
+; RV32-NEXT: .cfi_def_cfa_offset 32
+; RV32-NEXT: sw t0, 20(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -12
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 28(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
; RV32-NEXT: csrsi mstatus, 8
-; RV32-NEXT: sw s0, 4(sp) # 4-byte Folded Spill
-; RV32-NEXT: sw s1, 0(sp) # 4-byte Folded Spill
-; RV32-NEXT: .cfi_offset s0, -12
-; RV32-NEXT: .cfi_offset s1, -16
+; RV32-NEXT: sw t0, 24(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 16(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s1, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset s0, -16
+; RV32-NEXT: .cfi_offset s1, -20
; RV32-NEXT: #APP
; RV32-NEXT: #NO_APP
-; RV32-NEXT: lw s0, 4(sp) # 4-byte Folded Reload
-; RV32-NEXT: lw s1, 0(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 16(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s1, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t0, 24(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrci mstatus, 8
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 28(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 20(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore t0
; RV32-NEXT: .cfi_restore s0
; RV32-NEXT: .cfi_restore s1
-; RV32-NEXT: csrci mstatus, 8
-; RV32-NEXT: csrw mepc, s1
-; RV32-NEXT: csrw mcause, s0
-; RV32-NEXT: lw s1, 8(sp) # 4-byte Folded Reload
-; RV32-NEXT: lw s0, 12(sp) # 4-byte Folded Reload
-; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: addi sp, sp, 32
; RV32-NEXT: .cfi_def_cfa_offset 0
; RV32-NEXT: csrrw sp, sf.mscratchcsw, sp
; RV32-NEXT: mret
@@ -1019,32 +1047,223 @@ define void @both_clobber() "interrupt"="SiFive-CLIC-preemptible-stack-swap" {
; RV64-LABEL: both_clobber:
; RV64: # %bb.0:
; RV64-NEXT: csrrw sp, sf.mscratchcsw, sp
-; RV64-NEXT: addi sp, sp, -32
-; RV64-NEXT: .cfi_def_cfa_offset 32
-; RV64-NEXT: sd s0, 24(sp) # 8-byte Folded Spill
-; RV64-NEXT: sd s1, 16(sp) # 8-byte Folded Spill
-; RV64-NEXT: csrr s0, mcause
-; RV64-NEXT: csrr s1, mepc
+; RV64-NEXT: addi sp, sp, -48
+; RV64-NEXT: .cfi_def_cfa_offset 48
+; RV64-NEXT: sd t0, 24(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -24
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 40(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
; RV64-NEXT: csrsi mstatus, 8
-; RV64-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
-; RV64-NEXT: sd s1, 0(sp) # 8-byte Folded Spill
-; RV64-NEXT: .cfi_offset s0, -24
-; RV64-NEXT: .cfi_offset s1, -32
+; RV64-NEXT: sd t0, 32(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s0, 16(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s1, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset s0, -32
+; RV64-NEXT: .cfi_offset s1, -40
; RV64-NEXT: #APP
; RV64-NEXT: #NO_APP
-; RV64-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
-; RV64-NEXT: ld s1, 0(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t0, 32(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrci mstatus, 8
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 40(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 24(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore t0
; RV64-NEXT: .cfi_restore s0
; RV64-NEXT: .cfi_restore s1
-; RV64-NEXT: csrci mstatus, 8
-; RV64-NEXT: csrw mepc, s1
-; RV64-NEXT: csrw mcause, s0
-; RV64-NEXT: ld s1, 16(sp) # 8-byte Folded Reload
-; RV64-NEXT: ld s0, 24(sp) # 8-byte Folded Reload
-; RV64-NEXT: addi sp, sp, 32
+; RV64-NEXT: addi sp, sp, 48
; RV64-NEXT: .cfi_def_cfa_offset 0
; RV64-NEXT: csrrw sp, sf.mscratchcsw, sp
; RV64-NEXT: mret
call void asm sideeffect "", "~{x8},~{x9}"() #4
ret void
}
+
+declare void @use(ptr)
+
+define void @large_frame() "interrupt"="SiFive-CLIC-preemptible" "frame-pointer"="none" {
+; RV32-LABEL: large_frame:
+; RV32: # %bb.0:
+; RV32-NEXT: addi sp, sp, -2032
+; RV32-NEXT: .cfi_def_cfa_offset 2032
+; RV32-NEXT: sw t0, 2016(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -16
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 2028(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
+; RV32-NEXT: csrsi mstatus, 8
+; RV32-NEXT: sw t0, 2024(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw ra, 2020(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t1, 2012(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t2, 2008(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a0, 2004(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a1, 2000(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a2, 1996(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a3, 1992(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a4, 1988(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a5, 1984(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a6, 1980(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a7, 1976(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t3, 1972(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t4, 1968(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t5, 1964(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t6, 1960(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -12
+; RV32-NEXT: .cfi_offset t1, -20
+; RV32-NEXT: .cfi_offset t2, -24
+; RV32-NEXT: .cfi_offset a0, -28
+; RV32-NEXT: .cfi_offset a1, -32
+; RV32-NEXT: .cfi_offset a2, -36
+; RV32-NEXT: .cfi_offset a3, -40
+; RV32-NEXT: .cfi_offset a4, -44
+; RV32-NEXT: .cfi_offset a5, -48
+; RV32-NEXT: .cfi_offset a6, -52
+; RV32-NEXT: .cfi_offset a7, -56
+; RV32-NEXT: .cfi_offset t3, -60
+; RV32-NEXT: .cfi_offset t4, -64
+; RV32-NEXT: .cfi_offset t5, -68
+; RV32-NEXT: .cfi_offset t6, -72
+; RV32-NEXT: addi sp, sp, -2048
+; RV32-NEXT: addi sp, sp, -112
+; RV32-NEXT: .cfi_def_cfa_offset 4192
+; RV32-NEXT: addi a0, sp, 16
+; RV32-NEXT: call use
+; RV32-NEXT: addi sp, sp, 2032
+; RV32-NEXT: addi sp, sp, 128
+; RV32-NEXT: .cfi_def_cfa_offset 2032
+; RV32-NEXT: lw ra, 2020(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t1, 2012(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t2, 2008(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a0, 2004(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a1, 2000(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a2, 1996(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a3, 1992(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a4, 1988(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a5, 1984(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a6, 1980(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a7, 1976(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t3, 1972(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t4, 1968(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t5, 1964(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t6, 1960(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t0, 2024(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrci mstatus, 8
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 2028(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 2016(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore t0
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore t1
+; RV32-NEXT: .cfi_restore t2
+; RV32-NEXT: .cfi_restore a0
+; RV32-NEXT: .cfi_restore a1
+; RV32-NEXT: .cfi_restore a2
+; RV32-NEXT: .cfi_restore a3
+; RV32-NEXT: .cfi_restore a4
+; RV32-NEXT: .cfi_restore a5
+; RV32-NEXT: .cfi_restore a6
+; RV32-NEXT: .cfi_restore a7
+; RV32-NEXT: .cfi_restore t3
+; RV32-NEXT: .cfi_restore t4
+; RV32-NEXT: .cfi_restore t5
+; RV32-NEXT: .cfi_restore t6
+; RV32-NEXT: addi sp, sp, 2032
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: mret
+;
+; RV64-LABEL: large_frame:
+; RV64: # %bb.0:
+; RV64-NEXT: addi sp, sp, -2032
+; RV64-NEXT: .cfi_def_cfa_offset 2032
+; RV64-NEXT: sd t0, 2000(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -32
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 2024(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
+; RV64-NEXT: csrsi mstatus, 8
+; RV64-NEXT: sd t0, 2016(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd ra, 2008(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t1, 1992(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t2, 1984(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a0, 1976(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a1, 1968(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a2, 1960(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a3, 1952(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a4, 1944(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a5, 1936(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a6, 1928(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a7, 1920(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t3, 1912(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t4, 1904(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t5, 1896(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t6, 1888(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -24
+; RV64-NEXT: .cfi_offset t1, -40
+; RV64-NEXT: .cfi_offset t2, -48
+; RV64-NEXT: .cfi_offset a0, -56
+; RV64-NEXT: .cfi_offset a1, -64
+; RV64-NEXT: .cfi_offset a2, -72
+; RV64-NEXT: .cfi_offset a3, -80
+; RV64-NEXT: .cfi_offset a4, -88
+; RV64-NEXT: .cfi_offset a5, -96
+; RV64-NEXT: .cfi_offset a6, -104
+; RV64-NEXT: .cfi_offset a7, -112
+; RV64-NEXT: .cfi_offset t3, -120
+; RV64-NEXT: .cfi_offset t4, -128
+; RV64-NEXT: .cfi_offset t5, -136
+; RV64-NEXT: .cfi_offset t6, -144
+; RV64-NEXT: addi sp, sp, -2048
+; RV64-NEXT: addi sp, sp, -176
+; RV64-NEXT: .cfi_def_cfa_offset 4256
+; RV64-NEXT: addi a0, sp, 16
+; RV64-NEXT: call use
+; RV64-NEXT: addi sp, sp, 2032
+; RV64-NEXT: addi sp, sp, 192
+; RV64-NEXT: .cfi_def_cfa_offset 2032
+; RV64-NEXT: ld ra, 2008(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t1, 1992(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t2, 1984(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a0, 1976(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a1, 1968(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a2, 1960(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a3, 1952(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a4, 1944(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a5, 1936(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a6, 1928(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a7, 1920(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t3, 1912(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t4, 1904(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t5, 1896(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t6, 1888(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t0, 2016(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrci mstatus, 8
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 2024(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 2000(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore t0
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: .cfi_restore t1
+; RV64-NEXT: .cfi_restore t2
+; RV64-NEXT: .cfi_restore a0
+; RV64-NEXT: .cfi_restore a1
+; RV64-NEXT: .cfi_restore a2
+; RV64-NEXT: .cfi_restore a3
+; RV64-NEXT: .cfi_restore a4
+; RV64-NEXT: .cfi_restore a5
+; RV64-NEXT: .cfi_restore a6
+; RV64-NEXT: .cfi_restore a7
+; RV64-NEXT: .cfi_restore t3
+; RV64-NEXT: .cfi_restore t4
+; RV64-NEXT: .cfi_restore t5
+; RV64-NEXT: .cfi_restore t6
+; RV64-NEXT: addi sp, sp, 2032
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: mret
+ %object = alloca [4096 x i8], align 16
+ call void @use(ptr %object)
+ ret void
+}
diff --git a/llvm/test/CodeGen/RISCV/sifive-interrupt-frame-flags.ll b/llvm/test/CodeGen/RISCV/sifive-interrupt-frame-flags.ll
index e014c20febfb81..3c10e87fe861f0 100644
--- a/llvm/test/CodeGen/RISCV/sifive-interrupt-frame-flags.ll
+++ b/llvm/test/CodeGen/RISCV/sifive-interrupt-frame-flags.ll
@@ -9,20 +9,25 @@ define void @preemptible_stack_swap() "interrupt"="SiFive-CLIC-preemptible-stack
; CHECK-LABEL: name: preemptible_stack_swap
; CHECK: body: |
; CHECK-NEXT: bb.0
-; CHECK-NEXT: $x2 = frame-setup CSRRW 840, killed $x2
-; CHECK-NEXT: $x2 = frame-setup ADDI $x2, -16
-; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16
-; CHECK-NEXT: frame-setup {{SW|SD}} killed $x8
-; CHECK-NEXT: frame-setup {{SW|SD}} killed $x9
-; CHECK-NEXT: $x8 = frame-setup CSRRS 834, $x0
-; CHECK-NEXT: $x9 = frame-setup CSRRS 833, $x0
+; CHECK-NEXT: liveins: $x5
+; CHECK: $x2 = frame-setup CSRRW 840, killed $x2
+; CHECK-NEXT: $x2 = frame-setup ADDI $x2, -{{16|32}}
+; CHECK-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset {{16|32}}
+; CHECK-NEXT: frame-setup {{SW|SD}} killed $x5
+; CHECK-NEXT: frame-setup CFI_INSTRUCTION offset $x5, -{{12|24}}
+; CHECK-NEXT: $x5 = frame-setup CSRRS 834, $x0
+; CHECK-NEXT: frame-setup {{SW|SD}} killed $x5
+; CHECK-NEXT: $x5 = frame-setup CSRRS 833, $x0
; CHECK-NEXT: $x0 = frame-setup CSRRSI 768, 8
+; CHECK-NEXT: frame-setup {{SW|SD}} killed $x5
+; CHECK-NEXT: $x5 = frame-destroy {{LW|LD}}
; CHECK-NEXT: $x0 = frame-destroy CSRRCI 768, 8
-; CHECK-NEXT: $x0 = frame-destroy CSRRW 833, killed $x9
-; CHECK-NEXT: $x0 = frame-destroy CSRRW 834, killed $x8
-; CHECK-NEXT: $x9 = frame-destroy {{LW|LD}}
-; CHECK-NEXT: $x8 = frame-destroy {{LW|LD}}
-; CHECK-NEXT: $x2 = frame-destroy ADDI $x2, 16
+; CHECK-NEXT: $x0 = frame-destroy CSRRW 833, killed $x5
+; CHECK-NEXT: $x5 = frame-destroy {{LW|LD}}
+; CHECK-NEXT: $x0 = frame-destroy CSRRW 834, killed $x5
+; CHECK-NEXT: $x5 = frame-destroy {{LW|LD}}
+; CHECK-NEXT: frame-destroy CFI_INSTRUCTION restore $x5
+; CHECK-NEXT: $x2 = frame-destroy ADDI $x2, {{16|32}}
; CHECK-NEXT: frame-destroy CFI_INSTRUCTION def_cfa_offset 0
; CHECK-NEXT: $x2 = frame-destroy CSRRW 840, killed $x2
; CHECK-NEXT: MRET
diff --git a/llvm/test/CodeGen/RISCV/sifive-interrupt-frame-pointer.ll b/llvm/test/CodeGen/RISCV/sifive-interrupt-frame-pointer.ll
new file mode 100644
index 00000000000000..0145c6de8924f9
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/sifive-interrupt-frame-pointer.ll
@@ -0,0 +1,951 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple riscv32-unknown-elf -mattr=+experimental-xsfmclic \
+; RUN: -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV32
+; RUN: llc -mtriple riscv64-unknown-elf -mattr=+experimental-xsfmclic \
+; RUN: -verify-machineinstrs < %s | FileCheck %s --check-prefix=RV64
+
+ at size = external global i32
+
+declare void @use(ptr)
+
+define void @preemptible() "interrupt"="SiFive-CLIC-preemptible" "frame-pointer"="all" {
+; RV32-LABEL: preemptible:
+; RV32: # %bb.0:
+; RV32-NEXT: addi sp, sp, -32
+; RV32-NEXT: .cfi_def_cfa_offset 32
+; RV32-NEXT: sw t0, 16(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -16
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 28(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
+; RV32-NEXT: csrsi mstatus, 8
+; RV32-NEXT: sw t0, 24(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw ra, 20(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -12
+; RV32-NEXT: .cfi_offset s0, -20
+; RV32-NEXT: addi s0, sp, 32
+; RV32-NEXT: .cfi_def_cfa s0, 0
+; RV32-NEXT: .cfi_def_cfa sp, 32
+; RV32-NEXT: lw ra, 20(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t0, 24(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrci mstatus, 8
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 28(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 16(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore t0
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore s0
+; RV32-NEXT: addi sp, sp, 32
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: mret
+;
+; RV64-LABEL: preemptible:
+; RV64: # %bb.0:
+; RV64-NEXT: addi sp, sp, -48
+; RV64-NEXT: .cfi_def_cfa_offset 48
+; RV64-NEXT: sd t0, 16(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -32
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 40(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
+; RV64-NEXT: csrsi mstatus, 8
+; RV64-NEXT: sd t0, 32(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -24
+; RV64-NEXT: .cfi_offset s0, -40
+; RV64-NEXT: addi s0, sp, 48
+; RV64-NEXT: .cfi_def_cfa s0, 0
+; RV64-NEXT: .cfi_def_cfa sp, 48
+; RV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t0, 32(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrci mstatus, 8
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 40(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 16(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore t0
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: .cfi_restore s0
+; RV64-NEXT: addi sp, sp, 48
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: mret
+ ret void
+}
+
+define void @preemptible_stack_swap() "interrupt"="SiFive-CLIC-preemptible-stack-swap" "frame-pointer"="all" {
+; RV32-LABEL: preemptible_stack_swap:
+; RV32: # %bb.0:
+; RV32-NEXT: csrrw sp, sf.mscratchcsw, sp
+; RV32-NEXT: addi sp, sp, -32
+; RV32-NEXT: .cfi_def_cfa_offset 32
+; RV32-NEXT: sw t0, 16(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -16
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 28(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
+; RV32-NEXT: csrsi mstatus, 8
+; RV32-NEXT: sw t0, 24(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw ra, 20(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -12
+; RV32-NEXT: .cfi_offset s0, -20
+; RV32-NEXT: addi s0, sp, 32
+; RV32-NEXT: .cfi_def_cfa s0, 0
+; RV32-NEXT: .cfi_def_cfa sp, 32
+; RV32-NEXT: lw ra, 20(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t0, 24(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrci mstatus, 8
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 28(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 16(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore t0
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore s0
+; RV32-NEXT: addi sp, sp, 32
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: csrrw sp, sf.mscratchcsw, sp
+; RV32-NEXT: mret
+;
+; RV64-LABEL: preemptible_stack_swap:
+; RV64: # %bb.0:
+; RV64-NEXT: csrrw sp, sf.mscratchcsw, sp
+; RV64-NEXT: addi sp, sp, -48
+; RV64-NEXT: .cfi_def_cfa_offset 48
+; RV64-NEXT: sd t0, 16(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -32
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 40(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
+; RV64-NEXT: csrsi mstatus, 8
+; RV64-NEXT: sd t0, 32(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s0, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -24
+; RV64-NEXT: .cfi_offset s0, -40
+; RV64-NEXT: addi s0, sp, 48
+; RV64-NEXT: .cfi_def_cfa s0, 0
+; RV64-NEXT: .cfi_def_cfa sp, 48
+; RV64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s0, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t0, 32(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrci mstatus, 8
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 40(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 16(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore t0
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: .cfi_restore s0
+; RV64-NEXT: addi sp, sp, 48
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: csrrw sp, sf.mscratchcsw, sp
+; RV64-NEXT: mret
+ ret void
+}
+
+define void @preemptible_var_alloca() "interrupt"="SiFive-CLIC-preemptible" "frame-pointer"="none" {
+; RV32-LABEL: preemptible_var_alloca:
+; RV32: # %bb.0:
+; RV32-NEXT: addi sp, sp, -80
+; RV32-NEXT: .cfi_def_cfa_offset 80
+; RV32-NEXT: sw t0, 64(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -16
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 76(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
+; RV32-NEXT: csrsi mstatus, 8
+; RV32-NEXT: sw t0, 72(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw ra, 68(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t1, 60(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t2, 56(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 52(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a0, 48(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a1, 44(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a2, 40(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a3, 36(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a4, 32(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a5, 28(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a6, 24(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a7, 20(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t3, 16(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t4, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t5, 8(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t6, 4(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -12
+; RV32-NEXT: .cfi_offset t1, -20
+; RV32-NEXT: .cfi_offset t2, -24
+; RV32-NEXT: .cfi_offset s0, -28
+; RV32-NEXT: .cfi_offset a0, -32
+; RV32-NEXT: .cfi_offset a1, -36
+; RV32-NEXT: .cfi_offset a2, -40
+; RV32-NEXT: .cfi_offset a3, -44
+; RV32-NEXT: .cfi_offset a4, -48
+; RV32-NEXT: .cfi_offset a5, -52
+; RV32-NEXT: .cfi_offset a6, -56
+; RV32-NEXT: .cfi_offset a7, -60
+; RV32-NEXT: .cfi_offset t3, -64
+; RV32-NEXT: .cfi_offset t4, -68
+; RV32-NEXT: .cfi_offset t5, -72
+; RV32-NEXT: .cfi_offset t6, -76
+; RV32-NEXT: addi s0, sp, 80
+; RV32-NEXT: .cfi_def_cfa s0, 0
+; RV32-NEXT: lui a0, %hi(size)
+; RV32-NEXT: lw a0, %lo(size)(a0)
+; RV32-NEXT: addi a0, a0, 15
+; RV32-NEXT: andi a0, a0, -16
+; RV32-NEXT: sub a0, sp, a0
+; RV32-NEXT: mv sp, a0
+; RV32-NEXT: call use
+; RV32-NEXT: addi sp, s0, -80
+; RV32-NEXT: .cfi_def_cfa sp, 80
+; RV32-NEXT: lw ra, 68(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t1, 60(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t2, 56(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 52(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a0, 48(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a1, 44(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a2, 40(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a3, 36(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a4, 32(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a5, 28(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a6, 24(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a7, 20(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t3, 16(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t4, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t5, 8(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t6, 4(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t0, 72(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrci mstatus, 8
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 76(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 64(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore t0
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore t1
+; RV32-NEXT: .cfi_restore t2
+; RV32-NEXT: .cfi_restore s0
+; RV32-NEXT: .cfi_restore a0
+; RV32-NEXT: .cfi_restore a1
+; RV32-NEXT: .cfi_restore a2
+; RV32-NEXT: .cfi_restore a3
+; RV32-NEXT: .cfi_restore a4
+; RV32-NEXT: .cfi_restore a5
+; RV32-NEXT: .cfi_restore a6
+; RV32-NEXT: .cfi_restore a7
+; RV32-NEXT: .cfi_restore t3
+; RV32-NEXT: .cfi_restore t4
+; RV32-NEXT: .cfi_restore t5
+; RV32-NEXT: .cfi_restore t6
+; RV32-NEXT: addi sp, sp, 80
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: mret
+;
+; RV64-LABEL: preemptible_var_alloca:
+; RV64: # %bb.0:
+; RV64-NEXT: addi sp, sp, -160
+; RV64-NEXT: .cfi_def_cfa_offset 160
+; RV64-NEXT: sd t0, 128(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -32
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 152(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
+; RV64-NEXT: csrsi mstatus, 8
+; RV64-NEXT: sd t0, 144(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd ra, 136(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t1, 120(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t2, 112(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s0, 104(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a0, 96(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a1, 88(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a2, 80(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a3, 72(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a4, 64(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a5, 56(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a6, 48(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a7, 40(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t3, 32(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t4, 24(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t5, 16(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t6, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -24
+; RV64-NEXT: .cfi_offset t1, -40
+; RV64-NEXT: .cfi_offset t2, -48
+; RV64-NEXT: .cfi_offset s0, -56
+; RV64-NEXT: .cfi_offset a0, -64
+; RV64-NEXT: .cfi_offset a1, -72
+; RV64-NEXT: .cfi_offset a2, -80
+; RV64-NEXT: .cfi_offset a3, -88
+; RV64-NEXT: .cfi_offset a4, -96
+; RV64-NEXT: .cfi_offset a5, -104
+; RV64-NEXT: .cfi_offset a6, -112
+; RV64-NEXT: .cfi_offset a7, -120
+; RV64-NEXT: .cfi_offset t3, -128
+; RV64-NEXT: .cfi_offset t4, -136
+; RV64-NEXT: .cfi_offset t5, -144
+; RV64-NEXT: .cfi_offset t6, -152
+; RV64-NEXT: addi s0, sp, 160
+; RV64-NEXT: .cfi_def_cfa s0, 0
+; RV64-NEXT: lui a0, %hi(size)
+; RV64-NEXT: lwu a0, %lo(size)(a0)
+; RV64-NEXT: addi a0, a0, 15
+; RV64-NEXT: andi a0, a0, -16
+; RV64-NEXT: sub a0, sp, a0
+; RV64-NEXT: mv sp, a0
+; RV64-NEXT: call use
+; RV64-NEXT: addi sp, s0, -160
+; RV64-NEXT: .cfi_def_cfa sp, 160
+; RV64-NEXT: ld ra, 136(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t1, 120(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t2, 112(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s0, 104(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a0, 96(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a1, 88(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a2, 80(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a3, 72(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a4, 64(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a5, 56(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a6, 48(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a7, 40(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t3, 32(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t4, 24(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t5, 16(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t6, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t0, 144(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrci mstatus, 8
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 152(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 128(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore t0
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: .cfi_restore t1
+; RV64-NEXT: .cfi_restore t2
+; RV64-NEXT: .cfi_restore s0
+; RV64-NEXT: .cfi_restore a0
+; RV64-NEXT: .cfi_restore a1
+; RV64-NEXT: .cfi_restore a2
+; RV64-NEXT: .cfi_restore a3
+; RV64-NEXT: .cfi_restore a4
+; RV64-NEXT: .cfi_restore a5
+; RV64-NEXT: .cfi_restore a6
+; RV64-NEXT: .cfi_restore a7
+; RV64-NEXT: .cfi_restore t3
+; RV64-NEXT: .cfi_restore t4
+; RV64-NEXT: .cfi_restore t5
+; RV64-NEXT: .cfi_restore t6
+; RV64-NEXT: addi sp, sp, 160
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: mret
+ %count = load volatile i32, ptr @size
+ %object = alloca i8, i32 %count, align 16
+ call void @use(ptr %object)
+ ret void
+}
+
+define void @preemptible_realign() "interrupt"="SiFive-CLIC-preemptible" "frame-pointer"="none" {
+; RV32-LABEL: preemptible_realign:
+; RV32: # %bb.0:
+; RV32-NEXT: addi sp, sp, -192
+; RV32-NEXT: .cfi_def_cfa_offset 192
+; RV32-NEXT: sw t0, 176(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -16
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 188(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
+; RV32-NEXT: csrsi mstatus, 8
+; RV32-NEXT: sw t0, 184(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw ra, 180(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t1, 172(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t2, 168(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 164(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a0, 160(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a1, 156(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a2, 152(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a3, 148(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a4, 144(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a5, 140(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a6, 136(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a7, 132(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t3, 128(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t4, 124(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t5, 120(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t6, 116(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -12
+; RV32-NEXT: .cfi_offset t1, -20
+; RV32-NEXT: .cfi_offset t2, -24
+; RV32-NEXT: .cfi_offset s0, -28
+; RV32-NEXT: .cfi_offset a0, -32
+; RV32-NEXT: .cfi_offset a1, -36
+; RV32-NEXT: .cfi_offset a2, -40
+; RV32-NEXT: .cfi_offset a3, -44
+; RV32-NEXT: .cfi_offset a4, -48
+; RV32-NEXT: .cfi_offset a5, -52
+; RV32-NEXT: .cfi_offset a6, -56
+; RV32-NEXT: .cfi_offset a7, -60
+; RV32-NEXT: .cfi_offset t3, -64
+; RV32-NEXT: .cfi_offset t4, -68
+; RV32-NEXT: .cfi_offset t5, -72
+; RV32-NEXT: .cfi_offset t6, -76
+; RV32-NEXT: addi s0, sp, 192
+; RV32-NEXT: .cfi_def_cfa s0, 0
+; RV32-NEXT: andi sp, sp, -64
+; RV32-NEXT: mv a0, sp
+; RV32-NEXT: call use
+; RV32-NEXT: addi sp, s0, -192
+; RV32-NEXT: .cfi_def_cfa sp, 192
+; RV32-NEXT: lw ra, 180(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t1, 172(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t2, 168(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 164(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a0, 160(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a1, 156(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a2, 152(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a3, 148(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a4, 144(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a5, 140(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a6, 136(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a7, 132(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t3, 128(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t4, 124(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t5, 120(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t6, 116(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t0, 184(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrci mstatus, 8
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 188(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 176(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore t0
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore t1
+; RV32-NEXT: .cfi_restore t2
+; RV32-NEXT: .cfi_restore s0
+; RV32-NEXT: .cfi_restore a0
+; RV32-NEXT: .cfi_restore a1
+; RV32-NEXT: .cfi_restore a2
+; RV32-NEXT: .cfi_restore a3
+; RV32-NEXT: .cfi_restore a4
+; RV32-NEXT: .cfi_restore a5
+; RV32-NEXT: .cfi_restore a6
+; RV32-NEXT: .cfi_restore a7
+; RV32-NEXT: .cfi_restore t3
+; RV32-NEXT: .cfi_restore t4
+; RV32-NEXT: .cfi_restore t5
+; RV32-NEXT: .cfi_restore t6
+; RV32-NEXT: addi sp, sp, 192
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: mret
+;
+; RV64-LABEL: preemptible_realign:
+; RV64: # %bb.0:
+; RV64-NEXT: addi sp, sp, -256
+; RV64-NEXT: .cfi_def_cfa_offset 256
+; RV64-NEXT: sd t0, 224(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -32
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 248(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
+; RV64-NEXT: csrsi mstatus, 8
+; RV64-NEXT: sd t0, 240(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd ra, 232(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t1, 216(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t2, 208(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s0, 200(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a0, 192(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a1, 184(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a2, 176(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a3, 168(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a4, 160(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a5, 152(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a6, 144(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a7, 136(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t3, 128(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t4, 120(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t5, 112(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t6, 104(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -24
+; RV64-NEXT: .cfi_offset t1, -40
+; RV64-NEXT: .cfi_offset t2, -48
+; RV64-NEXT: .cfi_offset s0, -56
+; RV64-NEXT: .cfi_offset a0, -64
+; RV64-NEXT: .cfi_offset a1, -72
+; RV64-NEXT: .cfi_offset a2, -80
+; RV64-NEXT: .cfi_offset a3, -88
+; RV64-NEXT: .cfi_offset a4, -96
+; RV64-NEXT: .cfi_offset a5, -104
+; RV64-NEXT: .cfi_offset a6, -112
+; RV64-NEXT: .cfi_offset a7, -120
+; RV64-NEXT: .cfi_offset t3, -128
+; RV64-NEXT: .cfi_offset t4, -136
+; RV64-NEXT: .cfi_offset t5, -144
+; RV64-NEXT: .cfi_offset t6, -152
+; RV64-NEXT: addi s0, sp, 256
+; RV64-NEXT: .cfi_def_cfa s0, 0
+; RV64-NEXT: andi sp, sp, -64
+; RV64-NEXT: mv a0, sp
+; RV64-NEXT: call use
+; RV64-NEXT: addi sp, s0, -256
+; RV64-NEXT: .cfi_def_cfa sp, 256
+; RV64-NEXT: ld ra, 232(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t1, 216(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t2, 208(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s0, 200(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a0, 192(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a1, 184(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a2, 176(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a3, 168(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a4, 160(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a5, 152(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a6, 144(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a7, 136(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t3, 128(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t4, 120(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t5, 112(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t6, 104(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t0, 240(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrci mstatus, 8
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 248(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 224(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore t0
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: .cfi_restore t1
+; RV64-NEXT: .cfi_restore t2
+; RV64-NEXT: .cfi_restore s0
+; RV64-NEXT: .cfi_restore a0
+; RV64-NEXT: .cfi_restore a1
+; RV64-NEXT: .cfi_restore a2
+; RV64-NEXT: .cfi_restore a3
+; RV64-NEXT: .cfi_restore a4
+; RV64-NEXT: .cfi_restore a5
+; RV64-NEXT: .cfi_restore a6
+; RV64-NEXT: .cfi_restore a7
+; RV64-NEXT: .cfi_restore t3
+; RV64-NEXT: .cfi_restore t4
+; RV64-NEXT: .cfi_restore t5
+; RV64-NEXT: .cfi_restore t6
+; RV64-NEXT: addi sp, sp, 256
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: mret
+ %object = alloca [64 x i8], align 64
+ call void @use(ptr %object)
+ ret void
+}
+
+define void @large_frame_fp() "interrupt"="SiFive-CLIC-preemptible" "frame-pointer"="all" {
+; RV32-LABEL: large_frame_fp:
+; RV32: # %bb.0:
+; RV32-NEXT: addi sp, sp, -2032
+; RV32-NEXT: .cfi_def_cfa_offset 2032
+; RV32-NEXT: sw t0, 2016(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -16
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 2028(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
+; RV32-NEXT: csrsi mstatus, 8
+; RV32-NEXT: sw t0, 2024(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw ra, 2020(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t1, 2012(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t2, 2008(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 2004(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a0, 2000(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a1, 1996(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a2, 1992(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a3, 1988(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a4, 1984(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a5, 1980(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a6, 1976(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a7, 1972(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t3, 1968(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t4, 1964(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t5, 1960(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t6, 1956(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -12
+; RV32-NEXT: .cfi_offset t1, -20
+; RV32-NEXT: .cfi_offset t2, -24
+; RV32-NEXT: .cfi_offset s0, -28
+; RV32-NEXT: .cfi_offset a0, -32
+; RV32-NEXT: .cfi_offset a1, -36
+; RV32-NEXT: .cfi_offset a2, -40
+; RV32-NEXT: .cfi_offset a3, -44
+; RV32-NEXT: .cfi_offset a4, -48
+; RV32-NEXT: .cfi_offset a5, -52
+; RV32-NEXT: .cfi_offset a6, -56
+; RV32-NEXT: .cfi_offset a7, -60
+; RV32-NEXT: .cfi_offset t3, -64
+; RV32-NEXT: .cfi_offset t4, -68
+; RV32-NEXT: .cfi_offset t5, -72
+; RV32-NEXT: .cfi_offset t6, -76
+; RV32-NEXT: addi s0, sp, 2032
+; RV32-NEXT: .cfi_def_cfa s0, 0
+; RV32-NEXT: addi sp, sp, -2048
+; RV32-NEXT: addi sp, sp, -96
+; RV32-NEXT: mv a0, sp
+; RV32-NEXT: call use
+; RV32-NEXT: addi sp, sp, 2032
+; RV32-NEXT: addi sp, sp, 112
+; RV32-NEXT: .cfi_def_cfa sp, 2032
+; RV32-NEXT: lw ra, 2020(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t1, 2012(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t2, 2008(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 2004(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a0, 2000(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a1, 1996(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a2, 1992(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a3, 1988(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a4, 1984(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a5, 1980(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a6, 1976(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a7, 1972(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t3, 1968(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t4, 1964(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t5, 1960(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t6, 1956(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t0, 2024(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrci mstatus, 8
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 2028(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 2016(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore t0
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore t1
+; RV32-NEXT: .cfi_restore t2
+; RV32-NEXT: .cfi_restore s0
+; RV32-NEXT: .cfi_restore a0
+; RV32-NEXT: .cfi_restore a1
+; RV32-NEXT: .cfi_restore a2
+; RV32-NEXT: .cfi_restore a3
+; RV32-NEXT: .cfi_restore a4
+; RV32-NEXT: .cfi_restore a5
+; RV32-NEXT: .cfi_restore a6
+; RV32-NEXT: .cfi_restore a7
+; RV32-NEXT: .cfi_restore t3
+; RV32-NEXT: .cfi_restore t4
+; RV32-NEXT: .cfi_restore t5
+; RV32-NEXT: .cfi_restore t6
+; RV32-NEXT: addi sp, sp, 2032
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: mret
+;
+; RV64-LABEL: large_frame_fp:
+; RV64: # %bb.0:
+; RV64-NEXT: addi sp, sp, -2032
+; RV64-NEXT: .cfi_def_cfa_offset 2032
+; RV64-NEXT: sd t0, 2000(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -32
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 2024(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
+; RV64-NEXT: csrsi mstatus, 8
+; RV64-NEXT: sd t0, 2016(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd ra, 2008(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t1, 1992(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t2, 1984(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s0, 1976(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a0, 1968(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a1, 1960(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a2, 1952(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a3, 1944(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a4, 1936(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a5, 1928(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a6, 1920(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a7, 1912(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t3, 1904(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t4, 1896(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t5, 1888(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t6, 1880(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -24
+; RV64-NEXT: .cfi_offset t1, -40
+; RV64-NEXT: .cfi_offset t2, -48
+; RV64-NEXT: .cfi_offset s0, -56
+; RV64-NEXT: .cfi_offset a0, -64
+; RV64-NEXT: .cfi_offset a1, -72
+; RV64-NEXT: .cfi_offset a2, -80
+; RV64-NEXT: .cfi_offset a3, -88
+; RV64-NEXT: .cfi_offset a4, -96
+; RV64-NEXT: .cfi_offset a5, -104
+; RV64-NEXT: .cfi_offset a6, -112
+; RV64-NEXT: .cfi_offset a7, -120
+; RV64-NEXT: .cfi_offset t3, -128
+; RV64-NEXT: .cfi_offset t4, -136
+; RV64-NEXT: .cfi_offset t5, -144
+; RV64-NEXT: .cfi_offset t6, -152
+; RV64-NEXT: addi s0, sp, 2032
+; RV64-NEXT: .cfi_def_cfa s0, 0
+; RV64-NEXT: addi sp, sp, -2048
+; RV64-NEXT: addi sp, sp, -176
+; RV64-NEXT: mv a0, sp
+; RV64-NEXT: call use
+; RV64-NEXT: addi sp, sp, 2032
+; RV64-NEXT: addi sp, sp, 192
+; RV64-NEXT: .cfi_def_cfa sp, 2032
+; RV64-NEXT: ld ra, 2008(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t1, 1992(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t2, 1984(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s0, 1976(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a0, 1968(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a1, 1960(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a2, 1952(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a3, 1944(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a4, 1936(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a5, 1928(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a6, 1920(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a7, 1912(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t3, 1904(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t4, 1896(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t5, 1888(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t6, 1880(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t0, 2016(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrci mstatus, 8
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 2024(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 2000(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore t0
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: .cfi_restore t1
+; RV64-NEXT: .cfi_restore t2
+; RV64-NEXT: .cfi_restore s0
+; RV64-NEXT: .cfi_restore a0
+; RV64-NEXT: .cfi_restore a1
+; RV64-NEXT: .cfi_restore a2
+; RV64-NEXT: .cfi_restore a3
+; RV64-NEXT: .cfi_restore a4
+; RV64-NEXT: .cfi_restore a5
+; RV64-NEXT: .cfi_restore a6
+; RV64-NEXT: .cfi_restore a7
+; RV64-NEXT: .cfi_restore t3
+; RV64-NEXT: .cfi_restore t4
+; RV64-NEXT: .cfi_restore t5
+; RV64-NEXT: .cfi_restore t6
+; RV64-NEXT: addi sp, sp, 2032
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: mret
+ %object = alloca [4096 x i8], align 16
+ call void @use(ptr %object)
+ ret void
+}
+
+define void @realign_var_alloca() "interrupt"="SiFive-CLIC-preemptible" "frame-pointer"="none" {
+; RV32-LABEL: realign_var_alloca:
+; RV32: # %bb.0:
+; RV32-NEXT: addi sp, sp, -128
+; RV32-NEXT: .cfi_def_cfa_offset 128
+; RV32-NEXT: sw t0, 112(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset t0, -16
+; RV32-NEXT: csrr t0, mcause
+; RV32-NEXT: sw t0, 124(sp) # 4-byte Folded Spill
+; RV32-NEXT: csrr t0, mepc
+; RV32-NEXT: csrsi mstatus, 8
+; RV32-NEXT: sw t0, 120(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw ra, 116(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t1, 108(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t2, 104(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 100(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s1, 96(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a0, 92(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a1, 88(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a2, 84(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a3, 80(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a4, 76(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a5, 72(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a6, 68(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw a7, 64(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t3, 60(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t4, 56(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t5, 52(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw t6, 48(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -12
+; RV32-NEXT: .cfi_offset t1, -20
+; RV32-NEXT: .cfi_offset t2, -24
+; RV32-NEXT: .cfi_offset s0, -28
+; RV32-NEXT: .cfi_offset s1, -32
+; RV32-NEXT: .cfi_offset a0, -36
+; RV32-NEXT: .cfi_offset a1, -40
+; RV32-NEXT: .cfi_offset a2, -44
+; RV32-NEXT: .cfi_offset a3, -48
+; RV32-NEXT: .cfi_offset a4, -52
+; RV32-NEXT: .cfi_offset a5, -56
+; RV32-NEXT: .cfi_offset a6, -60
+; RV32-NEXT: .cfi_offset a7, -64
+; RV32-NEXT: .cfi_offset t3, -68
+; RV32-NEXT: .cfi_offset t4, -72
+; RV32-NEXT: .cfi_offset t5, -76
+; RV32-NEXT: .cfi_offset t6, -80
+; RV32-NEXT: addi s0, sp, 128
+; RV32-NEXT: .cfi_def_cfa s0, 0
+; RV32-NEXT: andi sp, sp, -64
+; RV32-NEXT: mv s1, sp
+; RV32-NEXT: lui a0, %hi(size)
+; RV32-NEXT: lw a0, %lo(size)(a0)
+; RV32-NEXT: addi a0, a0, 15
+; RV32-NEXT: andi a0, a0, -16
+; RV32-NEXT: sub a0, sp, a0
+; RV32-NEXT: andi a0, a0, -64
+; RV32-NEXT: mv sp, a0
+; RV32-NEXT: call use
+; RV32-NEXT: addi sp, s0, -128
+; RV32-NEXT: .cfi_def_cfa sp, 128
+; RV32-NEXT: lw ra, 116(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t1, 108(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t2, 104(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 100(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s1, 96(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a0, 92(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a1, 88(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a2, 84(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a3, 80(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a4, 76(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a5, 72(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a6, 68(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw a7, 64(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t3, 60(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t4, 56(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t5, 52(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t6, 48(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw t0, 120(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrci mstatus, 8
+; RV32-NEXT: csrw mepc, t0
+; RV32-NEXT: lw t0, 124(sp) # 4-byte Folded Reload
+; RV32-NEXT: csrw mcause, t0
+; RV32-NEXT: lw t0, 112(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore t0
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore t1
+; RV32-NEXT: .cfi_restore t2
+; RV32-NEXT: .cfi_restore s0
+; RV32-NEXT: .cfi_restore s1
+; RV32-NEXT: .cfi_restore a0
+; RV32-NEXT: .cfi_restore a1
+; RV32-NEXT: .cfi_restore a2
+; RV32-NEXT: .cfi_restore a3
+; RV32-NEXT: .cfi_restore a4
+; RV32-NEXT: .cfi_restore a5
+; RV32-NEXT: .cfi_restore a6
+; RV32-NEXT: .cfi_restore a7
+; RV32-NEXT: .cfi_restore t3
+; RV32-NEXT: .cfi_restore t4
+; RV32-NEXT: .cfi_restore t5
+; RV32-NEXT: .cfi_restore t6
+; RV32-NEXT: addi sp, sp, 128
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: mret
+;
+; RV64-LABEL: realign_var_alloca:
+; RV64: # %bb.0:
+; RV64-NEXT: addi sp, sp, -192
+; RV64-NEXT: .cfi_def_cfa_offset 192
+; RV64-NEXT: sd t0, 160(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset t0, -32
+; RV64-NEXT: csrr t0, mcause
+; RV64-NEXT: sd t0, 184(sp) # 8-byte Folded Spill
+; RV64-NEXT: csrr t0, mepc
+; RV64-NEXT: csrsi mstatus, 8
+; RV64-NEXT: sd t0, 176(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd ra, 168(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t1, 152(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t2, 144(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s0, 136(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s1, 128(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a0, 120(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a1, 112(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a2, 104(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a3, 96(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a4, 88(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a5, 80(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a6, 72(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd a7, 64(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t3, 56(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t4, 48(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t5, 40(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd t6, 32(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -24
+; RV64-NEXT: .cfi_offset t1, -40
+; RV64-NEXT: .cfi_offset t2, -48
+; RV64-NEXT: .cfi_offset s0, -56
+; RV64-NEXT: .cfi_offset s1, -64
+; RV64-NEXT: .cfi_offset a0, -72
+; RV64-NEXT: .cfi_offset a1, -80
+; RV64-NEXT: .cfi_offset a2, -88
+; RV64-NEXT: .cfi_offset a3, -96
+; RV64-NEXT: .cfi_offset a4, -104
+; RV64-NEXT: .cfi_offset a5, -112
+; RV64-NEXT: .cfi_offset a6, -120
+; RV64-NEXT: .cfi_offset a7, -128
+; RV64-NEXT: .cfi_offset t3, -136
+; RV64-NEXT: .cfi_offset t4, -144
+; RV64-NEXT: .cfi_offset t5, -152
+; RV64-NEXT: .cfi_offset t6, -160
+; RV64-NEXT: addi s0, sp, 192
+; RV64-NEXT: .cfi_def_cfa s0, 0
+; RV64-NEXT: andi sp, sp, -64
+; RV64-NEXT: mv s1, sp
+; RV64-NEXT: lui a0, %hi(size)
+; RV64-NEXT: lwu a0, %lo(size)(a0)
+; RV64-NEXT: addi a0, a0, 15
+; RV64-NEXT: andi a0, a0, -16
+; RV64-NEXT: sub a0, sp, a0
+; RV64-NEXT: andi a0, a0, -64
+; RV64-NEXT: mv sp, a0
+; RV64-NEXT: call use
+; RV64-NEXT: addi sp, s0, -192
+; RV64-NEXT: .cfi_def_cfa sp, 192
+; RV64-NEXT: ld ra, 168(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t1, 152(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t2, 144(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s0, 136(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s1, 128(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a0, 120(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a1, 112(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a2, 104(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a3, 96(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a4, 88(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a5, 80(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a6, 72(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld a7, 64(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t3, 56(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t4, 48(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t5, 40(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t6, 32(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld t0, 176(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrci mstatus, 8
+; RV64-NEXT: csrw mepc, t0
+; RV64-NEXT: ld t0, 184(sp) # 8-byte Folded Reload
+; RV64-NEXT: csrw mcause, t0
+; RV64-NEXT: ld t0, 160(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore t0
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: .cfi_restore t1
+; RV64-NEXT: .cfi_restore t2
+; RV64-NEXT: .cfi_restore s0
+; RV64-NEXT: .cfi_restore s1
+; RV64-NEXT: .cfi_restore a0
+; RV64-NEXT: .cfi_restore a1
+; RV64-NEXT: .cfi_restore a2
+; RV64-NEXT: .cfi_restore a3
+; RV64-NEXT: .cfi_restore a4
+; RV64-NEXT: .cfi_restore a5
+; RV64-NEXT: .cfi_restore a6
+; RV64-NEXT: .cfi_restore a7
+; RV64-NEXT: .cfi_restore t3
+; RV64-NEXT: .cfi_restore t4
+; RV64-NEXT: .cfi_restore t5
+; RV64-NEXT: .cfi_restore t6
+; RV64-NEXT: addi sp, sp, 192
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: mret
+ %count = load volatile i32, ptr @size
+ %object = alloca i8, i32 %count, align 64
+ call void @use(ptr %object)
+ ret void
+}
More information about the llvm-commits
mailing list