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