Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/PowerPC/GISel/PPCRegisterBankInfo.cpp
96382 views
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"
15
#include "llvm/CodeGen/GlobalISel/GenericMachineInstrs.h"
16
#include "llvm/CodeGen/GlobalISel/Utils.h"
17
#include "llvm/CodeGen/MachineFunction.h"
18
#include "llvm/CodeGen/MachineRegisterInfo.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
29
using namespace llvm;
30
31
PPCRegisterBankInfo::PPCRegisterBankInfo(const TargetRegisterInfo &TRI) {}
32
33
const RegisterBank &
34
PPCRegisterBankInfo::getRegBankFromRegClass(const TargetRegisterClass &RC,
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
69
const RegisterBankInfo::InstructionMapping &
70
PPCRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
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) {
76
const RegisterBankInfo::InstructionMapping &Mapping =
77
getInstrMappingImpl(MI);
78
if (Mapping.isValid())
79
return Mapping;
80
}
81
82
const MachineFunction &MF = *MI.getParent()->getParent();
83
const MachineRegisterInfo &MRI = MF.getRegInfo();
84
const TargetSubtargetInfo &STI = MF.getSubtarget();
85
const TargetRegisterInfo &TRI = *STI.getRegisterInfo();
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(
161
{getValueMapping(PMI_GPR64),
162
getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64)});
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 =
171
getOperandsMapping({getValueMapping(Size == 32 ? PMI_FPR32 : PMI_FPR64),
172
getValueMapping(PMI_GPR64)});
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(
190
{getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32),
191
getValueMapping(PMI_GPR64)});
192
else
193
OperandsMapping = getOperandsMapping(
194
{getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32),
195
getValueMapping(PMI_GPR64)});
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(
204
{getValueMapping(Size == 64 ? PMI_FPR64 : PMI_FPR32),
205
getValueMapping(PMI_GPR64)});
206
else
207
OperandsMapping = getOperandsMapping(
208
{getValueMapping(Size == 64 ? PMI_GPR64 : PMI_GPR32),
209
getValueMapping(PMI_GPR64)});
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
232
return getInstructionMapping(
233
MappingID, Cost, getCopyMapping(DstRB.getID(), SrcRB.getID(), DstSize),
234
NumOperands);
235
}
236
default:
237
return getInvalidInstructionMapping();
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.
244
static 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.
251
bool PPCRegisterBankInfo::hasFPConstraints(const MachineInstr &MI,
252
const MachineRegisterInfo &MRI,
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?
263
if (isPreISelGenericFloatingPointOpcode(Op))
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() &&
269
!isPreISelGenericOptimizationHint(Op))
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.
294
bool PPCRegisterBankInfo::onlyUsesFP(const MachineInstr &MI,
295
const MachineRegisterInfo &MRI,
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.
313
bool PPCRegisterBankInfo::onlyDefinesFP(const MachineInstr &MI,
314
const MachineRegisterInfo &MRI,
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
327
RegisterBankInfo::InstructionMappings
328
PPCRegisterBankInfo::getInstrAlternativeMappings(const MachineInstr &MI) const {
329
// TODO Implement.
330
return RegisterBankInfo::getInstrAlternativeMappings(MI);
331
}
332
333