1 //=- LoongArchInstrInfo.cpp - LoongArch Instruction Information -*- C++ -*-===// 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 the LoongArch implementation of the TargetInstrInfo class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "LoongArchInstrInfo.h" 14 #include "LoongArch.h" 15 #include "LoongArchMachineFunctionInfo.h" 16 #include "LoongArchRegisterInfo.h" 17 #include "MCTargetDesc/LoongArchMCTargetDesc.h" 18 #include "MCTargetDesc/LoongArchMatInt.h" 19 #include "llvm/CodeGen/RegisterScavenging.h" 20 #include "llvm/CodeGen/StackMaps.h" 21 #include "llvm/MC/MCInstBuilder.h" 22 23 using namespace llvm; 24 25 #define GET_INSTRINFO_CTOR_DTOR 26 #include "LoongArchGenInstrInfo.inc" 27 28 LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI) 29 : LoongArchGenInstrInfo(LoongArch::ADJCALLSTACKDOWN, 30 LoongArch::ADJCALLSTACKUP), 31 STI(STI) {} 32 33 MCInst LoongArchInstrInfo::getNop() const { 34 return MCInstBuilder(LoongArch::ANDI) 35 .addReg(LoongArch::R0) 36 .addReg(LoongArch::R0) 37 .addImm(0); 38 } 39 40 void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB, 41 MachineBasicBlock::iterator MBBI, 42 const DebugLoc &DL, Register DstReg, 43 Register SrcReg, bool KillSrc, 44 bool RenamableDest, 45 bool RenamableSrc) const { 46 if (LoongArch::GPRRegClass.contains(DstReg, SrcReg)) { 47 BuildMI(MBB, MBBI, DL, get(LoongArch::OR), DstReg) 48 .addReg(SrcReg, getKillRegState(KillSrc)) 49 .addReg(LoongArch::R0); 50 return; 51 } 52 53 // VR->VR copies. 54 if (LoongArch::LSX128RegClass.contains(DstReg, SrcReg)) { 55 BuildMI(MBB, MBBI, DL, get(LoongArch::VORI_B), DstReg) 56 .addReg(SrcReg, getKillRegState(KillSrc)) 57 .addImm(0); 58 return; 59 } 60 61 // XR->XR copies. 62 if (LoongArch::LASX256RegClass.contains(DstReg, SrcReg)) { 63 BuildMI(MBB, MBBI, DL, get(LoongArch::XVORI_B), DstReg) 64 .addReg(SrcReg, getKillRegState(KillSrc)) 65 .addImm(0); 66 return; 67 } 68 69 // GPR->CFR copy. 70 if (LoongArch::CFRRegClass.contains(DstReg) && 71 LoongArch::GPRRegClass.contains(SrcReg)) { 72 BuildMI(MBB, MBBI, DL, get(LoongArch::MOVGR2CF), DstReg) 73 .addReg(SrcReg, getKillRegState(KillSrc)); 74 return; 75 } 76 // CFR->GPR copy. 77 if (LoongArch::GPRRegClass.contains(DstReg) && 78 LoongArch::CFRRegClass.contains(SrcReg)) { 79 BuildMI(MBB, MBBI, DL, get(LoongArch::MOVCF2GR), DstReg) 80 .addReg(SrcReg, getKillRegState(KillSrc)); 81 return; 82 } 83 // CFR->CFR copy. 84 if (LoongArch::CFRRegClass.contains(DstReg, SrcReg)) { 85 BuildMI(MBB, MBBI, DL, get(LoongArch::PseudoCopyCFR), DstReg) 86 .addReg(SrcReg, getKillRegState(KillSrc)); 87 return; 88 } 89 90 // FPR->FPR copies. 91 unsigned Opc; 92 if (LoongArch::FPR32RegClass.contains(DstReg, SrcReg)) { 93 Opc = LoongArch::FMOV_S; 94 } else if (LoongArch::FPR64RegClass.contains(DstReg, SrcReg)) { 95 Opc = LoongArch::FMOV_D; 96 } else if (LoongArch::GPRRegClass.contains(DstReg) && 97 LoongArch::FPR32RegClass.contains(SrcReg)) { 98 // FPR32 -> GPR copies 99 Opc = LoongArch::MOVFR2GR_S; 100 } else if (LoongArch::GPRRegClass.contains(DstReg) && 101 LoongArch::FPR64RegClass.contains(SrcReg)) { 102 // FPR64 -> GPR copies 103 Opc = LoongArch::MOVFR2GR_D; 104 } else { 105 // TODO: support other copies. 106 llvm_unreachable("Impossible reg-to-reg copy"); 107 } 108 109 BuildMI(MBB, MBBI, DL, get(Opc), DstReg) 110 .addReg(SrcReg, getKillRegState(KillSrc)); 111 } 112 113 void LoongArchInstrInfo::storeRegToStackSlot( 114 MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register SrcReg, 115 bool IsKill, int FI, const TargetRegisterClass *RC, 116 const TargetRegisterInfo *TRI, Register VReg, 117 MachineInstr::MIFlag Flags) const { 118 MachineFunction *MF = MBB.getParent(); 119 MachineFrameInfo &MFI = MF->getFrameInfo(); 120 121 unsigned Opcode; 122 if (LoongArch::GPRRegClass.hasSubClassEq(RC)) 123 Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32 124 ? LoongArch::ST_W 125 : LoongArch::ST_D; 126 else if (LoongArch::FPR32RegClass.hasSubClassEq(RC)) 127 Opcode = LoongArch::FST_S; 128 else if (LoongArch::FPR64RegClass.hasSubClassEq(RC)) 129 Opcode = LoongArch::FST_D; 130 else if (LoongArch::LSX128RegClass.hasSubClassEq(RC)) 131 Opcode = LoongArch::VST; 132 else if (LoongArch::LASX256RegClass.hasSubClassEq(RC)) 133 Opcode = LoongArch::XVST; 134 else if (LoongArch::CFRRegClass.hasSubClassEq(RC)) 135 Opcode = LoongArch::PseudoST_CFR; 136 else 137 llvm_unreachable("Can't store this register to stack slot"); 138 139 MachineMemOperand *MMO = MF->getMachineMemOperand( 140 MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore, 141 MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); 142 143 BuildMI(MBB, I, DebugLoc(), get(Opcode)) 144 .addReg(SrcReg, getKillRegState(IsKill)) 145 .addFrameIndex(FI) 146 .addImm(0) 147 .addMemOperand(MMO); 148 } 149 150 void LoongArchInstrInfo::loadRegFromStackSlot( 151 MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register DstReg, 152 int FI, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, 153 Register VReg, MachineInstr::MIFlag Flags) const { 154 MachineFunction *MF = MBB.getParent(); 155 MachineFrameInfo &MFI = MF->getFrameInfo(); 156 DebugLoc DL; 157 if (I != MBB.end()) 158 DL = I->getDebugLoc(); 159 160 unsigned Opcode; 161 if (LoongArch::GPRRegClass.hasSubClassEq(RC)) 162 Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32 163 ? LoongArch::LD_W 164 : LoongArch::LD_D; 165 else if (LoongArch::FPR32RegClass.hasSubClassEq(RC)) 166 Opcode = LoongArch::FLD_S; 167 else if (LoongArch::FPR64RegClass.hasSubClassEq(RC)) 168 Opcode = LoongArch::FLD_D; 169 else if (LoongArch::LSX128RegClass.hasSubClassEq(RC)) 170 Opcode = LoongArch::VLD; 171 else if (LoongArch::LASX256RegClass.hasSubClassEq(RC)) 172 Opcode = LoongArch::XVLD; 173 else if (LoongArch::CFRRegClass.hasSubClassEq(RC)) 174 Opcode = LoongArch::PseudoLD_CFR; 175 else 176 llvm_unreachable("Can't load this register from stack slot"); 177 178 MachineMemOperand *MMO = MF->getMachineMemOperand( 179 MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad, 180 MFI.getObjectSize(FI), MFI.getObjectAlign(FI)); 181 182 BuildMI(MBB, I, DL, get(Opcode), DstReg) 183 .addFrameIndex(FI) 184 .addImm(0) 185 .addMemOperand(MMO); 186 } 187 188 void LoongArchInstrInfo::movImm(MachineBasicBlock &MBB, 189 MachineBasicBlock::iterator MBBI, 190 const DebugLoc &DL, Register DstReg, 191 uint64_t Val, MachineInstr::MIFlag Flag) const { 192 Register SrcReg = LoongArch::R0; 193 194 if (!STI.is64Bit() && !isInt<32>(Val)) 195 report_fatal_error("Should only materialize 32-bit constants for LA32"); 196 197 auto Seq = LoongArchMatInt::generateInstSeq(Val); 198 assert(!Seq.empty()); 199 200 for (auto &Inst : Seq) { 201 switch (Inst.Opc) { 202 case LoongArch::LU12I_W: 203 BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg) 204 .addImm(Inst.Imm) 205 .setMIFlag(Flag); 206 break; 207 case LoongArch::ADDI_W: 208 case LoongArch::ORI: 209 case LoongArch::LU32I_D: // "rj" is needed due to InstrInfo pattern 210 case LoongArch::LU52I_D: 211 BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg) 212 .addReg(SrcReg, RegState::Kill) 213 .addImm(Inst.Imm) 214 .setMIFlag(Flag); 215 break; 216 case LoongArch::BSTRINS_D: 217 BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg) 218 .addReg(SrcReg, RegState::Kill) 219 .addReg(SrcReg, RegState::Kill) 220 .addImm(Inst.Imm >> 32) 221 .addImm(Inst.Imm & 0xFF) 222 .setMIFlag(Flag); 223 break; 224 default: 225 assert(false && "Unknown insn emitted by LoongArchMatInt"); 226 } 227 228 // Only the first instruction has $zero as its source. 229 SrcReg = DstReg; 230 } 231 } 232 233 unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const { 234 unsigned Opcode = MI.getOpcode(); 235 236 if (Opcode == TargetOpcode::INLINEASM || 237 Opcode == TargetOpcode::INLINEASM_BR) { 238 const MachineFunction *MF = MI.getParent()->getParent(); 239 const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo(); 240 return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI); 241 } 242 243 unsigned NumBytes = 0; 244 const MCInstrDesc &Desc = MI.getDesc(); 245 246 // Size should be preferably set in 247 // llvm/lib/Target/LoongArch/LoongArch*InstrInfo.td (default case). 248 // Specific cases handle instructions of variable sizes. 249 switch (Desc.getOpcode()) { 250 default: 251 return Desc.getSize(); 252 case TargetOpcode::STATEPOINT: 253 NumBytes = StatepointOpers(&MI).getNumPatchBytes(); 254 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!"); 255 // No patch bytes means a normal call inst (i.e. `bl`) is emitted. 256 if (NumBytes == 0) 257 NumBytes = 4; 258 break; 259 } 260 return NumBytes; 261 } 262 263 bool LoongArchInstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const { 264 const unsigned Opcode = MI.getOpcode(); 265 switch (Opcode) { 266 default: 267 break; 268 case LoongArch::ADDI_D: 269 case LoongArch::ORI: 270 case LoongArch::XORI: 271 return (MI.getOperand(1).isReg() && 272 MI.getOperand(1).getReg() == LoongArch::R0) || 273 (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0); 274 } 275 return MI.isAsCheapAsAMove(); 276 } 277 278 MachineBasicBlock * 279 LoongArchInstrInfo::getBranchDestBlock(const MachineInstr &MI) const { 280 assert(MI.getDesc().isBranch() && "Unexpected opcode!"); 281 // The branch target is always the last operand. 282 return MI.getOperand(MI.getNumExplicitOperands() - 1).getMBB(); 283 } 284 285 static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target, 286 SmallVectorImpl<MachineOperand> &Cond) { 287 // Block ends with fall-through condbranch. 288 assert(LastInst.getDesc().isConditionalBranch() && 289 "Unknown conditional branch"); 290 int NumOp = LastInst.getNumExplicitOperands(); 291 Target = LastInst.getOperand(NumOp - 1).getMBB(); 292 293 Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode())); 294 for (int i = 0; i < NumOp - 1; i++) 295 Cond.push_back(LastInst.getOperand(i)); 296 } 297 298 bool LoongArchInstrInfo::analyzeBranch(MachineBasicBlock &MBB, 299 MachineBasicBlock *&TBB, 300 MachineBasicBlock *&FBB, 301 SmallVectorImpl<MachineOperand> &Cond, 302 bool AllowModify) const { 303 TBB = FBB = nullptr; 304 Cond.clear(); 305 306 // If the block has no terminators, it just falls into the block after it. 307 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); 308 if (I == MBB.end() || !isUnpredicatedTerminator(*I)) 309 return false; 310 311 // Count the number of terminators and find the first unconditional or 312 // indirect branch. 313 MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end(); 314 int NumTerminators = 0; 315 for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J); 316 J++) { 317 NumTerminators++; 318 if (J->getDesc().isUnconditionalBranch() || 319 J->getDesc().isIndirectBranch()) { 320 FirstUncondOrIndirectBr = J.getReverse(); 321 } 322 } 323 324 // If AllowModify is true, we can erase any terminators after 325 // FirstUncondOrIndirectBR. 326 if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) { 327 while (std::next(FirstUncondOrIndirectBr) != MBB.end()) { 328 std::next(FirstUncondOrIndirectBr)->eraseFromParent(); 329 NumTerminators--; 330 } 331 I = FirstUncondOrIndirectBr; 332 } 333 334 // Handle a single unconditional branch. 335 if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) { 336 TBB = getBranchDestBlock(*I); 337 return false; 338 } 339 340 // Handle a single conditional branch. 341 if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) { 342 parseCondBranch(*I, TBB, Cond); 343 return false; 344 } 345 346 // Handle a conditional branch followed by an unconditional branch. 347 if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() && 348 I->getDesc().isUnconditionalBranch()) { 349 parseCondBranch(*std::prev(I), TBB, Cond); 350 FBB = getBranchDestBlock(*I); 351 return false; 352 } 353 354 // Otherwise, we can't handle this. 355 return true; 356 } 357 358 bool LoongArchInstrInfo::isBranchOffsetInRange(unsigned BranchOp, 359 int64_t BrOffset) const { 360 switch (BranchOp) { 361 default: 362 llvm_unreachable("Unknown branch instruction!"); 363 case LoongArch::BEQ: 364 case LoongArch::BNE: 365 case LoongArch::BLT: 366 case LoongArch::BGE: 367 case LoongArch::BLTU: 368 case LoongArch::BGEU: 369 return isInt<18>(BrOffset); 370 case LoongArch::BEQZ: 371 case LoongArch::BNEZ: 372 case LoongArch::BCEQZ: 373 case LoongArch::BCNEZ: 374 return isInt<23>(BrOffset); 375 case LoongArch::B: 376 case LoongArch::PseudoBR: 377 return isInt<28>(BrOffset); 378 } 379 } 380 381 bool LoongArchInstrInfo::isSafeToMove(const MachineInstr &MI, 382 const MachineBasicBlock *MBB, 383 const MachineFunction &MF) const { 384 auto MII = MI.getIterator(); 385 auto MIE = MBB->end(); 386 387 // According to psABI v2.30: 388 // 389 // https://github.com/loongson/la-abi-specs/releases/tag/v2.30 390 // 391 // The following instruction patterns are prohibited from being reordered: 392 // 393 // * pcalau12i $a0, %pc_hi20(s) 394 // addi.d $a1, $zero, %pc_lo12(s) 395 // lu32i.d $a1, %pc64_lo20(s) 396 // lu52i.d $a1, $a1, %pc64_hi12(s) 397 // 398 // * pcalau12i $a0, %got_pc_hi20(s) | %ld_pc_hi20(s) | %gd_pc_hi20(s) 399 // addi.d $a1, $zero, %got_pc_lo12(s) 400 // lu32i.d $a1, %got64_pc_lo20(s) 401 // lu52i.d $a1, $a1, %got64_pc_hi12(s) 402 // 403 // * pcalau12i $a0, %ie_pc_hi20(s) 404 // addi.d $a1, $zero, %ie_pc_lo12(s) 405 // lu32i.d $a1, %ie64_pc_lo20(s) 406 // lu52i.d $a1, $a1, %ie64_pc_hi12(s) 407 // 408 // * pcalau12i $a0, %desc_pc_hi20(s) 409 // addi.d $a1, $zero, %desc_pc_lo12(s) 410 // lu32i.d $a1, %desc64_pc_lo20(s) 411 // lu52i.d $a1, $a1, %desc64_pc_hi12(s) 412 // 413 // For simplicity, only pcalau12i and lu52i.d are marked as scheduling 414 // boundaries, and the instructions between them are guaranteed to be 415 // ordered according to data dependencies. 416 switch (MI.getOpcode()) { 417 case LoongArch::PCALAU12I: { 418 auto AddI = std::next(MII); 419 if (AddI == MIE || AddI->getOpcode() != LoongArch::ADDI_D) 420 break; 421 auto Lu32I = std::next(AddI); 422 if (Lu32I == MIE || Lu32I->getOpcode() != LoongArch::LU32I_D) 423 break; 424 auto MO0 = MI.getOperand(1).getTargetFlags(); 425 auto MO1 = AddI->getOperand(2).getTargetFlags(); 426 auto MO2 = Lu32I->getOperand(2).getTargetFlags(); 427 if (MO0 == LoongArchII::MO_PCREL_HI && MO1 == LoongArchII::MO_PCREL_LO && 428 MO2 == LoongArchII::MO_PCREL64_LO) 429 return false; 430 if ((MO0 == LoongArchII::MO_GOT_PC_HI || MO0 == LoongArchII::MO_LD_PC_HI || 431 MO0 == LoongArchII::MO_GD_PC_HI) && 432 MO1 == LoongArchII::MO_GOT_PC_LO && MO2 == LoongArchII::MO_GOT_PC64_LO) 433 return false; 434 if (MO0 == LoongArchII::MO_IE_PC_HI && MO1 == LoongArchII::MO_IE_PC_LO && 435 MO2 == LoongArchII::MO_IE_PC64_LO) 436 return false; 437 if (MO0 == LoongArchII::MO_DESC_PC_HI && 438 MO1 == LoongArchII::MO_DESC_PC_LO && 439 MO2 == LoongArchII::MO_DESC64_PC_LO) 440 return false; 441 break; 442 } 443 case LoongArch::LU52I_D: { 444 auto MO = MI.getOperand(2).getTargetFlags(); 445 if (MO == LoongArchII::MO_PCREL64_HI || MO == LoongArchII::MO_GOT_PC64_HI || 446 MO == LoongArchII::MO_IE_PC64_HI || MO == LoongArchII::MO_DESC64_PC_HI) 447 return false; 448 break; 449 } 450 default: 451 break; 452 } 453 454 const auto &STI = MF.getSubtarget<LoongArchSubtarget>(); 455 if (STI.hasFeature(LoongArch::FeatureRelax)) { 456 // When linker relaxation enabled, the following instruction patterns are 457 // prohibited from being reordered: 458 // 459 // * pcalau12i $a0, %pc_hi20(s) 460 // addi.w/d $a0, $a0, %pc_lo12(s) 461 // 462 // * pcalau12i $a0, %got_pc_hi20(s) 463 // ld.w/d $a0, $a0, %got_pc_lo12(s) 464 // 465 // * pcalau12i $a0, %ld_pc_hi20(s) | %gd_pc_hi20(s) 466 // addi.w/d $a0, $a0, %got_pc_lo12(s) 467 // 468 // * pcalau12i $a0, %desc_pc_hi20(s) 469 // addi.w/d $a0, $a0, %desc_pc_lo12(s) 470 // ld.w/d $ra, $a0, %desc_ld(s) 471 // jirl $ra, $ra, %desc_call(s) 472 unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 473 unsigned LdOp = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 474 switch (MI.getOpcode()) { 475 case LoongArch::PCALAU12I: { 476 auto MO0 = LoongArchII::getDirectFlags(MI.getOperand(1)); 477 auto SecondOp = std::next(MII); 478 if (MO0 == LoongArchII::MO_DESC_PC_HI) { 479 if (SecondOp == MIE || SecondOp->getOpcode() != AddiOp) 480 break; 481 auto Ld = std::next(SecondOp); 482 if (Ld == MIE || Ld->getOpcode() != LdOp) 483 break; 484 auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2)); 485 auto MO2 = LoongArchII::getDirectFlags(Ld->getOperand(2)); 486 if (MO1 == LoongArchII::MO_DESC_PC_LO && MO2 == LoongArchII::MO_DESC_LD) 487 return false; 488 break; 489 } 490 if (SecondOp == MIE || 491 (SecondOp->getOpcode() != AddiOp && SecondOp->getOpcode() != LdOp)) 492 break; 493 auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2)); 494 if (MO0 == LoongArchII::MO_PCREL_HI && SecondOp->getOpcode() == AddiOp && 495 MO1 == LoongArchII::MO_PCREL_LO) 496 return false; 497 if (MO0 == LoongArchII::MO_GOT_PC_HI && SecondOp->getOpcode() == LdOp && 498 MO1 == LoongArchII::MO_GOT_PC_LO) 499 return false; 500 if ((MO0 == LoongArchII::MO_LD_PC_HI || 501 MO0 == LoongArchII::MO_GD_PC_HI) && 502 SecondOp->getOpcode() == AddiOp && MO1 == LoongArchII::MO_GOT_PC_LO) 503 return false; 504 break; 505 } 506 case LoongArch::ADDI_W: 507 case LoongArch::ADDI_D: { 508 auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); 509 if (MO == LoongArchII::MO_PCREL_LO || MO == LoongArchII::MO_GOT_PC_LO) 510 return false; 511 break; 512 } 513 case LoongArch::LD_W: 514 case LoongArch::LD_D: { 515 auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); 516 if (MO == LoongArchII::MO_GOT_PC_LO) 517 return false; 518 break; 519 } 520 case LoongArch::PseudoDESC_CALL: { 521 auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); 522 if (MO == LoongArchII::MO_DESC_CALL) 523 return false; 524 break; 525 } 526 default: 527 break; 528 } 529 } 530 531 return true; 532 } 533 534 bool LoongArchInstrInfo::isSchedulingBoundary(const MachineInstr &MI, 535 const MachineBasicBlock *MBB, 536 const MachineFunction &MF) const { 537 if (TargetInstrInfo::isSchedulingBoundary(MI, MBB, MF)) 538 return true; 539 540 if (!isSafeToMove(MI, MBB, MF)) 541 return true; 542 543 return false; 544 } 545 546 unsigned LoongArchInstrInfo::removeBranch(MachineBasicBlock &MBB, 547 int *BytesRemoved) const { 548 if (BytesRemoved) 549 *BytesRemoved = 0; 550 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); 551 if (I == MBB.end()) 552 return 0; 553 554 if (!I->getDesc().isBranch()) 555 return 0; 556 557 // Remove the branch. 558 if (BytesRemoved) 559 *BytesRemoved += getInstSizeInBytes(*I); 560 I->eraseFromParent(); 561 562 I = MBB.end(); 563 564 if (I == MBB.begin()) 565 return 1; 566 --I; 567 if (!I->getDesc().isConditionalBranch()) 568 return 1; 569 570 // Remove the branch. 571 if (BytesRemoved) 572 *BytesRemoved += getInstSizeInBytes(*I); 573 I->eraseFromParent(); 574 return 2; 575 } 576 577 // Inserts a branch into the end of the specific MachineBasicBlock, returning 578 // the number of instructions inserted. 579 unsigned LoongArchInstrInfo::insertBranch( 580 MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, 581 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const { 582 if (BytesAdded) 583 *BytesAdded = 0; 584 585 // Shouldn't be a fall through. 586 assert(TBB && "insertBranch must not be told to insert a fallthrough"); 587 assert(Cond.size() <= 3 && Cond.size() != 1 && 588 "LoongArch branch conditions have at most two components!"); 589 590 // Unconditional branch. 591 if (Cond.empty()) { 592 MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(TBB); 593 if (BytesAdded) 594 *BytesAdded += getInstSizeInBytes(MI); 595 return 1; 596 } 597 598 // Either a one or two-way conditional branch. 599 MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm())); 600 for (unsigned i = 1; i < Cond.size(); ++i) 601 MIB.add(Cond[i]); 602 MIB.addMBB(TBB); 603 if (BytesAdded) 604 *BytesAdded += getInstSizeInBytes(*MIB); 605 606 // One-way conditional branch. 607 if (!FBB) 608 return 1; 609 610 // Two-way conditional branch. 611 MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(FBB); 612 if (BytesAdded) 613 *BytesAdded += getInstSizeInBytes(MI); 614 return 2; 615 } 616 617 void LoongArchInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB, 618 MachineBasicBlock &DestBB, 619 MachineBasicBlock &RestoreBB, 620 const DebugLoc &DL, 621 int64_t BrOffset, 622 RegScavenger *RS) const { 623 assert(RS && "RegScavenger required for long branching"); 624 assert(MBB.empty() && 625 "new block should be inserted for expanding unconditional branch"); 626 assert(MBB.pred_size() == 1); 627 628 MachineFunction *MF = MBB.getParent(); 629 MachineRegisterInfo &MRI = MF->getRegInfo(); 630 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 631 LoongArchMachineFunctionInfo *LAFI = 632 MF->getInfo<LoongArchMachineFunctionInfo>(); 633 634 if (!isInt<32>(BrOffset)) 635 report_fatal_error( 636 "Branch offsets outside of the signed 32-bit range not supported"); 637 638 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass); 639 auto II = MBB.end(); 640 641 MachineInstr &PCALAU12I = 642 *BuildMI(MBB, II, DL, get(LoongArch::PCALAU12I), ScratchReg) 643 .addMBB(&DestBB, LoongArchII::MO_PCREL_HI); 644 MachineInstr &ADDI = 645 *BuildMI(MBB, II, DL, 646 get(STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W), 647 ScratchReg) 648 .addReg(ScratchReg) 649 .addMBB(&DestBB, LoongArchII::MO_PCREL_LO); 650 BuildMI(MBB, II, DL, get(LoongArch::PseudoBRIND)) 651 .addReg(ScratchReg, RegState::Kill) 652 .addImm(0); 653 654 RS->enterBasicBlockEnd(MBB); 655 Register Scav = RS->scavengeRegisterBackwards( 656 LoongArch::GPRRegClass, PCALAU12I.getIterator(), /*RestoreAfter=*/false, 657 /*SPAdj=*/0, /*AllowSpill=*/false); 658 if (Scav != LoongArch::NoRegister) 659 RS->setRegUsed(Scav); 660 else { 661 // When there is no scavenged register, it needs to specify a register. 662 // Specify t8 register because it won't be used too often. 663 Scav = LoongArch::R20; 664 int FrameIndex = LAFI->getBranchRelaxationSpillFrameIndex(); 665 if (FrameIndex == -1) 666 report_fatal_error("The function size is incorrectly estimated."); 667 storeRegToStackSlot(MBB, PCALAU12I, Scav, /*IsKill=*/true, FrameIndex, 668 &LoongArch::GPRRegClass, TRI, Register()); 669 TRI->eliminateFrameIndex(std::prev(PCALAU12I.getIterator()), 670 /*SpAdj=*/0, /*FIOperandNum=*/1); 671 PCALAU12I.getOperand(1).setMBB(&RestoreBB); 672 ADDI.getOperand(2).setMBB(&RestoreBB); 673 loadRegFromStackSlot(RestoreBB, RestoreBB.end(), Scav, FrameIndex, 674 &LoongArch::GPRRegClass, TRI, Register()); 675 TRI->eliminateFrameIndex(RestoreBB.back(), 676 /*SpAdj=*/0, /*FIOperandNum=*/1); 677 } 678 MRI.replaceRegWith(ScratchReg, Scav); 679 MRI.clearVirtRegs(); 680 } 681 682 static unsigned getOppositeBranchOpc(unsigned Opc) { 683 switch (Opc) { 684 default: 685 llvm_unreachable("Unrecognized conditional branch"); 686 case LoongArch::BEQ: 687 return LoongArch::BNE; 688 case LoongArch::BNE: 689 return LoongArch::BEQ; 690 case LoongArch::BEQZ: 691 return LoongArch::BNEZ; 692 case LoongArch::BNEZ: 693 return LoongArch::BEQZ; 694 case LoongArch::BCEQZ: 695 return LoongArch::BCNEZ; 696 case LoongArch::BCNEZ: 697 return LoongArch::BCEQZ; 698 case LoongArch::BLT: 699 return LoongArch::BGE; 700 case LoongArch::BGE: 701 return LoongArch::BLT; 702 case LoongArch::BLTU: 703 return LoongArch::BGEU; 704 case LoongArch::BGEU: 705 return LoongArch::BLTU; 706 } 707 } 708 709 bool LoongArchInstrInfo::reverseBranchCondition( 710 SmallVectorImpl<MachineOperand> &Cond) const { 711 assert((Cond.size() && Cond.size() <= 3) && "Invalid branch condition!"); 712 Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm())); 713 return false; 714 } 715 716 std::pair<unsigned, unsigned> 717 LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { 718 const unsigned Mask = LoongArchII::MO_DIRECT_FLAG_MASK; 719 return std::make_pair(TF & Mask, TF & ~Mask); 720 } 721 722 ArrayRef<std::pair<unsigned, const char *>> 723 LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { 724 using namespace LoongArchII; 725 // TODO: Add more target flags. 726 static const std::pair<unsigned, const char *> TargetFlags[] = { 727 {MO_CALL, "loongarch-call"}, 728 {MO_CALL_PLT, "loongarch-call-plt"}, 729 {MO_PCREL_HI, "loongarch-pcrel-hi"}, 730 {MO_PCREL_LO, "loongarch-pcrel-lo"}, 731 {MO_PCREL64_LO, "loongarch-pcrel64-lo"}, 732 {MO_PCREL64_HI, "loongarch-pcrel64-hi"}, 733 {MO_GOT_PC_HI, "loongarch-got-pc-hi"}, 734 {MO_GOT_PC_LO, "loongarch-got-pc-lo"}, 735 {MO_GOT_PC64_LO, "loongarch-got-pc64-lo"}, 736 {MO_GOT_PC64_HI, "loongarch-got-pc64-hi"}, 737 {MO_LE_HI, "loongarch-le-hi"}, 738 {MO_LE_LO, "loongarch-le-lo"}, 739 {MO_LE64_LO, "loongarch-le64-lo"}, 740 {MO_LE64_HI, "loongarch-le64-hi"}, 741 {MO_IE_PC_HI, "loongarch-ie-pc-hi"}, 742 {MO_IE_PC_LO, "loongarch-ie-pc-lo"}, 743 {MO_IE_PC64_LO, "loongarch-ie-pc64-lo"}, 744 {MO_IE_PC64_HI, "loongarch-ie-pc64-hi"}, 745 {MO_LD_PC_HI, "loongarch-ld-pc-hi"}, 746 {MO_GD_PC_HI, "loongarch-gd-pc-hi"}, 747 {MO_CALL36, "loongarch-call36"}, 748 {MO_DESC_PC_HI, "loongarch-desc-pc-hi"}, 749 {MO_DESC_PC_LO, "loongarch-desc-pc-lo"}, 750 {MO_DESC64_PC_LO, "loongarch-desc64-pc-lo"}, 751 {MO_DESC64_PC_HI, "loongarch-desc64-pc-hi"}, 752 {MO_DESC_LD, "loongarch-desc-ld"}, 753 {MO_DESC_CALL, "loongarch-desc-call"}, 754 {MO_LE_HI_R, "loongarch-le-hi-r"}, 755 {MO_LE_ADD_R, "loongarch-le-add-r"}, 756 {MO_LE_LO_R, "loongarch-le-lo-r"}}; 757 return ArrayRef(TargetFlags); 758 } 759 760 ArrayRef<std::pair<unsigned, const char *>> 761 LoongArchInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const { 762 using namespace LoongArchII; 763 static const std::pair<unsigned, const char *> TargetFlags[] = { 764 {MO_RELAX, "loongarch-relax"}}; 765 return ArrayRef(TargetFlags); 766 } 767 768 // Returns true if this is the sext.w pattern, addi.w rd, rs, 0. 769 bool LoongArch::isSEXT_W(const MachineInstr &MI) { 770 return MI.getOpcode() == LoongArch::ADDI_W && MI.getOperand(1).isReg() && 771 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0; 772 } 773