xref: /freebsd/contrib/llvm-project/llvm/utils/TableGen/Common/CodeGenTarget.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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.
getValueType(const Record * Rec)46 MVT::SimpleValueType llvm::getValueType(const Record *Rec) {
47   return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
48 }
49 
getName(MVT::SimpleValueType T)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 
getEnumName(MVT::SimpleValueType T)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 ///
getQualifiedName(const Record * R)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 ///
CodeGenTarget(RecordKeeper & records)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 
~CodeGenTarget()99 CodeGenTarget::~CodeGenTarget() {}
100 
getName() const101 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.
getInstNamespace() const105 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 
getRegNamespace() const119 StringRef CodeGenTarget::getRegNamespace() const {
120   auto &RegClasses = RegBank->getRegClasses();
121   return RegClasses.size() > 0 ? RegClasses.front().Namespace : "";
122 }
123 
getInstructionSet() const124 Record *CodeGenTarget::getInstructionSet() const {
125   return TargetRec->getValueAsDef("InstructionSet");
126 }
127 
getAllowRegisterRenaming() const128 bool CodeGenTarget::getAllowRegisterRenaming() const {
129   return TargetRec->getValueAsInt("AllowRegisterRenaming");
130 }
131 
132 /// getAsmParser - Return the AssemblyParser definition for this target.
133 ///
getAsmParser() const134 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 ///
getAsmParserVariant(unsigned i) const145 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 ///
getAsmParserVariantCount() const157 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 ///
getAsmWriter() const165 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 
getRegBank() const173 CodeGenRegBank &CodeGenTarget::getRegBank() const {
174   if (!RegBank)
175     RegBank = std::make_unique<CodeGenRegBank>(Records, getHwModes());
176   return *RegBank;
177 }
178 
getSuperRegForSubReg(const ValueTypeByHwMode & ValueTy,CodeGenRegBank & RegBank,const CodeGenSubRegIndex * SubIdx,bool MustBeAllocatable) const179 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 
ReadRegAltNameIndices() const226 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.
getRegisterByName(StringRef Name) const233 const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
234   return getRegBank().getRegistersByName().lookup(Name);
235 }
236 
getRegisterClass(Record * R) const237 const CodeGenRegisterClass &CodeGenTarget::getRegisterClass(Record *R) const {
238   return *getRegBank().getRegClass(R);
239 }
240 
getRegisterVTs(Record * R) const241 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 
ReadLegalValueTypes() const257 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 
getSchedModels() const266 CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
267   if (!SchedModels)
268     SchedModels = std::make_unique<CodeGenSchedModels>(Records, *this);
269   return *SchedModels;
270 }
271 
ReadInstructions() const272 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 
GetInstByName(const char * Name,const DenseMap<const Record *,std::unique_ptr<CodeGenInstruction>> & Insts,RecordKeeper & Records)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 
getNumFixedInstructions()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.
ComputeInstrsByEnum() const308 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 ///
isLittleEndianEncoding() const350 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.
reverseBitsForLittleEndianEncoding()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.
guessInstructionProperties() const398 bool CodeGenTarget::guessInstructionProperties() const {
399   return getInstructionSet()->getValueAsBit("guessInstructionProperties");
400 }
401 
402 //===----------------------------------------------------------------------===//
403 // ComplexPattern implementation
404 //
ComplexPattern(Record * R)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