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