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