Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/RISCVExpandPseudoInsts.cpp
35266 views
//===-- RISCVExpandPseudoInsts.cpp - Expand pseudo instructions -----------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file contains a pass that expands pseudo instructions into target9// instructions. This pass should be run after register allocation but before10// the post-regalloc scheduling pass.11//12//===----------------------------------------------------------------------===//1314#include "RISCV.h"15#include "RISCVInstrInfo.h"16#include "RISCVTargetMachine.h"1718#include "llvm/CodeGen/LivePhysRegs.h"19#include "llvm/CodeGen/MachineFunctionPass.h"20#include "llvm/CodeGen/MachineInstrBuilder.h"21#include "llvm/MC/MCContext.h"2223using namespace llvm;2425#define RISCV_EXPAND_PSEUDO_NAME "RISC-V pseudo instruction expansion pass"26#define RISCV_PRERA_EXPAND_PSEUDO_NAME "RISC-V Pre-RA pseudo instruction expansion pass"2728namespace {2930class RISCVExpandPseudo : public MachineFunctionPass {31public:32const RISCVSubtarget *STI;33const RISCVInstrInfo *TII;34static char ID;3536RISCVExpandPseudo() : MachineFunctionPass(ID) {}3738bool runOnMachineFunction(MachineFunction &MF) override;3940StringRef getPassName() const override { return RISCV_EXPAND_PSEUDO_NAME; }4142private:43bool expandMBB(MachineBasicBlock &MBB);44bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,45MachineBasicBlock::iterator &NextMBBI);46bool expandCCOp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,47MachineBasicBlock::iterator &NextMBBI);48bool expandVSetVL(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI);49bool expandVMSET_VMCLR(MachineBasicBlock &MBB,50MachineBasicBlock::iterator MBBI, unsigned Opcode);51bool expandRV32ZdinxStore(MachineBasicBlock &MBB,52MachineBasicBlock::iterator MBBI);53bool expandRV32ZdinxLoad(MachineBasicBlock &MBB,54MachineBasicBlock::iterator MBBI);55#ifndef NDEBUG56unsigned getInstSizeInBytes(const MachineFunction &MF) const {57unsigned Size = 0;58for (auto &MBB : MF)59for (auto &MI : MBB)60Size += TII->getInstSizeInBytes(MI);61return Size;62}63#endif64};6566char RISCVExpandPseudo::ID = 0;6768bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) {69STI = &MF.getSubtarget<RISCVSubtarget>();70TII = STI->getInstrInfo();7172#ifndef NDEBUG73const unsigned OldSize = getInstSizeInBytes(MF);74#endif7576bool Modified = false;77for (auto &MBB : MF)78Modified |= expandMBB(MBB);7980#ifndef NDEBUG81const unsigned NewSize = getInstSizeInBytes(MF);82assert(OldSize >= NewSize);83#endif84return Modified;85}8687bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) {88bool Modified = false;8990MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();91while (MBBI != E) {92MachineBasicBlock::iterator NMBBI = std::next(MBBI);93Modified |= expandMI(MBB, MBBI, NMBBI);94MBBI = NMBBI;95}9697return Modified;98}99100bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,101MachineBasicBlock::iterator MBBI,102MachineBasicBlock::iterator &NextMBBI) {103// RISCVInstrInfo::getInstSizeInBytes expects that the total size of the104// expanded instructions for each pseudo is correct in the Size field of the105// tablegen definition for the pseudo.106switch (MBBI->getOpcode()) {107case RISCV::PseudoRV32ZdinxSD:108return expandRV32ZdinxStore(MBB, MBBI);109case RISCV::PseudoRV32ZdinxLD:110return expandRV32ZdinxLoad(MBB, MBBI);111case RISCV::PseudoCCMOVGPRNoX0:112case RISCV::PseudoCCMOVGPR:113case RISCV::PseudoCCADD:114case RISCV::PseudoCCSUB:115case RISCV::PseudoCCAND:116case RISCV::PseudoCCOR:117case RISCV::PseudoCCXOR:118case RISCV::PseudoCCADDW:119case RISCV::PseudoCCSUBW:120case RISCV::PseudoCCSLL:121case RISCV::PseudoCCSRL:122case RISCV::PseudoCCSRA:123case RISCV::PseudoCCADDI:124case RISCV::PseudoCCSLLI:125case RISCV::PseudoCCSRLI:126case RISCV::PseudoCCSRAI:127case RISCV::PseudoCCANDI:128case RISCV::PseudoCCORI:129case RISCV::PseudoCCXORI:130case RISCV::PseudoCCSLLW:131case RISCV::PseudoCCSRLW:132case RISCV::PseudoCCSRAW:133case RISCV::PseudoCCADDIW:134case RISCV::PseudoCCSLLIW:135case RISCV::PseudoCCSRLIW:136case RISCV::PseudoCCSRAIW:137case RISCV::PseudoCCANDN:138case RISCV::PseudoCCORN:139case RISCV::PseudoCCXNOR:140return expandCCOp(MBB, MBBI, NextMBBI);141case RISCV::PseudoVSETVLI:142case RISCV::PseudoVSETVLIX0:143case RISCV::PseudoVSETIVLI:144return expandVSetVL(MBB, MBBI);145case RISCV::PseudoVMCLR_M_B1:146case RISCV::PseudoVMCLR_M_B2:147case RISCV::PseudoVMCLR_M_B4:148case RISCV::PseudoVMCLR_M_B8:149case RISCV::PseudoVMCLR_M_B16:150case RISCV::PseudoVMCLR_M_B32:151case RISCV::PseudoVMCLR_M_B64:152// vmclr.m vd => vmxor.mm vd, vd, vd153return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXOR_MM);154case RISCV::PseudoVMSET_M_B1:155case RISCV::PseudoVMSET_M_B2:156case RISCV::PseudoVMSET_M_B4:157case RISCV::PseudoVMSET_M_B8:158case RISCV::PseudoVMSET_M_B16:159case RISCV::PseudoVMSET_M_B32:160case RISCV::PseudoVMSET_M_B64:161// vmset.m vd => vmxnor.mm vd, vd, vd162return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM);163}164165return false;166}167168bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,169MachineBasicBlock::iterator MBBI,170MachineBasicBlock::iterator &NextMBBI) {171172MachineFunction *MF = MBB.getParent();173MachineInstr &MI = *MBBI;174DebugLoc DL = MI.getDebugLoc();175176MachineBasicBlock *TrueBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());177MachineBasicBlock *MergeBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());178179MF->insert(++MBB.getIterator(), TrueBB);180MF->insert(++TrueBB->getIterator(), MergeBB);181182// We want to copy the "true" value when the condition is true which means183// we need to invert the branch condition to jump over TrueBB when the184// condition is false.185auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());186CC = RISCVCC::getOppositeBranchCondition(CC);187188// Insert branch instruction.189BuildMI(MBB, MBBI, DL, TII->getBrCond(CC))190.addReg(MI.getOperand(1).getReg())191.addReg(MI.getOperand(2).getReg())192.addMBB(MergeBB);193194Register DestReg = MI.getOperand(0).getReg();195assert(MI.getOperand(4).getReg() == DestReg);196197if (MI.getOpcode() == RISCV::PseudoCCMOVGPR ||198MI.getOpcode() == RISCV::PseudoCCMOVGPRNoX0) {199// Add MV.200BuildMI(TrueBB, DL, TII->get(RISCV::ADDI), DestReg)201.add(MI.getOperand(5))202.addImm(0);203} else {204unsigned NewOpc;205switch (MI.getOpcode()) {206default:207llvm_unreachable("Unexpected opcode!");208case RISCV::PseudoCCADD: NewOpc = RISCV::ADD; break;209case RISCV::PseudoCCSUB: NewOpc = RISCV::SUB; break;210case RISCV::PseudoCCSLL: NewOpc = RISCV::SLL; break;211case RISCV::PseudoCCSRL: NewOpc = RISCV::SRL; break;212case RISCV::PseudoCCSRA: NewOpc = RISCV::SRA; break;213case RISCV::PseudoCCAND: NewOpc = RISCV::AND; break;214case RISCV::PseudoCCOR: NewOpc = RISCV::OR; break;215case RISCV::PseudoCCXOR: NewOpc = RISCV::XOR; break;216case RISCV::PseudoCCADDI: NewOpc = RISCV::ADDI; break;217case RISCV::PseudoCCSLLI: NewOpc = RISCV::SLLI; break;218case RISCV::PseudoCCSRLI: NewOpc = RISCV::SRLI; break;219case RISCV::PseudoCCSRAI: NewOpc = RISCV::SRAI; break;220case RISCV::PseudoCCANDI: NewOpc = RISCV::ANDI; break;221case RISCV::PseudoCCORI: NewOpc = RISCV::ORI; break;222case RISCV::PseudoCCXORI: NewOpc = RISCV::XORI; break;223case RISCV::PseudoCCADDW: NewOpc = RISCV::ADDW; break;224case RISCV::PseudoCCSUBW: NewOpc = RISCV::SUBW; break;225case RISCV::PseudoCCSLLW: NewOpc = RISCV::SLLW; break;226case RISCV::PseudoCCSRLW: NewOpc = RISCV::SRLW; break;227case RISCV::PseudoCCSRAW: NewOpc = RISCV::SRAW; break;228case RISCV::PseudoCCADDIW: NewOpc = RISCV::ADDIW; break;229case RISCV::PseudoCCSLLIW: NewOpc = RISCV::SLLIW; break;230case RISCV::PseudoCCSRLIW: NewOpc = RISCV::SRLIW; break;231case RISCV::PseudoCCSRAIW: NewOpc = RISCV::SRAIW; break;232case RISCV::PseudoCCANDN: NewOpc = RISCV::ANDN; break;233case RISCV::PseudoCCORN: NewOpc = RISCV::ORN; break;234case RISCV::PseudoCCXNOR: NewOpc = RISCV::XNOR; break;235}236BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg)237.add(MI.getOperand(5))238.add(MI.getOperand(6));239}240241TrueBB->addSuccessor(MergeBB);242243MergeBB->splice(MergeBB->end(), &MBB, MI, MBB.end());244MergeBB->transferSuccessors(&MBB);245246MBB.addSuccessor(TrueBB);247MBB.addSuccessor(MergeBB);248249NextMBBI = MBB.end();250MI.eraseFromParent();251252// Make sure live-ins are correctly attached to this new basic block.253LivePhysRegs LiveRegs;254computeAndAddLiveIns(LiveRegs, *TrueBB);255computeAndAddLiveIns(LiveRegs, *MergeBB);256257return true;258}259260bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock &MBB,261MachineBasicBlock::iterator MBBI) {262assert(MBBI->getNumExplicitOperands() == 3 && MBBI->getNumOperands() >= 5 &&263"Unexpected instruction format");264265DebugLoc DL = MBBI->getDebugLoc();266267assert((MBBI->getOpcode() == RISCV::PseudoVSETVLI ||268MBBI->getOpcode() == RISCV::PseudoVSETVLIX0 ||269MBBI->getOpcode() == RISCV::PseudoVSETIVLI) &&270"Unexpected pseudo instruction");271unsigned Opcode;272if (MBBI->getOpcode() == RISCV::PseudoVSETIVLI)273Opcode = RISCV::VSETIVLI;274else275Opcode = RISCV::VSETVLI;276const MCInstrDesc &Desc = TII->get(Opcode);277assert(Desc.getNumOperands() == 3 && "Unexpected instruction format");278279Register DstReg = MBBI->getOperand(0).getReg();280bool DstIsDead = MBBI->getOperand(0).isDead();281BuildMI(MBB, MBBI, DL, Desc)282.addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead))283.add(MBBI->getOperand(1)) // VL284.add(MBBI->getOperand(2)); // VType285286MBBI->eraseFromParent(); // The pseudo instruction is gone now.287return true;288}289290bool RISCVExpandPseudo::expandVMSET_VMCLR(MachineBasicBlock &MBB,291MachineBasicBlock::iterator MBBI,292unsigned Opcode) {293DebugLoc DL = MBBI->getDebugLoc();294Register DstReg = MBBI->getOperand(0).getReg();295const MCInstrDesc &Desc = TII->get(Opcode);296BuildMI(MBB, MBBI, DL, Desc, DstReg)297.addReg(DstReg, RegState::Undef)298.addReg(DstReg, RegState::Undef);299MBBI->eraseFromParent(); // The pseudo instruction is gone now.300return true;301}302303// This function expands the PseudoRV32ZdinxSD for storing a double-precision304// floating-point value into memory by generating an equivalent instruction305// sequence for RV32.306bool RISCVExpandPseudo::expandRV32ZdinxStore(MachineBasicBlock &MBB,307MachineBasicBlock::iterator MBBI) {308DebugLoc DL = MBBI->getDebugLoc();309const TargetRegisterInfo *TRI = STI->getRegisterInfo();310Register Lo =311TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_even);312Register Hi =313TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd);314315assert(MBBI->hasOneMemOperand() && "Expected mem operand");316MachineMemOperand *OldMMO = MBBI->memoperands().front();317MachineFunction *MF = MBB.getParent();318MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4);319MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4);320321BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))322.addReg(Lo, getKillRegState(MBBI->getOperand(0).isKill()))323.addReg(MBBI->getOperand(1).getReg())324.add(MBBI->getOperand(2))325.setMemRefs(MMOLo);326327if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {328// FIXME: Zdinx RV32 can not work on unaligned scalar memory.329assert(!STI->enableUnalignedScalarMem());330331assert(MBBI->getOperand(2).getOffset() % 8 == 0);332MBBI->getOperand(2).setOffset(MBBI->getOperand(2).getOffset() + 4);333BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))334.addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))335.add(MBBI->getOperand(1))336.add(MBBI->getOperand(2))337.setMemRefs(MMOHi);338} else {339assert(isInt<12>(MBBI->getOperand(2).getImm() + 4));340BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))341.addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))342.add(MBBI->getOperand(1))343.addImm(MBBI->getOperand(2).getImm() + 4)344.setMemRefs(MMOHi);345}346MBBI->eraseFromParent();347return true;348}349350// This function expands PseudoRV32ZdinxLoad for loading a double-precision351// floating-point value from memory into an equivalent instruction sequence for352// RV32.353bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB,354MachineBasicBlock::iterator MBBI) {355DebugLoc DL = MBBI->getDebugLoc();356const TargetRegisterInfo *TRI = STI->getRegisterInfo();357Register Lo =358TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_even);359Register Hi =360TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd);361362assert(MBBI->hasOneMemOperand() && "Expected mem operand");363MachineMemOperand *OldMMO = MBBI->memoperands().front();364MachineFunction *MF = MBB.getParent();365MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4);366MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4);367368// If the register of operand 1 is equal to the Lo register, then swap the369// order of loading the Lo and Hi statements.370bool IsOp1EqualToLo = Lo == MBBI->getOperand(1).getReg();371// Order: Lo, Hi372if (!IsOp1EqualToLo) {373BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)374.addReg(MBBI->getOperand(1).getReg())375.add(MBBI->getOperand(2))376.setMemRefs(MMOLo);377}378379if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {380auto Offset = MBBI->getOperand(2).getOffset();381assert(MBBI->getOperand(2).getOffset() % 8 == 0);382MBBI->getOperand(2).setOffset(Offset + 4);383BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)384.addReg(MBBI->getOperand(1).getReg())385.add(MBBI->getOperand(2))386.setMemRefs(MMOHi);387MBBI->getOperand(2).setOffset(Offset);388} else {389assert(isInt<12>(MBBI->getOperand(2).getImm() + 4));390BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)391.addReg(MBBI->getOperand(1).getReg())392.addImm(MBBI->getOperand(2).getImm() + 4)393.setMemRefs(MMOHi);394}395396// Order: Hi, Lo397if (IsOp1EqualToLo) {398BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)399.addReg(MBBI->getOperand(1).getReg())400.add(MBBI->getOperand(2))401.setMemRefs(MMOLo);402}403404MBBI->eraseFromParent();405return true;406}407408class RISCVPreRAExpandPseudo : public MachineFunctionPass {409public:410const RISCVSubtarget *STI;411const RISCVInstrInfo *TII;412static char ID;413414RISCVPreRAExpandPseudo() : MachineFunctionPass(ID) {}415416bool runOnMachineFunction(MachineFunction &MF) override;417418void getAnalysisUsage(AnalysisUsage &AU) const override {419AU.setPreservesCFG();420MachineFunctionPass::getAnalysisUsage(AU);421}422StringRef getPassName() const override {423return RISCV_PRERA_EXPAND_PSEUDO_NAME;424}425426private:427bool expandMBB(MachineBasicBlock &MBB);428bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,429MachineBasicBlock::iterator &NextMBBI);430bool expandAuipcInstPair(MachineBasicBlock &MBB,431MachineBasicBlock::iterator MBBI,432MachineBasicBlock::iterator &NextMBBI,433unsigned FlagsHi, unsigned SecondOpcode);434bool expandLoadLocalAddress(MachineBasicBlock &MBB,435MachineBasicBlock::iterator MBBI,436MachineBasicBlock::iterator &NextMBBI);437bool expandLoadGlobalAddress(MachineBasicBlock &MBB,438MachineBasicBlock::iterator MBBI,439MachineBasicBlock::iterator &NextMBBI);440bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,441MachineBasicBlock::iterator MBBI,442MachineBasicBlock::iterator &NextMBBI);443bool expandLoadTLSGDAddress(MachineBasicBlock &MBB,444MachineBasicBlock::iterator MBBI,445MachineBasicBlock::iterator &NextMBBI);446bool expandLoadTLSDescAddress(MachineBasicBlock &MBB,447MachineBasicBlock::iterator MBBI,448MachineBasicBlock::iterator &NextMBBI);449450#ifndef NDEBUG451unsigned getInstSizeInBytes(const MachineFunction &MF) const {452unsigned Size = 0;453for (auto &MBB : MF)454for (auto &MI : MBB)455Size += TII->getInstSizeInBytes(MI);456return Size;457}458#endif459};460461char RISCVPreRAExpandPseudo::ID = 0;462463bool RISCVPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {464STI = &MF.getSubtarget<RISCVSubtarget>();465TII = STI->getInstrInfo();466467#ifndef NDEBUG468const unsigned OldSize = getInstSizeInBytes(MF);469#endif470471bool Modified = false;472for (auto &MBB : MF)473Modified |= expandMBB(MBB);474475#ifndef NDEBUG476const unsigned NewSize = getInstSizeInBytes(MF);477assert(OldSize >= NewSize);478#endif479return Modified;480}481482bool RISCVPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {483bool Modified = false;484485MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();486while (MBBI != E) {487MachineBasicBlock::iterator NMBBI = std::next(MBBI);488Modified |= expandMI(MBB, MBBI, NMBBI);489MBBI = NMBBI;490}491492return Modified;493}494495bool RISCVPreRAExpandPseudo::expandMI(MachineBasicBlock &MBB,496MachineBasicBlock::iterator MBBI,497MachineBasicBlock::iterator &NextMBBI) {498499switch (MBBI->getOpcode()) {500case RISCV::PseudoLLA:501return expandLoadLocalAddress(MBB, MBBI, NextMBBI);502case RISCV::PseudoLGA:503return expandLoadGlobalAddress(MBB, MBBI, NextMBBI);504case RISCV::PseudoLA_TLS_IE:505return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);506case RISCV::PseudoLA_TLS_GD:507return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI);508case RISCV::PseudoLA_TLSDESC:509return expandLoadTLSDescAddress(MBB, MBBI, NextMBBI);510}511return false;512}513514bool RISCVPreRAExpandPseudo::expandAuipcInstPair(515MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,516MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,517unsigned SecondOpcode) {518MachineFunction *MF = MBB.getParent();519MachineInstr &MI = *MBBI;520DebugLoc DL = MI.getDebugLoc();521522Register DestReg = MI.getOperand(0).getReg();523Register ScratchReg =524MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);525526MachineOperand &Symbol = MI.getOperand(1);527Symbol.setTargetFlags(FlagsHi);528MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("pcrel_hi");529530MachineInstr *MIAUIPC =531BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);532MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);533534MachineInstr *SecondMI =535BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)536.addReg(ScratchReg)537.addSym(AUIPCSymbol, RISCVII::MO_PCREL_LO);538539if (MI.hasOneMemOperand())540SecondMI->addMemOperand(*MF, *MI.memoperands_begin());541542MI.eraseFromParent();543return true;544}545546bool RISCVPreRAExpandPseudo::expandLoadLocalAddress(547MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,548MachineBasicBlock::iterator &NextMBBI) {549return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI,550RISCV::ADDI);551}552553bool RISCVPreRAExpandPseudo::expandLoadGlobalAddress(554MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,555MachineBasicBlock::iterator &NextMBBI) {556unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW;557return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_GOT_HI,558SecondOpcode);559}560561bool RISCVPreRAExpandPseudo::expandLoadTLSIEAddress(562MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,563MachineBasicBlock::iterator &NextMBBI) {564unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW;565return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,566SecondOpcode);567}568569bool RISCVPreRAExpandPseudo::expandLoadTLSGDAddress(570MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,571MachineBasicBlock::iterator &NextMBBI) {572return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI,573RISCV::ADDI);574}575576bool RISCVPreRAExpandPseudo::expandLoadTLSDescAddress(577MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,578MachineBasicBlock::iterator &NextMBBI) {579MachineFunction *MF = MBB.getParent();580MachineInstr &MI = *MBBI;581DebugLoc DL = MI.getDebugLoc();582583const auto &STI = MF->getSubtarget<RISCVSubtarget>();584unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;585586Register FinalReg = MI.getOperand(0).getReg();587Register DestReg =588MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);589Register ScratchReg =590MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);591592MachineOperand &Symbol = MI.getOperand(1);593Symbol.setTargetFlags(RISCVII::MO_TLSDESC_HI);594MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("tlsdesc_hi");595596MachineInstr *MIAUIPC =597BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);598MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);599600BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)601.addReg(ScratchReg)602.addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_LOAD_LO);603604BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), RISCV::X10)605.addReg(ScratchReg)606.addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_ADD_LO);607608BuildMI(MBB, MBBI, DL, TII->get(RISCV::PseudoTLSDESCCall), RISCV::X5)609.addReg(DestReg)610.addImm(0)611.addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_CALL);612613BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADD), FinalReg)614.addReg(RISCV::X10)615.addReg(RISCV::X4);616617MI.eraseFromParent();618return true;619}620621} // end of anonymous namespace622623INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",624RISCV_EXPAND_PSEUDO_NAME, false, false)625626INITIALIZE_PASS(RISCVPreRAExpandPseudo, "riscv-prera-expand-pseudo",627RISCV_PRERA_EXPAND_PSEUDO_NAME, false, false)628629namespace llvm {630631FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }632FunctionPass *createRISCVPreRAExpandPseudoPass() { return new RISCVPreRAExpandPseudo(); }633634} // end of namespace llvm635636637