1 //===- AArch64RegisterBankInfo.cpp ----------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// This file implements the targeting of the RegisterBankInfo class for
12 /// \todo This should be generated by TableGen.
13 //===----------------------------------------------------------------------===//
15 #include "AArch64RegisterBankInfo.h"
16 #include "AArch64InstrInfo.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/CodeGen/LowLevelType.h"
19 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
21 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
22 #include "llvm/CodeGen/MachineFunction.h"
23 #include "llvm/CodeGen/MachineInstr.h"
24 #include "llvm/CodeGen/MachineOperand.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Target/TargetOpcodes.h"
27 #include "llvm/Target/TargetRegisterInfo.h"
28 #include "llvm/Target/TargetSubtargetInfo.h"
32 #define GET_TARGET_REGBANK_IMPL
33 #include "AArch64GenRegisterBank.inc"
35 // This file will be TableGen'ed at some point.
36 #include "AArch64GenRegisterBankInfo.def"
40 #ifndef LLVM_BUILD_GLOBAL_ISEL
41 #error "You shouldn't build this"
44 AArch64RegisterBankInfo::AArch64RegisterBankInfo(const TargetRegisterInfo &TRI)
45 : AArch64GenRegisterBankInfo() {
46 static bool AlreadyInit = false;
47 // We have only one set of register banks, whatever the subtarget
48 // is. Therefore, the initialization of the RegBanks table should be
49 // done only once. Indeed the table of all register banks
50 // (AArch64::RegBanks) is unique in the compiler. At some point, it
51 // will get tablegen'ed and the whole constructor becomes empty.
56 const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID);
58 assert(&AArch64::GPRRegBank == &RBGPR &&
59 "The order in RegBanks is messed up");
61 const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID);
63 assert(&AArch64::FPRRegBank == &RBFPR &&
64 "The order in RegBanks is messed up");
66 const RegisterBank &RBCCR = getRegBank(AArch64::CCRRegBankID);
68 assert(&AArch64::CCRRegBank == &RBCCR &&
69 "The order in RegBanks is messed up");
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(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
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(RBFPR.getSize() == 512 &&
84 "FPRs should hold up to 512-bit via QQQQ sequence");
86 assert(RBCCR.covers(*TRI.getRegClass(AArch64::CCRRegClassID)) &&
88 assert(RBCCR.getSize() == 32 && "CCR should hold up to 32-bit");
90 // Check that the TableGen'ed like file is in sync we our expectations.
92 assert(checkPartialMappingIdx(PMI_FirstGPR, PMI_LastGPR,
93 {PMI_GPR32, PMI_GPR64}) &&
94 "PartialMappingIdx's are incorrectly ordered");
95 assert(checkPartialMappingIdx(
96 PMI_FirstFPR, PMI_LastFPR,
97 {PMI_FPR32, PMI_FPR64, PMI_FPR128, PMI_FPR256, PMI_FPR512}) &&
98 "PartialMappingIdx's are incorrectly ordered");
100 // Check partial mapping.
101 #define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB) \
104 checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \
105 #Idx " is incorrectly initialized"); \
108 CHECK_PARTIALMAP(PMI_GPR32, 0, 32, RBGPR);
109 CHECK_PARTIALMAP(PMI_GPR64, 0, 64, RBGPR);
110 CHECK_PARTIALMAP(PMI_FPR32, 0, 32, RBFPR);
111 CHECK_PARTIALMAP(PMI_FPR64, 0, 64, RBFPR);
112 CHECK_PARTIALMAP(PMI_FPR128, 0, 128, RBFPR);
113 CHECK_PARTIALMAP(PMI_FPR256, 0, 256, RBFPR);
114 CHECK_PARTIALMAP(PMI_FPR512, 0, 512, RBFPR);
116 // Check value mapping.
117 #define CHECK_VALUEMAP_IMPL(RBName, Size, Offset) \
119 assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size, \
120 PartialMappingIdx::PMI_First##RBName, Size, \
122 #RBName #Size " " #Offset " is incorrectly initialized"); \
125 #define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0)
127 CHECK_VALUEMAP(GPR, 32);
128 CHECK_VALUEMAP(GPR, 64);
129 CHECK_VALUEMAP(FPR, 32);
130 CHECK_VALUEMAP(FPR, 64);
131 CHECK_VALUEMAP(FPR, 128);
132 CHECK_VALUEMAP(FPR, 256);
133 CHECK_VALUEMAP(FPR, 512);
135 // Check the value mapping for 3-operands instructions where all the operands
136 // map to the same value mapping.
137 #define CHECK_VALUEMAP_3OPS(RBName, Size) \
139 CHECK_VALUEMAP_IMPL(RBName, Size, 0); \
140 CHECK_VALUEMAP_IMPL(RBName, Size, 1); \
141 CHECK_VALUEMAP_IMPL(RBName, Size, 2); \
144 CHECK_VALUEMAP_3OPS(GPR, 32);
145 CHECK_VALUEMAP_3OPS(GPR, 64);
146 CHECK_VALUEMAP_3OPS(FPR, 32);
147 CHECK_VALUEMAP_3OPS(FPR, 64);
148 CHECK_VALUEMAP_3OPS(FPR, 128);
149 CHECK_VALUEMAP_3OPS(FPR, 256);
150 CHECK_VALUEMAP_3OPS(FPR, 512);
152 #define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size) \
154 unsigned PartialMapDstIdx = PMI_##RBNameDst##Size - PMI_Min; \
155 unsigned PartialMapSrcIdx = PMI_##RBNameSrc##Size - PMI_Min; \
156 (void)PartialMapDstIdx; \
157 (void)PartialMapSrcIdx; \
158 const ValueMapping *Map = getCopyMapping( \
159 AArch64::RBNameDst##RegBankID, AArch64::RBNameSrc##RegBankID, Size); \
161 assert(Map[0].BreakDown == \
162 &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
163 Map[0].NumBreakDowns == 1 && #RBNameDst #Size \
164 " Dst is incorrectly initialized"); \
165 assert(Map[1].BreakDown == \
166 &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
167 Map[1].NumBreakDowns == 1 && #RBNameSrc #Size \
168 " Src is incorrectly initialized"); \
172 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 32);
173 CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 32);
174 CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 64);
175 CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 64);
176 CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 32);
177 CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 32);
178 CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 64);
179 CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 64);
181 assert(verify(TRI) && "Invalid register bank information");
184 unsigned AArch64RegisterBankInfo::copyCost(const RegisterBank &A,
185 const RegisterBank &B,
186 unsigned Size) const {
187 // What do we do with different size?
188 // copy are same size.
189 // Will introduce other hooks for different size:
191 // * build_sequence cost.
193 // Copy from (resp. to) GPR to (resp. from) FPR involves FMOV.
194 // FIXME: This should be deduced from the scheduling model.
195 if (&A == &AArch64::GPRRegBank && &B == &AArch64::FPRRegBank)
196 // FMOVXDr or FMOVWSr.
198 if (&A == &AArch64::FPRRegBank && &B == &AArch64::GPRRegBank)
199 // FMOVDXr or FMOVSWr.
202 return RegisterBankInfo::copyCost(A, B, Size);
205 const RegisterBank &AArch64RegisterBankInfo::getRegBankFromRegClass(
206 const TargetRegisterClass &RC) const {
207 switch (RC.getID()) {
208 case AArch64::FPR8RegClassID:
209 case AArch64::FPR16RegClassID:
210 case AArch64::FPR32RegClassID:
211 case AArch64::FPR64RegClassID:
212 case AArch64::FPR128RegClassID:
213 case AArch64::FPR128_loRegClassID:
214 case AArch64::DDRegClassID:
215 case AArch64::DDDRegClassID:
216 case AArch64::DDDDRegClassID:
217 case AArch64::QQRegClassID:
218 case AArch64::QQQRegClassID:
219 case AArch64::QQQQRegClassID:
220 return getRegBank(AArch64::FPRRegBankID);
221 case AArch64::GPR32commonRegClassID:
222 case AArch64::GPR32RegClassID:
223 case AArch64::GPR32spRegClassID:
224 case AArch64::GPR32sponlyRegClassID:
225 case AArch64::GPR32allRegClassID:
226 case AArch64::GPR64commonRegClassID:
227 case AArch64::GPR64RegClassID:
228 case AArch64::GPR64spRegClassID:
229 case AArch64::GPR64sponlyRegClassID:
230 case AArch64::GPR64allRegClassID:
231 case AArch64::tcGPR64RegClassID:
232 case AArch64::WSeqPairsClassRegClassID:
233 case AArch64::XSeqPairsClassRegClassID:
234 return getRegBank(AArch64::GPRRegBankID);
235 case AArch64::CCRRegClassID:
236 return getRegBank(AArch64::CCRRegBankID);
238 llvm_unreachable("Register class not supported");
242 RegisterBankInfo::InstructionMappings
243 AArch64RegisterBankInfo::getInstrAlternativeMappings(
244 const MachineInstr &MI) const {
245 const MachineFunction &MF = *MI.getParent()->getParent();
246 const TargetSubtargetInfo &STI = MF.getSubtarget();
247 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
248 const MachineRegisterInfo &MRI = MF.getRegInfo();
250 switch (MI.getOpcode()) {
251 case TargetOpcode::G_OR: {
252 // 32 and 64-bit or can be mapped on either FPR or
253 // GPR for the same cost.
254 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
255 if (Size != 32 && Size != 64)
258 // If the instruction has any implicit-defs or uses,
259 // do not mess with it.
260 if (MI.getNumOperands() != 3)
262 InstructionMappings AltMappings;
263 const InstructionMapping &GPRMapping = getInstructionMapping(
264 /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size),
266 const InstructionMapping &FPRMapping = getInstructionMapping(
267 /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size),
270 AltMappings.push_back(&GPRMapping);
271 AltMappings.push_back(&FPRMapping);
274 case TargetOpcode::G_BITCAST: {
275 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
276 if (Size != 32 && Size != 64)
279 // If the instruction has any implicit-defs or uses,
280 // do not mess with it.
281 if (MI.getNumOperands() != 2)
284 InstructionMappings AltMappings;
285 const InstructionMapping &GPRMapping = getInstructionMapping(
286 /*ID*/ 1, /*Cost*/ 1,
287 getCopyMapping(AArch64::GPRRegBankID, AArch64::GPRRegBankID, Size),
289 const InstructionMapping &FPRMapping = getInstructionMapping(
290 /*ID*/ 2, /*Cost*/ 1,
291 getCopyMapping(AArch64::FPRRegBankID, AArch64::FPRRegBankID, Size),
293 const InstructionMapping &GPRToFPRMapping = getInstructionMapping(
295 /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
296 getCopyMapping(AArch64::FPRRegBankID, AArch64::GPRRegBankID, Size),
298 const InstructionMapping &FPRToGPRMapping = getInstructionMapping(
300 /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
301 getCopyMapping(AArch64::GPRRegBankID, AArch64::FPRRegBankID, Size),
304 AltMappings.push_back(&GPRMapping);
305 AltMappings.push_back(&FPRMapping);
306 AltMappings.push_back(&GPRToFPRMapping);
307 AltMappings.push_back(&FPRToGPRMapping);
310 case TargetOpcode::G_LOAD: {
311 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
315 // If the instruction has any implicit-defs or uses,
316 // do not mess with it.
317 if (MI.getNumOperands() != 2)
320 InstructionMappings AltMappings;
321 const InstructionMapping &GPRMapping = getInstructionMapping(
322 /*ID*/ 1, /*Cost*/ 1,
323 getOperandsMapping({getValueMapping(PMI_FirstGPR, Size),
324 // Addresses are GPR 64-bit.
325 getValueMapping(PMI_FirstGPR, 64)}),
327 const InstructionMapping &FPRMapping = getInstructionMapping(
328 /*ID*/ 2, /*Cost*/ 1,
329 getOperandsMapping({getValueMapping(PMI_FirstFPR, Size),
330 // Addresses are GPR 64-bit.
331 getValueMapping(PMI_FirstGPR, 64)}),
334 AltMappings.push_back(&GPRMapping);
335 AltMappings.push_back(&FPRMapping);
341 return RegisterBankInfo::getInstrAlternativeMappings(MI);
344 void AArch64RegisterBankInfo::applyMappingImpl(
345 const OperandsMapper &OpdMapper) const {
346 switch (OpdMapper.getMI().getOpcode()) {
347 case TargetOpcode::G_OR:
348 case TargetOpcode::G_BITCAST:
349 case TargetOpcode::G_LOAD:
350 // Those ID must match getInstrAlternativeMappings.
351 assert((OpdMapper.getInstrMapping().getID() >= 1 &&
352 OpdMapper.getInstrMapping().getID() <= 4) &&
353 "Don't know how to handle that ID");
354 return applyDefaultMapping(OpdMapper);
356 llvm_unreachable("Don't know how to handle that operation");
360 /// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode,
361 /// having only floating-point operands.
362 static bool isPreISelGenericFloatingPointOpcode(unsigned Opc) {
364 case TargetOpcode::G_FADD:
365 case TargetOpcode::G_FSUB:
366 case TargetOpcode::G_FMUL:
367 case TargetOpcode::G_FDIV:
368 case TargetOpcode::G_FCONSTANT:
369 case TargetOpcode::G_FPEXT:
370 case TargetOpcode::G_FPTRUNC:
376 const RegisterBankInfo::InstructionMapping &
377 AArch64RegisterBankInfo::getSameKindOfOperandsMapping(
378 const MachineInstr &MI) const {
379 const unsigned Opc = MI.getOpcode();
380 const MachineFunction &MF = *MI.getParent()->getParent();
381 const MachineRegisterInfo &MRI = MF.getRegInfo();
383 unsigned NumOperands = MI.getNumOperands();
384 assert(NumOperands <= 3 &&
385 "This code is for instructions with 3 or less operands");
387 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
388 unsigned Size = Ty.getSizeInBits();
389 bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
391 PartialMappingIdx RBIdx = IsFPR ? PMI_FirstFPR : PMI_FirstGPR;
394 // Make sure all the operands are using similar size and type.
395 // Should probably be checked by the machine verifier.
396 // This code won't catch cases where the number of lanes is
397 // different between the operands.
398 // If we want to go to that level of details, it is probably
399 // best to check that the types are the same, period.
400 // Currently, we just check that the register banks are the same
402 for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
403 LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
405 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(
406 RBIdx, OpTy.getSizeInBits()) ==
407 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(RBIdx, Size) &&
408 "Operand has incompatible size");
409 bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
411 assert(IsFPR == OpIsFPR && "Operand has incompatible type");
413 #endif // End NDEBUG.
415 return getInstructionMapping(DefaultMappingID, 1,
416 getValueMapping(RBIdx, Size), NumOperands);
419 const RegisterBankInfo::InstructionMapping &
420 AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
421 const unsigned Opc = MI.getOpcode();
422 const MachineFunction &MF = *MI.getParent()->getParent();
423 const MachineRegisterInfo &MRI = MF.getRegInfo();
425 // Try the default logic for non-generic instructions that are either copies
426 // or already have some operands assigned to banks.
427 if (!isPreISelGenericOpcode(Opc)) {
428 const RegisterBankInfo::InstructionMapping &Mapping =
429 getInstrMappingImpl(MI);
430 if (Mapping.isValid())
435 // G_{F|S|U}REM are not listed because they are not legal.
437 case TargetOpcode::G_ADD:
438 case TargetOpcode::G_SUB:
439 case TargetOpcode::G_GEP:
440 case TargetOpcode::G_MUL:
441 case TargetOpcode::G_SDIV:
442 case TargetOpcode::G_UDIV:
444 case TargetOpcode::G_AND:
445 case TargetOpcode::G_OR:
446 case TargetOpcode::G_XOR:
448 case TargetOpcode::G_SHL:
449 case TargetOpcode::G_LSHR:
450 case TargetOpcode::G_ASHR:
451 // Floating point ops.
452 case TargetOpcode::G_FADD:
453 case TargetOpcode::G_FSUB:
454 case TargetOpcode::G_FMUL:
455 case TargetOpcode::G_FDIV:
456 return getSameKindOfOperandsMapping(MI);
457 case TargetOpcode::G_BITCAST: {
458 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
459 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
460 unsigned Size = DstTy.getSizeInBits();
461 bool DstIsGPR = !DstTy.isVector();
462 bool SrcIsGPR = !SrcTy.isVector();
463 const RegisterBank &DstRB =
464 DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
465 const RegisterBank &SrcRB =
466 SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
467 return getInstructionMapping(
468 DefaultMappingID, copyCost(DstRB, SrcRB, Size),
469 getCopyMapping(DstRB.getID(), SrcRB.getID(), Size),
472 case TargetOpcode::G_SEQUENCE:
473 // FIXME: support this, but the generic code is really not going to do
475 return getInvalidInstructionMapping();
480 unsigned NumOperands = MI.getNumOperands();
482 // Track the size and bank of each register. We don't do partial mappings.
483 SmallVector<unsigned, 4> OpSize(NumOperands);
484 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
485 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
486 auto &MO = MI.getOperand(Idx);
487 if (!MO.isReg() || !MO.getReg())
490 LLT Ty = MRI.getType(MO.getReg());
491 OpSize[Idx] = Ty.getSizeInBits();
493 // As a top-level guess, vectors go in FPRs, scalars and pointers in GPRs.
494 // For floating-point instructions, scalars go in FPRs.
495 if (Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc))
496 OpRegBankIdx[Idx] = PMI_FirstFPR;
498 OpRegBankIdx[Idx] = PMI_FirstGPR;
502 // Some of the floating-point instructions have mixed GPR and FPR operands:
503 // fine-tune the computed mapping.
505 case TargetOpcode::G_SITOFP:
506 case TargetOpcode::G_UITOFP:
507 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
509 case TargetOpcode::G_FPTOSI:
510 case TargetOpcode::G_FPTOUI:
511 OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
513 case TargetOpcode::G_FCMP:
514 OpRegBankIdx = {PMI_FirstGPR,
515 /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR};
517 case TargetOpcode::G_BITCAST:
518 // This is going to be a cross register bank copy and this is expensive.
519 if (OpRegBankIdx[0] != OpRegBankIdx[1])
521 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank,
522 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank,
525 case TargetOpcode::G_LOAD:
526 // Loading in vector unit is slightly more expensive.
527 // This is actually only true for the LD1R and co instructions,
528 // but anyway for the fast mode this number does not matter and
529 // for the greedy mode the cost of the cross bank copy will
530 // offset this number.
531 // FIXME: Should be derived from the scheduling model.
532 if (OpRegBankIdx[0] >= PMI_FirstFPR)
537 // Finally construct the computed mapping.
538 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
539 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
540 if (MI.getOperand(Idx).isReg() && MI.getOperand(Idx).getReg()) {
541 auto Mapping = getValueMapping(OpRegBankIdx[Idx], OpSize[Idx]);
542 if (!Mapping->isValid())
543 return getInvalidInstructionMapping();
545 OpdsMapping[Idx] = Mapping;
549 return getInstructionMapping(DefaultMappingID, Cost,
550 getOperandsMapping(OpdsMapping), NumOperands);