LLVM 19.0.0git
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"
15#include "X86Subtarget.h"
20
21#define GET_TARGET_REGBANK_IMPL
22#include "X86GenRegisterBank.inc"
23
24using namespace llvm;
25// This file will be TableGen'ed at some point.
26#define GET_TARGET_REGBANK_INFO_IMPL
27#include "X86GenRegisterBankInfo.def"
28
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(getMaximumSize(RBGPR.getID()) == 64 &&
41 "GPRs should hold up to 64-bit");
42}
43
44const RegisterBank &
46 LLT) const {
47
48 if (X86::GR8RegClass.hasSubClassEq(&RC) ||
49 X86::GR16RegClass.hasSubClassEq(&RC) ||
50 X86::GR32RegClass.hasSubClassEq(&RC) ||
51 X86::GR64RegClass.hasSubClassEq(&RC) ||
52 X86::LOW32_ADDR_ACCESSRegClass.hasSubClassEq(&RC) ||
53 X86::LOW32_ADDR_ACCESS_RBPRegClass.hasSubClassEq(&RC))
54 return getRegBank(X86::GPRRegBankID);
55
56 if (X86::FR32XRegClass.hasSubClassEq(&RC) ||
57 X86::FR64XRegClass.hasSubClassEq(&RC) ||
58 X86::VR128XRegClass.hasSubClassEq(&RC) ||
59 X86::VR256XRegClass.hasSubClassEq(&RC) ||
60 X86::VR512RegClass.hasSubClassEq(&RC))
61 return getRegBank(X86::VECRRegBankID);
62
63 if (X86::RFP80RegClass.hasSubClassEq(&RC) ||
64 X86::RFP32RegClass.hasSubClassEq(&RC) ||
65 X86::RFP64RegClass.hasSubClassEq(&RC))
66 return getRegBank(X86::PSRRegBankID);
67
68 llvm_unreachable("Unsupported register kind yet.");
69}
70
71X86GenRegisterBankInfo::PartialMappingIdx
73 const LLT &Ty, bool isFP) {
74 const MachineFunction *MF = MI.getMF();
75 const X86Subtarget *ST = &MF->getSubtarget<X86Subtarget>();
76 bool HasSSE1 = ST->hasSSE1();
77 bool HasSSE2 = ST->hasSSE2();
78 // 80 bits is only generated for X87 floating points.
79 if (Ty.getSizeInBits() == 80)
80 isFP = true;
81 if ((Ty.isScalar() && !isFP) || Ty.isPointer()) {
82 switch (Ty.getSizeInBits()) {
83 case 1:
84 case 8:
85 return PMI_GPR8;
86 case 16:
87 return PMI_GPR16;
88 case 32:
89 return PMI_GPR32;
90 case 64:
91 return PMI_GPR64;
92 case 128:
93 return PMI_VEC128;
94 break;
95 default:
96 llvm_unreachable("Unsupported register size.");
97 }
98 } else if (Ty.isScalar()) {
99 switch (Ty.getSizeInBits()) {
100 case 32:
101 return HasSSE1 ? PMI_FP32 : PMI_PSR32;
102 case 64:
103 return HasSSE2 ? PMI_FP64 : PMI_PSR64;
104 case 128:
105 return PMI_VEC128;
106 case 80:
107 return PMI_PSR80;
108 default:
109 llvm_unreachable("Unsupported register size.");
110 }
111 } else {
112 switch (Ty.getSizeInBits()) {
113 case 128:
114 return PMI_VEC128;
115 case 256:
116 return PMI_VEC256;
117 case 512:
118 return PMI_VEC512;
119 default:
120 llvm_unreachable("Unsupported register size.");
121 }
122 }
123
124 return PMI_None;
125}
126
127void X86RegisterBankInfo::getInstrPartialMappingIdxs(
128 const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,
130
131 unsigned NumOperands = MI.getNumOperands();
132 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
133 auto &MO = MI.getOperand(Idx);
134 if (!MO.isReg() || !MO.getReg())
135 OpRegBankIdx[Idx] = PMI_None;
136 else
137 OpRegBankIdx[Idx] =
138 getPartialMappingIdx(MI, MRI.getType(MO.getReg()), isFP);
139 }
140}
141
142bool X86RegisterBankInfo::getInstrValueMapping(
143 const MachineInstr &MI,
144 const SmallVectorImpl<PartialMappingIdx> &OpRegBankIdx,
146
147 unsigned NumOperands = MI.getNumOperands();
148 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
149 if (!MI.getOperand(Idx).isReg())
150 continue;
151 if (!MI.getOperand(Idx).getReg())
152 continue;
153
154 auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
155 if (!Mapping->isValid())
156 return false;
157
158 OpdsMapping[Idx] = Mapping;
159 }
160 return true;
161}
162
164X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,
165 bool isFP) const {
166 const MachineFunction &MF = *MI.getParent()->getParent();
167 const MachineRegisterInfo &MRI = MF.getRegInfo();
168
169 unsigned NumOperands = MI.getNumOperands();
170 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
171
172 if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||
173 (Ty != MRI.getType(MI.getOperand(2).getReg())))
174 llvm_unreachable("Unsupported operand mapping yet.");
175
176 auto Mapping = getValueMapping(getPartialMappingIdx(MI, Ty, isFP), 3);
177 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
178}
179
182 const MachineFunction &MF = *MI.getParent()->getParent();
183 const MachineRegisterInfo &MRI = MF.getRegInfo();
184 unsigned Opc = MI.getOpcode();
185
186 // Try the default logic for non-generic instructions that are either copies
187 // or already have some operands assigned to banks.
188 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
189 const InstructionMapping &Mapping = getInstrMappingImpl(MI);
190 if (Mapping.isValid())
191 return Mapping;
192 }
193
194 switch (Opc) {
195 case TargetOpcode::G_ADD:
196 case TargetOpcode::G_SUB:
197 case TargetOpcode::G_MUL:
198 return getSameOperandsMapping(MI, false);
199 case TargetOpcode::G_FADD:
200 case TargetOpcode::G_FSUB:
201 case TargetOpcode::G_FMUL:
202 case TargetOpcode::G_FDIV:
203 return getSameOperandsMapping(MI, true);
204 case TargetOpcode::G_SHL:
205 case TargetOpcode::G_LSHR:
206 case TargetOpcode::G_ASHR: {
207 unsigned NumOperands = MI.getNumOperands();
208 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
209
210 auto Mapping = getValueMapping(getPartialMappingIdx(MI, Ty, false), 3);
211 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
212 }
213 default:
214 break;
215 }
216
217 unsigned NumOperands = MI.getNumOperands();
218 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
219
220 switch (Opc) {
221 case TargetOpcode::G_FPEXT:
222 case TargetOpcode::G_FPTRUNC:
223 case TargetOpcode::G_FCONSTANT:
224 // Instruction having only floating-point operands (all scalars in VECRReg)
225 getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);
226 break;
227 case TargetOpcode::G_SITOFP:
228 case TargetOpcode::G_FPTOSI: {
229 // Some of the floating-point instructions have mixed GPR and FP operands:
230 // fine-tune the computed mapping.
231 auto &Op0 = MI.getOperand(0);
232 auto &Op1 = MI.getOperand(1);
233 const LLT Ty0 = MRI.getType(Op0.getReg());
234 const LLT Ty1 = MRI.getType(Op1.getReg());
235
236 bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
237 bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
238 OpRegBankIdx[0] = getPartialMappingIdx(MI, Ty0, /* isFP= */ FirstArgIsFP);
239 OpRegBankIdx[1] = getPartialMappingIdx(MI, Ty1, /* isFP= */ SecondArgIsFP);
240 break;
241 }
242 case TargetOpcode::G_FCMP: {
243 LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
244 LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
245 (void)Ty2;
246 assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
247 "Mismatched operand sizes for G_FCMP");
248
249 unsigned Size = Ty1.getSizeInBits();
250 (void)Size;
251 assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
252
253 auto FpRegBank = getPartialMappingIdx(MI, Ty1, /* isFP= */ true);
254 OpRegBankIdx = {PMI_GPR8,
255 /* Predicate */ PMI_None, FpRegBank, FpRegBank};
256 break;
257 }
258 case TargetOpcode::G_TRUNC:
259 case TargetOpcode::G_ANYEXT: {
260 auto &Op0 = MI.getOperand(0);
261 auto &Op1 = MI.getOperand(1);
262 const LLT Ty0 = MRI.getType(Op0.getReg());
263 const LLT Ty1 = MRI.getType(Op1.getReg());
264
265 bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) &&
266 Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC;
267 bool isFPAnyExt =
268 Ty0.getSizeInBits() == 128 &&
269 (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) &&
270 Opc == TargetOpcode::G_ANYEXT;
271
272 getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ isFPTrunc || isFPAnyExt,
273 OpRegBankIdx);
274 } break;
275 default:
276 // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
277 getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ false, OpRegBankIdx);
278 break;
279 }
280
281 // Finally construct the computed mapping.
282 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
283 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
285
286 return getInstructionMapping(DefaultMappingID, /* Cost */ 1,
287 getOperandsMapping(OpdsMapping), NumOperands);
288}
289
291 MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const {
292 return applyDefaultMapping(OpdMapper);
293}
294
297
298 const MachineFunction &MF = *MI.getParent()->getParent();
299 const TargetSubtargetInfo &STI = MF.getSubtarget();
300 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
301 const MachineRegisterInfo &MRI = MF.getRegInfo();
302
303 switch (MI.getOpcode()) {
304 case TargetOpcode::G_LOAD:
305 case TargetOpcode::G_STORE:
306 case TargetOpcode::G_IMPLICIT_DEF: {
307 // we going to try to map 32/64/80 bit to PMI_FP32/PMI_FP64/PMI_FP80
308 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
309 if (Size != 32 && Size != 64 && Size != 80)
310 break;
311
312 unsigned NumOperands = MI.getNumOperands();
313
314 // Track the bank of each register, use FP mapping (all scalars in VEC)
315 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
316 getInstrPartialMappingIdxs(MI, MRI, /* isFP= */ true, OpRegBankIdx);
317
318 // Finally construct the computed mapping.
319 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
320 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
321 break;
322
324 /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);
325 InstructionMappings AltMappings;
326 AltMappings.push_back(&Mapping);
327 return AltMappings;
328 }
329 default:
330 break;
331 }
333}
unsigned const MachineRegisterInfo * MRI
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
uint64_t Size
IRTranslator LLVM IR MI
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file declares the targeting of the RegisterBankInfo class for X86.
constexpr bool isScalar() const
Definition: LowLevelType.h:146
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:193
constexpr bool isPointer() const
Definition: LowLevelType.h:149
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Helper class to build MachineInstr.
Representation of each machine instruction.
Definition: MachineInstr.h:69
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
Helper class that represents how the value of an instruction may be mapped and what is the related co...
bool isValid() const
Check whether this object is valid.
Helper class used to get/create the virtual registers that will be used to replace the MachineOperand...
virtual InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const
Get the alternative mappings for MI.
const InstructionMapping & getInstructionMapping(unsigned ID, unsigned Cost, const ValueMapping *OperandsMapping, unsigned NumOperands) const
Method to get a uniquely generated InstructionMapping.
static void applyDefaultMapping(const OperandsMapper &OpdMapper)
Helper method to apply something that is like the default mapping.
const InstructionMapping & getInvalidInstructionMapping() const
Method to get a uniquely generated invalid InstructionMapping.
const RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
unsigned getMaximumSize(unsigned RegBankID) const
Get the maximum size in bits that fits in the given register bank.
TypeSize getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
const ValueMapping * getOperandsMapping(Iterator Begin, Iterator End) const
Get the uniquely generated array of ValueMapping for the elements of between Begin and End.
static const unsigned DefaultMappingID
Identifier used when the related instruction mapping instance is generated by target independent code...
const InstructionMapping & getInstrMappingImpl(const MachineInstr &MI) const
Try to get the mapping of MI.
This class implements the register bank concept.
Definition: RegisterBank.h:28
bool covers(const TargetRegisterClass &RC) const
Check whether this register bank covers RC.
unsigned getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:45
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TargetSubtargetInfo - Generic base class for all target subtargets.
virtual const TargetRegisterInfo * getRegisterInfo() const
getRegisterInfo - If register information is available, return it.
static PartialMappingIdx getPartialMappingIdx(const MachineInstr &MI, const LLT &Ty, bool isFP)
static const RegisterBankInfo::ValueMapping * getValueMapping(PartialMappingIdx Idx, unsigned NumOperands)
X86RegisterBankInfo(const TargetRegisterInfo &TRI)
InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const override
Get the alternative mappings for MI.
const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT) 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.
void applyMappingImpl(MachineIRBuilder &Builder, const OperandsMapper &OpdMapper) const override
See RegisterBankInfo::applyMapping.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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