LLVM 18.0.0git
AArch64RegisterBankInfo.cpp
Go to the documentation of this file.
1//===- AArch64RegisterBankInfo.cpp ----------------------------------------===//
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
10/// AArch64.
11/// \todo This should be generated by TableGen.
12//===----------------------------------------------------------------------===//
13
15#include "AArch64RegisterInfo.h"
17#include "llvm/ADT/STLExtras.h"
31#include "llvm/IR/IntrinsicsAArch64.h"
34#include <algorithm>
35#include <cassert>
36
37#define GET_TARGET_REGBANK_IMPL
38#include "AArch64GenRegisterBank.inc"
39
40// This file will be TableGen'ed at some point.
41#include "AArch64GenRegisterBankInfo.def"
42
43using namespace llvm;
44
46 const TargetRegisterInfo &TRI) {
47 static llvm::once_flag InitializeRegisterBankFlag;
48
49 static auto InitializeRegisterBankOnce = [&]() {
50 // We have only one set of register banks, whatever the subtarget
51 // is. Therefore, the initialization of the RegBanks table should be
52 // done only once. Indeed the table of all register banks
53 // (AArch64::RegBanks) is unique in the compiler. At some point, it
54 // will get tablegen'ed and the whole constructor becomes empty.
55
56 const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID);
57 (void)RBGPR;
58 assert(&AArch64::GPRRegBank == &RBGPR &&
59 "The order in RegBanks is messed up");
60
61 const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID);
62 (void)RBFPR;
63 assert(&AArch64::FPRRegBank == &RBFPR &&
64 "The order in RegBanks is messed up");
65
66 const RegisterBank &RBCCR = getRegBank(AArch64::CCRegBankID);
67 (void)RBCCR;
68 assert(&AArch64::CCRegBank == &RBCCR &&
69 "The order in RegBanks is messed up");
70
71 // The GPR register bank is fully defined by all the registers in
72 // GR64all + its subclasses.
73 assert(RBGPR.covers(*TRI.getRegClass(AArch64::GPR32RegClassID)) &&
74 "Subclass not added?");
75 assert(getMaximumSize(RBGPR.getID()) == 128 &&
76 "GPRs should hold up to 128-bit");
77
78 // The FPR register bank is fully defined by all the registers in
79 // GR64all + its subclasses.
80 assert(RBFPR.covers(*TRI.getRegClass(AArch64::QQRegClassID)) &&
81 "Subclass not added?");
82 assert(RBFPR.covers(*TRI.getRegClass(AArch64::FPR64RegClassID)) &&
83 "Subclass not added?");
84 assert(getMaximumSize(RBFPR.getID()) == 512 &&
85 "FPRs should hold up to 512-bit via QQQQ sequence");
86
87 assert(RBCCR.covers(*TRI.getRegClass(AArch64::CCRRegClassID)) &&
88 "Class not added?");
89 assert(getMaximumSize(RBCCR.getID()) == 32 &&
90 "CCR should hold up to 32-bit");
91
92 // Check that the TableGen'ed like file is in sync we our expectations.
93 // First, the Idx.
96 "PartialMappingIdx's are incorrectly ordered");
100 "PartialMappingIdx's are incorrectly ordered");
101// Now, the content.
102// Check partial mapping.
103#define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB) \
104 do { \
105 assert( \
106 checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \
107 #Idx " is incorrectly initialized"); \
108 } while (false)
109
110 CHECK_PARTIALMAP(PMI_GPR32, 0, 32, RBGPR);
111 CHECK_PARTIALMAP(PMI_GPR64, 0, 64, RBGPR);
112 CHECK_PARTIALMAP(PMI_GPR128, 0, 128, RBGPR);
113 CHECK_PARTIALMAP(PMI_FPR16, 0, 16, RBFPR);
114 CHECK_PARTIALMAP(PMI_FPR32, 0, 32, RBFPR);
115 CHECK_PARTIALMAP(PMI_FPR64, 0, 64, RBFPR);
116 CHECK_PARTIALMAP(PMI_FPR128, 0, 128, RBFPR);
117 CHECK_PARTIALMAP(PMI_FPR256, 0, 256, RBFPR);
118 CHECK_PARTIALMAP(PMI_FPR512, 0, 512, RBFPR);
119
120// Check value mapping.
121#define CHECK_VALUEMAP_IMPL(RBName, Size, Offset) \
122 do { \
123 assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size, \
124 PartialMappingIdx::PMI_First##RBName, Size, \
125 Offset) && \
126 #RBName #Size " " #Offset " is incorrectly initialized"); \
127 } while (false)
128
129#define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0)
130
131 CHECK_VALUEMAP(GPR, 32);
132 CHECK_VALUEMAP(GPR, 64);
133 CHECK_VALUEMAP(GPR, 128);
134 CHECK_VALUEMAP(FPR, 16);
135 CHECK_VALUEMAP(FPR, 32);
136 CHECK_VALUEMAP(FPR, 64);
137 CHECK_VALUEMAP(FPR, 128);
138 CHECK_VALUEMAP(FPR, 256);
139 CHECK_VALUEMAP(FPR, 512);
140
141// Check the value mapping for 3-operands instructions where all the operands
142// map to the same value mapping.
143#define CHECK_VALUEMAP_3OPS(RBName, Size) \
144 do { \
145 CHECK_VALUEMAP_IMPL(RBName, Size, 0); \
146 CHECK_VALUEMAP_IMPL(RBName, Size, 1); \
147 CHECK_VALUEMAP_IMPL(RBName, Size, 2); \
148 } while (false)
149
150 CHECK_VALUEMAP_3OPS(GPR, 32);
151 CHECK_VALUEMAP_3OPS(GPR, 64);
152 CHECK_VALUEMAP_3OPS(GPR, 128);
158
159#define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size) \
160 do { \
161 unsigned PartialMapDstIdx = PMI_##RBNameDst##Size - PMI_Min; \
162 unsigned PartialMapSrcIdx = PMI_##RBNameSrc##Size - PMI_Min; \
163 (void)PartialMapDstIdx; \
164 (void)PartialMapSrcIdx; \
165 const ValueMapping *Map = getCopyMapping( \
166 AArch64::RBNameDst##RegBankID, AArch64::RBNameSrc##RegBankID, Size); \
167 (void)Map; \
168 assert(Map[0].BreakDown == \
169 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
170 Map[0].NumBreakDowns == 1 && #RBNameDst #Size \
171 " Dst is incorrectly initialized"); \
172 assert(Map[1].BreakDown == \
173 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
174 Map[1].NumBreakDowns == 1 && #RBNameSrc #Size \
175 " Src is incorrectly initialized"); \
176 \
177 } while (false)
178
179 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 32);
181 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 64);
187
188#define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize) \
189 do { \
190 unsigned PartialMapDstIdx = PMI_FPR##DstSize - PMI_Min; \
191 unsigned PartialMapSrcIdx = PMI_FPR##SrcSize - PMI_Min; \
192 (void)PartialMapDstIdx; \
193 (void)PartialMapSrcIdx; \
194 const ValueMapping *Map = getFPExtMapping(DstSize, SrcSize); \
195 (void)Map; \
196 assert(Map[0].BreakDown == \
197 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
198 Map[0].NumBreakDowns == 1 && "FPR" #DstSize \
199 " Dst is incorrectly initialized"); \
200 assert(Map[1].BreakDown == \
201 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
202 Map[1].NumBreakDowns == 1 && "FPR" #SrcSize \
203 " Src is incorrectly initialized"); \
204 \
205 } while (false)
206
207 CHECK_VALUEMAP_FPEXT(32, 16);
208 CHECK_VALUEMAP_FPEXT(64, 16);
209 CHECK_VALUEMAP_FPEXT(64, 32);
210 CHECK_VALUEMAP_FPEXT(128, 64);
211
212 assert(verify(TRI) && "Invalid register bank information");
213 };
214
215 llvm::call_once(InitializeRegisterBankFlag, InitializeRegisterBankOnce);
216}
217
219 const RegisterBank &B,
220 TypeSize Size) const {
221 // What do we do with different size?
222 // copy are same size.
223 // Will introduce other hooks for different size:
224 // * extract cost.
225 // * build_sequence cost.
226
227 // Copy from (resp. to) GPR to (resp. from) FPR involves FMOV.
228 // FIXME: This should be deduced from the scheduling model.
229 if (&A == &AArch64::GPRRegBank && &B == &AArch64::FPRRegBank)
230 // FMOVXDr or FMOVWSr.
231 return 5;
232 if (&A == &AArch64::FPRRegBank && &B == &AArch64::GPRRegBank)
233 // FMOVDXr or FMOVSWr.
234 return 4;
235
237}
238
239const RegisterBank &
241 LLT) const {
242 switch (RC.getID()) {
243 case AArch64::FPR8RegClassID:
244 case AArch64::FPR16RegClassID:
245 case AArch64::FPR16_loRegClassID:
246 case AArch64::FPR32_with_hsub_in_FPR16_loRegClassID:
247 case AArch64::FPR32RegClassID:
248 case AArch64::FPR64RegClassID:
249 case AArch64::FPR128RegClassID:
250 case AArch64::FPR64_loRegClassID:
251 case AArch64::FPR128_loRegClassID:
252 case AArch64::FPR128_0to7RegClassID:
253 case AArch64::DDRegClassID:
254 case AArch64::DDDRegClassID:
255 case AArch64::DDDDRegClassID:
256 case AArch64::QQRegClassID:
257 case AArch64::QQQRegClassID:
258 case AArch64::QQQQRegClassID:
259 return getRegBank(AArch64::FPRRegBankID);
260 case AArch64::GPR32commonRegClassID:
261 case AArch64::GPR32RegClassID:
262 case AArch64::GPR32spRegClassID:
263 case AArch64::GPR32sponlyRegClassID:
264 case AArch64::GPR32argRegClassID:
265 case AArch64::GPR32allRegClassID:
266 case AArch64::GPR64commonRegClassID:
267 case AArch64::GPR64RegClassID:
268 case AArch64::GPR64spRegClassID:
269 case AArch64::GPR64sponlyRegClassID:
270 case AArch64::GPR64argRegClassID:
271 case AArch64::GPR64allRegClassID:
272 case AArch64::GPR64noipRegClassID:
273 case AArch64::GPR64common_and_GPR64noipRegClassID:
274 case AArch64::GPR64noip_and_tcGPR64RegClassID:
275 case AArch64::tcGPR64RegClassID:
276 case AArch64::rtcGPR64RegClassID:
277 case AArch64::WSeqPairsClassRegClassID:
278 case AArch64::XSeqPairsClassRegClassID:
279 case AArch64::MatrixIndexGPR32_8_11RegClassID:
280 case AArch64::MatrixIndexGPR32_12_15RegClassID:
281 case AArch64::GPR64_with_sub_32_in_MatrixIndexGPR32_8_11RegClassID:
282 case AArch64::GPR64_with_sub_32_in_MatrixIndexGPR32_12_15RegClassID:
283 return getRegBank(AArch64::GPRRegBankID);
284 case AArch64::CCRRegClassID:
285 return getRegBank(AArch64::CCRegBankID);
286 default:
287 llvm_unreachable("Register class not supported");
288 }
289}
290
293 const MachineInstr &MI) const {
294 const MachineFunction &MF = *MI.getParent()->getParent();
295 const TargetSubtargetInfo &STI = MF.getSubtarget();
296 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
297 const MachineRegisterInfo &MRI = MF.getRegInfo();
298
299 switch (MI.getOpcode()) {
300 case TargetOpcode::G_OR: {
301 // 32 and 64-bit or can be mapped on either FPR or
302 // GPR for the same cost.
303 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
304 if (Size != 32 && Size != 64)
305 break;
306
307 // If the instruction has any implicit-defs or uses,
308 // do not mess with it.
309 if (MI.getNumOperands() != 3)
310 break;
311 InstructionMappings AltMappings;
312 const InstructionMapping &GPRMapping = getInstructionMapping(
313 /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size),
314 /*NumOperands*/ 3);
315 const InstructionMapping &FPRMapping = getInstructionMapping(
316 /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size),
317 /*NumOperands*/ 3);
318
319 AltMappings.push_back(&GPRMapping);
320 AltMappings.push_back(&FPRMapping);
321 return AltMappings;
322 }
323 case TargetOpcode::G_BITCAST: {
324 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
325 if (Size != 32 && Size != 64)
326 break;
327
328 // If the instruction has any implicit-defs or uses,
329 // do not mess with it.
330 if (MI.getNumOperands() != 2)
331 break;
332
333 InstructionMappings AltMappings;
334 const InstructionMapping &GPRMapping = getInstructionMapping(
335 /*ID*/ 1, /*Cost*/ 1,
336 getCopyMapping(AArch64::GPRRegBankID, AArch64::GPRRegBankID, Size),
337 /*NumOperands*/ 2);
338 const InstructionMapping &FPRMapping = getInstructionMapping(
339 /*ID*/ 2, /*Cost*/ 1,
340 getCopyMapping(AArch64::FPRRegBankID, AArch64::FPRRegBankID, Size),
341 /*NumOperands*/ 2);
342 const InstructionMapping &GPRToFPRMapping = getInstructionMapping(
343 /*ID*/ 3,
344 /*Cost*/
345 copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank,
347 getCopyMapping(AArch64::FPRRegBankID, AArch64::GPRRegBankID, Size),
348 /*NumOperands*/ 2);
349 const InstructionMapping &FPRToGPRMapping = getInstructionMapping(
350 /*ID*/ 3,
351 /*Cost*/
352 copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank,
354 getCopyMapping(AArch64::GPRRegBankID, AArch64::FPRRegBankID, Size),
355 /*NumOperands*/ 2);
356
357 AltMappings.push_back(&GPRMapping);
358 AltMappings.push_back(&FPRMapping);
359 AltMappings.push_back(&GPRToFPRMapping);
360 AltMappings.push_back(&FPRToGPRMapping);
361 return AltMappings;
362 }
363 case TargetOpcode::G_LOAD: {
364 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
365 if (Size != 64)
366 break;
367
368 // If the instruction has any implicit-defs or uses,
369 // do not mess with it.
370 if (MI.getNumOperands() != 2)
371 break;
372
373 InstructionMappings AltMappings;
374 const InstructionMapping &GPRMapping = getInstructionMapping(
375 /*ID*/ 1, /*Cost*/ 1,
377 // Addresses are GPR 64-bit.
379 /*NumOperands*/ 2);
380 const InstructionMapping &FPRMapping = getInstructionMapping(
381 /*ID*/ 2, /*Cost*/ 1,
383 // Addresses are GPR 64-bit.
385 /*NumOperands*/ 2);
386
387 AltMappings.push_back(&GPRMapping);
388 AltMappings.push_back(&FPRMapping);
389 return AltMappings;
390 }
391 default:
392 break;
393 }
395}
396
397void AArch64RegisterBankInfo::applyMappingImpl(
398 MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
399 switch (OpdMapper.getMI().getOpcode()) {
400 case TargetOpcode::G_OR:
401 case TargetOpcode::G_BITCAST:
402 case TargetOpcode::G_LOAD:
403 // Those ID must match getInstrAlternativeMappings.
404 assert((OpdMapper.getInstrMapping().getID() >= 1 &&
405 OpdMapper.getInstrMapping().getID() <= 4) &&
406 "Don't know how to handle that ID");
407 return applyDefaultMapping(OpdMapper);
408 default:
409 llvm_unreachable("Don't know how to handle that operation");
410 }
411}
412
413/// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode,
414/// having only floating-point operands.
415static bool isPreISelGenericFloatingPointOpcode(unsigned Opc) {
416 switch (Opc) {
417 case TargetOpcode::G_FADD:
418 case TargetOpcode::G_FSUB:
419 case TargetOpcode::G_FMUL:
420 case TargetOpcode::G_FMA:
421 case TargetOpcode::G_FDIV:
422 case TargetOpcode::G_FCONSTANT:
423 case TargetOpcode::G_FPEXT:
424 case TargetOpcode::G_FPTRUNC:
425 case TargetOpcode::G_FCEIL:
426 case TargetOpcode::G_FFLOOR:
427 case TargetOpcode::G_FNEARBYINT:
428 case TargetOpcode::G_FNEG:
429 case TargetOpcode::G_FCOS:
430 case TargetOpcode::G_FSIN:
431 case TargetOpcode::G_FLOG10:
432 case TargetOpcode::G_FLOG:
433 case TargetOpcode::G_FLOG2:
434 case TargetOpcode::G_FSQRT:
435 case TargetOpcode::G_FABS:
436 case TargetOpcode::G_FEXP:
437 case TargetOpcode::G_FRINT:
438 case TargetOpcode::G_INTRINSIC_TRUNC:
439 case TargetOpcode::G_INTRINSIC_ROUND:
440 case TargetOpcode::G_INTRINSIC_ROUNDEVEN:
441 case TargetOpcode::G_FMAXNUM:
442 case TargetOpcode::G_FMINNUM:
443 case TargetOpcode::G_FMAXIMUM:
444 case TargetOpcode::G_FMINIMUM:
445 return true;
446 }
447 return false;
448}
449
451AArch64RegisterBankInfo::getSameKindOfOperandsMapping(
452 const MachineInstr &MI) const {
453 const unsigned Opc = MI.getOpcode();
454 const MachineFunction &MF = *MI.getParent()->getParent();
455 const MachineRegisterInfo &MRI = MF.getRegInfo();
456
457 unsigned NumOperands = MI.getNumOperands();
458 assert(NumOperands <= 3 &&
459 "This code is for instructions with 3 or less operands");
460
461 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
462 unsigned Size = Ty.getSizeInBits();
463 bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
464
466
467#ifndef NDEBUG
468 // Make sure all the operands are using similar size and type.
469 // Should probably be checked by the machine verifier.
470 // This code won't catch cases where the number of lanes is
471 // different between the operands.
472 // If we want to go to that level of details, it is probably
473 // best to check that the types are the same, period.
474 // Currently, we just check that the register banks are the same
475 // for each types.
476 for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
477 LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
478 assert(
480 RBIdx, OpTy.getSizeInBits()) ==
482 "Operand has incompatible size");
483 bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
484 (void)OpIsFPR;
485 assert(IsFPR == OpIsFPR && "Operand has incompatible type");
486 }
487#endif // End NDEBUG.
488
490 getValueMapping(RBIdx, Size), NumOperands);
491}
492
493/// \returns true if a given intrinsic only uses and defines FPRs.
495 const MachineInstr &MI) {
496 // TODO: Add more intrinsics.
497 switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
498 default:
499 return false;
500 case Intrinsic::aarch64_neon_uaddlv:
501 case Intrinsic::aarch64_neon_uaddv:
502 case Intrinsic::aarch64_neon_saddv:
503 case Intrinsic::aarch64_neon_umaxv:
504 case Intrinsic::aarch64_neon_smaxv:
505 case Intrinsic::aarch64_neon_uminv:
506 case Intrinsic::aarch64_neon_sminv:
507 case Intrinsic::aarch64_neon_faddv:
508 case Intrinsic::aarch64_neon_fmaxv:
509 case Intrinsic::aarch64_neon_fminv:
510 case Intrinsic::aarch64_neon_fmaxnmv:
511 case Intrinsic::aarch64_neon_fminnmv:
512 return true;
513 case Intrinsic::aarch64_neon_saddlv: {
514 const LLT SrcTy = MRI.getType(MI.getOperand(2).getReg());
515 return SrcTy.getElementType().getSizeInBits() >= 16 &&
516 SrcTy.getElementCount().getFixedValue() >= 4;
517 }
518 }
519}
520
521bool AArch64RegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
523 const TargetRegisterInfo &TRI,
524 unsigned Depth) const {
525 unsigned Op = MI.getOpcode();
526 if (Op == TargetOpcode::G_INTRINSIC && isFPIntrinsic(MRI, MI))
527 return true;
528
529 // Do we have an explicit floating point instruction?
531 return true;
532
533 // No. Check if we have a copy-like instruction. If we do, then we could
534 // still be fed by floating point instructions.
535 if (Op != TargetOpcode::COPY && !MI.isPHI() &&
537 return false;
538
539 // Check if we already know the register bank.
540 auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);
541 if (RB == &AArch64::FPRRegBank)
542 return true;
543 if (RB == &AArch64::GPRRegBank)
544 return false;
545
546 // We don't know anything.
547 //
548 // If we have a phi, we may be able to infer that it will be assigned a FPR
549 // based off of its inputs.
550 if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
551 return false;
552
553 return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {
554 return Op.isReg() &&
555 onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
556 });
557}
558
559bool AArch64RegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
561 const TargetRegisterInfo &TRI,
562 unsigned Depth) const {
563 switch (MI.getOpcode()) {
564 case TargetOpcode::G_FPTOSI:
565 case TargetOpcode::G_FPTOUI:
566 case TargetOpcode::G_FCMP:
567 case TargetOpcode::G_LROUND:
568 case TargetOpcode::G_LLROUND:
569 return true;
570 default:
571 break;
572 }
573 return hasFPConstraints(MI, MRI, TRI, Depth);
574}
575
576bool AArch64RegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
578 const TargetRegisterInfo &TRI,
579 unsigned Depth) const {
580 switch (MI.getOpcode()) {
581 case AArch64::G_DUP:
582 case TargetOpcode::G_SITOFP:
583 case TargetOpcode::G_UITOFP:
584 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
585 case TargetOpcode::G_INSERT_VECTOR_ELT:
586 case TargetOpcode::G_BUILD_VECTOR:
587 case TargetOpcode::G_BUILD_VECTOR_TRUNC:
588 return true;
589 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
590 switch (cast<GIntrinsic>(MI).getIntrinsicID()) {
591 case Intrinsic::aarch64_neon_ld1x2:
592 case Intrinsic::aarch64_neon_ld1x3:
593 case Intrinsic::aarch64_neon_ld1x4:
594 case Intrinsic::aarch64_neon_ld2:
595 case Intrinsic::aarch64_neon_ld2lane:
596 case Intrinsic::aarch64_neon_ld2r:
597 case Intrinsic::aarch64_neon_ld3:
598 case Intrinsic::aarch64_neon_ld3lane:
599 case Intrinsic::aarch64_neon_ld3r:
600 case Intrinsic::aarch64_neon_ld4:
601 case Intrinsic::aarch64_neon_ld4lane:
602 case Intrinsic::aarch64_neon_ld4r:
603 return true;
604 default:
605 break;
606 }
607 break;
608 default:
609 break;
610 }
611 return hasFPConstraints(MI, MRI, TRI, Depth);
612}
613
614bool AArch64RegisterBankInfo::isLoadFromFPType(const MachineInstr &MI) const {
615 // GMemOperation because we also want to match indexed loads.
616 auto *MemOp = cast<GMemOperation>(&MI);
617 const Value *LdVal = MemOp->getMMO().getValue();
618 if (!LdVal)
619 return false;
620
621 Type *EltTy = nullptr;
622 if (const GlobalValue *GV = dyn_cast<GlobalValue>(LdVal)) {
623 EltTy = GV->getValueType();
624 } else {
625 // FIXME: grubbing around uses is pretty ugly, but with no more
626 // `getPointerElementType` there's not much else we can do.
627 for (const auto *LdUser : LdVal->users()) {
628 if (isa<LoadInst>(LdUser)) {
629 EltTy = LdUser->getType();
630 break;
631 }
632 if (isa<StoreInst>(LdUser) && LdUser->getOperand(1) == LdVal) {
633 EltTy = LdUser->getOperand(0)->getType();
634 break;
635 }
636 }
637 }
638 return EltTy && EltTy->isFPOrFPVectorTy();
639}
640
643 const unsigned Opc = MI.getOpcode();
644
645 // Try the default logic for non-generic instructions that are either copies
646 // or already have some operands assigned to banks.
647 if ((Opc != TargetOpcode::COPY && !isPreISelGenericOpcode(Opc)) ||
648 Opc == TargetOpcode::G_PHI) {
651 if (Mapping.isValid())
652 return Mapping;
653 }
654
655 const MachineFunction &MF = *MI.getParent()->getParent();
656 const MachineRegisterInfo &MRI = MF.getRegInfo();
657 const TargetSubtargetInfo &STI = MF.getSubtarget();
658 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
659
660 switch (Opc) {
661 // G_{F|S|U}REM are not listed because they are not legal.
662 // Arithmetic ops.
663 case TargetOpcode::G_ADD:
664 case TargetOpcode::G_SUB:
665 case TargetOpcode::G_PTR_ADD:
666 case TargetOpcode::G_MUL:
667 case TargetOpcode::G_SDIV:
668 case TargetOpcode::G_UDIV:
669 // Bitwise ops.
670 case TargetOpcode::G_AND:
671 case TargetOpcode::G_OR:
672 case TargetOpcode::G_XOR:
673 // Floating point ops.
674 case TargetOpcode::G_FADD:
675 case TargetOpcode::G_FSUB:
676 case TargetOpcode::G_FMUL:
677 case TargetOpcode::G_FDIV:
678 case TargetOpcode::G_FMAXIMUM:
679 case TargetOpcode::G_FMINIMUM:
680 return getSameKindOfOperandsMapping(MI);
681 case TargetOpcode::G_FPEXT: {
682 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
683 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
685 DefaultMappingID, /*Cost*/ 1,
687 /*NumOperands*/ 2);
688 }
689 // Shifts.
690 case TargetOpcode::G_SHL:
691 case TargetOpcode::G_LSHR:
692 case TargetOpcode::G_ASHR: {
693 LLT ShiftAmtTy = MRI.getType(MI.getOperand(2).getReg());
694 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
695 if (ShiftAmtTy.getSizeInBits() == 64 && SrcTy.getSizeInBits() == 32)
698 return getSameKindOfOperandsMapping(MI);
699 }
700 case TargetOpcode::COPY: {
701 Register DstReg = MI.getOperand(0).getReg();
702 Register SrcReg = MI.getOperand(1).getReg();
703 // Check if one of the register is not a generic register.
704 if ((DstReg.isPhysical() || !MRI.getType(DstReg).isValid()) ||
705 (SrcReg.isPhysical() || !MRI.getType(SrcReg).isValid())) {
706 const RegisterBank *DstRB = getRegBank(DstReg, MRI, TRI);
707 const RegisterBank *SrcRB = getRegBank(SrcReg, MRI, TRI);
708 if (!DstRB)
709 DstRB = SrcRB;
710 else if (!SrcRB)
711 SrcRB = DstRB;
712 // If both RB are null that means both registers are generic.
713 // We shouldn't be here.
714 assert(DstRB && SrcRB && "Both RegBank were nullptr");
715 unsigned Size = getSizeInBits(DstReg, MRI, TRI);
718 getCopyMapping(DstRB->getID(), SrcRB->getID(), Size),
719 // We only care about the mapping of the destination.
720 /*NumOperands*/ 1);
721 }
722 // Both registers are generic, use G_BITCAST.
723 [[fallthrough]];
724 }
725 case TargetOpcode::G_BITCAST: {
726 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
727 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
728 unsigned Size = DstTy.getSizeInBits();
729 bool DstIsGPR = !DstTy.isVector() && DstTy.getSizeInBits() <= 64;
730 bool SrcIsGPR = !SrcTy.isVector() && SrcTy.getSizeInBits() <= 64;
731 const RegisterBank &DstRB =
732 DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
733 const RegisterBank &SrcRB =
734 SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
737 getCopyMapping(DstRB.getID(), SrcRB.getID(), Size),
738 // We only care about the mapping of the destination for COPY.
739 /*NumOperands*/ Opc == TargetOpcode::G_BITCAST ? 2 : 1);
740 }
741 default:
742 break;
743 }
744
745 unsigned NumOperands = MI.getNumOperands();
746
747 // Track the size and bank of each register. We don't do partial mappings.
748 SmallVector<unsigned, 4> OpSize(NumOperands);
749 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
750 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
751 auto &MO = MI.getOperand(Idx);
752 if (!MO.isReg() || !MO.getReg())
753 continue;
754
755 LLT Ty = MRI.getType(MO.getReg());
756 if (!Ty.isValid())
757 continue;
758 OpSize[Idx] = Ty.getSizeInBits();
759
760 // As a top-level guess, vectors go in FPRs, scalars and pointers in GPRs.
761 // For floating-point instructions, scalars go in FPRs.
763 Ty.getSizeInBits() > 64)
764 OpRegBankIdx[Idx] = PMI_FirstFPR;
765 else
766 OpRegBankIdx[Idx] = PMI_FirstGPR;
767 }
768
769 unsigned Cost = 1;
770 // Some of the floating-point instructions have mixed GPR and FPR operands:
771 // fine-tune the computed mapping.
772 switch (Opc) {
773 case AArch64::G_DUP: {
774 Register ScalarReg = MI.getOperand(1).getReg();
775 LLT ScalarTy = MRI.getType(ScalarReg);
776 auto ScalarDef = MRI.getVRegDef(ScalarReg);
777 // We want to select dup(load) into LD1R.
778 if (ScalarDef->getOpcode() == TargetOpcode::G_LOAD)
779 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
780 // s8 is an exception for G_DUP, which we always want on gpr.
781 else if (ScalarTy.getSizeInBits() != 8 &&
782 (getRegBank(ScalarReg, MRI, TRI) == &AArch64::FPRRegBank ||
783 onlyDefinesFP(*ScalarDef, MRI, TRI)))
784 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
785 else
786 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
787 break;
788 }
789 case TargetOpcode::G_TRUNC: {
790 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
791 if (!SrcTy.isVector() && SrcTy.getSizeInBits() == 128)
792 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
793 break;
794 }
795 case TargetOpcode::G_SITOFP:
796 case TargetOpcode::G_UITOFP: {
797 if (MRI.getType(MI.getOperand(0).getReg()).isVector())
798 break;
799 // Integer to FP conversions don't necessarily happen between GPR -> FPR
800 // regbanks. They can also be done within an FPR register.
801 Register SrcReg = MI.getOperand(1).getReg();
802 if (getRegBank(SrcReg, MRI, TRI) == &AArch64::FPRRegBank)
803 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
804 else
805 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
806 break;
807 }
808 case TargetOpcode::G_FPTOSI:
809 case TargetOpcode::G_FPTOUI:
810 if (MRI.getType(MI.getOperand(0).getReg()).isVector())
811 break;
812 OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
813 break;
814 case TargetOpcode::G_FCMP: {
815 // If the result is a vector, it must use a FPR.
817 MRI.getType(MI.getOperand(0).getReg()).isVector() ? PMI_FirstFPR
818 : PMI_FirstGPR;
819 OpRegBankIdx = {Idx0,
820 /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR};
821 break;
822 }
823 case TargetOpcode::G_BITCAST:
824 // This is going to be a cross register bank copy and this is expensive.
825 if (OpRegBankIdx[0] != OpRegBankIdx[1])
826 Cost = copyCost(
827 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank,
828 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank,
829 TypeSize::getFixed(OpSize[0]));
830 break;
831 case TargetOpcode::G_LOAD: {
832 // Loading in vector unit is slightly more expensive.
833 // This is actually only true for the LD1R and co instructions,
834 // but anyway for the fast mode this number does not matter and
835 // for the greedy mode the cost of the cross bank copy will
836 // offset this number.
837 // FIXME: Should be derived from the scheduling model.
838 if (OpRegBankIdx[0] != PMI_FirstGPR) {
839 Cost = 2;
840 break;
841 }
842
843 if (cast<GLoad>(MI).isAtomic()) {
844 // Atomics always use GPR destinations. Don't refine any further.
845 OpRegBankIdx[0] = PMI_FirstGPR;
846 break;
847 }
848
849 // Try to guess the type of the load from the MMO.
850 if (isLoadFromFPType(MI)) {
851 OpRegBankIdx[0] = PMI_FirstFPR;
852 break;
853 }
854
855 // Check if that load feeds fp instructions.
856 // In that case, we want the default mapping to be on FPR
857 // instead of blind map every scalar to GPR.
858 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
859 [&](const MachineInstr &UseMI) {
860 // If we have at least one direct use in a FP instruction,
861 // assume this was a floating point load in the IR. If it was
862 // not, we would have had a bitcast before reaching that
863 // instruction.
864 //
865 // Int->FP conversion operations are also captured in
866 // onlyDefinesFP().
867 return onlyUsesFP(UseMI, MRI, TRI) ||
868 onlyDefinesFP(UseMI, MRI, TRI);
869 }))
870 OpRegBankIdx[0] = PMI_FirstFPR;
871 break;
872 }
873 case TargetOpcode::G_STORE:
874 // Check if that store is fed by fp instructions.
875 if (OpRegBankIdx[0] == PMI_FirstGPR) {
876 Register VReg = MI.getOperand(0).getReg();
877 if (!VReg)
878 break;
879 MachineInstr *DefMI = MRI.getVRegDef(VReg);
880 if (onlyDefinesFP(*DefMI, MRI, TRI))
881 OpRegBankIdx[0] = PMI_FirstFPR;
882 break;
883 }
884 break;
885 case TargetOpcode::G_INDEXED_STORE:
886 if (OpRegBankIdx[1] == PMI_FirstGPR) {
887 Register VReg = MI.getOperand(1).getReg();
888 if (!VReg)
889 break;
890 MachineInstr *DefMI = MRI.getVRegDef(VReg);
891 if (onlyDefinesFP(*DefMI, MRI, TRI))
892 OpRegBankIdx[1] = PMI_FirstFPR;
893 break;
894 }
895 break;
896 case TargetOpcode::G_INDEXED_SEXTLOAD:
897 case TargetOpcode::G_INDEXED_ZEXTLOAD:
898 // These should always be GPR.
899 OpRegBankIdx[0] = PMI_FirstGPR;
900 break;
901 case TargetOpcode::G_INDEXED_LOAD: {
902 if (isLoadFromFPType(MI))
903 OpRegBankIdx[0] = PMI_FirstFPR;
904 break;
905 }
906 case TargetOpcode::G_SELECT: {
907 // If the destination is FPR, preserve that.
908 if (OpRegBankIdx[0] != PMI_FirstGPR)
909 break;
910
911 // If we're taking in vectors, we have no choice but to put everything on
912 // FPRs, except for the condition. The condition must always be on a GPR.
913 LLT SrcTy = MRI.getType(MI.getOperand(2).getReg());
914 if (SrcTy.isVector()) {
916 break;
917 }
918
919 // Try to minimize the number of copies. If we have more floating point
920 // constrained values than not, then we'll put everything on FPR. Otherwise,
921 // everything has to be on GPR.
922 unsigned NumFP = 0;
923
924 // Check if the uses of the result always produce floating point values.
925 //
926 // For example:
927 //
928 // %z = G_SELECT %cond %x %y
929 // fpr = G_FOO %z ...
930 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
931 [&](MachineInstr &MI) { return onlyUsesFP(MI, MRI, TRI); }))
932 ++NumFP;
933
934 // Check if the defs of the source values always produce floating point
935 // values.
936 //
937 // For example:
938 //
939 // %x = G_SOMETHING_ALWAYS_FLOAT %a ...
940 // %z = G_SELECT %cond %x %y
941 //
942 // Also check whether or not the sources have already been decided to be
943 // FPR. Keep track of this.
944 //
945 // This doesn't check the condition, since it's just whatever is in NZCV.
946 // This isn't passed explicitly in a register to fcsel/csel.
947 for (unsigned Idx = 2; Idx < 4; ++Idx) {
948 Register VReg = MI.getOperand(Idx).getReg();
949 MachineInstr *DefMI = MRI.getVRegDef(VReg);
950 if (getRegBank(VReg, MRI, TRI) == &AArch64::FPRRegBank ||
951 onlyDefinesFP(*DefMI, MRI, TRI))
952 ++NumFP;
953 }
954
955 // If we have more FP constraints than not, then move everything over to
956 // FPR.
957 if (NumFP >= 2)
959
960 break;
961 }
962 case TargetOpcode::G_UNMERGE_VALUES: {
963 // If the first operand belongs to a FPR register bank, then make sure that
964 // we preserve that.
965 if (OpRegBankIdx[0] != PMI_FirstGPR)
966 break;
967
968 LLT SrcTy = MRI.getType(MI.getOperand(MI.getNumOperands()-1).getReg());
969 // UNMERGE into scalars from a vector should always use FPR.
970 // Likewise if any of the uses are FP instructions.
971 if (SrcTy.isVector() || SrcTy == LLT::scalar(128) ||
972 any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
973 [&](MachineInstr &MI) { return onlyUsesFP(MI, MRI, TRI); })) {
974 // Set the register bank of every operand to FPR.
975 for (unsigned Idx = 0, NumOperands = MI.getNumOperands();
976 Idx < NumOperands; ++Idx)
977 OpRegBankIdx[Idx] = PMI_FirstFPR;
978 }
979 break;
980 }
981 case TargetOpcode::G_EXTRACT_VECTOR_ELT:
982 // Destination and source need to be FPRs.
983 OpRegBankIdx[0] = PMI_FirstFPR;
984 OpRegBankIdx[1] = PMI_FirstFPR;
985
986 // Index needs to be a GPR.
987 OpRegBankIdx[2] = PMI_FirstGPR;
988 break;
989 case TargetOpcode::G_INSERT_VECTOR_ELT:
990 OpRegBankIdx[0] = PMI_FirstFPR;
991 OpRegBankIdx[1] = PMI_FirstFPR;
992
993 // The element may be either a GPR or FPR. Preserve that behaviour.
994 if (getRegBank(MI.getOperand(2).getReg(), MRI, TRI) == &AArch64::FPRRegBank)
995 OpRegBankIdx[2] = PMI_FirstFPR;
996 else
997 OpRegBankIdx[2] = PMI_FirstGPR;
998
999 // Index needs to be a GPR.
1000 OpRegBankIdx[3] = PMI_FirstGPR;
1001 break;
1002 case TargetOpcode::G_EXTRACT: {
1003 // For s128 sources we have to use fpr unless we know otherwise.
1004 auto Src = MI.getOperand(1).getReg();
1005 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
1006 if (SrcTy.getSizeInBits() != 128)
1007 break;
1008 auto Idx = MRI.getRegClassOrNull(Src) == &AArch64::XSeqPairsClassRegClass
1009 ? PMI_FirstGPR
1010 : PMI_FirstFPR;
1011 OpRegBankIdx[0] = Idx;
1012 OpRegBankIdx[1] = Idx;
1013 break;
1014 }
1015 case TargetOpcode::G_BUILD_VECTOR: {
1016 // If the first source operand belongs to a FPR register bank, then make
1017 // sure that we preserve that.
1018 if (OpRegBankIdx[1] != PMI_FirstGPR)
1019 break;
1020 Register VReg = MI.getOperand(1).getReg();
1021 if (!VReg)
1022 break;
1023
1024 // Get the instruction that defined the source operand reg, and check if
1025 // it's a floating point operation. Or, if it's a type like s16 which
1026 // doesn't have a exact size gpr register class. The exception is if the
1027 // build_vector has all constant operands, which may be better to leave as
1028 // gpr without copies, so it can be matched in imported patterns.
1029 MachineInstr *DefMI = MRI.getVRegDef(VReg);
1030 unsigned DefOpc = DefMI->getOpcode();
1031 const LLT SrcTy = MRI.getType(VReg);
1032 if (all_of(MI.operands(), [&](const MachineOperand &Op) {
1033 return Op.isDef() || MRI.getVRegDef(Op.getReg())->getOpcode() ==
1034 TargetOpcode::G_CONSTANT;
1035 }))
1036 break;
1038 SrcTy.getSizeInBits() < 32 ||
1039 getRegBank(VReg, MRI, TRI) == &AArch64::FPRRegBank) {
1040 // Have a floating point op.
1041 // Make sure every operand gets mapped to a FPR register class.
1042 unsigned NumOperands = MI.getNumOperands();
1043 for (unsigned Idx = 0; Idx < NumOperands; ++Idx)
1044 OpRegBankIdx[Idx] = PMI_FirstFPR;
1045 }
1046 break;
1047 }
1048 case TargetOpcode::G_VECREDUCE_FADD:
1049 case TargetOpcode::G_VECREDUCE_FMUL:
1050 case TargetOpcode::G_VECREDUCE_FMAX:
1051 case TargetOpcode::G_VECREDUCE_FMIN:
1052 case TargetOpcode::G_VECREDUCE_FMAXIMUM:
1053 case TargetOpcode::G_VECREDUCE_FMINIMUM:
1054 case TargetOpcode::G_VECREDUCE_ADD:
1055 case TargetOpcode::G_VECREDUCE_MUL:
1056 case TargetOpcode::G_VECREDUCE_AND:
1057 case TargetOpcode::G_VECREDUCE_OR:
1058 case TargetOpcode::G_VECREDUCE_XOR:
1059 case TargetOpcode::G_VECREDUCE_SMAX:
1060 case TargetOpcode::G_VECREDUCE_SMIN:
1061 case TargetOpcode::G_VECREDUCE_UMAX:
1062 case TargetOpcode::G_VECREDUCE_UMIN:
1063 // Reductions produce a scalar value from a vector, the scalar should be on
1064 // FPR bank.
1065 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR};
1066 break;
1067 case TargetOpcode::G_VECREDUCE_SEQ_FADD:
1068 case TargetOpcode::G_VECREDUCE_SEQ_FMUL:
1069 // These reductions also take a scalar accumulator input.
1070 // Assign them FPR for now.
1071 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstFPR, PMI_FirstFPR};
1072 break;
1073 case TargetOpcode::G_INTRINSIC:
1074 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {
1075 // Check if we know that the intrinsic has any constraints on its register
1076 // banks. If it does, then update the mapping accordingly.
1077 unsigned Idx = 0;
1078 if (onlyDefinesFP(MI, MRI, TRI))
1079 for (const auto &Op : MI.defs()) {
1080 if (Op.isReg())
1081 OpRegBankIdx[Idx] = PMI_FirstFPR;
1082 ++Idx;
1083 }
1084 else
1085 Idx += MI.getNumExplicitDefs();
1086
1087 if (onlyUsesFP(MI, MRI, TRI))
1088 for (const auto &Op : MI.explicit_uses()) {
1089 if (Op.isReg())
1090 OpRegBankIdx[Idx] = PMI_FirstFPR;
1091 ++Idx;
1092 }
1093 break;
1094 }
1095 case TargetOpcode::G_LROUND:
1096 case TargetOpcode::G_LLROUND: {
1097 // Source is always floating point and destination is always integer.
1098 OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
1099 break;
1100 }
1101 }
1102
1103 // Finally construct the computed mapping.
1104 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
1105 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
1106 if (MI.getOperand(Idx).isReg() && MI.getOperand(Idx).getReg()) {
1107 LLT Ty = MRI.getType(MI.getOperand(Idx).getReg());
1108 if (!Ty.isValid())
1109 continue;
1110 auto Mapping = getValueMapping(OpRegBankIdx[Idx], OpSize[Idx]);
1111 if (!Mapping->isValid())
1113
1114 OpdsMapping[Idx] = Mapping;
1115 }
1116 }
1117
1119 getOperandsMapping(OpdsMapping), NumOperands);
1120}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static unsigned getIntrinsicID(const SDNode *N)
#define CHECK_VALUEMAP(RBName, Size)
static bool isFPIntrinsic(const MachineRegisterInfo &MRI, const MachineInstr &MI)
#define CHECK_VALUEMAP_3OPS(RBName, Size)
static bool isPreISelGenericFloatingPointOpcode(unsigned Opc)
Returns whether opcode Opc is a pre-isel generic floating-point opcode, having only floating-point op...
#define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB)
#define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size)
#define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize)
This file declares the targeting of the RegisterBankInfo class for AArch64.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
uint64_t Size
Declares convenience wrapper classes for interpreting MachineInstr instances as specific generic oper...
IRTranslator LLVM IR MI
Implement a low-level type suitable for MachineInstr level instruction selection.
unsigned const TargetRegisterInfo * TRI
ppc ctr loops verify
static const MCPhysReg FPR[]
FPR - The set of FP registers that should be allocated for arguments on Darwin and AIX.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallVector class.
static const RegisterBankInfo::ValueMapping * getValueMapping(PartialMappingIdx RBIdx, unsigned Size)
Get the pointer to the ValueMapping representing the RegisterBank at RBIdx with a size of Size.
static bool checkPartialMappingIdx(PartialMappingIdx FirstAlias, PartialMappingIdx LastAlias, ArrayRef< PartialMappingIdx > Order)
static const RegisterBankInfo::PartialMapping PartMappings[]
static unsigned getRegBankBaseIdxOffset(unsigned RBIdx, unsigned Size)
static const RegisterBankInfo::ValueMapping * getFPExtMapping(unsigned DstSize, unsigned SrcSize)
Get the instruction mapping for G_FPEXT.
static const RegisterBankInfo::ValueMapping * getCopyMapping(unsigned DstBankID, unsigned SrcBankID, unsigned Size)
Get the pointer to the ValueMapping of the operands of a copy instruction from the SrcBankID register...
static const RegisterBankInfo::ValueMapping ValMappings[]
const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT) const override
Get a register bank that covers RC.
InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const override
Get the alternative mappings for MI.
unsigned copyCost(const RegisterBank &A, const RegisterBank &B, TypeSize Size) const override
Get the cost of a copy from B to A, or put differently, get the cost of A = COPY B.
AArch64RegisterBankInfo(const TargetRegisterInfo &TRI)
const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override
Get the mapping of the different operands of MI on the register bank.
This class represents an Operation in the Expression.
static constexpr LLT scalar(unsigned SizeInBits)
Get a low-level scalar or aggregate "bag of bits".
Definition: LowLevelType.h:42
constexpr bool isValid() const
Definition: LowLevelType.h:137
constexpr bool isVector() const
Definition: LowLevelType.h:145
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:183
constexpr LLT getElementType() const
Returns the vector's element type. Only valid for vector types.
Definition: LowLevelType.h:280
constexpr ElementCount getElementCount() const
Definition: LowLevelType.h:174
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.
Helper class to build MachineInstr.
Representation of each machine instruction.
Definition: MachineInstr.h:68
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:543
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
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.
virtual InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const
Get the alternative mappings for MI.
const InstructionMapping & getInstructionMapping(unsigned ID, unsigned Cost, const ValueMapping *OperandsMapping, unsigned NumOperands) const
Method to get a uniquely generated InstructionMapping.
static void applyDefaultMapping(const OperandsMapper &OpdMapper)
Helper method to apply something that is like the default mapping.
const InstructionMapping & getInvalidInstructionMapping() const
Method to get a uniquely generated invalid 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.
TypeSize getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
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...
virtual unsigned copyCost(const RegisterBank &A, const RegisterBank &B, TypeSize Size) const
Get the cost of a copy from B to A, or put differently, get the cost of A = COPY B.
const InstructionMapping & getInstrMappingImpl(const MachineInstr &MI) const
Try to get the mapping of MI.
This class implements the register bank concept.
Definition: RegisterBank.h:28
bool covers(const TargetRegisterClass &RC) const
Check whether this register bank covers RC.
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:45
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
constexpr bool isPhysical() const
Return true if the specified register number is in the physical register namespace.
Definition: Register.h:95
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
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
getRegisterInfo - If register information is available, return it.
static constexpr TypeSize getFixed(ScalarTy ExactSize)
Definition: TypeSize.h:333
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
bool isFPOrFPVectorTy() const
Return true if this is a FP type or a vector of FP.
Definition: Type.h:216
LLVM Value Representation.
Definition: Value.h:74
iterator_range< user_iterator > users()
Definition: Value.h:421
constexpr ScalarTy getFixedValue() const
Definition: TypeSize.h:188
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1726
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel.
Definition: TargetOpcodes.h:30
bool isPreISelGenericOptimizationHint(unsigned Opcode)
Definition: TargetOpcodes.h:42
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:1733
void call_once(once_flag &flag, Function &&F, Args &&... ArgList)
Execute the function specified as a parameter once.
Definition: Threading.h:87
The llvm::once_flag structure.
Definition: Threading.h:68