xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp (revision e8d8bef961a50d4dc22501cde4fb9fb0be1b2532)
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     return expandVSetVL(MBB, MBBI);
107   case RISCV::PseudoVMCLR_M_B1:
108   case RISCV::PseudoVMCLR_M_B2:
109   case RISCV::PseudoVMCLR_M_B4:
110   case RISCV::PseudoVMCLR_M_B8:
111   case RISCV::PseudoVMCLR_M_B16:
112   case RISCV::PseudoVMCLR_M_B32:
113   case RISCV::PseudoVMCLR_M_B64:
114     // vmclr.m vd => vmxor.mm vd, vd, vd
115     return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXOR_MM);
116   case RISCV::PseudoVMSET_M_B1:
117   case RISCV::PseudoVMSET_M_B2:
118   case RISCV::PseudoVMSET_M_B4:
119   case RISCV::PseudoVMSET_M_B8:
120   case RISCV::PseudoVMSET_M_B16:
121   case RISCV::PseudoVMSET_M_B32:
122   case RISCV::PseudoVMSET_M_B64:
123     // vmset.m vd => vmxnor.mm vd, vd, vd
124     return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM);
125   }
126 
127   return false;
128 }
129 
130 bool RISCVExpandPseudo::expandAuipcInstPair(
131     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
132     MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
133     unsigned SecondOpcode) {
134   MachineFunction *MF = MBB.getParent();
135   MachineInstr &MI = *MBBI;
136   DebugLoc DL = MI.getDebugLoc();
137 
138   Register DestReg = MI.getOperand(0).getReg();
139   const MachineOperand &Symbol = MI.getOperand(1);
140 
141   MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
142 
143   // Tell AsmPrinter that we unconditionally want the symbol of this label to be
144   // emitted.
145   NewMBB->setLabelMustBeEmitted();
146 
147   MF->insert(++MBB.getIterator(), NewMBB);
148 
149   BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg)
150       .addDisp(Symbol, 0, FlagsHi);
151   BuildMI(NewMBB, DL, TII->get(SecondOpcode), DestReg)
152       .addReg(DestReg)
153       .addMBB(NewMBB, RISCVII::MO_PCREL_LO);
154 
155   // Move all the rest of the instructions to NewMBB.
156   NewMBB->splice(NewMBB->end(), &MBB, std::next(MBBI), MBB.end());
157   // Update machine-CFG edges.
158   NewMBB->transferSuccessorsAndUpdatePHIs(&MBB);
159   // Make the original basic block fall-through to the new.
160   MBB.addSuccessor(NewMBB);
161 
162   // Make sure live-ins are correctly attached to this new basic block.
163   LivePhysRegs LiveRegs;
164   computeAndAddLiveIns(LiveRegs, *NewMBB);
165 
166   NextMBBI = MBB.end();
167   MI.eraseFromParent();
168   return true;
169 }
170 
171 bool RISCVExpandPseudo::expandLoadLocalAddress(
172     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
173     MachineBasicBlock::iterator &NextMBBI) {
174   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI,
175                              RISCV::ADDI);
176 }
177 
178 bool RISCVExpandPseudo::expandLoadAddress(
179     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
180     MachineBasicBlock::iterator &NextMBBI) {
181   MachineFunction *MF = MBB.getParent();
182 
183   unsigned SecondOpcode;
184   unsigned FlagsHi;
185   if (MF->getTarget().isPositionIndependent()) {
186     const auto &STI = MF->getSubtarget<RISCVSubtarget>();
187     SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
188     FlagsHi = RISCVII::MO_GOT_HI;
189   } else {
190     SecondOpcode = RISCV::ADDI;
191     FlagsHi = RISCVII::MO_PCREL_HI;
192   }
193   return expandAuipcInstPair(MBB, MBBI, NextMBBI, FlagsHi, SecondOpcode);
194 }
195 
196 bool RISCVExpandPseudo::expandLoadTLSIEAddress(
197     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
198     MachineBasicBlock::iterator &NextMBBI) {
199   MachineFunction *MF = MBB.getParent();
200 
201   const auto &STI = MF->getSubtarget<RISCVSubtarget>();
202   unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
203   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,
204                              SecondOpcode);
205 }
206 
207 bool RISCVExpandPseudo::expandLoadTLSGDAddress(
208     MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
209     MachineBasicBlock::iterator &NextMBBI) {
210   return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI,
211                              RISCV::ADDI);
212 }
213 
214 bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock &MBB,
215                                      MachineBasicBlock::iterator MBBI) {
216   assert(MBBI->getNumOperands() == 5 && "Unexpected instruction format");
217 
218   DebugLoc DL = MBBI->getDebugLoc();
219 
220   assert(MBBI->getOpcode() == RISCV::PseudoVSETVLI &&
221          "Unexpected pseudo instruction");
222   const MCInstrDesc &Desc = TII->get(RISCV::VSETVLI);
223   assert(Desc.getNumOperands() == 3 && "Unexpected instruction format");
224 
225   Register DstReg = MBBI->getOperand(0).getReg();
226   bool DstIsDead = MBBI->getOperand(0).isDead();
227   BuildMI(MBB, MBBI, DL, Desc)
228       .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
229       .add(MBBI->getOperand(1))  // VL
230       .add(MBBI->getOperand(2)); // VType
231 
232   MBBI->eraseFromParent(); // The pseudo instruction is gone now.
233   return true;
234 }
235 
236 bool RISCVExpandPseudo::expandVMSET_VMCLR(MachineBasicBlock &MBB,
237                                           MachineBasicBlock::iterator MBBI,
238                                           unsigned Opcode) {
239   DebugLoc DL = MBBI->getDebugLoc();
240   Register DstReg = MBBI->getOperand(0).getReg();
241   const MCInstrDesc &Desc = TII->get(Opcode);
242   BuildMI(MBB, MBBI, DL, Desc, DstReg)
243       .addReg(DstReg, RegState::Undef)
244       .addReg(DstReg, RegState::Undef);
245   MBBI->eraseFromParent(); // The pseudo instruction is gone now.
246   return true;
247 }
248 
249 } // end of anonymous namespace
250 
251 INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
252                 RISCV_EXPAND_PSEUDO_NAME, false, false)
253 namespace llvm {
254 
255 FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
256 
257 } // end of namespace llvm
258