1 //===- X86RegisterBankInfo.cpp -----------------------------------*- C++ -*-==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 /// This file implements the targeting of the RegisterBankInfo class for X86.
11 /// \todo This should be generated by TableGen.
12 //===----------------------------------------------------------------------===//
14 #include "X86RegisterBankInfo.h"
15 #include "X86InstrInfo.h"
16 #include "llvm/CodeGen/GlobalISel/RegisterBank.h"
17 #include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
19 #include "llvm/CodeGen/TargetRegisterInfo.h"
21 #define GET_TARGET_REGBANK_IMPL
22 #include "X86GenRegisterBank.inc"
25 // This file will be TableGen'ed at some point.
26 #define GET_TARGET_REGBANK_INFO_IMPL
27 #include "X86GenRegisterBankInfo.def"
29 X86RegisterBankInfo::X86RegisterBankInfo(const TargetRegisterInfo
&TRI
)
30 : X86GenRegisterBankInfo() {
32 // validate RegBank initialization.
33 const RegisterBank
&RBGPR
= getRegBank(X86::GPRRegBankID
);
35 assert(&X86::GPRRegBank
== &RBGPR
&& "Incorrect RegBanks inizalization.");
37 // The GPR register bank is fully defined by all the registers in
38 // GR64 + its subclasses.
39 assert(RBGPR
.covers(*TRI
.getRegClass(X86::GR64RegClassID
)) &&
40 "Subclass not added?");
41 assert(RBGPR
.getSize() == 64 && "GPRs should hold up to 64-bit");
44 const RegisterBank
&X86RegisterBankInfo::getRegBankFromRegClass(
45 const TargetRegisterClass
&RC
) const {
47 if (X86::GR8RegClass
.hasSubClassEq(&RC
) ||
48 X86::GR16RegClass
.hasSubClassEq(&RC
) ||
49 X86::GR32RegClass
.hasSubClassEq(&RC
) ||
50 X86::GR64RegClass
.hasSubClassEq(&RC
))
51 return getRegBank(X86::GPRRegBankID
);
53 if (X86::FR32XRegClass
.hasSubClassEq(&RC
) ||
54 X86::FR64XRegClass
.hasSubClassEq(&RC
) ||
55 X86::VR128XRegClass
.hasSubClassEq(&RC
) ||
56 X86::VR256XRegClass
.hasSubClassEq(&RC
) ||
57 X86::VR512RegClass
.hasSubClassEq(&RC
))
58 return getRegBank(X86::VECRRegBankID
);
60 llvm_unreachable("Unsupported register kind yet.");
63 X86GenRegisterBankInfo::PartialMappingIdx
64 X86GenRegisterBankInfo::getPartialMappingIdx(const LLT
&Ty
, bool isFP
) {
65 if ((Ty
.isScalar() && !isFP
) || Ty
.isPointer()) {
66 switch (Ty
.getSizeInBits()) {
80 llvm_unreachable("Unsupported register size.");
82 } else if (Ty
.isScalar()) {
83 switch (Ty
.getSizeInBits()) {
91 llvm_unreachable("Unsupported register size.");
94 switch (Ty
.getSizeInBits()) {
102 llvm_unreachable("Unsupported register size.");
109 void X86RegisterBankInfo::getInstrPartialMappingIdxs(
110 const MachineInstr
&MI
, const MachineRegisterInfo
&MRI
, const bool isFP
,
111 SmallVectorImpl
<PartialMappingIdx
> &OpRegBankIdx
) {
113 unsigned NumOperands
= MI
.getNumOperands();
114 for (unsigned Idx
= 0; Idx
< NumOperands
; ++Idx
) {
115 auto &MO
= MI
.getOperand(Idx
);
117 OpRegBankIdx
[Idx
] = PMI_None
;
119 OpRegBankIdx
[Idx
] = getPartialMappingIdx(MRI
.getType(MO
.getReg()), isFP
);
123 bool X86RegisterBankInfo::getInstrValueMapping(
124 const MachineInstr
&MI
,
125 const SmallVectorImpl
<PartialMappingIdx
> &OpRegBankIdx
,
126 SmallVectorImpl
<const ValueMapping
*> &OpdsMapping
) {
128 unsigned NumOperands
= MI
.getNumOperands();
129 for (unsigned Idx
= 0; Idx
< NumOperands
; ++Idx
) {
130 if (!MI
.getOperand(Idx
).isReg())
133 auto Mapping
= getValueMapping(OpRegBankIdx
[Idx
], 1);
134 if (!Mapping
->isValid())
137 OpdsMapping
[Idx
] = Mapping
;
142 const RegisterBankInfo::InstructionMapping
&
143 X86RegisterBankInfo::getSameOperandsMapping(const MachineInstr
&MI
,
145 const MachineFunction
&MF
= *MI
.getParent()->getParent();
146 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
148 unsigned NumOperands
= MI
.getNumOperands();
149 LLT Ty
= MRI
.getType(MI
.getOperand(0).getReg());
151 if (NumOperands
!= 3 || (Ty
!= MRI
.getType(MI
.getOperand(1).getReg())) ||
152 (Ty
!= MRI
.getType(MI
.getOperand(2).getReg())))
153 llvm_unreachable("Unsupported operand mapping yet.");
155 auto Mapping
= getValueMapping(getPartialMappingIdx(Ty
, isFP
), 3);
156 return getInstructionMapping(DefaultMappingID
, 1, Mapping
, NumOperands
);
159 const RegisterBankInfo::InstructionMapping
&
160 X86RegisterBankInfo::getInstrMapping(const MachineInstr
&MI
) const {
161 const MachineFunction
&MF
= *MI
.getParent()->getParent();
162 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
163 auto Opc
= MI
.getOpcode();
165 // Try the default logic for non-generic instructions that are either copies
166 // or already have some operands assigned to banks.
167 if (!isPreISelGenericOpcode(Opc
) || Opc
== TargetOpcode::G_PHI
) {
168 const InstructionMapping
&Mapping
= getInstrMappingImpl(MI
);
169 if (Mapping
.isValid())
174 case TargetOpcode::G_ADD
:
175 case TargetOpcode::G_SUB
:
176 case TargetOpcode::G_MUL
:
177 case TargetOpcode::G_SHL
:
178 case TargetOpcode::G_LSHR
:
179 case TargetOpcode::G_ASHR
:
180 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);
192 unsigned NumOperands
= MI
.getNumOperands();
193 SmallVector
<PartialMappingIdx
, 4> OpRegBankIdx(NumOperands
);
196 case TargetOpcode::G_FPEXT
:
197 case TargetOpcode::G_FPTRUNC
:
198 case TargetOpcode::G_FCONSTANT
:
199 // Instruction having only floating-point operands (all scalars in VECRReg)
200 getInstrPartialMappingIdxs(MI
, MRI
, /* isFP */ true, OpRegBankIdx
);
202 case TargetOpcode::G_SITOFP
:
203 case TargetOpcode::G_FPTOSI
: {
204 // Some of the floating-point instructions have mixed GPR and FP operands:
205 // fine-tune the computed mapping.
206 auto &Op0
= MI
.getOperand(0);
207 auto &Op1
= MI
.getOperand(1);
208 const LLT Ty0
= MRI
.getType(Op0
.getReg());
209 const LLT Ty1
= MRI
.getType(Op1
.getReg());
211 bool FirstArgIsFP
= Opc
== TargetOpcode::G_SITOFP
;
212 bool SecondArgIsFP
= Opc
== TargetOpcode::G_FPTOSI
;
213 OpRegBankIdx
[0] = getPartialMappingIdx(Ty0
, /* isFP */ FirstArgIsFP
);
214 OpRegBankIdx
[1] = getPartialMappingIdx(Ty1
, /* isFP */ SecondArgIsFP
);
217 case TargetOpcode::G_FCMP
: {
218 LLT Ty1
= MRI
.getType(MI
.getOperand(2).getReg());
219 LLT Ty2
= MRI
.getType(MI
.getOperand(3).getReg());
221 assert(Ty1
.getSizeInBits() == Ty2
.getSizeInBits() &&
222 "Mismatched operand sizes for G_FCMP");
224 unsigned Size
= Ty1
.getSizeInBits();
226 assert((Size
== 32 || Size
== 64) && "Unsupported size for G_FCMP");
228 auto FpRegBank
= getPartialMappingIdx(Ty1
, /* isFP */ true);
229 OpRegBankIdx
= {PMI_GPR8
,
230 /* Predicate */ PMI_None
, FpRegBank
, FpRegBank
};
233 case TargetOpcode::G_TRUNC
:
234 case TargetOpcode::G_ANYEXT
: {
235 auto &Op0
= MI
.getOperand(0);
236 auto &Op1
= MI
.getOperand(1);
237 const LLT Ty0
= MRI
.getType(Op0
.getReg());
238 const LLT Ty1
= MRI
.getType(Op1
.getReg());
240 bool isFPTrunc
= (Ty0
.getSizeInBits() == 32 || Ty0
.getSizeInBits() == 64) &&
241 Ty1
.getSizeInBits() == 128 && Opc
== TargetOpcode::G_TRUNC
;
243 Ty0
.getSizeInBits() == 128 &&
244 (Ty1
.getSizeInBits() == 32 || Ty1
.getSizeInBits() == 64) &&
245 Opc
== TargetOpcode::G_ANYEXT
;
247 getInstrPartialMappingIdxs(MI
, MRI
, /* isFP */ isFPTrunc
|| isFPAnyExt
,
251 // Track the bank of each register, use NotFP mapping (all scalars in GPRs)
252 getInstrPartialMappingIdxs(MI
, MRI
, /* isFP */ false, OpRegBankIdx
);
256 // Finally construct the computed mapping.
257 SmallVector
<const ValueMapping
*, 8> OpdsMapping(NumOperands
);
258 if (!getInstrValueMapping(MI
, OpRegBankIdx
, OpdsMapping
))
259 return getInvalidInstructionMapping();
261 return getInstructionMapping(DefaultMappingID
, /* Cost */ 1,
262 getOperandsMapping(OpdsMapping
), NumOperands
);
265 void X86RegisterBankInfo::applyMappingImpl(
266 const OperandsMapper
&OpdMapper
) const {
267 return applyDefaultMapping(OpdMapper
);
270 RegisterBankInfo::InstructionMappings
271 X86RegisterBankInfo::getInstrAlternativeMappings(const MachineInstr
&MI
) const {
273 const MachineFunction
&MF
= *MI
.getParent()->getParent();
274 const TargetSubtargetInfo
&STI
= MF
.getSubtarget();
275 const TargetRegisterInfo
&TRI
= *STI
.getRegisterInfo();
276 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
278 switch (MI
.getOpcode()) {
279 case TargetOpcode::G_LOAD
:
280 case TargetOpcode::G_STORE
:
281 case TargetOpcode::G_IMPLICIT_DEF
: {
282 // we going to try to map 32/64 bit to PMI_FP32/PMI_FP64
283 unsigned Size
= getSizeInBits(MI
.getOperand(0).getReg(), MRI
, TRI
);
284 if (Size
!= 32 && Size
!= 64)
287 unsigned NumOperands
= MI
.getNumOperands();
289 // Track the bank of each register, use FP mapping (all scalars in VEC)
290 SmallVector
<PartialMappingIdx
, 4> OpRegBankIdx(NumOperands
);
291 getInstrPartialMappingIdxs(MI
, MRI
, /* isFP */ true, OpRegBankIdx
);
293 // Finally construct the computed mapping.
294 SmallVector
<const ValueMapping
*, 8> OpdsMapping(NumOperands
);
295 if (!getInstrValueMapping(MI
, OpRegBankIdx
, OpdsMapping
))
298 const RegisterBankInfo::InstructionMapping
&Mapping
= getInstructionMapping(
299 /*ID*/ 1, /*Cost*/ 1, getOperandsMapping(OpdsMapping
), NumOperands
);
300 InstructionMappings AltMappings
;
301 AltMappings
.push_back(&Mapping
);
307 return RegisterBankInfo::getInstrAlternativeMappings(MI
);