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