LLVM 19.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::G8RCRegClassID:
38 case PPC::G8RC_NOX0RegClassID:
39 case PPC::G8RC_and_G8RC_NOX0RegClassID:
40 case PPC::GPRCRegClassID:
41 case PPC::GPRC_NOR0RegClassID:
42 case PPC::GPRC_and_GPRC_NOR0RegClassID:
43 return getRegBank(PPC::GPRRegBankID);
44 case PPC::VSFRCRegClassID:
45 case PPC::SPILLTOVSRRC_and_VSFRCRegClassID:
46 case PPC::SPILLTOVSRRC_and_VFRCRegClassID:
47 case PPC::SPILLTOVSRRC_and_F4RCRegClassID:
48 case PPC::F8RCRegClassID:
49 case PPC::VFRCRegClassID:
50 case PPC::VSSRCRegClassID:
51 case PPC::F4RCRegClassID:
52 return getRegBank(PPC::FPRRegBankID);
53 case PPC::VSRCRegClassID:
54 case PPC::VRRCRegClassID:
55 case PPC::VRRC_with_sub_64_in_SPILLTOVSRRCRegClassID:
56 case PPC::VSRC_with_sub_64_in_SPILLTOVSRRCRegClassID:
57 case PPC::SPILLTOVSRRCRegClassID:
58 case PPC::VSLRCRegClassID:
59 case PPC::VSLRC_with_sub_64_in_SPILLTOVSRRCRegClassID:
60 return getRegBank(PPC::VECRegBankID);
61 case PPC::CRRCRegClassID:
62 case PPC::CRBITRCRegClassID:
63 return getRegBank(PPC::CRRegBankID);
64 default:
65 llvm_unreachable("Unexpected register class");
66 }
67}
68
71 const unsigned Opc = MI.getOpcode();
72
73 // Try the default logic for non-generic instructions that are either copies
74 // or already have some operands assigned to banks.
75 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
78 if (Mapping.isValid())
79 return Mapping;
80 }
81
82 const MachineFunction &MF = *MI.getParent()->getParent();
84 const TargetSubtargetInfo &STI = MF.getSubtarget();
86
87 unsigned NumOperands = MI.getNumOperands();
88 const ValueMapping *OperandsMapping = nullptr;
89 unsigned Cost = 1;
90 unsigned MappingID = DefaultMappingID;
91
92 switch (Opc) {
93 // Arithmetic ops.
94 case TargetOpcode::G_ADD:
95 case TargetOpcode::G_SUB:
96 // Bitwise ops.
97 case TargetOpcode::G_AND:
98 case TargetOpcode::G_OR:
99 case TargetOpcode::G_XOR:
100 // Extension ops.
101 case TargetOpcode::G_SEXT:
102 case TargetOpcode::G_ZEXT:
103 case TargetOpcode::G_ANYEXT: {
104 assert(NumOperands <= 3 &&
105 "This code is for instructions with 3 or less operands");
106 LLT Ty = MRI.getType(MI.getOperand(0).getReg());
107 unsigned Size = Ty.getSizeInBits();
108 switch (Size) {
109 case 128:
110 OperandsMapping = getValueMapping(PMI_VEC128);
111 break;
112 default:
113 OperandsMapping = getValueMapping(PMI_GPR64);
114 break;
115 }
116 break;
117 }
118 case TargetOpcode::G_FADD:
119 case TargetOpcode::G_FSUB:
120 case TargetOpcode::G_FMUL:
121 case TargetOpcode::G_FDIV: {
122 Register SrcReg = MI.getOperand(1).getReg();
123 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
124
125 assert((Size == 32 || Size == 64 || Size == 128) &&
126 "Unsupported floating point types!\n");
127 switch (Size) {
128 case 32:
129 OperandsMapping = getValueMapping(PMI_FPR32);
130 break;
131 case 64:
132 OperandsMapping = getValueMapping(PMI_FPR64);
133 break;
134 case 128:
135 OperandsMapping = getValueMapping(PMI_VEC128);
136 break;
137 }
138 break;
139 }
140 case TargetOpcode::G_FCMP: {
141 unsigned CmpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
142
143 OperandsMapping = getOperandsMapping(
144 {getValueMapping(PMI_CR), nullptr,
145 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64),
146 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64)});
147 break;
148 }
149 case TargetOpcode::G_CONSTANT:
150 OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
151 break;
152 case TargetOpcode::G_CONSTANT_POOL:
153 OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
154 break;
155 case TargetOpcode::G_FPTOUI:
156 case TargetOpcode::G_FPTOSI: {
157 Register SrcReg = MI.getOperand(1).getReg();
158 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
159
160 OperandsMapping = getOperandsMapping(
163 break;
164 }
165 case TargetOpcode::G_UITOFP:
166 case TargetOpcode::G_SITOFP: {
167 Register SrcReg = MI.getOperand(0).getReg();
168 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
169
170 OperandsMapping =
173 break;
174 }
175 case TargetOpcode::G_LOAD: {
176 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
177 // Check if that load feeds fp instructions.
178 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
179 [&](const MachineInstr &UseMI) {
180 // If we have at least one direct use in a FP instruction,
181 // assume this was a floating point load in the IR. If it was
182 // not, we would have had a bitcast before reaching that
183 // instruction.
184 //
185 // Int->FP conversion operations are also captured in
186 // onlyDefinesFP().
187 return onlyUsesFP(UseMI, MRI, TRI);
188 }))
189 OperandsMapping = getOperandsMapping(
192 else
193 OperandsMapping = getOperandsMapping(
196 break;
197 }
198 case TargetOpcode::G_STORE: {
199 // Check if the store is fed by fp instructions.
200 MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg());
201 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
202 if (onlyDefinesFP(*DefMI, MRI, TRI))
203 OperandsMapping = getOperandsMapping(
206 else
207 OperandsMapping = getOperandsMapping(
210 break;
211 }
212 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {
213 // FIXME: We have to check every operand in this MI and compute value
214 // mapping accordingly.
215 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
216 OperandsMapping = getOperandsMapping(OpdsMapping);
217 break;
218 }
219 case TargetOpcode::G_BITCAST: {
220 LLT DstTy = MRI.getType(MI.getOperand(0).getReg());
221 LLT SrcTy = MRI.getType(MI.getOperand(1).getReg());
222 unsigned DstSize = DstTy.getSizeInBits();
223
224 bool DstIsGPR = !DstTy.isVector();
225 bool SrcIsGPR = !SrcTy.isVector();
226 // TODO: Currently, only vector and GPR register banks are handled.
227 // This needs to be extended to handle floating point register
228 // banks in the future.
229 const RegisterBank &DstRB = DstIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;
230 const RegisterBank &SrcRB = SrcIsGPR ? PPC::GPRRegBank : PPC::VECRegBank;
231
233 MappingID, Cost, getCopyMapping(DstRB.getID(), SrcRB.getID(), DstSize),
234 NumOperands);
235 }
236 default:
238 }
239
240 return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands);
241}
242
243/// \returns true if a given intrinsic \p ID only uses and defines FPRs.
244static bool isFPIntrinsic(unsigned ID) {
245 // TODO: Add more intrinsics.
246 return false;
247}
248
249/// FIXME: this is copied from target AArch64. Needs some code refactor here to
250/// put this function in class RegisterBankInfo.
251bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
253 const TargetRegisterInfo &TRI,
254 unsigned Depth) const {
255 unsigned Op = MI.getOpcode();
256
257 if (auto *GI = dyn_cast<GIntrinsic>(&MI)) {
258 if (isFPIntrinsic(GI->getIntrinsicID()))
259 return true;
260 }
261
262 // Do we have an explicit floating point instruction?
264 return true;
265
266 // No. Check if we have a copy-like instruction. If we do, then we could
267 // still be fed by floating point instructions.
268 if (Op != TargetOpcode::COPY && !MI.isPHI() &&
270 return false;
271
272 // Check if we already know the register bank.
273 auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);
274 if (RB == &PPC::FPRRegBank)
275 return true;
276 if (RB == &PPC::GPRRegBank)
277 return false;
278
279 // We don't know anything.
280 //
281 // If we have a phi, we may be able to infer that it will be assigned a FPR
282 // based off of its inputs.
283 if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
284 return false;
285
286 return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {
287 return Op.isReg() &&
288 onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
289 });
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::onlyUsesFP(const MachineInstr &MI,
296 const TargetRegisterInfo &TRI,
297 unsigned Depth) const {
298 switch (MI.getOpcode()) {
299 case TargetOpcode::G_FPTOSI:
300 case TargetOpcode::G_FPTOUI:
301 case TargetOpcode::G_FCMP:
302 case TargetOpcode::G_LROUND:
303 case TargetOpcode::G_LLROUND:
304 return true;
305 default:
306 break;
307 }
308 return hasFPConstraints(MI, MRI, TRI, Depth);
309}
310
311/// FIXME: this is copied from target AArch64. Needs some code refactor here to
312/// put this function in class RegisterBankInfo.
313bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
315 const TargetRegisterInfo &TRI,
316 unsigned Depth) const {
317 switch (MI.getOpcode()) {
318 case TargetOpcode::G_SITOFP:
319 case TargetOpcode::G_UITOFP:
320 return true;
321 default:
322 break;
323 }
324 return hasFPConstraints(MI, MRI, TRI, Depth);
325}
326
329 // TODO Implement.
331}
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.
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.
#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: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:1669
Helper struct that represents how a value is mapped through different register banks.