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
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::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);
45 default:
47 }
48}
49
52 const unsigned Opc = MI.getOpcode();
53
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) {
59 if (Mapping.isValid())
60 return Mapping;
61 }
62
63 const MachineFunction &MF = *MI.getParent()->getParent();
65 const TargetSubtargetInfo &STI = MF.getSubtarget();
67
68 unsigned NumOperands = MI.getNumOperands();
69 const ValueMapping *OperandsMapping = nullptr;
70 unsigned Cost = 1;
71 unsigned MappingID = DefaultMappingID;
72
73 switch (Opc) {
74 // Arithmetic ops.
75 case TargetOpcode::G_ADD:
76 case TargetOpcode::G_SUB:
77 // Bitwise ops.
78 case TargetOpcode::G_AND:
79 case TargetOpcode::G_OR:
80 case TargetOpcode::G_XOR:
81 // Extension ops.
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();
89 switch (Size) {
90 case 128:
91 OperandsMapping = getValueMapping(PMI_VEC128);
92 break;
93 default:
94 OperandsMapping = getValueMapping(PMI_GPR64);
95 break;
96 }
97 break;
98 }
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);
105
106 assert((Size == 32 || Size == 64 || Size == 128) &&
107 "Unsupported floating point types!\n");
108 switch (Size) {
109 case 32:
110 OperandsMapping = getValueMapping(PMI_FPR32);
111 break;
112 case 64:
113 OperandsMapping = getValueMapping(PMI_FPR64);
114 break;
115 case 128:
116 OperandsMapping = getValueMapping(PMI_VEC128);
117 break;
118 }
119 break;
120 }
121 case TargetOpcode::G_FCMP: {
122 unsigned CmpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
123
124 OperandsMapping = getOperandsMapping(
125 {getValueMapping(PMI_CR), nullptr,
126 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64),
127 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64)});
128 break;
129 }
130 case TargetOpcode::G_CONSTANT:
131 OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
132 break;
133 case TargetOpcode::G_CONSTANT_POOL:
134 OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
135 break;
136 case TargetOpcode::G_FPTOUI:
137 case TargetOpcode::G_FPTOSI: {
138 Register SrcReg = MI.getOperand(1).getReg();
139 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
140
141 OperandsMapping = getOperandsMapping(
144 break;
145 }
146 case TargetOpcode::G_UITOFP:
147 case TargetOpcode::G_SITOFP: {
148 Register SrcReg = MI.getOperand(0).getReg();
149 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
150
151 OperandsMapping =
154 break;
155 }
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
164 // instruction.
165 //
166 // Int->FP conversion operations are also captured in
167 // onlyDefinesFP().
168 return onlyUsesFP(UseMI, MRI, TRI);
169 }))
170 OperandsMapping = getOperandsMapping(
173 else
174 OperandsMapping = getOperandsMapping(
177 break;
178 }
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(
187 else
188 OperandsMapping = getOperandsMapping(
191 break;
192 }
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);
198 break;
199 }
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();
204
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;
212
214 MappingID, Cost, getCopyMapping(DstRB.getID(), SrcRB.getID(), DstSize),
215 NumOperands);
216 }
217 default:
219 }
220
221 return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands);
222}
223
224/// \returns true if a given intrinsic \p ID only uses and defines FPRs.
225static bool isFPIntrinsic(unsigned ID) {
226 // TODO: Add more intrinsics.
227 return false;
228}
229
230/// FIXME: this is copied from target AArch64. Needs some code refactor here to
231/// put this function in class RegisterBankInfo.
232bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
234 const TargetRegisterInfo &TRI,
235 unsigned Depth) const {
236 unsigned Op = MI.getOpcode();
237
238 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
239 if (isFPIntrinsic(GI->getIntrinsicID()))
240 return true;
241 }
242
243 // Do we have an explicit floating point instruction?
245 return true;
246
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() &&
251 return false;
252
253 // Check if we already know the register bank.
254 auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);
255 if (RB == &PPC::FPRRegBank)
256 return true;
257 if (RB == &PPC::GPRRegBank)
258 return false;
259
260 // We don't know anything.
261 //
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)
265 return false;
266
267 return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {
268 return Op.isReg() &&
269 onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
270 });
271}
272
273/// FIXME: this is copied from target AArch64. Needs some code refactor here to
274/// put this function in class RegisterBankInfo.
275bool PPCRegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
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:
285 return true;
286 default:
287 break;
288 }
289 return hasFPConstraints(MI, MRI, TRI, Depth);
290}
291
292/// FIXME: this is copied from target AArch64. Needs some code refactor here to
293/// put this function in class RegisterBankInfo.
294bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
296 const TargetRegisterInfo &TRI,
297 unsigned Depth) const {
298 switch (MI.getOpcode()) {
299 case TargetOpcode::G_SITOFP:
300 case TargetOpcode::G_UITOFP:
301 return true;
302 default:
303 break;
304 }
305 return hasFPConstraints(MI, MRI, TRI, Depth);
306}
307
310 // TODO Implement.
312}
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:190
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:1196
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:1746
bool isPreISelGenericFloatingPointOpcode(unsigned Opc)
Returns whether opcode Opc is a pre-isel generic floating-point opcode, having only floating-point op...
Definition: Utils.cpp:1675
Helper struct that represents how a value is mapped through different register banks.