LLVM  8.0.1
ARMRegisterBankInfo.cpp
Go to the documentation of this file.
1 //===- ARMRegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 /// \file
10 /// This file implements the targeting of the RegisterBankInfo class for ARM.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
13 
14 #include "ARMRegisterBankInfo.h"
15 #include "ARMInstrInfo.h" // For the register classes
16 #include "ARMSubtarget.h"
21 
22 #define GET_TARGET_REGBANK_IMPL
23 #include "ARMGenRegisterBank.inc"
24 
25 using namespace llvm;
26 
27 // FIXME: TableGen this.
28 // If it grows too much and TableGen still isn't ready to do the job, extract it
29 // into an ARMGenRegisterBankInfo.def (similar to AArch64).
30 namespace llvm {
31 namespace ARM {
37 };
38 
40  // GPR Partial Mapping
41  {0, 32, GPRRegBank},
42  // SPR Partial Mapping
43  {0, 32, FPRRegBank},
44  // DPR Partial Mapping
45  {0, 64, FPRRegBank},
46 };
47 
48 #ifndef NDEBUG
50  unsigned Start, unsigned Length,
51  unsigned RegBankID) {
52  return PM.StartIdx == Start && PM.Length == Length &&
53  PM.RegBank->getID() == RegBankID;
54 }
55 
56 static void checkPartialMappings() {
57  assert(
58  checkPartMapping(PartMappings[PMI_GPR - PMI_Min], 0, 32, GPRRegBankID) &&
59  "Wrong mapping for GPR");
60  assert(
61  checkPartMapping(PartMappings[PMI_SPR - PMI_Min], 0, 32, FPRRegBankID) &&
62  "Wrong mapping for SPR");
63  assert(
64  checkPartMapping(PartMappings[PMI_DPR - PMI_Min], 0, 64, FPRRegBankID) &&
65  "Wrong mapping for DPR");
66 }
67 #endif
68 
74 };
75 
77  // invalid
78  {nullptr, 0},
79  // 3 ops in GPRs
80  {&PartMappings[PMI_GPR - PMI_Min], 1},
81  {&PartMappings[PMI_GPR - PMI_Min], 1},
82  {&PartMappings[PMI_GPR - PMI_Min], 1},
83  // 3 ops in SPRs
84  {&PartMappings[PMI_SPR - PMI_Min], 1},
85  {&PartMappings[PMI_SPR - PMI_Min], 1},
86  {&PartMappings[PMI_SPR - PMI_Min], 1},
87  // 3 ops in DPRs
88  {&PartMappings[PMI_DPR - PMI_Min], 1},
89  {&PartMappings[PMI_DPR - PMI_Min], 1},
90  {&PartMappings[PMI_DPR - PMI_Min], 1}};
91 
92 #ifndef NDEBUG
95  return VM.NumBreakDowns == 1 && VM.BreakDown == BreakDown;
96 }
97 
98 static void checkValueMappings() {
99  assert(checkValueMapping(ValueMappings[GPR3OpsIdx],
101  "Wrong value mapping for 3 GPR ops instruction");
102  assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 1],
104  "Wrong value mapping for 3 GPR ops instruction");
105  assert(checkValueMapping(ValueMappings[GPR3OpsIdx + 2],
107  "Wrong value mapping for 3 GPR ops instruction");
108 
109  assert(checkValueMapping(ValueMappings[SPR3OpsIdx],
111  "Wrong value mapping for 3 SPR ops instruction");
112  assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 1],
114  "Wrong value mapping for 3 SPR ops instruction");
115  assert(checkValueMapping(ValueMappings[SPR3OpsIdx + 2],
117  "Wrong value mapping for 3 SPR ops instruction");
118 
119  assert(checkValueMapping(ValueMappings[DPR3OpsIdx],
121  "Wrong value mapping for 3 DPR ops instruction");
122  assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 1],
124  "Wrong value mapping for 3 DPR ops instruction");
125  assert(checkValueMapping(ValueMappings[DPR3OpsIdx + 2],
127  "Wrong value mapping for 3 DPR ops instruction");
128 }
129 #endif
130 } // end namespace arm
131 } // end namespace llvm
132 
135  static bool AlreadyInit = false;
136  // We have only one set of register banks, whatever the subtarget
137  // is. Therefore, the initialization of the RegBanks table should be
138  // done only once. Indeed the table of all register banks
139  // (ARM::RegBanks) is unique in the compiler. At some point, it
140  // will get tablegen'ed and the whole constructor becomes empty.
141  if (AlreadyInit)
142  return;
143  AlreadyInit = true;
144 
145  const RegisterBank &RBGPR = getRegBank(ARM::GPRRegBankID);
146  (void)RBGPR;
147  assert(&ARM::GPRRegBank == &RBGPR && "The order in RegBanks is messed up");
148 
149  // Initialize the GPR bank.
150  assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRRegClassID)) &&
151  "Subclass not added?");
152  assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRwithAPSRRegClassID)) &&
153  "Subclass not added?");
154  assert(RBGPR.covers(*TRI.getRegClass(ARM::GPRnopcRegClassID)) &&
155  "Subclass not added?");
156  assert(RBGPR.covers(*TRI.getRegClass(ARM::rGPRRegClassID)) &&
157  "Subclass not added?");
158  assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPRRegClassID)) &&
159  "Subclass not added?");
160  assert(RBGPR.covers(*TRI.getRegClass(ARM::tcGPRRegClassID)) &&
161  "Subclass not added?");
162  assert(RBGPR.covers(*TRI.getRegClass(ARM::tGPR_and_tcGPRRegClassID)) &&
163  "Subclass not added?");
164  assert(RBGPR.getSize() == 32 && "GPRs should hold up to 32-bit");
165 
166 #ifndef NDEBUG
169 #endif
170 }
171 
173  const TargetRegisterClass &RC) const {
174  using namespace ARM;
175 
176  switch (RC.getID()) {
177  case GPRRegClassID:
178  case GPRwithAPSRRegClassID:
179  case GPRnopcRegClassID:
180  case rGPRRegClassID:
181  case GPRspRegClassID:
182  case tGPR_and_tcGPRRegClassID:
183  case tcGPRRegClassID:
184  case tGPRRegClassID:
185  return getRegBank(ARM::GPRRegBankID);
186  case HPRRegClassID:
187  case SPR_8RegClassID:
188  case SPRRegClassID:
189  case DPR_8RegClassID:
190  case DPRRegClassID:
191  case QPRRegClassID:
192  return getRegBank(ARM::FPRRegBankID);
193  default:
194  llvm_unreachable("Unsupported register kind");
195  }
196 
197  llvm_unreachable("Switch should handle all register classes");
198 }
199 
202  auto Opc = MI.getOpcode();
203 
204  // Try the default logic for non-generic instructions that are either copies
205  // or already have some operands assigned to banks.
206  if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
207  const InstructionMapping &Mapping = getInstrMappingImpl(MI);
208  if (Mapping.isValid())
209  return Mapping;
210  }
211 
212  using namespace TargetOpcode;
213 
214  const MachineFunction &MF = *MI.getParent()->getParent();
215  const MachineRegisterInfo &MRI = MF.getRegInfo();
216  unsigned NumOperands = MI.getNumOperands();
217  const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
218 
219  switch (Opc) {
220  case G_ADD:
221  case G_SUB:
222  case G_MUL:
223  case G_AND:
224  case G_OR:
225  case G_XOR:
226  case G_LSHR:
227  case G_ASHR:
228  case G_SHL:
229  case G_SDIV:
230  case G_UDIV:
231  case G_SEXT:
232  case G_ZEXT:
233  case G_ANYEXT:
234  case G_GEP:
235  case G_INTTOPTR:
236  case G_PTRTOINT:
237  case G_CTLZ:
238  // FIXME: We're abusing the fact that everything lives in a GPR for now; in
239  // the real world we would use different mappings.
240  OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
241  break;
242  case G_TRUNC: {
243  // In some cases we may end up with a G_TRUNC from a 64-bit value to a
244  // 32-bit value. This isn't a real floating point trunc (that would be a
245  // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear
246  // because the legalizer doesn't distinguish between integer and floating
247  // point values so it may leave some 64-bit integers un-narrowed. Until we
248  // have a more principled solution that doesn't let such things sneak all
249  // the way to this point, just map the source to a DPR and the destination
250  // to a GPR.
251  LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());
252  OperandsMapping =
253  LargeTy.getSizeInBits() <= 32
257  break;
258  }
259  case G_LOAD:
260  case G_STORE: {
261  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
262  OperandsMapping =
263  Ty.getSizeInBits() == 64
267  break;
268  }
269  case G_FADD:
270  case G_FSUB:
271  case G_FMUL:
272  case G_FDIV:
273  case G_FNEG: {
274  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
275  OperandsMapping =Ty.getSizeInBits() == 64
278  break;
279  }
280  case G_FMA: {
281  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
282  OperandsMapping =
283  Ty.getSizeInBits() == 64
286  &ARM::ValueMappings[ARM::DPR3OpsIdx],
287  &ARM::ValueMappings[ARM::DPR3OpsIdx]})
290  &ARM::ValueMappings[ARM::SPR3OpsIdx],
291  &ARM::ValueMappings[ARM::SPR3OpsIdx]});
292  break;
293  }
294  case G_FPEXT: {
295  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
296  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
297  if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32)
298  OperandsMapping =
301  break;
302  }
303  case G_FPTRUNC: {
304  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
305  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
306  if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64)
307  OperandsMapping =
310  break;
311  }
312  case G_FPTOSI:
313  case G_FPTOUI: {
314  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
315  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
316  if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) &&
317  ToTy.getSizeInBits() == 32)
318  OperandsMapping =
319  FromTy.getSizeInBits() == 64
324  break;
325  }
326  case G_SITOFP:
327  case G_UITOFP: {
328  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
329  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
330  if (FromTy.getSizeInBits() == 32 &&
331  (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64))
332  OperandsMapping =
333  ToTy.getSizeInBits() == 64
338  break;
339  }
340  case G_CONSTANT:
341  case G_FRAME_INDEX:
342  case G_GLOBAL_VALUE:
343  OperandsMapping =
345  break;
346  case G_SELECT: {
347  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
348  (void)Ty;
349  LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());
350  (void)Ty2;
351  assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");
352  assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");
353  OperandsMapping =
356  &ARM::ValueMappings[ARM::GPR3OpsIdx],
357  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
358  break;
359  }
360  case G_ICMP: {
361  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
362  (void)Ty2;
363  assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");
364  OperandsMapping =
367  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
368  break;
369  }
370  case G_FCMP: {
371  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
372  (void)Ty;
373  LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
374  LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
375  (void)Ty2;
376  assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");
377  assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
378  "Mismatched operand sizes for G_FCMP");
379 
380  unsigned Size = Ty1.getSizeInBits();
381  assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
382 
383  auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]
385  OperandsMapping =
387  FPRValueMapping, FPRValueMapping});
388  break;
389  }
390  case G_MERGE_VALUES: {
391  // We only support G_MERGE_VALUES for creating a double precision floating
392  // point value out of two GPRs.
393  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
394  LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
395  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
396  if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
397  Ty2.getSizeInBits() != 32)
399  OperandsMapping =
402  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
403  break;
404  }
405  case G_UNMERGE_VALUES: {
406  // We only support G_UNMERGE_VALUES for splitting a double precision
407  // floating point value into two GPRs.
408  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
409  LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
410  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
411  if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
412  Ty2.getSizeInBits() != 64)
414  OperandsMapping =
417  &ARM::ValueMappings[ARM::DPR3OpsIdx]});
418  break;
419  }
420  case G_BR:
421  OperandsMapping = getOperandsMapping({nullptr});
422  break;
423  case G_BRCOND:
424  OperandsMapping =
426  break;
427  default:
429  }
430 
431 #ifndef NDEBUG
432  for (unsigned i = 0; i < NumOperands; i++) {
433  for (const auto &Mapping : OperandsMapping[i]) {
434  assert(
435  (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
436  MF.getSubtarget<ARMSubtarget>().hasVFP2()) &&
437  "Trying to use floating point register bank on target without vfp");
438  }
439  }
440 #endif
441 
442  return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
443  NumOperands);
444 }
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:24
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:412
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:409
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:29
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:254
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:64
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:47
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:55
bool isPreISelGenericOpcode(unsigned Opcode)
Check whether the given Opcode is a generic opcode that is not supposed to appear after ISel...
Definition: TargetOpcodes.h:31
unsigned NumBreakDowns
Number of partial mapping to break down this value.
IRTranslator LLVM IR MI
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:414
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:48