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