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