[llvm-branch-commits] [llvm] release/23.x: [RISCV] Ensure Shadow Stack checks correct RA (PR #231323)
Sam Elliott via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue Oct 20 21:28:09 PDT 2026
https://github.com/lenary updated https://github.com/llvm/llvm-project/pull/231323
>From 567802d91dbd11264a5bd66c4429c08758297be5 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Wed, 7 Oct 2026 14:52:38 -0700
Subject: [PATCH 1/2] [RISCV] Ensure Shadow Stack checks correct RA
This primarliy applies to the save-restore case, which was using
`__riscv_restore_<N>` incorrectly, entirely circumventing the software
shadow call stack.
This fix keeps the code size improvements of `__riscv_save_<N>` when
there is a shadow call stack, but it avoids the incorrect use of
`__riscv_restore_<N>`, instead emitting the correct sequence inline.
In the future, when there are better versions of `__riscv_save_<N>` and
`__riscv_restore_<N>` which support the shadow call stack variants (both
hardware and software), then we can revisit this approach and use the
correct pairs in all cases.
---
llvm/docs/RISCVUsage.rst | 6 +
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 105 +-
.../Target/RISCV/RISCVMachineFunctionInfo.cpp | 18 +
.../Target/RISCV/RISCVMachineFunctionInfo.h | 7 +
llvm/test/CodeGen/RISCV/saverestore-scs.ll | 15 +-
.../CodeGen/RISCV/shadow-stack-frame-opts.ll | 1871 +++++++++++++++++
6 files changed, 1977 insertions(+), 45 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/shadow-stack-frame-opts.ll
diff --git a/llvm/docs/RISCVUsage.rst b/llvm/docs/RISCVUsage.rst
index 72428398fc465..1301efb32df3e 100644
--- a/llvm/docs/RISCVUsage.rst
+++ b/llvm/docs/RISCVUsage.rst
@@ -643,6 +643,12 @@ The small data limit threshold is also used to separate small constants into sec
Data suggests that these options can produce significant improvements across a range of benchmarks.
+Save/Restore Support
+====================
+
+In some circumstances, LLVM may not emit ``__riscv_restore_<N>`` tail calls when it has used ``__riscv_save_<N>`` to save GPRs. This is done intentionally -- specifically when the ``__riscv_restore_<N>`` call does not support functionality that can be emitted inline before or after a ``__riscv_save<N>`` call. We still emit the ``__riscv_save_<N>`` call so that the code size impact of inlining the restore sequence is not as severe as if we also inlined the save sequence.
+
+
Sanitizers
==========
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 8eb20927fb8a0..0cd2394229ff8 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -107,20 +107,12 @@ static bool needsDwarfCFI(const MachineFunction &MF) {
static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const DebugLoc &DL) {
- const auto &STI = MF.getSubtarget<RISCVSubtarget>();
- // We check Zimop instead of (Zimop || Zcmop) to determine whether HW shadow
- // stack is available despite the fact that sspush/sspopchk both have a
- // compressed form, because if only Zcmop is available, we would need to
- // reserve X5 due to c.sspopchk only takes X5 and we currently do not support
- // using X5 as the return address register.
- // However, we can still aggressively use c.sspush x1 if zcmop is available.
- bool HasHWShadowStack = MF.getFunction().hasFnAttribute("hw-shadow-stack") &&
- STI.hasStdExtZimop();
- bool HasSWShadowStack =
- MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
- if (!HasHWShadowStack && !HasSWShadowStack)
+ const auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
+ RISCVMachineFunctionInfo::ShadowStackKind SSK = RVFI->getShadowStackKind(MF);
+ if (SSK == RISCVMachineFunctionInfo::ShadowStackKind::None)
return;
+ const auto &STI = MF.getSubtarget<RISCVSubtarget>();
const llvm::RISCVRegisterInfo *TRI = STI.getRegisterInfo();
// Do not save RA to the SCS if it's not saved to the regular stack,
@@ -131,13 +123,16 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
return;
const RISCVInstrInfo *TII = STI.getInstrInfo();
- if (HasHWShadowStack) {
+ if (SSK == RISCVMachineFunctionInfo::ShadowStackKind::Hardware) {
BuildMI(MBB, MI, DL, TII->get(RISCV::SSPUSH))
.addReg(RAReg)
.setMIFlag(MachineInstr::FrameSetup);
return;
}
+ assert(SSK == RISCVMachineFunctionInfo::ShadowStackKind::Software &&
+ "Unexpected Shadow Stack Kind");
+
Register SCSPReg = RISCVABI::getSCSPReg();
bool IsRV64 = STI.is64Bit();
@@ -180,14 +175,13 @@ static void emitSCSPrologue(MachineFunction &MF, MachineBasicBlock &MBB,
static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const DebugLoc &DL) {
- const auto &STI = MF.getSubtarget<RISCVSubtarget>();
- bool HasHWShadowStack = MF.getFunction().hasFnAttribute("hw-shadow-stack") &&
- STI.hasStdExtZimop();
- bool HasSWShadowStack =
- MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack);
- if (!HasHWShadowStack && !HasSWShadowStack)
+ const auto *RVFI = MF.getInfo<RISCVMachineFunctionInfo>();
+ RISCVMachineFunctionInfo::ShadowStackKind SSK = RVFI->getShadowStackKind(MF);
+ if (SSK == RISCVMachineFunctionInfo::ShadowStackKind::None)
return;
+ const auto &STI = MF.getSubtarget<RISCVSubtarget>();
+
// See emitSCSPrologue() above.
std::vector<CalleeSavedInfo> &CSI = MF.getFrameInfo().getCalleeSavedInfo();
if (llvm::none_of(
@@ -199,13 +193,19 @@ static void emitSCSEpilogue(MachineFunction &MF, MachineBasicBlock &MBB,
(MI->getOpcode() == RISCV::CM_POP || MI->getOpcode() == RISCV::QC_CM_POP))
++MI;
const RISCVInstrInfo *TII = STI.getInstrInfo();
- if (HasHWShadowStack) {
+ if (SSK == RISCVMachineFunctionInfo::ShadowStackKind::Hardware) {
+ // `sspopchk x5` is the only compressible form, but this would require using
+ // `x5` as the return address everywhere, which would also mean reserving
+ // it. We prefer to just use `x1` to avoid that complexity.
BuildMI(MBB, MI, DL, TII->get(RISCV::SSPOPCHK))
.addReg(RAReg)
.setMIFlag(MachineInstr::FrameDestroy);
return;
}
+ assert(SSK == RISCVMachineFunctionInfo::ShadowStackKind::Software &&
+ "Unexpected Shadow Stack Kind");
+
Register SCSPReg = RISCVABI::getSCSPReg();
bool IsRV64 = STI.is64Bit();
@@ -1361,23 +1361,8 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
getUnmanagedCSI(MF, CSI, PreferAscendingLS).size());
CFIBuilder.setInsertPoint(MBBI);
- if (getLibCallID(MF, CSI) != -1) {
- // tail __riscv_restore_[0-12] instruction is considered as a terminator,
- // therefore it is unnecessary to place any CFI instructions after it. Just
- // deallocate stack if needed and return.
- if (StackSize != 0)
- deallocateStack(MF, MBB, MBBI, DL, StackSize,
- RVFI->getLibCallStackSize());
-
- // Emit epilogue for shadow call stack.
- emitSCSEpilogue(MF, MBB, MBBI, DL);
- return;
- }
-
- // Recover callee-saved registers.
- if (NeedsDwarfCFI) {
- for (const CalleeSavedInfo &CS :
- getUnmanagedCSI(MF, CSI, PreferAscendingLS)) {
+ auto emitRestoreCFI = [&](auto CSInfo) {
+ for (auto &CS : CSInfo) {
MCRegister Reg = CS.getReg();
// Emit CFI for both sub-registers.
if (RISCV::GPRPairRegClass.contains(Reg)) {
@@ -1389,8 +1374,41 @@ void RISCVFrameLowering::emitEpilogue(MachineFunction &MF,
CFIBuilder.buildRestore(Reg);
}
}
+ };
+
+ if (RVFI->useSaveRestoreLibCalls(MF)) {
+ if (RVFI->hasShadowStack(MF)) {
+ // We don't use `__riscv_restore_<N>` to restore in this case, so we need
+ // to make sure we're correctly accounting for the stack deallocation we
+ // need to do, which now must include the allocation made by
+ // `__riscv_save_<N>`.
+ StackSize += RVFI->getLibCallStackSize();
+
+ SmallVector<CalleeSavedInfo, 8> LibcallCSI =
+ getPushOrLibCallsSavedInfo(MF, CSI);
+ MBBI = std::next(MBBI, LibcallCSI.size());
+ CFIBuilder.setInsertPoint(MBBI);
+
+ if (NeedsDwarfCFI)
+ emitRestoreCFI(LibcallCSI);
+ } else {
+ // tail __riscv_restore_[0-12] instruction is considered as a terminator,
+ // therefore it is unnecessary to place any CFI instructions after it.
+ // Just deallocate stack if needed and return.
+ if (StackSize != 0)
+ deallocateStack(MF, MBB, MBBI, DL, StackSize,
+ RVFI->getLibCallStackSize());
+
+ // Emit epilogue for shadow call stack.
+ emitSCSEpilogue(MF, MBB, MBBI, DL);
+ return;
+ }
}
+ // Recover callee-saved registers.
+ if (NeedsDwarfCFI)
+ emitRestoreCFI(getUnmanagedCSI(MF, CSI, PreferAscendingLS));
+
if (RVFI->isPushable(MF) && MBBI != MBB.end() && isPop(MBBI->getOpcode())) {
// Use available stack adjustment in pop instruction to deallocate stack
// space. Align the stack size down to a multiple of 16. This is needed for
@@ -2496,7 +2514,7 @@ bool RISCVFrameLowering::restoreCalleeSavedRegisters(
getUnmanagedCSI(*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);
@@ -2534,6 +2552,13 @@ bool RISCVFrameLowering::restoreCalleeSavedRegisters(
PopBuilder.addDef(FixedCSRFIMap[i], RegState::ImplicitDefine);
}
} else if (const char *RestoreLibCall = getRestoreLibCallName(*MF, CSI)) {
+ // Restore is not compatible with shadow stacks, so do the restore manually.
+ // This ensures we still get the code size saving of `__riscv_save_<N>`.
+ if (RVFI->hasShadowStack(*MF)) {
+ loadRegFromStackSlot(CSI);
+ return true;
+ }
+
// Add restore libcall via tail call.
MachineInstrBuilder NewMI =
BuildMI(MBB, MI, DL, TII.get(RISCV::PseudoTAIL))
@@ -2601,6 +2626,10 @@ bool RISCVFrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const {
if (RVFI->useQCIInterrupt(*MF))
return MBB.succ_empty();
+ // If we have a shadow stack, we don't use `__riscv_restore` libcalls.
+ if (RVFI->hasShadowStack(*MF))
+ return true;
+
if (!RVFI->useSaveRestoreLibCalls(*MF))
return true;
diff --git a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
index 4944df1e731a8..f185ddb4b1ae3 100644
--- a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.cpp
@@ -87,6 +87,24 @@ void yaml::RISCVMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
MappingTraits<RISCVMachineFunctionInfo>::mapping(YamlIO, *this);
}
+RISCVMachineFunctionInfo::ShadowStackKind
+RISCVMachineFunctionInfo::getShadowStackKind(const MachineFunction &MF) const {
+ // Prefer HW Shadow Stack
+ //
+ // Zicfiss is encoded using a Zimop, so that's the only extension we have to
+ // check here. MOPs will be compressed if they have the right structure to.
+ if (MF.getSubtarget<RISCVSubtarget>().hasStdExtZimop() &&
+ MF.getFunction().hasFnAttribute("hw-shadow-stack"))
+ return ShadowStackKind::Hardware;
+
+ // ShadowCallStack attribute is used for software shadow call stack
+ if (MF.getFunction().hasFnAttribute(Attribute::ShadowCallStack))
+ return ShadowStackKind::Software;
+
+ // Otherwise, none
+ return ShadowStackKind::None;
+}
+
RISCVMachineFunctionInfo::PushPopKind
RISCVMachineFunctionInfo::getPushPopKind(const MachineFunction &MF) const {
// We cannot use fixed locations for the callee saved spill slots if the
diff --git a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
index 06ef7661385c2..3aaf7466d7425 100644
--- a/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
+++ b/llvm/lib/Target/RISCV/RISCVMachineFunctionInfo.h
@@ -163,6 +163,13 @@ class RISCVMachineFunctionInfo : public MachineFunctionInfo {
return It->second;
}
+ enum class ShadowStackKind { None = 0, Hardware, Software };
+
+ ShadowStackKind getShadowStackKind(const MachineFunction &MF) const;
+ bool hasShadowStack(const MachineFunction &MF) const {
+ return getShadowStackKind(MF) != ShadowStackKind::None;
+ }
+
enum class PushPopKind { None = 0, StdExtZcmp, VendorXqccmp };
PushPopKind getPushPopKind(const MachineFunction &MF) const;
diff --git a/llvm/test/CodeGen/RISCV/saverestore-scs.ll b/llvm/test/CodeGen/RISCV/saverestore-scs.ll
index 6072943b38477..52ea38ae4bb0c 100644
--- a/llvm/test/CodeGen/RISCV/saverestore-scs.ll
+++ b/llvm/test/CodeGen/RISCV/saverestore-scs.ll
@@ -1,4 +1,5 @@
-;; Check that shadow call stack doesn't interfere with save/restore
+;; Check that shadow call stack can use save routines but does not use restore
+;; routines.
; RUN: llc -mtriple=riscv32 < %s | FileCheck %s -check-prefix=RV32I
; RUN: llc -mtriple=riscv64 < %s | FileCheck %s -check-prefix=RV64I
@@ -12,27 +13,27 @@
define void @callee_scs() nounwind shadowcallstack {
; RV32I-LABEL: callee_scs:
; RV32I-NOT: call t0, __riscv_save
-; RV32I-NOT: tail __riscv_restore
+; RV32I-NOT: __riscv_restore
;
; RV64I-LABEL: callee_scs:
; RV64I-NOT: call t0, __riscv_save
-; RV64I-NOT: tail __riscv_restore
+; RV64I-NOT: __riscv_restore
;
; RV32I-SR-LABEL: callee_scs:
; RV32I-SR: call t0, __riscv_save_12
-; RV32I-SR: tail __riscv_restore_12
+; RV32I-SR-NOT: __riscv_restore_12
;
; RV64I-SR-LABEL: callee_scs:
; RV64I-SR: call t0, __riscv_save_12
-; RV64I-SR: tail __riscv_restore_12
+; RV64I-SR-NOT: __riscv_restore_12
;
; RV32I-FP-SR-LABEL: callee_scs:
; RV32I-FP-SR: call t0, __riscv_save_12
-; RV32I-FP-SR: tail __riscv_restore_12
+; RV32I-FP-SR-NOT: __riscv_restore_12
;
; RV64I-FP-SR-LABEL: callee_scs:
; RV64I-FP-SR: call t0, __riscv_save_12
-; RV64I-FP-SR: tail __riscv_restore_12
+; RV64I-FP-SR-NOT: __riscv_restore_12
%val = load [30 x i32], ptr @var2
store volatile [30 x i32] %val, ptr @var2
ret void
diff --git a/llvm/test/CodeGen/RISCV/shadow-stack-frame-opts.ll b/llvm/test/CodeGen/RISCV/shadow-stack-frame-opts.ll
new file mode 100644
index 0000000000000..e73c461eaa81f
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/shadow-stack-frame-opts.ll
@@ -0,0 +1,1871 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+
+
+; RUN: llc -mtriple=riscv32 -mattr=+zimop < %s \
+; RUN: | FileCheck %s --check-prefix=RV32
+; RUN: llc -mtriple=riscv32 -mattr=+zimop,+save-restore < %s \
+; RUN: | FileCheck %s --check-prefix=RV32-SAVE-RESTORE
+; RUN: llc -mtriple=riscv32 -mattr=+zimop,+zcmp < %s \
+; RUN: | FileCheck %s --check-prefix=RV32-ZCMP
+; RUN: llc -mtriple=riscv32 -mattr=+zimop,+zcmp,+save-restore < %s \
+; RUN: | FileCheck %s --check-prefix=RV32-ZCMP-SAVE-RESTORE
+; RUN: llc -mtriple=riscv32 -mattr=+zimop,+xqccmp < %s \
+; RUN: | FileCheck %s --check-prefix=RV32-XQCCMP
+
+; RUN: llc -mtriple=riscv64 -mattr=+zimop < %s \
+; RUN: | FileCheck %s --check-prefix=RV64
+; RUN: llc -mtriple=riscv64 -mattr=+zimop,+save-restore < %s \
+; RUN: | FileCheck %s --check-prefix=RV64-SAVE-RESTORE
+; RUN: llc -mtriple=riscv64 -mattr=+zimop,+zcmp < %s \
+; RUN: | FileCheck %s --check-prefix=RV64-ZCMP
+; RUN: llc -mtriple=riscv64 -mattr=+zimop,+zcmp,+save-restore < %s \
+; RUN: | FileCheck %s --check-prefix=RV64-ZCMP-SAVE-RESTORE
+; RUN: llc -mtriple=riscv64 -mattr=+zimop,+xqccmp < %s \
+; RUN: | FileCheck %s --check-prefix=RV64-XQCCMP
+
+declare i32 @callee(i32 %x)
+
+;; Software Shadow Call Stack
+
+define i32 @caller_sw(i32 %x) shadowcallstack {
+; RV32-LABEL: caller_sw:
+; RV32: # %bb.0:
+; RV32-NEXT: addi gp, gp, 4
+; RV32-NEXT: sw ra, -4(gp)
+; RV32-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: .cfi_def_cfa_offset 16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -4
+; RV32-NEXT: neg a0, a0
+; RV32-NEXT: call callee
+; RV32-NEXT: addi a0, a0, 1
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: lw ra, -4(gp)
+; RV32-NEXT: addi gp, gp, -4
+; RV32-NEXT: .cfi_restore gp
+; RV32-NEXT: ret
+;
+; RV32-SAVE-RESTORE-LABEL: caller_sw:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-SAVE-RESTORE-NEXT: call callee
+; RV32-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32-SAVE-RESTORE-NEXT: ret
+;
+; RV32-ZCMP-LABEL: caller_sw:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: addi gp, gp, 4
+; RV32-ZCMP-NEXT: sw ra, -4(gp)
+; RV32-ZCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-ZCMP-NEXT: cm.push {ra}, -16
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-NEXT: neg a0, a0
+; RV32-ZCMP-NEXT: call callee
+; RV32-ZCMP-NEXT: addi a0, a0, 1
+; RV32-ZCMP-NEXT: cm.pop {ra}, 16
+; RV32-ZCMP-NEXT: lw ra, -4(gp)
+; RV32-ZCMP-NEXT: addi gp, gp, -4
+; RV32-ZCMP-NEXT: .cfi_restore gp
+; RV32-ZCMP-NEXT: ret
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_sw:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra}, -16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra}, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV32-XQCCMP-LABEL: caller_sw:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: addi gp, gp, 4
+; RV32-XQCCMP-NEXT: sw ra, -4(gp)
+; RV32-XQCCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-XQCCMP-NEXT: qc.cm.push {ra}, -16
+; RV32-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-XQCCMP-NEXT: .cfi_offset ra, -4
+; RV32-XQCCMP-NEXT: neg a0, a0
+; RV32-XQCCMP-NEXT: call callee
+; RV32-XQCCMP-NEXT: addi a0, a0, 1
+; RV32-XQCCMP-NEXT: qc.cm.pop {ra}, 16
+; RV32-XQCCMP-NEXT: lw ra, -4(gp)
+; RV32-XQCCMP-NEXT: addi gp, gp, -4
+; RV32-XQCCMP-NEXT: .cfi_restore gp
+; RV32-XQCCMP-NEXT: ret
+;
+; RV64-LABEL: caller_sw:
+; RV64: # %bb.0:
+; RV64-NEXT: addi gp, gp, 8
+; RV64-NEXT: sd ra, -8(gp)
+; RV64-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: .cfi_def_cfa_offset 16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -8
+; RV64-NEXT: negw a0, a0
+; RV64-NEXT: call callee
+; RV64-NEXT: addiw a0, a0, 1
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: ld ra, -8(gp)
+; RV64-NEXT: addi gp, gp, -8
+; RV64-NEXT: .cfi_restore gp
+; RV64-NEXT: ret
+;
+; RV64-SAVE-RESTORE-LABEL: caller_sw:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-SAVE-RESTORE-NEXT: call callee
+; RV64-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64-SAVE-RESTORE-NEXT: ret
+;
+; RV64-ZCMP-LABEL: caller_sw:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: addi gp, gp, 8
+; RV64-ZCMP-NEXT: sd ra, -8(gp)
+; RV64-ZCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-ZCMP-NEXT: cm.push {ra}, -16
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-NEXT: negw a0, a0
+; RV64-ZCMP-NEXT: call callee
+; RV64-ZCMP-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-NEXT: cm.pop {ra}, 16
+; RV64-ZCMP-NEXT: ld ra, -8(gp)
+; RV64-ZCMP-NEXT: addi gp, gp, -8
+; RV64-ZCMP-NEXT: .cfi_restore gp
+; RV64-ZCMP-NEXT: ret
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_sw:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra}, -16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra}, 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV64-XQCCMP-LABEL: caller_sw:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: addi gp, gp, 8
+; RV64-XQCCMP-NEXT: sd ra, -8(gp)
+; RV64-XQCCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-XQCCMP-NEXT: qc.cm.push {ra}, -16
+; RV64-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-XQCCMP-NEXT: .cfi_offset ra, -8
+; RV64-XQCCMP-NEXT: negw a0, a0
+; RV64-XQCCMP-NEXT: call callee
+; RV64-XQCCMP-NEXT: addiw a0, a0, 1
+; RV64-XQCCMP-NEXT: qc.cm.pop {ra}, 16
+; RV64-XQCCMP-NEXT: ld ra, -8(gp)
+; RV64-XQCCMP-NEXT: addi gp, gp, -8
+; RV64-XQCCMP-NEXT: .cfi_restore gp
+; RV64-XQCCMP-NEXT: ret
+ %sub = sub nsw i32 0, %x
+ %call = tail call i32 @callee(i32 %sub)
+ %add = add nsw i32 %call, 1
+ ret i32 %add
+}
+
+define i32 @caller_sw_tail(i32 %x) shadowcallstack {
+; RV32-LABEL: caller_sw_tail:
+; RV32: # %bb.0:
+; RV32-NEXT: neg a0, a0
+; RV32-NEXT: tail callee
+;
+; RV32-SAVE-RESTORE-LABEL: caller_sw_tail:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-SAVE-RESTORE-NEXT: tail callee
+;
+; RV32-ZCMP-LABEL: caller_sw_tail:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: neg a0, a0
+; RV32-ZCMP-NEXT: tail callee
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_sw_tail:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: tail callee
+;
+; RV32-XQCCMP-LABEL: caller_sw_tail:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: neg a0, a0
+; RV32-XQCCMP-NEXT: tail callee
+;
+; RV64-LABEL: caller_sw_tail:
+; RV64: # %bb.0:
+; RV64-NEXT: negw a0, a0
+; RV64-NEXT: tail callee
+;
+; RV64-SAVE-RESTORE-LABEL: caller_sw_tail:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-SAVE-RESTORE-NEXT: tail callee
+;
+; RV64-ZCMP-LABEL: caller_sw_tail:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: negw a0, a0
+; RV64-ZCMP-NEXT: tail callee
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_sw_tail:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: tail callee
+;
+; RV64-XQCCMP-LABEL: caller_sw_tail:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: negw a0, a0
+; RV64-XQCCMP-NEXT: tail callee
+ %sub = sub nsw i32 0, %x
+ %call = tail call i32 @callee(i32 %sub)
+ ret i32 %call
+}
+
+define i32 @caller_sw_fp(i32 %x) shadowcallstack "frame-pointer"="all" {
+; RV32-LABEL: caller_sw_fp:
+; RV32: # %bb.0:
+; RV32-NEXT: addi gp, gp, 4
+; RV32-NEXT: sw ra, -4(gp)
+; RV32-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: .cfi_def_cfa_offset 16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -4
+; RV32-NEXT: .cfi_offset s0, -8
+; RV32-NEXT: addi s0, sp, 16
+; RV32-NEXT: .cfi_def_cfa s0, 0
+; RV32-NEXT: neg a0, a0
+; RV32-NEXT: call callee
+; RV32-NEXT: addi a0, a0, 1
+; RV32-NEXT: .cfi_def_cfa sp, 16
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore s0
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: lw ra, -4(gp)
+; RV32-NEXT: addi gp, gp, -4
+; RV32-NEXT: .cfi_restore gp
+; RV32-NEXT: ret
+;
+; RV32-SAVE-RESTORE-LABEL: caller_sw_fp:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset s0, -8
+; RV32-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV32-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-SAVE-RESTORE-NEXT: call callee
+; RV32-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV32-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV32-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32-SAVE-RESTORE-NEXT: ret
+;
+; RV32-ZCMP-LABEL: caller_sw_fp:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: addi gp, gp, 4
+; RV32-ZCMP-NEXT: sw ra, -4(gp)
+; RV32-ZCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-ZCMP-NEXT: addi sp, sp, -16
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-ZCMP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32-ZCMP-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-NEXT: .cfi_offset s0, -8
+; RV32-ZCMP-NEXT: addi s0, sp, 16
+; RV32-ZCMP-NEXT: .cfi_def_cfa s0, 0
+; RV32-ZCMP-NEXT: neg a0, a0
+; RV32-ZCMP-NEXT: call callee
+; RV32-ZCMP-NEXT: addi a0, a0, 1
+; RV32-ZCMP-NEXT: .cfi_def_cfa sp, 16
+; RV32-ZCMP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-ZCMP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-ZCMP-NEXT: .cfi_restore ra
+; RV32-ZCMP-NEXT: .cfi_restore s0
+; RV32-ZCMP-NEXT: addi sp, sp, 16
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 0
+; RV32-ZCMP-NEXT: lw ra, -4(gp)
+; RV32-ZCMP-NEXT: addi gp, gp, -4
+; RV32-ZCMP-NEXT: .cfi_restore gp
+; RV32-ZCMP-NEXT: ret
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_sw_fp:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s0, -8
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-ZCMP-SAVE-RESTORE-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV32-XQCCMP-LABEL: caller_sw_fp:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: addi gp, gp, 4
+; RV32-XQCCMP-NEXT: sw ra, -4(gp)
+; RV32-XQCCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-XQCCMP-NEXT: qc.cm.pushfp {ra, s0}, -16
+; RV32-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-XQCCMP-NEXT: .cfi_offset ra, -4
+; RV32-XQCCMP-NEXT: .cfi_offset s0, -8
+; RV32-XQCCMP-NEXT: .cfi_def_cfa s0, 0
+; RV32-XQCCMP-NEXT: neg a0, a0
+; RV32-XQCCMP-NEXT: call callee
+; RV32-XQCCMP-NEXT: addi a0, a0, 1
+; RV32-XQCCMP-NEXT: .cfi_def_cfa sp, 16
+; RV32-XQCCMP-NEXT: qc.cm.pop {ra, s0}, 16
+; RV32-XQCCMP-NEXT: lw ra, -4(gp)
+; RV32-XQCCMP-NEXT: addi gp, gp, -4
+; RV32-XQCCMP-NEXT: .cfi_restore gp
+; RV32-XQCCMP-NEXT: ret
+;
+; RV64-LABEL: caller_sw_fp:
+; RV64: # %bb.0:
+; RV64-NEXT: addi gp, gp, 8
+; RV64-NEXT: sd ra, -8(gp)
+; RV64-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: .cfi_def_cfa_offset 16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s0, 0(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -8
+; RV64-NEXT: .cfi_offset s0, -16
+; RV64-NEXT: addi s0, sp, 16
+; RV64-NEXT: .cfi_def_cfa s0, 0
+; RV64-NEXT: negw a0, a0
+; RV64-NEXT: call callee
+; RV64-NEXT: addiw a0, a0, 1
+; RV64-NEXT: .cfi_def_cfa sp, 16
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: .cfi_restore s0
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: ld ra, -8(gp)
+; RV64-NEXT: addi gp, gp, -8
+; RV64-NEXT: .cfi_restore gp
+; RV64-NEXT: ret
+;
+; RV64-SAVE-RESTORE-LABEL: caller_sw_fp:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset s0, -16
+; RV64-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV64-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-SAVE-RESTORE-NEXT: call callee
+; RV64-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV64-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV64-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64-SAVE-RESTORE-NEXT: ret
+;
+; RV64-ZCMP-LABEL: caller_sw_fp:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: addi gp, gp, 8
+; RV64-ZCMP-NEXT: sd ra, -8(gp)
+; RV64-ZCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-ZCMP-NEXT: addi sp, sp, -16
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-ZCMP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill
+; RV64-ZCMP-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-NEXT: .cfi_offset s0, -16
+; RV64-ZCMP-NEXT: addi s0, sp, 16
+; RV64-ZCMP-NEXT: .cfi_def_cfa s0, 0
+; RV64-ZCMP-NEXT: negw a0, a0
+; RV64-ZCMP-NEXT: call callee
+; RV64-ZCMP-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-NEXT: .cfi_def_cfa sp, 16
+; RV64-ZCMP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-ZCMP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
+; RV64-ZCMP-NEXT: .cfi_restore ra
+; RV64-ZCMP-NEXT: .cfi_restore s0
+; RV64-ZCMP-NEXT: addi sp, sp, 16
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 0
+; RV64-ZCMP-NEXT: ld ra, -8(gp)
+; RV64-ZCMP-NEXT: addi gp, gp, -8
+; RV64-ZCMP-NEXT: .cfi_restore gp
+; RV64-ZCMP-NEXT: ret
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_sw_fp:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s0, -16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV64-XQCCMP-LABEL: caller_sw_fp:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: addi gp, gp, 8
+; RV64-XQCCMP-NEXT: sd ra, -8(gp)
+; RV64-XQCCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-XQCCMP-NEXT: qc.cm.pushfp {ra, s0}, -16
+; RV64-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-XQCCMP-NEXT: .cfi_offset ra, -8
+; RV64-XQCCMP-NEXT: .cfi_offset s0, -16
+; RV64-XQCCMP-NEXT: .cfi_def_cfa s0, 0
+; RV64-XQCCMP-NEXT: negw a0, a0
+; RV64-XQCCMP-NEXT: call callee
+; RV64-XQCCMP-NEXT: addiw a0, a0, 1
+; RV64-XQCCMP-NEXT: .cfi_def_cfa sp, 16
+; RV64-XQCCMP-NEXT: qc.cm.pop {ra, s0}, 16
+; RV64-XQCCMP-NEXT: ld ra, -8(gp)
+; RV64-XQCCMP-NEXT: addi gp, gp, -8
+; RV64-XQCCMP-NEXT: .cfi_restore gp
+; RV64-XQCCMP-NEXT: ret
+ %sub = sub nsw i32 0, %x
+ %call = tail call i32 @callee(i32 %sub)
+ %add = add nsw i32 %call, 1
+ ret i32 %add
+}
+
+define i32 @caller_sw_cond(i32 %x) shadowcallstack {
+; RV32-LABEL: caller_sw_cond:
+; RV32: # %bb.0:
+; RV32-NEXT: beqz a0, .LBB3_2
+; RV32-NEXT: # %bb.1: # %if.end
+; RV32-NEXT: addi gp, gp, 4
+; RV32-NEXT: sw ra, -4(gp)
+; RV32-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: .cfi_def_cfa_offset 16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -4
+; RV32-NEXT: neg a0, a0
+; RV32-NEXT: call callee
+; RV32-NEXT: addi a0, a0, 1
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: lw ra, -4(gp)
+; RV32-NEXT: addi gp, gp, -4
+; RV32-NEXT: .cfi_restore gp
+; RV32-NEXT: ret
+; RV32-NEXT: .LBB3_2: # %return
+; RV32-NEXT: li a0, 1
+; RV32-NEXT: ret
+;
+; RV32-SAVE-RESTORE-LABEL: caller_sw_cond:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: beqz a0, .LBB3_2
+; RV32-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV32-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-SAVE-RESTORE-NEXT: call callee
+; RV32-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32-SAVE-RESTORE-NEXT: ret
+; RV32-SAVE-RESTORE-NEXT: .LBB3_2: # %return
+; RV32-SAVE-RESTORE-NEXT: li a0, 1
+; RV32-SAVE-RESTORE-NEXT: ret
+;
+; RV32-ZCMP-LABEL: caller_sw_cond:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: beqz a0, .LBB3_2
+; RV32-ZCMP-NEXT: # %bb.1: # %if.end
+; RV32-ZCMP-NEXT: addi gp, gp, 4
+; RV32-ZCMP-NEXT: sw ra, -4(gp)
+; RV32-ZCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-ZCMP-NEXT: cm.push {ra}, -16
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-NEXT: neg a0, a0
+; RV32-ZCMP-NEXT: call callee
+; RV32-ZCMP-NEXT: addi a0, a0, 1
+; RV32-ZCMP-NEXT: cm.pop {ra}, 16
+; RV32-ZCMP-NEXT: lw ra, -4(gp)
+; RV32-ZCMP-NEXT: addi gp, gp, -4
+; RV32-ZCMP-NEXT: .cfi_restore gp
+; RV32-ZCMP-NEXT: ret
+; RV32-ZCMP-NEXT: .LBB3_2: # %return
+; RV32-ZCMP-NEXT: li a0, 1
+; RV32-ZCMP-NEXT: ret
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_sw_cond:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: beqz a0, .LBB3_2
+; RV32-ZCMP-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra}, -16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra}, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .LBB3_2: # %return
+; RV32-ZCMP-SAVE-RESTORE-NEXT: li a0, 1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV32-XQCCMP-LABEL: caller_sw_cond:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: beqz a0, .LBB3_2
+; RV32-XQCCMP-NEXT: # %bb.1: # %if.end
+; RV32-XQCCMP-NEXT: addi gp, gp, 4
+; RV32-XQCCMP-NEXT: sw ra, -4(gp)
+; RV32-XQCCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-XQCCMP-NEXT: qc.cm.push {ra}, -16
+; RV32-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-XQCCMP-NEXT: .cfi_offset ra, -4
+; RV32-XQCCMP-NEXT: neg a0, a0
+; RV32-XQCCMP-NEXT: call callee
+; RV32-XQCCMP-NEXT: addi a0, a0, 1
+; RV32-XQCCMP-NEXT: qc.cm.pop {ra}, 16
+; RV32-XQCCMP-NEXT: lw ra, -4(gp)
+; RV32-XQCCMP-NEXT: addi gp, gp, -4
+; RV32-XQCCMP-NEXT: .cfi_restore gp
+; RV32-XQCCMP-NEXT: ret
+; RV32-XQCCMP-NEXT: .LBB3_2: # %return
+; RV32-XQCCMP-NEXT: li a0, 1
+; RV32-XQCCMP-NEXT: ret
+;
+; RV64-LABEL: caller_sw_cond:
+; RV64: # %bb.0:
+; RV64-NEXT: sext.w a1, a0
+; RV64-NEXT: beqz a1, .LBB3_2
+; RV64-NEXT: # %bb.1: # %if.end
+; RV64-NEXT: addi gp, gp, 8
+; RV64-NEXT: sd ra, -8(gp)
+; RV64-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: .cfi_def_cfa_offset 16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -8
+; RV64-NEXT: negw a0, a0
+; RV64-NEXT: call callee
+; RV64-NEXT: addiw a0, a0, 1
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: ld ra, -8(gp)
+; RV64-NEXT: addi gp, gp, -8
+; RV64-NEXT: .cfi_restore gp
+; RV64-NEXT: ret
+; RV64-NEXT: .LBB3_2: # %return
+; RV64-NEXT: li a0, 1
+; RV64-NEXT: ret
+;
+; RV64-SAVE-RESTORE-LABEL: caller_sw_cond:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: sext.w a1, a0
+; RV64-SAVE-RESTORE-NEXT: beqz a1, .LBB3_2
+; RV64-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV64-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-SAVE-RESTORE-NEXT: call callee
+; RV64-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64-SAVE-RESTORE-NEXT: ret
+; RV64-SAVE-RESTORE-NEXT: .LBB3_2: # %return
+; RV64-SAVE-RESTORE-NEXT: li a0, 1
+; RV64-SAVE-RESTORE-NEXT: ret
+;
+; RV64-ZCMP-LABEL: caller_sw_cond:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: sext.w a1, a0
+; RV64-ZCMP-NEXT: beqz a1, .LBB3_2
+; RV64-ZCMP-NEXT: # %bb.1: # %if.end
+; RV64-ZCMP-NEXT: addi gp, gp, 8
+; RV64-ZCMP-NEXT: sd ra, -8(gp)
+; RV64-ZCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-ZCMP-NEXT: cm.push {ra}, -16
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-NEXT: negw a0, a0
+; RV64-ZCMP-NEXT: call callee
+; RV64-ZCMP-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-NEXT: cm.pop {ra}, 16
+; RV64-ZCMP-NEXT: ld ra, -8(gp)
+; RV64-ZCMP-NEXT: addi gp, gp, -8
+; RV64-ZCMP-NEXT: .cfi_restore gp
+; RV64-ZCMP-NEXT: ret
+; RV64-ZCMP-NEXT: .LBB3_2: # %return
+; RV64-ZCMP-NEXT: li a0, 1
+; RV64-ZCMP-NEXT: ret
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_sw_cond:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sext.w a1, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: beqz a1, .LBB3_2
+; RV64-ZCMP-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra}, -16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra}, 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .LBB3_2: # %return
+; RV64-ZCMP-SAVE-RESTORE-NEXT: li a0, 1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV64-XQCCMP-LABEL: caller_sw_cond:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: sext.w a1, a0
+; RV64-XQCCMP-NEXT: beqz a1, .LBB3_2
+; RV64-XQCCMP-NEXT: # %bb.1: # %if.end
+; RV64-XQCCMP-NEXT: addi gp, gp, 8
+; RV64-XQCCMP-NEXT: sd ra, -8(gp)
+; RV64-XQCCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-XQCCMP-NEXT: qc.cm.push {ra}, -16
+; RV64-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-XQCCMP-NEXT: .cfi_offset ra, -8
+; RV64-XQCCMP-NEXT: negw a0, a0
+; RV64-XQCCMP-NEXT: call callee
+; RV64-XQCCMP-NEXT: addiw a0, a0, 1
+; RV64-XQCCMP-NEXT: qc.cm.pop {ra}, 16
+; RV64-XQCCMP-NEXT: ld ra, -8(gp)
+; RV64-XQCCMP-NEXT: addi gp, gp, -8
+; RV64-XQCCMP-NEXT: .cfi_restore gp
+; RV64-XQCCMP-NEXT: ret
+; RV64-XQCCMP-NEXT: .LBB3_2: # %return
+; RV64-XQCCMP-NEXT: li a0, 1
+; RV64-XQCCMP-NEXT: ret
+ %cmp = icmp eq i32 %x, 0
+ br i1 %cmp, label %return, label %if.end
+
+if.end:
+ %sub = sub nsw i32 0, %x
+ %call = tail call i32 @callee(i32 %sub)
+ %add = add nsw i32 %call, 1
+ ret i32 %add
+
+return:
+ ret i32 1
+}
+
+define i32 @caller_sw_clobber_s11(i32 %x) shadowcallstack {
+; RV32-LABEL: caller_sw_clobber_s11:
+; RV32: # %bb.0:
+; RV32-NEXT: addi gp, gp, 4
+; RV32-NEXT: sw ra, -4(gp)
+; RV32-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: .cfi_def_cfa_offset 16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s11, 8(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -4
+; RV32-NEXT: .cfi_offset s11, -8
+; RV32-NEXT: neg a0, a0
+; RV32-NEXT: call callee
+; RV32-NEXT: addi a0, a0, 1
+; RV32-NEXT: #APP
+; RV32-NEXT: nop
+; RV32-NEXT: #NO_APP
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s11, 8(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore s11
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: lw ra, -4(gp)
+; RV32-NEXT: addi gp, gp, -4
+; RV32-NEXT: .cfi_restore gp
+; RV32-NEXT: ret
+;
+; RV32-SAVE-RESTORE-LABEL: caller_sw_clobber_s11:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-SAVE-RESTORE-NEXT: call t0, __riscv_save_12
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 64
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset s11, -52
+; RV32-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-SAVE-RESTORE-NEXT: call callee
+; RV32-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-SAVE-RESTORE-NEXT: #APP
+; RV32-SAVE-RESTORE-NEXT: nop
+; RV32-SAVE-RESTORE-NEXT: #NO_APP
+; RV32-SAVE-RESTORE-NEXT: lw ra, 60(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: lw s11, 12(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore s11
+; RV32-SAVE-RESTORE-NEXT: addi sp, sp, 64
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32-SAVE-RESTORE-NEXT: ret
+;
+; RV32-ZCMP-LABEL: caller_sw_clobber_s11:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: addi gp, gp, 4
+; RV32-ZCMP-NEXT: sw ra, -4(gp)
+; RV32-ZCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-ZCMP-NEXT: cm.push {ra, s0-s11}, -64
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 64
+; RV32-ZCMP-NEXT: .cfi_offset ra, -52
+; RV32-ZCMP-NEXT: .cfi_offset s11, -4
+; RV32-ZCMP-NEXT: neg a0, a0
+; RV32-ZCMP-NEXT: call callee
+; RV32-ZCMP-NEXT: addi a0, a0, 1
+; RV32-ZCMP-NEXT: #APP
+; RV32-ZCMP-NEXT: nop
+; RV32-ZCMP-NEXT: #NO_APP
+; RV32-ZCMP-NEXT: cm.pop {ra, s0-s11}, 64
+; RV32-ZCMP-NEXT: lw ra, -4(gp)
+; RV32-ZCMP-NEXT: addi gp, gp, -4
+; RV32-ZCMP-NEXT: .cfi_restore gp
+; RV32-ZCMP-NEXT: ret
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_sw_clobber_s11:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra, s0-s11}, -64
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 64
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -52
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s11, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: #APP
+; RV32-ZCMP-SAVE-RESTORE-NEXT: nop
+; RV32-ZCMP-SAVE-RESTORE-NEXT: #NO_APP
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra, s0-s11}, 64
+; RV32-ZCMP-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV32-XQCCMP-LABEL: caller_sw_clobber_s11:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: addi gp, gp, 4
+; RV32-XQCCMP-NEXT: sw ra, -4(gp)
+; RV32-XQCCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-XQCCMP-NEXT: qc.cm.push {ra, s0-s11}, -64
+; RV32-XQCCMP-NEXT: .cfi_def_cfa_offset 64
+; RV32-XQCCMP-NEXT: .cfi_offset ra, -4
+; RV32-XQCCMP-NEXT: .cfi_offset s11, -52
+; RV32-XQCCMP-NEXT: neg a0, a0
+; RV32-XQCCMP-NEXT: call callee
+; RV32-XQCCMP-NEXT: addi a0, a0, 1
+; RV32-XQCCMP-NEXT: #APP
+; RV32-XQCCMP-NEXT: nop
+; RV32-XQCCMP-NEXT: #NO_APP
+; RV32-XQCCMP-NEXT: qc.cm.pop {ra, s0-s11}, 64
+; RV32-XQCCMP-NEXT: lw ra, -4(gp)
+; RV32-XQCCMP-NEXT: addi gp, gp, -4
+; RV32-XQCCMP-NEXT: .cfi_restore gp
+; RV32-XQCCMP-NEXT: ret
+;
+; RV64-LABEL: caller_sw_clobber_s11:
+; RV64: # %bb.0:
+; RV64-NEXT: addi gp, gp, 8
+; RV64-NEXT: sd ra, -8(gp)
+; RV64-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: .cfi_def_cfa_offset 16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s11, 0(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -8
+; RV64-NEXT: .cfi_offset s11, -16
+; RV64-NEXT: negw a0, a0
+; RV64-NEXT: call callee
+; RV64-NEXT: addiw a0, a0, 1
+; RV64-NEXT: #APP
+; RV64-NEXT: nop
+; RV64-NEXT: #NO_APP
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s11, 0(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: .cfi_restore s11
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: ld ra, -8(gp)
+; RV64-NEXT: addi gp, gp, -8
+; RV64-NEXT: .cfi_restore gp
+; RV64-NEXT: ret
+;
+; RV64-SAVE-RESTORE-LABEL: caller_sw_clobber_s11:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-SAVE-RESTORE-NEXT: call t0, __riscv_save_12
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 112
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset s11, -104
+; RV64-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-SAVE-RESTORE-NEXT: call callee
+; RV64-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-SAVE-RESTORE-NEXT: #APP
+; RV64-SAVE-RESTORE-NEXT: nop
+; RV64-SAVE-RESTORE-NEXT: #NO_APP
+; RV64-SAVE-RESTORE-NEXT: ld ra, 104(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: ld s11, 8(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore s11
+; RV64-SAVE-RESTORE-NEXT: addi sp, sp, 112
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64-SAVE-RESTORE-NEXT: ret
+;
+; RV64-ZCMP-LABEL: caller_sw_clobber_s11:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: addi gp, gp, 8
+; RV64-ZCMP-NEXT: sd ra, -8(gp)
+; RV64-ZCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-ZCMP-NEXT: cm.push {ra, s0-s11}, -112
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 112
+; RV64-ZCMP-NEXT: .cfi_offset ra, -104
+; RV64-ZCMP-NEXT: .cfi_offset s11, -8
+; RV64-ZCMP-NEXT: negw a0, a0
+; RV64-ZCMP-NEXT: call callee
+; RV64-ZCMP-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-NEXT: #APP
+; RV64-ZCMP-NEXT: nop
+; RV64-ZCMP-NEXT: #NO_APP
+; RV64-ZCMP-NEXT: cm.pop {ra, s0-s11}, 112
+; RV64-ZCMP-NEXT: ld ra, -8(gp)
+; RV64-ZCMP-NEXT: addi gp, gp, -8
+; RV64-ZCMP-NEXT: .cfi_restore gp
+; RV64-ZCMP-NEXT: ret
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_sw_clobber_s11:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra, s0-s11}, -112
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 112
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -104
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s11, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: #APP
+; RV64-ZCMP-SAVE-RESTORE-NEXT: nop
+; RV64-ZCMP-SAVE-RESTORE-NEXT: #NO_APP
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra, s0-s11}, 112
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV64-XQCCMP-LABEL: caller_sw_clobber_s11:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: addi gp, gp, 8
+; RV64-XQCCMP-NEXT: sd ra, -8(gp)
+; RV64-XQCCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-XQCCMP-NEXT: qc.cm.push {ra, s0-s11}, -112
+; RV64-XQCCMP-NEXT: .cfi_def_cfa_offset 112
+; RV64-XQCCMP-NEXT: .cfi_offset ra, -8
+; RV64-XQCCMP-NEXT: .cfi_offset s11, -104
+; RV64-XQCCMP-NEXT: negw a0, a0
+; RV64-XQCCMP-NEXT: call callee
+; RV64-XQCCMP-NEXT: addiw a0, a0, 1
+; RV64-XQCCMP-NEXT: #APP
+; RV64-XQCCMP-NEXT: nop
+; RV64-XQCCMP-NEXT: #NO_APP
+; RV64-XQCCMP-NEXT: qc.cm.pop {ra, s0-s11}, 112
+; RV64-XQCCMP-NEXT: ld ra, -8(gp)
+; RV64-XQCCMP-NEXT: addi gp, gp, -8
+; RV64-XQCCMP-NEXT: .cfi_restore gp
+; RV64-XQCCMP-NEXT: ret
+ %sub = sub nsw i32 0, %x
+ %call = tail call i32 @callee(i32 %sub)
+ %add = add nsw i32 %call, 1
+ call void asm sideeffect "nop", "~{x27}"()
+ ret i32 %add
+}
+
+;; Hardware Shadow Call Stack
+
+define i32 @caller_hw(i32 %x) "hw-shadow-stack" {
+; RV32-LABEL: caller_hw:
+; RV32: # %bb.0:
+; RV32-NEXT: sspush ra
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: .cfi_def_cfa_offset 16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -4
+; RV32-NEXT: neg a0, a0
+; RV32-NEXT: call callee
+; RV32-NEXT: addi a0, a0, 1
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: sspopchk ra
+; RV32-NEXT: ret
+;
+; RV32-SAVE-RESTORE-LABEL: caller_hw:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: sspush ra
+; RV32-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-SAVE-RESTORE-NEXT: call callee
+; RV32-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32-SAVE-RESTORE-NEXT: ret
+;
+; RV32-ZCMP-LABEL: caller_hw:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: sspush ra
+; RV32-ZCMP-NEXT: cm.push {ra}, -16
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-NEXT: neg a0, a0
+; RV32-ZCMP-NEXT: call callee
+; RV32-ZCMP-NEXT: addi a0, a0, 1
+; RV32-ZCMP-NEXT: cm.pop {ra}, 16
+; RV32-ZCMP-NEXT: sspopchk ra
+; RV32-ZCMP-NEXT: ret
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_hw:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sspush ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra}, -16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra}, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV32-XQCCMP-LABEL: caller_hw:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: sspush ra
+; RV32-XQCCMP-NEXT: qc.cm.push {ra}, -16
+; RV32-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-XQCCMP-NEXT: .cfi_offset ra, -4
+; RV32-XQCCMP-NEXT: neg a0, a0
+; RV32-XQCCMP-NEXT: call callee
+; RV32-XQCCMP-NEXT: addi a0, a0, 1
+; RV32-XQCCMP-NEXT: qc.cm.pop {ra}, 16
+; RV32-XQCCMP-NEXT: sspopchk ra
+; RV32-XQCCMP-NEXT: ret
+;
+; RV64-LABEL: caller_hw:
+; RV64: # %bb.0:
+; RV64-NEXT: sspush ra
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: .cfi_def_cfa_offset 16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -8
+; RV64-NEXT: negw a0, a0
+; RV64-NEXT: call callee
+; RV64-NEXT: addiw a0, a0, 1
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: sspopchk ra
+; RV64-NEXT: ret
+;
+; RV64-SAVE-RESTORE-LABEL: caller_hw:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: sspush ra
+; RV64-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-SAVE-RESTORE-NEXT: call callee
+; RV64-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64-SAVE-RESTORE-NEXT: ret
+;
+; RV64-ZCMP-LABEL: caller_hw:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: sspush ra
+; RV64-ZCMP-NEXT: cm.push {ra}, -16
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-NEXT: negw a0, a0
+; RV64-ZCMP-NEXT: call callee
+; RV64-ZCMP-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-NEXT: cm.pop {ra}, 16
+; RV64-ZCMP-NEXT: sspopchk ra
+; RV64-ZCMP-NEXT: ret
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_hw:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sspush ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra}, -16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra}, 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV64-XQCCMP-LABEL: caller_hw:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: sspush ra
+; RV64-XQCCMP-NEXT: qc.cm.push {ra}, -16
+; RV64-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-XQCCMP-NEXT: .cfi_offset ra, -8
+; RV64-XQCCMP-NEXT: negw a0, a0
+; RV64-XQCCMP-NEXT: call callee
+; RV64-XQCCMP-NEXT: addiw a0, a0, 1
+; RV64-XQCCMP-NEXT: qc.cm.pop {ra}, 16
+; RV64-XQCCMP-NEXT: sspopchk ra
+; RV64-XQCCMP-NEXT: ret
+ %sub = sub nsw i32 0, %x
+ %call = tail call i32 @callee(i32 %sub)
+ %add = add nsw i32 %call, 1
+ ret i32 %add
+}
+
+define i32 @caller_hw_tail(i32 %x) "hw-shadow-stack" {
+; RV32-LABEL: caller_hw_tail:
+; RV32: # %bb.0:
+; RV32-NEXT: neg a0, a0
+; RV32-NEXT: tail callee
+;
+; RV32-SAVE-RESTORE-LABEL: caller_hw_tail:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-SAVE-RESTORE-NEXT: tail callee
+;
+; RV32-ZCMP-LABEL: caller_hw_tail:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: neg a0, a0
+; RV32-ZCMP-NEXT: tail callee
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_hw_tail:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: tail callee
+;
+; RV32-XQCCMP-LABEL: caller_hw_tail:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: neg a0, a0
+; RV32-XQCCMP-NEXT: tail callee
+;
+; RV64-LABEL: caller_hw_tail:
+; RV64: # %bb.0:
+; RV64-NEXT: negw a0, a0
+; RV64-NEXT: tail callee
+;
+; RV64-SAVE-RESTORE-LABEL: caller_hw_tail:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-SAVE-RESTORE-NEXT: tail callee
+;
+; RV64-ZCMP-LABEL: caller_hw_tail:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: negw a0, a0
+; RV64-ZCMP-NEXT: tail callee
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_hw_tail:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: tail callee
+;
+; RV64-XQCCMP-LABEL: caller_hw_tail:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: negw a0, a0
+; RV64-XQCCMP-NEXT: tail callee
+ %sub = sub nsw i32 0, %x
+ %call = tail call i32 @callee(i32 %sub)
+ ret i32 %call
+}
+
+define i32 @caller_hw_fp(i32 %x) "hw-shadow-stack" "frame-pointer"="all" {
+; RV32-LABEL: caller_hw_fp:
+; RV32: # %bb.0:
+; RV32-NEXT: sspush ra
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: .cfi_def_cfa_offset 16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -4
+; RV32-NEXT: .cfi_offset s0, -8
+; RV32-NEXT: addi s0, sp, 16
+; RV32-NEXT: .cfi_def_cfa s0, 0
+; RV32-NEXT: neg a0, a0
+; RV32-NEXT: call callee
+; RV32-NEXT: addi a0, a0, 1
+; RV32-NEXT: .cfi_def_cfa sp, 16
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore s0
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: sspopchk ra
+; RV32-NEXT: ret
+;
+; RV32-SAVE-RESTORE-LABEL: caller_hw_fp:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: sspush ra
+; RV32-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset s0, -8
+; RV32-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV32-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-SAVE-RESTORE-NEXT: call callee
+; RV32-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV32-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV32-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32-SAVE-RESTORE-NEXT: ret
+;
+; RV32-ZCMP-LABEL: caller_hw_fp:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: sspush ra
+; RV32-ZCMP-NEXT: addi sp, sp, -16
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-ZCMP-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32-ZCMP-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-NEXT: .cfi_offset s0, -8
+; RV32-ZCMP-NEXT: addi s0, sp, 16
+; RV32-ZCMP-NEXT: .cfi_def_cfa s0, 0
+; RV32-ZCMP-NEXT: neg a0, a0
+; RV32-ZCMP-NEXT: call callee
+; RV32-ZCMP-NEXT: addi a0, a0, 1
+; RV32-ZCMP-NEXT: .cfi_def_cfa sp, 16
+; RV32-ZCMP-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-ZCMP-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-ZCMP-NEXT: .cfi_restore ra
+; RV32-ZCMP-NEXT: .cfi_restore s0
+; RV32-ZCMP-NEXT: addi sp, sp, 16
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 0
+; RV32-ZCMP-NEXT: sspopchk ra
+; RV32-ZCMP-NEXT: ret
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_hw_fp:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sspush ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s0, -8
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-ZCMP-SAVE-RESTORE-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV32-XQCCMP-LABEL: caller_hw_fp:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: sspush ra
+; RV32-XQCCMP-NEXT: qc.cm.pushfp {ra, s0}, -16
+; RV32-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-XQCCMP-NEXT: .cfi_offset ra, -4
+; RV32-XQCCMP-NEXT: .cfi_offset s0, -8
+; RV32-XQCCMP-NEXT: .cfi_def_cfa s0, 0
+; RV32-XQCCMP-NEXT: neg a0, a0
+; RV32-XQCCMP-NEXT: call callee
+; RV32-XQCCMP-NEXT: addi a0, a0, 1
+; RV32-XQCCMP-NEXT: .cfi_def_cfa sp, 16
+; RV32-XQCCMP-NEXT: qc.cm.pop {ra, s0}, 16
+; RV32-XQCCMP-NEXT: sspopchk ra
+; RV32-XQCCMP-NEXT: ret
+;
+; RV64-LABEL: caller_hw_fp:
+; RV64: # %bb.0:
+; RV64-NEXT: sspush ra
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: .cfi_def_cfa_offset 16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s0, 0(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -8
+; RV64-NEXT: .cfi_offset s0, -16
+; RV64-NEXT: addi s0, sp, 16
+; RV64-NEXT: .cfi_def_cfa s0, 0
+; RV64-NEXT: negw a0, a0
+; RV64-NEXT: call callee
+; RV64-NEXT: addiw a0, a0, 1
+; RV64-NEXT: .cfi_def_cfa sp, 16
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: .cfi_restore s0
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: sspopchk ra
+; RV64-NEXT: ret
+;
+; RV64-SAVE-RESTORE-LABEL: caller_hw_fp:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: sspush ra
+; RV64-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset s0, -16
+; RV64-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV64-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-SAVE-RESTORE-NEXT: call callee
+; RV64-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV64-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV64-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64-SAVE-RESTORE-NEXT: ret
+;
+; RV64-ZCMP-LABEL: caller_hw_fp:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: sspush ra
+; RV64-ZCMP-NEXT: addi sp, sp, -16
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-ZCMP-NEXT: sd s0, 0(sp) # 8-byte Folded Spill
+; RV64-ZCMP-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-NEXT: .cfi_offset s0, -16
+; RV64-ZCMP-NEXT: addi s0, sp, 16
+; RV64-ZCMP-NEXT: .cfi_def_cfa s0, 0
+; RV64-ZCMP-NEXT: negw a0, a0
+; RV64-ZCMP-NEXT: call callee
+; RV64-ZCMP-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-NEXT: .cfi_def_cfa sp, 16
+; RV64-ZCMP-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-ZCMP-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
+; RV64-ZCMP-NEXT: .cfi_restore ra
+; RV64-ZCMP-NEXT: .cfi_restore s0
+; RV64-ZCMP-NEXT: addi sp, sp, 16
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 0
+; RV64-ZCMP-NEXT: sspopchk ra
+; RV64-ZCMP-NEXT: ret
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_hw_fp:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sspush ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s0, -16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV64-XQCCMP-LABEL: caller_hw_fp:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: sspush ra
+; RV64-XQCCMP-NEXT: qc.cm.pushfp {ra, s0}, -16
+; RV64-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-XQCCMP-NEXT: .cfi_offset ra, -8
+; RV64-XQCCMP-NEXT: .cfi_offset s0, -16
+; RV64-XQCCMP-NEXT: .cfi_def_cfa s0, 0
+; RV64-XQCCMP-NEXT: negw a0, a0
+; RV64-XQCCMP-NEXT: call callee
+; RV64-XQCCMP-NEXT: addiw a0, a0, 1
+; RV64-XQCCMP-NEXT: .cfi_def_cfa sp, 16
+; RV64-XQCCMP-NEXT: qc.cm.pop {ra, s0}, 16
+; RV64-XQCCMP-NEXT: sspopchk ra
+; RV64-XQCCMP-NEXT: ret
+ %sub = sub nsw i32 0, %x
+ %call = tail call i32 @callee(i32 %sub)
+ %add = add nsw i32 %call, 1
+ ret i32 %add
+}
+
+
+define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
+; RV32-LABEL: caller_hw_cond:
+; RV32: # %bb.0:
+; RV32-NEXT: beqz a0, .LBB8_2
+; RV32-NEXT: # %bb.1: # %if.end
+; RV32-NEXT: sspush ra
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: .cfi_def_cfa_offset 16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -4
+; RV32-NEXT: neg a0, a0
+; RV32-NEXT: call callee
+; RV32-NEXT: addi a0, a0, 1
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: sspopchk ra
+; RV32-NEXT: ret
+; RV32-NEXT: .LBB8_2: # %return
+; RV32-NEXT: li a0, 1
+; RV32-NEXT: ret
+;
+; RV32-SAVE-RESTORE-LABEL: caller_hw_cond:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: beqz a0, .LBB8_2
+; RV32-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV32-SAVE-RESTORE-NEXT: sspush ra
+; RV32-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-SAVE-RESTORE-NEXT: call callee
+; RV32-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32-SAVE-RESTORE-NEXT: ret
+; RV32-SAVE-RESTORE-NEXT: .LBB8_2: # %return
+; RV32-SAVE-RESTORE-NEXT: li a0, 1
+; RV32-SAVE-RESTORE-NEXT: ret
+;
+; RV32-ZCMP-LABEL: caller_hw_cond:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: beqz a0, .LBB8_2
+; RV32-ZCMP-NEXT: # %bb.1: # %if.end
+; RV32-ZCMP-NEXT: sspush ra
+; RV32-ZCMP-NEXT: cm.push {ra}, -16
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-NEXT: neg a0, a0
+; RV32-ZCMP-NEXT: call callee
+; RV32-ZCMP-NEXT: addi a0, a0, 1
+; RV32-ZCMP-NEXT: cm.pop {ra}, 16
+; RV32-ZCMP-NEXT: sspopchk ra
+; RV32-ZCMP-NEXT: ret
+; RV32-ZCMP-NEXT: .LBB8_2: # %return
+; RV32-ZCMP-NEXT: li a0, 1
+; RV32-ZCMP-NEXT: ret
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_hw_cond:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: beqz a0, .LBB8_2
+; RV32-ZCMP-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sspush ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra}, -16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra}, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .LBB8_2: # %return
+; RV32-ZCMP-SAVE-RESTORE-NEXT: li a0, 1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV32-XQCCMP-LABEL: caller_hw_cond:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: beqz a0, .LBB8_2
+; RV32-XQCCMP-NEXT: # %bb.1: # %if.end
+; RV32-XQCCMP-NEXT: sspush ra
+; RV32-XQCCMP-NEXT: qc.cm.push {ra}, -16
+; RV32-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-XQCCMP-NEXT: .cfi_offset ra, -4
+; RV32-XQCCMP-NEXT: neg a0, a0
+; RV32-XQCCMP-NEXT: call callee
+; RV32-XQCCMP-NEXT: addi a0, a0, 1
+; RV32-XQCCMP-NEXT: qc.cm.pop {ra}, 16
+; RV32-XQCCMP-NEXT: sspopchk ra
+; RV32-XQCCMP-NEXT: ret
+; RV32-XQCCMP-NEXT: .LBB8_2: # %return
+; RV32-XQCCMP-NEXT: li a0, 1
+; RV32-XQCCMP-NEXT: ret
+;
+; RV64-LABEL: caller_hw_cond:
+; RV64: # %bb.0:
+; RV64-NEXT: sext.w a1, a0
+; RV64-NEXT: beqz a1, .LBB8_2
+; RV64-NEXT: # %bb.1: # %if.end
+; RV64-NEXT: sspush ra
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: .cfi_def_cfa_offset 16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -8
+; RV64-NEXT: negw a0, a0
+; RV64-NEXT: call callee
+; RV64-NEXT: addiw a0, a0, 1
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: sspopchk ra
+; RV64-NEXT: ret
+; RV64-NEXT: .LBB8_2: # %return
+; RV64-NEXT: li a0, 1
+; RV64-NEXT: ret
+;
+; RV64-SAVE-RESTORE-LABEL: caller_hw_cond:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: sext.w a1, a0
+; RV64-SAVE-RESTORE-NEXT: beqz a1, .LBB8_2
+; RV64-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV64-SAVE-RESTORE-NEXT: sspush ra
+; RV64-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-SAVE-RESTORE-NEXT: call callee
+; RV64-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64-SAVE-RESTORE-NEXT: ret
+; RV64-SAVE-RESTORE-NEXT: .LBB8_2: # %return
+; RV64-SAVE-RESTORE-NEXT: li a0, 1
+; RV64-SAVE-RESTORE-NEXT: ret
+;
+; RV64-ZCMP-LABEL: caller_hw_cond:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: sext.w a1, a0
+; RV64-ZCMP-NEXT: beqz a1, .LBB8_2
+; RV64-ZCMP-NEXT: # %bb.1: # %if.end
+; RV64-ZCMP-NEXT: sspush ra
+; RV64-ZCMP-NEXT: cm.push {ra}, -16
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-NEXT: negw a0, a0
+; RV64-ZCMP-NEXT: call callee
+; RV64-ZCMP-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-NEXT: cm.pop {ra}, 16
+; RV64-ZCMP-NEXT: sspopchk ra
+; RV64-ZCMP-NEXT: ret
+; RV64-ZCMP-NEXT: .LBB8_2: # %return
+; RV64-ZCMP-NEXT: li a0, 1
+; RV64-ZCMP-NEXT: ret
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_hw_cond:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sext.w a1, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: beqz a1, .LBB8_2
+; RV64-ZCMP-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sspush ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra}, -16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra}, 16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .LBB8_2: # %return
+; RV64-ZCMP-SAVE-RESTORE-NEXT: li a0, 1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV64-XQCCMP-LABEL: caller_hw_cond:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: sext.w a1, a0
+; RV64-XQCCMP-NEXT: beqz a1, .LBB8_2
+; RV64-XQCCMP-NEXT: # %bb.1: # %if.end
+; RV64-XQCCMP-NEXT: sspush ra
+; RV64-XQCCMP-NEXT: qc.cm.push {ra}, -16
+; RV64-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV64-XQCCMP-NEXT: .cfi_offset ra, -8
+; RV64-XQCCMP-NEXT: negw a0, a0
+; RV64-XQCCMP-NEXT: call callee
+; RV64-XQCCMP-NEXT: addiw a0, a0, 1
+; RV64-XQCCMP-NEXT: qc.cm.pop {ra}, 16
+; RV64-XQCCMP-NEXT: sspopchk ra
+; RV64-XQCCMP-NEXT: ret
+; RV64-XQCCMP-NEXT: .LBB8_2: # %return
+; RV64-XQCCMP-NEXT: li a0, 1
+; RV64-XQCCMP-NEXT: ret
+ %cmp = icmp eq i32 %x, 0
+ br i1 %cmp, label %return, label %if.end
+
+if.end:
+ %sub = sub nsw i32 0, %x
+ %call = tail call i32 @callee(i32 %sub)
+ %add = add nsw i32 %call, 1
+ ret i32 %add
+
+return:
+ ret i32 1
+}
+
+define i32 @caller_hw_clobber_s11(i32 %x) "hw-shadow-stack" {
+; RV32-LABEL: caller_hw_clobber_s11:
+; RV32: # %bb.0:
+; RV32-NEXT: sspush ra
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: .cfi_def_cfa_offset 16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s11, 8(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -4
+; RV32-NEXT: .cfi_offset s11, -8
+; RV32-NEXT: neg a0, a0
+; RV32-NEXT: call callee
+; RV32-NEXT: addi a0, a0, 1
+; RV32-NEXT: #APP
+; RV32-NEXT: nop
+; RV32-NEXT: #NO_APP
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s11, 8(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore s11
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: sspopchk ra
+; RV32-NEXT: ret
+;
+; RV32-SAVE-RESTORE-LABEL: caller_hw_clobber_s11:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: sspush ra
+; RV32-SAVE-RESTORE-NEXT: call t0, __riscv_save_12
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 64
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset s11, -52
+; RV32-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-SAVE-RESTORE-NEXT: call callee
+; RV32-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-SAVE-RESTORE-NEXT: #APP
+; RV32-SAVE-RESTORE-NEXT: nop
+; RV32-SAVE-RESTORE-NEXT: #NO_APP
+; RV32-SAVE-RESTORE-NEXT: lw ra, 60(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: lw s11, 12(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore s11
+; RV32-SAVE-RESTORE-NEXT: addi sp, sp, 64
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32-SAVE-RESTORE-NEXT: ret
+;
+; RV32-ZCMP-LABEL: caller_hw_clobber_s11:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: sspush ra
+; RV32-ZCMP-NEXT: cm.push {ra, s0-s11}, -64
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 64
+; RV32-ZCMP-NEXT: .cfi_offset ra, -52
+; RV32-ZCMP-NEXT: .cfi_offset s11, -4
+; RV32-ZCMP-NEXT: neg a0, a0
+; RV32-ZCMP-NEXT: call callee
+; RV32-ZCMP-NEXT: addi a0, a0, 1
+; RV32-ZCMP-NEXT: #APP
+; RV32-ZCMP-NEXT: nop
+; RV32-ZCMP-NEXT: #NO_APP
+; RV32-ZCMP-NEXT: cm.pop {ra, s0-s11}, 64
+; RV32-ZCMP-NEXT: sspopchk ra
+; RV32-ZCMP-NEXT: ret
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_hw_clobber_s11:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sspush ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra, s0-s11}, -64
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 64
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -52
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s11, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: #APP
+; RV32-ZCMP-SAVE-RESTORE-NEXT: nop
+; RV32-ZCMP-SAVE-RESTORE-NEXT: #NO_APP
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra, s0-s11}, 64
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV32-XQCCMP-LABEL: caller_hw_clobber_s11:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: sspush ra
+; RV32-XQCCMP-NEXT: qc.cm.push {ra, s0-s11}, -64
+; RV32-XQCCMP-NEXT: .cfi_def_cfa_offset 64
+; RV32-XQCCMP-NEXT: .cfi_offset ra, -4
+; RV32-XQCCMP-NEXT: .cfi_offset s11, -52
+; RV32-XQCCMP-NEXT: neg a0, a0
+; RV32-XQCCMP-NEXT: call callee
+; RV32-XQCCMP-NEXT: addi a0, a0, 1
+; RV32-XQCCMP-NEXT: #APP
+; RV32-XQCCMP-NEXT: nop
+; RV32-XQCCMP-NEXT: #NO_APP
+; RV32-XQCCMP-NEXT: qc.cm.pop {ra, s0-s11}, 64
+; RV32-XQCCMP-NEXT: sspopchk ra
+; RV32-XQCCMP-NEXT: ret
+;
+; RV64-LABEL: caller_hw_clobber_s11:
+; RV64: # %bb.0:
+; RV64-NEXT: sspush ra
+; RV64-NEXT: addi sp, sp, -16
+; RV64-NEXT: .cfi_def_cfa_offset 16
+; RV64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT: sd s11, 0(sp) # 8-byte Folded Spill
+; RV64-NEXT: .cfi_offset ra, -8
+; RV64-NEXT: .cfi_offset s11, -16
+; RV64-NEXT: negw a0, a0
+; RV64-NEXT: call callee
+; RV64-NEXT: addiw a0, a0, 1
+; RV64-NEXT: #APP
+; RV64-NEXT: nop
+; RV64-NEXT: #NO_APP
+; RV64-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT: ld s11, 0(sp) # 8-byte Folded Reload
+; RV64-NEXT: .cfi_restore ra
+; RV64-NEXT: .cfi_restore s11
+; RV64-NEXT: addi sp, sp, 16
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: sspopchk ra
+; RV64-NEXT: ret
+;
+; RV64-SAVE-RESTORE-LABEL: caller_hw_clobber_s11:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: sspush ra
+; RV64-SAVE-RESTORE-NEXT: call t0, __riscv_save_12
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 112
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset s11, -104
+; RV64-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-SAVE-RESTORE-NEXT: call callee
+; RV64-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-SAVE-RESTORE-NEXT: #APP
+; RV64-SAVE-RESTORE-NEXT: nop
+; RV64-SAVE-RESTORE-NEXT: #NO_APP
+; RV64-SAVE-RESTORE-NEXT: ld ra, 104(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: ld s11, 8(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore s11
+; RV64-SAVE-RESTORE-NEXT: addi sp, sp, 112
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64-SAVE-RESTORE-NEXT: ret
+;
+; RV64-ZCMP-LABEL: caller_hw_clobber_s11:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: sspush ra
+; RV64-ZCMP-NEXT: cm.push {ra, s0-s11}, -112
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 112
+; RV64-ZCMP-NEXT: .cfi_offset ra, -104
+; RV64-ZCMP-NEXT: .cfi_offset s11, -8
+; RV64-ZCMP-NEXT: negw a0, a0
+; RV64-ZCMP-NEXT: call callee
+; RV64-ZCMP-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-NEXT: #APP
+; RV64-ZCMP-NEXT: nop
+; RV64-ZCMP-NEXT: #NO_APP
+; RV64-ZCMP-NEXT: cm.pop {ra, s0-s11}, 112
+; RV64-ZCMP-NEXT: sspopchk ra
+; RV64-ZCMP-NEXT: ret
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_hw_clobber_s11:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sspush ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra, s0-s11}, -112
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 112
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -104
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s11, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call callee
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: #APP
+; RV64-ZCMP-SAVE-RESTORE-NEXT: nop
+; RV64-ZCMP-SAVE-RESTORE-NEXT: #NO_APP
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra, s0-s11}, 112
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV64-XQCCMP-LABEL: caller_hw_clobber_s11:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: sspush ra
+; RV64-XQCCMP-NEXT: qc.cm.push {ra, s0-s11}, -112
+; RV64-XQCCMP-NEXT: .cfi_def_cfa_offset 112
+; RV64-XQCCMP-NEXT: .cfi_offset ra, -8
+; RV64-XQCCMP-NEXT: .cfi_offset s11, -104
+; RV64-XQCCMP-NEXT: negw a0, a0
+; RV64-XQCCMP-NEXT: call callee
+; RV64-XQCCMP-NEXT: addiw a0, a0, 1
+; RV64-XQCCMP-NEXT: #APP
+; RV64-XQCCMP-NEXT: nop
+; RV64-XQCCMP-NEXT: #NO_APP
+; RV64-XQCCMP-NEXT: qc.cm.pop {ra, s0-s11}, 112
+; RV64-XQCCMP-NEXT: sspopchk ra
+; RV64-XQCCMP-NEXT: ret
+ %sub = sub nsw i32 0, %x
+ %call = tail call i32 @callee(i32 %sub)
+ %add = add nsw i32 %call, 1
+ call void asm sideeffect "nop", "~{x27}"()
+ ret i32 %add
+}
>From 7f34271a6b8983b5276efba151daf146aae62417 Mon Sep 17 00:00:00 2001
From: Sam Elliott <aelliott at qti.qualcomm.com>
Date: Tue, 20 Oct 2026 14:56:19 -0700
Subject: [PATCH 2/2] [RISCV] Correctly restore libcall CSRs with SCS
Fixes #233318
Before this change, we were restoring some callee-saved registers twice
when using save/restore libcalls with shadow call stack (SCS), and the
second restore was happening after the stack was deallocated using the
wrong register and offset calculation, which was causing lots of access
problems.
The problems were:
- We were using the entire list of Callee Saves rather than just the
subset that would have been restored by the libcall. This caused
duplicate restores because of how the CSI subsetting works.
- We were not using the correct offset calculation in
eliminateFrameIndex, which was causing us to calculate the wrong
address for the saves/restores.
Assisted-by: AI
Co-authored-by: Mitch Briles <mitchbriles at gmail.com>
---
llvm/lib/Target/RISCV/RISCVFrameLowering.cpp | 17 +-
.../RISCV/shadow-stack-frame-opts-v.ll | 136 +++
.../CodeGen/RISCV/shadow-stack-frame-opts.ll | 1006 ++++++++++++++++-
3 files changed, 1136 insertions(+), 23 deletions(-)
create mode 100644 llvm/test/CodeGen/RISCV/shadow-stack-frame-opts-v.ll
diff --git a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
index 0cd2394229ff8..2ccbceeda5907 100644
--- a/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVFrameLowering.cpp
@@ -580,7 +580,10 @@ getUnmanagedCSI(const MachineFunction &MF,
for (auto &CS : CSI) {
int FI = CS.getFrameIdx();
- if (FI >= 0 && MFI.getStackID(FI) == TargetStackID::Default)
+ // Callee saves with negative frame indices have fixed positions on the
+ // stack, usually relating to libcalls or push/pop.
+ bool IsManagedFI = (FI < 0);
+ if (!IsManagedFI && MFI.getStackID(FI) == TargetStackID::Default)
NonLibcallCSI.push_back(CS);
}
@@ -1576,7 +1579,12 @@ RISCVFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,
MaxCSFI = std::max(CSI.front().getFrameIdx(), CSI.back().getFrameIdx());
}
- if (FI >= MinCSFI && FI <= MaxCSFI) {
+ auto FIIsCalleeSave = [&](const CalleeSavedInfo &CS) -> bool {
+ return FI == CS.getFrameIdx();
+ };
+ bool IsInlineRestoredLibcallCSR = llvm::any_of(
+ getPushOrLibCallsSavedInfo(MF, MFI.getCalleeSavedInfo()), FIIsCalleeSave);
+ if ((FI >= MinCSFI && FI <= MaxCSFI) || IsInlineRestoredLibcallCSR) {
FrameReg = SPReg;
if (FirstSPAdjustAmount)
@@ -2552,10 +2560,13 @@ bool RISCVFrameLowering::restoreCalleeSavedRegisters(
PopBuilder.addDef(FixedCSRFIMap[i], RegState::ImplicitDefine);
}
} else if (const char *RestoreLibCall = getRestoreLibCallName(*MF, CSI)) {
+ assert(RVFI->useSaveRestoreLibCalls(*MF) &&
+ "Expected restore with libcall to use save restore libcalls");
+
// Restore is not compatible with shadow stacks, so do the restore manually.
// This ensures we still get the code size saving of `__riscv_save_<N>`.
if (RVFI->hasShadowStack(*MF)) {
- loadRegFromStackSlot(CSI);
+ loadRegFromStackSlot(getPushOrLibCallsSavedInfo(*MF, CSI));
return true;
}
diff --git a/llvm/test/CodeGen/RISCV/shadow-stack-frame-opts-v.ll b/llvm/test/CodeGen/RISCV/shadow-stack-frame-opts-v.ll
new file mode 100644
index 0000000000000..ab43a6b7007bd
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/shadow-stack-frame-opts-v.ll
@@ -0,0 +1,136 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+
+; RUN: llc -mtriple=riscv32 -mattr=+v,+zimop,+save-restore %s -o - | FileCheck %s --check-prefixes=RV32V
+; RUN: llc -mtriple=riscv64 -mattr=+v,+zimop,+save-restore %s -o - | FileCheck %s --check-prefixes=RV64V
+
+
+declare void @g()
+
+define <vscale x 4 x i32> @w(<vscale x 4 x i32> %a) shadowcallstack {
+; RV32V-LABEL: w:
+; RV32V: # %bb.0:
+; RV32V-NEXT: addi gp, gp, 4
+; RV32V-NEXT: sw ra, -4(gp)
+; RV32V-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32V-NEXT: call t0, __riscv_save_0
+; RV32V-NEXT: .cfi_def_cfa_offset 16
+; RV32V-NEXT: .cfi_offset ra, -4
+; RV32V-NEXT: addi sp, sp, -16
+; RV32V-NEXT: .cfi_def_cfa_offset 32
+; RV32V-NEXT: csrr a0, vlenb
+; RV32V-NEXT: slli a0, a0, 1
+; RV32V-NEXT: sub sp, sp, a0
+; RV32V-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x20, 0x22, 0x11, 0x02, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 32 + 2 * vlenb
+; RV32V-NEXT: addi a0, sp, 32
+; RV32V-NEXT: vs2r.v v8, (a0) # vscale x 16-byte Folded Spill
+; RV32V-NEXT: call g
+; RV32V-NEXT: addi a0, sp, 32
+; RV32V-NEXT: vl2r.v v8, (a0) # vscale x 16-byte Folded Reload
+; RV32V-NEXT: csrr a0, vlenb
+; RV32V-NEXT: slli a0, a0, 1
+; RV32V-NEXT: add sp, sp, a0
+; RV32V-NEXT: .cfi_def_cfa sp, 32
+; RV32V-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
+; RV32V-NEXT: .cfi_restore ra
+; RV32V-NEXT: addi sp, sp, 32
+; RV32V-NEXT: .cfi_def_cfa_offset 0
+; RV32V-NEXT: lw ra, -4(gp)
+; RV32V-NEXT: addi gp, gp, -4
+; RV32V-NEXT: .cfi_restore gp
+; RV32V-NEXT: ret
+;
+; RV64V-LABEL: w:
+; RV64V: # %bb.0:
+; RV64V-NEXT: addi gp, gp, 8
+; RV64V-NEXT: sd ra, -8(gp)
+; RV64V-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64V-NEXT: call t0, __riscv_save_0
+; RV64V-NEXT: .cfi_def_cfa_offset 16
+; RV64V-NEXT: .cfi_offset ra, -8
+; RV64V-NEXT: addi sp, sp, -16
+; RV64V-NEXT: .cfi_def_cfa_offset 32
+; RV64V-NEXT: csrr a0, vlenb
+; RV64V-NEXT: slli a0, a0, 1
+; RV64V-NEXT: sub sp, sp, a0
+; RV64V-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x20, 0x22, 0x11, 0x02, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 32 + 2 * vlenb
+; RV64V-NEXT: addi a0, sp, 32
+; RV64V-NEXT: vs2r.v v8, (a0) # vscale x 16-byte Folded Spill
+; RV64V-NEXT: call g
+; RV64V-NEXT: addi a0, sp, 32
+; RV64V-NEXT: vl2r.v v8, (a0) # vscale x 16-byte Folded Reload
+; RV64V-NEXT: csrr a0, vlenb
+; RV64V-NEXT: slli a0, a0, 1
+; RV64V-NEXT: add sp, sp, a0
+; RV64V-NEXT: .cfi_def_cfa sp, 32
+; RV64V-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64V-NEXT: .cfi_restore ra
+; RV64V-NEXT: addi sp, sp, 32
+; RV64V-NEXT: .cfi_def_cfa_offset 0
+; RV64V-NEXT: ld ra, -8(gp)
+; RV64V-NEXT: addi gp, gp, -8
+; RV64V-NEXT: .cfi_restore gp
+; RV64V-NEXT: ret
+ call void @g()
+ ret <vscale x 4 x i32> %a
+}
+
+define <vscale x 4 x i32> @z(<vscale x 4 x i32> %a) "hw-shadow-stack" {
+; RV32V-LABEL: z:
+; RV32V: # %bb.0:
+; RV32V-NEXT: sspush ra
+; RV32V-NEXT: call t0, __riscv_save_0
+; RV32V-NEXT: .cfi_def_cfa_offset 16
+; RV32V-NEXT: .cfi_offset ra, -4
+; RV32V-NEXT: addi sp, sp, -16
+; RV32V-NEXT: .cfi_def_cfa_offset 32
+; RV32V-NEXT: csrr a0, vlenb
+; RV32V-NEXT: slli a0, a0, 1
+; RV32V-NEXT: sub sp, sp, a0
+; RV32V-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x20, 0x22, 0x11, 0x02, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 32 + 2 * vlenb
+; RV32V-NEXT: addi a0, sp, 32
+; RV32V-NEXT: vs2r.v v8, (a0) # vscale x 16-byte Folded Spill
+; RV32V-NEXT: call g
+; RV32V-NEXT: addi a0, sp, 32
+; RV32V-NEXT: vl2r.v v8, (a0) # vscale x 16-byte Folded Reload
+; RV32V-NEXT: csrr a0, vlenb
+; RV32V-NEXT: slli a0, a0, 1
+; RV32V-NEXT: add sp, sp, a0
+; RV32V-NEXT: .cfi_def_cfa sp, 32
+; RV32V-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
+; RV32V-NEXT: .cfi_restore ra
+; RV32V-NEXT: addi sp, sp, 32
+; RV32V-NEXT: .cfi_def_cfa_offset 0
+; RV32V-NEXT: sspopchk ra
+; RV32V-NEXT: ret
+;
+; RV64V-LABEL: z:
+; RV64V: # %bb.0:
+; RV64V-NEXT: sspush ra
+; RV64V-NEXT: call t0, __riscv_save_0
+; RV64V-NEXT: .cfi_def_cfa_offset 16
+; RV64V-NEXT: .cfi_offset ra, -8
+; RV64V-NEXT: addi sp, sp, -16
+; RV64V-NEXT: .cfi_def_cfa_offset 32
+; RV64V-NEXT: csrr a0, vlenb
+; RV64V-NEXT: slli a0, a0, 1
+; RV64V-NEXT: sub sp, sp, a0
+; RV64V-NEXT: .cfi_escape 0x0f, 0x0d, 0x72, 0x00, 0x11, 0x20, 0x22, 0x11, 0x02, 0x92, 0xa2, 0x38, 0x00, 0x1e, 0x22 # sp + 32 + 2 * vlenb
+; RV64V-NEXT: addi a0, sp, 32
+; RV64V-NEXT: vs2r.v v8, (a0) # vscale x 16-byte Folded Spill
+; RV64V-NEXT: call g
+; RV64V-NEXT: addi a0, sp, 32
+; RV64V-NEXT: vl2r.v v8, (a0) # vscale x 16-byte Folded Reload
+; RV64V-NEXT: csrr a0, vlenb
+; RV64V-NEXT: slli a0, a0, 1
+; RV64V-NEXT: add sp, sp, a0
+; RV64V-NEXT: .cfi_def_cfa sp, 32
+; RV64V-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64V-NEXT: .cfi_restore ra
+; RV64V-NEXT: addi sp, sp, 32
+; RV64V-NEXT: .cfi_def_cfa_offset 0
+; RV64V-NEXT: sspopchk ra
+; RV64V-NEXT: ret
+ call void @g()
+ ret <vscale x 4 x i32> %a
+}
+
diff --git a/llvm/test/CodeGen/RISCV/shadow-stack-frame-opts.ll b/llvm/test/CodeGen/RISCV/shadow-stack-frame-opts.ll
index e73c461eaa81f..8c872fdc6d5c2 100644
--- a/llvm/test/CodeGen/RISCV/shadow-stack-frame-opts.ll
+++ b/llvm/test/CodeGen/RISCV/shadow-stack-frame-opts.ll
@@ -5,6 +5,8 @@
; RUN: | FileCheck %s --check-prefix=RV32
; RUN: llc -mtriple=riscv32 -mattr=+zimop,+save-restore < %s \
; RUN: | FileCheck %s --check-prefix=RV32-SAVE-RESTORE
+; RUN: llc -mtriple=riscv32 -mattr=+d,+zimop,+save-restore -target-abi=ilp32d < %s \
+; RUN: | FileCheck %s --check-prefix=RV32D-SAVE-RESTORE
; RUN: llc -mtriple=riscv32 -mattr=+zimop,+zcmp < %s \
; RUN: | FileCheck %s --check-prefix=RV32-ZCMP
; RUN: llc -mtriple=riscv32 -mattr=+zimop,+zcmp,+save-restore < %s \
@@ -16,6 +18,8 @@
; RUN: | FileCheck %s --check-prefix=RV64
; RUN: llc -mtriple=riscv64 -mattr=+zimop,+save-restore < %s \
; RUN: | FileCheck %s --check-prefix=RV64-SAVE-RESTORE
+; RUN: llc -mtriple=riscv64 -mattr=+d,+zimop,+save-restore -target-abi=lp64d < %s \
+; RUN: | FileCheck %s --check-prefix=RV64D-SAVE-RESTORE
; RUN: llc -mtriple=riscv64 -mattr=+zimop,+zcmp < %s \
; RUN: | FileCheck %s --check-prefix=RV64-ZCMP
; RUN: llc -mtriple=riscv64 -mattr=+zimop,+zcmp,+save-restore < %s \
@@ -24,6 +28,7 @@
; RUN: | FileCheck %s --check-prefix=RV64-XQCCMP
declare i32 @callee(i32 %x)
+declare float @callee_float(float %x)
;; Software Shadow Call Stack
@@ -69,6 +74,26 @@ define i32 @caller_sw(i32 %x) shadowcallstack {
; RV32-SAVE-RESTORE-NEXT: .cfi_restore gp
; RV32-SAVE-RESTORE-NEXT: ret
;
+; RV32D-SAVE-RESTORE-LABEL: caller_sw:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32D-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32D-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32D-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32D-SAVE-RESTORE-NEXT: call callee
+; RV32D-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32D-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32D-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32D-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32D-SAVE-RESTORE-NEXT: ret
+;
; RV32-ZCMP-LABEL: caller_sw:
; RV32-ZCMP: # %bb.0:
; RV32-ZCMP-NEXT: addi gp, gp, 4
@@ -161,6 +186,26 @@ define i32 @caller_sw(i32 %x) shadowcallstack {
; RV64-SAVE-RESTORE-NEXT: .cfi_restore gp
; RV64-SAVE-RESTORE-NEXT: ret
;
+; RV64D-SAVE-RESTORE-LABEL: caller_sw:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64D-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64D-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64D-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64D-SAVE-RESTORE-NEXT: call callee
+; RV64D-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64D-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64D-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64D-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64D-SAVE-RESTORE-NEXT: ret
+;
; RV64-ZCMP-LABEL: caller_sw:
; RV64-ZCMP: # %bb.0:
; RV64-ZCMP-NEXT: addi gp, gp, 8
@@ -228,6 +273,11 @@ define i32 @caller_sw_tail(i32 %x) shadowcallstack {
; RV32-SAVE-RESTORE-NEXT: neg a0, a0
; RV32-SAVE-RESTORE-NEXT: tail callee
;
+; RV32D-SAVE-RESTORE-LABEL: caller_sw_tail:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32D-SAVE-RESTORE-NEXT: tail callee
+;
; RV32-ZCMP-LABEL: caller_sw_tail:
; RV32-ZCMP: # %bb.0:
; RV32-ZCMP-NEXT: neg a0, a0
@@ -253,6 +303,11 @@ define i32 @caller_sw_tail(i32 %x) shadowcallstack {
; RV64-SAVE-RESTORE-NEXT: negw a0, a0
; RV64-SAVE-RESTORE-NEXT: tail callee
;
+; RV64D-SAVE-RESTORE-LABEL: caller_sw_tail:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64D-SAVE-RESTORE-NEXT: tail callee
+;
; RV64-ZCMP-LABEL: caller_sw_tail:
; RV64-ZCMP: # %bb.0:
; RV64-ZCMP-NEXT: negw a0, a0
@@ -327,6 +382,32 @@ define i32 @caller_sw_fp(i32 %x) shadowcallstack "frame-pointer"="all" {
; RV32-SAVE-RESTORE-NEXT: .cfi_restore gp
; RV32-SAVE-RESTORE-NEXT: ret
;
+; RV32D-SAVE-RESTORE-LABEL: caller_sw_fp:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32D-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32D-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32D-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset s0, -8
+; RV32D-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV32D-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32D-SAVE-RESTORE-NEXT: call callee
+; RV32D-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV32D-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32D-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32D-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32D-SAVE-RESTORE-NEXT: ret
+;
; RV32-ZCMP-LABEL: caller_sw_fp:
; RV32-ZCMP: # %bb.0:
; RV32-ZCMP-NEXT: addi gp, gp, 4
@@ -455,6 +536,32 @@ define i32 @caller_sw_fp(i32 %x) shadowcallstack "frame-pointer"="all" {
; RV64-SAVE-RESTORE-NEXT: .cfi_restore gp
; RV64-SAVE-RESTORE-NEXT: ret
;
+; RV64D-SAVE-RESTORE-LABEL: caller_sw_fp:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64D-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64D-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64D-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset s0, -16
+; RV64D-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV64D-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64D-SAVE-RESTORE-NEXT: call callee
+; RV64D-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV64D-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64D-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64D-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64D-SAVE-RESTORE-NEXT: ret
+;
; RV64-ZCMP-LABEL: caller_sw_fp:
; RV64-ZCMP: # %bb.0:
; RV64-ZCMP-NEXT: addi gp, gp, 8
@@ -586,6 +693,31 @@ define i32 @caller_sw_cond(i32 %x) shadowcallstack {
; RV32-SAVE-RESTORE-NEXT: li a0, 1
; RV32-SAVE-RESTORE-NEXT: ret
;
+; RV32D-SAVE-RESTORE-LABEL: caller_sw_cond:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: beqz a0, .LBB3_2
+; RV32D-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV32D-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32D-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32D-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32D-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32D-SAVE-RESTORE-NEXT: call callee
+; RV32D-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32D-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32D-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32D-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32D-SAVE-RESTORE-NEXT: ret
+; RV32D-SAVE-RESTORE-NEXT: .LBB3_2: # %return
+; RV32D-SAVE-RESTORE-NEXT: li a0, 1
+; RV32D-SAVE-RESTORE-NEXT: ret
+;
; RV32-ZCMP-LABEL: caller_sw_cond:
; RV32-ZCMP: # %bb.0:
; RV32-ZCMP-NEXT: beqz a0, .LBB3_2
@@ -705,6 +837,32 @@ define i32 @caller_sw_cond(i32 %x) shadowcallstack {
; RV64-SAVE-RESTORE-NEXT: li a0, 1
; RV64-SAVE-RESTORE-NEXT: ret
;
+; RV64D-SAVE-RESTORE-LABEL: caller_sw_cond:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: sext.w a1, a0
+; RV64D-SAVE-RESTORE-NEXT: beqz a1, .LBB3_2
+; RV64D-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV64D-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64D-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64D-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64D-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64D-SAVE-RESTORE-NEXT: call callee
+; RV64D-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64D-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64D-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64D-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64D-SAVE-RESTORE-NEXT: ret
+; RV64D-SAVE-RESTORE-NEXT: .LBB3_2: # %return
+; RV64D-SAVE-RESTORE-NEXT: li a0, 1
+; RV64D-SAVE-RESTORE-NEXT: ret
+;
; RV64-ZCMP-LABEL: caller_sw_cond:
; RV64-ZCMP: # %bb.0:
; RV64-ZCMP-NEXT: sext.w a1, a0
@@ -841,6 +999,32 @@ define i32 @caller_sw_clobber_s11(i32 %x) shadowcallstack {
; RV32-SAVE-RESTORE-NEXT: .cfi_restore gp
; RV32-SAVE-RESTORE-NEXT: ret
;
+; RV32D-SAVE-RESTORE-LABEL: caller_sw_clobber_s11:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32D-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32D-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32D-SAVE-RESTORE-NEXT: call t0, __riscv_save_12
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 64
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset s11, -52
+; RV32D-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32D-SAVE-RESTORE-NEXT: call callee
+; RV32D-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32D-SAVE-RESTORE-NEXT: #APP
+; RV32D-SAVE-RESTORE-NEXT: nop
+; RV32D-SAVE-RESTORE-NEXT: #NO_APP
+; RV32D-SAVE-RESTORE-NEXT: lw ra, 60(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: lw s11, 12(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore s11
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, 64
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32D-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32D-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32D-SAVE-RESTORE-NEXT: ret
+;
; RV32-ZCMP-LABEL: caller_sw_clobber_s11:
; RV32-ZCMP: # %bb.0:
; RV32-ZCMP-NEXT: addi gp, gp, 4
@@ -958,6 +1142,32 @@ define i32 @caller_sw_clobber_s11(i32 %x) shadowcallstack {
; RV64-SAVE-RESTORE-NEXT: .cfi_restore gp
; RV64-SAVE-RESTORE-NEXT: ret
;
+; RV64D-SAVE-RESTORE-LABEL: caller_sw_clobber_s11:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64D-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64D-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64D-SAVE-RESTORE-NEXT: call t0, __riscv_save_12
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 112
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset s11, -104
+; RV64D-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64D-SAVE-RESTORE-NEXT: call callee
+; RV64D-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64D-SAVE-RESTORE-NEXT: #APP
+; RV64D-SAVE-RESTORE-NEXT: nop
+; RV64D-SAVE-RESTORE-NEXT: #NO_APP
+; RV64D-SAVE-RESTORE-NEXT: ld ra, 104(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: ld s11, 8(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore s11
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, 112
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64D-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64D-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64D-SAVE-RESTORE-NEXT: ret
+;
; RV64-ZCMP-LABEL: caller_sw_clobber_s11:
; RV64-ZCMP: # %bb.0:
; RV64-ZCMP-NEXT: addi gp, gp, 8
@@ -1027,6 +1237,322 @@ define i32 @caller_sw_clobber_s11(i32 %x) shadowcallstack {
ret i32 %add
}
+define float @caller_sw_float(float %x, float %y, float %z) shadowcallstack {
+; RV32-LABEL: caller_sw_float:
+; RV32: # %bb.0:
+; RV32-NEXT: addi gp, gp, 4
+; RV32-NEXT: sw ra, -4(gp)
+; RV32-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: .cfi_def_cfa_offset 16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -4
+; RV32-NEXT: .cfi_offset s0, -8
+; RV32-NEXT: .cfi_offset s1, -12
+; RV32-NEXT: mv s0, a2
+; RV32-NEXT: mv s1, a1
+; RV32-NEXT: call callee_float
+; RV32-NEXT: mv a0, s1
+; RV32-NEXT: mv a1, s0
+; RV32-NEXT: call __mulsf3
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore s0
+; RV32-NEXT: .cfi_restore s1
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: lw ra, -4(gp)
+; RV32-NEXT: addi gp, gp, -4
+; RV32-NEXT: .cfi_restore gp
+; RV32-NEXT: ret
+;
+; RV32-SAVE-RESTORE-LABEL: caller_sw_float:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-SAVE-RESTORE-NEXT: call t0, __riscv_save_2
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset s0, -8
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset s1, -12
+; RV32-SAVE-RESTORE-NEXT: mv s0, a2
+; RV32-SAVE-RESTORE-NEXT: mv s1, a1
+; RV32-SAVE-RESTORE-NEXT: call callee_float
+; RV32-SAVE-RESTORE-NEXT: mv a0, s1
+; RV32-SAVE-RESTORE-NEXT: mv a1, s0
+; RV32-SAVE-RESTORE-NEXT: call __mulsf3
+; RV32-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore s1
+; RV32-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32-SAVE-RESTORE-NEXT: ret
+;
+; RV32D-SAVE-RESTORE-LABEL: caller_sw_float:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32D-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32D-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, -16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 32
+; RV32D-SAVE-RESTORE-NEXT: fsd fs0, 8(sp) # 8-byte Folded Spill
+; RV32D-SAVE-RESTORE-NEXT: fsd fs1, 0(sp) # 8-byte Folded Spill
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset fs0, -24
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset fs1, -32
+; RV32D-SAVE-RESTORE-NEXT: fmv.s fs0, fa2
+; RV32D-SAVE-RESTORE-NEXT: fmv.s fs1, fa1
+; RV32D-SAVE-RESTORE-NEXT: call callee_float
+; RV32D-SAVE-RESTORE-NEXT: fmul.s fa0, fs1, fs0
+; RV32D-SAVE-RESTORE-NEXT: fld fs0, 8(sp) # 8-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: fld fs1, 0(sp) # 8-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore fs0
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore fs1
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, 32
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32D-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32D-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32D-SAVE-RESTORE-NEXT: ret
+;
+; RV32-ZCMP-LABEL: caller_sw_float:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: addi gp, gp, 4
+; RV32-ZCMP-NEXT: sw ra, -4(gp)
+; RV32-ZCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-ZCMP-NEXT: cm.push {ra, s0-s1}, -16
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-NEXT: .cfi_offset ra, -12
+; RV32-ZCMP-NEXT: .cfi_offset s0, -8
+; RV32-ZCMP-NEXT: .cfi_offset s1, -4
+; RV32-ZCMP-NEXT: mv s0, a2
+; RV32-ZCMP-NEXT: mv s1, a1
+; RV32-ZCMP-NEXT: call callee_float
+; RV32-ZCMP-NEXT: cm.mva01s s1, s0
+; RV32-ZCMP-NEXT: call __mulsf3
+; RV32-ZCMP-NEXT: cm.pop {ra, s0-s1}, 16
+; RV32-ZCMP-NEXT: lw ra, -4(gp)
+; RV32-ZCMP-NEXT: addi gp, gp, -4
+; RV32-ZCMP-NEXT: .cfi_restore gp
+; RV32-ZCMP-NEXT: ret
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_sw_float:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, 4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sw ra, -4(gp)
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra, s0-s1}, -16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -12
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s0, -8
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s1, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: mv s0, a2
+; RV32-ZCMP-SAVE-RESTORE-NEXT: mv s1, a1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call callee_float
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.mva01s s1, s0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call __mulsf3
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra, s0-s1}, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: lw ra, -4(gp)
+; RV32-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV32-XQCCMP-LABEL: caller_sw_float:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: addi gp, gp, 4
+; RV32-XQCCMP-NEXT: sw ra, -4(gp)
+; RV32-XQCCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x7c #
+; RV32-XQCCMP-NEXT: qc.cm.push {ra, s0-s1}, -16
+; RV32-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-XQCCMP-NEXT: .cfi_offset ra, -4
+; RV32-XQCCMP-NEXT: .cfi_offset s0, -8
+; RV32-XQCCMP-NEXT: .cfi_offset s1, -12
+; RV32-XQCCMP-NEXT: mv s0, a2
+; RV32-XQCCMP-NEXT: mv s1, a1
+; RV32-XQCCMP-NEXT: call callee_float
+; RV32-XQCCMP-NEXT: qc.cm.mva01s s1, s0
+; RV32-XQCCMP-NEXT: call __mulsf3
+; RV32-XQCCMP-NEXT: qc.cm.pop {ra, s0-s1}, 16
+; RV32-XQCCMP-NEXT: lw ra, -4(gp)
+; RV32-XQCCMP-NEXT: addi gp, gp, -4
+; RV32-XQCCMP-NEXT: .cfi_restore gp
+; RV32-XQCCMP-NEXT: ret
+;
+; RV64-LABEL: caller_sw_float:
+; RV64: # %bb.0:
+; RV64-NEXT: addi gp, gp, 8
+; RV64-NEXT: sd ra, -8(gp)
+; RV64-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-NEXT: addi sp, sp, -32
+; RV64-NEXT: .cfi_def_cfa_offset 32
+; RV64-NEXT: sd ra, 24(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 ra, -8
+; RV64-NEXT: .cfi_offset s0, -16
+; RV64-NEXT: .cfi_offset s1, -24
+; RV64-NEXT: mv s0, a2
+; RV64-NEXT: mv s1, a1
+; RV64-NEXT: call callee_float
+; RV64-NEXT: mv a0, s1
+; RV64-NEXT: mv a1, s0
+; RV64-NEXT: call __mulsf3
+; RV64-NEXT: ld ra, 24(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: .cfi_restore ra
+; RV64-NEXT: .cfi_restore s0
+; RV64-NEXT: .cfi_restore s1
+; RV64-NEXT: addi sp, sp, 32
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: ld ra, -8(gp)
+; RV64-NEXT: addi gp, gp, -8
+; RV64-NEXT: .cfi_restore gp
+; RV64-NEXT: ret
+;
+; RV64-SAVE-RESTORE-LABEL: caller_sw_float:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-SAVE-RESTORE-NEXT: call t0, __riscv_save_2
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 32
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset s0, -16
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset s1, -24
+; RV64-SAVE-RESTORE-NEXT: mv s0, a2
+; RV64-SAVE-RESTORE-NEXT: mv s1, a1
+; RV64-SAVE-RESTORE-NEXT: call callee_float
+; RV64-SAVE-RESTORE-NEXT: mv a0, s1
+; RV64-SAVE-RESTORE-NEXT: mv a1, s0
+; RV64-SAVE-RESTORE-NEXT: call __mulsf3
+; RV64-SAVE-RESTORE-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore s1
+; RV64-SAVE-RESTORE-NEXT: addi sp, sp, 32
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64-SAVE-RESTORE-NEXT: ret
+;
+; RV64D-SAVE-RESTORE-LABEL: caller_sw_float:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64D-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64D-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, -16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 32
+; RV64D-SAVE-RESTORE-NEXT: fsd fs0, 8(sp) # 8-byte Folded Spill
+; RV64D-SAVE-RESTORE-NEXT: fsd fs1, 0(sp) # 8-byte Folded Spill
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset fs0, -24
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset fs1, -32
+; RV64D-SAVE-RESTORE-NEXT: fmv.s fs0, fa2
+; RV64D-SAVE-RESTORE-NEXT: fmv.s fs1, fa1
+; RV64D-SAVE-RESTORE-NEXT: call callee_float
+; RV64D-SAVE-RESTORE-NEXT: fmul.s fa0, fs1, fs0
+; RV64D-SAVE-RESTORE-NEXT: fld fs0, 8(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: fld fs1, 0(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore fs0
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore fs1
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, 32
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64D-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64D-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64D-SAVE-RESTORE-NEXT: ret
+;
+; RV64-ZCMP-LABEL: caller_sw_float:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: addi gp, gp, 8
+; RV64-ZCMP-NEXT: sd ra, -8(gp)
+; RV64-ZCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-ZCMP-NEXT: cm.push {ra, s0-s1}, -32
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 32
+; RV64-ZCMP-NEXT: .cfi_offset ra, -24
+; RV64-ZCMP-NEXT: .cfi_offset s0, -16
+; RV64-ZCMP-NEXT: .cfi_offset s1, -8
+; RV64-ZCMP-NEXT: mv s0, a2
+; RV64-ZCMP-NEXT: mv s1, a1
+; RV64-ZCMP-NEXT: call callee_float
+; RV64-ZCMP-NEXT: cm.mva01s s1, s0
+; RV64-ZCMP-NEXT: call __mulsf3
+; RV64-ZCMP-NEXT: cm.pop {ra, s0-s1}, 32
+; RV64-ZCMP-NEXT: ld ra, -8(gp)
+; RV64-ZCMP-NEXT: addi gp, gp, -8
+; RV64-ZCMP-NEXT: .cfi_restore gp
+; RV64-ZCMP-NEXT: ret
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_sw_float:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, 8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sd ra, -8(gp)
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra, s0-s1}, -32
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 32
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -24
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s0, -16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s1, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: mv s0, a2
+; RV64-ZCMP-SAVE-RESTORE-NEXT: mv s1, a1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call callee_float
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.mva01s s1, s0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call __mulsf3
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra, s0-s1}, 32
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ld ra, -8(gp)
+; RV64-ZCMP-SAVE-RESTORE-NEXT: addi gp, gp, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_restore gp
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV64-XQCCMP-LABEL: caller_sw_float:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: addi gp, gp, 8
+; RV64-XQCCMP-NEXT: sd ra, -8(gp)
+; RV64-XQCCMP-NEXT: .cfi_escape 0x16, 0x03, 0x02, 0x73, 0x78 #
+; RV64-XQCCMP-NEXT: qc.cm.push {ra, s0-s1}, -32
+; RV64-XQCCMP-NEXT: .cfi_def_cfa_offset 32
+; RV64-XQCCMP-NEXT: .cfi_offset ra, -8
+; RV64-XQCCMP-NEXT: .cfi_offset s0, -16
+; RV64-XQCCMP-NEXT: .cfi_offset s1, -24
+; RV64-XQCCMP-NEXT: mv s0, a2
+; RV64-XQCCMP-NEXT: mv s1, a1
+; RV64-XQCCMP-NEXT: call callee_float
+; RV64-XQCCMP-NEXT: qc.cm.mva01s s1, s0
+; RV64-XQCCMP-NEXT: call __mulsf3
+; RV64-XQCCMP-NEXT: qc.cm.pop {ra, s0-s1}, 32
+; RV64-XQCCMP-NEXT: ld ra, -8(gp)
+; RV64-XQCCMP-NEXT: addi gp, gp, -8
+; RV64-XQCCMP-NEXT: .cfi_restore gp
+; RV64-XQCCMP-NEXT: ret
+ %a = call float @callee_float(float %x)
+ %b = fmul float %y, %z
+ ret float %b
+}
+
+
;; Hardware Shadow Call Stack
define i32 @caller_hw(i32 %x) "hw-shadow-stack" {
@@ -1063,6 +1589,22 @@ define i32 @caller_hw(i32 %x) "hw-shadow-stack" {
; RV32-SAVE-RESTORE-NEXT: sspopchk ra
; RV32-SAVE-RESTORE-NEXT: ret
;
+; RV32D-SAVE-RESTORE-LABEL: caller_hw:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: sspush ra
+; RV32D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32D-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32D-SAVE-RESTORE-NEXT: call callee
+; RV32D-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32D-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32D-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32D-SAVE-RESTORE-NEXT: ret
+;
; RV32-ZCMP-LABEL: caller_hw:
; RV32-ZCMP: # %bb.0:
; RV32-ZCMP-NEXT: sspush ra
@@ -1135,6 +1677,22 @@ define i32 @caller_hw(i32 %x) "hw-shadow-stack" {
; RV64-SAVE-RESTORE-NEXT: sspopchk ra
; RV64-SAVE-RESTORE-NEXT: ret
;
+; RV64D-SAVE-RESTORE-LABEL: caller_hw:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: sspush ra
+; RV64D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64D-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64D-SAVE-RESTORE-NEXT: call callee
+; RV64D-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64D-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64D-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64D-SAVE-RESTORE-NEXT: ret
+;
; RV64-ZCMP-LABEL: caller_hw:
; RV64-ZCMP: # %bb.0:
; RV64-ZCMP-NEXT: sspush ra
@@ -1190,6 +1748,11 @@ define i32 @caller_hw_tail(i32 %x) "hw-shadow-stack" {
; RV32-SAVE-RESTORE-NEXT: neg a0, a0
; RV32-SAVE-RESTORE-NEXT: tail callee
;
+; RV32D-SAVE-RESTORE-LABEL: caller_hw_tail:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32D-SAVE-RESTORE-NEXT: tail callee
+;
; RV32-ZCMP-LABEL: caller_hw_tail:
; RV32-ZCMP: # %bb.0:
; RV32-ZCMP-NEXT: neg a0, a0
@@ -1215,6 +1778,11 @@ define i32 @caller_hw_tail(i32 %x) "hw-shadow-stack" {
; RV64-SAVE-RESTORE-NEXT: negw a0, a0
; RV64-SAVE-RESTORE-NEXT: tail callee
;
+; RV64D-SAVE-RESTORE-LABEL: caller_hw_tail:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64D-SAVE-RESTORE-NEXT: tail callee
+;
; RV64-ZCMP-LABEL: caller_hw_tail:
; RV64-ZCMP: # %bb.0:
; RV64-ZCMP-NEXT: negw a0, a0
@@ -1281,6 +1849,28 @@ define i32 @caller_hw_fp(i32 %x) "hw-shadow-stack" "frame-pointer"="all" {
; RV32-SAVE-RESTORE-NEXT: sspopchk ra
; RV32-SAVE-RESTORE-NEXT: ret
;
+; RV32D-SAVE-RESTORE-LABEL: caller_hw_fp:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: sspush ra
+; RV32D-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset s0, -8
+; RV32D-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV32D-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32D-SAVE-RESTORE-NEXT: call callee
+; RV32D-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV32D-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32D-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32D-SAVE-RESTORE-NEXT: ret
+;
; RV32-ZCMP-LABEL: caller_hw_fp:
; RV32-ZCMP: # %bb.0:
; RV32-ZCMP-NEXT: sspush ra
@@ -1389,6 +1979,28 @@ define i32 @caller_hw_fp(i32 %x) "hw-shadow-stack" "frame-pointer"="all" {
; RV64-SAVE-RESTORE-NEXT: sspopchk ra
; RV64-SAVE-RESTORE-NEXT: ret
;
+; RV64D-SAVE-RESTORE-LABEL: caller_hw_fp:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: sspush ra
+; RV64D-SAVE-RESTORE-NEXT: call t0, __riscv_save_1
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset s0, -16
+; RV64D-SAVE-RESTORE-NEXT: addi s0, sp, 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa s0, 0
+; RV64D-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64D-SAVE-RESTORE-NEXT: call callee
+; RV64D-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa sp, 16
+; RV64D-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: ld s0, 0(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64D-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64D-SAVE-RESTORE-NEXT: ret
+;
; RV64-ZCMP-LABEL: caller_hw_fp:
; RV64-ZCMP: # %bb.0:
; RV64-ZCMP-NEXT: sspush ra
@@ -1460,7 +2072,7 @@ define i32 @caller_hw_fp(i32 %x) "hw-shadow-stack" "frame-pointer"="all" {
define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
; RV32-LABEL: caller_hw_cond:
; RV32: # %bb.0:
-; RV32-NEXT: beqz a0, .LBB8_2
+; RV32-NEXT: beqz a0, .LBB9_2
; RV32-NEXT: # %bb.1: # %if.end
; RV32-NEXT: sspush ra
; RV32-NEXT: addi sp, sp, -16
@@ -1476,13 +2088,13 @@ define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
; RV32-NEXT: .cfi_def_cfa_offset 0
; RV32-NEXT: sspopchk ra
; RV32-NEXT: ret
-; RV32-NEXT: .LBB8_2: # %return
+; RV32-NEXT: .LBB9_2: # %return
; RV32-NEXT: li a0, 1
; RV32-NEXT: ret
;
; RV32-SAVE-RESTORE-LABEL: caller_hw_cond:
; RV32-SAVE-RESTORE: # %bb.0:
-; RV32-SAVE-RESTORE-NEXT: beqz a0, .LBB8_2
+; RV32-SAVE-RESTORE-NEXT: beqz a0, .LBB9_2
; RV32-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
; RV32-SAVE-RESTORE-NEXT: sspush ra
; RV32-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
@@ -1497,13 +2109,34 @@ define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
; RV32-SAVE-RESTORE-NEXT: sspopchk ra
; RV32-SAVE-RESTORE-NEXT: ret
-; RV32-SAVE-RESTORE-NEXT: .LBB8_2: # %return
+; RV32-SAVE-RESTORE-NEXT: .LBB9_2: # %return
; RV32-SAVE-RESTORE-NEXT: li a0, 1
; RV32-SAVE-RESTORE-NEXT: ret
;
+; RV32D-SAVE-RESTORE-LABEL: caller_hw_cond:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: beqz a0, .LBB9_2
+; RV32D-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV32D-SAVE-RESTORE-NEXT: sspush ra
+; RV32D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32D-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32D-SAVE-RESTORE-NEXT: call callee
+; RV32D-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32D-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32D-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32D-SAVE-RESTORE-NEXT: ret
+; RV32D-SAVE-RESTORE-NEXT: .LBB9_2: # %return
+; RV32D-SAVE-RESTORE-NEXT: li a0, 1
+; RV32D-SAVE-RESTORE-NEXT: ret
+;
; RV32-ZCMP-LABEL: caller_hw_cond:
; RV32-ZCMP: # %bb.0:
-; RV32-ZCMP-NEXT: beqz a0, .LBB8_2
+; RV32-ZCMP-NEXT: beqz a0, .LBB9_2
; RV32-ZCMP-NEXT: # %bb.1: # %if.end
; RV32-ZCMP-NEXT: sspush ra
; RV32-ZCMP-NEXT: cm.push {ra}, -16
@@ -1515,13 +2148,13 @@ define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
; RV32-ZCMP-NEXT: cm.pop {ra}, 16
; RV32-ZCMP-NEXT: sspopchk ra
; RV32-ZCMP-NEXT: ret
-; RV32-ZCMP-NEXT: .LBB8_2: # %return
+; RV32-ZCMP-NEXT: .LBB9_2: # %return
; RV32-ZCMP-NEXT: li a0, 1
; RV32-ZCMP-NEXT: ret
;
; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_hw_cond:
; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
-; RV32-ZCMP-SAVE-RESTORE-NEXT: beqz a0, .LBB8_2
+; RV32-ZCMP-SAVE-RESTORE-NEXT: beqz a0, .LBB9_2
; RV32-ZCMP-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
; RV32-ZCMP-SAVE-RESTORE-NEXT: sspush ra
; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra}, -16
@@ -1533,13 +2166,13 @@ define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra}, 16
; RV32-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
-; RV32-ZCMP-SAVE-RESTORE-NEXT: .LBB8_2: # %return
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .LBB9_2: # %return
; RV32-ZCMP-SAVE-RESTORE-NEXT: li a0, 1
; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
;
; RV32-XQCCMP-LABEL: caller_hw_cond:
; RV32-XQCCMP: # %bb.0:
-; RV32-XQCCMP-NEXT: beqz a0, .LBB8_2
+; RV32-XQCCMP-NEXT: beqz a0, .LBB9_2
; RV32-XQCCMP-NEXT: # %bb.1: # %if.end
; RV32-XQCCMP-NEXT: sspush ra
; RV32-XQCCMP-NEXT: qc.cm.push {ra}, -16
@@ -1551,14 +2184,14 @@ define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
; RV32-XQCCMP-NEXT: qc.cm.pop {ra}, 16
; RV32-XQCCMP-NEXT: sspopchk ra
; RV32-XQCCMP-NEXT: ret
-; RV32-XQCCMP-NEXT: .LBB8_2: # %return
+; RV32-XQCCMP-NEXT: .LBB9_2: # %return
; RV32-XQCCMP-NEXT: li a0, 1
; RV32-XQCCMP-NEXT: ret
;
; RV64-LABEL: caller_hw_cond:
; RV64: # %bb.0:
; RV64-NEXT: sext.w a1, a0
-; RV64-NEXT: beqz a1, .LBB8_2
+; RV64-NEXT: beqz a1, .LBB9_2
; RV64-NEXT: # %bb.1: # %if.end
; RV64-NEXT: sspush ra
; RV64-NEXT: addi sp, sp, -16
@@ -1574,14 +2207,14 @@ define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
; RV64-NEXT: .cfi_def_cfa_offset 0
; RV64-NEXT: sspopchk ra
; RV64-NEXT: ret
-; RV64-NEXT: .LBB8_2: # %return
+; RV64-NEXT: .LBB9_2: # %return
; RV64-NEXT: li a0, 1
; RV64-NEXT: ret
;
; RV64-SAVE-RESTORE-LABEL: caller_hw_cond:
; RV64-SAVE-RESTORE: # %bb.0:
; RV64-SAVE-RESTORE-NEXT: sext.w a1, a0
-; RV64-SAVE-RESTORE-NEXT: beqz a1, .LBB8_2
+; RV64-SAVE-RESTORE-NEXT: beqz a1, .LBB9_2
; RV64-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
; RV64-SAVE-RESTORE-NEXT: sspush ra
; RV64-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
@@ -1596,14 +2229,36 @@ define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
; RV64-SAVE-RESTORE-NEXT: sspopchk ra
; RV64-SAVE-RESTORE-NEXT: ret
-; RV64-SAVE-RESTORE-NEXT: .LBB8_2: # %return
+; RV64-SAVE-RESTORE-NEXT: .LBB9_2: # %return
; RV64-SAVE-RESTORE-NEXT: li a0, 1
; RV64-SAVE-RESTORE-NEXT: ret
;
+; RV64D-SAVE-RESTORE-LABEL: caller_hw_cond:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: sext.w a1, a0
+; RV64D-SAVE-RESTORE-NEXT: beqz a1, .LBB9_2
+; RV64D-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
+; RV64D-SAVE-RESTORE-NEXT: sspush ra
+; RV64D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64D-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64D-SAVE-RESTORE-NEXT: call callee
+; RV64D-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64D-SAVE-RESTORE-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64D-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64D-SAVE-RESTORE-NEXT: ret
+; RV64D-SAVE-RESTORE-NEXT: .LBB9_2: # %return
+; RV64D-SAVE-RESTORE-NEXT: li a0, 1
+; RV64D-SAVE-RESTORE-NEXT: ret
+;
; RV64-ZCMP-LABEL: caller_hw_cond:
; RV64-ZCMP: # %bb.0:
; RV64-ZCMP-NEXT: sext.w a1, a0
-; RV64-ZCMP-NEXT: beqz a1, .LBB8_2
+; RV64-ZCMP-NEXT: beqz a1, .LBB9_2
; RV64-ZCMP-NEXT: # %bb.1: # %if.end
; RV64-ZCMP-NEXT: sspush ra
; RV64-ZCMP-NEXT: cm.push {ra}, -16
@@ -1615,14 +2270,14 @@ define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
; RV64-ZCMP-NEXT: cm.pop {ra}, 16
; RV64-ZCMP-NEXT: sspopchk ra
; RV64-ZCMP-NEXT: ret
-; RV64-ZCMP-NEXT: .LBB8_2: # %return
+; RV64-ZCMP-NEXT: .LBB9_2: # %return
; RV64-ZCMP-NEXT: li a0, 1
; RV64-ZCMP-NEXT: ret
;
; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_hw_cond:
; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
; RV64-ZCMP-SAVE-RESTORE-NEXT: sext.w a1, a0
-; RV64-ZCMP-SAVE-RESTORE-NEXT: beqz a1, .LBB8_2
+; RV64-ZCMP-SAVE-RESTORE-NEXT: beqz a1, .LBB9_2
; RV64-ZCMP-SAVE-RESTORE-NEXT: # %bb.1: # %if.end
; RV64-ZCMP-SAVE-RESTORE-NEXT: sspush ra
; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra}, -16
@@ -1634,14 +2289,14 @@ define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra}, 16
; RV64-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
-; RV64-ZCMP-SAVE-RESTORE-NEXT: .LBB8_2: # %return
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .LBB9_2: # %return
; RV64-ZCMP-SAVE-RESTORE-NEXT: li a0, 1
; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
;
; RV64-XQCCMP-LABEL: caller_hw_cond:
; RV64-XQCCMP: # %bb.0:
; RV64-XQCCMP-NEXT: sext.w a1, a0
-; RV64-XQCCMP-NEXT: beqz a1, .LBB8_2
+; RV64-XQCCMP-NEXT: beqz a1, .LBB9_2
; RV64-XQCCMP-NEXT: # %bb.1: # %if.end
; RV64-XQCCMP-NEXT: sspush ra
; RV64-XQCCMP-NEXT: qc.cm.push {ra}, -16
@@ -1653,7 +2308,7 @@ define i32 @caller_hw_cond(i32 %x) "hw-shadow-stack" {
; RV64-XQCCMP-NEXT: qc.cm.pop {ra}, 16
; RV64-XQCCMP-NEXT: sspopchk ra
; RV64-XQCCMP-NEXT: ret
-; RV64-XQCCMP-NEXT: .LBB8_2: # %return
+; RV64-XQCCMP-NEXT: .LBB9_2: # %return
; RV64-XQCCMP-NEXT: li a0, 1
; RV64-XQCCMP-NEXT: ret
%cmp = icmp eq i32 %x, 0
@@ -1716,6 +2371,28 @@ define i32 @caller_hw_clobber_s11(i32 %x) "hw-shadow-stack" {
; RV32-SAVE-RESTORE-NEXT: sspopchk ra
; RV32-SAVE-RESTORE-NEXT: ret
;
+; RV32D-SAVE-RESTORE-LABEL: caller_hw_clobber_s11:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: sspush ra
+; RV32D-SAVE-RESTORE-NEXT: call t0, __riscv_save_12
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 64
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset s11, -52
+; RV32D-SAVE-RESTORE-NEXT: neg a0, a0
+; RV32D-SAVE-RESTORE-NEXT: call callee
+; RV32D-SAVE-RESTORE-NEXT: addi a0, a0, 1
+; RV32D-SAVE-RESTORE-NEXT: #APP
+; RV32D-SAVE-RESTORE-NEXT: nop
+; RV32D-SAVE-RESTORE-NEXT: #NO_APP
+; RV32D-SAVE-RESTORE-NEXT: lw ra, 60(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: lw s11, 12(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore s11
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, 64
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32D-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32D-SAVE-RESTORE-NEXT: ret
+;
; RV32-ZCMP-LABEL: caller_hw_clobber_s11:
; RV32-ZCMP: # %bb.0:
; RV32-ZCMP-NEXT: sspush ra
@@ -1813,6 +2490,28 @@ define i32 @caller_hw_clobber_s11(i32 %x) "hw-shadow-stack" {
; RV64-SAVE-RESTORE-NEXT: sspopchk ra
; RV64-SAVE-RESTORE-NEXT: ret
;
+; RV64D-SAVE-RESTORE-LABEL: caller_hw_clobber_s11:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: sspush ra
+; RV64D-SAVE-RESTORE-NEXT: call t0, __riscv_save_12
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 112
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset s11, -104
+; RV64D-SAVE-RESTORE-NEXT: negw a0, a0
+; RV64D-SAVE-RESTORE-NEXT: call callee
+; RV64D-SAVE-RESTORE-NEXT: addiw a0, a0, 1
+; RV64D-SAVE-RESTORE-NEXT: #APP
+; RV64D-SAVE-RESTORE-NEXT: nop
+; RV64D-SAVE-RESTORE-NEXT: #NO_APP
+; RV64D-SAVE-RESTORE-NEXT: ld ra, 104(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: ld s11, 8(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore s11
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, 112
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64D-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64D-SAVE-RESTORE-NEXT: ret
+;
; RV64-ZCMP-LABEL: caller_hw_clobber_s11:
; RV64-ZCMP: # %bb.0:
; RV64-ZCMP-NEXT: sspush ra
@@ -1869,3 +2568,270 @@ define i32 @caller_hw_clobber_s11(i32 %x) "hw-shadow-stack" {
call void asm sideeffect "nop", "~{x27}"()
ret i32 %add
}
+
+define float @caller_hw_float(float %x, float %y, float %z) "hw-shadow-stack" {
+; RV32-LABEL: caller_hw_float:
+; RV32: # %bb.0:
+; RV32-NEXT: sspush ra
+; RV32-NEXT: addi sp, sp, -16
+; RV32-NEXT: .cfi_def_cfa_offset 16
+; RV32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32-NEXT: sw s1, 4(sp) # 4-byte Folded Spill
+; RV32-NEXT: .cfi_offset ra, -4
+; RV32-NEXT: .cfi_offset s0, -8
+; RV32-NEXT: .cfi_offset s1, -12
+; RV32-NEXT: mv s0, a2
+; RV32-NEXT: mv s1, a1
+; RV32-NEXT: call callee_float
+; RV32-NEXT: mv a0, s1
+; RV32-NEXT: mv a1, s0
+; RV32-NEXT: call __mulsf3
+; RV32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
+; RV32-NEXT: .cfi_restore ra
+; RV32-NEXT: .cfi_restore s0
+; RV32-NEXT: .cfi_restore s1
+; RV32-NEXT: addi sp, sp, 16
+; RV32-NEXT: .cfi_def_cfa_offset 0
+; RV32-NEXT: sspopchk ra
+; RV32-NEXT: ret
+;
+; RV32-SAVE-RESTORE-LABEL: caller_hw_float:
+; RV32-SAVE-RESTORE: # %bb.0:
+; RV32-SAVE-RESTORE-NEXT: sspush ra
+; RV32-SAVE-RESTORE-NEXT: call t0, __riscv_save_2
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset s0, -8
+; RV32-SAVE-RESTORE-NEXT: .cfi_offset s1, -12
+; RV32-SAVE-RESTORE-NEXT: mv s0, a2
+; RV32-SAVE-RESTORE-NEXT: mv s1, a1
+; RV32-SAVE-RESTORE-NEXT: call callee_float
+; RV32-SAVE-RESTORE-NEXT: mv a0, s1
+; RV32-SAVE-RESTORE-NEXT: mv a1, s0
+; RV32-SAVE-RESTORE-NEXT: call __mulsf3
+; RV32-SAVE-RESTORE-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: lw s1, 4(sp) # 4-byte Folded Reload
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV32-SAVE-RESTORE-NEXT: .cfi_restore s1
+; RV32-SAVE-RESTORE-NEXT: addi sp, sp, 16
+; RV32-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32-SAVE-RESTORE-NEXT: ret
+;
+; RV32D-SAVE-RESTORE-LABEL: caller_hw_float:
+; RV32D-SAVE-RESTORE: # %bb.0:
+; RV32D-SAVE-RESTORE-NEXT: sspush ra
+; RV32D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset ra, -4
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, -16
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 32
+; RV32D-SAVE-RESTORE-NEXT: fsd fs0, 8(sp) # 8-byte Folded Spill
+; RV32D-SAVE-RESTORE-NEXT: fsd fs1, 0(sp) # 8-byte Folded Spill
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset fs0, -24
+; RV32D-SAVE-RESTORE-NEXT: .cfi_offset fs1, -32
+; RV32D-SAVE-RESTORE-NEXT: fmv.s fs0, fa2
+; RV32D-SAVE-RESTORE-NEXT: fmv.s fs1, fa1
+; RV32D-SAVE-RESTORE-NEXT: call callee_float
+; RV32D-SAVE-RESTORE-NEXT: fmul.s fa0, fs1, fs0
+; RV32D-SAVE-RESTORE-NEXT: fld fs0, 8(sp) # 8-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: fld fs1, 0(sp) # 8-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: lw ra, 28(sp) # 4-byte Folded Reload
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore fs0
+; RV32D-SAVE-RESTORE-NEXT: .cfi_restore fs1
+; RV32D-SAVE-RESTORE-NEXT: addi sp, sp, 32
+; RV32D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV32D-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32D-SAVE-RESTORE-NEXT: ret
+;
+; RV32-ZCMP-LABEL: caller_hw_float:
+; RV32-ZCMP: # %bb.0:
+; RV32-ZCMP-NEXT: sspush ra
+; RV32-ZCMP-NEXT: cm.push {ra, s0-s1}, -16
+; RV32-ZCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-NEXT: .cfi_offset ra, -12
+; RV32-ZCMP-NEXT: .cfi_offset s0, -8
+; RV32-ZCMP-NEXT: .cfi_offset s1, -4
+; RV32-ZCMP-NEXT: mv s0, a2
+; RV32-ZCMP-NEXT: mv s1, a1
+; RV32-ZCMP-NEXT: call callee_float
+; RV32-ZCMP-NEXT: cm.mva01s s1, s0
+; RV32-ZCMP-NEXT: call __mulsf3
+; RV32-ZCMP-NEXT: cm.pop {ra, s0-s1}, 16
+; RV32-ZCMP-NEXT: sspopchk ra
+; RV32-ZCMP-NEXT: ret
+;
+; RV32-ZCMP-SAVE-RESTORE-LABEL: caller_hw_float:
+; RV32-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sspush ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra, s0-s1}, -16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -12
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s0, -8
+; RV32-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s1, -4
+; RV32-ZCMP-SAVE-RESTORE-NEXT: mv s0, a2
+; RV32-ZCMP-SAVE-RESTORE-NEXT: mv s1, a1
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call callee_float
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.mva01s s1, s0
+; RV32-ZCMP-SAVE-RESTORE-NEXT: call __mulsf3
+; RV32-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra, s0-s1}, 16
+; RV32-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
+; RV32-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV32-XQCCMP-LABEL: caller_hw_float:
+; RV32-XQCCMP: # %bb.0:
+; RV32-XQCCMP-NEXT: sspush ra
+; RV32-XQCCMP-NEXT: qc.cm.push {ra, s0-s1}, -16
+; RV32-XQCCMP-NEXT: .cfi_def_cfa_offset 16
+; RV32-XQCCMP-NEXT: .cfi_offset ra, -4
+; RV32-XQCCMP-NEXT: .cfi_offset s0, -8
+; RV32-XQCCMP-NEXT: .cfi_offset s1, -12
+; RV32-XQCCMP-NEXT: mv s0, a2
+; RV32-XQCCMP-NEXT: mv s1, a1
+; RV32-XQCCMP-NEXT: call callee_float
+; RV32-XQCCMP-NEXT: qc.cm.mva01s s1, s0
+; RV32-XQCCMP-NEXT: call __mulsf3
+; RV32-XQCCMP-NEXT: qc.cm.pop {ra, s0-s1}, 16
+; RV32-XQCCMP-NEXT: sspopchk ra
+; RV32-XQCCMP-NEXT: ret
+;
+; RV64-LABEL: caller_hw_float:
+; RV64: # %bb.0:
+; RV64-NEXT: sspush ra
+; RV64-NEXT: addi sp, sp, -32
+; RV64-NEXT: .cfi_def_cfa_offset 32
+; RV64-NEXT: sd ra, 24(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 ra, -8
+; RV64-NEXT: .cfi_offset s0, -16
+; RV64-NEXT: .cfi_offset s1, -24
+; RV64-NEXT: mv s0, a2
+; RV64-NEXT: mv s1, a1
+; RV64-NEXT: call callee_float
+; RV64-NEXT: mv a0, s1
+; RV64-NEXT: mv a1, s0
+; RV64-NEXT: call __mulsf3
+; RV64-NEXT: ld ra, 24(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: .cfi_restore ra
+; RV64-NEXT: .cfi_restore s0
+; RV64-NEXT: .cfi_restore s1
+; RV64-NEXT: addi sp, sp, 32
+; RV64-NEXT: .cfi_def_cfa_offset 0
+; RV64-NEXT: sspopchk ra
+; RV64-NEXT: ret
+;
+; RV64-SAVE-RESTORE-LABEL: caller_hw_float:
+; RV64-SAVE-RESTORE: # %bb.0:
+; RV64-SAVE-RESTORE-NEXT: sspush ra
+; RV64-SAVE-RESTORE-NEXT: call t0, __riscv_save_2
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 32
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset s0, -16
+; RV64-SAVE-RESTORE-NEXT: .cfi_offset s1, -24
+; RV64-SAVE-RESTORE-NEXT: mv s0, a2
+; RV64-SAVE-RESTORE-NEXT: mv s1, a1
+; RV64-SAVE-RESTORE-NEXT: call callee_float
+; RV64-SAVE-RESTORE-NEXT: mv a0, s1
+; RV64-SAVE-RESTORE-NEXT: mv a1, s0
+; RV64-SAVE-RESTORE-NEXT: call __mulsf3
+; RV64-SAVE-RESTORE-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: ld s0, 16(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: ld s1, 8(sp) # 8-byte Folded Reload
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore s0
+; RV64-SAVE-RESTORE-NEXT: .cfi_restore s1
+; RV64-SAVE-RESTORE-NEXT: addi sp, sp, 32
+; RV64-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64-SAVE-RESTORE-NEXT: ret
+;
+; RV64D-SAVE-RESTORE-LABEL: caller_hw_float:
+; RV64D-SAVE-RESTORE: # %bb.0:
+; RV64D-SAVE-RESTORE-NEXT: sspush ra
+; RV64D-SAVE-RESTORE-NEXT: call t0, __riscv_save_0
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset ra, -8
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, -16
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 32
+; RV64D-SAVE-RESTORE-NEXT: fsd fs0, 8(sp) # 8-byte Folded Spill
+; RV64D-SAVE-RESTORE-NEXT: fsd fs1, 0(sp) # 8-byte Folded Spill
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset fs0, -24
+; RV64D-SAVE-RESTORE-NEXT: .cfi_offset fs1, -32
+; RV64D-SAVE-RESTORE-NEXT: fmv.s fs0, fa2
+; RV64D-SAVE-RESTORE-NEXT: fmv.s fs1, fa1
+; RV64D-SAVE-RESTORE-NEXT: call callee_float
+; RV64D-SAVE-RESTORE-NEXT: fmul.s fa0, fs1, fs0
+; RV64D-SAVE-RESTORE-NEXT: fld fs0, 8(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: fld fs1, 0(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: ld ra, 24(sp) # 8-byte Folded Reload
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore ra
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore fs0
+; RV64D-SAVE-RESTORE-NEXT: .cfi_restore fs1
+; RV64D-SAVE-RESTORE-NEXT: addi sp, sp, 32
+; RV64D-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 0
+; RV64D-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64D-SAVE-RESTORE-NEXT: ret
+;
+; RV64-ZCMP-LABEL: caller_hw_float:
+; RV64-ZCMP: # %bb.0:
+; RV64-ZCMP-NEXT: sspush ra
+; RV64-ZCMP-NEXT: cm.push {ra, s0-s1}, -32
+; RV64-ZCMP-NEXT: .cfi_def_cfa_offset 32
+; RV64-ZCMP-NEXT: .cfi_offset ra, -24
+; RV64-ZCMP-NEXT: .cfi_offset s0, -16
+; RV64-ZCMP-NEXT: .cfi_offset s1, -8
+; RV64-ZCMP-NEXT: mv s0, a2
+; RV64-ZCMP-NEXT: mv s1, a1
+; RV64-ZCMP-NEXT: call callee_float
+; RV64-ZCMP-NEXT: cm.mva01s s1, s0
+; RV64-ZCMP-NEXT: call __mulsf3
+; RV64-ZCMP-NEXT: cm.pop {ra, s0-s1}, 32
+; RV64-ZCMP-NEXT: sspopchk ra
+; RV64-ZCMP-NEXT: ret
+;
+; RV64-ZCMP-SAVE-RESTORE-LABEL: caller_hw_float:
+; RV64-ZCMP-SAVE-RESTORE: # %bb.0:
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sspush ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.push {ra, s0-s1}, -32
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_def_cfa_offset 32
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset ra, -24
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s0, -16
+; RV64-ZCMP-SAVE-RESTORE-NEXT: .cfi_offset s1, -8
+; RV64-ZCMP-SAVE-RESTORE-NEXT: mv s0, a2
+; RV64-ZCMP-SAVE-RESTORE-NEXT: mv s1, a1
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call callee_float
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.mva01s s1, s0
+; RV64-ZCMP-SAVE-RESTORE-NEXT: call __mulsf3
+; RV64-ZCMP-SAVE-RESTORE-NEXT: cm.pop {ra, s0-s1}, 32
+; RV64-ZCMP-SAVE-RESTORE-NEXT: sspopchk ra
+; RV64-ZCMP-SAVE-RESTORE-NEXT: ret
+;
+; RV64-XQCCMP-LABEL: caller_hw_float:
+; RV64-XQCCMP: # %bb.0:
+; RV64-XQCCMP-NEXT: sspush ra
+; RV64-XQCCMP-NEXT: qc.cm.push {ra, s0-s1}, -32
+; RV64-XQCCMP-NEXT: .cfi_def_cfa_offset 32
+; RV64-XQCCMP-NEXT: .cfi_offset ra, -8
+; RV64-XQCCMP-NEXT: .cfi_offset s0, -16
+; RV64-XQCCMP-NEXT: .cfi_offset s1, -24
+; RV64-XQCCMP-NEXT: mv s0, a2
+; RV64-XQCCMP-NEXT: mv s1, a1
+; RV64-XQCCMP-NEXT: call callee_float
+; RV64-XQCCMP-NEXT: qc.cm.mva01s s1, s0
+; RV64-XQCCMP-NEXT: call __mulsf3
+; RV64-XQCCMP-NEXT: qc.cm.pop {ra, s0-s1}, 32
+; RV64-XQCCMP-NEXT: sspopchk ra
+; RV64-XQCCMP-NEXT: ret
+ %a = call float @callee_float(float %x)
+ %b = fmul float %y, %z
+ ret float %b
+}
More information about the llvm-branch-commits
mailing list