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 "LoongArchMachineFunctionInfo.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 extern cl::opt<bool> LArchAnnotateTableJump; 31 32 #define LOONGARCH_PRERA_EXPAND_PSEUDO_NAME \ 33 "LoongArch Pre-RA pseudo instruction expansion pass" 34 #define LOONGARCH_EXPAND_PSEUDO_NAME \ 35 "LoongArch pseudo instruction expansion pass" 36 37 namespace { 38 39 class LoongArchPreRAExpandPseudo : public MachineFunctionPass { 40 public: 41 const LoongArchInstrInfo *TII; 42 static char ID; 43 44 LoongArchPreRAExpandPseudo() : MachineFunctionPass(ID) { 45 initializeLoongArchPreRAExpandPseudoPass(*PassRegistry::getPassRegistry()); 46 } 47 48 bool runOnMachineFunction(MachineFunction &MF) override; 49 50 void getAnalysisUsage(AnalysisUsage &AU) const override { 51 AU.setPreservesCFG(); 52 MachineFunctionPass::getAnalysisUsage(AU); 53 } 54 StringRef getPassName() const override { 55 return LOONGARCH_PRERA_EXPAND_PSEUDO_NAME; 56 } 57 58 private: 59 bool expandMBB(MachineBasicBlock &MBB); 60 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 61 MachineBasicBlock::iterator &NextMBBI); 62 bool expandPcalau12iInstPair(MachineBasicBlock &MBB, 63 MachineBasicBlock::iterator MBBI, 64 MachineBasicBlock::iterator &NextMBBI, 65 unsigned FlagsHi, unsigned SecondOpcode, 66 unsigned FlagsLo); 67 bool expandLargeAddressLoad(MachineBasicBlock &MBB, 68 MachineBasicBlock::iterator MBBI, 69 MachineBasicBlock::iterator &NextMBBI, 70 unsigned LastOpcode, unsigned IdentifyingMO); 71 bool expandLargeAddressLoad(MachineBasicBlock &MBB, 72 MachineBasicBlock::iterator MBBI, 73 MachineBasicBlock::iterator &NextMBBI, 74 unsigned LastOpcode, unsigned IdentifyingMO, 75 const MachineOperand &Symbol, Register DestReg, 76 bool EraseFromParent); 77 bool expandLoadAddressPcrel(MachineBasicBlock &MBB, 78 MachineBasicBlock::iterator MBBI, 79 MachineBasicBlock::iterator &NextMBBI, 80 bool Large = false); 81 bool expandLoadAddressGot(MachineBasicBlock &MBB, 82 MachineBasicBlock::iterator MBBI, 83 MachineBasicBlock::iterator &NextMBBI, 84 bool Large = false); 85 bool expandLoadAddressTLSLE(MachineBasicBlock &MBB, 86 MachineBasicBlock::iterator MBBI, 87 MachineBasicBlock::iterator &NextMBBI); 88 bool expandLoadAddressTLSIE(MachineBasicBlock &MBB, 89 MachineBasicBlock::iterator MBBI, 90 MachineBasicBlock::iterator &NextMBBI, 91 bool Large = false); 92 bool expandLoadAddressTLSLD(MachineBasicBlock &MBB, 93 MachineBasicBlock::iterator MBBI, 94 MachineBasicBlock::iterator &NextMBBI, 95 bool Large = false); 96 bool expandLoadAddressTLSGD(MachineBasicBlock &MBB, 97 MachineBasicBlock::iterator MBBI, 98 MachineBasicBlock::iterator &NextMBBI, 99 bool Large = false); 100 bool expandLoadAddressTLSDesc(MachineBasicBlock &MBB, 101 MachineBasicBlock::iterator MBBI, 102 MachineBasicBlock::iterator &NextMBBI, 103 bool Large = false); 104 bool expandFunctionCALL(MachineBasicBlock &MBB, 105 MachineBasicBlock::iterator MBBI, 106 MachineBasicBlock::iterator &NextMBBI, 107 bool IsTailCall); 108 void annotateTableJump(MachineBasicBlock &MBB, 109 MachineBasicBlock::iterator MBBI); 110 }; 111 112 char LoongArchPreRAExpandPseudo::ID = 0; 113 114 bool LoongArchPreRAExpandPseudo::runOnMachineFunction(MachineFunction &MF) { 115 TII = 116 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo()); 117 bool Modified = false; 118 for (auto &MBB : MF) 119 Modified |= expandMBB(MBB); 120 return Modified; 121 } 122 123 bool LoongArchPreRAExpandPseudo::expandMBB(MachineBasicBlock &MBB) { 124 bool Modified = false; 125 126 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 127 while (MBBI != E) { 128 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 129 Modified |= expandMI(MBB, MBBI, NMBBI); 130 MBBI = NMBBI; 131 } 132 133 return Modified; 134 } 135 136 bool LoongArchPreRAExpandPseudo::expandMI( 137 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 138 MachineBasicBlock::iterator &NextMBBI) { 139 switch (MBBI->getOpcode()) { 140 case LoongArch::PseudoLA_PCREL: 141 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI); 142 case LoongArch::PseudoLA_PCREL_LARGE: 143 return expandLoadAddressPcrel(MBB, MBBI, NextMBBI, /*Large=*/true); 144 case LoongArch::PseudoLA_GOT: 145 return expandLoadAddressGot(MBB, MBBI, NextMBBI); 146 case LoongArch::PseudoLA_GOT_LARGE: 147 return expandLoadAddressGot(MBB, MBBI, NextMBBI, /*Large=*/true); 148 case LoongArch::PseudoLA_TLS_LE: 149 return expandLoadAddressTLSLE(MBB, MBBI, NextMBBI); 150 case LoongArch::PseudoLA_TLS_IE: 151 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI); 152 case LoongArch::PseudoLA_TLS_IE_LARGE: 153 return expandLoadAddressTLSIE(MBB, MBBI, NextMBBI, /*Large=*/true); 154 case LoongArch::PseudoLA_TLS_LD: 155 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI); 156 case LoongArch::PseudoLA_TLS_LD_LARGE: 157 return expandLoadAddressTLSLD(MBB, MBBI, NextMBBI, /*Large=*/true); 158 case LoongArch::PseudoLA_TLS_GD: 159 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI); 160 case LoongArch::PseudoLA_TLS_GD_LARGE: 161 return expandLoadAddressTLSGD(MBB, MBBI, NextMBBI, /*Large=*/true); 162 case LoongArch::PseudoLA_TLS_DESC: 163 return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI); 164 case LoongArch::PseudoLA_TLS_DESC_LARGE: 165 return expandLoadAddressTLSDesc(MBB, MBBI, NextMBBI, /*Large=*/true); 166 case LoongArch::PseudoCALL: 167 case LoongArch::PseudoCALL_LARGE: 168 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false); 169 case LoongArch::PseudoTAIL: 170 case LoongArch::PseudoTAIL_LARGE: 171 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true); 172 case LoongArch::PseudoBRIND: 173 // If the PseudoBRIND is used to table jump, then emit a label to annotate 174 // the `jr` instruction, and save the instructions. 175 if (LArchAnnotateTableJump) 176 annotateTableJump(MBB, MBBI); 177 break; 178 } 179 return false; 180 } 181 182 bool LoongArchPreRAExpandPseudo::expandPcalau12iInstPair( 183 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 184 MachineBasicBlock::iterator &NextMBBI, unsigned FlagsHi, 185 unsigned SecondOpcode, unsigned FlagsLo) { 186 MachineFunction *MF = MBB.getParent(); 187 MachineInstr &MI = *MBBI; 188 DebugLoc DL = MI.getDebugLoc(); 189 190 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 191 bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax); 192 193 Register DestReg = MI.getOperand(0).getReg(); 194 Register ScratchReg = 195 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 196 MachineOperand &Symbol = MI.getOperand(1); 197 198 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), ScratchReg) 199 .addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsHi, EnableRelax)); 200 201 MachineInstr *SecondMI = 202 BuildMI(MBB, MBBI, DL, TII->get(SecondOpcode), DestReg) 203 .addReg(ScratchReg) 204 .addDisp(Symbol, 0, LoongArchII::encodeFlags(FlagsLo, EnableRelax)); 205 206 if (MI.hasOneMemOperand()) 207 SecondMI->addMemOperand(*MF, *MI.memoperands_begin()); 208 209 MI.eraseFromParent(); 210 return true; 211 } 212 213 bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad( 214 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 215 MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode, 216 unsigned IdentifyingMO) { 217 MachineInstr &MI = *MBBI; 218 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LastOpcode, IdentifyingMO, 219 MI.getOperand(2), MI.getOperand(0).getReg(), 220 true); 221 } 222 223 bool LoongArchPreRAExpandPseudo::expandLargeAddressLoad( 224 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 225 MachineBasicBlock::iterator &NextMBBI, unsigned LastOpcode, 226 unsigned IdentifyingMO, const MachineOperand &Symbol, Register DestReg, 227 bool EraseFromParent) { 228 // Code Sequence: 229 // 230 // Part1: pcalau12i $scratch, %MO1(sym) 231 // Part0: addi.d $dest, $zero, %MO0(sym) 232 // Part2: lu32i.d $dest, %MO2(sym) 233 // Part3: lu52i.d $dest, $dest, %MO3(sym) 234 // Fin: LastOpcode $dest, $dest, $scratch 235 236 unsigned MO0, MO1, MO2, MO3; 237 switch (IdentifyingMO) { 238 default: 239 llvm_unreachable("unsupported identifying MO"); 240 case LoongArchII::MO_PCREL_LO: 241 MO0 = IdentifyingMO; 242 MO1 = LoongArchII::MO_PCREL_HI; 243 MO2 = LoongArchII::MO_PCREL64_LO; 244 MO3 = LoongArchII::MO_PCREL64_HI; 245 break; 246 case LoongArchII::MO_GOT_PC_HI: 247 case LoongArchII::MO_LD_PC_HI: 248 case LoongArchII::MO_GD_PC_HI: 249 // These cases relocate just like the GOT case, except for Part1. 250 MO0 = LoongArchII::MO_GOT_PC_LO; 251 MO1 = IdentifyingMO; 252 MO2 = LoongArchII::MO_GOT_PC64_LO; 253 MO3 = LoongArchII::MO_GOT_PC64_HI; 254 break; 255 case LoongArchII::MO_IE_PC_LO: 256 MO0 = IdentifyingMO; 257 MO1 = LoongArchII::MO_IE_PC_HI; 258 MO2 = LoongArchII::MO_IE_PC64_LO; 259 MO3 = LoongArchII::MO_IE_PC64_HI; 260 break; 261 } 262 263 MachineFunction *MF = MBB.getParent(); 264 MachineInstr &MI = *MBBI; 265 DebugLoc DL = MI.getDebugLoc(); 266 267 assert(MF->getSubtarget<LoongArchSubtarget>().is64Bit() && 268 "Large code model requires LA64"); 269 270 Register TmpPart1 = 271 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 272 Register TmpPart0 = 273 DestReg.isVirtual() 274 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass) 275 : DestReg; 276 Register TmpParts02 = 277 DestReg.isVirtual() 278 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass) 279 : DestReg; 280 Register TmpParts023 = 281 DestReg.isVirtual() 282 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass) 283 : DestReg; 284 285 auto Part1 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), TmpPart1); 286 auto Part0 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), TmpPart0) 287 .addReg(LoongArch::R0); 288 auto Part2 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), TmpParts02) 289 // "rj" is needed due to InstrInfo pattern requirement. 290 .addReg(TmpPart0, RegState::Kill); 291 auto Part3 = BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), TmpParts023) 292 .addReg(TmpParts02, RegState::Kill); 293 BuildMI(MBB, MBBI, DL, TII->get(LastOpcode), DestReg) 294 .addReg(TmpParts023) 295 .addReg(TmpPart1, RegState::Kill); 296 297 if (Symbol.getType() == MachineOperand::MO_ExternalSymbol) { 298 const char *SymName = Symbol.getSymbolName(); 299 Part0.addExternalSymbol(SymName, MO0); 300 Part1.addExternalSymbol(SymName, MO1); 301 Part2.addExternalSymbol(SymName, MO2); 302 Part3.addExternalSymbol(SymName, MO3); 303 } else { 304 Part0.addDisp(Symbol, 0, MO0); 305 Part1.addDisp(Symbol, 0, MO1); 306 Part2.addDisp(Symbol, 0, MO2); 307 Part3.addDisp(Symbol, 0, MO3); 308 } 309 310 if (EraseFromParent) 311 MI.eraseFromParent(); 312 313 return true; 314 } 315 316 bool LoongArchPreRAExpandPseudo::expandLoadAddressPcrel( 317 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 318 MachineBasicBlock::iterator &NextMBBI, bool Large) { 319 if (Large) 320 // Emit the 5-insn large address load sequence with the `%pc` family of 321 // relocs. 322 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D, 323 LoongArchII::MO_PCREL_LO); 324 325 // Code Sequence: 326 // pcalau12i $rd, %pc_hi20(sym) 327 // addi.w/d $rd, $rd, %pc_lo12(sym) 328 MachineFunction *MF = MBB.getParent(); 329 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 330 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 331 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_PCREL_HI, 332 SecondOpcode, LoongArchII::MO_PCREL_LO); 333 } 334 335 bool LoongArchPreRAExpandPseudo::expandLoadAddressGot( 336 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 337 MachineBasicBlock::iterator &NextMBBI, bool Large) { 338 if (Large) 339 // Emit the 5-insn large address load sequence with the `%got_pc` family 340 // of relocs, loading the result from GOT with `ldx.d` in the end. 341 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D, 342 LoongArchII::MO_GOT_PC_HI); 343 344 // Code Sequence: 345 // pcalau12i $rd, %got_pc_hi20(sym) 346 // ld.w/d $rd, $rd, %got_pc_lo12(sym) 347 MachineFunction *MF = MBB.getParent(); 348 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 349 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 350 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GOT_PC_HI, 351 SecondOpcode, LoongArchII::MO_GOT_PC_LO); 352 } 353 354 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLE( 355 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 356 MachineBasicBlock::iterator &NextMBBI) { 357 // Code Sequence: 358 // lu12i.w $rd, %le_hi20_r(sym) 359 // add.w/d $rd, $rd, $tp, %le_add_r(sym) 360 // addi.w/d $rd, $rd, %le_lo12_r(sym) 361 // 362 // Code Sequence while using the large code model: 363 // lu12i.w $rd, %le_hi20(sym) 364 // ori $rd, $rd, %le_lo12(sym) 365 // lu32i.d $rd, %le64_lo20(sym) 366 // lu52i.d $rd, $rd, %le64_hi12(sym) 367 MachineFunction *MF = MBB.getParent(); 368 MachineInstr &MI = *MBBI; 369 DebugLoc DL = MI.getDebugLoc(); 370 371 bool Large = MF->getTarget().getCodeModel() == CodeModel::Large; 372 Register DestReg = MI.getOperand(0).getReg(); 373 Register Parts01 = 374 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 375 Register Part1 = 376 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 377 MachineOperand &Symbol = MI.getOperand(1); 378 379 if (!Large) { 380 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1) 381 .addDisp(Symbol, 0, LoongArchII::MO_LE_HI_R); 382 383 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 384 unsigned AddOp = STI.is64Bit() ? LoongArch::PseudoAddTPRel_D 385 : LoongArch::PseudoAddTPRel_W; 386 BuildMI(MBB, MBBI, DL, TII->get(AddOp), Parts01) 387 .addReg(Part1, RegState::Kill) 388 .addReg(LoongArch::R2) 389 .addDisp(Symbol, 0, LoongArchII::MO_LE_ADD_R); 390 391 unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 392 BuildMI(MBB, MBBI, DL, TII->get(AddiOp), DestReg) 393 .addReg(Parts01, RegState::Kill) 394 .addDisp(Symbol, 0, LoongArchII::MO_LE_LO_R); 395 } else { 396 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU12I_W), Part1) 397 .addDisp(Symbol, 0, LoongArchII::MO_LE_HI); 398 399 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ORI), Parts01) 400 .addReg(Part1, RegState::Kill) 401 .addDisp(Symbol, 0, LoongArchII::MO_LE_LO); 402 403 Register Parts012 = 404 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 405 406 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Parts012) 407 // "rj" is needed due to InstrInfo pattern requirement. 408 .addReg(Parts01, RegState::Kill) 409 .addDisp(Symbol, 0, LoongArchII::MO_LE64_LO); 410 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), DestReg) 411 .addReg(Parts012, RegState::Kill) 412 .addDisp(Symbol, 0, LoongArchII::MO_LE64_HI); 413 } 414 415 MI.eraseFromParent(); 416 return true; 417 } 418 419 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSIE( 420 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 421 MachineBasicBlock::iterator &NextMBBI, bool Large) { 422 if (Large) 423 // Emit the 5-insn large address load sequence with the `%ie_pc` family 424 // of relocs, loading the result with `ldx.d` in the end. 425 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::LDX_D, 426 LoongArchII::MO_IE_PC_LO); 427 428 // Code Sequence: 429 // pcalau12i $rd, %ie_pc_hi20(sym) 430 // ld.w/d $rd, $rd, %ie_pc_lo12(sym) 431 MachineFunction *MF = MBB.getParent(); 432 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 433 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 434 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_IE_PC_HI, 435 SecondOpcode, LoongArchII::MO_IE_PC_LO); 436 } 437 438 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSLD( 439 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 440 MachineBasicBlock::iterator &NextMBBI, bool Large) { 441 if (Large) 442 // Emit the 5-insn large address load sequence with the `%got_pc` family 443 // of relocs, with the `pcalau12i` insn relocated with `%ld_pc_hi20`. 444 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D, 445 LoongArchII::MO_LD_PC_HI); 446 447 // Code Sequence: 448 // pcalau12i $rd, %ld_pc_hi20(sym) 449 // addi.w/d $rd, $rd, %got_pc_lo12(sym) 450 MachineFunction *MF = MBB.getParent(); 451 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 452 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 453 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_LD_PC_HI, 454 SecondOpcode, LoongArchII::MO_GOT_PC_LO); 455 } 456 457 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSGD( 458 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 459 MachineBasicBlock::iterator &NextMBBI, bool Large) { 460 if (Large) 461 // Emit the 5-insn large address load sequence with the `%got_pc` family 462 // of relocs, with the `pcalau12i` insn relocated with `%gd_pc_hi20`. 463 return expandLargeAddressLoad(MBB, MBBI, NextMBBI, LoongArch::ADD_D, 464 LoongArchII::MO_GD_PC_HI); 465 466 // Code Sequence: 467 // pcalau12i $rd, %gd_pc_hi20(sym) 468 // addi.w/d $rd, $rd, %got_pc_lo12(sym) 469 MachineFunction *MF = MBB.getParent(); 470 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 471 unsigned SecondOpcode = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 472 return expandPcalau12iInstPair(MBB, MBBI, NextMBBI, LoongArchII::MO_GD_PC_HI, 473 SecondOpcode, LoongArchII::MO_GOT_PC_LO); 474 } 475 476 bool LoongArchPreRAExpandPseudo::expandLoadAddressTLSDesc( 477 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 478 MachineBasicBlock::iterator &NextMBBI, bool Large) { 479 MachineFunction *MF = MBB.getParent(); 480 MachineInstr &MI = *MBBI; 481 DebugLoc DL = MI.getDebugLoc(); 482 483 const auto &STI = MF->getSubtarget<LoongArchSubtarget>(); 484 unsigned ADD = STI.is64Bit() ? LoongArch::ADD_D : LoongArch::ADD_W; 485 unsigned ADDI = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 486 unsigned LD = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 487 bool EnableRelax = STI.hasFeature(LoongArch::FeatureRelax); 488 489 Register DestReg = MI.getOperand(0).getReg(); 490 Register Tmp1Reg = 491 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 492 MachineOperand &Symbol = MI.getOperand(Large ? 2 : 1); 493 494 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCALAU12I), Tmp1Reg) 495 .addDisp(Symbol, 0, 496 LoongArchII::encodeFlags(LoongArchII::MO_DESC_PC_HI, 497 EnableRelax && !Large)); 498 499 if (Large) { 500 // Code Sequence: 501 // 502 // pcalau12i $a0, %desc_pc_hi20(sym) 503 // addi.d $a1, $zero, %desc_pc_lo12(sym) 504 // lu32i.d $a1, %desc64_pc_lo20(sym) 505 // lu52i.d $a1, $a1, %desc64_pc_hi12(sym) 506 // add.d $a0, $a0, $a1 507 // ld.d $ra, $a0, %desc_ld(sym) 508 // jirl $ra, $ra, %desc_call(sym) 509 // add.d $dst, $a0, $tp 510 assert(MBB.getParent()->getSubtarget<LoongArchSubtarget>().is64Bit() && 511 "Large code model requires LA64"); 512 Register Tmp2Reg = 513 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 514 Register Tmp3Reg = 515 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 516 Register Tmp4Reg = 517 MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass); 518 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADDI_D), Tmp2Reg) 519 .addReg(LoongArch::R0) 520 .addDisp(Symbol, 0, LoongArchII::MO_DESC_PC_LO); 521 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU32I_D), Tmp3Reg) 522 .addReg(Tmp2Reg, RegState::Kill) 523 .addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_LO); 524 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::LU52I_D), Tmp4Reg) 525 .addReg(Tmp3Reg) 526 .addDisp(Symbol, 0, LoongArchII::MO_DESC64_PC_HI); 527 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::ADD_D), LoongArch::R4) 528 .addReg(Tmp1Reg) 529 .addReg(Tmp4Reg); 530 } else { 531 // Code Sequence: 532 // pcalau12i $a0, %desc_pc_hi20(sym) 533 // addi.w/d $a0, $a0, %desc_pc_lo12(sym) 534 // ld.w/d $ra, $a0, %desc_ld(sym) 535 // jirl $ra, $ra, %desc_call(sym) 536 // add.w/d $dst, $a0, $tp 537 BuildMI(MBB, MBBI, DL, TII->get(ADDI), LoongArch::R4) 538 .addReg(Tmp1Reg) 539 .addDisp( 540 Symbol, 0, 541 LoongArchII::encodeFlags(LoongArchII::MO_DESC_PC_LO, EnableRelax)); 542 } 543 544 BuildMI(MBB, MBBI, DL, TII->get(LD), LoongArch::R1) 545 .addReg(LoongArch::R4) 546 .addDisp(Symbol, 0, 547 LoongArchII::encodeFlags(LoongArchII::MO_DESC_LD, 548 EnableRelax && !Large)); 549 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PseudoDESC_CALL), LoongArch::R1) 550 .addReg(LoongArch::R1) 551 .addDisp(Symbol, 0, 552 LoongArchII::encodeFlags(LoongArchII::MO_DESC_CALL, 553 EnableRelax && !Large)); 554 BuildMI(MBB, MBBI, DL, TII->get(ADD), DestReg) 555 .addReg(LoongArch::R4) 556 .addReg(LoongArch::R2); 557 558 MI.eraseFromParent(); 559 return true; 560 } 561 562 bool LoongArchPreRAExpandPseudo::expandFunctionCALL( 563 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 564 MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) { 565 MachineFunction *MF = MBB.getParent(); 566 MachineInstr &MI = *MBBI; 567 DebugLoc DL = MI.getDebugLoc(); 568 const MachineOperand &Func = MI.getOperand(0); 569 MachineInstrBuilder CALL; 570 unsigned Opcode; 571 572 switch (MF->getTarget().getCodeModel()) { 573 default: 574 report_fatal_error("Unexpected code model"); 575 break; 576 case CodeModel::Small: { 577 // CALL: 578 // bl func 579 // TAIL: 580 // b func 581 Opcode = IsTailCall ? LoongArch::PseudoB_TAIL : LoongArch::BL; 582 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).add(Func); 583 break; 584 } 585 case CodeModel::Large: { 586 // Emit the 5-insn large address load sequence, either directly or 587 // indirectly in case of going through the GOT, then JIRL_TAIL or 588 // JIRL_CALL to $addr. 589 Opcode = 590 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL; 591 Register AddrReg = 592 IsTailCall 593 ? MF->getRegInfo().createVirtualRegister(&LoongArch::GPRRegClass) 594 : LoongArch::R1; 595 596 bool UseGOT = Func.getTargetFlags() == LoongArchII::MO_CALL_PLT; 597 unsigned MO = UseGOT ? LoongArchII::MO_GOT_PC_HI : LoongArchII::MO_PCREL_LO; 598 unsigned LAOpcode = UseGOT ? LoongArch::LDX_D : LoongArch::ADD_D; 599 expandLargeAddressLoad(MBB, MBBI, NextMBBI, LAOpcode, MO, Func, AddrReg, 600 false); 601 CALL = BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(AddrReg).addImm(0); 602 break; 603 } 604 } 605 606 // Transfer implicit operands. 607 CALL.copyImplicitOps(MI); 608 609 // Transfer MI flags. 610 CALL.setMIFlags(MI.getFlags()); 611 612 MI.eraseFromParent(); 613 return true; 614 } 615 616 void LoongArchPreRAExpandPseudo::annotateTableJump( 617 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI) { 618 MachineFunction *MF = MBB.getParent(); 619 MachineRegisterInfo &MRI = MBB.getParent()->getRegInfo(); 620 621 bool IsFound = false; 622 623 std::function<void(MachineInstr *, int)> FindJTIMI = [&](MachineInstr *MInst, 624 int FindDepth) { 625 if (FindDepth < 0) 626 return; 627 for (auto &MO : MInst->all_uses()) { 628 if (IsFound) 629 return; 630 Register Reg = MO.getReg(); 631 if (!Reg.isVirtual()) 632 continue; 633 MachineInstr *DefMI = MRI.getVRegDef(Reg); 634 if (!DefMI) 635 continue; 636 for (unsigned Idx = 0; Idx < DefMI->getNumOperands(); ++Idx) { 637 MachineOperand &MO = DefMI->getOperand(Idx); 638 if (MO.isJTI()) { 639 MBBI->setPreInstrSymbol( 640 *MF, MF->getContext().createNamedTempSymbol("jrtb_")); 641 MF->getInfo<LoongArchMachineFunctionInfo>()->setJumpInfo(&*MBBI, &MO); 642 IsFound = true; 643 return; 644 } 645 } 646 FindJTIMI(DefMI, --FindDepth); 647 } 648 }; 649 650 // FindDepth = 3, probably sufficient. 651 FindJTIMI(&*MBBI, /*FindDepth=*/3); 652 } 653 654 class LoongArchExpandPseudo : public MachineFunctionPass { 655 public: 656 const LoongArchInstrInfo *TII; 657 static char ID; 658 659 LoongArchExpandPseudo() : MachineFunctionPass(ID) { 660 initializeLoongArchExpandPseudoPass(*PassRegistry::getPassRegistry()); 661 } 662 663 bool runOnMachineFunction(MachineFunction &MF) override; 664 665 StringRef getPassName() const override { 666 return LOONGARCH_EXPAND_PSEUDO_NAME; 667 } 668 669 private: 670 bool expandMBB(MachineBasicBlock &MBB); 671 bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 672 MachineBasicBlock::iterator &NextMBBI); 673 bool expandCopyCFR(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 674 MachineBasicBlock::iterator &NextMBBI); 675 bool expandFunctionCALL(MachineBasicBlock &MBB, 676 MachineBasicBlock::iterator MBBI, 677 MachineBasicBlock::iterator &NextMBBI, 678 bool IsTailCall); 679 }; 680 681 char LoongArchExpandPseudo::ID = 0; 682 683 bool LoongArchExpandPseudo::runOnMachineFunction(MachineFunction &MF) { 684 TII = 685 static_cast<const LoongArchInstrInfo *>(MF.getSubtarget().getInstrInfo()); 686 687 bool Modified = false; 688 for (auto &MBB : MF) 689 Modified |= expandMBB(MBB); 690 691 return Modified; 692 } 693 694 bool LoongArchExpandPseudo::expandMBB(MachineBasicBlock &MBB) { 695 bool Modified = false; 696 697 MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); 698 while (MBBI != E) { 699 MachineBasicBlock::iterator NMBBI = std::next(MBBI); 700 Modified |= expandMI(MBB, MBBI, NMBBI); 701 MBBI = NMBBI; 702 } 703 704 return Modified; 705 } 706 707 bool LoongArchExpandPseudo::expandMI(MachineBasicBlock &MBB, 708 MachineBasicBlock::iterator MBBI, 709 MachineBasicBlock::iterator &NextMBBI) { 710 switch (MBBI->getOpcode()) { 711 case LoongArch::PseudoCopyCFR: 712 return expandCopyCFR(MBB, MBBI, NextMBBI); 713 case LoongArch::PseudoCALL_MEDIUM: 714 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/false); 715 case LoongArch::PseudoTAIL_MEDIUM: 716 return expandFunctionCALL(MBB, MBBI, NextMBBI, /*IsTailCall=*/true); 717 } 718 719 return false; 720 } 721 722 bool LoongArchExpandPseudo::expandCopyCFR( 723 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 724 MachineBasicBlock::iterator &NextMBBI) { 725 MachineFunction *MF = MBB.getParent(); 726 MachineInstr &MI = *MBBI; 727 DebugLoc DL = MI.getDebugLoc(); 728 729 // Expand: 730 // MBB: 731 // fcmp.caf.s $dst, $fa0, $fa0 # set $dst 0(false) 732 // bceqz $src, SinkBB 733 // FalseBB: 734 // fcmp.cueq.s $dst, $fa0, $fa0 # set $dst 1(true) 735 // SinkBB: 736 // fallthrough 737 738 const BasicBlock *LLVM_BB = MBB.getBasicBlock(); 739 auto *FalseBB = MF->CreateMachineBasicBlock(LLVM_BB); 740 auto *SinkBB = MF->CreateMachineBasicBlock(LLVM_BB); 741 742 MF->insert(++MBB.getIterator(), FalseBB); 743 MF->insert(++FalseBB->getIterator(), SinkBB); 744 745 Register DestReg = MI.getOperand(0).getReg(); 746 Register SrcReg = MI.getOperand(1).getReg(); 747 // DestReg = 0 748 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::SET_CFR_FALSE), DestReg); 749 // Insert branch instruction. 750 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::BCEQZ)) 751 .addReg(SrcReg) 752 .addMBB(SinkBB); 753 // DestReg = 1 754 BuildMI(FalseBB, DL, TII->get(LoongArch::SET_CFR_TRUE), DestReg); 755 756 FalseBB->addSuccessor(SinkBB); 757 758 SinkBB->splice(SinkBB->end(), &MBB, MI, MBB.end()); 759 SinkBB->transferSuccessors(&MBB); 760 761 MBB.addSuccessor(FalseBB); 762 MBB.addSuccessor(SinkBB); 763 764 NextMBBI = MBB.end(); 765 MI.eraseFromParent(); 766 767 // Make sure live-ins are correctly attached to this new basic block. 768 LivePhysRegs LiveRegs; 769 computeAndAddLiveIns(LiveRegs, *FalseBB); 770 computeAndAddLiveIns(LiveRegs, *SinkBB); 771 772 return true; 773 } 774 775 bool LoongArchExpandPseudo::expandFunctionCALL( 776 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, 777 MachineBasicBlock::iterator &NextMBBI, bool IsTailCall) { 778 MachineFunction *MF = MBB.getParent(); 779 MachineInstr &MI = *MBBI; 780 DebugLoc DL = MI.getDebugLoc(); 781 const MachineOperand &Func = MI.getOperand(0); 782 MachineInstrBuilder CALL; 783 unsigned Opcode; 784 785 switch (MF->getTarget().getCodeModel()) { 786 default: 787 report_fatal_error("Unexpected code model"); 788 break; 789 case CodeModel::Medium: { 790 // CALL: 791 // pcaddu18i $ra, %call36(func) 792 // jirl $ra, $ra, 0 793 // TAIL: 794 // pcaddu18i $t8, %call36(func) 795 // jirl $r0, $t8, 0 796 Opcode = 797 IsTailCall ? LoongArch::PseudoJIRL_TAIL : LoongArch::PseudoJIRL_CALL; 798 Register ScratchReg = IsTailCall ? LoongArch::R20 : LoongArch::R1; 799 MachineInstrBuilder MIB = 800 BuildMI(MBB, MBBI, DL, TII->get(LoongArch::PCADDU18I), ScratchReg); 801 802 CALL = 803 BuildMI(MBB, MBBI, DL, TII->get(Opcode)).addReg(ScratchReg).addImm(0); 804 805 if (Func.isSymbol()) 806 MIB.addExternalSymbol(Func.getSymbolName(), LoongArchII::MO_CALL36); 807 else 808 MIB.addDisp(Func, 0, LoongArchII::MO_CALL36); 809 break; 810 } 811 } 812 813 // Transfer implicit operands. 814 CALL.copyImplicitOps(MI); 815 816 // Transfer MI flags. 817 CALL.setMIFlags(MI.getFlags()); 818 819 MI.eraseFromParent(); 820 return true; 821 } 822 823 } // end namespace 824 825 INITIALIZE_PASS(LoongArchPreRAExpandPseudo, "loongarch-prera-expand-pseudo", 826 LOONGARCH_PRERA_EXPAND_PSEUDO_NAME, false, false) 827 828 INITIALIZE_PASS(LoongArchExpandPseudo, "loongarch-expand-pseudo", 829 LOONGARCH_EXPAND_PSEUDO_NAME, false, false) 830 831 namespace llvm { 832 833 FunctionPass *createLoongArchPreRAExpandPseudoPass() { 834 return new LoongArchPreRAExpandPseudo(); 835 } 836 FunctionPass *createLoongArchExpandPseudoPass() { 837 return new LoongArchExpandPseudo(); 838 } 839 840 } // end namespace llvm 841