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);
315*0fca6ea1SDimitry Andric
316*0fca6ea1SDimitry Andric assert(MBBI->hasOneMemOperand() && "Expected mem operand");
317*0fca6ea1SDimitry Andric MachineMemOperand *OldMMO = MBBI->memoperands().front();
318*0fca6ea1SDimitry Andric MachineFunction *MF = MBB.getParent();
319*0fca6ea1SDimitry Andric MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4);
320*0fca6ea1SDimitry Andric MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4);
321*0fca6ea1SDimitry Andric
32206c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
32306c3fb27SDimitry Andric .addReg(Lo, getKillRegState(MBBI->getOperand(0).isKill()))
32406c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg())
325*0fca6ea1SDimitry Andric .add(MBBI->getOperand(2))
326*0fca6ea1SDimitry Andric .setMemRefs(MMOLo);
327*0fca6ea1SDimitry Andric
32806c3fb27SDimitry Andric if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {
3293a079333SDimitry Andric // FIXME: Zdinx RV32 can not work on unaligned scalar memory.
330*0fca6ea1SDimitry Andric assert(!STI->enableUnalignedScalarMem());
33106c3fb27SDimitry Andric
33206c3fb27SDimitry Andric assert(MBBI->getOperand(2).getOffset() % 8 == 0);
33306c3fb27SDimitry Andric MBBI->getOperand(2).setOffset(MBBI->getOperand(2).getOffset() + 4);
33406c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
33506c3fb27SDimitry Andric .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))
33606c3fb27SDimitry Andric .add(MBBI->getOperand(1))
337*0fca6ea1SDimitry Andric .add(MBBI->getOperand(2))
338*0fca6ea1SDimitry Andric .setMemRefs(MMOHi);
33906c3fb27SDimitry Andric } else {
34006c3fb27SDimitry Andric assert(isInt<12>(MBBI->getOperand(2).getImm() + 4));
34106c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))
34206c3fb27SDimitry Andric .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))
34306c3fb27SDimitry Andric .add(MBBI->getOperand(1))
344*0fca6ea1SDimitry Andric .addImm(MBBI->getOperand(2).getImm() + 4)
345*0fca6ea1SDimitry Andric .setMemRefs(MMOHi);
34606c3fb27SDimitry Andric }
34706c3fb27SDimitry Andric MBBI->eraseFromParent();
34806c3fb27SDimitry Andric return true;
34906c3fb27SDimitry Andric }
35006c3fb27SDimitry Andric
35106c3fb27SDimitry Andric // This function expands PseudoRV32ZdinxLoad for loading a double-precision
35206c3fb27SDimitry Andric // floating-point value from memory into an equivalent instruction sequence for
35306c3fb27SDimitry Andric // RV32.
expandRV32ZdinxLoad(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI)35406c3fb27SDimitry Andric bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB,
35506c3fb27SDimitry Andric MachineBasicBlock::iterator MBBI) {
35606c3fb27SDimitry Andric DebugLoc DL = MBBI->getDebugLoc();
35706c3fb27SDimitry Andric const TargetRegisterInfo *TRI = STI->getRegisterInfo();
358297eecfbSDimitry Andric Register Lo =
359297eecfbSDimitry Andric TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_even);
360297eecfbSDimitry Andric Register Hi =
361297eecfbSDimitry Andric TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd);
36206c3fb27SDimitry Andric
363*0fca6ea1SDimitry Andric assert(MBBI->hasOneMemOperand() && "Expected mem operand");
364*0fca6ea1SDimitry Andric MachineMemOperand *OldMMO = MBBI->memoperands().front();
365*0fca6ea1SDimitry Andric MachineFunction *MF = MBB.getParent();
366*0fca6ea1SDimitry Andric MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4);
367*0fca6ea1SDimitry Andric MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4);
368*0fca6ea1SDimitry Andric
36906c3fb27SDimitry Andric // If the register of operand 1 is equal to the Lo register, then swap the
37006c3fb27SDimitry Andric // order of loading the Lo and Hi statements.
37106c3fb27SDimitry Andric bool IsOp1EqualToLo = Lo == MBBI->getOperand(1).getReg();
37206c3fb27SDimitry Andric // Order: Lo, Hi
37306c3fb27SDimitry Andric if (!IsOp1EqualToLo) {
37406c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)
37506c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg())
376*0fca6ea1SDimitry Andric .add(MBBI->getOperand(2))
377*0fca6ea1SDimitry Andric .setMemRefs(MMOLo);
37806c3fb27SDimitry Andric }
37906c3fb27SDimitry Andric
38006c3fb27SDimitry Andric if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {
38106c3fb27SDimitry Andric auto Offset = MBBI->getOperand(2).getOffset();
38206c3fb27SDimitry Andric assert(MBBI->getOperand(2).getOffset() % 8 == 0);
38306c3fb27SDimitry Andric MBBI->getOperand(2).setOffset(Offset + 4);
38406c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)
38506c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg())
386*0fca6ea1SDimitry Andric .add(MBBI->getOperand(2))
387*0fca6ea1SDimitry Andric .setMemRefs(MMOHi);
38806c3fb27SDimitry Andric MBBI->getOperand(2).setOffset(Offset);
38906c3fb27SDimitry Andric } else {
39006c3fb27SDimitry Andric assert(isInt<12>(MBBI->getOperand(2).getImm() + 4));
39106c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)
39206c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg())
393*0fca6ea1SDimitry Andric .addImm(MBBI->getOperand(2).getImm() + 4)
394*0fca6ea1SDimitry Andric .setMemRefs(MMOHi);
39506c3fb27SDimitry Andric }
39606c3fb27SDimitry Andric
39706c3fb27SDimitry Andric // Order: Hi, Lo
39806c3fb27SDimitry Andric if (IsOp1EqualToLo) {
39906c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)
40006c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg())
401*0fca6ea1SDimitry Andric .add(MBBI->getOperand(2))
402*0fca6ea1SDimitry Andric .setMemRefs(MMOLo);
40306c3fb27SDimitry Andric }
40406c3fb27SDimitry Andric
40506c3fb27SDimitry Andric MBBI->eraseFromParent();
40606c3fb27SDimitry Andric return true;
40706c3fb27SDimitry Andric }
40806c3fb27SDimitry Andric
409bdd1243dSDimitry Andric class RISCVPreRAExpandPseudo : public MachineFunctionPass {
410bdd1243dSDimitry Andric public:
41106c3fb27SDimitry Andric const RISCVSubtarget *STI;
412bdd1243dSDimitry Andric const RISCVInstrInfo *TII;
413bdd1243dSDimitry Andric static char ID;
414fe6060f1SDimitry Andric
RISCVPreRAExpandPseudo()4155f757f3fSDimitry Andric RISCVPreRAExpandPseudo() : MachineFunctionPass(ID) {}
416bdd1243dSDimitry Andric
417bdd1243dSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override;
418bdd1243dSDimitry Andric
getAnalysisUsage(AnalysisUsage & AU) const419bdd1243dSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override {
420bdd1243dSDimitry Andric AU.setPreservesCFG();
421bdd1243dSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU);
422bdd1243dSDimitry Andric }
getPassName() const423bdd1243dSDimitry Andric StringRef getPassName() const override {
424bdd1243dSDimitry Andric return RISCV_PRERA_EXPAND_PSEUDO_NAME;
425bdd1243dSDimitry Andric }
426bdd1243dSDimitry Andric
427bdd1243dSDimitry Andric private:
428bdd1243dSDimitry Andric bool expandMBB(MachineBasicBlock &MBB);
429bdd1243dSDimitry Andric bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
430bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
431bdd1243dSDimitry Andric bool expandAuipcInstPair(MachineBasicBlock &MBB,
432bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
433bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI,
434bdd1243dSDimitry Andric unsigned FlagsHi, unsigned SecondOpcode);
435bdd1243dSDimitry Andric bool expandLoadLocalAddress(MachineBasicBlock &MBB,
436bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
437bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
43806c3fb27SDimitry Andric bool expandLoadGlobalAddress(MachineBasicBlock &MBB,
439bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
440bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
441bdd1243dSDimitry Andric bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,
442bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
443bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
444bdd1243dSDimitry Andric bool expandLoadTLSGDAddress(MachineBasicBlock &MBB,
445bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
446bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
4477a6dacacSDimitry Andric bool expandLoadTLSDescAddress(MachineBasicBlock &MBB,
4487a6dacacSDimitry Andric MachineBasicBlock::iterator MBBI,
4497a6dacacSDimitry Andric MachineBasicBlock::iterator &NextMBBI);
4507a6dacacSDimitry Andric
45106c3fb27SDimitry Andric #ifndef NDEBUG
getInstSizeInBytes(const MachineFunction & MF) const45206c3fb27SDimitry Andric unsigned getInstSizeInBytes(const MachineFunction &MF) const {
45306c3fb27SDimitry Andric unsigned Size = 0;
45406c3fb27SDimitry Andric for (auto &MBB : MF)
45506c3fb27SDimitry Andric for (auto &MI : MBB)
45606c3fb27SDimitry Andric Size += TII->getInstSizeInBytes(MI);
45706c3fb27SDimitry Andric return Size;
45806c3fb27SDimitry Andric }
45906c3fb27SDimitry Andric #endif
460bdd1243dSDimitry Andric };
461bdd1243dSDimitry Andric
462bdd1243dSDimitry Andric char RISCVPreRAExpandPseudo::ID = 0;
463bdd1243dSDimitry Andric
runOnMachineFunction(MachineFunction & MF)464bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {
46506c3fb27SDimitry Andric STI = &MF.getSubtarget<RISCVSubtarget>();
46606c3fb27SDimitry Andric TII = STI->getInstrInfo();
46706c3fb27SDimitry Andric
46806c3fb27SDimitry Andric #ifndef NDEBUG
46906c3fb27SDimitry Andric const unsigned OldSize = getInstSizeInBytes(MF);
47006c3fb27SDimitry Andric #endif
47106c3fb27SDimitry Andric
472bdd1243dSDimitry Andric bool Modified = false;
473bdd1243dSDimitry Andric for (auto &MBB : MF)
474bdd1243dSDimitry Andric Modified |= expandMBB(MBB);
47506c3fb27SDimitry Andric
47606c3fb27SDimitry Andric #ifndef NDEBUG
47706c3fb27SDimitry Andric const unsigned NewSize = getInstSizeInBytes(MF);
47806c3fb27SDimitry Andric assert(OldSize >= NewSize);
47906c3fb27SDimitry Andric #endif
480bdd1243dSDimitry Andric return Modified;
481bdd1243dSDimitry Andric }
482bdd1243dSDimitry Andric
expandMBB(MachineBasicBlock & MBB)483bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {
484bdd1243dSDimitry Andric bool Modified = false;
485bdd1243dSDimitry Andric
486bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();
487bdd1243dSDimitry Andric while (MBBI != E) {
488bdd1243dSDimitry Andric MachineBasicBlock::iterator NMBBI = std::next(MBBI);
489bdd1243dSDimitry Andric Modified |= expandMI(MBB, MBBI, NMBBI);
490bdd1243dSDimitry Andric MBBI = NMBBI;
491bdd1243dSDimitry Andric }
492bdd1243dSDimitry Andric
493bdd1243dSDimitry Andric return Modified;
494bdd1243dSDimitry Andric }
495bdd1243dSDimitry Andric
expandMI(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)496bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandMI(MachineBasicBlock &MBB,
497bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI,
498bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
499bdd1243dSDimitry Andric
500bdd1243dSDimitry Andric switch (MBBI->getOpcode()) {
501bdd1243dSDimitry Andric case RISCV::PseudoLLA:
502bdd1243dSDimitry Andric return expandLoadLocalAddress(MBB, MBBI, NextMBBI);
50306c3fb27SDimitry Andric case RISCV::PseudoLGA:
50406c3fb27SDimitry Andric return expandLoadGlobalAddress(MBB, MBBI, NextMBBI);
505bdd1243dSDimitry Andric case RISCV::PseudoLA_TLS_IE:
506bdd1243dSDimitry Andric return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);
507bdd1243dSDimitry Andric case RISCV::PseudoLA_TLS_GD:
508bdd1243dSDimitry Andric return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI);
5097a6dacacSDimitry Andric case RISCV::PseudoLA_TLSDESC:
5107a6dacacSDimitry Andric return expandLoadTLSDescAddress(MBB, MBBI, NextMBBI);
511bdd1243dSDimitry Andric }
512bdd1243dSDimitry Andric return false;
513bdd1243dSDimitry Andric }
514bdd1243dSDimitry Andric
expandAuipcInstPair(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI,unsigned FlagsHi,unsigned SecondOpcode)515bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandAuipcInstPair(
516bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
517bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,
518bdd1243dSDimitry Andric unsigned SecondOpcode) {
519bdd1243dSDimitry Andric MachineFunction *MF = MBB.getParent();
520bdd1243dSDimitry Andric MachineInstr &MI = *MBBI;
521bdd1243dSDimitry Andric DebugLoc DL = MI.getDebugLoc();
522bdd1243dSDimitry Andric
523bdd1243dSDimitry Andric Register DestReg = MI.getOperand(0).getReg();
524bdd1243dSDimitry Andric Register ScratchReg =
525bdd1243dSDimitry Andric MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
526bdd1243dSDimitry Andric
527bdd1243dSDimitry Andric MachineOperand &Symbol = MI.getOperand(1);
528bdd1243dSDimitry Andric Symbol.setTargetFlags(FlagsHi);
529bdd1243dSDimitry Andric MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("pcrel_hi");
530bdd1243dSDimitry Andric
531bdd1243dSDimitry Andric MachineInstr *MIAUIPC =
532bdd1243dSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);
533bdd1243dSDimitry Andric MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);
534bdd1243dSDimitry Andric
535bdd1243dSDimitry Andric MachineInstr *SecondMI =
536bdd1243dSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
537bdd1243dSDimitry Andric .addReg(ScratchReg)
538bdd1243dSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_PCREL_LO);
539bdd1243dSDimitry Andric
540bdd1243dSDimitry Andric if (MI.hasOneMemOperand())
541bdd1243dSDimitry Andric SecondMI->addMemOperand(*MF, *MI.memoperands_begin());
542bdd1243dSDimitry Andric
543bdd1243dSDimitry Andric MI.eraseFromParent();
544fe6060f1SDimitry Andric return true;
545fe6060f1SDimitry Andric }
546fe6060f1SDimitry Andric
expandLoadLocalAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)547bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadLocalAddress(
548bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
549bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
550bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI,
551bdd1243dSDimitry Andric RISCV::ADDI);
552fe6060f1SDimitry Andric }
553bdd1243dSDimitry Andric
expandLoadGlobalAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)55406c3fb27SDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadGlobalAddress(
555bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
556bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
55706c3fb27SDimitry Andric unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW;
558bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_GOT_HI,
559bdd1243dSDimitry Andric SecondOpcode);
560bdd1243dSDimitry Andric }
561bdd1243dSDimitry Andric
expandLoadTLSIEAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)562bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadTLSIEAddress(
563bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
564bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
56506c3fb27SDimitry Andric unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW;
566bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,
567bdd1243dSDimitry Andric SecondOpcode);
568bdd1243dSDimitry Andric }
569bdd1243dSDimitry Andric
expandLoadTLSGDAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)570bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadTLSGDAddress(
571bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
572bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
573bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI,
574bdd1243dSDimitry Andric RISCV::ADDI);
575fe6060f1SDimitry Andric }
576fe6060f1SDimitry Andric
expandLoadTLSDescAddress(MachineBasicBlock & MBB,MachineBasicBlock::iterator MBBI,MachineBasicBlock::iterator & NextMBBI)5777a6dacacSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadTLSDescAddress(
5787a6dacacSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
5797a6dacacSDimitry Andric MachineBasicBlock::iterator &NextMBBI) {
5807a6dacacSDimitry Andric MachineFunction *MF = MBB.getParent();
5817a6dacacSDimitry Andric MachineInstr &MI = *MBBI;
5827a6dacacSDimitry Andric DebugLoc DL = MI.getDebugLoc();
5837a6dacacSDimitry Andric
5847a6dacacSDimitry Andric const auto &STI = MF->getSubtarget<RISCVSubtarget>();
5857a6dacacSDimitry Andric unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;
5867a6dacacSDimitry Andric
5877a6dacacSDimitry Andric Register FinalReg = MI.getOperand(0).getReg();
5887a6dacacSDimitry Andric Register DestReg =
5897a6dacacSDimitry Andric MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
5907a6dacacSDimitry Andric Register ScratchReg =
5917a6dacacSDimitry Andric MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);
5927a6dacacSDimitry Andric
5937a6dacacSDimitry Andric MachineOperand &Symbol = MI.getOperand(1);
5947a6dacacSDimitry Andric Symbol.setTargetFlags(RISCVII::MO_TLSDESC_HI);
5957a6dacacSDimitry Andric MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("tlsdesc_hi");
5967a6dacacSDimitry Andric
5977a6dacacSDimitry Andric MachineInstr *MIAUIPC =
5987a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);
5997a6dacacSDimitry Andric MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);
6007a6dacacSDimitry Andric
6017a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)
6027a6dacacSDimitry Andric .addReg(ScratchReg)
6037a6dacacSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_LOAD_LO);
6047a6dacacSDimitry Andric
6057a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), RISCV::X10)
6067a6dacacSDimitry Andric .addReg(ScratchReg)
6077a6dacacSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_ADD_LO);
6087a6dacacSDimitry Andric
6097a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::PseudoTLSDESCCall), RISCV::X5)
6107a6dacacSDimitry Andric .addReg(DestReg)
6117a6dacacSDimitry Andric .addImm(0)
6127a6dacacSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_CALL);
6137a6dacacSDimitry Andric
6147a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADD), FinalReg)
6157a6dacacSDimitry Andric .addReg(RISCV::X10)
6167a6dacacSDimitry Andric .addReg(RISCV::X4);
6177a6dacacSDimitry Andric
6187a6dacacSDimitry Andric MI.eraseFromParent();
6197a6dacacSDimitry Andric return true;
6207a6dacacSDimitry Andric }
6217a6dacacSDimitry Andric
6220b57cec5SDimitry Andric } // end of anonymous namespace
6230b57cec5SDimitry Andric
6240b57cec5SDimitry Andric INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",
6250b57cec5SDimitry Andric RISCV_EXPAND_PSEUDO_NAME, false, false)
626bdd1243dSDimitry Andric
627bdd1243dSDimitry Andric INITIALIZE_PASS(RISCVPreRAExpandPseudo, "riscv-prera-expand-pseudo",
628bdd1243dSDimitry Andric RISCV_PRERA_EXPAND_PSEUDO_NAME, false, false)
629bdd1243dSDimitry Andric
6300b57cec5SDimitry Andric namespace llvm {
6310b57cec5SDimitry Andric
createRISCVExpandPseudoPass()6320b57cec5SDimitry Andric FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }
createRISCVPreRAExpandPseudoPass()633bdd1243dSDimitry Andric FunctionPass *createRISCVPreRAExpandPseudoPass() { return new RISCVPreRAExpandPseudo(); }
6340b57cec5SDimitry Andric
6350b57cec5SDimitry Andric } // end of namespace llvm
636