LLVM  10.0.0svn
ARMRegisterBankInfo.cpp
Go to the documentation of this file.
1 //===- ARMRegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
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 ARM.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
12 
13 #include "ARMRegisterBankInfo.h"
14 #include "ARMInstrInfo.h" // For the register classes
15 #include "ARMSubtarget.h"
20 
21 #define GET_TARGET_REGBANK_IMPL
22 #include "ARMGenRegisterBank.inc"
23 
24 using namespace llvm;
25 
26 // FIXME: TableGen this.
27 // If it grows too much and TableGen still isn't ready to do the job, extract it
28 // into an ARMGenRegisterBankInfo.def (similar to AArch64).
29 namespace llvm {
30 namespace ARM {
36 };
37 
39  // GPR Partial Mapping
40  {0, 32, GPRRegBank},
41  // SPR Partial Mapping
42  {0, 32, FPRRegBank},
43  // DPR Partial Mapping
44  {0, 64, FPRRegBank},
45 };
46 
47 #ifndef NDEBUG
49  unsigned Start, unsigned Length,
50  unsigned RegBankID) {
51  return PM.StartIdx == Start && PM.Length == Length &&
52  PM.RegBank->getID() == RegBankID;
53 }
54 
55 static void checkPartialMappings() {
56  assert(
57  checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) &&
58  "Wrong mapping for GPR");
59  assert(
60  checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) &&
61  "Wrong mapping for SPR");
62  assert(
63  checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) &&
64  "Wrong mapping for DPR");
65 }
66 #endif
67 
73 };
74 
76  // invalid
77  {nullptr, 0},
78  // 3 ops in GPRs
79  {&PartMappings[PMI_GPR - PMI_Min], 1},
80  {&PartMappings[PMI_GPR - PMI_Min], 1},
81  {&PartMappings[PMI_GPR - PMI_Min], 1},
82  // 3 ops in SPRs
83  {&PartMappings[PMI_SPR - PMI_Min], 1},
84  {&PartMappings[PMI_SPR - PMI_Min], 1},
85  {&PartMappings[PMI_SPR - PMI_Min], 1},
86  // 3 ops in DPRs
87  {&PartMappings[PMI_DPR - PMI_Min], 1},
88  {&PartMappings[PMI_DPR - PMI_Min], 1},
89  {&PartMappings[PMI_DPR - PMI_Min], 1}};
90 
91 #ifndef NDEBUG
94  return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown;
95 }
96 
97 static void checkValueMappings() {
98  assert(checkValueMapping(ValueMappings[GPR3OpsIdx],
100  "Wrong value mapping for 3 GPR ops instruction");
101  assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1],
103  "Wrong value mapping for 3 GPR ops instruction");
104  assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2],
106  "Wrong value mapping for 3 GPR ops instruction");
107 
108  assert(checkValueMapping(ValueMappings[SPR3OpsIdx],
110  "Wrong value mapping for 3 SPR ops instruction");
111  assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1],
113  "Wrong value mapping for 3 SPR ops instruction");
114  assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2],
116  "Wrong value mapping for 3 SPR ops instruction");
117 
118  assert(checkValueMapping(ValueMappings[DPR3OpsIdx],
120  "Wrong value mapping for 3 DPR ops instruction");
121  assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1],
123  "Wrong value mapping for 3 DPR ops instruction");
124  assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2],
126  "Wrong value mapping for 3 DPR ops instruction");
127 }
128 #endif
129 } // end namespace arm
130 } // end namespace llvm
131 
134  static bool AlreadyInit = false;
135  // We have only one set of register banks, whatever the subtarget
136  // is. Therefore, the initialization of the RegBanks table should be
137  // done only once. Indeed the table of all register banks
138  // (ARM::RegBanks) is unique in the compiler. At some point, it
139  // will get tablegen'ed and the whole constructor becomes empty.
140  if (AlreadyInit)
141  return;
142  AlreadyInit = true;
143 
144  const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);
145  (void)RBGPR;
146  assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");
147 
148  // Initialize the GPR bank.
149  assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) &&
150  "Subclass not added?");
151  assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) &&
152  "Subclass not added?");
153  assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) &&
154  "Subclass not added?");
155  assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) &&
156  "Subclass not added?");
157  assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) &&
158  "Subclass not added?");
159  assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&
160  "Subclass not added?");
161  assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) &&
162  "Subclass not added?");
163  assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPREven_and_tGPR_and_tcGPRRegClassID)) &&
164  "Subclass not added?");
165  assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPROdd_and_tcGPRRegClassID)) &&
166  "Subclass not added?");
167  assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit");
168 
169 #ifndef NDEBUG
172 #endif
173 }
174 
176  const TargetRegisterClass &RC) const {
177  using namespace ARM;
178 
179  switch (RC.getID()) {
180  case GPRRegClassID:
181  case GPRwithAPSRRegClassID:
182  case GPRnopcRegClassID:
183  case rGPRRegClassID:
184  case GPRspRegClassID:
185  case tGPR_and_tcGPRRegClassID:
186  case tcGPRRegClassID:
187  case tGPRRegClassID:
188  case tGPREvenRegClassID:
189  case tGPROddRegClassID:
190  case tGPR_and_tGPREvenRegClassID:
191  case tGPR_and_tGPROddRegClassID:
192  case tGPREven_and_tcGPRRegClassID:
193  case tGPREven_and_tGPR_and_tcGPRRegClassID:
194  case tGPROdd_and_tcGPRRegClassID:
195  return getRegBank(ARM::GPRRegBankID);
196  case HPRRegClassID:
197  case SPR_8RegClassID:
198  case SPRRegClassID:
199  case DPR_8RegClassID:
200  case DPRRegClassID:
201  case QPRRegClassID:
202  return getRegBank(ARM::FPRRegBankID);
203  default:
204  llvm_unreachable("Unsupported register kind");
205  }
206 
207  llvm_unreachable("Switch should handle all register classes");
208 }
209 
212  auto Opc = MI.getOpcode();
213 
214  // Try the default logic for non-generic instructions that are either copies
215  // or already have some operands assigned to banks.
216  if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
217  const InstructionMapping &Mapping = getInstrMappingImpl(MI);
218  if (Mapping.isValid())
219  return Mapping;
220  }
221 
222  using namespace TargetOpcode;
223 
224  const MachineFunction &MF = *MI.getParent()->getParent();
225  const MachineRegisterInfo &MRI = MF.getRegInfo();
226  unsigned NumOperands = MI.getNumOperands();
227  const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
228 
229  switch (Opc) {
230  case G_ADD:
231  case G_SUB: {
232  // Integer operations where the source and destination are in the
233  // same register class.
234  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
235  OperandsMapping = Ty.getSizeInBits() == 64
238  break;
239  }
240  case G_MUL:
241  case G_AND:
242  case G_OR:
243  case G_XOR:
244  case G_LSHR:
245  case G_ASHR:
246  case G_SHL:
247  case G_SDIV:
248  case G_UDIV:
249  case G_SEXT:
250  case G_ZEXT:
251  case G_ANYEXT:
252  case G_GEP:
253  case G_INTTOPTR:
254  case G_PTRTOINT:
255  case G_CTLZ:
256  // FIXME: We're abusing the fact that everything lives in a GPR for now; in
257  // the real world we would use different mappings.
258  OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
259  break;
260  case G_TRUNC: {
261  // In some cases we may end up with a G_TRUNC from a 64-bit value to a
262  // 32-bit value. This isn't a real floating point trunc (that would be a
263  // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear
264  // because the legalizer doesn't distinguish between integer and floating
265  // point values so it may leave some 64-bit integers un-narrowed. Until we
266  // have a more principled solution that doesn't let such things sneak all
267  // the way to this point, just map the source to a DPR and the destination
268  // to a GPR.
269  LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());
270  OperandsMapping =
271  LargeTy.getSizeInBits() <= 32
275  break;
276  }
277  case G_LOAD:
278  case G_STORE: {
279  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
280  OperandsMapping =
281  Ty.getSizeInBits() == 64
285  break;
286  }
287  case G_FADD:
288  case G_FSUB:
289  case G_FMUL:
290  case G_FDIV:
291  case G_FNEG: {
292  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
293  OperandsMapping =Ty.getSizeInBits() == 64
296  break;
297  }
298  case G_FMA: {
299  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
300  OperandsMapping =
301  Ty.getSizeInBits() == 64
304  &ARM::ValueMappings[ARM::DPR3OpsIdx],
305  &ARM::ValueMappings[ARM::DPR3OpsIdx]})
308  &ARM::ValueMappings[ARM::SPR3OpsIdx],
309  &ARM::ValueMappings[ARM::SPR3OpsIdx]});
310  break;
311  }
312  case G_FPEXT: {
313  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
314  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
315  if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32)
316  OperandsMapping =
319  break;
320  }
321  case G_FPTRUNC: {
322  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
323  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
324  if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64)
325  OperandsMapping =
328  break;
329  }
330  case G_FPTOSI:
331  case G_FPTOUI: {
332  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
333  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
334  if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) &&
335  ToTy.getSizeInBits() == 32)
336  OperandsMapping =
337  FromTy.getSizeInBits() == 64
342  break;
343  }
344  case G_SITOFP:
345  case G_UITOFP: {
346  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
347  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
348  if (FromTy.getSizeInBits() == 32 &&
349  (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64))
350  OperandsMapping =
351  ToTy.getSizeInBits() == 64
356  break;
357  }
358  case G_FCONSTANT: {
359  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
360  OperandsMapping = getOperandsMapping(
363  nullptr});
364  break;
365  }
366  case G_CONSTANT:
367  case G_FRAME_INDEX:
368  case G_GLOBAL_VALUE:
369  OperandsMapping =
371  break;
372  case G_SELECT: {
373  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
374  (void)Ty;
375  LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());
376  (void)Ty2;
377  assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");
378  assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");
379  OperandsMapping =
382  &ARM::ValueMappings[ARM::GPR3OpsIdx],
383  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
384  break;
385  }
386  case G_ICMP: {
387  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
388  (void)Ty2;
389  assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");
390  OperandsMapping =
393  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
394  break;
395  }
396  case G_FCMP: {
397  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
398  (void)Ty;
399  LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
400  LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
401  (void)Ty2;
402  assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");
403  assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
404  "Mismatched operand sizes for G_FCMP");
405 
406  unsigned Size = Ty1.getSizeInBits();
407  assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
408 
409  auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]
411  OperandsMapping =
413  FPRValueMapping, FPRValueMapping});
414  break;
415  }
416  case G_MERGE_VALUES: {
417  // We only support G_MERGE_VALUES for creating a double precision floating
418  // point value out of two GPRs.
419  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
420  LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
421  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
422  if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
423  Ty2.getSizeInBits() != 32)
425  OperandsMapping =
428  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
429  break;
430  }
431  case G_UNMERGE_VALUES: {
432  // We only support G_UNMERGE_VALUES for splitting a double precision
433  // floating point value into two GPRs.
434  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
435  LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
436  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
437  if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
438  Ty2.getSizeInBits() != 64)
440  OperandsMapping =
443  &ARM::ValueMappings[ARM::DPR3OpsIdx]});
444  break;
445  }
446  case G_BR:
447  OperandsMapping = getOperandsMapping({nullptr});
448  break;
449  case G_BRCOND:
450  OperandsMapping =
452  break;
453  case DBG_VALUE: {
454  SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands);
455  const MachineOperand &MaybeReg = MI.getOperand(0);
456  if (MaybeReg.isReg() && MaybeReg.getReg()) {
457  unsigned Size = MRI.getType(MaybeReg.getReg()).getSizeInBits();
458  if (Size > 32 && Size != 64)
460  OperandBanks[0] = Size == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
462  }
463  OperandsMapping = getOperandsMapping(OperandBanks);
464  break;
465  }
466  default:
468  }
469 
470 #ifndef NDEBUG
471  for (unsigned i = 0; i < NumOperands; i++) {
472  for (const auto &Mapping : OperandsMapping[i]) {
473  assert(
474  (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
475  MF.getSubtarget<ARMSubtarget>().hasVFP2Base()) &&
476  "Trying to use floating point register bank on target without vfp");
477  }
478  }
479 #endif
480 
481  return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
482  NumOperands);
483 }
static bool checkValueMapping(const RegisterBankInfo::ValueMapping &VM, RegisterBankInfo::PartialMapping *BreakDown)
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.
unsigned getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
Helper class that represents how the value of an instruction may be mapped and what is the related co...
LLT getType(unsigned Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
unsigned const TargetRegisterInfo * TRI
static void checkValueMappings()
const TargetRegisterClass * getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
const PartialMapping * BreakDown
How the value is broken down between the different register banks.
bool covers(const TargetRegisterClass &RC) const
Check whether this register bank covers RC.
unsigned getNumOperands() const
Retuns the total number of operands.
Definition: MachineInstr.h:413
unsigned StartIdx
Number of bits at which this partial mapping starts in the original value.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:410
unsigned getID() const
Return the register class ID number.
const RegisterBank * RegBank
Register bank where the partial value lives.
unsigned const MachineRegisterInfo * MRI
This file declares the targeting of the RegisterBankInfo class for ARM.
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.
RegisterBankInfo::ValueMapping ValueMappings[]
Helper struct that represents how a value is partially mapped into a register.
unsigned Length
Length of this mapping in bits.
static const unsigned DefaultMappingID
Identifier used when the related instruction mapping instance is generated by target independent code...
RegisterBankInfo::PartialMapping PartMappings[]
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
bool isValid() const
Check whether this object is valid.
ARMRegisterBankInfo(const TargetRegisterInfo &TRI)
static void checkPartialMappings()
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
MachineOperand class - Representation of each machine instruction operand.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
unsigned getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
This class implements the register bank concept.
Definition: RegisterBank.h:28
Helper struct that represents how a value is mapped through different register banks.
static bool checkPartMapping(const RegisterBankInfo::PartialMapping &PM, unsigned Start, unsigned Length, unsigned RegBankID)
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.
Representation of each machine instruction.
Definition: MachineInstr.h:63
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const InstructionMapping & getInstrMappingImpl(const MachineInstr &MI) const
Try to get the mapping of MI.
const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC) const override
Get a register bank that covers RC.
uint32_t Size
Definition: Profile.cpp:46
const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override
Get the mapping of the different operands of MI on the register bank.
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 NumBreakDowns
Number of partial mapping to break down this value.
IRTranslator LLVM IR MI
Register getReg() const
getReg - Returns the register number.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:415
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:47