LLVM  7.0.0svn
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  return true;
393  }
394  return false;
395 }
396 
398 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(
427  RBIdx, OpTy.getSizeInBits()) ==
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 
437  getValueMapping(RBIdx, Size), NumOperands);
438 }
439 
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 =
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.
495  !MRI.getType(DstReg).isValid()) ||
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.
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.
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();
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();
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())
644 
645  OpdsMapping[Idx] = Mapping;
646  }
647  }
648 
650  getOperandsMapping(OpdsMapping), NumOperands);
651 }
AArch64RegisterBankInfo(const TargetRegisterInfo &TRI)
void push_back(const T &Elt)
Definition: SmallVector.h:213
const ValueMapping * getOperandsMapping(Iterator Begin, Iterator End) const
Get the uniquely generated array of ValueMapping for the elements of between Begin and End...
Compute iterated dominance frontiers using a linear time algorithm.
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...
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...
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
Definition: MachineInstr.h:861
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
Access to explicit operands of the instruction.
Definition: MachineInstr.h:314
const InstructionMapping & getInstrMapping() const
The final mapping of the instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:311
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:841
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:156
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:60
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.
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.
constexpr char Size[]
Key for Kernel::Arg::Metadata::mSize.
#define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size)
IRTranslator LLVM IR MI
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:238
const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC) const override
Get a register bank that covers RC.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:316
static RegisterBankInfo::PartialMapping PartMappings[]
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:48