xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp (revision 734e82fe33aa764367791a7d603b383996c6b40b)
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 
36   RISCVExpandPseudo() : MachineFunctionPass(ID) {
37     initializeRISCVExpandPseudoPass(*PassRegistry::getPassRegistry());
38   }
39 
40   bool runOnMachineFunction(MachineFunction &MF) override;
41 
42   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 
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 
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 
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 
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 
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 
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 
240   RISCVPreRAExpandPseudo() : MachineFunctionPass(ID) {
241     initializeRISCVPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());
242   }
243 
244   bool runOnMachineFunction(MachineFunction &MF) override;
245 
246   void getAnalysisUsage(AnalysisUsage &AU) const override {
247     AU.setPreservesCFG();
248     MachineFunctionPass::getAnalysisUsage(AU);
249   }
250   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 
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 
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 
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 
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 
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 
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 
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 
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 
399 FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
400 FunctionPass *createRISCVPreRAExpandPseudoPass() { return new RISCVPreRAExpandPseudo(); }
401 
402 } // end of namespace llvm
403