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/GlobalISel/RegisterBank.h"
16 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
17 #include "llvm/CodeGen/MachineRegisterInfo.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
)
29 : X86GenRegisterBankInfo() {
31 // validate RegBank initialization.
32 const RegisterBank
&RBGPR
= getRegBank(X86::GPRRegBankID
);
34 assert(&X86::GPRRegBank
== &RBGPR
&& "Incorrect RegBanks inizalization.");
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");
43 const RegisterBank
&X86RegisterBankInfo::getRegBankFromRegClass(
44 const TargetRegisterClass
&RC
) const {
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
);
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
);
61 llvm_unreachable("Unsupported register kind yet.");
64 X86GenRegisterBankInfo::PartialMappingIdx
65 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT
&Ty
, bool isFP
) {
66 if ((Ty
.isScalar() && !isFP
) || Ty
.isPointer()) {
67 switch (Ty
.getSizeInBits()) {
81 llvm_unreachable("Unsupported register size.");
83 } else if (Ty
.isScalar()) {
84 switch (Ty
.getSizeInBits()) {
92 llvm_unreachable("Unsupported register size.");
95 switch (Ty
.getSizeInBits()) {
103 llvm_unreachable("Unsupported register size.");
110 void X86RegisterBankInfo::getInstrPartialMappingIdxs(
111 const MachineInstr
&MI
, const MachineRegisterInfo
&MRI
, const bool isFP
,
112 SmallVectorImpl
<PartialMappingIdx
> &OpRegBankIdx
) {
114 unsigned NumOperands
= MI
.getNumOperands();
115 for (unsigned Idx
= 0; Idx
< NumOperands
; ++Idx
) {
116 auto &MO
= MI
.getOperand(Idx
);
118 OpRegBankIdx
[Idx
] = PMI_None
;
120 OpRegBankIdx
[Idx
] = getPartialMappingIdx(MRI
.getType(MO
.getReg()), isFP
);
124 bool X86RegisterBankInfo::getInstrValueMapping(
125 const MachineInstr
&MI
,
126 const SmallVectorImpl
<PartialMappingIdx
> &OpRegBankIdx
,
127 SmallVectorImpl
<const ValueMapping
*> &OpdsMapping
) {
129 unsigned NumOperands
= MI
.getNumOperands();
130 for (unsigned Idx
= 0; Idx
< NumOperands
; ++Idx
) {
131 if (!MI
.getOperand(Idx
).isReg())
134 auto Mapping
= getValueMapping(OpRegBankIdx
[Idx
], 1);
135 if (!Mapping
->isValid())
138 OpdsMapping
[Idx
] = Mapping
;
143 const RegisterBankInfo::InstructionMapping
&
144 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr
&MI
,
146 const MachineFunction
&MF
= *MI
.getParent()->getParent();
147 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
149 unsigned NumOperands
= MI
.getNumOperands();
150 LLT Ty
= MRI
.getType(MI
.getOperand(0).getReg());
152 if (NumOperands
!= 3 || (Ty
!= MRI
.getType(MI
.getOperand(1).getReg())) ||
153 (Ty
!= MRI
.getType(MI
.getOperand(2).getReg())))
154 llvm_unreachable("Unsupported operand mapping yet.");
156 auto Mapping
= getValueMapping(getPartialMappingIdx(Ty
, isFP
), 3);
157 return getInstructionMapping(DefaultMappingID
, 1, Mapping
, NumOperands
);
160 const RegisterBankInfo::InstructionMapping
&
161 X86RegisterBankInfo::getInstrMapping(const MachineInstr
&MI
) const {
162 const MachineFunction
&MF
= *MI
.getParent()->getParent();
163 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
164 unsigned Opc
= MI
.getOpcode();
166 // Try the default logic for non-generic instructions that are either copies
167 // or already have some operands assigned to banks.
168 if (!isPreISelGenericOpcode(Opc
) || Opc
== TargetOpcode::G_PHI
) {
169 const InstructionMapping
&Mapping
= getInstrMappingImpl(MI
);
170 if (Mapping
.isValid())
175 case TargetOpcode::G_ADD
:
176 case TargetOpcode::G_SUB
:
177 case TargetOpcode::G_MUL
:
178 return getSameOperandsMapping(MI
, false);
179 case TargetOpcode::G_FADD
:
180 case TargetOpcode::G_FSUB
:
181 case TargetOpcode::G_FMUL
:
182 case TargetOpcode::G_FDIV
:
183 return getSameOperandsMapping(MI
, true);
184 case TargetOpcode::G_SHL
:
185 case TargetOpcode::G_LSHR
:
186 case TargetOpcode::G_ASHR
: {
187 unsigned NumOperands
= MI
.getNumOperands();
188 LLT Ty
= MRI
.getType(MI
.getOperand(0).getReg());
190 auto Mapping
= getValueMapping(getPartialMappingIdx(Ty
, false), 3);
191 return getInstructionMapping(DefaultMappingID
, 1, Mapping
, NumOperands
);
198 unsigned NumOperands
= MI
.getNumOperands();
199 SmallVector
<PartialMappingIdx
, 4> OpRegBankIdx(NumOperands
);
202 case TargetOpcode::G_FPEXT
:
203 case TargetOpcode::G_FPTRUNC
:
204 case TargetOpcode::G_FCONSTANT
:
205 // Instruction having only floating-point operands (all scalars in VECRReg)
206 getInstrPartialMappingIdxs(MI
, MRI
, /* isFP */ true, OpRegBankIdx
);
208 case TargetOpcode::G_SITOFP
:
209 case TargetOpcode::G_FPTOSI
: {
210 // Some of the floating-point instructions have mixed GPR and FP operands:
211 // fine-tune the computed mapping.
212 auto &Op0
= MI
.getOperand(0);
213 auto &Op1
= MI
.getOperand(1);
214 const LLT Ty0
= MRI
.getType(Op0
.getReg());
215 const LLT Ty1
= MRI
.getType(Op1
.getReg());
217 bool FirstArgIsFP
= Opc
== TargetOpcode::G_SITOFP
;
218 bool SecondArgIsFP
= Opc
== TargetOpcode::G_FPTOSI
;
219 OpRegBankIdx
[0] = getPartialMappingIdx(Ty0
, /* isFP */ FirstArgIsFP
);
220 OpRegBankIdx
[1] = getPartialMappingIdx(Ty1
, /* isFP */ SecondArgIsFP
);
223 case TargetOpcode::G_FCMP
: {
224 LLT Ty1
= MRI
.getType(MI
.getOperand(2).getReg());
225 LLT Ty2
= MRI
.getType(MI
.getOperand(3).getReg());
227 assert(Ty1
.getSizeInBits() == Ty2
.getSizeInBits() &&
228 "Mismatched operand sizes for G_FCMP");
230 unsigned Size
= Ty1
.getSizeInBits();
232 assert((Size
== 32 || Size
== 64) && "Unsupported size for G_FCMP");
234 auto FpRegBank
= getPartialMappingIdx(Ty1
, /* isFP */ true);
235 OpRegBankIdx
= {PMI_GPR8
,
236 /* Predicate */ PMI_None
, FpRegBank
, FpRegBank
};
239 case TargetOpcode::G_TRUNC
:
240 case TargetOpcode::G_ANYEXT
: {
241 auto &Op0
= MI
.getOperand(0);
242 auto &Op1
= MI
.getOperand(1);
243 const LLT Ty0
= MRI
.getType(Op0
.getReg());
244 const LLT Ty1
= MRI
.getType(Op1
.getReg());
246 bool isFPTrunc
= (Ty0
.getSizeInBits() == 32 || Ty0
.getSizeInBits() == 64) &&
247 Ty1
.getSizeInBits() == 128 && Opc
== TargetOpcode::G_TRUNC
;
249 Ty0
.getSizeInBits() == 128 &&
250 (Ty1
.getSizeInBits() == 32 || Ty1
.getSizeInBits() == 64) &&
251 Opc
== TargetOpcode::G_ANYEXT
;
253 getInstrPartialMappingIdxs(MI
, MRI
, /* isFP */ isFPTrunc
|| isFPAnyExt
,
257 // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
258 getInstrPartialMappingIdxs(MI
, MRI
, /* isFP */ false, OpRegBankIdx
);
262 // Finally construct the computed mapping.
263 SmallVector
<const ValueMapping
*, 8> OpdsMapping(NumOperands
);
264 if (!getInstrValueMapping(MI
, OpRegBankIdx
, OpdsMapping
))
265 return getInvalidInstructionMapping();
267 return getInstructionMapping(DefaultMappingID
, /* Cost */ 1,
268 getOperandsMapping(OpdsMapping
), NumOperands
);
271 void X86RegisterBankInfo::applyMappingImpl(
272 const OperandsMapper
&OpdMapper
) const {
273 return applyDefaultMapping(OpdMapper
);
276 RegisterBankInfo::InstructionMappings
277 X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr
&MI
) const {
279 const MachineFunction
&MF
= *MI
.getParent()->getParent();
280 const TargetSubtargetInfo
&STI
= MF
.getSubtarget();
281 const TargetRegisterInfo
&TRI
= *STI
.getRegisterInfo();
282 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
284 switch (MI
.getOpcode()) {
285 case TargetOpcode::G_LOAD
:
286 case TargetOpcode::G_STORE
:
287 case TargetOpcode::G_IMPLICIT_DEF
: {
288 // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
289 unsigned Size
= getSizeInBits(MI
.getOperand(0).getReg(), MRI
, TRI
);
290 if (Size
!= 32 && Size
!= 64)
293 unsigned NumOperands
= MI
.getNumOperands();
295 // Track the bank of each register, use FP mapping (all scalars in VEC)
296 SmallVector
<PartialMappingIdx
, 4> OpRegBankIdx(NumOperands
);
297 getInstrPartialMappingIdxs(MI
, MRI
, /* isFP */ true, OpRegBankIdx
);
299 // Finally construct the computed mapping.
300 SmallVector
<const ValueMapping
*, 8> OpdsMapping(NumOperands
);
301 if (!getInstrValueMapping(MI
, OpRegBankIdx
, OpdsMapping
))
304 const RegisterBankInfo::InstructionMapping
&Mapping
= getInstructionMapping(
305 /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping
), NumOperands
);
306 InstructionMappings AltMappings
;
307 AltMappings
.push_back(&Mapping
);
313 return RegisterBankInfo::getInstrAlternativeMappings(MI
);