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/DenseMap.h"
21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/Twine.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/TableGen/Error.h"
26#include "llvm/TableGen/Record.h"
27#include <tuple>
28using namespace llvm;
29
30static cl::OptionCategory AsmParserCat("Options for -gen-asm-parser");
31static cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer");
32
33static cl::opt<unsigned>
34 AsmParserNum("asmparsernum", cl::init(Val: 0),
35 cl::desc("Make -gen-asm-parser emit assembly parser #N"),
36 cl::cat(AsmParserCat));
37
38static cl::opt<unsigned>
39 AsmWriterNum("asmwriternum", cl::init(Val: 0),
40 cl::desc("Make -gen-asm-writer emit assembly writer #N"),
41 cl::cat(AsmWriterCat));
42
43/// Returns the MVT that the specified TableGen
44/// record corresponds to.
45MVT llvm::getValueType(const Record *Rec) {
46 static const DenseMap<StringRef, MVT> ValueTypes = {
47#define GET_VT_ATTR(Ty, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy) \
48 {#Ty, MVT::Ty},
49#include "llvm/CodeGen/GenVT.inc"
50#undef GET_VT_ATTR
51 {"INVALID_SIMPLE_VALUE_TYPE", MVT::INVALID_SIMPLE_VALUE_TYPE}};
52 return ValueTypes.lookup(Val: Rec->getValueAsString(FieldName: "LLVMName"));
53}
54
55StringRef llvm::getEnumName(MVT T) {
56 // clang-format off
57 switch (T.SimpleTy) {
58#define GET_VT_ATTR(Ty, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy) \
59 case MVT::Ty: return "MVT::" # Ty;
60#include "llvm/CodeGen/GenVT.inc"
61#undef GET_VT_ATTR
62 default: llvm_unreachable("ILLEGAL VALUE TYPE!");
63 }
64 // clang-format on
65}
66
67/// getQualifiedName - Return the name of the specified record, with a
68/// namespace qualifier if the record contains one.
69///
70std::string llvm::getQualifiedName(const Record *R) {
71 std::string Namespace;
72 if (R->getValue(Name: "Namespace"))
73 Namespace = R->getValueAsString(FieldName: "Namespace").str();
74 if (Namespace.empty())
75 return R->getName().str();
76 return Namespace + "::" + R->getName().str();
77}
78
79CodeGenTarget::CodeGenTarget(const RecordKeeper &records)
80 : Records(records), CGH(records), Intrinsics(records) {
81 ArrayRef<const Record *> Targets = Records.getAllDerivedDefinitions(ClassName: "Target");
82 if (Targets.size() == 0)
83 PrintFatalError(Msg: "No 'Target' subclasses defined!");
84 if (Targets.size() != 1)
85 PrintFatalError(Msg: "Multiple subclasses of Target defined!");
86 TargetRec = Targets[0];
87 MacroFusions = Records.getAllDerivedDefinitions(ClassName: "Fusion");
88}
89
90CodeGenTarget::~CodeGenTarget() = default;
91
92StringRef CodeGenTarget::getName() const { return TargetRec->getName(); }
93
94ArrayRef<const Record *> CodeGenTarget::getAllRegClassByHwMode() const {
95 if (!RegClassByHwModeList) {
96 RegClassByHwModeList.emplace();
97 for (const Record *R :
98 Records.getAllDerivedDefinitions(ClassName: "RegClassByHwMode")) {
99 if (!R->getValueAsListOfDefs(FieldName: "Objects").empty())
100 RegClassByHwModeList->push_back(x: R);
101 }
102 }
103
104 return *RegClassByHwModeList;
105}
106
107/// getInstNamespace - Find and return the target machine's instruction
108/// namespace. The namespace is cached because it is requested multiple times.
109StringRef CodeGenTarget::getInstNamespace() const {
110 if (InstNamespace.empty()) {
111 for (const CodeGenInstruction *Inst : getInstructions()) {
112 // We are not interested in the "TargetOpcode" namespace.
113 if (Inst->Namespace != "TargetOpcode") {
114 InstNamespace = Inst->Namespace;
115 break;
116 }
117 }
118 }
119
120 return InstNamespace;
121}
122
123StringRef CodeGenTarget::getRegNamespace() const {
124 auto &RegClasses = RegBank->getRegClasses();
125 return RegClasses.size() > 0 ? RegClasses.front().Namespace : "";
126}
127
128const Record *CodeGenTarget::getInstructionSet() const {
129 return TargetRec->getValueAsDef(FieldName: "InstructionSet");
130}
131
132bool CodeGenTarget::getAllowRegisterRenaming() const {
133 return TargetRec->getValueAsBit(FieldName: "AllowRegisterRenaming");
134}
135
136bool CodeGenTarget::getRegistersAreIntervals() const {
137 return TargetRec->getValueAsBit(FieldName: "RegistersAreIntervals");
138}
139
140/// getAsmParser - Return the AssemblyParser definition for this target.
141///
142const Record *CodeGenTarget::getAsmParser() const {
143 std::vector<const Record *> LI =
144 TargetRec->getValueAsListOfDefs(FieldName: "AssemblyParsers");
145 if (AsmParserNum >= LI.size())
146 PrintFatalError(Msg: "Target does not have an AsmParser #" +
147 Twine(AsmParserNum) + "!");
148 return LI[AsmParserNum];
149}
150
151/// getAsmParserVariant - Return the AssemblyParserVariant definition for
152/// this target.
153///
154const Record *CodeGenTarget::getAsmParserVariant(unsigned Idx) const {
155 std::vector<const Record *> LI =
156 TargetRec->getValueAsListOfDefs(FieldName: "AssemblyParserVariants");
157 if (Idx >= LI.size())
158 PrintFatalError(Msg: "Target does not have an AsmParserVariant #" + Twine(Idx) +
159 "!");
160 return LI[Idx];
161}
162
163/// getAsmParserVariantCount - Return the AssemblyParserVariant definition
164/// available for this target.
165///
166unsigned CodeGenTarget::getAsmParserVariantCount() const {
167 return TargetRec->getValueAsListOfDefs(FieldName: "AssemblyParserVariants").size();
168}
169
170/// getAsmWriter - Return the AssemblyWriter definition for this target.
171///
172const Record *CodeGenTarget::getAsmWriter() const {
173 std::vector<const Record *> LI =
174 TargetRec->getValueAsListOfDefs(FieldName: "AssemblyWriters");
175 if (AsmWriterNum >= LI.size())
176 PrintFatalError(Msg: "Target does not have an AsmWriter #" +
177 Twine(AsmWriterNum) + "!");
178 return LI[AsmWriterNum];
179}
180
181CodeGenRegBank &CodeGenTarget::getRegBank() const {
182 if (!RegBank)
183 RegBank = std::make_unique<CodeGenRegBank>(args: Records, args: getHwModes(),
184 args: getRegistersAreIntervals());
185 return *RegBank;
186}
187
188/// getRegisterByName - If there is a register with the specific AsmName,
189/// return it.
190const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
191 return getRegBank().getRegistersByName().lookup(Key: Name);
192}
193
194const CodeGenRegisterClass &
195CodeGenTarget::getRegisterClass(const Record *R, ArrayRef<SMLoc> Loc) const {
196 return *getRegBank().getRegClass(R, Loc);
197}
198
199std::vector<ValueTypeByHwMode>
200CodeGenTarget::getRegisterVTs(const Record *R) const {
201 const CodeGenRegister *Reg = getRegBank().getReg(R);
202 std::vector<ValueTypeByHwMode> Result;
203 for (const auto &RC : getRegBank().getRegClasses()) {
204 if (RC.contains(Reg)) {
205 ArrayRef<ValueTypeByHwMode> InVTs = RC.getValueTypes();
206 llvm::append_range(C&: Result, R&: InVTs);
207 }
208 }
209
210 // Remove duplicates.
211 llvm::sort(C&: Result);
212 Result.erase(first: llvm::unique(R&: Result), last: Result.end());
213 return Result;
214}
215
216void CodeGenTarget::ReadLegalValueTypes() const {
217 for (const auto &RC : getRegBank().getRegClasses())
218 llvm::append_range(C&: LegalValueTypes, R: RC.VTs);
219
220 // Remove duplicates.
221 llvm::sort(C&: LegalValueTypes);
222 LegalValueTypes.erase(CS: llvm::unique(R&: LegalValueTypes), CE: LegalValueTypes.end());
223}
224
225const Record *CodeGenTarget::getInitValueAsRegClass(
226 const Init *V, bool AssumeRegClassByHwModeIsDefault) const {
227 const Record *RegClassLike = getInitValueAsRegClassLike(V);
228 if (!RegClassLike || RegClassLike->isSubClassOf(Name: "RegisterClass"))
229 return RegClassLike;
230
231 // FIXME: We should figure out the hwmode and dispatch. But this interface
232 // is broken, we should be returning a register class. The expected uses
233 // will use the same RegBanks in all modes.
234 if (AssumeRegClassByHwModeIsDefault &&
235 RegClassLike->isSubClassOf(Name: "RegClassByHwMode")) {
236 const HwModeSelect &ModeSelect = getHwModes().getHwModeSelect(R: RegClassLike);
237 if (ModeSelect.Items.empty())
238 return nullptr;
239 return ModeSelect.Items.front().second;
240 }
241
242 return nullptr;
243}
244
245const Record *CodeGenTarget::getInitValueAsRegClassLike(const Init *V) const {
246 const DefInit *VDefInit = dyn_cast<DefInit>(Val: V);
247 if (!VDefInit)
248 return nullptr;
249 return getAsRegClassLike(V: VDefInit->getDef());
250}
251
252const Record *CodeGenTarget::getAsRegClassLike(const Record *Rec) const {
253 if (Rec->isSubClassOf(Name: "RegisterOperand"))
254 return Rec->getValueAsDef(FieldName: "RegClass");
255
256 return Rec->isSubClassOf(Name: "RegisterClassLike") ? Rec : nullptr;
257}
258
259CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
260 if (!SchedModels)
261 SchedModels = std::make_unique<CodeGenSchedModels>(args: Records, args: *this);
262 return *SchedModels;
263}
264
265void CodeGenTarget::ReadInstructions() const {
266 ArrayRef<const Record *> Insts =
267 Records.getAllDerivedDefinitions(ClassName: "Instruction");
268 if (Insts.size() <= 2)
269 PrintFatalError(Msg: "No 'Instruction' subclasses defined!");
270
271 // Parse the instructions defined in the .td file.
272 for (const Record *R : Insts) {
273 auto [II, _] =
274 InstructionMap.try_emplace(Key: R, Args: std::make_unique<CodeGenInstruction>(args&: R));
275 HasVariableLengthEncodings |= II->second->isVariableLengthEncoding();
276 }
277}
278
279static const CodeGenInstruction *GetInstByName(
280 StringRef Name,
281 const DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> &Insts,
282 const RecordKeeper &Records) {
283 const Record *Rec = Records.getDef(Name);
284
285 const auto I = Insts.find(Val: Rec);
286 if (!Rec || I == Insts.end())
287 PrintFatalError(Msg: "Could not find '" + Name + "' instruction!");
288 return I->second.get();
289}
290
291static const char *FixedInstrs[] = {
292#define HANDLE_TARGET_OPCODE(OPC) #OPC,
293#include "llvm/Support/TargetOpcodes.def"
294};
295
296unsigned CodeGenTarget::getNumFixedInstructions() {
297 return std::size(FixedInstrs);
298}
299
300/// Return all of the instructions defined by the target, ordered by
301/// their enum value.
302void CodeGenTarget::ComputeInstrsByEnum() const {
303 const auto &InstMap = getInstructionMap();
304 for (const char *Name : FixedInstrs) {
305 const CodeGenInstruction *Instr = GetInstByName(Name, Insts: InstMap, Records);
306 assert(Instr && "Missing target independent instruction");
307 assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
308 InstrsByEnum.push_back(x: Instr);
309 }
310 unsigned EndOfPredefines = InstrsByEnum.size();
311 assert(EndOfPredefines == getNumFixedInstructions() &&
312 "Missing generic opcode");
313
314 [[maybe_unused]] unsigned SkippedInsts = 0;
315
316 for (const auto &[_, CGIUp] : InstMap) {
317 const CodeGenInstruction *CGI = CGIUp.get();
318 if (CGI->Namespace != "TargetOpcode") {
319
320 if (CGI->TheDef->isSubClassOf(
321 Name: "TargetSpecializedStandardPseudoInstruction")) {
322 ++SkippedInsts;
323 continue;
324 }
325
326 InstrsByEnum.push_back(x: CGI);
327 NumPseudoInstructions += CGI->TheDef->getValueAsBit(FieldName: "isPseudo");
328 }
329 }
330
331 assert(InstrsByEnum.size() + SkippedInsts == InstMap.size() &&
332 "Missing predefined instr");
333
334 // All of the instructions are now in random order based on the map iteration.
335 llvm::sort(
336 Start: InstrsByEnum.begin() + EndOfPredefines, End: InstrsByEnum.end(),
337 Comp: [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
338 const Record &D1 = *Rec1->TheDef;
339 const Record &D2 = *Rec2->TheDef;
340 // Sort all pseudo instructions before non-pseudo ones, and sort by name
341 // within.
342 return std::tuple(!Rec1->isPseudo, D1.getName()) <
343 std::tuple(!Rec2->isPseudo, D2.getName());
344 });
345
346 // Assign an enum value to each instruction according to the sorted order.
347 for (const auto &[Idx, Inst] : enumerate(First&: InstrsByEnum))
348 Inst->EnumVal = Idx;
349}
350
351/// isLittleEndianEncoding - Return whether this target encodes its instruction
352/// in little-endian format, i.e. bits laid out in the order [0..n]
353///
354bool CodeGenTarget::isLittleEndianEncoding() const {
355 return getInstructionSet()->getValueAsBit(FieldName: "isLittleEndianEncoding");
356}
357
358/// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
359/// encodings, reverse the bit order of all instructions.
360void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
361 if (!isLittleEndianEncoding())
362 return;
363
364 for (const Record *R :
365 Records.getAllDerivedDefinitions(ClassName: "InstructionEncoding")) {
366 if (R->getValueAsString(FieldName: "Namespace") == "TargetOpcode" ||
367 R->getValueAsBit(FieldName: "isPseudo"))
368 continue;
369
370 const BitsInit *BI = R->getValueAsBitsInit(FieldName: "Inst");
371
372 unsigned numBits = BI->getNumBits();
373
374 SmallVector<const Init *, 16> NewBits(numBits);
375
376 for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
377 unsigned bitSwapIdx = numBits - bit - 1;
378 const Init *OrigBit = BI->getBit(Bit: bit);
379 const Init *BitSwap = BI->getBit(Bit: bitSwapIdx);
380 NewBits[bit] = BitSwap;
381 NewBits[bitSwapIdx] = OrigBit;
382 }
383 if (numBits % 2) {
384 unsigned middle = (numBits + 1) / 2;
385 NewBits[middle] = BI->getBit(Bit: middle);
386 }
387
388 RecordKeeper &MutableRC = const_cast<RecordKeeper &>(Records);
389 const BitsInit *NewBI = BitsInit::get(RK&: MutableRC, Range: NewBits);
390
391 // Update the bits in reversed order so that emitters will get the correct
392 // endianness.
393 // FIXME: Eliminate mutation of TG records by creating a helper function
394 // to reverse bits and maintain a cache instead of mutating records.
395 Record *MutableR = const_cast<Record *>(R);
396 MutableR->getValue(Name: "Inst")->setValue(NewBI);
397 }
398}
399
400/// guessInstructionProperties - Return true if it's OK to guess instruction
401/// properties instead of raising an error.
402///
403/// This is configurable as a temporary migration aid. It will eventually be
404/// permanently false.
405bool CodeGenTarget::guessInstructionProperties() const {
406 return getInstructionSet()->getValueAsBit(FieldName: "guessInstructionProperties");
407}
408
409//===----------------------------------------------------------------------===//
410// ComplexPattern implementation
411//
412ComplexPattern::ComplexPattern(const Record *R) {
413 Ty = R->getValueAsDef(FieldName: "Ty");
414 NumOperands = R->getValueAsInt(FieldName: "NumOperands");
415 SelectFunc = R->getValueAsString(FieldName: "SelectFunc").str();
416 RootNodes = R->getValueAsListOfDefs(FieldName: "RootNodes");
417
418 // FIXME: This is a hack to statically increase the priority of patterns which
419 // maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
420 // possible pattern match we'll need to dynamically calculate the complexity
421 // of all patterns a dag can potentially map to.
422 int64_t RawComplexity = R->getValueAsInt(FieldName: "Complexity");
423 if (RawComplexity == -1)
424 Complexity = NumOperands * 3;
425 else
426 Complexity = RawComplexity;
427
428 // FIXME: Why is this different from parseSDPatternOperatorProperties?
429 // Parse the properties.
430 Properties = 0;
431 for (const Record *Prop : R->getValueAsListOfDefs(FieldName: "Properties")) {
432 if (Prop->getName() == "SDNPHasChain") {
433 Properties |= 1 << SDNPHasChain;
434 } else if (Prop->getName() == "SDNPOptInGlue") {
435 Properties |= 1 << SDNPOptInGlue;
436 } else if (Prop->getName() == "SDNPMayStore") {
437 Properties |= 1 << SDNPMayStore;
438 } else if (Prop->getName() == "SDNPMayLoad") {
439 Properties |= 1 << SDNPMayLoad;
440 } else if (Prop->getName() == "SDNPSideEffect") {
441 Properties |= 1 << SDNPSideEffect;
442 } else if (Prop->getName() == "SDNPMemOperand") {
443 Properties |= 1 << SDNPMemOperand;
444 } else if (Prop->getName() == "SDNPVariadic") {
445 Properties |= 1 << SDNPVariadic;
446 } else {
447 PrintFatalError(ErrorLoc: R->getLoc(),
448 Msg: "Unsupported SD Node property '" + Prop->getName() +
449 "' on ComplexPattern '" + R->getName() + "'!");
450 }
451 }
452
453 WantsRoot = R->getValueAsBit(FieldName: "WantsRoot");
454 WantsParent = R->getValueAsBit(FieldName: "WantsParent");
455}
456