[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