]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/AArch64/AArch64RegisterBankInfo.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r302418, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / AArch64 / AArch64RegisterBankInfo.cpp
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/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"
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
40 #ifndef LLVM_BUILD_GLOBAL_ISEL
41 #error "You shouldn't build this"
42 #endif
43
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.
52   if (AlreadyInit)
53     return;
54   AlreadyInit = true;
55
56   const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID);
57   (void)RBGPR;
58   assert(&AArch64::GPRRegBank == &RBGPR &&
59          "The order in RegBanks is messed up");
60
61   const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID);
62   (void)RBFPR;
63   assert(&AArch64::FPRRegBank == &RBFPR &&
64          "The order in RegBanks is messed up");
65
66   const RegisterBank &RBCCR = getRegBank(AArch64::CCRRegBankID);
67   (void)RBCCR;
68   assert(&AArch64::CCRRegBank == &RBCCR &&
69          "The order in RegBanks is messed up");
70
71   // The GPR register bank is fully defined by all the registers in
72   // GR64all + its subclasses.
73   assert(RBGPR.covers(*TRI.getRegClass(AArch64::GPR32RegClassID)) &&
74          "Subclass not added?");
75   assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-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(RBFPR.getSize() == 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(RBCCR.getSize() == 32 && "CCR should hold up to 32-bit");
89
90   // Check that the TableGen'ed like file is in sync we our expectations.
91   // First, the Idx.
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");
99 // Now, the content.
100 // Check partial mapping.
101 #define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB)                      \
102   do {                                                                         \
103     assert(                                                                    \
104         checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \
105         #Idx " is incorrectly initialized");                                   \
106   } while (false)
107
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);
115
116 // Check value mapping.
117 #define CHECK_VALUEMAP_IMPL(RBName, Size, Offset)                              \
118   do {                                                                         \
119     assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size,            \
120                              PartialMappingIdx::PMI_First##RBName, Size,       \
121                              Offset) &&                                        \
122            #RBName #Size " " #Offset " is incorrectly initialized");           \
123   } while (false)
124
125 #define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0)
126
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);
134
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)                                      \
138   do {                                                                         \
139     CHECK_VALUEMAP_IMPL(RBName, Size, 0);                                      \
140     CHECK_VALUEMAP_IMPL(RBName, Size, 1);                                      \
141     CHECK_VALUEMAP_IMPL(RBName, Size, 2);                                      \
142   } while (false)
143
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);
151
152 #define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size)                 \
153   do {                                                                         \
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);  \
160     (void)Map;                                                                 \
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");                                 \
169                                                                                \
170   } while (false)
171
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);
180
181   assert(verify(TRI) && "Invalid register bank information");
182 }
183
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:
190   // * extract cost.
191   // * build_sequence cost.
192
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.
197     return 5;
198   if (&A == &AArch64::FPRRegBank && &B == &AArch64::GPRRegBank)
199     // FMOVDXr or FMOVSWr.
200     return 4;
201
202   return RegisterBankInfo::copyCost(A, B, Size);
203 }
204
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);
237   default:
238     llvm_unreachable("Register class not supported");
239   }
240 }
241
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();
249
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)
256       break;
257
258     // If the instruction has any implicit-defs or uses,
259     // do not mess with it.
260     if (MI.getNumOperands() != 3)
261       break;
262     InstructionMappings AltMappings;
263     const InstructionMapping &GPRMapping = getInstructionMapping(
264         /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size),
265         /*NumOperands*/ 3);
266     const InstructionMapping &FPRMapping = getInstructionMapping(
267         /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size),
268         /*NumOperands*/ 3);
269
270     AltMappings.push_back(&GPRMapping);
271     AltMappings.push_back(&FPRMapping);
272     return AltMappings;
273   }
274   case TargetOpcode::G_BITCAST: {
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() != 2)
282       break;
283
284     InstructionMappings AltMappings;
285     const InstructionMapping &GPRMapping = getInstructionMapping(
286         /*ID*/ 1, /*Cost*/ 1,
287         getCopyMapping(AArch64::GPRRegBankID, AArch64::GPRRegBankID, Size),
288         /*NumOperands*/ 2);
289     const InstructionMapping &FPRMapping = getInstructionMapping(
290         /*ID*/ 2, /*Cost*/ 1,
291         getCopyMapping(AArch64::FPRRegBankID, AArch64::FPRRegBankID, Size),
292         /*NumOperands*/ 2);
293     const InstructionMapping &GPRToFPRMapping = getInstructionMapping(
294         /*ID*/ 3,
295         /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
296         getCopyMapping(AArch64::FPRRegBankID, AArch64::GPRRegBankID, Size),
297         /*NumOperands*/ 2);
298     const InstructionMapping &FPRToGPRMapping = getInstructionMapping(
299         /*ID*/ 3,
300         /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
301         getCopyMapping(AArch64::GPRRegBankID, AArch64::FPRRegBankID, Size),
302         /*NumOperands*/ 2);
303
304     AltMappings.push_back(&GPRMapping);
305     AltMappings.push_back(&FPRMapping);
306     AltMappings.push_back(&GPRToFPRMapping);
307     AltMappings.push_back(&FPRToGPRMapping);
308     return AltMappings;
309   }
310   case TargetOpcode::G_LOAD: {
311     unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
312     if (Size != 64)
313       break;
314
315     // If the instruction has any implicit-defs or uses,
316     // do not mess with it.
317     if (MI.getNumOperands() != 2)
318       break;
319
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)}),
326         /*NumOperands*/ 2);
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)}),
332         /*NumOperands*/ 2);
333
334     AltMappings.push_back(&GPRMapping);
335     AltMappings.push_back(&FPRMapping);
336     return AltMappings;
337   }
338   default:
339     break;
340   }
341   return RegisterBankInfo::getInstrAlternativeMappings(MI);
342 }
343
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);
355   default:
356     llvm_unreachable("Don't know how to handle that operation");
357   }
358 }
359
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) {
363   switch (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:
371     return true;
372   }
373   return false;
374 }
375
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();
382
383   unsigned NumOperands = MI.getNumOperands();
384   assert(NumOperands <= 3 &&
385          "This code is for instructions with 3 or less operands");
386
387   LLT Ty = MRI.getType(MI.getOperand(0).getReg());
388   unsigned Size = Ty.getSizeInBits();
389   bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
390
391   PartialMappingIdx RBIdx = IsFPR ? PMI_FirstFPR : PMI_FirstGPR;
392
393 #ifndef NDEBUG
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
401   // for each types.
402   for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
403     LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
404     assert(
405         AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(
406             RBIdx, OpTy.getSizeInBits()) ==
407             AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(RBIdx, Size) &&
408         "Operand has incompatible size");
409     bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
410     (void)OpIsFPR;
411     assert(IsFPR == OpIsFPR && "Operand has incompatible type");
412   }
413 #endif // End NDEBUG.
414
415   return getInstructionMapping(DefaultMappingID, 1,
416                                getValueMapping(RBIdx, Size), NumOperands);
417 }
418
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();
424
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())
431       return Mapping;
432   }
433
434   switch (Opc) {
435     // G_{F|S|U}REM are not listed because they are not legal.
436     // Arithmetic ops.
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:
443     // Bitwise ops.
444   case TargetOpcode::G_AND:
445   case TargetOpcode::G_OR:
446   case TargetOpcode::G_XOR:
447     // Shifts.
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),
470         /*NumOperands*/ 2);
471   }
472   case TargetOpcode::G_SEQUENCE:
473     // FIXME: support this, but the generic code is really not going to do
474     // anything sane.
475     return getInvalidInstructionMapping();
476   default:
477     break;
478   }
479
480   unsigned NumOperands = MI.getNumOperands();
481
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())
488       continue;
489
490     LLT Ty = MRI.getType(MO.getReg());
491     OpSize[Idx] = Ty.getSizeInBits();
492
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;
497     else
498       OpRegBankIdx[Idx] = PMI_FirstGPR;
499   }
500
501   unsigned Cost = 1;
502   // Some of the floating-point instructions have mixed GPR and FPR operands:
503   // fine-tune the computed mapping.
504   switch (Opc) {
505   case TargetOpcode::G_SITOFP:
506   case TargetOpcode::G_UITOFP:
507     OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
508     break;
509   case TargetOpcode::G_FPTOSI:
510   case TargetOpcode::G_FPTOUI:
511     OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
512     break;
513   case TargetOpcode::G_FCMP:
514     OpRegBankIdx = {PMI_FirstGPR,
515                     /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR};
516     break;
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])
520       Cost = copyCost(
521           *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank,
522           *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank,
523           OpSize[0]);
524     break;
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)
533       Cost = 2;
534     break;
535   }
536
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();
544
545       OpdsMapping[Idx] = Mapping;
546     }
547   }
548
549   return getInstructionMapping(DefaultMappingID, Cost,
550                                getOperandsMapping(OpdsMapping), NumOperands);
551 }