LLVM 17.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(RBGPR.getSize() == 64 && "GPRs should hold up to 64-bit");
40}
41
42const RegisterBank &
44 LLT) 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
64X86GenRegisterBankInfo::PartialMappingIdx
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
110void X86RegisterBankInfo::getInstrPartialMappingIdxs(
111 const MachineInstr &MI, const MachineRegisterInfo &MRI, const bool isFP,
113
114 unsigned NumOperands = MI.getNumOperands();
115 for (unsigned Idx = 0; Idx < NumOperands; ++Idx) {
116 auto &MO = MI.getOperand(Idx);
117 if (!MO.isReg() || !MO.getReg())
118 OpRegBankIdx[Idx] = PMI_None;
119 else
120 OpRegBankIdx[Idx] = getPartialMappingIdx(MRI.getType(MO.getReg()), isFP);
121 }
122}
123
124bool 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 if (!MI.getOperand(Idx).getReg())
134 continue;
135
136 auto Mapping = getValueMapping(OpRegBankIdx[Idx], 1);
137 if (!Mapping->isValid())
138 return false;
139
140 OpdsMapping[Idx] = Mapping;
141 }
142 return true;
143}
144
146X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr &MI,
147 bool isFP) const {
148 const MachineFunction &MF = *MI.getParent()->getParent();
149 const MachineRegisterInfo &MRI = MF.getRegInfo();
150
151 unsigned NumOperands = MI.getNumOperands();
152 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
153
154 if (NumOperands != 3 || (Ty != MRI.getType(MI.getOperand(1).getReg())) ||
155 (Ty != MRI.getType(MI.getOperand(2).getReg())))
156 llvm_unreachable("Unsupported operand mapping yet.");
157
158 auto Mapping = getValueMapping(getPartialMappingIdx(Ty, isFP), 3);
159 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
160}
161
164 const MachineFunction &MF = *MI.getParent()->getParent();
165 const MachineRegisterInfo &MRI = MF.getRegInfo();
166 unsigned Opc = MI.getOpcode();
167
168 // Try the default logic for non-generic instructions that are either copies
169 // or already have some operands assigned to banks.
170 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
171 const InstructionMapping &Mapping = getInstrMappingImpl(MI);
172 if (Mapping.isValid())
173 return Mapping;
174 }
175
176 switch (Opc) {
177 case TargetOpcode::G_ADD:
178 case TargetOpcode::G_SUB:
179 case TargetOpcode::G_MUL:
180 return getSameOperandsMapping(MI, false);
181 case TargetOpcode::G_FADD:
182 case TargetOpcode::G_FSUB:
183 case TargetOpcode::G_FMUL:
184 case TargetOpcode::G_FDIV:
185 return getSameOperandsMapping(MI, true);
186 case TargetOpcode::G_SHL:
187 case TargetOpcode::G_LSHR:
188 case TargetOpcode::G_ASHR: {
189 unsigned NumOperands = MI.getNumOperands();
190 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
191
192 auto Mapping = getValueMapping(getPartialMappingIdx(Ty, false), 3);
193 return getInstructionMapping(DefaultMappingID, 1, Mapping, NumOperands);
194
195 }
196 default:
197 break;
198 }
199
200 unsigned NumOperands = MI.getNumOperands();
201 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
202
203 switch (Opc) {
204 case TargetOpcode::G_FPEXT:
205 case TargetOpcode::G_FPTRUNC:
206 case TargetOpcode::G_FCONSTANT:
207 // Instruction having only floating-point operands (all scalars in VECRReg)
208 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
209 break;
210 case TargetOpcode::G_SITOFP:
211 case TargetOpcode::G_FPTOSI: {
212 // Some of the floating-point instructions have mixed GPR and FP operands:
213 // fine-tune the computed mapping.
214 auto &Op0 = MI.getOperand(0);
215 auto &Op1 = MI.getOperand(1);
216 const LLT Ty0 = MRI.getType(Op0.getReg());
217 const LLT Ty1 = MRI.getType(Op1.getReg());
218
219 bool FirstArgIsFP = Opc == TargetOpcode::G_SITOFP;
220 bool SecondArgIsFP = Opc == TargetOpcode::G_FPTOSI;
221 OpRegBankIdx[0] = getPartialMappingIdx(Ty0, /* isFP */ FirstArgIsFP);
222 OpRegBankIdx[1] = getPartialMappingIdx(Ty1, /* isFP */ SecondArgIsFP);
223 break;
224 }
225 case TargetOpcode::G_FCMP: {
226 LLT Ty1 = MRI.getType(MI.getOperand(2).getReg());
227 LLT Ty2 = MRI.getType(MI.getOperand(3).getReg());
228 (void)Ty2;
229 assert(Ty1.getSizeInBits() == Ty2.getSizeInBits() &&
230 "Mismatched operand sizes for G_FCMP");
231
232 unsigned Size = Ty1.getSizeInBits();
233 (void)Size;
234 assert((Size == 32 || Size == 64) && "Unsupported size for G_FCMP");
235
236 auto FpRegBank = getPartialMappingIdx(Ty1, /* isFP */ true);
237 OpRegBankIdx = {PMI_GPR8,
238 /* Predicate */ PMI_None, FpRegBank, FpRegBank};
239 break;
240 }
241 case TargetOpcode::G_TRUNC:
242 case TargetOpcode::G_ANYEXT: {
243 auto &Op0 = MI.getOperand(0);
244 auto &Op1 = MI.getOperand(1);
245 const LLT Ty0 = MRI.getType(Op0.getReg());
246 const LLT Ty1 = MRI.getType(Op1.getReg());
247
248 bool isFPTrunc = (Ty0.getSizeInBits() == 32 || Ty0.getSizeInBits() == 64) &&
249 Ty1.getSizeInBits() == 128 && Opc == TargetOpcode::G_TRUNC;
250 bool isFPAnyExt =
251 Ty0.getSizeInBits() == 128 &&
252 (Ty1.getSizeInBits() == 32 || Ty1.getSizeInBits() == 64) &&
253 Opc == TargetOpcode::G_ANYEXT;
254
255 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ isFPTrunc || isFPAnyExt,
256 OpRegBankIdx);
257 } break;
258 default:
259 // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
260 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ false, OpRegBankIdx);
261 break;
262 }
263
264 // Finally construct the computed mapping.
265 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
266 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
268
269 return getInstructionMapping(DefaultMappingID, /* Cost */ 1,
270 getOperandsMapping(OpdsMapping), NumOperands);
271}
272
274 const OperandsMapper &OpdMapper) const {
275 return applyDefaultMapping(OpdMapper);
276}
277
280
281 const MachineFunction &MF = *MI.getParent()->getParent();
282 const TargetSubtargetInfo &STI = MF.getSubtarget();
283 const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
284 const MachineRegisterInfo &MRI = MF.getRegInfo();
285
286 switch (MI.getOpcode()) {
287 case TargetOpcode::G_LOAD:
288 case TargetOpcode::G_STORE:
289 case TargetOpcode::G_IMPLICIT_DEF: {
290 // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
291 unsigned Size = getSizeInBits(MI.getOperand(0).getReg(), MRI, TRI);
292 if (Size != 32 && Size != 64)
293 break;
294
295 unsigned NumOperands = MI.getNumOperands();
296
297 // Track the bank of each register, use FP mapping (all scalars in VEC)
298 SmallVector<PartialMappingIdx, 4> OpRegBankIdx(NumOperands);
299 getInstrPartialMappingIdxs(MI, MRI, /* isFP */ true, OpRegBankIdx);
300
301 // Finally construct the computed mapping.
302 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
303 if (!getInstrValueMapping(MI, OpRegBankIdx, OpdsMapping))
304 break;
305
307 /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping), NumOperands);
308 InstructionMappings AltMappings;
309 AltMappings.push_back(&Mapping);
310 return AltMappings;
311 }
312 default:
313 break;
314 }
316}
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
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
constexpr bool isPointer() const
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.
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.
RegisterBank & getRegBank(unsigned ID)
Get the register bank identified by ID.
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
unsigned getSize() const
Get the maximal size in bits that fits in this register bank.
Definition: RegisterBank.h:54
bool covers(const TargetRegisterClass &RC) const
Check whether this register bank covers RC.
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.
void applyMappingImpl(const OperandsMapper &OpdMapper) const override
See RegisterBankInfo::applyMapping.
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.
#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