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  unsigned 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  unsigned NumOperands = MI.getNumOperands();
186  LLT Ty = MRI.getType(MI.getOperand(0).getReg());
187 
188  auto Mapping = getValueMapping(getPartialMappingIdx(Ty, false), 3);
189  return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
190 
191  }
192  default:
193  break;
194  }
195 
196  unsigned NumOperands = MI.getNumOperands();
197  SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
198 
199  switch (Opc) {
200  case TargetOpcode::G_FPEXT:
201  case TargetOpcode::G_FPTRUNC:
202  case TargetOpcode::G_FCONSTANT:
203  // Instruction having only floating-point operands (all scalars in VECRReg)
204  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
205  break;
206  case TargetOpcode::G_SITOFP:
207  case TargetOpcode::G_FPTOSI: {
208  // Some of the floating-point instructions have mixed GPR and FP operands:
209  // fine-tune the computed mapping.
210  auto &Op0 = MI.getOperand(0);
211  auto &Op1 = MI.getOperand(1);
212  const LLT Ty0 = MRI.getType(Op0.getReg());
213  const LLT Ty1 = MRI.getType(Op1.getReg());
214 
215  bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
216  bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
217  OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP);
218  OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP);
219  break;
220  }
221  case TargetOpcode::G_FCMP: {
222  LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
223  LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
224  (void)Ty2;
225  assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
226  "Mismatched operand sizes for G_FCMP");
227 
228  unsigned Size = Ty1.getSizeInBits();
229  (void)Size;
230  assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
231 
232  auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true);
233  OpRegBankIdx = {PMI_GPR8,
234  /* Predicate */ PMI_None, FpRegBank, FpRegBank};
235  break;
236  }
237  case TargetOpcode::G_TRUNC:
238  case TargetOpcode::G_ANYEXT: {
239  auto &Op0 = MI.getOperand(0);
240  auto &Op1 = MI.getOperand(1);
241  const LLT Ty0 = MRI.getType(Op0.getReg());
242  const LLT Ty1 = MRI.getType(Op1.getReg());
243 
244  bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) &&
245  Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC;
246  bool isFPAnyExt =
247  Ty0.getSizeInBits() == 128 &&
248  (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) &&
249  Opc == TargetOpcode::G_ANYEXT;
250 
251  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt,
252  OpRegBankIdx);
253  } break;
254  default:
255  // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
256  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
257  break;
258  }
259 
260  // Finally construct the computed mapping.
261  SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
262  if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
264 
265  return getInstructionMapping(DefaultMappingID, /* Cost */ 1,
266  getOperandsMapping(OpdsMapping), NumOperands);
267 }
268 
270  const OperandsMapper &OpdMapper) const {
271  return applyDefaultMapping(OpdMapper);
272 }
273 
276 
277  const MachineFunction &MF = *MI.getParent()->getParent();
278  const TargetSubtargetInfo &STI = MF.getSubtarget();
279  const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
280  const MachineRegisterInfo &MRI = MF.getRegInfo();
281 
282  switch (MI.getOpcode()) {
283  case TargetOpcode::G_LOAD:
284  case TargetOpcode::G_STORE:
285  case TargetOpcode::G_IMPLICIT_DEF: {
286  // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
287  unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
288  if (Size != 32 && Size != 64)
289  break;
290 
291  unsigned NumOperands = MI.getNumOperands();
292 
293  // Track the bank of each register, use FP mapping (all scalars in VEC)
294  SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
295  getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
296 
297  // Finally construct the computed mapping.
298  SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
299  if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
300  break;
301 
303  /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);
304  InstructionMappings AltMappings;
305  AltMappings.push_back(&Mapping);
306  return AltMappings;
307  }
308  default:
309  break;
310  }
312 }
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:413
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:410
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:255
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:415