Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/utils/TableGen/Common/CodeGenTarget.cpp
35290 views
1
//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
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
//
9
// This class wraps target description classes used by the various code
10
// generation TableGen backends. This makes it easier to access the data and
11
// provides a single place that needs to check it for validity. All of these
12
// classes abort on error conditions.
13
//
14
//===----------------------------------------------------------------------===//
15
16
#include "CodeGenTarget.h"
17
#include "CodeGenInstruction.h"
18
#include "CodeGenRegisters.h"
19
#include "CodeGenSchedule.h"
20
#include "llvm/ADT/STLExtras.h"
21
#include "llvm/ADT/Twine.h"
22
#include "llvm/Support/CommandLine.h"
23
#include "llvm/Support/ErrorHandling.h"
24
#include "llvm/TableGen/Error.h"
25
#include "llvm/TableGen/Record.h"
26
#include <algorithm>
27
#include <iterator>
28
#include <tuple>
29
using namespace llvm;
30
31
cl::OptionCategory AsmParserCat("Options for -gen-asm-parser");
32
cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer");
33
34
static cl::opt<unsigned>
35
AsmParserNum("asmparsernum", cl::init(0),
36
cl::desc("Make -gen-asm-parser emit assembly parser #N"),
37
cl::cat(AsmParserCat));
38
39
static cl::opt<unsigned>
40
AsmWriterNum("asmwriternum", cl::init(0),
41
cl::desc("Make -gen-asm-writer emit assembly writer #N"),
42
cl::cat(AsmWriterCat));
43
44
/// getValueType - Return the MVT::SimpleValueType that the specified TableGen
45
/// record corresponds to.
46
MVT::SimpleValueType llvm::getValueType(const Record *Rec) {
47
return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
48
}
49
50
StringRef llvm::getName(MVT::SimpleValueType T) {
51
switch (T) {
52
case MVT::Other:
53
return "UNKNOWN";
54
case MVT::iPTR:
55
return "TLI.getPointerTy()";
56
case MVT::iPTRAny:
57
return "TLI.getPointerTy()";
58
default:
59
return getEnumName(T);
60
}
61
}
62
63
StringRef llvm::getEnumName(MVT::SimpleValueType T) {
64
// clang-format off
65
switch (T) {
66
#define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, NElem, EltTy) \
67
case MVT::Ty: return "MVT::" # Ty;
68
#include "llvm/CodeGen/GenVT.inc"
69
default: llvm_unreachable("ILLEGAL VALUE TYPE!");
70
}
71
// clang-format on
72
}
73
74
/// getQualifiedName - Return the name of the specified record, with a
75
/// namespace qualifier if the record contains one.
76
///
77
std::string llvm::getQualifiedName(const Record *R) {
78
std::string Namespace;
79
if (R->getValue("Namespace"))
80
Namespace = std::string(R->getValueAsString("Namespace"));
81
if (Namespace.empty())
82
return std::string(R->getName());
83
return Namespace + "::" + R->getName().str();
84
}
85
86
/// getTarget - Return the current instance of the Target class.
87
///
88
CodeGenTarget::CodeGenTarget(RecordKeeper &records)
89
: Records(records), CGH(records) {
90
std::vector<Record *> Targets = Records.getAllDerivedDefinitions("Target");
91
if (Targets.size() == 0)
92
PrintFatalError("No 'Target' subclasses defined!");
93
if (Targets.size() != 1)
94
PrintFatalError("Multiple subclasses of Target defined!");
95
TargetRec = Targets[0];
96
MacroFusions = Records.getAllDerivedDefinitions("Fusion");
97
}
98
99
CodeGenTarget::~CodeGenTarget() {}
100
101
StringRef CodeGenTarget::getName() const { return TargetRec->getName(); }
102
103
/// getInstNamespace - Find and return the target machine's instruction
104
/// namespace. The namespace is cached because it is requested multiple times.
105
StringRef CodeGenTarget::getInstNamespace() const {
106
if (InstNamespace.empty()) {
107
for (const CodeGenInstruction *Inst : getInstructionsByEnumValue()) {
108
// We are not interested in the "TargetOpcode" namespace.
109
if (Inst->Namespace != "TargetOpcode") {
110
InstNamespace = Inst->Namespace;
111
break;
112
}
113
}
114
}
115
116
return InstNamespace;
117
}
118
119
StringRef CodeGenTarget::getRegNamespace() const {
120
auto &RegClasses = RegBank->getRegClasses();
121
return RegClasses.size() > 0 ? RegClasses.front().Namespace : "";
122
}
123
124
Record *CodeGenTarget::getInstructionSet() const {
125
return TargetRec->getValueAsDef("InstructionSet");
126
}
127
128
bool CodeGenTarget::getAllowRegisterRenaming() const {
129
return TargetRec->getValueAsInt("AllowRegisterRenaming");
130
}
131
132
/// getAsmParser - Return the AssemblyParser definition for this target.
133
///
134
Record *CodeGenTarget::getAsmParser() const {
135
std::vector<Record *> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
136
if (AsmParserNum >= LI.size())
137
PrintFatalError("Target does not have an AsmParser #" +
138
Twine(AsmParserNum) + "!");
139
return LI[AsmParserNum];
140
}
141
142
/// getAsmParserVariant - Return the AssemblyParserVariant definition for
143
/// this target.
144
///
145
Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
146
std::vector<Record *> LI =
147
TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
148
if (i >= LI.size())
149
PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) +
150
"!");
151
return LI[i];
152
}
153
154
/// getAsmParserVariantCount - Return the AssemblyParserVariant definition
155
/// available for this target.
156
///
157
unsigned CodeGenTarget::getAsmParserVariantCount() const {
158
std::vector<Record *> LI =
159
TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
160
return LI.size();
161
}
162
163
/// getAsmWriter - Return the AssemblyWriter definition for this target.
164
///
165
Record *CodeGenTarget::getAsmWriter() const {
166
std::vector<Record *> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
167
if (AsmWriterNum >= LI.size())
168
PrintFatalError("Target does not have an AsmWriter #" +
169
Twine(AsmWriterNum) + "!");
170
return LI[AsmWriterNum];
171
}
172
173
CodeGenRegBank &CodeGenTarget::getRegBank() const {
174
if (!RegBank)
175
RegBank = std::make_unique<CodeGenRegBank>(Records, getHwModes());
176
return *RegBank;
177
}
178
179
std::optional<CodeGenRegisterClass *> CodeGenTarget::getSuperRegForSubReg(
180
const ValueTypeByHwMode &ValueTy, CodeGenRegBank &RegBank,
181
const CodeGenSubRegIndex *SubIdx, bool MustBeAllocatable) const {
182
std::vector<CodeGenRegisterClass *> Candidates;
183
auto &RegClasses = RegBank.getRegClasses();
184
185
// Try to find a register class which supports ValueTy, and also contains
186
// SubIdx.
187
for (CodeGenRegisterClass &RC : RegClasses) {
188
// Is there a subclass of this class which contains this subregister index?
189
CodeGenRegisterClass *SubClassWithSubReg = RC.getSubClassWithSubReg(SubIdx);
190
if (!SubClassWithSubReg)
191
continue;
192
193
// We have a class. Check if it supports this value type.
194
if (!llvm::is_contained(SubClassWithSubReg->VTs, ValueTy))
195
continue;
196
197
// If necessary, check that it is allocatable.
198
if (MustBeAllocatable && !SubClassWithSubReg->Allocatable)
199
continue;
200
201
// We have a register class which supports both the value type and
202
// subregister index. Remember it.
203
Candidates.push_back(SubClassWithSubReg);
204
}
205
206
// If we didn't find anything, we're done.
207
if (Candidates.empty())
208
return std::nullopt;
209
210
// Find and return the largest of our candidate classes.
211
llvm::stable_sort(Candidates, [&](const CodeGenRegisterClass *A,
212
const CodeGenRegisterClass *B) {
213
if (A->getMembers().size() > B->getMembers().size())
214
return true;
215
216
if (A->getMembers().size() < B->getMembers().size())
217
return false;
218
219
// Order by name as a tie-breaker.
220
return StringRef(A->getName()) < B->getName();
221
});
222
223
return Candidates[0];
224
}
225
226
void CodeGenTarget::ReadRegAltNameIndices() const {
227
RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex");
228
llvm::sort(RegAltNameIndices, LessRecord());
229
}
230
231
/// getRegisterByName - If there is a register with the specific AsmName,
232
/// return it.
233
const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
234
return getRegBank().getRegistersByName().lookup(Name);
235
}
236
237
const CodeGenRegisterClass &CodeGenTarget::getRegisterClass(Record *R) const {
238
return *getRegBank().getRegClass(R);
239
}
240
241
std::vector<ValueTypeByHwMode> CodeGenTarget::getRegisterVTs(Record *R) const {
242
const CodeGenRegister *Reg = getRegBank().getReg(R);
243
std::vector<ValueTypeByHwMode> Result;
244
for (const auto &RC : getRegBank().getRegClasses()) {
245
if (RC.contains(Reg)) {
246
ArrayRef<ValueTypeByHwMode> InVTs = RC.getValueTypes();
247
llvm::append_range(Result, InVTs);
248
}
249
}
250
251
// Remove duplicates.
252
llvm::sort(Result);
253
Result.erase(llvm::unique(Result), Result.end());
254
return Result;
255
}
256
257
void CodeGenTarget::ReadLegalValueTypes() const {
258
for (const auto &RC : getRegBank().getRegClasses())
259
llvm::append_range(LegalValueTypes, RC.VTs);
260
261
// Remove duplicates.
262
llvm::sort(LegalValueTypes);
263
LegalValueTypes.erase(llvm::unique(LegalValueTypes), LegalValueTypes.end());
264
}
265
266
CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
267
if (!SchedModels)
268
SchedModels = std::make_unique<CodeGenSchedModels>(Records, *this);
269
return *SchedModels;
270
}
271
272
void CodeGenTarget::ReadInstructions() const {
273
std::vector<Record *> Insts = Records.getAllDerivedDefinitions("Instruction");
274
if (Insts.size() <= 2)
275
PrintFatalError("No 'Instruction' subclasses defined!");
276
277
// Parse the instructions defined in the .td file.
278
for (Record *R : Insts) {
279
Instructions[R] = std::make_unique<CodeGenInstruction>(R);
280
if (Instructions[R]->isVariableLengthEncoding())
281
HasVariableLengthEncodings = true;
282
}
283
}
284
285
static const CodeGenInstruction *GetInstByName(
286
const char *Name,
287
const DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> &Insts,
288
RecordKeeper &Records) {
289
const Record *Rec = Records.getDef(Name);
290
291
const auto I = Insts.find(Rec);
292
if (!Rec || I == Insts.end())
293
PrintFatalError(Twine("Could not find '") + Name + "' instruction!");
294
return I->second.get();
295
}
296
297
static const char *FixedInstrs[] = {
298
#define HANDLE_TARGET_OPCODE(OPC) #OPC,
299
#include "llvm/Support/TargetOpcodes.def"
300
nullptr};
301
302
unsigned CodeGenTarget::getNumFixedInstructions() {
303
return std::size(FixedInstrs) - 1;
304
}
305
306
/// Return all of the instructions defined by the target, ordered by
307
/// their enum value.
308
void CodeGenTarget::ComputeInstrsByEnum() const {
309
const auto &Insts = getInstructions();
310
for (const char *const *p = FixedInstrs; *p; ++p) {
311
const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
312
assert(Instr && "Missing target independent instruction");
313
assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
314
InstrsByEnum.push_back(Instr);
315
}
316
unsigned EndOfPredefines = InstrsByEnum.size();
317
assert(EndOfPredefines == getNumFixedInstructions() &&
318
"Missing generic opcode");
319
320
for (const auto &I : Insts) {
321
const CodeGenInstruction *CGI = I.second.get();
322
if (CGI->Namespace != "TargetOpcode") {
323
InstrsByEnum.push_back(CGI);
324
if (CGI->TheDef->getValueAsBit("isPseudo"))
325
++NumPseudoInstructions;
326
}
327
}
328
329
assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr");
330
331
// All of the instructions are now in random order based on the map iteration.
332
llvm::sort(
333
InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(),
334
[](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
335
const auto &D1 = *Rec1->TheDef;
336
const auto &D2 = *Rec2->TheDef;
337
return std::tuple(!D1.getValueAsBit("isPseudo"), D1.getName()) <
338
std::tuple(!D2.getValueAsBit("isPseudo"), D2.getName());
339
});
340
341
// Assign an enum value to each instruction according to the sorted order.
342
unsigned Num = 0;
343
for (const CodeGenInstruction *Inst : InstrsByEnum)
344
Inst->EnumVal = Num++;
345
}
346
347
/// isLittleEndianEncoding - Return whether this target encodes its instruction
348
/// in little-endian format, i.e. bits laid out in the order [0..n]
349
///
350
bool CodeGenTarget::isLittleEndianEncoding() const {
351
return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
352
}
353
354
/// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
355
/// encodings, reverse the bit order of all instructions.
356
void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
357
if (!isLittleEndianEncoding())
358
return;
359
360
std::vector<Record *> Insts =
361
Records.getAllDerivedDefinitions("InstructionEncoding");
362
for (Record *R : Insts) {
363
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
364
R->getValueAsBit("isPseudo"))
365
continue;
366
367
BitsInit *BI = R->getValueAsBitsInit("Inst");
368
369
unsigned numBits = BI->getNumBits();
370
371
SmallVector<Init *, 16> NewBits(numBits);
372
373
for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
374
unsigned bitSwapIdx = numBits - bit - 1;
375
Init *OrigBit = BI->getBit(bit);
376
Init *BitSwap = BI->getBit(bitSwapIdx);
377
NewBits[bit] = BitSwap;
378
NewBits[bitSwapIdx] = OrigBit;
379
}
380
if (numBits % 2) {
381
unsigned middle = (numBits + 1) / 2;
382
NewBits[middle] = BI->getBit(middle);
383
}
384
385
BitsInit *NewBI = BitsInit::get(Records, NewBits);
386
387
// Update the bits in reversed order so that emitInstrOpBits will get the
388
// correct endianness.
389
R->getValue("Inst")->setValue(NewBI);
390
}
391
}
392
393
/// guessInstructionProperties - Return true if it's OK to guess instruction
394
/// properties instead of raising an error.
395
///
396
/// This is configurable as a temporary migration aid. It will eventually be
397
/// permanently false.
398
bool CodeGenTarget::guessInstructionProperties() const {
399
return getInstructionSet()->getValueAsBit("guessInstructionProperties");
400
}
401
402
//===----------------------------------------------------------------------===//
403
// ComplexPattern implementation
404
//
405
ComplexPattern::ComplexPattern(Record *R) {
406
Ty = R->getValueAsDef("Ty");
407
NumOperands = R->getValueAsInt("NumOperands");
408
SelectFunc = std::string(R->getValueAsString("SelectFunc"));
409
RootNodes = R->getValueAsListOfDefs("RootNodes");
410
411
// FIXME: This is a hack to statically increase the priority of patterns which
412
// maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
413
// possible pattern match we'll need to dynamically calculate the complexity
414
// of all patterns a dag can potentially map to.
415
int64_t RawComplexity = R->getValueAsInt("Complexity");
416
if (RawComplexity == -1)
417
Complexity = NumOperands * 3;
418
else
419
Complexity = RawComplexity;
420
421
// FIXME: Why is this different from parseSDPatternOperatorProperties?
422
// Parse the properties.
423
Properties = 0;
424
std::vector<Record *> PropList = R->getValueAsListOfDefs("Properties");
425
for (unsigned i = 0, e = PropList.size(); i != e; ++i)
426
if (PropList[i]->getName() == "SDNPHasChain") {
427
Properties |= 1 << SDNPHasChain;
428
} else if (PropList[i]->getName() == "SDNPOptInGlue") {
429
Properties |= 1 << SDNPOptInGlue;
430
} else if (PropList[i]->getName() == "SDNPMayStore") {
431
Properties |= 1 << SDNPMayStore;
432
} else if (PropList[i]->getName() == "SDNPMayLoad") {
433
Properties |= 1 << SDNPMayLoad;
434
} else if (PropList[i]->getName() == "SDNPSideEffect") {
435
Properties |= 1 << SDNPSideEffect;
436
} else if (PropList[i]->getName() == "SDNPMemOperand") {
437
Properties |= 1 << SDNPMemOperand;
438
} else if (PropList[i]->getName() == "SDNPVariadic") {
439
Properties |= 1 << SDNPVariadic;
440
} else if (PropList[i]->getName() == "SDNPWantRoot") {
441
Properties |= 1 << SDNPWantRoot;
442
} else if (PropList[i]->getName() == "SDNPWantParent") {
443
Properties |= 1 << SDNPWantParent;
444
} else {
445
PrintFatalError(R->getLoc(), "Unsupported SD Node property '" +
446
PropList[i]->getName() +
447
"' on ComplexPattern '" + R->getName() +
448
"'!");
449
}
450
}
451
452