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_FCMP:
174 return true;
175 default:
176 break;
177 }
178
179 return hasFPConstraints(MI, MRI, TRI);
180}
181
182bool RISCVRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
183 const MachineRegisterInfo &MRI,
184 const TargetRegisterInfo &TRI) const {
185 switch (MI.getOpcode()) {
186 case TargetOpcode::G_SITOFP:
187 case TargetOpcode::G_UITOFP:
188 return true;
189 default:
190 break;
191 }
192
193 return hasFPConstraints(MI, MRI, TRI);
194}
195
196bool RISCVRegisterBankInfo::anyUseOnlyUseFP(
197 Register Def, const MachineRegisterInfo &MRI,
198 const TargetRegisterInfo &TRI) const {
199 return any_of(
200 MRI.use_nodbg_instructions(Def),
201 [&](const MachineInstr &UseMI) { return onlyUsesFP(UseMI, MRI, TRI); });
202}
203
205 unsigned Idx;
206
207 if (Size <= 64)
208 Idx = RISCV::VRB64Idx;
209 else if (Size == 128)
210 Idx = RISCV::VRB128Idx;
211 else if (Size == 256)
212 Idx = RISCV::VRB256Idx;
213 else if (Size == 512)
214 Idx = RISCV::VRB512Idx;
215 else
216 llvm::report_fatal_error("Invalid Size");
217
218 return &RISCV::ValueMappings[Idx];
219}
220
223 const unsigned Opc = MI.getOpcode();
224
225 // Try the default logic for non-generic instructions that are either copies
226 // or already have some operands assigned to banks.
227 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
228 const InstructionMapping &Mapping = getInstrMappingImpl(MI);
229 if (Mapping.isValid())
230 return Mapping;
231 }
232
233 const MachineFunction &MF = *MI.getParent()->getParent();
234 const MachineRegisterInfo &MRI = MF.getRegInfo();
235 const RISCVSubtarget &Subtarget = MF.getSubtarget<RISCVSubtarget>();
236 const TargetRegisterInfo &TRI = *Subtarget.getRegisterInfo();
237
238 unsigned GPRSize = Subtarget.getXLen();
239
240 unsigned NumOperands = MI.getNumOperands();
241 const ValueMapping *GPRValueMapping =
244
245 switch (Opc) {
246 case TargetOpcode::G_ADD:
247 case TargetOpcode::G_SUB:
248 case TargetOpcode::G_SHL:
249 case TargetOpcode::G_ASHR:
250 case TargetOpcode::G_LSHR:
251 case TargetOpcode::G_AND:
252 case TargetOpcode::G_OR:
253 case TargetOpcode::G_XOR:
254 case TargetOpcode::G_MUL:
255 case TargetOpcode::G_SDIV:
256 case TargetOpcode::G_SREM:
257 case TargetOpcode::G_SMULH:
258 case TargetOpcode::G_SMAX:
259 case TargetOpcode::G_SMIN:
260 case TargetOpcode::G_UDIV:
261 case TargetOpcode::G_UREM:
262 case TargetOpcode::G_UMULH:
263 case TargetOpcode::G_UMAX:
264 case TargetOpcode::G_UMIN:
265 case TargetOpcode::G_PTR_ADD:
266 case TargetOpcode::G_PTRTOINT:
267 case TargetOpcode::G_INTTOPTR:
268 case TargetOpcode::G_FADD:
269 case TargetOpcode::G_FSUB:
270 case TargetOpcode::G_FMUL:
271 case TargetOpcode::G_FDIV:
272 case TargetOpcode::G_FABS:
273 case TargetOpcode::G_FNEG:
274 case TargetOpcode::G_FSQRT:
275 case TargetOpcode::G_FMAXNUM:
276 case TargetOpcode::G_FMINNUM: {
277 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
278 TypeSize Size = Ty.getSizeInBits();
279
280 const ValueMapping *Mapping;
281 if (Ty.isVector())
282 Mapping = getVRBValueMapping(Size.getKnownMinValue());
284 Mapping = getFPValueMapping(Size.getFixedValue());
285 else
286 Mapping = GPRValueMapping;
287
288#ifndef NDEBUG
289 // Make sure all the operands are using similar size and type.
290 for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
291 LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
292 assert(Ty.isVector() == OpTy.isVector() &&
293 "Operand has incompatible type");
294 // Don't check size for GPR.
296 assert(Size == OpTy.getSizeInBits() && "Operand has incompatible size");
297 }
298#endif // End NDEBUG
299
300 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
301 }
302 case TargetOpcode::G_SEXTLOAD:
303 case TargetOpcode::G_ZEXTLOAD:
304 return getInstructionMapping(DefaultMappingID, /*Cost=*/1, GPRValueMapping,
305 NumOperands);
306 case TargetOpcode::G_IMPLICIT_DEF: {
307 Register Dst = MI.getOperand(0).getReg();
308 LLT DstTy = MRI.getType(Dst);
309 unsigned DstMinSize = DstTy.getSizeInBits().getKnownMinValue();
310 auto Mapping = GPRValueMapping;
311 // FIXME: May need to do a better job determining when to use FPRB.
312 // For example, the look through COPY case:
313 // %0:_(s32) = G_IMPLICIT_DEF
314 // %1:_(s32) = COPY %0
315 // $f10_d = COPY %1(s32)
316 if (DstTy.isVector())
317 Mapping = getVRBValueMapping(DstMinSize);
318 else if (anyUseOnlyUseFP(Dst, MRI, TRI))
319 Mapping = getFPValueMapping(DstMinSize);
320
321 return getInstructionMapping(DefaultMappingID, /*Cost=*/1, Mapping,
322 NumOperands);
323 }
324 }
325
326 SmallVector<const ValueMapping *, 4> OpdsMapping(NumOperands);
327
328 switch (Opc) {
329 case TargetOpcode::G_LOAD: {
330 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
331 TypeSize Size = Ty.getSizeInBits();
332
333 OpdsMapping[1] = GPRValueMapping;
334
335 if (Ty.isVector()) {
336 OpdsMapping[0] = getVRBValueMapping(Size.getKnownMinValue());
337 break;
338 }
339
340 OpdsMapping[0] = GPRValueMapping;
341
342 // Atomics always use GPR destinations. Don't refine any further.
343 if (cast<GLoad>(MI).isAtomic())
344 break;
345
346 // Use FPR64 for s64 loads on rv32.
347 if (GPRSize == 32 && Size.getFixedValue() == 64) {
348 assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());
349 OpdsMapping[0] = getFPValueMapping(Size);
350 break;
351 }
352
353 // Check if that load feeds fp instructions.
354 // In that case, we want the default mapping to be on FPR
355 // instead of blind map every scalar to GPR.
356 if (anyUseOnlyUseFP(MI.getOperand(0).getReg(), MRI, TRI)) {
357 // If we have at least one direct use in a FP instruction,
358 // assume this was a floating point load in the IR. If it was
359 // not, we would have had a bitcast before reaching that
360 // instruction.
361 OpdsMapping[0] = getFPValueMapping(Size);
362 break;
363 }
364
365 break;
366 }
367 case TargetOpcode::G_STORE: {
368 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
369 TypeSize Size = Ty.getSizeInBits();
370
371 OpdsMapping[1] = GPRValueMapping;
372
373 if (Ty.isVector()) {
374 OpdsMapping[0] = getVRBValueMapping(Size.getKnownMinValue());
375 break;
376 }
377
378 OpdsMapping[0] = GPRValueMapping;
379
380 // Atomics always use GPR sources. Don't refine any further.
381 if (cast<GStore>(MI).isAtomic())
382 break;
383
384 // Use FPR64 for s64 stores on rv32.
385 if (GPRSize == 32 && Size.getFixedValue() == 64) {
386 assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());
387 OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
388 break;
389 }
390
391 MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg());
392 if (onlyDefinesFP(*DefMI, MRI, TRI))
393 OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
394 break;
395 }
396 case TargetOpcode::G_SELECT: {
397 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
398
399 if (Ty.isVector()) {
400 auto &Sel = cast<GSelect>(MI);
401 LLT TestTy = MRI.getType(Sel.getCondReg());
402 assert(TestTy.isVector() && "Unexpected condition argument type");
403 OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] =
404 getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue());
405 OpdsMapping[1] =
407 break;
408 }
409
410 // Try to minimize the number of copies. If we have more floating point
411 // constrained values than not, then we'll put everything on FPR. Otherwise,
412 // everything has to be on GPR.
413 unsigned NumFP = 0;
414
415 // Use FPR64 for s64 select on rv32.
416 if (GPRSize == 32 && Ty.getSizeInBits() == 64) {
417 NumFP = 3;
418 } else {
419 // Check if the uses of the result always produce floating point values.
420 //
421 // For example:
422 //
423 // %z = G_SELECT %cond %x %y
424 // fpr = G_FOO %z ...
425 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
426 [&](const MachineInstr &UseMI) {
427 return onlyUsesFP(UseMI, MRI, TRI);
428 }))
429 ++NumFP;
430
431 // Check if the defs of the source values always produce floating point
432 // values.
433 //
434 // For example:
435 //
436 // %x = G_SOMETHING_ALWAYS_FLOAT %a ...
437 // %z = G_SELECT %cond %x %y
438 //
439 // Also check whether or not the sources have already been decided to be
440 // FPR. Keep track of this.
441 //
442 // This doesn't check the condition, since the condition is always an
443 // integer.
444 for (unsigned Idx = 2; Idx < 4; ++Idx) {
445 Register VReg = MI.getOperand(Idx).getReg();
446 MachineInstr *DefMI = MRI.getVRegDef(VReg);
447 if (getRegBank(VReg, MRI, TRI) == &RISCV::FPRBRegBank ||
448 onlyDefinesFP(*DefMI, MRI, TRI))
449 ++NumFP;
450 }
451 }
452
453 // Condition operand is always GPR.
454 OpdsMapping[1] = GPRValueMapping;
455
456 const ValueMapping *Mapping = GPRValueMapping;
457 if (NumFP >= 2)
458 Mapping = getFPValueMapping(Ty.getSizeInBits());
459
460 OpdsMapping[0] = OpdsMapping[2] = OpdsMapping[3] = Mapping;
461 break;
462 }
463 case RISCV::G_FCVT_W_RV64:
464 case RISCV::G_FCVT_WU_RV64:
465 case TargetOpcode::G_FPTOSI:
466 case TargetOpcode::G_FPTOUI:
467 case TargetOpcode::G_LROUND:
468 case TargetOpcode::G_LLROUND:
469 case RISCV::G_FCLASS: {
470 LLT Ty = MRI.getType(MI.getOperand(1).getReg());
471 OpdsMapping[0] = GPRValueMapping;
472 OpdsMapping[1] = getFPValueMapping(Ty.getSizeInBits());
473 break;
474 }
475 case TargetOpcode::G_SITOFP:
476 case TargetOpcode::G_UITOFP: {
477 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
478 OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
479 OpdsMapping[1] = GPRValueMapping;
480 break;
481 }
482 case TargetOpcode::G_FCMP: {
483 LLT Ty = MRI.getType(MI.getOperand(2).getReg());
484
485 unsigned Size = Ty.getSizeInBits();
486
487 OpdsMapping[0] = GPRValueMapping;
488 OpdsMapping[2] = OpdsMapping[3] = getFPValueMapping(Size);
489 break;
490 }
491 case TargetOpcode::G_MERGE_VALUES: {
492 // Use FPR64 for s64 merge on rv32.
493 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
494 if (GPRSize == 32 && Ty.getSizeInBits() == 64) {
495 assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());
496 OpdsMapping[0] = getFPValueMapping(Ty.getSizeInBits());
497 OpdsMapping[1] = GPRValueMapping;
498 OpdsMapping[2] = GPRValueMapping;
499 }
500 break;
501 }
502 case TargetOpcode::G_UNMERGE_VALUES: {
503 // Use FPR64 for s64 unmerge on rv32.
504 LLT Ty = MRI.getType(MI.getOperand(2).getReg());
505 if (GPRSize == 32 && Ty.getSizeInBits() == 64) {
506 assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());
507 OpdsMapping[0] = GPRValueMapping;
508 OpdsMapping[1] = GPRValueMapping;
509 OpdsMapping[2] = getFPValueMapping(Ty.getSizeInBits());
510 }
511 break;
512 }
513 case TargetOpcode::G_SPLAT_VECTOR: {
514 OpdsMapping[0] = getVRBValueMapping(MRI.getType(MI.getOperand(0).getReg())
517
518 LLT ScalarTy = MRI.getType(MI.getOperand(1).getReg());
519 MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(1).getReg());
520 if ((GPRSize == 32 && ScalarTy.getSizeInBits() == 64) ||
521 onlyDefinesFP(*DefMI, MRI, TRI)) {
522 assert(MF.getSubtarget<RISCVSubtarget>().hasStdExtD());
523 OpdsMapping[1] = getFPValueMapping(ScalarTy.getSizeInBits());
524 } else
525 OpdsMapping[1] = GPRValueMapping;
526 break;
527 }
528 case TargetOpcode::G_INTRINSIC: {
529 Intrinsic::ID IntrinsicID = cast<GIntrinsic>(MI).getIntrinsicID();
530
532 RISCVVIntrinsicsTable::getRISCVVIntrinsicInfo(IntrinsicID)) {
533 unsigned ScalarIdx = -1;
534 if (II->hasScalarOperand()) {
535 ScalarIdx = II->ScalarOperand + 2;
536 }
537 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
538 const MachineOperand &MO = MI.getOperand(Idx);
539 if (!MO.isReg())
540 continue;
541 LLT Ty = MRI.getType(MO.getReg());
542 if (Ty.isVector()) {
543 OpdsMapping[Idx] =
544 getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue());
545 } else if (II->IsFPIntrinsic && ScalarIdx == Idx) {
546 // Chose the right FPR for scalar operand of RVV intrinsics.
547 OpdsMapping[Idx] = getFPValueMapping(Ty.getSizeInBits());
548 } else {
549 OpdsMapping[Idx] = GPRValueMapping;
550 }
551 }
552 }
553
554 if (IntrinsicID == Intrinsic::riscv_vsetvli ||
555 IntrinsicID == Intrinsic::riscv_vsetvlimax) {
556 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
557 const MachineOperand &MO = MI.getOperand(Idx);
558 if (!MO.isReg())
559 continue;
560 OpdsMapping[Idx] = GPRValueMapping;
561 }
562 }
563 break;
564 }
565 default:
566 // By default map all scalars to GPR.
567 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
568 auto &MO = MI.getOperand(Idx);
569 if (!MO.isReg() || !MO.getReg())
570 continue;
571 LLT Ty = MRI.getType(MO.getReg());
572 if (!Ty.isValid())
573 continue;
574
575 if (Ty.isVector())
576 OpdsMapping[Idx] =
577 getVRBValueMapping(Ty.getSizeInBits().getKnownMinValue());
579 OpdsMapping[Idx] = getFPValueMapping(Ty.getSizeInBits());
580 else
581 OpdsMapping[Idx] = GPRValueMapping;
582 }
583 break;
584 }
585
586 return getInstructionMapping(DefaultMappingID, /*Cost=*/1,
587 getOperandsMapping(OpdsMapping), NumOperands);
588}
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)
This file declares the targeting of the RegisterBankInfo class for RISC-V.
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 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:165
#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:1746
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:1694
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.