10b57cec5SDimitry Andric //===-- RISCVExpandPseudoInsts.cpp - Expand pseudo instructions -----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains a pass that expands pseudo instructions into target
100b57cec5SDimitry Andric // instructions. This pass should be run after register allocation but before
110b57cec5SDimitry Andric // the post-regalloc scheduling pass.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric #include "RISCV.h"
160b57cec5SDimitry Andric #include "RISCVInstrInfo.h"
170b57cec5SDimitry Andric #include "RISCVTargetMachine.h"
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h"
200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
22bdd1243dSDimitry Andric #include "llvm/MC/MCContext.h"
230b57cec5SDimitry Andric
240b57cec5SDimitry Andric using namespace llvm;
250b57cec5SDimitry Andric
2606c3fb27SDimitry Andric #define RISCV_EXPAND_PSEUDO_NAME "RISC-V pseudo instruction expansion pass"
2706c3fb27SDimitry Andric #define RISCV_PRERA_EXPAND_PSEUDO_NAME "RISC-V Pre-RA pseudo instruction expansion pass"
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric namespace {
300b57cec5SDimitry Andric
310b57cec5SDimitry Andric class RISCVExpandPseudo : public MachineFunctionPass {
320b57cec5SDimitry Andric public:
3306c3fb27SDimitry Andric const RISCVSubtarget *STI;
340b57cec5SDimitry Andric const RISCVInstrInfo *TII;
350b57cec5SDimitry Andric static char ID;
360b57cec5SDimitry Andric
RISCVExpandPseudo()375f757f3fSDimitry Andric RISCVExpandPseudo() : MachineFunctionPass(ID) {}
380b57cec5SDimitry Andric
390b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
400b57cec5SDimitry Andric
getPassName() const410b57cec5SDimitry Andric StringRef getPassName() const override { return RISCV_EXPAND_PSEUDO_NAME; }
420b57cec5SDimitry Andric
430b57cec5SDimitry Andric private:
440b57cec5SDimitry Andric bool expandMBB(MachineBasicBlock &MBB);
450b57cec5SDimitry Andric bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
460b57cec5SDimitry Andric MachineBasicBlock::iterator &NextMBBI);
47bdd1243dSDimitry Andric bool expandCCOp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
480b57cec5SDimitry Andric MachineBasicBlock::iterator &NextMBBI);
49e8d8bef9SDimitry Andric bool expandVSetVL(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);
50e8d8bef9SDimitry Andric bool expandVMSET_VMCLR(MachineBasicBlock &MBB,
51e8d8bef9SDimitry Andric MachineBasicBlock::iterator MBBI, unsigned Opcode);
5206c3fb27SDimitry Andric bool expandRV32ZdinxStore(MachineBasicBlock &MBB,
5306c3fb27SDimitry Andric MachineBasicBlock::iterator MBBI);
5406c3fb27SDimitry Andric bool expandRV32ZdinxLoad(MachineBasicBlock &MBB,
5506c3fb27SDimitry Andric MachineBasicBlock::iterator MBBI);
5606c3fb27SDimitry Andric #ifndef NDEBUG
getInstSizeInBytes(const MachineFunction & MF) const5706c3fb27SDimitry Andric unsigned getInstSizeInBytes(const MachineFunction &MF) const {
5806c3fb27SDimitry Andric unsigned Size = 0;
5906c3fb27SDimitry Andric for (auto &MBB : MF)
6006c3fb27SDimitry Andric for (auto &MI : MBB)
6106c3fb27SDimitry Andric Size += TII->getInstSizeInBytes(MI);
6206c3fb27SDimitry Andric return Size;
6306c3fb27SDimitry Andric }
6406c3fb27SDimitry Andric #endif
650b57cec5SDimitry Andric };
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric char RISCVExpandPseudo::ID = 0;
680b57cec5SDimitry Andric
runOnMachineFunction(MachineFunction & MF)690b57cec5SDimitry Andric bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
7006c3fb27SDimitry Andric STI = &MF.getSubtarget<RISCVSubtarget>();
7106c3fb27SDimitry Andric TII = STI->getInstrInfo();
7206c3fb27SDimitry Andric
7306c3fb27SDimitry Andric #ifndef NDEBUG
7406c3fb27SDimitry Andric const unsigned OldSize = getInstSizeInBytes(MF);
7506c3fb27SDimitry Andric #endif
7606c3fb27SDimitry Andric
770b57cec5SDimitry Andric bool Modified = false;
780b57cec5SDimitry Andric for (auto &MBB : MF)
790b57cec5SDimitry Andric Modified |= expandMBB(MBB);
8006c3fb27SDimitry Andric
8106c3fb27SDimitry Andric #ifndef NDEBUG
8206c3fb27SDimitry Andric const unsigned NewSize = getInstSizeInBytes(MF);
8306c3fb27SDimitry Andric assert(OldSize >= NewSize);
8406c3fb27SDimitry Andric #endif
850b57cec5SDimitry Andric return Modified;
860b57cec5SDimitry Andric }
870b57cec5SDimitry Andric
expandMBB(MachineBasicBlock & MBB)880b57cec5SDimitry Andric bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
890b57cec5SDimitry Andric bool Modified = false;
900b57cec5SDimitry Andric
910b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
920b57cec5SDimitry Andric while (MBBI != E) {
930b57cec5SDimitry Andric MachineBasicBlock::iterator NMBBI = std::next(MBBI);
940b57cec5SDimitry Andric Modified |= expandMI(MBB, MBBI, NMBBI);
950b57cec5SDimitry Andric MBBI = NMBBI;
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric return Modified;
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)1010b57cec5SDimitry Andric bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,
1020b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI,
1030b57cec5SDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
1041fd87a68SDimitry Andric // RISCVInstrInfo::getInstSizeInBytes expects that the total size of the
1051fd87a68SDimitry Andric // expanded instructions for each pseudo is correct in the Size field of the
1061fd87a68SDimitry Andric // tablegen definition for the pseudo.
1070b57cec5SDimitry Andric switch (MBBI->getOpcode()) {
10806c3fb27SDimitry Andric case RISCV::PseudoRV32ZdinxSD:
10906c3fb27SDimitry Andric return expandRV32ZdinxStore(MBB, MBBI);
11006c3fb27SDimitry Andric case RISCV::PseudoRV32ZdinxLD:
11106c3fb27SDimitry Andric return expandRV32ZdinxLoad(MBB, MBBI);
1121db9f3b2SDimitry Andric case RISCV::PseudoCCMOVGPRNoX0:
113bdd1243dSDimitry Andric case RISCV::PseudoCCMOVGPR:
114bdd1243dSDimitry Andric case RISCV::PseudoCCADD:
115bdd1243dSDimitry Andric case RISCV::PseudoCCSUB:
116bdd1243dSDimitry Andric case RISCV::PseudoCCAND:
117bdd1243dSDimitry Andric case RISCV::PseudoCCOR:
118bdd1243dSDimitry Andric case RISCV::PseudoCCXOR:
119bdd1243dSDimitry Andric case RISCV::PseudoCCADDW:
120bdd1243dSDimitry Andric case RISCV::PseudoCCSUBW:
1215f757f3fSDimitry Andric case RISCV::PseudoCCSLL:
1225f757f3fSDimitry Andric case RISCV::PseudoCCSRL:
1235f757f3fSDimitry Andric case RISCV::PseudoCCSRA:
1245f757f3fSDimitry Andric case RISCV::PseudoCCADDI:
1255f757f3fSDimitry Andric case RISCV::PseudoCCSLLI:
1265f757f3fSDimitry Andric case RISCV::PseudoCCSRLI:
1275f757f3fSDimitry Andric case RISCV::PseudoCCSRAI:
1285f757f3fSDimitry Andric case RISCV::PseudoCCANDI:
1295f757f3fSDimitry Andric case RISCV::PseudoCCORI:
1305f757f3fSDimitry Andric case RISCV::PseudoCCXORI:
1315f757f3fSDimitry Andric case RISCV::PseudoCCSLLW:
1325f757f3fSDimitry Andric case RISCV::PseudoCCSRLW:
1335f757f3fSDimitry Andric case RISCV::PseudoCCSRAW:
1345f757f3fSDimitry Andric case RISCV::PseudoCCADDIW:
1355f757f3fSDimitry Andric case RISCV::PseudoCCSLLIW:
1365f757f3fSDimitry Andric case RISCV::PseudoCCSRLIW:
1375f757f3fSDimitry Andric case RISCV::PseudoCCSRAIW:
1381db9f3b2SDimitry Andric case RISCV::PseudoCCANDN:
1391db9f3b2SDimitry Andric case RISCV::PseudoCCORN:
1401db9f3b2SDimitry Andric case RISCV::PseudoCCXNOR:
141bdd1243dSDimitry Andric return expandCCOp(MBB, MBBI, NextMBBI);
142e8d8bef9SDimitry Andric case RISCV::PseudoVSETVLI:
143349cc55cSDimitry Andric case RISCV::PseudoVSETVLIX0:
144d409305fSDimitry Andric case RISCV::PseudoVSETIVLI:
145e8d8bef9SDimitry Andric return expandVSetVL(MBB, MBBI);
146e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B1:
147e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B2:
148e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B4:
149e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B8:
150e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B16:
151e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B32:
152e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B64:
153e8d8bef9SDimitry Andric // vmclr.m vd => vmxor.mm vd, vd, vd
154e8d8bef9SDimitry Andric return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXOR_MM);
155e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B1:
156e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B2:
157e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B4:
158e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B8:
159e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B16:
160e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B32:
161e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B64:
162e8d8bef9SDimitry Andric // vmset.m vd => vmxnor.mm vd, vd, vd
163e8d8bef9SDimitry Andric return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM);
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric
1660b57cec5SDimitry Andric return false;
1670b57cec5SDimitry Andric }
1680b57cec5SDimitry Andric
expandCCOp(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)169bdd1243dSDimitry Andric bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,
170bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
171bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
172bdd1243dSDimitry Andric
1730b57cec5SDimitry Andric MachineFunction *MF = MBB.getParent();
1740b57cec5SDimitry Andric MachineInstr &MI = *MBBI;
1750b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc();
1760b57cec5SDimitry Andric
177bdd1243dSDimitry Andric MachineBasicBlock *TrueBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
178bdd1243dSDimitry Andric MachineBasicBlock *MergeBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());
179bdd1243dSDimitry Andric
180bdd1243dSDimitry Andric MF->insert(++MBB.getIterator(), TrueBB);
181bdd1243dSDimitry Andric MF->insert(++TrueBB->getIterator(), MergeBB);
182bdd1243dSDimitry Andric
183bdd1243dSDimitry Andric // We want to copy the "true" value when the condition is true which means
184bdd1243dSDimitry Andric // we need to invert the branch condition to jump over TrueBB when the
185bdd1243dSDimitry Andric // condition is false.
186bdd1243dSDimitry Andric auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());
187bdd1243dSDimitry Andric CC = RISCVCC::getOppositeBranchCondition(CC);
188bdd1243dSDimitry Andric
189bdd1243dSDimitry Andric // Insert branch instruction.
190bdd1243dSDimitry Andric BuildMI(MBB, MBBI, DL, TII->getBrCond(CC))
191bdd1243dSDimitry Andric .addReg(MI.getOperand(1).getReg())
192bdd1243dSDimitry Andric .addReg(MI.getOperand(2).getReg())
193bdd1243dSDimitry Andric .addMBB(MergeBB);
194bdd1243dSDimitry Andric
1958bcb0991SDimitry Andric Register DestReg = MI.getOperand(0).getReg();
196bdd1243dSDimitry Andric assert(MI.getOperand(4).getReg() == DestReg);
1970b57cec5SDimitry Andric
1981db9f3b2SDimitry Andric if (MI.getOpcode() == RISCV::PseudoCCMOVGPR ||
1991db9f3b2SDimitry Andric MI.getOpcode() == RISCV::PseudoCCMOVGPRNoX0) {
200bdd1243dSDimitry Andric // Add MV.
201bdd1243dSDimitry Andric BuildMI(TrueBB, DL, TII->get(RISCV::ADDI), DestReg)
202bdd1243dSDimitry Andric .add(MI.getOperand(5))
203bdd1243dSDimitry Andric .addImm(0);
204bdd1243dSDimitry Andric } else {
205bdd1243dSDimitry Andric unsigned NewOpc;
206bdd1243dSDimitry Andric switch (MI.getOpcode()) {
207bdd1243dSDimitry Andric default:
208bdd1243dSDimitry Andric llvm_unreachable("Unexpected opcode!");
209bdd1243dSDimitry Andric case RISCV::PseudoCCADD: NewOpc = RISCV::ADD; break;
210bdd1243dSDimitry Andric case RISCV::PseudoCCSUB: NewOpc = RISCV::SUB; break;
2115f757f3fSDimitry Andric case RISCV::PseudoCCSLL: NewOpc = RISCV::SLL; break;
2125f757f3fSDimitry Andric case RISCV::PseudoCCSRL: NewOpc = RISCV::SRL; break;
2135f757f3fSDimitry Andric case RISCV::PseudoCCSRA: NewOpc = RISCV::SRA; break;
214bdd1243dSDimitry Andric case RISCV::PseudoCCAND: NewOpc = RISCV::AND; break;
215bdd1243dSDimitry Andric case RISCV::PseudoCCOR: NewOpc = RISCV::OR; break;
216bdd1243dSDimitry Andric case RISCV::PseudoCCXOR: NewOpc = RISCV::XOR; break;
2175f757f3fSDimitry Andric case RISCV::PseudoCCADDI: NewOpc = RISCV::ADDI; break;
2185f757f3fSDimitry Andric case RISCV::PseudoCCSLLI: NewOpc = RISCV::SLLI; break;
2195f757f3fSDimitry Andric case RISCV::PseudoCCSRLI: NewOpc = RISCV::SRLI; break;
2205f757f3fSDimitry Andric case RISCV::PseudoCCSRAI: NewOpc = RISCV::SRAI; break;
2215f757f3fSDimitry Andric case RISCV::PseudoCCANDI: NewOpc = RISCV::ANDI; break;
2225f757f3fSDimitry Andric case RISCV::PseudoCCORI: NewOpc = RISCV::ORI; break;
2235f757f3fSDimitry Andric case RISCV::PseudoCCXORI: NewOpc = RISCV::XORI; break;
224bdd1243dSDimitry Andric case RISCV::PseudoCCADDW: NewOpc = RISCV::ADDW; break;
225bdd1243dSDimitry Andric case RISCV::PseudoCCSUBW: NewOpc = RISCV::SUBW; break;
2265f757f3fSDimitry Andric case RISCV::PseudoCCSLLW: NewOpc = RISCV::SLLW; break;
2275f757f3fSDimitry Andric case RISCV::PseudoCCSRLW: NewOpc = RISCV::SRLW; break;
2285f757f3fSDimitry Andric case RISCV::PseudoCCSRAW: NewOpc = RISCV::SRAW; break;
2295f757f3fSDimitry Andric case RISCV::PseudoCCADDIW: NewOpc = RISCV::ADDIW; break;
2305f757f3fSDimitry Andric case RISCV::PseudoCCSLLIW: NewOpc = RISCV::SLLIW; break;
2315f757f3fSDimitry Andric case RISCV::PseudoCCSRLIW: NewOpc = RISCV::SRLIW; break;
2325f757f3fSDimitry Andric case RISCV::PseudoCCSRAIW: NewOpc = RISCV::SRAIW; break;
2331db9f3b2SDimitry Andric case RISCV::PseudoCCANDN: NewOpc = RISCV::ANDN; break;
2341db9f3b2SDimitry Andric case RISCV::PseudoCCORN: NewOpc = RISCV::ORN; break;
2351db9f3b2SDimitry Andric case RISCV::PseudoCCXNOR: NewOpc = RISCV::XNOR; break;
236bdd1243dSDimitry Andric }
237bdd1243dSDimitry Andric BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg)
238bdd1243dSDimitry Andric .add(MI.getOperand(5))
239bdd1243dSDimitry Andric .add(MI.getOperand(6));
240bdd1243dSDimitry Andric }
2410b57cec5SDimitry Andric
242bdd1243dSDimitry Andric TrueBB->addSuccessor(MergeBB);
2430b57cec5SDimitry Andric
244bdd1243dSDimitry Andric MergeBB->splice(MergeBB->end(), &MBB, MI, MBB.end());
245bdd1243dSDimitry Andric MergeBB->transferSuccessors(&MBB);
2460b57cec5SDimitry Andric
247bdd1243dSDimitry Andric MBB.addSuccessor(TrueBB);
248bdd1243dSDimitry Andric MBB.addSuccessor(MergeBB);
2490b57cec5SDimitry Andric
2500b57cec5SDimitry Andric NextMBBI = MBB.end();
2510b57cec5SDimitry Andric MI.eraseFromParent();
252bdd1243dSDimitry Andric
253bdd1243dSDimitry Andric // Make sure live-ins are correctly attached to this new basic block.
254bdd1243dSDimitry Andric LivePhysRegs LiveRegs;
255bdd1243dSDimitry Andric computeAndAddLiveIns(LiveRegs, *TrueBB);
256bdd1243dSDimitry Andric computeAndAddLiveIns(LiveRegs, *MergeBB);
257bdd1243dSDimitry Andric
2580b57cec5SDimitry Andric return true;
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric
expandVSetVL(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)261e8d8bef9SDimitry Andric bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock &MBB,
262e8d8bef9SDimitry Andric MachineBasicBlock::iterator MBBI) {
263fe6060f1SDimitry Andric assert(MBBI->getNumExplicitOperands() == 3 && MBBI->getNumOperands() >= 5 &&
264fe6060f1SDimitry Andric "Unexpected instruction format");
265e8d8bef9SDimitry Andric
266e8d8bef9SDimitry Andric DebugLoc DL = MBBI->getDebugLoc();
267e8d8bef9SDimitry Andric
268d409305fSDimitry Andric assert((MBBI->getOpcode() == RISCV::PseudoVSETVLI ||
269349cc55cSDimitry Andric MBBI->getOpcode() == RISCV::PseudoVSETVLIX0 ||
270d409305fSDimitry Andric MBBI->getOpcode() == RISCV::PseudoVSETIVLI) &&
271e8d8bef9SDimitry Andric "Unexpected pseudo instruction");
272d409305fSDimitry Andric unsigned Opcode;
273349cc55cSDimitry Andric if (MBBI->getOpcode() == RISCV::PseudoVSETIVLI)
274d409305fSDimitry Andric Opcode = RISCV::VSETIVLI;
275349cc55cSDimitry Andric else
276349cc55cSDimitry Andric Opcode = RISCV::VSETVLI;
277d409305fSDimitry Andric const MCInstrDesc &Desc = TII->get(Opcode);
278e8d8bef9SDimitry Andric assert(Desc.getNumOperands() == 3 && "Unexpected instruction format");
279e8d8bef9SDimitry Andric
280e8d8bef9SDimitry Andric Register DstReg = MBBI->getOperand(0).getReg();
281e8d8bef9SDimitry Andric bool DstIsDead = MBBI->getOperand(0).isDead();
282e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, Desc)
283e8d8bef9SDimitry Andric .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))
284e8d8bef9SDimitry Andric .add(MBBI->getOperand(1)) // VL
285e8d8bef9SDimitry Andric .add(MBBI->getOperand(2)); // VType
286e8d8bef9SDimitry Andric
287e8d8bef9SDimitry Andric MBBI->eraseFromParent(); // The pseudo instruction is gone now.
288e8d8bef9SDimitry Andric return true;
289e8d8bef9SDimitry Andric }
290e8d8bef9SDimitry Andric
expandVMSET_VMCLR(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,unsigned Opcode)291e8d8bef9SDimitry Andric bool RISCVExpandPseudo::expandVMSET_VMCLR(MachineBasicBlock &MBB,
292e8d8bef9SDimitry Andric MachineBasicBlock::iterator MBBI,
293e8d8bef9SDimitry Andric unsigned Opcode) {
294e8d8bef9SDimitry Andric DebugLoc DL = MBBI->getDebugLoc();
295e8d8bef9SDimitry Andric Register DstReg = MBBI->getOperand(0).getReg();
296e8d8bef9SDimitry Andric const MCInstrDesc &Desc = TII->get(Opcode);
297e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, Desc, DstReg)
298e8d8bef9SDimitry Andric .addReg(DstReg, RegState::Undef)
299e8d8bef9SDimitry Andric .addReg(DstReg, RegState::Undef);
300e8d8bef9SDimitry Andric MBBI->eraseFromParent(); // The pseudo instruction is gone now.
301e8d8bef9SDimitry Andric return true;
302e8d8bef9SDimitry Andric }
303e8d8bef9SDimitry Andric
30406c3fb27SDimitry Andric // This function expands the PseudoRV32ZdinxSD for storing a double-precision
30506c3fb27SDimitry Andric // floating-point value into memory by generating an equivalent instruction
30606c3fb27SDimitry Andric // sequence for RV32.
expandRV32ZdinxStore(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)30706c3fb27SDimitry Andric bool RISCVExpandPseudo::expandRV32ZdinxStore(MachineBasicBlock &MBB,
30806c3fb27SDimitry Andric MachineBasicBlock::iterator MBBI) {
30906c3fb27SDimitry Andric DebugLoc DL = MBBI->getDebugLoc();
31006c3fb27SDimitry Andric const TargetRegisterInfo *TRI = STI->getRegisterInfo();
311297eecfbSDimitry Andric Register Lo =
312297eecfbSDimitry Andric TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_even);
313297eecfbSDimitry Andric Register Hi =
314297eecfbSDimitry Andric TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd);
31506c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
31606c3fb27SDimitry Andric .addReg(Lo, getKillRegState(MBBI->getOperand(0).isKill()))
31706c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg())
31806c3fb27SDimitry Andric .add(MBBI->getOperand(2));
31906c3fb27SDimitry Andric if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {
320*3a079333SDimitry Andric // FIXME: Zdinx RV32 can not work on unaligned scalar memory.
321*3a079333SDimitry Andric assert(!STI->hasFastUnalignedAccess() &&
322*3a079333SDimitry Andric !STI->enableUnalignedScalarMem());
32306c3fb27SDimitry Andric
32406c3fb27SDimitry Andric assert(MBBI->getOperand(2).getOffset() % 8 == 0);
32506c3fb27SDimitry Andric MBBI->getOperand(2).setOffset(MBBI->getOperand(2).getOffset() + 4);
32606c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
32706c3fb27SDimitry Andric .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))
32806c3fb27SDimitry Andric .add(MBBI->getOperand(1))
32906c3fb27SDimitry Andric .add(MBBI->getOperand(2));
33006c3fb27SDimitry Andric } else {
33106c3fb27SDimitry Andric assert(isInt<12>(MBBI->getOperand(2).getImm() + 4));
33206c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
33306c3fb27SDimitry Andric .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))
33406c3fb27SDimitry Andric .add(MBBI->getOperand(1))
33506c3fb27SDimitry Andric .addImm(MBBI->getOperand(2).getImm() + 4);
33606c3fb27SDimitry Andric }
33706c3fb27SDimitry Andric MBBI->eraseFromParent();
33806c3fb27SDimitry Andric return true;
33906c3fb27SDimitry Andric }
34006c3fb27SDimitry Andric
34106c3fb27SDimitry Andric // This function expands PseudoRV32ZdinxLoad for loading a double-precision
34206c3fb27SDimitry Andric // floating-point value from memory into an equivalent instruction sequence for
34306c3fb27SDimitry Andric // RV32.
expandRV32ZdinxLoad(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)34406c3fb27SDimitry Andric bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB,
34506c3fb27SDimitry Andric MachineBasicBlock::iterator MBBI) {
34606c3fb27SDimitry Andric DebugLoc DL = MBBI->getDebugLoc();
34706c3fb27SDimitry Andric const TargetRegisterInfo *TRI = STI->getRegisterInfo();
348297eecfbSDimitry Andric Register Lo =
349297eecfbSDimitry Andric TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_even);
350297eecfbSDimitry Andric Register Hi =
351297eecfbSDimitry Andric TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd);
35206c3fb27SDimitry Andric
35306c3fb27SDimitry Andric // If the register of operand 1 is equal to the Lo register, then swap the
35406c3fb27SDimitry Andric // order of loading the Lo and Hi statements.
35506c3fb27SDimitry Andric bool IsOp1EqualToLo = Lo == MBBI->getOperand(1).getReg();
35606c3fb27SDimitry Andric // Order: Lo, Hi
35706c3fb27SDimitry Andric if (!IsOp1EqualToLo) {
35806c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)
35906c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg())
36006c3fb27SDimitry Andric .add(MBBI->getOperand(2));
36106c3fb27SDimitry Andric }
36206c3fb27SDimitry Andric
36306c3fb27SDimitry Andric if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {
36406c3fb27SDimitry Andric auto Offset = MBBI->getOperand(2).getOffset();
36506c3fb27SDimitry Andric assert(MBBI->getOperand(2).getOffset() % 8 == 0);
36606c3fb27SDimitry Andric MBBI->getOperand(2).setOffset(Offset + 4);
36706c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)
36806c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg())
36906c3fb27SDimitry Andric .add(MBBI->getOperand(2));
37006c3fb27SDimitry Andric MBBI->getOperand(2).setOffset(Offset);
37106c3fb27SDimitry Andric } else {
37206c3fb27SDimitry Andric assert(isInt<12>(MBBI->getOperand(2).getImm() + 4));
37306c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)
37406c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg())
37506c3fb27SDimitry Andric .addImm(MBBI->getOperand(2).getImm() + 4);
37606c3fb27SDimitry Andric }
37706c3fb27SDimitry Andric
37806c3fb27SDimitry Andric // Order: Hi, Lo
37906c3fb27SDimitry Andric if (IsOp1EqualToLo) {
38006c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)
38106c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg())
38206c3fb27SDimitry Andric .add(MBBI->getOperand(2));
38306c3fb27SDimitry Andric }
38406c3fb27SDimitry Andric
38506c3fb27SDimitry Andric MBBI->eraseFromParent();
38606c3fb27SDimitry Andric return true;
38706c3fb27SDimitry Andric }
38806c3fb27SDimitry Andric
389bdd1243dSDimitry Andric class RISCVPreRAExpandPseudo : public MachineFunctionPass {
390bdd1243dSDimitry Andric public:
39106c3fb27SDimitry Andric const RISCVSubtarget *STI;
392bdd1243dSDimitry Andric const RISCVInstrInfo *TII;
393bdd1243dSDimitry Andric static char ID;
394fe6060f1SDimitry Andric
RISCVPreRAExpandPseudo()3955f757f3fSDimitry Andric RISCVPreRAExpandPseudo() : MachineFunctionPass(ID) {}
396bdd1243dSDimitry Andric
397bdd1243dSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
398bdd1243dSDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const399bdd1243dSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
400bdd1243dSDimitry Andric AU.setPreservesCFG();
401bdd1243dSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
402bdd1243dSDimitry Andric }
getPassName() const403bdd1243dSDimitry Andric StringRef getPassName() const override {
404bdd1243dSDimitry Andric return RISCV_PRERA_EXPAND_PSEUDO_NAME;
405bdd1243dSDimitry Andric }
406bdd1243dSDimitry Andric
407bdd1243dSDimitry Andric private:
408bdd1243dSDimitry Andric bool expandMBB(MachineBasicBlock &MBB);
409bdd1243dSDimitry Andric bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
410bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
411bdd1243dSDimitry Andric bool expandAuipcInstPair(MachineBasicBlock &MBB,
412bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
413bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI,
414bdd1243dSDimitry Andric unsigned FlagsHi, unsigned SecondOpcode);
415bdd1243dSDimitry Andric bool expandLoadLocalAddress(MachineBasicBlock &MBB,
416bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
417bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
41806c3fb27SDimitry Andric bool expandLoadGlobalAddress(MachineBasicBlock &MBB,
419bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
420bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
421bdd1243dSDimitry Andric bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,
422bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
423bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
424bdd1243dSDimitry Andric bool expandLoadTLSGDAddress(MachineBasicBlock &MBB,
425bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
426bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
4277a6dacacSDimitry Andric bool expandLoadTLSDescAddress(MachineBasicBlock &MBB,
4287a6dacacSDimitry Andric MachineBasicBlock::iterator MBBI,
4297a6dacacSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
4307a6dacacSDimitry Andric
43106c3fb27SDimitry Andric #ifndef NDEBUG
getInstSizeInBytes(const MachineFunction & MF) const43206c3fb27SDimitry Andric unsigned getInstSizeInBytes(const MachineFunction &MF) const {
43306c3fb27SDimitry Andric unsigned Size = 0;
43406c3fb27SDimitry Andric for (auto &MBB : MF)
43506c3fb27SDimitry Andric for (auto &MI : MBB)
43606c3fb27SDimitry Andric Size += TII->getInstSizeInBytes(MI);
43706c3fb27SDimitry Andric return Size;
43806c3fb27SDimitry Andric }
43906c3fb27SDimitry Andric #endif
440bdd1243dSDimitry Andric };
441bdd1243dSDimitry Andric
442bdd1243dSDimitry Andric char RISCVPreRAExpandPseudo::ID = 0;
443bdd1243dSDimitry Andric
runOnMachineFunction(MachineFunction & MF)444bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
44506c3fb27SDimitry Andric STI = &MF.getSubtarget<RISCVSubtarget>();
44606c3fb27SDimitry Andric TII = STI->getInstrInfo();
44706c3fb27SDimitry Andric
44806c3fb27SDimitry Andric #ifndef NDEBUG
44906c3fb27SDimitry Andric const unsigned OldSize = getInstSizeInBytes(MF);
45006c3fb27SDimitry Andric #endif
45106c3fb27SDimitry Andric
452bdd1243dSDimitry Andric bool Modified = false;
453bdd1243dSDimitry Andric for (auto &MBB : MF)
454bdd1243dSDimitry Andric Modified |= expandMBB(MBB);
45506c3fb27SDimitry Andric
45606c3fb27SDimitry Andric #ifndef NDEBUG
45706c3fb27SDimitry Andric const unsigned NewSize = getInstSizeInBytes(MF);
45806c3fb27SDimitry Andric assert(OldSize >= NewSize);
45906c3fb27SDimitry Andric #endif
460bdd1243dSDimitry Andric return Modified;
461bdd1243dSDimitry Andric }
462bdd1243dSDimitry Andric
expandMBB(MachineBasicBlock & MBB)463bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
464bdd1243dSDimitry Andric bool Modified = false;
465bdd1243dSDimitry Andric
466bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
467bdd1243dSDimitry Andric while (MBBI != E) {
468bdd1243dSDimitry Andric MachineBasicBlock::iterator NMBBI = std::next(MBBI);
469bdd1243dSDimitry Andric Modified |= expandMI(MBB, MBBI, NMBBI);
470bdd1243dSDimitry Andric MBBI = NMBBI;
471bdd1243dSDimitry Andric }
472bdd1243dSDimitry Andric
473bdd1243dSDimitry Andric return Modified;
474bdd1243dSDimitry Andric }
475bdd1243dSDimitry Andric
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)476bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandMI(MachineBasicBlock &MBB,
477bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
478bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
479bdd1243dSDimitry Andric
480bdd1243dSDimitry Andric switch (MBBI->getOpcode()) {
481bdd1243dSDimitry Andric case RISCV::PseudoLLA:
482bdd1243dSDimitry Andric return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
48306c3fb27SDimitry Andric case RISCV::PseudoLGA:
48406c3fb27SDimitry Andric return expandLoadGlobalAddress(MBB, MBBI, NextMBBI);
485bdd1243dSDimitry Andric case RISCV::PseudoLA_TLS_IE:
486bdd1243dSDimitry Andric return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);
487bdd1243dSDimitry Andric case RISCV::PseudoLA_TLS_GD:
488bdd1243dSDimitry Andric return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI);
4897a6dacacSDimitry Andric case RISCV::PseudoLA_TLSDESC:
4907a6dacacSDimitry Andric return expandLoadTLSDescAddress(MBB, MBBI, NextMBBI);
491bdd1243dSDimitry Andric }
492bdd1243dSDimitry Andric return false;
493bdd1243dSDimitry Andric }
494bdd1243dSDimitry Andric
expandAuipcInstPair(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI,unsigned FlagsHi,unsigned SecondOpcode)495bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandAuipcInstPair(
496bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
497bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
498bdd1243dSDimitry Andric unsigned SecondOpcode) {
499bdd1243dSDimitry Andric MachineFunction *MF = MBB.getParent();
500bdd1243dSDimitry Andric MachineInstr &MI = *MBBI;
501bdd1243dSDimitry Andric DebugLoc DL = MI.getDebugLoc();
502bdd1243dSDimitry Andric
503bdd1243dSDimitry Andric Register DestReg = MI.getOperand(0).getReg();
504bdd1243dSDimitry Andric Register ScratchReg =
505bdd1243dSDimitry Andric MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
506bdd1243dSDimitry Andric
507bdd1243dSDimitry Andric MachineOperand &Symbol = MI.getOperand(1);
508bdd1243dSDimitry Andric Symbol.setTargetFlags(FlagsHi);
509bdd1243dSDimitry Andric MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("pcrel_hi");
510bdd1243dSDimitry Andric
511bdd1243dSDimitry Andric MachineInstr *MIAUIPC =
512bdd1243dSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);
513bdd1243dSDimitry Andric MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);
514bdd1243dSDimitry Andric
515bdd1243dSDimitry Andric MachineInstr *SecondMI =
516bdd1243dSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
517bdd1243dSDimitry Andric .addReg(ScratchReg)
518bdd1243dSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_PCREL_LO);
519bdd1243dSDimitry Andric
520bdd1243dSDimitry Andric if (MI.hasOneMemOperand())
521bdd1243dSDimitry Andric SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
522bdd1243dSDimitry Andric
523bdd1243dSDimitry Andric MI.eraseFromParent();
524fe6060f1SDimitry Andric return true;
525fe6060f1SDimitry Andric }
526fe6060f1SDimitry Andric
expandLoadLocalAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)527bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadLocalAddress(
528bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
529bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
530bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI,
531bdd1243dSDimitry Andric RISCV::ADDI);
532fe6060f1SDimitry Andric }
533bdd1243dSDimitry Andric
expandLoadGlobalAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)53406c3fb27SDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadGlobalAddress(
535bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
536bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
53706c3fb27SDimitry Andric unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW;
538bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_GOT_HI,
539bdd1243dSDimitry Andric SecondOpcode);
540bdd1243dSDimitry Andric }
541bdd1243dSDimitry Andric
expandLoadTLSIEAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)542bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadTLSIEAddress(
543bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
544bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
54506c3fb27SDimitry Andric unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW;
546bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,
547bdd1243dSDimitry Andric SecondOpcode);
548bdd1243dSDimitry Andric }
549bdd1243dSDimitry Andric
expandLoadTLSGDAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)550bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadTLSGDAddress(
551bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
552bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
553bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI,
554bdd1243dSDimitry Andric RISCV::ADDI);
555fe6060f1SDimitry Andric }
556fe6060f1SDimitry Andric
expandLoadTLSDescAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)5577a6dacacSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadTLSDescAddress(
5587a6dacacSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
5597a6dacacSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
5607a6dacacSDimitry Andric MachineFunction *MF = MBB.getParent();
5617a6dacacSDimitry Andric MachineInstr &MI = *MBBI;
5627a6dacacSDimitry Andric DebugLoc DL = MI.getDebugLoc();
5637a6dacacSDimitry Andric
5647a6dacacSDimitry Andric const auto &STI = MF->getSubtarget<RISCVSubtarget>();
5657a6dacacSDimitry Andric unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
5667a6dacacSDimitry Andric
5677a6dacacSDimitry Andric Register FinalReg = MI.getOperand(0).getReg();
5687a6dacacSDimitry Andric Register DestReg =
5697a6dacacSDimitry Andric MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
5707a6dacacSDimitry Andric Register ScratchReg =
5717a6dacacSDimitry Andric MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
5727a6dacacSDimitry Andric
5737a6dacacSDimitry Andric MachineOperand &Symbol = MI.getOperand(1);
5747a6dacacSDimitry Andric Symbol.setTargetFlags(RISCVII::MO_TLSDESC_HI);
5757a6dacacSDimitry Andric MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("tlsdesc_hi");
5767a6dacacSDimitry Andric
5777a6dacacSDimitry Andric MachineInstr *MIAUIPC =
5787a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);
5797a6dacacSDimitry Andric MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);
5807a6dacacSDimitry Andric
5817a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
5827a6dacacSDimitry Andric .addReg(ScratchReg)
5837a6dacacSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_LOAD_LO);
5847a6dacacSDimitry Andric
5857a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), RISCV::X10)
5867a6dacacSDimitry Andric .addReg(ScratchReg)
5877a6dacacSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_ADD_LO);
5887a6dacacSDimitry Andric
5897a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::PseudoTLSDESCCall), RISCV::X5)
5907a6dacacSDimitry Andric .addReg(DestReg)
5917a6dacacSDimitry Andric .addImm(0)
5927a6dacacSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_CALL);
5937a6dacacSDimitry Andric
5947a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADD), FinalReg)
5957a6dacacSDimitry Andric .addReg(RISCV::X10)
5967a6dacacSDimitry Andric .addReg(RISCV::X4);
5977a6dacacSDimitry Andric
5987a6dacacSDimitry Andric MI.eraseFromParent();
5997a6dacacSDimitry Andric return true;
6007a6dacacSDimitry Andric }
6017a6dacacSDimitry Andric
6020b57cec5SDimitry Andric } // end of anonymous namespace
6030b57cec5SDimitry Andric
6040b57cec5SDimitry Andric INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
6050b57cec5SDimitry Andric RISCV_EXPAND_PSEUDO_NAME, false, false)
606bdd1243dSDimitry Andric
607bdd1243dSDimitry Andric INITIALIZE_PASS(RISCVPreRAExpandPseudo, "riscv-prera-expand-pseudo",
608bdd1243dSDimitry Andric RISCV_PRERA_EXPAND_PSEUDO_NAME, false, false)
609bdd1243dSDimitry Andric
6100b57cec5SDimitry Andric namespace llvm {
6110b57cec5SDimitry Andric
createRISCVExpandPseudoPass()6120b57cec5SDimitry Andric FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
createRISCVPreRAExpandPseudoPass()613bdd1243dSDimitry Andric FunctionPass *createRISCVPreRAExpandPseudoPass() { return new RISCVPreRAExpandPseudo(); }
6140b57cec5SDimitry Andric
6150b57cec5SDimitry Andric } // end of namespace llvm
616