Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchExpandPseudoInsts.cpp
35269 views
//===-- LoongArchExpandPseudoInsts.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.10//11//===----------------------------------------------------------------------===//1213#include "LoongArch.h"14#include "LoongArchInstrInfo.h"15#include "LoongArchTargetMachine.h"16#include "MCTargetDesc/LoongArchBaseInfo.h"17#include "MCTargetDesc/LoongArchMCTargetDesc.h"18#include "llvm/CodeGen/LivePhysRegs.h"19#include "llvm/CodeGen/MachineFunctionPass.h"20#include "llvm/CodeGen/MachineInstrBuilder.h"21#include "llvm/CodeGen/MachineOperand.h"22#include "llvm/CodeGen/Register.h"23#include "llvm/MC/MCContext.h"24#include "llvm/Support/CodeGen.h"25#include "llvm/Support/ErrorHandling.h"2627using namespace llvm;2829#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \30"LoongArch Pre-RA pseudo instruction expansion pass"31#define LOONGARCH_EXPAND_PSEUDO_NAME \32"LoongArch pseudo instruction expansion pass"3334namespace {3536class LoongArchPreRAExpandPseudo : public MachineFunctionPass {37public:38const LoongArchInstrInfo *TII;39static char ID;4041LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {42initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry());43}4445bool runOnMachineFunction(MachineFunction &MF) override;4647void getAnalysisUsage(AnalysisUsage &AU) const override {48AU.setPreservesCFG();49MachineFunctionPass::getAnalysisUsage(AU);50}51StringRef getPassName() const override {52return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME;53}5455private:56bool expandMBB(MachineBasicBlock &MBB);57bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,58MachineBasicBlock::iterator &NextMBBI);59bool expandPcalau12iInstPair(MachineBasicBlock &MBB,60MachineBasicBlock::iterator MBBI,61MachineBasicBlock::iterator &NextMBBI,62unsigned FlagsHi, unsigned SecondOpcode,63unsigned FlagsLo);64bool expandLoadAddressPcrel(MachineBasicBlock &MBB,65MachineBasicBlock::iterator MBBI,66MachineBasicBlock::iterator &NextMBBI);67bool expandLoadAddressGot(MachineBasicBlock &MBB,68MachineBasicBlock::iterator MBBI,69MachineBasicBlock::iterator &NextMBBI);70bool expandLoadAddressTLSLE(MachineBasicBlock &MBB,71MachineBasicBlock::iterator MBBI,72MachineBasicBlock::iterator &NextMBBI);73bool expandLoadAddressTLSIE(MachineBasicBlock &MBB,74MachineBasicBlock::iterator MBBI,75MachineBasicBlock::iterator &NextMBBI);76bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,77MachineBasicBlock::iterator MBBI,78MachineBasicBlock::iterator &NextMBBI);79bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,80MachineBasicBlock::iterator MBBI,81MachineBasicBlock::iterator &NextMBBI);82bool expandLoadAddressTLSDesc(MachineBasicBlock &MBB,83MachineBasicBlock::iterator MBBI,84MachineBasicBlock::iterator &NextMBBI);85};8687char LoongArchPreRAExpandPseudo::ID = 0;8889bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {90TII =91static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());92bool Modified = false;93for (auto &MBB : MF)94Modified |= expandMBB(MBB);95return Modified;96}9798bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {99bool Modified = false;100101MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();102while (MBBI != E) {103MachineBasicBlock::iterator NMBBI = std::next(MBBI);104Modified |= expandMI(MBB, MBBI, NMBBI);105MBBI = NMBBI;106}107108return Modified;109}110111bool LoongArchPreRAExpandPseudo::expandMI(112MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,113MachineBasicBlock::iterator &NextMBBI) {114switch (MBBI->getOpcode()) {115case LoongArch::PseudoLA_PCREL:116return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);117case LoongArch::PseudoLA_GOT:118return expandLoadAddressGot(MBB, MBBI, NextMBBI);119case LoongArch::PseudoLA_TLS_LE:120return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI);121case LoongArch::PseudoLA_TLS_IE:122return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI);123case LoongArch::PseudoLA_TLS_LD:124return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);125case LoongArch::PseudoLA_TLS_GD:126return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);127case LoongArch::PseudoLA_TLS_DESC_PC:128return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI);129}130return false;131}132133bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(134MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,135MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,136unsigned SecondOpcode, unsigned FlagsLo) {137MachineFunction *MF = MBB.getParent();138MachineInstr &MI = *MBBI;139DebugLoc DL = MI.getDebugLoc();140141Register DestReg = MI.getOperand(0).getReg();142Register ScratchReg =143MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);144MachineOperand &Symbol = MI.getOperand(1);145146BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)147.addDisp(Symbol, 0, FlagsHi);148149MachineInstr *SecondMI =150BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)151.addReg(ScratchReg)152.addDisp(Symbol, 0, FlagsLo);153154if (MI.hasOneMemOperand())155SecondMI->addMemOperand(*MF, *MI.memoperands_begin());156157MI.eraseFromParent();158return true;159}160161bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(162MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,163MachineBasicBlock::iterator &NextMBBI) {164// Code Sequence:165// pcalau12i $rd, %pc_hi20(sym)166// addi.w/d $rd, $rd, %pc_lo12(sym)167MachineFunction *MF = MBB.getParent();168const auto &STI = MF->getSubtarget<LoongArchSubtarget>();169unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;170return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI,171SecondOpcode, LoongArchII::MO_PCREL_LO);172}173174bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(175MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,176MachineBasicBlock::iterator &NextMBBI) {177// Code Sequence:178// pcalau12i $rd, %got_pc_hi20(sym)179// ld.w/d $rd, $rd, %got_pc_lo12(sym)180MachineFunction *MF = MBB.getParent();181const auto &STI = MF->getSubtarget<LoongArchSubtarget>();182unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;183return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI,184SecondOpcode, LoongArchII::MO_GOT_PC_LO);185}186187bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(188MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,189MachineBasicBlock::iterator &NextMBBI) {190// Code Sequence:191// lu12i.w $rd, %le_hi20(sym)192// ori $rd, $rd, %le_lo12(sym)193//194// And additionally if generating code using the large code model:195//196// lu32i.d $rd, %le64_lo20(sym)197// lu52i.d $rd, $rd, %le64_hi12(sym)198MachineFunction *MF = MBB.getParent();199MachineInstr &MI = *MBBI;200DebugLoc DL = MI.getDebugLoc();201202bool Large = MF->getTarget().getCodeModel() == CodeModel::Large;203Register DestReg = MI.getOperand(0).getReg();204Register Parts01 =205Large ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)206: DestReg;207Register Part1 =208MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);209MachineOperand &Symbol = MI.getOperand(1);210211BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)212.addDisp(Symbol, 0, LoongArchII::MO_LE_HI);213214BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01)215.addReg(Part1, RegState::Kill)216.addDisp(Symbol, 0, LoongArchII::MO_LE_LO);217218if (Large) {219Register Parts012 =220MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);221222BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Parts012)223// "rj" is needed due to InstrInfo pattern requirement.224.addReg(Parts01, RegState::Kill)225.addDisp(Symbol, 0, LoongArchII::MO_LE64_LO);226BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), DestReg)227.addReg(Parts012, RegState::Kill)228.addDisp(Symbol, 0, LoongArchII::MO_LE64_HI);229}230231MI.eraseFromParent();232return true;233}234235bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(236MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,237MachineBasicBlock::iterator &NextMBBI) {238// Code Sequence:239// pcalau12i $rd, %ie_pc_hi20(sym)240// ld.w/d $rd, $rd, %ie_pc_lo12(sym)241MachineFunction *MF = MBB.getParent();242const auto &STI = MF->getSubtarget<LoongArchSubtarget>();243unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;244return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_IE_PC_HI,245SecondOpcode, LoongArchII::MO_IE_PC_LO);246}247248bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(249MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,250MachineBasicBlock::iterator &NextMBBI) {251// Code Sequence:252// pcalau12i $rd, %ld_pc_hi20(sym)253// addi.w/d $rd, $rd, %got_pc_lo12(sym)254MachineFunction *MF = MBB.getParent();255const auto &STI = MF->getSubtarget<LoongArchSubtarget>();256unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;257return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_LD_PC_HI,258SecondOpcode, LoongArchII::MO_GOT_PC_LO);259}260261bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(262MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,263MachineBasicBlock::iterator &NextMBBI) {264// Code Sequence:265// pcalau12i $rd, %gd_pc_hi20(sym)266// addi.w/d $rd, $rd, %got_pc_lo12(sym)267MachineFunction *MF = MBB.getParent();268const auto &STI = MF->getSubtarget<LoongArchSubtarget>();269unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;270return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GD_PC_HI,271SecondOpcode, LoongArchII::MO_GOT_PC_LO);272}273274bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(275MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,276MachineBasicBlock::iterator &NextMBBI) {277// Code Sequence:278// pcalau12i $a0, %desc_pc_hi20(sym)279// addi.w/d $a0, $a0, %desc_pc_lo12(sym)280// ld.w/d $ra, $a0, %desc_ld(sym)281// jirl $ra, $ra, %desc_ld(sym)282// add.d $dst, $a0, $tp283MachineFunction *MF = MBB.getParent();284MachineInstr &MI = *MBBI;285DebugLoc DL = MI.getDebugLoc();286287const auto &STI = MF->getSubtarget<LoongArchSubtarget>();288unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W;289unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;290unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;291292Register DestReg = MI.getOperand(0).getReg();293Register ScratchReg =294MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);295MachineOperand &Symbol = MI.getOperand(1);296297BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)298.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_HI);299300BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)301.addReg(ScratchReg)302.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_LO);303304BuildMI(MBB, MBBI, DL, TII->get(LD), LoongArch::R1)305.addReg(LoongArch::R4)306.addDisp(Symbol, 0, LoongArchII::MO_DESC_LD);307308BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)309.addReg(LoongArch::R1)310.addDisp(Symbol, 0, LoongArchII::MO_DESC_CALL);311312BuildMI(MBB, MBBI, DL, TII->get(ADD), DestReg)313.addReg(LoongArch::R4)314.addReg(LoongArch::R2);315316MI.eraseFromParent();317return true;318}319320class LoongArchExpandPseudo : public MachineFunctionPass {321public:322const LoongArchInstrInfo *TII;323static char ID;324325LoongArchExpandPseudo() : MachineFunctionPass(ID) {326initializeLoongArchExpandPseudoPass(*PassRegistry::getPassRegistry());327}328329bool runOnMachineFunction(MachineFunction &MF) override;330331StringRef getPassName() const override {332return LOONGARCH_EXPAND_PSEUDO_NAME;333}334335private:336bool expandMBB(MachineBasicBlock &MBB);337bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,338MachineBasicBlock::iterator &NextMBBI);339bool expandCopyCFR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,340MachineBasicBlock::iterator &NextMBBI);341bool expandLargeAddressLoad(MachineBasicBlock &MBB,342MachineBasicBlock::iterator MBBI,343MachineBasicBlock::iterator &NextMBBI,344unsigned LastOpcode, unsigned IdentifyingMO);345bool expandLargeAddressLoad(MachineBasicBlock &MBB,346MachineBasicBlock::iterator MBBI,347MachineBasicBlock::iterator &NextMBBI,348unsigned LastOpcode, unsigned IdentifyingMO,349const MachineOperand &Symbol, Register DestReg,350bool EraseFromParent);351bool expandLoadAddressPcrelLarge(MachineBasicBlock &MBB,352MachineBasicBlock::iterator MBBI,353MachineBasicBlock::iterator &NextMBBI);354bool expandLoadAddressGotLarge(MachineBasicBlock &MBB,355MachineBasicBlock::iterator MBBI,356MachineBasicBlock::iterator &NextMBBI);357bool expandLoadAddressTLSIELarge(MachineBasicBlock &MBB,358MachineBasicBlock::iterator MBBI,359MachineBasicBlock::iterator &NextMBBI);360bool expandLoadAddressTLSLDLarge(MachineBasicBlock &MBB,361MachineBasicBlock::iterator MBBI,362MachineBasicBlock::iterator &NextMBBI);363bool expandLoadAddressTLSGDLarge(MachineBasicBlock &MBB,364MachineBasicBlock::iterator MBBI,365MachineBasicBlock::iterator &NextMBBI);366bool expandLoadAddressTLSDescPcLarge(MachineBasicBlock &MBB,367MachineBasicBlock::iterator MBBI,368MachineBasicBlock::iterator &NextMBBI);369bool expandFunctionCALL(MachineBasicBlock &MBB,370MachineBasicBlock::iterator MBBI,371MachineBasicBlock::iterator &NextMBBI,372bool IsTailCall);373};374375char LoongArchExpandPseudo::ID = 0;376377bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) {378TII =379static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());380381bool Modified = false;382for (auto &MBB : MF)383Modified |= expandMBB(MBB);384385return Modified;386}387388bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) {389bool Modified = false;390391MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();392while (MBBI != E) {393MachineBasicBlock::iterator NMBBI = std::next(MBBI);394Modified |= expandMI(MBB, MBBI, NMBBI);395MBBI = NMBBI;396}397398return Modified;399}400401bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,402MachineBasicBlock::iterator MBBI,403MachineBasicBlock::iterator &NextMBBI) {404switch (MBBI->getOpcode()) {405case LoongArch::PseudoCopyCFR:406return expandCopyCFR(MBB, MBBI, NextMBBI);407case LoongArch::PseudoLA_PCREL_LARGE:408return expandLoadAddressPcrelLarge(MBB, MBBI, NextMBBI);409case LoongArch::PseudoLA_GOT_LARGE:410return expandLoadAddressGotLarge(MBB, MBBI, NextMBBI);411case LoongArch::PseudoLA_TLS_IE_LARGE:412return expandLoadAddressTLSIELarge(MBB, MBBI, NextMBBI);413case LoongArch::PseudoLA_TLS_LD_LARGE:414return expandLoadAddressTLSLDLarge(MBB, MBBI, NextMBBI);415case LoongArch::PseudoLA_TLS_GD_LARGE:416return expandLoadAddressTLSGDLarge(MBB, MBBI, NextMBBI);417case LoongArch::PseudoLA_TLS_DESC_PC_LARGE:418return expandLoadAddressTLSDescPcLarge(MBB, MBBI, NextMBBI);419case LoongArch::PseudoCALL:420case LoongArch::PseudoCALL_MEDIUM:421case LoongArch::PseudoCALL_LARGE:422return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);423case LoongArch::PseudoTAIL:424case LoongArch::PseudoTAIL_MEDIUM:425case LoongArch::PseudoTAIL_LARGE:426return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);427}428429return false;430}431432bool LoongArchExpandPseudo::expandCopyCFR(433MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,434MachineBasicBlock::iterator &NextMBBI) {435MachineFunction *MF = MBB.getParent();436MachineInstr &MI = *MBBI;437DebugLoc DL = MI.getDebugLoc();438439// Expand:440// MBB:441// fcmp.caf.s $dst, $fa0, $fa0 # set $dst 0(false)442// bceqz $src, SinkBB443// FalseBB:444// fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true)445// SinkBB:446// fallthrough447448const BasicBlock *LLVM_BB = MBB.getBasicBlock();449auto *FalseBB = MF->CreateMachineBasicBlock(LLVM_BB);450auto *SinkBB = MF->CreateMachineBasicBlock(LLVM_BB);451452MF->insert(++MBB.getIterator(), FalseBB);453MF->insert(++FalseBB->getIterator(), SinkBB);454455Register DestReg = MI.getOperand(0).getReg();456Register SrcReg = MI.getOperand(1).getReg();457// DestReg = 0458BuildMI(MBB, MBBI, DL, TII->get(LoongArch::SET_CFR_FALSE), DestReg);459// Insert branch instruction.460BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BCEQZ))461.addReg(SrcReg)462.addMBB(SinkBB);463// DestReg = 1464BuildMI(FalseBB, DL, TII->get(LoongArch::SET_CFR_TRUE), DestReg);465466FalseBB->addSuccessor(SinkBB);467468SinkBB->splice(SinkBB->end(), &MBB, MI, MBB.end());469SinkBB->transferSuccessors(&MBB);470471MBB.addSuccessor(FalseBB);472MBB.addSuccessor(SinkBB);473474NextMBBI = MBB.end();475MI.eraseFromParent();476477// Make sure live-ins are correctly attached to this new basic block.478LivePhysRegs LiveRegs;479computeAndAddLiveIns(LiveRegs, *FalseBB);480computeAndAddLiveIns(LiveRegs, *SinkBB);481482return true;483}484485bool LoongArchExpandPseudo::expandLargeAddressLoad(486MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,487MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,488unsigned IdentifyingMO) {489MachineInstr &MI = *MBBI;490return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO,491MI.getOperand(2), MI.getOperand(0).getReg(),492true);493}494495bool LoongArchExpandPseudo::expandLargeAddressLoad(496MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,497MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,498unsigned IdentifyingMO, const MachineOperand &Symbol, Register DestReg,499bool EraseFromParent) {500// Code Sequence:501//502// Part1: pcalau12i $dst, %MO1(sym)503// Part0: addi.d $t8, $zero, %MO0(sym)504// Part2: lu32i.d $t8, %MO2(sym)505// Part3: lu52i.d $t8, $t8, %MO3(sym)506// Fin: LastOpcode $dst, $t8, $dst507508unsigned MO0, MO1, MO2, MO3;509switch (IdentifyingMO) {510default:511llvm_unreachable("unsupported identifying MO");512case LoongArchII::MO_PCREL_LO:513MO0 = IdentifyingMO;514MO1 = LoongArchII::MO_PCREL_HI;515MO2 = LoongArchII::MO_PCREL64_LO;516MO3 = LoongArchII::MO_PCREL64_HI;517break;518case LoongArchII::MO_GOT_PC_HI:519case LoongArchII::MO_LD_PC_HI:520case LoongArchII::MO_GD_PC_HI:521// These cases relocate just like the GOT case, except for Part1.522MO0 = LoongArchII::MO_GOT_PC_LO;523MO1 = IdentifyingMO;524MO2 = LoongArchII::MO_GOT_PC64_LO;525MO3 = LoongArchII::MO_GOT_PC64_HI;526break;527case LoongArchII::MO_IE_PC_LO:528MO0 = IdentifyingMO;529MO1 = LoongArchII::MO_IE_PC_HI;530MO2 = LoongArchII::MO_IE_PC64_LO;531MO3 = LoongArchII::MO_IE_PC64_HI;532break;533}534535MachineInstr &MI = *MBBI;536DebugLoc DL = MI.getDebugLoc();537Register ScratchReg = LoongArch::R20; // $t8538539assert(MBB.getParent()->getSubtarget<LoongArchSubtarget>().is64Bit() &&540"Large code model requires LA64");541542auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), DestReg);543auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), ScratchReg)544.addReg(LoongArch::R0);545auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), ScratchReg)546// "rj" is needed due to InstrInfo pattern requirement.547.addReg(ScratchReg);548auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), ScratchReg)549.addReg(ScratchReg);550BuildMI(MBB, MBBI, DL, TII->get(LastOpcode), DestReg)551.addReg(ScratchReg)552.addReg(DestReg);553554if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) {555const char *SymName = Symbol.getSymbolName();556Part0.addExternalSymbol(SymName, MO0);557Part1.addExternalSymbol(SymName, MO1);558Part2.addExternalSymbol(SymName, MO2);559Part3.addExternalSymbol(SymName, MO3);560} else {561Part0.addDisp(Symbol, 0, MO0);562Part1.addDisp(Symbol, 0, MO1);563Part2.addDisp(Symbol, 0, MO2);564Part3.addDisp(Symbol, 0, MO3);565}566567if (EraseFromParent)568MI.eraseFromParent();569570return true;571}572573bool LoongArchExpandPseudo::expandLoadAddressPcrelLarge(574MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,575MachineBasicBlock::iterator &NextMBBI) {576// Emit the 5-insn large address load sequence with the `%pc` family of577// relocs.578return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,579LoongArchII::MO_PCREL_LO);580}581582bool LoongArchExpandPseudo::expandLoadAddressGotLarge(583MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,584MachineBasicBlock::iterator &NextMBBI) {585// Emit the 5-insn large address load sequence with the `%got_pc` family586// of relocs, loading the result from GOT with `ldx.d` in the end.587return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,588LoongArchII::MO_GOT_PC_HI);589}590591bool LoongArchExpandPseudo::expandLoadAddressTLSIELarge(592MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,593MachineBasicBlock::iterator &NextMBBI) {594// Emit the 5-insn large address load sequence with the `%ie_pc` family595// of relocs, loading the result with `ldx.d` in the end.596return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,597LoongArchII::MO_IE_PC_LO);598}599600bool LoongArchExpandPseudo::expandLoadAddressTLSLDLarge(601MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,602MachineBasicBlock::iterator &NextMBBI) {603// Emit the 5-insn large address load sequence with the `%got_pc` family604// of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`.605return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,606LoongArchII::MO_LD_PC_HI);607}608609bool LoongArchExpandPseudo::expandLoadAddressTLSGDLarge(610MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,611MachineBasicBlock::iterator &NextMBBI) {612// Emit the 5-insn large address load sequence with the `%got_pc` family613// of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`.614return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,615LoongArchII::MO_GD_PC_HI);616}617618bool LoongArchExpandPseudo::expandLoadAddressTLSDescPcLarge(619MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,620MachineBasicBlock::iterator &NextMBBI) {621// Code Sequence:622//623// pcalau12i $a0, %desc_pc_hi20(sym)624// addi.d $t8, $zero, %desc_pc_lo12(sym)625// lu32i.d $t8, %desc64_pc_lo20(sym)626// lu52i.d $t8, $t8, %desc64_pc_hi12(sym)627// add.d $a0, $a0, $t8628// ld.d $ra, $a0, %desc_ld(sym)629// jirl $ra, $ra, %desc_call(sym)630// add.d $dst, $a0, $tp631632MachineInstr &MI = *MBBI;633DebugLoc DL = MI.getDebugLoc();634Register DestReg = MI.getOperand(0).getReg();635MachineOperand &Symbol = MI.getOperand(2);636Register ScratchReg = LoongArch::R20; // $t8637638assert(MBB.getParent()->getSubtarget<LoongArchSubtarget>().is64Bit() &&639"Large code model requires LA64");640641BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), LoongArch::R4)642.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_HI);643BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), ScratchReg)644.addReg(LoongArch::R0)645.addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_LO);646BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), ScratchReg)647.addReg(ScratchReg)648.addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_LO);649BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), ScratchReg)650.addReg(ScratchReg)651.addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_HI);652BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), LoongArch::R4)653.addReg(ScratchReg)654.addReg(LoongArch::R4);655BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LD_D), LoongArch::R1)656.addReg(LoongArch::R4)657.addDisp(Symbol, 0, LoongArchII::MO_DESC_LD);658BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)659.addReg(LoongArch::R1)660.addDisp(Symbol, 0, LoongArchII::MO_DESC_CALL);661BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), DestReg)662.addReg(LoongArch::R4)663.addReg(LoongArch::R2);664665MI.eraseFromParent();666667return true;668}669670bool LoongArchExpandPseudo::expandFunctionCALL(671MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,672MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {673MachineFunction *MF = MBB.getParent();674MachineInstr &MI = *MBBI;675DebugLoc DL = MI.getDebugLoc();676const MachineOperand &Func = MI.getOperand(0);677MachineInstrBuilder CALL;678unsigned Opcode;679680switch (MF->getTarget().getCodeModel()) {681default:682report_fatal_error("Unsupported code model");683break;684case CodeModel::Small: {685// CALL:686// bl func687// TAIL:688// b func689Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL;690CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);691break;692}693case CodeModel::Medium: {694// CALL:695// pcaddu18i $ra, %call36(func)696// jirl $ra, $ra, 0697// TAIL:698// pcaddu18i $t8, %call36(func)699// jr $t8700Opcode =701IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;702Register ScratchReg = IsTailCall ? LoongArch::R20 : LoongArch::R1;703MachineInstrBuilder MIB =704BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg);705706CALL =707BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);708709if (Func.isSymbol())710MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);711else712MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);713break;714}715case CodeModel::Large: {716// Emit the 5-insn large address load sequence, either directly or717// indirectly in case of going through the GOT, then JIRL_TAIL or718// JIRL_CALL to $addr.719Opcode =720IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;721Register AddrReg = IsTailCall ? LoongArch::R19 : LoongArch::R1;722723bool UseGOT = Func.getTargetFlags() == LoongArchII::MO_CALL_PLT;724unsigned MO = UseGOT ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_PCREL_LO;725unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D;726expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg,727false);728CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0);729break;730}731}732733// Transfer implicit operands.734CALL.copyImplicitOps(MI);735736// Transfer MI flags.737CALL.setMIFlags(MI.getFlags());738739MI.eraseFromParent();740return true;741}742743} // end namespace744745INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",746LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false)747748INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo",749LOONGARCH_EXPAND_PSEUDO_NAME, false, false)750751namespace llvm {752753FunctionPass *createLoongArchPreRAExpandPseudoPass() {754return new LoongArchPreRAExpandPseudo();755}756FunctionPass *createLoongArchExpandPseudoPass() {757return new LoongArchExpandPseudo();758}759760} // end namespace llvm761762763