LLVM 20.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"
22
23using namespace llvm;
24
25#define GET_INSTRINFO_CTOR_DTOR
26#include "LoongArchGenInstrInfo.inc"
27
29 : LoongArchGenInstrInfo(LoongArch::ADJCALLSTACKDOWN,
30 LoongArch::ADJCALLSTACKUP),
31 STI(STI) {}
32
34 return MCInstBuilder(LoongArch::ANDI)
35 .addReg(LoongArch::R0)
36 .addReg(LoongArch::R0)
37 .addImm(0);
38}
39
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
115 bool IsKill, int FI, const TargetRegisterClass *RC,
116 const TargetRegisterInfo *TRI, Register VReg) const {
118 MachineFrameInfo &MFI = MF->getFrameInfo();
119
120 unsigned Opcode;
121 if (LoongArch::GPRRegClass.hasSubClassEq(RC))
122 Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32
123 ? LoongArch::ST_W
124 : LoongArch::ST_D;
125 else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
126 Opcode = LoongArch::FST_S;
127 else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
128 Opcode = LoongArch::FST_D;
129 else if (LoongArch::LSX128RegClass.hasSubClassEq(RC))
130 Opcode = LoongArch::VST;
131 else if (LoongArch::LASX256RegClass.hasSubClassEq(RC))
132 Opcode = LoongArch::XVST;
133 else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
134 Opcode = LoongArch::PseudoST_CFR;
135 else
136 llvm_unreachable("Can't store this register to stack slot");
137
140 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
141
142 BuildMI(MBB, I, DebugLoc(), get(Opcode))
143 .addReg(SrcReg, getKillRegState(IsKill))
144 .addFrameIndex(FI)
145 .addImm(0)
146 .addMemOperand(MMO);
147}
148
151 Register DstReg, int FI,
152 const TargetRegisterClass *RC,
153 const TargetRegisterInfo *TRI,
154 Register VReg) const {
156 MachineFrameInfo &MFI = MF->getFrameInfo();
157
158 unsigned Opcode;
159 if (LoongArch::GPRRegClass.hasSubClassEq(RC))
160 Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32
161 ? LoongArch::LD_W
162 : LoongArch::LD_D;
163 else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
164 Opcode = LoongArch::FLD_S;
165 else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
166 Opcode = LoongArch::FLD_D;
167 else if (LoongArch::LSX128RegClass.hasSubClassEq(RC))
168 Opcode = LoongArch::VLD;
169 else if (LoongArch::LASX256RegClass.hasSubClassEq(RC))
170 Opcode = LoongArch::XVLD;
171 else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
172 Opcode = LoongArch::PseudoLD_CFR;
173 else
174 llvm_unreachable("Can't load this register from stack slot");
175
178 MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
179
180 BuildMI(MBB, I, DebugLoc(), get(Opcode), DstReg)
181 .addFrameIndex(FI)
182 .addImm(0)
183 .addMemOperand(MMO);
184}
185
188 const DebugLoc &DL, Register DstReg,
189 uint64_t Val, MachineInstr::MIFlag Flag) const {
190 Register SrcReg = LoongArch::R0;
191
192 if (!STI.is64Bit() && !isInt<32>(Val))
193 report_fatal_error("Should only materialize 32-bit constants for LA32");
194
195 auto Seq = LoongArchMatInt::generateInstSeq(Val);
196 assert(!Seq.empty());
197
198 for (auto &Inst : Seq) {
199 switch (Inst.Opc) {
200 case LoongArch::LU12I_W:
201 BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
202 .addImm(Inst.Imm)
203 .setMIFlag(Flag);
204 break;
205 case LoongArch::ADDI_W:
206 case LoongArch::ORI:
207 case LoongArch::LU32I_D: // "rj" is needed due to InstrInfo pattern
208 case LoongArch::LU52I_D:
209 BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
210 .addReg(SrcReg, RegState::Kill)
211 .addImm(Inst.Imm)
212 .setMIFlag(Flag);
213 break;
214 case LoongArch::BSTRINS_D:
215 BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
216 .addReg(SrcReg, RegState::Kill)
217 .addReg(SrcReg, RegState::Kill)
218 .addImm(Inst.Imm >> 32)
219 .addImm(Inst.Imm & 0xFF)
220 .setMIFlag(Flag);
221 break;
222 default:
223 assert(false && "Unknown insn emitted by LoongArchMatInt");
224 }
225
226 // Only the first instruction has $zero as its source.
227 SrcReg = DstReg;
228 }
229}
230
232 unsigned Opcode = MI.getOpcode();
233
234 if (Opcode == TargetOpcode::INLINEASM ||
235 Opcode == TargetOpcode::INLINEASM_BR) {
236 const MachineFunction *MF = MI.getParent()->getParent();
237 const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo();
238 return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI);
239 }
240
241 unsigned NumBytes = 0;
242 const MCInstrDesc &Desc = MI.getDesc();
243
244 // Size should be preferably set in
245 // llvm/lib/Target/LoongArch/LoongArch*InstrInfo.td (default case).
246 // Specific cases handle instructions of variable sizes.
247 switch (Desc.getOpcode()) {
248 default:
249 return Desc.getSize();
250 case TargetOpcode::STATEPOINT:
251 NumBytes = StatepointOpers(&MI).getNumPatchBytes();
252 assert(NumBytes % 4 == 0 && "Invalid number of NOP bytes requested!");
253 // No patch bytes means a normal call inst (i.e. `bl`) is emitted.
254 if (NumBytes == 0)
255 NumBytes = 4;
256 break;
257 }
258 return NumBytes;
259}
260
262 const unsigned Opcode = MI.getOpcode();
263 switch (Opcode) {
264 default:
265 break;
266 case LoongArch::ADDI_D:
267 case LoongArch::ORI:
268 case LoongArch::XORI:
269 return (MI.getOperand(1).isReg() &&
270 MI.getOperand(1).getReg() == LoongArch::R0) ||
271 (MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0);
272 }
273 return MI.isAsCheapAsAMove();
274}
275
278 assert(MI.getDesc().isBranch() && "Unexpected opcode!");
279 // The branch target is always the last operand.
280 return MI.getOperand(MI.getNumExplicitOperands() - 1).getMBB();
281}
282
285 // Block ends with fall-through condbranch.
286 assert(LastInst.getDesc().isConditionalBranch() &&
287 "Unknown conditional branch");
288 int NumOp = LastInst.getNumExplicitOperands();
289 Target = LastInst.getOperand(NumOp - 1).getMBB();
290
291 Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode()));
292 for (int i = 0; i < NumOp - 1; i++)
293 Cond.push_back(LastInst.getOperand(i));
294}
295
298 MachineBasicBlock *&FBB,
300 bool AllowModify) const {
301 TBB = FBB = nullptr;
302 Cond.clear();
303
304 // If the block has no terminators, it just falls into the block after it.
306 if (I == MBB.end() || !isUnpredicatedTerminator(*I))
307 return false;
308
309 // Count the number of terminators and find the first unconditional or
310 // indirect branch.
311 MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
312 int NumTerminators = 0;
313 for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
314 J++) {
315 NumTerminators++;
316 if (J->getDesc().isUnconditionalBranch() ||
317 J->getDesc().isIndirectBranch()) {
318 FirstUncondOrIndirectBr = J.getReverse();
319 }
320 }
321
322 // If AllowModify is true, we can erase any terminators after
323 // FirstUncondOrIndirectBR.
324 if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
325 while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
326 std::next(FirstUncondOrIndirectBr)->eraseFromParent();
327 NumTerminators--;
328 }
329 I = FirstUncondOrIndirectBr;
330 }
331
332 // Handle a single unconditional branch.
333 if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
335 return false;
336 }
337
338 // Handle a single conditional branch.
339 if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
341 return false;
342 }
343
344 // Handle a conditional branch followed by an unconditional branch.
345 if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
346 I->getDesc().isUnconditionalBranch()) {
347 parseCondBranch(*std::prev(I), TBB, Cond);
348 FBB = getBranchDestBlock(*I);
349 return false;
350 }
351
352 // Otherwise, we can't handle this.
353 return true;
354}
355
357 int64_t BrOffset) const {
358 switch (BranchOp) {
359 default:
360 llvm_unreachable("Unknown branch instruction!");
361 case LoongArch::BEQ:
362 case LoongArch::BNE:
363 case LoongArch::BLT:
364 case LoongArch::BGE:
365 case LoongArch::BLTU:
366 case LoongArch::BGEU:
367 return isInt<18>(BrOffset);
368 case LoongArch::BEQZ:
369 case LoongArch::BNEZ:
370 case LoongArch::BCEQZ:
371 case LoongArch::BCNEZ:
372 return isInt<23>(BrOffset);
373 case LoongArch::B:
374 case LoongArch::PseudoBR:
375 return isInt<28>(BrOffset);
376 }
377}
378
380 const MachineBasicBlock *MBB,
381 const MachineFunction &MF) const {
383 return true;
384
385 auto MII = MI.getIterator();
386 auto MIE = MBB->end();
387
388 // According to psABI v2.30:
389 //
390 // https://github.com/loongson/la-abi-specs/releases/tag/v2.30
391 //
392 // The following instruction patterns are prohibited from being reordered:
393 //
394 // * pcalau12i $a0, %pc_hi20(s)
395 // addi.d $a1, $zero, %pc_lo12(s)
396 // lu32i.d $a1, %pc64_lo20(s)
397 // lu52i.d $a1, $a1, %pc64_hi12(s)
398 //
399 // * pcalau12i $a0, %got_pc_hi20(s) | %ld_pc_hi20(s) | %gd_pc_hi20(s)
400 // addi.d $a1, $zero, %got_pc_lo12(s)
401 // lu32i.d $a1, %got64_pc_lo20(s)
402 // lu52i.d $a1, $a1, %got64_pc_hi12(s)
403 //
404 // * pcalau12i $a0, %ie_pc_hi20(s)
405 // addi.d $a1, $zero, %ie_pc_lo12(s)
406 // lu32i.d $a1, %ie64_pc_lo20(s)
407 // lu52i.d $a1, $a1, %ie64_pc_hi12(s)
408 //
409 // For simplicity, only pcalau12i and lu52i.d are marked as scheduling
410 // boundaries, and the instructions between them are guaranteed to be
411 // ordered according to data dependencies.
412 switch (MI.getOpcode()) {
413 case LoongArch::PCALAU12I: {
414 auto AddI = std::next(MII);
415 if (AddI == MIE || AddI->getOpcode() != LoongArch::ADDI_D)
416 break;
417 auto Lu32I = std::next(AddI);
418 if (Lu32I == MIE || Lu32I->getOpcode() != LoongArch::LU32I_D)
419 break;
420 auto MO0 = MI.getOperand(1).getTargetFlags();
421 auto MO1 = AddI->getOperand(2).getTargetFlags();
422 auto MO2 = Lu32I->getOperand(2).getTargetFlags();
425 return true;
427 MO0 == LoongArchII::MO_GD_PC_HI) &&
429 return true;
432 return true;
433 break;
434 }
435 case LoongArch::LU52I_D: {
436 auto MO = MI.getOperand(2).getTargetFlags();
439 return true;
440 break;
441 }
442 default:
443 break;
444 }
445
446 return false;
447}
448
450 int *BytesRemoved) const {
451 if (BytesRemoved)
452 *BytesRemoved = 0;
454 if (I == MBB.end())
455 return 0;
456
457 if (!I->getDesc().isBranch())
458 return 0;
459
460 // Remove the branch.
461 if (BytesRemoved)
462 *BytesRemoved += getInstSizeInBytes(*I);
463 I->eraseFromParent();
464
465 I = MBB.end();
466
467 if (I == MBB.begin())
468 return 1;
469 --I;
470 if (!I->getDesc().isConditionalBranch())
471 return 1;
472
473 // Remove the branch.
474 if (BytesRemoved)
475 *BytesRemoved += getInstSizeInBytes(*I);
476 I->eraseFromParent();
477 return 2;
478}
479
480// Inserts a branch into the end of the specific MachineBasicBlock, returning
481// the number of instructions inserted.
484 ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
485 if (BytesAdded)
486 *BytesAdded = 0;
487
488 // Shouldn't be a fall through.
489 assert(TBB && "insertBranch must not be told to insert a fallthrough");
490 assert(Cond.size() <= 3 && Cond.size() != 1 &&
491 "LoongArch branch conditions have at most two components!");
492
493 // Unconditional branch.
494 if (Cond.empty()) {
495 MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(TBB);
496 if (BytesAdded)
497 *BytesAdded += getInstSizeInBytes(MI);
498 return 1;
499 }
500
501 // Either a one or two-way conditional branch.
502 MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm()));
503 for (unsigned i = 1; i < Cond.size(); ++i)
504 MIB.add(Cond[i]);
505 MIB.addMBB(TBB);
506 if (BytesAdded)
507 *BytesAdded += getInstSizeInBytes(*MIB);
508
509 // One-way conditional branch.
510 if (!FBB)
511 return 1;
512
513 // Two-way conditional branch.
514 MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(FBB);
515 if (BytesAdded)
516 *BytesAdded += getInstSizeInBytes(MI);
517 return 2;
518}
519
521 MachineBasicBlock &DestBB,
522 MachineBasicBlock &RestoreBB,
523 const DebugLoc &DL,
524 int64_t BrOffset,
525 RegScavenger *RS) const {
526 assert(RS && "RegScavenger required for long branching");
527 assert(MBB.empty() &&
528 "new block should be inserted for expanding unconditional branch");
529 assert(MBB.pred_size() == 1);
530
536
537 if (!isInt<32>(BrOffset))
539 "Branch offsets outside of the signed 32-bit range not supported");
540
541 Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
542 auto II = MBB.end();
543
544 MachineInstr &PCALAU12I =
545 *BuildMI(MBB, II, DL, get(LoongArch::PCALAU12I), ScratchReg)
547 MachineInstr &ADDI =
548 *BuildMI(MBB, II, DL,
549 get(STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W),
550 ScratchReg)
551 .addReg(ScratchReg)
553 BuildMI(MBB, II, DL, get(LoongArch::PseudoBRIND))
554 .addReg(ScratchReg, RegState::Kill)
555 .addImm(0);
556
559 LoongArch::GPRRegClass, PCALAU12I.getIterator(), /*RestoreAfter=*/false,
560 /*SPAdj=*/0, /*AllowSpill=*/false);
561 if (Scav != LoongArch::NoRegister)
562 RS->setRegUsed(Scav);
563 else {
564 // When there is no scavenged register, it needs to specify a register.
565 // Specify t8 register because it won't be used too often.
566 Scav = LoongArch::R20;
567 int FrameIndex = LAFI->getBranchRelaxationSpillFrameIndex();
568 if (FrameIndex == -1)
569 report_fatal_error("The function size is incorrectly estimated.");
570 storeRegToStackSlot(MBB, PCALAU12I, Scav, /*IsKill=*/true, FrameIndex,
571 &LoongArch::GPRRegClass, TRI, Register());
572 TRI->eliminateFrameIndex(std::prev(PCALAU12I.getIterator()),
573 /*SpAdj=*/0, /*FIOperandNum=*/1);
574 PCALAU12I.getOperand(1).setMBB(&RestoreBB);
575 ADDI.getOperand(2).setMBB(&RestoreBB);
576 loadRegFromStackSlot(RestoreBB, RestoreBB.end(), Scav, FrameIndex,
577 &LoongArch::GPRRegClass, TRI, Register());
578 TRI->eliminateFrameIndex(RestoreBB.back(),
579 /*SpAdj=*/0, /*FIOperandNum=*/1);
580 }
581 MRI.replaceRegWith(ScratchReg, Scav);
582 MRI.clearVirtRegs();
583}
584
585static unsigned getOppositeBranchOpc(unsigned Opc) {
586 switch (Opc) {
587 default:
588 llvm_unreachable("Unrecognized conditional branch");
589 case LoongArch::BEQ:
590 return LoongArch::BNE;
591 case LoongArch::BNE:
592 return LoongArch::BEQ;
593 case LoongArch::BEQZ:
594 return LoongArch::BNEZ;
595 case LoongArch::BNEZ:
596 return LoongArch::BEQZ;
597 case LoongArch::BCEQZ:
598 return LoongArch::BCNEZ;
599 case LoongArch::BCNEZ:
600 return LoongArch::BCEQZ;
601 case LoongArch::BLT:
602 return LoongArch::BGE;
603 case LoongArch::BGE:
604 return LoongArch::BLT;
605 case LoongArch::BLTU:
606 return LoongArch::BGEU;
607 case LoongArch::BGEU:
608 return LoongArch::BLTU;
609 }
610}
611
614 assert((Cond.size() && Cond.size() <= 3) && "Invalid branch condition!");
615 Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm()));
616 return false;
617}
618
619std::pair<unsigned, unsigned>
621 return std::make_pair(TF, 0u);
622}
623
626 using namespace LoongArchII;
627 // TODO: Add more target flags.
628 static const std::pair<unsigned, const char *> TargetFlags[] = {
629 {MO_CALL, "loongarch-call"},
630 {MO_CALL_PLT, "loongarch-call-plt"},
631 {MO_PCREL_HI, "loongarch-pcrel-hi"},
632 {MO_PCREL_LO, "loongarch-pcrel-lo"},
633 {MO_PCREL64_LO, "loongarch-pcrel64-lo"},
634 {MO_PCREL64_HI, "loongarch-pcrel64-hi"},
635 {MO_GOT_PC_HI, "loongarch-got-pc-hi"},
636 {MO_GOT_PC_LO, "loongarch-got-pc-lo"},
637 {MO_GOT_PC64_LO, "loongarch-got-pc64-lo"},
638 {MO_GOT_PC64_HI, "loongarch-got-pc64-hi"},
639 {MO_LE_HI, "loongarch-le-hi"},
640 {MO_LE_LO, "loongarch-le-lo"},
641 {MO_LE64_LO, "loongarch-le64-lo"},
642 {MO_LE64_HI, "loongarch-le64-hi"},
643 {MO_IE_PC_HI, "loongarch-ie-pc-hi"},
644 {MO_IE_PC_LO, "loongarch-ie-pc-lo"},
645 {MO_IE_PC64_LO, "loongarch-ie-pc64-lo"},
646 {MO_IE_PC64_HI, "loongarch-ie-pc64-hi"},
647 {MO_DESC_PC_HI, "loongarch-desc-pc-hi"},
648 {MO_DESC_PC_LO, "loongarch-desc-pc-lo"},
649 {MO_DESC64_PC_LO, "loongarch-desc64-pc-lo"},
650 {MO_DESC64_PC_HI, "loongarch-desc64-pc-hi"},
651 {MO_DESC_LD, "loongarch-desc-ld"},
652 {MO_DESC_CALL, "loongarch-desc-call"},
653 {MO_LD_PC_HI, "loongarch-ld-pc-hi"},
654 {MO_GD_PC_HI, "loongarch-gd-pc-hi"}};
655 return ArrayRef(TargetFlags);
656}
657
658// Returns true if this is the sext.w pattern, addi.w rd, rs, 0.
660 return MI.getOpcode() == LoongArch::ADDI_W && MI.getOperand(1).isReg() &&
661 MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0;
662}
unsigned const MachineRegisterInfo * MRI
static void parseCondBranch(MachineInstr *LastInst, MachineBasicBlock *&Target, SmallVectorImpl< MachineOperand > &Cond)
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
static unsigned getOppositeBranchOpc(unsigned Opcode)
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
unsigned const TargetRegisterInfo * TRI
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
const SmallVectorImpl< MachineOperand > & Cond
This file declares the machine register scavenger class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition: Value.cpp:469
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
A debug info location.
Definition: DebugLoc.h:33
void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register DstReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
const LoongArchSubtarget & STI
bool reverseBranchCondition(SmallVectorImpl< MachineOperand > &Cond) const override
bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl< MachineOperand > &Cond, bool AllowModify) const override
std::pair< unsigned, unsigned > decomposeMachineOperandsTargetFlags(unsigned TF) const override
bool isAsCheapAsAMove(const MachineInstr &MI) const override
LoongArchInstrInfo(LoongArchSubtarget &STI)
MCInst getNop() const override
ArrayRef< std::pair< unsigned, const char * > > getSerializableDirectMachineOperandTargetFlags() const override
unsigned removeBranch(MachineBasicBlock &MBB, int *BytesRemoved=nullptr) 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 copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg, bool KillSrc, bool RenamableDest=false, bool RenamableSrc=false) const override
void insertIndirectBranch(MachineBasicBlock &MBB, MachineBasicBlock &NewDestBB, MachineBasicBlock &RestoreBB, const DebugLoc &DL, int64_t BrOffset, RegScavenger *RS) const override
void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, Register SrcReg, bool IsKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI, Register VReg) const override
bool isSchedulingBoundary(const MachineInstr &MI, const MachineBasicBlock *MBB, const MachineFunction &MF) const override
bool isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const override
unsigned getInstSizeInBytes(const MachineInstr &MI) const override
MachineBasicBlock * getBranchDestBlock(const MachineInstr &MI) 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:56
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
Definition: MCInstBuilder.h:37
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
Definition: MCInstBuilder.h:43
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:185
Describe properties that are true of each instruction in the target description file.
Definition: MCInstrDesc.h:198
bool isConditionalBranch() const
Return true if this is a branch which may fall through to the next instruction or may transfer contro...
Definition: MCInstrDesc.h:317
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
unsigned pred_size() const
reverse_iterator rend()
iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
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.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
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 & 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 & addFrameIndex(int Idx) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
reverse_iterator getReverse() const
Get a reverse iterator to the same node.
Representation of each machine instruction.
Definition: MachineInstr.h:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:575
unsigned getNumExplicitOperands() const
Returns the number of non-implicit operands.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
Definition: MachineInstr.h:572
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:585
A description of a memory reference used in the backend.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineBasicBlock * getMBB() const
void setMBB(MachineBasicBlock *MBB)
static MachineOperand CreateImm(int64_t Val)
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
void enterBasicBlockEnd(MachineBasicBlock &MBB)
Start tracking liveness from the end of basic block MBB.
void setRegUsed(Register Reg, LaneBitmask LaneMask=LaneBitmask::getAll())
Tell the scavenger a register is used.
Register scavengeRegisterBackwards(const TargetRegisterClass &RC, MachineBasicBlock::iterator To, bool RestoreAfter, int SPAdj, bool AllowSpill=true)
Make a register of the specific register class available from the current position backwards to the p...
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
MI-level Statepoint operands.
Definition: StackMaps.h:158
uint32_t getNumPatchBytes() const
Return the number of patchable bytes the given statepoint should emit.
Definition: StackMaps.h:207
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
getRegisterInfo - If register information is available, return it.
Target - Wrapper for Target specific information.
self_iterator getIterator()
Definition: ilist_node.h:132
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
InstSeq generateInstSeq(int64_t Val)
bool isSEXT_W(const MachineInstr &MI)
@ Kill
The last use of a register.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
decltype(auto) get(const PointerIntPair< PointerTy, IntBits, IntType, PtrTraits, Info > &Pair)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
unsigned getKillRegState(bool B)
Description of the encoding of one expression Op.
static MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.