1 //===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
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
7 //===----------------------------------------------------------------------===//
9 /// This file implements the targeting of the RegisterBankInfo class for X86.
10 /// \todo This should be generated by TableGen.
11 //===----------------------------------------------------------------------===//
13 #include "X86RegisterBankInfo.h"
14 #include "X86InstrInfo.h"
15 #include "llvm/CodeGen/MachineRegisterInfo.h"
16 #include "llvm/CodeGen/RegisterBank.h"
17 #include "llvm/CodeGen/RegisterBankInfo.h"
18 #include "llvm/CodeGen/TargetRegisterInfo.h"
20 #define GET_TARGET_REGBANK_IMPL
21 #include "X86GenRegisterBank.inc"
24 // This file will be TableGen'ed at some point.
25 #define GET_TARGET_REGBANK_INFO_IMPL
26 #include "X86GenRegisterBankInfo.def"
28 X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo
&TRI
) {
30 // validate RegBank initialization.
31 const RegisterBank
&RBGPR
= getRegBank(X86::GPRRegBankID
);
33 assert(&X86::GPRRegBank
== &RBGPR
&& "Incorrect RegBanks inizalization.");
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");
44 X86RegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass
&RC
,
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
);
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
);
62 llvm_unreachable("Unsupported register kind yet.");
65 X86GenRegisterBankInfo::PartialMappingIdx
66 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT
&Ty
, bool isFP
) {
67 if ((Ty
.isScalar() && !isFP
) || Ty
.isPointer()) {
68 switch (Ty
.getSizeInBits()) {
82 llvm_unreachable("Unsupported register size.");
84 } else if (Ty
.isScalar()) {
85 switch (Ty
.getSizeInBits()) {
93 llvm_unreachable("Unsupported register size.");
96 switch (Ty
.getSizeInBits()) {
104 llvm_unreachable("Unsupported register size.");
111 void X86RegisterBankInfo::getInstrPartialMappingIdxs(
112 const MachineInstr
&MI
, const MachineRegisterInfo
&MRI
, const bool isFP
,
113 SmallVectorImpl
<PartialMappingIdx
> &OpRegBankIdx
) {
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
;
121 OpRegBankIdx
[Idx
] = getPartialMappingIdx(MRI
.getType(MO
.getReg()), isFP
);
125 bool X86RegisterBankInfo::getInstrValueMapping(
126 const MachineInstr
&MI
,
127 const SmallVectorImpl
<PartialMappingIdx
> &OpRegBankIdx
,
128 SmallVectorImpl
<const ValueMapping
*> &OpdsMapping
) {
130 unsigned NumOperands
= MI
.getNumOperands();
131 for (unsigned Idx
= 0; Idx
< NumOperands
; ++Idx
) {
132 if (!MI
.getOperand(Idx
).isReg())
134 if (!MI
.getOperand(Idx
).getReg())
137 auto Mapping
= getValueMapping(OpRegBankIdx
[Idx
], 1);
138 if (!Mapping
->isValid())
141 OpdsMapping
[Idx
] = Mapping
;
146 const RegisterBankInfo::InstructionMapping
&
147 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr
&MI
,
149 const MachineFunction
&MF
= *MI
.getParent()->getParent();
150 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
152 unsigned NumOperands
= MI
.getNumOperands();
153 LLT Ty
= MRI
.getType(MI
.getOperand(0).getReg());
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.");
159 auto Mapping
= getValueMapping(getPartialMappingIdx(Ty
, isFP
), 3);
160 return getInstructionMapping(DefaultMappingID
, 1, Mapping
, NumOperands
);
163 const RegisterBankInfo::InstructionMapping
&
164 X86RegisterBankInfo::getInstrMapping(const MachineInstr
&MI
) const {
165 const MachineFunction
&MF
= *MI
.getParent()->getParent();
166 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
167 unsigned Opc
= MI
.getOpcode();
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())
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());
193 auto Mapping
= getValueMapping(getPartialMappingIdx(Ty
, false), 3);
194 return getInstructionMapping(DefaultMappingID
, 1, Mapping
, NumOperands
);
201 unsigned NumOperands
= MI
.getNumOperands();
202 SmallVector
<PartialMappingIdx
, 4> OpRegBankIdx(NumOperands
);
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
);
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());
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
);
226 case TargetOpcode::G_FCMP
: {
227 LLT Ty1
= MRI
.getType(MI
.getOperand(2).getReg());
228 LLT Ty2
= MRI
.getType(MI
.getOperand(3).getReg());
230 assert(Ty1
.getSizeInBits() == Ty2
.getSizeInBits() &&
231 "Mismatched operand sizes for G_FCMP");
233 unsigned Size
= Ty1
.getSizeInBits();
235 assert((Size
== 32 || Size
== 64) && "Unsupported size for G_FCMP");
237 auto FpRegBank
= getPartialMappingIdx(Ty1
, /* isFP */ true);
238 OpRegBankIdx
= {PMI_GPR8
,
239 /* Predicate */ PMI_None
, FpRegBank
, FpRegBank
};
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());
249 bool isFPTrunc
= (Ty0
.getSizeInBits() == 32 || Ty0
.getSizeInBits() == 64) &&
250 Ty1
.getSizeInBits() == 128 && Opc
== TargetOpcode::G_TRUNC
;
252 Ty0
.getSizeInBits() == 128 &&
253 (Ty1
.getSizeInBits() == 32 || Ty1
.getSizeInBits() == 64) &&
254 Opc
== TargetOpcode::G_ANYEXT
;
256 getInstrPartialMappingIdxs(MI
, MRI
, /* isFP */ isFPTrunc
|| isFPAnyExt
,
260 // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
261 getInstrPartialMappingIdxs(MI
, MRI
, /* isFP */ false, OpRegBankIdx
);
265 // Finally construct the computed mapping.
266 SmallVector
<const ValueMapping
*, 8> OpdsMapping(NumOperands
);
267 if (!getInstrValueMapping(MI
, OpRegBankIdx
, OpdsMapping
))
268 return getInvalidInstructionMapping();
270 return getInstructionMapping(DefaultMappingID
, /* Cost */ 1,
271 getOperandsMapping(OpdsMapping
), NumOperands
);
274 void X86RegisterBankInfo::applyMappingImpl(
275 MachineIRBuilder
&Builder
, const OperandsMapper
&OpdMapper
) const {
276 return applyDefaultMapping(OpdMapper
);
279 RegisterBankInfo::InstructionMappings
280 X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr
&MI
) const {
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();
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)
296 unsigned NumOperands
= MI
.getNumOperands();
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
);
302 // Finally construct the computed mapping.
303 SmallVector
<const ValueMapping
*, 8> OpdsMapping(NumOperands
);
304 if (!getInstrValueMapping(MI
, OpRegBankIdx
, OpdsMapping
))
307 const RegisterBankInfo::InstructionMapping
&Mapping
= getInstructionMapping(
308 /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping
), NumOperands
);
309 InstructionMappings AltMappings
;
310 AltMappings
.push_back(&Mapping
);
316 return RegisterBankInfo::getInstrAlternativeMappings(MI
);