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