LLVM  10.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  X86::LOW32_ADDR_ACCESSRegClass.hasSubClassEq(&RC) ||
51  X86::LOW32_ADDR_ACCESS_RBPRegClass.hasSubClassEq(&RC))
52  return getRegBank(X86::GPRRegBankID);
53 
54  if (X86::FR32XRegClass.hasSubClassEq(&RC) ||
55  X86::FR64XRegClass.hasSubClassEq(&RC) ||
56  X86::VR128XRegClass.hasSubClassEq(&RC) ||
57  X86::VR256XRegClass.hasSubClassEq(&RC) ||
58  X86::VR512RegClass.hasSubClassEq(&RC))
59  return getRegBank(X86::VECRRegBankID);
60 
61  llvm_unreachable("Unsupported register kind yet.");
62 }
63 
66  if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
67  switch (Ty.getSizeInBits()) {
68  case 1:
69  case 8:
70  return PMI_GPR8;
71  case 16:
72  return PMI_GPR16;
73  case 32:
74  return PMI_GPR32;
75  case 64:
76  return PMI_GPR64;
77  case 128:
78  return PMI_VEC128;
79  break;
80  default:
81  llvm_unreachable("Unsupported register size.");
82  }
83  } else if (Ty.isScalar()) {
84  switch (Ty.getSizeInBits()) {
85  case 32:
86  return PMI_FP32;
87  case 64:
88  return PMI_FP64;
89  case 128:
90  return PMI_VEC128;
91  default:
92  llvm_unreachable("Unsupported register size.");
93  }
94  } else {
95  switch (Ty.getSizeInBits()) {
96  case 128:
97  return PMI_VEC128;
98  case 256:
99  return PMI_VEC256;
100  case 512:
101  return PMI_VEC512;
102  default:
103  llvm_unreachable("Unsupported register size.");
104  }
105  }
106 
107  return PMI_None;
108 }
109 
110 void X86RegisterBankInfo::getInstrPartialMappingIdxs(
111  const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,
112  SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx) {
113 
114  unsigned NumOperands = MI.getNumOperands();
115  for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
116  auto &MO = MI.getOperand(Idx);
117  if (!MO.isReg())
118  OpRegBankIdx[Idx] = PMI_None;
119  else
120  OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP);
121  }
122 }
123 
124 bool X86RegisterBankInfo::getInstrValueMapping(
125  const MachineInstr &MI,
126  const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx,
128 
129  unsigned NumOperands = MI.getNumOperands();
130  for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
131  if (!MI.getOperand(Idx).isReg())
132  continue;
133 
134  auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
135  if (!Mapping->isValid())
136  return false;
137 
138  OpdsMapping[Idx] = Mapping;
139  }
140  return true;
141 }
142 
144 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,
145  bool isFP) const {
146  const MachineFunction &MF = *MI.getParent()->getParent();
147  const MachineRegisterInfo &MRI = MF.getRegInfo();
148 
149  unsigned NumOperands = MI.getNumOperands();
150  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
151 
152  if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||
153  (Ty != MRI.getType(MI.getOperand(2).getReg())))
154  llvm_unreachable("Unsupported operand mapping yet.");
155 
156  auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3);
157  return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
158 }
159 
162  const MachineFunction &MF = *MI.getParent()->getParent();
163  const MachineRegisterInfo &MRI = MF.getRegInfo();
164  unsigned Opc = MI.getOpcode();
165 
166  // Try the default logic for non-generic instructions that are either copies
167  // or already have some operands assigned to banks.
168  if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
169  const InstructionMapping &Mapping = getInstrMappingImpl(MI);
170  if (Mapping.isValid())
171  return Mapping;
172  }
173 
174  switch (Opc) {
175  case TargetOpcode::G_ADD:
176  case TargetOpcode::G_SUB:
177  case TargetOpcode::G_MUL:
178  return getSameOperandsMapping(MI, false);
179  case TargetOpcode::G_FADD:
180  case TargetOpcode::G_FSUB:
181  case TargetOpcode::G_FMUL:
182  case TargetOpcode::G_FDIV:
183  return getSameOperandsMapping(MI, true);
184  case TargetOpcode::G_SHL:
185  case TargetOpcode::G_LSHR:
186  case TargetOpcode::G_ASHR: {
187  unsigned NumOperands = MI.getNumOperands();
188  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
189 
190  auto Mapping = getValueMapping(getPartialMappingIdx(Ty, false), 3);
191  return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
192 
193  }
194  default:
195  break;
196  }
197 
198  unsigned NumOperands = MI.getNumOperands();
199  SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
200 
201  switch (Opc) {
202  case TargetOpcode::G_FPEXT:
203  case TargetOpcode::G_FPTRUNC:
204  case TargetOpcode::G_FCONSTANT:
205  // Instruction having only floating-point operands (all scalars in VECRReg)
206  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
207  break;
208  case TargetOpcode::G_SITOFP:
209  case TargetOpcode::G_FPTOSI: {
210  // Some of the floating-point instructions have mixed GPR and FP operands:
211  // fine-tune the computed mapping.
212  auto &Op0 = MI.getOperand(0);
213  auto &Op1 = MI.getOperand(1);
214  const LLT Ty0 = MRI.getType(Op0.getReg());
215  const LLT Ty1 = MRI.getType(Op1.getReg());
216 
217  bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
218  bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
219  OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP);
220  OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP);
221  break;
222  }
223  case TargetOpcode::G_FCMP: {
224  LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
225  LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
226  (void)Ty2;
227  assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
228  "Mismatched operand sizes for G_FCMP");
229 
230  unsigned Size = Ty1.getSizeInBits();
231  (void)Size;
232  assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
233 
234  auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true);
235  OpRegBankIdx = {PMI_GPR8,
236  /* Predicate */ PMI_None, FpRegBank, FpRegBank};
237  break;
238  }
239  case TargetOpcode::G_TRUNC:
240  case TargetOpcode::G_ANYEXT: {
241  auto &Op0 = MI.getOperand(0);
242  auto &Op1 = MI.getOperand(1);
243  const LLT Ty0 = MRI.getType(Op0.getReg());
244  const LLT Ty1 = MRI.getType(Op1.getReg());
245 
246  bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) &&
247  Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC;
248  bool isFPAnyExt =
249  Ty0.getSizeInBits() == 128 &&
250  (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) &&
251  Opc == TargetOpcode::G_ANYEXT;
252 
253  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt,
254  OpRegBankIdx);
255  } break;
256  default:
257  // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
258  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
259  break;
260  }
261 
262  // Finally construct the computed mapping.
263  SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
264  if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
266 
267  return getInstructionMapping(DefaultMappingID, /* Cost */ 1,
268  getOperandsMapping(OpdsMapping), NumOperands);
269 }
270 
272  const OperandsMapper &OpdMapper) const {
273  return applyDefaultMapping(OpdMapper);
274 }
275 
278 
279  const MachineFunction &MF = *MI.getParent()->getParent();
280  const TargetSubtargetInfo &STI = MF.getSubtarget();
281  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
282  const MachineRegisterInfo &MRI = MF.getRegInfo();
283 
284  switch (MI.getOpcode()) {
285  case TargetOpcode::G_LOAD:
286  case TargetOpcode::G_STORE:
287  case TargetOpcode::G_IMPLICIT_DEF: {
288  // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
289  unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
290  if (Size != 32 && Size != 64)
291  break;
292 
293  unsigned NumOperands = MI.getNumOperands();
294 
295  // Track the bank of each register, use FP mapping (all scalars in VEC)
296  SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
297  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
298 
299  // Finally construct the computed mapping.
300  SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
301  if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
302  break;
303 
305  /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);
306  InstructionMappings AltMappings;
307  AltMappings.push_back(&Mapping);
308  return AltMappings;
309  }
310  default:
311  break;
312  }
314 }
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.
unsigned getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
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
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:414
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:411
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:837
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:256
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: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
IRTranslator LLVM IR MI
Register getReg() const
getReg - Returns the register number.
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:416