[llvm] c0221e0 - [RISCV] Add a pass to combine `cm.pop` and `ret` insts
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 6 23:04:17 PDT 2023
Author: WuXinlong
Date: 2023-07-07T14:04:11+08:00
New Revision: c0221e006d47ed24c4562f264411943596a6800e
URL: https://github.com/llvm/llvm-project/commit/c0221e006d47ed24c4562f264411943596a6800e
DIFF: https://github.com/llvm/llvm-project/commit/c0221e006d47ed24c4562f264411943596a6800e.diff
LOG: [RISCV] Add a pass to combine `cm.pop` and `ret` insts
`RISCVPushPopOptimizer.cpp` combine `cm.pop` and `ret` to generates `cm.popretz` or `cm.popret` .
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D150416
Added:
llvm/lib/Target/RISCV/RISCVPushPopOptimizer.cpp
Modified:
llvm/lib/Target/RISCV/CMakeLists.txt
llvm/lib/Target/RISCV/RISCV.h
llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
llvm/test/CodeGen/RISCV/O3-pipeline.ll
llvm/test/CodeGen/RISCV/callee-saved-gprs.ll
llvm/test/CodeGen/RISCV/cm_mvas_mvsa.ll
llvm/test/CodeGen/RISCV/push-pop-popret.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/RISCV/CMakeLists.txt b/llvm/lib/Target/RISCV/CMakeLists.txt
index 5203c00415bce3..60d81da57da0e1 100644
--- a/llvm/lib/Target/RISCV/CMakeLists.txt
+++ b/llvm/lib/Target/RISCV/CMakeLists.txt
@@ -37,6 +37,7 @@ add_llvm_target(RISCVCodeGen
RISCVOptWInstrs.cpp
RISCVRedundantCopyElimination.cpp
RISCVMoveMerger.cpp
+ RISCVPushPopOptimizer.cpp
RISCVRegisterInfo.cpp
RISCVRVVInitUndef.cpp
RISCVSubtarget.cpp
diff --git a/llvm/lib/Target/RISCV/RISCV.h b/llvm/lib/Target/RISCV/RISCV.h
index 3f5966dd8538fd..107ca51520b77c 100644
--- a/llvm/lib/Target/RISCV/RISCV.h
+++ b/llvm/lib/Target/RISCV/RISCV.h
@@ -73,6 +73,9 @@ extern char &RISCVInitUndefID;
FunctionPass *createRISCVMoveMergePass();
void initializeRISCVMoveMergePass(PassRegistry &);
+FunctionPass *createRISCVPushPopOptimizationPass();
+void initializeRISCVPushPopOptPass(PassRegistry &);
+
InstructionSelector *createRISCVInstructionSelector(const RISCVTargetMachine &,
RISCVSubtarget &,
RISCVRegisterBankInfo &);
diff --git a/llvm/lib/Target/RISCV/RISCVPushPopOptimizer.cpp b/llvm/lib/Target/RISCV/RISCVPushPopOptimizer.cpp
new file mode 100644
index 00000000000000..5eb990f19562f7
--- /dev/null
+++ b/llvm/lib/Target/RISCV/RISCVPushPopOptimizer.cpp
@@ -0,0 +1,145 @@
+//===------- RISCVPushPopOptimizer.cpp - RISCV Push/Pop opt. pass ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a pass that modifies PUSH/POP instructions from Zca
+// standard to use their non prolog/epilog related functionalities
+// and generates POPRET instruction.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RISCVInstrInfo.h"
+#include "RISCVMachineFunctionInfo.h"
+
+using namespace llvm;
+
+#define RISCV_PUSH_POP_OPT_NAME "RISC-V Zcmp Push/Pop optimization pass"
+
+namespace {
+struct RISCVPushPopOpt : public MachineFunctionPass {
+ static char ID;
+
+ RISCVPushPopOpt() : MachineFunctionPass(ID) {
+ initializeRISCVPushPopOptPass(*PassRegistry::getPassRegistry());
+ }
+
+ const RISCVInstrInfo *TII;
+ const TargetRegisterInfo *TRI;
+
+ // Track which register units have been modified and used.
+ LiveRegUnits ModifiedRegUnits, UsedRegUnits;
+
+ bool usePopRet(MachineBasicBlock::iterator &MBBI,
+ MachineBasicBlock::iterator &NextI, bool IsReturnZero);
+ bool adjustRetVal(MachineBasicBlock::iterator &MBBI);
+ bool runOnMachineFunction(MachineFunction &Fn) override;
+
+ StringRef getPassName() const override { return RISCV_PUSH_POP_OPT_NAME; }
+};
+
+char RISCVPushPopOpt::ID = 0;
+
+} // end of anonymous namespace
+
+INITIALIZE_PASS(RISCVPushPopOpt, "riscv-push-pop-opt", RISCV_PUSH_POP_OPT_NAME,
+ false, false)
+
+// Check if POP instruction was inserted into the MBB and return iterator to it.
+static MachineBasicBlock::iterator containsPop(MachineBasicBlock &MBB) {
+ for (MachineBasicBlock::iterator MBBI = MBB.begin(); MBBI != MBB.end();
+ MBBI = next_nodbg(MBBI, MBB.end()))
+ if (MBBI->getOpcode() == RISCV::CM_POP)
+ return MBBI;
+
+ return MBB.end();
+}
+
+bool RISCVPushPopOpt::usePopRet(MachineBasicBlock::iterator &MBBI,
+ MachineBasicBlock::iterator &NextI,
+ bool IsReturnZero) {
+ // Since Pseudo instruction lowering happen later in the pipeline,
+ // this will detect all ret instruction.
+ DebugLoc DL = NextI->getDebugLoc();
+ unsigned Opc = IsReturnZero ? RISCV::CM_POPRETZ : RISCV::CM_POPRET;
+ BuildMI(*NextI->getParent(), NextI, DL, TII->get(Opc))
+ .add(MBBI->getOperand(0))
+ .add(MBBI->getOperand(1));
+
+ MBBI->eraseFromParent();
+ NextI->eraseFromParent();
+ return true;
+}
+
+// Search for last assignment to a0 and if possible use ret_val slot of POP to
+// store return value.
+bool RISCVPushPopOpt::adjustRetVal(MachineBasicBlock::iterator &MBBI) {
+ MachineBasicBlock::reverse_iterator RE = MBBI->getParent()->rend();
+ // Track which register units have been modified and used between the POP
+ // insn and the last assignment to register a0.
+ ModifiedRegUnits.clear();
+ UsedRegUnits.clear();
+ // Since POP instruction is in Epilogue no normal instructions will follow
+ // after it. Therefore search only previous ones to find the return value.
+ for (MachineBasicBlock::reverse_iterator I =
+ next_nodbg(MBBI.getReverse(), RE);
+ I != RE; I = next_nodbg(I, RE)) {
+ MachineInstr &MI = *I;
+ if (auto OperandPair = TII->isCopyInstrImpl(MI)) {
+ Register DestReg = OperandPair->Destination->getReg();
+ Register Source = OperandPair->Source->getReg();
+ if (DestReg == RISCV::X10 && Source == RISCV::X0) {
+ MI.removeFromParent();
+ return true;
+ }
+ }
+ // Update modified / used register units.
+ LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
+ // If a0 was modified or used, there is no possibility
+ // of using ret_val slot of POP instruction.
+ if (!ModifiedRegUnits.available(RISCV::X10) ||
+ !UsedRegUnits.available(RISCV::X10))
+ return false;
+ }
+ return false;
+}
+
+bool RISCVPushPopOpt::runOnMachineFunction(MachineFunction &Fn) {
+ if (skipFunction(Fn.getFunction()))
+ return false;
+
+ // If Zcmp extension is not supported, abort.
+ const RISCVSubtarget *Subtarget = &Fn.getSubtarget<RISCVSubtarget>();
+ if (!Subtarget->hasStdExtZcmp())
+ return false;
+
+ // If frame pointer elimination has been disabled, abort to avoid breaking the
+ // ABI.
+ if (Fn.getTarget().Options.DisableFramePointerElim(Fn))
+ return false;
+
+ TII = static_cast<const RISCVInstrInfo *>(Subtarget->getInstrInfo());
+ TRI = Subtarget->getRegisterInfo();
+ // Resize the modified and used register unit trackers. We do this once
+ // per function and then clear the register units each time we determine
+ // correct return value for the POP.
+ ModifiedRegUnits.init(*TRI);
+ UsedRegUnits.init(*TRI);
+ bool Modified = false;
+ for (auto &MBB : Fn) {
+ MachineBasicBlock::iterator MBBI = containsPop(MBB);
+ MachineBasicBlock::iterator NextI = next_nodbg(MBBI, MBB.end());
+ if (MBBI != MBB.end() && NextI->getOpcode() == RISCV::PseudoRET)
+ Modified |= usePopRet(MBBI, NextI, adjustRetVal(MBBI));
+ }
+ return Modified;
+}
+
+/// createRISCVPushPopOptimizationPass - returns an instance of the
+/// Push/Pop optimization pass.
+FunctionPass *llvm::createRISCVPushPopOptimizationPass() {
+ return new RISCVPushPopOpt();
+}
diff --git a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
index 93e66b65f0dcba..59dac5c7b57d8c 100644
--- a/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
+++ b/llvm/lib/Target/RISCV/RISCVTargetMachine.cpp
@@ -89,6 +89,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVTarget() {
initializeRISCVDAGToDAGISelPass(*PR);
initializeRISCVInitUndefPass(*PR);
initializeRISCVMoveMergePass(*PR);
+ initializeRISCVPushPopOptPass(*PR);
}
static StringRef computeDataLayout(const Triple &TT) {
@@ -353,8 +354,12 @@ void RISCVPassConfig::addPreEmitPass() {
}
void RISCVPassConfig::addPreEmitPass2() {
- if (TM->getOptLevel() != CodeGenOpt::None)
+ if (TM->getOptLevel() != CodeGenOpt::None) {
addPass(createRISCVMoveMergePass());
+ // Schedule PushPop Optimization before expansion of Pseudo instruction,
+ // ensuring return instruction is detected correctly.
+ addPass(createRISCVPushPopOptimizationPass());
+ }
addPass(createRISCVExpandPseudoPass());
// Schedule the expansion of AMOs at the last possible moment, avoiding the
diff --git a/llvm/test/CodeGen/RISCV/O3-pipeline.ll b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
index 33da32f7cef6a4..a9636cdf8bb17f 100644
--- a/llvm/test/CodeGen/RISCV/O3-pipeline.ll
+++ b/llvm/test/CodeGen/RISCV/O3-pipeline.ll
@@ -179,6 +179,7 @@
; CHECK-NEXT: Machine Optimization Remark Emitter
; CHECK-NEXT: Stack Frame Layout Analysis
; CHECK-NEXT: RISC-V Zcmp move merging pass
+; CHECK-NEXT: RISC-V Zcmp Push/Pop optimization pass
; CHECK-NEXT: RISC-V pseudo instruction expansion pass
; CHECK-NEXT: RISC-V atomic pseudo instruction expansion pass
; CHECK-NEXT: Unpack machine instruction bundles
diff --git a/llvm/test/CodeGen/RISCV/callee-saved-gprs.ll b/llvm/test/CodeGen/RISCV/callee-saved-gprs.ll
index c240469cc686de..ab1af17a4bf8e0 100644
--- a/llvm/test/CodeGen/RISCV/callee-saved-gprs.ll
+++ b/llvm/test/CodeGen/RISCV/callee-saved-gprs.ll
@@ -338,8 +338,7 @@ define void @callee() nounwind {
; RV32IZCMP-NEXT: sw a0, %lo(var+4)(a7)
; RV32IZCMP-NEXT: lw a0, 28(sp) # 4-byte Folded Reload
; RV32IZCMP-NEXT: sw a0, %lo(var)(a7)
-; RV32IZCMP-NEXT: cm.pop {ra, s0-s11}, 96
-; RV32IZCMP-NEXT: ret
+; RV32IZCMP-NEXT: cm.popret {ra, s0-s11}, 96
;
; RV32IZCMP-WITH-FP-LABEL: callee:
; RV32IZCMP-WITH-FP: # %bb.0:
@@ -758,8 +757,7 @@ define void @callee() nounwind {
; RV64IZCMP-NEXT: sw a0, %lo(var+4)(a7)
; RV64IZCMP-NEXT: ld a0, 40(sp) # 8-byte Folded Reload
; RV64IZCMP-NEXT: sw a0, %lo(var)(a7)
-; RV64IZCMP-NEXT: cm.pop {ra, s0-s11}, 160
-; RV64IZCMP-NEXT: ret
+; RV64IZCMP-NEXT: cm.popret {ra, s0-s11}, 160
;
; RV64IZCMP-WITH-FP-LABEL: callee:
; RV64IZCMP-WITH-FP: # %bb.0:
@@ -1287,8 +1285,7 @@ define void @caller() nounwind {
; RV32IZCMP-NEXT: lw a0, 92(sp) # 4-byte Folded Reload
; RV32IZCMP-NEXT: sw a0, %lo(var)(s0)
; RV32IZCMP-NEXT: addi sp, sp, 48
-; RV32IZCMP-NEXT: cm.pop {ra, s0-s11}, 112
-; RV32IZCMP-NEXT: ret
+; RV32IZCMP-NEXT: cm.popret {ra, s0-s11}, 112
;
; RV32IZCMP-WITH-FP-LABEL: caller:
; RV32IZCMP-WITH-FP: # %bb.0:
@@ -1841,8 +1838,7 @@ define void @caller() nounwind {
; RV64IZCMP-NEXT: ld a0, 168(sp) # 8-byte Folded Reload
; RV64IZCMP-NEXT: sw a0, %lo(var)(s0)
; RV64IZCMP-NEXT: addi sp, sp, 128
-; RV64IZCMP-NEXT: cm.pop {ra, s0-s11}, 160
-; RV64IZCMP-NEXT: ret
+; RV64IZCMP-NEXT: cm.popret {ra, s0-s11}, 160
;
; RV64IZCMP-WITH-FP-LABEL: caller:
; RV64IZCMP-WITH-FP: # %bb.0:
diff --git a/llvm/test/CodeGen/RISCV/cm_mvas_mvsa.ll b/llvm/test/CodeGen/RISCV/cm_mvas_mvsa.ll
index 7171277fbfd416..7992c2cda28d5b 100644
--- a/llvm/test/CodeGen/RISCV/cm_mvas_mvsa.ll
+++ b/llvm/test/CodeGen/RISCV/cm_mvas_mvsa.ll
@@ -43,8 +43,7 @@ define i32 @zcmp_mv(i32 %num, i32 %f) nounwind {
; CHECK32ZCMP-NEXT: cm.mva01s s1, s0
; CHECK32ZCMP-NEXT: call func at plt
; CHECK32ZCMP-NEXT: add a0, s2, s0
-; CHECK32ZCMP-NEXT: cm.pop {ra, s0-s2}, 16
-; CHECK32ZCMP-NEXT: ret
+; CHECK32ZCMP-NEXT: cm.popret {ra, s0-s2}, 16
;
; CHECK64I-LABEL: zcmp_mv:
; CHECK64I: # %bb.0:
@@ -77,8 +76,7 @@ define i32 @zcmp_mv(i32 %num, i32 %f) nounwind {
; CHECK64ZCMP-NEXT: cm.mva01s s1, s0
; CHECK64ZCMP-NEXT: call func at plt
; CHECK64ZCMP-NEXT: addw a0, s2, s0
-; CHECK64ZCMP-NEXT: cm.pop {ra, s0-s2}, 32
-; CHECK64ZCMP-NEXT: ret
+; CHECK64ZCMP-NEXT: cm.popret {ra, s0-s2}, 32
%call = call i32 @func(i32 %num, i32 %f)
%call1 = call i32 @func(i32 %num, i32 %f)
%res = add i32 %call, %f
@@ -121,8 +119,7 @@ define i32 @not_zcmp_mv(i32 %num, i32 %f) nounwind {
; CHECK32ZCMP-NEXT: li a0, 1
; CHECK32ZCMP-NEXT: mv a1, s0
; CHECK32ZCMP-NEXT: call func at plt
-; CHECK32ZCMP-NEXT: cm.pop {ra, s0-s1}, 16
-; CHECK32ZCMP-NEXT: ret
+; CHECK32ZCMP-NEXT: cm.popret {ra, s0-s1}, 16
;
; CHECK64I-LABEL: not_zcmp_mv:
; CHECK64I: # %bb.0:
@@ -159,8 +156,7 @@ define i32 @not_zcmp_mv(i32 %num, i32 %f) nounwind {
; CHECK64ZCMP-NEXT: li a0, 1
; CHECK64ZCMP-NEXT: mv a1, s0
; CHECK64ZCMP-NEXT: call func at plt
-; CHECK64ZCMP-NEXT: cm.pop {ra, s0-s1}, 32
-; CHECK64ZCMP-NEXT: ret
+; CHECK64ZCMP-NEXT: cm.popret {ra, s0-s1}, 32
%call = call i32 @foo(i32 %num)
%call1 = call i32 @foo(i32 %f)
%tmp = call i32 @foo(i32 %call)
diff --git a/llvm/test/CodeGen/RISCV/push-pop-popret.ll b/llvm/test/CodeGen/RISCV/push-pop-popret.ll
index c0e46fc7649b5c..2b50cbbaded7b3 100644
--- a/llvm/test/CodeGen/RISCV/push-pop-popret.ll
+++ b/llvm/test/CodeGen/RISCV/push-pop-popret.ll
@@ -25,10 +25,8 @@ define i32 @foo() {
; RV32IZCMP-NEXT: .cfi_offset ra, -4
; RV32IZCMP-NEXT: mv a0, sp
; RV32IZCMP-NEXT: call test at plt
-; RV32IZCMP-NEXT: li a0, 0
; RV32IZCMP-NEXT: addi sp, sp, 464
-; RV32IZCMP-NEXT: cm.pop {ra}, 64
-; RV32IZCMP-NEXT: ret
+; RV32IZCMP-NEXT: cm.popretz {ra}, 64
;
; RV64IZCMP-LABEL: foo:
; RV64IZCMP: # %bb.0:
@@ -38,10 +36,8 @@ define i32 @foo() {
; RV64IZCMP-NEXT: .cfi_offset ra, -8
; RV64IZCMP-NEXT: mv a0, sp
; RV64IZCMP-NEXT: call test at plt
-; RV64IZCMP-NEXT: li a0, 0
; RV64IZCMP-NEXT: addi sp, sp, 464
-; RV64IZCMP-NEXT: cm.pop {ra}, 64
-; RV64IZCMP-NEXT: ret
+; RV64IZCMP-NEXT: cm.popretz {ra}, 64
;
; RV32IZCMP-SR-LABEL: foo:
; RV32IZCMP-SR: # %bb.0:
@@ -112,10 +108,8 @@ define i32 @pushpopret0(i32 signext %size){
; RV32IZCMP-NEXT: sub a0, sp, a0
; RV32IZCMP-NEXT: mv sp, a0
; RV32IZCMP-NEXT: call callee_void at plt
-; RV32IZCMP-NEXT: li a0, 0
; RV32IZCMP-NEXT: addi sp, s0, -16
-; RV32IZCMP-NEXT: cm.pop {ra, s0}, 16
-; RV32IZCMP-NEXT: ret
+; RV32IZCMP-NEXT: cm.popretz {ra, s0}, 16
;
; RV64IZCMP-LABEL: pushpopret0:
; RV64IZCMP: # %bb.0: # %entry
@@ -132,10 +126,8 @@ define i32 @pushpopret0(i32 signext %size){
; RV64IZCMP-NEXT: sub a0, sp, a0
; RV64IZCMP-NEXT: mv sp, a0
; RV64IZCMP-NEXT: call callee_void at plt
-; RV64IZCMP-NEXT: li a0, 0
; RV64IZCMP-NEXT: addi sp, s0, -16
-; RV64IZCMP-NEXT: cm.pop {ra, s0}, 16
-; RV64IZCMP-NEXT: ret
+; RV64IZCMP-NEXT: cm.popretz {ra, s0}, 16
;
; RV32IZCMP-SR-LABEL: pushpopret0:
; RV32IZCMP-SR: # %bb.0: # %entry
@@ -240,8 +232,7 @@ define i32 @pushpopret1(i32 signext %size) {
; RV32IZCMP-NEXT: call callee_void at plt
; RV32IZCMP-NEXT: li a0, 1
; RV32IZCMP-NEXT: addi sp, s0, -16
-; RV32IZCMP-NEXT: cm.pop {ra, s0}, 16
-; RV32IZCMP-NEXT: ret
+; RV32IZCMP-NEXT: cm.popret {ra, s0}, 16
;
; RV64IZCMP-LABEL: pushpopret1:
; RV64IZCMP: # %bb.0: # %entry
@@ -260,8 +251,7 @@ define i32 @pushpopret1(i32 signext %size) {
; RV64IZCMP-NEXT: call callee_void at plt
; RV64IZCMP-NEXT: li a0, 1
; RV64IZCMP-NEXT: addi sp, s0, -16
-; RV64IZCMP-NEXT: cm.pop {ra, s0}, 16
-; RV64IZCMP-NEXT: ret
+; RV64IZCMP-NEXT: cm.popret {ra, s0}, 16
;
; RV32IZCMP-SR-LABEL: pushpopret1:
; RV32IZCMP-SR: # %bb.0: # %entry
@@ -366,8 +356,7 @@ define i32 @pushpopretneg1(i32 signext %size) {
; RV32IZCMP-NEXT: call callee_void at plt
; RV32IZCMP-NEXT: li a0, -1
; RV32IZCMP-NEXT: addi sp, s0, -16
-; RV32IZCMP-NEXT: cm.pop {ra, s0}, 16
-; RV32IZCMP-NEXT: ret
+; RV32IZCMP-NEXT: cm.popret {ra, s0}, 16
;
; RV64IZCMP-LABEL: pushpopretneg1:
; RV64IZCMP: # %bb.0: # %entry
@@ -386,8 +375,7 @@ define i32 @pushpopretneg1(i32 signext %size) {
; RV64IZCMP-NEXT: call callee_void at plt
; RV64IZCMP-NEXT: li a0, -1
; RV64IZCMP-NEXT: addi sp, s0, -16
-; RV64IZCMP-NEXT: cm.pop {ra, s0}, 16
-; RV64IZCMP-NEXT: ret
+; RV64IZCMP-NEXT: cm.popret {ra, s0}, 16
;
; RV32IZCMP-SR-LABEL: pushpopretneg1:
; RV32IZCMP-SR: # %bb.0: # %entry
@@ -492,8 +480,7 @@ define i32 @pushpopret2(i32 signext %size) {
; RV32IZCMP-NEXT: call callee_void at plt
; RV32IZCMP-NEXT: li a0, 2
; RV32IZCMP-NEXT: addi sp, s0, -16
-; RV32IZCMP-NEXT: cm.pop {ra, s0}, 16
-; RV32IZCMP-NEXT: ret
+; RV32IZCMP-NEXT: cm.popret {ra, s0}, 16
;
; RV64IZCMP-LABEL: pushpopret2:
; RV64IZCMP: # %bb.0: # %entry
@@ -512,8 +499,7 @@ define i32 @pushpopret2(i32 signext %size) {
; RV64IZCMP-NEXT: call callee_void at plt
; RV64IZCMP-NEXT: li a0, 2
; RV64IZCMP-NEXT: addi sp, s0, -16
-; RV64IZCMP-NEXT: cm.pop {ra, s0}, 16
-; RV64IZCMP-NEXT: ret
+; RV64IZCMP-NEXT: cm.popret {ra, s0}, 16
;
; RV32IZCMP-SR-LABEL: pushpopret2:
; RV32IZCMP-SR: # %bb.0: # %entry
@@ -1187,8 +1173,7 @@ define void @many_args(i32, i32, i32, i32, i32, i32, i32, i32, i32) nounwind {
; RV32IZCMP-NEXT: sw t0, %lo(var0+8)(a0)
; RV32IZCMP-NEXT: sw a7, %lo(var0+4)(a0)
; RV32IZCMP-NEXT: sw a6, %lo(var0)(a0)
-; RV32IZCMP-NEXT: cm.pop {ra, s0-s4}, 32
-; RV32IZCMP-NEXT: ret
+; RV32IZCMP-NEXT: cm.popret {ra, s0-s4}, 32
;
; RV64IZCMP-LABEL: many_args:
; RV64IZCMP: # %bb.0: # %entry
@@ -1231,8 +1216,7 @@ define void @many_args(i32, i32, i32, i32, i32, i32, i32, i32, i32) nounwind {
; RV64IZCMP-NEXT: sw t0, %lo(var0+8)(a0)
; RV64IZCMP-NEXT: sw a7, %lo(var0+4)(a0)
; RV64IZCMP-NEXT: sw a6, %lo(var0)(a0)
-; RV64IZCMP-NEXT: cm.pop {ra, s0-s4}, 48
-; RV64IZCMP-NEXT: ret
+; RV64IZCMP-NEXT: cm.popret {ra, s0-s4}, 48
;
; RV32IZCMP-SR-LABEL: many_args:
; RV32IZCMP-SR: # %bb.0: # %entry
@@ -1452,8 +1436,7 @@ define void @alloca(i32 %n) nounwind {
; RV32IZCMP-NEXT: call notdead at plt
; RV32IZCMP-NEXT: mv sp, s1
; RV32IZCMP-NEXT: addi sp, s0, -16
-; RV32IZCMP-NEXT: cm.pop {ra, s0-s1}, 16
-; RV32IZCMP-NEXT: ret
+; RV32IZCMP-NEXT: cm.popret {ra, s0-s1}, 16
;
; RV64IZCMP-LABEL: alloca:
; RV64IZCMP: # %bb.0:
@@ -1469,8 +1452,7 @@ define void @alloca(i32 %n) nounwind {
; RV64IZCMP-NEXT: call notdead at plt
; RV64IZCMP-NEXT: mv sp, s1
; RV64IZCMP-NEXT: addi sp, s0, -32
-; RV64IZCMP-NEXT: cm.pop {ra, s0-s1}, 32
-; RV64IZCMP-NEXT: ret
+; RV64IZCMP-NEXT: cm.popret {ra, s0-s1}, 32
;
; RV32IZCMP-SR-LABEL: alloca:
; RV32IZCMP-SR: # %bb.0:
@@ -1793,6 +1775,52 @@ define void @foo_with_irq() nounwind "interrupt"="user" {
ret void
}
+define void @foo_no_irq() nounwind{
+; RV32IZCMP-LABEL: foo_no_irq:
+; RV32IZCMP: # %bb.0:
+; RV32IZCMP-NEXT: cm.push {ra}, -16
+; RV32IZCMP-NEXT: call foo_test_irq at plt
+; RV32IZCMP-NEXT: cm.popret {ra}, 16
+;
+; RV64IZCMP-LABEL: foo_no_irq:
+; RV64IZCMP: # %bb.0:
+; RV64IZCMP-NEXT: cm.push {ra}, -16
+; RV64IZCMP-NEXT: call foo_test_irq at plt
+; RV64IZCMP-NEXT: cm.popret {ra}, 16
+;
+; RV32IZCMP-SR-LABEL: foo_no_irq:
+; RV32IZCMP-SR: # %bb.0:
+; RV32IZCMP-SR-NEXT: call t0, __riscv_save_0
+; RV32IZCMP-SR-NEXT: call foo_test_irq at plt
+; RV32IZCMP-SR-NEXT: tail __riscv_restore_0
+;
+; RV64IZCMP-SR-LABEL: foo_no_irq:
+; RV64IZCMP-SR: # %bb.0:
+; RV64IZCMP-SR-NEXT: call t0, __riscv_save_0
+; RV64IZCMP-SR-NEXT: call foo_test_irq at plt
+; RV64IZCMP-SR-NEXT: tail __riscv_restore_0
+;
+; RV32I-LABEL: foo_no_irq:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: call foo_test_irq at plt
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV64I-LABEL: foo_no_irq:
+; RV64I: # %bb.0:
+; RV64I-NEXT: addi sp, sp, -16
+; RV64I-NEXT: sd ra, 8(sp) # 8-byte Folded Spill
+; RV64I-NEXT: call foo_test_irq at plt
+; RV64I-NEXT: ld ra, 8(sp) # 8-byte Folded Reload
+; RV64I-NEXT: addi sp, sp, 16
+; RV64I-NEXT: ret
+ %call = call i32 bitcast (i32 (...)* @foo_test_irq to i32 ()*)()
+ ret void
+}
+
define void @callee_with_irq() nounwind "interrupt"="user" {
; RV32IZCMP-LABEL: callee_with_irq:
; RV32IZCMP: # %bb.0:
@@ -2624,8 +2652,7 @@ define void @callee_no_irq() nounwind{
; RV32IZCMP-NEXT: sw a0, %lo(var_test_irq+4)(a7)
; RV32IZCMP-NEXT: lw a0, 28(sp) # 4-byte Folded Reload
; RV32IZCMP-NEXT: sw a0, %lo(var_test_irq)(a7)
-; RV32IZCMP-NEXT: cm.pop {ra, s0-s11}, 96
-; RV32IZCMP-NEXT: ret
+; RV32IZCMP-NEXT: cm.popret {ra, s0-s11}, 96
;
; RV64IZCMP-LABEL: callee_no_irq:
; RV64IZCMP: # %bb.0:
@@ -2708,8 +2735,7 @@ define void @callee_no_irq() nounwind{
; RV64IZCMP-NEXT: sw a0, %lo(var_test_irq+4)(a7)
; RV64IZCMP-NEXT: ld a0, 40(sp) # 8-byte Folded Reload
; RV64IZCMP-NEXT: sw a0, %lo(var_test_irq)(a7)
-; RV64IZCMP-NEXT: cm.pop {ra, s0-s11}, 160
-; RV64IZCMP-NEXT: ret
+; RV64IZCMP-NEXT: cm.popret {ra, s0-s11}, 160
;
; RV32IZCMP-SR-LABEL: callee_no_irq:
; RV32IZCMP-SR: # %bb.0:
More information about the llvm-commits
mailing list