| //===----------------------------------------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| // | |
| // This file contains one of the several passes that expand pseudo instructions | |
| // into target instructions. This pass is run before register allocation. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "RISCV.h" | |
| #include "RISCVExpandPseudoBase.h" | |
| #include "RISCVInstrInfo.h" | |
| #include "RISCVSubtarget.h" | |
| #include "llvm/CodeGen/MachineFunctionPass.h" | |
| #include "llvm/CodeGen/MachineInstrBuilder.h" | |
| #include "llvm/MC/MCContext.h" | |
| using namespace llvm; | |
| #define RISCV_EXPAND_PSEUDO_PRE_RA_NAME \ | |
| "RISC-V Pseudo Instruction Expansion - Pre-RA" | |
| namespace { | |
| class RISCVExpandPseudoPreRAImpl final : public RISCVExpandPseudoImplBase { | |
| bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, | |
| MachineBasicBlock::iterator &NextMBBI) const override; | |
| bool expandAuipcInstPair(MachineBasicBlock &MBB, | |
| MachineBasicBlock::iterator MBBI, unsigned FlagsHi, | |
| unsigned SecondOpcode) const; | |
| bool expandLoadLocalAddress(MachineBasicBlock &MBB, | |
| MachineBasicBlock::iterator MBBI) const; | |
| bool expandLoadGlobalAddress(MachineBasicBlock &MBB, | |
| MachineBasicBlock::iterator MBBI) const; | |
| bool expandLoadTLSIEAddress(MachineBasicBlock &MBB, | |
| MachineBasicBlock::iterator MBBI) const; | |
| bool expandLoadTLSGDAddress(MachineBasicBlock &MBB, | |
| MachineBasicBlock::iterator MBBI) const; | |
| bool expandLoadTLSDescAddress(MachineBasicBlock &MBB, | |
| MachineBasicBlock::iterator MBBI) const; | |
| }; | |
| class RISCVExpandPseudoPreRALegacy : public MachineFunctionPass { | |
| public: | |
| static char ID; | |
| RISCVExpandPseudoPreRALegacy() : MachineFunctionPass(ID) {} | |
| bool runOnMachineFunction(MachineFunction &MF) override { | |
| return RISCVExpandPseudoPreRAImpl().run(MF); | |
| } | |
| MachineFunctionProperties getRequiredProperties() const override { | |
| return MachineFunctionProperties().setIsSSA(); | |
| } | |
| void getAnalysisUsage(AnalysisUsage &AU) const override { | |
| AU.setPreservesCFG(); | |
| MachineFunctionPass::getAnalysisUsage(AU); | |
| } | |
| StringRef getPassName() const override { | |
| return RISCV_EXPAND_PSEUDO_PRE_RA_NAME; | |
| } | |
| }; | |
| } // anonymous namespace | |
| bool RISCVExpandPseudoPreRAImpl::expandMI( | |
| MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, | |
| MachineBasicBlock::iterator &NextMBBI) const { | |
| switch (MBBI->getOpcode()) { | |
| case RISCV::PseudoLLA: | |
| return expandLoadLocalAddress(MBB, MBBI); | |
| case RISCV::PseudoLGA: | |
| return expandLoadGlobalAddress(MBB, MBBI); | |
| case RISCV::PseudoLA_TLS_IE: | |
| return expandLoadTLSIEAddress(MBB, MBBI); | |
| case RISCV::PseudoLA_TLS_GD: | |
| return expandLoadTLSGDAddress(MBB, MBBI); | |
| case RISCV::PseudoLA_TLSDESC: | |
| return expandLoadTLSDescAddress(MBB, MBBI); | |
| } | |
| return false; | |
| } | |
| bool RISCVExpandPseudoPreRAImpl::expandAuipcInstPair( | |
| MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned FlagsHi, | |
| unsigned SecondOpcode) const { | |
| MachineFunction *MF = MBB.getParent(); | |
| MachineInstr &MI = *MBBI; | |
| DebugLoc DL = MI.getDebugLoc(); | |
| Register DestReg = MI.getOperand(0).getReg(); | |
| Register ScratchReg = | |
| MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass); | |
| MachineOperand &Symbol = MI.getOperand(1); | |
| Symbol.setTargetFlags(FlagsHi); | |
| MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("pcrel_hi"); | |
| MachineInstr *MIAUIPC = | |
| BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol); | |
| MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol); | |
| MachineInstr *SecondMI = | |
| BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg) | |
| .addReg(ScratchReg) | |
| .addSym(AUIPCSymbol, RISCVII::MO_PCREL_LO); | |
| if (MI.hasOneMemOperand()) | |
| SecondMI->addMemOperand(*MF, *MI.memoperands_begin()); | |
| MI.eraseFromParent(); | |
| return true; | |
| } | |
| bool RISCVExpandPseudoPreRAImpl::expandLoadLocalAddress( | |
| MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const { | |
| return expandAuipcInstPair(MBB, MBBI, RISCVII::MO_PCREL_HI, RISCV::ADDI); | |
| } | |
| bool RISCVExpandPseudoPreRAImpl::expandLoadGlobalAddress( | |
| MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const { | |
| unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW; | |
| return expandAuipcInstPair(MBB, MBBI, RISCVII::MO_GOT_HI, SecondOpcode); | |
| } | |
| bool RISCVExpandPseudoPreRAImpl::expandLoadTLSIEAddress( | |
| MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const { | |
| unsigned SecondOpcode = STI->is64Bit() ? RISCV::LD : RISCV::LW; | |
| return expandAuipcInstPair(MBB, MBBI, RISCVII::MO_TLS_GOT_HI, SecondOpcode); | |
| } | |
| bool RISCVExpandPseudoPreRAImpl::expandLoadTLSGDAddress( | |
| MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const { | |
| return expandAuipcInstPair(MBB, MBBI, RISCVII::MO_TLS_GD_HI, RISCV::ADDI); | |
| } | |
| bool RISCVExpandPseudoPreRAImpl::expandLoadTLSDescAddress( | |
| MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) const { | |
| MachineFunction *MF = MBB.getParent(); | |
| MachineInstr &MI = *MBBI; | |
| DebugLoc DL = MI.getDebugLoc(); | |
| const auto &STI = MF->getSubtarget<RISCVSubtarget>(); | |
| unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; | |
| Register FinalReg = MI.getOperand(0).getReg(); | |
| Register DestReg = | |
| MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass); | |
| Register ScratchReg = | |
| MF->getRegInfo().createVirtualRegister(&RISCV::GPRRegClass); | |
| MachineOperand &Symbol = MI.getOperand(1); | |
| Symbol.setTargetFlags(RISCVII::MO_TLSDESC_HI); | |
| MCSymbol *AUIPCSymbol = MF->getContext().createNamedTempSymbol("tlsdesc_hi"); | |
| MachineInstr *MIAUIPC = | |
| BuildMI(MBB, MBBI, DL, TII->get(RISCV::AUIPC), ScratchReg).add(Symbol); | |
| MIAUIPC->setPreInstrSymbol(*MF, AUIPCSymbol); | |
| BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg) | |
| .addReg(ScratchReg) | |
| .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_LOAD_LO); | |
| BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADDI), RISCV::X10) | |
| .addReg(ScratchReg) | |
| .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_ADD_LO); | |
| BuildMI(MBB, MBBI, DL, TII->get(RISCV::PseudoTLSDESCCall), RISCV::X5) | |
| .addReg(DestReg) | |
| .addImm(0) | |
| .addSym(AUIPCSymbol, RISCVII::MO_TLSDESC_CALL); | |
| BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADD), FinalReg) | |
| .addReg(RISCV::X10) | |
| .addReg(RISCV::X4); | |
| MI.eraseFromParent(); | |
| return true; | |
| } | |
| char RISCVExpandPseudoPreRALegacy::ID = 0; | |
| INITIALIZE_PASS(RISCVExpandPseudoPreRALegacy, "riscv-expand-pseudo-pre-ra", | |
| RISCV_EXPAND_PSEUDO_PRE_RA_NAME, false, false) | |
| FunctionPass *llvm::createRISCVExpandPseudoPreRALegacyPass() { | |
| return new RISCVExpandPseudoPreRALegacy(); | |
| } | |
| PreservedAnalyses | |
| RISCVExpandPseudoPreRAPass::run(MachineFunction &MF, | |
| MachineFunctionAnalysisManager &MFAM) { | |
| MFPropsModifier _(*this, MF); | |
| bool Changed = RISCVExpandPseudoPreRAImpl().run(MF); | |
| if (!Changed) | |
| return PreservedAnalyses::all(); | |
| PreservedAnalyses PA = getMachineFunctionPassPreservedAnalyses(); | |
| PA.preserveSet<CFGAnalyses>(); | |
| return PA; | |
| } |