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 bool expandVSetVL(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); 63 bool expandVMSET_VMCLR(MachineBasicBlock &MBB, 64 MachineBasicBlock::iterator MBBI, unsigned Opcode); 65 }; 66 67 char RISCVExpandPseudo::ID = 0; 68 69 bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) { 70 TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo()); 71 bool Modified = false; 72 for (auto &MBB : MF) 73 Modified |= expandMBB(MBB); 74 return Modified; 75 } 76 77 bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) { 78 bool Modified = false; 79 80 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 81 while (MBBI != E) { 82 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 83 Modified |= expandMI(MBB, MBBI, NMBBI); 84 MBBI = NMBBI; 85 } 86 87 return Modified; 88 } 89 90 bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB, 91 MachineBasicBlock::iterator MBBI, 92 MachineBasicBlock::iterator &NextMBBI) { 93 // RISCVInstrInfo::getInstSizeInBytes hard-codes the number of expanded 94 // instructions for each pseudo, and must be updated when adding new pseudos 95 // or changing existing ones. 96 switch (MBBI->getOpcode()) { 97 case RISCV::PseudoLLA: 98 return expandLoadLocalAddress(MBB, MBBI, NextMBBI); 99 case RISCV::PseudoLA: 100 return expandLoadAddress(MBB, MBBI, NextMBBI); 101 case RISCV::PseudoLA_TLS_IE: 102 return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI); 103 case RISCV::PseudoLA_TLS_GD: 104 return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI); 105 case RISCV::PseudoVSETVLI: 106 case RISCV::PseudoVSETIVLI: 107 return expandVSetVL(MBB, MBBI); 108 case RISCV::PseudoVMCLR_M_B1: 109 case RISCV::PseudoVMCLR_M_B2: 110 case RISCV::PseudoVMCLR_M_B4: 111 case RISCV::PseudoVMCLR_M_B8: 112 case RISCV::PseudoVMCLR_M_B16: 113 case RISCV::PseudoVMCLR_M_B32: 114 case RISCV::PseudoVMCLR_M_B64: 115 // vmclr.m vd => vmxor.mm vd, vd, vd 116 return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXOR_MM); 117 case RISCV::PseudoVMSET_M_B1: 118 case RISCV::PseudoVMSET_M_B2: 119 case RISCV::PseudoVMSET_M_B4: 120 case RISCV::PseudoVMSET_M_B8: 121 case RISCV::PseudoVMSET_M_B16: 122 case RISCV::PseudoVMSET_M_B32: 123 case RISCV::PseudoVMSET_M_B64: 124 // vmset.m vd => vmxnor.mm vd, vd, vd 125 return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM); 126 } 127 128 return false; 129 } 130 131 bool RISCVExpandPseudo::expandAuipcInstPair( 132 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 133 MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi, 134 unsigned SecondOpcode) { 135 MachineFunction *MF = MBB.getParent(); 136 MachineInstr &MI = *MBBI; 137 DebugLoc DL = MI.getDebugLoc(); 138 139 Register DestReg = MI.getOperand(0).getReg(); 140 const MachineOperand &Symbol = MI.getOperand(1); 141 142 MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 143 144 // Tell AsmPrinter that we unconditionally want the symbol of this label to be 145 // emitted. 146 NewMBB->setLabelMustBeEmitted(); 147 148 MF->insert(++MBB.getIterator(), NewMBB); 149 150 BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg) 151 .addDisp(Symbol, 0, FlagsHi); 152 BuildMI(NewMBB, DL, TII->get(SecondOpcode), DestReg) 153 .addReg(DestReg) 154 .addMBB(NewMBB, RISCVII::MO_PCREL_LO); 155 156 // Move all the rest of the instructions to NewMBB. 157 NewMBB->splice(NewMBB->end(), &MBB, std::next(MBBI), MBB.end()); 158 // Update machine-CFG edges. 159 NewMBB->transferSuccessorsAndUpdatePHIs(&MBB); 160 // Make the original basic block fall-through to the new. 161 MBB.addSuccessor(NewMBB); 162 163 // Make sure live-ins are correctly attached to this new basic block. 164 LivePhysRegs LiveRegs; 165 computeAndAddLiveIns(LiveRegs, *NewMBB); 166 167 NextMBBI = MBB.end(); 168 MI.eraseFromParent(); 169 return true; 170 } 171 172 bool RISCVExpandPseudo::expandLoadLocalAddress( 173 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 174 MachineBasicBlock::iterator &NextMBBI) { 175 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI, 176 RISCV::ADDI); 177 } 178 179 bool RISCVExpandPseudo::expandLoadAddress( 180 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 181 MachineBasicBlock::iterator &NextMBBI) { 182 MachineFunction *MF = MBB.getParent(); 183 184 unsigned SecondOpcode; 185 unsigned FlagsHi; 186 if (MF->getTarget().isPositionIndependent()) { 187 const auto &STI = MF->getSubtarget<RISCVSubtarget>(); 188 SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; 189 FlagsHi = RISCVII::MO_GOT_HI; 190 } else { 191 SecondOpcode = RISCV::ADDI; 192 FlagsHi = RISCVII::MO_PCREL_HI; 193 } 194 return expandAuipcInstPair(MBB, MBBI, NextMBBI, FlagsHi, SecondOpcode); 195 } 196 197 bool RISCVExpandPseudo::expandLoadTLSIEAddress( 198 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 199 MachineBasicBlock::iterator &NextMBBI) { 200 MachineFunction *MF = MBB.getParent(); 201 202 const auto &STI = MF->getSubtarget<RISCVSubtarget>(); 203 unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; 204 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI, 205 SecondOpcode); 206 } 207 208 bool RISCVExpandPseudo::expandLoadTLSGDAddress( 209 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 210 MachineBasicBlock::iterator &NextMBBI) { 211 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI, 212 RISCV::ADDI); 213 } 214 215 bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock &MBB, 216 MachineBasicBlock::iterator MBBI) { 217 assert(MBBI->getNumOperands() == 5 && "Unexpected instruction format"); 218 219 DebugLoc DL = MBBI->getDebugLoc(); 220 221 assert((MBBI->getOpcode() == RISCV::PseudoVSETVLI || 222 MBBI->getOpcode() == RISCV::PseudoVSETIVLI) && 223 "Unexpected pseudo instruction"); 224 unsigned Opcode; 225 if (MBBI->getOpcode() == RISCV::PseudoVSETVLI) 226 Opcode = RISCV::VSETVLI; 227 else 228 Opcode = RISCV::VSETIVLI; 229 const MCInstrDesc &Desc = TII->get(Opcode); 230 assert(Desc.getNumOperands() == 3 && "Unexpected instruction format"); 231 232 Register DstReg = MBBI->getOperand(0).getReg(); 233 bool DstIsDead = MBBI->getOperand(0).isDead(); 234 BuildMI(MBB, MBBI, DL, Desc) 235 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) 236 .add(MBBI->getOperand(1)) // VL 237 .add(MBBI->getOperand(2)); // VType 238 239 MBBI->eraseFromParent(); // The pseudo instruction is gone now. 240 return true; 241 } 242 243 bool RISCVExpandPseudo::expandVMSET_VMCLR(MachineBasicBlock &MBB, 244 MachineBasicBlock::iterator MBBI, 245 unsigned Opcode) { 246 DebugLoc DL = MBBI->getDebugLoc(); 247 Register DstReg = MBBI->getOperand(0).getReg(); 248 const MCInstrDesc &Desc = TII->get(Opcode); 249 BuildMI(MBB, MBBI, DL, Desc, DstReg) 250 .addReg(DstReg, RegState::Undef) 251 .addReg(DstReg, RegState::Undef); 252 MBBI->eraseFromParent(); // The pseudo instruction is gone now. 253 return true; 254 } 255 256 } // end of anonymous namespace 257 258 INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo", 259 RISCV_EXPAND_PSEUDO_NAME, false, false) 260 namespace llvm { 261 262 FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); } 263 264 } // end of namespace llvm 265