xref: /llvm-project/llvm/utils/TableGen/Common/CodeGenTarget.cpp (revision 73eecb70c2abb1c6149647ec213cb9312c398569)
1fa3d789dSPierre van Houtryve //===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
2fa3d789dSPierre van Houtryve //
3fa3d789dSPierre van Houtryve // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fa3d789dSPierre van Houtryve // See https://llvm.org/LICENSE.txt for license information.
5fa3d789dSPierre van Houtryve // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fa3d789dSPierre van Houtryve //
7fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===//
8fa3d789dSPierre van Houtryve //
9fa3d789dSPierre van Houtryve // This class wraps target description classes used by the various code
10fa3d789dSPierre van Houtryve // generation TableGen backends.  This makes it easier to access the data and
11fa3d789dSPierre van Houtryve // provides a single place that needs to check it for validity.  All of these
12fa3d789dSPierre van Houtryve // classes abort on error conditions.
13fa3d789dSPierre van Houtryve //
14fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===//
15fa3d789dSPierre van Houtryve 
16fa3d789dSPierre van Houtryve #include "CodeGenTarget.h"
17fa3d789dSPierre van Houtryve #include "CodeGenInstruction.h"
18fa3d789dSPierre van Houtryve #include "CodeGenRegisters.h"
19fa3d789dSPierre van Houtryve #include "CodeGenSchedule.h"
20fa3d789dSPierre van Houtryve #include "llvm/ADT/STLExtras.h"
21fa3d789dSPierre van Houtryve #include "llvm/ADT/Twine.h"
22fa3d789dSPierre van Houtryve #include "llvm/Support/CommandLine.h"
23fa3d789dSPierre van Houtryve #include "llvm/Support/ErrorHandling.h"
24fa3d789dSPierre van Houtryve #include "llvm/TableGen/Error.h"
25fa3d789dSPierre van Houtryve #include "llvm/TableGen/Record.h"
26fa3d789dSPierre van Houtryve #include <algorithm>
27fa3d789dSPierre van Houtryve #include <iterator>
28fa3d789dSPierre van Houtryve #include <tuple>
29fa3d789dSPierre van Houtryve using namespace llvm;
30fa3d789dSPierre van Houtryve 
31fa3d789dSPierre van Houtryve cl::OptionCategory AsmParserCat("Options for -gen-asm-parser");
32fa3d789dSPierre van Houtryve cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer");
33fa3d789dSPierre van Houtryve 
34fa3d789dSPierre van Houtryve static cl::opt<unsigned>
35fa3d789dSPierre van Houtryve     AsmParserNum("asmparsernum", cl::init(0),
36fa3d789dSPierre van Houtryve                  cl::desc("Make -gen-asm-parser emit assembly parser #N"),
37fa3d789dSPierre van Houtryve                  cl::cat(AsmParserCat));
38fa3d789dSPierre van Houtryve 
39fa3d789dSPierre van Houtryve static cl::opt<unsigned>
40fa3d789dSPierre van Houtryve     AsmWriterNum("asmwriternum", cl::init(0),
41fa3d789dSPierre van Houtryve                  cl::desc("Make -gen-asm-writer emit assembly writer #N"),
42fa3d789dSPierre van Houtryve                  cl::cat(AsmWriterCat));
43fa3d789dSPierre van Houtryve 
44fa3d789dSPierre van Houtryve /// getValueType - Return the MVT::SimpleValueType that the specified TableGen
45fa3d789dSPierre van Houtryve /// record corresponds to.
46fa3d789dSPierre van Houtryve MVT::SimpleValueType llvm::getValueType(const Record *Rec) {
47fa3d789dSPierre van Houtryve   return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
48fa3d789dSPierre van Houtryve }
49fa3d789dSPierre van Houtryve 
50fa3d789dSPierre van Houtryve StringRef llvm::getEnumName(MVT::SimpleValueType T) {
51fa3d789dSPierre van Houtryve   // clang-format off
52fa3d789dSPierre van Houtryve   switch (T) {
53dc03ee3cSBrandon Wu #define GET_VT_ATTR(Ty, N, Sz, Any, Int, FP, Vec, Sc, Tup, NF, NElem, EltTy)   \
5485cf2e5eSBrandon Wu   case MVT::Ty: return "MVT::" # Ty;
5585cf2e5eSBrandon Wu #include "llvm/CodeGen/GenVT.inc"
56fa3d789dSPierre van Houtryve   default: llvm_unreachable("ILLEGAL VALUE TYPE!");
57fa3d789dSPierre van Houtryve   }
58fa3d789dSPierre van Houtryve   // clang-format on
59fa3d789dSPierre van Houtryve }
60fa3d789dSPierre van Houtryve 
61fa3d789dSPierre van Houtryve /// getQualifiedName - Return the name of the specified record, with a
62fa3d789dSPierre van Houtryve /// namespace qualifier if the record contains one.
63fa3d789dSPierre van Houtryve ///
64fa3d789dSPierre van Houtryve std::string llvm::getQualifiedName(const Record *R) {
65fa3d789dSPierre van Houtryve   std::string Namespace;
66fa3d789dSPierre van Houtryve   if (R->getValue("Namespace"))
67fa3d789dSPierre van Houtryve     Namespace = std::string(R->getValueAsString("Namespace"));
68fa3d789dSPierre van Houtryve   if (Namespace.empty())
69fa3d789dSPierre van Houtryve     return std::string(R->getName());
70fa3d789dSPierre van Houtryve   return Namespace + "::" + R->getName().str();
71fa3d789dSPierre van Houtryve }
72fa3d789dSPierre van Houtryve 
73fa3d789dSPierre van Houtryve /// getTarget - Return the current instance of the Target class.
74fa3d789dSPierre van Houtryve ///
7543f044baSRahul Joshi CodeGenTarget::CodeGenTarget(const RecordKeeper &records)
76c1e3b990SRahul Joshi     : Records(records), CGH(records), Intrinsics(records) {
7743f044baSRahul Joshi   ArrayRef<const Record *> Targets = Records.getAllDerivedDefinitions("Target");
78fa3d789dSPierre van Houtryve   if (Targets.size() == 0)
79fa3d789dSPierre van Houtryve     PrintFatalError("No 'Target' subclasses defined!");
80fa3d789dSPierre van Houtryve   if (Targets.size() != 1)
81fa3d789dSPierre van Houtryve     PrintFatalError("Multiple subclasses of Target defined!");
82fa3d789dSPierre van Houtryve   TargetRec = Targets[0];
83fa3d789dSPierre van Houtryve   MacroFusions = Records.getAllDerivedDefinitions("Fusion");
84fa3d789dSPierre van Houtryve }
85fa3d789dSPierre van Houtryve 
86fa3d789dSPierre van Houtryve CodeGenTarget::~CodeGenTarget() {}
87fa3d789dSPierre van Houtryve 
88fa3d789dSPierre van Houtryve StringRef CodeGenTarget::getName() const { return TargetRec->getName(); }
89fa3d789dSPierre van Houtryve 
90fa3d789dSPierre van Houtryve /// getInstNamespace - Find and return the target machine's instruction
91fa3d789dSPierre van Houtryve /// namespace. The namespace is cached because it is requested multiple times.
92fa3d789dSPierre van Houtryve StringRef CodeGenTarget::getInstNamespace() const {
93fa3d789dSPierre van Houtryve   if (InstNamespace.empty()) {
94fa3d789dSPierre van Houtryve     for (const CodeGenInstruction *Inst : getInstructionsByEnumValue()) {
95fa3d789dSPierre van Houtryve       // We are not interested in the "TargetOpcode" namespace.
96fa3d789dSPierre van Houtryve       if (Inst->Namespace != "TargetOpcode") {
97fa3d789dSPierre van Houtryve         InstNamespace = Inst->Namespace;
98fa3d789dSPierre van Houtryve         break;
99fa3d789dSPierre van Houtryve       }
100fa3d789dSPierre van Houtryve     }
101fa3d789dSPierre van Houtryve   }
102fa3d789dSPierre van Houtryve 
103fa3d789dSPierre van Houtryve   return InstNamespace;
104fa3d789dSPierre van Houtryve }
105fa3d789dSPierre van Houtryve 
106fa3d789dSPierre van Houtryve StringRef CodeGenTarget::getRegNamespace() const {
107fa3d789dSPierre van Houtryve   auto &RegClasses = RegBank->getRegClasses();
108fa3d789dSPierre van Houtryve   return RegClasses.size() > 0 ? RegClasses.front().Namespace : "";
109fa3d789dSPierre van Houtryve }
110fa3d789dSPierre van Houtryve 
1113138eb50SRahul Joshi const Record *CodeGenTarget::getInstructionSet() const {
112fa3d789dSPierre van Houtryve   return TargetRec->getValueAsDef("InstructionSet");
113fa3d789dSPierre van Houtryve }
114fa3d789dSPierre van Houtryve 
115fa3d789dSPierre van Houtryve bool CodeGenTarget::getAllowRegisterRenaming() const {
116fa3d789dSPierre van Houtryve   return TargetRec->getValueAsInt("AllowRegisterRenaming");
117fa3d789dSPierre van Houtryve }
118fa3d789dSPierre van Houtryve 
119fa3d789dSPierre van Houtryve /// getAsmParser - Return the AssemblyParser definition for this target.
120fa3d789dSPierre van Houtryve ///
1213138eb50SRahul Joshi const Record *CodeGenTarget::getAsmParser() const {
1223138eb50SRahul Joshi   std::vector<const Record *> LI =
123a140931bSRahul Joshi       TargetRec->getValueAsListOfDefs("AssemblyParsers");
124fa3d789dSPierre van Houtryve   if (AsmParserNum >= LI.size())
125fa3d789dSPierre van Houtryve     PrintFatalError("Target does not have an AsmParser #" +
126fa3d789dSPierre van Houtryve                     Twine(AsmParserNum) + "!");
127fa3d789dSPierre van Houtryve   return LI[AsmParserNum];
128fa3d789dSPierre van Houtryve }
129fa3d789dSPierre van Houtryve 
130fa3d789dSPierre van Houtryve /// getAsmParserVariant - Return the AssemblyParserVariant definition for
131fa3d789dSPierre van Houtryve /// this target.
132fa3d789dSPierre van Houtryve ///
1333138eb50SRahul Joshi const Record *CodeGenTarget::getAsmParserVariant(unsigned Idx) const {
1343138eb50SRahul Joshi   std::vector<const Record *> LI =
135a140931bSRahul Joshi       TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
1363138eb50SRahul Joshi   if (Idx >= LI.size())
1373138eb50SRahul Joshi     PrintFatalError("Target does not have an AsmParserVariant #" + Twine(Idx) +
138fa3d789dSPierre van Houtryve                     "!");
1393138eb50SRahul Joshi   return LI[Idx];
140fa3d789dSPierre van Houtryve }
141fa3d789dSPierre van Houtryve 
142fa3d789dSPierre van Houtryve /// getAsmParserVariantCount - Return the AssemblyParserVariant definition
143fa3d789dSPierre van Houtryve /// available for this target.
144fa3d789dSPierre van Houtryve ///
145fa3d789dSPierre van Houtryve unsigned CodeGenTarget::getAsmParserVariantCount() const {
1463138eb50SRahul Joshi   return TargetRec->getValueAsListOfDefs("AssemblyParserVariants").size();
147fa3d789dSPierre van Houtryve }
148fa3d789dSPierre van Houtryve 
149fa3d789dSPierre van Houtryve /// getAsmWriter - Return the AssemblyWriter definition for this target.
150fa3d789dSPierre van Houtryve ///
1513138eb50SRahul Joshi const Record *CodeGenTarget::getAsmWriter() const {
1523138eb50SRahul Joshi   std::vector<const Record *> LI =
153a140931bSRahul Joshi       TargetRec->getValueAsListOfDefs("AssemblyWriters");
154fa3d789dSPierre van Houtryve   if (AsmWriterNum >= LI.size())
155fa3d789dSPierre van Houtryve     PrintFatalError("Target does not have an AsmWriter #" +
156fa3d789dSPierre van Houtryve                     Twine(AsmWriterNum) + "!");
157fa3d789dSPierre van Houtryve   return LI[AsmWriterNum];
158fa3d789dSPierre van Houtryve }
159fa3d789dSPierre van Houtryve 
160fa3d789dSPierre van Houtryve CodeGenRegBank &CodeGenTarget::getRegBank() const {
161fa3d789dSPierre van Houtryve   if (!RegBank)
162fa3d789dSPierre van Houtryve     RegBank = std::make_unique<CodeGenRegBank>(Records, getHwModes());
163fa3d789dSPierre van Houtryve   return *RegBank;
164fa3d789dSPierre van Houtryve }
165fa3d789dSPierre van Houtryve 
166*73eecb70SSergei Barannikov const CodeGenRegisterClass *CodeGenTarget::getSuperRegForSubReg(
167fa3d789dSPierre van Houtryve     const ValueTypeByHwMode &ValueTy, CodeGenRegBank &RegBank,
168fa3d789dSPierre van Houtryve     const CodeGenSubRegIndex *SubIdx, bool MustBeAllocatable) const {
169fa3d789dSPierre van Houtryve   std::vector<CodeGenRegisterClass *> Candidates;
170fa3d789dSPierre van Houtryve   auto &RegClasses = RegBank.getRegClasses();
171fa3d789dSPierre van Houtryve 
172fa3d789dSPierre van Houtryve   // Try to find a register class which supports ValueTy, and also contains
173fa3d789dSPierre van Houtryve   // SubIdx.
174fa3d789dSPierre van Houtryve   for (CodeGenRegisterClass &RC : RegClasses) {
175fa3d789dSPierre van Houtryve     // Is there a subclass of this class which contains this subregister index?
176fa3d789dSPierre van Houtryve     CodeGenRegisterClass *SubClassWithSubReg = RC.getSubClassWithSubReg(SubIdx);
177fa3d789dSPierre van Houtryve     if (!SubClassWithSubReg)
178fa3d789dSPierre van Houtryve       continue;
179fa3d789dSPierre van Houtryve 
180fa3d789dSPierre van Houtryve     // We have a class. Check if it supports this value type.
181fa3d789dSPierre van Houtryve     if (!llvm::is_contained(SubClassWithSubReg->VTs, ValueTy))
182fa3d789dSPierre van Houtryve       continue;
183fa3d789dSPierre van Houtryve 
184fa3d789dSPierre van Houtryve     // If necessary, check that it is allocatable.
185fa3d789dSPierre van Houtryve     if (MustBeAllocatable && !SubClassWithSubReg->Allocatable)
186fa3d789dSPierre van Houtryve       continue;
187fa3d789dSPierre van Houtryve 
188fa3d789dSPierre van Houtryve     // We have a register class which supports both the value type and
189fa3d789dSPierre van Houtryve     // subregister index. Remember it.
190fa3d789dSPierre van Houtryve     Candidates.push_back(SubClassWithSubReg);
191fa3d789dSPierre van Houtryve   }
192fa3d789dSPierre van Houtryve 
193fa3d789dSPierre van Houtryve   // If we didn't find anything, we're done.
194fa3d789dSPierre van Houtryve   if (Candidates.empty())
195*73eecb70SSergei Barannikov     return nullptr;
196fa3d789dSPierre van Houtryve 
197fa3d789dSPierre van Houtryve   // Find and return the largest of our candidate classes.
198fa3d789dSPierre van Houtryve   llvm::stable_sort(Candidates, [&](const CodeGenRegisterClass *A,
199fa3d789dSPierre van Houtryve                                     const CodeGenRegisterClass *B) {
200fa3d789dSPierre van Houtryve     if (A->getMembers().size() > B->getMembers().size())
201fa3d789dSPierre van Houtryve       return true;
202fa3d789dSPierre van Houtryve 
203fa3d789dSPierre van Houtryve     if (A->getMembers().size() < B->getMembers().size())
204fa3d789dSPierre van Houtryve       return false;
205fa3d789dSPierre van Houtryve 
206fa3d789dSPierre van Houtryve     // Order by name as a tie-breaker.
207fa3d789dSPierre van Houtryve     return StringRef(A->getName()) < B->getName();
208fa3d789dSPierre van Houtryve   });
209fa3d789dSPierre van Houtryve 
210fa3d789dSPierre van Houtryve   return Candidates[0];
211fa3d789dSPierre van Houtryve }
212fa3d789dSPierre van Houtryve 
213fa3d789dSPierre van Houtryve /// getRegisterByName - If there is a register with the specific AsmName,
214fa3d789dSPierre van Houtryve /// return it.
215fa3d789dSPierre van Houtryve const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
216fa3d789dSPierre van Houtryve   return getRegBank().getRegistersByName().lookup(Name);
217fa3d789dSPierre van Houtryve }
218fa3d789dSPierre van Houtryve 
219bdf02249SRahul Joshi const CodeGenRegisterClass &
220bdf02249SRahul Joshi CodeGenTarget::getRegisterClass(const Record *R) const {
221fa3d789dSPierre van Houtryve   return *getRegBank().getRegClass(R);
222fa3d789dSPierre van Houtryve }
223fa3d789dSPierre van Houtryve 
22423123aa4SRahul Joshi std::vector<ValueTypeByHwMode>
22523123aa4SRahul Joshi CodeGenTarget::getRegisterVTs(const Record *R) const {
226fa3d789dSPierre van Houtryve   const CodeGenRegister *Reg = getRegBank().getReg(R);
227fa3d789dSPierre van Houtryve   std::vector<ValueTypeByHwMode> Result;
228fa3d789dSPierre van Houtryve   for (const auto &RC : getRegBank().getRegClasses()) {
229fa3d789dSPierre van Houtryve     if (RC.contains(Reg)) {
230fa3d789dSPierre van Houtryve       ArrayRef<ValueTypeByHwMode> InVTs = RC.getValueTypes();
231fa3d789dSPierre van Houtryve       llvm::append_range(Result, InVTs);
232fa3d789dSPierre van Houtryve     }
233fa3d789dSPierre van Houtryve   }
234fa3d789dSPierre van Houtryve 
235fa3d789dSPierre van Houtryve   // Remove duplicates.
236fa3d789dSPierre van Houtryve   llvm::sort(Result);
237d9293519SKazu Hirata   Result.erase(llvm::unique(Result), Result.end());
238fa3d789dSPierre van Houtryve   return Result;
239fa3d789dSPierre van Houtryve }
240fa3d789dSPierre van Houtryve 
241fa3d789dSPierre van Houtryve void CodeGenTarget::ReadLegalValueTypes() const {
242fa3d789dSPierre van Houtryve   for (const auto &RC : getRegBank().getRegClasses())
243fa3d789dSPierre van Houtryve     llvm::append_range(LegalValueTypes, RC.VTs);
244fa3d789dSPierre van Houtryve 
245fa3d789dSPierre van Houtryve   // Remove duplicates.
246fa3d789dSPierre van Houtryve   llvm::sort(LegalValueTypes);
247d9293519SKazu Hirata   LegalValueTypes.erase(llvm::unique(LegalValueTypes), LegalValueTypes.end());
248fa3d789dSPierre van Houtryve }
249fa3d789dSPierre van Houtryve 
250fa3d789dSPierre van Houtryve CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
251fa3d789dSPierre van Houtryve   if (!SchedModels)
252fa3d789dSPierre van Houtryve     SchedModels = std::make_unique<CodeGenSchedModels>(Records, *this);
253fa3d789dSPierre van Houtryve   return *SchedModels;
254fa3d789dSPierre van Houtryve }
255fa3d789dSPierre van Houtryve 
256fa3d789dSPierre van Houtryve void CodeGenTarget::ReadInstructions() const {
25743f044baSRahul Joshi   ArrayRef<const Record *> Insts =
25843f044baSRahul Joshi       Records.getAllDerivedDefinitions("Instruction");
259fa3d789dSPierre van Houtryve   if (Insts.size() <= 2)
260fa3d789dSPierre van Houtryve     PrintFatalError("No 'Instruction' subclasses defined!");
261fa3d789dSPierre van Houtryve 
262fa3d789dSPierre van Houtryve   // Parse the instructions defined in the .td file.
26343f044baSRahul Joshi   for (const Record *R : Insts) {
264fa3d789dSPierre van Houtryve     Instructions[R] = std::make_unique<CodeGenInstruction>(R);
265fa3d789dSPierre van Houtryve     if (Instructions[R]->isVariableLengthEncoding())
266fa3d789dSPierre van Houtryve       HasVariableLengthEncodings = true;
267fa3d789dSPierre van Houtryve   }
268fa3d789dSPierre van Houtryve }
269fa3d789dSPierre van Houtryve 
270fa3d789dSPierre van Houtryve static const CodeGenInstruction *GetInstByName(
271fa3d789dSPierre van Houtryve     const char *Name,
272fa3d789dSPierre van Houtryve     const DenseMap<const Record *, std::unique_ptr<CodeGenInstruction>> &Insts,
27343f044baSRahul Joshi     const RecordKeeper &Records) {
274fa3d789dSPierre van Houtryve   const Record *Rec = Records.getDef(Name);
275fa3d789dSPierre van Houtryve 
276fa3d789dSPierre van Houtryve   const auto I = Insts.find(Rec);
277fa3d789dSPierre van Houtryve   if (!Rec || I == Insts.end())
278fa3d789dSPierre van Houtryve     PrintFatalError(Twine("Could not find '") + Name + "' instruction!");
279fa3d789dSPierre van Houtryve   return I->second.get();
280fa3d789dSPierre van Houtryve }
281fa3d789dSPierre van Houtryve 
282fa3d789dSPierre van Houtryve static const char *FixedInstrs[] = {
283fa3d789dSPierre van Houtryve #define HANDLE_TARGET_OPCODE(OPC) #OPC,
284fa3d789dSPierre van Houtryve #include "llvm/Support/TargetOpcodes.def"
285fa3d789dSPierre van Houtryve     nullptr};
286fa3d789dSPierre van Houtryve 
287fa3d789dSPierre van Houtryve unsigned CodeGenTarget::getNumFixedInstructions() {
288fa3d789dSPierre van Houtryve   return std::size(FixedInstrs) - 1;
289fa3d789dSPierre van Houtryve }
290fa3d789dSPierre van Houtryve 
291fa3d789dSPierre van Houtryve /// Return all of the instructions defined by the target, ordered by
292fa3d789dSPierre van Houtryve /// their enum value.
293fa3d789dSPierre van Houtryve void CodeGenTarget::ComputeInstrsByEnum() const {
294fa3d789dSPierre van Houtryve   const auto &Insts = getInstructions();
295fa3d789dSPierre van Houtryve   for (const char *const *p = FixedInstrs; *p; ++p) {
296fa3d789dSPierre van Houtryve     const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
297fa3d789dSPierre van Houtryve     assert(Instr && "Missing target independent instruction");
298fa3d789dSPierre van Houtryve     assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
299fa3d789dSPierre van Houtryve     InstrsByEnum.push_back(Instr);
300fa3d789dSPierre van Houtryve   }
301fa3d789dSPierre van Houtryve   unsigned EndOfPredefines = InstrsByEnum.size();
302fa3d789dSPierre van Houtryve   assert(EndOfPredefines == getNumFixedInstructions() &&
303fa3d789dSPierre van Houtryve          "Missing generic opcode");
304fa3d789dSPierre van Houtryve 
305fa3d789dSPierre van Houtryve   for (const auto &I : Insts) {
306fa3d789dSPierre van Houtryve     const CodeGenInstruction *CGI = I.second.get();
307fa3d789dSPierre van Houtryve     if (CGI->Namespace != "TargetOpcode") {
308fa3d789dSPierre van Houtryve       InstrsByEnum.push_back(CGI);
309fa3d789dSPierre van Houtryve       if (CGI->TheDef->getValueAsBit("isPseudo"))
310fa3d789dSPierre van Houtryve         ++NumPseudoInstructions;
311fa3d789dSPierre van Houtryve     }
312fa3d789dSPierre van Houtryve   }
313fa3d789dSPierre van Houtryve 
314fa3d789dSPierre van Houtryve   assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr");
315fa3d789dSPierre van Houtryve 
316fa3d789dSPierre van Houtryve   // All of the instructions are now in random order based on the map iteration.
317fa3d789dSPierre van Houtryve   llvm::sort(
318fa3d789dSPierre van Houtryve       InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(),
319fa3d789dSPierre van Houtryve       [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
320fa3d789dSPierre van Houtryve         const auto &D1 = *Rec1->TheDef;
321fa3d789dSPierre van Houtryve         const auto &D2 = *Rec2->TheDef;
322fa3d789dSPierre van Houtryve         return std::tuple(!D1.getValueAsBit("isPseudo"), D1.getName()) <
323fa3d789dSPierre van Houtryve                std::tuple(!D2.getValueAsBit("isPseudo"), D2.getName());
324fa3d789dSPierre van Houtryve       });
325fa3d789dSPierre van Houtryve 
326fa3d789dSPierre van Houtryve   // Assign an enum value to each instruction according to the sorted order.
327fa3d789dSPierre van Houtryve   unsigned Num = 0;
328fa3d789dSPierre van Houtryve   for (const CodeGenInstruction *Inst : InstrsByEnum)
329fa3d789dSPierre van Houtryve     Inst->EnumVal = Num++;
330fa3d789dSPierre van Houtryve }
331fa3d789dSPierre van Houtryve 
332fa3d789dSPierre van Houtryve /// isLittleEndianEncoding - Return whether this target encodes its instruction
333fa3d789dSPierre van Houtryve /// in little-endian format, i.e. bits laid out in the order [0..n]
334fa3d789dSPierre van Houtryve ///
335fa3d789dSPierre van Houtryve bool CodeGenTarget::isLittleEndianEncoding() const {
336fa3d789dSPierre van Houtryve   return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
337fa3d789dSPierre van Houtryve }
338fa3d789dSPierre van Houtryve 
339fa3d789dSPierre van Houtryve /// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
340fa3d789dSPierre van Houtryve /// encodings, reverse the bit order of all instructions.
341fa3d789dSPierre van Houtryve void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
342fa3d789dSPierre van Houtryve   if (!isLittleEndianEncoding())
343fa3d789dSPierre van Houtryve     return;
344fa3d789dSPierre van Houtryve 
34543f044baSRahul Joshi   for (const Record *R :
34643f044baSRahul Joshi        Records.getAllDerivedDefinitions("InstructionEncoding")) {
347fa3d789dSPierre van Houtryve     if (R->getValueAsString("Namespace") == "TargetOpcode" ||
348fa3d789dSPierre van Houtryve         R->getValueAsBit("isPseudo"))
349fa3d789dSPierre van Houtryve       continue;
350fa3d789dSPierre van Houtryve 
35162e2c7fbSRahul Joshi     const BitsInit *BI = R->getValueAsBitsInit("Inst");
352fa3d789dSPierre van Houtryve 
353fa3d789dSPierre van Houtryve     unsigned numBits = BI->getNumBits();
354fa3d789dSPierre van Houtryve 
35562e2c7fbSRahul Joshi     SmallVector<const Init *, 16> NewBits(numBits);
356fa3d789dSPierre van Houtryve 
357fa3d789dSPierre van Houtryve     for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
358fa3d789dSPierre van Houtryve       unsigned bitSwapIdx = numBits - bit - 1;
35962e2c7fbSRahul Joshi       const Init *OrigBit = BI->getBit(bit);
36062e2c7fbSRahul Joshi       const Init *BitSwap = BI->getBit(bitSwapIdx);
361fa3d789dSPierre van Houtryve       NewBits[bit] = BitSwap;
362fa3d789dSPierre van Houtryve       NewBits[bitSwapIdx] = OrigBit;
363fa3d789dSPierre van Houtryve     }
364fa3d789dSPierre van Houtryve     if (numBits % 2) {
365fa3d789dSPierre van Houtryve       unsigned middle = (numBits + 1) / 2;
366fa3d789dSPierre van Houtryve       NewBits[middle] = BI->getBit(middle);
367fa3d789dSPierre van Houtryve     }
368fa3d789dSPierre van Houtryve 
36943f044baSRahul Joshi     RecordKeeper &MutableRC = const_cast<RecordKeeper &>(Records);
37062e2c7fbSRahul Joshi     const BitsInit *NewBI = BitsInit::get(MutableRC, NewBits);
371fa3d789dSPierre van Houtryve 
37243f044baSRahul Joshi     // Update the bits in reversed order so that emitters will get the correct
37343f044baSRahul Joshi     // endianness.
37443f044baSRahul Joshi     // FIXME: Eliminate mutation of TG records by creating a helper function
37543f044baSRahul Joshi     // to reverse bits and maintain a cache instead of mutating records.
37643f044baSRahul Joshi     Record *MutableR = const_cast<Record *>(R);
37743f044baSRahul Joshi     MutableR->getValue("Inst")->setValue(NewBI);
378fa3d789dSPierre van Houtryve   }
379fa3d789dSPierre van Houtryve }
380fa3d789dSPierre van Houtryve 
381fa3d789dSPierre van Houtryve /// guessInstructionProperties - Return true if it's OK to guess instruction
382fa3d789dSPierre van Houtryve /// properties instead of raising an error.
383fa3d789dSPierre van Houtryve ///
384fa3d789dSPierre van Houtryve /// This is configurable as a temporary migration aid. It will eventually be
385fa3d789dSPierre van Houtryve /// permanently false.
386fa3d789dSPierre van Houtryve bool CodeGenTarget::guessInstructionProperties() const {
387fa3d789dSPierre van Houtryve   return getInstructionSet()->getValueAsBit("guessInstructionProperties");
388fa3d789dSPierre van Houtryve }
389fa3d789dSPierre van Houtryve 
390fa3d789dSPierre van Houtryve //===----------------------------------------------------------------------===//
391fa3d789dSPierre van Houtryve // ComplexPattern implementation
392fa3d789dSPierre van Houtryve //
39387e8b530SRahul Joshi ComplexPattern::ComplexPattern(const Record *R) {
394fa3d789dSPierre van Houtryve   Ty = R->getValueAsDef("Ty");
395fa3d789dSPierre van Houtryve   NumOperands = R->getValueAsInt("NumOperands");
396fa3d789dSPierre van Houtryve   SelectFunc = std::string(R->getValueAsString("SelectFunc"));
397a140931bSRahul Joshi   RootNodes = R->getValueAsListOfDefs("RootNodes");
398fa3d789dSPierre van Houtryve 
399fa3d789dSPierre van Houtryve   // FIXME: This is a hack to statically increase the priority of patterns which
400fa3d789dSPierre van Houtryve   // maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
401fa3d789dSPierre van Houtryve   // possible pattern match we'll need to dynamically calculate the complexity
402fa3d789dSPierre van Houtryve   // of all patterns a dag can potentially map to.
403fa3d789dSPierre van Houtryve   int64_t RawComplexity = R->getValueAsInt("Complexity");
404fa3d789dSPierre van Houtryve   if (RawComplexity == -1)
405fa3d789dSPierre van Houtryve     Complexity = NumOperands * 3;
406fa3d789dSPierre van Houtryve   else
407fa3d789dSPierre van Houtryve     Complexity = RawComplexity;
408fa3d789dSPierre van Houtryve 
409fa3d789dSPierre van Houtryve   // FIXME: Why is this different from parseSDPatternOperatorProperties?
410fa3d789dSPierre van Houtryve   // Parse the properties.
411fa3d789dSPierre van Houtryve   Properties = 0;
4123138eb50SRahul Joshi   for (const Record *Prop : R->getValueAsListOfDefs("Properties")) {
4133138eb50SRahul Joshi     if (Prop->getName() == "SDNPHasChain") {
414fa3d789dSPierre van Houtryve       Properties |= 1 << SDNPHasChain;
4153138eb50SRahul Joshi     } else if (Prop->getName() == "SDNPOptInGlue") {
416fa3d789dSPierre van Houtryve       Properties |= 1 << SDNPOptInGlue;
4173138eb50SRahul Joshi     } else if (Prop->getName() == "SDNPMayStore") {
418fa3d789dSPierre van Houtryve       Properties |= 1 << SDNPMayStore;
4193138eb50SRahul Joshi     } else if (Prop->getName() == "SDNPMayLoad") {
420fa3d789dSPierre van Houtryve       Properties |= 1 << SDNPMayLoad;
4213138eb50SRahul Joshi     } else if (Prop->getName() == "SDNPSideEffect") {
422fa3d789dSPierre van Houtryve       Properties |= 1 << SDNPSideEffect;
4233138eb50SRahul Joshi     } else if (Prop->getName() == "SDNPMemOperand") {
424fa3d789dSPierre van Houtryve       Properties |= 1 << SDNPMemOperand;
4253138eb50SRahul Joshi     } else if (Prop->getName() == "SDNPVariadic") {
426fa3d789dSPierre van Houtryve       Properties |= 1 << SDNPVariadic;
427fa3d789dSPierre van Houtryve     } else {
4283138eb50SRahul Joshi       PrintFatalError(R->getLoc(),
4293138eb50SRahul Joshi                       "Unsupported SD Node property '" + Prop->getName() +
4303138eb50SRahul Joshi                           "' on ComplexPattern '" + R->getName() + "'!");
4313138eb50SRahul Joshi     }
432fa3d789dSPierre van Houtryve   }
4336b223260SSergei Barannikov 
4346b223260SSergei Barannikov   WantsRoot = R->getValueAsBit("WantsRoot");
4356b223260SSergei Barannikov   WantsParent = R->getValueAsBit("WantsParent");
436fa3d789dSPierre van Houtryve }
437