| //===----------------------------------------------------------------------===// |
| // |
| // 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; |
| } |