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 InstructionMapping GPRMapping(
264 /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size),
266 InstructionMapping FPRMapping(
267 /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size),
270 AltMappings.emplace_back(std::move(GPRMapping));
271 AltMappings.emplace_back(std::move(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 InstructionMapping GPRMapping(
286 /*ID*/ 1, /*Cost*/ 1,
287 getCopyMapping(AArch64::GPRRegBankID, AArch64::GPRRegBankID, Size),
289 InstructionMapping FPRMapping(
290 /*ID*/ 2, /*Cost*/ 1,
291 getCopyMapping(AArch64::FPRRegBankID, AArch64::FPRRegBankID, Size),
293 InstructionMapping GPRToFPRMapping(
295 /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
296 getCopyMapping(AArch64::FPRRegBankID, AArch64::GPRRegBankID, Size),
298 InstructionMapping FPRToGPRMapping(
300 /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
301 getCopyMapping(AArch64::GPRRegBankID, AArch64::FPRRegBankID, Size),
304 AltMappings.emplace_back(std::move(GPRMapping));
305 AltMappings.emplace_back(std::move(FPRMapping));
306 AltMappings.emplace_back(std::move(GPRToFPRMapping));
307 AltMappings.emplace_back(std::move(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 InstructionMapping GPRMapping(
322 /*ID*/ 1, /*Cost*/ 1,
323 getOperandsMapping({getValueMapping(PMI_FirstGPR, Size),
324 // Addresses are GPR 64-bit.
325 getValueMapping(PMI_FirstGPR, 64)}),
327 InstructionMapping FPRMapping(
328 /*ID*/ 2, /*Cost*/ 1,
329 getOperandsMapping({getValueMapping(PMI_FirstFPR, Size),
330 // Addresses are GPR 64-bit.
331 getValueMapping(PMI_FirstGPR, 64)}),
334 AltMappings.emplace_back(std::move(GPRMapping));
335 AltMappings.emplace_back(std::move(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 RegisterBankInfo::InstructionMapping
377 AArch64RegisterBankInfo::getSameKindOfOperandsMapping(const MachineInstr &MI) {
378 const unsigned Opc = MI.getOpcode();
379 const MachineFunction &MF = *MI.getParent()->getParent();
380 const MachineRegisterInfo &MRI = MF.getRegInfo();
382 unsigned NumOperands = MI.getNumOperands();
383 assert(NumOperands <= 3 &&
384 "This code is for instructions with 3 or less operands");
386 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
387 unsigned Size = Ty.getSizeInBits();
388 bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
390 PartialMappingIdx RBIdx = IsFPR ? PMI_FirstFPR : PMI_FirstGPR;
393 // Make sure all the operands are using similar size and type.
394 // Should probably be checked by the machine verifier.
395 // This code won't catch cases where the number of lanes is
396 // different between the operands.
397 // If we want to go to that level of details, it is probably
398 // best to check that the types are the same, period.
399 // Currently, we just check that the register banks are the same
401 for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
402 LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
404 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(
405 RBIdx, OpTy.getSizeInBits()) ==
406 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(RBIdx, Size) &&
407 "Operand has incompatible size");
408 bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
410 assert(IsFPR == OpIsFPR && "Operand has incompatible type");
412 #endif // End NDEBUG.
414 return InstructionMapping{DefaultMappingID, 1, getValueMapping(RBIdx, Size),
418 RegisterBankInfo::InstructionMapping
419 AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
420 const unsigned Opc = MI.getOpcode();
421 const MachineFunction &MF = *MI.getParent()->getParent();
422 const MachineRegisterInfo &MRI = MF.getRegInfo();
424 // Try the default logic for non-generic instructions that are either copies
425 // or already have some operands assigned to banks.
426 if (!isPreISelGenericOpcode(Opc)) {
427 RegisterBankInfo::InstructionMapping Mapping = getInstrMappingImpl(MI);
428 if (Mapping.isValid())
433 // G_{F|S|U}REM are not listed because they are not legal.
435 case TargetOpcode::G_ADD:
436 case TargetOpcode::G_SUB:
437 case TargetOpcode::G_GEP:
438 case TargetOpcode::G_MUL:
439 case TargetOpcode::G_SDIV:
440 case TargetOpcode::G_UDIV:
442 case TargetOpcode::G_AND:
443 case TargetOpcode::G_OR:
444 case TargetOpcode::G_XOR:
446 case TargetOpcode::G_SHL:
447 case TargetOpcode::G_LSHR:
448 case TargetOpcode::G_ASHR:
449 // Floating point ops.
450 case TargetOpcode::G_FADD:
451 case TargetOpcode::G_FSUB:
452 case TargetOpcode::G_FMUL:
453 case TargetOpcode::G_FDIV:
454 return getSameKindOfOperandsMapping(MI);
455 case TargetOpcode::G_BITCAST: {
456 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
457 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
458 unsigned Size = DstTy.getSizeInBits();
459 bool DstIsGPR = !DstTy.isVector();
460 bool SrcIsGPR = !SrcTy.isVector();
461 const RegisterBank &DstRB =
462 DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
463 const RegisterBank &SrcRB =
464 SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
465 return InstructionMapping{
466 DefaultMappingID, copyCost(DstRB, SrcRB, Size),
467 getCopyMapping(DstRB.getID(), SrcRB.getID(), Size),
470 case TargetOpcode::G_SEQUENCE:
471 // FIXME: support this, but the generic code is really not going to do
473 return InstructionMapping();
478 unsigned NumOperands = MI.getNumOperands();
480 // Track the size and bank of each register. We don't do partial mappings.
481 SmallVector<unsigned, 4> OpSize(NumOperands);
482 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
483 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
484 auto &MO = MI.getOperand(Idx);
488 LLT Ty = MRI.getType(MO.getReg());
489 OpSize[Idx] = Ty.getSizeInBits();
491 // As a top-level guess, vectors go in FPRs, scalars and pointers in GPRs.
492 // For floating-point instructions, scalars go in FPRs.
493 if (Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc))
494 OpRegBankIdx[Idx] = PMI_FirstFPR;
496 OpRegBankIdx[Idx] = PMI_FirstGPR;
500 // Some of the floating-point instructions have mixed GPR and FPR operands:
501 // fine-tune the computed mapping.
503 case TargetOpcode::G_SITOFP:
504 case TargetOpcode::G_UITOFP:
505 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
507 case TargetOpcode::G_FPTOSI:
508 case TargetOpcode::G_FPTOUI:
509 OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
511 case TargetOpcode::G_FCMP:
512 OpRegBankIdx = {PMI_FirstGPR,
513 /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR};
515 case TargetOpcode::G_BITCAST:
516 // This is going to be a cross register bank copy and this is expensive.
517 if (OpRegBankIdx[0] != OpRegBankIdx[1])
519 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank,
520 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank,
523 case TargetOpcode::G_LOAD:
524 // Loading in vector unit is slightly more expensive.
525 // This is actually only true for the LD1R and co instructions,
526 // but anyway for the fast mode this number does not matter and
527 // for the greedy mode the cost of the cross bank copy will
528 // offset this number.
529 // FIXME: Should be derived from the scheduling model.
530 if (OpRegBankIdx[0] >= PMI_FirstFPR)
535 // Finally construct the computed mapping.
536 RegisterBankInfo::InstructionMapping Mapping =
537 InstructionMapping{DefaultMappingID, Cost, nullptr, NumOperands};
538 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
539 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
540 if (MI.getOperand(Idx).isReg()) {
541 auto Mapping = getValueMapping(OpRegBankIdx[Idx], OpSize[Idx]);
542 if (!Mapping->isValid())
543 return InstructionMapping();
545 OpdsMapping[Idx] = Mapping;
549 Mapping.setOperandsMapping(getOperandsMapping(OpdsMapping));