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 GPRnopcRegClassID:
179  case GPRspRegClassID:
180  case tGPR_and_tcGPRRegClassID:
181  case tGPRRegClassID:
182  return getRegBank(ARM::GPRRegBankID);
183  case SPR_8RegClassID:
184  case SPRRegClassID:
185  case DPR_8RegClassID:
186  case DPRRegClassID:
187  return getRegBank(ARM::FPRRegBankID);
188  default:
189  llvm_unreachable("Unsupported register kind");
190  }
191 
192  llvm_unreachable("Switch should handle all register classes");
193 }
194 
197  auto Opc = MI.getOpcode();
198 
199  // Try the default logic for non-generic instructions that are either copies
200  // or already have some operands assigned to banks.
201  if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
202  const InstructionMapping &Mapping = getInstrMappingImpl(MI);
203  if (Mapping.isValid())
204  return Mapping;
205  }
206 
207  using namespace TargetOpcode;
208 
209  const MachineFunction &MF = *MI.getParent()->getParent();
210  const MachineRegisterInfo &MRI = MF.getRegInfo();
211  unsigned NumOperands = MI.getNumOperands();
212  const ValueMapping *OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
213 
214  switch (Opc) {
215  case G_ADD:
216  case G_SUB:
217  case G_MUL:
218  case G_AND:
219  case G_OR:
220  case G_XOR:
221  case G_LSHR:
222  case G_ASHR:
223  case G_SHL:
224  case G_SDIV:
225  case G_UDIV:
226  case G_SEXT:
227  case G_ZEXT:
228  case G_ANYEXT:
229  case G_GEP:
230  case G_INTTOPTR:
231  case G_PTRTOINT:
232  // FIXME: We're abusing the fact that everything lives in a GPR for now; in
233  // the real world we would use different mappings.
234  OperandsMapping = &ARM::ValueMappings[ARM::GPR3OpsIdx];
235  break;
236  case G_TRUNC: {
237  // In some cases we may end up with a G_TRUNC from a 64-bit value to a
238  // 32-bit value. This isn't a real floating point trunc (that would be a
239  // G_FPTRUNC). Instead it is an integer trunc in disguise, which can appear
240  // because the legalizer doesn't distinguish between integer and floating
241  // point values so it may leave some 64-bit integers un-narrowed. Until we
242  // have a more principled solution that doesn't let such things sneak all
243  // the way to this point, just map the source to a DPR and the destination
244  // to a GPR.
245  LLT LargeTy = MRI.getType(MI.getOperand(1).getReg());
246  OperandsMapping =
247  LargeTy.getSizeInBits() <= 32
251  break;
252  }
253  case G_LOAD:
254  case G_STORE: {
255  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
256  OperandsMapping =
257  Ty.getSizeInBits() == 64
261  break;
262  }
263  case G_FADD:
264  case G_FSUB:
265  case G_FMUL:
266  case G_FDIV:
267  case G_FNEG: {
268  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
269  OperandsMapping =Ty.getSizeInBits() == 64
272  break;
273  }
274  case G_FMA: {
275  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
276  OperandsMapping =
277  Ty.getSizeInBits() == 64
280  &ARM::ValueMappings[ARM::DPR3OpsIdx],
281  &ARM::ValueMappings[ARM::DPR3OpsIdx]})
284  &ARM::ValueMappings[ARM::SPR3OpsIdx],
285  &ARM::ValueMappings[ARM::SPR3OpsIdx]});
286  break;
287  }
288  case G_FPEXT: {
289  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
290  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
291  if (ToTy.getSizeInBits() == 64 && FromTy.getSizeInBits() == 32)
292  OperandsMapping =
295  break;
296  }
297  case G_FPTRUNC: {
298  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
299  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
300  if (ToTy.getSizeInBits() == 32 && FromTy.getSizeInBits() == 64)
301  OperandsMapping =
304  break;
305  }
306  case G_FPTOSI:
307  case G_FPTOUI: {
308  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
309  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
310  if ((FromTy.getSizeInBits() == 32 || FromTy.getSizeInBits() == 64) &&
311  ToTy.getSizeInBits() == 32)
312  OperandsMapping =
313  FromTy.getSizeInBits() == 64
318  break;
319  }
320  case G_SITOFP:
321  case G_UITOFP: {
322  LLT ToTy = MRI.getType(MI.getOperand(0).getReg());
323  LLT FromTy = MRI.getType(MI.getOperand(1).getReg());
324  if (FromTy.getSizeInBits() == 32 &&
325  (ToTy.getSizeInBits() == 32 || ToTy.getSizeInBits() == 64))
326  OperandsMapping =
327  ToTy.getSizeInBits() == 64
332  break;
333  }
334  case G_CONSTANT:
335  case G_FRAME_INDEX:
336  case G_GLOBAL_VALUE:
337  OperandsMapping =
339  break;
340  case G_SELECT: {
341  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
342  (void)Ty;
343  LLT Ty2 = MRI.getType(MI.getOperand(1).getReg());
344  (void)Ty2;
345  assert(Ty.getSizeInBits() == 32 && "Unsupported size for G_SELECT");
346  assert(Ty2.getSizeInBits() == 1 && "Unsupported size for G_SELECT");
347  OperandsMapping =
350  &ARM::ValueMappings[ARM::GPR3OpsIdx],
351  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
352  break;
353  }
354  case G_ICMP: {
355  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
356  (void)Ty2;
357  assert(Ty2.getSizeInBits() == 32 && "Unsupported size for G_ICMP");
358  OperandsMapping =
361  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
362  break;
363  }
364  case G_FCMP: {
365  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
366  (void)Ty;
367  LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
368  LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
369  (void)Ty2;
370  assert(Ty.getSizeInBits() == 1 && "Unsupported size for G_FCMP");
371  assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
372  "Mismatched operand sizes for G_FCMP");
373 
374  unsigned Size = Ty1.getSizeInBits();
375  assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
376 
377  auto FPRValueMapping = Size == 32 ? &ARM::ValueMappings[ARM::SPR3OpsIdx]
379  OperandsMapping =
381  FPRValueMapping, FPRValueMapping});
382  break;
383  }
384  case G_MERGE_VALUES: {
385  // We only support G_MERGE_VALUES for creating a double precision floating
386  // point value out of two GPRs.
387  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
388  LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
389  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
390  if (Ty.getSizeInBits() != 64 || Ty1.getSizeInBits() != 32 ||
391  Ty2.getSizeInBits() != 32)
393  OperandsMapping =
396  &ARM::ValueMappings[ARM::GPR3OpsIdx]});
397  break;
398  }
399  case G_UNMERGE_VALUES: {
400  // We only support G_UNMERGE_VALUES for splitting a double precision
401  // floating point value into two GPRs.
402  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
403  LLT Ty1 = MRI.getType(MI.getOperand(1).getReg());
404  LLT Ty2 = MRI.getType(MI.getOperand(2).getReg());
405  if (Ty.getSizeInBits() != 32 || Ty1.getSizeInBits() != 32 ||
406  Ty2.getSizeInBits() != 64)
408  OperandsMapping =
411  &ARM::ValueMappings[ARM::DPR3OpsIdx]});
412  break;
413  }
414  case G_BR:
415  OperandsMapping = getOperandsMapping({nullptr});
416  break;
417  case G_BRCOND:
418  OperandsMapping =
420  break;
421  default:
423  }
424 
425 #ifndef NDEBUG
426  for (unsigned i = 0; i < NumOperands; i++) {
427  for (const auto &Mapping : OperandsMapping[i]) {
428  assert(
429  (Mapping.RegBank->getID() != ARM::FPRRegBankID ||
430  MF.getSubtarget<ARMSubtarget>().hasVFP2()) &&
431  "Trying to use floating point register bank on target without vfp");
432  }
433  }
434 #endif
435 
436  return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping,
437  NumOperands);
438 }
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.
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:296
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:293
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:142
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.
LLT getType(unsigned VReg) const
Get the low-level type of VReg or LLT{} if VReg is not a generic (target independent) virtual registe...
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:298
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:48