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::CRRCRegClassID:
52 case PPC::CRBITRCRegClassID:
53 return getRegBank(PPC::CRRegBankID);
54 default:
55 llvm_unreachable("Unexpected register class");
56 }
57}
58
61 const unsigned Opc = MI.getOpcode();
62
63 // Try the default logic for non-generic instructions that are either copies
64 // or already have some operands assigned to banks.
65 if (!isPreISelGenericOpcode(Opc) || Opc == TargetOpcode::G_PHI) {
68 if (Mapping.isValid())
69 return Mapping;
70 }
71
72 const MachineFunction &MF = *MI.getParent()->getParent();
74 const TargetSubtargetInfo &STI = MF.getSubtarget();
76
77 unsigned NumOperands = MI.getNumOperands();
78 const ValueMapping *OperandsMapping = nullptr;
79 unsigned Cost = 1;
80 unsigned MappingID = DefaultMappingID;
81
82 switch (Opc) {
83 // Arithmetic ops.
84 case TargetOpcode::G_ADD:
85 case TargetOpcode::G_SUB:
86 // Bitwise ops.
87 case TargetOpcode::G_AND:
88 case TargetOpcode::G_OR:
89 case TargetOpcode::G_XOR:
90 // Extension ops.
91 case TargetOpcode::G_SEXT:
92 case TargetOpcode::G_ZEXT:
93 case TargetOpcode::G_ANYEXT:
94 assert(NumOperands <= 3 &&
95 "This code is for instructions with 3 or less operands");
96 OperandsMapping = getValueMapping(PMI_GPR64);
97 break;
98 case TargetOpcode::G_FADD:
99 case TargetOpcode::G_FSUB:
100 case TargetOpcode::G_FMUL:
101 case TargetOpcode::G_FDIV: {
102 Register SrcReg = MI.getOperand(1).getReg();
103 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
104
105 assert((Size == 32 || Size == 64) && "Unsupported floating point types!\n");
106 OperandsMapping = getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64);
107 break;
108 }
109 case TargetOpcode::G_FCMP: {
110 unsigned CmpSize = MRI.getType(MI.getOperand(2).getReg()).getSizeInBits();
111
112 OperandsMapping = getOperandsMapping(
113 {getValueMapping(PMI_CR), nullptr,
114 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64),
115 getValueMapping(CmpSize == 32 ? PMI_FPR32 : PMI_FPR64)});
116 break;
117 }
118 case TargetOpcode::G_CONSTANT:
119 OperandsMapping = getOperandsMapping({getValueMapping(PMI_GPR64), nullptr});
120 break;
121 case TargetOpcode::G_FPTOUI:
122 case TargetOpcode::G_FPTOSI: {
123 Register SrcReg = MI.getOperand(1).getReg();
124 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
125
126 OperandsMapping = getOperandsMapping(
129 break;
130 }
131 case TargetOpcode::G_UITOFP:
132 case TargetOpcode::G_SITOFP: {
133 Register SrcReg = MI.getOperand(0).getReg();
134 unsigned Size = getSizeInBits(SrcReg, MRI, TRI);
135
136 OperandsMapping =
139 break;
140 }
141 case TargetOpcode::G_LOAD: {
142 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
143 // Check if that load feeds fp instructions.
144 if (any_of(MRI.use_nodbg_instructions(MI.getOperand(0).getReg()),
145 [&](const MachineInstr &UseMI) {
146 // If we have at least one direct use in a FP instruction,
147 // assume this was a floating point load in the IR. If it was
148 // not, we would have had a bitcast before reaching that
149 // instruction.
150 //
151 // Int->FP conversion operations are also captured in
152 // onlyDefinesFP().
153 return onlyUsesFP(UseMI, MRI, TRI);
154 }))
155 OperandsMapping = getOperandsMapping(
158 else
159 OperandsMapping = getOperandsMapping(
162 break;
163 }
164 case TargetOpcode::G_STORE: {
165 // Check if the store is fed by fp instructions.
166 MachineInstr *DefMI = MRI.getVRegDef(MI.getOperand(0).getReg());
167 unsigned Size = MRI.getType(MI.getOperand(0).getReg()).getSizeInBits();
168 if (onlyDefinesFP(*DefMI, MRI, TRI))
169 OperandsMapping = getOperandsMapping(
172 else
173 OperandsMapping = getOperandsMapping(
176 break;
177 }
178 case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS: {
179 // FIXME: We have to check every operand in this MI and compute value
180 // mapping accordingly.
181 SmallVector<const ValueMapping *, 8> OpdsMapping(NumOperands);
182 OperandsMapping = getOperandsMapping(OpdsMapping);
183 break;
184 }
185 default:
187 }
188
189 return getInstructionMapping(MappingID, Cost, OperandsMapping, NumOperands);
190}
191
192/// Returns whether opcode \p Opc is a pre-isel generic floating-point opcode,
193/// having only floating-point operands.
194/// FIXME: this is copied from target AArch64. Needs some code refactor here to
195/// put this function in GlobalISel/Utils.cpp.
196static bool isPreISelGenericFloatingPointOpcode(unsigned Opc) {
197 switch (Opc) {
198 case TargetOpcode::G_FADD:
199 case TargetOpcode::G_FSUB:
200 case TargetOpcode::G_FMUL:
201 case TargetOpcode::G_FMA:
202 case TargetOpcode::G_FDIV:
203 case TargetOpcode::G_FCONSTANT:
204 case TargetOpcode::G_FPEXT:
205 case TargetOpcode::G_FPTRUNC:
206 case TargetOpcode::G_FCEIL:
207 case TargetOpcode::G_FFLOOR:
208 case TargetOpcode::G_FNEARBYINT:
209 case TargetOpcode::G_FNEG:
210 case TargetOpcode::G_FCOS:
211 case TargetOpcode::G_FSIN:
212 case TargetOpcode::G_FLOG10:
213 case TargetOpcode::G_FLOG:
214 case TargetOpcode::G_FLOG2:
215 case TargetOpcode::G_FSQRT:
216 case TargetOpcode::G_FABS:
217 case TargetOpcode::G_FEXP:
218 case TargetOpcode::G_FRINT:
219 case TargetOpcode::G_INTRINSIC_TRUNC:
220 case TargetOpcode::G_INTRINSIC_ROUND:
221 case TargetOpcode::G_FMAXNUM:
222 case TargetOpcode::G_FMINNUM:
223 case TargetOpcode::G_FMAXIMUM:
224 case TargetOpcode::G_FMINIMUM:
225 return true;
226 }
227 return false;
228}
229
230/// \returns true if a given intrinsic \p ID only uses and defines FPRs.
231static bool isFPIntrinsic(unsigned ID) {
232 // TODO: Add more intrinsics.
233 return false;
234}
235
236/// FIXME: this is copied from target AArch64. Needs some code refactor here to
237/// put this function in class RegisterBankInfo.
238bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
240 const TargetRegisterInfo &TRI,
241 unsigned Depth) const {
242 unsigned Op = MI.getOpcode();
243 if (Op == TargetOpcode::G_INTRINSIC && isFPIntrinsic(MI.getIntrinsicID()))
244 return true;
245
246 // Do we have an explicit floating point instruction?
248 return true;
249
250 // No. Check if we have a copy-like instruction. If we do, then we could
251 // still be fed by floating point instructions.
252 if (Op != TargetOpcode::COPY && !MI.isPHI() &&
254 return false;
255
256 // Check if we already know the register bank.
257 auto *RB = getRegBank(MI.getOperand(0).getReg(), MRI, TRI);
258 if (RB == &PPC::FPRRegBank)
259 return true;
260 if (RB == &PPC::GPRRegBank)
261 return false;
262
263 // We don't know anything.
264 //
265 // If we have a phi, we may be able to infer that it will be assigned a FPR
266 // based off of its inputs.
267 if (!MI.isPHI() || Depth > MaxFPRSearchDepth)
268 return false;
269
270 return any_of(MI.explicit_uses(), [&](const MachineOperand &Op) {
271 return Op.isReg() &&
272 onlyDefinesFP(*MRI.getVRegDef(Op.getReg()), MRI, TRI, Depth + 1);
273 });
274}
275
276/// FIXME: this is copied from target AArch64. Needs some code refactor here to
277/// put this function in class RegisterBankInfo.
278bool PPCRegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
280 const TargetRegisterInfo &TRI,
281 unsigned Depth) const {
282 switch (MI.getOpcode()) {
283 case TargetOpcode::G_FPTOSI:
284 case TargetOpcode::G_FPTOUI:
285 case TargetOpcode::G_FCMP:
286 case TargetOpcode::G_LROUND:
287 case TargetOpcode::G_LLROUND:
288 return true;
289 default:
290 break;
291 }
292 return hasFPConstraints(MI, MRI, TRI, Depth);
293}
294
295/// FIXME: this is copied from target AArch64. Needs some code refactor here to
296/// put this function in class RegisterBankInfo.
297bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
299 const TargetRegisterInfo &TRI,
300 unsigned Depth) const {
301 switch (MI.getOpcode()) {
302 case TargetOpcode::G_SITOFP:
303 case TargetOpcode::G_UITOFP:
304 return true;
305 default:
306 break;
307 }
308 return hasFPConstraints(MI, MRI, TRI, Depth);
309}
310
313 // TODO Implement.
315}
unsigned const MachineRegisterInfo * MRI
MachineInstrBuilder & UseMI
MachineInstrBuilder MachineInstrBuilder & DefMI
static bool isPreISelGenericFloatingPointOpcode(unsigned Opc)
Returns whether opcode Opc is a pre-isel generic floating-point opcode, having only floating-point op...
static bool isFPIntrinsic(unsigned ID)
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())
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 * 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
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:1742
Helper struct that represents how a value is mapped through different register banks.