1 //===-- RISCVExpandPseudoInsts.cpp - Expand pseudo instructions -----------===//
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
7 //===----------------------------------------------------------------------===//
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.
13 //===----------------------------------------------------------------------===//
16 #include "RISCVInstrInfo.h"
17 #include "RISCVTargetMachine.h"
19 #include "llvm/CodeGen/LivePhysRegs.h"
20 #include "llvm/CodeGen/MachineFunctionPass.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
25 #define RISCV_EXPAND_PSEUDO_NAME "RISCV pseudo instruction expansion pass"
29 class RISCVExpandPseudo
: public MachineFunctionPass
{
31 const RISCVInstrInfo
*TII
;
34 RISCVExpandPseudo() : MachineFunctionPass(ID
) {
35 initializeRISCVExpandPseudoPass(*PassRegistry::getPassRegistry());
38 bool runOnMachineFunction(MachineFunction
&MF
) override
;
40 StringRef
getPassName() const override
{ return RISCV_EXPAND_PSEUDO_NAME
; }
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 bool expandVSPILL(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
);
66 bool expandVRELOAD(MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
);
69 char RISCVExpandPseudo::ID
= 0;
71 bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction
&MF
) {
72 TII
= static_cast<const RISCVInstrInfo
*>(MF
.getSubtarget().getInstrInfo());
73 bool Modified
= false;
75 Modified
|= expandMBB(MBB
);
79 bool RISCVExpandPseudo::expandMBB(MachineBasicBlock
&MBB
) {
80 bool Modified
= false;
82 MachineBasicBlock::iterator MBBI
= MBB
.begin(), E
= MBB
.end();
84 MachineBasicBlock::iterator NMBBI
= std::next(MBBI
);
85 Modified
|= expandMI(MBB
, MBBI
, NMBBI
);
92 bool RISCVExpandPseudo::expandMI(MachineBasicBlock
&MBB
,
93 MachineBasicBlock::iterator MBBI
,
94 MachineBasicBlock::iterator
&NextMBBI
) {
95 // RISCVInstrInfo::getInstSizeInBytes hard-codes the number of expanded
96 // instructions for each pseudo, and must be updated when adding new pseudos
97 // or changing existing ones.
98 switch (MBBI
->getOpcode()) {
99 case RISCV::PseudoLLA
:
100 return expandLoadLocalAddress(MBB
, MBBI
, NextMBBI
);
101 case RISCV::PseudoLA
:
102 return expandLoadAddress(MBB
, MBBI
, NextMBBI
);
103 case RISCV::PseudoLA_TLS_IE
:
104 return expandLoadTLSIEAddress(MBB
, MBBI
, NextMBBI
);
105 case RISCV::PseudoLA_TLS_GD
:
106 return expandLoadTLSGDAddress(MBB
, MBBI
, NextMBBI
);
107 case RISCV::PseudoVSETVLI
:
108 case RISCV::PseudoVSETIVLI
:
109 return expandVSetVL(MBB
, MBBI
);
110 case RISCV::PseudoVMCLR_M_B1
:
111 case RISCV::PseudoVMCLR_M_B2
:
112 case RISCV::PseudoVMCLR_M_B4
:
113 case RISCV::PseudoVMCLR_M_B8
:
114 case RISCV::PseudoVMCLR_M_B16
:
115 case RISCV::PseudoVMCLR_M_B32
:
116 case RISCV::PseudoVMCLR_M_B64
:
117 // vmclr.m vd => vmxor.mm vd, vd, vd
118 return expandVMSET_VMCLR(MBB
, MBBI
, RISCV::VMXOR_MM
);
119 case RISCV::PseudoVMSET_M_B1
:
120 case RISCV::PseudoVMSET_M_B2
:
121 case RISCV::PseudoVMSET_M_B4
:
122 case RISCV::PseudoVMSET_M_B8
:
123 case RISCV::PseudoVMSET_M_B16
:
124 case RISCV::PseudoVMSET_M_B32
:
125 case RISCV::PseudoVMSET_M_B64
:
126 // vmset.m vd => vmxnor.mm vd, vd, vd
127 return expandVMSET_VMCLR(MBB
, MBBI
, RISCV::VMXNOR_MM
);
128 case RISCV::PseudoVSPILL2_M1
:
129 case RISCV::PseudoVSPILL2_M2
:
130 case RISCV::PseudoVSPILL2_M4
:
131 case RISCV::PseudoVSPILL3_M1
:
132 case RISCV::PseudoVSPILL3_M2
:
133 case RISCV::PseudoVSPILL4_M1
:
134 case RISCV::PseudoVSPILL4_M2
:
135 case RISCV::PseudoVSPILL5_M1
:
136 case RISCV::PseudoVSPILL6_M1
:
137 case RISCV::PseudoVSPILL7_M1
:
138 case RISCV::PseudoVSPILL8_M1
:
139 return expandVSPILL(MBB
, MBBI
);
140 case RISCV::PseudoVRELOAD2_M1
:
141 case RISCV::PseudoVRELOAD2_M2
:
142 case RISCV::PseudoVRELOAD2_M4
:
143 case RISCV::PseudoVRELOAD3_M1
:
144 case RISCV::PseudoVRELOAD3_M2
:
145 case RISCV::PseudoVRELOAD4_M1
:
146 case RISCV::PseudoVRELOAD4_M2
:
147 case RISCV::PseudoVRELOAD5_M1
:
148 case RISCV::PseudoVRELOAD6_M1
:
149 case RISCV::PseudoVRELOAD7_M1
:
150 case RISCV::PseudoVRELOAD8_M1
:
151 return expandVRELOAD(MBB
, MBBI
);
157 bool RISCVExpandPseudo::expandAuipcInstPair(
158 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
159 MachineBasicBlock::iterator
&NextMBBI
, unsigned FlagsHi
,
160 unsigned SecondOpcode
) {
161 MachineFunction
*MF
= MBB
.getParent();
162 MachineInstr
&MI
= *MBBI
;
163 DebugLoc DL
= MI
.getDebugLoc();
165 Register DestReg
= MI
.getOperand(0).getReg();
166 const MachineOperand
&Symbol
= MI
.getOperand(1);
168 MachineBasicBlock
*NewMBB
= MF
->CreateMachineBasicBlock(MBB
.getBasicBlock());
170 // Tell AsmPrinter that we unconditionally want the symbol of this label to be
172 NewMBB
->setLabelMustBeEmitted();
174 MF
->insert(++MBB
.getIterator(), NewMBB
);
176 BuildMI(NewMBB
, DL
, TII
->get(RISCV::AUIPC
), DestReg
)
177 .addDisp(Symbol
, 0, FlagsHi
);
178 BuildMI(NewMBB
, DL
, TII
->get(SecondOpcode
), DestReg
)
180 .addMBB(NewMBB
, RISCVII::MO_PCREL_LO
);
182 // Move all the rest of the instructions to NewMBB.
183 NewMBB
->splice(NewMBB
->end(), &MBB
, std::next(MBBI
), MBB
.end());
184 // Update machine-CFG edges.
185 NewMBB
->transferSuccessorsAndUpdatePHIs(&MBB
);
186 // Make the original basic block fall-through to the new.
187 MBB
.addSuccessor(NewMBB
);
189 // Make sure live-ins are correctly attached to this new basic block.
190 LivePhysRegs LiveRegs
;
191 computeAndAddLiveIns(LiveRegs
, *NewMBB
);
193 NextMBBI
= MBB
.end();
194 MI
.eraseFromParent();
198 bool RISCVExpandPseudo::expandLoadLocalAddress(
199 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
200 MachineBasicBlock::iterator
&NextMBBI
) {
201 return expandAuipcInstPair(MBB
, MBBI
, NextMBBI
, RISCVII::MO_PCREL_HI
,
205 bool RISCVExpandPseudo::expandLoadAddress(
206 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
207 MachineBasicBlock::iterator
&NextMBBI
) {
208 MachineFunction
*MF
= MBB
.getParent();
210 unsigned SecondOpcode
;
212 if (MF
->getTarget().isPositionIndependent()) {
213 const auto &STI
= MF
->getSubtarget
<RISCVSubtarget
>();
214 SecondOpcode
= STI
.is64Bit() ? RISCV::LD
: RISCV::LW
;
215 FlagsHi
= RISCVII::MO_GOT_HI
;
217 SecondOpcode
= RISCV::ADDI
;
218 FlagsHi
= RISCVII::MO_PCREL_HI
;
220 return expandAuipcInstPair(MBB
, MBBI
, NextMBBI
, FlagsHi
, SecondOpcode
);
223 bool RISCVExpandPseudo::expandLoadTLSIEAddress(
224 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
225 MachineBasicBlock::iterator
&NextMBBI
) {
226 MachineFunction
*MF
= MBB
.getParent();
228 const auto &STI
= MF
->getSubtarget
<RISCVSubtarget
>();
229 unsigned SecondOpcode
= STI
.is64Bit() ? RISCV::LD
: RISCV::LW
;
230 return expandAuipcInstPair(MBB
, MBBI
, NextMBBI
, RISCVII::MO_TLS_GOT_HI
,
234 bool RISCVExpandPseudo::expandLoadTLSGDAddress(
235 MachineBasicBlock
&MBB
, MachineBasicBlock::iterator MBBI
,
236 MachineBasicBlock::iterator
&NextMBBI
) {
237 return expandAuipcInstPair(MBB
, MBBI
, NextMBBI
, RISCVII::MO_TLS_GD_HI
,
241 bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock
&MBB
,
242 MachineBasicBlock::iterator MBBI
) {
243 assert(MBBI
->getNumExplicitOperands() == 3 && MBBI
->getNumOperands() >= 5 &&
244 "Unexpected instruction format");
246 DebugLoc DL
= MBBI
->getDebugLoc();
248 assert((MBBI
->getOpcode() == RISCV::PseudoVSETVLI
||
249 MBBI
->getOpcode() == RISCV::PseudoVSETIVLI
) &&
250 "Unexpected pseudo instruction");
252 if (MBBI
->getOpcode() == RISCV::PseudoVSETVLI
)
253 Opcode
= RISCV::VSETVLI
;
255 Opcode
= RISCV::VSETIVLI
;
256 const MCInstrDesc
&Desc
= TII
->get(Opcode
);
257 assert(Desc
.getNumOperands() == 3 && "Unexpected instruction format");
259 Register DstReg
= MBBI
->getOperand(0).getReg();
260 bool DstIsDead
= MBBI
->getOperand(0).isDead();
261 BuildMI(MBB
, MBBI
, DL
, Desc
)
262 .addReg(DstReg
, RegState::Define
| getDeadRegState(DstIsDead
))
263 .add(MBBI
->getOperand(1)) // VL
264 .add(MBBI
->getOperand(2)); // VType
266 MBBI
->eraseFromParent(); // The pseudo instruction is gone now.
270 bool RISCVExpandPseudo::expandVMSET_VMCLR(MachineBasicBlock
&MBB
,
271 MachineBasicBlock::iterator MBBI
,
273 DebugLoc DL
= MBBI
->getDebugLoc();
274 Register DstReg
= MBBI
->getOperand(0).getReg();
275 const MCInstrDesc
&Desc
= TII
->get(Opcode
);
276 BuildMI(MBB
, MBBI
, DL
, Desc
, DstReg
)
277 .addReg(DstReg
, RegState::Undef
)
278 .addReg(DstReg
, RegState::Undef
);
279 MBBI
->eraseFromParent(); // The pseudo instruction is gone now.
283 bool RISCVExpandPseudo::expandVSPILL(MachineBasicBlock
&MBB
,
284 MachineBasicBlock::iterator MBBI
) {
285 const TargetRegisterInfo
*TRI
=
286 MBB
.getParent()->getSubtarget().getRegisterInfo();
287 DebugLoc DL
= MBBI
->getDebugLoc();
288 Register SrcReg
= MBBI
->getOperand(0).getReg();
289 Register Base
= MBBI
->getOperand(1).getReg();
290 Register VL
= MBBI
->getOperand(2).getReg();
291 auto ZvlssegInfo
= TII
->isRVVSpillForZvlsseg(MBBI
->getOpcode());
294 unsigned NF
= ZvlssegInfo
->first
;
295 unsigned LMUL
= ZvlssegInfo
->second
;
296 assert(NF
* LMUL
<= 8 && "Invalid NF/LMUL combinations.");
297 unsigned Opcode
= RISCV::VS1R_V
;
298 unsigned SubRegIdx
= RISCV::sub_vrm1_0
;
299 static_assert(RISCV::sub_vrm1_7
== RISCV::sub_vrm1_0
+ 7,
300 "Unexpected subreg numbering");
302 Opcode
= RISCV::VS2R_V
;
303 SubRegIdx
= RISCV::sub_vrm2_0
;
304 static_assert(RISCV::sub_vrm2_3
== RISCV::sub_vrm2_0
+ 3,
305 "Unexpected subreg numbering");
306 } else if (LMUL
== 4) {
307 Opcode
= RISCV::VS4R_V
;
308 SubRegIdx
= RISCV::sub_vrm4_0
;
309 static_assert(RISCV::sub_vrm4_1
== RISCV::sub_vrm4_0
+ 1,
310 "Unexpected subreg numbering");
312 assert(LMUL
== 1 && "LMUL must be 1, 2, or 4.");
314 for (unsigned I
= 0; I
< NF
; ++I
) {
315 BuildMI(MBB
, MBBI
, DL
, TII
->get(Opcode
))
316 .addReg(TRI
->getSubReg(SrcReg
, SubRegIdx
+ I
))
318 .addMemOperand(*(MBBI
->memoperands_begin()));
320 BuildMI(MBB
, MBBI
, DL
, TII
->get(RISCV::ADD
), Base
)
324 MBBI
->eraseFromParent();
328 bool RISCVExpandPseudo::expandVRELOAD(MachineBasicBlock
&MBB
,
329 MachineBasicBlock::iterator MBBI
) {
330 const TargetRegisterInfo
*TRI
=
331 MBB
.getParent()->getSubtarget().getRegisterInfo();
332 DebugLoc DL
= MBBI
->getDebugLoc();
333 Register DestReg
= MBBI
->getOperand(0).getReg();
334 Register Base
= MBBI
->getOperand(1).getReg();
335 Register VL
= MBBI
->getOperand(2).getReg();
336 auto ZvlssegInfo
= TII
->isRVVSpillForZvlsseg(MBBI
->getOpcode());
339 unsigned NF
= ZvlssegInfo
->first
;
340 unsigned LMUL
= ZvlssegInfo
->second
;
341 assert(NF
* LMUL
<= 8 && "Invalid NF/LMUL combinations.");
342 unsigned Opcode
= RISCV::VL1RE8_V
;
343 unsigned SubRegIdx
= RISCV::sub_vrm1_0
;
344 static_assert(RISCV::sub_vrm1_7
== RISCV::sub_vrm1_0
+ 7,
345 "Unexpected subreg numbering");
347 Opcode
= RISCV::VL2RE8_V
;
348 SubRegIdx
= RISCV::sub_vrm2_0
;
349 static_assert(RISCV::sub_vrm2_3
== RISCV::sub_vrm2_0
+ 3,
350 "Unexpected subreg numbering");
351 } else if (LMUL
== 4) {
352 Opcode
= RISCV::VL4RE8_V
;
353 SubRegIdx
= RISCV::sub_vrm4_0
;
354 static_assert(RISCV::sub_vrm4_1
== RISCV::sub_vrm4_0
+ 1,
355 "Unexpected subreg numbering");
357 assert(LMUL
== 1 && "LMUL must be 1, 2, or 4.");
359 for (unsigned I
= 0; I
< NF
; ++I
) {
360 BuildMI(MBB
, MBBI
, DL
, TII
->get(Opcode
),
361 TRI
->getSubReg(DestReg
, SubRegIdx
+ I
))
363 .addMemOperand(*(MBBI
->memoperands_begin()));
365 BuildMI(MBB
, MBBI
, DL
, TII
->get(RISCV::ADD
), Base
)
369 MBBI
->eraseFromParent();
373 } // end of anonymous namespace
375 INITIALIZE_PASS(RISCVExpandPseudo
, "riscv-expand-pseudo",
376 RISCV_EXPAND_PSEUDO_NAME
, false, false)
379 FunctionPass
*createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
381 } // end of namespace llvm