1 //===- PPCRegisterBankInfo.cpp --------------------------------------------===//
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
11 //===----------------------------------------------------------------------===//
13 #include "PPCRegisterBankInfo.h"
14 #include "PPCRegisterInfo.h"
15 #include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
16 #include "llvm/CodeGen/GlobalISel/Utils.h"
17 #include "llvm/CodeGen/MachineFunction.h"
18 #include "llvm/CodeGen/MachineRegisterInfo.h"
20 #define DEBUG_TYPE "ppc-reg-bank-info"
22 #define GET_TARGET_REGBANK_IMPL
23 #include "PPCGenRegisterBank.inc"
25 // This file will be TableGen'ed at some point.
26 #include "PPCGenRegisterBankInfo.def"
30 PPCRegisterBankInfo::PPCRegisterBankInfo(const TargetRegisterInfo
&TRI
) {}
33 PPCRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass
&RC
,
36 case PPC::VSFRCRegClassID
:
37 case PPC::SPILLTOVSRRC_and_VSFRCRegClassID
:
38 case PPC::SPILLTOVSRRC_and_VFRCRegClassID
:
39 case PPC::SPILLTOVSRRC_and_F4RCRegClassID
:
40 case PPC::F8RCRegClassID
:
41 case PPC::VFRCRegClassID
:
42 case PPC::VSSRCRegClassID
:
43 case PPC::F4RCRegClassID
:
44 return getRegBank(PPC::FPRRegBankID
);
46 return PPCGenRegisterBankInfo::getRegBankFromRegClass(RC
, Ty
);
50 const RegisterBankInfo::InstructionMapping
&
51 PPCRegisterBankInfo::getInstrMapping(const MachineInstr
&MI
) const {
52 const unsigned Opc
= MI
.getOpcode();
54 // Try the default logic for non-generic instructions that are either copies
55 // or already have some operands assigned to banks.
56 if (!isPreISelGenericOpcode(Opc
) || Opc
== TargetOpcode::G_PHI
) {
57 const RegisterBankInfo::InstructionMapping
&Mapping
=
58 getInstrMappingImpl(MI
);
59 if (Mapping
.isValid())
63 const MachineFunction
&MF
= *MI
.getParent()->getParent();
64 const MachineRegisterInfo
&MRI
= MF
.getRegInfo();
65 const TargetSubtargetInfo
&STI
= MF
.getSubtarget();
66 const TargetRegisterInfo
&TRI
= *STI
.getRegisterInfo();
68 unsigned NumOperands
= MI
.getNumOperands();
69 const ValueMapping
*OperandsMapping
= nullptr;
71 unsigned MappingID
= DefaultMappingID
;
75 case TargetOpcode::G_ADD
:
76 case TargetOpcode::G_SUB
:
78 case TargetOpcode::G_AND
:
79 case TargetOpcode::G_OR
:
80 case TargetOpcode::G_XOR
:
82 case TargetOpcode::G_SEXT
:
83 case TargetOpcode::G_ZEXT
:
84 case TargetOpcode::G_ANYEXT
: {
85 assert(NumOperands
<= 3 &&
86 "This code is for instructions with 3 or less operands");
87 LLT Ty
= MRI
.getType(MI
.getOperand(0).getReg());
88 unsigned Size
= Ty
.getSizeInBits();
91 OperandsMapping
= getValueMapping(PMI_VEC128
);
94 OperandsMapping
= getValueMapping(PMI_GPR64
);
99 case TargetOpcode::G_FADD
:
100 case TargetOpcode::G_FSUB
:
101 case TargetOpcode::G_FMUL
:
102 case TargetOpcode::G_FDIV
: {
103 Register SrcReg
= MI
.getOperand(1).getReg();
104 unsigned Size
= getSizeInBits(SrcReg
, MRI
, TRI
);
106 assert((Size
== 32 || Size
== 64 || Size
== 128) &&
107 "Unsupported floating point types!\n");
110 OperandsMapping
= getValueMapping(PMI_FPR32
);
113 OperandsMapping
= getValueMapping(PMI_FPR64
);
116 OperandsMapping
= getValueMapping(PMI_VEC128
);
121 case TargetOpcode::G_FCMP
: {
122 unsigned CmpSize
= MRI
.getType(MI
.getOperand(2).getReg()).getSizeInBits();
124 OperandsMapping
= getOperandsMapping(
125 {getValueMapping(PMI_CR
), nullptr,
126 getValueMapping(CmpSize
== 32 ? PMI_FPR32
: PMI_FPR64
),
127 getValueMapping(CmpSize
== 32 ? PMI_FPR32
: PMI_FPR64
)});
130 case TargetOpcode::G_CONSTANT
:
131 OperandsMapping
= getOperandsMapping({getValueMapping(PMI_GPR64
), nullptr});
133 case TargetOpcode::G_CONSTANT_POOL
:
134 OperandsMapping
= getOperandsMapping({getValueMapping(PMI_GPR64
), nullptr});
136 case TargetOpcode::G_FPTOUI
:
137 case TargetOpcode::G_FPTOSI
: {
138 Register SrcReg
= MI
.getOperand(1).getReg();
139 unsigned Size
= getSizeInBits(SrcReg
, MRI
, TRI
);
141 OperandsMapping
= getOperandsMapping(
142 {getValueMapping(PMI_GPR64
),
143 getValueMapping(Size
== 32 ? PMI_FPR32
: PMI_FPR64
)});
146 case TargetOpcode::G_UITOFP
:
147 case TargetOpcode::G_SITOFP
: {
148 Register SrcReg
= MI
.getOperand(0).getReg();
149 unsigned Size
= getSizeInBits(SrcReg
, MRI
, TRI
);
152 getOperandsMapping({getValueMapping(Size
== 32 ? PMI_FPR32
: PMI_FPR64
),
153 getValueMapping(PMI_GPR64
)});
156 case TargetOpcode::G_LOAD
: {
157 unsigned Size
= MRI
.getType(MI
.getOperand(0).getReg()).getSizeInBits();
158 // Check if that load feeds fp instructions.
159 if (any_of(MRI
.use_nodbg_instructions(MI
.getOperand(0).getReg()),
160 [&](const MachineInstr
&UseMI
) {
161 // If we have at least one direct use in a FP instruction,
162 // assume this was a floating point load in the IR. If it was
163 // not, we would have had a bitcast before reaching that
166 // Int->FP conversion operations are also captured in
168 return onlyUsesFP(UseMI
, MRI
, TRI
);
170 OperandsMapping
= getOperandsMapping(
171 {getValueMapping(Size
== 64 ? PMI_FPR64
: PMI_FPR32
),
172 getValueMapping(PMI_GPR64
)});
174 OperandsMapping
= getOperandsMapping(
175 {getValueMapping(Size
== 64 ? PMI_GPR64
: PMI_GPR32
),
176 getValueMapping(PMI_GPR64
)});
179 case TargetOpcode::G_STORE
: {
180 // Check if the store is fed by fp instructions.
181 MachineInstr
*DefMI
= MRI
.getVRegDef(MI
.getOperand(0).getReg());
182 unsigned Size
= MRI
.getType(MI
.getOperand(0).getReg()).getSizeInBits();
183 if (onlyDefinesFP(*DefMI
, MRI
, TRI
))
184 OperandsMapping
= getOperandsMapping(
185 {getValueMapping(Size
== 64 ? PMI_FPR64
: PMI_FPR32
),
186 getValueMapping(PMI_GPR64
)});
188 OperandsMapping
= getOperandsMapping(
189 {getValueMapping(Size
== 64 ? PMI_GPR64
: PMI_GPR32
),
190 getValueMapping(PMI_GPR64
)});
193 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS
: {
194 // FIXME: We have to check every operand in this MI and compute value
195 // mapping accordingly.
196 SmallVector
<const ValueMapping
*, 8> OpdsMapping(NumOperands
);
197 OperandsMapping
= getOperandsMapping(OpdsMapping
);
200 case TargetOpcode::G_BITCAST
: {
201 LLT DstTy
= MRI
.getType(MI
.getOperand(0).getReg());
202 LLT SrcTy
= MRI
.getType(MI
.getOperand(1).getReg());
203 unsigned DstSize
= DstTy
.getSizeInBits();
205 bool DstIsGPR
= !DstTy
.isVector();
206 bool SrcIsGPR
= !SrcTy
.isVector();
207 // TODO: Currently, only vector and GPR register banks are handled.
208 // This needs to be extended to handle floating point register
209 // banks in the future.
210 const RegisterBank
&DstRB
= DstIsGPR
? PPC::GPRRegBank
: PPC::VECRegBank
;
211 const RegisterBank
&SrcRB
= SrcIsGPR
? PPC::GPRRegBank
: PPC::VECRegBank
;
213 return getInstructionMapping(
214 MappingID
, Cost
, getCopyMapping(DstRB
.getID(), SrcRB
.getID(), DstSize
),
218 return getInvalidInstructionMapping();
221 return getInstructionMapping(MappingID
, Cost
, OperandsMapping
, NumOperands
);
224 /// \returns true if a given intrinsic \p ID only uses and defines FPRs.
225 static bool isFPIntrinsic(unsigned ID
) {
226 // TODO: Add more intrinsics.
230 /// FIXME: this is copied from target AArch64. Needs some code refactor here to
231 /// put this function in class RegisterBankInfo.
232 bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr
&MI
,
233 const MachineRegisterInfo
&MRI
,
234 const TargetRegisterInfo
&TRI
,
235 unsigned Depth
) const {
236 unsigned Op
= MI
.getOpcode();
238 if (auto *GI
= dyn_cast
<GIntrinsic
>(&MI
)) {
239 if (isFPIntrinsic(GI
->getIntrinsicID()))
243 // Do we have an explicit floating point instruction?
244 if (isPreISelGenericFloatingPointOpcode(Op
))
247 // No. Check if we have a copy-like instruction. If we do, then we could
248 // still be fed by floating point instructions.
249 if (Op
!= TargetOpcode::COPY
&& !MI
.isPHI() &&
250 !isPreISelGenericOptimizationHint(Op
))
253 // Check if we already know the register bank.
254 auto *RB
= getRegBank(MI
.getOperand(0).getReg(), MRI
, TRI
);
255 if (RB
== &PPC::FPRRegBank
)
257 if (RB
== &PPC::GPRRegBank
)
260 // We don't know anything.
262 // If we have a phi, we may be able to infer that it will be assigned a FPR
263 // based off of its inputs.
264 if (!MI
.isPHI() || Depth
> MaxFPRSearchDepth
)
267 return any_of(MI
.explicit_uses(), [&](const MachineOperand
&Op
) {
269 onlyDefinesFP(*MRI
.getVRegDef(Op
.getReg()), MRI
, TRI
, Depth
+ 1);
273 /// FIXME: this is copied from target AArch64. Needs some code refactor here to
274 /// put this function in class RegisterBankInfo.
275 bool PPCRegisterBankInfo::onlyUsesFP(const MachineInstr
&MI
,
276 const MachineRegisterInfo
&MRI
,
277 const TargetRegisterInfo
&TRI
,
278 unsigned Depth
) const {
279 switch (MI
.getOpcode()) {
280 case TargetOpcode::G_FPTOSI
:
281 case TargetOpcode::G_FPTOUI
:
282 case TargetOpcode::G_FCMP
:
283 case TargetOpcode::G_LROUND
:
284 case TargetOpcode::G_LLROUND
:
289 return hasFPConstraints(MI
, MRI
, TRI
, Depth
);
292 /// FIXME: this is copied from target AArch64. Needs some code refactor here to
293 /// put this function in class RegisterBankInfo.
294 bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr
&MI
,
295 const MachineRegisterInfo
&MRI
,
296 const TargetRegisterInfo
&TRI
,
297 unsigned Depth
) const {
298 switch (MI
.getOpcode()) {
299 case TargetOpcode::G_SITOFP
:
300 case TargetOpcode::G_UITOFP
:
305 return hasFPConstraints(MI
, MRI
, TRI
, Depth
);
308 RegisterBankInfo::InstructionMappings
309 PPCRegisterBankInfo::getInstrAlternativeMappings(const MachineInstr
&MI
) const {
311 return RegisterBankInfo::getInstrAlternativeMappings(MI
);