LLVM 24.0.0git
RISCVRegisterBankInfo.cpp
Go to the documentation of this file.
1//===-- RISCVRegisterBankInfo.cpp -------------------------------*- 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/// \file
9/// This file implements the targeting of the RegisterBankInfo class for RISC-V.
10/// \todo This should be generated by TableGen.
11//===----------------------------------------------------------------------===//
12
15#include "RISCVSubtarget.h"
21#include "llvm/IR/IntrinsicsRISCV.h"
22
23#define GET_TARGET_REGBANK_IMPL
24#include "RISCVGenRegisterBank.inc"
25
26namespace llvm {
27namespace RISCV {
28
30 // clang-format off
31 {0, 32, GPRBRegBank},
32 {0, 64, GPRBRegBank},
33 {0, 16, FPRBRegBank},
34 {0, 32, FPRBRegBank},
35 {0, 64, FPRBRegBank},
36 {0, 64, VRBRegBank},
37 {0, 128, VRBRegBank},
38 {0, 256, VRBRegBank},
39 {0, 512, VRBRegBank},
40 // clang-format on
41};
42
54
56 // Invalid value mapping.
57 {nullptr, 0},
58 // Maximum 3 GPR operands; 32 bit.
62 // Maximum 3 GPR operands; 64 bit.
66 // Maximum 3 FPR operands; 16 bit.
70 // Maximum 3 FPR operands; 32 bit.
74 // Maximum 3 FPR operands; 64 bit.
78 // Maximum 3 VR LMUL={1, MF2, MF4, MF8} operands.
82 // Maximum 3 VR LMUL=2 operands.
86 // Maximum 3 VR LMUL=4 operands.
90 // Maximum 3 VR LMUL=8 operands.
94};
95
108} // namespace RISCV
109} // namespace llvm
110
111using namespace llvm;
112
115
116const RegisterBank &
118 LLT Ty) const {
119 switch (RC.getID()) {
120 // Vector control and status register class
121 case RISCV::VCSRRegClassID:
122 return getRegBank(RISCV::GPRBRegBankID);
123 default:
124 // For all GPR register classes and others, use the default implementation
126 }
127}
128
130 unsigned Idx;
131 switch (Size) {
132 default:
133 llvm_unreachable("Unexpected size");
134 case 16:
135 Idx = RISCV::FPRB16Idx;
136 break;
137 case 32:
138 Idx = RISCV::FPRB32Idx;
139 break;
140 case 64:
141 Idx = RISCV::FPRB64Idx;
142 break;
143 }
144 return &RISCV::ValueMappings[Idx];
145}
146
147// TODO: Make this more like AArch64?
148bool RISCVRegisterBankInfo::hasFPConstraints(
149 const MachineInstr &MI, const MachineRegisterInfo &MRI,
150 const TargetRegisterInfo &TRI) const {
152 return true;
153
154 // If we have a copy instruction, we could be feeding floating point
155 // instructions.
156 if (MI.getOpcode() != TargetOpcode::COPY)
157 return false;
158
159 return getRegBank(MI.getOperand(0).getReg(), MRI, TRI) == &RISCV::FPRBRegBank;
160}
161
162bool RISCVRegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
163 const MachineRegisterInfo &MRI,
164 const TargetRegisterInfo &TRI) const {
165 switch (MI.getOpcode()) {
166 case RISCV::G_FCVT_W_RV64:
167 case RISCV::G_FCVT_WU_RV64:
168 case RISCV::G_FCLASS:
169 case TargetOpcode::G_FPTOSI:
170 case TargetOpcode::G_FPTOUI:
171 case TargetOpcode::G_LROUND:
172 case TargetOpcode::G_LLROUND:
173 case TargetOpcode::G_INTRINSIC_LRINT:
174 case TargetOpcode::G_INTRINSIC_LLRINT:
175 case TargetOpcode::G_FCMP:
176 return true;
177 default:
178 break;
179 }
180
181 return hasFPConstraints(MI, MRI, TRI);
182}
183
184bool RISCVRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
185 const MachineRegisterInfo &MRI,
186 const TargetRegisterInfo &TRI) const {
187 switch (MI.getOpcode()) {
188 case TargetOpcode::G_SITOFP:
189 case TargetOpcode::G_UITOFP:
190 return true;
191 default:
192 break;
193 }
194
195 return hasFPConstraints(MI, MRI, TRI);
196}
197
198bool RISCVRegisterBankInfo::anyUseOnlyUseFP(
199 Register Def, const MachineRegisterInfo &MRI,
200 const TargetRegisterInfo &TRI) const {
201 return any_of(
202 MRI.use_nodbg_instructions(Def),
203 [&](const MachineInstr &UseMI) { return onlyUsesFP(UseMI, MRI, TRI); });
204}
205
206/// Decide whether an s64 value on RV32 belongs in a GPRPair (an i64, needs
207/// Zilsd) rather than in FPR64 (an f64, needs D).
208///
209/// With extended LLTs the type answers this directly. Without them every
210/// 64-bit scalar is an ANY_SCALAR LLT, so i64 and f64 are indistinguishable --
211/// guessing from the uses gets it wrong, e.g. an f64 whose only use is a
212/// G_SELECT looks like an integer because G_SELECT is not itself floating
213/// point constrained. So fall back to using a GPRPair only where the value
214/// cannot be an f64 at all.
215static bool useGPRPairForS64(const RISCVSubtarget &ST, LLT Ty) {
216 if (!ST.hasStdExtZilsd())
217 return false;
219 return Ty.isInteger();
220 return !ST.hasStdExtD();
221}
222
224 unsigned Idx;
225
226 if (Size <= 64)
227 Idx = RISCV::VRB64Idx;
228 else if (Size == 128)
229 Idx = RISCV::VRB128Idx;
230 else if (Size == 256)
231 Idx = RISCV::VRB256Idx;
232 else if (Size == 512)
233 Idx = RISCV::VRB512Idx;
234 else
235 llvm::report_fatal_error("Invalid Size");
236
237 return &RISCV::ValueMappings[Idx];
238}
239
242 const unsigned Opc = MI.getOpcode();
243
244 // Try the default logic for non-generic instructions that are either copies
245 // or already have some operands assigned to banks.
246 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
247 const InstructionMapping &Mapping = getInstrMappingImpl(MI);
248 if (Mapping.isValid())
249 return Mapping;
250 }
251
252 const MachineFunction &MF = *MI.getParent()->getParent();
253 const MachineRegisterInfo &MRI = MF.getRegInfo();
254 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
255 const TargetRegisterInfo &TRI = *Subtarget.getRegisterInfo();
256
257 unsigned GPRSize = Subtarget.getXLen();
258
259 unsigned NumOperands = MI.getNumOperands();
260 const ValueMapping *GPRValueMapping =
263
264 switch (Opc) {
265 case TargetOpcode::G_ADD:
266 case TargetOpcode::G_SUB:
267 case TargetOpcode::G_SHL:
268 case TargetOpcode::G_ASHR:
269 case TargetOpcode::G_LSHR:
270 case TargetOpcode::G_AND:
271 case TargetOpcode::G_OR:
272 case TargetOpcode::G_XOR:
273 case TargetOpcode::G_MUL:
274 case TargetOpcode::G_SDIV:
275 case TargetOpcode::G_SREM:
276 case TargetOpcode::G_SMULH:
277 case TargetOpcode::G_SMAX:
278 case TargetOpcode::G_SMIN:
279 case TargetOpcode::G_UDIV:
280 case TargetOpcode::G_UREM:
281 case TargetOpcode::G_UMULH:
282 case TargetOpcode::G_UMAX:
283 case TargetOpcode::G_UMIN:
284 case TargetOpcode::G_PTR_ADD:
285 case TargetOpcode::G_PTRTOINT:
286 case TargetOpcode::G_INTTOPTR:
287 case TargetOpcode::G_FADD:
288 case TargetOpcode::G_FSUB:
289 case TargetOpcode::G_FMUL:
290 case TargetOpcode::G_FDIV:
291 case TargetOpcode::G_FABS:
292 case TargetOpcode::G_FNEG:
293 case TargetOpcode::G_FSQRT:
294 case TargetOpcode::G_FMAXNUM:
295 case TargetOpcode::G_FMINNUM: {
296 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
297 TypeSize Size = Ty.getSizeInBits();
298
299 const ValueMapping *Mapping;
300 if (Ty.isVector())
301 Mapping = getVRBValueMapping(Size.getKnownMinValue());
303 Mapping = getFPValueMapping(Size.getFixedValue());
304 else
305 Mapping = GPRValueMapping;
306
307#ifndef NDEBUG
308 // Make sure all the operands are using similar size and type.
309 for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
310 LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
311 assert(Ty.isVector() == OpTy.isVector() &&
312 "Operand has incompatible type");
313 // Don't check size for GPR.
315 assert(Size == OpTy.getSizeInBits() && "Operand has incompatible size");
316 }
317#endif // End NDEBUG
318
319 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
320 }
321 case TargetOpcode::G_SEXTLOAD:
322 case TargetOpcode::G_ZEXTLOAD:
323 return getInstructionMapping(DefaultMappingID, /*Cost=*/1, GPRValueMapping,
324 NumOperands);
325 case TargetOpcode::G_IMPLICIT_DEF: {
326 Register Dst = MI.getOperand(0).getReg();
327 LLT DstTy = MRI.getType(Dst);
328 unsigned DstMinSize = DstTy.getSizeInBits().getKnownMinValue();
329 auto Mapping = GPRValueMapping;
330 // FIXME: May need to do a better job determining when to use FPRB.
331 // For example, the look through COPY case:
332 // %0:_(s32) = G_IMPLICIT_DEF
333 // %1:_(s32) = COPY %0
334 // $f10_d = COPY %1(s32)
335 if (DstTy.isVector())
336 Mapping = getVRBValueMapping(DstMinSize);
337 else if (anyUseOnlyUseFP(Dst, MRI, TRI))
338 Mapping = getFPValueMapping(DstMinSize);
339
340 return getInstructionMapping(DefaultMappingID, /*Cost=*/1, Mapping,
341 NumOperands);
342 }
343 }
344
345 SmallVector<const ValueMapping *, 4> OpdsMapping(NumOperands);
346
347 switch (Opc) {
348 case TargetOpcode::G_LOAD: {
349 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
350 TypeSize Size = Ty.getSizeInBits();
351
352 OpdsMapping[1] = GPRValueMapping;
353
354 if (Ty.isVector()) {
355 OpdsMapping[0] = getVRBValueMapping(Size.getKnownMinValue());
356 break;
357 }
358
359 OpdsMapping[0] = GPRValueMapping;
360
361 // Atomics always use GPR destinations. Don't refine any further.
362 if (cast<GLoad>(MI).isAtomic())
363 break;
364
365 // RV32 s64 loads: f64 (D) uses FPR64; i64 (Zilsd without D) uses a
366 // GPRPair.
367 if (GPRSize == 32 && Size.getFixedValue() == 64) {
369 if (useGPRPairForS64(ST, Ty)) {
370 OpdsMapping[0] = &RISCV::ValueMappings[RISCV::GPRB64Idx];
371 break;
372 }
373 assert(ST.hasStdExtD() && "s64 load without D or Zilsd");
374 OpdsMapping[0] = getFPValueMapping(Size);
375 break;
376 }
377
378 // Check if that load feeds fp instructions.
379 // In that case, we want the default mapping to be on FPR
380 // instead of blind map every scalar to GPR.
381 if (anyUseOnlyUseFP(MI.getOperand(0).getReg(), MRI, TRI)) {
382 // If we have at least one direct use in a FP instruction,
383 // assume this was a floating point load in the IR. If it was
384 // not, we would have had a bitcast before reaching that
385 // instruction.
386 OpdsMapping[0] = getFPValueMapping(Size);
387 break;
388 }
389
390 break;
391 }
392 case TargetOpcode::G_STORE: {
393 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
394 TypeSize Size = Ty.getSizeInBits();
395
396 OpdsMapping[1] = GPRValueMapping;
397
398 if (Ty.isVector()) {
399 OpdsMapping[0] = getVRBValueMapping(Size.getKnownMinValue());
400 break;
401 }
402
403 OpdsMapping[0] = GPRValueMapping;
404
405 // Atomics always use GPR sources. Don't refine any further.
406 if (cast<GStore>(MI).isAtomic())
407 break;
408
409 // RV32 s64 stores: f64 (D) uses FPR64; i64 (Zilsd without D) uses a
410 // GPRPair.
411 if (GPRSize == 32 && Size.getFixedValue() == 64) {
413 if (useGPRPairForS64(ST, Ty)) {
414 OpdsMapping[0] = &RISCV::ValueMappings[RISCV::GPRB64Idx];
415 break;
416 }
417 assert(ST.hasStdExtD() && "s64 store without D or Zilsd");
418 OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
419 break;
420 }
421
422 MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg());
423 if (onlyDefinesFP(*DefMI, MRI, TRI))
424 OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
425 break;
426 }
427 case TargetOpcode::G_SELECT: {
428 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
429
430 if (Ty.isVector()) {
431 auto &Sel = cast<GSelect>(MI);
432 LLT TestTy = MRI.getType(Sel.getCondReg());
433 assert(TestTy.isVector() && "Unexpected condition argument type");
434 OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] =
435 getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue());
436 OpdsMapping[1] =
438 break;
439 }
440
441 // Try to minimize the number of copies. If we have more floating point
442 // constrained values than not, then we'll put everything on FPR. Otherwise,
443 // everything has to be on GPR.
444 unsigned NumFP = 0;
445
446 // Use FPR64 for s64 select on rv32. An s64 select is only legal here when
447 // D is present (see the G_SELECT rules), so this cannot be a Zilsd i64,
448 // which would need a GPRPair instead.
449 if (GPRSize == 32 && Ty.getSizeInBits() == 64) {
450 NumFP = 3;
451 } else {
452 // Check if the uses of the result always produce floating point values.
453 //
454 // For example:
455 //
456 // %z = G_SELECT %cond %x %y
457 // fpr = G_FOO %z ...
458 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
459 [&](const MachineInstr &UseMI) {
460 return onlyUsesFP(UseMI, MRI, TRI);
461 }))
462 ++NumFP;
463
464 // Check if the defs of the source values always produce floating point
465 // values.
466 //
467 // For example:
468 //
469 // %x = G_SOMETHING_ALWAYS_FLOAT %a ...
470 // %z = G_SELECT %cond %x %y
471 //
472 // Also check whether or not the sources have already been decided to be
473 // FPR. Keep track of this.
474 //
475 // This doesn't check the condition, since the condition is always an
476 // integer.
477 for (unsigned Idx = 2; Idx < 4; ++Idx) {
478 Register VReg = MI.getOperand(Idx).getReg();
479 MachineInstr *DefMI = MRI.getVRegDef(VReg);
480 if (getRegBank(VReg, MRI, TRI) == &RISCV::FPRBRegBank ||
481 onlyDefinesFP(*DefMI, MRI, TRI))
482 ++NumFP;
483 }
484 }
485
486 // Condition operand is always GPR.
487 OpdsMapping[1] = GPRValueMapping;
488
489 const ValueMapping *Mapping = GPRValueMapping;
490 if (NumFP >= 2)
491 Mapping = getFPValueMapping(Ty.getSizeInBits());
492
493 OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] = Mapping;
494 break;
495 }
496 case RISCV::G_FCVT_W_RV64:
497 case RISCV::G_FCVT_WU_RV64:
498 case TargetOpcode::G_FPTOSI:
499 case TargetOpcode::G_FPTOUI:
500 case TargetOpcode::G_LROUND:
501 case TargetOpcode::G_LLROUND:
502 case TargetOpcode::G_INTRINSIC_LRINT:
503 case TargetOpcode::G_INTRINSIC_LLRINT:
504 case RISCV::G_FCLASS: {
505 LLT Ty = MRI.getType(MI.getOperand(1).getReg());
506 OpdsMapping[0] = GPRValueMapping;
507 OpdsMapping[1] = getFPValueMapping(Ty.getSizeInBits());
508 break;
509 }
510 case TargetOpcode::G_SITOFP:
511 case TargetOpcode::G_UITOFP: {
512 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
513 OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
514 OpdsMapping[1] = GPRValueMapping;
515 break;
516 }
517 case TargetOpcode::G_FCMP: {
518 LLT Ty = MRI.getType(MI.getOperand(2).getReg());
519
520 unsigned Size = Ty.getSizeInBits();
521
522 OpdsMapping[0] = GPRValueMapping;
523 OpdsMapping[2] = OpdsMapping[3] = getFPValueMapping(Size);
524 break;
525 }
526 case TargetOpcode::G_MERGE_VALUES: {
527 // RV32 s64: f64 (D) uses FPR64; i64 (Zilsd without D) uses a GPRPair.
528 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
529 if (GPRSize == 32 && Ty.getSizeInBits() == 64) {
531 OpdsMapping[0] = useGPRPairForS64(ST, Ty)
533 : getFPValueMapping(Ty.getSizeInBits());
534 assert((useGPRPairForS64(ST, Ty) || ST.hasStdExtD()) &&
535 "s64 merge without D or Zilsd");
536 OpdsMapping[1] = GPRValueMapping;
537 OpdsMapping[2] = GPRValueMapping;
538 }
539 break;
540 }
541 case TargetOpcode::G_UNMERGE_VALUES: {
542 // RV32 s64: f64 (D) uses FPR64; i64 (Zilsd without D) uses a GPRPair.
543 LLT Ty = MRI.getType(MI.getOperand(2).getReg());
544 if (GPRSize == 32 && Ty.getSizeInBits() == 64) {
546 OpdsMapping[2] = useGPRPairForS64(ST, Ty)
548 : getFPValueMapping(Ty.getSizeInBits());
549 assert((useGPRPairForS64(ST, Ty) || ST.hasStdExtD()) &&
550 "s64 unmerge without D or Zilsd");
551 OpdsMapping[0] = GPRValueMapping;
552 OpdsMapping[1] = GPRValueMapping;
553 }
554 break;
555 }
556 case TargetOpcode::G_SPLAT_VECTOR: {
557 OpdsMapping[0] = getVRBValueMapping(MRI.getType(MI.getOperand(0).getReg())
560
561 LLT ScalarTy = MRI.getType(MI.getOperand(1).getReg());
562 MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(1).getReg());
563 if ((GPRSize == 32 && ScalarTy.getSizeInBits() == 64) ||
564 onlyDefinesFP(*DefMI, MRI, TRI)) {
565 assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());
566 OpdsMapping[1] = getFPValueMapping(ScalarTy.getSizeInBits());
567 } else
568 OpdsMapping[1] = GPRValueMapping;
569 break;
570 }
571 case TargetOpcode::G_INTRINSIC: {
572 Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();
573
575 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntrinsicID)) {
576 unsigned ScalarIdx = -1;
577 if (II->hasScalarOperand()) {
578 ScalarIdx = II->ScalarOperand + 2;
579 }
580 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
581 const MachineOperand &MO = MI.getOperand(Idx);
582 if (!MO.isReg())
583 continue;
584 LLT Ty = MRI.getType(MO.getReg());
585 if (Ty.isVector()) {
586 OpdsMapping[Idx] =
587 getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue());
588 } else if (II->IsFPIntrinsic && ScalarIdx == Idx) {
589 // Chose the right FPR for scalar operand of RVV intrinsics.
590 OpdsMapping[Idx] = getFPValueMapping(Ty.getSizeInBits());
591 } else {
592 OpdsMapping[Idx] = GPRValueMapping;
593 }
594 }
595 }
596
597 if (IntrinsicID == Intrinsic::riscv_orc_b ||
598 IntrinsicID == Intrinsic::riscv_vsetvli ||
599 IntrinsicID == Intrinsic::riscv_vsetvlimax) {
600 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
601 const MachineOperand &MO = MI.getOperand(Idx);
602 if (!MO.isReg())
603 continue;
604 OpdsMapping[Idx] = GPRValueMapping;
605 }
606 }
607 break;
608 }
609 default:
610 // By default map all scalars to GPR.
611 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
612 auto &MO = MI.getOperand(Idx);
613 if (!MO.isReg() || !MO.getReg())
614 continue;
615 LLT Ty = MRI.getType(MO.getReg());
616 if (!Ty.isValid())
617 continue;
618
619 if (Ty.isVector())
620 OpdsMapping[Idx] =
621 getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue());
623 OpdsMapping[Idx] = getFPValueMapping(Ty.getSizeInBits());
624 else
625 OpdsMapping[Idx] = GPRValueMapping;
626 }
627 break;
628 }
629
630 return getInstructionMapping(DefaultMappingID, /*Cost=*/1,
631 getOperandsMapping(OpdsMapping), NumOperands);
632}
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
IRTranslator LLVM IR MI
Register const TargetRegisterInfo * TRI
uint64_t IntrinsicInst * II
static const RegisterBankInfo::ValueMapping * getFPValueMapping(unsigned Size)
static const RegisterBankInfo::ValueMapping * getVRBValueMapping(unsigned Size)
static bool useGPRPairForS64(const RISCVSubtarget &ST, LLT Ty)
Decide whether an s64 value on RV32 belongs in a GPRPair (an i64, needs Zilsd) rather than in FPR64 (...
This file declares the targeting of the RegisterBankInfo class for RISC-V.
static bool getUseExtended()
constexpr bool isVector() const
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
unsigned getID() const
getID() - Return the register class ID number.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI LLVM_READONLY MachineInstr * getVRegDef(Register Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
LLT getType(Register Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register.
iterator_range< use_instr_nodbg_iterator > use_nodbg_instructions(Register Reg) const
const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT Ty) const override
Get a register bank that covers RC.
const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override
Get the mapping of the different operands of MI on the register bank.
unsigned getXLen() const
const RISCVRegisterInfo * getRegisterInfo() const override
Helper class that represents how the value of an instruction may be mapped and what is the related co...
bool isValid() const
Check whether this object is valid.
const InstructionMapping & getInstructionMapping(unsigned ID, unsigned Cost, const ValueMapping *OperandsMapping, unsigned NumOperands) const
Method to get a uniquely generated InstructionMapping.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
virtual const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT Ty) const
Get a register bank that covers RC.
const ValueMapping * getOperandsMapping(Iterator Begin, Iterator End) const
Get the uniquely generated array of ValueMapping for the elements of between Begin and End.
static const unsigned DefaultMappingID
Identifier used when the related instruction mapping instance is generated by target independent code...
unsigned HwMode
Current HwMode for the target.
const InstructionMapping & getInstrMappingImpl(const MachineInstr &MI) const
Try to get the mapping of MI.
This class implements the register bank concept.
Wrapper class representing virtual and physical registers.
Definition Register.h:20
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
constexpr ScalarTy getKnownMinValue() const
Returns the minimum value this quantity can represent.
Definition TypeSize.h:166
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const RegisterBankInfo::PartialMapping PartMappings[]
const RegisterBankInfo::ValueMapping ValueMappings[]
This is an optimization pass for GlobalISel generic memory operations.
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI bool isPreISelGenericFloatingPointOpcode(unsigned Opc)
Returns whether opcode Opc is a pre-isel generic floating-point opcode, having only floating-point op...
Definition Utils.cpp:1701
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58
Helper struct that represents how a value is partially mapped into a register.
Helper struct that represents how a value is mapped through different register banks.