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