LLVM 17.0.0git
PPCRegisterBankInfo.cpp
Go to the documentation of this file.
1//===- PPCRegisterBankInfo.cpp --------------------------------------------===//
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
10/// PowerPC.
11//===----------------------------------------------------------------------===//
12
13#include "PPCRegisterBankInfo.h"
14#include "PPCRegisterInfo.h"
17#include "llvm/Support/Debug.h"
18
19#define DEBUG_TYPE "ppc-reg-bank-info"
20
21#define GET_TARGET_REGBANK_IMPL
22#include "PPCGenRegisterBank.inc"
23
24// This file will be TableGen'ed at some point.
25#include "PPCGenRegisterBankInfo.def"
26
27using namespace llvm;
28
30
31const RegisterBank &
33 LLT Ty) const {
34 switch (RC.getID()) {
35 case PPC::G8RCRegClassID:
36 case PPC::G8RC_NOX0RegClassID:
37 case PPC::G8RC_and_G8RC_NOX0RegClassID:
38 case PPC::GPRCRegClassID:
39 case PPC::GPRC_NOR0RegClassID:
40 case PPC::GPRC_and_GPRC_NOR0RegClassID:
41 return getRegBank(PPC::GPRRegBankID);
42 case PPC::VSFRCRegClassID:
43 case PPC::SPILLTOVSRRC_and_VSFRCRegClassID:
44 case PPC::SPILLTOVSRRC_and_VFRCRegClassID:
45 case PPC::SPILLTOVSRRC_and_F4RCRegClassID:
46 case PPC::F8RCRegClassID:
47 case PPC::VFRCRegClassID:
48 case PPC::VSSRCRegClassID:
49 case PPC::F4RCRegClassID:
50 return getRegBank(PPC::FPRRegBankID);
51 case PPC::VSRCRegClassID:
52 case PPC::VRRCRegClassID:
53 case PPC::VRRC_with_sub_64_in_SPILLTOVSRRCRegClassID:
54 case PPC::VSRC_with_sub_64_in_SPILLTOVSRRCRegClassID:
55 case PPC::SPILLTOVSRRCRegClassID:
56 case PPC::VSLRCRegClassID:
57 case PPC::VSLRC_with_sub_64_in_SPILLTOVSRRCRegClassID:
58 return getRegBank(PPC::VECRegBankID);
59 case PPC::CRRCRegClassID:
60 case PPC::CRBITRCRegClassID:
61 return getRegBank(PPC::CRRegBankID);
62 default:
63 llvm_unreachable("Unexpected register class");
64 }
65}
66
69 const unsigned Opc = MI.getOpcode();
70
71 // Try the default logic for non-generic instructions that are either copies
72 // or already have some operands assigned to banks.
73 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
76 if (Mapping.isValid())
77 return Mapping;
78 }
79
80 const MachineFunction &MF = *MI.getParent()->getParent();
82 const TargetSubtargetInfo &STI = MF.getSubtarget();
84
85 unsigned NumOperands = MI.getNumOperands();
86 const ValueMapping *OperandsMapping = nullptr;
87 unsigned Cost = 1;
88 unsigned MappingID = DefaultMappingID;
89
90 switch (Opc) {
91 // Arithmetic ops.
92 case TargetOpcode::G_ADD:
93 case TargetOpcode::G_SUB:
94 // Bitwise ops.
95 case TargetOpcode::G_AND:
96 case TargetOpcode::G_OR:
97 case TargetOpcode::G_XOR:
98 // Extension ops.
99 case TargetOpcode::G_SEXT:
100 case TargetOpcode::G_ZEXT:
101 case TargetOpcode::G_ANYEXT: {
102 assert(NumOperands <= 3 &&
103 "This code is for instructions with 3 or less operands");
104 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
105 unsigned Size = Ty.getSizeInBits();
106 switch (Size) {
107 case 128:
108 OperandsMapping = getValueMapping(PMI_VEC128);
109 break;
110 default:
111 OperandsMapping = getValueMapping(PMI_GPR64);
112 break;
113 }
114 break;
115 }
116 case TargetOpcode::G_FADD:
117 case TargetOpcode::G_FSUB:
118 case TargetOpcode::G_FMUL:
119 case TargetOpcode::G_FDIV: {
120 Register SrcReg = MI.getOperand(1).getReg();
121 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
122
123 assert((Size == 32 || Size == 64 || Size == 128) &&
124 "Unsupported floating point types!\n");
125 switch (Size) {
126 case 32:
127 OperandsMapping = getValueMapping(PMI_FPR32);
128 break;
129 case 64:
130 OperandsMapping = getValueMapping(PMI_FPR64);
131 break;
132 case 128:
133 OperandsMapping = getValueMapping(PMI_VEC128);
134 break;
135 }
136 break;
137 }
138 case TargetOpcode::G_FCMP: {
139 unsigned CmpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
140
141 OperandsMapping = getOperandsMapping(
142 {getValueMapping(PMI_CR), nullptr,
143 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64),
144 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64)});
145 break;
146 }
147 case TargetOpcode::G_CONSTANT:
148 OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
149 break;
150 case TargetOpcode::G_CONSTANT_POOL:
151 OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
152 break;
153 case TargetOpcode::G_FPTOUI:
154 case TargetOpcode::G_FPTOSI: {
155 Register SrcReg = MI.getOperand(1).getReg();
156 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
157
158 OperandsMapping = getOperandsMapping(
161 break;
162 }
163 case TargetOpcode::G_UITOFP:
164 case TargetOpcode::G_SITOFP: {
165 Register SrcReg = MI.getOperand(0).getReg();
166 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
167
168 OperandsMapping =
171 break;
172 }
173 case TargetOpcode::G_LOAD: {
174 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
175 // Check if that load feeds fp instructions.
176 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
177 [&](const MachineInstr &UseMI) {
178 // If we have at least one direct use in a FP instruction,
179 // assume this was a floating point load in the IR. If it was
180 // not, we would have had a bitcast before reaching that
181 // instruction.
182 //
183 // Int->FP conversion operations are also captured in
184 // onlyDefinesFP().
185 return onlyUsesFP(UseMI, MRI, TRI);
186 }))
187 OperandsMapping = getOperandsMapping(
190 else
191 OperandsMapping = getOperandsMapping(
194 break;
195 }
196 case TargetOpcode::G_STORE: {
197 // Check if the store is fed by fp instructions.
198 MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg());
199 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
200 if (onlyDefinesFP(*DefMI, MRI, TRI))
201 OperandsMapping = getOperandsMapping(
204 else
205 OperandsMapping = getOperandsMapping(
208 break;
209 }
210 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {
211 // FIXME: We have to check every operand in this MI and compute value
212 // mapping accordingly.
213 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
214 OperandsMapping = getOperandsMapping(OpdsMapping);
215 break;
216 }
217 case TargetOpcode::G_BITCAST: {
218 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
219 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
220 unsigned DstSize = DstTy.getSizeInBits();
221
222 bool DstIsGPR = !DstTy.isVector();
223 bool SrcIsGPR = !SrcTy.isVector();
224 // TODO: Currently, only vector and GPR register banks are handled.
225 // This needs to be extended to handle floating point register
226 // banks in the future.
227 const RegisterBank &DstRB = DstIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;
228 const RegisterBank &SrcRB = SrcIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;
229
231 MappingID, Cost, getCopyMapping(DstRB.getID(), SrcRB.getID(), DstSize),
232 NumOperands);
233 }
234 default:
236 }
237
238 return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands);
239}
240
241/// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode,
242/// having only floating-point operands.
243/// FIXME: this is copied from target AArch64. Needs some code refactor here to
244/// put this function in GlobalISel/Utils.cpp.
245static bool isPreISelGenericFloatingPointOpcode(unsigned Opc) {
246 switch (Opc) {
247 case TargetOpcode::G_FADD:
248 case TargetOpcode::G_FSUB:
249 case TargetOpcode::G_FMUL:
250 case TargetOpcode::G_FMA:
251 case TargetOpcode::G_FDIV:
252 case TargetOpcode::G_FCONSTANT:
253 case TargetOpcode::G_FPEXT:
254 case TargetOpcode::G_FPTRUNC:
255 case TargetOpcode::G_FCEIL:
256 case TargetOpcode::G_FFLOOR:
257 case TargetOpcode::G_FNEARBYINT:
258 case TargetOpcode::G_FNEG:
259 case TargetOpcode::G_FCOS:
260 case TargetOpcode::G_FSIN:
261 case TargetOpcode::G_FLOG10:
262 case TargetOpcode::G_FLOG:
263 case TargetOpcode::G_FLOG2:
264 case TargetOpcode::G_FSQRT:
265 case TargetOpcode::G_FABS:
266 case TargetOpcode::G_FEXP:
267 case TargetOpcode::G_FRINT:
268 case TargetOpcode::G_INTRINSIC_TRUNC:
269 case TargetOpcode::G_INTRINSIC_ROUND:
270 case TargetOpcode::G_FMAXNUM:
271 case TargetOpcode::G_FMINNUM:
272 case TargetOpcode::G_FMAXIMUM:
273 case TargetOpcode::G_FMINIMUM:
274 return true;
275 }
276 return false;
277}
278
279/// \returns true if a given intrinsic \p ID only uses and defines FPRs.
280static bool isFPIntrinsic(unsigned ID) {
281 // TODO: Add more intrinsics.
282 return false;
283}
284
285/// FIXME: this is copied from target AArch64. Needs some code refactor here to
286/// put this function in class RegisterBankInfo.
287bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
289 const TargetRegisterInfo &TRI,
290 unsigned Depth) const {
291 unsigned Op = MI.getOpcode();
292 if (Op == TargetOpcode::G_INTRINSIC && isFPIntrinsic(MI.getIntrinsicID()))
293 return true;
294
295 // Do we have an explicit floating point instruction?
297 return true;
298
299 // No. Check if we have a copy-like instruction. If we do, then we could
300 // still be fed by floating point instructions.
301 if (Op != TargetOpcode::COPY && !MI.isPHI() &&
303 return false;
304
305 // Check if we already know the register bank.
306 auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);
307 if (RB == &PPC::FPRRegBank)
308 return true;
309 if (RB == &PPC::GPRRegBank)
310 return false;
311
312 // We don't know anything.
313 //
314 // If we have a phi, we may be able to infer that it will be assigned a FPR
315 // based off of its inputs.
316 if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
317 return false;
318
319 return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {
320 return Op.isReg() &&
321 onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
322 });
323}
324
325/// FIXME: this is copied from target AArch64. Needs some code refactor here to
326/// put this function in class RegisterBankInfo.
327bool PPCRegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
329 const TargetRegisterInfo &TRI,
330 unsigned Depth) const {
331 switch (MI.getOpcode()) {
332 case TargetOpcode::G_FPTOSI:
333 case TargetOpcode::G_FPTOUI:
334 case TargetOpcode::G_FCMP:
335 case TargetOpcode::G_LROUND:
336 case TargetOpcode::G_LLROUND:
337 return true;
338 default:
339 break;
340 }
341 return hasFPConstraints(MI, MRI, TRI, Depth);
342}
343
344/// FIXME: this is copied from target AArch64. Needs some code refactor here to
345/// put this function in class RegisterBankInfo.
346bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
348 const TargetRegisterInfo &TRI,
349 unsigned Depth) const {
350 switch (MI.getOpcode()) {
351 case TargetOpcode::G_SITOFP:
352 case TargetOpcode::G_UITOFP:
353 return true;
354 default:
355 break;
356 }
357 return hasFPConstraints(MI, MRI, TRI, Depth);
358}
359
362 // TODO Implement.
364}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool isFPIntrinsic(const MachineRegisterInfo &MRI, const MachineInstr &MI)
static bool isPreISelGenericFloatingPointOpcode(unsigned Opc)
Returns whether opcode Opc is a pre-isel generic floating-point opcode, having only floating-point op...
uint64_t Size
IRTranslator LLVM IR MI
unsigned const TargetRegisterInfo * TRI
This file declares the targeting of the RegisterBankInfo class for PowerPC.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
constexpr bool isVector() const
Definition: LowLevelType.h:129
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:159
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
MachineOperand class - Representation of each machine instruction operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static const RegisterBankInfo::ValueMapping * getCopyMapping(unsigned DstBankID, unsigned SrcBankID, unsigned Size)
Get the pointer to the ValueMapping of the operands of a copy instruction from the SrcBankID register...
static const RegisterBankInfo::ValueMapping * getValueMapping(PartialMappingIdx RBIdx)
Get the pointer to the ValueMapping representing the RegisterBank at RBIdx.
const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT Ty) const override
Get a register bank that covers RC.
PPCRegisterBankInfo(const TargetRegisterInfo &TRI)
InstructionMappings getInstrAlternativeMappings(const MachineInstr &MI) const override
Get the alternative mappings for MI.
const InstructionMapping & getInstrMapping(const MachineInstr &MI) const override
Get the mapping of the different operands of MI on the register bank.
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.
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.
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 getID() const
Get the identifier of this register bank.
Definition: RegisterBank.h:47
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
unsigned getID() const
Return the register class ID number.
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.
#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
bool isPreISelGenericOptimizationHint(unsigned Opcode)
Definition: TargetOpcodes.h:42
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1826
Helper struct that represents how a value is mapped through different register banks.