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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains a pass that expands pseudo instructions into target 10 // instructions. This pass should be run after register allocation but before 11 // 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 23 using namespace llvm; 24 25 #define RISCV_EXPAND_PSEUDO_NAME "RISCV pseudo instruction expansion pass" 26 27 namespace { 28 29 class RISCVExpandPseudo : public MachineFunctionPass { 30 public: 31 const RISCVInstrInfo *TII; 32 static char ID; 33 34 RISCVExpandPseudo() : MachineFunctionPass(ID) { 35 initializeRISCVExpandPseudoPass(*PassRegistry::getPassRegistry()); 36 } 37 38 bool runOnMachineFunction(MachineFunction &MF) override; 39 40 StringRef getPassName() const override { return RISCV_EXPAND_PSEUDO_NAME; } 41 42 private: 43 bool expandMBB(MachineBasicBlock &MBB); 44 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 45 MachineBasicBlock::iterator &NextMBBI); 46 bool expandAuipcInstPair(MachineBasicBlock &MBB, 47 MachineBasicBlock::iterator MBBI, 48 MachineBasicBlock::iterator &NextMBBI, 49 unsigned FlagsHi, unsigned SecondOpcode); 50 bool expandLoadLocalAddress(MachineBasicBlock &MBB, 51 MachineBasicBlock::iterator MBBI, 52 MachineBasicBlock::iterator &NextMBBI); 53 bool expandLoadAddress(MachineBasicBlock &MBB, 54 MachineBasicBlock::iterator MBBI, 55 MachineBasicBlock::iterator &NextMBBI); 56 bool expandLoadTLSIEAddress(MachineBasicBlock &MBB, 57 MachineBasicBlock::iterator MBBI, 58 MachineBasicBlock::iterator &NextMBBI); 59 bool expandLoadTLSGDAddress(MachineBasicBlock &MBB, 60 MachineBasicBlock::iterator MBBI, 61 MachineBasicBlock::iterator &NextMBBI); 62 }; 63 64 char RISCVExpandPseudo::ID = 0; 65 66 bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) { 67 TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo()); 68 bool Modified = false; 69 for (auto &MBB : MF) 70 Modified |= expandMBB(MBB); 71 return Modified; 72 } 73 74 bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) { 75 bool Modified = false; 76 77 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 78 while (MBBI != E) { 79 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 80 Modified |= expandMI(MBB, MBBI, NMBBI); 81 MBBI = NMBBI; 82 } 83 84 return Modified; 85 } 86 87 bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB, 88 MachineBasicBlock::iterator MBBI, 89 MachineBasicBlock::iterator &NextMBBI) { 90 // RISCVInstrInfo::getInstSizeInBytes hard-codes the number of expanded 91 // instructions for each pseudo, and must be updated when adding new pseudos 92 // or changing existing ones. 93 switch (MBBI->getOpcode()) { 94 case RISCV::PseudoLLA: 95 return expandLoadLocalAddress(MBB, MBBI, NextMBBI); 96 case RISCV::PseudoLA: 97 return expandLoadAddress(MBB, MBBI, NextMBBI); 98 case RISCV::PseudoLA_TLS_IE: 99 return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI); 100 case RISCV::PseudoLA_TLS_GD: 101 return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI); 102 } 103 104 return false; 105 } 106 107 bool RISCVExpandPseudo::expandAuipcInstPair( 108 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 109 MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi, 110 unsigned SecondOpcode) { 111 MachineFunction *MF = MBB.getParent(); 112 MachineInstr &MI = *MBBI; 113 DebugLoc DL = MI.getDebugLoc(); 114 115 Register DestReg = MI.getOperand(0).getReg(); 116 const MachineOperand &Symbol = MI.getOperand(1); 117 118 MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 119 120 // Tell AsmPrinter that we unconditionally want the symbol of this label to be 121 // emitted. 122 NewMBB->setLabelMustBeEmitted(); 123 124 MF->insert(++MBB.getIterator(), NewMBB); 125 126 BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg) 127 .addDisp(Symbol, 0, FlagsHi); 128 BuildMI(NewMBB, DL, TII->get(SecondOpcode), DestReg) 129 .addReg(DestReg) 130 .addMBB(NewMBB, RISCVII::MO_PCREL_LO); 131 132 // Move all the rest of the instructions to NewMBB. 133 NewMBB->splice(NewMBB->end(), &MBB, std::next(MBBI), MBB.end()); 134 // Update machine-CFG edges. 135 NewMBB->transferSuccessorsAndUpdatePHIs(&MBB); 136 // Make the original basic block fall-through to the new. 137 MBB.addSuccessor(NewMBB); 138 139 // Make sure live-ins are correctly attached to this new basic block. 140 LivePhysRegs LiveRegs; 141 computeAndAddLiveIns(LiveRegs, *NewMBB); 142 143 NextMBBI = MBB.end(); 144 MI.eraseFromParent(); 145 return true; 146 } 147 148 bool RISCVExpandPseudo::expandLoadLocalAddress( 149 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 150 MachineBasicBlock::iterator &NextMBBI) { 151 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI, 152 RISCV::ADDI); 153 } 154 155 bool RISCVExpandPseudo::expandLoadAddress( 156 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 157 MachineBasicBlock::iterator &NextMBBI) { 158 MachineFunction *MF = MBB.getParent(); 159 160 unsigned SecondOpcode; 161 unsigned FlagsHi; 162 if (MF->getTarget().isPositionIndependent()) { 163 const auto &STI = MF->getSubtarget<RISCVSubtarget>(); 164 SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; 165 FlagsHi = RISCVII::MO_GOT_HI; 166 } else { 167 SecondOpcode = RISCV::ADDI; 168 FlagsHi = RISCVII::MO_PCREL_HI; 169 } 170 return expandAuipcInstPair(MBB, MBBI, NextMBBI, FlagsHi, SecondOpcode); 171 } 172 173 bool RISCVExpandPseudo::expandLoadTLSIEAddress( 174 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 175 MachineBasicBlock::iterator &NextMBBI) { 176 MachineFunction *MF = MBB.getParent(); 177 178 const auto &STI = MF->getSubtarget<RISCVSubtarget>(); 179 unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; 180 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI, 181 SecondOpcode); 182 } 183 184 bool RISCVExpandPseudo::expandLoadTLSGDAddress( 185 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 186 MachineBasicBlock::iterator &NextMBBI) { 187 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI, 188 RISCV::ADDI); 189 } 190 191 } // end of anonymous namespace 192 193 INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo", 194 RISCV_EXPAND_PSEUDO_NAME, false, false) 195 namespace llvm { 196 197 FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); } 198 199 } // end of namespace llvm 200