|  | //===-- RISCVExpandPseudoInsts.cpp - Expand pseudo instructions -----------===// | 
|  | // | 
|  | // 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 a pass that expands pseudo instructions into target | 
|  | // instructions. This pass should be run after register allocation but before | 
|  | // the post-regalloc scheduling pass. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "RISCV.h" | 
|  | #include "RISCVInstrInfo.h" | 
|  | #include "RISCVTargetMachine.h" | 
|  |  | 
|  | #include "llvm/CodeGen/LivePhysRegs.h" | 
|  | #include "llvm/CodeGen/MachineFunctionPass.h" | 
|  | #include "llvm/CodeGen/MachineInstrBuilder.h" | 
|  |  | 
|  | using namespace llvm; | 
|  |  | 
|  | #define RISCV_EXPAND_PSEUDO_NAME "RISCV pseudo instruction expansion pass" | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | class RISCVExpandPseudo : public MachineFunctionPass { | 
|  | public: | 
|  | const RISCVInstrInfo *TII; | 
|  | static char ID; | 
|  |  | 
|  | RISCVExpandPseudo() : MachineFunctionPass(ID) { | 
|  | initializeRISCVExpandPseudoPass(*PassRegistry::getPassRegistry()); | 
|  | } | 
|  |  | 
|  | bool runOnMachineFunction(MachineFunction &MF) override; | 
|  |  | 
|  | StringRef getPassName() const override { return RISCV_EXPAND_PSEUDO_NAME; } | 
|  |  | 
|  | private: | 
|  | bool expandMBB(MachineBasicBlock &MBB); | 
|  | bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI); | 
|  | bool expandAuipcInstPair(MachineBasicBlock &MBB, | 
|  | MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI, | 
|  | unsigned FlagsHi, unsigned SecondOpcode); | 
|  | bool expandLoadLocalAddress(MachineBasicBlock &MBB, | 
|  | MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI); | 
|  | bool expandLoadAddress(MachineBasicBlock &MBB, | 
|  | MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI); | 
|  | bool expandLoadTLSIEAddress(MachineBasicBlock &MBB, | 
|  | MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI); | 
|  | bool expandLoadTLSGDAddress(MachineBasicBlock &MBB, | 
|  | MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI); | 
|  | }; | 
|  |  | 
|  | char RISCVExpandPseudo::ID = 0; | 
|  |  | 
|  | bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) { | 
|  | TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo()); | 
|  | bool Modified = false; | 
|  | for (auto &MBB : MF) | 
|  | Modified |= expandMBB(MBB); | 
|  | return Modified; | 
|  | } | 
|  |  | 
|  | bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) { | 
|  | bool Modified = false; | 
|  |  | 
|  | MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); | 
|  | while (MBBI != E) { | 
|  | MachineBasicBlock::iterator NMBBI = std::next(MBBI); | 
|  | Modified |= expandMI(MBB, MBBI, NMBBI); | 
|  | MBBI = NMBBI; | 
|  | } | 
|  |  | 
|  | return Modified; | 
|  | } | 
|  |  | 
|  | bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB, | 
|  | MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI) { | 
|  | switch (MBBI->getOpcode()) { | 
|  | case RISCV::PseudoLLA: | 
|  | return expandLoadLocalAddress(MBB, MBBI, NextMBBI); | 
|  | case RISCV::PseudoLA: | 
|  | return expandLoadAddress(MBB, MBBI, NextMBBI); | 
|  | case RISCV::PseudoLA_TLS_IE: | 
|  | return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI); | 
|  | case RISCV::PseudoLA_TLS_GD: | 
|  | return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI); | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool RISCVExpandPseudo::expandAuipcInstPair( | 
|  | MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi, | 
|  | unsigned SecondOpcode) { | 
|  | MachineFunction *MF = MBB.getParent(); | 
|  | MachineInstr &MI = *MBBI; | 
|  | DebugLoc DL = MI.getDebugLoc(); | 
|  |  | 
|  | Register DestReg = MI.getOperand(0).getReg(); | 
|  | const MachineOperand &Symbol = MI.getOperand(1); | 
|  |  | 
|  | MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); | 
|  |  | 
|  | // Tell AsmPrinter that we unconditionally want the symbol of this label to be | 
|  | // emitted. | 
|  | NewMBB->setLabelMustBeEmitted(); | 
|  |  | 
|  | MF->insert(++MBB.getIterator(), NewMBB); | 
|  |  | 
|  | BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg) | 
|  | .addDisp(Symbol, 0, FlagsHi); | 
|  | BuildMI(NewMBB, DL, TII->get(SecondOpcode), DestReg) | 
|  | .addReg(DestReg) | 
|  | .addMBB(NewMBB, RISCVII::MO_PCREL_LO); | 
|  |  | 
|  | // Move all the rest of the instructions to NewMBB. | 
|  | NewMBB->splice(NewMBB->end(), &MBB, std::next(MBBI), MBB.end()); | 
|  | // Update machine-CFG edges. | 
|  | NewMBB->transferSuccessorsAndUpdatePHIs(&MBB); | 
|  | // Make the original basic block fall-through to the new. | 
|  | MBB.addSuccessor(NewMBB); | 
|  |  | 
|  | // Make sure live-ins are correctly attached to this new basic block. | 
|  | LivePhysRegs LiveRegs; | 
|  | computeAndAddLiveIns(LiveRegs, *NewMBB); | 
|  |  | 
|  | NextMBBI = MBB.end(); | 
|  | MI.eraseFromParent(); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool RISCVExpandPseudo::expandLoadLocalAddress( | 
|  | MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI) { | 
|  | return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI, | 
|  | RISCV::ADDI); | 
|  | } | 
|  |  | 
|  | bool RISCVExpandPseudo::expandLoadAddress( | 
|  | MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI) { | 
|  | MachineFunction *MF = MBB.getParent(); | 
|  |  | 
|  | unsigned SecondOpcode; | 
|  | unsigned FlagsHi; | 
|  | if (MF->getTarget().isPositionIndependent()) { | 
|  | const auto &STI = MF->getSubtarget<RISCVSubtarget>(); | 
|  | SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; | 
|  | FlagsHi = RISCVII::MO_GOT_HI; | 
|  | } else { | 
|  | SecondOpcode = RISCV::ADDI; | 
|  | FlagsHi = RISCVII::MO_PCREL_HI; | 
|  | } | 
|  | return expandAuipcInstPair(MBB, MBBI, NextMBBI, FlagsHi, SecondOpcode); | 
|  | } | 
|  |  | 
|  | bool RISCVExpandPseudo::expandLoadTLSIEAddress( | 
|  | MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI) { | 
|  | MachineFunction *MF = MBB.getParent(); | 
|  |  | 
|  | const auto &STI = MF->getSubtarget<RISCVSubtarget>(); | 
|  | unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; | 
|  | return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI, | 
|  | SecondOpcode); | 
|  | } | 
|  |  | 
|  | bool RISCVExpandPseudo::expandLoadTLSGDAddress( | 
|  | MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, | 
|  | MachineBasicBlock::iterator &NextMBBI) { | 
|  | return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI, | 
|  | RISCV::ADDI); | 
|  | } | 
|  |  | 
|  | } // end of anonymous namespace | 
|  |  | 
|  | INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo", | 
|  | RISCV_EXPAND_PSEUDO_NAME, false, false) | 
|  | namespace llvm { | 
|  |  | 
|  | FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); } | 
|  |  | 
|  | } // end of namespace llvm |