LLVM  8.0.1
AArch64RegisterBankInfo.cpp
Go to the documentation of this file.
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 
16 #include "AArch64InstrInfo.h"
17 #include "llvm/ADT/SmallVector.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 
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.
88  {PMI_GPR32, PMI_GPR64}) &&
89  "PartialMappingIdx's are incorrectly ordered");
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 
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 
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 
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 
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 
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,
345  // Addresses are GPR 64-bit.
347  /*NumOperands*/ 2);
348  const InstructionMapping &FPRMapping = getInstructionMapping(
349  /*ID*/ 2, /*Cost*/ 1,
351  // Addresses are GPR 64-bit.
353  /*NumOperands*/ 2);
354 
355  AltMappings.push_back(&GPRMapping);
356  AltMappings.push_back(&FPRMapping);
357  return AltMappings;
358  }
359  default:
360  break;
361  }
363 }
364 
365 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.
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 
399 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(
428  RBIdx, OpTy.getSizeInBits()) ==
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 
438  getValueMapping(RBIdx, Size), NumOperands);
439 }
440 
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 =
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.
496  !MRI.getType(DstReg).isValid()) ||
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.
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.
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();
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();
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())
645 
646  OpdsMapping[Idx] = Mapping;
647  }
648  }
649 
651  getOperandsMapping(OpdsMapping), NumOperands);
652 }
AArch64RegisterBankInfo(const TargetRegisterInfo &TRI)
const ValueMapping * getOperandsMapping(Iterator Begin, Iterator End) const
Get the uniquely generated array of ValueMapping for the elements of between Begin and End...
This class represents lattice values for constants.
Definition: AllocatorList.h:24
const InstructionMapping & getInstructionMapping(unsigned ID, unsigned Cost, const ValueMapping *OperandsMapping, unsigned NumOperands) const
Method to get a uniquely generated InstructionMapping.
static const RegisterBankInfo::ValueMapping * getCopyMapping(unsigned DstBankID, unsigned SrcBankID, unsigned Size)
Get the pointer to the ValueMapping of the operands of a copy instruction from the SrcBankID register...
#define LLVM_FALLTHROUGH
Definition: Compiler.h:86
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
class llvm::RegisterBankInfo GPR
Helper class that represents how the value of an instruction may be mapped and what is the related co...
void push_back(const T &Elt)
Definition: SmallVector.h:218
unsigned getReg() const
getReg - Returns the register number.
static bool checkPartialMappingIdx(PartialMappingIdx FirstAlias, PartialMappingIdx LastAlias, ArrayRef< PartialMappingIdx > Order)
LLT getType(unsigned Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
Helper class used to get/create the virtual registers that will be used to replace the MachineOperand...
#define CHECK_VALUEMAP(RBName, Size)
unsigned const TargetRegisterInfo * TRI
bool isPHI() const
const TargetRegisterClass * getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
bool covers(const TargetRegisterClass &RC) const
Check whether this register bank covers RC.
This file declares the targeting of the RegisterBankInfo class for AArch64.
bool isVector() const
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:412
const InstructionMapping & getInstrMapping() const
The final mapping of the instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:409
unsigned getID() const
Return the register class ID number.
MachineInstr * getVRegDef(unsigned Reg) const
getVRegDef - Return the machine instr that defines the specified virtual register or null if none is ...
#define CHECK_VALUEMAP_3OPS(RBName, Size)
static const MCPhysReg FPR[]
FPR - The set of FP registers that should be allocated for arguments, on Darwin.
#define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize)
static const RegisterBankInfo::ValueMapping * getFPExtMapping(unsigned DstSize, unsigned SrcSize)
Get the instruction mapping for G_FPEXT.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
unsigned const MachineRegisterInfo * MRI
const InstructionMapping & getInvalidInstructionMapping() const
Method to get a uniquely generated invalid InstructionMapping.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineInstrBuilder & UseMI
bool isValid() const
static const unsigned DefaultMappingID
Identifier used when the related instruction mapping instance is generated by target independent code...
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
static bool isPreISelGenericFloatingPointOpcode(unsigned Opc)
Returns whether opcode Opc is a pre-isel generic floating-point opcode, having only floating-point op...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool verify(const TargetRegisterInfo &TRI) const
Check that information hold by this instance make sense for the given TRI.
bool isValid() const
Check whether this object is valid.
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
static void applyDefaultMapping(const OperandsMapper &OpdMapper)
Helper method to apply something that is like the default mapping.
MachineInstrBuilder MachineInstrBuilder & DefMI
InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const override
Get the alternative mappings for MI.
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
unsigned copyCost(const RegisterBank &A, const RegisterBank &B, unsigned Size) const override
Get the cost of a copy from B to A, or put differently, get the cost of A = COPY B.
#define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB)
static unsigned getRegBankBaseIdxOffset(unsigned RBIdx, unsigned Size)
This class implements the register bank concept.
Definition: RegisterBank.h:29
static const RegisterBankInfo::ValueMapping * getValueMapping(PartialMappingIdx RBIdx, unsigned Size)
Get the pointer to the ValueMapping representing the RegisterBank at RBIdx with a size of Size...
const MachineBasicBlock * getParent() const
Definition: MachineInstr.h:254
MachineRegisterInfo - Keep track of information for virtual and physical registers, including vreg register classes, use/def chains for registers, etc.
TargetSubtargetInfo - Generic base class for all target subtargets.
Representation of each machine instruction.
Definition: MachineInstr.h:64
static bool isPhysicalRegister(unsigned Reg)
Return true if the specified register number is in the physical register namespace.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override
Get the mapping of the different operands of MI on the register bank.
virtual InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const
Get the alternative mappings for MI.
virtual unsigned copyCost(const RegisterBank &A, const RegisterBank &B, unsigned Size) const
Get the cost of a copy from B to A, or put differently, get the cost of A = COPY B.
const InstructionMapping & getInstrMappingImpl(const MachineInstr &MI) const
Try to get the mapping of MI.
uint32_t Size
Definition: Profile.cpp:47
bool isReg() const
isReg - Tests if this is a MO_Register operand.
iterator_range< use_instr_iterator > use_instructions(unsigned Reg) const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
unsigned getSize() const
Get the maximal size in bits that fits in this register bank.
Definition: RegisterBank.h:55
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel...
Definition: TargetOpcodes.h:31
unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
#define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size)
IRTranslator LLVM IR MI
const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC) const override
Get a register bank that covers RC.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:414
static RegisterBankInfo::PartialMapping PartMappings[]
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:48