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