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_FCONSTANT: {
340  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
341  OperandsMapping = getOperandsMapping(
344  nullptr});
345  break;
346  }
347  case G_CONSTANT:
348  case G_FRAME_INDEX:
349  case G_GLOBAL_VALUE:
350  OperandsMapping =
352  break;
353  case G_SELECT: {
354  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
355  (void)Ty;
356  LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());
357  (void)Ty2;
358  assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");
359  assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");
360  OperandsMapping =
363  &ARM::ValueMappings[ARM::GPR3OpsIdx],
364  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
365  break;
366  }
367  case G_ICMP: {
368  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
369  (void)Ty2;
370  assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");
371  OperandsMapping =
374  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
375  break;
376  }
377  case G_FCMP: {
378  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
379  (void)Ty;
380  LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
381  LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
382  (void)Ty2;
383  assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");
384  assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
385  "Mismatched operand sizes for G_FCMP");
386 
387  unsigned Size = Ty1.getSizeInBits();
388  assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
389 
390  auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]
392  OperandsMapping =
394  FPRValueMapping, FPRValueMapping});
395  break;
396  }
397  case G_MERGE_VALUES: {
398  // We only support G_MERGE_VALUES for creating a double precision floating
399  // point value out of two GPRs.
400  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
401  LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
402  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
403  if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
404  Ty2.getSizeInBits() != 32)
406  OperandsMapping =
409  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
410  break;
411  }
412  case G_UNMERGE_VALUES: {
413  // We only support G_UNMERGE_VALUES for splitting a double precision
414  // floating point value into two GPRs.
415  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
416  LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
417  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
418  if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
419  Ty2.getSizeInBits() != 64)
421  OperandsMapping =
424  &ARM::ValueMappings[ARM::DPR3OpsIdx]});
425  break;
426  }
427  case G_BR:
428  OperandsMapping = getOperandsMapping({nullptr});
429  break;
430  case G_BRCOND:
431  OperandsMapping =
433  break;
434  case DBG_VALUE: {
435  SmallVector<const ValueMapping *, 4> OperandBanks(NumOperands);
436  const MachineOperand &MaybeReg = MI.getOperand(0);
437  if (MaybeReg.isReg() && MaybeReg.getReg()) {
438  unsigned Size = MRI.getType(MaybeReg.getReg()).getSizeInBits();
439  if (Size > 32 && Size != 64)
441  OperandBanks[0] = Size == 64 ? &ARM::ValueMappings[ARM::DPR3OpsIdx]
443  }
444  OperandsMapping = getOperandsMapping(OperandBanks);
445  break;
446  }
447  default:
449  }
450 
451 #ifndef NDEBUG
452  for (unsigned i = 0; i < NumOperands; i++) {
453  for (const auto &Mapping : OperandsMapping[i]) {
454  assert(
455  (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
456  MF.getSubtarget<ARMSubtarget>().hasVFP2()) &&
457  "Trying to use floating point register bank on target without vfp");
458  }
459  }
460 #endif
461 
462  return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
463  NumOperands);
464 }
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
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.
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:841
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.
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.
unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
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