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 
462  const unsigned Opc = MI.getOpcode();
463 
464  // Try the default logic for non-generic instructions that are either copies
465  // or already have some operands assigned to banks.
466  if ((Opc != TargetOpcode::COPY && !isPreISelGenericOpcode(Opc)) ||
467  Opc == TargetOpcode::G_PHI) {
468  const RegisterBankInfo::InstructionMapping &Mapping =
470  if (Mapping.isValid())
471  return Mapping;
472  }
473 
474  const MachineFunction &MF = *MI.getParent()->getParent();
475  const MachineRegisterInfo &MRI = MF.getRegInfo();
476  const TargetSubtargetInfo &STI = MF.getSubtarget();
477  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
478 
479  // Helper lambda that returns true if MI has floating point constraints.
480  auto HasFPConstraints = [&TRI, &MRI, this](MachineInstr &MI) {
481  unsigned Op = MI.getOpcode();
482 
483  // Do we have an explicit floating point instruction?
485  return true;
486 
487  // No. Check if we have a copy-like instruction. If we do, then we could
488  // still be fed by floating point instructions.
489  if (Op != TargetOpcode::COPY && !MI.isPHI())
490  return false;
491 
492  // MI is copy-like. Return true if it's using an FPR.
493  return getRegBank(MI.getOperand(0).getReg(), MRI, TRI) ==
494  &AArch64::FPRRegBank;
495  };
496 
497  switch (Opc) {
498  // G_{F|S|U}REM are not listed because they are not legal.
499  // Arithmetic ops.
500  case TargetOpcode::G_ADD:
501  case TargetOpcode::G_SUB:
502  case TargetOpcode::G_GEP:
503  case TargetOpcode::G_MUL:
504  case TargetOpcode::G_SDIV:
505  case TargetOpcode::G_UDIV:
506  // Bitwise ops.
507  case TargetOpcode::G_AND:
508  case TargetOpcode::G_OR:
509  case TargetOpcode::G_XOR:
510  // Shifts.
511  case TargetOpcode::G_SHL:
512  case TargetOpcode::G_LSHR:
513  case TargetOpcode::G_ASHR:
514  // Floating point ops.
515  case TargetOpcode::G_FADD:
516  case TargetOpcode::G_FSUB:
517  case TargetOpcode::G_FMUL:
518  case TargetOpcode::G_FDIV:
519  return getSameKindOfOperandsMapping(MI);
520  case TargetOpcode::G_FPEXT: {
521  LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
522  LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
523  return getInstructionMapping(
524  DefaultMappingID, /*Cost*/ 1,
525  getFPExtMapping(DstTy.getSizeInBits(), SrcTy.getSizeInBits()),
526  /*NumOperands*/ 2);
527  }
528  case TargetOpcode::COPY: {
529  unsigned DstReg = MI.getOperand(0).getReg();
530  unsigned SrcReg = MI.getOperand(1).getReg();
531  // Check if one of the register is not a generic register.
533  !MRI.getType(DstReg).isValid()) ||
535  !MRI.getType(SrcReg).isValid())) {
536  const RegisterBank *DstRB = getRegBank(DstReg, MRI, TRI);
537  const RegisterBank *SrcRB = getRegBank(SrcReg, MRI, TRI);
538  if (!DstRB)
539  DstRB = SrcRB;
540  else if (!SrcRB)
541  SrcRB = DstRB;
542  // If both RB are null that means both registers are generic.
543  // We shouldn't be here.
544  assert(DstRB && SrcRB && "Both RegBank were nullptr");
545  unsigned Size = getSizeInBits(DstReg, MRI, TRI);
546  return getInstructionMapping(
547  DefaultMappingID, copyCost(*DstRB, *SrcRB, Size),
548  getCopyMapping(DstRB->getID(), SrcRB->getID(), Size),
549  // We only care about the mapping of the destination.
550  /*NumOperands*/ 1);
551  }
552  // Both registers are generic, use G_BITCAST.
554  }
555  case TargetOpcode::G_BITCAST: {
556  LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
557  LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
558  unsigned Size = DstTy.getSizeInBits();
559  bool DstIsGPR = !DstTy.isVector() && DstTy.getSizeInBits() <= 64;
560  bool SrcIsGPR = !SrcTy.isVector() && SrcTy.getSizeInBits() <= 64;
561  const RegisterBank &DstRB =
562  DstIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
563  const RegisterBank &SrcRB =
564  SrcIsGPR ? AArch64::GPRRegBank : AArch64::FPRRegBank;
565  return getInstructionMapping(
566  DefaultMappingID, copyCost(DstRB, SrcRB, Size),
567  getCopyMapping(DstRB.getID(), SrcRB.getID(), Size),
568  // We only care about the mapping of the destination for COPY.
569  /*NumOperands*/ Opc == TargetOpcode::G_BITCAST ? 2 : 1);
570  }
571  default:
572  break;
573  }
574 
575  unsigned NumOperands = MI.getNumOperands();
576 
577  // Track the size and bank of each register. We don't do partial mappings.
578  SmallVector<unsigned, 4> OpSize(NumOperands);
579  SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
580  for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
581  auto &MO = MI.getOperand(Idx);
582  if (!MO.isReg() || !MO.getReg())
583  continue;
584 
585  LLT Ty = MRI.getType(MO.getReg());
586  OpSize[Idx] = Ty.getSizeInBits();
587 
588  // As a top-level guess, vectors go in FPRs, scalars and pointers in GPRs.
589  // For floating-point instructions, scalars go in FPRs.
591  Ty.getSizeInBits() > 64)
592  OpRegBankIdx[Idx] = PMI_FirstFPR;
593  else
594  OpRegBankIdx[Idx] = PMI_FirstGPR;
595  }
596 
597  unsigned Cost = 1;
598  // Some of the floating-point instructions have mixed GPR and FPR operands:
599  // fine-tune the computed mapping.
600  switch (Opc) {
601  case TargetOpcode::G_SITOFP:
602  case TargetOpcode::G_UITOFP:
603  if (MRI.getType(MI.getOperand(0).getReg()).isVector())
604  break;
605  OpRegBankIdx = {PMI_FirstFPR, PMI_FirstGPR};
606  break;
607  case TargetOpcode::G_FPTOSI:
608  case TargetOpcode::G_FPTOUI:
609  if (MRI.getType(MI.getOperand(0).getReg()).isVector())
610  break;
611  OpRegBankIdx = {PMI_FirstGPR, PMI_FirstFPR};
612  break;
613  case TargetOpcode::G_FCMP:
614  OpRegBankIdx = {PMI_FirstGPR,
615  /* Predicate */ PMI_None, PMI_FirstFPR, PMI_FirstFPR};
616  break;
617  case TargetOpcode::G_BITCAST:
618  // This is going to be a cross register bank copy and this is expensive.
619  if (OpRegBankIdx[0] != OpRegBankIdx[1])
620  Cost = copyCost(
621  *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[0]].RegBank,
622  *AArch64GenRegisterBankInfo::PartMappings[OpRegBankIdx[1]].RegBank,
623  OpSize[0]);
624  break;
625  case TargetOpcode::G_LOAD:
626  // Loading in vector unit is slightly more expensive.
627  // This is actually only true for the LD1R and co instructions,
628  // but anyway for the fast mode this number does not matter and
629  // for the greedy mode the cost of the cross bank copy will
630  // offset this number.
631  // FIXME: Should be derived from the scheduling model.
632  if (OpRegBankIdx[0] != PMI_FirstGPR)
633  Cost = 2;
634  else
635  // Check if that load feeds fp instructions.
636  // In that case, we want the default mapping to be on FPR
637  // instead of blind map every scalar to GPR.
638  for (const MachineInstr &UseMI :
639  MRI.use_instructions(MI.getOperand(0).getReg())) {
640  // If we have at least one direct use in a FP instruction,
641  // assume this was a floating point load in the IR.
642  // If it was not, we would have had a bitcast before
643  // reaching that instruction.
644  unsigned UseOpc = UseMI.getOpcode();
646  // Check if we feed a copy-like instruction with
647  // floating point constraints. In that case, we are still
648  // feeding fp instructions, but indirectly
649  // (e.g., through ABI copies).
650  ((UseOpc == TargetOpcode::COPY || UseMI.isPHI()) &&
651  getRegBank(UseMI.getOperand(0).getReg(), MRI, TRI) ==
652  &AArch64::FPRRegBank)) {
653  OpRegBankIdx[0] = PMI_FirstFPR;
654  break;
655  }
656  }
657  break;
658  case TargetOpcode::G_STORE:
659  // Check if that store is fed by fp instructions.
660  if (OpRegBankIdx[0] == PMI_FirstGPR) {
661  unsigned VReg = MI.getOperand(0).getReg();
662  if (!VReg)
663  break;
664  MachineInstr *DefMI = MRI.getVRegDef(VReg);
665  unsigned DefOpc = DefMI->getOpcode();
667  // Check if we come from a copy-like instruction with
668  // floating point constraints. In that case, we are still
669  // fed by fp instructions, but indirectly
670  // (e.g., through ABI copies).
671  ((DefOpc == TargetOpcode::COPY || DefMI->isPHI()) &&
672  getRegBank(DefMI->getOperand(0).getReg(), MRI, TRI) ==
673  &AArch64::FPRRegBank))
674  OpRegBankIdx[0] = PMI_FirstFPR;
675  break;
676  }
677  break;
678  case TargetOpcode::G_SELECT: {
679  // If the destination is FPR, preserve that.
680  if (OpRegBankIdx[0] != PMI_FirstGPR)
681  break;
682  LLT SrcTy = MRI.getType(MI.getOperand(2).getReg());
683  if (SrcTy.isVector() ||
684  any_of(MRI.use_instructions(MI.getOperand(0).getReg()),
685  [&](MachineInstr &MI) { return HasFPConstraints(MI); })) {
686  // Set the register bank of every operand to FPR.
687  for (unsigned Idx = 0, NumOperands = MI.getNumOperands();
688  Idx < NumOperands; ++Idx)
689  OpRegBankIdx[Idx] = PMI_FirstFPR;
690  }
691  break;
692  }
693  case TargetOpcode::G_UNMERGE_VALUES: {
694  // If the first operand belongs to a FPR register bank, then make sure that
695  // we preserve that.
696  if (OpRegBankIdx[0] != PMI_FirstGPR)
697  break;
698 
699  LLT SrcTy = MRI.getType(MI.getOperand(MI.getNumOperands()-1).getReg());
700  // UNMERGE into scalars from a vector should always use FPR.
701  // Likewise if any of the uses are FP instructions.
702  if (SrcTy.isVector() ||
703  any_of(MRI.use_instructions(MI.getOperand(0).getReg()),
704  [&](MachineInstr &MI) { return HasFPConstraints(MI); })) {
705  // Set the register bank of every operand to FPR.
706  for (unsigned Idx = 0, NumOperands = MI.getNumOperands();
707  Idx < NumOperands; ++Idx)
708  OpRegBankIdx[Idx] = PMI_FirstFPR;
709  }
710  break;
711  }
712  case TargetOpcode::G_EXTRACT_VECTOR_ELT:
713  // Destination and source need to be FPRs.
714  OpRegBankIdx[0] = PMI_FirstFPR;
715  OpRegBankIdx[1] = PMI_FirstFPR;
716 
717  // Index needs to be a GPR.
718  OpRegBankIdx[2] = PMI_FirstGPR;
719  break;
720  case TargetOpcode::G_INSERT_VECTOR_ELT:
721  OpRegBankIdx[0] = PMI_FirstFPR;
722  OpRegBankIdx[1] = PMI_FirstFPR;
723 
724  // The element may be either a GPR or FPR. Preserve that behaviour.
725  if (getRegBank(MI.getOperand(2).getReg(), MRI, TRI) == &AArch64::FPRRegBank)
726  OpRegBankIdx[2] = PMI_FirstFPR;
727  else
728  OpRegBankIdx[2] = PMI_FirstGPR;
729 
730  // Index needs to be a GPR.
731  OpRegBankIdx[3] = PMI_FirstGPR;
732  break;
733  case TargetOpcode::G_BUILD_VECTOR:
734  // If the first source operand belongs to a FPR register bank, then make
735  // sure that we preserve that.
736  if (OpRegBankIdx[1] != PMI_FirstGPR)
737  break;
738  unsigned VReg = MI.getOperand(1).getReg();
739  if (!VReg)
740  break;
741 
742  // Get the instruction that defined the source operand reg, and check if
743  // it's a floating point operation. Or, if it's a type like s16 which
744  // doesn't have a exact size gpr register class.
745  MachineInstr *DefMI = MRI.getVRegDef(VReg);
746  unsigned DefOpc = DefMI->getOpcode();
747  const LLT SrcTy = MRI.getType(VReg);
749  SrcTy.getSizeInBits() < 32) {
750  // Have a floating point op.
751  // Make sure every operand gets mapped to a FPR register class.
752  unsigned NumOperands = MI.getNumOperands();
753  for (unsigned Idx = 0; Idx < NumOperands; ++Idx)
754  OpRegBankIdx[Idx] = PMI_FirstFPR;
755  }
756  break;
757  }
758 
759  // Finally construct the computed mapping.
760  SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
761  for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
762  if (MI.getOperand(Idx).isReg() && MI.getOperand(Idx).getReg()) {
763  auto Mapping = getValueMapping(OpRegBankIdx[Idx], OpSize[Idx]);
764  if (!Mapping->isValid())
766 
767  OpdsMapping[Idx] = Mapping;
768  }
769  }
770 
772  getOperandsMapping(OpdsMapping), NumOperands);
773 }
AArch64RegisterBankInfo(const TargetRegisterInfo &TRI)
unsigned getReg(unsigned Idx) const
Get the register for the operand index.
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:411
const InstructionMapping & getInstrMapping() const
The final mapping of the instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:408
unsigned getID() const
Return the register class ID number.
#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:1192
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: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:253
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.
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:413
static RegisterBankInfo::PartialMapping PartMappings[]
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:47