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 23using namespace llvm; 24 25#define RISCV_EXPAND_PSEUDO_NAME "RISCV pseudo instruction expansion pass" 26 27namespace { 28 29class RISCVExpandPseudo : public MachineFunctionPass { 30public: 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 42private: 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 bool expandVSPILL(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); 66 bool expandVRELOAD(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); 67}; 68 69char RISCVExpandPseudo::ID = 0; 70 71bool RISCVExpandPseudo::runOnMachineFunction(MachineFunction &MF) { 72 TII = static_cast<const RISCVInstrInfo *>(MF.getSubtarget().getInstrInfo()); 73 bool Modified = false; 74 for (auto &MBB : MF) 75 Modified |= expandMBB(MBB); 76 return Modified; 77} 78 79bool RISCVExpandPseudo::expandMBB(MachineBasicBlock &MBB) { 80 bool Modified = false; 81 82 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 83 while (MBBI != E) { 84 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 85 Modified |= expandMI(MBB, MBBI, NMBBI); 86 MBBI = NMBBI; 87 } 88 89 return Modified; 90} 91 92bool RISCVExpandPseudo::expandMI(MachineBasicBlock &MBB, 93 MachineBasicBlock::iterator MBBI, 94 MachineBasicBlock::iterator &NextMBBI) { 95 // RISCVInstrInfo::getInstSizeInBytes hard-codes the number of expanded 96 // instructions for each pseudo, and must be updated when adding new pseudos 97 // or changing existing ones. 98 switch (MBBI->getOpcode()) { 99 case RISCV::PseudoLLA: 100 return expandLoadLocalAddress(MBB, MBBI, NextMBBI); 101 case RISCV::PseudoLA: 102 return expandLoadAddress(MBB, MBBI, NextMBBI); 103 case RISCV::PseudoLA_TLS_IE: 104 return expandLoadTLSIEAddress(MBB, MBBI, NextMBBI); 105 case RISCV::PseudoLA_TLS_GD: 106 return expandLoadTLSGDAddress(MBB, MBBI, NextMBBI); 107 case RISCV::PseudoVSETVLI: 108 case RISCV::PseudoVSETIVLI: 109 return expandVSetVL(MBB, MBBI); 110 case RISCV::PseudoVMCLR_M_B1: 111 case RISCV::PseudoVMCLR_M_B2: 112 case RISCV::PseudoVMCLR_M_B4: 113 case RISCV::PseudoVMCLR_M_B8: 114 case RISCV::PseudoVMCLR_M_B16: 115 case RISCV::PseudoVMCLR_M_B32: 116 case RISCV::PseudoVMCLR_M_B64: 117 // vmclr.m vd => vmxor.mm vd, vd, vd 118 return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXOR_MM); 119 case RISCV::PseudoVMSET_M_B1: 120 case RISCV::PseudoVMSET_M_B2: 121 case RISCV::PseudoVMSET_M_B4: 122 case RISCV::PseudoVMSET_M_B8: 123 case RISCV::PseudoVMSET_M_B16: 124 case RISCV::PseudoVMSET_M_B32: 125 case RISCV::PseudoVMSET_M_B64: 126 // vmset.m vd => vmxnor.mm vd, vd, vd 127 return expandVMSET_VMCLR(MBB, MBBI, RISCV::VMXNOR_MM); 128 case RISCV::PseudoVSPILL2_M1: 129 case RISCV::PseudoVSPILL2_M2: 130 case RISCV::PseudoVSPILL2_M4: 131 case RISCV::PseudoVSPILL3_M1: 132 case RISCV::PseudoVSPILL3_M2: 133 case RISCV::PseudoVSPILL4_M1: 134 case RISCV::PseudoVSPILL4_M2: 135 case RISCV::PseudoVSPILL5_M1: 136 case RISCV::PseudoVSPILL6_M1: 137 case RISCV::PseudoVSPILL7_M1: 138 case RISCV::PseudoVSPILL8_M1: 139 return expandVSPILL(MBB, MBBI); 140 case RISCV::PseudoVRELOAD2_M1: 141 case RISCV::PseudoVRELOAD2_M2: 142 case RISCV::PseudoVRELOAD2_M4: 143 case RISCV::PseudoVRELOAD3_M1: 144 case RISCV::PseudoVRELOAD3_M2: 145 case RISCV::PseudoVRELOAD4_M1: 146 case RISCV::PseudoVRELOAD4_M2: 147 case RISCV::PseudoVRELOAD5_M1: 148 case RISCV::PseudoVRELOAD6_M1: 149 case RISCV::PseudoVRELOAD7_M1: 150 case RISCV::PseudoVRELOAD8_M1: 151 return expandVRELOAD(MBB, MBBI); 152 } 153 154 return false; 155} 156 157bool RISCVExpandPseudo::expandAuipcInstPair( 158 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 159 MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi, 160 unsigned SecondOpcode) { 161 MachineFunction *MF = MBB.getParent(); 162 MachineInstr &MI = *MBBI; 163 DebugLoc DL = MI.getDebugLoc(); 164 165 Register DestReg = MI.getOperand(0).getReg(); 166 const MachineOperand &Symbol = MI.getOperand(1); 167 168 MachineBasicBlock *NewMBB = MF->CreateMachineBasicBlock(MBB.getBasicBlock()); 169 170 // Tell AsmPrinter that we unconditionally want the symbol of this label to be 171 // emitted. 172 NewMBB->setLabelMustBeEmitted(); 173 174 MF->insert(++MBB.getIterator(), NewMBB); 175 176 BuildMI(NewMBB, DL, TII->get(RISCV::AUIPC), DestReg) 177 .addDisp(Symbol, 0, FlagsHi); 178 BuildMI(NewMBB, DL, TII->get(SecondOpcode), DestReg) 179 .addReg(DestReg) 180 .addMBB(NewMBB, RISCVII::MO_PCREL_LO); 181 182 // Move all the rest of the instructions to NewMBB. 183 NewMBB->splice(NewMBB->end(), &MBB, std::next(MBBI), MBB.end()); 184 // Update machine-CFG edges. 185 NewMBB->transferSuccessorsAndUpdatePHIs(&MBB); 186 // Make the original basic block fall-through to the new. 187 MBB.addSuccessor(NewMBB); 188 189 // Make sure live-ins are correctly attached to this new basic block. 190 LivePhysRegs LiveRegs; 191 computeAndAddLiveIns(LiveRegs, *NewMBB); 192 193 NextMBBI = MBB.end(); 194 MI.eraseFromParent(); 195 return true; 196} 197 198bool RISCVExpandPseudo::expandLoadLocalAddress( 199 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 200 MachineBasicBlock::iterator &NextMBBI) { 201 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_PCREL_HI, 202 RISCV::ADDI); 203} 204 205bool RISCVExpandPseudo::expandLoadAddress( 206 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 207 MachineBasicBlock::iterator &NextMBBI) { 208 MachineFunction *MF = MBB.getParent(); 209 210 unsigned SecondOpcode; 211 unsigned FlagsHi; 212 if (MF->getTarget().isPositionIndependent()) { 213 const auto &STI = MF->getSubtarget<RISCVSubtarget>(); 214 SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; 215 FlagsHi = RISCVII::MO_GOT_HI; 216 } else { 217 SecondOpcode = RISCV::ADDI; 218 FlagsHi = RISCVII::MO_PCREL_HI; 219 } 220 return expandAuipcInstPair(MBB, MBBI, NextMBBI, FlagsHi, SecondOpcode); 221} 222 223bool RISCVExpandPseudo::expandLoadTLSIEAddress( 224 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 225 MachineBasicBlock::iterator &NextMBBI) { 226 MachineFunction *MF = MBB.getParent(); 227 228 const auto &STI = MF->getSubtarget<RISCVSubtarget>(); 229 unsigned SecondOpcode = STI.is64Bit() ? RISCV::LD : RISCV::LW; 230 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GOT_HI, 231 SecondOpcode); 232} 233 234bool RISCVExpandPseudo::expandLoadTLSGDAddress( 235 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 236 MachineBasicBlock::iterator &NextMBBI) { 237 return expandAuipcInstPair(MBB, MBBI, NextMBBI, RISCVII::MO_TLS_GD_HI, 238 RISCV::ADDI); 239} 240 241bool RISCVExpandPseudo::expandVSetVL(MachineBasicBlock &MBB, 242 MachineBasicBlock::iterator MBBI) { 243 assert(MBBI->getNumOperands() == 5 && "Unexpected instruction format"); 244 245 DebugLoc DL = MBBI->getDebugLoc(); 246 247 assert((MBBI->getOpcode() == RISCV::PseudoVSETVLI || 248 MBBI->getOpcode() == RISCV::PseudoVSETIVLI) && 249 "Unexpected pseudo instruction"); 250 unsigned Opcode; 251 if (MBBI->getOpcode() == RISCV::PseudoVSETVLI) 252 Opcode = RISCV::VSETVLI; 253 else 254 Opcode = RISCV::VSETIVLI; 255 const MCInstrDesc &Desc = TII->get(Opcode); 256 assert(Desc.getNumOperands() == 3 && "Unexpected instruction format"); 257 258 Register DstReg = MBBI->getOperand(0).getReg(); 259 bool DstIsDead = MBBI->getOperand(0).isDead(); 260 BuildMI(MBB, MBBI, DL, Desc) 261 .addReg(DstReg, RegState::Define | getDeadRegState(DstIsDead)) 262 .add(MBBI->getOperand(1)) // VL 263 .add(MBBI->getOperand(2)); // VType 264 265 MBBI->eraseFromParent(); // The pseudo instruction is gone now. 266 return true; 267} 268 269bool RISCVExpandPseudo::expandVMSET_VMCLR(MachineBasicBlock &MBB, 270 MachineBasicBlock::iterator MBBI, 271 unsigned Opcode) { 272 DebugLoc DL = MBBI->getDebugLoc(); 273 Register DstReg = MBBI->getOperand(0).getReg(); 274 const MCInstrDesc &Desc = TII->get(Opcode); 275 BuildMI(MBB, MBBI, DL, Desc, DstReg) 276 .addReg(DstReg, RegState::Undef) 277 .addReg(DstReg, RegState::Undef); 278 MBBI->eraseFromParent(); // The pseudo instruction is gone now. 279 return true; 280} 281 282bool RISCVExpandPseudo::expandVSPILL(MachineBasicBlock &MBB, 283 MachineBasicBlock::iterator MBBI) { 284 const TargetRegisterInfo *TRI = 285 MBB.getParent()->getSubtarget().getRegisterInfo(); 286 DebugLoc DL = MBBI->getDebugLoc(); 287 Register SrcReg = MBBI->getOperand(0).getReg(); 288 Register Base = MBBI->getOperand(1).getReg(); 289 Register VL = MBBI->getOperand(2).getReg(); 290 auto ZvlssegInfo = TII->isRVVSpillForZvlsseg(MBBI->getOpcode()); 291 if (!ZvlssegInfo) 292 return false; 293 unsigned NF = ZvlssegInfo->first; 294 unsigned LMUL = ZvlssegInfo->second; 295 assert(NF * LMUL <= 8 && "Invalid NF/LMUL combinations."); 296 unsigned Opcode = RISCV::VS1R_V; 297 unsigned SubRegIdx = RISCV::sub_vrm1_0; 298 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7, 299 "Unexpected subreg numbering"); 300 if (LMUL == 2) { 301 Opcode = RISCV::VS2R_V; 302 SubRegIdx = RISCV::sub_vrm2_0; 303 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3, 304 "Unexpected subreg numbering"); 305 } else if (LMUL == 4) { 306 Opcode = RISCV::VS4R_V; 307 SubRegIdx = RISCV::sub_vrm4_0; 308 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1, 309 "Unexpected subreg numbering"); 310 } else 311 assert(LMUL == 1 && "LMUL must be 1, 2, or 4."); 312 313 for (unsigned I = 0; I < NF; ++I) { 314 BuildMI(MBB, MBBI, DL, TII->get(Opcode)) 315 .addReg(TRI->getSubReg(SrcReg, SubRegIdx + I)) 316 .addReg(Base) 317 .addMemOperand(*(MBBI->memoperands_begin())); 318 if (I != NF - 1) 319 BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADD), Base) 320 .addReg(Base) 321 .addReg(VL); 322 } 323 MBBI->eraseFromParent(); 324 return true; 325} 326 327bool RISCVExpandPseudo::expandVRELOAD(MachineBasicBlock &MBB, 328 MachineBasicBlock::iterator MBBI) { 329 const TargetRegisterInfo *TRI = 330 MBB.getParent()->getSubtarget().getRegisterInfo(); 331 DebugLoc DL = MBBI->getDebugLoc(); 332 Register DestReg = MBBI->getOperand(0).getReg(); 333 Register Base = MBBI->getOperand(1).getReg(); 334 Register VL = MBBI->getOperand(2).getReg(); 335 auto ZvlssegInfo = TII->isRVVSpillForZvlsseg(MBBI->getOpcode()); 336 if (!ZvlssegInfo) 337 return false; 338 unsigned NF = ZvlssegInfo->first; 339 unsigned LMUL = ZvlssegInfo->second; 340 assert(NF * LMUL <= 8 && "Invalid NF/LMUL combinations."); 341 unsigned Opcode = RISCV::VL1RE8_V; 342 unsigned SubRegIdx = RISCV::sub_vrm1_0; 343 static_assert(RISCV::sub_vrm1_7 == RISCV::sub_vrm1_0 + 7, 344 "Unexpected subreg numbering"); 345 if (LMUL == 2) { 346 Opcode = RISCV::VL2RE8_V; 347 SubRegIdx = RISCV::sub_vrm2_0; 348 static_assert(RISCV::sub_vrm2_3 == RISCV::sub_vrm2_0 + 3, 349 "Unexpected subreg numbering"); 350 } else if (LMUL == 4) { 351 Opcode = RISCV::VL4RE8_V; 352 SubRegIdx = RISCV::sub_vrm4_0; 353 static_assert(RISCV::sub_vrm4_1 == RISCV::sub_vrm4_0 + 1, 354 "Unexpected subreg numbering"); 355 } else 356 assert(LMUL == 1 && "LMUL must be 1, 2, or 4."); 357 358 for (unsigned I = 0; I < NF; ++I) { 359 BuildMI(MBB, MBBI, DL, TII->get(Opcode), 360 TRI->getSubReg(DestReg, SubRegIdx + I)) 361 .addReg(Base) 362 .addMemOperand(*(MBBI->memoperands_begin())); 363 if (I != NF - 1) 364 BuildMI(MBB, MBBI, DL, TII->get(RISCV::ADD), Base) 365 .addReg(Base) 366 .addReg(VL); 367 } 368 MBBI->eraseFromParent(); 369 return true; 370} 371 372} // end of anonymous namespace 373 374INITIALIZE_PASS(RISCVExpandPseudo, "riscv-expand-pseudo", 375 RISCV_EXPAND_PSEUDO_NAME, false, false) 376namespace llvm { 377 378FunctionPass *createRISCVExpandPseudoPass() { return new RISCVExpandPseudo(); } 379 380} // end of namespace llvm 381