1 //===-- RISCVExpandPseudoInsts.cpp - Expand pseudo instructions -----------===//
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 pseudo instructions into target
10 // instructions. This pass should be run after register allocation but before
11 // the post-regalloc scheduling pass.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "RISCV.h"
16 #include "RISCVInstrInfo.h"
17 #include "RISCVTargetMachine.h"
18
19 #include "llvm/CodeGen/LivePhysRegs.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/MC/MCContext.h"
23
24 using namespace llvm;
25
26 #define RISCV_EXPAND_PSEUDO_NAME "RISCV pseudo instruction expansion pass"
27 #define RISCV_PRERA_EXPAND_PSEUDO_NAME "RISCV Pre-RA pseudo instruction expansion pass"
28
29 namespace {
30
31 class RISCVExpandPseudo : public MachineFunctionPass {
32 public:
33 const RISCVInstrInfo *TII;
34 static char ID;
35
RISCVExpandPseudo()36 RISCVExpandPseudo() : MachineFunctionPass(ID) {
37 initializeRISCVExpandPseudoPass(*PassRegistry::getPassRegistry());
38 }
39
40 bool runOnMachineFunction(MachineFunction &MF) override;
41
getPassName() const42 StringRef getPassName() const override { return RISCV_EXPAND_PSEUDO_NAME; }
43
44 private:
45 bool expandMBB(MachineBasicBlock &MBB);
46 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
47 MachineBasicBlock::iterator &NextMBBI);
48 bool expandCCOp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
49 MachineBasicBlock::iterator &NextMBBI);
50 bool expandVSetVL(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
51 bool expandVMSET_VMCLR(MachineBasicBlock &MBB,
52 MachineBasicBlock::iterator MBBI, unsigned Opcode);
53 };
54
55 char RISCVExpandPseudo::ID = 0;
56
runOnMachineFunction(MachineFunction & MF)57 bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
58 TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo());
59 bool Modified = false;
60 for (auto &MBB : MF)
61 Modified |= expandMBB(MBB);
62 return Modified;
63 }
64
expandMBB(MachineBasicBlock & MBB)65 bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
66 bool Modified = false;
67
68 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
69 while (MBBI != E) {
70 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
71 Modified |= expandMI(MBB, MBBI, NMBBI);
72 MBBI = NMBBI;
73 }
74
75 return Modified;
76 }
77
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)78 bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
79 MachineBasicBlock::iterator MBBI,
80 MachineBasicBlock::iterator &NextMBBI) {
81 // RISCVInstrInfo::getInstSizeInBytes expects that the total size of the
82 // expanded instructions for each pseudo is correct in the Size field of the
83 // tablegen definition for the pseudo.
84 switch (MBBI->getOpcode()) {
85 case RISCV::PseudoCCMOVGPR:
86 case RISCV::PseudoCCADD:
87 case RISCV::PseudoCCSUB:
88 case RISCV::PseudoCCAND:
89 case RISCV::PseudoCCOR:
90 case RISCV::PseudoCCXOR:
91 case RISCV::PseudoCCADDW:
92 case RISCV::PseudoCCSUBW:
93 return expandCCOp(MBB, MBBI, NextMBBI);
94 case RISCV::PseudoVSETVLI:
95 case RISCV::PseudoVSETVLIX0:
96 case RISCV::PseudoVSETIVLI:
97 return expandVSetVL(MBB, MBBI);
98 case RISCV::PseudoVMCLR_M_B1:
99 case RISCV::PseudoVMCLR_M_B2:
100 case RISCV::PseudoVMCLR_M_B4:
101 case RISCV::PseudoVMCLR_M_B8:
102 case RISCV::PseudoVMCLR_M_B16:
103 case RISCV::PseudoVMCLR_M_B32:
104 case RISCV::PseudoVMCLR_M_B64:
105 // vmclr.m vd => vmxor.mm vd, vd, vd
106 return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXOR_MM);
107 case RISCV::PseudoVMSET_M_B1:
108 case RISCV::PseudoVMSET_M_B2:
109 case RISCV::PseudoVMSET_M_B4:
110 case RISCV::PseudoVMSET_M_B8:
111 case RISCV::PseudoVMSET_M_B16:
112 case RISCV::PseudoVMSET_M_B32:
113 case RISCV::PseudoVMSET_M_B64:
114 // vmset.m vd => vmxnor.mm vd, vd, vd
115 return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM);
116 }
117
118 return false;
119 }
120
expandCCOp(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)121 bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,
122 MachineBasicBlock::iterator MBBI,
123 MachineBasicBlock::iterator &NextMBBI) {
124
125 MachineFunction *MF = MBB.getParent();
126 MachineInstr &MI = *MBBI;
127 DebugLoc DL = MI.getDebugLoc();
128
129 MachineBasicBlock *TrueBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
130 MachineBasicBlock *MergeBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
131
132 MF->insert(++MBB.getIterator(), TrueBB);
133 MF->insert(++TrueBB->getIterator(), MergeBB);
134
135 // We want to copy the "true" value when the condition is true which means
136 // we need to invert the branch condition to jump over TrueBB when the
137 // condition is false.
138 auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
139 CC = RISCVCC::getOppositeBranchCondition(CC);
140
141 // Insert branch instruction.
142 BuildMI(MBB, MBBI, DL, TII->getBrCond(CC))
143 .addReg(MI.getOperand(1).getReg())
144 .addReg(MI.getOperand(2).getReg())
145 .addMBB(MergeBB);
146
147 Register DestReg = MI.getOperand(0).getReg();
148 assert(MI.getOperand(4).getReg() == DestReg);
149
150 if (MI.getOpcode() == RISCV::PseudoCCMOVGPR) {
151 // Add MV.
152 BuildMI(TrueBB, DL, TII->get(RISCV::ADDI), DestReg)
153 .add(MI.getOperand(5))
154 .addImm(0);
155 } else {
156 unsigned NewOpc;
157 switch (MI.getOpcode()) {
158 default:
159 llvm_unreachable("Unexpected opcode!");
160 case RISCV::PseudoCCADD: NewOpc = RISCV::ADD; break;
161 case RISCV::PseudoCCSUB: NewOpc = RISCV::SUB; break;
162 case RISCV::PseudoCCAND: NewOpc = RISCV::AND; break;
163 case RISCV::PseudoCCOR: NewOpc = RISCV::OR; break;
164 case RISCV::PseudoCCXOR: NewOpc = RISCV::XOR; break;
165 case RISCV::PseudoCCADDW: NewOpc = RISCV::ADDW; break;
166 case RISCV::PseudoCCSUBW: NewOpc = RISCV::SUBW; break;
167 }
168 BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg)
169 .add(MI.getOperand(5))
170 .add(MI.getOperand(6));
171 }
172
173 TrueBB->addSuccessor(MergeBB);
174
175 MergeBB->splice(MergeBB->end(), &MBB, MI, MBB.end());
176 MergeBB->transferSuccessors(&MBB);
177
178 MBB.addSuccessor(TrueBB);
179 MBB.addSuccessor(MergeBB);
180
181 NextMBBI = MBB.end();
182 MI.eraseFromParent();
183
184 // Make sure live-ins are correctly attached to this new basic block.
185 LivePhysRegs LiveRegs;
186 computeAndAddLiveIns(LiveRegs, *TrueBB);
187 computeAndAddLiveIns(LiveRegs, *MergeBB);
188
189 return true;
190 }
191
expandVSetVL(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)192 bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock &MBB,
193 MachineBasicBlock::iterator MBBI) {
194 assert(MBBI->getNumExplicitOperands() == 3 && MBBI->getNumOperands() >= 5 &&
195 "Unexpected instruction format");
196
197 DebugLoc DL = MBBI->getDebugLoc();
198
199 assert((MBBI->getOpcode() == RISCV::PseudoVSETVLI ||
200 MBBI->getOpcode() == RISCV::PseudoVSETVLIX0 ||
201 MBBI->getOpcode() == RISCV::PseudoVSETIVLI) &&
202 "Unexpected pseudo instruction");
203 unsigned Opcode;
204 if (MBBI->getOpcode() == RISCV::PseudoVSETIVLI)
205 Opcode = RISCV::VSETIVLI;
206 else
207 Opcode = RISCV::VSETVLI;
208 const MCInstrDesc &Desc = TII->get(Opcode);
209 assert(Desc.getNumOperands() == 3 && "Unexpected instruction format");
210
211 Register DstReg = MBBI->getOperand(0).getReg();
212 bool DstIsDead = MBBI->getOperand(0).isDead();
213 BuildMI(MBB, MBBI, DL, Desc)
214 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
215 .add(MBBI->getOperand(1)) // VL
216 .add(MBBI->getOperand(2)); // VType
217
218 MBBI->eraseFromParent(); // The pseudo instruction is gone now.
219 return true;
220 }
221
expandVMSET_VMCLR(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned Opcode)222 bool RISCVExpandPseudo::expandVMSET_VMCLR(MachineBasicBlock &MBB,
223 MachineBasicBlock::iterator MBBI,
224 unsigned Opcode) {
225 DebugLoc DL = MBBI->getDebugLoc();
226 Register DstReg = MBBI->getOperand(0).getReg();
227 const MCInstrDesc &Desc = TII->get(Opcode);
228 BuildMI(MBB, MBBI, DL, Desc, DstReg)
229 .addReg(DstReg, RegState::Undef)
230 .addReg(DstReg, RegState::Undef);
231 MBBI->eraseFromParent(); // The pseudo instruction is gone now.
232 return true;
233 }
234
235 class RISCVPreRAExpandPseudo : public MachineFunctionPass {
236 public:
237 const RISCVInstrInfo *TII;
238 static char ID;
239
RISCVPreRAExpandPseudo()240 RISCVPreRAExpandPseudo() : MachineFunctionPass(ID) {
241 initializeRISCVPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
242 }
243
244 bool runOnMachineFunction(MachineFunction &MF) override;
245
getAnalysisUsage(AnalysisUsage & AU) const246 void getAnalysisUsage(AnalysisUsage &AU) const override {
247 AU.setPreservesCFG();
248 MachineFunctionPass::getAnalysisUsage(AU);
249 }
getPassName() const250 StringRef getPassName() const override {
251 return RISCV_PRERA_EXPAND_PSEUDO_NAME;
252 }
253
254 private:
255 bool expandMBB(MachineBasicBlock &MBB);
256 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
257 MachineBasicBlock::iterator &NextMBBI);
258 bool expandAuipcInstPair(MachineBasicBlock &MBB,
259 MachineBasicBlock::iterator MBBI,
260 MachineBasicBlock::iterator &NextMBBI,
261 unsigned FlagsHi, unsigned SecondOpcode);
262 bool expandLoadLocalAddress(MachineBasicBlock &MBB,
263 MachineBasicBlock::iterator MBBI,
264 MachineBasicBlock::iterator &NextMBBI);
265 bool expandLoadAddress(MachineBasicBlock &MBB,
266 MachineBasicBlock::iterator MBBI,
267 MachineBasicBlock::iterator &NextMBBI);
268 bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,
269 MachineBasicBlock::iterator MBBI,
270 MachineBasicBlock::iterator &NextMBBI);
271 bool expandLoadTLSGDAddress(MachineBasicBlock &MBB,
272 MachineBasicBlock::iterator MBBI,
273 MachineBasicBlock::iterator &NextMBBI);
274 };
275
276 char RISCVPreRAExpandPseudo::ID = 0;
277
runOnMachineFunction(MachineFunction & MF)278 bool RISCVPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
279 TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo());
280 bool Modified = false;
281 for (auto &MBB : MF)
282 Modified |= expandMBB(MBB);
283 return Modified;
284 }
285
expandMBB(MachineBasicBlock & MBB)286 bool RISCVPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
287 bool Modified = false;
288
289 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
290 while (MBBI != E) {
291 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
292 Modified |= expandMI(MBB, MBBI, NMBBI);
293 MBBI = NMBBI;
294 }
295
296 return Modified;
297 }
298
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)299 bool RISCVPreRAExpandPseudo::expandMI(MachineBasicBlock &MBB,
300 MachineBasicBlock::iterator MBBI,
301 MachineBasicBlock::iterator &NextMBBI) {
302
303 switch (MBBI->getOpcode()) {
304 case RISCV::PseudoLLA:
305 return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
306 case RISCV::PseudoLA:
307 return expandLoadAddress(MBB, MBBI, NextMBBI);
308 case RISCV::PseudoLA_TLS_IE:
309 return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);
310 case RISCV::PseudoLA_TLS_GD:
311 return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI);
312 }
313 return false;
314 }
315
expandAuipcInstPair(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI,unsigned FlagsHi,unsigned SecondOpcode)316 bool RISCVPreRAExpandPseudo::expandAuipcInstPair(
317 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
318 MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
319 unsigned SecondOpcode) {
320 MachineFunction *MF = MBB.getParent();
321 MachineInstr &MI = *MBBI;
322 DebugLoc DL = MI.getDebugLoc();
323
324 Register DestReg = MI.getOperand(0).getReg();
325 Register ScratchReg =
326 MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
327
328 MachineOperand &Symbol = MI.getOperand(1);
329 Symbol.setTargetFlags(FlagsHi);
330 MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("pcrel_hi");
331
332 MachineInstr *MIAUIPC =
333 BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);
334 MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);
335
336 MachineInstr *SecondMI =
337 BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
338 .addReg(ScratchReg)
339 .addSym(AUIPCSymbol, RISCVII::MO_PCREL_LO);
340
341 if (MI.hasOneMemOperand())
342 SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
343
344 MI.eraseFromParent();
345 return true;
346 }
347
expandLoadLocalAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)348 bool RISCVPreRAExpandPseudo::expandLoadLocalAddress(
349 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
350 MachineBasicBlock::iterator &NextMBBI) {
351 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI,
352 RISCV::ADDI);
353 }
354
expandLoadAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)355 bool RISCVPreRAExpandPseudo::expandLoadAddress(
356 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
357 MachineBasicBlock::iterator &NextMBBI) {
358 MachineFunction *MF = MBB.getParent();
359
360 const auto &STI = MF->getSubtarget<RISCVSubtarget>();
361 // When HWASAN is used and tagging of global variables is enabled
362 // they should be accessed via the GOT, since the tagged address of a global
363 // is incompatible with existing code models. This also applies to non-pic
364 // mode.
365 assert(MF->getTarget().isPositionIndependent() || STI.allowTaggedGlobals());
366 unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
367 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_GOT_HI,
368 SecondOpcode);
369 }
370
expandLoadTLSIEAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)371 bool RISCVPreRAExpandPseudo::expandLoadTLSIEAddress(
372 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
373 MachineBasicBlock::iterator &NextMBBI) {
374 MachineFunction *MF = MBB.getParent();
375
376 const auto &STI = MF->getSubtarget<RISCVSubtarget>();
377 unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
378 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,
379 SecondOpcode);
380 }
381
expandLoadTLSGDAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)382 bool RISCVPreRAExpandPseudo::expandLoadTLSGDAddress(
383 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
384 MachineBasicBlock::iterator &NextMBBI) {
385 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI,
386 RISCV::ADDI);
387 }
388
389 } // end of anonymous namespace
390
391 INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
392 RISCV_EXPAND_PSEUDO_NAME, false, false)
393
394 INITIALIZE_PASS(RISCVPreRAExpandPseudo, "riscv-prera-expand-pseudo",
395 RISCV_PRERA_EXPAND_PSEUDO_NAME, false, false)
396
397 namespace llvm {
398
createRISCVExpandPseudoPass()399 FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
createRISCVPreRAExpandPseudoPass()400 FunctionPass *createRISCVPreRAExpandPseudoPass() { return new RISCVPreRAExpandPseudo(); }
401
402 } // end of namespace llvm
403