LLVM  7.0.0svn
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  // 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...
Compute iterated dominance frontiers using a linear time algorithm.
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
Access to explicit operands of the instruction.
Definition: MachineInstr.h:314
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:311
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:156
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:60
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.
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.
constexpr char Size[]
Key for Kernel::Arg::Metadata::mSize.
IRTranslator LLVM IR MI
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:316
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:48