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