LLVM 24.0.0git
RISCVPostRAExpandPseudoInsts.cpp
Go to the documentation of this file.
1//===-- RISCVPostRAExpandPseudoInsts.cpp - Expand pseudo instrs ----===//
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 expands the pseudo instruction pseudolisimm32
10// into target instructions. This pass should be run during the post-regalloc
11// passes, before post RA scheduling.
12//
13//===----------------------------------------------------------------------===//
14
15#include "RISCV.h"
16#include "RISCVInstrInfo.h"
19
20using namespace llvm;
21
22#define RISCV_POST_RA_EXPAND_PSEUDO_NAME \
23 "RISC-V post-regalloc pseudo instruction expansion pass"
24
25namespace {
26
27class RISCVPostRAExpandPseudo : public MachineFunctionPass {
28public:
29 const RISCVInstrInfo *TII;
30 static char ID;
31
32 RISCVPostRAExpandPseudo() : MachineFunctionPass(ID) {}
33
34 bool runOnMachineFunction(MachineFunction &MF) override;
35
36 StringRef getPassName() const override {
38 }
39
40private:
41 bool expandMBB(MachineBasicBlock &MBB);
47 bool expandAddUpperImm(MachineBasicBlock &MBB,
49};
50
51char RISCVPostRAExpandPseudo::ID = 0;
52
53bool RISCVPostRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
54 TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo());
55 bool Modified = false;
56 for (auto &MBB : MF)
57 Modified |= expandMBB(MBB);
58 return Modified;
59}
60
61bool RISCVPostRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
62 bool Modified = false;
63
64 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
65 while (MBBI != E) {
66 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
67 Modified |= expandMI(MBB, MBBI, NMBBI);
68 MBBI = NMBBI;
69 }
70
71 return Modified;
72}
73
74bool RISCVPostRAExpandPseudo::expandMI(MachineBasicBlock &MBB,
77 switch (MBBI->getOpcode()) {
78 case RISCV::PseudoMovImm:
79 return expandMovImm(MBB, MBBI);
80 case RISCV::PseudoMovAddr:
81 return expandMovAddr(MBB, MBBI);
82 case RISCV::PseudoAddUpperImm:
83 return expandAddUpperImm(MBB, MBBI);
84 case RISCV::PseudoMERGE:
85 return expandMERGE(MBB, MBBI);
86 default:
87 return false;
88 }
89}
90
91bool RISCVPostRAExpandPseudo::expandMovImm(MachineBasicBlock &MBB,
93 DebugLoc DL = MBBI->getDebugLoc();
94
95 int64_t Val = MBBI->getOperand(1).getImm();
96
97 Register DstReg = MBBI->getOperand(0).getReg();
98 bool DstIsDead = MBBI->getOperand(0).isDead();
99 bool Renamable = MBBI->getOperand(0).isRenamable();
100
101 TII->movImm(MBB, MBBI, DL, DstReg, Val, MachineInstr::NoFlags, Renamable,
102 DstIsDead);
103
104 MBBI->eraseFromParent();
105 return true;
106}
107
108bool RISCVPostRAExpandPseudo::expandMovAddr(MachineBasicBlock &MBB,
110 DebugLoc DL = MBBI->getDebugLoc();
111
112 Register DstReg = MBBI->getOperand(0).getReg();
113 bool DstIsDead = MBBI->getOperand(0).isDead();
114 bool Renamable = MBBI->getOperand(0).isRenamable();
115
116 BuildMI(MBB, MBBI, DL, TII->get(RISCV::LUI))
118 .add(MBBI->getOperand(1));
119 BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI))
120 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead) |
123 .add(MBBI->getOperand(2));
124 MBBI->eraseFromParent();
125 return true;
126}
127
128bool RISCVPostRAExpandPseudo::expandAddUpperImm(
130 DebugLoc DL = MBBI->getDebugLoc();
131
132 Register DstReg = MBBI->getOperand(0).getReg();
133 bool DstIsDead = MBBI->getOperand(0).isDead();
134 bool Renamable = MBBI->getOperand(0).isRenamable();
135 Register BaseReg = MBBI->getOperand(1).getReg();
136 int64_t Hi = MBBI->getOperand(2).getImm();
137
138 // Expand to LUI+ADD: the immediate is already the upper 20-bit value.
139 BuildMI(MBB, MBBI, DL, TII->get(RISCV::LUI))
141 .addImm(Hi);
142 BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADD))
143 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead) |
145 .addReg(BaseReg)
147
148 MBBI->eraseFromParent();
149 return true;
150}
151
152/// Transfer implicit operands on the pseudo instruction to the
153/// instructions created from the expansion.
154static void transferImpOps(MachineInstr &OldMI, MachineInstrBuilder &MI) {
155 const MCInstrDesc &Desc = OldMI.getDesc();
156 for (const MachineOperand &MO :
157 llvm::drop_begin(OldMI.operands(), Desc.getNumOperands())) {
158 assert(MO.isReg() && MO.getReg());
159 MI.add(MO);
160 }
161}
162
163// Expand PseudoMERGE to MERGE, MVM, or MVMN.
164bool RISCVPostRAExpandPseudo::expandMERGE(MachineBasicBlock &MBB,
166 MachineInstr &MI = *MBBI;
167 DebugLoc DL = MI.getDebugLoc();
168
169 Register DstReg = MI.getOperand(0).getReg();
170 if (DstReg == MI.getOperand(3).getReg()) {
171 // Expand to MVMN
172 auto I = BuildMI(MBB, MBBI, DL, TII->get(RISCV::MVMN))
173 .add(MI.getOperand(0))
174 .add(MI.getOperand(3))
175 .add(MI.getOperand(2))
176 .add(MI.getOperand(1));
177 transferImpOps(*MBBI, I);
178 } else if (DstReg == MBBI->getOperand(2).getReg()) {
179 // Expand to MVM
180 auto I = BuildMI(MBB, MBBI, DL, TII->get(RISCV::MVM))
181 .add(MI.getOperand(0))
182 .add(MI.getOperand(2))
183 .add(MI.getOperand(3))
184 .add(MI.getOperand(1));
185 transferImpOps(*MBBI, I);
186 } else if (DstReg == MI.getOperand(1).getReg()) {
187 // Expand to MERGE
188 auto I = BuildMI(MBB, MBBI, DL, TII->get(RISCV::MERGE))
189 .add(MI.getOperand(0))
190 .add(MI.getOperand(1))
191 .add(MI.getOperand(2))
192 .add(MI.getOperand(3));
193 transferImpOps(*MBBI, I);
194 } else {
195 // Use an additional move.
197 getRenamableRegState(MI.getOperand(1).isRenamable()) |
198 getKillRegState(MI.getOperand(1).isKill() &&
199 MI.getOperand(1).getReg() !=
200 MI.getOperand(2).getReg() &&
201 MI.getOperand(1).getReg() != MI.getOperand(3).getReg());
202 BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(RISCV::ADDI))
203 .addDef(DstReg, getRenamableRegState(MI.getOperand(0).isRenamable()))
204 .addReg(MI.getOperand(1).getReg(), RegState)
205 .addImm(0);
206 auto I = BuildMI(MBB, MBBI, MI.getDebugLoc(), TII->get(RISCV::MERGE))
207 .add(MI.getOperand(0))
208 .addReg(DstReg,
210 MI.getOperand(0).isRenamable()))
211 .add(MI.getOperand(2))
212 .add(MI.getOperand(3));
213 transferImpOps(*MBBI, I);
214 }
215 MI.eraseFromParent();
216 return true;
217}
218
219} // end of anonymous namespace
220
221INITIALIZE_PASS(RISCVPostRAExpandPseudo, "riscv-post-ra-expand-pseudo",
223namespace llvm {
224
226 return new RISCVPostRAExpandPseudo();
227}
228
229} // end of namespace llvm
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
#define RISCV_POST_RA_EXPAND_PSEUDO_NAME
A debug info location.
Definition DebugLoc.h:126
FunctionPass class - This class is used to implement most global optimizations.
Definition Pass.h:314
Describe properties that are true of each instruction in the target description file.
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.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addDef(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a virtual register definition operand.
Representation of each machine instruction.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
mop_range operands()
MachineOperand class - Representation of each machine instruction operand.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
RegState
Flags to represent properties of register accesses.
@ Kill
The last use of a register.
@ Define
Register definition.
@ Renamable
Register that may be renamed.
constexpr RegState getKillRegState(bool B)
FunctionPass * createRISCVPostRAExpandPseudoPass()
constexpr RegState getDeadRegState(bool B)
Op::Description Desc
constexpr RegState getRenamableRegState(bool B)