Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
35267 views
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/MC/MCInstBuilder.h"
21
22
using namespace llvm;
23
24
#define GET_INSTRINFO_CTOR_DTOR
25
#include "LoongArchGenInstrInfo.inc"
26
27
LoongArchInstrInfo::LoongArchInstrInfo(LoongArchSubtarget &STI)
28
: LoongArchGenInstrInfo(LoongArch::ADJCALLSTACKDOWN,
29
LoongArch::ADJCALLSTACKUP),
30
STI(STI) {}
31
32
MCInst LoongArchInstrInfo::getNop() const {
33
return MCInstBuilder(LoongArch::ANDI)
34
.addReg(LoongArch::R0)
35
.addReg(LoongArch::R0)
36
.addImm(0);
37
}
38
39
void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
40
MachineBasicBlock::iterator MBBI,
41
const DebugLoc &DL, MCRegister DstReg,
42
MCRegister SrcReg, bool KillSrc) const {
43
if (LoongArch::GPRRegClass.contains(DstReg, SrcReg)) {
44
BuildMI(MBB, MBBI, DL, get(LoongArch::OR), DstReg)
45
.addReg(SrcReg, getKillRegState(KillSrc))
46
.addReg(LoongArch::R0);
47
return;
48
}
49
50
// VR->VR copies.
51
if (LoongArch::LSX128RegClass.contains(DstReg, SrcReg)) {
52
BuildMI(MBB, MBBI, DL, get(LoongArch::VORI_B), DstReg)
53
.addReg(SrcReg, getKillRegState(KillSrc))
54
.addImm(0);
55
return;
56
}
57
58
// XR->XR copies.
59
if (LoongArch::LASX256RegClass.contains(DstReg, SrcReg)) {
60
BuildMI(MBB, MBBI, DL, get(LoongArch::XVORI_B), DstReg)
61
.addReg(SrcReg, getKillRegState(KillSrc))
62
.addImm(0);
63
return;
64
}
65
66
// GPR->CFR copy.
67
if (LoongArch::CFRRegClass.contains(DstReg) &&
68
LoongArch::GPRRegClass.contains(SrcReg)) {
69
BuildMI(MBB, MBBI, DL, get(LoongArch::MOVGR2CF), DstReg)
70
.addReg(SrcReg, getKillRegState(KillSrc));
71
return;
72
}
73
// CFR->GPR copy.
74
if (LoongArch::GPRRegClass.contains(DstReg) &&
75
LoongArch::CFRRegClass.contains(SrcReg)) {
76
BuildMI(MBB, MBBI, DL, get(LoongArch::MOVCF2GR), DstReg)
77
.addReg(SrcReg, getKillRegState(KillSrc));
78
return;
79
}
80
// CFR->CFR copy.
81
if (LoongArch::CFRRegClass.contains(DstReg, SrcReg)) {
82
BuildMI(MBB, MBBI, DL, get(LoongArch::PseudoCopyCFR), DstReg)
83
.addReg(SrcReg, getKillRegState(KillSrc));
84
return;
85
}
86
87
// FPR->FPR copies.
88
unsigned Opc;
89
if (LoongArch::FPR32RegClass.contains(DstReg, SrcReg)) {
90
Opc = LoongArch::FMOV_S;
91
} else if (LoongArch::FPR64RegClass.contains(DstReg, SrcReg)) {
92
Opc = LoongArch::FMOV_D;
93
} else if (LoongArch::GPRRegClass.contains(DstReg) &&
94
LoongArch::FPR32RegClass.contains(SrcReg)) {
95
// FPR32 -> GPR copies
96
Opc = LoongArch::MOVFR2GR_S;
97
} else if (LoongArch::GPRRegClass.contains(DstReg) &&
98
LoongArch::FPR64RegClass.contains(SrcReg)) {
99
// FPR64 -> GPR copies
100
Opc = LoongArch::MOVFR2GR_D;
101
} else {
102
// TODO: support other copies.
103
llvm_unreachable("Impossible reg-to-reg copy");
104
}
105
106
BuildMI(MBB, MBBI, DL, get(Opc), DstReg)
107
.addReg(SrcReg, getKillRegState(KillSrc));
108
}
109
110
void LoongArchInstrInfo::storeRegToStackSlot(
111
MachineBasicBlock &MBB, MachineBasicBlock::iterator I, Register SrcReg,
112
bool IsKill, int FI, const TargetRegisterClass *RC,
113
const TargetRegisterInfo *TRI, Register VReg) const {
114
MachineFunction *MF = MBB.getParent();
115
MachineFrameInfo &MFI = MF->getFrameInfo();
116
117
unsigned Opcode;
118
if (LoongArch::GPRRegClass.hasSubClassEq(RC))
119
Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32
120
? LoongArch::ST_W
121
: LoongArch::ST_D;
122
else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
123
Opcode = LoongArch::FST_S;
124
else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
125
Opcode = LoongArch::FST_D;
126
else if (LoongArch::LSX128RegClass.hasSubClassEq(RC))
127
Opcode = LoongArch::VST;
128
else if (LoongArch::LASX256RegClass.hasSubClassEq(RC))
129
Opcode = LoongArch::XVST;
130
else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
131
Opcode = LoongArch::PseudoST_CFR;
132
else
133
llvm_unreachable("Can't store this register to stack slot");
134
135
MachineMemOperand *MMO = MF->getMachineMemOperand(
136
MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,
137
MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
138
139
BuildMI(MBB, I, DebugLoc(), get(Opcode))
140
.addReg(SrcReg, getKillRegState(IsKill))
141
.addFrameIndex(FI)
142
.addImm(0)
143
.addMemOperand(MMO);
144
}
145
146
void LoongArchInstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
147
MachineBasicBlock::iterator I,
148
Register DstReg, int FI,
149
const TargetRegisterClass *RC,
150
const TargetRegisterInfo *TRI,
151
Register VReg) const {
152
MachineFunction *MF = MBB.getParent();
153
MachineFrameInfo &MFI = MF->getFrameInfo();
154
155
unsigned Opcode;
156
if (LoongArch::GPRRegClass.hasSubClassEq(RC))
157
Opcode = TRI->getRegSizeInBits(LoongArch::GPRRegClass) == 32
158
? LoongArch::LD_W
159
: LoongArch::LD_D;
160
else if (LoongArch::FPR32RegClass.hasSubClassEq(RC))
161
Opcode = LoongArch::FLD_S;
162
else if (LoongArch::FPR64RegClass.hasSubClassEq(RC))
163
Opcode = LoongArch::FLD_D;
164
else if (LoongArch::LSX128RegClass.hasSubClassEq(RC))
165
Opcode = LoongArch::VLD;
166
else if (LoongArch::LASX256RegClass.hasSubClassEq(RC))
167
Opcode = LoongArch::XVLD;
168
else if (LoongArch::CFRRegClass.hasSubClassEq(RC))
169
Opcode = LoongArch::PseudoLD_CFR;
170
else
171
llvm_unreachable("Can't load this register from stack slot");
172
173
MachineMemOperand *MMO = MF->getMachineMemOperand(
174
MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,
175
MFI.getObjectSize(FI), MFI.getObjectAlign(FI));
176
177
BuildMI(MBB, I, DebugLoc(), get(Opcode), DstReg)
178
.addFrameIndex(FI)
179
.addImm(0)
180
.addMemOperand(MMO);
181
}
182
183
void LoongArchInstrInfo::movImm(MachineBasicBlock &MBB,
184
MachineBasicBlock::iterator MBBI,
185
const DebugLoc &DL, Register DstReg,
186
uint64_t Val, MachineInstr::MIFlag Flag) const {
187
Register SrcReg = LoongArch::R0;
188
189
if (!STI.is64Bit() && !isInt<32>(Val))
190
report_fatal_error("Should only materialize 32-bit constants for LA32");
191
192
auto Seq = LoongArchMatInt::generateInstSeq(Val);
193
assert(!Seq.empty());
194
195
for (auto &Inst : Seq) {
196
switch (Inst.Opc) {
197
case LoongArch::LU12I_W:
198
BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
199
.addImm(Inst.Imm)
200
.setMIFlag(Flag);
201
break;
202
case LoongArch::ADDI_W:
203
case LoongArch::ORI:
204
case LoongArch::LU32I_D: // "rj" is needed due to InstrInfo pattern
205
case LoongArch::LU52I_D:
206
BuildMI(MBB, MBBI, DL, get(Inst.Opc), DstReg)
207
.addReg(SrcReg, RegState::Kill)
208
.addImm(Inst.Imm)
209
.setMIFlag(Flag);
210
break;
211
default:
212
assert(false && "Unknown insn emitted by LoongArchMatInt");
213
}
214
215
// Only the first instruction has $zero as its source.
216
SrcReg = DstReg;
217
}
218
}
219
220
unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
221
unsigned Opcode = MI.getOpcode();
222
223
if (Opcode == TargetOpcode::INLINEASM ||
224
Opcode == TargetOpcode::INLINEASM_BR) {
225
const MachineFunction *MF = MI.getParent()->getParent();
226
const MCAsmInfo *MAI = MF->getTarget().getMCAsmInfo();
227
return getInlineAsmLength(MI.getOperand(0).getSymbolName(), *MAI);
228
}
229
return MI.getDesc().getSize();
230
}
231
232
bool LoongArchInstrInfo::isAsCheapAsAMove(const MachineInstr &MI) const {
233
const unsigned Opcode = MI.getOpcode();
234
switch (Opcode) {
235
default:
236
break;
237
case LoongArch::ADDI_D:
238
case LoongArch::ORI:
239
case LoongArch::XORI:
240
return (MI.getOperand(1).isReg() &&
241
MI.getOperand(1).getReg() == LoongArch::R0) ||
242
(MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0);
243
}
244
return MI.isAsCheapAsAMove();
245
}
246
247
MachineBasicBlock *
248
LoongArchInstrInfo::getBranchDestBlock(const MachineInstr &MI) const {
249
assert(MI.getDesc().isBranch() && "Unexpected opcode!");
250
// The branch target is always the last operand.
251
return MI.getOperand(MI.getNumExplicitOperands() - 1).getMBB();
252
}
253
254
static void parseCondBranch(MachineInstr &LastInst, MachineBasicBlock *&Target,
255
SmallVectorImpl<MachineOperand> &Cond) {
256
// Block ends with fall-through condbranch.
257
assert(LastInst.getDesc().isConditionalBranch() &&
258
"Unknown conditional branch");
259
int NumOp = LastInst.getNumExplicitOperands();
260
Target = LastInst.getOperand(NumOp - 1).getMBB();
261
262
Cond.push_back(MachineOperand::CreateImm(LastInst.getOpcode()));
263
for (int i = 0; i < NumOp - 1; i++)
264
Cond.push_back(LastInst.getOperand(i));
265
}
266
267
bool LoongArchInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
268
MachineBasicBlock *&TBB,
269
MachineBasicBlock *&FBB,
270
SmallVectorImpl<MachineOperand> &Cond,
271
bool AllowModify) const {
272
TBB = FBB = nullptr;
273
Cond.clear();
274
275
// If the block has no terminators, it just falls into the block after it.
276
MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
277
if (I == MBB.end() || !isUnpredicatedTerminator(*I))
278
return false;
279
280
// Count the number of terminators and find the first unconditional or
281
// indirect branch.
282
MachineBasicBlock::iterator FirstUncondOrIndirectBr = MBB.end();
283
int NumTerminators = 0;
284
for (auto J = I.getReverse(); J != MBB.rend() && isUnpredicatedTerminator(*J);
285
J++) {
286
NumTerminators++;
287
if (J->getDesc().isUnconditionalBranch() ||
288
J->getDesc().isIndirectBranch()) {
289
FirstUncondOrIndirectBr = J.getReverse();
290
}
291
}
292
293
// If AllowModify is true, we can erase any terminators after
294
// FirstUncondOrIndirectBR.
295
if (AllowModify && FirstUncondOrIndirectBr != MBB.end()) {
296
while (std::next(FirstUncondOrIndirectBr) != MBB.end()) {
297
std::next(FirstUncondOrIndirectBr)->eraseFromParent();
298
NumTerminators--;
299
}
300
I = FirstUncondOrIndirectBr;
301
}
302
303
// Handle a single unconditional branch.
304
if (NumTerminators == 1 && I->getDesc().isUnconditionalBranch()) {
305
TBB = getBranchDestBlock(*I);
306
return false;
307
}
308
309
// Handle a single conditional branch.
310
if (NumTerminators == 1 && I->getDesc().isConditionalBranch()) {
311
parseCondBranch(*I, TBB, Cond);
312
return false;
313
}
314
315
// Handle a conditional branch followed by an unconditional branch.
316
if (NumTerminators == 2 && std::prev(I)->getDesc().isConditionalBranch() &&
317
I->getDesc().isUnconditionalBranch()) {
318
parseCondBranch(*std::prev(I), TBB, Cond);
319
FBB = getBranchDestBlock(*I);
320
return false;
321
}
322
323
// Otherwise, we can't handle this.
324
return true;
325
}
326
327
bool LoongArchInstrInfo::isBranchOffsetInRange(unsigned BranchOp,
328
int64_t BrOffset) const {
329
switch (BranchOp) {
330
default:
331
llvm_unreachable("Unknown branch instruction!");
332
case LoongArch::BEQ:
333
case LoongArch::BNE:
334
case LoongArch::BLT:
335
case LoongArch::BGE:
336
case LoongArch::BLTU:
337
case LoongArch::BGEU:
338
return isInt<18>(BrOffset);
339
case LoongArch::BEQZ:
340
case LoongArch::BNEZ:
341
case LoongArch::BCEQZ:
342
case LoongArch::BCNEZ:
343
return isInt<23>(BrOffset);
344
case LoongArch::B:
345
case LoongArch::PseudoBR:
346
return isInt<28>(BrOffset);
347
}
348
}
349
350
unsigned LoongArchInstrInfo::removeBranch(MachineBasicBlock &MBB,
351
int *BytesRemoved) const {
352
if (BytesRemoved)
353
*BytesRemoved = 0;
354
MachineBasicBlock::iterator I = MBB.getLastNonDebugInstr();
355
if (I == MBB.end())
356
return 0;
357
358
if (!I->getDesc().isBranch())
359
return 0;
360
361
// Remove the branch.
362
if (BytesRemoved)
363
*BytesRemoved += getInstSizeInBytes(*I);
364
I->eraseFromParent();
365
366
I = MBB.end();
367
368
if (I == MBB.begin())
369
return 1;
370
--I;
371
if (!I->getDesc().isConditionalBranch())
372
return 1;
373
374
// Remove the branch.
375
if (BytesRemoved)
376
*BytesRemoved += getInstSizeInBytes(*I);
377
I->eraseFromParent();
378
return 2;
379
}
380
381
// Inserts a branch into the end of the specific MachineBasicBlock, returning
382
// the number of instructions inserted.
383
unsigned LoongArchInstrInfo::insertBranch(
384
MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
385
ArrayRef<MachineOperand> Cond, const DebugLoc &DL, int *BytesAdded) const {
386
if (BytesAdded)
387
*BytesAdded = 0;
388
389
// Shouldn't be a fall through.
390
assert(TBB && "insertBranch must not be told to insert a fallthrough");
391
assert(Cond.size() <= 3 && Cond.size() != 1 &&
392
"LoongArch branch conditions have at most two components!");
393
394
// Unconditional branch.
395
if (Cond.empty()) {
396
MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(TBB);
397
if (BytesAdded)
398
*BytesAdded += getInstSizeInBytes(MI);
399
return 1;
400
}
401
402
// Either a one or two-way conditional branch.
403
MachineInstrBuilder MIB = BuildMI(&MBB, DL, get(Cond[0].getImm()));
404
for (unsigned i = 1; i < Cond.size(); ++i)
405
MIB.add(Cond[i]);
406
MIB.addMBB(TBB);
407
if (BytesAdded)
408
*BytesAdded += getInstSizeInBytes(*MIB);
409
410
// One-way conditional branch.
411
if (!FBB)
412
return 1;
413
414
// Two-way conditional branch.
415
MachineInstr &MI = *BuildMI(&MBB, DL, get(LoongArch::PseudoBR)).addMBB(FBB);
416
if (BytesAdded)
417
*BytesAdded += getInstSizeInBytes(MI);
418
return 2;
419
}
420
421
void LoongArchInstrInfo::insertIndirectBranch(MachineBasicBlock &MBB,
422
MachineBasicBlock &DestBB,
423
MachineBasicBlock &RestoreBB,
424
const DebugLoc &DL,
425
int64_t BrOffset,
426
RegScavenger *RS) const {
427
assert(RS && "RegScavenger required for long branching");
428
assert(MBB.empty() &&
429
"new block should be inserted for expanding unconditional branch");
430
assert(MBB.pred_size() == 1);
431
432
MachineFunction *MF = MBB.getParent();
433
MachineRegisterInfo &MRI = MF->getRegInfo();
434
const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
435
LoongArchMachineFunctionInfo *LAFI =
436
MF->getInfo<LoongArchMachineFunctionInfo>();
437
438
if (!isInt<32>(BrOffset))
439
report_fatal_error(
440
"Branch offsets outside of the signed 32-bit range not supported");
441
442
Register ScratchReg = MRI.createVirtualRegister(&LoongArch::GPRRegClass);
443
auto II = MBB.end();
444
445
MachineInstr &PCALAU12I =
446
*BuildMI(MBB, II, DL, get(LoongArch::PCALAU12I), ScratchReg)
447
.addMBB(&DestBB, LoongArchII::MO_PCREL_HI);
448
MachineInstr &ADDI =
449
*BuildMI(MBB, II, DL,
450
get(STI.is64Bit() ? LoongArch::ADDI_D : LoongArch::ADDI_W),
451
ScratchReg)
452
.addReg(ScratchReg)
453
.addMBB(&DestBB, LoongArchII::MO_PCREL_LO);
454
BuildMI(MBB, II, DL, get(LoongArch::PseudoBRIND))
455
.addReg(ScratchReg, RegState::Kill)
456
.addImm(0);
457
458
RS->enterBasicBlockEnd(MBB);
459
Register Scav = RS->scavengeRegisterBackwards(
460
LoongArch::GPRRegClass, PCALAU12I.getIterator(), /*RestoreAfter=*/false,
461
/*SPAdj=*/0, /*AllowSpill=*/false);
462
if (Scav != LoongArch::NoRegister)
463
RS->setRegUsed(Scav);
464
else {
465
// When there is no scavenged register, it needs to specify a register.
466
// Specify t8 register because it won't be used too often.
467
Scav = LoongArch::R20;
468
int FrameIndex = LAFI->getBranchRelaxationSpillFrameIndex();
469
if (FrameIndex == -1)
470
report_fatal_error("The function size is incorrectly estimated.");
471
storeRegToStackSlot(MBB, PCALAU12I, Scav, /*IsKill=*/true, FrameIndex,
472
&LoongArch::GPRRegClass, TRI, Register());
473
TRI->eliminateFrameIndex(std::prev(PCALAU12I.getIterator()),
474
/*SpAdj=*/0, /*FIOperandNum=*/1);
475
PCALAU12I.getOperand(1).setMBB(&RestoreBB);
476
ADDI.getOperand(2).setMBB(&RestoreBB);
477
loadRegFromStackSlot(RestoreBB, RestoreBB.end(), Scav, FrameIndex,
478
&LoongArch::GPRRegClass, TRI, Register());
479
TRI->eliminateFrameIndex(RestoreBB.back(),
480
/*SpAdj=*/0, /*FIOperandNum=*/1);
481
}
482
MRI.replaceRegWith(ScratchReg, Scav);
483
MRI.clearVirtRegs();
484
}
485
486
static unsigned getOppositeBranchOpc(unsigned Opc) {
487
switch (Opc) {
488
default:
489
llvm_unreachable("Unrecognized conditional branch");
490
case LoongArch::BEQ:
491
return LoongArch::BNE;
492
case LoongArch::BNE:
493
return LoongArch::BEQ;
494
case LoongArch::BEQZ:
495
return LoongArch::BNEZ;
496
case LoongArch::BNEZ:
497
return LoongArch::BEQZ;
498
case LoongArch::BCEQZ:
499
return LoongArch::BCNEZ;
500
case LoongArch::BCNEZ:
501
return LoongArch::BCEQZ;
502
case LoongArch::BLT:
503
return LoongArch::BGE;
504
case LoongArch::BGE:
505
return LoongArch::BLT;
506
case LoongArch::BLTU:
507
return LoongArch::BGEU;
508
case LoongArch::BGEU:
509
return LoongArch::BLTU;
510
}
511
}
512
513
bool LoongArchInstrInfo::reverseBranchCondition(
514
SmallVectorImpl<MachineOperand> &Cond) const {
515
assert((Cond.size() && Cond.size() <= 3) && "Invalid branch condition!");
516
Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm()));
517
return false;
518
}
519
520
std::pair<unsigned, unsigned>
521
LoongArchInstrInfo::decomposeMachineOperandsTargetFlags(unsigned TF) const {
522
return std::make_pair(TF, 0u);
523
}
524
525
ArrayRef<std::pair<unsigned, const char *>>
526
LoongArchInstrInfo::getSerializableDirectMachineOperandTargetFlags() const {
527
using namespace LoongArchII;
528
// TODO: Add more target flags.
529
static const std::pair<unsigned, const char *> TargetFlags[] = {
530
{MO_CALL, "loongarch-call"},
531
{MO_CALL_PLT, "loongarch-call-plt"},
532
{MO_PCREL_HI, "loongarch-pcrel-hi"},
533
{MO_PCREL_LO, "loongarch-pcrel-lo"},
534
{MO_PCREL64_LO, "loongarch-pcrel64-lo"},
535
{MO_PCREL64_HI, "loongarch-pcrel64-hi"},
536
{MO_GOT_PC_HI, "loongarch-got-pc-hi"},
537
{MO_GOT_PC_LO, "loongarch-got-pc-lo"},
538
{MO_GOT_PC64_LO, "loongarch-got-pc64-lo"},
539
{MO_GOT_PC64_HI, "loongarch-got-pc64-hi"},
540
{MO_LE_HI, "loongarch-le-hi"},
541
{MO_LE_LO, "loongarch-le-lo"},
542
{MO_LE64_LO, "loongarch-le64-lo"},
543
{MO_LE64_HI, "loongarch-le64-hi"},
544
{MO_IE_PC_HI, "loongarch-ie-pc-hi"},
545
{MO_IE_PC_LO, "loongarch-ie-pc-lo"},
546
{MO_IE_PC64_LO, "loongarch-ie-pc64-lo"},
547
{MO_IE_PC64_HI, "loongarch-ie-pc64-hi"},
548
{MO_DESC_PC_HI, "loongarch-desc-pc-hi"},
549
{MO_DESC_PC_LO, "loongarch-desc-pc-lo"},
550
{MO_DESC64_PC_LO, "loongarch-desc64-pc-lo"},
551
{MO_DESC64_PC_HI, "loongarch-desc64-pc-hi"},
552
{MO_DESC_LD, "loongarch-desc-ld"},
553
{MO_DESC_CALL, "loongarch-desc-call"},
554
{MO_LD_PC_HI, "loongarch-ld-pc-hi"},
555
{MO_GD_PC_HI, "loongarch-gd-pc-hi"}};
556
return ArrayRef(TargetFlags);
557
}
558
559
// Returns true if this is the sext.w pattern, addi.w rd, rs, 0.
560
bool LoongArch::isSEXT_W(const MachineInstr &MI) {
561
return MI.getOpcode() == LoongArch::ADDI_W && MI.getOperand(1).isReg() &&
562
MI.getOperand(2).isImm() && MI.getOperand(2).getImm() == 0;
563
}
564
565