LLVM 18.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"
16
17using namespace llvm;
18
19#define RISCV_PUSH_POP_OPT_NAME "RISC-V Zcmp Push/Pop optimization pass"
20
21namespace {
22struct RISCVPushPopOpt : public MachineFunctionPass {
23 static char ID;
24
25 RISCVPushPopOpt() : MachineFunctionPass(ID) {
27 }
28
29 const RISCVInstrInfo *TII;
31
32 // Track which register units have been modified and used.
33 LiveRegUnits ModifiedRegUnits, UsedRegUnits;
34
35 bool usePopRet(MachineBasicBlock::iterator &MBBI,
36 MachineBasicBlock::iterator &NextI, bool IsReturnZero);
37 bool adjustRetVal(MachineBasicBlock::iterator &MBBI);
38 bool runOnMachineFunction(MachineFunction &Fn) override;
39
40 StringRef getPassName() const override { return RISCV_PUSH_POP_OPT_NAME; }
41};
42
43char RISCVPushPopOpt::ID = 0;
44
45} // end of anonymous namespace
46
47INITIALIZE_PASS(RISCVPushPopOpt, "riscv-push-pop-opt", RISCV_PUSH_POP_OPT_NAME,
48 false, false)
49
50// Check if POP instruction was inserted into the MBB and return iterator to it.
51static MachineBasicBlock::iterator containsPop(MachineBasicBlock &MBB) {
54 if (MBBI->getOpcode() == RISCV::CM_POP)
55 return MBBI;
56
57 return MBB.end();
58}
59
60bool RISCVPushPopOpt::usePopRet(MachineBasicBlock::iterator &MBBI,
62 bool IsReturnZero) {
63 // Since Pseudo instruction lowering happen later in the pipeline,
64 // this will detect all ret instruction.
65 DebugLoc DL = NextI->getDebugLoc();
66 unsigned Opc = IsReturnZero ? RISCV::CM_POPRETZ : RISCV::CM_POPRET;
67 BuildMI(*NextI->getParent(), NextI, DL, TII->get(Opc))
68 .add(MBBI->getOperand(0))
69 .add(MBBI->getOperand(1));
70
72 NextI->eraseFromParent();
73 return true;
74}
75
76// Search for last assignment to a0 and if possible use ret_val slot of POP to
77// store return value.
78bool RISCVPushPopOpt::adjustRetVal(MachineBasicBlock::iterator &MBBI) {
80 // Track which register units have been modified and used between the POP
81 // insn and the last assignment to register a0.
82 ModifiedRegUnits.clear();
83 UsedRegUnits.clear();
84 // Since POP instruction is in Epilogue no normal instructions will follow
85 // after it. Therefore search only previous ones to find the return value.
87 next_nodbg(MBBI.getReverse(), RE);
88 I != RE; I = next_nodbg(I, RE)) {
89 MachineInstr &MI = *I;
90 if (auto OperandPair = TII->isCopyInstrImpl(MI)) {
91 Register DestReg = OperandPair->Destination->getReg();
92 Register Source = OperandPair->Source->getReg();
93 if (DestReg == RISCV::X10 && Source == RISCV::X0) {
94 MI.removeFromParent();
95 return true;
96 }
97 }
98 // Update modified / used register units.
99 LiveRegUnits::accumulateUsedDefed(MI, ModifiedRegUnits, UsedRegUnits, TRI);
100 // If a0 was modified or used, there is no possibility
101 // of using ret_val slot of POP instruction.
102 if (!ModifiedRegUnits.available(RISCV::X10) ||
103 !UsedRegUnits.available(RISCV::X10))
104 return false;
105 }
106 return false;
107}
108
109bool RISCVPushPopOpt::runOnMachineFunction(MachineFunction &Fn) {
110 if (skipFunction(Fn.getFunction()))
111 return false;
112
113 // If Zcmp extension is not supported, abort.
114 const RISCVSubtarget *Subtarget = &Fn.getSubtarget<RISCVSubtarget>();
115 if (!Subtarget->hasStdExtZcmp())
116 return false;
117
118 // If frame pointer elimination has been disabled, abort to avoid breaking the
119 // ABI.
121 return false;
122
123 TII = Subtarget->getInstrInfo();
124 TRI = Subtarget->getRegisterInfo();
125 // Resize the modified and used register unit trackers. We do this once
126 // per function and then clear the register units each time we determine
127 // correct return value for the POP.
128 ModifiedRegUnits.init(*TRI);
129 UsedRegUnits.init(*TRI);
130 bool Modified = false;
131 for (auto &MBB : Fn) {
132 MachineBasicBlock::iterator MBBI = containsPop(MBB);
134 if (MBBI != MBB.end() && NextI != MBB.end() &&
135 NextI->getOpcode() == RISCV::PseudoRET)
136 Modified |= usePopRet(MBBI, NextI, adjustRetVal(MBBI));
137 }
138 return Modified;
139}
140
141/// createRISCVPushPopOptimizationPass - returns an instance of the
142/// Push/Pop optimization pass.
144 return new RISCVPushPopOpt();
145}
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
unsigned const TargetRegisterInfo * TRI
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:38
#define RISCV_PUSH_POP_OPT_NAME
A debug info location.
Definition: DebugLoc.h:33
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
A set of register units used to track register liveness.
Definition: LiveRegUnits.h:30
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...
Definition: LiveRegUnits.h:47
void eraseFromParent()
This method unlinks 'this' from the containing function and deletes it.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
virtual bool runOnMachineFunction(MachineFunction &MF)=0
runOnMachineFunction - This method must be overloaded to perform the desired machine code transformat...
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 LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & add(const MachineOperand &MO) const
Representation of each machine instruction.
Definition: MachineInstr.h:68
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
const RISCVRegisterInfo * getRegisterInfo() const override
const RISCVInstrInfo * getInstrInfo() const override
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
TargetOptions Options
bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
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.
Definition: AddressRanges.h:18
IterT next_nodbg(IterT It, IterT End, bool SkipPseudoOp=true)
Increment It, then continue incrementing it while it points to a debug instruction.
void initializeRISCVPushPopOptPass(PassRegistry &)
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.