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
23using namespace llvm;
24
25#define GET_INSTRINFO_CTOR_DTOR
26#include "LoongArchGenInstrInfo.inc"
27
28LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI)
29 : LoongArchGenInstrInfo(LoongArch::ADJCALLSTACKDOWN,
30 LoongArch::ADJCALLSTACKUP),
31 STI(STI) {}
32
33MCInst LoongArchInstrInfo::getNop() const {
34 return MCInstBuilder(LoongArch::ANDI)
35 .addReg(Reg: LoongArch::R0)
36 .addReg(Reg: LoongArch::R0)
37 .addImm(Val: 0);
38}
39
40void 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(Reg1: DstReg, Reg2: SrcReg)) {
47 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: get(Opcode: LoongArch::OR), DestReg: DstReg)
48 .addReg(RegNo: SrcReg, flags: getKillRegState(B: KillSrc))
49 .addReg(RegNo: LoongArch::R0);
50 return;
51 }
52
53 // VR->VR copies.
54 if (LoongArch::LSX128RegClass.contains(Reg1: DstReg, Reg2: SrcReg)) {
55 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: get(Opcode: LoongArch::VORI_B), DestReg: DstReg)
56 .addReg(RegNo: SrcReg, flags: getKillRegState(B: KillSrc))
57 .addImm(Val: 0);
58 return;
59 }
60
61 // XR->XR copies.
62 if (LoongArch::LASX256RegClass.contains(Reg1: DstReg, Reg2: SrcReg)) {
63 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: get(Opcode: LoongArch::XVORI_B), DestReg: DstReg)
64 .addReg(RegNo: SrcReg, flags: getKillRegState(B: KillSrc))
65 .addImm(Val: 0);
66 return;
67 }
68
69 // GPR->CFR copy.
70 if (LoongArch::CFRRegClass.contains(Reg: DstReg) &&
71 LoongArch::GPRRegClass.contains(Reg: SrcReg)) {
72 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: get(Opcode: LoongArch::MOVGR2CF), DestReg: DstReg)
73 .addReg(RegNo: SrcReg, flags: getKillRegState(B: KillSrc));
74 return;
75 }
76 // CFR->GPR copy.
77 if (LoongArch::GPRRegClass.contains(Reg: DstReg) &&
78 LoongArch::CFRRegClass.contains(Reg: SrcReg)) {
79 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: get(Opcode: LoongArch::MOVCF2GR), DestReg: DstReg)
80 .addReg(RegNo: SrcReg, flags: getKillRegState(B: KillSrc));
81 return;
82 }
83 // CFR->CFR copy.
84 if (LoongArch::CFRRegClass.contains(Reg1: DstReg, Reg2: SrcReg)) {
85 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: get(Opcode: LoongArch::PseudoCopyCFR), DestReg: DstReg)
86 .addReg(RegNo: SrcReg, flags: getKillRegState(B: KillSrc));
87 return;
88 }
89
90 // FPR->FPR copies.
91 unsigned Opc;
92 if (LoongArch::FPR32RegClass.contains(Reg1: DstReg, Reg2: SrcReg)) {
93 Opc = LoongArch::FMOV_S;
94 } else if (LoongArch::FPR64RegClass.contains(Reg1: DstReg, Reg2: SrcReg)) {
95 Opc = LoongArch::FMOV_D;
96 } else if (LoongArch::GPRRegClass.contains(Reg: DstReg) &&
97 LoongArch::FPR32RegClass.contains(Reg: SrcReg)) {
98 // FPR32 -> GPR copies
99 Opc = LoongArch::MOVFR2GR_S;
100 } else if (LoongArch::GPRRegClass.contains(Reg: DstReg) &&
101 LoongArch::FPR64RegClass.contains(Reg: 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(BB&: MBB, I: MBBI, MIMD: DL, MCID: get(Opcode: Opc), DestReg: DstReg)
110 .addReg(RegNo: SrcReg, flags: getKillRegState(B: KillSrc));
111}
112
113void 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(RC: 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 PtrInfo: MachinePointerInfo::getFixedStack(MF&: *MF, FI), F: MachineMemOperand::MOStore,
141 Size: MFI.getObjectSize(ObjectIdx: FI), BaseAlignment: MFI.getObjectAlign(ObjectIdx: FI));
142
143 BuildMI(BB&: MBB, I, MIMD: DebugLoc(), MCID: get(Opcode))
144 .addReg(RegNo: SrcReg, flags: getKillRegState(B: IsKill))
145 .addFrameIndex(Idx: FI)
146 .addImm(Val: 0)
147 .addMemOperand(MMO);
148}
149
150void 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(RC: 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 PtrInfo: MachinePointerInfo::getFixedStack(MF&: *MF, FI), F: MachineMemOperand::MOLoad,
180 Size: MFI.getObjectSize(ObjectIdx: FI), BaseAlignment: MFI.getObjectAlign(ObjectIdx: FI));
181
182 BuildMI(BB&: MBB, I, MIMD: DL, MCID: get(Opcode), DestReg: DstReg)
183 .addFrameIndex(Idx: FI)
184 .addImm(Val: 0)
185 .addMemOperand(MMO);
186}
187
188void 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>(x: Val))
195 report_fatal_error(reason: "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(BB&: MBB, I: MBBI, MIMD: DL, MCID: get(Opcode: Inst.Opc), DestReg: DstReg)
204 .addImm(Val: 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(BB&: MBB, I: MBBI, MIMD: DL, MCID: get(Opcode: Inst.Opc), DestReg: DstReg)
212 .addReg(RegNo: SrcReg, flags: RegState::Kill)
213 .addImm(Val: Inst.Imm)
214 .setMIFlag(Flag);
215 break;
216 case LoongArch::BSTRINS_D:
217 BuildMI(BB&: MBB, I: MBBI, MIMD: DL, MCID: get(Opcode: Inst.Opc), DestReg: DstReg)
218 .addReg(RegNo: SrcReg, flags: RegState::Kill)
219 .addReg(RegNo: SrcReg, flags: RegState::Kill)
220 .addImm(Val: Inst.Imm >> 32)
221 .addImm(Val: 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
233unsigned 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(Str: MI.getOperand(i: 0).getSymbolName(), MAI: *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
263bool 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(i: 1).isReg() &&
272 MI.getOperand(i: 1).getReg() == LoongArch::R0) ||
273 (MI.getOperand(i: 2).isImm() && MI.getOperand(i: 2).getImm() == 0);
274 }
275 return MI.isAsCheapAsAMove();
276}
277
278MachineBasicBlock *
279LoongArchInstrInfo::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(i: MI.getNumExplicitOperands() - 1).getMBB();
283}
284
285static 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(i: NumOp - 1).getMBB();
292
293 Cond.push_back(Elt: MachineOperand::CreateImm(Val: LastInst.getOpcode()));
294 for (int i = 0; i < NumOp - 1; i++)
295 Cond.push_back(Elt: LastInst.getOperand(i));
296}
297
298bool 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(MI: *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(MI: *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(x: FirstUncondOrIndirectBr) != MBB.end()) {
328 std::next(x: 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(MI: *I);
337 return false;
338 }
339
340 // Handle a single conditional branch.
341 if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
342 parseCondBranch(LastInst&: *I, Target&: TBB, Cond);
343 return false;
344 }
345
346 // Handle a conditional branch followed by an unconditional branch.
347 if (NumTerminators == 2 && std::prev(x: I)->getDesc().isConditionalBranch() &&
348 I->getDesc().isUnconditionalBranch()) {
349 parseCondBranch(LastInst&: *std::prev(x: I), Target&: TBB, Cond);
350 FBB = getBranchDestBlock(MI: *I);
351 return false;
352 }
353
354 // Otherwise, we can't handle this.
355 return true;
356}
357
358bool 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>(x: BrOffset);
370 case LoongArch::BEQZ:
371 case LoongArch::BNEZ:
372 case LoongArch::BCEQZ:
373 case LoongArch::BCNEZ:
374 return isInt<23>(x: BrOffset);
375 case LoongArch::B:
376 case LoongArch::PseudoBR:
377 return isInt<28>(x: BrOffset);
378 }
379}
380
381bool 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(x: MII);
422 if (AddI == MIE || AddI->getOpcode() != LoongArch::ADDI_D)
423 break;
424 auto Lu32I = std::next(x: AddI);
425 if (Lu32I == MIE || Lu32I->getOpcode() != LoongArch::LU32I_D)
426 break;
427 auto MO0 = MI.getOperand(i: 1).getTargetFlags();
428 auto MO1 = AddI->getOperand(i: 2).getTargetFlags();
429 auto MO2 = Lu32I->getOperand(i: 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(i: 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(Feature: 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(MO: MI.getOperand(i: 1));
480 auto SecondOp = std::next(x: MII);
481 if (MO0 == LoongArchII::MO_DESC_PC_HI) {
482 if (SecondOp == MIE || SecondOp->getOpcode() != AddiOp)
483 break;
484 auto Ld = std::next(x: SecondOp);
485 if (Ld == MIE || Ld->getOpcode() != LdOp)
486 break;
487 auto MO1 = LoongArchII::getDirectFlags(MO: SecondOp->getOperand(i: 2));
488 auto MO2 = LoongArchII::getDirectFlags(MO: Ld->getOperand(i: 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(MO: SecondOp->getOperand(i: 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(MO: MI.getOperand(i: 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(MO: MI.getOperand(i: 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(MO: MI.getOperand(i: 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
537unsigned 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(MI: *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(MI: *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.
570unsigned 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(BB: &MBB, MIMD: DL, MCID: get(Opcode: LoongArch::PseudoBR)).addMBB(MBB: 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(BB: &MBB, MIMD: DL, MCID: get(Opcode: Cond[0].getImm()));
591 for (unsigned i = 1; i < Cond.size(); ++i)
592 MIB.add(MO: Cond[i]);
593 MIB.addMBB(MBB: TBB);
594 if (BytesAdded)
595 *BytesAdded += getInstSizeInBytes(MI: *MIB);
596
597 // One-way conditional branch.
598 if (!FBB)
599 return 1;
600
601 // Two-way conditional branch.
602 MachineInstr &MI = *BuildMI(BB: &MBB, MIMD: DL, MCID: get(Opcode: LoongArch::PseudoBR)).addMBB(MBB: FBB);
603 if (BytesAdded)
604 *BytesAdded += getInstSizeInBytes(MI);
605 return 2;
606}
607
608void 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>(x: BrOffset))
626 report_fatal_error(
627 reason: "Branch offsets outside of the signed 32-bit range not supported");
628
629 Register ScratchReg = MRI.createVirtualRegister(RegClass: &LoongArch::GPRRegClass);
630 auto II = MBB.end();
631
632 MachineInstr &PCALAU12I =
633 *BuildMI(BB&: MBB, I: II, MIMD: DL, MCID: get(Opcode: LoongArch::PCALAU12I), DestReg: ScratchReg)
634 .addMBB(MBB: &DestBB, TargetFlags: LoongArchII::MO_PCREL_HI);
635 MachineInstr &ADDI =
636 *BuildMI(BB&: MBB, I: II, MIMD: DL,
637 MCID: get(Opcode: STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W),
638 DestReg: ScratchReg)
639 .addReg(RegNo: ScratchReg)
640 .addMBB(MBB: &DestBB, TargetFlags: LoongArchII::MO_PCREL_LO);
641 BuildMI(BB&: MBB, I: II, MIMD: DL, MCID: get(Opcode: LoongArch::PseudoBRIND))
642 .addReg(RegNo: ScratchReg, flags: RegState::Kill)
643 .addImm(Val: 0);
644
645 RS->enterBasicBlockEnd(MBB);
646 Register Scav = RS->scavengeRegisterBackwards(
647 RC: LoongArch::GPRRegClass, To: PCALAU12I.getIterator(), /*RestoreAfter=*/false,
648 /*SPAdj=*/0, /*AllowSpill=*/false);
649 if (Scav != LoongArch::NoRegister)
650 RS->setRegUsed(Reg: 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(reason: "The function size is incorrectly estimated.");
658 storeRegToStackSlot(MBB, I: PCALAU12I, SrcReg: Scav, /*IsKill=*/true, FI: FrameIndex,
659 RC: &LoongArch::GPRRegClass, TRI, VReg: Register());
660 TRI->eliminateFrameIndex(MI: std::prev(x: PCALAU12I.getIterator()),
661 /*SpAdj=*/SPAdj: 0, /*FIOperandNum=*/1);
662 PCALAU12I.getOperand(i: 1).setMBB(&RestoreBB);
663 ADDI.getOperand(i: 2).setMBB(&RestoreBB);
664 loadRegFromStackSlot(MBB&: RestoreBB, I: RestoreBB.end(), DstReg: Scav, FI: FrameIndex,
665 RC: &LoongArch::GPRRegClass, TRI, VReg: Register());
666 TRI->eliminateFrameIndex(MI: RestoreBB.back(),
667 /*SpAdj=*/SPAdj: 0, /*FIOperandNum=*/1);
668 }
669 MRI.replaceRegWith(FromReg: ScratchReg, ToReg: Scav);
670 MRI.clearVirtRegs();
671}
672
673static 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
700bool LoongArchInstrInfo::reverseBranchCondition(
701 SmallVectorImpl<MachineOperand> &Cond) const {
702 assert((Cond.size() && Cond.size() <= 3) && "Invalid branch condition!");
703 Cond[0].setImm(getOppositeBranchOpc(Opc: Cond[0].getImm()));
704 return false;
705}
706
707std::pair<unsigned, unsigned>
708LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
709 const unsigned Mask = LoongArchII::MO_DIRECT_FLAG_MASK;
710 return std::make_pair(x: TF & Mask, y: TF & ~Mask);
711}
712
713ArrayRef<std::pair<unsigned, const char *>>
714LoongArchInstrInfo::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
751ArrayRef<std::pair<unsigned, const char *>>
752LoongArchInstrInfo::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.
760bool LoongArch::isSEXT_W(const MachineInstr &MI) {
761 return MI.getOpcode() == LoongArch::ADDI_W && MI.getOperand(i: 1).isReg() &&
762 MI.getOperand(i: 2).isImm() && MI.getOperand(i: 2).getImm() == 0;
763}
764