brintos

brintos / llvm-project-archived public Read only

0
0
Text · 27.9 KiB · 60e0afd Raw
788 lines · cpp
1//===-- RISCVExpandPseudoInsts.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. This pass should be run after register allocation but before11// the post-regalloc scheduling pass.12//13//===----------------------------------------------------------------------===//14 15#include "RISCV.h"16#include "RISCVInstrInfo.h"17#include "RISCVTargetMachine.h"18 19#include "llvm/CodeGen/LivePhysRegs.h"20#include "llvm/CodeGen/MachineFunctionPass.h"21#include "llvm/CodeGen/MachineInstrBuilder.h"22#include "llvm/MC/MCContext.h"23 24using namespace llvm;25 26#define RISCV_EXPAND_PSEUDO_NAME "RISC-V pseudo instruction expansion pass"27#define RISCV_PRERA_EXPAND_PSEUDO_NAME "RISC-V Pre-RA pseudo instruction expansion pass"28 29namespace {30 31class RISCVExpandPseudo : public MachineFunctionPass {32public:33  const RISCVSubtarget *STI;34  const RISCVInstrInfo *TII;35  static char ID;36 37  RISCVExpandPseudo() : MachineFunctionPass(ID) {}38 39  bool runOnMachineFunction(MachineFunction &MF) override;40 41  StringRef getPassName() const override { return RISCV_EXPAND_PSEUDO_NAME; }42 43private:44  bool expandMBB(MachineBasicBlock &MBB);45  bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,46                MachineBasicBlock::iterator &NextMBBI);47  bool expandCCOp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,48                  MachineBasicBlock::iterator &NextMBBI);49  bool expandCCOpToCMov(MachineBasicBlock &MBB,50                        MachineBasicBlock::iterator MBBI);51  bool expandVMSET_VMCLR(MachineBasicBlock &MBB,52                         MachineBasicBlock::iterator MBBI, unsigned Opcode);53  bool expandMV_FPR16INX(MachineBasicBlock &MBB,54                         MachineBasicBlock::iterator MBBI);55  bool expandMV_FPR32INX(MachineBasicBlock &MBB,56                         MachineBasicBlock::iterator MBBI);57  bool expandRV32ZdinxStore(MachineBasicBlock &MBB,58                            MachineBasicBlock::iterator MBBI);59  bool expandRV32ZdinxLoad(MachineBasicBlock &MBB,60                           MachineBasicBlock::iterator MBBI);61  bool expandPseudoReadVLENBViaVSETVLIX0(MachineBasicBlock &MBB,62                                         MachineBasicBlock::iterator MBBI);63#ifndef NDEBUG64  unsigned getInstSizeInBytes(const MachineFunction &MF) const {65    unsigned Size = 0;66    for (auto &MBB : MF)67      for (auto &MI : MBB)68        Size += TII->getInstSizeInBytes(MI);69    return Size;70  }71#endif72};73 74char RISCVExpandPseudo::ID = 0;75 76bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) {77  STI = &MF.getSubtarget<RISCVSubtarget>();78  TII = STI->getInstrInfo();79 80#ifndef NDEBUG81  const unsigned OldSize = getInstSizeInBytes(MF);82#endif83 84  bool Modified = false;85  for (auto &MBB : MF)86    Modified |= expandMBB(MBB);87 88#ifndef NDEBUG89  const unsigned NewSize = getInstSizeInBytes(MF);90  assert(OldSize >= NewSize);91#endif92  return Modified;93}94 95bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) {96  bool Modified = false;97 98  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();99  while (MBBI != E) {100    MachineBasicBlock::iterator NMBBI = std::next(MBBI);101    Modified |= expandMI(MBB, MBBI, NMBBI);102    MBBI = NMBBI;103  }104 105  return Modified;106}107 108bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB,109                                 MachineBasicBlock::iterator MBBI,110                                 MachineBasicBlock::iterator &NextMBBI) {111  // RISCVInstrInfo::getInstSizeInBytes expects that the total size of the112  // expanded instructions for each pseudo is correct in the Size field of the113  // tablegen definition for the pseudo.114  switch (MBBI->getOpcode()) {115  case RISCV::PseudoMV_FPR16INX:116    return expandMV_FPR16INX(MBB, MBBI);117  case RISCV::PseudoMV_FPR32INX:118    return expandMV_FPR32INX(MBB, MBBI);119  case RISCV::PseudoRV32ZdinxSD:120    return expandRV32ZdinxStore(MBB, MBBI);121  case RISCV::PseudoRV32ZdinxLD:122    return expandRV32ZdinxLoad(MBB, MBBI);123  case RISCV::PseudoCCMOVGPRNoX0:124  case RISCV::PseudoCCMOVGPR:125  case RISCV::PseudoCCADD:126  case RISCV::PseudoCCSUB:127  case RISCV::PseudoCCAND:128  case RISCV::PseudoCCOR:129  case RISCV::PseudoCCXOR:130  case RISCV::PseudoCCMAX:131  case RISCV::PseudoCCMAXU:132  case RISCV::PseudoCCMIN:133  case RISCV::PseudoCCMINU:134  case RISCV::PseudoCCMUL:135  case RISCV::PseudoCCLUI:136  case RISCV::PseudoCCQC_LI:137  case RISCV::PseudoCCQC_E_LI:138  case RISCV::PseudoCCADDW:139  case RISCV::PseudoCCSUBW:140  case RISCV::PseudoCCSLL:141  case RISCV::PseudoCCSRL:142  case RISCV::PseudoCCSRA:143  case RISCV::PseudoCCADDI:144  case RISCV::PseudoCCSLLI:145  case RISCV::PseudoCCSRLI:146  case RISCV::PseudoCCSRAI:147  case RISCV::PseudoCCANDI:148  case RISCV::PseudoCCORI:149  case RISCV::PseudoCCXORI:150  case RISCV::PseudoCCSLLW:151  case RISCV::PseudoCCSRLW:152  case RISCV::PseudoCCSRAW:153  case RISCV::PseudoCCADDIW:154  case RISCV::PseudoCCSLLIW:155  case RISCV::PseudoCCSRLIW:156  case RISCV::PseudoCCSRAIW:157  case RISCV::PseudoCCANDN:158  case RISCV::PseudoCCORN:159  case RISCV::PseudoCCXNOR:160  case RISCV::PseudoCCNDS_BFOS:161  case RISCV::PseudoCCNDS_BFOZ:162    return expandCCOp(MBB, MBBI, NextMBBI);163  case RISCV::PseudoVMCLR_M_B1:164  case RISCV::PseudoVMCLR_M_B2:165  case RISCV::PseudoVMCLR_M_B4:166  case RISCV::PseudoVMCLR_M_B8:167  case RISCV::PseudoVMCLR_M_B16:168  case RISCV::PseudoVMCLR_M_B32:169  case RISCV::PseudoVMCLR_M_B64:170    // vmclr.m vd => vmxor.mm vd, vd, vd171    return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXOR_MM);172  case RISCV::PseudoVMSET_M_B1:173  case RISCV::PseudoVMSET_M_B2:174  case RISCV::PseudoVMSET_M_B4:175  case RISCV::PseudoVMSET_M_B8:176  case RISCV::PseudoVMSET_M_B16:177  case RISCV::PseudoVMSET_M_B32:178  case RISCV::PseudoVMSET_M_B64:179    // vmset.m vd => vmxnor.mm vd, vd, vd180    return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM);181  case RISCV::PseudoReadVLENBViaVSETVLIX0:182    return expandPseudoReadVLENBViaVSETVLIX0(MBB, MBBI);183  }184 185  return false;186}187 188bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB,189                                   MachineBasicBlock::iterator MBBI,190                                   MachineBasicBlock::iterator &NextMBBI) {191  // First try expanding to a Conditional Move rather than a branch+mv192  if (expandCCOpToCMov(MBB, MBBI))193    return true;194 195  MachineFunction *MF = MBB.getParent();196  MachineInstr &MI = *MBBI;197  DebugLoc DL = MI.getDebugLoc();198 199  MachineBasicBlock *TrueBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());200  MachineBasicBlock *MergeBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock());201 202  MF->insert(++MBB.getIterator(), TrueBB);203  MF->insert(++TrueBB->getIterator(), MergeBB);204 205  // We want to copy the "true" value when the condition is true which means206  // we need to invert the branch condition to jump over TrueBB when the207  // condition is false.208  auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());209  CC = RISCVCC::getInverseBranchCondition(CC);210 211  // Insert branch instruction.212  BuildMI(MBB, MBBI, DL, TII->get(RISCVCC::getBrCond(CC)))213      .addReg(MI.getOperand(1).getReg())214      .addReg(MI.getOperand(2).getReg())215      .addMBB(MergeBB);216 217  Register DestReg = MI.getOperand(0).getReg();218  assert(MI.getOperand(4).getReg() == DestReg);219 220  if (MI.getOpcode() == RISCV::PseudoCCMOVGPR ||221      MI.getOpcode() == RISCV::PseudoCCMOVGPRNoX0) {222    // Add MV.223    BuildMI(TrueBB, DL, TII->get(RISCV::ADDI), DestReg)224        .add(MI.getOperand(5))225        .addImm(0);226  } else {227    unsigned NewOpc;228    // clang-format off229    switch (MI.getOpcode()) {230    default:231      llvm_unreachable("Unexpected opcode!");232    case RISCV::PseudoCCADD:   NewOpc = RISCV::ADD;   break;233    case RISCV::PseudoCCSUB:   NewOpc = RISCV::SUB;   break;234    case RISCV::PseudoCCSLL:   NewOpc = RISCV::SLL;   break;235    case RISCV::PseudoCCSRL:   NewOpc = RISCV::SRL;   break;236    case RISCV::PseudoCCSRA:   NewOpc = RISCV::SRA;   break;237    case RISCV::PseudoCCAND:   NewOpc = RISCV::AND;   break;238    case RISCV::PseudoCCOR:    NewOpc = RISCV::OR;    break;239    case RISCV::PseudoCCXOR:   NewOpc = RISCV::XOR;   break;240    case RISCV::PseudoCCMAX:   NewOpc = RISCV::MAX;   break;241    case RISCV::PseudoCCMIN:   NewOpc = RISCV::MIN;   break;242    case RISCV::PseudoCCMAXU:  NewOpc = RISCV::MAXU;  break;243    case RISCV::PseudoCCMINU:  NewOpc = RISCV::MINU;  break;244    case RISCV::PseudoCCMUL:   NewOpc = RISCV::MUL;   break;245    case RISCV::PseudoCCLUI:   NewOpc = RISCV::LUI;   break;246    case RISCV::PseudoCCQC_LI:  NewOpc = RISCV::QC_LI;   break;247    case RISCV::PseudoCCQC_E_LI: NewOpc = RISCV::QC_E_LI;   break;248    case RISCV::PseudoCCADDI:  NewOpc = RISCV::ADDI;  break;249    case RISCV::PseudoCCSLLI:  NewOpc = RISCV::SLLI;  break;250    case RISCV::PseudoCCSRLI:  NewOpc = RISCV::SRLI;  break;251    case RISCV::PseudoCCSRAI:  NewOpc = RISCV::SRAI;  break;252    case RISCV::PseudoCCANDI:  NewOpc = RISCV::ANDI;  break;253    case RISCV::PseudoCCORI:   NewOpc = RISCV::ORI;   break;254    case RISCV::PseudoCCXORI:  NewOpc = RISCV::XORI;  break;255    case RISCV::PseudoCCADDW:  NewOpc = RISCV::ADDW;  break;256    case RISCV::PseudoCCSUBW:  NewOpc = RISCV::SUBW;  break;257    case RISCV::PseudoCCSLLW:  NewOpc = RISCV::SLLW;  break;258    case RISCV::PseudoCCSRLW:  NewOpc = RISCV::SRLW;  break;259    case RISCV::PseudoCCSRAW:  NewOpc = RISCV::SRAW;  break;260    case RISCV::PseudoCCADDIW: NewOpc = RISCV::ADDIW; break;261    case RISCV::PseudoCCSLLIW: NewOpc = RISCV::SLLIW; break;262    case RISCV::PseudoCCSRLIW: NewOpc = RISCV::SRLIW; break;263    case RISCV::PseudoCCSRAIW: NewOpc = RISCV::SRAIW; break;264    case RISCV::PseudoCCANDN:  NewOpc = RISCV::ANDN;  break;265    case RISCV::PseudoCCORN:   NewOpc = RISCV::ORN;   break;266    case RISCV::PseudoCCXNOR:  NewOpc = RISCV::XNOR;  break;267    case RISCV::PseudoCCNDS_BFOS: NewOpc = RISCV::NDS_BFOS; break;268    case RISCV::PseudoCCNDS_BFOZ: NewOpc = RISCV::NDS_BFOZ; break;269    }270    // clang-format on271 272    if (NewOpc == RISCV::NDS_BFOZ || NewOpc == RISCV::NDS_BFOS) {273      BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg)274          .add(MI.getOperand(5))275          .add(MI.getOperand(6))276          .add(MI.getOperand(7));277    } else if (NewOpc == RISCV::LUI || NewOpc == RISCV::QC_LI ||278               NewOpc == RISCV::QC_E_LI) {279      BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg).add(MI.getOperand(5));280    } else {281      BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg)282          .add(MI.getOperand(5))283          .add(MI.getOperand(6));284    }285  }286 287  TrueBB->addSuccessor(MergeBB);288 289  MergeBB->splice(MergeBB->end(), &MBB, MI, MBB.end());290  MergeBB->transferSuccessors(&MBB);291 292  MBB.addSuccessor(TrueBB);293  MBB.addSuccessor(MergeBB);294 295  NextMBBI = MBB.end();296  MI.eraseFromParent();297 298  // Make sure live-ins are correctly attached to this new basic block.299  LivePhysRegs LiveRegs;300  computeAndAddLiveIns(LiveRegs, *TrueBB);301  computeAndAddLiveIns(LiveRegs, *MergeBB);302 303  return true;304}305 306bool RISCVExpandPseudo::expandCCOpToCMov(MachineBasicBlock &MBB,307                                         MachineBasicBlock::iterator MBBI) {308  MachineInstr &MI = *MBBI;309  DebugLoc DL = MI.getDebugLoc();310 311  if (MI.getOpcode() != RISCV::PseudoCCMOVGPR &&312      MI.getOpcode() != RISCV::PseudoCCMOVGPRNoX0)313    return false;314 315  if (!STI->hasVendorXqcicm())316    return false;317 318  // FIXME: Would be wonderful to support LHS=X0, but not very easy.319  if (MI.getOperand(1).getReg() == RISCV::X0 ||320      MI.getOperand(4).getReg() == RISCV::X0 ||321      MI.getOperand(5).getReg() == RISCV::X0)322    return false;323 324  auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm());325 326  unsigned CMovOpcode, CMovIOpcode;327  switch (CC) {328  default:329    llvm_unreachable("Unhandled CC");330  case RISCVCC::COND_EQ:331    CMovOpcode = RISCV::QC_MVEQ;332    CMovIOpcode = RISCV::QC_MVEQI;333    break;334  case RISCVCC::COND_NE:335    CMovOpcode = RISCV::QC_MVNE;336    CMovIOpcode = RISCV::QC_MVNEI;337    break;338  case RISCVCC::COND_LT:339    CMovOpcode = RISCV::QC_MVLT;340    CMovIOpcode = RISCV::QC_MVLTI;341    break;342  case RISCVCC::COND_GE:343    CMovOpcode = RISCV::QC_MVGE;344    CMovIOpcode = RISCV::QC_MVGEI;345    break;346  case RISCVCC::COND_LTU:347    CMovOpcode = RISCV::QC_MVLTU;348    CMovIOpcode = RISCV::QC_MVLTUI;349    break;350  case RISCVCC::COND_GEU:351    CMovOpcode = RISCV::QC_MVGEU;352    CMovIOpcode = RISCV::QC_MVGEUI;353    break;354  }355 356  if (MI.getOperand(2).getReg() == RISCV::X0) {357    // $dst = PseudoCCMOVGPR $lhs, X0, $cc, $falsev (=$dst), $truev358    // $dst = PseudoCCMOVGPRNoX0 $lhs, X0, $cc, $falsev (=$dst), $truev359    // =>360    // $dst = QC_MVccI $falsev (=$dst), $lhs, 0, $truev361    BuildMI(MBB, MBBI, DL, TII->get(CMovIOpcode))362        .addDef(MI.getOperand(0).getReg())363        .addReg(MI.getOperand(4).getReg())364        .addReg(MI.getOperand(1).getReg())365        .addImm(0)366        .addReg(MI.getOperand(5).getReg());367 368    MI.eraseFromParent();369    return true;370  }371 372  // $dst = PseudoCCMOVGPR $lhs, $rhs, $cc, $falsev (=$dst), $truev373  // $dst = PseudoCCMOVGPRNoX0 $lhs, $rhs, $cc, $falsev (=$dst), $truev374  // =>375  // $dst = QC_MVcc $falsev (=$dst), $lhs, $rhs, $truev376  BuildMI(MBB, MBBI, DL, TII->get(CMovOpcode))377      .addDef(MI.getOperand(0).getReg())378      .addReg(MI.getOperand(4).getReg())379      .addReg(MI.getOperand(1).getReg())380      .addReg(MI.getOperand(2).getReg())381      .addReg(MI.getOperand(5).getReg());382  MI.eraseFromParent();383  return true;384}385 386bool RISCVExpandPseudo::expandVMSET_VMCLR(MachineBasicBlock &MBB,387                                          MachineBasicBlock::iterator MBBI,388                                          unsigned Opcode) {389  DebugLoc DL = MBBI->getDebugLoc();390  Register DstReg = MBBI->getOperand(0).getReg();391  const MCInstrDesc &Desc = TII->get(Opcode);392  BuildMI(MBB, MBBI, DL, Desc, DstReg)393      .addReg(DstReg, RegState::Undef)394      .addReg(DstReg, RegState::Undef);395  MBBI->eraseFromParent(); // The pseudo instruction is gone now.396  return true;397}398 399bool RISCVExpandPseudo::expandMV_FPR16INX(MachineBasicBlock &MBB,400                                          MachineBasicBlock::iterator MBBI) {401  DebugLoc DL = MBBI->getDebugLoc();402  const TargetRegisterInfo *TRI = STI->getRegisterInfo();403  Register DstReg = TRI->getMatchingSuperReg(404      MBBI->getOperand(0).getReg(), RISCV::sub_16, &RISCV::GPRRegClass);405  Register SrcReg = TRI->getMatchingSuperReg(406      MBBI->getOperand(1).getReg(), RISCV::sub_16, &RISCV::GPRRegClass);407 408  BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DstReg)409      .addReg(SrcReg, getKillRegState(MBBI->getOperand(1).isKill()))410      .addImm(0);411 412  MBBI->eraseFromParent(); // The pseudo instruction is gone now.413  return true;414}415 416bool RISCVExpandPseudo::expandMV_FPR32INX(MachineBasicBlock &MBB,417                                          MachineBasicBlock::iterator MBBI) {418  DebugLoc DL = MBBI->getDebugLoc();419  const TargetRegisterInfo *TRI = STI->getRegisterInfo();420  Register DstReg = TRI->getMatchingSuperReg(421      MBBI->getOperand(0).getReg(), RISCV::sub_32, &RISCV::GPRRegClass);422  Register SrcReg = TRI->getMatchingSuperReg(423      MBBI->getOperand(1).getReg(), RISCV::sub_32, &RISCV::GPRRegClass);424 425  BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), DstReg)426      .addReg(SrcReg, getKillRegState(MBBI->getOperand(1).isKill()))427      .addImm(0);428 429  MBBI->eraseFromParent(); // The pseudo instruction is gone now.430  return true;431}432 433// This function expands the PseudoRV32ZdinxSD for storing a double-precision434// floating-point value into memory by generating an equivalent instruction435// sequence for RV32.436bool RISCVExpandPseudo::expandRV32ZdinxStore(MachineBasicBlock &MBB,437                                             MachineBasicBlock::iterator MBBI) {438  DebugLoc DL = MBBI->getDebugLoc();439  const TargetRegisterInfo *TRI = STI->getRegisterInfo();440  Register Lo =441      TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_even);442  Register Hi =443      TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd);444  if (Hi == RISCV::DUMMY_REG_PAIR_WITH_X0)445    Hi = RISCV::X0;446 447  auto MIBLo = BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))448                   .addReg(Lo, getKillRegState(MBBI->getOperand(0).isKill()))449                   .addReg(MBBI->getOperand(1).getReg())450                   .add(MBBI->getOperand(2));451 452  MachineInstrBuilder MIBHi;453  if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {454    assert(MBBI->getOperand(2).getOffset() % 8 == 0);455    MBBI->getOperand(2).setOffset(MBBI->getOperand(2).getOffset() + 4);456    MIBHi = BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))457                .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))458                .add(MBBI->getOperand(1))459                .add(MBBI->getOperand(2));460  } else {461    assert(isInt<12>(MBBI->getOperand(2).getImm() + 4));462    MIBHi = BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW))463                .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill()))464                .add(MBBI->getOperand(1))465                .addImm(MBBI->getOperand(2).getImm() + 4);466  }467 468  MachineFunction *MF = MBB.getParent();469  SmallVector<MachineMemOperand *> NewLoMMOs;470  SmallVector<MachineMemOperand *> NewHiMMOs;471  for (const MachineMemOperand *MMO : MBBI->memoperands()) {472    NewLoMMOs.push_back(MF->getMachineMemOperand(MMO, 0, 4));473    NewHiMMOs.push_back(MF->getMachineMemOperand(MMO, 4, 4));474  }475  MIBLo.setMemRefs(NewLoMMOs);476  MIBHi.setMemRefs(NewHiMMOs);477 478  MBBI->eraseFromParent();479  return true;480}481 482// This function expands PseudoRV32ZdinxLoad for loading a double-precision483// floating-point value from memory into an equivalent instruction sequence for484// RV32.485bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB,486                                            MachineBasicBlock::iterator MBBI) {487  DebugLoc DL = MBBI->getDebugLoc();488  const TargetRegisterInfo *TRI = STI->getRegisterInfo();489  Register Lo =490      TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_even);491  Register Hi =492      TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd);493  assert(Hi != RISCV::DUMMY_REG_PAIR_WITH_X0 && "Cannot write to X0_Pair");494 495  MachineInstrBuilder MIBLo, MIBHi;496 497  // If the register of operand 1 is equal to the Lo register, then swap the498  // order of loading the Lo and Hi statements.499  bool IsOp1EqualToLo = Lo == MBBI->getOperand(1).getReg();500  // Order: Lo, Hi501  if (!IsOp1EqualToLo) {502    MIBLo = BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)503                .addReg(MBBI->getOperand(1).getReg())504                .add(MBBI->getOperand(2));505  }506 507  if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) {508    auto Offset = MBBI->getOperand(2).getOffset();509    assert(Offset % 8 == 0);510    MBBI->getOperand(2).setOffset(Offset + 4);511    MIBHi = BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)512                .addReg(MBBI->getOperand(1).getReg())513                .add(MBBI->getOperand(2));514    MBBI->getOperand(2).setOffset(Offset);515  } else {516    assert(isInt<12>(MBBI->getOperand(2).getImm() + 4));517    MIBHi = BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi)518                .addReg(MBBI->getOperand(1).getReg())519                .addImm(MBBI->getOperand(2).getImm() + 4);520  }521 522  // Order: Hi, Lo523  if (IsOp1EqualToLo) {524    MIBLo = BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo)525                .addReg(MBBI->getOperand(1).getReg())526                .add(MBBI->getOperand(2));527  }528 529  MachineFunction *MF = MBB.getParent();530  SmallVector<MachineMemOperand *> NewLoMMOs;531  SmallVector<MachineMemOperand *> NewHiMMOs;532  for (const MachineMemOperand *MMO : MBBI->memoperands()) {533    NewLoMMOs.push_back(MF->getMachineMemOperand(MMO, 0, 4));534    NewHiMMOs.push_back(MF->getMachineMemOperand(MMO, 4, 4));535  }536  MIBLo.setMemRefs(NewLoMMOs);537  MIBHi.setMemRefs(NewHiMMOs);538 539  MBBI->eraseFromParent();540  return true;541}542 543bool RISCVExpandPseudo::expandPseudoReadVLENBViaVSETVLIX0(544    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) {545  DebugLoc DL = MBBI->getDebugLoc();546  Register Dst = MBBI->getOperand(0).getReg();547  unsigned Mul = MBBI->getOperand(1).getImm();548  RISCVVType::VLMUL VLMUL = RISCVVType::encodeLMUL(Mul, /*Fractional=*/false);549  unsigned VTypeImm = RISCVVType::encodeVTYPE(550      VLMUL, /*SEW=*/8, /*TailAgnostic=*/true, /*MaskAgnostic=*/true);551 552  BuildMI(MBB, MBBI, DL, TII->get(RISCV::PseudoVSETVLIX0))553      .addReg(Dst, RegState::Define)554      .addReg(RISCV::X0, RegState::Kill)555      .addImm(VTypeImm);556 557  MBBI->eraseFromParent();558  return true;559}560 561class RISCVPreRAExpandPseudo : public MachineFunctionPass {562public:563  const RISCVSubtarget *STI;564  const RISCVInstrInfo *TII;565  static char ID;566 567  RISCVPreRAExpandPseudo() : MachineFunctionPass(ID) {}568 569  bool runOnMachineFunction(MachineFunction &MF) override;570 571  void getAnalysisUsage(AnalysisUsage &AU) const override {572    AU.setPreservesCFG();573    MachineFunctionPass::getAnalysisUsage(AU);574  }575  StringRef getPassName() const override {576    return RISCV_PRERA_EXPAND_PSEUDO_NAME;577  }578 579private:580  bool expandMBB(MachineBasicBlock &MBB);581  bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,582                MachineBasicBlock::iterator &NextMBBI);583  bool expandAuipcInstPair(MachineBasicBlock &MBB,584                           MachineBasicBlock::iterator MBBI,585                           MachineBasicBlock::iterator &NextMBBI,586                           unsigned FlagsHi, unsigned SecondOpcode);587  bool expandLoadLocalAddress(MachineBasicBlock &MBB,588                              MachineBasicBlock::iterator MBBI,589                              MachineBasicBlock::iterator &NextMBBI);590  bool expandLoadGlobalAddress(MachineBasicBlock &MBB,591                               MachineBasicBlock::iterator MBBI,592                               MachineBasicBlock::iterator &NextMBBI);593  bool expandLoadTLSIEAddress(MachineBasicBlock &MBB,594                              MachineBasicBlock::iterator MBBI,595                              MachineBasicBlock::iterator &NextMBBI);596  bool expandLoadTLSGDAddress(MachineBasicBlock &MBB,597                              MachineBasicBlock::iterator MBBI,598                              MachineBasicBlock::iterator &NextMBBI);599  bool expandLoadTLSDescAddress(MachineBasicBlock &MBB,600                                MachineBasicBlock::iterator MBBI,601                                MachineBasicBlock::iterator &NextMBBI);602 603#ifndef NDEBUG604  unsigned getInstSizeInBytes(const MachineFunction &MF) const {605    unsigned Size = 0;606    for (auto &MBB : MF)607      for (auto &MI : MBB)608        Size += TII->getInstSizeInBytes(MI);609    return Size;610  }611#endif612};613 614char RISCVPreRAExpandPseudo::ID = 0;615 616bool RISCVPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) {617  STI = &MF.getSubtarget<RISCVSubtarget>();618  TII = STI->getInstrInfo();619 620#ifndef NDEBUG621  const unsigned OldSize = getInstSizeInBytes(MF);622#endif623 624  bool Modified = false;625  for (auto &MBB : MF)626    Modified |= expandMBB(MBB);627 628#ifndef NDEBUG629  const unsigned NewSize = getInstSizeInBytes(MF);630  assert(OldSize >= NewSize);631#endif632  return Modified;633}634 635bool RISCVPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) {636  bool Modified = false;637 638  MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end();639  while (MBBI != E) {640    MachineBasicBlock::iterator NMBBI = std::next(MBBI);641    Modified |= expandMI(MBB, MBBI, NMBBI);642    MBBI = NMBBI;643  }644 645  return Modified;646}647 648bool RISCVPreRAExpandPseudo::expandMI(MachineBasicBlock &MBB,649                                      MachineBasicBlock::iterator MBBI,650                                      MachineBasicBlock::iterator &NextMBBI) {651 652  switch (MBBI->getOpcode()) {653  case RISCV::PseudoLLA:654    return expandLoadLocalAddress(MBB, MBBI, NextMBBI);655  case RISCV::PseudoLGA:656    return expandLoadGlobalAddress(MBB, MBBI, NextMBBI);657  case RISCV::PseudoLA_TLS_IE:658    return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI);659  case RISCV::PseudoLA_TLS_GD:660    return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI);661  case RISCV::PseudoLA_TLSDESC:662    return expandLoadTLSDescAddress(MBB, MBBI, NextMBBI);663  }664  return false;665}666 667bool RISCVPreRAExpandPseudo::expandAuipcInstPair(668    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,669    MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi,670    unsigned SecondOpcode) {671  MachineFunction *MF = MBB.getParent();672  MachineInstr &MI = *MBBI;673  DebugLoc DL = MI.getDebugLoc();674 675  Register DestReg = MI.getOperand(0).getReg();676  Register ScratchReg =677      MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);678 679  MachineOperand &Symbol = MI.getOperand(1);680  Symbol.setTargetFlags(FlagsHi);681  MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("pcrel_hi");682 683  MachineInstr *MIAUIPC =684      BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);685  MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);686 687  MachineInstr *SecondMI =688      BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)689          .addReg(ScratchReg)690          .addSym(AUIPCSymbol, RISCVII::MO_PCREL_LO);691 692  if (MI.hasOneMemOperand())693    SecondMI->addMemOperand(*MF, *MI.memoperands_begin());694 695  MI.eraseFromParent();696  return true;697}698 699bool RISCVPreRAExpandPseudo::expandLoadLocalAddress(700    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,701    MachineBasicBlock::iterator &NextMBBI) {702  return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI,703                             RISCV::ADDI);704}705 706bool RISCVPreRAExpandPseudo::expandLoadGlobalAddress(707    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,708    MachineBasicBlock::iterator &NextMBBI) {709  unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW;710  return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_GOT_HI,711                             SecondOpcode);712}713 714bool RISCVPreRAExpandPseudo::expandLoadTLSIEAddress(715    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,716    MachineBasicBlock::iterator &NextMBBI) {717  unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW;718  return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI,719                             SecondOpcode);720}721 722bool RISCVPreRAExpandPseudo::expandLoadTLSGDAddress(723    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,724    MachineBasicBlock::iterator &NextMBBI) {725  return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI,726                             RISCV::ADDI);727}728 729bool RISCVPreRAExpandPseudo::expandLoadTLSDescAddress(730    MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,731    MachineBasicBlock::iterator &NextMBBI) {732  MachineFunction *MF = MBB.getParent();733  MachineInstr &MI = *MBBI;734  DebugLoc DL = MI.getDebugLoc();735 736  const auto &STI = MF->getSubtarget<RISCVSubtarget>();737  unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW;738 739  Register FinalReg = MI.getOperand(0).getReg();740  Register DestReg =741      MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);742  Register ScratchReg =743      MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass);744 745  MachineOperand &Symbol = MI.getOperand(1);746  Symbol.setTargetFlags(RISCVII::MO_TLSDESC_HI);747  MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("tlsdesc_hi");748 749  MachineInstr *MIAUIPC =750      BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol);751  MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol);752 753  BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg)754      .addReg(ScratchReg)755      .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_LOAD_LO);756 757  BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), RISCV::X10)758      .addReg(ScratchReg)759      .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_ADD_LO);760 761  BuildMI(MBB, MBBI, DL, TII->get(RISCV::PseudoTLSDESCCall), RISCV::X5)762      .addReg(DestReg)763      .addImm(0)764      .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_CALL);765 766  BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADD), FinalReg)767      .addReg(RISCV::X10)768      .addReg(RISCV::X4);769 770  MI.eraseFromParent();771  return true;772}773 774} // end of anonymous namespace775 776INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo",777                RISCV_EXPAND_PSEUDO_NAME, false, false)778 779INITIALIZE_PASS(RISCVPreRAExpandPseudo, "riscv-prera-expand-pseudo",780                RISCV_PRERA_EXPAND_PSEUDO_NAME, false, false)781 782namespace llvm {783 784FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); }785FunctionPass *createRISCVPreRAExpandPseudoPass() { return new RISCVPreRAExpandPseudo(); }786 787} // end of namespace llvm788