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, MCRegister DstReg, 43 MCRegister 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::isSchedulingBoundary(const MachineInstr &MI, 382 const MachineBasicBlock *MBB, 383 const MachineFunction &MF) const { 384 if (TargetInstrInfo::isSchedulingBoundary(MI, MBB, MF)) 385 return true; 386 387 auto MII = MI.getIterator(); 388 auto MIE = MBB->end(); 389 390 // According to psABI v2.30: 391 // 392 // https://github.com/loongson/la-abi-specs/releases/tag/v2.30 393 // 394 // The following instruction patterns are prohibited from being reordered: 395 // 396 // * pcalau12i $a0, %pc_hi20(s) 397 // addi.d $a1, $zero, %pc_lo12(s) 398 // lu32i.d $a1, %pc64_lo20(s) 399 // lu52i.d $a1, $a1, %pc64_hi12(s) 400 // 401 // * pcalau12i $a0, %got_pc_hi20(s) | %ld_pc_hi20(s) | %gd_pc_hi20(s) 402 // addi.d $a1, $zero, %got_pc_lo12(s) 403 // lu32i.d $a1, %got64_pc_lo20(s) 404 // lu52i.d $a1, $a1, %got64_pc_hi12(s) 405 // 406 // * pcalau12i $a0, %ie_pc_hi20(s) 407 // addi.d $a1, $zero, %ie_pc_lo12(s) 408 // lu32i.d $a1, %ie64_pc_lo20(s) 409 // lu52i.d $a1, $a1, %ie64_pc_hi12(s) 410 // 411 // * pcalau12i $a0, %desc_pc_hi20(s) 412 // addi.d $a1, $zero, %desc_pc_lo12(s) 413 // lu32i.d $a1, %desc64_pc_lo20(s) 414 // lu52i.d $a1, $a1, %desc64_pc_hi12(s) 415 // 416 // For simplicity, only pcalau12i and lu52i.d are marked as scheduling 417 // boundaries, and the instructions between them are guaranteed to be 418 // ordered according to data dependencies. 419 switch (MI.getOpcode()) { 420 case LoongArch::PCALAU12I: { 421 auto AddI = std::next(MII); 422 if (AddI == MIE || AddI->getOpcode() != LoongArch::ADDI_D) 423 break; 424 auto Lu32I = std::next(AddI); 425 if (Lu32I == MIE || Lu32I->getOpcode() != LoongArch::LU32I_D) 426 break; 427 auto MO0 = MI.getOperand(1).getTargetFlags(); 428 auto MO1 = AddI->getOperand(2).getTargetFlags(); 429 auto MO2 = Lu32I->getOperand(2).getTargetFlags(); 430 if (MO0 == LoongArchII::MO_PCREL_HI && MO1 == LoongArchII::MO_PCREL_LO && 431 MO2 == LoongArchII::MO_PCREL64_LO) 432 return true; 433 if ((MO0 == LoongArchII::MO_GOT_PC_HI || MO0 == LoongArchII::MO_LD_PC_HI || 434 MO0 == LoongArchII::MO_GD_PC_HI) && 435 MO1 == LoongArchII::MO_GOT_PC_LO && MO2 == LoongArchII::MO_GOT_PC64_LO) 436 return true; 437 if (MO0 == LoongArchII::MO_IE_PC_HI && MO1 == LoongArchII::MO_IE_PC_LO && 438 MO2 == LoongArchII::MO_IE_PC64_LO) 439 return true; 440 if (MO0 == LoongArchII::MO_DESC_PC_HI && 441 MO1 == LoongArchII::MO_DESC_PC_LO && 442 MO2 == LoongArchII::MO_DESC64_PC_LO) 443 return true; 444 break; 445 } 446 case LoongArch::LU52I_D: { 447 auto MO = MI.getOperand(2).getTargetFlags(); 448 if (MO == LoongArchII::MO_PCREL64_HI || MO == LoongArchII::MO_GOT_PC64_HI || 449 MO == LoongArchII::MO_IE_PC64_HI || MO == LoongArchII::MO_DESC64_PC_HI) 450 return true; 451 break; 452 } 453 default: 454 break; 455 } 456 457 const auto &STI = MF.getSubtarget<LoongArchSubtarget>(); 458 if (STI.hasFeature(LoongArch::FeatureRelax)) { 459 // When linker relaxation enabled, the following instruction patterns are 460 // prohibited from being reordered: 461 // 462 // * pcalau12i $a0, %pc_hi20(s) 463 // addi.w/d $a0, $a0, %pc_lo12(s) 464 // 465 // * pcalau12i $a0, %got_pc_hi20(s) 466 // ld.w/d $a0, $a0, %got_pc_lo12(s) 467 // 468 // * pcalau12i $a0, %ld_pc_hi20(s) | %gd_pc_hi20(s) 469 // addi.w/d $a0, $a0, %got_pc_lo12(s) 470 // 471 // * pcalau12i $a0, %desc_pc_hi20(s) 472 // addi.w/d $a0, $a0, %desc_pc_lo12(s) 473 // ld.w/d $ra, $a0, %desc_ld(s) 474 // jirl $ra, $ra, %desc_call(s) 475 unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W; 476 unsigned LdOp = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W; 477 switch (MI.getOpcode()) { 478 case LoongArch::PCALAU12I: { 479 auto MO0 = LoongArchII::getDirectFlags(MI.getOperand(1)); 480 auto SecondOp = std::next(MII); 481 if (MO0 == LoongArchII::MO_DESC_PC_HI) { 482 if (SecondOp == MIE || SecondOp->getOpcode() != AddiOp) 483 break; 484 auto Ld = std::next(SecondOp); 485 if (Ld == MIE || Ld->getOpcode() != LdOp) 486 break; 487 auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2)); 488 auto MO2 = LoongArchII::getDirectFlags(Ld->getOperand(2)); 489 if (MO1 == LoongArchII::MO_DESC_PC_LO && MO2 == LoongArchII::MO_DESC_LD) 490 return true; 491 break; 492 } 493 if (SecondOp == MIE || 494 (SecondOp->getOpcode() != AddiOp && SecondOp->getOpcode() != LdOp)) 495 break; 496 auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2)); 497 if (MO0 == LoongArchII::MO_PCREL_HI && SecondOp->getOpcode() == AddiOp && 498 MO1 == LoongArchII::MO_PCREL_LO) 499 return true; 500 if (MO0 == LoongArchII::MO_GOT_PC_HI && SecondOp->getOpcode() == LdOp && 501 MO1 == LoongArchII::MO_GOT_PC_LO) 502 return true; 503 if ((MO0 == LoongArchII::MO_LD_PC_HI || 504 MO0 == LoongArchII::MO_GD_PC_HI) && 505 SecondOp->getOpcode() == AddiOp && MO1 == LoongArchII::MO_GOT_PC_LO) 506 return true; 507 break; 508 } 509 case LoongArch::ADDI_W: 510 case LoongArch::ADDI_D: { 511 auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); 512 if (MO == LoongArchII::MO_PCREL_LO || MO == LoongArchII::MO_GOT_PC_LO) 513 return true; 514 break; 515 } 516 case LoongArch::LD_W: 517 case LoongArch::LD_D: { 518 auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); 519 if (MO == LoongArchII::MO_GOT_PC_LO) 520 return true; 521 break; 522 } 523 case LoongArch::PseudoDESC_CALL: { 524 auto MO = LoongArchII::getDirectFlags(MI.getOperand(2)); 525 if (MO == LoongArchII::MO_DESC_CALL) 526 return true; 527 break; 528 } 529 default: 530 break; 531 } 532 } 533 534 return false; 535 } 536 537 unsigned LoongArchInstrInfo::removeBranch(MachineBasicBlock &MBB, 538 int *BytesRemoved) const { 539 if (BytesRemoved) 540 *BytesRemoved = 0; 541 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr(); 542 if (I == MBB.end()) 543 return 0; 544 545 if (!I->getDesc().isBranch()) 546 return 0; 547 548 // Remove the branch. 549 if (BytesRemoved) 550 *BytesRemoved += getInstSizeInBytes(*I); 551 I->eraseFromParent(); 552 553 I = MBB.end(); 554 555 if (I == MBB.begin()) 556 return 1; 557 --I; 558 if (!I->getDesc().isConditionalBranch()) 559 return 1; 560 561 // Remove the branch. 562 if (BytesRemoved) 563 *BytesRemoved += getInstSizeInBytes(*I); 564 I->eraseFromParent(); 565 return 2; 566 } 567 568 // Inserts a branch into the end of the specific MachineBasicBlock, returning 569 // the number of instructions inserted. 570 unsigned LoongArchInstrInfo::insertBranch( 571 MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, 572 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const { 573 if (BytesAdded) 574 *BytesAdded = 0; 575 576 // Shouldn't be a fall through. 577 assert(TBB && "insertBranch must not be told to insert a fallthrough"); 578 assert(Cond.size() <= 3 && Cond.size() != 1 && 579 "LoongArch branch conditions have at most two components!"); 580 581 // Unconditional branch. 582 if (Cond.empty()) { 583 MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(TBB); 584 if (BytesAdded) 585 *BytesAdded += getInstSizeInBytes(MI); 586 return 1; 587 } 588 589 // Either a one or two-way conditional branch. 590 MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm())); 591 for (unsigned i = 1; i < Cond.size(); ++i) 592 MIB.add(Cond[i]); 593 MIB.addMBB(TBB); 594 if (BytesAdded) 595 *BytesAdded += getInstSizeInBytes(*MIB); 596 597 // One-way conditional branch. 598 if (!FBB) 599 return 1; 600 601 // Two-way conditional branch. 602 MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(FBB); 603 if (BytesAdded) 604 *BytesAdded += getInstSizeInBytes(MI); 605 return 2; 606 } 607 608 void LoongArchInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB, 609 MachineBasicBlock &DestBB, 610 MachineBasicBlock &RestoreBB, 611 const DebugLoc &DL, 612 int64_t BrOffset, 613 RegScavenger *RS) const { 614 assert(RS && "RegScavenger required for long branching"); 615 assert(MBB.empty() && 616 "new block should be inserted for expanding unconditional branch"); 617 assert(MBB.pred_size() == 1); 618 619 MachineFunction *MF = MBB.getParent(); 620 MachineRegisterInfo &MRI = MF->getRegInfo(); 621 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 622 LoongArchMachineFunctionInfo *LAFI = 623 MF->getInfo<LoongArchMachineFunctionInfo>(); 624 625 if (!isInt<32>(BrOffset)) 626 report_fatal_error( 627 "Branch offsets outside of the signed 32-bit range not supported"); 628 629 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass); 630 auto II = MBB.end(); 631 632 MachineInstr &PCALAU12I = 633 *BuildMI(MBB, II, DL, get(LoongArch::PCALAU12I), ScratchReg) 634 .addMBB(&DestBB, LoongArchII::MO_PCREL_HI); 635 MachineInstr &ADDI = 636 *BuildMI(MBB, II, DL, 637 get(STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W), 638 ScratchReg) 639 .addReg(ScratchReg) 640 .addMBB(&DestBB, LoongArchII::MO_PCREL_LO); 641 BuildMI(MBB, II, DL, get(LoongArch::PseudoBRIND)) 642 .addReg(ScratchReg, RegState::Kill) 643 .addImm(0); 644 645 RS->enterBasicBlockEnd(MBB); 646 Register Scav = RS->scavengeRegisterBackwards( 647 LoongArch::GPRRegClass, PCALAU12I.getIterator(), /*RestoreAfter=*/false, 648 /*SPAdj=*/0, /*AllowSpill=*/false); 649 if (Scav != LoongArch::NoRegister) 650 RS->setRegUsed(Scav); 651 else { 652 // When there is no scavenged register, it needs to specify a register. 653 // Specify t8 register because it won't be used too often. 654 Scav = LoongArch::R20; 655 int FrameIndex = LAFI->getBranchRelaxationSpillFrameIndex(); 656 if (FrameIndex == -1) 657 report_fatal_error("The function size is incorrectly estimated."); 658 storeRegToStackSlot(MBB, PCALAU12I, Scav, /*IsKill=*/true, FrameIndex, 659 &LoongArch::GPRRegClass, TRI, Register()); 660 TRI->eliminateFrameIndex(std::prev(PCALAU12I.getIterator()), 661 /*SpAdj=*/0, /*FIOperandNum=*/1); 662 PCALAU12I.getOperand(1).setMBB(&RestoreBB); 663 ADDI.getOperand(2).setMBB(&RestoreBB); 664 loadRegFromStackSlot(RestoreBB, RestoreBB.end(), Scav, FrameIndex, 665 &LoongArch::GPRRegClass, TRI, Register()); 666 TRI->eliminateFrameIndex(RestoreBB.back(), 667 /*SpAdj=*/0, /*FIOperandNum=*/1); 668 } 669 MRI.replaceRegWith(ScratchReg, Scav); 670 MRI.clearVirtRegs(); 671 } 672 673 static unsigned getOppositeBranchOpc(unsigned Opc) { 674 switch (Opc) { 675 default: 676 llvm_unreachable("Unrecognized conditional branch"); 677 case LoongArch::BEQ: 678 return LoongArch::BNE; 679 case LoongArch::BNE: 680 return LoongArch::BEQ; 681 case LoongArch::BEQZ: 682 return LoongArch::BNEZ; 683 case LoongArch::BNEZ: 684 return LoongArch::BEQZ; 685 case LoongArch::BCEQZ: 686 return LoongArch::BCNEZ; 687 case LoongArch::BCNEZ: 688 return LoongArch::BCEQZ; 689 case LoongArch::BLT: 690 return LoongArch::BGE; 691 case LoongArch::BGE: 692 return LoongArch::BLT; 693 case LoongArch::BLTU: 694 return LoongArch::BGEU; 695 case LoongArch::BGEU: 696 return LoongArch::BLTU; 697 } 698 } 699 700 bool LoongArchInstrInfo::reverseBranchCondition( 701 SmallVectorImpl<MachineOperand> &Cond) const { 702 assert((Cond.size() && Cond.size() <= 3) && "Invalid branch condition!"); 703 Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm())); 704 return false; 705 } 706 707 std::pair<unsigned, unsigned> 708 LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const { 709 const unsigned Mask = LoongArchII::MO_DIRECT_FLAG_MASK; 710 return std::make_pair(TF & Mask, TF & ~Mask); 711 } 712 713 ArrayRef<std::pair<unsigned, const char *>> 714 LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const { 715 using namespace LoongArchII; 716 // TODO: Add more target flags. 717 static const std::pair<unsigned, const char *> TargetFlags[] = { 718 {MO_CALL, "loongarch-call"}, 719 {MO_CALL_PLT, "loongarch-call-plt"}, 720 {MO_PCREL_HI, "loongarch-pcrel-hi"}, 721 {MO_PCREL_LO, "loongarch-pcrel-lo"}, 722 {MO_PCREL64_LO, "loongarch-pcrel64-lo"}, 723 {MO_PCREL64_HI, "loongarch-pcrel64-hi"}, 724 {MO_GOT_PC_HI, "loongarch-got-pc-hi"}, 725 {MO_GOT_PC_LO, "loongarch-got-pc-lo"}, 726 {MO_GOT_PC64_LO, "loongarch-got-pc64-lo"}, 727 {MO_GOT_PC64_HI, "loongarch-got-pc64-hi"}, 728 {MO_LE_HI, "loongarch-le-hi"}, 729 {MO_LE_LO, "loongarch-le-lo"}, 730 {MO_LE64_LO, "loongarch-le64-lo"}, 731 {MO_LE64_HI, "loongarch-le64-hi"}, 732 {MO_IE_PC_HI, "loongarch-ie-pc-hi"}, 733 {MO_IE_PC_LO, "loongarch-ie-pc-lo"}, 734 {MO_IE_PC64_LO, "loongarch-ie-pc64-lo"}, 735 {MO_IE_PC64_HI, "loongarch-ie-pc64-hi"}, 736 {MO_LD_PC_HI, "loongarch-ld-pc-hi"}, 737 {MO_GD_PC_HI, "loongarch-gd-pc-hi"}, 738 {MO_CALL36, "loongarch-call36"}, 739 {MO_DESC_PC_HI, "loongarch-desc-pc-hi"}, 740 {MO_DESC_PC_LO, "loongarch-desc-pc-lo"}, 741 {MO_DESC64_PC_LO, "loongarch-desc64-pc-lo"}, 742 {MO_DESC64_PC_HI, "loongarch-desc64-pc-hi"}, 743 {MO_DESC_LD, "loongarch-desc-ld"}, 744 {MO_DESC_CALL, "loongarch-desc-call"}, 745 {MO_LE_HI_R, "loongarch-le-hi-r"}, 746 {MO_LE_ADD_R, "loongarch-le-add-r"}, 747 {MO_LE_LO_R, "loongarch-le-lo-r"}}; 748 return ArrayRef(TargetFlags); 749 } 750 751 ArrayRef<std::pair<unsigned, const char *>> 752 LoongArchInstrInfo::getSerializableBitmaskMachineOperandTargetFlags() const { 753 using namespace LoongArchII; 754 static const std::pair<unsigned, const char *> TargetFlags[] = { 755 {MO_RELAX, "loongarch-relax"}}; 756 return ArrayRef(TargetFlags); 757 } 758 759 // Returns true if this is the sext.w pattern, addi.w rd, rs, 0. 760 bool LoongArch::isSEXT_W(const MachineInstr &MI) { 761 return MI.getOpcode() == LoongArch::ADDI_W && MI.getOperand(1).isReg() && 762 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0; 763 } 764