brintos

brintos / llvm-project-archived public Read only

0
0
Text · 30.7 KiB · 7aef4ab Raw
838 lines · cpp
1//===-- LoongArchExpandPseudoInsts.cpp - Expand pseudo instructions -------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains a pass that expands pseudo instructions into target10// instructions.11//12//===----------------------------------------------------------------------===//13 14#include "LoongArch.h"15#include "LoongArchInstrInfo.h"16#include "LoongArchMachineFunctionInfo.h"17#include "MCTargetDesc/LoongArchBaseInfo.h"18#include "MCTargetDesc/LoongArchMCTargetDesc.h"19#include "llvm/CodeGen/LivePhysRegs.h"20#include "llvm/CodeGen/MachineFunctionPass.h"21#include "llvm/CodeGen/MachineInstrBuilder.h"22#include "llvm/CodeGen/MachineOperand.h"23#include "llvm/CodeGen/Register.h"24#include "llvm/MC/MCContext.h"25#include "llvm/Support/CodeGen.h"26#include "llvm/Support/ErrorHandling.h"27 28using namespace llvm;29 30extern cl::opt<bool> LArchAnnotateTableJump;31 32#define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME                                     \33  "LoongArch Pre-RA pseudo instruction expansion pass"34#define LOONGARCH_EXPAND_PSEUDO_NAME                                           \35  "LoongArch pseudo instruction expansion pass"36 37namespace {38 39class LoongArchPreRAExpandPseudo : public MachineFunctionPass {40public:41  const LoongArchInstrInfo *TII;42  static char ID;43 44  LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) {}45 46  bool runOnMachineFunction(MachineFunction &MF) override;47 48  void getAnalysisUsage(AnalysisUsage &AU) const override {49    AU.setPreservesCFG();50    MachineFunctionPass::getAnalysisUsage(AU);51  }52  StringRef getPassName() const override {53    return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME;54  }55 56private:57  bool expandMBB(MachineBasicBlock &MBB);58  bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,59                MachineBasicBlock::iterator &NextMBBI);60  bool expandPcalau12iInstPair(MachineBasicBlock &MBB,61                               MachineBasicBlock::iterator MBBI,62                               MachineBasicBlock::iterator &NextMBBI,63                               unsigned FlagsHi, unsigned SecondOpcode,64                               unsigned FlagsLo);65  bool expandLargeAddressLoad(MachineBasicBlock &MBB,66                              MachineBasicBlock::iterator MBBI,67                              MachineBasicBlock::iterator &NextMBBI,68                              unsigned LastOpcode, unsigned IdentifyingMO);69  bool expandLargeAddressLoad(MachineBasicBlock &MBB,70                              MachineBasicBlock::iterator MBBI,71                              MachineBasicBlock::iterator &NextMBBI,72                              unsigned LastOpcode, unsigned IdentifyingMO,73                              const MachineOperand &Symbol, Register DestReg,74                              bool EraseFromParent);75  bool expandLoadAddressPcrel(MachineBasicBlock &MBB,76                              MachineBasicBlock::iterator MBBI,77                              MachineBasicBlock::iterator &NextMBBI,78                              bool Large = false);79  bool expandLoadAddressGot(MachineBasicBlock &MBB,80                            MachineBasicBlock::iterator MBBI,81                            MachineBasicBlock::iterator &NextMBBI,82                            bool Large = false);83  bool expandLoadAddressTLSLE(MachineBasicBlock &MBB,84                              MachineBasicBlock::iterator MBBI,85                              MachineBasicBlock::iterator &NextMBBI);86  bool expandLoadAddressTLSIE(MachineBasicBlock &MBB,87                              MachineBasicBlock::iterator MBBI,88                              MachineBasicBlock::iterator &NextMBBI,89                              bool Large = false);90  bool expandLoadAddressTLSLD(MachineBasicBlock &MBB,91                              MachineBasicBlock::iterator MBBI,92                              MachineBasicBlock::iterator &NextMBBI,93                              bool Large = false);94  bool expandLoadAddressTLSGD(MachineBasicBlock &MBB,95                              MachineBasicBlock::iterator MBBI,96                              MachineBasicBlock::iterator &NextMBBI,97                              bool Large = false);98  bool expandLoadAddressTLSDesc(MachineBasicBlock &MBB,99                                MachineBasicBlock::iterator MBBI,100                                MachineBasicBlock::iterator &NextMBBI,101                                bool Large = false);102  bool expandFunctionCALL(MachineBasicBlock &MBB,103                          MachineBasicBlock::iterator MBBI,104                          MachineBasicBlock::iterator &NextMBBI,105                          bool IsTailCall);106  void annotateTableJump(MachineBasicBlock &MBB,107                         MachineBasicBlock::iterator MBBI);108};109 110char LoongArchPreRAExpandPseudo::ID = 0;111 112bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {113  TII =114      static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());115  bool Modified = false;116  for (auto &MBB : MF)117    Modified |= expandMBB(MBB);118  return Modified;119}120 121bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {122  bool Modified = false;123 124  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();125  while (MBBI != E) {126    MachineBasicBlock::iterator NMBBI = std::next(MBBI);127    Modified |= expandMI(MBB, MBBI, NMBBI);128    MBBI = NMBBI;129  }130 131  return Modified;132}133 134bool LoongArchPreRAExpandPseudo::expandMI(135    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,136    MachineBasicBlock::iterator &NextMBBI) {137  switch (MBBI->getOpcode()) {138  case LoongArch::PseudoLA_PCREL:139    return expandLoadAddressPcrel(MBB, MBBI, NextMBBI);140  case LoongArch::PseudoLA_PCREL_LARGE:141    return expandLoadAddressPcrel(MBB, MBBI, NextMBBI, /*Large=*/true);142  case LoongArch::PseudoLA_GOT:143    return expandLoadAddressGot(MBB, MBBI, NextMBBI);144  case LoongArch::PseudoLA_GOT_LARGE:145    return expandLoadAddressGot(MBB, MBBI, NextMBBI, /*Large=*/true);146  case LoongArch::PseudoLA_TLS_LE:147    return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI);148  case LoongArch::PseudoLA_TLS_IE:149    return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI);150  case LoongArch::PseudoLA_TLS_IE_LARGE:151    return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI, /*Large=*/true);152  case LoongArch::PseudoLA_TLS_LD:153    return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI);154  case LoongArch::PseudoLA_TLS_LD_LARGE:155    return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI, /*Large=*/true);156  case LoongArch::PseudoLA_TLS_GD:157    return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI);158  case LoongArch::PseudoLA_TLS_GD_LARGE:159    return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI, /*Large=*/true);160  case LoongArch::PseudoLA_TLS_DESC:161    return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI);162  case LoongArch::PseudoLA_TLS_DESC_LARGE:163    return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI, /*Large=*/true);164  case LoongArch::PseudoCALL:165  case LoongArch::PseudoCALL_LARGE:166    return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);167  case LoongArch::PseudoTAIL:168  case LoongArch::PseudoTAIL_LARGE:169    return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);170  case LoongArch::PseudoBRIND:171    // If the PseudoBRIND is used to table jump, then emit a label to annotate172    // the `jr` instruction, and save the instructions.173    if (LArchAnnotateTableJump)174      annotateTableJump(MBB, MBBI);175    break;176  }177  return false;178}179 180bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair(181    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,182    MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,183    unsigned SecondOpcode, unsigned FlagsLo) {184  MachineFunction *MF = MBB.getParent();185  MachineInstr &MI = *MBBI;186  DebugLoc DL = MI.getDebugLoc();187 188  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();189  bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);190 191  Register DestReg = MI.getOperand(0).getReg();192  Register ScratchReg =193      MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);194  MachineOperand &Symbol = MI.getOperand(1);195 196  BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg)197      .addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsHi, EnableRelax));198 199  MachineInstr *SecondMI =200      BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)201          .addReg(ScratchReg)202          .addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsLo, EnableRelax));203 204  if (MI.hasOneMemOperand())205    SecondMI->addMemOperand(*MF, *MI.memoperands_begin());206 207  MI.eraseFromParent();208  return true;209}210 211bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(212    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,213    MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,214    unsigned IdentifyingMO) {215  MachineInstr &MI = *MBBI;216  return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO,217                                MI.getOperand(2), MI.getOperand(0).getReg(),218                                true);219}220 221bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad(222    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,223    MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode,224    unsigned IdentifyingMO, const MachineOperand &Symbol, Register DestReg,225    bool EraseFromParent) {226  // Code Sequence:227  //228  // Part1: pcalau12i  $scratch, %MO1(sym)229  // Part0: addi.d     $dest, $zero, %MO0(sym)230  // Part2: lu32i.d    $dest, %MO2(sym)231  // Part3: lu52i.d    $dest, $dest, %MO3(sym)232  // Fin:   LastOpcode $dest, $dest, $scratch233 234  unsigned MO0, MO1, MO2, MO3;235  switch (IdentifyingMO) {236  default:237    llvm_unreachable("unsupported identifying MO");238  case LoongArchII::MO_PCREL_LO:239    MO0 = IdentifyingMO;240    MO1 = LoongArchII::MO_PCREL_HI;241    MO2 = LoongArchII::MO_PCREL64_LO;242    MO3 = LoongArchII::MO_PCREL64_HI;243    break;244  case LoongArchII::MO_GOT_PC_HI:245  case LoongArchII::MO_LD_PC_HI:246  case LoongArchII::MO_GD_PC_HI:247    // These cases relocate just like the GOT case, except for Part1.248    MO0 = LoongArchII::MO_GOT_PC_LO;249    MO1 = IdentifyingMO;250    MO2 = LoongArchII::MO_GOT_PC64_LO;251    MO3 = LoongArchII::MO_GOT_PC64_HI;252    break;253  case LoongArchII::MO_IE_PC_LO:254    MO0 = IdentifyingMO;255    MO1 = LoongArchII::MO_IE_PC_HI;256    MO2 = LoongArchII::MO_IE_PC64_LO;257    MO3 = LoongArchII::MO_IE_PC64_HI;258    break;259  }260 261  MachineFunction *MF = MBB.getParent();262  MachineInstr &MI = *MBBI;263  DebugLoc DL = MI.getDebugLoc();264 265  assert(MF->getSubtarget<LoongArchSubtarget>().is64Bit() &&266         "Large code model requires LA64");267 268  Register TmpPart1 =269      MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);270  Register TmpPart0 =271      DestReg.isVirtual()272          ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)273          : DestReg;274  Register TmpParts02 =275      DestReg.isVirtual()276          ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)277          : DestReg;278  Register TmpParts023 =279      DestReg.isVirtual()280          ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)281          : DestReg;282 283  auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), TmpPart1);284  auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), TmpPart0)285                   .addReg(LoongArch::R0);286  auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), TmpParts02)287                   // "rj" is needed due to InstrInfo pattern requirement.288                   .addReg(TmpPart0, RegState::Kill);289  auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), TmpParts023)290                   .addReg(TmpParts02, RegState::Kill);291  BuildMI(MBB, MBBI, DL, TII->get(LastOpcode), DestReg)292      .addReg(TmpParts023)293      .addReg(TmpPart1, RegState::Kill);294 295  if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) {296    const char *SymName = Symbol.getSymbolName();297    Part0.addExternalSymbol(SymName, MO0);298    Part1.addExternalSymbol(SymName, MO1);299    Part2.addExternalSymbol(SymName, MO2);300    Part3.addExternalSymbol(SymName, MO3);301  } else {302    Part0.addDisp(Symbol, 0, MO0);303    Part1.addDisp(Symbol, 0, MO1);304    Part2.addDisp(Symbol, 0, MO2);305    Part3.addDisp(Symbol, 0, MO3);306  }307 308  if (EraseFromParent)309    MI.eraseFromParent();310 311  return true;312}313 314bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel(315    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,316    MachineBasicBlock::iterator &NextMBBI, bool Large) {317  if (Large)318    // Emit the 5-insn large address load sequence with the `%pc` family of319    // relocs.320    return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,321                                  LoongArchII::MO_PCREL_LO);322 323  // Code Sequence:324  // pcalau12i $rd, %pc_hi20(sym)325  // addi.w/d $rd, $rd, %pc_lo12(sym)326  MachineFunction *MF = MBB.getParent();327  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();328  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;329  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI,330                                 SecondOpcode, LoongArchII::MO_PCREL_LO);331}332 333bool LoongArchPreRAExpandPseudo::expandLoadAddressGot(334    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,335    MachineBasicBlock::iterator &NextMBBI, bool Large) {336  if (Large)337    // Emit the 5-insn large address load sequence with the `%got_pc` family338    // of relocs, loading the result from GOT with `ldx.d` in the end.339    return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,340                                  LoongArchII::MO_GOT_PC_HI);341 342  // Code Sequence:343  // pcalau12i $rd, %got_pc_hi20(sym)344  // ld.w/d $rd, $rd, %got_pc_lo12(sym)345  MachineFunction *MF = MBB.getParent();346  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();347  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;348  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI,349                                 SecondOpcode, LoongArchII::MO_GOT_PC_LO);350}351 352bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE(353    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,354    MachineBasicBlock::iterator &NextMBBI) {355  // Code Sequence:356  // lu12i.w $rd, %le_hi20_r(sym)357  // add.w/d $rd, $rd, $tp, %le_add_r(sym)358  // addi.w/d $rd, $rd, %le_lo12_r(sym)359  //360  // Code Sequence while using the large code model:361  // lu12i.w $rd, %le_hi20(sym)362  // ori $rd, $rd, %le_lo12(sym)363  // lu32i.d $rd, %le64_lo20(sym)364  // lu52i.d $rd, $rd, %le64_hi12(sym)365  MachineFunction *MF = MBB.getParent();366  MachineInstr &MI = *MBBI;367  DebugLoc DL = MI.getDebugLoc();368 369  bool Large = MF->getTarget().getCodeModel() == CodeModel::Large;370  Register DestReg = MI.getOperand(0).getReg();371  Register Parts01 =372      MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);373  Register Part1 =374      MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);375  MachineOperand &Symbol = MI.getOperand(1);376 377  if (!Large) {378    BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)379        .addDisp(Symbol, 0, LoongArchII::MO_LE_HI_R);380 381    const auto &STI = MF->getSubtarget<LoongArchSubtarget>();382    unsigned AddOp = STI.is64Bit() ? LoongArch::PseudoAddTPRel_D383                                   : LoongArch::PseudoAddTPRel_W;384    BuildMI(MBB, MBBI, DL, TII->get(AddOp), Parts01)385        .addReg(Part1, RegState::Kill)386        .addReg(LoongArch::R2)387        .addDisp(Symbol, 0, LoongArchII::MO_LE_ADD_R);388 389    unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;390    BuildMI(MBB, MBBI, DL, TII->get(AddiOp), DestReg)391        .addReg(Parts01, RegState::Kill)392        .addDisp(Symbol, 0, LoongArchII::MO_LE_LO_R);393  } else {394    BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1)395        .addDisp(Symbol, 0, LoongArchII::MO_LE_HI);396 397    BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01)398        .addReg(Part1, RegState::Kill)399        .addDisp(Symbol, 0, LoongArchII::MO_LE_LO);400 401    Register Parts012 =402        MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);403 404    BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Parts012)405        // "rj" is needed due to InstrInfo pattern requirement.406        .addReg(Parts01, RegState::Kill)407        .addDisp(Symbol, 0, LoongArchII::MO_LE64_LO);408    BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), DestReg)409        .addReg(Parts012, RegState::Kill)410        .addDisp(Symbol, 0, LoongArchII::MO_LE64_HI);411  }412 413  MI.eraseFromParent();414  return true;415}416 417bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE(418    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,419    MachineBasicBlock::iterator &NextMBBI, bool Large) {420  if (Large)421    // Emit the 5-insn large address load sequence with the `%ie_pc` family422    // of relocs, loading the result with `ldx.d` in the end.423    return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D,424                                  LoongArchII::MO_IE_PC_LO);425 426  // Code Sequence:427  // pcalau12i $rd, %ie_pc_hi20(sym)428  // ld.w/d $rd, $rd, %ie_pc_lo12(sym)429  MachineFunction *MF = MBB.getParent();430  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();431  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;432  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_IE_PC_HI,433                                 SecondOpcode, LoongArchII::MO_IE_PC_LO);434}435 436bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD(437    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,438    MachineBasicBlock::iterator &NextMBBI, bool Large) {439  if (Large)440    // Emit the 5-insn large address load sequence with the `%got_pc` family441    // of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`.442    return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,443                                  LoongArchII::MO_LD_PC_HI);444 445  // Code Sequence:446  // pcalau12i $rd, %ld_pc_hi20(sym)447  // addi.w/d $rd, $rd, %got_pc_lo12(sym)448  MachineFunction *MF = MBB.getParent();449  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();450  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;451  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_LD_PC_HI,452                                 SecondOpcode, LoongArchII::MO_GOT_PC_LO);453}454 455bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD(456    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,457    MachineBasicBlock::iterator &NextMBBI, bool Large) {458  if (Large)459    // Emit the 5-insn large address load sequence with the `%got_pc` family460    // of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`.461    return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D,462                                  LoongArchII::MO_GD_PC_HI);463 464  // Code Sequence:465  // pcalau12i $rd, %gd_pc_hi20(sym)466  // addi.w/d $rd, $rd, %got_pc_lo12(sym)467  MachineFunction *MF = MBB.getParent();468  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();469  unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;470  return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GD_PC_HI,471                                 SecondOpcode, LoongArchII::MO_GOT_PC_LO);472}473 474bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc(475    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,476    MachineBasicBlock::iterator &NextMBBI, bool Large) {477  MachineFunction *MF = MBB.getParent();478  MachineInstr &MI = *MBBI;479  DebugLoc DL = MI.getDebugLoc();480 481  const auto &STI = MF->getSubtarget<LoongArchSubtarget>();482  unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W;483  unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;484  unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;485  bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax);486 487  Register DestReg = MI.getOperand(0).getReg();488  Register Tmp1Reg =489      MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);490  MachineOperand &Symbol = MI.getOperand(Large ? 2 : 1);491 492  BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), Tmp1Reg)493      .addDisp(Symbol, 0,494               LoongArchII::encodeFlags(LoongArchII::MO_DESC_PC_HI,495                                        EnableRelax && !Large));496 497  if (Large) {498    // Code Sequence:499    //500    // pcalau12i  $a0, %desc_pc_hi20(sym)501    // addi.d     $a1, $zero, %desc_pc_lo12(sym)502    // lu32i.d    $a1, %desc64_pc_lo20(sym)503    // lu52i.d    $a1, $a1, %desc64_pc_hi12(sym)504    // add.d      $a0, $a0, $a1505    // ld.d       $ra, $a0, %desc_ld(sym)506    // jirl       $ra, $ra, %desc_call(sym)507    // add.d      $dst, $a0, $tp508    assert(MBB.getParent()->getSubtarget<LoongArchSubtarget>().is64Bit() &&509           "Large code model requires LA64");510    Register Tmp2Reg =511        MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);512    Register Tmp3Reg =513        MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);514    Register Tmp4Reg =515        MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass);516    BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), Tmp2Reg)517        .addReg(LoongArch::R0)518        .addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_LO);519    BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Tmp3Reg)520        .addReg(Tmp2Reg, RegState::Kill)521        .addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_LO);522    BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), Tmp4Reg)523        .addReg(Tmp3Reg)524        .addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_HI);525    BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), LoongArch::R4)526        .addReg(Tmp1Reg)527        .addReg(Tmp4Reg);528  } else {529    // Code Sequence:530    // pcalau12i $a0, %desc_pc_hi20(sym)531    // addi.w/d  $a0, $a0, %desc_pc_lo12(sym)532    // ld.w/d    $ra, $a0, %desc_ld(sym)533    // jirl      $ra, $ra, %desc_call(sym)534    // add.w/d   $dst, $a0, $tp535    BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4)536        .addReg(Tmp1Reg)537        .addDisp(538            Symbol, 0,539            LoongArchII::encodeFlags(LoongArchII::MO_DESC_PC_LO, EnableRelax));540  }541 542  BuildMI(MBB, MBBI, DL, TII->get(LD), LoongArch::R1)543      .addReg(LoongArch::R4)544      .addDisp(Symbol, 0,545               LoongArchII::encodeFlags(LoongArchII::MO_DESC_LD,546                                        EnableRelax && !Large));547  BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1)548      .addReg(LoongArch::R1)549      .addDisp(Symbol, 0,550               LoongArchII::encodeFlags(LoongArchII::MO_DESC_CALL,551                                        EnableRelax && !Large));552  BuildMI(MBB, MBBI, DL, TII->get(ADD), DestReg)553      .addReg(LoongArch::R4)554      .addReg(LoongArch::R2);555 556  MI.eraseFromParent();557  return true;558}559 560bool LoongArchPreRAExpandPseudo::expandFunctionCALL(561    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,562    MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {563  MachineFunction *MF = MBB.getParent();564  MachineInstr &MI = *MBBI;565  DebugLoc DL = MI.getDebugLoc();566  const MachineOperand &Func = MI.getOperand(0);567  MachineInstrBuilder CALL;568  unsigned Opcode;569 570  switch (MF->getTarget().getCodeModel()) {571  default:572    report_fatal_error("Unexpected code model");573    break;574  case CodeModel::Small: {575    // CALL:576    // bl func577    // TAIL:578    // b func579    Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL;580    CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func);581    break;582  }583  case CodeModel::Large: {584    // Emit the 5-insn large address load sequence, either directly or585    // indirectly in case of going through the GOT, then JIRL_TAIL or586    // JIRL_CALL to $addr.587    Opcode =588        IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;589    Register AddrReg =590        IsTailCall591            ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass)592            : LoongArch::R1;593 594    bool UseGOT = Func.getTargetFlags() == LoongArchII::MO_CALL_PLT;595    unsigned MO = UseGOT ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_PCREL_LO;596    unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D;597    expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg,598                           false);599    CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0);600    break;601  }602  }603 604  // Transfer implicit operands.605  CALL.copyImplicitOps(MI);606 607  // Transfer MI flags.608  CALL.setMIFlags(MI.getFlags());609 610  MI.eraseFromParent();611  return true;612}613 614void LoongArchPreRAExpandPseudo::annotateTableJump(615    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {616  MachineFunction *MF = MBB.getParent();617  MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo();618 619  bool IsFound = false;620 621  std::function<void(MachineInstr *, int)> FindJTIMI = [&](MachineInstr *MInst,622                                                           int FindDepth) {623    if (FindDepth < 0)624      return;625    for (auto &MO : MInst->all_uses()) {626      if (IsFound)627        return;628      Register Reg = MO.getReg();629      if (!Reg.isVirtual())630        continue;631      MachineInstr *DefMI = MRI.getVRegDef(Reg);632      if (!DefMI)633        continue;634      for (unsigned Idx = 0; Idx < DefMI->getNumOperands(); ++Idx) {635        MachineOperand &MO = DefMI->getOperand(Idx);636        if (MO.isJTI()) {637          MBBI->setPreInstrSymbol(638              *MF, MF->getContext().createNamedTempSymbol("jrtb_"));639          MF->getInfo<LoongArchMachineFunctionInfo>()->setJumpInfo(640              &*MBBI, MO.getIndex());641          IsFound = true;642          return;643        }644      }645      FindJTIMI(DefMI, --FindDepth);646    }647  };648 649  // FindDepth = 3, probably sufficient.650  FindJTIMI(&*MBBI, /*FindDepth=*/3);651}652 653class LoongArchExpandPseudo : public MachineFunctionPass {654public:655  const LoongArchInstrInfo *TII;656  static char ID;657 658  LoongArchExpandPseudo() : MachineFunctionPass(ID) {}659 660  bool runOnMachineFunction(MachineFunction &MF) override;661 662  StringRef getPassName() const override {663    return LOONGARCH_EXPAND_PSEUDO_NAME;664  }665 666private:667  bool expandMBB(MachineBasicBlock &MBB);668  bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,669                MachineBasicBlock::iterator &NextMBBI);670  bool expandCopyCFR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,671                     MachineBasicBlock::iterator &NextMBBI);672  bool expandFunctionCALL(MachineBasicBlock &MBB,673                          MachineBasicBlock::iterator MBBI,674                          MachineBasicBlock::iterator &NextMBBI,675                          bool IsTailCall);676};677 678char LoongArchExpandPseudo::ID = 0;679 680bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) {681  TII =682      static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo());683 684  bool Modified = false;685  for (auto &MBB : MF)686    Modified |= expandMBB(MBB);687 688  return Modified;689}690 691bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) {692  bool Modified = false;693 694  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();695  while (MBBI != E) {696    MachineBasicBlock::iterator NMBBI = std::next(MBBI);697    Modified |= expandMI(MBB, MBBI, NMBBI);698    MBBI = NMBBI;699  }700 701  return Modified;702}703 704bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB,705                                     MachineBasicBlock::iterator MBBI,706                                     MachineBasicBlock::iterator &NextMBBI) {707  switch (MBBI->getOpcode()) {708  case LoongArch::PseudoCopyCFR:709    return expandCopyCFR(MBB, MBBI, NextMBBI);710  case LoongArch::PseudoCALL_MEDIUM:711    return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false);712  case LoongArch::PseudoTAIL_MEDIUM:713    return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true);714  }715 716  return false;717}718 719bool LoongArchExpandPseudo::expandCopyCFR(720    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,721    MachineBasicBlock::iterator &NextMBBI) {722  MachineFunction *MF = MBB.getParent();723  MachineInstr &MI = *MBBI;724  DebugLoc DL = MI.getDebugLoc();725 726  // Expand:727  // MBB:728  //    fcmp.caf.s  $dst, $fa0, $fa0 # set $dst 0(false)729  //    bceqz $src, SinkBB730  // FalseBB:731  //    fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true)732  // SinkBB:733  //    fallthrough734 735  const BasicBlock *LLVM_BB = MBB.getBasicBlock();736  auto *FalseBB = MF->CreateMachineBasicBlock(LLVM_BB);737  auto *SinkBB = MF->CreateMachineBasicBlock(LLVM_BB);738 739  MF->insert(++MBB.getIterator(), FalseBB);740  MF->insert(++FalseBB->getIterator(), SinkBB);741 742  Register DestReg = MI.getOperand(0).getReg();743  Register SrcReg = MI.getOperand(1).getReg();744  // DestReg = 0745  BuildMI(MBB, MBBI, DL, TII->get(LoongArch::SET_CFR_FALSE), DestReg);746  // Insert branch instruction.747  BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BCEQZ))748      .addReg(SrcReg)749      .addMBB(SinkBB);750  // DestReg = 1751  BuildMI(FalseBB, DL, TII->get(LoongArch::SET_CFR_TRUE), DestReg);752 753  FalseBB->addSuccessor(SinkBB);754 755  SinkBB->splice(SinkBB->end(), &MBB, MI, MBB.end());756  SinkBB->transferSuccessors(&MBB);757 758  MBB.addSuccessor(FalseBB);759  MBB.addSuccessor(SinkBB);760 761  NextMBBI = MBB.end();762  MI.eraseFromParent();763 764  // Make sure live-ins are correctly attached to this new basic block.765  LivePhysRegs LiveRegs;766  computeAndAddLiveIns(LiveRegs, *FalseBB);767  computeAndAddLiveIns(LiveRegs, *SinkBB);768 769  return true;770}771 772bool LoongArchExpandPseudo::expandFunctionCALL(773    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,774    MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) {775  MachineFunction *MF = MBB.getParent();776  MachineInstr &MI = *MBBI;777  DebugLoc DL = MI.getDebugLoc();778  const MachineOperand &Func = MI.getOperand(0);779  MachineInstrBuilder CALL;780  unsigned Opcode;781 782  switch (MF->getTarget().getCodeModel()) {783  default:784    report_fatal_error("Unexpected code model");785    break;786  case CodeModel::Medium: {787    // CALL:788    // pcaddu18i $ra, %call36(func)789    // jirl      $ra, $ra, 0790    // TAIL:791    // pcaddu18i $t8, %call36(func)792    // jirl      $r0, $t8, 0793    Opcode =794        IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL;795    Register ScratchReg = IsTailCall ? LoongArch::R20 : LoongArch::R1;796    MachineInstrBuilder MIB =797        BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg);798 799    CALL =800        BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0);801 802    if (Func.isSymbol())803      MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36);804    else805      MIB.addDisp(Func, 0, LoongArchII::MO_CALL36);806    break;807  }808  }809 810  // Transfer implicit operands.811  CALL.copyImplicitOps(MI);812 813  // Transfer MI flags.814  CALL.setMIFlags(MI.getFlags());815 816  MI.eraseFromParent();817  return true;818}819 820} // end namespace821 822INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo",823                LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false)824 825INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo",826                LOONGARCH_EXPAND_PSEUDO_NAME, false, false)827 828namespace llvm {829 830FunctionPass *createLoongArchPreRAExpandPseudoPass() {831  return new LoongArchPreRAExpandPseudo();832}833FunctionPass *createLoongArchExpandPseudoPass() {834  return new LoongArchExpandPseudo();835}836 837} // end namespace llvm838