LLVM  9.0.0svn
AArch64RegisterBankInfo.cpp
Go to the documentation of this file.
1 //===- AArch64RegisterBankInfo.cpp ----------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file implements the targeting of the RegisterBankInfo class for
10 /// AArch64.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
13 
15 #include "AArch64InstrInfo.h"
16 #include "llvm/ADT/SmallVector.h"
28 #include <algorithm>
29 #include <cassert>
30 
31 #define GET_TARGET_REGBANK_IMPL
32 #include "AArch64GenRegisterBank.inc"
33 
34 // This file will be TableGen'ed at some point.
35 #include "AArch64GenRegisterBankInfo.def"
36 
37 using namespace llvm;
38 
41  static bool AlreadyInit = false;
42  // We have only one set of register banks, whatever the subtarget
43  // is. Therefore, the initialization of the RegBanks table should be
44  // done only once. Indeed the table of all register banks
45  // (AArch64::RegBanks) is unique in the compiler. At some point, it
46  // will get tablegen'ed and the whole constructor becomes empty.
47  if (AlreadyInit)
48  return;
49  AlreadyInit = true;
50 
51  const RegisterBank &RBGPR = getRegBank(AArch64::GPRRegBankID);
52  (void)RBGPR;
53  assert(&AArch64::GPRRegBank == &RBGPR &&
54  "The order in RegBanks is messed up");
55 
56  const RegisterBank &RBFPR = getRegBank(AArch64::FPRRegBankID);
57  (void)RBFPR;
58  assert(&AArch64::FPRRegBank == &RBFPR &&
59  "The order in RegBanks is messed up");
60 
61  const RegisterBank &RBCCR = getRegBank(AArch64::CCRegBankID);
62  (void)RBCCR;
63  assert(&AArch64::CCRegBank == &RBCCR && "The order in RegBanks is messed up");
64 
65  // The GPR register bank is fully defined by all the registers in
66  // GR64all + its subclasses.
67  assert(RBGPR.covers(*TRI.getRegClass(AArch64::GPR32RegClassID)) &&
68  "Subclass not added?");
69  assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
70 
71  // The FPR register bank is fully defined by all the registers in
72  // GR64all + its subclasses.
73  assert(RBFPR.covers(*TRI.getRegClass(AArch64::QQRegClassID)) &&
74  "Subclass not added?");
75  assert(RBFPR.covers(*TRI.getRegClass(AArch64::FPR64RegClassID)) &&
76  "Subclass not added?");
77  assert(RBFPR.getSize() == 512 &&
78  "FPRs should hold up to 512-bit via QQQQ sequence");
79 
80  assert(RBCCR.covers(*TRI.getRegClass(AArch64::CCRRegClassID)) &&
81  "Class not added?");
82  assert(RBCCR.getSize() == 32 && "CCR should hold up to 32-bit");
83 
84  // Check that the TableGen'ed like file is in sync we our expectations.
85  // First, the Idx.
87  {PMI_GPR32, PMI_GPR64}) &&
88  "PartialMappingIdx's are incorrectly ordered");
92  "PartialMappingIdx's are incorrectly ordered");
93 // Now, the content.
94 // Check partial mapping.
95 #define CHECK_PARTIALMAP(Idx, ValStartIdx, ValLength, RB) \
96  do { \
97  assert( \
98  checkPartialMap(PartialMappingIdx::Idx, ValStartIdx, ValLength, RB) && \
99  #Idx " is incorrectly initialized"); \
100  } while (false)
101 
102  CHECK_PARTIALMAP(PMI_GPR32, 0, 32, RBGPR);
103  CHECK_PARTIALMAP(PMI_GPR64, 0, 64, RBGPR);
104  CHECK_PARTIALMAP(PMI_FPR16, 0, 16, RBFPR);
105  CHECK_PARTIALMAP(PMI_FPR32, 0, 32, RBFPR);
106  CHECK_PARTIALMAP(PMI_FPR64, 0, 64, RBFPR);
107  CHECK_PARTIALMAP(PMI_FPR128, 0, 128, RBFPR);
108  CHECK_PARTIALMAP(PMI_FPR256, 0, 256, RBFPR);
109  CHECK_PARTIALMAP(PMI_FPR512, 0, 512, RBFPR);
110 
111 // Check value mapping.
112 #define CHECK_VALUEMAP_IMPL(RBName, Size, Offset) \
113  do { \
114  assert(checkValueMapImpl(PartialMappingIdx::PMI_##RBName##Size, \
115  PartialMappingIdx::PMI_First##RBName, Size, \
116  Offset) && \
117  #RBName #Size " " #Offset " is incorrectly initialized"); \
118  } while (false)
119 
120 #define CHECK_VALUEMAP(RBName, Size) CHECK_VALUEMAP_IMPL(RBName, Size, 0)
121 
122  CHECK_VALUEMAP(GPR, 32);
123  CHECK_VALUEMAP(GPR, 64);
124  CHECK_VALUEMAP(FPR, 16);
125  CHECK_VALUEMAP(FPR, 32);
126  CHECK_VALUEMAP(FPR, 64);
127  CHECK_VALUEMAP(FPR, 128);
128  CHECK_VALUEMAP(FPR, 256);
129  CHECK_VALUEMAP(FPR, 512);
130 
131 // Check the value mapping for 3-operands instructions where all the operands
132 // map to the same value mapping.
133 #define CHECK_VALUEMAP_3OPS(RBName, Size) \
134  do { \
135  CHECK_VALUEMAP_IMPL(RBName, Size, 0); \
136  CHECK_VALUEMAP_IMPL(RBName, Size, 1); \
137  CHECK_VALUEMAP_IMPL(RBName, Size, 2); \
138  } while (false)
139 
144  CHECK_VALUEMAP_3OPS(FPR, 128);
145  CHECK_VALUEMAP_3OPS(FPR, 256);
146  CHECK_VALUEMAP_3OPS(FPR, 512);
147 
148 #define CHECK_VALUEMAP_CROSSREGCPY(RBNameDst, RBNameSrc, Size) \
149  do { \
150  unsigned PartialMapDstIdx = PMI_##RBNameDst##Size - PMI_Min; \
151  unsigned PartialMapSrcIdx = PMI_##RBNameSrc##Size - PMI_Min; \
152  (void)PartialMapDstIdx; \
153  (void)PartialMapSrcIdx; \
154  const ValueMapping *Map = getCopyMapping( \
155  AArch64::RBNameDst##RegBankID, AArch64::RBNameSrc##RegBankID, Size); \
156  (void)Map; \
157  assert(Map[0].BreakDown == \
158  &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
159  Map[0].NumBreakDowns == 1 && #RBNameDst #Size \
160  " Dst is incorrectly initialized"); \
161  assert(Map[1].BreakDown == \
162  &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
163  Map[1].NumBreakDowns == 1 && #RBNameSrc #Size \
164  " Src is incorrectly initialized"); \
165  \
166  } while (false)
167 
176 
177 #define CHECK_VALUEMAP_FPEXT(DstSize, SrcSize) \
178  do { \
179  unsigned PartialMapDstIdx = PMI_FPR##DstSize - PMI_Min; \
180  unsigned PartialMapSrcIdx = PMI_FPR##SrcSize - PMI_Min; \
181  (void)PartialMapDstIdx; \
182  (void)PartialMapSrcIdx; \
183  const ValueMapping *Map = getFPExtMapping(DstSize, SrcSize); \
184  (void)Map; \
185  assert(Map[0].BreakDown == \
186  &AArch64GenRegisterBankInfo::PartMappings[PartialMapDstIdx] && \
187  Map[0].NumBreakDowns == 1 && "FPR" #DstSize \
188  " Dst is incorrectly initialized"); \
189  assert(Map[1].BreakDown == \
190  &AArch64GenRegisterBankInfo::PartMappings[PartialMapSrcIdx] && \
191  Map[1].NumBreakDowns == 1 && "FPR" #SrcSize \
192  " Src is incorrectly initialized"); \
193  \
194  } while (false)
195 
196  CHECK_VALUEMAP_FPEXT(32, 16);
197  CHECK_VALUEMAP_FPEXT(64, 16);
198  CHECK_VALUEMAP_FPEXT(64, 32);
199  CHECK_VALUEMAP_FPEXT(128, 64);
200 
201  assert(verify(TRI) && "Invalid register bank information");
202 }
203 
205  const RegisterBank &B,
206  unsigned Size) const {
207  // What do we do with different size?
208  // copy are same size.
209  // Will introduce other hooks for different size:
210  // * extract cost.
211  // * build_sequence cost.
212 
213  // Copy from (resp. to) GPR to (resp. from) FPR involves FMOV.
214  // FIXME: This should be deduced from the scheduling model.
215  if (&A == &AArch64::GPRRegBank && &B == &AArch64::FPRRegBank)
216  // FMOVXDr or FMOVWSr.
217  return 5;
218  if (&A == &AArch64::FPRRegBank && &B == &AArch64::GPRRegBank)
219  // FMOVDXr or FMOVSWr.
220  return 4;
221 
222  return RegisterBankInfo::copyCost(A, B, Size);
223 }
224 
226  const TargetRegisterClass &RC) const {
227  switch (RC.getID()) {
228  case AArch64::FPR8RegClassID:
229  case AArch64::FPR16RegClassID:
230  case AArch64::FPR32RegClassID:
231  case AArch64::FPR64RegClassID:
232  case AArch64::FPR128RegClassID:
233  case AArch64::FPR128_loRegClassID:
234  case AArch64::DDRegClassID:
235  case AArch64::DDDRegClassID:
236  case AArch64::DDDDRegClassID:
237  case AArch64::QQRegClassID:
238  case AArch64::QQQRegClassID:
239  case AArch64::QQQQRegClassID:
240  return getRegBank(AArch64::FPRRegBankID);
241  case AArch64::GPR32commonRegClassID:
242  case AArch64::GPR32RegClassID:
243  case AArch64::GPR32spRegClassID:
244  case AArch64::GPR32sponlyRegClassID:
245  case AArch64::GPR32argRegClassID:
246  case AArch64::GPR32allRegClassID:
247  case AArch64::GPR64commonRegClassID:
248  case AArch64::GPR64RegClassID:
249  case AArch64::GPR64spRegClassID:
250  case AArch64::GPR64sponlyRegClassID:
251  case AArch64::GPR64argRegClassID:
252  case AArch64::GPR64allRegClassID:
253  case AArch64::GPR64noipRegClassID:
254  case AArch64::GPR64common_and_GPR64noipRegClassID:
255  case AArch64::GPR64noip_and_tcGPR64RegClassID:
256  case AArch64::tcGPR64RegClassID:
257  case AArch64::WSeqPairsClassRegClassID:
258  case AArch64::XSeqPairsClassRegClassID:
259  return getRegBank(AArch64::GPRRegBankID);
260  case AArch64::CCRRegClassID:
261  return getRegBank(AArch64::CCRegBankID);
262  default:
263  llvm_unreachable("Register class not supported");
264  }
265 }
266 
269  const MachineInstr &MI) const {
270  const MachineFunction &MF = *MI.getParent()->getParent();
271  const TargetSubtargetInfo &STI = MF.getSubtarget();
272  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
273  const MachineRegisterInfo &MRI = MF.getRegInfo();
274 
275  switch (MI.getOpcode()) {
276  case TargetOpcode::G_OR: {
277  // 32 and 64-bit or can be mapped on either FPR or
278  // GPR for the same cost.
279  unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
280  if (Size != 32 && Size != 64)
281  break;
282 
283  // If the instruction has any implicit-defs or uses,
284  // do not mess with it.
285  if (MI.getNumOperands() != 3)
286  break;
287  InstructionMappings AltMappings;
288  const InstructionMapping &GPRMapping = getInstructionMapping(
289  /*ID*/ 1, /*Cost*/ 1, getValueMapping(PMI_FirstGPR, Size),
290  /*NumOperands*/ 3);
291  const InstructionMapping &FPRMapping = getInstructionMapping(
292  /*ID*/ 2, /*Cost*/ 1, getValueMapping(PMI_FirstFPR, Size),
293  /*NumOperands*/ 3);
294 
295  AltMappings.push_back(&GPRMapping);
296  AltMappings.push_back(&FPRMapping);
297  return AltMappings;
298  }
299  case TargetOpcode::G_BITCAST: {
300  unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
301  if (Size != 32 && Size != 64)
302  break;
303 
304  // If the instruction has any implicit-defs or uses,
305  // do not mess with it.
306  if (MI.getNumOperands() != 2)
307  break;
308 
309  InstructionMappings AltMappings;
310  const InstructionMapping &GPRMapping = getInstructionMapping(
311  /*ID*/ 1, /*Cost*/ 1,
312  getCopyMapping(AArch64::GPRRegBankID, AArch64::GPRRegBankID, Size),
313  /*NumOperands*/ 2);
314  const InstructionMapping &FPRMapping = getInstructionMapping(
315  /*ID*/ 2, /*Cost*/ 1,
316  getCopyMapping(AArch64::FPRRegBankID, AArch64::FPRRegBankID, Size),
317  /*NumOperands*/ 2);
318  const InstructionMapping &GPRToFPRMapping = getInstructionMapping(
319  /*ID*/ 3,
320  /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
321  getCopyMapping(AArch64::FPRRegBankID, AArch64::GPRRegBankID, Size),
322  /*NumOperands*/ 2);
323  const InstructionMapping &FPRToGPRMapping = getInstructionMapping(
324  /*ID*/ 3,
325  /*Cost*/ copyCost(AArch64::GPRRegBank, AArch64::FPRRegBank, Size),
326  getCopyMapping(AArch64::GPRRegBankID, AArch64::FPRRegBankID, Size),
327  /*NumOperands*/ 2);
328 
329  AltMappings.push_back(&GPRMapping);
330  AltMappings.push_back(&FPRMapping);
331  AltMappings.push_back(&GPRToFPRMapping);
332  AltMappings.push_back(&FPRToGPRMapping);
333  return AltMappings;
334  }
335  case TargetOpcode::G_LOAD: {
336  unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
337  if (Size != 64)
338  break;
339 
340  // If the instruction has any implicit-defs or uses,
341  // do not mess with it.
342  if (MI.getNumOperands() != 2)
343  break;
344 
345  InstructionMappings AltMappings;
346  const InstructionMapping &GPRMapping = getInstructionMapping(
347  /*ID*/ 1, /*Cost*/ 1,
349  // Addresses are GPR 64-bit.
351  /*NumOperands*/ 2);
352  const InstructionMapping &FPRMapping = getInstructionMapping(
353  /*ID*/ 2, /*Cost*/ 1,
355  // Addresses are GPR 64-bit.
357  /*NumOperands*/ 2);
358 
359  AltMappings.push_back(&GPRMapping);
360  AltMappings.push_back(&FPRMapping);
361  return AltMappings;
362  }
363  default:
364  break;
365  }
367 }
368 
369 void AArch64RegisterBankInfo::applyMappingImpl(
370  const OperandsMapper &OpdMapper) const {
371  switch (OpdMapper.getMI().getOpcode()) {
372  case TargetOpcode::G_OR:
373  case TargetOpcode::G_BITCAST:
374  case TargetOpcode::G_LOAD:
375  // Those ID must match getInstrAlternativeMappings.
376  assert((OpdMapper.getInstrMapping().getID() >= 1 &&
377  OpdMapper.getInstrMapping().getID() <= 4) &&
378  "Don't know how to handle that ID");
379  return applyDefaultMapping(OpdMapper);
380  default:
381  llvm_unreachable("Don't know how to handle that operation");
382  }
383 }
384 
385 /// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode,
386 /// having only floating-point operands.
387 static bool isPreISelGenericFloatingPointOpcode(unsigned Opc) {
388  switch (Opc) {
389  case TargetOpcode::G_FADD:
390  case TargetOpcode::G_FSUB:
391  case TargetOpcode::G_FMUL:
392  case TargetOpcode::G_FMA:
393  case TargetOpcode::G_FDIV:
394  case TargetOpcode::G_FCONSTANT:
395  case TargetOpcode::G_FPEXT:
396  case TargetOpcode::G_FPTRUNC:
397  case TargetOpcode::G_FCEIL:
398  case TargetOpcode::G_FFLOOR:
399  case TargetOpcode::G_FNEARBYINT:
400  case TargetOpcode::G_FNEG:
401  case TargetOpcode::G_FCOS:
402  case TargetOpcode::G_FSIN:
403  case TargetOpcode::G_FLOG10:
404  case TargetOpcode::G_FLOG:
405  case TargetOpcode::G_FLOG2:
406  case TargetOpcode::G_FSQRT:
407  case TargetOpcode::G_FABS:
408  case TargetOpcode::G_FEXP:
409  case TargetOpcode::G_FRINT:
410  case TargetOpcode::G_INTRINSIC_TRUNC:
411  case TargetOpcode::G_INTRINSIC_ROUND:
412  return true;
413  }
414  return false;
415 }
416 
418 AArch64RegisterBankInfo::getSameKindOfOperandsMapping(
419  const MachineInstr &MI) const {
420  const unsigned Opc = MI.getOpcode();
421  const MachineFunction &MF = *MI.getParent()->getParent();
422  const MachineRegisterInfo &MRI = MF.getRegInfo();
423 
424  unsigned NumOperands = MI.getNumOperands();
425  assert(NumOperands <= 3 &&
426  "This code is for instructions with 3 or less operands");
427 
428  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
429  unsigned Size = Ty.getSizeInBits();
430  bool IsFPR = Ty.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
431 
432  PartialMappingIdx RBIdx = IsFPR ? PMI_FirstFPR : PMI_FirstGPR;
433 
434 #ifndef NDEBUG
435  // Make sure all the operands are using similar size and type.
436  // Should probably be checked by the machine verifier.
437  // This code won't catch cases where the number of lanes is
438  // different between the operands.
439  // If we want to go to that level of details, it is probably
440  // best to check that the types are the same, period.
441  // Currently, we just check that the register banks are the same
442  // for each types.
443  for (unsigned Idx = 1; Idx != NumOperands; ++Idx) {
444  LLT OpTy = MRI.getType(MI.getOperand(Idx).getReg());
445  assert(
447  RBIdx, OpTy.getSizeInBits()) ==
449  "Operand has incompatible size");
450  bool OpIsFPR = OpTy.isVector() || isPreISelGenericFloatingPointOpcode(Opc);
451  (void)OpIsFPR;
452  assert(IsFPR == OpIsFPR && "Operand has incompatible type");
453  }
454 #endif // End NDEBUG.
455 
457  getValueMapping(RBIdx, Size), NumOperands);
458 }
459 
460 bool AArch64RegisterBankInfo::hasFPConstraints(
461  const MachineInstr &MI, const MachineRegisterInfo &MRI,
462  const TargetRegisterInfo &TRI) const {
463  unsigned Op = MI.getOpcode();
464 
465  // Do we have an explicit floating point instruction?
467  return true;
468 
469  // No. Check if we have a copy-like instruction. If we do, then we could
470  // still be fed by floating point instructions.
471  if (Op != TargetOpcode::COPY && !MI.isPHI())
472  return false;
473 
474  // MI is copy-like. Return true if it outputs an FPR.
475  return getRegBank(MI.getOperand(0).getReg(), MRI, TRI) ==
476  &AArch64::FPRRegBank;
477 }
478 
479 bool AArch64RegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
480  const MachineRegisterInfo &MRI,
481  const TargetRegisterInfo &TRI) const {
482  switch (MI.getOpcode()) {
483  case TargetOpcode::G_FPTOSI:
484  case TargetOpcode::G_FPTOUI:
485  case TargetOpcode::G_FCMP:
486  return true;
487  default:
488  break;
489  }
490  return hasFPConstraints(MI, MRI, TRI);
491 }
492 
493 bool AArch64RegisterBankInfo::onlyDefinesFP(
494  const MachineInstr &MI, const MachineRegisterInfo &MRI,
495  const TargetRegisterInfo &TRI) const {
496  switch (MI.getOpcode()) {
497  case TargetOpcode::G_SITOFP:
498  case TargetOpcode::G_UITOFP:
499  case TargetOpcode::G_EXTRACT_VECTOR_ELT:
500  case TargetOpcode::G_INSERT_VECTOR_ELT:
501  return true;
502  default:
503  break;
504  }
505  return hasFPConstraints(MI, MRI, TRI);
506 }
507 
510  const unsigned Opc = MI.getOpcode();
511 
512  // Try the default logic for non-generic instructions that are either copies
513  // or already have some operands assigned to banks.
514  if ((Opc != TargetOpcode::COPY && !isPreISelGenericOpcode(Opc)) ||
515  Opc == TargetOpcode::G_PHI) {
516  const RegisterBankInfo::InstructionMapping &Mapping =
518  if (Mapping.isValid())
519  return Mapping;
520  }
521 
522  const MachineFunction &MF = *MI.getParent()->getParent();
523  const MachineRegisterInfo &MRI = MF.getRegInfo();
524  const TargetSubtargetInfo &STI = MF.getSubtarget();
525  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
526 
527  switch (Opc) {
528  // G_{F|S|U}REM are not listed because they are not legal.
529  // Arithmetic ops.
530  case TargetOpcode::G_ADD:
531  case TargetOpcode::G_SUB:
532  case TargetOpcode::G_GEP:
533  case TargetOpcode::G_MUL:
534  case TargetOpcode::G_SDIV:
535  case TargetOpcode::G_UDIV:
536  // Bitwise ops.
537  case TargetOpcode::G_AND:
538  case TargetOpcode::G_OR:
539  case TargetOpcode::G_XOR:
540  // Shifts.
541  case TargetOpcode::G_SHL:
542  case TargetOpcode::G_LSHR:
543  case TargetOpcode::G_ASHR:
544  // Floating point ops.
545  case TargetOpcode::G_FADD:
546  case TargetOpcode::G_FSUB:
547  case TargetOpcode::G_FMUL:
548  case TargetOpcode::G_FDIV:
549  return getSameKindOfOperandsMapping(MI);
550  case TargetOpcode::G_FPEXT: {
551  LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
552  LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
553  return getInstructionMapping(
554  DefaultMappingID, /*Cost*/ 1,
555  getFPExtMapping(DstTy.getSizeInBits(), SrcTy.getSizeInBits()),
556  /*NumOperands*/ 2);
557  }
558  case TargetOpcode::COPY: {
559  unsigned DstReg = MI.getOperand(0).getReg();
560  unsigned SrcReg = MI.getOperand(1).getReg();
561  // Check if one of the register is not a generic register.
563  !MRI.getType(DstReg).isValid()) ||
565  !MRI.getType(SrcReg).isValid())) {
566  const RegisterBank *DstRB = getRegBank(DstReg, MRI, TRI);
567  const RegisterBank *SrcRB = getRegBank(SrcReg, MRI, TRI);
568  if (!DstRB)
569  DstRB = SrcRB;
570  else if (!SrcRB)
571  SrcRB = DstRB;
572  // If both RB are null that means both registers are generic.
573  // We shouldn't be here.
574  assert(DstRB && SrcRB && "Both RegBank were nullptr");
575  unsigned Size = getSizeInBits(DstReg, MRI, TRI);
576  return getInstructionMapping(
577  DefaultMappingID, copyCost(*DstRB, *SrcRB, Size),
578  getCopyMapping(DstRB->getID(), SrcRB->getID(), Size),
579  // We only care about the mapping of the destination.
580  /*NumOperands*/ 1);
581  }
582  // Both registers are generic, use G_BITCAST.
584  }
585  case TargetOpcode::G_BITCAST: {
586  LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
587  LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
588  unsigned Size = DstTy.getSizeInBits();
589  bool DstIsGPR = !DstTy.isVector() && DstTy.getSizeInBits() <= 64;
590  bool SrcIsGPR = !SrcTy.isVector() && SrcTy.getSizeInBits() <= 64;
591  const RegisterBank &DstRB =
592  DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
593  const RegisterBank &SrcRB =
594  SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
595  return getInstructionMapping(
596  DefaultMappingID, copyCost(DstRB, SrcRB, Size),
597  getCopyMapping(DstRB.getID(), SrcRB.getID(), Size),
598  // We only care about the mapping of the destination for COPY.
599  /*NumOperands*/ Opc == TargetOpcode::G_BITCAST ? 2 : 1);
600  }
601  default:
602  break;
603  }
604 
605  unsigned NumOperands = MI.getNumOperands();
606 
607  // Track the size and bank of each register. We don't do partial mappings.
608  SmallVector<unsigned, 4> OpSize(NumOperands);
609  SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
610  for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
611  auto &MO = MI.getOperand(Idx);
612  if (!MO.isReg() || !MO.getReg())
613  continue;
614 
615  LLT Ty = MRI.getType(MO.getReg());
616  OpSize[Idx] = Ty.getSizeInBits();
617 
618  // As a top-level guess, vectors go in FPRs, scalars and pointers in GPRs.
619  // For floating-point instructions, scalars go in FPRs.
621  Ty.getSizeInBits() > 64)
622  OpRegBankIdx[Idx] = PMI_FirstFPR;
623  else
624  OpRegBankIdx[Idx] = PMI_FirstGPR;
625  }
626 
627  unsigned Cost = 1;
628  // Some of the floating-point instructions have mixed GPR and FPR operands:
629  // fine-tune the computed mapping.
630  switch (Opc) {
631  case TargetOpcode::G_SITOFP:
632  case TargetOpcode::G_UITOFP:
633  if (MRI.getType(MI.getOperand(0).getReg()).isVector())
634  break;
635  OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
636  break;
637  case TargetOpcode::G_FPTOSI:
638  case TargetOpcode::G_FPTOUI:
639  if (MRI.getType(MI.getOperand(0).getReg()).isVector())
640  break;
641  OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
642  break;
643  case TargetOpcode::G_FCMP:
644  OpRegBankIdx = {PMI_FirstGPR,
645  /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR};
646  break;
647  case TargetOpcode::G_BITCAST:
648  // This is going to be a cross register bank copy and this is expensive.
649  if (OpRegBankIdx[0] != OpRegBankIdx[1])
650  Cost = copyCost(
651  *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank,
652  *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank,
653  OpSize[0]);
654  break;
655  case TargetOpcode::G_LOAD:
656  // Loading in vector unit is slightly more expensive.
657  // This is actually only true for the LD1R and co instructions,
658  // but anyway for the fast mode this number does not matter and
659  // for the greedy mode the cost of the cross bank copy will
660  // offset this number.
661  // FIXME: Should be derived from the scheduling model.
662  if (OpRegBankIdx[0] != PMI_FirstGPR)
663  Cost = 2;
664  else
665  // Check if that load feeds fp instructions.
666  // In that case, we want the default mapping to be on FPR
667  // instead of blind map every scalar to GPR.
668  for (const MachineInstr &UseMI :
669  MRI.use_instructions(MI.getOperand(0).getReg())) {
670  // If we have at least one direct use in a FP instruction,
671  // assume this was a floating point load in the IR.
672  // If it was not, we would have had a bitcast before
673  // reaching that instruction.
674  if (onlyUsesFP(UseMI, MRI, TRI)) {
675  OpRegBankIdx[0] = PMI_FirstFPR;
676  break;
677  }
678  }
679  break;
680  case TargetOpcode::G_STORE:
681  // Check if that store is fed by fp instructions.
682  if (OpRegBankIdx[0] == PMI_FirstGPR) {
683  unsigned VReg = MI.getOperand(0).getReg();
684  if (!VReg)
685  break;
686  MachineInstr *DefMI = MRI.getVRegDef(VReg);
687  if (onlyDefinesFP(*DefMI, MRI, TRI))
688  OpRegBankIdx[0] = PMI_FirstFPR;
689  break;
690  }
691  break;
692  case TargetOpcode::G_SELECT: {
693  // If the destination is FPR, preserve that.
694  if (OpRegBankIdx[0] != PMI_FirstGPR)
695  break;
696 
697  // If we're taking in vectors, we have no choice but to put everything on
698  // FPRs.
699  LLT SrcTy = MRI.getType(MI.getOperand(2).getReg());
700  if (SrcTy.isVector()) {
701  for (unsigned Idx = 0; Idx < 4; ++Idx)
702  OpRegBankIdx[Idx] = PMI_FirstFPR;
703  break;
704  }
705 
706  // Try to minimize the number of copies. If we have more floating point
707  // constrained values than not, then we'll put everything on FPR. Otherwise,
708  // everything has to be on GPR.
709  unsigned NumFP = 0;
710 
711  // Check if the uses of the result always produce floating point values.
712  //
713  // For example:
714  //
715  // %z = G_SELECT %cond %x %y
716  // fpr = G_FOO %z ...
717  if (any_of(
718  MRI.use_instructions(MI.getOperand(0).getReg()),
719  [&](MachineInstr &MI) { return onlyUsesFP(MI, MRI, TRI); }))
720  ++NumFP;
721 
722  // Check if the defs of the source values always produce floating point
723  // values.
724  //
725  // For example:
726  //
727  // %x = G_SOMETHING_ALWAYS_FLOAT %a ...
728  // %z = G_SELECT %cond %x %y
729  //
730  // Also check whether or not the sources have already been decided to be
731  // FPR. Keep track of this.
732  //
733  // This doesn't check the condition, since it's just whatever is in NZCV.
734  // This isn't passed explicitly in a register to fcsel/csel.
735  for (unsigned Idx = 2; Idx < 4; ++Idx) {
736  unsigned VReg = MI.getOperand(Idx).getReg();
737  MachineInstr *DefMI = MRI.getVRegDef(VReg);
738  if (getRegBank(VReg, MRI, TRI) == &AArch64::FPRRegBank ||
739  onlyDefinesFP(*DefMI, MRI, TRI))
740  ++NumFP;
741  }
742 
743  // If we have more FP constraints than not, then move everything over to
744  // FPR.
745  if (NumFP >= 2)
746  for (unsigned Idx = 0; Idx < 4; ++Idx)
747  OpRegBankIdx[Idx] = PMI_FirstFPR;
748 
749  break;
750  }
751  case TargetOpcode::G_UNMERGE_VALUES: {
752  // If the first operand belongs to a FPR register bank, then make sure that
753  // we preserve that.
754  if (OpRegBankIdx[0] != PMI_FirstGPR)
755  break;
756 
757  LLT SrcTy = MRI.getType(MI.getOperand(MI.getNumOperands()-1).getReg());
758  // UNMERGE into scalars from a vector should always use FPR.
759  // Likewise if any of the uses are FP instructions.
760  if (SrcTy.isVector() ||
762  [&](MachineInstr &MI) { return onlyUsesFP(MI, MRI, TRI); })) {
763  // Set the register bank of every operand to FPR.
764  for (unsigned Idx = 0, NumOperands = MI.getNumOperands();
765  Idx < NumOperands; ++Idx)
766  OpRegBankIdx[Idx] = PMI_FirstFPR;
767  }
768  break;
769  }
770  case TargetOpcode::G_EXTRACT_VECTOR_ELT:
771  // Destination and source need to be FPRs.
772  OpRegBankIdx[0] = PMI_FirstFPR;
773  OpRegBankIdx[1] = PMI_FirstFPR;
774 
775  // Index needs to be a GPR.
776  OpRegBankIdx[2] = PMI_FirstGPR;
777  break;
778  case TargetOpcode::G_INSERT_VECTOR_ELT:
779  OpRegBankIdx[0] = PMI_FirstFPR;
780  OpRegBankIdx[1] = PMI_FirstFPR;
781 
782  // The element may be either a GPR or FPR. Preserve that behaviour.
783  if (getRegBank(MI.getOperand(2).getReg(), MRI, TRI) == &AArch64::FPRRegBank)
784  OpRegBankIdx[2] = PMI_FirstFPR;
785  else
786  OpRegBankIdx[2] = PMI_FirstGPR;
787 
788  // Index needs to be a GPR.
789  OpRegBankIdx[3] = PMI_FirstGPR;
790  break;
791  case TargetOpcode::G_BUILD_VECTOR:
792  // If the first source operand belongs to a FPR register bank, then make
793  // sure that we preserve that.
794  if (OpRegBankIdx[1] != PMI_FirstGPR)
795  break;
796  unsigned VReg = MI.getOperand(1).getReg();
797  if (!VReg)
798  break;
799 
800  // Get the instruction that defined the source operand reg, and check if
801  // it's a floating point operation. Or, if it's a type like s16 which
802  // doesn't have a exact size gpr register class.
803  MachineInstr *DefMI = MRI.getVRegDef(VReg);
804  unsigned DefOpc = DefMI->getOpcode();
805  const LLT SrcTy = MRI.getType(VReg);
807  SrcTy.getSizeInBits() < 32) {
808  // Have a floating point op.
809  // Make sure every operand gets mapped to a FPR register class.
810  unsigned NumOperands = MI.getNumOperands();
811  for (unsigned Idx = 0; Idx < NumOperands; ++Idx)
812  OpRegBankIdx[Idx] = PMI_FirstFPR;
813  }
814  break;
815  }
816 
817  // Finally construct the computed mapping.
818  SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
819  for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
820  if (MI.getOperand(Idx).isReg() && MI.getOperand(Idx).getReg()) {
821  auto Mapping = getValueMapping(OpRegBankIdx[Idx], OpSize[Idx]);
822  if (!Mapping->isValid())
824 
825  OpdsMapping[Idx] = Mapping;
826  }
827  }
828 
830  getOperandsMapping(OpdsMapping), NumOperands);
831 }
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:23
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...
void push_back(const T &Elt)
Definition: SmallVector.h:211
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
LegalityPredicate isVector(unsigned TypeIdx)
True iff the specified type index is a vector.
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:413
const InstructionMapping & getInstrMapping() const
The final mapping of the instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:410
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 any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1199
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:837
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:28
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
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:255
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:63
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:46
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:54
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel...
Definition: TargetOpcodes.h:30
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)
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:250
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:415
static RegisterBankInfo::PartialMapping PartMappings[]
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:47