LLVM  9.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.getSize() == 32 && "GPRs should hold up to 32-bit");
164 
165 #ifndef NDEBUG
168 #endif
169 }
170 
172  const TargetRegisterClass &RC) const {
173  using namespace ARM;
174 
175  switch (RC.getID()) {
176  case GPRRegClassID:
177  case GPRwithAPSRRegClassID:
178  case GPRnopcRegClassID:
179  case rGPRRegClassID:
180  case GPRspRegClassID:
181  case tGPR_and_tcGPRRegClassID:
182  case tcGPRRegClassID:
183  case tGPRRegClassID:
184  return getRegBank(ARM::GPRRegBankID);
185  case HPRRegClassID:
186  case SPR_8RegClassID:
187  case SPRRegClassID:
188  case DPR_8RegClassID:
189  case DPRRegClassID:
190  case QPRRegClassID:
191  return getRegBank(ARM::FPRRegBankID);
192  default:
193  llvm_unreachable("Unsupported register kind");
194  }
195 
196  llvm_unreachable("Switch should handle all register classes");
197 }
198 
201  auto Opc = MI.getOpcode();
202 
203  // Try the default logic for non-generic instructions that are either copies
204  // or already have some operands assigned to banks.
205  if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
206  const InstructionMapping &Mapping = getInstrMappingImpl(MI);
207  if (Mapping.isValid())
208  return Mapping;
209  }
210 
211  using namespace TargetOpcode;
212 
213  const MachineFunction &MF = *MI.getParent()->getParent();
214  const MachineRegisterInfo &MRI = MF.getRegInfo();
215  unsigned NumOperands = MI.getNumOperands();
216  const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
217 
218  switch (Opc) {
219  case G_ADD:
220  case G_SUB:
221  case G_MUL:
222  case G_AND:
223  case G_OR:
224  case G_XOR:
225  case G_LSHR:
226  case G_ASHR:
227  case G_SHL:
228  case G_SDIV:
229  case G_UDIV:
230  case G_SEXT:
231  case G_ZEXT:
232  case G_ANYEXT:
233  case G_GEP:
234  case G_INTTOPTR:
235  case G_PTRTOINT:
236  case G_CTLZ:
237  // FIXME: We're abusing the fact that everything lives in a GPR for now; in
238  // the real world we would use different mappings.
239  OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
240  break;
241  case G_TRUNC: {
242  // In some cases we may end up with a G_TRUNC from a 64-bit value to a
243  // 32-bit value. This isn't a real floating point trunc (that would be a
244  // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear
245  // because the legalizer doesn't distinguish between integer and floating
246  // point values so it may leave some 64-bit integers un-narrowed. Until we
247  // have a more principled solution that doesn't let such things sneak all
248  // the way to this point, just map the source to a DPR and the destination
249  // to a GPR.
250  LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());
251  OperandsMapping =
252  LargeTy.getSizeInBits() <= 32
256  break;
257  }
258  case G_LOAD:
259  case G_STORE: {
260  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
261  OperandsMapping =
262  Ty.getSizeInBits() == 64
266  break;
267  }
268  case G_FADD:
269  case G_FSUB:
270  case G_FMUL:
271  case G_FDIV:
272  case G_FNEG: {
273  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
274  OperandsMapping =Ty.getSizeInBits() == 64
277  break;
278  }
279  case G_FMA: {
280  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
281  OperandsMapping =
282  Ty.getSizeInBits() == 64
285  &ARM::ValueMappings[ARM::DPR3OpsIdx],
286  &ARM::ValueMappings[ARM::DPR3OpsIdx]})
289  &ARM::ValueMappings[ARM::SPR3OpsIdx],
290  &ARM::ValueMappings[ARM::SPR3OpsIdx]});
291  break;
292  }
293  case G_FPEXT: {
294  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
295  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
296  if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32)
297  OperandsMapping =
300  break;
301  }
302  case G_FPTRUNC: {
303  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
304  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
305  if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64)
306  OperandsMapping =
309  break;
310  }
311  case G_FPTOSI:
312  case G_FPTOUI: {
313  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
314  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
315  if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) &&
316  ToTy.getSizeInBits() == 32)
317  OperandsMapping =
318  FromTy.getSizeInBits() == 64
323  break;
324  }
325  case G_SITOFP:
326  case G_UITOFP: {
327  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
328  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
329  if (FromTy.getSizeInBits() == 32 &&
330  (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64))
331  OperandsMapping =
332  ToTy.getSizeInBits() == 64
337  break;
338  }
339  case G_CONSTANT:
340  case G_FRAME_INDEX:
341  case G_GLOBAL_VALUE:
342  OperandsMapping =
344  break;
345  case G_SELECT: {
346  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
347  (void)Ty;
348  LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());
349  (void)Ty2;
350  assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");
351  assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");
352  OperandsMapping =
355  &ARM::ValueMappings[ARM::GPR3OpsIdx],
356  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
357  break;
358  }
359  case G_ICMP: {
360  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
361  (void)Ty2;
362  assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");
363  OperandsMapping =
366  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
367  break;
368  }
369  case G_FCMP: {
370  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
371  (void)Ty;
372  LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
373  LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
374  (void)Ty2;
375  assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");
376  assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
377  "Mismatched operand sizes for G_FCMP");
378 
379  unsigned Size = Ty1.getSizeInBits();
380  assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
381 
382  auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]
384  OperandsMapping =
386  FPRValueMapping, FPRValueMapping});
387  break;
388  }
389  case G_MERGE_VALUES: {
390  // We only support G_MERGE_VALUES for creating a double precision floating
391  // point value out of two GPRs.
392  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
393  LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
394  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
395  if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
396  Ty2.getSizeInBits() != 32)
398  OperandsMapping =
401  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
402  break;
403  }
404  case G_UNMERGE_VALUES: {
405  // We only support G_UNMERGE_VALUES for splitting a double precision
406  // floating point value into two GPRs.
407  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
408  LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
409  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
410  if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
411  Ty2.getSizeInBits() != 64)
413  OperandsMapping =
416  &ARM::ValueMappings[ARM::DPR3OpsIdx]});
417  break;
418  }
419  case G_BR:
420  OperandsMapping = getOperandsMapping({nullptr});
421  break;
422  case G_BRCOND:
423  OperandsMapping =
425  break;
426  default:
428  }
429 
430 #ifndef NDEBUG
431  for (unsigned i = 0; i < NumOperands; i++) {
432  for (const auto &Mapping : OperandsMapping[i]) {
433  assert(
434  (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
435  MF.getSubtarget<ARMSubtarget>().hasVFP2()) &&
436  "Trying to use floating point register bank on target without vfp");
437  }
438  }
439 #endif
440 
441  return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
442  NumOperands);
443 }
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.
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.
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
setjmp/longjmp based exceptions
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:411
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:408
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.
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:253
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.
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
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:413
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:47