LLVM 20.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"
19#include "llvm/Support/Debug.h"
20
21#define DEBUG_TYPE "ppc-reg-bank-info"
22
23#define GET_TARGET_REGBANK_IMPL
24#include "PPCGenRegisterBank.inc"
25
26// This file will be TableGen'ed at some point.
27#include "PPCGenRegisterBankInfo.def"
28
29using namespace llvm;
30
32
33const RegisterBank &
35 LLT Ty) const {
36 switch (RC.getID()) {
37 case PPC::VSFRCRegClassID:
38 case PPC::SPILLTOVSRRC_and_VSFRCRegClassID:
39 case PPC::SPILLTOVSRRC_and_VFRCRegClassID:
40 case PPC::SPILLTOVSRRC_and_F4RCRegClassID:
41 case PPC::F8RCRegClassID:
42 case PPC::VFRCRegClassID:
43 case PPC::VSSRCRegClassID:
44 case PPC::F4RCRegClassID:
45 return getRegBank(PPC::FPRRegBankID);
46 default:
48 }
49}
50
53 const unsigned Opc = MI.getOpcode();
54
55 // Try the default logic for non-generic instructions that are either copies
56 // or already have some operands assigned to banks.
57 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
60 if (Mapping.isValid())
61 return Mapping;
62 }
63
64 const MachineFunction &MF = *MI.getParent()->getParent();
66 const TargetSubtargetInfo &STI = MF.getSubtarget();
68
69 unsigned NumOperands = MI.getNumOperands();
70 const ValueMapping *OperandsMapping = nullptr;
71 unsigned Cost = 1;
72 unsigned MappingID = DefaultMappingID;
73
74 switch (Opc) {
75 // Arithmetic ops.
76 case TargetOpcode::G_ADD:
77 case TargetOpcode::G_SUB:
78 // Bitwise ops.
79 case TargetOpcode::G_AND:
80 case TargetOpcode::G_OR:
81 case TargetOpcode::G_XOR:
82 // Extension ops.
83 case TargetOpcode::G_SEXT:
84 case TargetOpcode::G_ZEXT:
85 case TargetOpcode::G_ANYEXT: {
86 assert(NumOperands <= 3 &&
87 "This code is for instructions with 3 or less operands");
88 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
89 unsigned Size = Ty.getSizeInBits();
90 switch (Size) {
91 case 128:
92 OperandsMapping = getValueMapping(PMI_VEC128);
93 break;
94 default:
95 OperandsMapping = getValueMapping(PMI_GPR64);
96 break;
97 }
98 break;
99 }
100 case TargetOpcode::G_FADD:
101 case TargetOpcode::G_FSUB:
102 case TargetOpcode::G_FMUL:
103 case TargetOpcode::G_FDIV: {
104 Register SrcReg = MI.getOperand(1).getReg();
105 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
106
107 assert((Size == 32 || Size == 64 || Size == 128) &&
108 "Unsupported floating point types!\n");
109 switch (Size) {
110 case 32:
111 OperandsMapping = getValueMapping(PMI_FPR32);
112 break;
113 case 64:
114 OperandsMapping = getValueMapping(PMI_FPR64);
115 break;
116 case 128:
117 OperandsMapping = getValueMapping(PMI_VEC128);
118 break;
119 }
120 break;
121 }
122 case TargetOpcode::G_FCMP: {
123 unsigned CmpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
124
125 OperandsMapping = getOperandsMapping(
126 {getValueMapping(PMI_CR), nullptr,
127 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64),
128 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64)});
129 break;
130 }
131 case TargetOpcode::G_CONSTANT:
132 OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
133 break;
134 case TargetOpcode::G_CONSTANT_POOL:
135 OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
136 break;
137 case TargetOpcode::G_FPTOUI:
138 case TargetOpcode::G_FPTOSI: {
139 Register SrcReg = MI.getOperand(1).getReg();
140 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
141
142 OperandsMapping = getOperandsMapping(
145 break;
146 }
147 case TargetOpcode::G_UITOFP:
148 case TargetOpcode::G_SITOFP: {
149 Register SrcReg = MI.getOperand(0).getReg();
150 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
151
152 OperandsMapping =
155 break;
156 }
157 case TargetOpcode::G_LOAD: {
158 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
159 // Check if that load feeds fp instructions.
160 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
161 [&](const MachineInstr &UseMI) {
162 // If we have at least one direct use in a FP instruction,
163 // assume this was a floating point load in the IR. If it was
164 // not, we would have had a bitcast before reaching that
165 // instruction.
166 //
167 // Int->FP conversion operations are also captured in
168 // onlyDefinesFP().
169 return onlyUsesFP(UseMI, MRI, TRI);
170 }))
171 OperandsMapping = getOperandsMapping(
174 else
175 OperandsMapping = getOperandsMapping(
178 break;
179 }
180 case TargetOpcode::G_STORE: {
181 // Check if the store is fed by fp instructions.
182 MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg());
183 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
184 if (onlyDefinesFP(*DefMI, MRI, TRI))
185 OperandsMapping = getOperandsMapping(
188 else
189 OperandsMapping = getOperandsMapping(
192 break;
193 }
194 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {
195 // FIXME: We have to check every operand in this MI and compute value
196 // mapping accordingly.
197 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
198 OperandsMapping = getOperandsMapping(OpdsMapping);
199 break;
200 }
201 case TargetOpcode::G_BITCAST: {
202 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
203 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
204 unsigned DstSize = DstTy.getSizeInBits();
205
206 bool DstIsGPR = !DstTy.isVector();
207 bool SrcIsGPR = !SrcTy.isVector();
208 // TODO: Currently, only vector and GPR register banks are handled.
209 // This needs to be extended to handle floating point register
210 // banks in the future.
211 const RegisterBank &DstRB = DstIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;
212 const RegisterBank &SrcRB = SrcIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;
213
215 MappingID, Cost, getCopyMapping(DstRB.getID(), SrcRB.getID(), DstSize),
216 NumOperands);
217 }
218 default:
220 }
221
222 return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands);
223}
224
225/// \returns true if a given intrinsic \p ID only uses and defines FPRs.
226static bool isFPIntrinsic(unsigned ID) {
227 // TODO: Add more intrinsics.
228 return false;
229}
230
231/// FIXME: this is copied from target AArch64. Needs some code refactor here to
232/// put this function in class RegisterBankInfo.
233bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
235 const TargetRegisterInfo &TRI,
236 unsigned Depth) const {
237 unsigned Op = MI.getOpcode();
238
239 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
240 if (isFPIntrinsic(GI->getIntrinsicID()))
241 return true;
242 }
243
244 // Do we have an explicit floating point instruction?
246 return true;
247
248 // No. Check if we have a copy-like instruction. If we do, then we could
249 // still be fed by floating point instructions.
250 if (Op != TargetOpcode::COPY && !MI.isPHI() &&
252 return false;
253
254 // Check if we already know the register bank.
255 auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);
256 if (RB == &PPC::FPRRegBank)
257 return true;
258 if (RB == &PPC::GPRRegBank)
259 return false;
260
261 // We don't know anything.
262 //
263 // If we have a phi, we may be able to infer that it will be assigned a FPR
264 // based off of its inputs.
265 if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
266 return false;
267
268 return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {
269 return Op.isReg() &&
270 onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
271 });
272}
273
274/// FIXME: this is copied from target AArch64. Needs some code refactor here to
275/// put this function in class RegisterBankInfo.
276bool PPCRegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
278 const TargetRegisterInfo &TRI,
279 unsigned Depth) const {
280 switch (MI.getOpcode()) {
281 case TargetOpcode::G_FPTOSI:
282 case TargetOpcode::G_FPTOUI:
283 case TargetOpcode::G_FCMP:
284 case TargetOpcode::G_LROUND:
285 case TargetOpcode::G_LLROUND:
286 return true;
287 default:
288 break;
289 }
290 return hasFPConstraints(MI, MRI, TRI, Depth);
291}
292
293/// FIXME: this is copied from target AArch64. Needs some code refactor here to
294/// put this function in class RegisterBankInfo.
295bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
297 const TargetRegisterInfo &TRI,
298 unsigned Depth) const {
299 switch (MI.getOpcode()) {
300 case TargetOpcode::G_SITOFP:
301 case TargetOpcode::G_UITOFP:
302 return true;
303 default:
304 break;
305 }
306 return hasFPConstraints(MI, MRI, TRI, Depth);
307}
308
311 // TODO Implement.
313}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool isFPIntrinsic(const MachineRegisterInfo &MRI, const MachineInstr &MI)
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:148
constexpr TypeSize getSizeInBits() const
Returns the total size of the type. Must only be called on sized types.
Definition: LowLevelType.h:193
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:69
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.
virtual const RegisterBank & getRegBankFromRegClass(const TargetRegisterClass &RC, LLT Ty) const
Get a register bank that covers RC.
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:1209
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.
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:1729
bool isPreISelGenericFloatingPointOpcode(unsigned Opc)
Returns whether opcode Opc is a pre-isel generic floating-point opcode, having only floating-point op...
Definition: Utils.cpp:1697
Helper struct that represents how a value is mapped through different register banks.