aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/utils
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/utils')
-rw-r--r--contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp3215
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp1129
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterInst.cpp197
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterInst.h106
-rw-r--r--contrib/llvm/utils/TableGen/Attributes.cpp179
-rw-r--r--contrib/llvm/utils/TableGen/CTagsEmitter.cpp87
-rw-r--r--contrib/llvm/utils/TableGen/CallingConvEmitter.cpp284
-rw-r--r--contrib/llvm/utils/TableGen/CodeEmitterGen.cpp394
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp3852
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h866
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.cpp688
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.h355
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenIntrinsics.h155
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenMapTable.cpp608
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenRegisters.cpp2179
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenRegisters.h746
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenSchedule.cpp1864
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenSchedule.h444
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.cpp677
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.h215
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelEmitter.cpp174
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcher.cpp391
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcher.h1053
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp982
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp1010
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp470
-rw-r--r--contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp991
-rw-r--r--contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp148
-rw-r--r--contrib/llvm/utils/TableGen/FastISelEmitter.cpp885
-rw-r--r--contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp2325
-rw-r--r--contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp1762
-rw-r--r--contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp612
-rw-r--r--contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp818
-rw-r--r--contrib/llvm/utils/TableGen/OptParserEmitter.cpp290
-rw-r--r--contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp301
-rw-r--r--contrib/llvm/utils/TableGen/RegisterBankEmitter.cpp320
-rw-r--r--contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp1539
-rw-r--r--contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp320
-rw-r--r--contrib/llvm/utils/TableGen/SequenceToOffsetTable.h146
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetEmitter.cpp1533
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetFeatureInfo.cpp133
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetFeatureInfo.h72
-rw-r--r--contrib/llvm/utils/TableGen/TableGen.cpp222
-rw-r--r--contrib/llvm/utils/TableGen/TableGenBackends.h89
-rw-r--r--contrib/llvm/utils/TableGen/Types.cpp44
-rw-r--r--contrib/llvm/utils/TableGen/Types.h25
-rw-r--r--contrib/llvm/utils/TableGen/X86DisassemblerShared.h54
-rw-r--r--contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp929
-rw-r--r--contrib/llvm/utils/TableGen/X86DisassemblerTables.h283
-rw-r--r--contrib/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp339
-rw-r--r--contrib/llvm/utils/TableGen/X86ModRMFilters.cpp22
-rw-r--r--contrib/llvm/utils/TableGen/X86ModRMFilters.h135
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp1326
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.h233
54 files changed, 38216 insertions, 0 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
new file mode 100644
index 000000000000..3947d0220ed5
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -0,0 +1,3215 @@
+//===- AsmMatcherEmitter.cpp - Generate an assembly matcher ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits a target specifier matcher for converting parsed
+// assembly operands in the MCInst structures. It also emits a matcher for
+// custom operand parsing.
+//
+// Converting assembly operands into MCInst structures
+// ---------------------------------------------------
+//
+// The input to the target specific matcher is a list of literal tokens and
+// operands. The target specific parser should generally eliminate any syntax
+// which is not relevant for matching; for example, comma tokens should have
+// already been consumed and eliminated by the parser. Most instructions will
+// end up with a single literal token (the instruction name) and some number of
+// operands.
+//
+// Some example inputs, for X86:
+// 'addl' (immediate ...) (register ...)
+// 'add' (immediate ...) (memory ...)
+// 'call' '*' %epc
+//
+// The assembly matcher is responsible for converting this input into a precise
+// machine instruction (i.e., an instruction with a well defined encoding). This
+// mapping has several properties which complicate matching:
+//
+// - It may be ambiguous; many architectures can legally encode particular
+// variants of an instruction in different ways (for example, using a smaller
+// encoding for small immediates). Such ambiguities should never be
+// arbitrarily resolved by the assembler, the assembler is always responsible
+// for choosing the "best" available instruction.
+//
+// - It may depend on the subtarget or the assembler context. Instructions
+// which are invalid for the current mode, but otherwise unambiguous (e.g.,
+// an SSE instruction in a file being assembled for i486) should be accepted
+// and rejected by the assembler front end. However, if the proper encoding
+// for an instruction is dependent on the assembler context then the matcher
+// is responsible for selecting the correct machine instruction for the
+// current mode.
+//
+// The core matching algorithm attempts to exploit the regularity in most
+// instruction sets to quickly determine the set of possibly matching
+// instructions, and the simplify the generated code. Additionally, this helps
+// to ensure that the ambiguities are intentionally resolved by the user.
+//
+// The matching is divided into two distinct phases:
+//
+// 1. Classification: Each operand is mapped to the unique set which (a)
+// contains it, and (b) is the largest such subset for which a single
+// instruction could match all members.
+//
+// For register classes, we can generate these subgroups automatically. For
+// arbitrary operands, we expect the user to define the classes and their
+// relations to one another (for example, 8-bit signed immediates as a
+// subset of 32-bit immediates).
+//
+// By partitioning the operands in this way, we guarantee that for any
+// tuple of classes, any single instruction must match either all or none
+// of the sets of operands which could classify to that tuple.
+//
+// In addition, the subset relation amongst classes induces a partial order
+// on such tuples, which we use to resolve ambiguities.
+//
+// 2. The input can now be treated as a tuple of classes (static tokens are
+// simple singleton sets). Each such tuple should generally map to a single
+// instruction (we currently ignore cases where this isn't true, whee!!!),
+// which we can emit a simple matcher for.
+//
+// Custom Operand Parsing
+// ----------------------
+//
+// Some targets need a custom way to parse operands, some specific instructions
+// can contain arguments that can represent processor flags and other kinds of
+// identifiers that need to be mapped to specific values in the final encoded
+// instructions. The target specific custom operand parsing works in the
+// following way:
+//
+// 1. A operand match table is built, each entry contains a mnemonic, an
+// operand class, a mask for all operand positions for that same
+// class/mnemonic and target features to be checked while trying to match.
+//
+// 2. The operand matcher will try every possible entry with the same
+// mnemonic and will check if the target feature for this mnemonic also
+// matches. After that, if the operand to be matched has its index
+// present in the mask, a successful match occurs. Otherwise, fallback
+// to the regular operand parsing.
+//
+// 3. For a match success, each operand class that has a 'ParserMethod'
+// becomes part of a switch from where the custom method is called.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenTarget.h"
+#include "SubtargetFeatureInfo.h"
+#include "Types.h"
+#include "llvm/ADT/CachedHashString.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include "llvm/TableGen/StringToOffsetTable.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <cassert>
+#include <cctype>
+#include <forward_list>
+#include <map>
+#include <set>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "asm-matcher-emitter"
+
+cl::OptionCategory AsmMatcherEmitterCat("Options for -gen-asm-matcher");
+
+static cl::opt<std::string>
+ MatchPrefix("match-prefix", cl::init(""),
+ cl::desc("Only match instructions with the given prefix"),
+ cl::cat(AsmMatcherEmitterCat));
+
+namespace {
+class AsmMatcherInfo;
+
+// Register sets are used as keys in some second-order sets TableGen creates
+// when generating its data structures. This means that the order of two
+// RegisterSets can be seen in the outputted AsmMatcher tables occasionally, and
+// can even affect compiler output (at least seen in diagnostics produced when
+// all matches fail). So we use a type that sorts them consistently.
+typedef std::set<Record*, LessRecordByID> RegisterSet;
+
+class AsmMatcherEmitter {
+ RecordKeeper &Records;
+public:
+ AsmMatcherEmitter(RecordKeeper &R) : Records(R) {}
+
+ void run(raw_ostream &o);
+};
+
+/// ClassInfo - Helper class for storing the information about a particular
+/// class of operands which can be matched.
+struct ClassInfo {
+ enum ClassInfoKind {
+ /// Invalid kind, for use as a sentinel value.
+ Invalid = 0,
+
+ /// The class for a particular token.
+ Token,
+
+ /// The (first) register class, subsequent register classes are
+ /// RegisterClass0+1, and so on.
+ RegisterClass0,
+
+ /// The (first) user defined class, subsequent user defined classes are
+ /// UserClass0+1, and so on.
+ UserClass0 = 1<<16
+ };
+
+ /// Kind - The class kind, which is either a predefined kind, or (UserClass0 +
+ /// N) for the Nth user defined class.
+ unsigned Kind;
+
+ /// SuperClasses - The super classes of this class. Note that for simplicities
+ /// sake user operands only record their immediate super class, while register
+ /// operands include all superclasses.
+ std::vector<ClassInfo*> SuperClasses;
+
+ /// Name - The full class name, suitable for use in an enum.
+ std::string Name;
+
+ /// ClassName - The unadorned generic name for this class (e.g., Token).
+ std::string ClassName;
+
+ /// ValueName - The name of the value this class represents; for a token this
+ /// is the literal token string, for an operand it is the TableGen class (or
+ /// empty if this is a derived class).
+ std::string ValueName;
+
+ /// PredicateMethod - The name of the operand method to test whether the
+ /// operand matches this class; this is not valid for Token or register kinds.
+ std::string PredicateMethod;
+
+ /// RenderMethod - The name of the operand method to add this operand to an
+ /// MCInst; this is not valid for Token or register kinds.
+ std::string RenderMethod;
+
+ /// ParserMethod - The name of the operand method to do a target specific
+ /// parsing on the operand.
+ std::string ParserMethod;
+
+ /// For register classes: the records for all the registers in this class.
+ RegisterSet Registers;
+
+ /// For custom match classes: the diagnostic kind for when the predicate fails.
+ std::string DiagnosticType;
+
+ /// Is this operand optional and not always required.
+ bool IsOptional;
+
+ /// DefaultMethod - The name of the method that returns the default operand
+ /// for optional operand
+ std::string DefaultMethod;
+
+public:
+ /// isRegisterClass() - Check if this is a register class.
+ bool isRegisterClass() const {
+ return Kind >= RegisterClass0 && Kind < UserClass0;
+ }
+
+ /// isUserClass() - Check if this is a user defined class.
+ bool isUserClass() const {
+ return Kind >= UserClass0;
+ }
+
+ /// isRelatedTo - Check whether this class is "related" to \p RHS. Classes
+ /// are related if they are in the same class hierarchy.
+ bool isRelatedTo(const ClassInfo &RHS) const {
+ // Tokens are only related to tokens.
+ if (Kind == Token || RHS.Kind == Token)
+ return Kind == Token && RHS.Kind == Token;
+
+ // Registers classes are only related to registers classes, and only if
+ // their intersection is non-empty.
+ if (isRegisterClass() || RHS.isRegisterClass()) {
+ if (!isRegisterClass() || !RHS.isRegisterClass())
+ return false;
+
+ RegisterSet Tmp;
+ std::insert_iterator<RegisterSet> II(Tmp, Tmp.begin());
+ std::set_intersection(Registers.begin(), Registers.end(),
+ RHS.Registers.begin(), RHS.Registers.end(),
+ II, LessRecordByID());
+
+ return !Tmp.empty();
+ }
+
+ // Otherwise we have two users operands; they are related if they are in the
+ // same class hierarchy.
+ //
+ // FIXME: This is an oversimplification, they should only be related if they
+ // intersect, however we don't have that information.
+ assert(isUserClass() && RHS.isUserClass() && "Unexpected class!");
+ const ClassInfo *Root = this;
+ while (!Root->SuperClasses.empty())
+ Root = Root->SuperClasses.front();
+
+ const ClassInfo *RHSRoot = &RHS;
+ while (!RHSRoot->SuperClasses.empty())
+ RHSRoot = RHSRoot->SuperClasses.front();
+
+ return Root == RHSRoot;
+ }
+
+ /// isSubsetOf - Test whether this class is a subset of \p RHS.
+ bool isSubsetOf(const ClassInfo &RHS) const {
+ // This is a subset of RHS if it is the same class...
+ if (this == &RHS)
+ return true;
+
+ // ... or if any of its super classes are a subset of RHS.
+ for (const ClassInfo *CI : SuperClasses)
+ if (CI->isSubsetOf(RHS))
+ return true;
+
+ return false;
+ }
+
+ int getTreeDepth() const {
+ int Depth = 0;
+ const ClassInfo *Root = this;
+ while (!Root->SuperClasses.empty()) {
+ Depth++;
+ Root = Root->SuperClasses.front();
+ }
+ return Depth;
+ }
+
+ const ClassInfo *findRoot() const {
+ const ClassInfo *Root = this;
+ while (!Root->SuperClasses.empty())
+ Root = Root->SuperClasses.front();
+ return Root;
+ }
+
+ /// Compare two classes. This does not produce a total ordering, but does
+ /// guarantee that subclasses are sorted before their parents, and that the
+ /// ordering is transitive.
+ bool operator<(const ClassInfo &RHS) const {
+ if (this == &RHS)
+ return false;
+
+ // First, enforce the ordering between the three different types of class.
+ // Tokens sort before registers, which sort before user classes.
+ if (Kind == Token) {
+ if (RHS.Kind != Token)
+ return true;
+ assert(RHS.Kind == Token);
+ } else if (isRegisterClass()) {
+ if (RHS.Kind == Token)
+ return false;
+ else if (RHS.isUserClass())
+ return true;
+ assert(RHS.isRegisterClass());
+ } else if (isUserClass()) {
+ if (!RHS.isUserClass())
+ return false;
+ assert(RHS.isUserClass());
+ } else {
+ llvm_unreachable("Unknown ClassInfoKind");
+ }
+
+ if (Kind == Token || isUserClass()) {
+ // Related tokens and user classes get sorted by depth in the inheritence
+ // tree (so that subclasses are before their parents).
+ if (isRelatedTo(RHS)) {
+ if (getTreeDepth() > RHS.getTreeDepth())
+ return true;
+ if (getTreeDepth() < RHS.getTreeDepth())
+ return false;
+ } else {
+ // Unrelated tokens and user classes are ordered by the name of their
+ // root nodes, so that there is a consistent ordering between
+ // unconnected trees.
+ return findRoot()->ValueName < RHS.findRoot()->ValueName;
+ }
+ } else if (isRegisterClass()) {
+ // For register sets, sort by number of registers. This guarantees that
+ // a set will always sort before all of it's strict supersets.
+ if (Registers.size() != RHS.Registers.size())
+ return Registers.size() < RHS.Registers.size();
+ } else {
+ llvm_unreachable("Unknown ClassInfoKind");
+ }
+
+ // FIXME: We should be able to just return false here, as we only need a
+ // partial order (we use stable sorts, so this is deterministic) and the
+ // name of a class shouldn't be significant. However, some of the backends
+ // accidentally rely on this behaviour, so it will have to stay like this
+ // until they are fixed.
+ return ValueName < RHS.ValueName;
+ }
+};
+
+class AsmVariantInfo {
+public:
+ std::string RegisterPrefix;
+ std::string TokenizingCharacters;
+ std::string SeparatorCharacters;
+ std::string BreakCharacters;
+ std::string Name;
+ int AsmVariantNo;
+};
+
+/// MatchableInfo - Helper class for storing the necessary information for an
+/// instruction or alias which is capable of being matched.
+struct MatchableInfo {
+ struct AsmOperand {
+ /// Token - This is the token that the operand came from.
+ StringRef Token;
+
+ /// The unique class instance this operand should match.
+ ClassInfo *Class;
+
+ /// The operand name this is, if anything.
+ StringRef SrcOpName;
+
+ /// The suboperand index within SrcOpName, or -1 for the entire operand.
+ int SubOpIdx;
+
+ /// Whether the token is "isolated", i.e., it is preceded and followed
+ /// by separators.
+ bool IsIsolatedToken;
+
+ /// Register record if this token is singleton register.
+ Record *SingletonReg;
+
+ explicit AsmOperand(bool IsIsolatedToken, StringRef T)
+ : Token(T), Class(nullptr), SubOpIdx(-1),
+ IsIsolatedToken(IsIsolatedToken), SingletonReg(nullptr) {}
+ };
+
+ /// ResOperand - This represents a single operand in the result instruction
+ /// generated by the match. In cases (like addressing modes) where a single
+ /// assembler operand expands to multiple MCOperands, this represents the
+ /// single assembler operand, not the MCOperand.
+ struct ResOperand {
+ enum {
+ /// RenderAsmOperand - This represents an operand result that is
+ /// generated by calling the render method on the assembly operand. The
+ /// corresponding AsmOperand is specified by AsmOperandNum.
+ RenderAsmOperand,
+
+ /// TiedOperand - This represents a result operand that is a duplicate of
+ /// a previous result operand.
+ TiedOperand,
+
+ /// ImmOperand - This represents an immediate value that is dumped into
+ /// the operand.
+ ImmOperand,
+
+ /// RegOperand - This represents a fixed register that is dumped in.
+ RegOperand
+ } Kind;
+
+ union {
+ /// This is the operand # in the AsmOperands list that this should be
+ /// copied from.
+ unsigned AsmOperandNum;
+
+ /// TiedOperandNum - This is the (earlier) result operand that should be
+ /// copied from.
+ unsigned TiedOperandNum;
+
+ /// ImmVal - This is the immediate value added to the instruction.
+ int64_t ImmVal;
+
+ /// Register - This is the register record.
+ Record *Register;
+ };
+
+ /// MINumOperands - The number of MCInst operands populated by this
+ /// operand.
+ unsigned MINumOperands;
+
+ static ResOperand getRenderedOp(unsigned AsmOpNum, unsigned NumOperands) {
+ ResOperand X;
+ X.Kind = RenderAsmOperand;
+ X.AsmOperandNum = AsmOpNum;
+ X.MINumOperands = NumOperands;
+ return X;
+ }
+
+ static ResOperand getTiedOp(unsigned TiedOperandNum) {
+ ResOperand X;
+ X.Kind = TiedOperand;
+ X.TiedOperandNum = TiedOperandNum;
+ X.MINumOperands = 1;
+ return X;
+ }
+
+ static ResOperand getImmOp(int64_t Val) {
+ ResOperand X;
+ X.Kind = ImmOperand;
+ X.ImmVal = Val;
+ X.MINumOperands = 1;
+ return X;
+ }
+
+ static ResOperand getRegOp(Record *Reg) {
+ ResOperand X;
+ X.Kind = RegOperand;
+ X.Register = Reg;
+ X.MINumOperands = 1;
+ return X;
+ }
+ };
+
+ /// AsmVariantID - Target's assembly syntax variant no.
+ int AsmVariantID;
+
+ /// AsmString - The assembly string for this instruction (with variants
+ /// removed), e.g. "movsx $src, $dst".
+ std::string AsmString;
+
+ /// TheDef - This is the definition of the instruction or InstAlias that this
+ /// matchable came from.
+ Record *const TheDef;
+
+ /// DefRec - This is the definition that it came from.
+ PointerUnion<const CodeGenInstruction*, const CodeGenInstAlias*> DefRec;
+
+ const CodeGenInstruction *getResultInst() const {
+ if (DefRec.is<const CodeGenInstruction*>())
+ return DefRec.get<const CodeGenInstruction*>();
+ return DefRec.get<const CodeGenInstAlias*>()->ResultInst;
+ }
+
+ /// ResOperands - This is the operand list that should be built for the result
+ /// MCInst.
+ SmallVector<ResOperand, 8> ResOperands;
+
+ /// Mnemonic - This is the first token of the matched instruction, its
+ /// mnemonic.
+ StringRef Mnemonic;
+
+ /// AsmOperands - The textual operands that this instruction matches,
+ /// annotated with a class and where in the OperandList they were defined.
+ /// This directly corresponds to the tokenized AsmString after the mnemonic is
+ /// removed.
+ SmallVector<AsmOperand, 8> AsmOperands;
+
+ /// Predicates - The required subtarget features to match this instruction.
+ SmallVector<const SubtargetFeatureInfo *, 4> RequiredFeatures;
+
+ /// ConversionFnKind - The enum value which is passed to the generated
+ /// convertToMCInst to convert parsed operands into an MCInst for this
+ /// function.
+ std::string ConversionFnKind;
+
+ /// If this instruction is deprecated in some form.
+ bool HasDeprecation;
+
+ /// If this is an alias, this is use to determine whether or not to using
+ /// the conversion function defined by the instruction's AsmMatchConverter
+ /// or to use the function generated by the alias.
+ bool UseInstAsmMatchConverter;
+
+ MatchableInfo(const CodeGenInstruction &CGI)
+ : AsmVariantID(0), AsmString(CGI.AsmString), TheDef(CGI.TheDef), DefRec(&CGI),
+ UseInstAsmMatchConverter(true) {
+ }
+
+ MatchableInfo(std::unique_ptr<const CodeGenInstAlias> Alias)
+ : AsmVariantID(0), AsmString(Alias->AsmString), TheDef(Alias->TheDef),
+ DefRec(Alias.release()),
+ UseInstAsmMatchConverter(
+ TheDef->getValueAsBit("UseInstAsmMatchConverter")) {
+ }
+
+ // Could remove this and the dtor if PointerUnion supported unique_ptr
+ // elements with a dynamic failure/assertion (like the one below) in the case
+ // where it was copied while being in an owning state.
+ MatchableInfo(const MatchableInfo &RHS)
+ : AsmVariantID(RHS.AsmVariantID), AsmString(RHS.AsmString),
+ TheDef(RHS.TheDef), DefRec(RHS.DefRec), ResOperands(RHS.ResOperands),
+ Mnemonic(RHS.Mnemonic), AsmOperands(RHS.AsmOperands),
+ RequiredFeatures(RHS.RequiredFeatures),
+ ConversionFnKind(RHS.ConversionFnKind),
+ HasDeprecation(RHS.HasDeprecation),
+ UseInstAsmMatchConverter(RHS.UseInstAsmMatchConverter) {
+ assert(!DefRec.is<const CodeGenInstAlias *>());
+ }
+
+ ~MatchableInfo() {
+ delete DefRec.dyn_cast<const CodeGenInstAlias*>();
+ }
+
+ // Two-operand aliases clone from the main matchable, but mark the second
+ // operand as a tied operand of the first for purposes of the assembler.
+ void formTwoOperandAlias(StringRef Constraint);
+
+ void initialize(const AsmMatcherInfo &Info,
+ SmallPtrSetImpl<Record*> &SingletonRegisters,
+ AsmVariantInfo const &Variant,
+ bool HasMnemonicFirst);
+
+ /// validate - Return true if this matchable is a valid thing to match against
+ /// and perform a bunch of validity checking.
+ bool validate(StringRef CommentDelimiter, bool Hack) const;
+
+ /// findAsmOperand - Find the AsmOperand with the specified name and
+ /// suboperand index.
+ int findAsmOperand(StringRef N, int SubOpIdx) const {
+ auto I = find_if(AsmOperands, [&](const AsmOperand &Op) {
+ return Op.SrcOpName == N && Op.SubOpIdx == SubOpIdx;
+ });
+ return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;
+ }
+
+ /// findAsmOperandNamed - Find the first AsmOperand with the specified name.
+ /// This does not check the suboperand index.
+ int findAsmOperandNamed(StringRef N) const {
+ auto I = find_if(AsmOperands,
+ [&](const AsmOperand &Op) { return Op.SrcOpName == N; });
+ return (I != AsmOperands.end()) ? I - AsmOperands.begin() : -1;
+ }
+
+ void buildInstructionResultOperands();
+ void buildAliasResultOperands();
+
+ /// operator< - Compare two matchables.
+ bool operator<(const MatchableInfo &RHS) const {
+ // The primary comparator is the instruction mnemonic.
+ if (int Cmp = Mnemonic.compare(RHS.Mnemonic))
+ return Cmp == -1;
+
+ if (AsmOperands.size() != RHS.AsmOperands.size())
+ return AsmOperands.size() < RHS.AsmOperands.size();
+
+ // Compare lexicographically by operand. The matcher validates that other
+ // orderings wouldn't be ambiguous using \see couldMatchAmbiguouslyWith().
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
+ if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class)
+ return true;
+ if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
+ return false;
+ }
+
+ // Give matches that require more features higher precedence. This is useful
+ // because we cannot define AssemblerPredicates with the negation of
+ // processor features. For example, ARM v6 "nop" may be either a HINT or
+ // MOV. With v6, we want to match HINT. The assembler has no way to
+ // predicate MOV under "NoV6", but HINT will always match first because it
+ // requires V6 while MOV does not.
+ if (RequiredFeatures.size() != RHS.RequiredFeatures.size())
+ return RequiredFeatures.size() > RHS.RequiredFeatures.size();
+
+ return false;
+ }
+
+ /// couldMatchAmbiguouslyWith - Check whether this matchable could
+ /// ambiguously match the same set of operands as \p RHS (without being a
+ /// strictly superior match).
+ bool couldMatchAmbiguouslyWith(const MatchableInfo &RHS) const {
+ // The primary comparator is the instruction mnemonic.
+ if (Mnemonic != RHS.Mnemonic)
+ return false;
+
+ // The number of operands is unambiguous.
+ if (AsmOperands.size() != RHS.AsmOperands.size())
+ return false;
+
+ // Otherwise, make sure the ordering of the two instructions is unambiguous
+ // by checking that either (a) a token or operand kind discriminates them,
+ // or (b) the ordering among equivalent kinds is consistent.
+
+ // Tokens and operand kinds are unambiguous (assuming a correct target
+ // specific parser).
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i)
+ if (AsmOperands[i].Class->Kind != RHS.AsmOperands[i].Class->Kind ||
+ AsmOperands[i].Class->Kind == ClassInfo::Token)
+ if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class ||
+ *RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
+ return false;
+
+ // Otherwise, this operand could commute if all operands are equivalent, or
+ // there is a pair of operands that compare less than and a pair that
+ // compare greater than.
+ bool HasLT = false, HasGT = false;
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
+ if (*AsmOperands[i].Class < *RHS.AsmOperands[i].Class)
+ HasLT = true;
+ if (*RHS.AsmOperands[i].Class < *AsmOperands[i].Class)
+ HasGT = true;
+ }
+
+ return HasLT == HasGT;
+ }
+
+ void dump() const;
+
+private:
+ void tokenizeAsmString(AsmMatcherInfo const &Info,
+ AsmVariantInfo const &Variant);
+ void addAsmOperand(StringRef Token, bool IsIsolatedToken = false);
+};
+
+struct OperandMatchEntry {
+ unsigned OperandMask;
+ const MatchableInfo* MI;
+ ClassInfo *CI;
+
+ static OperandMatchEntry create(const MatchableInfo *mi, ClassInfo *ci,
+ unsigned opMask) {
+ OperandMatchEntry X;
+ X.OperandMask = opMask;
+ X.CI = ci;
+ X.MI = mi;
+ return X;
+ }
+};
+
+class AsmMatcherInfo {
+public:
+ /// Tracked Records
+ RecordKeeper &Records;
+
+ /// The tablegen AsmParser record.
+ Record *AsmParser;
+
+ /// Target - The target information.
+ CodeGenTarget &Target;
+
+ /// The classes which are needed for matching.
+ std::forward_list<ClassInfo> Classes;
+
+ /// The information on the matchables to match.
+ std::vector<std::unique_ptr<MatchableInfo>> Matchables;
+
+ /// Info for custom matching operands by user defined methods.
+ std::vector<OperandMatchEntry> OperandMatchInfo;
+
+ /// Map of Register records to their class information.
+ typedef std::map<Record*, ClassInfo*, LessRecordByID> RegisterClassesTy;
+ RegisterClassesTy RegisterClasses;
+
+ /// Map of Predicate records to their subtarget information.
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
+
+ /// Map of AsmOperandClass records to their class information.
+ std::map<Record*, ClassInfo*> AsmOperandClasses;
+
+private:
+ /// Map of token to class information which has already been constructed.
+ std::map<std::string, ClassInfo*> TokenClasses;
+
+ /// Map of RegisterClass records to their class information.
+ std::map<Record*, ClassInfo*> RegisterClassClasses;
+
+private:
+ /// getTokenClass - Lookup or create the class for the given token.
+ ClassInfo *getTokenClass(StringRef Token);
+
+ /// getOperandClass - Lookup or create the class for the given operand.
+ ClassInfo *getOperandClass(const CGIOperandList::OperandInfo &OI,
+ int SubOpIdx);
+ ClassInfo *getOperandClass(Record *Rec, int SubOpIdx);
+
+ /// buildRegisterClasses - Build the ClassInfo* instances for register
+ /// classes.
+ void buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters);
+
+ /// buildOperandClasses - Build the ClassInfo* instances for user defined
+ /// operand classes.
+ void buildOperandClasses();
+
+ void buildInstructionOperandReference(MatchableInfo *II, StringRef OpName,
+ unsigned AsmOpIdx);
+ void buildAliasOperandReference(MatchableInfo *II, StringRef OpName,
+ MatchableInfo::AsmOperand &Op);
+
+public:
+ AsmMatcherInfo(Record *AsmParser,
+ CodeGenTarget &Target,
+ RecordKeeper &Records);
+
+ /// Construct the various tables used during matching.
+ void buildInfo();
+
+ /// buildOperandMatchInfo - Build the necessary information to handle user
+ /// defined operand parsing methods.
+ void buildOperandMatchInfo();
+
+ /// getSubtargetFeature - Lookup or create the subtarget feature info for the
+ /// given operand.
+ const SubtargetFeatureInfo *getSubtargetFeature(Record *Def) const {
+ assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
+ const auto &I = SubtargetFeatures.find(Def);
+ return I == SubtargetFeatures.end() ? nullptr : &I->second;
+ }
+
+ RecordKeeper &getRecords() const {
+ return Records;
+ }
+
+ bool hasOptionalOperands() const {
+ return find_if(Classes, [](const ClassInfo &Class) {
+ return Class.IsOptional;
+ }) != Classes.end();
+ }
+};
+
+} // end anonymous namespace
+
+void MatchableInfo::dump() const {
+ errs() << TheDef->getName() << " -- " << "flattened:\"" << AsmString <<"\"\n";
+
+ for (unsigned i = 0, e = AsmOperands.size(); i != e; ++i) {
+ const AsmOperand &Op = AsmOperands[i];
+ errs() << " op[" << i << "] = " << Op.Class->ClassName << " - ";
+ errs() << '\"' << Op.Token << "\"\n";
+ }
+}
+
+static std::pair<StringRef, StringRef>
+parseTwoOperandConstraint(StringRef S, ArrayRef<SMLoc> Loc) {
+ // Split via the '='.
+ std::pair<StringRef, StringRef> Ops = S.split('=');
+ if (Ops.second == "")
+ PrintFatalError(Loc, "missing '=' in two-operand alias constraint");
+ // Trim whitespace and the leading '$' on the operand names.
+ size_t start = Ops.first.find_first_of('$');
+ if (start == std::string::npos)
+ PrintFatalError(Loc, "expected '$' prefix on asm operand name");
+ Ops.first = Ops.first.slice(start + 1, std::string::npos);
+ size_t end = Ops.first.find_last_of(" \t");
+ Ops.first = Ops.first.slice(0, end);
+ // Now the second operand.
+ start = Ops.second.find_first_of('$');
+ if (start == std::string::npos)
+ PrintFatalError(Loc, "expected '$' prefix on asm operand name");
+ Ops.second = Ops.second.slice(start + 1, std::string::npos);
+ end = Ops.second.find_last_of(" \t");
+ Ops.first = Ops.first.slice(0, end);
+ return Ops;
+}
+
+void MatchableInfo::formTwoOperandAlias(StringRef Constraint) {
+ // Figure out which operands are aliased and mark them as tied.
+ std::pair<StringRef, StringRef> Ops =
+ parseTwoOperandConstraint(Constraint, TheDef->getLoc());
+
+ // Find the AsmOperands that refer to the operands we're aliasing.
+ int SrcAsmOperand = findAsmOperandNamed(Ops.first);
+ int DstAsmOperand = findAsmOperandNamed(Ops.second);
+ if (SrcAsmOperand == -1)
+ PrintFatalError(TheDef->getLoc(),
+ "unknown source two-operand alias operand '" + Ops.first +
+ "'.");
+ if (DstAsmOperand == -1)
+ PrintFatalError(TheDef->getLoc(),
+ "unknown destination two-operand alias operand '" +
+ Ops.second + "'.");
+
+ // Find the ResOperand that refers to the operand we're aliasing away
+ // and update it to refer to the combined operand instead.
+ for (ResOperand &Op : ResOperands) {
+ if (Op.Kind == ResOperand::RenderAsmOperand &&
+ Op.AsmOperandNum == (unsigned)SrcAsmOperand) {
+ Op.AsmOperandNum = DstAsmOperand;
+ break;
+ }
+ }
+ // Remove the AsmOperand for the alias operand.
+ AsmOperands.erase(AsmOperands.begin() + SrcAsmOperand);
+ // Adjust the ResOperand references to any AsmOperands that followed
+ // the one we just deleted.
+ for (ResOperand &Op : ResOperands) {
+ switch(Op.Kind) {
+ default:
+ // Nothing to do for operands that don't reference AsmOperands.
+ break;
+ case ResOperand::RenderAsmOperand:
+ if (Op.AsmOperandNum > (unsigned)SrcAsmOperand)
+ --Op.AsmOperandNum;
+ break;
+ case ResOperand::TiedOperand:
+ if (Op.TiedOperandNum > (unsigned)SrcAsmOperand)
+ --Op.TiedOperandNum;
+ break;
+ }
+ }
+}
+
+/// extractSingletonRegisterForAsmOperand - Extract singleton register,
+/// if present, from specified token.
+static void
+extractSingletonRegisterForAsmOperand(MatchableInfo::AsmOperand &Op,
+ const AsmMatcherInfo &Info,
+ StringRef RegisterPrefix) {
+ StringRef Tok = Op.Token;
+
+ // If this token is not an isolated token, i.e., it isn't separated from
+ // other tokens (e.g. with whitespace), don't interpret it as a register name.
+ if (!Op.IsIsolatedToken)
+ return;
+
+ if (RegisterPrefix.empty()) {
+ std::string LoweredTok = Tok.lower();
+ if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(LoweredTok))
+ Op.SingletonReg = Reg->TheDef;
+ return;
+ }
+
+ if (!Tok.startswith(RegisterPrefix))
+ return;
+
+ StringRef RegName = Tok.substr(RegisterPrefix.size());
+ if (const CodeGenRegister *Reg = Info.Target.getRegisterByName(RegName))
+ Op.SingletonReg = Reg->TheDef;
+
+ // If there is no register prefix (i.e. "%" in "%eax"), then this may
+ // be some random non-register token, just ignore it.
+}
+
+void MatchableInfo::initialize(const AsmMatcherInfo &Info,
+ SmallPtrSetImpl<Record*> &SingletonRegisters,
+ AsmVariantInfo const &Variant,
+ bool HasMnemonicFirst) {
+ AsmVariantID = Variant.AsmVariantNo;
+ AsmString =
+ CodeGenInstruction::FlattenAsmStringVariants(AsmString,
+ Variant.AsmVariantNo);
+
+ tokenizeAsmString(Info, Variant);
+
+ // The first token of the instruction is the mnemonic, which must be a
+ // simple string, not a $foo variable or a singleton register.
+ if (AsmOperands.empty())
+ PrintFatalError(TheDef->getLoc(),
+ "Instruction '" + TheDef->getName() + "' has no tokens");
+
+ assert(!AsmOperands[0].Token.empty());
+ if (HasMnemonicFirst) {
+ Mnemonic = AsmOperands[0].Token;
+ if (Mnemonic[0] == '$')
+ PrintFatalError(TheDef->getLoc(),
+ "Invalid instruction mnemonic '" + Mnemonic + "'!");
+
+ // Remove the first operand, it is tracked in the mnemonic field.
+ AsmOperands.erase(AsmOperands.begin());
+ } else if (AsmOperands[0].Token[0] != '$')
+ Mnemonic = AsmOperands[0].Token;
+
+ // Compute the require features.
+ for (Record *Predicate : TheDef->getValueAsListOfDefs("Predicates"))
+ if (const SubtargetFeatureInfo *Feature =
+ Info.getSubtargetFeature(Predicate))
+ RequiredFeatures.push_back(Feature);
+
+ // Collect singleton registers, if used.
+ for (MatchableInfo::AsmOperand &Op : AsmOperands) {
+ extractSingletonRegisterForAsmOperand(Op, Info, Variant.RegisterPrefix);
+ if (Record *Reg = Op.SingletonReg)
+ SingletonRegisters.insert(Reg);
+ }
+
+ const RecordVal *DepMask = TheDef->getValue("DeprecatedFeatureMask");
+ if (!DepMask)
+ DepMask = TheDef->getValue("ComplexDeprecationPredicate");
+
+ HasDeprecation =
+ DepMask ? !DepMask->getValue()->getAsUnquotedString().empty() : false;
+}
+
+/// Append an AsmOperand for the given substring of AsmString.
+void MatchableInfo::addAsmOperand(StringRef Token, bool IsIsolatedToken) {
+ AsmOperands.push_back(AsmOperand(IsIsolatedToken, Token));
+}
+
+/// tokenizeAsmString - Tokenize a simplified assembly string.
+void MatchableInfo::tokenizeAsmString(const AsmMatcherInfo &Info,
+ AsmVariantInfo const &Variant) {
+ StringRef String = AsmString;
+ size_t Prev = 0;
+ bool InTok = false;
+ bool IsIsolatedToken = true;
+ for (size_t i = 0, e = String.size(); i != e; ++i) {
+ char Char = String[i];
+ if (Variant.BreakCharacters.find(Char) != std::string::npos) {
+ if (InTok) {
+ addAsmOperand(String.slice(Prev, i), false);
+ Prev = i;
+ IsIsolatedToken = false;
+ }
+ InTok = true;
+ continue;
+ }
+ if (Variant.TokenizingCharacters.find(Char) != std::string::npos) {
+ if (InTok) {
+ addAsmOperand(String.slice(Prev, i), IsIsolatedToken);
+ InTok = false;
+ IsIsolatedToken = false;
+ }
+ addAsmOperand(String.slice(i, i + 1), IsIsolatedToken);
+ Prev = i + 1;
+ IsIsolatedToken = true;
+ continue;
+ }
+ if (Variant.SeparatorCharacters.find(Char) != std::string::npos) {
+ if (InTok) {
+ addAsmOperand(String.slice(Prev, i), IsIsolatedToken);
+ InTok = false;
+ }
+ Prev = i + 1;
+ IsIsolatedToken = true;
+ continue;
+ }
+
+ switch (Char) {
+ case '\\':
+ if (InTok) {
+ addAsmOperand(String.slice(Prev, i), false);
+ InTok = false;
+ IsIsolatedToken = false;
+ }
+ ++i;
+ assert(i != String.size() && "Invalid quoted character");
+ addAsmOperand(String.slice(i, i + 1), IsIsolatedToken);
+ Prev = i + 1;
+ IsIsolatedToken = false;
+ break;
+
+ case '$': {
+ if (InTok) {
+ addAsmOperand(String.slice(Prev, i), false);
+ InTok = false;
+ IsIsolatedToken = false;
+ }
+
+ // If this isn't "${", start new identifier looking like "$xxx"
+ if (i + 1 == String.size() || String[i + 1] != '{') {
+ Prev = i;
+ break;
+ }
+
+ size_t EndPos = String.find('}', i);
+ assert(EndPos != StringRef::npos &&
+ "Missing brace in operand reference!");
+ addAsmOperand(String.slice(i, EndPos+1), IsIsolatedToken);
+ Prev = EndPos + 1;
+ i = EndPos;
+ IsIsolatedToken = false;
+ break;
+ }
+
+ default:
+ InTok = true;
+ break;
+ }
+ }
+ if (InTok && Prev != String.size())
+ addAsmOperand(String.substr(Prev), IsIsolatedToken);
+}
+
+bool MatchableInfo::validate(StringRef CommentDelimiter, bool Hack) const {
+ // Reject matchables with no .s string.
+ if (AsmString.empty())
+ PrintFatalError(TheDef->getLoc(), "instruction with empty asm string");
+
+ // Reject any matchables with a newline in them, they should be marked
+ // isCodeGenOnly if they are pseudo instructions.
+ if (AsmString.find('\n') != std::string::npos)
+ PrintFatalError(TheDef->getLoc(),
+ "multiline instruction is not valid for the asmparser, "
+ "mark it isCodeGenOnly");
+
+ // Remove comments from the asm string. We know that the asmstring only
+ // has one line.
+ if (!CommentDelimiter.empty() &&
+ StringRef(AsmString).find(CommentDelimiter) != StringRef::npos)
+ PrintFatalError(TheDef->getLoc(),
+ "asmstring for instruction has comment character in it, "
+ "mark it isCodeGenOnly");
+
+ // Reject matchables with operand modifiers, these aren't something we can
+ // handle, the target should be refactored to use operands instead of
+ // modifiers.
+ //
+ // Also, check for instructions which reference the operand multiple times;
+ // this implies a constraint we would not honor.
+ std::set<std::string> OperandNames;
+ for (const AsmOperand &Op : AsmOperands) {
+ StringRef Tok = Op.Token;
+ if (Tok[0] == '$' && Tok.find(':') != StringRef::npos)
+ PrintFatalError(TheDef->getLoc(),
+ "matchable with operand modifier '" + Tok +
+ "' not supported by asm matcher. Mark isCodeGenOnly!");
+
+ // Verify that any operand is only mentioned once.
+ // We reject aliases and ignore instructions for now.
+ if (Tok[0] == '$' && !OperandNames.insert(Tok).second) {
+ if (!Hack)
+ PrintFatalError(TheDef->getLoc(),
+ "ERROR: matchable with tied operand '" + Tok +
+ "' can never be matched!");
+ // FIXME: Should reject these. The ARM backend hits this with $lane in a
+ // bunch of instructions. It is unclear what the right answer is.
+ DEBUG({
+ errs() << "warning: '" << TheDef->getName() << "': "
+ << "ignoring instruction with tied operand '"
+ << Tok << "'\n";
+ });
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static std::string getEnumNameForToken(StringRef Str) {
+ std::string Res;
+
+ for (StringRef::iterator it = Str.begin(), ie = Str.end(); it != ie; ++it) {
+ switch (*it) {
+ case '*': Res += "_STAR_"; break;
+ case '%': Res += "_PCT_"; break;
+ case ':': Res += "_COLON_"; break;
+ case '!': Res += "_EXCLAIM_"; break;
+ case '.': Res += "_DOT_"; break;
+ case '<': Res += "_LT_"; break;
+ case '>': Res += "_GT_"; break;
+ case '-': Res += "_MINUS_"; break;
+ default:
+ if ((*it >= 'A' && *it <= 'Z') ||
+ (*it >= 'a' && *it <= 'z') ||
+ (*it >= '0' && *it <= '9'))
+ Res += *it;
+ else
+ Res += "_" + utostr((unsigned) *it) + "_";
+ }
+ }
+
+ return Res;
+}
+
+ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
+ ClassInfo *&Entry = TokenClasses[Token];
+
+ if (!Entry) {
+ Classes.emplace_front();
+ Entry = &Classes.front();
+ Entry->Kind = ClassInfo::Token;
+ Entry->ClassName = "Token";
+ Entry->Name = "MCK_" + getEnumNameForToken(Token);
+ Entry->ValueName = Token;
+ Entry->PredicateMethod = "<invalid>";
+ Entry->RenderMethod = "<invalid>";
+ Entry->ParserMethod = "";
+ Entry->DiagnosticType = "";
+ Entry->IsOptional = false;
+ Entry->DefaultMethod = "<invalid>";
+ }
+
+ return Entry;
+}
+
+ClassInfo *
+AsmMatcherInfo::getOperandClass(const CGIOperandList::OperandInfo &OI,
+ int SubOpIdx) {
+ Record *Rec = OI.Rec;
+ if (SubOpIdx != -1)
+ Rec = cast<DefInit>(OI.MIOperandInfo->getArg(SubOpIdx))->getDef();
+ return getOperandClass(Rec, SubOpIdx);
+}
+
+ClassInfo *
+AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) {
+ if (Rec->isSubClassOf("RegisterOperand")) {
+ // RegisterOperand may have an associated ParserMatchClass. If it does,
+ // use it, else just fall back to the underlying register class.
+ const RecordVal *R = Rec->getValue("ParserMatchClass");
+ if (!R || !R->getValue())
+ PrintFatalError("Record `" + Rec->getName() +
+ "' does not have a ParserMatchClass!\n");
+
+ if (DefInit *DI= dyn_cast<DefInit>(R->getValue())) {
+ Record *MatchClass = DI->getDef();
+ if (ClassInfo *CI = AsmOperandClasses[MatchClass])
+ return CI;
+ }
+
+ // No custom match class. Just use the register class.
+ Record *ClassRec = Rec->getValueAsDef("RegClass");
+ if (!ClassRec)
+ PrintFatalError(Rec->getLoc(), "RegisterOperand `" + Rec->getName() +
+ "' has no associated register class!\n");
+ if (ClassInfo *CI = RegisterClassClasses[ClassRec])
+ return CI;
+ PrintFatalError(Rec->getLoc(), "register class has no class info!");
+ }
+
+ if (Rec->isSubClassOf("RegisterClass")) {
+ if (ClassInfo *CI = RegisterClassClasses[Rec])
+ return CI;
+ PrintFatalError(Rec->getLoc(), "register class has no class info!");
+ }
+
+ if (!Rec->isSubClassOf("Operand"))
+ PrintFatalError(Rec->getLoc(), "Operand `" + Rec->getName() +
+ "' does not derive from class Operand!\n");
+ Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
+ if (ClassInfo *CI = AsmOperandClasses[MatchClass])
+ return CI;
+
+ PrintFatalError(Rec->getLoc(), "operand has no match class!");
+}
+
+struct LessRegisterSet {
+ bool operator() (const RegisterSet &LHS, const RegisterSet & RHS) const {
+ // std::set<T> defines its own compariso "operator<", but it
+ // performs a lexicographical comparison by T's innate comparison
+ // for some reason. We don't want non-deterministic pointer
+ // comparisons so use this instead.
+ return std::lexicographical_compare(LHS.begin(), LHS.end(),
+ RHS.begin(), RHS.end(),
+ LessRecordByID());
+ }
+};
+
+void AsmMatcherInfo::
+buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
+ const auto &Registers = Target.getRegBank().getRegisters();
+ auto &RegClassList = Target.getRegBank().getRegClasses();
+
+ typedef std::set<RegisterSet, LessRegisterSet> RegisterSetSet;
+
+ // The register sets used for matching.
+ RegisterSetSet RegisterSets;
+
+ // Gather the defined sets.
+ for (const CodeGenRegisterClass &RC : RegClassList)
+ RegisterSets.insert(
+ RegisterSet(RC.getOrder().begin(), RC.getOrder().end()));
+
+ // Add any required singleton sets.
+ for (Record *Rec : SingletonRegisters) {
+ RegisterSets.insert(RegisterSet(&Rec, &Rec + 1));
+ }
+
+ // Introduce derived sets where necessary (when a register does not determine
+ // a unique register set class), and build the mapping of registers to the set
+ // they should classify to.
+ std::map<Record*, RegisterSet> RegisterMap;
+ for (const CodeGenRegister &CGR : Registers) {
+ // Compute the intersection of all sets containing this register.
+ RegisterSet ContainingSet;
+
+ for (const RegisterSet &RS : RegisterSets) {
+ if (!RS.count(CGR.TheDef))
+ continue;
+
+ if (ContainingSet.empty()) {
+ ContainingSet = RS;
+ continue;
+ }
+
+ RegisterSet Tmp;
+ std::swap(Tmp, ContainingSet);
+ std::insert_iterator<RegisterSet> II(ContainingSet,
+ ContainingSet.begin());
+ std::set_intersection(Tmp.begin(), Tmp.end(), RS.begin(), RS.end(), II,
+ LessRecordByID());
+ }
+
+ if (!ContainingSet.empty()) {
+ RegisterSets.insert(ContainingSet);
+ RegisterMap.insert(std::make_pair(CGR.TheDef, ContainingSet));
+ }
+ }
+
+ // Construct the register classes.
+ std::map<RegisterSet, ClassInfo*, LessRegisterSet> RegisterSetClasses;
+ unsigned Index = 0;
+ for (const RegisterSet &RS : RegisterSets) {
+ Classes.emplace_front();
+ ClassInfo *CI = &Classes.front();
+ CI->Kind = ClassInfo::RegisterClass0 + Index;
+ CI->ClassName = "Reg" + utostr(Index);
+ CI->Name = "MCK_Reg" + utostr(Index);
+ CI->ValueName = "";
+ CI->PredicateMethod = ""; // unused
+ CI->RenderMethod = "addRegOperands";
+ CI->Registers = RS;
+ // FIXME: diagnostic type.
+ CI->DiagnosticType = "";
+ CI->IsOptional = false;
+ CI->DefaultMethod = ""; // unused
+ RegisterSetClasses.insert(std::make_pair(RS, CI));
+ ++Index;
+ }
+
+ // Find the superclasses; we could compute only the subgroup lattice edges,
+ // but there isn't really a point.
+ for (const RegisterSet &RS : RegisterSets) {
+ ClassInfo *CI = RegisterSetClasses[RS];
+ for (const RegisterSet &RS2 : RegisterSets)
+ if (RS != RS2 &&
+ std::includes(RS2.begin(), RS2.end(), RS.begin(), RS.end(),
+ LessRecordByID()))
+ CI->SuperClasses.push_back(RegisterSetClasses[RS2]);
+ }
+
+ // Name the register classes which correspond to a user defined RegisterClass.
+ for (const CodeGenRegisterClass &RC : RegClassList) {
+ // Def will be NULL for non-user defined register classes.
+ Record *Def = RC.getDef();
+ if (!Def)
+ continue;
+ ClassInfo *CI = RegisterSetClasses[RegisterSet(RC.getOrder().begin(),
+ RC.getOrder().end())];
+ if (CI->ValueName.empty()) {
+ CI->ClassName = RC.getName();
+ CI->Name = "MCK_" + RC.getName();
+ CI->ValueName = RC.getName();
+ } else
+ CI->ValueName = CI->ValueName + "," + RC.getName();
+
+ RegisterClassClasses.insert(std::make_pair(Def, CI));
+ }
+
+ // Populate the map for individual registers.
+ for (std::map<Record*, RegisterSet>::iterator it = RegisterMap.begin(),
+ ie = RegisterMap.end(); it != ie; ++it)
+ RegisterClasses[it->first] = RegisterSetClasses[it->second];
+
+ // Name the register classes which correspond to singleton registers.
+ for (Record *Rec : SingletonRegisters) {
+ ClassInfo *CI = RegisterClasses[Rec];
+ assert(CI && "Missing singleton register class info!");
+
+ if (CI->ValueName.empty()) {
+ CI->ClassName = Rec->getName();
+ CI->Name = "MCK_" + Rec->getName().str();
+ CI->ValueName = Rec->getName();
+ } else
+ CI->ValueName = CI->ValueName + "," + Rec->getName().str();
+ }
+}
+
+void AsmMatcherInfo::buildOperandClasses() {
+ std::vector<Record*> AsmOperands =
+ Records.getAllDerivedDefinitions("AsmOperandClass");
+
+ // Pre-populate AsmOperandClasses map.
+ for (Record *Rec : AsmOperands) {
+ Classes.emplace_front();
+ AsmOperandClasses[Rec] = &Classes.front();
+ }
+
+ unsigned Index = 0;
+ for (Record *Rec : AsmOperands) {
+ ClassInfo *CI = AsmOperandClasses[Rec];
+ CI->Kind = ClassInfo::UserClass0 + Index;
+
+ ListInit *Supers = Rec->getValueAsListInit("SuperClasses");
+ for (Init *I : Supers->getValues()) {
+ DefInit *DI = dyn_cast<DefInit>(I);
+ if (!DI) {
+ PrintError(Rec->getLoc(), "Invalid super class reference!");
+ continue;
+ }
+
+ ClassInfo *SC = AsmOperandClasses[DI->getDef()];
+ if (!SC)
+ PrintError(Rec->getLoc(), "Invalid super class reference!");
+ else
+ CI->SuperClasses.push_back(SC);
+ }
+ CI->ClassName = Rec->getValueAsString("Name");
+ CI->Name = "MCK_" + CI->ClassName;
+ CI->ValueName = Rec->getName();
+
+ // Get or construct the predicate method name.
+ Init *PMName = Rec->getValueInit("PredicateMethod");
+ if (StringInit *SI = dyn_cast<StringInit>(PMName)) {
+ CI->PredicateMethod = SI->getValue();
+ } else {
+ assert(isa<UnsetInit>(PMName) && "Unexpected PredicateMethod field!");
+ CI->PredicateMethod = "is" + CI->ClassName;
+ }
+
+ // Get or construct the render method name.
+ Init *RMName = Rec->getValueInit("RenderMethod");
+ if (StringInit *SI = dyn_cast<StringInit>(RMName)) {
+ CI->RenderMethod = SI->getValue();
+ } else {
+ assert(isa<UnsetInit>(RMName) && "Unexpected RenderMethod field!");
+ CI->RenderMethod = "add" + CI->ClassName + "Operands";
+ }
+
+ // Get the parse method name or leave it as empty.
+ Init *PRMName = Rec->getValueInit("ParserMethod");
+ if (StringInit *SI = dyn_cast<StringInit>(PRMName))
+ CI->ParserMethod = SI->getValue();
+
+ // Get the diagnostic type or leave it as empty.
+ // Get the parse method name or leave it as empty.
+ Init *DiagnosticType = Rec->getValueInit("DiagnosticType");
+ if (StringInit *SI = dyn_cast<StringInit>(DiagnosticType))
+ CI->DiagnosticType = SI->getValue();
+
+ Init *IsOptional = Rec->getValueInit("IsOptional");
+ if (BitInit *BI = dyn_cast<BitInit>(IsOptional))
+ CI->IsOptional = BI->getValue();
+
+ // Get or construct the default method name.
+ Init *DMName = Rec->getValueInit("DefaultMethod");
+ if (StringInit *SI = dyn_cast<StringInit>(DMName)) {
+ CI->DefaultMethod = SI->getValue();
+ } else {
+ assert(isa<UnsetInit>(DMName) && "Unexpected DefaultMethod field!");
+ CI->DefaultMethod = "default" + CI->ClassName + "Operands";
+ }
+
+ ++Index;
+ }
+}
+
+AsmMatcherInfo::AsmMatcherInfo(Record *asmParser,
+ CodeGenTarget &target,
+ RecordKeeper &records)
+ : Records(records), AsmParser(asmParser), Target(target) {
+}
+
+/// buildOperandMatchInfo - Build the necessary information to handle user
+/// defined operand parsing methods.
+void AsmMatcherInfo::buildOperandMatchInfo() {
+
+ /// Map containing a mask with all operands indices that can be found for
+ /// that class inside a instruction.
+ typedef std::map<ClassInfo *, unsigned, less_ptr<ClassInfo>> OpClassMaskTy;
+ OpClassMaskTy OpClassMask;
+
+ for (const auto &MI : Matchables) {
+ OpClassMask.clear();
+
+ // Keep track of all operands of this instructions which belong to the
+ // same class.
+ for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) {
+ const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i];
+ if (Op.Class->ParserMethod.empty())
+ continue;
+ unsigned &OperandMask = OpClassMask[Op.Class];
+ OperandMask |= (1 << i);
+ }
+
+ // Generate operand match info for each mnemonic/operand class pair.
+ for (const auto &OCM : OpClassMask) {
+ unsigned OpMask = OCM.second;
+ ClassInfo *CI = OCM.first;
+ OperandMatchInfo.push_back(OperandMatchEntry::create(MI.get(), CI,
+ OpMask));
+ }
+ }
+}
+
+void AsmMatcherInfo::buildInfo() {
+ // Build information about all of the AssemblerPredicates.
+ const std::vector<std::pair<Record *, SubtargetFeatureInfo>>
+ &SubtargetFeaturePairs = SubtargetFeatureInfo::getAll(Records);
+ SubtargetFeatures.insert(SubtargetFeaturePairs.begin(),
+ SubtargetFeaturePairs.end());
+#ifndef NDEBUG
+ for (const auto &Pair : SubtargetFeatures)
+ DEBUG(Pair.second.dump());
+#endif // NDEBUG
+ assert(SubtargetFeatures.size() <= 64 && "Too many subtarget features!");
+
+ bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");
+
+ // Parse the instructions; we need to do this first so that we can gather the
+ // singleton register classes.
+ SmallPtrSet<Record*, 16> SingletonRegisters;
+ unsigned VariantCount = Target.getAsmParserVariantCount();
+ for (unsigned VC = 0; VC != VariantCount; ++VC) {
+ Record *AsmVariant = Target.getAsmParserVariant(VC);
+ std::string CommentDelimiter =
+ AsmVariant->getValueAsString("CommentDelimiter");
+ AsmVariantInfo Variant;
+ Variant.RegisterPrefix = AsmVariant->getValueAsString("RegisterPrefix");
+ Variant.TokenizingCharacters =
+ AsmVariant->getValueAsString("TokenizingCharacters");
+ Variant.SeparatorCharacters =
+ AsmVariant->getValueAsString("SeparatorCharacters");
+ Variant.BreakCharacters =
+ AsmVariant->getValueAsString("BreakCharacters");
+ Variant.Name = AsmVariant->getValueAsString("Name");
+ Variant.AsmVariantNo = AsmVariant->getValueAsInt("Variant");
+
+ for (const CodeGenInstruction *CGI : Target.getInstructionsByEnumValue()) {
+
+ // If the tblgen -match-prefix option is specified (for tblgen hackers),
+ // filter the set of instructions we consider.
+ if (!StringRef(CGI->TheDef->getName()).startswith(MatchPrefix))
+ continue;
+
+ // Ignore "codegen only" instructions.
+ if (CGI->TheDef->getValueAsBit("isCodeGenOnly"))
+ continue;
+
+ // Ignore instructions for different instructions
+ const std::string V = CGI->TheDef->getValueAsString("AsmVariantName");
+ if (!V.empty() && V != Variant.Name)
+ continue;
+
+ auto II = llvm::make_unique<MatchableInfo>(*CGI);
+
+ II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);
+
+ // Ignore instructions which shouldn't be matched and diagnose invalid
+ // instruction definitions with an error.
+ if (!II->validate(CommentDelimiter, true))
+ continue;
+
+ Matchables.push_back(std::move(II));
+ }
+
+ // Parse all of the InstAlias definitions and stick them in the list of
+ // matchables.
+ std::vector<Record*> AllInstAliases =
+ Records.getAllDerivedDefinitions("InstAlias");
+ for (unsigned i = 0, e = AllInstAliases.size(); i != e; ++i) {
+ auto Alias = llvm::make_unique<CodeGenInstAlias>(AllInstAliases[i],
+ Variant.AsmVariantNo,
+ Target);
+
+ // If the tblgen -match-prefix option is specified (for tblgen hackers),
+ // filter the set of instruction aliases we consider, based on the target
+ // instruction.
+ if (!StringRef(Alias->ResultInst->TheDef->getName())
+ .startswith( MatchPrefix))
+ continue;
+
+ const std::string V = Alias->TheDef->getValueAsString("AsmVariantName");
+ if (!V.empty() && V != Variant.Name)
+ continue;
+
+ auto II = llvm::make_unique<MatchableInfo>(std::move(Alias));
+
+ II->initialize(*this, SingletonRegisters, Variant, HasMnemonicFirst);
+
+ // Validate the alias definitions.
+ II->validate(CommentDelimiter, false);
+
+ Matchables.push_back(std::move(II));
+ }
+ }
+
+ // Build info for the register classes.
+ buildRegisterClasses(SingletonRegisters);
+
+ // Build info for the user defined assembly operand classes.
+ buildOperandClasses();
+
+ // Build the information about matchables, now that we have fully formed
+ // classes.
+ std::vector<std::unique_ptr<MatchableInfo>> NewMatchables;
+ for (auto &II : Matchables) {
+ // Parse the tokens after the mnemonic.
+ // Note: buildInstructionOperandReference may insert new AsmOperands, so
+ // don't precompute the loop bound.
+ for (unsigned i = 0; i != II->AsmOperands.size(); ++i) {
+ MatchableInfo::AsmOperand &Op = II->AsmOperands[i];
+ StringRef Token = Op.Token;
+
+ // Check for singleton registers.
+ if (Record *RegRecord = Op.SingletonReg) {
+ Op.Class = RegisterClasses[RegRecord];
+ assert(Op.Class && Op.Class->Registers.size() == 1 &&
+ "Unexpected class for singleton register");
+ continue;
+ }
+
+ // Check for simple tokens.
+ if (Token[0] != '$') {
+ Op.Class = getTokenClass(Token);
+ continue;
+ }
+
+ if (Token.size() > 1 && isdigit(Token[1])) {
+ Op.Class = getTokenClass(Token);
+ continue;
+ }
+
+ // Otherwise this is an operand reference.
+ StringRef OperandName;
+ if (Token[1] == '{')
+ OperandName = Token.substr(2, Token.size() - 3);
+ else
+ OperandName = Token.substr(1);
+
+ if (II->DefRec.is<const CodeGenInstruction*>())
+ buildInstructionOperandReference(II.get(), OperandName, i);
+ else
+ buildAliasOperandReference(II.get(), OperandName, Op);
+ }
+
+ if (II->DefRec.is<const CodeGenInstruction*>()) {
+ II->buildInstructionResultOperands();
+ // If the instruction has a two-operand alias, build up the
+ // matchable here. We'll add them in bulk at the end to avoid
+ // confusing this loop.
+ std::string Constraint =
+ II->TheDef->getValueAsString("TwoOperandAliasConstraint");
+ if (Constraint != "") {
+ // Start by making a copy of the original matchable.
+ auto AliasII = llvm::make_unique<MatchableInfo>(*II);
+
+ // Adjust it to be a two-operand alias.
+ AliasII->formTwoOperandAlias(Constraint);
+
+ // Add the alias to the matchables list.
+ NewMatchables.push_back(std::move(AliasII));
+ }
+ } else
+ II->buildAliasResultOperands();
+ }
+ if (!NewMatchables.empty())
+ Matchables.insert(Matchables.end(),
+ std::make_move_iterator(NewMatchables.begin()),
+ std::make_move_iterator(NewMatchables.end()));
+
+ // Process token alias definitions and set up the associated superclass
+ // information.
+ std::vector<Record*> AllTokenAliases =
+ Records.getAllDerivedDefinitions("TokenAlias");
+ for (Record *Rec : AllTokenAliases) {
+ ClassInfo *FromClass = getTokenClass(Rec->getValueAsString("FromToken"));
+ ClassInfo *ToClass = getTokenClass(Rec->getValueAsString("ToToken"));
+ if (FromClass == ToClass)
+ PrintFatalError(Rec->getLoc(),
+ "error: Destination value identical to source value.");
+ FromClass->SuperClasses.push_back(ToClass);
+ }
+
+ // Reorder classes so that classes precede super classes.
+ Classes.sort();
+
+#ifdef EXPENSIVE_CHECKS
+ // Verify that the table is sorted and operator < works transitively.
+ for (auto I = Classes.begin(), E = Classes.end(); I != E; ++I) {
+ for (auto J = I; J != E; ++J) {
+ assert(!(*J < *I));
+ assert(I == J || !J->isSubsetOf(*I));
+ }
+ }
+#endif
+}
+
+/// buildInstructionOperandReference - The specified operand is a reference to a
+/// named operand such as $src. Resolve the Class and OperandInfo pointers.
+void AsmMatcherInfo::
+buildInstructionOperandReference(MatchableInfo *II,
+ StringRef OperandName,
+ unsigned AsmOpIdx) {
+ const CodeGenInstruction &CGI = *II->DefRec.get<const CodeGenInstruction*>();
+ const CGIOperandList &Operands = CGI.Operands;
+ MatchableInfo::AsmOperand *Op = &II->AsmOperands[AsmOpIdx];
+
+ // Map this token to an operand.
+ unsigned Idx;
+ if (!Operands.hasOperandNamed(OperandName, Idx))
+ PrintFatalError(II->TheDef->getLoc(),
+ "error: unable to find operand: '" + OperandName + "'");
+
+ // If the instruction operand has multiple suboperands, but the parser
+ // match class for the asm operand is still the default "ImmAsmOperand",
+ // then handle each suboperand separately.
+ if (Op->SubOpIdx == -1 && Operands[Idx].MINumOperands > 1) {
+ Record *Rec = Operands[Idx].Rec;
+ assert(Rec->isSubClassOf("Operand") && "Unexpected operand!");
+ Record *MatchClass = Rec->getValueAsDef("ParserMatchClass");
+ if (MatchClass && MatchClass->getValueAsString("Name") == "Imm") {
+ // Insert remaining suboperands after AsmOpIdx in II->AsmOperands.
+ StringRef Token = Op->Token; // save this in case Op gets moved
+ for (unsigned SI = 1, SE = Operands[Idx].MINumOperands; SI != SE; ++SI) {
+ MatchableInfo::AsmOperand NewAsmOp(/*IsIsolatedToken=*/true, Token);
+ NewAsmOp.SubOpIdx = SI;
+ II->AsmOperands.insert(II->AsmOperands.begin()+AsmOpIdx+SI, NewAsmOp);
+ }
+ // Replace Op with first suboperand.
+ Op = &II->AsmOperands[AsmOpIdx]; // update the pointer in case it moved
+ Op->SubOpIdx = 0;
+ }
+ }
+
+ // Set up the operand class.
+ Op->Class = getOperandClass(Operands[Idx], Op->SubOpIdx);
+
+ // If the named operand is tied, canonicalize it to the untied operand.
+ // For example, something like:
+ // (outs GPR:$dst), (ins GPR:$src)
+ // with an asmstring of
+ // "inc $src"
+ // we want to canonicalize to:
+ // "inc $dst"
+ // so that we know how to provide the $dst operand when filling in the result.
+ int OITied = -1;
+ if (Operands[Idx].MINumOperands == 1)
+ OITied = Operands[Idx].getTiedRegister();
+ if (OITied != -1) {
+ // The tied operand index is an MIOperand index, find the operand that
+ // contains it.
+ std::pair<unsigned, unsigned> Idx = Operands.getSubOperandNumber(OITied);
+ OperandName = Operands[Idx.first].Name;
+ Op->SubOpIdx = Idx.second;
+ }
+
+ Op->SrcOpName = OperandName;
+}
+
+/// buildAliasOperandReference - When parsing an operand reference out of the
+/// matching string (e.g. "movsx $src, $dst"), determine what the class of the
+/// operand reference is by looking it up in the result pattern definition.
+void AsmMatcherInfo::buildAliasOperandReference(MatchableInfo *II,
+ StringRef OperandName,
+ MatchableInfo::AsmOperand &Op) {
+ const CodeGenInstAlias &CGA = *II->DefRec.get<const CodeGenInstAlias*>();
+
+ // Set up the operand class.
+ for (unsigned i = 0, e = CGA.ResultOperands.size(); i != e; ++i)
+ if (CGA.ResultOperands[i].isRecord() &&
+ CGA.ResultOperands[i].getName() == OperandName) {
+ // It's safe to go with the first one we find, because CodeGenInstAlias
+ // validates that all operands with the same name have the same record.
+ Op.SubOpIdx = CGA.ResultInstOperandIndex[i].second;
+ // Use the match class from the Alias definition, not the
+ // destination instruction, as we may have an immediate that's
+ // being munged by the match class.
+ Op.Class = getOperandClass(CGA.ResultOperands[i].getRecord(),
+ Op.SubOpIdx);
+ Op.SrcOpName = OperandName;
+ return;
+ }
+
+ PrintFatalError(II->TheDef->getLoc(),
+ "error: unable to find operand: '" + OperandName + "'");
+}
+
+void MatchableInfo::buildInstructionResultOperands() {
+ const CodeGenInstruction *ResultInst = getResultInst();
+
+ // Loop over all operands of the result instruction, determining how to
+ // populate them.
+ for (const CGIOperandList::OperandInfo &OpInfo : ResultInst->Operands) {
+ // If this is a tied operand, just copy from the previously handled operand.
+ int TiedOp = -1;
+ if (OpInfo.MINumOperands == 1)
+ TiedOp = OpInfo.getTiedRegister();
+ if (TiedOp != -1) {
+ ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
+ continue;
+ }
+
+ // Find out what operand from the asmparser this MCInst operand comes from.
+ int SrcOperand = findAsmOperandNamed(OpInfo.Name);
+ if (OpInfo.Name.empty() || SrcOperand == -1) {
+ // This may happen for operands that are tied to a suboperand of a
+ // complex operand. Simply use a dummy value here; nobody should
+ // use this operand slot.
+ // FIXME: The long term goal is for the MCOperand list to not contain
+ // tied operands at all.
+ ResOperands.push_back(ResOperand::getImmOp(0));
+ continue;
+ }
+
+ // Check if the one AsmOperand populates the entire operand.
+ unsigned NumOperands = OpInfo.MINumOperands;
+ if (AsmOperands[SrcOperand].SubOpIdx == -1) {
+ ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand, NumOperands));
+ continue;
+ }
+
+ // Add a separate ResOperand for each suboperand.
+ for (unsigned AI = 0; AI < NumOperands; ++AI) {
+ assert(AsmOperands[SrcOperand+AI].SubOpIdx == (int)AI &&
+ AsmOperands[SrcOperand+AI].SrcOpName == OpInfo.Name &&
+ "unexpected AsmOperands for suboperands");
+ ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand + AI, 1));
+ }
+ }
+}
+
+void MatchableInfo::buildAliasResultOperands() {
+ const CodeGenInstAlias &CGA = *DefRec.get<const CodeGenInstAlias*>();
+ const CodeGenInstruction *ResultInst = getResultInst();
+
+ // Loop over all operands of the result instruction, determining how to
+ // populate them.
+ unsigned AliasOpNo = 0;
+ unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
+ for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
+ const CGIOperandList::OperandInfo *OpInfo = &ResultInst->Operands[i];
+
+ // If this is a tied operand, just copy from the previously handled operand.
+ int TiedOp = -1;
+ if (OpInfo->MINumOperands == 1)
+ TiedOp = OpInfo->getTiedRegister();
+ if (TiedOp != -1) {
+ ResOperands.push_back(ResOperand::getTiedOp(TiedOp));
+ continue;
+ }
+
+ // Handle all the suboperands for this operand.
+ const std::string &OpName = OpInfo->Name;
+ for ( ; AliasOpNo < LastOpNo &&
+ CGA.ResultInstOperandIndex[AliasOpNo].first == i; ++AliasOpNo) {
+ int SubIdx = CGA.ResultInstOperandIndex[AliasOpNo].second;
+
+ // Find out what operand from the asmparser that this MCInst operand
+ // comes from.
+ switch (CGA.ResultOperands[AliasOpNo].Kind) {
+ case CodeGenInstAlias::ResultOperand::K_Record: {
+ StringRef Name = CGA.ResultOperands[AliasOpNo].getName();
+ int SrcOperand = findAsmOperand(Name, SubIdx);
+ if (SrcOperand == -1)
+ PrintFatalError(TheDef->getLoc(), "Instruction '" +
+ TheDef->getName() + "' has operand '" + OpName +
+ "' that doesn't appear in asm string!");
+ unsigned NumOperands = (SubIdx == -1 ? OpInfo->MINumOperands : 1);
+ ResOperands.push_back(ResOperand::getRenderedOp(SrcOperand,
+ NumOperands));
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Imm: {
+ int64_t ImmVal = CGA.ResultOperands[AliasOpNo].getImm();
+ ResOperands.push_back(ResOperand::getImmOp(ImmVal));
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Reg: {
+ Record *Reg = CGA.ResultOperands[AliasOpNo].getRegister();
+ ResOperands.push_back(ResOperand::getRegOp(Reg));
+ break;
+ }
+ }
+ }
+ }
+}
+
+static unsigned
+getConverterOperandID(const std::string &Name,
+ SmallSetVector<CachedHashString, 16> &Table,
+ bool &IsNew) {
+ IsNew = Table.insert(CachedHashString(Name));
+
+ unsigned ID = IsNew ? Table.size() - 1 : find(Table, Name) - Table.begin();
+
+ assert(ID < Table.size());
+
+ return ID;
+}
+
+static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
+ std::vector<std::unique_ptr<MatchableInfo>> &Infos,
+ bool HasMnemonicFirst, bool HasOptionalOperands,
+ raw_ostream &OS) {
+ SmallSetVector<CachedHashString, 16> OperandConversionKinds;
+ SmallSetVector<CachedHashString, 16> InstructionConversionKinds;
+ std::vector<std::vector<uint8_t> > ConversionTable;
+ size_t MaxRowLength = 2; // minimum is custom converter plus terminator.
+
+ // TargetOperandClass - This is the target's operand class, like X86Operand.
+ std::string TargetOperandClass = Target.getName().str() + "Operand";
+
+ // Write the convert function to a separate stream, so we can drop it after
+ // the enum. We'll build up the conversion handlers for the individual
+ // operand types opportunistically as we encounter them.
+ std::string ConvertFnBody;
+ raw_string_ostream CvtOS(ConvertFnBody);
+ // Start the unified conversion function.
+ if (HasOptionalOperands) {
+ CvtOS << "void " << Target.getName() << ClassName << "::\n"
+ << "convertToMCInst(unsigned Kind, MCInst &Inst, "
+ << "unsigned Opcode,\n"
+ << " const OperandVector &Operands,\n"
+ << " const SmallBitVector &OptionalOperandsMask) {\n";
+ } else {
+ CvtOS << "void " << Target.getName() << ClassName << "::\n"
+ << "convertToMCInst(unsigned Kind, MCInst &Inst, "
+ << "unsigned Opcode,\n"
+ << " const OperandVector &Operands) {\n";
+ }
+ CvtOS << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n";
+ CvtOS << " const uint8_t *Converter = ConversionTable[Kind];\n";
+ if (HasOptionalOperands) {
+ CvtOS << " unsigned NumDefaults = 0;\n";
+ }
+ CvtOS << " unsigned OpIdx;\n";
+ CvtOS << " Inst.setOpcode(Opcode);\n";
+ CvtOS << " for (const uint8_t *p = Converter; *p; p+= 2) {\n";
+ if (HasOptionalOperands) {
+ CvtOS << " OpIdx = *(p + 1) - NumDefaults;\n";
+ } else {
+ CvtOS << " OpIdx = *(p + 1);\n";
+ }
+ CvtOS << " switch (*p) {\n";
+ CvtOS << " default: llvm_unreachable(\"invalid conversion entry!\");\n";
+ CvtOS << " case CVT_Reg:\n";
+ CvtOS << " static_cast<" << TargetOperandClass
+ << "&>(*Operands[OpIdx]).addRegOperands(Inst, 1);\n";
+ CvtOS << " break;\n";
+ CvtOS << " case CVT_Tied:\n";
+ CvtOS << " Inst.addOperand(Inst.getOperand(OpIdx));\n";
+ CvtOS << " break;\n";
+
+ std::string OperandFnBody;
+ raw_string_ostream OpOS(OperandFnBody);
+ // Start the operand number lookup function.
+ OpOS << "void " << Target.getName() << ClassName << "::\n"
+ << "convertToMapAndConstraints(unsigned Kind,\n";
+ OpOS.indent(27);
+ OpOS << "const OperandVector &Operands) {\n"
+ << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n"
+ << " unsigned NumMCOperands = 0;\n"
+ << " const uint8_t *Converter = ConversionTable[Kind];\n"
+ << " for (const uint8_t *p = Converter; *p; p+= 2) {\n"
+ << " switch (*p) {\n"
+ << " default: llvm_unreachable(\"invalid conversion entry!\");\n"
+ << " case CVT_Reg:\n"
+ << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"
+ << " Operands[*(p + 1)]->setConstraint(\"r\");\n"
+ << " ++NumMCOperands;\n"
+ << " break;\n"
+ << " case CVT_Tied:\n"
+ << " ++NumMCOperands;\n"
+ << " break;\n";
+
+ // Pre-populate the operand conversion kinds with the standard always
+ // available entries.
+ OperandConversionKinds.insert(CachedHashString("CVT_Done"));
+ OperandConversionKinds.insert(CachedHashString("CVT_Reg"));
+ OperandConversionKinds.insert(CachedHashString("CVT_Tied"));
+ enum { CVT_Done, CVT_Reg, CVT_Tied };
+
+ for (auto &II : Infos) {
+ // Check if we have a custom match function.
+ std::string AsmMatchConverter =
+ II->getResultInst()->TheDef->getValueAsString("AsmMatchConverter");
+ if (!AsmMatchConverter.empty() && II->UseInstAsmMatchConverter) {
+ std::string Signature = "ConvertCustom_" + AsmMatchConverter;
+ II->ConversionFnKind = Signature;
+
+ // Check if we have already generated this signature.
+ if (!InstructionConversionKinds.insert(CachedHashString(Signature)))
+ continue;
+
+ // Remember this converter for the kind enum.
+ unsigned KindID = OperandConversionKinds.size();
+ OperandConversionKinds.insert(
+ CachedHashString("CVT_" + getEnumNameForToken(AsmMatchConverter)));
+
+ // Add the converter row for this instruction.
+ ConversionTable.emplace_back();
+ ConversionTable.back().push_back(KindID);
+ ConversionTable.back().push_back(CVT_Done);
+
+ // Add the handler to the conversion driver function.
+ CvtOS << " case CVT_"
+ << getEnumNameForToken(AsmMatchConverter) << ":\n"
+ << " " << AsmMatchConverter << "(Inst, Operands);\n"
+ << " break;\n";
+
+ // FIXME: Handle the operand number lookup for custom match functions.
+ continue;
+ }
+
+ // Build the conversion function signature.
+ std::string Signature = "Convert";
+
+ std::vector<uint8_t> ConversionRow;
+
+ // Compute the convert enum and the case body.
+ MaxRowLength = std::max(MaxRowLength, II->ResOperands.size()*2 + 1 );
+
+ for (unsigned i = 0, e = II->ResOperands.size(); i != e; ++i) {
+ const MatchableInfo::ResOperand &OpInfo = II->ResOperands[i];
+
+ // Generate code to populate each result operand.
+ switch (OpInfo.Kind) {
+ case MatchableInfo::ResOperand::RenderAsmOperand: {
+ // This comes from something we parsed.
+ const MatchableInfo::AsmOperand &Op =
+ II->AsmOperands[OpInfo.AsmOperandNum];
+
+ // Registers are always converted the same, don't duplicate the
+ // conversion function based on them.
+ Signature += "__";
+ std::string Class;
+ Class = Op.Class->isRegisterClass() ? "Reg" : Op.Class->ClassName;
+ Signature += Class;
+ Signature += utostr(OpInfo.MINumOperands);
+ Signature += "_" + itostr(OpInfo.AsmOperandNum);
+
+ // Add the conversion kind, if necessary, and get the associated ID
+ // the index of its entry in the vector).
+ std::string Name = "CVT_" + (Op.Class->isRegisterClass() ? "Reg" :
+ Op.Class->RenderMethod);
+ if (Op.Class->IsOptional) {
+ // For optional operands we must also care about DefaultMethod
+ assert(HasOptionalOperands);
+ Name += "_" + Op.Class->DefaultMethod;
+ }
+ Name = getEnumNameForToken(Name);
+
+ bool IsNewConverter = false;
+ unsigned ID = getConverterOperandID(Name, OperandConversionKinds,
+ IsNewConverter);
+
+ // Add the operand entry to the instruction kind conversion row.
+ ConversionRow.push_back(ID);
+ ConversionRow.push_back(OpInfo.AsmOperandNum + HasMnemonicFirst);
+
+ if (!IsNewConverter)
+ break;
+
+ // This is a new operand kind. Add a handler for it to the
+ // converter driver.
+ CvtOS << " case " << Name << ":\n";
+ if (Op.Class->IsOptional) {
+ // If optional operand is not present in actual instruction then we
+ // should call its DefaultMethod before RenderMethod
+ assert(HasOptionalOperands);
+ CvtOS << " if (OptionalOperandsMask[*(p + 1) - 1]) {\n"
+ << " " << Op.Class->DefaultMethod << "()"
+ << "->" << Op.Class->RenderMethod << "(Inst, "
+ << OpInfo.MINumOperands << ");\n"
+ << " ++NumDefaults;\n"
+ << " } else {\n"
+ << " static_cast<" << TargetOperandClass
+ << "&>(*Operands[OpIdx])." << Op.Class->RenderMethod
+ << "(Inst, " << OpInfo.MINumOperands << ");\n"
+ << " }\n";
+ } else {
+ CvtOS << " static_cast<" << TargetOperandClass
+ << "&>(*Operands[OpIdx])." << Op.Class->RenderMethod
+ << "(Inst, " << OpInfo.MINumOperands << ");\n";
+ }
+ CvtOS << " break;\n";
+
+ // Add a handler for the operand number lookup.
+ OpOS << " case " << Name << ":\n"
+ << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n";
+
+ if (Op.Class->isRegisterClass())
+ OpOS << " Operands[*(p + 1)]->setConstraint(\"r\");\n";
+ else
+ OpOS << " Operands[*(p + 1)]->setConstraint(\"m\");\n";
+ OpOS << " NumMCOperands += " << OpInfo.MINumOperands << ";\n"
+ << " break;\n";
+ break;
+ }
+ case MatchableInfo::ResOperand::TiedOperand: {
+ // If this operand is tied to a previous one, just copy the MCInst
+ // operand from the earlier one.We can only tie single MCOperand values.
+ assert(OpInfo.MINumOperands == 1 && "Not a singular MCOperand");
+ unsigned TiedOp = OpInfo.TiedOperandNum;
+ assert(i > TiedOp && "Tied operand precedes its target!");
+ Signature += "__Tie" + utostr(TiedOp);
+ ConversionRow.push_back(CVT_Tied);
+ ConversionRow.push_back(TiedOp);
+ break;
+ }
+ case MatchableInfo::ResOperand::ImmOperand: {
+ int64_t Val = OpInfo.ImmVal;
+ std::string Ty = "imm_" + itostr(Val);
+ Ty = getEnumNameForToken(Ty);
+ Signature += "__" + Ty;
+
+ std::string Name = "CVT_" + Ty;
+ bool IsNewConverter = false;
+ unsigned ID = getConverterOperandID(Name, OperandConversionKinds,
+ IsNewConverter);
+ // Add the operand entry to the instruction kind conversion row.
+ ConversionRow.push_back(ID);
+ ConversionRow.push_back(0);
+
+ if (!IsNewConverter)
+ break;
+
+ CvtOS << " case " << Name << ":\n"
+ << " Inst.addOperand(MCOperand::createImm(" << Val << "));\n"
+ << " break;\n";
+
+ OpOS << " case " << Name << ":\n"
+ << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"
+ << " Operands[*(p + 1)]->setConstraint(\"\");\n"
+ << " ++NumMCOperands;\n"
+ << " break;\n";
+ break;
+ }
+ case MatchableInfo::ResOperand::RegOperand: {
+ std::string Reg, Name;
+ if (!OpInfo.Register) {
+ Name = "reg0";
+ Reg = "0";
+ } else {
+ Reg = getQualifiedName(OpInfo.Register);
+ Name = "reg" + OpInfo.Register->getName().str();
+ }
+ Signature += "__" + Name;
+ Name = "CVT_" + Name;
+ bool IsNewConverter = false;
+ unsigned ID = getConverterOperandID(Name, OperandConversionKinds,
+ IsNewConverter);
+ // Add the operand entry to the instruction kind conversion row.
+ ConversionRow.push_back(ID);
+ ConversionRow.push_back(0);
+
+ if (!IsNewConverter)
+ break;
+ CvtOS << " case " << Name << ":\n"
+ << " Inst.addOperand(MCOperand::createReg(" << Reg << "));\n"
+ << " break;\n";
+
+ OpOS << " case " << Name << ":\n"
+ << " Operands[*(p + 1)]->setMCOperandNum(NumMCOperands);\n"
+ << " Operands[*(p + 1)]->setConstraint(\"m\");\n"
+ << " ++NumMCOperands;\n"
+ << " break;\n";
+ }
+ }
+ }
+
+ // If there were no operands, add to the signature to that effect
+ if (Signature == "Convert")
+ Signature += "_NoOperands";
+
+ II->ConversionFnKind = Signature;
+
+ // Save the signature. If we already have it, don't add a new row
+ // to the table.
+ if (!InstructionConversionKinds.insert(CachedHashString(Signature)))
+ continue;
+
+ // Add the row to the table.
+ ConversionTable.push_back(std::move(ConversionRow));
+ }
+
+ // Finish up the converter driver function.
+ CvtOS << " }\n }\n}\n\n";
+
+ // Finish up the operand number lookup function.
+ OpOS << " }\n }\n}\n\n";
+
+ OS << "namespace {\n";
+
+ // Output the operand conversion kind enum.
+ OS << "enum OperatorConversionKind {\n";
+ for (const auto &Converter : OperandConversionKinds)
+ OS << " " << Converter << ",\n";
+ OS << " CVT_NUM_CONVERTERS\n";
+ OS << "};\n\n";
+
+ // Output the instruction conversion kind enum.
+ OS << "enum InstructionConversionKind {\n";
+ for (const auto &Signature : InstructionConversionKinds)
+ OS << " " << Signature << ",\n";
+ OS << " CVT_NUM_SIGNATURES\n";
+ OS << "};\n\n";
+
+ OS << "} // end anonymous namespace\n\n";
+
+ // Output the conversion table.
+ OS << "static const uint8_t ConversionTable[CVT_NUM_SIGNATURES]["
+ << MaxRowLength << "] = {\n";
+
+ for (unsigned Row = 0, ERow = ConversionTable.size(); Row != ERow; ++Row) {
+ assert(ConversionTable[Row].size() % 2 == 0 && "bad conversion row!");
+ OS << " // " << InstructionConversionKinds[Row] << "\n";
+ OS << " { ";
+ for (unsigned i = 0, e = ConversionTable[Row].size(); i != e; i += 2)
+ OS << OperandConversionKinds[ConversionTable[Row][i]] << ", "
+ << (unsigned)(ConversionTable[Row][i + 1]) << ", ";
+ OS << "CVT_Done },\n";
+ }
+
+ OS << "};\n\n";
+
+ // Spit out the conversion driver function.
+ OS << CvtOS.str();
+
+ // Spit out the operand number lookup function.
+ OS << OpOS.str();
+}
+
+/// emitMatchClassEnumeration - Emit the enumeration for match class kinds.
+static void emitMatchClassEnumeration(CodeGenTarget &Target,
+ std::forward_list<ClassInfo> &Infos,
+ raw_ostream &OS) {
+ OS << "namespace {\n\n";
+
+ OS << "/// MatchClassKind - The kinds of classes which participate in\n"
+ << "/// instruction matching.\n";
+ OS << "enum MatchClassKind {\n";
+ OS << " InvalidMatchClass = 0,\n";
+ OS << " OptionalMatchClass = 1,\n";
+ for (const auto &CI : Infos) {
+ OS << " " << CI.Name << ", // ";
+ if (CI.Kind == ClassInfo::Token) {
+ OS << "'" << CI.ValueName << "'\n";
+ } else if (CI.isRegisterClass()) {
+ if (!CI.ValueName.empty())
+ OS << "register class '" << CI.ValueName << "'\n";
+ else
+ OS << "derived register class\n";
+ } else {
+ OS << "user defined class '" << CI.ValueName << "'\n";
+ }
+ }
+ OS << " NumMatchClassKinds\n";
+ OS << "};\n\n";
+
+ OS << "}\n\n";
+}
+
+/// emitValidateOperandClass - Emit the function to validate an operand class.
+static void emitValidateOperandClass(AsmMatcherInfo &Info,
+ raw_ostream &OS) {
+ OS << "static unsigned validateOperandClass(MCParsedAsmOperand &GOp, "
+ << "MatchClassKind Kind) {\n";
+ OS << " " << Info.Target.getName() << "Operand &Operand = ("
+ << Info.Target.getName() << "Operand&)GOp;\n";
+
+ // The InvalidMatchClass is not to match any operand.
+ OS << " if (Kind == InvalidMatchClass)\n";
+ OS << " return MCTargetAsmParser::Match_InvalidOperand;\n\n";
+
+ // Check for Token operands first.
+ // FIXME: Use a more specific diagnostic type.
+ OS << " if (Operand.isToken())\n";
+ OS << " return isSubclass(matchTokenString(Operand.getToken()), Kind) ?\n"
+ << " MCTargetAsmParser::Match_Success :\n"
+ << " MCTargetAsmParser::Match_InvalidOperand;\n\n";
+
+ // Check the user classes. We don't care what order since we're only
+ // actually matching against one of them.
+ OS << " switch (Kind) {\n"
+ " default: break;\n";
+ for (const auto &CI : Info.Classes) {
+ if (!CI.isUserClass())
+ continue;
+
+ OS << " // '" << CI.ClassName << "' class\n";
+ OS << " case " << CI.Name << ":\n";
+ OS << " if (Operand." << CI.PredicateMethod << "())\n";
+ OS << " return MCTargetAsmParser::Match_Success;\n";
+ if (!CI.DiagnosticType.empty())
+ OS << " return " << Info.Target.getName() << "AsmParser::Match_"
+ << CI.DiagnosticType << ";\n";
+ else
+ OS << " break;\n";
+ }
+ OS << " } // end switch (Kind)\n\n";
+
+ // Check for register operands, including sub-classes.
+ OS << " if (Operand.isReg()) {\n";
+ OS << " MatchClassKind OpKind;\n";
+ OS << " switch (Operand.getReg()) {\n";
+ OS << " default: OpKind = InvalidMatchClass; break;\n";
+ for (const auto &RC : Info.RegisterClasses)
+ OS << " case " << Info.Target.getName() << "::"
+ << RC.first->getName() << ": OpKind = " << RC.second->Name
+ << "; break;\n";
+ OS << " }\n";
+ OS << " return isSubclass(OpKind, Kind) ? "
+ << "MCTargetAsmParser::Match_Success :\n "
+ << " MCTargetAsmParser::Match_InvalidOperand;\n }\n\n";
+
+ // Generic fallthrough match failure case for operands that don't have
+ // specialized diagnostic types.
+ OS << " return MCTargetAsmParser::Match_InvalidOperand;\n";
+ OS << "}\n\n";
+}
+
+/// emitIsSubclass - Emit the subclass predicate function.
+static void emitIsSubclass(CodeGenTarget &Target,
+ std::forward_list<ClassInfo> &Infos,
+ raw_ostream &OS) {
+ OS << "/// isSubclass - Compute whether \\p A is a subclass of \\p B.\n";
+ OS << "static bool isSubclass(MatchClassKind A, MatchClassKind B) {\n";
+ OS << " if (A == B)\n";
+ OS << " return true;\n\n";
+
+ bool EmittedSwitch = false;
+ for (const auto &A : Infos) {
+ std::vector<StringRef> SuperClasses;
+ if (A.IsOptional)
+ SuperClasses.push_back("OptionalMatchClass");
+ for (const auto &B : Infos) {
+ if (&A != &B && A.isSubsetOf(B))
+ SuperClasses.push_back(B.Name);
+ }
+
+ if (SuperClasses.empty())
+ continue;
+
+ // If this is the first SuperClass, emit the switch header.
+ if (!EmittedSwitch) {
+ OS << " switch (A) {\n";
+ OS << " default:\n";
+ OS << " return false;\n";
+ EmittedSwitch = true;
+ }
+
+ OS << "\n case " << A.Name << ":\n";
+
+ if (SuperClasses.size() == 1) {
+ OS << " return B == " << SuperClasses.back() << ";\n";
+ continue;
+ }
+
+ if (!SuperClasses.empty()) {
+ OS << " switch (B) {\n";
+ OS << " default: return false;\n";
+ for (StringRef SC : SuperClasses)
+ OS << " case " << SC << ": return true;\n";
+ OS << " }\n";
+ } else {
+ // No case statement to emit
+ OS << " return false;\n";
+ }
+ }
+
+ // If there were case statements emitted into the string stream write the
+ // default.
+ if (EmittedSwitch)
+ OS << " }\n";
+ else
+ OS << " return false;\n";
+
+ OS << "}\n\n";
+}
+
+/// emitMatchTokenString - Emit the function to match a token string to the
+/// appropriate match class value.
+static void emitMatchTokenString(CodeGenTarget &Target,
+ std::forward_list<ClassInfo> &Infos,
+ raw_ostream &OS) {
+ // Construct the match list.
+ std::vector<StringMatcher::StringPair> Matches;
+ for (const auto &CI : Infos) {
+ if (CI.Kind == ClassInfo::Token)
+ Matches.emplace_back(CI.ValueName, "return " + CI.Name + ";");
+ }
+
+ OS << "static MatchClassKind matchTokenString(StringRef Name) {\n";
+
+ StringMatcher("Name", Matches, OS).Emit();
+
+ OS << " return InvalidMatchClass;\n";
+ OS << "}\n\n";
+}
+
+/// emitMatchRegisterName - Emit the function to match a string to the target
+/// specific register enum.
+static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
+ raw_ostream &OS) {
+ // Construct the match list.
+ std::vector<StringMatcher::StringPair> Matches;
+ const auto &Regs = Target.getRegBank().getRegisters();
+ for (const CodeGenRegister &Reg : Regs) {
+ if (Reg.TheDef->getValueAsString("AsmName").empty())
+ continue;
+
+ Matches.emplace_back(Reg.TheDef->getValueAsString("AsmName"),
+ "return " + utostr(Reg.EnumValue) + ";");
+ }
+
+ OS << "static unsigned MatchRegisterName(StringRef Name) {\n";
+
+ StringMatcher("Name", Matches, OS).Emit();
+
+ OS << " return 0;\n";
+ OS << "}\n\n";
+}
+
+/// Emit the function to match a string to the target
+/// specific register enum.
+static void emitMatchRegisterAltName(CodeGenTarget &Target, Record *AsmParser,
+ raw_ostream &OS) {
+ // Construct the match list.
+ std::vector<StringMatcher::StringPair> Matches;
+ const auto &Regs = Target.getRegBank().getRegisters();
+ for (const CodeGenRegister &Reg : Regs) {
+
+ auto AltNames = Reg.TheDef->getValueAsListOfStrings("AltNames");
+
+ for (auto AltName : AltNames) {
+ AltName = StringRef(AltName).trim();
+
+ // don't handle empty alternative names
+ if (AltName.empty())
+ continue;
+
+ Matches.emplace_back(AltName,
+ "return " + utostr(Reg.EnumValue) + ";");
+ }
+ }
+
+ OS << "static unsigned MatchRegisterAltName(StringRef Name) {\n";
+
+ StringMatcher("Name", Matches, OS).Emit();
+
+ OS << " return 0;\n";
+ OS << "}\n\n";
+}
+
+/// emitOperandDiagnosticTypes - Emit the operand matching diagnostic types.
+static void emitOperandDiagnosticTypes(AsmMatcherInfo &Info, raw_ostream &OS) {
+ // Get the set of diagnostic types from all of the operand classes.
+ std::set<StringRef> Types;
+ for (const auto &OpClassEntry : Info.AsmOperandClasses) {
+ if (!OpClassEntry.second->DiagnosticType.empty())
+ Types.insert(OpClassEntry.second->DiagnosticType);
+ }
+
+ if (Types.empty()) return;
+
+ // Now emit the enum entries.
+ for (StringRef Type : Types)
+ OS << " Match_" << Type << ",\n";
+ OS << " END_OPERAND_DIAGNOSTIC_TYPES\n";
+}
+
+/// emitGetSubtargetFeatureName - Emit the helper function to get the
+/// user-level name for a subtarget feature.
+static void emitGetSubtargetFeatureName(AsmMatcherInfo &Info, raw_ostream &OS) {
+ OS << "// User-level names for subtarget features that participate in\n"
+ << "// instruction matching.\n"
+ << "static const char *getSubtargetFeatureName(uint64_t Val) {\n";
+ if (!Info.SubtargetFeatures.empty()) {
+ OS << " switch(Val) {\n";
+ for (const auto &SF : Info.SubtargetFeatures) {
+ const SubtargetFeatureInfo &SFI = SF.second;
+ // FIXME: Totally just a placeholder name to get the algorithm working.
+ OS << " case " << SFI.getEnumName() << ": return \""
+ << SFI.TheDef->getValueAsString("PredicateName") << "\";\n";
+ }
+ OS << " default: return \"(unknown)\";\n";
+ OS << " }\n";
+ } else {
+ // Nothing to emit, so skip the switch
+ OS << " return \"(unknown)\";\n";
+ }
+ OS << "}\n\n";
+}
+
+static std::string GetAliasRequiredFeatures(Record *R,
+ const AsmMatcherInfo &Info) {
+ std::vector<Record*> ReqFeatures = R->getValueAsListOfDefs("Predicates");
+ std::string Result;
+ unsigned NumFeatures = 0;
+ for (unsigned i = 0, e = ReqFeatures.size(); i != e; ++i) {
+ const SubtargetFeatureInfo *F = Info.getSubtargetFeature(ReqFeatures[i]);
+
+ if (!F)
+ PrintFatalError(R->getLoc(), "Predicate '" + ReqFeatures[i]->getName() +
+ "' is not marked as an AssemblerPredicate!");
+
+ if (NumFeatures)
+ Result += '|';
+
+ Result += F->getEnumName();
+ ++NumFeatures;
+ }
+
+ if (NumFeatures > 1)
+ Result = '(' + Result + ')';
+ return Result;
+}
+
+static void emitMnemonicAliasVariant(raw_ostream &OS,const AsmMatcherInfo &Info,
+ std::vector<Record*> &Aliases,
+ unsigned Indent = 0,
+ StringRef AsmParserVariantName = StringRef()){
+ // Keep track of all the aliases from a mnemonic. Use an std::map so that the
+ // iteration order of the map is stable.
+ std::map<std::string, std::vector<Record*> > AliasesFromMnemonic;
+
+ for (Record *R : Aliases) {
+ // FIXME: Allow AssemblerVariantName to be a comma separated list.
+ std::string AsmVariantName = R->getValueAsString("AsmVariantName");
+ if (AsmVariantName != AsmParserVariantName)
+ continue;
+ AliasesFromMnemonic[R->getValueAsString("FromMnemonic")].push_back(R);
+ }
+ if (AliasesFromMnemonic.empty())
+ return;
+
+ // Process each alias a "from" mnemonic at a time, building the code executed
+ // by the string remapper.
+ std::vector<StringMatcher::StringPair> Cases;
+ for (const auto &AliasEntry : AliasesFromMnemonic) {
+ const std::vector<Record*> &ToVec = AliasEntry.second;
+
+ // Loop through each alias and emit code that handles each case. If there
+ // are two instructions without predicates, emit an error. If there is one,
+ // emit it last.
+ std::string MatchCode;
+ int AliasWithNoPredicate = -1;
+
+ for (unsigned i = 0, e = ToVec.size(); i != e; ++i) {
+ Record *R = ToVec[i];
+ std::string FeatureMask = GetAliasRequiredFeatures(R, Info);
+
+ // If this unconditionally matches, remember it for later and diagnose
+ // duplicates.
+ if (FeatureMask.empty()) {
+ if (AliasWithNoPredicate != -1) {
+ // We can't have two aliases from the same mnemonic with no predicate.
+ PrintError(ToVec[AliasWithNoPredicate]->getLoc(),
+ "two MnemonicAliases with the same 'from' mnemonic!");
+ PrintFatalError(R->getLoc(), "this is the other MnemonicAlias.");
+ }
+
+ AliasWithNoPredicate = i;
+ continue;
+ }
+ if (R->getValueAsString("ToMnemonic") == AliasEntry.first)
+ PrintFatalError(R->getLoc(), "MnemonicAlias to the same string");
+
+ if (!MatchCode.empty())
+ MatchCode += "else ";
+ MatchCode += "if ((Features & " + FeatureMask + ") == "+FeatureMask+")\n";
+ MatchCode += " Mnemonic = \"" +R->getValueAsString("ToMnemonic")+"\";\n";
+ }
+
+ if (AliasWithNoPredicate != -1) {
+ Record *R = ToVec[AliasWithNoPredicate];
+ if (!MatchCode.empty())
+ MatchCode += "else\n ";
+ MatchCode += "Mnemonic = \"" + R->getValueAsString("ToMnemonic")+"\";\n";
+ }
+
+ MatchCode += "return;";
+
+ Cases.push_back(std::make_pair(AliasEntry.first, MatchCode));
+ }
+ StringMatcher("Mnemonic", Cases, OS).Emit(Indent);
+}
+
+/// emitMnemonicAliases - If the target has any MnemonicAlias<> definitions,
+/// emit a function for them and return true, otherwise return false.
+static bool emitMnemonicAliases(raw_ostream &OS, const AsmMatcherInfo &Info,
+ CodeGenTarget &Target) {
+ // Ignore aliases when match-prefix is set.
+ if (!MatchPrefix.empty())
+ return false;
+
+ std::vector<Record*> Aliases =
+ Info.getRecords().getAllDerivedDefinitions("MnemonicAlias");
+ if (Aliases.empty()) return false;
+
+ OS << "static void applyMnemonicAliases(StringRef &Mnemonic, "
+ "uint64_t Features, unsigned VariantID) {\n";
+ OS << " switch (VariantID) {\n";
+ unsigned VariantCount = Target.getAsmParserVariantCount();
+ for (unsigned VC = 0; VC != VariantCount; ++VC) {
+ Record *AsmVariant = Target.getAsmParserVariant(VC);
+ int AsmParserVariantNo = AsmVariant->getValueAsInt("Variant");
+ std::string AsmParserVariantName = AsmVariant->getValueAsString("Name");
+ OS << " case " << AsmParserVariantNo << ":\n";
+ emitMnemonicAliasVariant(OS, Info, Aliases, /*Indent=*/2,
+ AsmParserVariantName);
+ OS << " break;\n";
+ }
+ OS << " }\n";
+
+ // Emit aliases that apply to all variants.
+ emitMnemonicAliasVariant(OS, Info, Aliases);
+
+ OS << "}\n\n";
+
+ return true;
+}
+
+static void emitCustomOperandParsing(raw_ostream &OS, CodeGenTarget &Target,
+ const AsmMatcherInfo &Info, StringRef ClassName,
+ StringToOffsetTable &StringTable,
+ unsigned MaxMnemonicIndex, bool HasMnemonicFirst) {
+ unsigned MaxMask = 0;
+ for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) {
+ MaxMask |= OMI.OperandMask;
+ }
+
+ // Emit the static custom operand parsing table;
+ OS << "namespace {\n";
+ OS << " struct OperandMatchEntry {\n";
+ OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size())
+ << " RequiredFeatures;\n";
+ OS << " " << getMinimalTypeForRange(MaxMnemonicIndex)
+ << " Mnemonic;\n";
+ OS << " " << getMinimalTypeForRange(std::distance(
+ Info.Classes.begin(), Info.Classes.end())) << " Class;\n";
+ OS << " " << getMinimalTypeForRange(MaxMask)
+ << " OperandMask;\n\n";
+ OS << " StringRef getMnemonic() const {\n";
+ OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n";
+ OS << " MnemonicTable[Mnemonic]);\n";
+ OS << " }\n";
+ OS << " };\n\n";
+
+ OS << " // Predicate for searching for an opcode.\n";
+ OS << " struct LessOpcodeOperand {\n";
+ OS << " bool operator()(const OperandMatchEntry &LHS, StringRef RHS) {\n";
+ OS << " return LHS.getMnemonic() < RHS;\n";
+ OS << " }\n";
+ OS << " bool operator()(StringRef LHS, const OperandMatchEntry &RHS) {\n";
+ OS << " return LHS < RHS.getMnemonic();\n";
+ OS << " }\n";
+ OS << " bool operator()(const OperandMatchEntry &LHS,";
+ OS << " const OperandMatchEntry &RHS) {\n";
+ OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n";
+ OS << " }\n";
+ OS << " };\n";
+
+ OS << "} // end anonymous namespace.\n\n";
+
+ OS << "static const OperandMatchEntry OperandMatchTable["
+ << Info.OperandMatchInfo.size() << "] = {\n";
+
+ OS << " /* Operand List Mask, Mnemonic, Operand Class, Features */\n";
+ for (const OperandMatchEntry &OMI : Info.OperandMatchInfo) {
+ const MatchableInfo &II = *OMI.MI;
+
+ OS << " { ";
+
+ // Write the required features mask.
+ if (!II.RequiredFeatures.empty()) {
+ for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) {
+ if (i) OS << "|";
+ OS << II.RequiredFeatures[i]->getEnumName();
+ }
+ } else
+ OS << "0";
+
+ // Store a pascal-style length byte in the mnemonic.
+ std::string LenMnemonic = char(II.Mnemonic.size()) + II.Mnemonic.str();
+ OS << ", " << StringTable.GetOrAddStringOffset(LenMnemonic, false)
+ << " /* " << II.Mnemonic << " */, ";
+
+ OS << OMI.CI->Name;
+
+ OS << ", " << OMI.OperandMask;
+ OS << " /* ";
+ bool printComma = false;
+ for (int i = 0, e = 31; i !=e; ++i)
+ if (OMI.OperandMask & (1 << i)) {
+ if (printComma)
+ OS << ", ";
+ OS << i;
+ printComma = true;
+ }
+ OS << " */";
+
+ OS << " },\n";
+ }
+ OS << "};\n\n";
+
+ // Emit the operand class switch to call the correct custom parser for
+ // the found operand class.
+ OS << "OperandMatchResultTy " << Target.getName() << ClassName << "::\n"
+ << "tryCustomParseOperand(OperandVector"
+ << " &Operands,\n unsigned MCK) {\n\n"
+ << " switch(MCK) {\n";
+
+ for (const auto &CI : Info.Classes) {
+ if (CI.ParserMethod.empty())
+ continue;
+ OS << " case " << CI.Name << ":\n"
+ << " return " << CI.ParserMethod << "(Operands);\n";
+ }
+
+ OS << " default:\n";
+ OS << " return MatchOperand_NoMatch;\n";
+ OS << " }\n";
+ OS << " return MatchOperand_NoMatch;\n";
+ OS << "}\n\n";
+
+ // Emit the static custom operand parser. This code is very similar with
+ // the other matcher. Also use MatchResultTy here just in case we go for
+ // a better error handling.
+ OS << "OperandMatchResultTy " << Target.getName() << ClassName << "::\n"
+ << "MatchOperandParserImpl(OperandVector"
+ << " &Operands,\n StringRef Mnemonic) {\n";
+
+ // Emit code to get the available features.
+ OS << " // Get the current feature set.\n";
+ OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n";
+
+ OS << " // Get the next operand index.\n";
+ OS << " unsigned NextOpNum = Operands.size()"
+ << (HasMnemonicFirst ? " - 1" : "") << ";\n";
+
+ // Emit code to search the table.
+ OS << " // Search the table.\n";
+ if (HasMnemonicFirst) {
+ OS << " auto MnemonicRange =\n";
+ OS << " std::equal_range(std::begin(OperandMatchTable), "
+ "std::end(OperandMatchTable),\n";
+ OS << " Mnemonic, LessOpcodeOperand());\n\n";
+ } else {
+ OS << " auto MnemonicRange = std::make_pair(std::begin(OperandMatchTable),"
+ " std::end(OperandMatchTable));\n";
+ OS << " if (!Mnemonic.empty())\n";
+ OS << " MnemonicRange =\n";
+ OS << " std::equal_range(std::begin(OperandMatchTable), "
+ "std::end(OperandMatchTable),\n";
+ OS << " Mnemonic, LessOpcodeOperand());\n\n";
+ }
+
+ OS << " if (MnemonicRange.first == MnemonicRange.second)\n";
+ OS << " return MatchOperand_NoMatch;\n\n";
+
+ OS << " for (const OperandMatchEntry *it = MnemonicRange.first,\n"
+ << " *ie = MnemonicRange.second; it != ie; ++it) {\n";
+
+ OS << " // equal_range guarantees that instruction mnemonic matches.\n";
+ OS << " assert(Mnemonic == it->getMnemonic());\n\n";
+
+ // Emit check that the required features are available.
+ OS << " // check if the available features match\n";
+ OS << " if ((AvailableFeatures & it->RequiredFeatures) "
+ << "!= it->RequiredFeatures) {\n";
+ OS << " continue;\n";
+ OS << " }\n\n";
+
+ // Emit check to ensure the operand number matches.
+ OS << " // check if the operand in question has a custom parser.\n";
+ OS << " if (!(it->OperandMask & (1 << NextOpNum)))\n";
+ OS << " continue;\n\n";
+
+ // Emit call to the custom parser method
+ OS << " // call custom parse method to handle the operand\n";
+ OS << " OperandMatchResultTy Result = ";
+ OS << "tryCustomParseOperand(Operands, it->Class);\n";
+ OS << " if (Result != MatchOperand_NoMatch)\n";
+ OS << " return Result;\n";
+ OS << " }\n\n";
+
+ OS << " // Okay, we had no match.\n";
+ OS << " return MatchOperand_NoMatch;\n";
+ OS << "}\n\n";
+}
+
+void AsmMatcherEmitter::run(raw_ostream &OS) {
+ CodeGenTarget Target(Records);
+ Record *AsmParser = Target.getAsmParser();
+ std::string ClassName = AsmParser->getValueAsString("AsmParserClassName");
+
+ // Compute the information on the instructions to match.
+ AsmMatcherInfo Info(AsmParser, Target, Records);
+ Info.buildInfo();
+
+ // Sort the instruction table using the partial order on classes. We use
+ // stable_sort to ensure that ambiguous instructions are still
+ // deterministically ordered.
+ std::stable_sort(Info.Matchables.begin(), Info.Matchables.end(),
+ [](const std::unique_ptr<MatchableInfo> &a,
+ const std::unique_ptr<MatchableInfo> &b){
+ return *a < *b;});
+
+#ifdef EXPENSIVE_CHECKS
+ // Verify that the table is sorted and operator < works transitively.
+ for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;
+ ++I) {
+ for (auto J = I; J != E; ++J) {
+ assert(!(**J < **I));
+ }
+ }
+#endif
+
+ DEBUG_WITH_TYPE("instruction_info", {
+ for (const auto &MI : Info.Matchables)
+ MI->dump();
+ });
+
+ // Check for ambiguous matchables.
+ DEBUG_WITH_TYPE("ambiguous_instrs", {
+ unsigned NumAmbiguous = 0;
+ for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;
+ ++I) {
+ for (auto J = std::next(I); J != E; ++J) {
+ const MatchableInfo &A = **I;
+ const MatchableInfo &B = **J;
+
+ if (A.couldMatchAmbiguouslyWith(B)) {
+ errs() << "warning: ambiguous matchables:\n";
+ A.dump();
+ errs() << "\nis incomparable with:\n";
+ B.dump();
+ errs() << "\n\n";
+ ++NumAmbiguous;
+ }
+ }
+ }
+ if (NumAmbiguous)
+ errs() << "warning: " << NumAmbiguous
+ << " ambiguous matchables!\n";
+ });
+
+ // Compute the information on the custom operand parsing.
+ Info.buildOperandMatchInfo();
+
+ bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");
+ bool HasOptionalOperands = Info.hasOptionalOperands();
+
+ // Write the output.
+
+ // Information for the class declaration.
+ OS << "\n#ifdef GET_ASSEMBLER_HEADER\n";
+ OS << "#undef GET_ASSEMBLER_HEADER\n";
+ OS << " // This should be included into the middle of the declaration of\n";
+ OS << " // your subclasses implementation of MCTargetAsmParser.\n";
+ OS << " uint64_t ComputeAvailableFeatures(const FeatureBitset& FB) const;\n";
+ if (HasOptionalOperands) {
+ OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
+ << "unsigned Opcode,\n"
+ << " const OperandVector &Operands,\n"
+ << " const SmallBitVector &OptionalOperandsMask);\n";
+ } else {
+ OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
+ << "unsigned Opcode,\n"
+ << " const OperandVector &Operands);\n";
+ }
+ OS << " void convertToMapAndConstraints(unsigned Kind,\n ";
+ OS << " const OperandVector &Operands) override;\n";
+ OS << " unsigned MatchInstructionImpl(const OperandVector &Operands,\n"
+ << " MCInst &Inst,\n"
+ << " uint64_t &ErrorInfo,"
+ << " bool matchingInlineAsm,\n"
+ << " unsigned VariantID = 0);\n";
+
+ if (!Info.OperandMatchInfo.empty()) {
+ OS << " OperandMatchResultTy MatchOperandParserImpl(\n";
+ OS << " OperandVector &Operands,\n";
+ OS << " StringRef Mnemonic);\n";
+
+ OS << " OperandMatchResultTy tryCustomParseOperand(\n";
+ OS << " OperandVector &Operands,\n";
+ OS << " unsigned MCK);\n\n";
+ }
+
+ OS << "#endif // GET_ASSEMBLER_HEADER_INFO\n\n";
+
+ // Emit the operand match diagnostic enum names.
+ OS << "\n#ifdef GET_OPERAND_DIAGNOSTIC_TYPES\n";
+ OS << "#undef GET_OPERAND_DIAGNOSTIC_TYPES\n\n";
+ emitOperandDiagnosticTypes(Info, OS);
+ OS << "#endif // GET_OPERAND_DIAGNOSTIC_TYPES\n\n";
+
+ OS << "\n#ifdef GET_REGISTER_MATCHER\n";
+ OS << "#undef GET_REGISTER_MATCHER\n\n";
+
+ // Emit the subtarget feature enumeration.
+ SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(
+ Info.SubtargetFeatures, OS);
+
+ // Emit the function to match a register name to number.
+ // This should be omitted for Mips target
+ if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterName"))
+ emitMatchRegisterName(Target, AsmParser, OS);
+
+ if (AsmParser->getValueAsBit("ShouldEmitMatchRegisterAltName"))
+ emitMatchRegisterAltName(Target, AsmParser, OS);
+
+ OS << "#endif // GET_REGISTER_MATCHER\n\n";
+
+ OS << "\n#ifdef GET_SUBTARGET_FEATURE_NAME\n";
+ OS << "#undef GET_SUBTARGET_FEATURE_NAME\n\n";
+
+ // Generate the helper function to get the names for subtarget features.
+ emitGetSubtargetFeatureName(Info, OS);
+
+ OS << "#endif // GET_SUBTARGET_FEATURE_NAME\n\n";
+
+ OS << "\n#ifdef GET_MATCHER_IMPLEMENTATION\n";
+ OS << "#undef GET_MATCHER_IMPLEMENTATION\n\n";
+
+ // Generate the function that remaps for mnemonic aliases.
+ bool HasMnemonicAliases = emitMnemonicAliases(OS, Info, Target);
+
+ // Generate the convertToMCInst function to convert operands into an MCInst.
+ // Also, generate the convertToMapAndConstraints function for MS-style inline
+ // assembly. The latter doesn't actually generate a MCInst.
+ emitConvertFuncs(Target, ClassName, Info.Matchables, HasMnemonicFirst,
+ HasOptionalOperands, OS);
+
+ // Emit the enumeration for classes which participate in matching.
+ emitMatchClassEnumeration(Target, Info.Classes, OS);
+
+ // Emit the routine to match token strings to their match class.
+ emitMatchTokenString(Target, Info.Classes, OS);
+
+ // Emit the subclass predicate routine.
+ emitIsSubclass(Target, Info.Classes, OS);
+
+ // Emit the routine to validate an operand against a match class.
+ emitValidateOperandClass(Info, OS);
+
+ // Emit the available features compute function.
+ SubtargetFeatureInfo::emitComputeAvailableFeatures(
+ Info.Target.getName(), ClassName, "ComputeAvailableFeatures",
+ Info.SubtargetFeatures, OS);
+
+ StringToOffsetTable StringTable;
+
+ size_t MaxNumOperands = 0;
+ unsigned MaxMnemonicIndex = 0;
+ bool HasDeprecation = false;
+ for (const auto &MI : Info.Matchables) {
+ MaxNumOperands = std::max(MaxNumOperands, MI->AsmOperands.size());
+ HasDeprecation |= MI->HasDeprecation;
+
+ // Store a pascal-style length byte in the mnemonic.
+ std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str();
+ MaxMnemonicIndex = std::max(MaxMnemonicIndex,
+ StringTable.GetOrAddStringOffset(LenMnemonic, false));
+ }
+
+ OS << "static const char *const MnemonicTable =\n";
+ StringTable.EmitString(OS);
+ OS << ";\n\n";
+
+ // Emit the static match table; unused classes get initialized to 0 which is
+ // guaranteed to be InvalidMatchClass.
+ //
+ // FIXME: We can reduce the size of this table very easily. First, we change
+ // it so that store the kinds in separate bit-fields for each index, which
+ // only needs to be the max width used for classes at that index (we also need
+ // to reject based on this during classification). If we then make sure to
+ // order the match kinds appropriately (putting mnemonics last), then we
+ // should only end up using a few bits for each class, especially the ones
+ // following the mnemonic.
+ OS << "namespace {\n";
+ OS << " struct MatchEntry {\n";
+ OS << " " << getMinimalTypeForRange(MaxMnemonicIndex)
+ << " Mnemonic;\n";
+ OS << " uint16_t Opcode;\n";
+ OS << " " << getMinimalTypeForRange(Info.Matchables.size())
+ << " ConvertFn;\n";
+ OS << " " << getMinimalTypeForEnumBitfield(Info.SubtargetFeatures.size())
+ << " RequiredFeatures;\n";
+ OS << " " << getMinimalTypeForRange(
+ std::distance(Info.Classes.begin(), Info.Classes.end()))
+ << " Classes[" << MaxNumOperands << "];\n";
+ OS << " StringRef getMnemonic() const {\n";
+ OS << " return StringRef(MnemonicTable + Mnemonic + 1,\n";
+ OS << " MnemonicTable[Mnemonic]);\n";
+ OS << " }\n";
+ OS << " };\n\n";
+
+ OS << " // Predicate for searching for an opcode.\n";
+ OS << " struct LessOpcode {\n";
+ OS << " bool operator()(const MatchEntry &LHS, StringRef RHS) {\n";
+ OS << " return LHS.getMnemonic() < RHS;\n";
+ OS << " }\n";
+ OS << " bool operator()(StringRef LHS, const MatchEntry &RHS) {\n";
+ OS << " return LHS < RHS.getMnemonic();\n";
+ OS << " }\n";
+ OS << " bool operator()(const MatchEntry &LHS, const MatchEntry &RHS) {\n";
+ OS << " return LHS.getMnemonic() < RHS.getMnemonic();\n";
+ OS << " }\n";
+ OS << " };\n";
+
+ OS << "} // end anonymous namespace.\n\n";
+
+ unsigned VariantCount = Target.getAsmParserVariantCount();
+ for (unsigned VC = 0; VC != VariantCount; ++VC) {
+ Record *AsmVariant = Target.getAsmParserVariant(VC);
+ int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
+
+ OS << "static const MatchEntry MatchTable" << VC << "[] = {\n";
+
+ for (const auto &MI : Info.Matchables) {
+ if (MI->AsmVariantID != AsmVariantNo)
+ continue;
+
+ // Store a pascal-style length byte in the mnemonic.
+ std::string LenMnemonic = char(MI->Mnemonic.size()) + MI->Mnemonic.str();
+ OS << " { " << StringTable.GetOrAddStringOffset(LenMnemonic, false)
+ << " /* " << MI->Mnemonic << " */, "
+ << Target.getName() << "::"
+ << MI->getResultInst()->TheDef->getName() << ", "
+ << MI->ConversionFnKind << ", ";
+
+ // Write the required features mask.
+ if (!MI->RequiredFeatures.empty()) {
+ for (unsigned i = 0, e = MI->RequiredFeatures.size(); i != e; ++i) {
+ if (i) OS << "|";
+ OS << MI->RequiredFeatures[i]->getEnumName();
+ }
+ } else
+ OS << "0";
+
+ OS << ", { ";
+ for (unsigned i = 0, e = MI->AsmOperands.size(); i != e; ++i) {
+ const MatchableInfo::AsmOperand &Op = MI->AsmOperands[i];
+
+ if (i) OS << ", ";
+ OS << Op.Class->Name;
+ }
+ OS << " }, },\n";
+ }
+
+ OS << "};\n\n";
+ }
+
+ // Finally, build the match function.
+ OS << "unsigned " << Target.getName() << ClassName << "::\n"
+ << "MatchInstructionImpl(const OperandVector &Operands,\n";
+ OS << " MCInst &Inst, uint64_t &ErrorInfo,\n"
+ << " bool matchingInlineAsm, unsigned VariantID) {\n";
+
+ OS << " // Eliminate obvious mismatches.\n";
+ OS << " if (Operands.size() > "
+ << (MaxNumOperands + HasMnemonicFirst) << ") {\n";
+ OS << " ErrorInfo = "
+ << (MaxNumOperands + HasMnemonicFirst) << ";\n";
+ OS << " return Match_InvalidOperand;\n";
+ OS << " }\n\n";
+
+ // Emit code to get the available features.
+ OS << " // Get the current feature set.\n";
+ OS << " uint64_t AvailableFeatures = getAvailableFeatures();\n\n";
+
+ OS << " // Get the instruction mnemonic, which is the first token.\n";
+ if (HasMnemonicFirst) {
+ OS << " StringRef Mnemonic = ((" << Target.getName()
+ << "Operand&)*Operands[0]).getToken();\n\n";
+ } else {
+ OS << " StringRef Mnemonic;\n";
+ OS << " if (Operands[0]->isToken())\n";
+ OS << " Mnemonic = ((" << Target.getName()
+ << "Operand&)*Operands[0]).getToken();\n\n";
+ }
+
+ if (HasMnemonicAliases) {
+ OS << " // Process all MnemonicAliases to remap the mnemonic.\n";
+ OS << " applyMnemonicAliases(Mnemonic, AvailableFeatures, VariantID);\n\n";
+ }
+
+ // Emit code to compute the class list for this operand vector.
+ OS << " // Some state to try to produce better error messages.\n";
+ OS << " bool HadMatchOtherThanFeatures = false;\n";
+ OS << " bool HadMatchOtherThanPredicate = false;\n";
+ OS << " unsigned RetCode = Match_InvalidOperand;\n";
+ OS << " uint64_t MissingFeatures = ~0ULL;\n";
+ if (HasOptionalOperands) {
+ OS << " SmallBitVector OptionalOperandsMask(" << MaxNumOperands << ");\n";
+ }
+ OS << " // Set ErrorInfo to the operand that mismatches if it is\n";
+ OS << " // wrong for all instances of the instruction.\n";
+ OS << " ErrorInfo = ~0ULL;\n";
+
+ // Emit code to search the table.
+ OS << " // Find the appropriate table for this asm variant.\n";
+ OS << " const MatchEntry *Start, *End;\n";
+ OS << " switch (VariantID) {\n";
+ OS << " default: llvm_unreachable(\"invalid variant!\");\n";
+ for (unsigned VC = 0; VC != VariantCount; ++VC) {
+ Record *AsmVariant = Target.getAsmParserVariant(VC);
+ int AsmVariantNo = AsmVariant->getValueAsInt("Variant");
+ OS << " case " << AsmVariantNo << ": Start = std::begin(MatchTable" << VC
+ << "); End = std::end(MatchTable" << VC << "); break;\n";
+ }
+ OS << " }\n";
+
+ OS << " // Search the table.\n";
+ if (HasMnemonicFirst) {
+ OS << " auto MnemonicRange = "
+ "std::equal_range(Start, End, Mnemonic, LessOpcode());\n\n";
+ } else {
+ OS << " auto MnemonicRange = std::make_pair(Start, End);\n";
+ OS << " unsigned SIndex = Mnemonic.empty() ? 0 : 1;\n";
+ OS << " if (!Mnemonic.empty())\n";
+ OS << " MnemonicRange = "
+ "std::equal_range(Start, End, Mnemonic.lower(), LessOpcode());\n\n";
+ }
+
+ OS << " // Return a more specific error code if no mnemonics match.\n";
+ OS << " if (MnemonicRange.first == MnemonicRange.second)\n";
+ OS << " return Match_MnemonicFail;\n\n";
+
+ OS << " for (const MatchEntry *it = MnemonicRange.first, "
+ << "*ie = MnemonicRange.second;\n";
+ OS << " it != ie; ++it) {\n";
+
+ if (HasMnemonicFirst) {
+ OS << " // equal_range guarantees that instruction mnemonic matches.\n";
+ OS << " assert(Mnemonic == it->getMnemonic());\n";
+ }
+
+ // Emit check that the subclasses match.
+ OS << " bool OperandsValid = true;\n";
+ if (HasOptionalOperands) {
+ OS << " OptionalOperandsMask.reset(0, " << MaxNumOperands << ");\n";
+ }
+ OS << " for (unsigned FormalIdx = " << (HasMnemonicFirst ? "0" : "SIndex")
+ << ", ActualIdx = " << (HasMnemonicFirst ? "1" : "SIndex")
+ << "; FormalIdx != " << MaxNumOperands << "; ++FormalIdx) {\n";
+ OS << " auto Formal = "
+ << "static_cast<MatchClassKind>(it->Classes[FormalIdx]);\n";
+ OS << " if (ActualIdx >= Operands.size()) {\n";
+ OS << " OperandsValid = (Formal == " <<"InvalidMatchClass) || "
+ "isSubclass(Formal, OptionalMatchClass);\n";
+ OS << " if (!OperandsValid) ErrorInfo = ActualIdx;\n";
+ if (HasOptionalOperands) {
+ OS << " OptionalOperandsMask.set(FormalIdx, " << MaxNumOperands
+ << ");\n";
+ }
+ OS << " break;\n";
+ OS << " }\n";
+ OS << " MCParsedAsmOperand &Actual = *Operands[ActualIdx];\n";
+ OS << " unsigned Diag = validateOperandClass(Actual, Formal);\n";
+ OS << " if (Diag == Match_Success) {\n";
+ OS << " ++ActualIdx;\n";
+ OS << " continue;\n";
+ OS << " }\n";
+ OS << " // If the generic handler indicates an invalid operand\n";
+ OS << " // failure, check for a special case.\n";
+ OS << " if (Diag == Match_InvalidOperand) {\n";
+ OS << " Diag = validateTargetOperandClass(Actual, Formal);\n";
+ OS << " if (Diag == Match_Success) {\n";
+ OS << " ++ActualIdx;\n";
+ OS << " continue;\n";
+ OS << " }\n";
+ OS << " }\n";
+ OS << " // If current formal operand wasn't matched and it is optional\n"
+ << " // then try to match next formal operand\n";
+ OS << " if (Diag == Match_InvalidOperand "
+ << "&& isSubclass(Formal, OptionalMatchClass)) {\n";
+ if (HasOptionalOperands) {
+ OS << " OptionalOperandsMask.set(FormalIdx);\n";
+ }
+ OS << " continue;\n";
+ OS << " }\n";
+ OS << " // If this operand is broken for all of the instances of this\n";
+ OS << " // mnemonic, keep track of it so we can report loc info.\n";
+ OS << " // If we already had a match that only failed due to a\n";
+ OS << " // target predicate, that diagnostic is preferred.\n";
+ OS << " if (!HadMatchOtherThanPredicate &&\n";
+ OS << " (it == MnemonicRange.first || ErrorInfo <= ActualIdx)) {\n";
+ OS << " ErrorInfo = ActualIdx;\n";
+ OS << " // InvalidOperand is the default. Prefer specificity.\n";
+ OS << " if (Diag != Match_InvalidOperand)\n";
+ OS << " RetCode = Diag;\n";
+ OS << " }\n";
+ OS << " // Otherwise, just reject this instance of the mnemonic.\n";
+ OS << " OperandsValid = false;\n";
+ OS << " break;\n";
+ OS << " }\n\n";
+
+ OS << " if (!OperandsValid) continue;\n";
+
+ // Emit check that the required features are available.
+ OS << " if ((AvailableFeatures & it->RequiredFeatures) "
+ << "!= it->RequiredFeatures) {\n";
+ OS << " HadMatchOtherThanFeatures = true;\n";
+ OS << " uint64_t NewMissingFeatures = it->RequiredFeatures & "
+ "~AvailableFeatures;\n";
+ OS << " if (countPopulation(NewMissingFeatures) <=\n"
+ " countPopulation(MissingFeatures))\n";
+ OS << " MissingFeatures = NewMissingFeatures;\n";
+ OS << " continue;\n";
+ OS << " }\n";
+ OS << "\n";
+ OS << " Inst.clear();\n\n";
+ OS << " Inst.setOpcode(it->Opcode);\n";
+ // Verify the instruction with the target-specific match predicate function.
+ OS << " // We have a potential match but have not rendered the operands.\n"
+ << " // Check the target predicate to handle any context sensitive\n"
+ " // constraints.\n"
+ << " // For example, Ties that are referenced multiple times must be\n"
+ " // checked here to ensure the input is the same for each match\n"
+ " // constraints. If we leave it any later the ties will have been\n"
+ " // canonicalized\n"
+ << " unsigned MatchResult;\n"
+ << " if ((MatchResult = checkEarlyTargetMatchPredicate(Inst, "
+ "Operands)) != Match_Success) {\n"
+ << " Inst.clear();\n"
+ << " RetCode = MatchResult;\n"
+ << " HadMatchOtherThanPredicate = true;\n"
+ << " continue;\n"
+ << " }\n\n";
+ OS << " if (matchingInlineAsm) {\n";
+ OS << " convertToMapAndConstraints(it->ConvertFn, Operands);\n";
+ OS << " return Match_Success;\n";
+ OS << " }\n\n";
+ OS << " // We have selected a definite instruction, convert the parsed\n"
+ << " // operands into the appropriate MCInst.\n";
+ if (HasOptionalOperands) {
+ OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands,\n"
+ << " OptionalOperandsMask);\n";
+ } else {
+ OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\n";
+ }
+ OS << "\n";
+
+ // Verify the instruction with the target-specific match predicate function.
+ OS << " // We have a potential match. Check the target predicate to\n"
+ << " // handle any context sensitive constraints.\n"
+ << " if ((MatchResult = checkTargetMatchPredicate(Inst)) !="
+ << " Match_Success) {\n"
+ << " Inst.clear();\n"
+ << " RetCode = MatchResult;\n"
+ << " HadMatchOtherThanPredicate = true;\n"
+ << " continue;\n"
+ << " }\n\n";
+
+ // Call the post-processing function, if used.
+ std::string InsnCleanupFn =
+ AsmParser->getValueAsString("AsmParserInstCleanup");
+ if (!InsnCleanupFn.empty())
+ OS << " " << InsnCleanupFn << "(Inst);\n";
+
+ if (HasDeprecation) {
+ OS << " std::string Info;\n";
+ OS << " if (!getParser().getTargetParser().\n";
+ OS << " getTargetOptions().MCNoDeprecatedWarn &&\n";
+ OS << " MII.get(Inst.getOpcode()).getDeprecatedInfo(Inst, getSTI(), Info)) {\n";
+ OS << " SMLoc Loc = ((" << Target.getName()
+ << "Operand&)*Operands[0]).getStartLoc();\n";
+ OS << " getParser().Warning(Loc, Info, None);\n";
+ OS << " }\n";
+ }
+
+ OS << " return Match_Success;\n";
+ OS << " }\n\n";
+
+ OS << " // Okay, we had no match. Try to return a useful error code.\n";
+ OS << " if (HadMatchOtherThanPredicate || !HadMatchOtherThanFeatures)\n";
+ OS << " return RetCode;\n\n";
+ OS << " // Missing feature matches return which features were missing\n";
+ OS << " ErrorInfo = MissingFeatures;\n";
+ OS << " return Match_MissingFeature;\n";
+ OS << "}\n\n";
+
+ if (!Info.OperandMatchInfo.empty())
+ emitCustomOperandParsing(OS, Target, Info, ClassName, StringTable,
+ MaxMnemonicIndex, HasMnemonicFirst);
+
+ OS << "#endif // GET_MATCHER_IMPLEMENTATION\n\n";
+}
+
+namespace llvm {
+
+void EmitAsmMatcher(RecordKeeper &RK, raw_ostream &OS) {
+ emitSourceFileHeader("Assembly Matcher Source Fragment", OS);
+ AsmMatcherEmitter(RK).run(OS);
+}
+
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
new file mode 100644
index 000000000000..40b7857ab994
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -0,0 +1,1129 @@
+//===- AsmWriterEmitter.cpp - Generate an assembly writer -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits an assembly printer for the current target.
+// Note that this is currently fairly skeletal, but will grow over time.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AsmWriterInst.h"
+#include "CodeGenInstruction.h"
+#include "CodeGenRegisters.h"
+#include "CodeGenTarget.h"
+#include "SequenceToOffsetTable.h"
+#include "Types.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <deque>
+#include <iterator>
+#include <map>
+#include <set>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "asm-writer-emitter"
+
+namespace {
+
+class AsmWriterEmitter {
+ RecordKeeper &Records;
+ CodeGenTarget Target;
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions;
+ std::vector<AsmWriterInst> Instructions;
+
+public:
+ AsmWriterEmitter(RecordKeeper &R);
+
+ void run(raw_ostream &o);
+
+private:
+ void EmitPrintInstruction(raw_ostream &o);
+ void EmitGetRegisterName(raw_ostream &o);
+ void EmitPrintAliasInstruction(raw_ostream &O);
+
+ void FindUniqueOperandCommands(std::vector<std::string> &UOC,
+ std::vector<std::vector<unsigned>> &InstIdxs,
+ std::vector<unsigned> &InstOpsUsed,
+ bool PassSubtarget) const;
+};
+
+} // end anonymous namespace
+
+static void PrintCases(std::vector<std::pair<std::string,
+ AsmWriterOperand>> &OpsToPrint, raw_ostream &O,
+ bool PassSubtarget) {
+ O << " case " << OpsToPrint.back().first << ":";
+ AsmWriterOperand TheOp = OpsToPrint.back().second;
+ OpsToPrint.pop_back();
+
+ // Check to see if any other operands are identical in this list, and if so,
+ // emit a case label for them.
+ for (unsigned i = OpsToPrint.size(); i != 0; --i)
+ if (OpsToPrint[i-1].second == TheOp) {
+ O << "\n case " << OpsToPrint[i-1].first << ":";
+ OpsToPrint.erase(OpsToPrint.begin()+i-1);
+ }
+
+ // Finally, emit the code.
+ O << "\n " << TheOp.getCode(PassSubtarget);
+ O << "\n break;\n";
+}
+
+/// EmitInstructions - Emit the last instruction in the vector and any other
+/// instructions that are suitably similar to it.
+static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
+ raw_ostream &O, bool PassSubtarget) {
+ AsmWriterInst FirstInst = Insts.back();
+ Insts.pop_back();
+
+ std::vector<AsmWriterInst> SimilarInsts;
+ unsigned DifferingOperand = ~0;
+ for (unsigned i = Insts.size(); i != 0; --i) {
+ unsigned DiffOp = Insts[i-1].MatchesAllButOneOp(FirstInst);
+ if (DiffOp != ~1U) {
+ if (DifferingOperand == ~0U) // First match!
+ DifferingOperand = DiffOp;
+
+ // If this differs in the same operand as the rest of the instructions in
+ // this class, move it to the SimilarInsts list.
+ if (DifferingOperand == DiffOp || DiffOp == ~0U) {
+ SimilarInsts.push_back(Insts[i-1]);
+ Insts.erase(Insts.begin()+i-1);
+ }
+ }
+ }
+
+ O << " case " << FirstInst.CGI->Namespace << "::"
+ << FirstInst.CGI->TheDef->getName() << ":\n";
+ for (const AsmWriterInst &AWI : SimilarInsts)
+ O << " case " << AWI.CGI->Namespace << "::"
+ << AWI.CGI->TheDef->getName() << ":\n";
+ for (unsigned i = 0, e = FirstInst.Operands.size(); i != e; ++i) {
+ if (i != DifferingOperand) {
+ // If the operand is the same for all instructions, just print it.
+ O << " " << FirstInst.Operands[i].getCode(PassSubtarget);
+ } else {
+ // If this is the operand that varies between all of the instructions,
+ // emit a switch for just this operand now.
+ O << " switch (MI->getOpcode()) {\n";
+ O << " default: llvm_unreachable(\"Unexpected opcode.\");\n";
+ std::vector<std::pair<std::string, AsmWriterOperand>> OpsToPrint;
+ OpsToPrint.push_back(std::make_pair(FirstInst.CGI->Namespace + "::" +
+ FirstInst.CGI->TheDef->getName().str(),
+ FirstInst.Operands[i]));
+
+ for (const AsmWriterInst &AWI : SimilarInsts) {
+ OpsToPrint.push_back(std::make_pair(AWI.CGI->Namespace+"::" +
+ AWI.CGI->TheDef->getName().str(),
+ AWI.Operands[i]));
+ }
+ std::reverse(OpsToPrint.begin(), OpsToPrint.end());
+ while (!OpsToPrint.empty())
+ PrintCases(OpsToPrint, O, PassSubtarget);
+ O << " }";
+ }
+ O << "\n";
+ }
+ O << " break;\n";
+}
+
+void AsmWriterEmitter::
+FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
+ std::vector<std::vector<unsigned>> &InstIdxs,
+ std::vector<unsigned> &InstOpsUsed,
+ bool PassSubtarget) const {
+ // This vector parallels UniqueOperandCommands, keeping track of which
+ // instructions each case are used for. It is a comma separated string of
+ // enums.
+ std::vector<std::string> InstrsForCase;
+ InstrsForCase.resize(UniqueOperandCommands.size());
+ InstOpsUsed.assign(UniqueOperandCommands.size(), 0);
+
+ for (size_t i = 0, e = Instructions.size(); i != e; ++i) {
+ const AsmWriterInst &Inst = Instructions[i];
+ if (Inst.Operands.empty())
+ continue; // Instruction already done.
+
+ std::string Command = " "+Inst.Operands[0].getCode(PassSubtarget)+"\n";
+
+ // Check to see if we already have 'Command' in UniqueOperandCommands.
+ // If not, add it.
+ auto I = llvm::find(UniqueOperandCommands, Command);
+ if (I != UniqueOperandCommands.end()) {
+ size_t idx = I - UniqueOperandCommands.begin();
+ InstrsForCase[idx] += ", ";
+ InstrsForCase[idx] += Inst.CGI->TheDef->getName();
+ InstIdxs[idx].push_back(i);
+ } else {
+ UniqueOperandCommands.push_back(std::move(Command));
+ InstrsForCase.push_back(Inst.CGI->TheDef->getName());
+ InstIdxs.emplace_back();
+ InstIdxs.back().push_back(i);
+
+ // This command matches one operand so far.
+ InstOpsUsed.push_back(1);
+ }
+ }
+
+ // For each entry of UniqueOperandCommands, there is a set of instructions
+ // that uses it. If the next command of all instructions in the set are
+ // identical, fold it into the command.
+ for (size_t CommandIdx = 0, e = UniqueOperandCommands.size();
+ CommandIdx != e; ++CommandIdx) {
+
+ const auto &Idxs = InstIdxs[CommandIdx];
+
+ for (unsigned Op = 1; ; ++Op) {
+ // Find the first instruction in the set.
+ const AsmWriterInst &FirstInst = Instructions[Idxs.front()];
+ // If this instruction has no more operands, we isn't anything to merge
+ // into this command.
+ if (FirstInst.Operands.size() == Op)
+ break;
+
+ // Otherwise, scan to see if all of the other instructions in this command
+ // set share the operand.
+ if (std::any_of(Idxs.begin()+1, Idxs.end(),
+ [&](unsigned Idx) {
+ const AsmWriterInst &OtherInst = Instructions[Idx];
+ return OtherInst.Operands.size() == Op ||
+ OtherInst.Operands[Op] != FirstInst.Operands[Op];
+ }))
+ break;
+
+ // Okay, everything in this command set has the same next operand. Add it
+ // to UniqueOperandCommands and remember that it was consumed.
+ std::string Command = " " +
+ FirstInst.Operands[Op].getCode(PassSubtarget) + "\n";
+
+ UniqueOperandCommands[CommandIdx] += Command;
+ InstOpsUsed[CommandIdx]++;
+ }
+ }
+
+ // Prepend some of the instructions each case is used for onto the case val.
+ for (unsigned i = 0, e = InstrsForCase.size(); i != e; ++i) {
+ std::string Instrs = InstrsForCase[i];
+ if (Instrs.size() > 70) {
+ Instrs.erase(Instrs.begin()+70, Instrs.end());
+ Instrs += "...";
+ }
+
+ if (!Instrs.empty())
+ UniqueOperandCommands[i] = " // " + Instrs + "\n" +
+ UniqueOperandCommands[i];
+ }
+}
+
+static void UnescapeString(std::string &Str) {
+ for (unsigned i = 0; i != Str.size(); ++i) {
+ if (Str[i] == '\\' && i != Str.size()-1) {
+ switch (Str[i+1]) {
+ default: continue; // Don't execute the code after the switch.
+ case 'a': Str[i] = '\a'; break;
+ case 'b': Str[i] = '\b'; break;
+ case 'e': Str[i] = 27; break;
+ case 'f': Str[i] = '\f'; break;
+ case 'n': Str[i] = '\n'; break;
+ case 'r': Str[i] = '\r'; break;
+ case 't': Str[i] = '\t'; break;
+ case 'v': Str[i] = '\v'; break;
+ case '"': Str[i] = '\"'; break;
+ case '\'': Str[i] = '\''; break;
+ case '\\': Str[i] = '\\'; break;
+ }
+ // Nuke the second character.
+ Str.erase(Str.begin()+i+1);
+ }
+ }
+}
+
+/// EmitPrintInstruction - Generate the code for the "printInstruction" method
+/// implementation. Destroys all instances of AsmWriterInst information, by
+/// clearing the Instructions vector.
+void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
+ Record *AsmWriter = Target.getAsmWriter();
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+ bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
+
+ O <<
+ "/// printInstruction - This method is automatically generated by tablegen\n"
+ "/// from the instruction set description.\n"
+ "void " << Target.getName() << ClassName
+ << "::printInstruction(const MCInst *MI, "
+ << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
+ << "raw_ostream &O) {\n";
+
+ // Build an aggregate string, and build a table of offsets into it.
+ SequenceToOffsetTable<std::string> StringTable;
+
+ /// OpcodeInfo - This encodes the index of the string to use for the first
+ /// chunk of the output as well as indices used for operand printing.
+ std::vector<uint64_t> OpcodeInfo(NumberedInstructions.size());
+ const unsigned OpcodeInfoBits = 64;
+
+ // Add all strings to the string table upfront so it can generate an optimized
+ // representation.
+ for (AsmWriterInst &AWI : Instructions) {
+ if (AWI.Operands[0].OperandType ==
+ AsmWriterOperand::isLiteralTextOperand &&
+ !AWI.Operands[0].Str.empty()) {
+ std::string Str = AWI.Operands[0].Str;
+ UnescapeString(Str);
+ StringTable.add(Str);
+ }
+ }
+
+ StringTable.layout();
+
+ unsigned MaxStringIdx = 0;
+ for (AsmWriterInst &AWI : Instructions) {
+ unsigned Idx;
+ if (AWI.Operands[0].OperandType != AsmWriterOperand::isLiteralTextOperand ||
+ AWI.Operands[0].Str.empty()) {
+ // Something handled by the asmwriter printer, but with no leading string.
+ Idx = StringTable.get("");
+ } else {
+ std::string Str = AWI.Operands[0].Str;
+ UnescapeString(Str);
+ Idx = StringTable.get(Str);
+ MaxStringIdx = std::max(MaxStringIdx, Idx);
+
+ // Nuke the string from the operand list. It is now handled!
+ AWI.Operands.erase(AWI.Operands.begin());
+ }
+
+ // Bias offset by one since we want 0 as a sentinel.
+ OpcodeInfo[AWI.CGIIndex] = Idx+1;
+ }
+
+ // Figure out how many bits we used for the string index.
+ unsigned AsmStrBits = Log2_32_Ceil(MaxStringIdx+2);
+
+ // To reduce code size, we compactify common instructions into a few bits
+ // in the opcode-indexed table.
+ unsigned BitsLeft = OpcodeInfoBits-AsmStrBits;
+
+ std::vector<std::vector<std::string>> TableDrivenOperandPrinters;
+
+ while (true) {
+ std::vector<std::string> UniqueOperandCommands;
+ std::vector<std::vector<unsigned>> InstIdxs;
+ std::vector<unsigned> NumInstOpsHandled;
+ FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs,
+ NumInstOpsHandled, PassSubtarget);
+
+ // If we ran out of operands to print, we're done.
+ if (UniqueOperandCommands.empty()) break;
+
+ // Compute the number of bits we need to represent these cases, this is
+ // ceil(log2(numentries)).
+ unsigned NumBits = Log2_32_Ceil(UniqueOperandCommands.size());
+
+ // If we don't have enough bits for this operand, don't include it.
+ if (NumBits > BitsLeft) {
+ DEBUG(errs() << "Not enough bits to densely encode " << NumBits
+ << " more bits\n");
+ break;
+ }
+
+ // Otherwise, we can include this in the initial lookup table. Add it in.
+ for (size_t i = 0, e = InstIdxs.size(); i != e; ++i) {
+ unsigned NumOps = NumInstOpsHandled[i];
+ for (unsigned Idx : InstIdxs[i]) {
+ OpcodeInfo[Instructions[Idx].CGIIndex] |=
+ (uint64_t)i << (OpcodeInfoBits-BitsLeft);
+ // Remove the info about this operand from the instruction.
+ AsmWriterInst &Inst = Instructions[Idx];
+ if (!Inst.Operands.empty()) {
+ assert(NumOps <= Inst.Operands.size() &&
+ "Can't remove this many ops!");
+ Inst.Operands.erase(Inst.Operands.begin(),
+ Inst.Operands.begin()+NumOps);
+ }
+ }
+ }
+ BitsLeft -= NumBits;
+
+ // Remember the handlers for this set of operands.
+ TableDrivenOperandPrinters.push_back(std::move(UniqueOperandCommands));
+ }
+
+ // Emit the string table itself.
+ O << " static const char AsmStrs[] = {\n";
+ StringTable.emit(O, printChar);
+ O << " };\n\n";
+
+ // Emit the lookup tables in pieces to minimize wasted bytes.
+ unsigned BytesNeeded = ((OpcodeInfoBits - BitsLeft) + 7) / 8;
+ unsigned Table = 0, Shift = 0;
+ SmallString<128> BitsString;
+ raw_svector_ostream BitsOS(BitsString);
+ // If the total bits is more than 32-bits we need to use a 64-bit type.
+ BitsOS << " uint" << ((BitsLeft < (OpcodeInfoBits - 32)) ? 64 : 32)
+ << "_t Bits = 0;\n";
+ while (BytesNeeded != 0) {
+ // Figure out how big this table section needs to be, but no bigger than 4.
+ unsigned TableSize = std::min(1 << Log2_32(BytesNeeded), 4);
+ BytesNeeded -= TableSize;
+ TableSize *= 8; // Convert to bits;
+ uint64_t Mask = (1ULL << TableSize) - 1;
+ O << " static const uint" << TableSize << "_t OpInfo" << Table
+ << "[] = {\n";
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ O << " " << ((OpcodeInfo[i] >> Shift) & Mask) << "U,\t// "
+ << NumberedInstructions[i]->TheDef->getName() << "\n";
+ }
+ O << " };\n\n";
+ // Emit string to combine the individual table lookups.
+ BitsOS << " Bits |= ";
+ // If the total bits is more than 32-bits we need to use a 64-bit type.
+ if (BitsLeft < (OpcodeInfoBits - 32))
+ BitsOS << "(uint64_t)";
+ BitsOS << "OpInfo" << Table << "[MI->getOpcode()] << " << Shift << ";\n";
+ // Prepare the shift for the next iteration and increment the table count.
+ Shift += TableSize;
+ ++Table;
+ }
+
+ // Emit the initial tab character.
+ O << " O << \"\\t\";\n\n";
+
+ O << " // Emit the opcode for the instruction.\n";
+ O << BitsString;
+
+ // Emit the starting string.
+ O << " assert(Bits != 0 && \"Cannot print this instruction.\");\n"
+ << " O << AsmStrs+(Bits & " << (1 << AsmStrBits)-1 << ")-1;\n\n";
+
+ // Output the table driven operand information.
+ BitsLeft = OpcodeInfoBits-AsmStrBits;
+ for (unsigned i = 0, e = TableDrivenOperandPrinters.size(); i != e; ++i) {
+ std::vector<std::string> &Commands = TableDrivenOperandPrinters[i];
+
+ // Compute the number of bits we need to represent these cases, this is
+ // ceil(log2(numentries)).
+ unsigned NumBits = Log2_32_Ceil(Commands.size());
+ assert(NumBits <= BitsLeft && "consistency error");
+
+ // Emit code to extract this field from Bits.
+ O << "\n // Fragment " << i << " encoded into " << NumBits
+ << " bits for " << Commands.size() << " unique commands.\n";
+
+ if (Commands.size() == 2) {
+ // Emit two possibilitys with if/else.
+ O << " if ((Bits >> "
+ << (OpcodeInfoBits-BitsLeft) << ") & "
+ << ((1 << NumBits)-1) << ") {\n"
+ << Commands[1]
+ << " } else {\n"
+ << Commands[0]
+ << " }\n\n";
+ } else if (Commands.size() == 1) {
+ // Emit a single possibility.
+ O << Commands[0] << "\n\n";
+ } else {
+ O << " switch ((Bits >> "
+ << (OpcodeInfoBits-BitsLeft) << ") & "
+ << ((1 << NumBits)-1) << ") {\n"
+ << " default: llvm_unreachable(\"Invalid command number.\");\n";
+
+ // Print out all the cases.
+ for (unsigned j = 0, e = Commands.size(); j != e; ++j) {
+ O << " case " << j << ":\n";
+ O << Commands[j];
+ O << " break;\n";
+ }
+ O << " }\n\n";
+ }
+ BitsLeft -= NumBits;
+ }
+
+ // Okay, delete instructions with no operand info left.
+ auto I = llvm::remove_if(Instructions,
+ [](AsmWriterInst &Inst) { return Inst.Operands.empty(); });
+ Instructions.erase(I, Instructions.end());
+
+
+ // Because this is a vector, we want to emit from the end. Reverse all of the
+ // elements in the vector.
+ std::reverse(Instructions.begin(), Instructions.end());
+
+
+ // Now that we've emitted all of the operand info that fit into 64 bits, emit
+ // information for those instructions that are left. This is a less dense
+ // encoding, but we expect the main 64-bit table to handle the majority of
+ // instructions.
+ if (!Instructions.empty()) {
+ // Find the opcode # of inline asm.
+ O << " switch (MI->getOpcode()) {\n";
+ O << " default: llvm_unreachable(\"Unexpected opcode.\");\n";
+ while (!Instructions.empty())
+ EmitInstructions(Instructions, O, PassSubtarget);
+
+ O << " }\n";
+ }
+
+ O << "}\n";
+}
+
+static void
+emitRegisterNameString(raw_ostream &O, StringRef AltName,
+ const std::deque<CodeGenRegister> &Registers) {
+ SequenceToOffsetTable<std::string> StringTable;
+ SmallVector<std::string, 4> AsmNames(Registers.size());
+ unsigned i = 0;
+ for (const auto &Reg : Registers) {
+ std::string &AsmName = AsmNames[i++];
+
+ // "NoRegAltName" is special. We don't need to do a lookup for that,
+ // as it's just a reference to the default register name.
+ if (AltName == "" || AltName == "NoRegAltName") {
+ AsmName = Reg.TheDef->getValueAsString("AsmName");
+ if (AsmName.empty())
+ AsmName = Reg.getName();
+ } else {
+ // Make sure the register has an alternate name for this index.
+ std::vector<Record*> AltNameList =
+ Reg.TheDef->getValueAsListOfDefs("RegAltNameIndices");
+ unsigned Idx = 0, e;
+ for (e = AltNameList.size();
+ Idx < e && (AltNameList[Idx]->getName() != AltName);
+ ++Idx)
+ ;
+ // If the register has an alternate name for this index, use it.
+ // Otherwise, leave it empty as an error flag.
+ if (Idx < e) {
+ std::vector<std::string> AltNames =
+ Reg.TheDef->getValueAsListOfStrings("AltNames");
+ if (AltNames.size() <= Idx)
+ PrintFatalError(Reg.TheDef->getLoc(),
+ "Register definition missing alt name for '" +
+ AltName + "'.");
+ AsmName = AltNames[Idx];
+ }
+ }
+ StringTable.add(AsmName);
+ }
+
+ StringTable.layout();
+ O << " static const char AsmStrs" << AltName << "[] = {\n";
+ StringTable.emit(O, printChar);
+ O << " };\n\n";
+
+ O << " static const " << getMinimalTypeForRange(StringTable.size() - 1, 32)
+ << " RegAsmOffset" << AltName << "[] = {";
+ for (unsigned i = 0, e = Registers.size(); i != e; ++i) {
+ if ((i % 14) == 0)
+ O << "\n ";
+ O << StringTable.get(AsmNames[i]) << ", ";
+ }
+ O << "\n };\n"
+ << "\n";
+}
+
+void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
+ Record *AsmWriter = Target.getAsmWriter();
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+ const auto &Registers = Target.getRegBank().getRegisters();
+ const std::vector<Record*> &AltNameIndices = Target.getRegAltNameIndices();
+ bool hasAltNames = AltNameIndices.size() > 1;
+ std::string Namespace =
+ Registers.front().TheDef->getValueAsString("Namespace");
+
+ O <<
+ "\n\n/// getRegisterName - This method is automatically generated by tblgen\n"
+ "/// from the register set description. This returns the assembler name\n"
+ "/// for the specified register.\n"
+ "const char *" << Target.getName() << ClassName << "::";
+ if (hasAltNames)
+ O << "\ngetRegisterName(unsigned RegNo, unsigned AltIdx) {\n";
+ else
+ O << "getRegisterName(unsigned RegNo) {\n";
+ O << " assert(RegNo && RegNo < " << (Registers.size()+1)
+ << " && \"Invalid register number!\");\n"
+ << "\n";
+
+ if (hasAltNames) {
+ for (const Record *R : AltNameIndices)
+ emitRegisterNameString(O, R->getName(), Registers);
+ } else
+ emitRegisterNameString(O, "", Registers);
+
+ if (hasAltNames) {
+ O << " switch(AltIdx) {\n"
+ << " default: llvm_unreachable(\"Invalid register alt name index!\");\n";
+ for (const Record *R : AltNameIndices) {
+ const std::string &AltName = R->getName();
+ std::string Prefix = !Namespace.empty() ? Namespace + "::" : "";
+ O << " case " << Prefix << AltName << ":\n"
+ << " assert(*(AsmStrs" << AltName << "+RegAsmOffset"
+ << AltName << "[RegNo-1]) &&\n"
+ << " \"Invalid alt name index for register!\");\n"
+ << " return AsmStrs" << AltName << "+RegAsmOffset"
+ << AltName << "[RegNo-1];\n";
+ }
+ O << " }\n";
+ } else {
+ O << " assert (*(AsmStrs+RegAsmOffset[RegNo-1]) &&\n"
+ << " \"Invalid alt name index for register!\");\n"
+ << " return AsmStrs+RegAsmOffset[RegNo-1];\n";
+ }
+ O << "}\n";
+}
+
+namespace {
+
+// IAPrinter - Holds information about an InstAlias. Two InstAliases match if
+// they both have the same conditionals. In which case, we cannot print out the
+// alias for that pattern.
+class IAPrinter {
+ std::vector<std::string> Conds;
+ std::map<StringRef, std::pair<int, int>> OpMap;
+
+ std::string Result;
+ std::string AsmString;
+
+public:
+ IAPrinter(std::string R, std::string AS)
+ : Result(std::move(R)), AsmString(std::move(AS)) {}
+
+ void addCond(const std::string &C) { Conds.push_back(C); }
+
+ void addOperand(StringRef Op, int OpIdx, int PrintMethodIdx = -1) {
+ assert(OpIdx >= 0 && OpIdx < 0xFE && "Idx out of range");
+ assert(PrintMethodIdx >= -1 && PrintMethodIdx < 0xFF &&
+ "Idx out of range");
+ OpMap[Op] = std::make_pair(OpIdx, PrintMethodIdx);
+ }
+
+ bool isOpMapped(StringRef Op) { return OpMap.find(Op) != OpMap.end(); }
+ int getOpIndex(StringRef Op) { return OpMap[Op].first; }
+ std::pair<int, int> &getOpData(StringRef Op) { return OpMap[Op]; }
+
+ std::pair<StringRef, StringRef::iterator> parseName(StringRef::iterator Start,
+ StringRef::iterator End) {
+ StringRef::iterator I = Start;
+ StringRef::iterator Next;
+ if (*I == '{') {
+ // ${some_name}
+ Start = ++I;
+ while (I != End && *I != '}')
+ ++I;
+ Next = I;
+ // eat the final '}'
+ if (Next != End)
+ ++Next;
+ } else {
+ // $name, just eat the usual suspects.
+ while (I != End &&
+ ((*I >= 'a' && *I <= 'z') || (*I >= 'A' && *I <= 'Z') ||
+ (*I >= '0' && *I <= '9') || *I == '_'))
+ ++I;
+ Next = I;
+ }
+
+ return std::make_pair(StringRef(Start, I - Start), Next);
+ }
+
+ void print(raw_ostream &O) {
+ if (Conds.empty()) {
+ O.indent(6) << "return true;\n";
+ return;
+ }
+
+ O << "if (";
+
+ for (std::vector<std::string>::iterator
+ I = Conds.begin(), E = Conds.end(); I != E; ++I) {
+ if (I != Conds.begin()) {
+ O << " &&\n";
+ O.indent(8);
+ }
+
+ O << *I;
+ }
+
+ O << ") {\n";
+ O.indent(6) << "// " << Result << "\n";
+
+ // Directly mangle mapped operands into the string. Each operand is
+ // identified by a '$' sign followed by a byte identifying the number of the
+ // operand. We add one to the index to avoid zero bytes.
+ StringRef ASM(AsmString);
+ SmallString<128> OutString;
+ raw_svector_ostream OS(OutString);
+ for (StringRef::iterator I = ASM.begin(), E = ASM.end(); I != E;) {
+ OS << *I;
+ if (*I == '$') {
+ StringRef Name;
+ std::tie(Name, I) = parseName(++I, E);
+ assert(isOpMapped(Name) && "Unmapped operand!");
+
+ int OpIndex, PrintIndex;
+ std::tie(OpIndex, PrintIndex) = getOpData(Name);
+ if (PrintIndex == -1) {
+ // Can use the default printOperand route.
+ OS << format("\\x%02X", (unsigned char)OpIndex + 1);
+ } else
+ // 3 bytes if a PrintMethod is needed: 0xFF, the MCInst operand
+ // number, and which of our pre-detected Methods to call.
+ OS << format("\\xFF\\x%02X\\x%02X", OpIndex + 1, PrintIndex + 1);
+ } else {
+ ++I;
+ }
+ }
+
+ // Emit the string.
+ O.indent(6) << "AsmString = \"" << OutString << "\";\n";
+
+ O.indent(6) << "break;\n";
+ O.indent(4) << '}';
+ }
+
+ bool operator==(const IAPrinter &RHS) const {
+ if (Conds.size() != RHS.Conds.size())
+ return false;
+
+ unsigned Idx = 0;
+ for (const auto &str : Conds)
+ if (str != RHS.Conds[Idx++])
+ return false;
+
+ return true;
+ }
+};
+
+} // end anonymous namespace
+
+static unsigned CountNumOperands(StringRef AsmString, unsigned Variant) {
+ std::string FlatAsmString =
+ CodeGenInstruction::FlattenAsmStringVariants(AsmString, Variant);
+ AsmString = FlatAsmString;
+
+ return AsmString.count(' ') + AsmString.count('\t');
+}
+
+namespace {
+
+struct AliasPriorityComparator {
+ typedef std::pair<CodeGenInstAlias, int> ValueType;
+ bool operator()(const ValueType &LHS, const ValueType &RHS) const {
+ if (LHS.second == RHS.second) {
+ // We don't actually care about the order, but for consistency it
+ // shouldn't depend on pointer comparisons.
+ return LessRecordByID()(LHS.first.TheDef, RHS.first.TheDef);
+ }
+
+ // Aliases with larger priorities should be considered first.
+ return LHS.second > RHS.second;
+ }
+};
+
+} // end anonymous namespace
+
+void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
+ Record *AsmWriter = Target.getAsmWriter();
+
+ O << "\n#ifdef PRINT_ALIAS_INSTR\n";
+ O << "#undef PRINT_ALIAS_INSTR\n\n";
+
+ //////////////////////////////
+ // Gather information about aliases we need to print
+ //////////////////////////////
+
+ // Emit the method that prints the alias instruction.
+ std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
+ unsigned Variant = AsmWriter->getValueAsInt("Variant");
+ bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
+
+ std::vector<Record*> AllInstAliases =
+ Records.getAllDerivedDefinitions("InstAlias");
+
+ // Create a map from the qualified name to a list of potential matches.
+ typedef std::set<std::pair<CodeGenInstAlias, int>, AliasPriorityComparator>
+ AliasWithPriority;
+ std::map<std::string, AliasWithPriority> AliasMap;
+ for (Record *R : AllInstAliases) {
+ int Priority = R->getValueAsInt("EmitPriority");
+ if (Priority < 1)
+ continue; // Aliases with priority 0 are never emitted.
+
+ const DagInit *DI = R->getValueAsDag("ResultInst");
+ const DefInit *Op = cast<DefInit>(DI->getOperator());
+ AliasMap[getQualifiedName(Op->getDef())].insert(
+ std::make_pair(CodeGenInstAlias(R, Variant, Target), Priority));
+ }
+
+ // A map of which conditions need to be met for each instruction operand
+ // before it can be matched to the mnemonic.
+ std::map<std::string, std::vector<IAPrinter>> IAPrinterMap;
+
+ std::vector<std::string> PrintMethods;
+
+ // A list of MCOperandPredicates for all operands in use, and the reverse map
+ std::vector<const Record*> MCOpPredicates;
+ DenseMap<const Record*, unsigned> MCOpPredicateMap;
+
+ for (auto &Aliases : AliasMap) {
+ for (auto &Alias : Aliases.second) {
+ const CodeGenInstAlias &CGA = Alias.first;
+ unsigned LastOpNo = CGA.ResultInstOperandIndex.size();
+ unsigned NumResultOps =
+ CountNumOperands(CGA.ResultInst->AsmString, Variant);
+
+ // Don't emit the alias if it has more operands than what it's aliasing.
+ if (NumResultOps < CountNumOperands(CGA.AsmString, Variant))
+ continue;
+
+ IAPrinter IAP(CGA.Result->getAsString(), CGA.AsmString);
+
+ std::string Namespace = Target.getName();
+ std::vector<Record *> ReqFeatures;
+ if (PassSubtarget) {
+ // We only consider ReqFeatures predicates if PassSubtarget
+ std::vector<Record *> RF =
+ CGA.TheDef->getValueAsListOfDefs("Predicates");
+ copy_if(RF, std::back_inserter(ReqFeatures), [](Record *R) {
+ return R->getValueAsBit("AssemblerMatcherPredicate");
+ });
+ }
+
+ unsigned NumMIOps = 0;
+ for (auto &Operand : CGA.ResultOperands)
+ NumMIOps += Operand.getMINumOperands();
+
+ std::string Cond;
+ Cond = std::string("MI->getNumOperands() == ") + utostr(NumMIOps);
+ IAP.addCond(Cond);
+
+ bool CantHandle = false;
+
+ unsigned MIOpNum = 0;
+ for (unsigned i = 0, e = LastOpNo; i != e; ++i) {
+ std::string Op = "MI->getOperand(" + utostr(MIOpNum) + ")";
+
+ const CodeGenInstAlias::ResultOperand &RO = CGA.ResultOperands[i];
+
+ switch (RO.Kind) {
+ case CodeGenInstAlias::ResultOperand::K_Record: {
+ const Record *Rec = RO.getRecord();
+ StringRef ROName = RO.getName();
+ int PrintMethodIdx = -1;
+
+ // These two may have a PrintMethod, which we want to record (if it's
+ // the first time we've seen it) and provide an index for the aliasing
+ // code to use.
+ if (Rec->isSubClassOf("RegisterOperand") ||
+ Rec->isSubClassOf("Operand")) {
+ std::string PrintMethod = Rec->getValueAsString("PrintMethod");
+ if (PrintMethod != "" && PrintMethod != "printOperand") {
+ PrintMethodIdx =
+ llvm::find(PrintMethods, PrintMethod) - PrintMethods.begin();
+ if (static_cast<unsigned>(PrintMethodIdx) == PrintMethods.size())
+ PrintMethods.push_back(PrintMethod);
+ }
+ }
+
+ if (Rec->isSubClassOf("RegisterOperand"))
+ Rec = Rec->getValueAsDef("RegClass");
+ if (Rec->isSubClassOf("RegisterClass")) {
+ IAP.addCond(Op + ".isReg()");
+
+ if (!IAP.isOpMapped(ROName)) {
+ IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
+ Record *R = CGA.ResultOperands[i].getRecord();
+ if (R->isSubClassOf("RegisterOperand"))
+ R = R->getValueAsDef("RegClass");
+ Cond = std::string("MRI.getRegClass(") + Target.getName().str() +
+ "::" + R->getName().str() + "RegClassID).contains(" + Op +
+ ".getReg())";
+ } else {
+ Cond = Op + ".getReg() == MI->getOperand(" +
+ utostr(IAP.getOpIndex(ROName)) + ").getReg()";
+ }
+ } else {
+ // Assume all printable operands are desired for now. This can be
+ // overridden in the InstAlias instantiation if necessary.
+ IAP.addOperand(ROName, MIOpNum, PrintMethodIdx);
+
+ // There might be an additional predicate on the MCOperand
+ unsigned Entry = MCOpPredicateMap[Rec];
+ if (!Entry) {
+ if (!Rec->isValueUnset("MCOperandPredicate")) {
+ MCOpPredicates.push_back(Rec);
+ Entry = MCOpPredicates.size();
+ MCOpPredicateMap[Rec] = Entry;
+ } else
+ break; // No conditions on this operand at all
+ }
+ Cond = Target.getName().str() + ClassName + "ValidateMCOperand(" +
+ Op + ", STI, " + utostr(Entry) + ")";
+ }
+ // for all subcases of ResultOperand::K_Record:
+ IAP.addCond(Cond);
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Imm: {
+ // Just because the alias has an immediate result, doesn't mean the
+ // MCInst will. An MCExpr could be present, for example.
+ IAP.addCond(Op + ".isImm()");
+
+ Cond = Op + ".getImm() == " + itostr(CGA.ResultOperands[i].getImm());
+ IAP.addCond(Cond);
+ break;
+ }
+ case CodeGenInstAlias::ResultOperand::K_Reg:
+ // If this is zero_reg, something's playing tricks we're not
+ // equipped to handle.
+ if (!CGA.ResultOperands[i].getRegister()) {
+ CantHandle = true;
+ break;
+ }
+
+ Cond = Op + ".getReg() == " + Target.getName().str() + "::" +
+ CGA.ResultOperands[i].getRegister()->getName().str();
+ IAP.addCond(Cond);
+ break;
+ }
+
+ MIOpNum += RO.getMINumOperands();
+ }
+
+ if (CantHandle) continue;
+
+ for (auto I = ReqFeatures.cbegin(); I != ReqFeatures.cend(); I++) {
+ Record *R = *I;
+ std::string AsmCondString = R->getValueAsString("AssemblerCondString");
+
+ // AsmCondString has syntax [!]F(,[!]F)*
+ SmallVector<StringRef, 4> Ops;
+ SplitString(AsmCondString, Ops, ",");
+ assert(!Ops.empty() && "AssemblerCondString cannot be empty");
+
+ for (auto &Op : Ops) {
+ assert(!Op.empty() && "Empty operator");
+ if (Op[0] == '!')
+ Cond = "!STI.getFeatureBits()[" + Namespace + "::" +
+ Op.substr(1).str() + "]";
+ else
+ Cond = "STI.getFeatureBits()[" + Namespace + "::" + Op.str() + "]";
+ IAP.addCond(Cond);
+ }
+ }
+
+ IAPrinterMap[Aliases.first].push_back(std::move(IAP));
+ }
+ }
+
+ //////////////////////////////
+ // Write out the printAliasInstr function
+ //////////////////////////////
+
+ std::string Header;
+ raw_string_ostream HeaderO(Header);
+
+ HeaderO << "bool " << Target.getName() << ClassName
+ << "::printAliasInstr(const MCInst"
+ << " *MI, " << (PassSubtarget ? "const MCSubtargetInfo &STI, " : "")
+ << "raw_ostream &OS) {\n";
+
+ std::string Cases;
+ raw_string_ostream CasesO(Cases);
+
+ for (auto &Entry : IAPrinterMap) {
+ std::vector<IAPrinter> &IAPs = Entry.second;
+ std::vector<IAPrinter*> UniqueIAPs;
+
+ for (auto &LHS : IAPs) {
+ bool IsDup = false;
+ for (const auto &RHS : IAPs) {
+ if (&LHS != &RHS && LHS == RHS) {
+ IsDup = true;
+ break;
+ }
+ }
+
+ if (!IsDup)
+ UniqueIAPs.push_back(&LHS);
+ }
+
+ if (UniqueIAPs.empty()) continue;
+
+ CasesO.indent(2) << "case " << Entry.first << ":\n";
+
+ for (IAPrinter *IAP : UniqueIAPs) {
+ CasesO.indent(4);
+ IAP->print(CasesO);
+ CasesO << '\n';
+ }
+
+ CasesO.indent(4) << "return false;\n";
+ }
+
+ if (CasesO.str().empty()) {
+ O << HeaderO.str();
+ O << " return false;\n";
+ O << "}\n\n";
+ O << "#endif // PRINT_ALIAS_INSTR\n";
+ return;
+ }
+
+ if (!MCOpPredicates.empty())
+ O << "static bool " << Target.getName() << ClassName
+ << "ValidateMCOperand(const MCOperand &MCOp,\n"
+ << " const MCSubtargetInfo &STI,\n"
+ << " unsigned PredicateIndex);\n";
+
+ O << HeaderO.str();
+ O.indent(2) << "const char *AsmString;\n";
+ O.indent(2) << "switch (MI->getOpcode()) {\n";
+ O.indent(2) << "default: return false;\n";
+ O << CasesO.str();
+ O.indent(2) << "}\n\n";
+
+ // Code that prints the alias, replacing the operands with the ones from the
+ // MCInst.
+ O << " unsigned I = 0;\n";
+ O << " while (AsmString[I] != ' ' && AsmString[I] != '\\t' &&\n";
+ O << " AsmString[I] != '$' && AsmString[I] != '\\0')\n";
+ O << " ++I;\n";
+ O << " OS << '\\t' << StringRef(AsmString, I);\n";
+
+ O << " if (AsmString[I] != '\\0') {\n";
+ O << " if (AsmString[I] == ' ' || AsmString[I] == '\\t')";
+ O << " OS << '\\t';\n";
+ O << " do {\n";
+ O << " if (AsmString[I] == '$') {\n";
+ O << " ++I;\n";
+ O << " if (AsmString[I] == (char)0xff) {\n";
+ O << " ++I;\n";
+ O << " int OpIdx = AsmString[I++] - 1;\n";
+ O << " int PrintMethodIdx = AsmString[I++] - 1;\n";
+ O << " printCustomAliasOperand(MI, OpIdx, PrintMethodIdx, ";
+ O << (PassSubtarget ? "STI, " : "");
+ O << "OS);\n";
+ O << " } else\n";
+ O << " printOperand(MI, unsigned(AsmString[I++]) - 1, ";
+ O << (PassSubtarget ? "STI, " : "");
+ O << "OS);\n";
+ O << " } else {\n";
+ O << " OS << AsmString[I++];\n";
+ O << " }\n";
+ O << " } while (AsmString[I] != '\\0');\n";
+ O << " }\n\n";
+
+ O << " return true;\n";
+ O << "}\n\n";
+
+ //////////////////////////////
+ // Write out the printCustomAliasOperand function
+ //////////////////////////////
+
+ O << "void " << Target.getName() << ClassName << "::"
+ << "printCustomAliasOperand(\n"
+ << " const MCInst *MI, unsigned OpIdx,\n"
+ << " unsigned PrintMethodIdx,\n"
+ << (PassSubtarget ? " const MCSubtargetInfo &STI,\n" : "")
+ << " raw_ostream &OS) {\n";
+ if (PrintMethods.empty())
+ O << " llvm_unreachable(\"Unknown PrintMethod kind\");\n";
+ else {
+ O << " switch (PrintMethodIdx) {\n"
+ << " default:\n"
+ << " llvm_unreachable(\"Unknown PrintMethod kind\");\n"
+ << " break;\n";
+
+ for (unsigned i = 0; i < PrintMethods.size(); ++i) {
+ O << " case " << i << ":\n"
+ << " " << PrintMethods[i] << "(MI, OpIdx, "
+ << (PassSubtarget ? "STI, " : "") << "OS);\n"
+ << " break;\n";
+ }
+ O << " }\n";
+ }
+ O << "}\n\n";
+
+ if (!MCOpPredicates.empty()) {
+ O << "static bool " << Target.getName() << ClassName
+ << "ValidateMCOperand(const MCOperand &MCOp,\n"
+ << " const MCSubtargetInfo &STI,\n"
+ << " unsigned PredicateIndex) {\n"
+ << " switch (PredicateIndex) {\n"
+ << " default:\n"
+ << " llvm_unreachable(\"Unknown MCOperandPredicate kind\");\n"
+ << " break;\n";
+
+ for (unsigned i = 0; i < MCOpPredicates.size(); ++i) {
+ Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate");
+ if (CodeInit *SI = dyn_cast<CodeInit>(MCOpPred)) {
+ O << " case " << i + 1 << ": {\n"
+ << SI->getValue() << "\n"
+ << " }\n";
+ } else
+ llvm_unreachable("Unexpected MCOperandPredicate field!");
+ }
+ O << " }\n"
+ << "}\n\n";
+ }
+
+ O << "#endif // PRINT_ALIAS_INSTR\n";
+}
+
+AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) {
+ Record *AsmWriter = Target.getAsmWriter();
+ unsigned Variant = AsmWriter->getValueAsInt("Variant");
+
+ // Get the instruction numbering.
+ NumberedInstructions = Target.getInstructionsByEnumValue();
+
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
+ const CodeGenInstruction *I = NumberedInstructions[i];
+ if (!I->AsmString.empty() && I->TheDef->getName() != "PHI")
+ Instructions.emplace_back(*I, i, Variant);
+ }
+}
+
+void AsmWriterEmitter::run(raw_ostream &O) {
+ EmitPrintInstruction(O);
+ EmitGetRegisterName(O);
+ EmitPrintAliasInstruction(O);
+}
+
+namespace llvm {
+
+void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS) {
+ emitSourceFileHeader("Assembly Writer Source Fragment", OS);
+ AsmWriterEmitter(RK).run(OS);
+}
+
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/AsmWriterInst.cpp b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp
new file mode 100644
index 000000000000..2c19e5d663d6
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp
@@ -0,0 +1,197 @@
+//===- AsmWriterInst.h - Classes encapsulating a printable inst -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes implement a parser for assembly strings.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AsmWriterInst.h"
+#include "CodeGenTarget.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+
+using namespace llvm;
+
+static bool isIdentChar(char C) {
+ return (C >= 'a' && C <= 'z') ||
+ (C >= 'A' && C <= 'Z') ||
+ (C >= '0' && C <= '9') ||
+ C == '_';
+}
+
+std::string AsmWriterOperand::getCode(bool PassSubtarget) const {
+ if (OperandType == isLiteralTextOperand) {
+ if (Str.size() == 1)
+ return "O << '" + Str + "';";
+ return "O << \"" + Str + "\";";
+ }
+
+ if (OperandType == isLiteralStatementOperand)
+ return Str;
+
+ std::string Result = Str + "(MI";
+ if (MIOpNo != ~0U)
+ Result += ", " + utostr(MIOpNo);
+ if (PassSubtarget)
+ Result += ", STI";
+ Result += ", O";
+ if (!MiModifier.empty())
+ Result += ", \"" + MiModifier + '"';
+ return Result + ");";
+}
+
+/// ParseAsmString - Parse the specified Instruction's AsmString into this
+/// AsmWriterInst.
+///
+AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
+ unsigned Variant)
+ : CGI(&CGI), CGIIndex(CGIIndex) {
+
+ // NOTE: Any extensions to this code need to be mirrored in the
+ // AsmPrinter::printInlineAsm code that executes as compile time (assuming
+ // that inline asm strings should also get the new feature)!
+ std::string AsmString = CGI.FlattenAsmStringVariants(CGI.AsmString, Variant);
+ std::string::size_type LastEmitted = 0;
+ while (LastEmitted != AsmString.size()) {
+ std::string::size_type DollarPos =
+ AsmString.find_first_of("$\\", LastEmitted);
+ if (DollarPos == std::string::npos) DollarPos = AsmString.size();
+
+ // Emit a constant string fragment.
+ if (DollarPos != LastEmitted) {
+ for (; LastEmitted != DollarPos; ++LastEmitted)
+ switch (AsmString[LastEmitted]) {
+ case '\n':
+ AddLiteralString("\\n");
+ break;
+ case '\t':
+ AddLiteralString("\\t");
+ break;
+ case '"':
+ AddLiteralString("\\\"");
+ break;
+ case '\\':
+ AddLiteralString("\\\\");
+ break;
+ default:
+ AddLiteralString(std::string(1, AsmString[LastEmitted]));
+ break;
+ }
+ } else if (AsmString[DollarPos] == '\\') {
+ if (DollarPos+1 != AsmString.size()) {
+ if (AsmString[DollarPos+1] == 'n') {
+ AddLiteralString("\\n");
+ } else if (AsmString[DollarPos+1] == 't') {
+ AddLiteralString("\\t");
+ } else if (std::string("${|}\\").find(AsmString[DollarPos+1])
+ != std::string::npos) {
+ AddLiteralString(std::string(1, AsmString[DollarPos+1]));
+ } else {
+ PrintFatalError("Non-supported escaped character found in instruction '" +
+ CGI.TheDef->getName() + "'!");
+ }
+ LastEmitted = DollarPos+2;
+ continue;
+ }
+ } else if (DollarPos+1 != AsmString.size() &&
+ AsmString[DollarPos+1] == '$') {
+ AddLiteralString("$"); // "$$" -> $
+ LastEmitted = DollarPos+2;
+ } else {
+ // Get the name of the variable.
+ std::string::size_type VarEnd = DollarPos+1;
+
+ // handle ${foo}bar as $foo by detecting whether the character following
+ // the dollar sign is a curly brace. If so, advance VarEnd and DollarPos
+ // so the variable name does not contain the leading curly brace.
+ bool hasCurlyBraces = false;
+ if (VarEnd < AsmString.size() && '{' == AsmString[VarEnd]) {
+ hasCurlyBraces = true;
+ ++DollarPos;
+ ++VarEnd;
+ }
+
+ while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
+ ++VarEnd;
+ StringRef VarName(AsmString.data()+DollarPos+1, VarEnd-DollarPos-1);
+
+ // Modifier - Support ${foo:modifier} syntax, where "modifier" is passed
+ // into printOperand. Also support ${:feature}, which is passed into
+ // PrintSpecial.
+ std::string Modifier;
+
+ // In order to avoid starting the next string at the terminating curly
+ // brace, advance the end position past it if we found an opening curly
+ // brace.
+ if (hasCurlyBraces) {
+ if (VarEnd >= AsmString.size())
+ PrintFatalError("Reached end of string before terminating curly brace in '"
+ + CGI.TheDef->getName() + "'");
+
+ // Look for a modifier string.
+ if (AsmString[VarEnd] == ':') {
+ ++VarEnd;
+ if (VarEnd >= AsmString.size())
+ PrintFatalError("Reached end of string before terminating curly brace in '"
+ + CGI.TheDef->getName() + "'");
+
+ std::string::size_type ModifierStart = VarEnd;
+ while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
+ ++VarEnd;
+ Modifier = std::string(AsmString.begin()+ModifierStart,
+ AsmString.begin()+VarEnd);
+ if (Modifier.empty())
+ PrintFatalError("Bad operand modifier name in '"+ CGI.TheDef->getName() + "'");
+ }
+
+ if (AsmString[VarEnd] != '}')
+ PrintFatalError("Variable name beginning with '{' did not end with '}' in '"
+ + CGI.TheDef->getName() + "'");
+ ++VarEnd;
+ }
+ if (VarName.empty() && Modifier.empty())
+ PrintFatalError("Stray '$' in '" + CGI.TheDef->getName() +
+ "' asm string, maybe you want $$?");
+
+ if (VarName.empty()) {
+ // Just a modifier, pass this into PrintSpecial.
+ Operands.emplace_back("PrintSpecial", ~0U, Modifier);
+ } else {
+ // Otherwise, normal operand.
+ unsigned OpNo = CGI.Operands.getOperandNamed(VarName);
+ CGIOperandList::OperandInfo OpInfo = CGI.Operands[OpNo];
+
+ unsigned MIOp = OpInfo.MIOperandNo;
+ Operands.emplace_back(OpInfo.PrinterMethodName, MIOp, Modifier);
+ }
+ LastEmitted = VarEnd;
+ }
+ }
+
+ Operands.emplace_back("return;", AsmWriterOperand::isLiteralStatementOperand);
+}
+
+/// MatchesAllButOneOp - If this instruction is exactly identical to the
+/// specified instruction except for one differing operand, return the differing
+/// operand number. If more than one operand mismatches, return ~1, otherwise
+/// if the instructions are identical return ~0.
+unsigned AsmWriterInst::MatchesAllButOneOp(const AsmWriterInst &Other)const{
+ if (Operands.size() != Other.Operands.size()) return ~1;
+
+ unsigned MismatchOperand = ~0U;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (Operands[i] != Other.Operands[i]) {
+ if (MismatchOperand != ~0U) // Already have one mismatch?
+ return ~1U;
+ MismatchOperand = i;
+ }
+ }
+ return MismatchOperand;
+}
diff --git a/contrib/llvm/utils/TableGen/AsmWriterInst.h b/contrib/llvm/utils/TableGen/AsmWriterInst.h
new file mode 100644
index 000000000000..708f23cb5b0e
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/AsmWriterInst.h
@@ -0,0 +1,106 @@
+//===- AsmWriterInst.h - Classes encapsulating a printable inst -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These classes implement a parser for assembly strings. The parser splits
+// the string into operands, which can be literal strings (the constant bits of
+// the string), actual operands (i.e., operands from the MachineInstr), and
+// dynamically-generated text, specified by raw C++ code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_ASMWRITERINST_H
+#define LLVM_UTILS_TABLEGEN_ASMWRITERINST_H
+
+#include <string>
+#include <vector>
+
+namespace llvm {
+ class CodeGenInstruction;
+ class Record;
+
+ struct AsmWriterOperand {
+ enum OpType {
+ // Output this text surrounded by quotes to the asm.
+ isLiteralTextOperand,
+ // This is the name of a routine to call to print the operand.
+ isMachineInstrOperand,
+ // Output this text verbatim to the asm writer. It is code that
+ // will output some text to the asm.
+ isLiteralStatementOperand
+ } OperandType;
+
+ /// MiOpNo - For isMachineInstrOperand, this is the operand number of the
+ /// machine instruction.
+ unsigned MIOpNo;
+
+ /// Str - For isLiteralTextOperand, this IS the literal text. For
+ /// isMachineInstrOperand, this is the PrinterMethodName for the operand..
+ /// For isLiteralStatementOperand, this is the code to insert verbatim
+ /// into the asm writer.
+ std::string Str;
+
+ /// MiModifier - For isMachineInstrOperand, this is the modifier string for
+ /// an operand, specified with syntax like ${opname:modifier}.
+ std::string MiModifier;
+
+ // To make VS STL happy
+ AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {}
+
+ AsmWriterOperand(const std::string &LitStr,
+ OpType op = isLiteralTextOperand)
+ : OperandType(op), Str(LitStr) {}
+
+ AsmWriterOperand(const std::string &Printer,
+ unsigned _MIOpNo,
+ const std::string &Modifier,
+ OpType op = isMachineInstrOperand)
+ : OperandType(op), MIOpNo(_MIOpNo), Str(Printer), MiModifier(Modifier) {}
+
+ bool operator!=(const AsmWriterOperand &Other) const {
+ if (OperandType != Other.OperandType || Str != Other.Str) return true;
+ if (OperandType == isMachineInstrOperand)
+ return MIOpNo != Other.MIOpNo || MiModifier != Other.MiModifier;
+ return false;
+ }
+ bool operator==(const AsmWriterOperand &Other) const {
+ return !operator!=(Other);
+ }
+
+ /// getCode - Return the code that prints this operand.
+ std::string getCode(bool PassSubtarget) const;
+ };
+
+ class AsmWriterInst {
+ public:
+ std::vector<AsmWriterOperand> Operands;
+ const CodeGenInstruction *CGI;
+ unsigned CGIIndex;
+
+ AsmWriterInst(const CodeGenInstruction &CGI, unsigned CGIIndex,
+ unsigned Variant);
+
+ /// MatchesAllButOneOp - If this instruction is exactly identical to the
+ /// specified instruction except for one differing operand, return the
+ /// differing operand number. Otherwise return ~0.
+ unsigned MatchesAllButOneOp(const AsmWriterInst &Other) const;
+
+ private:
+ void AddLiteralString(const std::string &Str) {
+ // If the last operand was already a literal text string, append this to
+ // it, otherwise add a new operand.
+ if (!Operands.empty() &&
+ Operands.back().OperandType == AsmWriterOperand::isLiteralTextOperand)
+ Operands.back().Str.append(Str);
+ else
+ Operands.push_back(AsmWriterOperand(Str));
+ }
+ };
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/Attributes.cpp b/contrib/llvm/utils/TableGen/Attributes.cpp
new file mode 100644
index 000000000000..927f6e0e5b44
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/Attributes.cpp
@@ -0,0 +1,179 @@
+//===- Attributes.cpp - Generate attributes -------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include <algorithm>
+#include <string>
+#include <vector>
+using namespace llvm;
+
+#define DEBUG_TYPE "attr-enum"
+
+namespace {
+
+class Attributes {
+public:
+ Attributes(RecordKeeper &R) : Records(R) {}
+ void emit(raw_ostream &OS);
+
+private:
+ void emitTargetIndependentEnums(raw_ostream &OS);
+ void emitConversionFn(raw_ostream &OS);
+ void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
+
+ void printEnumAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records);
+ void printStrBoolAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records);
+
+ RecordKeeper &Records;
+};
+
+} // End anonymous namespace.
+
+void Attributes::emitTargetIndependentEnums(raw_ostream &OS) {
+ OS << "#ifdef GET_ATTR_ENUM\n";
+ OS << "#undef GET_ATTR_ENUM\n";
+
+ std::vector<Record*> Attrs =
+ Records.getAllDerivedDefinitions("EnumAttr");
+
+ for (auto A : Attrs)
+ OS << A->getName() << ",\n";
+
+ OS << "#endif\n";
+}
+
+void Attributes::emitConversionFn(raw_ostream &OS) {
+ OS << "#ifdef GET_ATTR_KIND_FROM_NAME\n";
+ OS << "#undef GET_ATTR_KIND_FROM_NAME\n";
+
+ std::vector<Record*> Attrs =
+ Records.getAllDerivedDefinitions("EnumAttr");
+
+ OS << "static Attribute::AttrKind getAttrKindFromName(StringRef AttrName) {\n";
+ OS << " return StringSwitch<Attribute::AttrKind>(AttrName)\n";
+
+ for (auto A : Attrs) {
+ OS << " .Case(\"" << A->getValueAsString("AttrString");
+ OS << "\", Attribute::" << A->getName() << ")\n";
+ }
+
+ OS << " .Default(Attribute::None);\n";
+ OS << "}\n\n";
+
+ OS << "#endif\n";
+}
+
+void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
+ OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
+ OS << "#undef GET_ATTR_COMPAT_FUNC\n";
+
+ OS << "struct EnumAttr {\n";
+ OS << " static bool isSet(const Function &Fn,\n";
+ OS << " Attribute::AttrKind Kind) {\n";
+ OS << " return Fn.hasFnAttribute(Kind);\n";
+ OS << " }\n\n";
+ OS << " static void set(Function &Fn,\n";
+ OS << " Attribute::AttrKind Kind, bool Val) {\n";
+ OS << " if (Val)\n";
+ OS << " Fn.addFnAttr(Kind);\n";
+ OS << " else\n";
+ OS << " Fn.removeFnAttr(Kind);\n";
+ OS << " }\n";
+ OS << "};\n\n";
+
+ OS << "struct StrBoolAttr {\n";
+ OS << " static bool isSet(const Function &Fn,\n";
+ OS << " StringRef Kind) {\n";
+ OS << " auto A = Fn.getFnAttribute(Kind);\n";
+ OS << " return A.getValueAsString().equals(\"true\");\n";
+ OS << " }\n\n";
+ OS << " static void set(Function &Fn,\n";
+ OS << " StringRef Kind, bool Val) {\n";
+ OS << " Fn.addFnAttr(Kind, Val ? \"true\" : \"false\");\n";
+ OS << " }\n";
+ OS << "};\n\n";
+
+ printEnumAttrClasses(OS ,Records.getAllDerivedDefinitions("EnumAttr"));
+ printStrBoolAttrClasses(OS , Records.getAllDerivedDefinitions("StrBoolAttr"));
+
+ OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
+ << " const Function &Callee) {\n";
+ OS << " bool Ret = true;\n\n";
+
+ std::vector<Record *> CompatRules =
+ Records.getAllDerivedDefinitions("CompatRule");
+
+ for (auto *Rule : CompatRules) {
+ std::string FuncName = Rule->getValueAsString("CompatFunc");
+ OS << " Ret &= " << FuncName << "(Caller, Callee);\n";
+ }
+
+ OS << "\n";
+ OS << " return Ret;\n";
+ OS << "}\n\n";
+
+ std::vector<Record *> MergeRules =
+ Records.getAllDerivedDefinitions("MergeRule");
+ OS << "static inline void mergeFnAttrs(Function &Caller,\n"
+ << " const Function &Callee) {\n";
+
+ for (auto *Rule : MergeRules) {
+ std::string FuncName = Rule->getValueAsString("MergeFunc");
+ OS << " " << FuncName << "(Caller, Callee);\n";
+ }
+
+ OS << "}\n\n";
+
+ OS << "#endif\n";
+}
+
+void Attributes::printEnumAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records) {
+ OS << "// EnumAttr classes\n";
+ for (const auto *R : Records) {
+ OS << "struct " << R->getName() << "Attr : EnumAttr {\n";
+ OS << " static enum Attribute::AttrKind getKind() {\n";
+ OS << " return llvm::Attribute::" << R->getName() << ";\n";
+ OS << " }\n";
+ OS << "};\n";
+ }
+ OS << "\n";
+}
+
+void Attributes::printStrBoolAttrClasses(raw_ostream &OS,
+ const std::vector<Record *> &Records) {
+ OS << "// StrBoolAttr classes\n";
+ for (const auto *R : Records) {
+ OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n";
+ OS << " static StringRef getKind() {\n";
+ OS << " return \"" << R->getValueAsString("AttrString") << "\";\n";
+ OS << " }\n";
+ OS << "};\n";
+ }
+ OS << "\n";
+}
+
+void Attributes::emit(raw_ostream &OS) {
+ emitTargetIndependentEnums(OS);
+ emitConversionFn(OS);
+ emitFnAttrCompatCheck(OS, false);
+}
+
+namespace llvm {
+
+void EmitAttributes(RecordKeeper &RK, raw_ostream &OS) {
+ Attributes(RK).emit(OS);
+}
+
+} // End llvm namespace.
diff --git a/contrib/llvm/utils/TableGen/CTagsEmitter.cpp b/contrib/llvm/utils/TableGen/CTagsEmitter.cpp
new file mode 100644
index 000000000000..5213cd904462
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CTagsEmitter.cpp
@@ -0,0 +1,87 @@
+//===- CTagsEmitter.cpp - Generate ctags-compatible index ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits an index of definitions in ctags(1) format.
+// A helper script, utils/TableGen/tdtags, provides an easier-to-use
+// interface; run 'tdtags -H' for documentation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include <algorithm>
+#include <string>
+#include <vector>
+using namespace llvm;
+
+#define DEBUG_TYPE "ctags-emitter"
+
+namespace {
+
+class Tag {
+private:
+ const std::string *Id;
+ SMLoc Loc;
+public:
+ Tag(const std::string &Name, const SMLoc Location)
+ : Id(&Name), Loc(Location) {}
+ int operator<(const Tag &B) const { return *Id < *B.Id; }
+ void emit(raw_ostream &OS) const {
+ const MemoryBuffer *CurMB =
+ SrcMgr.getMemoryBuffer(SrcMgr.FindBufferContainingLoc(Loc));
+ auto BufferName = CurMB->getBufferIdentifier();
+ std::pair<unsigned, unsigned> LineAndColumn = SrcMgr.getLineAndColumn(Loc);
+ OS << *Id << "\t" << BufferName << "\t" << LineAndColumn.first << "\n";
+ }
+};
+
+class CTagsEmitter {
+private:
+ RecordKeeper &Records;
+public:
+ CTagsEmitter(RecordKeeper &R) : Records(R) {}
+
+ void run(raw_ostream &OS);
+
+private:
+ static SMLoc locate(const Record *R);
+};
+
+} // End anonymous namespace.
+
+SMLoc CTagsEmitter::locate(const Record *R) {
+ ArrayRef<SMLoc> Locs = R->getLoc();
+ return !Locs.empty() ? Locs.front() : SMLoc();
+}
+
+void CTagsEmitter::run(raw_ostream &OS) {
+ const auto &Classes = Records.getClasses();
+ const auto &Defs = Records.getDefs();
+ std::vector<Tag> Tags;
+ // Collect tags.
+ Tags.reserve(Classes.size() + Defs.size());
+ for (const auto &C : Classes)
+ Tags.push_back(Tag(C.first, locate(C.second.get())));
+ for (const auto &D : Defs)
+ Tags.push_back(Tag(D.first, locate(D.second.get())));
+ // Emit tags.
+ std::sort(Tags.begin(), Tags.end());
+ OS << "!_TAG_FILE_FORMAT\t1\t/original ctags format/\n";
+ OS << "!_TAG_FILE_SORTED\t1\t/0=unsorted, 1=sorted, 2=foldcase/\n";
+ for (const Tag &T : Tags)
+ T.emit(OS);
+}
+
+namespace llvm {
+
+void EmitCTags(RecordKeeper &RK, raw_ostream &OS) { CTagsEmitter(RK).run(OS); }
+
+} // End llvm namespace.
diff --git a/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp
new file mode 100644
index 000000000000..013e96065752
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CallingConvEmitter.cpp
@@ -0,0 +1,284 @@
+//===- CallingConvEmitter.cpp - Generate calling conventions --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting descriptions of the calling
+// conventions supported by this target.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenTarget.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <cassert>
+using namespace llvm;
+
+namespace {
+class CallingConvEmitter {
+ RecordKeeper &Records;
+public:
+ explicit CallingConvEmitter(RecordKeeper &R) : Records(R) {}
+
+ void run(raw_ostream &o);
+
+private:
+ void EmitCallingConv(Record *CC, raw_ostream &O);
+ void EmitAction(Record *Action, unsigned Indent, raw_ostream &O);
+ unsigned Counter;
+};
+} // End anonymous namespace
+
+void CallingConvEmitter::run(raw_ostream &O) {
+ std::vector<Record*> CCs = Records.getAllDerivedDefinitions("CallingConv");
+
+ // Emit prototypes for all of the non-custom CC's so that they can forward ref
+ // each other.
+ for (unsigned i = 0, e = CCs.size(); i != e; ++i) {
+ if (!CCs[i]->getValueAsBit("Custom")) {
+ O << "static bool " << CCs[i]->getName()
+ << "(unsigned ValNo, MVT ValVT,\n"
+ << std::string(CCs[i]->getName().size() + 13, ' ')
+ << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
+ << std::string(CCs[i]->getName().size() + 13, ' ')
+ << "ISD::ArgFlagsTy ArgFlags, CCState &State);\n";
+ }
+ }
+
+ // Emit each non-custom calling convention description in full.
+ for (unsigned i = 0, e = CCs.size(); i != e; ++i) {
+ if (!CCs[i]->getValueAsBit("Custom"))
+ EmitCallingConv(CCs[i], O);
+ }
+}
+
+
+void CallingConvEmitter::EmitCallingConv(Record *CC, raw_ostream &O) {
+ ListInit *CCActions = CC->getValueAsListInit("Actions");
+ Counter = 0;
+
+ O << "\n\nstatic bool " << CC->getName()
+ << "(unsigned ValNo, MVT ValVT,\n"
+ << std::string(CC->getName().size()+13, ' ')
+ << "MVT LocVT, CCValAssign::LocInfo LocInfo,\n"
+ << std::string(CC->getName().size()+13, ' ')
+ << "ISD::ArgFlagsTy ArgFlags, CCState &State) {\n";
+ // Emit all of the actions, in order.
+ for (unsigned i = 0, e = CCActions->size(); i != e; ++i) {
+ O << "\n";
+ EmitAction(CCActions->getElementAsRecord(i), 2, O);
+ }
+
+ O << "\n return true; // CC didn't match.\n";
+ O << "}\n";
+}
+
+void CallingConvEmitter::EmitAction(Record *Action,
+ unsigned Indent, raw_ostream &O) {
+ std::string IndentStr = std::string(Indent, ' ');
+
+ if (Action->isSubClassOf("CCPredicateAction")) {
+ O << IndentStr << "if (";
+
+ if (Action->isSubClassOf("CCIfType")) {
+ ListInit *VTs = Action->getValueAsListInit("VTs");
+ for (unsigned i = 0, e = VTs->size(); i != e; ++i) {
+ Record *VT = VTs->getElementAsRecord(i);
+ if (i != 0) O << " ||\n " << IndentStr;
+ O << "LocVT == " << getEnumName(getValueType(VT));
+ }
+
+ } else if (Action->isSubClassOf("CCIf")) {
+ O << Action->getValueAsString("Predicate");
+ } else {
+ errs() << *Action;
+ PrintFatalError("Unknown CCPredicateAction!");
+ }
+
+ O << ") {\n";
+ EmitAction(Action->getValueAsDef("SubAction"), Indent+2, O);
+ O << IndentStr << "}\n";
+ } else {
+ if (Action->isSubClassOf("CCDelegateTo")) {
+ Record *CC = Action->getValueAsDef("CC");
+ O << IndentStr << "if (!" << CC->getName()
+ << "(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State))\n"
+ << IndentStr << " return false;\n";
+ } else if (Action->isSubClassOf("CCAssignToReg")) {
+ ListInit *RegList = Action->getValueAsListInit("RegList");
+ if (RegList->size() == 1) {
+ O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
+ O << getQualifiedName(RegList->getElementAsRecord(0)) << ")) {\n";
+ } else {
+ O << IndentStr << "static const MCPhysReg RegList" << ++Counter
+ << "[] = {\n";
+ O << IndentStr << " ";
+ for (unsigned i = 0, e = RegList->size(); i != e; ++i) {
+ if (i != 0) O << ", ";
+ O << getQualifiedName(RegList->getElementAsRecord(i));
+ }
+ O << "\n" << IndentStr << "};\n";
+ O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
+ << Counter << ")) {\n";
+ }
+ O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
+ << "Reg, LocVT, LocInfo));\n";
+ O << IndentStr << " return false;\n";
+ O << IndentStr << "}\n";
+ } else if (Action->isSubClassOf("CCAssignToRegWithShadow")) {
+ ListInit *RegList = Action->getValueAsListInit("RegList");
+ ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
+ if (!ShadowRegList->empty() && ShadowRegList->size() != RegList->size())
+ PrintFatalError("Invalid length of list of shadowed registers");
+
+ if (RegList->size() == 1) {
+ O << IndentStr << "if (unsigned Reg = State.AllocateReg(";
+ O << getQualifiedName(RegList->getElementAsRecord(0));
+ O << ", " << getQualifiedName(ShadowRegList->getElementAsRecord(0));
+ O << ")) {\n";
+ } else {
+ unsigned RegListNumber = ++Counter;
+ unsigned ShadowRegListNumber = ++Counter;
+
+ O << IndentStr << "static const MCPhysReg RegList" << RegListNumber
+ << "[] = {\n";
+ O << IndentStr << " ";
+ for (unsigned i = 0, e = RegList->size(); i != e; ++i) {
+ if (i != 0) O << ", ";
+ O << getQualifiedName(RegList->getElementAsRecord(i));
+ }
+ O << "\n" << IndentStr << "};\n";
+
+ O << IndentStr << "static const MCPhysReg RegList"
+ << ShadowRegListNumber << "[] = {\n";
+ O << IndentStr << " ";
+ for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) {
+ if (i != 0) O << ", ";
+ O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
+ }
+ O << "\n" << IndentStr << "};\n";
+
+ O << IndentStr << "if (unsigned Reg = State.AllocateReg(RegList"
+ << RegListNumber << ", " << "RegList" << ShadowRegListNumber
+ << ")) {\n";
+ }
+ O << IndentStr << " State.addLoc(CCValAssign::getReg(ValNo, ValVT, "
+ << "Reg, LocVT, LocInfo));\n";
+ O << IndentStr << " return false;\n";
+ O << IndentStr << "}\n";
+ } else if (Action->isSubClassOf("CCAssignToStack")) {
+ int Size = Action->getValueAsInt("Size");
+ int Align = Action->getValueAsInt("Align");
+
+ O << IndentStr << "unsigned Offset" << ++Counter
+ << " = State.AllocateStack(";
+ if (Size)
+ O << Size << ", ";
+ else
+ O << "\n" << IndentStr
+ << " State.getMachineFunction().getDataLayout()."
+ "getTypeAllocSize(EVT(LocVT).getTypeForEVT(State.getContext())),"
+ " ";
+ if (Align)
+ O << Align;
+ else
+ O << "\n" << IndentStr
+ << " State.getMachineFunction().getDataLayout()."
+ "getABITypeAlignment(EVT(LocVT).getTypeForEVT(State.getContext()"
+ "))";
+ O << ");\n" << IndentStr
+ << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
+ << Counter << ", LocVT, LocInfo));\n";
+ O << IndentStr << "return false;\n";
+ } else if (Action->isSubClassOf("CCAssignToStackWithShadow")) {
+ int Size = Action->getValueAsInt("Size");
+ int Align = Action->getValueAsInt("Align");
+ ListInit *ShadowRegList = Action->getValueAsListInit("ShadowRegList");
+
+ unsigned ShadowRegListNumber = ++Counter;
+
+ O << IndentStr << "static const MCPhysReg ShadowRegList"
+ << ShadowRegListNumber << "[] = {\n";
+ O << IndentStr << " ";
+ for (unsigned i = 0, e = ShadowRegList->size(); i != e; ++i) {
+ if (i != 0) O << ", ";
+ O << getQualifiedName(ShadowRegList->getElementAsRecord(i));
+ }
+ O << "\n" << IndentStr << "};\n";
+
+ O << IndentStr << "unsigned Offset" << ++Counter
+ << " = State.AllocateStack("
+ << Size << ", " << Align << ", "
+ << "ShadowRegList" << ShadowRegListNumber << ");\n";
+ O << IndentStr << "State.addLoc(CCValAssign::getMem(ValNo, ValVT, Offset"
+ << Counter << ", LocVT, LocInfo));\n";
+ O << IndentStr << "return false;\n";
+ } else if (Action->isSubClassOf("CCPromoteToType")) {
+ Record *DestTy = Action->getValueAsDef("DestTy");
+ MVT::SimpleValueType DestVT = getValueType(DestTy);
+ O << IndentStr << "LocVT = " << getEnumName(DestVT) <<";\n";
+ if (MVT(DestVT).isFloatingPoint()) {
+ O << IndentStr << "LocInfo = CCValAssign::FPExt;\n";
+ } else {
+ O << IndentStr << "if (ArgFlags.isSExt())\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::SExt;\n"
+ << IndentStr << "else if (ArgFlags.isZExt())\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExt;\n"
+ << IndentStr << "else\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::AExt;\n";
+ }
+ } else if (Action->isSubClassOf("CCPromoteToUpperBitsInType")) {
+ Record *DestTy = Action->getValueAsDef("DestTy");
+ MVT::SimpleValueType DestVT = getValueType(DestTy);
+ O << IndentStr << "LocVT = " << getEnumName(DestVT) << ";\n";
+ if (MVT(DestVT).isFloatingPoint()) {
+ PrintFatalError("CCPromoteToUpperBitsInType does not handle floating "
+ "point");
+ } else {
+ O << IndentStr << "if (ArgFlags.isSExt())\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::SExtUpper;\n"
+ << IndentStr << "else if (ArgFlags.isZExt())\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::ZExtUpper;\n"
+ << IndentStr << "else\n"
+ << IndentStr << IndentStr << "LocInfo = CCValAssign::AExtUpper;\n";
+ }
+ } else if (Action->isSubClassOf("CCBitConvertToType")) {
+ Record *DestTy = Action->getValueAsDef("DestTy");
+ O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
+ O << IndentStr << "LocInfo = CCValAssign::BCvt;\n";
+ } else if (Action->isSubClassOf("CCPassIndirect")) {
+ Record *DestTy = Action->getValueAsDef("DestTy");
+ O << IndentStr << "LocVT = " << getEnumName(getValueType(DestTy)) <<";\n";
+ O << IndentStr << "LocInfo = CCValAssign::Indirect;\n";
+ } else if (Action->isSubClassOf("CCPassByVal")) {
+ int Size = Action->getValueAsInt("Size");
+ int Align = Action->getValueAsInt("Align");
+ O << IndentStr
+ << "State.HandleByVal(ValNo, ValVT, LocVT, LocInfo, "
+ << Size << ", " << Align << ", ArgFlags);\n";
+ O << IndentStr << "return false;\n";
+ } else if (Action->isSubClassOf("CCCustom")) {
+ O << IndentStr
+ << "if (" << Action->getValueAsString("FuncName") << "(ValNo, ValVT, "
+ << "LocVT, LocInfo, ArgFlags, State))\n";
+ O << IndentStr << IndentStr << "return false;\n";
+ } else {
+ errs() << *Action;
+ PrintFatalError("Unknown CCAction!");
+ }
+ }
+}
+
+namespace llvm {
+
+void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS) {
+ emitSourceFileHeader("Calling Convention Implementation Fragment", OS);
+ CallingConvEmitter(RK).run(OS);
+}
+
+} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
new file mode 100644
index 000000000000..f34c0ded0a35
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -0,0 +1,394 @@
+//===- CodeEmitterGen.cpp - Code Emitter Generator ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// CodeEmitterGen uses the descriptions of instructions and their fields to
+// construct an automated code emitter: a function that, given a MachineInstr,
+// returns the (currently, 32-bit unsigned) value of the instruction.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenInstruction.h"
+#include "CodeGenTarget.h"
+#include "SubtargetFeatureInfo.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <cassert>
+#include <cstdint>
+#include <map>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+
+class CodeEmitterGen {
+ RecordKeeper &Records;
+
+public:
+ CodeEmitterGen(RecordKeeper &R) : Records(R) {}
+
+ void run(raw_ostream &o);
+
+private:
+ int getVariableBit(const std::string &VarName, BitsInit *BI, int bit);
+ std::string getInstructionCase(Record *R, CodeGenTarget &Target);
+ void AddCodeToMergeInOperand(Record *R, BitsInit *BI,
+ const std::string &VarName,
+ unsigned &NumberedOp,
+ std::set<unsigned> &NamedOpIndices,
+ std::string &Case, CodeGenTarget &Target);
+
+};
+
+// If the VarBitInit at position 'bit' matches the specified variable then
+// return the variable bit position. Otherwise return -1.
+int CodeEmitterGen::getVariableBit(const std::string &VarName,
+ BitsInit *BI, int bit) {
+ if (VarBitInit *VBI = dyn_cast<VarBitInit>(BI->getBit(bit))) {
+ if (VarInit *VI = dyn_cast<VarInit>(VBI->getBitVar()))
+ if (VI->getName() == VarName)
+ return VBI->getBitNum();
+ } else if (VarInit *VI = dyn_cast<VarInit>(BI->getBit(bit))) {
+ if (VI->getName() == VarName)
+ return 0;
+ }
+
+ return -1;
+}
+
+void CodeEmitterGen::
+AddCodeToMergeInOperand(Record *R, BitsInit *BI, const std::string &VarName,
+ unsigned &NumberedOp,
+ std::set<unsigned> &NamedOpIndices,
+ std::string &Case, CodeGenTarget &Target) {
+ CodeGenInstruction &CGI = Target.getInstruction(R);
+
+ // Determine if VarName actually contributes to the Inst encoding.
+ int bit = BI->getNumBits()-1;
+
+ // Scan for a bit that this contributed to.
+ for (; bit >= 0; ) {
+ if (getVariableBit(VarName, BI, bit) != -1)
+ break;
+
+ --bit;
+ }
+
+ // If we found no bits, ignore this value, otherwise emit the call to get the
+ // operand encoding.
+ if (bit < 0) return;
+
+ // If the operand matches by name, reference according to that
+ // operand number. Non-matching operands are assumed to be in
+ // order.
+ unsigned OpIdx;
+ if (CGI.Operands.hasOperandNamed(VarName, OpIdx)) {
+ // Get the machine operand number for the indicated operand.
+ OpIdx = CGI.Operands[OpIdx].MIOperandNo;
+ assert(!CGI.Operands.isFlatOperandNotEmitted(OpIdx) &&
+ "Explicitly used operand also marked as not emitted!");
+ } else {
+ unsigned NumberOps = CGI.Operands.size();
+ /// If this operand is not supposed to be emitted by the
+ /// generated emitter, skip it.
+ while (NumberedOp < NumberOps &&
+ (CGI.Operands.isFlatOperandNotEmitted(NumberedOp) ||
+ (!NamedOpIndices.empty() && NamedOpIndices.count(
+ CGI.Operands.getSubOperandNumber(NumberedOp).first)))) {
+ ++NumberedOp;
+
+ if (NumberedOp >= CGI.Operands.back().MIOperandNo +
+ CGI.Operands.back().MINumOperands) {
+ errs() << "Too few operands in record " << R->getName() <<
+ " (no match for variable " << VarName << "):\n";
+ errs() << *R;
+ errs() << '\n';
+
+ return;
+ }
+ }
+
+ OpIdx = NumberedOp++;
+ }
+
+ std::pair<unsigned, unsigned> SO = CGI.Operands.getSubOperandNumber(OpIdx);
+ std::string &EncoderMethodName = CGI.Operands[SO.first].EncoderMethodName;
+
+ // If the source operand has a custom encoder, use it. This will
+ // get the encoding for all of the suboperands.
+ if (!EncoderMethodName.empty()) {
+ // A custom encoder has all of the information for the
+ // sub-operands, if there are more than one, so only
+ // query the encoder once per source operand.
+ if (SO.second == 0) {
+ Case += " // op: " + VarName + "\n" +
+ " op = " + EncoderMethodName + "(MI, " + utostr(OpIdx);
+ Case += ", Fixups, STI";
+ Case += ");\n";
+ }
+ } else {
+ Case += " // op: " + VarName + "\n" +
+ " op = getMachineOpValue(MI, MI.getOperand(" + utostr(OpIdx) + ")";
+ Case += ", Fixups, STI";
+ Case += ");\n";
+ }
+
+ for (; bit >= 0; ) {
+ int varBit = getVariableBit(VarName, BI, bit);
+
+ // If this bit isn't from a variable, skip it.
+ if (varBit == -1) {
+ --bit;
+ continue;
+ }
+
+ // Figure out the consecutive range of bits covered by this operand, in
+ // order to generate better encoding code.
+ int beginInstBit = bit;
+ int beginVarBit = varBit;
+ int N = 1;
+ for (--bit; bit >= 0;) {
+ varBit = getVariableBit(VarName, BI, bit);
+ if (varBit == -1 || varBit != (beginVarBit - N)) break;
+ ++N;
+ --bit;
+ }
+
+ uint64_t opMask = ~(uint64_t)0 >> (64-N);
+ int opShift = beginVarBit - N + 1;
+ opMask <<= opShift;
+ opShift = beginInstBit - beginVarBit;
+
+ if (opShift > 0) {
+ Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) << " +
+ itostr(opShift) + ";\n";
+ } else if (opShift < 0) {
+ Case += " Value |= (op & UINT64_C(" + utostr(opMask) + ")) >> " +
+ itostr(-opShift) + ";\n";
+ } else {
+ Case += " Value |= op & UINT64_C(" + utostr(opMask) + ");\n";
+ }
+ }
+}
+
+std::string CodeEmitterGen::getInstructionCase(Record *R,
+ CodeGenTarget &Target) {
+ std::string Case;
+
+ BitsInit *BI = R->getValueAsBitsInit("Inst");
+ const std::vector<RecordVal> &Vals = R->getValues();
+ unsigned NumberedOp = 0;
+
+ std::set<unsigned> NamedOpIndices;
+ // Collect the set of operand indices that might correspond to named
+ // operand, and skip these when assigning operands based on position.
+ if (Target.getInstructionSet()->
+ getValueAsBit("noNamedPositionallyEncodedOperands")) {
+ CodeGenInstruction &CGI = Target.getInstruction(R);
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ unsigned OpIdx;
+ if (!CGI.Operands.hasOperandNamed(Vals[i].getName(), OpIdx))
+ continue;
+
+ NamedOpIndices.insert(OpIdx);
+ }
+ }
+
+ // Loop over all of the fields in the instruction, determining which are the
+ // operands to the instruction.
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ // Ignore fixed fields in the record, we're looking for values like:
+ // bits<5> RST = { ?, ?, ?, ?, ? };
+ if (Vals[i].getPrefix() || Vals[i].getValue()->isComplete())
+ continue;
+
+ AddCodeToMergeInOperand(R, BI, Vals[i].getName(), NumberedOp,
+ NamedOpIndices, Case, Target);
+ }
+
+ std::string PostEmitter = R->getValueAsString("PostEncoderMethod");
+ if (!PostEmitter.empty()) {
+ Case += " Value = " + PostEmitter + "(MI, Value";
+ Case += ", STI";
+ Case += ");\n";
+ }
+
+ return Case;
+}
+
+void CodeEmitterGen::run(raw_ostream &o) {
+ CodeGenTarget Target(Records);
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+
+ // For little-endian instruction bit encodings, reverse the bit order
+ Target.reverseBitsForLittleEndianEncoding();
+
+ ArrayRef<const CodeGenInstruction*> NumberedInstructions =
+ Target.getInstructionsByEnumValue();
+
+ // Emit function declaration
+ o << "uint64_t " << Target.getName();
+ o << "MCCodeEmitter::getBinaryCodeForInstr(const MCInst &MI,\n"
+ << " SmallVectorImpl<MCFixup> &Fixups,\n"
+ << " const MCSubtargetInfo &STI) const {\n";
+
+ // Emit instruction base values
+ o << " static const uint64_t InstBits[] = {\n";
+ for (const CodeGenInstruction *CGI : NumberedInstructions) {
+ Record *R = CGI->TheDef;
+
+ if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+ R->getValueAsBit("isPseudo")) {
+ o << " UINT64_C(0),\n";
+ continue;
+ }
+
+ BitsInit *BI = R->getValueAsBitsInit("Inst");
+
+ // Start by filling in fixed values.
+ uint64_t Value = 0;
+ for (unsigned i = 0, e = BI->getNumBits(); i != e; ++i) {
+ if (BitInit *B = dyn_cast<BitInit>(BI->getBit(e-i-1)))
+ Value |= (uint64_t)B->getValue() << (e-i-1);
+ }
+ o << " UINT64_C(" << Value << ")," << '\t' << "// " << R->getName() << "\n";
+ }
+ o << " UINT64_C(0)\n };\n";
+
+ // Map to accumulate all the cases.
+ std::map<std::string, std::vector<std::string>> CaseMap;
+
+ // Construct all cases statement for each opcode
+ for (std::vector<Record*>::iterator IC = Insts.begin(), EC = Insts.end();
+ IC != EC; ++IC) {
+ Record *R = *IC;
+ if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+ R->getValueAsBit("isPseudo"))
+ continue;
+ const std::string &InstName = R->getValueAsString("Namespace") + "::"
+ + R->getName().str();
+ std::string Case = getInstructionCase(R, Target);
+
+ CaseMap[Case].push_back(InstName);
+ }
+
+ // Emit initial function code
+ o << " const unsigned opcode = MI.getOpcode();\n"
+ << " uint64_t Value = InstBits[opcode];\n"
+ << " uint64_t op = 0;\n"
+ << " (void)op; // suppress warning\n"
+ << " switch (opcode) {\n";
+
+ // Emit each case statement
+ std::map<std::string, std::vector<std::string>>::iterator IE, EE;
+ for (IE = CaseMap.begin(), EE = CaseMap.end(); IE != EE; ++IE) {
+ const std::string &Case = IE->first;
+ std::vector<std::string> &InstList = IE->second;
+
+ for (int i = 0, N = InstList.size(); i < N; i++) {
+ if (i) o << "\n";
+ o << " case " << InstList[i] << ":";
+ }
+ o << " {\n";
+ o << Case;
+ o << " break;\n"
+ << " }\n";
+ }
+
+ // Default case: unhandled opcode
+ o << " default:\n"
+ << " std::string msg;\n"
+ << " raw_string_ostream Msg(msg);\n"
+ << " Msg << \"Not supported instr: \" << MI;\n"
+ << " report_fatal_error(Msg.str());\n"
+ << " }\n"
+ << " return Value;\n"
+ << "}\n\n";
+
+ const auto &All = SubtargetFeatureInfo::getAll(Records);
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID> SubtargetFeatures;
+ SubtargetFeatures.insert(All.begin(), All.end());
+
+ o << "#ifdef ENABLE_INSTR_PREDICATE_VERIFIER\n"
+ << "#undef ENABLE_INSTR_PREDICATE_VERIFIER\n"
+ << "#include <sstream>\n\n";
+
+ // Emit the subtarget feature enumeration.
+ SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(SubtargetFeatures,
+ o);
+
+ // Emit the name table for error messages.
+ o << "#ifndef NDEBUG\n";
+ SubtargetFeatureInfo::emitNameTable(SubtargetFeatures, o);
+ o << "#endif // NDEBUG\n";
+
+ // Emit the available features compute function.
+ SubtargetFeatureInfo::emitComputeAvailableFeatures(
+ Target.getName(), "MCCodeEmitter", "computeAvailableFeatures",
+ SubtargetFeatures, o);
+
+ // Emit the predicate verifier.
+ o << "void " << Target.getName()
+ << "MCCodeEmitter::verifyInstructionPredicates(\n"
+ << " const MCInst &Inst, uint64_t AvailableFeatures) const {\n"
+ << "#ifndef NDEBUG\n"
+ << " static uint64_t RequiredFeatures[] = {\n";
+ unsigned InstIdx = 0;
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ o << " ";
+ for (Record *Predicate : Inst->TheDef->getValueAsListOfDefs("Predicates")) {
+ const auto &I = SubtargetFeatures.find(Predicate);
+ if (I != SubtargetFeatures.end())
+ o << I->second.getEnumName() << " | ";
+ }
+ o << "0, // " << Inst->TheDef->getName() << " = " << InstIdx << "\n";
+ InstIdx++;
+ }
+ o << " };\n\n";
+ o << " assert(Inst.getOpcode() < " << InstIdx << ");\n";
+ o << " uint64_t MissingFeatures =\n"
+ << " (AvailableFeatures & RequiredFeatures[Inst.getOpcode()]) ^\n"
+ << " RequiredFeatures[Inst.getOpcode()];\n"
+ << " if (MissingFeatures) {\n"
+ << " std::ostringstream Msg;\n"
+ << " Msg << \"Attempting to emit \" << "
+ "MCII.getName(Inst.getOpcode()).str()\n"
+ << " << \" instruction but the \";\n"
+ << " for (unsigned i = 0; i < 8 * sizeof(MissingFeatures); ++i)\n"
+ << " if (MissingFeatures & (1ULL << i))\n"
+ << " Msg << SubtargetFeatureNames[i] << \" \";\n"
+ << " Msg << \"predicate(s) are not met\";\n"
+ << " report_fatal_error(Msg.str());\n"
+ << " }\n"
+ << "#else\n"
+ << "// Silence unused variable warning on targets that don't use MCII for "
+ "other purposes (e.g. BPF).\n"
+ << "(void)MCII;\n"
+ << "#endif // NDEBUG\n";
+ o << "}\n";
+ o << "#endif\n";
+}
+
+} // end anonymous namespace
+
+namespace llvm {
+
+void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS) {
+ emitSourceFileHeader("Machine Code Emitter", OS);
+ CodeEmitterGen(RK).run(OS);
+}
+
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
new file mode 100644
index 000000000000..972eb9cd3403
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -0,0 +1,3852 @@
+//===- CodeGenDAGPatterns.cpp - Read DAG patterns from .td file -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the CodeGenDAGPatterns class, which is used to read and
+// represent the patterns present in a .td file for instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenDAGPatterns.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include <algorithm>
+#include <cstdio>
+#include <set>
+using namespace llvm;
+
+#define DEBUG_TYPE "dag-patterns"
+
+//===----------------------------------------------------------------------===//
+// EEVT::TypeSet Implementation
+//===----------------------------------------------------------------------===//
+
+static inline bool isInteger(MVT::SimpleValueType VT) {
+ return MVT(VT).isInteger();
+}
+static inline bool isFloatingPoint(MVT::SimpleValueType VT) {
+ return MVT(VT).isFloatingPoint();
+}
+static inline bool isVector(MVT::SimpleValueType VT) {
+ return MVT(VT).isVector();
+}
+static inline bool isScalar(MVT::SimpleValueType VT) {
+ return !MVT(VT).isVector();
+}
+
+EEVT::TypeSet::TypeSet(MVT::SimpleValueType VT, TreePattern &TP) {
+ if (VT == MVT::iAny)
+ EnforceInteger(TP);
+ else if (VT == MVT::fAny)
+ EnforceFloatingPoint(TP);
+ else if (VT == MVT::vAny)
+ EnforceVector(TP);
+ else {
+ assert((VT < MVT::LAST_VALUETYPE || VT == MVT::iPTR ||
+ VT == MVT::iPTRAny || VT == MVT::Any) && "Not a concrete type!");
+ TypeVec.push_back(VT);
+ }
+}
+
+
+EEVT::TypeSet::TypeSet(ArrayRef<MVT::SimpleValueType> VTList) {
+ assert(!VTList.empty() && "empty list?");
+ TypeVec.append(VTList.begin(), VTList.end());
+
+ if (!VTList.empty())
+ assert(VTList[0] != MVT::iAny && VTList[0] != MVT::vAny &&
+ VTList[0] != MVT::fAny);
+
+ // Verify no duplicates.
+ array_pod_sort(TypeVec.begin(), TypeVec.end());
+ assert(std::unique(TypeVec.begin(), TypeVec.end()) == TypeVec.end());
+}
+
+/// FillWithPossibleTypes - Set to all legal types and return true, only valid
+/// on completely unknown type sets.
+bool EEVT::TypeSet::FillWithPossibleTypes(TreePattern &TP,
+ bool (*Pred)(MVT::SimpleValueType),
+ const char *PredicateName) {
+ assert(isCompletelyUnknown());
+ ArrayRef<MVT::SimpleValueType> LegalTypes =
+ TP.getDAGPatterns().getTargetInfo().getLegalValueTypes();
+
+ if (TP.hasError())
+ return false;
+
+ for (MVT::SimpleValueType VT : LegalTypes)
+ if (!Pred || Pred(VT))
+ TypeVec.push_back(VT);
+
+ // If we have nothing that matches the predicate, bail out.
+ if (TypeVec.empty()) {
+ TP.error("Type inference contradiction found, no " +
+ std::string(PredicateName) + " types found");
+ return false;
+ }
+ // No need to sort with one element.
+ if (TypeVec.size() == 1) return true;
+
+ // Remove duplicates.
+ array_pod_sort(TypeVec.begin(), TypeVec.end());
+ TypeVec.erase(std::unique(TypeVec.begin(), TypeVec.end()), TypeVec.end());
+
+ return true;
+}
+
+/// hasIntegerTypes - Return true if this TypeSet contains iAny or an
+/// integer value type.
+bool EEVT::TypeSet::hasIntegerTypes() const {
+ return any_of(TypeVec, isInteger);
+}
+
+/// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or
+/// a floating point value type.
+bool EEVT::TypeSet::hasFloatingPointTypes() const {
+ return any_of(TypeVec, isFloatingPoint);
+}
+
+/// hasScalarTypes - Return true if this TypeSet contains a scalar value type.
+bool EEVT::TypeSet::hasScalarTypes() const {
+ return any_of(TypeVec, isScalar);
+}
+
+/// hasVectorTypes - Return true if this TypeSet contains a vAny or a vector
+/// value type.
+bool EEVT::TypeSet::hasVectorTypes() const {
+ return any_of(TypeVec, isVector);
+}
+
+
+std::string EEVT::TypeSet::getName() const {
+ if (TypeVec.empty()) return "<empty>";
+
+ std::string Result;
+
+ for (unsigned i = 0, e = TypeVec.size(); i != e; ++i) {
+ std::string VTName = llvm::getEnumName(TypeVec[i]);
+ // Strip off MVT:: prefix if present.
+ if (VTName.substr(0,5) == "MVT::")
+ VTName = VTName.substr(5);
+ if (i) Result += ':';
+ Result += VTName;
+ }
+
+ if (TypeVec.size() == 1)
+ return Result;
+ return "{" + Result + "}";
+}
+
+/// MergeInTypeInfo - This merges in type information from the specified
+/// argument. If 'this' changes, it returns true. If the two types are
+/// contradictory (e.g. merge f32 into i32) then this flags an error.
+bool EEVT::TypeSet::MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP){
+ if (InVT.isCompletelyUnknown() || *this == InVT || TP.hasError())
+ return false;
+
+ if (isCompletelyUnknown()) {
+ *this = InVT;
+ return true;
+ }
+
+ assert(!TypeVec.empty() && !InVT.TypeVec.empty() && "No unknowns");
+
+ // Handle the abstract cases, seeing if we can resolve them better.
+ switch (TypeVec[0]) {
+ default: break;
+ case MVT::iPTR:
+ case MVT::iPTRAny:
+ if (InVT.hasIntegerTypes()) {
+ EEVT::TypeSet InCopy(InVT);
+ InCopy.EnforceInteger(TP);
+ InCopy.EnforceScalar(TP);
+
+ if (InCopy.isConcrete()) {
+ // If the RHS has one integer type, upgrade iPTR to i32.
+ TypeVec[0] = InVT.TypeVec[0];
+ return true;
+ }
+
+ // If the input has multiple scalar integers, this doesn't add any info.
+ if (!InCopy.isCompletelyUnknown())
+ return false;
+ }
+ break;
+ }
+
+ // If the input constraint is iAny/iPTR and this is an integer type list,
+ // remove non-integer types from the list.
+ if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) &&
+ hasIntegerTypes()) {
+ bool MadeChange = EnforceInteger(TP);
+
+ // If we're merging in iPTR/iPTRAny and the node currently has a list of
+ // multiple different integer types, replace them with a single iPTR.
+ if ((InVT.TypeVec[0] == MVT::iPTR || InVT.TypeVec[0] == MVT::iPTRAny) &&
+ TypeVec.size() != 1) {
+ TypeVec.assign(1, InVT.TypeVec[0]);
+ MadeChange = true;
+ }
+
+ return MadeChange;
+ }
+
+ // If this is a type list and the RHS is a typelist as well, eliminate entries
+ // from this list that aren't in the other one.
+ TypeSet InputSet(*this);
+
+ TypeVec.clear();
+ std::set_intersection(InputSet.TypeVec.begin(), InputSet.TypeVec.end(),
+ InVT.TypeVec.begin(), InVT.TypeVec.end(),
+ std::back_inserter(TypeVec));
+
+ // If the intersection is the same size as the original set then we're done.
+ if (TypeVec.size() == InputSet.TypeVec.size())
+ return false;
+
+ // If we removed all of our types, we have a type contradiction.
+ if (!TypeVec.empty())
+ return true;
+
+ // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, merging '" +
+ InVT.getName() + "' into '" + InputSet.getName() + "'");
+ return false;
+}
+
+/// EnforceInteger - Remove all non-integer types from this set.
+bool EEVT::TypeSet::EnforceInteger(TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+ // If we know nothing, then get the full set.
+ if (TypeVec.empty())
+ return FillWithPossibleTypes(TP, isInteger, "integer");
+
+ if (!hasFloatingPointTypes())
+ return false;
+
+ TypeSet InputSet(*this);
+
+ // Filter out all the fp types.
+ TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isInteger))),
+ TypeVec.end());
+
+ if (TypeVec.empty()) {
+ TP.error("Type inference contradiction found, '" +
+ InputSet.getName() + "' needs to be integer");
+ return false;
+ }
+ return true;
+}
+
+/// EnforceFloatingPoint - Remove all integer types from this set.
+bool EEVT::TypeSet::EnforceFloatingPoint(TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+ // If we know nothing, then get the full set.
+ if (TypeVec.empty())
+ return FillWithPossibleTypes(TP, isFloatingPoint, "floating point");
+
+ if (!hasIntegerTypes())
+ return false;
+
+ TypeSet InputSet(*this);
+
+ // Filter out all the integer types.
+ TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isFloatingPoint))),
+ TypeVec.end());
+
+ if (TypeVec.empty()) {
+ TP.error("Type inference contradiction found, '" +
+ InputSet.getName() + "' needs to be floating point");
+ return false;
+ }
+ return true;
+}
+
+/// EnforceScalar - Remove all vector types from this.
+bool EEVT::TypeSet::EnforceScalar(TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+
+ // If we know nothing, then get the full set.
+ if (TypeVec.empty())
+ return FillWithPossibleTypes(TP, isScalar, "scalar");
+
+ if (!hasVectorTypes())
+ return false;
+
+ TypeSet InputSet(*this);
+
+ // Filter out all the vector types.
+ TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isScalar))),
+ TypeVec.end());
+
+ if (TypeVec.empty()) {
+ TP.error("Type inference contradiction found, '" +
+ InputSet.getName() + "' needs to be scalar");
+ return false;
+ }
+ return true;
+}
+
+/// EnforceVector - Remove all vector types from this.
+bool EEVT::TypeSet::EnforceVector(TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+
+ // If we know nothing, then get the full set.
+ if (TypeVec.empty())
+ return FillWithPossibleTypes(TP, isVector, "vector");
+
+ TypeSet InputSet(*this);
+ bool MadeChange = false;
+
+ // Filter out all the scalar types.
+ TypeVec.erase(remove_if(TypeVec, std::not1(std::ptr_fun(isVector))),
+ TypeVec.end());
+
+ if (TypeVec.empty()) {
+ TP.error("Type inference contradiction found, '" +
+ InputSet.getName() + "' needs to be a vector");
+ return false;
+ }
+ return MadeChange;
+}
+
+
+
+/// EnforceSmallerThan - 'this' must be a smaller VT than Other. For vectors
+/// this should be based on the element type. Update this and other based on
+/// this information.
+bool EEVT::TypeSet::EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+
+ // Both operands must be integer or FP, but we don't care which.
+ bool MadeChange = false;
+
+ if (isCompletelyUnknown())
+ MadeChange = FillWithPossibleTypes(TP);
+
+ if (Other.isCompletelyUnknown())
+ MadeChange = Other.FillWithPossibleTypes(TP);
+
+ // If one side is known to be integer or known to be FP but the other side has
+ // no information, get at least the type integrality info in there.
+ if (!hasFloatingPointTypes())
+ MadeChange |= Other.EnforceInteger(TP);
+ else if (!hasIntegerTypes())
+ MadeChange |= Other.EnforceFloatingPoint(TP);
+ if (!Other.hasFloatingPointTypes())
+ MadeChange |= EnforceInteger(TP);
+ else if (!Other.hasIntegerTypes())
+ MadeChange |= EnforceFloatingPoint(TP);
+
+ assert(!isCompletelyUnknown() && !Other.isCompletelyUnknown() &&
+ "Should have a type list now");
+
+ // If one contains vectors but the other doesn't pull vectors out.
+ if (!hasVectorTypes())
+ MadeChange |= Other.EnforceScalar(TP);
+ else if (!hasScalarTypes())
+ MadeChange |= Other.EnforceVector(TP);
+ if (!Other.hasVectorTypes())
+ MadeChange |= EnforceScalar(TP);
+ else if (!Other.hasScalarTypes())
+ MadeChange |= EnforceVector(TP);
+
+ // This code does not currently handle nodes which have multiple types,
+ // where some types are integer, and some are fp. Assert that this is not
+ // the case.
+ assert(!(hasIntegerTypes() && hasFloatingPointTypes()) &&
+ !(Other.hasIntegerTypes() && Other.hasFloatingPointTypes()) &&
+ "SDTCisOpSmallerThanOp does not handle mixed int/fp types!");
+
+ if (TP.hasError())
+ return false;
+
+ // Okay, find the smallest type from current set and remove anything the
+ // same or smaller from the other set. We need to ensure that the scalar
+ // type size is smaller than the scalar size of the smallest type. For
+ // vectors, we also need to make sure that the total size is no larger than
+ // the size of the smallest type.
+ {
+ TypeSet InputSet(Other);
+ MVT Smallest = *std::min_element(TypeVec.begin(), TypeVec.end(),
+ [](MVT A, MVT B) {
+ return A.getScalarSizeInBits() < B.getScalarSizeInBits() ||
+ (A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
+ A.getSizeInBits() < B.getSizeInBits());
+ });
+
+ auto I = remove_if(Other.TypeVec, [Smallest](MVT OtherVT) {
+ // Don't compare vector and non-vector types.
+ if (OtherVT.isVector() != Smallest.isVector())
+ return false;
+ // The getSizeInBits() check here is only needed for vectors, but is
+ // a subset of the scalar check for scalars so no need to qualify.
+ return OtherVT.getScalarSizeInBits() <= Smallest.getScalarSizeInBits() ||
+ OtherVT.getSizeInBits() < Smallest.getSizeInBits();
+ });
+ MadeChange |= I != Other.TypeVec.end(); // If we're about to remove types.
+ Other.TypeVec.erase(I, Other.TypeVec.end());
+
+ if (Other.TypeVec.empty()) {
+ TP.error("Type inference contradiction found, '" + InputSet.getName() +
+ "' has nothing larger than '" + getName() +"'!");
+ return false;
+ }
+ }
+
+ // Okay, find the largest type from the other set and remove anything the
+ // same or smaller from the current set. We need to ensure that the scalar
+ // type size is larger than the scalar size of the largest type. For
+ // vectors, we also need to make sure that the total size is no smaller than
+ // the size of the largest type.
+ {
+ TypeSet InputSet(*this);
+ MVT Largest = *std::max_element(Other.TypeVec.begin(), Other.TypeVec.end(),
+ [](MVT A, MVT B) {
+ return A.getScalarSizeInBits() < B.getScalarSizeInBits() ||
+ (A.getScalarSizeInBits() == B.getScalarSizeInBits() &&
+ A.getSizeInBits() < B.getSizeInBits());
+ });
+ auto I = remove_if(TypeVec, [Largest](MVT OtherVT) {
+ // Don't compare vector and non-vector types.
+ if (OtherVT.isVector() != Largest.isVector())
+ return false;
+ return OtherVT.getScalarSizeInBits() >= Largest.getScalarSizeInBits() ||
+ OtherVT.getSizeInBits() > Largest.getSizeInBits();
+ });
+ MadeChange |= I != TypeVec.end(); // If we're about to remove types.
+ TypeVec.erase(I, TypeVec.end());
+
+ if (TypeVec.empty()) {
+ TP.error("Type inference contradiction found, '" + InputSet.getName() +
+ "' has nothing smaller than '" + Other.getName() +"'!");
+ return false;
+ }
+ }
+
+ return MadeChange;
+}
+
+/// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
+/// whose element is specified by VTOperand.
+bool EEVT::TypeSet::EnforceVectorEltTypeIs(MVT::SimpleValueType VT,
+ TreePattern &TP) {
+ bool MadeChange = false;
+
+ MadeChange |= EnforceVector(TP);
+
+ TypeSet InputSet(*this);
+
+ // Filter out all the types which don't have the right element type.
+ auto I = remove_if(TypeVec, [VT](MVT VVT) {
+ return VVT.getVectorElementType().SimpleTy != VT;
+ });
+ MadeChange |= I != TypeVec.end();
+ TypeVec.erase(I, TypeVec.end());
+
+ if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have a vector element of type " +
+ getEnumName(VT));
+ return false;
+ }
+
+ return MadeChange;
+}
+
+/// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
+/// whose element is specified by VTOperand.
+bool EEVT::TypeSet::EnforceVectorEltTypeIs(EEVT::TypeSet &VTOperand,
+ TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+
+ // "This" must be a vector and "VTOperand" must be a scalar.
+ bool MadeChange = false;
+ MadeChange |= EnforceVector(TP);
+ MadeChange |= VTOperand.EnforceScalar(TP);
+
+ // If we know the vector type, it forces the scalar to agree.
+ if (isConcrete()) {
+ MVT IVT = getConcrete();
+ IVT = IVT.getVectorElementType();
+ return MadeChange || VTOperand.MergeInTypeInfo(IVT.SimpleTy, TP);
+ }
+
+ // If the scalar type is known, filter out vector types whose element types
+ // disagree.
+ if (!VTOperand.isConcrete())
+ return MadeChange;
+
+ MVT::SimpleValueType VT = VTOperand.getConcrete();
+
+ MadeChange |= EnforceVectorEltTypeIs(VT, TP);
+
+ return MadeChange;
+}
+
+/// EnforceVectorSubVectorTypeIs - 'this' is now constrained to be a
+/// vector type specified by VTOperand.
+bool EEVT::TypeSet::EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VTOperand,
+ TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+
+ // "This" must be a vector and "VTOperand" must be a vector.
+ bool MadeChange = false;
+ MadeChange |= EnforceVector(TP);
+ MadeChange |= VTOperand.EnforceVector(TP);
+
+ // If one side is known to be integer or known to be FP but the other side has
+ // no information, get at least the type integrality info in there.
+ if (!hasFloatingPointTypes())
+ MadeChange |= VTOperand.EnforceInteger(TP);
+ else if (!hasIntegerTypes())
+ MadeChange |= VTOperand.EnforceFloatingPoint(TP);
+ if (!VTOperand.hasFloatingPointTypes())
+ MadeChange |= EnforceInteger(TP);
+ else if (!VTOperand.hasIntegerTypes())
+ MadeChange |= EnforceFloatingPoint(TP);
+
+ assert(!isCompletelyUnknown() && !VTOperand.isCompletelyUnknown() &&
+ "Should have a type list now");
+
+ // If we know the vector type, it forces the scalar types to agree.
+ // Also force one vector to have more elements than the other.
+ if (isConcrete()) {
+ MVT IVT = getConcrete();
+ unsigned NumElems = IVT.getVectorNumElements();
+ IVT = IVT.getVectorElementType();
+
+ EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP);
+ MadeChange |= VTOperand.EnforceVectorEltTypeIs(EltTypeSet, TP);
+
+ // Only keep types that have less elements than VTOperand.
+ TypeSet InputSet(VTOperand);
+
+ auto I = remove_if(VTOperand.TypeVec, [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() >= NumElems;
+ });
+ MadeChange |= I != VTOperand.TypeVec.end();
+ VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
+
+ if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have less vector elements than '" +
+ getName() + "'");
+ return false;
+ }
+ } else if (VTOperand.isConcrete()) {
+ MVT IVT = VTOperand.getConcrete();
+ unsigned NumElems = IVT.getVectorNumElements();
+ IVT = IVT.getVectorElementType();
+
+ EEVT::TypeSet EltTypeSet(IVT.SimpleTy, TP);
+ MadeChange |= EnforceVectorEltTypeIs(EltTypeSet, TP);
+
+ // Only keep types that have more elements than 'this'.
+ TypeSet InputSet(*this);
+
+ auto I = remove_if(TypeVec, [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() <= NumElems;
+ });
+ MadeChange |= I != TypeVec.end();
+ TypeVec.erase(I, TypeVec.end());
+
+ if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have more vector elements than '" +
+ VTOperand.getName() + "'");
+ return false;
+ }
+ }
+
+ return MadeChange;
+}
+
+/// EnforceameNumElts - If VTOperand is a scalar, then 'this' is a scalar. If
+/// VTOperand is a vector, then 'this' must have the same number of elements.
+bool EEVT::TypeSet::EnforceSameNumElts(EEVT::TypeSet &VTOperand,
+ TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+
+ bool MadeChange = false;
+
+ if (isCompletelyUnknown())
+ MadeChange = FillWithPossibleTypes(TP);
+
+ if (VTOperand.isCompletelyUnknown())
+ MadeChange = VTOperand.FillWithPossibleTypes(TP);
+
+ // If one contains vectors but the other doesn't pull vectors out.
+ if (!hasVectorTypes())
+ MadeChange |= VTOperand.EnforceScalar(TP);
+ else if (!hasScalarTypes())
+ MadeChange |= VTOperand.EnforceVector(TP);
+ if (!VTOperand.hasVectorTypes())
+ MadeChange |= EnforceScalar(TP);
+ else if (!VTOperand.hasScalarTypes())
+ MadeChange |= EnforceVector(TP);
+
+ // If one type is a vector, make sure the other has the same element count.
+ // If this a scalar, then we are already done with the above.
+ if (isConcrete()) {
+ MVT IVT = getConcrete();
+ if (IVT.isVector()) {
+ unsigned NumElems = IVT.getVectorNumElements();
+
+ // Only keep types that have same elements as 'this'.
+ TypeSet InputSet(VTOperand);
+
+ auto I = remove_if(VTOperand.TypeVec, [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() != NumElems;
+ });
+ MadeChange |= I != VTOperand.TypeVec.end();
+ VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
+
+ if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have same number elements as '" +
+ getName() + "'");
+ return false;
+ }
+ }
+ } else if (VTOperand.isConcrete()) {
+ MVT IVT = VTOperand.getConcrete();
+ if (IVT.isVector()) {
+ unsigned NumElems = IVT.getVectorNumElements();
+
+ // Only keep types that have same elements as VTOperand.
+ TypeSet InputSet(*this);
+
+ auto I = remove_if(TypeVec, [NumElems](MVT VVT) {
+ return VVT.getVectorNumElements() != NumElems;
+ });
+ MadeChange |= I != TypeVec.end();
+ TypeVec.erase(I, TypeVec.end());
+
+ if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have same number elements than '" +
+ VTOperand.getName() + "'");
+ return false;
+ }
+ }
+ }
+
+ return MadeChange;
+}
+
+/// EnforceSameSize - 'this' is now constrained to be same size as VTOperand.
+bool EEVT::TypeSet::EnforceSameSize(EEVT::TypeSet &VTOperand,
+ TreePattern &TP) {
+ if (TP.hasError())
+ return false;
+
+ bool MadeChange = false;
+
+ if (isCompletelyUnknown())
+ MadeChange = FillWithPossibleTypes(TP);
+
+ if (VTOperand.isCompletelyUnknown())
+ MadeChange = VTOperand.FillWithPossibleTypes(TP);
+
+ // If we know one of the types, it forces the other type agree.
+ if (isConcrete()) {
+ MVT IVT = getConcrete();
+ unsigned Size = IVT.getSizeInBits();
+
+ // Only keep types that have the same size as 'this'.
+ TypeSet InputSet(VTOperand);
+
+ auto I = remove_if(VTOperand.TypeVec,
+ [&](MVT VT) { return VT.getSizeInBits() != Size; });
+ MadeChange |= I != VTOperand.TypeVec.end();
+ VTOperand.TypeVec.erase(I, VTOperand.TypeVec.end());
+
+ if (VTOperand.TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have same size as '" +
+ getName() + "'");
+ return false;
+ }
+ } else if (VTOperand.isConcrete()) {
+ MVT IVT = VTOperand.getConcrete();
+ unsigned Size = IVT.getSizeInBits();
+
+ // Only keep types that have the same size as VTOperand.
+ TypeSet InputSet(*this);
+
+ auto I =
+ remove_if(TypeVec, [&](MVT VT) { return VT.getSizeInBits() != Size; });
+ MadeChange |= I != TypeVec.end();
+ TypeVec.erase(I, TypeVec.end());
+
+ if (TypeVec.empty()) { // FIXME: Really want an SMLoc here!
+ TP.error("Type inference contradiction found, forcing '" +
+ InputSet.getName() + "' to have same size as '" +
+ VTOperand.getName() + "'");
+ return false;
+ }
+ }
+
+ return MadeChange;
+}
+
+//===----------------------------------------------------------------------===//
+// Helpers for working with extended types.
+
+/// Dependent variable map for CodeGenDAGPattern variant generation
+typedef std::map<std::string, int> DepVarMap;
+
+static void FindDepVarsOf(TreePatternNode *N, DepVarMap &DepMap) {
+ if (N->isLeaf()) {
+ if (isa<DefInit>(N->getLeafValue()))
+ DepMap[N->getName()]++;
+ } else {
+ for (size_t i = 0, e = N->getNumChildren(); i != e; ++i)
+ FindDepVarsOf(N->getChild(i), DepMap);
+ }
+}
+
+/// Find dependent variables within child patterns
+static void FindDepVars(TreePatternNode *N, MultipleUseVarSet &DepVars) {
+ DepVarMap depcounts;
+ FindDepVarsOf(N, depcounts);
+ for (const std::pair<std::string, int> &Pair : depcounts) {
+ if (Pair.second > 1)
+ DepVars.insert(Pair.first);
+ }
+}
+
+#ifndef NDEBUG
+/// Dump the dependent variable set:
+static void DumpDepVars(MultipleUseVarSet &DepVars) {
+ if (DepVars.empty()) {
+ DEBUG(errs() << "<empty set>");
+ } else {
+ DEBUG(errs() << "[ ");
+ for (const std::string &DepVar : DepVars) {
+ DEBUG(errs() << DepVar << " ");
+ }
+ DEBUG(errs() << "]");
+ }
+}
+#endif
+
+
+//===----------------------------------------------------------------------===//
+// TreePredicateFn Implementation
+//===----------------------------------------------------------------------===//
+
+/// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag.
+TreePredicateFn::TreePredicateFn(TreePattern *N) : PatFragRec(N) {
+ assert((getPredCode().empty() || getImmCode().empty()) &&
+ ".td file corrupt: can't have a node predicate *and* an imm predicate");
+}
+
+std::string TreePredicateFn::getPredCode() const {
+ return PatFragRec->getRecord()->getValueAsString("PredicateCode");
+}
+
+std::string TreePredicateFn::getImmCode() const {
+ return PatFragRec->getRecord()->getValueAsString("ImmediateCode");
+}
+
+
+/// isAlwaysTrue - Return true if this is a noop predicate.
+bool TreePredicateFn::isAlwaysTrue() const {
+ return getPredCode().empty() && getImmCode().empty();
+}
+
+/// Return the name to use in the generated code to reference this, this is
+/// "Predicate_foo" if from a pattern fragment "foo".
+std::string TreePredicateFn::getFnName() const {
+ return "Predicate_" + PatFragRec->getRecord()->getName().str();
+}
+
+/// getCodeToRunOnSDNode - Return the code for the function body that
+/// evaluates this predicate. The argument is expected to be in "Node",
+/// not N. This handles casting and conversion to a concrete node type as
+/// appropriate.
+std::string TreePredicateFn::getCodeToRunOnSDNode() const {
+ // Handle immediate predicates first.
+ std::string ImmCode = getImmCode();
+ if (!ImmCode.empty()) {
+ std::string Result =
+ " int64_t Imm = cast<ConstantSDNode>(Node)->getSExtValue();\n";
+ return Result + ImmCode;
+ }
+
+ // Handle arbitrary node predicates.
+ assert(!getPredCode().empty() && "Don't have any predicate code!");
+ std::string ClassName;
+ if (PatFragRec->getOnlyTree()->isLeaf())
+ ClassName = "SDNode";
+ else {
+ Record *Op = PatFragRec->getOnlyTree()->getOperator();
+ ClassName = PatFragRec->getDAGPatterns().getSDNodeInfo(Op).getSDClassName();
+ }
+ std::string Result;
+ if (ClassName == "SDNode")
+ Result = " SDNode *N = Node;\n";
+ else
+ Result = " auto *N = cast<" + ClassName + ">(Node);\n";
+
+ return Result + getPredCode();
+}
+
+//===----------------------------------------------------------------------===//
+// PatternToMatch implementation
+//
+
+
+/// getPatternSize - Return the 'size' of this pattern. We want to match large
+/// patterns before small ones. This is used to determine the size of a
+/// pattern.
+static unsigned getPatternSize(const TreePatternNode *P,
+ const CodeGenDAGPatterns &CGP) {
+ unsigned Size = 3; // The node itself.
+ // If the root node is a ConstantSDNode, increases its size.
+ // e.g. (set R32:$dst, 0).
+ if (P->isLeaf() && isa<IntInit>(P->getLeafValue()))
+ Size += 2;
+
+ const ComplexPattern *AM = P->getComplexPatternInfo(CGP);
+ if (AM) {
+ Size += AM->getComplexity();
+
+ // We don't want to count any children twice, so return early.
+ return Size;
+ }
+
+ // If this node has some predicate function that must match, it adds to the
+ // complexity of this node.
+ if (!P->getPredicateFns().empty())
+ ++Size;
+
+ // Count children in the count if they are also nodes.
+ for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = P->getChild(i);
+ if (!Child->isLeaf() && Child->getNumTypes() &&
+ Child->getType(0) != MVT::Other)
+ Size += getPatternSize(Child, CGP);
+ else if (Child->isLeaf()) {
+ if (isa<IntInit>(Child->getLeafValue()))
+ Size += 5; // Matches a ConstantSDNode (+3) and a specific value (+2).
+ else if (Child->getComplexPatternInfo(CGP))
+ Size += getPatternSize(Child, CGP);
+ else if (!Child->getPredicateFns().empty())
+ ++Size;
+ }
+ }
+
+ return Size;
+}
+
+/// Compute the complexity metric for the input pattern. This roughly
+/// corresponds to the number of nodes that are covered.
+int PatternToMatch::
+getPatternComplexity(const CodeGenDAGPatterns &CGP) const {
+ return getPatternSize(getSrcPattern(), CGP) + getAddedComplexity();
+}
+
+
+/// getPredicateCheck - Return a single string containing all of this
+/// pattern's predicates concatenated with "&&" operators.
+///
+std::string PatternToMatch::getPredicateCheck() const {
+ SmallVector<Record *, 4> PredicateRecs;
+ for (Init *I : Predicates->getValues()) {
+ if (DefInit *Pred = dyn_cast<DefInit>(I)) {
+ Record *Def = Pred->getDef();
+ if (!Def->isSubClassOf("Predicate")) {
+#ifndef NDEBUG
+ Def->dump();
+#endif
+ llvm_unreachable("Unknown predicate type!");
+ }
+ PredicateRecs.push_back(Def);
+ }
+ }
+ // Sort so that different orders get canonicalized to the same string.
+ std::sort(PredicateRecs.begin(), PredicateRecs.end(), LessRecord());
+
+ SmallString<128> PredicateCheck;
+ for (Record *Pred : PredicateRecs) {
+ if (!PredicateCheck.empty())
+ PredicateCheck += " && ";
+ PredicateCheck += "(" + Pred->getValueAsString("CondString") + ")";
+ }
+
+ return PredicateCheck.str();
+}
+
+//===----------------------------------------------------------------------===//
+// SDTypeConstraint implementation
+//
+
+SDTypeConstraint::SDTypeConstraint(Record *R) {
+ OperandNo = R->getValueAsInt("OperandNum");
+
+ if (R->isSubClassOf("SDTCisVT")) {
+ ConstraintType = SDTCisVT;
+ x.SDTCisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
+ if (x.SDTCisVT_Info.VT == MVT::isVoid)
+ PrintFatalError(R->getLoc(), "Cannot use 'Void' as type to SDTCisVT");
+
+ } else if (R->isSubClassOf("SDTCisPtrTy")) {
+ ConstraintType = SDTCisPtrTy;
+ } else if (R->isSubClassOf("SDTCisInt")) {
+ ConstraintType = SDTCisInt;
+ } else if (R->isSubClassOf("SDTCisFP")) {
+ ConstraintType = SDTCisFP;
+ } else if (R->isSubClassOf("SDTCisVec")) {
+ ConstraintType = SDTCisVec;
+ } else if (R->isSubClassOf("SDTCisSameAs")) {
+ ConstraintType = SDTCisSameAs;
+ x.SDTCisSameAs_Info.OtherOperandNum = R->getValueAsInt("OtherOperandNum");
+ } else if (R->isSubClassOf("SDTCisVTSmallerThanOp")) {
+ ConstraintType = SDTCisVTSmallerThanOp;
+ x.SDTCisVTSmallerThanOp_Info.OtherOperandNum =
+ R->getValueAsInt("OtherOperandNum");
+ } else if (R->isSubClassOf("SDTCisOpSmallerThanOp")) {
+ ConstraintType = SDTCisOpSmallerThanOp;
+ x.SDTCisOpSmallerThanOp_Info.BigOperandNum =
+ R->getValueAsInt("BigOperandNum");
+ } else if (R->isSubClassOf("SDTCisEltOfVec")) {
+ ConstraintType = SDTCisEltOfVec;
+ x.SDTCisEltOfVec_Info.OtherOperandNum = R->getValueAsInt("OtherOpNum");
+ } else if (R->isSubClassOf("SDTCisSubVecOfVec")) {
+ ConstraintType = SDTCisSubVecOfVec;
+ x.SDTCisSubVecOfVec_Info.OtherOperandNum =
+ R->getValueAsInt("OtherOpNum");
+ } else if (R->isSubClassOf("SDTCVecEltisVT")) {
+ ConstraintType = SDTCVecEltisVT;
+ x.SDTCVecEltisVT_Info.VT = getValueType(R->getValueAsDef("VT"));
+ if (MVT(x.SDTCVecEltisVT_Info.VT).isVector())
+ PrintFatalError(R->getLoc(), "Cannot use vector type as SDTCVecEltisVT");
+ if (!MVT(x.SDTCVecEltisVT_Info.VT).isInteger() &&
+ !MVT(x.SDTCVecEltisVT_Info.VT).isFloatingPoint())
+ PrintFatalError(R->getLoc(), "Must use integer or floating point type "
+ "as SDTCVecEltisVT");
+ } else if (R->isSubClassOf("SDTCisSameNumEltsAs")) {
+ ConstraintType = SDTCisSameNumEltsAs;
+ x.SDTCisSameNumEltsAs_Info.OtherOperandNum =
+ R->getValueAsInt("OtherOperandNum");
+ } else if (R->isSubClassOf("SDTCisSameSizeAs")) {
+ ConstraintType = SDTCisSameSizeAs;
+ x.SDTCisSameSizeAs_Info.OtherOperandNum =
+ R->getValueAsInt("OtherOperandNum");
+ } else {
+ PrintFatalError("Unrecognized SDTypeConstraint '" + R->getName() + "'!\n");
+ }
+}
+
+/// getOperandNum - Return the node corresponding to operand #OpNo in tree
+/// N, and the result number in ResNo.
+static TreePatternNode *getOperandNum(unsigned OpNo, TreePatternNode *N,
+ const SDNodeInfo &NodeInfo,
+ unsigned &ResNo) {
+ unsigned NumResults = NodeInfo.getNumResults();
+ if (OpNo < NumResults) {
+ ResNo = OpNo;
+ return N;
+ }
+
+ OpNo -= NumResults;
+
+ if (OpNo >= N->getNumChildren()) {
+ std::string S;
+ raw_string_ostream OS(S);
+ OS << "Invalid operand number in type constraint "
+ << (OpNo+NumResults) << " ";
+ N->print(OS);
+ PrintFatalError(OS.str());
+ }
+
+ return N->getChild(OpNo);
+}
+
+/// ApplyTypeConstraint - Given a node in a pattern, apply this type
+/// constraint to the nodes operands. This returns true if it makes a
+/// change, false otherwise. If a type contradiction is found, flag an error.
+bool SDTypeConstraint::ApplyTypeConstraint(TreePatternNode *N,
+ const SDNodeInfo &NodeInfo,
+ TreePattern &TP) const {
+ if (TP.hasError())
+ return false;
+
+ unsigned ResNo = 0; // The result number being referenced.
+ TreePatternNode *NodeToApply = getOperandNum(OperandNo, N, NodeInfo, ResNo);
+
+ switch (ConstraintType) {
+ case SDTCisVT:
+ // Operand must be a particular type.
+ return NodeToApply->UpdateNodeType(ResNo, x.SDTCisVT_Info.VT, TP);
+ case SDTCisPtrTy:
+ // Operand must be same as target pointer type.
+ return NodeToApply->UpdateNodeType(ResNo, MVT::iPTR, TP);
+ case SDTCisInt:
+ // Require it to be one of the legal integer VTs.
+ return NodeToApply->getExtType(ResNo).EnforceInteger(TP);
+ case SDTCisFP:
+ // Require it to be one of the legal fp VTs.
+ return NodeToApply->getExtType(ResNo).EnforceFloatingPoint(TP);
+ case SDTCisVec:
+ // Require it to be one of the legal vector VTs.
+ return NodeToApply->getExtType(ResNo).EnforceVector(TP);
+ case SDTCisSameAs: {
+ unsigned OResNo = 0;
+ TreePatternNode *OtherNode =
+ getOperandNum(x.SDTCisSameAs_Info.OtherOperandNum, N, NodeInfo, OResNo);
+ return NodeToApply->UpdateNodeType(ResNo, OtherNode->getExtType(OResNo),TP)|
+ OtherNode->UpdateNodeType(OResNo,NodeToApply->getExtType(ResNo),TP);
+ }
+ case SDTCisVTSmallerThanOp: {
+ // The NodeToApply must be a leaf node that is a VT. OtherOperandNum must
+ // have an integer type that is smaller than the VT.
+ if (!NodeToApply->isLeaf() ||
+ !isa<DefInit>(NodeToApply->getLeafValue()) ||
+ !static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef()
+ ->isSubClassOf("ValueType")) {
+ TP.error(N->getOperator()->getName() + " expects a VT operand!");
+ return false;
+ }
+ MVT::SimpleValueType VT =
+ getValueType(static_cast<DefInit*>(NodeToApply->getLeafValue())->getDef());
+
+ EEVT::TypeSet TypeListTmp(VT, TP);
+
+ unsigned OResNo = 0;
+ TreePatternNode *OtherNode =
+ getOperandNum(x.SDTCisVTSmallerThanOp_Info.OtherOperandNum, N, NodeInfo,
+ OResNo);
+
+ return TypeListTmp.EnforceSmallerThan(OtherNode->getExtType(OResNo), TP);
+ }
+ case SDTCisOpSmallerThanOp: {
+ unsigned BResNo = 0;
+ TreePatternNode *BigOperand =
+ getOperandNum(x.SDTCisOpSmallerThanOp_Info.BigOperandNum, N, NodeInfo,
+ BResNo);
+ return NodeToApply->getExtType(ResNo).
+ EnforceSmallerThan(BigOperand->getExtType(BResNo), TP);
+ }
+ case SDTCisEltOfVec: {
+ unsigned VResNo = 0;
+ TreePatternNode *VecOperand =
+ getOperandNum(x.SDTCisEltOfVec_Info.OtherOperandNum, N, NodeInfo,
+ VResNo);
+
+ // Filter vector types out of VecOperand that don't have the right element
+ // type.
+ return VecOperand->getExtType(VResNo).
+ EnforceVectorEltTypeIs(NodeToApply->getExtType(ResNo), TP);
+ }
+ case SDTCisSubVecOfVec: {
+ unsigned VResNo = 0;
+ TreePatternNode *BigVecOperand =
+ getOperandNum(x.SDTCisSubVecOfVec_Info.OtherOperandNum, N, NodeInfo,
+ VResNo);
+
+ // Filter vector types out of BigVecOperand that don't have the
+ // right subvector type.
+ return BigVecOperand->getExtType(VResNo).
+ EnforceVectorSubVectorTypeIs(NodeToApply->getExtType(ResNo), TP);
+ }
+ case SDTCVecEltisVT: {
+ return NodeToApply->getExtType(ResNo).
+ EnforceVectorEltTypeIs(x.SDTCVecEltisVT_Info.VT, TP);
+ }
+ case SDTCisSameNumEltsAs: {
+ unsigned OResNo = 0;
+ TreePatternNode *OtherNode =
+ getOperandNum(x.SDTCisSameNumEltsAs_Info.OtherOperandNum,
+ N, NodeInfo, OResNo);
+ return OtherNode->getExtType(OResNo).
+ EnforceSameNumElts(NodeToApply->getExtType(ResNo), TP);
+ }
+ case SDTCisSameSizeAs: {
+ unsigned OResNo = 0;
+ TreePatternNode *OtherNode =
+ getOperandNum(x.SDTCisSameSizeAs_Info.OtherOperandNum,
+ N, NodeInfo, OResNo);
+ return OtherNode->getExtType(OResNo).
+ EnforceSameSize(NodeToApply->getExtType(ResNo), TP);
+ }
+ }
+ llvm_unreachable("Invalid ConstraintType!");
+}
+
+// Update the node type to match an instruction operand or result as specified
+// in the ins or outs lists on the instruction definition. Return true if the
+// type was actually changed.
+bool TreePatternNode::UpdateNodeTypeFromInst(unsigned ResNo,
+ Record *Operand,
+ TreePattern &TP) {
+ // The 'unknown' operand indicates that types should be inferred from the
+ // context.
+ if (Operand->isSubClassOf("unknown_class"))
+ return false;
+
+ // The Operand class specifies a type directly.
+ if (Operand->isSubClassOf("Operand"))
+ return UpdateNodeType(ResNo, getValueType(Operand->getValueAsDef("Type")),
+ TP);
+
+ // PointerLikeRegClass has a type that is determined at runtime.
+ if (Operand->isSubClassOf("PointerLikeRegClass"))
+ return UpdateNodeType(ResNo, MVT::iPTR, TP);
+
+ // Both RegisterClass and RegisterOperand operands derive their types from a
+ // register class def.
+ Record *RC = nullptr;
+ if (Operand->isSubClassOf("RegisterClass"))
+ RC = Operand;
+ else if (Operand->isSubClassOf("RegisterOperand"))
+ RC = Operand->getValueAsDef("RegClass");
+
+ assert(RC && "Unknown operand type");
+ CodeGenTarget &Tgt = TP.getDAGPatterns().getTargetInfo();
+ return UpdateNodeType(ResNo, Tgt.getRegisterClass(RC).getValueTypes(), TP);
+}
+
+
+//===----------------------------------------------------------------------===//
+// SDNodeInfo implementation
+//
+SDNodeInfo::SDNodeInfo(Record *R) : Def(R) {
+ EnumName = R->getValueAsString("Opcode");
+ SDClassName = R->getValueAsString("SDClass");
+ Record *TypeProfile = R->getValueAsDef("TypeProfile");
+ NumResults = TypeProfile->getValueAsInt("NumResults");
+ NumOperands = TypeProfile->getValueAsInt("NumOperands");
+
+ // Parse the properties.
+ Properties = 0;
+ for (Record *Property : R->getValueAsListOfDefs("Properties")) {
+ if (Property->getName() == "SDNPCommutative") {
+ Properties |= 1 << SDNPCommutative;
+ } else if (Property->getName() == "SDNPAssociative") {
+ Properties |= 1 << SDNPAssociative;
+ } else if (Property->getName() == "SDNPHasChain") {
+ Properties |= 1 << SDNPHasChain;
+ } else if (Property->getName() == "SDNPOutGlue") {
+ Properties |= 1 << SDNPOutGlue;
+ } else if (Property->getName() == "SDNPInGlue") {
+ Properties |= 1 << SDNPInGlue;
+ } else if (Property->getName() == "SDNPOptInGlue") {
+ Properties |= 1 << SDNPOptInGlue;
+ } else if (Property->getName() == "SDNPMayStore") {
+ Properties |= 1 << SDNPMayStore;
+ } else if (Property->getName() == "SDNPMayLoad") {
+ Properties |= 1 << SDNPMayLoad;
+ } else if (Property->getName() == "SDNPSideEffect") {
+ Properties |= 1 << SDNPSideEffect;
+ } else if (Property->getName() == "SDNPMemOperand") {
+ Properties |= 1 << SDNPMemOperand;
+ } else if (Property->getName() == "SDNPVariadic") {
+ Properties |= 1 << SDNPVariadic;
+ } else {
+ PrintFatalError("Unknown SD Node property '" +
+ Property->getName() + "' on node '" +
+ R->getName() + "'!");
+ }
+ }
+
+
+ // Parse the type constraints.
+ std::vector<Record*> ConstraintList =
+ TypeProfile->getValueAsListOfDefs("Constraints");
+ TypeConstraints.assign(ConstraintList.begin(), ConstraintList.end());
+}
+
+/// getKnownType - If the type constraints on this node imply a fixed type
+/// (e.g. all stores return void, etc), then return it as an
+/// MVT::SimpleValueType. Otherwise, return EEVT::Other.
+MVT::SimpleValueType SDNodeInfo::getKnownType(unsigned ResNo) const {
+ unsigned NumResults = getNumResults();
+ assert(NumResults <= 1 &&
+ "We only work with nodes with zero or one result so far!");
+ assert(ResNo == 0 && "Only handles single result nodes so far");
+
+ for (const SDTypeConstraint &Constraint : TypeConstraints) {
+ // Make sure that this applies to the correct node result.
+ if (Constraint.OperandNo >= NumResults) // FIXME: need value #
+ continue;
+
+ switch (Constraint.ConstraintType) {
+ default: break;
+ case SDTypeConstraint::SDTCisVT:
+ return Constraint.x.SDTCisVT_Info.VT;
+ case SDTypeConstraint::SDTCisPtrTy:
+ return MVT::iPTR;
+ }
+ }
+ return MVT::Other;
+}
+
+//===----------------------------------------------------------------------===//
+// TreePatternNode implementation
+//
+
+TreePatternNode::~TreePatternNode() {
+#if 0 // FIXME: implement refcounted tree nodes!
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ delete getChild(i);
+#endif
+}
+
+static unsigned GetNumNodeResults(Record *Operator, CodeGenDAGPatterns &CDP) {
+ if (Operator->getName() == "set" ||
+ Operator->getName() == "implicit")
+ return 0; // All return nothing.
+
+ if (Operator->isSubClassOf("Intrinsic"))
+ return CDP.getIntrinsic(Operator).IS.RetVTs.size();
+
+ if (Operator->isSubClassOf("SDNode"))
+ return CDP.getSDNodeInfo(Operator).getNumResults();
+
+ if (Operator->isSubClassOf("PatFrag")) {
+ // If we've already parsed this pattern fragment, get it. Otherwise, handle
+ // the forward reference case where one pattern fragment references another
+ // before it is processed.
+ if (TreePattern *PFRec = CDP.getPatternFragmentIfRead(Operator))
+ return PFRec->getOnlyTree()->getNumTypes();
+
+ // Get the result tree.
+ DagInit *Tree = Operator->getValueAsDag("Fragment");
+ Record *Op = nullptr;
+ if (Tree)
+ if (DefInit *DI = dyn_cast<DefInit>(Tree->getOperator()))
+ Op = DI->getDef();
+ assert(Op && "Invalid Fragment");
+ return GetNumNodeResults(Op, CDP);
+ }
+
+ if (Operator->isSubClassOf("Instruction")) {
+ CodeGenInstruction &InstInfo = CDP.getTargetInfo().getInstruction(Operator);
+
+ unsigned NumDefsToAdd = InstInfo.Operands.NumDefs;
+
+ // Subtract any defaulted outputs.
+ for (unsigned i = 0; i != InstInfo.Operands.NumDefs; ++i) {
+ Record *OperandNode = InstInfo.Operands[i].Rec;
+
+ if (OperandNode->isSubClassOf("OperandWithDefaultOps") &&
+ !CDP.getDefaultOperand(OperandNode).DefaultOps.empty())
+ --NumDefsToAdd;
+ }
+
+ // Add on one implicit def if it has a resolvable type.
+ if (InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo()) !=MVT::Other)
+ ++NumDefsToAdd;
+ return NumDefsToAdd;
+ }
+
+ if (Operator->isSubClassOf("SDNodeXForm"))
+ return 1; // FIXME: Generalize SDNodeXForm
+
+ if (Operator->isSubClassOf("ValueType"))
+ return 1; // A type-cast of one result.
+
+ if (Operator->isSubClassOf("ComplexPattern"))
+ return 1;
+
+ errs() << *Operator;
+ PrintFatalError("Unhandled node in GetNumNodeResults");
+}
+
+void TreePatternNode::print(raw_ostream &OS) const {
+ if (isLeaf())
+ OS << *getLeafValue();
+ else
+ OS << '(' << getOperator()->getName();
+
+ for (unsigned i = 0, e = Types.size(); i != e; ++i)
+ OS << ':' << getExtType(i).getName();
+
+ if (!isLeaf()) {
+ if (getNumChildren() != 0) {
+ OS << " ";
+ getChild(0)->print(OS);
+ for (unsigned i = 1, e = getNumChildren(); i != e; ++i) {
+ OS << ", ";
+ getChild(i)->print(OS);
+ }
+ }
+ OS << ")";
+ }
+
+ for (const TreePredicateFn &Pred : PredicateFns)
+ OS << "<<P:" << Pred.getFnName() << ">>";
+ if (TransformFn)
+ OS << "<<X:" << TransformFn->getName() << ">>";
+ if (!getName().empty())
+ OS << ":$" << getName();
+
+}
+void TreePatternNode::dump() const {
+ print(errs());
+}
+
+/// isIsomorphicTo - Return true if this node is recursively
+/// isomorphic to the specified node. For this comparison, the node's
+/// entire state is considered. The assigned name is ignored, since
+/// nodes with differing names are considered isomorphic. However, if
+/// the assigned name is present in the dependent variable set, then
+/// the assigned name is considered significant and the node is
+/// isomorphic if the names match.
+bool TreePatternNode::isIsomorphicTo(const TreePatternNode *N,
+ const MultipleUseVarSet &DepVars) const {
+ if (N == this) return true;
+ if (N->isLeaf() != isLeaf() || getExtTypes() != N->getExtTypes() ||
+ getPredicateFns() != N->getPredicateFns() ||
+ getTransformFn() != N->getTransformFn())
+ return false;
+
+ if (isLeaf()) {
+ if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) {
+ if (DefInit *NDI = dyn_cast<DefInit>(N->getLeafValue())) {
+ return ((DI->getDef() == NDI->getDef())
+ && (DepVars.find(getName()) == DepVars.end()
+ || getName() == N->getName()));
+ }
+ }
+ return getLeafValue() == N->getLeafValue();
+ }
+
+ if (N->getOperator() != getOperator() ||
+ N->getNumChildren() != getNumChildren()) return false;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (!getChild(i)->isIsomorphicTo(N->getChild(i), DepVars))
+ return false;
+ return true;
+}
+
+/// clone - Make a copy of this tree and all of its children.
+///
+TreePatternNode *TreePatternNode::clone() const {
+ TreePatternNode *New;
+ if (isLeaf()) {
+ New = new TreePatternNode(getLeafValue(), getNumTypes());
+ } else {
+ std::vector<TreePatternNode*> CChildren;
+ CChildren.reserve(Children.size());
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ CChildren.push_back(getChild(i)->clone());
+ New = new TreePatternNode(getOperator(), CChildren, getNumTypes());
+ }
+ New->setName(getName());
+ New->Types = Types;
+ New->setPredicateFns(getPredicateFns());
+ New->setTransformFn(getTransformFn());
+ return New;
+}
+
+/// RemoveAllTypes - Recursively strip all the types of this tree.
+void TreePatternNode::RemoveAllTypes() {
+ // Reset to unknown type.
+ std::fill(Types.begin(), Types.end(), EEVT::TypeSet());
+ if (isLeaf()) return;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ getChild(i)->RemoveAllTypes();
+}
+
+
+/// SubstituteFormalArguments - Replace the formal arguments in this tree
+/// with actual values specified by ArgMap.
+void TreePatternNode::
+SubstituteFormalArguments(std::map<std::string, TreePatternNode*> &ArgMap) {
+ if (isLeaf()) return;
+
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = getChild(i);
+ if (Child->isLeaf()) {
+ Init *Val = Child->getLeafValue();
+ // Note that, when substituting into an output pattern, Val might be an
+ // UnsetInit.
+ if (isa<UnsetInit>(Val) || (isa<DefInit>(Val) &&
+ cast<DefInit>(Val)->getDef()->getName() == "node")) {
+ // We found a use of a formal argument, replace it with its value.
+ TreePatternNode *NewChild = ArgMap[Child->getName()];
+ assert(NewChild && "Couldn't find formal argument!");
+ assert((Child->getPredicateFns().empty() ||
+ NewChild->getPredicateFns() == Child->getPredicateFns()) &&
+ "Non-empty child predicate clobbered!");
+ setChild(i, NewChild);
+ }
+ } else {
+ getChild(i)->SubstituteFormalArguments(ArgMap);
+ }
+ }
+}
+
+
+/// InlinePatternFragments - If this pattern refers to any pattern
+/// fragments, inline them into place, giving us a pattern without any
+/// PatFrag references.
+TreePatternNode *TreePatternNode::InlinePatternFragments(TreePattern &TP) {
+ if (TP.hasError())
+ return nullptr;
+
+ if (isLeaf())
+ return this; // nothing to do.
+ Record *Op = getOperator();
+
+ if (!Op->isSubClassOf("PatFrag")) {
+ // Just recursively inline children nodes.
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = getChild(i);
+ TreePatternNode *NewChild = Child->InlinePatternFragments(TP);
+
+ assert((Child->getPredicateFns().empty() ||
+ NewChild->getPredicateFns() == Child->getPredicateFns()) &&
+ "Non-empty child predicate clobbered!");
+
+ setChild(i, NewChild);
+ }
+ return this;
+ }
+
+ // Otherwise, we found a reference to a fragment. First, look up its
+ // TreePattern record.
+ TreePattern *Frag = TP.getDAGPatterns().getPatternFragment(Op);
+
+ // Verify that we are passing the right number of operands.
+ if (Frag->getNumArgs() != Children.size()) {
+ TP.error("'" + Op->getName() + "' fragment requires " +
+ utostr(Frag->getNumArgs()) + " operands!");
+ return nullptr;
+ }
+
+ TreePatternNode *FragTree = Frag->getOnlyTree()->clone();
+
+ TreePredicateFn PredFn(Frag);
+ if (!PredFn.isAlwaysTrue())
+ FragTree->addPredicateFn(PredFn);
+
+ // Resolve formal arguments to their actual value.
+ if (Frag->getNumArgs()) {
+ // Compute the map of formal to actual arguments.
+ std::map<std::string, TreePatternNode*> ArgMap;
+ for (unsigned i = 0, e = Frag->getNumArgs(); i != e; ++i)
+ ArgMap[Frag->getArgName(i)] = getChild(i)->InlinePatternFragments(TP);
+
+ FragTree->SubstituteFormalArguments(ArgMap);
+ }
+
+ FragTree->setName(getName());
+ for (unsigned i = 0, e = Types.size(); i != e; ++i)
+ FragTree->UpdateNodeType(i, getExtType(i), TP);
+
+ // Transfer in the old predicates.
+ for (const TreePredicateFn &Pred : getPredicateFns())
+ FragTree->addPredicateFn(Pred);
+
+ // Get a new copy of this fragment to stitch into here.
+ //delete this; // FIXME: implement refcounting!
+
+ // The fragment we inlined could have recursive inlining that is needed. See
+ // if there are any pattern fragments in it and inline them as needed.
+ return FragTree->InlinePatternFragments(TP);
+}
+
+/// getImplicitType - Check to see if the specified record has an implicit
+/// type which should be applied to it. This will infer the type of register
+/// references from the register file information, for example.
+///
+/// When Unnamed is set, return the type of a DAG operand with no name, such as
+/// the F8RC register class argument in:
+///
+/// (COPY_TO_REGCLASS GPR:$src, F8RC)
+///
+/// When Unnamed is false, return the type of a named DAG operand such as the
+/// GPR:$src operand above.
+///
+static EEVT::TypeSet getImplicitType(Record *R, unsigned ResNo,
+ bool NotRegisters,
+ bool Unnamed,
+ TreePattern &TP) {
+ // Check to see if this is a register operand.
+ if (R->isSubClassOf("RegisterOperand")) {
+ assert(ResNo == 0 && "Regoperand ref only has one result!");
+ if (NotRegisters)
+ return EEVT::TypeSet(); // Unknown.
+ Record *RegClass = R->getValueAsDef("RegClass");
+ const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
+ return EEVT::TypeSet(T.getRegisterClass(RegClass).getValueTypes());
+ }
+
+ // Check to see if this is a register or a register class.
+ if (R->isSubClassOf("RegisterClass")) {
+ assert(ResNo == 0 && "Regclass ref only has one result!");
+ // An unnamed register class represents itself as an i32 immediate, for
+ // example on a COPY_TO_REGCLASS instruction.
+ if (Unnamed)
+ return EEVT::TypeSet(MVT::i32, TP);
+
+ // In a named operand, the register class provides the possible set of
+ // types.
+ if (NotRegisters)
+ return EEVT::TypeSet(); // Unknown.
+ const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
+ return EEVT::TypeSet(T.getRegisterClass(R).getValueTypes());
+ }
+
+ if (R->isSubClassOf("PatFrag")) {
+ assert(ResNo == 0 && "FIXME: PatFrag with multiple results?");
+ // Pattern fragment types will be resolved when they are inlined.
+ return EEVT::TypeSet(); // Unknown.
+ }
+
+ if (R->isSubClassOf("Register")) {
+ assert(ResNo == 0 && "Registers only produce one result!");
+ if (NotRegisters)
+ return EEVT::TypeSet(); // Unknown.
+ const CodeGenTarget &T = TP.getDAGPatterns().getTargetInfo();
+ return EEVT::TypeSet(T.getRegisterVTs(R));
+ }
+
+ if (R->isSubClassOf("SubRegIndex")) {
+ assert(ResNo == 0 && "SubRegisterIndices only produce one result!");
+ return EEVT::TypeSet(MVT::i32, TP);
+ }
+
+ if (R->isSubClassOf("ValueType")) {
+ assert(ResNo == 0 && "This node only has one result!");
+ // An unnamed VTSDNode represents itself as an MVT::Other immediate.
+ //
+ // (sext_inreg GPR:$src, i16)
+ // ~~~
+ if (Unnamed)
+ return EEVT::TypeSet(MVT::Other, TP);
+ // With a name, the ValueType simply provides the type of the named
+ // variable.
+ //
+ // (sext_inreg i32:$src, i16)
+ // ~~~~~~~~
+ if (NotRegisters)
+ return EEVT::TypeSet(); // Unknown.
+ return EEVT::TypeSet(getValueType(R), TP);
+ }
+
+ if (R->isSubClassOf("CondCode")) {
+ assert(ResNo == 0 && "This node only has one result!");
+ // Using a CondCodeSDNode.
+ return EEVT::TypeSet(MVT::Other, TP);
+ }
+
+ if (R->isSubClassOf("ComplexPattern")) {
+ assert(ResNo == 0 && "FIXME: ComplexPattern with multiple results?");
+ if (NotRegisters)
+ return EEVT::TypeSet(); // Unknown.
+ return EEVT::TypeSet(TP.getDAGPatterns().getComplexPattern(R).getValueType(),
+ TP);
+ }
+ if (R->isSubClassOf("PointerLikeRegClass")) {
+ assert(ResNo == 0 && "Regclass can only have one result!");
+ return EEVT::TypeSet(MVT::iPTR, TP);
+ }
+
+ if (R->getName() == "node" || R->getName() == "srcvalue" ||
+ R->getName() == "zero_reg") {
+ // Placeholder.
+ return EEVT::TypeSet(); // Unknown.
+ }
+
+ if (R->isSubClassOf("Operand"))
+ return EEVT::TypeSet(getValueType(R->getValueAsDef("Type")));
+
+ TP.error("Unknown node flavor used in pattern: " + R->getName());
+ return EEVT::TypeSet(MVT::Other, TP);
+}
+
+
+/// getIntrinsicInfo - If this node corresponds to an intrinsic, return the
+/// CodeGenIntrinsic information for it, otherwise return a null pointer.
+const CodeGenIntrinsic *TreePatternNode::
+getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const {
+ if (getOperator() != CDP.get_intrinsic_void_sdnode() &&
+ getOperator() != CDP.get_intrinsic_w_chain_sdnode() &&
+ getOperator() != CDP.get_intrinsic_wo_chain_sdnode())
+ return nullptr;
+
+ unsigned IID = cast<IntInit>(getChild(0)->getLeafValue())->getValue();
+ return &CDP.getIntrinsicInfo(IID);
+}
+
+/// getComplexPatternInfo - If this node corresponds to a ComplexPattern,
+/// return the ComplexPattern information, otherwise return null.
+const ComplexPattern *
+TreePatternNode::getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const {
+ Record *Rec;
+ if (isLeaf()) {
+ DefInit *DI = dyn_cast<DefInit>(getLeafValue());
+ if (!DI)
+ return nullptr;
+ Rec = DI->getDef();
+ } else
+ Rec = getOperator();
+
+ if (!Rec->isSubClassOf("ComplexPattern"))
+ return nullptr;
+ return &CGP.getComplexPattern(Rec);
+}
+
+unsigned TreePatternNode::getNumMIResults(const CodeGenDAGPatterns &CGP) const {
+ // A ComplexPattern specifically declares how many results it fills in.
+ if (const ComplexPattern *CP = getComplexPatternInfo(CGP))
+ return CP->getNumOperands();
+
+ // If MIOperandInfo is specified, that gives the count.
+ if (isLeaf()) {
+ DefInit *DI = dyn_cast<DefInit>(getLeafValue());
+ if (DI && DI->getDef()->isSubClassOf("Operand")) {
+ DagInit *MIOps = DI->getDef()->getValueAsDag("MIOperandInfo");
+ if (MIOps->getNumArgs())
+ return MIOps->getNumArgs();
+ }
+ }
+
+ // Otherwise there is just one result.
+ return 1;
+}
+
+/// NodeHasProperty - Return true if this node has the specified property.
+bool TreePatternNode::NodeHasProperty(SDNP Property,
+ const CodeGenDAGPatterns &CGP) const {
+ if (isLeaf()) {
+ if (const ComplexPattern *CP = getComplexPatternInfo(CGP))
+ return CP->hasProperty(Property);
+ return false;
+ }
+
+ Record *Operator = getOperator();
+ if (!Operator->isSubClassOf("SDNode")) return false;
+
+ return CGP.getSDNodeInfo(Operator).hasProperty(Property);
+}
+
+
+
+
+/// TreeHasProperty - Return true if any node in this tree has the specified
+/// property.
+bool TreePatternNode::TreeHasProperty(SDNP Property,
+ const CodeGenDAGPatterns &CGP) const {
+ if (NodeHasProperty(Property, CGP))
+ return true;
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (getChild(i)->TreeHasProperty(Property, CGP))
+ return true;
+ return false;
+}
+
+/// isCommutativeIntrinsic - Return true if the node corresponds to a
+/// commutative intrinsic.
+bool
+TreePatternNode::isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const {
+ if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP))
+ return Int->isCommutative;
+ return false;
+}
+
+static bool isOperandClass(const TreePatternNode *N, StringRef Class) {
+ if (!N->isLeaf())
+ return N->getOperator()->isSubClassOf(Class);
+
+ DefInit *DI = dyn_cast<DefInit>(N->getLeafValue());
+ if (DI && DI->getDef()->isSubClassOf(Class))
+ return true;
+
+ return false;
+}
+
+static void emitTooManyOperandsError(TreePattern &TP,
+ StringRef InstName,
+ unsigned Expected,
+ unsigned Actual) {
+ TP.error("Instruction '" + InstName + "' was provided " + Twine(Actual) +
+ " operands but expected only " + Twine(Expected) + "!");
+}
+
+static void emitTooFewOperandsError(TreePattern &TP,
+ StringRef InstName,
+ unsigned Actual) {
+ TP.error("Instruction '" + InstName +
+ "' expects more than the provided " + Twine(Actual) + " operands!");
+}
+
+/// ApplyTypeConstraints - Apply all of the type constraints relevant to
+/// this node and its children in the tree. This returns true if it makes a
+/// change, false otherwise. If a type contradiction is found, flag an error.
+bool TreePatternNode::ApplyTypeConstraints(TreePattern &TP, bool NotRegisters) {
+ if (TP.hasError())
+ return false;
+
+ CodeGenDAGPatterns &CDP = TP.getDAGPatterns();
+ if (isLeaf()) {
+ if (DefInit *DI = dyn_cast<DefInit>(getLeafValue())) {
+ // If it's a regclass or something else known, include the type.
+ bool MadeChange = false;
+ for (unsigned i = 0, e = Types.size(); i != e; ++i)
+ MadeChange |= UpdateNodeType(i, getImplicitType(DI->getDef(), i,
+ NotRegisters,
+ !hasName(), TP), TP);
+ return MadeChange;
+ }
+
+ if (IntInit *II = dyn_cast<IntInit>(getLeafValue())) {
+ assert(Types.size() == 1 && "Invalid IntInit");
+
+ // Int inits are always integers. :)
+ bool MadeChange = Types[0].EnforceInteger(TP);
+
+ if (!Types[0].isConcrete())
+ return MadeChange;
+
+ MVT::SimpleValueType VT = getType(0);
+ if (VT == MVT::iPTR || VT == MVT::iPTRAny)
+ return MadeChange;
+
+ unsigned Size = MVT(VT).getSizeInBits();
+ // Make sure that the value is representable for this type.
+ if (Size >= 32) return MadeChange;
+
+ // Check that the value doesn't use more bits than we have. It must either
+ // be a sign- or zero-extended equivalent of the original.
+ int64_t SignBitAndAbove = II->getValue() >> (Size - 1);
+ if (SignBitAndAbove == -1 || SignBitAndAbove == 0 || SignBitAndAbove == 1)
+ return MadeChange;
+
+ TP.error("Integer value '" + itostr(II->getValue()) +
+ "' is out of range for type '" + getEnumName(getType(0)) + "'!");
+ return false;
+ }
+ return false;
+ }
+
+ // special handling for set, which isn't really an SDNode.
+ if (getOperator()->getName() == "set") {
+ assert(getNumTypes() == 0 && "Set doesn't produce a value");
+ assert(getNumChildren() >= 2 && "Missing RHS of a set?");
+ unsigned NC = getNumChildren();
+
+ TreePatternNode *SetVal = getChild(NC-1);
+ bool MadeChange = SetVal->ApplyTypeConstraints(TP, NotRegisters);
+
+ for (unsigned i = 0; i < NC-1; ++i) {
+ TreePatternNode *Child = getChild(i);
+ MadeChange |= Child->ApplyTypeConstraints(TP, NotRegisters);
+
+ // Types of operands must match.
+ MadeChange |= Child->UpdateNodeType(0, SetVal->getExtType(i), TP);
+ MadeChange |= SetVal->UpdateNodeType(i, Child->getExtType(0), TP);
+ }
+ return MadeChange;
+ }
+
+ if (getOperator()->getName() == "implicit") {
+ assert(getNumTypes() == 0 && "Node doesn't produce a value");
+
+ bool MadeChange = false;
+ for (unsigned i = 0; i < getNumChildren(); ++i)
+ MadeChange = getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
+ return MadeChange;
+ }
+
+ if (const CodeGenIntrinsic *Int = getIntrinsicInfo(CDP)) {
+ bool MadeChange = false;
+
+ // Apply the result type to the node.
+ unsigned NumRetVTs = Int->IS.RetVTs.size();
+ unsigned NumParamVTs = Int->IS.ParamVTs.size();
+
+ for (unsigned i = 0, e = NumRetVTs; i != e; ++i)
+ MadeChange |= UpdateNodeType(i, Int->IS.RetVTs[i], TP);
+
+ if (getNumChildren() != NumParamVTs + 1) {
+ TP.error("Intrinsic '" + Int->Name + "' expects " +
+ utostr(NumParamVTs) + " operands, not " +
+ utostr(getNumChildren() - 1) + " operands!");
+ return false;
+ }
+
+ // Apply type info to the intrinsic ID.
+ MadeChange |= getChild(0)->UpdateNodeType(0, MVT::iPTR, TP);
+
+ for (unsigned i = 0, e = getNumChildren()-1; i != e; ++i) {
+ MadeChange |= getChild(i+1)->ApplyTypeConstraints(TP, NotRegisters);
+
+ MVT::SimpleValueType OpVT = Int->IS.ParamVTs[i];
+ assert(getChild(i+1)->getNumTypes() == 1 && "Unhandled case");
+ MadeChange |= getChild(i+1)->UpdateNodeType(0, OpVT, TP);
+ }
+ return MadeChange;
+ }
+
+ if (getOperator()->isSubClassOf("SDNode")) {
+ const SDNodeInfo &NI = CDP.getSDNodeInfo(getOperator());
+
+ // Check that the number of operands is sane. Negative operands -> varargs.
+ if (NI.getNumOperands() >= 0 &&
+ getNumChildren() != (unsigned)NI.getNumOperands()) {
+ TP.error(getOperator()->getName() + " node requires exactly " +
+ itostr(NI.getNumOperands()) + " operands!");
+ return false;
+ }
+
+ bool MadeChange = NI.ApplyTypeConstraints(this, TP);
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
+ return MadeChange;
+ }
+
+ if (getOperator()->isSubClassOf("Instruction")) {
+ const DAGInstruction &Inst = CDP.getInstruction(getOperator());
+ CodeGenInstruction &InstInfo =
+ CDP.getTargetInfo().getInstruction(getOperator());
+
+ bool MadeChange = false;
+
+ // Apply the result types to the node, these come from the things in the
+ // (outs) list of the instruction.
+ unsigned NumResultsToAdd = std::min(InstInfo.Operands.NumDefs,
+ Inst.getNumResults());
+ for (unsigned ResNo = 0; ResNo != NumResultsToAdd; ++ResNo)
+ MadeChange |= UpdateNodeTypeFromInst(ResNo, Inst.getResult(ResNo), TP);
+
+ // If the instruction has implicit defs, we apply the first one as a result.
+ // FIXME: This sucks, it should apply all implicit defs.
+ if (!InstInfo.ImplicitDefs.empty()) {
+ unsigned ResNo = NumResultsToAdd;
+
+ // FIXME: Generalize to multiple possible types and multiple possible
+ // ImplicitDefs.
+ MVT::SimpleValueType VT =
+ InstInfo.HasOneImplicitDefWithKnownVT(CDP.getTargetInfo());
+
+ if (VT != MVT::Other)
+ MadeChange |= UpdateNodeType(ResNo, VT, TP);
+ }
+
+ // If this is an INSERT_SUBREG, constrain the source and destination VTs to
+ // be the same.
+ if (getOperator()->getName() == "INSERT_SUBREG") {
+ assert(getChild(0)->getNumTypes() == 1 && "FIXME: Unhandled");
+ MadeChange |= UpdateNodeType(0, getChild(0)->getExtType(0), TP);
+ MadeChange |= getChild(0)->UpdateNodeType(0, getExtType(0), TP);
+ } else if (getOperator()->getName() == "REG_SEQUENCE") {
+ // We need to do extra, custom typechecking for REG_SEQUENCE since it is
+ // variadic.
+
+ unsigned NChild = getNumChildren();
+ if (NChild < 3) {
+ TP.error("REG_SEQUENCE requires at least 3 operands!");
+ return false;
+ }
+
+ if (NChild % 2 == 0) {
+ TP.error("REG_SEQUENCE requires an odd number of operands!");
+ return false;
+ }
+
+ if (!isOperandClass(getChild(0), "RegisterClass")) {
+ TP.error("REG_SEQUENCE requires a RegisterClass for first operand!");
+ return false;
+ }
+
+ for (unsigned I = 1; I < NChild; I += 2) {
+ TreePatternNode *SubIdxChild = getChild(I + 1);
+ if (!isOperandClass(SubIdxChild, "SubRegIndex")) {
+ TP.error("REG_SEQUENCE requires a SubRegIndex for operand " +
+ itostr(I + 1) + "!");
+ return false;
+ }
+ }
+ }
+
+ unsigned ChildNo = 0;
+ for (unsigned i = 0, e = Inst.getNumOperands(); i != e; ++i) {
+ Record *OperandNode = Inst.getOperand(i);
+
+ // If the instruction expects a predicate or optional def operand, we
+ // codegen this by setting the operand to it's default value if it has a
+ // non-empty DefaultOps field.
+ if (OperandNode->isSubClassOf("OperandWithDefaultOps") &&
+ !CDP.getDefaultOperand(OperandNode).DefaultOps.empty())
+ continue;
+
+ // Verify that we didn't run out of provided operands.
+ if (ChildNo >= getNumChildren()) {
+ emitTooFewOperandsError(TP, getOperator()->getName(), getNumChildren());
+ return false;
+ }
+
+ TreePatternNode *Child = getChild(ChildNo++);
+ unsigned ChildResNo = 0; // Instructions always use res #0 of their op.
+
+ // If the operand has sub-operands, they may be provided by distinct
+ // child patterns, so attempt to match each sub-operand separately.
+ if (OperandNode->isSubClassOf("Operand")) {
+ DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo");
+ if (unsigned NumArgs = MIOpInfo->getNumArgs()) {
+ // But don't do that if the whole operand is being provided by
+ // a single ComplexPattern-related Operand.
+
+ if (Child->getNumMIResults(CDP) < NumArgs) {
+ // Match first sub-operand against the child we already have.
+ Record *SubRec = cast<DefInit>(MIOpInfo->getArg(0))->getDef();
+ MadeChange |=
+ Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP);
+
+ // And the remaining sub-operands against subsequent children.
+ for (unsigned Arg = 1; Arg < NumArgs; ++Arg) {
+ if (ChildNo >= getNumChildren()) {
+ emitTooFewOperandsError(TP, getOperator()->getName(),
+ getNumChildren());
+ return false;
+ }
+ Child = getChild(ChildNo++);
+
+ SubRec = cast<DefInit>(MIOpInfo->getArg(Arg))->getDef();
+ MadeChange |=
+ Child->UpdateNodeTypeFromInst(ChildResNo, SubRec, TP);
+ }
+ continue;
+ }
+ }
+ }
+
+ // If we didn't match by pieces above, attempt to match the whole
+ // operand now.
+ MadeChange |= Child->UpdateNodeTypeFromInst(ChildResNo, OperandNode, TP);
+ }
+
+ if (!InstInfo.Operands.isVariadic && ChildNo != getNumChildren()) {
+ emitTooManyOperandsError(TP, getOperator()->getName(),
+ ChildNo, getNumChildren());
+ return false;
+ }
+
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
+ return MadeChange;
+ }
+
+ if (getOperator()->isSubClassOf("ComplexPattern")) {
+ bool MadeChange = false;
+
+ for (unsigned i = 0; i < getNumChildren(); ++i)
+ MadeChange |= getChild(i)->ApplyTypeConstraints(TP, NotRegisters);
+
+ return MadeChange;
+ }
+
+ assert(getOperator()->isSubClassOf("SDNodeXForm") && "Unknown node type!");
+
+ // Node transforms always take one operand.
+ if (getNumChildren() != 1) {
+ TP.error("Node transform '" + getOperator()->getName() +
+ "' requires one operand!");
+ return false;
+ }
+
+ bool MadeChange = getChild(0)->ApplyTypeConstraints(TP, NotRegisters);
+
+
+ // If either the output or input of the xform does not have exact
+ // type info. We assume they must be the same. Otherwise, it is perfectly
+ // legal to transform from one type to a completely different type.
+#if 0
+ if (!hasTypeSet() || !getChild(0)->hasTypeSet()) {
+ bool MadeChange = UpdateNodeType(getChild(0)->getExtType(), TP);
+ MadeChange |= getChild(0)->UpdateNodeType(getExtType(), TP);
+ return MadeChange;
+ }
+#endif
+ return MadeChange;
+}
+
+/// OnlyOnRHSOfCommutative - Return true if this value is only allowed on the
+/// RHS of a commutative operation, not the on LHS.
+static bool OnlyOnRHSOfCommutative(TreePatternNode *N) {
+ if (!N->isLeaf() && N->getOperator()->getName() == "imm")
+ return true;
+ if (N->isLeaf() && isa<IntInit>(N->getLeafValue()))
+ return true;
+ return false;
+}
+
+
+/// canPatternMatch - If it is impossible for this pattern to match on this
+/// target, fill in Reason and return false. Otherwise, return true. This is
+/// used as a sanity check for .td files (to prevent people from writing stuff
+/// that can never possibly work), and to prevent the pattern permuter from
+/// generating stuff that is useless.
+bool TreePatternNode::canPatternMatch(std::string &Reason,
+ const CodeGenDAGPatterns &CDP) {
+ if (isLeaf()) return true;
+
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (!getChild(i)->canPatternMatch(Reason, CDP))
+ return false;
+
+ // If this is an intrinsic, handle cases that would make it not match. For
+ // example, if an operand is required to be an immediate.
+ if (getOperator()->isSubClassOf("Intrinsic")) {
+ // TODO:
+ return true;
+ }
+
+ if (getOperator()->isSubClassOf("ComplexPattern"))
+ return true;
+
+ // If this node is a commutative operator, check that the LHS isn't an
+ // immediate.
+ const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(getOperator());
+ bool isCommIntrinsic = isCommutativeIntrinsic(CDP);
+ if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) {
+ // Scan all of the operands of the node and make sure that only the last one
+ // is a constant node, unless the RHS also is.
+ if (!OnlyOnRHSOfCommutative(getChild(getNumChildren()-1))) {
+ unsigned Skip = isCommIntrinsic ? 1 : 0; // First operand is intrinsic id.
+ for (unsigned i = Skip, e = getNumChildren()-1; i != e; ++i)
+ if (OnlyOnRHSOfCommutative(getChild(i))) {
+ Reason="Immediate value must be on the RHS of commutative operators!";
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+//===----------------------------------------------------------------------===//
+// TreePattern implementation
+//
+
+TreePattern::TreePattern(Record *TheRec, ListInit *RawPat, bool isInput,
+ CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp),
+ isInputPattern(isInput), HasError(false) {
+ for (Init *I : RawPat->getValues())
+ Trees.push_back(ParseTreePattern(I, ""));
+}
+
+TreePattern::TreePattern(Record *TheRec, DagInit *Pat, bool isInput,
+ CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp),
+ isInputPattern(isInput), HasError(false) {
+ Trees.push_back(ParseTreePattern(Pat, ""));
+}
+
+TreePattern::TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
+ CodeGenDAGPatterns &cdp) : TheRecord(TheRec), CDP(cdp),
+ isInputPattern(isInput), HasError(false) {
+ Trees.push_back(Pat);
+}
+
+void TreePattern::error(const Twine &Msg) {
+ if (HasError)
+ return;
+ dump();
+ PrintError(TheRecord->getLoc(), "In " + TheRecord->getName() + ": " + Msg);
+ HasError = true;
+}
+
+void TreePattern::ComputeNamedNodes() {
+ for (TreePatternNode *Tree : Trees)
+ ComputeNamedNodes(Tree);
+}
+
+void TreePattern::ComputeNamedNodes(TreePatternNode *N) {
+ if (!N->getName().empty())
+ NamedNodes[N->getName()].push_back(N);
+
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ ComputeNamedNodes(N->getChild(i));
+}
+
+
+TreePatternNode *TreePattern::ParseTreePattern(Init *TheInit, StringRef OpName){
+ if (DefInit *DI = dyn_cast<DefInit>(TheInit)) {
+ Record *R = DI->getDef();
+
+ // Direct reference to a leaf DagNode or PatFrag? Turn it into a
+ // TreePatternNode of its own. For example:
+ /// (foo GPR, imm) -> (foo GPR, (imm))
+ if (R->isSubClassOf("SDNode") || R->isSubClassOf("PatFrag"))
+ return ParseTreePattern(
+ DagInit::get(DI, nullptr,
+ std::vector<std::pair<Init*, StringInit*> >()),
+ OpName);
+
+ // Input argument?
+ TreePatternNode *Res = new TreePatternNode(DI, 1);
+ if (R->getName() == "node" && !OpName.empty()) {
+ if (OpName.empty())
+ error("'node' argument requires a name to match with operand list");
+ Args.push_back(OpName);
+ }
+
+ Res->setName(OpName);
+ return Res;
+ }
+
+ // ?:$name or just $name.
+ if (isa<UnsetInit>(TheInit)) {
+ if (OpName.empty())
+ error("'?' argument requires a name to match with operand list");
+ TreePatternNode *Res = new TreePatternNode(TheInit, 1);
+ Args.push_back(OpName);
+ Res->setName(OpName);
+ return Res;
+ }
+
+ if (IntInit *II = dyn_cast<IntInit>(TheInit)) {
+ if (!OpName.empty())
+ error("Constant int argument should not have a name!");
+ return new TreePatternNode(II, 1);
+ }
+
+ if (BitsInit *BI = dyn_cast<BitsInit>(TheInit)) {
+ // Turn this into an IntInit.
+ Init *II = BI->convertInitializerTo(IntRecTy::get());
+ if (!II || !isa<IntInit>(II))
+ error("Bits value must be constants!");
+ return ParseTreePattern(II, OpName);
+ }
+
+ DagInit *Dag = dyn_cast<DagInit>(TheInit);
+ if (!Dag) {
+ TheInit->print(errs());
+ error("Pattern has unexpected init kind!");
+ }
+ DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator());
+ if (!OpDef) error("Pattern has unexpected operator type!");
+ Record *Operator = OpDef->getDef();
+
+ if (Operator->isSubClassOf("ValueType")) {
+ // If the operator is a ValueType, then this must be "type cast" of a leaf
+ // node.
+ if (Dag->getNumArgs() != 1)
+ error("Type cast only takes one operand!");
+
+ TreePatternNode *New = ParseTreePattern(Dag->getArg(0),
+ Dag->getArgNameStr(0));
+
+ // Apply the type cast.
+ assert(New->getNumTypes() == 1 && "FIXME: Unhandled");
+ New->UpdateNodeType(0, getValueType(Operator), *this);
+
+ if (!OpName.empty())
+ error("ValueType cast should not have a name!");
+ return New;
+ }
+
+ // Verify that this is something that makes sense for an operator.
+ if (!Operator->isSubClassOf("PatFrag") &&
+ !Operator->isSubClassOf("SDNode") &&
+ !Operator->isSubClassOf("Instruction") &&
+ !Operator->isSubClassOf("SDNodeXForm") &&
+ !Operator->isSubClassOf("Intrinsic") &&
+ !Operator->isSubClassOf("ComplexPattern") &&
+ Operator->getName() != "set" &&
+ Operator->getName() != "implicit")
+ error("Unrecognized node '" + Operator->getName() + "'!");
+
+ // Check to see if this is something that is illegal in an input pattern.
+ if (isInputPattern) {
+ if (Operator->isSubClassOf("Instruction") ||
+ Operator->isSubClassOf("SDNodeXForm"))
+ error("Cannot use '" + Operator->getName() + "' in an input pattern!");
+ } else {
+ if (Operator->isSubClassOf("Intrinsic"))
+ error("Cannot use '" + Operator->getName() + "' in an output pattern!");
+
+ if (Operator->isSubClassOf("SDNode") &&
+ Operator->getName() != "imm" &&
+ Operator->getName() != "fpimm" &&
+ Operator->getName() != "tglobaltlsaddr" &&
+ Operator->getName() != "tconstpool" &&
+ Operator->getName() != "tjumptable" &&
+ Operator->getName() != "tframeindex" &&
+ Operator->getName() != "texternalsym" &&
+ Operator->getName() != "tblockaddress" &&
+ Operator->getName() != "tglobaladdr" &&
+ Operator->getName() != "bb" &&
+ Operator->getName() != "vt" &&
+ Operator->getName() != "mcsym")
+ error("Cannot use '" + Operator->getName() + "' in an output pattern!");
+ }
+
+ std::vector<TreePatternNode*> Children;
+
+ // Parse all the operands.
+ for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i)
+ Children.push_back(ParseTreePattern(Dag->getArg(i), Dag->getArgNameStr(i)));
+
+ // If the operator is an intrinsic, then this is just syntactic sugar for for
+ // (intrinsic_* <number>, ..children..). Pick the right intrinsic node, and
+ // convert the intrinsic name to a number.
+ if (Operator->isSubClassOf("Intrinsic")) {
+ const CodeGenIntrinsic &Int = getDAGPatterns().getIntrinsic(Operator);
+ unsigned IID = getDAGPatterns().getIntrinsicID(Operator)+1;
+
+ // If this intrinsic returns void, it must have side-effects and thus a
+ // chain.
+ if (Int.IS.RetVTs.empty())
+ Operator = getDAGPatterns().get_intrinsic_void_sdnode();
+ else if (Int.ModRef != CodeGenIntrinsic::NoMem)
+ // Has side-effects, requires chain.
+ Operator = getDAGPatterns().get_intrinsic_w_chain_sdnode();
+ else // Otherwise, no chain.
+ Operator = getDAGPatterns().get_intrinsic_wo_chain_sdnode();
+
+ TreePatternNode *IIDNode = new TreePatternNode(IntInit::get(IID), 1);
+ Children.insert(Children.begin(), IIDNode);
+ }
+
+ if (Operator->isSubClassOf("ComplexPattern")) {
+ for (unsigned i = 0; i < Children.size(); ++i) {
+ TreePatternNode *Child = Children[i];
+
+ if (Child->getName().empty())
+ error("All arguments to a ComplexPattern must be named");
+
+ // Check that the ComplexPattern uses are consistent: "(MY_PAT $a, $b)"
+ // and "(MY_PAT $b, $a)" should not be allowed in the same pattern;
+ // neither should "(MY_PAT_1 $a, $b)" and "(MY_PAT_2 $a, $b)".
+ auto OperandId = std::make_pair(Operator, i);
+ auto PrevOp = ComplexPatternOperands.find(Child->getName());
+ if (PrevOp != ComplexPatternOperands.end()) {
+ if (PrevOp->getValue() != OperandId)
+ error("All ComplexPattern operands must appear consistently: "
+ "in the same order in just one ComplexPattern instance.");
+ } else
+ ComplexPatternOperands[Child->getName()] = OperandId;
+ }
+ }
+
+ unsigned NumResults = GetNumNodeResults(Operator, CDP);
+ TreePatternNode *Result = new TreePatternNode(Operator, Children, NumResults);
+ Result->setName(OpName);
+
+ if (Dag->getName()) {
+ assert(Result->getName().empty());
+ Result->setName(Dag->getNameStr());
+ }
+ return Result;
+}
+
+/// SimplifyTree - See if we can simplify this tree to eliminate something that
+/// will never match in favor of something obvious that will. This is here
+/// strictly as a convenience to target authors because it allows them to write
+/// more type generic things and have useless type casts fold away.
+///
+/// This returns true if any change is made.
+static bool SimplifyTree(TreePatternNode *&N) {
+ if (N->isLeaf())
+ return false;
+
+ // If we have a bitconvert with a resolved type and if the source and
+ // destination types are the same, then the bitconvert is useless, remove it.
+ if (N->getOperator()->getName() == "bitconvert" &&
+ N->getExtType(0).isConcrete() &&
+ N->getExtType(0) == N->getChild(0)->getExtType(0) &&
+ N->getName().empty()) {
+ N = N->getChild(0);
+ SimplifyTree(N);
+ return true;
+ }
+
+ // Walk all children.
+ bool MadeChange = false;
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = N->getChild(i);
+ MadeChange |= SimplifyTree(Child);
+ N->setChild(i, Child);
+ }
+ return MadeChange;
+}
+
+
+
+/// InferAllTypes - Infer/propagate as many types throughout the expression
+/// patterns as possible. Return true if all types are inferred, false
+/// otherwise. Flags an error if a type contradiction is found.
+bool TreePattern::
+InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> > *InNamedTypes) {
+ if (NamedNodes.empty())
+ ComputeNamedNodes();
+
+ bool MadeChange = true;
+ while (MadeChange) {
+ MadeChange = false;
+ for (TreePatternNode *Tree : Trees) {
+ MadeChange |= Tree->ApplyTypeConstraints(*this, false);
+ MadeChange |= SimplifyTree(Tree);
+ }
+
+ // If there are constraints on our named nodes, apply them.
+ for (auto &Entry : NamedNodes) {
+ SmallVectorImpl<TreePatternNode*> &Nodes = Entry.second;
+
+ // If we have input named node types, propagate their types to the named
+ // values here.
+ if (InNamedTypes) {
+ if (!InNamedTypes->count(Entry.getKey())) {
+ error("Node '" + std::string(Entry.getKey()) +
+ "' in output pattern but not input pattern");
+ return true;
+ }
+
+ const SmallVectorImpl<TreePatternNode*> &InNodes =
+ InNamedTypes->find(Entry.getKey())->second;
+
+ // The input types should be fully resolved by now.
+ for (TreePatternNode *Node : Nodes) {
+ // If this node is a register class, and it is the root of the pattern
+ // then we're mapping something onto an input register. We allow
+ // changing the type of the input register in this case. This allows
+ // us to match things like:
+ // def : Pat<(v1i64 (bitconvert(v2i32 DPR:$src))), (v1i64 DPR:$src)>;
+ if (Node == Trees[0] && Node->isLeaf()) {
+ DefInit *DI = dyn_cast<DefInit>(Node->getLeafValue());
+ if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
+ DI->getDef()->isSubClassOf("RegisterOperand")))
+ continue;
+ }
+
+ assert(Node->getNumTypes() == 1 &&
+ InNodes[0]->getNumTypes() == 1 &&
+ "FIXME: cannot name multiple result nodes yet");
+ MadeChange |= Node->UpdateNodeType(0, InNodes[0]->getExtType(0),
+ *this);
+ }
+ }
+
+ // If there are multiple nodes with the same name, they must all have the
+ // same type.
+ if (Entry.second.size() > 1) {
+ for (unsigned i = 0, e = Nodes.size()-1; i != e; ++i) {
+ TreePatternNode *N1 = Nodes[i], *N2 = Nodes[i+1];
+ assert(N1->getNumTypes() == 1 && N2->getNumTypes() == 1 &&
+ "FIXME: cannot name multiple result nodes yet");
+
+ MadeChange |= N1->UpdateNodeType(0, N2->getExtType(0), *this);
+ MadeChange |= N2->UpdateNodeType(0, N1->getExtType(0), *this);
+ }
+ }
+ }
+ }
+
+ bool HasUnresolvedTypes = false;
+ for (const TreePatternNode *Tree : Trees)
+ HasUnresolvedTypes |= Tree->ContainsUnresolvedType();
+ return !HasUnresolvedTypes;
+}
+
+void TreePattern::print(raw_ostream &OS) const {
+ OS << getRecord()->getName();
+ if (!Args.empty()) {
+ OS << "(" << Args[0];
+ for (unsigned i = 1, e = Args.size(); i != e; ++i)
+ OS << ", " << Args[i];
+ OS << ")";
+ }
+ OS << ": ";
+
+ if (Trees.size() > 1)
+ OS << "[\n";
+ for (const TreePatternNode *Tree : Trees) {
+ OS << "\t";
+ Tree->print(OS);
+ OS << "\n";
+ }
+
+ if (Trees.size() > 1)
+ OS << "]\n";
+}
+
+void TreePattern::dump() const { print(errs()); }
+
+//===----------------------------------------------------------------------===//
+// CodeGenDAGPatterns implementation
+//
+
+CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
+ Records(R), Target(R) {
+
+ Intrinsics = CodeGenIntrinsicTable(Records, false);
+ TgtIntrinsics = CodeGenIntrinsicTable(Records, true);
+ ParseNodeInfo();
+ ParseNodeTransforms();
+ ParseComplexPatterns();
+ ParsePatternFragments();
+ ParseDefaultOperands();
+ ParseInstructions();
+ ParsePatternFragments(/*OutFrags*/true);
+ ParsePatterns();
+
+ // Generate variants. For example, commutative patterns can match
+ // multiple ways. Add them to PatternsToMatch as well.
+ GenerateVariants();
+
+ // Infer instruction flags. For example, we can detect loads,
+ // stores, and side effects in many cases by examining an
+ // instruction's pattern.
+ InferInstructionFlags();
+
+ // Verify that instruction flags match the patterns.
+ VerifyInstructionFlags();
+}
+
+Record *CodeGenDAGPatterns::getSDNodeNamed(const std::string &Name) const {
+ Record *N = Records.getDef(Name);
+ if (!N || !N->isSubClassOf("SDNode"))
+ PrintFatalError("Error getting SDNode '" + Name + "'!");
+
+ return N;
+}
+
+// Parse all of the SDNode definitions for the target, populating SDNodes.
+void CodeGenDAGPatterns::ParseNodeInfo() {
+ std::vector<Record*> Nodes = Records.getAllDerivedDefinitions("SDNode");
+ while (!Nodes.empty()) {
+ SDNodes.insert(std::make_pair(Nodes.back(), Nodes.back()));
+ Nodes.pop_back();
+ }
+
+ // Get the builtin intrinsic nodes.
+ intrinsic_void_sdnode = getSDNodeNamed("intrinsic_void");
+ intrinsic_w_chain_sdnode = getSDNodeNamed("intrinsic_w_chain");
+ intrinsic_wo_chain_sdnode = getSDNodeNamed("intrinsic_wo_chain");
+}
+
+/// ParseNodeTransforms - Parse all SDNodeXForm instances into the SDNodeXForms
+/// map, and emit them to the file as functions.
+void CodeGenDAGPatterns::ParseNodeTransforms() {
+ std::vector<Record*> Xforms = Records.getAllDerivedDefinitions("SDNodeXForm");
+ while (!Xforms.empty()) {
+ Record *XFormNode = Xforms.back();
+ Record *SDNode = XFormNode->getValueAsDef("Opcode");
+ std::string Code = XFormNode->getValueAsString("XFormFunction");
+ SDNodeXForms.insert(std::make_pair(XFormNode, NodeXForm(SDNode, Code)));
+
+ Xforms.pop_back();
+ }
+}
+
+void CodeGenDAGPatterns::ParseComplexPatterns() {
+ std::vector<Record*> AMs = Records.getAllDerivedDefinitions("ComplexPattern");
+ while (!AMs.empty()) {
+ ComplexPatterns.insert(std::make_pair(AMs.back(), AMs.back()));
+ AMs.pop_back();
+ }
+}
+
+
+/// ParsePatternFragments - Parse all of the PatFrag definitions in the .td
+/// file, building up the PatternFragments map. After we've collected them all,
+/// inline fragments together as necessary, so that there are no references left
+/// inside a pattern fragment to a pattern fragment.
+///
+void CodeGenDAGPatterns::ParsePatternFragments(bool OutFrags) {
+ std::vector<Record*> Fragments = Records.getAllDerivedDefinitions("PatFrag");
+
+ // First step, parse all of the fragments.
+ for (Record *Frag : Fragments) {
+ if (OutFrags != Frag->isSubClassOf("OutPatFrag"))
+ continue;
+
+ DagInit *Tree = Frag->getValueAsDag("Fragment");
+ TreePattern *P =
+ (PatternFragments[Frag] = llvm::make_unique<TreePattern>(
+ Frag, Tree, !Frag->isSubClassOf("OutPatFrag"),
+ *this)).get();
+
+ // Validate the argument list, converting it to set, to discard duplicates.
+ std::vector<std::string> &Args = P->getArgList();
+ std::set<std::string> OperandsSet(Args.begin(), Args.end());
+
+ if (OperandsSet.count(""))
+ P->error("Cannot have unnamed 'node' values in pattern fragment!");
+
+ // Parse the operands list.
+ DagInit *OpsList = Frag->getValueAsDag("Operands");
+ DefInit *OpsOp = dyn_cast<DefInit>(OpsList->getOperator());
+ // Special cases: ops == outs == ins. Different names are used to
+ // improve readability.
+ if (!OpsOp ||
+ (OpsOp->getDef()->getName() != "ops" &&
+ OpsOp->getDef()->getName() != "outs" &&
+ OpsOp->getDef()->getName() != "ins"))
+ P->error("Operands list should start with '(ops ... '!");
+
+ // Copy over the arguments.
+ Args.clear();
+ for (unsigned j = 0, e = OpsList->getNumArgs(); j != e; ++j) {
+ if (!isa<DefInit>(OpsList->getArg(j)) ||
+ cast<DefInit>(OpsList->getArg(j))->getDef()->getName() != "node")
+ P->error("Operands list should all be 'node' values.");
+ if (!OpsList->getArgName(j))
+ P->error("Operands list should have names for each operand!");
+ StringRef ArgNameStr = OpsList->getArgNameStr(j);
+ if (!OperandsSet.count(ArgNameStr))
+ P->error("'" + ArgNameStr +
+ "' does not occur in pattern or was multiply specified!");
+ OperandsSet.erase(ArgNameStr);
+ Args.push_back(ArgNameStr);
+ }
+
+ if (!OperandsSet.empty())
+ P->error("Operands list does not contain an entry for operand '" +
+ *OperandsSet.begin() + "'!");
+
+ // If there is a code init for this fragment, keep track of the fact that
+ // this fragment uses it.
+ TreePredicateFn PredFn(P);
+ if (!PredFn.isAlwaysTrue())
+ P->getOnlyTree()->addPredicateFn(PredFn);
+
+ // If there is a node transformation corresponding to this, keep track of
+ // it.
+ Record *Transform = Frag->getValueAsDef("OperandTransform");
+ if (!getSDNodeTransform(Transform).second.empty()) // not noop xform?
+ P->getOnlyTree()->setTransformFn(Transform);
+ }
+
+ // Now that we've parsed all of the tree fragments, do a closure on them so
+ // that there are not references to PatFrags left inside of them.
+ for (Record *Frag : Fragments) {
+ if (OutFrags != Frag->isSubClassOf("OutPatFrag"))
+ continue;
+
+ TreePattern &ThePat = *PatternFragments[Frag];
+ ThePat.InlinePatternFragments();
+
+ // Infer as many types as possible. Don't worry about it if we don't infer
+ // all of them, some may depend on the inputs of the pattern.
+ ThePat.InferAllTypes();
+ ThePat.resetError();
+
+ // If debugging, print out the pattern fragment result.
+ DEBUG(ThePat.dump());
+ }
+}
+
+void CodeGenDAGPatterns::ParseDefaultOperands() {
+ std::vector<Record*> DefaultOps;
+ DefaultOps = Records.getAllDerivedDefinitions("OperandWithDefaultOps");
+
+ // Find some SDNode.
+ assert(!SDNodes.empty() && "No SDNodes parsed?");
+ Init *SomeSDNode = DefInit::get(SDNodes.begin()->first);
+
+ for (unsigned i = 0, e = DefaultOps.size(); i != e; ++i) {
+ DagInit *DefaultInfo = DefaultOps[i]->getValueAsDag("DefaultOps");
+
+ // Clone the DefaultInfo dag node, changing the operator from 'ops' to
+ // SomeSDnode so that we can parse this.
+ std::vector<std::pair<Init*, StringInit*> > Ops;
+ for (unsigned op = 0, e = DefaultInfo->getNumArgs(); op != e; ++op)
+ Ops.push_back(std::make_pair(DefaultInfo->getArg(op),
+ DefaultInfo->getArgName(op)));
+ DagInit *DI = DagInit::get(SomeSDNode, nullptr, Ops);
+
+ // Create a TreePattern to parse this.
+ TreePattern P(DefaultOps[i], DI, false, *this);
+ assert(P.getNumTrees() == 1 && "This ctor can only produce one tree!");
+
+ // Copy the operands over into a DAGDefaultOperand.
+ DAGDefaultOperand DefaultOpInfo;
+
+ TreePatternNode *T = P.getTree(0);
+ for (unsigned op = 0, e = T->getNumChildren(); op != e; ++op) {
+ TreePatternNode *TPN = T->getChild(op);
+ while (TPN->ApplyTypeConstraints(P, false))
+ /* Resolve all types */;
+
+ if (TPN->ContainsUnresolvedType()) {
+ PrintFatalError("Value #" + Twine(i) + " of OperandWithDefaultOps '" +
+ DefaultOps[i]->getName() +
+ "' doesn't have a concrete type!");
+ }
+ DefaultOpInfo.DefaultOps.push_back(TPN);
+ }
+
+ // Insert it into the DefaultOperands map so we can find it later.
+ DefaultOperands[DefaultOps[i]] = DefaultOpInfo;
+ }
+}
+
+/// HandleUse - Given "Pat" a leaf in the pattern, check to see if it is an
+/// instruction input. Return true if this is a real use.
+static bool HandleUse(TreePattern *I, TreePatternNode *Pat,
+ std::map<std::string, TreePatternNode*> &InstInputs) {
+ // No name -> not interesting.
+ if (Pat->getName().empty()) {
+ if (Pat->isLeaf()) {
+ DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue());
+ if (DI && (DI->getDef()->isSubClassOf("RegisterClass") ||
+ DI->getDef()->isSubClassOf("RegisterOperand")))
+ I->error("Input " + DI->getDef()->getName() + " must be named!");
+ }
+ return false;
+ }
+
+ Record *Rec;
+ if (Pat->isLeaf()) {
+ DefInit *DI = dyn_cast<DefInit>(Pat->getLeafValue());
+ if (!DI) I->error("Input $" + Pat->getName() + " must be an identifier!");
+ Rec = DI->getDef();
+ } else {
+ Rec = Pat->getOperator();
+ }
+
+ // SRCVALUE nodes are ignored.
+ if (Rec->getName() == "srcvalue")
+ return false;
+
+ TreePatternNode *&Slot = InstInputs[Pat->getName()];
+ if (!Slot) {
+ Slot = Pat;
+ return true;
+ }
+ Record *SlotRec;
+ if (Slot->isLeaf()) {
+ SlotRec = cast<DefInit>(Slot->getLeafValue())->getDef();
+ } else {
+ assert(Slot->getNumChildren() == 0 && "can't be a use with children!");
+ SlotRec = Slot->getOperator();
+ }
+
+ // Ensure that the inputs agree if we've already seen this input.
+ if (Rec != SlotRec)
+ I->error("All $" + Pat->getName() + " inputs must agree with each other");
+ if (Slot->getExtTypes() != Pat->getExtTypes())
+ I->error("All $" + Pat->getName() + " inputs must agree with each other");
+ return true;
+}
+
+/// FindPatternInputsAndOutputs - Scan the specified TreePatternNode (which is
+/// part of "I", the instruction), computing the set of inputs and outputs of
+/// the pattern. Report errors if we see anything naughty.
+void CodeGenDAGPatterns::
+FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
+ std::map<std::string, TreePatternNode*> &InstInputs,
+ std::map<std::string, TreePatternNode*>&InstResults,
+ std::vector<Record*> &InstImpResults) {
+ if (Pat->isLeaf()) {
+ bool isUse = HandleUse(I, Pat, InstInputs);
+ if (!isUse && Pat->getTransformFn())
+ I->error("Cannot specify a transform function for a non-input value!");
+ return;
+ }
+
+ if (Pat->getOperator()->getName() == "implicit") {
+ for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Dest = Pat->getChild(i);
+ if (!Dest->isLeaf())
+ I->error("implicitly defined value should be a register!");
+
+ DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue());
+ if (!Val || !Val->getDef()->isSubClassOf("Register"))
+ I->error("implicitly defined value should be a register!");
+ InstImpResults.push_back(Val->getDef());
+ }
+ return;
+ }
+
+ if (Pat->getOperator()->getName() != "set") {
+ // If this is not a set, verify that the children nodes are not void typed,
+ // and recurse.
+ for (unsigned i = 0, e = Pat->getNumChildren(); i != e; ++i) {
+ if (Pat->getChild(i)->getNumTypes() == 0)
+ I->error("Cannot have void nodes inside of patterns!");
+ FindPatternInputsAndOutputs(I, Pat->getChild(i), InstInputs, InstResults,
+ InstImpResults);
+ }
+
+ // If this is a non-leaf node with no children, treat it basically as if
+ // it were a leaf. This handles nodes like (imm).
+ bool isUse = HandleUse(I, Pat, InstInputs);
+
+ if (!isUse && Pat->getTransformFn())
+ I->error("Cannot specify a transform function for a non-input value!");
+ return;
+ }
+
+ // Otherwise, this is a set, validate and collect instruction results.
+ if (Pat->getNumChildren() == 0)
+ I->error("set requires operands!");
+
+ if (Pat->getTransformFn())
+ I->error("Cannot specify a transform function on a set node!");
+
+ // Check the set destinations.
+ unsigned NumDests = Pat->getNumChildren()-1;
+ for (unsigned i = 0; i != NumDests; ++i) {
+ TreePatternNode *Dest = Pat->getChild(i);
+ if (!Dest->isLeaf())
+ I->error("set destination should be a register!");
+
+ DefInit *Val = dyn_cast<DefInit>(Dest->getLeafValue());
+ if (!Val) {
+ I->error("set destination should be a register!");
+ continue;
+ }
+
+ if (Val->getDef()->isSubClassOf("RegisterClass") ||
+ Val->getDef()->isSubClassOf("ValueType") ||
+ Val->getDef()->isSubClassOf("RegisterOperand") ||
+ Val->getDef()->isSubClassOf("PointerLikeRegClass")) {
+ if (Dest->getName().empty())
+ I->error("set destination must have a name!");
+ if (InstResults.count(Dest->getName()))
+ I->error("cannot set '" + Dest->getName() +"' multiple times");
+ InstResults[Dest->getName()] = Dest;
+ } else if (Val->getDef()->isSubClassOf("Register")) {
+ InstImpResults.push_back(Val->getDef());
+ } else {
+ I->error("set destination should be a register!");
+ }
+ }
+
+ // Verify and collect info from the computation.
+ FindPatternInputsAndOutputs(I, Pat->getChild(NumDests),
+ InstInputs, InstResults, InstImpResults);
+}
+
+//===----------------------------------------------------------------------===//
+// Instruction Analysis
+//===----------------------------------------------------------------------===//
+
+class InstAnalyzer {
+ const CodeGenDAGPatterns &CDP;
+public:
+ bool hasSideEffects;
+ bool mayStore;
+ bool mayLoad;
+ bool isBitcast;
+ bool isVariadic;
+
+ InstAnalyzer(const CodeGenDAGPatterns &cdp)
+ : CDP(cdp), hasSideEffects(false), mayStore(false), mayLoad(false),
+ isBitcast(false), isVariadic(false) {}
+
+ void Analyze(const TreePattern *Pat) {
+ // Assume only the first tree is the pattern. The others are clobber nodes.
+ AnalyzeNode(Pat->getTree(0));
+ }
+
+ void Analyze(const PatternToMatch *Pat) {
+ AnalyzeNode(Pat->getSrcPattern());
+ }
+
+private:
+ bool IsNodeBitcast(const TreePatternNode *N) const {
+ if (hasSideEffects || mayLoad || mayStore || isVariadic)
+ return false;
+
+ if (N->getNumChildren() != 2)
+ return false;
+
+ const TreePatternNode *N0 = N->getChild(0);
+ if (!N0->isLeaf() || !isa<DefInit>(N0->getLeafValue()))
+ return false;
+
+ const TreePatternNode *N1 = N->getChild(1);
+ if (N1->isLeaf())
+ return false;
+ if (N1->getNumChildren() != 1 || !N1->getChild(0)->isLeaf())
+ return false;
+
+ const SDNodeInfo &OpInfo = CDP.getSDNodeInfo(N1->getOperator());
+ if (OpInfo.getNumResults() != 1 || OpInfo.getNumOperands() != 1)
+ return false;
+ return OpInfo.getEnumName() == "ISD::BITCAST";
+ }
+
+public:
+ void AnalyzeNode(const TreePatternNode *N) {
+ if (N->isLeaf()) {
+ if (DefInit *DI = dyn_cast<DefInit>(N->getLeafValue())) {
+ Record *LeafRec = DI->getDef();
+ // Handle ComplexPattern leaves.
+ if (LeafRec->isSubClassOf("ComplexPattern")) {
+ const ComplexPattern &CP = CDP.getComplexPattern(LeafRec);
+ if (CP.hasProperty(SDNPMayStore)) mayStore = true;
+ if (CP.hasProperty(SDNPMayLoad)) mayLoad = true;
+ if (CP.hasProperty(SDNPSideEffect)) hasSideEffects = true;
+ }
+ }
+ return;
+ }
+
+ // Analyze children.
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ AnalyzeNode(N->getChild(i));
+
+ // Ignore set nodes, which are not SDNodes.
+ if (N->getOperator()->getName() == "set") {
+ isBitcast = IsNodeBitcast(N);
+ return;
+ }
+
+ // Notice properties of the node.
+ if (N->NodeHasProperty(SDNPMayStore, CDP)) mayStore = true;
+ if (N->NodeHasProperty(SDNPMayLoad, CDP)) mayLoad = true;
+ if (N->NodeHasProperty(SDNPSideEffect, CDP)) hasSideEffects = true;
+ if (N->NodeHasProperty(SDNPVariadic, CDP)) isVariadic = true;
+
+ if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) {
+ // If this is an intrinsic, analyze it.
+ if (IntInfo->ModRef & CodeGenIntrinsic::MR_Ref)
+ mayLoad = true;// These may load memory.
+
+ if (IntInfo->ModRef & CodeGenIntrinsic::MR_Mod)
+ mayStore = true;// Intrinsics that can write to memory are 'mayStore'.
+
+ if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteMem)
+ // ReadWriteMem intrinsics can have other strange effects.
+ hasSideEffects = true;
+ }
+ }
+
+};
+
+static bool InferFromPattern(CodeGenInstruction &InstInfo,
+ const InstAnalyzer &PatInfo,
+ Record *PatDef) {
+ bool Error = false;
+
+ // Remember where InstInfo got its flags.
+ if (InstInfo.hasUndefFlags())
+ InstInfo.InferredFrom = PatDef;
+
+ // Check explicitly set flags for consistency.
+ if (InstInfo.hasSideEffects != PatInfo.hasSideEffects &&
+ !InstInfo.hasSideEffects_Unset) {
+ // Allow explicitly setting hasSideEffects = 1 on instructions, even when
+ // the pattern has no side effects. That could be useful for div/rem
+ // instructions that may trap.
+ if (!InstInfo.hasSideEffects) {
+ Error = true;
+ PrintError(PatDef->getLoc(), "Pattern doesn't match hasSideEffects = " +
+ Twine(InstInfo.hasSideEffects));
+ }
+ }
+
+ if (InstInfo.mayStore != PatInfo.mayStore && !InstInfo.mayStore_Unset) {
+ Error = true;
+ PrintError(PatDef->getLoc(), "Pattern doesn't match mayStore = " +
+ Twine(InstInfo.mayStore));
+ }
+
+ if (InstInfo.mayLoad != PatInfo.mayLoad && !InstInfo.mayLoad_Unset) {
+ // Allow explicitly setting mayLoad = 1, even when the pattern has no loads.
+ // Some targets translate immediates to loads.
+ if (!InstInfo.mayLoad) {
+ Error = true;
+ PrintError(PatDef->getLoc(), "Pattern doesn't match mayLoad = " +
+ Twine(InstInfo.mayLoad));
+ }
+ }
+
+ // Transfer inferred flags.
+ InstInfo.hasSideEffects |= PatInfo.hasSideEffects;
+ InstInfo.mayStore |= PatInfo.mayStore;
+ InstInfo.mayLoad |= PatInfo.mayLoad;
+
+ // These flags are silently added without any verification.
+ InstInfo.isBitcast |= PatInfo.isBitcast;
+
+ // Don't infer isVariadic. This flag means something different on SDNodes and
+ // instructions. For example, a CALL SDNode is variadic because it has the
+ // call arguments as operands, but a CALL instruction is not variadic - it
+ // has argument registers as implicit, not explicit uses.
+
+ return Error;
+}
+
+/// hasNullFragReference - Return true if the DAG has any reference to the
+/// null_frag operator.
+static bool hasNullFragReference(DagInit *DI) {
+ DefInit *OpDef = dyn_cast<DefInit>(DI->getOperator());
+ if (!OpDef) return false;
+ Record *Operator = OpDef->getDef();
+
+ // If this is the null fragment, return true.
+ if (Operator->getName() == "null_frag") return true;
+ // If any of the arguments reference the null fragment, return true.
+ for (unsigned i = 0, e = DI->getNumArgs(); i != e; ++i) {
+ DagInit *Arg = dyn_cast<DagInit>(DI->getArg(i));
+ if (Arg && hasNullFragReference(Arg))
+ return true;
+ }
+
+ return false;
+}
+
+/// hasNullFragReference - Return true if any DAG in the list references
+/// the null_frag operator.
+static bool hasNullFragReference(ListInit *LI) {
+ for (Init *I : LI->getValues()) {
+ DagInit *DI = dyn_cast<DagInit>(I);
+ assert(DI && "non-dag in an instruction Pattern list?!");
+ if (hasNullFragReference(DI))
+ return true;
+ }
+ return false;
+}
+
+/// Get all the instructions in a tree.
+static void
+getInstructionsInTree(TreePatternNode *Tree, SmallVectorImpl<Record*> &Instrs) {
+ if (Tree->isLeaf())
+ return;
+ if (Tree->getOperator()->isSubClassOf("Instruction"))
+ Instrs.push_back(Tree->getOperator());
+ for (unsigned i = 0, e = Tree->getNumChildren(); i != e; ++i)
+ getInstructionsInTree(Tree->getChild(i), Instrs);
+}
+
+/// Check the class of a pattern leaf node against the instruction operand it
+/// represents.
+static bool checkOperandClass(CGIOperandList::OperandInfo &OI,
+ Record *Leaf) {
+ if (OI.Rec == Leaf)
+ return true;
+
+ // Allow direct value types to be used in instruction set patterns.
+ // The type will be checked later.
+ if (Leaf->isSubClassOf("ValueType"))
+ return true;
+
+ // Patterns can also be ComplexPattern instances.
+ if (Leaf->isSubClassOf("ComplexPattern"))
+ return true;
+
+ return false;
+}
+
+const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
+ CodeGenInstruction &CGI, ListInit *Pat, DAGInstMap &DAGInsts) {
+
+ assert(!DAGInsts.count(CGI.TheDef) && "Instruction already parsed!");
+
+ // Parse the instruction.
+ TreePattern *I = new TreePattern(CGI.TheDef, Pat, true, *this);
+ // Inline pattern fragments into it.
+ I->InlinePatternFragments();
+
+ // Infer as many types as possible. If we cannot infer all of them, we can
+ // never do anything with this instruction pattern: report it to the user.
+ if (!I->InferAllTypes())
+ I->error("Could not infer all types in pattern!");
+
+ // InstInputs - Keep track of all of the inputs of the instruction, along
+ // with the record they are declared as.
+ std::map<std::string, TreePatternNode*> InstInputs;
+
+ // InstResults - Keep track of all the virtual registers that are 'set'
+ // in the instruction, including what reg class they are.
+ std::map<std::string, TreePatternNode*> InstResults;
+
+ std::vector<Record*> InstImpResults;
+
+ // Verify that the top-level forms in the instruction are of void type, and
+ // fill in the InstResults map.
+ for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
+ TreePatternNode *Pat = I->getTree(j);
+ if (Pat->getNumTypes() != 0) {
+ std::string Types;
+ for (unsigned k = 0, ke = Pat->getNumTypes(); k != ke; ++k) {
+ if (k > 0)
+ Types += ", ";
+ Types += Pat->getExtType(k).getName();
+ }
+ I->error("Top-level forms in instruction pattern should have"
+ " void types, has types " + Types);
+ }
+
+ // Find inputs and outputs, and verify the structure of the uses/defs.
+ FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,
+ InstImpResults);
+ }
+
+ // Now that we have inputs and outputs of the pattern, inspect the operands
+ // list for the instruction. This determines the order that operands are
+ // added to the machine instruction the node corresponds to.
+ unsigned NumResults = InstResults.size();
+
+ // Parse the operands list from the (ops) list, validating it.
+ assert(I->getArgList().empty() && "Args list should still be empty here!");
+
+ // Check that all of the results occur first in the list.
+ std::vector<Record*> Results;
+ SmallVector<TreePatternNode *, 2> ResNodes;
+ for (unsigned i = 0; i != NumResults; ++i) {
+ if (i == CGI.Operands.size())
+ I->error("'" + InstResults.begin()->first +
+ "' set but does not appear in operand list!");
+ const std::string &OpName = CGI.Operands[i].Name;
+
+ // Check that it exists in InstResults.
+ TreePatternNode *RNode = InstResults[OpName];
+ if (!RNode)
+ I->error("Operand $" + OpName + " does not exist in operand list!");
+
+ ResNodes.push_back(RNode);
+
+ Record *R = cast<DefInit>(RNode->getLeafValue())->getDef();
+ if (!R)
+ I->error("Operand $" + OpName + " should be a set destination: all "
+ "outputs must occur before inputs in operand list!");
+
+ if (!checkOperandClass(CGI.Operands[i], R))
+ I->error("Operand $" + OpName + " class mismatch!");
+
+ // Remember the return type.
+ Results.push_back(CGI.Operands[i].Rec);
+
+ // Okay, this one checks out.
+ InstResults.erase(OpName);
+ }
+
+ // Loop over the inputs next. Make a copy of InstInputs so we can destroy
+ // the copy while we're checking the inputs.
+ std::map<std::string, TreePatternNode*> InstInputsCheck(InstInputs);
+
+ std::vector<TreePatternNode*> ResultNodeOperands;
+ std::vector<Record*> Operands;
+ for (unsigned i = NumResults, e = CGI.Operands.size(); i != e; ++i) {
+ CGIOperandList::OperandInfo &Op = CGI.Operands[i];
+ const std::string &OpName = Op.Name;
+ if (OpName.empty())
+ I->error("Operand #" + utostr(i) + " in operands list has no name!");
+
+ if (!InstInputsCheck.count(OpName)) {
+ // If this is an operand with a DefaultOps set filled in, we can ignore
+ // this. When we codegen it, we will do so as always executed.
+ if (Op.Rec->isSubClassOf("OperandWithDefaultOps")) {
+ // Does it have a non-empty DefaultOps field? If so, ignore this
+ // operand.
+ if (!getDefaultOperand(Op.Rec).DefaultOps.empty())
+ continue;
+ }
+ I->error("Operand $" + OpName +
+ " does not appear in the instruction pattern");
+ }
+ TreePatternNode *InVal = InstInputsCheck[OpName];
+ InstInputsCheck.erase(OpName); // It occurred, remove from map.
+
+ if (InVal->isLeaf() && isa<DefInit>(InVal->getLeafValue())) {
+ Record *InRec = static_cast<DefInit*>(InVal->getLeafValue())->getDef();
+ if (!checkOperandClass(Op, InRec))
+ I->error("Operand $" + OpName + "'s register class disagrees"
+ " between the operand and pattern");
+ }
+ Operands.push_back(Op.Rec);
+
+ // Construct the result for the dest-pattern operand list.
+ TreePatternNode *OpNode = InVal->clone();
+
+ // No predicate is useful on the result.
+ OpNode->clearPredicateFns();
+
+ // Promote the xform function to be an explicit node if set.
+ if (Record *Xform = OpNode->getTransformFn()) {
+ OpNode->setTransformFn(nullptr);
+ std::vector<TreePatternNode*> Children;
+ Children.push_back(OpNode);
+ OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
+ }
+
+ ResultNodeOperands.push_back(OpNode);
+ }
+
+ if (!InstInputsCheck.empty())
+ I->error("Input operand $" + InstInputsCheck.begin()->first +
+ " occurs in pattern but not in operands list!");
+
+ TreePatternNode *ResultPattern =
+ new TreePatternNode(I->getRecord(), ResultNodeOperands,
+ GetNumNodeResults(I->getRecord(), *this));
+ // Copy fully inferred output node types to instruction result pattern.
+ for (unsigned i = 0; i != NumResults; ++i) {
+ assert(ResNodes[i]->getNumTypes() == 1 && "FIXME: Unhandled");
+ ResultPattern->setType(i, ResNodes[i]->getExtType(0));
+ }
+
+ // Create and insert the instruction.
+ // FIXME: InstImpResults should not be part of DAGInstruction.
+ DAGInstruction TheInst(I, Results, Operands, InstImpResults);
+ DAGInsts.insert(std::make_pair(I->getRecord(), TheInst));
+
+ // Use a temporary tree pattern to infer all types and make sure that the
+ // constructed result is correct. This depends on the instruction already
+ // being inserted into the DAGInsts map.
+ TreePattern Temp(I->getRecord(), ResultPattern, false, *this);
+ Temp.InferAllTypes(&I->getNamedNodesMap());
+
+ DAGInstruction &TheInsertedInst = DAGInsts.find(I->getRecord())->second;
+ TheInsertedInst.setResultPattern(Temp.getOnlyTree());
+
+ return TheInsertedInst;
+}
+
+/// ParseInstructions - Parse all of the instructions, inlining and resolving
+/// any fragments involved. This populates the Instructions list with fully
+/// resolved instructions.
+void CodeGenDAGPatterns::ParseInstructions() {
+ std::vector<Record*> Instrs = Records.getAllDerivedDefinitions("Instruction");
+
+ for (Record *Instr : Instrs) {
+ ListInit *LI = nullptr;
+
+ if (isa<ListInit>(Instr->getValueInit("Pattern")))
+ LI = Instr->getValueAsListInit("Pattern");
+
+ // If there is no pattern, only collect minimal information about the
+ // instruction for its operand list. We have to assume that there is one
+ // result, as we have no detailed info. A pattern which references the
+ // null_frag operator is as-if no pattern were specified. Normally this
+ // is from a multiclass expansion w/ a SDPatternOperator passed in as
+ // null_frag.
+ if (!LI || LI->empty() || hasNullFragReference(LI)) {
+ std::vector<Record*> Results;
+ std::vector<Record*> Operands;
+
+ CodeGenInstruction &InstInfo = Target.getInstruction(Instr);
+
+ if (InstInfo.Operands.size() != 0) {
+ for (unsigned j = 0, e = InstInfo.Operands.NumDefs; j < e; ++j)
+ Results.push_back(InstInfo.Operands[j].Rec);
+
+ // The rest are inputs.
+ for (unsigned j = InstInfo.Operands.NumDefs,
+ e = InstInfo.Operands.size(); j < e; ++j)
+ Operands.push_back(InstInfo.Operands[j].Rec);
+ }
+
+ // Create and insert the instruction.
+ std::vector<Record*> ImpResults;
+ Instructions.insert(std::make_pair(Instr,
+ DAGInstruction(nullptr, Results, Operands, ImpResults)));
+ continue; // no pattern.
+ }
+
+ CodeGenInstruction &CGI = Target.getInstruction(Instr);
+ const DAGInstruction &DI = parseInstructionPattern(CGI, LI, Instructions);
+
+ (void)DI;
+ DEBUG(DI.getPattern()->dump());
+ }
+
+ // If we can, convert the instructions to be patterns that are matched!
+ for (auto &Entry : Instructions) {
+ DAGInstruction &TheInst = Entry.second;
+ TreePattern *I = TheInst.getPattern();
+ if (!I) continue; // No pattern.
+
+ // FIXME: Assume only the first tree is the pattern. The others are clobber
+ // nodes.
+ TreePatternNode *Pattern = I->getTree(0);
+ TreePatternNode *SrcPattern;
+ if (Pattern->getOperator()->getName() == "set") {
+ SrcPattern = Pattern->getChild(Pattern->getNumChildren()-1)->clone();
+ } else{
+ // Not a set (store or something?)
+ SrcPattern = Pattern;
+ }
+
+ Record *Instr = Entry.first;
+ AddPatternToMatch(I,
+ PatternToMatch(Instr,
+ Instr->getValueAsListInit("Predicates"),
+ SrcPattern,
+ TheInst.getResultPattern(),
+ TheInst.getImpResults(),
+ Instr->getValueAsInt("AddedComplexity"),
+ Instr->getID()));
+ }
+}
+
+
+typedef std::pair<const TreePatternNode*, unsigned> NameRecord;
+
+static void FindNames(const TreePatternNode *P,
+ std::map<std::string, NameRecord> &Names,
+ TreePattern *PatternTop) {
+ if (!P->getName().empty()) {
+ NameRecord &Rec = Names[P->getName()];
+ // If this is the first instance of the name, remember the node.
+ if (Rec.second++ == 0)
+ Rec.first = P;
+ else if (Rec.first->getExtTypes() != P->getExtTypes())
+ PatternTop->error("repetition of value: $" + P->getName() +
+ " where different uses have different types!");
+ }
+
+ if (!P->isLeaf()) {
+ for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
+ FindNames(P->getChild(i), Names, PatternTop);
+ }
+}
+
+void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern,
+ const PatternToMatch &PTM) {
+ // Do some sanity checking on the pattern we're about to match.
+ std::string Reason;
+ if (!PTM.getSrcPattern()->canPatternMatch(Reason, *this)) {
+ PrintWarning(Pattern->getRecord()->getLoc(),
+ Twine("Pattern can never match: ") + Reason);
+ return;
+ }
+
+ // If the source pattern's root is a complex pattern, that complex pattern
+ // must specify the nodes it can potentially match.
+ if (const ComplexPattern *CP =
+ PTM.getSrcPattern()->getComplexPatternInfo(*this))
+ if (CP->getRootNodes().empty())
+ Pattern->error("ComplexPattern at root must specify list of opcodes it"
+ " could match");
+
+
+ // Find all of the named values in the input and output, ensure they have the
+ // same type.
+ std::map<std::string, NameRecord> SrcNames, DstNames;
+ FindNames(PTM.getSrcPattern(), SrcNames, Pattern);
+ FindNames(PTM.getDstPattern(), DstNames, Pattern);
+
+ // Scan all of the named values in the destination pattern, rejecting them if
+ // they don't exist in the input pattern.
+ for (const auto &Entry : DstNames) {
+ if (SrcNames[Entry.first].first == nullptr)
+ Pattern->error("Pattern has input without matching name in output: $" +
+ Entry.first);
+ }
+
+ // Scan all of the named values in the source pattern, rejecting them if the
+ // name isn't used in the dest, and isn't used to tie two values together.
+ for (const auto &Entry : SrcNames)
+ if (DstNames[Entry.first].first == nullptr &&
+ SrcNames[Entry.first].second == 1)
+ Pattern->error("Pattern has dead named input: $" + Entry.first);
+
+ PatternsToMatch.push_back(PTM);
+}
+
+
+
+void CodeGenDAGPatterns::InferInstructionFlags() {
+ ArrayRef<const CodeGenInstruction*> Instructions =
+ Target.getInstructionsByEnumValue();
+
+ // First try to infer flags from the primary instruction pattern, if any.
+ SmallVector<CodeGenInstruction*, 8> Revisit;
+ unsigned Errors = 0;
+ for (unsigned i = 0, e = Instructions.size(); i != e; ++i) {
+ CodeGenInstruction &InstInfo =
+ const_cast<CodeGenInstruction &>(*Instructions[i]);
+
+ // Get the primary instruction pattern.
+ const TreePattern *Pattern = getInstruction(InstInfo.TheDef).getPattern();
+ if (!Pattern) {
+ if (InstInfo.hasUndefFlags())
+ Revisit.push_back(&InstInfo);
+ continue;
+ }
+ InstAnalyzer PatInfo(*this);
+ PatInfo.Analyze(Pattern);
+ Errors += InferFromPattern(InstInfo, PatInfo, InstInfo.TheDef);
+ }
+
+ // Second, look for single-instruction patterns defined outside the
+ // instruction.
+ for (ptm_iterator I = ptm_begin(), E = ptm_end(); I != E; ++I) {
+ const PatternToMatch &PTM = *I;
+
+ // We can only infer from single-instruction patterns, otherwise we won't
+ // know which instruction should get the flags.
+ SmallVector<Record*, 8> PatInstrs;
+ getInstructionsInTree(PTM.getDstPattern(), PatInstrs);
+ if (PatInstrs.size() != 1)
+ continue;
+
+ // Get the single instruction.
+ CodeGenInstruction &InstInfo = Target.getInstruction(PatInstrs.front());
+
+ // Only infer properties from the first pattern. We'll verify the others.
+ if (InstInfo.InferredFrom)
+ continue;
+
+ InstAnalyzer PatInfo(*this);
+ PatInfo.Analyze(&PTM);
+ Errors += InferFromPattern(InstInfo, PatInfo, PTM.getSrcRecord());
+ }
+
+ if (Errors)
+ PrintFatalError("pattern conflicts");
+
+ // Revisit instructions with undefined flags and no pattern.
+ if (Target.guessInstructionProperties()) {
+ for (CodeGenInstruction *InstInfo : Revisit) {
+ if (InstInfo->InferredFrom)
+ continue;
+ // The mayLoad and mayStore flags default to false.
+ // Conservatively assume hasSideEffects if it wasn't explicit.
+ if (InstInfo->hasSideEffects_Unset)
+ InstInfo->hasSideEffects = true;
+ }
+ return;
+ }
+
+ // Complain about any flags that are still undefined.
+ for (CodeGenInstruction *InstInfo : Revisit) {
+ if (InstInfo->InferredFrom)
+ continue;
+ if (InstInfo->hasSideEffects_Unset)
+ PrintError(InstInfo->TheDef->getLoc(),
+ "Can't infer hasSideEffects from patterns");
+ if (InstInfo->mayStore_Unset)
+ PrintError(InstInfo->TheDef->getLoc(),
+ "Can't infer mayStore from patterns");
+ if (InstInfo->mayLoad_Unset)
+ PrintError(InstInfo->TheDef->getLoc(),
+ "Can't infer mayLoad from patterns");
+ }
+}
+
+
+/// Verify instruction flags against pattern node properties.
+void CodeGenDAGPatterns::VerifyInstructionFlags() {
+ unsigned Errors = 0;
+ for (ptm_iterator I = ptm_begin(), E = ptm_end(); I != E; ++I) {
+ const PatternToMatch &PTM = *I;
+ SmallVector<Record*, 8> Instrs;
+ getInstructionsInTree(PTM.getDstPattern(), Instrs);
+ if (Instrs.empty())
+ continue;
+
+ // Count the number of instructions with each flag set.
+ unsigned NumSideEffects = 0;
+ unsigned NumStores = 0;
+ unsigned NumLoads = 0;
+ for (const Record *Instr : Instrs) {
+ const CodeGenInstruction &InstInfo = Target.getInstruction(Instr);
+ NumSideEffects += InstInfo.hasSideEffects;
+ NumStores += InstInfo.mayStore;
+ NumLoads += InstInfo.mayLoad;
+ }
+
+ // Analyze the source pattern.
+ InstAnalyzer PatInfo(*this);
+ PatInfo.Analyze(&PTM);
+
+ // Collect error messages.
+ SmallVector<std::string, 4> Msgs;
+
+ // Check for missing flags in the output.
+ // Permit extra flags for now at least.
+ if (PatInfo.hasSideEffects && !NumSideEffects)
+ Msgs.push_back("pattern has side effects, but hasSideEffects isn't set");
+
+ // Don't verify store flags on instructions with side effects. At least for
+ // intrinsics, side effects implies mayStore.
+ if (!PatInfo.hasSideEffects && PatInfo.mayStore && !NumStores)
+ Msgs.push_back("pattern may store, but mayStore isn't set");
+
+ // Similarly, mayStore implies mayLoad on intrinsics.
+ if (!PatInfo.mayStore && PatInfo.mayLoad && !NumLoads)
+ Msgs.push_back("pattern may load, but mayLoad isn't set");
+
+ // Print error messages.
+ if (Msgs.empty())
+ continue;
+ ++Errors;
+
+ for (const std::string &Msg : Msgs)
+ PrintError(PTM.getSrcRecord()->getLoc(), Twine(Msg) + " on the " +
+ (Instrs.size() == 1 ?
+ "instruction" : "output instructions"));
+ // Provide the location of the relevant instruction definitions.
+ for (const Record *Instr : Instrs) {
+ if (Instr != PTM.getSrcRecord())
+ PrintError(Instr->getLoc(), "defined here");
+ const CodeGenInstruction &InstInfo = Target.getInstruction(Instr);
+ if (InstInfo.InferredFrom &&
+ InstInfo.InferredFrom != InstInfo.TheDef &&
+ InstInfo.InferredFrom != PTM.getSrcRecord())
+ PrintError(InstInfo.InferredFrom->getLoc(), "inferred from pattern");
+ }
+ }
+ if (Errors)
+ PrintFatalError("Errors in DAG patterns");
+}
+
+/// Given a pattern result with an unresolved type, see if we can find one
+/// instruction with an unresolved result type. Force this result type to an
+/// arbitrary element if it's possible types to converge results.
+static bool ForceArbitraryInstResultType(TreePatternNode *N, TreePattern &TP) {
+ if (N->isLeaf())
+ return false;
+
+ // Analyze children.
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ if (ForceArbitraryInstResultType(N->getChild(i), TP))
+ return true;
+
+ if (!N->getOperator()->isSubClassOf("Instruction"))
+ return false;
+
+ // If this type is already concrete or completely unknown we can't do
+ // anything.
+ for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i) {
+ if (N->getExtType(i).isCompletelyUnknown() || N->getExtType(i).isConcrete())
+ continue;
+
+ // Otherwise, force its type to the first possibility (an arbitrary choice).
+ if (N->getExtType(i).MergeInTypeInfo(N->getExtType(i).getTypeList()[0], TP))
+ return true;
+ }
+
+ return false;
+}
+
+void CodeGenDAGPatterns::ParsePatterns() {
+ std::vector<Record*> Patterns = Records.getAllDerivedDefinitions("Pattern");
+
+ for (Record *CurPattern : Patterns) {
+ DagInit *Tree = CurPattern->getValueAsDag("PatternToMatch");
+
+ // If the pattern references the null_frag, there's nothing to do.
+ if (hasNullFragReference(Tree))
+ continue;
+
+ TreePattern *Pattern = new TreePattern(CurPattern, Tree, true, *this);
+
+ // Inline pattern fragments into it.
+ Pattern->InlinePatternFragments();
+
+ ListInit *LI = CurPattern->getValueAsListInit("ResultInstrs");
+ if (LI->empty()) continue; // no pattern.
+
+ // Parse the instruction.
+ TreePattern Result(CurPattern, LI, false, *this);
+
+ // Inline pattern fragments into it.
+ Result.InlinePatternFragments();
+
+ if (Result.getNumTrees() != 1)
+ Result.error("Cannot handle instructions producing instructions "
+ "with temporaries yet!");
+
+ bool IterateInference;
+ bool InferredAllPatternTypes, InferredAllResultTypes;
+ do {
+ // Infer as many types as possible. If we cannot infer all of them, we
+ // can never do anything with this pattern: report it to the user.
+ InferredAllPatternTypes =
+ Pattern->InferAllTypes(&Pattern->getNamedNodesMap());
+
+ // Infer as many types as possible. If we cannot infer all of them, we
+ // can never do anything with this pattern: report it to the user.
+ InferredAllResultTypes =
+ Result.InferAllTypes(&Pattern->getNamedNodesMap());
+
+ IterateInference = false;
+
+ // Apply the type of the result to the source pattern. This helps us
+ // resolve cases where the input type is known to be a pointer type (which
+ // is considered resolved), but the result knows it needs to be 32- or
+ // 64-bits. Infer the other way for good measure.
+ for (unsigned i = 0, e = std::min(Result.getTree(0)->getNumTypes(),
+ Pattern->getTree(0)->getNumTypes());
+ i != e; ++i) {
+ IterateInference = Pattern->getTree(0)->UpdateNodeType(
+ i, Result.getTree(0)->getExtType(i), Result);
+ IterateInference |= Result.getTree(0)->UpdateNodeType(
+ i, Pattern->getTree(0)->getExtType(i), Result);
+ }
+
+ // If our iteration has converged and the input pattern's types are fully
+ // resolved but the result pattern is not fully resolved, we may have a
+ // situation where we have two instructions in the result pattern and
+ // the instructions require a common register class, but don't care about
+ // what actual MVT is used. This is actually a bug in our modelling:
+ // output patterns should have register classes, not MVTs.
+ //
+ // In any case, to handle this, we just go through and disambiguate some
+ // arbitrary types to the result pattern's nodes.
+ if (!IterateInference && InferredAllPatternTypes &&
+ !InferredAllResultTypes)
+ IterateInference =
+ ForceArbitraryInstResultType(Result.getTree(0), Result);
+ } while (IterateInference);
+
+ // Verify that we inferred enough types that we can do something with the
+ // pattern and result. If these fire the user has to add type casts.
+ if (!InferredAllPatternTypes)
+ Pattern->error("Could not infer all types in pattern!");
+ if (!InferredAllResultTypes) {
+ Pattern->dump();
+ Result.error("Could not infer all types in pattern result!");
+ }
+
+ // Validate that the input pattern is correct.
+ std::map<std::string, TreePatternNode*> InstInputs;
+ std::map<std::string, TreePatternNode*> InstResults;
+ std::vector<Record*> InstImpResults;
+ for (unsigned j = 0, ee = Pattern->getNumTrees(); j != ee; ++j)
+ FindPatternInputsAndOutputs(Pattern, Pattern->getTree(j),
+ InstInputs, InstResults,
+ InstImpResults);
+
+ // Promote the xform function to be an explicit node if set.
+ TreePatternNode *DstPattern = Result.getOnlyTree();
+ std::vector<TreePatternNode*> ResultNodeOperands;
+ for (unsigned ii = 0, ee = DstPattern->getNumChildren(); ii != ee; ++ii) {
+ TreePatternNode *OpNode = DstPattern->getChild(ii);
+ if (Record *Xform = OpNode->getTransformFn()) {
+ OpNode->setTransformFn(nullptr);
+ std::vector<TreePatternNode*> Children;
+ Children.push_back(OpNode);
+ OpNode = new TreePatternNode(Xform, Children, OpNode->getNumTypes());
+ }
+ ResultNodeOperands.push_back(OpNode);
+ }
+ DstPattern = Result.getOnlyTree();
+ if (!DstPattern->isLeaf())
+ DstPattern = new TreePatternNode(DstPattern->getOperator(),
+ ResultNodeOperands,
+ DstPattern->getNumTypes());
+
+ for (unsigned i = 0, e = Result.getOnlyTree()->getNumTypes(); i != e; ++i)
+ DstPattern->setType(i, Result.getOnlyTree()->getExtType(i));
+
+ TreePattern Temp(Result.getRecord(), DstPattern, false, *this);
+ Temp.InferAllTypes();
+
+
+ AddPatternToMatch(Pattern,
+ PatternToMatch(CurPattern,
+ CurPattern->getValueAsListInit("Predicates"),
+ Pattern->getTree(0),
+ Temp.getOnlyTree(), InstImpResults,
+ CurPattern->getValueAsInt("AddedComplexity"),
+ CurPattern->getID()));
+ }
+}
+
+/// CombineChildVariants - Given a bunch of permutations of each child of the
+/// 'operator' node, put them together in all possible ways.
+static void CombineChildVariants(TreePatternNode *Orig,
+ const std::vector<std::vector<TreePatternNode*> > &ChildVariants,
+ std::vector<TreePatternNode*> &OutVariants,
+ CodeGenDAGPatterns &CDP,
+ const MultipleUseVarSet &DepVars) {
+ // Make sure that each operand has at least one variant to choose from.
+ for (const auto &Variants : ChildVariants)
+ if (Variants.empty())
+ return;
+
+ // The end result is an all-pairs construction of the resultant pattern.
+ std::vector<unsigned> Idxs;
+ Idxs.resize(ChildVariants.size());
+ bool NotDone;
+ do {
+#ifndef NDEBUG
+ DEBUG(if (!Idxs.empty()) {
+ errs() << Orig->getOperator()->getName() << ": Idxs = [ ";
+ for (unsigned Idx : Idxs) {
+ errs() << Idx << " ";
+ }
+ errs() << "]\n";
+ });
+#endif
+ // Create the variant and add it to the output list.
+ std::vector<TreePatternNode*> NewChildren;
+ for (unsigned i = 0, e = ChildVariants.size(); i != e; ++i)
+ NewChildren.push_back(ChildVariants[i][Idxs[i]]);
+ auto R = llvm::make_unique<TreePatternNode>(
+ Orig->getOperator(), NewChildren, Orig->getNumTypes());
+
+ // Copy over properties.
+ R->setName(Orig->getName());
+ R->setPredicateFns(Orig->getPredicateFns());
+ R->setTransformFn(Orig->getTransformFn());
+ for (unsigned i = 0, e = Orig->getNumTypes(); i != e; ++i)
+ R->setType(i, Orig->getExtType(i));
+
+ // If this pattern cannot match, do not include it as a variant.
+ std::string ErrString;
+ // Scan to see if this pattern has already been emitted. We can get
+ // duplication due to things like commuting:
+ // (and GPRC:$a, GPRC:$b) -> (and GPRC:$b, GPRC:$a)
+ // which are the same pattern. Ignore the dups.
+ if (R->canPatternMatch(ErrString, CDP) &&
+ none_of(OutVariants, [&](TreePatternNode *Variant) {
+ return R->isIsomorphicTo(Variant, DepVars);
+ }))
+ OutVariants.push_back(R.release());
+
+ // Increment indices to the next permutation by incrementing the
+ // indices from last index backward, e.g., generate the sequence
+ // [0, 0], [0, 1], [1, 0], [1, 1].
+ int IdxsIdx;
+ for (IdxsIdx = Idxs.size() - 1; IdxsIdx >= 0; --IdxsIdx) {
+ if (++Idxs[IdxsIdx] == ChildVariants[IdxsIdx].size())
+ Idxs[IdxsIdx] = 0;
+ else
+ break;
+ }
+ NotDone = (IdxsIdx >= 0);
+ } while (NotDone);
+}
+
+/// CombineChildVariants - A helper function for binary operators.
+///
+static void CombineChildVariants(TreePatternNode *Orig,
+ const std::vector<TreePatternNode*> &LHS,
+ const std::vector<TreePatternNode*> &RHS,
+ std::vector<TreePatternNode*> &OutVariants,
+ CodeGenDAGPatterns &CDP,
+ const MultipleUseVarSet &DepVars) {
+ std::vector<std::vector<TreePatternNode*> > ChildVariants;
+ ChildVariants.push_back(LHS);
+ ChildVariants.push_back(RHS);
+ CombineChildVariants(Orig, ChildVariants, OutVariants, CDP, DepVars);
+}
+
+
+static void GatherChildrenOfAssociativeOpcode(TreePatternNode *N,
+ std::vector<TreePatternNode *> &Children) {
+ assert(N->getNumChildren()==2 &&"Associative but doesn't have 2 children!");
+ Record *Operator = N->getOperator();
+
+ // Only permit raw nodes.
+ if (!N->getName().empty() || !N->getPredicateFns().empty() ||
+ N->getTransformFn()) {
+ Children.push_back(N);
+ return;
+ }
+
+ if (N->getChild(0)->isLeaf() || N->getChild(0)->getOperator() != Operator)
+ Children.push_back(N->getChild(0));
+ else
+ GatherChildrenOfAssociativeOpcode(N->getChild(0), Children);
+
+ if (N->getChild(1)->isLeaf() || N->getChild(1)->getOperator() != Operator)
+ Children.push_back(N->getChild(1));
+ else
+ GatherChildrenOfAssociativeOpcode(N->getChild(1), Children);
+}
+
+/// GenerateVariantsOf - Given a pattern N, generate all permutations we can of
+/// the (potentially recursive) pattern by using algebraic laws.
+///
+static void GenerateVariantsOf(TreePatternNode *N,
+ std::vector<TreePatternNode*> &OutVariants,
+ CodeGenDAGPatterns &CDP,
+ const MultipleUseVarSet &DepVars) {
+ // We cannot permute leaves or ComplexPattern uses.
+ if (N->isLeaf() || N->getOperator()->isSubClassOf("ComplexPattern")) {
+ OutVariants.push_back(N);
+ return;
+ }
+
+ // Look up interesting info about the node.
+ const SDNodeInfo &NodeInfo = CDP.getSDNodeInfo(N->getOperator());
+
+ // If this node is associative, re-associate.
+ if (NodeInfo.hasProperty(SDNPAssociative)) {
+ // Re-associate by pulling together all of the linked operators
+ std::vector<TreePatternNode*> MaximalChildren;
+ GatherChildrenOfAssociativeOpcode(N, MaximalChildren);
+
+ // Only handle child sizes of 3. Otherwise we'll end up trying too many
+ // permutations.
+ if (MaximalChildren.size() == 3) {
+ // Find the variants of all of our maximal children.
+ std::vector<TreePatternNode*> AVariants, BVariants, CVariants;
+ GenerateVariantsOf(MaximalChildren[0], AVariants, CDP, DepVars);
+ GenerateVariantsOf(MaximalChildren[1], BVariants, CDP, DepVars);
+ GenerateVariantsOf(MaximalChildren[2], CVariants, CDP, DepVars);
+
+ // There are only two ways we can permute the tree:
+ // (A op B) op C and A op (B op C)
+ // Within these forms, we can also permute A/B/C.
+
+ // Generate legal pair permutations of A/B/C.
+ std::vector<TreePatternNode*> ABVariants;
+ std::vector<TreePatternNode*> BAVariants;
+ std::vector<TreePatternNode*> ACVariants;
+ std::vector<TreePatternNode*> CAVariants;
+ std::vector<TreePatternNode*> BCVariants;
+ std::vector<TreePatternNode*> CBVariants;
+ CombineChildVariants(N, AVariants, BVariants, ABVariants, CDP, DepVars);
+ CombineChildVariants(N, BVariants, AVariants, BAVariants, CDP, DepVars);
+ CombineChildVariants(N, AVariants, CVariants, ACVariants, CDP, DepVars);
+ CombineChildVariants(N, CVariants, AVariants, CAVariants, CDP, DepVars);
+ CombineChildVariants(N, BVariants, CVariants, BCVariants, CDP, DepVars);
+ CombineChildVariants(N, CVariants, BVariants, CBVariants, CDP, DepVars);
+
+ // Combine those into the result: (x op x) op x
+ CombineChildVariants(N, ABVariants, CVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, BAVariants, CVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, ACVariants, BVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, CAVariants, BVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, BCVariants, AVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, CBVariants, AVariants, OutVariants, CDP, DepVars);
+
+ // Combine those into the result: x op (x op x)
+ CombineChildVariants(N, CVariants, ABVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, CVariants, BAVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, BVariants, ACVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, BVariants, CAVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, AVariants, BCVariants, OutVariants, CDP, DepVars);
+ CombineChildVariants(N, AVariants, CBVariants, OutVariants, CDP, DepVars);
+ return;
+ }
+ }
+
+ // Compute permutations of all children.
+ std::vector<std::vector<TreePatternNode*> > ChildVariants;
+ ChildVariants.resize(N->getNumChildren());
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ GenerateVariantsOf(N->getChild(i), ChildVariants[i], CDP, DepVars);
+
+ // Build all permutations based on how the children were formed.
+ CombineChildVariants(N, ChildVariants, OutVariants, CDP, DepVars);
+
+ // If this node is commutative, consider the commuted order.
+ bool isCommIntrinsic = N->isCommutativeIntrinsic(CDP);
+ if (NodeInfo.hasProperty(SDNPCommutative) || isCommIntrinsic) {
+ assert((N->getNumChildren()==2 || isCommIntrinsic) &&
+ "Commutative but doesn't have 2 children!");
+ // Don't count children which are actually register references.
+ unsigned NC = 0;
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Child = N->getChild(i);
+ if (Child->isLeaf())
+ if (DefInit *DI = dyn_cast<DefInit>(Child->getLeafValue())) {
+ Record *RR = DI->getDef();
+ if (RR->isSubClassOf("Register"))
+ continue;
+ }
+ NC++;
+ }
+ // Consider the commuted order.
+ if (isCommIntrinsic) {
+ // Commutative intrinsic. First operand is the intrinsic id, 2nd and 3rd
+ // operands are the commutative operands, and there might be more operands
+ // after those.
+ assert(NC >= 3 &&
+ "Commutative intrinsic should have at least 3 children!");
+ std::vector<std::vector<TreePatternNode*> > Variants;
+ Variants.push_back(ChildVariants[0]); // Intrinsic id.
+ Variants.push_back(ChildVariants[2]);
+ Variants.push_back(ChildVariants[1]);
+ for (unsigned i = 3; i != NC; ++i)
+ Variants.push_back(ChildVariants[i]);
+ CombineChildVariants(N, Variants, OutVariants, CDP, DepVars);
+ } else if (NC == 2)
+ CombineChildVariants(N, ChildVariants[1], ChildVariants[0],
+ OutVariants, CDP, DepVars);
+ }
+}
+
+
+// GenerateVariants - Generate variants. For example, commutative patterns can
+// match multiple ways. Add them to PatternsToMatch as well.
+void CodeGenDAGPatterns::GenerateVariants() {
+ DEBUG(errs() << "Generating instruction variants.\n");
+
+ // Loop over all of the patterns we've collected, checking to see if we can
+ // generate variants of the instruction, through the exploitation of
+ // identities. This permits the target to provide aggressive matching without
+ // the .td file having to contain tons of variants of instructions.
+ //
+ // Note that this loop adds new patterns to the PatternsToMatch list, but we
+ // intentionally do not reconsider these. Any variants of added patterns have
+ // already been added.
+ //
+ for (unsigned i = 0, e = PatternsToMatch.size(); i != e; ++i) {
+ MultipleUseVarSet DepVars;
+ std::vector<TreePatternNode*> Variants;
+ FindDepVars(PatternsToMatch[i].getSrcPattern(), DepVars);
+ DEBUG(errs() << "Dependent/multiply used variables: ");
+ DEBUG(DumpDepVars(DepVars));
+ DEBUG(errs() << "\n");
+ GenerateVariantsOf(PatternsToMatch[i].getSrcPattern(), Variants, *this,
+ DepVars);
+
+ assert(!Variants.empty() && "Must create at least original variant!");
+ Variants.erase(Variants.begin()); // Remove the original pattern.
+
+ if (Variants.empty()) // No variants for this pattern.
+ continue;
+
+ DEBUG(errs() << "FOUND VARIANTS OF: ";
+ PatternsToMatch[i].getSrcPattern()->dump();
+ errs() << "\n");
+
+ for (unsigned v = 0, e = Variants.size(); v != e; ++v) {
+ TreePatternNode *Variant = Variants[v];
+
+ DEBUG(errs() << " VAR#" << v << ": ";
+ Variant->dump();
+ errs() << "\n");
+
+ // Scan to see if an instruction or explicit pattern already matches this.
+ bool AlreadyExists = false;
+ for (unsigned p = 0, e = PatternsToMatch.size(); p != e; ++p) {
+ // Skip if the top level predicates do not match.
+ if (PatternsToMatch[i].getPredicates() !=
+ PatternsToMatch[p].getPredicates())
+ continue;
+ // Check to see if this variant already exists.
+ if (Variant->isIsomorphicTo(PatternsToMatch[p].getSrcPattern(),
+ DepVars)) {
+ DEBUG(errs() << " *** ALREADY EXISTS, ignoring variant.\n");
+ AlreadyExists = true;
+ break;
+ }
+ }
+ // If we already have it, ignore the variant.
+ if (AlreadyExists) continue;
+
+ // Otherwise, add it to the list of patterns we have.
+ PatternsToMatch.emplace_back(
+ PatternsToMatch[i].getSrcRecord(), PatternsToMatch[i].getPredicates(),
+ Variant, PatternsToMatch[i].getDstPattern(),
+ PatternsToMatch[i].getDstRegs(),
+ PatternsToMatch[i].getAddedComplexity(), Record::getNewUID());
+ }
+
+ DEBUG(errs() << "\n");
+ }
+}
diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
new file mode 100644
index 000000000000..189d6e382ee7
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
@@ -0,0 +1,866 @@
+//===- CodeGenDAGPatterns.h - Read DAG patterns from .td file ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the CodeGenDAGPatterns class, which is used to read and
+// represent the patterns present in a .td file for instructions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H
+#define LLVM_UTILS_TABLEGEN_CODEGENDAGPATTERNS_H
+
+#include "CodeGenIntrinsics.h"
+#include "CodeGenTarget.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <algorithm>
+#include <map>
+#include <set>
+#include <vector>
+
+namespace llvm {
+ class Record;
+ class Init;
+ class ListInit;
+ class DagInit;
+ class SDNodeInfo;
+ class TreePattern;
+ class TreePatternNode;
+ class CodeGenDAGPatterns;
+ class ComplexPattern;
+
+/// EEVT::DAGISelGenValueType - These are some extended forms of
+/// MVT::SimpleValueType that we use as lattice values during type inference.
+/// The existing MVT iAny, fAny and vAny types suffice to represent
+/// arbitrary integer, floating-point, and vector types, so only an unknown
+/// value is needed.
+namespace EEVT {
+ /// TypeSet - This is either empty if it's completely unknown, or holds a set
+ /// of types. It is used during type inference because register classes can
+ /// have multiple possible types and we don't know which one they get until
+ /// type inference is complete.
+ ///
+ /// TypeSet can have three states:
+ /// Vector is empty: The type is completely unknown, it can be any valid
+ /// target type.
+ /// Vector has multiple constrained types: (e.g. v4i32 + v4f32) it is one
+ /// of those types only.
+ /// Vector has one concrete type: The type is completely known.
+ ///
+ class TypeSet {
+ SmallVector<MVT::SimpleValueType, 4> TypeVec;
+ public:
+ TypeSet() {}
+ TypeSet(MVT::SimpleValueType VT, TreePattern &TP);
+ TypeSet(ArrayRef<MVT::SimpleValueType> VTList);
+
+ bool isCompletelyUnknown() const { return TypeVec.empty(); }
+
+ bool isConcrete() const {
+ if (TypeVec.size() != 1) return false;
+ unsigned char T = TypeVec[0]; (void)T;
+ assert(T < MVT::LAST_VALUETYPE || T == MVT::iPTR || T == MVT::iPTRAny);
+ return true;
+ }
+
+ MVT::SimpleValueType getConcrete() const {
+ assert(isConcrete() && "Type isn't concrete yet");
+ return (MVT::SimpleValueType)TypeVec[0];
+ }
+
+ bool isDynamicallyResolved() const {
+ return getConcrete() == MVT::iPTR || getConcrete() == MVT::iPTRAny;
+ }
+
+ const SmallVectorImpl<MVT::SimpleValueType> &getTypeList() const {
+ assert(!TypeVec.empty() && "Not a type list!");
+ return TypeVec;
+ }
+
+ bool isVoid() const {
+ return TypeVec.size() == 1 && TypeVec[0] == MVT::isVoid;
+ }
+
+ /// hasIntegerTypes - Return true if this TypeSet contains any integer value
+ /// types.
+ bool hasIntegerTypes() const;
+
+ /// hasFloatingPointTypes - Return true if this TypeSet contains an fAny or
+ /// a floating point value type.
+ bool hasFloatingPointTypes() const;
+
+ /// hasScalarTypes - Return true if this TypeSet contains a scalar value
+ /// type.
+ bool hasScalarTypes() const;
+
+ /// hasVectorTypes - Return true if this TypeSet contains a vector value
+ /// type.
+ bool hasVectorTypes() const;
+
+ /// getName() - Return this TypeSet as a string.
+ std::string getName() const;
+
+ /// MergeInTypeInfo - This merges in type information from the specified
+ /// argument. If 'this' changes, it returns true. If the two types are
+ /// contradictory (e.g. merge f32 into i32) then this flags an error.
+ bool MergeInTypeInfo(const EEVT::TypeSet &InVT, TreePattern &TP);
+
+ bool MergeInTypeInfo(MVT::SimpleValueType InVT, TreePattern &TP) {
+ return MergeInTypeInfo(EEVT::TypeSet(InVT, TP), TP);
+ }
+
+ /// Force this type list to only contain integer types.
+ bool EnforceInteger(TreePattern &TP);
+
+ /// Force this type list to only contain floating point types.
+ bool EnforceFloatingPoint(TreePattern &TP);
+
+ /// EnforceScalar - Remove all vector types from this type list.
+ bool EnforceScalar(TreePattern &TP);
+
+ /// EnforceVector - Remove all non-vector types from this type list.
+ bool EnforceVector(TreePattern &TP);
+
+ /// EnforceSmallerThan - 'this' must be a smaller VT than Other. Update
+ /// this an other based on this information.
+ bool EnforceSmallerThan(EEVT::TypeSet &Other, TreePattern &TP);
+
+ /// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
+ /// whose element is VT.
+ bool EnforceVectorEltTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
+
+ /// EnforceVectorEltTypeIs - 'this' is now constrained to be a vector type
+ /// whose element is VT.
+ bool EnforceVectorEltTypeIs(MVT::SimpleValueType VT, TreePattern &TP);
+
+ /// EnforceVectorSubVectorTypeIs - 'this' is now constrained to
+ /// be a vector type VT.
+ bool EnforceVectorSubVectorTypeIs(EEVT::TypeSet &VT, TreePattern &TP);
+
+ /// EnforceSameNumElts - If VTOperand is a scalar, then 'this' is a scalar.
+ /// If VTOperand is a vector, then 'this' must have the same number of
+ /// elements.
+ bool EnforceSameNumElts(EEVT::TypeSet &VT, TreePattern &TP);
+
+ /// EnforceSameSize - 'this' is now constrained to be the same size as VT.
+ bool EnforceSameSize(EEVT::TypeSet &VT, TreePattern &TP);
+
+ bool operator!=(const TypeSet &RHS) const { return TypeVec != RHS.TypeVec; }
+ bool operator==(const TypeSet &RHS) const { return TypeVec == RHS.TypeVec; }
+
+ private:
+ /// FillWithPossibleTypes - Set to all legal types and return true, only
+ /// valid on completely unknown type sets. If Pred is non-null, only MVTs
+ /// that pass the predicate are added.
+ bool FillWithPossibleTypes(TreePattern &TP,
+ bool (*Pred)(MVT::SimpleValueType) = nullptr,
+ const char *PredicateName = nullptr);
+ };
+}
+
+/// Set type used to track multiply used variables in patterns
+typedef std::set<std::string> MultipleUseVarSet;
+
+/// SDTypeConstraint - This is a discriminated union of constraints,
+/// corresponding to the SDTypeConstraint tablegen class in Target.td.
+struct SDTypeConstraint {
+ SDTypeConstraint(Record *R);
+
+ unsigned OperandNo; // The operand # this constraint applies to.
+ enum {
+ SDTCisVT, SDTCisPtrTy, SDTCisInt, SDTCisFP, SDTCisVec, SDTCisSameAs,
+ SDTCisVTSmallerThanOp, SDTCisOpSmallerThanOp, SDTCisEltOfVec,
+ SDTCisSubVecOfVec, SDTCVecEltisVT, SDTCisSameNumEltsAs, SDTCisSameSizeAs
+ } ConstraintType;
+
+ union { // The discriminated union.
+ struct {
+ MVT::SimpleValueType VT;
+ } SDTCisVT_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisSameAs_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisVTSmallerThanOp_Info;
+ struct {
+ unsigned BigOperandNum;
+ } SDTCisOpSmallerThanOp_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisEltOfVec_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisSubVecOfVec_Info;
+ struct {
+ MVT::SimpleValueType VT;
+ } SDTCVecEltisVT_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisSameNumEltsAs_Info;
+ struct {
+ unsigned OtherOperandNum;
+ } SDTCisSameSizeAs_Info;
+ } x;
+
+ /// ApplyTypeConstraint - Given a node in a pattern, apply this type
+ /// constraint to the nodes operands. This returns true if it makes a
+ /// change, false otherwise. If a type contradiction is found, an error
+ /// is flagged.
+ bool ApplyTypeConstraint(TreePatternNode *N, const SDNodeInfo &NodeInfo,
+ TreePattern &TP) const;
+};
+
+/// SDNodeInfo - One of these records is created for each SDNode instance in
+/// the target .td file. This represents the various dag nodes we will be
+/// processing.
+class SDNodeInfo {
+ Record *Def;
+ std::string EnumName;
+ std::string SDClassName;
+ unsigned Properties;
+ unsigned NumResults;
+ int NumOperands;
+ std::vector<SDTypeConstraint> TypeConstraints;
+public:
+ SDNodeInfo(Record *R); // Parse the specified record.
+
+ unsigned getNumResults() const { return NumResults; }
+
+ /// getNumOperands - This is the number of operands required or -1 if
+ /// variadic.
+ int getNumOperands() const { return NumOperands; }
+ Record *getRecord() const { return Def; }
+ const std::string &getEnumName() const { return EnumName; }
+ const std::string &getSDClassName() const { return SDClassName; }
+
+ const std::vector<SDTypeConstraint> &getTypeConstraints() const {
+ return TypeConstraints;
+ }
+
+ /// getKnownType - If the type constraints on this node imply a fixed type
+ /// (e.g. all stores return void, etc), then return it as an
+ /// MVT::SimpleValueType. Otherwise, return MVT::Other.
+ MVT::SimpleValueType getKnownType(unsigned ResNo) const;
+
+ /// hasProperty - Return true if this node has the specified property.
+ ///
+ bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
+
+ /// ApplyTypeConstraints - Given a node in a pattern, apply the type
+ /// constraints for this node to the operands of the node. This returns
+ /// true if it makes a change, false otherwise. If a type contradiction is
+ /// found, an error is flagged.
+ bool ApplyTypeConstraints(TreePatternNode *N, TreePattern &TP) const {
+ bool MadeChange = false;
+ for (unsigned i = 0, e = TypeConstraints.size(); i != e; ++i)
+ MadeChange |= TypeConstraints[i].ApplyTypeConstraint(N, *this, TP);
+ return MadeChange;
+ }
+};
+
+/// TreePredicateFn - This is an abstraction that represents the predicates on
+/// a PatFrag node. This is a simple one-word wrapper around a pointer to
+/// provide nice accessors.
+class TreePredicateFn {
+ /// PatFragRec - This is the TreePattern for the PatFrag that we
+ /// originally came from.
+ TreePattern *PatFragRec;
+public:
+ /// TreePredicateFn constructor. Here 'N' is a subclass of PatFrag.
+ TreePredicateFn(TreePattern *N);
+
+
+ TreePattern *getOrigPatFragRecord() const { return PatFragRec; }
+
+ /// isAlwaysTrue - Return true if this is a noop predicate.
+ bool isAlwaysTrue() const;
+
+ bool isImmediatePattern() const { return !getImmCode().empty(); }
+
+ /// getImmediatePredicateCode - Return the code that evaluates this pattern if
+ /// this is an immediate predicate. It is an error to call this on a
+ /// non-immediate pattern.
+ std::string getImmediatePredicateCode() const {
+ std::string Result = getImmCode();
+ assert(!Result.empty() && "Isn't an immediate pattern!");
+ return Result;
+ }
+
+
+ bool operator==(const TreePredicateFn &RHS) const {
+ return PatFragRec == RHS.PatFragRec;
+ }
+
+ bool operator!=(const TreePredicateFn &RHS) const { return !(*this == RHS); }
+
+ /// Return the name to use in the generated code to reference this, this is
+ /// "Predicate_foo" if from a pattern fragment "foo".
+ std::string getFnName() const;
+
+ /// getCodeToRunOnSDNode - Return the code for the function body that
+ /// evaluates this predicate. The argument is expected to be in "Node",
+ /// not N. This handles casting and conversion to a concrete node type as
+ /// appropriate.
+ std::string getCodeToRunOnSDNode() const;
+
+private:
+ std::string getPredCode() const;
+ std::string getImmCode() const;
+};
+
+
+/// FIXME: TreePatternNode's can be shared in some cases (due to dag-shaped
+/// patterns), and as such should be ref counted. We currently just leak all
+/// TreePatternNode objects!
+class TreePatternNode {
+ /// The type of each node result. Before and during type inference, each
+ /// result may be a set of possible types. After (successful) type inference,
+ /// each is a single concrete type.
+ SmallVector<EEVT::TypeSet, 1> Types;
+
+ /// Operator - The Record for the operator if this is an interior node (not
+ /// a leaf).
+ Record *Operator;
+
+ /// Val - The init value (e.g. the "GPRC" record, or "7") for a leaf.
+ ///
+ Init *Val;
+
+ /// Name - The name given to this node with the :$foo notation.
+ ///
+ std::string Name;
+
+ /// PredicateFns - The predicate functions to execute on this node to check
+ /// for a match. If this list is empty, no predicate is involved.
+ std::vector<TreePredicateFn> PredicateFns;
+
+ /// TransformFn - The transformation function to execute on this node before
+ /// it can be substituted into the resulting instruction on a pattern match.
+ Record *TransformFn;
+
+ std::vector<TreePatternNode*> Children;
+public:
+ TreePatternNode(Record *Op, const std::vector<TreePatternNode*> &Ch,
+ unsigned NumResults)
+ : Operator(Op), Val(nullptr), TransformFn(nullptr), Children(Ch) {
+ Types.resize(NumResults);
+ }
+ TreePatternNode(Init *val, unsigned NumResults) // leaf ctor
+ : Operator(nullptr), Val(val), TransformFn(nullptr) {
+ Types.resize(NumResults);
+ }
+ ~TreePatternNode();
+
+ bool hasName() const { return !Name.empty(); }
+ const std::string &getName() const { return Name; }
+ void setName(StringRef N) { Name.assign(N.begin(), N.end()); }
+
+ bool isLeaf() const { return Val != nullptr; }
+
+ // Type accessors.
+ unsigned getNumTypes() const { return Types.size(); }
+ MVT::SimpleValueType getType(unsigned ResNo) const {
+ return Types[ResNo].getConcrete();
+ }
+ const SmallVectorImpl<EEVT::TypeSet> &getExtTypes() const { return Types; }
+ const EEVT::TypeSet &getExtType(unsigned ResNo) const { return Types[ResNo]; }
+ EEVT::TypeSet &getExtType(unsigned ResNo) { return Types[ResNo]; }
+ void setType(unsigned ResNo, const EEVT::TypeSet &T) { Types[ResNo] = T; }
+
+ bool hasTypeSet(unsigned ResNo) const {
+ return Types[ResNo].isConcrete();
+ }
+ bool isTypeCompletelyUnknown(unsigned ResNo) const {
+ return Types[ResNo].isCompletelyUnknown();
+ }
+ bool isTypeDynamicallyResolved(unsigned ResNo) const {
+ return Types[ResNo].isDynamicallyResolved();
+ }
+
+ Init *getLeafValue() const { assert(isLeaf()); return Val; }
+ Record *getOperator() const { assert(!isLeaf()); return Operator; }
+
+ unsigned getNumChildren() const { return Children.size(); }
+ TreePatternNode *getChild(unsigned N) const { return Children[N]; }
+ void setChild(unsigned i, TreePatternNode *N) {
+ Children[i] = N;
+ }
+
+ /// hasChild - Return true if N is any of our children.
+ bool hasChild(const TreePatternNode *N) const {
+ for (unsigned i = 0, e = Children.size(); i != e; ++i)
+ if (Children[i] == N) return true;
+ return false;
+ }
+
+ bool hasAnyPredicate() const { return !PredicateFns.empty(); }
+
+ const std::vector<TreePredicateFn> &getPredicateFns() const {
+ return PredicateFns;
+ }
+ void clearPredicateFns() { PredicateFns.clear(); }
+ void setPredicateFns(const std::vector<TreePredicateFn> &Fns) {
+ assert(PredicateFns.empty() && "Overwriting non-empty predicate list!");
+ PredicateFns = Fns;
+ }
+ void addPredicateFn(const TreePredicateFn &Fn) {
+ assert(!Fn.isAlwaysTrue() && "Empty predicate string!");
+ if (!is_contained(PredicateFns, Fn))
+ PredicateFns.push_back(Fn);
+ }
+
+ Record *getTransformFn() const { return TransformFn; }
+ void setTransformFn(Record *Fn) { TransformFn = Fn; }
+
+ /// getIntrinsicInfo - If this node corresponds to an intrinsic, return the
+ /// CodeGenIntrinsic information for it, otherwise return a null pointer.
+ const CodeGenIntrinsic *getIntrinsicInfo(const CodeGenDAGPatterns &CDP) const;
+
+ /// getComplexPatternInfo - If this node corresponds to a ComplexPattern,
+ /// return the ComplexPattern information, otherwise return null.
+ const ComplexPattern *
+ getComplexPatternInfo(const CodeGenDAGPatterns &CGP) const;
+
+ /// Returns the number of MachineInstr operands that would be produced by this
+ /// node if it mapped directly to an output Instruction's
+ /// operand. ComplexPattern specifies this explicitly; MIOperandInfo gives it
+ /// for Operands; otherwise 1.
+ unsigned getNumMIResults(const CodeGenDAGPatterns &CGP) const;
+
+ /// NodeHasProperty - Return true if this node has the specified property.
+ bool NodeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
+
+ /// TreeHasProperty - Return true if any node in this tree has the specified
+ /// property.
+ bool TreeHasProperty(SDNP Property, const CodeGenDAGPatterns &CGP) const;
+
+ /// isCommutativeIntrinsic - Return true if the node is an intrinsic which is
+ /// marked isCommutative.
+ bool isCommutativeIntrinsic(const CodeGenDAGPatterns &CDP) const;
+
+ void print(raw_ostream &OS) const;
+ void dump() const;
+
+public: // Higher level manipulation routines.
+
+ /// clone - Return a new copy of this tree.
+ ///
+ TreePatternNode *clone() const;
+
+ /// RemoveAllTypes - Recursively strip all the types of this tree.
+ void RemoveAllTypes();
+
+ /// isIsomorphicTo - Return true if this node is recursively isomorphic to
+ /// the specified node. For this comparison, all of the state of the node
+ /// is considered, except for the assigned name. Nodes with differing names
+ /// that are otherwise identical are considered isomorphic.
+ bool isIsomorphicTo(const TreePatternNode *N,
+ const MultipleUseVarSet &DepVars) const;
+
+ /// SubstituteFormalArguments - Replace the formal arguments in this tree
+ /// with actual values specified by ArgMap.
+ void SubstituteFormalArguments(std::map<std::string,
+ TreePatternNode*> &ArgMap);
+
+ /// InlinePatternFragments - If this pattern refers to any pattern
+ /// fragments, inline them into place, giving us a pattern without any
+ /// PatFrag references.
+ TreePatternNode *InlinePatternFragments(TreePattern &TP);
+
+ /// ApplyTypeConstraints - Apply all of the type constraints relevant to
+ /// this node and its children in the tree. This returns true if it makes a
+ /// change, false otherwise. If a type contradiction is found, flag an error.
+ bool ApplyTypeConstraints(TreePattern &TP, bool NotRegisters);
+
+ /// UpdateNodeType - Set the node type of N to VT if VT contains
+ /// information. If N already contains a conflicting type, then flag an
+ /// error. This returns true if any information was updated.
+ ///
+ bool UpdateNodeType(unsigned ResNo, const EEVT::TypeSet &InTy,
+ TreePattern &TP) {
+ return Types[ResNo].MergeInTypeInfo(InTy, TP);
+ }
+
+ bool UpdateNodeType(unsigned ResNo, MVT::SimpleValueType InTy,
+ TreePattern &TP) {
+ return Types[ResNo].MergeInTypeInfo(EEVT::TypeSet(InTy, TP), TP);
+ }
+
+ // Update node type with types inferred from an instruction operand or result
+ // def from the ins/outs lists.
+ // Return true if the type changed.
+ bool UpdateNodeTypeFromInst(unsigned ResNo, Record *Operand, TreePattern &TP);
+
+ /// ContainsUnresolvedType - Return true if this tree contains any
+ /// unresolved types.
+ bool ContainsUnresolvedType() const {
+ for (unsigned i = 0, e = Types.size(); i != e; ++i)
+ if (!Types[i].isConcrete()) return true;
+
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
+ if (getChild(i)->ContainsUnresolvedType()) return true;
+ return false;
+ }
+
+ /// canPatternMatch - If it is impossible for this pattern to match on this
+ /// target, fill in Reason and return false. Otherwise, return true.
+ bool canPatternMatch(std::string &Reason, const CodeGenDAGPatterns &CDP);
+};
+
+inline raw_ostream &operator<<(raw_ostream &OS, const TreePatternNode &TPN) {
+ TPN.print(OS);
+ return OS;
+}
+
+
+/// TreePattern - Represent a pattern, used for instructions, pattern
+/// fragments, etc.
+///
+class TreePattern {
+ /// Trees - The list of pattern trees which corresponds to this pattern.
+ /// Note that PatFrag's only have a single tree.
+ ///
+ std::vector<TreePatternNode*> Trees;
+
+ /// NamedNodes - This is all of the nodes that have names in the trees in this
+ /// pattern.
+ StringMap<SmallVector<TreePatternNode*,1> > NamedNodes;
+
+ /// TheRecord - The actual TableGen record corresponding to this pattern.
+ ///
+ Record *TheRecord;
+
+ /// Args - This is a list of all of the arguments to this pattern (for
+ /// PatFrag patterns), which are the 'node' markers in this pattern.
+ std::vector<std::string> Args;
+
+ /// CDP - the top-level object coordinating this madness.
+ ///
+ CodeGenDAGPatterns &CDP;
+
+ /// isInputPattern - True if this is an input pattern, something to match.
+ /// False if this is an output pattern, something to emit.
+ bool isInputPattern;
+
+ /// hasError - True if the currently processed nodes have unresolvable types
+ /// or other non-fatal errors
+ bool HasError;
+
+ /// It's important that the usage of operands in ComplexPatterns is
+ /// consistent: each named operand can be defined by at most one
+ /// ComplexPattern. This records the ComplexPattern instance and the operand
+ /// number for each operand encountered in a ComplexPattern to aid in that
+ /// check.
+ StringMap<std::pair<Record *, unsigned>> ComplexPatternOperands;
+public:
+
+ /// TreePattern constructor - Parse the specified DagInits into the
+ /// current record.
+ TreePattern(Record *TheRec, ListInit *RawPat, bool isInput,
+ CodeGenDAGPatterns &ise);
+ TreePattern(Record *TheRec, DagInit *Pat, bool isInput,
+ CodeGenDAGPatterns &ise);
+ TreePattern(Record *TheRec, TreePatternNode *Pat, bool isInput,
+ CodeGenDAGPatterns &ise);
+
+ /// getTrees - Return the tree patterns which corresponds to this pattern.
+ ///
+ const std::vector<TreePatternNode*> &getTrees() const { return Trees; }
+ unsigned getNumTrees() const { return Trees.size(); }
+ TreePatternNode *getTree(unsigned i) const { return Trees[i]; }
+ TreePatternNode *getOnlyTree() const {
+ assert(Trees.size() == 1 && "Doesn't have exactly one pattern!");
+ return Trees[0];
+ }
+
+ const StringMap<SmallVector<TreePatternNode*,1> > &getNamedNodesMap() {
+ if (NamedNodes.empty())
+ ComputeNamedNodes();
+ return NamedNodes;
+ }
+
+ /// getRecord - Return the actual TableGen record corresponding to this
+ /// pattern.
+ ///
+ Record *getRecord() const { return TheRecord; }
+
+ unsigned getNumArgs() const { return Args.size(); }
+ const std::string &getArgName(unsigned i) const {
+ assert(i < Args.size() && "Argument reference out of range!");
+ return Args[i];
+ }
+ std::vector<std::string> &getArgList() { return Args; }
+
+ CodeGenDAGPatterns &getDAGPatterns() const { return CDP; }
+
+ /// InlinePatternFragments - If this pattern refers to any pattern
+ /// fragments, inline them into place, giving us a pattern without any
+ /// PatFrag references.
+ void InlinePatternFragments() {
+ for (unsigned i = 0, e = Trees.size(); i != e; ++i)
+ Trees[i] = Trees[i]->InlinePatternFragments(*this);
+ }
+
+ /// InferAllTypes - Infer/propagate as many types throughout the expression
+ /// patterns as possible. Return true if all types are inferred, false
+ /// otherwise. Bail out if a type contradiction is found.
+ bool InferAllTypes(const StringMap<SmallVector<TreePatternNode*,1> >
+ *NamedTypes=nullptr);
+
+ /// error - If this is the first error in the current resolution step,
+ /// print it and set the error flag. Otherwise, continue silently.
+ void error(const Twine &Msg);
+ bool hasError() const {
+ return HasError;
+ }
+ void resetError() {
+ HasError = false;
+ }
+
+ void print(raw_ostream &OS) const;
+ void dump() const;
+
+private:
+ TreePatternNode *ParseTreePattern(Init *DI, StringRef OpName);
+ void ComputeNamedNodes();
+ void ComputeNamedNodes(TreePatternNode *N);
+};
+
+/// DAGDefaultOperand - One of these is created for each OperandWithDefaultOps
+/// that has a set ExecuteAlways / DefaultOps field.
+struct DAGDefaultOperand {
+ std::vector<TreePatternNode*> DefaultOps;
+};
+
+class DAGInstruction {
+ TreePattern *Pattern;
+ std::vector<Record*> Results;
+ std::vector<Record*> Operands;
+ std::vector<Record*> ImpResults;
+ TreePatternNode *ResultPattern;
+public:
+ DAGInstruction(TreePattern *TP,
+ const std::vector<Record*> &results,
+ const std::vector<Record*> &operands,
+ const std::vector<Record*> &impresults)
+ : Pattern(TP), Results(results), Operands(operands),
+ ImpResults(impresults), ResultPattern(nullptr) {}
+
+ TreePattern *getPattern() const { return Pattern; }
+ unsigned getNumResults() const { return Results.size(); }
+ unsigned getNumOperands() const { return Operands.size(); }
+ unsigned getNumImpResults() const { return ImpResults.size(); }
+ const std::vector<Record*>& getImpResults() const { return ImpResults; }
+
+ void setResultPattern(TreePatternNode *R) { ResultPattern = R; }
+
+ Record *getResult(unsigned RN) const {
+ assert(RN < Results.size());
+ return Results[RN];
+ }
+
+ Record *getOperand(unsigned ON) const {
+ assert(ON < Operands.size());
+ return Operands[ON];
+ }
+
+ Record *getImpResult(unsigned RN) const {
+ assert(RN < ImpResults.size());
+ return ImpResults[RN];
+ }
+
+ TreePatternNode *getResultPattern() const { return ResultPattern; }
+};
+
+/// PatternToMatch - Used by CodeGenDAGPatterns to keep tab of patterns
+/// processed to produce isel.
+class PatternToMatch {
+public:
+ PatternToMatch(Record *srcrecord, ListInit *preds,
+ TreePatternNode *src, TreePatternNode *dst,
+ const std::vector<Record*> &dstregs,
+ int complexity, unsigned uid)
+ : SrcRecord(srcrecord), Predicates(preds), SrcPattern(src), DstPattern(dst),
+ Dstregs(dstregs), AddedComplexity(complexity), ID(uid) {}
+
+ Record *SrcRecord; // Originating Record for the pattern.
+ ListInit *Predicates; // Top level predicate conditions to match.
+ TreePatternNode *SrcPattern; // Source pattern to match.
+ TreePatternNode *DstPattern; // Resulting pattern.
+ std::vector<Record*> Dstregs; // Physical register defs being matched.
+ int AddedComplexity; // Add to matching pattern complexity.
+ unsigned ID; // Unique ID for the record.
+
+ Record *getSrcRecord() const { return SrcRecord; }
+ ListInit *getPredicates() const { return Predicates; }
+ TreePatternNode *getSrcPattern() const { return SrcPattern; }
+ TreePatternNode *getDstPattern() const { return DstPattern; }
+ const std::vector<Record*> &getDstRegs() const { return Dstregs; }
+ int getAddedComplexity() const { return AddedComplexity; }
+
+ std::string getPredicateCheck() const;
+
+ /// Compute the complexity metric for the input pattern. This roughly
+ /// corresponds to the number of nodes that are covered.
+ int getPatternComplexity(const CodeGenDAGPatterns &CGP) const;
+};
+
+class CodeGenDAGPatterns {
+ RecordKeeper &Records;
+ CodeGenTarget Target;
+ CodeGenIntrinsicTable Intrinsics;
+ CodeGenIntrinsicTable TgtIntrinsics;
+
+ std::map<Record*, SDNodeInfo, LessRecordByID> SDNodes;
+ std::map<Record*, std::pair<Record*, std::string>, LessRecordByID> SDNodeXForms;
+ std::map<Record*, ComplexPattern, LessRecordByID> ComplexPatterns;
+ std::map<Record *, std::unique_ptr<TreePattern>, LessRecordByID>
+ PatternFragments;
+ std::map<Record*, DAGDefaultOperand, LessRecordByID> DefaultOperands;
+ std::map<Record*, DAGInstruction, LessRecordByID> Instructions;
+
+ // Specific SDNode definitions:
+ Record *intrinsic_void_sdnode;
+ Record *intrinsic_w_chain_sdnode, *intrinsic_wo_chain_sdnode;
+
+ /// PatternsToMatch - All of the things we are matching on the DAG. The first
+ /// value is the pattern to match, the second pattern is the result to
+ /// emit.
+ std::vector<PatternToMatch> PatternsToMatch;
+public:
+ CodeGenDAGPatterns(RecordKeeper &R);
+
+ CodeGenTarget &getTargetInfo() { return Target; }
+ const CodeGenTarget &getTargetInfo() const { return Target; }
+
+ Record *getSDNodeNamed(const std::string &Name) const;
+
+ const SDNodeInfo &getSDNodeInfo(Record *R) const {
+ assert(SDNodes.count(R) && "Unknown node!");
+ return SDNodes.find(R)->second;
+ }
+
+ // Node transformation lookups.
+ typedef std::pair<Record*, std::string> NodeXForm;
+ const NodeXForm &getSDNodeTransform(Record *R) const {
+ assert(SDNodeXForms.count(R) && "Invalid transform!");
+ return SDNodeXForms.find(R)->second;
+ }
+
+ typedef std::map<Record*, NodeXForm, LessRecordByID>::const_iterator
+ nx_iterator;
+ nx_iterator nx_begin() const { return SDNodeXForms.begin(); }
+ nx_iterator nx_end() const { return SDNodeXForms.end(); }
+
+
+ const ComplexPattern &getComplexPattern(Record *R) const {
+ assert(ComplexPatterns.count(R) && "Unknown addressing mode!");
+ return ComplexPatterns.find(R)->second;
+ }
+
+ const CodeGenIntrinsic &getIntrinsic(Record *R) const {
+ for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
+ if (Intrinsics[i].TheDef == R) return Intrinsics[i];
+ for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i)
+ if (TgtIntrinsics[i].TheDef == R) return TgtIntrinsics[i];
+ llvm_unreachable("Unknown intrinsic!");
+ }
+
+ const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const {
+ if (IID-1 < Intrinsics.size())
+ return Intrinsics[IID-1];
+ if (IID-Intrinsics.size()-1 < TgtIntrinsics.size())
+ return TgtIntrinsics[IID-Intrinsics.size()-1];
+ llvm_unreachable("Bad intrinsic ID!");
+ }
+
+ unsigned getIntrinsicID(Record *R) const {
+ for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
+ if (Intrinsics[i].TheDef == R) return i;
+ for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i)
+ if (TgtIntrinsics[i].TheDef == R) return i + Intrinsics.size();
+ llvm_unreachable("Unknown intrinsic!");
+ }
+
+ const DAGDefaultOperand &getDefaultOperand(Record *R) const {
+ assert(DefaultOperands.count(R) &&"Isn't an analyzed default operand!");
+ return DefaultOperands.find(R)->second;
+ }
+
+ // Pattern Fragment information.
+ TreePattern *getPatternFragment(Record *R) const {
+ assert(PatternFragments.count(R) && "Invalid pattern fragment request!");
+ return PatternFragments.find(R)->second.get();
+ }
+ TreePattern *getPatternFragmentIfRead(Record *R) const {
+ if (!PatternFragments.count(R))
+ return nullptr;
+ return PatternFragments.find(R)->second.get();
+ }
+
+ typedef std::map<Record *, std::unique_ptr<TreePattern>,
+ LessRecordByID>::const_iterator pf_iterator;
+ pf_iterator pf_begin() const { return PatternFragments.begin(); }
+ pf_iterator pf_end() const { return PatternFragments.end(); }
+ iterator_range<pf_iterator> ptfs() const { return PatternFragments; }
+
+ // Patterns to match information.
+ typedef std::vector<PatternToMatch>::const_iterator ptm_iterator;
+ ptm_iterator ptm_begin() const { return PatternsToMatch.begin(); }
+ ptm_iterator ptm_end() const { return PatternsToMatch.end(); }
+ iterator_range<ptm_iterator> ptms() const { return PatternsToMatch; }
+
+ /// Parse the Pattern for an instruction, and insert the result in DAGInsts.
+ typedef std::map<Record*, DAGInstruction, LessRecordByID> DAGInstMap;
+ const DAGInstruction &parseInstructionPattern(
+ CodeGenInstruction &CGI, ListInit *Pattern,
+ DAGInstMap &DAGInsts);
+
+ const DAGInstruction &getInstruction(Record *R) const {
+ assert(Instructions.count(R) && "Unknown instruction!");
+ return Instructions.find(R)->second;
+ }
+
+ Record *get_intrinsic_void_sdnode() const {
+ return intrinsic_void_sdnode;
+ }
+ Record *get_intrinsic_w_chain_sdnode() const {
+ return intrinsic_w_chain_sdnode;
+ }
+ Record *get_intrinsic_wo_chain_sdnode() const {
+ return intrinsic_wo_chain_sdnode;
+ }
+
+ bool hasTargetIntrinsics() { return !TgtIntrinsics.empty(); }
+
+private:
+ void ParseNodeInfo();
+ void ParseNodeTransforms();
+ void ParseComplexPatterns();
+ void ParsePatternFragments(bool OutFrags = false);
+ void ParseDefaultOperands();
+ void ParseInstructions();
+ void ParsePatterns();
+ void InferInstructionFlags();
+ void GenerateVariants();
+ void VerifyInstructionFlags();
+
+ void AddPatternToMatch(TreePattern *Pattern, const PatternToMatch &PTM);
+ void FindPatternInputsAndOutputs(TreePattern *I, TreePatternNode *Pat,
+ std::map<std::string,
+ TreePatternNode*> &InstInputs,
+ std::map<std::string,
+ TreePatternNode*> &InstResults,
+ std::vector<Record*> &InstImpResults);
+};
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
new file mode 100644
index 000000000000..bb2ec2a64e49
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -0,0 +1,688 @@
+//===- CodeGenInstruction.cpp - CodeGen Instruction Class Wrapper ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the CodeGenInstruction class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenInstruction.h"
+#include "CodeGenTarget.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include <set>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// CGIOperandList Implementation
+//===----------------------------------------------------------------------===//
+
+CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
+ isPredicable = false;
+ hasOptionalDef = false;
+ isVariadic = false;
+
+ DagInit *OutDI = R->getValueAsDag("OutOperandList");
+
+ if (DefInit *Init = dyn_cast<DefInit>(OutDI->getOperator())) {
+ if (Init->getDef()->getName() != "outs")
+ PrintFatalError(R->getName() + ": invalid def name for output list: use 'outs'");
+ } else
+ PrintFatalError(R->getName() + ": invalid output list: use 'outs'");
+
+ NumDefs = OutDI->getNumArgs();
+
+ DagInit *InDI = R->getValueAsDag("InOperandList");
+ if (DefInit *Init = dyn_cast<DefInit>(InDI->getOperator())) {
+ if (Init->getDef()->getName() != "ins")
+ PrintFatalError(R->getName() + ": invalid def name for input list: use 'ins'");
+ } else
+ PrintFatalError(R->getName() + ": invalid input list: use 'ins'");
+
+ unsigned MIOperandNo = 0;
+ std::set<std::string> OperandNames;
+ unsigned e = InDI->getNumArgs() + OutDI->getNumArgs();
+ OperandList.reserve(e);
+ for (unsigned i = 0; i != e; ++i){
+ Init *ArgInit;
+ StringRef ArgName;
+ if (i < NumDefs) {
+ ArgInit = OutDI->getArg(i);
+ ArgName = OutDI->getArgNameStr(i);
+ } else {
+ ArgInit = InDI->getArg(i-NumDefs);
+ ArgName = InDI->getArgNameStr(i-NumDefs);
+ }
+
+ DefInit *Arg = dyn_cast<DefInit>(ArgInit);
+ if (!Arg)
+ PrintFatalError("Illegal operand for the '" + R->getName() + "' instruction!");
+
+ Record *Rec = Arg->getDef();
+ std::string PrintMethod = "printOperand";
+ std::string EncoderMethod;
+ std::string OperandType = "OPERAND_UNKNOWN";
+ std::string OperandNamespace = "MCOI";
+ unsigned NumOps = 1;
+ DagInit *MIOpInfo = nullptr;
+ if (Rec->isSubClassOf("RegisterOperand")) {
+ PrintMethod = Rec->getValueAsString("PrintMethod");
+ OperandType = Rec->getValueAsString("OperandType");
+ OperandNamespace = Rec->getValueAsString("OperandNamespace");
+ } else if (Rec->isSubClassOf("Operand")) {
+ PrintMethod = Rec->getValueAsString("PrintMethod");
+ OperandType = Rec->getValueAsString("OperandType");
+ OperandNamespace = Rec->getValueAsString("OperandNamespace");
+ // If there is an explicit encoder method, use it.
+ EncoderMethod = Rec->getValueAsString("EncoderMethod");
+ MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
+
+ // Verify that MIOpInfo has an 'ops' root value.
+ if (!isa<DefInit>(MIOpInfo->getOperator()) ||
+ cast<DefInit>(MIOpInfo->getOperator())->getDef()->getName() != "ops")
+ PrintFatalError("Bad value for MIOperandInfo in operand '" + Rec->getName() +
+ "'\n");
+
+ // If we have MIOpInfo, then we have #operands equal to number of entries
+ // in MIOperandInfo.
+ if (unsigned NumArgs = MIOpInfo->getNumArgs())
+ NumOps = NumArgs;
+
+ if (Rec->isSubClassOf("PredicateOp"))
+ isPredicable = true;
+ else if (Rec->isSubClassOf("OptionalDefOperand"))
+ hasOptionalDef = true;
+ } else if (Rec->getName() == "variable_ops") {
+ isVariadic = true;
+ continue;
+ } else if (Rec->isSubClassOf("RegisterClass")) {
+ OperandType = "OPERAND_REGISTER";
+ } else if (!Rec->isSubClassOf("PointerLikeRegClass") &&
+ !Rec->isSubClassOf("unknown_class"))
+ PrintFatalError("Unknown operand class '" + Rec->getName() +
+ "' in '" + R->getName() + "' instruction!");
+
+ // Check that the operand has a name and that it's unique.
+ if (ArgName.empty())
+ PrintFatalError("In instruction '" + R->getName() + "', operand #" +
+ Twine(i) + " has no name!");
+ if (!OperandNames.insert(ArgName).second)
+ PrintFatalError("In instruction '" + R->getName() + "', operand #" +
+ Twine(i) + " has the same name as a previous operand!");
+
+ OperandList.emplace_back(Rec, ArgName, PrintMethod, EncoderMethod,
+ OperandNamespace + "::" + OperandType, MIOperandNo,
+ NumOps, MIOpInfo);
+ MIOperandNo += NumOps;
+ }
+
+
+ // Make sure the constraints list for each operand is large enough to hold
+ // constraint info, even if none is present.
+ for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
+ OperandList[i].Constraints.resize(OperandList[i].MINumOperands);
+}
+
+
+/// getOperandNamed - Return the index of the operand with the specified
+/// non-empty name. If the instruction does not have an operand with the
+/// specified name, abort.
+///
+unsigned CGIOperandList::getOperandNamed(StringRef Name) const {
+ unsigned OpIdx;
+ if (hasOperandNamed(Name, OpIdx)) return OpIdx;
+ PrintFatalError("'" + TheDef->getName() +
+ "' does not have an operand named '$" + Name + "'!");
+}
+
+/// hasOperandNamed - Query whether the instruction has an operand of the
+/// given name. If so, return true and set OpIdx to the index of the
+/// operand. Otherwise, return false.
+bool CGIOperandList::hasOperandNamed(StringRef Name, unsigned &OpIdx) const {
+ assert(!Name.empty() && "Cannot search for operand with no name!");
+ for (unsigned i = 0, e = OperandList.size(); i != e; ++i)
+ if (OperandList[i].Name == Name) {
+ OpIdx = i;
+ return true;
+ }
+ return false;
+}
+
+std::pair<unsigned,unsigned>
+CGIOperandList::ParseOperandName(const std::string &Op, bool AllowWholeOp) {
+ if (Op.empty() || Op[0] != '$')
+ PrintFatalError(TheDef->getName() + ": Illegal operand name: '" + Op + "'");
+
+ std::string OpName = Op.substr(1);
+ std::string SubOpName;
+
+ // Check to see if this is $foo.bar.
+ std::string::size_type DotIdx = OpName.find_first_of('.');
+ if (DotIdx != std::string::npos) {
+ SubOpName = OpName.substr(DotIdx+1);
+ if (SubOpName.empty())
+ PrintFatalError(TheDef->getName() + ": illegal empty suboperand name in '" +Op +"'");
+ OpName = OpName.substr(0, DotIdx);
+ }
+
+ unsigned OpIdx = getOperandNamed(OpName);
+
+ if (SubOpName.empty()) { // If no suboperand name was specified:
+ // If one was needed, throw.
+ if (OperandList[OpIdx].MINumOperands > 1 && !AllowWholeOp &&
+ SubOpName.empty())
+ PrintFatalError(TheDef->getName() + ": Illegal to refer to"
+ " whole operand part of complex operand '" + Op + "'");
+
+ // Otherwise, return the operand.
+ return std::make_pair(OpIdx, 0U);
+ }
+
+ // Find the suboperand number involved.
+ DagInit *MIOpInfo = OperandList[OpIdx].MIOperandInfo;
+ if (!MIOpInfo)
+ PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'");
+
+ // Find the operand with the right name.
+ for (unsigned i = 0, e = MIOpInfo->getNumArgs(); i != e; ++i)
+ if (MIOpInfo->getArgNameStr(i) == SubOpName)
+ return std::make_pair(OpIdx, i);
+
+ // Otherwise, didn't find it!
+ PrintFatalError(TheDef->getName() + ": unknown suboperand name in '" + Op + "'");
+ return std::make_pair(0U, 0U);
+}
+
+static void ParseConstraint(const std::string &CStr, CGIOperandList &Ops) {
+ // EARLY_CLOBBER: @early $reg
+ std::string::size_type wpos = CStr.find_first_of(" \t");
+ std::string::size_type start = CStr.find_first_not_of(" \t");
+ std::string Tok = CStr.substr(start, wpos - start);
+ if (Tok == "@earlyclobber") {
+ std::string Name = CStr.substr(wpos+1);
+ wpos = Name.find_first_not_of(" \t");
+ if (wpos == std::string::npos)
+ PrintFatalError("Illegal format for @earlyclobber constraint: '" + CStr + "'");
+ Name = Name.substr(wpos);
+ std::pair<unsigned,unsigned> Op = Ops.ParseOperandName(Name, false);
+
+ // Build the string for the operand
+ if (!Ops[Op.first].Constraints[Op.second].isNone())
+ PrintFatalError("Operand '" + Name + "' cannot have multiple constraints!");
+ Ops[Op.first].Constraints[Op.second] =
+ CGIOperandList::ConstraintInfo::getEarlyClobber();
+ return;
+ }
+
+ // Only other constraint is "TIED_TO" for now.
+ std::string::size_type pos = CStr.find_first_of('=');
+ assert(pos != std::string::npos && "Unrecognized constraint");
+ start = CStr.find_first_not_of(" \t");
+ std::string Name = CStr.substr(start, pos - start);
+
+ // TIED_TO: $src1 = $dst
+ wpos = Name.find_first_of(" \t");
+ if (wpos == std::string::npos)
+ PrintFatalError("Illegal format for tied-to constraint: '" + CStr + "'");
+ std::string DestOpName = Name.substr(0, wpos);
+ std::pair<unsigned,unsigned> DestOp = Ops.ParseOperandName(DestOpName, false);
+
+ Name = CStr.substr(pos+1);
+ wpos = Name.find_first_not_of(" \t");
+ if (wpos == std::string::npos)
+ PrintFatalError("Illegal format for tied-to constraint: '" + CStr + "'");
+
+ std::string SrcOpName = Name.substr(wpos);
+ std::pair<unsigned,unsigned> SrcOp = Ops.ParseOperandName(SrcOpName, false);
+ if (SrcOp > DestOp) {
+ std::swap(SrcOp, DestOp);
+ std::swap(SrcOpName, DestOpName);
+ }
+
+ unsigned FlatOpNo = Ops.getFlattenedOperandNumber(SrcOp);
+
+ if (!Ops[DestOp.first].Constraints[DestOp.second].isNone())
+ PrintFatalError("Operand '" + DestOpName +
+ "' cannot have multiple constraints!");
+ Ops[DestOp.first].Constraints[DestOp.second] =
+ CGIOperandList::ConstraintInfo::getTied(FlatOpNo);
+}
+
+static void ParseConstraints(const std::string &CStr, CGIOperandList &Ops) {
+ if (CStr.empty()) return;
+
+ const std::string delims(",");
+ std::string::size_type bidx, eidx;
+
+ bidx = CStr.find_first_not_of(delims);
+ while (bidx != std::string::npos) {
+ eidx = CStr.find_first_of(delims, bidx);
+ if (eidx == std::string::npos)
+ eidx = CStr.length();
+
+ ParseConstraint(CStr.substr(bidx, eidx - bidx), Ops);
+ bidx = CStr.find_first_not_of(delims, eidx);
+ }
+}
+
+void CGIOperandList::ProcessDisableEncoding(std::string DisableEncoding) {
+ while (1) {
+ std::pair<StringRef, StringRef> P = getToken(DisableEncoding, " ,\t");
+ std::string OpName = P.first;
+ DisableEncoding = P.second;
+ if (OpName.empty()) break;
+
+ // Figure out which operand this is.
+ std::pair<unsigned,unsigned> Op = ParseOperandName(OpName, false);
+
+ // Mark the operand as not-to-be encoded.
+ if (Op.second >= OperandList[Op.first].DoNotEncode.size())
+ OperandList[Op.first].DoNotEncode.resize(Op.second+1);
+ OperandList[Op.first].DoNotEncode[Op.second] = true;
+ }
+
+}
+
+//===----------------------------------------------------------------------===//
+// CodeGenInstruction Implementation
+//===----------------------------------------------------------------------===//
+
+CodeGenInstruction::CodeGenInstruction(Record *R)
+ : TheDef(R), Operands(R), InferredFrom(nullptr) {
+ Namespace = R->getValueAsString("Namespace");
+ AsmString = R->getValueAsString("AsmString");
+
+ isReturn = R->getValueAsBit("isReturn");
+ isBranch = R->getValueAsBit("isBranch");
+ isIndirectBranch = R->getValueAsBit("isIndirectBranch");
+ isCompare = R->getValueAsBit("isCompare");
+ isMoveImm = R->getValueAsBit("isMoveImm");
+ isBitcast = R->getValueAsBit("isBitcast");
+ isSelect = R->getValueAsBit("isSelect");
+ isBarrier = R->getValueAsBit("isBarrier");
+ isCall = R->getValueAsBit("isCall");
+ isAdd = R->getValueAsBit("isAdd");
+ canFoldAsLoad = R->getValueAsBit("canFoldAsLoad");
+ isPredicable = Operands.isPredicable || R->getValueAsBit("isPredicable");
+ isConvertibleToThreeAddress = R->getValueAsBit("isConvertibleToThreeAddress");
+ isCommutable = R->getValueAsBit("isCommutable");
+ isTerminator = R->getValueAsBit("isTerminator");
+ isReMaterializable = R->getValueAsBit("isReMaterializable");
+ hasDelaySlot = R->getValueAsBit("hasDelaySlot");
+ usesCustomInserter = R->getValueAsBit("usesCustomInserter");
+ hasPostISelHook = R->getValueAsBit("hasPostISelHook");
+ hasCtrlDep = R->getValueAsBit("hasCtrlDep");
+ isNotDuplicable = R->getValueAsBit("isNotDuplicable");
+ isRegSequence = R->getValueAsBit("isRegSequence");
+ isExtractSubreg = R->getValueAsBit("isExtractSubreg");
+ isInsertSubreg = R->getValueAsBit("isInsertSubreg");
+ isConvergent = R->getValueAsBit("isConvergent");
+ hasNoSchedulingInfo = R->getValueAsBit("hasNoSchedulingInfo");
+
+ bool Unset;
+ mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset);
+ mayLoad_Unset = Unset;
+ mayStore = R->getValueAsBitOrUnset("mayStore", Unset);
+ mayStore_Unset = Unset;
+ hasSideEffects = R->getValueAsBitOrUnset("hasSideEffects", Unset);
+ hasSideEffects_Unset = Unset;
+
+ isAsCheapAsAMove = R->getValueAsBit("isAsCheapAsAMove");
+ hasExtraSrcRegAllocReq = R->getValueAsBit("hasExtraSrcRegAllocReq");
+ hasExtraDefRegAllocReq = R->getValueAsBit("hasExtraDefRegAllocReq");
+ isCodeGenOnly = R->getValueAsBit("isCodeGenOnly");
+ isPseudo = R->getValueAsBit("isPseudo");
+ ImplicitDefs = R->getValueAsListOfDefs("Defs");
+ ImplicitUses = R->getValueAsListOfDefs("Uses");
+
+ // Parse Constraints.
+ ParseConstraints(R->getValueAsString("Constraints"), Operands);
+
+ // Parse the DisableEncoding field.
+ Operands.ProcessDisableEncoding(R->getValueAsString("DisableEncoding"));
+
+ // First check for a ComplexDeprecationPredicate.
+ if (R->getValue("ComplexDeprecationPredicate")) {
+ HasComplexDeprecationPredicate = true;
+ DeprecatedReason = R->getValueAsString("ComplexDeprecationPredicate");
+ } else if (RecordVal *Dep = R->getValue("DeprecatedFeatureMask")) {
+ // Check if we have a Subtarget feature mask.
+ HasComplexDeprecationPredicate = false;
+ DeprecatedReason = Dep->getValue()->getAsString();
+ } else {
+ // This instruction isn't deprecated.
+ HasComplexDeprecationPredicate = false;
+ DeprecatedReason = "";
+ }
+}
+
+/// HasOneImplicitDefWithKnownVT - If the instruction has at least one
+/// implicit def and it has a known VT, return the VT, otherwise return
+/// MVT::Other.
+MVT::SimpleValueType CodeGenInstruction::
+HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const {
+ if (ImplicitDefs.empty()) return MVT::Other;
+
+ // Check to see if the first implicit def has a resolvable type.
+ Record *FirstImplicitDef = ImplicitDefs[0];
+ assert(FirstImplicitDef->isSubClassOf("Register"));
+ const std::vector<MVT::SimpleValueType> &RegVTs =
+ TargetInfo.getRegisterVTs(FirstImplicitDef);
+ if (RegVTs.size() == 1)
+ return RegVTs[0];
+ return MVT::Other;
+}
+
+
+/// FlattenAsmStringVariants - Flatten the specified AsmString to only
+/// include text from the specified variant, returning the new string.
+std::string CodeGenInstruction::
+FlattenAsmStringVariants(StringRef Cur, unsigned Variant) {
+ std::string Res = "";
+
+ for (;;) {
+ // Find the start of the next variant string.
+ size_t VariantsStart = 0;
+ for (size_t e = Cur.size(); VariantsStart != e; ++VariantsStart)
+ if (Cur[VariantsStart] == '{' &&
+ (VariantsStart == 0 || (Cur[VariantsStart-1] != '$' &&
+ Cur[VariantsStart-1] != '\\')))
+ break;
+
+ // Add the prefix to the result.
+ Res += Cur.slice(0, VariantsStart);
+ if (VariantsStart == Cur.size())
+ break;
+
+ ++VariantsStart; // Skip the '{'.
+
+ // Scan to the end of the variants string.
+ size_t VariantsEnd = VariantsStart;
+ unsigned NestedBraces = 1;
+ for (size_t e = Cur.size(); VariantsEnd != e; ++VariantsEnd) {
+ if (Cur[VariantsEnd] == '}' && Cur[VariantsEnd-1] != '\\') {
+ if (--NestedBraces == 0)
+ break;
+ } else if (Cur[VariantsEnd] == '{')
+ ++NestedBraces;
+ }
+
+ // Select the Nth variant (or empty).
+ StringRef Selection = Cur.slice(VariantsStart, VariantsEnd);
+ for (unsigned i = 0; i != Variant; ++i)
+ Selection = Selection.split('|').second;
+ Res += Selection.split('|').first;
+
+ assert(VariantsEnd != Cur.size() &&
+ "Unterminated variants in assembly string!");
+ Cur = Cur.substr(VariantsEnd + 1);
+ }
+
+ return Res;
+}
+
+
+//===----------------------------------------------------------------------===//
+/// CodeGenInstAlias Implementation
+//===----------------------------------------------------------------------===//
+
+/// tryAliasOpMatch - This is a helper function for the CodeGenInstAlias
+/// constructor. It checks if an argument in an InstAlias pattern matches
+/// the corresponding operand of the instruction. It returns true on a
+/// successful match, with ResOp set to the result operand to be used.
+bool CodeGenInstAlias::tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
+ Record *InstOpRec, bool hasSubOps,
+ ArrayRef<SMLoc> Loc, CodeGenTarget &T,
+ ResultOperand &ResOp) {
+ Init *Arg = Result->getArg(AliasOpNo);
+ DefInit *ADI = dyn_cast<DefInit>(Arg);
+ Record *ResultRecord = ADI ? ADI->getDef() : nullptr;
+
+ if (ADI && ADI->getDef() == InstOpRec) {
+ // If the operand is a record, it must have a name, and the record type
+ // must match up with the instruction's argument type.
+ if (!Result->getArgName(AliasOpNo))
+ PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
+ " must have a name!");
+ ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ResultRecord);
+ return true;
+ }
+
+ // For register operands, the source register class can be a subclass
+ // of the instruction register class, not just an exact match.
+ if (InstOpRec->isSubClassOf("RegisterOperand"))
+ InstOpRec = InstOpRec->getValueAsDef("RegClass");
+
+ if (ADI && ADI->getDef()->isSubClassOf("RegisterOperand"))
+ ADI = ADI->getDef()->getValueAsDef("RegClass")->getDefInit();
+
+ if (ADI && ADI->getDef()->isSubClassOf("RegisterClass")) {
+ if (!InstOpRec->isSubClassOf("RegisterClass"))
+ return false;
+ if (!T.getRegisterClass(InstOpRec)
+ .hasSubClass(&T.getRegisterClass(ADI->getDef())))
+ return false;
+ ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ResultRecord);
+ return true;
+ }
+
+ // Handle explicit registers.
+ if (ADI && ADI->getDef()->isSubClassOf("Register")) {
+ if (InstOpRec->isSubClassOf("OptionalDefOperand")) {
+ DagInit *DI = InstOpRec->getValueAsDag("MIOperandInfo");
+ // The operand info should only have a single (register) entry. We
+ // want the register class of it.
+ InstOpRec = cast<DefInit>(DI->getArg(0))->getDef();
+ }
+
+ if (!InstOpRec->isSubClassOf("RegisterClass"))
+ return false;
+
+ if (!T.getRegisterClass(InstOpRec)
+ .contains(T.getRegBank().getReg(ADI->getDef())))
+ PrintFatalError(Loc, "fixed register " + ADI->getDef()->getName() +
+ " is not a member of the " + InstOpRec->getName() +
+ " register class!");
+
+ if (Result->getArgName(AliasOpNo))
+ PrintFatalError(Loc, "result fixed register argument must "
+ "not have a name!");
+
+ ResOp = ResultOperand(ResultRecord);
+ return true;
+ }
+
+ // Handle "zero_reg" for optional def operands.
+ if (ADI && ADI->getDef()->getName() == "zero_reg") {
+
+ // Check if this is an optional def.
+ // Tied operands where the source is a sub-operand of a complex operand
+ // need to represent both operands in the alias destination instruction.
+ // Allow zero_reg for the tied portion. This can and should go away once
+ // the MC representation of things doesn't use tied operands at all.
+ //if (!InstOpRec->isSubClassOf("OptionalDefOperand"))
+ // throw TGError(Loc, "reg0 used for result that is not an "
+ // "OptionalDefOperand!");
+
+ ResOp = ResultOperand(static_cast<Record*>(nullptr));
+ return true;
+ }
+
+ // Literal integers.
+ if (IntInit *II = dyn_cast<IntInit>(Arg)) {
+ if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
+ return false;
+ // Integer arguments can't have names.
+ if (Result->getArgName(AliasOpNo))
+ PrintFatalError(Loc, "result argument #" + Twine(AliasOpNo) +
+ " must not have a name!");
+ ResOp = ResultOperand(II->getValue());
+ return true;
+ }
+
+ // Bits<n> (also used for 0bxx literals)
+ if (BitsInit *BI = dyn_cast<BitsInit>(Arg)) {
+ if (hasSubOps || !InstOpRec->isSubClassOf("Operand"))
+ return false;
+ if (!BI->isComplete())
+ return false;
+ // Convert the bits init to an integer and use that for the result.
+ IntInit *II =
+ dyn_cast_or_null<IntInit>(BI->convertInitializerTo(IntRecTy::get()));
+ if (!II)
+ return false;
+ ResOp = ResultOperand(II->getValue());
+ return true;
+ }
+
+ // If both are Operands with the same MVT, allow the conversion. It's
+ // up to the user to make sure the values are appropriate, just like
+ // for isel Pat's.
+ if (InstOpRec->isSubClassOf("Operand") && ADI &&
+ ADI->getDef()->isSubClassOf("Operand")) {
+ // FIXME: What other attributes should we check here? Identical
+ // MIOperandInfo perhaps?
+ if (InstOpRec->getValueInit("Type") != ADI->getDef()->getValueInit("Type"))
+ return false;
+ ResOp = ResultOperand(Result->getArgNameStr(AliasOpNo), ADI->getDef());
+ return true;
+ }
+
+ return false;
+}
+
+unsigned CodeGenInstAlias::ResultOperand::getMINumOperands() const {
+ if (!isRecord())
+ return 1;
+
+ Record *Rec = getRecord();
+ if (!Rec->isSubClassOf("Operand"))
+ return 1;
+
+ DagInit *MIOpInfo = Rec->getValueAsDag("MIOperandInfo");
+ if (MIOpInfo->getNumArgs() == 0) {
+ // Unspecified, so it defaults to 1
+ return 1;
+ }
+
+ return MIOpInfo->getNumArgs();
+}
+
+CodeGenInstAlias::CodeGenInstAlias(Record *R, unsigned Variant,
+ CodeGenTarget &T)
+ : TheDef(R) {
+ Result = R->getValueAsDag("ResultInst");
+ AsmString = R->getValueAsString("AsmString");
+ AsmString = CodeGenInstruction::FlattenAsmStringVariants(AsmString, Variant);
+
+
+ // Verify that the root of the result is an instruction.
+ DefInit *DI = dyn_cast<DefInit>(Result->getOperator());
+ if (!DI || !DI->getDef()->isSubClassOf("Instruction"))
+ PrintFatalError(R->getLoc(),
+ "result of inst alias should be an instruction");
+
+ ResultInst = &T.getInstruction(DI->getDef());
+
+ // NameClass - If argument names are repeated, we need to verify they have
+ // the same class.
+ StringMap<Record*> NameClass;
+ for (unsigned i = 0, e = Result->getNumArgs(); i != e; ++i) {
+ DefInit *ADI = dyn_cast<DefInit>(Result->getArg(i));
+ if (!ADI || !Result->getArgName(i))
+ continue;
+ // Verify we don't have something like: (someinst GR16:$foo, GR32:$foo)
+ // $foo can exist multiple times in the result list, but it must have the
+ // same type.
+ Record *&Entry = NameClass[Result->getArgNameStr(i)];
+ if (Entry && Entry != ADI->getDef())
+ PrintFatalError(R->getLoc(), "result value $" + Result->getArgNameStr(i) +
+ " is both " + Entry->getName() + " and " +
+ ADI->getDef()->getName() + "!");
+ Entry = ADI->getDef();
+ }
+
+ // Decode and validate the arguments of the result.
+ unsigned AliasOpNo = 0;
+ for (unsigned i = 0, e = ResultInst->Operands.size(); i != e; ++i) {
+
+ // Tied registers don't have an entry in the result dag unless they're part
+ // of a complex operand, in which case we include them anyways, as we
+ // don't have any other way to specify the whole operand.
+ if (ResultInst->Operands[i].MINumOperands == 1 &&
+ ResultInst->Operands[i].getTiedRegister() != -1)
+ continue;
+
+ if (AliasOpNo >= Result->getNumArgs())
+ PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
+
+ Record *InstOpRec = ResultInst->Operands[i].Rec;
+ unsigned NumSubOps = ResultInst->Operands[i].MINumOperands;
+ ResultOperand ResOp(static_cast<int64_t>(0));
+ if (tryAliasOpMatch(Result, AliasOpNo, InstOpRec, (NumSubOps > 1),
+ R->getLoc(), T, ResOp)) {
+ // If this is a simple operand, or a complex operand with a custom match
+ // class, then we can match is verbatim.
+ if (NumSubOps == 1 ||
+ (InstOpRec->getValue("ParserMatchClass") &&
+ InstOpRec->getValueAsDef("ParserMatchClass")
+ ->getValueAsString("Name") != "Imm")) {
+ ResultOperands.push_back(ResOp);
+ ResultInstOperandIndex.push_back(std::make_pair(i, -1));
+ ++AliasOpNo;
+
+ // Otherwise, we need to match each of the suboperands individually.
+ } else {
+ DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
+ for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
+ Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
+
+ // Take care to instantiate each of the suboperands with the correct
+ // nomenclature: $foo.bar
+ ResultOperands.emplace_back(
+ Result->getArgName(AliasOpNo)->getAsUnquotedString() + "." +
+ MIOI->getArgName(SubOp)->getAsUnquotedString(), SubRec);
+ ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
+ }
+ ++AliasOpNo;
+ }
+ continue;
+ }
+
+ // If the argument did not match the instruction operand, and the operand
+ // is composed of multiple suboperands, try matching the suboperands.
+ if (NumSubOps > 1) {
+ DagInit *MIOI = ResultInst->Operands[i].MIOperandInfo;
+ for (unsigned SubOp = 0; SubOp != NumSubOps; ++SubOp) {
+ if (AliasOpNo >= Result->getNumArgs())
+ PrintFatalError(R->getLoc(), "not enough arguments for instruction!");
+ Record *SubRec = cast<DefInit>(MIOI->getArg(SubOp))->getDef();
+ if (tryAliasOpMatch(Result, AliasOpNo, SubRec, false,
+ R->getLoc(), T, ResOp)) {
+ ResultOperands.push_back(ResOp);
+ ResultInstOperandIndex.push_back(std::make_pair(i, SubOp));
+ ++AliasOpNo;
+ } else {
+ PrintFatalError(R->getLoc(), "result argument #" + Twine(AliasOpNo) +
+ " does not match instruction operand class " +
+ (SubOp == 0 ? InstOpRec->getName() :SubRec->getName()));
+ }
+ }
+ continue;
+ }
+ PrintFatalError(R->getLoc(), "result argument #" + Twine(AliasOpNo) +
+ " does not match instruction operand class " +
+ InstOpRec->getName());
+ }
+
+ if (AliasOpNo != Result->getNumArgs())
+ PrintFatalError(R->getLoc(), "too many operands for instruction!");
+}
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.h b/contrib/llvm/utils/TableGen/CodeGenInstruction.h
new file mode 100644
index 000000000000..75db17b59ac3
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.h
@@ -0,0 +1,355 @@
+//===- CodeGenInstruction.h - Instruction Class Wrapper ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a wrapper class for the 'Instruction' TableGen class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H
+#define LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/Support/SMLoc.h"
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+template <typename T> class ArrayRef;
+ class Record;
+ class DagInit;
+ class CodeGenTarget;
+
+ class CGIOperandList {
+ public:
+ class ConstraintInfo {
+ enum { None, EarlyClobber, Tied } Kind;
+ unsigned OtherTiedOperand;
+ public:
+ ConstraintInfo() : Kind(None) {}
+
+ static ConstraintInfo getEarlyClobber() {
+ ConstraintInfo I;
+ I.Kind = EarlyClobber;
+ I.OtherTiedOperand = 0;
+ return I;
+ }
+
+ static ConstraintInfo getTied(unsigned Op) {
+ ConstraintInfo I;
+ I.Kind = Tied;
+ I.OtherTiedOperand = Op;
+ return I;
+ }
+
+ bool isNone() const { return Kind == None; }
+ bool isEarlyClobber() const { return Kind == EarlyClobber; }
+ bool isTied() const { return Kind == Tied; }
+
+ unsigned getTiedOperand() const {
+ assert(isTied());
+ return OtherTiedOperand;
+ }
+ };
+
+ /// OperandInfo - The information we keep track of for each operand in the
+ /// operand list for a tablegen instruction.
+ struct OperandInfo {
+ /// Rec - The definition this operand is declared as.
+ ///
+ Record *Rec;
+
+ /// Name - If this operand was assigned a symbolic name, this is it,
+ /// otherwise, it's empty.
+ std::string Name;
+
+ /// PrinterMethodName - The method used to print operands of this type in
+ /// the asmprinter.
+ std::string PrinterMethodName;
+
+ /// EncoderMethodName - The method used to get the machine operand value
+ /// for binary encoding. "getMachineOpValue" by default.
+ std::string EncoderMethodName;
+
+ /// OperandType - A value from MCOI::OperandType representing the type of
+ /// the operand.
+ std::string OperandType;
+
+ /// MIOperandNo - Currently (this is meant to be phased out), some logical
+ /// operands correspond to multiple MachineInstr operands. In the X86
+ /// target for example, one address operand is represented as 4
+ /// MachineOperands. Because of this, the operand number in the
+ /// OperandList may not match the MachineInstr operand num. Until it
+ /// does, this contains the MI operand index of this operand.
+ unsigned MIOperandNo;
+ unsigned MINumOperands; // The number of operands.
+
+ /// DoNotEncode - Bools are set to true in this vector for each operand in
+ /// the DisableEncoding list. These should not be emitted by the code
+ /// emitter.
+ std::vector<bool> DoNotEncode;
+
+ /// MIOperandInfo - Default MI operand type. Note an operand may be made
+ /// up of multiple MI operands.
+ DagInit *MIOperandInfo;
+
+ /// Constraint info for this operand. This operand can have pieces, so we
+ /// track constraint info for each.
+ std::vector<ConstraintInfo> Constraints;
+
+ OperandInfo(Record *R, const std::string &N, const std::string &PMN,
+ const std::string &EMN, const std::string &OT, unsigned MION,
+ unsigned MINO, DagInit *MIOI)
+ : Rec(R), Name(N), PrinterMethodName(PMN), EncoderMethodName(EMN),
+ OperandType(OT), MIOperandNo(MION), MINumOperands(MINO),
+ MIOperandInfo(MIOI) {}
+
+
+ /// getTiedOperand - If this operand is tied to another one, return the
+ /// other operand number. Otherwise, return -1.
+ int getTiedRegister() const {
+ for (unsigned j = 0, e = Constraints.size(); j != e; ++j) {
+ const CGIOperandList::ConstraintInfo &CI = Constraints[j];
+ if (CI.isTied()) return CI.getTiedOperand();
+ }
+ return -1;
+ }
+ };
+
+ CGIOperandList(Record *D);
+
+ Record *TheDef; // The actual record containing this OperandList.
+
+ /// NumDefs - Number of def operands declared, this is the number of
+ /// elements in the instruction's (outs) list.
+ ///
+ unsigned NumDefs;
+
+ /// OperandList - The list of declared operands, along with their declared
+ /// type (which is a record).
+ std::vector<OperandInfo> OperandList;
+
+ // Information gleaned from the operand list.
+ bool isPredicable;
+ bool hasOptionalDef;
+ bool isVariadic;
+
+ // Provide transparent accessors to the operand list.
+ bool empty() const { return OperandList.empty(); }
+ unsigned size() const { return OperandList.size(); }
+ const OperandInfo &operator[](unsigned i) const { return OperandList[i]; }
+ OperandInfo &operator[](unsigned i) { return OperandList[i]; }
+ OperandInfo &back() { return OperandList.back(); }
+ const OperandInfo &back() const { return OperandList.back(); }
+
+ typedef std::vector<OperandInfo>::iterator iterator;
+ typedef std::vector<OperandInfo>::const_iterator const_iterator;
+ iterator begin() { return OperandList.begin(); }
+ const_iterator begin() const { return OperandList.begin(); }
+ iterator end() { return OperandList.end(); }
+ const_iterator end() const { return OperandList.end(); }
+
+ /// getOperandNamed - Return the index of the operand with the specified
+ /// non-empty name. If the instruction does not have an operand with the
+ /// specified name, abort.
+ unsigned getOperandNamed(StringRef Name) const;
+
+ /// hasOperandNamed - Query whether the instruction has an operand of the
+ /// given name. If so, return true and set OpIdx to the index of the
+ /// operand. Otherwise, return false.
+ bool hasOperandNamed(StringRef Name, unsigned &OpIdx) const;
+
+ /// ParseOperandName - Parse an operand name like "$foo" or "$foo.bar",
+ /// where $foo is a whole operand and $foo.bar refers to a suboperand.
+ /// This aborts if the name is invalid. If AllowWholeOp is true, references
+ /// to operands with suboperands are allowed, otherwise not.
+ std::pair<unsigned,unsigned> ParseOperandName(const std::string &Op,
+ bool AllowWholeOp = true);
+
+ /// getFlattenedOperandNumber - Flatten a operand/suboperand pair into a
+ /// flat machineinstr operand #.
+ unsigned getFlattenedOperandNumber(std::pair<unsigned,unsigned> Op) const {
+ return OperandList[Op.first].MIOperandNo + Op.second;
+ }
+
+ /// getSubOperandNumber - Unflatten a operand number into an
+ /// operand/suboperand pair.
+ std::pair<unsigned,unsigned> getSubOperandNumber(unsigned Op) const {
+ for (unsigned i = 0; ; ++i) {
+ assert(i < OperandList.size() && "Invalid flat operand #");
+ if (OperandList[i].MIOperandNo+OperandList[i].MINumOperands > Op)
+ return std::make_pair(i, Op-OperandList[i].MIOperandNo);
+ }
+ }
+
+
+ /// isFlatOperandNotEmitted - Return true if the specified flat operand #
+ /// should not be emitted with the code emitter.
+ bool isFlatOperandNotEmitted(unsigned FlatOpNo) const {
+ std::pair<unsigned,unsigned> Op = getSubOperandNumber(FlatOpNo);
+ if (OperandList[Op.first].DoNotEncode.size() > Op.second)
+ return OperandList[Op.first].DoNotEncode[Op.second];
+ return false;
+ }
+
+ void ProcessDisableEncoding(std::string Value);
+ };
+
+
+ class CodeGenInstruction {
+ public:
+ Record *TheDef; // The actual record defining this instruction.
+ std::string Namespace; // The namespace the instruction is in.
+
+ /// AsmString - The format string used to emit a .s file for the
+ /// instruction.
+ std::string AsmString;
+
+ /// Operands - This is information about the (ins) and (outs) list specified
+ /// to the instruction.
+ CGIOperandList Operands;
+
+ /// ImplicitDefs/ImplicitUses - These are lists of registers that are
+ /// implicitly defined and used by the instruction.
+ std::vector<Record*> ImplicitDefs, ImplicitUses;
+
+ // Various boolean values we track for the instruction.
+ bool isReturn : 1;
+ bool isBranch : 1;
+ bool isIndirectBranch : 1;
+ bool isCompare : 1;
+ bool isMoveImm : 1;
+ bool isBitcast : 1;
+ bool isSelect : 1;
+ bool isBarrier : 1;
+ bool isCall : 1;
+ bool isAdd : 1;
+ bool canFoldAsLoad : 1;
+ bool mayLoad : 1;
+ bool mayLoad_Unset : 1;
+ bool mayStore : 1;
+ bool mayStore_Unset : 1;
+ bool isPredicable : 1;
+ bool isConvertibleToThreeAddress : 1;
+ bool isCommutable : 1;
+ bool isTerminator : 1;
+ bool isReMaterializable : 1;
+ bool hasDelaySlot : 1;
+ bool usesCustomInserter : 1;
+ bool hasPostISelHook : 1;
+ bool hasCtrlDep : 1;
+ bool isNotDuplicable : 1;
+ bool hasSideEffects : 1;
+ bool hasSideEffects_Unset : 1;
+ bool isAsCheapAsAMove : 1;
+ bool hasExtraSrcRegAllocReq : 1;
+ bool hasExtraDefRegAllocReq : 1;
+ bool isCodeGenOnly : 1;
+ bool isPseudo : 1;
+ bool isRegSequence : 1;
+ bool isExtractSubreg : 1;
+ bool isInsertSubreg : 1;
+ bool isConvergent : 1;
+ bool hasNoSchedulingInfo : 1;
+
+ std::string DeprecatedReason;
+ bool HasComplexDeprecationPredicate;
+
+ /// Are there any undefined flags?
+ bool hasUndefFlags() const {
+ return mayLoad_Unset || mayStore_Unset || hasSideEffects_Unset;
+ }
+
+ // The record used to infer instruction flags, or NULL if no flag values
+ // have been inferred.
+ Record *InferredFrom;
+
+ CodeGenInstruction(Record *R);
+
+ /// HasOneImplicitDefWithKnownVT - If the instruction has at least one
+ /// implicit def and it has a known VT, return the VT, otherwise return
+ /// MVT::Other.
+ MVT::SimpleValueType
+ HasOneImplicitDefWithKnownVT(const CodeGenTarget &TargetInfo) const;
+
+
+ /// FlattenAsmStringVariants - Flatten the specified AsmString to only
+ /// include text from the specified variant, returning the new string.
+ static std::string FlattenAsmStringVariants(StringRef AsmString,
+ unsigned Variant);
+ };
+
+
+ /// CodeGenInstAlias - This represents an InstAlias definition.
+ class CodeGenInstAlias {
+ public:
+ Record *TheDef; // The actual record defining this InstAlias.
+
+ /// AsmString - The format string used to emit a .s file for the
+ /// instruction.
+ std::string AsmString;
+
+ /// Result - The result instruction.
+ DagInit *Result;
+
+ /// ResultInst - The instruction generated by the alias (decoded from
+ /// Result).
+ CodeGenInstruction *ResultInst;
+
+
+ struct ResultOperand {
+ private:
+ std::string Name;
+ Record *R;
+
+ int64_t Imm;
+ public:
+ enum {
+ K_Record,
+ K_Imm,
+ K_Reg
+ } Kind;
+
+ ResultOperand(std::string N, Record *r)
+ : Name(std::move(N)), R(r), Kind(K_Record) {}
+ ResultOperand(int64_t I) : Imm(I), Kind(K_Imm) {}
+ ResultOperand(Record *r) : R(r), Kind(K_Reg) {}
+
+ bool isRecord() const { return Kind == K_Record; }
+ bool isImm() const { return Kind == K_Imm; }
+ bool isReg() const { return Kind == K_Reg; }
+
+ StringRef getName() const { assert(isRecord()); return Name; }
+ Record *getRecord() const { assert(isRecord()); return R; }
+ int64_t getImm() const { assert(isImm()); return Imm; }
+ Record *getRegister() const { assert(isReg()); return R; }
+
+ unsigned getMINumOperands() const;
+ };
+
+ /// ResultOperands - The decoded operands for the result instruction.
+ std::vector<ResultOperand> ResultOperands;
+
+ /// ResultInstOperandIndex - For each operand, this vector holds a pair of
+ /// indices to identify the corresponding operand in the result
+ /// instruction. The first index specifies the operand and the second
+ /// index specifies the suboperand. If there are no suboperands or if all
+ /// of them are matched by the operand, the second value should be -1.
+ std::vector<std::pair<unsigned, int> > ResultInstOperandIndex;
+
+ CodeGenInstAlias(Record *R, unsigned Variant, CodeGenTarget &T);
+
+ bool tryAliasOpMatch(DagInit *Result, unsigned AliasOpNo,
+ Record *InstOpRec, bool hasSubOps, ArrayRef<SMLoc> Loc,
+ CodeGenTarget &T, ResultOperand &ResOp);
+ };
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
new file mode 100644
index 000000000000..6df0e6a62caf
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
@@ -0,0 +1,155 @@
+//===- CodeGenIntrinsic.h - Intrinsic Class Wrapper ------------*- C++ -*--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a wrapper class for the 'Intrinsic' TableGen class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H
+#define LLVM_UTILS_TABLEGEN_CODEGENINTRINSICS_H
+
+#include "llvm/CodeGen/MachineValueType.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+class Record;
+class RecordKeeper;
+class CodeGenTarget;
+
+struct CodeGenIntrinsic {
+ Record *TheDef; // The actual record defining this intrinsic.
+ std::string Name; // The name of the LLVM function "llvm.bswap.i32"
+ std::string EnumName; // The name of the enum "bswap_i32"
+ std::string GCCBuiltinName; // Name of the corresponding GCC builtin, or "".
+ std::string MSBuiltinName; // Name of the corresponding MS builtin, or "".
+ std::string TargetPrefix; // Target prefix, e.g. "ppc" for t-s intrinsics.
+
+ /// This structure holds the return values and parameter values of an
+ /// intrinsic. If the number of return values is > 1, then the intrinsic
+ /// implicitly returns a first-class aggregate. The numbering of the types
+ /// starts at 0 with the first return value and continues from there through
+ /// the parameter list. This is useful for "matching" types.
+ struct IntrinsicSignature {
+ /// The MVT::SimpleValueType for each return type. Note that this list is
+ /// only populated when in the context of a target .td file. When building
+ /// Intrinsics.td, this isn't available, because we don't know the target
+ /// pointer size.
+ std::vector<MVT::SimpleValueType> RetVTs;
+
+ /// The records for each return type.
+ std::vector<Record *> RetTypeDefs;
+
+ /// The MVT::SimpleValueType for each parameter type. Note that this list is
+ /// only populated when in the context of a target .td file. When building
+ /// Intrinsics.td, this isn't available, because we don't know the target
+ /// pointer size.
+ std::vector<MVT::SimpleValueType> ParamVTs;
+
+ /// The records for each parameter type.
+ std::vector<Record *> ParamTypeDefs;
+ };
+
+ IntrinsicSignature IS;
+
+ /// Bit flags describing the type (ref/mod) and location of memory
+ /// accesses that may be performed by the intrinsics. Analogous to
+ /// \c FunctionModRefBehaviour.
+ enum ModRefBits {
+ /// The intrinsic may access memory that is otherwise inaccessible via
+ /// LLVM IR.
+ MR_InaccessibleMem = 1,
+
+ /// The intrinsic may access memory through pointer arguments.
+ /// LLVM IR.
+ MR_ArgMem = 2,
+
+ /// The intrinsic may access memory anywhere, i.e. it is not restricted
+ /// to access through pointer arguments.
+ MR_Anywhere = 4 | MR_ArgMem | MR_InaccessibleMem,
+
+ /// The intrinsic may read memory.
+ MR_Ref = 8,
+
+ /// The intrinsic may write memory.
+ MR_Mod = 16,
+
+ /// The intrinsic may both read and write memory.
+ MR_ModRef = MR_Ref | MR_Mod,
+ };
+
+ /// Memory mod/ref behavior of this intrinsic, corresponding to intrinsic
+ /// properties (IntrReadMem, IntrArgMemOnly, etc.).
+ enum ModRefBehavior {
+ NoMem = 0,
+ ReadArgMem = MR_Ref | MR_ArgMem,
+ ReadInaccessibleMem = MR_Ref | MR_InaccessibleMem,
+ ReadInaccessibleMemOrArgMem = MR_Ref | MR_ArgMem | MR_InaccessibleMem,
+ ReadMem = MR_Ref | MR_Anywhere,
+ WriteArgMem = MR_Mod | MR_ArgMem,
+ WriteInaccessibleMem = MR_Mod | MR_InaccessibleMem,
+ WriteInaccessibleMemOrArgMem = MR_Mod | MR_ArgMem | MR_InaccessibleMem,
+ WriteMem = MR_Mod | MR_Anywhere,
+ ReadWriteArgMem = MR_ModRef | MR_ArgMem,
+ ReadWriteInaccessibleMem = MR_ModRef | MR_InaccessibleMem,
+ ReadWriteInaccessibleMemOrArgMem = MR_ModRef | MR_ArgMem |
+ MR_InaccessibleMem,
+ ReadWriteMem = MR_ModRef | MR_Anywhere,
+ };
+ ModRefBehavior ModRef;
+
+ /// This is set to true if the intrinsic is overloaded by its argument
+ /// types.
+ bool isOverloaded;
+
+ /// True if the intrinsic is commutative.
+ bool isCommutative;
+
+ /// True if the intrinsic can throw.
+ bool canThrow;
+
+ /// True if the intrinsic is marked as noduplicate.
+ bool isNoDuplicate;
+
+ /// True if the intrinsic is no-return.
+ bool isNoReturn;
+
+ /// True if the intrinsic is marked as convergent.
+ bool isConvergent;
+
+ enum ArgAttribute { NoCapture, Returned, ReadOnly, WriteOnly, ReadNone };
+ std::vector<std::pair<unsigned, ArgAttribute>> ArgumentAttributes;
+
+ CodeGenIntrinsic(Record *R);
+};
+
+class CodeGenIntrinsicTable {
+ std::vector<CodeGenIntrinsic> Intrinsics;
+
+public:
+ struct TargetSet {
+ std::string Name;
+ size_t Offset;
+ size_t Count;
+ };
+ std::vector<TargetSet> Targets;
+
+ explicit CodeGenIntrinsicTable(const RecordKeeper &RC, bool TargetOnly);
+ CodeGenIntrinsicTable() = default;
+
+ bool empty() const { return Intrinsics.empty(); }
+ size_t size() const { return Intrinsics.size(); }
+ CodeGenIntrinsic &operator[](size_t Pos) { return Intrinsics[Pos]; }
+ const CodeGenIntrinsic &operator[](size_t Pos) const {
+ return Intrinsics[Pos];
+ }
+};
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp
new file mode 100644
index 000000000000..60db6c267ad7
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp
@@ -0,0 +1,608 @@
+//===- CodeGenMapTable.cpp - Instruction Mapping Table Generator ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// CodeGenMapTable provides functionality for the TabelGen to create
+// relation mapping between instructions. Relation models are defined using
+// InstrMapping as a base class. This file implements the functionality which
+// parses these definitions and generates relation maps using the information
+// specified there. These maps are emitted as tables in the XXXGenInstrInfo.inc
+// file along with the functions to query them.
+//
+// A relationship model to relate non-predicate instructions with their
+// predicated true/false forms can be defined as follows:
+//
+// def getPredOpcode : InstrMapping {
+// let FilterClass = "PredRel";
+// let RowFields = ["BaseOpcode"];
+// let ColFields = ["PredSense"];
+// let KeyCol = ["none"];
+// let ValueCols = [["true"], ["false"]]; }
+//
+// CodeGenMapTable parses this map and generates a table in XXXGenInstrInfo.inc
+// file that contains the instructions modeling this relationship. This table
+// is defined in the function
+// "int getPredOpcode(uint16_t Opcode, enum PredSense inPredSense)"
+// that can be used to retrieve the predicated form of the instruction by
+// passing its opcode value and the predicate sense (true/false) of the desired
+// instruction as arguments.
+//
+// Short description of the algorithm:
+//
+// 1) Iterate through all the records that derive from "InstrMapping" class.
+// 2) For each record, filter out instructions based on the FilterClass value.
+// 3) Iterate through this set of instructions and insert them into
+// RowInstrMap map based on their RowFields values. RowInstrMap is keyed by the
+// vector of RowFields values and contains vectors of Records (instructions) as
+// values. RowFields is a list of fields that are required to have the same
+// values for all the instructions appearing in the same row of the relation
+// table. All the instructions in a given row of the relation table have some
+// sort of relationship with the key instruction defined by the corresponding
+// relationship model.
+//
+// Ex: RowInstrMap(RowVal1, RowVal2, ...) -> [Instr1, Instr2, Instr3, ... ]
+// Here Instr1, Instr2, Instr3 have same values (RowVal1, RowVal2) for
+// RowFields. These groups of instructions are later matched against ValueCols
+// to determine the column they belong to, if any.
+//
+// While building the RowInstrMap map, collect all the key instructions in
+// KeyInstrVec. These are the instructions having the same values as KeyCol
+// for all the fields listed in ColFields.
+//
+// For Example:
+//
+// Relate non-predicate instructions with their predicated true/false forms.
+//
+// def getPredOpcode : InstrMapping {
+// let FilterClass = "PredRel";
+// let RowFields = ["BaseOpcode"];
+// let ColFields = ["PredSense"];
+// let KeyCol = ["none"];
+// let ValueCols = [["true"], ["false"]]; }
+//
+// Here, only instructions that have "none" as PredSense will be selected as key
+// instructions.
+//
+// 4) For each key instruction, get the group of instructions that share the
+// same key-value as the key instruction from RowInstrMap. Iterate over the list
+// of columns in ValueCols (it is defined as a list<list<string> >. Therefore,
+// it can specify multi-column relationships). For each column, find the
+// instruction from the group that matches all the values for the column.
+// Multiple matches are not allowed.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenTarget.h"
+#include "llvm/Support/Format.h"
+#include "llvm/TableGen/Error.h"
+using namespace llvm;
+typedef std::map<std::string, std::vector<Record*> > InstrRelMapTy;
+
+typedef std::map<std::vector<Init*>, std::vector<Record*> > RowInstrMapTy;
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+// This class is used to represent InstrMapping class defined in Target.td file.
+class InstrMap {
+private:
+ std::string Name;
+ std::string FilterClass;
+ ListInit *RowFields;
+ ListInit *ColFields;
+ ListInit *KeyCol;
+ std::vector<ListInit*> ValueCols;
+
+public:
+ InstrMap(Record* MapRec) {
+ Name = MapRec->getName();
+
+ // FilterClass - It's used to reduce the search space only to the
+ // instructions that define the kind of relationship modeled by
+ // this InstrMapping object/record.
+ const RecordVal *Filter = MapRec->getValue("FilterClass");
+ FilterClass = Filter->getValue()->getAsUnquotedString();
+
+ // List of fields/attributes that need to be same across all the
+ // instructions in a row of the relation table.
+ RowFields = MapRec->getValueAsListInit("RowFields");
+
+ // List of fields/attributes that are constant across all the instruction
+ // in a column of the relation table. Ex: ColFields = 'predSense'
+ ColFields = MapRec->getValueAsListInit("ColFields");
+
+ // Values for the fields/attributes listed in 'ColFields'.
+ // Ex: KeyCol = 'noPred' -- key instruction is non-predicated
+ KeyCol = MapRec->getValueAsListInit("KeyCol");
+
+ // List of values for the fields/attributes listed in 'ColFields', one for
+ // each column in the relation table.
+ //
+ // Ex: ValueCols = [['true'],['false']] -- it results two columns in the
+ // table. First column requires all the instructions to have predSense
+ // set to 'true' and second column requires it to be 'false'.
+ ListInit *ColValList = MapRec->getValueAsListInit("ValueCols");
+
+ // Each instruction map must specify at least one column for it to be valid.
+ if (ColValList->empty())
+ PrintFatalError(MapRec->getLoc(), "InstrMapping record `" +
+ MapRec->getName() + "' has empty " + "`ValueCols' field!");
+
+ for (Init *I : ColValList->getValues()) {
+ ListInit *ColI = dyn_cast<ListInit>(I);
+
+ // Make sure that all the sub-lists in 'ValueCols' have same number of
+ // elements as the fields in 'ColFields'.
+ if (ColI->size() != ColFields->size())
+ PrintFatalError(MapRec->getLoc(), "Record `" + MapRec->getName() +
+ "', field `ValueCols' entries don't match with " +
+ " the entries in 'ColFields'!");
+ ValueCols.push_back(ColI);
+ }
+ }
+
+ std::string getName() const {
+ return Name;
+ }
+
+ std::string getFilterClass() {
+ return FilterClass;
+ }
+
+ ListInit *getRowFields() const {
+ return RowFields;
+ }
+
+ ListInit *getColFields() const {
+ return ColFields;
+ }
+
+ ListInit *getKeyCol() const {
+ return KeyCol;
+ }
+
+ const std::vector<ListInit*> &getValueCols() const {
+ return ValueCols;
+ }
+};
+} // End anonymous namespace.
+
+
+//===----------------------------------------------------------------------===//
+// class MapTableEmitter : It builds the instruction relation maps using
+// the information provided in InstrMapping records. It outputs these
+// relationship maps as tables into XXXGenInstrInfo.inc file along with the
+// functions to query them.
+
+namespace {
+class MapTableEmitter {
+private:
+// std::string TargetName;
+ const CodeGenTarget &Target;
+ // InstrMapDesc - InstrMapping record to be processed.
+ InstrMap InstrMapDesc;
+
+ // InstrDefs - list of instructions filtered using FilterClass defined
+ // in InstrMapDesc.
+ std::vector<Record*> InstrDefs;
+
+ // RowInstrMap - maps RowFields values to the instructions. It's keyed by the
+ // values of the row fields and contains vector of records as values.
+ RowInstrMapTy RowInstrMap;
+
+ // KeyInstrVec - list of key instructions.
+ std::vector<Record*> KeyInstrVec;
+ DenseMap<Record*, std::vector<Record*> > MapTable;
+
+public:
+ MapTableEmitter(CodeGenTarget &Target, RecordKeeper &Records, Record *IMRec):
+ Target(Target), InstrMapDesc(IMRec) {
+ const std::string FilterClass = InstrMapDesc.getFilterClass();
+ InstrDefs = Records.getAllDerivedDefinitions(FilterClass);
+ }
+
+ void buildRowInstrMap();
+
+ // Returns true if an instruction is a key instruction, i.e., its ColFields
+ // have same values as KeyCol.
+ bool isKeyColInstr(Record* CurInstr);
+
+ // Find column instruction corresponding to a key instruction based on the
+ // constraints for that column.
+ Record *getInstrForColumn(Record *KeyInstr, ListInit *CurValueCol);
+
+ // Find column instructions for each key instruction based
+ // on ValueCols and store them into MapTable.
+ void buildMapTable();
+
+ void emitBinSearch(raw_ostream &OS, unsigned TableSize);
+ void emitTablesWithFunc(raw_ostream &OS);
+ unsigned emitBinSearchTable(raw_ostream &OS);
+
+ // Lookup functions to query binary search tables.
+ void emitMapFuncBody(raw_ostream &OS, unsigned TableSize);
+
+};
+} // End anonymous namespace.
+
+
+//===----------------------------------------------------------------------===//
+// Process all the instructions that model this relation (alreday present in
+// InstrDefs) and insert them into RowInstrMap which is keyed by the values of
+// the fields listed as RowFields. It stores vectors of records as values.
+// All the related instructions have the same values for the RowFields thus are
+// part of the same key-value pair.
+//===----------------------------------------------------------------------===//
+
+void MapTableEmitter::buildRowInstrMap() {
+ for (Record *CurInstr : InstrDefs) {
+ std::vector<Init*> KeyValue;
+ ListInit *RowFields = InstrMapDesc.getRowFields();
+ for (Init *RowField : RowFields->getValues()) {
+ Init *CurInstrVal = CurInstr->getValue(RowField)->getValue();
+ KeyValue.push_back(CurInstrVal);
+ }
+
+ // Collect key instructions into KeyInstrVec. Later, these instructions are
+ // processed to assign column position to the instructions sharing
+ // their KeyValue in RowInstrMap.
+ if (isKeyColInstr(CurInstr))
+ KeyInstrVec.push_back(CurInstr);
+
+ RowInstrMap[KeyValue].push_back(CurInstr);
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Return true if an instruction is a KeyCol instruction.
+//===----------------------------------------------------------------------===//
+
+bool MapTableEmitter::isKeyColInstr(Record* CurInstr) {
+ ListInit *ColFields = InstrMapDesc.getColFields();
+ ListInit *KeyCol = InstrMapDesc.getKeyCol();
+
+ // Check if the instruction is a KeyCol instruction.
+ bool MatchFound = true;
+ for (unsigned j = 0, endCF = ColFields->size();
+ (j < endCF) && MatchFound; j++) {
+ RecordVal *ColFieldName = CurInstr->getValue(ColFields->getElement(j));
+ std::string CurInstrVal = ColFieldName->getValue()->getAsUnquotedString();
+ std::string KeyColValue = KeyCol->getElement(j)->getAsUnquotedString();
+ MatchFound = (CurInstrVal == KeyColValue);
+ }
+ return MatchFound;
+}
+
+//===----------------------------------------------------------------------===//
+// Build a map to link key instructions with the column instructions arranged
+// according to their column positions.
+//===----------------------------------------------------------------------===//
+
+void MapTableEmitter::buildMapTable() {
+ // Find column instructions for a given key based on the ColField
+ // constraints.
+ const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
+ unsigned NumOfCols = ValueCols.size();
+ for (Record *CurKeyInstr : KeyInstrVec) {
+ std::vector<Record*> ColInstrVec(NumOfCols);
+
+ // Find the column instruction based on the constraints for the column.
+ for (unsigned ColIdx = 0; ColIdx < NumOfCols; ColIdx++) {
+ ListInit *CurValueCol = ValueCols[ColIdx];
+ Record *ColInstr = getInstrForColumn(CurKeyInstr, CurValueCol);
+ ColInstrVec[ColIdx] = ColInstr;
+ }
+ MapTable[CurKeyInstr] = ColInstrVec;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Find column instruction based on the constraints for that column.
+//===----------------------------------------------------------------------===//
+
+Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
+ ListInit *CurValueCol) {
+ ListInit *RowFields = InstrMapDesc.getRowFields();
+ std::vector<Init*> KeyValue;
+
+ // Construct KeyValue using KeyInstr's values for RowFields.
+ for (Init *RowField : RowFields->getValues()) {
+ Init *KeyInstrVal = KeyInstr->getValue(RowField)->getValue();
+ KeyValue.push_back(KeyInstrVal);
+ }
+
+ // Get all the instructions that share the same KeyValue as the KeyInstr
+ // in RowInstrMap. We search through these instructions to find a match
+ // for the current column, i.e., the instruction which has the same values
+ // as CurValueCol for all the fields in ColFields.
+ const std::vector<Record*> &RelatedInstrVec = RowInstrMap[KeyValue];
+
+ ListInit *ColFields = InstrMapDesc.getColFields();
+ Record *MatchInstr = nullptr;
+
+ for (unsigned i = 0, e = RelatedInstrVec.size(); i < e; i++) {
+ bool MatchFound = true;
+ Record *CurInstr = RelatedInstrVec[i];
+ for (unsigned j = 0, endCF = ColFields->size();
+ (j < endCF) && MatchFound; j++) {
+ Init *ColFieldJ = ColFields->getElement(j);
+ Init *CurInstrInit = CurInstr->getValue(ColFieldJ)->getValue();
+ std::string CurInstrVal = CurInstrInit->getAsUnquotedString();
+ Init *ColFieldJVallue = CurValueCol->getElement(j);
+ MatchFound = (CurInstrVal == ColFieldJVallue->getAsUnquotedString());
+ }
+
+ if (MatchFound) {
+ if (MatchInstr) {
+ // Already had a match
+ // Error if multiple matches are found for a column.
+ std::string KeyValueStr;
+ for (Init *Value : KeyValue) {
+ if (!KeyValueStr.empty())
+ KeyValueStr += ", ";
+ KeyValueStr += Value->getAsString();
+ }
+
+ PrintFatalError("Multiple matches found for `" + KeyInstr->getName() +
+ "', for the relation `" + InstrMapDesc.getName() + "', row fields [" +
+ KeyValueStr + "], column `" + CurValueCol->getAsString() + "'");
+ }
+ MatchInstr = CurInstr;
+ }
+ }
+ return MatchInstr;
+}
+
+//===----------------------------------------------------------------------===//
+// Emit one table per relation. Only instructions with a valid relation of a
+// given type are included in the table sorted by their enum values (opcodes).
+// Binary search is used for locating instructions in the table.
+//===----------------------------------------------------------------------===//
+
+unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) {
+
+ ArrayRef<const CodeGenInstruction*> NumberedInstructions =
+ Target.getInstructionsByEnumValue();
+ std::string Namespace = Target.getInstNamespace();
+ const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
+ unsigned NumCol = ValueCols.size();
+ unsigned TotalNumInstr = NumberedInstructions.size();
+ unsigned TableSize = 0;
+
+ OS << "static const uint16_t "<<InstrMapDesc.getName();
+ // Number of columns in the table are NumCol+1 because key instructions are
+ // emitted as first column.
+ OS << "Table[]["<< NumCol+1 << "] = {\n";
+ for (unsigned i = 0; i < TotalNumInstr; i++) {
+ Record *CurInstr = NumberedInstructions[i]->TheDef;
+ std::vector<Record*> ColInstrs = MapTable[CurInstr];
+ std::string OutStr("");
+ unsigned RelExists = 0;
+ if (!ColInstrs.empty()) {
+ for (unsigned j = 0; j < NumCol; j++) {
+ if (ColInstrs[j] != nullptr) {
+ RelExists = 1;
+ OutStr += ", ";
+ OutStr += Namespace;
+ OutStr += "::";
+ OutStr += ColInstrs[j]->getName();
+ } else { OutStr += ", (uint16_t)-1U";}
+ }
+
+ if (RelExists) {
+ OS << " { " << Namespace << "::" << CurInstr->getName();
+ OS << OutStr <<" },\n";
+ TableSize++;
+ }
+ }
+ }
+ if (!TableSize) {
+ OS << " { " << Namespace << "::" << "INSTRUCTION_LIST_END, ";
+ OS << Namespace << "::" << "INSTRUCTION_LIST_END }";
+ }
+ OS << "}; // End of " << InstrMapDesc.getName() << "Table\n\n";
+ return TableSize;
+}
+
+//===----------------------------------------------------------------------===//
+// Emit binary search algorithm as part of the functions used to query
+// relation tables.
+//===----------------------------------------------------------------------===//
+
+void MapTableEmitter::emitBinSearch(raw_ostream &OS, unsigned TableSize) {
+ OS << " unsigned mid;\n";
+ OS << " unsigned start = 0;\n";
+ OS << " unsigned end = " << TableSize << ";\n";
+ OS << " while (start < end) {\n";
+ OS << " mid = start + (end - start)/2;\n";
+ OS << " if (Opcode == " << InstrMapDesc.getName() << "Table[mid][0]) {\n";
+ OS << " break;\n";
+ OS << " }\n";
+ OS << " if (Opcode < " << InstrMapDesc.getName() << "Table[mid][0])\n";
+ OS << " end = mid;\n";
+ OS << " else\n";
+ OS << " start = mid + 1;\n";
+ OS << " }\n";
+ OS << " if (start == end)\n";
+ OS << " return -1; // Instruction doesn't exist in this table.\n\n";
+}
+
+//===----------------------------------------------------------------------===//
+// Emit functions to query relation tables.
+//===----------------------------------------------------------------------===//
+
+void MapTableEmitter::emitMapFuncBody(raw_ostream &OS,
+ unsigned TableSize) {
+
+ ListInit *ColFields = InstrMapDesc.getColFields();
+ const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
+
+ // Emit binary search algorithm to locate instructions in the
+ // relation table. If found, return opcode value from the appropriate column
+ // of the table.
+ emitBinSearch(OS, TableSize);
+
+ if (ValueCols.size() > 1) {
+ for (unsigned i = 0, e = ValueCols.size(); i < e; i++) {
+ ListInit *ColumnI = ValueCols[i];
+ for (unsigned j = 0, ColSize = ColumnI->size(); j < ColSize; ++j) {
+ std::string ColName = ColFields->getElement(j)->getAsUnquotedString();
+ OS << " if (in" << ColName;
+ OS << " == ";
+ OS << ColName << "_" << ColumnI->getElement(j)->getAsUnquotedString();
+ if (j < ColumnI->size() - 1) OS << " && ";
+ else OS << ")\n";
+ }
+ OS << " return " << InstrMapDesc.getName();
+ OS << "Table[mid]["<<i+1<<"];\n";
+ }
+ OS << " return -1;";
+ }
+ else
+ OS << " return " << InstrMapDesc.getName() << "Table[mid][1];\n";
+
+ OS <<"}\n\n";
+}
+
+//===----------------------------------------------------------------------===//
+// Emit relation tables and the functions to query them.
+//===----------------------------------------------------------------------===//
+
+void MapTableEmitter::emitTablesWithFunc(raw_ostream &OS) {
+
+ // Emit function name and the input parameters : mostly opcode value of the
+ // current instruction. However, if a table has multiple columns (more than 2
+ // since first column is used for the key instructions), then we also need
+ // to pass another input to indicate the column to be selected.
+
+ ListInit *ColFields = InstrMapDesc.getColFields();
+ const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
+ OS << "// "<< InstrMapDesc.getName() << "\nLLVM_READONLY\n";
+ OS << "int "<< InstrMapDesc.getName() << "(uint16_t Opcode";
+ if (ValueCols.size() > 1) {
+ for (Init *CF : ColFields->getValues()) {
+ std::string ColName = CF->getAsUnquotedString();
+ OS << ", enum " << ColName << " in" << ColName << ") {\n";
+ }
+ } else { OS << ") {\n"; }
+
+ // Emit map table.
+ unsigned TableSize = emitBinSearchTable(OS);
+
+ // Emit rest of the function body.
+ emitMapFuncBody(OS, TableSize);
+}
+
+//===----------------------------------------------------------------------===//
+// Emit enums for the column fields across all the instruction maps.
+//===----------------------------------------------------------------------===//
+
+static void emitEnums(raw_ostream &OS, RecordKeeper &Records) {
+
+ std::vector<Record*> InstrMapVec;
+ InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping");
+ std::map<std::string, std::vector<Init*> > ColFieldValueMap;
+
+ // Iterate over all InstrMapping records and create a map between column
+ // fields and their possible values across all records.
+ for (Record *CurMap : InstrMapVec) {
+ ListInit *ColFields;
+ ColFields = CurMap->getValueAsListInit("ColFields");
+ ListInit *List = CurMap->getValueAsListInit("ValueCols");
+ std::vector<ListInit*> ValueCols;
+ unsigned ListSize = List->size();
+
+ for (unsigned j = 0; j < ListSize; j++) {
+ ListInit *ListJ = dyn_cast<ListInit>(List->getElement(j));
+
+ if (ListJ->size() != ColFields->size())
+ PrintFatalError("Record `" + CurMap->getName() + "', field "
+ "`ValueCols' entries don't match with the entries in 'ColFields' !");
+ ValueCols.push_back(ListJ);
+ }
+
+ for (unsigned j = 0, endCF = ColFields->size(); j < endCF; j++) {
+ for (unsigned k = 0; k < ListSize; k++){
+ std::string ColName = ColFields->getElement(j)->getAsUnquotedString();
+ ColFieldValueMap[ColName].push_back((ValueCols[k])->getElement(j));
+ }
+ }
+ }
+
+ for (auto &Entry : ColFieldValueMap) {
+ std::vector<Init*> FieldValues = Entry.second;
+
+ // Delete duplicate entries from ColFieldValueMap
+ for (unsigned i = 0; i < FieldValues.size() - 1; i++) {
+ Init *CurVal = FieldValues[i];
+ for (unsigned j = i+1; j < FieldValues.size(); j++) {
+ if (CurVal == FieldValues[j]) {
+ FieldValues.erase(FieldValues.begin()+j);
+ --j;
+ }
+ }
+ }
+
+ // Emit enumerated values for the column fields.
+ OS << "enum " << Entry.first << " {\n";
+ for (unsigned i = 0, endFV = FieldValues.size(); i < endFV; i++) {
+ OS << "\t" << Entry.first << "_" << FieldValues[i]->getAsUnquotedString();
+ if (i != endFV - 1)
+ OS << ",\n";
+ else
+ OS << "\n};\n\n";
+ }
+ }
+}
+
+namespace llvm {
+//===----------------------------------------------------------------------===//
+// Parse 'InstrMapping' records and use the information to form relationship
+// between instructions. These relations are emitted as a tables along with the
+// functions to query them.
+//===----------------------------------------------------------------------===//
+void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) {
+ CodeGenTarget Target(Records);
+ std::string NameSpace = Target.getInstNamespace();
+ std::vector<Record*> InstrMapVec;
+ InstrMapVec = Records.getAllDerivedDefinitions("InstrMapping");
+
+ if (InstrMapVec.empty())
+ return;
+
+ OS << "#ifdef GET_INSTRMAP_INFO\n";
+ OS << "#undef GET_INSTRMAP_INFO\n";
+ OS << "namespace llvm {\n\n";
+ OS << "namespace " << NameSpace << " {\n\n";
+
+ // Emit coulumn field names and their values as enums.
+ emitEnums(OS, Records);
+
+ // Iterate over all instruction mapping records and construct relationship
+ // maps based on the information specified there.
+ //
+ for (Record *CurMap : InstrMapVec) {
+ MapTableEmitter IMap(Target, Records, CurMap);
+
+ // Build RowInstrMap to group instructions based on their values for
+ // RowFields. In the process, also collect key instructions into
+ // KeyInstrVec.
+ IMap.buildRowInstrMap();
+
+ // Build MapTable to map key instructions with the corresponding column
+ // instructions.
+ IMap.buildMapTable();
+
+ // Emit map tables and the functions to query them.
+ IMap.emitTablesWithFunc(OS);
+ }
+ OS << "} // End " << NameSpace << " namespace\n";
+ OS << "} // End llvm namespace\n";
+ OS << "#endif // GET_INSTRMAP_INFO\n\n";
+}
+
+} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
new file mode 100644
index 000000000000..627614d991d5
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
@@ -0,0 +1,2179 @@
+//===- CodeGenRegisters.cpp - Register and RegisterClass Info -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines structures to encapsulate information gleaned from the
+// target register and register class definitions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenRegisters.h"
+#include "CodeGenTarget.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntEqClasses.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SparseBitVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/MathExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <map>
+#include <set>
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "regalloc-emitter"
+
+//===----------------------------------------------------------------------===//
+// CodeGenSubRegIndex
+//===----------------------------------------------------------------------===//
+
+CodeGenSubRegIndex::CodeGenSubRegIndex(Record *R, unsigned Enum)
+ : TheDef(R), EnumValue(Enum), AllSuperRegsCovered(true) {
+ Name = R->getName();
+ if (R->getValue("Namespace"))
+ Namespace = R->getValueAsString("Namespace");
+ Size = R->getValueAsInt("Size");
+ Offset = R->getValueAsInt("Offset");
+}
+
+CodeGenSubRegIndex::CodeGenSubRegIndex(StringRef N, StringRef Nspace,
+ unsigned Enum)
+ : TheDef(nullptr), Name(N), Namespace(Nspace), Size(-1), Offset(-1),
+ EnumValue(Enum), AllSuperRegsCovered(true) {
+}
+
+std::string CodeGenSubRegIndex::getQualifiedName() const {
+ std::string N = getNamespace();
+ if (!N.empty())
+ N += "::";
+ N += getName();
+ return N;
+}
+
+void CodeGenSubRegIndex::updateComponents(CodeGenRegBank &RegBank) {
+ if (!TheDef)
+ return;
+
+ std::vector<Record*> Comps = TheDef->getValueAsListOfDefs("ComposedOf");
+ if (!Comps.empty()) {
+ if (Comps.size() != 2)
+ PrintFatalError(TheDef->getLoc(),
+ "ComposedOf must have exactly two entries");
+ CodeGenSubRegIndex *A = RegBank.getSubRegIdx(Comps[0]);
+ CodeGenSubRegIndex *B = RegBank.getSubRegIdx(Comps[1]);
+ CodeGenSubRegIndex *X = A->addComposite(B, this);
+ if (X)
+ PrintFatalError(TheDef->getLoc(), "Ambiguous ComposedOf entries");
+ }
+
+ std::vector<Record*> Parts =
+ TheDef->getValueAsListOfDefs("CoveringSubRegIndices");
+ if (!Parts.empty()) {
+ if (Parts.size() < 2)
+ PrintFatalError(TheDef->getLoc(),
+ "CoveredBySubRegs must have two or more entries");
+ SmallVector<CodeGenSubRegIndex*, 8> IdxParts;
+ for (unsigned i = 0, e = Parts.size(); i != e; ++i)
+ IdxParts.push_back(RegBank.getSubRegIdx(Parts[i]));
+ RegBank.addConcatSubRegIndex(IdxParts, this);
+ }
+}
+
+LaneBitmask CodeGenSubRegIndex::computeLaneMask() const {
+ // Already computed?
+ if (LaneMask.any())
+ return LaneMask;
+
+ // Recursion guard, shouldn't be required.
+ LaneMask = LaneBitmask::getAll();
+
+ // The lane mask is simply the union of all sub-indices.
+ LaneBitmask M;
+ for (const auto &C : Composed)
+ M |= C.second->computeLaneMask();
+ assert(M.any() && "Missing lane mask, sub-register cycle?");
+ LaneMask = M;
+ return LaneMask;
+}
+
+//===----------------------------------------------------------------------===//
+// CodeGenRegister
+//===----------------------------------------------------------------------===//
+
+CodeGenRegister::CodeGenRegister(Record *R, unsigned Enum)
+ : TheDef(R),
+ EnumValue(Enum),
+ CostPerUse(R->getValueAsInt("CostPerUse")),
+ CoveredBySubRegs(R->getValueAsBit("CoveredBySubRegs")),
+ HasDisjunctSubRegs(false),
+ SubRegsComplete(false),
+ SuperRegsComplete(false),
+ TopoSig(~0u)
+{}
+
+void CodeGenRegister::buildObjectGraph(CodeGenRegBank &RegBank) {
+ std::vector<Record*> SRIs = TheDef->getValueAsListOfDefs("SubRegIndices");
+ std::vector<Record*> SRs = TheDef->getValueAsListOfDefs("SubRegs");
+
+ if (SRIs.size() != SRs.size())
+ PrintFatalError(TheDef->getLoc(),
+ "SubRegs and SubRegIndices must have the same size");
+
+ for (unsigned i = 0, e = SRIs.size(); i != e; ++i) {
+ ExplicitSubRegIndices.push_back(RegBank.getSubRegIdx(SRIs[i]));
+ ExplicitSubRegs.push_back(RegBank.getReg(SRs[i]));
+ }
+
+ // Also compute leading super-registers. Each register has a list of
+ // covered-by-subregs super-registers where it appears as the first explicit
+ // sub-register.
+ //
+ // This is used by computeSecondarySubRegs() to find candidates.
+ if (CoveredBySubRegs && !ExplicitSubRegs.empty())
+ ExplicitSubRegs.front()->LeadingSuperRegs.push_back(this);
+
+ // Add ad hoc alias links. This is a symmetric relationship between two
+ // registers, so build a symmetric graph by adding links in both ends.
+ std::vector<Record*> Aliases = TheDef->getValueAsListOfDefs("Aliases");
+ for (unsigned i = 0, e = Aliases.size(); i != e; ++i) {
+ CodeGenRegister *Reg = RegBank.getReg(Aliases[i]);
+ ExplicitAliases.push_back(Reg);
+ Reg->ExplicitAliases.push_back(this);
+ }
+}
+
+const StringRef CodeGenRegister::getName() const {
+ assert(TheDef && "no def");
+ return TheDef->getName();
+}
+
+namespace {
+
+// Iterate over all register units in a set of registers.
+class RegUnitIterator {
+ CodeGenRegister::Vec::const_iterator RegI, RegE;
+ CodeGenRegister::RegUnitList::iterator UnitI, UnitE;
+
+public:
+ RegUnitIterator(const CodeGenRegister::Vec &Regs):
+ RegI(Regs.begin()), RegE(Regs.end()) {
+
+ if (RegI != RegE) {
+ UnitI = (*RegI)->getRegUnits().begin();
+ UnitE = (*RegI)->getRegUnits().end();
+ advance();
+ }
+ }
+
+ bool isValid() const { return UnitI != UnitE; }
+
+ unsigned operator* () const { assert(isValid()); return *UnitI; }
+
+ const CodeGenRegister *getReg() const { assert(isValid()); return *RegI; }
+
+ /// Preincrement. Move to the next unit.
+ void operator++() {
+ assert(isValid() && "Cannot advance beyond the last operand");
+ ++UnitI;
+ advance();
+ }
+
+protected:
+ void advance() {
+ while (UnitI == UnitE) {
+ if (++RegI == RegE)
+ break;
+ UnitI = (*RegI)->getRegUnits().begin();
+ UnitE = (*RegI)->getRegUnits().end();
+ }
+ }
+};
+
+} // end anonymous namespace
+
+// Return true of this unit appears in RegUnits.
+static bool hasRegUnit(CodeGenRegister::RegUnitList &RegUnits, unsigned Unit) {
+ return RegUnits.test(Unit);
+}
+
+// Inherit register units from subregisters.
+// Return true if the RegUnits changed.
+bool CodeGenRegister::inheritRegUnits(CodeGenRegBank &RegBank) {
+ bool changed = false;
+ for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
+ I != E; ++I) {
+ CodeGenRegister *SR = I->second;
+ // Merge the subregister's units into this register's RegUnits.
+ changed |= (RegUnits |= SR->RegUnits);
+ }
+
+ return changed;
+}
+
+const CodeGenRegister::SubRegMap &
+CodeGenRegister::computeSubRegs(CodeGenRegBank &RegBank) {
+ // Only compute this map once.
+ if (SubRegsComplete)
+ return SubRegs;
+ SubRegsComplete = true;
+
+ HasDisjunctSubRegs = ExplicitSubRegs.size() > 1;
+
+ // First insert the explicit subregs and make sure they are fully indexed.
+ for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
+ CodeGenRegister *SR = ExplicitSubRegs[i];
+ CodeGenSubRegIndex *Idx = ExplicitSubRegIndices[i];
+ if (!SubRegs.insert(std::make_pair(Idx, SR)).second)
+ PrintFatalError(TheDef->getLoc(), "SubRegIndex " + Idx->getName() +
+ " appears twice in Register " + getName());
+ // Map explicit sub-registers first, so the names take precedence.
+ // The inherited sub-registers are mapped below.
+ SubReg2Idx.insert(std::make_pair(SR, Idx));
+ }
+
+ // Keep track of inherited subregs and how they can be reached.
+ SmallPtrSet<CodeGenRegister*, 8> Orphans;
+
+ // Clone inherited subregs and place duplicate entries in Orphans.
+ // Here the order is important - earlier subregs take precedence.
+ for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
+ CodeGenRegister *SR = ExplicitSubRegs[i];
+ const SubRegMap &Map = SR->computeSubRegs(RegBank);
+ HasDisjunctSubRegs |= SR->HasDisjunctSubRegs;
+
+ for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE;
+ ++SI) {
+ if (!SubRegs.insert(*SI).second)
+ Orphans.insert(SI->second);
+ }
+ }
+
+ // Expand any composed subreg indices.
+ // If dsub_2 has ComposedOf = [qsub_1, dsub_0], and this register has a
+ // qsub_1 subreg, add a dsub_2 subreg. Keep growing Indices and process
+ // expanded subreg indices recursively.
+ SmallVector<CodeGenSubRegIndex*, 8> Indices = ExplicitSubRegIndices;
+ for (unsigned i = 0; i != Indices.size(); ++i) {
+ CodeGenSubRegIndex *Idx = Indices[i];
+ const CodeGenSubRegIndex::CompMap &Comps = Idx->getComposites();
+ CodeGenRegister *SR = SubRegs[Idx];
+ const SubRegMap &Map = SR->computeSubRegs(RegBank);
+
+ // Look at the possible compositions of Idx.
+ // They may not all be supported by SR.
+ for (CodeGenSubRegIndex::CompMap::const_iterator I = Comps.begin(),
+ E = Comps.end(); I != E; ++I) {
+ SubRegMap::const_iterator SRI = Map.find(I->first);
+ if (SRI == Map.end())
+ continue; // Idx + I->first doesn't exist in SR.
+ // Add I->second as a name for the subreg SRI->second, assuming it is
+ // orphaned, and the name isn't already used for something else.
+ if (SubRegs.count(I->second) || !Orphans.erase(SRI->second))
+ continue;
+ // We found a new name for the orphaned sub-register.
+ SubRegs.insert(std::make_pair(I->second, SRI->second));
+ Indices.push_back(I->second);
+ }
+ }
+
+ // Now Orphans contains the inherited subregisters without a direct index.
+ // Create inferred indexes for all missing entries.
+ // Work backwards in the Indices vector in order to compose subregs bottom-up.
+ // Consider this subreg sequence:
+ //
+ // qsub_1 -> dsub_0 -> ssub_0
+ //
+ // The qsub_1 -> dsub_0 composition becomes dsub_2, so the ssub_0 register
+ // can be reached in two different ways:
+ //
+ // qsub_1 -> ssub_0
+ // dsub_2 -> ssub_0
+ //
+ // We pick the latter composition because another register may have [dsub_0,
+ // dsub_1, dsub_2] subregs without necessarily having a qsub_1 subreg. The
+ // dsub_2 -> ssub_0 composition can be shared.
+ while (!Indices.empty() && !Orphans.empty()) {
+ CodeGenSubRegIndex *Idx = Indices.pop_back_val();
+ CodeGenRegister *SR = SubRegs[Idx];
+ const SubRegMap &Map = SR->computeSubRegs(RegBank);
+ for (SubRegMap::const_iterator SI = Map.begin(), SE = Map.end(); SI != SE;
+ ++SI)
+ if (Orphans.erase(SI->second))
+ SubRegs[RegBank.getCompositeSubRegIndex(Idx, SI->first)] = SI->second;
+ }
+
+ // Compute the inverse SubReg -> Idx map.
+ for (SubRegMap::const_iterator SI = SubRegs.begin(), SE = SubRegs.end();
+ SI != SE; ++SI) {
+ if (SI->second == this) {
+ ArrayRef<SMLoc> Loc;
+ if (TheDef)
+ Loc = TheDef->getLoc();
+ PrintFatalError(Loc, "Register " + getName() +
+ " has itself as a sub-register");
+ }
+
+ // Compute AllSuperRegsCovered.
+ if (!CoveredBySubRegs)
+ SI->first->AllSuperRegsCovered = false;
+
+ // Ensure that every sub-register has a unique name.
+ DenseMap<const CodeGenRegister*, CodeGenSubRegIndex*>::iterator Ins =
+ SubReg2Idx.insert(std::make_pair(SI->second, SI->first)).first;
+ if (Ins->second == SI->first)
+ continue;
+ // Trouble: Two different names for SI->second.
+ ArrayRef<SMLoc> Loc;
+ if (TheDef)
+ Loc = TheDef->getLoc();
+ PrintFatalError(Loc, "Sub-register can't have two names: " +
+ SI->second->getName() + " available as " +
+ SI->first->getName() + " and " + Ins->second->getName());
+ }
+
+ // Derive possible names for sub-register concatenations from any explicit
+ // sub-registers. By doing this before computeSecondarySubRegs(), we ensure
+ // that getConcatSubRegIndex() won't invent any concatenated indices that the
+ // user already specified.
+ for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
+ CodeGenRegister *SR = ExplicitSubRegs[i];
+ if (!SR->CoveredBySubRegs || SR->ExplicitSubRegs.size() <= 1)
+ continue;
+
+ // SR is composed of multiple sub-regs. Find their names in this register.
+ SmallVector<CodeGenSubRegIndex*, 8> Parts;
+ for (unsigned j = 0, e = SR->ExplicitSubRegs.size(); j != e; ++j)
+ Parts.push_back(getSubRegIndex(SR->ExplicitSubRegs[j]));
+
+ // Offer this as an existing spelling for the concatenation of Parts.
+ RegBank.addConcatSubRegIndex(Parts, ExplicitSubRegIndices[i]);
+ }
+
+ // Initialize RegUnitList. Because getSubRegs is called recursively, this
+ // processes the register hierarchy in postorder.
+ //
+ // Inherit all sub-register units. It is good enough to look at the explicit
+ // sub-registers, the other registers won't contribute any more units.
+ for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
+ CodeGenRegister *SR = ExplicitSubRegs[i];
+ RegUnits |= SR->RegUnits;
+ }
+
+ // Absent any ad hoc aliasing, we create one register unit per leaf register.
+ // These units correspond to the maximal cliques in the register overlap
+ // graph which is optimal.
+ //
+ // When there is ad hoc aliasing, we simply create one unit per edge in the
+ // undirected ad hoc aliasing graph. Technically, we could do better by
+ // identifying maximal cliques in the ad hoc graph, but cliques larger than 2
+ // are extremely rare anyway (I've never seen one), so we don't bother with
+ // the added complexity.
+ for (unsigned i = 0, e = ExplicitAliases.size(); i != e; ++i) {
+ CodeGenRegister *AR = ExplicitAliases[i];
+ // Only visit each edge once.
+ if (AR->SubRegsComplete)
+ continue;
+ // Create a RegUnit representing this alias edge, and add it to both
+ // registers.
+ unsigned Unit = RegBank.newRegUnit(this, AR);
+ RegUnits.set(Unit);
+ AR->RegUnits.set(Unit);
+ }
+
+ // Finally, create units for leaf registers without ad hoc aliases. Note that
+ // a leaf register with ad hoc aliases doesn't get its own unit - it isn't
+ // necessary. This means the aliasing leaf registers can share a single unit.
+ if (RegUnits.empty())
+ RegUnits.set(RegBank.newRegUnit(this));
+
+ // We have now computed the native register units. More may be adopted later
+ // for balancing purposes.
+ NativeRegUnits = RegUnits;
+
+ return SubRegs;
+}
+
+// In a register that is covered by its sub-registers, try to find redundant
+// sub-registers. For example:
+//
+// QQ0 = {Q0, Q1}
+// Q0 = {D0, D1}
+// Q1 = {D2, D3}
+//
+// We can infer that D1_D2 is also a sub-register, even if it wasn't named in
+// the register definition.
+//
+// The explicitly specified registers form a tree. This function discovers
+// sub-register relationships that would force a DAG.
+//
+void CodeGenRegister::computeSecondarySubRegs(CodeGenRegBank &RegBank) {
+ // Collect new sub-registers first, add them later.
+ SmallVector<SubRegMap::value_type, 8> NewSubRegs;
+
+ // Look at the leading super-registers of each sub-register. Those are the
+ // candidates for new sub-registers, assuming they are fully contained in
+ // this register.
+ for (SubRegMap::iterator I = SubRegs.begin(), E = SubRegs.end(); I != E; ++I){
+ const CodeGenRegister *SubReg = I->second;
+ const CodeGenRegister::SuperRegList &Leads = SubReg->LeadingSuperRegs;
+ for (unsigned i = 0, e = Leads.size(); i != e; ++i) {
+ CodeGenRegister *Cand = const_cast<CodeGenRegister*>(Leads[i]);
+ // Already got this sub-register?
+ if (Cand == this || getSubRegIndex(Cand))
+ continue;
+ // Check if each component of Cand is already a sub-register.
+ // We know that the first component is I->second, and is present with the
+ // name I->first.
+ SmallVector<CodeGenSubRegIndex*, 8> Parts(1, I->first);
+ assert(!Cand->ExplicitSubRegs.empty() &&
+ "Super-register has no sub-registers");
+ for (unsigned j = 1, e = Cand->ExplicitSubRegs.size(); j != e; ++j) {
+ if (CodeGenSubRegIndex *Idx = getSubRegIndex(Cand->ExplicitSubRegs[j]))
+ Parts.push_back(Idx);
+ else {
+ // Sub-register doesn't exist.
+ Parts.clear();
+ break;
+ }
+ }
+ // If some Cand sub-register is not part of this register, or if Cand only
+ // has one sub-register, there is nothing to do.
+ if (Parts.size() <= 1)
+ continue;
+
+ // Each part of Cand is a sub-register of this. Make the full Cand also
+ // a sub-register with a concatenated sub-register index.
+ CodeGenSubRegIndex *Concat= RegBank.getConcatSubRegIndex(Parts);
+ NewSubRegs.push_back(std::make_pair(Concat, Cand));
+ }
+ }
+
+ // Now add all the new sub-registers.
+ for (unsigned i = 0, e = NewSubRegs.size(); i != e; ++i) {
+ // Don't add Cand if another sub-register is already using the index.
+ if (!SubRegs.insert(NewSubRegs[i]).second)
+ continue;
+
+ CodeGenSubRegIndex *NewIdx = NewSubRegs[i].first;
+ CodeGenRegister *NewSubReg = NewSubRegs[i].second;
+ SubReg2Idx.insert(std::make_pair(NewSubReg, NewIdx));
+ }
+
+ // Create sub-register index composition maps for the synthesized indices.
+ for (unsigned i = 0, e = NewSubRegs.size(); i != e; ++i) {
+ CodeGenSubRegIndex *NewIdx = NewSubRegs[i].first;
+ CodeGenRegister *NewSubReg = NewSubRegs[i].second;
+ for (SubRegMap::const_iterator SI = NewSubReg->SubRegs.begin(),
+ SE = NewSubReg->SubRegs.end(); SI != SE; ++SI) {
+ CodeGenSubRegIndex *SubIdx = getSubRegIndex(SI->second);
+ if (!SubIdx)
+ PrintFatalError(TheDef->getLoc(), "No SubRegIndex for " +
+ SI->second->getName() + " in " + getName());
+ NewIdx->addComposite(SI->first, SubIdx);
+ }
+ }
+}
+
+void CodeGenRegister::computeSuperRegs(CodeGenRegBank &RegBank) {
+ // Only visit each register once.
+ if (SuperRegsComplete)
+ return;
+ SuperRegsComplete = true;
+
+ // Make sure all sub-registers have been visited first, so the super-reg
+ // lists will be topologically ordered.
+ for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
+ I != E; ++I)
+ I->second->computeSuperRegs(RegBank);
+
+ // Now add this as a super-register on all sub-registers.
+ // Also compute the TopoSigId in post-order.
+ TopoSigId Id;
+ for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
+ I != E; ++I) {
+ // Topological signature computed from SubIdx, TopoId(SubReg).
+ // Loops and idempotent indices have TopoSig = ~0u.
+ Id.push_back(I->first->EnumValue);
+ Id.push_back(I->second->TopoSig);
+
+ // Don't add duplicate entries.
+ if (!I->second->SuperRegs.empty() && I->second->SuperRegs.back() == this)
+ continue;
+ I->second->SuperRegs.push_back(this);
+ }
+ TopoSig = RegBank.getTopoSig(Id);
+}
+
+void
+CodeGenRegister::addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet,
+ CodeGenRegBank &RegBank) const {
+ assert(SubRegsComplete && "Must precompute sub-registers");
+ for (unsigned i = 0, e = ExplicitSubRegs.size(); i != e; ++i) {
+ CodeGenRegister *SR = ExplicitSubRegs[i];
+ if (OSet.insert(SR))
+ SR->addSubRegsPreOrder(OSet, RegBank);
+ }
+ // Add any secondary sub-registers that weren't part of the explicit tree.
+ for (SubRegMap::const_iterator I = SubRegs.begin(), E = SubRegs.end();
+ I != E; ++I)
+ OSet.insert(I->second);
+}
+
+// Get the sum of this register's unit weights.
+unsigned CodeGenRegister::getWeight(const CodeGenRegBank &RegBank) const {
+ unsigned Weight = 0;
+ for (RegUnitList::iterator I = RegUnits.begin(), E = RegUnits.end();
+ I != E; ++I) {
+ Weight += RegBank.getRegUnit(*I).Weight;
+ }
+ return Weight;
+}
+
+//===----------------------------------------------------------------------===//
+// RegisterTuples
+//===----------------------------------------------------------------------===//
+
+// A RegisterTuples def is used to generate pseudo-registers from lists of
+// sub-registers. We provide a SetTheory expander class that returns the new
+// registers.
+namespace {
+
+struct TupleExpander : SetTheory::Expander {
+ void expand(SetTheory &ST, Record *Def, SetTheory::RecSet &Elts) override {
+ std::vector<Record*> Indices = Def->getValueAsListOfDefs("SubRegIndices");
+ unsigned Dim = Indices.size();
+ ListInit *SubRegs = Def->getValueAsListInit("SubRegs");
+ if (Dim != SubRegs->size())
+ PrintFatalError(Def->getLoc(), "SubRegIndices and SubRegs size mismatch");
+ if (Dim < 2)
+ PrintFatalError(Def->getLoc(),
+ "Tuples must have at least 2 sub-registers");
+
+ // Evaluate the sub-register lists to be zipped.
+ unsigned Length = ~0u;
+ SmallVector<SetTheory::RecSet, 4> Lists(Dim);
+ for (unsigned i = 0; i != Dim; ++i) {
+ ST.evaluate(SubRegs->getElement(i), Lists[i], Def->getLoc());
+ Length = std::min(Length, unsigned(Lists[i].size()));
+ }
+
+ if (Length == 0)
+ return;
+
+ // Precompute some types.
+ Record *RegisterCl = Def->getRecords().getClass("Register");
+ RecTy *RegisterRecTy = RecordRecTy::get(RegisterCl);
+ StringInit *BlankName = StringInit::get("");
+
+ // Zip them up.
+ for (unsigned n = 0; n != Length; ++n) {
+ std::string Name;
+ Record *Proto = Lists[0][n];
+ std::vector<Init*> Tuple;
+ unsigned CostPerUse = 0;
+ for (unsigned i = 0; i != Dim; ++i) {
+ Record *Reg = Lists[i][n];
+ if (i) Name += '_';
+ Name += Reg->getName();
+ Tuple.push_back(DefInit::get(Reg));
+ CostPerUse = std::max(CostPerUse,
+ unsigned(Reg->getValueAsInt("CostPerUse")));
+ }
+
+ // Create a new Record representing the synthesized register. This record
+ // is only for consumption by CodeGenRegister, it is not added to the
+ // RecordKeeper.
+ Record *NewReg = new Record(Name, Def->getLoc(), Def->getRecords());
+ Elts.insert(NewReg);
+
+ // Copy Proto super-classes.
+ ArrayRef<std::pair<Record *, SMRange>> Supers = Proto->getSuperClasses();
+ for (const auto &SuperPair : Supers)
+ NewReg->addSuperClass(SuperPair.first, SuperPair.second);
+
+ // Copy Proto fields.
+ for (unsigned i = 0, e = Proto->getValues().size(); i != e; ++i) {
+ RecordVal RV = Proto->getValues()[i];
+
+ // Skip existing fields, like NAME.
+ if (NewReg->getValue(RV.getNameInit()))
+ continue;
+
+ StringRef Field = RV.getName();
+
+ // Replace the sub-register list with Tuple.
+ if (Field == "SubRegs")
+ RV.setValue(ListInit::get(Tuple, RegisterRecTy));
+
+ // Provide a blank AsmName. MC hacks are required anyway.
+ if (Field == "AsmName")
+ RV.setValue(BlankName);
+
+ // CostPerUse is aggregated from all Tuple members.
+ if (Field == "CostPerUse")
+ RV.setValue(IntInit::get(CostPerUse));
+
+ // Composite registers are always covered by sub-registers.
+ if (Field == "CoveredBySubRegs")
+ RV.setValue(BitInit::get(true));
+
+ // Copy fields from the RegisterTuples def.
+ if (Field == "SubRegIndices" ||
+ Field == "CompositeIndices") {
+ NewReg->addValue(*Def->getValue(Field));
+ continue;
+ }
+
+ // Some fields get their default uninitialized value.
+ if (Field == "DwarfNumbers" ||
+ Field == "DwarfAlias" ||
+ Field == "Aliases") {
+ if (const RecordVal *DefRV = RegisterCl->getValue(Field))
+ NewReg->addValue(*DefRV);
+ continue;
+ }
+
+ // Everything else is copied from Proto.
+ NewReg->addValue(RV);
+ }
+ }
+ }
+};
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// CodeGenRegisterClass
+//===----------------------------------------------------------------------===//
+
+static void sortAndUniqueRegisters(CodeGenRegister::Vec &M) {
+ std::sort(M.begin(), M.end(), deref<llvm::less>());
+ M.erase(std::unique(M.begin(), M.end(), deref<llvm::equal>()), M.end());
+}
+
+CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank, Record *R)
+ : TheDef(R),
+ Name(R->getName()),
+ TopoSigs(RegBank.getNumTopoSigs()),
+ EnumValue(-1) {
+ // Rename anonymous register classes.
+ if (R->getName().size() > 9 && R->getName()[9] == '.') {
+ static unsigned AnonCounter = 0;
+ R->setName("AnonRegClass_" + utostr(AnonCounter++));
+ }
+
+ std::vector<Record*> TypeList = R->getValueAsListOfDefs("RegTypes");
+ for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
+ Record *Type = TypeList[i];
+ if (!Type->isSubClassOf("ValueType"))
+ PrintFatalError("RegTypes list member '" + Type->getName() +
+ "' does not derive from the ValueType class!");
+ VTs.push_back(getValueType(Type));
+ }
+ assert(!VTs.empty() && "RegisterClass must contain at least one ValueType!");
+
+ // Allocation order 0 is the full set. AltOrders provides others.
+ const SetTheory::RecVec *Elements = RegBank.getSets().expand(R);
+ ListInit *AltOrders = R->getValueAsListInit("AltOrders");
+ Orders.resize(1 + AltOrders->size());
+
+ // Default allocation order always contains all registers.
+ for (unsigned i = 0, e = Elements->size(); i != e; ++i) {
+ Orders[0].push_back((*Elements)[i]);
+ const CodeGenRegister *Reg = RegBank.getReg((*Elements)[i]);
+ Members.push_back(Reg);
+ TopoSigs.set(Reg->getTopoSig());
+ }
+ sortAndUniqueRegisters(Members);
+
+ // Alternative allocation orders may be subsets.
+ SetTheory::RecSet Order;
+ for (unsigned i = 0, e = AltOrders->size(); i != e; ++i) {
+ RegBank.getSets().evaluate(AltOrders->getElement(i), Order, R->getLoc());
+ Orders[1 + i].append(Order.begin(), Order.end());
+ // Verify that all altorder members are regclass members.
+ while (!Order.empty()) {
+ CodeGenRegister *Reg = RegBank.getReg(Order.back());
+ Order.pop_back();
+ if (!contains(Reg))
+ PrintFatalError(R->getLoc(), " AltOrder register " + Reg->getName() +
+ " is not a class member");
+ }
+ }
+
+ // Allow targets to override the size in bits of the RegisterClass.
+ unsigned Size = R->getValueAsInt("Size");
+
+ Namespace = R->getValueAsString("Namespace");
+ SpillSize = Size ? Size : MVT(VTs[0]).getSizeInBits();
+ SpillAlignment = R->getValueAsInt("Alignment");
+ CopyCost = R->getValueAsInt("CopyCost");
+ Allocatable = R->getValueAsBit("isAllocatable");
+ AltOrderSelect = R->getValueAsString("AltOrderSelect");
+ int AllocationPriority = R->getValueAsInt("AllocationPriority");
+ if (AllocationPriority < 0 || AllocationPriority > 63)
+ PrintFatalError(R->getLoc(), "AllocationPriority out of range [0,63]");
+ this->AllocationPriority = AllocationPriority;
+}
+
+// Create an inferred register class that was missing from the .td files.
+// Most properties will be inherited from the closest super-class after the
+// class structure has been computed.
+CodeGenRegisterClass::CodeGenRegisterClass(CodeGenRegBank &RegBank,
+ StringRef Name, Key Props)
+ : Members(*Props.Members),
+ TheDef(nullptr),
+ Name(Name),
+ TopoSigs(RegBank.getNumTopoSigs()),
+ EnumValue(-1),
+ SpillSize(Props.SpillSize),
+ SpillAlignment(Props.SpillAlignment),
+ CopyCost(0),
+ Allocatable(true),
+ AllocationPriority(0) {
+ for (const auto R : Members)
+ TopoSigs.set(R->getTopoSig());
+}
+
+// Compute inherited propertied for a synthesized register class.
+void CodeGenRegisterClass::inheritProperties(CodeGenRegBank &RegBank) {
+ assert(!getDef() && "Only synthesized classes can inherit properties");
+ assert(!SuperClasses.empty() && "Synthesized class without super class");
+
+ // The last super-class is the smallest one.
+ CodeGenRegisterClass &Super = *SuperClasses.back();
+
+ // Most properties are copied directly.
+ // Exceptions are members, size, and alignment
+ Namespace = Super.Namespace;
+ VTs = Super.VTs;
+ CopyCost = Super.CopyCost;
+ Allocatable = Super.Allocatable;
+ AltOrderSelect = Super.AltOrderSelect;
+ AllocationPriority = Super.AllocationPriority;
+
+ // Copy all allocation orders, filter out foreign registers from the larger
+ // super-class.
+ Orders.resize(Super.Orders.size());
+ for (unsigned i = 0, ie = Super.Orders.size(); i != ie; ++i)
+ for (unsigned j = 0, je = Super.Orders[i].size(); j != je; ++j)
+ if (contains(RegBank.getReg(Super.Orders[i][j])))
+ Orders[i].push_back(Super.Orders[i][j]);
+}
+
+bool CodeGenRegisterClass::contains(const CodeGenRegister *Reg) const {
+ return std::binary_search(Members.begin(), Members.end(), Reg,
+ deref<llvm::less>());
+}
+
+namespace llvm {
+
+ raw_ostream &operator<<(raw_ostream &OS, const CodeGenRegisterClass::Key &K) {
+ OS << "{ S=" << K.SpillSize << ", A=" << K.SpillAlignment;
+ for (const auto R : *K.Members)
+ OS << ", " << R->getName();
+ return OS << " }";
+ }
+
+} // end namespace llvm
+
+// This is a simple lexicographical order that can be used to search for sets.
+// It is not the same as the topological order provided by TopoOrderRC.
+bool CodeGenRegisterClass::Key::
+operator<(const CodeGenRegisterClass::Key &B) const {
+ assert(Members && B.Members);
+ return std::tie(*Members, SpillSize, SpillAlignment) <
+ std::tie(*B.Members, B.SpillSize, B.SpillAlignment);
+}
+
+// Returns true if RC is a strict subclass.
+// RC is a sub-class of this class if it is a valid replacement for any
+// instruction operand where a register of this classis required. It must
+// satisfy these conditions:
+//
+// 1. All RC registers are also in this.
+// 2. The RC spill size must not be smaller than our spill size.
+// 3. RC spill alignment must be compatible with ours.
+//
+static bool testSubClass(const CodeGenRegisterClass *A,
+ const CodeGenRegisterClass *B) {
+ return A->SpillAlignment && B->SpillAlignment % A->SpillAlignment == 0 &&
+ A->SpillSize <= B->SpillSize &&
+ std::includes(A->getMembers().begin(), A->getMembers().end(),
+ B->getMembers().begin(), B->getMembers().end(),
+ deref<llvm::less>());
+}
+
+/// Sorting predicate for register classes. This provides a topological
+/// ordering that arranges all register classes before their sub-classes.
+///
+/// Register classes with the same registers, spill size, and alignment form a
+/// clique. They will be ordered alphabetically.
+///
+static bool TopoOrderRC(const CodeGenRegisterClass &PA,
+ const CodeGenRegisterClass &PB) {
+ auto *A = &PA;
+ auto *B = &PB;
+ if (A == B)
+ return false;
+
+ // Order by ascending spill size.
+ if (A->SpillSize < B->SpillSize)
+ return true;
+ if (A->SpillSize > B->SpillSize)
+ return false;
+
+ // Order by ascending spill alignment.
+ if (A->SpillAlignment < B->SpillAlignment)
+ return true;
+ if (A->SpillAlignment > B->SpillAlignment)
+ return false;
+
+ // Order by descending set size. Note that the classes' allocation order may
+ // not have been computed yet. The Members set is always vaild.
+ if (A->getMembers().size() > B->getMembers().size())
+ return true;
+ if (A->getMembers().size() < B->getMembers().size())
+ return false;
+
+ // Finally order by name as a tie breaker.
+ return StringRef(A->getName()) < B->getName();
+}
+
+std::string CodeGenRegisterClass::getQualifiedName() const {
+ if (Namespace.empty())
+ return getName();
+ else
+ return Namespace + "::" + getName();
+}
+
+// Compute sub-classes of all register classes.
+// Assume the classes are ordered topologically.
+void CodeGenRegisterClass::computeSubClasses(CodeGenRegBank &RegBank) {
+ auto &RegClasses = RegBank.getRegClasses();
+
+ // Visit backwards so sub-classes are seen first.
+ for (auto I = RegClasses.rbegin(), E = RegClasses.rend(); I != E; ++I) {
+ CodeGenRegisterClass &RC = *I;
+ RC.SubClasses.resize(RegClasses.size());
+ RC.SubClasses.set(RC.EnumValue);
+
+ // Normally, all subclasses have IDs >= rci, unless RC is part of a clique.
+ for (auto I2 = I.base(), E2 = RegClasses.end(); I2 != E2; ++I2) {
+ CodeGenRegisterClass &SubRC = *I2;
+ if (RC.SubClasses.test(SubRC.EnumValue))
+ continue;
+ if (!testSubClass(&RC, &SubRC))
+ continue;
+ // SubRC is a sub-class. Grap all its sub-classes so we won't have to
+ // check them again.
+ RC.SubClasses |= SubRC.SubClasses;
+ }
+
+ // Sweep up missed clique members. They will be immediately preceding RC.
+ for (auto I2 = std::next(I); I2 != E && testSubClass(&RC, &*I2); ++I2)
+ RC.SubClasses.set(I2->EnumValue);
+ }
+
+ // Compute the SuperClasses lists from the SubClasses vectors.
+ for (auto &RC : RegClasses) {
+ const BitVector &SC = RC.getSubClasses();
+ auto I = RegClasses.begin();
+ for (int s = 0, next_s = SC.find_first(); next_s != -1;
+ next_s = SC.find_next(s)) {
+ std::advance(I, next_s - s);
+ s = next_s;
+ if (&*I == &RC)
+ continue;
+ I->SuperClasses.push_back(&RC);
+ }
+ }
+
+ // With the class hierarchy in place, let synthesized register classes inherit
+ // properties from their closest super-class. The iteration order here can
+ // propagate properties down multiple levels.
+ for (auto &RC : RegClasses)
+ if (!RC.getDef())
+ RC.inheritProperties(RegBank);
+}
+
+void CodeGenRegisterClass::getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
+ BitVector &Out) const {
+ auto FindI = SuperRegClasses.find(SubIdx);
+ if (FindI == SuperRegClasses.end())
+ return;
+ for (CodeGenRegisterClass *RC : FindI->second)
+ Out.set(RC->EnumValue);
+}
+
+// Populate a unique sorted list of units from a register set.
+void CodeGenRegisterClass::buildRegUnitSet(
+ std::vector<unsigned> &RegUnits) const {
+ std::vector<unsigned> TmpUnits;
+ for (RegUnitIterator UnitI(Members); UnitI.isValid(); ++UnitI)
+ TmpUnits.push_back(*UnitI);
+ std::sort(TmpUnits.begin(), TmpUnits.end());
+ std::unique_copy(TmpUnits.begin(), TmpUnits.end(),
+ std::back_inserter(RegUnits));
+}
+
+//===----------------------------------------------------------------------===//
+// CodeGenRegBank
+//===----------------------------------------------------------------------===//
+
+CodeGenRegBank::CodeGenRegBank(RecordKeeper &Records) {
+ // Configure register Sets to understand register classes and tuples.
+ Sets.addFieldExpander("RegisterClass", "MemberList");
+ Sets.addFieldExpander("CalleeSavedRegs", "SaveList");
+ Sets.addExpander("RegisterTuples", llvm::make_unique<TupleExpander>());
+
+ // Read in the user-defined (named) sub-register indices.
+ // More indices will be synthesized later.
+ std::vector<Record*> SRIs = Records.getAllDerivedDefinitions("SubRegIndex");
+ std::sort(SRIs.begin(), SRIs.end(), LessRecord());
+ for (unsigned i = 0, e = SRIs.size(); i != e; ++i)
+ getSubRegIdx(SRIs[i]);
+ // Build composite maps from ComposedOf fields.
+ for (auto &Idx : SubRegIndices)
+ Idx.updateComponents(*this);
+
+ // Read in the register definitions.
+ std::vector<Record*> Regs = Records.getAllDerivedDefinitions("Register");
+ std::sort(Regs.begin(), Regs.end(), LessRecordRegister());
+ // Assign the enumeration values.
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i)
+ getReg(Regs[i]);
+
+ // Expand tuples and number the new registers.
+ std::vector<Record*> Tups =
+ Records.getAllDerivedDefinitions("RegisterTuples");
+
+ for (Record *R : Tups) {
+ std::vector<Record *> TupRegs = *Sets.expand(R);
+ std::sort(TupRegs.begin(), TupRegs.end(), LessRecordRegister());
+ for (Record *RC : TupRegs)
+ getReg(RC);
+ }
+
+ // Now all the registers are known. Build the object graph of explicit
+ // register-register references.
+ for (auto &Reg : Registers)
+ Reg.buildObjectGraph(*this);
+
+ // Compute register name map.
+ for (auto &Reg : Registers)
+ // FIXME: This could just be RegistersByName[name] = register, except that
+ // causes some failures in MIPS - perhaps they have duplicate register name
+ // entries? (or maybe there's a reason for it - I don't know much about this
+ // code, just drive-by refactoring)
+ RegistersByName.insert(
+ std::make_pair(Reg.TheDef->getValueAsString("AsmName"), &Reg));
+
+ // Precompute all sub-register maps.
+ // This will create Composite entries for all inferred sub-register indices.
+ for (auto &Reg : Registers)
+ Reg.computeSubRegs(*this);
+
+ // Infer even more sub-registers by combining leading super-registers.
+ for (auto &Reg : Registers)
+ if (Reg.CoveredBySubRegs)
+ Reg.computeSecondarySubRegs(*this);
+
+ // After the sub-register graph is complete, compute the topologically
+ // ordered SuperRegs list.
+ for (auto &Reg : Registers)
+ Reg.computeSuperRegs(*this);
+
+ // Native register units are associated with a leaf register. They've all been
+ // discovered now.
+ NumNativeRegUnits = RegUnits.size();
+
+ // Read in register class definitions.
+ std::vector<Record*> RCs = Records.getAllDerivedDefinitions("RegisterClass");
+ if (RCs.empty())
+ PrintFatalError("No 'RegisterClass' subclasses defined!");
+
+ // Allocate user-defined register classes.
+ for (auto *RC : RCs) {
+ RegClasses.emplace_back(*this, RC);
+ addToMaps(&RegClasses.back());
+ }
+
+ // Infer missing classes to create a full algebra.
+ computeInferredRegisterClasses();
+
+ // Order register classes topologically and assign enum values.
+ RegClasses.sort(TopoOrderRC);
+ unsigned i = 0;
+ for (auto &RC : RegClasses)
+ RC.EnumValue = i++;
+ CodeGenRegisterClass::computeSubClasses(*this);
+}
+
+// Create a synthetic CodeGenSubRegIndex without a corresponding Record.
+CodeGenSubRegIndex*
+CodeGenRegBank::createSubRegIndex(StringRef Name, StringRef Namespace) {
+ SubRegIndices.emplace_back(Name, Namespace, SubRegIndices.size() + 1);
+ return &SubRegIndices.back();
+}
+
+CodeGenSubRegIndex *CodeGenRegBank::getSubRegIdx(Record *Def) {
+ CodeGenSubRegIndex *&Idx = Def2SubRegIdx[Def];
+ if (Idx)
+ return Idx;
+ SubRegIndices.emplace_back(Def, SubRegIndices.size() + 1);
+ Idx = &SubRegIndices.back();
+ return Idx;
+}
+
+CodeGenRegister *CodeGenRegBank::getReg(Record *Def) {
+ CodeGenRegister *&Reg = Def2Reg[Def];
+ if (Reg)
+ return Reg;
+ Registers.emplace_back(Def, Registers.size() + 1);
+ Reg = &Registers.back();
+ return Reg;
+}
+
+void CodeGenRegBank::addToMaps(CodeGenRegisterClass *RC) {
+ if (Record *Def = RC->getDef())
+ Def2RC.insert(std::make_pair(Def, RC));
+
+ // Duplicate classes are rejected by insert().
+ // That's OK, we only care about the properties handled by CGRC::Key.
+ CodeGenRegisterClass::Key K(*RC);
+ Key2RC.insert(std::make_pair(K, RC));
+}
+
+// Create a synthetic sub-class if it is missing.
+CodeGenRegisterClass*
+CodeGenRegBank::getOrCreateSubClass(const CodeGenRegisterClass *RC,
+ const CodeGenRegister::Vec *Members,
+ StringRef Name) {
+ // Synthetic sub-class has the same size and alignment as RC.
+ CodeGenRegisterClass::Key K(Members, RC->SpillSize, RC->SpillAlignment);
+ RCKeyMap::const_iterator FoundI = Key2RC.find(K);
+ if (FoundI != Key2RC.end())
+ return FoundI->second;
+
+ // Sub-class doesn't exist, create a new one.
+ RegClasses.emplace_back(*this, Name, K);
+ addToMaps(&RegClasses.back());
+ return &RegClasses.back();
+}
+
+CodeGenRegisterClass *CodeGenRegBank::getRegClass(Record *Def) {
+ if (CodeGenRegisterClass *RC = Def2RC[Def])
+ return RC;
+
+ PrintFatalError(Def->getLoc(), "Not a known RegisterClass!");
+}
+
+CodeGenSubRegIndex*
+CodeGenRegBank::getCompositeSubRegIndex(CodeGenSubRegIndex *A,
+ CodeGenSubRegIndex *B) {
+ // Look for an existing entry.
+ CodeGenSubRegIndex *Comp = A->compose(B);
+ if (Comp)
+ return Comp;
+
+ // None exists, synthesize one.
+ std::string Name = A->getName() + "_then_" + B->getName();
+ Comp = createSubRegIndex(Name, A->getNamespace());
+ A->addComposite(B, Comp);
+ return Comp;
+}
+
+CodeGenSubRegIndex *CodeGenRegBank::
+getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &Parts) {
+ assert(Parts.size() > 1 && "Need two parts to concatenate");
+
+ // Look for an existing entry.
+ CodeGenSubRegIndex *&Idx = ConcatIdx[Parts];
+ if (Idx)
+ return Idx;
+
+ // None exists, synthesize one.
+ std::string Name = Parts.front()->getName();
+ // Determine whether all parts are contiguous.
+ bool isContinuous = true;
+ unsigned Size = Parts.front()->Size;
+ unsigned LastOffset = Parts.front()->Offset;
+ unsigned LastSize = Parts.front()->Size;
+ for (unsigned i = 1, e = Parts.size(); i != e; ++i) {
+ Name += '_';
+ Name += Parts[i]->getName();
+ Size += Parts[i]->Size;
+ if (Parts[i]->Offset != (LastOffset + LastSize))
+ isContinuous = false;
+ LastOffset = Parts[i]->Offset;
+ LastSize = Parts[i]->Size;
+ }
+ Idx = createSubRegIndex(Name, Parts.front()->getNamespace());
+ Idx->Size = Size;
+ Idx->Offset = isContinuous ? Parts.front()->Offset : -1;
+ return Idx;
+}
+
+void CodeGenRegBank::computeComposites() {
+ // Keep track of TopoSigs visited. We only need to visit each TopoSig once,
+ // and many registers will share TopoSigs on regular architectures.
+ BitVector TopoSigs(getNumTopoSigs());
+
+ for (const auto &Reg1 : Registers) {
+ // Skip identical subreg structures already processed.
+ if (TopoSigs.test(Reg1.getTopoSig()))
+ continue;
+ TopoSigs.set(Reg1.getTopoSig());
+
+ const CodeGenRegister::SubRegMap &SRM1 = Reg1.getSubRegs();
+ for (CodeGenRegister::SubRegMap::const_iterator i1 = SRM1.begin(),
+ e1 = SRM1.end(); i1 != e1; ++i1) {
+ CodeGenSubRegIndex *Idx1 = i1->first;
+ CodeGenRegister *Reg2 = i1->second;
+ // Ignore identity compositions.
+ if (&Reg1 == Reg2)
+ continue;
+ const CodeGenRegister::SubRegMap &SRM2 = Reg2->getSubRegs();
+ // Try composing Idx1 with another SubRegIndex.
+ for (CodeGenRegister::SubRegMap::const_iterator i2 = SRM2.begin(),
+ e2 = SRM2.end(); i2 != e2; ++i2) {
+ CodeGenSubRegIndex *Idx2 = i2->first;
+ CodeGenRegister *Reg3 = i2->second;
+ // Ignore identity compositions.
+ if (Reg2 == Reg3)
+ continue;
+ // OK Reg1:IdxPair == Reg3. Find the index with Reg:Idx == Reg3.
+ CodeGenSubRegIndex *Idx3 = Reg1.getSubRegIndex(Reg3);
+ assert(Idx3 && "Sub-register doesn't have an index");
+
+ // Conflicting composition? Emit a warning but allow it.
+ if (CodeGenSubRegIndex *Prev = Idx1->addComposite(Idx2, Idx3))
+ PrintWarning(Twine("SubRegIndex ") + Idx1->getQualifiedName() +
+ " and " + Idx2->getQualifiedName() +
+ " compose ambiguously as " + Prev->getQualifiedName() +
+ " or " + Idx3->getQualifiedName());
+ }
+ }
+ }
+}
+
+// Compute lane masks. This is similar to register units, but at the
+// sub-register index level. Each bit in the lane mask is like a register unit
+// class, and two lane masks will have a bit in common if two sub-register
+// indices overlap in some register.
+//
+// Conservatively share a lane mask bit if two sub-register indices overlap in
+// some registers, but not in others. That shouldn't happen a lot.
+void CodeGenRegBank::computeSubRegLaneMasks() {
+ // First assign individual bits to all the leaf indices.
+ unsigned Bit = 0;
+ // Determine mask of lanes that cover their registers.
+ CoveringLanes = LaneBitmask::getAll();
+ for (auto &Idx : SubRegIndices) {
+ if (Idx.getComposites().empty()) {
+ if (Bit > 32) {
+ PrintFatalError(
+ Twine("Ran out of lanemask bits to represent subregister ")
+ + Idx.getName());
+ }
+ Idx.LaneMask = LaneBitmask(1 << Bit);
+ ++Bit;
+ } else {
+ Idx.LaneMask = LaneBitmask::getNone();
+ }
+ }
+
+ // Compute transformation sequences for composeSubRegIndexLaneMask. The idea
+ // here is that for each possible target subregister we look at the leafs
+ // in the subregister graph that compose for this target and create
+ // transformation sequences for the lanemasks. Each step in the sequence
+ // consists of a bitmask and a bitrotate operation. As the rotation amounts
+ // are usually the same for many subregisters we can easily combine the steps
+ // by combining the masks.
+ for (const auto &Idx : SubRegIndices) {
+ const auto &Composites = Idx.getComposites();
+ auto &LaneTransforms = Idx.CompositionLaneMaskTransform;
+
+ if (Composites.empty()) {
+ // Moving from a class with no subregisters we just had a single lane:
+ // The subregister must be a leaf subregister and only occupies 1 bit.
+ // Move the bit from the class without subregisters into that position.
+ static_assert(sizeof(Idx.LaneMask.getAsInteger()) == 4,
+ "Change Log2_32 to a proper one");
+ unsigned DstBit = Log2_32(Idx.LaneMask.getAsInteger());
+ assert(Idx.LaneMask == LaneBitmask(1 << DstBit) &&
+ "Must be a leaf subregister");
+ MaskRolPair MaskRol = { LaneBitmask(1), (uint8_t)DstBit };
+ LaneTransforms.push_back(MaskRol);
+ } else {
+ // Go through all leaf subregisters and find the ones that compose with
+ // Idx. These make out all possible valid bits in the lane mask we want to
+ // transform. Looking only at the leafs ensure that only a single bit in
+ // the mask is set.
+ unsigned NextBit = 0;
+ for (auto &Idx2 : SubRegIndices) {
+ // Skip non-leaf subregisters.
+ if (!Idx2.getComposites().empty())
+ continue;
+ // Replicate the behaviour from the lane mask generation loop above.
+ unsigned SrcBit = NextBit;
+ LaneBitmask SrcMask = LaneBitmask(1 << SrcBit);
+ if (NextBit < LaneBitmask::BitWidth-1)
+ ++NextBit;
+ assert(Idx2.LaneMask == SrcMask);
+
+ // Get the composed subregister if there is any.
+ auto C = Composites.find(&Idx2);
+ if (C == Composites.end())
+ continue;
+ const CodeGenSubRegIndex *Composite = C->second;
+ // The Composed subreg should be a leaf subreg too
+ assert(Composite->getComposites().empty());
+
+ // Create Mask+Rotate operation and merge with existing ops if possible.
+ static_assert(sizeof(Composite->LaneMask.getAsInteger()) == 4,
+ "Change Log2_32 to a proper one");
+ unsigned DstBit = Log2_32(Composite->LaneMask.getAsInteger());
+ int Shift = DstBit - SrcBit;
+ uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift
+ : LaneBitmask::BitWidth + Shift;
+ for (auto &I : LaneTransforms) {
+ if (I.RotateLeft == RotateLeft) {
+ I.Mask |= SrcMask;
+ SrcMask = LaneBitmask::getNone();
+ }
+ }
+ if (SrcMask.any()) {
+ MaskRolPair MaskRol = { SrcMask, RotateLeft };
+ LaneTransforms.push_back(MaskRol);
+ }
+ }
+ }
+
+ // Optimize if the transformation consists of one step only: Set mask to
+ // 0xffffffff (including some irrelevant invalid bits) so that it should
+ // merge with more entries later while compressing the table.
+ if (LaneTransforms.size() == 1)
+ LaneTransforms[0].Mask = LaneBitmask::getAll();
+
+ // Further compression optimization: For invalid compositions resulting
+ // in a sequence with 0 entries we can just pick any other. Choose
+ // Mask 0xffffffff with Rotation 0.
+ if (LaneTransforms.size() == 0) {
+ MaskRolPair P = { LaneBitmask::getAll(), 0 };
+ LaneTransforms.push_back(P);
+ }
+ }
+
+ // FIXME: What if ad-hoc aliasing introduces overlaps that aren't represented
+ // by the sub-register graph? This doesn't occur in any known targets.
+
+ // Inherit lanes from composites.
+ for (const auto &Idx : SubRegIndices) {
+ LaneBitmask Mask = Idx.computeLaneMask();
+ // If some super-registers without CoveredBySubRegs use this index, we can
+ // no longer assume that the lanes are covering their registers.
+ if (!Idx.AllSuperRegsCovered)
+ CoveringLanes &= ~Mask;
+ }
+
+ // Compute lane mask combinations for register classes.
+ for (auto &RegClass : RegClasses) {
+ LaneBitmask LaneMask;
+ for (const auto &SubRegIndex : SubRegIndices) {
+ if (RegClass.getSubClassWithSubReg(&SubRegIndex) == nullptr)
+ continue;
+ LaneMask |= SubRegIndex.LaneMask;
+ }
+
+ // For classes without any subregisters set LaneMask to 1 instead of 0.
+ // This makes it easier for client code to handle classes uniformly.
+ if (LaneMask.none())
+ LaneMask = LaneBitmask(1);
+
+ RegClass.LaneMask = LaneMask;
+ }
+}
+
+namespace {
+
+// UberRegSet is a helper class for computeRegUnitWeights. Each UberRegSet is
+// the transitive closure of the union of overlapping register
+// classes. Together, the UberRegSets form a partition of the registers. If we
+// consider overlapping register classes to be connected, then each UberRegSet
+// is a set of connected components.
+//
+// An UberRegSet will likely be a horizontal slice of register names of
+// the same width. Nontrivial subregisters should then be in a separate
+// UberRegSet. But this property isn't required for valid computation of
+// register unit weights.
+//
+// A Weight field caches the max per-register unit weight in each UberRegSet.
+//
+// A set of SingularDeterminants flags single units of some register in this set
+// for which the unit weight equals the set weight. These units should not have
+// their weight increased.
+struct UberRegSet {
+ CodeGenRegister::Vec Regs;
+ unsigned Weight = 0;
+ CodeGenRegister::RegUnitList SingularDeterminants;
+
+ UberRegSet() = default;
+};
+
+} // end anonymous namespace
+
+// Partition registers into UberRegSets, where each set is the transitive
+// closure of the union of overlapping register classes.
+//
+// UberRegSets[0] is a special non-allocatable set.
+static void computeUberSets(std::vector<UberRegSet> &UberSets,
+ std::vector<UberRegSet*> &RegSets,
+ CodeGenRegBank &RegBank) {
+ const auto &Registers = RegBank.getRegisters();
+
+ // The Register EnumValue is one greater than its index into Registers.
+ assert(Registers.size() == Registers.back().EnumValue &&
+ "register enum value mismatch");
+
+ // For simplicitly make the SetID the same as EnumValue.
+ IntEqClasses UberSetIDs(Registers.size()+1);
+ std::set<unsigned> AllocatableRegs;
+ for (auto &RegClass : RegBank.getRegClasses()) {
+ if (!RegClass.Allocatable)
+ continue;
+
+ const CodeGenRegister::Vec &Regs = RegClass.getMembers();
+ if (Regs.empty())
+ continue;
+
+ unsigned USetID = UberSetIDs.findLeader((*Regs.begin())->EnumValue);
+ assert(USetID && "register number 0 is invalid");
+
+ AllocatableRegs.insert((*Regs.begin())->EnumValue);
+ for (auto I = std::next(Regs.begin()), E = Regs.end(); I != E; ++I) {
+ AllocatableRegs.insert((*I)->EnumValue);
+ UberSetIDs.join(USetID, (*I)->EnumValue);
+ }
+ }
+ // Combine non-allocatable regs.
+ for (const auto &Reg : Registers) {
+ unsigned RegNum = Reg.EnumValue;
+ if (AllocatableRegs.count(RegNum))
+ continue;
+
+ UberSetIDs.join(0, RegNum);
+ }
+ UberSetIDs.compress();
+
+ // Make the first UberSet a special unallocatable set.
+ unsigned ZeroID = UberSetIDs[0];
+
+ // Insert Registers into the UberSets formed by union-find.
+ // Do not resize after this.
+ UberSets.resize(UberSetIDs.getNumClasses());
+ unsigned i = 0;
+ for (const CodeGenRegister &Reg : Registers) {
+ unsigned USetID = UberSetIDs[Reg.EnumValue];
+ if (!USetID)
+ USetID = ZeroID;
+ else if (USetID == ZeroID)
+ USetID = 0;
+
+ UberRegSet *USet = &UberSets[USetID];
+ USet->Regs.push_back(&Reg);
+ sortAndUniqueRegisters(USet->Regs);
+ RegSets[i++] = USet;
+ }
+}
+
+// Recompute each UberSet weight after changing unit weights.
+static void computeUberWeights(std::vector<UberRegSet> &UberSets,
+ CodeGenRegBank &RegBank) {
+ // Skip the first unallocatable set.
+ for (std::vector<UberRegSet>::iterator I = std::next(UberSets.begin()),
+ E = UberSets.end(); I != E; ++I) {
+
+ // Initialize all unit weights in this set, and remember the max units/reg.
+ const CodeGenRegister *Reg = nullptr;
+ unsigned MaxWeight = 0, Weight = 0;
+ for (RegUnitIterator UnitI(I->Regs); UnitI.isValid(); ++UnitI) {
+ if (Reg != UnitI.getReg()) {
+ if (Weight > MaxWeight)
+ MaxWeight = Weight;
+ Reg = UnitI.getReg();
+ Weight = 0;
+ }
+ unsigned UWeight = RegBank.getRegUnit(*UnitI).Weight;
+ if (!UWeight) {
+ UWeight = 1;
+ RegBank.increaseRegUnitWeight(*UnitI, UWeight);
+ }
+ Weight += UWeight;
+ }
+ if (Weight > MaxWeight)
+ MaxWeight = Weight;
+ if (I->Weight != MaxWeight) {
+ DEBUG(
+ dbgs() << "UberSet " << I - UberSets.begin() << " Weight " << MaxWeight;
+ for (auto &Unit : I->Regs)
+ dbgs() << " " << Unit->getName();
+ dbgs() << "\n");
+ // Update the set weight.
+ I->Weight = MaxWeight;
+ }
+
+ // Find singular determinants.
+ for (const auto R : I->Regs) {
+ if (R->getRegUnits().count() == 1 && R->getWeight(RegBank) == I->Weight) {
+ I->SingularDeterminants |= R->getRegUnits();
+ }
+ }
+ }
+}
+
+// normalizeWeight is a computeRegUnitWeights helper that adjusts the weight of
+// a register and its subregisters so that they have the same weight as their
+// UberSet. Self-recursion processes the subregister tree in postorder so
+// subregisters are normalized first.
+//
+// Side effects:
+// - creates new adopted register units
+// - causes superregisters to inherit adopted units
+// - increases the weight of "singular" units
+// - induces recomputation of UberWeights.
+static bool normalizeWeight(CodeGenRegister *Reg,
+ std::vector<UberRegSet> &UberSets,
+ std::vector<UberRegSet*> &RegSets,
+ SparseBitVector<> &NormalRegs,
+ CodeGenRegister::RegUnitList &NormalUnits,
+ CodeGenRegBank &RegBank) {
+ if (NormalRegs.test(Reg->EnumValue))
+ return false;
+ NormalRegs.set(Reg->EnumValue);
+
+ bool Changed = false;
+ const CodeGenRegister::SubRegMap &SRM = Reg->getSubRegs();
+ for (CodeGenRegister::SubRegMap::const_iterator SRI = SRM.begin(),
+ SRE = SRM.end(); SRI != SRE; ++SRI) {
+ if (SRI->second == Reg)
+ continue; // self-cycles happen
+
+ Changed |= normalizeWeight(SRI->second, UberSets, RegSets,
+ NormalRegs, NormalUnits, RegBank);
+ }
+ // Postorder register normalization.
+
+ // Inherit register units newly adopted by subregisters.
+ if (Reg->inheritRegUnits(RegBank))
+ computeUberWeights(UberSets, RegBank);
+
+ // Check if this register is too skinny for its UberRegSet.
+ UberRegSet *UberSet = RegSets[RegBank.getRegIndex(Reg)];
+
+ unsigned RegWeight = Reg->getWeight(RegBank);
+ if (UberSet->Weight > RegWeight) {
+ // A register unit's weight can be adjusted only if it is the singular unit
+ // for this register, has not been used to normalize a subregister's set,
+ // and has not already been used to singularly determine this UberRegSet.
+ unsigned AdjustUnit = *Reg->getRegUnits().begin();
+ if (Reg->getRegUnits().count() != 1
+ || hasRegUnit(NormalUnits, AdjustUnit)
+ || hasRegUnit(UberSet->SingularDeterminants, AdjustUnit)) {
+ // We don't have an adjustable unit, so adopt a new one.
+ AdjustUnit = RegBank.newRegUnit(UberSet->Weight - RegWeight);
+ Reg->adoptRegUnit(AdjustUnit);
+ // Adopting a unit does not immediately require recomputing set weights.
+ }
+ else {
+ // Adjust the existing single unit.
+ RegBank.increaseRegUnitWeight(AdjustUnit, UberSet->Weight - RegWeight);
+ // The unit may be shared among sets and registers within this set.
+ computeUberWeights(UberSets, RegBank);
+ }
+ Changed = true;
+ }
+
+ // Mark these units normalized so superregisters can't change their weights.
+ NormalUnits |= Reg->getRegUnits();
+
+ return Changed;
+}
+
+// Compute a weight for each register unit created during getSubRegs.
+//
+// The goal is that two registers in the same class will have the same weight,
+// where each register's weight is defined as sum of its units' weights.
+void CodeGenRegBank::computeRegUnitWeights() {
+ std::vector<UberRegSet> UberSets;
+ std::vector<UberRegSet*> RegSets(Registers.size());
+ computeUberSets(UberSets, RegSets, *this);
+ // UberSets and RegSets are now immutable.
+
+ computeUberWeights(UberSets, *this);
+
+ // Iterate over each Register, normalizing the unit weights until reaching
+ // a fix point.
+ unsigned NumIters = 0;
+ for (bool Changed = true; Changed; ++NumIters) {
+ assert(NumIters <= NumNativeRegUnits && "Runaway register unit weights");
+ Changed = false;
+ for (auto &Reg : Registers) {
+ CodeGenRegister::RegUnitList NormalUnits;
+ SparseBitVector<> NormalRegs;
+ Changed |= normalizeWeight(&Reg, UberSets, RegSets, NormalRegs,
+ NormalUnits, *this);
+ }
+ }
+}
+
+// Find a set in UniqueSets with the same elements as Set.
+// Return an iterator into UniqueSets.
+static std::vector<RegUnitSet>::const_iterator
+findRegUnitSet(const std::vector<RegUnitSet> &UniqueSets,
+ const RegUnitSet &Set) {
+ std::vector<RegUnitSet>::const_iterator
+ I = UniqueSets.begin(), E = UniqueSets.end();
+ for(;I != E; ++I) {
+ if (I->Units == Set.Units)
+ break;
+ }
+ return I;
+}
+
+// Return true if the RUSubSet is a subset of RUSuperSet.
+static bool isRegUnitSubSet(const std::vector<unsigned> &RUSubSet,
+ const std::vector<unsigned> &RUSuperSet) {
+ return std::includes(RUSuperSet.begin(), RUSuperSet.end(),
+ RUSubSet.begin(), RUSubSet.end());
+}
+
+/// Iteratively prune unit sets. Prune subsets that are close to the superset,
+/// but with one or two registers removed. We occasionally have registers like
+/// APSR and PC thrown in with the general registers. We also see many
+/// special-purpose register subsets, such as tail-call and Thumb
+/// encodings. Generating all possible overlapping sets is combinatorial and
+/// overkill for modeling pressure. Ideally we could fix this statically in
+/// tablegen by (1) having the target define register classes that only include
+/// the allocatable registers and marking other classes as non-allocatable and
+/// (2) having a way to mark special purpose classes as "don't-care" classes for
+/// the purpose of pressure. However, we make an attempt to handle targets that
+/// are not nicely defined by merging nearly identical register unit sets
+/// statically. This generates smaller tables. Then, dynamically, we adjust the
+/// set limit by filtering the reserved registers.
+///
+/// Merge sets only if the units have the same weight. For example, on ARM,
+/// Q-tuples with ssub index 0 include all S regs but also include D16+. We
+/// should not expand the S set to include D regs.
+void CodeGenRegBank::pruneUnitSets() {
+ assert(RegClassUnitSets.empty() && "this invalidates RegClassUnitSets");
+
+ // Form an equivalence class of UnitSets with no significant difference.
+ std::vector<unsigned> SuperSetIDs;
+ for (unsigned SubIdx = 0, EndIdx = RegUnitSets.size();
+ SubIdx != EndIdx; ++SubIdx) {
+ const RegUnitSet &SubSet = RegUnitSets[SubIdx];
+ unsigned SuperIdx = 0;
+ for (; SuperIdx != EndIdx; ++SuperIdx) {
+ if (SuperIdx == SubIdx)
+ continue;
+
+ unsigned UnitWeight = RegUnits[SubSet.Units[0]].Weight;
+ const RegUnitSet &SuperSet = RegUnitSets[SuperIdx];
+ if (isRegUnitSubSet(SubSet.Units, SuperSet.Units)
+ && (SubSet.Units.size() + 3 > SuperSet.Units.size())
+ && UnitWeight == RegUnits[SuperSet.Units[0]].Weight
+ && UnitWeight == RegUnits[SuperSet.Units.back()].Weight) {
+ DEBUG(dbgs() << "UnitSet " << SubIdx << " subsumed by " << SuperIdx
+ << "\n");
+ // We can pick any of the set names for the merged set. Go for the
+ // shortest one to avoid picking the name of one of the classes that are
+ // artificially created by tablegen. So "FPR128_lo" instead of
+ // "QQQQ_with_qsub3_in_FPR128_lo".
+ if (RegUnitSets[SubIdx].Name.size() < RegUnitSets[SuperIdx].Name.size())
+ RegUnitSets[SuperIdx].Name = RegUnitSets[SubIdx].Name;
+ break;
+ }
+ }
+ if (SuperIdx == EndIdx)
+ SuperSetIDs.push_back(SubIdx);
+ }
+ // Populate PrunedUnitSets with each equivalence class's superset.
+ std::vector<RegUnitSet> PrunedUnitSets(SuperSetIDs.size());
+ for (unsigned i = 0, e = SuperSetIDs.size(); i != e; ++i) {
+ unsigned SuperIdx = SuperSetIDs[i];
+ PrunedUnitSets[i].Name = RegUnitSets[SuperIdx].Name;
+ PrunedUnitSets[i].Units.swap(RegUnitSets[SuperIdx].Units);
+ }
+ RegUnitSets.swap(PrunedUnitSets);
+}
+
+// Create a RegUnitSet for each RegClass that contains all units in the class
+// including adopted units that are necessary to model register pressure. Then
+// iteratively compute RegUnitSets such that the union of any two overlapping
+// RegUnitSets is repreresented.
+//
+// RegisterInfoEmitter will map each RegClass to its RegUnitClass and any
+// RegUnitSet that is a superset of that RegUnitClass.
+void CodeGenRegBank::computeRegUnitSets() {
+ assert(RegUnitSets.empty() && "dirty RegUnitSets");
+
+ // Compute a unique RegUnitSet for each RegClass.
+ auto &RegClasses = getRegClasses();
+ for (auto &RC : RegClasses) {
+ if (!RC.Allocatable)
+ continue;
+
+ // Speculatively grow the RegUnitSets to hold the new set.
+ RegUnitSets.resize(RegUnitSets.size() + 1);
+ RegUnitSets.back().Name = RC.getName();
+
+ // Compute a sorted list of units in this class.
+ RC.buildRegUnitSet(RegUnitSets.back().Units);
+
+ // Find an existing RegUnitSet.
+ std::vector<RegUnitSet>::const_iterator SetI =
+ findRegUnitSet(RegUnitSets, RegUnitSets.back());
+ if (SetI != std::prev(RegUnitSets.end()))
+ RegUnitSets.pop_back();
+ }
+
+ DEBUG(dbgs() << "\nBefore pruning:\n";
+ for (unsigned USIdx = 0, USEnd = RegUnitSets.size();
+ USIdx < USEnd; ++USIdx) {
+ dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name
+ << ":";
+ for (auto &U : RegUnitSets[USIdx].Units)
+ printRegUnitName(U);
+ dbgs() << "\n";
+ });
+
+ // Iteratively prune unit sets.
+ pruneUnitSets();
+
+ DEBUG(dbgs() << "\nBefore union:\n";
+ for (unsigned USIdx = 0, USEnd = RegUnitSets.size();
+ USIdx < USEnd; ++USIdx) {
+ dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name
+ << ":";
+ for (auto &U : RegUnitSets[USIdx].Units)
+ printRegUnitName(U);
+ dbgs() << "\n";
+ }
+ dbgs() << "\nUnion sets:\n");
+
+ // Iterate over all unit sets, including new ones added by this loop.
+ unsigned NumRegUnitSubSets = RegUnitSets.size();
+ for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx) {
+ // In theory, this is combinatorial. In practice, it needs to be bounded
+ // by a small number of sets for regpressure to be efficient.
+ // If the assert is hit, we need to implement pruning.
+ assert(Idx < (2*NumRegUnitSubSets) && "runaway unit set inference");
+
+ // Compare new sets with all original classes.
+ for (unsigned SearchIdx = (Idx >= NumRegUnitSubSets) ? 0 : Idx+1;
+ SearchIdx != EndIdx; ++SearchIdx) {
+ std::set<unsigned> Intersection;
+ std::set_intersection(RegUnitSets[Idx].Units.begin(),
+ RegUnitSets[Idx].Units.end(),
+ RegUnitSets[SearchIdx].Units.begin(),
+ RegUnitSets[SearchIdx].Units.end(),
+ std::inserter(Intersection, Intersection.begin()));
+ if (Intersection.empty())
+ continue;
+
+ // Speculatively grow the RegUnitSets to hold the new set.
+ RegUnitSets.resize(RegUnitSets.size() + 1);
+ RegUnitSets.back().Name =
+ RegUnitSets[Idx].Name + "+" + RegUnitSets[SearchIdx].Name;
+
+ std::set_union(RegUnitSets[Idx].Units.begin(),
+ RegUnitSets[Idx].Units.end(),
+ RegUnitSets[SearchIdx].Units.begin(),
+ RegUnitSets[SearchIdx].Units.end(),
+ std::inserter(RegUnitSets.back().Units,
+ RegUnitSets.back().Units.begin()));
+
+ // Find an existing RegUnitSet, or add the union to the unique sets.
+ std::vector<RegUnitSet>::const_iterator SetI =
+ findRegUnitSet(RegUnitSets, RegUnitSets.back());
+ if (SetI != std::prev(RegUnitSets.end()))
+ RegUnitSets.pop_back();
+ else {
+ DEBUG(dbgs() << "UnitSet " << RegUnitSets.size()-1
+ << " " << RegUnitSets.back().Name << ":";
+ for (auto &U : RegUnitSets.back().Units)
+ printRegUnitName(U);
+ dbgs() << "\n";);
+ }
+ }
+ }
+
+ // Iteratively prune unit sets after inferring supersets.
+ pruneUnitSets();
+
+ DEBUG(dbgs() << "\n";
+ for (unsigned USIdx = 0, USEnd = RegUnitSets.size();
+ USIdx < USEnd; ++USIdx) {
+ dbgs() << "UnitSet " << USIdx << " " << RegUnitSets[USIdx].Name
+ << ":";
+ for (auto &U : RegUnitSets[USIdx].Units)
+ printRegUnitName(U);
+ dbgs() << "\n";
+ });
+
+ // For each register class, list the UnitSets that are supersets.
+ RegClassUnitSets.resize(RegClasses.size());
+ int RCIdx = -1;
+ for (auto &RC : RegClasses) {
+ ++RCIdx;
+ if (!RC.Allocatable)
+ continue;
+
+ // Recompute the sorted list of units in this class.
+ std::vector<unsigned> RCRegUnits;
+ RC.buildRegUnitSet(RCRegUnits);
+
+ // Don't increase pressure for unallocatable regclasses.
+ if (RCRegUnits.empty())
+ continue;
+
+ DEBUG(dbgs() << "RC " << RC.getName() << " Units: \n";
+ for (auto U : RCRegUnits)
+ printRegUnitName(U);
+ dbgs() << "\n UnitSetIDs:");
+
+ // Find all supersets.
+ for (unsigned USIdx = 0, USEnd = RegUnitSets.size();
+ USIdx != USEnd; ++USIdx) {
+ if (isRegUnitSubSet(RCRegUnits, RegUnitSets[USIdx].Units)) {
+ DEBUG(dbgs() << " " << USIdx);
+ RegClassUnitSets[RCIdx].push_back(USIdx);
+ }
+ }
+ DEBUG(dbgs() << "\n");
+ assert(!RegClassUnitSets[RCIdx].empty() && "missing unit set for regclass");
+ }
+
+ // For each register unit, ensure that we have the list of UnitSets that
+ // contain the unit. Normally, this matches an existing list of UnitSets for a
+ // register class. If not, we create a new entry in RegClassUnitSets as a
+ // "fake" register class.
+ for (unsigned UnitIdx = 0, UnitEnd = NumNativeRegUnits;
+ UnitIdx < UnitEnd; ++UnitIdx) {
+ std::vector<unsigned> RUSets;
+ for (unsigned i = 0, e = RegUnitSets.size(); i != e; ++i) {
+ RegUnitSet &RUSet = RegUnitSets[i];
+ if (!is_contained(RUSet.Units, UnitIdx))
+ continue;
+ RUSets.push_back(i);
+ }
+ unsigned RCUnitSetsIdx = 0;
+ for (unsigned e = RegClassUnitSets.size();
+ RCUnitSetsIdx != e; ++RCUnitSetsIdx) {
+ if (RegClassUnitSets[RCUnitSetsIdx] == RUSets) {
+ break;
+ }
+ }
+ RegUnits[UnitIdx].RegClassUnitSetsIdx = RCUnitSetsIdx;
+ if (RCUnitSetsIdx == RegClassUnitSets.size()) {
+ // Create a new list of UnitSets as a "fake" register class.
+ RegClassUnitSets.resize(RCUnitSetsIdx + 1);
+ RegClassUnitSets[RCUnitSetsIdx].swap(RUSets);
+ }
+ }
+}
+
+void CodeGenRegBank::computeRegUnitLaneMasks() {
+ for (auto &Register : Registers) {
+ // Create an initial lane mask for all register units.
+ const auto &RegUnits = Register.getRegUnits();
+ CodeGenRegister::RegUnitLaneMaskList
+ RegUnitLaneMasks(RegUnits.count(), LaneBitmask::getNone());
+ // Iterate through SubRegisters.
+ typedef CodeGenRegister::SubRegMap SubRegMap;
+ const SubRegMap &SubRegs = Register.getSubRegs();
+ for (SubRegMap::const_iterator S = SubRegs.begin(),
+ SE = SubRegs.end(); S != SE; ++S) {
+ CodeGenRegister *SubReg = S->second;
+ // Ignore non-leaf subregisters, their lane masks are fully covered by
+ // the leaf subregisters anyway.
+ if (!SubReg->getSubRegs().empty())
+ continue;
+ CodeGenSubRegIndex *SubRegIndex = S->first;
+ const CodeGenRegister *SubRegister = S->second;
+ LaneBitmask LaneMask = SubRegIndex->LaneMask;
+ // Distribute LaneMask to Register Units touched.
+ for (unsigned SUI : SubRegister->getRegUnits()) {
+ bool Found = false;
+ unsigned u = 0;
+ for (unsigned RU : RegUnits) {
+ if (SUI == RU) {
+ RegUnitLaneMasks[u] |= LaneMask;
+ assert(!Found);
+ Found = true;
+ }
+ ++u;
+ }
+ (void)Found;
+ assert(Found);
+ }
+ }
+ Register.setRegUnitLaneMasks(RegUnitLaneMasks);
+ }
+}
+
+void CodeGenRegBank::computeDerivedInfo() {
+ computeComposites();
+ computeSubRegLaneMasks();
+
+ // Compute a weight for each register unit created during getSubRegs.
+ // This may create adopted register units (with unit # >= NumNativeRegUnits).
+ computeRegUnitWeights();
+
+ // Compute a unique set of RegUnitSets. One for each RegClass and inferred
+ // supersets for the union of overlapping sets.
+ computeRegUnitSets();
+
+ computeRegUnitLaneMasks();
+
+ // Compute register class HasDisjunctSubRegs/CoveredBySubRegs flag.
+ for (CodeGenRegisterClass &RC : RegClasses) {
+ RC.HasDisjunctSubRegs = false;
+ RC.CoveredBySubRegs = true;
+ for (const CodeGenRegister *Reg : RC.getMembers()) {
+ RC.HasDisjunctSubRegs |= Reg->HasDisjunctSubRegs;
+ RC.CoveredBySubRegs &= Reg->CoveredBySubRegs;
+ }
+ }
+
+ // Get the weight of each set.
+ for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx)
+ RegUnitSets[Idx].Weight = getRegUnitSetWeight(RegUnitSets[Idx].Units);
+
+ // Find the order of each set.
+ RegUnitSetOrder.reserve(RegUnitSets.size());
+ for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx)
+ RegUnitSetOrder.push_back(Idx);
+
+ std::stable_sort(RegUnitSetOrder.begin(), RegUnitSetOrder.end(),
+ [this](unsigned ID1, unsigned ID2) {
+ return getRegPressureSet(ID1).Units.size() <
+ getRegPressureSet(ID2).Units.size();
+ });
+ for (unsigned Idx = 0, EndIdx = RegUnitSets.size(); Idx != EndIdx; ++Idx) {
+ RegUnitSets[RegUnitSetOrder[Idx]].Order = Idx;
+ }
+}
+
+//
+// Synthesize missing register class intersections.
+//
+// Make sure that sub-classes of RC exists such that getCommonSubClass(RC, X)
+// returns a maximal register class for all X.
+//
+void CodeGenRegBank::inferCommonSubClass(CodeGenRegisterClass *RC) {
+ assert(!RegClasses.empty());
+ // Stash the iterator to the last element so that this loop doesn't visit
+ // elements added by the getOrCreateSubClass call within it.
+ for (auto I = RegClasses.begin(), E = std::prev(RegClasses.end());
+ I != std::next(E); ++I) {
+ CodeGenRegisterClass *RC1 = RC;
+ CodeGenRegisterClass *RC2 = &*I;
+ if (RC1 == RC2)
+ continue;
+
+ // Compute the set intersection of RC1 and RC2.
+ const CodeGenRegister::Vec &Memb1 = RC1->getMembers();
+ const CodeGenRegister::Vec &Memb2 = RC2->getMembers();
+ CodeGenRegister::Vec Intersection;
+ std::set_intersection(
+ Memb1.begin(), Memb1.end(), Memb2.begin(), Memb2.end(),
+ std::inserter(Intersection, Intersection.begin()), deref<llvm::less>());
+
+ // Skip disjoint class pairs.
+ if (Intersection.empty())
+ continue;
+
+ // If RC1 and RC2 have different spill sizes or alignments, use the
+ // larger size for sub-classing. If they are equal, prefer RC1.
+ if (RC2->SpillSize > RC1->SpillSize ||
+ (RC2->SpillSize == RC1->SpillSize &&
+ RC2->SpillAlignment > RC1->SpillAlignment))
+ std::swap(RC1, RC2);
+
+ getOrCreateSubClass(RC1, &Intersection,
+ RC1->getName() + "_and_" + RC2->getName());
+ }
+}
+
+//
+// Synthesize missing sub-classes for getSubClassWithSubReg().
+//
+// Make sure that the set of registers in RC with a given SubIdx sub-register
+// form a register class. Update RC->SubClassWithSubReg.
+//
+void CodeGenRegBank::inferSubClassWithSubReg(CodeGenRegisterClass *RC) {
+ // Map SubRegIndex to set of registers in RC supporting that SubRegIndex.
+ typedef std::map<const CodeGenSubRegIndex *, CodeGenRegister::Vec,
+ deref<llvm::less>> SubReg2SetMap;
+
+ // Compute the set of registers supporting each SubRegIndex.
+ SubReg2SetMap SRSets;
+ for (const auto R : RC->getMembers()) {
+ const CodeGenRegister::SubRegMap &SRM = R->getSubRegs();
+ for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
+ E = SRM.end(); I != E; ++I)
+ SRSets[I->first].push_back(R);
+ }
+
+ for (auto I : SRSets)
+ sortAndUniqueRegisters(I.second);
+
+ // Find matching classes for all SRSets entries. Iterate in SubRegIndex
+ // numerical order to visit synthetic indices last.
+ for (const auto &SubIdx : SubRegIndices) {
+ SubReg2SetMap::const_iterator I = SRSets.find(&SubIdx);
+ // Unsupported SubRegIndex. Skip it.
+ if (I == SRSets.end())
+ continue;
+ // In most cases, all RC registers support the SubRegIndex.
+ if (I->second.size() == RC->getMembers().size()) {
+ RC->setSubClassWithSubReg(&SubIdx, RC);
+ continue;
+ }
+ // This is a real subset. See if we have a matching class.
+ CodeGenRegisterClass *SubRC =
+ getOrCreateSubClass(RC, &I->second,
+ RC->getName() + "_with_" + I->first->getName());
+ RC->setSubClassWithSubReg(&SubIdx, SubRC);
+ }
+}
+
+//
+// Synthesize missing sub-classes of RC for getMatchingSuperRegClass().
+//
+// Create sub-classes of RC such that getMatchingSuperRegClass(RC, SubIdx, X)
+// has a maximal result for any SubIdx and any X >= FirstSubRegRC.
+//
+
+void CodeGenRegBank::inferMatchingSuperRegClass(CodeGenRegisterClass *RC,
+ std::list<CodeGenRegisterClass>::iterator FirstSubRegRC) {
+ SmallVector<std::pair<const CodeGenRegister*,
+ const CodeGenRegister*>, 16> SSPairs;
+ BitVector TopoSigs(getNumTopoSigs());
+
+ // Iterate in SubRegIndex numerical order to visit synthetic indices last.
+ for (auto &SubIdx : SubRegIndices) {
+ // Skip indexes that aren't fully supported by RC's registers. This was
+ // computed by inferSubClassWithSubReg() above which should have been
+ // called first.
+ if (RC->getSubClassWithSubReg(&SubIdx) != RC)
+ continue;
+
+ // Build list of (Super, Sub) pairs for this SubIdx.
+ SSPairs.clear();
+ TopoSigs.reset();
+ for (const auto Super : RC->getMembers()) {
+ const CodeGenRegister *Sub = Super->getSubRegs().find(&SubIdx)->second;
+ assert(Sub && "Missing sub-register");
+ SSPairs.push_back(std::make_pair(Super, Sub));
+ TopoSigs.set(Sub->getTopoSig());
+ }
+
+ // Iterate over sub-register class candidates. Ignore classes created by
+ // this loop. They will never be useful.
+ // Store an iterator to the last element (not end) so that this loop doesn't
+ // visit newly inserted elements.
+ assert(!RegClasses.empty());
+ for (auto I = FirstSubRegRC, E = std::prev(RegClasses.end());
+ I != std::next(E); ++I) {
+ CodeGenRegisterClass &SubRC = *I;
+ // Topological shortcut: SubRC members have the wrong shape.
+ if (!TopoSigs.anyCommon(SubRC.getTopoSigs()))
+ continue;
+ // Compute the subset of RC that maps into SubRC.
+ CodeGenRegister::Vec SubSetVec;
+ for (unsigned i = 0, e = SSPairs.size(); i != e; ++i)
+ if (SubRC.contains(SSPairs[i].second))
+ SubSetVec.push_back(SSPairs[i].first);
+
+ if (SubSetVec.empty())
+ continue;
+
+ // RC injects completely into SubRC.
+ sortAndUniqueRegisters(SubSetVec);
+ if (SubSetVec.size() == SSPairs.size()) {
+ SubRC.addSuperRegClass(&SubIdx, RC);
+ continue;
+ }
+
+ // Only a subset of RC maps into SubRC. Make sure it is represented by a
+ // class.
+ getOrCreateSubClass(RC, &SubSetVec, RC->getName() + "_with_" +
+ SubIdx.getName() + "_in_" +
+ SubRC.getName());
+ }
+ }
+}
+
+//
+// Infer missing register classes.
+//
+void CodeGenRegBank::computeInferredRegisterClasses() {
+ assert(!RegClasses.empty());
+ // When this function is called, the register classes have not been sorted
+ // and assigned EnumValues yet. That means getSubClasses(),
+ // getSuperClasses(), and hasSubClass() functions are defunct.
+
+ // Use one-before-the-end so it doesn't move forward when new elements are
+ // added.
+ auto FirstNewRC = std::prev(RegClasses.end());
+
+ // Visit all register classes, including the ones being added by the loop.
+ // Watch out for iterator invalidation here.
+ for (auto I = RegClasses.begin(), E = RegClasses.end(); I != E; ++I) {
+ CodeGenRegisterClass *RC = &*I;
+
+ // Synthesize answers for getSubClassWithSubReg().
+ inferSubClassWithSubReg(RC);
+
+ // Synthesize answers for getCommonSubClass().
+ inferCommonSubClass(RC);
+
+ // Synthesize answers for getMatchingSuperRegClass().
+ inferMatchingSuperRegClass(RC);
+
+ // New register classes are created while this loop is running, and we need
+ // to visit all of them. I particular, inferMatchingSuperRegClass needs
+ // to match old super-register classes with sub-register classes created
+ // after inferMatchingSuperRegClass was called. At this point,
+ // inferMatchingSuperRegClass has checked SuperRC = [0..rci] with SubRC =
+ // [0..FirstNewRC). We need to cover SubRC = [FirstNewRC..rci].
+ if (I == FirstNewRC) {
+ auto NextNewRC = std::prev(RegClasses.end());
+ for (auto I2 = RegClasses.begin(), E2 = std::next(FirstNewRC); I2 != E2;
+ ++I2)
+ inferMatchingSuperRegClass(&*I2, E2);
+ FirstNewRC = NextNewRC;
+ }
+ }
+}
+
+/// getRegisterClassForRegister - Find the register class that contains the
+/// specified physical register. If the register is not in a register class,
+/// return null. If the register is in multiple classes, and the classes have a
+/// superset-subset relationship and the same set of types, return the
+/// superclass. Otherwise return null.
+const CodeGenRegisterClass*
+CodeGenRegBank::getRegClassForRegister(Record *R) {
+ const CodeGenRegister *Reg = getReg(R);
+ const CodeGenRegisterClass *FoundRC = nullptr;
+ for (const auto &RC : getRegClasses()) {
+ if (!RC.contains(Reg))
+ continue;
+
+ // If this is the first class that contains the register,
+ // make a note of it and go on to the next class.
+ if (!FoundRC) {
+ FoundRC = &RC;
+ continue;
+ }
+
+ // If a register's classes have different types, return null.
+ if (RC.getValueTypes() != FoundRC->getValueTypes())
+ return nullptr;
+
+ // Check to see if the previously found class that contains
+ // the register is a subclass of the current class. If so,
+ // prefer the superclass.
+ if (RC.hasSubClass(FoundRC)) {
+ FoundRC = &RC;
+ continue;
+ }
+
+ // Check to see if the previously found class that contains
+ // the register is a superclass of the current class. If so,
+ // prefer the superclass.
+ if (FoundRC->hasSubClass(&RC))
+ continue;
+
+ // Multiple classes, and neither is a superclass of the other.
+ // Return null.
+ return nullptr;
+ }
+ return FoundRC;
+}
+
+BitVector CodeGenRegBank::computeCoveredRegisters(ArrayRef<Record*> Regs) {
+ SetVector<const CodeGenRegister*> Set;
+
+ // First add Regs with all sub-registers.
+ for (unsigned i = 0, e = Regs.size(); i != e; ++i) {
+ CodeGenRegister *Reg = getReg(Regs[i]);
+ if (Set.insert(Reg))
+ // Reg is new, add all sub-registers.
+ // The pre-ordering is not important here.
+ Reg->addSubRegsPreOrder(Set, *this);
+ }
+
+ // Second, find all super-registers that are completely covered by the set.
+ for (unsigned i = 0; i != Set.size(); ++i) {
+ const CodeGenRegister::SuperRegList &SR = Set[i]->getSuperRegs();
+ for (unsigned j = 0, e = SR.size(); j != e; ++j) {
+ const CodeGenRegister *Super = SR[j];
+ if (!Super->CoveredBySubRegs || Set.count(Super))
+ continue;
+ // This new super-register is covered by its sub-registers.
+ bool AllSubsInSet = true;
+ const CodeGenRegister::SubRegMap &SRM = Super->getSubRegs();
+ for (CodeGenRegister::SubRegMap::const_iterator I = SRM.begin(),
+ E = SRM.end(); I != E; ++I)
+ if (!Set.count(I->second)) {
+ AllSubsInSet = false;
+ break;
+ }
+ // All sub-registers in Set, add Super as well.
+ // We will visit Super later to recheck its super-registers.
+ if (AllSubsInSet)
+ Set.insert(Super);
+ }
+ }
+
+ // Convert to BitVector.
+ BitVector BV(Registers.size() + 1);
+ for (unsigned i = 0, e = Set.size(); i != e; ++i)
+ BV.set(Set[i]->EnumValue);
+ return BV;
+}
+
+void CodeGenRegBank::printRegUnitName(unsigned Unit) const {
+ if (Unit < NumNativeRegUnits)
+ dbgs() << ' ' << RegUnits[Unit].Roots[0]->getName();
+ else
+ dbgs() << " #" << Unit;
+}
diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h
new file mode 100644
index 000000000000..9366838c77cd
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h
@@ -0,0 +1,746 @@
+//===- CodeGenRegisters.h - Register and RegisterClass Info -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines structures to encapsulate information gleaned from the
+// target register and register class definitions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H
+#define LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SparseBitVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/MC/LaneBitmask.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/SetTheory.h"
+#include <cassert>
+#include <cstdint>
+#include <deque>
+#include <list>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+ class CodeGenRegBank;
+ template <typename T, typename Vector, typename Set> class SetVector;
+
+ /// Used to encode a step in a register lane mask transformation.
+ /// Mask the bits specified in Mask, then rotate them Rol bits to the left
+ /// assuming a wraparound at 32bits.
+ struct MaskRolPair {
+ LaneBitmask Mask;
+ uint8_t RotateLeft;
+
+ bool operator==(const MaskRolPair Other) const {
+ return Mask == Other.Mask && RotateLeft == Other.RotateLeft;
+ }
+ bool operator!=(const MaskRolPair Other) const {
+ return Mask != Other.Mask || RotateLeft != Other.RotateLeft;
+ }
+ };
+
+ /// CodeGenSubRegIndex - Represents a sub-register index.
+ class CodeGenSubRegIndex {
+ Record *const TheDef;
+ std::string Name;
+ std::string Namespace;
+
+ public:
+ uint16_t Size;
+ uint16_t Offset;
+ const unsigned EnumValue;
+ mutable LaneBitmask LaneMask;
+ mutable SmallVector<MaskRolPair,1> CompositionLaneMaskTransform;
+
+ // Are all super-registers containing this SubRegIndex covered by their
+ // sub-registers?
+ bool AllSuperRegsCovered;
+
+ CodeGenSubRegIndex(Record *R, unsigned Enum);
+ CodeGenSubRegIndex(StringRef N, StringRef Nspace, unsigned Enum);
+
+ const std::string &getName() const { return Name; }
+ const std::string &getNamespace() const { return Namespace; }
+ std::string getQualifiedName() const;
+
+ // Map of composite subreg indices.
+ typedef std::map<CodeGenSubRegIndex *, CodeGenSubRegIndex *,
+ deref<llvm::less>> CompMap;
+
+ // Returns the subreg index that results from composing this with Idx.
+ // Returns NULL if this and Idx don't compose.
+ CodeGenSubRegIndex *compose(CodeGenSubRegIndex *Idx) const {
+ CompMap::const_iterator I = Composed.find(Idx);
+ return I == Composed.end() ? nullptr : I->second;
+ }
+
+ // Add a composite subreg index: this+A = B.
+ // Return a conflicting composite, or NULL
+ CodeGenSubRegIndex *addComposite(CodeGenSubRegIndex *A,
+ CodeGenSubRegIndex *B) {
+ assert(A && B);
+ std::pair<CompMap::iterator, bool> Ins =
+ Composed.insert(std::make_pair(A, B));
+ // Synthetic subreg indices that aren't contiguous (for instance ARM
+ // register tuples) don't have a bit range, so it's OK to let
+ // B->Offset == -1. For the other cases, accumulate the offset and set
+ // the size here. Only do so if there is no offset yet though.
+ if ((Offset != (uint16_t)-1 && A->Offset != (uint16_t)-1) &&
+ (B->Offset == (uint16_t)-1)) {
+ B->Offset = Offset + A->Offset;
+ B->Size = A->Size;
+ }
+ return (Ins.second || Ins.first->second == B) ? nullptr
+ : Ins.first->second;
+ }
+
+ // Update the composite maps of components specified in 'ComposedOf'.
+ void updateComponents(CodeGenRegBank&);
+
+ // Return the map of composites.
+ const CompMap &getComposites() const { return Composed; }
+
+ // Compute LaneMask from Composed. Return LaneMask.
+ LaneBitmask computeLaneMask() const;
+
+ private:
+ CompMap Composed;
+ };
+
+ inline bool operator<(const CodeGenSubRegIndex &A,
+ const CodeGenSubRegIndex &B) {
+ return A.EnumValue < B.EnumValue;
+ }
+
+ /// CodeGenRegister - Represents a register definition.
+ struct CodeGenRegister {
+ Record *TheDef;
+ unsigned EnumValue;
+ unsigned CostPerUse;
+ bool CoveredBySubRegs;
+ bool HasDisjunctSubRegs;
+
+ // Map SubRegIndex -> Register.
+ typedef std::map<CodeGenSubRegIndex *, CodeGenRegister *, deref<llvm::less>>
+ SubRegMap;
+
+ CodeGenRegister(Record *R, unsigned Enum);
+
+ const StringRef getName() const;
+
+ // Extract more information from TheDef. This is used to build an object
+ // graph after all CodeGenRegister objects have been created.
+ void buildObjectGraph(CodeGenRegBank&);
+
+ // Lazily compute a map of all sub-registers.
+ // This includes unique entries for all sub-sub-registers.
+ const SubRegMap &computeSubRegs(CodeGenRegBank&);
+
+ // Compute extra sub-registers by combining the existing sub-registers.
+ void computeSecondarySubRegs(CodeGenRegBank&);
+
+ // Add this as a super-register to all sub-registers after the sub-register
+ // graph has been built.
+ void computeSuperRegs(CodeGenRegBank&);
+
+ const SubRegMap &getSubRegs() const {
+ assert(SubRegsComplete && "Must precompute sub-registers");
+ return SubRegs;
+ }
+
+ // Add sub-registers to OSet following a pre-order defined by the .td file.
+ void addSubRegsPreOrder(SetVector<const CodeGenRegister*> &OSet,
+ CodeGenRegBank&) const;
+
+ // Return the sub-register index naming Reg as a sub-register of this
+ // register. Returns NULL if Reg is not a sub-register.
+ CodeGenSubRegIndex *getSubRegIndex(const CodeGenRegister *Reg) const {
+ return SubReg2Idx.lookup(Reg);
+ }
+
+ typedef std::vector<const CodeGenRegister*> SuperRegList;
+
+ // Get the list of super-registers in topological order, small to large.
+ // This is valid after computeSubRegs visits all registers during RegBank
+ // construction.
+ const SuperRegList &getSuperRegs() const {
+ assert(SubRegsComplete && "Must precompute sub-registers");
+ return SuperRegs;
+ }
+
+ // Get the list of ad hoc aliases. The graph is symmetric, so the list
+ // contains all registers in 'Aliases', and all registers that mention this
+ // register in 'Aliases'.
+ ArrayRef<CodeGenRegister*> getExplicitAliases() const {
+ return ExplicitAliases;
+ }
+
+ // Get the topological signature of this register. This is a small integer
+ // less than RegBank.getNumTopoSigs(). Registers with the same TopoSig have
+ // identical sub-register structure. That is, they support the same set of
+ // sub-register indices mapping to the same kind of sub-registers
+ // (TopoSig-wise).
+ unsigned getTopoSig() const {
+ assert(SuperRegsComplete && "TopoSigs haven't been computed yet.");
+ return TopoSig;
+ }
+
+ // List of register units in ascending order.
+ typedef SparseBitVector<> RegUnitList;
+ typedef SmallVector<LaneBitmask, 16> RegUnitLaneMaskList;
+
+ // How many entries in RegUnitList are native?
+ RegUnitList NativeRegUnits;
+
+ // Get the list of register units.
+ // This is only valid after computeSubRegs() completes.
+ const RegUnitList &getRegUnits() const { return RegUnits; }
+
+ ArrayRef<LaneBitmask> getRegUnitLaneMasks() const {
+ return makeArrayRef(RegUnitLaneMasks).slice(0, NativeRegUnits.count());
+ }
+
+ // Get the native register units. This is a prefix of getRegUnits().
+ RegUnitList getNativeRegUnits() const {
+ return NativeRegUnits;
+ }
+
+ void setRegUnitLaneMasks(const RegUnitLaneMaskList &LaneMasks) {
+ RegUnitLaneMasks = LaneMasks;
+ }
+
+ // Inherit register units from subregisters.
+ // Return true if the RegUnits changed.
+ bool inheritRegUnits(CodeGenRegBank &RegBank);
+
+ // Adopt a register unit for pressure tracking.
+ // A unit is adopted iff its unit number is >= NativeRegUnits.count().
+ void adoptRegUnit(unsigned RUID) { RegUnits.set(RUID); }
+
+ // Get the sum of this register's register unit weights.
+ unsigned getWeight(const CodeGenRegBank &RegBank) const;
+
+ // Canonically ordered set.
+ typedef std::vector<const CodeGenRegister*> Vec;
+
+ private:
+ bool SubRegsComplete;
+ bool SuperRegsComplete;
+ unsigned TopoSig;
+
+ // The sub-registers explicit in the .td file form a tree.
+ SmallVector<CodeGenSubRegIndex*, 8> ExplicitSubRegIndices;
+ SmallVector<CodeGenRegister*, 8> ExplicitSubRegs;
+
+ // Explicit ad hoc aliases, symmetrized to form an undirected graph.
+ SmallVector<CodeGenRegister*, 8> ExplicitAliases;
+
+ // Super-registers where this is the first explicit sub-register.
+ SuperRegList LeadingSuperRegs;
+
+ SubRegMap SubRegs;
+ SuperRegList SuperRegs;
+ DenseMap<const CodeGenRegister*, CodeGenSubRegIndex*> SubReg2Idx;
+ RegUnitList RegUnits;
+ RegUnitLaneMaskList RegUnitLaneMasks;
+ };
+
+ inline bool operator<(const CodeGenRegister &A, const CodeGenRegister &B) {
+ return A.EnumValue < B.EnumValue;
+ }
+
+ inline bool operator==(const CodeGenRegister &A, const CodeGenRegister &B) {
+ return A.EnumValue == B.EnumValue;
+ }
+
+ class CodeGenRegisterClass {
+ CodeGenRegister::Vec Members;
+ // Allocation orders. Order[0] always contains all registers in Members.
+ std::vector<SmallVector<Record*, 16>> Orders;
+ // Bit mask of sub-classes including this, indexed by their EnumValue.
+ BitVector SubClasses;
+ // List of super-classes, topologocally ordered to have the larger classes
+ // first. This is the same as sorting by EnumValue.
+ SmallVector<CodeGenRegisterClass*, 4> SuperClasses;
+ Record *TheDef;
+ std::string Name;
+
+ // For a synthesized class, inherit missing properties from the nearest
+ // super-class.
+ void inheritProperties(CodeGenRegBank&);
+
+ // Map SubRegIndex -> sub-class. This is the largest sub-class where all
+ // registers have a SubRegIndex sub-register.
+ DenseMap<const CodeGenSubRegIndex *, CodeGenRegisterClass *>
+ SubClassWithSubReg;
+
+ // Map SubRegIndex -> set of super-reg classes. This is all register
+ // classes SuperRC such that:
+ //
+ // R:SubRegIndex in this RC for all R in SuperRC.
+ //
+ DenseMap<const CodeGenSubRegIndex *, SmallPtrSet<CodeGenRegisterClass *, 8>>
+ SuperRegClasses;
+
+ // Bit vector of TopoSigs for the registers in this class. This will be
+ // very sparse on regular architectures.
+ BitVector TopoSigs;
+
+ public:
+ unsigned EnumValue;
+ std::string Namespace;
+ SmallVector<MVT::SimpleValueType, 4> VTs;
+ unsigned SpillSize;
+ unsigned SpillAlignment;
+ int CopyCost;
+ bool Allocatable;
+ std::string AltOrderSelect;
+ uint8_t AllocationPriority;
+ /// Contains the combination of the lane masks of all subregisters.
+ LaneBitmask LaneMask;
+ /// True if there are at least 2 subregisters which do not interfere.
+ bool HasDisjunctSubRegs;
+ bool CoveredBySubRegs;
+
+ // Return the Record that defined this class, or NULL if the class was
+ // created by TableGen.
+ Record *getDef() const { return TheDef; }
+
+ const std::string &getName() const { return Name; }
+ std::string getQualifiedName() const;
+ ArrayRef<MVT::SimpleValueType> getValueTypes() const {return VTs;}
+ unsigned getNumValueTypes() const { return VTs.size(); }
+
+ MVT::SimpleValueType getValueTypeNum(unsigned VTNum) const {
+ if (VTNum < VTs.size())
+ return VTs[VTNum];
+ llvm_unreachable("VTNum greater than number of ValueTypes in RegClass!");
+ }
+
+ // Return true if this this class contains the register.
+ bool contains(const CodeGenRegister*) const;
+
+ // Returns true if RC is a subclass.
+ // RC is a sub-class of this class if it is a valid replacement for any
+ // instruction operand where a register of this classis required. It must
+ // satisfy these conditions:
+ //
+ // 1. All RC registers are also in this.
+ // 2. The RC spill size must not be smaller than our spill size.
+ // 3. RC spill alignment must be compatible with ours.
+ //
+ bool hasSubClass(const CodeGenRegisterClass *RC) const {
+ return SubClasses.test(RC->EnumValue);
+ }
+
+ // getSubClassWithSubReg - Returns the largest sub-class where all
+ // registers have a SubIdx sub-register.
+ CodeGenRegisterClass *
+ getSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx) const {
+ return SubClassWithSubReg.lookup(SubIdx);
+ }
+
+ void setSubClassWithSubReg(const CodeGenSubRegIndex *SubIdx,
+ CodeGenRegisterClass *SubRC) {
+ SubClassWithSubReg[SubIdx] = SubRC;
+ }
+
+ // getSuperRegClasses - Returns a bit vector of all register classes
+ // containing only SubIdx super-registers of this class.
+ void getSuperRegClasses(const CodeGenSubRegIndex *SubIdx,
+ BitVector &Out) const;
+
+ // addSuperRegClass - Add a class containing only SudIdx super-registers.
+ void addSuperRegClass(CodeGenSubRegIndex *SubIdx,
+ CodeGenRegisterClass *SuperRC) {
+ SuperRegClasses[SubIdx].insert(SuperRC);
+ }
+
+ // getSubClasses - Returns a constant BitVector of subclasses indexed by
+ // EnumValue.
+ // The SubClasses vector includes an entry for this class.
+ const BitVector &getSubClasses() const { return SubClasses; }
+
+ // getSuperClasses - Returns a list of super classes ordered by EnumValue.
+ // The array does not include an entry for this class.
+ ArrayRef<CodeGenRegisterClass*> getSuperClasses() const {
+ return SuperClasses;
+ }
+
+ // Returns an ordered list of class members.
+ // The order of registers is the same as in the .td file.
+ // No = 0 is the default allocation order, No = 1 is the first alternative.
+ ArrayRef<Record*> getOrder(unsigned No = 0) const {
+ return Orders[No];
+ }
+
+ // Return the total number of allocation orders available.
+ unsigned getNumOrders() const { return Orders.size(); }
+
+ // Get the set of registers. This set contains the same registers as
+ // getOrder(0).
+ const CodeGenRegister::Vec &getMembers() const { return Members; }
+
+ // Get a bit vector of TopoSigs present in this register class.
+ const BitVector &getTopoSigs() const { return TopoSigs; }
+
+ // Populate a unique sorted list of units from a register set.
+ void buildRegUnitSet(std::vector<unsigned> &RegUnits) const;
+
+ CodeGenRegisterClass(CodeGenRegBank&, Record *R);
+
+ // A key representing the parts of a register class used for forming
+ // sub-classes. Note the ordering provided by this key is not the same as
+ // the topological order used for the EnumValues.
+ struct Key {
+ const CodeGenRegister::Vec *Members;
+ unsigned SpillSize;
+ unsigned SpillAlignment;
+
+ Key(const CodeGenRegister::Vec *M, unsigned S = 0, unsigned A = 0)
+ : Members(M), SpillSize(S), SpillAlignment(A) {}
+
+ Key(const CodeGenRegisterClass &RC)
+ : Members(&RC.getMembers()),
+ SpillSize(RC.SpillSize),
+ SpillAlignment(RC.SpillAlignment) {}
+
+ // Lexicographical order of (Members, SpillSize, SpillAlignment).
+ bool operator<(const Key&) const;
+ };
+
+ // Create a non-user defined register class.
+ CodeGenRegisterClass(CodeGenRegBank&, StringRef Name, Key Props);
+
+ // Called by CodeGenRegBank::CodeGenRegBank().
+ static void computeSubClasses(CodeGenRegBank&);
+ };
+
+ // Register units are used to model interference and register pressure.
+ // Every register is assigned one or more register units such that two
+ // registers overlap if and only if they have a register unit in common.
+ //
+ // Normally, one register unit is created per leaf register. Non-leaf
+ // registers inherit the units of their sub-registers.
+ struct RegUnit {
+ // Weight assigned to this RegUnit for estimating register pressure.
+ // This is useful when equalizing weights in register classes with mixed
+ // register topologies.
+ unsigned Weight;
+
+ // Each native RegUnit corresponds to one or two root registers. The full
+ // set of registers containing this unit can be computed as the union of
+ // these two registers and their super-registers.
+ const CodeGenRegister *Roots[2];
+
+ // Index into RegClassUnitSets where we can find the list of UnitSets that
+ // contain this unit.
+ unsigned RegClassUnitSetsIdx;
+
+ RegUnit() : Weight(0), RegClassUnitSetsIdx(0) {
+ Roots[0] = Roots[1] = nullptr;
+ }
+
+ ArrayRef<const CodeGenRegister*> getRoots() const {
+ assert(!(Roots[1] && !Roots[0]) && "Invalid roots array");
+ return makeArrayRef(Roots, !!Roots[0] + !!Roots[1]);
+ }
+ };
+
+ // Each RegUnitSet is a sorted vector with a name.
+ struct RegUnitSet {
+ typedef std::vector<unsigned>::const_iterator iterator;
+
+ std::string Name;
+ std::vector<unsigned> Units;
+ unsigned Weight = 0; // Cache the sum of all unit weights.
+ unsigned Order = 0; // Cache the sort key.
+
+ RegUnitSet() = default;
+ };
+
+ // Base vector for identifying TopoSigs. The contents uniquely identify a
+ // TopoSig, only computeSuperRegs needs to know how.
+ typedef SmallVector<unsigned, 16> TopoSigId;
+
+ // CodeGenRegBank - Represent a target's registers and the relations between
+ // them.
+ class CodeGenRegBank {
+ SetTheory Sets;
+
+ std::deque<CodeGenSubRegIndex> SubRegIndices;
+ DenseMap<Record*, CodeGenSubRegIndex*> Def2SubRegIdx;
+
+ CodeGenSubRegIndex *createSubRegIndex(StringRef Name, StringRef NameSpace);
+
+ typedef std::map<SmallVector<CodeGenSubRegIndex*, 8>,
+ CodeGenSubRegIndex*> ConcatIdxMap;
+ ConcatIdxMap ConcatIdx;
+
+ // Registers.
+ std::deque<CodeGenRegister> Registers;
+ StringMap<CodeGenRegister*> RegistersByName;
+ DenseMap<Record*, CodeGenRegister*> Def2Reg;
+ unsigned NumNativeRegUnits;
+
+ std::map<TopoSigId, unsigned> TopoSigs;
+
+ // Includes native (0..NumNativeRegUnits-1) and adopted register units.
+ SmallVector<RegUnit, 8> RegUnits;
+
+ // Register classes.
+ std::list<CodeGenRegisterClass> RegClasses;
+ DenseMap<Record*, CodeGenRegisterClass*> Def2RC;
+ typedef std::map<CodeGenRegisterClass::Key, CodeGenRegisterClass*> RCKeyMap;
+ RCKeyMap Key2RC;
+
+ // Remember each unique set of register units. Initially, this contains a
+ // unique set for each register class. Simliar sets are coalesced with
+ // pruneUnitSets and new supersets are inferred during computeRegUnitSets.
+ std::vector<RegUnitSet> RegUnitSets;
+
+ // Map RegisterClass index to the index of the RegUnitSet that contains the
+ // class's units and any inferred RegUnit supersets.
+ //
+ // NOTE: This could grow beyond the number of register classes when we map
+ // register units to lists of unit sets. If the list of unit sets does not
+ // already exist for a register class, we create a new entry in this vector.
+ std::vector<std::vector<unsigned>> RegClassUnitSets;
+
+ // Give each register unit set an order based on sorting criteria.
+ std::vector<unsigned> RegUnitSetOrder;
+
+ // Add RC to *2RC maps.
+ void addToMaps(CodeGenRegisterClass*);
+
+ // Create a synthetic sub-class if it is missing.
+ CodeGenRegisterClass *getOrCreateSubClass(const CodeGenRegisterClass *RC,
+ const CodeGenRegister::Vec *Membs,
+ StringRef Name);
+
+ // Infer missing register classes.
+ void computeInferredRegisterClasses();
+ void inferCommonSubClass(CodeGenRegisterClass *RC);
+ void inferSubClassWithSubReg(CodeGenRegisterClass *RC);
+
+ void inferMatchingSuperRegClass(CodeGenRegisterClass *RC) {
+ inferMatchingSuperRegClass(RC, RegClasses.begin());
+ }
+
+ void inferMatchingSuperRegClass(
+ CodeGenRegisterClass *RC,
+ std::list<CodeGenRegisterClass>::iterator FirstSubRegRC);
+
+ // Iteratively prune unit sets.
+ void pruneUnitSets();
+
+ // Compute a weight for each register unit created during getSubRegs.
+ void computeRegUnitWeights();
+
+ // Create a RegUnitSet for each RegClass and infer superclasses.
+ void computeRegUnitSets();
+
+ // Populate the Composite map from sub-register relationships.
+ void computeComposites();
+
+ // Compute a lane mask for each sub-register index.
+ void computeSubRegLaneMasks();
+
+ /// Computes a lane mask for each register unit enumerated by a physical
+ /// register.
+ void computeRegUnitLaneMasks();
+
+ public:
+ CodeGenRegBank(RecordKeeper&);
+
+ SetTheory &getSets() { return Sets; }
+
+ // Sub-register indices. The first NumNamedIndices are defined by the user
+ // in the .td files. The rest are synthesized such that all sub-registers
+ // have a unique name.
+ const std::deque<CodeGenSubRegIndex> &getSubRegIndices() const {
+ return SubRegIndices;
+ }
+
+ // Find a SubRegIndex form its Record def.
+ CodeGenSubRegIndex *getSubRegIdx(Record*);
+
+ // Find or create a sub-register index representing the A+B composition.
+ CodeGenSubRegIndex *getCompositeSubRegIndex(CodeGenSubRegIndex *A,
+ CodeGenSubRegIndex *B);
+
+ // Find or create a sub-register index representing the concatenation of
+ // non-overlapping sibling indices.
+ CodeGenSubRegIndex *
+ getConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8>&);
+
+ void
+ addConcatSubRegIndex(const SmallVector<CodeGenSubRegIndex *, 8> &Parts,
+ CodeGenSubRegIndex *Idx) {
+ ConcatIdx.insert(std::make_pair(Parts, Idx));
+ }
+
+ const std::deque<CodeGenRegister> &getRegisters() { return Registers; }
+
+ const StringMap<CodeGenRegister*> &getRegistersByName() {
+ return RegistersByName;
+ }
+
+ // Find a register from its Record def.
+ CodeGenRegister *getReg(Record*);
+
+ // Get a Register's index into the Registers array.
+ unsigned getRegIndex(const CodeGenRegister *Reg) const {
+ return Reg->EnumValue - 1;
+ }
+
+ // Return the number of allocated TopoSigs. The first TopoSig representing
+ // leaf registers is allocated number 0.
+ unsigned getNumTopoSigs() const {
+ return TopoSigs.size();
+ }
+
+ // Find or create a TopoSig for the given TopoSigId.
+ // This function is only for use by CodeGenRegister::computeSuperRegs().
+ // Others should simply use Reg->getTopoSig().
+ unsigned getTopoSig(const TopoSigId &Id) {
+ return TopoSigs.insert(std::make_pair(Id, TopoSigs.size())).first->second;
+ }
+
+ // Create a native register unit that is associated with one or two root
+ // registers.
+ unsigned newRegUnit(CodeGenRegister *R0, CodeGenRegister *R1 = nullptr) {
+ RegUnits.resize(RegUnits.size() + 1);
+ RegUnits.back().Roots[0] = R0;
+ RegUnits.back().Roots[1] = R1;
+ return RegUnits.size() - 1;
+ }
+
+ // Create a new non-native register unit that can be adopted by a register
+ // to increase its pressure. Note that NumNativeRegUnits is not increased.
+ unsigned newRegUnit(unsigned Weight) {
+ RegUnits.resize(RegUnits.size() + 1);
+ RegUnits.back().Weight = Weight;
+ return RegUnits.size() - 1;
+ }
+
+ // Native units are the singular unit of a leaf register. Register aliasing
+ // is completely characterized by native units. Adopted units exist to give
+ // register additional weight but don't affect aliasing.
+ bool isNativeUnit(unsigned RUID) {
+ return RUID < NumNativeRegUnits;
+ }
+
+ unsigned getNumNativeRegUnits() const {
+ return NumNativeRegUnits;
+ }
+
+ RegUnit &getRegUnit(unsigned RUID) { return RegUnits[RUID]; }
+ const RegUnit &getRegUnit(unsigned RUID) const { return RegUnits[RUID]; }
+
+ std::list<CodeGenRegisterClass> &getRegClasses() { return RegClasses; }
+
+ const std::list<CodeGenRegisterClass> &getRegClasses() const {
+ return RegClasses;
+ }
+
+ // Find a register class from its def.
+ CodeGenRegisterClass *getRegClass(Record*);
+
+ /// getRegisterClassForRegister - Find the register class that contains the
+ /// specified physical register. If the register is not in a register
+ /// class, return null. If the register is in multiple classes, and the
+ /// classes have a superset-subset relationship and the same set of types,
+ /// return the superclass. Otherwise return null.
+ const CodeGenRegisterClass* getRegClassForRegister(Record *R);
+
+ // Get the sum of unit weights.
+ unsigned getRegUnitSetWeight(const std::vector<unsigned> &Units) const {
+ unsigned Weight = 0;
+ for (std::vector<unsigned>::const_iterator
+ I = Units.begin(), E = Units.end(); I != E; ++I)
+ Weight += getRegUnit(*I).Weight;
+ return Weight;
+ }
+
+ unsigned getRegSetIDAt(unsigned Order) const {
+ return RegUnitSetOrder[Order];
+ }
+
+ const RegUnitSet &getRegSetAt(unsigned Order) const {
+ return RegUnitSets[RegUnitSetOrder[Order]];
+ }
+
+ // Increase a RegUnitWeight.
+ void increaseRegUnitWeight(unsigned RUID, unsigned Inc) {
+ getRegUnit(RUID).Weight += Inc;
+ }
+
+ // Get the number of register pressure dimensions.
+ unsigned getNumRegPressureSets() const { return RegUnitSets.size(); }
+
+ // Get a set of register unit IDs for a given dimension of pressure.
+ const RegUnitSet &getRegPressureSet(unsigned Idx) const {
+ return RegUnitSets[Idx];
+ }
+
+ // The number of pressure set lists may be larget than the number of
+ // register classes if some register units appeared in a list of sets that
+ // did not correspond to an existing register class.
+ unsigned getNumRegClassPressureSetLists() const {
+ return RegClassUnitSets.size();
+ }
+
+ // Get a list of pressure set IDs for a register class. Liveness of a
+ // register in this class impacts each pressure set in this list by the
+ // weight of the register. An exact solution requires all registers in a
+ // class to have the same class, but it is not strictly guaranteed.
+ ArrayRef<unsigned> getRCPressureSetIDs(unsigned RCIdx) const {
+ return RegClassUnitSets[RCIdx];
+ }
+
+ // Computed derived records such as missing sub-register indices.
+ void computeDerivedInfo();
+
+ // Compute the set of registers completely covered by the registers in Regs.
+ // The returned BitVector will have a bit set for each register in Regs,
+ // all sub-registers, and all super-registers that are covered by the
+ // registers in Regs.
+ //
+ // This is used to compute the mask of call-preserved registers from a list
+ // of callee-saves.
+ BitVector computeCoveredRegisters(ArrayRef<Record*> Regs);
+
+ // Bit mask of lanes that cover their registers. A sub-register index whose
+ // LaneMask is contained in CoveringLanes will be completely covered by
+ // another sub-register with the same or larger lane mask.
+ LaneBitmask CoveringLanes;
+
+ // Helper function for printing debug information. Handles artificial
+ // (non-native) reg units.
+ void printRegUnitName(unsigned Unit) const;
+ };
+
+} // end namespace llvm
+
+#endif // LLVM_UTILS_TABLEGEN_CODEGENREGISTERS_H
diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp
new file mode 100644
index 000000000000..cae1cf4b861e
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp
@@ -0,0 +1,1864 @@
+//===- CodeGenSchedule.cpp - Scheduling MachineModels ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines structures to encapsulate the machine model as described in
+// the target description.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenInstruction.h"
+#include "CodeGenSchedule.h"
+#include "CodeGenTarget.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Regex.h"
+#include "llvm/TableGen/Error.h"
+#include <algorithm>
+#include <iterator>
+#include <utility>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "subtarget-emitter"
+
+#ifndef NDEBUG
+static void dumpIdxVec(ArrayRef<unsigned> V) {
+ for (unsigned Idx : V)
+ dbgs() << Idx << ", ";
+}
+#endif
+
+namespace {
+
+// (instrs a, b, ...) Evaluate and union all arguments. Identical to AddOp.
+struct InstrsOp : public SetTheory::Operator {
+ void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
+ ArrayRef<SMLoc> Loc) override {
+ ST.evaluate(Expr->arg_begin(), Expr->arg_end(), Elts, Loc);
+ }
+};
+
+// (instregex "OpcPat",...) Find all instructions matching an opcode pattern.
+//
+// TODO: Since this is a prefix match, perform a binary search over the
+// instruction names using lower_bound. Note that the predefined instrs must be
+// scanned linearly first. However, this is only safe if the regex pattern has
+// no top-level bars. The DAG already has a list of patterns, so there's no
+// reason to use top-level bars, but we need a way to verify they don't exist
+// before implementing the optimization.
+struct InstRegexOp : public SetTheory::Operator {
+ const CodeGenTarget &Target;
+ InstRegexOp(const CodeGenTarget &t): Target(t) {}
+
+ void apply(SetTheory &ST, DagInit *Expr, SetTheory::RecSet &Elts,
+ ArrayRef<SMLoc> Loc) override {
+ SmallVector<Regex, 4> RegexList;
+ for (DagInit::const_arg_iterator
+ AI = Expr->arg_begin(), AE = Expr->arg_end(); AI != AE; ++AI) {
+ StringInit *SI = dyn_cast<StringInit>(*AI);
+ if (!SI)
+ PrintFatalError(Loc, "instregex requires pattern string: "
+ + Expr->getAsString());
+ std::string pat = SI->getValue();
+ // Implement a python-style prefix match.
+ if (pat[0] != '^') {
+ pat.insert(0, "^(");
+ pat.insert(pat.end(), ')');
+ }
+ RegexList.push_back(Regex(pat));
+ }
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ for (auto &R : RegexList) {
+ if (R.match(Inst->TheDef->getName()))
+ Elts.insert(Inst->TheDef);
+ }
+ }
+ }
+};
+
+} // end anonymous namespace
+
+/// CodeGenModels ctor interprets machine model records and populates maps.
+CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
+ const CodeGenTarget &TGT):
+ Records(RK), Target(TGT) {
+
+ Sets.addFieldExpander("InstRW", "Instrs");
+
+ // Allow Set evaluation to recognize the dags used in InstRW records:
+ // (instrs Op1, Op1...)
+ Sets.addOperator("instrs", llvm::make_unique<InstrsOp>());
+ Sets.addOperator("instregex", llvm::make_unique<InstRegexOp>(Target));
+
+ // Instantiate a CodeGenProcModel for each SchedMachineModel with the values
+ // that are explicitly referenced in tablegen records. Resources associated
+ // with each processor will be derived later. Populate ProcModelMap with the
+ // CodeGenProcModel instances.
+ collectProcModels();
+
+ // Instantiate a CodeGenSchedRW for each SchedReadWrite record explicitly
+ // defined, and populate SchedReads and SchedWrites vectors. Implicit
+ // SchedReadWrites that represent sequences derived from expanded variant will
+ // be inferred later.
+ collectSchedRW();
+
+ // Instantiate a CodeGenSchedClass for each unique SchedRW signature directly
+ // required by an instruction definition, and populate SchedClassIdxMap. Set
+ // NumItineraryClasses to the number of explicit itinerary classes referenced
+ // by instructions. Set NumInstrSchedClasses to the number of itinerary
+ // classes plus any classes implied by instructions that derive from class
+ // Sched and provide SchedRW list. This does not infer any new classes from
+ // SchedVariant.
+ collectSchedClasses();
+
+ // Find instruction itineraries for each processor. Sort and populate
+ // CodeGenProcModel::ItinDefList. (Cycle-to-cycle itineraries). This requires
+ // all itinerary classes to be discovered.
+ collectProcItins();
+
+ // Find ItinRW records for each processor and itinerary class.
+ // (For per-operand resources mapped to itinerary classes).
+ collectProcItinRW();
+
+ // Find UnsupportedFeatures records for each processor.
+ // (For per-operand resources mapped to itinerary classes).
+ collectProcUnsupportedFeatures();
+
+ // Infer new SchedClasses from SchedVariant.
+ inferSchedClasses();
+
+ // Populate each CodeGenProcModel's WriteResDefs, ReadAdvanceDefs, and
+ // ProcResourceDefs.
+ collectProcResources();
+
+ checkCompleteness();
+}
+
+/// Gather all processor models.
+void CodeGenSchedModels::collectProcModels() {
+ RecVec ProcRecords = Records.getAllDerivedDefinitions("Processor");
+ std::sort(ProcRecords.begin(), ProcRecords.end(), LessRecordFieldName());
+
+ // Reserve space because we can. Reallocation would be ok.
+ ProcModels.reserve(ProcRecords.size()+1);
+
+ // Use idx=0 for NoModel/NoItineraries.
+ Record *NoModelDef = Records.getDef("NoSchedModel");
+ Record *NoItinsDef = Records.getDef("NoItineraries");
+ ProcModels.emplace_back(0, "NoSchedModel", NoModelDef, NoItinsDef);
+ ProcModelMap[NoModelDef] = 0;
+
+ // For each processor, find a unique machine model.
+ for (unsigned i = 0, N = ProcRecords.size(); i < N; ++i)
+ addProcModel(ProcRecords[i]);
+}
+
+/// Get a unique processor model based on the defined MachineModel and
+/// ProcessorItineraries.
+void CodeGenSchedModels::addProcModel(Record *ProcDef) {
+ Record *ModelKey = getModelOrItinDef(ProcDef);
+ if (!ProcModelMap.insert(std::make_pair(ModelKey, ProcModels.size())).second)
+ return;
+
+ std::string Name = ModelKey->getName();
+ if (ModelKey->isSubClassOf("SchedMachineModel")) {
+ Record *ItinsDef = ModelKey->getValueAsDef("Itineraries");
+ ProcModels.emplace_back(ProcModels.size(), Name, ModelKey, ItinsDef);
+ }
+ else {
+ // An itinerary is defined without a machine model. Infer a new model.
+ if (!ModelKey->getValueAsListOfDefs("IID").empty())
+ Name = Name + "Model";
+ ProcModels.emplace_back(ProcModels.size(), Name,
+ ProcDef->getValueAsDef("SchedModel"), ModelKey);
+ }
+ DEBUG(ProcModels.back().dump());
+}
+
+// Recursively find all reachable SchedReadWrite records.
+static void scanSchedRW(Record *RWDef, RecVec &RWDefs,
+ SmallPtrSet<Record*, 16> &RWSet) {
+ if (!RWSet.insert(RWDef).second)
+ return;
+ RWDefs.push_back(RWDef);
+ // Reads don't current have sequence records, but it can be added later.
+ if (RWDef->isSubClassOf("WriteSequence")) {
+ RecVec Seq = RWDef->getValueAsListOfDefs("Writes");
+ for (RecIter I = Seq.begin(), E = Seq.end(); I != E; ++I)
+ scanSchedRW(*I, RWDefs, RWSet);
+ }
+ else if (RWDef->isSubClassOf("SchedVariant")) {
+ // Visit each variant (guarded by a different predicate).
+ RecVec Vars = RWDef->getValueAsListOfDefs("Variants");
+ for (RecIter VI = Vars.begin(), VE = Vars.end(); VI != VE; ++VI) {
+ // Visit each RW in the sequence selected by the current variant.
+ RecVec Selected = (*VI)->getValueAsListOfDefs("Selected");
+ for (RecIter I = Selected.begin(), E = Selected.end(); I != E; ++I)
+ scanSchedRW(*I, RWDefs, RWSet);
+ }
+ }
+}
+
+// Collect and sort all SchedReadWrites reachable via tablegen records.
+// More may be inferred later when inferring new SchedClasses from variants.
+void CodeGenSchedModels::collectSchedRW() {
+ // Reserve idx=0 for invalid writes/reads.
+ SchedWrites.resize(1);
+ SchedReads.resize(1);
+
+ SmallPtrSet<Record*, 16> RWSet;
+
+ // Find all SchedReadWrites referenced by instruction defs.
+ RecVec SWDefs, SRDefs;
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ Record *SchedDef = Inst->TheDef;
+ if (SchedDef->isValueUnset("SchedRW"))
+ continue;
+ RecVec RWs = SchedDef->getValueAsListOfDefs("SchedRW");
+ for (RecIter RWI = RWs.begin(), RWE = RWs.end(); RWI != RWE; ++RWI) {
+ if ((*RWI)->isSubClassOf("SchedWrite"))
+ scanSchedRW(*RWI, SWDefs, RWSet);
+ else {
+ assert((*RWI)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
+ scanSchedRW(*RWI, SRDefs, RWSet);
+ }
+ }
+ }
+ // Find all ReadWrites referenced by InstRW.
+ RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");
+ for (RecIter OI = InstRWDefs.begin(), OE = InstRWDefs.end(); OI != OE; ++OI) {
+ // For all OperandReadWrites.
+ RecVec RWDefs = (*OI)->getValueAsListOfDefs("OperandReadWrites");
+ for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end();
+ RWI != RWE; ++RWI) {
+ if ((*RWI)->isSubClassOf("SchedWrite"))
+ scanSchedRW(*RWI, SWDefs, RWSet);
+ else {
+ assert((*RWI)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
+ scanSchedRW(*RWI, SRDefs, RWSet);
+ }
+ }
+ }
+ // Find all ReadWrites referenced by ItinRW.
+ RecVec ItinRWDefs = Records.getAllDerivedDefinitions("ItinRW");
+ for (RecIter II = ItinRWDefs.begin(), IE = ItinRWDefs.end(); II != IE; ++II) {
+ // For all OperandReadWrites.
+ RecVec RWDefs = (*II)->getValueAsListOfDefs("OperandReadWrites");
+ for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end();
+ RWI != RWE; ++RWI) {
+ if ((*RWI)->isSubClassOf("SchedWrite"))
+ scanSchedRW(*RWI, SWDefs, RWSet);
+ else {
+ assert((*RWI)->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
+ scanSchedRW(*RWI, SRDefs, RWSet);
+ }
+ }
+ }
+ // Find all ReadWrites referenced by SchedAlias. AliasDefs needs to be sorted
+ // for the loop below that initializes Alias vectors.
+ RecVec AliasDefs = Records.getAllDerivedDefinitions("SchedAlias");
+ std::sort(AliasDefs.begin(), AliasDefs.end(), LessRecord());
+ for (RecIter AI = AliasDefs.begin(), AE = AliasDefs.end(); AI != AE; ++AI) {
+ Record *MatchDef = (*AI)->getValueAsDef("MatchRW");
+ Record *AliasDef = (*AI)->getValueAsDef("AliasRW");
+ if (MatchDef->isSubClassOf("SchedWrite")) {
+ if (!AliasDef->isSubClassOf("SchedWrite"))
+ PrintFatalError((*AI)->getLoc(), "SchedWrite Alias must be SchedWrite");
+ scanSchedRW(AliasDef, SWDefs, RWSet);
+ }
+ else {
+ assert(MatchDef->isSubClassOf("SchedRead") && "Unknown SchedReadWrite");
+ if (!AliasDef->isSubClassOf("SchedRead"))
+ PrintFatalError((*AI)->getLoc(), "SchedRead Alias must be SchedRead");
+ scanSchedRW(AliasDef, SRDefs, RWSet);
+ }
+ }
+ // Sort and add the SchedReadWrites directly referenced by instructions or
+ // itinerary resources. Index reads and writes in separate domains.
+ std::sort(SWDefs.begin(), SWDefs.end(), LessRecord());
+ for (RecIter SWI = SWDefs.begin(), SWE = SWDefs.end(); SWI != SWE; ++SWI) {
+ assert(!getSchedRWIdx(*SWI, /*IsRead=*/false) && "duplicate SchedWrite");
+ SchedWrites.emplace_back(SchedWrites.size(), *SWI);
+ }
+ std::sort(SRDefs.begin(), SRDefs.end(), LessRecord());
+ for (RecIter SRI = SRDefs.begin(), SRE = SRDefs.end(); SRI != SRE; ++SRI) {
+ assert(!getSchedRWIdx(*SRI, /*IsRead-*/true) && "duplicate SchedWrite");
+ SchedReads.emplace_back(SchedReads.size(), *SRI);
+ }
+ // Initialize WriteSequence vectors.
+ for (std::vector<CodeGenSchedRW>::iterator WI = SchedWrites.begin(),
+ WE = SchedWrites.end(); WI != WE; ++WI) {
+ if (!WI->IsSequence)
+ continue;
+ findRWs(WI->TheDef->getValueAsListOfDefs("Writes"), WI->Sequence,
+ /*IsRead=*/false);
+ }
+ // Initialize Aliases vectors.
+ for (RecIter AI = AliasDefs.begin(), AE = AliasDefs.end(); AI != AE; ++AI) {
+ Record *AliasDef = (*AI)->getValueAsDef("AliasRW");
+ getSchedRW(AliasDef).IsAlias = true;
+ Record *MatchDef = (*AI)->getValueAsDef("MatchRW");
+ CodeGenSchedRW &RW = getSchedRW(MatchDef);
+ if (RW.IsAlias)
+ PrintFatalError((*AI)->getLoc(), "Cannot Alias an Alias");
+ RW.Aliases.push_back(*AI);
+ }
+ DEBUG(
+ for (unsigned WIdx = 0, WEnd = SchedWrites.size(); WIdx != WEnd; ++WIdx) {
+ dbgs() << WIdx << ": ";
+ SchedWrites[WIdx].dump();
+ dbgs() << '\n';
+ }
+ for (unsigned RIdx = 0, REnd = SchedReads.size(); RIdx != REnd; ++RIdx) {
+ dbgs() << RIdx << ": ";
+ SchedReads[RIdx].dump();
+ dbgs() << '\n';
+ }
+ RecVec RWDefs = Records.getAllDerivedDefinitions("SchedReadWrite");
+ for (RecIter RI = RWDefs.begin(), RE = RWDefs.end();
+ RI != RE; ++RI) {
+ if (!getSchedRWIdx(*RI, (*RI)->isSubClassOf("SchedRead"))) {
+ const std::string &Name = (*RI)->getName();
+ if (Name != "NoWrite" && Name != "ReadDefault")
+ dbgs() << "Unused SchedReadWrite " << (*RI)->getName() << '\n';
+ }
+ });
+}
+
+/// Compute a SchedWrite name from a sequence of writes.
+std::string CodeGenSchedModels::genRWName(ArrayRef<unsigned> Seq, bool IsRead) {
+ std::string Name("(");
+ for (auto I = Seq.begin(), E = Seq.end(); I != E; ++I) {
+ if (I != Seq.begin())
+ Name += '_';
+ Name += getSchedRW(*I, IsRead).Name;
+ }
+ Name += ')';
+ return Name;
+}
+
+unsigned CodeGenSchedModels::getSchedRWIdx(Record *Def, bool IsRead,
+ unsigned After) const {
+ const std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites;
+ assert(After < RWVec.size() && "start position out of bounds");
+ for (std::vector<CodeGenSchedRW>::const_iterator I = RWVec.begin() + After,
+ E = RWVec.end(); I != E; ++I) {
+ if (I->TheDef == Def)
+ return I - RWVec.begin();
+ }
+ return 0;
+}
+
+bool CodeGenSchedModels::hasReadOfWrite(Record *WriteDef) const {
+ for (unsigned i = 0, e = SchedReads.size(); i < e; ++i) {
+ Record *ReadDef = SchedReads[i].TheDef;
+ if (!ReadDef || !ReadDef->isSubClassOf("ProcReadAdvance"))
+ continue;
+
+ RecVec ValidWrites = ReadDef->getValueAsListOfDefs("ValidWrites");
+ if (is_contained(ValidWrites, WriteDef)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+namespace llvm {
+
+void splitSchedReadWrites(const RecVec &RWDefs,
+ RecVec &WriteDefs, RecVec &ReadDefs) {
+ for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end(); RWI != RWE; ++RWI) {
+ if ((*RWI)->isSubClassOf("SchedWrite"))
+ WriteDefs.push_back(*RWI);
+ else {
+ assert((*RWI)->isSubClassOf("SchedRead") && "unknown SchedReadWrite");
+ ReadDefs.push_back(*RWI);
+ }
+ }
+}
+
+} // end namespace llvm
+
+// Split the SchedReadWrites defs and call findRWs for each list.
+void CodeGenSchedModels::findRWs(const RecVec &RWDefs,
+ IdxVec &Writes, IdxVec &Reads) const {
+ RecVec WriteDefs;
+ RecVec ReadDefs;
+ splitSchedReadWrites(RWDefs, WriteDefs, ReadDefs);
+ findRWs(WriteDefs, Writes, false);
+ findRWs(ReadDefs, Reads, true);
+}
+
+// Call getSchedRWIdx for all elements in a sequence of SchedRW defs.
+void CodeGenSchedModels::findRWs(const RecVec &RWDefs, IdxVec &RWs,
+ bool IsRead) const {
+ for (RecIter RI = RWDefs.begin(), RE = RWDefs.end(); RI != RE; ++RI) {
+ unsigned Idx = getSchedRWIdx(*RI, IsRead);
+ assert(Idx && "failed to collect SchedReadWrite");
+ RWs.push_back(Idx);
+ }
+}
+
+void CodeGenSchedModels::expandRWSequence(unsigned RWIdx, IdxVec &RWSeq,
+ bool IsRead) const {
+ const CodeGenSchedRW &SchedRW = getSchedRW(RWIdx, IsRead);
+ if (!SchedRW.IsSequence) {
+ RWSeq.push_back(RWIdx);
+ return;
+ }
+ int Repeat =
+ SchedRW.TheDef ? SchedRW.TheDef->getValueAsInt("Repeat") : 1;
+ for (int i = 0; i < Repeat; ++i) {
+ for (IdxIter I = SchedRW.Sequence.begin(), E = SchedRW.Sequence.end();
+ I != E; ++I) {
+ expandRWSequence(*I, RWSeq, IsRead);
+ }
+ }
+}
+
+// Expand a SchedWrite as a sequence following any aliases that coincide with
+// the given processor model.
+void CodeGenSchedModels::expandRWSeqForProc(
+ unsigned RWIdx, IdxVec &RWSeq, bool IsRead,
+ const CodeGenProcModel &ProcModel) const {
+
+ const CodeGenSchedRW &SchedWrite = getSchedRW(RWIdx, IsRead);
+ Record *AliasDef = nullptr;
+ for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
+ AI != AE; ++AI) {
+ const CodeGenSchedRW &AliasRW = getSchedRW((*AI)->getValueAsDef("AliasRW"));
+ if ((*AI)->getValueInit("SchedModel")->isComplete()) {
+ Record *ModelDef = (*AI)->getValueAsDef("SchedModel");
+ if (&getProcModel(ModelDef) != &ProcModel)
+ continue;
+ }
+ if (AliasDef)
+ PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
+ "defined for processor " + ProcModel.ModelName +
+ " Ensure only one SchedAlias exists per RW.");
+ AliasDef = AliasRW.TheDef;
+ }
+ if (AliasDef) {
+ expandRWSeqForProc(getSchedRWIdx(AliasDef, IsRead),
+ RWSeq, IsRead,ProcModel);
+ return;
+ }
+ if (!SchedWrite.IsSequence) {
+ RWSeq.push_back(RWIdx);
+ return;
+ }
+ int Repeat =
+ SchedWrite.TheDef ? SchedWrite.TheDef->getValueAsInt("Repeat") : 1;
+ for (int i = 0; i < Repeat; ++i) {
+ for (IdxIter I = SchedWrite.Sequence.begin(), E = SchedWrite.Sequence.end();
+ I != E; ++I) {
+ expandRWSeqForProc(*I, RWSeq, IsRead, ProcModel);
+ }
+ }
+}
+
+// Find the existing SchedWrite that models this sequence of writes.
+unsigned CodeGenSchedModels::findRWForSequence(ArrayRef<unsigned> Seq,
+ bool IsRead) {
+ std::vector<CodeGenSchedRW> &RWVec = IsRead ? SchedReads : SchedWrites;
+
+ for (std::vector<CodeGenSchedRW>::iterator I = RWVec.begin(), E = RWVec.end();
+ I != E; ++I) {
+ if (makeArrayRef(I->Sequence) == Seq)
+ return I - RWVec.begin();
+ }
+ // Index zero reserved for invalid RW.
+ return 0;
+}
+
+/// Add this ReadWrite if it doesn't already exist.
+unsigned CodeGenSchedModels::findOrInsertRW(ArrayRef<unsigned> Seq,
+ bool IsRead) {
+ assert(!Seq.empty() && "cannot insert empty sequence");
+ if (Seq.size() == 1)
+ return Seq.back();
+
+ unsigned Idx = findRWForSequence(Seq, IsRead);
+ if (Idx)
+ return Idx;
+
+ unsigned RWIdx = IsRead ? SchedReads.size() : SchedWrites.size();
+ CodeGenSchedRW SchedRW(RWIdx, IsRead, Seq, genRWName(Seq, IsRead));
+ if (IsRead)
+ SchedReads.push_back(SchedRW);
+ else
+ SchedWrites.push_back(SchedRW);
+ return RWIdx;
+}
+
+/// Visit all the instruction definitions for this target to gather and
+/// enumerate the itinerary classes. These are the explicitly specified
+/// SchedClasses. More SchedClasses may be inferred.
+void CodeGenSchedModels::collectSchedClasses() {
+
+ // NoItinerary is always the first class at Idx=0
+ SchedClasses.resize(1);
+ SchedClasses.back().Index = 0;
+ SchedClasses.back().Name = "NoInstrModel";
+ SchedClasses.back().ItinClassDef = Records.getDef("NoItinerary");
+ SchedClasses.back().ProcIndices.push_back(0);
+
+ // Create a SchedClass for each unique combination of itinerary class and
+ // SchedRW list.
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ Record *ItinDef = Inst->TheDef->getValueAsDef("Itinerary");
+ IdxVec Writes, Reads;
+ if (!Inst->TheDef->isValueUnset("SchedRW"))
+ findRWs(Inst->TheDef->getValueAsListOfDefs("SchedRW"), Writes, Reads);
+
+ // ProcIdx == 0 indicates the class applies to all processors.
+ IdxVec ProcIndices(1, 0);
+
+ unsigned SCIdx = addSchedClass(ItinDef, Writes, Reads, ProcIndices);
+ InstrClassMap[Inst->TheDef] = SCIdx;
+ }
+ // Create classes for InstRW defs.
+ RecVec InstRWDefs = Records.getAllDerivedDefinitions("InstRW");
+ std::sort(InstRWDefs.begin(), InstRWDefs.end(), LessRecord());
+ for (RecIter OI = InstRWDefs.begin(), OE = InstRWDefs.end(); OI != OE; ++OI)
+ createInstRWClass(*OI);
+
+ NumInstrSchedClasses = SchedClasses.size();
+
+ bool EnableDump = false;
+ DEBUG(EnableDump = true);
+ if (!EnableDump)
+ return;
+
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ std::string InstName = Inst->TheDef->getName();
+ unsigned SCIdx = InstrClassMap.lookup(Inst->TheDef);
+ if (!SCIdx) {
+ if (!Inst->hasNoSchedulingInfo)
+ dbgs() << "No machine model for " << Inst->TheDef->getName() << '\n';
+ continue;
+ }
+ CodeGenSchedClass &SC = getSchedClass(SCIdx);
+ if (SC.ProcIndices[0] != 0)
+ PrintFatalError(Inst->TheDef->getLoc(), "Instruction's sched class "
+ "must not be subtarget specific.");
+
+ IdxVec ProcIndices;
+ if (SC.ItinClassDef->getName() != "NoItinerary") {
+ ProcIndices.push_back(0);
+ dbgs() << "Itinerary for " << InstName << ": "
+ << SC.ItinClassDef->getName() << '\n';
+ }
+ if (!SC.Writes.empty()) {
+ ProcIndices.push_back(0);
+ dbgs() << "SchedRW machine model for " << InstName;
+ for (IdxIter WI = SC.Writes.begin(), WE = SC.Writes.end(); WI != WE; ++WI)
+ dbgs() << " " << SchedWrites[*WI].Name;
+ for (IdxIter RI = SC.Reads.begin(), RE = SC.Reads.end(); RI != RE; ++RI)
+ dbgs() << " " << SchedReads[*RI].Name;
+ dbgs() << '\n';
+ }
+ const RecVec &RWDefs = SchedClasses[SCIdx].InstRWs;
+ for (RecIter RWI = RWDefs.begin(), RWE = RWDefs.end();
+ RWI != RWE; ++RWI) {
+ const CodeGenProcModel &ProcModel =
+ getProcModel((*RWI)->getValueAsDef("SchedModel"));
+ ProcIndices.push_back(ProcModel.Index);
+ dbgs() << "InstRW on " << ProcModel.ModelName << " for " << InstName;
+ IdxVec Writes;
+ IdxVec Reads;
+ findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"),
+ Writes, Reads);
+ for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI)
+ dbgs() << " " << SchedWrites[*WI].Name;
+ for (IdxIter RI = Reads.begin(), RE = Reads.end(); RI != RE; ++RI)
+ dbgs() << " " << SchedReads[*RI].Name;
+ dbgs() << '\n';
+ }
+ // If ProcIndices contains zero, the class applies to all processors.
+ if (!std::count(ProcIndices.begin(), ProcIndices.end(), 0)) {
+ for (std::vector<CodeGenProcModel>::iterator PI = ProcModels.begin(),
+ PE = ProcModels.end(); PI != PE; ++PI) {
+ if (!std::count(ProcIndices.begin(), ProcIndices.end(), PI->Index))
+ dbgs() << "No machine model for " << Inst->TheDef->getName()
+ << " on processor " << PI->ModelName << '\n';
+ }
+ }
+ }
+}
+
+/// Find an SchedClass that has been inferred from a per-operand list of
+/// SchedWrites and SchedReads.
+unsigned CodeGenSchedModels::findSchedClassIdx(Record *ItinClassDef,
+ ArrayRef<unsigned> Writes,
+ ArrayRef<unsigned> Reads) const {
+ for (SchedClassIter I = schedClassBegin(), E = schedClassEnd(); I != E; ++I) {
+ if (I->ItinClassDef == ItinClassDef && makeArrayRef(I->Writes) == Writes &&
+ makeArrayRef(I->Reads) == Reads) {
+ return I - schedClassBegin();
+ }
+ }
+ return 0;
+}
+
+// Get the SchedClass index for an instruction.
+unsigned CodeGenSchedModels::getSchedClassIdx(
+ const CodeGenInstruction &Inst) const {
+
+ return InstrClassMap.lookup(Inst.TheDef);
+}
+
+std::string
+CodeGenSchedModels::createSchedClassName(Record *ItinClassDef,
+ ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads) {
+
+ std::string Name;
+ if (ItinClassDef && ItinClassDef->getName() != "NoItinerary")
+ Name = ItinClassDef->getName();
+ for (unsigned Idx : OperWrites) {
+ if (!Name.empty())
+ Name += '_';
+ Name += SchedWrites[Idx].Name;
+ }
+ for (unsigned Idx : OperReads) {
+ Name += '_';
+ Name += SchedReads[Idx].Name;
+ }
+ return Name;
+}
+
+std::string CodeGenSchedModels::createSchedClassName(const RecVec &InstDefs) {
+
+ std::string Name;
+ for (RecIter I = InstDefs.begin(), E = InstDefs.end(); I != E; ++I) {
+ if (I != InstDefs.begin())
+ Name += '_';
+ Name += (*I)->getName();
+ }
+ return Name;
+}
+
+/// Add an inferred sched class from an itinerary class and per-operand list of
+/// SchedWrites and SchedReads. ProcIndices contains the set of IDs of
+/// processors that may utilize this class.
+unsigned CodeGenSchedModels::addSchedClass(Record *ItinClassDef,
+ ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads,
+ ArrayRef<unsigned> ProcIndices) {
+ assert(!ProcIndices.empty() && "expect at least one ProcIdx");
+
+ unsigned Idx = findSchedClassIdx(ItinClassDef, OperWrites, OperReads);
+ if (Idx || SchedClasses[0].isKeyEqual(ItinClassDef, OperWrites, OperReads)) {
+ IdxVec PI;
+ std::set_union(SchedClasses[Idx].ProcIndices.begin(),
+ SchedClasses[Idx].ProcIndices.end(),
+ ProcIndices.begin(), ProcIndices.end(),
+ std::back_inserter(PI));
+ SchedClasses[Idx].ProcIndices.swap(PI);
+ return Idx;
+ }
+ Idx = SchedClasses.size();
+ SchedClasses.resize(Idx+1);
+ CodeGenSchedClass &SC = SchedClasses.back();
+ SC.Index = Idx;
+ SC.Name = createSchedClassName(ItinClassDef, OperWrites, OperReads);
+ SC.ItinClassDef = ItinClassDef;
+ SC.Writes = OperWrites;
+ SC.Reads = OperReads;
+ SC.ProcIndices = ProcIndices;
+
+ return Idx;
+}
+
+// Create classes for each set of opcodes that are in the same InstReadWrite
+// definition across all processors.
+void CodeGenSchedModels::createInstRWClass(Record *InstRWDef) {
+ // ClassInstrs will hold an entry for each subset of Instrs in InstRWDef that
+ // intersects with an existing class via a previous InstRWDef. Instrs that do
+ // not intersect with an existing class refer back to their former class as
+ // determined from ItinDef or SchedRW.
+ SmallVector<std::pair<unsigned, SmallVector<Record *, 8>>, 4> ClassInstrs;
+ // Sort Instrs into sets.
+ const RecVec *InstDefs = Sets.expand(InstRWDef);
+ if (InstDefs->empty())
+ PrintFatalError(InstRWDef->getLoc(), "No matching instruction opcodes");
+
+ for (RecIter I = InstDefs->begin(), E = InstDefs->end(); I != E; ++I) {
+ InstClassMapTy::const_iterator Pos = InstrClassMap.find(*I);
+ if (Pos == InstrClassMap.end())
+ PrintFatalError((*I)->getLoc(), "No sched class for instruction.");
+ unsigned SCIdx = Pos->second;
+ unsigned CIdx = 0, CEnd = ClassInstrs.size();
+ for (; CIdx != CEnd; ++CIdx) {
+ if (ClassInstrs[CIdx].first == SCIdx)
+ break;
+ }
+ if (CIdx == CEnd) {
+ ClassInstrs.resize(CEnd + 1);
+ ClassInstrs[CIdx].first = SCIdx;
+ }
+ ClassInstrs[CIdx].second.push_back(*I);
+ }
+ // For each set of Instrs, create a new class if necessary, and map or remap
+ // the Instrs to it.
+ unsigned CIdx = 0, CEnd = ClassInstrs.size();
+ for (; CIdx != CEnd; ++CIdx) {
+ unsigned OldSCIdx = ClassInstrs[CIdx].first;
+ ArrayRef<Record*> InstDefs = ClassInstrs[CIdx].second;
+ // If the all instrs in the current class are accounted for, then leave
+ // them mapped to their old class.
+ if (OldSCIdx) {
+ const RecVec &RWDefs = SchedClasses[OldSCIdx].InstRWs;
+ if (!RWDefs.empty()) {
+ const RecVec *OrigInstDefs = Sets.expand(RWDefs[0]);
+ unsigned OrigNumInstrs = 0;
+ for (RecIter I = OrigInstDefs->begin(), E = OrigInstDefs->end();
+ I != E; ++I) {
+ if (InstrClassMap[*I] == OldSCIdx)
+ ++OrigNumInstrs;
+ }
+ if (OrigNumInstrs == InstDefs.size()) {
+ assert(SchedClasses[OldSCIdx].ProcIndices[0] == 0 &&
+ "expected a generic SchedClass");
+ DEBUG(dbgs() << "InstRW: Reuse SC " << OldSCIdx << ":"
+ << SchedClasses[OldSCIdx].Name << " on "
+ << InstRWDef->getValueAsDef("SchedModel")->getName() << "\n");
+ SchedClasses[OldSCIdx].InstRWs.push_back(InstRWDef);
+ continue;
+ }
+ }
+ }
+ unsigned SCIdx = SchedClasses.size();
+ SchedClasses.resize(SCIdx+1);
+ CodeGenSchedClass &SC = SchedClasses.back();
+ SC.Index = SCIdx;
+ SC.Name = createSchedClassName(InstDefs);
+ DEBUG(dbgs() << "InstRW: New SC " << SCIdx << ":" << SC.Name << " on "
+ << InstRWDef->getValueAsDef("SchedModel")->getName() << "\n");
+
+ // Preserve ItinDef and Writes/Reads for processors without an InstRW entry.
+ SC.ItinClassDef = SchedClasses[OldSCIdx].ItinClassDef;
+ SC.Writes = SchedClasses[OldSCIdx].Writes;
+ SC.Reads = SchedClasses[OldSCIdx].Reads;
+ SC.ProcIndices.push_back(0);
+ // Map each Instr to this new class.
+ // Note that InstDefs may be a smaller list than InstRWDef's "Instrs".
+ Record *RWModelDef = InstRWDef->getValueAsDef("SchedModel");
+ SmallSet<unsigned, 4> RemappedClassIDs;
+ for (ArrayRef<Record*>::const_iterator
+ II = InstDefs.begin(), IE = InstDefs.end(); II != IE; ++II) {
+ unsigned OldSCIdx = InstrClassMap[*II];
+ if (OldSCIdx && RemappedClassIDs.insert(OldSCIdx).second) {
+ for (RecIter RI = SchedClasses[OldSCIdx].InstRWs.begin(),
+ RE = SchedClasses[OldSCIdx].InstRWs.end(); RI != RE; ++RI) {
+ if ((*RI)->getValueAsDef("SchedModel") == RWModelDef) {
+ PrintFatalError(InstRWDef->getLoc(), "Overlapping InstRW def " +
+ (*II)->getName() + " also matches " +
+ (*RI)->getValue("Instrs")->getValue()->getAsString());
+ }
+ assert(*RI != InstRWDef && "SchedClass has duplicate InstRW def");
+ SC.InstRWs.push_back(*RI);
+ }
+ }
+ InstrClassMap[*II] = SCIdx;
+ }
+ SC.InstRWs.push_back(InstRWDef);
+ }
+}
+
+// True if collectProcItins found anything.
+bool CodeGenSchedModels::hasItineraries() const {
+ for (CodeGenSchedModels::ProcIter PI = procModelBegin(), PE = procModelEnd();
+ PI != PE; ++PI) {
+ if (PI->hasItineraries())
+ return true;
+ }
+ return false;
+}
+
+// Gather the processor itineraries.
+void CodeGenSchedModels::collectProcItins() {
+ for (CodeGenProcModel &ProcModel : ProcModels) {
+ if (!ProcModel.hasItineraries())
+ continue;
+
+ RecVec ItinRecords = ProcModel.ItinsDef->getValueAsListOfDefs("IID");
+ assert(!ItinRecords.empty() && "ProcModel.hasItineraries is incorrect");
+
+ // Populate ItinDefList with Itinerary records.
+ ProcModel.ItinDefList.resize(NumInstrSchedClasses);
+
+ // Insert each itinerary data record in the correct position within
+ // the processor model's ItinDefList.
+ for (unsigned i = 0, N = ItinRecords.size(); i < N; i++) {
+ Record *ItinData = ItinRecords[i];
+ Record *ItinDef = ItinData->getValueAsDef("TheClass");
+ bool FoundClass = false;
+ for (SchedClassIter SCI = schedClassBegin(), SCE = schedClassEnd();
+ SCI != SCE; ++SCI) {
+ // Multiple SchedClasses may share an itinerary. Update all of them.
+ if (SCI->ItinClassDef == ItinDef) {
+ ProcModel.ItinDefList[SCI->Index] = ItinData;
+ FoundClass = true;
+ }
+ }
+ if (!FoundClass) {
+ DEBUG(dbgs() << ProcModel.ItinsDef->getName()
+ << " missing class for itinerary " << ItinDef->getName() << '\n');
+ }
+ }
+ // Check for missing itinerary entries.
+ assert(!ProcModel.ItinDefList[0] && "NoItinerary class can't have rec");
+ DEBUG(
+ for (unsigned i = 1, N = ProcModel.ItinDefList.size(); i < N; ++i) {
+ if (!ProcModel.ItinDefList[i])
+ dbgs() << ProcModel.ItinsDef->getName()
+ << " missing itinerary for class "
+ << SchedClasses[i].Name << '\n';
+ });
+ }
+}
+
+// Gather the read/write types for each itinerary class.
+void CodeGenSchedModels::collectProcItinRW() {
+ RecVec ItinRWDefs = Records.getAllDerivedDefinitions("ItinRW");
+ std::sort(ItinRWDefs.begin(), ItinRWDefs.end(), LessRecord());
+ for (RecIter II = ItinRWDefs.begin(), IE = ItinRWDefs.end(); II != IE; ++II) {
+ if (!(*II)->getValueInit("SchedModel")->isComplete())
+ PrintFatalError((*II)->getLoc(), "SchedModel is undefined");
+ Record *ModelDef = (*II)->getValueAsDef("SchedModel");
+ ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
+ if (I == ProcModelMap.end()) {
+ PrintFatalError((*II)->getLoc(), "Undefined SchedMachineModel "
+ + ModelDef->getName());
+ }
+ ProcModels[I->second].ItinRWDefs.push_back(*II);
+ }
+}
+
+// Gather the unsupported features for processor models.
+void CodeGenSchedModels::collectProcUnsupportedFeatures() {
+ for (CodeGenProcModel &ProcModel : ProcModels) {
+ for (Record *Pred : ProcModel.ModelDef->getValueAsListOfDefs("UnsupportedFeatures")) {
+ ProcModel.UnsupportedFeaturesDefs.push_back(Pred);
+ }
+ }
+}
+
+/// Infer new classes from existing classes. In the process, this may create new
+/// SchedWrites from sequences of existing SchedWrites.
+void CodeGenSchedModels::inferSchedClasses() {
+ DEBUG(dbgs() << NumInstrSchedClasses << " instr sched classes.\n");
+
+ // Visit all existing classes and newly created classes.
+ for (unsigned Idx = 0; Idx != SchedClasses.size(); ++Idx) {
+ assert(SchedClasses[Idx].Index == Idx && "bad SCIdx");
+
+ if (SchedClasses[Idx].ItinClassDef)
+ inferFromItinClass(SchedClasses[Idx].ItinClassDef, Idx);
+ if (!SchedClasses[Idx].InstRWs.empty())
+ inferFromInstRWs(Idx);
+ if (!SchedClasses[Idx].Writes.empty()) {
+ inferFromRW(SchedClasses[Idx].Writes, SchedClasses[Idx].Reads,
+ Idx, SchedClasses[Idx].ProcIndices);
+ }
+ assert(SchedClasses.size() < (NumInstrSchedClasses*6) &&
+ "too many SchedVariants");
+ }
+}
+
+/// Infer classes from per-processor itinerary resources.
+void CodeGenSchedModels::inferFromItinClass(Record *ItinClassDef,
+ unsigned FromClassIdx) {
+ for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) {
+ const CodeGenProcModel &PM = ProcModels[PIdx];
+ // For all ItinRW entries.
+ bool HasMatch = false;
+ for (RecIter II = PM.ItinRWDefs.begin(), IE = PM.ItinRWDefs.end();
+ II != IE; ++II) {
+ RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
+ if (!std::count(Matched.begin(), Matched.end(), ItinClassDef))
+ continue;
+ if (HasMatch)
+ PrintFatalError((*II)->getLoc(), "Duplicate itinerary class "
+ + ItinClassDef->getName()
+ + " in ItinResources for " + PM.ModelName);
+ HasMatch = true;
+ IdxVec Writes, Reads;
+ findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
+ IdxVec ProcIndices(1, PIdx);
+ inferFromRW(Writes, Reads, FromClassIdx, ProcIndices);
+ }
+ }
+}
+
+/// Infer classes from per-processor InstReadWrite definitions.
+void CodeGenSchedModels::inferFromInstRWs(unsigned SCIdx) {
+ for (unsigned I = 0, E = SchedClasses[SCIdx].InstRWs.size(); I != E; ++I) {
+ assert(SchedClasses[SCIdx].InstRWs.size() == E && "InstrRWs was mutated!");
+ Record *Rec = SchedClasses[SCIdx].InstRWs[I];
+ const RecVec *InstDefs = Sets.expand(Rec);
+ RecIter II = InstDefs->begin(), IE = InstDefs->end();
+ for (; II != IE; ++II) {
+ if (InstrClassMap[*II] == SCIdx)
+ break;
+ }
+ // If this class no longer has any instructions mapped to it, it has become
+ // irrelevant.
+ if (II == IE)
+ continue;
+ IdxVec Writes, Reads;
+ findRWs(Rec->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
+ unsigned PIdx = getProcModel(Rec->getValueAsDef("SchedModel")).Index;
+ IdxVec ProcIndices(1, PIdx);
+ inferFromRW(Writes, Reads, SCIdx, ProcIndices); // May mutate SchedClasses.
+ }
+}
+
+namespace {
+
+// Helper for substituteVariantOperand.
+struct TransVariant {
+ Record *VarOrSeqDef; // Variant or sequence.
+ unsigned RWIdx; // Index of this variant or sequence's matched type.
+ unsigned ProcIdx; // Processor model index or zero for any.
+ unsigned TransVecIdx; // Index into PredTransitions::TransVec.
+
+ TransVariant(Record *def, unsigned rwi, unsigned pi, unsigned ti):
+ VarOrSeqDef(def), RWIdx(rwi), ProcIdx(pi), TransVecIdx(ti) {}
+};
+
+// Associate a predicate with the SchedReadWrite that it guards.
+// RWIdx is the index of the read/write variant.
+struct PredCheck {
+ bool IsRead;
+ unsigned RWIdx;
+ Record *Predicate;
+
+ PredCheck(bool r, unsigned w, Record *p): IsRead(r), RWIdx(w), Predicate(p) {}
+};
+
+// A Predicate transition is a list of RW sequences guarded by a PredTerm.
+struct PredTransition {
+ // A predicate term is a conjunction of PredChecks.
+ SmallVector<PredCheck, 4> PredTerm;
+ SmallVector<SmallVector<unsigned,4>, 16> WriteSequences;
+ SmallVector<SmallVector<unsigned,4>, 16> ReadSequences;
+ SmallVector<unsigned, 4> ProcIndices;
+};
+
+// Encapsulate a set of partially constructed transitions.
+// The results are built by repeated calls to substituteVariants.
+class PredTransitions {
+ CodeGenSchedModels &SchedModels;
+
+public:
+ std::vector<PredTransition> TransVec;
+
+ PredTransitions(CodeGenSchedModels &sm): SchedModels(sm) {}
+
+ void substituteVariantOperand(const SmallVectorImpl<unsigned> &RWSeq,
+ bool IsRead, unsigned StartIdx);
+
+ void substituteVariants(const PredTransition &Trans);
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+
+private:
+ bool mutuallyExclusive(Record *PredDef, ArrayRef<PredCheck> Term);
+ void getIntersectingVariants(
+ const CodeGenSchedRW &SchedRW, unsigned TransIdx,
+ std::vector<TransVariant> &IntersectingVariants);
+ void pushVariant(const TransVariant &VInfo, bool IsRead);
+};
+
+} // end anonymous namespace
+
+// Return true if this predicate is mutually exclusive with a PredTerm. This
+// degenerates into checking if the predicate is mutually exclusive with any
+// predicate in the Term's conjunction.
+//
+// All predicates associated with a given SchedRW are considered mutually
+// exclusive. This should work even if the conditions expressed by the
+// predicates are not exclusive because the predicates for a given SchedWrite
+// are always checked in the order they are defined in the .td file. Later
+// conditions implicitly negate any prior condition.
+bool PredTransitions::mutuallyExclusive(Record *PredDef,
+ ArrayRef<PredCheck> Term) {
+ for (ArrayRef<PredCheck>::iterator I = Term.begin(), E = Term.end();
+ I != E; ++I) {
+ if (I->Predicate == PredDef)
+ return false;
+
+ const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(I->RWIdx, I->IsRead);
+ assert(SchedRW.HasVariants && "PredCheck must refer to a SchedVariant");
+ RecVec Variants = SchedRW.TheDef->getValueAsListOfDefs("Variants");
+ for (RecIter VI = Variants.begin(), VE = Variants.end(); VI != VE; ++VI) {
+ if ((*VI)->getValueAsDef("Predicate") == PredDef)
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool hasAliasedVariants(const CodeGenSchedRW &RW,
+ CodeGenSchedModels &SchedModels) {
+ if (RW.HasVariants)
+ return true;
+
+ for (RecIter I = RW.Aliases.begin(), E = RW.Aliases.end(); I != E; ++I) {
+ const CodeGenSchedRW &AliasRW =
+ SchedModels.getSchedRW((*I)->getValueAsDef("AliasRW"));
+ if (AliasRW.HasVariants)
+ return true;
+ if (AliasRW.IsSequence) {
+ IdxVec ExpandedRWs;
+ SchedModels.expandRWSequence(AliasRW.Index, ExpandedRWs, AliasRW.IsRead);
+ for (IdxIter SI = ExpandedRWs.begin(), SE = ExpandedRWs.end();
+ SI != SE; ++SI) {
+ if (hasAliasedVariants(SchedModels.getSchedRW(*SI, AliasRW.IsRead),
+ SchedModels)) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+static bool hasVariant(ArrayRef<PredTransition> Transitions,
+ CodeGenSchedModels &SchedModels) {
+ for (ArrayRef<PredTransition>::iterator
+ PTI = Transitions.begin(), PTE = Transitions.end();
+ PTI != PTE; ++PTI) {
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
+ WSI = PTI->WriteSequences.begin(), WSE = PTI->WriteSequences.end();
+ WSI != WSE; ++WSI) {
+ for (SmallVectorImpl<unsigned>::const_iterator
+ WI = WSI->begin(), WE = WSI->end(); WI != WE; ++WI) {
+ if (hasAliasedVariants(SchedModels.getSchedWrite(*WI), SchedModels))
+ return true;
+ }
+ }
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
+ RSI = PTI->ReadSequences.begin(), RSE = PTI->ReadSequences.end();
+ RSI != RSE; ++RSI) {
+ for (SmallVectorImpl<unsigned>::const_iterator
+ RI = RSI->begin(), RE = RSI->end(); RI != RE; ++RI) {
+ if (hasAliasedVariants(SchedModels.getSchedRead(*RI), SchedModels))
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Populate IntersectingVariants with any variants or aliased sequences of the
+// given SchedRW whose processor indices and predicates are not mutually
+// exclusive with the given transition.
+void PredTransitions::getIntersectingVariants(
+ const CodeGenSchedRW &SchedRW, unsigned TransIdx,
+ std::vector<TransVariant> &IntersectingVariants) {
+
+ bool GenericRW = false;
+
+ std::vector<TransVariant> Variants;
+ if (SchedRW.HasVariants) {
+ unsigned VarProcIdx = 0;
+ if (SchedRW.TheDef->getValueInit("SchedModel")->isComplete()) {
+ Record *ModelDef = SchedRW.TheDef->getValueAsDef("SchedModel");
+ VarProcIdx = SchedModels.getProcModel(ModelDef).Index;
+ }
+ // Push each variant. Assign TransVecIdx later.
+ const RecVec VarDefs = SchedRW.TheDef->getValueAsListOfDefs("Variants");
+ for (RecIter RI = VarDefs.begin(), RE = VarDefs.end(); RI != RE; ++RI)
+ Variants.push_back(TransVariant(*RI, SchedRW.Index, VarProcIdx, 0));
+ if (VarProcIdx == 0)
+ GenericRW = true;
+ }
+ for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
+ AI != AE; ++AI) {
+ // If either the SchedAlias itself or the SchedReadWrite that it aliases
+ // to is defined within a processor model, constrain all variants to
+ // that processor.
+ unsigned AliasProcIdx = 0;
+ if ((*AI)->getValueInit("SchedModel")->isComplete()) {
+ Record *ModelDef = (*AI)->getValueAsDef("SchedModel");
+ AliasProcIdx = SchedModels.getProcModel(ModelDef).Index;
+ }
+ const CodeGenSchedRW &AliasRW =
+ SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
+
+ if (AliasRW.HasVariants) {
+ const RecVec VarDefs = AliasRW.TheDef->getValueAsListOfDefs("Variants");
+ for (RecIter RI = VarDefs.begin(), RE = VarDefs.end(); RI != RE; ++RI)
+ Variants.push_back(TransVariant(*RI, AliasRW.Index, AliasProcIdx, 0));
+ }
+ if (AliasRW.IsSequence) {
+ Variants.push_back(
+ TransVariant(AliasRW.TheDef, SchedRW.Index, AliasProcIdx, 0));
+ }
+ if (AliasProcIdx == 0)
+ GenericRW = true;
+ }
+ for (unsigned VIdx = 0, VEnd = Variants.size(); VIdx != VEnd; ++VIdx) {
+ TransVariant &Variant = Variants[VIdx];
+ // Don't expand variants if the processor models don't intersect.
+ // A zero processor index means any processor.
+ SmallVectorImpl<unsigned> &ProcIndices = TransVec[TransIdx].ProcIndices;
+ if (ProcIndices[0] && Variants[VIdx].ProcIdx) {
+ unsigned Cnt = std::count(ProcIndices.begin(), ProcIndices.end(),
+ Variant.ProcIdx);
+ if (!Cnt)
+ continue;
+ if (Cnt > 1) {
+ const CodeGenProcModel &PM =
+ *(SchedModels.procModelBegin() + Variant.ProcIdx);
+ PrintFatalError(Variant.VarOrSeqDef->getLoc(),
+ "Multiple variants defined for processor " +
+ PM.ModelName +
+ " Ensure only one SchedAlias exists per RW.");
+ }
+ }
+ if (Variant.VarOrSeqDef->isSubClassOf("SchedVar")) {
+ Record *PredDef = Variant.VarOrSeqDef->getValueAsDef("Predicate");
+ if (mutuallyExclusive(PredDef, TransVec[TransIdx].PredTerm))
+ continue;
+ }
+ if (IntersectingVariants.empty()) {
+ // The first variant builds on the existing transition.
+ Variant.TransVecIdx = TransIdx;
+ IntersectingVariants.push_back(Variant);
+ }
+ else {
+ // Push another copy of the current transition for more variants.
+ Variant.TransVecIdx = TransVec.size();
+ IntersectingVariants.push_back(Variant);
+ TransVec.push_back(TransVec[TransIdx]);
+ }
+ }
+ if (GenericRW && IntersectingVariants.empty()) {
+ PrintFatalError(SchedRW.TheDef->getLoc(), "No variant of this type has "
+ "a matching predicate on any processor");
+ }
+}
+
+// Push the Reads/Writes selected by this variant onto the PredTransition
+// specified by VInfo.
+void PredTransitions::
+pushVariant(const TransVariant &VInfo, bool IsRead) {
+ PredTransition &Trans = TransVec[VInfo.TransVecIdx];
+
+ // If this operand transition is reached through a processor-specific alias,
+ // then the whole transition is specific to this processor.
+ if (VInfo.ProcIdx != 0)
+ Trans.ProcIndices.assign(1, VInfo.ProcIdx);
+
+ IdxVec SelectedRWs;
+ if (VInfo.VarOrSeqDef->isSubClassOf("SchedVar")) {
+ Record *PredDef = VInfo.VarOrSeqDef->getValueAsDef("Predicate");
+ Trans.PredTerm.push_back(PredCheck(IsRead, VInfo.RWIdx,PredDef));
+ RecVec SelectedDefs = VInfo.VarOrSeqDef->getValueAsListOfDefs("Selected");
+ SchedModels.findRWs(SelectedDefs, SelectedRWs, IsRead);
+ }
+ else {
+ assert(VInfo.VarOrSeqDef->isSubClassOf("WriteSequence") &&
+ "variant must be a SchedVariant or aliased WriteSequence");
+ SelectedRWs.push_back(SchedModels.getSchedRWIdx(VInfo.VarOrSeqDef, IsRead));
+ }
+
+ const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(VInfo.RWIdx, IsRead);
+
+ SmallVectorImpl<SmallVector<unsigned,4>> &RWSequences = IsRead
+ ? Trans.ReadSequences : Trans.WriteSequences;
+ if (SchedRW.IsVariadic) {
+ unsigned OperIdx = RWSequences.size()-1;
+ // Make N-1 copies of this transition's last sequence.
+ for (unsigned i = 1, e = SelectedRWs.size(); i != e; ++i) {
+ // Create a temporary copy the vector could reallocate.
+ RWSequences.reserve(RWSequences.size() + 1);
+ RWSequences.push_back(RWSequences[OperIdx]);
+ }
+ // Push each of the N elements of the SelectedRWs onto a copy of the last
+ // sequence (split the current operand into N operands).
+ // Note that write sequences should be expanded within this loop--the entire
+ // sequence belongs to a single operand.
+ for (IdxIter RWI = SelectedRWs.begin(), RWE = SelectedRWs.end();
+ RWI != RWE; ++RWI, ++OperIdx) {
+ IdxVec ExpandedRWs;
+ if (IsRead)
+ ExpandedRWs.push_back(*RWI);
+ else
+ SchedModels.expandRWSequence(*RWI, ExpandedRWs, IsRead);
+ RWSequences[OperIdx].insert(RWSequences[OperIdx].end(),
+ ExpandedRWs.begin(), ExpandedRWs.end());
+ }
+ assert(OperIdx == RWSequences.size() && "missed a sequence");
+ }
+ else {
+ // Push this transition's expanded sequence onto this transition's last
+ // sequence (add to the current operand's sequence).
+ SmallVectorImpl<unsigned> &Seq = RWSequences.back();
+ IdxVec ExpandedRWs;
+ for (IdxIter RWI = SelectedRWs.begin(), RWE = SelectedRWs.end();
+ RWI != RWE; ++RWI) {
+ if (IsRead)
+ ExpandedRWs.push_back(*RWI);
+ else
+ SchedModels.expandRWSequence(*RWI, ExpandedRWs, IsRead);
+ }
+ Seq.insert(Seq.end(), ExpandedRWs.begin(), ExpandedRWs.end());
+ }
+}
+
+// RWSeq is a sequence of all Reads or all Writes for the next read or write
+// operand. StartIdx is an index into TransVec where partial results
+// starts. RWSeq must be applied to all transitions between StartIdx and the end
+// of TransVec.
+void PredTransitions::substituteVariantOperand(
+ const SmallVectorImpl<unsigned> &RWSeq, bool IsRead, unsigned StartIdx) {
+
+ // Visit each original RW within the current sequence.
+ for (SmallVectorImpl<unsigned>::const_iterator
+ RWI = RWSeq.begin(), RWE = RWSeq.end(); RWI != RWE; ++RWI) {
+ const CodeGenSchedRW &SchedRW = SchedModels.getSchedRW(*RWI, IsRead);
+ // Push this RW on all partial PredTransitions or distribute variants.
+ // New PredTransitions may be pushed within this loop which should not be
+ // revisited (TransEnd must be loop invariant).
+ for (unsigned TransIdx = StartIdx, TransEnd = TransVec.size();
+ TransIdx != TransEnd; ++TransIdx) {
+ // In the common case, push RW onto the current operand's sequence.
+ if (!hasAliasedVariants(SchedRW, SchedModels)) {
+ if (IsRead)
+ TransVec[TransIdx].ReadSequences.back().push_back(*RWI);
+ else
+ TransVec[TransIdx].WriteSequences.back().push_back(*RWI);
+ continue;
+ }
+ // Distribute this partial PredTransition across intersecting variants.
+ // This will push a copies of TransVec[TransIdx] on the back of TransVec.
+ std::vector<TransVariant> IntersectingVariants;
+ getIntersectingVariants(SchedRW, TransIdx, IntersectingVariants);
+ // Now expand each variant on top of its copy of the transition.
+ for (std::vector<TransVariant>::const_iterator
+ IVI = IntersectingVariants.begin(),
+ IVE = IntersectingVariants.end();
+ IVI != IVE; ++IVI) {
+ pushVariant(*IVI, IsRead);
+ }
+ }
+ }
+}
+
+// For each variant of a Read/Write in Trans, substitute the sequence of
+// Read/Writes guarded by the variant. This is exponential in the number of
+// variant Read/Writes, but in practice detection of mutually exclusive
+// predicates should result in linear growth in the total number variants.
+//
+// This is one step in a breadth-first search of nested variants.
+void PredTransitions::substituteVariants(const PredTransition &Trans) {
+ // Build up a set of partial results starting at the back of
+ // PredTransitions. Remember the first new transition.
+ unsigned StartIdx = TransVec.size();
+ TransVec.resize(TransVec.size() + 1);
+ TransVec.back().PredTerm = Trans.PredTerm;
+ TransVec.back().ProcIndices = Trans.ProcIndices;
+
+ // Visit each original write sequence.
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
+ WSI = Trans.WriteSequences.begin(), WSE = Trans.WriteSequences.end();
+ WSI != WSE; ++WSI) {
+ // Push a new (empty) write sequence onto all partial Transitions.
+ for (std::vector<PredTransition>::iterator I =
+ TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) {
+ I->WriteSequences.resize(I->WriteSequences.size() + 1);
+ }
+ substituteVariantOperand(*WSI, /*IsRead=*/false, StartIdx);
+ }
+ // Visit each original read sequence.
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
+ RSI = Trans.ReadSequences.begin(), RSE = Trans.ReadSequences.end();
+ RSI != RSE; ++RSI) {
+ // Push a new (empty) read sequence onto all partial Transitions.
+ for (std::vector<PredTransition>::iterator I =
+ TransVec.begin() + StartIdx, E = TransVec.end(); I != E; ++I) {
+ I->ReadSequences.resize(I->ReadSequences.size() + 1);
+ }
+ substituteVariantOperand(*RSI, /*IsRead=*/true, StartIdx);
+ }
+}
+
+// Create a new SchedClass for each variant found by inferFromRW. Pass
+static void inferFromTransitions(ArrayRef<PredTransition> LastTransitions,
+ unsigned FromClassIdx,
+ CodeGenSchedModels &SchedModels) {
+ // For each PredTransition, create a new CodeGenSchedTransition, which usually
+ // requires creating a new SchedClass.
+ for (ArrayRef<PredTransition>::iterator
+ I = LastTransitions.begin(), E = LastTransitions.end(); I != E; ++I) {
+ IdxVec OperWritesVariant;
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
+ WSI = I->WriteSequences.begin(), WSE = I->WriteSequences.end();
+ WSI != WSE; ++WSI) {
+ // Create a new write representing the expanded sequence.
+ OperWritesVariant.push_back(
+ SchedModels.findOrInsertRW(*WSI, /*IsRead=*/false));
+ }
+ IdxVec OperReadsVariant;
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
+ RSI = I->ReadSequences.begin(), RSE = I->ReadSequences.end();
+ RSI != RSE; ++RSI) {
+ // Create a new read representing the expanded sequence.
+ OperReadsVariant.push_back(
+ SchedModels.findOrInsertRW(*RSI, /*IsRead=*/true));
+ }
+ IdxVec ProcIndices(I->ProcIndices.begin(), I->ProcIndices.end());
+ CodeGenSchedTransition SCTrans;
+ SCTrans.ToClassIdx =
+ SchedModels.addSchedClass(/*ItinClassDef=*/nullptr, OperWritesVariant,
+ OperReadsVariant, ProcIndices);
+ SCTrans.ProcIndices = ProcIndices;
+ // The final PredTerm is unique set of predicates guarding the transition.
+ RecVec Preds;
+ for (SmallVectorImpl<PredCheck>::const_iterator
+ PI = I->PredTerm.begin(), PE = I->PredTerm.end(); PI != PE; ++PI) {
+ Preds.push_back(PI->Predicate);
+ }
+ RecIter PredsEnd = std::unique(Preds.begin(), Preds.end());
+ Preds.resize(PredsEnd - Preds.begin());
+ SCTrans.PredTerm = Preds;
+ SchedModels.getSchedClass(FromClassIdx).Transitions.push_back(SCTrans);
+ }
+}
+
+// Create new SchedClasses for the given ReadWrite list. If any of the
+// ReadWrites refers to a SchedVariant, create a new SchedClass for each variant
+// of the ReadWrite list, following Aliases if necessary.
+void CodeGenSchedModels::inferFromRW(ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads,
+ unsigned FromClassIdx,
+ ArrayRef<unsigned> ProcIndices) {
+ DEBUG(dbgs() << "INFER RW proc("; dumpIdxVec(ProcIndices); dbgs() << ") ");
+
+ // Create a seed transition with an empty PredTerm and the expanded sequences
+ // of SchedWrites for the current SchedClass.
+ std::vector<PredTransition> LastTransitions;
+ LastTransitions.resize(1);
+ LastTransitions.back().ProcIndices.append(ProcIndices.begin(),
+ ProcIndices.end());
+
+ for (unsigned WriteIdx : OperWrites) {
+ IdxVec WriteSeq;
+ expandRWSequence(WriteIdx, WriteSeq, /*IsRead=*/false);
+ unsigned Idx = LastTransitions[0].WriteSequences.size();
+ LastTransitions[0].WriteSequences.resize(Idx + 1);
+ SmallVectorImpl<unsigned> &Seq = LastTransitions[0].WriteSequences[Idx];
+ for (IdxIter WI = WriteSeq.begin(), WE = WriteSeq.end(); WI != WE; ++WI)
+ Seq.push_back(*WI);
+ DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") ");
+ }
+ DEBUG(dbgs() << " Reads: ");
+ for (unsigned ReadIdx : OperReads) {
+ IdxVec ReadSeq;
+ expandRWSequence(ReadIdx, ReadSeq, /*IsRead=*/true);
+ unsigned Idx = LastTransitions[0].ReadSequences.size();
+ LastTransitions[0].ReadSequences.resize(Idx + 1);
+ SmallVectorImpl<unsigned> &Seq = LastTransitions[0].ReadSequences[Idx];
+ for (IdxIter RI = ReadSeq.begin(), RE = ReadSeq.end(); RI != RE; ++RI)
+ Seq.push_back(*RI);
+ DEBUG(dbgs() << "("; dumpIdxVec(Seq); dbgs() << ") ");
+ }
+ DEBUG(dbgs() << '\n');
+
+ // Collect all PredTransitions for individual operands.
+ // Iterate until no variant writes remain.
+ while (hasVariant(LastTransitions, *this)) {
+ PredTransitions Transitions(*this);
+ for (std::vector<PredTransition>::const_iterator
+ I = LastTransitions.begin(), E = LastTransitions.end();
+ I != E; ++I) {
+ Transitions.substituteVariants(*I);
+ }
+ DEBUG(Transitions.dump());
+ LastTransitions.swap(Transitions.TransVec);
+ }
+ // If the first transition has no variants, nothing to do.
+ if (LastTransitions[0].PredTerm.empty())
+ return;
+
+ // WARNING: We are about to mutate the SchedClasses vector. Do not refer to
+ // OperWrites, OperReads, or ProcIndices after calling inferFromTransitions.
+ inferFromTransitions(LastTransitions, FromClassIdx, *this);
+}
+
+// Check if any processor resource group contains all resource records in
+// SubUnits.
+bool CodeGenSchedModels::hasSuperGroup(RecVec &SubUnits, CodeGenProcModel &PM) {
+ for (unsigned i = 0, e = PM.ProcResourceDefs.size(); i < e; ++i) {
+ if (!PM.ProcResourceDefs[i]->isSubClassOf("ProcResGroup"))
+ continue;
+ RecVec SuperUnits =
+ PM.ProcResourceDefs[i]->getValueAsListOfDefs("Resources");
+ RecIter RI = SubUnits.begin(), RE = SubUnits.end();
+ for ( ; RI != RE; ++RI) {
+ if (!is_contained(SuperUnits, *RI)) {
+ break;
+ }
+ }
+ if (RI == RE)
+ return true;
+ }
+ return false;
+}
+
+// Verify that overlapping groups have a common supergroup.
+void CodeGenSchedModels::verifyProcResourceGroups(CodeGenProcModel &PM) {
+ for (unsigned i = 0, e = PM.ProcResourceDefs.size(); i < e; ++i) {
+ if (!PM.ProcResourceDefs[i]->isSubClassOf("ProcResGroup"))
+ continue;
+ RecVec CheckUnits =
+ PM.ProcResourceDefs[i]->getValueAsListOfDefs("Resources");
+ for (unsigned j = i+1; j < e; ++j) {
+ if (!PM.ProcResourceDefs[j]->isSubClassOf("ProcResGroup"))
+ continue;
+ RecVec OtherUnits =
+ PM.ProcResourceDefs[j]->getValueAsListOfDefs("Resources");
+ if (std::find_first_of(CheckUnits.begin(), CheckUnits.end(),
+ OtherUnits.begin(), OtherUnits.end())
+ != CheckUnits.end()) {
+ // CheckUnits and OtherUnits overlap
+ OtherUnits.insert(OtherUnits.end(), CheckUnits.begin(),
+ CheckUnits.end());
+ if (!hasSuperGroup(OtherUnits, PM)) {
+ PrintFatalError((PM.ProcResourceDefs[i])->getLoc(),
+ "proc resource group overlaps with "
+ + PM.ProcResourceDefs[j]->getName()
+ + " but no supergroup contains both.");
+ }
+ }
+ }
+ }
+}
+
+// Collect and sort WriteRes, ReadAdvance, and ProcResources.
+void CodeGenSchedModels::collectProcResources() {
+ ProcResourceDefs = Records.getAllDerivedDefinitions("ProcResourceUnits");
+ ProcResGroups = Records.getAllDerivedDefinitions("ProcResGroup");
+
+ // Add any subtarget-specific SchedReadWrites that are directly associated
+ // with processor resources. Refer to the parent SchedClass's ProcIndices to
+ // determine which processors they apply to.
+ for (SchedClassIter SCI = schedClassBegin(), SCE = schedClassEnd();
+ SCI != SCE; ++SCI) {
+ if (SCI->ItinClassDef)
+ collectItinProcResources(SCI->ItinClassDef);
+ else {
+ // This class may have a default ReadWrite list which can be overriden by
+ // InstRW definitions.
+ if (!SCI->InstRWs.empty()) {
+ for (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
+ RWI != RWE; ++RWI) {
+ Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
+ IdxVec ProcIndices(1, getProcModel(RWModelDef).Index);
+ IdxVec Writes, Reads;
+ findRWs((*RWI)->getValueAsListOfDefs("OperandReadWrites"),
+ Writes, Reads);
+ collectRWResources(Writes, Reads, ProcIndices);
+ }
+ }
+ collectRWResources(SCI->Writes, SCI->Reads, SCI->ProcIndices);
+ }
+ }
+ // Add resources separately defined by each subtarget.
+ RecVec WRDefs = Records.getAllDerivedDefinitions("WriteRes");
+ for (RecIter WRI = WRDefs.begin(), WRE = WRDefs.end(); WRI != WRE; ++WRI) {
+ Record *ModelDef = (*WRI)->getValueAsDef("SchedModel");
+ addWriteRes(*WRI, getProcModel(ModelDef).Index);
+ }
+ RecVec SWRDefs = Records.getAllDerivedDefinitions("SchedWriteRes");
+ for (RecIter WRI = SWRDefs.begin(), WRE = SWRDefs.end(); WRI != WRE; ++WRI) {
+ Record *ModelDef = (*WRI)->getValueAsDef("SchedModel");
+ addWriteRes(*WRI, getProcModel(ModelDef).Index);
+ }
+ RecVec RADefs = Records.getAllDerivedDefinitions("ReadAdvance");
+ for (RecIter RAI = RADefs.begin(), RAE = RADefs.end(); RAI != RAE; ++RAI) {
+ Record *ModelDef = (*RAI)->getValueAsDef("SchedModel");
+ addReadAdvance(*RAI, getProcModel(ModelDef).Index);
+ }
+ RecVec SRADefs = Records.getAllDerivedDefinitions("SchedReadAdvance");
+ for (RecIter RAI = SRADefs.begin(), RAE = SRADefs.end(); RAI != RAE; ++RAI) {
+ if ((*RAI)->getValueInit("SchedModel")->isComplete()) {
+ Record *ModelDef = (*RAI)->getValueAsDef("SchedModel");
+ addReadAdvance(*RAI, getProcModel(ModelDef).Index);
+ }
+ }
+ // Add ProcResGroups that are defined within this processor model, which may
+ // not be directly referenced but may directly specify a buffer size.
+ RecVec ProcResGroups = Records.getAllDerivedDefinitions("ProcResGroup");
+ for (RecIter RI = ProcResGroups.begin(), RE = ProcResGroups.end();
+ RI != RE; ++RI) {
+ if (!(*RI)->getValueInit("SchedModel")->isComplete())
+ continue;
+ CodeGenProcModel &PM = getProcModel((*RI)->getValueAsDef("SchedModel"));
+ if (!is_contained(PM.ProcResourceDefs, *RI))
+ PM.ProcResourceDefs.push_back(*RI);
+ }
+ // Finalize each ProcModel by sorting the record arrays.
+ for (CodeGenProcModel &PM : ProcModels) {
+ std::sort(PM.WriteResDefs.begin(), PM.WriteResDefs.end(),
+ LessRecord());
+ std::sort(PM.ReadAdvanceDefs.begin(), PM.ReadAdvanceDefs.end(),
+ LessRecord());
+ std::sort(PM.ProcResourceDefs.begin(), PM.ProcResourceDefs.end(),
+ LessRecord());
+ DEBUG(
+ PM.dump();
+ dbgs() << "WriteResDefs: ";
+ for (RecIter RI = PM.WriteResDefs.begin(),
+ RE = PM.WriteResDefs.end(); RI != RE; ++RI) {
+ if ((*RI)->isSubClassOf("WriteRes"))
+ dbgs() << (*RI)->getValueAsDef("WriteType")->getName() << " ";
+ else
+ dbgs() << (*RI)->getName() << " ";
+ }
+ dbgs() << "\nReadAdvanceDefs: ";
+ for (RecIter RI = PM.ReadAdvanceDefs.begin(),
+ RE = PM.ReadAdvanceDefs.end(); RI != RE; ++RI) {
+ if ((*RI)->isSubClassOf("ReadAdvance"))
+ dbgs() << (*RI)->getValueAsDef("ReadType")->getName() << " ";
+ else
+ dbgs() << (*RI)->getName() << " ";
+ }
+ dbgs() << "\nProcResourceDefs: ";
+ for (RecIter RI = PM.ProcResourceDefs.begin(),
+ RE = PM.ProcResourceDefs.end(); RI != RE; ++RI) {
+ dbgs() << (*RI)->getName() << " ";
+ }
+ dbgs() << '\n');
+ verifyProcResourceGroups(PM);
+ }
+
+ ProcResourceDefs.clear();
+ ProcResGroups.clear();
+}
+
+void CodeGenSchedModels::checkCompleteness() {
+ bool Complete = true;
+ bool HadCompleteModel = false;
+ for (const CodeGenProcModel &ProcModel : procModels()) {
+ if (!ProcModel.ModelDef->getValueAsBit("CompleteModel"))
+ continue;
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ if (Inst->hasNoSchedulingInfo)
+ continue;
+ if (ProcModel.isUnsupported(*Inst))
+ continue;
+ unsigned SCIdx = getSchedClassIdx(*Inst);
+ if (!SCIdx) {
+ if (Inst->TheDef->isValueUnset("SchedRW") && !HadCompleteModel) {
+ PrintError("No schedule information for instruction '"
+ + Inst->TheDef->getName() + "'");
+ Complete = false;
+ }
+ continue;
+ }
+
+ const CodeGenSchedClass &SC = getSchedClass(SCIdx);
+ if (!SC.Writes.empty())
+ continue;
+ if (SC.ItinClassDef != nullptr &&
+ SC.ItinClassDef->getName() != "NoItinerary")
+ continue;
+
+ const RecVec &InstRWs = SC.InstRWs;
+ auto I = find_if(InstRWs, [&ProcModel](const Record *R) {
+ return R->getValueAsDef("SchedModel") == ProcModel.ModelDef;
+ });
+ if (I == InstRWs.end()) {
+ PrintError("'" + ProcModel.ModelName + "' lacks information for '" +
+ Inst->TheDef->getName() + "'");
+ Complete = false;
+ }
+ }
+ HadCompleteModel = true;
+ }
+ if (!Complete) {
+ errs() << "\n\nIncomplete schedule models found.\n"
+ << "- Consider setting 'CompleteModel = 0' while developing new models.\n"
+ << "- Pseudo instructions can be marked with 'hasNoSchedulingInfo = 1'.\n"
+ << "- Instructions should usually have Sched<[...]> as a superclass, "
+ "you may temporarily use an empty list.\n"
+ << "- Instructions related to unsupported features can be excluded with "
+ "list<Predicate> UnsupportedFeatures = [HasA,..,HasY]; in the "
+ "processor model.\n\n";
+ PrintFatalError("Incomplete schedule model");
+ }
+}
+
+// Collect itinerary class resources for each processor.
+void CodeGenSchedModels::collectItinProcResources(Record *ItinClassDef) {
+ for (unsigned PIdx = 0, PEnd = ProcModels.size(); PIdx != PEnd; ++PIdx) {
+ const CodeGenProcModel &PM = ProcModels[PIdx];
+ // For all ItinRW entries.
+ bool HasMatch = false;
+ for (RecIter II = PM.ItinRWDefs.begin(), IE = PM.ItinRWDefs.end();
+ II != IE; ++II) {
+ RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
+ if (!std::count(Matched.begin(), Matched.end(), ItinClassDef))
+ continue;
+ if (HasMatch)
+ PrintFatalError((*II)->getLoc(), "Duplicate itinerary class "
+ + ItinClassDef->getName()
+ + " in ItinResources for " + PM.ModelName);
+ HasMatch = true;
+ IdxVec Writes, Reads;
+ findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"), Writes, Reads);
+ IdxVec ProcIndices(1, PIdx);
+ collectRWResources(Writes, Reads, ProcIndices);
+ }
+ }
+}
+
+void CodeGenSchedModels::collectRWResources(unsigned RWIdx, bool IsRead,
+ ArrayRef<unsigned> ProcIndices) {
+ const CodeGenSchedRW &SchedRW = getSchedRW(RWIdx, IsRead);
+ if (SchedRW.TheDef) {
+ if (!IsRead && SchedRW.TheDef->isSubClassOf("SchedWriteRes")) {
+ for (unsigned Idx : ProcIndices)
+ addWriteRes(SchedRW.TheDef, Idx);
+ }
+ else if (IsRead && SchedRW.TheDef->isSubClassOf("SchedReadAdvance")) {
+ for (unsigned Idx : ProcIndices)
+ addReadAdvance(SchedRW.TheDef, Idx);
+ }
+ }
+ for (RecIter AI = SchedRW.Aliases.begin(), AE = SchedRW.Aliases.end();
+ AI != AE; ++AI) {
+ IdxVec AliasProcIndices;
+ if ((*AI)->getValueInit("SchedModel")->isComplete()) {
+ AliasProcIndices.push_back(
+ getProcModel((*AI)->getValueAsDef("SchedModel")).Index);
+ }
+ else
+ AliasProcIndices = ProcIndices;
+ const CodeGenSchedRW &AliasRW = getSchedRW((*AI)->getValueAsDef("AliasRW"));
+ assert(AliasRW.IsRead == IsRead && "cannot alias reads to writes");
+
+ IdxVec ExpandedRWs;
+ expandRWSequence(AliasRW.Index, ExpandedRWs, IsRead);
+ for (IdxIter SI = ExpandedRWs.begin(), SE = ExpandedRWs.end();
+ SI != SE; ++SI) {
+ collectRWResources(*SI, IsRead, AliasProcIndices);
+ }
+ }
+}
+
+// Collect resources for a set of read/write types and processor indices.
+void CodeGenSchedModels::collectRWResources(ArrayRef<unsigned> Writes,
+ ArrayRef<unsigned> Reads,
+ ArrayRef<unsigned> ProcIndices) {
+ for (unsigned Idx : Writes)
+ collectRWResources(Idx, /*IsRead=*/false, ProcIndices);
+
+ for (unsigned Idx : Reads)
+ collectRWResources(Idx, /*IsRead=*/true, ProcIndices);
+}
+
+// Find the processor's resource units for this kind of resource.
+Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind,
+ const CodeGenProcModel &PM) const {
+ if (ProcResKind->isSubClassOf("ProcResourceUnits"))
+ return ProcResKind;
+
+ Record *ProcUnitDef = nullptr;
+ assert(!ProcResourceDefs.empty());
+ assert(!ProcResGroups.empty());
+
+ for (RecIter RI = ProcResourceDefs.begin(), RE = ProcResourceDefs.end();
+ RI != RE; ++RI) {
+
+ if ((*RI)->getValueAsDef("Kind") == ProcResKind
+ && (*RI)->getValueAsDef("SchedModel") == PM.ModelDef) {
+ if (ProcUnitDef) {
+ PrintFatalError((*RI)->getLoc(),
+ "Multiple ProcessorResourceUnits associated with "
+ + ProcResKind->getName());
+ }
+ ProcUnitDef = *RI;
+ }
+ }
+ for (RecIter RI = ProcResGroups.begin(), RE = ProcResGroups.end();
+ RI != RE; ++RI) {
+
+ if (*RI == ProcResKind
+ && (*RI)->getValueAsDef("SchedModel") == PM.ModelDef) {
+ if (ProcUnitDef) {
+ PrintFatalError((*RI)->getLoc(),
+ "Multiple ProcessorResourceUnits associated with "
+ + ProcResKind->getName());
+ }
+ ProcUnitDef = *RI;
+ }
+ }
+ if (!ProcUnitDef) {
+ PrintFatalError(ProcResKind->getLoc(),
+ "No ProcessorResources associated with "
+ + ProcResKind->getName());
+ }
+ return ProcUnitDef;
+}
+
+// Iteratively add a resource and its super resources.
+void CodeGenSchedModels::addProcResource(Record *ProcResKind,
+ CodeGenProcModel &PM) {
+ while (true) {
+ Record *ProcResUnits = findProcResUnits(ProcResKind, PM);
+
+ // See if this ProcResource is already associated with this processor.
+ if (is_contained(PM.ProcResourceDefs, ProcResUnits))
+ return;
+
+ PM.ProcResourceDefs.push_back(ProcResUnits);
+ if (ProcResUnits->isSubClassOf("ProcResGroup"))
+ return;
+
+ if (!ProcResUnits->getValueInit("Super")->isComplete())
+ return;
+
+ ProcResKind = ProcResUnits->getValueAsDef("Super");
+ }
+}
+
+// Add resources for a SchedWrite to this processor if they don't exist.
+void CodeGenSchedModels::addWriteRes(Record *ProcWriteResDef, unsigned PIdx) {
+ assert(PIdx && "don't add resources to an invalid Processor model");
+
+ RecVec &WRDefs = ProcModels[PIdx].WriteResDefs;
+ if (is_contained(WRDefs, ProcWriteResDef))
+ return;
+ WRDefs.push_back(ProcWriteResDef);
+
+ // Visit ProcResourceKinds referenced by the newly discovered WriteRes.
+ RecVec ProcResDefs = ProcWriteResDef->getValueAsListOfDefs("ProcResources");
+ for (RecIter WritePRI = ProcResDefs.begin(), WritePRE = ProcResDefs.end();
+ WritePRI != WritePRE; ++WritePRI) {
+ addProcResource(*WritePRI, ProcModels[PIdx]);
+ }
+}
+
+// Add resources for a ReadAdvance to this processor if they don't exist.
+void CodeGenSchedModels::addReadAdvance(Record *ProcReadAdvanceDef,
+ unsigned PIdx) {
+ RecVec &RADefs = ProcModels[PIdx].ReadAdvanceDefs;
+ if (is_contained(RADefs, ProcReadAdvanceDef))
+ return;
+ RADefs.push_back(ProcReadAdvanceDef);
+}
+
+unsigned CodeGenProcModel::getProcResourceIdx(Record *PRDef) const {
+ RecIter PRPos = find(ProcResourceDefs, PRDef);
+ if (PRPos == ProcResourceDefs.end())
+ PrintFatalError(PRDef->getLoc(), "ProcResource def is not included in "
+ "the ProcResources list for " + ModelName);
+ // Idx=0 is reserved for invalid.
+ return 1 + (PRPos - ProcResourceDefs.begin());
+}
+
+bool CodeGenProcModel::isUnsupported(const CodeGenInstruction &Inst) const {
+ for (const Record *TheDef : UnsupportedFeaturesDefs) {
+ for (const Record *PredDef : Inst.TheDef->getValueAsListOfDefs("Predicates")) {
+ if (TheDef->getName() == PredDef->getName())
+ return true;
+ }
+ }
+ return false;
+}
+
+#ifndef NDEBUG
+void CodeGenProcModel::dump() const {
+ dbgs() << Index << ": " << ModelName << " "
+ << (ModelDef ? ModelDef->getName() : "inferred") << " "
+ << (ItinsDef ? ItinsDef->getName() : "no itinerary") << '\n';
+}
+
+void CodeGenSchedRW::dump() const {
+ dbgs() << Name << (IsVariadic ? " (V) " : " ");
+ if (IsSequence) {
+ dbgs() << "(";
+ dumpIdxVec(Sequence);
+ dbgs() << ")";
+ }
+}
+
+void CodeGenSchedClass::dump(const CodeGenSchedModels* SchedModels) const {
+ dbgs() << "SCHEDCLASS " << Index << ":" << Name << '\n'
+ << " Writes: ";
+ for (unsigned i = 0, N = Writes.size(); i < N; ++i) {
+ SchedModels->getSchedWrite(Writes[i]).dump();
+ if (i < N-1) {
+ dbgs() << '\n';
+ dbgs().indent(10);
+ }
+ }
+ dbgs() << "\n Reads: ";
+ for (unsigned i = 0, N = Reads.size(); i < N; ++i) {
+ SchedModels->getSchedRead(Reads[i]).dump();
+ if (i < N-1) {
+ dbgs() << '\n';
+ dbgs().indent(10);
+ }
+ }
+ dbgs() << "\n ProcIdx: "; dumpIdxVec(ProcIndices); dbgs() << '\n';
+ if (!Transitions.empty()) {
+ dbgs() << "\n Transitions for Proc ";
+ for (std::vector<CodeGenSchedTransition>::const_iterator
+ TI = Transitions.begin(), TE = Transitions.end(); TI != TE; ++TI) {
+ dumpIdxVec(TI->ProcIndices);
+ }
+ }
+}
+
+void PredTransitions::dump() const {
+ dbgs() << "Expanded Variants:\n";
+ for (std::vector<PredTransition>::const_iterator
+ TI = TransVec.begin(), TE = TransVec.end(); TI != TE; ++TI) {
+ dbgs() << "{";
+ for (SmallVectorImpl<PredCheck>::const_iterator
+ PCI = TI->PredTerm.begin(), PCE = TI->PredTerm.end();
+ PCI != PCE; ++PCI) {
+ if (PCI != TI->PredTerm.begin())
+ dbgs() << ", ";
+ dbgs() << SchedModels.getSchedRW(PCI->RWIdx, PCI->IsRead).Name
+ << ":" << PCI->Predicate->getName();
+ }
+ dbgs() << "},\n => {";
+ for (SmallVectorImpl<SmallVector<unsigned,4>>::const_iterator
+ WSI = TI->WriteSequences.begin(), WSE = TI->WriteSequences.end();
+ WSI != WSE; ++WSI) {
+ dbgs() << "(";
+ for (SmallVectorImpl<unsigned>::const_iterator
+ WI = WSI->begin(), WE = WSI->end(); WI != WE; ++WI) {
+ if (WI != WSI->begin())
+ dbgs() << ", ";
+ dbgs() << SchedModels.getSchedWrite(*WI).Name;
+ }
+ dbgs() << "),";
+ }
+ dbgs() << "}\n";
+ }
+}
+#endif // NDEBUG
diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.h b/contrib/llvm/utils/TableGen/CodeGenSchedule.h
new file mode 100644
index 000000000000..755ffd25b0cb
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.h
@@ -0,0 +1,444 @@
+//===- CodeGenSchedule.h - Scheduling Machine Models ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines structures to encapsulate the machine model as described in
+// the target description.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H
+#define LLVM_UTILS_TABLEGEN_CODEGENSCHEDULE_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/SetTheory.h"
+
+namespace llvm {
+
+class CodeGenTarget;
+class CodeGenSchedModels;
+class CodeGenInstruction;
+
+typedef std::vector<Record*> RecVec;
+typedef std::vector<Record*>::const_iterator RecIter;
+
+typedef std::vector<unsigned> IdxVec;
+typedef std::vector<unsigned>::const_iterator IdxIter;
+
+void splitSchedReadWrites(const RecVec &RWDefs,
+ RecVec &WriteDefs, RecVec &ReadDefs);
+
+/// We have two kinds of SchedReadWrites. Explicitly defined and inferred
+/// sequences. TheDef is nonnull for explicit SchedWrites, but Sequence may or
+/// may not be empty. TheDef is null for inferred sequences, and Sequence must
+/// be nonempty.
+///
+/// IsVariadic controls whether the variants are expanded into multiple operands
+/// or a sequence of writes on one operand.
+struct CodeGenSchedRW {
+ unsigned Index;
+ std::string Name;
+ Record *TheDef;
+ bool IsRead;
+ bool IsAlias;
+ bool HasVariants;
+ bool IsVariadic;
+ bool IsSequence;
+ IdxVec Sequence;
+ RecVec Aliases;
+
+ CodeGenSchedRW()
+ : Index(0), TheDef(nullptr), IsRead(false), IsAlias(false),
+ HasVariants(false), IsVariadic(false), IsSequence(false) {}
+ CodeGenSchedRW(unsigned Idx, Record *Def)
+ : Index(Idx), TheDef(Def), IsAlias(false), IsVariadic(false) {
+ Name = Def->getName();
+ IsRead = Def->isSubClassOf("SchedRead");
+ HasVariants = Def->isSubClassOf("SchedVariant");
+ if (HasVariants)
+ IsVariadic = Def->getValueAsBit("Variadic");
+
+ // Read records don't currently have sequences, but it can be easily
+ // added. Note that implicit Reads (from ReadVariant) may have a Sequence
+ // (but no record).
+ IsSequence = Def->isSubClassOf("WriteSequence");
+ }
+
+ CodeGenSchedRW(unsigned Idx, bool Read, ArrayRef<unsigned> Seq,
+ const std::string &Name)
+ : Index(Idx), Name(Name), TheDef(nullptr), IsRead(Read), IsAlias(false),
+ HasVariants(false), IsVariadic(false), IsSequence(true), Sequence(Seq) {
+ assert(Sequence.size() > 1 && "implied sequence needs >1 RWs");
+ }
+
+ bool isValid() const {
+ assert((!HasVariants || TheDef) && "Variant write needs record def");
+ assert((!IsVariadic || HasVariants) && "Variadic write needs variants");
+ assert((!IsSequence || !HasVariants) && "Sequence can't have variant");
+ assert((!IsSequence || !Sequence.empty()) && "Sequence should be nonempty");
+ assert((!IsAlias || Aliases.empty()) && "Alias cannot have aliases");
+ return TheDef || !Sequence.empty();
+ }
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+};
+
+/// Represent a transition between SchedClasses induced by SchedVariant.
+struct CodeGenSchedTransition {
+ unsigned ToClassIdx;
+ IdxVec ProcIndices;
+ RecVec PredTerm;
+};
+
+/// Scheduling class.
+///
+/// Each instruction description will be mapped to a scheduling class. There are
+/// four types of classes:
+///
+/// 1) An explicitly defined itinerary class with ItinClassDef set.
+/// Writes and ReadDefs are empty. ProcIndices contains 0 for any processor.
+///
+/// 2) An implied class with a list of SchedWrites and SchedReads that are
+/// defined in an instruction definition and which are common across all
+/// subtargets. ProcIndices contains 0 for any processor.
+///
+/// 3) An implied class with a list of InstRW records that map instructions to
+/// SchedWrites and SchedReads per-processor. InstrClassMap should map the same
+/// instructions to this class. ProcIndices contains all the processors that
+/// provided InstrRW records for this class. ItinClassDef or Writes/Reads may
+/// still be defined for processors with no InstRW entry.
+///
+/// 4) An inferred class represents a variant of another class that may be
+/// resolved at runtime. ProcIndices contains the set of processors that may
+/// require the class. ProcIndices are propagated through SchedClasses as
+/// variants are expanded. Multiple SchedClasses may be inferred from an
+/// itinerary class. Each inherits the processor index from the ItinRW record
+/// that mapped the itinerary class to the variant Writes or Reads.
+struct CodeGenSchedClass {
+ unsigned Index;
+ std::string Name;
+ Record *ItinClassDef;
+
+ IdxVec Writes;
+ IdxVec Reads;
+ // Sorted list of ProcIdx, where ProcIdx==0 implies any processor.
+ IdxVec ProcIndices;
+
+ std::vector<CodeGenSchedTransition> Transitions;
+
+ // InstRW records associated with this class. These records may refer to an
+ // Instruction no longer mapped to this class by InstrClassMap. These
+ // Instructions should be ignored by this class because they have been split
+ // off to join another inferred class.
+ RecVec InstRWs;
+
+ CodeGenSchedClass(): Index(0), ItinClassDef(nullptr) {}
+
+ bool isKeyEqual(Record *IC, ArrayRef<unsigned> W, ArrayRef<unsigned> R) {
+ return ItinClassDef == IC && makeArrayRef(Writes) == W &&
+ makeArrayRef(Reads) == R;
+ }
+
+ // Is this class generated from a variants if existing classes? Instructions
+ // are never mapped directly to inferred scheduling classes.
+ bool isInferred() const { return !ItinClassDef; }
+
+#ifndef NDEBUG
+ void dump(const CodeGenSchedModels *SchedModels) const;
+#endif
+};
+
+// Processor model.
+//
+// ModelName is a unique name used to name an instantiation of MCSchedModel.
+//
+// ModelDef is NULL for inferred Models. This happens when a processor defines
+// an itinerary but no machine model. If the processor defines neither a machine
+// model nor itinerary, then ModelDef remains pointing to NoModel. NoModel has
+// the special "NoModel" field set to true.
+//
+// ItinsDef always points to a valid record definition, but may point to the
+// default NoItineraries. NoItineraries has an empty list of InstrItinData
+// records.
+//
+// ItinDefList orders this processor's InstrItinData records by SchedClass idx.
+struct CodeGenProcModel {
+ unsigned Index;
+ std::string ModelName;
+ Record *ModelDef;
+ Record *ItinsDef;
+
+ // Derived members...
+
+ // Array of InstrItinData records indexed by a CodeGenSchedClass index.
+ // This list is empty if the Processor has no value for Itineraries.
+ // Initialized by collectProcItins().
+ RecVec ItinDefList;
+
+ // Map itinerary classes to per-operand resources.
+ // This list is empty if no ItinRW refers to this Processor.
+ RecVec ItinRWDefs;
+
+ // List of unsupported feature.
+ // This list is empty if the Processor has no UnsupportedFeatures.
+ RecVec UnsupportedFeaturesDefs;
+
+ // All read/write resources associated with this processor.
+ RecVec WriteResDefs;
+ RecVec ReadAdvanceDefs;
+
+ // Per-operand machine model resources associated with this processor.
+ RecVec ProcResourceDefs;
+ RecVec ProcResGroupDefs;
+
+ CodeGenProcModel(unsigned Idx, const std::string &Name, Record *MDef,
+ Record *IDef) :
+ Index(Idx), ModelName(Name), ModelDef(MDef), ItinsDef(IDef) {}
+
+ bool hasItineraries() const {
+ return !ItinsDef->getValueAsListOfDefs("IID").empty();
+ }
+
+ bool hasInstrSchedModel() const {
+ return !WriteResDefs.empty() || !ItinRWDefs.empty();
+ }
+
+ unsigned getProcResourceIdx(Record *PRDef) const;
+
+ bool isUnsupported(const CodeGenInstruction &Inst) const;
+
+#ifndef NDEBUG
+ void dump() const;
+#endif
+};
+
+/// Top level container for machine model data.
+class CodeGenSchedModels {
+ RecordKeeper &Records;
+ const CodeGenTarget &Target;
+
+ // Map dag expressions to Instruction lists.
+ SetTheory Sets;
+
+ // List of unique processor models.
+ std::vector<CodeGenProcModel> ProcModels;
+
+ // Map Processor's MachineModel or ProcItin to a CodeGenProcModel index.
+ typedef DenseMap<Record*, unsigned> ProcModelMapTy;
+ ProcModelMapTy ProcModelMap;
+
+ // Per-operand SchedReadWrite types.
+ std::vector<CodeGenSchedRW> SchedWrites;
+ std::vector<CodeGenSchedRW> SchedReads;
+
+ // List of unique SchedClasses.
+ std::vector<CodeGenSchedClass> SchedClasses;
+
+ // Any inferred SchedClass has an index greater than NumInstrSchedClassses.
+ unsigned NumInstrSchedClasses;
+
+ RecVec ProcResourceDefs;
+ RecVec ProcResGroups;
+
+ // Map each instruction to its unique SchedClass index considering the
+ // combination of it's itinerary class, SchedRW list, and InstRW records.
+ typedef DenseMap<Record*, unsigned> InstClassMapTy;
+ InstClassMapTy InstrClassMap;
+
+public:
+ CodeGenSchedModels(RecordKeeper& RK, const CodeGenTarget &TGT);
+
+ // iterator access to the scheduling classes.
+ typedef std::vector<CodeGenSchedClass>::iterator class_iterator;
+ typedef std::vector<CodeGenSchedClass>::const_iterator const_class_iterator;
+ class_iterator classes_begin() { return SchedClasses.begin(); }
+ const_class_iterator classes_begin() const { return SchedClasses.begin(); }
+ class_iterator classes_end() { return SchedClasses.end(); }
+ const_class_iterator classes_end() const { return SchedClasses.end(); }
+ iterator_range<class_iterator> classes() {
+ return make_range(classes_begin(), classes_end());
+ }
+ iterator_range<const_class_iterator> classes() const {
+ return make_range(classes_begin(), classes_end());
+ }
+ iterator_range<class_iterator> explicit_classes() {
+ return make_range(classes_begin(), classes_begin() + NumInstrSchedClasses);
+ }
+ iterator_range<const_class_iterator> explicit_classes() const {
+ return make_range(classes_begin(), classes_begin() + NumInstrSchedClasses);
+ }
+
+ Record *getModelOrItinDef(Record *ProcDef) const {
+ Record *ModelDef = ProcDef->getValueAsDef("SchedModel");
+ Record *ItinsDef = ProcDef->getValueAsDef("ProcItin");
+ if (!ItinsDef->getValueAsListOfDefs("IID").empty()) {
+ assert(ModelDef->getValueAsBit("NoModel")
+ && "Itineraries must be defined within SchedMachineModel");
+ return ItinsDef;
+ }
+ return ModelDef;
+ }
+
+ const CodeGenProcModel &getModelForProc(Record *ProcDef) const {
+ Record *ModelDef = getModelOrItinDef(ProcDef);
+ ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
+ assert(I != ProcModelMap.end() && "missing machine model");
+ return ProcModels[I->second];
+ }
+
+ CodeGenProcModel &getProcModel(Record *ModelDef) {
+ ProcModelMapTy::const_iterator I = ProcModelMap.find(ModelDef);
+ assert(I != ProcModelMap.end() && "missing machine model");
+ return ProcModels[I->second];
+ }
+ const CodeGenProcModel &getProcModel(Record *ModelDef) const {
+ return const_cast<CodeGenSchedModels*>(this)->getProcModel(ModelDef);
+ }
+
+ // Iterate over the unique processor models.
+ typedef std::vector<CodeGenProcModel>::const_iterator ProcIter;
+ ProcIter procModelBegin() const { return ProcModels.begin(); }
+ ProcIter procModelEnd() const { return ProcModels.end(); }
+ ArrayRef<CodeGenProcModel> procModels() const { return ProcModels; }
+
+ // Return true if any processors have itineraries.
+ bool hasItineraries() const;
+
+ // Get a SchedWrite from its index.
+ const CodeGenSchedRW &getSchedWrite(unsigned Idx) const {
+ assert(Idx < SchedWrites.size() && "bad SchedWrite index");
+ assert(SchedWrites[Idx].isValid() && "invalid SchedWrite");
+ return SchedWrites[Idx];
+ }
+ // Get a SchedWrite from its index.
+ const CodeGenSchedRW &getSchedRead(unsigned Idx) const {
+ assert(Idx < SchedReads.size() && "bad SchedRead index");
+ assert(SchedReads[Idx].isValid() && "invalid SchedRead");
+ return SchedReads[Idx];
+ }
+
+ const CodeGenSchedRW &getSchedRW(unsigned Idx, bool IsRead) const {
+ return IsRead ? getSchedRead(Idx) : getSchedWrite(Idx);
+ }
+ CodeGenSchedRW &getSchedRW(Record *Def) {
+ bool IsRead = Def->isSubClassOf("SchedRead");
+ unsigned Idx = getSchedRWIdx(Def, IsRead);
+ return const_cast<CodeGenSchedRW&>(
+ IsRead ? getSchedRead(Idx) : getSchedWrite(Idx));
+ }
+ const CodeGenSchedRW &getSchedRW(Record*Def) const {
+ return const_cast<CodeGenSchedModels&>(*this).getSchedRW(Def);
+ }
+
+ unsigned getSchedRWIdx(Record *Def, bool IsRead, unsigned After = 0) const;
+
+ // Return true if the given write record is referenced by a ReadAdvance.
+ bool hasReadOfWrite(Record *WriteDef) const;
+
+ // Get a SchedClass from its index.
+ CodeGenSchedClass &getSchedClass(unsigned Idx) {
+ assert(Idx < SchedClasses.size() && "bad SchedClass index");
+ return SchedClasses[Idx];
+ }
+ const CodeGenSchedClass &getSchedClass(unsigned Idx) const {
+ assert(Idx < SchedClasses.size() && "bad SchedClass index");
+ return SchedClasses[Idx];
+ }
+
+ // Get the SchedClass index for an instruction. Instructions with no
+ // itinerary, no SchedReadWrites, and no InstrReadWrites references return 0
+ // for NoItinerary.
+ unsigned getSchedClassIdx(const CodeGenInstruction &Inst) const;
+
+ typedef std::vector<CodeGenSchedClass>::const_iterator SchedClassIter;
+ SchedClassIter schedClassBegin() const { return SchedClasses.begin(); }
+ SchedClassIter schedClassEnd() const { return SchedClasses.end(); }
+ ArrayRef<CodeGenSchedClass> schedClasses() const { return SchedClasses; }
+
+ unsigned numInstrSchedClasses() const { return NumInstrSchedClasses; }
+
+ void findRWs(const RecVec &RWDefs, IdxVec &Writes, IdxVec &Reads) const;
+ void findRWs(const RecVec &RWDefs, IdxVec &RWs, bool IsRead) const;
+ void expandRWSequence(unsigned RWIdx, IdxVec &RWSeq, bool IsRead) const;
+ void expandRWSeqForProc(unsigned RWIdx, IdxVec &RWSeq, bool IsRead,
+ const CodeGenProcModel &ProcModel) const;
+
+ unsigned addSchedClass(Record *ItinDef, ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads,
+ ArrayRef<unsigned> ProcIndices);
+
+ unsigned findOrInsertRW(ArrayRef<unsigned> Seq, bool IsRead);
+
+ unsigned findSchedClassIdx(Record *ItinClassDef, ArrayRef<unsigned> Writes,
+ ArrayRef<unsigned> Reads) const;
+
+ Record *findProcResUnits(Record *ProcResKind,
+ const CodeGenProcModel &PM) const;
+
+private:
+ void collectProcModels();
+
+ // Initialize a new processor model if it is unique.
+ void addProcModel(Record *ProcDef);
+
+ void collectSchedRW();
+
+ std::string genRWName(ArrayRef<unsigned> Seq, bool IsRead);
+ unsigned findRWForSequence(ArrayRef<unsigned> Seq, bool IsRead);
+
+ void collectSchedClasses();
+
+ std::string createSchedClassName(Record *ItinClassDef,
+ ArrayRef<unsigned> OperWrites,
+ ArrayRef<unsigned> OperReads);
+ std::string createSchedClassName(const RecVec &InstDefs);
+ void createInstRWClass(Record *InstRWDef);
+
+ void collectProcItins();
+
+ void collectProcItinRW();
+
+ void collectProcUnsupportedFeatures();
+
+ void inferSchedClasses();
+
+ void checkCompleteness();
+
+ void inferFromRW(ArrayRef<unsigned> OperWrites, ArrayRef<unsigned> OperReads,
+ unsigned FromClassIdx, ArrayRef<unsigned> ProcIndices);
+ void inferFromItinClass(Record *ItinClassDef, unsigned FromClassIdx);
+ void inferFromInstRWs(unsigned SCIdx);
+
+ bool hasSuperGroup(RecVec &SubUnits, CodeGenProcModel &PM);
+ void verifyProcResourceGroups(CodeGenProcModel &PM);
+
+ void collectProcResources();
+
+ void collectItinProcResources(Record *ItinClassDef);
+
+ void collectRWResources(unsigned RWIdx, bool IsRead,
+ ArrayRef<unsigned> ProcIndices);
+
+ void collectRWResources(ArrayRef<unsigned> Writes, ArrayRef<unsigned> Reads,
+ ArrayRef<unsigned> ProcIndices);
+
+ void addProcResource(Record *ProcResourceKind, CodeGenProcModel &PM);
+
+ void addWriteRes(Record *ProcWriteResDef, unsigned PIdx);
+
+ void addReadAdvance(Record *ProcReadAdvanceDef, unsigned PIdx);
+};
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
new file mode 100644
index 000000000000..03c58ac09c2d
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
@@ -0,0 +1,677 @@
+//===- CodeGenTarget.cpp - CodeGen Target Class Wrapper -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class wraps target description classes used by the various code
+// generation TableGen backends. This makes it easier to access the data and
+// provides a single place that needs to check it for validity. All of these
+// classes abort on error conditions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenTarget.h"
+#include "CodeGenIntrinsics.h"
+#include "CodeGenSchedule.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include <algorithm>
+using namespace llvm;
+
+cl::OptionCategory AsmParserCat("Options for -gen-asm-parser");
+cl::OptionCategory AsmWriterCat("Options for -gen-asm-writer");
+
+static cl::opt<unsigned>
+ AsmParserNum("asmparsernum", cl::init(0),
+ cl::desc("Make -gen-asm-parser emit assembly parser #N"),
+ cl::cat(AsmParserCat));
+
+static cl::opt<unsigned>
+ AsmWriterNum("asmwriternum", cl::init(0),
+ cl::desc("Make -gen-asm-writer emit assembly writer #N"),
+ cl::cat(AsmWriterCat));
+
+/// getValueType - Return the MVT::SimpleValueType that the specified TableGen
+/// record corresponds to.
+MVT::SimpleValueType llvm::getValueType(Record *Rec) {
+ return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
+}
+
+StringRef llvm::getName(MVT::SimpleValueType T) {
+ switch (T) {
+ case MVT::Other: return "UNKNOWN";
+ case MVT::iPTR: return "TLI.getPointerTy()";
+ case MVT::iPTRAny: return "TLI.getPointerTy()";
+ default: return getEnumName(T);
+ }
+}
+
+StringRef llvm::getEnumName(MVT::SimpleValueType T) {
+ switch (T) {
+ case MVT::Other: return "MVT::Other";
+ case MVT::i1: return "MVT::i1";
+ case MVT::i8: return "MVT::i8";
+ case MVT::i16: return "MVT::i16";
+ case MVT::i32: return "MVT::i32";
+ case MVT::i64: return "MVT::i64";
+ case MVT::i128: return "MVT::i128";
+ case MVT::Any: return "MVT::Any";
+ case MVT::iAny: return "MVT::iAny";
+ case MVT::fAny: return "MVT::fAny";
+ case MVT::vAny: return "MVT::vAny";
+ case MVT::f16: return "MVT::f16";
+ case MVT::f32: return "MVT::f32";
+ case MVT::f64: return "MVT::f64";
+ case MVT::f80: return "MVT::f80";
+ case MVT::f128: return "MVT::f128";
+ case MVT::ppcf128: return "MVT::ppcf128";
+ case MVT::x86mmx: return "MVT::x86mmx";
+ case MVT::Glue: return "MVT::Glue";
+ case MVT::isVoid: return "MVT::isVoid";
+ case MVT::v2i1: return "MVT::v2i1";
+ case MVT::v4i1: return "MVT::v4i1";
+ case MVT::v8i1: return "MVT::v8i1";
+ case MVT::v16i1: return "MVT::v16i1";
+ case MVT::v32i1: return "MVT::v32i1";
+ case MVT::v64i1: return "MVT::v64i1";
+ case MVT::v512i1: return "MVT::v512i1";
+ case MVT::v1024i1: return "MVT::v1024i1";
+ case MVT::v1i8: return "MVT::v1i8";
+ case MVT::v2i8: return "MVT::v2i8";
+ case MVT::v4i8: return "MVT::v4i8";
+ case MVT::v8i8: return "MVT::v8i8";
+ case MVT::v16i8: return "MVT::v16i8";
+ case MVT::v32i8: return "MVT::v32i8";
+ case MVT::v64i8: return "MVT::v64i8";
+ case MVT::v128i8: return "MVT::v128i8";
+ case MVT::v256i8: return "MVT::v256i8";
+ case MVT::v1i16: return "MVT::v1i16";
+ case MVT::v2i16: return "MVT::v2i16";
+ case MVT::v4i16: return "MVT::v4i16";
+ case MVT::v8i16: return "MVT::v8i16";
+ case MVT::v16i16: return "MVT::v16i16";
+ case MVT::v32i16: return "MVT::v32i16";
+ case MVT::v64i16: return "MVT::v64i16";
+ case MVT::v128i16: return "MVT::v128i16";
+ case MVT::v1i32: return "MVT::v1i32";
+ case MVT::v2i32: return "MVT::v2i32";
+ case MVT::v4i32: return "MVT::v4i32";
+ case MVT::v8i32: return "MVT::v8i32";
+ case MVT::v16i32: return "MVT::v16i32";
+ case MVT::v32i32: return "MVT::v32i32";
+ case MVT::v64i32: return "MVT::v64i32";
+ case MVT::v1i64: return "MVT::v1i64";
+ case MVT::v2i64: return "MVT::v2i64";
+ case MVT::v4i64: return "MVT::v4i64";
+ case MVT::v8i64: return "MVT::v8i64";
+ case MVT::v16i64: return "MVT::v16i64";
+ case MVT::v32i64: return "MVT::v32i64";
+ case MVT::v1i128: return "MVT::v1i128";
+ case MVT::v2f16: return "MVT::v2f16";
+ case MVT::v4f16: return "MVT::v4f16";
+ case MVT::v8f16: return "MVT::v8f16";
+ case MVT::v1f32: return "MVT::v1f32";
+ case MVT::v2f32: return "MVT::v2f32";
+ case MVT::v4f32: return "MVT::v4f32";
+ case MVT::v8f32: return "MVT::v8f32";
+ case MVT::v16f32: return "MVT::v16f32";
+ case MVT::v1f64: return "MVT::v1f64";
+ case MVT::v2f64: return "MVT::v2f64";
+ case MVT::v4f64: return "MVT::v4f64";
+ case MVT::v8f64: return "MVT::v8f64";
+ case MVT::nxv2i1: return "MVT::nxv2i1";
+ case MVT::nxv4i1: return "MVT::nxv4i1";
+ case MVT::nxv8i1: return "MVT::nxv8i1";
+ case MVT::nxv16i1: return "MVT::nxv16i1";
+ case MVT::nxv32i1: return "MVT::nxv32i1";
+ case MVT::nxv1i8: return "MVT::nxv1i8";
+ case MVT::nxv2i8: return "MVT::nxv2i8";
+ case MVT::nxv4i8: return "MVT::nxv4i8";
+ case MVT::nxv8i8: return "MVT::nxv8i8";
+ case MVT::nxv16i8: return "MVT::nxv16i8";
+ case MVT::nxv32i8: return "MVT::nxv32i8";
+ case MVT::nxv1i16: return "MVT::nxv1i16";
+ case MVT::nxv2i16: return "MVT::nxv2i16";
+ case MVT::nxv4i16: return "MVT::nxv4i16";
+ case MVT::nxv8i16: return "MVT::nxv8i16";
+ case MVT::nxv16i16: return "MVT::nxv16i16";
+ case MVT::nxv32i16: return "MVT::nxv32i16";
+ case MVT::nxv1i32: return "MVT::nxv1i32";
+ case MVT::nxv2i32: return "MVT::nxv2i32";
+ case MVT::nxv4i32: return "MVT::nxv4i32";
+ case MVT::nxv8i32: return "MVT::nxv8i32";
+ case MVT::nxv16i32: return "MVT::nxv16i32";
+ case MVT::nxv1i64: return "MVT::nxv1i64";
+ case MVT::nxv2i64: return "MVT::nxv2i64";
+ case MVT::nxv4i64: return "MVT::nxv4i64";
+ case MVT::nxv8i64: return "MVT::nxv8i64";
+ case MVT::nxv16i64: return "MVT::nxv16i64";
+ case MVT::nxv2f16: return "MVT::nxv2f16";
+ case MVT::nxv4f16: return "MVT::nxv4f16";
+ case MVT::nxv8f16: return "MVT::nxv8f16";
+ case MVT::nxv1f32: return "MVT::nxv1f32";
+ case MVT::nxv2f32: return "MVT::nxv2f32";
+ case MVT::nxv4f32: return "MVT::nxv4f32";
+ case MVT::nxv8f32: return "MVT::nxv8f32";
+ case MVT::nxv16f32: return "MVT::nxv16f32";
+ case MVT::nxv1f64: return "MVT::nxv1f64";
+ case MVT::nxv2f64: return "MVT::nxv2f64";
+ case MVT::nxv4f64: return "MVT::nxv4f64";
+ case MVT::nxv8f64: return "MVT::nxv8f64";
+ case MVT::token: return "MVT::token";
+ case MVT::Metadata: return "MVT::Metadata";
+ case MVT::iPTR: return "MVT::iPTR";
+ case MVT::iPTRAny: return "MVT::iPTRAny";
+ case MVT::Untyped: return "MVT::Untyped";
+ default: llvm_unreachable("ILLEGAL VALUE TYPE!");
+ }
+}
+
+/// getQualifiedName - Return the name of the specified record, with a
+/// namespace qualifier if the record contains one.
+///
+std::string llvm::getQualifiedName(const Record *R) {
+ std::string Namespace;
+ if (R->getValue("Namespace"))
+ Namespace = R->getValueAsString("Namespace");
+ if (Namespace.empty()) return R->getName();
+ return Namespace + "::" + R->getName().str();
+}
+
+
+/// getTarget - Return the current instance of the Target class.
+///
+CodeGenTarget::CodeGenTarget(RecordKeeper &records)
+ : Records(records) {
+ std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
+ if (Targets.size() == 0)
+ PrintFatalError("ERROR: No 'Target' subclasses defined!");
+ if (Targets.size() != 1)
+ PrintFatalError("ERROR: Multiple subclasses of Target defined!");
+ TargetRec = Targets[0];
+}
+
+CodeGenTarget::~CodeGenTarget() {
+}
+
+const StringRef CodeGenTarget::getName() const {
+ return TargetRec->getName();
+}
+
+std::string CodeGenTarget::getInstNamespace() const {
+ for (const CodeGenInstruction *Inst : getInstructionsByEnumValue()) {
+ // Make sure not to pick up "TargetOpcode" by accidentally getting
+ // the namespace off the PHI instruction or something.
+ if (Inst->Namespace != "TargetOpcode")
+ return Inst->Namespace;
+ }
+
+ return "";
+}
+
+Record *CodeGenTarget::getInstructionSet() const {
+ return TargetRec->getValueAsDef("InstructionSet");
+}
+
+
+/// getAsmParser - Return the AssemblyParser definition for this target.
+///
+Record *CodeGenTarget::getAsmParser() const {
+ std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyParsers");
+ if (AsmParserNum >= LI.size())
+ PrintFatalError("Target does not have an AsmParser #" +
+ Twine(AsmParserNum) + "!");
+ return LI[AsmParserNum];
+}
+
+/// getAsmParserVariant - Return the AssmblyParserVariant definition for
+/// this target.
+///
+Record *CodeGenTarget::getAsmParserVariant(unsigned i) const {
+ std::vector<Record*> LI =
+ TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
+ if (i >= LI.size())
+ PrintFatalError("Target does not have an AsmParserVariant #" + Twine(i) +
+ "!");
+ return LI[i];
+}
+
+/// getAsmParserVariantCount - Return the AssmblyParserVariant definition
+/// available for this target.
+///
+unsigned CodeGenTarget::getAsmParserVariantCount() const {
+ std::vector<Record*> LI =
+ TargetRec->getValueAsListOfDefs("AssemblyParserVariants");
+ return LI.size();
+}
+
+/// getAsmWriter - Return the AssemblyWriter definition for this target.
+///
+Record *CodeGenTarget::getAsmWriter() const {
+ std::vector<Record*> LI = TargetRec->getValueAsListOfDefs("AssemblyWriters");
+ if (AsmWriterNum >= LI.size())
+ PrintFatalError("Target does not have an AsmWriter #" +
+ Twine(AsmWriterNum) + "!");
+ return LI[AsmWriterNum];
+}
+
+CodeGenRegBank &CodeGenTarget::getRegBank() const {
+ if (!RegBank)
+ RegBank = llvm::make_unique<CodeGenRegBank>(Records);
+ return *RegBank;
+}
+
+void CodeGenTarget::ReadRegAltNameIndices() const {
+ RegAltNameIndices = Records.getAllDerivedDefinitions("RegAltNameIndex");
+ std::sort(RegAltNameIndices.begin(), RegAltNameIndices.end(), LessRecord());
+}
+
+/// getRegisterByName - If there is a register with the specific AsmName,
+/// return it.
+const CodeGenRegister *CodeGenTarget::getRegisterByName(StringRef Name) const {
+ const StringMap<CodeGenRegister*> &Regs = getRegBank().getRegistersByName();
+ StringMap<CodeGenRegister*>::const_iterator I = Regs.find(Name);
+ if (I == Regs.end())
+ return nullptr;
+ return I->second;
+}
+
+std::vector<MVT::SimpleValueType> CodeGenTarget::
+getRegisterVTs(Record *R) const {
+ const CodeGenRegister *Reg = getRegBank().getReg(R);
+ std::vector<MVT::SimpleValueType> Result;
+ for (const auto &RC : getRegBank().getRegClasses()) {
+ if (RC.contains(Reg)) {
+ ArrayRef<MVT::SimpleValueType> InVTs = RC.getValueTypes();
+ Result.insert(Result.end(), InVTs.begin(), InVTs.end());
+ }
+ }
+
+ // Remove duplicates.
+ array_pod_sort(Result.begin(), Result.end());
+ Result.erase(std::unique(Result.begin(), Result.end()), Result.end());
+ return Result;
+}
+
+
+void CodeGenTarget::ReadLegalValueTypes() const {
+ for (const auto &RC : getRegBank().getRegClasses())
+ LegalValueTypes.insert(LegalValueTypes.end(), RC.VTs.begin(), RC.VTs.end());
+
+ // Remove duplicates.
+ array_pod_sort(LegalValueTypes.begin(), LegalValueTypes.end());
+ LegalValueTypes.erase(std::unique(LegalValueTypes.begin(),
+ LegalValueTypes.end()),
+ LegalValueTypes.end());
+}
+
+CodeGenSchedModels &CodeGenTarget::getSchedModels() const {
+ if (!SchedModels)
+ SchedModels = llvm::make_unique<CodeGenSchedModels>(Records, *this);
+ return *SchedModels;
+}
+
+void CodeGenTarget::ReadInstructions() const {
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+ if (Insts.size() <= 2)
+ PrintFatalError("No 'Instruction' subclasses defined!");
+
+ // Parse the instructions defined in the .td file.
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i)
+ Instructions[Insts[i]] = llvm::make_unique<CodeGenInstruction>(Insts[i]);
+}
+
+static const CodeGenInstruction *
+GetInstByName(const char *Name,
+ const DenseMap<const Record*,
+ std::unique_ptr<CodeGenInstruction>> &Insts,
+ RecordKeeper &Records) {
+ const Record *Rec = Records.getDef(Name);
+
+ const auto I = Insts.find(Rec);
+ if (!Rec || I == Insts.end())
+ PrintFatalError(Twine("Could not find '") + Name + "' instruction!");
+ return I->second.get();
+}
+
+/// \brief Return all of the instructions defined by the target, ordered by
+/// their enum value.
+void CodeGenTarget::ComputeInstrsByEnum() const {
+ static const char *const FixedInstrs[] = {
+#define HANDLE_TARGET_OPCODE(OPC) #OPC,
+#include "llvm/Target/TargetOpcodes.def"
+ nullptr};
+ const auto &Insts = getInstructions();
+ for (const char *const *p = FixedInstrs; *p; ++p) {
+ const CodeGenInstruction *Instr = GetInstByName(*p, Insts, Records);
+ assert(Instr && "Missing target independent instruction");
+ assert(Instr->Namespace == "TargetOpcode" && "Bad namespace");
+ InstrsByEnum.push_back(Instr);
+ }
+ unsigned EndOfPredefines = InstrsByEnum.size();
+
+ for (const auto &I : Insts) {
+ const CodeGenInstruction *CGI = I.second.get();
+ if (CGI->Namespace != "TargetOpcode")
+ InstrsByEnum.push_back(CGI);
+ }
+
+ assert(InstrsByEnum.size() == Insts.size() && "Missing predefined instr");
+
+ // All of the instructions are now in random order based on the map iteration.
+ // Sort them by name.
+ std::sort(InstrsByEnum.begin() + EndOfPredefines, InstrsByEnum.end(),
+ [](const CodeGenInstruction *Rec1, const CodeGenInstruction *Rec2) {
+ return Rec1->TheDef->getName() < Rec2->TheDef->getName();
+ });
+}
+
+
+/// isLittleEndianEncoding - Return whether this target encodes its instruction
+/// in little-endian format, i.e. bits laid out in the order [0..n]
+///
+bool CodeGenTarget::isLittleEndianEncoding() const {
+ return getInstructionSet()->getValueAsBit("isLittleEndianEncoding");
+}
+
+/// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
+/// encodings, reverse the bit order of all instructions.
+void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
+ if (!isLittleEndianEncoding())
+ return;
+
+ std::vector<Record*> Insts = Records.getAllDerivedDefinitions("Instruction");
+ for (Record *R : Insts) {
+ if (R->getValueAsString("Namespace") == "TargetOpcode" ||
+ R->getValueAsBit("isPseudo"))
+ continue;
+
+ BitsInit *BI = R->getValueAsBitsInit("Inst");
+
+ unsigned numBits = BI->getNumBits();
+
+ SmallVector<Init *, 16> NewBits(numBits);
+
+ for (unsigned bit = 0, end = numBits / 2; bit != end; ++bit) {
+ unsigned bitSwapIdx = numBits - bit - 1;
+ Init *OrigBit = BI->getBit(bit);
+ Init *BitSwap = BI->getBit(bitSwapIdx);
+ NewBits[bit] = BitSwap;
+ NewBits[bitSwapIdx] = OrigBit;
+ }
+ if (numBits % 2) {
+ unsigned middle = (numBits + 1) / 2;
+ NewBits[middle] = BI->getBit(middle);
+ }
+
+ BitsInit *NewBI = BitsInit::get(NewBits);
+
+ // Update the bits in reversed order so that emitInstrOpBits will get the
+ // correct endianness.
+ R->getValue("Inst")->setValue(NewBI);
+ }
+}
+
+/// guessInstructionProperties - Return true if it's OK to guess instruction
+/// properties instead of raising an error.
+///
+/// This is configurable as a temporary migration aid. It will eventually be
+/// permanently false.
+bool CodeGenTarget::guessInstructionProperties() const {
+ return getInstructionSet()->getValueAsBit("guessInstructionProperties");
+}
+
+//===----------------------------------------------------------------------===//
+// ComplexPattern implementation
+//
+ComplexPattern::ComplexPattern(Record *R) {
+ Ty = ::getValueType(R->getValueAsDef("Ty"));
+ NumOperands = R->getValueAsInt("NumOperands");
+ SelectFunc = R->getValueAsString("SelectFunc");
+ RootNodes = R->getValueAsListOfDefs("RootNodes");
+
+ // FIXME: This is a hack to statically increase the priority of patterns which
+ // maps a sub-dag to a complex pattern. e.g. favors LEA over ADD. To get best
+ // possible pattern match we'll need to dynamically calculate the complexity
+ // of all patterns a dag can potentially map to.
+ int64_t RawComplexity = R->getValueAsInt("Complexity");
+ if (RawComplexity == -1)
+ Complexity = NumOperands * 3;
+ else
+ Complexity = RawComplexity;
+
+ // Parse the properties.
+ Properties = 0;
+ std::vector<Record*> PropList = R->getValueAsListOfDefs("Properties");
+ for (unsigned i = 0, e = PropList.size(); i != e; ++i)
+ if (PropList[i]->getName() == "SDNPHasChain") {
+ Properties |= 1 << SDNPHasChain;
+ } else if (PropList[i]->getName() == "SDNPOptInGlue") {
+ Properties |= 1 << SDNPOptInGlue;
+ } else if (PropList[i]->getName() == "SDNPMayStore") {
+ Properties |= 1 << SDNPMayStore;
+ } else if (PropList[i]->getName() == "SDNPMayLoad") {
+ Properties |= 1 << SDNPMayLoad;
+ } else if (PropList[i]->getName() == "SDNPSideEffect") {
+ Properties |= 1 << SDNPSideEffect;
+ } else if (PropList[i]->getName() == "SDNPMemOperand") {
+ Properties |= 1 << SDNPMemOperand;
+ } else if (PropList[i]->getName() == "SDNPVariadic") {
+ Properties |= 1 << SDNPVariadic;
+ } else if (PropList[i]->getName() == "SDNPWantRoot") {
+ Properties |= 1 << SDNPWantRoot;
+ } else if (PropList[i]->getName() == "SDNPWantParent") {
+ Properties |= 1 << SDNPWantParent;
+ } else {
+ PrintFatalError("Unsupported SD Node property '" +
+ PropList[i]->getName() + "' on ComplexPattern '" +
+ R->getName() + "'!");
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// CodeGenIntrinsic Implementation
+//===----------------------------------------------------------------------===//
+
+CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC,
+ bool TargetOnly) {
+ std::vector<Record*> Defs = RC.getAllDerivedDefinitions("Intrinsic");
+
+ Intrinsics.reserve(Defs.size());
+
+ for (unsigned I = 0, e = Defs.size(); I != e; ++I) {
+ bool isTarget = Defs[I]->getValueAsBit("isTarget");
+ if (isTarget == TargetOnly)
+ Intrinsics.push_back(CodeGenIntrinsic(Defs[I]));
+ }
+ std::sort(Intrinsics.begin(), Intrinsics.end(),
+ [](const CodeGenIntrinsic &LHS, const CodeGenIntrinsic &RHS) {
+ return std::tie(LHS.TargetPrefix, LHS.Name) <
+ std::tie(RHS.TargetPrefix, RHS.Name);
+ });
+ Targets.push_back({"", 0, 0});
+ for (size_t I = 0, E = Intrinsics.size(); I < E; ++I)
+ if (Intrinsics[I].TargetPrefix != Targets.back().Name) {
+ Targets.back().Count = I - Targets.back().Offset;
+ Targets.push_back({Intrinsics[I].TargetPrefix, I, 0});
+ }
+ Targets.back().Count = Intrinsics.size() - Targets.back().Offset;
+}
+
+CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
+ TheDef = R;
+ std::string DefName = R->getName();
+ ModRef = ReadWriteMem;
+ isOverloaded = false;
+ isCommutative = false;
+ canThrow = false;
+ isNoReturn = false;
+ isNoDuplicate = false;
+ isConvergent = false;
+
+ if (DefName.size() <= 4 ||
+ std::string(DefName.begin(), DefName.begin() + 4) != "int_")
+ PrintFatalError("Intrinsic '" + DefName + "' does not start with 'int_'!");
+
+ EnumName = std::string(DefName.begin()+4, DefName.end());
+
+ if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field.
+ GCCBuiltinName = R->getValueAsString("GCCBuiltinName");
+ if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field.
+ MSBuiltinName = R->getValueAsString("MSBuiltinName");
+
+ TargetPrefix = R->getValueAsString("TargetPrefix");
+ Name = R->getValueAsString("LLVMName");
+
+ if (Name == "") {
+ // If an explicit name isn't specified, derive one from the DefName.
+ Name = "llvm.";
+
+ for (unsigned i = 0, e = EnumName.size(); i != e; ++i)
+ Name += (EnumName[i] == '_') ? '.' : EnumName[i];
+ } else {
+ // Verify it starts with "llvm.".
+ if (Name.size() <= 5 ||
+ std::string(Name.begin(), Name.begin() + 5) != "llvm.")
+ PrintFatalError("Intrinsic '" + DefName + "'s name does not start with 'llvm.'!");
+ }
+
+ // If TargetPrefix is specified, make sure that Name starts with
+ // "llvm.<targetprefix>.".
+ if (!TargetPrefix.empty()) {
+ if (Name.size() < 6+TargetPrefix.size() ||
+ std::string(Name.begin() + 5, Name.begin() + 6 + TargetPrefix.size())
+ != (TargetPrefix + "."))
+ PrintFatalError("Intrinsic '" + DefName + "' does not start with 'llvm." +
+ TargetPrefix + ".'!");
+ }
+
+ // Parse the list of return types.
+ std::vector<MVT::SimpleValueType> OverloadedVTs;
+ ListInit *TypeList = R->getValueAsListInit("RetTypes");
+ for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
+ Record *TyEl = TypeList->getElementAsRecord(i);
+ assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
+ MVT::SimpleValueType VT;
+ if (TyEl->isSubClassOf("LLVMMatchType")) {
+ unsigned MatchTy = TyEl->getValueAsInt("Number");
+ assert(MatchTy < OverloadedVTs.size() &&
+ "Invalid matching number!");
+ VT = OverloadedVTs[MatchTy];
+ // It only makes sense to use the extended and truncated vector element
+ // variants with iAny types; otherwise, if the intrinsic is not
+ // overloaded, all the types can be specified directly.
+ assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
+ !TyEl->isSubClassOf("LLVMTruncatedType")) ||
+ VT == MVT::iAny || VT == MVT::vAny) &&
+ "Expected iAny or vAny type");
+ } else {
+ VT = getValueType(TyEl->getValueAsDef("VT"));
+ }
+ if (MVT(VT).isOverloaded()) {
+ OverloadedVTs.push_back(VT);
+ isOverloaded = true;
+ }
+
+ // Reject invalid types.
+ if (VT == MVT::isVoid)
+ PrintFatalError("Intrinsic '" + DefName + " has void in result type list!");
+
+ IS.RetVTs.push_back(VT);
+ IS.RetTypeDefs.push_back(TyEl);
+ }
+
+ // Parse the list of parameter types.
+ TypeList = R->getValueAsListInit("ParamTypes");
+ for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
+ Record *TyEl = TypeList->getElementAsRecord(i);
+ assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
+ MVT::SimpleValueType VT;
+ if (TyEl->isSubClassOf("LLVMMatchType")) {
+ unsigned MatchTy = TyEl->getValueAsInt("Number");
+ assert(MatchTy < OverloadedVTs.size() &&
+ "Invalid matching number!");
+ VT = OverloadedVTs[MatchTy];
+ // It only makes sense to use the extended and truncated vector element
+ // variants with iAny types; otherwise, if the intrinsic is not
+ // overloaded, all the types can be specified directly.
+ assert(((!TyEl->isSubClassOf("LLVMExtendedType") &&
+ !TyEl->isSubClassOf("LLVMTruncatedType") &&
+ !TyEl->isSubClassOf("LLVMVectorSameWidth")) ||
+ VT == MVT::iAny || VT == MVT::vAny) &&
+ "Expected iAny or vAny type");
+ } else
+ VT = getValueType(TyEl->getValueAsDef("VT"));
+
+ if (MVT(VT).isOverloaded()) {
+ OverloadedVTs.push_back(VT);
+ isOverloaded = true;
+ }
+
+ // Reject invalid types.
+ if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
+ PrintFatalError("Intrinsic '" + DefName + " has void in result type list!");
+
+ IS.ParamVTs.push_back(VT);
+ IS.ParamTypeDefs.push_back(TyEl);
+ }
+
+ // Parse the intrinsic properties.
+ ListInit *PropList = R->getValueAsListInit("IntrProperties");
+ for (unsigned i = 0, e = PropList->size(); i != e; ++i) {
+ Record *Property = PropList->getElementAsRecord(i);
+ assert(Property->isSubClassOf("IntrinsicProperty") &&
+ "Expected a property!");
+
+ if (Property->getName() == "IntrNoMem")
+ ModRef = NoMem;
+ else if (Property->getName() == "IntrReadMem")
+ ModRef = ModRefBehavior(ModRef & ~MR_Mod);
+ else if (Property->getName() == "IntrWriteMem")
+ ModRef = ModRefBehavior(ModRef & ~MR_Ref);
+ else if (Property->getName() == "IntrArgMemOnly")
+ ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem);
+ else if (Property->getName() == "IntrInaccessibleMemOnly")
+ ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_InaccessibleMem);
+ else if (Property->getName() == "IntrInaccessibleMemOrArgMemOnly")
+ ModRef = ModRefBehavior((ModRef & ~MR_Anywhere) | MR_ArgMem |
+ MR_InaccessibleMem);
+ else if (Property->getName() == "Commutative")
+ isCommutative = true;
+ else if (Property->getName() == "Throws")
+ canThrow = true;
+ else if (Property->getName() == "IntrNoDuplicate")
+ isNoDuplicate = true;
+ else if (Property->getName() == "IntrConvergent")
+ isConvergent = true;
+ else if (Property->getName() == "IntrNoReturn")
+ isNoReturn = true;
+ else if (Property->isSubClassOf("NoCapture")) {
+ unsigned ArgNo = Property->getValueAsInt("ArgNo");
+ ArgumentAttributes.push_back(std::make_pair(ArgNo, NoCapture));
+ } else if (Property->isSubClassOf("Returned")) {
+ unsigned ArgNo = Property->getValueAsInt("ArgNo");
+ ArgumentAttributes.push_back(std::make_pair(ArgNo, Returned));
+ } else if (Property->isSubClassOf("ReadOnly")) {
+ unsigned ArgNo = Property->getValueAsInt("ArgNo");
+ ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadOnly));
+ } else if (Property->isSubClassOf("WriteOnly")) {
+ unsigned ArgNo = Property->getValueAsInt("ArgNo");
+ ArgumentAttributes.push_back(std::make_pair(ArgNo, WriteOnly));
+ } else if (Property->isSubClassOf("ReadNone")) {
+ unsigned ArgNo = Property->getValueAsInt("ArgNo");
+ ArgumentAttributes.push_back(std::make_pair(ArgNo, ReadNone));
+ } else
+ llvm_unreachable("Unknown property!");
+ }
+
+ // Sort the argument attributes for later benefit.
+ std::sort(ArgumentAttributes.begin(), ArgumentAttributes.end());
+}
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h
new file mode 100644
index 000000000000..c822e940ffae
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h
@@ -0,0 +1,215 @@
+//===- CodeGenTarget.h - Target Class Wrapper -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines wrappers for the Target class and related global
+// functionality. This makes it easier to access the data and provides a single
+// place that needs to check it for validity. All of these classes abort
+// on error conditions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_CODEGENTARGET_H
+#define LLVM_UTILS_TABLEGEN_CODEGENTARGET_H
+
+#include "CodeGenInstruction.h"
+#include "CodeGenRegisters.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Record.h"
+#include <algorithm>
+
+namespace llvm {
+
+struct CodeGenRegister;
+class CodeGenSchedModels;
+class CodeGenTarget;
+
+// SelectionDAG node properties.
+// SDNPMemOperand: indicates that a node touches memory and therefore must
+// have an associated memory operand that describes the access.
+enum SDNP {
+ SDNPCommutative,
+ SDNPAssociative,
+ SDNPHasChain,
+ SDNPOutGlue,
+ SDNPInGlue,
+ SDNPOptInGlue,
+ SDNPMayLoad,
+ SDNPMayStore,
+ SDNPSideEffect,
+ SDNPMemOperand,
+ SDNPVariadic,
+ SDNPWantRoot,
+ SDNPWantParent
+};
+
+/// getValueType - Return the MVT::SimpleValueType that the specified TableGen
+/// record corresponds to.
+MVT::SimpleValueType getValueType(Record *Rec);
+
+StringRef getName(MVT::SimpleValueType T);
+StringRef getEnumName(MVT::SimpleValueType T);
+
+/// getQualifiedName - Return the name of the specified record, with a
+/// namespace qualifier if the record contains one.
+std::string getQualifiedName(const Record *R);
+
+/// CodeGenTarget - This class corresponds to the Target class in the .td files.
+///
+class CodeGenTarget {
+ RecordKeeper &Records;
+ Record *TargetRec;
+
+ mutable DenseMap<const Record*,
+ std::unique_ptr<CodeGenInstruction>> Instructions;
+ mutable std::unique_ptr<CodeGenRegBank> RegBank;
+ mutable std::vector<Record*> RegAltNameIndices;
+ mutable SmallVector<MVT::SimpleValueType, 8> LegalValueTypes;
+ void ReadRegAltNameIndices() const;
+ void ReadInstructions() const;
+ void ReadLegalValueTypes() const;
+
+ mutable std::unique_ptr<CodeGenSchedModels> SchedModels;
+
+ mutable std::vector<const CodeGenInstruction*> InstrsByEnum;
+public:
+ CodeGenTarget(RecordKeeper &Records);
+ ~CodeGenTarget();
+
+ Record *getTargetRecord() const { return TargetRec; }
+ const StringRef getName() const;
+
+ /// getInstNamespace - Return the target-specific instruction namespace.
+ ///
+ std::string getInstNamespace() const;
+
+ /// getInstructionSet - Return the InstructionSet object.
+ ///
+ Record *getInstructionSet() const;
+
+ /// getAsmParser - Return the AssemblyParser definition for this target.
+ ///
+ Record *getAsmParser() const;
+
+ /// getAsmParserVariant - Return the AssmblyParserVariant definition for
+ /// this target.
+ ///
+ Record *getAsmParserVariant(unsigned i) const;
+
+ /// getAsmParserVariantCount - Return the AssmblyParserVariant definition
+ /// available for this target.
+ ///
+ unsigned getAsmParserVariantCount() const;
+
+ /// getAsmWriter - Return the AssemblyWriter definition for this target.
+ ///
+ Record *getAsmWriter() const;
+
+ /// getRegBank - Return the register bank description.
+ CodeGenRegBank &getRegBank() const;
+
+ /// getRegisterByName - If there is a register with the specific AsmName,
+ /// return it.
+ const CodeGenRegister *getRegisterByName(StringRef Name) const;
+
+ const std::vector<Record*> &getRegAltNameIndices() const {
+ if (RegAltNameIndices.empty()) ReadRegAltNameIndices();
+ return RegAltNameIndices;
+ }
+
+ const CodeGenRegisterClass &getRegisterClass(Record *R) const {
+ return *getRegBank().getRegClass(R);
+ }
+
+ /// getRegisterVTs - Find the union of all possible SimpleValueTypes for the
+ /// specified physical register.
+ std::vector<MVT::SimpleValueType> getRegisterVTs(Record *R) const;
+
+ ArrayRef<MVT::SimpleValueType> getLegalValueTypes() const {
+ if (LegalValueTypes.empty()) ReadLegalValueTypes();
+ return LegalValueTypes;
+ }
+
+ /// isLegalValueType - Return true if the specified value type is natively
+ /// supported by the target (i.e. there are registers that directly hold it).
+ bool isLegalValueType(MVT::SimpleValueType VT) const {
+ ArrayRef<MVT::SimpleValueType> LegalVTs = getLegalValueTypes();
+ return is_contained(LegalVTs, VT);
+ }
+
+ CodeGenSchedModels &getSchedModels() const;
+
+private:
+ DenseMap<const Record*, std::unique_ptr<CodeGenInstruction>> &
+ getInstructions() const {
+ if (Instructions.empty()) ReadInstructions();
+ return Instructions;
+ }
+public:
+
+ CodeGenInstruction &getInstruction(const Record *InstRec) const {
+ if (Instructions.empty()) ReadInstructions();
+ auto I = Instructions.find(InstRec);
+ assert(I != Instructions.end() && "Not an instruction");
+ return *I->second;
+ }
+
+ /// getInstructionsByEnumValue - Return all of the instructions defined by the
+ /// target, ordered by their enum value.
+ ArrayRef<const CodeGenInstruction *>
+ getInstructionsByEnumValue() const {
+ if (InstrsByEnum.empty()) ComputeInstrsByEnum();
+ return InstrsByEnum;
+ }
+
+ typedef ArrayRef<const CodeGenInstruction *>::const_iterator inst_iterator;
+ inst_iterator inst_begin() const{return getInstructionsByEnumValue().begin();}
+ inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); }
+
+
+ /// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]?
+ ///
+ bool isLittleEndianEncoding() const;
+
+ /// reverseBitsForLittleEndianEncoding - For little-endian instruction bit
+ /// encodings, reverse the bit order of all instructions.
+ void reverseBitsForLittleEndianEncoding();
+
+ /// guessInstructionProperties - should we just guess unset instruction
+ /// properties?
+ bool guessInstructionProperties() const;
+
+private:
+ void ComputeInstrsByEnum() const;
+};
+
+/// ComplexPattern - ComplexPattern info, corresponding to the ComplexPattern
+/// tablegen class in TargetSelectionDAG.td
+class ComplexPattern {
+ MVT::SimpleValueType Ty;
+ unsigned NumOperands;
+ std::string SelectFunc;
+ std::vector<Record*> RootNodes;
+ unsigned Properties; // Node properties
+ unsigned Complexity;
+public:
+ ComplexPattern(Record *R);
+
+ MVT::SimpleValueType getValueType() const { return Ty; }
+ unsigned getNumOperands() const { return NumOperands; }
+ const std::string &getSelectFunc() const { return SelectFunc; }
+ const std::vector<Record*> &getRootNodes() const {
+ return RootNodes;
+ }
+ bool hasProperty(enum SDNP Prop) const { return Properties & (1 << Prop); }
+ unsigned getComplexity() const { return Complexity; }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp
new file mode 100644
index 000000000000..60fe866f194d
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelEmitter.cpp
@@ -0,0 +1,174 @@
+//===- DAGISelEmitter.cpp - Generate an instruction selector --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits a DAG instruction selector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenDAGPatterns.h"
+#include "DAGISelMatcher.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "dag-isel-emitter"
+
+namespace {
+/// DAGISelEmitter - The top-level class which coordinates construction
+/// and emission of the instruction selector.
+class DAGISelEmitter {
+ CodeGenDAGPatterns CGP;
+public:
+ explicit DAGISelEmitter(RecordKeeper &R) : CGP(R) {}
+ void run(raw_ostream &OS);
+};
+} // End anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// DAGISelEmitter Helper methods
+//
+
+/// getResultPatternCost - Compute the number of instructions for this pattern.
+/// This is a temporary hack. We should really include the instruction
+/// latencies in this calculation.
+static unsigned getResultPatternCost(TreePatternNode *P,
+ CodeGenDAGPatterns &CGP) {
+ if (P->isLeaf()) return 0;
+
+ unsigned Cost = 0;
+ Record *Op = P->getOperator();
+ if (Op->isSubClassOf("Instruction")) {
+ Cost++;
+ CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op);
+ if (II.usesCustomInserter)
+ Cost += 10;
+ }
+ for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
+ Cost += getResultPatternCost(P->getChild(i), CGP);
+ return Cost;
+}
+
+/// getResultPatternCodeSize - Compute the code size of instructions for this
+/// pattern.
+static unsigned getResultPatternSize(TreePatternNode *P,
+ CodeGenDAGPatterns &CGP) {
+ if (P->isLeaf()) return 0;
+
+ unsigned Cost = 0;
+ Record *Op = P->getOperator();
+ if (Op->isSubClassOf("Instruction")) {
+ Cost += Op->getValueAsInt("CodeSize");
+ }
+ for (unsigned i = 0, e = P->getNumChildren(); i != e; ++i)
+ Cost += getResultPatternSize(P->getChild(i), CGP);
+ return Cost;
+}
+
+namespace {
+// PatternSortingPredicate - return true if we prefer to match LHS before RHS.
+// In particular, we want to match maximal patterns first and lowest cost within
+// a particular complexity first.
+struct PatternSortingPredicate {
+ PatternSortingPredicate(CodeGenDAGPatterns &cgp) : CGP(cgp) {}
+ CodeGenDAGPatterns &CGP;
+
+ bool operator()(const PatternToMatch *LHS, const PatternToMatch *RHS) {
+ const TreePatternNode *LHSSrc = LHS->getSrcPattern();
+ const TreePatternNode *RHSSrc = RHS->getSrcPattern();
+
+ MVT LHSVT = (LHSSrc->getNumTypes() != 0 ? LHSSrc->getType(0) : MVT::Other);
+ MVT RHSVT = (RHSSrc->getNumTypes() != 0 ? RHSSrc->getType(0) : MVT::Other);
+ if (LHSVT.isVector() != RHSVT.isVector())
+ return RHSVT.isVector();
+
+ if (LHSVT.isFloatingPoint() != RHSVT.isFloatingPoint())
+ return RHSVT.isFloatingPoint();
+
+ // Otherwise, if the patterns might both match, sort based on complexity,
+ // which means that we prefer to match patterns that cover more nodes in the
+ // input over nodes that cover fewer.
+ int LHSSize = LHS->getPatternComplexity(CGP);
+ int RHSSize = RHS->getPatternComplexity(CGP);
+ if (LHSSize > RHSSize) return true; // LHS -> bigger -> less cost
+ if (LHSSize < RHSSize) return false;
+
+ // If the patterns have equal complexity, compare generated instruction cost
+ unsigned LHSCost = getResultPatternCost(LHS->getDstPattern(), CGP);
+ unsigned RHSCost = getResultPatternCost(RHS->getDstPattern(), CGP);
+ if (LHSCost < RHSCost) return true;
+ if (LHSCost > RHSCost) return false;
+
+ unsigned LHSPatSize = getResultPatternSize(LHS->getDstPattern(), CGP);
+ unsigned RHSPatSize = getResultPatternSize(RHS->getDstPattern(), CGP);
+ if (LHSPatSize < RHSPatSize) return true;
+ if (LHSPatSize > RHSPatSize) return false;
+
+ // Sort based on the UID of the pattern, giving us a deterministic ordering
+ // if all other sorting conditions fail.
+ assert(LHS == RHS || LHS->ID != RHS->ID);
+ return LHS->ID < RHS->ID;
+ }
+};
+} // End anonymous namespace
+
+
+void DAGISelEmitter::run(raw_ostream &OS) {
+ emitSourceFileHeader("DAG Instruction Selector for the " +
+ CGP.getTargetInfo().getName().str() + " target", OS);
+
+ OS << "// *** NOTE: This file is #included into the middle of the target\n"
+ << "// *** instruction selector class. These functions are really "
+ << "methods.\n\n";
+
+ DEBUG(errs() << "\n\nALL PATTERNS TO MATCH:\n\n";
+ for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
+ E = CGP.ptm_end(); I != E; ++I) {
+ errs() << "PATTERN: "; I->getSrcPattern()->dump();
+ errs() << "\nRESULT: "; I->getDstPattern()->dump();
+ errs() << "\n";
+ });
+
+ // Add all the patterns to a temporary list so we can sort them.
+ std::vector<const PatternToMatch*> Patterns;
+ for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(), E = CGP.ptm_end();
+ I != E; ++I)
+ Patterns.push_back(&*I);
+
+ // We want to process the matches in order of minimal cost. Sort the patterns
+ // so the least cost one is at the start.
+ std::sort(Patterns.begin(), Patterns.end(), PatternSortingPredicate(CGP));
+
+
+ // Convert each variant of each pattern into a Matcher.
+ std::vector<Matcher*> PatternMatchers;
+ for (unsigned i = 0, e = Patterns.size(); i != e; ++i) {
+ for (unsigned Variant = 0; ; ++Variant) {
+ if (Matcher *M = ConvertPatternToMatcher(*Patterns[i], Variant, CGP))
+ PatternMatchers.push_back(M);
+ else
+ break;
+ }
+ }
+
+ std::unique_ptr<Matcher> TheMatcher =
+ llvm::make_unique<ScopeMatcher>(PatternMatchers);
+
+ OptimizeMatcher(TheMatcher, CGP);
+ //Matcher->dump();
+ EmitMatcherTable(TheMatcher.get(), CGP, OS);
+}
+
+namespace llvm {
+
+void EmitDAGISel(RecordKeeper &RK, raw_ostream &OS) {
+ DAGISelEmitter(RK).run(OS);
+}
+
+} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp
new file mode 100644
index 000000000000..6ac3958e0f43
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp
@@ -0,0 +1,391 @@
+//===- DAGISelMatcher.cpp - Representation of DAG pattern matcher ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "CodeGenTarget.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Record.h"
+using namespace llvm;
+
+void Matcher::anchor() { }
+
+void Matcher::dump() const {
+ print(errs(), 0);
+}
+
+void Matcher::print(raw_ostream &OS, unsigned indent) const {
+ printImpl(OS, indent);
+ if (Next)
+ return Next->print(OS, indent);
+}
+
+void Matcher::printOne(raw_ostream &OS) const {
+ printImpl(OS, 0);
+}
+
+/// unlinkNode - Unlink the specified node from this chain. If Other == this,
+/// we unlink the next pointer and return it. Otherwise we unlink Other from
+/// the list and return this.
+Matcher *Matcher::unlinkNode(Matcher *Other) {
+ if (this == Other)
+ return takeNext();
+
+ // Scan until we find the predecessor of Other.
+ Matcher *Cur = this;
+ for (; Cur && Cur->getNext() != Other; Cur = Cur->getNext())
+ /*empty*/;
+
+ if (!Cur) return nullptr;
+ Cur->takeNext();
+ Cur->setNext(Other->takeNext());
+ return this;
+}
+
+/// canMoveBefore - Return true if this matcher is the same as Other, or if
+/// we can move this matcher past all of the nodes in-between Other and this
+/// node. Other must be equal to or before this.
+bool Matcher::canMoveBefore(const Matcher *Other) const {
+ for (;; Other = Other->getNext()) {
+ assert(Other && "Other didn't come before 'this'?");
+ if (this == Other) return true;
+
+ // We have to be able to move this node across the Other node.
+ if (!canMoveBeforeNode(Other))
+ return false;
+ }
+}
+
+/// canMoveBeforeNode - Return true if it is safe to move the current matcher
+/// across the specified one.
+bool Matcher::canMoveBeforeNode(const Matcher *Other) const {
+ // We can move simple predicates before record nodes.
+ if (isSimplePredicateNode())
+ return Other->isSimplePredicateOrRecordNode();
+
+ // We can move record nodes across simple predicates.
+ if (isSimplePredicateOrRecordNode())
+ return isSimplePredicateNode();
+
+ // We can't move record nodes across each other etc.
+ return false;
+}
+
+
+ScopeMatcher::~ScopeMatcher() {
+ for (unsigned i = 0, e = Children.size(); i != e; ++i)
+ delete Children[i];
+}
+
+SwitchOpcodeMatcher::~SwitchOpcodeMatcher() {
+ for (unsigned i = 0, e = Cases.size(); i != e; ++i)
+ delete Cases[i].second;
+}
+
+SwitchTypeMatcher::~SwitchTypeMatcher() {
+ for (unsigned i = 0, e = Cases.size(); i != e; ++i)
+ delete Cases[i].second;
+}
+
+CheckPredicateMatcher::CheckPredicateMatcher(const TreePredicateFn &pred)
+ : Matcher(CheckPredicate), Pred(pred.getOrigPatFragRecord()) {}
+
+TreePredicateFn CheckPredicateMatcher::getPredicate() const {
+ return TreePredicateFn(Pred);
+}
+
+
+
+// printImpl methods.
+
+void ScopeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "Scope\n";
+ for (unsigned i = 0, e = getNumChildren(); i != e; ++i) {
+ if (!getChild(i))
+ OS.indent(indent+1) << "NULL POINTER\n";
+ else
+ getChild(i)->print(OS, indent+2);
+ }
+}
+
+void RecordMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "Record\n";
+}
+
+void RecordChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "RecordChild: " << ChildNo << '\n';
+}
+
+void RecordMemRefMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "RecordMemRef\n";
+}
+
+void CaptureGlueInputMatcher::printImpl(raw_ostream &OS, unsigned indent) const{
+ OS.indent(indent) << "CaptureGlueInput\n";
+}
+
+void MoveChildMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "MoveChild " << ChildNo << '\n';
+}
+
+void MoveParentMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "MoveParent\n";
+}
+
+void CheckSameMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckSame " << MatchNumber << '\n';
+}
+
+void CheckChildSameMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckChild" << ChildNo << "Same\n";
+}
+
+void CheckPatternPredicateMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckPatternPredicate " << Predicate << '\n';
+}
+
+void CheckPredicateMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckPredicate " << getPredicate().getFnName() << '\n';
+}
+
+void CheckOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckOpcode " << Opcode.getEnumName() << '\n';
+}
+
+void SwitchOpcodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "SwitchOpcode: {\n";
+ for (unsigned i = 0, e = Cases.size(); i != e; ++i) {
+ OS.indent(indent) << "case " << Cases[i].first->getEnumName() << ":\n";
+ Cases[i].second->print(OS, indent+2);
+ }
+ OS.indent(indent) << "}\n";
+}
+
+
+void CheckTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckType " << getEnumName(Type) << ", ResNo="
+ << ResNo << '\n';
+}
+
+void SwitchTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "SwitchType: {\n";
+ for (unsigned i = 0, e = Cases.size(); i != e; ++i) {
+ OS.indent(indent) << "case " << getEnumName(Cases[i].first) << ":\n";
+ Cases[i].second->print(OS, indent+2);
+ }
+ OS.indent(indent) << "}\n";
+}
+
+void CheckChildTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckChildType " << ChildNo << " "
+ << getEnumName(Type) << '\n';
+}
+
+
+void CheckIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckInteger " << Value << '\n';
+}
+
+void CheckChildIntegerMatcher::printImpl(raw_ostream &OS,
+ unsigned indent) const {
+ OS.indent(indent) << "CheckChildInteger " << ChildNo << " " << Value << '\n';
+}
+
+void CheckCondCodeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckCondCode ISD::" << CondCodeName << '\n';
+}
+
+void CheckValueTypeMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckValueType MVT::" << TypeName << '\n';
+}
+
+void CheckComplexPatMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckComplexPat " << Pattern.getSelectFunc() << '\n';
+}
+
+void CheckAndImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckAndImm " << Value << '\n';
+}
+
+void CheckOrImmMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CheckOrImm " << Value << '\n';
+}
+
+void CheckFoldableChainNodeMatcher::printImpl(raw_ostream &OS,
+ unsigned indent) const {
+ OS.indent(indent) << "CheckFoldableChainNode\n";
+}
+
+void EmitIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitInteger " << Val << " VT=" << getEnumName(VT)
+ << '\n';
+}
+
+void EmitStringIntegerMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitStringInteger " << Val << " VT=" << getEnumName(VT)
+ << '\n';
+}
+
+void EmitRegisterMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitRegister ";
+ if (Reg)
+ OS << Reg->getName();
+ else
+ OS << "zero_reg";
+ OS << " VT=" << getEnumName(VT) << '\n';
+}
+
+void EmitConvertToTargetMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitConvertToTarget " << Slot << '\n';
+}
+
+void EmitMergeInputChainsMatcher::
+printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitMergeInputChains <todo: args>\n";
+}
+
+void EmitCopyToRegMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitCopyToReg <todo: args>\n";
+}
+
+void EmitNodeXFormMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "EmitNodeXForm " << NodeXForm->getName()
+ << " Slot=" << Slot << '\n';
+}
+
+
+void EmitNodeMatcherCommon::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent);
+ OS << (isa<MorphNodeToMatcher>(this) ? "MorphNodeTo: " : "EmitNode: ")
+ << OpcodeName << ": <todo flags> ";
+
+ for (unsigned i = 0, e = VTs.size(); i != e; ++i)
+ OS << ' ' << getEnumName(VTs[i]);
+ OS << '(';
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ OS << Operands[i] << ' ';
+ OS << ")\n";
+}
+
+void CompleteMatchMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
+ OS.indent(indent) << "CompleteMatch <todo args>\n";
+ OS.indent(indent) << "Src = " << *Pattern.getSrcPattern() << "\n";
+ OS.indent(indent) << "Dst = " << *Pattern.getDstPattern() << "\n";
+}
+
+bool CheckOpcodeMatcher::isEqualImpl(const Matcher *M) const {
+ // Note: pointer equality isn't enough here, we have to check the enum names
+ // to ensure that the nodes are for the same opcode.
+ return cast<CheckOpcodeMatcher>(M)->Opcode.getEnumName() ==
+ Opcode.getEnumName();
+}
+
+bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const {
+ const EmitNodeMatcherCommon *M = cast<EmitNodeMatcherCommon>(m);
+ return M->OpcodeName == OpcodeName && M->VTs == VTs &&
+ M->Operands == Operands && M->HasChain == HasChain &&
+ M->HasInGlue == HasInGlue && M->HasOutGlue == HasOutGlue &&
+ M->HasMemRefs == HasMemRefs &&
+ M->NumFixedArityOperands == NumFixedArityOperands;
+}
+
+void EmitNodeMatcher::anchor() { }
+
+void MorphNodeToMatcher::anchor() { }
+
+// isContradictoryImpl Implementations.
+
+static bool TypesAreContradictory(MVT::SimpleValueType T1,
+ MVT::SimpleValueType T2) {
+ // If the two types are the same, then they are the same, so they don't
+ // contradict.
+ if (T1 == T2) return false;
+
+ // If either type is about iPtr, then they don't conflict unless the other
+ // one is not a scalar integer type.
+ if (T1 == MVT::iPTR)
+ return !MVT(T2).isInteger() || MVT(T2).isVector();
+
+ if (T2 == MVT::iPTR)
+ return !MVT(T1).isInteger() || MVT(T1).isVector();
+
+ // Otherwise, they are two different non-iPTR types, they conflict.
+ return true;
+}
+
+bool CheckOpcodeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckOpcodeMatcher *COM = dyn_cast<CheckOpcodeMatcher>(M)) {
+ // One node can't have two different opcodes!
+ // Note: pointer equality isn't enough here, we have to check the enum names
+ // to ensure that the nodes are for the same opcode.
+ return COM->getOpcode().getEnumName() != getOpcode().getEnumName();
+ }
+
+ // If the node has a known type, and if the type we're checking for is
+ // different, then we know they contradict. For example, a check for
+ // ISD::STORE will never be true at the same time a check for Type i32 is.
+ if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M)) {
+ // If checking for a result the opcode doesn't have, it can't match.
+ if (CT->getResNo() >= getOpcode().getNumResults())
+ return true;
+
+ MVT::SimpleValueType NodeType = getOpcode().getKnownType(CT->getResNo());
+ if (NodeType != MVT::Other)
+ return TypesAreContradictory(NodeType, CT->getType());
+ }
+
+ return false;
+}
+
+bool CheckTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(M))
+ return TypesAreContradictory(getType(), CT->getType());
+ return false;
+}
+
+bool CheckChildTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckChildTypeMatcher *CC = dyn_cast<CheckChildTypeMatcher>(M)) {
+ // If the two checks are about different nodes, we don't know if they
+ // conflict!
+ if (CC->getChildNo() != getChildNo())
+ return false;
+
+ return TypesAreContradictory(getType(), CC->getType());
+ }
+ return false;
+}
+
+bool CheckIntegerMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckIntegerMatcher *CIM = dyn_cast<CheckIntegerMatcher>(M))
+ return CIM->getValue() != getValue();
+ return false;
+}
+
+bool CheckChildIntegerMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckChildIntegerMatcher *CCIM = dyn_cast<CheckChildIntegerMatcher>(M)) {
+ // If the two checks are about different nodes, we don't know if they
+ // conflict!
+ if (CCIM->getChildNo() != getChildNo())
+ return false;
+
+ return CCIM->getValue() != getValue();
+ }
+ return false;
+}
+
+bool CheckValueTypeMatcher::isContradictoryImpl(const Matcher *M) const {
+ if (const CheckValueTypeMatcher *CVT = dyn_cast<CheckValueTypeMatcher>(M))
+ return CVT->getTypeName() != getTypeName();
+ return false;
+}
+
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.h b/contrib/llvm/utils/TableGen/DAGISelMatcher.h
new file mode 100644
index 000000000000..6bda9ca5f96f
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.h
@@ -0,0 +1,1053 @@
+//===- DAGISelMatcher.h - Representation of DAG pattern matcher -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H
+#define LLVM_UTILS_TABLEGEN_DAGISELMATCHER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/Support/Casting.h"
+
+namespace llvm {
+ struct CodeGenRegister;
+ class CodeGenDAGPatterns;
+ class Matcher;
+ class PatternToMatch;
+ class raw_ostream;
+ class ComplexPattern;
+ class Record;
+ class SDNodeInfo;
+ class TreePredicateFn;
+ class TreePattern;
+
+Matcher *ConvertPatternToMatcher(const PatternToMatch &Pattern,unsigned Variant,
+ const CodeGenDAGPatterns &CGP);
+void OptimizeMatcher(std::unique_ptr<Matcher> &Matcher,
+ const CodeGenDAGPatterns &CGP);
+void EmitMatcherTable(const Matcher *Matcher, const CodeGenDAGPatterns &CGP,
+ raw_ostream &OS);
+
+
+/// Matcher - Base class for all the DAG ISel Matcher representation
+/// nodes.
+class Matcher {
+ // The next matcher node that is executed after this one. Null if this is the
+ // last stage of a match.
+ std::unique_ptr<Matcher> Next;
+ virtual void anchor();
+public:
+ enum KindTy {
+ // Matcher state manipulation.
+ Scope, // Push a checking scope.
+ RecordNode, // Record the current node.
+ RecordChild, // Record a child of the current node.
+ RecordMemRef, // Record the memref in the current node.
+ CaptureGlueInput, // If the current node has an input glue, save it.
+ MoveChild, // Move current node to specified child.
+ MoveParent, // Move current node to parent.
+
+ // Predicate checking.
+ CheckSame, // Fail if not same as prev match.
+ CheckChildSame, // Fail if child not same as prev match.
+ CheckPatternPredicate,
+ CheckPredicate, // Fail if node predicate fails.
+ CheckOpcode, // Fail if not opcode.
+ SwitchOpcode, // Dispatch based on opcode.
+ CheckType, // Fail if not correct type.
+ SwitchType, // Dispatch based on type.
+ CheckChildType, // Fail if child has wrong type.
+ CheckInteger, // Fail if wrong val.
+ CheckChildInteger, // Fail if child is wrong val.
+ CheckCondCode, // Fail if not condcode.
+ CheckValueType,
+ CheckComplexPat,
+ CheckAndImm,
+ CheckOrImm,
+ CheckFoldableChainNode,
+
+ // Node creation/emisssion.
+ EmitInteger, // Create a TargetConstant
+ EmitStringInteger, // Create a TargetConstant from a string.
+ EmitRegister, // Create a register.
+ EmitConvertToTarget, // Convert a imm/fpimm to target imm/fpimm
+ EmitMergeInputChains, // Merge together a chains for an input.
+ EmitCopyToReg, // Emit a copytoreg into a physreg.
+ EmitNode, // Create a DAG node
+ EmitNodeXForm, // Run a SDNodeXForm
+ CompleteMatch, // Finish a match and update the results.
+ MorphNodeTo // Build a node, finish a match and update results.
+ };
+ const KindTy Kind;
+
+protected:
+ Matcher(KindTy K) : Kind(K) {}
+public:
+ virtual ~Matcher() {}
+
+ KindTy getKind() const { return Kind; }
+
+ Matcher *getNext() { return Next.get(); }
+ const Matcher *getNext() const { return Next.get(); }
+ void setNext(Matcher *C) { Next.reset(C); }
+ Matcher *takeNext() { return Next.release(); }
+
+ std::unique_ptr<Matcher> &getNextPtr() { return Next; }
+
+ bool isEqual(const Matcher *M) const {
+ if (getKind() != M->getKind()) return false;
+ return isEqualImpl(M);
+ }
+
+ /// isSimplePredicateNode - Return true if this is a simple predicate that
+ /// operates on the node or its children without potential side effects or a
+ /// change of the current node.
+ bool isSimplePredicateNode() const {
+ switch (getKind()) {
+ default: return false;
+ case CheckSame:
+ case CheckChildSame:
+ case CheckPatternPredicate:
+ case CheckPredicate:
+ case CheckOpcode:
+ case CheckType:
+ case CheckChildType:
+ case CheckInteger:
+ case CheckChildInteger:
+ case CheckCondCode:
+ case CheckValueType:
+ case CheckAndImm:
+ case CheckOrImm:
+ case CheckFoldableChainNode:
+ return true;
+ }
+ }
+
+ /// isSimplePredicateOrRecordNode - Return true if this is a record node or
+ /// a simple predicate.
+ bool isSimplePredicateOrRecordNode() const {
+ return isSimplePredicateNode() ||
+ getKind() == RecordNode || getKind() == RecordChild;
+ }
+
+ /// unlinkNode - Unlink the specified node from this chain. If Other == this,
+ /// we unlink the next pointer and return it. Otherwise we unlink Other from
+ /// the list and return this.
+ Matcher *unlinkNode(Matcher *Other);
+
+ /// canMoveBefore - Return true if this matcher is the same as Other, or if
+ /// we can move this matcher past all of the nodes in-between Other and this
+ /// node. Other must be equal to or before this.
+ bool canMoveBefore(const Matcher *Other) const;
+
+ /// canMoveBeforeNode - Return true if it is safe to move the current matcher
+ /// across the specified one.
+ bool canMoveBeforeNode(const Matcher *Other) const;
+
+ /// isContradictory - Return true of these two matchers could never match on
+ /// the same node.
+ bool isContradictory(const Matcher *Other) const {
+ // Since this predicate is reflexive, we canonicalize the ordering so that
+ // we always match a node against nodes with kinds that are greater or equal
+ // to them. For example, we'll pass in a CheckType node as an argument to
+ // the CheckOpcode method, not the other way around.
+ if (getKind() < Other->getKind())
+ return isContradictoryImpl(Other);
+ return Other->isContradictoryImpl(this);
+ }
+
+ void print(raw_ostream &OS, unsigned indent = 0) const;
+ void printOne(raw_ostream &OS) const;
+ void dump() const;
+protected:
+ virtual void printImpl(raw_ostream &OS, unsigned indent) const = 0;
+ virtual bool isEqualImpl(const Matcher *M) const = 0;
+ virtual bool isContradictoryImpl(const Matcher *M) const { return false; }
+};
+
+/// ScopeMatcher - This attempts to match each of its children to find the first
+/// one that successfully matches. If one child fails, it tries the next child.
+/// If none of the children match then this check fails. It never has a 'next'.
+class ScopeMatcher : public Matcher {
+ SmallVector<Matcher*, 4> Children;
+public:
+ ScopeMatcher(ArrayRef<Matcher *> children)
+ : Matcher(Scope), Children(children.begin(), children.end()) {
+ }
+ ~ScopeMatcher() override;
+
+ unsigned getNumChildren() const { return Children.size(); }
+
+ Matcher *getChild(unsigned i) { return Children[i]; }
+ const Matcher *getChild(unsigned i) const { return Children[i]; }
+
+ void resetChild(unsigned i, Matcher *N) {
+ delete Children[i];
+ Children[i] = N;
+ }
+
+ Matcher *takeChild(unsigned i) {
+ Matcher *Res = Children[i];
+ Children[i] = nullptr;
+ return Res;
+ }
+
+ void setNumChildren(unsigned NC) {
+ if (NC < Children.size()) {
+ // delete any children we're about to lose pointers to.
+ for (unsigned i = NC, e = Children.size(); i != e; ++i)
+ delete Children[i];
+ }
+ Children.resize(NC);
+ }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == Scope;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override { return false; }
+};
+
+/// RecordMatcher - Save the current node in the operand list.
+class RecordMatcher : public Matcher {
+ /// WhatFor - This is a string indicating why we're recording this. This
+ /// should only be used for comment generation not anything semantic.
+ std::string WhatFor;
+
+ /// ResultNo - The slot number in the RecordedNodes vector that this will be,
+ /// just printed as a comment.
+ unsigned ResultNo;
+public:
+ RecordMatcher(const std::string &whatfor, unsigned resultNo)
+ : Matcher(RecordNode), WhatFor(whatfor), ResultNo(resultNo) {}
+
+ const std::string &getWhatFor() const { return WhatFor; }
+ unsigned getResultNo() const { return ResultNo; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == RecordNode;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override { return true; }
+};
+
+/// RecordChildMatcher - Save a numbered child of the current node, or fail
+/// the match if it doesn't exist. This is logically equivalent to:
+/// MoveChild N + RecordNode + MoveParent.
+class RecordChildMatcher : public Matcher {
+ unsigned ChildNo;
+
+ /// WhatFor - This is a string indicating why we're recording this. This
+ /// should only be used for comment generation not anything semantic.
+ std::string WhatFor;
+
+ /// ResultNo - The slot number in the RecordedNodes vector that this will be,
+ /// just printed as a comment.
+ unsigned ResultNo;
+public:
+ RecordChildMatcher(unsigned childno, const std::string &whatfor,
+ unsigned resultNo)
+ : Matcher(RecordChild), ChildNo(childno), WhatFor(whatfor),
+ ResultNo(resultNo) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+ const std::string &getWhatFor() const { return WhatFor; }
+ unsigned getResultNo() const { return ResultNo; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == RecordChild;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<RecordChildMatcher>(M)->getChildNo() == getChildNo();
+ }
+};
+
+/// RecordMemRefMatcher - Save the current node's memref.
+class RecordMemRefMatcher : public Matcher {
+public:
+ RecordMemRefMatcher() : Matcher(RecordMemRef) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == RecordMemRef;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override { return true; }
+};
+
+
+/// CaptureGlueInputMatcher - If the current record has a glue input, record
+/// it so that it is used as an input to the generated code.
+class CaptureGlueInputMatcher : public Matcher {
+public:
+ CaptureGlueInputMatcher() : Matcher(CaptureGlueInput) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CaptureGlueInput;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override { return true; }
+};
+
+/// MoveChildMatcher - This tells the interpreter to move into the
+/// specified child node.
+class MoveChildMatcher : public Matcher {
+ unsigned ChildNo;
+public:
+ MoveChildMatcher(unsigned childNo) : Matcher(MoveChild), ChildNo(childNo) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MoveChild;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<MoveChildMatcher>(M)->getChildNo() == getChildNo();
+ }
+};
+
+/// MoveParentMatcher - This tells the interpreter to move to the parent
+/// of the current node.
+class MoveParentMatcher : public Matcher {
+public:
+ MoveParentMatcher() : Matcher(MoveParent) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MoveParent;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override { return true; }
+};
+
+/// CheckSameMatcher - This checks to see if this node is exactly the same
+/// node as the specified match that was recorded with 'Record'. This is used
+/// when patterns have the same name in them, like '(mul GPR:$in, GPR:$in)'.
+class CheckSameMatcher : public Matcher {
+ unsigned MatchNumber;
+public:
+ CheckSameMatcher(unsigned matchnumber)
+ : Matcher(CheckSame), MatchNumber(matchnumber) {}
+
+ unsigned getMatchNumber() const { return MatchNumber; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckSame;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckSameMatcher>(M)->getMatchNumber() == getMatchNumber();
+ }
+};
+
+/// CheckChildSameMatcher - This checks to see if child node is exactly the same
+/// node as the specified match that was recorded with 'Record'. This is used
+/// when patterns have the same name in them, like '(mul GPR:$in, GPR:$in)'.
+class CheckChildSameMatcher : public Matcher {
+ unsigned ChildNo;
+ unsigned MatchNumber;
+public:
+ CheckChildSameMatcher(unsigned childno, unsigned matchnumber)
+ : Matcher(CheckChildSame), ChildNo(childno), MatchNumber(matchnumber) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+ unsigned getMatchNumber() const { return MatchNumber; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckChildSame;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckChildSameMatcher>(M)->ChildNo == ChildNo &&
+ cast<CheckChildSameMatcher>(M)->MatchNumber == MatchNumber;
+ }
+};
+
+/// CheckPatternPredicateMatcher - This checks the target-specific predicate
+/// to see if the entire pattern is capable of matching. This predicate does
+/// not take a node as input. This is used for subtarget feature checks etc.
+class CheckPatternPredicateMatcher : public Matcher {
+ std::string Predicate;
+public:
+ CheckPatternPredicateMatcher(StringRef predicate)
+ : Matcher(CheckPatternPredicate), Predicate(predicate) {}
+
+ StringRef getPredicate() const { return Predicate; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckPatternPredicate;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckPatternPredicateMatcher>(M)->getPredicate() == Predicate;
+ }
+};
+
+/// CheckPredicateMatcher - This checks the target-specific predicate to
+/// see if the node is acceptable.
+class CheckPredicateMatcher : public Matcher {
+ TreePattern *Pred;
+public:
+ CheckPredicateMatcher(const TreePredicateFn &pred);
+
+ TreePredicateFn getPredicate() const;
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckPredicate;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckPredicateMatcher>(M)->Pred == Pred;
+ }
+};
+
+
+/// CheckOpcodeMatcher - This checks to see if the current node has the
+/// specified opcode, if not it fails to match.
+class CheckOpcodeMatcher : public Matcher {
+ const SDNodeInfo &Opcode;
+public:
+ CheckOpcodeMatcher(const SDNodeInfo &opcode)
+ : Matcher(CheckOpcode), Opcode(opcode) {}
+
+ const SDNodeInfo &getOpcode() const { return Opcode; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckOpcode;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override;
+ bool isContradictoryImpl(const Matcher *M) const override;
+};
+
+/// SwitchOpcodeMatcher - Switch based on the current node's opcode, dispatching
+/// to one matcher per opcode. If the opcode doesn't match any of the cases,
+/// then the match fails. This is semantically equivalent to a Scope node where
+/// every child does a CheckOpcode, but is much faster.
+class SwitchOpcodeMatcher : public Matcher {
+ SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases;
+public:
+ SwitchOpcodeMatcher(ArrayRef<std::pair<const SDNodeInfo*, Matcher*> > cases)
+ : Matcher(SwitchOpcode), Cases(cases.begin(), cases.end()) {}
+ ~SwitchOpcodeMatcher() override;
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == SwitchOpcode;
+ }
+
+ unsigned getNumCases() const { return Cases.size(); }
+
+ const SDNodeInfo &getCaseOpcode(unsigned i) const { return *Cases[i].first; }
+ Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
+ const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override { return false; }
+};
+
+/// CheckTypeMatcher - This checks to see if the current node has the
+/// specified type at the specified result, if not it fails to match.
+class CheckTypeMatcher : public Matcher {
+ MVT::SimpleValueType Type;
+ unsigned ResNo;
+public:
+ CheckTypeMatcher(MVT::SimpleValueType type, unsigned resno)
+ : Matcher(CheckType), Type(type), ResNo(resno) {}
+
+ MVT::SimpleValueType getType() const { return Type; }
+ unsigned getResNo() const { return ResNo; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckType;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckTypeMatcher>(M)->Type == Type;
+ }
+ bool isContradictoryImpl(const Matcher *M) const override;
+};
+
+/// SwitchTypeMatcher - Switch based on the current node's type, dispatching
+/// to one matcher per case. If the type doesn't match any of the cases,
+/// then the match fails. This is semantically equivalent to a Scope node where
+/// every child does a CheckType, but is much faster.
+class SwitchTypeMatcher : public Matcher {
+ SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases;
+public:
+ SwitchTypeMatcher(ArrayRef<std::pair<MVT::SimpleValueType, Matcher*> > cases)
+ : Matcher(SwitchType), Cases(cases.begin(), cases.end()) {}
+ ~SwitchTypeMatcher() override;
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == SwitchType;
+ }
+
+ unsigned getNumCases() const { return Cases.size(); }
+
+ MVT::SimpleValueType getCaseType(unsigned i) const { return Cases[i].first; }
+ Matcher *getCaseMatcher(unsigned i) { return Cases[i].second; }
+ const Matcher *getCaseMatcher(unsigned i) const { return Cases[i].second; }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override { return false; }
+};
+
+
+/// CheckChildTypeMatcher - This checks to see if a child node has the
+/// specified type, if not it fails to match.
+class CheckChildTypeMatcher : public Matcher {
+ unsigned ChildNo;
+ MVT::SimpleValueType Type;
+public:
+ CheckChildTypeMatcher(unsigned childno, MVT::SimpleValueType type)
+ : Matcher(CheckChildType), ChildNo(childno), Type(type) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+ MVT::SimpleValueType getType() const { return Type; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckChildType;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckChildTypeMatcher>(M)->ChildNo == ChildNo &&
+ cast<CheckChildTypeMatcher>(M)->Type == Type;
+ }
+ bool isContradictoryImpl(const Matcher *M) const override;
+};
+
+
+/// CheckIntegerMatcher - This checks to see if the current node is a
+/// ConstantSDNode with the specified integer value, if not it fails to match.
+class CheckIntegerMatcher : public Matcher {
+ int64_t Value;
+public:
+ CheckIntegerMatcher(int64_t value)
+ : Matcher(CheckInteger), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckInteger;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckIntegerMatcher>(M)->Value == Value;
+ }
+ bool isContradictoryImpl(const Matcher *M) const override;
+};
+
+/// CheckChildIntegerMatcher - This checks to see if the child node is a
+/// ConstantSDNode with a specified integer value, if not it fails to match.
+class CheckChildIntegerMatcher : public Matcher {
+ unsigned ChildNo;
+ int64_t Value;
+public:
+ CheckChildIntegerMatcher(unsigned childno, int64_t value)
+ : Matcher(CheckChildInteger), ChildNo(childno), Value(value) {}
+
+ unsigned getChildNo() const { return ChildNo; }
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckChildInteger;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckChildIntegerMatcher>(M)->ChildNo == ChildNo &&
+ cast<CheckChildIntegerMatcher>(M)->Value == Value;
+ }
+ bool isContradictoryImpl(const Matcher *M) const override;
+};
+
+/// CheckCondCodeMatcher - This checks to see if the current node is a
+/// CondCodeSDNode with the specified condition, if not it fails to match.
+class CheckCondCodeMatcher : public Matcher {
+ StringRef CondCodeName;
+public:
+ CheckCondCodeMatcher(StringRef condcodename)
+ : Matcher(CheckCondCode), CondCodeName(condcodename) {}
+
+ StringRef getCondCodeName() const { return CondCodeName; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckCondCode;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckCondCodeMatcher>(M)->CondCodeName == CondCodeName;
+ }
+};
+
+/// CheckValueTypeMatcher - This checks to see if the current node is a
+/// VTSDNode with the specified type, if not it fails to match.
+class CheckValueTypeMatcher : public Matcher {
+ StringRef TypeName;
+public:
+ CheckValueTypeMatcher(StringRef type_name)
+ : Matcher(CheckValueType), TypeName(type_name) {}
+
+ StringRef getTypeName() const { return TypeName; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckValueType;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckValueTypeMatcher>(M)->TypeName == TypeName;
+ }
+ bool isContradictoryImpl(const Matcher *M) const override;
+};
+
+
+
+/// CheckComplexPatMatcher - This node runs the specified ComplexPattern on
+/// the current node.
+class CheckComplexPatMatcher : public Matcher {
+ const ComplexPattern &Pattern;
+
+ /// MatchNumber - This is the recorded nodes slot that contains the node we
+ /// want to match against.
+ unsigned MatchNumber;
+
+ /// Name - The name of the node we're matching, for comment emission.
+ std::string Name;
+
+ /// FirstResult - This is the first slot in the RecordedNodes list that the
+ /// result of the match populates.
+ unsigned FirstResult;
+public:
+ CheckComplexPatMatcher(const ComplexPattern &pattern, unsigned matchnumber,
+ const std::string &name, unsigned firstresult)
+ : Matcher(CheckComplexPat), Pattern(pattern), MatchNumber(matchnumber),
+ Name(name), FirstResult(firstresult) {}
+
+ const ComplexPattern &getPattern() const { return Pattern; }
+ unsigned getMatchNumber() const { return MatchNumber; }
+
+ const std::string getName() const { return Name; }
+ unsigned getFirstResult() const { return FirstResult; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckComplexPat;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return &cast<CheckComplexPatMatcher>(M)->Pattern == &Pattern &&
+ cast<CheckComplexPatMatcher>(M)->MatchNumber == MatchNumber;
+ }
+};
+
+/// CheckAndImmMatcher - This checks to see if the current node is an 'and'
+/// with something equivalent to the specified immediate.
+class CheckAndImmMatcher : public Matcher {
+ int64_t Value;
+public:
+ CheckAndImmMatcher(int64_t value)
+ : Matcher(CheckAndImm), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckAndImm;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckAndImmMatcher>(M)->Value == Value;
+ }
+};
+
+/// CheckOrImmMatcher - This checks to see if the current node is an 'and'
+/// with something equivalent to the specified immediate.
+class CheckOrImmMatcher : public Matcher {
+ int64_t Value;
+public:
+ CheckOrImmMatcher(int64_t value)
+ : Matcher(CheckOrImm), Value(value) {}
+
+ int64_t getValue() const { return Value; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckOrImm;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CheckOrImmMatcher>(M)->Value == Value;
+ }
+};
+
+/// CheckFoldableChainNodeMatcher - This checks to see if the current node
+/// (which defines a chain operand) is safe to fold into a larger pattern.
+class CheckFoldableChainNodeMatcher : public Matcher {
+public:
+ CheckFoldableChainNodeMatcher()
+ : Matcher(CheckFoldableChainNode) {}
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CheckFoldableChainNode;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override { return true; }
+};
+
+/// EmitIntegerMatcher - This creates a new TargetConstant.
+class EmitIntegerMatcher : public Matcher {
+ int64_t Val;
+ MVT::SimpleValueType VT;
+public:
+ EmitIntegerMatcher(int64_t val, MVT::SimpleValueType vt)
+ : Matcher(EmitInteger), Val(val), VT(vt) {}
+
+ int64_t getValue() const { return Val; }
+ MVT::SimpleValueType getVT() const { return VT; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitInteger;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<EmitIntegerMatcher>(M)->Val == Val &&
+ cast<EmitIntegerMatcher>(M)->VT == VT;
+ }
+};
+
+/// EmitStringIntegerMatcher - A target constant whose value is represented
+/// by a string.
+class EmitStringIntegerMatcher : public Matcher {
+ std::string Val;
+ MVT::SimpleValueType VT;
+public:
+ EmitStringIntegerMatcher(const std::string &val, MVT::SimpleValueType vt)
+ : Matcher(EmitStringInteger), Val(val), VT(vt) {}
+
+ const std::string &getValue() const { return Val; }
+ MVT::SimpleValueType getVT() const { return VT; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitStringInteger;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<EmitStringIntegerMatcher>(M)->Val == Val &&
+ cast<EmitStringIntegerMatcher>(M)->VT == VT;
+ }
+};
+
+/// EmitRegisterMatcher - This creates a new TargetConstant.
+class EmitRegisterMatcher : public Matcher {
+ /// Reg - The def for the register that we're emitting. If this is null, then
+ /// this is a reference to zero_reg.
+ const CodeGenRegister *Reg;
+ MVT::SimpleValueType VT;
+public:
+ EmitRegisterMatcher(const CodeGenRegister *reg, MVT::SimpleValueType vt)
+ : Matcher(EmitRegister), Reg(reg), VT(vt) {}
+
+ const CodeGenRegister *getReg() const { return Reg; }
+ MVT::SimpleValueType getVT() const { return VT; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitRegister;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<EmitRegisterMatcher>(M)->Reg == Reg &&
+ cast<EmitRegisterMatcher>(M)->VT == VT;
+ }
+};
+
+/// EmitConvertToTargetMatcher - Emit an operation that reads a specified
+/// recorded node and converts it from being a ISD::Constant to
+/// ISD::TargetConstant, likewise for ConstantFP.
+class EmitConvertToTargetMatcher : public Matcher {
+ unsigned Slot;
+public:
+ EmitConvertToTargetMatcher(unsigned slot)
+ : Matcher(EmitConvertToTarget), Slot(slot) {}
+
+ unsigned getSlot() const { return Slot; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitConvertToTarget;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<EmitConvertToTargetMatcher>(M)->Slot == Slot;
+ }
+};
+
+/// EmitMergeInputChainsMatcher - Emit a node that merges a list of input
+/// chains together with a token factor. The list of nodes are the nodes in the
+/// matched pattern that have chain input/outputs. This node adds all input
+/// chains of these nodes if they are not themselves a node in the pattern.
+class EmitMergeInputChainsMatcher : public Matcher {
+ SmallVector<unsigned, 3> ChainNodes;
+public:
+ EmitMergeInputChainsMatcher(ArrayRef<unsigned> nodes)
+ : Matcher(EmitMergeInputChains), ChainNodes(nodes.begin(), nodes.end()) {}
+
+ unsigned getNumNodes() const { return ChainNodes.size(); }
+
+ unsigned getNode(unsigned i) const {
+ assert(i < ChainNodes.size());
+ return ChainNodes[i];
+ }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitMergeInputChains;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<EmitMergeInputChainsMatcher>(M)->ChainNodes == ChainNodes;
+ }
+};
+
+/// EmitCopyToRegMatcher - Emit a CopyToReg node from a value to a physreg,
+/// pushing the chain and glue results.
+///
+class EmitCopyToRegMatcher : public Matcher {
+ unsigned SrcSlot; // Value to copy into the physreg.
+ Record *DestPhysReg;
+public:
+ EmitCopyToRegMatcher(unsigned srcSlot, Record *destPhysReg)
+ : Matcher(EmitCopyToReg), SrcSlot(srcSlot), DestPhysReg(destPhysReg) {}
+
+ unsigned getSrcSlot() const { return SrcSlot; }
+ Record *getDestPhysReg() const { return DestPhysReg; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitCopyToReg;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<EmitCopyToRegMatcher>(M)->SrcSlot == SrcSlot &&
+ cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg;
+ }
+};
+
+
+
+/// EmitNodeXFormMatcher - Emit an operation that runs an SDNodeXForm on a
+/// recorded node and records the result.
+class EmitNodeXFormMatcher : public Matcher {
+ unsigned Slot;
+ Record *NodeXForm;
+public:
+ EmitNodeXFormMatcher(unsigned slot, Record *nodeXForm)
+ : Matcher(EmitNodeXForm), Slot(slot), NodeXForm(nodeXForm) {}
+
+ unsigned getSlot() const { return Slot; }
+ Record *getNodeXForm() const { return NodeXForm; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitNodeXForm;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<EmitNodeXFormMatcher>(M)->Slot == Slot &&
+ cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm;
+ }
+};
+
+/// EmitNodeMatcherCommon - Common class shared between EmitNode and
+/// MorphNodeTo.
+class EmitNodeMatcherCommon : public Matcher {
+ std::string OpcodeName;
+ const SmallVector<MVT::SimpleValueType, 3> VTs;
+ const SmallVector<unsigned, 6> Operands;
+ bool HasChain, HasInGlue, HasOutGlue, HasMemRefs;
+
+ /// NumFixedArityOperands - If this is a fixed arity node, this is set to -1.
+ /// If this is a varidic node, this is set to the number of fixed arity
+ /// operands in the root of the pattern. The rest are appended to this node.
+ int NumFixedArityOperands;
+public:
+ EmitNodeMatcherCommon(const std::string &opcodeName,
+ ArrayRef<MVT::SimpleValueType> vts,
+ ArrayRef<unsigned> operands,
+ bool hasChain, bool hasInGlue, bool hasOutGlue,
+ bool hasmemrefs,
+ int numfixedarityoperands, bool isMorphNodeTo)
+ : Matcher(isMorphNodeTo ? MorphNodeTo : EmitNode), OpcodeName(opcodeName),
+ VTs(vts.begin(), vts.end()), Operands(operands.begin(), operands.end()),
+ HasChain(hasChain), HasInGlue(hasInGlue), HasOutGlue(hasOutGlue),
+ HasMemRefs(hasmemrefs), NumFixedArityOperands(numfixedarityoperands) {}
+
+ const std::string &getOpcodeName() const { return OpcodeName; }
+
+ unsigned getNumVTs() const { return VTs.size(); }
+ MVT::SimpleValueType getVT(unsigned i) const {
+ assert(i < VTs.size());
+ return VTs[i];
+ }
+
+ unsigned getNumOperands() const { return Operands.size(); }
+ unsigned getOperand(unsigned i) const {
+ assert(i < Operands.size());
+ return Operands[i];
+ }
+
+ const SmallVectorImpl<MVT::SimpleValueType> &getVTList() const { return VTs; }
+ const SmallVectorImpl<unsigned> &getOperandList() const { return Operands; }
+
+
+ bool hasChain() const { return HasChain; }
+ bool hasInFlag() const { return HasInGlue; }
+ bool hasOutFlag() const { return HasOutGlue; }
+ bool hasMemRefs() const { return HasMemRefs; }
+ int getNumFixedArityOperands() const { return NumFixedArityOperands; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitNode || N->getKind() == MorphNodeTo;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override;
+};
+
+/// EmitNodeMatcher - This signals a successful match and generates a node.
+class EmitNodeMatcher : public EmitNodeMatcherCommon {
+ void anchor() override;
+ unsigned FirstResultSlot;
+public:
+ EmitNodeMatcher(const std::string &opcodeName,
+ ArrayRef<MVT::SimpleValueType> vts,
+ ArrayRef<unsigned> operands,
+ bool hasChain, bool hasInFlag, bool hasOutFlag,
+ bool hasmemrefs,
+ int numfixedarityoperands, unsigned firstresultslot)
+ : EmitNodeMatcherCommon(opcodeName, vts, operands, hasChain,
+ hasInFlag, hasOutFlag, hasmemrefs,
+ numfixedarityoperands, false),
+ FirstResultSlot(firstresultslot) {}
+
+ unsigned getFirstResultSlot() const { return FirstResultSlot; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == EmitNode;
+ }
+
+};
+
+class MorphNodeToMatcher : public EmitNodeMatcherCommon {
+ void anchor() override;
+ const PatternToMatch &Pattern;
+public:
+ MorphNodeToMatcher(const std::string &opcodeName,
+ ArrayRef<MVT::SimpleValueType> vts,
+ ArrayRef<unsigned> operands,
+ bool hasChain, bool hasInFlag, bool hasOutFlag,
+ bool hasmemrefs,
+ int numfixedarityoperands, const PatternToMatch &pattern)
+ : EmitNodeMatcherCommon(opcodeName, vts, operands, hasChain,
+ hasInFlag, hasOutFlag, hasmemrefs,
+ numfixedarityoperands, true),
+ Pattern(pattern) {
+ }
+
+ const PatternToMatch &getPattern() const { return Pattern; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == MorphNodeTo;
+ }
+};
+
+/// CompleteMatchMatcher - Complete a match by replacing the results of the
+/// pattern with the newly generated nodes. This also prints a comment
+/// indicating the source and dest patterns.
+class CompleteMatchMatcher : public Matcher {
+ SmallVector<unsigned, 2> Results;
+ const PatternToMatch &Pattern;
+public:
+ CompleteMatchMatcher(ArrayRef<unsigned> results,
+ const PatternToMatch &pattern)
+ : Matcher(CompleteMatch), Results(results.begin(), results.end()),
+ Pattern(pattern) {}
+
+ unsigned getNumResults() const { return Results.size(); }
+ unsigned getResult(unsigned R) const { return Results[R]; }
+ const PatternToMatch &getPattern() const { return Pattern; }
+
+ static inline bool classof(const Matcher *N) {
+ return N->getKind() == CompleteMatch;
+ }
+
+private:
+ void printImpl(raw_ostream &OS, unsigned indent) const override;
+ bool isEqualImpl(const Matcher *M) const override {
+ return cast<CompleteMatchMatcher>(M)->Results == Results &&
+ &cast<CompleteMatchMatcher>(M)->Pattern == &Pattern;
+ }
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
new file mode 100644
index 000000000000..67e8f15b248e
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -0,0 +1,982 @@
+//===- DAGISelMatcherEmitter.cpp - Matcher Emitter ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains code to generate C++ code for a matcher.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenDAGPatterns.h"
+#include "DAGISelMatcher.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+using namespace llvm;
+
+enum {
+ CommentIndent = 30
+};
+
+cl::OptionCategory DAGISelCat("Options for -gen-dag-isel");
+
+// To reduce generated source code size.
+static cl::opt<bool> OmitComments("omit-comments",
+ cl::desc("Do not generate comments"),
+ cl::init(false), cl::cat(DAGISelCat));
+
+static cl::opt<bool> InstrumentCoverage(
+ "instrument-coverage",
+ cl::desc("Generates tables to help identify patterns matched"),
+ cl::init(false), cl::cat(DAGISelCat));
+
+namespace {
+class MatcherTableEmitter {
+ const CodeGenDAGPatterns &CGP;
+
+ DenseMap<TreePattern *, unsigned> NodePredicateMap;
+ std::vector<TreePredicateFn> NodePredicates;
+
+ // We de-duplicate the predicates by code string, and use this map to track
+ // all the patterns with "identical" predicates.
+ StringMap<TinyPtrVector<TreePattern *>> NodePredicatesByCodeToRun;
+
+ StringMap<unsigned> PatternPredicateMap;
+ std::vector<std::string> PatternPredicates;
+
+ DenseMap<const ComplexPattern*, unsigned> ComplexPatternMap;
+ std::vector<const ComplexPattern*> ComplexPatterns;
+
+
+ DenseMap<Record*, unsigned> NodeXFormMap;
+ std::vector<Record*> NodeXForms;
+
+ std::vector<std::string> VecIncludeStrings;
+ MapVector<std::string, unsigned, StringMap<unsigned> > VecPatterns;
+
+ unsigned getPatternIdxFromTable(std::string &&P, std::string &&include_loc) {
+ const auto It = VecPatterns.find(P);
+ if (It == VecPatterns.end()) {
+ VecPatterns.insert(make_pair(std::move(P), VecPatterns.size()));
+ VecIncludeStrings.push_back(std::move(include_loc));
+ return VecIncludeStrings.size() - 1;
+ }
+ return It->second;
+ }
+
+public:
+ MatcherTableEmitter(const CodeGenDAGPatterns &cgp)
+ : CGP(cgp) {}
+
+ unsigned EmitMatcherList(const Matcher *N, unsigned Indent,
+ unsigned StartIdx, formatted_raw_ostream &OS);
+
+ void EmitPredicateFunctions(formatted_raw_ostream &OS);
+
+ void EmitHistogram(const Matcher *N, formatted_raw_ostream &OS);
+
+ void EmitPatternMatchTable(raw_ostream &OS);
+
+private:
+ unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
+ formatted_raw_ostream &OS);
+
+ unsigned getNodePredicate(TreePredicateFn Pred) {
+ TreePattern *TP = Pred.getOrigPatFragRecord();
+ unsigned &Entry = NodePredicateMap[TP];
+ if (Entry == 0) {
+ TinyPtrVector<TreePattern *> &SameCodePreds =
+ NodePredicatesByCodeToRun[Pred.getCodeToRunOnSDNode()];
+ if (SameCodePreds.empty()) {
+ // We've never seen a predicate with the same code: allocate an entry.
+ NodePredicates.push_back(Pred);
+ Entry = NodePredicates.size();
+ } else {
+ // We did see an identical predicate: re-use it.
+ Entry = NodePredicateMap[SameCodePreds.front()];
+ assert(Entry != 0);
+ }
+ // In both cases, we've never seen this particular predicate before, so
+ // mark it in the list of predicates sharing the same code.
+ SameCodePreds.push_back(TP);
+ }
+ return Entry-1;
+ }
+
+ unsigned getPatternPredicate(StringRef PredName) {
+ unsigned &Entry = PatternPredicateMap[PredName];
+ if (Entry == 0) {
+ PatternPredicates.push_back(PredName.str());
+ Entry = PatternPredicates.size();
+ }
+ return Entry-1;
+ }
+ unsigned getComplexPat(const ComplexPattern &P) {
+ unsigned &Entry = ComplexPatternMap[&P];
+ if (Entry == 0) {
+ ComplexPatterns.push_back(&P);
+ Entry = ComplexPatterns.size();
+ }
+ return Entry-1;
+ }
+
+ unsigned getNodeXFormID(Record *Rec) {
+ unsigned &Entry = NodeXFormMap[Rec];
+ if (Entry == 0) {
+ NodeXForms.push_back(Rec);
+ Entry = NodeXForms.size();
+ }
+ return Entry-1;
+ }
+
+};
+} // end anonymous namespace.
+
+static std::string GetPatFromTreePatternNode(const TreePatternNode *N) {
+ std::string str;
+ raw_string_ostream Stream(str);
+ Stream << *N;
+ Stream.str();
+ return str;
+}
+
+static unsigned GetVBRSize(unsigned Val) {
+ if (Val <= 127) return 1;
+
+ unsigned NumBytes = 0;
+ while (Val >= 128) {
+ Val >>= 7;
+ ++NumBytes;
+ }
+ return NumBytes+1;
+}
+
+/// EmitVBRValue - Emit the specified value as a VBR, returning the number of
+/// bytes emitted.
+static uint64_t EmitVBRValue(uint64_t Val, raw_ostream &OS) {
+ if (Val <= 127) {
+ OS << Val << ", ";
+ return 1;
+ }
+
+ uint64_t InVal = Val;
+ unsigned NumBytes = 0;
+ while (Val >= 128) {
+ OS << (Val&127) << "|128,";
+ Val >>= 7;
+ ++NumBytes;
+ }
+ OS << Val;
+ if (!OmitComments)
+ OS << "/*" << InVal << "*/";
+ OS << ", ";
+ return NumBytes+1;
+}
+
+// This is expensive and slow.
+static std::string getIncludePath(const Record *R) {
+ std::string str;
+ raw_string_ostream Stream(str);
+ auto Locs = R->getLoc();
+ SMLoc L;
+ if (Locs.size() > 1) {
+ // Get where the pattern prototype was instantiated
+ L = Locs[1];
+ } else if (Locs.size() == 1) {
+ L = Locs[0];
+ }
+ unsigned CurBuf = SrcMgr.FindBufferContainingLoc(L);
+ assert(CurBuf && "Invalid or unspecified location!");
+
+ Stream << SrcMgr.getBufferInfo(CurBuf).Buffer->getBufferIdentifier() << ":"
+ << SrcMgr.FindLineNumber(L, CurBuf);
+ Stream.str();
+ return str;
+}
+
+void MatcherTableEmitter::EmitPatternMatchTable(raw_ostream &OS) {
+
+ assert(isUInt<16>(VecPatterns.size()) &&
+ "Using only 16 bits to encode offset into Pattern Table");
+ assert(VecPatterns.size() == VecIncludeStrings.size() &&
+ "The sizes of Pattern and include vectors should be the same");
+ OS << "StringRef getPatternForIndex(unsigned Index) override {\n";
+ OS << "static const char * PATTERN_MATCH_TABLE[] = {\n";
+
+ for (const auto &It : VecPatterns) {
+ OS << "\"" << It.first << "\",\n";
+ }
+
+ OS << "\n};";
+ OS << "\nreturn StringRef(PATTERN_MATCH_TABLE[Index]);";
+ OS << "\n}";
+
+ OS << "\nStringRef getIncludePathForIndex(unsigned Index) override {\n";
+ OS << "static const char * INCLUDE_PATH_TABLE[] = {\n";
+
+ for (const auto &It : VecIncludeStrings) {
+ OS << "\"" << It << "\",\n";
+ }
+
+ OS << "\n};";
+ OS << "\nreturn StringRef(INCLUDE_PATH_TABLE[Index]);";
+ OS << "\n}";
+}
+
+/// EmitMatcher - Emit bytes for the specified matcher and return
+/// the number of bytes emitted.
+unsigned MatcherTableEmitter::
+EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
+ formatted_raw_ostream &OS) {
+ OS.PadToColumn(Indent*2);
+
+ switch (N->getKind()) {
+ case Matcher::Scope: {
+ const ScopeMatcher *SM = cast<ScopeMatcher>(N);
+ assert(SM->getNext() == nullptr && "Shouldn't have next after scope");
+
+ unsigned StartIdx = CurrentIdx;
+
+ // Emit all of the children.
+ for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) {
+ if (i == 0) {
+ OS << "OPC_Scope, ";
+ ++CurrentIdx;
+ } else {
+ if (!OmitComments) {
+ OS << "/*" << CurrentIdx << "*/";
+ OS.PadToColumn(Indent*2) << "/*Scope*/ ";
+ } else
+ OS.PadToColumn(Indent*2);
+ }
+
+ // We need to encode the child and the offset of the failure code before
+ // emitting either of them. Handle this by buffering the output into a
+ // string while we get the size. Unfortunately, the offset of the
+ // children depends on the VBR size of the child, so for large children we
+ // have to iterate a bit.
+ SmallString<128> TmpBuf;
+ unsigned ChildSize = 0;
+ unsigned VBRSize = 0;
+ do {
+ VBRSize = GetVBRSize(ChildSize);
+
+ TmpBuf.clear();
+ raw_svector_ostream OS(TmpBuf);
+ formatted_raw_ostream FOS(OS);
+ ChildSize = EmitMatcherList(SM->getChild(i), Indent+1,
+ CurrentIdx+VBRSize, FOS);
+ } while (GetVBRSize(ChildSize) != VBRSize);
+
+ assert(ChildSize != 0 && "Should not have a zero-sized child!");
+
+ CurrentIdx += EmitVBRValue(ChildSize, OS);
+ if (!OmitComments) {
+ OS << "/*->" << CurrentIdx+ChildSize << "*/";
+
+ if (i == 0)
+ OS.PadToColumn(CommentIndent) << "// " << SM->getNumChildren()
+ << " children in Scope";
+ }
+
+ OS << '\n' << TmpBuf;
+ CurrentIdx += ChildSize;
+ }
+
+ // Emit a zero as a sentinel indicating end of 'Scope'.
+ if (!OmitComments)
+ OS << "/*" << CurrentIdx << "*/";
+ OS.PadToColumn(Indent*2) << "0, ";
+ if (!OmitComments)
+ OS << "/*End of Scope*/";
+ OS << '\n';
+ return CurrentIdx - StartIdx + 1;
+ }
+
+ case Matcher::RecordNode:
+ OS << "OPC_RecordNode,";
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// #"
+ << cast<RecordMatcher>(N)->getResultNo() << " = "
+ << cast<RecordMatcher>(N)->getWhatFor();
+ OS << '\n';
+ return 1;
+
+ case Matcher::RecordChild:
+ OS << "OPC_RecordChild" << cast<RecordChildMatcher>(N)->getChildNo()
+ << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// #"
+ << cast<RecordChildMatcher>(N)->getResultNo() << " = "
+ << cast<RecordChildMatcher>(N)->getWhatFor();
+ OS << '\n';
+ return 1;
+
+ case Matcher::RecordMemRef:
+ OS << "OPC_RecordMemRef,\n";
+ return 1;
+
+ case Matcher::CaptureGlueInput:
+ OS << "OPC_CaptureGlueInput,\n";
+ return 1;
+
+ case Matcher::MoveChild: {
+ const auto *MCM = cast<MoveChildMatcher>(N);
+
+ OS << "OPC_MoveChild";
+ // Handle the specialized forms.
+ if (MCM->getChildNo() >= 8)
+ OS << ", ";
+ OS << MCM->getChildNo() << ",\n";
+ return (MCM->getChildNo() >= 8) ? 2 : 1;
+ }
+
+ case Matcher::MoveParent:
+ OS << "OPC_MoveParent,\n";
+ return 1;
+
+ case Matcher::CheckSame:
+ OS << "OPC_CheckSame, "
+ << cast<CheckSameMatcher>(N)->getMatchNumber() << ",\n";
+ return 2;
+
+ case Matcher::CheckChildSame:
+ OS << "OPC_CheckChild"
+ << cast<CheckChildSameMatcher>(N)->getChildNo() << "Same, "
+ << cast<CheckChildSameMatcher>(N)->getMatchNumber() << ",\n";
+ return 2;
+
+ case Matcher::CheckPatternPredicate: {
+ StringRef Pred =cast<CheckPatternPredicateMatcher>(N)->getPredicate();
+ OS << "OPC_CheckPatternPredicate, " << getPatternPredicate(Pred) << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// " << Pred;
+ OS << '\n';
+ return 2;
+ }
+ case Matcher::CheckPredicate: {
+ TreePredicateFn Pred = cast<CheckPredicateMatcher>(N)->getPredicate();
+ OS << "OPC_CheckPredicate, " << getNodePredicate(Pred) << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// " << Pred.getFnName();
+ OS << '\n';
+ return 2;
+ }
+
+ case Matcher::CheckOpcode:
+ OS << "OPC_CheckOpcode, TARGET_VAL("
+ << cast<CheckOpcodeMatcher>(N)->getOpcode().getEnumName() << "),\n";
+ return 3;
+
+ case Matcher::SwitchOpcode:
+ case Matcher::SwitchType: {
+ unsigned StartIdx = CurrentIdx;
+
+ unsigned NumCases;
+ if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
+ OS << "OPC_SwitchOpcode ";
+ NumCases = SOM->getNumCases();
+ } else {
+ OS << "OPC_SwitchType ";
+ NumCases = cast<SwitchTypeMatcher>(N)->getNumCases();
+ }
+
+ if (!OmitComments)
+ OS << "/*" << NumCases << " cases */";
+ OS << ", ";
+ ++CurrentIdx;
+
+ // For each case we emit the size, then the opcode, then the matcher.
+ for (unsigned i = 0, e = NumCases; i != e; ++i) {
+ const Matcher *Child;
+ unsigned IdxSize;
+ if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N)) {
+ Child = SOM->getCaseMatcher(i);
+ IdxSize = 2; // size of opcode in table is 2 bytes.
+ } else {
+ Child = cast<SwitchTypeMatcher>(N)->getCaseMatcher(i);
+ IdxSize = 1; // size of type in table is 1 byte.
+ }
+
+ // We need to encode the opcode and the offset of the case code before
+ // emitting the case code. Handle this by buffering the output into a
+ // string while we get the size. Unfortunately, the offset of the
+ // children depends on the VBR size of the child, so for large children we
+ // have to iterate a bit.
+ SmallString<128> TmpBuf;
+ unsigned ChildSize = 0;
+ unsigned VBRSize = 0;
+ do {
+ VBRSize = GetVBRSize(ChildSize);
+
+ TmpBuf.clear();
+ raw_svector_ostream OS(TmpBuf);
+ formatted_raw_ostream FOS(OS);
+ ChildSize = EmitMatcherList(Child, Indent+1, CurrentIdx+VBRSize+IdxSize,
+ FOS);
+ } while (GetVBRSize(ChildSize) != VBRSize);
+
+ assert(ChildSize != 0 && "Should not have a zero-sized child!");
+
+ if (i != 0) {
+ if (!OmitComments)
+ OS << "/*" << CurrentIdx << "*/";
+ OS.PadToColumn(Indent*2);
+ if (!OmitComments)
+ OS << (isa<SwitchOpcodeMatcher>(N) ?
+ "/*SwitchOpcode*/ " : "/*SwitchType*/ ");
+ }
+
+ // Emit the VBR.
+ CurrentIdx += EmitVBRValue(ChildSize, OS);
+
+ if (const SwitchOpcodeMatcher *SOM = dyn_cast<SwitchOpcodeMatcher>(N))
+ OS << "TARGET_VAL(" << SOM->getCaseOpcode(i).getEnumName() << "),";
+ else
+ OS << getEnumName(cast<SwitchTypeMatcher>(N)->getCaseType(i)) << ',';
+
+ CurrentIdx += IdxSize;
+
+ if (!OmitComments)
+ OS << "// ->" << CurrentIdx+ChildSize;
+ OS << '\n';
+ OS << TmpBuf;
+ CurrentIdx += ChildSize;
+ }
+
+ // Emit the final zero to terminate the switch.
+ if (!OmitComments)
+ OS << "/*" << CurrentIdx << "*/";
+ OS.PadToColumn(Indent*2) << "0, ";
+ if (!OmitComments)
+ OS << (isa<SwitchOpcodeMatcher>(N) ?
+ "// EndSwitchOpcode" : "// EndSwitchType");
+
+ OS << '\n';
+ ++CurrentIdx;
+ return CurrentIdx-StartIdx;
+ }
+
+ case Matcher::CheckType:
+ assert(cast<CheckTypeMatcher>(N)->getResNo() == 0 &&
+ "FIXME: Add support for CheckType of resno != 0");
+ OS << "OPC_CheckType, "
+ << getEnumName(cast<CheckTypeMatcher>(N)->getType()) << ",\n";
+ return 2;
+
+ case Matcher::CheckChildType:
+ OS << "OPC_CheckChild"
+ << cast<CheckChildTypeMatcher>(N)->getChildNo() << "Type, "
+ << getEnumName(cast<CheckChildTypeMatcher>(N)->getType()) << ",\n";
+ return 2;
+
+ case Matcher::CheckInteger: {
+ OS << "OPC_CheckInteger, ";
+ unsigned Bytes=1+EmitVBRValue(cast<CheckIntegerMatcher>(N)->getValue(), OS);
+ OS << '\n';
+ return Bytes;
+ }
+ case Matcher::CheckChildInteger: {
+ OS << "OPC_CheckChild" << cast<CheckChildIntegerMatcher>(N)->getChildNo()
+ << "Integer, ";
+ unsigned Bytes=1+EmitVBRValue(cast<CheckChildIntegerMatcher>(N)->getValue(),
+ OS);
+ OS << '\n';
+ return Bytes;
+ }
+ case Matcher::CheckCondCode:
+ OS << "OPC_CheckCondCode, ISD::"
+ << cast<CheckCondCodeMatcher>(N)->getCondCodeName() << ",\n";
+ return 2;
+
+ case Matcher::CheckValueType:
+ OS << "OPC_CheckValueType, MVT::"
+ << cast<CheckValueTypeMatcher>(N)->getTypeName() << ",\n";
+ return 2;
+
+ case Matcher::CheckComplexPat: {
+ const CheckComplexPatMatcher *CCPM = cast<CheckComplexPatMatcher>(N);
+ const ComplexPattern &Pattern = CCPM->getPattern();
+ OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/"
+ << CCPM->getMatchNumber() << ',';
+
+ if (!OmitComments) {
+ OS.PadToColumn(CommentIndent) << "// " << Pattern.getSelectFunc();
+ OS << ":$" << CCPM->getName();
+ for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i)
+ OS << " #" << CCPM->getFirstResult()+i;
+
+ if (Pattern.hasProperty(SDNPHasChain))
+ OS << " + chain result";
+ }
+ OS << '\n';
+ return 3;
+ }
+
+ case Matcher::CheckAndImm: {
+ OS << "OPC_CheckAndImm, ";
+ unsigned Bytes=1+EmitVBRValue(cast<CheckAndImmMatcher>(N)->getValue(), OS);
+ OS << '\n';
+ return Bytes;
+ }
+
+ case Matcher::CheckOrImm: {
+ OS << "OPC_CheckOrImm, ";
+ unsigned Bytes = 1+EmitVBRValue(cast<CheckOrImmMatcher>(N)->getValue(), OS);
+ OS << '\n';
+ return Bytes;
+ }
+
+ case Matcher::CheckFoldableChainNode:
+ OS << "OPC_CheckFoldableChainNode,\n";
+ return 1;
+
+ case Matcher::EmitInteger: {
+ int64_t Val = cast<EmitIntegerMatcher>(N)->getValue();
+ OS << "OPC_EmitInteger, "
+ << getEnumName(cast<EmitIntegerMatcher>(N)->getVT()) << ", ";
+ unsigned Bytes = 2+EmitVBRValue(Val, OS);
+ OS << '\n';
+ return Bytes;
+ }
+ case Matcher::EmitStringInteger: {
+ const std::string &Val = cast<EmitStringIntegerMatcher>(N)->getValue();
+ // These should always fit into one byte.
+ OS << "OPC_EmitInteger, "
+ << getEnumName(cast<EmitStringIntegerMatcher>(N)->getVT()) << ", "
+ << Val << ",\n";
+ return 3;
+ }
+
+ case Matcher::EmitRegister: {
+ const EmitRegisterMatcher *Matcher = cast<EmitRegisterMatcher>(N);
+ const CodeGenRegister *Reg = Matcher->getReg();
+ // If the enum value of the register is larger than one byte can handle,
+ // use EmitRegister2.
+ if (Reg && Reg->EnumValue > 255) {
+ OS << "OPC_EmitRegister2, " << getEnumName(Matcher->getVT()) << ", ";
+ OS << "TARGET_VAL(" << getQualifiedName(Reg->TheDef) << "),\n";
+ return 4;
+ } else {
+ OS << "OPC_EmitRegister, " << getEnumName(Matcher->getVT()) << ", ";
+ if (Reg) {
+ OS << getQualifiedName(Reg->TheDef) << ",\n";
+ } else {
+ OS << "0 ";
+ if (!OmitComments)
+ OS << "/*zero_reg*/";
+ OS << ",\n";
+ }
+ return 3;
+ }
+ }
+
+ case Matcher::EmitConvertToTarget:
+ OS << "OPC_EmitConvertToTarget, "
+ << cast<EmitConvertToTargetMatcher>(N)->getSlot() << ",\n";
+ return 2;
+
+ case Matcher::EmitMergeInputChains: {
+ const EmitMergeInputChainsMatcher *MN =
+ cast<EmitMergeInputChainsMatcher>(N);
+
+ // Handle the specialized forms OPC_EmitMergeInputChains1_0, 1_1, and 1_2.
+ if (MN->getNumNodes() == 1 && MN->getNode(0) < 3) {
+ OS << "OPC_EmitMergeInputChains1_" << MN->getNode(0) << ",\n";
+ return 1;
+ }
+
+ OS << "OPC_EmitMergeInputChains, " << MN->getNumNodes() << ", ";
+ for (unsigned i = 0, e = MN->getNumNodes(); i != e; ++i)
+ OS << MN->getNode(i) << ", ";
+ OS << '\n';
+ return 2+MN->getNumNodes();
+ }
+ case Matcher::EmitCopyToReg:
+ OS << "OPC_EmitCopyToReg, "
+ << cast<EmitCopyToRegMatcher>(N)->getSrcSlot() << ", "
+ << getQualifiedName(cast<EmitCopyToRegMatcher>(N)->getDestPhysReg())
+ << ",\n";
+ return 3;
+ case Matcher::EmitNodeXForm: {
+ const EmitNodeXFormMatcher *XF = cast<EmitNodeXFormMatcher>(N);
+ OS << "OPC_EmitNodeXForm, " << getNodeXFormID(XF->getNodeXForm()) << ", "
+ << XF->getSlot() << ',';
+ if (!OmitComments)
+ OS.PadToColumn(CommentIndent) << "// "<<XF->getNodeXForm()->getName();
+ OS <<'\n';
+ return 3;
+ }
+
+ case Matcher::EmitNode:
+ case Matcher::MorphNodeTo: {
+ auto NumCoveredBytes = 0;
+ if (InstrumentCoverage) {
+ if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {
+ NumCoveredBytes = 3;
+ OS << "OPC_Coverage, ";
+ std::string src =
+ GetPatFromTreePatternNode(SNT->getPattern().getSrcPattern());
+ std::string dst =
+ GetPatFromTreePatternNode(SNT->getPattern().getDstPattern());
+ Record *PatRecord = SNT->getPattern().getSrcRecord();
+ std::string include_src = getIncludePath(PatRecord);
+ unsigned Offset =
+ getPatternIdxFromTable(src + " -> " + dst, std::move(include_src));
+ OS << "TARGET_VAL(" << Offset << "),\n";
+ OS.PadToColumn(Indent * 2);
+ }
+ }
+ const EmitNodeMatcherCommon *EN = cast<EmitNodeMatcherCommon>(N);
+ OS << (isa<EmitNodeMatcher>(EN) ? "OPC_EmitNode" : "OPC_MorphNodeTo");
+ bool CompressVTs = EN->getNumVTs() < 3;
+ if (CompressVTs)
+ OS << EN->getNumVTs();
+
+ OS << ", TARGET_VAL(" << EN->getOpcodeName() << "), 0";
+
+ if (EN->hasChain()) OS << "|OPFL_Chain";
+ if (EN->hasInFlag()) OS << "|OPFL_GlueInput";
+ if (EN->hasOutFlag()) OS << "|OPFL_GlueOutput";
+ if (EN->hasMemRefs()) OS << "|OPFL_MemRefs";
+ if (EN->getNumFixedArityOperands() != -1)
+ OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands();
+ OS << ",\n";
+
+ OS.PadToColumn(Indent*2+4);
+ if (!CompressVTs) {
+ OS << EN->getNumVTs();
+ if (!OmitComments)
+ OS << "/*#VTs*/";
+ OS << ", ";
+ }
+ for (unsigned i = 0, e = EN->getNumVTs(); i != e; ++i)
+ OS << getEnumName(EN->getVT(i)) << ", ";
+
+ OS << EN->getNumOperands();
+ if (!OmitComments)
+ OS << "/*#Ops*/";
+ OS << ", ";
+ unsigned NumOperandBytes = 0;
+ for (unsigned i = 0, e = EN->getNumOperands(); i != e; ++i)
+ NumOperandBytes += EmitVBRValue(EN->getOperand(i), OS);
+
+ if (!OmitComments) {
+ // Print the result #'s for EmitNode.
+ if (const EmitNodeMatcher *E = dyn_cast<EmitNodeMatcher>(EN)) {
+ if (unsigned NumResults = EN->getNumVTs()) {
+ OS.PadToColumn(CommentIndent) << "// Results =";
+ unsigned First = E->getFirstResultSlot();
+ for (unsigned i = 0; i != NumResults; ++i)
+ OS << " #" << First+i;
+ }
+ }
+ OS << '\n';
+
+ if (const MorphNodeToMatcher *SNT = dyn_cast<MorphNodeToMatcher>(N)) {
+ OS.PadToColumn(Indent*2) << "// Src: "
+ << *SNT->getPattern().getSrcPattern() << " - Complexity = "
+ << SNT->getPattern().getPatternComplexity(CGP) << '\n';
+ OS.PadToColumn(Indent*2) << "// Dst: "
+ << *SNT->getPattern().getDstPattern() << '\n';
+ }
+ } else
+ OS << '\n';
+
+ return 5 + !CompressVTs + EN->getNumVTs() + NumOperandBytes +
+ NumCoveredBytes;
+ }
+ case Matcher::CompleteMatch: {
+ const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N);
+ auto NumCoveredBytes = 0;
+ if (InstrumentCoverage) {
+ NumCoveredBytes = 3;
+ OS << "OPC_Coverage, ";
+ std::string src =
+ GetPatFromTreePatternNode(CM->getPattern().getSrcPattern());
+ std::string dst =
+ GetPatFromTreePatternNode(CM->getPattern().getDstPattern());
+ Record *PatRecord = CM->getPattern().getSrcRecord();
+ std::string include_src = getIncludePath(PatRecord);
+ unsigned Offset =
+ getPatternIdxFromTable(src + " -> " + dst, std::move(include_src));
+ OS << "TARGET_VAL(" << Offset << "),\n";
+ OS.PadToColumn(Indent * 2);
+ }
+ OS << "OPC_CompleteMatch, " << CM->getNumResults() << ", ";
+ unsigned NumResultBytes = 0;
+ for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
+ NumResultBytes += EmitVBRValue(CM->getResult(i), OS);
+ OS << '\n';
+ if (!OmitComments) {
+ OS.PadToColumn(Indent*2) << "// Src: "
+ << *CM->getPattern().getSrcPattern() << " - Complexity = "
+ << CM->getPattern().getPatternComplexity(CGP) << '\n';
+ OS.PadToColumn(Indent*2) << "// Dst: "
+ << *CM->getPattern().getDstPattern();
+ }
+ OS << '\n';
+ return 2 + NumResultBytes + NumCoveredBytes;
+ }
+ }
+ llvm_unreachable("Unreachable");
+}
+
+/// EmitMatcherList - Emit the bytes for the specified matcher subtree.
+unsigned MatcherTableEmitter::
+EmitMatcherList(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
+ formatted_raw_ostream &OS) {
+ unsigned Size = 0;
+ while (N) {
+ if (!OmitComments)
+ OS << "/*" << CurrentIdx << "*/";
+ unsigned MatcherSize = EmitMatcher(N, Indent, CurrentIdx, OS);
+ Size += MatcherSize;
+ CurrentIdx += MatcherSize;
+
+ // If there are other nodes in this list, iterate to them, otherwise we're
+ // done.
+ N = N->getNext();
+ }
+ return Size;
+}
+
+void MatcherTableEmitter::EmitPredicateFunctions(formatted_raw_ostream &OS) {
+ // Emit pattern predicates.
+ if (!PatternPredicates.empty()) {
+ OS << "bool CheckPatternPredicate(unsigned PredNo) const override {\n";
+ OS << " switch (PredNo) {\n";
+ OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n";
+ for (unsigned i = 0, e = PatternPredicates.size(); i != e; ++i)
+ OS << " case " << i << ": return " << PatternPredicates[i] << ";\n";
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+
+ // Emit Node predicates.
+ if (!NodePredicates.empty()) {
+ OS << "bool CheckNodePredicate(SDNode *Node,\n";
+ OS << " unsigned PredNo) const override {\n";
+ OS << " switch (PredNo) {\n";
+ OS << " default: llvm_unreachable(\"Invalid predicate in table?\");\n";
+ for (unsigned i = 0, e = NodePredicates.size(); i != e; ++i) {
+ // Emit the predicate code corresponding to this pattern.
+ TreePredicateFn PredFn = NodePredicates[i];
+
+ assert(!PredFn.isAlwaysTrue() && "No code in this predicate");
+ OS << " case " << i << ": { \n";
+ for (auto *SimilarPred :
+ NodePredicatesByCodeToRun[PredFn.getCodeToRunOnSDNode()])
+ OS << " // " << TreePredicateFn(SimilarPred).getFnName() <<'\n';
+
+ OS << PredFn.getCodeToRunOnSDNode() << "\n }\n";
+ }
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+
+ // Emit CompletePattern matchers.
+ // FIXME: This should be const.
+ if (!ComplexPatterns.empty()) {
+ OS << "bool CheckComplexPattern(SDNode *Root, SDNode *Parent,\n";
+ OS << " SDValue N, unsigned PatternNo,\n";
+ OS << " SmallVectorImpl<std::pair<SDValue, SDNode*> > &Result) override {\n";
+ OS << " unsigned NextRes = Result.size();\n";
+ OS << " switch (PatternNo) {\n";
+ OS << " default: llvm_unreachable(\"Invalid pattern # in table?\");\n";
+ for (unsigned i = 0, e = ComplexPatterns.size(); i != e; ++i) {
+ const ComplexPattern &P = *ComplexPatterns[i];
+ unsigned NumOps = P.getNumOperands();
+
+ if (P.hasProperty(SDNPHasChain))
+ ++NumOps; // Get the chained node too.
+
+ OS << " case " << i << ":\n";
+ if (InstrumentCoverage)
+ OS << " {\n";
+ OS << " Result.resize(NextRes+" << NumOps << ");\n";
+ if (InstrumentCoverage)
+ OS << " bool Succeeded = " << P.getSelectFunc();
+ else
+ OS << " return " << P.getSelectFunc();
+
+ OS << "(";
+ // If the complex pattern wants the root of the match, pass it in as the
+ // first argument.
+ if (P.hasProperty(SDNPWantRoot))
+ OS << "Root, ";
+
+ // If the complex pattern wants the parent of the operand being matched,
+ // pass it in as the next argument.
+ if (P.hasProperty(SDNPWantParent))
+ OS << "Parent, ";
+
+ OS << "N";
+ for (unsigned i = 0; i != NumOps; ++i)
+ OS << ", Result[NextRes+" << i << "].first";
+ OS << ");\n";
+ if (InstrumentCoverage) {
+ OS << " if (Succeeded)\n";
+ OS << " dbgs() << \"\\nCOMPLEX_PATTERN: " << P.getSelectFunc()
+ << "\\n\" ;\n";
+ OS << " return Succeeded;\n";
+ OS << " }\n";
+ }
+ }
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+
+
+ // Emit SDNodeXForm handlers.
+ // FIXME: This should be const.
+ if (!NodeXForms.empty()) {
+ OS << "SDValue RunSDNodeXForm(SDValue V, unsigned XFormNo) override {\n";
+ OS << " switch (XFormNo) {\n";
+ OS << " default: llvm_unreachable(\"Invalid xform # in table?\");\n";
+
+ // FIXME: The node xform could take SDValue's instead of SDNode*'s.
+ for (unsigned i = 0, e = NodeXForms.size(); i != e; ++i) {
+ const CodeGenDAGPatterns::NodeXForm &Entry =
+ CGP.getSDNodeTransform(NodeXForms[i]);
+
+ Record *SDNode = Entry.first;
+ const std::string &Code = Entry.second;
+
+ OS << " case " << i << ": { ";
+ if (!OmitComments)
+ OS << "// " << NodeXForms[i]->getName();
+ OS << '\n';
+
+ std::string ClassName = CGP.getSDNodeInfo(SDNode).getSDClassName();
+ if (ClassName == "SDNode")
+ OS << " SDNode *N = V.getNode();\n";
+ else
+ OS << " " << ClassName << " *N = cast<" << ClassName
+ << ">(V.getNode());\n";
+ OS << Code << "\n }\n";
+ }
+ OS << " }\n";
+ OS << "}\n\n";
+ }
+}
+
+static void BuildHistogram(const Matcher *M, std::vector<unsigned> &OpcodeFreq){
+ for (; M != nullptr; M = M->getNext()) {
+ // Count this node.
+ if (unsigned(M->getKind()) >= OpcodeFreq.size())
+ OpcodeFreq.resize(M->getKind()+1);
+ OpcodeFreq[M->getKind()]++;
+
+ // Handle recursive nodes.
+ if (const ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M)) {
+ for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i)
+ BuildHistogram(SM->getChild(i), OpcodeFreq);
+ } else if (const SwitchOpcodeMatcher *SOM =
+ dyn_cast<SwitchOpcodeMatcher>(M)) {
+ for (unsigned i = 0, e = SOM->getNumCases(); i != e; ++i)
+ BuildHistogram(SOM->getCaseMatcher(i), OpcodeFreq);
+ } else if (const SwitchTypeMatcher *STM = dyn_cast<SwitchTypeMatcher>(M)) {
+ for (unsigned i = 0, e = STM->getNumCases(); i != e; ++i)
+ BuildHistogram(STM->getCaseMatcher(i), OpcodeFreq);
+ }
+ }
+}
+
+void MatcherTableEmitter::EmitHistogram(const Matcher *M,
+ formatted_raw_ostream &OS) {
+ if (OmitComments)
+ return;
+
+ std::vector<unsigned> OpcodeFreq;
+ BuildHistogram(M, OpcodeFreq);
+
+ OS << " // Opcode Histogram:\n";
+ for (unsigned i = 0, e = OpcodeFreq.size(); i != e; ++i) {
+ OS << " // #";
+ switch ((Matcher::KindTy)i) {
+ case Matcher::Scope: OS << "OPC_Scope"; break;
+ case Matcher::RecordNode: OS << "OPC_RecordNode"; break;
+ case Matcher::RecordChild: OS << "OPC_RecordChild"; break;
+ case Matcher::RecordMemRef: OS << "OPC_RecordMemRef"; break;
+ case Matcher::CaptureGlueInput: OS << "OPC_CaptureGlueInput"; break;
+ case Matcher::MoveChild: OS << "OPC_MoveChild"; break;
+ case Matcher::MoveParent: OS << "OPC_MoveParent"; break;
+ case Matcher::CheckSame: OS << "OPC_CheckSame"; break;
+ case Matcher::CheckChildSame: OS << "OPC_CheckChildSame"; break;
+ case Matcher::CheckPatternPredicate:
+ OS << "OPC_CheckPatternPredicate"; break;
+ case Matcher::CheckPredicate: OS << "OPC_CheckPredicate"; break;
+ case Matcher::CheckOpcode: OS << "OPC_CheckOpcode"; break;
+ case Matcher::SwitchOpcode: OS << "OPC_SwitchOpcode"; break;
+ case Matcher::CheckType: OS << "OPC_CheckType"; break;
+ case Matcher::SwitchType: OS << "OPC_SwitchType"; break;
+ case Matcher::CheckChildType: OS << "OPC_CheckChildType"; break;
+ case Matcher::CheckInteger: OS << "OPC_CheckInteger"; break;
+ case Matcher::CheckChildInteger: OS << "OPC_CheckChildInteger"; break;
+ case Matcher::CheckCondCode: OS << "OPC_CheckCondCode"; break;
+ case Matcher::CheckValueType: OS << "OPC_CheckValueType"; break;
+ case Matcher::CheckComplexPat: OS << "OPC_CheckComplexPat"; break;
+ case Matcher::CheckAndImm: OS << "OPC_CheckAndImm"; break;
+ case Matcher::CheckOrImm: OS << "OPC_CheckOrImm"; break;
+ case Matcher::CheckFoldableChainNode:
+ OS << "OPC_CheckFoldableChainNode"; break;
+ case Matcher::EmitInteger: OS << "OPC_EmitInteger"; break;
+ case Matcher::EmitStringInteger: OS << "OPC_EmitStringInteger"; break;
+ case Matcher::EmitRegister: OS << "OPC_EmitRegister"; break;
+ case Matcher::EmitConvertToTarget: OS << "OPC_EmitConvertToTarget"; break;
+ case Matcher::EmitMergeInputChains: OS << "OPC_EmitMergeInputChains"; break;
+ case Matcher::EmitCopyToReg: OS << "OPC_EmitCopyToReg"; break;
+ case Matcher::EmitNode: OS << "OPC_EmitNode"; break;
+ case Matcher::MorphNodeTo: OS << "OPC_MorphNodeTo"; break;
+ case Matcher::EmitNodeXForm: OS << "OPC_EmitNodeXForm"; break;
+ case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break;
+ }
+
+ OS.PadToColumn(40) << " = " << OpcodeFreq[i] << '\n';
+ }
+ OS << '\n';
+}
+
+
+void llvm::EmitMatcherTable(const Matcher *TheMatcher,
+ const CodeGenDAGPatterns &CGP,
+ raw_ostream &O) {
+ formatted_raw_ostream OS(O);
+
+ OS << "// The main instruction selector code.\n";
+ OS << "void SelectCode(SDNode *N) {\n";
+
+ MatcherTableEmitter MatcherEmitter(CGP);
+
+ OS << " // Some target values are emitted as 2 bytes, TARGET_VAL handles\n";
+ OS << " // this.\n";
+ OS << " #define TARGET_VAL(X) X & 255, unsigned(X) >> 8\n";
+ OS << " static const unsigned char MatcherTable[] = {\n";
+ unsigned TotalSize = MatcherEmitter.EmitMatcherList(TheMatcher, 6, 0, OS);
+ OS << " 0\n }; // Total Array size is " << (TotalSize+1) << " bytes\n\n";
+
+ MatcherEmitter.EmitHistogram(TheMatcher, OS);
+
+ OS << " #undef TARGET_VAL\n";
+ OS << " SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n";
+ OS << "}\n";
+
+ // Next up, emit the function for node and pattern predicates:
+ MatcherEmitter.EmitPredicateFunctions(OS);
+
+ if (InstrumentCoverage)
+ MatcherEmitter.EmitPatternMatchTable(OS);
+}
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
new file mode 100644
index 000000000000..aafc1157893e
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
@@ -0,0 +1,1010 @@
+//===- DAGISelMatcherGen.cpp - Matcher generator --------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "CodeGenRegisters.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include <utility>
+using namespace llvm;
+
+
+/// getRegisterValueType - Look up and return the ValueType of the specified
+/// register. If the register is a member of multiple register classes which
+/// have different associated types, return MVT::Other.
+static MVT::SimpleValueType getRegisterValueType(Record *R,
+ const CodeGenTarget &T) {
+ bool FoundRC = false;
+ MVT::SimpleValueType VT = MVT::Other;
+ const CodeGenRegister *Reg = T.getRegBank().getReg(R);
+
+ for (const auto &RC : T.getRegBank().getRegClasses()) {
+ if (!RC.contains(Reg))
+ continue;
+
+ if (!FoundRC) {
+ FoundRC = true;
+ VT = RC.getValueTypeNum(0);
+ continue;
+ }
+
+ // If this occurs in multiple register classes, they all have to agree.
+ assert(VT == RC.getValueTypeNum(0));
+ }
+ return VT;
+}
+
+
+namespace {
+ class MatcherGen {
+ const PatternToMatch &Pattern;
+ const CodeGenDAGPatterns &CGP;
+
+ /// PatWithNoTypes - This is a clone of Pattern.getSrcPattern() that starts
+ /// out with all of the types removed. This allows us to insert type checks
+ /// as we scan the tree.
+ TreePatternNode *PatWithNoTypes;
+
+ /// VariableMap - A map from variable names ('$dst') to the recorded operand
+ /// number that they were captured as. These are biased by 1 to make
+ /// insertion easier.
+ StringMap<unsigned> VariableMap;
+
+ /// This maintains the recorded operand number that OPC_CheckComplexPattern
+ /// drops each sub-operand into. We don't want to insert these into
+ /// VariableMap because that leads to identity checking if they are
+ /// encountered multiple times. Biased by 1 like VariableMap for
+ /// consistency.
+ StringMap<unsigned> NamedComplexPatternOperands;
+
+ /// NextRecordedOperandNo - As we emit opcodes to record matched values in
+ /// the RecordedNodes array, this keeps track of which slot will be next to
+ /// record into.
+ unsigned NextRecordedOperandNo;
+
+ /// MatchedChainNodes - This maintains the position in the recorded nodes
+ /// array of all of the recorded input nodes that have chains.
+ SmallVector<unsigned, 2> MatchedChainNodes;
+
+ /// MatchedComplexPatterns - This maintains a list of all of the
+ /// ComplexPatterns that we need to check. The second element of each pair
+ /// is the recorded operand number of the input node.
+ SmallVector<std::pair<const TreePatternNode*,
+ unsigned>, 2> MatchedComplexPatterns;
+
+ /// PhysRegInputs - List list has an entry for each explicitly specified
+ /// physreg input to the pattern. The first elt is the Register node, the
+ /// second is the recorded slot number the input pattern match saved it in.
+ SmallVector<std::pair<Record*, unsigned>, 2> PhysRegInputs;
+
+ /// Matcher - This is the top level of the generated matcher, the result.
+ Matcher *TheMatcher;
+
+ /// CurPredicate - As we emit matcher nodes, this points to the latest check
+ /// which should have future checks stuck into its Next position.
+ Matcher *CurPredicate;
+ public:
+ MatcherGen(const PatternToMatch &pattern, const CodeGenDAGPatterns &cgp);
+
+ ~MatcherGen() {
+ delete PatWithNoTypes;
+ }
+
+ bool EmitMatcherCode(unsigned Variant);
+ void EmitResultCode();
+
+ Matcher *GetMatcher() const { return TheMatcher; }
+ private:
+ void AddMatcher(Matcher *NewNode);
+ void InferPossibleTypes();
+
+ // Matcher Generation.
+ void EmitMatchCode(const TreePatternNode *N, TreePatternNode *NodeNoTypes);
+ void EmitLeafMatchCode(const TreePatternNode *N);
+ void EmitOperatorMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes);
+
+ /// If this is the first time a node with unique identifier Name has been
+ /// seen, record it. Otherwise, emit a check to make sure this is the same
+ /// node. Returns true if this is the first encounter.
+ bool recordUniqueNode(const std::string &Name);
+
+ // Result Code Generation.
+ unsigned getNamedArgumentSlot(StringRef Name) {
+ unsigned VarMapEntry = VariableMap[Name];
+ assert(VarMapEntry != 0 &&
+ "Variable referenced but not defined and not caught earlier!");
+ return VarMapEntry-1;
+ }
+
+ /// GetInstPatternNode - Get the pattern for an instruction.
+ const TreePatternNode *GetInstPatternNode(const DAGInstruction &Ins,
+ const TreePatternNode *N);
+
+ void EmitResultOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultOfNamedOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultLeafAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultInstructionAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ void EmitResultSDNodeXFormAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps);
+ };
+
+} // end anon namespace.
+
+MatcherGen::MatcherGen(const PatternToMatch &pattern,
+ const CodeGenDAGPatterns &cgp)
+: Pattern(pattern), CGP(cgp), NextRecordedOperandNo(0),
+ TheMatcher(nullptr), CurPredicate(nullptr) {
+ // We need to produce the matcher tree for the patterns source pattern. To do
+ // this we need to match the structure as well as the types. To do the type
+ // matching, we want to figure out the fewest number of type checks we need to
+ // emit. For example, if there is only one integer type supported by a
+ // target, there should be no type comparisons at all for integer patterns!
+ //
+ // To figure out the fewest number of type checks needed, clone the pattern,
+ // remove the types, then perform type inference on the pattern as a whole.
+ // If there are unresolved types, emit an explicit check for those types,
+ // apply the type to the tree, then rerun type inference. Iterate until all
+ // types are resolved.
+ //
+ PatWithNoTypes = Pattern.getSrcPattern()->clone();
+ PatWithNoTypes->RemoveAllTypes();
+
+ // If there are types that are manifestly known, infer them.
+ InferPossibleTypes();
+}
+
+/// InferPossibleTypes - As we emit the pattern, we end up generating type
+/// checks and applying them to the 'PatWithNoTypes' tree. As we do this, we
+/// want to propagate implied types as far throughout the tree as possible so
+/// that we avoid doing redundant type checks. This does the type propagation.
+void MatcherGen::InferPossibleTypes() {
+ // TP - Get *SOME* tree pattern, we don't care which. It is only used for
+ // diagnostics, which we know are impossible at this point.
+ TreePattern &TP = *CGP.pf_begin()->second;
+
+ bool MadeChange = true;
+ while (MadeChange)
+ MadeChange = PatWithNoTypes->ApplyTypeConstraints(TP,
+ true/*Ignore reg constraints*/);
+}
+
+
+/// AddMatcher - Add a matcher node to the current graph we're building.
+void MatcherGen::AddMatcher(Matcher *NewNode) {
+ if (CurPredicate)
+ CurPredicate->setNext(NewNode);
+ else
+ TheMatcher = NewNode;
+ CurPredicate = NewNode;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Pattern Match Generation
+//===----------------------------------------------------------------------===//
+
+/// EmitLeafMatchCode - Generate matching code for leaf nodes.
+void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) {
+ assert(N->isLeaf() && "Not a leaf?");
+
+ // Direct match against an integer constant.
+ if (IntInit *II = dyn_cast<IntInit>(N->getLeafValue())) {
+ // If this is the root of the dag we're matching, we emit a redundant opcode
+ // check to ensure that this gets folded into the normal top-level
+ // OpcodeSwitch.
+ if (N == Pattern.getSrcPattern()) {
+ const SDNodeInfo &NI = CGP.getSDNodeInfo(CGP.getSDNodeNamed("imm"));
+ AddMatcher(new CheckOpcodeMatcher(NI));
+ }
+
+ return AddMatcher(new CheckIntegerMatcher(II->getValue()));
+ }
+
+ // An UnsetInit represents a named node without any constraints.
+ if (isa<UnsetInit>(N->getLeafValue())) {
+ assert(N->hasName() && "Unnamed ? leaf");
+ return;
+ }
+
+ DefInit *DI = dyn_cast<DefInit>(N->getLeafValue());
+ if (!DI) {
+ errs() << "Unknown leaf kind: " << *N << "\n";
+ abort();
+ }
+
+ Record *LeafRec = DI->getDef();
+
+ // A ValueType leaf node can represent a register when named, or itself when
+ // unnamed.
+ if (LeafRec->isSubClassOf("ValueType")) {
+ // A named ValueType leaf always matches: (add i32:$a, i32:$b).
+ if (N->hasName())
+ return;
+ // An unnamed ValueType as in (sext_inreg GPR:$foo, i8).
+ return AddMatcher(new CheckValueTypeMatcher(LeafRec->getName()));
+ }
+
+ if (// Handle register references. Nothing to do here, they always match.
+ LeafRec->isSubClassOf("RegisterClass") ||
+ LeafRec->isSubClassOf("RegisterOperand") ||
+ LeafRec->isSubClassOf("PointerLikeRegClass") ||
+ LeafRec->isSubClassOf("SubRegIndex") ||
+ // Place holder for SRCVALUE nodes. Nothing to do here.
+ LeafRec->getName() == "srcvalue")
+ return;
+
+ // If we have a physreg reference like (mul gpr:$src, EAX) then we need to
+ // record the register
+ if (LeafRec->isSubClassOf("Register")) {
+ AddMatcher(new RecordMatcher("physreg input "+LeafRec->getName().str(),
+ NextRecordedOperandNo));
+ PhysRegInputs.push_back(std::make_pair(LeafRec, NextRecordedOperandNo++));
+ return;
+ }
+
+ if (LeafRec->isSubClassOf("CondCode"))
+ return AddMatcher(new CheckCondCodeMatcher(LeafRec->getName()));
+
+ if (LeafRec->isSubClassOf("ComplexPattern")) {
+ // We can't model ComplexPattern uses that don't have their name taken yet.
+ // The OPC_CheckComplexPattern operation implicitly records the results.
+ if (N->getName().empty()) {
+ std::string S;
+ raw_string_ostream OS(S);
+ OS << "We expect complex pattern uses to have names: " << *N;
+ PrintFatalError(OS.str());
+ }
+
+ // Remember this ComplexPattern so that we can emit it after all the other
+ // structural matches are done.
+ unsigned InputOperand = VariableMap[N->getName()] - 1;
+ MatchedComplexPatterns.push_back(std::make_pair(N, InputOperand));
+ return;
+ }
+
+ errs() << "Unknown leaf kind: " << *N << "\n";
+ abort();
+}
+
+void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes) {
+ assert(!N->isLeaf() && "Not an operator?");
+
+ if (N->getOperator()->isSubClassOf("ComplexPattern")) {
+ // The "name" of a non-leaf complex pattern (MY_PAT $op1, $op2) is
+ // "MY_PAT:op1:op2". We should already have validated that the uses are
+ // consistent.
+ std::string PatternName = N->getOperator()->getName();
+ for (unsigned i = 0; i < N->getNumChildren(); ++i) {
+ PatternName += ":";
+ PatternName += N->getChild(i)->getName();
+ }
+
+ if (recordUniqueNode(PatternName)) {
+ auto NodeAndOpNum = std::make_pair(N, NextRecordedOperandNo - 1);
+ MatchedComplexPatterns.push_back(NodeAndOpNum);
+ }
+
+ return;
+ }
+
+ const SDNodeInfo &CInfo = CGP.getSDNodeInfo(N->getOperator());
+
+ // If this is an 'and R, 1234' where the operation is AND/OR and the RHS is
+ // a constant without a predicate fn that has more that one bit set, handle
+ // this as a special case. This is usually for targets that have special
+ // handling of certain large constants (e.g. alpha with it's 8/16/32-bit
+ // handling stuff). Using these instructions is often far more efficient
+ // than materializing the constant. Unfortunately, both the instcombiner
+ // and the dag combiner can often infer that bits are dead, and thus drop
+ // them from the mask in the dag. For example, it might turn 'AND X, 255'
+ // into 'AND X, 254' if it knows the low bit is set. Emit code that checks
+ // to handle this.
+ if ((N->getOperator()->getName() == "and" ||
+ N->getOperator()->getName() == "or") &&
+ N->getChild(1)->isLeaf() && N->getChild(1)->getPredicateFns().empty() &&
+ N->getPredicateFns().empty()) {
+ if (IntInit *II = dyn_cast<IntInit>(N->getChild(1)->getLeafValue())) {
+ if (!isPowerOf2_32(II->getValue())) { // Don't bother with single bits.
+ // If this is at the root of the pattern, we emit a redundant
+ // CheckOpcode so that the following checks get factored properly under
+ // a single opcode check.
+ if (N == Pattern.getSrcPattern())
+ AddMatcher(new CheckOpcodeMatcher(CInfo));
+
+ // Emit the CheckAndImm/CheckOrImm node.
+ if (N->getOperator()->getName() == "and")
+ AddMatcher(new CheckAndImmMatcher(II->getValue()));
+ else
+ AddMatcher(new CheckOrImmMatcher(II->getValue()));
+
+ // Match the LHS of the AND as appropriate.
+ AddMatcher(new MoveChildMatcher(0));
+ EmitMatchCode(N->getChild(0), NodeNoTypes->getChild(0));
+ AddMatcher(new MoveParentMatcher());
+ return;
+ }
+ }
+ }
+
+ // Check that the current opcode lines up.
+ AddMatcher(new CheckOpcodeMatcher(CInfo));
+
+ // If this node has memory references (i.e. is a load or store), tell the
+ // interpreter to capture them in the memref array.
+ if (N->NodeHasProperty(SDNPMemOperand, CGP))
+ AddMatcher(new RecordMemRefMatcher());
+
+ // If this node has a chain, then the chain is operand #0 is the SDNode, and
+ // the child numbers of the node are all offset by one.
+ unsigned OpNo = 0;
+ if (N->NodeHasProperty(SDNPHasChain, CGP)) {
+ // Record the node and remember it in our chained nodes list.
+ AddMatcher(new RecordMatcher("'" + N->getOperator()->getName().str() +
+ "' chained node",
+ NextRecordedOperandNo));
+ // Remember all of the input chains our pattern will match.
+ MatchedChainNodes.push_back(NextRecordedOperandNo++);
+
+ // Don't look at the input chain when matching the tree pattern to the
+ // SDNode.
+ OpNo = 1;
+
+ // If this node is not the root and the subtree underneath it produces a
+ // chain, then the result of matching the node is also produce a chain.
+ // Beyond that, this means that we're also folding (at least) the root node
+ // into the node that produce the chain (for example, matching
+ // "(add reg, (load ptr))" as a add_with_memory on X86). This is
+ // problematic, if the 'reg' node also uses the load (say, its chain).
+ // Graphically:
+ //
+ // [LD]
+ // ^ ^
+ // | \ DAG's like cheese.
+ // / |
+ // / [YY]
+ // | ^
+ // [XX]--/
+ //
+ // It would be invalid to fold XX and LD. In this case, folding the two
+ // nodes together would induce a cycle in the DAG, making it a 'cyclic DAG'
+ // To prevent this, we emit a dynamic check for legality before allowing
+ // this to be folded.
+ //
+ const TreePatternNode *Root = Pattern.getSrcPattern();
+ if (N != Root) { // Not the root of the pattern.
+ // If there is a node between the root and this node, then we definitely
+ // need to emit the check.
+ bool NeedCheck = !Root->hasChild(N);
+
+ // If it *is* an immediate child of the root, we can still need a check if
+ // the root SDNode has multiple inputs. For us, this means that it is an
+ // intrinsic, has multiple operands, or has other inputs like chain or
+ // glue).
+ if (!NeedCheck) {
+ const SDNodeInfo &PInfo = CGP.getSDNodeInfo(Root->getOperator());
+ NeedCheck =
+ Root->getOperator() == CGP.get_intrinsic_void_sdnode() ||
+ Root->getOperator() == CGP.get_intrinsic_w_chain_sdnode() ||
+ Root->getOperator() == CGP.get_intrinsic_wo_chain_sdnode() ||
+ PInfo.getNumOperands() > 1 ||
+ PInfo.hasProperty(SDNPHasChain) ||
+ PInfo.hasProperty(SDNPInGlue) ||
+ PInfo.hasProperty(SDNPOptInGlue);
+ }
+
+ if (NeedCheck)
+ AddMatcher(new CheckFoldableChainNodeMatcher());
+ }
+ }
+
+ // If this node has an output glue and isn't the root, remember it.
+ if (N->NodeHasProperty(SDNPOutGlue, CGP) &&
+ N != Pattern.getSrcPattern()) {
+ // TODO: This redundantly records nodes with both glues and chains.
+
+ // Record the node and remember it in our chained nodes list.
+ AddMatcher(new RecordMatcher("'" + N->getOperator()->getName().str() +
+ "' glue output node",
+ NextRecordedOperandNo));
+ }
+
+ // If this node is known to have an input glue or if it *might* have an input
+ // glue, capture it as the glue input of the pattern.
+ if (N->NodeHasProperty(SDNPOptInGlue, CGP) ||
+ N->NodeHasProperty(SDNPInGlue, CGP))
+ AddMatcher(new CaptureGlueInputMatcher());
+
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i, ++OpNo) {
+ // Get the code suitable for matching this child. Move to the child, check
+ // it then move back to the parent.
+ AddMatcher(new MoveChildMatcher(OpNo));
+ EmitMatchCode(N->getChild(i), NodeNoTypes->getChild(i));
+ AddMatcher(new MoveParentMatcher());
+ }
+}
+
+bool MatcherGen::recordUniqueNode(const std::string &Name) {
+ unsigned &VarMapEntry = VariableMap[Name];
+ if (VarMapEntry == 0) {
+ // If it is a named node, we must emit a 'Record' opcode.
+ AddMatcher(new RecordMatcher("$" + Name, NextRecordedOperandNo));
+ VarMapEntry = ++NextRecordedOperandNo;
+ return true;
+ }
+
+ // If we get here, this is a second reference to a specific name. Since
+ // we already have checked that the first reference is valid, we don't
+ // have to recursively match it, just check that it's the same as the
+ // previously named thing.
+ AddMatcher(new CheckSameMatcher(VarMapEntry-1));
+ return false;
+}
+
+void MatcherGen::EmitMatchCode(const TreePatternNode *N,
+ TreePatternNode *NodeNoTypes) {
+ // If N and NodeNoTypes don't agree on a type, then this is a case where we
+ // need to do a type check. Emit the check, apply the type to NodeNoTypes and
+ // reinfer any correlated types.
+ SmallVector<unsigned, 2> ResultsToTypeCheck;
+
+ for (unsigned i = 0, e = NodeNoTypes->getNumTypes(); i != e; ++i) {
+ if (NodeNoTypes->getExtType(i) == N->getExtType(i)) continue;
+ NodeNoTypes->setType(i, N->getExtType(i));
+ InferPossibleTypes();
+ ResultsToTypeCheck.push_back(i);
+ }
+
+ // If this node has a name associated with it, capture it in VariableMap. If
+ // we already saw this in the pattern, emit code to verify dagness.
+ if (!N->getName().empty())
+ if (!recordUniqueNode(N->getName()))
+ return;
+
+ if (N->isLeaf())
+ EmitLeafMatchCode(N);
+ else
+ EmitOperatorMatchCode(N, NodeNoTypes);
+
+ // If there are node predicates for this node, generate their checks.
+ for (unsigned i = 0, e = N->getPredicateFns().size(); i != e; ++i)
+ AddMatcher(new CheckPredicateMatcher(N->getPredicateFns()[i]));
+
+ for (unsigned i = 0, e = ResultsToTypeCheck.size(); i != e; ++i)
+ AddMatcher(new CheckTypeMatcher(N->getType(ResultsToTypeCheck[i]),
+ ResultsToTypeCheck[i]));
+}
+
+/// EmitMatcherCode - Generate the code that matches the predicate of this
+/// pattern for the specified Variant. If the variant is invalid this returns
+/// true and does not generate code, if it is valid, it returns false.
+bool MatcherGen::EmitMatcherCode(unsigned Variant) {
+ // If the root of the pattern is a ComplexPattern and if it is specified to
+ // match some number of root opcodes, these are considered to be our variants.
+ // Depending on which variant we're generating code for, emit the root opcode
+ // check.
+ if (const ComplexPattern *CP =
+ Pattern.getSrcPattern()->getComplexPatternInfo(CGP)) {
+ const std::vector<Record*> &OpNodes = CP->getRootNodes();
+ assert(!OpNodes.empty() &&"Complex Pattern must specify what it can match");
+ if (Variant >= OpNodes.size()) return true;
+
+ AddMatcher(new CheckOpcodeMatcher(CGP.getSDNodeInfo(OpNodes[Variant])));
+ } else {
+ if (Variant != 0) return true;
+ }
+
+ // Emit the matcher for the pattern structure and types.
+ EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes);
+
+ // If the pattern has a predicate on it (e.g. only enabled when a subtarget
+ // feature is around, do the check).
+ if (!Pattern.getPredicateCheck().empty())
+ AddMatcher(new CheckPatternPredicateMatcher(Pattern.getPredicateCheck()));
+
+ // Now that we've completed the structural type match, emit any ComplexPattern
+ // checks (e.g. addrmode matches). We emit this after the structural match
+ // because they are generally more expensive to evaluate and more difficult to
+ // factor.
+ for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) {
+ const TreePatternNode *N = MatchedComplexPatterns[i].first;
+
+ // Remember where the results of this match get stuck.
+ if (N->isLeaf()) {
+ NamedComplexPatternOperands[N->getName()] = NextRecordedOperandNo + 1;
+ } else {
+ unsigned CurOp = NextRecordedOperandNo;
+ for (unsigned i = 0; i < N->getNumChildren(); ++i) {
+ NamedComplexPatternOperands[N->getChild(i)->getName()] = CurOp + 1;
+ CurOp += N->getChild(i)->getNumMIResults(CGP);
+ }
+ }
+
+ // Get the slot we recorded the value in from the name on the node.
+ unsigned RecNodeEntry = MatchedComplexPatterns[i].second;
+
+ const ComplexPattern &CP = *N->getComplexPatternInfo(CGP);
+
+ // Emit a CheckComplexPat operation, which does the match (aborting if it
+ // fails) and pushes the matched operands onto the recorded nodes list.
+ AddMatcher(new CheckComplexPatMatcher(CP, RecNodeEntry,
+ N->getName(), NextRecordedOperandNo));
+
+ // Record the right number of operands.
+ NextRecordedOperandNo += CP.getNumOperands();
+ if (CP.hasProperty(SDNPHasChain)) {
+ // If the complex pattern has a chain, then we need to keep track of the
+ // fact that we just recorded a chain input. The chain input will be
+ // matched as the last operand of the predicate if it was successful.
+ ++NextRecordedOperandNo; // Chained node operand.
+
+ // It is the last operand recorded.
+ assert(NextRecordedOperandNo > 1 &&
+ "Should have recorded input/result chains at least!");
+ MatchedChainNodes.push_back(NextRecordedOperandNo-1);
+ }
+
+ // TODO: Complex patterns can't have output glues, if they did, we'd want
+ // to record them.
+ }
+
+ return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Node Result Generation
+//===----------------------------------------------------------------------===//
+
+void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps){
+ assert(!N->getName().empty() && "Operand not named!");
+
+ if (unsigned SlotNo = NamedComplexPatternOperands[N->getName()]) {
+ // Complex operands have already been completely selected, just find the
+ // right slot ant add the arguments directly.
+ for (unsigned i = 0; i < N->getNumMIResults(CGP); ++i)
+ ResultOps.push_back(SlotNo - 1 + i);
+
+ return;
+ }
+
+ unsigned SlotNo = getNamedArgumentSlot(N->getName());
+
+ // If this is an 'imm' or 'fpimm' node, make sure to convert it to the target
+ // version of the immediate so that it doesn't get selected due to some other
+ // node use.
+ if (!N->isLeaf()) {
+ StringRef OperatorName = N->getOperator()->getName();
+ if (OperatorName == "imm" || OperatorName == "fpimm") {
+ AddMatcher(new EmitConvertToTargetMatcher(SlotNo));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+ }
+
+ for (unsigned i = 0; i < N->getNumMIResults(CGP); ++i)
+ ResultOps.push_back(SlotNo + i);
+}
+
+void MatcherGen::EmitResultLeafAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps) {
+ assert(N->isLeaf() && "Must be a leaf");
+
+ if (IntInit *II = dyn_cast<IntInit>(N->getLeafValue())) {
+ AddMatcher(new EmitIntegerMatcher(II->getValue(), N->getType(0)));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+
+ // If this is an explicit register reference, handle it.
+ if (DefInit *DI = dyn_cast<DefInit>(N->getLeafValue())) {
+ Record *Def = DI->getDef();
+ if (Def->isSubClassOf("Register")) {
+ const CodeGenRegister *Reg =
+ CGP.getTargetInfo().getRegBank().getReg(Def);
+ AddMatcher(new EmitRegisterMatcher(Reg, N->getType(0)));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+
+ if (Def->getName() == "zero_reg") {
+ AddMatcher(new EmitRegisterMatcher(nullptr, N->getType(0)));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+
+ // Handle a reference to a register class. This is used
+ // in COPY_TO_SUBREG instructions.
+ if (Def->isSubClassOf("RegisterOperand"))
+ Def = Def->getValueAsDef("RegClass");
+ if (Def->isSubClassOf("RegisterClass")) {
+ std::string Value = getQualifiedName(Def) + "RegClassID";
+ AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+
+ // Handle a subregister index. This is used for INSERT_SUBREG etc.
+ if (Def->isSubClassOf("SubRegIndex")) {
+ std::string Value = getQualifiedName(Def);
+ AddMatcher(new EmitStringIntegerMatcher(Value, MVT::i32));
+ ResultOps.push_back(NextRecordedOperandNo++);
+ return;
+ }
+ }
+
+ errs() << "unhandled leaf node: \n";
+ N->dump();
+}
+
+/// GetInstPatternNode - Get the pattern for an instruction.
+///
+const TreePatternNode *MatcherGen::
+GetInstPatternNode(const DAGInstruction &Inst, const TreePatternNode *N) {
+ const TreePattern *InstPat = Inst.getPattern();
+
+ // FIXME2?: Assume actual pattern comes before "implicit".
+ TreePatternNode *InstPatNode;
+ if (InstPat)
+ InstPatNode = InstPat->getTree(0);
+ else if (/*isRoot*/ N == Pattern.getDstPattern())
+ InstPatNode = Pattern.getSrcPattern();
+ else
+ return nullptr;
+
+ if (InstPatNode && !InstPatNode->isLeaf() &&
+ InstPatNode->getOperator()->getName() == "set")
+ InstPatNode = InstPatNode->getChild(InstPatNode->getNumChildren()-1);
+
+ return InstPatNode;
+}
+
+static bool
+mayInstNodeLoadOrStore(const TreePatternNode *N,
+ const CodeGenDAGPatterns &CGP) {
+ Record *Op = N->getOperator();
+ const CodeGenTarget &CGT = CGP.getTargetInfo();
+ CodeGenInstruction &II = CGT.getInstruction(Op);
+ return II.mayLoad || II.mayStore;
+}
+
+static unsigned
+numNodesThatMayLoadOrStore(const TreePatternNode *N,
+ const CodeGenDAGPatterns &CGP) {
+ if (N->isLeaf())
+ return 0;
+
+ Record *OpRec = N->getOperator();
+ if (!OpRec->isSubClassOf("Instruction"))
+ return 0;
+
+ unsigned Count = 0;
+ if (mayInstNodeLoadOrStore(N, CGP))
+ ++Count;
+
+ for (unsigned i = 0, e = N->getNumChildren(); i != e; ++i)
+ Count += numNodesThatMayLoadOrStore(N->getChild(i), CGP);
+
+ return Count;
+}
+
+void MatcherGen::
+EmitResultInstructionAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &OutputOps) {
+ Record *Op = N->getOperator();
+ const CodeGenTarget &CGT = CGP.getTargetInfo();
+ CodeGenInstruction &II = CGT.getInstruction(Op);
+ const DAGInstruction &Inst = CGP.getInstruction(Op);
+
+ // If we can, get the pattern for the instruction we're generating. We derive
+ // a variety of information from this pattern, such as whether it has a chain.
+ //
+ // FIXME2: This is extremely dubious for several reasons, not the least of
+ // which it gives special status to instructions with patterns that Pat<>
+ // nodes can't duplicate.
+ const TreePatternNode *InstPatNode = GetInstPatternNode(Inst, N);
+
+ // NodeHasChain - Whether the instruction node we're creating takes chains.
+ bool NodeHasChain = InstPatNode &&
+ InstPatNode->TreeHasProperty(SDNPHasChain, CGP);
+
+ // Instructions which load and store from memory should have a chain,
+ // regardless of whether they happen to have an internal pattern saying so.
+ if (Pattern.getSrcPattern()->TreeHasProperty(SDNPHasChain, CGP)
+ && (II.hasCtrlDep || II.mayLoad || II.mayStore || II.canFoldAsLoad ||
+ II.hasSideEffects))
+ NodeHasChain = true;
+
+ bool isRoot = N == Pattern.getDstPattern();
+
+ // TreeHasOutGlue - True if this tree has glue.
+ bool TreeHasInGlue = false, TreeHasOutGlue = false;
+ if (isRoot) {
+ const TreePatternNode *SrcPat = Pattern.getSrcPattern();
+ TreeHasInGlue = SrcPat->TreeHasProperty(SDNPOptInGlue, CGP) ||
+ SrcPat->TreeHasProperty(SDNPInGlue, CGP);
+
+ // FIXME2: this is checking the entire pattern, not just the node in
+ // question, doing this just for the root seems like a total hack.
+ TreeHasOutGlue = SrcPat->TreeHasProperty(SDNPOutGlue, CGP);
+ }
+
+ // NumResults - This is the number of results produced by the instruction in
+ // the "outs" list.
+ unsigned NumResults = Inst.getNumResults();
+
+ // Number of operands we know the output instruction must have. If it is
+ // variadic, we could have more operands.
+ unsigned NumFixedOperands = II.Operands.size();
+
+ SmallVector<unsigned, 8> InstOps;
+
+ // Loop over all of the fixed operands of the instruction pattern, emitting
+ // code to fill them all in. The node 'N' usually has number children equal to
+ // the number of input operands of the instruction. However, in cases where
+ // there are predicate operands for an instruction, we need to fill in the
+ // 'execute always' values. Match up the node operands to the instruction
+ // operands to do this.
+ unsigned ChildNo = 0;
+ for (unsigned InstOpNo = NumResults, e = NumFixedOperands;
+ InstOpNo != e; ++InstOpNo) {
+ // Determine what to emit for this operand.
+ Record *OperandNode = II.Operands[InstOpNo].Rec;
+ if (OperandNode->isSubClassOf("OperandWithDefaultOps") &&
+ !CGP.getDefaultOperand(OperandNode).DefaultOps.empty()) {
+ // This is a predicate or optional def operand; emit the
+ // 'default ops' operands.
+ const DAGDefaultOperand &DefaultOp
+ = CGP.getDefaultOperand(OperandNode);
+ for (unsigned i = 0, e = DefaultOp.DefaultOps.size(); i != e; ++i)
+ EmitResultOperand(DefaultOp.DefaultOps[i], InstOps);
+ continue;
+ }
+
+ // Otherwise this is a normal operand or a predicate operand without
+ // 'execute always'; emit it.
+
+ // For operands with multiple sub-operands we may need to emit
+ // multiple child patterns to cover them all. However, ComplexPattern
+ // children may themselves emit multiple MI operands.
+ unsigned NumSubOps = 1;
+ if (OperandNode->isSubClassOf("Operand")) {
+ DagInit *MIOpInfo = OperandNode->getValueAsDag("MIOperandInfo");
+ if (unsigned NumArgs = MIOpInfo->getNumArgs())
+ NumSubOps = NumArgs;
+ }
+
+ unsigned FinalNumOps = InstOps.size() + NumSubOps;
+ while (InstOps.size() < FinalNumOps) {
+ const TreePatternNode *Child = N->getChild(ChildNo);
+ unsigned BeforeAddingNumOps = InstOps.size();
+ EmitResultOperand(Child, InstOps);
+ assert(InstOps.size() > BeforeAddingNumOps && "Didn't add any operands");
+
+ // If the operand is an instruction and it produced multiple results, just
+ // take the first one.
+ if (!Child->isLeaf() && Child->getOperator()->isSubClassOf("Instruction"))
+ InstOps.resize(BeforeAddingNumOps+1);
+
+ ++ChildNo;
+ }
+ }
+
+ // If this is a variadic output instruction (i.e. REG_SEQUENCE), we can't
+ // expand suboperands, use default operands, or other features determined from
+ // the CodeGenInstruction after the fixed operands, which were handled
+ // above. Emit the remaining instructions implicitly added by the use for
+ // variable_ops.
+ if (II.Operands.isVariadic) {
+ for (unsigned I = ChildNo, E = N->getNumChildren(); I < E; ++I)
+ EmitResultOperand(N->getChild(I), InstOps);
+ }
+
+ // If this node has input glue or explicitly specified input physregs, we
+ // need to add chained and glued copyfromreg nodes and materialize the glue
+ // input.
+ if (isRoot && !PhysRegInputs.empty()) {
+ // Emit all of the CopyToReg nodes for the input physical registers. These
+ // occur in patterns like (mul:i8 AL:i8, GR8:i8:$src).
+ for (unsigned i = 0, e = PhysRegInputs.size(); i != e; ++i)
+ AddMatcher(new EmitCopyToRegMatcher(PhysRegInputs[i].second,
+ PhysRegInputs[i].first));
+ // Even if the node has no other glue inputs, the resultant node must be
+ // glued to the CopyFromReg nodes we just generated.
+ TreeHasInGlue = true;
+ }
+
+ // Result order: node results, chain, glue
+
+ // Determine the result types.
+ SmallVector<MVT::SimpleValueType, 4> ResultVTs;
+ for (unsigned i = 0, e = N->getNumTypes(); i != e; ++i)
+ ResultVTs.push_back(N->getType(i));
+
+ // If this is the root instruction of a pattern that has physical registers in
+ // its result pattern, add output VTs for them. For example, X86 has:
+ // (set AL, (mul ...))
+ // This also handles implicit results like:
+ // (implicit EFLAGS)
+ if (isRoot && !Pattern.getDstRegs().empty()) {
+ // If the root came from an implicit def in the instruction handling stuff,
+ // don't re-add it.
+ Record *HandledReg = nullptr;
+ if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other)
+ HandledReg = II.ImplicitDefs[0];
+
+ for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) {
+ Record *Reg = Pattern.getDstRegs()[i];
+ if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue;
+ ResultVTs.push_back(getRegisterValueType(Reg, CGT));
+ }
+ }
+
+ // If this is the root of the pattern and the pattern we're matching includes
+ // a node that is variadic, mark the generated node as variadic so that it
+ // gets the excess operands from the input DAG.
+ int NumFixedArityOperands = -1;
+ if (isRoot &&
+ Pattern.getSrcPattern()->NodeHasProperty(SDNPVariadic, CGP))
+ NumFixedArityOperands = Pattern.getSrcPattern()->getNumChildren();
+
+ // If this is the root node and multiple matched nodes in the input pattern
+ // have MemRefs in them, have the interpreter collect them and plop them onto
+ // this node. If there is just one node with MemRefs, leave them on that node
+ // even if it is not the root.
+ //
+ // FIXME3: This is actively incorrect for result patterns with multiple
+ // memory-referencing instructions.
+ bool PatternHasMemOperands =
+ Pattern.getSrcPattern()->TreeHasProperty(SDNPMemOperand, CGP);
+
+ bool NodeHasMemRefs = false;
+ if (PatternHasMemOperands) {
+ unsigned NumNodesThatLoadOrStore =
+ numNodesThatMayLoadOrStore(Pattern.getDstPattern(), CGP);
+ bool NodeIsUniqueLoadOrStore = mayInstNodeLoadOrStore(N, CGP) &&
+ NumNodesThatLoadOrStore == 1;
+ NodeHasMemRefs =
+ NodeIsUniqueLoadOrStore || (isRoot && (mayInstNodeLoadOrStore(N, CGP) ||
+ NumNodesThatLoadOrStore != 1));
+ }
+
+ assert((!ResultVTs.empty() || TreeHasOutGlue || NodeHasChain) &&
+ "Node has no result");
+
+ AddMatcher(new EmitNodeMatcher(II.Namespace+"::"+II.TheDef->getName().str(),
+ ResultVTs, InstOps,
+ NodeHasChain, TreeHasInGlue, TreeHasOutGlue,
+ NodeHasMemRefs, NumFixedArityOperands,
+ NextRecordedOperandNo));
+
+ // The non-chain and non-glue results of the newly emitted node get recorded.
+ for (unsigned i = 0, e = ResultVTs.size(); i != e; ++i) {
+ if (ResultVTs[i] == MVT::Other || ResultVTs[i] == MVT::Glue) break;
+ OutputOps.push_back(NextRecordedOperandNo++);
+ }
+}
+
+void MatcherGen::
+EmitResultSDNodeXFormAsOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps) {
+ assert(N->getOperator()->isSubClassOf("SDNodeXForm") && "Not SDNodeXForm?");
+
+ // Emit the operand.
+ SmallVector<unsigned, 8> InputOps;
+
+ // FIXME2: Could easily generalize this to support multiple inputs and outputs
+ // to the SDNodeXForm. For now we just support one input and one output like
+ // the old instruction selector.
+ assert(N->getNumChildren() == 1);
+ EmitResultOperand(N->getChild(0), InputOps);
+
+ // The input currently must have produced exactly one result.
+ assert(InputOps.size() == 1 && "Unexpected input to SDNodeXForm");
+
+ AddMatcher(new EmitNodeXFormMatcher(InputOps[0], N->getOperator()));
+ ResultOps.push_back(NextRecordedOperandNo++);
+}
+
+void MatcherGen::EmitResultOperand(const TreePatternNode *N,
+ SmallVectorImpl<unsigned> &ResultOps) {
+ // This is something selected from the pattern we matched.
+ if (!N->getName().empty())
+ return EmitResultOfNamedOperand(N, ResultOps);
+
+ if (N->isLeaf())
+ return EmitResultLeafAsOperand(N, ResultOps);
+
+ Record *OpRec = N->getOperator();
+ if (OpRec->isSubClassOf("Instruction"))
+ return EmitResultInstructionAsOperand(N, ResultOps);
+ if (OpRec->isSubClassOf("SDNodeXForm"))
+ return EmitResultSDNodeXFormAsOperand(N, ResultOps);
+ errs() << "Unknown result node to emit code for: " << *N << '\n';
+ PrintFatalError("Unknown node in result pattern!");
+}
+
+void MatcherGen::EmitResultCode() {
+ // Patterns that match nodes with (potentially multiple) chain inputs have to
+ // merge them together into a token factor. This informs the generated code
+ // what all the chained nodes are.
+ if (!MatchedChainNodes.empty())
+ AddMatcher(new EmitMergeInputChainsMatcher(MatchedChainNodes));
+
+ // Codegen the root of the result pattern, capturing the resulting values.
+ SmallVector<unsigned, 8> Ops;
+ EmitResultOperand(Pattern.getDstPattern(), Ops);
+
+ // At this point, we have however many values the result pattern produces.
+ // However, the input pattern might not need all of these. If there are
+ // excess values at the end (such as implicit defs of condition codes etc)
+ // just lop them off. This doesn't need to worry about glue or chains, just
+ // explicit results.
+ //
+ unsigned NumSrcResults = Pattern.getSrcPattern()->getNumTypes();
+
+ // If the pattern also has (implicit) results, count them as well.
+ if (!Pattern.getDstRegs().empty()) {
+ // If the root came from an implicit def in the instruction handling stuff,
+ // don't re-add it.
+ Record *HandledReg = nullptr;
+ const TreePatternNode *DstPat = Pattern.getDstPattern();
+ if (!DstPat->isLeaf() &&DstPat->getOperator()->isSubClassOf("Instruction")){
+ const CodeGenTarget &CGT = CGP.getTargetInfo();
+ CodeGenInstruction &II = CGT.getInstruction(DstPat->getOperator());
+
+ if (II.HasOneImplicitDefWithKnownVT(CGT) != MVT::Other)
+ HandledReg = II.ImplicitDefs[0];
+ }
+
+ for (unsigned i = 0; i != Pattern.getDstRegs().size(); ++i) {
+ Record *Reg = Pattern.getDstRegs()[i];
+ if (!Reg->isSubClassOf("Register") || Reg == HandledReg) continue;
+ ++NumSrcResults;
+ }
+ }
+
+ assert(Ops.size() >= NumSrcResults && "Didn't provide enough results");
+ Ops.resize(NumSrcResults);
+
+ AddMatcher(new CompleteMatchMatcher(Ops, Pattern));
+}
+
+
+/// ConvertPatternToMatcher - Create the matcher for the specified pattern with
+/// the specified variant. If the variant number is invalid, this returns null.
+Matcher *llvm::ConvertPatternToMatcher(const PatternToMatch &Pattern,
+ unsigned Variant,
+ const CodeGenDAGPatterns &CGP) {
+ MatcherGen Gen(Pattern, CGP);
+
+ // Generate the code for the matcher.
+ if (Gen.EmitMatcherCode(Variant))
+ return nullptr;
+
+ // FIXME2: Kill extra MoveParent commands at the end of the matcher sequence.
+ // FIXME2: Split result code out to another table, and make the matcher end
+ // with an "Emit <index>" command. This allows result generation stuff to be
+ // shared and factored?
+
+ // If the match succeeds, then we generate Pattern.
+ Gen.EmitResultCode();
+
+ // Unconditional match.
+ return Gen.GetMatcher();
+}
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
new file mode 100644
index 000000000000..0bb656826fbd
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -0,0 +1,470 @@
+//===- DAGISelMatcherOpt.cpp - Optimize a DAG Matcher ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the DAG Matcher optimizer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "DAGISelMatcher.h"
+#include "CodeGenDAGPatterns.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "isel-opt"
+
+/// ContractNodes - Turn multiple matcher node patterns like 'MoveChild+Record'
+/// into single compound nodes like RecordChild.
+static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr,
+ const CodeGenDAGPatterns &CGP) {
+ // If we reached the end of the chain, we're done.
+ Matcher *N = MatcherPtr.get();
+ if (!N) return;
+
+ // If we have a scope node, walk down all of the children.
+ if (ScopeMatcher *Scope = dyn_cast<ScopeMatcher>(N)) {
+ for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
+ std::unique_ptr<Matcher> Child(Scope->takeChild(i));
+ ContractNodes(Child, CGP);
+ Scope->resetChild(i, Child.release());
+ }
+ return;
+ }
+
+ // If we found a movechild node with a node that comes in a 'foochild' form,
+ // transform it.
+ if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N)) {
+ Matcher *New = nullptr;
+ if (RecordMatcher *RM = dyn_cast<RecordMatcher>(MC->getNext()))
+ if (MC->getChildNo() < 8) // Only have RecordChild0...7
+ New = new RecordChildMatcher(MC->getChildNo(), RM->getWhatFor(),
+ RM->getResultNo());
+
+ if (CheckTypeMatcher *CT = dyn_cast<CheckTypeMatcher>(MC->getNext()))
+ if (MC->getChildNo() < 8 && // Only have CheckChildType0...7
+ CT->getResNo() == 0) // CheckChildType checks res #0
+ New = new CheckChildTypeMatcher(MC->getChildNo(), CT->getType());
+
+ if (CheckSameMatcher *CS = dyn_cast<CheckSameMatcher>(MC->getNext()))
+ if (MC->getChildNo() < 4) // Only have CheckChildSame0...3
+ New = new CheckChildSameMatcher(MC->getChildNo(), CS->getMatchNumber());
+
+ if (CheckIntegerMatcher *CS = dyn_cast<CheckIntegerMatcher>(MC->getNext()))
+ if (MC->getChildNo() < 5) // Only have CheckChildInteger0...4
+ New = new CheckChildIntegerMatcher(MC->getChildNo(), CS->getValue());
+
+ if (New) {
+ // Insert the new node.
+ New->setNext(MatcherPtr.release());
+ MatcherPtr.reset(New);
+ // Remove the old one.
+ MC->setNext(MC->getNext()->takeNext());
+ return ContractNodes(MatcherPtr, CGP);
+ }
+ }
+
+ // Zap movechild -> moveparent.
+ if (MoveChildMatcher *MC = dyn_cast<MoveChildMatcher>(N))
+ if (MoveParentMatcher *MP =
+ dyn_cast<MoveParentMatcher>(MC->getNext())) {
+ MatcherPtr.reset(MP->takeNext());
+ return ContractNodes(MatcherPtr, CGP);
+ }
+
+ // Turn EmitNode->CompleteMatch into MorphNodeTo if we can.
+ if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N))
+ if (CompleteMatchMatcher *CM =
+ dyn_cast<CompleteMatchMatcher>(EN->getNext())) {
+ // We can only use MorphNodeTo if the result values match up.
+ unsigned RootResultFirst = EN->getFirstResultSlot();
+ bool ResultsMatch = true;
+ for (unsigned i = 0, e = CM->getNumResults(); i != e; ++i)
+ if (CM->getResult(i) != RootResultFirst+i)
+ ResultsMatch = false;
+
+ // If the selected node defines a subset of the glue/chain results, we
+ // can't use MorphNodeTo. For example, we can't use MorphNodeTo if the
+ // matched pattern has a chain but the root node doesn't.
+ const PatternToMatch &Pattern = CM->getPattern();
+
+ if (!EN->hasChain() &&
+ Pattern.getSrcPattern()->NodeHasProperty(SDNPHasChain, CGP))
+ ResultsMatch = false;
+
+ // If the matched node has glue and the output root doesn't, we can't
+ // use MorphNodeTo.
+ //
+ // NOTE: Strictly speaking, we don't have to check for glue here
+ // because the code in the pattern generator doesn't handle it right. We
+ // do it anyway for thoroughness.
+ if (!EN->hasOutFlag() &&
+ Pattern.getSrcPattern()->NodeHasProperty(SDNPOutGlue, CGP))
+ ResultsMatch = false;
+
+
+ // If the root result node defines more results than the source root node
+ // *and* has a chain or glue input, then we can't match it because it
+ // would end up replacing the extra result with the chain/glue.
+#if 0
+ if ((EN->hasGlue() || EN->hasChain()) &&
+ EN->getNumNonChainGlueVTs() > ... need to get no results reliably ...)
+ ResultMatch = false;
+#endif
+
+ if (ResultsMatch) {
+ const SmallVectorImpl<MVT::SimpleValueType> &VTs = EN->getVTList();
+ const SmallVectorImpl<unsigned> &Operands = EN->getOperandList();
+ MatcherPtr.reset(new MorphNodeToMatcher(EN->getOpcodeName(),
+ VTs, Operands,
+ EN->hasChain(), EN->hasInFlag(),
+ EN->hasOutFlag(),
+ EN->hasMemRefs(),
+ EN->getNumFixedArityOperands(),
+ Pattern));
+ return;
+ }
+
+ // FIXME2: Kill off all the SelectionDAG::SelectNodeTo and getMachineNode
+ // variants.
+ }
+
+ ContractNodes(N->getNextPtr(), CGP);
+
+
+ // If we have a CheckType/CheckChildType/Record node followed by a
+ // CheckOpcode, invert the two nodes. We prefer to do structural checks
+ // before type checks, as this opens opportunities for factoring on targets
+ // like X86 where many operations are valid on multiple types.
+ if ((isa<CheckTypeMatcher>(N) || isa<CheckChildTypeMatcher>(N) ||
+ isa<RecordMatcher>(N)) &&
+ isa<CheckOpcodeMatcher>(N->getNext())) {
+ // Unlink the two nodes from the list.
+ Matcher *CheckType = MatcherPtr.release();
+ Matcher *CheckOpcode = CheckType->takeNext();
+ Matcher *Tail = CheckOpcode->takeNext();
+
+ // Relink them.
+ MatcherPtr.reset(CheckOpcode);
+ CheckOpcode->setNext(CheckType);
+ CheckType->setNext(Tail);
+ return ContractNodes(MatcherPtr, CGP);
+ }
+}
+
+/// FindNodeWithKind - Scan a series of matchers looking for a matcher with a
+/// specified kind. Return null if we didn't find one otherwise return the
+/// matcher.
+static Matcher *FindNodeWithKind(Matcher *M, Matcher::KindTy Kind) {
+ for (; M; M = M->getNext())
+ if (M->getKind() == Kind)
+ return M;
+ return nullptr;
+}
+
+
+/// FactorNodes - Turn matches like this:
+/// Scope
+/// OPC_CheckType i32
+/// ABC
+/// OPC_CheckType i32
+/// XYZ
+/// into:
+/// OPC_CheckType i32
+/// Scope
+/// ABC
+/// XYZ
+///
+static void FactorNodes(std::unique_ptr<Matcher> &InputMatcherPtr) {
+ // Look for a push node. Iterates instead of recurses to reduce stack usage.
+ ScopeMatcher *Scope = nullptr;
+ std::unique_ptr<Matcher> *RebindableMatcherPtr = &InputMatcherPtr;
+ while (!Scope) {
+ // If we reached the end of the chain, we're done.
+ Matcher *N = RebindableMatcherPtr->get();
+ if (!N) return;
+
+ // If this is not a push node, just scan for one.
+ Scope = dyn_cast<ScopeMatcher>(N);
+ if (!Scope)
+ RebindableMatcherPtr = &(N->getNextPtr());
+ }
+ std::unique_ptr<Matcher> &MatcherPtr = *RebindableMatcherPtr;
+
+ // Okay, pull together the children of the scope node into a vector so we can
+ // inspect it more easily.
+ SmallVector<Matcher*, 32> OptionsToMatch;
+
+ for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
+ // Factor the subexpression.
+ std::unique_ptr<Matcher> Child(Scope->takeChild(i));
+ FactorNodes(Child);
+
+ if (Child) {
+ // If the child is a ScopeMatcher we can just merge its contents.
+ if (auto *SM = dyn_cast<ScopeMatcher>(Child.get())) {
+ for (unsigned j = 0, e = SM->getNumChildren(); j != e; ++j)
+ OptionsToMatch.push_back(SM->takeChild(j));
+ } else {
+ OptionsToMatch.push_back(Child.release());
+ }
+ }
+ }
+
+ SmallVector<Matcher*, 32> NewOptionsToMatch;
+
+ // Loop over options to match, merging neighboring patterns with identical
+ // starting nodes into a shared matcher.
+ for (unsigned OptionIdx = 0, e = OptionsToMatch.size(); OptionIdx != e;) {
+ // Find the set of matchers that start with this node.
+ Matcher *Optn = OptionsToMatch[OptionIdx++];
+
+ if (OptionIdx == e) {
+ NewOptionsToMatch.push_back(Optn);
+ continue;
+ }
+
+ // See if the next option starts with the same matcher. If the two
+ // neighbors *do* start with the same matcher, we can factor the matcher out
+ // of at least these two patterns. See what the maximal set we can merge
+ // together is.
+ SmallVector<Matcher*, 8> EqualMatchers;
+ EqualMatchers.push_back(Optn);
+
+ // Factor all of the known-equal matchers after this one into the same
+ // group.
+ while (OptionIdx != e && OptionsToMatch[OptionIdx]->isEqual(Optn))
+ EqualMatchers.push_back(OptionsToMatch[OptionIdx++]);
+
+ // If we found a non-equal matcher, see if it is contradictory with the
+ // current node. If so, we know that the ordering relation between the
+ // current sets of nodes and this node don't matter. Look past it to see if
+ // we can merge anything else into this matching group.
+ unsigned Scan = OptionIdx;
+ while (1) {
+ // If we ran out of stuff to scan, we're done.
+ if (Scan == e) break;
+
+ Matcher *ScanMatcher = OptionsToMatch[Scan];
+
+ // If we found an entry that matches out matcher, merge it into the set to
+ // handle.
+ if (Optn->isEqual(ScanMatcher)) {
+ // If is equal after all, add the option to EqualMatchers and remove it
+ // from OptionsToMatch.
+ EqualMatchers.push_back(ScanMatcher);
+ OptionsToMatch.erase(OptionsToMatch.begin()+Scan);
+ --e;
+ continue;
+ }
+
+ // If the option we're checking for contradicts the start of the list,
+ // skip over it.
+ if (Optn->isContradictory(ScanMatcher)) {
+ ++Scan;
+ continue;
+ }
+
+ // If we're scanning for a simple node, see if it occurs later in the
+ // sequence. If so, and if we can move it up, it might be contradictory
+ // or the same as what we're looking for. If so, reorder it.
+ if (Optn->isSimplePredicateOrRecordNode()) {
+ Matcher *M2 = FindNodeWithKind(ScanMatcher, Optn->getKind());
+ if (M2 && M2 != ScanMatcher &&
+ M2->canMoveBefore(ScanMatcher) &&
+ (M2->isEqual(Optn) || M2->isContradictory(Optn))) {
+ Matcher *MatcherWithoutM2 = ScanMatcher->unlinkNode(M2);
+ M2->setNext(MatcherWithoutM2);
+ OptionsToMatch[Scan] = M2;
+ continue;
+ }
+ }
+
+ // Otherwise, we don't know how to handle this entry, we have to bail.
+ break;
+ }
+
+ if (Scan != e &&
+ // Don't print it's obvious nothing extra could be merged anyway.
+ Scan+1 != e) {
+ DEBUG(errs() << "Couldn't merge this:\n";
+ Optn->print(errs(), 4);
+ errs() << "into this:\n";
+ OptionsToMatch[Scan]->print(errs(), 4);
+ if (Scan+1 != e)
+ OptionsToMatch[Scan+1]->printOne(errs());
+ if (Scan+2 < e)
+ OptionsToMatch[Scan+2]->printOne(errs());
+ errs() << "\n");
+ }
+
+ // If we only found one option starting with this matcher, no factoring is
+ // possible.
+ if (EqualMatchers.size() == 1) {
+ NewOptionsToMatch.push_back(EqualMatchers[0]);
+ continue;
+ }
+
+ // Factor these checks by pulling the first node off each entry and
+ // discarding it. Take the first one off the first entry to reuse.
+ Matcher *Shared = Optn;
+ Optn = Optn->takeNext();
+ EqualMatchers[0] = Optn;
+
+ // Remove and delete the first node from the other matchers we're factoring.
+ for (unsigned i = 1, e = EqualMatchers.size(); i != e; ++i) {
+ Matcher *Tmp = EqualMatchers[i]->takeNext();
+ delete EqualMatchers[i];
+ EqualMatchers[i] = Tmp;
+ }
+
+ Shared->setNext(new ScopeMatcher(EqualMatchers));
+
+ // Recursively factor the newly created node.
+ FactorNodes(Shared->getNextPtr());
+
+ NewOptionsToMatch.push_back(Shared);
+ }
+
+ // If we're down to a single pattern to match, then we don't need this scope
+ // anymore.
+ if (NewOptionsToMatch.size() == 1) {
+ MatcherPtr.reset(NewOptionsToMatch[0]);
+ return;
+ }
+
+ if (NewOptionsToMatch.empty()) {
+ MatcherPtr.reset();
+ return;
+ }
+
+ // If our factoring failed (didn't achieve anything) see if we can simplify in
+ // other ways.
+
+ // Check to see if all of the leading entries are now opcode checks. If so,
+ // we can convert this Scope to be a OpcodeSwitch instead.
+ bool AllOpcodeChecks = true, AllTypeChecks = true;
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
+ // Check to see if this breaks a series of CheckOpcodeMatchers.
+ if (AllOpcodeChecks &&
+ !isa<CheckOpcodeMatcher>(NewOptionsToMatch[i])) {
+#if 0
+ if (i > 3) {
+ errs() << "FAILING OPC #" << i << "\n";
+ NewOptionsToMatch[i]->dump();
+ }
+#endif
+ AllOpcodeChecks = false;
+ }
+
+ // Check to see if this breaks a series of CheckTypeMatcher's.
+ if (AllTypeChecks) {
+ CheckTypeMatcher *CTM =
+ cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],
+ Matcher::CheckType));
+ if (!CTM ||
+ // iPTR checks could alias any other case without us knowing, don't
+ // bother with them.
+ CTM->getType() == MVT::iPTR ||
+ // SwitchType only works for result #0.
+ CTM->getResNo() != 0 ||
+ // If the CheckType isn't at the start of the list, see if we can move
+ // it there.
+ !CTM->canMoveBefore(NewOptionsToMatch[i])) {
+#if 0
+ if (i > 3 && AllTypeChecks) {
+ errs() << "FAILING TYPE #" << i << "\n";
+ NewOptionsToMatch[i]->dump();
+ }
+#endif
+ AllTypeChecks = false;
+ }
+ }
+ }
+
+ // If all the options are CheckOpcode's, we can form the SwitchOpcode, woot.
+ if (AllOpcodeChecks) {
+ StringSet<> Opcodes;
+ SmallVector<std::pair<const SDNodeInfo*, Matcher*>, 8> Cases;
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
+ CheckOpcodeMatcher *COM = cast<CheckOpcodeMatcher>(NewOptionsToMatch[i]);
+ assert(Opcodes.insert(COM->getOpcode().getEnumName()).second &&
+ "Duplicate opcodes not factored?");
+ Cases.push_back(std::make_pair(&COM->getOpcode(), COM->takeNext()));
+ delete COM;
+ }
+
+ MatcherPtr.reset(new SwitchOpcodeMatcher(Cases));
+ return;
+ }
+
+ // If all the options are CheckType's, we can form the SwitchType, woot.
+ if (AllTypeChecks) {
+ DenseMap<unsigned, unsigned> TypeEntry;
+ SmallVector<std::pair<MVT::SimpleValueType, Matcher*>, 8> Cases;
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i) {
+ CheckTypeMatcher *CTM =
+ cast_or_null<CheckTypeMatcher>(FindNodeWithKind(NewOptionsToMatch[i],
+ Matcher::CheckType));
+ Matcher *MatcherWithoutCTM = NewOptionsToMatch[i]->unlinkNode(CTM);
+ MVT::SimpleValueType CTMTy = CTM->getType();
+ delete CTM;
+
+ unsigned &Entry = TypeEntry[CTMTy];
+ if (Entry != 0) {
+ // If we have unfactored duplicate types, then we should factor them.
+ Matcher *PrevMatcher = Cases[Entry-1].second;
+ if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(PrevMatcher)) {
+ SM->setNumChildren(SM->getNumChildren()+1);
+ SM->resetChild(SM->getNumChildren()-1, MatcherWithoutCTM);
+ continue;
+ }
+
+ Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM };
+ Cases[Entry-1].second = new ScopeMatcher(Entries);
+ continue;
+ }
+
+ Entry = Cases.size()+1;
+ Cases.push_back(std::make_pair(CTMTy, MatcherWithoutCTM));
+ }
+
+ // Make sure we recursively factor any scopes we may have created.
+ for (auto &M : Cases) {
+ if (ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M.second)) {
+ std::unique_ptr<Matcher> Scope(SM);
+ FactorNodes(Scope);
+ M.second = Scope.release();
+ assert(M.second && "null matcher");
+ }
+ }
+
+ if (Cases.size() != 1) {
+ MatcherPtr.reset(new SwitchTypeMatcher(Cases));
+ } else {
+ // If we factored and ended up with one case, create it now.
+ MatcherPtr.reset(new CheckTypeMatcher(Cases[0].first, 0));
+ MatcherPtr->setNext(Cases[0].second);
+ }
+ return;
+ }
+
+
+ // Reassemble the Scope node with the adjusted children.
+ Scope->setNumChildren(NewOptionsToMatch.size());
+ for (unsigned i = 0, e = NewOptionsToMatch.size(); i != e; ++i)
+ Scope->resetChild(i, NewOptionsToMatch[i]);
+}
+
+void
+llvm::OptimizeMatcher(std::unique_ptr<Matcher> &MatcherPtr,
+ const CodeGenDAGPatterns &CGP) {
+ ContractNodes(MatcherPtr, CGP);
+ FactorNodes(MatcherPtr);
+}
diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
new file mode 100644
index 000000000000..f879a5bae215
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -0,0 +1,991 @@
+//===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This class parses the Schedule.td file and produces an API that can be used
+// to reason about whether an instruction can be added to a packet on a VLIW
+// architecture. The class internally generates a deterministic finite
+// automaton (DFA) that models all possible mappings of machine instructions
+// to functional units as instructions are added to a packet.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "dfa-emitter"
+
+#include "CodeGenTarget.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <cstdint>
+#include <map>
+#include <set>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+// --------------------------------------------------------------------
+// Definitions shared between DFAPacketizer.cpp and DFAPacketizerEmitter.cpp
+
+// DFA_MAX_RESTERMS * DFA_MAX_RESOURCES must fit within sizeof DFAInput.
+// This is verified in DFAPacketizer.cpp:DFAPacketizer::DFAPacketizer.
+//
+// e.g. terms x resource bit combinations that fit in uint32_t:
+// 4 terms x 8 bits = 32 bits
+// 3 terms x 10 bits = 30 bits
+// 2 terms x 16 bits = 32 bits
+//
+// e.g. terms x resource bit combinations that fit in uint64_t:
+// 8 terms x 8 bits = 64 bits
+// 7 terms x 9 bits = 63 bits
+// 6 terms x 10 bits = 60 bits
+// 5 terms x 12 bits = 60 bits
+// 4 terms x 16 bits = 64 bits <--- current
+// 3 terms x 21 bits = 63 bits
+// 2 terms x 32 bits = 64 bits
+//
+#define DFA_MAX_RESTERMS 4 // The max # of AND'ed resource terms.
+#define DFA_MAX_RESOURCES 16 // The max # of resource bits in one term.
+
+typedef uint64_t DFAInput;
+typedef int64_t DFAStateInput;
+#define DFA_TBLTYPE "int64_t" // For generating DFAStateInputTable.
+
+namespace {
+
+ DFAInput addDFAFuncUnits(DFAInput Inp, unsigned FuncUnits) {
+ return (Inp << DFA_MAX_RESOURCES) | FuncUnits;
+ }
+
+ /// Return the DFAInput for an instruction class input vector.
+ /// This function is used in both DFAPacketizer.cpp and in
+ /// DFAPacketizerEmitter.cpp.
+ DFAInput getDFAInsnInput(const std::vector<unsigned> &InsnClass) {
+ DFAInput InsnInput = 0;
+ assert((InsnClass.size() <= DFA_MAX_RESTERMS) &&
+ "Exceeded maximum number of DFA terms");
+ for (auto U : InsnClass)
+ InsnInput = addDFAFuncUnits(InsnInput, U);
+ return InsnInput;
+ }
+
+} // end anonymous namespace
+
+// --------------------------------------------------------------------
+
+#ifndef NDEBUG
+// To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".
+//
+// dbgsInsnClass - When debugging, print instruction class stages.
+//
+void dbgsInsnClass(const std::vector<unsigned> &InsnClass);
+//
+// dbgsStateInfo - When debugging, print the set of state info.
+//
+void dbgsStateInfo(const std::set<unsigned> &stateInfo);
+//
+// dbgsIndent - When debugging, indent by the specified amount.
+//
+void dbgsIndent(unsigned indent);
+#endif
+
+//
+// class DFAPacketizerEmitter: class that generates and prints out the DFA
+// for resource tracking.
+//
+namespace {
+
+class DFAPacketizerEmitter {
+private:
+ std::string TargetName;
+ //
+ // allInsnClasses is the set of all possible resources consumed by an
+ // InstrStage.
+ //
+ std::vector<std::vector<unsigned>> allInsnClasses;
+ RecordKeeper &Records;
+
+public:
+ DFAPacketizerEmitter(RecordKeeper &R);
+
+ //
+ // collectAllFuncUnits - Construct a map of function unit names to bits.
+ //
+ int collectAllFuncUnits(std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ int &maxResources,
+ raw_ostream &OS);
+
+ //
+ // collectAllComboFuncs - Construct a map from a combo function unit bit to
+ // the bits of all included functional units.
+ //
+ int collectAllComboFuncs(std::vector<Record*> &ComboFuncList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ raw_ostream &OS);
+
+ //
+ // collectOneInsnClass - Populate allInsnClasses with one instruction class.
+ //
+ int collectOneInsnClass(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ Record *ItinData,
+ raw_ostream &OS);
+
+ //
+ // collectAllInsnClasses - Populate allInsnClasses which is a set of units
+ // used in each stage.
+ //
+ int collectAllInsnClasses(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::vector<Record*> &ItinDataList,
+ int &maxStages,
+ raw_ostream &OS);
+
+ void run(raw_ostream &OS);
+};
+
+//
+// State represents the usage of machine resources if the packet contains
+// a set of instruction classes.
+//
+// Specifically, currentState is a set of bit-masks.
+// The nth bit in a bit-mask indicates whether the nth resource is being used
+// by this state. The set of bit-masks in a state represent the different
+// possible outcomes of transitioning to this state.
+// For example: consider a two resource architecture: resource L and resource M
+// with three instruction classes: L, M, and L_or_M.
+// From the initial state (currentState = 0x00), if we add instruction class
+// L_or_M we will transition to a state with currentState = [0x01, 0x10]. This
+// represents the possible resource states that can result from adding a L_or_M
+// instruction
+//
+// Another way of thinking about this transition is we are mapping a NDFA with
+// two states [0x01] and [0x10] into a DFA with a single state [0x01, 0x10].
+//
+// A State instance also contains a collection of transitions from that state:
+// a map from inputs to new states.
+//
+class State {
+ public:
+ static int currentStateNum;
+ // stateNum is the only member used for equality/ordering, all other members
+ // can be mutated even in const State objects.
+ const int stateNum;
+ mutable bool isInitial;
+ mutable std::set<unsigned> stateInfo;
+ typedef std::map<std::vector<unsigned>, const State *> TransitionMap;
+ mutable TransitionMap Transitions;
+
+ State();
+
+ bool operator<(const State &s) const {
+ return stateNum < s.stateNum;
+ }
+
+ //
+ // canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass
+ // may be a valid transition from this state i.e., can an instruction of type
+ // InsnClass be added to the packet represented by this state.
+ //
+ // Note that for multiple stages, this quick check does not take into account
+ // any possible resource competition between the stages themselves. That is
+ // enforced in AddInsnClassStages which checks the cross product of all
+ // stages for resource availability (which is a more involved check).
+ //
+ bool canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap) const;
+
+ //
+ // AddInsnClass - Return all combinations of resource reservation
+ // which are possible from this state (PossibleStates).
+ //
+ // PossibleStates is the set of valid resource states that ensue from valid
+ // transitions.
+ //
+ void AddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ std::set<unsigned> &PossibleStates) const;
+
+ //
+ // AddInsnClassStages - Return all combinations of resource reservation
+ // resulting from the cross product of all stages for this InsnClass
+ // which are possible from this state (PossibleStates).
+ //
+ void AddInsnClassStages(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ unsigned chkstage, unsigned numstages,
+ unsigned prevState, unsigned origState,
+ DenseSet<unsigned> &VisitedResourceStates,
+ std::set<unsigned> &PossibleStates) const;
+
+ //
+ // addTransition - Add a transition from this state given the input InsnClass
+ //
+ void addTransition(std::vector<unsigned> InsnClass, const State *To) const;
+
+ //
+ // hasTransition - Returns true if there is a transition from this state
+ // given the input InsnClass
+ //
+ bool hasTransition(std::vector<unsigned> InsnClass) const;
+};
+
+//
+// class DFA: deterministic finite automaton for processor resource tracking.
+//
+class DFA {
+public:
+ DFA() = default;
+
+ // Set of states. Need to keep this sorted to emit the transition table.
+ typedef std::set<State> StateSet;
+ StateSet states;
+
+ State *currentState = nullptr;
+
+ //
+ // Modify the DFA.
+ //
+ const State &newState();
+
+ //
+ // writeTable: Print out a table representing the DFA.
+ //
+ void writeTableAndAPI(raw_ostream &OS, const std::string &ClassName,
+ int numInsnClasses = 0,
+ int maxResources = 0, int numCombos = 0, int maxStages = 0);
+};
+
+} // end anonymous namespace
+
+#ifndef NDEBUG
+// To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".
+//
+// dbgsInsnClass - When debugging, print instruction class stages.
+//
+void dbgsInsnClass(const std::vector<unsigned> &InsnClass) {
+ DEBUG(dbgs() << "InsnClass: ");
+ for (unsigned i = 0; i < InsnClass.size(); ++i) {
+ if (i > 0) {
+ DEBUG(dbgs() << ", ");
+ }
+ DEBUG(dbgs() << "0x" << utohexstr(InsnClass[i]));
+ }
+ DFAInput InsnInput = getDFAInsnInput(InsnClass);
+ DEBUG(dbgs() << " (input: 0x" << utohexstr(InsnInput) << ")");
+}
+
+//
+// dbgsStateInfo - When debugging, print the set of state info.
+//
+void dbgsStateInfo(const std::set<unsigned> &stateInfo) {
+ DEBUG(dbgs() << "StateInfo: ");
+ unsigned i = 0;
+ for (std::set<unsigned>::iterator SI = stateInfo.begin();
+ SI != stateInfo.end(); ++SI, ++i) {
+ unsigned thisState = *SI;
+ if (i > 0) {
+ DEBUG(dbgs() << ", ");
+ }
+ DEBUG(dbgs() << "0x" << utohexstr(thisState));
+ }
+}
+
+//
+// dbgsIndent - When debugging, indent by the specified amount.
+//
+void dbgsIndent(unsigned indent) {
+ for (unsigned i = 0; i < indent; ++i) {
+ DEBUG(dbgs() << " ");
+ }
+}
+#endif // NDEBUG
+
+//
+// Constructors and destructors for State and DFA
+//
+State::State() :
+ stateNum(currentStateNum++), isInitial(false) {}
+
+//
+// addTransition - Add a transition from this state given the input InsnClass
+//
+void State::addTransition(std::vector<unsigned> InsnClass, const State *To)
+ const {
+ assert(!Transitions.count(InsnClass) &&
+ "Cannot have multiple transitions for the same input");
+ Transitions[InsnClass] = To;
+}
+
+//
+// hasTransition - Returns true if there is a transition from this state
+// given the input InsnClass
+//
+bool State::hasTransition(std::vector<unsigned> InsnClass) const {
+ return Transitions.count(InsnClass) > 0;
+}
+
+//
+// AddInsnClass - Return all combinations of resource reservation
+// which are possible from this state (PossibleStates).
+//
+// PossibleStates is the set of valid resource states that ensue from valid
+// transitions.
+//
+void State::AddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ std::set<unsigned> &PossibleStates) const {
+ //
+ // Iterate over all resource states in currentState.
+ //
+ unsigned numstages = InsnClass.size();
+ assert((numstages > 0) && "InsnClass has no stages");
+
+ for (std::set<unsigned>::iterator SI = stateInfo.begin();
+ SI != stateInfo.end(); ++SI) {
+ unsigned thisState = *SI;
+
+ DenseSet<unsigned> VisitedResourceStates;
+
+ DEBUG(dbgs() << " thisState: 0x" << utohexstr(thisState) << "\n");
+ AddInsnClassStages(InsnClass, ComboBitToBitsMap,
+ numstages - 1, numstages,
+ thisState, thisState,
+ VisitedResourceStates, PossibleStates);
+ }
+}
+
+void State::AddInsnClassStages(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ unsigned chkstage, unsigned numstages,
+ unsigned prevState, unsigned origState,
+ DenseSet<unsigned> &VisitedResourceStates,
+ std::set<unsigned> &PossibleStates) const {
+ assert((chkstage < numstages) && "AddInsnClassStages: stage out of range");
+ unsigned thisStage = InsnClass[chkstage];
+
+ DEBUG({
+ dbgsIndent((1 + numstages - chkstage) << 1);
+ dbgs() << "AddInsnClassStages " << chkstage << " (0x"
+ << utohexstr(thisStage) << ") from ";
+ dbgsInsnClass(InsnClass);
+ dbgs() << "\n";
+ });
+
+ //
+ // Iterate over all possible resources used in thisStage.
+ // For ex: for thisStage = 0x11, all resources = {0x01, 0x10}.
+ //
+ for (unsigned int j = 0; j < DFA_MAX_RESOURCES; ++j) {
+ unsigned resourceMask = (0x1 << j);
+ if (resourceMask & thisStage) {
+ unsigned combo = ComboBitToBitsMap[resourceMask];
+ if (combo && ((~prevState & combo) != combo)) {
+ DEBUG(dbgs() << "\tSkipped Add 0x" << utohexstr(prevState)
+ << " - combo op 0x" << utohexstr(resourceMask)
+ << " (0x" << utohexstr(combo) <<") cannot be scheduled\n");
+ continue;
+ }
+ //
+ // For each possible resource used in thisStage, generate the
+ // resource state if that resource was used.
+ //
+ unsigned ResultingResourceState = prevState | resourceMask | combo;
+ DEBUG({
+ dbgsIndent((2 + numstages - chkstage) << 1);
+ dbgs() << "0x" << utohexstr(prevState)
+ << " | 0x" << utohexstr(resourceMask);
+ if (combo)
+ dbgs() << " | 0x" << utohexstr(combo);
+ dbgs() << " = 0x" << utohexstr(ResultingResourceState) << " ";
+ });
+
+ //
+ // If this is the final stage for this class
+ //
+ if (chkstage == 0) {
+ //
+ // Check if the resulting resource state can be accommodated in this
+ // packet.
+ // We compute resource OR prevState (originally started as origState).
+ // If the result of the OR is different than origState, it implies
+ // that there is at least one resource that can be used to schedule
+ // thisStage in the current packet.
+ // Insert ResultingResourceState into PossibleStates only if we haven't
+ // processed ResultingResourceState before.
+ //
+ if (ResultingResourceState != prevState) {
+ if (VisitedResourceStates.count(ResultingResourceState) == 0) {
+ VisitedResourceStates.insert(ResultingResourceState);
+ PossibleStates.insert(ResultingResourceState);
+ DEBUG(dbgs() << "\tResultingResourceState: 0x"
+ << utohexstr(ResultingResourceState) << "\n");
+ } else {
+ DEBUG(dbgs() << "\tSkipped Add - state already seen\n");
+ }
+ } else {
+ DEBUG(dbgs() << "\tSkipped Add - no final resources available\n");
+ }
+ } else {
+ //
+ // If the current resource can be accommodated, check the next
+ // stage in InsnClass for available resources.
+ //
+ if (ResultingResourceState != prevState) {
+ DEBUG(dbgs() << "\n");
+ AddInsnClassStages(InsnClass, ComboBitToBitsMap,
+ chkstage - 1, numstages,
+ ResultingResourceState, origState,
+ VisitedResourceStates, PossibleStates);
+ } else {
+ DEBUG(dbgs() << "\tSkipped Add - no resources available\n");
+ }
+ }
+ }
+ }
+}
+
+//
+// canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass
+// may be a valid transition from this state i.e., can an instruction of type
+// InsnClass be added to the packet represented by this state.
+//
+// Note that this routine is performing conservative checks that can be
+// quickly executed acting as a filter before calling AddInsnClassStages.
+// Any cases allowed through here will be caught later in AddInsnClassStages
+// which performs the more expensive exact check.
+//
+bool State::canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap) const {
+ for (std::set<unsigned>::const_iterator SI = stateInfo.begin();
+ SI != stateInfo.end(); ++SI) {
+ // Check to see if all required resources are available.
+ bool available = true;
+
+ // Inspect each stage independently.
+ // note: This is a conservative check as we aren't checking for
+ // possible resource competition between the stages themselves
+ // The full cross product is examined later in AddInsnClass.
+ for (unsigned i = 0; i < InsnClass.size(); ++i) {
+ unsigned resources = *SI;
+ if ((~resources & InsnClass[i]) == 0) {
+ available = false;
+ break;
+ }
+ // Make sure _all_ resources for a combo function are available.
+ // note: This is a quick conservative check as it won't catch an
+ // unscheduleable combo if this stage is an OR expression
+ // containing a combo.
+ // These cases are caught later in AddInsnClass.
+ unsigned combo = ComboBitToBitsMap[InsnClass[i]];
+ if (combo && ((~resources & combo) != combo)) {
+ DEBUG(dbgs() << "\tSkipped canMaybeAdd 0x" << utohexstr(resources)
+ << " - combo op 0x" << utohexstr(InsnClass[i])
+ << " (0x" << utohexstr(combo) <<") cannot be scheduled\n");
+ available = false;
+ break;
+ }
+ }
+
+ if (available) {
+ return true;
+ }
+ }
+ return false;
+}
+
+const State &DFA::newState() {
+ auto IterPair = states.insert(State());
+ assert(IterPair.second && "State already exists");
+ return *IterPair.first;
+}
+
+int State::currentStateNum = 0;
+
+DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R):
+ TargetName(CodeGenTarget(R).getName()), Records(R) {}
+
+//
+// writeTableAndAPI - Print out a table representing the DFA and the
+// associated API to create a DFA packetizer.
+//
+// Format:
+// DFAStateInputTable[][2] = pairs of <Input, Transition> for all valid
+// transitions.
+// DFAStateEntryTable[i] = Index of the first entry in DFAStateInputTable for
+// the ith state.
+//
+//
+void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName,
+ int numInsnClasses,
+ int maxResources, int numCombos, int maxStages) {
+ unsigned numStates = states.size();
+
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");
+ DEBUG(dbgs() << "writeTableAndAPI\n");
+ DEBUG(dbgs() << "Total states: " << numStates << "\n");
+
+ OS << "namespace llvm {\n";
+
+ OS << "\n// Input format:\n";
+ OS << "#define DFA_MAX_RESTERMS " << DFA_MAX_RESTERMS
+ << "\t// maximum AND'ed resource terms\n";
+ OS << "#define DFA_MAX_RESOURCES " << DFA_MAX_RESOURCES
+ << "\t// maximum resource bits in one term\n";
+
+ OS << "\n// " << TargetName << "DFAStateInputTable[][2] = "
+ << "pairs of <Input, NextState> for all valid\n";
+ OS << "// transitions.\n";
+ OS << "// " << numStates << "\tstates\n";
+ OS << "// " << numInsnClasses << "\tinstruction classes\n";
+ OS << "// " << maxResources << "\tresources max\n";
+ OS << "// " << numCombos << "\tcombo resources\n";
+ OS << "// " << maxStages << "\tstages max\n";
+ OS << "const " << DFA_TBLTYPE << " "
+ << TargetName << "DFAStateInputTable[][2] = {\n";
+
+ // This table provides a map to the beginning of the transitions for State s
+ // in DFAStateInputTable.
+ std::vector<int> StateEntry(numStates+1);
+ static const std::string SentinelEntry = "{-1, -1}";
+
+ // Tracks the total valid transitions encountered so far. It is used
+ // to construct the StateEntry table.
+ int ValidTransitions = 0;
+ DFA::StateSet::iterator SI = states.begin();
+ for (unsigned i = 0; i < numStates; ++i, ++SI) {
+ assert ((SI->stateNum == (int) i) && "Mismatch in state numbers");
+ StateEntry[i] = ValidTransitions;
+ for (State::TransitionMap::iterator
+ II = SI->Transitions.begin(), IE = SI->Transitions.end();
+ II != IE; ++II) {
+ OS << "{0x" << utohexstr(getDFAInsnInput(II->first)) << ", "
+ << II->second->stateNum
+ << "},\t";
+ }
+ ValidTransitions += SI->Transitions.size();
+
+ // If there are no valid transitions from this stage, we need a sentinel
+ // transition.
+ if (ValidTransitions == StateEntry[i]) {
+ OS << SentinelEntry << ",\t";
+ ++ValidTransitions;
+ }
+
+ OS << " // state " << i << ": " << StateEntry[i];
+ if (StateEntry[i] != (ValidTransitions-1)) { // More than one transition.
+ OS << "-" << (ValidTransitions-1);
+ }
+ OS << "\n";
+ }
+
+ // Print out a sentinel entry at the end of the StateInputTable. This is
+ // needed to iterate over StateInputTable in DFAPacketizer::ReadTable()
+ OS << SentinelEntry << "\t";
+ OS << " // state " << numStates << ": " << ValidTransitions;
+ OS << "\n";
+
+ OS << "};\n\n";
+ OS << "// " << TargetName << "DFAStateEntryTable[i] = "
+ << "Index of the first entry in DFAStateInputTable for\n";
+ OS << "// "
+ << "the ith state.\n";
+ OS << "// " << numStates << " states\n";
+ OS << "const unsigned int " << TargetName << "DFAStateEntryTable[] = {\n";
+
+ // Multiply i by 2 since each entry in DFAStateInputTable is a set of
+ // two numbers.
+ unsigned lastState = 0;
+ for (unsigned i = 0; i < numStates; ++i) {
+ if (i && ((i % 10) == 0)) {
+ lastState = i-1;
+ OS << " // states " << (i-10) << ":" << lastState << "\n";
+ }
+ OS << StateEntry[i] << ", ";
+ }
+
+ // Print out the index to the sentinel entry in StateInputTable
+ OS << ValidTransitions << ", ";
+ OS << " // states " << (lastState+1) << ":" << numStates << "\n";
+
+ OS << "};\n";
+ OS << "} // namespace\n";
+
+ //
+ // Emit DFA Packetizer tables if the target is a VLIW machine.
+ //
+ std::string SubTargetClassName = TargetName + "GenSubtargetInfo";
+ OS << "\n" << "#include \"llvm/CodeGen/DFAPacketizer.h\"\n";
+ OS << "namespace llvm {\n";
+ OS << "DFAPacketizer *" << SubTargetClassName << "::"
+ << "createDFAPacketizer(const InstrItineraryData *IID) const {\n"
+ << " return new DFAPacketizer(IID, " << TargetName
+ << "DFAStateInputTable, " << TargetName << "DFAStateEntryTable);\n}\n\n";
+ OS << "} // End llvm namespace \n";
+}
+
+//
+// collectAllFuncUnits - Construct a map of function unit names to bits.
+//
+int DFAPacketizerEmitter::collectAllFuncUnits(
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ int &maxFUs,
+ raw_ostream &OS) {
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");
+ DEBUG(dbgs() << "collectAllFuncUnits");
+ DEBUG(dbgs() << " (" << ProcItinList.size() << " itineraries)\n");
+
+ int totalFUs = 0;
+ // Parse functional units for all the itineraries.
+ for (unsigned i = 0, N = ProcItinList.size(); i < N; ++i) {
+ Record *Proc = ProcItinList[i];
+ std::vector<Record*> FUs = Proc->getValueAsListOfDefs("FU");
+
+ DEBUG(dbgs() << " FU:" << i
+ << " (" << FUs.size() << " FUs) "
+ << Proc->getName());
+
+
+ // Convert macros to bits for each stage.
+ unsigned numFUs = FUs.size();
+ for (unsigned j = 0; j < numFUs; ++j) {
+ assert ((j < DFA_MAX_RESOURCES) &&
+ "Exceeded maximum number of representable resources");
+ unsigned FuncResources = (unsigned) (1U << j);
+ FUNameToBitsMap[FUs[j]->getName()] = FuncResources;
+ DEBUG(dbgs() << " " << FUs[j]->getName()
+ << ":0x" << utohexstr(FuncResources));
+ }
+ if (((int) numFUs) > maxFUs) {
+ maxFUs = numFUs;
+ }
+ totalFUs += numFUs;
+ DEBUG(dbgs() << "\n");
+ }
+ return totalFUs;
+}
+
+//
+// collectAllComboFuncs - Construct a map from a combo function unit bit to
+// the bits of all included functional units.
+//
+int DFAPacketizerEmitter::collectAllComboFuncs(
+ std::vector<Record*> &ComboFuncList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::map<unsigned, unsigned> &ComboBitToBitsMap,
+ raw_ostream &OS) {
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n");
+ DEBUG(dbgs() << "collectAllComboFuncs");
+ DEBUG(dbgs() << " (" << ComboFuncList.size() << " sets)\n");
+
+ int numCombos = 0;
+ for (unsigned i = 0, N = ComboFuncList.size(); i < N; ++i) {
+ Record *Func = ComboFuncList[i];
+ std::vector<Record*> FUs = Func->getValueAsListOfDefs("CFD");
+
+ DEBUG(dbgs() << " CFD:" << i
+ << " (" << FUs.size() << " combo FUs) "
+ << Func->getName() << "\n");
+
+ // Convert macros to bits for each stage.
+ for (unsigned j = 0, N = FUs.size(); j < N; ++j) {
+ assert ((j < DFA_MAX_RESOURCES) &&
+ "Exceeded maximum number of DFA resources");
+ Record *FuncData = FUs[j];
+ Record *ComboFunc = FuncData->getValueAsDef("TheComboFunc");
+ const std::vector<Record*> &FuncList =
+ FuncData->getValueAsListOfDefs("FuncList");
+ const std::string &ComboFuncName = ComboFunc->getName();
+ unsigned ComboBit = FUNameToBitsMap[ComboFuncName];
+ unsigned ComboResources = ComboBit;
+ DEBUG(dbgs() << " combo: " << ComboFuncName
+ << ":0x" << utohexstr(ComboResources) << "\n");
+ for (unsigned k = 0, M = FuncList.size(); k < M; ++k) {
+ std::string FuncName = FuncList[k]->getName();
+ unsigned FuncResources = FUNameToBitsMap[FuncName];
+ DEBUG(dbgs() << " " << FuncName
+ << ":0x" << utohexstr(FuncResources) << "\n");
+ ComboResources |= FuncResources;
+ }
+ ComboBitToBitsMap[ComboBit] = ComboResources;
+ numCombos++;
+ DEBUG(dbgs() << " => combo bits: " << ComboFuncName << ":0x"
+ << utohexstr(ComboBit) << " = 0x"
+ << utohexstr(ComboResources) << "\n");
+ }
+ }
+ return numCombos;
+}
+
+//
+// collectOneInsnClass - Populate allInsnClasses with one instruction class
+//
+int DFAPacketizerEmitter::collectOneInsnClass(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ Record *ItinData,
+ raw_ostream &OS) {
+ const std::vector<Record*> &StageList =
+ ItinData->getValueAsListOfDefs("Stages");
+
+ // The number of stages.
+ unsigned NStages = StageList.size();
+
+ DEBUG(dbgs() << " " << ItinData->getValueAsDef("TheClass")->getName()
+ << "\n");
+
+ std::vector<unsigned> UnitBits;
+
+ // Compute the bitwise or of each unit used in this stage.
+ for (unsigned i = 0; i < NStages; ++i) {
+ const Record *Stage = StageList[i];
+
+ // Get unit list.
+ const std::vector<Record*> &UnitList =
+ Stage->getValueAsListOfDefs("Units");
+
+ DEBUG(dbgs() << " stage:" << i
+ << " [" << UnitList.size() << " units]:");
+ unsigned dbglen = 26; // cursor after stage dbgs
+
+ // Compute the bitwise or of each unit used in this stage.
+ unsigned UnitBitValue = 0;
+ for (unsigned j = 0, M = UnitList.size(); j < M; ++j) {
+ // Conduct bitwise or.
+ std::string UnitName = UnitList[j]->getName();
+ DEBUG(dbgs() << " " << j << ":" << UnitName);
+ dbglen += 3 + UnitName.length();
+ assert(FUNameToBitsMap.count(UnitName));
+ UnitBitValue |= FUNameToBitsMap[UnitName];
+ }
+
+ if (UnitBitValue != 0)
+ UnitBits.push_back(UnitBitValue);
+
+ while (dbglen <= 64) { // line up bits dbgs
+ dbglen += 8;
+ DEBUG(dbgs() << "\t");
+ }
+ DEBUG(dbgs() << " (bits: 0x" << utohexstr(UnitBitValue) << ")\n");
+ }
+
+ if (!UnitBits.empty())
+ allInsnClasses.push_back(UnitBits);
+
+ DEBUG({
+ dbgs() << " ";
+ dbgsInsnClass(UnitBits);
+ dbgs() << "\n";
+ });
+
+ return NStages;
+}
+
+//
+// collectAllInsnClasses - Populate allInsnClasses which is a set of units
+// used in each stage.
+//
+int DFAPacketizerEmitter::collectAllInsnClasses(const std::string &ProcName,
+ std::vector<Record*> &ProcItinList,
+ std::map<std::string, unsigned> &FUNameToBitsMap,
+ std::vector<Record*> &ItinDataList,
+ int &maxStages,
+ raw_ostream &OS) {
+ // Collect all instruction classes.
+ unsigned M = ItinDataList.size();
+
+ int numInsnClasses = 0;
+ DEBUG(dbgs() << "-----------------------------------------------------------------------------\n"
+ << "collectAllInsnClasses "
+ << ProcName
+ << " (" << M << " classes)\n");
+
+ // Collect stages for each instruction class for all itinerary data
+ for (unsigned j = 0; j < M; j++) {
+ Record *ItinData = ItinDataList[j];
+ int NStages = collectOneInsnClass(ProcName, ProcItinList,
+ FUNameToBitsMap, ItinData, OS);
+ if (NStages > maxStages) {
+ maxStages = NStages;
+ }
+ numInsnClasses++;
+ }
+ return numInsnClasses;
+}
+
+//
+// Run the worklist algorithm to generate the DFA.
+//
+void DFAPacketizerEmitter::run(raw_ostream &OS) {
+ // Collect processor iteraries.
+ std::vector<Record*> ProcItinList =
+ Records.getAllDerivedDefinitions("ProcessorItineraries");
+
+ //
+ // Collect the Functional units.
+ //
+ std::map<std::string, unsigned> FUNameToBitsMap;
+ int maxResources = 0;
+ collectAllFuncUnits(ProcItinList,
+ FUNameToBitsMap, maxResources, OS);
+
+ //
+ // Collect the Combo Functional units.
+ //
+ std::map<unsigned, unsigned> ComboBitToBitsMap;
+ std::vector<Record*> ComboFuncList =
+ Records.getAllDerivedDefinitions("ComboFuncUnits");
+ int numCombos = collectAllComboFuncs(ComboFuncList,
+ FUNameToBitsMap, ComboBitToBitsMap, OS);
+
+ //
+ // Collect the itineraries.
+ //
+ int maxStages = 0;
+ int numInsnClasses = 0;
+ for (unsigned i = 0, N = ProcItinList.size(); i < N; i++) {
+ Record *Proc = ProcItinList[i];
+
+ // Get processor itinerary name.
+ const std::string &ProcName = Proc->getName();
+
+ // Skip default.
+ if (ProcName == "NoItineraries")
+ continue;
+
+ // Sanity check for at least one instruction itinerary class.
+ unsigned NItinClasses =
+ Records.getAllDerivedDefinitions("InstrItinClass").size();
+ if (NItinClasses == 0)
+ return;
+
+ // Get itinerary data list.
+ std::vector<Record*> ItinDataList = Proc->getValueAsListOfDefs("IID");
+
+ // Collect all instruction classes
+ numInsnClasses += collectAllInsnClasses(ProcName, ProcItinList,
+ FUNameToBitsMap, ItinDataList, maxStages, OS);
+ }
+
+ //
+ // Run a worklist algorithm to generate the DFA.
+ //
+ DFA D;
+ const State *Initial = &D.newState();
+ Initial->isInitial = true;
+ Initial->stateInfo.insert(0x0);
+ SmallVector<const State*, 32> WorkList;
+ std::map<std::set<unsigned>, const State*> Visited;
+
+ WorkList.push_back(Initial);
+
+ //
+ // Worklist algorithm to create a DFA for processor resource tracking.
+ // C = {set of InsnClasses}
+ // Begin with initial node in worklist. Initial node does not have
+ // any consumed resources,
+ // ResourceState = 0x0
+ // Visited = {}
+ // While worklist != empty
+ // S = first element of worklist
+ // For every instruction class C
+ // if we can accommodate C in S:
+ // S' = state with resource states = {S Union C}
+ // Add a new transition: S x C -> S'
+ // If S' is not in Visited:
+ // Add S' to worklist
+ // Add S' to Visited
+ //
+ while (!WorkList.empty()) {
+ const State *current = WorkList.pop_back_val();
+ DEBUG({
+ dbgs() << "---------------------\n";
+ dbgs() << "Processing state: " << current->stateNum << " - ";
+ dbgsStateInfo(current->stateInfo);
+ dbgs() << "\n";
+ });
+ for (unsigned i = 0; i < allInsnClasses.size(); i++) {
+ std::vector<unsigned> InsnClass = allInsnClasses[i];
+ DEBUG({
+ dbgs() << i << " ";
+ dbgsInsnClass(InsnClass);
+ dbgs() << "\n";
+ });
+
+ std::set<unsigned> NewStateResources;
+ //
+ // If we haven't already created a transition for this input
+ // and the state can accommodate this InsnClass, create a transition.
+ //
+ if (!current->hasTransition(InsnClass) &&
+ current->canMaybeAddInsnClass(InsnClass, ComboBitToBitsMap)) {
+ const State *NewState = nullptr;
+ current->AddInsnClass(InsnClass, ComboBitToBitsMap, NewStateResources);
+ if (NewStateResources.empty()) {
+ DEBUG(dbgs() << " Skipped - no new states generated\n");
+ continue;
+ }
+
+ DEBUG({
+ dbgs() << "\t";
+ dbgsStateInfo(NewStateResources);
+ dbgs() << "\n";
+ });
+
+ //
+ // If we have seen this state before, then do not create a new state.
+ //
+ auto VI = Visited.find(NewStateResources);
+ if (VI != Visited.end()) {
+ NewState = VI->second;
+ DEBUG({
+ dbgs() << "\tFound existing state: " << NewState->stateNum
+ << " - ";
+ dbgsStateInfo(NewState->stateInfo);
+ dbgs() << "\n";
+ });
+ } else {
+ NewState = &D.newState();
+ NewState->stateInfo = NewStateResources;
+ Visited[NewStateResources] = NewState;
+ WorkList.push_back(NewState);
+ DEBUG({
+ dbgs() << "\tAccepted new state: " << NewState->stateNum << " - ";
+ dbgsStateInfo(NewState->stateInfo);
+ dbgs() << "\n";
+ });
+ }
+
+ current->addTransition(InsnClass, NewState);
+ }
+ }
+ }
+
+ // Print out the table.
+ D.writeTableAndAPI(OS, TargetName,
+ numInsnClasses, maxResources, numCombos, maxStages);
+}
+
+namespace llvm {
+
+void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS) {
+ emitSourceFileHeader("Target DFA Packetizer Tables", OS);
+ DFAPacketizerEmitter(RK).run(OS);
+}
+
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
new file mode 100644
index 000000000000..6e1d8dde981c
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
@@ -0,0 +1,148 @@
+//===- DisassemblerEmitter.cpp - Generate a disassembler ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenTarget.h"
+#include "X86DisassemblerTables.h"
+#include "X86RecognizableInstr.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+using namespace llvm;
+using namespace llvm::X86Disassembler;
+
+/// DisassemblerEmitter - Contains disassembler table emitters for various
+/// architectures.
+
+/// X86 Disassembler Emitter
+///
+/// *** IF YOU'RE HERE TO RESOLVE A "Primary decode conflict", LOOK DOWN NEAR
+/// THE END OF THIS COMMENT!
+///
+/// The X86 disassembler emitter is part of the X86 Disassembler, which is
+/// documented in lib/Target/X86/X86Disassembler.h.
+///
+/// The emitter produces the tables that the disassembler uses to translate
+/// instructions. The emitter generates the following tables:
+///
+/// - One table (CONTEXTS_SYM) that contains a mapping of attribute masks to
+/// instruction contexts. Although for each attribute there are cases where
+/// that attribute determines decoding, in the majority of cases decoding is
+/// the same whether or not an attribute is present. For example, a 64-bit
+/// instruction with an OPSIZE prefix and an XS prefix decodes the same way in
+/// all cases as a 64-bit instruction with only OPSIZE set. (The XS prefix
+/// may have effects on its execution, but does not change the instruction
+/// returned.) This allows considerable space savings in other tables.
+/// - Six tables (ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, THREEBYTE3A_SYM,
+/// THREEBYTEA6_SYM, and THREEBYTEA7_SYM contain the hierarchy that the
+/// decoder traverses while decoding an instruction. At the lowest level of
+/// this hierarchy are instruction UIDs, 16-bit integers that can be used to
+/// uniquely identify the instruction and correspond exactly to its position
+/// in the list of CodeGenInstructions for the target.
+/// - One table (INSTRUCTIONS_SYM) contains information about the operands of
+/// each instruction and how to decode them.
+///
+/// During table generation, there may be conflicts between instructions that
+/// occupy the same space in the decode tables. These conflicts are resolved as
+/// follows in setTableFields() (X86DisassemblerTables.cpp)
+///
+/// - If the current context is the native context for one of the instructions
+/// (that is, the attributes specified for it in the LLVM tables specify
+/// precisely the current context), then it has priority.
+/// - If the current context isn't native for either of the instructions, then
+/// the higher-priority context wins (that is, the one that is more specific).
+/// That hierarchy is determined by outranks() (X86DisassemblerTables.cpp)
+/// - If the current context is native for both instructions, then the table
+/// emitter reports a conflict and dies.
+///
+/// *** RESOLUTION FOR "Primary decode conflict"S
+///
+/// If two instructions collide, typically the solution is (in order of
+/// likelihood):
+///
+/// (1) to filter out one of the instructions by editing filter()
+/// (X86RecognizableInstr.cpp). This is the most common resolution, but
+/// check the Intel manuals first to make sure that (2) and (3) are not the
+/// problem.
+/// (2) to fix the tables (X86.td and its subsidiaries) so the opcodes are
+/// accurate. Sometimes they are not.
+/// (3) to fix the tables to reflect the actual context (for example, required
+/// prefixes), and possibly to add a new context by editing
+/// lib/Target/X86/X86DisassemblerDecoderCommon.h. This is unlikely to be
+/// the cause.
+///
+/// DisassemblerEmitter.cpp contains the implementation for the emitter,
+/// which simply pulls out instructions from the CodeGenTarget and pushes them
+/// into X86DisassemblerTables.
+/// X86DisassemblerTables.h contains the interface for the instruction tables,
+/// which manage and emit the structures discussed above.
+/// X86DisassemblerTables.cpp contains the implementation for the instruction
+/// tables.
+/// X86ModRMFilters.h contains filters that can be used to determine which
+/// ModR/M values are valid for a particular instruction. These are used to
+/// populate ModRMDecisions.
+/// X86RecognizableInstr.h contains the interface for a single instruction,
+/// which knows how to translate itself from a CodeGenInstruction and provide
+/// the information necessary for integration into the tables.
+/// X86RecognizableInstr.cpp contains the implementation for a single
+/// instruction.
+
+namespace llvm {
+
+extern void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
+ const std::string &PredicateNamespace,
+ const std::string &GPrefix,
+ const std::string &GPostfix,
+ const std::string &ROK,
+ const std::string &RFail, const std::string &L);
+
+void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
+ CodeGenTarget Target(Records);
+ emitSourceFileHeader(" * " + Target.getName().str() + " Disassembler", OS);
+
+ // X86 uses a custom disassembler.
+ if (Target.getName() == "X86") {
+ DisassemblerTables Tables;
+
+ ArrayRef<const CodeGenInstruction*> numberedInstructions =
+ Target.getInstructionsByEnumValue();
+
+ for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i)
+ RecognizableInstr::processInstr(Tables, *numberedInstructions[i], i);
+
+ if (Tables.hasConflicts()) {
+ PrintError(Target.getTargetRecord()->getLoc(), "Primary decode conflict");
+ return;
+ }
+
+ Tables.emit(OS);
+ return;
+ }
+
+ // ARM and Thumb have a CHECK() macro to deal with DecodeStatuses.
+ if (Target.getName() == "ARM" || Target.getName() == "Thumb" ||
+ Target.getName() == "AArch64" || Target.getName() == "ARM64") {
+ std::string PredicateNamespace = Target.getName();
+ if (PredicateNamespace == "Thumb")
+ PredicateNamespace = "ARM";
+
+ EmitFixedLenDecoder(Records, OS, PredicateNamespace,
+ "if (!Check(S, ", "))",
+ "S", "MCDisassembler::Fail",
+ " MCDisassembler::DecodeStatus S = "
+ "MCDisassembler::Success;\n(void)S;");
+ return;
+ }
+
+ EmitFixedLenDecoder(Records, OS, Target.getName(),
+ "if (", " == MCDisassembler::Fail)",
+ "MCDisassembler::Success", "MCDisassembler::Fail", "");
+}
+
+} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
new file mode 100644
index 000000000000..0e7b0dc09442
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
@@ -0,0 +1,885 @@
+///===- FastISelEmitter.cpp - Generate an instruction selector -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits code for use by the "fast" instruction
+// selection algorithm. See the comments at the top of
+// lib/CodeGen/SelectionDAG/FastISel.cpp for background.
+//
+// This file scans through the target's tablegen instruction-info files
+// and extracts instructions with obvious-looking patterns, and it emits
+// code to look up these instructions by type and operator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenDAGPatterns.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <utility>
+using namespace llvm;
+
+
+/// InstructionMemo - This class holds additional information about an
+/// instruction needed to emit code for it.
+///
+namespace {
+struct InstructionMemo {
+ std::string Name;
+ const CodeGenRegisterClass *RC;
+ std::string SubRegNo;
+ std::vector<std::string>* PhysRegs;
+ std::string PredicateCheck;
+};
+} // End anonymous namespace
+
+/// ImmPredicateSet - This uniques predicates (represented as a string) and
+/// gives them unique (small) integer ID's that start at 0.
+namespace {
+class ImmPredicateSet {
+ DenseMap<TreePattern *, unsigned> ImmIDs;
+ std::vector<TreePredicateFn> PredsByName;
+public:
+
+ unsigned getIDFor(TreePredicateFn Pred) {
+ unsigned &Entry = ImmIDs[Pred.getOrigPatFragRecord()];
+ if (Entry == 0) {
+ PredsByName.push_back(Pred);
+ Entry = PredsByName.size();
+ }
+ return Entry-1;
+ }
+
+ const TreePredicateFn &getPredicate(unsigned i) {
+ assert(i < PredsByName.size());
+ return PredsByName[i];
+ }
+
+ typedef std::vector<TreePredicateFn>::const_iterator iterator;
+ iterator begin() const { return PredsByName.begin(); }
+ iterator end() const { return PredsByName.end(); }
+
+};
+} // End anonymous namespace
+
+/// OperandsSignature - This class holds a description of a list of operand
+/// types. It has utility methods for emitting text based on the operands.
+///
+namespace {
+struct OperandsSignature {
+ class OpKind {
+ enum { OK_Reg, OK_FP, OK_Imm, OK_Invalid = -1 };
+ char Repr;
+ public:
+
+ OpKind() : Repr(OK_Invalid) {}
+
+ bool operator<(OpKind RHS) const { return Repr < RHS.Repr; }
+ bool operator==(OpKind RHS) const { return Repr == RHS.Repr; }
+
+ static OpKind getReg() { OpKind K; K.Repr = OK_Reg; return K; }
+ static OpKind getFP() { OpKind K; K.Repr = OK_FP; return K; }
+ static OpKind getImm(unsigned V) {
+ assert((unsigned)OK_Imm+V < 128 &&
+ "Too many integer predicates for the 'Repr' char");
+ OpKind K; K.Repr = OK_Imm+V; return K;
+ }
+
+ bool isReg() const { return Repr == OK_Reg; }
+ bool isFP() const { return Repr == OK_FP; }
+ bool isImm() const { return Repr >= OK_Imm; }
+
+ unsigned getImmCode() const { assert(isImm()); return Repr-OK_Imm; }
+
+ void printManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,
+ bool StripImmCodes) const {
+ if (isReg())
+ OS << 'r';
+ else if (isFP())
+ OS << 'f';
+ else {
+ OS << 'i';
+ if (!StripImmCodes)
+ if (unsigned Code = getImmCode())
+ OS << "_" << ImmPredicates.getPredicate(Code-1).getFnName();
+ }
+ }
+ };
+
+
+ SmallVector<OpKind, 3> Operands;
+
+ bool operator<(const OperandsSignature &O) const {
+ return Operands < O.Operands;
+ }
+ bool operator==(const OperandsSignature &O) const {
+ return Operands == O.Operands;
+ }
+
+ bool empty() const { return Operands.empty(); }
+
+ bool hasAnyImmediateCodes() const {
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ if (Operands[i].isImm() && Operands[i].getImmCode() != 0)
+ return true;
+ return false;
+ }
+
+ /// getWithoutImmCodes - Return a copy of this with any immediate codes forced
+ /// to zero.
+ OperandsSignature getWithoutImmCodes() const {
+ OperandsSignature Result;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ if (!Operands[i].isImm())
+ Result.Operands.push_back(Operands[i]);
+ else
+ Result.Operands.push_back(OpKind::getImm(0));
+ return Result;
+ }
+
+ void emitImmediatePredicate(raw_ostream &OS, ImmPredicateSet &ImmPredicates) {
+ bool EmittedAnything = false;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (!Operands[i].isImm()) continue;
+
+ unsigned Code = Operands[i].getImmCode();
+ if (Code == 0) continue;
+
+ if (EmittedAnything)
+ OS << " &&\n ";
+
+ TreePredicateFn PredFn = ImmPredicates.getPredicate(Code-1);
+
+ // Emit the type check.
+ OS << "VT == "
+ << getEnumName(PredFn.getOrigPatFragRecord()->getTree(0)->getType(0))
+ << " && ";
+
+
+ OS << PredFn.getFnName() << "(imm" << i <<')';
+ EmittedAnything = true;
+ }
+ }
+
+ /// initialize - Examine the given pattern and initialize the contents
+ /// of the Operands array accordingly. Return true if all the operands
+ /// are supported, false otherwise.
+ ///
+ bool initialize(TreePatternNode *InstPatNode, const CodeGenTarget &Target,
+ MVT::SimpleValueType VT,
+ ImmPredicateSet &ImmediatePredicates,
+ const CodeGenRegisterClass *OrigDstRC) {
+ if (InstPatNode->isLeaf())
+ return false;
+
+ if (InstPatNode->getOperator()->getName() == "imm") {
+ Operands.push_back(OpKind::getImm(0));
+ return true;
+ }
+
+ if (InstPatNode->getOperator()->getName() == "fpimm") {
+ Operands.push_back(OpKind::getFP());
+ return true;
+ }
+
+ const CodeGenRegisterClass *DstRC = nullptr;
+
+ for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) {
+ TreePatternNode *Op = InstPatNode->getChild(i);
+
+ // Handle imm operands specially.
+ if (!Op->isLeaf() && Op->getOperator()->getName() == "imm") {
+ unsigned PredNo = 0;
+ if (!Op->getPredicateFns().empty()) {
+ TreePredicateFn PredFn = Op->getPredicateFns()[0];
+ // If there is more than one predicate weighing in on this operand
+ // then we don't handle it. This doesn't typically happen for
+ // immediates anyway.
+ if (Op->getPredicateFns().size() > 1 ||
+ !PredFn.isImmediatePattern())
+ return false;
+ // Ignore any instruction with 'FastIselShouldIgnore', these are
+ // not needed and just bloat the fast instruction selector. For
+ // example, X86 doesn't need to generate code to match ADD16ri8 since
+ // ADD16ri will do just fine.
+ Record *Rec = PredFn.getOrigPatFragRecord()->getRecord();
+ if (Rec->getValueAsBit("FastIselShouldIgnore"))
+ return false;
+
+ PredNo = ImmediatePredicates.getIDFor(PredFn)+1;
+ }
+
+ // Handle unmatched immediate sizes here.
+ //if (Op->getType(0) != VT)
+ // return false;
+
+ Operands.push_back(OpKind::getImm(PredNo));
+ continue;
+ }
+
+
+ // For now, filter out any operand with a predicate.
+ // For now, filter out any operand with multiple values.
+ if (!Op->getPredicateFns().empty() || Op->getNumTypes() != 1)
+ return false;
+
+ if (!Op->isLeaf()) {
+ if (Op->getOperator()->getName() == "fpimm") {
+ Operands.push_back(OpKind::getFP());
+ continue;
+ }
+ // For now, ignore other non-leaf nodes.
+ return false;
+ }
+
+ assert(Op->hasTypeSet(0) && "Type infererence not done?");
+
+ // For now, all the operands must have the same type (if they aren't
+ // immediates). Note that this causes us to reject variable sized shifts
+ // on X86.
+ if (Op->getType(0) != VT)
+ return false;
+
+ DefInit *OpDI = dyn_cast<DefInit>(Op->getLeafValue());
+ if (!OpDI)
+ return false;
+ Record *OpLeafRec = OpDI->getDef();
+
+ // For now, the only other thing we accept is register operands.
+ const CodeGenRegisterClass *RC = nullptr;
+ if (OpLeafRec->isSubClassOf("RegisterOperand"))
+ OpLeafRec = OpLeafRec->getValueAsDef("RegClass");
+ if (OpLeafRec->isSubClassOf("RegisterClass"))
+ RC = &Target.getRegisterClass(OpLeafRec);
+ else if (OpLeafRec->isSubClassOf("Register"))
+ RC = Target.getRegBank().getRegClassForRegister(OpLeafRec);
+ else if (OpLeafRec->isSubClassOf("ValueType")) {
+ RC = OrigDstRC;
+ } else
+ return false;
+
+ // For now, this needs to be a register class of some sort.
+ if (!RC)
+ return false;
+
+ // For now, all the operands must have the same register class or be
+ // a strict subclass of the destination.
+ if (DstRC) {
+ if (DstRC != RC && !DstRC->hasSubClass(RC))
+ return false;
+ } else
+ DstRC = RC;
+ Operands.push_back(OpKind::getReg());
+ }
+ return true;
+ }
+
+ void PrintParameters(raw_ostream &OS) const {
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (Operands[i].isReg()) {
+ OS << "unsigned Op" << i << ", bool Op" << i << "IsKill";
+ } else if (Operands[i].isImm()) {
+ OS << "uint64_t imm" << i;
+ } else if (Operands[i].isFP()) {
+ OS << "const ConstantFP *f" << i;
+ } else {
+ llvm_unreachable("Unknown operand kind!");
+ }
+ if (i + 1 != e)
+ OS << ", ";
+ }
+ }
+
+ void PrintArguments(raw_ostream &OS,
+ const std::vector<std::string> &PR) const {
+ assert(PR.size() == Operands.size());
+ bool PrintedArg = false;
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (PR[i] != "")
+ // Implicit physical register operand.
+ continue;
+
+ if (PrintedArg)
+ OS << ", ";
+ if (Operands[i].isReg()) {
+ OS << "Op" << i << ", Op" << i << "IsKill";
+ PrintedArg = true;
+ } else if (Operands[i].isImm()) {
+ OS << "imm" << i;
+ PrintedArg = true;
+ } else if (Operands[i].isFP()) {
+ OS << "f" << i;
+ PrintedArg = true;
+ } else {
+ llvm_unreachable("Unknown operand kind!");
+ }
+ }
+ }
+
+ void PrintArguments(raw_ostream &OS) const {
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (Operands[i].isReg()) {
+ OS << "Op" << i << ", Op" << i << "IsKill";
+ } else if (Operands[i].isImm()) {
+ OS << "imm" << i;
+ } else if (Operands[i].isFP()) {
+ OS << "f" << i;
+ } else {
+ llvm_unreachable("Unknown operand kind!");
+ }
+ if (i + 1 != e)
+ OS << ", ";
+ }
+ }
+
+
+ void PrintManglingSuffix(raw_ostream &OS, const std::vector<std::string> &PR,
+ ImmPredicateSet &ImmPredicates,
+ bool StripImmCodes = false) const {
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i) {
+ if (PR[i] != "")
+ // Implicit physical register operand. e.g. Instruction::Mul expect to
+ // select to a binary op. On x86, mul may take a single operand with
+ // the other operand being implicit. We must emit something that looks
+ // like a binary instruction except for the very inner fastEmitInst_*
+ // call.
+ continue;
+ Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);
+ }
+ }
+
+ void PrintManglingSuffix(raw_ostream &OS, ImmPredicateSet &ImmPredicates,
+ bool StripImmCodes = false) const {
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ Operands[i].printManglingSuffix(OS, ImmPredicates, StripImmCodes);
+ }
+};
+} // End anonymous namespace
+
+namespace {
+class FastISelMap {
+ // A multimap is needed instead of a "plain" map because the key is
+ // the instruction's complexity (an int) and they are not unique.
+ typedef std::multimap<int, InstructionMemo> PredMap;
+ typedef std::map<MVT::SimpleValueType, PredMap> RetPredMap;
+ typedef std::map<MVT::SimpleValueType, RetPredMap> TypeRetPredMap;
+ typedef std::map<std::string, TypeRetPredMap> OpcodeTypeRetPredMap;
+ typedef std::map<OperandsSignature, OpcodeTypeRetPredMap>
+ OperandsOpcodeTypeRetPredMap;
+
+ OperandsOpcodeTypeRetPredMap SimplePatterns;
+
+ // This is used to check that there are no duplicate predicates
+ typedef std::multimap<std::string, bool> PredCheckMap;
+ typedef std::map<MVT::SimpleValueType, PredCheckMap> RetPredCheckMap;
+ typedef std::map<MVT::SimpleValueType, RetPredCheckMap> TypeRetPredCheckMap;
+ typedef std::map<std::string, TypeRetPredCheckMap> OpcodeTypeRetPredCheckMap;
+ typedef std::map<OperandsSignature, OpcodeTypeRetPredCheckMap>
+ OperandsOpcodeTypeRetPredCheckMap;
+
+ OperandsOpcodeTypeRetPredCheckMap SimplePatternsCheck;
+
+ std::map<OperandsSignature, std::vector<OperandsSignature> >
+ SignaturesWithConstantForms;
+
+ std::string InstNS;
+ ImmPredicateSet ImmediatePredicates;
+public:
+ explicit FastISelMap(std::string InstNS);
+
+ void collectPatterns(CodeGenDAGPatterns &CGP);
+ void printImmediatePredicates(raw_ostream &OS);
+ void printFunctionDefinitions(raw_ostream &OS);
+private:
+ void emitInstructionCode(raw_ostream &OS,
+ const OperandsSignature &Operands,
+ const PredMap &PM,
+ const std::string &RetVTName);
+};
+} // End anonymous namespace
+
+static std::string getOpcodeName(Record *Op, CodeGenDAGPatterns &CGP) {
+ return CGP.getSDNodeInfo(Op).getEnumName();
+}
+
+static std::string getLegalCName(std::string OpName) {
+ std::string::size_type pos = OpName.find("::");
+ if (pos != std::string::npos)
+ OpName.replace(pos, 2, "_");
+ return OpName;
+}
+
+FastISelMap::FastISelMap(std::string instns) : InstNS(std::move(instns)) {}
+
+static std::string PhyRegForNode(TreePatternNode *Op,
+ const CodeGenTarget &Target) {
+ std::string PhysReg;
+
+ if (!Op->isLeaf())
+ return PhysReg;
+
+ Record *OpLeafRec = cast<DefInit>(Op->getLeafValue())->getDef();
+ if (!OpLeafRec->isSubClassOf("Register"))
+ return PhysReg;
+
+ PhysReg += cast<StringInit>(OpLeafRec->getValue("Namespace")->getValue())
+ ->getValue();
+ PhysReg += "::";
+ PhysReg += Target.getRegBank().getReg(OpLeafRec)->getName();
+ return PhysReg;
+}
+
+void FastISelMap::collectPatterns(CodeGenDAGPatterns &CGP) {
+ const CodeGenTarget &Target = CGP.getTargetInfo();
+
+ // Determine the target's namespace name.
+ InstNS = Target.getInstNamespace() + "::";
+ assert(InstNS.size() > 2 && "Can't determine target-specific namespace!");
+
+ // Scan through all the patterns and record the simple ones.
+ for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
+ E = CGP.ptm_end(); I != E; ++I) {
+ const PatternToMatch &Pattern = *I;
+
+ // For now, just look at Instructions, so that we don't have to worry
+ // about emitting multiple instructions for a pattern.
+ TreePatternNode *Dst = Pattern.getDstPattern();
+ if (Dst->isLeaf()) continue;
+ Record *Op = Dst->getOperator();
+ if (!Op->isSubClassOf("Instruction"))
+ continue;
+ CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op);
+ if (II.Operands.empty())
+ continue;
+
+ // For now, ignore multi-instruction patterns.
+ bool MultiInsts = false;
+ for (unsigned i = 0, e = Dst->getNumChildren(); i != e; ++i) {
+ TreePatternNode *ChildOp = Dst->getChild(i);
+ if (ChildOp->isLeaf())
+ continue;
+ if (ChildOp->getOperator()->isSubClassOf("Instruction")) {
+ MultiInsts = true;
+ break;
+ }
+ }
+ if (MultiInsts)
+ continue;
+
+ // For now, ignore instructions where the first operand is not an
+ // output register.
+ const CodeGenRegisterClass *DstRC = nullptr;
+ std::string SubRegNo;
+ if (Op->getName() != "EXTRACT_SUBREG") {
+ Record *Op0Rec = II.Operands[0].Rec;
+ if (Op0Rec->isSubClassOf("RegisterOperand"))
+ Op0Rec = Op0Rec->getValueAsDef("RegClass");
+ if (!Op0Rec->isSubClassOf("RegisterClass"))
+ continue;
+ DstRC = &Target.getRegisterClass(Op0Rec);
+ if (!DstRC)
+ continue;
+ } else {
+ // If this isn't a leaf, then continue since the register classes are
+ // a bit too complicated for now.
+ if (!Dst->getChild(1)->isLeaf()) continue;
+
+ DefInit *SR = dyn_cast<DefInit>(Dst->getChild(1)->getLeafValue());
+ if (SR)
+ SubRegNo = getQualifiedName(SR->getDef());
+ else
+ SubRegNo = Dst->getChild(1)->getLeafValue()->getAsString();
+ }
+
+ // Inspect the pattern.
+ TreePatternNode *InstPatNode = Pattern.getSrcPattern();
+ if (!InstPatNode) continue;
+ if (InstPatNode->isLeaf()) continue;
+
+ // Ignore multiple result nodes for now.
+ if (InstPatNode->getNumTypes() > 1) continue;
+
+ Record *InstPatOp = InstPatNode->getOperator();
+ std::string OpcodeName = getOpcodeName(InstPatOp, CGP);
+ MVT::SimpleValueType RetVT = MVT::isVoid;
+ if (InstPatNode->getNumTypes()) RetVT = InstPatNode->getType(0);
+ MVT::SimpleValueType VT = RetVT;
+ if (InstPatNode->getNumChildren()) {
+ assert(InstPatNode->getChild(0)->getNumTypes() == 1);
+ VT = InstPatNode->getChild(0)->getType(0);
+ }
+
+ // For now, filter out any instructions with predicates.
+ if (!InstPatNode->getPredicateFns().empty())
+ continue;
+
+ // Check all the operands.
+ OperandsSignature Operands;
+ if (!Operands.initialize(InstPatNode, Target, VT, ImmediatePredicates,
+ DstRC))
+ continue;
+
+ std::vector<std::string>* PhysRegInputs = new std::vector<std::string>();
+ if (InstPatNode->getOperator()->getName() == "imm" ||
+ InstPatNode->getOperator()->getName() == "fpimm")
+ PhysRegInputs->push_back("");
+ else {
+ // Compute the PhysRegs used by the given pattern, and check that
+ // the mapping from the src to dst patterns is simple.
+ bool FoundNonSimplePattern = false;
+ unsigned DstIndex = 0;
+ for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e; ++i) {
+ std::string PhysReg = PhyRegForNode(InstPatNode->getChild(i), Target);
+ if (PhysReg.empty()) {
+ if (DstIndex >= Dst->getNumChildren() ||
+ Dst->getChild(DstIndex)->getName() !=
+ InstPatNode->getChild(i)->getName()) {
+ FoundNonSimplePattern = true;
+ break;
+ }
+ ++DstIndex;
+ }
+
+ PhysRegInputs->push_back(PhysReg);
+ }
+
+ if (Op->getName() != "EXTRACT_SUBREG" && DstIndex < Dst->getNumChildren())
+ FoundNonSimplePattern = true;
+
+ if (FoundNonSimplePattern)
+ continue;
+ }
+
+ // Check if the operands match one of the patterns handled by FastISel.
+ std::string ManglingSuffix;
+ raw_string_ostream SuffixOS(ManglingSuffix);
+ Operands.PrintManglingSuffix(SuffixOS, ImmediatePredicates, true);
+ SuffixOS.flush();
+ if (!StringSwitch<bool>(ManglingSuffix)
+ .Cases("", "r", "rr", "ri", "i", "f", true)
+ .Default(false))
+ continue;
+
+ // Get the predicate that guards this pattern.
+ std::string PredicateCheck = Pattern.getPredicateCheck();
+
+ // Ok, we found a pattern that we can handle. Remember it.
+ InstructionMemo Memo = {
+ Pattern.getDstPattern()->getOperator()->getName(),
+ DstRC,
+ SubRegNo,
+ PhysRegInputs,
+ PredicateCheck
+ };
+
+ int complexity = Pattern.getPatternComplexity(CGP);
+
+ if (SimplePatternsCheck[Operands][OpcodeName][VT]
+ [RetVT].count(PredicateCheck)) {
+ PrintFatalError(Pattern.getSrcRecord()->getLoc(),
+ "Duplicate predicate in FastISel table!");
+ }
+ SimplePatternsCheck[Operands][OpcodeName][VT][RetVT].insert(
+ std::make_pair(PredicateCheck, true));
+
+ // Note: Instructions with the same complexity will appear in the order
+ // that they are encountered.
+ SimplePatterns[Operands][OpcodeName][VT][RetVT].insert(
+ std::make_pair(complexity, Memo));
+
+ // If any of the operands were immediates with predicates on them, strip
+ // them down to a signature that doesn't have predicates so that we can
+ // associate them with the stripped predicate version.
+ if (Operands.hasAnyImmediateCodes()) {
+ SignaturesWithConstantForms[Operands.getWithoutImmCodes()]
+ .push_back(Operands);
+ }
+ }
+}
+
+void FastISelMap::printImmediatePredicates(raw_ostream &OS) {
+ if (ImmediatePredicates.begin() == ImmediatePredicates.end())
+ return;
+
+ OS << "\n// FastEmit Immediate Predicate functions.\n";
+ for (ImmPredicateSet::iterator I = ImmediatePredicates.begin(),
+ E = ImmediatePredicates.end(); I != E; ++I) {
+ OS << "static bool " << I->getFnName() << "(int64_t Imm) {\n";
+ OS << I->getImmediatePredicateCode() << "\n}\n";
+ }
+
+ OS << "\n\n";
+}
+
+void FastISelMap::emitInstructionCode(raw_ostream &OS,
+ const OperandsSignature &Operands,
+ const PredMap &PM,
+ const std::string &RetVTName) {
+ // Emit code for each possible instruction. There may be
+ // multiple if there are subtarget concerns. A reverse iterator
+ // is used to produce the ones with highest complexity first.
+
+ bool OneHadNoPredicate = false;
+ for (PredMap::const_reverse_iterator PI = PM.rbegin(), PE = PM.rend();
+ PI != PE; ++PI) {
+ const InstructionMemo &Memo = PI->second;
+ std::string PredicateCheck = Memo.PredicateCheck;
+
+ if (PredicateCheck.empty()) {
+ assert(!OneHadNoPredicate &&
+ "Multiple instructions match and more than one had "
+ "no predicate!");
+ OneHadNoPredicate = true;
+ } else {
+ if (OneHadNoPredicate) {
+ PrintFatalError("Multiple instructions match and one with no "
+ "predicate came before one with a predicate! "
+ "name:" + Memo.Name + " predicate: " + PredicateCheck);
+ }
+ OS << " if (" + PredicateCheck + ") {\n";
+ OS << " ";
+ }
+
+ for (unsigned i = 0; i < Memo.PhysRegs->size(); ++i) {
+ if ((*Memo.PhysRegs)[i] != "")
+ OS << " BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, "
+ << "TII.get(TargetOpcode::COPY), "
+ << (*Memo.PhysRegs)[i] << ").addReg(Op" << i << ");\n";
+ }
+
+ OS << " return fastEmitInst_";
+ if (Memo.SubRegNo.empty()) {
+ Operands.PrintManglingSuffix(OS, *Memo.PhysRegs,
+ ImmediatePredicates, true);
+ OS << "(" << InstNS << Memo.Name << ", ";
+ OS << "&" << InstNS << Memo.RC->getName() << "RegClass";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintArguments(OS, *Memo.PhysRegs);
+ OS << ");\n";
+ } else {
+ OS << "extractsubreg(" << RetVTName
+ << ", Op0, Op0IsKill, " << Memo.SubRegNo << ");\n";
+ }
+
+ if (!PredicateCheck.empty()) {
+ OS << " }\n";
+ }
+ }
+ // Return 0 if all of the possibilities had predicates but none
+ // were satisfied.
+ if (!OneHadNoPredicate)
+ OS << " return 0;\n";
+ OS << "}\n";
+ OS << "\n";
+}
+
+
+void FastISelMap::printFunctionDefinitions(raw_ostream &OS) {
+ // Now emit code for all the patterns that we collected.
+ for (OperandsOpcodeTypeRetPredMap::const_iterator OI = SimplePatterns.begin(),
+ OE = SimplePatterns.end(); OI != OE; ++OI) {
+ const OperandsSignature &Operands = OI->first;
+ const OpcodeTypeRetPredMap &OTM = OI->second;
+
+ for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end();
+ I != E; ++I) {
+ const std::string &Opcode = I->first;
+ const TypeRetPredMap &TM = I->second;
+
+ OS << "// FastEmit functions for " << Opcode << ".\n";
+ OS << "\n";
+
+ // Emit one function for each opcode,type pair.
+ for (TypeRetPredMap::const_iterator TI = TM.begin(), TE = TM.end();
+ TI != TE; ++TI) {
+ MVT::SimpleValueType VT = TI->first;
+ const RetPredMap &RM = TI->second;
+ if (RM.size() != 1) {
+ for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end();
+ RI != RE; ++RI) {
+ MVT::SimpleValueType RetVT = RI->first;
+ const PredMap &PM = RI->second;
+
+ OS << "unsigned fastEmit_"
+ << getLegalCName(Opcode)
+ << "_" << getLegalCName(getName(VT))
+ << "_" << getLegalCName(getName(RetVT)) << "_";
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
+ OS << "(";
+ Operands.PrintParameters(OS);
+ OS << ") {\n";
+
+ emitInstructionCode(OS, Operands, PM, getName(RetVT));
+ }
+
+ // Emit one function for the type that demultiplexes on return type.
+ OS << "unsigned fastEmit_"
+ << getLegalCName(Opcode) << "_"
+ << getLegalCName(getName(VT)) << "_";
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
+ OS << "(MVT RetVT";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintParameters(OS);
+ OS << ") {\nswitch (RetVT.SimpleTy) {\n";
+ for (RetPredMap::const_iterator RI = RM.begin(), RE = RM.end();
+ RI != RE; ++RI) {
+ MVT::SimpleValueType RetVT = RI->first;
+ OS << " case " << getName(RetVT) << ": return fastEmit_"
+ << getLegalCName(Opcode) << "_" << getLegalCName(getName(VT))
+ << "_" << getLegalCName(getName(RetVT)) << "_";
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
+ OS << "(";
+ Operands.PrintArguments(OS);
+ OS << ");\n";
+ }
+ OS << " default: return 0;\n}\n}\n\n";
+
+ } else {
+ // Non-variadic return type.
+ OS << "unsigned fastEmit_"
+ << getLegalCName(Opcode) << "_"
+ << getLegalCName(getName(VT)) << "_";
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
+ OS << "(MVT RetVT";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintParameters(OS);
+ OS << ") {\n";
+
+ OS << " if (RetVT.SimpleTy != " << getName(RM.begin()->first)
+ << ")\n return 0;\n";
+
+ const PredMap &PM = RM.begin()->second;
+
+ emitInstructionCode(OS, Operands, PM, "RetVT");
+ }
+ }
+
+ // Emit one function for the opcode that demultiplexes based on the type.
+ OS << "unsigned fastEmit_"
+ << getLegalCName(Opcode) << "_";
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
+ OS << "(MVT VT, MVT RetVT";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintParameters(OS);
+ OS << ") {\n";
+ OS << " switch (VT.SimpleTy) {\n";
+ for (TypeRetPredMap::const_iterator TI = TM.begin(), TE = TM.end();
+ TI != TE; ++TI) {
+ MVT::SimpleValueType VT = TI->first;
+ std::string TypeName = getName(VT);
+ OS << " case " << TypeName << ": return fastEmit_"
+ << getLegalCName(Opcode) << "_" << getLegalCName(TypeName) << "_";
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
+ OS << "(RetVT";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintArguments(OS);
+ OS << ");\n";
+ }
+ OS << " default: return 0;\n";
+ OS << " }\n";
+ OS << "}\n";
+ OS << "\n";
+ }
+
+ OS << "// Top-level FastEmit function.\n";
+ OS << "\n";
+
+ // Emit one function for the operand signature that demultiplexes based
+ // on opcode and type.
+ OS << "unsigned fastEmit_";
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
+ OS << "(MVT VT, MVT RetVT, unsigned Opcode";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintParameters(OS);
+ OS << ") ";
+ if (!Operands.hasAnyImmediateCodes())
+ OS << "override ";
+ OS << "{\n";
+
+ // If there are any forms of this signature available that operate on
+ // constrained forms of the immediate (e.g., 32-bit sext immediate in a
+ // 64-bit operand), check them first.
+
+ std::map<OperandsSignature, std::vector<OperandsSignature> >::iterator MI
+ = SignaturesWithConstantForms.find(Operands);
+ if (MI != SignaturesWithConstantForms.end()) {
+ // Unique any duplicates out of the list.
+ std::sort(MI->second.begin(), MI->second.end());
+ MI->second.erase(std::unique(MI->second.begin(), MI->second.end()),
+ MI->second.end());
+
+ // Check each in order it was seen. It would be nice to have a good
+ // relative ordering between them, but we're not going for optimality
+ // here.
+ for (unsigned i = 0, e = MI->second.size(); i != e; ++i) {
+ OS << " if (";
+ MI->second[i].emitImmediatePredicate(OS, ImmediatePredicates);
+ OS << ")\n if (unsigned Reg = fastEmit_";
+ MI->second[i].PrintManglingSuffix(OS, ImmediatePredicates);
+ OS << "(VT, RetVT, Opcode";
+ if (!MI->second[i].empty())
+ OS << ", ";
+ MI->second[i].PrintArguments(OS);
+ OS << "))\n return Reg;\n\n";
+ }
+
+ // Done with this, remove it.
+ SignaturesWithConstantForms.erase(MI);
+ }
+
+ OS << " switch (Opcode) {\n";
+ for (OpcodeTypeRetPredMap::const_iterator I = OTM.begin(), E = OTM.end();
+ I != E; ++I) {
+ const std::string &Opcode = I->first;
+
+ OS << " case " << Opcode << ": return fastEmit_"
+ << getLegalCName(Opcode) << "_";
+ Operands.PrintManglingSuffix(OS, ImmediatePredicates);
+ OS << "(VT, RetVT";
+ if (!Operands.empty())
+ OS << ", ";
+ Operands.PrintArguments(OS);
+ OS << ");\n";
+ }
+ OS << " default: return 0;\n";
+ OS << " }\n";
+ OS << "}\n";
+ OS << "\n";
+ }
+
+ // TODO: SignaturesWithConstantForms should be empty here.
+}
+
+namespace llvm {
+
+void EmitFastISel(RecordKeeper &RK, raw_ostream &OS) {
+ CodeGenDAGPatterns CGP(RK);
+ const CodeGenTarget &Target = CGP.getTargetInfo();
+ emitSourceFileHeader("\"Fast\" Instruction Selector for the " +
+ Target.getName().str() + " target", OS);
+
+ // Determine the target's namespace name.
+ std::string InstNS = Target.getInstNamespace() + "::";
+ assert(InstNS.size() > 2 && "Can't determine target-specific namespace!");
+
+ FastISelMap F(InstNS);
+ F.collectPatterns(CGP);
+ F.printImmediatePredicates(OS);
+ F.printFunctionDefinitions(OS);
+}
+
+} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
new file mode 100644
index 000000000000..e1aaeccb08d0
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -0,0 +1,2325 @@
+//===------------ FixedLenDecoderEmitter.cpp - Decoder Generator ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// It contains the tablegen backend that emits the decoder functions for
+// targets with fixed length instruction set.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenInstruction.h"
+#include "CodeGenTarget.h"
+#include "llvm/ADT/APInt.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/CachedHashString.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCFixedLenDisassembler.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <map>
+#include <memory>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "decoder-emitter"
+
+namespace {
+
+struct EncodingField {
+ unsigned Base, Width, Offset;
+ EncodingField(unsigned B, unsigned W, unsigned O)
+ : Base(B), Width(W), Offset(O) { }
+};
+
+struct OperandInfo {
+ std::vector<EncodingField> Fields;
+ std::string Decoder;
+ bool HasCompleteDecoder;
+
+ OperandInfo(std::string D, bool HCD)
+ : Decoder(std::move(D)), HasCompleteDecoder(HCD) {}
+
+ void addField(unsigned Base, unsigned Width, unsigned Offset) {
+ Fields.push_back(EncodingField(Base, Width, Offset));
+ }
+
+ unsigned numFields() const { return Fields.size(); }
+
+ typedef std::vector<EncodingField>::const_iterator const_iterator;
+
+ const_iterator begin() const { return Fields.begin(); }
+ const_iterator end() const { return Fields.end(); }
+};
+
+typedef std::vector<uint8_t> DecoderTable;
+typedef uint32_t DecoderFixup;
+typedef std::vector<DecoderFixup> FixupList;
+typedef std::vector<FixupList> FixupScopeList;
+typedef SmallSetVector<CachedHashString, 16> PredicateSet;
+typedef SmallSetVector<CachedHashString, 16> DecoderSet;
+struct DecoderTableInfo {
+ DecoderTable Table;
+ FixupScopeList FixupStack;
+ PredicateSet Predicates;
+ DecoderSet Decoders;
+};
+
+class FixedLenDecoderEmitter {
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions;
+
+public:
+ // Defaults preserved here for documentation, even though they aren't
+ // strictly necessary given the way that this is currently being called.
+ FixedLenDecoderEmitter(RecordKeeper &R, std::string PredicateNamespace,
+ std::string GPrefix = "if (",
+ std::string GPostfix = " == MCDisassembler::Fail)",
+ std::string ROK = "MCDisassembler::Success",
+ std::string RFail = "MCDisassembler::Fail",
+ std::string L = "")
+ : Target(R), PredicateNamespace(std::move(PredicateNamespace)),
+ GuardPrefix(std::move(GPrefix)), GuardPostfix(std::move(GPostfix)),
+ ReturnOK(std::move(ROK)), ReturnFail(std::move(RFail)),
+ Locals(std::move(L)) {}
+
+ // Emit the decoder state machine table.
+ void emitTable(formatted_raw_ostream &o, DecoderTable &Table,
+ unsigned Indentation, unsigned BitWidth,
+ StringRef Namespace) const;
+ void emitPredicateFunction(formatted_raw_ostream &OS,
+ PredicateSet &Predicates,
+ unsigned Indentation) const;
+ void emitDecoderFunction(formatted_raw_ostream &OS,
+ DecoderSet &Decoders,
+ unsigned Indentation) const;
+
+ // run - Output the code emitter
+ void run(raw_ostream &o);
+
+private:
+ CodeGenTarget Target;
+
+public:
+ std::string PredicateNamespace;
+ std::string GuardPrefix, GuardPostfix;
+ std::string ReturnOK, ReturnFail;
+ std::string Locals;
+};
+
+} // end anonymous namespace
+
+// The set (BIT_TRUE, BIT_FALSE, BIT_UNSET) represents a ternary logic system
+// for a bit value.
+//
+// BIT_UNFILTERED is used as the init value for a filter position. It is used
+// only for filter processings.
+typedef enum {
+ BIT_TRUE, // '1'
+ BIT_FALSE, // '0'
+ BIT_UNSET, // '?'
+ BIT_UNFILTERED // unfiltered
+} bit_value_t;
+
+static bool ValueSet(bit_value_t V) {
+ return (V == BIT_TRUE || V == BIT_FALSE);
+}
+
+static bool ValueNotSet(bit_value_t V) {
+ return (V == BIT_UNSET);
+}
+
+static int Value(bit_value_t V) {
+ return ValueNotSet(V) ? -1 : (V == BIT_FALSE ? 0 : 1);
+}
+
+static bit_value_t bitFromBits(const BitsInit &bits, unsigned index) {
+ if (BitInit *bit = dyn_cast<BitInit>(bits.getBit(index)))
+ return bit->getValue() ? BIT_TRUE : BIT_FALSE;
+
+ // The bit is uninitialized.
+ return BIT_UNSET;
+}
+
+// Prints the bit value for each position.
+static void dumpBits(raw_ostream &o, const BitsInit &bits) {
+ for (unsigned index = bits.getNumBits(); index > 0; --index) {
+ switch (bitFromBits(bits, index - 1)) {
+ case BIT_TRUE:
+ o << "1";
+ break;
+ case BIT_FALSE:
+ o << "0";
+ break;
+ case BIT_UNSET:
+ o << "_";
+ break;
+ default:
+ llvm_unreachable("unexpected return value from bitFromBits");
+ }
+ }
+}
+
+static BitsInit &getBitsField(const Record &def, StringRef str) {
+ BitsInit *bits = def.getValueAsBitsInit(str);
+ return *bits;
+}
+
+// Representation of the instruction to work on.
+typedef std::vector<bit_value_t> insn_t;
+
+namespace {
+
+class FilterChooser;
+
+/// Filter - Filter works with FilterChooser to produce the decoding tree for
+/// the ISA.
+///
+/// It is useful to think of a Filter as governing the switch stmts of the
+/// decoding tree in a certain level. Each case stmt delegates to an inferior
+/// FilterChooser to decide what further decoding logic to employ, or in another
+/// words, what other remaining bits to look at. The FilterChooser eventually
+/// chooses a best Filter to do its job.
+///
+/// This recursive scheme ends when the number of Opcodes assigned to the
+/// FilterChooser becomes 1 or if there is a conflict. A conflict happens when
+/// the Filter/FilterChooser combo does not know how to distinguish among the
+/// Opcodes assigned.
+///
+/// An example of a conflict is
+///
+/// Conflict:
+/// 111101000.00........00010000....
+/// 111101000.00........0001........
+/// 1111010...00........0001........
+/// 1111010...00....................
+/// 1111010.........................
+/// 1111............................
+/// ................................
+/// VST4q8a 111101000_00________00010000____
+/// VST4q8b 111101000_00________00010000____
+///
+/// The Debug output shows the path that the decoding tree follows to reach the
+/// the conclusion that there is a conflict. VST4q8a is a vst4 to double-spaced
+/// even registers, while VST4q8b is a vst4 to double-spaced odd registers.
+///
+/// The encoding info in the .td files does not specify this meta information,
+/// which could have been used by the decoder to resolve the conflict. The
+/// decoder could try to decode the even/odd register numbering and assign to
+/// VST4q8a or VST4q8b, but for the time being, the decoder chooses the "a"
+/// version and return the Opcode since the two have the same Asm format string.
+class Filter {
+protected:
+ const FilterChooser *Owner;// points to the FilterChooser who owns this filter
+ unsigned StartBit; // the starting bit position
+ unsigned NumBits; // number of bits to filter
+ bool Mixed; // a mixed region contains both set and unset bits
+
+ // Map of well-known segment value to the set of uid's with that value.
+ std::map<uint64_t, std::vector<unsigned>> FilteredInstructions;
+
+ // Set of uid's with non-constant segment values.
+ std::vector<unsigned> VariableInstructions;
+
+ // Map of well-known segment value to its delegate.
+ std::map<unsigned, std::unique_ptr<const FilterChooser>> FilterChooserMap;
+
+ // Number of instructions which fall under FilteredInstructions category.
+ unsigned NumFiltered;
+
+ // Keeps track of the last opcode in the filtered bucket.
+ unsigned LastOpcFiltered;
+
+public:
+ Filter(Filter &&f);
+ Filter(FilterChooser &owner, unsigned startBit, unsigned numBits, bool mixed);
+
+ ~Filter() = default;
+
+ unsigned getNumFiltered() const { return NumFiltered; }
+
+ unsigned getSingletonOpc() const {
+ assert(NumFiltered == 1);
+ return LastOpcFiltered;
+ }
+
+ // Return the filter chooser for the group of instructions without constant
+ // segment values.
+ const FilterChooser &getVariableFC() const {
+ assert(NumFiltered == 1);
+ assert(FilterChooserMap.size() == 1);
+ return *(FilterChooserMap.find((unsigned)-1)->second);
+ }
+
+ // Divides the decoding task into sub tasks and delegates them to the
+ // inferior FilterChooser's.
+ //
+ // A special case arises when there's only one entry in the filtered
+ // instructions. In order to unambiguously decode the singleton, we need to
+ // match the remaining undecoded encoding bits against the singleton.
+ void recurse();
+
+ // Emit table entries to decode instructions given a segment or segments of
+ // bits.
+ void emitTableEntry(DecoderTableInfo &TableInfo) const;
+
+ // Returns the number of fanout produced by the filter. More fanout implies
+ // the filter distinguishes more categories of instructions.
+ unsigned usefulness() const;
+}; // end class Filter
+
+} // end anonymous namespace
+
+// These are states of our finite state machines used in FilterChooser's
+// filterProcessor() which produces the filter candidates to use.
+typedef enum {
+ ATTR_NONE,
+ ATTR_FILTERED,
+ ATTR_ALL_SET,
+ ATTR_ALL_UNSET,
+ ATTR_MIXED
+} bitAttr_t;
+
+/// FilterChooser - FilterChooser chooses the best filter among a set of Filters
+/// in order to perform the decoding of instructions at the current level.
+///
+/// Decoding proceeds from the top down. Based on the well-known encoding bits
+/// of instructions available, FilterChooser builds up the possible Filters that
+/// can further the task of decoding by distinguishing among the remaining
+/// candidate instructions.
+///
+/// Once a filter has been chosen, it is called upon to divide the decoding task
+/// into sub-tasks and delegates them to its inferior FilterChoosers for further
+/// processings.
+///
+/// It is useful to think of a Filter as governing the switch stmts of the
+/// decoding tree. And each case is delegated to an inferior FilterChooser to
+/// decide what further remaining bits to look at.
+namespace {
+
+class FilterChooser {
+protected:
+ friend class Filter;
+
+ // Vector of codegen instructions to choose our filter.
+ ArrayRef<const CodeGenInstruction *> AllInstructions;
+
+ // Vector of uid's for this filter chooser to work on.
+ const std::vector<unsigned> &Opcodes;
+
+ // Lookup table for the operand decoding of instructions.
+ const std::map<unsigned, std::vector<OperandInfo>> &Operands;
+
+ // Vector of candidate filters.
+ std::vector<Filter> Filters;
+
+ // Array of bit values passed down from our parent.
+ // Set to all BIT_UNFILTERED's for Parent == NULL.
+ std::vector<bit_value_t> FilterBitValues;
+
+ // Links to the FilterChooser above us in the decoding tree.
+ const FilterChooser *Parent;
+
+ // Index of the best filter from Filters.
+ int BestIndex;
+
+ // Width of instructions
+ unsigned BitWidth;
+
+ // Parent emitter
+ const FixedLenDecoderEmitter *Emitter;
+
+public:
+ FilterChooser(ArrayRef<const CodeGenInstruction *> Insts,
+ const std::vector<unsigned> &IDs,
+ const std::map<unsigned, std::vector<OperandInfo>> &Ops,
+ unsigned BW,
+ const FixedLenDecoderEmitter *E)
+ : AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
+ FilterBitValues(BW, BIT_UNFILTERED), Parent(nullptr), BestIndex(-1),
+ BitWidth(BW), Emitter(E) {
+ doFilter();
+ }
+
+ FilterChooser(ArrayRef<const CodeGenInstruction *> Insts,
+ const std::vector<unsigned> &IDs,
+ const std::map<unsigned, std::vector<OperandInfo>> &Ops,
+ const std::vector<bit_value_t> &ParentFilterBitValues,
+ const FilterChooser &parent)
+ : AllInstructions(Insts), Opcodes(IDs), Operands(Ops),
+ FilterBitValues(ParentFilterBitValues), Parent(&parent), BestIndex(-1),
+ BitWidth(parent.BitWidth), Emitter(parent.Emitter) {
+ doFilter();
+ }
+
+ FilterChooser(const FilterChooser &) = delete;
+ void operator=(const FilterChooser &) = delete;
+
+ unsigned getBitWidth() const { return BitWidth; }
+
+protected:
+ // Populates the insn given the uid.
+ void insnWithID(insn_t &Insn, unsigned Opcode) const {
+ BitsInit &Bits = getBitsField(*AllInstructions[Opcode]->TheDef, "Inst");
+
+ // We may have a SoftFail bitmask, which specifies a mask where an encoding
+ // may differ from the value in "Inst" and yet still be valid, but the
+ // disassembler should return SoftFail instead of Success.
+ //
+ // This is used for marking UNPREDICTABLE instructions in the ARM world.
+ BitsInit *SFBits =
+ AllInstructions[Opcode]->TheDef->getValueAsBitsInit("SoftFail");
+
+ for (unsigned i = 0; i < BitWidth; ++i) {
+ if (SFBits && bitFromBits(*SFBits, i) == BIT_TRUE)
+ Insn.push_back(BIT_UNSET);
+ else
+ Insn.push_back(bitFromBits(Bits, i));
+ }
+ }
+
+ // Returns the record name.
+ const StringRef nameWithID(unsigned Opcode) const {
+ return AllInstructions[Opcode]->TheDef->getName();
+ }
+
+ // Populates the field of the insn given the start position and the number of
+ // consecutive bits to scan for.
+ //
+ // Returns false if there exists any uninitialized bit value in the range.
+ // Returns true, otherwise.
+ bool fieldFromInsn(uint64_t &Field, insn_t &Insn, unsigned StartBit,
+ unsigned NumBits) const;
+
+ /// dumpFilterArray - dumpFilterArray prints out debugging info for the given
+ /// filter array as a series of chars.
+ void dumpFilterArray(raw_ostream &o,
+ const std::vector<bit_value_t> & filter) const;
+
+ /// dumpStack - dumpStack traverses the filter chooser chain and calls
+ /// dumpFilterArray on each filter chooser up to the top level one.
+ void dumpStack(raw_ostream &o, const char *prefix) const;
+
+ Filter &bestFilter() {
+ assert(BestIndex != -1 && "BestIndex not set");
+ return Filters[BestIndex];
+ }
+
+ bool PositionFiltered(unsigned i) const {
+ return ValueSet(FilterBitValues[i]);
+ }
+
+ // Calculates the island(s) needed to decode the instruction.
+ // This returns a lit of undecoded bits of an instructions, for example,
+ // Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
+ // decoded bits in order to verify that the instruction matches the Opcode.
+ unsigned getIslands(std::vector<unsigned> &StartBits,
+ std::vector<unsigned> &EndBits,
+ std::vector<uint64_t> &FieldVals,
+ const insn_t &Insn) const;
+
+ // Emits code to check the Predicates member of an instruction are true.
+ // Returns true if predicate matches were emitted, false otherwise.
+ bool emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
+ unsigned Opc) const;
+
+ bool doesOpcodeNeedPredicate(unsigned Opc) const;
+ unsigned getPredicateIndex(DecoderTableInfo &TableInfo, StringRef P) const;
+ void emitPredicateTableEntry(DecoderTableInfo &TableInfo,
+ unsigned Opc) const;
+
+ void emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
+ unsigned Opc) const;
+
+ // Emits table entries to decode the singleton.
+ void emitSingletonTableEntry(DecoderTableInfo &TableInfo,
+ unsigned Opc) const;
+
+ // Emits code to decode the singleton, and then to decode the rest.
+ void emitSingletonTableEntry(DecoderTableInfo &TableInfo,
+ const Filter &Best) const;
+
+ void emitBinaryParser(raw_ostream &o, unsigned &Indentation,
+ const OperandInfo &OpInfo,
+ bool &OpHasCompleteDecoder) const;
+
+ void emitDecoder(raw_ostream &OS, unsigned Indentation, unsigned Opc,
+ bool &HasCompleteDecoder) const;
+ unsigned getDecoderIndex(DecoderSet &Decoders, unsigned Opc,
+ bool &HasCompleteDecoder) const;
+
+ // Assign a single filter and run with it.
+ void runSingleFilter(unsigned startBit, unsigned numBit, bool mixed);
+
+ // reportRegion is a helper function for filterProcessor to mark a region as
+ // eligible for use as a filter region.
+ void reportRegion(bitAttr_t RA, unsigned StartBit, unsigned BitIndex,
+ bool AllowMixed);
+
+ // FilterProcessor scans the well-known encoding bits of the instructions and
+ // builds up a list of candidate filters. It chooses the best filter and
+ // recursively descends down the decoding tree.
+ bool filterProcessor(bool AllowMixed, bool Greedy = true);
+
+ // Decides on the best configuration of filter(s) to use in order to decode
+ // the instructions. A conflict of instructions may occur, in which case we
+ // dump the conflict set to the standard error.
+ void doFilter();
+
+public:
+ // emitTableEntries - Emit state machine entries to decode our share of
+ // instructions.
+ void emitTableEntries(DecoderTableInfo &TableInfo) const;
+};
+
+} // end anonymous namespace
+
+///////////////////////////
+// //
+// Filter Implementation //
+// //
+///////////////////////////
+
+Filter::Filter(Filter &&f)
+ : Owner(f.Owner), StartBit(f.StartBit), NumBits(f.NumBits), Mixed(f.Mixed),
+ FilteredInstructions(std::move(f.FilteredInstructions)),
+ VariableInstructions(std::move(f.VariableInstructions)),
+ FilterChooserMap(std::move(f.FilterChooserMap)), NumFiltered(f.NumFiltered),
+ LastOpcFiltered(f.LastOpcFiltered) {
+}
+
+Filter::Filter(FilterChooser &owner, unsigned startBit, unsigned numBits,
+ bool mixed)
+ : Owner(&owner), StartBit(startBit), NumBits(numBits), Mixed(mixed) {
+ assert(StartBit + NumBits - 1 < Owner->BitWidth);
+
+ NumFiltered = 0;
+ LastOpcFiltered = 0;
+
+ for (unsigned i = 0, e = Owner->Opcodes.size(); i != e; ++i) {
+ insn_t Insn;
+
+ // Populates the insn given the uid.
+ Owner->insnWithID(Insn, Owner->Opcodes[i]);
+
+ uint64_t Field;
+ // Scans the segment for possibly well-specified encoding bits.
+ bool ok = Owner->fieldFromInsn(Field, Insn, StartBit, NumBits);
+
+ if (ok) {
+ // The encoding bits are well-known. Lets add the uid of the
+ // instruction into the bucket keyed off the constant field value.
+ LastOpcFiltered = Owner->Opcodes[i];
+ FilteredInstructions[Field].push_back(LastOpcFiltered);
+ ++NumFiltered;
+ } else {
+ // Some of the encoding bit(s) are unspecified. This contributes to
+ // one additional member of "Variable" instructions.
+ VariableInstructions.push_back(Owner->Opcodes[i]);
+ }
+ }
+
+ assert((FilteredInstructions.size() + VariableInstructions.size() > 0)
+ && "Filter returns no instruction categories");
+}
+
+// Divides the decoding task into sub tasks and delegates them to the
+// inferior FilterChooser's.
+//
+// A special case arises when there's only one entry in the filtered
+// instructions. In order to unambiguously decode the singleton, we need to
+// match the remaining undecoded encoding bits against the singleton.
+void Filter::recurse() {
+ // Starts by inheriting our parent filter chooser's filter bit values.
+ std::vector<bit_value_t> BitValueArray(Owner->FilterBitValues);
+
+ if (!VariableInstructions.empty()) {
+ // Conservatively marks each segment position as BIT_UNSET.
+ for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex)
+ BitValueArray[StartBit + bitIndex] = BIT_UNSET;
+
+ // Delegates to an inferior filter chooser for further processing on this
+ // group of instructions whose segment values are variable.
+ FilterChooserMap.insert(
+ std::make_pair(-1U, llvm::make_unique<FilterChooser>(
+ Owner->AllInstructions, VariableInstructions,
+ Owner->Operands, BitValueArray, *Owner)));
+ }
+
+ // No need to recurse for a singleton filtered instruction.
+ // See also Filter::emit*().
+ if (getNumFiltered() == 1) {
+ assert(FilterChooserMap.size() == 1);
+ return;
+ }
+
+ // Otherwise, create sub choosers.
+ for (const auto &Inst : FilteredInstructions) {
+
+ // Marks all the segment positions with either BIT_TRUE or BIT_FALSE.
+ for (unsigned bitIndex = 0; bitIndex < NumBits; ++bitIndex) {
+ if (Inst.first & (1ULL << bitIndex))
+ BitValueArray[StartBit + bitIndex] = BIT_TRUE;
+ else
+ BitValueArray[StartBit + bitIndex] = BIT_FALSE;
+ }
+
+ // Delegates to an inferior filter chooser for further processing on this
+ // category of instructions.
+ FilterChooserMap.insert(std::make_pair(
+ Inst.first, llvm::make_unique<FilterChooser>(
+ Owner->AllInstructions, Inst.second,
+ Owner->Operands, BitValueArray, *Owner)));
+ }
+}
+
+static void resolveTableFixups(DecoderTable &Table, const FixupList &Fixups,
+ uint32_t DestIdx) {
+ // Any NumToSkip fixups in the current scope can resolve to the
+ // current location.
+ for (FixupList::const_reverse_iterator I = Fixups.rbegin(),
+ E = Fixups.rend();
+ I != E; ++I) {
+ // Calculate the distance from the byte following the fixup entry byte
+ // to the destination. The Target is calculated from after the 16-bit
+ // NumToSkip entry itself, so subtract two from the displacement here
+ // to account for that.
+ uint32_t FixupIdx = *I;
+ uint32_t Delta = DestIdx - FixupIdx - 2;
+ // Our NumToSkip entries are 16-bits. Make sure our table isn't too
+ // big.
+ assert(Delta < 65536U && "disassembler decoding table too large!");
+ Table[FixupIdx] = (uint8_t)Delta;
+ Table[FixupIdx + 1] = (uint8_t)(Delta >> 8);
+ }
+}
+
+// Emit table entries to decode instructions given a segment or segments
+// of bits.
+void Filter::emitTableEntry(DecoderTableInfo &TableInfo) const {
+ TableInfo.Table.push_back(MCD::OPC_ExtractField);
+ TableInfo.Table.push_back(StartBit);
+ TableInfo.Table.push_back(NumBits);
+
+ // A new filter entry begins a new scope for fixup resolution.
+ TableInfo.FixupStack.emplace_back();
+
+ DecoderTable &Table = TableInfo.Table;
+
+ size_t PrevFilter = 0;
+ bool HasFallthrough = false;
+ for (auto &Filter : FilterChooserMap) {
+ // Field value -1 implies a non-empty set of variable instructions.
+ // See also recurse().
+ if (Filter.first == (unsigned)-1) {
+ HasFallthrough = true;
+
+ // Each scope should always have at least one filter value to check
+ // for.
+ assert(PrevFilter != 0 && "empty filter set!");
+ FixupList &CurScope = TableInfo.FixupStack.back();
+ // Resolve any NumToSkip fixups in the current scope.
+ resolveTableFixups(Table, CurScope, Table.size());
+ CurScope.clear();
+ PrevFilter = 0; // Don't re-process the filter's fallthrough.
+ } else {
+ Table.push_back(MCD::OPC_FilterValue);
+ // Encode and emit the value to filter against.
+ uint8_t Buffer[8];
+ unsigned Len = encodeULEB128(Filter.first, Buffer);
+ Table.insert(Table.end(), Buffer, Buffer + Len);
+ // Reserve space for the NumToSkip entry. We'll backpatch the value
+ // later.
+ PrevFilter = Table.size();
+ Table.push_back(0);
+ Table.push_back(0);
+ }
+
+ // We arrive at a category of instructions with the same segment value.
+ // Now delegate to the sub filter chooser for further decodings.
+ // The case may fallthrough, which happens if the remaining well-known
+ // encoding bits do not match exactly.
+ Filter.second->emitTableEntries(TableInfo);
+
+ // Now that we've emitted the body of the handler, update the NumToSkip
+ // of the filter itself to be able to skip forward when false. Subtract
+ // two as to account for the width of the NumToSkip field itself.
+ if (PrevFilter) {
+ uint32_t NumToSkip = Table.size() - PrevFilter - 2;
+ assert(NumToSkip < 65536U && "disassembler decoding table too large!");
+ Table[PrevFilter] = (uint8_t)NumToSkip;
+ Table[PrevFilter + 1] = (uint8_t)(NumToSkip >> 8);
+ }
+ }
+
+ // Any remaining unresolved fixups bubble up to the parent fixup scope.
+ assert(TableInfo.FixupStack.size() > 1 && "fixup stack underflow!");
+ FixupScopeList::iterator Source = TableInfo.FixupStack.end() - 1;
+ FixupScopeList::iterator Dest = Source - 1;
+ Dest->insert(Dest->end(), Source->begin(), Source->end());
+ TableInfo.FixupStack.pop_back();
+
+ // If there is no fallthrough, then the final filter should get fixed
+ // up according to the enclosing scope rather than the current position.
+ if (!HasFallthrough)
+ TableInfo.FixupStack.back().push_back(PrevFilter);
+}
+
+// Returns the number of fanout produced by the filter. More fanout implies
+// the filter distinguishes more categories of instructions.
+unsigned Filter::usefulness() const {
+ if (!VariableInstructions.empty())
+ return FilteredInstructions.size();
+ else
+ return FilteredInstructions.size() + 1;
+}
+
+//////////////////////////////////
+// //
+// Filterchooser Implementation //
+// //
+//////////////////////////////////
+
+// Emit the decoder state machine table.
+void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
+ DecoderTable &Table,
+ unsigned Indentation,
+ unsigned BitWidth,
+ StringRef Namespace) const {
+ OS.indent(Indentation) << "static const uint8_t DecoderTable" << Namespace
+ << BitWidth << "[] = {\n";
+
+ Indentation += 2;
+
+ // FIXME: We may be able to use the NumToSkip values to recover
+ // appropriate indentation levels.
+ DecoderTable::const_iterator I = Table.begin();
+ DecoderTable::const_iterator E = Table.end();
+ while (I != E) {
+ assert (I < E && "incomplete decode table entry!");
+
+ uint64_t Pos = I - Table.begin();
+ OS << "/* " << Pos << " */";
+ OS.PadToColumn(12);
+
+ switch (*I) {
+ default:
+ PrintFatalError("invalid decode table opcode");
+ case MCD::OPC_ExtractField: {
+ ++I;
+ unsigned Start = *I++;
+ unsigned Len = *I++;
+ OS.indent(Indentation) << "MCD::OPC_ExtractField, " << Start << ", "
+ << Len << ", // Inst{";
+ if (Len > 1)
+ OS << (Start + Len - 1) << "-";
+ OS << Start << "} ...\n";
+ break;
+ }
+ case MCD::OPC_FilterValue: {
+ ++I;
+ OS.indent(Indentation) << "MCD::OPC_FilterValue, ";
+ // The filter value is ULEB128 encoded.
+ while (*I >= 128)
+ OS << (unsigned)*I++ << ", ";
+ OS << (unsigned)*I++ << ", ";
+
+ // 16-bit numtoskip value.
+ uint8_t Byte = *I++;
+ uint32_t NumToSkip = Byte;
+ OS << (unsigned)Byte << ", ";
+ Byte = *I++;
+ OS << (unsigned)Byte << ", ";
+ NumToSkip |= Byte << 8;
+ OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
+ break;
+ }
+ case MCD::OPC_CheckField: {
+ ++I;
+ unsigned Start = *I++;
+ unsigned Len = *I++;
+ OS.indent(Indentation) << "MCD::OPC_CheckField, " << Start << ", "
+ << Len << ", ";// << Val << ", " << NumToSkip << ",\n";
+ // ULEB128 encoded field value.
+ for (; *I >= 128; ++I)
+ OS << (unsigned)*I << ", ";
+ OS << (unsigned)*I++ << ", ";
+ // 16-bit numtoskip value.
+ uint8_t Byte = *I++;
+ uint32_t NumToSkip = Byte;
+ OS << (unsigned)Byte << ", ";
+ Byte = *I++;
+ OS << (unsigned)Byte << ", ";
+ NumToSkip |= Byte << 8;
+ OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
+ break;
+ }
+ case MCD::OPC_CheckPredicate: {
+ ++I;
+ OS.indent(Indentation) << "MCD::OPC_CheckPredicate, ";
+ for (; *I >= 128; ++I)
+ OS << (unsigned)*I << ", ";
+ OS << (unsigned)*I++ << ", ";
+
+ // 16-bit numtoskip value.
+ uint8_t Byte = *I++;
+ uint32_t NumToSkip = Byte;
+ OS << (unsigned)Byte << ", ";
+ Byte = *I++;
+ OS << (unsigned)Byte << ", ";
+ NumToSkip |= Byte << 8;
+ OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
+ break;
+ }
+ case MCD::OPC_Decode:
+ case MCD::OPC_TryDecode: {
+ bool IsTry = *I == MCD::OPC_TryDecode;
+ ++I;
+ // Extract the ULEB128 encoded Opcode to a buffer.
+ uint8_t Buffer[8], *p = Buffer;
+ while ((*p++ = *I++) >= 128)
+ assert((p - Buffer) <= (ptrdiff_t)sizeof(Buffer)
+ && "ULEB128 value too large!");
+ // Decode the Opcode value.
+ unsigned Opc = decodeULEB128(Buffer);
+ OS.indent(Indentation) << "MCD::OPC_" << (IsTry ? "Try" : "")
+ << "Decode, ";
+ for (p = Buffer; *p >= 128; ++p)
+ OS << (unsigned)*p << ", ";
+ OS << (unsigned)*p << ", ";
+
+ // Decoder index.
+ for (; *I >= 128; ++I)
+ OS << (unsigned)*I << ", ";
+ OS << (unsigned)*I++ << ", ";
+
+ if (!IsTry) {
+ OS << "// Opcode: "
+ << NumberedInstructions[Opc]->TheDef->getName() << "\n";
+ break;
+ }
+
+ // Fallthrough for OPC_TryDecode.
+
+ // 16-bit numtoskip value.
+ uint8_t Byte = *I++;
+ uint32_t NumToSkip = Byte;
+ OS << (unsigned)Byte << ", ";
+ Byte = *I++;
+ OS << (unsigned)Byte << ", ";
+ NumToSkip |= Byte << 8;
+
+ OS << "// Opcode: "
+ << NumberedInstructions[Opc]->TheDef->getName()
+ << ", skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
+ break;
+ }
+ case MCD::OPC_SoftFail: {
+ ++I;
+ OS.indent(Indentation) << "MCD::OPC_SoftFail";
+ // Positive mask
+ uint64_t Value = 0;
+ unsigned Shift = 0;
+ do {
+ OS << ", " << (unsigned)*I;
+ Value += (*I & 0x7f) << Shift;
+ Shift += 7;
+ } while (*I++ >= 128);
+ if (Value > 127) {
+ OS << " /* 0x";
+ OS.write_hex(Value);
+ OS << " */";
+ }
+ // Negative mask
+ Value = 0;
+ Shift = 0;
+ do {
+ OS << ", " << (unsigned)*I;
+ Value += (*I & 0x7f) << Shift;
+ Shift += 7;
+ } while (*I++ >= 128);
+ if (Value > 127) {
+ OS << " /* 0x";
+ OS.write_hex(Value);
+ OS << " */";
+ }
+ OS << ",\n";
+ break;
+ }
+ case MCD::OPC_Fail: {
+ ++I;
+ OS.indent(Indentation) << "MCD::OPC_Fail,\n";
+ break;
+ }
+ }
+ }
+ OS.indent(Indentation) << "0\n";
+
+ Indentation -= 2;
+
+ OS.indent(Indentation) << "};\n\n";
+}
+
+void FixedLenDecoderEmitter::
+emitPredicateFunction(formatted_raw_ostream &OS, PredicateSet &Predicates,
+ unsigned Indentation) const {
+ // The predicate function is just a big switch statement based on the
+ // input predicate index.
+ OS.indent(Indentation) << "static bool checkDecoderPredicate(unsigned Idx, "
+ << "const FeatureBitset& Bits) {\n";
+ Indentation += 2;
+ if (!Predicates.empty()) {
+ OS.indent(Indentation) << "switch (Idx) {\n";
+ OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
+ unsigned Index = 0;
+ for (const auto &Predicate : Predicates) {
+ OS.indent(Indentation) << "case " << Index++ << ":\n";
+ OS.indent(Indentation+2) << "return (" << Predicate << ");\n";
+ }
+ OS.indent(Indentation) << "}\n";
+ } else {
+ // No case statement to emit
+ OS.indent(Indentation) << "llvm_unreachable(\"Invalid index!\");\n";
+ }
+ Indentation -= 2;
+ OS.indent(Indentation) << "}\n\n";
+}
+
+void FixedLenDecoderEmitter::
+emitDecoderFunction(formatted_raw_ostream &OS, DecoderSet &Decoders,
+ unsigned Indentation) const {
+ // The decoder function is just a big switch statement based on the
+ // input decoder index.
+ OS.indent(Indentation) << "template<typename InsnType>\n";
+ OS.indent(Indentation) << "static DecodeStatus decodeToMCInst(DecodeStatus S,"
+ << " unsigned Idx, InsnType insn, MCInst &MI,\n";
+ OS.indent(Indentation) << " uint64_t "
+ << "Address, const void *Decoder, bool &DecodeComplete) {\n";
+ Indentation += 2;
+ OS.indent(Indentation) << "DecodeComplete = true;\n";
+ OS.indent(Indentation) << "InsnType tmp;\n";
+ OS.indent(Indentation) << "switch (Idx) {\n";
+ OS.indent(Indentation) << "default: llvm_unreachable(\"Invalid index!\");\n";
+ unsigned Index = 0;
+ for (const auto &Decoder : Decoders) {
+ OS.indent(Indentation) << "case " << Index++ << ":\n";
+ OS << Decoder;
+ OS.indent(Indentation+2) << "return S;\n";
+ }
+ OS.indent(Indentation) << "}\n";
+ Indentation -= 2;
+ OS.indent(Indentation) << "}\n\n";
+}
+
+// Populates the field of the insn given the start position and the number of
+// consecutive bits to scan for.
+//
+// Returns false if and on the first uninitialized bit value encountered.
+// Returns true, otherwise.
+bool FilterChooser::fieldFromInsn(uint64_t &Field, insn_t &Insn,
+ unsigned StartBit, unsigned NumBits) const {
+ Field = 0;
+
+ for (unsigned i = 0; i < NumBits; ++i) {
+ if (Insn[StartBit + i] == BIT_UNSET)
+ return false;
+
+ if (Insn[StartBit + i] == BIT_TRUE)
+ Field = Field | (1ULL << i);
+ }
+
+ return true;
+}
+
+/// dumpFilterArray - dumpFilterArray prints out debugging info for the given
+/// filter array as a series of chars.
+void FilterChooser::dumpFilterArray(raw_ostream &o,
+ const std::vector<bit_value_t> &filter) const {
+ for (unsigned bitIndex = BitWidth; bitIndex > 0; bitIndex--) {
+ switch (filter[bitIndex - 1]) {
+ case BIT_UNFILTERED:
+ o << ".";
+ break;
+ case BIT_UNSET:
+ o << "_";
+ break;
+ case BIT_TRUE:
+ o << "1";
+ break;
+ case BIT_FALSE:
+ o << "0";
+ break;
+ }
+ }
+}
+
+/// dumpStack - dumpStack traverses the filter chooser chain and calls
+/// dumpFilterArray on each filter chooser up to the top level one.
+void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) const {
+ const FilterChooser *current = this;
+
+ while (current) {
+ o << prefix;
+ dumpFilterArray(o, current->FilterBitValues);
+ o << '\n';
+ current = current->Parent;
+ }
+}
+
+// Calculates the island(s) needed to decode the instruction.
+// This returns a list of undecoded bits of an instructions, for example,
+// Inst{20} = 1 && Inst{3-0} == 0b1111 represents two islands of yet-to-be
+// decoded bits in order to verify that the instruction matches the Opcode.
+unsigned FilterChooser::getIslands(std::vector<unsigned> &StartBits,
+ std::vector<unsigned> &EndBits,
+ std::vector<uint64_t> &FieldVals,
+ const insn_t &Insn) const {
+ unsigned Num, BitNo;
+ Num = BitNo = 0;
+
+ uint64_t FieldVal = 0;
+
+ // 0: Init
+ // 1: Water (the bit value does not affect decoding)
+ // 2: Island (well-known bit value needed for decoding)
+ int State = 0;
+ int Val = -1;
+
+ for (unsigned i = 0; i < BitWidth; ++i) {
+ Val = Value(Insn[i]);
+ bool Filtered = PositionFiltered(i);
+ switch (State) {
+ default: llvm_unreachable("Unreachable code!");
+ case 0:
+ case 1:
+ if (Filtered || Val == -1)
+ State = 1; // Still in Water
+ else {
+ State = 2; // Into the Island
+ BitNo = 0;
+ StartBits.push_back(i);
+ FieldVal = Val;
+ }
+ break;
+ case 2:
+ if (Filtered || Val == -1) {
+ State = 1; // Into the Water
+ EndBits.push_back(i - 1);
+ FieldVals.push_back(FieldVal);
+ ++Num;
+ } else {
+ State = 2; // Still in Island
+ ++BitNo;
+ FieldVal = FieldVal | Val << BitNo;
+ }
+ break;
+ }
+ }
+ // If we are still in Island after the loop, do some housekeeping.
+ if (State == 2) {
+ EndBits.push_back(BitWidth - 1);
+ FieldVals.push_back(FieldVal);
+ ++Num;
+ }
+
+ assert(StartBits.size() == Num && EndBits.size() == Num &&
+ FieldVals.size() == Num);
+ return Num;
+}
+
+void FilterChooser::emitBinaryParser(raw_ostream &o, unsigned &Indentation,
+ const OperandInfo &OpInfo,
+ bool &OpHasCompleteDecoder) const {
+ const std::string &Decoder = OpInfo.Decoder;
+
+ if (OpInfo.numFields() != 1)
+ o.indent(Indentation) << "tmp = 0;\n";
+
+ for (const EncodingField &EF : OpInfo) {
+ o.indent(Indentation) << "tmp ";
+ if (OpInfo.numFields() != 1) o << '|';
+ o << "= fieldFromInstruction"
+ << "(insn, " << EF.Base << ", " << EF.Width << ')';
+ if (OpInfo.numFields() != 1 || EF.Offset != 0)
+ o << " << " << EF.Offset;
+ o << ";\n";
+ }
+
+ if (Decoder != "") {
+ OpHasCompleteDecoder = OpInfo.HasCompleteDecoder;
+ o.indent(Indentation) << Emitter->GuardPrefix << Decoder
+ << "(MI, tmp, Address, Decoder)"
+ << Emitter->GuardPostfix
+ << " { " << (OpHasCompleteDecoder ? "" : "DecodeComplete = false; ")
+ << "return MCDisassembler::Fail; }\n";
+ } else {
+ OpHasCompleteDecoder = true;
+ o.indent(Indentation) << "MI.addOperand(MCOperand::createImm(tmp));\n";
+ }
+}
+
+void FilterChooser::emitDecoder(raw_ostream &OS, unsigned Indentation,
+ unsigned Opc, bool &HasCompleteDecoder) const {
+ HasCompleteDecoder = true;
+
+ for (const auto &Op : Operands.find(Opc)->second) {
+ // If a custom instruction decoder was specified, use that.
+ if (Op.numFields() == 0 && !Op.Decoder.empty()) {
+ HasCompleteDecoder = Op.HasCompleteDecoder;
+ OS.indent(Indentation) << Emitter->GuardPrefix << Op.Decoder
+ << "(MI, insn, Address, Decoder)"
+ << Emitter->GuardPostfix
+ << " { " << (HasCompleteDecoder ? "" : "DecodeComplete = false; ")
+ << "return MCDisassembler::Fail; }\n";
+ break;
+ }
+
+ bool OpHasCompleteDecoder;
+ emitBinaryParser(OS, Indentation, Op, OpHasCompleteDecoder);
+ if (!OpHasCompleteDecoder)
+ HasCompleteDecoder = false;
+ }
+}
+
+unsigned FilterChooser::getDecoderIndex(DecoderSet &Decoders,
+ unsigned Opc,
+ bool &HasCompleteDecoder) const {
+ // Build up the predicate string.
+ SmallString<256> Decoder;
+ // FIXME: emitDecoder() function can take a buffer directly rather than
+ // a stream.
+ raw_svector_ostream S(Decoder);
+ unsigned I = 4;
+ emitDecoder(S, I, Opc, HasCompleteDecoder);
+
+ // Using the full decoder string as the key value here is a bit
+ // heavyweight, but is effective. If the string comparisons become a
+ // performance concern, we can implement a mangling of the predicate
+ // data easily enough with a map back to the actual string. That's
+ // overkill for now, though.
+
+ // Make sure the predicate is in the table.
+ Decoders.insert(CachedHashString(Decoder));
+ // Now figure out the index for when we write out the table.
+ DecoderSet::const_iterator P = find(Decoders, Decoder.str());
+ return (unsigned)(P - Decoders.begin());
+}
+
+static void emitSinglePredicateMatch(raw_ostream &o, StringRef str,
+ const std::string &PredicateNamespace) {
+ if (str[0] == '!')
+ o << "!Bits[" << PredicateNamespace << "::"
+ << str.slice(1,str.size()) << "]";
+ else
+ o << "Bits[" << PredicateNamespace << "::" << str << "]";
+}
+
+bool FilterChooser::emitPredicateMatch(raw_ostream &o, unsigned &Indentation,
+ unsigned Opc) const {
+ ListInit *Predicates =
+ AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates");
+ bool IsFirstEmission = true;
+ for (unsigned i = 0; i < Predicates->size(); ++i) {
+ Record *Pred = Predicates->getElementAsRecord(i);
+ if (!Pred->getValue("AssemblerMatcherPredicate"))
+ continue;
+
+ std::string P = Pred->getValueAsString("AssemblerCondString");
+
+ if (!P.length())
+ continue;
+
+ if (!IsFirstEmission)
+ o << " && ";
+
+ StringRef SR(P);
+ std::pair<StringRef, StringRef> pairs = SR.split(',');
+ while (!pairs.second.empty()) {
+ emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
+ o << " && ";
+ pairs = pairs.second.split(',');
+ }
+ emitSinglePredicateMatch(o, pairs.first, Emitter->PredicateNamespace);
+ IsFirstEmission = false;
+ }
+ return !Predicates->empty();
+}
+
+bool FilterChooser::doesOpcodeNeedPredicate(unsigned Opc) const {
+ ListInit *Predicates =
+ AllInstructions[Opc]->TheDef->getValueAsListInit("Predicates");
+ for (unsigned i = 0; i < Predicates->size(); ++i) {
+ Record *Pred = Predicates->getElementAsRecord(i);
+ if (!Pred->getValue("AssemblerMatcherPredicate"))
+ continue;
+
+ std::string P = Pred->getValueAsString("AssemblerCondString");
+
+ if (!P.length())
+ continue;
+
+ return true;
+ }
+ return false;
+}
+
+unsigned FilterChooser::getPredicateIndex(DecoderTableInfo &TableInfo,
+ StringRef Predicate) const {
+ // Using the full predicate string as the key value here is a bit
+ // heavyweight, but is effective. If the string comparisons become a
+ // performance concern, we can implement a mangling of the predicate
+ // data easily enough with a map back to the actual string. That's
+ // overkill for now, though.
+
+ // Make sure the predicate is in the table.
+ TableInfo.Predicates.insert(CachedHashString(Predicate));
+ // Now figure out the index for when we write out the table.
+ PredicateSet::const_iterator P = find(TableInfo.Predicates, Predicate);
+ return (unsigned)(P - TableInfo.Predicates.begin());
+}
+
+void FilterChooser::emitPredicateTableEntry(DecoderTableInfo &TableInfo,
+ unsigned Opc) const {
+ if (!doesOpcodeNeedPredicate(Opc))
+ return;
+
+ // Build up the predicate string.
+ SmallString<256> Predicate;
+ // FIXME: emitPredicateMatch() functions can take a buffer directly rather
+ // than a stream.
+ raw_svector_ostream PS(Predicate);
+ unsigned I = 0;
+ emitPredicateMatch(PS, I, Opc);
+
+ // Figure out the index into the predicate table for the predicate just
+ // computed.
+ unsigned PIdx = getPredicateIndex(TableInfo, PS.str());
+ SmallString<16> PBytes;
+ raw_svector_ostream S(PBytes);
+ encodeULEB128(PIdx, S);
+
+ TableInfo.Table.push_back(MCD::OPC_CheckPredicate);
+ // Predicate index
+ for (unsigned i = 0, e = PBytes.size(); i != e; ++i)
+ TableInfo.Table.push_back(PBytes[i]);
+ // Push location for NumToSkip backpatching.
+ TableInfo.FixupStack.back().push_back(TableInfo.Table.size());
+ TableInfo.Table.push_back(0);
+ TableInfo.Table.push_back(0);
+}
+
+void FilterChooser::emitSoftFailTableEntry(DecoderTableInfo &TableInfo,
+ unsigned Opc) const {
+ BitsInit *SFBits =
+ AllInstructions[Opc]->TheDef->getValueAsBitsInit("SoftFail");
+ if (!SFBits) return;
+ BitsInit *InstBits = AllInstructions[Opc]->TheDef->getValueAsBitsInit("Inst");
+
+ APInt PositiveMask(BitWidth, 0ULL);
+ APInt NegativeMask(BitWidth, 0ULL);
+ for (unsigned i = 0; i < BitWidth; ++i) {
+ bit_value_t B = bitFromBits(*SFBits, i);
+ bit_value_t IB = bitFromBits(*InstBits, i);
+
+ if (B != BIT_TRUE) continue;
+
+ switch (IB) {
+ case BIT_FALSE:
+ // The bit is meant to be false, so emit a check to see if it is true.
+ PositiveMask.setBit(i);
+ break;
+ case BIT_TRUE:
+ // The bit is meant to be true, so emit a check to see if it is false.
+ NegativeMask.setBit(i);
+ break;
+ default:
+ // The bit is not set; this must be an error!
+ StringRef Name = AllInstructions[Opc]->TheDef->getName();
+ errs() << "SoftFail Conflict: bit SoftFail{" << i << "} in " << Name
+ << " is set but Inst{" << i << "} is unset!\n"
+ << " - You can only mark a bit as SoftFail if it is fully defined"
+ << " (1/0 - not '?') in Inst\n";
+ return;
+ }
+ }
+
+ bool NeedPositiveMask = PositiveMask.getBoolValue();
+ bool NeedNegativeMask = NegativeMask.getBoolValue();
+
+ if (!NeedPositiveMask && !NeedNegativeMask)
+ return;
+
+ TableInfo.Table.push_back(MCD::OPC_SoftFail);
+
+ SmallString<16> MaskBytes;
+ raw_svector_ostream S(MaskBytes);
+ if (NeedPositiveMask) {
+ encodeULEB128(PositiveMask.getZExtValue(), S);
+ for (unsigned i = 0, e = MaskBytes.size(); i != e; ++i)
+ TableInfo.Table.push_back(MaskBytes[i]);
+ } else
+ TableInfo.Table.push_back(0);
+ if (NeedNegativeMask) {
+ MaskBytes.clear();
+ encodeULEB128(NegativeMask.getZExtValue(), S);
+ for (unsigned i = 0, e = MaskBytes.size(); i != e; ++i)
+ TableInfo.Table.push_back(MaskBytes[i]);
+ } else
+ TableInfo.Table.push_back(0);
+}
+
+// Emits table entries to decode the singleton.
+void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
+ unsigned Opc) const {
+ std::vector<unsigned> StartBits;
+ std::vector<unsigned> EndBits;
+ std::vector<uint64_t> FieldVals;
+ insn_t Insn;
+ insnWithID(Insn, Opc);
+
+ // Look for islands of undecoded bits of the singleton.
+ getIslands(StartBits, EndBits, FieldVals, Insn);
+
+ unsigned Size = StartBits.size();
+
+ // Emit the predicate table entry if one is needed.
+ emitPredicateTableEntry(TableInfo, Opc);
+
+ // Check any additional encoding fields needed.
+ for (unsigned I = Size; I != 0; --I) {
+ unsigned NumBits = EndBits[I-1] - StartBits[I-1] + 1;
+ TableInfo.Table.push_back(MCD::OPC_CheckField);
+ TableInfo.Table.push_back(StartBits[I-1]);
+ TableInfo.Table.push_back(NumBits);
+ uint8_t Buffer[8], *p;
+ encodeULEB128(FieldVals[I-1], Buffer);
+ for (p = Buffer; *p >= 128 ; ++p)
+ TableInfo.Table.push_back(*p);
+ TableInfo.Table.push_back(*p);
+ // Push location for NumToSkip backpatching.
+ TableInfo.FixupStack.back().push_back(TableInfo.Table.size());
+ // The fixup is always 16-bits, so go ahead and allocate the space
+ // in the table so all our relative position calculations work OK even
+ // before we fully resolve the real value here.
+ TableInfo.Table.push_back(0);
+ TableInfo.Table.push_back(0);
+ }
+
+ // Check for soft failure of the match.
+ emitSoftFailTableEntry(TableInfo, Opc);
+
+ bool HasCompleteDecoder;
+ unsigned DIdx = getDecoderIndex(TableInfo.Decoders, Opc, HasCompleteDecoder);
+
+ // Produce OPC_Decode or OPC_TryDecode opcode based on the information
+ // whether the instruction decoder is complete or not. If it is complete
+ // then it handles all possible values of remaining variable/unfiltered bits
+ // and for any value can determine if the bitpattern is a valid instruction
+ // or not. This means OPC_Decode will be the final step in the decoding
+ // process. If it is not complete, then the Fail return code from the
+ // decoder method indicates that additional processing should be done to see
+ // if there is any other instruction that also matches the bitpattern and
+ // can decode it.
+ TableInfo.Table.push_back(HasCompleteDecoder ? MCD::OPC_Decode :
+ MCD::OPC_TryDecode);
+ uint8_t Buffer[8], *p;
+ encodeULEB128(Opc, Buffer);
+ for (p = Buffer; *p >= 128 ; ++p)
+ TableInfo.Table.push_back(*p);
+ TableInfo.Table.push_back(*p);
+
+ SmallString<16> Bytes;
+ raw_svector_ostream S(Bytes);
+ encodeULEB128(DIdx, S);
+
+ // Decoder index
+ for (unsigned i = 0, e = Bytes.size(); i != e; ++i)
+ TableInfo.Table.push_back(Bytes[i]);
+
+ if (!HasCompleteDecoder) {
+ // Push location for NumToSkip backpatching.
+ TableInfo.FixupStack.back().push_back(TableInfo.Table.size());
+ // Allocate the space for the fixup.
+ TableInfo.Table.push_back(0);
+ TableInfo.Table.push_back(0);
+ }
+}
+
+// Emits table entries to decode the singleton, and then to decode the rest.
+void FilterChooser::emitSingletonTableEntry(DecoderTableInfo &TableInfo,
+ const Filter &Best) const {
+ unsigned Opc = Best.getSingletonOpc();
+
+ // complex singletons need predicate checks from the first singleton
+ // to refer forward to the variable filterchooser that follows.
+ TableInfo.FixupStack.emplace_back();
+
+ emitSingletonTableEntry(TableInfo, Opc);
+
+ resolveTableFixups(TableInfo.Table, TableInfo.FixupStack.back(),
+ TableInfo.Table.size());
+ TableInfo.FixupStack.pop_back();
+
+ Best.getVariableFC().emitTableEntries(TableInfo);
+}
+
+// Assign a single filter and run with it. Top level API client can initialize
+// with a single filter to start the filtering process.
+void FilterChooser::runSingleFilter(unsigned startBit, unsigned numBit,
+ bool mixed) {
+ Filters.clear();
+ Filters.emplace_back(*this, startBit, numBit, true);
+ BestIndex = 0; // Sole Filter instance to choose from.
+ bestFilter().recurse();
+}
+
+// reportRegion is a helper function for filterProcessor to mark a region as
+// eligible for use as a filter region.
+void FilterChooser::reportRegion(bitAttr_t RA, unsigned StartBit,
+ unsigned BitIndex, bool AllowMixed) {
+ if (RA == ATTR_MIXED && AllowMixed)
+ Filters.emplace_back(*this, StartBit, BitIndex - StartBit, true);
+ else if (RA == ATTR_ALL_SET && !AllowMixed)
+ Filters.emplace_back(*this, StartBit, BitIndex - StartBit, false);
+}
+
+// FilterProcessor scans the well-known encoding bits of the instructions and
+// builds up a list of candidate filters. It chooses the best filter and
+// recursively descends down the decoding tree.
+bool FilterChooser::filterProcessor(bool AllowMixed, bool Greedy) {
+ Filters.clear();
+ BestIndex = -1;
+ unsigned numInstructions = Opcodes.size();
+
+ assert(numInstructions && "Filter created with no instructions");
+
+ // No further filtering is necessary.
+ if (numInstructions == 1)
+ return true;
+
+ // Heuristics. See also doFilter()'s "Heuristics" comment when num of
+ // instructions is 3.
+ if (AllowMixed && !Greedy) {
+ assert(numInstructions == 3);
+
+ for (unsigned i = 0; i < Opcodes.size(); ++i) {
+ std::vector<unsigned> StartBits;
+ std::vector<unsigned> EndBits;
+ std::vector<uint64_t> FieldVals;
+ insn_t Insn;
+
+ insnWithID(Insn, Opcodes[i]);
+
+ // Look for islands of undecoded bits of any instruction.
+ if (getIslands(StartBits, EndBits, FieldVals, Insn) > 0) {
+ // Found an instruction with island(s). Now just assign a filter.
+ runSingleFilter(StartBits[0], EndBits[0] - StartBits[0] + 1, true);
+ return true;
+ }
+ }
+ }
+
+ unsigned BitIndex;
+
+ // We maintain BIT_WIDTH copies of the bitAttrs automaton.
+ // The automaton consumes the corresponding bit from each
+ // instruction.
+ //
+ // Input symbols: 0, 1, and _ (unset).
+ // States: NONE, FILTERED, ALL_SET, ALL_UNSET, and MIXED.
+ // Initial state: NONE.
+ //
+ // (NONE) ------- [01] -> (ALL_SET)
+ // (NONE) ------- _ ----> (ALL_UNSET)
+ // (ALL_SET) ---- [01] -> (ALL_SET)
+ // (ALL_SET) ---- _ ----> (MIXED)
+ // (ALL_UNSET) -- [01] -> (MIXED)
+ // (ALL_UNSET) -- _ ----> (ALL_UNSET)
+ // (MIXED) ------ . ----> (MIXED)
+ // (FILTERED)---- . ----> (FILTERED)
+
+ std::vector<bitAttr_t> bitAttrs;
+
+ // FILTERED bit positions provide no entropy and are not worthy of pursuing.
+ // Filter::recurse() set either BIT_TRUE or BIT_FALSE for each position.
+ for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex)
+ if (FilterBitValues[BitIndex] == BIT_TRUE ||
+ FilterBitValues[BitIndex] == BIT_FALSE)
+ bitAttrs.push_back(ATTR_FILTERED);
+ else
+ bitAttrs.push_back(ATTR_NONE);
+
+ for (unsigned InsnIndex = 0; InsnIndex < numInstructions; ++InsnIndex) {
+ insn_t insn;
+
+ insnWithID(insn, Opcodes[InsnIndex]);
+
+ for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
+ switch (bitAttrs[BitIndex]) {
+ case ATTR_NONE:
+ if (insn[BitIndex] == BIT_UNSET)
+ bitAttrs[BitIndex] = ATTR_ALL_UNSET;
+ else
+ bitAttrs[BitIndex] = ATTR_ALL_SET;
+ break;
+ case ATTR_ALL_SET:
+ if (insn[BitIndex] == BIT_UNSET)
+ bitAttrs[BitIndex] = ATTR_MIXED;
+ break;
+ case ATTR_ALL_UNSET:
+ if (insn[BitIndex] != BIT_UNSET)
+ bitAttrs[BitIndex] = ATTR_MIXED;
+ break;
+ case ATTR_MIXED:
+ case ATTR_FILTERED:
+ break;
+ }
+ }
+ }
+
+ // The regionAttr automaton consumes the bitAttrs automatons' state,
+ // lowest-to-highest.
+ //
+ // Input symbols: F(iltered), (all_)S(et), (all_)U(nset), M(ixed)
+ // States: NONE, ALL_SET, MIXED
+ // Initial state: NONE
+ //
+ // (NONE) ----- F --> (NONE)
+ // (NONE) ----- S --> (ALL_SET) ; and set region start
+ // (NONE) ----- U --> (NONE)
+ // (NONE) ----- M --> (MIXED) ; and set region start
+ // (ALL_SET) -- F --> (NONE) ; and report an ALL_SET region
+ // (ALL_SET) -- S --> (ALL_SET)
+ // (ALL_SET) -- U --> (NONE) ; and report an ALL_SET region
+ // (ALL_SET) -- M --> (MIXED) ; and report an ALL_SET region
+ // (MIXED) ---- F --> (NONE) ; and report a MIXED region
+ // (MIXED) ---- S --> (ALL_SET) ; and report a MIXED region
+ // (MIXED) ---- U --> (NONE) ; and report a MIXED region
+ // (MIXED) ---- M --> (MIXED)
+
+ bitAttr_t RA = ATTR_NONE;
+ unsigned StartBit = 0;
+
+ for (BitIndex = 0; BitIndex < BitWidth; ++BitIndex) {
+ bitAttr_t bitAttr = bitAttrs[BitIndex];
+
+ assert(bitAttr != ATTR_NONE && "Bit without attributes");
+
+ switch (RA) {
+ case ATTR_NONE:
+ switch (bitAttr) {
+ case ATTR_FILTERED:
+ break;
+ case ATTR_ALL_SET:
+ StartBit = BitIndex;
+ RA = ATTR_ALL_SET;
+ break;
+ case ATTR_ALL_UNSET:
+ break;
+ case ATTR_MIXED:
+ StartBit = BitIndex;
+ RA = ATTR_MIXED;
+ break;
+ default:
+ llvm_unreachable("Unexpected bitAttr!");
+ }
+ break;
+ case ATTR_ALL_SET:
+ switch (bitAttr) {
+ case ATTR_FILTERED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ RA = ATTR_NONE;
+ break;
+ case ATTR_ALL_SET:
+ break;
+ case ATTR_ALL_UNSET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ RA = ATTR_NONE;
+ break;
+ case ATTR_MIXED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ StartBit = BitIndex;
+ RA = ATTR_MIXED;
+ break;
+ default:
+ llvm_unreachable("Unexpected bitAttr!");
+ }
+ break;
+ case ATTR_MIXED:
+ switch (bitAttr) {
+ case ATTR_FILTERED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ StartBit = BitIndex;
+ RA = ATTR_NONE;
+ break;
+ case ATTR_ALL_SET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ StartBit = BitIndex;
+ RA = ATTR_ALL_SET;
+ break;
+ case ATTR_ALL_UNSET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ RA = ATTR_NONE;
+ break;
+ case ATTR_MIXED:
+ break;
+ default:
+ llvm_unreachable("Unexpected bitAttr!");
+ }
+ break;
+ case ATTR_ALL_UNSET:
+ llvm_unreachable("regionAttr state machine has no ATTR_UNSET state");
+ case ATTR_FILTERED:
+ llvm_unreachable("regionAttr state machine has no ATTR_FILTERED state");
+ }
+ }
+
+ // At the end, if we're still in ALL_SET or MIXED states, report a region
+ switch (RA) {
+ case ATTR_NONE:
+ break;
+ case ATTR_FILTERED:
+ break;
+ case ATTR_ALL_SET:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ break;
+ case ATTR_ALL_UNSET:
+ break;
+ case ATTR_MIXED:
+ reportRegion(RA, StartBit, BitIndex, AllowMixed);
+ break;
+ }
+
+ // We have finished with the filter processings. Now it's time to choose
+ // the best performing filter.
+ BestIndex = 0;
+ bool AllUseless = true;
+ unsigned BestScore = 0;
+
+ for (unsigned i = 0, e = Filters.size(); i != e; ++i) {
+ unsigned Usefulness = Filters[i].usefulness();
+
+ if (Usefulness)
+ AllUseless = false;
+
+ if (Usefulness > BestScore) {
+ BestIndex = i;
+ BestScore = Usefulness;
+ }
+ }
+
+ if (!AllUseless)
+ bestFilter().recurse();
+
+ return !AllUseless;
+} // end of FilterChooser::filterProcessor(bool)
+
+// Decides on the best configuration of filter(s) to use in order to decode
+// the instructions. A conflict of instructions may occur, in which case we
+// dump the conflict set to the standard error.
+void FilterChooser::doFilter() {
+ unsigned Num = Opcodes.size();
+ assert(Num && "FilterChooser created with no instructions");
+
+ // Try regions of consecutive known bit values first.
+ if (filterProcessor(false))
+ return;
+
+ // Then regions of mixed bits (both known and unitialized bit values allowed).
+ if (filterProcessor(true))
+ return;
+
+ // Heuristics to cope with conflict set {t2CMPrs, t2SUBSrr, t2SUBSrs} where
+ // no single instruction for the maximum ATTR_MIXED region Inst{14-4} has a
+ // well-known encoding pattern. In such case, we backtrack and scan for the
+ // the very first consecutive ATTR_ALL_SET region and assign a filter to it.
+ if (Num == 3 && filterProcessor(true, false))
+ return;
+
+ // If we come to here, the instruction decoding has failed.
+ // Set the BestIndex to -1 to indicate so.
+ BestIndex = -1;
+}
+
+// emitTableEntries - Emit state machine entries to decode our share of
+// instructions.
+void FilterChooser::emitTableEntries(DecoderTableInfo &TableInfo) const {
+ if (Opcodes.size() == 1) {
+ // There is only one instruction in the set, which is great!
+ // Call emitSingletonDecoder() to see whether there are any remaining
+ // encodings bits.
+ emitSingletonTableEntry(TableInfo, Opcodes[0]);
+ return;
+ }
+
+ // Choose the best filter to do the decodings!
+ if (BestIndex != -1) {
+ const Filter &Best = Filters[BestIndex];
+ if (Best.getNumFiltered() == 1)
+ emitSingletonTableEntry(TableInfo, Best);
+ else
+ Best.emitTableEntry(TableInfo);
+ return;
+ }
+
+ // We don't know how to decode these instructions! Dump the
+ // conflict set and bail.
+
+ // Print out useful conflict information for postmortem analysis.
+ errs() << "Decoding Conflict:\n";
+
+ dumpStack(errs(), "\t\t");
+
+ for (unsigned i = 0; i < Opcodes.size(); ++i) {
+ const std::string &Name = nameWithID(Opcodes[i]);
+
+ errs() << '\t' << Name << " ";
+ dumpBits(errs(),
+ getBitsField(*AllInstructions[Opcodes[i]]->TheDef, "Inst"));
+ errs() << '\n';
+ }
+}
+
+static std::string findOperandDecoderMethod(TypedInit *TI) {
+ std::string Decoder;
+
+ RecordRecTy *Type = cast<RecordRecTy>(TI->getType());
+ Record *TypeRecord = Type->getRecord();
+
+ RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod");
+ StringInit *String = DecoderString ?
+ dyn_cast<StringInit>(DecoderString->getValue()) : nullptr;
+ if (String) {
+ Decoder = String->getValue();
+ if (!Decoder.empty())
+ return Decoder;
+ }
+
+ if (TypeRecord->isSubClassOf("RegisterOperand"))
+ TypeRecord = TypeRecord->getValueAsDef("RegClass");
+
+ if (TypeRecord->isSubClassOf("RegisterClass")) {
+ Decoder = "Decode" + TypeRecord->getName().str() + "RegisterClass";
+ } else if (TypeRecord->isSubClassOf("PointerLikeRegClass")) {
+ Decoder = "DecodePointerLikeRegClass" +
+ utostr(TypeRecord->getValueAsInt("RegClassKind"));
+ }
+
+ return Decoder;
+}
+
+static bool populateInstruction(CodeGenTarget &Target,
+ const CodeGenInstruction &CGI, unsigned Opc,
+ std::map<unsigned, std::vector<OperandInfo>> &Operands){
+ const Record &Def = *CGI.TheDef;
+ // If all the bit positions are not specified; do not decode this instruction.
+ // We are bound to fail! For proper disassembly, the well-known encoding bits
+ // of the instruction must be fully specified.
+
+ BitsInit &Bits = getBitsField(Def, "Inst");
+ if (Bits.allInComplete()) return false;
+
+ std::vector<OperandInfo> InsnOperands;
+
+ // If the instruction has specified a custom decoding hook, use that instead
+ // of trying to auto-generate the decoder.
+ std::string InstDecoder = Def.getValueAsString("DecoderMethod");
+ if (InstDecoder != "") {
+ bool HasCompleteInstDecoder = Def.getValueAsBit("hasCompleteDecoder");
+ InsnOperands.push_back(OperandInfo(InstDecoder, HasCompleteInstDecoder));
+ Operands[Opc] = InsnOperands;
+ return true;
+ }
+
+ // Generate a description of the operand of the instruction that we know
+ // how to decode automatically.
+ // FIXME: We'll need to have a way to manually override this as needed.
+
+ // Gather the outputs/inputs of the instruction, so we can find their
+ // positions in the encoding. This assumes for now that they appear in the
+ // MCInst in the order that they're listed.
+ std::vector<std::pair<Init*, StringRef>> InOutOperands;
+ DagInit *Out = Def.getValueAsDag("OutOperandList");
+ DagInit *In = Def.getValueAsDag("InOperandList");
+ for (unsigned i = 0; i < Out->getNumArgs(); ++i)
+ InOutOperands.push_back(std::make_pair(Out->getArg(i),
+ Out->getArgNameStr(i)));
+ for (unsigned i = 0; i < In->getNumArgs(); ++i)
+ InOutOperands.push_back(std::make_pair(In->getArg(i),
+ In->getArgNameStr(i)));
+
+ // Search for tied operands, so that we can correctly instantiate
+ // operands that are not explicitly represented in the encoding.
+ std::map<std::string, std::string> TiedNames;
+ for (unsigned i = 0; i < CGI.Operands.size(); ++i) {
+ int tiedTo = CGI.Operands[i].getTiedRegister();
+ if (tiedTo != -1) {
+ std::pair<unsigned, unsigned> SO =
+ CGI.Operands.getSubOperandNumber(tiedTo);
+ TiedNames[InOutOperands[i].second] = InOutOperands[SO.first].second;
+ TiedNames[InOutOperands[SO.first].second] = InOutOperands[i].second;
+ }
+ }
+
+ std::map<std::string, std::vector<OperandInfo>> NumberedInsnOperands;
+ std::set<std::string> NumberedInsnOperandsNoTie;
+ if (Target.getInstructionSet()->
+ getValueAsBit("decodePositionallyEncodedOperands")) {
+ const std::vector<RecordVal> &Vals = Def.getValues();
+ unsigned NumberedOp = 0;
+
+ std::set<unsigned> NamedOpIndices;
+ if (Target.getInstructionSet()->
+ getValueAsBit("noNamedPositionallyEncodedOperands"))
+ // Collect the set of operand indices that might correspond to named
+ // operand, and skip these when assigning operands based on position.
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ unsigned OpIdx;
+ if (!CGI.Operands.hasOperandNamed(Vals[i].getName(), OpIdx))
+ continue;
+
+ NamedOpIndices.insert(OpIdx);
+ }
+
+ for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
+ // Ignore fixed fields in the record, we're looking for values like:
+ // bits<5> RST = { ?, ?, ?, ?, ? };
+ if (Vals[i].getPrefix() || Vals[i].getValue()->isComplete())
+ continue;
+
+ // Determine if Vals[i] actually contributes to the Inst encoding.
+ unsigned bi = 0;
+ for (; bi < Bits.getNumBits(); ++bi) {
+ VarInit *Var = nullptr;
+ VarBitInit *BI = dyn_cast<VarBitInit>(Bits.getBit(bi));
+ if (BI)
+ Var = dyn_cast<VarInit>(BI->getBitVar());
+ else
+ Var = dyn_cast<VarInit>(Bits.getBit(bi));
+
+ if (Var && Var->getName() == Vals[i].getName())
+ break;
+ }
+
+ if (bi == Bits.getNumBits())
+ continue;
+
+ // Skip variables that correspond to explicitly-named operands.
+ unsigned OpIdx;
+ if (CGI.Operands.hasOperandNamed(Vals[i].getName(), OpIdx))
+ continue;
+
+ // Get the bit range for this operand:
+ unsigned bitStart = bi++, bitWidth = 1;
+ for (; bi < Bits.getNumBits(); ++bi) {
+ VarInit *Var = nullptr;
+ VarBitInit *BI = dyn_cast<VarBitInit>(Bits.getBit(bi));
+ if (BI)
+ Var = dyn_cast<VarInit>(BI->getBitVar());
+ else
+ Var = dyn_cast<VarInit>(Bits.getBit(bi));
+
+ if (!Var)
+ break;
+
+ if (Var->getName() != Vals[i].getName())
+ break;
+
+ ++bitWidth;
+ }
+
+ unsigned NumberOps = CGI.Operands.size();
+ while (NumberedOp < NumberOps &&
+ (CGI.Operands.isFlatOperandNotEmitted(NumberedOp) ||
+ (!NamedOpIndices.empty() && NamedOpIndices.count(
+ CGI.Operands.getSubOperandNumber(NumberedOp).first))))
+ ++NumberedOp;
+
+ OpIdx = NumberedOp++;
+
+ // OpIdx now holds the ordered operand number of Vals[i].
+ std::pair<unsigned, unsigned> SO =
+ CGI.Operands.getSubOperandNumber(OpIdx);
+ const std::string &Name = CGI.Operands[SO.first].Name;
+
+ DEBUG(dbgs() << "Numbered operand mapping for " << Def.getName() << ": " <<
+ Name << "(" << SO.first << ", " << SO.second << ") => " <<
+ Vals[i].getName() << "\n");
+
+ std::string Decoder;
+ Record *TypeRecord = CGI.Operands[SO.first].Rec;
+
+ RecordVal *DecoderString = TypeRecord->getValue("DecoderMethod");
+ StringInit *String = DecoderString ?
+ dyn_cast<StringInit>(DecoderString->getValue()) : nullptr;
+ if (String && String->getValue() != "")
+ Decoder = String->getValue();
+
+ if (Decoder == "" &&
+ CGI.Operands[SO.first].MIOperandInfo &&
+ CGI.Operands[SO.first].MIOperandInfo->getNumArgs()) {
+ Init *Arg = CGI.Operands[SO.first].MIOperandInfo->
+ getArg(SO.second);
+ if (TypedInit *TI = cast<TypedInit>(Arg)) {
+ RecordRecTy *Type = cast<RecordRecTy>(TI->getType());
+ TypeRecord = Type->getRecord();
+ }
+ }
+
+ bool isReg = false;
+ if (TypeRecord->isSubClassOf("RegisterOperand"))
+ TypeRecord = TypeRecord->getValueAsDef("RegClass");
+ if (TypeRecord->isSubClassOf("RegisterClass")) {
+ Decoder = "Decode" + TypeRecord->getName().str() + "RegisterClass";
+ isReg = true;
+ } else if (TypeRecord->isSubClassOf("PointerLikeRegClass")) {
+ Decoder = "DecodePointerLikeRegClass" +
+ utostr(TypeRecord->getValueAsInt("RegClassKind"));
+ isReg = true;
+ }
+
+ DecoderString = TypeRecord->getValue("DecoderMethod");
+ String = DecoderString ?
+ dyn_cast<StringInit>(DecoderString->getValue()) : nullptr;
+ if (!isReg && String && String->getValue() != "")
+ Decoder = String->getValue();
+
+ RecordVal *HasCompleteDecoderVal =
+ TypeRecord->getValue("hasCompleteDecoder");
+ BitInit *HasCompleteDecoderBit = HasCompleteDecoderVal ?
+ dyn_cast<BitInit>(HasCompleteDecoderVal->getValue()) : nullptr;
+ bool HasCompleteDecoder = HasCompleteDecoderBit ?
+ HasCompleteDecoderBit->getValue() : true;
+
+ OperandInfo OpInfo(Decoder, HasCompleteDecoder);
+ OpInfo.addField(bitStart, bitWidth, 0);
+
+ NumberedInsnOperands[Name].push_back(OpInfo);
+
+ // FIXME: For complex operands with custom decoders we can't handle tied
+ // sub-operands automatically. Skip those here and assume that this is
+ // fixed up elsewhere.
+ if (CGI.Operands[SO.first].MIOperandInfo &&
+ CGI.Operands[SO.first].MIOperandInfo->getNumArgs() > 1 &&
+ String && String->getValue() != "")
+ NumberedInsnOperandsNoTie.insert(Name);
+ }
+ }
+
+ // For each operand, see if we can figure out where it is encoded.
+ for (const auto &Op : InOutOperands) {
+ if (!NumberedInsnOperands[Op.second].empty()) {
+ InsnOperands.insert(InsnOperands.end(),
+ NumberedInsnOperands[Op.second].begin(),
+ NumberedInsnOperands[Op.second].end());
+ continue;
+ }
+ if (!NumberedInsnOperands[TiedNames[Op.second]].empty()) {
+ if (!NumberedInsnOperandsNoTie.count(TiedNames[Op.second])) {
+ // Figure out to which (sub)operand we're tied.
+ unsigned i = CGI.Operands.getOperandNamed(TiedNames[Op.second]);
+ int tiedTo = CGI.Operands[i].getTiedRegister();
+ if (tiedTo == -1) {
+ i = CGI.Operands.getOperandNamed(Op.second);
+ tiedTo = CGI.Operands[i].getTiedRegister();
+ }
+
+ if (tiedTo != -1) {
+ std::pair<unsigned, unsigned> SO =
+ CGI.Operands.getSubOperandNumber(tiedTo);
+
+ InsnOperands.push_back(NumberedInsnOperands[TiedNames[Op.second]]
+ [SO.second]);
+ }
+ }
+ continue;
+ }
+
+ TypedInit *TI = cast<TypedInit>(Op.first);
+
+ // At this point, we can locate the decoder field, but we need to know how
+ // to interpret it. As a first step, require the target to provide
+ // callbacks for decoding register classes.
+ std::string Decoder = findOperandDecoderMethod(TI);
+ Record *TypeRecord = cast<RecordRecTy>(TI->getType())->getRecord();
+
+ RecordVal *HasCompleteDecoderVal =
+ TypeRecord->getValue("hasCompleteDecoder");
+ BitInit *HasCompleteDecoderBit = HasCompleteDecoderVal ?
+ dyn_cast<BitInit>(HasCompleteDecoderVal->getValue()) : nullptr;
+ bool HasCompleteDecoder = HasCompleteDecoderBit ?
+ HasCompleteDecoderBit->getValue() : true;
+
+ OperandInfo OpInfo(Decoder, HasCompleteDecoder);
+ unsigned Base = ~0U;
+ unsigned Width = 0;
+ unsigned Offset = 0;
+
+ for (unsigned bi = 0; bi < Bits.getNumBits(); ++bi) {
+ VarInit *Var = nullptr;
+ VarBitInit *BI = dyn_cast<VarBitInit>(Bits.getBit(bi));
+ if (BI)
+ Var = dyn_cast<VarInit>(BI->getBitVar());
+ else
+ Var = dyn_cast<VarInit>(Bits.getBit(bi));
+
+ if (!Var) {
+ if (Base != ~0U) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = ~0U;
+ Width = 0;
+ Offset = 0;
+ }
+ continue;
+ }
+
+ if (Var->getName() != Op.second &&
+ Var->getName() != TiedNames[Op.second]) {
+ if (Base != ~0U) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = ~0U;
+ Width = 0;
+ Offset = 0;
+ }
+ continue;
+ }
+
+ if (Base == ~0U) {
+ Base = bi;
+ Width = 1;
+ Offset = BI ? BI->getBitNum() : 0;
+ } else if (BI && BI->getBitNum() != Offset + Width) {
+ OpInfo.addField(Base, Width, Offset);
+ Base = bi;
+ Width = 1;
+ Offset = BI->getBitNum();
+ } else {
+ ++Width;
+ }
+ }
+
+ if (Base != ~0U)
+ OpInfo.addField(Base, Width, Offset);
+
+ if (OpInfo.numFields() > 0)
+ InsnOperands.push_back(OpInfo);
+ }
+
+ Operands[Opc] = InsnOperands;
+
+#if 0
+ DEBUG({
+ // Dumps the instruction encoding bits.
+ dumpBits(errs(), Bits);
+
+ errs() << '\n';
+
+ // Dumps the list of operand info.
+ for (unsigned i = 0, e = CGI.Operands.size(); i != e; ++i) {
+ const CGIOperandList::OperandInfo &Info = CGI.Operands[i];
+ const std::string &OperandName = Info.Name;
+ const Record &OperandDef = *Info.Rec;
+
+ errs() << "\t" << OperandName << " (" << OperandDef.getName() << ")\n";
+ }
+ });
+#endif
+
+ return true;
+}
+
+// emitFieldFromInstruction - Emit the templated helper function
+// fieldFromInstruction().
+static void emitFieldFromInstruction(formatted_raw_ostream &OS) {
+ OS << "// Helper function for extracting fields from encoded instructions.\n"
+ << "template<typename InsnType>\n"
+ << "static InsnType fieldFromInstruction(InsnType insn, unsigned startBit,\n"
+ << " unsigned numBits) {\n"
+ << " assert(startBit + numBits <= (sizeof(InsnType)*8) &&\n"
+ << " \"Instruction field out of bounds!\");\n"
+ << " InsnType fieldMask;\n"
+ << " if (numBits == sizeof(InsnType)*8)\n"
+ << " fieldMask = (InsnType)(-1LL);\n"
+ << " else\n"
+ << " fieldMask = (((InsnType)1 << numBits) - 1) << startBit;\n"
+ << " return (insn & fieldMask) >> startBit;\n"
+ << "}\n\n";
+}
+
+// emitDecodeInstruction - Emit the templated helper function
+// decodeInstruction().
+static void emitDecodeInstruction(formatted_raw_ostream &OS) {
+ OS << "template<typename InsnType>\n"
+ << "static DecodeStatus decodeInstruction(const uint8_t DecodeTable[], MCInst &MI,\n"
+ << " InsnType insn, uint64_t Address,\n"
+ << " const void *DisAsm,\n"
+ << " const MCSubtargetInfo &STI) {\n"
+ << " const FeatureBitset& Bits = STI.getFeatureBits();\n"
+ << "\n"
+ << " const uint8_t *Ptr = DecodeTable;\n"
+ << " uint32_t CurFieldValue = 0;\n"
+ << " DecodeStatus S = MCDisassembler::Success;\n"
+ << " while (true) {\n"
+ << " ptrdiff_t Loc = Ptr - DecodeTable;\n"
+ << " switch (*Ptr) {\n"
+ << " default:\n"
+ << " errs() << Loc << \": Unexpected decode table opcode!\\n\";\n"
+ << " return MCDisassembler::Fail;\n"
+ << " case MCD::OPC_ExtractField: {\n"
+ << " unsigned Start = *++Ptr;\n"
+ << " unsigned Len = *++Ptr;\n"
+ << " ++Ptr;\n"
+ << " CurFieldValue = fieldFromInstruction(insn, Start, Len);\n"
+ << " DEBUG(dbgs() << Loc << \": OPC_ExtractField(\" << Start << \", \"\n"
+ << " << Len << \"): \" << CurFieldValue << \"\\n\");\n"
+ << " break;\n"
+ << " }\n"
+ << " case MCD::OPC_FilterValue: {\n"
+ << " // Decode the field value.\n"
+ << " unsigned Len;\n"
+ << " InsnType Val = decodeULEB128(++Ptr, &Len);\n"
+ << " Ptr += Len;\n"
+ << " // NumToSkip is a plain 16-bit integer.\n"
+ << " unsigned NumToSkip = *Ptr++;\n"
+ << " NumToSkip |= (*Ptr++) << 8;\n"
+ << "\n"
+ << " // Perform the filter operation.\n"
+ << " if (Val != CurFieldValue)\n"
+ << " Ptr += NumToSkip;\n"
+ << " DEBUG(dbgs() << Loc << \": OPC_FilterValue(\" << Val << \", \" << NumToSkip\n"
+ << " << \"): \" << ((Val != CurFieldValue) ? \"FAIL:\" : \"PASS:\")\n"
+ << " << \" continuing at \" << (Ptr - DecodeTable) << \"\\n\");\n"
+ << "\n"
+ << " break;\n"
+ << " }\n"
+ << " case MCD::OPC_CheckField: {\n"
+ << " unsigned Start = *++Ptr;\n"
+ << " unsigned Len = *++Ptr;\n"
+ << " InsnType FieldValue = fieldFromInstruction(insn, Start, Len);\n"
+ << " // Decode the field value.\n"
+ << " uint32_t ExpectedValue = decodeULEB128(++Ptr, &Len);\n"
+ << " Ptr += Len;\n"
+ << " // NumToSkip is a plain 16-bit integer.\n"
+ << " unsigned NumToSkip = *Ptr++;\n"
+ << " NumToSkip |= (*Ptr++) << 8;\n"
+ << "\n"
+ << " // If the actual and expected values don't match, skip.\n"
+ << " if (ExpectedValue != FieldValue)\n"
+ << " Ptr += NumToSkip;\n"
+ << " DEBUG(dbgs() << Loc << \": OPC_CheckField(\" << Start << \", \"\n"
+ << " << Len << \", \" << ExpectedValue << \", \" << NumToSkip\n"
+ << " << \"): FieldValue = \" << FieldValue << \", ExpectedValue = \"\n"
+ << " << ExpectedValue << \": \"\n"
+ << " << ((ExpectedValue == FieldValue) ? \"PASS\\n\" : \"FAIL\\n\"));\n"
+ << " break;\n"
+ << " }\n"
+ << " case MCD::OPC_CheckPredicate: {\n"
+ << " unsigned Len;\n"
+ << " // Decode the Predicate Index value.\n"
+ << " unsigned PIdx = decodeULEB128(++Ptr, &Len);\n"
+ << " Ptr += Len;\n"
+ << " // NumToSkip is a plain 16-bit integer.\n"
+ << " unsigned NumToSkip = *Ptr++;\n"
+ << " NumToSkip |= (*Ptr++) << 8;\n"
+ << " // Check the predicate.\n"
+ << " bool Pred;\n"
+ << " if (!(Pred = checkDecoderPredicate(PIdx, Bits)))\n"
+ << " Ptr += NumToSkip;\n"
+ << " (void)Pred;\n"
+ << " DEBUG(dbgs() << Loc << \": OPC_CheckPredicate(\" << PIdx << \"): \"\n"
+ << " << (Pred ? \"PASS\\n\" : \"FAIL\\n\"));\n"
+ << "\n"
+ << " break;\n"
+ << " }\n"
+ << " case MCD::OPC_Decode: {\n"
+ << " unsigned Len;\n"
+ << " // Decode the Opcode value.\n"
+ << " unsigned Opc = decodeULEB128(++Ptr, &Len);\n"
+ << " Ptr += Len;\n"
+ << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n"
+ << " Ptr += Len;\n"
+ << "\n"
+ << " MI.clear();\n"
+ << " MI.setOpcode(Opc);\n"
+ << " bool DecodeComplete;\n"
+ << " S = decodeToMCInst(S, DecodeIdx, insn, MI, Address, DisAsm, DecodeComplete);\n"
+ << " assert(DecodeComplete);\n"
+ << "\n"
+ << " DEBUG(dbgs() << Loc << \": OPC_Decode: opcode \" << Opc\n"
+ << " << \", using decoder \" << DecodeIdx << \": \"\n"
+ << " << (S != MCDisassembler::Fail ? \"PASS\" : \"FAIL\") << \"\\n\");\n"
+ << " return S;\n"
+ << " }\n"
+ << " case MCD::OPC_TryDecode: {\n"
+ << " unsigned Len;\n"
+ << " // Decode the Opcode value.\n"
+ << " unsigned Opc = decodeULEB128(++Ptr, &Len);\n"
+ << " Ptr += Len;\n"
+ << " unsigned DecodeIdx = decodeULEB128(Ptr, &Len);\n"
+ << " Ptr += Len;\n"
+ << " // NumToSkip is a plain 16-bit integer.\n"
+ << " unsigned NumToSkip = *Ptr++;\n"
+ << " NumToSkip |= (*Ptr++) << 8;\n"
+ << "\n"
+ << " // Perform the decode operation.\n"
+ << " MCInst TmpMI;\n"
+ << " TmpMI.setOpcode(Opc);\n"
+ << " bool DecodeComplete;\n"
+ << " S = decodeToMCInst(S, DecodeIdx, insn, TmpMI, Address, DisAsm, DecodeComplete);\n"
+ << " DEBUG(dbgs() << Loc << \": OPC_TryDecode: opcode \" << Opc\n"
+ << " << \", using decoder \" << DecodeIdx << \": \");\n"
+ << "\n"
+ << " if (DecodeComplete) {\n"
+ << " // Decoding complete.\n"
+ << " DEBUG(dbgs() << (S != MCDisassembler::Fail ? \"PASS\" : \"FAIL\") << \"\\n\");\n"
+ << " MI = TmpMI;\n"
+ << " return S;\n"
+ << " } else {\n"
+ << " assert(S == MCDisassembler::Fail);\n"
+ << " // If the decoding was incomplete, skip.\n"
+ << " Ptr += NumToSkip;\n"
+ << " DEBUG(dbgs() << \"FAIL: continuing at \" << (Ptr - DecodeTable) << \"\\n\");\n"
+ << " // Reset decode status. This also drops a SoftFail status that could be\n"
+ << " // set before the decode attempt.\n"
+ << " S = MCDisassembler::Success;\n"
+ << " }\n"
+ << " break;\n"
+ << " }\n"
+ << " case MCD::OPC_SoftFail: {\n"
+ << " // Decode the mask values.\n"
+ << " unsigned Len;\n"
+ << " InsnType PositiveMask = decodeULEB128(++Ptr, &Len);\n"
+ << " Ptr += Len;\n"
+ << " InsnType NegativeMask = decodeULEB128(Ptr, &Len);\n"
+ << " Ptr += Len;\n"
+ << " bool Fail = (insn & PositiveMask) || (~insn & NegativeMask);\n"
+ << " if (Fail)\n"
+ << " S = MCDisassembler::SoftFail;\n"
+ << " DEBUG(dbgs() << Loc << \": OPC_SoftFail: \" << (Fail ? \"FAIL\\n\":\"PASS\\n\"));\n"
+ << " break;\n"
+ << " }\n"
+ << " case MCD::OPC_Fail: {\n"
+ << " DEBUG(dbgs() << Loc << \": OPC_Fail\\n\");\n"
+ << " return MCDisassembler::Fail;\n"
+ << " }\n"
+ << " }\n"
+ << " }\n"
+ << " llvm_unreachable(\"bogosity detected in disassembler state machine!\");\n"
+ << "}\n\n";
+}
+
+// Emits disassembler code for instruction decoding.
+void FixedLenDecoderEmitter::run(raw_ostream &o) {
+ formatted_raw_ostream OS(o);
+ OS << "#include \"llvm/MC/MCInst.h\"\n";
+ OS << "#include \"llvm/Support/Debug.h\"\n";
+ OS << "#include \"llvm/Support/DataTypes.h\"\n";
+ OS << "#include \"llvm/Support/LEB128.h\"\n";
+ OS << "#include \"llvm/Support/raw_ostream.h\"\n";
+ OS << "#include <assert.h>\n";
+ OS << '\n';
+ OS << "namespace llvm {\n\n";
+
+ emitFieldFromInstruction(OS);
+
+ Target.reverseBitsForLittleEndianEncoding();
+
+ // Parameterize the decoders based on namespace and instruction width.
+ NumberedInstructions = Target.getInstructionsByEnumValue();
+ std::map<std::pair<std::string, unsigned>,
+ std::vector<unsigned>> OpcMap;
+ std::map<unsigned, std::vector<OperandInfo>> Operands;
+
+ for (unsigned i = 0; i < NumberedInstructions.size(); ++i) {
+ const CodeGenInstruction *Inst = NumberedInstructions[i];
+ const Record *Def = Inst->TheDef;
+ unsigned Size = Def->getValueAsInt("Size");
+ if (Def->getValueAsString("Namespace") == "TargetOpcode" ||
+ Def->getValueAsBit("isPseudo") ||
+ Def->getValueAsBit("isAsmParserOnly") ||
+ Def->getValueAsBit("isCodeGenOnly"))
+ continue;
+
+ std::string DecoderNamespace = Def->getValueAsString("DecoderNamespace");
+
+ if (Size) {
+ if (populateInstruction(Target, *Inst, i, Operands)) {
+ OpcMap[std::make_pair(DecoderNamespace, Size)].push_back(i);
+ }
+ }
+ }
+
+ DecoderTableInfo TableInfo;
+ for (const auto &Opc : OpcMap) {
+ // Emit the decoder for this namespace+width combination.
+ FilterChooser FC(NumberedInstructions, Opc.second, Operands,
+ 8*Opc.first.second, this);
+
+ // The decode table is cleared for each top level decoder function. The
+ // predicates and decoders themselves, however, are shared across all
+ // decoders to give more opportunities for uniqueing.
+ TableInfo.Table.clear();
+ TableInfo.FixupStack.clear();
+ TableInfo.Table.reserve(16384);
+ TableInfo.FixupStack.emplace_back();
+ FC.emitTableEntries(TableInfo);
+ // Any NumToSkip fixups in the top level scope can resolve to the
+ // OPC_Fail at the end of the table.
+ assert(TableInfo.FixupStack.size() == 1 && "fixup stack phasing error!");
+ // Resolve any NumToSkip fixups in the current scope.
+ resolveTableFixups(TableInfo.Table, TableInfo.FixupStack.back(),
+ TableInfo.Table.size());
+ TableInfo.FixupStack.clear();
+
+ TableInfo.Table.push_back(MCD::OPC_Fail);
+
+ // Print the table to the output stream.
+ emitTable(OS, TableInfo.Table, 0, FC.getBitWidth(), Opc.first.first);
+ OS.flush();
+ }
+
+ // Emit the predicate function.
+ emitPredicateFunction(OS, TableInfo.Predicates, 0);
+
+ // Emit the decoder function.
+ emitDecoderFunction(OS, TableInfo.Decoders, 0);
+
+ // Emit the main entry point for the decoder, decodeInstruction().
+ emitDecodeInstruction(OS);
+
+ OS << "\n} // End llvm namespace\n";
+}
+
+namespace llvm {
+
+void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
+ const std::string &PredicateNamespace,
+ const std::string &GPrefix,
+ const std::string &GPostfix, const std::string &ROK,
+ const std::string &RFail, const std::string &L) {
+ FixedLenDecoderEmitter(RK, PredicateNamespace, GPrefix, GPostfix,
+ ROK, RFail, L).run(OS);
+}
+
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp b/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp
new file mode 100644
index 000000000000..7acc65e349ea
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/GlobalISelEmitter.cpp
@@ -0,0 +1,1762 @@
+//===- GlobalISelEmitter.cpp - Generate an instruction selector -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// This tablegen backend emits code for use by the GlobalISel instruction
+/// selector. See include/llvm/CodeGen/TargetGlobalISel.td.
+///
+/// This file analyzes the patterns recognized by the SelectionDAGISel tablegen
+/// backend, filters out the ones that are unsupported, maps
+/// SelectionDAG-specific constructs to their GlobalISel counterpart
+/// (when applicable: MVT to LLT; SDNode to generic Instruction).
+///
+/// Not all patterns are supported: pass the tablegen invocation
+/// "-warn-on-skipped-patterns" to emit a warning when a pattern is skipped,
+/// as well as why.
+///
+/// The generated file defines a single method:
+/// bool <Target>InstructionSelector::selectImpl(MachineInstr &I) const;
+/// intended to be used in InstructionSelector::select as the first-step
+/// selector for the patterns that don't require complex C++.
+///
+/// FIXME: We'll probably want to eventually define a base
+/// "TargetGenInstructionSelector" class.
+///
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenDAGPatterns.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/LowLevelTypeImpl.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <string>
+#include <numeric>
+using namespace llvm;
+
+#define DEBUG_TYPE "gisel-emitter"
+
+STATISTIC(NumPatternTotal, "Total number of patterns");
+STATISTIC(NumPatternImported, "Number of patterns imported from SelectionDAG");
+STATISTIC(NumPatternImportsSkipped, "Number of SelectionDAG imports skipped");
+STATISTIC(NumPatternEmitted, "Number of patterns emitted");
+
+cl::OptionCategory GlobalISelEmitterCat("Options for -gen-global-isel");
+
+static cl::opt<bool> WarnOnSkippedPatterns(
+ "warn-on-skipped-patterns",
+ cl::desc("Explain why a pattern was skipped for inclusion "
+ "in the GlobalISel selector"),
+ cl::init(false), cl::cat(GlobalISelEmitterCat));
+
+namespace {
+//===- Helper functions ---------------------------------------------------===//
+
+/// This class stands in for LLT wherever we want to tablegen-erate an
+/// equivalent at compiler run-time.
+class LLTCodeGen {
+private:
+ LLT Ty;
+
+public:
+ LLTCodeGen(const LLT &Ty) : Ty(Ty) {}
+
+ void emitCxxConstructorCall(raw_ostream &OS) const {
+ if (Ty.isScalar()) {
+ OS << "LLT::scalar(" << Ty.getSizeInBits() << ")";
+ return;
+ }
+ if (Ty.isVector()) {
+ OS << "LLT::vector(" << Ty.getNumElements() << ", " << Ty.getSizeInBits()
+ << ")";
+ return;
+ }
+ llvm_unreachable("Unhandled LLT");
+ }
+
+ const LLT &get() const { return Ty; }
+};
+
+class InstructionMatcher;
+class OperandPlaceholder {
+private:
+ enum PlaceholderKind {
+ OP_MatchReference,
+ OP_Temporary,
+ } Kind;
+
+ struct MatchReferenceData {
+ InstructionMatcher *InsnMatcher;
+ StringRef InsnVarName;
+ StringRef SymbolicName;
+ };
+
+ struct TemporaryData {
+ unsigned OpIdx;
+ };
+
+ union {
+ struct MatchReferenceData MatchReference;
+ struct TemporaryData Temporary;
+ };
+
+ OperandPlaceholder(PlaceholderKind Kind) : Kind(Kind) {}
+
+public:
+ ~OperandPlaceholder() {}
+
+ static OperandPlaceholder
+ CreateMatchReference(InstructionMatcher *InsnMatcher,
+ StringRef InsnVarName, StringRef SymbolicName) {
+ OperandPlaceholder Result(OP_MatchReference);
+ Result.MatchReference.InsnMatcher = InsnMatcher;
+ Result.MatchReference.InsnVarName = InsnVarName;
+ Result.MatchReference.SymbolicName = SymbolicName;
+ return Result;
+ }
+
+ static OperandPlaceholder CreateTemporary(unsigned OpIdx) {
+ OperandPlaceholder Result(OP_Temporary);
+ Result.Temporary.OpIdx = OpIdx;
+ return Result;
+ }
+
+ void emitCxxValueExpr(raw_ostream &OS) const;
+};
+
+/// Convert an MVT to an equivalent LLT if possible, or the invalid LLT() for
+/// MVTs that don't map cleanly to an LLT (e.g., iPTR, *any, ...).
+static Optional<LLTCodeGen> MVTToLLT(MVT::SimpleValueType SVT) {
+ MVT VT(SVT);
+ if (VT.isVector() && VT.getVectorNumElements() != 1)
+ return LLTCodeGen(LLT::vector(VT.getVectorNumElements(), VT.getScalarSizeInBits()));
+ if (VT.isInteger() || VT.isFloatingPoint())
+ return LLTCodeGen(LLT::scalar(VT.getSizeInBits()));
+ return None;
+}
+
+static std::string explainPredicates(const TreePatternNode *N) {
+ std::string Explanation = "";
+ StringRef Separator = "";
+ for (const auto &P : N->getPredicateFns()) {
+ Explanation +=
+ (Separator + P.getOrigPatFragRecord()->getRecord()->getName()).str();
+ if (P.isAlwaysTrue())
+ Explanation += " always-true";
+ if (P.isImmediatePattern())
+ Explanation += " immediate";
+ }
+ return Explanation;
+}
+
+static std::string explainRulePredicates(const ArrayRef<Init *> Predicates) {
+ std::string Explanation = "";
+ StringRef Separator = "";
+ for (const auto *P : Predicates) {
+ Explanation += Separator;
+
+ if (const DefInit *PDef = dyn_cast<DefInit>(P)) {
+ Explanation += PDef->getDef()->getName();
+ } else
+ Explanation += "<unknown>";
+ }
+ return Explanation;
+}
+
+std::string explainOperator(Record *Operator) {
+ if (Operator->isSubClassOf("SDNode"))
+ return " (" + Operator->getValueAsString("Opcode") + ")";
+
+ if (Operator->isSubClassOf("Intrinsic"))
+ return (" (Operator is an Intrinsic, " + Operator->getName() + ")").str();
+
+ return " (Operator not understood)";
+}
+
+/// Helper function to let the emitter report skip reason error messages.
+static Error failedImport(const Twine &Reason) {
+ return make_error<StringError>(Reason, inconvertibleErrorCode());
+}
+
+static Error isTrivialOperatorNode(const TreePatternNode *N) {
+ std::string Explanation = "";
+ std::string Separator = "";
+ if (N->isLeaf()) {
+ Explanation = "Is a leaf";
+ Separator = ", ";
+ }
+
+ if (N->hasAnyPredicate()) {
+ Explanation = Separator + "Has a predicate (" + explainPredicates(N) + ")";
+ Separator = ", ";
+ }
+
+ if (N->getTransformFn()) {
+ Explanation += Separator + "Has a transform function";
+ Separator = ", ";
+ }
+
+ if (!N->isLeaf() && !N->hasAnyPredicate() && !N->getTransformFn())
+ return Error::success();
+
+ return failedImport(Explanation);
+}
+
+//===- Matchers -----------------------------------------------------------===//
+
+class OperandMatcher;
+class MatchAction;
+
+/// Generates code to check that a match rule matches.
+class RuleMatcher {
+ /// A list of matchers that all need to succeed for the current rule to match.
+ /// FIXME: This currently supports a single match position but could be
+ /// extended to support multiple positions to support div/rem fusion or
+ /// load-multiple instructions.
+ std::vector<std::unique_ptr<InstructionMatcher>> Matchers;
+
+ /// A list of actions that need to be taken when all predicates in this rule
+ /// have succeeded.
+ std::vector<std::unique_ptr<MatchAction>> Actions;
+
+ /// A map of instruction matchers to the local variables created by
+ /// emitCxxCaptureStmts().
+ std::map<const InstructionMatcher *, std::string> InsnVariableNames;
+
+ /// ID for the next instruction variable defined with defineInsnVar()
+ unsigned NextInsnVarID;
+
+public:
+ RuleMatcher()
+ : Matchers(), Actions(), InsnVariableNames(), NextInsnVarID(0) {}
+ RuleMatcher(RuleMatcher &&Other) = default;
+ RuleMatcher &operator=(RuleMatcher &&Other) = default;
+
+ InstructionMatcher &addInstructionMatcher();
+
+ template <class Kind, class... Args> Kind &addAction(Args &&... args);
+
+ std::string defineInsnVar(raw_ostream &OS, const InstructionMatcher &Matcher,
+ StringRef Value);
+ StringRef getInsnVarName(const InstructionMatcher &InsnMatcher) const;
+
+ void emitCxxCapturedInsnList(raw_ostream &OS);
+ void emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr);
+
+ void emit(raw_ostream &OS);
+
+ /// Compare the priority of this object and B.
+ ///
+ /// Returns true if this object is more important than B.
+ bool isHigherPriorityThan(const RuleMatcher &B) const;
+
+ /// Report the maximum number of temporary operands needed by the rule
+ /// matcher.
+ unsigned countTemporaryOperands() const;
+};
+
+template <class PredicateTy> class PredicateListMatcher {
+private:
+ typedef std::vector<std::unique_ptr<PredicateTy>> PredicateVec;
+ PredicateVec Predicates;
+
+public:
+ /// Construct a new operand predicate and add it to the matcher.
+ template <class Kind, class... Args>
+ Kind &addPredicate(Args&&... args) {
+ Predicates.emplace_back(
+ llvm::make_unique<Kind>(std::forward<Args>(args)...));
+ return *static_cast<Kind *>(Predicates.back().get());
+ }
+
+ typename PredicateVec::const_iterator predicates_begin() const { return Predicates.begin(); }
+ typename PredicateVec::const_iterator predicates_end() const { return Predicates.end(); }
+ iterator_range<typename PredicateVec::const_iterator> predicates() const {
+ return make_range(predicates_begin(), predicates_end());
+ }
+ typename PredicateVec::size_type predicates_size() const { return Predicates.size(); }
+
+ /// Emit a C++ expression that tests whether all the predicates are met.
+ template <class... Args>
+ void emitCxxPredicateListExpr(raw_ostream &OS, Args &&... args) const {
+ if (Predicates.empty()) {
+ OS << "true";
+ return;
+ }
+
+ StringRef Separator = "";
+ for (const auto &Predicate : predicates()) {
+ OS << Separator << "(";
+ Predicate->emitCxxPredicateExpr(OS, std::forward<Args>(args)...);
+ OS << ")";
+ Separator = " &&\n";
+ }
+ }
+};
+
+/// Generates code to check a predicate of an operand.
+///
+/// Typical predicates include:
+/// * Operand is a particular register.
+/// * Operand is assigned a particular register bank.
+/// * Operand is an MBB.
+class OperandPredicateMatcher {
+public:
+ /// This enum is used for RTTI and also defines the priority that is given to
+ /// the predicate when generating the matcher code. Kinds with higher priority
+ /// must be tested first.
+ ///
+ /// The relative priority of OPM_LLT, OPM_RegBank, and OPM_MBB do not matter
+ /// but OPM_Int must have priority over OPM_RegBank since constant integers
+ /// are represented by a virtual register defined by a G_CONSTANT instruction.
+ enum PredicateKind {
+ OPM_ComplexPattern,
+ OPM_Instruction,
+ OPM_Int,
+ OPM_LLT,
+ OPM_RegBank,
+ OPM_MBB,
+ };
+
+protected:
+ PredicateKind Kind;
+
+public:
+ OperandPredicateMatcher(PredicateKind Kind) : Kind(Kind) {}
+ virtual ~OperandPredicateMatcher() {}
+
+ PredicateKind getKind() const { return Kind; }
+
+ /// Return the OperandMatcher for the specified operand or nullptr if there
+ /// isn't one by that name in this operand predicate matcher.
+ ///
+ /// InstructionOperandMatcher is the only subclass that can return non-null
+ /// for this.
+ virtual Optional<const OperandMatcher *>
+ getOptionalOperand(StringRef SymbolicName) const {
+ assert(!SymbolicName.empty() && "Cannot lookup unnamed operand");
+ return None;
+ }
+
+ /// Emit C++ statements to capture instructions into local variables.
+ ///
+ /// Only InstructionOperandMatcher needs to do anything for this method.
+ virtual void emitCxxCaptureStmts(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef Expr) const {}
+
+ /// Emit a C++ expression that checks the predicate for the given operand.
+ virtual void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef OperandExpr) const = 0;
+
+ /// Compare the priority of this object and B.
+ ///
+ /// Returns true if this object is more important than B.
+ virtual bool isHigherPriorityThan(const OperandPredicateMatcher &B) const {
+ return Kind < B.Kind;
+ };
+
+ /// Report the maximum number of temporary operands needed by the predicate
+ /// matcher.
+ virtual unsigned countTemporaryOperands() const { return 0; }
+};
+
+/// Generates code to check that an operand is a particular LLT.
+class LLTOperandMatcher : public OperandPredicateMatcher {
+protected:
+ LLTCodeGen Ty;
+
+public:
+ LLTOperandMatcher(const LLTCodeGen &Ty)
+ : OperandPredicateMatcher(OPM_LLT), Ty(Ty) {}
+
+ static bool classof(const OperandPredicateMatcher *P) {
+ return P->getKind() == OPM_LLT;
+ }
+
+ void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef OperandExpr) const override {
+ OS << "MRI.getType(" << OperandExpr << ".getReg()) == (";
+ Ty.emitCxxConstructorCall(OS);
+ OS << ")";
+ }
+};
+
+/// Generates code to check that an operand is a particular target constant.
+class ComplexPatternOperandMatcher : public OperandPredicateMatcher {
+protected:
+ const OperandMatcher &Operand;
+ const Record &TheDef;
+
+ unsigned getNumOperands() const {
+ return TheDef.getValueAsDag("Operands")->getNumArgs();
+ }
+
+ unsigned getAllocatedTemporariesBaseID() const;
+
+public:
+ ComplexPatternOperandMatcher(const OperandMatcher &Operand,
+ const Record &TheDef)
+ : OperandPredicateMatcher(OPM_ComplexPattern), Operand(Operand),
+ TheDef(TheDef) {}
+
+ static bool classof(const OperandPredicateMatcher *P) {
+ return P->getKind() == OPM_ComplexPattern;
+ }
+
+ void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef OperandExpr) const override {
+ OS << TheDef.getValueAsString("MatcherFn") << "(" << OperandExpr;
+ for (unsigned I = 0; I < getNumOperands(); ++I) {
+ OS << ", ";
+ OperandPlaceholder::CreateTemporary(getAllocatedTemporariesBaseID() + I)
+ .emitCxxValueExpr(OS);
+ }
+ OS << ")";
+ }
+
+ unsigned countTemporaryOperands() const override {
+ return getNumOperands();
+ }
+};
+
+/// Generates code to check that an operand is in a particular register bank.
+class RegisterBankOperandMatcher : public OperandPredicateMatcher {
+protected:
+ const CodeGenRegisterClass &RC;
+
+public:
+ RegisterBankOperandMatcher(const CodeGenRegisterClass &RC)
+ : OperandPredicateMatcher(OPM_RegBank), RC(RC) {}
+
+ static bool classof(const OperandPredicateMatcher *P) {
+ return P->getKind() == OPM_RegBank;
+ }
+
+ void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef OperandExpr) const override {
+ OS << "(&RBI.getRegBankFromRegClass(" << RC.getQualifiedName()
+ << "RegClass) == RBI.getRegBank(" << OperandExpr
+ << ".getReg(), MRI, TRI))";
+ }
+};
+
+/// Generates code to check that an operand is a basic block.
+class MBBOperandMatcher : public OperandPredicateMatcher {
+public:
+ MBBOperandMatcher() : OperandPredicateMatcher(OPM_MBB) {}
+
+ static bool classof(const OperandPredicateMatcher *P) {
+ return P->getKind() == OPM_MBB;
+ }
+
+ void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef OperandExpr) const override {
+ OS << OperandExpr << ".isMBB()";
+ }
+};
+
+/// Generates code to check that an operand is a particular int.
+class IntOperandMatcher : public OperandPredicateMatcher {
+protected:
+ int64_t Value;
+
+public:
+ IntOperandMatcher(int64_t Value)
+ : OperandPredicateMatcher(OPM_Int), Value(Value) {}
+
+ static bool classof(const OperandPredicateMatcher *P) {
+ return P->getKind() == OPM_Int;
+ }
+
+ void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef OperandExpr) const override {
+ OS << "isOperandImmEqual(" << OperandExpr << ", " << Value << ", MRI)";
+ }
+};
+
+/// Generates code to check that a set of predicates match for a particular
+/// operand.
+class OperandMatcher : public PredicateListMatcher<OperandPredicateMatcher> {
+protected:
+ InstructionMatcher &Insn;
+ unsigned OpIdx;
+ std::string SymbolicName;
+
+ /// The index of the first temporary variable allocated to this operand. The
+ /// number of allocated temporaries can be found with
+ /// countTemporaryOperands().
+ unsigned AllocatedTemporariesBaseID;
+
+public:
+ OperandMatcher(InstructionMatcher &Insn, unsigned OpIdx,
+ const std::string &SymbolicName,
+ unsigned AllocatedTemporariesBaseID)
+ : Insn(Insn), OpIdx(OpIdx), SymbolicName(SymbolicName),
+ AllocatedTemporariesBaseID(AllocatedTemporariesBaseID) {}
+
+ bool hasSymbolicName() const { return !SymbolicName.empty(); }
+ const StringRef getSymbolicName() const { return SymbolicName; }
+ void setSymbolicName(StringRef Name) {
+ assert(SymbolicName.empty() && "Operand already has a symbolic name");
+ SymbolicName = Name;
+ }
+ unsigned getOperandIndex() const { return OpIdx; }
+
+ std::string getOperandExpr(StringRef InsnVarName) const {
+ return (InsnVarName + ".getOperand(" + llvm::to_string(OpIdx) + ")").str();
+ }
+
+ Optional<const OperandMatcher *>
+ getOptionalOperand(StringRef DesiredSymbolicName) const {
+ assert(!DesiredSymbolicName.empty() && "Cannot lookup unnamed operand");
+ if (DesiredSymbolicName == SymbolicName)
+ return this;
+ for (const auto &OP : predicates()) {
+ const auto &MaybeOperand = OP->getOptionalOperand(DesiredSymbolicName);
+ if (MaybeOperand.hasValue())
+ return MaybeOperand.getValue();
+ }
+ return None;
+ }
+
+ InstructionMatcher &getInstructionMatcher() const { return Insn; }
+
+ /// Emit C++ statements to capture instructions into local variables.
+ void emitCxxCaptureStmts(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef OperandExpr) const {
+ for (const auto &Predicate : predicates())
+ Predicate->emitCxxCaptureStmts(OS, Rule, OperandExpr);
+ }
+
+ /// Emit a C++ expression that tests whether the instruction named in
+ /// InsnVarName matches all the predicate and all the operands.
+ void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef InsnVarName) const {
+ OS << "(/* ";
+ if (SymbolicName.empty())
+ OS << "Operand " << OpIdx;
+ else
+ OS << SymbolicName;
+ OS << " */ ";
+ emitCxxPredicateListExpr(OS, Rule, getOperandExpr(InsnVarName));
+ OS << ")";
+ }
+
+ /// Compare the priority of this object and B.
+ ///
+ /// Returns true if this object is more important than B.
+ bool isHigherPriorityThan(const OperandMatcher &B) const {
+ // Operand matchers involving more predicates have higher priority.
+ if (predicates_size() > B.predicates_size())
+ return true;
+ if (predicates_size() < B.predicates_size())
+ return false;
+
+ // This assumes that predicates are added in a consistent order.
+ for (const auto &Predicate : zip(predicates(), B.predicates())) {
+ if (std::get<0>(Predicate)->isHigherPriorityThan(*std::get<1>(Predicate)))
+ return true;
+ if (std::get<1>(Predicate)->isHigherPriorityThan(*std::get<0>(Predicate)))
+ return false;
+ }
+
+ return false;
+ };
+
+ /// Report the maximum number of temporary operands needed by the operand
+ /// matcher.
+ unsigned countTemporaryOperands() const {
+ return std::accumulate(
+ predicates().begin(), predicates().end(), 0,
+ [](unsigned A,
+ const std::unique_ptr<OperandPredicateMatcher> &Predicate) {
+ return A + Predicate->countTemporaryOperands();
+ });
+ }
+
+ unsigned getAllocatedTemporariesBaseID() const {
+ return AllocatedTemporariesBaseID;
+ }
+};
+
+unsigned ComplexPatternOperandMatcher::getAllocatedTemporariesBaseID() const {
+ return Operand.getAllocatedTemporariesBaseID();
+}
+
+/// Generates code to check a predicate on an instruction.
+///
+/// Typical predicates include:
+/// * The opcode of the instruction is a particular value.
+/// * The nsw/nuw flag is/isn't set.
+class InstructionPredicateMatcher {
+protected:
+ /// This enum is used for RTTI and also defines the priority that is given to
+ /// the predicate when generating the matcher code. Kinds with higher priority
+ /// must be tested first.
+ enum PredicateKind {
+ IPM_Opcode,
+ };
+
+ PredicateKind Kind;
+
+public:
+ InstructionPredicateMatcher(PredicateKind Kind) : Kind(Kind) {}
+ virtual ~InstructionPredicateMatcher() {}
+
+ PredicateKind getKind() const { return Kind; }
+
+ /// Emit a C++ expression that tests whether the instruction named in
+ /// InsnVarName matches the predicate.
+ virtual void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef InsnVarName) const = 0;
+
+ /// Compare the priority of this object and B.
+ ///
+ /// Returns true if this object is more important than B.
+ virtual bool isHigherPriorityThan(const InstructionPredicateMatcher &B) const {
+ return Kind < B.Kind;
+ };
+
+ /// Report the maximum number of temporary operands needed by the predicate
+ /// matcher.
+ virtual unsigned countTemporaryOperands() const { return 0; }
+};
+
+/// Generates code to check the opcode of an instruction.
+class InstructionOpcodeMatcher : public InstructionPredicateMatcher {
+protected:
+ const CodeGenInstruction *I;
+
+public:
+ InstructionOpcodeMatcher(const CodeGenInstruction *I)
+ : InstructionPredicateMatcher(IPM_Opcode), I(I) {}
+
+ static bool classof(const InstructionPredicateMatcher *P) {
+ return P->getKind() == IPM_Opcode;
+ }
+
+ void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef InsnVarName) const override {
+ OS << InsnVarName << ".getOpcode() == " << I->Namespace
+ << "::" << I->TheDef->getName();
+ }
+
+ /// Compare the priority of this object and B.
+ ///
+ /// Returns true if this object is more important than B.
+ bool isHigherPriorityThan(const InstructionPredicateMatcher &B) const override {
+ if (InstructionPredicateMatcher::isHigherPriorityThan(B))
+ return true;
+ if (B.InstructionPredicateMatcher::isHigherPriorityThan(*this))
+ return false;
+
+ // Prioritize opcodes for cosmetic reasons in the generated source. Although
+ // this is cosmetic at the moment, we may want to drive a similar ordering
+ // using instruction frequency information to improve compile time.
+ if (const InstructionOpcodeMatcher *BO =
+ dyn_cast<InstructionOpcodeMatcher>(&B))
+ return I->TheDef->getName() < BO->I->TheDef->getName();
+
+ return false;
+ };
+};
+
+/// Generates code to check that a set of predicates and operands match for a
+/// particular instruction.
+///
+/// Typical predicates include:
+/// * Has a specific opcode.
+/// * Has an nsw/nuw flag or doesn't.
+class InstructionMatcher
+ : public PredicateListMatcher<InstructionPredicateMatcher> {
+protected:
+ typedef std::vector<std::unique_ptr<OperandMatcher>> OperandVec;
+
+ /// The operands to match. All rendered operands must be present even if the
+ /// condition is always true.
+ OperandVec Operands;
+
+public:
+ /// Add an operand to the matcher.
+ OperandMatcher &addOperand(unsigned OpIdx, const std::string &SymbolicName,
+ unsigned AllocatedTemporariesBaseID) {
+ Operands.emplace_back(new OperandMatcher(*this, OpIdx, SymbolicName,
+ AllocatedTemporariesBaseID));
+ return *Operands.back();
+ }
+
+ OperandMatcher &getOperand(unsigned OpIdx) {
+ auto I = std::find_if(Operands.begin(), Operands.end(),
+ [&OpIdx](const std::unique_ptr<OperandMatcher> &X) {
+ return X->getOperandIndex() == OpIdx;
+ });
+ if (I != Operands.end())
+ return **I;
+ llvm_unreachable("Failed to lookup operand");
+ }
+
+ Optional<const OperandMatcher *>
+ getOptionalOperand(StringRef SymbolicName) const {
+ assert(!SymbolicName.empty() && "Cannot lookup unnamed operand");
+ for (const auto &Operand : Operands) {
+ const auto &OM = Operand->getOptionalOperand(SymbolicName);
+ if (OM.hasValue())
+ return OM.getValue();
+ }
+ return None;
+ }
+
+ const OperandMatcher &getOperand(StringRef SymbolicName) const {
+ Optional<const OperandMatcher *>OM = getOptionalOperand(SymbolicName);
+ if (OM.hasValue())
+ return *OM.getValue();
+ llvm_unreachable("Failed to lookup operand");
+ }
+
+ unsigned getNumOperands() const { return Operands.size(); }
+ OperandVec::iterator operands_begin() { return Operands.begin(); }
+ OperandVec::iterator operands_end() { return Operands.end(); }
+ iterator_range<OperandVec::iterator> operands() {
+ return make_range(operands_begin(), operands_end());
+ }
+ OperandVec::const_iterator operands_begin() const { return Operands.begin(); }
+ OperandVec::const_iterator operands_end() const { return Operands.end(); }
+ iterator_range<OperandVec::const_iterator> operands() const {
+ return make_range(operands_begin(), operands_end());
+ }
+
+ /// Emit C++ statements to check the shape of the match and capture
+ /// instructions into local variables.
+ void emitCxxCaptureStmts(raw_ostream &OS, RuleMatcher &Rule, StringRef Expr) {
+ OS << "if (" << Expr << ".getNumOperands() < " << getNumOperands() << ")\n"
+ << " return false;\n";
+ for (const auto &Operand : Operands) {
+ Operand->emitCxxCaptureStmts(OS, Rule, Operand->getOperandExpr(Expr));
+ }
+ }
+
+ /// Emit a C++ expression that tests whether the instruction named in
+ /// InsnVarName matches all the predicates and all the operands.
+ void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef InsnVarName) const {
+ emitCxxPredicateListExpr(OS, Rule, InsnVarName);
+ for (const auto &Operand : Operands) {
+ OS << " &&\n(";
+ Operand->emitCxxPredicateExpr(OS, Rule, InsnVarName);
+ OS << ")";
+ }
+ }
+
+ /// Compare the priority of this object and B.
+ ///
+ /// Returns true if this object is more important than B.
+ bool isHigherPriorityThan(const InstructionMatcher &B) const {
+ // Instruction matchers involving more operands have higher priority.
+ if (Operands.size() > B.Operands.size())
+ return true;
+ if (Operands.size() < B.Operands.size())
+ return false;
+
+ for (const auto &Predicate : zip(predicates(), B.predicates())) {
+ if (std::get<0>(Predicate)->isHigherPriorityThan(*std::get<1>(Predicate)))
+ return true;
+ if (std::get<1>(Predicate)->isHigherPriorityThan(*std::get<0>(Predicate)))
+ return false;
+ }
+
+ for (const auto &Operand : zip(Operands, B.Operands)) {
+ if (std::get<0>(Operand)->isHigherPriorityThan(*std::get<1>(Operand)))
+ return true;
+ if (std::get<1>(Operand)->isHigherPriorityThan(*std::get<0>(Operand)))
+ return false;
+ }
+
+ return false;
+ };
+
+ /// Report the maximum number of temporary operands needed by the instruction
+ /// matcher.
+ unsigned countTemporaryOperands() const {
+ return std::accumulate(predicates().begin(), predicates().end(), 0,
+ [](unsigned A,
+ const std::unique_ptr<InstructionPredicateMatcher>
+ &Predicate) {
+ return A + Predicate->countTemporaryOperands();
+ }) +
+ std::accumulate(
+ Operands.begin(), Operands.end(), 0,
+ [](unsigned A, const std::unique_ptr<OperandMatcher> &Operand) {
+ return A + Operand->countTemporaryOperands();
+ });
+ }
+};
+
+/// Generates code to check that the operand is a register defined by an
+/// instruction that matches the given instruction matcher.
+///
+/// For example, the pattern:
+/// (set $dst, (G_MUL (G_ADD $src1, $src2), $src3))
+/// would use an InstructionOperandMatcher for operand 1 of the G_MUL to match
+/// the:
+/// (G_ADD $src1, $src2)
+/// subpattern.
+class InstructionOperandMatcher : public OperandPredicateMatcher {
+protected:
+ std::unique_ptr<InstructionMatcher> InsnMatcher;
+
+public:
+ InstructionOperandMatcher()
+ : OperandPredicateMatcher(OPM_Instruction),
+ InsnMatcher(new InstructionMatcher()) {}
+
+ static bool classof(const OperandPredicateMatcher *P) {
+ return P->getKind() == OPM_Instruction;
+ }
+
+ InstructionMatcher &getInsnMatcher() const { return *InsnMatcher; }
+
+ Optional<const OperandMatcher *>
+ getOptionalOperand(StringRef SymbolicName) const override {
+ assert(!SymbolicName.empty() && "Cannot lookup unnamed operand");
+ return InsnMatcher->getOptionalOperand(SymbolicName);
+ }
+
+ void emitCxxCaptureStmts(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef OperandExpr) const override {
+ OS << "if (!" << OperandExpr + ".isReg())\n"
+ << " return false;\n";
+ std::string InsnVarName = Rule.defineInsnVar(
+ OS, *InsnMatcher,
+ ("*MRI.getVRegDef(" + OperandExpr + ".getReg())").str());
+ InsnMatcher->emitCxxCaptureStmts(OS, Rule, InsnVarName);
+ }
+
+ void emitCxxPredicateExpr(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef OperandExpr) const override {
+ OperandExpr = Rule.getInsnVarName(*InsnMatcher);
+ OS << "(";
+ InsnMatcher->emitCxxPredicateExpr(OS, Rule, OperandExpr);
+ OS << ")\n";
+ }
+};
+
+//===- Actions ------------------------------------------------------------===//
+void OperandPlaceholder::emitCxxValueExpr(raw_ostream &OS) const {
+ switch (Kind) {
+ case OP_MatchReference:
+ OS << MatchReference.InsnMatcher->getOperand(MatchReference.SymbolicName)
+ .getOperandExpr(MatchReference.InsnVarName);
+ break;
+ case OP_Temporary:
+ OS << "TempOp" << Temporary.OpIdx;
+ break;
+ }
+}
+
+class OperandRenderer {
+public:
+ enum RendererKind { OR_Copy, OR_Imm, OR_Register, OR_ComplexPattern };
+
+protected:
+ RendererKind Kind;
+
+public:
+ OperandRenderer(RendererKind Kind) : Kind(Kind) {}
+ virtual ~OperandRenderer() {}
+
+ RendererKind getKind() const { return Kind; }
+
+ virtual void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const = 0;
+};
+
+/// A CopyRenderer emits code to copy a single operand from an existing
+/// instruction to the one being built.
+class CopyRenderer : public OperandRenderer {
+protected:
+ /// The matcher for the instruction that this operand is copied from.
+ /// This provides the facility for looking up an a operand by it's name so
+ /// that it can be used as a source for the instruction being built.
+ const InstructionMatcher &Matched;
+ /// The name of the operand.
+ const StringRef SymbolicName;
+
+public:
+ CopyRenderer(const InstructionMatcher &Matched, StringRef SymbolicName)
+ : OperandRenderer(OR_Copy), Matched(Matched), SymbolicName(SymbolicName) {
+ }
+
+ static bool classof(const OperandRenderer *R) {
+ return R->getKind() == OR_Copy;
+ }
+
+ const StringRef getSymbolicName() const { return SymbolicName; }
+
+ void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
+ const OperandMatcher &Operand = Matched.getOperand(SymbolicName);
+ StringRef InsnVarName =
+ Rule.getInsnVarName(Operand.getInstructionMatcher());
+ std::string OperandExpr = Operand.getOperandExpr(InsnVarName);
+ OS << " MIB.add(" << OperandExpr << "/*" << SymbolicName << "*/);\n";
+ }
+};
+
+/// Adds a specific physical register to the instruction being built.
+/// This is typically useful for WZR/XZR on AArch64.
+class AddRegisterRenderer : public OperandRenderer {
+protected:
+ const Record *RegisterDef;
+
+public:
+ AddRegisterRenderer(const Record *RegisterDef)
+ : OperandRenderer(OR_Register), RegisterDef(RegisterDef) {}
+
+ static bool classof(const OperandRenderer *R) {
+ return R->getKind() == OR_Register;
+ }
+
+ void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
+ OS << " MIB.addReg(" << RegisterDef->getValueAsString("Namespace")
+ << "::" << RegisterDef->getName() << ");\n";
+ }
+};
+
+/// Adds a specific immediate to the instruction being built.
+class ImmRenderer : public OperandRenderer {
+protected:
+ int64_t Imm;
+
+public:
+ ImmRenderer(int64_t Imm)
+ : OperandRenderer(OR_Imm), Imm(Imm) {}
+
+ static bool classof(const OperandRenderer *R) {
+ return R->getKind() == OR_Imm;
+ }
+
+ void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
+ OS << " MIB.addImm(" << Imm << ");\n";
+ }
+};
+
+class RenderComplexPatternOperand : public OperandRenderer {
+private:
+ const Record &TheDef;
+ std::vector<OperandPlaceholder> Sources;
+
+ unsigned getNumOperands() const {
+ return TheDef.getValueAsDag("Operands")->getNumArgs();
+ }
+
+public:
+ RenderComplexPatternOperand(const Record &TheDef,
+ const ArrayRef<OperandPlaceholder> Sources)
+ : OperandRenderer(OR_ComplexPattern), TheDef(TheDef), Sources(Sources) {}
+
+ static bool classof(const OperandRenderer *R) {
+ return R->getKind() == OR_ComplexPattern;
+ }
+
+ void emitCxxRenderStmts(raw_ostream &OS, RuleMatcher &Rule) const override {
+ assert(Sources.size() == getNumOperands() && "Inconsistent number of operands");
+ for (const auto &Source : Sources) {
+ OS << "MIB.add(";
+ Source.emitCxxValueExpr(OS);
+ OS << ");\n";
+ }
+ }
+};
+
+/// An action taken when all Matcher predicates succeeded for a parent rule.
+///
+/// Typical actions include:
+/// * Changing the opcode of an instruction.
+/// * Adding an operand to an instruction.
+class MatchAction {
+public:
+ virtual ~MatchAction() {}
+
+ /// Emit the C++ statements to implement the action.
+ ///
+ /// \param RecycleVarName If given, it's an instruction to recycle. The
+ /// requirements on the instruction vary from action to
+ /// action.
+ virtual void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef RecycleVarName) const = 0;
+};
+
+/// Generates a comment describing the matched rule being acted upon.
+class DebugCommentAction : public MatchAction {
+private:
+ const PatternToMatch &P;
+
+public:
+ DebugCommentAction(const PatternToMatch &P) : P(P) {}
+
+ void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef RecycleVarName) const override {
+ OS << "// " << *P.getSrcPattern() << " => " << *P.getDstPattern() << "\n";
+ }
+};
+
+/// Generates code to build an instruction or mutate an existing instruction
+/// into the desired instruction when this is possible.
+class BuildMIAction : public MatchAction {
+private:
+ const CodeGenInstruction *I;
+ const InstructionMatcher &Matched;
+ std::vector<std::unique_ptr<OperandRenderer>> OperandRenderers;
+
+ /// True if the instruction can be built solely by mutating the opcode.
+ bool canMutate() const {
+ for (const auto &Renderer : enumerate(OperandRenderers)) {
+ if (const auto *Copy = dyn_cast<CopyRenderer>(&*Renderer.value())) {
+ if (Matched.getOperand(Copy->getSymbolicName()).getOperandIndex() !=
+ Renderer.index())
+ return false;
+ } else
+ return false;
+ }
+
+ return true;
+ }
+
+public:
+ BuildMIAction(const CodeGenInstruction *I, const InstructionMatcher &Matched)
+ : I(I), Matched(Matched) {}
+
+ template <class Kind, class... Args>
+ Kind &addRenderer(Args&&... args) {
+ OperandRenderers.emplace_back(
+ llvm::make_unique<Kind>(std::forward<Args>(args)...));
+ return *static_cast<Kind *>(OperandRenderers.back().get());
+ }
+
+ void emitCxxActionStmts(raw_ostream &OS, RuleMatcher &Rule,
+ StringRef RecycleVarName) const override {
+ if (canMutate()) {
+ OS << " " << RecycleVarName << ".setDesc(TII.get(" << I->Namespace
+ << "::" << I->TheDef->getName() << "));\n";
+
+ if (!I->ImplicitDefs.empty() || !I->ImplicitUses.empty()) {
+ OS << " auto MIB = MachineInstrBuilder(MF, &" << RecycleVarName
+ << ");\n";
+
+ for (auto Def : I->ImplicitDefs) {
+ auto Namespace = Def->getValueAsString("Namespace");
+ OS << " MIB.addDef(" << Namespace << "::" << Def->getName()
+ << ", RegState::Implicit);\n";
+ }
+ for (auto Use : I->ImplicitUses) {
+ auto Namespace = Use->getValueAsString("Namespace");
+ OS << " MIB.addUse(" << Namespace << "::" << Use->getName()
+ << ", RegState::Implicit);\n";
+ }
+ }
+
+ OS << " MachineInstr &NewI = " << RecycleVarName << ";\n";
+ return;
+ }
+
+ // TODO: Simple permutation looks like it could be almost as common as
+ // mutation due to commutative operations.
+
+ OS << "MachineInstrBuilder MIB = BuildMI(*I.getParent(), I, "
+ "I.getDebugLoc(), TII.get("
+ << I->Namespace << "::" << I->TheDef->getName() << "));\n";
+ for (const auto &Renderer : OperandRenderers)
+ Renderer->emitCxxRenderStmts(OS, Rule);
+ OS << " for (const auto *FromMI : ";
+ Rule.emitCxxCapturedInsnList(OS);
+ OS << ")\n";
+ OS << " for (const auto &MMO : FromMI->memoperands())\n";
+ OS << " MIB.addMemOperand(MMO);\n";
+ OS << " " << RecycleVarName << ".eraseFromParent();\n";
+ OS << " MachineInstr &NewI = *MIB;\n";
+ }
+};
+
+InstructionMatcher &RuleMatcher::addInstructionMatcher() {
+ Matchers.emplace_back(new InstructionMatcher());
+ return *Matchers.back();
+}
+
+template <class Kind, class... Args>
+Kind &RuleMatcher::addAction(Args &&... args) {
+ Actions.emplace_back(llvm::make_unique<Kind>(std::forward<Args>(args)...));
+ return *static_cast<Kind *>(Actions.back().get());
+}
+
+std::string RuleMatcher::defineInsnVar(raw_ostream &OS,
+ const InstructionMatcher &Matcher,
+ StringRef Value) {
+ std::string InsnVarName = "MI" + llvm::to_string(NextInsnVarID++);
+ OS << "MachineInstr &" << InsnVarName << " = " << Value << ";\n";
+ InsnVariableNames[&Matcher] = InsnVarName;
+ return InsnVarName;
+}
+
+StringRef RuleMatcher::getInsnVarName(const InstructionMatcher &InsnMatcher) const {
+ const auto &I = InsnVariableNames.find(&InsnMatcher);
+ if (I != InsnVariableNames.end())
+ return I->second;
+ llvm_unreachable("Matched Insn was not captured in a local variable");
+}
+
+/// Emit a C++ initializer_list containing references to every matched instruction.
+void RuleMatcher::emitCxxCapturedInsnList(raw_ostream &OS) {
+ SmallVector<StringRef, 2> Names;
+ for (const auto &Pair : InsnVariableNames)
+ Names.push_back(Pair.second);
+ std::sort(Names.begin(), Names.end());
+
+ OS << "{";
+ for (const auto &Name : Names)
+ OS << "&" << Name << ", ";
+ OS << "}";
+}
+
+/// Emit C++ statements to check the shape of the match and capture
+/// instructions into local variables.
+void RuleMatcher::emitCxxCaptureStmts(raw_ostream &OS, StringRef Expr) {
+ assert(Matchers.size() == 1 && "Cannot handle multi-root matchers yet");
+ std::string InsnVarName = defineInsnVar(OS, *Matchers.front(), Expr);
+ Matchers.front()->emitCxxCaptureStmts(OS, *this, InsnVarName);
+}
+
+void RuleMatcher::emit(raw_ostream &OS) {
+ if (Matchers.empty())
+ llvm_unreachable("Unexpected empty matcher!");
+
+ // The representation supports rules that require multiple roots such as:
+ // %ptr(p0) = ...
+ // %elt0(s32) = G_LOAD %ptr
+ // %1(p0) = G_ADD %ptr, 4
+ // %elt1(s32) = G_LOAD p0 %1
+ // which could be usefully folded into:
+ // %ptr(p0) = ...
+ // %elt0(s32), %elt1(s32) = TGT_LOAD_PAIR %ptr
+ // on some targets but we don't need to make use of that yet.
+ assert(Matchers.size() == 1 && "Cannot handle multi-root matchers yet");
+ OS << "if ([&]() {\n";
+
+ emitCxxCaptureStmts(OS, "I");
+
+ OS << " if (";
+ Matchers.front()->emitCxxPredicateExpr(OS, *this,
+ getInsnVarName(*Matchers.front()));
+ OS << ") {\n";
+
+ // We must also check if it's safe to fold the matched instructions.
+ if (InsnVariableNames.size() >= 2) {
+ for (const auto &Pair : InsnVariableNames) {
+ // Skip the root node since it isn't moving anywhere. Everything else is
+ // sinking to meet it.
+ if (Pair.first == Matchers.front().get())
+ continue;
+
+ // Reject the difficult cases until we have a more accurate check.
+ OS << " if (!isObviouslySafeToFold(" << Pair.second
+ << ")) return false;\n";
+
+ // FIXME: Emit checks to determine it's _actually_ safe to fold and/or
+ // account for unsafe cases.
+ //
+ // Example:
+ // MI1--> %0 = ...
+ // %1 = ... %0
+ // MI0--> %2 = ... %0
+ // It's not safe to erase MI1. We currently handle this by not
+ // erasing %0 (even when it's dead).
+ //
+ // Example:
+ // MI1--> %0 = load volatile @a
+ // %1 = load volatile @a
+ // MI0--> %2 = ... %0
+ // It's not safe to sink %0's def past %1. We currently handle
+ // this by rejecting all loads.
+ //
+ // Example:
+ // MI1--> %0 = load @a
+ // %1 = store @a
+ // MI0--> %2 = ... %0
+ // It's not safe to sink %0's def past %1. We currently handle
+ // this by rejecting all loads.
+ //
+ // Example:
+ // G_CONDBR %cond, @BB1
+ // BB0:
+ // MI1--> %0 = load @a
+ // G_BR @BB1
+ // BB1:
+ // MI0--> %2 = ... %0
+ // It's not always safe to sink %0 across control flow. In this
+ // case it may introduce a memory fault. We currentl handle this
+ // by rejecting all loads.
+ }
+ }
+
+ for (const auto &MA : Actions) {
+ MA->emitCxxActionStmts(OS, *this, "I");
+ }
+
+ OS << " constrainSelectedInstRegOperands(NewI, TII, TRI, RBI);\n";
+ OS << " return true;\n";
+ OS << " }\n";
+ OS << " return false;\n";
+ OS << " }()) { return true; }\n\n";
+}
+
+bool RuleMatcher::isHigherPriorityThan(const RuleMatcher &B) const {
+ // Rules involving more match roots have higher priority.
+ if (Matchers.size() > B.Matchers.size())
+ return true;
+ if (Matchers.size() < B.Matchers.size())
+ return false;
+
+ for (const auto &Matcher : zip(Matchers, B.Matchers)) {
+ if (std::get<0>(Matcher)->isHigherPriorityThan(*std::get<1>(Matcher)))
+ return true;
+ if (std::get<1>(Matcher)->isHigherPriorityThan(*std::get<0>(Matcher)))
+ return false;
+ }
+
+ return false;
+}
+
+unsigned RuleMatcher::countTemporaryOperands() const {
+ return std::accumulate(
+ Matchers.begin(), Matchers.end(), 0,
+ [](unsigned A, const std::unique_ptr<InstructionMatcher> &Matcher) {
+ return A + Matcher->countTemporaryOperands();
+ });
+}
+
+//===- GlobalISelEmitter class --------------------------------------------===//
+
+class GlobalISelEmitter {
+public:
+ explicit GlobalISelEmitter(RecordKeeper &RK);
+ void run(raw_ostream &OS);
+
+private:
+ const RecordKeeper &RK;
+ const CodeGenDAGPatterns CGP;
+ const CodeGenTarget &Target;
+
+ /// Keep track of the equivalence between SDNodes and Instruction.
+ /// This is defined using 'GINodeEquiv' in the target description.
+ DenseMap<Record *, const CodeGenInstruction *> NodeEquivs;
+
+ /// Keep track of the equivalence between ComplexPattern's and
+ /// GIComplexOperandMatcher. Map entries are specified by subclassing
+ /// GIComplexPatternEquiv.
+ DenseMap<const Record *, const Record *> ComplexPatternEquivs;
+
+ void gatherNodeEquivs();
+ const CodeGenInstruction *findNodeEquiv(Record *N) const;
+
+ Error importRulePredicates(RuleMatcher &M, ArrayRef<Init *> Predicates) const;
+ Expected<InstructionMatcher &>
+ createAndImportSelDAGMatcher(InstructionMatcher &InsnMatcher,
+ const TreePatternNode *Src) const;
+ Error importChildMatcher(InstructionMatcher &InsnMatcher,
+ TreePatternNode *SrcChild, unsigned OpIdx,
+ unsigned &TempOpIdx) const;
+ Expected<BuildMIAction &> createAndImportInstructionRenderer(
+ RuleMatcher &M, const TreePatternNode *Dst,
+ const InstructionMatcher &InsnMatcher) const;
+ Error importExplicitUseRenderer(BuildMIAction &DstMIBuilder,
+ TreePatternNode *DstChild,
+ const InstructionMatcher &InsnMatcher) const;
+ Error
+ importImplicitDefRenderers(BuildMIAction &DstMIBuilder,
+ const std::vector<Record *> &ImplicitDefs) const;
+
+ /// Analyze pattern \p P, returning a matcher for it if possible.
+ /// Otherwise, return an Error explaining why we don't support it.
+ Expected<RuleMatcher> runOnPattern(const PatternToMatch &P);
+};
+
+void GlobalISelEmitter::gatherNodeEquivs() {
+ assert(NodeEquivs.empty());
+ for (Record *Equiv : RK.getAllDerivedDefinitions("GINodeEquiv"))
+ NodeEquivs[Equiv->getValueAsDef("Node")] =
+ &Target.getInstruction(Equiv->getValueAsDef("I"));
+
+ assert(ComplexPatternEquivs.empty());
+ for (Record *Equiv : RK.getAllDerivedDefinitions("GIComplexPatternEquiv")) {
+ Record *SelDAGEquiv = Equiv->getValueAsDef("SelDAGEquivalent");
+ if (!SelDAGEquiv)
+ continue;
+ ComplexPatternEquivs[SelDAGEquiv] = Equiv;
+ }
+}
+
+const CodeGenInstruction *GlobalISelEmitter::findNodeEquiv(Record *N) const {
+ return NodeEquivs.lookup(N);
+}
+
+GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK)
+ : RK(RK), CGP(RK), Target(CGP.getTargetInfo()) {}
+
+//===- Emitter ------------------------------------------------------------===//
+
+Error
+GlobalISelEmitter::importRulePredicates(RuleMatcher &M,
+ ArrayRef<Init *> Predicates) const {
+ if (!Predicates.empty())
+ return failedImport("Pattern has a rule predicate (" +
+ explainRulePredicates(Predicates) + ")");
+ return Error::success();
+}
+
+Expected<InstructionMatcher &> GlobalISelEmitter::createAndImportSelDAGMatcher(
+ InstructionMatcher &InsnMatcher, const TreePatternNode *Src) const {
+ // Start with the defined operands (i.e., the results of the root operator).
+ if (Src->getExtTypes().size() > 1)
+ return failedImport("Src pattern has multiple results");
+
+ auto SrcGIOrNull = findNodeEquiv(Src->getOperator());
+ if (!SrcGIOrNull)
+ return failedImport("Pattern operator lacks an equivalent Instruction" +
+ explainOperator(Src->getOperator()));
+ auto &SrcGI = *SrcGIOrNull;
+
+ // The operators look good: match the opcode and mutate it to the new one.
+ InsnMatcher.addPredicate<InstructionOpcodeMatcher>(&SrcGI);
+
+ unsigned OpIdx = 0;
+ unsigned TempOpIdx = 0;
+ for (const EEVT::TypeSet &Ty : Src->getExtTypes()) {
+ auto OpTyOrNone = MVTToLLT(Ty.getConcrete());
+
+ if (!OpTyOrNone)
+ return failedImport(
+ "Result of Src pattern operator has an unsupported type");
+
+ // Results don't have a name unless they are the root node. The caller will
+ // set the name if appropriate.
+ OperandMatcher &OM = InsnMatcher.addOperand(OpIdx++, "", TempOpIdx);
+ OM.addPredicate<LLTOperandMatcher>(*OpTyOrNone);
+ }
+
+ // Match the used operands (i.e. the children of the operator).
+ for (unsigned i = 0, e = Src->getNumChildren(); i != e; ++i) {
+ if (auto Error = importChildMatcher(InsnMatcher, Src->getChild(i), OpIdx++,
+ TempOpIdx))
+ return std::move(Error);
+ }
+
+ return InsnMatcher;
+}
+
+Error GlobalISelEmitter::importChildMatcher(InstructionMatcher &InsnMatcher,
+ TreePatternNode *SrcChild,
+ unsigned OpIdx,
+ unsigned &TempOpIdx) const {
+ OperandMatcher &OM =
+ InsnMatcher.addOperand(OpIdx, SrcChild->getName(), TempOpIdx);
+
+ if (SrcChild->hasAnyPredicate())
+ return failedImport("Src pattern child has predicate (" +
+ explainPredicates(SrcChild) + ")");
+
+ ArrayRef<EEVT::TypeSet> ChildTypes = SrcChild->getExtTypes();
+ if (ChildTypes.size() != 1)
+ return failedImport("Src pattern child has multiple results");
+
+ // Check MBB's before the type check since they are not a known type.
+ if (!SrcChild->isLeaf()) {
+ if (SrcChild->getOperator()->isSubClassOf("SDNode")) {
+ auto &ChildSDNI = CGP.getSDNodeInfo(SrcChild->getOperator());
+ if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") {
+ OM.addPredicate<MBBOperandMatcher>();
+ return Error::success();
+ }
+ }
+ }
+
+ auto OpTyOrNone = MVTToLLT(ChildTypes.front().getConcrete());
+ if (!OpTyOrNone)
+ return failedImport("Src operand has an unsupported type");
+ OM.addPredicate<LLTOperandMatcher>(*OpTyOrNone);
+
+ // Check for nested instructions.
+ if (!SrcChild->isLeaf()) {
+ // Map the node to a gMIR instruction.
+ InstructionOperandMatcher &InsnOperand =
+ OM.addPredicate<InstructionOperandMatcher>();
+ auto InsnMatcherOrError =
+ createAndImportSelDAGMatcher(InsnOperand.getInsnMatcher(), SrcChild);
+ if (auto Error = InsnMatcherOrError.takeError())
+ return Error;
+
+ return Error::success();
+ }
+
+ // Check for constant immediates.
+ if (auto *ChildInt = dyn_cast<IntInit>(SrcChild->getLeafValue())) {
+ OM.addPredicate<IntOperandMatcher>(ChildInt->getValue());
+ return Error::success();
+ }
+
+ // Check for def's like register classes or ComplexPattern's.
+ if (auto *ChildDefInit = dyn_cast<DefInit>(SrcChild->getLeafValue())) {
+ auto *ChildRec = ChildDefInit->getDef();
+
+ // Check for register classes.
+ if (ChildRec->isSubClassOf("RegisterClass")) {
+ OM.addPredicate<RegisterBankOperandMatcher>(
+ Target.getRegisterClass(ChildRec));
+ return Error::success();
+ }
+
+ // Check for ComplexPattern's.
+ if (ChildRec->isSubClassOf("ComplexPattern")) {
+ const auto &ComplexPattern = ComplexPatternEquivs.find(ChildRec);
+ if (ComplexPattern == ComplexPatternEquivs.end())
+ return failedImport("SelectionDAG ComplexPattern (" +
+ ChildRec->getName() + ") not mapped to GlobalISel");
+
+ const auto &Predicate = OM.addPredicate<ComplexPatternOperandMatcher>(
+ OM, *ComplexPattern->second);
+ TempOpIdx += Predicate.countTemporaryOperands();
+ return Error::success();
+ }
+
+ if (ChildRec->isSubClassOf("ImmLeaf")) {
+ return failedImport(
+ "Src pattern child def is an unsupported tablegen class (ImmLeaf)");
+ }
+
+ return failedImport(
+ "Src pattern child def is an unsupported tablegen class");
+ }
+
+ return failedImport("Src pattern child is an unsupported kind");
+}
+
+Error GlobalISelEmitter::importExplicitUseRenderer(
+ BuildMIAction &DstMIBuilder, TreePatternNode *DstChild,
+ const InstructionMatcher &InsnMatcher) const {
+ // The only non-leaf child we accept is 'bb': it's an operator because
+ // BasicBlockSDNode isn't inline, but in MI it's just another operand.
+ if (!DstChild->isLeaf()) {
+ if (DstChild->getOperator()->isSubClassOf("SDNode")) {
+ auto &ChildSDNI = CGP.getSDNodeInfo(DstChild->getOperator());
+ if (ChildSDNI.getSDClassName() == "BasicBlockSDNode") {
+ DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher,
+ DstChild->getName());
+ return Error::success();
+ }
+ }
+ return failedImport("Dst pattern child isn't a leaf node or an MBB");
+ }
+
+ // Otherwise, we're looking for a bog-standard RegisterClass operand.
+ if (DstChild->hasAnyPredicate())
+ return failedImport("Dst pattern child has predicate (" +
+ explainPredicates(DstChild) + ")");
+
+ if (auto *ChildDefInit = dyn_cast<DefInit>(DstChild->getLeafValue())) {
+ auto *ChildRec = ChildDefInit->getDef();
+
+ ArrayRef<EEVT::TypeSet> ChildTypes = DstChild->getExtTypes();
+ if (ChildTypes.size() != 1)
+ return failedImport("Dst pattern child has multiple results");
+
+ auto OpTyOrNone = MVTToLLT(ChildTypes.front().getConcrete());
+ if (!OpTyOrNone)
+ return failedImport("Dst operand has an unsupported type");
+
+ if (ChildRec->isSubClassOf("Register")) {
+ DstMIBuilder.addRenderer<AddRegisterRenderer>(ChildRec);
+ return Error::success();
+ }
+
+ if (ChildRec->isSubClassOf("RegisterClass")) {
+ DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher, DstChild->getName());
+ return Error::success();
+ }
+
+ if (ChildRec->isSubClassOf("ComplexPattern")) {
+ const auto &ComplexPattern = ComplexPatternEquivs.find(ChildRec);
+ if (ComplexPattern == ComplexPatternEquivs.end())
+ return failedImport(
+ "SelectionDAG ComplexPattern not mapped to GlobalISel");
+
+ SmallVector<OperandPlaceholder, 2> RenderedOperands;
+ const OperandMatcher &OM = InsnMatcher.getOperand(DstChild->getName());
+ for (unsigned I = 0; I < OM.countTemporaryOperands(); ++I)
+ RenderedOperands.push_back(OperandPlaceholder::CreateTemporary(
+ OM.getAllocatedTemporariesBaseID() + I));
+ DstMIBuilder.addRenderer<RenderComplexPatternOperand>(
+ *ComplexPattern->second, RenderedOperands);
+ return Error::success();
+ }
+
+ if (ChildRec->isSubClassOf("SDNodeXForm"))
+ return failedImport("Dst pattern child def is an unsupported tablegen "
+ "class (SDNodeXForm)");
+
+ return failedImport(
+ "Dst pattern child def is an unsupported tablegen class");
+ }
+
+ return failedImport("Dst pattern child is an unsupported kind");
+}
+
+Expected<BuildMIAction &> GlobalISelEmitter::createAndImportInstructionRenderer(
+ RuleMatcher &M, const TreePatternNode *Dst,
+ const InstructionMatcher &InsnMatcher) const {
+ Record *DstOp = Dst->getOperator();
+ if (!DstOp->isSubClassOf("Instruction")) {
+ if (DstOp->isSubClassOf("ValueType"))
+ return failedImport(
+ "Pattern operator isn't an instruction (it's a ValueType)");
+ return failedImport("Pattern operator isn't an instruction");
+ }
+ auto &DstI = Target.getInstruction(DstOp);
+
+ auto &DstMIBuilder = M.addAction<BuildMIAction>(&DstI, InsnMatcher);
+
+ // Render the explicit defs.
+ for (unsigned I = 0; I < DstI.Operands.NumDefs; ++I) {
+ const auto &DstIOperand = DstI.Operands[I];
+ DstMIBuilder.addRenderer<CopyRenderer>(InsnMatcher, DstIOperand.Name);
+ }
+
+ // Figure out which operands need defaults inserted. Operands that subclass
+ // OperandWithDefaultOps are considered from left to right until we have
+ // enough operands to render the instruction.
+ SmallSet<unsigned, 2> DefaultOperands;
+ unsigned DstINumUses = DstI.Operands.size() - DstI.Operands.NumDefs;
+ unsigned NumDefaultOperands = 0;
+ for (unsigned I = 0; I < DstINumUses &&
+ DstINumUses > Dst->getNumChildren() + NumDefaultOperands;
+ ++I) {
+ const auto &DstIOperand = DstI.Operands[DstI.Operands.NumDefs + I];
+ if (DstIOperand.Rec->isSubClassOf("OperandWithDefaultOps")) {
+ DefaultOperands.insert(I);
+ NumDefaultOperands +=
+ DstIOperand.Rec->getValueAsDag("DefaultOps")->getNumArgs();
+ }
+ }
+ if (DstINumUses > Dst->getNumChildren() + DefaultOperands.size())
+ return failedImport("Insufficient operands supplied and default ops "
+ "couldn't make up the shortfall");
+ if (DstINumUses < Dst->getNumChildren() + DefaultOperands.size())
+ return failedImport("Too many operands supplied");
+
+ // Render the explicit uses.
+ unsigned Child = 0;
+ for (unsigned I = 0; I != DstINumUses; ++I) {
+ // If we need to insert default ops here, then do so.
+ if (DefaultOperands.count(I)) {
+ const auto &DstIOperand = DstI.Operands[DstI.Operands.NumDefs + I];
+
+ DagInit *DefaultOps = DstIOperand.Rec->getValueAsDag("DefaultOps");
+ for (const auto *DefaultOp : DefaultOps->args()) {
+ // Look through ValueType operators.
+ if (const DagInit *DefaultDagOp = dyn_cast<DagInit>(DefaultOp)) {
+ if (const DefInit *DefaultDagOperator =
+ dyn_cast<DefInit>(DefaultDagOp->getOperator())) {
+ if (DefaultDagOperator->getDef()->isSubClassOf("ValueType"))
+ DefaultOp = DefaultDagOp->getArg(0);
+ }
+ }
+
+ if (const DefInit *DefaultDefOp = dyn_cast<DefInit>(DefaultOp)) {
+ DstMIBuilder.addRenderer<AddRegisterRenderer>(DefaultDefOp->getDef());
+ continue;
+ }
+
+ if (const IntInit *DefaultIntOp = dyn_cast<IntInit>(DefaultOp)) {
+ DstMIBuilder.addRenderer<ImmRenderer>(DefaultIntOp->getValue());
+ continue;
+ }
+
+ return failedImport("Could not add default op");
+ }
+
+ continue;
+ }
+
+ if (auto Error = importExplicitUseRenderer(
+ DstMIBuilder, Dst->getChild(Child), InsnMatcher))
+ return std::move(Error);
+ ++Child;
+ }
+
+ return DstMIBuilder;
+}
+
+Error GlobalISelEmitter::importImplicitDefRenderers(
+ BuildMIAction &DstMIBuilder,
+ const std::vector<Record *> &ImplicitDefs) const {
+ if (!ImplicitDefs.empty())
+ return failedImport("Pattern defines a physical register");
+ return Error::success();
+}
+
+Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) {
+ // Keep track of the matchers and actions to emit.
+ RuleMatcher M;
+ M.addAction<DebugCommentAction>(P);
+
+ if (auto Error = importRulePredicates(M, P.getPredicates()->getValues()))
+ return std::move(Error);
+
+ // Next, analyze the pattern operators.
+ TreePatternNode *Src = P.getSrcPattern();
+ TreePatternNode *Dst = P.getDstPattern();
+
+ // If the root of either pattern isn't a simple operator, ignore it.
+ if (auto Err = isTrivialOperatorNode(Dst))
+ return failedImport("Dst pattern root isn't a trivial operator (" +
+ toString(std::move(Err)) + ")");
+ if (auto Err = isTrivialOperatorNode(Src))
+ return failedImport("Src pattern root isn't a trivial operator (" +
+ toString(std::move(Err)) + ")");
+
+ // Start with the defined operands (i.e., the results of the root operator).
+ Record *DstOp = Dst->getOperator();
+ if (!DstOp->isSubClassOf("Instruction"))
+ return failedImport("Pattern operator isn't an instruction");
+
+ auto &DstI = Target.getInstruction(DstOp);
+ if (DstI.Operands.NumDefs != Src->getExtTypes().size())
+ return failedImport("Src pattern results and dst MI defs are different (" +
+ to_string(Src->getExtTypes().size()) + " def(s) vs " +
+ to_string(DstI.Operands.NumDefs) + " def(s))");
+
+ InstructionMatcher &InsnMatcherTemp = M.addInstructionMatcher();
+ auto InsnMatcherOrError = createAndImportSelDAGMatcher(InsnMatcherTemp, Src);
+ if (auto Error = InsnMatcherOrError.takeError())
+ return std::move(Error);
+ InstructionMatcher &InsnMatcher = InsnMatcherOrError.get();
+
+ // The root of the match also has constraints on the register bank so that it
+ // matches the result instruction.
+ unsigned OpIdx = 0;
+ for (const EEVT::TypeSet &Ty : Src->getExtTypes()) {
+ (void)Ty;
+
+ const auto &DstIOperand = DstI.Operands[OpIdx];
+ Record *DstIOpRec = DstIOperand.Rec;
+ if (!DstIOpRec->isSubClassOf("RegisterClass"))
+ return failedImport("Dst MI def isn't a register class");
+
+ OperandMatcher &OM = InsnMatcher.getOperand(OpIdx);
+ OM.setSymbolicName(DstIOperand.Name);
+ OM.addPredicate<RegisterBankOperandMatcher>(
+ Target.getRegisterClass(DstIOpRec));
+ ++OpIdx;
+ }
+
+ auto DstMIBuilderOrError =
+ createAndImportInstructionRenderer(M, Dst, InsnMatcher);
+ if (auto Error = DstMIBuilderOrError.takeError())
+ return std::move(Error);
+ BuildMIAction &DstMIBuilder = DstMIBuilderOrError.get();
+
+ // Render the implicit defs.
+ // These are only added to the root of the result.
+ if (auto Error = importImplicitDefRenderers(DstMIBuilder, P.getDstRegs()))
+ return std::move(Error);
+
+ // We're done with this pattern! It's eligible for GISel emission; return it.
+ ++NumPatternImported;
+ return std::move(M);
+}
+
+void GlobalISelEmitter::run(raw_ostream &OS) {
+ // Track the GINodeEquiv definitions.
+ gatherNodeEquivs();
+
+ emitSourceFileHeader(("Global Instruction Selector for the " +
+ Target.getName() + " target").str(), OS);
+ std::vector<RuleMatcher> Rules;
+ // Look through the SelectionDAG patterns we found, possibly emitting some.
+ for (const PatternToMatch &Pat : CGP.ptms()) {
+ ++NumPatternTotal;
+ auto MatcherOrErr = runOnPattern(Pat);
+
+ // The pattern analysis can fail, indicating an unsupported pattern.
+ // Report that if we've been asked to do so.
+ if (auto Err = MatcherOrErr.takeError()) {
+ if (WarnOnSkippedPatterns) {
+ PrintWarning(Pat.getSrcRecord()->getLoc(),
+ "Skipped pattern: " + toString(std::move(Err)));
+ } else {
+ consumeError(std::move(Err));
+ }
+ ++NumPatternImportsSkipped;
+ continue;
+ }
+
+ Rules.push_back(std::move(MatcherOrErr.get()));
+ }
+
+ std::stable_sort(Rules.begin(), Rules.end(),
+ [&](const RuleMatcher &A, const RuleMatcher &B) {
+ if (A.isHigherPriorityThan(B)) {
+ assert(!B.isHigherPriorityThan(A) && "Cannot be more important "
+ "and less important at "
+ "the same time");
+ return true;
+ }
+ return false;
+ });
+
+ unsigned MaxTemporaries = 0;
+ for (const auto &Rule : Rules)
+ MaxTemporaries = std::max(MaxTemporaries, Rule.countTemporaryOperands());
+
+ OS << "#ifdef GET_GLOBALISEL_TEMPORARIES_DECL\n";
+ for (unsigned I = 0; I < MaxTemporaries; ++I)
+ OS << " mutable MachineOperand TempOp" << I << ";\n";
+ OS << "#endif // ifdef GET_GLOBALISEL_TEMPORARIES_DECL\n\n";
+
+ OS << "#ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n";
+ for (unsigned I = 0; I < MaxTemporaries; ++I)
+ OS << ", TempOp" << I << "(MachineOperand::CreatePlaceholder())\n";
+ OS << "#endif // ifdef GET_GLOBALISEL_TEMPORARIES_INIT\n\n";
+
+ OS << "#ifdef GET_GLOBALISEL_IMPL\n"
+ << "bool " << Target.getName()
+ << "InstructionSelector::selectImpl(MachineInstr &I) const {\n"
+ << " MachineFunction &MF = *I.getParent()->getParent();\n"
+ << " const MachineRegisterInfo &MRI = MF.getRegInfo();\n";
+
+ for (auto &Rule : Rules) {
+ Rule.emit(OS);
+ ++NumPatternEmitted;
+ }
+
+ OS << " return false;\n"
+ << "}\n"
+ << "#endif // ifdef GET_GLOBALISEL_IMPL\n";
+}
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+
+namespace llvm {
+void EmitGlobalISel(RecordKeeper &RK, raw_ostream &OS) {
+ GlobalISelEmitter(RK).run(OS);
+}
+} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
new file mode 100644
index 000000000000..ab7d964cd671
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -0,0 +1,612 @@
+//===- InstrInfoEmitter.cpp - Generate a Instruction Set Desc. --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting a description of the target
+// instruction set for the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenDAGPatterns.h"
+#include "CodeGenInstruction.h"
+#include "CodeGenSchedule.h"
+#include "CodeGenTarget.h"
+#include "SequenceToOffsetTable.h"
+#include "TableGenBackends.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <cassert>
+#include <cstdint>
+#include <map>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+
+class InstrInfoEmitter {
+ RecordKeeper &Records;
+ CodeGenDAGPatterns CDP;
+ const CodeGenSchedModels &SchedModels;
+
+public:
+ InstrInfoEmitter(RecordKeeper &R):
+ Records(R), CDP(R), SchedModels(CDP.getTargetInfo().getSchedModels()) {}
+
+ // run - Output the instruction set description.
+ void run(raw_ostream &OS);
+
+private:
+ void emitEnums(raw_ostream &OS);
+
+ typedef std::map<std::vector<std::string>, unsigned> OperandInfoMapTy;
+
+ /// The keys of this map are maps which have OpName enum values as their keys
+ /// and instruction operand indices as their values. The values of this map
+ /// are lists of instruction names.
+ typedef std::map<std::map<unsigned, unsigned>,
+ std::vector<std::string>> OpNameMapTy;
+ typedef std::map<std::string, unsigned>::iterator StrUintMapIter;
+ void emitRecord(const CodeGenInstruction &Inst, unsigned Num,
+ Record *InstrInfo,
+ std::map<std::vector<Record*>, unsigned> &EL,
+ const OperandInfoMapTy &OpInfo,
+ raw_ostream &OS);
+ void emitOperandTypesEnum(raw_ostream &OS, const CodeGenTarget &Target);
+ void initOperandMapData(
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions,
+ const std::string &Namespace,
+ std::map<std::string, unsigned> &Operands,
+ OpNameMapTy &OperandMap);
+ void emitOperandNameMappings(raw_ostream &OS, const CodeGenTarget &Target,
+ ArrayRef<const CodeGenInstruction*> NumberedInstructions);
+
+ // Operand information.
+ void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs);
+ std::vector<std::string> GetOperandInfo(const CodeGenInstruction &Inst);
+};
+
+} // end anonymous namespace
+
+static void PrintDefList(const std::vector<Record*> &Uses,
+ unsigned Num, raw_ostream &OS) {
+ OS << "static const MCPhysReg ImplicitList" << Num << "[] = { ";
+ for (Record *U : Uses)
+ OS << getQualifiedName(U) << ", ";
+ OS << "0 };\n";
+}
+
+//===----------------------------------------------------------------------===//
+// Operand Info Emission.
+//===----------------------------------------------------------------------===//
+
+std::vector<std::string>
+InstrInfoEmitter::GetOperandInfo(const CodeGenInstruction &Inst) {
+ std::vector<std::string> Result;
+
+ for (auto &Op : Inst.Operands) {
+ // Handle aggregate operands and normal operands the same way by expanding
+ // either case into a list of operands for this op.
+ std::vector<CGIOperandList::OperandInfo> OperandList;
+
+ // This might be a multiple operand thing. Targets like X86 have
+ // registers in their multi-operand operands. It may also be an anonymous
+ // operand, which has a single operand, but no declared class for the
+ // operand.
+ DagInit *MIOI = Op.MIOperandInfo;
+
+ if (!MIOI || MIOI->getNumArgs() == 0) {
+ // Single, anonymous, operand.
+ OperandList.push_back(Op);
+ } else {
+ for (unsigned j = 0, e = Op.MINumOperands; j != e; ++j) {
+ OperandList.push_back(Op);
+
+ auto *OpR = cast<DefInit>(MIOI->getArg(j))->getDef();
+ OperandList.back().Rec = OpR;
+ }
+ }
+
+ for (unsigned j = 0, e = OperandList.size(); j != e; ++j) {
+ Record *OpR = OperandList[j].Rec;
+ std::string Res;
+
+ if (OpR->isSubClassOf("RegisterOperand"))
+ OpR = OpR->getValueAsDef("RegClass");
+ if (OpR->isSubClassOf("RegisterClass"))
+ Res += getQualifiedName(OpR) + "RegClassID, ";
+ else if (OpR->isSubClassOf("PointerLikeRegClass"))
+ Res += utostr(OpR->getValueAsInt("RegClassKind")) + ", ";
+ else
+ // -1 means the operand does not have a fixed register class.
+ Res += "-1, ";
+
+ // Fill in applicable flags.
+ Res += "0";
+
+ // Ptr value whose register class is resolved via callback.
+ if (OpR->isSubClassOf("PointerLikeRegClass"))
+ Res += "|(1<<MCOI::LookupPtrRegClass)";
+
+ // Predicate operands. Check to see if the original unexpanded operand
+ // was of type PredicateOp.
+ if (Op.Rec->isSubClassOf("PredicateOp"))
+ Res += "|(1<<MCOI::Predicate)";
+
+ // Optional def operands. Check to see if the original unexpanded operand
+ // was of type OptionalDefOperand.
+ if (Op.Rec->isSubClassOf("OptionalDefOperand"))
+ Res += "|(1<<MCOI::OptionalDef)";
+
+ // Fill in operand type.
+ Res += ", ";
+ assert(!Op.OperandType.empty() && "Invalid operand type.");
+ Res += Op.OperandType;
+
+ // Fill in constraint info.
+ Res += ", ";
+
+ const CGIOperandList::ConstraintInfo &Constraint =
+ Op.Constraints[j];
+ if (Constraint.isNone())
+ Res += "0";
+ else if (Constraint.isEarlyClobber())
+ Res += "(1 << MCOI::EARLY_CLOBBER)";
+ else {
+ assert(Constraint.isTied());
+ Res += "((" + utostr(Constraint.getTiedOperand()) +
+ " << 16) | (1 << MCOI::TIED_TO))";
+ }
+
+ Result.push_back(Res);
+ }
+ }
+
+ return Result;
+}
+
+void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
+ OperandInfoMapTy &OperandInfoIDs) {
+ // ID #0 is for no operand info.
+ unsigned OperandListNum = 0;
+ OperandInfoIDs[std::vector<std::string>()] = ++OperandListNum;
+
+ OS << "\n";
+ const CodeGenTarget &Target = CDP.getTargetInfo();
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
+ std::vector<std::string> OperandInfo = GetOperandInfo(*Inst);
+ unsigned &N = OperandInfoIDs[OperandInfo];
+ if (N != 0) continue;
+
+ N = ++OperandListNum;
+ OS << "static const MCOperandInfo OperandInfo" << N << "[] = { ";
+ for (const std::string &Info : OperandInfo)
+ OS << "{ " << Info << " }, ";
+ OS << "};\n";
+ }
+}
+
+/// Initialize data structures for generating operand name mappings.
+///
+/// \param Operands [out] A map used to generate the OpName enum with operand
+/// names as its keys and operand enum values as its values.
+/// \param OperandMap [out] A map for representing the operand name mappings for
+/// each instructions. This is used to generate the OperandMap table as
+/// well as the getNamedOperandIdx() function.
+void InstrInfoEmitter::initOperandMapData(
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions,
+ const std::string &Namespace,
+ std::map<std::string, unsigned> &Operands,
+ OpNameMapTy &OperandMap) {
+ unsigned NumOperands = 0;
+ for (const CodeGenInstruction *Inst : NumberedInstructions) {
+ if (!Inst->TheDef->getValueAsBit("UseNamedOperandTable"))
+ continue;
+ std::map<unsigned, unsigned> OpList;
+ for (const auto &Info : Inst->Operands) {
+ StrUintMapIter I = Operands.find(Info.Name);
+
+ if (I == Operands.end()) {
+ I = Operands.insert(Operands.begin(),
+ std::pair<std::string, unsigned>(Info.Name, NumOperands++));
+ }
+ OpList[I->second] = Info.MIOperandNo;
+ }
+ OperandMap[OpList].push_back(Namespace + "::" +
+ Inst->TheDef->getName().str());
+ }
+}
+
+/// Generate a table and function for looking up the indices of operands by
+/// name.
+///
+/// This code generates:
+/// - An enum in the llvm::TargetNamespace::OpName namespace, with one entry
+/// for each operand name.
+/// - A 2-dimensional table called OperandMap for mapping OpName enum values to
+/// operand indices.
+/// - A function called getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
+/// for looking up the operand index for an instruction, given a value from
+/// OpName enum
+void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
+ const CodeGenTarget &Target,
+ ArrayRef<const CodeGenInstruction*> NumberedInstructions) {
+ const std::string &Namespace = Target.getInstNamespace();
+ std::string OpNameNS = "OpName";
+ // Map of operand names to their enumeration value. This will be used to
+ // generate the OpName enum.
+ std::map<std::string, unsigned> Operands;
+ OpNameMapTy OperandMap;
+
+ initOperandMapData(NumberedInstructions, Namespace, Operands, OperandMap);
+
+ OS << "#ifdef GET_INSTRINFO_OPERAND_ENUM\n";
+ OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n";
+ OS << "namespace llvm {\n";
+ OS << "namespace " << Namespace << " {\n";
+ OS << "namespace " << OpNameNS << " {\n";
+ OS << "enum {\n";
+ for (const auto &Op : Operands)
+ OS << " " << Op.first << " = " << Op.second << ",\n";
+
+ OS << "OPERAND_LAST";
+ OS << "\n};\n";
+ OS << "} // end namespace OpName\n";
+ OS << "} // end namespace " << Namespace << "\n";
+ OS << "} // end namespace llvm\n";
+ OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n\n";
+
+ OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n";
+ OS << "#undef GET_INSTRINFO_NAMED_OPS\n";
+ OS << "namespace llvm {\n";
+ OS << "namespace " << Namespace << " {\n";
+ OS << "LLVM_READONLY\n";
+ OS << "int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx) {\n";
+ if (!Operands.empty()) {
+ OS << " static const int16_t OperandMap [][" << Operands.size()
+ << "] = {\n";
+ for (const auto &Entry : OperandMap) {
+ const std::map<unsigned, unsigned> &OpList = Entry.first;
+ OS << "{";
+
+ // Emit a row of the OperandMap table
+ for (unsigned i = 0, e = Operands.size(); i != e; ++i)
+ OS << (OpList.count(i) == 0 ? -1 : (int)OpList.find(i)->second) << ", ";
+
+ OS << "},\n";
+ }
+ OS << "};\n";
+
+ OS << " switch(Opcode) {\n";
+ unsigned TableIndex = 0;
+ for (const auto &Entry : OperandMap) {
+ for (const std::string &Name : Entry.second)
+ OS << " case " << Name << ":\n";
+
+ OS << " return OperandMap[" << TableIndex++ << "][NamedIdx];\n";
+ }
+ OS << " default: return -1;\n";
+ OS << " }\n";
+ } else {
+ // There are no operands, so no need to emit anything
+ OS << " return -1;\n";
+ }
+ OS << "}\n";
+ OS << "} // end namespace " << Namespace << "\n";
+ OS << "} // end namespace llvm\n";
+ OS << "#endif //GET_INSTRINFO_NAMED_OPS\n\n";
+}
+
+/// Generate an enum for all the operand types for this target, under the
+/// llvm::TargetNamespace::OpTypes namespace.
+/// Operand types are all definitions derived of the Operand Target.td class.
+void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
+ const CodeGenTarget &Target) {
+
+ const std::string &Namespace = Target.getInstNamespace();
+ std::vector<Record *> Operands = Records.getAllDerivedDefinitions("Operand");
+
+ OS << "#ifdef GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
+ OS << "#undef GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
+ OS << "namespace llvm {\n";
+ OS << "namespace " << Namespace << " {\n";
+ OS << "namespace OpTypes {\n";
+ OS << "enum OperandType {\n";
+
+ unsigned EnumVal = 0;
+ for (const Record *Op : Operands) {
+ if (!Op->isAnonymous())
+ OS << " " << Op->getName() << " = " << EnumVal << ",\n";
+ ++EnumVal;
+ }
+
+ OS << " OPERAND_TYPE_LIST_END" << "\n};\n";
+ OS << "} // end namespace OpTypes\n";
+ OS << "} // end namespace " << Namespace << "\n";
+ OS << "} // end namespace llvm\n";
+ OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n";
+}
+
+//===----------------------------------------------------------------------===//
+// Main Output.
+//===----------------------------------------------------------------------===//
+
+// run - Emit the main instruction description records for the target...
+void InstrInfoEmitter::run(raw_ostream &OS) {
+ emitSourceFileHeader("Target Instruction Enum Values and Descriptors", OS);
+ emitEnums(OS);
+
+ OS << "#ifdef GET_INSTRINFO_MC_DESC\n";
+ OS << "#undef GET_INSTRINFO_MC_DESC\n";
+
+ OS << "namespace llvm {\n\n";
+
+ CodeGenTarget &Target = CDP.getTargetInfo();
+ const std::string &TargetName = Target.getName();
+ Record *InstrInfo = Target.getInstructionSet();
+
+ // Keep track of all of the def lists we have emitted already.
+ std::map<std::vector<Record*>, unsigned> EmittedLists;
+ unsigned ListNumber = 0;
+
+ // Emit all of the instruction's implicit uses and defs.
+ for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
+ Record *Inst = II->TheDef;
+ std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses");
+ if (!Uses.empty()) {
+ unsigned &IL = EmittedLists[Uses];
+ if (!IL) PrintDefList(Uses, IL = ++ListNumber, OS);
+ }
+ std::vector<Record*> Defs = Inst->getValueAsListOfDefs("Defs");
+ if (!Defs.empty()) {
+ unsigned &IL = EmittedLists[Defs];
+ if (!IL) PrintDefList(Defs, IL = ++ListNumber, OS);
+ }
+ }
+
+ OperandInfoMapTy OperandInfoIDs;
+
+ // Emit all of the operand info records.
+ EmitOperandInfo(OS, OperandInfoIDs);
+
+ // Emit all of the MCInstrDesc records in their ENUM ordering.
+ //
+ OS << "\nextern const MCInstrDesc " << TargetName << "Insts[] = {\n";
+ ArrayRef<const CodeGenInstruction*> NumberedInstructions =
+ Target.getInstructionsByEnumValue();
+
+ SequenceToOffsetTable<std::string> InstrNames;
+ unsigned Num = 0;
+ for (const CodeGenInstruction *Inst : NumberedInstructions) {
+ // Keep a list of the instruction names.
+ InstrNames.add(Inst->TheDef->getName());
+ // Emit the record into the table.
+ emitRecord(*Inst, Num++, InstrInfo, EmittedLists, OperandInfoIDs, OS);
+ }
+ OS << "};\n\n";
+
+ // Emit the array of instruction names.
+ InstrNames.layout();
+ OS << "extern const char " << TargetName << "InstrNameData[] = {\n";
+ InstrNames.emit(OS, printChar);
+ OS << "};\n\n";
+
+ OS << "extern const unsigned " << TargetName <<"InstrNameIndices[] = {";
+ Num = 0;
+ for (const CodeGenInstruction *Inst : NumberedInstructions) {
+ // Newline every eight entries.
+ if (Num % 8 == 0)
+ OS << "\n ";
+ OS << InstrNames.get(Inst->TheDef->getName()) << "U, ";
+ ++Num;
+ }
+
+ OS << "\n};\n\n";
+
+ // MCInstrInfo initialization routine.
+ OS << "static inline void Init" << TargetName
+ << "MCInstrInfo(MCInstrInfo *II) {\n";
+ OS << " II->InitMCInstrInfo(" << TargetName << "Insts, "
+ << TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, "
+ << NumberedInstructions.size() << ");\n}\n\n";
+
+ OS << "} // end llvm namespace\n";
+
+ OS << "#endif // GET_INSTRINFO_MC_DESC\n\n";
+
+ // Create a TargetInstrInfo subclass to hide the MC layer initialization.
+ OS << "#ifdef GET_INSTRINFO_HEADER\n";
+ OS << "#undef GET_INSTRINFO_HEADER\n";
+
+ std::string ClassName = TargetName + "GenInstrInfo";
+ OS << "namespace llvm {\n";
+ OS << "struct " << ClassName << " : public TargetInstrInfo {\n"
+ << " explicit " << ClassName
+ << "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1, int ReturnOpcode = -1);\n"
+ << " ~" << ClassName << "() override = default;\n"
+ << "};\n";
+ OS << "} // end llvm namespace\n";
+
+ OS << "#endif // GET_INSTRINFO_HEADER\n\n";
+
+ OS << "#ifdef GET_INSTRINFO_CTOR_DTOR\n";
+ OS << "#undef GET_INSTRINFO_CTOR_DTOR\n";
+
+ OS << "namespace llvm {\n";
+ OS << "extern const MCInstrDesc " << TargetName << "Insts[];\n";
+ OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n";
+ OS << "extern const char " << TargetName << "InstrNameData[];\n";
+ OS << ClassName << "::" << ClassName
+ << "(int CFSetupOpcode, int CFDestroyOpcode, int CatchRetOpcode, int ReturnOpcode)\n"
+ << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode, ReturnOpcode) {\n"
+ << " InitMCInstrInfo(" << TargetName << "Insts, " << TargetName
+ << "InstrNameIndices, " << TargetName << "InstrNameData, "
+ << NumberedInstructions.size() << ");\n}\n";
+ OS << "} // end llvm namespace\n";
+
+ OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n";
+
+ emitOperandNameMappings(OS, Target, NumberedInstructions);
+
+ emitOperandTypesEnum(OS, Target);
+}
+
+void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
+ Record *InstrInfo,
+ std::map<std::vector<Record*>, unsigned> &EmittedLists,
+ const OperandInfoMapTy &OpInfo,
+ raw_ostream &OS) {
+ int MinOperands = 0;
+ if (!Inst.Operands.empty())
+ // Each logical operand can be multiple MI operands.
+ MinOperands = Inst.Operands.back().MIOperandNo +
+ Inst.Operands.back().MINumOperands;
+
+ OS << " { ";
+ OS << Num << ",\t" << MinOperands << ",\t"
+ << Inst.Operands.NumDefs << ",\t"
+ << Inst.TheDef->getValueAsInt("Size") << ",\t"
+ << SchedModels.getSchedClassIdx(Inst) << ",\t0";
+
+ // Emit all of the target independent flags...
+ if (Inst.isPseudo) OS << "|(1ULL<<MCID::Pseudo)";
+ if (Inst.isReturn) OS << "|(1ULL<<MCID::Return)";
+ if (Inst.isBranch) OS << "|(1ULL<<MCID::Branch)";
+ if (Inst.isIndirectBranch) OS << "|(1ULL<<MCID::IndirectBranch)";
+ if (Inst.isCompare) OS << "|(1ULL<<MCID::Compare)";
+ if (Inst.isMoveImm) OS << "|(1ULL<<MCID::MoveImm)";
+ if (Inst.isBitcast) OS << "|(1ULL<<MCID::Bitcast)";
+ if (Inst.isAdd) OS << "|(1ULL<<MCID::Add)";
+ if (Inst.isSelect) OS << "|(1ULL<<MCID::Select)";
+ if (Inst.isBarrier) OS << "|(1ULL<<MCID::Barrier)";
+ if (Inst.hasDelaySlot) OS << "|(1ULL<<MCID::DelaySlot)";
+ if (Inst.isCall) OS << "|(1ULL<<MCID::Call)";
+ if (Inst.canFoldAsLoad) OS << "|(1ULL<<MCID::FoldableAsLoad)";
+ if (Inst.mayLoad) OS << "|(1ULL<<MCID::MayLoad)";
+ if (Inst.mayStore) OS << "|(1ULL<<MCID::MayStore)";
+ if (Inst.isPredicable) OS << "|(1ULL<<MCID::Predicable)";
+ if (Inst.isConvertibleToThreeAddress) OS << "|(1ULL<<MCID::ConvertibleTo3Addr)";
+ if (Inst.isCommutable) OS << "|(1ULL<<MCID::Commutable)";
+ if (Inst.isTerminator) OS << "|(1ULL<<MCID::Terminator)";
+ if (Inst.isReMaterializable) OS << "|(1ULL<<MCID::Rematerializable)";
+ if (Inst.isNotDuplicable) OS << "|(1ULL<<MCID::NotDuplicable)";
+ if (Inst.Operands.hasOptionalDef) OS << "|(1ULL<<MCID::HasOptionalDef)";
+ if (Inst.usesCustomInserter) OS << "|(1ULL<<MCID::UsesCustomInserter)";
+ if (Inst.hasPostISelHook) OS << "|(1ULL<<MCID::HasPostISelHook)";
+ if (Inst.Operands.isVariadic)OS << "|(1ULL<<MCID::Variadic)";
+ if (Inst.hasSideEffects) OS << "|(1ULL<<MCID::UnmodeledSideEffects)";
+ if (Inst.isAsCheapAsAMove) OS << "|(1ULL<<MCID::CheapAsAMove)";
+ if (Inst.hasExtraSrcRegAllocReq) OS << "|(1ULL<<MCID::ExtraSrcRegAllocReq)";
+ if (Inst.hasExtraDefRegAllocReq) OS << "|(1ULL<<MCID::ExtraDefRegAllocReq)";
+ if (Inst.isRegSequence) OS << "|(1ULL<<MCID::RegSequence)";
+ if (Inst.isExtractSubreg) OS << "|(1ULL<<MCID::ExtractSubreg)";
+ if (Inst.isInsertSubreg) OS << "|(1ULL<<MCID::InsertSubreg)";
+ if (Inst.isConvergent) OS << "|(1ULL<<MCID::Convergent)";
+
+ // Emit all of the target-specific flags...
+ BitsInit *TSF = Inst.TheDef->getValueAsBitsInit("TSFlags");
+ if (!TSF)
+ PrintFatalError("no TSFlags?");
+ uint64_t Value = 0;
+ for (unsigned i = 0, e = TSF->getNumBits(); i != e; ++i) {
+ if (const auto *Bit = dyn_cast<BitInit>(TSF->getBit(i)))
+ Value |= uint64_t(Bit->getValue()) << i;
+ else
+ PrintFatalError("Invalid TSFlags bit in " + Inst.TheDef->getName());
+ }
+ OS << ", 0x";
+ OS.write_hex(Value);
+ OS << "ULL, ";
+
+ // Emit the implicit uses and defs lists...
+ std::vector<Record*> UseList = Inst.TheDef->getValueAsListOfDefs("Uses");
+ if (UseList.empty())
+ OS << "nullptr, ";
+ else
+ OS << "ImplicitList" << EmittedLists[UseList] << ", ";
+
+ std::vector<Record*> DefList = Inst.TheDef->getValueAsListOfDefs("Defs");
+ if (DefList.empty())
+ OS << "nullptr, ";
+ else
+ OS << "ImplicitList" << EmittedLists[DefList] << ", ";
+
+ // Emit the operand info.
+ std::vector<std::string> OperandInfo = GetOperandInfo(Inst);
+ if (OperandInfo.empty())
+ OS << "nullptr";
+ else
+ OS << "OperandInfo" << OpInfo.find(OperandInfo)->second;
+
+ CodeGenTarget &Target = CDP.getTargetInfo();
+ if (Inst.HasComplexDeprecationPredicate)
+ // Emit a function pointer to the complex predicate method.
+ OS << ", -1 "
+ << ",&get" << Inst.DeprecatedReason << "DeprecationInfo";
+ else if (!Inst.DeprecatedReason.empty())
+ // Emit the Subtarget feature.
+ OS << ", " << Target.getInstNamespace() << "::" << Inst.DeprecatedReason
+ << " ,nullptr";
+ else
+ // Instruction isn't deprecated.
+ OS << ", -1 ,nullptr";
+
+ OS << " }, // Inst #" << Num << " = " << Inst.TheDef->getName() << "\n";
+}
+
+// emitEnums - Print out enum values for all of the instructions.
+void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
+ OS << "#ifdef GET_INSTRINFO_ENUM\n";
+ OS << "#undef GET_INSTRINFO_ENUM\n";
+
+ OS << "namespace llvm {\n\n";
+
+ CodeGenTarget Target(Records);
+
+ // We must emit the PHI opcode first...
+ std::string Namespace = Target.getInstNamespace();
+
+ if (Namespace.empty())
+ PrintFatalError("No instructions defined!");
+
+ OS << "namespace " << Namespace << " {\n";
+ OS << " enum {\n";
+ unsigned Num = 0;
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue())
+ OS << " " << Inst->TheDef->getName() << "\t= " << Num++ << ",\n";
+ OS << " INSTRUCTION_LIST_END = " << Num << "\n";
+ OS << " };\n\n";
+ OS << "namespace Sched {\n";
+ OS << " enum {\n";
+ Num = 0;
+ for (const auto &Class : SchedModels.explicit_classes())
+ OS << " " << Class.Name << "\t= " << Num++ << ",\n";
+ OS << " SCHED_LIST_END = " << Num << "\n";
+ OS << " };\n";
+ OS << "} // end Sched namespace\n";
+ OS << "} // end " << Namespace << " namespace\n";
+ OS << "} // end llvm namespace\n";
+
+ OS << "#endif // GET_INSTRINFO_ENUM\n\n";
+}
+
+namespace llvm {
+
+void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS) {
+ InstrInfoEmitter(RK).run(OS);
+ EmitMapTable(RK, OS);
+}
+
+} // end llvm namespace
diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
new file mode 100644
index 000000000000..e979b94e46d6
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
@@ -0,0 +1,818 @@
+//===- IntrinsicEmitter.cpp - Generate intrinsic information --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits information about intrinsic functions.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenIntrinsics.h"
+#include "CodeGenTarget.h"
+#include "SequenceToOffsetTable.h"
+#include "TableGenBackends.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringMatcher.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include "llvm/TableGen/StringToOffsetTable.h"
+#include <algorithm>
+using namespace llvm;
+
+namespace {
+class IntrinsicEmitter {
+ RecordKeeper &Records;
+ bool TargetOnly;
+ std::string TargetPrefix;
+
+public:
+ IntrinsicEmitter(RecordKeeper &R, bool T)
+ : Records(R), TargetOnly(T) {}
+
+ void run(raw_ostream &OS);
+
+ void EmitPrefix(raw_ostream &OS);
+
+ void EmitEnumInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
+ void EmitTargetInfo(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
+ void EmitIntrinsicToNameTable(const CodeGenIntrinsicTable &Ints,
+ raw_ostream &OS);
+ void EmitIntrinsicToOverloadTable(const CodeGenIntrinsicTable &Ints,
+ raw_ostream &OS);
+ void EmitGenerator(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
+ void EmitAttributes(const CodeGenIntrinsicTable &Ints, raw_ostream &OS);
+ void EmitIntrinsicToBuiltinMap(const CodeGenIntrinsicTable &Ints, bool IsGCC,
+ raw_ostream &OS);
+ void EmitSuffix(raw_ostream &OS);
+};
+} // End anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// IntrinsicEmitter Implementation
+//===----------------------------------------------------------------------===//
+
+void IntrinsicEmitter::run(raw_ostream &OS) {
+ emitSourceFileHeader("Intrinsic Function Source Fragment", OS);
+
+ CodeGenIntrinsicTable Ints(Records, TargetOnly);
+
+ if (TargetOnly && !Ints.empty())
+ TargetPrefix = Ints[0].TargetPrefix;
+
+ EmitPrefix(OS);
+
+ // Emit the enum information.
+ EmitEnumInfo(Ints, OS);
+
+ // Emit the target metadata.
+ EmitTargetInfo(Ints, OS);
+
+ // Emit the intrinsic ID -> name table.
+ EmitIntrinsicToNameTable(Ints, OS);
+
+ // Emit the intrinsic ID -> overload table.
+ EmitIntrinsicToOverloadTable(Ints, OS);
+
+ // Emit the intrinsic declaration generator.
+ EmitGenerator(Ints, OS);
+
+ // Emit the intrinsic parameter attributes.
+ EmitAttributes(Ints, OS);
+
+ // Emit code to translate GCC builtins into LLVM intrinsics.
+ EmitIntrinsicToBuiltinMap(Ints, true, OS);
+
+ // Emit code to translate MS builtins into LLVM intrinsics.
+ EmitIntrinsicToBuiltinMap(Ints, false, OS);
+
+ EmitSuffix(OS);
+}
+
+void IntrinsicEmitter::EmitPrefix(raw_ostream &OS) {
+ OS << "// VisualStudio defines setjmp as _setjmp\n"
+ "#if defined(_MSC_VER) && defined(setjmp) && \\\n"
+ " !defined(setjmp_undefined_for_msvc)\n"
+ "# pragma push_macro(\"setjmp\")\n"
+ "# undef setjmp\n"
+ "# define setjmp_undefined_for_msvc\n"
+ "#endif\n\n";
+}
+
+void IntrinsicEmitter::EmitSuffix(raw_ostream &OS) {
+ OS << "#if defined(_MSC_VER) && defined(setjmp_undefined_for_msvc)\n"
+ "// let's return it to _setjmp state\n"
+ "# pragma pop_macro(\"setjmp\")\n"
+ "# undef setjmp_undefined_for_msvc\n"
+ "#endif\n\n";
+}
+
+void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable &Ints,
+ raw_ostream &OS) {
+ OS << "// Enum values for Intrinsics.h\n";
+ OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ OS << " " << Ints[i].EnumName;
+ OS << ((i != e-1) ? ", " : " ");
+ if (Ints[i].EnumName.size() < 40)
+ OS << std::string(40-Ints[i].EnumName.size(), ' ');
+ OS << " // " << Ints[i].Name << "\n";
+ }
+ OS << "#endif\n\n";
+}
+
+void IntrinsicEmitter::EmitTargetInfo(const CodeGenIntrinsicTable &Ints,
+ raw_ostream &OS) {
+ OS << "// Target mapping\n";
+ OS << "#ifdef GET_INTRINSIC_TARGET_DATA\n";
+ OS << "struct IntrinsicTargetInfo {\n"
+ << " llvm::StringLiteral Name;\n"
+ << " size_t Offset;\n"
+ << " size_t Count;\n"
+ << "};\n";
+ OS << "static constexpr IntrinsicTargetInfo TargetInfos[] = {\n";
+ for (auto Target : Ints.Targets)
+ OS << " {llvm::StringLiteral(\"" << Target.Name << "\"), " << Target.Offset
+ << ", " << Target.Count << "},\n";
+ OS << "};\n";
+ OS << "#endif\n\n";
+}
+
+void IntrinsicEmitter::EmitIntrinsicToNameTable(
+ const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
+ OS << "// Intrinsic ID to name table\n";
+ OS << "#ifdef GET_INTRINSIC_NAME_TABLE\n";
+ OS << " // Note that entry #0 is the invalid intrinsic!\n";
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i)
+ OS << " \"" << Ints[i].Name << "\",\n";
+ OS << "#endif\n\n";
+}
+
+void IntrinsicEmitter::EmitIntrinsicToOverloadTable(
+ const CodeGenIntrinsicTable &Ints, raw_ostream &OS) {
+ OS << "// Intrinsic ID to overload bitset\n";
+ OS << "#ifdef GET_INTRINSIC_OVERLOAD_TABLE\n";
+ OS << "static const uint8_t OTable[] = {\n";
+ OS << " 0";
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ // Add one to the index so we emit a null bit for the invalid #0 intrinsic.
+ if ((i+1)%8 == 0)
+ OS << ",\n 0";
+ if (Ints[i].isOverloaded)
+ OS << " | (1<<" << (i+1)%8 << ')';
+ }
+ OS << "\n};\n\n";
+ // OTable contains a true bit at the position if the intrinsic is overloaded.
+ OS << "return (OTable[id/8] & (1 << (id%8))) != 0;\n";
+ OS << "#endif\n\n";
+}
+
+
+// NOTE: This must be kept in synch with the copy in lib/VMCore/Function.cpp!
+enum IIT_Info {
+ // Common values should be encoded with 0-15.
+ IIT_Done = 0,
+ IIT_I1 = 1,
+ IIT_I8 = 2,
+ IIT_I16 = 3,
+ IIT_I32 = 4,
+ IIT_I64 = 5,
+ IIT_F16 = 6,
+ IIT_F32 = 7,
+ IIT_F64 = 8,
+ IIT_V2 = 9,
+ IIT_V4 = 10,
+ IIT_V8 = 11,
+ IIT_V16 = 12,
+ IIT_V32 = 13,
+ IIT_PTR = 14,
+ IIT_ARG = 15,
+
+ // Values from 16+ are only encodable with the inefficient encoding.
+ IIT_V64 = 16,
+ IIT_MMX = 17,
+ IIT_TOKEN = 18,
+ IIT_METADATA = 19,
+ IIT_EMPTYSTRUCT = 20,
+ IIT_STRUCT2 = 21,
+ IIT_STRUCT3 = 22,
+ IIT_STRUCT4 = 23,
+ IIT_STRUCT5 = 24,
+ IIT_EXTEND_ARG = 25,
+ IIT_TRUNC_ARG = 26,
+ IIT_ANYPTR = 27,
+ IIT_V1 = 28,
+ IIT_VARARG = 29,
+ IIT_HALF_VEC_ARG = 30,
+ IIT_SAME_VEC_WIDTH_ARG = 31,
+ IIT_PTR_TO_ARG = 32,
+ IIT_PTR_TO_ELT = 33,
+ IIT_VEC_OF_PTRS_TO_ELT = 34,
+ IIT_I128 = 35,
+ IIT_V512 = 36,
+ IIT_V1024 = 37
+};
+
+
+static void EncodeFixedValueType(MVT::SimpleValueType VT,
+ std::vector<unsigned char> &Sig) {
+ if (MVT(VT).isInteger()) {
+ unsigned BitWidth = MVT(VT).getSizeInBits();
+ switch (BitWidth) {
+ default: PrintFatalError("unhandled integer type width in intrinsic!");
+ case 1: return Sig.push_back(IIT_I1);
+ case 8: return Sig.push_back(IIT_I8);
+ case 16: return Sig.push_back(IIT_I16);
+ case 32: return Sig.push_back(IIT_I32);
+ case 64: return Sig.push_back(IIT_I64);
+ case 128: return Sig.push_back(IIT_I128);
+ }
+ }
+
+ switch (VT) {
+ default: PrintFatalError("unhandled MVT in intrinsic!");
+ case MVT::f16: return Sig.push_back(IIT_F16);
+ case MVT::f32: return Sig.push_back(IIT_F32);
+ case MVT::f64: return Sig.push_back(IIT_F64);
+ case MVT::token: return Sig.push_back(IIT_TOKEN);
+ case MVT::Metadata: return Sig.push_back(IIT_METADATA);
+ case MVT::x86mmx: return Sig.push_back(IIT_MMX);
+ // MVT::OtherVT is used to mean the empty struct type here.
+ case MVT::Other: return Sig.push_back(IIT_EMPTYSTRUCT);
+ // MVT::isVoid is used to represent varargs here.
+ case MVT::isVoid: return Sig.push_back(IIT_VARARG);
+ }
+}
+
+#if defined(_MSC_VER) && !defined(__clang__)
+#pragma optimize("",off) // MSVC 2015 optimizer can't deal with this function.
+#endif
+
+static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
+ std::vector<unsigned char> &Sig) {
+
+ if (R->isSubClassOf("LLVMMatchType")) {
+ unsigned Number = R->getValueAsInt("Number");
+ assert(Number < ArgCodes.size() && "Invalid matching number!");
+ if (R->isSubClassOf("LLVMExtendedType"))
+ Sig.push_back(IIT_EXTEND_ARG);
+ else if (R->isSubClassOf("LLVMTruncatedType"))
+ Sig.push_back(IIT_TRUNC_ARG);
+ else if (R->isSubClassOf("LLVMHalfElementsVectorType"))
+ Sig.push_back(IIT_HALF_VEC_ARG);
+ else if (R->isSubClassOf("LLVMVectorSameWidth")) {
+ Sig.push_back(IIT_SAME_VEC_WIDTH_ARG);
+ Sig.push_back((Number << 3) | ArgCodes[Number]);
+ MVT::SimpleValueType VT = getValueType(R->getValueAsDef("ElTy"));
+ EncodeFixedValueType(VT, Sig);
+ return;
+ }
+ else if (R->isSubClassOf("LLVMPointerTo"))
+ Sig.push_back(IIT_PTR_TO_ARG);
+ else if (R->isSubClassOf("LLVMVectorOfPointersToElt"))
+ Sig.push_back(IIT_VEC_OF_PTRS_TO_ELT);
+ else if (R->isSubClassOf("LLVMPointerToElt"))
+ Sig.push_back(IIT_PTR_TO_ELT);
+ else
+ Sig.push_back(IIT_ARG);
+ return Sig.push_back((Number << 3) | ArgCodes[Number]);
+ }
+
+ MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT"));
+
+ unsigned Tmp = 0;
+ switch (VT) {
+ default: break;
+ case MVT::iPTRAny: ++Tmp; LLVM_FALLTHROUGH;
+ case MVT::vAny: ++Tmp; LLVM_FALLTHROUGH;
+ case MVT::fAny: ++Tmp; LLVM_FALLTHROUGH;
+ case MVT::iAny: ++Tmp; LLVM_FALLTHROUGH;
+ case MVT::Any: {
+ // If this is an "any" valuetype, then the type is the type of the next
+ // type in the list specified to getIntrinsic().
+ Sig.push_back(IIT_ARG);
+
+ // Figure out what arg # this is consuming, and remember what kind it was.
+ unsigned ArgNo = ArgCodes.size();
+ ArgCodes.push_back(Tmp);
+
+ // Encode what sort of argument it must be in the low 3 bits of the ArgNo.
+ return Sig.push_back((ArgNo << 3) | Tmp);
+ }
+
+ case MVT::iPTR: {
+ unsigned AddrSpace = 0;
+ if (R->isSubClassOf("LLVMQualPointerType")) {
+ AddrSpace = R->getValueAsInt("AddrSpace");
+ assert(AddrSpace < 256 && "Address space exceeds 255");
+ }
+ if (AddrSpace) {
+ Sig.push_back(IIT_ANYPTR);
+ Sig.push_back(AddrSpace);
+ } else {
+ Sig.push_back(IIT_PTR);
+ }
+ return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, Sig);
+ }
+ }
+
+ if (MVT(VT).isVector()) {
+ MVT VVT = VT;
+ switch (VVT.getVectorNumElements()) {
+ default: PrintFatalError("unhandled vector type width in intrinsic!");
+ case 1: Sig.push_back(IIT_V1); break;
+ case 2: Sig.push_back(IIT_V2); break;
+ case 4: Sig.push_back(IIT_V4); break;
+ case 8: Sig.push_back(IIT_V8); break;
+ case 16: Sig.push_back(IIT_V16); break;
+ case 32: Sig.push_back(IIT_V32); break;
+ case 64: Sig.push_back(IIT_V64); break;
+ case 512: Sig.push_back(IIT_V512); break;
+ case 1024: Sig.push_back(IIT_V1024); break;
+ }
+
+ return EncodeFixedValueType(VVT.getVectorElementType().SimpleTy, Sig);
+ }
+
+ EncodeFixedValueType(VT, Sig);
+}
+
+#if defined(_MSC_VER) && !defined(__clang__)
+#pragma optimize("",on)
+#endif
+
+/// ComputeFixedEncoding - If we can encode the type signature for this
+/// intrinsic into 32 bits, return it. If not, return ~0U.
+static void ComputeFixedEncoding(const CodeGenIntrinsic &Int,
+ std::vector<unsigned char> &TypeSig) {
+ std::vector<unsigned char> ArgCodes;
+
+ if (Int.IS.RetVTs.empty())
+ TypeSig.push_back(IIT_Done);
+ else if (Int.IS.RetVTs.size() == 1 &&
+ Int.IS.RetVTs[0] == MVT::isVoid)
+ TypeSig.push_back(IIT_Done);
+ else {
+ switch (Int.IS.RetVTs.size()) {
+ case 1: break;
+ case 2: TypeSig.push_back(IIT_STRUCT2); break;
+ case 3: TypeSig.push_back(IIT_STRUCT3); break;
+ case 4: TypeSig.push_back(IIT_STRUCT4); break;
+ case 5: TypeSig.push_back(IIT_STRUCT5); break;
+ default: llvm_unreachable("Unhandled case in struct");
+ }
+
+ for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i)
+ EncodeFixedType(Int.IS.RetTypeDefs[i], ArgCodes, TypeSig);
+ }
+
+ for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i)
+ EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, TypeSig);
+}
+
+static void printIITEntry(raw_ostream &OS, unsigned char X) {
+ OS << (unsigned)X;
+}
+
+void IntrinsicEmitter::EmitGenerator(const CodeGenIntrinsicTable &Ints,
+ raw_ostream &OS) {
+ // If we can compute a 32-bit fixed encoding for this intrinsic, do so and
+ // capture it in this vector, otherwise store a ~0U.
+ std::vector<unsigned> FixedEncodings;
+
+ SequenceToOffsetTable<std::vector<unsigned char> > LongEncodingTable;
+
+ std::vector<unsigned char> TypeSig;
+
+ // Compute the unique argument type info.
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ // Get the signature for the intrinsic.
+ TypeSig.clear();
+ ComputeFixedEncoding(Ints[i], TypeSig);
+
+ // Check to see if we can encode it into a 32-bit word. We can only encode
+ // 8 nibbles into a 32-bit word.
+ if (TypeSig.size() <= 8) {
+ bool Failed = false;
+ unsigned Result = 0;
+ for (unsigned i = 0, e = TypeSig.size(); i != e; ++i) {
+ // If we had an unencodable argument, bail out.
+ if (TypeSig[i] > 15) {
+ Failed = true;
+ break;
+ }
+ Result = (Result << 4) | TypeSig[e-i-1];
+ }
+
+ // If this could be encoded into a 31-bit word, return it.
+ if (!Failed && (Result >> 31) == 0) {
+ FixedEncodings.push_back(Result);
+ continue;
+ }
+ }
+
+ // Otherwise, we're going to unique the sequence into the
+ // LongEncodingTable, and use its offset in the 32-bit table instead.
+ LongEncodingTable.add(TypeSig);
+
+ // This is a placehold that we'll replace after the table is laid out.
+ FixedEncodings.push_back(~0U);
+ }
+
+ LongEncodingTable.layout();
+
+ OS << "// Global intrinsic function declaration type table.\n";
+ OS << "#ifdef GET_INTRINSIC_GENERATOR_GLOBAL\n";
+
+ OS << "static const unsigned IIT_Table[] = {\n ";
+
+ for (unsigned i = 0, e = FixedEncodings.size(); i != e; ++i) {
+ if ((i & 7) == 7)
+ OS << "\n ";
+
+ // If the entry fit in the table, just emit it.
+ if (FixedEncodings[i] != ~0U) {
+ OS << "0x" << utohexstr(FixedEncodings[i]) << ", ";
+ continue;
+ }
+
+ TypeSig.clear();
+ ComputeFixedEncoding(Ints[i], TypeSig);
+
+
+ // Otherwise, emit the offset into the long encoding table. We emit it this
+ // way so that it is easier to read the offset in the .def file.
+ OS << "(1U<<31) | " << LongEncodingTable.get(TypeSig) << ", ";
+ }
+
+ OS << "0\n};\n\n";
+
+ // Emit the shared table of register lists.
+ OS << "static const unsigned char IIT_LongEncodingTable[] = {\n";
+ if (!LongEncodingTable.empty())
+ LongEncodingTable.emit(OS, printIITEntry);
+ OS << " 255\n};\n\n";
+
+ OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL
+}
+
+namespace {
+struct AttributeComparator {
+ bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
+ // Sort throwing intrinsics after non-throwing intrinsics.
+ if (L->canThrow != R->canThrow)
+ return R->canThrow;
+
+ if (L->isNoDuplicate != R->isNoDuplicate)
+ return R->isNoDuplicate;
+
+ if (L->isNoReturn != R->isNoReturn)
+ return R->isNoReturn;
+
+ if (L->isConvergent != R->isConvergent)
+ return R->isConvergent;
+
+ // Try to order by readonly/readnone attribute.
+ CodeGenIntrinsic::ModRefBehavior LK = L->ModRef;
+ CodeGenIntrinsic::ModRefBehavior RK = R->ModRef;
+ if (LK != RK) return (LK > RK);
+
+ // Order by argument attributes.
+ // This is reliable because each side is already sorted internally.
+ return (L->ArgumentAttributes < R->ArgumentAttributes);
+ }
+};
+} // End anonymous namespace
+
+/// EmitAttributes - This emits the Intrinsic::getAttributes method.
+void IntrinsicEmitter::EmitAttributes(const CodeGenIntrinsicTable &Ints,
+ raw_ostream &OS) {
+ OS << "// Add parameter attributes that are not common to all intrinsics.\n";
+ OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
+ if (TargetOnly)
+ OS << "static AttributeList getAttributes(LLVMContext &C, " << TargetPrefix
+ << "Intrinsic::ID id) {\n";
+ else
+ OS << "AttributeList Intrinsic::getAttributes(LLVMContext &C, ID id) {\n";
+
+ // Compute the maximum number of attribute arguments and the map
+ typedef std::map<const CodeGenIntrinsic*, unsigned,
+ AttributeComparator> UniqAttrMapTy;
+ UniqAttrMapTy UniqAttributes;
+ unsigned maxArgAttrs = 0;
+ unsigned AttrNum = 0;
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ const CodeGenIntrinsic &intrinsic = Ints[i];
+ maxArgAttrs =
+ std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size()));
+ unsigned &N = UniqAttributes[&intrinsic];
+ if (N) continue;
+ assert(AttrNum < 256 && "Too many unique attributes for table!");
+ N = ++AttrNum;
+ }
+
+ // Emit an array of AttributeList. Most intrinsics will have at least one
+ // entry, for the function itself (index ~1), which is usually nounwind.
+ OS << " static const uint8_t IntrinsicsToAttributesMap[] = {\n";
+
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ const CodeGenIntrinsic &intrinsic = Ints[i];
+
+ OS << " " << UniqAttributes[&intrinsic] << ", // "
+ << intrinsic.Name << "\n";
+ }
+ OS << " };\n\n";
+
+ OS << " AttributeList AS[" << maxArgAttrs + 1 << "];\n";
+ OS << " unsigned NumAttrs = 0;\n";
+ OS << " if (id != 0) {\n";
+ OS << " switch(IntrinsicsToAttributesMap[id - ";
+ if (TargetOnly)
+ OS << "Intrinsic::num_intrinsics";
+ else
+ OS << "1";
+ OS << "]) {\n";
+ OS << " default: llvm_unreachable(\"Invalid attribute number\");\n";
+ for (UniqAttrMapTy::const_iterator I = UniqAttributes.begin(),
+ E = UniqAttributes.end(); I != E; ++I) {
+ OS << " case " << I->second << ": {\n";
+
+ const CodeGenIntrinsic &intrinsic = *(I->first);
+
+ // Keep track of the number of attributes we're writing out.
+ unsigned numAttrs = 0;
+
+ // The argument attributes are alreadys sorted by argument index.
+ unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size();
+ if (ae) {
+ while (ai != ae) {
+ unsigned argNo = intrinsic.ArgumentAttributes[ai].first;
+
+ OS << " const Attribute::AttrKind AttrParam" << argNo + 1 <<"[]= {";
+ bool addComma = false;
+
+ do {
+ switch (intrinsic.ArgumentAttributes[ai].second) {
+ case CodeGenIntrinsic::NoCapture:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::NoCapture";
+ addComma = true;
+ break;
+ case CodeGenIntrinsic::Returned:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::Returned";
+ addComma = true;
+ break;
+ case CodeGenIntrinsic::ReadOnly:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadOnly";
+ addComma = true;
+ break;
+ case CodeGenIntrinsic::WriteOnly:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::WriteOnly";
+ addComma = true;
+ break;
+ case CodeGenIntrinsic::ReadNone:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadNone";
+ addComma = true;
+ break;
+ }
+
+ ++ai;
+ } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo);
+ OS << "};\n";
+ OS << " AS[" << numAttrs++ << "] = AttributeList::get(C, "
+ << argNo + 1 << ", AttrParam" << argNo + 1 << ");\n";
+ }
+ }
+
+ if (!intrinsic.canThrow ||
+ intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem ||
+ intrinsic.isNoReturn || intrinsic.isNoDuplicate ||
+ intrinsic.isConvergent) {
+ OS << " const Attribute::AttrKind Atts[] = {";
+ bool addComma = false;
+ if (!intrinsic.canThrow) {
+ OS << "Attribute::NoUnwind";
+ addComma = true;
+ }
+ if (intrinsic.isNoReturn) {
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::NoReturn";
+ addComma = true;
+ }
+ if (intrinsic.isNoDuplicate) {
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::NoDuplicate";
+ addComma = true;
+ }
+ if (intrinsic.isConvergent) {
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::Convergent";
+ addComma = true;
+ }
+
+ switch (intrinsic.ModRef) {
+ case CodeGenIntrinsic::NoMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadNone";
+ break;
+ case CodeGenIntrinsic::ReadArgMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadOnly,";
+ OS << "Attribute::ArgMemOnly";
+ break;
+ case CodeGenIntrinsic::ReadMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadOnly";
+ break;
+ case CodeGenIntrinsic::ReadInaccessibleMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadOnly,";
+ OS << "Attribute::InaccessibleMemOnly";
+ break;
+ case CodeGenIntrinsic::ReadInaccessibleMemOrArgMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadOnly,";
+ OS << "Attribute::InaccessibleMemOrArgMemOnly";
+ break;
+ case CodeGenIntrinsic::WriteArgMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::WriteOnly,";
+ OS << "Attribute::ArgMemOnly";
+ break;
+ case CodeGenIntrinsic::WriteMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::WriteOnly";
+ break;
+ case CodeGenIntrinsic::WriteInaccessibleMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::WriteOnly,";
+ OS << "Attribute::InaccessibleMemOnly";
+ break;
+ case CodeGenIntrinsic::WriteInaccessibleMemOrArgMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::WriteOnly,";
+ OS << "Attribute::InaccessibleMemOrArgOnly";
+ break;
+ case CodeGenIntrinsic::ReadWriteArgMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ArgMemOnly";
+ break;
+ case CodeGenIntrinsic::ReadWriteInaccessibleMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::InaccessibleMemOnly";
+ break;
+ case CodeGenIntrinsic::ReadWriteInaccessibleMemOrArgMem:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::InaccessibleMemOrArgMemOnly";
+ case CodeGenIntrinsic::ReadWriteMem:
+ break;
+ }
+ OS << "};\n";
+ OS << " AS[" << numAttrs++ << "] = AttributeList::get(C, "
+ << "AttributeList::FunctionIndex, Atts);\n";
+ }
+
+ if (numAttrs) {
+ OS << " NumAttrs = " << numAttrs << ";\n";
+ OS << " break;\n";
+ OS << " }\n";
+ } else {
+ OS << " return AttributeList();\n";
+ OS << " }\n";
+ }
+ }
+
+ OS << " }\n";
+ OS << " }\n";
+ OS << " return AttributeList::get(C, makeArrayRef(AS, NumAttrs));\n";
+ OS << "}\n";
+ OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
+}
+
+void IntrinsicEmitter::EmitIntrinsicToBuiltinMap(
+ const CodeGenIntrinsicTable &Ints, bool IsGCC, raw_ostream &OS) {
+ StringRef CompilerName = (IsGCC ? "GCC" : "MS");
+ typedef std::map<std::string, std::map<std::string, std::string>> BIMTy;
+ BIMTy BuiltinMap;
+ StringToOffsetTable Table;
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ const std::string &BuiltinName =
+ IsGCC ? Ints[i].GCCBuiltinName : Ints[i].MSBuiltinName;
+ if (!BuiltinName.empty()) {
+ // Get the map for this target prefix.
+ std::map<std::string, std::string> &BIM =
+ BuiltinMap[Ints[i].TargetPrefix];
+
+ if (!BIM.insert(std::make_pair(BuiltinName, Ints[i].EnumName)).second)
+ PrintFatalError("Intrinsic '" + Ints[i].TheDef->getName() +
+ "': duplicate " + CompilerName + " builtin name!");
+ Table.GetOrAddStringOffset(BuiltinName);
+ }
+ }
+
+ OS << "// Get the LLVM intrinsic that corresponds to a builtin.\n";
+ OS << "// This is used by the C front-end. The builtin name is passed\n";
+ OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
+ OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n";
+ OS << "#ifdef GET_LLVM_INTRINSIC_FOR_" << CompilerName << "_BUILTIN\n";
+
+ if (TargetOnly) {
+ OS << "static " << TargetPrefix << "Intrinsic::ID "
+ << "getIntrinsicFor" << CompilerName << "Builtin(const char "
+ << "*TargetPrefixStr, StringRef BuiltinNameStr) {\n";
+ } else {
+ OS << "Intrinsic::ID Intrinsic::getIntrinsicFor" << CompilerName
+ << "Builtin(const char "
+ << "*TargetPrefixStr, StringRef BuiltinNameStr) {\n";
+ }
+
+ if (Table.Empty()) {
+ OS << " return ";
+ if (!TargetPrefix.empty())
+ OS << "(" << TargetPrefix << "Intrinsic::ID)";
+ OS << "Intrinsic::not_intrinsic;\n";
+ OS << "}\n";
+ OS << "#endif\n\n";
+ return;
+ }
+
+ OS << " static const char BuiltinNames[] = {\n";
+ Table.EmitCharArray(OS);
+ OS << " };\n\n";
+
+ OS << " struct BuiltinEntry {\n";
+ OS << " Intrinsic::ID IntrinID;\n";
+ OS << " unsigned StrTabOffset;\n";
+ OS << " const char *getName() const {\n";
+ OS << " return &BuiltinNames[StrTabOffset];\n";
+ OS << " }\n";
+ OS << " bool operator<(StringRef RHS) const {\n";
+ OS << " return strncmp(getName(), RHS.data(), RHS.size()) < 0;\n";
+ OS << " }\n";
+ OS << " };\n";
+
+ OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n";
+
+ // Note: this could emit significantly better code if we cared.
+ for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
+ OS << " ";
+ if (!I->first.empty())
+ OS << "if (TargetPrefix == \"" << I->first << "\") ";
+ else
+ OS << "/* Target Independent Builtins */ ";
+ OS << "{\n";
+
+ // Emit the comparisons for this target prefix.
+ OS << " static const BuiltinEntry " << I->first << "Names[] = {\n";
+ for (const auto &P : I->second) {
+ OS << " {Intrinsic::" << P.second << ", "
+ << Table.GetOrAddStringOffset(P.first) << "}, // " << P.first << "\n";
+ }
+ OS << " };\n";
+ OS << " auto I = std::lower_bound(std::begin(" << I->first << "Names),\n";
+ OS << " std::end(" << I->first << "Names),\n";
+ OS << " BuiltinNameStr);\n";
+ OS << " if (I != std::end(" << I->first << "Names) &&\n";
+ OS << " I->getName() == BuiltinNameStr)\n";
+ OS << " return I->IntrinID;\n";
+ OS << " }\n";
+ }
+ OS << " return ";
+ if (!TargetPrefix.empty())
+ OS << "(" << TargetPrefix << "Intrinsic::ID)";
+ OS << "Intrinsic::not_intrinsic;\n";
+ OS << "}\n";
+ OS << "#endif\n\n";
+}
+
+void llvm::EmitIntrinsics(RecordKeeper &RK, raw_ostream &OS, bool TargetOnly) {
+ IntrinsicEmitter(RK, TargetOnly).run(OS);
+}
diff --git a/contrib/llvm/utils/TableGen/OptParserEmitter.cpp b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp
new file mode 100644
index 000000000000..c1b5e6510325
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/OptParserEmitter.cpp
@@ -0,0 +1,290 @@
+//===- OptParserEmitter.cpp - Table Driven Command Line Parsing -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TableGen/Error.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <cctype>
+#include <cstring>
+#include <map>
+
+using namespace llvm;
+
+// Ordering on Info. The logic should match with the consumer-side function in
+// llvm/Option/OptTable.h.
+static int StrCmpOptionName(const char *A, const char *B) {
+ const char *X = A, *Y = B;
+ char a = tolower(*A), b = tolower(*B);
+ while (a == b) {
+ if (a == '\0')
+ return strcmp(A, B);
+
+ a = tolower(*++X);
+ b = tolower(*++Y);
+ }
+
+ if (a == '\0') // A is a prefix of B.
+ return 1;
+ if (b == '\0') // B is a prefix of A.
+ return -1;
+
+ // Otherwise lexicographic.
+ return (a < b) ? -1 : 1;
+}
+
+static int CompareOptionRecords(Record *const *Av, Record *const *Bv) {
+ const Record *A = *Av;
+ const Record *B = *Bv;
+
+ // Sentinel options precede all others and are only ordered by precedence.
+ bool ASent = A->getValueAsDef("Kind")->getValueAsBit("Sentinel");
+ bool BSent = B->getValueAsDef("Kind")->getValueAsBit("Sentinel");
+ if (ASent != BSent)
+ return ASent ? -1 : 1;
+
+ // Compare options by name, unless they are sentinels.
+ if (!ASent)
+ if (int Cmp = StrCmpOptionName(A->getValueAsString("Name").c_str(),
+ B->getValueAsString("Name").c_str()))
+ return Cmp;
+
+ if (!ASent) {
+ std::vector<std::string> APrefixes = A->getValueAsListOfStrings("Prefixes");
+ std::vector<std::string> BPrefixes = B->getValueAsListOfStrings("Prefixes");
+
+ for (std::vector<std::string>::const_iterator APre = APrefixes.begin(),
+ AEPre = APrefixes.end(),
+ BPre = BPrefixes.begin(),
+ BEPre = BPrefixes.end();
+ APre != AEPre &&
+ BPre != BEPre;
+ ++APre, ++BPre) {
+ if (int Cmp = StrCmpOptionName(APre->c_str(), BPre->c_str()))
+ return Cmp;
+ }
+ }
+
+ // Then by the kind precedence;
+ int APrec = A->getValueAsDef("Kind")->getValueAsInt("Precedence");
+ int BPrec = B->getValueAsDef("Kind")->getValueAsInt("Precedence");
+ if (APrec == BPrec &&
+ A->getValueAsListOfStrings("Prefixes") ==
+ B->getValueAsListOfStrings("Prefixes")) {
+ PrintError(A->getLoc(), Twine("Option is equivalent to"));
+ PrintError(B->getLoc(), Twine("Other defined here"));
+ PrintFatalError("Equivalent Options found.");
+ }
+ return APrec < BPrec ? -1 : 1;
+}
+
+static const std::string getOptionName(const Record &R) {
+ // Use the record name unless EnumName is defined.
+ if (isa<UnsetInit>(R.getValueInit("EnumName")))
+ return R.getName();
+
+ return R.getValueAsString("EnumName");
+}
+
+static raw_ostream &write_cstring(raw_ostream &OS, llvm::StringRef Str) {
+ OS << '"';
+ OS.write_escaped(Str);
+ OS << '"';
+ return OS;
+}
+
+/// OptParserEmitter - This tablegen backend takes an input .td file
+/// describing a list of options and emits a data structure for parsing and
+/// working with those options when given an input command line.
+namespace llvm {
+void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
+ // Get the option groups and options.
+ const std::vector<Record*> &Groups =
+ Records.getAllDerivedDefinitions("OptionGroup");
+ std::vector<Record*> Opts = Records.getAllDerivedDefinitions("Option");
+
+ emitSourceFileHeader("Option Parsing Definitions", OS);
+
+ array_pod_sort(Opts.begin(), Opts.end(), CompareOptionRecords);
+ // Generate prefix groups.
+ typedef SmallVector<SmallString<2>, 2> PrefixKeyT;
+ typedef std::map<PrefixKeyT, std::string> PrefixesT;
+ PrefixesT Prefixes;
+ Prefixes.insert(std::make_pair(PrefixKeyT(), "prefix_0"));
+ unsigned CurPrefix = 0;
+ for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
+ const Record &R = *Opts[i];
+ std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
+ PrefixKeyT prfkey(prf.begin(), prf.end());
+ unsigned NewPrefix = CurPrefix + 1;
+ if (Prefixes.insert(std::make_pair(prfkey, (Twine("prefix_") +
+ Twine(NewPrefix)).str())).second)
+ CurPrefix = NewPrefix;
+ }
+
+ // Dump prefixes.
+
+ OS << "/////////\n";
+ OS << "// Prefixes\n\n";
+ OS << "#ifdef PREFIX\n";
+ OS << "#define COMMA ,\n";
+ for (PrefixesT::const_iterator I = Prefixes.begin(), E = Prefixes.end();
+ I != E; ++I) {
+ OS << "PREFIX(";
+
+ // Prefix name.
+ OS << I->second;
+
+ // Prefix values.
+ OS << ", {";
+ for (PrefixKeyT::const_iterator PI = I->first.begin(),
+ PE = I->first.end(); PI != PE; ++PI) {
+ OS << "\"" << *PI << "\" COMMA ";
+ }
+ OS << "nullptr})\n";
+ }
+ OS << "#undef COMMA\n";
+ OS << "#endif // PREFIX\n\n";
+
+ OS << "/////////\n";
+ OS << "// Groups\n\n";
+ OS << "#ifdef OPTION\n";
+ for (unsigned i = 0, e = Groups.size(); i != e; ++i) {
+ const Record &R = *Groups[i];
+
+ // Start a single option entry.
+ OS << "OPTION(";
+
+ // The option prefix;
+ OS << "nullptr";
+
+ // The option string.
+ OS << ", \"" << R.getValueAsString("Name") << '"';
+
+ // The option identifier name.
+ OS << ", "<< getOptionName(R);
+
+ // The option kind.
+ OS << ", Group";
+
+ // The containing option group (if any).
+ OS << ", ";
+ if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group")))
+ OS << getOptionName(*DI->getDef());
+ else
+ OS << "INVALID";
+
+ // The other option arguments (unused for groups).
+ OS << ", INVALID, nullptr, 0, 0";
+
+ // The option help text.
+ if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
+ OS << ",\n";
+ OS << " ";
+ write_cstring(OS, R.getValueAsString("HelpText"));
+ } else
+ OS << ", nullptr";
+
+ // The option meta-variable name (unused).
+ OS << ", nullptr)\n";
+ }
+ OS << "\n";
+
+ OS << "//////////\n";
+ OS << "// Options\n\n";
+ for (unsigned i = 0, e = Opts.size(); i != e; ++i) {
+ const Record &R = *Opts[i];
+
+ // Start a single option entry.
+ OS << "OPTION(";
+
+ // The option prefix;
+ std::vector<std::string> prf = R.getValueAsListOfStrings("Prefixes");
+ OS << Prefixes[PrefixKeyT(prf.begin(), prf.end())] << ", ";
+
+ // The option string.
+ write_cstring(OS, R.getValueAsString("Name"));
+
+ // The option identifier name.
+ OS << ", "<< getOptionName(R);
+
+ // The option kind.
+ OS << ", " << R.getValueAsDef("Kind")->getValueAsString("Name");
+
+ // The containing option group (if any).
+ OS << ", ";
+ const ListInit *GroupFlags = nullptr;
+ if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
+ GroupFlags = DI->getDef()->getValueAsListInit("Flags");
+ OS << getOptionName(*DI->getDef());
+ } else
+ OS << "INVALID";
+
+ // The option alias (if any).
+ OS << ", ";
+ if (const DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Alias")))
+ OS << getOptionName(*DI->getDef());
+ else
+ OS << "INVALID";
+
+ // The option alias arguments (if any).
+ // Emitted as a \0 separated list in a string, e.g. ["foo", "bar"]
+ // would become "foo\0bar\0". Note that the compiler adds an implicit
+ // terminating \0 at the end.
+ OS << ", ";
+ std::vector<std::string> AliasArgs = R.getValueAsListOfStrings("AliasArgs");
+ if (AliasArgs.size() == 0) {
+ OS << "nullptr";
+ } else {
+ OS << "\"";
+ for (size_t i = 0, e = AliasArgs.size(); i != e; ++i)
+ OS << AliasArgs[i] << "\\0";
+ OS << "\"";
+ }
+
+ // The option flags.
+ OS << ", ";
+ int NumFlags = 0;
+ const ListInit *LI = R.getValueAsListInit("Flags");
+ for (Init *I : *LI)
+ OS << (NumFlags++ ? " | " : "")
+ << cast<DefInit>(I)->getDef()->getName();
+ if (GroupFlags) {
+ for (Init *I : *GroupFlags)
+ OS << (NumFlags++ ? " | " : "")
+ << cast<DefInit>(I)->getDef()->getName();
+ }
+ if (NumFlags == 0)
+ OS << '0';
+
+ // The option parameter field.
+ OS << ", " << R.getValueAsInt("NumArgs");
+
+ // The option help text.
+ if (!isa<UnsetInit>(R.getValueInit("HelpText"))) {
+ OS << ",\n";
+ OS << " ";
+ write_cstring(OS, R.getValueAsString("HelpText"));
+ } else
+ OS << ", nullptr";
+
+ // The option meta-variable name.
+ OS << ", ";
+ if (!isa<UnsetInit>(R.getValueInit("MetaVarName")))
+ write_cstring(OS, R.getValueAsString("MetaVarName"));
+ else
+ OS << "nullptr";
+
+ OS << ")\n";
+ }
+ OS << "#endif // OPTION\n";
+}
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp
new file mode 100644
index 000000000000..63bdd36235a0
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/PseudoLoweringEmitter.cpp
@@ -0,0 +1,301 @@
+//===- PseudoLoweringEmitter.cpp - PseudoLowering Generator -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenInstruction.h"
+#include "CodeGenTarget.h"
+#include "llvm/ADT/IndexedMap.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <vector>
+using namespace llvm;
+
+#define DEBUG_TYPE "pseudo-lowering"
+
+namespace {
+class PseudoLoweringEmitter {
+ struct OpData {
+ enum MapKind { Operand, Imm, Reg };
+ MapKind Kind;
+ union {
+ unsigned Operand; // Operand number mapped to.
+ uint64_t Imm; // Integer immedate value.
+ Record *Reg; // Physical register.
+ } Data;
+ };
+ struct PseudoExpansion {
+ CodeGenInstruction Source; // The source pseudo instruction definition.
+ CodeGenInstruction Dest; // The destination instruction to lower to.
+ IndexedMap<OpData> OperandMap;
+
+ PseudoExpansion(CodeGenInstruction &s, CodeGenInstruction &d,
+ IndexedMap<OpData> &m) :
+ Source(s), Dest(d), OperandMap(m) {}
+ };
+
+ RecordKeeper &Records;
+
+ // It's overkill to have an instance of the full CodeGenTarget object,
+ // but it loads everything on demand, not in the constructor, so it's
+ // lightweight in performance, so it works out OK.
+ CodeGenTarget Target;
+
+ SmallVector<PseudoExpansion, 64> Expansions;
+
+ unsigned addDagOperandMapping(Record *Rec, DagInit *Dag,
+ CodeGenInstruction &Insn,
+ IndexedMap<OpData> &OperandMap,
+ unsigned BaseIdx);
+ void evaluateExpansion(Record *Pseudo);
+ void emitLoweringEmitter(raw_ostream &o);
+public:
+ PseudoLoweringEmitter(RecordKeeper &R) : Records(R), Target(R) {}
+
+ /// run - Output the pseudo-lowerings.
+ void run(raw_ostream &o);
+};
+} // End anonymous namespace
+
+// FIXME: This pass currently can only expand a pseudo to a single instruction.
+// The pseudo expansion really should take a list of dags, not just
+// a single dag, so we can do fancier things.
+
+unsigned PseudoLoweringEmitter::
+addDagOperandMapping(Record *Rec, DagInit *Dag, CodeGenInstruction &Insn,
+ IndexedMap<OpData> &OperandMap, unsigned BaseIdx) {
+ unsigned OpsAdded = 0;
+ for (unsigned i = 0, e = Dag->getNumArgs(); i != e; ++i) {
+ if (DefInit *DI = dyn_cast<DefInit>(Dag->getArg(i))) {
+ // Physical register reference. Explicit check for the special case
+ // "zero_reg" definition.
+ if (DI->getDef()->isSubClassOf("Register") ||
+ DI->getDef()->getName() == "zero_reg") {
+ OperandMap[BaseIdx + i].Kind = OpData::Reg;
+ OperandMap[BaseIdx + i].Data.Reg = DI->getDef();
+ ++OpsAdded;
+ continue;
+ }
+
+ // Normal operands should always have the same type, or we have a
+ // problem.
+ // FIXME: We probably shouldn't ever get a non-zero BaseIdx here.
+ assert(BaseIdx == 0 && "Named subargument in pseudo expansion?!");
+ if (DI->getDef() != Insn.Operands[BaseIdx + i].Rec)
+ PrintFatalError(Rec->getLoc(),
+ "Pseudo operand type '" + DI->getDef()->getName() +
+ "' does not match expansion operand type '" +
+ Insn.Operands[BaseIdx + i].Rec->getName() + "'");
+ // Source operand maps to destination operand. The Data element
+ // will be filled in later, just set the Kind for now. Do it
+ // for each corresponding MachineInstr operand, not just the first.
+ for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
+ OperandMap[BaseIdx + i + I].Kind = OpData::Operand;
+ OpsAdded += Insn.Operands[i].MINumOperands;
+ } else if (IntInit *II = dyn_cast<IntInit>(Dag->getArg(i))) {
+ OperandMap[BaseIdx + i].Kind = OpData::Imm;
+ OperandMap[BaseIdx + i].Data.Imm = II->getValue();
+ ++OpsAdded;
+ } else if (DagInit *SubDag = dyn_cast<DagInit>(Dag->getArg(i))) {
+ // Just add the operands recursively. This is almost certainly
+ // a constant value for a complex operand (> 1 MI operand).
+ unsigned NewOps =
+ addDagOperandMapping(Rec, SubDag, Insn, OperandMap, BaseIdx + i);
+ OpsAdded += NewOps;
+ // Since we added more than one, we also need to adjust the base.
+ BaseIdx += NewOps - 1;
+ } else
+ llvm_unreachable("Unhandled pseudo-expansion argument type!");
+ }
+ return OpsAdded;
+}
+
+void PseudoLoweringEmitter::evaluateExpansion(Record *Rec) {
+ DEBUG(dbgs() << "Pseudo definition: " << Rec->getName() << "\n");
+
+ // Validate that the result pattern has the corrent number and types
+ // of arguments for the instruction it references.
+ DagInit *Dag = Rec->getValueAsDag("ResultInst");
+ assert(Dag && "Missing result instruction in pseudo expansion!");
+ DEBUG(dbgs() << " Result: " << *Dag << "\n");
+
+ DefInit *OpDef = dyn_cast<DefInit>(Dag->getOperator());
+ if (!OpDef)
+ PrintFatalError(Rec->getLoc(), Rec->getName() +
+ " has unexpected operator type!");
+ Record *Operator = OpDef->getDef();
+ if (!Operator->isSubClassOf("Instruction"))
+ PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
+ "' is not an instruction!");
+
+ CodeGenInstruction Insn(Operator);
+
+ if (Insn.isCodeGenOnly || Insn.isPseudo)
+ PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
+ "' cannot be another pseudo instruction!");
+
+ if (Insn.Operands.size() != Dag->getNumArgs())
+ PrintFatalError(Rec->getLoc(), "Pseudo result '" + Operator->getName() +
+ "' operand count mismatch");
+
+ unsigned NumMIOperands = 0;
+ for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i)
+ NumMIOperands += Insn.Operands[i].MINumOperands;
+ IndexedMap<OpData> OperandMap;
+ OperandMap.grow(NumMIOperands);
+
+ addDagOperandMapping(Rec, Dag, Insn, OperandMap, 0);
+
+ // If there are more operands that weren't in the DAG, they have to
+ // be operands that have default values, or we have an error. Currently,
+ // Operands that are a subclass of OperandWithDefaultOp have default values.
+
+ // Validate that each result pattern argument has a matching (by name)
+ // argument in the source instruction, in either the (outs) or (ins) list.
+ // Also check that the type of the arguments match.
+ //
+ // Record the mapping of the source to result arguments for use by
+ // the lowering emitter.
+ CodeGenInstruction SourceInsn(Rec);
+ StringMap<unsigned> SourceOperands;
+ for (unsigned i = 0, e = SourceInsn.Operands.size(); i != e; ++i)
+ SourceOperands[SourceInsn.Operands[i].Name] = i;
+
+ DEBUG(dbgs() << " Operand mapping:\n");
+ for (unsigned i = 0, e = Insn.Operands.size(); i != e; ++i) {
+ // We've already handled constant values. Just map instruction operands
+ // here.
+ if (OperandMap[Insn.Operands[i].MIOperandNo].Kind != OpData::Operand)
+ continue;
+ StringMap<unsigned>::iterator SourceOp =
+ SourceOperands.find(Dag->getArgNameStr(i));
+ if (SourceOp == SourceOperands.end())
+ PrintFatalError(Rec->getLoc(),
+ "Pseudo output operand '" + Dag->getArgNameStr(i) +
+ "' has no matching source operand.");
+ // Map the source operand to the destination operand index for each
+ // MachineInstr operand.
+ for (unsigned I = 0, E = Insn.Operands[i].MINumOperands; I != E; ++I)
+ OperandMap[Insn.Operands[i].MIOperandNo + I].Data.Operand =
+ SourceOp->getValue();
+
+ DEBUG(dbgs() << " " << SourceOp->getValue() << " ==> " << i << "\n");
+ }
+
+ Expansions.push_back(PseudoExpansion(SourceInsn, Insn, OperandMap));
+}
+
+void PseudoLoweringEmitter::emitLoweringEmitter(raw_ostream &o) {
+ // Emit file header.
+ emitSourceFileHeader("Pseudo-instruction MC lowering Source Fragment", o);
+
+ o << "bool " << Target.getName() + "AsmPrinter" << "::\n"
+ << "emitPseudoExpansionLowering(MCStreamer &OutStreamer,\n"
+ << " const MachineInstr *MI) {\n";
+
+ if (!Expansions.empty()) {
+ o << " switch (MI->getOpcode()) {\n"
+ << " default: return false;\n";
+ for (auto &Expansion : Expansions) {
+ CodeGenInstruction &Source = Expansion.Source;
+ CodeGenInstruction &Dest = Expansion.Dest;
+ o << " case " << Source.Namespace << "::"
+ << Source.TheDef->getName() << ": {\n"
+ << " MCInst TmpInst;\n"
+ << " MCOperand MCOp;\n"
+ << " TmpInst.setOpcode(" << Dest.Namespace << "::"
+ << Dest.TheDef->getName() << ");\n";
+
+ // Copy the operands from the source instruction.
+ // FIXME: Instruction operands with defaults values (predicates and cc_out
+ // in ARM, for example shouldn't need explicit values in the
+ // expansion DAG.
+ unsigned MIOpNo = 0;
+ for (const auto &DestOperand : Dest.Operands) {
+ o << " // Operand: " << DestOperand.Name << "\n";
+ for (unsigned i = 0, e = DestOperand.MINumOperands; i != e; ++i) {
+ switch (Expansion.OperandMap[MIOpNo + i].Kind) {
+ case OpData::Operand:
+ o << " lowerOperand(MI->getOperand("
+ << Source.Operands[Expansion.OperandMap[MIOpNo].Data
+ .Operand].MIOperandNo + i
+ << "), MCOp);\n"
+ << " TmpInst.addOperand(MCOp);\n";
+ break;
+ case OpData::Imm:
+ o << " TmpInst.addOperand(MCOperand::createImm("
+ << Expansion.OperandMap[MIOpNo + i].Data.Imm << "));\n";
+ break;
+ case OpData::Reg: {
+ Record *Reg = Expansion.OperandMap[MIOpNo + i].Data.Reg;
+ o << " TmpInst.addOperand(MCOperand::createReg(";
+ // "zero_reg" is special.
+ if (Reg->getName() == "zero_reg")
+ o << "0";
+ else
+ o << Reg->getValueAsString("Namespace") << "::"
+ << Reg->getName();
+ o << "));\n";
+ break;
+ }
+ }
+ }
+ MIOpNo += DestOperand.MINumOperands;
+ }
+ if (Dest.Operands.isVariadic) {
+ MIOpNo = Source.Operands.size() + 1;
+ o << " // variable_ops\n";
+ o << " for (unsigned i = " << MIOpNo
+ << ", e = MI->getNumOperands(); i != e; ++i)\n"
+ << " if (lowerOperand(MI->getOperand(i), MCOp))\n"
+ << " TmpInst.addOperand(MCOp);\n";
+ }
+ o << " EmitToStreamer(OutStreamer, TmpInst);\n"
+ << " break;\n"
+ << " }\n";
+ }
+ o << " }\n return true;";
+ } else
+ o << " return false;";
+
+ o << "\n}\n\n";
+}
+
+void PseudoLoweringEmitter::run(raw_ostream &o) {
+ Record *ExpansionClass = Records.getClass("PseudoInstExpansion");
+ Record *InstructionClass = Records.getClass("Instruction");
+ assert(ExpansionClass && "PseudoInstExpansion class definition missing!");
+ assert(InstructionClass && "Instruction class definition missing!");
+
+ std::vector<Record*> Insts;
+ for (const auto &D : Records.getDefs()) {
+ if (D.second->isSubClassOf(ExpansionClass) &&
+ D.second->isSubClassOf(InstructionClass))
+ Insts.push_back(D.second.get());
+ }
+
+ // Process the pseudo expansion definitions, validating them as we do so.
+ for (unsigned i = 0, e = Insts.size(); i != e; ++i)
+ evaluateExpansion(Insts[i]);
+
+ // Generate expansion code to lower the pseudo to an MCInst of the real
+ // instruction.
+ emitLoweringEmitter(o);
+}
+
+namespace llvm {
+
+void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS) {
+ PseudoLoweringEmitter(RK).run(OS);
+}
+
+} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/RegisterBankEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterBankEmitter.cpp
new file mode 100644
index 000000000000..bf066412b286
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/RegisterBankEmitter.cpp
@@ -0,0 +1,320 @@
+//===- RegisterBankEmitter.cpp - Generate a Register Bank Desc. -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting a description of a target
+// register bank for a code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/BitVector.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+#include "CodeGenRegisters.h"
+
+#define DEBUG_TYPE "register-bank-emitter"
+
+using namespace llvm;
+
+namespace {
+class RegisterBank {
+
+ /// A vector of register classes that are included in the register bank.
+ typedef std::vector<const CodeGenRegisterClass *> RegisterClassesTy;
+
+private:
+ const Record &TheDef;
+
+ /// The register classes that are covered by the register bank.
+ RegisterClassesTy RCs;
+
+ /// The register class with the largest register size.
+ const CodeGenRegisterClass *RCWithLargestRegsSize;
+
+public:
+ RegisterBank(const Record &TheDef)
+ : TheDef(TheDef), RCs(), RCWithLargestRegsSize(nullptr) {}
+
+ /// Get the human-readable name for the bank.
+ std::string getName() const { return TheDef.getValueAsString("Name"); }
+ /// Get the name of the enumerator in the ID enumeration.
+ std::string getEnumeratorName() const { return (TheDef.getName() + "ID").str(); }
+
+ /// Get the name of the array holding the register class coverage data;
+ std::string getCoverageArrayName() const {
+ return (TheDef.getName() + "CoverageData").str();
+ }
+
+ /// Get the name of the global instance variable.
+ StringRef getInstanceVarName() const { return TheDef.getName(); }
+
+ const Record &getDef() const { return TheDef; }
+
+ /// Get the register classes listed in the RegisterBank.RegisterClasses field.
+ std::vector<const CodeGenRegisterClass *>
+ getExplictlySpecifiedRegisterClasses(
+ CodeGenRegBank &RegisterClassHierarchy) const {
+ std::vector<const CodeGenRegisterClass *> RCs;
+ for (const auto &RCDef : getDef().getValueAsListOfDefs("RegisterClasses"))
+ RCs.push_back(RegisterClassHierarchy.getRegClass(RCDef));
+ return RCs;
+ }
+
+ /// Add a register class to the bank without duplicates.
+ void addRegisterClass(const CodeGenRegisterClass *RC) {
+ if (std::find_if(RCs.begin(), RCs.end(),
+ [&RC](const CodeGenRegisterClass *X) {
+ return X == RC;
+ }) != RCs.end())
+ return;
+
+ // FIXME? We really want the register size rather than the spill size
+ // since the spill size may be bigger on some targets with
+ // limited load/store instructions. However, we don't store the
+ // register size anywhere (we could sum the sizes of the subregisters
+ // but there may be additional bits too) and we can't derive it from
+ // the VT's reliably due to Untyped.
+ if (RCWithLargestRegsSize == nullptr)
+ RCWithLargestRegsSize = RC;
+ else if (RCWithLargestRegsSize->SpillSize < RC->SpillSize)
+ RCWithLargestRegsSize = RC;
+ assert(RCWithLargestRegsSize && "RC was nullptr?");
+
+ RCs.emplace_back(RC);
+ }
+
+ const CodeGenRegisterClass *getRCWithLargestRegsSize() const {
+ return RCWithLargestRegsSize;
+ }
+
+ iterator_range<typename RegisterClassesTy::const_iterator>
+ register_classes() const {
+ return llvm::make_range(RCs.begin(), RCs.end());
+ }
+};
+
+class RegisterBankEmitter {
+private:
+ RecordKeeper &Records;
+ CodeGenRegBank RegisterClassHierarchy;
+
+ void emitHeader(raw_ostream &OS, const StringRef TargetName,
+ const std::vector<RegisterBank> &Banks);
+ void emitBaseClassDefinition(raw_ostream &OS, const StringRef TargetName,
+ const std::vector<RegisterBank> &Banks);
+ void emitBaseClassImplementation(raw_ostream &OS, const StringRef TargetName,
+ std::vector<RegisterBank> &Banks);
+
+public:
+ RegisterBankEmitter(RecordKeeper &R)
+ : Records(R), RegisterClassHierarchy(Records) {}
+
+ void run(raw_ostream &OS);
+};
+
+} // end anonymous namespace
+
+/// Emit code to declare the ID enumeration and external global instance
+/// variables.
+void RegisterBankEmitter::emitHeader(raw_ostream &OS,
+ const StringRef TargetName,
+ const std::vector<RegisterBank> &Banks) {
+ // <Target>RegisterBankInfo.h
+ OS << "namespace llvm {\n"
+ << "namespace " << TargetName << " {\n"
+ << "enum {\n";
+ for (const auto &Bank : Banks)
+ OS << " " << Bank.getEnumeratorName() << ",\n";
+ OS << " NumRegisterBanks,\n"
+ << "};\n"
+ << "} // end namespace " << TargetName << "\n"
+ << "} // end namespace llvm\n";
+}
+
+/// Emit declarations of the <Target>GenRegisterBankInfo class.
+void RegisterBankEmitter::emitBaseClassDefinition(
+ raw_ostream &OS, const StringRef TargetName,
+ const std::vector<RegisterBank> &Banks) {
+ OS << "private:\n"
+ << " static RegisterBank *RegBanks[];\n\n"
+ << "protected:\n"
+ << " " << TargetName << "GenRegisterBankInfo();\n"
+ << "\n";
+}
+
+/// Visit each register class belonging to the given register bank.
+///
+/// A class belongs to the bank iff any of these apply:
+/// * It is explicitly specified
+/// * It is a subclass of a class that is a member.
+/// * It is a class containing subregisters of the registers of a class that
+/// is a member. This is known as a subreg-class.
+///
+/// This function must be called for each explicitly specified register class.
+///
+/// \param RC The register class to search.
+/// \param Kind A debug string containing the path the visitor took to reach RC.
+/// \param VisitFn The action to take for each class visited. It may be called
+/// multiple times for a given class if there are multiple paths
+/// to the class.
+static void visitRegisterBankClasses(
+ CodeGenRegBank &RegisterClassHierarchy, const CodeGenRegisterClass *RC,
+ const Twine Kind,
+ std::function<void(const CodeGenRegisterClass *, StringRef)> VisitFn,
+ SmallPtrSetImpl<const CodeGenRegisterClass *> &VisitedRCs) {
+
+ // Make sure we only visit each class once to avoid infinite loops.
+ if (VisitedRCs.count(RC))
+ return;
+ VisitedRCs.insert(RC);
+
+ // Visit each explicitly named class.
+ VisitFn(RC, Kind.str());
+
+ for (const auto &PossibleSubclass : RegisterClassHierarchy.getRegClasses()) {
+ std::string TmpKind =
+ (Twine(Kind) + " (" + PossibleSubclass.getName() + ")").str();
+
+ // Visit each subclass of an explicitly named class.
+ if (RC != &PossibleSubclass && RC->hasSubClass(&PossibleSubclass))
+ visitRegisterBankClasses(RegisterClassHierarchy, &PossibleSubclass,
+ TmpKind + " " + RC->getName() + " subclass",
+ VisitFn, VisitedRCs);
+
+ // Visit each class that contains only subregisters of RC with a common
+ // subregister-index.
+ //
+ // More precisely, PossibleSubclass is a subreg-class iff Reg:SubIdx is in
+ // PossibleSubclass for all registers Reg from RC using any
+ // subregister-index SubReg
+ for (const auto &SubIdx : RegisterClassHierarchy.getSubRegIndices()) {
+ BitVector BV(RegisterClassHierarchy.getRegClasses().size());
+ PossibleSubclass.getSuperRegClasses(&SubIdx, BV);
+ if (BV.test(RC->EnumValue)) {
+ std::string TmpKind2 = (Twine(TmpKind) + " " + RC->getName() +
+ " class-with-subregs: " + RC->getName())
+ .str();
+ VisitFn(&PossibleSubclass, TmpKind2);
+ }
+ }
+ }
+}
+
+void RegisterBankEmitter::emitBaseClassImplementation(
+ raw_ostream &OS, StringRef TargetName,
+ std::vector<RegisterBank> &Banks) {
+
+ OS << "namespace llvm {\n"
+ << "namespace " << TargetName << " {\n";
+ for (const auto &Bank : Banks) {
+ std::vector<std::vector<const CodeGenRegisterClass *>> RCsGroupedByWord(
+ (RegisterClassHierarchy.getRegClasses().size() + 31) / 32);
+
+ for (const auto &RC : Bank.register_classes())
+ RCsGroupedByWord[RC->EnumValue / 32].push_back(RC);
+
+ OS << "const uint32_t " << Bank.getCoverageArrayName() << "[] = {\n";
+ unsigned LowestIdxInWord = 0;
+ for (const auto &RCs : RCsGroupedByWord) {
+ OS << " // " << LowestIdxInWord << "-" << (LowestIdxInWord + 31) << "\n";
+ for (const auto &RC : RCs) {
+ std::string QualifiedRegClassID =
+ (Twine(TargetName) + "::" + RC->getName() + "RegClassID").str();
+ OS << " (1u << (" << QualifiedRegClassID << " - "
+ << LowestIdxInWord << ")) |\n";
+ }
+ OS << " 0,\n";
+ LowestIdxInWord += 32;
+ }
+ OS << "};\n";
+ }
+ OS << "\n";
+
+ for (const auto &Bank : Banks) {
+ std::string QualifiedBankID =
+ (TargetName + "::" + Bank.getEnumeratorName()).str();
+ unsigned Size = Bank.getRCWithLargestRegsSize()->SpillSize;
+ OS << "RegisterBank " << Bank.getInstanceVarName() << "(/* ID */ "
+ << QualifiedBankID << ", /* Name */ \"" << Bank.getName()
+ << "\", /* Size */ " << Size << ", "
+ << "/* CoveredRegClasses */ " << Bank.getCoverageArrayName()
+ << ", /* NumRegClasses */ "
+ << RegisterClassHierarchy.getRegClasses().size() << ");\n";
+ }
+ OS << "} // end namespace " << TargetName << "\n"
+ << "\n";
+
+ OS << "RegisterBank *" << TargetName
+ << "GenRegisterBankInfo::RegBanks[] = {\n";
+ for (const auto &Bank : Banks)
+ OS << " &" << TargetName << "::" << Bank.getInstanceVarName() << ",\n";
+ OS << "};\n\n";
+
+ OS << TargetName << "GenRegisterBankInfo::" << TargetName
+ << "GenRegisterBankInfo()\n"
+ << " : RegisterBankInfo(RegBanks, " << TargetName
+ << "::NumRegisterBanks) {\n"
+ << " // Assert that RegBank indices match their ID's\n"
+ << "#ifndef NDEBUG\n"
+ << " unsigned Index = 0;\n"
+ << " for (const auto &RB : RegBanks)\n"
+ << " assert(Index++ == RB->getID() && \"Index != ID\");\n"
+ << "#endif // NDEBUG\n"
+ << "}\n"
+ << "} // end namespace llvm\n";
+}
+
+void RegisterBankEmitter::run(raw_ostream &OS) {
+ std::vector<Record*> Targets = Records.getAllDerivedDefinitions("Target");
+ if (Targets.size() != 1)
+ PrintFatalError("ERROR: Too many or too few subclasses of Target defined!");
+ StringRef TargetName = Targets[0]->getName();
+
+ std::vector<RegisterBank> Banks;
+ for (const auto &V : Records.getAllDerivedDefinitions("RegisterBank")) {
+ SmallPtrSet<const CodeGenRegisterClass *, 8> VisitedRCs;
+ RegisterBank Bank(*V);
+
+ for (const CodeGenRegisterClass *RC :
+ Bank.getExplictlySpecifiedRegisterClasses(RegisterClassHierarchy)) {
+ visitRegisterBankClasses(
+ RegisterClassHierarchy, RC, "explicit",
+ [&Bank](const CodeGenRegisterClass *RC, StringRef Kind) {
+ DEBUG(dbgs() << "Added " << RC->getName() << "(" << Kind << ")\n");
+ Bank.addRegisterClass(RC);
+ }, VisitedRCs);
+ }
+
+ Banks.push_back(Bank);
+ }
+
+ emitSourceFileHeader("Register Bank Source Fragments", OS);
+ OS << "#ifdef GET_REGBANK_DECLARATIONS\n"
+ << "#undef GET_REGBANK_DECLARATIONS\n";
+ emitHeader(OS, TargetName, Banks);
+ OS << "#endif // GET_REGBANK_DECLARATIONS\n\n"
+ << "#ifdef GET_TARGET_REGBANK_CLASS\n"
+ << "#undef GET_TARGET_REGBANK_CLASS\n";
+ emitBaseClassDefinition(OS, TargetName, Banks);
+ OS << "#endif // GET_TARGET_REGBANK_CLASS\n\n"
+ << "#ifdef GET_TARGET_REGBANK_IMPL\n"
+ << "#undef GET_TARGET_REGBANK_IMPL\n";
+ emitBaseClassImplementation(OS, TargetName, Banks);
+ OS << "#endif // GET_TARGET_REGBANK_IMPL\n";
+}
+
+namespace llvm {
+
+void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS) {
+ RegisterBankEmitter(RK).run(OS);
+}
+
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
new file mode 100644
index 000000000000..5b56578a64b3
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -0,0 +1,1539 @@
+//===- RegisterInfoEmitter.cpp - Generate a Register File Desc. -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend is responsible for emitting a description of a target
+// register file for a code generator. It uses instances of the Register,
+// RegisterAliases, and RegisterClass classes to gather this information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenRegisters.h"
+#include "CodeGenTarget.h"
+#include "Types.h"
+#include "SequenceToOffsetTable.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/SparseBitVector.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/CodeGen/MachineValueType.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/SetTheory.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <algorithm>
+#include <cassert>
+#include <cstddef>
+#include <cstdint>
+#include <deque>
+#include <iterator>
+#include <set>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+
+class RegisterInfoEmitter {
+ RecordKeeper &Records;
+
+public:
+ RegisterInfoEmitter(RecordKeeper &R) : Records(R) {}
+
+ // runEnums - Print out enum values for all of the registers.
+ void runEnums(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank);
+
+ // runMCDesc - Print out MC register descriptions.
+ void runMCDesc(raw_ostream &o, CodeGenTarget &Target, CodeGenRegBank &Bank);
+
+ // runTargetHeader - Emit a header fragment for the register info emitter.
+ void runTargetHeader(raw_ostream &o, CodeGenTarget &Target,
+ CodeGenRegBank &Bank);
+
+ // runTargetDesc - Output the target register and register file descriptions.
+ void runTargetDesc(raw_ostream &o, CodeGenTarget &Target,
+ CodeGenRegBank &Bank);
+
+ // run - Output the register file description.
+ void run(raw_ostream &o);
+
+private:
+ void EmitRegMapping(raw_ostream &o, const std::deque<CodeGenRegister> &Regs,
+ bool isCtor);
+ void EmitRegMappingTables(raw_ostream &o,
+ const std::deque<CodeGenRegister> &Regs,
+ bool isCtor);
+ void EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
+ const std::string &ClassName);
+ void emitComposeSubRegIndices(raw_ostream &OS, CodeGenRegBank &RegBank,
+ const std::string &ClassName);
+ void emitComposeSubRegIndexLaneMask(raw_ostream &OS, CodeGenRegBank &RegBank,
+ const std::string &ClassName);
+};
+
+} // end anonymous namespace
+
+// runEnums - Print out enum values for all of the registers.
+void RegisterInfoEmitter::runEnums(raw_ostream &OS,
+ CodeGenTarget &Target, CodeGenRegBank &Bank) {
+ const auto &Registers = Bank.getRegisters();
+
+ // Register enums are stored as uint16_t in the tables. Make sure we'll fit.
+ assert(Registers.size() <= 0xffff && "Too many regs to fit in tables");
+
+ std::string Namespace =
+ Registers.front().TheDef->getValueAsString("Namespace");
+
+ emitSourceFileHeader("Target Register Enum Values", OS);
+
+ OS << "\n#ifdef GET_REGINFO_ENUM\n";
+ OS << "#undef GET_REGINFO_ENUM\n\n";
+
+ OS << "namespace llvm {\n\n";
+
+ OS << "class MCRegisterClass;\n"
+ << "extern const MCRegisterClass " << Target.getName()
+ << "MCRegisterClasses[];\n\n";
+
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << "enum {\n NoRegister,\n";
+
+ for (const auto &Reg : Registers)
+ OS << " " << Reg.getName() << " = " << Reg.EnumValue << ",\n";
+ assert(Registers.size() == Registers.back().EnumValue &&
+ "Register enum value mismatch!");
+ OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
+ OS << "};\n";
+ if (!Namespace.empty())
+ OS << "} // end namespace " << Namespace << "\n";
+
+ const auto &RegisterClasses = Bank.getRegClasses();
+ if (!RegisterClasses.empty()) {
+
+ // RegisterClass enums are stored as uint16_t in the tables.
+ assert(RegisterClasses.size() <= 0xffff &&
+ "Too many register classes to fit in tables");
+
+ OS << "\n// Register classes\n\n";
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << "enum {\n";
+ for (const auto &RC : RegisterClasses)
+ OS << " " << RC.getName() << "RegClassID"
+ << " = " << RC.EnumValue << ",\n";
+ OS << "\n };\n";
+ if (!Namespace.empty())
+ OS << "} // end namespace " << Namespace << "\n\n";
+ }
+
+ const std::vector<Record*> &RegAltNameIndices = Target.getRegAltNameIndices();
+ // If the only definition is the default NoRegAltName, we don't need to
+ // emit anything.
+ if (RegAltNameIndices.size() > 1) {
+ OS << "\n// Register alternate name indices\n\n";
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << "enum {\n";
+ for (unsigned i = 0, e = RegAltNameIndices.size(); i != e; ++i)
+ OS << " " << RegAltNameIndices[i]->getName() << ",\t// " << i << "\n";
+ OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n";
+ OS << "};\n";
+ if (!Namespace.empty())
+ OS << "} // end namespace " << Namespace << "\n\n";
+ }
+
+ auto &SubRegIndices = Bank.getSubRegIndices();
+ if (!SubRegIndices.empty()) {
+ OS << "\n// Subregister indices\n\n";
+ std::string Namespace = SubRegIndices.front().getNamespace();
+ if (!Namespace.empty())
+ OS << "namespace " << Namespace << " {\n";
+ OS << "enum {\n NoSubRegister,\n";
+ unsigned i = 0;
+ for (const auto &Idx : SubRegIndices)
+ OS << " " << Idx.getName() << ",\t// " << ++i << "\n";
+ OS << " NUM_TARGET_SUBREGS\n};\n";
+ if (!Namespace.empty())
+ OS << "} // end namespace " << Namespace << "\n\n";
+ }
+
+ OS << "} // end namespace llvm\n\n";
+ OS << "#endif // GET_REGINFO_ENUM\n\n";
+}
+
+static void printInt(raw_ostream &OS, int Val) {
+ OS << Val;
+}
+
+void RegisterInfoEmitter::
+EmitRegUnitPressure(raw_ostream &OS, const CodeGenRegBank &RegBank,
+ const std::string &ClassName) {
+ unsigned NumRCs = RegBank.getRegClasses().size();
+ unsigned NumSets = RegBank.getNumRegPressureSets();
+
+ OS << "/// Get the weight in units of pressure for this register class.\n"
+ << "const RegClassWeight &" << ClassName << "::\n"
+ << "getRegClassWeight(const TargetRegisterClass *RC) const {\n"
+ << " static const RegClassWeight RCWeightTable[] = {\n";
+ for (const auto &RC : RegBank.getRegClasses()) {
+ const CodeGenRegister::Vec &Regs = RC.getMembers();
+ if (Regs.empty())
+ OS << " {0, 0";
+ else {
+ std::vector<unsigned> RegUnits;
+ RC.buildRegUnitSet(RegUnits);
+ OS << " {" << (*Regs.begin())->getWeight(RegBank)
+ << ", " << RegBank.getRegUnitSetWeight(RegUnits);
+ }
+ OS << "}, \t// " << RC.getName() << "\n";
+ }
+ OS << " };\n"
+ << " return RCWeightTable[RC->getID()];\n"
+ << "}\n\n";
+
+ // Reasonable targets (not ARMv7) have unit weight for all units, so don't
+ // bother generating a table.
+ bool RegUnitsHaveUnitWeight = true;
+ for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits();
+ UnitIdx < UnitEnd; ++UnitIdx) {
+ if (RegBank.getRegUnit(UnitIdx).Weight > 1)
+ RegUnitsHaveUnitWeight = false;
+ }
+ OS << "/// Get the weight in units of pressure for this register unit.\n"
+ << "unsigned " << ClassName << "::\n"
+ << "getRegUnitWeight(unsigned RegUnit) const {\n"
+ << " assert(RegUnit < " << RegBank.getNumNativeRegUnits()
+ << " && \"invalid register unit\");\n";
+ if (!RegUnitsHaveUnitWeight) {
+ OS << " static const uint8_t RUWeightTable[] = {\n ";
+ for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits();
+ UnitIdx < UnitEnd; ++UnitIdx) {
+ const RegUnit &RU = RegBank.getRegUnit(UnitIdx);
+ assert(RU.Weight < 256 && "RegUnit too heavy");
+ OS << RU.Weight << ", ";
+ }
+ OS << "};\n"
+ << " return RUWeightTable[RegUnit];\n";
+ }
+ else {
+ OS << " // All register units have unit weight.\n"
+ << " return 1;\n";
+ }
+ OS << "}\n\n";
+
+ OS << "\n"
+ << "// Get the number of dimensions of register pressure.\n"
+ << "unsigned " << ClassName << "::getNumRegPressureSets() const {\n"
+ << " return " << NumSets << ";\n}\n\n";
+
+ OS << "// Get the name of this register unit pressure set.\n"
+ << "const char *" << ClassName << "::\n"
+ << "getRegPressureSetName(unsigned Idx) const {\n"
+ << " static const char *const PressureNameTable[] = {\n";
+ unsigned MaxRegUnitWeight = 0;
+ for (unsigned i = 0; i < NumSets; ++i ) {
+ const RegUnitSet &RegUnits = RegBank.getRegSetAt(i);
+ MaxRegUnitWeight = std::max(MaxRegUnitWeight, RegUnits.Weight);
+ OS << " \"" << RegUnits.Name << "\",\n";
+ }
+ OS << " };\n"
+ << " return PressureNameTable[Idx];\n"
+ << "}\n\n";
+
+ OS << "// Get the register unit pressure limit for this dimension.\n"
+ << "// This limit must be adjusted dynamically for reserved registers.\n"
+ << "unsigned " << ClassName << "::\n"
+ << "getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const "
+ "{\n"
+ << " static const " << getMinimalTypeForRange(MaxRegUnitWeight, 32)
+ << " PressureLimitTable[] = {\n";
+ for (unsigned i = 0; i < NumSets; ++i ) {
+ const RegUnitSet &RegUnits = RegBank.getRegSetAt(i);
+ OS << " " << RegUnits.Weight << ", \t// " << i << ": "
+ << RegUnits.Name << "\n";
+ }
+ OS << " };\n"
+ << " return PressureLimitTable[Idx];\n"
+ << "}\n\n";
+
+ SequenceToOffsetTable<std::vector<int>> PSetsSeqs;
+
+ // This table may be larger than NumRCs if some register units needed a list
+ // of unit sets that did not correspond to a register class.
+ unsigned NumRCUnitSets = RegBank.getNumRegClassPressureSetLists();
+ std::vector<std::vector<int>> PSets(NumRCUnitSets);
+
+ for (unsigned i = 0, e = NumRCUnitSets; i != e; ++i) {
+ ArrayRef<unsigned> PSetIDs = RegBank.getRCPressureSetIDs(i);
+ PSets[i].reserve(PSetIDs.size());
+ for (ArrayRef<unsigned>::iterator PSetI = PSetIDs.begin(),
+ PSetE = PSetIDs.end(); PSetI != PSetE; ++PSetI) {
+ PSets[i].push_back(RegBank.getRegPressureSet(*PSetI).Order);
+ }
+ std::sort(PSets[i].begin(), PSets[i].end());
+ PSetsSeqs.add(PSets[i]);
+ }
+
+ PSetsSeqs.layout();
+
+ OS << "/// Table of pressure sets per register class or unit.\n"
+ << "static const int RCSetsTable[] = {\n";
+ PSetsSeqs.emit(OS, printInt, "-1");
+ OS << "};\n\n";
+
+ OS << "/// Get the dimensions of register pressure impacted by this "
+ << "register class.\n"
+ << "/// Returns a -1 terminated array of pressure set IDs\n"
+ << "const int* " << ClassName << "::\n"
+ << "getRegClassPressureSets(const TargetRegisterClass *RC) const {\n";
+ OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32)
+ << " RCSetStartTable[] = {\n ";
+ for (unsigned i = 0, e = NumRCs; i != e; ++i) {
+ OS << PSetsSeqs.get(PSets[i]) << ",";
+ }
+ OS << "};\n"
+ << " return &RCSetsTable[RCSetStartTable[RC->getID()]];\n"
+ << "}\n\n";
+
+ OS << "/// Get the dimensions of register pressure impacted by this "
+ << "register unit.\n"
+ << "/// Returns a -1 terminated array of pressure set IDs\n"
+ << "const int* " << ClassName << "::\n"
+ << "getRegUnitPressureSets(unsigned RegUnit) const {\n"
+ << " assert(RegUnit < " << RegBank.getNumNativeRegUnits()
+ << " && \"invalid register unit\");\n";
+ OS << " static const " << getMinimalTypeForRange(PSetsSeqs.size() - 1, 32)
+ << " RUSetStartTable[] = {\n ";
+ for (unsigned UnitIdx = 0, UnitEnd = RegBank.getNumNativeRegUnits();
+ UnitIdx < UnitEnd; ++UnitIdx) {
+ OS << PSetsSeqs.get(PSets[RegBank.getRegUnit(UnitIdx).RegClassUnitSetsIdx])
+ << ",";
+ }
+ OS << "};\n"
+ << " return &RCSetsTable[RUSetStartTable[RegUnit]];\n"
+ << "}\n\n";
+}
+
+void RegisterInfoEmitter::EmitRegMappingTables(
+ raw_ostream &OS, const std::deque<CodeGenRegister> &Regs, bool isCtor) {
+ // Collect all information about dwarf register numbers
+ typedef std::map<Record*, std::vector<int64_t>, LessRecordRegister> DwarfRegNumsMapTy;
+ DwarfRegNumsMapTy DwarfRegNums;
+
+ // First, just pull all provided information to the map
+ unsigned maxLength = 0;
+ for (auto &RE : Regs) {
+ Record *Reg = RE.TheDef;
+ std::vector<int64_t> RegNums = Reg->getValueAsListOfInts("DwarfNumbers");
+ maxLength = std::max((size_t)maxLength, RegNums.size());
+ if (DwarfRegNums.count(Reg))
+ PrintWarning(Reg->getLoc(), Twine("DWARF numbers for register ") +
+ getQualifiedName(Reg) + "specified multiple times");
+ DwarfRegNums[Reg] = RegNums;
+ }
+
+ if (!maxLength)
+ return;
+
+ // Now we know maximal length of number list. Append -1's, where needed
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I)
+ for (unsigned i = I->second.size(), e = maxLength; i != e; ++i)
+ I->second.push_back(-1);
+
+ std::string Namespace = Regs.front().TheDef->getValueAsString("Namespace");
+
+ OS << "// " << Namespace << " Dwarf<->LLVM register mappings.\n";
+
+ // Emit reverse information about the dwarf register numbers.
+ for (unsigned j = 0; j < 2; ++j) {
+ for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace;
+ OS << (j == 0 ? "DwarfFlavour" : "EHFlavour");
+ OS << i << "Dwarf2L[]";
+
+ if (!isCtor) {
+ OS << " = {\n";
+
+ // Store the mapping sorted by the LLVM reg num so lookup can be done
+ // with a binary search.
+ std::map<uint64_t, Record*> Dwarf2LMap;
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
+ int DwarfRegNo = I->second[i];
+ if (DwarfRegNo < 0)
+ continue;
+ Dwarf2LMap[DwarfRegNo] = I->first;
+ }
+
+ for (std::map<uint64_t, Record*>::iterator
+ I = Dwarf2LMap.begin(), E = Dwarf2LMap.end(); I != E; ++I)
+ OS << " { " << I->first << "U, " << getQualifiedName(I->second)
+ << " },\n";
+
+ OS << "};\n";
+ } else {
+ OS << ";\n";
+ }
+
+ // We have to store the size in a const global, it's used in multiple
+ // places.
+ OS << "extern const unsigned " << Namespace
+ << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "Dwarf2LSize";
+ if (!isCtor)
+ OS << " = array_lengthof(" << Namespace
+ << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
+ << "Dwarf2L);\n\n";
+ else
+ OS << ";\n\n";
+ }
+ }
+
+ for (auto &RE : Regs) {
+ Record *Reg = RE.TheDef;
+ const RecordVal *V = Reg->getValue("DwarfAlias");
+ if (!V || !V->getValue())
+ continue;
+
+ DefInit *DI = cast<DefInit>(V->getValue());
+ Record *Alias = DI->getDef();
+ DwarfRegNums[Reg] = DwarfRegNums[Alias];
+ }
+
+ // Emit information about the dwarf register numbers.
+ for (unsigned j = 0; j < 2; ++j) {
+ for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ OS << "extern const MCRegisterInfo::DwarfLLVMRegPair " << Namespace;
+ OS << (j == 0 ? "DwarfFlavour" : "EHFlavour");
+ OS << i << "L2Dwarf[]";
+ if (!isCtor) {
+ OS << " = {\n";
+ // Store the mapping sorted by the Dwarf reg num so lookup can be done
+ // with a binary search.
+ for (DwarfRegNumsMapTy::iterator
+ I = DwarfRegNums.begin(), E = DwarfRegNums.end(); I != E; ++I) {
+ int RegNo = I->second[i];
+ if (RegNo == -1) // -1 is the default value, don't emit a mapping.
+ continue;
+
+ OS << " { " << getQualifiedName(I->first) << ", " << RegNo
+ << "U },\n";
+ }
+ OS << "};\n";
+ } else {
+ OS << ";\n";
+ }
+
+ // We have to store the size in a const global, it's used in multiple
+ // places.
+ OS << "extern const unsigned " << Namespace
+ << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2DwarfSize";
+ if (!isCtor)
+ OS << " = array_lengthof(" << Namespace
+ << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i << "L2Dwarf);\n\n";
+ else
+ OS << ";\n\n";
+ }
+ }
+}
+
+void RegisterInfoEmitter::EmitRegMapping(
+ raw_ostream &OS, const std::deque<CodeGenRegister> &Regs, bool isCtor) {
+ // Emit the initializer so the tables from EmitRegMappingTables get wired up
+ // to the MCRegisterInfo object.
+ unsigned maxLength = 0;
+ for (auto &RE : Regs) {
+ Record *Reg = RE.TheDef;
+ maxLength = std::max((size_t)maxLength,
+ Reg->getValueAsListOfInts("DwarfNumbers").size());
+ }
+
+ if (!maxLength)
+ return;
+
+ std::string Namespace = Regs.front().TheDef->getValueAsString("Namespace");
+
+ // Emit reverse information about the dwarf register numbers.
+ for (unsigned j = 0; j < 2; ++j) {
+ OS << " switch (";
+ if (j == 0)
+ OS << "DwarfFlavour";
+ else
+ OS << "EHFlavour";
+ OS << ") {\n"
+ << " default:\n"
+ << " llvm_unreachable(\"Unknown DWARF flavour\");\n";
+
+ for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ OS << " case " << i << ":\n";
+ OS << " ";
+ if (!isCtor)
+ OS << "RI->";
+ std::string Tmp;
+ raw_string_ostream(Tmp) << Namespace
+ << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
+ << "Dwarf2L";
+ OS << "mapDwarfRegsToLLVMRegs(" << Tmp << ", " << Tmp << "Size, ";
+ if (j == 0)
+ OS << "false";
+ else
+ OS << "true";
+ OS << ");\n";
+ OS << " break;\n";
+ }
+ OS << " }\n";
+ }
+
+ // Emit information about the dwarf register numbers.
+ for (unsigned j = 0; j < 2; ++j) {
+ OS << " switch (";
+ if (j == 0)
+ OS << "DwarfFlavour";
+ else
+ OS << "EHFlavour";
+ OS << ") {\n"
+ << " default:\n"
+ << " llvm_unreachable(\"Unknown DWARF flavour\");\n";
+
+ for (unsigned i = 0, e = maxLength; i != e; ++i) {
+ OS << " case " << i << ":\n";
+ OS << " ";
+ if (!isCtor)
+ OS << "RI->";
+ std::string Tmp;
+ raw_string_ostream(Tmp) << Namespace
+ << (j == 0 ? "DwarfFlavour" : "EHFlavour") << i
+ << "L2Dwarf";
+ OS << "mapLLVMRegsToDwarfRegs(" << Tmp << ", " << Tmp << "Size, ";
+ if (j == 0)
+ OS << "false";
+ else
+ OS << "true";
+ OS << ");\n";
+ OS << " break;\n";
+ }
+ OS << " }\n";
+ }
+}
+
+// Print a BitVector as a sequence of hex numbers using a little-endian mapping.
+// Width is the number of bits per hex number.
+static void printBitVectorAsHex(raw_ostream &OS,
+ const BitVector &Bits,
+ unsigned Width) {
+ assert(Width <= 32 && "Width too large");
+ unsigned Digits = (Width + 3) / 4;
+ for (unsigned i = 0, e = Bits.size(); i < e; i += Width) {
+ unsigned Value = 0;
+ for (unsigned j = 0; j != Width && i + j != e; ++j)
+ Value |= Bits.test(i + j) << j;
+ OS << format("0x%0*x, ", Digits, Value);
+ }
+}
+
+// Helper to emit a set of bits into a constant byte array.
+class BitVectorEmitter {
+ BitVector Values;
+public:
+ void add(unsigned v) {
+ if (v >= Values.size())
+ Values.resize(((v/8)+1)*8); // Round up to the next byte.
+ Values[v] = true;
+ }
+
+ void print(raw_ostream &OS) {
+ printBitVectorAsHex(OS, Values, 8);
+ }
+};
+
+static void printSimpleValueType(raw_ostream &OS, MVT::SimpleValueType VT) {
+ OS << getEnumName(VT);
+}
+
+static void printSubRegIndex(raw_ostream &OS, const CodeGenSubRegIndex *Idx) {
+ OS << Idx->EnumValue;
+}
+
+// Differentially encoded register and regunit lists allow for better
+// compression on regular register banks. The sequence is computed from the
+// differential list as:
+//
+// out[0] = InitVal;
+// out[n+1] = out[n] + diff[n]; // n = 0, 1, ...
+//
+// The initial value depends on the specific list. The list is terminated by a
+// 0 differential which means we can't encode repeated elements.
+
+typedef SmallVector<uint16_t, 4> DiffVec;
+typedef SmallVector<LaneBitmask, 4> MaskVec;
+
+// Differentially encode a sequence of numbers into V. The starting value and
+// terminating 0 are not added to V, so it will have the same size as List.
+static
+DiffVec &diffEncode(DiffVec &V, unsigned InitVal, SparseBitVector<> List) {
+ assert(V.empty() && "Clear DiffVec before diffEncode.");
+ uint16_t Val = uint16_t(InitVal);
+
+ for (uint16_t Cur : List) {
+ V.push_back(Cur - Val);
+ Val = Cur;
+ }
+ return V;
+}
+
+template<typename Iter>
+static
+DiffVec &diffEncode(DiffVec &V, unsigned InitVal, Iter Begin, Iter End) {
+ assert(V.empty() && "Clear DiffVec before diffEncode.");
+ uint16_t Val = uint16_t(InitVal);
+ for (Iter I = Begin; I != End; ++I) {
+ uint16_t Cur = (*I)->EnumValue;
+ V.push_back(Cur - Val);
+ Val = Cur;
+ }
+ return V;
+}
+
+static void printDiff16(raw_ostream &OS, uint16_t Val) {
+ OS << Val;
+}
+
+static void printMask(raw_ostream &OS, LaneBitmask Val) {
+ OS << "LaneBitmask(0x" << PrintLaneMask(Val) << ')';
+}
+
+// Try to combine Idx's compose map into Vec if it is compatible.
+// Return false if it's not possible.
+static bool combine(const CodeGenSubRegIndex *Idx,
+ SmallVectorImpl<CodeGenSubRegIndex*> &Vec) {
+ const CodeGenSubRegIndex::CompMap &Map = Idx->getComposites();
+ for (const auto &I : Map) {
+ CodeGenSubRegIndex *&Entry = Vec[I.first->EnumValue - 1];
+ if (Entry && Entry != I.second)
+ return false;
+ }
+
+ // All entries are compatible. Make it so.
+ for (const auto &I : Map) {
+ auto *&Entry = Vec[I.first->EnumValue - 1];
+ assert((!Entry || Entry == I.second) &&
+ "Expected EnumValue to be unique");
+ Entry = I.second;
+ }
+ return true;
+}
+
+void
+RegisterInfoEmitter::emitComposeSubRegIndices(raw_ostream &OS,
+ CodeGenRegBank &RegBank,
+ const std::string &ClName) {
+ const auto &SubRegIndices = RegBank.getSubRegIndices();
+ OS << "unsigned " << ClName
+ << "::composeSubRegIndicesImpl(unsigned IdxA, unsigned IdxB) const {\n";
+
+ // Many sub-register indexes are composition-compatible, meaning that
+ //
+ // compose(IdxA, IdxB) == compose(IdxA', IdxB)
+ //
+ // for many IdxA, IdxA' pairs. Not all sub-register indexes can be composed.
+ // The illegal entries can be use as wildcards to compress the table further.
+
+ // Map each Sub-register index to a compatible table row.
+ SmallVector<unsigned, 4> RowMap;
+ SmallVector<SmallVector<CodeGenSubRegIndex*, 4>, 4> Rows;
+
+ auto SubRegIndicesSize =
+ std::distance(SubRegIndices.begin(), SubRegIndices.end());
+ for (const auto &Idx : SubRegIndices) {
+ unsigned Found = ~0u;
+ for (unsigned r = 0, re = Rows.size(); r != re; ++r) {
+ if (combine(&Idx, Rows[r])) {
+ Found = r;
+ break;
+ }
+ }
+ if (Found == ~0u) {
+ Found = Rows.size();
+ Rows.resize(Found + 1);
+ Rows.back().resize(SubRegIndicesSize);
+ combine(&Idx, Rows.back());
+ }
+ RowMap.push_back(Found);
+ }
+
+ // Output the row map if there is multiple rows.
+ if (Rows.size() > 1) {
+ OS << " static const " << getMinimalTypeForRange(Rows.size(), 32)
+ << " RowMap[" << SubRegIndicesSize << "] = {\n ";
+ for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i)
+ OS << RowMap[i] << ", ";
+ OS << "\n };\n";
+ }
+
+ // Output the rows.
+ OS << " static const " << getMinimalTypeForRange(SubRegIndicesSize + 1, 32)
+ << " Rows[" << Rows.size() << "][" << SubRegIndicesSize << "] = {\n";
+ for (unsigned r = 0, re = Rows.size(); r != re; ++r) {
+ OS << " { ";
+ for (unsigned i = 0, e = SubRegIndicesSize; i != e; ++i)
+ if (Rows[r][i])
+ OS << Rows[r][i]->EnumValue << ", ";
+ else
+ OS << "0, ";
+ OS << "},\n";
+ }
+ OS << " };\n\n";
+
+ OS << " --IdxA; assert(IdxA < " << SubRegIndicesSize << ");\n"
+ << " --IdxB; assert(IdxB < " << SubRegIndicesSize << ");\n";
+ if (Rows.size() > 1)
+ OS << " return Rows[RowMap[IdxA]][IdxB];\n";
+ else
+ OS << " return Rows[0][IdxB];\n";
+ OS << "}\n\n";
+}
+
+void
+RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
+ CodeGenRegBank &RegBank,
+ const std::string &ClName) {
+ // See the comments in computeSubRegLaneMasks() for our goal here.
+ const auto &SubRegIndices = RegBank.getSubRegIndices();
+
+ // Create a list of Mask+Rotate operations, with equivalent entries merged.
+ SmallVector<unsigned, 4> SubReg2SequenceIndexMap;
+ SmallVector<SmallVector<MaskRolPair, 1>, 4> Sequences;
+ for (const auto &Idx : SubRegIndices) {
+ const SmallVector<MaskRolPair, 1> &IdxSequence
+ = Idx.CompositionLaneMaskTransform;
+
+ unsigned Found = ~0u;
+ unsigned SIdx = 0;
+ unsigned NextSIdx;
+ for (size_t s = 0, se = Sequences.size(); s != se; ++s, SIdx = NextSIdx) {
+ SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s];
+ NextSIdx = SIdx + Sequence.size() + 1;
+ if (Sequence == IdxSequence) {
+ Found = SIdx;
+ break;
+ }
+ }
+ if (Found == ~0u) {
+ Sequences.push_back(IdxSequence);
+ Found = SIdx;
+ }
+ SubReg2SequenceIndexMap.push_back(Found);
+ }
+
+ OS << " struct MaskRolOp {\n"
+ " LaneBitmask Mask;\n"
+ " uint8_t RotateLeft;\n"
+ " };\n"
+ " static const MaskRolOp LaneMaskComposeSequences[] = {\n";
+ unsigned Idx = 0;
+ for (size_t s = 0, se = Sequences.size(); s != se; ++s) {
+ OS << " ";
+ const SmallVectorImpl<MaskRolPair> &Sequence = Sequences[s];
+ for (size_t p = 0, pe = Sequence.size(); p != pe; ++p) {
+ const MaskRolPair &P = Sequence[p];
+ printMask(OS << "{ ", P.Mask);
+ OS << format(", %2u }, ", P.RotateLeft);
+ }
+ OS << "{ LaneBitmask::getNone(), 0 }";
+ if (s+1 != se)
+ OS << ", ";
+ OS << " // Sequence " << Idx << "\n";
+ Idx += Sequence.size() + 1;
+ }
+ OS << " };\n"
+ " static const MaskRolOp *const CompositeSequences[] = {\n";
+ for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) {
+ OS << " ";
+ unsigned Idx = SubReg2SequenceIndexMap[i];
+ OS << format("&LaneMaskComposeSequences[%u]", Idx);
+ if (i+1 != e)
+ OS << ",";
+ OS << " // to " << SubRegIndices[i].getName() << "\n";
+ }
+ OS << " };\n\n";
+
+ OS << "LaneBitmask " << ClName
+ << "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, LaneBitmask LaneMask)"
+ " const {\n"
+ " --IdxA; assert(IdxA < " << SubRegIndices.size()
+ << " && \"Subregister index out of bounds\");\n"
+ " LaneBitmask Result;\n"
+ " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask.any(); ++Ops) {\n"
+ " LaneBitmask::Type M = LaneMask.getAsInteger() & Ops->Mask.getAsInteger();\n"
+ " if (unsigned S = Ops->RotateLeft)\n"
+ " Result |= LaneBitmask((M << S) | (M >> (LaneBitmask::BitWidth - S)));\n"
+ " else\n"
+ " Result |= LaneBitmask(M);\n"
+ " }\n"
+ " return Result;\n"
+ "}\n\n";
+
+ OS << "LaneBitmask " << ClName
+ << "::reverseComposeSubRegIndexLaneMaskImpl(unsigned IdxA, "
+ " LaneBitmask LaneMask) const {\n"
+ " LaneMask &= getSubRegIndexLaneMask(IdxA);\n"
+ " --IdxA; assert(IdxA < " << SubRegIndices.size()
+ << " && \"Subregister index out of bounds\");\n"
+ " LaneBitmask Result;\n"
+ " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask.any(); ++Ops) {\n"
+ " LaneBitmask::Type M = LaneMask.getAsInteger();\n"
+ " if (unsigned S = Ops->RotateLeft)\n"
+ " Result |= LaneBitmask((M >> S) | (M << (LaneBitmask::BitWidth - S)));\n"
+ " else\n"
+ " Result |= LaneBitmask(M);\n"
+ " }\n"
+ " return Result;\n"
+ "}\n\n";
+}
+
+//
+// runMCDesc - Print out MC register descriptions.
+//
+void
+RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
+ CodeGenRegBank &RegBank) {
+ emitSourceFileHeader("MC Register Information", OS);
+
+ OS << "\n#ifdef GET_REGINFO_MC_DESC\n";
+ OS << "#undef GET_REGINFO_MC_DESC\n\n";
+
+ const auto &Regs = RegBank.getRegisters();
+
+ auto &SubRegIndices = RegBank.getSubRegIndices();
+ // The lists of sub-registers and super-registers go in the same array. That
+ // allows us to share suffixes.
+ typedef std::vector<const CodeGenRegister*> RegVec;
+
+ // Differentially encoded lists.
+ SequenceToOffsetTable<DiffVec> DiffSeqs;
+ SmallVector<DiffVec, 4> SubRegLists(Regs.size());
+ SmallVector<DiffVec, 4> SuperRegLists(Regs.size());
+ SmallVector<DiffVec, 4> RegUnitLists(Regs.size());
+ SmallVector<unsigned, 4> RegUnitInitScale(Regs.size());
+
+ // List of lane masks accompanying register unit sequences.
+ SequenceToOffsetTable<MaskVec> LaneMaskSeqs;
+ SmallVector<MaskVec, 4> RegUnitLaneMasks(Regs.size());
+
+ // Keep track of sub-register names as well. These are not differentially
+ // encoded.
+ typedef SmallVector<const CodeGenSubRegIndex*, 4> SubRegIdxVec;
+ SequenceToOffsetTable<SubRegIdxVec, deref<llvm::less>> SubRegIdxSeqs;
+ SmallVector<SubRegIdxVec, 4> SubRegIdxLists(Regs.size());
+
+ SequenceToOffsetTable<std::string> RegStrings;
+
+ // Precompute register lists for the SequenceToOffsetTable.
+ unsigned i = 0;
+ for (auto I = Regs.begin(), E = Regs.end(); I != E; ++I, ++i) {
+ const auto &Reg = *I;
+ RegStrings.add(Reg.getName());
+
+ // Compute the ordered sub-register list.
+ SetVector<const CodeGenRegister*> SR;
+ Reg.addSubRegsPreOrder(SR, RegBank);
+ diffEncode(SubRegLists[i], Reg.EnumValue, SR.begin(), SR.end());
+ DiffSeqs.add(SubRegLists[i]);
+
+ // Compute the corresponding sub-register indexes.
+ SubRegIdxVec &SRIs = SubRegIdxLists[i];
+ for (unsigned j = 0, je = SR.size(); j != je; ++j)
+ SRIs.push_back(Reg.getSubRegIndex(SR[j]));
+ SubRegIdxSeqs.add(SRIs);
+
+ // Super-registers are already computed.
+ const RegVec &SuperRegList = Reg.getSuperRegs();
+ diffEncode(SuperRegLists[i], Reg.EnumValue, SuperRegList.begin(),
+ SuperRegList.end());
+ DiffSeqs.add(SuperRegLists[i]);
+
+ // Differentially encode the register unit list, seeded by register number.
+ // First compute a scale factor that allows more diff-lists to be reused:
+ //
+ // D0 -> (S0, S1)
+ // D1 -> (S2, S3)
+ //
+ // A scale factor of 2 allows D0 and D1 to share a diff-list. The initial
+ // value for the differential decoder is the register number multiplied by
+ // the scale.
+ //
+ // Check the neighboring registers for arithmetic progressions.
+ unsigned ScaleA = ~0u, ScaleB = ~0u;
+ SparseBitVector<> RUs = Reg.getNativeRegUnits();
+ if (I != Regs.begin() &&
+ std::prev(I)->getNativeRegUnits().count() == RUs.count())
+ ScaleB = *RUs.begin() - *std::prev(I)->getNativeRegUnits().begin();
+ if (std::next(I) != Regs.end() &&
+ std::next(I)->getNativeRegUnits().count() == RUs.count())
+ ScaleA = *std::next(I)->getNativeRegUnits().begin() - *RUs.begin();
+ unsigned Scale = std::min(ScaleB, ScaleA);
+ // Default the scale to 0 if it can't be encoded in 4 bits.
+ if (Scale >= 16)
+ Scale = 0;
+ RegUnitInitScale[i] = Scale;
+ DiffSeqs.add(diffEncode(RegUnitLists[i], Scale * Reg.EnumValue, RUs));
+
+ const auto &RUMasks = Reg.getRegUnitLaneMasks();
+ MaskVec &LaneMaskVec = RegUnitLaneMasks[i];
+ assert(LaneMaskVec.empty());
+ LaneMaskVec.insert(LaneMaskVec.begin(), RUMasks.begin(), RUMasks.end());
+ // Terminator mask should not be used inside of the list.
+#ifndef NDEBUG
+ for (LaneBitmask M : LaneMaskVec) {
+ assert(!M.all() && "terminator mask should not be part of the list");
+ }
+#endif
+ LaneMaskSeqs.add(LaneMaskVec);
+ }
+
+ // Compute the final layout of the sequence table.
+ DiffSeqs.layout();
+ LaneMaskSeqs.layout();
+ SubRegIdxSeqs.layout();
+
+ OS << "namespace llvm {\n\n";
+
+ const std::string &TargetName = Target.getName();
+
+ // Emit the shared table of differential lists.
+ OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[] = {\n";
+ DiffSeqs.emit(OS, printDiff16);
+ OS << "};\n\n";
+
+ // Emit the shared table of regunit lane mask sequences.
+ OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[] = {\n";
+ LaneMaskSeqs.emit(OS, printMask, "LaneBitmask::getAll()");
+ OS << "};\n\n";
+
+ // Emit the table of sub-register indexes.
+ OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[] = {\n";
+ SubRegIdxSeqs.emit(OS, printSubRegIndex);
+ OS << "};\n\n";
+
+ // Emit the table of sub-register index sizes.
+ OS << "extern const MCRegisterInfo::SubRegCoveredBits "
+ << TargetName << "SubRegIdxRanges[] = {\n";
+ OS << " { " << (uint16_t)-1 << ", " << (uint16_t)-1 << " },\n";
+ for (const auto &Idx : SubRegIndices) {
+ OS << " { " << Idx.Offset << ", " << Idx.Size << " },\t// "
+ << Idx.getName() << "\n";
+ }
+ OS << "};\n\n";
+
+ // Emit the string table.
+ RegStrings.layout();
+ OS << "extern const char " << TargetName << "RegStrings[] = {\n";
+ RegStrings.emit(OS, printChar);
+ OS << "};\n\n";
+
+ OS << "extern const MCRegisterDesc " << TargetName
+ << "RegDesc[] = { // Descriptors\n";
+ OS << " { " << RegStrings.get("") << ", 0, 0, 0, 0, 0 },\n";
+
+ // Emit the register descriptors now.
+ i = 0;
+ for (const auto &Reg : Regs) {
+ OS << " { " << RegStrings.get(Reg.getName()) << ", "
+ << DiffSeqs.get(SubRegLists[i]) << ", " << DiffSeqs.get(SuperRegLists[i])
+ << ", " << SubRegIdxSeqs.get(SubRegIdxLists[i]) << ", "
+ << (DiffSeqs.get(RegUnitLists[i]) * 16 + RegUnitInitScale[i]) << ", "
+ << LaneMaskSeqs.get(RegUnitLaneMasks[i]) << " },\n";
+ ++i;
+ }
+ OS << "};\n\n"; // End of register descriptors...
+
+ // Emit the table of register unit roots. Each regunit has one or two root
+ // registers.
+ OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2] = {\n";
+ for (unsigned i = 0, e = RegBank.getNumNativeRegUnits(); i != e; ++i) {
+ ArrayRef<const CodeGenRegister*> Roots = RegBank.getRegUnit(i).getRoots();
+ assert(!Roots.empty() && "All regunits must have a root register.");
+ assert(Roots.size() <= 2 && "More than two roots not supported yet.");
+ OS << " { " << getQualifiedName(Roots.front()->TheDef);
+ for (unsigned r = 1; r != Roots.size(); ++r)
+ OS << ", " << getQualifiedName(Roots[r]->TheDef);
+ OS << " },\n";
+ }
+ OS << "};\n\n";
+
+ const auto &RegisterClasses = RegBank.getRegClasses();
+
+ // Loop over all of the register classes... emitting each one.
+ OS << "namespace { // Register classes...\n";
+
+ SequenceToOffsetTable<std::string> RegClassStrings;
+
+ // Emit the register enum value arrays for each RegisterClass
+ for (const auto &RC : RegisterClasses) {
+ ArrayRef<Record*> Order = RC.getOrder();
+
+ // Give the register class a legal C name if it's anonymous.
+ const std::string &Name = RC.getName();
+
+ RegClassStrings.add(Name);
+
+ // Emit the register list now.
+ OS << " // " << Name << " Register Class...\n"
+ << " const MCPhysReg " << Name
+ << "[] = {\n ";
+ for (unsigned i = 0, e = Order.size(); i != e; ++i) {
+ Record *Reg = Order[i];
+ OS << getQualifiedName(Reg) << ", ";
+ }
+ OS << "\n };\n\n";
+
+ OS << " // " << Name << " Bit set.\n"
+ << " const uint8_t " << Name
+ << "Bits[] = {\n ";
+ BitVectorEmitter BVE;
+ for (unsigned i = 0, e = Order.size(); i != e; ++i) {
+ Record *Reg = Order[i];
+ BVE.add(Target.getRegBank().getReg(Reg)->EnumValue);
+ }
+ BVE.print(OS);
+ OS << "\n };\n\n";
+
+ }
+ OS << "} // end anonymous namespace\n\n";
+
+ RegClassStrings.layout();
+ OS << "extern const char " << TargetName << "RegClassStrings[] = {\n";
+ RegClassStrings.emit(OS, printChar);
+ OS << "};\n\n";
+
+ OS << "extern const MCRegisterClass " << TargetName
+ << "MCRegisterClasses[] = {\n";
+
+ for (const auto &RC : RegisterClasses) {
+ assert(isInt<8>(RC.CopyCost) && "Copy cost too large.");
+ // Register size and spill size will become independent, but are not at
+ // the moment. For now use SpillSize as the register size.
+ OS << " { " << RC.getName() << ", " << RC.getName() << "Bits, "
+ << RegClassStrings.get(RC.getName()) << ", "
+ << RC.getOrder().size() << ", sizeof(" << RC.getName() << "Bits), "
+ << RC.getQualifiedName() + "RegClassID" << ", "
+ << RC.SpillSize/8 << ", "
+ << RC.CopyCost << ", "
+ << ( RC.Allocatable ? "true" : "false" ) << " },\n";
+ }
+
+ OS << "};\n\n";
+
+ EmitRegMappingTables(OS, Regs, false);
+
+ // Emit Reg encoding table
+ OS << "extern const uint16_t " << TargetName;
+ OS << "RegEncodingTable[] = {\n";
+ // Add entry for NoRegister
+ OS << " 0,\n";
+ for (const auto &RE : Regs) {
+ Record *Reg = RE.TheDef;
+ BitsInit *BI = Reg->getValueAsBitsInit("HWEncoding");
+ uint64_t Value = 0;
+ for (unsigned b = 0, be = BI->getNumBits(); b != be; ++b) {
+ if (BitInit *B = dyn_cast<BitInit>(BI->getBit(b)))
+ Value |= (uint64_t)B->getValue() << b;
+ }
+ OS << " " << Value << ",\n";
+ }
+ OS << "};\n"; // End of HW encoding table
+
+ // MCRegisterInfo initialization routine.
+ OS << "static inline void Init" << TargetName
+ << "MCRegisterInfo(MCRegisterInfo *RI, unsigned RA, "
+ << "unsigned DwarfFlavour = 0, unsigned EHFlavour = 0, unsigned PC = 0) "
+ "{\n"
+ << " RI->InitMCRegisterInfo(" << TargetName << "RegDesc, "
+ << Regs.size() + 1 << ", RA, PC, " << TargetName << "MCRegisterClasses, "
+ << RegisterClasses.size() << ", " << TargetName << "RegUnitRoots, "
+ << RegBank.getNumNativeRegUnits() << ", " << TargetName << "RegDiffLists, "
+ << TargetName << "LaneMaskLists, " << TargetName << "RegStrings, "
+ << TargetName << "RegClassStrings, " << TargetName << "SubRegIdxLists, "
+ << (std::distance(SubRegIndices.begin(), SubRegIndices.end()) + 1) << ",\n"
+ << TargetName << "SubRegIdxRanges, " << TargetName
+ << "RegEncodingTable);\n\n";
+
+ EmitRegMapping(OS, Regs, false);
+
+ OS << "}\n\n";
+
+ OS << "} // end namespace llvm\n\n";
+ OS << "#endif // GET_REGINFO_MC_DESC\n\n";
+}
+
+void
+RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
+ CodeGenRegBank &RegBank) {
+ emitSourceFileHeader("Register Information Header Fragment", OS);
+
+ OS << "\n#ifdef GET_REGINFO_HEADER\n";
+ OS << "#undef GET_REGINFO_HEADER\n\n";
+
+ const std::string &TargetName = Target.getName();
+ std::string ClassName = TargetName + "GenRegisterInfo";
+
+ OS << "#include \"llvm/Target/TargetRegisterInfo.h\"\n\n";
+
+ OS << "namespace llvm {\n\n";
+
+ OS << "class " << TargetName << "FrameLowering;\n\n";
+
+ OS << "struct " << ClassName << " : public TargetRegisterInfo {\n"
+ << " explicit " << ClassName
+ << "(unsigned RA, unsigned D = 0, unsigned E = 0, unsigned PC = 0);\n";
+ if (!RegBank.getSubRegIndices().empty()) {
+ OS << " unsigned composeSubRegIndicesImpl"
+ << "(unsigned, unsigned) const override;\n"
+ << " LaneBitmask composeSubRegIndexLaneMaskImpl"
+ << "(unsigned, LaneBitmask) const override;\n"
+ << " LaneBitmask reverseComposeSubRegIndexLaneMaskImpl"
+ << "(unsigned, LaneBitmask) const override;\n"
+ << " const TargetRegisterClass *getSubClassWithSubReg"
+ << "(const TargetRegisterClass*, unsigned) const override;\n";
+ }
+ OS << " const RegClassWeight &getRegClassWeight("
+ << "const TargetRegisterClass *RC) const override;\n"
+ << " unsigned getRegUnitWeight(unsigned RegUnit) const override;\n"
+ << " unsigned getNumRegPressureSets() const override;\n"
+ << " const char *getRegPressureSetName(unsigned Idx) const override;\n"
+ << " unsigned getRegPressureSetLimit(const MachineFunction &MF, unsigned "
+ "Idx) const override;\n"
+ << " const int *getRegClassPressureSets("
+ << "const TargetRegisterClass *RC) const override;\n"
+ << " const int *getRegUnitPressureSets("
+ << "unsigned RegUnit) const override;\n"
+ << " ArrayRef<const char *> getRegMaskNames() const override;\n"
+ << " ArrayRef<const uint32_t *> getRegMasks() const override;\n"
+ << " /// Devirtualized TargetFrameLowering.\n"
+ << " static const " << TargetName << "FrameLowering *getFrameLowering(\n"
+ << " const MachineFunction &MF);\n"
+ << "};\n\n";
+
+ const auto &RegisterClasses = RegBank.getRegClasses();
+
+ if (!RegisterClasses.empty()) {
+ OS << "namespace " << RegisterClasses.front().Namespace
+ << " { // Register classes\n";
+
+ for (const auto &RC : RegisterClasses) {
+ const std::string &Name = RC.getName();
+
+ // Output the extern for the instance.
+ OS << " extern const TargetRegisterClass " << Name << "RegClass;\n";
+ }
+ OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n\n";
+ }
+ OS << "} // end namespace llvm\n\n";
+ OS << "#endif // GET_REGINFO_HEADER\n\n";
+}
+
+//
+// runTargetDesc - Output the target register and register file descriptions.
+//
+void
+RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
+ CodeGenRegBank &RegBank){
+ emitSourceFileHeader("Target Register and Register Classes Information", OS);
+
+ OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n";
+ OS << "#undef GET_REGINFO_TARGET_DESC\n\n";
+
+ OS << "namespace llvm {\n\n";
+
+ // Get access to MCRegisterClass data.
+ OS << "extern const MCRegisterClass " << Target.getName()
+ << "MCRegisterClasses[];\n";
+
+ // Start out by emitting each of the register classes.
+ const auto &RegisterClasses = RegBank.getRegClasses();
+ const auto &SubRegIndices = RegBank.getSubRegIndices();
+
+ // Collect all registers belonging to any allocatable class.
+ std::set<Record*> AllocatableRegs;
+
+ // Collect allocatable registers.
+ for (const auto &RC : RegisterClasses) {
+ ArrayRef<Record*> Order = RC.getOrder();
+
+ if (RC.Allocatable)
+ AllocatableRegs.insert(Order.begin(), Order.end());
+ }
+
+ // Build a shared array of value types.
+ SequenceToOffsetTable<SmallVector<MVT::SimpleValueType, 4> > VTSeqs;
+ for (const auto &RC : RegisterClasses)
+ VTSeqs.add(RC.VTs);
+ VTSeqs.layout();
+ OS << "\nstatic const MVT::SimpleValueType VTLists[] = {\n";
+ VTSeqs.emit(OS, printSimpleValueType, "MVT::Other");
+ OS << "};\n";
+
+ // Emit SubRegIndex names, skipping 0.
+ OS << "\nstatic const char *const SubRegIndexNameTable[] = { \"";
+
+ for (const auto &Idx : SubRegIndices) {
+ OS << Idx.getName();
+ OS << "\", \"";
+ }
+ OS << "\" };\n\n";
+
+ // Emit SubRegIndex lane masks, including 0.
+ OS << "\nstatic const LaneBitmask SubRegIndexLaneMaskTable[] = {\n LaneBitmask::getAll(),\n";
+ for (const auto &Idx : SubRegIndices) {
+ printMask(OS << " ", Idx.LaneMask);
+ OS << ", // " << Idx.getName() << '\n';
+ }
+ OS << " };\n\n";
+
+ OS << "\n";
+
+ // Now that all of the structs have been emitted, emit the instances.
+ if (!RegisterClasses.empty()) {
+ OS << "\nstatic const TargetRegisterClass *const "
+ << "NullRegClasses[] = { nullptr };\n\n";
+
+ // Emit register class bit mask tables. The first bit mask emitted for a
+ // register class, RC, is the set of sub-classes, including RC itself.
+ //
+ // If RC has super-registers, also create a list of subreg indices and bit
+ // masks, (Idx, Mask). The bit mask has a bit for every superreg regclass,
+ // SuperRC, that satisfies:
+ //
+ // For all SuperReg in SuperRC: SuperReg:Idx in RC
+ //
+ // The 0-terminated list of subreg indices starts at:
+ //
+ // RC->getSuperRegIndices() = SuperRegIdxSeqs + ...
+ //
+ // The corresponding bitmasks follow the sub-class mask in memory. Each
+ // mask has RCMaskWords uint32_t entries.
+ //
+ // Every bit mask present in the list has at least one bit set.
+
+ // Compress the sub-reg index lists.
+ typedef std::vector<const CodeGenSubRegIndex*> IdxList;
+ SmallVector<IdxList, 8> SuperRegIdxLists(RegisterClasses.size());
+ SequenceToOffsetTable<IdxList, deref<llvm::less>> SuperRegIdxSeqs;
+ BitVector MaskBV(RegisterClasses.size());
+
+ for (const auto &RC : RegisterClasses) {
+ OS << "static const uint32_t " << RC.getName() << "SubClassMask[] = {\n ";
+ printBitVectorAsHex(OS, RC.getSubClasses(), 32);
+
+ // Emit super-reg class masks for any relevant SubRegIndices that can
+ // project into RC.
+ IdxList &SRIList = SuperRegIdxLists[RC.EnumValue];
+ for (auto &Idx : SubRegIndices) {
+ MaskBV.reset();
+ RC.getSuperRegClasses(&Idx, MaskBV);
+ if (MaskBV.none())
+ continue;
+ SRIList.push_back(&Idx);
+ OS << "\n ";
+ printBitVectorAsHex(OS, MaskBV, 32);
+ OS << "// " << Idx.getName();
+ }
+ SuperRegIdxSeqs.add(SRIList);
+ OS << "\n};\n\n";
+ }
+
+ OS << "static const uint16_t SuperRegIdxSeqs[] = {\n";
+ SuperRegIdxSeqs.layout();
+ SuperRegIdxSeqs.emit(OS, printSubRegIndex);
+ OS << "};\n\n";
+
+ // Emit NULL terminated super-class lists.
+ for (const auto &RC : RegisterClasses) {
+ ArrayRef<CodeGenRegisterClass*> Supers = RC.getSuperClasses();
+
+ // Skip classes without supers. We can reuse NullRegClasses.
+ if (Supers.empty())
+ continue;
+
+ OS << "static const TargetRegisterClass *const "
+ << RC.getName() << "Superclasses[] = {\n";
+ for (const auto *Super : Supers)
+ OS << " &" << Super->getQualifiedName() << "RegClass,\n";
+ OS << " nullptr\n};\n\n";
+ }
+
+ // Emit methods.
+ for (const auto &RC : RegisterClasses) {
+ if (!RC.AltOrderSelect.empty()) {
+ OS << "\nstatic inline unsigned " << RC.getName()
+ << "AltOrderSelect(const MachineFunction &MF) {"
+ << RC.AltOrderSelect << "}\n\n"
+ << "static ArrayRef<MCPhysReg> " << RC.getName()
+ << "GetRawAllocationOrder(const MachineFunction &MF) {\n";
+ for (unsigned oi = 1 , oe = RC.getNumOrders(); oi != oe; ++oi) {
+ ArrayRef<Record*> Elems = RC.getOrder(oi);
+ if (!Elems.empty()) {
+ OS << " static const MCPhysReg AltOrder" << oi << "[] = {";
+ for (unsigned elem = 0; elem != Elems.size(); ++elem)
+ OS << (elem ? ", " : " ") << getQualifiedName(Elems[elem]);
+ OS << " };\n";
+ }
+ }
+ OS << " const MCRegisterClass &MCR = " << Target.getName()
+ << "MCRegisterClasses[" << RC.getQualifiedName() + "RegClassID];\n"
+ << " const ArrayRef<MCPhysReg> Order[] = {\n"
+ << " makeArrayRef(MCR.begin(), MCR.getNumRegs()";
+ for (unsigned oi = 1, oe = RC.getNumOrders(); oi != oe; ++oi)
+ if (RC.getOrder(oi).empty())
+ OS << "),\n ArrayRef<MCPhysReg>(";
+ else
+ OS << "),\n makeArrayRef(AltOrder" << oi;
+ OS << ")\n };\n const unsigned Select = " << RC.getName()
+ << "AltOrderSelect(MF);\n assert(Select < " << RC.getNumOrders()
+ << ");\n return Order[Select];\n}\n";
+ }
+ }
+
+ // Now emit the actual value-initialized register class instances.
+ OS << "\nnamespace " << RegisterClasses.front().Namespace
+ << " { // Register class instances\n";
+
+ for (const auto &RC : RegisterClasses) {
+ assert(isUInt<16>(RC.SpillSize/8) && "SpillSize too large.");
+ assert(isUInt<16>(RC.SpillAlignment/8) && "SpillAlignment too large.");
+ OS << " extern const TargetRegisterClass " << RC.getName()
+ << "RegClass = {\n " << '&' << Target.getName()
+ << "MCRegisterClasses[" << RC.getName() << "RegClassID],\n "
+ << RC.SpillSize/8 << ", /* SpillSize */\n "
+ << RC.SpillAlignment/8 << ", /* SpillAlignment */\n "
+ << "VTLists + " << VTSeqs.get(RC.VTs) << ",\n " << RC.getName()
+ << "SubClassMask,\n SuperRegIdxSeqs + "
+ << SuperRegIdxSeqs.get(SuperRegIdxLists[RC.EnumValue]) << ",\n ";
+ printMask(OS, RC.LaneMask);
+ OS << ",\n " << (unsigned)RC.AllocationPriority << ",\n "
+ << (RC.HasDisjunctSubRegs?"true":"false")
+ << ", /* HasDisjunctSubRegs */\n "
+ << (RC.CoveredBySubRegs?"true":"false")
+ << ", /* CoveredBySubRegs */\n ";
+ if (RC.getSuperClasses().empty())
+ OS << "NullRegClasses,\n ";
+ else
+ OS << RC.getName() << "Superclasses,\n ";
+ if (RC.AltOrderSelect.empty())
+ OS << "nullptr\n";
+ else
+ OS << RC.getName() << "GetRawAllocationOrder\n";
+ OS << " };\n\n";
+ }
+
+ OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n";
+ }
+
+ OS << "\nnamespace {\n";
+ OS << " const TargetRegisterClass* const RegisterClasses[] = {\n";
+ for (const auto &RC : RegisterClasses)
+ OS << " &" << RC.getQualifiedName() << "RegClass,\n";
+ OS << " };\n";
+ OS << "} // end anonymous namespace\n";
+
+ // Emit extra information about registers.
+ const std::string &TargetName = Target.getName();
+ OS << "\nstatic const TargetRegisterInfoDesc "
+ << TargetName << "RegInfoDesc[] = { // Extra Descriptors\n";
+ OS << " { 0, false },\n";
+
+ const auto &Regs = RegBank.getRegisters();
+ for (const auto &Reg : Regs) {
+ OS << " { ";
+ OS << Reg.CostPerUse << ", "
+ << ( AllocatableRegs.count(Reg.TheDef) != 0 ? "true" : "false" )
+ << " },\n";
+ }
+ OS << "};\n"; // End of register descriptors...
+
+
+ std::string ClassName = Target.getName().str() + "GenRegisterInfo";
+
+ auto SubRegIndicesSize =
+ std::distance(SubRegIndices.begin(), SubRegIndices.end());
+
+ if (!SubRegIndices.empty()) {
+ emitComposeSubRegIndices(OS, RegBank, ClassName);
+ emitComposeSubRegIndexLaneMask(OS, RegBank, ClassName);
+ }
+
+ // Emit getSubClassWithSubReg.
+ if (!SubRegIndices.empty()) {
+ OS << "const TargetRegisterClass *" << ClassName
+ << "::getSubClassWithSubReg(const TargetRegisterClass *RC, unsigned Idx)"
+ << " const {\n";
+ // Use the smallest type that can hold a regclass ID with room for a
+ // sentinel.
+ if (RegisterClasses.size() < UINT8_MAX)
+ OS << " static const uint8_t Table[";
+ else if (RegisterClasses.size() < UINT16_MAX)
+ OS << " static const uint16_t Table[";
+ else
+ PrintFatalError("Too many register classes.");
+ OS << RegisterClasses.size() << "][" << SubRegIndicesSize << "] = {\n";
+ for (const auto &RC : RegisterClasses) {
+ OS << " {\t// " << RC.getName() << "\n";
+ for (auto &Idx : SubRegIndices) {
+ if (CodeGenRegisterClass *SRC = RC.getSubClassWithSubReg(&Idx))
+ OS << " " << SRC->EnumValue + 1 << ",\t// " << Idx.getName()
+ << " -> " << SRC->getName() << "\n";
+ else
+ OS << " 0,\t// " << Idx.getName() << "\n";
+ }
+ OS << " },\n";
+ }
+ OS << " };\n assert(RC && \"Missing regclass\");\n"
+ << " if (!Idx) return RC;\n --Idx;\n"
+ << " assert(Idx < " << SubRegIndicesSize << " && \"Bad subreg\");\n"
+ << " unsigned TV = Table[RC->getID()][Idx];\n"
+ << " return TV ? getRegClass(TV - 1) : nullptr;\n}\n\n";
+ }
+
+ EmitRegUnitPressure(OS, RegBank, ClassName);
+
+ // Emit the constructor of the class...
+ OS << "extern const MCRegisterDesc " << TargetName << "RegDesc[];\n";
+ OS << "extern const MCPhysReg " << TargetName << "RegDiffLists[];\n";
+ OS << "extern const LaneBitmask " << TargetName << "LaneMaskLists[];\n";
+ OS << "extern const char " << TargetName << "RegStrings[];\n";
+ OS << "extern const char " << TargetName << "RegClassStrings[];\n";
+ OS << "extern const MCPhysReg " << TargetName << "RegUnitRoots[][2];\n";
+ OS << "extern const uint16_t " << TargetName << "SubRegIdxLists[];\n";
+ OS << "extern const MCRegisterInfo::SubRegCoveredBits "
+ << TargetName << "SubRegIdxRanges[];\n";
+ OS << "extern const uint16_t " << TargetName << "RegEncodingTable[];\n";
+
+ EmitRegMappingTables(OS, Regs, true);
+
+ OS << ClassName << "::\n" << ClassName
+ << "(unsigned RA, unsigned DwarfFlavour, unsigned EHFlavour, unsigned PC)\n"
+ << " : TargetRegisterInfo(" << TargetName << "RegInfoDesc"
+ << ", RegisterClasses, RegisterClasses+" << RegisterClasses.size() <<",\n"
+ << " SubRegIndexNameTable, SubRegIndexLaneMaskTable, ";
+ printMask(OS, RegBank.CoveringLanes);
+ OS << ") {\n"
+ << " InitMCRegisterInfo(" << TargetName << "RegDesc, " << Regs.size() + 1
+ << ", RA, PC,\n " << TargetName
+ << "MCRegisterClasses, " << RegisterClasses.size() << ",\n"
+ << " " << TargetName << "RegUnitRoots,\n"
+ << " " << RegBank.getNumNativeRegUnits() << ",\n"
+ << " " << TargetName << "RegDiffLists,\n"
+ << " " << TargetName << "LaneMaskLists,\n"
+ << " " << TargetName << "RegStrings,\n"
+ << " " << TargetName << "RegClassStrings,\n"
+ << " " << TargetName << "SubRegIdxLists,\n"
+ << " " << SubRegIndicesSize + 1 << ",\n"
+ << " " << TargetName << "SubRegIdxRanges,\n"
+ << " " << TargetName << "RegEncodingTable);\n\n";
+
+ EmitRegMapping(OS, Regs, true);
+
+ OS << "}\n\n";
+
+ // Emit CalleeSavedRegs information.
+ std::vector<Record*> CSRSets =
+ Records.getAllDerivedDefinitions("CalleeSavedRegs");
+ for (unsigned i = 0, e = CSRSets.size(); i != e; ++i) {
+ Record *CSRSet = CSRSets[i];
+ const SetTheory::RecVec *Regs = RegBank.getSets().expand(CSRSet);
+ assert(Regs && "Cannot expand CalleeSavedRegs instance");
+
+ // Emit the *_SaveList list of callee-saved registers.
+ OS << "static const MCPhysReg " << CSRSet->getName()
+ << "_SaveList[] = { ";
+ for (unsigned r = 0, re = Regs->size(); r != re; ++r)
+ OS << getQualifiedName((*Regs)[r]) << ", ";
+ OS << "0 };\n";
+
+ // Emit the *_RegMask bit mask of call-preserved registers.
+ BitVector Covered = RegBank.computeCoveredRegisters(*Regs);
+
+ // Check for an optional OtherPreserved set.
+ // Add those registers to RegMask, but not to SaveList.
+ if (DagInit *OPDag =
+ dyn_cast<DagInit>(CSRSet->getValueInit("OtherPreserved"))) {
+ SetTheory::RecSet OPSet;
+ RegBank.getSets().evaluate(OPDag, OPSet, CSRSet->getLoc());
+ Covered |= RegBank.computeCoveredRegisters(
+ ArrayRef<Record*>(OPSet.begin(), OPSet.end()));
+ }
+
+ OS << "static const uint32_t " << CSRSet->getName()
+ << "_RegMask[] = { ";
+ printBitVectorAsHex(OS, Covered, 32);
+ OS << "};\n";
+ }
+ OS << "\n\n";
+
+ OS << "ArrayRef<const uint32_t *> " << ClassName
+ << "::getRegMasks() const {\n";
+ if (!CSRSets.empty()) {
+ OS << " static const uint32_t *const Masks[] = {\n";
+ for (Record *CSRSet : CSRSets)
+ OS << " " << CSRSet->getName() << "_RegMask,\n";
+ OS << " };\n";
+ OS << " return makeArrayRef(Masks);\n";
+ } else {
+ OS << " return None;\n";
+ }
+ OS << "}\n\n";
+
+ OS << "ArrayRef<const char *> " << ClassName
+ << "::getRegMaskNames() const {\n";
+ if (!CSRSets.empty()) {
+ OS << " static const char *const Names[] = {\n";
+ for (Record *CSRSet : CSRSets)
+ OS << " " << '"' << CSRSet->getName() << '"' << ",\n";
+ OS << " };\n";
+ OS << " return makeArrayRef(Names);\n";
+ } else {
+ OS << " return None;\n";
+ }
+ OS << "}\n\n";
+
+ OS << "const " << TargetName << "FrameLowering *\n" << TargetName
+ << "GenRegisterInfo::getFrameLowering(const MachineFunction &MF) {\n"
+ << " return static_cast<const " << TargetName << "FrameLowering *>(\n"
+ << " MF.getSubtarget().getFrameLowering());\n"
+ << "}\n\n";
+
+ OS << "} // end namespace llvm\n\n";
+ OS << "#endif // GET_REGINFO_TARGET_DESC\n\n";
+}
+
+void RegisterInfoEmitter::run(raw_ostream &OS) {
+ CodeGenTarget Target(Records);
+ CodeGenRegBank &RegBank = Target.getRegBank();
+ RegBank.computeDerivedInfo();
+
+ runEnums(OS, Target, RegBank);
+ runMCDesc(OS, Target, RegBank);
+ runTargetHeader(OS, Target, RegBank);
+ runTargetDesc(OS, Target, RegBank);
+}
+
+namespace llvm {
+
+void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS) {
+ RegisterInfoEmitter(RK).run(OS);
+}
+
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp b/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp
new file mode 100644
index 000000000000..80f0b0d4aaf4
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp
@@ -0,0 +1,320 @@
+//===- SearchableTableEmitter.cpp - Generate efficiently searchable tables -==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits a generic array initialized by specified fields,
+// together with companion index tables and lookup functions (binary search,
+// currently).
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include <algorithm>
+#include <sstream>
+#include <string>
+#include <vector>
+using namespace llvm;
+
+#define DEBUG_TYPE "searchable-table-emitter"
+
+namespace {
+
+class SearchableTableEmitter {
+ RecordKeeper &Records;
+
+public:
+ SearchableTableEmitter(RecordKeeper &R) : Records(R) {}
+
+ void run(raw_ostream &OS);
+
+private:
+ typedef std::pair<Init *, int> SearchTableEntry;
+
+ int getAsInt(BitsInit *B) {
+ return cast<IntInit>(B->convertInitializerTo(IntRecTy::get()))->getValue();
+ }
+ int getInt(Record *R, StringRef Field) {
+ return getAsInt(R->getValueAsBitsInit(Field));
+ }
+
+ std::string primaryRepresentation(Init *I) {
+ if (StringInit *SI = dyn_cast<StringInit>(I))
+ return SI->getAsString();
+ else if (BitsInit *BI = dyn_cast<BitsInit>(I))
+ return "0x" + utohexstr(getAsInt(BI));
+ else if (BitInit *BI = dyn_cast<BitInit>(I))
+ return BI->getValue() ? "true" : "false";
+ else if (CodeInit *CI = dyn_cast<CodeInit>(I)) {
+ return CI->getValue();
+ }
+ PrintFatalError(SMLoc(),
+ "invalid field type, expected: string, bits, bit or code");
+ }
+
+ std::string searchRepresentation(Init *I) {
+ std::string PrimaryRep = primaryRepresentation(I);
+ if (!isa<StringInit>(I))
+ return PrimaryRep;
+ return StringRef(PrimaryRep).upper();
+ }
+
+ std::string searchableFieldType(Init *I) {
+ if (isa<StringInit>(I))
+ return "const char *";
+ else if (BitsInit *BI = dyn_cast<BitsInit>(I)) {
+ unsigned NumBits = BI->getNumBits();
+ if (NumBits <= 8)
+ NumBits = 8;
+ else if (NumBits <= 16)
+ NumBits = 16;
+ else if (NumBits <= 32)
+ NumBits = 32;
+ else if (NumBits <= 64)
+ NumBits = 64;
+ else
+ PrintFatalError(SMLoc(), "bitfield too large to search");
+ return "uint" + utostr(NumBits) + "_t";
+ }
+ PrintFatalError(SMLoc(), "Unknown type to search by");
+ }
+
+ void emitMapping(Record *MappingDesc, raw_ostream &OS);
+ void emitMappingEnum(std::vector<Record *> &Items, Record *InstanceClass,
+ raw_ostream &OS);
+ void
+ emitPrimaryTable(StringRef Name, std::vector<std::string> &FieldNames,
+ std::vector<std::string> &SearchFieldNames,
+ std::vector<std::vector<SearchTableEntry>> &SearchTables,
+ std::vector<Record *> &Items, raw_ostream &OS);
+ void emitSearchTable(StringRef Name, StringRef Field,
+ std::vector<SearchTableEntry> &SearchTable,
+ raw_ostream &OS);
+ void emitLookupDeclaration(StringRef Name, StringRef Field, Init *I,
+ raw_ostream &OS);
+ void emitLookupFunction(StringRef Name, StringRef Field, Init *I,
+ raw_ostream &OS);
+};
+
+} // End anonymous namespace.
+
+/// Emit an enum providing symbolic access to some preferred field from
+/// C++.
+void SearchableTableEmitter::emitMappingEnum(std::vector<Record *> &Items,
+ Record *InstanceClass,
+ raw_ostream &OS) {
+ std::string EnumNameField = InstanceClass->getValueAsString("EnumNameField");
+ std::string EnumValueField;
+ if (!InstanceClass->isValueUnset("EnumValueField"))
+ EnumValueField = InstanceClass->getValueAsString("EnumValueField");
+
+ OS << "enum " << InstanceClass->getName() << "Values {\n";
+ for (auto Item : Items) {
+ OS << " " << Item->getValueAsString(EnumNameField);
+ if (EnumValueField != StringRef())
+ OS << " = " << getInt(Item, EnumValueField);
+ OS << ",\n";
+ }
+ OS << "};\n\n";
+}
+
+void SearchableTableEmitter::emitPrimaryTable(
+ StringRef Name, std::vector<std::string> &FieldNames,
+ std::vector<std::string> &SearchFieldNames,
+ std::vector<std::vector<SearchTableEntry>> &SearchTables,
+ std::vector<Record *> &Items, raw_ostream &OS) {
+ OS << "const " << Name << " " << Name << "sList[] = {\n";
+
+ for (auto Item : Items) {
+ OS << " { ";
+ for (unsigned i = 0; i < FieldNames.size(); ++i) {
+ OS << primaryRepresentation(Item->getValueInit(FieldNames[i]));
+ if (i != FieldNames.size() - 1)
+ OS << ", ";
+ }
+ OS << "},\n";
+ }
+ OS << "};\n\n";
+}
+
+void SearchableTableEmitter::emitSearchTable(
+ StringRef Name, StringRef Field, std::vector<SearchTableEntry> &SearchTable,
+ raw_ostream &OS) {
+ OS << "const std::pair<" << searchableFieldType(SearchTable[0].first)
+ << ", int> " << Name << "sBy" << Field << "[] = {\n";
+
+ if (isa<BitsInit>(SearchTable[0].first)) {
+ std::stable_sort(SearchTable.begin(), SearchTable.end(),
+ [this](const SearchTableEntry &LHS,
+ const SearchTableEntry &RHS) {
+ return getAsInt(cast<BitsInit>(LHS.first)) <
+ getAsInt(cast<BitsInit>(RHS.first));
+ });
+ } else {
+ std::stable_sort(SearchTable.begin(), SearchTable.end(),
+ [this](const SearchTableEntry &LHS,
+ const SearchTableEntry &RHS) {
+ return searchRepresentation(LHS.first) <
+ searchRepresentation(RHS.first);
+ });
+ }
+
+ for (auto Entry : SearchTable) {
+ OS << " { " << searchRepresentation(Entry.first) << ", " << Entry.second
+ << " },\n";
+ }
+ OS << "};\n\n";
+}
+
+void SearchableTableEmitter::emitLookupFunction(StringRef Name, StringRef Field,
+ Init *I, raw_ostream &OS) {
+ bool IsIntegral = isa<BitsInit>(I);
+ std::string FieldType = searchableFieldType(I);
+ std::string PairType = "std::pair<" + FieldType + ", int>";
+
+ // const SysRegs *lookupSysRegByName(const char *Name) {
+ OS << "const " << Name << " *"
+ << "lookup" << Name << "By" << Field;
+ OS << "(" << (IsIntegral ? FieldType : "StringRef") << " " << Field
+ << ") {\n";
+
+ if (IsIntegral) {
+ OS << " auto CanonicalVal = " << Field << ";\n";
+ OS << " " << PairType << " Val = {CanonicalVal, 0};\n";
+ } else {
+ // Make sure the result is null terminated because it's going via "char *".
+ OS << " std::string CanonicalVal = " << Field << ".upper();\n";
+ OS << " " << PairType << " Val = {CanonicalVal.c_str(), 0};\n";
+ }
+
+ OS << " ArrayRef<" << PairType << "> Table(" << Name << "sBy" << Field
+ << ");\n";
+ OS << " auto Idx = std::lower_bound(Table.begin(), Table.end(), Val";
+
+ if (IsIntegral)
+ OS << ");\n";
+ else {
+ OS << ",\n ";
+ OS << "[](const " << PairType << " &LHS, const " << PairType
+ << " &RHS) {\n";
+ OS << " return std::strcmp(LHS.first, RHS.first) < 0;\n";
+ OS << " });\n\n";
+ }
+
+ OS << " if (Idx == Table.end() || CanonicalVal != Idx->first)\n";
+ OS << " return nullptr;\n";
+
+ OS << " return &" << Name << "sList[Idx->second];\n";
+ OS << "}\n\n";
+}
+
+void SearchableTableEmitter::emitLookupDeclaration(StringRef Name,
+ StringRef Field, Init *I,
+ raw_ostream &OS) {
+ bool IsIntegral = isa<BitsInit>(I);
+ std::string FieldType = searchableFieldType(I);
+ OS << "const " << Name << " *"
+ << "lookup" << Name << "By" << Field;
+ OS << "(" << (IsIntegral ? FieldType : "StringRef") << " " << Field
+ << ");\n\n";
+}
+
+void SearchableTableEmitter::emitMapping(Record *InstanceClass,
+ raw_ostream &OS) {
+ const std::string &TableName = InstanceClass->getName();
+ std::vector<Record *> Items = Records.getAllDerivedDefinitions(TableName);
+
+ // Gather all the records we're going to need for this particular mapping.
+ std::vector<std::vector<SearchTableEntry>> SearchTables;
+ std::vector<std::string> SearchFieldNames;
+
+ std::vector<std::string> FieldNames;
+ for (const RecordVal &Field : InstanceClass->getValues()) {
+ std::string FieldName = Field.getName();
+
+ // Skip uninteresting fields: either built-in, special to us, or injected
+ // template parameters (if they contain a ':').
+ if (FieldName.find(':') != std::string::npos || FieldName == "NAME" ||
+ FieldName == "SearchableFields" || FieldName == "EnumNameField" ||
+ FieldName == "EnumValueField")
+ continue;
+
+ FieldNames.push_back(FieldName);
+ }
+
+ for (auto *Field : *InstanceClass->getValueAsListInit("SearchableFields")) {
+ SearchTables.emplace_back();
+ SearchFieldNames.push_back(Field->getAsUnquotedString());
+ }
+
+ int Idx = 0;
+ for (Record *Item : Items) {
+ for (unsigned i = 0; i < SearchFieldNames.size(); ++i) {
+ Init *SearchVal = Item->getValueInit(SearchFieldNames[i]);
+ SearchTables[i].emplace_back(SearchVal, Idx);
+ }
+ ++Idx;
+ }
+
+ OS << "#ifdef GET_" << StringRef(TableName).upper() << "_DECL\n";
+ OS << "#undef GET_" << StringRef(TableName).upper() << "_DECL\n";
+
+ // Next emit the enum containing the top-level names for use in C++ code if
+ // requested
+ if (!InstanceClass->isValueUnset("EnumNameField")) {
+ emitMappingEnum(Items, InstanceClass, OS);
+ }
+
+ // And the declarations for the functions that will perform lookup.
+ for (unsigned i = 0; i < SearchFieldNames.size(); ++i)
+ emitLookupDeclaration(TableName, SearchFieldNames[i],
+ SearchTables[i][0].first, OS);
+
+ OS << "#endif\n\n";
+
+ OS << "#ifdef GET_" << StringRef(TableName).upper() << "_IMPL\n";
+ OS << "#undef GET_" << StringRef(TableName).upper() << "_IMPL\n";
+
+ // The primary data table contains all the fields defined for this map.
+ emitPrimaryTable(TableName, FieldNames, SearchFieldNames, SearchTables, Items,
+ OS);
+
+ // Indexes are sorted "{ Thing, PrimaryIdx }" arrays, so that a binary
+ // search can be performed by "Thing".
+ for (unsigned i = 0; i < SearchTables.size(); ++i) {
+ emitSearchTable(TableName, SearchFieldNames[i], SearchTables[i], OS);
+ emitLookupFunction(TableName, SearchFieldNames[i], SearchTables[i][0].first,
+ OS);
+ }
+
+ OS << "#endif\n";
+}
+
+void SearchableTableEmitter::run(raw_ostream &OS) {
+ // Tables are defined to be the direct descendents of "SearchableEntry".
+ Record *SearchableTable = Records.getClass("SearchableTable");
+ for (auto &NameRec : Records.getClasses()) {
+ Record *Class = NameRec.second.get();
+ if (Class->getSuperClasses().size() != 1 ||
+ !Class->isSubClassOf(SearchableTable))
+ continue;
+ emitMapping(Class, OS);
+ }
+}
+
+namespace llvm {
+
+void EmitSearchableTables(RecordKeeper &RK, raw_ostream &OS) {
+ SearchableTableEmitter(RK).run(OS);
+}
+
+} // End llvm namespace.
diff --git a/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h b/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h
new file mode 100644
index 000000000000..e026b1c9fbf0
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h
@@ -0,0 +1,146 @@
+//===-- SequenceToOffsetTable.h - Compress similar sequences ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// SequenceToOffsetTable can be used to emit a number of null-terminated
+// sequences as one big array. Use the same memory when a sequence is a suffix
+// of another.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H
+#define LLVM_UTILS_TABLEGEN_SEQUENCETOOFFSETTABLE_H
+
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <functional>
+#include <map>
+
+namespace llvm {
+
+/// SequenceToOffsetTable - Collect a number of terminated sequences of T.
+/// Compute the layout of a table that contains all the sequences, possibly by
+/// reusing entries.
+///
+/// @tparam SeqT The sequence container. (vector or string).
+/// @tparam Less A stable comparator for SeqT elements.
+template<typename SeqT, typename Less = std::less<typename SeqT::value_type> >
+class SequenceToOffsetTable {
+ typedef typename SeqT::value_type ElemT;
+
+ // Define a comparator for SeqT that sorts a suffix immediately before a
+ // sequence with that suffix.
+ struct SeqLess : public std::binary_function<SeqT, SeqT, bool> {
+ Less L;
+ bool operator()(const SeqT &A, const SeqT &B) const {
+ return std::lexicographical_compare(A.rbegin(), A.rend(),
+ B.rbegin(), B.rend(), L);
+ }
+ };
+
+ // Keep sequences ordered according to SeqLess so suffixes are easy to find.
+ // Map each sequence to its offset in the table.
+ typedef std::map<SeqT, unsigned, SeqLess> SeqMap;
+
+ // Sequences added so far, with suffixes removed.
+ SeqMap Seqs;
+
+ // Entries in the final table, or 0 before layout was called.
+ unsigned Entries;
+
+ // isSuffix - Returns true if A is a suffix of B.
+ static bool isSuffix(const SeqT &A, const SeqT &B) {
+ return A.size() <= B.size() && std::equal(A.rbegin(), A.rend(), B.rbegin());
+ }
+
+public:
+ SequenceToOffsetTable() : Entries(0) {}
+
+ /// add - Add a sequence to the table.
+ /// This must be called before layout().
+ void add(const SeqT &Seq) {
+ assert(Entries == 0 && "Cannot call add() after layout()");
+ typename SeqMap::iterator I = Seqs.lower_bound(Seq);
+
+ // If SeqMap contains a sequence that has Seq as a suffix, I will be
+ // pointing to it.
+ if (I != Seqs.end() && isSuffix(Seq, I->first))
+ return;
+
+ I = Seqs.insert(I, std::make_pair(Seq, 0u));
+
+ // The entry before I may be a suffix of Seq that can now be erased.
+ if (I != Seqs.begin() && isSuffix((--I)->first, Seq))
+ Seqs.erase(I);
+ }
+
+ bool empty() const { return Seqs.empty(); }
+
+ unsigned size() const {
+ assert(Entries && "Call layout() before size()");
+ return Entries;
+ }
+
+ /// layout - Computes the final table layout.
+ void layout() {
+ assert(Entries == 0 && "Can only call layout() once");
+ // Lay out the table in Seqs iteration order.
+ for (typename SeqMap::iterator I = Seqs.begin(), E = Seqs.end(); I != E;
+ ++I) {
+ I->second = Entries;
+ // Include space for a terminator.
+ Entries += I->first.size() + 1;
+ }
+ }
+
+ /// get - Returns the offset of Seq in the final table.
+ unsigned get(const SeqT &Seq) const {
+ assert(Entries && "Call layout() before get()");
+ typename SeqMap::const_iterator I = Seqs.lower_bound(Seq);
+ assert(I != Seqs.end() && isSuffix(Seq, I->first) &&
+ "get() called with sequence that wasn't added first");
+ return I->second + (I->first.size() - Seq.size());
+ }
+
+ /// emit - Print out the table as the body of an array initializer.
+ /// Use the Print function to print elements.
+ void emit(raw_ostream &OS,
+ void (*Print)(raw_ostream&, ElemT),
+ const char *Term = "0") const {
+ assert(Entries && "Call layout() before emit()");
+ for (typename SeqMap::const_iterator I = Seqs.begin(), E = Seqs.end();
+ I != E; ++I) {
+ OS << " /* " << I->second << " */ ";
+ for (typename SeqT::const_iterator SI = I->first.begin(),
+ SE = I->first.end(); SI != SE; ++SI) {
+ Print(OS, *SI);
+ OS << ", ";
+ }
+ OS << Term << ",\n";
+ }
+ }
+};
+
+// Helper function for SequenceToOffsetTable<string>.
+static inline void printChar(raw_ostream &OS, char C) {
+ unsigned char UC(C);
+ if (isalnum(UC) || ispunct(UC)) {
+ OS << '\'';
+ if (C == '\\' || C == '\'')
+ OS << '\\';
+ OS << C << '\'';
+ } else {
+ OS << unsigned(UC);
+ }
+}
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
new file mode 100644
index 000000000000..30516ef5d10d
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -0,0 +1,1533 @@
+//===- SubtargetEmitter.cpp - Generate subtarget enumerations -------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This tablegen backend emits subtarget enumerations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenTarget.h"
+#include "CodeGenSchedule.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/MC/MCInstrItineraries.h"
+#include "llvm/MC/MCSchedule.h"
+#include "llvm/MC/SubtargetFeature.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <algorithm>
+#include <cassert>
+#include <cstdint>
+#include <iterator>
+#include <map>
+#include <string>
+#include <vector>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "subtarget-emitter"
+
+namespace {
+
+class SubtargetEmitter {
+ // Each processor has a SchedClassDesc table with an entry for each SchedClass.
+ // The SchedClassDesc table indexes into a global write resource table, write
+ // latency table, and read advance table.
+ struct SchedClassTables {
+ std::vector<std::vector<MCSchedClassDesc>> ProcSchedClasses;
+ std::vector<MCWriteProcResEntry> WriteProcResources;
+ std::vector<MCWriteLatencyEntry> WriteLatencies;
+ std::vector<std::string> WriterNames;
+ std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
+
+ // Reserve an invalid entry at index 0
+ SchedClassTables() {
+ ProcSchedClasses.resize(1);
+ WriteProcResources.resize(1);
+ WriteLatencies.resize(1);
+ WriterNames.push_back("InvalidWrite");
+ ReadAdvanceEntries.resize(1);
+ }
+ };
+
+ struct LessWriteProcResources {
+ bool operator()(const MCWriteProcResEntry &LHS,
+ const MCWriteProcResEntry &RHS) {
+ return LHS.ProcResourceIdx < RHS.ProcResourceIdx;
+ }
+ };
+
+ RecordKeeper &Records;
+ CodeGenSchedModels &SchedModels;
+ std::string Target;
+
+ void Enumeration(raw_ostream &OS);
+ unsigned FeatureKeyValues(raw_ostream &OS);
+ unsigned CPUKeyValues(raw_ostream &OS);
+ void FormItineraryStageString(const std::string &Names,
+ Record *ItinData, std::string &ItinString,
+ unsigned &NStages);
+ void FormItineraryOperandCycleString(Record *ItinData, std::string &ItinString,
+ unsigned &NOperandCycles);
+ void FormItineraryBypassString(const std::string &Names,
+ Record *ItinData,
+ std::string &ItinString, unsigned NOperandCycles);
+ void EmitStageAndOperandCycleData(raw_ostream &OS,
+ std::vector<std::vector<InstrItinerary>>
+ &ProcItinLists);
+ void EmitItineraries(raw_ostream &OS,
+ std::vector<std::vector<InstrItinerary>>
+ &ProcItinLists);
+ void EmitProcessorProp(raw_ostream &OS, const Record *R, StringRef Name,
+ char Separator);
+ void EmitProcessorResources(const CodeGenProcModel &ProcModel,
+ raw_ostream &OS);
+ Record *FindWriteResources(const CodeGenSchedRW &SchedWrite,
+ const CodeGenProcModel &ProcModel);
+ Record *FindReadAdvance(const CodeGenSchedRW &SchedRead,
+ const CodeGenProcModel &ProcModel);
+ void ExpandProcResources(RecVec &PRVec, std::vector<int64_t> &Cycles,
+ const CodeGenProcModel &ProcModel);
+ void GenSchedClassTables(const CodeGenProcModel &ProcModel,
+ SchedClassTables &SchedTables);
+ void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
+ void EmitProcessorModels(raw_ostream &OS);
+ void EmitProcessorLookup(raw_ostream &OS);
+ void EmitSchedModelHelpers(const std::string &ClassName, raw_ostream &OS);
+ void EmitSchedModel(raw_ostream &OS);
+ void ParseFeaturesFunction(raw_ostream &OS, unsigned NumFeatures,
+ unsigned NumProcs);
+
+public:
+ SubtargetEmitter(RecordKeeper &R, CodeGenTarget &TGT):
+ Records(R), SchedModels(TGT.getSchedModels()), Target(TGT.getName()) {}
+
+ void run(raw_ostream &o);
+};
+
+} // end anonymous namespace
+
+//
+// Enumeration - Emit the specified class as an enumeration.
+//
+void SubtargetEmitter::Enumeration(raw_ostream &OS) {
+ // Get all records of class and sort
+ std::vector<Record*> DefList =
+ Records.getAllDerivedDefinitions("SubtargetFeature");
+ std::sort(DefList.begin(), DefList.end(), LessRecord());
+
+ unsigned N = DefList.size();
+ if (N == 0)
+ return;
+ if (N > MAX_SUBTARGET_FEATURES)
+ PrintFatalError("Too many subtarget features! Bump MAX_SUBTARGET_FEATURES.");
+
+ OS << "namespace " << Target << " {\n";
+
+ // Open enumeration.
+ OS << "enum {\n";
+
+ // For each record
+ for (unsigned i = 0; i < N;) {
+ // Next record
+ Record *Def = DefList[i];
+
+ // Get and emit name
+ OS << " " << Def->getName() << " = " << i;
+ if (++i < N) OS << ",";
+
+ OS << "\n";
+ }
+
+ // Close enumeration and namespace
+ OS << "};\n";
+ OS << "} // end namespace " << Target << "\n";
+}
+
+//
+// FeatureKeyValues - Emit data of all the subtarget features. Used by the
+// command line.
+//
+unsigned SubtargetEmitter::FeatureKeyValues(raw_ostream &OS) {
+ // Gather and sort all the features
+ std::vector<Record*> FeatureList =
+ Records.getAllDerivedDefinitions("SubtargetFeature");
+
+ if (FeatureList.empty())
+ return 0;
+
+ std::sort(FeatureList.begin(), FeatureList.end(), LessRecordFieldName());
+
+ // Begin feature table
+ OS << "// Sorted (by key) array of values for CPU features.\n"
+ << "extern const llvm::SubtargetFeatureKV " << Target
+ << "FeatureKV[] = {\n";
+
+ // For each feature
+ unsigned NumFeatures = 0;
+ for (unsigned i = 0, N = FeatureList.size(); i < N; ++i) {
+ // Next feature
+ Record *Feature = FeatureList[i];
+
+ const std::string &Name = Feature->getName();
+ const std::string &CommandLineName = Feature->getValueAsString("Name");
+ const std::string &Desc = Feature->getValueAsString("Desc");
+
+ if (CommandLineName.empty()) continue;
+
+ // Emit as { "feature", "description", { featureEnum }, { i1 , i2 , ... , in } }
+ OS << " { "
+ << "\"" << CommandLineName << "\", "
+ << "\"" << Desc << "\", "
+ << "{ " << Target << "::" << Name << " }, ";
+
+ const std::vector<Record*> &ImpliesList =
+ Feature->getValueAsListOfDefs("Implies");
+
+ OS << "{";
+ for (unsigned j = 0, M = ImpliesList.size(); j < M;) {
+ OS << " " << Target << "::" << ImpliesList[j]->getName();
+ if (++j < M) OS << ",";
+ }
+ OS << " }";
+
+ OS << " }";
+ ++NumFeatures;
+
+ // Depending on 'if more in the list' emit comma
+ if ((i + 1) < N) OS << ",";
+
+ OS << "\n";
+ }
+
+ // End feature table
+ OS << "};\n";
+
+ return NumFeatures;
+}
+
+//
+// CPUKeyValues - Emit data of all the subtarget processors. Used by command
+// line.
+//
+unsigned SubtargetEmitter::CPUKeyValues(raw_ostream &OS) {
+ // Gather and sort processor information
+ std::vector<Record*> ProcessorList =
+ Records.getAllDerivedDefinitions("Processor");
+ std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
+
+ // Begin processor table
+ OS << "// Sorted (by key) array of values for CPU subtype.\n"
+ << "extern const llvm::SubtargetFeatureKV " << Target
+ << "SubTypeKV[] = {\n";
+
+ // For each processor
+ for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
+ // Next processor
+ Record *Processor = ProcessorList[i];
+
+ const std::string &Name = Processor->getValueAsString("Name");
+ const std::vector<Record*> &FeatureList =
+ Processor->getValueAsListOfDefs("Features");
+
+ // Emit as { "cpu", "description", { f1 , f2 , ... fn } },
+ OS << " { "
+ << "\"" << Name << "\", "
+ << "\"Select the " << Name << " processor\", ";
+
+ OS << "{";
+ for (unsigned j = 0, M = FeatureList.size(); j < M;) {
+ OS << " " << Target << "::" << FeatureList[j]->getName();
+ if (++j < M) OS << ",";
+ }
+ OS << " }";
+
+ // The { } is for the "implies" section of this data structure.
+ OS << ", { } }";
+
+ // Depending on 'if more in the list' emit comma
+ if (++i < N) OS << ",";
+
+ OS << "\n";
+ }
+
+ // End processor table
+ OS << "};\n";
+
+ return ProcessorList.size();
+}
+
+//
+// FormItineraryStageString - Compose a string containing the stage
+// data initialization for the specified itinerary. N is the number
+// of stages.
+//
+void SubtargetEmitter::FormItineraryStageString(const std::string &Name,
+ Record *ItinData,
+ std::string &ItinString,
+ unsigned &NStages) {
+ // Get states list
+ const std::vector<Record*> &StageList =
+ ItinData->getValueAsListOfDefs("Stages");
+
+ // For each stage
+ unsigned N = NStages = StageList.size();
+ for (unsigned i = 0; i < N;) {
+ // Next stage
+ const Record *Stage = StageList[i];
+
+ // Form string as ,{ cycles, u1 | u2 | ... | un, timeinc, kind }
+ int Cycles = Stage->getValueAsInt("Cycles");
+ ItinString += " { " + itostr(Cycles) + ", ";
+
+ // Get unit list
+ const std::vector<Record*> &UnitList = Stage->getValueAsListOfDefs("Units");
+
+ // For each unit
+ for (unsigned j = 0, M = UnitList.size(); j < M;) {
+ // Add name and bitwise or
+ ItinString += Name + "FU::" + UnitList[j]->getName().str();
+ if (++j < M) ItinString += " | ";
+ }
+
+ int TimeInc = Stage->getValueAsInt("TimeInc");
+ ItinString += ", " + itostr(TimeInc);
+
+ int Kind = Stage->getValueAsInt("Kind");
+ ItinString += ", (llvm::InstrStage::ReservationKinds)" + itostr(Kind);
+
+ // Close off stage
+ ItinString += " }";
+ if (++i < N) ItinString += ", ";
+ }
+}
+
+//
+// FormItineraryOperandCycleString - Compose a string containing the
+// operand cycle initialization for the specified itinerary. N is the
+// number of operands that has cycles specified.
+//
+void SubtargetEmitter::FormItineraryOperandCycleString(Record *ItinData,
+ std::string &ItinString, unsigned &NOperandCycles) {
+ // Get operand cycle list
+ const std::vector<int64_t> &OperandCycleList =
+ ItinData->getValueAsListOfInts("OperandCycles");
+
+ // For each operand cycle
+ unsigned N = NOperandCycles = OperandCycleList.size();
+ for (unsigned i = 0; i < N;) {
+ // Next operand cycle
+ const int OCycle = OperandCycleList[i];
+
+ ItinString += " " + itostr(OCycle);
+ if (++i < N) ItinString += ", ";
+ }
+}
+
+void SubtargetEmitter::FormItineraryBypassString(const std::string &Name,
+ Record *ItinData,
+ std::string &ItinString,
+ unsigned NOperandCycles) {
+ const std::vector<Record*> &BypassList =
+ ItinData->getValueAsListOfDefs("Bypasses");
+ unsigned N = BypassList.size();
+ unsigned i = 0;
+ for (; i < N;) {
+ ItinString += Name + "Bypass::" + BypassList[i]->getName().str();
+ if (++i < NOperandCycles) ItinString += ", ";
+ }
+ for (; i < NOperandCycles;) {
+ ItinString += " 0";
+ if (++i < NOperandCycles) ItinString += ", ";
+ }
+}
+
+//
+// EmitStageAndOperandCycleData - Generate unique itinerary stages and operand
+// cycle tables. Create a list of InstrItinerary objects (ProcItinLists) indexed
+// by CodeGenSchedClass::Index.
+//
+void SubtargetEmitter::
+EmitStageAndOperandCycleData(raw_ostream &OS,
+ std::vector<std::vector<InstrItinerary>>
+ &ProcItinLists) {
+ // Multiple processor models may share an itinerary record. Emit it once.
+ SmallPtrSet<Record*, 8> ItinsDefSet;
+
+ // Emit functional units for all the itineraries.
+ for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
+
+ if (!ItinsDefSet.insert(ProcModel.ItinsDef).second)
+ continue;
+
+ std::vector<Record*> FUs = ProcModel.ItinsDef->getValueAsListOfDefs("FU");
+ if (FUs.empty())
+ continue;
+
+ const std::string &Name = ProcModel.ItinsDef->getName();
+ OS << "\n// Functional units for \"" << Name << "\"\n"
+ << "namespace " << Name << "FU {\n";
+
+ for (unsigned j = 0, FUN = FUs.size(); j < FUN; ++j)
+ OS << " const unsigned " << FUs[j]->getName()
+ << " = 1 << " << j << ";\n";
+
+ OS << "} // end namespace " << Name << "FU\n";
+
+ std::vector<Record*> BPs = ProcModel.ItinsDef->getValueAsListOfDefs("BP");
+ if (!BPs.empty()) {
+ OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
+ << "\"\n" << "namespace " << Name << "Bypass {\n";
+
+ OS << " const unsigned NoBypass = 0;\n";
+ for (unsigned j = 0, BPN = BPs.size(); j < BPN; ++j)
+ OS << " const unsigned " << BPs[j]->getName()
+ << " = 1 << " << j << ";\n";
+
+ OS << "} // end namespace " << Name << "Bypass\n";
+ }
+ }
+
+ // Begin stages table
+ std::string StageTable = "\nextern const llvm::InstrStage " + Target +
+ "Stages[] = {\n";
+ StageTable += " { 0, 0, 0, llvm::InstrStage::Required }, // No itinerary\n";
+
+ // Begin operand cycle table
+ std::string OperandCycleTable = "extern const unsigned " + Target +
+ "OperandCycles[] = {\n";
+ OperandCycleTable += " 0, // No itinerary\n";
+
+ // Begin pipeline bypass table
+ std::string BypassTable = "extern const unsigned " + Target +
+ "ForwardingPaths[] = {\n";
+ BypassTable += " 0, // No itinerary\n";
+
+ // For each Itinerary across all processors, add a unique entry to the stages,
+ // operand cycles, and pipepine bypess tables. Then add the new Itinerary
+ // object with computed offsets to the ProcItinLists result.
+ unsigned StageCount = 1, OperandCycleCount = 1;
+ std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
+ for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
+ // Add process itinerary to the list.
+ ProcItinLists.resize(ProcItinLists.size()+1);
+
+ // If this processor defines no itineraries, then leave the itinerary list
+ // empty.
+ std::vector<InstrItinerary> &ItinList = ProcItinLists.back();
+ if (!ProcModel.hasItineraries())
+ continue;
+
+ const std::string &Name = ProcModel.ItinsDef->getName();
+
+ ItinList.resize(SchedModels.numInstrSchedClasses());
+ assert(ProcModel.ItinDefList.size() == ItinList.size() && "bad Itins");
+
+ for (unsigned SchedClassIdx = 0, SchedClassEnd = ItinList.size();
+ SchedClassIdx < SchedClassEnd; ++SchedClassIdx) {
+
+ // Next itinerary data
+ Record *ItinData = ProcModel.ItinDefList[SchedClassIdx];
+
+ // Get string and stage count
+ std::string ItinStageString;
+ unsigned NStages = 0;
+ if (ItinData)
+ FormItineraryStageString(Name, ItinData, ItinStageString, NStages);
+
+ // Get string and operand cycle count
+ std::string ItinOperandCycleString;
+ unsigned NOperandCycles = 0;
+ std::string ItinBypassString;
+ if (ItinData) {
+ FormItineraryOperandCycleString(ItinData, ItinOperandCycleString,
+ NOperandCycles);
+
+ FormItineraryBypassString(Name, ItinData, ItinBypassString,
+ NOperandCycles);
+ }
+
+ // Check to see if stage already exists and create if it doesn't
+ unsigned FindStage = 0;
+ if (NStages > 0) {
+ FindStage = ItinStageMap[ItinStageString];
+ if (FindStage == 0) {
+ // Emit as { cycles, u1 | u2 | ... | un, timeinc }, // indices
+ StageTable += ItinStageString + ", // " + itostr(StageCount);
+ if (NStages > 1)
+ StageTable += "-" + itostr(StageCount + NStages - 1);
+ StageTable += "\n";
+ // Record Itin class number.
+ ItinStageMap[ItinStageString] = FindStage = StageCount;
+ StageCount += NStages;
+ }
+ }
+
+ // Check to see if operand cycle already exists and create if it doesn't
+ unsigned FindOperandCycle = 0;
+ if (NOperandCycles > 0) {
+ std::string ItinOperandString = ItinOperandCycleString+ItinBypassString;
+ FindOperandCycle = ItinOperandMap[ItinOperandString];
+ if (FindOperandCycle == 0) {
+ // Emit as cycle, // index
+ OperandCycleTable += ItinOperandCycleString + ", // ";
+ std::string OperandIdxComment = itostr(OperandCycleCount);
+ if (NOperandCycles > 1)
+ OperandIdxComment += "-"
+ + itostr(OperandCycleCount + NOperandCycles - 1);
+ OperandCycleTable += OperandIdxComment + "\n";
+ // Record Itin class number.
+ ItinOperandMap[ItinOperandCycleString] =
+ FindOperandCycle = OperandCycleCount;
+ // Emit as bypass, // index
+ BypassTable += ItinBypassString + ", // " + OperandIdxComment + "\n";
+ OperandCycleCount += NOperandCycles;
+ }
+ }
+
+ // Set up itinerary as location and location + stage count
+ int NumUOps = ItinData ? ItinData->getValueAsInt("NumMicroOps") : 0;
+ InstrItinerary Intinerary = { NumUOps, FindStage, FindStage + NStages,
+ FindOperandCycle,
+ FindOperandCycle + NOperandCycles };
+
+ // Inject - empty slots will be 0, 0
+ ItinList[SchedClassIdx] = Intinerary;
+ }
+ }
+
+ // Closing stage
+ StageTable += " { 0, 0, 0, llvm::InstrStage::Required } // End stages\n";
+ StageTable += "};\n";
+
+ // Closing operand cycles
+ OperandCycleTable += " 0 // End operand cycles\n";
+ OperandCycleTable += "};\n";
+
+ BypassTable += " 0 // End bypass tables\n";
+ BypassTable += "};\n";
+
+ // Emit tables.
+ OS << StageTable;
+ OS << OperandCycleTable;
+ OS << BypassTable;
+}
+
+//
+// EmitProcessorData - Generate data for processor itineraries that were
+// computed during EmitStageAndOperandCycleData(). ProcItinLists lists all
+// Itineraries for each processor. The Itinerary lists are indexed on
+// CodeGenSchedClass::Index.
+//
+void SubtargetEmitter::
+EmitItineraries(raw_ostream &OS,
+ std::vector<std::vector<InstrItinerary>> &ProcItinLists) {
+ // Multiple processor models may share an itinerary record. Emit it once.
+ SmallPtrSet<Record*, 8> ItinsDefSet;
+
+ // For each processor's machine model
+ std::vector<std::vector<InstrItinerary>>::iterator
+ ProcItinListsIter = ProcItinLists.begin();
+ for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
+ PE = SchedModels.procModelEnd(); PI != PE; ++PI, ++ProcItinListsIter) {
+
+ Record *ItinsDef = PI->ItinsDef;
+ if (!ItinsDefSet.insert(ItinsDef).second)
+ continue;
+
+ // Get processor itinerary name
+ const std::string &Name = ItinsDef->getName();
+
+ // Get the itinerary list for the processor.
+ assert(ProcItinListsIter != ProcItinLists.end() && "bad iterator");
+ std::vector<InstrItinerary> &ItinList = *ProcItinListsIter;
+
+ // Empty itineraries aren't referenced anywhere in the tablegen output
+ // so don't emit them.
+ if (ItinList.empty())
+ continue;
+
+ OS << "\n";
+ OS << "static const llvm::InstrItinerary ";
+
+ // Begin processor itinerary table
+ OS << Name << "[] = {\n";
+
+ // For each itinerary class in CodeGenSchedClass::Index order.
+ for (unsigned j = 0, M = ItinList.size(); j < M; ++j) {
+ InstrItinerary &Intinerary = ItinList[j];
+
+ // Emit Itinerary in the form of
+ // { firstStage, lastStage, firstCycle, lastCycle } // index
+ OS << " { " <<
+ Intinerary.NumMicroOps << ", " <<
+ Intinerary.FirstStage << ", " <<
+ Intinerary.LastStage << ", " <<
+ Intinerary.FirstOperandCycle << ", " <<
+ Intinerary.LastOperandCycle << " }" <<
+ ", // " << j << " " << SchedModels.getSchedClass(j).Name << "\n";
+ }
+ // End processor itinerary table
+ OS << " { 0, ~0U, ~0U, ~0U, ~0U } // end marker\n";
+ OS << "};\n";
+ }
+}
+
+// Emit either the value defined in the TableGen Record, or the default
+// value defined in the C++ header. The Record is null if the processor does not
+// define a model.
+void SubtargetEmitter::EmitProcessorProp(raw_ostream &OS, const Record *R,
+ StringRef Name, char Separator) {
+ OS << " ";
+ int V = R ? R->getValueAsInt(Name) : -1;
+ if (V >= 0)
+ OS << V << Separator << " // " << Name;
+ else
+ OS << "MCSchedModel::Default" << Name << Separator;
+ OS << '\n';
+}
+
+void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
+ raw_ostream &OS) {
+ char Sep = ProcModel.ProcResourceDefs.empty() ? ' ' : ',';
+
+ OS << "\n// {Name, NumUnits, SuperIdx, IsBuffered}\n";
+ OS << "static const llvm::MCProcResourceDesc "
+ << ProcModel.ModelName << "ProcResources" << "[] = {\n"
+ << " {DBGFIELD(\"InvalidUnit\") 0, 0, 0}" << Sep << "\n";
+
+ for (unsigned i = 0, e = ProcModel.ProcResourceDefs.size(); i < e; ++i) {
+ Record *PRDef = ProcModel.ProcResourceDefs[i];
+
+ Record *SuperDef = nullptr;
+ unsigned SuperIdx = 0;
+ unsigned NumUnits = 0;
+ int BufferSize = PRDef->getValueAsInt("BufferSize");
+ if (PRDef->isSubClassOf("ProcResGroup")) {
+ RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources");
+ for (Record *RU : ResUnits) {
+ NumUnits += RU->getValueAsInt("NumUnits");
+ }
+ }
+ else {
+ // Find the SuperIdx
+ if (PRDef->getValueInit("Super")->isComplete()) {
+ SuperDef = SchedModels.findProcResUnits(
+ PRDef->getValueAsDef("Super"), ProcModel);
+ SuperIdx = ProcModel.getProcResourceIdx(SuperDef);
+ }
+ NumUnits = PRDef->getValueAsInt("NumUnits");
+ }
+ // Emit the ProcResourceDesc
+ if (i+1 == e)
+ Sep = ' ';
+ OS << " {DBGFIELD(\"" << PRDef->getName() << "\") ";
+ if (PRDef->getName().size() < 15)
+ OS.indent(15 - PRDef->getName().size());
+ OS << NumUnits << ", " << SuperIdx << ", "
+ << BufferSize << "}" << Sep << " // #" << i+1;
+ if (SuperDef)
+ OS << ", Super=" << SuperDef->getName();
+ OS << "\n";
+ }
+ OS << "};\n";
+}
+
+// Find the WriteRes Record that defines processor resources for this
+// SchedWrite.
+Record *SubtargetEmitter::FindWriteResources(
+ const CodeGenSchedRW &SchedWrite, const CodeGenProcModel &ProcModel) {
+
+ // Check if the SchedWrite is already subtarget-specific and directly
+ // specifies a set of processor resources.
+ if (SchedWrite.TheDef->isSubClassOf("SchedWriteRes"))
+ return SchedWrite.TheDef;
+
+ Record *AliasDef = nullptr;
+ for (Record *A : SchedWrite.Aliases) {
+ const CodeGenSchedRW &AliasRW =
+ SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
+ if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
+ Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+ if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
+ continue;
+ }
+ if (AliasDef)
+ PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
+ "defined for processor " + ProcModel.ModelName +
+ " Ensure only one SchedAlias exists per RW.");
+ AliasDef = AliasRW.TheDef;
+ }
+ if (AliasDef && AliasDef->isSubClassOf("SchedWriteRes"))
+ return AliasDef;
+
+ // Check this processor's list of write resources.
+ Record *ResDef = nullptr;
+ for (Record *WR : ProcModel.WriteResDefs) {
+ if (!WR->isSubClassOf("WriteRes"))
+ continue;
+ if (AliasDef == WR->getValueAsDef("WriteType")
+ || SchedWrite.TheDef == WR->getValueAsDef("WriteType")) {
+ if (ResDef) {
+ PrintFatalError(WR->getLoc(), "Resources are defined for both "
+ "SchedWrite and its alias on processor " +
+ ProcModel.ModelName);
+ }
+ ResDef = WR;
+ }
+ }
+ // TODO: If ProcModel has a base model (previous generation processor),
+ // then call FindWriteResources recursively with that model here.
+ if (!ResDef) {
+ PrintFatalError(ProcModel.ModelDef->getLoc(),
+ std::string("Processor does not define resources for ")
+ + SchedWrite.TheDef->getName());
+ }
+ return ResDef;
+}
+
+/// Find the ReadAdvance record for the given SchedRead on this processor or
+/// return NULL.
+Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
+ const CodeGenProcModel &ProcModel) {
+ // Check for SchedReads that directly specify a ReadAdvance.
+ if (SchedRead.TheDef->isSubClassOf("SchedReadAdvance"))
+ return SchedRead.TheDef;
+
+ // Check this processor's list of aliases for SchedRead.
+ Record *AliasDef = nullptr;
+ for (Record *A : SchedRead.Aliases) {
+ const CodeGenSchedRW &AliasRW =
+ SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
+ if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
+ Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
+ if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
+ continue;
+ }
+ if (AliasDef)
+ PrintFatalError(AliasRW.TheDef->getLoc(), "Multiple aliases "
+ "defined for processor " + ProcModel.ModelName +
+ " Ensure only one SchedAlias exists per RW.");
+ AliasDef = AliasRW.TheDef;
+ }
+ if (AliasDef && AliasDef->isSubClassOf("SchedReadAdvance"))
+ return AliasDef;
+
+ // Check this processor's ReadAdvanceList.
+ Record *ResDef = nullptr;
+ for (Record *RA : ProcModel.ReadAdvanceDefs) {
+ if (!RA->isSubClassOf("ReadAdvance"))
+ continue;
+ if (AliasDef == RA->getValueAsDef("ReadType")
+ || SchedRead.TheDef == RA->getValueAsDef("ReadType")) {
+ if (ResDef) {
+ PrintFatalError(RA->getLoc(), "Resources are defined for both "
+ "SchedRead and its alias on processor " +
+ ProcModel.ModelName);
+ }
+ ResDef = RA;
+ }
+ }
+ // TODO: If ProcModel has a base model (previous generation processor),
+ // then call FindReadAdvance recursively with that model here.
+ if (!ResDef && SchedRead.TheDef->getName() != "ReadDefault") {
+ PrintFatalError(ProcModel.ModelDef->getLoc(),
+ std::string("Processor does not define resources for ")
+ + SchedRead.TheDef->getName());
+ }
+ return ResDef;
+}
+
+// Expand an explicit list of processor resources into a full list of implied
+// resource groups and super resources that cover them.
+void SubtargetEmitter::ExpandProcResources(RecVec &PRVec,
+ std::vector<int64_t> &Cycles,
+ const CodeGenProcModel &PM) {
+ // Default to 1 resource cycle.
+ Cycles.resize(PRVec.size(), 1);
+ for (unsigned i = 0, e = PRVec.size(); i != e; ++i) {
+ Record *PRDef = PRVec[i];
+ RecVec SubResources;
+ if (PRDef->isSubClassOf("ProcResGroup"))
+ SubResources = PRDef->getValueAsListOfDefs("Resources");
+ else {
+ SubResources.push_back(PRDef);
+ PRDef = SchedModels.findProcResUnits(PRVec[i], PM);
+ for (Record *SubDef = PRDef;
+ SubDef->getValueInit("Super")->isComplete();) {
+ if (SubDef->isSubClassOf("ProcResGroup")) {
+ // Disallow this for simplicitly.
+ PrintFatalError(SubDef->getLoc(), "Processor resource group "
+ " cannot be a super resources.");
+ }
+ Record *SuperDef =
+ SchedModels.findProcResUnits(SubDef->getValueAsDef("Super"), PM);
+ PRVec.push_back(SuperDef);
+ Cycles.push_back(Cycles[i]);
+ SubDef = SuperDef;
+ }
+ }
+ for (Record *PR : PM.ProcResourceDefs) {
+ if (PR == PRDef || !PR->isSubClassOf("ProcResGroup"))
+ continue;
+ RecVec SuperResources = PR->getValueAsListOfDefs("Resources");
+ RecIter SubI = SubResources.begin(), SubE = SubResources.end();
+ for( ; SubI != SubE; ++SubI) {
+ if (!is_contained(SuperResources, *SubI)) {
+ break;
+ }
+ }
+ if (SubI == SubE) {
+ PRVec.push_back(PR);
+ Cycles.push_back(Cycles[i]);
+ }
+ }
+ }
+}
+
+// Generate the SchedClass table for this processor and update global
+// tables. Must be called for each processor in order.
+void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
+ SchedClassTables &SchedTables) {
+ SchedTables.ProcSchedClasses.resize(SchedTables.ProcSchedClasses.size() + 1);
+ if (!ProcModel.hasInstrSchedModel())
+ return;
+
+ std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back();
+ for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) {
+ DEBUG(SC.dump(&SchedModels));
+
+ SCTab.resize(SCTab.size() + 1);
+ MCSchedClassDesc &SCDesc = SCTab.back();
+ // SCDesc.Name is guarded by NDEBUG
+ SCDesc.NumMicroOps = 0;
+ SCDesc.BeginGroup = false;
+ SCDesc.EndGroup = false;
+ SCDesc.WriteProcResIdx = 0;
+ SCDesc.WriteLatencyIdx = 0;
+ SCDesc.ReadAdvanceIdx = 0;
+
+ // A Variant SchedClass has no resources of its own.
+ bool HasVariants = false;
+ for (std::vector<CodeGenSchedTransition>::const_iterator
+ TI = SC.Transitions.begin(), TE = SC.Transitions.end();
+ TI != TE; ++TI) {
+ if (TI->ProcIndices[0] == 0) {
+ HasVariants = true;
+ break;
+ }
+ if (is_contained(TI->ProcIndices, ProcModel.Index)) {
+ HasVariants = true;
+ break;
+ }
+ }
+ if (HasVariants) {
+ SCDesc.NumMicroOps = MCSchedClassDesc::VariantNumMicroOps;
+ continue;
+ }
+
+ // Determine if the SchedClass is actually reachable on this processor. If
+ // not don't try to locate the processor resources, it will fail.
+ // If ProcIndices contains 0, this class applies to all processors.
+ assert(!SC.ProcIndices.empty() && "expect at least one procidx");
+ if (SC.ProcIndices[0] != 0) {
+ if (!is_contained(SC.ProcIndices, ProcModel.Index))
+ continue;
+ }
+ IdxVec Writes = SC.Writes;
+ IdxVec Reads = SC.Reads;
+ if (!SC.InstRWs.empty()) {
+ // This class has a default ReadWrite list which can be overriden by
+ // InstRW definitions.
+ Record *RWDef = nullptr;
+ for (Record *RW : SC.InstRWs) {
+ Record *RWModelDef = RW->getValueAsDef("SchedModel");
+ if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) {
+ RWDef = RW;
+ break;
+ }
+ }
+ if (RWDef) {
+ Writes.clear();
+ Reads.clear();
+ SchedModels.findRWs(RWDef->getValueAsListOfDefs("OperandReadWrites"),
+ Writes, Reads);
+ }
+ }
+ if (Writes.empty()) {
+ // Check this processor's itinerary class resources.
+ for (Record *I : ProcModel.ItinRWDefs) {
+ RecVec Matched = I->getValueAsListOfDefs("MatchedItinClasses");
+ if (is_contained(Matched, SC.ItinClassDef)) {
+ SchedModels.findRWs(I->getValueAsListOfDefs("OperandReadWrites"),
+ Writes, Reads);
+ break;
+ }
+ }
+ if (Writes.empty()) {
+ DEBUG(dbgs() << ProcModel.ModelName
+ << " does not have resources for class " << SC.Name << '\n');
+ }
+ }
+ // Sum resources across all operand writes.
+ std::vector<MCWriteProcResEntry> WriteProcResources;
+ std::vector<MCWriteLatencyEntry> WriteLatencies;
+ std::vector<std::string> WriterNames;
+ std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
+ for (unsigned W : Writes) {
+ IdxVec WriteSeq;
+ SchedModels.expandRWSeqForProc(W, WriteSeq, /*IsRead=*/false,
+ ProcModel);
+
+ // For each operand, create a latency entry.
+ MCWriteLatencyEntry WLEntry;
+ WLEntry.Cycles = 0;
+ unsigned WriteID = WriteSeq.back();
+ WriterNames.push_back(SchedModels.getSchedWrite(WriteID).Name);
+ // If this Write is not referenced by a ReadAdvance, don't distinguish it
+ // from other WriteLatency entries.
+ if (!SchedModels.hasReadOfWrite(
+ SchedModels.getSchedWrite(WriteID).TheDef)) {
+ WriteID = 0;
+ }
+ WLEntry.WriteResourceID = WriteID;
+
+ for (unsigned WS : WriteSeq) {
+
+ Record *WriteRes =
+ FindWriteResources(SchedModels.getSchedWrite(WS), ProcModel);
+
+ // Mark the parent class as invalid for unsupported write types.
+ if (WriteRes->getValueAsBit("Unsupported")) {
+ SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
+ break;
+ }
+ WLEntry.Cycles += WriteRes->getValueAsInt("Latency");
+ SCDesc.NumMicroOps += WriteRes->getValueAsInt("NumMicroOps");
+ SCDesc.BeginGroup |= WriteRes->getValueAsBit("BeginGroup");
+ SCDesc.EndGroup |= WriteRes->getValueAsBit("EndGroup");
+ SCDesc.BeginGroup |= WriteRes->getValueAsBit("SingleIssue");
+ SCDesc.EndGroup |= WriteRes->getValueAsBit("SingleIssue");
+
+ // Create an entry for each ProcResource listed in WriteRes.
+ RecVec PRVec = WriteRes->getValueAsListOfDefs("ProcResources");
+ std::vector<int64_t> Cycles =
+ WriteRes->getValueAsListOfInts("ResourceCycles");
+
+ ExpandProcResources(PRVec, Cycles, ProcModel);
+
+ for (unsigned PRIdx = 0, PREnd = PRVec.size();
+ PRIdx != PREnd; ++PRIdx) {
+ MCWriteProcResEntry WPREntry;
+ WPREntry.ProcResourceIdx = ProcModel.getProcResourceIdx(PRVec[PRIdx]);
+ assert(WPREntry.ProcResourceIdx && "Bad ProcResourceIdx");
+ WPREntry.Cycles = Cycles[PRIdx];
+ // If this resource is already used in this sequence, add the current
+ // entry's cycles so that the same resource appears to be used
+ // serially, rather than multiple parallel uses. This is important for
+ // in-order machine where the resource consumption is a hazard.
+ unsigned WPRIdx = 0, WPREnd = WriteProcResources.size();
+ for( ; WPRIdx != WPREnd; ++WPRIdx) {
+ if (WriteProcResources[WPRIdx].ProcResourceIdx
+ == WPREntry.ProcResourceIdx) {
+ WriteProcResources[WPRIdx].Cycles += WPREntry.Cycles;
+ break;
+ }
+ }
+ if (WPRIdx == WPREnd)
+ WriteProcResources.push_back(WPREntry);
+ }
+ }
+ WriteLatencies.push_back(WLEntry);
+ }
+ // Create an entry for each operand Read in this SchedClass.
+ // Entries must be sorted first by UseIdx then by WriteResourceID.
+ for (unsigned UseIdx = 0, EndIdx = Reads.size();
+ UseIdx != EndIdx; ++UseIdx) {
+ Record *ReadAdvance =
+ FindReadAdvance(SchedModels.getSchedRead(Reads[UseIdx]), ProcModel);
+ if (!ReadAdvance)
+ continue;
+
+ // Mark the parent class as invalid for unsupported write types.
+ if (ReadAdvance->getValueAsBit("Unsupported")) {
+ SCDesc.NumMicroOps = MCSchedClassDesc::InvalidNumMicroOps;
+ break;
+ }
+ RecVec ValidWrites = ReadAdvance->getValueAsListOfDefs("ValidWrites");
+ IdxVec WriteIDs;
+ if (ValidWrites.empty())
+ WriteIDs.push_back(0);
+ else {
+ for (Record *VW : ValidWrites) {
+ WriteIDs.push_back(SchedModels.getSchedRWIdx(VW, /*IsRead=*/false));
+ }
+ }
+ std::sort(WriteIDs.begin(), WriteIDs.end());
+ for(unsigned W : WriteIDs) {
+ MCReadAdvanceEntry RAEntry;
+ RAEntry.UseIdx = UseIdx;
+ RAEntry.WriteResourceID = W;
+ RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
+ ReadAdvanceEntries.push_back(RAEntry);
+ }
+ }
+ if (SCDesc.NumMicroOps == MCSchedClassDesc::InvalidNumMicroOps) {
+ WriteProcResources.clear();
+ WriteLatencies.clear();
+ ReadAdvanceEntries.clear();
+ }
+ // Add the information for this SchedClass to the global tables using basic
+ // compression.
+ //
+ // WritePrecRes entries are sorted by ProcResIdx.
+ std::sort(WriteProcResources.begin(), WriteProcResources.end(),
+ LessWriteProcResources());
+
+ SCDesc.NumWriteProcResEntries = WriteProcResources.size();
+ std::vector<MCWriteProcResEntry>::iterator WPRPos =
+ std::search(SchedTables.WriteProcResources.begin(),
+ SchedTables.WriteProcResources.end(),
+ WriteProcResources.begin(), WriteProcResources.end());
+ if (WPRPos != SchedTables.WriteProcResources.end())
+ SCDesc.WriteProcResIdx = WPRPos - SchedTables.WriteProcResources.begin();
+ else {
+ SCDesc.WriteProcResIdx = SchedTables.WriteProcResources.size();
+ SchedTables.WriteProcResources.insert(WPRPos, WriteProcResources.begin(),
+ WriteProcResources.end());
+ }
+ // Latency entries must remain in operand order.
+ SCDesc.NumWriteLatencyEntries = WriteLatencies.size();
+ std::vector<MCWriteLatencyEntry>::iterator WLPos =
+ std::search(SchedTables.WriteLatencies.begin(),
+ SchedTables.WriteLatencies.end(),
+ WriteLatencies.begin(), WriteLatencies.end());
+ if (WLPos != SchedTables.WriteLatencies.end()) {
+ unsigned idx = WLPos - SchedTables.WriteLatencies.begin();
+ SCDesc.WriteLatencyIdx = idx;
+ for (unsigned i = 0, e = WriteLatencies.size(); i < e; ++i)
+ if (SchedTables.WriterNames[idx + i].find(WriterNames[i]) ==
+ std::string::npos) {
+ SchedTables.WriterNames[idx + i] += std::string("_") + WriterNames[i];
+ }
+ }
+ else {
+ SCDesc.WriteLatencyIdx = SchedTables.WriteLatencies.size();
+ SchedTables.WriteLatencies.insert(SchedTables.WriteLatencies.end(),
+ WriteLatencies.begin(),
+ WriteLatencies.end());
+ SchedTables.WriterNames.insert(SchedTables.WriterNames.end(),
+ WriterNames.begin(), WriterNames.end());
+ }
+ // ReadAdvanceEntries must remain in operand order.
+ SCDesc.NumReadAdvanceEntries = ReadAdvanceEntries.size();
+ std::vector<MCReadAdvanceEntry>::iterator RAPos =
+ std::search(SchedTables.ReadAdvanceEntries.begin(),
+ SchedTables.ReadAdvanceEntries.end(),
+ ReadAdvanceEntries.begin(), ReadAdvanceEntries.end());
+ if (RAPos != SchedTables.ReadAdvanceEntries.end())
+ SCDesc.ReadAdvanceIdx = RAPos - SchedTables.ReadAdvanceEntries.begin();
+ else {
+ SCDesc.ReadAdvanceIdx = SchedTables.ReadAdvanceEntries.size();
+ SchedTables.ReadAdvanceEntries.insert(RAPos, ReadAdvanceEntries.begin(),
+ ReadAdvanceEntries.end());
+ }
+ }
+}
+
+// Emit SchedClass tables for all processors and associated global tables.
+void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
+ raw_ostream &OS) {
+ // Emit global WriteProcResTable.
+ OS << "\n// {ProcResourceIdx, Cycles}\n"
+ << "extern const llvm::MCWriteProcResEntry "
+ << Target << "WriteProcResTable[] = {\n"
+ << " { 0, 0}, // Invalid\n";
+ for (unsigned WPRIdx = 1, WPREnd = SchedTables.WriteProcResources.size();
+ WPRIdx != WPREnd; ++WPRIdx) {
+ MCWriteProcResEntry &WPREntry = SchedTables.WriteProcResources[WPRIdx];
+ OS << " {" << format("%2d", WPREntry.ProcResourceIdx) << ", "
+ << format("%2d", WPREntry.Cycles) << "}";
+ if (WPRIdx + 1 < WPREnd)
+ OS << ',';
+ OS << " // #" << WPRIdx << '\n';
+ }
+ OS << "}; // " << Target << "WriteProcResTable\n";
+
+ // Emit global WriteLatencyTable.
+ OS << "\n// {Cycles, WriteResourceID}\n"
+ << "extern const llvm::MCWriteLatencyEntry "
+ << Target << "WriteLatencyTable[] = {\n"
+ << " { 0, 0}, // Invalid\n";
+ for (unsigned WLIdx = 1, WLEnd = SchedTables.WriteLatencies.size();
+ WLIdx != WLEnd; ++WLIdx) {
+ MCWriteLatencyEntry &WLEntry = SchedTables.WriteLatencies[WLIdx];
+ OS << " {" << format("%2d", WLEntry.Cycles) << ", "
+ << format("%2d", WLEntry.WriteResourceID) << "}";
+ if (WLIdx + 1 < WLEnd)
+ OS << ',';
+ OS << " // #" << WLIdx << " " << SchedTables.WriterNames[WLIdx] << '\n';
+ }
+ OS << "}; // " << Target << "WriteLatencyTable\n";
+
+ // Emit global ReadAdvanceTable.
+ OS << "\n// {UseIdx, WriteResourceID, Cycles}\n"
+ << "extern const llvm::MCReadAdvanceEntry "
+ << Target << "ReadAdvanceTable[] = {\n"
+ << " {0, 0, 0}, // Invalid\n";
+ for (unsigned RAIdx = 1, RAEnd = SchedTables.ReadAdvanceEntries.size();
+ RAIdx != RAEnd; ++RAIdx) {
+ MCReadAdvanceEntry &RAEntry = SchedTables.ReadAdvanceEntries[RAIdx];
+ OS << " {" << RAEntry.UseIdx << ", "
+ << format("%2d", RAEntry.WriteResourceID) << ", "
+ << format("%2d", RAEntry.Cycles) << "}";
+ if (RAIdx + 1 < RAEnd)
+ OS << ',';
+ OS << " // #" << RAIdx << '\n';
+ }
+ OS << "}; // " << Target << "ReadAdvanceTable\n";
+
+ // Emit a SchedClass table for each processor.
+ for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
+ PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
+ if (!PI->hasInstrSchedModel())
+ continue;
+
+ std::vector<MCSchedClassDesc> &SCTab =
+ SchedTables.ProcSchedClasses[1 + (PI - SchedModels.procModelBegin())];
+
+ OS << "\n// {Name, NumMicroOps, BeginGroup, EndGroup,"
+ << " WriteProcResIdx,#, WriteLatencyIdx,#, ReadAdvanceIdx,#}\n";
+ OS << "static const llvm::MCSchedClassDesc "
+ << PI->ModelName << "SchedClasses[] = {\n";
+
+ // The first class is always invalid. We no way to distinguish it except by
+ // name and position.
+ assert(SchedModels.getSchedClass(0).Name == "NoInstrModel"
+ && "invalid class not first");
+ OS << " {DBGFIELD(\"InvalidSchedClass\") "
+ << MCSchedClassDesc::InvalidNumMicroOps
+ << ", false, false, 0, 0, 0, 0, 0, 0},\n";
+
+ for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
+ MCSchedClassDesc &MCDesc = SCTab[SCIdx];
+ const CodeGenSchedClass &SchedClass = SchedModels.getSchedClass(SCIdx);
+ OS << " {DBGFIELD(\"" << SchedClass.Name << "\") ";
+ if (SchedClass.Name.size() < 18)
+ OS.indent(18 - SchedClass.Name.size());
+ OS << MCDesc.NumMicroOps
+ << ", " << ( MCDesc.BeginGroup ? "true" : "false" )
+ << ", " << ( MCDesc.EndGroup ? "true" : "false" )
+ << ", " << format("%2d", MCDesc.WriteProcResIdx)
+ << ", " << MCDesc.NumWriteProcResEntries
+ << ", " << format("%2d", MCDesc.WriteLatencyIdx)
+ << ", " << MCDesc.NumWriteLatencyEntries
+ << ", " << format("%2d", MCDesc.ReadAdvanceIdx)
+ << ", " << MCDesc.NumReadAdvanceEntries << "}";
+ if (SCIdx + 1 < SCEnd)
+ OS << ',';
+ OS << " // #" << SCIdx << '\n';
+ }
+ OS << "}; // " << PI->ModelName << "SchedClasses\n";
+ }
+}
+
+void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
+ // For each processor model.
+ for (const CodeGenProcModel &PM : SchedModels.procModels()) {
+ // Emit processor resource table.
+ if (PM.hasInstrSchedModel())
+ EmitProcessorResources(PM, OS);
+ else if(!PM.ProcResourceDefs.empty())
+ PrintFatalError(PM.ModelDef->getLoc(), "SchedMachineModel defines "
+ "ProcResources without defining WriteRes SchedWriteRes");
+
+ // Begin processor itinerary properties
+ OS << "\n";
+ OS << "static const llvm::MCSchedModel " << PM.ModelName << " = {\n";
+ EmitProcessorProp(OS, PM.ModelDef, "IssueWidth", ',');
+ EmitProcessorProp(OS, PM.ModelDef, "MicroOpBufferSize", ',');
+ EmitProcessorProp(OS, PM.ModelDef, "LoopMicroOpBufferSize", ',');
+ EmitProcessorProp(OS, PM.ModelDef, "LoadLatency", ',');
+ EmitProcessorProp(OS, PM.ModelDef, "HighLatency", ',');
+ EmitProcessorProp(OS, PM.ModelDef, "MispredictPenalty", ',');
+
+ bool PostRAScheduler =
+ (PM.ModelDef ? PM.ModelDef->getValueAsBit("PostRAScheduler") : false);
+
+ OS << " " << (PostRAScheduler ? "true" : "false") << ", // "
+ << "PostRAScheduler\n";
+
+ bool CompleteModel =
+ (PM.ModelDef ? PM.ModelDef->getValueAsBit("CompleteModel") : false);
+
+ OS << " " << (CompleteModel ? "true" : "false") << ", // "
+ << "CompleteModel\n";
+
+ OS << " " << PM.Index << ", // Processor ID\n";
+ if (PM.hasInstrSchedModel())
+ OS << " " << PM.ModelName << "ProcResources" << ",\n"
+ << " " << PM.ModelName << "SchedClasses" << ",\n"
+ << " " << PM.ProcResourceDefs.size()+1 << ",\n"
+ << " " << (SchedModels.schedClassEnd()
+ - SchedModels.schedClassBegin()) << ",\n";
+ else
+ OS << " nullptr, nullptr, 0, 0,"
+ << " // No instruction-level machine model.\n";
+ if (PM.hasItineraries())
+ OS << " " << PM.ItinsDef->getName() << "};\n";
+ else
+ OS << " nullptr}; // No Itinerary\n";
+ }
+}
+
+//
+// EmitProcessorLookup - generate cpu name to itinerary lookup table.
+//
+void SubtargetEmitter::EmitProcessorLookup(raw_ostream &OS) {
+ // Gather and sort processor information
+ std::vector<Record*> ProcessorList =
+ Records.getAllDerivedDefinitions("Processor");
+ std::sort(ProcessorList.begin(), ProcessorList.end(), LessRecordFieldName());
+
+ // Begin processor table
+ OS << "\n";
+ OS << "// Sorted (by key) array of itineraries for CPU subtype.\n"
+ << "extern const llvm::SubtargetInfoKV "
+ << Target << "ProcSchedKV[] = {\n";
+
+ // For each processor
+ for (unsigned i = 0, N = ProcessorList.size(); i < N;) {
+ // Next processor
+ Record *Processor = ProcessorList[i];
+
+ const std::string &Name = Processor->getValueAsString("Name");
+ const std::string &ProcModelName =
+ SchedModels.getModelForProc(Processor).ModelName;
+
+ // Emit as { "cpu", procinit },
+ OS << " { \"" << Name << "\", (const void *)&" << ProcModelName << " }";
+
+ // Depending on ''if more in the list'' emit comma
+ if (++i < N) OS << ",";
+
+ OS << "\n";
+ }
+
+ // End processor table
+ OS << "};\n";
+}
+
+//
+// EmitSchedModel - Emits all scheduling model tables, folding common patterns.
+//
+void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
+ OS << "#ifdef DBGFIELD\n"
+ << "#error \"<target>GenSubtargetInfo.inc requires a DBGFIELD macro\"\n"
+ << "#endif\n"
+ << "#ifndef NDEBUG\n"
+ << "#define DBGFIELD(x) x,\n"
+ << "#else\n"
+ << "#define DBGFIELD(x)\n"
+ << "#endif\n";
+
+ if (SchedModels.hasItineraries()) {
+ std::vector<std::vector<InstrItinerary>> ProcItinLists;
+ // Emit the stage data
+ EmitStageAndOperandCycleData(OS, ProcItinLists);
+ EmitItineraries(OS, ProcItinLists);
+ }
+ OS << "\n// ===============================================================\n"
+ << "// Data tables for the new per-operand machine model.\n";
+
+ SchedClassTables SchedTables;
+ for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
+ GenSchedClassTables(ProcModel, SchedTables);
+ }
+ EmitSchedClassTables(SchedTables, OS);
+
+ // Emit the processor machine model
+ EmitProcessorModels(OS);
+ // Emit the processor lookup data
+ EmitProcessorLookup(OS);
+
+ OS << "#undef DBGFIELD";
+}
+
+void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName,
+ raw_ostream &OS) {
+ OS << "unsigned " << ClassName
+ << "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,"
+ << " const TargetSchedModel *SchedModel) const {\n";
+
+ std::vector<Record*> Prologs = Records.getAllDerivedDefinitions("PredicateProlog");
+ std::sort(Prologs.begin(), Prologs.end(), LessRecord());
+ for (Record *P : Prologs) {
+ OS << P->getValueAsString("Code") << '\n';
+ }
+ IdxVec VariantClasses;
+ for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) {
+ if (SC.Transitions.empty())
+ continue;
+ VariantClasses.push_back(SC.Index);
+ }
+ if (!VariantClasses.empty()) {
+ OS << " switch (SchedClass) {\n";
+ for (unsigned VC : VariantClasses) {
+ const CodeGenSchedClass &SC = SchedModels.getSchedClass(VC);
+ OS << " case " << VC << ": // " << SC.Name << '\n';
+ IdxVec ProcIndices;
+ for (const CodeGenSchedTransition &T : SC.Transitions) {
+ IdxVec PI;
+ std::set_union(T.ProcIndices.begin(), T.ProcIndices.end(),
+ ProcIndices.begin(), ProcIndices.end(),
+ std::back_inserter(PI));
+ ProcIndices.swap(PI);
+ }
+ for (unsigned PI : ProcIndices) {
+ OS << " ";
+ if (PI != 0)
+ OS << "if (SchedModel->getProcessorID() == " << PI << ") ";
+ OS << "{ // " << (SchedModels.procModelBegin() + PI)->ModelName
+ << '\n';
+ for (const CodeGenSchedTransition &T : SC.Transitions) {
+ if (PI != 0 && !std::count(T.ProcIndices.begin(),
+ T.ProcIndices.end(), PI)) {
+ continue;
+ }
+ OS << " if (";
+ for (RecIter RI = T.PredTerm.begin(), RE = T.PredTerm.end();
+ RI != RE; ++RI) {
+ if (RI != T.PredTerm.begin())
+ OS << "\n && ";
+ OS << "(" << (*RI)->getValueAsString("Predicate") << ")";
+ }
+ OS << ")\n"
+ << " return " << T.ToClassIdx << "; // "
+ << SchedModels.getSchedClass(T.ToClassIdx).Name << '\n';
+ }
+ OS << " }\n";
+ if (PI == 0)
+ break;
+ }
+ if (SC.isInferred())
+ OS << " return " << SC.Index << ";\n";
+ OS << " break;\n";
+ }
+ OS << " };\n";
+ }
+ OS << " report_fatal_error(\"Expected a variant SchedClass\");\n"
+ << "} // " << ClassName << "::resolveSchedClass\n";
+}
+
+//
+// ParseFeaturesFunction - Produces a subtarget specific function for parsing
+// the subtarget features string.
+//
+void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
+ unsigned NumFeatures,
+ unsigned NumProcs) {
+ std::vector<Record*> Features =
+ Records.getAllDerivedDefinitions("SubtargetFeature");
+ std::sort(Features.begin(), Features.end(), LessRecord());
+
+ OS << "// ParseSubtargetFeatures - Parses features string setting specified\n"
+ << "// subtarget options.\n"
+ << "void llvm::";
+ OS << Target;
+ OS << "Subtarget::ParseSubtargetFeatures(StringRef CPU, StringRef FS) {\n"
+ << " DEBUG(dbgs() << \"\\nFeatures:\" << FS);\n"
+ << " DEBUG(dbgs() << \"\\nCPU:\" << CPU << \"\\n\\n\");\n";
+
+ if (Features.empty()) {
+ OS << "}\n";
+ return;
+ }
+
+ OS << " InitMCProcessorInfo(CPU, FS);\n"
+ << " const FeatureBitset& Bits = getFeatureBits();\n";
+
+ for (Record *R : Features) {
+ // Next record
+ const std::string &Instance = R->getName();
+ const std::string &Value = R->getValueAsString("Value");
+ const std::string &Attribute = R->getValueAsString("Attribute");
+
+ if (Value=="true" || Value=="false")
+ OS << " if (Bits[" << Target << "::"
+ << Instance << "]) "
+ << Attribute << " = " << Value << ";\n";
+ else
+ OS << " if (Bits[" << Target << "::"
+ << Instance << "] && "
+ << Attribute << " < " << Value << ") "
+ << Attribute << " = " << Value << ";\n";
+ }
+
+ OS << "}\n";
+}
+
+//
+// SubtargetEmitter::run - Main subtarget enumeration emitter.
+//
+void SubtargetEmitter::run(raw_ostream &OS) {
+ emitSourceFileHeader("Subtarget Enumeration Source Fragment", OS);
+
+ OS << "\n#ifdef GET_SUBTARGETINFO_ENUM\n";
+ OS << "#undef GET_SUBTARGETINFO_ENUM\n\n";
+
+ OS << "namespace llvm {\n";
+ Enumeration(OS);
+ OS << "} // end namespace llvm\n\n";
+ OS << "#endif // GET_SUBTARGETINFO_ENUM\n\n";
+
+ OS << "\n#ifdef GET_SUBTARGETINFO_MC_DESC\n";
+ OS << "#undef GET_SUBTARGETINFO_MC_DESC\n\n";
+
+ OS << "namespace llvm {\n";
+#if 0
+ OS << "namespace {\n";
+#endif
+ unsigned NumFeatures = FeatureKeyValues(OS);
+ OS << "\n";
+ unsigned NumProcs = CPUKeyValues(OS);
+ OS << "\n";
+ EmitSchedModel(OS);
+ OS << "\n";
+#if 0
+ OS << "} // end anonymous namespace\n\n";
+#endif
+
+ // MCInstrInfo initialization routine.
+ OS << "static inline MCSubtargetInfo *create" << Target
+ << "MCSubtargetInfoImpl("
+ << "const Triple &TT, StringRef CPU, StringRef FS) {\n";
+ OS << " return new MCSubtargetInfo(TT, CPU, FS, ";
+ if (NumFeatures)
+ OS << Target << "FeatureKV, ";
+ else
+ OS << "None, ";
+ if (NumProcs)
+ OS << Target << "SubTypeKV, ";
+ else
+ OS << "None, ";
+ OS << '\n'; OS.indent(22);
+ OS << Target << "ProcSchedKV, "
+ << Target << "WriteProcResTable, "
+ << Target << "WriteLatencyTable, "
+ << Target << "ReadAdvanceTable, ";
+ OS << '\n'; OS.indent(22);
+ if (SchedModels.hasItineraries()) {
+ OS << Target << "Stages, "
+ << Target << "OperandCycles, "
+ << Target << "ForwardingPaths";
+ } else
+ OS << "nullptr, nullptr, nullptr";
+ OS << ");\n}\n\n";
+
+ OS << "} // end namespace llvm\n\n";
+
+ OS << "#endif // GET_SUBTARGETINFO_MC_DESC\n\n";
+
+ OS << "\n#ifdef GET_SUBTARGETINFO_TARGET_DESC\n";
+ OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n\n";
+
+ OS << "#include \"llvm/Support/Debug.h\"\n";
+ OS << "#include \"llvm/Support/raw_ostream.h\"\n\n";
+ ParseFeaturesFunction(OS, NumFeatures, NumProcs);
+
+ OS << "#endif // GET_SUBTARGETINFO_TARGET_DESC\n\n";
+
+ // Create a TargetSubtargetInfo subclass to hide the MC layer initialization.
+ OS << "\n#ifdef GET_SUBTARGETINFO_HEADER\n";
+ OS << "#undef GET_SUBTARGETINFO_HEADER\n\n";
+
+ std::string ClassName = Target + "GenSubtargetInfo";
+ OS << "namespace llvm {\n";
+ OS << "class DFAPacketizer;\n";
+ OS << "struct " << ClassName << " : public TargetSubtargetInfo {\n"
+ << " explicit " << ClassName << "(const Triple &TT, StringRef CPU, "
+ << "StringRef FS);\n"
+ << "public:\n"
+ << " unsigned resolveSchedClass(unsigned SchedClass, "
+ << " const MachineInstr *DefMI,"
+ << " const TargetSchedModel *SchedModel) const override;\n"
+ << " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
+ << " const;\n"
+ << "};\n";
+ OS << "} // end namespace llvm\n\n";
+
+ OS << "#endif // GET_SUBTARGETINFO_HEADER\n\n";
+
+ OS << "\n#ifdef GET_SUBTARGETINFO_CTOR\n";
+ OS << "#undef GET_SUBTARGETINFO_CTOR\n\n";
+
+ OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\n\n";
+ OS << "namespace llvm {\n";
+ OS << "extern const llvm::SubtargetFeatureKV " << Target << "FeatureKV[];\n";
+ OS << "extern const llvm::SubtargetFeatureKV " << Target << "SubTypeKV[];\n";
+ OS << "extern const llvm::SubtargetInfoKV " << Target << "ProcSchedKV[];\n";
+ OS << "extern const llvm::MCWriteProcResEntry "
+ << Target << "WriteProcResTable[];\n";
+ OS << "extern const llvm::MCWriteLatencyEntry "
+ << Target << "WriteLatencyTable[];\n";
+ OS << "extern const llvm::MCReadAdvanceEntry "
+ << Target << "ReadAdvanceTable[];\n";
+
+ if (SchedModels.hasItineraries()) {
+ OS << "extern const llvm::InstrStage " << Target << "Stages[];\n";
+ OS << "extern const unsigned " << Target << "OperandCycles[];\n";
+ OS << "extern const unsigned " << Target << "ForwardingPaths[];\n";
+ }
+
+ OS << ClassName << "::" << ClassName << "(const Triple &TT, StringRef CPU, "
+ << "StringRef FS)\n"
+ << " : TargetSubtargetInfo(TT, CPU, FS, ";
+ if (NumFeatures)
+ OS << "makeArrayRef(" << Target << "FeatureKV, " << NumFeatures << "), ";
+ else
+ OS << "None, ";
+ if (NumProcs)
+ OS << "makeArrayRef(" << Target << "SubTypeKV, " << NumProcs << "), ";
+ else
+ OS << "None, ";
+ OS << '\n'; OS.indent(24);
+ OS << Target << "ProcSchedKV, "
+ << Target << "WriteProcResTable, "
+ << Target << "WriteLatencyTable, "
+ << Target << "ReadAdvanceTable, ";
+ OS << '\n'; OS.indent(24);
+ if (SchedModels.hasItineraries()) {
+ OS << Target << "Stages, "
+ << Target << "OperandCycles, "
+ << Target << "ForwardingPaths";
+ } else
+ OS << "nullptr, nullptr, nullptr";
+ OS << ") {}\n\n";
+
+ EmitSchedModelHelpers(ClassName, OS);
+
+ OS << "} // end namespace llvm\n\n";
+
+ OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
+}
+
+namespace llvm {
+
+void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
+ CodeGenTarget CGTarget(RK);
+ SubtargetEmitter(RK, CGTarget).run(OS);
+}
+
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.cpp b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
new file mode 100644
index 000000000000..72a556182b1d
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.cpp
@@ -0,0 +1,133 @@
+//===- SubtargetFeatureInfo.cpp - Helpers for subtarget features ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SubtargetFeatureInfo.h"
+
+#include "Types.h"
+#include "llvm/TableGen/Record.h"
+
+#include <map>
+
+using namespace llvm;
+
+#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
+LLVM_DUMP_METHOD void SubtargetFeatureInfo::dump() const {
+ errs() << getEnumName() << " " << Index << "\n" << *TheDef;
+}
+#endif
+
+std::vector<std::pair<Record *, SubtargetFeatureInfo>>
+SubtargetFeatureInfo::getAll(const RecordKeeper &Records) {
+ std::vector<std::pair<Record *, SubtargetFeatureInfo>> SubtargetFeatures;
+ std::vector<Record *> AllPredicates =
+ Records.getAllDerivedDefinitions("Predicate");
+ for (Record *Pred : AllPredicates) {
+ // Ignore predicates that are not intended for the assembler.
+ //
+ // The "AssemblerMatcherPredicate" string should be promoted to an argument
+ // if we re-use the machinery for non-assembler purposes in future.
+ if (!Pred->getValueAsBit("AssemblerMatcherPredicate"))
+ continue;
+
+ if (Pred->getName().empty())
+ PrintFatalError(Pred->getLoc(), "Predicate has no name!");
+
+ SubtargetFeatures.emplace_back(
+ Pred, SubtargetFeatureInfo(Pred, SubtargetFeatures.size()));
+ }
+ return SubtargetFeatures;
+}
+
+void SubtargetFeatureInfo::emitSubtargetFeatureFlagEnumeration(
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
+ raw_ostream &OS) {
+ OS << "// Flags for subtarget features that participate in "
+ << "instruction matching.\n";
+ OS << "enum SubtargetFeatureFlag : "
+ << getMinimalTypeForEnumBitfield(SubtargetFeatures.size()) << " {\n";
+ for (const auto &SF : SubtargetFeatures) {
+ const SubtargetFeatureInfo &SFI = SF.second;
+ OS << " " << SFI.getEnumName() << " = (1ULL << " << SFI.Index << "),\n";
+ }
+ OS << " Feature_None = 0\n";
+ OS << "};\n\n";
+}
+
+void SubtargetFeatureInfo::emitNameTable(
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
+ raw_ostream &OS) {
+ // Need to sort the name table so that lookup by the log of the enum value
+ // gives the proper name. More specifically, for a feature of value 1<<n,
+ // SubtargetFeatureNames[n] should be the name of the feature.
+ uint64_t IndexUB = 0;
+ for (const auto &SF : SubtargetFeatures)
+ if (IndexUB <= SF.second.Index)
+ IndexUB = SF.second.Index+1;
+
+ std::vector<std::string> Names;
+ if (IndexUB > 0)
+ Names.resize(IndexUB);
+ for (const auto &SF : SubtargetFeatures)
+ Names[SF.second.Index] = SF.second.getEnumName();
+
+ OS << "static const char *SubtargetFeatureNames[] = {\n";
+ for (uint64_t I = 0; I < IndexUB; ++I)
+ OS << " \"" << Names[I] << "\",\n";
+
+ // A small number of targets have no predicates. Null terminate the array to
+ // avoid a zero-length array.
+ OS << " nullptr\n"
+ << "};\n\n";
+}
+
+void SubtargetFeatureInfo::emitComputeAvailableFeatures(
+ StringRef TargetName, StringRef ClassName, StringRef FuncName,
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID> &SubtargetFeatures,
+ raw_ostream &OS) {
+ OS << "uint64_t " << TargetName << ClassName << "::\n"
+ << FuncName << "(const FeatureBitset& FB) const {\n";
+ OS << " uint64_t Features = 0;\n";
+ for (const auto &SF : SubtargetFeatures) {
+ const SubtargetFeatureInfo &SFI = SF.second;
+
+ OS << " if (";
+ std::string CondStorage =
+ SFI.TheDef->getValueAsString("AssemblerCondString");
+ StringRef Conds = CondStorage;
+ std::pair<StringRef, StringRef> Comma = Conds.split(',');
+ bool First = true;
+ do {
+ if (!First)
+ OS << " && ";
+
+ bool Neg = false;
+ StringRef Cond = Comma.first;
+ if (Cond[0] == '!') {
+ Neg = true;
+ Cond = Cond.substr(1);
+ }
+
+ OS << "(";
+ if (Neg)
+ OS << "!";
+ OS << "FB[" << TargetName << "::" << Cond << "])";
+
+ if (Comma.second.empty())
+ break;
+
+ First = false;
+ Comma = Comma.second.split(',');
+ } while (true);
+
+ OS << ")\n";
+ OS << " Features |= " << SFI.getEnumName() << ";\n";
+ }
+ OS << " return Features;\n";
+ OS << "}\n\n";
+}
diff --git a/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.h b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.h
new file mode 100644
index 000000000000..99f380f2a1d7
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/SubtargetFeatureInfo.h
@@ -0,0 +1,72 @@
+//===- SubtargetFeatureInfo.h - Helpers for subtarget features ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H
+#define LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H
+
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+namespace llvm {
+class Record;
+class RecordKeeper;
+
+/// Helper class for storing information on a subtarget feature which
+/// participates in instruction matching.
+struct SubtargetFeatureInfo {
+ /// \brief The predicate record for this feature.
+ Record *TheDef;
+
+ /// \brief An unique index assigned to represent this feature.
+ uint64_t Index;
+
+ SubtargetFeatureInfo(Record *D, uint64_t Idx) : TheDef(D), Index(Idx) {}
+
+ /// \brief The name of the enumerated constant identifying this feature.
+ std::string getEnumName() const {
+ return "Feature_" + TheDef->getName().str();
+ }
+
+ void dump() const;
+ static std::vector<std::pair<Record *, SubtargetFeatureInfo>>
+ getAll(const RecordKeeper &Records);
+
+ /// Emit the subtarget feature flag definitions.
+ static void emitSubtargetFeatureFlagEnumeration(
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
+ &SubtargetFeatures,
+ raw_ostream &OS);
+
+ static void emitNameTable(std::map<Record *, SubtargetFeatureInfo,
+ LessRecordByID> &SubtargetFeatures,
+ raw_ostream &OS);
+
+ /// Emit the function to compute the list of available features given a
+ /// subtarget.
+ ///
+ /// \param TargetName The name of the target as used in class prefixes (e.g.
+ /// <TargetName>Subtarget)
+ /// \param ClassName The name of the class (without the <Target> prefix)
+ /// that will contain the generated functions.
+ /// \param FuncName The name of the function to emit.
+ /// \param SubtargetFeatures A map of TableGen records to the
+ /// SubtargetFeatureInfo equivalent.
+ static void emitComputeAvailableFeatures(
+ StringRef TargetName, StringRef ClassName, StringRef FuncName,
+ std::map<Record *, SubtargetFeatureInfo, LessRecordByID>
+ &SubtargetFeatures,
+ raw_ostream &OS);
+};
+} // end namespace llvm
+
+#endif // LLVM_UTIL_TABLEGEN_SUBTARGETFEATUREINFO_H
diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp
new file mode 100644
index 000000000000..00d20f1df6c2
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/TableGen.cpp
@@ -0,0 +1,222 @@
+//===- TableGen.cpp - Top-Level TableGen implementation for LLVM ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the main function for LLVM's TableGen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TableGenBackends.h" // Declares all backends.
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Main.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/SetTheory.h"
+
+using namespace llvm;
+
+enum ActionType {
+ PrintRecords,
+ GenEmitter,
+ GenRegisterInfo,
+ GenInstrInfo,
+ GenAsmWriter,
+ GenAsmMatcher,
+ GenDisassembler,
+ GenPseudoLowering,
+ GenCallingConv,
+ GenDAGISel,
+ GenDFAPacketizer,
+ GenFastISel,
+ GenSubtarget,
+ GenIntrinsic,
+ GenTgtIntrinsic,
+ PrintEnums,
+ PrintSets,
+ GenOptParserDefs,
+ GenCTags,
+ GenAttributes,
+ GenSearchableTables,
+ GenGlobalISel,
+ GenX86EVEX2VEXTables,
+ GenRegisterBank,
+};
+
+namespace {
+ cl::opt<ActionType>
+ Action(cl::desc("Action to perform:"),
+ cl::values(clEnumValN(PrintRecords, "print-records",
+ "Print all records to stdout (default)"),
+ clEnumValN(GenEmitter, "gen-emitter",
+ "Generate machine code emitter"),
+ clEnumValN(GenRegisterInfo, "gen-register-info",
+ "Generate registers and register classes info"),
+ clEnumValN(GenInstrInfo, "gen-instr-info",
+ "Generate instruction descriptions"),
+ clEnumValN(GenCallingConv, "gen-callingconv",
+ "Generate calling convention descriptions"),
+ clEnumValN(GenAsmWriter, "gen-asm-writer",
+ "Generate assembly writer"),
+ clEnumValN(GenDisassembler, "gen-disassembler",
+ "Generate disassembler"),
+ clEnumValN(GenPseudoLowering, "gen-pseudo-lowering",
+ "Generate pseudo instruction lowering"),
+ clEnumValN(GenAsmMatcher, "gen-asm-matcher",
+ "Generate assembly instruction matcher"),
+ clEnumValN(GenDAGISel, "gen-dag-isel",
+ "Generate a DAG instruction selector"),
+ clEnumValN(GenDFAPacketizer, "gen-dfa-packetizer",
+ "Generate DFA Packetizer for VLIW targets"),
+ clEnumValN(GenFastISel, "gen-fast-isel",
+ "Generate a \"fast\" instruction selector"),
+ clEnumValN(GenSubtarget, "gen-subtarget",
+ "Generate subtarget enumerations"),
+ clEnumValN(GenIntrinsic, "gen-intrinsic",
+ "Generate intrinsic information"),
+ clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic",
+ "Generate target intrinsic information"),
+ clEnumValN(PrintEnums, "print-enums",
+ "Print enum values for a class"),
+ clEnumValN(PrintSets, "print-sets",
+ "Print expanded sets for testing DAG exprs"),
+ clEnumValN(GenOptParserDefs, "gen-opt-parser-defs",
+ "Generate option definitions"),
+ clEnumValN(GenCTags, "gen-ctags",
+ "Generate ctags-compatible index"),
+ clEnumValN(GenAttributes, "gen-attrs",
+ "Generate attributes"),
+ clEnumValN(GenSearchableTables, "gen-searchable-tables",
+ "Generate generic binary-searchable table"),
+ clEnumValN(GenGlobalISel, "gen-global-isel",
+ "Generate GlobalISel selector"),
+ clEnumValN(GenX86EVEX2VEXTables, "gen-x86-EVEX2VEX-tables",
+ "Generate X86 EVEX to VEX compress tables"),
+ clEnumValN(GenRegisterBank, "gen-register-bank",
+ "Generate registers bank descriptions")));
+
+ cl::OptionCategory PrintEnumsCat("Options for -print-enums");
+ cl::opt<std::string>
+ Class("class", cl::desc("Print Enum list for this class"),
+ cl::value_desc("class name"), cl::cat(PrintEnumsCat));
+
+bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
+ switch (Action) {
+ case PrintRecords:
+ OS << Records; // No argument, dump all contents
+ break;
+ case GenEmitter:
+ EmitCodeEmitter(Records, OS);
+ break;
+ case GenRegisterInfo:
+ EmitRegisterInfo(Records, OS);
+ break;
+ case GenInstrInfo:
+ EmitInstrInfo(Records, OS);
+ break;
+ case GenCallingConv:
+ EmitCallingConv(Records, OS);
+ break;
+ case GenAsmWriter:
+ EmitAsmWriter(Records, OS);
+ break;
+ case GenAsmMatcher:
+ EmitAsmMatcher(Records, OS);
+ break;
+ case GenDisassembler:
+ EmitDisassembler(Records, OS);
+ break;
+ case GenPseudoLowering:
+ EmitPseudoLowering(Records, OS);
+ break;
+ case GenDAGISel:
+ EmitDAGISel(Records, OS);
+ break;
+ case GenDFAPacketizer:
+ EmitDFAPacketizer(Records, OS);
+ break;
+ case GenFastISel:
+ EmitFastISel(Records, OS);
+ break;
+ case GenSubtarget:
+ EmitSubtarget(Records, OS);
+ break;
+ case GenIntrinsic:
+ EmitIntrinsics(Records, OS);
+ break;
+ case GenTgtIntrinsic:
+ EmitIntrinsics(Records, OS, true);
+ break;
+ case GenOptParserDefs:
+ EmitOptParser(Records, OS);
+ break;
+ case PrintEnums:
+ {
+ for (Record *Rec : Records.getAllDerivedDefinitions(Class))
+ OS << Rec->getName() << ", ";
+ OS << "\n";
+ break;
+ }
+ case PrintSets:
+ {
+ SetTheory Sets;
+ Sets.addFieldExpander("Set", "Elements");
+ for (Record *Rec : Records.getAllDerivedDefinitions("Set")) {
+ OS << Rec->getName() << " = [";
+ const std::vector<Record*> *Elts = Sets.expand(Rec);
+ assert(Elts && "Couldn't expand Set instance");
+ for (Record *Elt : *Elts)
+ OS << ' ' << Elt->getName();
+ OS << " ]\n";
+ }
+ break;
+ }
+ case GenCTags:
+ EmitCTags(Records, OS);
+ break;
+ case GenAttributes:
+ EmitAttributes(Records, OS);
+ break;
+ case GenSearchableTables:
+ EmitSearchableTables(Records, OS);
+ break;
+ case GenGlobalISel:
+ EmitGlobalISel(Records, OS);
+ break;
+ case GenRegisterBank:
+ EmitRegisterBank(Records, OS);
+ break;
+ case GenX86EVEX2VEXTables:
+ EmitX86EVEX2VEXTables(Records, OS);
+ break;
+ }
+
+ return false;
+}
+}
+
+int main(int argc, char **argv) {
+ sys::PrintStackTraceOnErrorSignal(argv[0]);
+ PrettyStackTraceProgram X(argc, argv);
+ cl::ParseCommandLineOptions(argc, argv);
+
+ llvm_shutdown_obj Y;
+
+ return TableGenMain(argv[0], &LLVMTableGenMain);
+}
+
+#ifdef __has_feature
+#if __has_feature(address_sanitizer)
+#include <sanitizer/lsan_interface.h>
+// Disable LeakSanitizer for this binary as it has too many leaks that are not
+// very interesting to fix. See compiler-rt/include/sanitizer/lsan_interface.h .
+int __lsan_is_turned_off() { return 1; }
+#endif // __has_feature(address_sanitizer)
+#endif // defined(__has_feature)
diff --git a/contrib/llvm/utils/TableGen/TableGenBackends.h b/contrib/llvm/utils/TableGen/TableGenBackends.h
new file mode 100644
index 000000000000..2512997e27f9
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/TableGenBackends.h
@@ -0,0 +1,89 @@
+//===- TableGenBackends.h - Declarations for LLVM TableGen Backends -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declarations for all of the LLVM TableGen
+// backends. A "TableGen backend" is just a function. See below for a
+// precise description.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H
+#define LLVM_UTILS_TABLEGEN_TABLEGENBACKENDS_H
+
+// A TableGen backend is a function that looks like
+//
+// EmitFoo(RecordKeeper &RK, raw_ostream &OS /*, anything else you need */ )
+//
+// What you do inside of that function is up to you, but it will usually
+// involve generating C++ code to the provided raw_ostream.
+//
+// The RecordKeeper is just a top-level container for an in-memory
+// representation of the data encoded in the TableGen file. What a TableGen
+// backend does is walk around that in-memory representation and generate
+// stuff based on the information it contains.
+//
+// The in-memory representation is a node-graph (think of it like JSON but
+// with a richer ontology of types), where the nodes are subclasses of
+// Record. The methods `getClass`, `getDef` are the basic interface to
+// access the node-graph. RecordKeeper also provides a handy method
+// `getAllDerivedDefinitions`. Consult "include/llvm/TableGen/Record.h" for
+// the exact interfaces provided by Record's and RecordKeeper.
+//
+// A common pattern for TableGen backends is for the EmitFoo function to
+// instantiate a class which holds some context for the generation process,
+// and then have most of the work happen in that class's methods. This
+// pattern partly has historical roots in the previous TableGen backend API
+// that involved a class and an invocation like `FooEmitter(RK).run(OS)`.
+//
+// Remember to wrap private things in an anonymous namespace. For most
+// backends, this means that the EmitFoo function is the only thing not in
+// the anonymous namespace.
+
+
+// FIXME: Reorganize TableGen so that build dependencies can be more
+// accurately expressed. Currently, touching any of the emitters (or
+// anything that they transitively depend on) causes everything dependent
+// on TableGen to be rebuilt (this includes all the targets!). Perhaps have
+// a standalone TableGen binary and have the backends be loadable modules
+// of some sort; then the dependency could be expressed as being on the
+// module, and all the modules would have a common dependency on the
+// TableGen binary with as few dependencies as possible on the rest of
+// LLVM.
+
+
+namespace llvm {
+
+class raw_ostream;
+class RecordKeeper;
+
+void EmitIntrinsics(RecordKeeper &RK, raw_ostream &OS, bool TargetOnly = false);
+void EmitAsmMatcher(RecordKeeper &RK, raw_ostream &OS);
+void EmitAsmWriter(RecordKeeper &RK, raw_ostream &OS);
+void EmitCallingConv(RecordKeeper &RK, raw_ostream &OS);
+void EmitCodeEmitter(RecordKeeper &RK, raw_ostream &OS);
+void EmitDAGISel(RecordKeeper &RK, raw_ostream &OS);
+void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS);
+void EmitDisassembler(RecordKeeper &RK, raw_ostream &OS);
+void EmitFastISel(RecordKeeper &RK, raw_ostream &OS);
+void EmitInstrInfo(RecordKeeper &RK, raw_ostream &OS);
+void EmitPseudoLowering(RecordKeeper &RK, raw_ostream &OS);
+void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS);
+void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS);
+void EmitMapTable(RecordKeeper &RK, raw_ostream &OS);
+void EmitOptParser(RecordKeeper &RK, raw_ostream &OS);
+void EmitCTags(RecordKeeper &RK, raw_ostream &OS);
+void EmitAttributes(RecordKeeper &RK, raw_ostream &OS);
+void EmitSearchableTables(RecordKeeper &RK, raw_ostream &OS);
+void EmitGlobalISel(RecordKeeper &RK, raw_ostream &OS);
+void EmitX86EVEX2VEXTables(RecordKeeper &RK, raw_ostream &OS);
+void EmitRegisterBank(RecordKeeper &RK, raw_ostream &OS);
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/Types.cpp b/contrib/llvm/utils/TableGen/Types.cpp
new file mode 100644
index 000000000000..35458296f8fd
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/Types.cpp
@@ -0,0 +1,44 @@
+//===- Types.cpp - Helper for the selection of C++ data types. ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Types.h"
+
+// For LLVM_ATTRIBUTE_UNUSED
+#include "llvm/Support/Compiler.h"
+
+#include <cassert>
+
+using namespace llvm;
+
+const char *llvm::getMinimalTypeForRange(uint64_t Range, unsigned MaxSize LLVM_ATTRIBUTE_UNUSED) {
+ // TODO: The original callers only used 32 and 64 so these are the only
+ // values permitted. Rather than widen the supported values we should
+ // allow 64 for the callers that currently use 32 and remove the
+ // argument altogether.
+ assert((MaxSize == 32 || MaxSize == 64) && "Unexpected size");
+ assert(MaxSize <= 64 && "Unexpected size");
+ assert(((MaxSize > 32) ? Range <= 0xFFFFFFFFFFFFFFFFULL
+ : Range <= 0xFFFFFFFFULL) &&
+ "Enum too large");
+
+ if (Range > 0xFFFFFFFFULL)
+ return "uint64_t";
+ if (Range > 0xFFFF)
+ return "uint32_t";
+ if (Range > 0xFF)
+ return "uint16_t";
+ return "uint8_t";
+}
+
+const char *llvm::getMinimalTypeForEnumBitfield(uint64_t Size) {
+ uint64_t MaxIndex = Size;
+ if (MaxIndex > 0)
+ MaxIndex--;
+ return getMinimalTypeForRange(1ULL << MaxIndex);
+}
diff --git a/contrib/llvm/utils/TableGen/Types.h b/contrib/llvm/utils/TableGen/Types.h
new file mode 100644
index 000000000000..d511b7eae6e8
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/Types.h
@@ -0,0 +1,25 @@
+//===- Types.h - Helper for the selection of C++ types. ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_TYPES_H
+#define LLVM_UTILS_TABLEGEN_TYPES_H
+
+#include <cstdint>
+
+namespace llvm {
+/// Returns the smallest unsigned integer type that can hold the given range.
+/// MaxSize indicates the largest size of integer to consider (in bits) and only
+/// supports values of at least 32.
+const char *getMinimalTypeForRange(uint64_t Range, unsigned MaxSize = 64);
+
+/// Returns the smallest unsigned integer type that can hold the given bitfield.
+const char *getMinimalTypeForEnumBitfield(uint64_t Size);
+}
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerShared.h b/contrib/llvm/utils/TableGen/X86DisassemblerShared.h
new file mode 100644
index 000000000000..e5889e92415d
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86DisassemblerShared.h
@@ -0,0 +1,54 @@
+//===- X86DisassemblerShared.h - Emitter shared header ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H
+#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERSHARED_H
+
+#include <cstring>
+#include <string>
+
+#include "../../lib/Target/X86/Disassembler/X86DisassemblerDecoderCommon.h"
+
+struct InstructionSpecifier {
+ llvm::X86Disassembler::OperandSpecifier
+ operands[llvm::X86Disassembler::X86_MAX_OPERANDS];
+ llvm::X86Disassembler::InstructionContext insnContext;
+ std::string name;
+
+ InstructionSpecifier() {
+ insnContext = llvm::X86Disassembler::IC;
+ name = "";
+ memset(operands, 0, sizeof(operands));
+ }
+};
+
+/// Specifies whether a ModR/M byte is needed and (if so) which
+/// instruction each possible value of the ModR/M byte corresponds to. Once
+/// this information is known, we have narrowed down to a single instruction.
+struct ModRMDecision {
+ uint8_t modrm_type;
+ llvm::X86Disassembler::InstrUID instructionIDs[256];
+};
+
+/// Specifies which set of ModR/M->instruction tables to look at
+/// given a particular opcode.
+struct OpcodeDecision {
+ ModRMDecision modRMDecisions[256];
+};
+
+/// Specifies which opcode->instruction tables to look at given
+/// a particular context (set of attributes). Since there are many possible
+/// contexts, the decoder first uses CONTEXTS_SYM to determine which context
+/// applies given a specific set of attributes. Hence there are only IC_max
+/// entries in this table, rather than 2^(ATTR_max).
+struct ContextDecision {
+ OpcodeDecision opcodeDecisions[llvm::X86Disassembler::IC_max];
+};
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp
new file mode 100644
index 000000000000..c9e36f96736a
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp
@@ -0,0 +1,929 @@
+//===- X86DisassemblerTables.cpp - Disassembler tables ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the X86 Disassembler Emitter.
+// It contains the implementation of the disassembler tables.
+// Documentation for the disassembler emitter in general can be found in
+// X86DisasemblerEmitter.h.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86DisassemblerTables.h"
+#include "X86DisassemblerShared.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include <map>
+
+using namespace llvm;
+using namespace X86Disassembler;
+
+/// stringForContext - Returns a string containing the name of a particular
+/// InstructionContext, usually for diagnostic purposes.
+///
+/// @param insnContext - The instruction class to transform to a string.
+/// @return - A statically-allocated string constant that contains the
+/// name of the instruction class.
+static inline const char* stringForContext(InstructionContext insnContext) {
+ switch (insnContext) {
+ default:
+ llvm_unreachable("Unhandled instruction class");
+#define ENUM_ENTRY(n, r, d) case n: return #n; break;
+#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) ENUM_ENTRY(n##_K_B, r, d)\
+ ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)\
+ ENUM_ENTRY(n##_KZ_B, r, d)
+ INSTRUCTION_CONTEXTS
+#undef ENUM_ENTRY
+#undef ENUM_ENTRY_K_B
+ }
+}
+
+/// stringForOperandType - Like stringForContext, but for OperandTypes.
+static inline const char* stringForOperandType(OperandType type) {
+ switch (type) {
+ default:
+ llvm_unreachable("Unhandled type");
+#define ENUM_ENTRY(i, d) case i: return #i;
+ TYPES
+#undef ENUM_ENTRY
+ }
+}
+
+/// stringForOperandEncoding - like stringForContext, but for
+/// OperandEncodings.
+static inline const char* stringForOperandEncoding(OperandEncoding encoding) {
+ switch (encoding) {
+ default:
+ llvm_unreachable("Unhandled encoding");
+#define ENUM_ENTRY(i, d) case i: return #i;
+ ENCODINGS
+#undef ENUM_ENTRY
+ }
+}
+
+/// inheritsFrom - Indicates whether all instructions in one class also belong
+/// to another class.
+///
+/// @param child - The class that may be the subset
+/// @param parent - The class that may be the superset
+/// @return - True if child is a subset of parent, false otherwise.
+static inline bool inheritsFrom(InstructionContext child,
+ InstructionContext parent,
+ bool VEX_LIG = false, bool AdSize64 = false) {
+ if (child == parent)
+ return true;
+
+ switch (parent) {
+ case IC:
+ return(inheritsFrom(child, IC_64BIT, AdSize64) ||
+ inheritsFrom(child, IC_OPSIZE) ||
+ inheritsFrom(child, IC_ADSIZE) ||
+ inheritsFrom(child, IC_XD) ||
+ inheritsFrom(child, IC_XS));
+ case IC_64BIT:
+ return(inheritsFrom(child, IC_64BIT_REXW) ||
+ inheritsFrom(child, IC_64BIT_OPSIZE) ||
+ (!AdSize64 && inheritsFrom(child, IC_64BIT_ADSIZE)) ||
+ inheritsFrom(child, IC_64BIT_XD) ||
+ inheritsFrom(child, IC_64BIT_XS));
+ case IC_OPSIZE:
+ return inheritsFrom(child, IC_64BIT_OPSIZE) ||
+ inheritsFrom(child, IC_OPSIZE_ADSIZE);
+ case IC_ADSIZE:
+ return inheritsFrom(child, IC_OPSIZE_ADSIZE);
+ case IC_OPSIZE_ADSIZE:
+ return false;
+ case IC_64BIT_ADSIZE:
+ return inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE);
+ case IC_64BIT_OPSIZE_ADSIZE:
+ return false;
+ case IC_XD:
+ return inheritsFrom(child, IC_64BIT_XD);
+ case IC_XS:
+ return inheritsFrom(child, IC_64BIT_XS);
+ case IC_XD_OPSIZE:
+ return inheritsFrom(child, IC_64BIT_XD_OPSIZE);
+ case IC_XS_OPSIZE:
+ return inheritsFrom(child, IC_64BIT_XS_OPSIZE);
+ case IC_64BIT_REXW:
+ return(inheritsFrom(child, IC_64BIT_REXW_XS) ||
+ inheritsFrom(child, IC_64BIT_REXW_XD) ||
+ inheritsFrom(child, IC_64BIT_REXW_OPSIZE) ||
+ (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE)));
+ case IC_64BIT_OPSIZE:
+ return inheritsFrom(child, IC_64BIT_REXW_OPSIZE) ||
+ (!AdSize64 && inheritsFrom(child, IC_64BIT_OPSIZE_ADSIZE)) ||
+ (!AdSize64 && inheritsFrom(child, IC_64BIT_REXW_ADSIZE));
+ case IC_64BIT_XD:
+ return(inheritsFrom(child, IC_64BIT_REXW_XD));
+ case IC_64BIT_XS:
+ return(inheritsFrom(child, IC_64BIT_REXW_XS));
+ case IC_64BIT_XD_OPSIZE:
+ case IC_64BIT_XS_OPSIZE:
+ return false;
+ case IC_64BIT_REXW_XD:
+ case IC_64BIT_REXW_XS:
+ case IC_64BIT_REXW_OPSIZE:
+ case IC_64BIT_REXW_ADSIZE:
+ return false;
+ case IC_VEX:
+ return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W)) ||
+ inheritsFrom(child, IC_VEX_W) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L));
+ case IC_VEX_XS:
+ return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XS)) ||
+ inheritsFrom(child, IC_VEX_W_XS) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_XS));
+ case IC_VEX_XD:
+ return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XD)) ||
+ inheritsFrom(child, IC_VEX_W_XD) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_XD));
+ case IC_VEX_OPSIZE:
+ return (VEX_LIG && inheritsFrom(child, IC_VEX_L_W_OPSIZE)) ||
+ inheritsFrom(child, IC_VEX_W_OPSIZE) ||
+ (VEX_LIG && inheritsFrom(child, IC_VEX_L_OPSIZE));
+ case IC_VEX_W:
+ return VEX_LIG && inheritsFrom(child, IC_VEX_L_W);
+ case IC_VEX_W_XS:
+ return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XS);
+ case IC_VEX_W_XD:
+ return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_XD);
+ case IC_VEX_W_OPSIZE:
+ return VEX_LIG && inheritsFrom(child, IC_VEX_L_W_OPSIZE);
+ case IC_VEX_L:
+ return inheritsFrom(child, IC_VEX_L_W);
+ case IC_VEX_L_XS:
+ return inheritsFrom(child, IC_VEX_L_W_XS);
+ case IC_VEX_L_XD:
+ return inheritsFrom(child, IC_VEX_L_W_XD);
+ case IC_VEX_L_OPSIZE:
+ return inheritsFrom(child, IC_VEX_L_W_OPSIZE);
+ case IC_VEX_L_W:
+ case IC_VEX_L_W_XS:
+ case IC_VEX_L_W_XD:
+ case IC_VEX_L_W_OPSIZE:
+ return false;
+ case IC_EVEX:
+ return inheritsFrom(child, IC_EVEX_W) ||
+ inheritsFrom(child, IC_EVEX_L_W);
+ case IC_EVEX_XS:
+ return inheritsFrom(child, IC_EVEX_W_XS) ||
+ inheritsFrom(child, IC_EVEX_L_W_XS);
+ case IC_EVEX_XD:
+ return inheritsFrom(child, IC_EVEX_W_XD) ||
+ inheritsFrom(child, IC_EVEX_L_W_XD);
+ case IC_EVEX_OPSIZE:
+ return inheritsFrom(child, IC_EVEX_W_OPSIZE) ||
+ inheritsFrom(child, IC_EVEX_L_W_OPSIZE);
+ case IC_EVEX_B:
+ return false;
+ case IC_EVEX_W:
+ case IC_EVEX_W_XS:
+ case IC_EVEX_W_XD:
+ case IC_EVEX_W_OPSIZE:
+ return false;
+ case IC_EVEX_L:
+ case IC_EVEX_L_K_B:
+ case IC_EVEX_L_KZ_B:
+ case IC_EVEX_L_B:
+ case IC_EVEX_L_XS:
+ case IC_EVEX_L_XD:
+ case IC_EVEX_L_OPSIZE:
+ return false;
+ case IC_EVEX_L_W:
+ case IC_EVEX_L_W_XS:
+ case IC_EVEX_L_W_XD:
+ case IC_EVEX_L_W_OPSIZE:
+ return false;
+ case IC_EVEX_L2:
+ case IC_EVEX_L2_XS:
+ case IC_EVEX_L2_XD:
+ case IC_EVEX_L2_OPSIZE:
+ return false;
+ case IC_EVEX_L2_W:
+ case IC_EVEX_L2_W_XS:
+ case IC_EVEX_L2_W_XD:
+ case IC_EVEX_L2_W_OPSIZE:
+ return false;
+ case IC_EVEX_K:
+ return inheritsFrom(child, IC_EVEX_W_K) ||
+ inheritsFrom(child, IC_EVEX_L_W_K);
+ case IC_EVEX_XS_K:
+ case IC_EVEX_XS_K_B:
+ case IC_EVEX_XS_KZ_B:
+ return inheritsFrom(child, IC_EVEX_W_XS_K) ||
+ inheritsFrom(child, IC_EVEX_L_W_XS_K);
+ case IC_EVEX_XD_K:
+ case IC_EVEX_XD_K_B:
+ case IC_EVEX_XD_KZ_B:
+ return inheritsFrom(child, IC_EVEX_W_XD_K) ||
+ inheritsFrom(child, IC_EVEX_L_W_XD_K);
+ case IC_EVEX_XS_B:
+ case IC_EVEX_XD_B:
+ case IC_EVEX_K_B:
+ case IC_EVEX_KZ:
+ return false;
+ case IC_EVEX_XS_KZ:
+ return inheritsFrom(child, IC_EVEX_W_XS_KZ) ||
+ inheritsFrom(child, IC_EVEX_L_W_XS_KZ);
+ case IC_EVEX_XD_KZ:
+ return inheritsFrom(child, IC_EVEX_W_XD_KZ) ||
+ inheritsFrom(child, IC_EVEX_L_W_XD_KZ);
+ case IC_EVEX_KZ_B:
+ case IC_EVEX_OPSIZE_K:
+ case IC_EVEX_OPSIZE_B:
+ case IC_EVEX_OPSIZE_K_B:
+ case IC_EVEX_OPSIZE_KZ:
+ case IC_EVEX_OPSIZE_KZ_B:
+ return false;
+ case IC_EVEX_W_K:
+ case IC_EVEX_W_B:
+ case IC_EVEX_W_K_B:
+ case IC_EVEX_W_KZ_B:
+ case IC_EVEX_W_XS_K:
+ case IC_EVEX_W_XD_K:
+ case IC_EVEX_W_OPSIZE_K:
+ case IC_EVEX_W_OPSIZE_B:
+ case IC_EVEX_W_OPSIZE_K_B:
+ return false;
+ case IC_EVEX_L_K:
+ case IC_EVEX_L_XS_K:
+ case IC_EVEX_L_XD_K:
+ case IC_EVEX_L_XD_B:
+ case IC_EVEX_L_XD_K_B:
+ case IC_EVEX_L_OPSIZE_K:
+ case IC_EVEX_L_OPSIZE_B:
+ case IC_EVEX_L_OPSIZE_K_B:
+ return false;
+ case IC_EVEX_W_KZ:
+ case IC_EVEX_W_XS_KZ:
+ case IC_EVEX_W_XD_KZ:
+ case IC_EVEX_W_XS_B:
+ case IC_EVEX_W_XD_B:
+ case IC_EVEX_W_XS_K_B:
+ case IC_EVEX_W_XD_K_B:
+ case IC_EVEX_W_XS_KZ_B:
+ case IC_EVEX_W_XD_KZ_B:
+ case IC_EVEX_W_OPSIZE_KZ:
+ case IC_EVEX_W_OPSIZE_KZ_B:
+ return false;
+ case IC_EVEX_L_KZ:
+ case IC_EVEX_L_XS_KZ:
+ case IC_EVEX_L_XS_B:
+ case IC_EVEX_L_XS_K_B:
+ case IC_EVEX_L_XS_KZ_B:
+ case IC_EVEX_L_XD_KZ:
+ case IC_EVEX_L_XD_KZ_B:
+ case IC_EVEX_L_OPSIZE_KZ:
+ case IC_EVEX_L_OPSIZE_KZ_B:
+ return false;
+ case IC_EVEX_L_W_K:
+ case IC_EVEX_L_W_B:
+ case IC_EVEX_L_W_K_B:
+ case IC_EVEX_L_W_XS_K:
+ case IC_EVEX_L_W_XS_B:
+ case IC_EVEX_L_W_XS_K_B:
+ case IC_EVEX_L_W_XS_KZ:
+ case IC_EVEX_L_W_XS_KZ_B:
+ case IC_EVEX_L_W_OPSIZE_K:
+ case IC_EVEX_L_W_OPSIZE_B:
+ case IC_EVEX_L_W_OPSIZE_K_B:
+ case IC_EVEX_L_W_KZ:
+ case IC_EVEX_L_W_KZ_B:
+ case IC_EVEX_L_W_XD_K:
+ case IC_EVEX_L_W_XD_B:
+ case IC_EVEX_L_W_XD_K_B:
+ case IC_EVEX_L_W_XD_KZ:
+ case IC_EVEX_L_W_XD_KZ_B:
+ case IC_EVEX_L_W_OPSIZE_KZ:
+ case IC_EVEX_L_W_OPSIZE_KZ_B:
+ return false;
+ case IC_EVEX_L2_K:
+ case IC_EVEX_L2_B:
+ case IC_EVEX_L2_K_B:
+ case IC_EVEX_L2_KZ_B:
+ case IC_EVEX_L2_XS_K:
+ case IC_EVEX_L2_XS_K_B:
+ case IC_EVEX_L2_XS_B:
+ case IC_EVEX_L2_XD_B:
+ case IC_EVEX_L2_XD_K:
+ case IC_EVEX_L2_XD_K_B:
+ case IC_EVEX_L2_OPSIZE_K:
+ case IC_EVEX_L2_OPSIZE_B:
+ case IC_EVEX_L2_OPSIZE_K_B:
+ case IC_EVEX_L2_KZ:
+ case IC_EVEX_L2_XS_KZ:
+ case IC_EVEX_L2_XS_KZ_B:
+ case IC_EVEX_L2_XD_KZ:
+ case IC_EVEX_L2_XD_KZ_B:
+ case IC_EVEX_L2_OPSIZE_KZ:
+ case IC_EVEX_L2_OPSIZE_KZ_B:
+ return false;
+ case IC_EVEX_L2_W_K:
+ case IC_EVEX_L2_W_B:
+ case IC_EVEX_L2_W_K_B:
+ case IC_EVEX_L2_W_KZ_B:
+ case IC_EVEX_L2_W_XS_K:
+ case IC_EVEX_L2_W_XS_B:
+ case IC_EVEX_L2_W_XS_K_B:
+ case IC_EVEX_L2_W_XD_K:
+ case IC_EVEX_L2_W_XD_B:
+ case IC_EVEX_L2_W_OPSIZE_K:
+ case IC_EVEX_L2_W_OPSIZE_B:
+ case IC_EVEX_L2_W_OPSIZE_K_B:
+ case IC_EVEX_L2_W_KZ:
+ case IC_EVEX_L2_W_XS_KZ:
+ case IC_EVEX_L2_W_XS_KZ_B:
+ case IC_EVEX_L2_W_XD_KZ:
+ case IC_EVEX_L2_W_XD_K_B:
+ case IC_EVEX_L2_W_XD_KZ_B:
+ case IC_EVEX_L2_W_OPSIZE_KZ:
+ case IC_EVEX_L2_W_OPSIZE_KZ_B:
+ return false;
+ default:
+ errs() << "Unknown instruction class: " <<
+ stringForContext((InstructionContext)parent) << "\n";
+ llvm_unreachable("Unknown instruction class");
+ }
+}
+
+/// outranks - Indicates whether, if an instruction has two different applicable
+/// classes, which class should be preferred when performing decode. This
+/// imposes a total ordering (ties are resolved toward "lower")
+///
+/// @param upper - The class that may be preferable
+/// @param lower - The class that may be less preferable
+/// @return - True if upper is to be preferred, false otherwise.
+static inline bool outranks(InstructionContext upper,
+ InstructionContext lower) {
+ assert(upper < IC_max);
+ assert(lower < IC_max);
+
+#define ENUM_ENTRY(n, r, d) r,
+#define ENUM_ENTRY_K_B(n, r, d) ENUM_ENTRY(n, r, d) \
+ ENUM_ENTRY(n##_K_B, r, d) ENUM_ENTRY(n##_KZ_B, r, d) \
+ ENUM_ENTRY(n##_KZ, r, d) ENUM_ENTRY(n##_K, r, d) ENUM_ENTRY(n##_B, r, d)
+ static int ranks[IC_max] = {
+ INSTRUCTION_CONTEXTS
+ };
+#undef ENUM_ENTRY
+#undef ENUM_ENTRY_K_B
+
+ return (ranks[upper] > ranks[lower]);
+}
+
+/// getDecisionType - Determines whether a ModRM decision with 255 entries can
+/// be compacted by eliminating redundant information.
+///
+/// @param decision - The decision to be compacted.
+/// @return - The compactest available representation for the decision.
+static ModRMDecisionType getDecisionType(ModRMDecision &decision) {
+ bool satisfiesOneEntry = true;
+ bool satisfiesSplitRM = true;
+ bool satisfiesSplitReg = true;
+ bool satisfiesSplitMisc = true;
+
+ for (unsigned index = 0; index < 256; ++index) {
+ if (decision.instructionIDs[index] != decision.instructionIDs[0])
+ satisfiesOneEntry = false;
+
+ if (((index & 0xc0) == 0xc0) &&
+ (decision.instructionIDs[index] != decision.instructionIDs[0xc0]))
+ satisfiesSplitRM = false;
+
+ if (((index & 0xc0) != 0xc0) &&
+ (decision.instructionIDs[index] != decision.instructionIDs[0x00]))
+ satisfiesSplitRM = false;
+
+ if (((index & 0xc0) == 0xc0) &&
+ (decision.instructionIDs[index] != decision.instructionIDs[index&0xf8]))
+ satisfiesSplitReg = false;
+
+ if (((index & 0xc0) != 0xc0) &&
+ (decision.instructionIDs[index] != decision.instructionIDs[index&0x38]))
+ satisfiesSplitMisc = false;
+ }
+
+ if (satisfiesOneEntry)
+ return MODRM_ONEENTRY;
+
+ if (satisfiesSplitRM)
+ return MODRM_SPLITRM;
+
+ if (satisfiesSplitReg && satisfiesSplitMisc)
+ return MODRM_SPLITREG;
+
+ if (satisfiesSplitMisc)
+ return MODRM_SPLITMISC;
+
+ return MODRM_FULL;
+}
+
+/// stringForDecisionType - Returns a statically-allocated string corresponding
+/// to a particular decision type.
+///
+/// @param dt - The decision type.
+/// @return - A pointer to the statically-allocated string (e.g.,
+/// "MODRM_ONEENTRY" for MODRM_ONEENTRY).
+static const char* stringForDecisionType(ModRMDecisionType dt) {
+#define ENUM_ENTRY(n) case n: return #n;
+ switch (dt) {
+ default:
+ llvm_unreachable("Unknown decision type");
+ MODRMTYPES
+ };
+#undef ENUM_ENTRY
+}
+
+DisassemblerTables::DisassemblerTables() {
+ unsigned i;
+
+ for (i = 0; i < array_lengthof(Tables); i++) {
+ Tables[i] = new ContextDecision;
+ memset(Tables[i], 0, sizeof(ContextDecision));
+ }
+
+ HasConflicts = false;
+}
+
+DisassemblerTables::~DisassemblerTables() {
+ unsigned i;
+
+ for (i = 0; i < array_lengthof(Tables); i++)
+ delete Tables[i];
+}
+
+void DisassemblerTables::emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2,
+ unsigned &ModRMTableNum,
+ ModRMDecision &decision) const {
+ static uint32_t sTableNumber = 0;
+ static uint32_t sEntryNumber = 1;
+ ModRMDecisionType dt = getDecisionType(decision);
+
+ if (dt == MODRM_ONEENTRY && decision.instructionIDs[0] == 0)
+ {
+ o2.indent(i2) << "{ /* ModRMDecision */" << "\n";
+ i2++;
+
+ o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
+ o2.indent(i2) << 0 << " /* EmptyTable */\n";
+
+ i2--;
+ o2.indent(i2) << "}";
+ return;
+ }
+
+ std::vector<unsigned> ModRMDecision;
+
+ switch (dt) {
+ default:
+ llvm_unreachable("Unknown decision type");
+ case MODRM_ONEENTRY:
+ ModRMDecision.push_back(decision.instructionIDs[0]);
+ break;
+ case MODRM_SPLITRM:
+ ModRMDecision.push_back(decision.instructionIDs[0x00]);
+ ModRMDecision.push_back(decision.instructionIDs[0xc0]);
+ break;
+ case MODRM_SPLITREG:
+ for (unsigned index = 0; index < 64; index += 8)
+ ModRMDecision.push_back(decision.instructionIDs[index]);
+ for (unsigned index = 0xc0; index < 256; index += 8)
+ ModRMDecision.push_back(decision.instructionIDs[index]);
+ break;
+ case MODRM_SPLITMISC:
+ for (unsigned index = 0; index < 64; index += 8)
+ ModRMDecision.push_back(decision.instructionIDs[index]);
+ for (unsigned index = 0xc0; index < 256; ++index)
+ ModRMDecision.push_back(decision.instructionIDs[index]);
+ break;
+ case MODRM_FULL:
+ for (unsigned index = 0; index < 256; ++index)
+ ModRMDecision.push_back(decision.instructionIDs[index]);
+ break;
+ }
+
+ unsigned &EntryNumber = ModRMTable[ModRMDecision];
+ if (EntryNumber == 0) {
+ EntryNumber = ModRMTableNum;
+
+ ModRMTableNum += ModRMDecision.size();
+ o1 << "/* Table" << EntryNumber << " */\n";
+ i1++;
+ for (std::vector<unsigned>::const_iterator I = ModRMDecision.begin(),
+ E = ModRMDecision.end(); I != E; ++I) {
+ o1.indent(i1 * 2) << format("0x%hx", *I) << ", /* "
+ << InstructionSpecifiers[*I].name << " */\n";
+ }
+ i1--;
+ }
+
+ o2.indent(i2) << "{ /* struct ModRMDecision */" << "\n";
+ i2++;
+
+ o2.indent(i2) << stringForDecisionType(dt) << "," << "\n";
+ o2.indent(i2) << EntryNumber << " /* Table" << EntryNumber << " */\n";
+
+ i2--;
+ o2.indent(i2) << "}";
+
+ switch (dt) {
+ default:
+ llvm_unreachable("Unknown decision type");
+ case MODRM_ONEENTRY:
+ sEntryNumber += 1;
+ break;
+ case MODRM_SPLITRM:
+ sEntryNumber += 2;
+ break;
+ case MODRM_SPLITREG:
+ sEntryNumber += 16;
+ break;
+ case MODRM_SPLITMISC:
+ sEntryNumber += 8 + 64;
+ break;
+ case MODRM_FULL:
+ sEntryNumber += 256;
+ break;
+ }
+
+ // We assume that the index can fit into uint16_t.
+ assert(sEntryNumber < 65536U &&
+ "Index into ModRMDecision is too large for uint16_t!");
+
+ ++sTableNumber;
+}
+
+void DisassemblerTables::emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2,
+ unsigned &ModRMTableNum,
+ OpcodeDecision &decision) const {
+ o2.indent(i2) << "{ /* struct OpcodeDecision */" << "\n";
+ i2++;
+ o2.indent(i2) << "{" << "\n";
+ i2++;
+
+ for (unsigned index = 0; index < 256; ++index) {
+ o2.indent(i2);
+
+ o2 << "/* 0x" << format("%02hhx", index) << " */" << "\n";
+
+ emitModRMDecision(o1, o2, i1, i2, ModRMTableNum,
+ decision.modRMDecisions[index]);
+
+ if (index < 255)
+ o2 << ",";
+
+ o2 << "\n";
+ }
+
+ i2--;
+ o2.indent(i2) << "}" << "\n";
+ i2--;
+ o2.indent(i2) << "}" << "\n";
+}
+
+void DisassemblerTables::emitContextDecision(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2,
+ unsigned &ModRMTableNum,
+ ContextDecision &decision,
+ const char* name) const {
+ o2.indent(i2) << "static const struct ContextDecision " << name << " = {\n";
+ i2++;
+ o2.indent(i2) << "{ /* opcodeDecisions */" << "\n";
+ i2++;
+
+ for (unsigned index = 0; index < IC_max; ++index) {
+ o2.indent(i2) << "/* ";
+ o2 << stringForContext((InstructionContext)index);
+ o2 << " */";
+ o2 << "\n";
+
+ emitOpcodeDecision(o1, o2, i1, i2, ModRMTableNum,
+ decision.opcodeDecisions[index]);
+
+ if (index + 1 < IC_max)
+ o2 << ", ";
+ }
+
+ i2--;
+ o2.indent(i2) << "}" << "\n";
+ i2--;
+ o2.indent(i2) << "};" << "\n";
+}
+
+void DisassemblerTables::emitInstructionInfo(raw_ostream &o,
+ unsigned &i) const {
+ unsigned NumInstructions = InstructionSpecifiers.size();
+
+ o << "static const struct OperandSpecifier x86OperandSets[]["
+ << X86_MAX_OPERANDS << "] = {\n";
+
+ typedef SmallVector<std::pair<OperandEncoding, OperandType>,
+ X86_MAX_OPERANDS> OperandListTy;
+ std::map<OperandListTy, unsigned> OperandSets;
+
+ unsigned OperandSetNum = 0;
+ for (unsigned Index = 0; Index < NumInstructions; ++Index) {
+ OperandListTy OperandList;
+
+ for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
+ ++OperandIndex) {
+ OperandEncoding Encoding = (OperandEncoding)InstructionSpecifiers[Index]
+ .operands[OperandIndex].encoding;
+ OperandType Type = (OperandType)InstructionSpecifiers[Index]
+ .operands[OperandIndex].type;
+ OperandList.push_back(std::make_pair(Encoding, Type));
+ }
+ unsigned &N = OperandSets[OperandList];
+ if (N != 0) continue;
+
+ N = ++OperandSetNum;
+
+ o << " { /* " << (OperandSetNum - 1) << " */\n";
+ for (unsigned i = 0, e = OperandList.size(); i != e; ++i) {
+ const char *Encoding = stringForOperandEncoding(OperandList[i].first);
+ const char *Type = stringForOperandType(OperandList[i].second);
+ o << " { " << Encoding << ", " << Type << " },\n";
+ }
+ o << " },\n";
+ }
+ o << "};" << "\n\n";
+
+ o.indent(i * 2) << "static const struct InstructionSpecifier ";
+ o << INSTRUCTIONS_STR "[" << InstructionSpecifiers.size() << "] = {\n";
+
+ i++;
+
+ for (unsigned index = 0; index < NumInstructions; ++index) {
+ o.indent(i * 2) << "{ /* " << index << " */\n";
+ i++;
+
+ OperandListTy OperandList;
+ for (unsigned OperandIndex = 0; OperandIndex < X86_MAX_OPERANDS;
+ ++OperandIndex) {
+ OperandEncoding Encoding = (OperandEncoding)InstructionSpecifiers[index]
+ .operands[OperandIndex].encoding;
+ OperandType Type = (OperandType)InstructionSpecifiers[index]
+ .operands[OperandIndex].type;
+ OperandList.push_back(std::make_pair(Encoding, Type));
+ }
+ o.indent(i * 2) << (OperandSets[OperandList] - 1) << ",\n";
+
+ o.indent(i * 2) << "/* " << InstructionSpecifiers[index].name << " */\n";
+
+ i--;
+ o.indent(i * 2) << "},\n";
+ }
+
+ i--;
+ o.indent(i * 2) << "};" << "\n";
+}
+
+void DisassemblerTables::emitContextTable(raw_ostream &o, unsigned &i) const {
+ const unsigned int tableSize = 16384;
+ o.indent(i * 2) << "static const uint8_t " CONTEXTS_STR
+ "[" << tableSize << "] = {\n";
+ i++;
+
+ for (unsigned index = 0; index < tableSize; ++index) {
+ o.indent(i * 2);
+
+ if (index & ATTR_EVEX) {
+ o << "IC_EVEX";
+ if (index & ATTR_EVEXL2)
+ o << "_L2";
+ else if (index & ATTR_EVEXL)
+ o << "_L";
+ if (index & ATTR_REXW)
+ o << "_W";
+ if (index & ATTR_OPSIZE)
+ o << "_OPSIZE";
+ else if (index & ATTR_XD)
+ o << "_XD";
+ else if (index & ATTR_XS)
+ o << "_XS";
+ if (index & ATTR_EVEXKZ)
+ o << "_KZ";
+ else if (index & ATTR_EVEXK)
+ o << "_K";
+ if (index & ATTR_EVEXB)
+ o << "_B";
+ }
+ else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
+ o << "IC_VEX_L_W_OPSIZE";
+ else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XD))
+ o << "IC_VEX_L_W_XD";
+ else if ((index & ATTR_VEXL) && (index & ATTR_REXW) && (index & ATTR_XS))
+ o << "IC_VEX_L_W_XS";
+ else if ((index & ATTR_VEXL) && (index & ATTR_REXW))
+ o << "IC_VEX_L_W";
+ else if ((index & ATTR_VEXL) && (index & ATTR_OPSIZE))
+ o << "IC_VEX_L_OPSIZE";
+ else if ((index & ATTR_VEXL) && (index & ATTR_XD))
+ o << "IC_VEX_L_XD";
+ else if ((index & ATTR_VEXL) && (index & ATTR_XS))
+ o << "IC_VEX_L_XS";
+ else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_OPSIZE))
+ o << "IC_VEX_W_OPSIZE";
+ else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XD))
+ o << "IC_VEX_W_XD";
+ else if ((index & ATTR_VEX) && (index & ATTR_REXW) && (index & ATTR_XS))
+ o << "IC_VEX_W_XS";
+ else if (index & ATTR_VEXL)
+ o << "IC_VEX_L";
+ else if ((index & ATTR_VEX) && (index & ATTR_REXW))
+ o << "IC_VEX_W";
+ else if ((index & ATTR_VEX) && (index & ATTR_OPSIZE))
+ o << "IC_VEX_OPSIZE";
+ else if ((index & ATTR_VEX) && (index & ATTR_XD))
+ o << "IC_VEX_XD";
+ else if ((index & ATTR_VEX) && (index & ATTR_XS))
+ o << "IC_VEX_XS";
+ else if (index & ATTR_VEX)
+ o << "IC_VEX";
+ else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XS))
+ o << "IC_64BIT_REXW_XS";
+ else if ((index & ATTR_64BIT) && (index & ATTR_REXW) && (index & ATTR_XD))
+ o << "IC_64BIT_REXW_XD";
+ else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
+ (index & ATTR_OPSIZE))
+ o << "IC_64BIT_REXW_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_REXW) &&
+ (index & ATTR_ADSIZE))
+ o << "IC_64BIT_REXW_ADSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XD) && (index & ATTR_OPSIZE))
+ o << "IC_64BIT_XD_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XS) && (index & ATTR_OPSIZE))
+ o << "IC_64BIT_XS_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XS))
+ o << "IC_64BIT_XS";
+ else if ((index & ATTR_64BIT) && (index & ATTR_XD))
+ o << "IC_64BIT_XD";
+ else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE) &&
+ (index & ATTR_ADSIZE))
+ o << "IC_64BIT_OPSIZE_ADSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_OPSIZE))
+ o << "IC_64BIT_OPSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_ADSIZE))
+ o << "IC_64BIT_ADSIZE";
+ else if ((index & ATTR_64BIT) && (index & ATTR_REXW))
+ o << "IC_64BIT_REXW";
+ else if ((index & ATTR_64BIT))
+ o << "IC_64BIT";
+ else if ((index & ATTR_XS) && (index & ATTR_OPSIZE))
+ o << "IC_XS_OPSIZE";
+ else if ((index & ATTR_XD) && (index & ATTR_OPSIZE))
+ o << "IC_XD_OPSIZE";
+ else if (index & ATTR_XS)
+ o << "IC_XS";
+ else if (index & ATTR_XD)
+ o << "IC_XD";
+ else if ((index & ATTR_OPSIZE) && (index & ATTR_ADSIZE))
+ o << "IC_OPSIZE_ADSIZE";
+ else if (index & ATTR_OPSIZE)
+ o << "IC_OPSIZE";
+ else if (index & ATTR_ADSIZE)
+ o << "IC_ADSIZE";
+ else
+ o << "IC";
+
+ if (index < tableSize - 1)
+ o << ",";
+ else
+ o << " ";
+
+ o << " /* " << index << " */";
+
+ o << "\n";
+ }
+
+ i--;
+ o.indent(i * 2) << "};" << "\n";
+}
+
+void DisassemblerTables::emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2,
+ unsigned &ModRMTableNum) const {
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[0], ONEBYTE_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[1], TWOBYTE_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[2], THREEBYTE38_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[3], THREEBYTE3A_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[4], XOP8_MAP_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[5], XOP9_MAP_STR);
+ emitContextDecision(o1, o2, i1, i2, ModRMTableNum, *Tables[6], XOPA_MAP_STR);
+}
+
+void DisassemblerTables::emit(raw_ostream &o) const {
+ unsigned i1 = 0;
+ unsigned i2 = 0;
+
+ std::string s1;
+ std::string s2;
+
+ raw_string_ostream o1(s1);
+ raw_string_ostream o2(s2);
+
+ emitInstructionInfo(o, i2);
+ o << "\n";
+
+ emitContextTable(o, i2);
+ o << "\n";
+
+ unsigned ModRMTableNum = 0;
+
+ o << "static const InstrUID modRMTable[] = {\n";
+ i1++;
+ std::vector<unsigned> EmptyTable(1, 0);
+ ModRMTable[EmptyTable] = ModRMTableNum;
+ ModRMTableNum += EmptyTable.size();
+ o1 << "/* EmptyTable */\n";
+ o1.indent(i1 * 2) << "0x0,\n";
+ i1--;
+ emitContextDecisions(o1, o2, i1, i2, ModRMTableNum);
+
+ o << o1.str();
+ o << " 0x0\n";
+ o << "};\n";
+ o << "\n";
+ o << o2.str();
+ o << "\n";
+ o << "\n";
+}
+
+void DisassemblerTables::setTableFields(ModRMDecision &decision,
+ const ModRMFilter &filter,
+ InstrUID uid,
+ uint8_t opcode) {
+ for (unsigned index = 0; index < 256; ++index) {
+ if (filter.accepts(index)) {
+ if (decision.instructionIDs[index] == uid)
+ continue;
+
+ if (decision.instructionIDs[index] != 0) {
+ InstructionSpecifier &newInfo =
+ InstructionSpecifiers[uid];
+ InstructionSpecifier &previousInfo =
+ InstructionSpecifiers[decision.instructionIDs[index]];
+
+ if(previousInfo.name == "NOOP" && (newInfo.name == "XCHG16ar" ||
+ newInfo.name == "XCHG32ar" ||
+ newInfo.name == "XCHG32ar64" ||
+ newInfo.name == "XCHG64ar"))
+ continue; // special case for XCHG*ar and NOOP
+
+ if (previousInfo.name == "DATA16_PREFIX" &&
+ newInfo.name == "DATA32_PREFIX")
+ continue; // special case for data16 and data32
+
+ if (outranks(previousInfo.insnContext, newInfo.insnContext))
+ continue;
+
+ if (previousInfo.insnContext == newInfo.insnContext) {
+ errs() << "Error: Primary decode conflict: ";
+ errs() << newInfo.name << " would overwrite " << previousInfo.name;
+ errs() << "\n";
+ errs() << "ModRM " << index << "\n";
+ errs() << "Opcode " << (uint16_t)opcode << "\n";
+ errs() << "Context " << stringForContext(newInfo.insnContext) << "\n";
+ HasConflicts = true;
+ }
+ }
+
+ decision.instructionIDs[index] = uid;
+ }
+ }
+}
+
+void DisassemblerTables::setTableFields(OpcodeType type,
+ InstructionContext insnContext,
+ uint8_t opcode,
+ const ModRMFilter &filter,
+ InstrUID uid,
+ bool is32bit,
+ bool ignoresVEX_L,
+ unsigned addressSize) {
+ ContextDecision &decision = *Tables[type];
+
+ for (unsigned index = 0; index < IC_max; ++index) {
+ if ((is32bit || addressSize == 16) &&
+ inheritsFrom((InstructionContext)index, IC_64BIT))
+ continue;
+
+ bool adSize64 = addressSize == 64;
+ if (inheritsFrom((InstructionContext)index,
+ InstructionSpecifiers[uid].insnContext, ignoresVEX_L,
+ adSize64))
+ setTableFields(decision.opcodeDecisions[index].modRMDecisions[opcode],
+ filter,
+ uid,
+ opcode);
+ }
+}
diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.h b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h
new file mode 100644
index 000000000000..5a8688be0819
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.h
@@ -0,0 +1,283 @@
+//===- X86DisassemblerTables.h - Disassembler tables ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the X86 Disassembler Emitter.
+// It contains the interface of the disassembler tables.
+// Documentation for the disassembler emitter in general can be found in
+// X86DisasemblerEmitter.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H
+#define LLVM_UTILS_TABLEGEN_X86DISASSEMBLERTABLES_H
+
+#include "X86DisassemblerShared.h"
+#include "X86ModRMFilters.h"
+#include "llvm/Support/raw_ostream.h"
+#include <map>
+#include <vector>
+
+namespace llvm {
+
+namespace X86Disassembler {
+
+/// DisassemblerTables - Encapsulates all the decode tables being generated by
+/// the table emitter. Contains functions to populate the tables as well as
+/// to emit them as hierarchical C structures suitable for consumption by the
+/// runtime.
+class DisassemblerTables {
+private:
+ /// The decoder tables. There is one for each opcode type:
+ /// [0] one-byte opcodes
+ /// [1] two-byte opcodes of the form 0f __
+ /// [2] three-byte opcodes of the form 0f 38 __
+ /// [3] three-byte opcodes of the form 0f 3a __
+ /// [4] XOP8 map opcode
+ /// [5] XOP9 map opcode
+ /// [6] XOPA map opcode
+ ContextDecision* Tables[7];
+
+ // Table of ModRM encodings.
+ typedef std::map<std::vector<unsigned>, unsigned> ModRMMapTy;
+ mutable ModRMMapTy ModRMTable;
+
+ /// The instruction information table
+ std::vector<InstructionSpecifier> InstructionSpecifiers;
+
+ /// True if there are primary decode conflicts in the instruction set
+ bool HasConflicts;
+
+ /// emitModRMDecision - Emits a table of entries corresponding to a single
+ /// ModR/M decision. Compacts the ModR/M decision if possible. ModR/M
+ /// decisions are printed as:
+ ///
+ /// { /* struct ModRMDecision */
+ /// TYPE,
+ /// modRMTablennnn
+ /// }
+ ///
+ /// where nnnn is a unique ID for the corresponding table of IDs.
+ /// TYPE indicates whether the table has one entry that is the same
+ /// regardless of ModR/M byte, two entries - one for bytes 0x00-0xbf and one
+ /// for bytes 0xc0-0xff -, or 256 entries, one for each possible byte.
+ /// nnnn is the number of a table for looking up these values. The tables
+ /// are written separately so that tables consisting entirely of zeros will
+ /// not be duplicated. (These all have the name modRMEmptyTable.) A table
+ /// is printed as:
+ ///
+ /// InstrUID modRMTablennnn[k] = {
+ /// nnnn, /* MNEMONIC */
+ /// ...
+ /// nnnn /* MNEMONIC */
+ /// };
+ ///
+ /// @param o1 - The output stream to print the ID table to.
+ /// @param o2 - The output stream to print the decision structure to.
+ /// @param i1 - The indentation level to use with stream o1.
+ /// @param i2 - The indentation level to use with stream o2.
+ /// @param ModRMTableNum - next table number for adding to ModRMTable.
+ /// @param decision - The ModR/M decision to emit. This decision has 256
+ /// entries - emitModRMDecision decides how to compact it.
+ void emitModRMDecision(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
+ ModRMDecision &decision) const;
+
+ /// emitOpcodeDecision - Emits an OpcodeDecision and all its subsidiary ModR/M
+ /// decisions. An OpcodeDecision is printed as:
+ ///
+ /// { /* struct OpcodeDecision */
+ /// /* 0x00 */
+ /// { /* struct ModRMDecision */
+ /// ...
+ /// }
+ /// ...
+ /// }
+ ///
+ /// where the ModRMDecision structure is printed as described in the
+ /// documentation for emitModRMDecision(). emitOpcodeDecision() passes on a
+ /// stream and indent level for the UID tables generated by
+ /// emitModRMDecision(), but does not use them itself.
+ ///
+ /// @param o1 - The output stream to print the ID tables generated by
+ /// emitModRMDecision() to.
+ /// @param o2 - The output stream for the decision structure itself.
+ /// @param i1 - The indent level to use with stream o1.
+ /// @param i2 - The indent level to use with stream o2.
+ /// @param ModRMTableNum - next table number for adding to ModRMTable.
+ /// @param decision - The OpcodeDecision to emit along with its subsidiary
+ /// structures.
+ void emitOpcodeDecision(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
+ OpcodeDecision &decision) const;
+
+ /// emitContextDecision - Emits a ContextDecision and all its subsidiary
+ /// Opcode and ModRMDecisions. A ContextDecision is printed as:
+ ///
+ /// struct ContextDecision NAME = {
+ /// { /* OpcodeDecisions */
+ /// /* IC */
+ /// { /* struct OpcodeDecision */
+ /// ...
+ /// },
+ /// ...
+ /// }
+ /// }
+ ///
+ /// NAME is the name of the ContextDecision (typically one of the four names
+ /// ONEBYTE_SYM, TWOBYTE_SYM, THREEBYTE38_SYM, THREEBYTE3A_SYM from
+ /// X86DisassemblerDecoderCommon.h).
+ /// IC is one of the contexts in InstructionContext. There is an opcode
+ /// decision for each possible context.
+ /// The OpcodeDecision structures are printed as described in the
+ /// documentation for emitOpcodeDecision.
+ ///
+ /// @param o1 - The output stream to print the ID tables generated by
+ /// emitModRMDecision() to.
+ /// @param o2 - The output stream to print the decision structure to.
+ /// @param i1 - The indent level to use with stream o1.
+ /// @param i2 - The indent level to use with stream o2.
+ /// @param ModRMTableNum - next table number for adding to ModRMTable.
+ /// @param decision - The ContextDecision to emit along with its subsidiary
+ /// structures.
+ /// @param name - The name for the ContextDecision.
+ void emitContextDecision(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2, unsigned &ModRMTableNum,
+ ContextDecision &decision, const char* name) const;
+
+ /// emitInstructionInfo - Prints the instruction specifier table, which has
+ /// one entry for each instruction, and contains name and operand
+ /// information. This table is printed as:
+ ///
+ /// struct InstructionSpecifier CONTEXTS_SYM[k] = {
+ /// {
+ /// /* nnnn */
+ /// "MNEMONIC",
+ /// 0xnn,
+ /// {
+ /// {
+ /// ENCODING,
+ /// TYPE
+ /// },
+ /// ...
+ /// }
+ /// },
+ /// };
+ ///
+ /// k is the total number of instructions.
+ /// nnnn is the ID of the current instruction (0-based). This table
+ /// includes entries for non-instructions like PHINODE.
+ /// 0xnn is the lowest possible opcode for the current instruction, used for
+ /// AddRegFrm instructions to compute the operand's value.
+ /// ENCODING and TYPE describe the encoding and type for a single operand.
+ ///
+ /// @param o - The output stream to which the instruction table should be
+ /// written.
+ /// @param i - The indent level for use with the stream.
+ void emitInstructionInfo(raw_ostream &o, unsigned &i) const;
+
+ /// emitContextTable - Prints the table that is used to translate from an
+ /// instruction attribute mask to an instruction context. This table is
+ /// printed as:
+ ///
+ /// InstructionContext CONTEXTS_STR[256] = {
+ /// IC, /* 0x00 */
+ /// ...
+ /// };
+ ///
+ /// IC is the context corresponding to the mask 0x00, and there are 256
+ /// possible masks.
+ ///
+ /// @param o - The output stream to which the context table should be written.
+ /// @param i - The indent level for use with the stream.
+ void emitContextTable(raw_ostream &o, uint32_t &i) const;
+
+ /// emitContextDecisions - Prints all four ContextDecision structures using
+ /// emitContextDecision().
+ ///
+ /// @param o1 - The output stream to print the ID tables generated by
+ /// emitModRMDecision() to.
+ /// @param o2 - The output stream to print the decision structures to.
+ /// @param i1 - The indent level to use with stream o1.
+ /// @param i2 - The indent level to use with stream o2.
+ /// @param ModRMTableNum - next table number for adding to ModRMTable.
+ void emitContextDecisions(raw_ostream &o1, raw_ostream &o2,
+ unsigned &i1, unsigned &i2,
+ unsigned &ModRMTableNum) const;
+
+ /// setTableFields - Uses a ModRMFilter to set the appropriate entries in a
+ /// ModRMDecision to refer to a particular instruction ID.
+ ///
+ /// @param decision - The ModRMDecision to populate.
+ /// @param filter - The filter to use in deciding which entries to populate.
+ /// @param uid - The unique ID to set matching entries to.
+ /// @param opcode - The opcode of the instruction, for error reporting.
+ void setTableFields(ModRMDecision &decision,
+ const ModRMFilter &filter,
+ InstrUID uid,
+ uint8_t opcode);
+public:
+ /// Constructor - Allocates space for the class decisions and clears them.
+ DisassemblerTables();
+
+ ~DisassemblerTables();
+
+ /// emit - Emits the instruction table, context table, and class decisions.
+ ///
+ /// @param o - The output stream to print the tables to.
+ void emit(raw_ostream &o) const;
+
+ /// setTableFields - Uses the opcode type, instruction context, opcode, and a
+ /// ModRMFilter as criteria to set a particular set of entries in the
+ /// decode tables to point to a specific uid.
+ ///
+ /// @param type - The opcode type (ONEBYTE, TWOBYTE, etc.)
+ /// @param insnContext - The context to use (IC, IC_64BIT, etc.)
+ /// @param opcode - The last byte of the opcode (not counting any escape
+ /// or extended opcodes).
+ /// @param filter - The ModRMFilter that decides which ModR/M byte values
+ /// correspond to the desired instruction.
+ /// @param uid - The unique ID of the instruction.
+ /// @param is32bit - Instructon is only 32-bit
+ /// @param ignoresVEX_L - Instruction ignores VEX.L
+ /// @param AddrSize - Instructions address size 16/32/64. 0 is unspecified
+ void setTableFields(OpcodeType type,
+ InstructionContext insnContext,
+ uint8_t opcode,
+ const ModRMFilter &filter,
+ InstrUID uid,
+ bool is32bit,
+ bool ignoresVEX_L,
+ unsigned AddrSize);
+
+ /// specForUID - Returns the instruction specifier for a given unique
+ /// instruction ID. Used when resolving collisions.
+ ///
+ /// @param uid - The unique ID of the instruction.
+ /// @return - A reference to the instruction specifier.
+ InstructionSpecifier& specForUID(InstrUID uid) {
+ if (uid >= InstructionSpecifiers.size())
+ InstructionSpecifiers.resize(uid + 1);
+
+ return InstructionSpecifiers[uid];
+ }
+
+ // hasConflicts - Reports whether there were primary decode conflicts
+ // from any instructions added to the tables.
+ // @return - true if there were; false otherwise.
+
+ bool hasConflicts() {
+ return HasConflicts;
+ }
+};
+
+} // namespace X86Disassembler
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp b/contrib/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp
new file mode 100644
index 000000000000..07b96b03b01c
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86EVEX2VEXTablesEmitter.cpp
@@ -0,0 +1,339 @@
+//===- utils/TableGen/X86EVEX2VEXTablesEmitter.cpp - X86 backend-*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// This tablegen backend is responsible for emitting the X86 backend EVEX2VEX
+/// compression tables.
+///
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenDAGPatterns.h"
+#include "CodeGenTarget.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/TableGenBackend.h"
+
+using namespace llvm;
+
+namespace {
+
+class X86EVEX2VEXTablesEmitter {
+ CodeGenTarget Target;
+
+ // Hold all non-masked & non-broadcasted EVEX encoded instructions
+ std::vector<const CodeGenInstruction *> EVEXInsts;
+ // Hold all VEX encoded instructions. Divided into groups with same opcodes
+ // to make the search more efficient
+ std::map<uint64_t, std::vector<const CodeGenInstruction *>> VEXInsts;
+
+ typedef std::pair<const CodeGenInstruction *, const CodeGenInstruction *> Entry;
+
+ // Represent both compress tables
+ std::vector<Entry> EVEX2VEX128;
+ std::vector<Entry> EVEX2VEX256;
+
+ // Represents a manually added entry to the tables
+ struct ManualEntry {
+ const char *EVEXInstStr;
+ const char *VEXInstStr;
+ bool Is128Bit;
+ };
+
+public:
+ X86EVEX2VEXTablesEmitter(RecordKeeper &R) : Target(R) {}
+
+ // run - Output X86 EVEX2VEX tables.
+ void run(raw_ostream &OS);
+
+private:
+ // Prints the given table as a C++ array of type
+ // X86EvexToVexCompressTableEntry
+ void printTable(const std::vector<Entry> &Table, raw_ostream &OS);
+
+ bool inExceptionList(const CodeGenInstruction *Inst) {
+ // List of EVEX instructions that match VEX instructions by the encoding
+ // but do not perform the same operation.
+ static constexpr const char *ExceptionList[] = {
+ "VCVTQQ2PD",
+ "VCVTQQ2PS",
+ "VPMAXSQ",
+ "VPMAXUQ",
+ "VPMINSQ",
+ "VPMINUQ",
+ "VPMULLQ",
+ "VPSRAQ",
+ "VDBPSADBW",
+ "VRNDSCALE",
+ "VSCALEFPS"
+ };
+ // Instruction's name starts with one of the entries in the exception list
+ for (StringRef InstStr : ExceptionList) {
+ if (Inst->TheDef->getName().startswith(InstStr))
+ return true;
+ }
+ return false;
+ }
+
+};
+
+void X86EVEX2VEXTablesEmitter::printTable(const std::vector<Entry> &Table,
+ raw_ostream &OS) {
+ std::string Size = (Table == EVEX2VEX128) ? "128" : "256";
+
+ OS << "// X86 EVEX encoded instructions that have a VEX " << Size
+ << " encoding\n"
+ << "// (table format: <EVEX opcode, VEX-" << Size << " opcode>).\n"
+ << "static const X86EvexToVexCompressTableEntry X86EvexToVex" << Size
+ << "CompressTable[] = {\n"
+ << " // EVEX scalar with corresponding VEX.\n";
+
+ // Print all entries added to the table
+ for (auto Pair : Table) {
+ OS << " { X86::" << Pair.first->TheDef->getName()
+ << ", X86::" << Pair.second->TheDef->getName() << " },\n";
+ }
+
+ // Some VEX instructions were duplicated to multiple EVEX versions due the
+ // introduction of mask variants, and thus some of the EVEX versions have
+ // different encoding than the VEX instruction. In order to maximize the
+ // compression we add these entries manually.
+ static constexpr ManualEntry ManuallyAddedEntries[] = {
+ // EVEX-Inst VEX-Inst Is128-bit
+ {"VMOVDQU8Z128mr", "VMOVDQUmr", true},
+ {"VMOVDQU8Z128rm", "VMOVDQUrm", true},
+ {"VMOVDQU8Z128rr", "VMOVDQUrr", true},
+ {"VMOVDQU8Z128rr_REV", "VMOVDQUrr_REV", true},
+ {"VMOVDQU16Z128mr", "VMOVDQUmr", true},
+ {"VMOVDQU16Z128rm", "VMOVDQUrm", true},
+ {"VMOVDQU16Z128rr", "VMOVDQUrr", true},
+ {"VMOVDQU16Z128rr_REV", "VMOVDQUrr_REV", true},
+ {"VMOVDQU8Z256mr", "VMOVDQUYmr", false},
+ {"VMOVDQU8Z256rm", "VMOVDQUYrm", false},
+ {"VMOVDQU8Z256rr", "VMOVDQUYrr", false},
+ {"VMOVDQU8Z256rr_REV", "VMOVDQUYrr_REV", false},
+ {"VMOVDQU16Z256mr", "VMOVDQUYmr", false},
+ {"VMOVDQU16Z256rm", "VMOVDQUYrm", false},
+ {"VMOVDQU16Z256rr", "VMOVDQUYrr", false},
+ {"VMOVDQU16Z256rr_REV", "VMOVDQUYrr_REV", false},
+
+ {"VPERMILPDZ128mi", "VPERMILPDmi", true},
+ {"VPERMILPDZ128ri", "VPERMILPDri", true},
+ {"VPERMILPDZ128rm", "VPERMILPDrm", true},
+ {"VPERMILPDZ128rr", "VPERMILPDrr", true},
+ {"VPERMILPDZ256mi", "VPERMILPDYmi", false},
+ {"VPERMILPDZ256ri", "VPERMILPDYri", false},
+ {"VPERMILPDZ256rm", "VPERMILPDYrm", false},
+ {"VPERMILPDZ256rr", "VPERMILPDYrr", false},
+
+ {"VPBROADCASTQZ128m", "VPBROADCASTQrm", true},
+ {"VPBROADCASTQZ128r", "VPBROADCASTQrr", true},
+ {"VPBROADCASTQZ256m", "VPBROADCASTQYrm", false},
+ {"VPBROADCASTQZ256r", "VPBROADCASTQYrr", false},
+
+ {"VBROADCASTSDZ256m", "VBROADCASTSDYrm", false},
+ {"VBROADCASTSDZ256r", "VBROADCASTSDYrr", false},
+
+ {"VEXTRACTF64x2Z256mr", "VEXTRACTF128mr", false},
+ {"VEXTRACTF64x2Z256rr", "VEXTRACTF128rr", false},
+ {"VEXTRACTI64x2Z256mr", "VEXTRACTI128mr", false},
+ {"VEXTRACTI64x2Z256rr", "VEXTRACTI128rr", false},
+
+ {"VINSERTF64x2Z256rm", "VINSERTF128rm", false},
+ {"VINSERTF64x2Z256rr", "VINSERTF128rr", false},
+ {"VINSERTI64x2Z256rm", "VINSERTI128rm", false},
+ {"VINSERTI64x2Z256rr", "VINSERTI128rr", false}
+ };
+
+ // Print the manually added entries
+ for (const ManualEntry &Entry : ManuallyAddedEntries) {
+ if ((Table == EVEX2VEX128 && Entry.Is128Bit) ||
+ (Table == EVEX2VEX256 && !Entry.Is128Bit)) {
+ OS << " { X86::" << Entry.EVEXInstStr << ", X86::" << Entry.VEXInstStr
+ << " },\n";
+ }
+ }
+
+ OS << "};\n\n";
+}
+
+// Return true if the 2 BitsInits are equal
+static inline bool equalBitsInits(const BitsInit *B1, const BitsInit *B2) {
+ if (B1->getNumBits() != B2->getNumBits())
+ PrintFatalError("Comparing two BitsInits with different sizes!");
+
+ for (unsigned i = 0, e = B1->getNumBits(); i != e; ++i) {
+ if (BitInit *Bit1 = dyn_cast<BitInit>(B1->getBit(i))) {
+ if (BitInit *Bit2 = dyn_cast<BitInit>(B2->getBit(i))) {
+ if (Bit1->getValue() != Bit2->getValue())
+ return false;
+ } else
+ PrintFatalError("Invalid BitsInit bit");
+ } else
+ PrintFatalError("Invalid BitsInit bit");
+ }
+ return true;
+}
+
+// Calculates the integer value residing BitsInit object
+static inline uint64_t getValueFromBitsInit(const BitsInit *B) {
+ uint64_t Value = 0;
+ for (unsigned i = 0, e = B->getNumBits(); i != e; ++i) {
+ if (BitInit *Bit = dyn_cast<BitInit>(B->getBit(i)))
+ Value |= uint64_t(Bit->getValue()) << i;
+ else
+ PrintFatalError("Invalid VectSize bit");
+ }
+ return Value;
+}
+
+// Function object - Operator() returns true if the given VEX instruction
+// matches the EVEX instruction of this object.
+class IsMatch {
+ const CodeGenInstruction *Inst;
+
+public:
+ IsMatch(const CodeGenInstruction *Inst) : Inst(Inst) {}
+
+ bool operator()(const CodeGenInstruction *Inst2) {
+ Record *Rec1 = Inst->TheDef;
+ Record *Rec2 = Inst2->TheDef;
+ uint64_t Rec1WVEX =
+ getValueFromBitsInit(Rec1->getValueAsBitsInit("VEX_WPrefix"));
+ uint64_t Rec2WVEX =
+ getValueFromBitsInit(Rec2->getValueAsBitsInit("VEX_WPrefix"));
+
+ if (Rec2->getValueAsDef("OpEnc")->getName().str() != "EncVEX" ||
+ // VEX/EVEX fields
+ Rec2->getValueAsDef("OpPrefix") != Rec1->getValueAsDef("OpPrefix") ||
+ Rec2->getValueAsDef("OpMap") != Rec1->getValueAsDef("OpMap") ||
+ Rec2->getValueAsBit("hasVEX_4V") != Rec1->getValueAsBit("hasVEX_4V") ||
+ !equalBitsInits(Rec2->getValueAsBitsInit("EVEX_LL"),
+ Rec1->getValueAsBitsInit("EVEX_LL")) ||
+ (Rec1WVEX != 2 && Rec2WVEX != 2 && Rec1WVEX != Rec2WVEX) ||
+ // Instruction's format
+ Rec2->getValueAsDef("Form") != Rec1->getValueAsDef("Form") ||
+ Rec2->getValueAsBit("isAsmParserOnly") !=
+ Rec1->getValueAsBit("isAsmParserOnly"))
+ return false;
+
+ // This is needed for instructions with intrinsic version (_Int).
+ // Where the only difference is the size of the operands.
+ // For example: VUCOMISDZrm and Int_VUCOMISDrm
+ // Also for instructions that their EVEX version was upgraded to work with
+ // k-registers. For example VPCMPEQBrm (xmm output register) and
+ // VPCMPEQBZ128rm (k register output register).
+ for (unsigned i = 0; i < Inst->Operands.size(); i++) {
+ Record *OpRec1 = Inst->Operands[i].Rec;
+ Record *OpRec2 = Inst2->Operands[i].Rec;
+
+ if (OpRec1 == OpRec2)
+ continue;
+
+ if (isRegisterOperand(OpRec1) && isRegisterOperand(OpRec2)) {
+ if (getRegOperandSize(OpRec1) != getRegOperandSize(OpRec2))
+ return false;
+ } else if (isMemoryOperand(OpRec1) && isMemoryOperand(OpRec2)) {
+ return false;
+ } else if (isImmediateOperand(OpRec1) && isImmediateOperand(OpRec2)) {
+ if (OpRec1->getValueAsDef("Type") != OpRec2->getValueAsDef("Type"))
+ return false;
+ } else
+ return false;
+ }
+
+ return true;
+ }
+
+private:
+ static inline bool isRegisterOperand(const Record *Rec) {
+ return Rec->isSubClassOf("RegisterClass") ||
+ Rec->isSubClassOf("RegisterOperand");
+ }
+
+ static inline bool isMemoryOperand(const Record *Rec) {
+ return Rec->isSubClassOf("Operand") &&
+ Rec->getValueAsString("OperandType") == "OPERAND_MEMORY";
+ }
+
+ static inline bool isImmediateOperand(const Record *Rec) {
+ return Rec->isSubClassOf("Operand") &&
+ Rec->getValueAsString("OperandType") == "OPERAND_IMMEDIATE";
+ }
+
+ static inline unsigned int getRegOperandSize(const Record *RegRec) {
+ if (RegRec->isSubClassOf("RegisterClass"))
+ return RegRec->getValueAsInt("Alignment");
+ if (RegRec->isSubClassOf("RegisterOperand"))
+ return RegRec->getValueAsDef("RegClass")->getValueAsInt("Alignment");
+
+ llvm_unreachable("Register operand's size not known!");
+ }
+};
+
+void X86EVEX2VEXTablesEmitter::run(raw_ostream &OS) {
+ emitSourceFileHeader("X86 EVEX2VEX tables", OS);
+
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions =
+ Target.getInstructionsByEnumValue();
+
+ for (const CodeGenInstruction *Inst : NumberedInstructions) {
+ // Filter non-X86 instructions.
+ if (!Inst->TheDef->isSubClassOf("X86Inst"))
+ continue;
+
+ // Add VEX encoded instructions to one of VEXInsts vectors according to
+ // it's opcode.
+ if (Inst->TheDef->getValueAsDef("OpEnc")->getName() == "EncVEX") {
+ uint64_t Opcode = getValueFromBitsInit(Inst->TheDef->
+ getValueAsBitsInit("Opcode"));
+ VEXInsts[Opcode].push_back(Inst);
+ }
+ // Add relevant EVEX encoded instructions to EVEXInsts
+ else if (Inst->TheDef->getValueAsDef("OpEnc")->getName() == "EncEVEX" &&
+ !Inst->TheDef->getValueAsBit("hasEVEX_K") &&
+ !Inst->TheDef->getValueAsBit("hasEVEX_B") &&
+ getValueFromBitsInit(Inst->TheDef->
+ getValueAsBitsInit("EVEX_LL")) != 2 &&
+ !inExceptionList(Inst))
+ EVEXInsts.push_back(Inst);
+ }
+
+ for (const CodeGenInstruction *EVEXInst : EVEXInsts) {
+ uint64_t Opcode = getValueFromBitsInit(EVEXInst->TheDef->
+ getValueAsBitsInit("Opcode"));
+ // For each EVEX instruction look for a VEX match in the appropriate vector
+ // (instructions with the same opcode) using function object IsMatch.
+ auto Match = llvm::find_if(VEXInsts[Opcode], IsMatch(EVEXInst));
+ if (Match != VEXInsts[Opcode].end()) {
+ const CodeGenInstruction *VEXInst = *Match;
+
+ // In case a match is found add new entry to the appropriate table
+ switch (getValueFromBitsInit(
+ EVEXInst->TheDef->getValueAsBitsInit("EVEX_LL"))) {
+ case 0:
+ EVEX2VEX128.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,0}
+ break;
+ case 1:
+ EVEX2VEX256.push_back(std::make_pair(EVEXInst, VEXInst)); // {0,1}
+ break;
+ default:
+ llvm_unreachable("Instruction's size not fit for the mapping!");
+ }
+ }
+ }
+
+ // Print both tables
+ printTable(EVEX2VEX128, OS);
+ printTable(EVEX2VEX256, OS);
+}
+}
+
+namespace llvm {
+void EmitX86EVEX2VEXTables(RecordKeeper &RK, raw_ostream &OS) {
+ X86EVEX2VEXTablesEmitter(RK).run(OS);
+}
+}
diff --git a/contrib/llvm/utils/TableGen/X86ModRMFilters.cpp b/contrib/llvm/utils/TableGen/X86ModRMFilters.cpp
new file mode 100644
index 000000000000..1641613aa32d
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86ModRMFilters.cpp
@@ -0,0 +1,22 @@
+//===- X86ModRMFilters.cpp - Disassembler ModR/M filterss -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86ModRMFilters.h"
+
+using namespace llvm::X86Disassembler;
+
+void ModRMFilter::anchor() { }
+
+void DumbFilter::anchor() { }
+
+void ModFilter::anchor() { }
+
+void ExtendedFilter::anchor() { }
+
+void ExactFilter::anchor() { }
diff --git a/contrib/llvm/utils/TableGen/X86ModRMFilters.h b/contrib/llvm/utils/TableGen/X86ModRMFilters.h
new file mode 100644
index 000000000000..d919c588c644
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86ModRMFilters.h
@@ -0,0 +1,135 @@
+//===- X86ModRMFilters.h - Disassembler ModR/M filterss ---------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the X86 Disassembler Emitter.
+// It contains ModR/M filters that determine which values of the ModR/M byte
+// are valid for a partiuclar instruction.
+// Documentation for the disassembler emitter in general can be found in
+// X86DisasemblerEmitter.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H
+#define LLVM_UTILS_TABLEGEN_X86MODRMFILTERS_H
+
+#include "llvm/Support/DataTypes.h"
+
+namespace llvm {
+
+namespace X86Disassembler {
+
+/// ModRMFilter - Abstract base class for clases that recognize patterns in
+/// ModR/M bytes.
+class ModRMFilter {
+ virtual void anchor();
+public:
+ /// Destructor - Override as necessary.
+ virtual ~ModRMFilter() { }
+
+ /// isDumb - Indicates whether this filter returns the same value for
+ /// any value of the ModR/M byte.
+ ///
+ /// @result - True if the filter returns the same value for any ModR/M
+ /// byte; false if not.
+ virtual bool isDumb() const { return false; }
+
+ /// accepts - Indicates whether the filter accepts a particular ModR/M
+ /// byte value.
+ ///
+ /// @result - True if the filter accepts the ModR/M byte; false if not.
+ virtual bool accepts(uint8_t modRM) const = 0;
+};
+
+/// DumbFilter - Accepts any ModR/M byte. Used for instructions that do not
+/// require a ModR/M byte or instructions where the entire ModR/M byte is used
+/// for operands.
+class DumbFilter : public ModRMFilter {
+ void anchor() override;
+public:
+ bool isDumb() const override {
+ return true;
+ }
+
+ bool accepts(uint8_t modRM) const override {
+ return true;
+ }
+};
+
+/// ModFilter - Filters based on the mod bits [bits 7-6] of the ModR/M byte.
+/// Some instructions are classified based on whether they are 11 or anything
+/// else. This filter performs that classification.
+class ModFilter : public ModRMFilter {
+ void anchor() override;
+ bool R;
+public:
+ /// Constructor
+ ///
+ /// \param r True if the mod bits of the ModR/M byte must be 11; false
+ /// otherwise. The name r derives from the fact that the mod
+ /// bits indicate whether the R/M bits [bits 2-0] signify a
+ /// register or a memory operand.
+ ModFilter(bool r) :
+ ModRMFilter(),
+ R(r) {
+ }
+
+ bool accepts(uint8_t modRM) const override {
+ return (R == ((modRM & 0xc0) == 0xc0));
+ }
+};
+
+/// ExtendedFilter - Extended opcodes are classified based on the value of the
+/// mod field [bits 7-6] and the value of the nnn field [bits 5-3].
+class ExtendedFilter : public ModRMFilter {
+ void anchor() override;
+ bool R;
+ uint8_t NNN;
+public:
+ /// Constructor
+ ///
+ /// \param r True if the mod field must be set to 11; false otherwise.
+ /// The name is explained at ModFilter.
+ /// \param nnn The required value of the nnn field.
+ ExtendedFilter(bool r, uint8_t nnn) :
+ ModRMFilter(),
+ R(r),
+ NNN(nnn) {
+ }
+
+ bool accepts(uint8_t modRM) const override {
+ return (((R && ((modRM & 0xc0) == 0xc0)) ||
+ (!R && ((modRM & 0xc0) != 0xc0))) &&
+ (((modRM & 0x38) >> 3) == NNN));
+ }
+};
+
+/// ExactFilter - The occasional extended opcode (such as VMCALL or MONITOR)
+/// requires the ModR/M byte to have a specific value.
+class ExactFilter : public ModRMFilter {
+ void anchor() override;
+ uint8_t ModRM;
+public:
+ /// Constructor
+ ///
+ /// \param modRM The required value of the full ModR/M byte.
+ ExactFilter(uint8_t modRM) :
+ ModRMFilter(),
+ ModRM(modRM) {
+ }
+
+ bool accepts(uint8_t modRM) const override {
+ return (ModRM == modRM);
+ }
+};
+
+} // namespace X86Disassembler
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
new file mode 100644
index 000000000000..e703bbfc4496
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -0,0 +1,1326 @@
+//===- X86RecognizableInstr.cpp - Disassembler instruction spec --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the X86 Disassembler Emitter.
+// It contains the implementation of a single recognizable instruction.
+// Documentation for the disassembler emitter in general can be found in
+// X86DisasemblerEmitter.h.
+//
+//===----------------------------------------------------------------------===//
+
+#include "X86RecognizableInstr.h"
+#include "X86DisassemblerShared.h"
+#include "X86ModRMFilters.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <string>
+
+using namespace llvm;
+
+#define MRM_MAPPING \
+ MAP(C0, 64) \
+ MAP(C1, 65) \
+ MAP(C2, 66) \
+ MAP(C3, 67) \
+ MAP(C4, 68) \
+ MAP(C5, 69) \
+ MAP(C6, 70) \
+ MAP(C7, 71) \
+ MAP(C8, 72) \
+ MAP(C9, 73) \
+ MAP(CA, 74) \
+ MAP(CB, 75) \
+ MAP(CC, 76) \
+ MAP(CD, 77) \
+ MAP(CE, 78) \
+ MAP(CF, 79) \
+ MAP(D0, 80) \
+ MAP(D1, 81) \
+ MAP(D2, 82) \
+ MAP(D3, 83) \
+ MAP(D4, 84) \
+ MAP(D5, 85) \
+ MAP(D6, 86) \
+ MAP(D7, 87) \
+ MAP(D8, 88) \
+ MAP(D9, 89) \
+ MAP(DA, 90) \
+ MAP(DB, 91) \
+ MAP(DC, 92) \
+ MAP(DD, 93) \
+ MAP(DE, 94) \
+ MAP(DF, 95) \
+ MAP(E0, 96) \
+ MAP(E1, 97) \
+ MAP(E2, 98) \
+ MAP(E3, 99) \
+ MAP(E4, 100) \
+ MAP(E5, 101) \
+ MAP(E6, 102) \
+ MAP(E7, 103) \
+ MAP(E8, 104) \
+ MAP(E9, 105) \
+ MAP(EA, 106) \
+ MAP(EB, 107) \
+ MAP(EC, 108) \
+ MAP(ED, 109) \
+ MAP(EE, 110) \
+ MAP(EF, 111) \
+ MAP(F0, 112) \
+ MAP(F1, 113) \
+ MAP(F2, 114) \
+ MAP(F3, 115) \
+ MAP(F4, 116) \
+ MAP(F5, 117) \
+ MAP(F6, 118) \
+ MAP(F7, 119) \
+ MAP(F8, 120) \
+ MAP(F9, 121) \
+ MAP(FA, 122) \
+ MAP(FB, 123) \
+ MAP(FC, 124) \
+ MAP(FD, 125) \
+ MAP(FE, 126) \
+ MAP(FF, 127)
+
+// A clone of X86 since we can't depend on something that is generated.
+namespace X86Local {
+ enum {
+ Pseudo = 0,
+ RawFrm = 1,
+ AddRegFrm = 2,
+ RawFrmMemOffs = 3,
+ RawFrmSrc = 4,
+ RawFrmDst = 5,
+ RawFrmDstSrc = 6,
+ RawFrmImm8 = 7,
+ RawFrmImm16 = 8,
+ MRMDestMem = 32,
+ MRMSrcMem = 33,
+ MRMSrcMem4VOp3 = 34,
+ MRMSrcMemOp4 = 35,
+ MRMXm = 39,
+ MRM0m = 40, MRM1m = 41, MRM2m = 42, MRM3m = 43,
+ MRM4m = 44, MRM5m = 45, MRM6m = 46, MRM7m = 47,
+ MRMDestReg = 48,
+ MRMSrcReg = 49,
+ MRMSrcReg4VOp3 = 50,
+ MRMSrcRegOp4 = 51,
+ MRMXr = 55,
+ MRM0r = 56, MRM1r = 57, MRM2r = 58, MRM3r = 59,
+ MRM4r = 60, MRM5r = 61, MRM6r = 62, MRM7r = 63,
+#define MAP(from, to) MRM_##from = to,
+ MRM_MAPPING
+#undef MAP
+ };
+
+ enum {
+ OB = 0, TB = 1, T8 = 2, TA = 3, XOP8 = 4, XOP9 = 5, XOPA = 6
+ };
+
+ enum {
+ PS = 1, PD = 2, XS = 3, XD = 4
+ };
+
+ enum {
+ VEX = 1, XOP = 2, EVEX = 3
+ };
+
+ enum {
+ OpSize16 = 1, OpSize32 = 2
+ };
+
+ enum {
+ AdSize16 = 1, AdSize32 = 2, AdSize64 = 3
+ };
+
+ enum {
+ VEX_W0 = 0, VEX_W1 = 1, VEX_WIG = 2
+ };
+}
+
+using namespace X86Disassembler;
+
+/// byteFromBitsInit - Extracts a value at most 8 bits in width from a BitsInit.
+/// Useful for switch statements and the like.
+///
+/// @param init - A reference to the BitsInit to be decoded.
+/// @return - The field, with the first bit in the BitsInit as the lowest
+/// order bit.
+static uint8_t byteFromBitsInit(BitsInit &init) {
+ int width = init.getNumBits();
+
+ assert(width <= 8 && "Field is too large for uint8_t!");
+
+ int index;
+ uint8_t mask = 0x01;
+
+ uint8_t ret = 0;
+
+ for (index = 0; index < width; index++) {
+ if (static_cast<BitInit*>(init.getBit(index))->getValue())
+ ret |= mask;
+
+ mask <<= 1;
+ }
+
+ return ret;
+}
+
+/// byteFromRec - Extract a value at most 8 bits in with from a Record given the
+/// name of the field.
+///
+/// @param rec - The record from which to extract the value.
+/// @param name - The name of the field in the record.
+/// @return - The field, as translated by byteFromBitsInit().
+static uint8_t byteFromRec(const Record* rec, const std::string &name) {
+ BitsInit* bits = rec->getValueAsBitsInit(name);
+ return byteFromBitsInit(*bits);
+}
+
+RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
+ const CodeGenInstruction &insn,
+ InstrUID uid) {
+ UID = uid;
+
+ Rec = insn.TheDef;
+ Name = Rec->getName();
+ Spec = &tables.specForUID(UID);
+
+ if (!Rec->isSubClassOf("X86Inst")) {
+ ShouldBeEmitted = false;
+ return;
+ }
+
+ OpPrefix = byteFromRec(Rec, "OpPrefixBits");
+ OpMap = byteFromRec(Rec, "OpMapBits");
+ Opcode = byteFromRec(Rec, "Opcode");
+ Form = byteFromRec(Rec, "FormBits");
+ Encoding = byteFromRec(Rec, "OpEncBits");
+
+ OpSize = byteFromRec(Rec, "OpSizeBits");
+ AdSize = byteFromRec(Rec, "AdSizeBits");
+ HasREX_WPrefix = Rec->getValueAsBit("hasREX_WPrefix");
+ HasVEX_4V = Rec->getValueAsBit("hasVEX_4V");
+ VEX_WPrefix = byteFromRec(Rec,"VEX_WPrefix");
+ IgnoresVEX_L = Rec->getValueAsBit("ignoresVEX_L");
+ HasEVEX_L2Prefix = Rec->getValueAsBit("hasEVEX_L2");
+ HasEVEX_K = Rec->getValueAsBit("hasEVEX_K");
+ HasEVEX_KZ = Rec->getValueAsBit("hasEVEX_Z");
+ HasEVEX_B = Rec->getValueAsBit("hasEVEX_B");
+ IsCodeGenOnly = Rec->getValueAsBit("isCodeGenOnly");
+ ForceDisassemble = Rec->getValueAsBit("ForceDisassemble");
+ CD8_Scale = byteFromRec(Rec, "CD8_Scale");
+
+ Name = Rec->getName();
+
+ Operands = &insn.Operands.OperandList;
+
+ HasVEX_LPrefix = Rec->getValueAsBit("hasVEX_L");
+
+ // Check for 64-bit inst which does not require REX
+ Is32Bit = false;
+ Is64Bit = false;
+ // FIXME: Is there some better way to check for In64BitMode?
+ std::vector<Record*> Predicates = Rec->getValueAsListOfDefs("Predicates");
+ for (unsigned i = 0, e = Predicates.size(); i != e; ++i) {
+ if (Predicates[i]->getName().find("Not64Bit") != Name.npos ||
+ Predicates[i]->getName().find("In32Bit") != Name.npos) {
+ Is32Bit = true;
+ break;
+ }
+ if (Predicates[i]->getName().find("In64Bit") != Name.npos) {
+ Is64Bit = true;
+ break;
+ }
+ }
+
+ if (Form == X86Local::Pseudo || (IsCodeGenOnly && !ForceDisassemble)) {
+ ShouldBeEmitted = false;
+ return;
+ }
+
+ // Special case since there is no attribute class for 64-bit and VEX
+ if (Name == "VMASKMOVDQU64") {
+ ShouldBeEmitted = false;
+ return;
+ }
+
+ ShouldBeEmitted = true;
+}
+
+void RecognizableInstr::processInstr(DisassemblerTables &tables,
+ const CodeGenInstruction &insn,
+ InstrUID uid)
+{
+ // Ignore "asm parser only" instructions.
+ if (insn.TheDef->getValueAsBit("isAsmParserOnly"))
+ return;
+
+ RecognizableInstr recogInstr(tables, insn, uid);
+
+ if (recogInstr.shouldBeEmitted()) {
+ recogInstr.emitInstructionSpecifier();
+ recogInstr.emitDecodePath(tables);
+ }
+}
+
+#define EVEX_KB(n) (HasEVEX_KZ && HasEVEX_B ? n##_KZ_B : \
+ (HasEVEX_K && HasEVEX_B ? n##_K_B : \
+ (HasEVEX_KZ ? n##_KZ : \
+ (HasEVEX_K? n##_K : (HasEVEX_B ? n##_B : n)))))
+
+InstructionContext RecognizableInstr::insnContext() const {
+ InstructionContext insnContext;
+
+ if (Encoding == X86Local::EVEX) {
+ if (HasVEX_LPrefix && HasEVEX_L2Prefix) {
+ errs() << "Don't support VEX.L if EVEX_L2 is enabled: " << Name << "\n";
+ llvm_unreachable("Don't support VEX.L if EVEX_L2 is enabled");
+ }
+ // VEX_L & VEX_W
+ if (HasVEX_LPrefix && VEX_WPrefix == X86Local::VEX_W1) {
+ if (OpPrefix == X86Local::PD)
+ insnContext = EVEX_KB(IC_EVEX_L_W_OPSIZE);
+ else if (OpPrefix == X86Local::XS)
+ insnContext = EVEX_KB(IC_EVEX_L_W_XS);
+ else if (OpPrefix == X86Local::XD)
+ insnContext = EVEX_KB(IC_EVEX_L_W_XD);
+ else if (OpPrefix == X86Local::PS)
+ insnContext = EVEX_KB(IC_EVEX_L_W);
+ else {
+ errs() << "Instruction does not use a prefix: " << Name << "\n";
+ llvm_unreachable("Invalid prefix");
+ }
+ } else if (HasVEX_LPrefix) {
+ // VEX_L
+ if (OpPrefix == X86Local::PD)
+ insnContext = EVEX_KB(IC_EVEX_L_OPSIZE);
+ else if (OpPrefix == X86Local::XS)
+ insnContext = EVEX_KB(IC_EVEX_L_XS);
+ else if (OpPrefix == X86Local::XD)
+ insnContext = EVEX_KB(IC_EVEX_L_XD);
+ else if (OpPrefix == X86Local::PS)
+ insnContext = EVEX_KB(IC_EVEX_L);
+ else {
+ errs() << "Instruction does not use a prefix: " << Name << "\n";
+ llvm_unreachable("Invalid prefix");
+ }
+ }
+ else if (HasEVEX_L2Prefix && VEX_WPrefix == X86Local::VEX_W1) {
+ // EVEX_L2 & VEX_W
+ if (OpPrefix == X86Local::PD)
+ insnContext = EVEX_KB(IC_EVEX_L2_W_OPSIZE);
+ else if (OpPrefix == X86Local::XS)
+ insnContext = EVEX_KB(IC_EVEX_L2_W_XS);
+ else if (OpPrefix == X86Local::XD)
+ insnContext = EVEX_KB(IC_EVEX_L2_W_XD);
+ else if (OpPrefix == X86Local::PS)
+ insnContext = EVEX_KB(IC_EVEX_L2_W);
+ else {
+ errs() << "Instruction does not use a prefix: " << Name << "\n";
+ llvm_unreachable("Invalid prefix");
+ }
+ } else if (HasEVEX_L2Prefix) {
+ // EVEX_L2
+ if (OpPrefix == X86Local::PD)
+ insnContext = EVEX_KB(IC_EVEX_L2_OPSIZE);
+ else if (OpPrefix == X86Local::XD)
+ insnContext = EVEX_KB(IC_EVEX_L2_XD);
+ else if (OpPrefix == X86Local::XS)
+ insnContext = EVEX_KB(IC_EVEX_L2_XS);
+ else if (OpPrefix == X86Local::PS)
+ insnContext = EVEX_KB(IC_EVEX_L2);
+ else {
+ errs() << "Instruction does not use a prefix: " << Name << "\n";
+ llvm_unreachable("Invalid prefix");
+ }
+ }
+ else if (VEX_WPrefix == X86Local::VEX_W1) {
+ // VEX_W
+ if (OpPrefix == X86Local::PD)
+ insnContext = EVEX_KB(IC_EVEX_W_OPSIZE);
+ else if (OpPrefix == X86Local::XS)
+ insnContext = EVEX_KB(IC_EVEX_W_XS);
+ else if (OpPrefix == X86Local::XD)
+ insnContext = EVEX_KB(IC_EVEX_W_XD);
+ else if (OpPrefix == X86Local::PS)
+ insnContext = EVEX_KB(IC_EVEX_W);
+ else {
+ errs() << "Instruction does not use a prefix: " << Name << "\n";
+ llvm_unreachable("Invalid prefix");
+ }
+ }
+ // No L, no W
+ else if (OpPrefix == X86Local::PD)
+ insnContext = EVEX_KB(IC_EVEX_OPSIZE);
+ else if (OpPrefix == X86Local::XD)
+ insnContext = EVEX_KB(IC_EVEX_XD);
+ else if (OpPrefix == X86Local::XS)
+ insnContext = EVEX_KB(IC_EVEX_XS);
+ else
+ insnContext = EVEX_KB(IC_EVEX);
+ /// eof EVEX
+ } else if (Encoding == X86Local::VEX || Encoding == X86Local::XOP) {
+ if (HasVEX_LPrefix && VEX_WPrefix == X86Local::VEX_W1) {
+ if (OpPrefix == X86Local::PD)
+ insnContext = IC_VEX_L_W_OPSIZE;
+ else if (OpPrefix == X86Local::XS)
+ insnContext = IC_VEX_L_W_XS;
+ else if (OpPrefix == X86Local::XD)
+ insnContext = IC_VEX_L_W_XD;
+ else if (OpPrefix == X86Local::PS)
+ insnContext = IC_VEX_L_W;
+ else {
+ errs() << "Instruction does not use a prefix: " << Name << "\n";
+ llvm_unreachable("Invalid prefix");
+ }
+ } else if (OpPrefix == X86Local::PD && HasVEX_LPrefix)
+ insnContext = IC_VEX_L_OPSIZE;
+ else if (OpPrefix == X86Local::PD && VEX_WPrefix == X86Local::VEX_W1)
+ insnContext = IC_VEX_W_OPSIZE;
+ else if (OpPrefix == X86Local::PD)
+ insnContext = IC_VEX_OPSIZE;
+ else if (HasVEX_LPrefix && OpPrefix == X86Local::XS)
+ insnContext = IC_VEX_L_XS;
+ else if (HasVEX_LPrefix && OpPrefix == X86Local::XD)
+ insnContext = IC_VEX_L_XD;
+ else if (VEX_WPrefix == X86Local::VEX_W1 && OpPrefix == X86Local::XS)
+ insnContext = IC_VEX_W_XS;
+ else if (VEX_WPrefix == X86Local::VEX_W1 && OpPrefix == X86Local::XD)
+ insnContext = IC_VEX_W_XD;
+ else if (VEX_WPrefix == X86Local::VEX_W1 && OpPrefix == X86Local::PS)
+ insnContext = IC_VEX_W;
+ else if (HasVEX_LPrefix && OpPrefix == X86Local::PS)
+ insnContext = IC_VEX_L;
+ else if (OpPrefix == X86Local::XD)
+ insnContext = IC_VEX_XD;
+ else if (OpPrefix == X86Local::XS)
+ insnContext = IC_VEX_XS;
+ else if (OpPrefix == X86Local::PS)
+ insnContext = IC_VEX;
+ else {
+ errs() << "Instruction does not use a prefix: " << Name << "\n";
+ llvm_unreachable("Invalid prefix");
+ }
+ } else if (Is64Bit || HasREX_WPrefix || AdSize == X86Local::AdSize64) {
+ if (HasREX_WPrefix && (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD))
+ insnContext = IC_64BIT_REXW_OPSIZE;
+ else if (HasREX_WPrefix && AdSize == X86Local::AdSize32)
+ insnContext = IC_64BIT_REXW_ADSIZE;
+ else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD)
+ insnContext = IC_64BIT_XD_OPSIZE;
+ else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS)
+ insnContext = IC_64BIT_XS_OPSIZE;
+ else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize32)
+ insnContext = IC_64BIT_OPSIZE_ADSIZE;
+ else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)
+ insnContext = IC_64BIT_OPSIZE;
+ else if (AdSize == X86Local::AdSize32)
+ insnContext = IC_64BIT_ADSIZE;
+ else if (HasREX_WPrefix && OpPrefix == X86Local::XS)
+ insnContext = IC_64BIT_REXW_XS;
+ else if (HasREX_WPrefix && OpPrefix == X86Local::XD)
+ insnContext = IC_64BIT_REXW_XD;
+ else if (OpPrefix == X86Local::XD)
+ insnContext = IC_64BIT_XD;
+ else if (OpPrefix == X86Local::XS)
+ insnContext = IC_64BIT_XS;
+ else if (HasREX_WPrefix)
+ insnContext = IC_64BIT_REXW;
+ else
+ insnContext = IC_64BIT;
+ } else {
+ if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XD)
+ insnContext = IC_XD_OPSIZE;
+ else if (OpSize == X86Local::OpSize16 && OpPrefix == X86Local::XS)
+ insnContext = IC_XS_OPSIZE;
+ else if (OpSize == X86Local::OpSize16 && AdSize == X86Local::AdSize16)
+ insnContext = IC_OPSIZE_ADSIZE;
+ else if (OpSize == X86Local::OpSize16 || OpPrefix == X86Local::PD)
+ insnContext = IC_OPSIZE;
+ else if (AdSize == X86Local::AdSize16)
+ insnContext = IC_ADSIZE;
+ else if (OpPrefix == X86Local::XD)
+ insnContext = IC_XD;
+ else if (OpPrefix == X86Local::XS)
+ insnContext = IC_XS;
+ else
+ insnContext = IC;
+ }
+
+ return insnContext;
+}
+
+void RecognizableInstr::adjustOperandEncoding(OperandEncoding &encoding) {
+ // The scaling factor for AVX512 compressed displacement encoding is an
+ // instruction attribute. Adjust the ModRM encoding type to include the
+ // scale for compressed displacement.
+ if ((encoding != ENCODING_RM && encoding != ENCODING_VSIB) ||CD8_Scale == 0)
+ return;
+ encoding = (OperandEncoding)(encoding + Log2_32(CD8_Scale));
+ assert(((encoding >= ENCODING_RM && encoding <= ENCODING_RM_CD64) ||
+ (encoding >= ENCODING_VSIB && encoding <= ENCODING_VSIB_CD64)) &&
+ "Invalid CDisp scaling");
+}
+
+void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
+ unsigned &physicalOperandIndex,
+ unsigned numPhysicalOperands,
+ const unsigned *operandMapping,
+ OperandEncoding (*encodingFromString)
+ (const std::string&,
+ uint8_t OpSize)) {
+ if (optional) {
+ if (physicalOperandIndex >= numPhysicalOperands)
+ return;
+ } else {
+ assert(physicalOperandIndex < numPhysicalOperands);
+ }
+
+ while (operandMapping[operandIndex] != operandIndex) {
+ Spec->operands[operandIndex].encoding = ENCODING_DUP;
+ Spec->operands[operandIndex].type =
+ (OperandType)(TYPE_DUP0 + operandMapping[operandIndex]);
+ ++operandIndex;
+ }
+
+ const std::string &typeName = (*Operands)[operandIndex].Rec->getName();
+
+ OperandEncoding encoding = encodingFromString(typeName, OpSize);
+ // Adjust the encoding type for an operand based on the instruction.
+ adjustOperandEncoding(encoding);
+ Spec->operands[operandIndex].encoding = encoding;
+ Spec->operands[operandIndex].type = typeFromString(typeName,
+ HasREX_WPrefix, OpSize);
+
+ ++operandIndex;
+ ++physicalOperandIndex;
+}
+
+void RecognizableInstr::emitInstructionSpecifier() {
+ Spec->name = Name;
+
+ Spec->insnContext = insnContext();
+
+ const std::vector<CGIOperandList::OperandInfo> &OperandList = *Operands;
+
+ unsigned numOperands = OperandList.size();
+ unsigned numPhysicalOperands = 0;
+
+ // operandMapping maps from operands in OperandList to their originals.
+ // If operandMapping[i] != i, then the entry is a duplicate.
+ unsigned operandMapping[X86_MAX_OPERANDS];
+ assert(numOperands <= X86_MAX_OPERANDS && "X86_MAX_OPERANDS is not large enough");
+
+ for (unsigned operandIndex = 0; operandIndex < numOperands; ++operandIndex) {
+ if (!OperandList[operandIndex].Constraints.empty()) {
+ const CGIOperandList::ConstraintInfo &Constraint =
+ OperandList[operandIndex].Constraints[0];
+ if (Constraint.isTied()) {
+ operandMapping[operandIndex] = operandIndex;
+ operandMapping[Constraint.getTiedOperand()] = operandIndex;
+ } else {
+ ++numPhysicalOperands;
+ operandMapping[operandIndex] = operandIndex;
+ }
+ } else {
+ ++numPhysicalOperands;
+ operandMapping[operandIndex] = operandIndex;
+ }
+ }
+
+#define HANDLE_OPERAND(class) \
+ handleOperand(false, \
+ operandIndex, \
+ physicalOperandIndex, \
+ numPhysicalOperands, \
+ operandMapping, \
+ class##EncodingFromString);
+
+#define HANDLE_OPTIONAL(class) \
+ handleOperand(true, \
+ operandIndex, \
+ physicalOperandIndex, \
+ numPhysicalOperands, \
+ operandMapping, \
+ class##EncodingFromString);
+
+ // operandIndex should always be < numOperands
+ unsigned operandIndex = 0;
+ // physicalOperandIndex should always be < numPhysicalOperands
+ unsigned physicalOperandIndex = 0;
+
+#ifndef NDEBUG
+ // Given the set of prefix bits, how many additional operands does the
+ // instruction have?
+ unsigned additionalOperands = 0;
+ if (HasVEX_4V)
+ ++additionalOperands;
+ if (HasEVEX_K)
+ ++additionalOperands;
+#endif
+
+ switch (Form) {
+ default: llvm_unreachable("Unhandled form");
+ case X86Local::RawFrmSrc:
+ HANDLE_OPERAND(relocation);
+ return;
+ case X86Local::RawFrmDst:
+ HANDLE_OPERAND(relocation);
+ return;
+ case X86Local::RawFrmDstSrc:
+ HANDLE_OPERAND(relocation);
+ HANDLE_OPERAND(relocation);
+ return;
+ case X86Local::RawFrm:
+ // Operand 1 (optional) is an address or immediate.
+ assert(numPhysicalOperands <= 1 &&
+ "Unexpected number of operands for RawFrm");
+ HANDLE_OPTIONAL(relocation)
+ break;
+ case X86Local::RawFrmMemOffs:
+ // Operand 1 is an address.
+ HANDLE_OPERAND(relocation);
+ break;
+ case X86Local::AddRegFrm:
+ // Operand 1 is added to the opcode.
+ // Operand 2 (optional) is an address.
+ assert(numPhysicalOperands >= 1 && numPhysicalOperands <= 2 &&
+ "Unexpected number of operands for AddRegFrm");
+ HANDLE_OPERAND(opcodeModifier)
+ HANDLE_OPTIONAL(relocation)
+ break;
+ case X86Local::MRMDestReg:
+ // Operand 1 is a register operand in the R/M field.
+ // - In AVX512 there may be a mask operand here -
+ // Operand 2 is a register operand in the Reg/Opcode field.
+ // - In AVX, there is a register operand in the VEX.vvvv field here -
+ // Operand 3 (optional) is an immediate.
+ assert(numPhysicalOperands >= 2 + additionalOperands &&
+ numPhysicalOperands <= 3 + additionalOperands &&
+ "Unexpected number of operands for MRMDestRegFrm");
+
+ HANDLE_OPERAND(rmRegister)
+ if (HasEVEX_K)
+ HANDLE_OPERAND(writemaskRegister)
+
+ if (HasVEX_4V)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPERAND(vvvvRegister)
+
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPTIONAL(immediate)
+ break;
+ case X86Local::MRMDestMem:
+ // Operand 1 is a memory operand (possibly SIB-extended)
+ // Operand 2 is a register operand in the Reg/Opcode field.
+ // - In AVX, there is a register operand in the VEX.vvvv field here -
+ // Operand 3 (optional) is an immediate.
+ assert(numPhysicalOperands >= 2 + additionalOperands &&
+ numPhysicalOperands <= 3 + additionalOperands &&
+ "Unexpected number of operands for MRMDestMemFrm with VEX_4V");
+
+ HANDLE_OPERAND(memory)
+
+ if (HasEVEX_K)
+ HANDLE_OPERAND(writemaskRegister)
+
+ if (HasVEX_4V)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPERAND(vvvvRegister)
+
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPTIONAL(immediate)
+ break;
+ case X86Local::MRMSrcReg:
+ // Operand 1 is a register operand in the Reg/Opcode field.
+ // Operand 2 is a register operand in the R/M field.
+ // - In AVX, there is a register operand in the VEX.vvvv field here -
+ // Operand 3 (optional) is an immediate.
+ // Operand 4 (optional) is an immediate.
+
+ assert(numPhysicalOperands >= 2 + additionalOperands &&
+ numPhysicalOperands <= 4 + additionalOperands &&
+ "Unexpected number of operands for MRMSrcRegFrm");
+
+ HANDLE_OPERAND(roRegister)
+
+ if (HasEVEX_K)
+ HANDLE_OPERAND(writemaskRegister)
+
+ if (HasVEX_4V)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPERAND(vvvvRegister)
+
+ HANDLE_OPERAND(rmRegister)
+ HANDLE_OPTIONAL(immediate)
+ HANDLE_OPTIONAL(immediate) // above might be a register in 7:4
+ HANDLE_OPTIONAL(immediate)
+ break;
+ case X86Local::MRMSrcReg4VOp3:
+ assert(numPhysicalOperands == 3 &&
+ "Unexpected number of operands for MRMSrcRegFrm");
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPERAND(rmRegister)
+ HANDLE_OPERAND(vvvvRegister)
+ break;
+ case X86Local::MRMSrcRegOp4:
+ assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 &&
+ "Unexpected number of operands for MRMSrcRegOp4Frm");
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPERAND(vvvvRegister)
+ HANDLE_OPERAND(immediate) // Register in imm[7:4]
+ HANDLE_OPERAND(rmRegister)
+ HANDLE_OPTIONAL(immediate)
+ break;
+ case X86Local::MRMSrcMem:
+ // Operand 1 is a register operand in the Reg/Opcode field.
+ // Operand 2 is a memory operand (possibly SIB-extended)
+ // - In AVX, there is a register operand in the VEX.vvvv field here -
+ // Operand 3 (optional) is an immediate.
+
+ assert(numPhysicalOperands >= 2 + additionalOperands &&
+ numPhysicalOperands <= 4 + additionalOperands &&
+ "Unexpected number of operands for MRMSrcMemFrm");
+
+ HANDLE_OPERAND(roRegister)
+
+ if (HasEVEX_K)
+ HANDLE_OPERAND(writemaskRegister)
+
+ if (HasVEX_4V)
+ // FIXME: In AVX, the register below becomes the one encoded
+ // in ModRMVEX and the one above the one in the VEX.VVVV field
+ HANDLE_OPERAND(vvvvRegister)
+
+ HANDLE_OPERAND(memory)
+ HANDLE_OPTIONAL(immediate)
+ HANDLE_OPTIONAL(immediate) // above might be a register in 7:4
+ break;
+ case X86Local::MRMSrcMem4VOp3:
+ assert(numPhysicalOperands == 3 &&
+ "Unexpected number of operands for MRMSrcMemFrm");
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPERAND(memory)
+ HANDLE_OPERAND(vvvvRegister)
+ break;
+ case X86Local::MRMSrcMemOp4:
+ assert(numPhysicalOperands >= 4 && numPhysicalOperands <= 5 &&
+ "Unexpected number of operands for MRMSrcMemOp4Frm");
+ HANDLE_OPERAND(roRegister)
+ HANDLE_OPERAND(vvvvRegister)
+ HANDLE_OPERAND(immediate) // Register in imm[7:4]
+ HANDLE_OPERAND(memory)
+ HANDLE_OPTIONAL(immediate)
+ break;
+ case X86Local::MRMXr:
+ case X86Local::MRM0r:
+ case X86Local::MRM1r:
+ case X86Local::MRM2r:
+ case X86Local::MRM3r:
+ case X86Local::MRM4r:
+ case X86Local::MRM5r:
+ case X86Local::MRM6r:
+ case X86Local::MRM7r:
+ // Operand 1 is a register operand in the R/M field.
+ // Operand 2 (optional) is an immediate or relocation.
+ // Operand 3 (optional) is an immediate.
+ assert(numPhysicalOperands >= 0 + additionalOperands &&
+ numPhysicalOperands <= 3 + additionalOperands &&
+ "Unexpected number of operands for MRMnr");
+
+ if (HasVEX_4V)
+ HANDLE_OPERAND(vvvvRegister)
+
+ if (HasEVEX_K)
+ HANDLE_OPERAND(writemaskRegister)
+ HANDLE_OPTIONAL(rmRegister)
+ HANDLE_OPTIONAL(relocation)
+ HANDLE_OPTIONAL(immediate)
+ break;
+ case X86Local::MRMXm:
+ case X86Local::MRM0m:
+ case X86Local::MRM1m:
+ case X86Local::MRM2m:
+ case X86Local::MRM3m:
+ case X86Local::MRM4m:
+ case X86Local::MRM5m:
+ case X86Local::MRM6m:
+ case X86Local::MRM7m:
+ // Operand 1 is a memory operand (possibly SIB-extended)
+ // Operand 2 (optional) is an immediate or relocation.
+ assert(numPhysicalOperands >= 1 + additionalOperands &&
+ numPhysicalOperands <= 2 + additionalOperands &&
+ "Unexpected number of operands for MRMnm");
+
+ if (HasVEX_4V)
+ HANDLE_OPERAND(vvvvRegister)
+ if (HasEVEX_K)
+ HANDLE_OPERAND(writemaskRegister)
+ HANDLE_OPERAND(memory)
+ HANDLE_OPTIONAL(relocation)
+ break;
+ case X86Local::RawFrmImm8:
+ // operand 1 is a 16-bit immediate
+ // operand 2 is an 8-bit immediate
+ assert(numPhysicalOperands == 2 &&
+ "Unexpected number of operands for X86Local::RawFrmImm8");
+ HANDLE_OPERAND(immediate)
+ HANDLE_OPERAND(immediate)
+ break;
+ case X86Local::RawFrmImm16:
+ // operand 1 is a 16-bit immediate
+ // operand 2 is a 16-bit immediate
+ HANDLE_OPERAND(immediate)
+ HANDLE_OPERAND(immediate)
+ break;
+ case X86Local::MRM_F8:
+ if (Opcode == 0xc6) {
+ assert(numPhysicalOperands == 1 &&
+ "Unexpected number of operands for X86Local::MRM_F8");
+ HANDLE_OPERAND(immediate)
+ } else if (Opcode == 0xc7) {
+ assert(numPhysicalOperands == 1 &&
+ "Unexpected number of operands for X86Local::MRM_F8");
+ HANDLE_OPERAND(relocation)
+ }
+ break;
+ case X86Local::MRM_C0: case X86Local::MRM_C1: case X86Local::MRM_C2:
+ case X86Local::MRM_C3: case X86Local::MRM_C4: case X86Local::MRM_C8:
+ case X86Local::MRM_C9: case X86Local::MRM_CA: case X86Local::MRM_CB:
+ case X86Local::MRM_CF: case X86Local::MRM_D0: case X86Local::MRM_D1:
+ case X86Local::MRM_D4: case X86Local::MRM_D5: case X86Local::MRM_D6:
+ case X86Local::MRM_D7: case X86Local::MRM_D8: case X86Local::MRM_D9:
+ case X86Local::MRM_DA: case X86Local::MRM_DB: case X86Local::MRM_DC:
+ case X86Local::MRM_DD: case X86Local::MRM_DE: case X86Local::MRM_DF:
+ case X86Local::MRM_E0: case X86Local::MRM_E1: case X86Local::MRM_E2:
+ case X86Local::MRM_E3: case X86Local::MRM_E4: case X86Local::MRM_E5:
+ case X86Local::MRM_E8: case X86Local::MRM_E9: case X86Local::MRM_EA:
+ case X86Local::MRM_EB: case X86Local::MRM_EC: case X86Local::MRM_ED:
+ case X86Local::MRM_EE: case X86Local::MRM_EF: case X86Local::MRM_F0:
+ case X86Local::MRM_F1: case X86Local::MRM_F2: case X86Local::MRM_F3:
+ case X86Local::MRM_F4: case X86Local::MRM_F5: case X86Local::MRM_F6:
+ case X86Local::MRM_F7: case X86Local::MRM_F9: case X86Local::MRM_FA:
+ case X86Local::MRM_FB: case X86Local::MRM_FC: case X86Local::MRM_FD:
+ case X86Local::MRM_FE: case X86Local::MRM_FF:
+ // Ignored.
+ break;
+ }
+
+ #undef HANDLE_OPERAND
+ #undef HANDLE_OPTIONAL
+}
+
+void RecognizableInstr::emitDecodePath(DisassemblerTables &tables) const {
+ // Special cases where the LLVM tables are not complete
+
+#define MAP(from, to) \
+ case X86Local::MRM_##from:
+
+ OpcodeType opcodeType = (OpcodeType)-1;
+
+ ModRMFilter* filter = nullptr;
+ uint8_t opcodeToSet = 0;
+
+ switch (OpMap) {
+ default: llvm_unreachable("Invalid map!");
+ case X86Local::OB:
+ case X86Local::TB:
+ case X86Local::T8:
+ case X86Local::TA:
+ case X86Local::XOP8:
+ case X86Local::XOP9:
+ case X86Local::XOPA:
+ switch (OpMap) {
+ default: llvm_unreachable("Unexpected map!");
+ case X86Local::OB: opcodeType = ONEBYTE; break;
+ case X86Local::TB: opcodeType = TWOBYTE; break;
+ case X86Local::T8: opcodeType = THREEBYTE_38; break;
+ case X86Local::TA: opcodeType = THREEBYTE_3A; break;
+ case X86Local::XOP8: opcodeType = XOP8_MAP; break;
+ case X86Local::XOP9: opcodeType = XOP9_MAP; break;
+ case X86Local::XOPA: opcodeType = XOPA_MAP; break;
+ }
+
+ switch (Form) {
+ default: llvm_unreachable("Invalid form!");
+ case X86Local::Pseudo: llvm_unreachable("Pseudo should not be emitted!");
+ case X86Local::RawFrm:
+ case X86Local::AddRegFrm:
+ case X86Local::RawFrmMemOffs:
+ case X86Local::RawFrmSrc:
+ case X86Local::RawFrmDst:
+ case X86Local::RawFrmDstSrc:
+ case X86Local::RawFrmImm8:
+ case X86Local::RawFrmImm16:
+ filter = new DumbFilter();
+ break;
+ case X86Local::MRMDestReg:
+ case X86Local::MRMSrcReg:
+ case X86Local::MRMSrcReg4VOp3:
+ case X86Local::MRMSrcRegOp4:
+ case X86Local::MRMXr:
+ filter = new ModFilter(true);
+ break;
+ case X86Local::MRMDestMem:
+ case X86Local::MRMSrcMem:
+ case X86Local::MRMSrcMem4VOp3:
+ case X86Local::MRMSrcMemOp4:
+ case X86Local::MRMXm:
+ filter = new ModFilter(false);
+ break;
+ case X86Local::MRM0r: case X86Local::MRM1r:
+ case X86Local::MRM2r: case X86Local::MRM3r:
+ case X86Local::MRM4r: case X86Local::MRM5r:
+ case X86Local::MRM6r: case X86Local::MRM7r:
+ filter = new ExtendedFilter(true, Form - X86Local::MRM0r);
+ break;
+ case X86Local::MRM0m: case X86Local::MRM1m:
+ case X86Local::MRM2m: case X86Local::MRM3m:
+ case X86Local::MRM4m: case X86Local::MRM5m:
+ case X86Local::MRM6m: case X86Local::MRM7m:
+ filter = new ExtendedFilter(false, Form - X86Local::MRM0m);
+ break;
+ MRM_MAPPING
+ filter = new ExactFilter(0xC0 + Form - X86Local::MRM_C0); \
+ break;
+ } // switch (Form)
+
+ opcodeToSet = Opcode;
+ break;
+ } // switch (OpMap)
+
+ unsigned AddressSize = 0;
+ switch (AdSize) {
+ case X86Local::AdSize16: AddressSize = 16; break;
+ case X86Local::AdSize32: AddressSize = 32; break;
+ case X86Local::AdSize64: AddressSize = 64; break;
+ }
+
+ assert(opcodeType != (OpcodeType)-1 &&
+ "Opcode type not set");
+ assert(filter && "Filter not set");
+
+ if (Form == X86Local::AddRegFrm) {
+ assert(((opcodeToSet & 7) == 0) &&
+ "ADDREG_FRM opcode not aligned");
+
+ uint8_t currentOpcode;
+
+ for (currentOpcode = opcodeToSet;
+ currentOpcode < opcodeToSet + 8;
+ ++currentOpcode)
+ tables.setTableFields(opcodeType,
+ insnContext(),
+ currentOpcode,
+ *filter,
+ UID, Is32Bit, IgnoresVEX_L, AddressSize);
+ } else {
+ tables.setTableFields(opcodeType,
+ insnContext(),
+ opcodeToSet,
+ *filter,
+ UID, Is32Bit, IgnoresVEX_L, AddressSize);
+ }
+
+ delete filter;
+
+#undef MAP
+}
+
+#define TYPE(str, type) if (s == str) return type;
+OperandType RecognizableInstr::typeFromString(const std::string &s,
+ bool hasREX_WPrefix,
+ uint8_t OpSize) {
+ if(hasREX_WPrefix) {
+ // For instructions with a REX_W prefix, a declared 32-bit register encoding
+ // is special.
+ TYPE("GR32", TYPE_R32)
+ }
+ if(OpSize == X86Local::OpSize16) {
+ // For OpSize16 instructions, a declared 16-bit register or
+ // immediate encoding is special.
+ TYPE("GR16", TYPE_Rv)
+ } else if(OpSize == X86Local::OpSize32) {
+ // For OpSize32 instructions, a declared 32-bit register or
+ // immediate encoding is special.
+ TYPE("GR32", TYPE_Rv)
+ }
+ TYPE("i16mem", TYPE_M)
+ TYPE("i16imm", TYPE_IMM)
+ TYPE("i16i8imm", TYPE_IMM)
+ TYPE("GR16", TYPE_R16)
+ TYPE("i32mem", TYPE_M)
+ TYPE("i32imm", TYPE_IMM)
+ TYPE("i32i8imm", TYPE_IMM)
+ TYPE("GR32", TYPE_R32)
+ TYPE("GR32orGR64", TYPE_R32)
+ TYPE("i64mem", TYPE_M)
+ TYPE("i64i32imm", TYPE_IMM)
+ TYPE("i64i8imm", TYPE_IMM)
+ TYPE("GR64", TYPE_R64)
+ TYPE("i8mem", TYPE_M)
+ TYPE("i8imm", TYPE_IMM)
+ TYPE("u8imm", TYPE_UIMM8)
+ TYPE("i32u8imm", TYPE_UIMM8)
+ TYPE("GR8", TYPE_R8)
+ TYPE("VR128", TYPE_XMM)
+ TYPE("VR128X", TYPE_XMM)
+ TYPE("f128mem", TYPE_M)
+ TYPE("f256mem", TYPE_M)
+ TYPE("f512mem", TYPE_M)
+ TYPE("FR128", TYPE_XMM)
+ TYPE("FR64", TYPE_XMM)
+ TYPE("FR64X", TYPE_XMM)
+ TYPE("f64mem", TYPE_M)
+ TYPE("sdmem", TYPE_M)
+ TYPE("FR32", TYPE_XMM)
+ TYPE("FR32X", TYPE_XMM)
+ TYPE("f32mem", TYPE_M)
+ TYPE("ssmem", TYPE_M)
+ TYPE("RST", TYPE_ST)
+ TYPE("i128mem", TYPE_M)
+ TYPE("i256mem", TYPE_M)
+ TYPE("i512mem", TYPE_M)
+ TYPE("i64i32imm_pcrel", TYPE_REL)
+ TYPE("i16imm_pcrel", TYPE_REL)
+ TYPE("i32imm_pcrel", TYPE_REL)
+ TYPE("SSECC", TYPE_IMM3)
+ TYPE("XOPCC", TYPE_IMM3)
+ TYPE("AVXCC", TYPE_IMM5)
+ TYPE("AVX512ICC", TYPE_AVX512ICC)
+ TYPE("AVX512RC", TYPE_IMM)
+ TYPE("brtarget32", TYPE_REL)
+ TYPE("brtarget16", TYPE_REL)
+ TYPE("brtarget8", TYPE_REL)
+ TYPE("f80mem", TYPE_M)
+ TYPE("lea64_32mem", TYPE_M)
+ TYPE("lea64mem", TYPE_M)
+ TYPE("VR64", TYPE_MM64)
+ TYPE("i64imm", TYPE_IMM)
+ TYPE("anymem", TYPE_M)
+ TYPE("opaque32mem", TYPE_M)
+ TYPE("opaque48mem", TYPE_M)
+ TYPE("opaque80mem", TYPE_M)
+ TYPE("opaque512mem", TYPE_M)
+ TYPE("SEGMENT_REG", TYPE_SEGMENTREG)
+ TYPE("DEBUG_REG", TYPE_DEBUGREG)
+ TYPE("CONTROL_REG", TYPE_CONTROLREG)
+ TYPE("srcidx8", TYPE_SRCIDX)
+ TYPE("srcidx16", TYPE_SRCIDX)
+ TYPE("srcidx32", TYPE_SRCIDX)
+ TYPE("srcidx64", TYPE_SRCIDX)
+ TYPE("dstidx8", TYPE_DSTIDX)
+ TYPE("dstidx16", TYPE_DSTIDX)
+ TYPE("dstidx32", TYPE_DSTIDX)
+ TYPE("dstidx64", TYPE_DSTIDX)
+ TYPE("offset16_8", TYPE_MOFFS)
+ TYPE("offset16_16", TYPE_MOFFS)
+ TYPE("offset16_32", TYPE_MOFFS)
+ TYPE("offset32_8", TYPE_MOFFS)
+ TYPE("offset32_16", TYPE_MOFFS)
+ TYPE("offset32_32", TYPE_MOFFS)
+ TYPE("offset32_64", TYPE_MOFFS)
+ TYPE("offset64_8", TYPE_MOFFS)
+ TYPE("offset64_16", TYPE_MOFFS)
+ TYPE("offset64_32", TYPE_MOFFS)
+ TYPE("offset64_64", TYPE_MOFFS)
+ TYPE("VR256", TYPE_YMM)
+ TYPE("VR256X", TYPE_YMM)
+ TYPE("VR512", TYPE_ZMM)
+ TYPE("VK1", TYPE_VK)
+ TYPE("VK1WM", TYPE_VK)
+ TYPE("VK2", TYPE_VK)
+ TYPE("VK2WM", TYPE_VK)
+ TYPE("VK4", TYPE_VK)
+ TYPE("VK4WM", TYPE_VK)
+ TYPE("VK8", TYPE_VK)
+ TYPE("VK8WM", TYPE_VK)
+ TYPE("VK16", TYPE_VK)
+ TYPE("VK16WM", TYPE_VK)
+ TYPE("VK32", TYPE_VK)
+ TYPE("VK32WM", TYPE_VK)
+ TYPE("VK64", TYPE_VK)
+ TYPE("VK64WM", TYPE_VK)
+ TYPE("GR32_NOAX", TYPE_Rv)
+ TYPE("vx64mem", TYPE_M)
+ TYPE("vx128mem", TYPE_M)
+ TYPE("vx256mem", TYPE_M)
+ TYPE("vy128mem", TYPE_M)
+ TYPE("vy256mem", TYPE_M)
+ TYPE("vx64xmem", TYPE_M)
+ TYPE("vx128xmem", TYPE_M)
+ TYPE("vx256xmem", TYPE_M)
+ TYPE("vy128xmem", TYPE_M)
+ TYPE("vy256xmem", TYPE_M)
+ TYPE("vy512mem", TYPE_M)
+ TYPE("vz256xmem", TYPE_M)
+ TYPE("vz512mem", TYPE_M)
+ TYPE("BNDR", TYPE_BNDR)
+ errs() << "Unhandled type string " << s << "\n";
+ llvm_unreachable("Unhandled type string");
+}
+#undef TYPE
+
+#define ENCODING(str, encoding) if (s == str) return encoding;
+OperandEncoding
+RecognizableInstr::immediateEncodingFromString(const std::string &s,
+ uint8_t OpSize) {
+ if(OpSize != X86Local::OpSize16) {
+ // For instructions without an OpSize prefix, a declared 16-bit register or
+ // immediate encoding is special.
+ ENCODING("i16imm", ENCODING_IW)
+ }
+ ENCODING("i32i8imm", ENCODING_IB)
+ ENCODING("SSECC", ENCODING_IB)
+ ENCODING("XOPCC", ENCODING_IB)
+ ENCODING("AVXCC", ENCODING_IB)
+ ENCODING("AVX512ICC", ENCODING_IB)
+ ENCODING("AVX512RC", ENCODING_IB)
+ ENCODING("i16imm", ENCODING_Iv)
+ ENCODING("i16i8imm", ENCODING_IB)
+ ENCODING("i32imm", ENCODING_Iv)
+ ENCODING("i64i32imm", ENCODING_ID)
+ ENCODING("i64i8imm", ENCODING_IB)
+ ENCODING("i8imm", ENCODING_IB)
+ ENCODING("u8imm", ENCODING_IB)
+ ENCODING("i32u8imm", ENCODING_IB)
+ // This is not a typo. Instructions like BLENDVPD put
+ // register IDs in 8-bit immediates nowadays.
+ ENCODING("FR32", ENCODING_IB)
+ ENCODING("FR64", ENCODING_IB)
+ ENCODING("FR128", ENCODING_IB)
+ ENCODING("VR128", ENCODING_IB)
+ ENCODING("VR256", ENCODING_IB)
+ ENCODING("FR32X", ENCODING_IB)
+ ENCODING("FR64X", ENCODING_IB)
+ ENCODING("VR128X", ENCODING_IB)
+ ENCODING("VR256X", ENCODING_IB)
+ ENCODING("VR512", ENCODING_IB)
+ errs() << "Unhandled immediate encoding " << s << "\n";
+ llvm_unreachable("Unhandled immediate encoding");
+}
+
+OperandEncoding
+RecognizableInstr::rmRegisterEncodingFromString(const std::string &s,
+ uint8_t OpSize) {
+ ENCODING("RST", ENCODING_FP)
+ ENCODING("GR16", ENCODING_RM)
+ ENCODING("GR32", ENCODING_RM)
+ ENCODING("GR32orGR64", ENCODING_RM)
+ ENCODING("GR64", ENCODING_RM)
+ ENCODING("GR8", ENCODING_RM)
+ ENCODING("VR128", ENCODING_RM)
+ ENCODING("VR128X", ENCODING_RM)
+ ENCODING("FR128", ENCODING_RM)
+ ENCODING("FR64", ENCODING_RM)
+ ENCODING("FR32", ENCODING_RM)
+ ENCODING("FR64X", ENCODING_RM)
+ ENCODING("FR32X", ENCODING_RM)
+ ENCODING("VR64", ENCODING_RM)
+ ENCODING("VR256", ENCODING_RM)
+ ENCODING("VR256X", ENCODING_RM)
+ ENCODING("VR512", ENCODING_RM)
+ ENCODING("VK1", ENCODING_RM)
+ ENCODING("VK2", ENCODING_RM)
+ ENCODING("VK4", ENCODING_RM)
+ ENCODING("VK8", ENCODING_RM)
+ ENCODING("VK16", ENCODING_RM)
+ ENCODING("VK32", ENCODING_RM)
+ ENCODING("VK64", ENCODING_RM)
+ ENCODING("BNDR", ENCODING_RM)
+ errs() << "Unhandled R/M register encoding " << s << "\n";
+ llvm_unreachable("Unhandled R/M register encoding");
+}
+
+OperandEncoding
+RecognizableInstr::roRegisterEncodingFromString(const std::string &s,
+ uint8_t OpSize) {
+ ENCODING("GR16", ENCODING_REG)
+ ENCODING("GR32", ENCODING_REG)
+ ENCODING("GR32orGR64", ENCODING_REG)
+ ENCODING("GR64", ENCODING_REG)
+ ENCODING("GR8", ENCODING_REG)
+ ENCODING("VR128", ENCODING_REG)
+ ENCODING("FR128", ENCODING_REG)
+ ENCODING("FR64", ENCODING_REG)
+ ENCODING("FR32", ENCODING_REG)
+ ENCODING("VR64", ENCODING_REG)
+ ENCODING("SEGMENT_REG", ENCODING_REG)
+ ENCODING("DEBUG_REG", ENCODING_REG)
+ ENCODING("CONTROL_REG", ENCODING_REG)
+ ENCODING("VR256", ENCODING_REG)
+ ENCODING("VR256X", ENCODING_REG)
+ ENCODING("VR128X", ENCODING_REG)
+ ENCODING("FR64X", ENCODING_REG)
+ ENCODING("FR32X", ENCODING_REG)
+ ENCODING("VR512", ENCODING_REG)
+ ENCODING("VK1", ENCODING_REG)
+ ENCODING("VK2", ENCODING_REG)
+ ENCODING("VK4", ENCODING_REG)
+ ENCODING("VK8", ENCODING_REG)
+ ENCODING("VK16", ENCODING_REG)
+ ENCODING("VK32", ENCODING_REG)
+ ENCODING("VK64", ENCODING_REG)
+ ENCODING("VK1WM", ENCODING_REG)
+ ENCODING("VK2WM", ENCODING_REG)
+ ENCODING("VK4WM", ENCODING_REG)
+ ENCODING("VK8WM", ENCODING_REG)
+ ENCODING("VK16WM", ENCODING_REG)
+ ENCODING("VK32WM", ENCODING_REG)
+ ENCODING("VK64WM", ENCODING_REG)
+ ENCODING("BNDR", ENCODING_REG)
+ errs() << "Unhandled reg/opcode register encoding " << s << "\n";
+ llvm_unreachable("Unhandled reg/opcode register encoding");
+}
+
+OperandEncoding
+RecognizableInstr::vvvvRegisterEncodingFromString(const std::string &s,
+ uint8_t OpSize) {
+ ENCODING("GR32", ENCODING_VVVV)
+ ENCODING("GR64", ENCODING_VVVV)
+ ENCODING("FR32", ENCODING_VVVV)
+ ENCODING("FR128", ENCODING_VVVV)
+ ENCODING("FR64", ENCODING_VVVV)
+ ENCODING("VR128", ENCODING_VVVV)
+ ENCODING("VR256", ENCODING_VVVV)
+ ENCODING("FR32X", ENCODING_VVVV)
+ ENCODING("FR64X", ENCODING_VVVV)
+ ENCODING("VR128X", ENCODING_VVVV)
+ ENCODING("VR256X", ENCODING_VVVV)
+ ENCODING("VR512", ENCODING_VVVV)
+ ENCODING("VK1", ENCODING_VVVV)
+ ENCODING("VK2", ENCODING_VVVV)
+ ENCODING("VK4", ENCODING_VVVV)
+ ENCODING("VK8", ENCODING_VVVV)
+ ENCODING("VK16", ENCODING_VVVV)
+ ENCODING("VK32", ENCODING_VVVV)
+ ENCODING("VK64", ENCODING_VVVV)
+ errs() << "Unhandled VEX.vvvv register encoding " << s << "\n";
+ llvm_unreachable("Unhandled VEX.vvvv register encoding");
+}
+
+OperandEncoding
+RecognizableInstr::writemaskRegisterEncodingFromString(const std::string &s,
+ uint8_t OpSize) {
+ ENCODING("VK1WM", ENCODING_WRITEMASK)
+ ENCODING("VK2WM", ENCODING_WRITEMASK)
+ ENCODING("VK4WM", ENCODING_WRITEMASK)
+ ENCODING("VK8WM", ENCODING_WRITEMASK)
+ ENCODING("VK16WM", ENCODING_WRITEMASK)
+ ENCODING("VK32WM", ENCODING_WRITEMASK)
+ ENCODING("VK64WM", ENCODING_WRITEMASK)
+ errs() << "Unhandled mask register encoding " << s << "\n";
+ llvm_unreachable("Unhandled mask register encoding");
+}
+
+OperandEncoding
+RecognizableInstr::memoryEncodingFromString(const std::string &s,
+ uint8_t OpSize) {
+ ENCODING("i16mem", ENCODING_RM)
+ ENCODING("i32mem", ENCODING_RM)
+ ENCODING("i64mem", ENCODING_RM)
+ ENCODING("i8mem", ENCODING_RM)
+ ENCODING("ssmem", ENCODING_RM)
+ ENCODING("sdmem", ENCODING_RM)
+ ENCODING("f128mem", ENCODING_RM)
+ ENCODING("f256mem", ENCODING_RM)
+ ENCODING("f512mem", ENCODING_RM)
+ ENCODING("f64mem", ENCODING_RM)
+ ENCODING("f32mem", ENCODING_RM)
+ ENCODING("i128mem", ENCODING_RM)
+ ENCODING("i256mem", ENCODING_RM)
+ ENCODING("i512mem", ENCODING_RM)
+ ENCODING("f80mem", ENCODING_RM)
+ ENCODING("lea64_32mem", ENCODING_RM)
+ ENCODING("lea64mem", ENCODING_RM)
+ ENCODING("anymem", ENCODING_RM)
+ ENCODING("opaque32mem", ENCODING_RM)
+ ENCODING("opaque48mem", ENCODING_RM)
+ ENCODING("opaque80mem", ENCODING_RM)
+ ENCODING("opaque512mem", ENCODING_RM)
+ ENCODING("vx64mem", ENCODING_VSIB)
+ ENCODING("vx128mem", ENCODING_VSIB)
+ ENCODING("vx256mem", ENCODING_VSIB)
+ ENCODING("vy128mem", ENCODING_VSIB)
+ ENCODING("vy256mem", ENCODING_VSIB)
+ ENCODING("vx64xmem", ENCODING_VSIB)
+ ENCODING("vx128xmem", ENCODING_VSIB)
+ ENCODING("vx256xmem", ENCODING_VSIB)
+ ENCODING("vy128xmem", ENCODING_VSIB)
+ ENCODING("vy256xmem", ENCODING_VSIB)
+ ENCODING("vy512mem", ENCODING_VSIB)
+ ENCODING("vz256xmem", ENCODING_VSIB)
+ ENCODING("vz512mem", ENCODING_VSIB)
+ errs() << "Unhandled memory encoding " << s << "\n";
+ llvm_unreachable("Unhandled memory encoding");
+}
+
+OperandEncoding
+RecognizableInstr::relocationEncodingFromString(const std::string &s,
+ uint8_t OpSize) {
+ if(OpSize != X86Local::OpSize16) {
+ // For instructions without an OpSize prefix, a declared 16-bit register or
+ // immediate encoding is special.
+ ENCODING("i16imm", ENCODING_IW)
+ }
+ ENCODING("i16imm", ENCODING_Iv)
+ ENCODING("i16i8imm", ENCODING_IB)
+ ENCODING("i32imm", ENCODING_Iv)
+ ENCODING("i32i8imm", ENCODING_IB)
+ ENCODING("i64i32imm", ENCODING_ID)
+ ENCODING("i64i8imm", ENCODING_IB)
+ ENCODING("i8imm", ENCODING_IB)
+ ENCODING("u8imm", ENCODING_IB)
+ ENCODING("i32u8imm", ENCODING_IB)
+ ENCODING("i64i32imm_pcrel", ENCODING_ID)
+ ENCODING("i16imm_pcrel", ENCODING_IW)
+ ENCODING("i32imm_pcrel", ENCODING_ID)
+ ENCODING("brtarget32", ENCODING_Iv)
+ ENCODING("brtarget16", ENCODING_Iv)
+ ENCODING("brtarget8", ENCODING_IB)
+ ENCODING("i64imm", ENCODING_IO)
+ ENCODING("offset16_8", ENCODING_Ia)
+ ENCODING("offset16_16", ENCODING_Ia)
+ ENCODING("offset16_32", ENCODING_Ia)
+ ENCODING("offset32_8", ENCODING_Ia)
+ ENCODING("offset32_16", ENCODING_Ia)
+ ENCODING("offset32_32", ENCODING_Ia)
+ ENCODING("offset32_64", ENCODING_Ia)
+ ENCODING("offset64_8", ENCODING_Ia)
+ ENCODING("offset64_16", ENCODING_Ia)
+ ENCODING("offset64_32", ENCODING_Ia)
+ ENCODING("offset64_64", ENCODING_Ia)
+ ENCODING("srcidx8", ENCODING_SI)
+ ENCODING("srcidx16", ENCODING_SI)
+ ENCODING("srcidx32", ENCODING_SI)
+ ENCODING("srcidx64", ENCODING_SI)
+ ENCODING("dstidx8", ENCODING_DI)
+ ENCODING("dstidx16", ENCODING_DI)
+ ENCODING("dstidx32", ENCODING_DI)
+ ENCODING("dstidx64", ENCODING_DI)
+ errs() << "Unhandled relocation encoding " << s << "\n";
+ llvm_unreachable("Unhandled relocation encoding");
+}
+
+OperandEncoding
+RecognizableInstr::opcodeModifierEncodingFromString(const std::string &s,
+ uint8_t OpSize) {
+ ENCODING("GR32", ENCODING_Rv)
+ ENCODING("GR64", ENCODING_RO)
+ ENCODING("GR16", ENCODING_Rv)
+ ENCODING("GR8", ENCODING_RB)
+ ENCODING("GR32_NOAX", ENCODING_Rv)
+ errs() << "Unhandled opcode modifier encoding " << s << "\n";
+ llvm_unreachable("Unhandled opcode modifier encoding");
+}
+#undef ENCODING
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
new file mode 100644
index 000000000000..91ed928540c3
--- /dev/null
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
@@ -0,0 +1,233 @@
+//===- X86RecognizableInstr.h - Disassembler instruction spec ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is part of the X86 Disassembler Emitter.
+// It contains the interface of a single recognizable instruction.
+// Documentation for the disassembler emitter in general can be found in
+// X86DisasemblerEmitter.h.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H
+#define LLVM_UTILS_TABLEGEN_X86RECOGNIZABLEINSTR_H
+
+#include "CodeGenTarget.h"
+#include "X86DisassemblerTables.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/TableGen/Record.h"
+
+namespace llvm {
+
+namespace X86Disassembler {
+
+/// RecognizableInstr - Encapsulates all information required to decode a single
+/// instruction, as extracted from the LLVM instruction tables. Has methods
+/// to interpret the information available in the LLVM tables, and to emit the
+/// instruction into DisassemblerTables.
+class RecognizableInstr {
+private:
+ /// The opcode of the instruction, as used in an MCInst
+ InstrUID UID;
+ /// The record from the .td files corresponding to this instruction
+ const Record* Rec;
+ /// The OpPrefix field from the record
+ uint8_t OpPrefix;
+ /// The OpMap field from the record
+ uint8_t OpMap;
+ /// The opcode field from the record; this is the opcode used in the Intel
+ /// encoding and therefore distinct from the UID
+ uint8_t Opcode;
+ /// The form field from the record
+ uint8_t Form;
+ // The encoding field from the record
+ uint8_t Encoding;
+ /// The OpSize field from the record
+ uint8_t OpSize;
+ /// The AdSize field from the record
+ uint8_t AdSize;
+ /// The hasREX_WPrefix field from the record
+ bool HasREX_WPrefix;
+ /// The hasVEX_4V field from the record
+ bool HasVEX_4V;
+ /// The VEX_WPrefix field from the record
+ uint8_t VEX_WPrefix;
+ /// Inferred from the operands; indicates whether the L bit in the VEX prefix is set
+ bool HasVEX_LPrefix;
+ /// The ignoreVEX_L field from the record
+ bool IgnoresVEX_L;
+ /// The hasEVEX_L2Prefix field from the record
+ bool HasEVEX_L2Prefix;
+ /// The hasEVEX_K field from the record
+ bool HasEVEX_K;
+ /// The hasEVEX_KZ field from the record
+ bool HasEVEX_KZ;
+ /// The hasEVEX_B field from the record
+ bool HasEVEX_B;
+ /// The isCodeGenOnly field from the record
+ bool IsCodeGenOnly;
+ /// The ForceDisassemble field from the record
+ bool ForceDisassemble;
+ // The CD8_Scale field from the record
+ uint8_t CD8_Scale;
+ // Whether the instruction has the predicate "In64BitMode"
+ bool Is64Bit;
+ // Whether the instruction has the predicate "In32BitMode"
+ bool Is32Bit;
+
+ /// The instruction name as listed in the tables
+ std::string Name;
+
+ /// Indicates whether the instruction should be emitted into the decode
+ /// tables; regardless, it will be emitted into the instruction info table
+ bool ShouldBeEmitted;
+
+ /// The operands of the instruction, as listed in the CodeGenInstruction.
+ /// They are not one-to-one with operands listed in the MCInst; for example,
+ /// memory operands expand to 5 operands in the MCInst
+ const std::vector<CGIOperandList::OperandInfo>* Operands;
+
+ /// The description of the instruction that is emitted into the instruction
+ /// info table
+ InstructionSpecifier* Spec;
+
+ /// insnContext - Returns the primary context in which the instruction is
+ /// valid.
+ ///
+ /// @return - The context in which the instruction is valid.
+ InstructionContext insnContext() const;
+
+ /// typeFromString - Translates an operand type from the string provided in
+ /// the LLVM tables to an OperandType for use in the operand specifier.
+ ///
+ /// @param s - The string, as extracted by calling Rec->getName()
+ /// on a CodeGenInstruction::OperandInfo.
+ /// @param hasREX_WPrefix - Indicates whether the instruction has a REX.W
+ /// prefix. If it does, 32-bit register operands stay
+ /// 32-bit regardless of the operand size.
+ /// @param OpSize Indicates the operand size of the instruction.
+ /// If register size does not match OpSize, then
+ /// register sizes keep their size.
+ /// @return - The operand's type.
+ static OperandType typeFromString(const std::string& s,
+ bool hasREX_WPrefix, uint8_t OpSize);
+
+ /// immediateEncodingFromString - Translates an immediate encoding from the
+ /// string provided in the LLVM tables to an OperandEncoding for use in
+ /// the operand specifier.
+ ///
+ /// @param s - See typeFromString().
+ /// @param OpSize - Indicates whether this is an OpSize16 instruction.
+ /// If it is not, then 16-bit immediate operands stay 16-bit.
+ /// @return - The operand's encoding.
+ static OperandEncoding immediateEncodingFromString(const std::string &s,
+ uint8_t OpSize);
+
+ /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but
+ /// handles operands that are in the REG field of the ModR/M byte.
+ static OperandEncoding rmRegisterEncodingFromString(const std::string &s,
+ uint8_t OpSize);
+
+ /// rmRegisterEncodingFromString - Like immediateEncodingFromString, but
+ /// handles operands that are in the REG field of the ModR/M byte.
+ static OperandEncoding roRegisterEncodingFromString(const std::string &s,
+ uint8_t OpSize);
+ static OperandEncoding memoryEncodingFromString(const std::string &s,
+ uint8_t OpSize);
+ static OperandEncoding relocationEncodingFromString(const std::string &s,
+ uint8_t OpSize);
+ static OperandEncoding opcodeModifierEncodingFromString(const std::string &s,
+ uint8_t OpSize);
+ static OperandEncoding vvvvRegisterEncodingFromString(const std::string &s,
+ uint8_t OpSize);
+ static OperandEncoding writemaskRegisterEncodingFromString(const std::string &s,
+ uint8_t OpSize);
+
+ /// \brief Adjust the encoding type for an operand based on the instruction.
+ void adjustOperandEncoding(OperandEncoding &encoding);
+
+ /// handleOperand - Converts a single operand from the LLVM table format to
+ /// the emitted table format, handling any duplicate operands it encounters
+ /// and then one non-duplicate.
+ ///
+ /// @param optional - Determines whether to assert that the
+ /// operand exists.
+ /// @param operandIndex - The index into the generated operand table.
+ /// Incremented by this function one or more
+ /// times to reflect possible duplicate
+ /// operands).
+ /// @param physicalOperandIndex - The index of the current operand into the
+ /// set of non-duplicate ('physical') operands.
+ /// Incremented by this function once.
+ /// @param numPhysicalOperands - The number of non-duplicate operands in the
+ /// instructions.
+ /// @param operandMapping - The operand mapping, which has an entry for
+ /// each operand that indicates whether it is a
+ /// duplicate, and of what.
+ void handleOperand(bool optional,
+ unsigned &operandIndex,
+ unsigned &physicalOperandIndex,
+ unsigned numPhysicalOperands,
+ const unsigned *operandMapping,
+ OperandEncoding (*encodingFromString)
+ (const std::string&,
+ uint8_t OpSize));
+
+ /// shouldBeEmitted - Returns the shouldBeEmitted field. Although filter()
+ /// filters out many instructions, at various points in decoding we
+ /// determine that the instruction should not actually be decodable. In
+ /// particular, MMX MOV instructions aren't emitted, but they're only
+ /// identified during operand parsing.
+ ///
+ /// @return - true if at this point we believe the instruction should be
+ /// emitted; false if not. This will return false if filter() returns false
+ /// once emitInstructionSpecifier() has been called.
+ bool shouldBeEmitted() const {
+ return ShouldBeEmitted;
+ }
+
+ /// emitInstructionSpecifier - Loads the instruction specifier for the current
+ /// instruction into a DisassemblerTables.
+ ///
+ void emitInstructionSpecifier();
+
+ /// emitDecodePath - Populates the proper fields in the decode tables
+ /// corresponding to the decode paths for this instruction.
+ ///
+ /// \param tables The DisassemblerTables to populate with the decode
+ /// decode information for the current instruction.
+ void emitDecodePath(DisassemblerTables &tables) const;
+
+ /// Constructor - Initializes a RecognizableInstr with the appropriate fields
+ /// from a CodeGenInstruction.
+ ///
+ /// \param tables The DisassemblerTables that the specifier will be added to.
+ /// \param insn The CodeGenInstruction to extract information from.
+ /// \param uid The unique ID of the current instruction.
+ RecognizableInstr(DisassemblerTables &tables,
+ const CodeGenInstruction &insn,
+ InstrUID uid);
+public:
+ /// processInstr - Accepts a CodeGenInstruction and loads decode information
+ /// for it into a DisassemblerTables if appropriate.
+ ///
+ /// \param tables The DiassemblerTables to be populated with decode
+ /// information.
+ /// \param insn The CodeGenInstruction to be used as a source for this
+ /// information.
+ /// \param uid The unique ID of the instruction.
+ static void processInstr(DisassemblerTables &tables,
+ const CodeGenInstruction &insn,
+ InstrUID uid);
+};
+
+} // namespace X86Disassembler
+
+} // namespace llvm
+
+#endif