1 //===-- LoongArchExpandPseudoInsts.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. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "LoongArch.h" 15 #include "LoongArchInstrInfo.h" 16 #include "LoongArchTargetMachine.h" 17 #include "MCTargetDesc/LoongArchBaseInfo.h" 18 #include "MCTargetDesc/LoongArchMCTargetDesc.h" 19 #include "llvm/CodeGen/LivePhysRegs.h" 20 #include "llvm/CodeGen/MachineFunctionPass.h" 21 #include "llvm/CodeGen/MachineInstrBuilder.h" 22 #include "llvm/CodeGen/MachineOperand.h" 23 #include "llvm/CodeGen/Register.h" 24 #include "llvm/MC/MCContext.h" 25 #include "llvm/Support/CodeGen.h" 26 #include "llvm/Support/ErrorHandling.h" 27 28 using namespace llvm; 29 30 #define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \ 31 "LoongArch Pre-RA pseudo instruction expansion pass" 32 #define LOONGARCH_EXPAND_PSEUDO_NAME \ 33 "LoongArch pseudo instruction expansion pass" 34 35 namespace { 36 37 class LoongArchPreRAExpandPseudo : public MachineFunctionPass { 38 public: 39 const LoongArchInstrInfo *TII; 40 static char ID; 41 42 LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) { 43 initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry()); 44 } 45 46 bool runOnMachineFunction(MachineFunction &MF) override; 47 48 void getAnalysisUsage(AnalysisUsage &AU) const override { 49 AU.setPreservesCFG(); 50 MachineFunctionPass::getAnalysisUsage(AU); 51 } 52 StringRef getPassName() const override { 53 return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME; 54 } 55 56 private: 57 bool expandMBB(MachineBasicBlock &MBB); 58 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 59 MachineBasicBlock::iterator &NextMBBI); 60 bool expandPcalau12iInstPair(MachineBasicBlock &MBB, 61 MachineBasicBlock::iterator MBBI, 62 MachineBasicBlock::iterator &NextMBBI, 63 unsigned FlagsHi, unsigned SecondOpcode, 64 unsigned FlagsLo); 65 bool expandLargeAddressLoad(MachineBasicBlock &MBB, 66 MachineBasicBlock::iterator MBBI, 67 MachineBasicBlock::iterator &NextMBBI, 68 unsigned LastOpcode, unsigned IdentifyingMO); 69 bool expandLargeAddressLoad(MachineBasicBlock &MBB, 70 MachineBasicBlock::iterator MBBI, 71 MachineBasicBlock::iterator &NextMBBI, 72 unsigned LastOpcode, unsigned IdentifyingMO, 73 const MachineOperand &Symbol, Register DestReg, 74 bool EraseFromParent); 75 bool expandLoadAddressPcrel(MachineBasicBlock &MBB, 76 MachineBasicBlock::iterator MBBI, 77 MachineBasicBlock::iterator &NextMBBI, 78 bool Large = false); 79 bool expandLoadAddressGot(MachineBasicBlock &MBB, 80 MachineBasicBlock::iterator MBBI, 81 MachineBasicBlock::iterator &NextMBBI, 82 bool Large = false); 83 bool expandLoadAddressTLSLE(MachineBasicBlock &MBB, 84 MachineBasicBlock::iterator MBBI, 85 MachineBasicBlock::iterator &NextMBBI); 86 bool expandLoadAddressTLSIE(MachineBasicBlock &MBB, 87 MachineBasicBlock::iterator MBBI, 88 MachineBasicBlock::iterator &NextMBBI, 89 bool Large = false); 90 bool expandLoadAddressTLSLD(MachineBasicBlock &MBB, 91 MachineBasicBlock::iterator MBBI, 92 MachineBasicBlock::iterator &NextMBBI, 93 bool Large = false); 94 bool expandLoadAddressTLSGD(MachineBasicBlock &MBB, 95 MachineBasicBlock::iterator MBBI, 96 MachineBasicBlock::iterator &NextMBBI, 97 bool Large = false); 98 bool expandFunctionCALL(MachineBasicBlock &MBB, 99 MachineBasicBlock::iterator MBBI, 100 MachineBasicBlock::iterator &NextMBBI, 101 bool IsTailCall); 102 }; 103 104 char LoongArchPreRAExpandPseudo::ID = 0; 105 106 bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) { 107 TII = 108 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo()); 109 bool Modified = false; 110 for (auto &MBB : MF) 111 Modified |= expandMBB(MBB); 112 return Modified; 113 } 114 115 bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) { 116 bool Modified = false; 117 118 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 119 while (MBBI != E) { 120 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 121 Modified |= expandMI(MBB, MBBI, NMBBI); 122 MBBI = NMBBI; 123 } 124 125 return Modified; 126 } 127 128 bool LoongArchPreRAExpandPseudo::expandMI( 129 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 130 MachineBasicBlock::iterator &NextMBBI) { 131 switch (MBBI->getOpcode()) { 132 case LoongArch::PseudoLA_PCREL: 133 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI); 134 case LoongArch::PseudoLA_PCREL_LARGE: 135 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI, /*Large=*/true); 136 case LoongArch::PseudoLA_GOT: 137 return expandLoadAddressGot(MBB, MBBI, NextMBBI); 138 case LoongArch::PseudoLA_GOT_LARGE: 139 return expandLoadAddressGot(MBB, MBBI, NextMBBI, /*Large=*/true); 140 case LoongArch::PseudoLA_TLS_LE: 141 return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI); 142 case LoongArch::PseudoLA_TLS_IE: 143 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI); 144 case LoongArch::PseudoLA_TLS_IE_LARGE: 145 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI, /*Large=*/true); 146 case LoongArch::PseudoLA_TLS_LD: 147 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI); 148 case LoongArch::PseudoLA_TLS_LD_LARGE: 149 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI, /*Large=*/true); 150 case LoongArch::PseudoLA_TLS_GD: 151 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI); 152 case LoongArch::PseudoLA_TLS_GD_LARGE: 153 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI, /*Large=*/true); 154 case LoongArch::PseudoCALL: 155 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false); 156 case LoongArch::PseudoTAIL: 157 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true); 158 } 159 return false; 160 } 161 162 bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair( 163 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 164 MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi, 165 unsigned SecondOpcode, unsigned FlagsLo) { 166 MachineFunction *MF = MBB.getParent(); 167 MachineInstr &MI = *MBBI; 168 DebugLoc DL = MI.getDebugLoc(); 169 170 Register DestReg = MI.getOperand(0).getReg(); 171 Register ScratchReg = 172 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 173 MachineOperand &Symbol = MI.getOperand(1); 174 175 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg) 176 .addDisp(Symbol, 0, FlagsHi); 177 178 MachineInstr *SecondMI = 179 BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg) 180 .addReg(ScratchReg) 181 .addDisp(Symbol, 0, FlagsLo); 182 183 if (MI.hasOneMemOperand()) 184 SecondMI->addMemOperand(*MF, *MI.memoperands_begin()); 185 186 MI.eraseFromParent(); 187 return true; 188 } 189 190 bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad( 191 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 192 MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode, 193 unsigned IdentifyingMO) { 194 MachineInstr &MI = *MBBI; 195 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO, 196 MI.getOperand(2), MI.getOperand(0).getReg(), 197 true); 198 } 199 200 bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad( 201 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 202 MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode, 203 unsigned IdentifyingMO, const MachineOperand &Symbol, Register DestReg, 204 bool EraseFromParent) { 205 // Code Sequence: 206 // 207 // Part1: pcalau12i $scratch, %MO1(sym) 208 // Part0: addi.d $dest, $zero, %MO0(sym) 209 // Part2: lu32i.d $dest, %MO2(sym) 210 // Part3: lu52i.d $dest, $dest, %MO3(sym) 211 // Fin: LastOpcode $dest, $dest, $scratch 212 213 unsigned MO0, MO1, MO2, MO3; 214 switch (IdentifyingMO) { 215 default: 216 llvm_unreachable("unsupported identifying MO"); 217 case LoongArchII::MO_PCREL_LO: 218 MO0 = IdentifyingMO; 219 MO1 = LoongArchII::MO_PCREL_HI; 220 MO2 = LoongArchII::MO_PCREL64_LO; 221 MO3 = LoongArchII::MO_PCREL64_HI; 222 break; 223 case LoongArchII::MO_GOT_PC_HI: 224 case LoongArchII::MO_LD_PC_HI: 225 case LoongArchII::MO_GD_PC_HI: 226 // These cases relocate just like the GOT case, except for Part1. 227 MO0 = LoongArchII::MO_GOT_PC_LO; 228 MO1 = IdentifyingMO; 229 MO2 = LoongArchII::MO_GOT_PC64_LO; 230 MO3 = LoongArchII::MO_GOT_PC64_HI; 231 break; 232 case LoongArchII::MO_IE_PC_LO: 233 MO0 = IdentifyingMO; 234 MO1 = LoongArchII::MO_IE_PC_HI; 235 MO2 = LoongArchII::MO_IE_PC64_LO; 236 MO3 = LoongArchII::MO_IE_PC64_HI; 237 break; 238 } 239 240 MachineFunction *MF = MBB.getParent(); 241 MachineInstr &MI = *MBBI; 242 DebugLoc DL = MI.getDebugLoc(); 243 244 assert(MF->getSubtarget<LoongArchSubtarget>().is64Bit() && 245 "Large code model requires LA64"); 246 247 Register TmpPart1 = 248 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 249 Register TmpPart0 = 250 DestReg.isVirtual() 251 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass) 252 : DestReg; 253 Register TmpParts02 = 254 DestReg.isVirtual() 255 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass) 256 : DestReg; 257 Register TmpParts023 = 258 DestReg.isVirtual() 259 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass) 260 : DestReg; 261 262 auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), TmpPart1); 263 auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), TmpPart0) 264 .addReg(LoongArch::R0); 265 auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), TmpParts02) 266 // "rj" is needed due to InstrInfo pattern requirement. 267 .addReg(TmpPart0, RegState::Kill); 268 auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), TmpParts023) 269 .addReg(TmpParts02, RegState::Kill); 270 BuildMI(MBB, MBBI, DL, TII->get(LastOpcode), DestReg) 271 .addReg(TmpParts023) 272 .addReg(TmpPart1, RegState::Kill); 273 274 if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) { 275 const char *SymName = Symbol.getSymbolName(); 276 Part0.addExternalSymbol(SymName, MO0); 277 Part1.addExternalSymbol(SymName, MO1); 278 Part2.addExternalSymbol(SymName, MO2); 279 Part3.addExternalSymbol(SymName, MO3); 280 } else { 281 Part0.addDisp(Symbol, 0, MO0); 282 Part1.addDisp(Symbol, 0, MO1); 283 Part2.addDisp(Symbol, 0, MO2); 284 Part3.addDisp(Symbol, 0, MO3); 285 } 286 287 if (EraseFromParent) 288 MI.eraseFromParent(); 289 290 return true; 291 } 292 293 bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel( 294 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 295 MachineBasicBlock::iterator &NextMBBI, bool Large) { 296 if (Large) 297 // Emit the 5-insn large address load sequence with the `%pc` family of 298 // relocs. 299 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D, 300 LoongArchII::MO_PCREL_LO); 301 302 // Code Sequence: 303 // pcalau12i $rd, %pc_hi20(sym) 304 // addi.w/d $rd, $rd, %pc_lo12(sym) 305 MachineFunction *MF = MBB.getParent(); 306 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 307 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 308 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI, 309 SecondOpcode, LoongArchII::MO_PCREL_LO); 310 } 311 312 bool LoongArchPreRAExpandPseudo::expandLoadAddressGot( 313 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 314 MachineBasicBlock::iterator &NextMBBI, bool Large) { 315 if (Large) 316 // Emit the 5-insn large address load sequence with the `%got_pc` family 317 // of relocs, loading the result from GOT with `ldx.d` in the end. 318 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D, 319 LoongArchII::MO_GOT_PC_HI); 320 321 // Code Sequence: 322 // pcalau12i $rd, %got_pc_hi20(sym) 323 // ld.w/d $rd, $rd, %got_pc_lo12(sym) 324 MachineFunction *MF = MBB.getParent(); 325 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 326 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 327 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI, 328 SecondOpcode, LoongArchII::MO_GOT_PC_LO); 329 } 330 331 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE( 332 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 333 MachineBasicBlock::iterator &NextMBBI) { 334 // Code Sequence: 335 // lu12i.w $rd, %le_hi20(sym) 336 // ori $rd, $rd, %le_lo12(sym) 337 // 338 // And additionally if generating code using the large code model: 339 // 340 // lu32i.d $rd, %le64_lo20(sym) 341 // lu52i.d $rd, $rd, %le64_hi12(sym) 342 MachineFunction *MF = MBB.getParent(); 343 MachineInstr &MI = *MBBI; 344 DebugLoc DL = MI.getDebugLoc(); 345 346 bool Large = MF->getTarget().getCodeModel() == CodeModel::Large; 347 Register DestReg = MI.getOperand(0).getReg(); 348 Register Parts01 = 349 Large ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass) 350 : DestReg; 351 Register Part1 = 352 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 353 MachineOperand &Symbol = MI.getOperand(1); 354 355 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1) 356 .addDisp(Symbol, 0, LoongArchII::MO_LE_HI); 357 358 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01) 359 .addReg(Part1, RegState::Kill) 360 .addDisp(Symbol, 0, LoongArchII::MO_LE_LO); 361 362 if (Large) { 363 Register Parts012 = 364 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 365 366 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Parts012) 367 // "rj" is needed due to InstrInfo pattern requirement. 368 .addReg(Parts01, RegState::Kill) 369 .addDisp(Symbol, 0, LoongArchII::MO_LE64_LO); 370 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), DestReg) 371 .addReg(Parts012, RegState::Kill) 372 .addDisp(Symbol, 0, LoongArchII::MO_LE64_HI); 373 } 374 375 MI.eraseFromParent(); 376 return true; 377 } 378 379 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE( 380 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 381 MachineBasicBlock::iterator &NextMBBI, bool Large) { 382 if (Large) 383 // Emit the 5-insn large address load sequence with the `%ie_pc` family 384 // of relocs, loading the result with `ldx.d` in the end. 385 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D, 386 LoongArchII::MO_IE_PC_LO); 387 388 // Code Sequence: 389 // pcalau12i $rd, %ie_pc_hi20(sym) 390 // ld.w/d $rd, $rd, %ie_pc_lo12(sym) 391 MachineFunction *MF = MBB.getParent(); 392 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 393 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 394 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_IE_PC_HI, 395 SecondOpcode, LoongArchII::MO_IE_PC_LO); 396 } 397 398 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD( 399 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 400 MachineBasicBlock::iterator &NextMBBI, bool Large) { 401 if (Large) 402 // Emit the 5-insn large address load sequence with the `%got_pc` family 403 // of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`. 404 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D, 405 LoongArchII::MO_LD_PC_HI); 406 407 // Code Sequence: 408 // pcalau12i $rd, %ld_pc_hi20(sym) 409 // addi.w/d $rd, $rd, %got_pc_lo12(sym) 410 MachineFunction *MF = MBB.getParent(); 411 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 412 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 413 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_LD_PC_HI, 414 SecondOpcode, LoongArchII::MO_GOT_PC_LO); 415 } 416 417 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD( 418 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 419 MachineBasicBlock::iterator &NextMBBI, bool Large) { 420 if (Large) 421 // Emit the 5-insn large address load sequence with the `%got_pc` family 422 // of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`. 423 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D, 424 LoongArchII::MO_GD_PC_HI); 425 426 // Code Sequence: 427 // pcalau12i $rd, %gd_pc_hi20(sym) 428 // addi.w/d $rd, $rd, %got_pc_lo12(sym) 429 MachineFunction *MF = MBB.getParent(); 430 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 431 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 432 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GD_PC_HI, 433 SecondOpcode, LoongArchII::MO_GOT_PC_LO); 434 } 435 436 bool LoongArchPreRAExpandPseudo::expandFunctionCALL( 437 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 438 MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) { 439 MachineFunction *MF = MBB.getParent(); 440 MachineInstr &MI = *MBBI; 441 DebugLoc DL = MI.getDebugLoc(); 442 const MachineOperand &Func = MI.getOperand(0); 443 MachineInstrBuilder CALL; 444 unsigned Opcode; 445 446 switch (MF->getTarget().getCodeModel()) { 447 default: 448 report_fatal_error("Unsupported code model"); 449 break; 450 case CodeModel::Small: { 451 // CALL: 452 // bl func 453 // TAIL: 454 // b func 455 Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL; 456 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func); 457 break; 458 } 459 case CodeModel::Medium: { 460 // CALL: 461 // pcalau12i $ra, %pc_hi20(func) 462 // jirl $ra, $ra, %pc_lo12(func) 463 // TAIL: 464 // pcalau12i $scratch, %pc_hi20(func) 465 // jirl $r0, $scratch, %pc_lo12(func) 466 Opcode = 467 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL; 468 Register ScratchReg = 469 IsTailCall 470 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass) 471 : LoongArch::R1; 472 MachineInstrBuilder MIB = 473 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg); 474 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg); 475 if (Func.isSymbol()) { 476 const char *FnName = Func.getSymbolName(); 477 MIB.addExternalSymbol(FnName, LoongArchII::MO_PCREL_HI); 478 CALL.addExternalSymbol(FnName, LoongArchII::MO_PCREL_LO); 479 break; 480 } 481 assert(Func.isGlobal() && "Expected a GlobalValue at this time"); 482 const GlobalValue *GV = Func.getGlobal(); 483 MIB.addGlobalAddress(GV, 0, LoongArchII::MO_PCREL_HI); 484 CALL.addGlobalAddress(GV, 0, LoongArchII::MO_PCREL_LO); 485 break; 486 } 487 case CodeModel::Large: { 488 // Emit the 5-insn large address load sequence, either directly or 489 // indirectly in case of going through the GOT, then JIRL_TAIL or 490 // JIRL_CALL to $addr. 491 Opcode = 492 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL; 493 Register AddrReg = 494 IsTailCall 495 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass) 496 : LoongArch::R1; 497 498 bool UseGOT = Func.isGlobal() && !Func.getGlobal()->isDSOLocal(); 499 unsigned MO = UseGOT ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_PCREL_LO; 500 unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D; 501 expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg, 502 false); 503 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0); 504 break; 505 } 506 } 507 508 // Transfer implicit operands. 509 CALL.copyImplicitOps(MI); 510 511 // Transfer MI flags. 512 CALL.setMIFlags(MI.getFlags()); 513 514 MI.eraseFromParent(); 515 return true; 516 } 517 518 class LoongArchExpandPseudo : public MachineFunctionPass { 519 public: 520 const LoongArchInstrInfo *TII; 521 static char ID; 522 523 LoongArchExpandPseudo() : MachineFunctionPass(ID) { 524 initializeLoongArchExpandPseudoPass(*PassRegistry::getPassRegistry()); 525 } 526 527 bool runOnMachineFunction(MachineFunction &MF) override; 528 529 StringRef getPassName() const override { 530 return LOONGARCH_EXPAND_PSEUDO_NAME; 531 } 532 533 private: 534 bool expandMBB(MachineBasicBlock &MBB); 535 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 536 MachineBasicBlock::iterator &NextMBBI); 537 bool expandCopyCFR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 538 MachineBasicBlock::iterator &NextMBBI); 539 }; 540 541 char LoongArchExpandPseudo::ID = 0; 542 543 bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) { 544 TII = 545 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo()); 546 547 bool Modified = false; 548 for (auto &MBB : MF) 549 Modified |= expandMBB(MBB); 550 551 return Modified; 552 } 553 554 bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) { 555 bool Modified = false; 556 557 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 558 while (MBBI != E) { 559 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 560 Modified |= expandMI(MBB, MBBI, NMBBI); 561 MBBI = NMBBI; 562 } 563 564 return Modified; 565 } 566 567 bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB, 568 MachineBasicBlock::iterator MBBI, 569 MachineBasicBlock::iterator &NextMBBI) { 570 switch (MBBI->getOpcode()) { 571 case LoongArch::PseudoCopyCFR: 572 return expandCopyCFR(MBB, MBBI, NextMBBI); 573 } 574 575 return false; 576 } 577 578 bool LoongArchExpandPseudo::expandCopyCFR( 579 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 580 MachineBasicBlock::iterator &NextMBBI) { 581 MachineFunction *MF = MBB.getParent(); 582 MachineInstr &MI = *MBBI; 583 DebugLoc DL = MI.getDebugLoc(); 584 585 // Expand: 586 // MBB: 587 // fcmp.caf.s $dst, $fa0, $fa0 # set $dst 0(false) 588 // bceqz $src, SinkBB 589 // FalseBB: 590 // fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true) 591 // SinkBB: 592 // fallthrough 593 594 const BasicBlock *LLVM_BB = MBB.getBasicBlock(); 595 auto *FalseBB = MF->CreateMachineBasicBlock(LLVM_BB); 596 auto *SinkBB = MF->CreateMachineBasicBlock(LLVM_BB); 597 598 MF->insert(++MBB.getIterator(), FalseBB); 599 MF->insert(++FalseBB->getIterator(), SinkBB); 600 601 Register DestReg = MI.getOperand(0).getReg(); 602 Register SrcReg = MI.getOperand(1).getReg(); 603 // DestReg = 0 604 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::SET_CFR_FALSE), DestReg); 605 // Insert branch instruction. 606 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BCEQZ)) 607 .addReg(SrcReg) 608 .addMBB(SinkBB); 609 // DestReg = 1 610 BuildMI(FalseBB, DL, TII->get(LoongArch::SET_CFR_TRUE), DestReg); 611 612 FalseBB->addSuccessor(SinkBB); 613 614 SinkBB->splice(SinkBB->end(), &MBB, MI, MBB.end()); 615 SinkBB->transferSuccessors(&MBB); 616 617 MBB.addSuccessor(FalseBB); 618 MBB.addSuccessor(SinkBB); 619 620 NextMBBI = MBB.end(); 621 MI.eraseFromParent(); 622 623 // Make sure live-ins are correctly attached to this new basic block. 624 LivePhysRegs LiveRegs; 625 computeAndAddLiveIns(LiveRegs, *FalseBB); 626 computeAndAddLiveIns(LiveRegs, *SinkBB); 627 628 return true; 629 } 630 631 } // end namespace 632 633 INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo", 634 LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false) 635 636 INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo", 637 LOONGARCH_EXPAND_PSEUDO_NAME, false, false) 638 639 namespace llvm { 640 641 FunctionPass *createLoongArchPreRAExpandPseudoPass() { 642 return new LoongArchPreRAExpandPseudo(); 643 } 644 FunctionPass *createLoongArchExpandPseudoPass() { 645 return new LoongArchExpandPseudo(); 646 } 647 648 } // end namespace llvm 649