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