xref: /freebsd/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp (revision ae7e8a02e6e93455e026036132c4d053b2c12ad9)
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 
23 using namespace llvm;
24 
25 #define RISCV_EXPAND_PSEUDO_NAME "RISCV pseudo instruction expansion pass"
26 
27 namespace {
28 
29 class RISCVExpandPseudo : public MachineFunctionPass {
30 public:
31   const RISCVInstrInfo *TII;
32   static char ID;
33 
34   RISCVExpandPseudo() : MachineFunctionPass(ID) {
35     initializeRISCVExpandPseudoPass(*PassRegistry::getPassRegistry());
36   }
37 
38   bool runOnMachineFunction(MachineFunction &MF) override;
39 
40   StringRef getPassName() const override { return RISCV_EXPAND_PSEUDO_NAME; }
41 
42 private:
43   bool expandMBB(MachineBasicBlock &MBB);
44   bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
45                 MachineBasicBlock::iterator &NextMBBI);
46   bool expandAuipcInstPair(MachineBasicBlock &MBB,
47                            MachineBasicBlock::iterator MBBI,
48                            MachineBasicBlock::iterator &NextMBBI,
49                            unsigned FlagsHi, unsigned SecondOpcode);
50   bool expandLoadLocalAddress(MachineBasicBlock &MBB,
51                               MachineBasicBlock::iterator MBBI,
52                               MachineBasicBlock::iterator &NextMBBI);
53   bool expandLoadAddress(MachineBasicBlock &MBB,
54                          MachineBasicBlock::iterator MBBI,
55                          MachineBasicBlock::iterator &NextMBBI);
56   bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,
57                               MachineBasicBlock::iterator MBBI,
58                               MachineBasicBlock::iterator &NextMBBI);
59   bool expandLoadTLSGDAddress(MachineBasicBlock &MBB,
60                               MachineBasicBlock::iterator MBBI,
61                               MachineBasicBlock::iterator &NextMBBI);
62   bool expandVSetVL(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
63   bool expandVMSET_VMCLR(MachineBasicBlock &MBB,
64                          MachineBasicBlock::iterator MBBI, unsigned Opcode);
65 };
66 
67 char RISCVExpandPseudo::ID = 0;
68 
69 bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
70   TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo());
71   bool Modified = false;
72   for (auto &MBB : MF)
73     Modified |= expandMBB(MBB);
74   return Modified;
75 }
76 
77 bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
78   bool Modified = false;
79 
80   MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
81   while (MBBI != E) {
82     MachineBasicBlock::iterator NMBBI = std::next(MBBI);
83     Modified |= expandMI(MBB, MBBI, NMBBI);
84     MBBI = NMBBI;
85   }
86 
87   return Modified;
88 }
89 
90 bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
91                                  MachineBasicBlock::iterator MBBI,
92                                  MachineBasicBlock::iterator &NextMBBI) {
93   // RISCVInstrInfo::getInstSizeInBytes hard-codes the number of expanded
94   // instructions for each pseudo, and must be updated when adding new pseudos
95   // or changing existing ones.
96   switch (MBBI->getOpcode()) {
97   case RISCV::PseudoLLA:
98     return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
99   case RISCV::PseudoLA:
100     return expandLoadAddress(MBB, MBBI, NextMBBI);
101   case RISCV::PseudoLA_TLS_IE:
102     return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);
103   case RISCV::PseudoLA_TLS_GD:
104     return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI);
105   case RISCV::PseudoVSETVLI:
106   case RISCV::PseudoVSETIVLI:
107     return expandVSetVL(MBB, MBBI);
108   case RISCV::PseudoVMCLR_M_B1:
109   case RISCV::PseudoVMCLR_M_B2:
110   case RISCV::PseudoVMCLR_M_B4:
111   case RISCV::PseudoVMCLR_M_B8:
112   case RISCV::PseudoVMCLR_M_B16:
113   case RISCV::PseudoVMCLR_M_B32:
114   case RISCV::PseudoVMCLR_M_B64:
115     // vmclr.m vd => vmxor.mm vd, vd, vd
116     return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXOR_MM);
117   case RISCV::PseudoVMSET_M_B1:
118   case RISCV::PseudoVMSET_M_B2:
119   case RISCV::PseudoVMSET_M_B4:
120   case RISCV::PseudoVMSET_M_B8:
121   case RISCV::PseudoVMSET_M_B16:
122   case RISCV::PseudoVMSET_M_B32:
123   case RISCV::PseudoVMSET_M_B64:
124     // vmset.m vd => vmxnor.mm vd, vd, vd
125     return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM);
126   }
127 
128   return false;
129 }
130 
131 bool RISCVExpandPseudo::expandAuipcInstPair(
132     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
133     MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
134     unsigned SecondOpcode) {
135   MachineFunction *MF = MBB.getParent();
136   MachineInstr &MI = *MBBI;
137   DebugLoc DL = MI.getDebugLoc();
138 
139   Register DestReg = MI.getOperand(0).getReg();
140   const MachineOperand &Symbol = MI.getOperand(1);
141 
142   MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
143 
144   // Tell AsmPrinter that we unconditionally want the symbol of this label to be
145   // emitted.
146   NewMBB->setLabelMustBeEmitted();
147 
148   MF->insert(++MBB.getIterator(), NewMBB);
149 
150   BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg)
151       .addDisp(Symbol, 0, FlagsHi);
152   BuildMI(NewMBB, DL, TII->get(SecondOpcode), DestReg)
153       .addReg(DestReg)
154       .addMBB(NewMBB, RISCVII::MO_PCREL_LO);
155 
156   // Move all the rest of the instructions to NewMBB.
157   NewMBB->splice(NewMBB->end(), &MBB, std::next(MBBI), MBB.end());
158   // Update machine-CFG edges.
159   NewMBB->transferSuccessorsAndUpdatePHIs(&MBB);
160   // Make the original basic block fall-through to the new.
161   MBB.addSuccessor(NewMBB);
162 
163   // Make sure live-ins are correctly attached to this new basic block.
164   LivePhysRegs LiveRegs;
165   computeAndAddLiveIns(LiveRegs, *NewMBB);
166 
167   NextMBBI = MBB.end();
168   MI.eraseFromParent();
169   return true;
170 }
171 
172 bool RISCVExpandPseudo::expandLoadLocalAddress(
173     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
174     MachineBasicBlock::iterator &NextMBBI) {
175   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI,
176                              RISCV::ADDI);
177 }
178 
179 bool RISCVExpandPseudo::expandLoadAddress(
180     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
181     MachineBasicBlock::iterator &NextMBBI) {
182   MachineFunction *MF = MBB.getParent();
183 
184   unsigned SecondOpcode;
185   unsigned FlagsHi;
186   if (MF->getTarget().isPositionIndependent()) {
187     const auto &STI = MF->getSubtarget<RISCVSubtarget>();
188     SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
189     FlagsHi = RISCVII::MO_GOT_HI;
190   } else {
191     SecondOpcode = RISCV::ADDI;
192     FlagsHi = RISCVII::MO_PCREL_HI;
193   }
194   return expandAuipcInstPair(MBB, MBBI, NextMBBI, FlagsHi, SecondOpcode);
195 }
196 
197 bool RISCVExpandPseudo::expandLoadTLSIEAddress(
198     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
199     MachineBasicBlock::iterator &NextMBBI) {
200   MachineFunction *MF = MBB.getParent();
201 
202   const auto &STI = MF->getSubtarget<RISCVSubtarget>();
203   unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
204   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,
205                              SecondOpcode);
206 }
207 
208 bool RISCVExpandPseudo::expandLoadTLSGDAddress(
209     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
210     MachineBasicBlock::iterator &NextMBBI) {
211   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI,
212                              RISCV::ADDI);
213 }
214 
215 bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock &MBB,
216                                      MachineBasicBlock::iterator MBBI) {
217   assert(MBBI->getNumOperands() == 5 && "Unexpected instruction format");
218 
219   DebugLoc DL = MBBI->getDebugLoc();
220 
221   assert((MBBI->getOpcode() == RISCV::PseudoVSETVLI ||
222           MBBI->getOpcode() == RISCV::PseudoVSETIVLI) &&
223          "Unexpected pseudo instruction");
224   unsigned Opcode;
225   if (MBBI->getOpcode() == RISCV::PseudoVSETVLI)
226     Opcode = RISCV::VSETVLI;
227   else
228     Opcode = RISCV::VSETIVLI;
229   const MCInstrDesc &Desc = TII->get(Opcode);
230   assert(Desc.getNumOperands() == 3 && "Unexpected instruction format");
231 
232   Register DstReg = MBBI->getOperand(0).getReg();
233   bool DstIsDead = MBBI->getOperand(0).isDead();
234   BuildMI(MBB, MBBI, DL, Desc)
235       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
236       .add(MBBI->getOperand(1))  // VL
237       .add(MBBI->getOperand(2)); // VType
238 
239   MBBI->eraseFromParent(); // The pseudo instruction is gone now.
240   return true;
241 }
242 
243 bool RISCVExpandPseudo::expandVMSET_VMCLR(MachineBasicBlock &MBB,
244                                           MachineBasicBlock::iterator MBBI,
245                                           unsigned Opcode) {
246   DebugLoc DL = MBBI->getDebugLoc();
247   Register DstReg = MBBI->getOperand(0).getReg();
248   const MCInstrDesc &Desc = TII->get(Opcode);
249   BuildMI(MBB, MBBI, DL, Desc, DstReg)
250       .addReg(DstReg, RegState::Undef)
251       .addReg(DstReg, RegState::Undef);
252   MBBI->eraseFromParent(); // The pseudo instruction is gone now.
253   return true;
254 }
255 
256 } // end of anonymous namespace
257 
258 INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
259                 RISCV_EXPAND_PSEUDO_NAME, false, false)
260 namespace llvm {
261 
262 FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
263 
264 } // end of namespace llvm
265