LLVM 23.0.0git
LoongArchInstrInfo.cpp
Go to the documentation of this file.
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"
21#include "llvm/MC/MCContext.h"
24
25using namespace llvm;
26
28 "loongarch-disable-reloc-sched",
29 cl::desc("Disable scheduling of instructions with target flags"),
30 cl::init(false), cl::Hidden);
31
32#define GET_INSTRINFO_CTOR_DTOR
33#include "LoongArchGenInstrInfo.inc"
34
36 : LoongArchGenInstrInfo(STI, RegInfo, LoongArch::ADJCALLSTACKDOWN,
37 LoongArch::ADJCALLSTACKUP),
38 RegInfo(STI.getHwMode()), STI(STI) {}
39
41 return MCInstBuilder(LoongArch::ANDI)
42 .addReg(LoongArch::R0)
43 .addReg(LoongArch::R0)
44 .addImm(0);
45}
46
49 const DebugLoc &DL, Register DstReg,
50 Register SrcReg, bool KillSrc,
51 bool RenamableDest,
52 bool RenamableSrc) const {
53 if (LoongArch::GPRRegClass.contains(DstReg, SrcReg)) {
54 BuildMI(MBB, MBBI, DL, get(LoongArch::OR), DstReg)
55 .addReg(SrcReg, getKillRegState(KillSrc))
56 .addReg(LoongArch::R0);
57 return;
58 }
59
60 // VR->VR copies.
61 if (LoongArch::LSX128RegClass.contains(DstReg, SrcReg)) {
62 BuildMI(MBB, MBBI, DL, get(LoongArch::VORI_B), DstReg)
63 .addReg(SrcReg, getKillRegState(KillSrc))
64 .addImm(0);
65 return;
66 }
67
68 // XR->XR copies.
69 if (LoongArch::LASX256RegClass.contains(DstReg, SrcReg)) {
70 BuildMI(MBB, MBBI, DL, get(LoongArch::XVORI_B), DstReg)
71 .addReg(SrcReg, getKillRegState(KillSrc))
72 .addImm(0);
73 return;
74 }
75
76 // GPR->CFR copy.
77 if (LoongArch::CFRRegClass.contains(DstReg) &&
78 LoongArch::GPRRegClass.contains(SrcReg)) {
79 BuildMI(MBB, MBBI, DL, get(LoongArch::MOVGR2CF), DstReg)
80 .addReg(SrcReg, getKillRegState(KillSrc));
81 return;
82 }
83 // CFR->GPR copy.
84 if (LoongArch::GPRRegClass.contains(DstReg) &&
85 LoongArch::CFRRegClass.contains(SrcReg)) {
86 BuildMI(MBB, MBBI, DL, get(LoongArch::MOVCF2GR), DstReg)
87 .addReg(SrcReg, getKillRegState(KillSrc));
88 return;
89 }
90 // CFR->CFR copy.
91 if (LoongArch::CFRRegClass.contains(DstReg, SrcReg)) {
92 BuildMI(MBB, MBBI, DL, get(LoongArch::PseudoCopyCFR), DstReg)
93 .addReg(SrcReg, getKillRegState(KillSrc));
94 return;
95 }
96
97 // FPR->FPR copies.
98 unsigned Opc;
99 if (LoongArch::FPR32RegClass.contains(DstReg, SrcReg)) {
100 Opc = LoongArch::FMOV_S;
101 } else if (LoongArch::FPR64RegClass.contains(DstReg, SrcReg)) {
102 Opc = LoongArch::FMOV_D;
103 } else if (LoongArch::GPRRegClass.contains(DstReg) &&
104 LoongArch::FPR32RegClass.contains(SrcReg)) {
105 // FPR32 -> GPR copies
106 Opc = LoongArch::MOVFR2GR_S;
107 } else if (LoongArch::GPRRegClass.contains(DstReg) &&
108 LoongArch::FPR64RegClass.contains(SrcReg)) {
109 // FPR64 -> GPR copies
110 Opc = LoongArch::MOVFR2GR_D;
111 } else {
112 // TODO: support other copies.
113 llvm_unreachable("Impossible reg-to-reg copy");
114 }
115
116 BuildMI(MBB, MBBI, DL, get(Opc), DstReg)
117 .addReg(SrcReg, getKillRegState(KillSrc));
118}
119
122 bool IsKill, int FI, const TargetRegisterClass *RC,
123
124 Register VReg, MachineInstr::MIFlag Flags) const {
125 MachineFunction *MF = MBB.getParent();
126 MachineFrameInfo &MFI = MF->getFrameInfo();
127
128 unsigned Opcode;
129 if (LoongArch::GPRRegClass.hasSubClassEq(RC))
130 Opcode = TRI.getRegSizeInBits(LoongArch::GPRRegClass) == 32
131 ? LoongArch::ST_W
132 : LoongArch::ST_D;
133 else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
134 Opcode = LoongArch::FST_S;
135 else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
136 Opcode = LoongArch::FST_D;
137 else if (LoongArch::LSX128RegClass.hasSubClassEq(RC))
138 Opcode = LoongArch::VST;
139 else if (LoongArch::LASX256RegClass.hasSubClassEq(RC))
140 Opcode = LoongArch::XVST;
141 else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
142 Opcode = LoongArch::PseudoST_CFR;
143 else
144 llvm_unreachable("Can't store this register to stack slot");
145
148 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
149
150 BuildMI(MBB, I, DebugLoc(), get(Opcode))
151 .addReg(SrcReg, getKillRegState(IsKill))
152 .addFrameIndex(FI)
153 .addImm(0)
154 .addMemOperand(MMO);
155}
156
159 int FI, const TargetRegisterClass *RC, Register VReg, unsigned SubReg,
160 MachineInstr::MIFlag Flags) const {
161 MachineFunction *MF = MBB.getParent();
162 MachineFrameInfo &MFI = MF->getFrameInfo();
163 DebugLoc DL;
164 if (I != MBB.end())
165 DL = I->getDebugLoc();
166
167 unsigned Opcode;
168 if (LoongArch::GPRRegClass.hasSubClassEq(RC))
169 Opcode = RegInfo.getRegSizeInBits(LoongArch::GPRRegClass) == 32
170 ? LoongArch::LD_W
171 : LoongArch::LD_D;
172 else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
173 Opcode = LoongArch::FLD_S;
174 else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
175 Opcode = LoongArch::FLD_D;
176 else if (LoongArch::LSX128RegClass.hasSubClassEq(RC))
177 Opcode = LoongArch::VLD;
178 else if (LoongArch::LASX256RegClass.hasSubClassEq(RC))
179 Opcode = LoongArch::XVLD;
180 else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
181 Opcode = LoongArch::PseudoLD_CFR;
182 else
183 llvm_unreachable("Can't load this register from stack slot");
184
187 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
188
189 BuildMI(MBB, I, DL, get(Opcode), DstReg)
190 .addFrameIndex(FI)
191 .addImm(0)
192 .addMemOperand(MMO);
193}
194
196 int &FrameIndex) const {
197 TypeSize Dummy = TypeSize::getZero();
198 return isLoadFromStackSlot(MI, FrameIndex, Dummy);
199}
200
202 int &FrameIndex,
203 TypeSize &MemBytes) const {
204 switch (MI.getOpcode()) {
205 default:
206 return Register();
207 case LoongArch::LD_W:
208 case LoongArch::FLD_S:
209 MemBytes = TypeSize::getFixed(4);
210 break;
211 case LoongArch::LD_D:
212 case LoongArch::FLD_D:
213 MemBytes = TypeSize::getFixed(8);
214 break;
215 case LoongArch::VLD:
216 MemBytes = TypeSize::getFixed(16);
217 break;
218 case LoongArch::XVLD:
219 MemBytes = TypeSize::getFixed(32);
220 break;
221 }
222
223 if ((MI.getOperand(1).isFI()) && // is a stack slot
224 (MI.getOperand(2).isImm()) && // the imm is zero
225 (MI.getOperand(2).getImm() == 0)) {
226 FrameIndex = MI.getOperand(1).getIndex();
227 return MI.getOperand(0).getReg();
228 }
229
230 return Register();
231}
232
234 int &FrameIndex) const {
235 TypeSize Dummy = TypeSize::getZero();
236 return isStoreToStackSlot(MI, FrameIndex, Dummy);
237}
238
240 int &FrameIndex,
241 TypeSize &MemBytes) const {
242 switch (MI.getOpcode()) {
243 default:
244 return Register();
245 case LoongArch::ST_W:
246 case LoongArch::FST_S:
247 MemBytes = TypeSize::getFixed(4);
248 break;
249 case LoongArch::ST_D:
250 case LoongArch::FST_D:
251 MemBytes = TypeSize::getFixed(8);
252 break;
253 case LoongArch::VST:
254 MemBytes = TypeSize::getFixed(16);
255 break;
256 case LoongArch::XVST:
257 MemBytes = TypeSize::getFixed(32);
258 break;
259 }
260
261 if ((MI.getOperand(1).isFI()) && // is a stack slot
262 (MI.getOperand(2).isImm()) && // the imm is zero
263 (MI.getOperand(2).getImm() == 0)) {
264 FrameIndex = MI.getOperand(1).getIndex();
265 return MI.getOperand(0).getReg();
266 }
267
268 return Register();
269}
270
273 const DebugLoc &DL, Register DstReg,
274 uint64_t Val, MachineInstr::MIFlag Flag) const {
275 Register SrcReg = LoongArch::R0;
276
277 if (!STI.is64Bit() && !isInt<32>(Val))
278 report_fatal_error("Should only materialize 32-bit constants for LA32");
279
280 auto Seq = LoongArchMatInt::generateInstSeq(Val);
281 assert(!Seq.empty());
282
283 for (auto &Inst : Seq) {
284 switch (Inst.Opc) {
285 case LoongArch::LU12I_W:
286 BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
287 .addImm(Inst.Imm)
288 .setMIFlag(Flag);
289 break;
290 case LoongArch::ADDI_W:
291 case LoongArch::ORI:
292 case LoongArch::LU32I_D: // "rj" is needed due to InstrInfo pattern
293 case LoongArch::LU52I_D:
294 BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
295 .addReg(SrcReg, RegState::Kill)
296 .addImm(Inst.Imm)
297 .setMIFlag(Flag);
298 break;
299 case LoongArch::BSTRINS_D:
300 BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
301 .addReg(SrcReg, RegState::Kill)
302 .addReg(SrcReg, RegState::Kill)
303 .addImm(Inst.Imm >> 32)
304 .addImm(Inst.Imm & 0xFF)
305 .setMIFlag(Flag);
306 break;
307 default:
308 assert(false && "Unknown insn emitted by LoongArchMatInt");
309 }
310
311 // Only the first instruction has $zero as its source.
312 SrcReg = DstReg;
313 }
314}
315
317 unsigned Opcode = MI.getOpcode();
318
319 if (Opcode == TargetOpcode::INLINEASM ||
320 Opcode == TargetOpcode::INLINEASM_BR) {
321 const MachineFunction *MF = MI.getParent()->getParent();
322 const MCAsmInfo &MAI = MF->getTarget().getMCAsmInfo();
323 return getInlineAsmLength(MI.getOperand(0).getSymbolName(), MAI);
324 }
325
326 unsigned NumBytes = 0;
327 const MCInstrDesc &Desc = MI.getDesc();
328
329 // Size should be preferably set in
330 // llvm/lib/Target/LoongArch/LoongArch*InstrInfo.td (default case).
331 // Specific cases handle instructions of variable sizes.
332 switch (Desc.getOpcode()) {
333 default:
334 return Desc.getSize();
335 case TargetOpcode::STATEPOINT:
336 NumBytes = StatepointOpers(&MI).getNumPatchBytes();
337 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
338 // No patch bytes means a normal call inst (i.e. `bl`) is emitted.
339 if (NumBytes == 0)
340 NumBytes = 4;
341 break;
342 case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
343 const MachineFunction *MF = MI.getParent()->getParent();
344 const Function &F = MF->getFunction();
345 if (F.hasFnAttribute("patchable-function-entry")) {
346 unsigned Num =
347 F.getFnAttributeAsParsedInteger("patchable-function-entry");
348 return Num * 4;
349 }
350 [[fallthrough]];
351 }
352 case TargetOpcode::PATCHABLE_FUNCTION_EXIT:
353 case TargetOpcode::PATCHABLE_TAIL_CALL:
354 // Size of xray sled (branch + 11 nops).
355 return 12 * 4;
356 case TargetOpcode::BUNDLE:
357 return getInstBundleSize(MI);
358 }
359 return NumBytes;
360}
361
363 const unsigned Opcode = MI.getOpcode();
364 switch (Opcode) {
365 default:
366 break;
367 case LoongArch::ADDI_D:
368 case LoongArch::ORI:
369 case LoongArch::XORI:
370 return (MI.getOperand(1).isReg() &&
371 MI.getOperand(1).getReg() == LoongArch::R0) ||
372 (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0);
373 }
374 return MI.isAsCheapAsAMove();
375}
376
379 assert(MI.getDesc().isBranch() && "Unexpected opcode!");
380 // The branch target is always the last operand.
381 return MI.getOperand(MI.getNumExplicitOperands() - 1).getMBB();
382}
383
386 // Block ends with fall-through condbranch.
387 assert(LastInst.getDesc().isConditionalBranch() &&
388 "Unknown conditional branch");
389 int NumOp = LastInst.getNumExplicitOperands();
390 Target = LastInst.getOperand(NumOp - 1).getMBB();
391
392 Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode()));
393 for (int i = 0; i < NumOp - 1; i++)
394 Cond.push_back(LastInst.getOperand(i));
395}
396
399 MachineBasicBlock *&FBB,
401 bool AllowModify) const {
402 TBB = FBB = nullptr;
403 Cond.clear();
404
405 // If the block has no terminators, it just falls into the block after it.
406 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
407 if (I == MBB.end() || !isUnpredicatedTerminator(*I))
408 return false;
409
410 // Count the number of terminators and find the first unconditional or
411 // indirect branch.
412 MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
413 int NumTerminators = 0;
414 for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
415 J++) {
416 NumTerminators++;
417 if (J->getDesc().isUnconditionalBranch() ||
418 J->getDesc().isIndirectBranch()) {
419 FirstUncondOrIndirectBr = J.getReverse();
420 }
421 }
422
423 // If AllowModify is true, we can erase any terminators after
424 // FirstUncondOrIndirectBR.
425 if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
426 while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
427 std::next(FirstUncondOrIndirectBr)->eraseFromParent();
428 NumTerminators--;
429 }
430 I = FirstUncondOrIndirectBr;
431 }
432
433 // Handle a single unconditional branch.
434 if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
436 return false;
437 }
438
439 // Handle a single conditional branch.
440 if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
442 return false;
443 }
444
445 // Handle a conditional branch followed by an unconditional branch.
446 if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
447 I->getDesc().isUnconditionalBranch()) {
448 parseCondBranch(*std::prev(I), TBB, Cond);
449 FBB = getBranchDestBlock(*I);
450 return false;
451 }
452
453 // Otherwise, we can't handle this.
454 return true;
455}
456
458 int64_t BrOffset) const {
459 switch (BranchOp) {
460 default:
461 llvm_unreachable("Unknown branch instruction!");
462 case LoongArch::BEQ:
463 case LoongArch::BNE:
464 case LoongArch::BLT:
465 case LoongArch::BGE:
466 case LoongArch::BLTU:
467 case LoongArch::BGEU:
468 return isInt<18>(BrOffset);
469 case LoongArch::BEQZ:
470 case LoongArch::BNEZ:
471 case LoongArch::BCEQZ:
472 case LoongArch::BCNEZ:
473 return isInt<23>(BrOffset);
474 case LoongArch::B:
475 case LoongArch::PseudoBR:
476 return isInt<28>(BrOffset);
477 }
478}
479
481 const MachineBasicBlock *MBB,
482 const MachineFunction &MF) const {
483 if (DisableRelocSched) {
484 for (const MachineOperand &MO : MI.operands())
485 if (MO.getTargetFlags())
486 return false;
487 }
488
489 auto MII = MI.getIterator();
490 auto MIE = MBB->end();
491
492 // According to psABI v2.30:
493 //
494 // https://github.com/loongson/la-abi-specs/releases/tag/v2.30
495 //
496 // The following instruction patterns are prohibited from being reordered:
497 //
498 // * pcalau12i $a0, %pc_hi20(s)
499 // addi.d $a1, $zero, %pc_lo12(s)
500 // lu32i.d $a1, %pc64_lo20(s)
501 // lu52i.d $a1, $a1, %pc64_hi12(s)
502 //
503 // * pcalau12i $a0, %got_pc_hi20(s) | %ld_pc_hi20(s) | %gd_pc_hi20(s)
504 // addi.d $a1, $zero, %got_pc_lo12(s)
505 // lu32i.d $a1, %got64_pc_lo20(s)
506 // lu52i.d $a1, $a1, %got64_pc_hi12(s)
507 //
508 // * pcalau12i $a0, %ie_pc_hi20(s)
509 // addi.d $a1, $zero, %ie_pc_lo12(s)
510 // lu32i.d $a1, %ie64_pc_lo20(s)
511 // lu52i.d $a1, $a1, %ie64_pc_hi12(s)
512 //
513 // * pcalau12i $a0, %desc_pc_hi20(s)
514 // addi.d $a1, $zero, %desc_pc_lo12(s)
515 // lu32i.d $a1, %desc64_pc_lo20(s)
516 // lu52i.d $a1, $a1, %desc64_pc_hi12(s)
517 //
518 // For simplicity, only pcalau12i and lu52i.d are marked as scheduling
519 // boundaries, and the instructions between them are guaranteed to be
520 // ordered according to data dependencies.
521 switch (MI.getOpcode()) {
522 case LoongArch::PCALAU12I: {
523 auto AddI = std::next(MII);
524 if (AddI == MIE || AddI->getOpcode() != LoongArch::ADDI_D)
525 break;
526 auto Lu32I = std::next(AddI);
527 if (Lu32I == MIE || Lu32I->getOpcode() != LoongArch::LU32I_D)
528 break;
529 auto MO0 = MI.getOperand(1).getTargetFlags();
530 auto MO1 = AddI->getOperand(2).getTargetFlags();
531 auto MO2 = Lu32I->getOperand(2).getTargetFlags();
534 return false;
536 MO0 == LoongArchII::MO_GD_PC_HI) &&
538 return false;
541 return false;
542 if (MO0 == LoongArchII::MO_DESC_PC_HI &&
545 return false;
546 break;
547 }
548 case LoongArch::LU52I_D: {
549 auto MO = MI.getOperand(2).getTargetFlags();
552 return false;
553 break;
554 }
555 default:
556 break;
557 }
558
559 const auto &STI = MF.getSubtarget<LoongArchSubtarget>();
560 if (STI.hasFeature(LoongArch::FeatureRelax)) {
561 // When linker relaxation enabled, the following instruction patterns are
562 // prohibited from being reordered:
563 //
564 // * pcalau12i $a0, %pc_hi20(s)
565 // addi.w/d $a0, $a0, %pc_lo12(s)
566 //
567 // * pcalau12i $a0, %got_pc_hi20(s)
568 // ld.w/d $a0, $a0, %got_pc_lo12(s)
569 //
570 // * pcalau12i $a0, %ld_pc_hi20(s) | %gd_pc_hi20(s)
571 // addi.w/d $a0, $a0, %got_pc_lo12(s)
572 //
573 // * pcalau12i $a0, %desc_pc_hi20(s)
574 // addi.w/d $a0, $a0, %desc_pc_lo12(s)
575 // ld.w/d $ra, $a0, %desc_ld(s)
576 // jirl $ra, $ra, %desc_call(s)
577 unsigned AddiOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
578 unsigned LdOp = STI.is64Bit() ? LoongArch::LD_D : LoongArch::LD_W;
579 switch (MI.getOpcode()) {
580 case LoongArch::PCALAU12I: {
581 auto MO0 = LoongArchII::getDirectFlags(MI.getOperand(1));
582 auto SecondOp = std::next(MII);
583 if (MO0 == LoongArchII::MO_DESC_PC_HI) {
584 if (SecondOp == MIE || SecondOp->getOpcode() != AddiOp)
585 break;
586 auto Ld = std::next(SecondOp);
587 if (Ld == MIE || Ld->getOpcode() != LdOp)
588 break;
589 auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2));
590 auto MO2 = LoongArchII::getDirectFlags(Ld->getOperand(2));
592 return false;
593 break;
594 }
595 if (SecondOp == MIE ||
596 (SecondOp->getOpcode() != AddiOp && SecondOp->getOpcode() != LdOp))
597 break;
598 auto MO1 = LoongArchII::getDirectFlags(SecondOp->getOperand(2));
599 if (MO0 == LoongArchII::MO_PCREL_HI && SecondOp->getOpcode() == AddiOp &&
601 return false;
602 if (MO0 == LoongArchII::MO_GOT_PC_HI && SecondOp->getOpcode() == LdOp &&
604 return false;
605 if ((MO0 == LoongArchII::MO_LD_PC_HI ||
606 MO0 == LoongArchII::MO_GD_PC_HI) &&
607 SecondOp->getOpcode() == AddiOp && MO1 == LoongArchII::MO_GOT_PC_LO)
608 return false;
609 break;
610 }
611 case LoongArch::ADDI_W:
612 case LoongArch::ADDI_D: {
613 auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
615 return false;
616 break;
617 }
618 case LoongArch::LD_W:
619 case LoongArch::LD_D: {
620 auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
622 return false;
623 break;
624 }
625 case LoongArch::PseudoDESC_CALL: {
626 auto MO = LoongArchII::getDirectFlags(MI.getOperand(2));
628 return false;
629 break;
630 }
631 default:
632 break;
633 }
634 }
635
636 return true;
637}
638
640 const MachineBasicBlock *MBB,
641 const MachineFunction &MF) const {
643 return true;
644
645 if (!isSafeToMove(MI, MBB, MF))
646 return true;
647
648 return false;
649}
650
652 int *BytesRemoved) const {
653 if (BytesRemoved)
654 *BytesRemoved = 0;
655 MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
656 if (I == MBB.end())
657 return 0;
658
659 if (!I->getDesc().isBranch())
660 return 0;
661
662 // Remove the branch.
663 if (BytesRemoved)
664 *BytesRemoved += getInstSizeInBytes(*I);
665 I->eraseFromParent();
666
667 I = MBB.end();
668
669 if (I == MBB.begin())
670 return 1;
671 --I;
672 if (!I->getDesc().isConditionalBranch())
673 return 1;
674
675 // Remove the branch.
676 if (BytesRemoved)
677 *BytesRemoved += getInstSizeInBytes(*I);
678 I->eraseFromParent();
679 return 2;
680}
681
682// Inserts a branch into the end of the specific MachineBasicBlock, returning
683// the number of instructions inserted.
686 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
687 if (BytesAdded)
688 *BytesAdded = 0;
689
690 // Shouldn't be a fall through.
691 assert(TBB && "insertBranch must not be told to insert a fallthrough");
692 assert(Cond.size() <= 3 && Cond.size() != 1 &&
693 "LoongArch branch conditions have at most two components!");
694
695 // Unconditional branch.
696 if (Cond.empty()) {
697 MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(TBB);
698 if (BytesAdded)
699 *BytesAdded += getInstSizeInBytes(MI);
700 return 1;
701 }
702
703 // Either a one or two-way conditional branch.
705 for (unsigned i = 1; i < Cond.size(); ++i)
706 MIB.add(Cond[i]);
707 MIB.addMBB(TBB);
708 if (BytesAdded)
709 *BytesAdded += getInstSizeInBytes(*MIB);
710
711 // One-way conditional branch.
712 if (!FBB)
713 return 1;
714
715 // Two-way conditional branch.
716 MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(FBB);
717 if (BytesAdded)
718 *BytesAdded += getInstSizeInBytes(MI);
719 return 2;
720}
721
723 MachineBasicBlock &DestBB,
724 MachineBasicBlock &RestoreBB,
725 const DebugLoc &DL,
726 int64_t BrOffset,
727 RegScavenger *RS) const {
728 assert(RS && "RegScavenger required for long branching");
729 assert(MBB.empty() &&
730 "new block should be inserted for expanding unconditional branch");
731 assert(MBB.pred_size() == 1);
732
733 MachineFunction *MF = MBB.getParent();
734 MachineRegisterInfo &MRI = MF->getRegInfo();
738 bool Has32S = STI.hasFeature(LoongArch::Feature32S);
739
740 if (!isInt<32>(BrOffset))
742 "Branch offsets outside of the signed 32-bit range not supported");
743
744 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
745 MachineInstr *PCAI = nullptr;
746 MachineInstr *ADDI = nullptr;
747 auto II = MBB.end();
748 unsigned ADDIOp = STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W;
749
750 if (Has32S) {
751 PCAI = BuildMI(MBB, II, DL, get(LoongArch::PCALAU12I), ScratchReg)
753 ADDI = BuildMI(MBB, II, DL, get(ADDIOp), ScratchReg)
754 .addReg(ScratchReg)
756 } else {
757 MCSymbol *PCAddSymbol = MF->getContext().createNamedTempSymbol("pcadd_hi");
758 PCAI = BuildMI(MBB, II, DL, get(LoongArch::PCADDU12I), ScratchReg)
760 PCAI->setPreInstrSymbol(*MF, PCAddSymbol);
761 ADDI = BuildMI(MBB, II, DL, get(ADDIOp), ScratchReg)
762 .addReg(ScratchReg)
763 .addSym(PCAddSymbol, LoongArchII::MO_PCADD_LO);
764 }
765 BuildMI(MBB, II, DL, get(LoongArch::PseudoBRIND))
766 .addReg(ScratchReg, RegState::Kill)
767 .addImm(0);
768
769 RS->enterBasicBlockEnd(MBB);
770 Register Scav = RS->scavengeRegisterBackwards(
771 LoongArch::GPRRegClass, PCAI->getIterator(), /*RestoreAfter=*/false,
772 /*SPAdj=*/0, /*AllowSpill=*/false);
773 if (Scav != LoongArch::NoRegister)
774 RS->setRegUsed(Scav);
775 else {
776 // When there is no scavenged register, it needs to specify a register.
777 // Specify t8 register because it won't be used too often.
778 Scav = LoongArch::R20;
779 int FrameIndex = LAFI->getBranchRelaxationSpillFrameIndex();
780 if (FrameIndex == -1)
781 report_fatal_error("The function size is incorrectly estimated.");
782 storeRegToStackSlot(MBB, PCAI, Scav, /*IsKill=*/true, FrameIndex,
783 &LoongArch::GPRRegClass, Register());
784 TRI->eliminateFrameIndex(std::prev(PCAI->getIterator()),
785 /*SpAdj=*/0, /*FIOperandNum=*/1);
786 PCAI->getOperand(1).setMBB(&RestoreBB);
787 if (Has32S)
788 ADDI->getOperand(2).setMBB(&RestoreBB);
789 loadRegFromStackSlot(RestoreBB, RestoreBB.end(), Scav, FrameIndex,
790 &LoongArch::GPRRegClass, Register());
791 TRI->eliminateFrameIndex(RestoreBB.back(),
792 /*SpAdj=*/0, /*FIOperandNum=*/1);
793 }
794 MRI.replaceRegWith(ScratchReg, Scav);
795 MRI.clearVirtRegs();
796}
797
798static unsigned getOppositeBranchOpc(unsigned Opc) {
799 switch (Opc) {
800 default:
801 llvm_unreachable("Unrecognized conditional branch");
802 case LoongArch::BEQ:
803 return LoongArch::BNE;
804 case LoongArch::BNE:
805 return LoongArch::BEQ;
806 case LoongArch::BEQZ:
807 return LoongArch::BNEZ;
808 case LoongArch::BNEZ:
809 return LoongArch::BEQZ;
810 case LoongArch::BCEQZ:
811 return LoongArch::BCNEZ;
812 case LoongArch::BCNEZ:
813 return LoongArch::BCEQZ;
814 case LoongArch::BLT:
815 return LoongArch::BGE;
816 case LoongArch::BGE:
817 return LoongArch::BLT;
818 case LoongArch::BLTU:
819 return LoongArch::BGEU;
820 case LoongArch::BGEU:
821 return LoongArch::BLTU;
822 }
823}
824
827 assert((Cond.size() && Cond.size() <= 3) && "Invalid branch condition!");
828 Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm()));
829 return false;
830}
831
832std::pair<unsigned, unsigned>
834 const unsigned Mask = LoongArchII::MO_DIRECT_FLAG_MASK;
835 return std::make_pair(TF & Mask, TF & ~Mask);
836}
837
840 using namespace LoongArchII;
841 // TODO: Add more target flags.
842 static const std::pair<unsigned, const char *> TargetFlags[] = {
843 {MO_CALL, "loongarch-call"},
844 {MO_CALL_PLT, "loongarch-call-plt"},
845 {MO_PCREL_HI, "loongarch-pcrel-hi"},
846 {MO_PCREL_LO, "loongarch-pcrel-lo"},
847 {MO_PCREL64_LO, "loongarch-pcrel64-lo"},
848 {MO_PCREL64_HI, "loongarch-pcrel64-hi"},
849 {MO_GOT_PC_HI, "loongarch-got-pc-hi"},
850 {MO_GOT_PC_LO, "loongarch-got-pc-lo"},
851 {MO_GOT_PC64_LO, "loongarch-got-pc64-lo"},
852 {MO_GOT_PC64_HI, "loongarch-got-pc64-hi"},
853 {MO_LE_HI, "loongarch-le-hi"},
854 {MO_LE_LO, "loongarch-le-lo"},
855 {MO_LE64_LO, "loongarch-le64-lo"},
856 {MO_LE64_HI, "loongarch-le64-hi"},
857 {MO_IE_PC_HI, "loongarch-ie-pc-hi"},
858 {MO_IE_PC_LO, "loongarch-ie-pc-lo"},
859 {MO_IE_PC64_LO, "loongarch-ie-pc64-lo"},
860 {MO_IE_PC64_HI, "loongarch-ie-pc64-hi"},
861 {MO_LD_PC_HI, "loongarch-ld-pc-hi"},
862 {MO_GD_PC_HI, "loongarch-gd-pc-hi"},
863 {MO_CALL30, "loongarch-call30"},
864 {MO_CALL36, "loongarch-call36"},
865 {MO_DESC_PC_HI, "loongarch-desc-pc-hi"},
866 {MO_DESC_PC_LO, "loongarch-desc-pc-lo"},
867 {MO_DESC64_PC_LO, "loongarch-desc64-pc-lo"},
868 {MO_DESC64_PC_HI, "loongarch-desc64-pc-hi"},
869 {MO_DESC_LD, "loongarch-desc-ld"},
870 {MO_DESC_CALL, "loongarch-desc-call"},
871 {MO_LE_HI_R, "loongarch-le-hi-r"},
872 {MO_LE_ADD_R, "loongarch-le-add-r"},
873 {MO_LE_LO_R, "loongarch-le-lo-r"},
874 {MO_PCADD_HI, "loongarch-pcadd-hi"},
875 {MO_PCADD_LO, "loongarch-pcadd-lo"},
876 {MO_GOT_PCADD_HI, "loongarch-got-pcadd-hi"},
877 {MO_GOT_PCADD_LO, "loongarch-got-pcadd-lo"},
878 {MO_IE_PCADD_HI, "loongarch-ie-pcadd-hi"},
879 {MO_IE_PCADD_LO, "loongarch-ie-pcadd-lo"},
880 {MO_LD_PCADD_HI, "loongarch-ld-pcadd-hi"},
881 {MO_LD_PCADD_LO, "loongarch-ld-pcadd-lo"},
882 {MO_GD_PCADD_HI, "loongarch-gd-pcadd-hi"},
883 {MO_GD_PCADD_LO, "loongarch-gd-pcadd-lo"},
884 {MO_DESC_PCADD_HI, "loongarch-pcadd-desc-hi"},
885 {MO_DESC_PCADD_LO, "loongarch-pcadd-desc-lo"}};
886 return ArrayRef(TargetFlags);
887}
888
891 using namespace LoongArchII;
892 static const std::pair<unsigned, const char *> TargetFlags[] = {
893 {MO_RELAX, "loongarch-relax"}};
894 return ArrayRef(TargetFlags);
895}
896
898 Register Reg,
899 const MachineInstr &AddrI,
900 ExtAddrMode &AM) const {
901 enum MemIOffsetType {
902 Imm14Shift2,
903 Imm12,
904 Imm11Shift1,
905 Imm10Shift2,
906 Imm9Shift3,
907 Imm8,
908 Imm8Shift1,
909 Imm8Shift2,
910 Imm8Shift3
911 };
912
913 MemIOffsetType OT;
914 switch (MemI.getOpcode()) {
915 default:
916 return false;
917 case LoongArch::LDPTR_W:
918 case LoongArch::LDPTR_D:
919 case LoongArch::STPTR_W:
920 case LoongArch::STPTR_D:
921 OT = Imm14Shift2;
922 break;
923 case LoongArch::LD_B:
924 case LoongArch::LD_H:
925 case LoongArch::LD_W:
926 case LoongArch::LD_D:
927 case LoongArch::LD_BU:
928 case LoongArch::LD_HU:
929 case LoongArch::LD_WU:
930 case LoongArch::ST_B:
931 case LoongArch::ST_H:
932 case LoongArch::ST_W:
933 case LoongArch::ST_D:
934 case LoongArch::FLD_S:
935 case LoongArch::FLD_D:
936 case LoongArch::FST_S:
937 case LoongArch::FST_D:
938 case LoongArch::VLD:
939 case LoongArch::VST:
940 case LoongArch::XVLD:
941 case LoongArch::XVST:
942 case LoongArch::VLDREPL_B:
943 case LoongArch::XVLDREPL_B:
944 OT = Imm12;
945 break;
946 case LoongArch::VLDREPL_H:
947 case LoongArch::XVLDREPL_H:
948 OT = Imm11Shift1;
949 break;
950 case LoongArch::VLDREPL_W:
951 case LoongArch::XVLDREPL_W:
952 OT = Imm10Shift2;
953 break;
954 case LoongArch::VLDREPL_D:
955 case LoongArch::XVLDREPL_D:
956 OT = Imm9Shift3;
957 break;
958 case LoongArch::VSTELM_B:
959 case LoongArch::XVSTELM_B:
960 OT = Imm8;
961 break;
962 case LoongArch::VSTELM_H:
963 case LoongArch::XVSTELM_H:
964 OT = Imm8Shift1;
965 break;
966 case LoongArch::VSTELM_W:
967 case LoongArch::XVSTELM_W:
968 OT = Imm8Shift2;
969 break;
970 case LoongArch::VSTELM_D:
971 case LoongArch::XVSTELM_D:
972 OT = Imm8Shift3;
973 break;
974 }
975
976 if (MemI.getOperand(0).getReg() == Reg)
977 return false;
978
979 if ((AddrI.getOpcode() != LoongArch::ADDI_W &&
980 AddrI.getOpcode() != LoongArch::ADDI_D) ||
981 !AddrI.getOperand(1).isReg() || !AddrI.getOperand(2).isImm())
982 return false;
983
984 int64_t OldOffset = MemI.getOperand(2).getImm();
985 int64_t Disp = AddrI.getOperand(2).getImm();
986 int64_t NewOffset = OldOffset + Disp;
987 if (!STI.is64Bit())
988 NewOffset = SignExtend64<32>(NewOffset);
989
990 if (!(OT == Imm14Shift2 && isShiftedInt<14, 2>(NewOffset) && STI.hasUAL()) &&
991 !(OT == Imm12 && isInt<12>(NewOffset)) &&
992 !(OT == Imm11Shift1 && isShiftedInt<11, 1>(NewOffset)) &&
993 !(OT == Imm10Shift2 && isShiftedInt<10, 2>(NewOffset)) &&
994 !(OT == Imm9Shift3 && isShiftedInt<9, 3>(NewOffset)) &&
995 !(OT == Imm8 && isInt<8>(NewOffset)) &&
996 !(OT == Imm8Shift1 && isShiftedInt<8, 1>(NewOffset)) &&
997 !(OT == Imm8Shift2 && isShiftedInt<8, 2>(NewOffset)) &&
998 !(OT == Imm8Shift3 && isShiftedInt<8, 3>(NewOffset)))
999 return false;
1000
1001 AM.BaseReg = AddrI.getOperand(1).getReg();
1002 AM.ScaledReg = 0;
1003 AM.Scale = 0;
1004 AM.Displacement = NewOffset;
1006 return true;
1007}
1008
1011 const ExtAddrMode &AM) const {
1012 const DebugLoc &DL = MemI.getDebugLoc();
1013 MachineBasicBlock &MBB = *MemI.getParent();
1014
1015 assert(AM.ScaledReg == 0 && AM.Scale == 0 &&
1016 "Addressing mode not supported for folding");
1017
1018 unsigned MemIOp = MemI.getOpcode();
1019 switch (MemIOp) {
1020 default:
1021 return BuildMI(MBB, MemI, DL, get(MemIOp))
1022 .addReg(MemI.getOperand(0).getReg(), getDefRegState(MemI.mayLoad()))
1023 .addReg(AM.BaseReg)
1024 .addImm(AM.Displacement)
1025 .setMemRefs(MemI.memoperands())
1026 .setMIFlags(MemI.getFlags());
1027 case LoongArch::VSTELM_B:
1028 case LoongArch::VSTELM_H:
1029 case LoongArch::VSTELM_W:
1030 case LoongArch::VSTELM_D:
1031 case LoongArch::XVSTELM_B:
1032 case LoongArch::XVSTELM_H:
1033 case LoongArch::XVSTELM_W:
1034 case LoongArch::XVSTELM_D:
1035 return BuildMI(MBB, MemI, DL, get(MemIOp))
1036 .addReg(MemI.getOperand(0).getReg())
1037 .addReg(AM.BaseReg)
1038 .addImm(AM.Displacement)
1039 .addImm(MemI.getOperand(3).getImm())
1040 .setMemRefs(MemI.memoperands())
1041 .setMIFlags(MemI.getFlags());
1042 }
1043}
1044
1045// Returns true if this is the sext.w pattern, addi.w rd, rs, 0.
1047 return MI.getOpcode() == LoongArch::ADDI_W && MI.getOperand(1).isReg() &&
1048 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0;
1049}
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static unsigned getOppositeBranchOpc(unsigned Opcode)
IRTranslator LLVM IR MI
static cl::opt< bool > DisableRelocSched("loongarch-disable-reloc-sched", cl::desc("Disable scheduling of instructions with target flags"), cl::init(false), cl::Hidden)
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:483
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
A debug info location.
Definition DebugLoc.h:123
void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register DstReg, Register SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableBitmaskMachineOperandTargetFlags() const override
const LoongArchSubtarget & STI
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
bool isSafeToMove(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool IsKill, int FrameIndex, const TargetRegisterClass *RC, Register VReg, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool isAsCheapAsAMove(const MachineInstr &MI) const override
MCInst getNop() const override
LoongArchInstrInfo(const LoongArchSubtarget &STI)
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) const override
Register isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override
void movImm(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, Register DstReg, uint64_t Val, MachineInstr::MIFlag Flag=MachineInstr::NoFlags) const
unsigned insertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef< MachineOperand > Cond, const DebugLoc &dl, int *BytesAdded=nullptr) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DstReg, int FrameIndex, const TargetRegisterClass *RC, Register VReg, unsigned SubReg=0, MachineInstr::MIFlag Flags=MachineInstr::NoFlags) const override
Register isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
bool canFoldIntoAddrMode(const MachineInstr &MemI, Register Reg, const MachineInstr &AddrI, ExtAddrMode &AM) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) const override
MachineInstr * emitLdStWithAddr(MachineInstr &MemI, const ExtAddrMode &AM) const override
LoongArchMachineFunctionInfo - This class is derived from MachineFunctionInfo and contains private Lo...
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition MCAsmInfo.h:64
LLVM_ABI MCSymbol * createNamedTempSymbol()
Create a temporary symbol with a unique name whose name cannot be omitted in the symbol table.
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
Describe properties that are true of each instruction in the target description file.
bool isConditionalBranch() const
Return true if this is a branch which may fall through to the next instruction or may transfer contro...
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
Align getObjectAlign(int ObjectIdx) const
Return the alignment of the specified stack object.
int64_t getObjectSize(int ObjectIdx) const
Return the size of the specified object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & setMemRefs(ArrayRef< MachineMemOperand * > MMOs) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & add(const MachineOperand &MO) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & setMIFlags(unsigned Flags) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineBasicBlock * getParent() const
LLVM_ABI void setPreInstrSymbol(MachineFunction &MF, MCSymbol *Symbol)
Set a symbol that will be emitted just prior to the instruction itself.
LLVM_ABI unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
bool mayLoad(QueryType Type=AnyInBundle) const
Return true if this instruction could possibly read memory.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
ArrayRef< MachineMemOperand * > memoperands() const
Access to memory operands of the instruction.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
uint32_t getFlags() const
Return the MI flags bitvector.
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI Register createVirtualRegister(const TargetRegisterClass *RegClass, StringRef Name="")
createVirtualRegister - Create and return a new virtual register in the function with the specified r...
LLVM_ABI void clearVirtRegs()
clearVirtRegs - Remove all virtual registers (after physreg assignment).
LLVM_ABI void replaceRegWith(Register FromReg, Register ToReg)
replaceRegWith - Replace all instances of FromReg with ToReg in the machine function.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
MI-level Statepoint operands.
Definition StackMaps.h:159
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
Definition StackMaps.h:208
virtual bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const
Test if the given instruction should be considered a scheduling boundary.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Target - Wrapper for Target specific information.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition TypeSize.h:343
static constexpr TypeSize getZero()
Definition TypeSize.h:349
self_iterator getIterator()
Definition ilist_node.h:123
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
static unsigned getDirectFlags(const MachineOperand &MO)
InstSeq generateInstSeq(int64_t Val)
bool isSEXT_W(const MachineInstr &MI)
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
Definition MathExtras.h:165
@ Kill
The last use of a register.
constexpr RegState getKillRegState(bool B)
Op::Description Desc
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
constexpr RegState getDefRegState(bool B)
ArrayRef(const T &OneElt) -> ArrayRef< T >
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
Definition MathExtras.h:182
constexpr int64_t SignExtend64(uint64_t x)
Sign-extend the number in the bottom B bits of X to a 64-bit integer.
Definition MathExtras.h:572
Used to describe addressing mode similar to ExtAddrMode in CodeGenPrepare.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.