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 return true;
393 }
394 return false;
395 }
396
397 const RegisterBankInfo::InstructionMapping &
getSameKindOfOperandsMapping(const MachineInstr & MI) const398 AArch64RegisterBankInfo::getSameKindOfOperandsMapping(
399 const MachineInstr &MI) const {
400 const unsigned Opc = MI.getOpcode();
401 const MachineFunction &MF = *MI.getParent()->getParent();
402 const MachineRegisterInfo &MRI = MF.getRegInfo();
403
404 unsigned NumOperands = MI.getNumOperands();
405 assert(NumOperands <= 3 &&
406 "This code is for instructions with 3 or less operands");
407
408 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
409 unsigned Size = Ty.getSizeInBits();
410 bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
411
412 PartialMappingIdx RBIdx = IsFPR ? PMI_FirstFPR : PMI_FirstGPR;
413
414 #ifndef NDEBUG
415 // Make sure all the operands are using similar size and type.
416 // Should probably be checked by the machine verifier.
417 // This code won't catch cases where the number of lanes is
418 // different between the operands.
419 // If we want to go to that level of details, it is probably
420 // best to check that the types are the same, period.
421 // Currently, we just check that the register banks are the same
422 // for each types.
423 for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
424 LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
425 assert(
426 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(
427 RBIdx, OpTy.getSizeInBits()) ==
428 AArch64GenRegisterBankInfo::getRegBankBaseIdxOffset(RBIdx, Size) &&
429 "Operand has incompatible size");
430 bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
431 (void)OpIsFPR;
432 assert(IsFPR == OpIsFPR && "Operand has incompatible type");
433 }
434 #endif // End NDEBUG.
435
436 return getInstructionMapping(DefaultMappingID, 1,
437 getValueMapping(RBIdx, Size), NumOperands);
438 }
439
440 const RegisterBankInfo::InstructionMapping &
getInstrMapping(const MachineInstr & MI) const441 AArch64RegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
442 const unsigned Opc = MI.getOpcode();
443
444 // Try the default logic for non-generic instructions that are either copies
445 // or already have some operands assigned to banks.
446 if ((Opc != TargetOpcode::COPY && !isPreISelGenericOpcode(Opc)) ||
447 Opc == TargetOpcode::G_PHI) {
448 const RegisterBankInfo::InstructionMapping &Mapping =
449 getInstrMappingImpl(MI);
450 if (Mapping.isValid())
451 return Mapping;
452 }
453
454 const MachineFunction &MF = *MI.getParent()->getParent();
455 const MachineRegisterInfo &MRI = MF.getRegInfo();
456 const TargetSubtargetInfo &STI = MF.getSubtarget();
457 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
458
459 switch (Opc) {
460 // G_{F|S|U}REM are not listed because they are not legal.
461 // Arithmetic ops.
462 case TargetOpcode::G_ADD:
463 case TargetOpcode::G_SUB:
464 case TargetOpcode::G_GEP:
465 case TargetOpcode::G_MUL:
466 case TargetOpcode::G_SDIV:
467 case TargetOpcode::G_UDIV:
468 // Bitwise ops.
469 case TargetOpcode::G_AND:
470 case TargetOpcode::G_OR:
471 case TargetOpcode::G_XOR:
472 // Shifts.
473 case TargetOpcode::G_SHL:
474 case TargetOpcode::G_LSHR:
475 case TargetOpcode::G_ASHR:
476 // Floating point ops.
477 case TargetOpcode::G_FADD:
478 case TargetOpcode::G_FSUB:
479 case TargetOpcode::G_FMUL:
480 case TargetOpcode::G_FDIV:
481 return getSameKindOfOperandsMapping(MI);
482 case TargetOpcode::G_FPEXT: {
483 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
484 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
485 return getInstructionMapping(
486 DefaultMappingID, /*Cost*/ 1,
487 getFPExtMapping(DstTy.getSizeInBits(), SrcTy.getSizeInBits()),
488 /*NumOperands*/ 2);
489 }
490 case TargetOpcode::COPY: {
491 unsigned DstReg = MI.getOperand(0).getReg();
492 unsigned SrcReg = MI.getOperand(1).getReg();
493 // Check if one of the register is not a generic register.
494 if ((TargetRegisterInfo::isPhysicalRegister(DstReg) ||
495 !MRI.getType(DstReg).isValid()) ||
496 (TargetRegisterInfo::isPhysicalRegister(SrcReg) ||
497 !MRI.getType(SrcReg).isValid())) {
498 const RegisterBank *DstRB = getRegBank(DstReg, MRI, TRI);
499 const RegisterBank *SrcRB = getRegBank(SrcReg, MRI, TRI);
500 if (!DstRB)
501 DstRB = SrcRB;
502 else if (!SrcRB)
503 SrcRB = DstRB;
504 // If both RB are null that means both registers are generic.
505 // We shouldn't be here.
506 assert(DstRB && SrcRB && "Both RegBank were nullptr");
507 unsigned Size = getSizeInBits(DstReg, MRI, TRI);
508 return getInstructionMapping(
509 DefaultMappingID, copyCost(*DstRB, *SrcRB, Size),
510 getCopyMapping(DstRB->getID(), SrcRB->getID(), Size),
511 // We only care about the mapping of the destination.
512 /*NumOperands*/ 1);
513 }
514 // Both registers are generic, use G_BITCAST.
515 LLVM_FALLTHROUGH;
516 }
517 case TargetOpcode::G_BITCAST: {
518 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
519 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
520 unsigned Size = DstTy.getSizeInBits();
521 bool DstIsGPR = !DstTy.isVector() && DstTy.getSizeInBits() <= 64;
522 bool SrcIsGPR = !SrcTy.isVector() && SrcTy.getSizeInBits() <= 64;
523 const RegisterBank &DstRB =
524 DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
525 const RegisterBank &SrcRB =
526 SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
527 return getInstructionMapping(
528 DefaultMappingID, copyCost(DstRB, SrcRB, Size),
529 getCopyMapping(DstRB.getID(), SrcRB.getID(), Size),
530 // We only care about the mapping of the destination for COPY.
531 /*NumOperands*/ Opc == TargetOpcode::G_BITCAST ? 2 : 1);
532 }
533 default:
534 break;
535 }
536
537 unsigned NumOperands = MI.getNumOperands();
538
539 // Track the size and bank of each register. We don't do partial mappings.
540 SmallVector<unsigned, 4> OpSize(NumOperands);
541 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
542 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
543 auto &MO = MI.getOperand(Idx);
544 if (!MO.isReg() || !MO.getReg())
545 continue;
546
547 LLT Ty = MRI.getType(MO.getReg());
548 OpSize[Idx] = Ty.getSizeInBits();
549
550 // As a top-level guess, vectors go in FPRs, scalars and pointers in GPRs.
551 // For floating-point instructions, scalars go in FPRs.
552 if (Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc) ||
553 Ty.getSizeInBits() > 64)
554 OpRegBankIdx[Idx] = PMI_FirstFPR;
555 else
556 OpRegBankIdx[Idx] = PMI_FirstGPR;
557 }
558
559 unsigned Cost = 1;
560 // Some of the floating-point instructions have mixed GPR and FPR operands:
561 // fine-tune the computed mapping.
562 switch (Opc) {
563 case TargetOpcode::G_SITOFP:
564 case TargetOpcode::G_UITOFP:
565 OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
566 break;
567 case TargetOpcode::G_FPTOSI:
568 case TargetOpcode::G_FPTOUI:
569 OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
570 break;
571 case TargetOpcode::G_FCMP:
572 OpRegBankIdx = {PMI_FirstGPR,
573 /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR};
574 break;
575 case TargetOpcode::G_BITCAST:
576 // This is going to be a cross register bank copy and this is expensive.
577 if (OpRegBankIdx[0] != OpRegBankIdx[1])
578 Cost = copyCost(
579 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank,
580 *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank,
581 OpSize[0]);
582 break;
583 case TargetOpcode::G_LOAD:
584 // Loading in vector unit is slightly more expensive.
585 // This is actually only true for the LD1R and co instructions,
586 // but anyway for the fast mode this number does not matter and
587 // for the greedy mode the cost of the cross bank copy will
588 // offset this number.
589 // FIXME: Should be derived from the scheduling model.
590 if (OpRegBankIdx[0] != PMI_FirstGPR)
591 Cost = 2;
592 else
593 // Check if that load feeds fp instructions.
594 // In that case, we want the default mapping to be on FPR
595 // instead of blind map every scalar to GPR.
596 for (const MachineInstr &UseMI :
597 MRI.use_instructions(MI.getOperand(0).getReg())) {
598 // If we have at least one direct use in a FP instruction,
599 // assume this was a floating point load in the IR.
600 // If it was not, we would have had a bitcast before
601 // reaching that instruction.
602 unsigned UseOpc = UseMI.getOpcode();
603 if (isPreISelGenericFloatingPointOpcode(UseOpc) ||
604 // Check if we feed a copy-like instruction with
605 // floating point constraints. In that case, we are still
606 // feeding fp instructions, but indirectly
607 // (e.g., through ABI copies).
608 ((UseOpc == TargetOpcode::COPY || UseMI.isPHI()) &&
609 getRegBank(UseMI.getOperand(0).getReg(), MRI, TRI) ==
610 &AArch64::FPRRegBank)) {
611 OpRegBankIdx[0] = PMI_FirstFPR;
612 break;
613 }
614 }
615 break;
616 case TargetOpcode::G_STORE:
617 // Check if that store is fed by fp instructions.
618 if (OpRegBankIdx[0] == PMI_FirstGPR) {
619 unsigned VReg = MI.getOperand(0).getReg();
620 if (!VReg)
621 break;
622 MachineInstr *DefMI = MRI.getVRegDef(VReg);
623 unsigned DefOpc = DefMI->getOpcode();
624 if (isPreISelGenericFloatingPointOpcode(DefOpc) ||
625 // Check if we come from a copy-like instruction with
626 // floating point constraints. In that case, we are still
627 // fed by fp instructions, but indirectly
628 // (e.g., through ABI copies).
629 ((DefOpc == TargetOpcode::COPY || DefMI->isPHI()) &&
630 getRegBank(DefMI->getOperand(0).getReg(), MRI, TRI) ==
631 &AArch64::FPRRegBank))
632 OpRegBankIdx[0] = PMI_FirstFPR;
633 break;
634 }
635 }
636
637 // Finally construct the computed mapping.
638 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
639 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
640 if (MI.getOperand(Idx).isReg() && MI.getOperand(Idx).getReg()) {
641 auto Mapping = getValueMapping(OpRegBankIdx[Idx], OpSize[Idx]);
642 if (!Mapping->isValid())
643 return getInvalidInstructionMapping();
644
645 OpdsMapping[Idx] = Mapping;
646 }
647 }
648
649 return getInstructionMapping(DefaultMappingID, Cost,
650 getOperandsMapping(OpdsMapping), NumOperands);
651 }
652