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.
getValueType(const Record * Rec)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
getName(MVT::SimpleValueType T)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
getEnumName(MVT::SimpleValueType T)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 ///
getQualifiedName(const Record * R)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 ///
CodeGenTarget(RecordKeeper & records)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
~CodeGenTarget()99*0fca6ea1SDimitry Andric CodeGenTarget::~CodeGenTarget() {}
100*0fca6ea1SDimitry Andric
getName() const101*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.
getInstNamespace() const105*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
getRegNamespace() const119*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
getInstructionSet() const124*0fca6ea1SDimitry Andric Record *CodeGenTarget::getInstructionSet() const {
125*0fca6ea1SDimitry Andric return TargetRec->getValueAsDef("InstructionSet");
126*0fca6ea1SDimitry Andric }
127*0fca6ea1SDimitry Andric
getAllowRegisterRenaming() const128*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 ///
getAsmParser() const134*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 ///
getAsmParserVariant(unsigned i) const145*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 ///
getAsmParserVariantCount() const157*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 ///
getAsmWriter() const165*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
getRegBank() const173*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
getSuperRegForSubReg(const ValueTypeByHwMode & ValueTy,CodeGenRegBank & RegBank,const CodeGenSubRegIndex * SubIdx,bool MustBeAllocatable) const179*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
ReadRegAltNameIndices() const226*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.
getRegisterByName(StringRef Name) const233*0fca6ea1SDimitry Andric const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
234*0fca6ea1SDimitry Andric return getRegBank().getRegistersByName().lookup(Name);
235*0fca6ea1SDimitry Andric }
236*0fca6ea1SDimitry Andric
getRegisterClass(Record * R) const237*0fca6ea1SDimitry Andric const CodeGenRegisterClass &CodeGenTarget::getRegisterClass(Record *R) const {
238*0fca6ea1SDimitry Andric return *getRegBank().getRegClass(R);
239*0fca6ea1SDimitry Andric }
240*0fca6ea1SDimitry Andric
getRegisterVTs(Record * R) const241*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
ReadLegalValueTypes() const257*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
getSchedModels() const266*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
ReadInstructions() const272*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
GetInstByName(const char * Name,const DenseMap<const Record *,std::unique_ptr<CodeGenInstruction>> & Insts,RecordKeeper & Records)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
getNumFixedInstructions()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.
ComputeInstrsByEnum() const308*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 ///
isLittleEndianEncoding() const350*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.
reverseBitsForLittleEndianEncoding()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.
guessInstructionProperties() const398*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 //
ComplexPattern(Record * R)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