Thanks to visit codestin.com
Credit goes to llvm.org

LLVM 22.0.0git
RISCVPushPopOptimizer.cpp
Go to the documentation of this file.
1//===------- RISCVPushPopOptimizer.cpp - RISC-V Push/Pop opt. pass --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a pass that replaces Zcmp POP instructions with
10// POPRET[Z] where possible.
11//
12//===----------------------------------------------------------------------===//
13
14#include "RISCVInstrInfo.h"
17
18using namespace llvm;
19
20#define RISCV_PUSH_POP_OPT_NAME "RISC-V Zcmp Push/Pop optimization pass"
21
22namespace {
23struct RISCVPushPopOpt : public MachineFunctionPass {
24 static char ID;
25
26 RISCVPushPopOpt() : MachineFunctionPass(ID) {}
27
28 const RISCVInstrInfo *TII;
30
31 // Track which register units have been modified and used.
32 LiveRegUnits ModifiedRegUnits, UsedRegUnits;
33
34 bool usePopRet(MachineBasicBlock::iterator &MBBI,
35 MachineBasicBlock::iterator &NextI, bool IsReturnZero);
36 bool adjustRetVal(MachineBasicBlock::iterator &MBBI);
37 bool runOnMachineFunction(MachineFunction &Fn) override;
38
39 StringRef getPassName() const override { return RISCV_PUSH_POP_OPT_NAME; }
40};
41
42char RISCVPushPopOpt::ID = 0;
43
44} // end of anonymous namespace
45
46INITIALIZE_PASS(RISCVPushPopOpt, "riscv-push-pop-opt", RISCV_PUSH_POP_OPT_NAME,
47 false, false)
48
49static bool isPop(unsigned Opcode) {
50 switch (Opcode) {
51 case RISCV::CM_POP:
52 case RISCV::QC_CM_POP:
53 return true;
54 default:
55 return false;
56 }
57}
58
59static unsigned getPopRetOpcode(unsigned PopOpcode, bool IsReturnZero) {
60 assert(isPop(PopOpcode) && "Unexpected Pop Opcode");
61
62 switch (PopOpcode) {
63 case RISCV::CM_POP:
64 return IsReturnZero ? RISCV::CM_POPRETZ : RISCV::CM_POPRET;
65 case RISCV::QC_CM_POP:
66 return IsReturnZero ? RISCV::QC_CM_POPRETZ : RISCV::QC_CM_POPRET;
67 default:
68 llvm_unreachable("Unhandled Pop Opcode");
69 }
70}
71
72bool RISCVPushPopOpt::usePopRet(MachineBasicBlock::iterator &MBBI,
74 bool IsReturnZero) {
75 // Since Pseudo instruction lowering happen later in the pipeline,
76 // this will detect all ret instruction.
77 DebugLoc DL = NextI->getDebugLoc();
78 unsigned Opc = getPopRetOpcode(MBBI->getOpcode(), IsReturnZero);
79 MachineInstrBuilder PopRetBuilder =
80 BuildMI(*NextI->getParent(), NextI, DL, TII->get(Opc))
81 .add(MBBI->getOperand(0))
82 .add(MBBI->getOperand(1))
84
85 // Copy over the variable implicit uses and defs from the CM_POP. They depend
86 // on what register list has been picked during frame lowering.
87 const MCInstrDesc &PopDesc = MBBI->getDesc();
88 unsigned FirstNonDeclaredOp = PopDesc.getNumOperands() +
89 PopDesc.NumImplicitUses +
90 PopDesc.NumImplicitDefs;
91 for (unsigned i = FirstNonDeclaredOp; i < MBBI->getNumOperands(); ++i)
92 PopRetBuilder.add(MBBI->getOperand(i));
93
95 NextI->eraseFromParent();
96 return true;
97}
98
99// Search for last assignment to a0 and if possible use ret_val slot of POP to
100// store return value.
101bool RISCVPushPopOpt::adjustRetVal(MachineBasicBlock::iterator &MBBI) {
103 // Track which register units have been modified and used between the POP
104 // insn and the last assignment to register a0.
105 ModifiedRegUnits.clear();
106 UsedRegUnits.clear();
107 // Since POP instruction is in Epilogue no normal instructions will follow
108 // after it. Therefore search only previous ones to find the return value.
110 next_nodbg(MBBI.getReverse(), RE);
111 I != RE; I = next_nodbg(I, RE)) {
112 MachineInstr &MI = *I;
113 if (auto OperandPair = TII->isCopyInstrImpl(MI)) {
114 Register DestReg = OperandPair->Destination->getReg();
115 Register Source = OperandPair->Source->getReg();
116 if (DestReg == RISCV::X10 && Source == RISCV::X0) {
117 MI.removeFromParent();
118 return true;
119 }
120 }
121 // Update modified / used register units.
122 LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
123 // If a0 was modified or used, there is no possibility
124 // of using ret_val slot of POP instruction.
125 if (!ModifiedRegUnits.available(RISCV::X10) ||
126 !UsedRegUnits.available(RISCV::X10))
127 return false;
128 }
129 return false;
130}
131
132bool RISCVPushPopOpt::runOnMachineFunction(MachineFunction &Fn) {
133 if (skipFunction(Fn.getFunction()))
134 return false;
135
136 // If Zcmp extension is not supported, abort.
137 const RISCVSubtarget *Subtarget = &Fn.getSubtarget<RISCVSubtarget>();
138 if (!Subtarget->hasStdExtZcmp() && !Subtarget->hasVendorXqccmp())
139 return false;
140
141 TII = Subtarget->getInstrInfo();
142 TRI = Subtarget->getRegisterInfo();
143
144 // Resize the modified and used register unit trackers. We do this once
145 // per function and then clear the register units each time we determine
146 // correct return value for the POP.
147 ModifiedRegUnits.init(*TRI);
148 UsedRegUnits.init(*TRI);
149
150 bool Modified = false;
151 for (auto &MBB : Fn) {
152 // RET should be the only terminator.
153 auto RetMBBI = MBB.getFirstTerminator();
154 if (RetMBBI == MBB.end() || RetMBBI->getOpcode() != RISCV::PseudoRET ||
155 RetMBBI == MBB.begin())
156 continue;
157
158 // The previous instruction should be a POP.
159 auto PopMBBI = prev_nodbg(RetMBBI, MBB.begin());
160 if (isPop(PopMBBI->getOpcode()) &&
161 PopMBBI->getFlag(MachineInstr::FrameDestroy))
162 Modified |= usePopRet(PopMBBI, RetMBBI, adjustRetVal(PopMBBI));
163 }
164
165 return Modified;
166}
167
168/// createRISCVPushPopOptimizationPass - returns an instance of the
169/// Push/Pop optimization pass.
171 return new RISCVPushPopOpt();
172}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:58
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool isPop(unsigned Opcode)
#define RISCV_PUSH_POP_OPT_NAME
static unsigned getPopRetOpcode(unsigned PopOpcode, bool IsReturnZero)
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
A set of register units used to track register liveness.
static void accumulateUsedDefed(const MachineInstr &MI, LiveRegUnits &ModifiedRegUnits, LiveRegUnits &UsedRegUnits, const TargetRegisterInfo *TRI)
For a machine instruction MI, adds all register units used in UsedRegUnits and defined or clobbered i...
bool available(MCRegister Reg) const
Returns true if no part of physical register Reg is live.
void init(const TargetRegisterInfo &TRI)
Initialize and clear the set.
void clear()
Clears the set.
unsigned char NumImplicitUses
unsigned getNumOperands() const
Return the number of declared MachineOperands for this MachineInstruction.
unsigned char NumImplicitDefs
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
MachineInstrBundleIterator< MachineInstr, true > reverse_iterator
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
reverse_iterator rend()
Function & getFunction()
Return the LLVM function that this machine code represents.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & add(const MachineOperand &MO) const
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
This is an optimization pass for GlobalISel generic memory operations.
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
FunctionPass * createRISCVPushPopOptimizationPass()
createRISCVPushPopOptimizationPass - returns an instance of the Push/Pop optimization pass.
IterT prev_nodbg(IterT It, IterT Begin, bool SkipPseudoOp=true)
Decrement It, then continue decrementing it while it points to a debug instruction.