10b57cec5SDimitry Andric //===-- RISCVExpandPseudoInsts.cpp - Expand pseudo instructions -----------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file contains a pass that expands pseudo instructions into target 100b57cec5SDimitry Andric // instructions. This pass should be run after register allocation but before 110b57cec5SDimitry Andric // the post-regalloc scheduling pass. 120b57cec5SDimitry Andric // 130b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 140b57cec5SDimitry Andric 150b57cec5SDimitry Andric #include "RISCV.h" 160b57cec5SDimitry Andric #include "RISCVInstrInfo.h" 170b57cec5SDimitry Andric #include "RISCVTargetMachine.h" 180b57cec5SDimitry Andric 190b57cec5SDimitry Andric #include "llvm/CodeGen/LivePhysRegs.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h" 22bdd1243dSDimitry Andric #include "llvm/MC/MCContext.h" 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric using namespace llvm; 250b57cec5SDimitry Andric 2606c3fb27SDimitry Andric #define RISCV_EXPAND_PSEUDO_NAME "RISC-V pseudo instruction expansion pass" 2706c3fb27SDimitry Andric #define RISCV_PRERA_EXPAND_PSEUDO_NAME "RISC-V Pre-RA pseudo instruction expansion pass" 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric namespace { 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric class RISCVExpandPseudo : public MachineFunctionPass { 320b57cec5SDimitry Andric public: 3306c3fb27SDimitry Andric const RISCVSubtarget *STI; 340b57cec5SDimitry Andric const RISCVInstrInfo *TII; 350b57cec5SDimitry Andric static char ID; 360b57cec5SDimitry Andric 375f757f3fSDimitry Andric RISCVExpandPseudo() : MachineFunctionPass(ID) {} 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric StringRef getPassName() const override { return RISCV_EXPAND_PSEUDO_NAME; } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric private: 440b57cec5SDimitry Andric bool expandMBB(MachineBasicBlock &MBB); 450b57cec5SDimitry Andric bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 460b57cec5SDimitry Andric MachineBasicBlock::iterator &NextMBBI); 47bdd1243dSDimitry Andric bool expandCCOp(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 480b57cec5SDimitry Andric MachineBasicBlock::iterator &NextMBBI); 49e8d8bef9SDimitry Andric bool expandVSetVL(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); 50e8d8bef9SDimitry Andric bool expandVMSET_VMCLR(MachineBasicBlock &MBB, 51e8d8bef9SDimitry Andric MachineBasicBlock::iterator MBBI, unsigned Opcode); 5206c3fb27SDimitry Andric bool expandRV32ZdinxStore(MachineBasicBlock &MBB, 5306c3fb27SDimitry Andric MachineBasicBlock::iterator MBBI); 5406c3fb27SDimitry Andric bool expandRV32ZdinxLoad(MachineBasicBlock &MBB, 5506c3fb27SDimitry Andric MachineBasicBlock::iterator MBBI); 5606c3fb27SDimitry Andric #ifndef NDEBUG 5706c3fb27SDimitry Andric unsigned getInstSizeInBytes(const MachineFunction &MF) const { 5806c3fb27SDimitry Andric unsigned Size = 0; 5906c3fb27SDimitry Andric for (auto &MBB : MF) 6006c3fb27SDimitry Andric for (auto &MI : MBB) 6106c3fb27SDimitry Andric Size += TII->getInstSizeInBytes(MI); 6206c3fb27SDimitry Andric return Size; 6306c3fb27SDimitry Andric } 6406c3fb27SDimitry Andric #endif 650b57cec5SDimitry Andric }; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric char RISCVExpandPseudo::ID = 0; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) { 7006c3fb27SDimitry Andric STI = &MF.getSubtarget<RISCVSubtarget>(); 7106c3fb27SDimitry Andric TII = STI->getInstrInfo(); 7206c3fb27SDimitry Andric 7306c3fb27SDimitry Andric #ifndef NDEBUG 7406c3fb27SDimitry Andric const unsigned OldSize = getInstSizeInBytes(MF); 7506c3fb27SDimitry Andric #endif 7606c3fb27SDimitry Andric 770b57cec5SDimitry Andric bool Modified = false; 780b57cec5SDimitry Andric for (auto &MBB : MF) 790b57cec5SDimitry Andric Modified |= expandMBB(MBB); 8006c3fb27SDimitry Andric 8106c3fb27SDimitry Andric #ifndef NDEBUG 8206c3fb27SDimitry Andric const unsigned NewSize = getInstSizeInBytes(MF); 8306c3fb27SDimitry Andric assert(OldSize >= NewSize); 8406c3fb27SDimitry Andric #endif 850b57cec5SDimitry Andric return Modified; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) { 890b57cec5SDimitry Andric bool Modified = false; 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 920b57cec5SDimitry Andric while (MBBI != E) { 930b57cec5SDimitry Andric MachineBasicBlock::iterator NMBBI = std::next(MBBI); 940b57cec5SDimitry Andric Modified |= expandMI(MBB, MBBI, NMBBI); 950b57cec5SDimitry Andric MBBI = NMBBI; 960b57cec5SDimitry Andric } 970b57cec5SDimitry Andric 980b57cec5SDimitry Andric return Modified; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB, 1020b57cec5SDimitry Andric MachineBasicBlock::iterator MBBI, 1030b57cec5SDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 1041fd87a68SDimitry Andric // RISCVInstrInfo::getInstSizeInBytes expects that the total size of the 1051fd87a68SDimitry Andric // expanded instructions for each pseudo is correct in the Size field of the 1061fd87a68SDimitry Andric // tablegen definition for the pseudo. 1070b57cec5SDimitry Andric switch (MBBI->getOpcode()) { 10806c3fb27SDimitry Andric case RISCV::PseudoRV32ZdinxSD: 10906c3fb27SDimitry Andric return expandRV32ZdinxStore(MBB, MBBI); 11006c3fb27SDimitry Andric case RISCV::PseudoRV32ZdinxLD: 11106c3fb27SDimitry Andric return expandRV32ZdinxLoad(MBB, MBBI); 1121db9f3b2SDimitry Andric case RISCV::PseudoCCMOVGPRNoX0: 113bdd1243dSDimitry Andric case RISCV::PseudoCCMOVGPR: 114bdd1243dSDimitry Andric case RISCV::PseudoCCADD: 115bdd1243dSDimitry Andric case RISCV::PseudoCCSUB: 116bdd1243dSDimitry Andric case RISCV::PseudoCCAND: 117bdd1243dSDimitry Andric case RISCV::PseudoCCOR: 118bdd1243dSDimitry Andric case RISCV::PseudoCCXOR: 119bdd1243dSDimitry Andric case RISCV::PseudoCCADDW: 120bdd1243dSDimitry Andric case RISCV::PseudoCCSUBW: 1215f757f3fSDimitry Andric case RISCV::PseudoCCSLL: 1225f757f3fSDimitry Andric case RISCV::PseudoCCSRL: 1235f757f3fSDimitry Andric case RISCV::PseudoCCSRA: 1245f757f3fSDimitry Andric case RISCV::PseudoCCADDI: 1255f757f3fSDimitry Andric case RISCV::PseudoCCSLLI: 1265f757f3fSDimitry Andric case RISCV::PseudoCCSRLI: 1275f757f3fSDimitry Andric case RISCV::PseudoCCSRAI: 1285f757f3fSDimitry Andric case RISCV::PseudoCCANDI: 1295f757f3fSDimitry Andric case RISCV::PseudoCCORI: 1305f757f3fSDimitry Andric case RISCV::PseudoCCXORI: 1315f757f3fSDimitry Andric case RISCV::PseudoCCSLLW: 1325f757f3fSDimitry Andric case RISCV::PseudoCCSRLW: 1335f757f3fSDimitry Andric case RISCV::PseudoCCSRAW: 1345f757f3fSDimitry Andric case RISCV::PseudoCCADDIW: 1355f757f3fSDimitry Andric case RISCV::PseudoCCSLLIW: 1365f757f3fSDimitry Andric case RISCV::PseudoCCSRLIW: 1375f757f3fSDimitry Andric case RISCV::PseudoCCSRAIW: 1381db9f3b2SDimitry Andric case RISCV::PseudoCCANDN: 1391db9f3b2SDimitry Andric case RISCV::PseudoCCORN: 1401db9f3b2SDimitry Andric case RISCV::PseudoCCXNOR: 141bdd1243dSDimitry Andric return expandCCOp(MBB, MBBI, NextMBBI); 142e8d8bef9SDimitry Andric case RISCV::PseudoVSETVLI: 143349cc55cSDimitry Andric case RISCV::PseudoVSETVLIX0: 144d409305fSDimitry Andric case RISCV::PseudoVSETIVLI: 145e8d8bef9SDimitry Andric return expandVSetVL(MBB, MBBI); 146e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B1: 147e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B2: 148e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B4: 149e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B8: 150e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B16: 151e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B32: 152e8d8bef9SDimitry Andric case RISCV::PseudoVMCLR_M_B64: 153e8d8bef9SDimitry Andric // vmclr.m vd => vmxor.mm vd, vd, vd 154e8d8bef9SDimitry Andric return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXOR_MM); 155e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B1: 156e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B2: 157e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B4: 158e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B8: 159e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B16: 160e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B32: 161e8d8bef9SDimitry Andric case RISCV::PseudoVMSET_M_B64: 162e8d8bef9SDimitry Andric // vmset.m vd => vmxnor.mm vd, vd, vd 163e8d8bef9SDimitry Andric return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM); 1640b57cec5SDimitry Andric } 1650b57cec5SDimitry Andric 1660b57cec5SDimitry Andric return false; 1670b57cec5SDimitry Andric } 1680b57cec5SDimitry Andric 169bdd1243dSDimitry Andric bool RISCVExpandPseudo::expandCCOp(MachineBasicBlock &MBB, 170bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI, 171bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 172bdd1243dSDimitry Andric 1730b57cec5SDimitry Andric MachineFunction *MF = MBB.getParent(); 1740b57cec5SDimitry Andric MachineInstr &MI = *MBBI; 1750b57cec5SDimitry Andric DebugLoc DL = MI.getDebugLoc(); 1760b57cec5SDimitry Andric 177bdd1243dSDimitry Andric MachineBasicBlock *TrueBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 178bdd1243dSDimitry Andric MachineBasicBlock *MergeBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 179bdd1243dSDimitry Andric 180bdd1243dSDimitry Andric MF->insert(++MBB.getIterator(), TrueBB); 181bdd1243dSDimitry Andric MF->insert(++TrueBB->getIterator(), MergeBB); 182bdd1243dSDimitry Andric 183bdd1243dSDimitry Andric // We want to copy the "true" value when the condition is true which means 184bdd1243dSDimitry Andric // we need to invert the branch condition to jump over TrueBB when the 185bdd1243dSDimitry Andric // condition is false. 186bdd1243dSDimitry Andric auto CC = static_cast<RISCVCC::CondCode>(MI.getOperand(3).getImm()); 187bdd1243dSDimitry Andric CC = RISCVCC::getOppositeBranchCondition(CC); 188bdd1243dSDimitry Andric 189bdd1243dSDimitry Andric // Insert branch instruction. 190bdd1243dSDimitry Andric BuildMI(MBB, MBBI, DL, TII->getBrCond(CC)) 191bdd1243dSDimitry Andric .addReg(MI.getOperand(1).getReg()) 192bdd1243dSDimitry Andric .addReg(MI.getOperand(2).getReg()) 193bdd1243dSDimitry Andric .addMBB(MergeBB); 194bdd1243dSDimitry Andric 1958bcb0991SDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 196bdd1243dSDimitry Andric assert(MI.getOperand(4).getReg() == DestReg); 1970b57cec5SDimitry Andric 1981db9f3b2SDimitry Andric if (MI.getOpcode() == RISCV::PseudoCCMOVGPR || 1991db9f3b2SDimitry Andric MI.getOpcode() == RISCV::PseudoCCMOVGPRNoX0) { 200bdd1243dSDimitry Andric // Add MV. 201bdd1243dSDimitry Andric BuildMI(TrueBB, DL, TII->get(RISCV::ADDI), DestReg) 202bdd1243dSDimitry Andric .add(MI.getOperand(5)) 203bdd1243dSDimitry Andric .addImm(0); 204bdd1243dSDimitry Andric } else { 205bdd1243dSDimitry Andric unsigned NewOpc; 206bdd1243dSDimitry Andric switch (MI.getOpcode()) { 207bdd1243dSDimitry Andric default: 208bdd1243dSDimitry Andric llvm_unreachable("Unexpected opcode!"); 209bdd1243dSDimitry Andric case RISCV::PseudoCCADD: NewOpc = RISCV::ADD; break; 210bdd1243dSDimitry Andric case RISCV::PseudoCCSUB: NewOpc = RISCV::SUB; break; 2115f757f3fSDimitry Andric case RISCV::PseudoCCSLL: NewOpc = RISCV::SLL; break; 2125f757f3fSDimitry Andric case RISCV::PseudoCCSRL: NewOpc = RISCV::SRL; break; 2135f757f3fSDimitry Andric case RISCV::PseudoCCSRA: NewOpc = RISCV::SRA; break; 214bdd1243dSDimitry Andric case RISCV::PseudoCCAND: NewOpc = RISCV::AND; break; 215bdd1243dSDimitry Andric case RISCV::PseudoCCOR: NewOpc = RISCV::OR; break; 216bdd1243dSDimitry Andric case RISCV::PseudoCCXOR: NewOpc = RISCV::XOR; break; 2175f757f3fSDimitry Andric case RISCV::PseudoCCADDI: NewOpc = RISCV::ADDI; break; 2185f757f3fSDimitry Andric case RISCV::PseudoCCSLLI: NewOpc = RISCV::SLLI; break; 2195f757f3fSDimitry Andric case RISCV::PseudoCCSRLI: NewOpc = RISCV::SRLI; break; 2205f757f3fSDimitry Andric case RISCV::PseudoCCSRAI: NewOpc = RISCV::SRAI; break; 2215f757f3fSDimitry Andric case RISCV::PseudoCCANDI: NewOpc = RISCV::ANDI; break; 2225f757f3fSDimitry Andric case RISCV::PseudoCCORI: NewOpc = RISCV::ORI; break; 2235f757f3fSDimitry Andric case RISCV::PseudoCCXORI: NewOpc = RISCV::XORI; break; 224bdd1243dSDimitry Andric case RISCV::PseudoCCADDW: NewOpc = RISCV::ADDW; break; 225bdd1243dSDimitry Andric case RISCV::PseudoCCSUBW: NewOpc = RISCV::SUBW; break; 2265f757f3fSDimitry Andric case RISCV::PseudoCCSLLW: NewOpc = RISCV::SLLW; break; 2275f757f3fSDimitry Andric case RISCV::PseudoCCSRLW: NewOpc = RISCV::SRLW; break; 2285f757f3fSDimitry Andric case RISCV::PseudoCCSRAW: NewOpc = RISCV::SRAW; break; 2295f757f3fSDimitry Andric case RISCV::PseudoCCADDIW: NewOpc = RISCV::ADDIW; break; 2305f757f3fSDimitry Andric case RISCV::PseudoCCSLLIW: NewOpc = RISCV::SLLIW; break; 2315f757f3fSDimitry Andric case RISCV::PseudoCCSRLIW: NewOpc = RISCV::SRLIW; break; 2325f757f3fSDimitry Andric case RISCV::PseudoCCSRAIW: NewOpc = RISCV::SRAIW; break; 2331db9f3b2SDimitry Andric case RISCV::PseudoCCANDN: NewOpc = RISCV::ANDN; break; 2341db9f3b2SDimitry Andric case RISCV::PseudoCCORN: NewOpc = RISCV::ORN; break; 2351db9f3b2SDimitry Andric case RISCV::PseudoCCXNOR: NewOpc = RISCV::XNOR; break; 236bdd1243dSDimitry Andric } 237bdd1243dSDimitry Andric BuildMI(TrueBB, DL, TII->get(NewOpc), DestReg) 238bdd1243dSDimitry Andric .add(MI.getOperand(5)) 239bdd1243dSDimitry Andric .add(MI.getOperand(6)); 240bdd1243dSDimitry Andric } 2410b57cec5SDimitry Andric 242bdd1243dSDimitry Andric TrueBB->addSuccessor(MergeBB); 2430b57cec5SDimitry Andric 244bdd1243dSDimitry Andric MergeBB->splice(MergeBB->end(), &MBB, MI, MBB.end()); 245bdd1243dSDimitry Andric MergeBB->transferSuccessors(&MBB); 2460b57cec5SDimitry Andric 247bdd1243dSDimitry Andric MBB.addSuccessor(TrueBB); 248bdd1243dSDimitry Andric MBB.addSuccessor(MergeBB); 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric NextMBBI = MBB.end(); 2510b57cec5SDimitry Andric MI.eraseFromParent(); 252bdd1243dSDimitry Andric 253bdd1243dSDimitry Andric // Make sure live-ins are correctly attached to this new basic block. 254bdd1243dSDimitry Andric LivePhysRegs LiveRegs; 255bdd1243dSDimitry Andric computeAndAddLiveIns(LiveRegs, *TrueBB); 256bdd1243dSDimitry Andric computeAndAddLiveIns(LiveRegs, *MergeBB); 257bdd1243dSDimitry Andric 2580b57cec5SDimitry Andric return true; 2590b57cec5SDimitry Andric } 2600b57cec5SDimitry Andric 261e8d8bef9SDimitry Andric bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock &MBB, 262e8d8bef9SDimitry Andric MachineBasicBlock::iterator MBBI) { 263fe6060f1SDimitry Andric assert(MBBI->getNumExplicitOperands() == 3 && MBBI->getNumOperands() >= 5 && 264fe6060f1SDimitry Andric "Unexpected instruction format"); 265e8d8bef9SDimitry Andric 266e8d8bef9SDimitry Andric DebugLoc DL = MBBI->getDebugLoc(); 267e8d8bef9SDimitry Andric 268d409305fSDimitry Andric assert((MBBI->getOpcode() == RISCV::PseudoVSETVLI || 269349cc55cSDimitry Andric MBBI->getOpcode() == RISCV::PseudoVSETVLIX0 || 270d409305fSDimitry Andric MBBI->getOpcode() == RISCV::PseudoVSETIVLI) && 271e8d8bef9SDimitry Andric "Unexpected pseudo instruction"); 272d409305fSDimitry Andric unsigned Opcode; 273349cc55cSDimitry Andric if (MBBI->getOpcode() == RISCV::PseudoVSETIVLI) 274d409305fSDimitry Andric Opcode = RISCV::VSETIVLI; 275349cc55cSDimitry Andric else 276349cc55cSDimitry Andric Opcode = RISCV::VSETVLI; 277d409305fSDimitry Andric const MCInstrDesc &Desc = TII->get(Opcode); 278e8d8bef9SDimitry Andric assert(Desc.getNumOperands() == 3 && "Unexpected instruction format"); 279e8d8bef9SDimitry Andric 280e8d8bef9SDimitry Andric Register DstReg = MBBI->getOperand(0).getReg(); 281e8d8bef9SDimitry Andric bool DstIsDead = MBBI->getOperand(0).isDead(); 282e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, Desc) 283e8d8bef9SDimitry Andric .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) 284e8d8bef9SDimitry Andric .add(MBBI->getOperand(1)) // VL 285e8d8bef9SDimitry Andric .add(MBBI->getOperand(2)); // VType 286e8d8bef9SDimitry Andric 287e8d8bef9SDimitry Andric MBBI->eraseFromParent(); // The pseudo instruction is gone now. 288e8d8bef9SDimitry Andric return true; 289e8d8bef9SDimitry Andric } 290e8d8bef9SDimitry Andric 291e8d8bef9SDimitry Andric bool RISCVExpandPseudo::expandVMSET_VMCLR(MachineBasicBlock &MBB, 292e8d8bef9SDimitry Andric MachineBasicBlock::iterator MBBI, 293e8d8bef9SDimitry Andric unsigned Opcode) { 294e8d8bef9SDimitry Andric DebugLoc DL = MBBI->getDebugLoc(); 295e8d8bef9SDimitry Andric Register DstReg = MBBI->getOperand(0).getReg(); 296e8d8bef9SDimitry Andric const MCInstrDesc &Desc = TII->get(Opcode); 297e8d8bef9SDimitry Andric BuildMI(MBB, MBBI, DL, Desc, DstReg) 298e8d8bef9SDimitry Andric .addReg(DstReg, RegState::Undef) 299e8d8bef9SDimitry Andric .addReg(DstReg, RegState::Undef); 300e8d8bef9SDimitry Andric MBBI->eraseFromParent(); // The pseudo instruction is gone now. 301e8d8bef9SDimitry Andric return true; 302e8d8bef9SDimitry Andric } 303e8d8bef9SDimitry Andric 30406c3fb27SDimitry Andric // This function expands the PseudoRV32ZdinxSD for storing a double-precision 30506c3fb27SDimitry Andric // floating-point value into memory by generating an equivalent instruction 30606c3fb27SDimitry Andric // sequence for RV32. 30706c3fb27SDimitry Andric bool RISCVExpandPseudo::expandRV32ZdinxStore(MachineBasicBlock &MBB, 30806c3fb27SDimitry Andric MachineBasicBlock::iterator MBBI) { 30906c3fb27SDimitry Andric DebugLoc DL = MBBI->getDebugLoc(); 31006c3fb27SDimitry Andric const TargetRegisterInfo *TRI = STI->getRegisterInfo(); 311297eecfbSDimitry Andric Register Lo = 312297eecfbSDimitry Andric TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_even); 313297eecfbSDimitry Andric Register Hi = 314297eecfbSDimitry Andric TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd); 315*0fca6ea1SDimitry Andric 316*0fca6ea1SDimitry Andric assert(MBBI->hasOneMemOperand() && "Expected mem operand"); 317*0fca6ea1SDimitry Andric MachineMemOperand *OldMMO = MBBI->memoperands().front(); 318*0fca6ea1SDimitry Andric MachineFunction *MF = MBB.getParent(); 319*0fca6ea1SDimitry Andric MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4); 320*0fca6ea1SDimitry Andric MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4); 321*0fca6ea1SDimitry Andric 32206c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW)) 32306c3fb27SDimitry Andric .addReg(Lo, getKillRegState(MBBI->getOperand(0).isKill())) 32406c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg()) 325*0fca6ea1SDimitry Andric .add(MBBI->getOperand(2)) 326*0fca6ea1SDimitry Andric .setMemRefs(MMOLo); 327*0fca6ea1SDimitry Andric 32806c3fb27SDimitry Andric if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) { 3293a079333SDimitry Andric // FIXME: Zdinx RV32 can not work on unaligned scalar memory. 330*0fca6ea1SDimitry Andric assert(!STI->enableUnalignedScalarMem()); 33106c3fb27SDimitry Andric 33206c3fb27SDimitry Andric assert(MBBI->getOperand(2).getOffset() % 8 == 0); 33306c3fb27SDimitry Andric MBBI->getOperand(2).setOffset(MBBI->getOperand(2).getOffset() + 4); 33406c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW)) 33506c3fb27SDimitry Andric .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill())) 33606c3fb27SDimitry Andric .add(MBBI->getOperand(1)) 337*0fca6ea1SDimitry Andric .add(MBBI->getOperand(2)) 338*0fca6ea1SDimitry Andric .setMemRefs(MMOHi); 33906c3fb27SDimitry Andric } else { 34006c3fb27SDimitry Andric assert(isInt<12>(MBBI->getOperand(2).getImm() + 4)); 34106c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::SW)) 34206c3fb27SDimitry Andric .addReg(Hi, getKillRegState(MBBI->getOperand(0).isKill())) 34306c3fb27SDimitry Andric .add(MBBI->getOperand(1)) 344*0fca6ea1SDimitry Andric .addImm(MBBI->getOperand(2).getImm() + 4) 345*0fca6ea1SDimitry Andric .setMemRefs(MMOHi); 34606c3fb27SDimitry Andric } 34706c3fb27SDimitry Andric MBBI->eraseFromParent(); 34806c3fb27SDimitry Andric return true; 34906c3fb27SDimitry Andric } 35006c3fb27SDimitry Andric 35106c3fb27SDimitry Andric // This function expands PseudoRV32ZdinxLoad for loading a double-precision 35206c3fb27SDimitry Andric // floating-point value from memory into an equivalent instruction sequence for 35306c3fb27SDimitry Andric // RV32. 35406c3fb27SDimitry Andric bool RISCVExpandPseudo::expandRV32ZdinxLoad(MachineBasicBlock &MBB, 35506c3fb27SDimitry Andric MachineBasicBlock::iterator MBBI) { 35606c3fb27SDimitry Andric DebugLoc DL = MBBI->getDebugLoc(); 35706c3fb27SDimitry Andric const TargetRegisterInfo *TRI = STI->getRegisterInfo(); 358297eecfbSDimitry Andric Register Lo = 359297eecfbSDimitry Andric TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_even); 360297eecfbSDimitry Andric Register Hi = 361297eecfbSDimitry Andric TRI->getSubReg(MBBI->getOperand(0).getReg(), RISCV::sub_gpr_odd); 36206c3fb27SDimitry Andric 363*0fca6ea1SDimitry Andric assert(MBBI->hasOneMemOperand() && "Expected mem operand"); 364*0fca6ea1SDimitry Andric MachineMemOperand *OldMMO = MBBI->memoperands().front(); 365*0fca6ea1SDimitry Andric MachineFunction *MF = MBB.getParent(); 366*0fca6ea1SDimitry Andric MachineMemOperand *MMOLo = MF->getMachineMemOperand(OldMMO, 0, 4); 367*0fca6ea1SDimitry Andric MachineMemOperand *MMOHi = MF->getMachineMemOperand(OldMMO, 4, 4); 368*0fca6ea1SDimitry Andric 36906c3fb27SDimitry Andric // If the register of operand 1 is equal to the Lo register, then swap the 37006c3fb27SDimitry Andric // order of loading the Lo and Hi statements. 37106c3fb27SDimitry Andric bool IsOp1EqualToLo = Lo == MBBI->getOperand(1).getReg(); 37206c3fb27SDimitry Andric // Order: Lo, Hi 37306c3fb27SDimitry Andric if (!IsOp1EqualToLo) { 37406c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo) 37506c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg()) 376*0fca6ea1SDimitry Andric .add(MBBI->getOperand(2)) 377*0fca6ea1SDimitry Andric .setMemRefs(MMOLo); 37806c3fb27SDimitry Andric } 37906c3fb27SDimitry Andric 38006c3fb27SDimitry Andric if (MBBI->getOperand(2).isGlobal() || MBBI->getOperand(2).isCPI()) { 38106c3fb27SDimitry Andric auto Offset = MBBI->getOperand(2).getOffset(); 38206c3fb27SDimitry Andric assert(MBBI->getOperand(2).getOffset() % 8 == 0); 38306c3fb27SDimitry Andric MBBI->getOperand(2).setOffset(Offset + 4); 38406c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi) 38506c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg()) 386*0fca6ea1SDimitry Andric .add(MBBI->getOperand(2)) 387*0fca6ea1SDimitry Andric .setMemRefs(MMOHi); 38806c3fb27SDimitry Andric MBBI->getOperand(2).setOffset(Offset); 38906c3fb27SDimitry Andric } else { 39006c3fb27SDimitry Andric assert(isInt<12>(MBBI->getOperand(2).getImm() + 4)); 39106c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Hi) 39206c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg()) 393*0fca6ea1SDimitry Andric .addImm(MBBI->getOperand(2).getImm() + 4) 394*0fca6ea1SDimitry Andric .setMemRefs(MMOHi); 39506c3fb27SDimitry Andric } 39606c3fb27SDimitry Andric 39706c3fb27SDimitry Andric // Order: Hi, Lo 39806c3fb27SDimitry Andric if (IsOp1EqualToLo) { 39906c3fb27SDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::LW), Lo) 40006c3fb27SDimitry Andric .addReg(MBBI->getOperand(1).getReg()) 401*0fca6ea1SDimitry Andric .add(MBBI->getOperand(2)) 402*0fca6ea1SDimitry Andric .setMemRefs(MMOLo); 40306c3fb27SDimitry Andric } 40406c3fb27SDimitry Andric 40506c3fb27SDimitry Andric MBBI->eraseFromParent(); 40606c3fb27SDimitry Andric return true; 40706c3fb27SDimitry Andric } 40806c3fb27SDimitry Andric 409bdd1243dSDimitry Andric class RISCVPreRAExpandPseudo : public MachineFunctionPass { 410bdd1243dSDimitry Andric public: 41106c3fb27SDimitry Andric const RISCVSubtarget *STI; 412bdd1243dSDimitry Andric const RISCVInstrInfo *TII; 413bdd1243dSDimitry Andric static char ID; 414fe6060f1SDimitry Andric 4155f757f3fSDimitry Andric RISCVPreRAExpandPseudo() : MachineFunctionPass(ID) {} 416bdd1243dSDimitry Andric 417bdd1243dSDimitry Andric bool runOnMachineFunction(MachineFunction &MF) override; 418bdd1243dSDimitry Andric 419bdd1243dSDimitry Andric void getAnalysisUsage(AnalysisUsage &AU) const override { 420bdd1243dSDimitry Andric AU.setPreservesCFG(); 421bdd1243dSDimitry Andric MachineFunctionPass::getAnalysisUsage(AU); 422bdd1243dSDimitry Andric } 423bdd1243dSDimitry Andric StringRef getPassName() const override { 424bdd1243dSDimitry Andric return RISCV_PRERA_EXPAND_PSEUDO_NAME; 425bdd1243dSDimitry Andric } 426bdd1243dSDimitry Andric 427bdd1243dSDimitry Andric private: 428bdd1243dSDimitry Andric bool expandMBB(MachineBasicBlock &MBB); 429bdd1243dSDimitry Andric bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 430bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI); 431bdd1243dSDimitry Andric bool expandAuipcInstPair(MachineBasicBlock &MBB, 432bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI, 433bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI, 434bdd1243dSDimitry Andric unsigned FlagsHi, unsigned SecondOpcode); 435bdd1243dSDimitry Andric bool expandLoadLocalAddress(MachineBasicBlock &MBB, 436bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI, 437bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI); 43806c3fb27SDimitry Andric bool expandLoadGlobalAddress(MachineBasicBlock &MBB, 439bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI, 440bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI); 441bdd1243dSDimitry Andric bool expandLoadTLSIEAddress(MachineBasicBlock &MBB, 442bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI, 443bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI); 444bdd1243dSDimitry Andric bool expandLoadTLSGDAddress(MachineBasicBlock &MBB, 445bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI, 446bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI); 4477a6dacacSDimitry Andric bool expandLoadTLSDescAddress(MachineBasicBlock &MBB, 4487a6dacacSDimitry Andric MachineBasicBlock::iterator MBBI, 4497a6dacacSDimitry Andric MachineBasicBlock::iterator &NextMBBI); 4507a6dacacSDimitry Andric 45106c3fb27SDimitry Andric #ifndef NDEBUG 45206c3fb27SDimitry Andric unsigned getInstSizeInBytes(const MachineFunction &MF) const { 45306c3fb27SDimitry Andric unsigned Size = 0; 45406c3fb27SDimitry Andric for (auto &MBB : MF) 45506c3fb27SDimitry Andric for (auto &MI : MBB) 45606c3fb27SDimitry Andric Size += TII->getInstSizeInBytes(MI); 45706c3fb27SDimitry Andric return Size; 45806c3fb27SDimitry Andric } 45906c3fb27SDimitry Andric #endif 460bdd1243dSDimitry Andric }; 461bdd1243dSDimitry Andric 462bdd1243dSDimitry Andric char RISCVPreRAExpandPseudo::ID = 0; 463bdd1243dSDimitry Andric 464bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) { 46506c3fb27SDimitry Andric STI = &MF.getSubtarget<RISCVSubtarget>(); 46606c3fb27SDimitry Andric TII = STI->getInstrInfo(); 46706c3fb27SDimitry Andric 46806c3fb27SDimitry Andric #ifndef NDEBUG 46906c3fb27SDimitry Andric const unsigned OldSize = getInstSizeInBytes(MF); 47006c3fb27SDimitry Andric #endif 47106c3fb27SDimitry Andric 472bdd1243dSDimitry Andric bool Modified = false; 473bdd1243dSDimitry Andric for (auto &MBB : MF) 474bdd1243dSDimitry Andric Modified |= expandMBB(MBB); 47506c3fb27SDimitry Andric 47606c3fb27SDimitry Andric #ifndef NDEBUG 47706c3fb27SDimitry Andric const unsigned NewSize = getInstSizeInBytes(MF); 47806c3fb27SDimitry Andric assert(OldSize >= NewSize); 47906c3fb27SDimitry Andric #endif 480bdd1243dSDimitry Andric return Modified; 481bdd1243dSDimitry Andric } 482bdd1243dSDimitry Andric 483bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) { 484bdd1243dSDimitry Andric bool Modified = false; 485bdd1243dSDimitry Andric 486bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 487bdd1243dSDimitry Andric while (MBBI != E) { 488bdd1243dSDimitry Andric MachineBasicBlock::iterator NMBBI = std::next(MBBI); 489bdd1243dSDimitry Andric Modified |= expandMI(MBB, MBBI, NMBBI); 490bdd1243dSDimitry Andric MBBI = NMBBI; 491bdd1243dSDimitry Andric } 492bdd1243dSDimitry Andric 493bdd1243dSDimitry Andric return Modified; 494bdd1243dSDimitry Andric } 495bdd1243dSDimitry Andric 496bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandMI(MachineBasicBlock &MBB, 497bdd1243dSDimitry Andric MachineBasicBlock::iterator MBBI, 498bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 499bdd1243dSDimitry Andric 500bdd1243dSDimitry Andric switch (MBBI->getOpcode()) { 501bdd1243dSDimitry Andric case RISCV::PseudoLLA: 502bdd1243dSDimitry Andric return expandLoadLocalAddress(MBB, MBBI, NextMBBI); 50306c3fb27SDimitry Andric case RISCV::PseudoLGA: 50406c3fb27SDimitry Andric return expandLoadGlobalAddress(MBB, MBBI, NextMBBI); 505bdd1243dSDimitry Andric case RISCV::PseudoLA_TLS_IE: 506bdd1243dSDimitry Andric return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI); 507bdd1243dSDimitry Andric case RISCV::PseudoLA_TLS_GD: 508bdd1243dSDimitry Andric return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI); 5097a6dacacSDimitry Andric case RISCV::PseudoLA_TLSDESC: 5107a6dacacSDimitry Andric return expandLoadTLSDescAddress(MBB, MBBI, NextMBBI); 511bdd1243dSDimitry Andric } 512bdd1243dSDimitry Andric return false; 513bdd1243dSDimitry Andric } 514bdd1243dSDimitry Andric 515bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandAuipcInstPair( 516bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 517bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi, 518bdd1243dSDimitry Andric unsigned SecondOpcode) { 519bdd1243dSDimitry Andric MachineFunction *MF = MBB.getParent(); 520bdd1243dSDimitry Andric MachineInstr &MI = *MBBI; 521bdd1243dSDimitry Andric DebugLoc DL = MI.getDebugLoc(); 522bdd1243dSDimitry Andric 523bdd1243dSDimitry Andric Register DestReg = MI.getOperand(0).getReg(); 524bdd1243dSDimitry Andric Register ScratchReg = 525bdd1243dSDimitry Andric MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass); 526bdd1243dSDimitry Andric 527bdd1243dSDimitry Andric MachineOperand &Symbol = MI.getOperand(1); 528bdd1243dSDimitry Andric Symbol.setTargetFlags(FlagsHi); 529bdd1243dSDimitry Andric MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("pcrel_hi"); 530bdd1243dSDimitry Andric 531bdd1243dSDimitry Andric MachineInstr *MIAUIPC = 532bdd1243dSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol); 533bdd1243dSDimitry Andric MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol); 534bdd1243dSDimitry Andric 535bdd1243dSDimitry Andric MachineInstr *SecondMI = 536bdd1243dSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg) 537bdd1243dSDimitry Andric .addReg(ScratchReg) 538bdd1243dSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_PCREL_LO); 539bdd1243dSDimitry Andric 540bdd1243dSDimitry Andric if (MI.hasOneMemOperand()) 541bdd1243dSDimitry Andric SecondMI->addMemOperand(*MF, *MI.memoperands_begin()); 542bdd1243dSDimitry Andric 543bdd1243dSDimitry Andric MI.eraseFromParent(); 544fe6060f1SDimitry Andric return true; 545fe6060f1SDimitry Andric } 546fe6060f1SDimitry Andric 547bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadLocalAddress( 548bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 549bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 550bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI, 551bdd1243dSDimitry Andric RISCV::ADDI); 552fe6060f1SDimitry Andric } 553bdd1243dSDimitry Andric 55406c3fb27SDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadGlobalAddress( 555bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 556bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 55706c3fb27SDimitry Andric unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW; 558bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_GOT_HI, 559bdd1243dSDimitry Andric SecondOpcode); 560bdd1243dSDimitry Andric } 561bdd1243dSDimitry Andric 562bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadTLSIEAddress( 563bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 564bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 56506c3fb27SDimitry Andric unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW; 566bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI, 567bdd1243dSDimitry Andric SecondOpcode); 568bdd1243dSDimitry Andric } 569bdd1243dSDimitry Andric 570bdd1243dSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadTLSGDAddress( 571bdd1243dSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 572bdd1243dSDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 573bdd1243dSDimitry Andric return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI, 574bdd1243dSDimitry Andric RISCV::ADDI); 575fe6060f1SDimitry Andric } 576fe6060f1SDimitry Andric 5777a6dacacSDimitry Andric bool RISCVPreRAExpandPseudo::expandLoadTLSDescAddress( 5787a6dacacSDimitry Andric MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 5797a6dacacSDimitry Andric MachineBasicBlock::iterator &NextMBBI) { 5807a6dacacSDimitry Andric MachineFunction *MF = MBB.getParent(); 5817a6dacacSDimitry Andric MachineInstr &MI = *MBBI; 5827a6dacacSDimitry Andric DebugLoc DL = MI.getDebugLoc(); 5837a6dacacSDimitry Andric 5847a6dacacSDimitry Andric const auto &STI = MF->getSubtarget<RISCVSubtarget>(); 5857a6dacacSDimitry Andric unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; 5867a6dacacSDimitry Andric 5877a6dacacSDimitry Andric Register FinalReg = MI.getOperand(0).getReg(); 5887a6dacacSDimitry Andric Register DestReg = 5897a6dacacSDimitry Andric MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass); 5907a6dacacSDimitry Andric Register ScratchReg = 5917a6dacacSDimitry Andric MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass); 5927a6dacacSDimitry Andric 5937a6dacacSDimitry Andric MachineOperand &Symbol = MI.getOperand(1); 5947a6dacacSDimitry Andric Symbol.setTargetFlags(RISCVII::MO_TLSDESC_HI); 5957a6dacacSDimitry Andric MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("tlsdesc_hi"); 5967a6dacacSDimitry Andric 5977a6dacacSDimitry Andric MachineInstr *MIAUIPC = 5987a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol); 5997a6dacacSDimitry Andric MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol); 6007a6dacacSDimitry Andric 6017a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg) 6027a6dacacSDimitry Andric .addReg(ScratchReg) 6037a6dacacSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_LOAD_LO); 6047a6dacacSDimitry Andric 6057a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), RISCV::X10) 6067a6dacacSDimitry Andric .addReg(ScratchReg) 6077a6dacacSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_ADD_LO); 6087a6dacacSDimitry Andric 6097a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::PseudoTLSDESCCall), RISCV::X5) 6107a6dacacSDimitry Andric .addReg(DestReg) 6117a6dacacSDimitry Andric .addImm(0) 6127a6dacacSDimitry Andric .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_CALL); 6137a6dacacSDimitry Andric 6147a6dacacSDimitry Andric BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADD), FinalReg) 6157a6dacacSDimitry Andric .addReg(RISCV::X10) 6167a6dacacSDimitry Andric .addReg(RISCV::X4); 6177a6dacacSDimitry Andric 6187a6dacacSDimitry Andric MI.eraseFromParent(); 6197a6dacacSDimitry Andric return true; 6207a6dacacSDimitry Andric } 6217a6dacacSDimitry Andric 6220b57cec5SDimitry Andric } // end of anonymous namespace 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo", 6250b57cec5SDimitry Andric RISCV_EXPAND_PSEUDO_NAME, false, false) 626bdd1243dSDimitry Andric 627bdd1243dSDimitry Andric INITIALIZE_PASS(RISCVPreRAExpandPseudo, "riscv-prera-expand-pseudo", 628bdd1243dSDimitry Andric RISCV_PRERA_EXPAND_PSEUDO_NAME, false, false) 629bdd1243dSDimitry Andric 6300b57cec5SDimitry Andric namespace llvm { 6310b57cec5SDimitry Andric 6320b57cec5SDimitry Andric FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); } 633bdd1243dSDimitry Andric FunctionPass *createRISCVPreRAExpandPseudoPass() { return new RISCVPreRAExpandPseudo(); } 6340b57cec5SDimitry Andric 6350b57cec5SDimitry Andric } // end of namespace llvm 636