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