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>
29using namespace llvm;
30
31cl::OptionCategory AsmParserCat("Options for -gen-asm-parser");
32cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer");
33
34static cl::opt<unsigned>
35 AsmParserNum("asmparsernum", cl::init(Val: 0),
36 cl::desc("Make -gen-asm-parser emit assembly parser #N"),
37 cl::cat(AsmParserCat));
38
39static cl::opt<unsigned>
40 AsmWriterNum("asmwriternum", cl::init(Val: 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.
46MVT::SimpleValueType llvm::getValueType(const Record *Rec) {
47 return (MVT::SimpleValueType)Rec->getValueAsInt(FieldName: "Value");
48}
49
50StringRef 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
63StringRef 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///
77std::string llvm::getQualifiedName(const Record *R) {
78 std::string Namespace;
79 if (R->getValue(Name: "Namespace"))
80 Namespace = std::string(R->getValueAsString(FieldName: "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///
88CodeGenTarget::CodeGenTarget(RecordKeeper &records)
89 : Records(records), CGH(records) {
90 std::vector<Record *> Targets = Records.getAllDerivedDefinitions(ClassName: "Target");
91 if (Targets.size() == 0)
92 PrintFatalError(Msg: "No 'Target' subclasses defined!");
93 if (Targets.size() != 1)
94 PrintFatalError(Msg: "Multiple subclasses of Target defined!");
95 TargetRec = Targets[0];
96 MacroFusions = Records.getAllDerivedDefinitions(ClassName: "Fusion");
97}
98
99CodeGenTarget::~CodeGenTarget() {}
100
101StringRef 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.
105StringRef 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
119StringRef CodeGenTarget::getRegNamespace() const {
120 auto &RegClasses = RegBank->getRegClasses();
121 return RegClasses.size() > 0 ? RegClasses.front().Namespace : "";
122}
123
124Record *CodeGenTarget::getInstructionSet() const {
125 return TargetRec->getValueAsDef(FieldName: "InstructionSet");
126}
127
128bool CodeGenTarget::getAllowRegisterRenaming() const {
129 return TargetRec->getValueAsInt(FieldName: "AllowRegisterRenaming");
130}
131
132/// getAsmParser - Return the AssemblyParser definition for this target.
133///
134Record *CodeGenTarget::getAsmParser() const {
135 std::vector<Record *> LI = TargetRec->getValueAsListOfDefs(FieldName: "AssemblyParsers");
136 if (AsmParserNum >= LI.size())
137 PrintFatalError(Msg: "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///
145Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
146 std::vector<Record *> LI =
147 TargetRec->getValueAsListOfDefs(FieldName: "AssemblyParserVariants");
148 if (i >= LI.size())
149 PrintFatalError(Msg: "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///
157unsigned CodeGenTarget::getAsmParserVariantCount() const {
158 std::vector<Record *> LI =
159 TargetRec->getValueAsListOfDefs(FieldName: "AssemblyParserVariants");
160 return LI.size();
161}
162
163/// getAsmWriter - Return the AssemblyWriter definition for this target.
164///
165Record *CodeGenTarget::getAsmWriter() const {
166 std::vector<Record *> LI = TargetRec->getValueAsListOfDefs(FieldName: "AssemblyWriters");
167 if (AsmWriterNum >= LI.size())
168 PrintFatalError(Msg: "Target does not have an AsmWriter #" +
169 Twine(AsmWriterNum) + "!");
170 return LI[AsmWriterNum];
171}
172
173CodeGenRegBank &CodeGenTarget::getRegBank() const {
174 if (!RegBank)
175 RegBank = std::make_unique<CodeGenRegBank>(args&: Records, args: getHwModes());
176 return *RegBank;
177}
178
179std::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(Range&: SubClassWithSubReg->VTs, Element: 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(x: 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(Range&: Candidates, C: [&](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
226void CodeGenTarget::ReadRegAltNameIndices() const {
227 RegAltNameIndices = Records.getAllDerivedDefinitions(ClassName: "RegAltNameIndex");
228 llvm::sort(C&: RegAltNameIndices, Comp: LessRecord());
229}
230
231/// getRegisterByName - If there is a register with the specific AsmName,
232/// return it.
233const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
234 return getRegBank().getRegistersByName().lookup(Key: Name);
235}
236
237const CodeGenRegisterClass &CodeGenTarget::getRegisterClass(Record *R) const {
238 return *getRegBank().getRegClass(R);
239}
240
241std::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(C&: Result, R&: InVTs);
248 }
249 }
250
251 // Remove duplicates.
252 llvm::sort(C&: Result);
253 Result.erase(first: llvm::unique(R&: Result), last: Result.end());
254 return Result;
255}
256
257void CodeGenTarget::ReadLegalValueTypes() const {
258 for (const auto &RC : getRegBank().getRegClasses())
259 llvm::append_range(C&: LegalValueTypes, R: RC.VTs);
260
261 // Remove duplicates.
262 llvm::sort(C&: LegalValueTypes);
263 LegalValueTypes.erase(CS: llvm::unique(R&: LegalValueTypes), CE: LegalValueTypes.end());
264}
265
266CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
267 if (!SchedModels)
268 SchedModels = std::make_unique<CodeGenSchedModels>(args&: Records, args: *this);
269 return *SchedModels;
270}
271
272void CodeGenTarget::ReadInstructions() const {
273 std::vector<Record *> Insts = Records.getAllDerivedDefinitions(ClassName: "Instruction");
274 if (Insts.size() <= 2)
275 PrintFatalError(Msg: "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>(args&: R);
280 if (Instructions[R]->isVariableLengthEncoding())
281 HasVariableLengthEncodings = true;
282 }
283}
284
285static 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(Val: Rec);
292 if (!Rec || I == Insts.end())
293 PrintFatalError(Msg: Twine("Could not find '") + Name + "' instruction!");
294 return I->second.get();
295}
296
297static const char *FixedInstrs[] = {
298#define HANDLE_TARGET_OPCODE(OPC) #OPC,
299#include "llvm/Support/TargetOpcodes.def"
300 nullptr};
301
302unsigned 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.
308void CodeGenTarget::ComputeInstrsByEnum() const {
309 const auto &Insts = getInstructions();
310 for (const char *const *p = FixedInstrs; *p; ++p) {
311 const CodeGenInstruction *Instr = GetInstByName(Name: *p, Insts, Records);
312 assert(Instr && "Missing target independent instruction");
313 assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
314 InstrsByEnum.push_back(x: 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(x: CGI);
324 if (CGI->TheDef->getValueAsBit(FieldName: "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 Start: InstrsByEnum.begin() + EndOfPredefines, End: InstrsByEnum.end(),
334 Comp: [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
335 const auto &D1 = *Rec1->TheDef;
336 const auto &D2 = *Rec2->TheDef;
337 return std::tuple(!D1.getValueAsBit(FieldName: "isPseudo"), D1.getName()) <
338 std::tuple(!D2.getValueAsBit(FieldName: "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///
350bool CodeGenTarget::isLittleEndianEncoding() const {
351 return getInstructionSet()->getValueAsBit(FieldName: "isLittleEndianEncoding");
352}
353
354/// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
355/// encodings, reverse the bit order of all instructions.
356void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
357 if (!isLittleEndianEncoding())
358 return;
359
360 std::vector<Record *> Insts =
361 Records.getAllDerivedDefinitions(ClassName: "InstructionEncoding");
362 for (Record *R : Insts) {
363 if (R->getValueAsString(FieldName: "Namespace") == "TargetOpcode" ||
364 R->getValueAsBit(FieldName: "isPseudo"))
365 continue;
366
367 BitsInit *BI = R->getValueAsBitsInit(FieldName: "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: bit);
376 Init *BitSwap = BI->getBit(Bit: 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(Bit: middle);
383 }
384
385 BitsInit *NewBI = BitsInit::get(RK&: Records, Range: NewBits);
386
387 // Update the bits in reversed order so that emitInstrOpBits will get the
388 // correct endianness.
389 R->getValue(Name: "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.
398bool CodeGenTarget::guessInstructionProperties() const {
399 return getInstructionSet()->getValueAsBit(FieldName: "guessInstructionProperties");
400}
401
402//===----------------------------------------------------------------------===//
403// ComplexPattern implementation
404//
405ComplexPattern::ComplexPattern(Record *R) {
406 Ty = R->getValueAsDef(FieldName: "Ty");
407 NumOperands = R->getValueAsInt(FieldName: "NumOperands");
408 SelectFunc = std::string(R->getValueAsString(FieldName: "SelectFunc"));
409 RootNodes = R->getValueAsListOfDefs(FieldName: "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(FieldName: "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(FieldName: "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(ErrorLoc: R->getLoc(), Msg: "Unsupported SD Node property '" +
446 PropList[i]->getName() +
447 "' on ComplexPattern '" + R->getName() +
448 "'!");
449 }
450}
451