[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