LLVM  9.0.0svn
X86RegisterBankInfo.cpp
Go to the documentation of this file.
1 //===- X86RegisterBankInfo.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 X86.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
12 
13 #include "X86RegisterBankInfo.h"
14 #include "X86InstrInfo.h"
19 
20 #define GET_TARGET_REGBANK_IMPL
21 #include "X86GenRegisterBank.inc"
22 
23 using namespace llvm;
24 // This file will be TableGen'ed at some point.
25 #define GET_TARGET_REGBANK_INFO_IMPL
26 #include "X86GenRegisterBankInfo.def"
27 
30 
31  // validate RegBank initialization.
32  const RegisterBank &RBGPR = getRegBank(X86::GPRRegBankID);
33  (void)RBGPR;
34  assert(&X86::GPRRegBank == &RBGPR && "Incorrect RegBanks inizalization.");
35 
36  // The GPR register bank is fully defined by all the registers in
37  // GR64 + its subclasses.
38  assert(RBGPR.covers(*TRI.getRegClass(X86::GR64RegClassID)) &&
39  "Subclass not added?");
40  assert(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
41 }
42 
44  const TargetRegisterClass &RC) const {
45 
46  if (X86::GR8RegClass.hasSubClassEq(&RC) ||
47  X86::GR16RegClass.hasSubClassEq(&RC) ||
48  X86::GR32RegClass.hasSubClassEq(&RC) ||
49  X86::GR64RegClass.hasSubClassEq(&RC))
50  return getRegBank(X86::GPRRegBankID);
51 
52  if (X86::FR32XRegClass.hasSubClassEq(&RC) ||
53  X86::FR64XRegClass.hasSubClassEq(&RC) ||
54  X86::VR128XRegClass.hasSubClassEq(&RC) ||
55  X86::VR256XRegClass.hasSubClassEq(&RC) ||
56  X86::VR512RegClass.hasSubClassEq(&RC))
57  return getRegBank(X86::VECRRegBankID);
58 
59  llvm_unreachable("Unsupported register kind yet.");
60 }
61 
64  if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
65  switch (Ty.getSizeInBits()) {
66  case 1:
67  case 8:
68  return PMI_GPR8;
69  case 16:
70  return PMI_GPR16;
71  case 32:
72  return PMI_GPR32;
73  case 64:
74  return PMI_GPR64;
75  case 128:
76  return PMI_VEC128;
77  break;
78  default:
79  llvm_unreachable("Unsupported register size.");
80  }
81  } else if (Ty.isScalar()) {
82  switch (Ty.getSizeInBits()) {
83  case 32:
84  return PMI_FP32;
85  case 64:
86  return PMI_FP64;
87  case 128:
88  return PMI_VEC128;
89  default:
90  llvm_unreachable("Unsupported register size.");
91  }
92  } else {
93  switch (Ty.getSizeInBits()) {
94  case 128:
95  return PMI_VEC128;
96  case 256:
97  return PMI_VEC256;
98  case 512:
99  return PMI_VEC512;
100  default:
101  llvm_unreachable("Unsupported register size.");
102  }
103  }
104 
105  return PMI_None;
106 }
107 
108 void X86RegisterBankInfo::getInstrPartialMappingIdxs(
109  const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,
110  SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) {
111 
112  unsigned NumOperands = MI.getNumOperands();
113  for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
114  auto &MO = MI.getOperand(Idx);
115  if (!MO.isReg())
116  OpRegBankIdx[Idx] = PMI_None;
117  else
118  OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP);
119  }
120 }
121 
122 bool X86RegisterBankInfo::getInstrValueMapping(
123  const MachineInstr &MI,
124  const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx,
126 
127  unsigned NumOperands = MI.getNumOperands();
128  for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
129  if (!MI.getOperand(Idx).isReg())
130  continue;
131 
132  auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
133  if (!Mapping->isValid())
134  return false;
135 
136  OpdsMapping[Idx] = Mapping;
137  }
138  return true;
139 }
140 
142 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,
143  bool isFP) const {
144  const MachineFunction &MF = *MI.getParent()->getParent();
145  const MachineRegisterInfo &MRI = MF.getRegInfo();
146 
147  unsigned NumOperands = MI.getNumOperands();
148  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
149 
150  if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||
151  (Ty != MRI.getType(MI.getOperand(2).getReg())))
152  llvm_unreachable("Unsupported operand mapping yet.");
153 
154  auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3);
155  return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
156 }
157 
160  const MachineFunction &MF = *MI.getParent()->getParent();
161  const MachineRegisterInfo &MRI = MF.getRegInfo();
162  auto Opc = MI.getOpcode();
163 
164  // Try the default logic for non-generic instructions that are either copies
165  // or already have some operands assigned to banks.
166  if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
167  const InstructionMapping &Mapping = getInstrMappingImpl(MI);
168  if (Mapping.isValid())
169  return Mapping;
170  }
171 
172  switch (Opc) {
173  case TargetOpcode::G_ADD:
174  case TargetOpcode::G_SUB:
175  case TargetOpcode::G_MUL:
176  return getSameOperandsMapping(MI, false);
177  case TargetOpcode::G_FADD:
178  case TargetOpcode::G_FSUB:
179  case TargetOpcode::G_FMUL:
180  case TargetOpcode::G_FDIV:
181  return getSameOperandsMapping(MI, true);
182  case TargetOpcode::G_SHL:
183  case TargetOpcode::G_LSHR:
184  case TargetOpcode::G_ASHR: {
185  const MachineFunction &MF = *MI.getParent()->getParent();
186  const MachineRegisterInfo &MRI = MF.getRegInfo();
187 
188  unsigned NumOperands = MI.getNumOperands();
189  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
190 
191  auto Mapping = getValueMapping(getPartialMappingIdx(Ty, false), 3);
192  return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
193 
194  }
195  default:
196  break;
197  }
198 
199  unsigned NumOperands = MI.getNumOperands();
200  SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
201 
202  switch (Opc) {
203  case TargetOpcode::G_FPEXT:
204  case TargetOpcode::G_FPTRUNC:
205  case TargetOpcode::G_FCONSTANT:
206  // Instruction having only floating-point operands (all scalars in VECRReg)
207  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
208  break;
209  case TargetOpcode::G_SITOFP:
210  case TargetOpcode::G_FPTOSI: {
211  // Some of the floating-point instructions have mixed GPR and FP operands:
212  // fine-tune the computed mapping.
213  auto &Op0 = MI.getOperand(0);
214  auto &Op1 = MI.getOperand(1);
215  const LLT Ty0 = MRI.getType(Op0.getReg());
216  const LLT Ty1 = MRI.getType(Op1.getReg());
217 
218  bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
219  bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
220  OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP);
221  OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP);
222  break;
223  }
224  case TargetOpcode::G_FCMP: {
225  LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
226  LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
227  (void)Ty2;
228  assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
229  "Mismatched operand sizes for G_FCMP");
230 
231  unsigned Size = Ty1.getSizeInBits();
232  (void)Size;
233  assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
234 
235  auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true);
236  OpRegBankIdx = {PMI_GPR8,
237  /* Predicate */ PMI_None, FpRegBank, FpRegBank};
238  break;
239  }
240  case TargetOpcode::G_TRUNC:
241  case TargetOpcode::G_ANYEXT: {
242  auto &Op0 = MI.getOperand(0);
243  auto &Op1 = MI.getOperand(1);
244  const LLT Ty0 = MRI.getType(Op0.getReg());
245  const LLT Ty1 = MRI.getType(Op1.getReg());
246 
247  bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) &&
248  Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC;
249  bool isFPAnyExt =
250  Ty0.getSizeInBits() == 128 &&
251  (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) &&
252  Opc == TargetOpcode::G_ANYEXT;
253 
254  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt,
255  OpRegBankIdx);
256  } break;
257  default:
258  // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
259  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
260  break;
261  }
262 
263  // Finally construct the computed mapping.
264  SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
265  if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
267 
268  return getInstructionMapping(DefaultMappingID, /* Cost */ 1,
269  getOperandsMapping(OpdsMapping), NumOperands);
270 }
271 
273  const OperandsMapper &OpdMapper) const {
274  return applyDefaultMapping(OpdMapper);
275 }
276 
279 
280  const MachineFunction &MF = *MI.getParent()->getParent();
281  const TargetSubtargetInfo &STI = MF.getSubtarget();
282  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
283  const MachineRegisterInfo &MRI = MF.getRegInfo();
284 
285  switch (MI.getOpcode()) {
286  case TargetOpcode::G_LOAD:
287  case TargetOpcode::G_STORE:
288  case TargetOpcode::G_IMPLICIT_DEF: {
289  // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
290  unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
291  if (Size != 32 && Size != 64)
292  break;
293 
294  unsigned NumOperands = MI.getNumOperands();
295 
296  // Track the bank of each register, use FP mapping (all scalars in VEC)
297  SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
298  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
299 
300  // Finally construct the computed mapping.
301  SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
302  if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
303  break;
304 
306  /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);
307  InstructionMappings AltMappings;
308  AltMappings.push_back(&Mapping);
309  return AltMappings;
310  }
311  default:
312  break;
313  }
315 }
InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const override
Get the alternative mappings for MI.
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.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
Helper class that represents how the value of an instruction may be mapped and what is the related co...
void push_back(const T &Elt)
Definition: SmallVector.h:211
bool isScalar() const
unsigned getReg() const
getReg - Returns the register number.
X86RegisterBankInfo(const TargetRegisterInfo &TRI)
LLT getType(unsigned Reg) const
Get the low-level type of Reg or LLT{} if Reg is not a generic (target independent) virtual register...
Helper class used to get/create the virtual registers that will be used to replace the MachineOperand...
unsigned const TargetRegisterInfo * TRI
const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC) const override
Get a register bank that covers RC.
const TargetRegisterClass * getRegClass(unsigned i) const
Returns the register class associated with the enumeration value.
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
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:41
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:408
static PartialMappingIdx getPartialMappingIdx(const LLT &Ty, bool isFP)
static const RegisterBankInfo::ValueMapping * getValueMapping(PartialMappingIdx Idx, unsigned NumOperands)
unsigned const MachineRegisterInfo * MRI
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.
static const unsigned DefaultMappingID
Identifier used when the related instruction mapping instance is generated by target independent code...
void applyMappingImpl(const OperandsMapper &OpdMapper) const override
See RegisterBankInfo::applyMapping.
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.
This file declares the targeting of the RegisterBankInfo class for X86.
bool isValid() const
Check whether this object is valid.
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:839
static void applyDefaultMapping(const OperandsMapper &OpdMapper)
Helper method to apply something that is like the default mapping.
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
const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override
Get the mapping of the different operands of MI on the register bank.
bool isPointer() const
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.
TargetSubtargetInfo - Generic base class for all target subtargets.
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.
virtual InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const
Get the alternative mappings for MI.
const InstructionMapping & getInstrMappingImpl(const MachineInstr &MI) const
Try to get the mapping of MI.
uint32_t Size
Definition: Profile.cpp:46
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 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