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
RISCVExpandPseudo()34 RISCVExpandPseudo() : MachineFunctionPass(ID) {
35 initializeRISCVExpandPseudoPass(*PassRegistry::getPassRegistry());
36 }
37
38 bool runOnMachineFunction(MachineFunction &MF) override;
39
getPassName() const40 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 };
64
65 char RISCVExpandPseudo::ID = 0;
66
runOnMachineFunction(MachineFunction & MF)67 bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
68 TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo());
69 bool Modified = false;
70 for (auto &MBB : MF)
71 Modified |= expandMBB(MBB);
72 return Modified;
73 }
74
expandMBB(MachineBasicBlock & MBB)75 bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
76 bool Modified = false;
77
78 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
79 while (MBBI != E) {
80 MachineBasicBlock::iterator NMBBI = std::next(MBBI);
81 Modified |= expandMI(MBB, MBBI, NMBBI);
82 MBBI = NMBBI;
83 }
84
85 return Modified;
86 }
87
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)88 bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
89 MachineBasicBlock::iterator MBBI,
90 MachineBasicBlock::iterator &NextMBBI) {
91 // RISCVInstrInfo::getInstSizeInBytes hard-codes the number of expanded
92 // instructions for each pseudo, and must be updated when adding new pseudos
93 // or changing existing ones.
94 switch (MBBI->getOpcode()) {
95 case RISCV::PseudoLLA:
96 return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
97 case RISCV::PseudoLA:
98 return expandLoadAddress(MBB, MBBI, NextMBBI);
99 case RISCV::PseudoLA_TLS_IE:
100 return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);
101 case RISCV::PseudoLA_TLS_GD:
102 return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI);
103 case RISCV::PseudoVSETVLI:
104 return expandVSetVL(MBB, MBBI);
105 }
106
107 return false;
108 }
109
expandAuipcInstPair(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI,unsigned FlagsHi,unsigned SecondOpcode)110 bool RISCVExpandPseudo::expandAuipcInstPair(
111 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
112 MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
113 unsigned SecondOpcode) {
114 MachineFunction *MF = MBB.getParent();
115 MachineInstr &MI = *MBBI;
116 DebugLoc DL = MI.getDebugLoc();
117
118 Register DestReg = MI.getOperand(0).getReg();
119 const MachineOperand &Symbol = MI.getOperand(1);
120
121 MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
122
123 // Tell AsmPrinter that we unconditionally want the symbol of this label to be
124 // emitted.
125 NewMBB->setLabelMustBeEmitted();
126
127 MF->insert(++MBB.getIterator(), NewMBB);
128
129 BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg)
130 .addDisp(Symbol, 0, FlagsHi);
131 BuildMI(NewMBB, DL, TII->get(SecondOpcode), DestReg)
132 .addReg(DestReg)
133 .addMBB(NewMBB, RISCVII::MO_PCREL_LO);
134
135 // Move all the rest of the instructions to NewMBB.
136 NewMBB->splice(NewMBB->end(), &MBB, std::next(MBBI), MBB.end());
137 // Update machine-CFG edges.
138 NewMBB->transferSuccessorsAndUpdatePHIs(&MBB);
139 // Make the original basic block fall-through to the new.
140 MBB.addSuccessor(NewMBB);
141
142 // Make sure live-ins are correctly attached to this new basic block.
143 LivePhysRegs LiveRegs;
144 computeAndAddLiveIns(LiveRegs, *NewMBB);
145
146 NextMBBI = MBB.end();
147 MI.eraseFromParent();
148 return true;
149 }
150
expandLoadLocalAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)151 bool RISCVExpandPseudo::expandLoadLocalAddress(
152 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
153 MachineBasicBlock::iterator &NextMBBI) {
154 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI,
155 RISCV::ADDI);
156 }
157
expandLoadAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)158 bool RISCVExpandPseudo::expandLoadAddress(
159 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
160 MachineBasicBlock::iterator &NextMBBI) {
161 MachineFunction *MF = MBB.getParent();
162
163 unsigned SecondOpcode;
164 unsigned FlagsHi;
165 if (MF->getTarget().isPositionIndependent()) {
166 const auto &STI = MF->getSubtarget<RISCVSubtarget>();
167 SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
168 FlagsHi = RISCVII::MO_GOT_HI;
169 } else {
170 SecondOpcode = RISCV::ADDI;
171 FlagsHi = RISCVII::MO_PCREL_HI;
172 }
173 return expandAuipcInstPair(MBB, MBBI, NextMBBI, FlagsHi, SecondOpcode);
174 }
175
expandLoadTLSIEAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)176 bool RISCVExpandPseudo::expandLoadTLSIEAddress(
177 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
178 MachineBasicBlock::iterator &NextMBBI) {
179 MachineFunction *MF = MBB.getParent();
180
181 const auto &STI = MF->getSubtarget<RISCVSubtarget>();
182 unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
183 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,
184 SecondOpcode);
185 }
186
expandLoadTLSGDAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)187 bool RISCVExpandPseudo::expandLoadTLSGDAddress(
188 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
189 MachineBasicBlock::iterator &NextMBBI) {
190 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI,
191 RISCV::ADDI);
192 }
193
expandVSetVL(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)194 bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock &MBB,
195 MachineBasicBlock::iterator MBBI) {
196 assert(MBBI->getNumOperands() == 5 && "Unexpected instruction format");
197
198 DebugLoc DL = MBBI->getDebugLoc();
199
200 assert(MBBI->getOpcode() == RISCV::PseudoVSETVLI &&
201 "Unexpected pseudo instruction");
202 const MCInstrDesc &Desc = TII->get(RISCV::VSETVLI);
203 assert(Desc.getNumOperands() == 3 && "Unexpected instruction format");
204
205 Register DstReg = MBBI->getOperand(0).getReg();
206 bool DstIsDead = MBBI->getOperand(0).isDead();
207 BuildMI(MBB, MBBI, DL, Desc)
208 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
209 .add(MBBI->getOperand(1)) // VL
210 .add(MBBI->getOperand(2)); // VType
211
212 MBBI->eraseFromParent(); // The pseudo instruction is gone now.
213 return true;
214 }
215
216 } // end of anonymous namespace
217
218 INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
219 RISCV_EXPAND_PSEUDO_NAME, false, false)
220 namespace llvm {
221
createRISCVExpandPseudoPass()222 FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
223
224 } // end of namespace llvm
225