1 //===- AArch64RegisterBankInfo.cpp ----------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This file implements the targeting of the RegisterBankInfo class for
11 /// AArch64.
12 /// \todo This should be generated by TableGen.
13 //===----------------------------------------------------------------------===//
14 
15 #include "AArch64RegisterBankInfo.h"
16 #include "AArch64InstrInfo.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
19 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
20 #include "llvm/CodeGen/LowLevelType.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineInstr.h"
23 #include "llvm/CodeGen/MachineOperand.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/TargetOpcodes.h"
26 #include "llvm/CodeGen/TargetRegisterInfo.h"
27 #include "llvm/CodeGen/TargetSubtargetInfo.h"
28 #include "llvm/Support/ErrorHandling.h"
29 #include <algorithm>
30 #include <cassert>
31 
32 #define GET_TARGET_REGBANK_IMPL
33 #include "AArch64GenRegisterBank.inc"
34 
35 // This file will be TableGen'ed at some point.
36 #include "AArch64GenRegisterBankInfo.def"
37 
38 using namespace llvm;
39 
AArch64RegisterBankInfo(const TargetRegisterInfo & TRI)40 AArch64RegisterBankInfo::AArch64RegisterBankInfo(const TargetRegisterInfo &TRI)
41     : AArch64GenRegisterBankInfo() {
42   static bool AlreadyInit = false;
43   // We have only one set of register banks, whatever the subtarget
44   // is. Therefore, the initialization of the RegBanks table should be
45   // done only once. Indeed the table of all register banks
46   // (AArch64::RegBanks) is unique in the compiler. At some point, it
47   // will get tablegen'ed and the whole constructor becomes empty.
48   if (AlreadyInit)
49     return;
50   AlreadyInit = true;
51 
52   const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID);
53   (void)RBGPR;
54   assert(&AArch64::GPRRegBank == &RBGPR &&
55          "The order in RegBanks is messed up");
56 
57   const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID);
58   (void)RBFPR;
59   assert(&AArch64::FPRRegBank == &RBFPR &&
60          "The order in RegBanks is messed up");
61 
62   const RegisterBank &RBCCR = getRegBank(AArch64::CCRegBankID);
63   (void)RBCCR;
64   assert(&AArch64::CCRegBank == &RBCCR && "The order in RegBanks is messed up");
65 
66   // The GPR register bank is fully defined by all the registers in
67   // GR64all + its subclasses.
68   assert(RBGPR.covers(*TRI.getRegClass(AArch64::GPR32RegClassID)) &&
69          "Subclass not added?");
70   assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
71 
72   // The FPR register bank is fully defined by all the registers in
73   // GR64all + its subclasses.
74   assert(RBFPR.covers(*TRI.getRegClass(AArch64::QQRegClassID)) &&
75          "Subclass not added?");
76   assert(RBFPR.covers(*TRI.getRegClass(AArch64::FPR64RegClassID)) &&
77          "Subclass not added?");
78   assert(RBFPR.getSize() == 512 &&
79          "FPRs should hold up to 512-bit via QQQQ sequence");
80 
81   assert(RBCCR.covers(*TRI.getRegClass(AArch64::CCRRegClassID)) &&
82          "Class not added?");
83   assert(RBCCR.getSize() == 32 && "CCR should hold up to 32-bit");
84 
85   // Check that the TableGen'ed like file is in sync we our expectations.
86   // First, the Idx.
87   assert(checkPartialMappingIdx(PMI_FirstGPR, PMI_LastGPR,
88                                 {PMI_GPR32, PMI_GPR64}) &&
89          "PartialMappingIdx's are incorrectly ordered");
90   assert(checkPartialMappingIdx(PMI_FirstFPR, PMI_LastFPR,
91                                 {PMI_FPR16, PMI_FPR32, PMI_FPR64, PMI_FPR128,
92                                  PMI_FPR256, PMI_FPR512}) &&
93          "PartialMappingIdx's are incorrectly ordered");
94 // Now, the content.
95 // Check partial mapping.
96 #define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB)                      \
97   do {                                                                         \
98     assert(                                                                    \
99         checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \
100         #Idx " is incorrectly initialized");                                   \
101   } while (false)
102 
103   CHECK_PARTIALMAP(PMI_GPR32, 0, 32, RBGPR);
104   CHECK_PARTIALMAP(PMI_GPR64, 0, 64, RBGPR);
105   CHECK_PARTIALMAP(PMI_FPR16, 0, 16, RBFPR);
106   CHECK_PARTIALMAP(PMI_FPR32, 0, 32, RBFPR);
107   CHECK_PARTIALMAP(PMI_FPR64, 0, 64, RBFPR);
108   CHECK_PARTIALMAP(PMI_FPR128, 0, 128, RBFPR);
109   CHECK_PARTIALMAP(PMI_FPR256, 0, 256, RBFPR);
110   CHECK_PARTIALMAP(PMI_FPR512, 0, 512, RBFPR);
111 
112 // Check value mapping.
113 #define CHECK_VALUEMAP_IMPL(RBName, Size, Offset)                              \
114   do {                                                                         \
115     assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size,            \
116                              PartialMappingIdx::PMI_First##RBName, Size,       \
117                              Offset) &&                                        \
118            #RBName #Size " " #Offset " is incorrectly initialized");           \
119   } while (false)
120 
121 #define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0)
122 
123   CHECK_VALUEMAP(GPR, 32);
124   CHECK_VALUEMAP(GPR, 64);
125   CHECK_VALUEMAP(FPR, 16);
126   CHECK_VALUEMAP(FPR, 32);
127   CHECK_VALUEMAP(FPR, 64);
128   CHECK_VALUEMAP(FPR, 128);
129   CHECK_VALUEMAP(FPR, 256);
130   CHECK_VALUEMAP(FPR, 512);
131 
132 // Check the value mapping for 3-operands instructions where all the operands
133 // map to the same value mapping.
134 #define CHECK_VALUEMAP_3OPS(RBName, Size)                                      \
135   do {                                                                         \
136     CHECK_VALUEMAP_IMPL(RBName, Size, 0);                                      \
137     CHECK_VALUEMAP_IMPL(RBName, Size, 1);                                      \
138     CHECK_VALUEMAP_IMPL(RBName, Size, 2);                                      \
139   } while (false)
140 
141   CHECK_VALUEMAP_3OPS(GPR, 32);
142   CHECK_VALUEMAP_3OPS(GPR, 64);
143   CHECK_VALUEMAP_3OPS(FPR, 32);
144   CHECK_VALUEMAP_3OPS(FPR, 64);
145   CHECK_VALUEMAP_3OPS(FPR, 128);
146   CHECK_VALUEMAP_3OPS(FPR, 256);
147   CHECK_VALUEMAP_3OPS(FPR, 512);
148 
149 #define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size)                 \
150   do {                                                                         \
151     unsigned PartialMapDstIdx = PMI_##RBNameDst##Size - PMI_Min;               \
152     unsigned PartialMapSrcIdx = PMI_##RBNameSrc##Size - PMI_Min;               \
153     (void)PartialMapDstIdx;                                                    \
154     (void)PartialMapSrcIdx;                                                    \
155     const ValueMapping *Map = getCopyMapping(                                  \
156         AArch64::RBNameDst##RegBankID, AArch64::RBNameSrc##RegBankID, Size);  \
157     (void)Map;                                                                 \
158     assert(Map[0].BreakDown ==                                                 \
159                &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] &&  \
160            Map[0].NumBreakDowns == 1 && #RBNameDst #Size                       \
161            " Dst is incorrectly initialized");                                 \
162     assert(Map[1].BreakDown ==                                                 \
163                &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] &&  \
164            Map[1].NumBreakDowns == 1 && #RBNameSrc #Size                       \
165            " Src is incorrectly initialized");                                 \
166                                                                                \
167   } while (false)
168 
169   CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 32);
170   CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 32);
171   CHECK_VALUEMAP_CROSSREGCPY(GPR, GPR, 64);
172   CHECK_VALUEMAP_CROSSREGCPY(GPR, FPR, 64);
173   CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 32);
174   CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 32);
175   CHECK_VALUEMAP_CROSSREGCPY(FPR, FPR, 64);
176   CHECK_VALUEMAP_CROSSREGCPY(FPR, GPR, 64);
177 
178 #define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize)                                 \
179   do {                                                                         \
180     unsigned PartialMapDstIdx = PMI_FPR##DstSize - PMI_Min;                    \
181     unsigned PartialMapSrcIdx = PMI_FPR##SrcSize - PMI_Min;                    \
182     (void)PartialMapDstIdx;                                                    \
183     (void)PartialMapSrcIdx;                                                    \
184     const ValueMapping *Map = getFPExtMapping(DstSize, SrcSize);               \
185     (void)Map;                                                                 \
186     assert(Map[0].BreakDown ==                                                 \
187                &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] &&  \
188            Map[0].NumBreakDowns == 1 && "FPR" #DstSize                         \
189                                         " Dst is incorrectly initialized");    \
190     assert(Map[1].BreakDown ==                                                 \
191                &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] &&  \
192            Map[1].NumBreakDowns == 1 && "FPR" #SrcSize                         \
193                                         " Src is incorrectly initialized");    \
194                                                                                \
195   } while (false)
196 
197   CHECK_VALUEMAP_FPEXT(32, 16);
198   CHECK_VALUEMAP_FPEXT(64, 16);
199   CHECK_VALUEMAP_FPEXT(64, 32);
200   CHECK_VALUEMAP_FPEXT(128, 64);
201 
202   assert(verify(TRI) && "Invalid register bank information");
203 }
204 
copyCost(const RegisterBank & A,const RegisterBank & B,unsigned Size) const205 unsigned AArch64RegisterBankInfo::copyCost(const RegisterBank &A,
206                                            const RegisterBank &B,
207                                            unsigned Size) const {
208   // What do we do with different size?
209   // copy are same size.
210   // Will introduce other hooks for different size:
211   // * extract cost.
212   // * build_sequence cost.
213 
214   // Copy from (resp. to) GPR to (resp. from) FPR involves FMOV.
215   // FIXME: This should be deduced from the scheduling model.
216   if (&A == &AArch64::GPRRegBank && &B == &AArch64::FPRRegBank)
217     // FMOVXDr or FMOVWSr.
218     return 5;
219   if (&A == &AArch64::FPRRegBank && &B == &AArch64::GPRRegBank)
220     // FMOVDXr or FMOVSWr.
221     return 4;
222 
223   return RegisterBankInfo::copyCost(A, B, Size);
224 }
225 
getRegBankFromRegClass(const TargetRegisterClass & RC) const226 const RegisterBank &AArch64RegisterBankInfo::getRegBankFromRegClass(
227     const TargetRegisterClass &RC) const {
228   switch (RC.getID()) {
229   case AArch64::FPR8RegClassID:
230   case AArch64::FPR16RegClassID:
231   case AArch64::FPR32RegClassID:
232   case AArch64::FPR64RegClassID:
233   case AArch64::FPR128RegClassID:
234   case AArch64::FPR128_loRegClassID:
235   case AArch64::DDRegClassID:
236   case AArch64::DDDRegClassID:
237   case AArch64::DDDDRegClassID:
238   case AArch64::QQRegClassID:
239   case AArch64::QQQRegClassID:
240   case AArch64::QQQQRegClassID:
241     return getRegBank(AArch64::FPRRegBankID);
242   case AArch64::GPR32commonRegClassID:
243   case AArch64::GPR32RegClassID:
244   case AArch64::GPR32spRegClassID:
245   case AArch64::GPR32sponlyRegClassID:
246   case AArch64::GPR32allRegClassID:
247   case AArch64::GPR64commonRegClassID:
248   case AArch64::GPR64RegClassID:
249   case AArch64::GPR64spRegClassID:
250   case AArch64::GPR64sponlyRegClassID:
251   case AArch64::GPR64allRegClassID:
252   case AArch64::tcGPR64RegClassID:
253   case AArch64::WSeqPairsClassRegClassID:
254   case AArch64::XSeqPairsClassRegClassID:
255     return getRegBank(AArch64::GPRRegBankID);
256   case AArch64::CCRRegClassID:
257     return getRegBank(AArch64::CCRegBankID);
258   default:
259     llvm_unreachable("Register class not supported");
260   }
261 }
262 
263 RegisterBankInfo::InstructionMappings
getInstrAlternativeMappings(const MachineInstr & MI) const264 AArch64RegisterBankInfo::getInstrAlternativeMappings(
265     const MachineInstr &MI) const {
266   const MachineFunction &MF = *MI.getParent()->getParent();
267   const TargetSubtargetInfo &STI = MF.getSubtarget();
268   const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
269   const MachineRegisterInfo &MRI = MF.getRegInfo();
270 
271   switch (MI.getOpcode()) {
272   case TargetOpcode::G_OR: {
273     // 32 and 64-bit or can be mapped on either FPR or
274     // GPR for the same cost.
275     unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
276     if (Size != 32 && Size != 64)
277       break;
278 
279     // If the instruction has any implicit-defs or uses,
280     // do not mess with it.
281     if (MI.getNumOperands() != 3)
282       break;
283     InstructionMappings AltMappings;
284     const InstructionMapping &GPRMapping = getInstructionMapping(
285         /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size),
286         /*NumOperands*/ 3);
287     const InstructionMapping &FPRMapping = getInstructionMapping(
288         /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size),
289         /*NumOperands*/ 3);
290 
291     AltMappings.push_back(&GPRMapping);
292     AltMappings.push_back(&FPRMapping);
293     return AltMappings;
294   }
295   case TargetOpcode::G_BITCAST: {
296     unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
297     if (Size != 32 && Size != 64)
298       break;
299 
300     // If the instruction has any implicit-defs or uses,
301     // do not mess with it.
302     if (MI.getNumOperands() != 2)
303       break;
304 
305     InstructionMappings AltMappings;
306     const InstructionMapping &GPRMapping = getInstructionMapping(
307         /*ID*/ 1, /*Cost*/ 1,
308         getCopyMapping(AArch64::GPRRegBankID, AArch64::GPRRegBankID, Size),
309         /*NumOperands*/ 2);
310     const InstructionMapping &FPRMapping = getInstructionMapping(
311         /*ID*/ 2, /*Cost*/ 1,
312         getCopyMapping(AArch64::FPRRegBankID, AArch64::FPRRegBankID, Size),
313         /*NumOperands*/ 2);
314     const InstructionMapping &GPRToFPRMapping = getInstructionMapping(
315         /*ID*/ 3,
316         /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
317         getCopyMapping(AArch64::FPRRegBankID, AArch64::GPRRegBankID, Size),
318         /*NumOperands*/ 2);
319     const InstructionMapping &FPRToGPRMapping = getInstructionMapping(
320         /*ID*/ 3,
321         /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
322         getCopyMapping(AArch64::GPRRegBankID, AArch64::FPRRegBankID, Size),
323         /*NumOperands*/ 2);
324 
325     AltMappings.push_back(&GPRMapping);
326     AltMappings.push_back(&FPRMapping);
327     AltMappings.push_back(&GPRToFPRMapping);
328     AltMappings.push_back(&FPRToGPRMapping);
329     return AltMappings;
330   }
331   case TargetOpcode::G_LOAD: {
332     unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
333     if (Size != 64)
334       break;
335 
336     // If the instruction has any implicit-defs or uses,
337     // do not mess with it.
338     if (MI.getNumOperands() != 2)
339       break;
340 
341     InstructionMappings AltMappings;
342     const InstructionMapping &GPRMapping = getInstructionMapping(
343         /*ID*/ 1, /*Cost*/ 1,
344         getOperandsMapping({getValueMapping(PMI_FirstGPR, Size),
345                             // Addresses are GPR 64-bit.
346                             getValueMapping(PMI_FirstGPR, 64)}),
347         /*NumOperands*/ 2);
348     const InstructionMapping &FPRMapping = getInstructionMapping(
349         /*ID*/ 2, /*Cost*/ 1,
350         getOperandsMapping({getValueMapping(PMI_FirstFPR, Size),
351                             // Addresses are GPR 64-bit.
352                             getValueMapping(PMI_FirstGPR, 64)}),
353         /*NumOperands*/ 2);
354 
355     AltMappings.push_back(&GPRMapping);
356     AltMappings.push_back(&FPRMapping);
357     return AltMappings;
358   }
359   default:
360     break;
361   }
362   return RegisterBankInfo::getInstrAlternativeMappings(MI);
363 }
364 
applyMappingImpl(const OperandsMapper & OpdMapper) const365 void AArch64RegisterBankInfo::applyMappingImpl(
366     const OperandsMapper &OpdMapper) const {
367   switch (OpdMapper.getMI().getOpcode()) {
368   case TargetOpcode::G_OR:
369   case TargetOpcode::G_BITCAST:
370   case TargetOpcode::G_LOAD:
371     // Those ID must match getInstrAlternativeMappings.
372     assert((OpdMapper.getInstrMapping().getID() >= 1 &&
373             OpdMapper.getInstrMapping().getID() <= 4) &&
374            "Don't know how to handle that ID");
375     return applyDefaultMapping(OpdMapper);
376   default:
377     llvm_unreachable("Don't know how to handle that operation");
378   }
379 }
380 
381 /// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode,
382 /// having only floating-point operands.
isPreISelGenericFloatingPointOpcode(unsigned Opc)383 static bool isPreISelGenericFloatingPointOpcode(unsigned Opc) {
384   switch (Opc) {
385   case TargetOpcode::G_FADD:
386   case TargetOpcode::G_FSUB:
387   case TargetOpcode::G_FMUL:
388   case TargetOpcode::G_FDIV:
389   case TargetOpcode::G_FCONSTANT:
390   case TargetOpcode::G_FPEXT:
391   case TargetOpcode::G_FPTRUNC:
392   case TargetOpcode::G_FCEIL:
393     return true;
394   }
395   return false;
396 }
397 
398 const RegisterBankInfo::InstructionMapping &
getSameKindOfOperandsMapping(const MachineInstr & MI) const399 AArch64RegisterBankInfo::getSameKindOfOperandsMapping(
400     const MachineInstr &MI) const {
401   const unsigned Opc = MI.getOpcode();
402   const MachineFunction &MF = *MI.getParent()->getParent();
403   const MachineRegisterInfo &MRI = MF.getRegInfo();
404 
405   unsigned NumOperands = MI.getNumOperands();
406   assert(NumOperands <= 3 &&
407          "This code is for instructions with 3 or less operands");
408 
409   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
410   unsigned Size = Ty.getSizeInBits();
411   bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
412 
413   PartialMappingIdx RBIdx = IsFPR ? PMI_FirstFPR : PMI_FirstGPR;
414 
415 #ifndef NDEBUG
416   // Make sure all the operands are using similar size and type.
417   // Should probably be checked by the machine verifier.
418   // This code won't catch cases where the number of lanes is
419   // different between the operands.
420   // If we want to go to that level of details, it is probably
421   // best to check that the types are the same, period.
422   // Currently, we just check that the register banks are the same
423   // for each types.
424   for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
425     LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
426     assert(
427         AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(
428             RBIdx, OpTy.getSizeInBits()) ==
429             AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(RBIdx, Size) &&
430         "Operand has incompatible size");
431     bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
432     (void)OpIsFPR;
433     assert(IsFPR == OpIsFPR && "Operand has incompatible type");
434   }
435 #endif // End NDEBUG.
436 
437   return getInstructionMapping(DefaultMappingID, 1,
438                                getValueMapping(RBIdx, Size), NumOperands);
439 }
440 
441 const RegisterBankInfo::InstructionMapping &
getInstrMapping(const MachineInstr & MI) const442 AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
443   const unsigned Opc = MI.getOpcode();
444 
445   // Try the default logic for non-generic instructions that are either copies
446   // or already have some operands assigned to banks.
447   if ((Opc != TargetOpcode::COPY && !isPreISelGenericOpcode(Opc)) ||
448       Opc == TargetOpcode::G_PHI) {
449     const RegisterBankInfo::InstructionMapping &Mapping =
450         getInstrMappingImpl(MI);
451     if (Mapping.isValid())
452       return Mapping;
453   }
454 
455   const MachineFunction &MF = *MI.getParent()->getParent();
456   const MachineRegisterInfo &MRI = MF.getRegInfo();
457   const TargetSubtargetInfo &STI = MF.getSubtarget();
458   const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
459 
460   switch (Opc) {
461     // G_{F|S|U}REM are not listed because they are not legal.
462     // Arithmetic ops.
463   case TargetOpcode::G_ADD:
464   case TargetOpcode::G_SUB:
465   case TargetOpcode::G_GEP:
466   case TargetOpcode::G_MUL:
467   case TargetOpcode::G_SDIV:
468   case TargetOpcode::G_UDIV:
469     // Bitwise ops.
470   case TargetOpcode::G_AND:
471   case TargetOpcode::G_OR:
472   case TargetOpcode::G_XOR:
473     // Shifts.
474   case TargetOpcode::G_SHL:
475   case TargetOpcode::G_LSHR:
476   case TargetOpcode::G_ASHR:
477     // Floating point ops.
478   case TargetOpcode::G_FADD:
479   case TargetOpcode::G_FSUB:
480   case TargetOpcode::G_FMUL:
481   case TargetOpcode::G_FDIV:
482     return getSameKindOfOperandsMapping(MI);
483   case TargetOpcode::G_FPEXT: {
484     LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
485     LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
486     return getInstructionMapping(
487         DefaultMappingID, /*Cost*/ 1,
488         getFPExtMapping(DstTy.getSizeInBits(), SrcTy.getSizeInBits()),
489         /*NumOperands*/ 2);
490   }
491   case TargetOpcode::COPY: {
492     unsigned DstReg = MI.getOperand(0).getReg();
493     unsigned SrcReg = MI.getOperand(1).getReg();
494     // Check if one of the register is not a generic register.
495     if ((TargetRegisterInfo::isPhysicalRegister(DstReg) ||
496          !MRI.getType(DstReg).isValid()) ||
497         (TargetRegisterInfo::isPhysicalRegister(SrcReg) ||
498          !MRI.getType(SrcReg).isValid())) {
499       const RegisterBank *DstRB = getRegBank(DstReg, MRI, TRI);
500       const RegisterBank *SrcRB = getRegBank(SrcReg, MRI, TRI);
501       if (!DstRB)
502         DstRB = SrcRB;
503       else if (!SrcRB)
504         SrcRB = DstRB;
505       // If both RB are null that means both registers are generic.
506       // We shouldn't be here.
507       assert(DstRB && SrcRB && "Both RegBank were nullptr");
508       unsigned Size = getSizeInBits(DstReg, MRI, TRI);
509       return getInstructionMapping(
510           DefaultMappingID, copyCost(*DstRB, *SrcRB, Size),
511           getCopyMapping(DstRB->getID(), SrcRB->getID(), Size),
512           // We only care about the mapping of the destination.
513           /*NumOperands*/ 1);
514     }
515     // Both registers are generic, use G_BITCAST.
516     LLVM_FALLTHROUGH;
517   }
518   case TargetOpcode::G_BITCAST: {
519     LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
520     LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
521     unsigned Size = DstTy.getSizeInBits();
522     bool DstIsGPR = !DstTy.isVector() && DstTy.getSizeInBits() <= 64;
523     bool SrcIsGPR = !SrcTy.isVector() && SrcTy.getSizeInBits() <= 64;
524     const RegisterBank &DstRB =
525         DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
526     const RegisterBank &SrcRB =
527         SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
528     return getInstructionMapping(
529         DefaultMappingID, copyCost(DstRB, SrcRB, Size),
530         getCopyMapping(DstRB.getID(), SrcRB.getID(), Size),
531         // We only care about the mapping of the destination for COPY.
532         /*NumOperands*/ Opc == TargetOpcode::G_BITCAST ? 2 : 1);
533   }
534   default:
535     break;
536   }
537 
538   unsigned NumOperands = MI.getNumOperands();
539 
540   // Track the size and bank of each register.  We don't do partial mappings.
541   SmallVector<unsigned, 4> OpSize(NumOperands);
542   SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
543   for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
544     auto &MO = MI.getOperand(Idx);
545     if (!MO.isReg() || !MO.getReg())
546       continue;
547 
548     LLT Ty = MRI.getType(MO.getReg());
549     OpSize[Idx] = Ty.getSizeInBits();
550 
551     // As a top-level guess, vectors go in FPRs, scalars and pointers in GPRs.
552     // For floating-point instructions, scalars go in FPRs.
553     if (Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc) ||
554         Ty.getSizeInBits() > 64)
555       OpRegBankIdx[Idx] = PMI_FirstFPR;
556     else
557       OpRegBankIdx[Idx] = PMI_FirstGPR;
558   }
559 
560   unsigned Cost = 1;
561   // Some of the floating-point instructions have mixed GPR and FPR operands:
562   // fine-tune the computed mapping.
563   switch (Opc) {
564   case TargetOpcode::G_SITOFP:
565   case TargetOpcode::G_UITOFP:
566     OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
567     break;
568   case TargetOpcode::G_FPTOSI:
569   case TargetOpcode::G_FPTOUI:
570     OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
571     break;
572   case TargetOpcode::G_FCMP:
573     OpRegBankIdx = {PMI_FirstGPR,
574                     /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR};
575     break;
576   case TargetOpcode::G_BITCAST:
577     // This is going to be a cross register bank copy and this is expensive.
578     if (OpRegBankIdx[0] != OpRegBankIdx[1])
579       Cost = copyCost(
580           *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank,
581           *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank,
582           OpSize[0]);
583     break;
584   case TargetOpcode::G_LOAD:
585     // Loading in vector unit is slightly more expensive.
586     // This is actually only true for the LD1R and co instructions,
587     // but anyway for the fast mode this number does not matter and
588     // for the greedy mode the cost of the cross bank copy will
589     // offset this number.
590     // FIXME: Should be derived from the scheduling model.
591     if (OpRegBankIdx[0] != PMI_FirstGPR)
592       Cost = 2;
593     else
594       // Check if that load feeds fp instructions.
595       // In that case, we want the default mapping to be on FPR
596       // instead of blind map every scalar to GPR.
597       for (const MachineInstr &UseMI :
598            MRI.use_instructions(MI.getOperand(0).getReg())) {
599         // If we have at least one direct use in a FP instruction,
600         // assume this was a floating point load in the IR.
601         // If it was not, we would have had a bitcast before
602         // reaching that instruction.
603         unsigned UseOpc = UseMI.getOpcode();
604         if (isPreISelGenericFloatingPointOpcode(UseOpc) ||
605             // Check if we feed a copy-like instruction with
606             // floating point constraints. In that case, we are still
607             // feeding fp instructions, but indirectly
608             // (e.g., through ABI copies).
609             ((UseOpc == TargetOpcode::COPY || UseMI.isPHI()) &&
610              getRegBank(UseMI.getOperand(0).getReg(), MRI, TRI) ==
611                  &AArch64::FPRRegBank)) {
612           OpRegBankIdx[0] = PMI_FirstFPR;
613           break;
614         }
615       }
616     break;
617   case TargetOpcode::G_STORE:
618     // Check if that store is fed by fp instructions.
619     if (OpRegBankIdx[0] == PMI_FirstGPR) {
620       unsigned VReg = MI.getOperand(0).getReg();
621       if (!VReg)
622         break;
623       MachineInstr *DefMI = MRI.getVRegDef(VReg);
624       unsigned DefOpc = DefMI->getOpcode();
625       if (isPreISelGenericFloatingPointOpcode(DefOpc) ||
626           // Check if we come from a copy-like instruction with
627           // floating point constraints. In that case, we are still
628           // fed by fp instructions, but indirectly
629           // (e.g., through ABI copies).
630           ((DefOpc == TargetOpcode::COPY || DefMI->isPHI()) &&
631            getRegBank(DefMI->getOperand(0).getReg(), MRI, TRI) ==
632                &AArch64::FPRRegBank))
633         OpRegBankIdx[0] = PMI_FirstFPR;
634       break;
635     }
636   }
637 
638   // Finally construct the computed mapping.
639   SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
640   for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
641     if (MI.getOperand(Idx).isReg() && MI.getOperand(Idx).getReg()) {
642       auto Mapping = getValueMapping(OpRegBankIdx[Idx], OpSize[Idx]);
643       if (!Mapping->isValid())
644         return getInvalidInstructionMapping();
645 
646       OpdsMapping[Idx] = Mapping;
647     }
648   }
649 
650   return getInstructionMapping(DefaultMappingID, Cost,
651                                getOperandsMapping(OpdsMapping), NumOperands);
652 }
653