summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/utils/TableGen
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2016-12-26 20:36:37 +0000
committerdim <dim@FreeBSD.org>2016-12-26 20:36:37 +0000
commit06210ae42d418d50d8d9365d5c9419308ae9e7ee (patch)
treeab60b4cdd6e430dda1f292a46a77ddb744723f31 /contrib/llvm/utils/TableGen
parent2dd166267f53df1c3748b4325d294b9b839de74b (diff)
downloadFreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.zip
FreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.tar.gz
MFC r309124:
Upgrade our copies of clang, llvm, lldb, compiler-rt and libc++ to 3.9.0 release, and add lld 3.9.0. Also completely revamp the build system for clang, llvm, lldb and their related tools. Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11 support to build; see UPDATING for more information. Release notes for llvm, clang and lld are available here: <http://llvm.org/releases/3.9.0/docs/ReleaseNotes.html> <http://llvm.org/releases/3.9.0/tools/clang/docs/ReleaseNotes.html> <http://llvm.org/releases/3.9.0/tools/lld/docs/ReleaseNotes.html> Thanks to Ed Maste, Bryan Drewery, Andrew Turner, Antoine Brodin and Jan Beich for their help. Relnotes: yes MFC r309147: Pull in r282174 from upstream llvm trunk (by Krzysztof Parzyszek): [PPC] Set SP after loading data from stack frame, if no red zone is present Follow-up to r280705: Make sure that the SP is only restored after all data is loaded from the stack frame, if there is no red zone. This completes the fix for https://llvm.org/bugs/show_bug.cgi?id=26519. Differential Revision: https://reviews.llvm.org/D24466 Reported by: Mark Millard PR: 214433 MFC r309149: Pull in r283060 from upstream llvm trunk (by Hal Finkel): [PowerPC] Refactor soft-float support, and enable PPC64 soft float This change enables soft-float for PowerPC64, and also makes soft-float disable all vector instruction sets for both 32-bit and 64-bit modes. This latter part is necessary because the PPC backend canonicalizes many Altivec vector types to floating-point types, and so soft-float breaks scalarization support for many operations. Both for embedded targets and for operating-system kernels desiring soft-float support, it seems reasonable that disabling hardware floating-point also disables vector instructions (embedded targets without hardware floating point support are unlikely to have Altivec, etc. and operating system kernels desiring not to use floating-point registers to lower syscall cost are unlikely to want to use vector registers either). If someone needs this to work, we'll need to change the fact that we promote many Altivec operations to act on v4f32. To make it possible to disable Altivec when soft-float is enabled, hardware floating-point support needs to be expressed as a positive feature, like the others, and not a negative feature, because target features cannot have dependencies on the disabling of some other feature. So +soft-float has now become -hard-float. Fixes PR26970. Pull in r283061 from upstream clang trunk (by Hal Finkel): [PowerPC] Enable soft-float for PPC64, and +soft-float -> -hard-float Enable soft-float support on PPC64, as the backend now supports it. Also, the backend now uses -hard-float instead of +soft-float, so set the target features accordingly. Fixes PR26970. Reported by: Mark Millard PR: 214433 MFC r309212: Add a few missed clang 3.9.0 files to OptionalObsoleteFiles. MFC r309262: Fix packaging for clang, lldb and lld 3.9.0 During the upgrade of clang/llvm etc to 3.9.0 in r309124, the PACKAGE directive in the usr.bin/clang/*.mk files got dropped accidentally. Restore it, with a few minor changes and additions: * Correct license in clang.ucl to NCSA * Add PACKAGE=clang for clang and most of the "ll" tools * Put lldb in its own package * Put lld in its own package Reviewed by: gjb, jmallett Differential Revision: https://reviews.freebsd.org/D8666 MFC r309656: During the bootstrap phase, when building the minimal llvm library on PowerPC, add lib/Support/Atomic.cpp. This is needed because upstream llvm revision r271821 disabled the use of std::call_once, which causes some fallback functions from Atomic.cpp to be used instead. Reported by: Mark Millard PR: 214902 MFC r309835: Tentatively apply https://reviews.llvm.org/D18730 to work around gcc PR 70528 (bogus error: constructor required before non-static data member). This should fix buildworld with the external gcc package. Reported by: https://jenkins.freebsd.org/job/FreeBSD_HEAD_amd64_gcc/ MFC r310194: Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to 3.9.1 release. Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11 support to build; see UPDATING for more information. Release notes for llvm, clang and lld will be available here: <http://releases.llvm.org/3.9.1/docs/ReleaseNotes.html> <http://releases.llvm.org/3.9.1/tools/clang/docs/ReleaseNotes.html> <http://releases.llvm.org/3.9.1/tools/lld/docs/ReleaseNotes.html> Relnotes: yes
Diffstat (limited to 'contrib/llvm/utils/TableGen')
-rw-r--r--contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp365
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp252
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterInst.cpp19
-rw-r--r--contrib/llvm/utils/TableGen/AsmWriterInst.h29
-rw-r--r--contrib/llvm/utils/TableGen/Attributes.cpp23
-rw-r--r--contrib/llvm/utils/TableGen/CodeEmitterGen.cpp9
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp23
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h4
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.cpp5
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenInstruction.h7
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenIntrinsics.h191
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenMapTable.cpp33
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenRegisters.cpp102
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenRegisters.h6
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenSchedule.cpp101
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenSchedule.h15
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.cpp64
-rw-r--r--contrib/llvm/utils/TableGen/CodeGenTarget.h15
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcher.cpp64
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcher.h125
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp49
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp16
-rw-r--r--contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp83
-rw-r--r--contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp27
-rw-r--r--contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp13
-rw-r--r--contrib/llvm/utils/TableGen/FastISelEmitter.cpp6
-rw-r--r--contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp134
-rw-r--r--contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp65
-rw-r--r--contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp283
-rw-r--r--contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp116
-rw-r--r--contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp320
-rw-r--r--contrib/llvm/utils/TableGen/SequenceToOffsetTable.h1
-rw-r--r--contrib/llvm/utils/TableGen/SubtargetEmitter.cpp311
-rw-r--r--contrib/llvm/utils/TableGen/TableGen.cpp10
-rw-r--r--contrib/llvm/utils/TableGen/TableGenBackends.h1
-rw-r--r--contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp2
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp53
-rw-r--r--contrib/llvm/utils/TableGen/X86RecognizableInstr.h5
-rw-r--r--contrib/llvm/utils/TableGen/module.modulemap4
39 files changed, 1662 insertions, 1289 deletions
diff --git a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
index 6e9a948..76228e0 100644
--- a/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmMatcherEmitter.cpp
@@ -112,10 +112,10 @@
#include "llvm/TableGen/TableGenBackend.h"
#include <cassert>
#include <cctype>
+#include <forward_list>
#include <map>
#include <set>
-#include <sstream>
-#include <forward_list>
+
using namespace llvm;
#define DEBUG_TYPE "asm-matcher-emitter"
@@ -199,6 +199,14 @@ struct ClassInfo {
/// 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 {
@@ -263,34 +271,79 @@ public:
return false;
}
- /// operator< - Compare two classes.
- // FIXME: This ordering seems to be broken. For example:
- // u64 < i64, i64 < s8, s8 < u64, forming a cycle
- // u64 is a subset of i64
- // i64 and s8 are not subsets of each other, so are ordered by name
- // s8 and u64 are not subsets of each other, so are ordered by name
+ 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;
- // Unrelated classes can be ordered by kind.
- if (!isRelatedTo(RHS))
- return Kind < RHS.Kind;
-
- switch (Kind) {
- case Invalid:
- llvm_unreachable("Invalid kind!");
-
- default:
- // This class precedes the RHS if it is a proper subset of the RHS.
- if (isSubsetOf(RHS))
+ // 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;
- if (RHS.isSubsetOf(*this))
+ 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");
+ }
- // Otherwise, order by name to ensure we have a total ordering.
- return ValueName < RHS.ValueName;
+ 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;
}
};
@@ -526,8 +579,8 @@ struct MatchableInfo {
/// operator< - Compare two matchables.
bool operator<(const MatchableInfo &RHS) const {
// The primary comparator is the instruction mnemonic.
- if (Mnemonic != RHS.Mnemonic)
- return Mnemonic < RHS.Mnemonic;
+ if (int Cmp = Mnemonic.compare(RHS.Mnemonic))
+ return Cmp == -1;
if (AsmOperands.size() != RHS.AsmOperands.size())
return AsmOperands.size() < RHS.AsmOperands.size();
@@ -637,7 +690,6 @@ struct OperandMatchEntry {
}
};
-
class AsmMatcherInfo {
public:
/// Tracked Records
@@ -720,9 +772,15 @@ public:
RecordKeeper &getRecords() const {
return Records;
}
+
+ bool hasOptionalOperands() const {
+ return std::find_if(Classes.begin(), Classes.end(),
+ [](const ClassInfo& Class){ return Class.IsOptional; })
+ != Classes.end();
+ }
};
-} // End anonymous namespace
+} // end anonymous namespace
void MatchableInfo::dump() const {
errs() << TheDef->getName() << " -- " << "flattened:\"" << AsmString <<"\"\n";
@@ -833,7 +891,6 @@ extractSingletonRegisterForAsmOperand(MatchableInfo::AsmOperand &Op,
// If there is no register prefix (i.e. "%" in "%eax"), then this may
// be some random non-register token, just ignore it.
- return;
}
void MatchableInfo::initialize(const AsmMatcherInfo &Info,
@@ -1071,6 +1128,8 @@ ClassInfo *AsmMatcherInfo::getTokenClass(StringRef Token) {
Entry->RenderMethod = "<invalid>";
Entry->ParserMethod = "";
Entry->DiagnosticType = "";
+ Entry->IsOptional = false;
+ Entry->DefaultMethod = "<invalid>";
}
return Entry;
@@ -1111,7 +1170,6 @@ AsmMatcherInfo::getOperandClass(Record *Rec, int SubOpIdx) {
PrintFatalError(Rec->getLoc(), "register class has no class info!");
}
-
if (Rec->isSubClassOf("RegisterClass")) {
if (ClassInfo *CI = RegisterClassClasses[Rec])
return CI;
@@ -1206,6 +1264,8 @@ buildRegisterClasses(SmallPtrSetImpl<Record*> &SingletonRegisters) {
CI->Registers = RS;
// FIXME: diagnostic type.
CI->DiagnosticType = "";
+ CI->IsOptional = false;
+ CI->DefaultMethod = ""; // unused
RegisterSetClasses.insert(std::make_pair(RS, CI));
++Index;
}
@@ -1320,6 +1380,19 @@ void AsmMatcherInfo::buildOperandClasses() {
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;
}
}
@@ -1400,7 +1473,7 @@ void AsmMatcherInfo::buildInfo() {
AsmVariant->getValueAsString("BreakCharacters");
Variant.AsmVariantNo = AsmVariant->getValueAsInt("Variant");
- for (const CodeGenInstruction *CGI : Target.instructions()) {
+ for (const CodeGenInstruction *CGI : Target.getInstructionsByEnumValue()) {
// If the tblgen -match-prefix option is specified (for tblgen hackers),
// filter the set of instructions we consider.
@@ -1539,6 +1612,16 @@ void AsmMatcherInfo::buildInfo() {
// Reorder classes so that classes precede super classes.
Classes.sort();
+
+#ifndef NDEBUG
+ // Verify that the table is now sorted
+ 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 // NDEBUG
}
/// buildInstructionOperandReference - The specified operand is a reference to a
@@ -1744,10 +1827,10 @@ static unsigned getConverterOperandID(const std::string &Name,
return ID;
}
-
static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
std::vector<std::unique_ptr<MatchableInfo>> &Infos,
- bool HasMnemonicFirst, raw_ostream &OS) {
+ bool HasMnemonicFirst, bool HasOptionalOperands,
+ raw_ostream &OS) {
SmallSetVector<std::string, 16> OperandConversionKinds;
SmallSetVector<std::string, 16> InstructionConversionKinds;
std::vector<std::vector<uint8_t> > ConversionTable;
@@ -1762,24 +1845,40 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
std::string ConvertFnBody;
raw_string_ostream CvtOS(ConvertFnBody);
// Start the unified conversion function.
- CvtOS << "void " << Target.getName() << ClassName << "::\n"
- << "convertToMCInst(unsigned Kind, MCInst &Inst, "
- << "unsigned Opcode,\n"
- << " const OperandVector"
- << " &Operands) {\n"
- << " assert(Kind < CVT_NUM_SIGNATURES && \"Invalid signature!\");\n"
- << " const uint8_t *Converter = ConversionTable[Kind];\n"
- << " Inst.setOpcode(Opcode);\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"
- << " static_cast<" << TargetOperandClass
- << "&>(*Operands[*(p + 1)]).addRegOperands(Inst, 1);\n"
- << " break;\n"
- << " case CVT_Tied:\n"
- << " Inst.addOperand(Inst.getOperand(*(p + 1)));\n"
- << " break;\n";
+ 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);
@@ -1873,6 +1972,11 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// 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;
@@ -1888,11 +1992,27 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
// This is a new operand kind. Add a handler for it to the
// converter driver.
- CvtOS << " case " << Name << ":\n"
- << " static_cast<" << TargetOperandClass
- << "&>(*Operands[*(p + 1)])." << Op.Class->RenderMethod
- << "(Inst, " << OpInfo.MINumOperands << ");\n"
- << " break;\n";
+ 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"
@@ -2015,7 +2135,6 @@ static void emitConvertFuncs(CodeGenTarget &Target, StringRef ClassName,
OS << " CVT_NUM_SIGNATURES\n";
OS << "};\n\n";
-
OS << "} // end anonymous namespace\n\n";
// Output the conversion table.
@@ -2051,6 +2170,7 @@ static void emitMatchClassEnumeration(CodeGenTarget &Target,
<< "/// 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) {
@@ -2091,19 +2211,23 @@ static void emitValidateOperandClass(AsmMatcherInfo &Info,
// 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 << " if (Kind == " << CI.Name << ") {\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";
- OS << " }\n\n";
+ else
+ OS << " break;\n";
}
+ OS << " } // end switch (Kind)\n\n";
// Check for register operands, including sub-classes.
OS << " if (Operand.isReg()) {\n";
@@ -2137,6 +2261,8 @@ static void emitIsSubclass(CodeGenTarget &Target,
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);
@@ -2225,6 +2351,37 @@ static void emitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
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";
+}
+
static const char *getMinimalTypeForRange(uint64_t Range) {
assert(Range <= 0xFFFFFFFFFFFFFFFFULL && "Enum too large");
if (Range > 0xFFFFFFFFULL)
@@ -2665,6 +2822,16 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
const std::unique_ptr<MatchableInfo> &b){
return *a < *b;});
+#ifndef NDEBUG
+ // Verify that the table is now sorted
+ for (auto I = Info.Matchables.begin(), E = Info.Matchables.end(); I != E;
+ ++I) {
+ for (auto J = I; J != E; ++J) {
+ assert(!(**J < **I));
+ }
+ }
+#endif // NDEBUG
+
DEBUG_WITH_TYPE("instruction_info", {
for (const auto &MI : Info.Matchables)
MI->dump();
@@ -2698,6 +2865,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
Info.buildOperandMatchInfo();
bool HasMnemonicFirst = AsmParser->getValueAsBit("HasMnemonicFirst");
+ bool HasOptionalOperands = Info.hasOptionalOperands();
// Write the output.
@@ -2707,10 +2875,16 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
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";
- OS << " void convertToMCInst(unsigned Kind, MCInst &Inst, "
- << "unsigned Opcode,\n"
- << " const OperandVector "
- << "&Operands);\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";
if (HasMnemonicFirst)
@@ -2744,7 +2918,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
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";
@@ -2756,6 +2929,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
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";
@@ -2775,7 +2951,8 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// 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, OS);
+ emitConvertFuncs(Target, ClassName, Info.Matchables, HasMnemonicFirst,
+ HasOptionalOperands, OS);
// Emit the enumeration for classes which participate in matching.
emitMatchClassEnumeration(Target, Info.Classes, OS);
@@ -2792,7 +2969,6 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Emit the available features compute function.
emitComputeAvailableFeatures(Info, OS);
-
StringToOffsetTable StringTable;
size_t MaxNumOperands = 0;
@@ -2958,6 +3134,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
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";
@@ -3002,36 +3181,55 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Emit check that the subclasses match.
OS << " bool OperandsValid = true;\n";
- OS << " for (unsigned i = " << (HasMnemonicFirst ? "0" : "SIndex")
- << "; i != " << MaxNumOperands << "; ++i) {\n";
- OS << " auto Formal = static_cast<MatchClassKind>(it->Classes[i]);\n";
- OS << " if (i" << (HasMnemonicFirst ? "+1" : "")
- << " >= Operands.size()) {\n";
- OS << " OperandsValid = (Formal == " <<"InvalidMatchClass);\n";
- OS << " if (!OperandsValid) ErrorInfo = i"
- << (HasMnemonicFirst ? "+1" : "") << ";\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[i"
- << (HasMnemonicFirst ? "+1" : "") << "];\n";
+ OS << " MCParsedAsmOperand &Actual = *Operands[ActualIdx];\n";
OS << " unsigned Diag = validateOperandClass(Actual, Formal);\n";
- OS << " if (Diag == Match_Success)\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 << " 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 <= i"
- << (HasMnemonicFirst ? "+1" : "") << ")) {\n";
- OS << " ErrorInfo = i" << (HasMnemonicFirst ? "+1" : "") << ";\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";
@@ -3063,7 +3261,12 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " }\n\n";
OS << " // We have selected a definite instruction, convert the parsed\n"
<< " // operands into the appropriate MCInst.\n";
- OS << " convertToMCInst(it->ConvertFn, Inst, it->Opcode, Operands);\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.
@@ -3118,4 +3321,4 @@ void EmitAsmMatcher(RecordKeeper &RK, raw_ostream &OS) {
AsmMatcherEmitter(RK).run(OS);
}
-} // End llvm namespace
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
index cf7cbd9..fc2138f 100644
--- a/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/AsmWriterEmitter.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This tablegen backend is emits an assembly printer for the current target.
+// This tablegen backend emits an assembly printer for the current target.
// Note that this is currently fairly skeletal, but will grow over time.
//
//===----------------------------------------------------------------------===//
@@ -27,6 +27,7 @@
#include <algorithm>
#include <cassert>
#include <map>
+#include <utility>
#include <vector>
using namespace llvm;
@@ -36,10 +37,8 @@ namespace {
class AsmWriterEmitter {
RecordKeeper &Records;
CodeGenTarget Target;
- std::map<const CodeGenInstruction*, AsmWriterInst*> CGIAWIMap;
- const std::vector<const CodeGenInstruction*> *NumberedInstructions;
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions;
std::vector<AsmWriterInst> Instructions;
- std::vector<std::string> PrintMethods;
public:
AsmWriterEmitter(RecordKeeper &R);
@@ -50,21 +49,16 @@ private:
void EmitGetRegisterName(raw_ostream &o);
void EmitPrintAliasInstruction(raw_ostream &O);
- AsmWriterInst *getAsmWriterInstByID(unsigned ID) const {
- assert(ID < NumberedInstructions->size());
- std::map<const CodeGenInstruction*, AsmWriterInst*>::const_iterator I =
- CGIAWIMap.find(NumberedInstructions->at(ID));
- assert(I != CGIAWIMap.end() && "Didn't find inst!");
- return I->second;
- }
void FindUniqueOperandCommands(std::vector<std::string> &UOC,
- std::vector<unsigned> &InstIdxs,
- std::vector<unsigned> &InstOpsUsed) const;
+ 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) {
+ AsmWriterOperand> > &OpsToPrint, raw_ostream &O,
+ bool PassSubtarget) {
O << " case " << OpsToPrint.back().first << ":";
AsmWriterOperand TheOp = OpsToPrint.back().second;
OpsToPrint.pop_back();
@@ -78,7 +72,7 @@ static void PrintCases(std::vector<std::pair<std::string,
}
// Finally, emit the code.
- O << "\n " << TheOp.getCode();
+ O << "\n " << TheOp.getCode(PassSubtarget);
O << "\n break;\n";
}
@@ -86,7 +80,7 @@ static void PrintCases(std::vector<std::pair<std::string,
/// 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) {
+ raw_ostream &O, bool PassSubtarget) {
AsmWriterInst FirstInst = Insts.back();
Insts.pop_back();
@@ -115,7 +109,7 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
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();
+ 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.
@@ -133,7 +127,7 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
}
std::reverse(OpsToPrint.begin(), OpsToPrint.end());
while (!OpsToPrint.empty())
- PrintCases(OpsToPrint, O);
+ PrintCases(OpsToPrint, O, PassSubtarget);
O << " }";
}
O << "\n";
@@ -143,9 +137,9 @@ static void EmitInstructions(std::vector<AsmWriterInst> &Insts,
void AsmWriterEmitter::
FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
- std::vector<unsigned> &InstIdxs,
- std::vector<unsigned> &InstOpsUsed) const {
- InstIdxs.assign(NumberedInstructions->size(), ~0U);
+ 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
@@ -154,31 +148,27 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
InstrsForCase.resize(UniqueOperandCommands.size());
InstOpsUsed.assign(UniqueOperandCommands.size(), 0);
- for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) {
- const AsmWriterInst *Inst = getAsmWriterInstByID(i);
- if (!Inst)
- continue; // PHI, INLINEASM, CFI_INSTRUCTION, etc.
-
- if (Inst->Operands.empty())
+ 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() + "\n";
+ std::string Command = " "+Inst.Operands[0].getCode(PassSubtarget)+"\n";
// Check to see if we already have 'Command' in UniqueOperandCommands.
// If not, add it.
- bool FoundIt = false;
- for (unsigned idx = 0, e = UniqueOperandCommands.size(); idx != e; ++idx)
- if (UniqueOperandCommands[idx] == Command) {
- InstIdxs[i] = idx;
- InstrsForCase[idx] += ", ";
- InstrsForCase[idx] += Inst->CGI->TheDef->getName();
- FoundIt = true;
- break;
- }
- if (!FoundIt) {
- InstIdxs[i] = UniqueOperandCommands.size();
+ auto I = std::find(UniqueOperandCommands.begin(),
+ UniqueOperandCommands.end(), 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());
+ 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);
@@ -188,45 +178,33 @@ FindUniqueOperandCommands(std::vector<std::string> &UniqueOperandCommands,
// 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 (unsigned CommandIdx = 0, e = UniqueOperandCommands.size();
+ for (size_t CommandIdx = 0, e = UniqueOperandCommands.size();
CommandIdx != e; ++CommandIdx) {
- for (unsigned Op = 1; ; ++Op) {
- // Scan for the first instruction in the set.
- std::vector<unsigned>::iterator NIT =
- std::find(InstIdxs.begin(), InstIdxs.end(), CommandIdx);
- if (NIT == InstIdxs.end()) break; // No commonality.
+ 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.
- const AsmWriterInst *FirstInst =
- getAsmWriterInstByID(NIT-InstIdxs.begin());
- if (!FirstInst || FirstInst->Operands.size() == Op)
+ if (FirstInst.Operands.size() == Op)
break;
// Otherwise, scan to see if all of the other instructions in this command
// set share the operand.
- bool AllSame = true;
-
- for (NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx);
- NIT != InstIdxs.end();
- NIT = std::find(NIT+1, InstIdxs.end(), CommandIdx)) {
- // Okay, found another instruction in this command set. If the operand
- // matches, we're ok, otherwise bail out.
- const AsmWriterInst *OtherInst =
- getAsmWriterInstByID(NIT-InstIdxs.begin());
-
- if (!OtherInst || OtherInst->Operands.size() == Op ||
- OtherInst->Operands[Op] != FirstInst->Operands[Op]) {
- AllSame = false;
- break;
- }
- }
- if (!AllSame) break;
+ 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() + "\n";
+ std::string Command = " " +
+ FirstInst.Operands[Op].getCode(PassSubtarget) + "\n";
UniqueOperandCommands[CommandIdx] += Command;
InstOpsUsed[CommandIdx]++;
@@ -277,7 +255,7 @@ static void UnescapeString(std::string &Str) {
void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
Record *AsmWriter = Target.getAsmWriter();
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
- unsigned PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
+ bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
O <<
"/// printInstruction - This method is automatically generated by tablegen\n"
@@ -292,18 +270,16 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
/// 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;
+ 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 (const CodeGenInstruction *Inst : *NumberedInstructions) {
- AsmWriterInst *AWI = CGIAWIMap[Inst];
- if (AWI &&
- AWI->Operands[0].OperandType ==
+ for (AsmWriterInst &AWI : Instructions) {
+ if (AWI.Operands[0].OperandType ==
AsmWriterOperand::isLiteralTextOperand &&
- !AWI->Operands[0].Str.empty()) {
- std::string Str = AWI->Operands[0].Str;
+ !AWI.Operands[0].Str.empty()) {
+ std::string Str = AWI.Operands[0].Str;
UnescapeString(Str);
StringTable.add(Str);
}
@@ -312,29 +288,24 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
StringTable.layout();
unsigned MaxStringIdx = 0;
- for (const CodeGenInstruction *Inst : *NumberedInstructions) {
- AsmWriterInst *AWI = CGIAWIMap[Inst];
+ for (AsmWriterInst &AWI : Instructions) {
unsigned Idx;
- if (!AWI) {
- // Something not handled by the asmwriter printer.
- Idx = ~0U;
- } else if (AWI->Operands[0].OperandType !=
- AsmWriterOperand::isLiteralTextOperand ||
- AWI->Operands[0].Str.empty()) {
+ 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;
+ 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());
+ AWI.Operands.erase(AWI.Operands.begin());
}
// Bias offset by one since we want 0 as a sentinel.
- OpcodeInfo.push_back(Idx+1);
+ OpcodeInfo[AWI.CGIIndex] = Idx+1;
}
// Figure out how many bits we used for the string index.
@@ -348,10 +319,10 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
while (1) {
std::vector<std::string> UniqueOperandCommands;
- std::vector<unsigned> InstIdxs;
+ std::vector<std::vector<unsigned>> InstIdxs;
std::vector<unsigned> NumInstOpsHandled;
FindUniqueOperandCommands(UniqueOperandCommands, InstIdxs,
- NumInstOpsHandled);
+ NumInstOpsHandled, PassSubtarget);
// If we ran out of operands to print, we're done.
if (UniqueOperandCommands.empty()) break;
@@ -368,23 +339,22 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
}
// Otherwise, we can include this in the initial lookup table. Add it in.
- for (unsigned i = 0, e = InstIdxs.size(); i != e; ++i)
- if (InstIdxs[i] != ~0U) {
- OpcodeInfo[i] |= (uint64_t)InstIdxs[i] << (OpcodeInfoBits-BitsLeft);
- }
- BitsLeft -= NumBits;
-
- // Remove the info about this operand.
- for (unsigned i = 0, e = NumberedInstructions->size(); i != e; ++i) {
- if (AsmWriterInst *Inst = getAsmWriterInstByID(i))
- if (!Inst->Operands.empty()) {
- unsigned NumOps = NumInstOpsHandled[InstIdxs[i]];
- assert(NumOps <= Inst->Operands.size() &&
+ 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);
+ 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));
@@ -411,9 +381,9 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
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) {
+ for (unsigned i = 0, e = NumberedInstructions.size(); i != e; ++i) {
O << " " << ((OpcodeInfo[i] >> Shift) & Mask) << "U,\t// "
- << NumberedInstructions->at(i)->TheDef->getName() << "\n";
+ << NumberedInstructions[i]->TheDef->getName() << "\n";
}
O << " };\n\n";
// Emit string to combine the individual table lookups.
@@ -502,7 +472,7 @@ void AsmWriterEmitter::EmitPrintInstruction(raw_ostream &O) {
O << " switch (MI->getOpcode()) {\n";
O << " default: llvm_unreachable(\"Unexpected opcode.\");\n";
while (!Instructions.empty())
- EmitInstructions(Instructions, O);
+ EmitInstructions(Instructions, O, PassSubtarget);
O << " }\n";
}
@@ -578,7 +548,7 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
Record *AsmWriter = Target.getAsmWriter();
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
const auto &Registers = Target.getRegBank().getRegisters();
- std::vector<Record*> AltNameIndices = Target.getRegAltNameIndices();
+ const std::vector<Record*> &AltNameIndices = Target.getRegAltNameIndices();
bool hasAltNames = AltNameIndices.size() > 1;
std::string Namespace =
Registers.front().TheDef->getValueAsString("Namespace");
@@ -606,7 +576,7 @@ void AsmWriterEmitter::EmitGetRegisterName(raw_ostream &O) {
O << " switch(AltIdx) {\n"
<< " default: llvm_unreachable(\"Invalid register alt name index!\");\n";
for (const Record *R : AltNameIndices) {
- std::string AltName(R->getName());
+ const std::string &AltName = R->getName();
std::string Prefix = !Namespace.empty() ? Namespace + "::" : "";
O << " case " << Prefix << AltName << ":\n"
<< " assert(*(AsmStrs" << AltName << "+RegAsmOffset"
@@ -631,12 +601,12 @@ namespace {
class IAPrinter {
std::vector<std::string> Conds;
std::map<StringRef, std::pair<int, int>> OpMap;
- SmallVector<Record*, 4> ReqFeatures;
std::string Result;
std::string AsmString;
public:
- IAPrinter(std::string R, std::string AS) : Result(R), AsmString(AS) {}
+ 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); }
@@ -677,7 +647,7 @@ public:
}
void print(raw_ostream &O) {
- if (Conds.empty() && ReqFeatures.empty()) {
+ if (Conds.empty()) {
O.indent(6) << "return true;\n";
return;
}
@@ -784,7 +754,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
// Emit the method that prints the alias instruction.
std::string ClassName = AsmWriter->getValueAsString("AsmWriterClassName");
unsigned Variant = AsmWriter->getValueAsInt("Variant");
- unsigned PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
+ bool PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
std::vector<Record*> AllInstAliases =
Records.getAllDerivedDefinitions("InstAlias");
@@ -808,6 +778,8 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
// 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;
@@ -825,6 +797,18 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
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");
+ std::copy_if(RF.begin(), RF.end(), std::back_inserter(ReqFeatures),
+ [](Record *R) {
+ return R->getValueAsBit("AssemblerMatcherPredicate");
+ });
+ }
+
unsigned NumMIOps = 0;
for (auto &Operand : CGA.ResultOperands)
NumMIOps += Operand.getMINumOperands();
@@ -929,6 +913,27 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
}
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));
}
}
@@ -1002,13 +1007,14 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
// 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] != '\\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 << " OS << '\\t';\n";
+ O << " if (AsmString[I] == ' ' || AsmString[I] == '\\t')";
+ O << " OS << '\\t';\n";
O << " do {\n";
O << " if (AsmString[I] == '$') {\n";
O << " ++I;\n";
@@ -1072,7 +1078,7 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
for (unsigned i = 0; i < MCOpPredicates.size(); ++i) {
Init *MCOpPred = MCOpPredicates[i]->getValueInit("MCOperandPredicate");
- if (StringInit *SI = dyn_cast<StringInit>(MCOpPred)) {
+ if (CodeInit *SI = dyn_cast<CodeInit>(MCOpPred)) {
O << " case " << i + 1 << ": {\n"
<< SI->getValue() << "\n"
<< " }\n";
@@ -1089,19 +1095,15 @@ void AsmWriterEmitter::EmitPrintAliasInstruction(raw_ostream &O) {
AsmWriterEmitter::AsmWriterEmitter(RecordKeeper &R) : Records(R), Target(R) {
Record *AsmWriter = Target.getAsmWriter();
unsigned Variant = AsmWriter->getValueAsInt("Variant");
- unsigned PassSubtarget = AsmWriter->getValueAsInt("PassSubtarget");
- for (const CodeGenInstruction *I : Target.instructions())
- if (!I->AsmString.empty() && I->TheDef->getName() != "PHI")
- Instructions.emplace_back(*I, Variant, PassSubtarget);
// Get the instruction numbering.
- NumberedInstructions = &Target.getInstructionsByEnumValue();
+ NumberedInstructions = Target.getInstructionsByEnumValue();
- // Compute the CodeGenInstruction -> AsmWriterInst mapping. Note that not
- // all machine instructions are necessarily being printed, so there may be
- // target instructions not in this map.
- for (AsmWriterInst &AWI : Instructions)
- CGIAWIMap.insert(std::make_pair(AWI.CGI, &AWI));
+ 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) {
diff --git a/contrib/llvm/utils/TableGen/AsmWriterInst.cpp b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp
index 5b09765..2c19e5d 100644
--- a/contrib/llvm/utils/TableGen/AsmWriterInst.cpp
+++ b/contrib/llvm/utils/TableGen/AsmWriterInst.cpp
@@ -26,7 +26,7 @@ static bool isIdentChar(char C) {
C == '_';
}
-std::string AsmWriterOperand::getCode() const {
+std::string AsmWriterOperand::getCode(bool PassSubtarget) const {
if (OperandType == isLiteralTextOperand) {
if (Str.size() == 1)
return "O << '" + Str + "';";
@@ -50,9 +50,9 @@ std::string AsmWriterOperand::getCode() const {
/// ParseAsmString - Parse the specified Instruction's AsmString into this
/// AsmWriterInst.
///
-AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant,
- unsigned PassSubtarget) {
- this->CGI = &CGI;
+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
@@ -120,8 +120,7 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant,
while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
++VarEnd;
- std::string VarName(AsmString.begin()+DollarPos+1,
- AsmString.begin()+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
@@ -143,7 +142,7 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant,
PrintFatalError("Reached end of string before terminating curly brace in '"
+ CGI.TheDef->getName() + "'");
- unsigned ModifierStart = VarEnd;
+ std::string::size_type ModifierStart = VarEnd;
while (VarEnd < AsmString.size() && isIdentChar(AsmString[VarEnd]))
++VarEnd;
Modifier = std::string(AsmString.begin()+ModifierStart,
@@ -163,16 +162,14 @@ AsmWriterInst::AsmWriterInst(const CodeGenInstruction &CGI, unsigned Variant,
if (VarName.empty()) {
// Just a modifier, pass this into PrintSpecial.
- Operands.emplace_back("PrintSpecial", ~0U, ~0U, Modifier,
- PassSubtarget);
+ 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, OpNo, MIOp, Modifier,
- PassSubtarget);
+ Operands.emplace_back(OpInfo.PrinterMethodName, MIOp, Modifier);
}
LastEmitted = VarEnd;
}
diff --git a/contrib/llvm/utils/TableGen/AsmWriterInst.h b/contrib/llvm/utils/TableGen/AsmWriterInst.h
index a597e6b..708f23c 100644
--- a/contrib/llvm/utils/TableGen/AsmWriterInst.h
+++ b/contrib/llvm/utils/TableGen/AsmWriterInst.h
@@ -35,29 +35,20 @@ namespace llvm {
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;
- /// CGIOpNo - For isMachineInstrOperand, this is the index of the operand in
- /// the CodeGenInstruction.
- unsigned CGIOpNo;
-
- /// MiOpNo - For isMachineInstrOperand, this is the operand number of the
- /// machine instruction.
- unsigned MIOpNo;
-
/// MiModifier - For isMachineInstrOperand, this is the modifier string for
/// an operand, specified with syntax like ${opname:modifier}.
std::string MiModifier;
- // PassSubtarget - Pass MCSubtargetInfo to the print method if this is
- // equal to 1.
- // FIXME: Remove after all ports are updated.
- unsigned PassSubtarget;
-
// To make VS STL happy
AsmWriterOperand(OpType op = isLiteralTextOperand):OperandType(op) {}
@@ -66,13 +57,10 @@ namespace llvm {
: OperandType(op), Str(LitStr) {}
AsmWriterOperand(const std::string &Printer,
- unsigned _CGIOpNo,
unsigned _MIOpNo,
const std::string &Modifier,
- unsigned PassSubtarget,
OpType op = isMachineInstrOperand)
- : OperandType(op), Str(Printer), CGIOpNo(_CGIOpNo), MIOpNo(_MIOpNo),
- MiModifier(Modifier), PassSubtarget(PassSubtarget) {}
+ : OperandType(op), MIOpNo(_MIOpNo), Str(Printer), MiModifier(Modifier) {}
bool operator!=(const AsmWriterOperand &Other) const {
if (OperandType != Other.OperandType || Str != Other.Str) return true;
@@ -85,16 +73,17 @@ namespace llvm {
}
/// getCode - Return the code that prints this operand.
- std::string getCode() const;
+ std::string getCode(bool PassSubtarget) const;
};
class AsmWriterInst {
public:
std::vector<AsmWriterOperand> Operands;
const CodeGenInstruction *CGI;
+ unsigned CGIIndex;
- AsmWriterInst(const CodeGenInstruction &CGI,
- unsigned Variant, unsigned PassSubtarget);
+ 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
diff --git a/contrib/llvm/utils/TableGen/Attributes.cpp b/contrib/llvm/utils/TableGen/Attributes.cpp
index 7b001bf..58dbe57 100644
--- a/contrib/llvm/utils/TableGen/Attributes.cpp
+++ b/contrib/llvm/utils/TableGen/Attributes.cpp
@@ -27,6 +27,7 @@ public:
private:
void emitTargetIndependentEnums(raw_ostream &OS);
+ void emitConversionFn(raw_ostream &OS);
void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
void printEnumAttrClasses(raw_ostream &OS,
@@ -52,6 +53,27 @@ void Attributes::emitTargetIndependentEnums(raw_ostream &OS) {
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";
@@ -144,6 +166,7 @@ void Attributes::printStrBoolAttrClasses(raw_ostream &OS,
void Attributes::emit(raw_ostream &OS) {
emitTargetIndependentEnums(OS);
+ emitConversionFn(OS);
emitFnAttrCompatCheck(OS, false);
}
diff --git a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
index 46fcdf5..400913e 100644
--- a/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
+++ b/contrib/llvm/utils/TableGen/CodeEmitterGen.cpp
@@ -15,7 +15,6 @@
#include "CodeGenTarget.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
@@ -227,7 +226,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
// For little-endian instruction bit encodings, reverse the bit order
Target.reverseBitsForLittleEndianEncoding();
- const std::vector<const CodeGenInstruction*> &NumberedInstructions =
+ ArrayRef<const CodeGenInstruction*> NumberedInstructions =
Target.getInstructionsByEnumValue();
// Emit function declaration
@@ -238,11 +237,7 @@ void CodeEmitterGen::run(raw_ostream &o) {
// Emit instruction base values
o << " static const uint64_t InstBits[] = {\n";
- for (std::vector<const CodeGenInstruction*>::const_iterator
- IN = NumberedInstructions.begin(),
- EN = NumberedInstructions.end();
- IN != EN; ++IN) {
- const CodeGenInstruction *CGI = *IN;
+ for (const CodeGenInstruction *CGI : NumberedInstructions) {
Record *R = CGI->TheDef;
if (R->getValueAsString("Namespace") == "TargetOpcode" ||
diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
index 3ebe51e..307a953 100644
--- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -2392,8 +2392,8 @@ void TreePattern::dump() const { print(errs()); }
CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) :
Records(R), Target(R) {
- Intrinsics = LoadIntrinsics(Records, false);
- TgtIntrinsics = LoadIntrinsics(Records, true);
+ Intrinsics = CodeGenIntrinsicTable(Records, false);
+ TgtIntrinsics = CodeGenIntrinsicTable(Records, true);
ParseNodeInfo();
ParseNodeTransforms();
ParseComplexPatterns();
@@ -2816,14 +2816,14 @@ public:
if (const CodeGenIntrinsic *IntInfo = N->getIntrinsicInfo(CDP)) {
// If this is an intrinsic, analyze it.
- if (IntInfo->ModRef >= CodeGenIntrinsic::ReadArgMem)
+ if (IntInfo->ModRef & CodeGenIntrinsic::MR_Ref)
mayLoad = true;// These may load memory.
- if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteArgMem)
+ if (IntInfo->ModRef & CodeGenIntrinsic::MR_Mod)
mayStore = true;// Intrinsics that can write to memory are 'mayStore'.
if (IntInfo->ModRef >= CodeGenIntrinsic::ReadWriteMem)
- // WriteMem intrinsics can have other strange effects.
+ // ReadWriteMem intrinsics can have other strange effects.
hasSideEffects = true;
}
}
@@ -2974,9 +2974,16 @@ const DAGInstruction &CodeGenDAGPatterns::parseInstructionPattern(
// fill in the InstResults map.
for (unsigned j = 0, e = I->getNumTrees(); j != e; ++j) {
TreePatternNode *Pat = I->getTree(j);
- if (Pat->getNumTypes() != 0)
+ 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");
+ " void types, has types " + Types);
+ }
// Find inputs and outputs, and verify the structure of the uses/defs.
FindPatternInputsAndOutputs(I, Pat, InstInputs, InstResults,
@@ -3249,7 +3256,7 @@ void CodeGenDAGPatterns::AddPatternToMatch(TreePattern *Pattern,
void CodeGenDAGPatterns::InferInstructionFlags() {
- const std::vector<const CodeGenInstruction*> &Instructions =
+ ArrayRef<const CodeGenInstruction*> Instructions =
Target.getInstructionsByEnumValue();
// First try to infer flags from the primary instruction pattern, if any.
diff --git a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
index 76c9cef..819c4b8 100644
--- a/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
+++ b/contrib/llvm/utils/TableGen/CodeGenDAGPatterns.h
@@ -716,8 +716,8 @@ public:
class CodeGenDAGPatterns {
RecordKeeper &Records;
CodeGenTarget Target;
- std::vector<CodeGenIntrinsic> Intrinsics;
- std::vector<CodeGenIntrinsic> TgtIntrinsics;
+ CodeGenIntrinsicTable Intrinsics;
+ CodeGenIntrinsicTable TgtIntrinsics;
std::map<Record*, SDNodeInfo, LessRecordByID> SDNodes;
std::map<Record*, std::pair<Record*, std::string>, LessRecordByID> SDNodeXForms;
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
index 366e8ec..ec80236 100644
--- a/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.cpp
@@ -49,7 +49,9 @@ CGIOperandList::CGIOperandList(Record *R) : TheDef(R) {
unsigned MIOperandNo = 0;
std::set<std::string> OperandNames;
- for (unsigned i = 0, e = InDI->getNumArgs()+OutDI->getNumArgs(); i != e; ++i){
+ unsigned e = InDI->getNumArgs() + OutDI->getNumArgs();
+ OperandList.reserve(e);
+ for (unsigned i = 0; i != e; ++i){
Init *ArgInit;
std::string ArgName;
if (i < NumDefs) {
@@ -322,6 +324,7 @@ CodeGenInstruction::CodeGenInstruction(Record *R)
isExtractSubreg = R->getValueAsBit("isExtractSubreg");
isInsertSubreg = R->getValueAsBit("isInsertSubreg");
isConvergent = R->getValueAsBit("isConvergent");
+ hasNoSchedulingInfo = R->getValueAsBit("hasNoSchedulingInfo");
bool Unset;
mayLoad = R->getValueAsBitOrUnset("mayLoad", Unset);
diff --git a/contrib/llvm/utils/TableGen/CodeGenInstruction.h b/contrib/llvm/utils/TableGen/CodeGenInstruction.h
index 8f01abd..8e5a03d 100644
--- a/contrib/llvm/utils/TableGen/CodeGenInstruction.h
+++ b/contrib/llvm/utils/TableGen/CodeGenInstruction.h
@@ -14,7 +14,6 @@
#ifndef LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H
#define LLVM_UTILS_TABLEGEN_CODEGENINSTRUCTION_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/Support/SMLoc.h"
@@ -23,10 +22,10 @@
#include <vector>
namespace llvm {
+template <typename T> class ArrayRef;
class Record;
class DagInit;
class CodeGenTarget;
- class StringRef;
class CGIOperandList {
public:
@@ -257,6 +256,7 @@ namespace llvm {
bool isExtractSubreg : 1;
bool isInsertSubreg : 1;
bool isConvergent : 1;
+ bool hasNoSchedulingInfo : 1;
std::string DeprecatedReason;
bool HasComplexDeprecationPredicate;
@@ -316,7 +316,8 @@ namespace llvm {
K_Reg
} Kind;
- ResultOperand(std::string N, Record *r) : Name(N), R(r), Kind(K_Record) {}
+ 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) {}
diff --git a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
index 7bdb7e1..ea3ec67 100644
--- a/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
+++ b/contrib/llvm/utils/TableGen/CodeGenIntrinsics.h
@@ -19,85 +19,122 @@
#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.
-
- /// IntrinsicSignature - 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 {
- /// RetVTs - 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;
-
- /// RetTypeDefs - The records for each return type.
- std::vector<Record*> RetTypeDefs;
-
- /// ParamVTs - 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;
-
- /// ParamTypeDefs - The records for each parameter type.
- std::vector<Record*> ParamTypeDefs;
- };
-
- IntrinsicSignature IS;
-
- // Memory mod/ref behavior of this intrinsic.
- enum ModRefKind {
- NoMem, ReadArgMem, ReadMem, ReadWriteArgMem, ReadWriteMem
- };
- ModRefKind ModRef;
-
- /// This is set to true if the intrinsic is overloaded by its argument
- /// types.
- bool isOverloaded;
-
- /// isCommutative - True if the intrinsic is commutative.
- bool isCommutative;
-
- /// canThrow - True if the intrinsic can throw.
- bool canThrow;
-
- /// isNoDuplicate - True if the intrinsic is marked as noduplicate.
- bool isNoDuplicate;
-
- /// isNoReturn - True if the intrinsic is no-return.
- bool isNoReturn;
-
- /// isConvergent - True if the intrinsic is marked as convergent.
- bool isConvergent;
-
- enum ArgAttribute {
- NoCapture,
- ReadOnly,
- ReadNone
- };
- std::vector<std::pair<unsigned, ArgAttribute> > ArgumentAttributes;
-
- CodeGenIntrinsic(Record *R);
+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;
};
- /// LoadIntrinsics - Read all of the intrinsics defined in the specified
- /// .td file.
- std::vector<CodeGenIntrinsic> LoadIntrinsics(const RecordKeeper &RC,
- bool TargetOnly);
+ 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 anywhere, i.e. it is not restricted
+ /// to access through pointer arguments.
+ MR_Anywhere = 1,
+
+ /// The intrinsic may read memory.
+ MR_Ref = 2,
+
+ /// The intrinsic may write memory.
+ MR_Mod = 4,
+
+ /// 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,
+ ReadMem = MR_Ref | MR_Anywhere,
+ WriteArgMem = MR_Mod,
+ WriteMem = MR_Mod | MR_Anywhere,
+ ReadWriteArgMem = MR_ModRef,
+ 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
index f66dd08..527f530 100644
--- a/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenMapTable.cpp
@@ -337,10 +337,20 @@ Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
}
if (MatchFound) {
- if (MatchInstr) // Already had a match
+ 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());
+ "', for the relation `" + InstrMapDesc.getName() + "', row fields [" +
+ KeyValueStr + "], column `" + CurValueCol->getAsString() + "'");
+ }
MatchInstr = CurInstr;
}
}
@@ -355,7 +365,7 @@ Record *MapTableEmitter::getInstrForColumn(Record *KeyInstr,
unsigned MapTableEmitter::emitBinSearchTable(raw_ostream &OS) {
- const std::vector<const CodeGenInstruction*> &NumberedInstructions =
+ ArrayRef<const CodeGenInstruction*> NumberedInstructions =
Target.getInstructionsByEnumValue();
std::string TargetName = Target.getName();
const std::vector<ListInit*> &ValueCols = InstrMapDesc.getValueCols();
@@ -499,8 +509,7 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) {
// Iterate over all InstrMapping records and create a map between column
// fields and their possible values across all records.
- for (unsigned i = 0, e = InstrMapVec.size(); i < e; i++) {
- Record *CurMap = InstrMapVec[i];
+ for (Record *CurMap : InstrMapVec) {
ListInit *ColFields;
ColFields = CurMap->getValueAsListInit("ColFields");
ListInit *List = CurMap->getValueAsListInit("ValueCols");
@@ -524,10 +533,8 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) {
}
}
- for (std::map<std::string, std::vector<Init*> >::iterator
- II = ColFieldValueMap.begin(), IE = ColFieldValueMap.end();
- II != IE; II++) {
- std::vector<Init*> FieldValues = (*II).second;
+ for (auto &Entry : ColFieldValueMap) {
+ std::vector<Init*> FieldValues = Entry.second;
// Delete duplicate entries from ColFieldValueMap
for (unsigned i = 0; i < FieldValues.size() - 1; i++) {
@@ -540,9 +547,9 @@ static void emitEnums(raw_ostream &OS, RecordKeeper &Records) {
}
// Emit enumerated values for the column fields.
- OS << "enum " << (*II).first << " {\n";
+ OS << "enum " << Entry.first << " {\n";
for (unsigned i = 0, endFV = FieldValues.size(); i < endFV; i++) {
- OS << "\t" << (*II).first << "_" << FieldValues[i]->getAsUnquotedString();
+ OS << "\t" << Entry.first << "_" << FieldValues[i]->getAsUnquotedString();
if (i != endFV - 1)
OS << ",\n";
else
@@ -577,8 +584,8 @@ void EmitMapTable(RecordKeeper &Records, raw_ostream &OS) {
// Iterate over all instruction mapping records and construct relationship
// maps based on the information specified there.
//
- for (unsigned i = 0, e = InstrMapVec.size(); i < e; i++) {
- MapTableEmitter IMap(Target, Records, InstrMapVec[i]);
+ 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
diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
index ca316e9..626144f 100644
--- a/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.cpp
@@ -587,10 +587,9 @@ struct TupleExpander : SetTheory::Expander {
Elts.insert(NewReg);
// Copy Proto super-classes.
- ArrayRef<Record *> Supers = Proto->getSuperClasses();
- ArrayRef<SMRange> Ranges = Proto->getSuperClassRanges();
- for (unsigned i = 0, e = Supers.size(); i != e; ++i)
- NewReg->addSuperClass(Supers[i], Ranges[i]);
+ 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) {
@@ -1193,45 +1192,57 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
for (const auto &Idx : SubRegIndices) {
const auto &Composites = Idx.getComposites();
auto &LaneTransforms = Idx.CompositionLaneMaskTransform;
- // 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;
- unsigned SrcMask = 1u << SrcBit;
- if (NextBit < 31)
- ++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.
- unsigned DstBit = Log2_32(Composite->LaneMask);
- int Shift = DstBit - SrcBit;
- uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift : 32+Shift;
- for (auto &I : LaneTransforms) {
- if (I.RotateLeft == RotateLeft) {
- I.Mask |= SrcMask;
- SrcMask = 0;
+
+ 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.
+ unsigned DstBit = Log2_32(Idx.LaneMask);
+ assert(Idx.LaneMask == 1u << DstBit && "Must be a leaf subregister");
+ MaskRolPair MaskRol = { 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;
+ unsigned SrcMask = 1u << SrcBit;
+ if (NextBit < 31)
+ ++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.
+ unsigned DstBit = Log2_32(Composite->LaneMask);
+ int Shift = DstBit - SrcBit;
+ uint8_t RotateLeft = Shift >= 0 ? (uint8_t)Shift : 32+Shift;
+ for (auto &I : LaneTransforms) {
+ if (I.RotateLeft == RotateLeft) {
+ I.Mask |= SrcMask;
+ SrcMask = 0;
+ }
+ }
+ if (SrcMask != 0) {
+ MaskRolPair MaskRol = { SrcMask, RotateLeft };
+ LaneTransforms.push_back(MaskRol);
}
- }
- if (SrcMask != 0) {
- 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.
@@ -1268,10 +1279,10 @@ void CodeGenRegBank::computeSubRegLaneMasks() {
LaneMask |= SubRegIndex.LaneMask;
}
- // For classes without any subregisters set LaneMask to ~0u instead of 0.
+ // 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 == 0)
- LaneMask = ~0u;
+ LaneMask = 1;
RegClass.LaneMask = LaneMask;
}
@@ -1818,11 +1829,14 @@ void CodeGenRegBank::computeDerivedInfo() {
computeRegUnitLaneMasks();
- // Compute register class HasDisjunctSubRegs flag.
+ // Compute register class HasDisjunctSubRegs/CoveredBySubRegs flag.
for (CodeGenRegisterClass &RC : RegClasses) {
RC.HasDisjunctSubRegs = false;
- for (const CodeGenRegister *Reg : RC.getMembers())
+ RC.CoveredBySubRegs = true;
+ for (const CodeGenRegister *Reg : RC.getMembers()) {
RC.HasDisjunctSubRegs |= Reg->HasDisjunctSubRegs;
+ RC.CoveredBySubRegs &= Reg->CoveredBySubRegs;
+ }
}
// Get the weight of each set.
diff --git a/contrib/llvm/utils/TableGen/CodeGenRegisters.h b/contrib/llvm/utils/TableGen/CodeGenRegisters.h
index dc44143..b8d47aa 100644
--- a/contrib/llvm/utils/TableGen/CodeGenRegisters.h
+++ b/contrib/llvm/utils/TableGen/CodeGenRegisters.h
@@ -19,22 +19,21 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SparseBitVector.h"
#include "llvm/CodeGen/MachineValueType.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/SetTheory.h"
#include <cstdlib>
+#include <deque>
#include <list>
#include <map>
-#include <set>
#include <string>
#include <vector>
-#include <deque>
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
@@ -311,6 +310,7 @@ namespace llvm {
unsigned 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.
diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp
index c98f623..d1b141e 100644
--- a/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.cpp
@@ -68,7 +68,7 @@ struct InstRegexOp : public SetTheory::Operator {
}
RegexList.push_back(Regex(pat));
}
- for (const CodeGenInstruction *Inst : Target.instructions()) {
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
for (auto &R : RegexList) {
if (R.match(Inst->TheDef->getName()))
Elts.insert(Inst->TheDef);
@@ -120,12 +120,18 @@ CodeGenSchedModels::CodeGenSchedModels(RecordKeeper &RK,
// (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.
@@ -204,7 +210,7 @@ void CodeGenSchedModels::collectSchedRW() {
// Find all SchedReadWrites referenced by instruction defs.
RecVec SWDefs, SRDefs;
- for (const CodeGenInstruction *Inst : Target.instructions()) {
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
Record *SchedDef = Inst->TheDef;
if (SchedDef->isValueUnset("SchedRW"))
continue;
@@ -498,7 +504,7 @@ void CodeGenSchedModels::collectSchedClasses() {
// Create a SchedClass for each unique combination of itinerary class and
// SchedRW list.
- for (const CodeGenInstruction *Inst : Target.instructions()) {
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
Record *ItinDef = Inst->TheDef->getValueAsDef("Itinerary");
IdxVec Writes, Reads;
if (!Inst->TheDef->isValueUnset("SchedRW"))
@@ -523,11 +529,12 @@ void CodeGenSchedModels::collectSchedClasses() {
if (!EnableDump)
return;
- for (const CodeGenInstruction *Inst : Target.instructions()) {
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
std::string InstName = Inst->TheDef->getName();
unsigned SCIdx = InstrClassMap.lookup(Inst->TheDef);
if (!SCIdx) {
- dbgs() << "No machine model for " << Inst->TheDef->getName() << '\n';
+ if (!Inst->hasNoSchedulingInfo)
+ dbgs() << "No machine model for " << Inst->TheDef->getName() << '\n';
continue;
}
CodeGenSchedClass &SC = getSchedClass(SCIdx);
@@ -826,6 +833,15 @@ void CodeGenSchedModels::collectProcItinRW() {
}
}
+// 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() {
@@ -1426,6 +1442,9 @@ void CodeGenSchedModels::verifyProcResourceGroups(CodeGenProcModel &PM) {
// 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.
@@ -1520,6 +1539,63 @@ void CodeGenSchedModels::collectProcResources() {
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)
+ continue;
+
+ const RecVec &InstRWs = SC.InstRWs;
+ auto I = std::find_if(InstRWs.begin(), InstRWs.end(),
+ [&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.
@@ -1600,8 +1676,8 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind,
return ProcResKind;
Record *ProcUnitDef = nullptr;
- RecVec ProcResourceDefs =
- Records.getAllDerivedDefinitions("ProcResourceUnits");
+ assert(!ProcResourceDefs.empty());
+ assert(!ProcResGroups.empty());
for (RecIter RI = ProcResourceDefs.begin(), RE = ProcResourceDefs.end();
RI != RE; ++RI) {
@@ -1616,7 +1692,6 @@ Record *CodeGenSchedModels::findProcResUnits(Record *ProcResKind,
ProcUnitDef = *RI;
}
}
- RecVec ProcResGroups = Records.getAllDerivedDefinitions("ProcResGroup");
for (RecIter RI = ProcResGroups.begin(), RE = ProcResGroups.end();
RI != RE; ++RI) {
@@ -1699,6 +1774,16 @@ unsigned CodeGenProcModel::getProcResourceIdx(Record *PRDef) const {
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 << " "
diff --git a/contrib/llvm/utils/TableGen/CodeGenSchedule.h b/contrib/llvm/utils/TableGen/CodeGenSchedule.h
index f5c50c9..755ffd2 100644
--- a/contrib/llvm/utils/TableGen/CodeGenSchedule.h
+++ b/contrib/llvm/utils/TableGen/CodeGenSchedule.h
@@ -189,6 +189,10 @@ struct CodeGenProcModel {
// 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;
@@ -211,6 +215,8 @@ struct CodeGenProcModel {
unsigned getProcResourceIdx(Record *PRDef) const;
+ bool isUnsupported(const CodeGenInstruction &Inst) const;
+
#ifndef NDEBUG
void dump() const;
#endif
@@ -241,6 +247,9 @@ class CodeGenSchedModels {
// 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;
@@ -300,6 +309,7 @@ public:
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;
@@ -353,6 +363,7 @@ public:
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; }
@@ -397,8 +408,12 @@ private:
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);
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
index aaad422..245b9ee 100644
--- a/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.cpp
@@ -39,7 +39,7 @@ MVT::SimpleValueType llvm::getValueType(Record *Rec) {
return (MVT::SimpleValueType)Rec->getValueAsInt("Value");
}
-std::string llvm::getName(MVT::SimpleValueType T) {
+StringRef llvm::getName(MVT::SimpleValueType T) {
switch (T) {
case MVT::Other: return "UNKNOWN";
case MVT::iPTR: return "TLI.getPointerTy()";
@@ -48,7 +48,7 @@ std::string llvm::getName(MVT::SimpleValueType T) {
}
}
-std::string llvm::getEnumName(MVT::SimpleValueType T) {
+StringRef llvm::getEnumName(MVT::SimpleValueType T) {
switch (T) {
case MVT::Other: return "MVT::Other";
case MVT::i1: return "MVT::i1";
@@ -162,7 +162,7 @@ const std::string &CodeGenTarget::getName() const {
}
std::string CodeGenTarget::getInstNamespace() const {
- for (const CodeGenInstruction *Inst : instructions()) {
+ 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")
@@ -300,14 +300,9 @@ GetInstByName(const char *Name,
/// \brief Return all of the instructions defined by the target, ordered by
/// their enum value.
void CodeGenTarget::ComputeInstrsByEnum() const {
- // The ordering here must match the ordering in TargetOpcodes.h.
static const char *const FixedInstrs[] = {
- "PHI", "INLINEASM", "CFI_INSTRUCTION", "EH_LABEL",
- "GC_LABEL", "KILL", "EXTRACT_SUBREG", "INSERT_SUBREG",
- "IMPLICIT_DEF", "SUBREG_TO_REG", "COPY_TO_REGCLASS", "DBG_VALUE",
- "REG_SEQUENCE", "COPY", "BUNDLE", "LIFETIME_START",
- "LIFETIME_END", "STACKMAP", "PATCHPOINT", "LOAD_STACK_GUARD",
- "STATEPOINT", "LOCAL_ESCAPE", "FAULTING_LOAD_OP",
+#define HANDLE_TARGET_OPCODE(OPC, NUM) #OPC,
+#include "llvm/Target/TargetOpcodes.def"
nullptr};
const auto &Insts = getInstructions();
for (const char *const *p = FixedInstrs; *p; ++p) {
@@ -357,9 +352,9 @@ void CodeGenTarget::reverseBitsForLittleEndianEncoding() {
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);
@@ -431,18 +426,29 @@ ComplexPattern::ComplexPattern(Record *R) {
// CodeGenIntrinsic Implementation
//===----------------------------------------------------------------------===//
-std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC,
- bool TargetOnly) {
- std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic");
+CodeGenIntrinsicTable::CodeGenIntrinsicTable(const RecordKeeper &RC,
+ bool TargetOnly) {
+ std::vector<Record*> Defs = RC.getAllDerivedDefinitions("Intrinsic");
- std::vector<CodeGenIntrinsic> Result;
+ Intrinsics.reserve(Defs.size());
- for (unsigned i = 0, e = I.size(); i != e; ++i) {
- bool isTarget = I[i]->getValueAsBit("isTarget");
+ for (unsigned I = 0, e = Defs.size(); I != e; ++I) {
+ bool isTarget = Defs[I]->getValueAsBit("isTarget");
if (isTarget == TargetOnly)
- Result.push_back(CodeGenIntrinsic(I[i]));
+ Intrinsics.push_back(CodeGenIntrinsic(Defs[I]));
}
- return Result;
+ 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) {
@@ -565,7 +571,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
}
// Parse the intrinsic properties.
- ListInit *PropList = R->getValueAsListInit("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") &&
@@ -573,12 +579,12 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
if (Property->getName() == "IntrNoMem")
ModRef = NoMem;
- else if (Property->getName() == "IntrReadArgMem")
- ModRef = ReadArgMem;
else if (Property->getName() == "IntrReadMem")
- ModRef = ReadMem;
- else if (Property->getName() == "IntrReadWriteArgMem")
- ModRef = ReadWriteArgMem;
+ 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);
else if (Property->getName() == "Commutative")
isCommutative = true;
else if (Property->getName() == "Throws")
@@ -592,9 +598,15 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
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));
diff --git a/contrib/llvm/utils/TableGen/CodeGenTarget.h b/contrib/llvm/utils/TableGen/CodeGenTarget.h
index cf4a0bb..85a8c1b 100644
--- a/contrib/llvm/utils/TableGen/CodeGenTarget.h
+++ b/contrib/llvm/utils/TableGen/CodeGenTarget.h
@@ -52,8 +52,8 @@ enum SDNP {
/// record corresponds to.
MVT::SimpleValueType getValueType(Record *Rec);
-std::string getName(MVT::SimpleValueType T);
-std::string getEnumName(MVT::SimpleValueType T);
+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.
@@ -139,9 +139,7 @@ public:
/// supported by the target (i.e. there are registers that directly hold it).
bool isLegalValueType(MVT::SimpleValueType VT) const {
ArrayRef<MVT::SimpleValueType> LegalVTs = getLegalValueTypes();
- for (unsigned i = 0, e = LegalVTs.size(); i != e; ++i)
- if (LegalVTs[i] == VT) return true;
- return false;
+ return std::find(LegalVTs.begin(), LegalVTs.end(), VT) != LegalVTs.end();
}
CodeGenSchedModels &getSchedModels() const;
@@ -163,18 +161,15 @@ public:
/// getInstructionsByEnumValue - Return all of the instructions defined by the
/// target, ordered by their enum value.
- const std::vector<const CodeGenInstruction*> &
+ ArrayRef<const CodeGenInstruction *>
getInstructionsByEnumValue() const {
if (InstrsByEnum.empty()) ComputeInstrsByEnum();
return InstrsByEnum;
}
- typedef std::vector<const CodeGenInstruction*>::const_iterator inst_iterator;
+ typedef ArrayRef<const CodeGenInstruction *>::const_iterator inst_iterator;
inst_iterator inst_begin() const{return getInstructionsByEnumValue().begin();}
inst_iterator inst_end() const { return getInstructionsByEnumValue().end(); }
- iterator_range<inst_iterator> instructions() const {
- return make_range(inst_begin(), inst_end());
- }
/// isLittleEndianEncoding - are instruction bit patterns defined as [0..n]?
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp
index 9c40799..6ac3958 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.cpp
@@ -225,12 +225,14 @@ void CheckFoldableChainNodeMatcher::printImpl(raw_ostream &OS,
}
void EmitIntegerMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
- OS.indent(indent) << "EmitInteger " << Val << " VT=" << VT << '\n';
+ OS.indent(indent) << "EmitInteger " << Val << " VT=" << getEnumName(VT)
+ << '\n';
}
void EmitStringIntegerMatcher::
printImpl(raw_ostream &OS, unsigned indent) const {
- OS.indent(indent) << "EmitStringInteger " << Val << " VT=" << VT << '\n';
+ OS.indent(indent) << "EmitStringInteger " << Val << " VT=" << getEnumName(VT)
+ << '\n';
}
void EmitRegisterMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
@@ -239,7 +241,7 @@ void EmitRegisterMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
OS << Reg->getName();
else
OS << "zero_reg";
- OS << " VT=" << VT << '\n';
+ OS << " VT=" << getEnumName(VT) << '\n';
}
void EmitConvertToTargetMatcher::
@@ -275,54 +277,12 @@ void EmitNodeMatcherCommon::printImpl(raw_ostream &OS, unsigned indent) const {
OS << ")\n";
}
-void MarkGlueResultsMatcher::printImpl(raw_ostream &OS, unsigned indent) const {
- OS.indent(indent) << "MarkGlueResults <todo: args>\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";
}
-// getHashImpl Implementation.
-
-unsigned CheckPatternPredicateMatcher::getHashImpl() const {
- return HashString(Predicate);
-}
-
-unsigned CheckPredicateMatcher::getHashImpl() const {
- return HashString(getPredicate().getFnName());
-}
-
-unsigned CheckOpcodeMatcher::getHashImpl() const {
- return HashString(Opcode.getEnumName());
-}
-
-unsigned CheckCondCodeMatcher::getHashImpl() const {
- return HashString(CondCodeName);
-}
-
-unsigned CheckValueTypeMatcher::getHashImpl() const {
- return HashString(TypeName);
-}
-
-unsigned EmitStringIntegerMatcher::getHashImpl() const {
- return HashString(Val) ^ VT;
-}
-
-template<typename It>
-static unsigned HashUnsigneds(It I, It E) {
- unsigned Result = 0;
- for (; I != E; ++I)
- Result = (Result<<3) ^ *I;
- return Result;
-}
-
-unsigned EmitMergeInputChainsMatcher::getHashImpl() const {
- return HashUnsigneds(ChainNodes.begin(), ChainNodes.end());
-}
-
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.
@@ -339,24 +299,10 @@ bool EmitNodeMatcherCommon::isEqualImpl(const Matcher *m) const {
M->NumFixedArityOperands == NumFixedArityOperands;
}
-unsigned EmitNodeMatcherCommon::getHashImpl() const {
- return (HashString(OpcodeName) << 4) | Operands.size();
-}
-
-
void EmitNodeMatcher::anchor() { }
void MorphNodeToMatcher::anchor() { }
-unsigned MarkGlueResultsMatcher::getHashImpl() const {
- return HashUnsigneds(GlueResultNodes.begin(), GlueResultNodes.end());
-}
-
-unsigned CompleteMatchMatcher::getHashImpl() const {
- return HashUnsigneds(Results.begin(), Results.end()) ^
- ((unsigned)(intptr_t)&Pattern << 8);
-}
-
// isContradictoryImpl Implementations.
static bool TypesAreContradictory(MVT::SimpleValueType T1,
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcher.h b/contrib/llvm/utils/TableGen/DAGISelMatcher.h
index a8a6ba5..6bda9ca 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcher.h
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcher.h
@@ -82,7 +82,6 @@ public:
EmitCopyToReg, // Emit a copytoreg into a physreg.
EmitNode, // Create a DAG node
EmitNodeXForm, // Run a SDNodeXForm
- MarkGlueResults, // Indicate which interior nodes have glue results.
CompleteMatch, // Finish a match and update the results.
MorphNodeTo // Build a node, finish a match and update results.
};
@@ -107,17 +106,6 @@ public:
return isEqualImpl(M);
}
- unsigned getHash() const {
- // Clear the high bit so we don't conflict with tombstones etc.
- return ((getHashImpl() << 4) ^ getKind()) & (~0U>>1);
- }
-
- /// isSafeToReorderWithPatternPredicate - Return true if it is safe to sink a
- /// PatternPredicate node past this one.
- virtual bool isSafeToReorderWithPatternPredicate() const {
- return false;
- }
-
/// 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.
@@ -181,7 +169,6 @@ public:
protected:
virtual void printImpl(raw_ostream &OS, unsigned indent) const = 0;
virtual bool isEqualImpl(const Matcher *M) const = 0;
- virtual unsigned getHashImpl() const = 0;
virtual bool isContradictoryImpl(const Matcher *M) const { return false; }
};
@@ -228,7 +215,6 @@ public:
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override { return false; }
- unsigned getHashImpl() const override { return 12312; }
};
/// RecordMatcher - Save the current node in the operand list.
@@ -251,11 +237,9 @@ public:
return N->getKind() == RecordNode;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override { return true; }
- unsigned getHashImpl() const override { return 0; }
};
/// RecordChildMatcher - Save a numbered child of the current node, or fail
@@ -285,14 +269,11 @@ public:
return N->getKind() == RecordChild;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<RecordChildMatcher>(M)->getChildNo() == getChildNo();
}
- unsigned getHashImpl() const override { return getChildNo(); }
};
/// RecordMemRefMatcher - Save the current node's memref.
@@ -304,12 +285,9 @@ public:
return N->getKind() == RecordMemRef;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override { return true; }
- unsigned getHashImpl() const override { return 0; }
};
@@ -323,12 +301,9 @@ public:
return N->getKind() == CaptureGlueInput;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override { return true; }
- unsigned getHashImpl() const override { return 0; }
};
/// MoveChildMatcher - This tells the interpreter to move into the
@@ -344,14 +319,11 @@ public:
return N->getKind() == MoveChild;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<MoveChildMatcher>(M)->getChildNo() == getChildNo();
}
- unsigned getHashImpl() const override { return getChildNo(); }
};
/// MoveParentMatcher - This tells the interpreter to move to the parent
@@ -364,12 +336,9 @@ public:
return N->getKind() == MoveParent;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override { return true; }
- unsigned getHashImpl() const override { return 0; }
};
/// CheckSameMatcher - This checks to see if this node is exactly the same
@@ -387,14 +356,11 @@ public:
return N->getKind() == CheckSame;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<CheckSameMatcher>(M)->getMatchNumber() == getMatchNumber();
}
- unsigned getHashImpl() const override { return getMatchNumber(); }
};
/// CheckChildSameMatcher - This checks to see if child node is exactly the same
@@ -414,15 +380,12 @@ public:
return N->getKind() == CheckChildSame;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
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;
}
- unsigned getHashImpl() const override { return (MatchNumber << 2) | ChildNo; }
};
/// CheckPatternPredicateMatcher - This checks the target-specific predicate
@@ -440,14 +403,11 @@ public:
return N->getKind() == CheckPatternPredicate;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<CheckPatternPredicateMatcher>(M)->getPredicate() == Predicate;
}
- unsigned getHashImpl() const override;
};
/// CheckPredicateMatcher - This checks the target-specific predicate to
@@ -463,15 +423,11 @@ public:
return N->getKind() == CheckPredicate;
}
- // TODO: Ok?
- //virtual bool isSafeToReorderWithPatternPredicate() const { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<CheckPredicateMatcher>(M)->Pred == Pred;
}
- unsigned getHashImpl() const override;
};
@@ -489,12 +445,9 @@ public:
return N->getKind() == CheckOpcode;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override;
- unsigned getHashImpl() const override;
bool isContradictoryImpl(const Matcher *M) const override;
};
@@ -522,7 +475,6 @@ public:
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override { return false; }
- unsigned getHashImpl() const override { return 4123; }
};
/// CheckTypeMatcher - This checks to see if the current node has the
@@ -541,14 +493,11 @@ public:
return N->getKind() == CheckType;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<CheckTypeMatcher>(M)->Type == Type;
}
- unsigned getHashImpl() const override { return Type; }
bool isContradictoryImpl(const Matcher *M) const override;
};
@@ -576,7 +525,6 @@ public:
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override { return false; }
- unsigned getHashImpl() const override { return 4123; }
};
@@ -596,15 +544,12 @@ public:
return N->getKind() == CheckChildType;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
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;
}
- unsigned getHashImpl() const override { return (Type << 3) | ChildNo; }
bool isContradictoryImpl(const Matcher *M) const override;
};
@@ -623,14 +568,11 @@ public:
return N->getKind() == CheckInteger;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<CheckIntegerMatcher>(M)->Value == Value;
}
- unsigned getHashImpl() const override { return Value; }
bool isContradictoryImpl(const Matcher *M) const override;
};
@@ -650,15 +592,12 @@ public:
return N->getKind() == CheckChildInteger;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
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;
}
- unsigned getHashImpl() const override { return (Value << 3) | ChildNo; }
bool isContradictoryImpl(const Matcher *M) const override;
};
@@ -676,14 +615,11 @@ public:
return N->getKind() == CheckCondCode;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<CheckCondCodeMatcher>(M)->CondCodeName == CondCodeName;
}
- unsigned getHashImpl() const override;
};
/// CheckValueTypeMatcher - This checks to see if the current node is a
@@ -700,14 +636,11 @@ public:
return N->getKind() == CheckValueType;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<CheckValueTypeMatcher>(M)->TypeName == TypeName;
}
- unsigned getHashImpl() const override;
bool isContradictoryImpl(const Matcher *M) const override;
};
@@ -744,18 +677,12 @@ public:
return N->getKind() == CheckComplexPat;
}
- // Not safe to move a pattern predicate past a complex pattern.
- bool isSafeToReorderWithPatternPredicate() const override { return false; }
-
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;
}
- unsigned getHashImpl() const override {
- return (unsigned)(intptr_t)&Pattern ^ MatchNumber;
- }
};
/// CheckAndImmMatcher - This checks to see if the current node is an 'and'
@@ -772,14 +699,11 @@ public:
return N->getKind() == CheckAndImm;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<CheckAndImmMatcher>(M)->Value == Value;
}
- unsigned getHashImpl() const override { return Value; }
};
/// CheckOrImmMatcher - This checks to see if the current node is an 'and'
@@ -796,14 +720,11 @@ public:
return N->getKind() == CheckOrImm;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override {
return cast<CheckOrImmMatcher>(M)->Value == Value;
}
- unsigned getHashImpl() const override { return Value; }
};
/// CheckFoldableChainNodeMatcher - This checks to see if the current node
@@ -817,12 +738,9 @@ public:
return N->getKind() == CheckFoldableChainNode;
}
- bool isSafeToReorderWithPatternPredicate() const override { return true; }
-
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override { return true; }
- unsigned getHashImpl() const override { return 0; }
};
/// EmitIntegerMatcher - This creates a new TargetConstant.
@@ -846,7 +764,6 @@ private:
return cast<EmitIntegerMatcher>(M)->Val == Val &&
cast<EmitIntegerMatcher>(M)->VT == VT;
}
- unsigned getHashImpl() const override { return (Val << 4) | VT; }
};
/// EmitStringIntegerMatcher - A target constant whose value is represented
@@ -871,7 +788,6 @@ private:
return cast<EmitStringIntegerMatcher>(M)->Val == Val &&
cast<EmitStringIntegerMatcher>(M)->VT == VT;
}
- unsigned getHashImpl() const override;
};
/// EmitRegisterMatcher - This creates a new TargetConstant.
@@ -897,9 +813,6 @@ private:
return cast<EmitRegisterMatcher>(M)->Reg == Reg &&
cast<EmitRegisterMatcher>(M)->VT == VT;
}
- unsigned getHashImpl() const override {
- return ((unsigned)(intptr_t)Reg) << 4 | VT;
- }
};
/// EmitConvertToTargetMatcher - Emit an operation that reads a specified
@@ -922,7 +835,6 @@ private:
bool isEqualImpl(const Matcher *M) const override {
return cast<EmitConvertToTargetMatcher>(M)->Slot == Slot;
}
- unsigned getHashImpl() const override { return Slot; }
};
/// EmitMergeInputChainsMatcher - Emit a node that merges a list of input
@@ -951,7 +863,6 @@ private:
bool isEqualImpl(const Matcher *M) const override {
return cast<EmitMergeInputChainsMatcher>(M)->ChainNodes == ChainNodes;
}
- unsigned getHashImpl() const override;
};
/// EmitCopyToRegMatcher - Emit a CopyToReg node from a value to a physreg,
@@ -977,9 +888,6 @@ private:
return cast<EmitCopyToRegMatcher>(M)->SrcSlot == SrcSlot &&
cast<EmitCopyToRegMatcher>(M)->DestPhysReg == DestPhysReg;
}
- unsigned getHashImpl() const override {
- return SrcSlot ^ ((unsigned)(intptr_t)DestPhysReg << 4);
- }
};
@@ -1006,9 +914,6 @@ private:
return cast<EmitNodeXFormMatcher>(M)->Slot == Slot &&
cast<EmitNodeXFormMatcher>(M)->NodeXForm == NodeXForm;
}
- unsigned getHashImpl() const override {
- return Slot ^ ((unsigned)(intptr_t)NodeXForm << 4);
- }
};
/// EmitNodeMatcherCommon - Common class shared between EmitNode and
@@ -1066,7 +971,6 @@ public:
private:
void printImpl(raw_ostream &OS, unsigned indent) const override;
bool isEqualImpl(const Matcher *M) const override;
- unsigned getHashImpl() const override;
};
/// EmitNodeMatcher - This signals a successful match and generates a node.
@@ -1116,34 +1020,6 @@ public:
}
};
-/// MarkGlueResultsMatcher - This node indicates which non-root nodes in the
-/// pattern produce glue. This allows CompleteMatchMatcher to update them
-/// with the output glue of the resultant code.
-class MarkGlueResultsMatcher : public Matcher {
- SmallVector<unsigned, 3> GlueResultNodes;
-public:
- MarkGlueResultsMatcher(ArrayRef<unsigned> nodes)
- : Matcher(MarkGlueResults), GlueResultNodes(nodes.begin(), nodes.end()) {}
-
- unsigned getNumNodes() const { return GlueResultNodes.size(); }
-
- unsigned getNode(unsigned i) const {
- assert(i < GlueResultNodes.size());
- return GlueResultNodes[i];
- }
-
- static inline bool classof(const Matcher *N) {
- return N->getKind() == MarkGlueResults;
- }
-
-private:
- void printImpl(raw_ostream &OS, unsigned indent) const override;
- bool isEqualImpl(const Matcher *M) const override {
- return cast<MarkGlueResultsMatcher>(M)->GlueResultNodes == GlueResultNodes;
- }
- unsigned getHashImpl() const override;
-};
-
/// 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.
@@ -1170,7 +1046,6 @@ private:
return cast<CompleteMatchMatcher>(M)->Results == Results &&
&cast<CompleteMatchMatcher>(M)->Pattern == &Pattern;
}
- unsigned getHashImpl() const override;
};
} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
index 26f53dc..d30fc51 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherEmitter.cpp
@@ -247,9 +247,16 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
OS << "OPC_CaptureGlueInput,\n";
return 1;
- case Matcher::MoveChild:
- OS << "OPC_MoveChild, " << cast<MoveChildMatcher>(N)->getChildNo() << ",\n";
- return 2;
+ 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";
@@ -500,8 +507,8 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
const EmitMergeInputChainsMatcher *MN =
cast<EmitMergeInputChainsMatcher>(N);
- // Handle the specialized forms OPC_EmitMergeInputChains1_0 and 1_1.
- if (MN->getNumNodes() == 1 && MN->getNode(0) < 2) {
+ // 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;
}
@@ -532,6 +539,10 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
case Matcher::MorphNodeTo: {
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";
@@ -542,10 +553,13 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
OS << "|OPFL_Variadic" << EN->getNumFixedArityOperands();
OS << ",\n";
- OS.PadToColumn(Indent*2+4) << EN->getNumVTs();
- if (!OmitComments)
- OS << "/*#VTs*/";
- OS << ", ";
+ 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)) << ", ";
@@ -579,16 +593,7 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx,
} else
OS << '\n';
- return 6+EN->getNumVTs()+NumOperandBytes;
- }
- case Matcher::MarkGlueResults: {
- const MarkGlueResultsMatcher *CFR = cast<MarkGlueResultsMatcher>(N);
- OS << "OPC_MarkGlueResults, " << CFR->getNumNodes() << ", ";
- unsigned NumOperandBytes = 0;
- for (unsigned i = 0, e = CFR->getNumNodes(); i != e; ++i)
- NumOperandBytes += EmitVBRValue(CFR->getNode(i), OS);
- OS << '\n';
- return 2+NumOperandBytes;
+ return 5 + !CompressVTs + EN->getNumVTs() + NumOperandBytes;
}
case Matcher::CompleteMatch: {
const CompleteMatchMatcher *CM = cast<CompleteMatchMatcher>(N);
@@ -807,7 +812,6 @@ void MatcherTableEmitter::EmitHistogram(const Matcher *M,
case Matcher::EmitNode: OS << "OPC_EmitNode"; break;
case Matcher::MorphNodeTo: OS << "OPC_MorphNodeTo"; break;
case Matcher::EmitNodeXForm: OS << "OPC_EmitNodeXForm"; break;
- case Matcher::MarkGlueResults: OS << "OPC_MarkGlueResults"; break;
case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break;
}
@@ -837,8 +841,9 @@ void llvm::EmitMatcherTable(const Matcher *TheMatcher,
MatcherEmitter.EmitHistogram(TheMatcher, OS);
OS << " #undef TARGET_VAL\n";
- OS << " return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n";
- OS << '\n';
+ OS << " SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n";
+ OS << " return nullptr;\n";
+ OS << "}\n";
// Next up, emit the function for node and pattern predicates:
MatcherEmitter.EmitPredicateFunctions(OS);
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
index 9663b71..4110e97 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherGen.cpp
@@ -10,7 +10,6 @@
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
#include "CodeGenRegisters.h"
-#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/TableGen/Error.h"
@@ -76,10 +75,6 @@ namespace {
/// array of all of the recorded input nodes that have chains.
SmallVector<unsigned, 2> MatchedChainNodes;
- /// MatchedGlueResultNodes - This maintains the position in the recorded
- /// nodes array of all of the recorded input nodes that have glue results.
- SmallVector<unsigned, 2> MatchedGlueResultNodes;
-
/// 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.
@@ -121,7 +116,7 @@ namespace {
/// 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(std::string Name);
+ bool recordUniqueNode(const std::string &Name);
// Result Code Generation.
unsigned getNamedArgumentSlot(StringRef Name) {
@@ -426,8 +421,6 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
AddMatcher(new RecordMatcher("'" + N->getOperator()->getName() +
"' glue output node",
NextRecordedOperandNo));
- // Remember all of the nodes with output glue our pattern will match.
- MatchedGlueResultNodes.push_back(NextRecordedOperandNo++);
}
// If this node is known to have an input glue or if it *might* have an input
@@ -445,7 +438,7 @@ void MatcherGen::EmitOperatorMatchCode(const TreePatternNode *N,
}
}
-bool MatcherGen::recordUniqueNode(std::string Name) {
+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.
@@ -989,11 +982,6 @@ void MatcherGen::EmitResultCode() {
assert(Ops.size() >= NumSrcResults && "Didn't provide enough results");
Ops.resize(NumSrcResults);
- // If the matched pattern covers nodes which define a glue result, emit a node
- // that tells the matcher about them so that it can update their results.
- if (!MatchedGlueResultNodes.empty())
- AddMatcher(new MarkGlueResultsMatcher(MatchedGlueResultNodes));
-
AddMatcher(new CompleteMatchMatcher(Ops, Pattern));
}
diff --git a/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
index c9ee371..ad385fa 100644
--- a/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/contrib/llvm/utils/TableGen/DAGISelMatcherOpt.cpp
@@ -13,7 +13,6 @@
#include "DAGISelMatcher.h"
#include "CodeGenDAGPatterns.h"
-#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -79,24 +78,6 @@ static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr,
return ContractNodes(MatcherPtr, CGP);
}
- // Turn EmitNode->MarkFlagResults->CompleteMatch into
- // MarkFlagResults->EmitNode->CompleteMatch when we can to encourage
- // MorphNodeTo formation. This is safe because MarkFlagResults never refers
- // to the root of the pattern.
- if (isa<EmitNodeMatcher>(N) && isa<MarkGlueResultsMatcher>(N->getNext()) &&
- isa<CompleteMatchMatcher>(N->getNext()->getNext())) {
- // Unlink the two nodes from the list.
- Matcher *EmitNode = MatcherPtr.release();
- Matcher *MFR = EmitNode->takeNext();
- Matcher *Tail = MFR->takeNext();
-
- // Relink them.
- MatcherPtr.reset(MFR);
- MFR->setNext(EmitNode);
- EmitNode->setNext(Tail);
- return ContractNodes(MatcherPtr, CGP);
- }
-
// Turn EmitNode->CompleteMatch into MorphNodeTo if we can.
if (EmitNodeMatcher *EN = dyn_cast<EmitNodeMatcher>(N))
if (CompleteMatchMatcher *CM =
@@ -177,59 +158,6 @@ static void ContractNodes(std::unique_ptr<Matcher> &MatcherPtr,
}
}
-/// SinkPatternPredicates - Pattern predicates can be checked at any level of
-/// the matching tree. The generator dumps them at the top level of the pattern
-/// though, which prevents factoring from being able to see past them. This
-/// optimization sinks them as far down into the pattern as possible.
-///
-/// Conceptually, we'd like to sink these predicates all the way to the last
-/// matcher predicate in the series. However, it turns out that some
-/// ComplexPatterns have side effects on the graph, so we really don't want to
-/// run a complex pattern if the pattern predicate will fail. For this
-/// reason, we refuse to sink the pattern predicate past a ComplexPattern.
-///
-static void SinkPatternPredicates(std::unique_ptr<Matcher> &MatcherPtr) {
- // Recursively scan for a PatternPredicate.
- // If we reached the end of the chain, we're done.
- Matcher *N = MatcherPtr.get();
- if (!N) return;
-
- // Walk down all members of a scope node.
- 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));
- SinkPatternPredicates(Child);
- Scope->resetChild(i, Child.release());
- }
- return;
- }
-
- // If this node isn't a CheckPatternPredicateMatcher we keep scanning until
- // we find one.
- CheckPatternPredicateMatcher *CPPM =dyn_cast<CheckPatternPredicateMatcher>(N);
- if (!CPPM)
- return SinkPatternPredicates(N->getNextPtr());
-
- // Ok, we found one, lets try to sink it. Check if we can sink it past the
- // next node in the chain. If not, we won't be able to change anything and
- // might as well bail.
- if (!CPPM->getNext()->isSafeToReorderWithPatternPredicate())
- return;
-
- // Okay, we know we can sink it past at least one node. Unlink it from the
- // chain and scan for the new insertion point.
- MatcherPtr.release(); // Don't delete CPPM.
- MatcherPtr.reset(CPPM->takeNext());
-
- N = MatcherPtr.get();
- while (N->getNext()->isSafeToReorderWithPatternPredicate())
- N = N->getNext();
-
- // At this point, we want to insert CPPM after N.
- CPPM->setNext(N->takeNext());
- N->setNext(CPPM);
-}
-
/// 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.
@@ -264,8 +192,7 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) {
return FactorNodes(N->getNextPtr());
// Okay, pull together the children of the scope node into a vector so we can
- // inspect it more easily. While we're at it, bucket them up by the hash
- // code of their first predicate.
+ // inspect it more easily.
SmallVector<Matcher*, 32> OptionsToMatch;
for (unsigned i = 0, e = Scope->getNumChildren(); i != e; ++i) {
@@ -456,7 +383,8 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) {
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->getNext()));
+ Cases.push_back(std::make_pair(&COM->getOpcode(), COM->takeNext()));
+ delete COM;
}
MatcherPtr.reset(new SwitchOpcodeMatcher(Cases));
@@ -486,7 +414,9 @@ static void FactorNodes(std::unique_ptr<Matcher> &MatcherPtr) {
}
Matcher *Entries[2] = { PrevMatcher, MatcherWithoutCTM };
- Cases[Entry-1].second = new ScopeMatcher(Entries);
+ std::unique_ptr<Matcher> Case(new ScopeMatcher(Entries));
+ FactorNodes(Case);
+ Cases[Entry-1].second = Case.release();
continue;
}
@@ -515,6 +445,5 @@ void
llvm::OptimizeMatcher(std::unique_ptr<Matcher> &MatcherPtr,
const CodeGenDAGPatterns &CGP) {
ContractNodes(MatcherPtr, CGP);
- SinkPatternPredicates(MatcherPtr);
FactorNodes(MatcherPtr);
}
diff --git a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
index 77afff7..e31caaf 100644
--- a/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DFAPacketizerEmitter.cpp
@@ -1,4 +1,4 @@
-//===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine-----===//
+//===- DFAPacketizerEmitter.cpp - Packetization DFA for a VLIW machine ----===//
//
// The LLVM Compiler Infrastructure
//
@@ -24,10 +24,10 @@
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/Support/Debug.h"
-#include <list>
#include <map>
#include <string>
#include <queue>
+
using namespace llvm;
// --------------------------------------------------------------------
@@ -73,7 +73,8 @@ namespace {
InsnInput = addDFAFuncUnits(InsnInput, U);
return InsnInput;
}
-}
+} // end anonymous namespace
+
// --------------------------------------------------------------------
#ifndef NDEBUG
@@ -149,7 +150,7 @@ public:
void run(raw_ostream &OS);
};
-} // End anonymous namespace.
+} // end anonymous namespace
//
//
@@ -234,7 +235,7 @@ class State {
//
bool hasTransition(std::vector<unsigned> InsnClass) const;
};
-} // End anonymous namespace.
+} // end anonymous namespace
//
// class DFA: deterministic finite automaton for processor resource tracking.
@@ -262,7 +263,7 @@ public:
int numInsnClasses = 0,
int maxResources = 0, int numCombos = 0, int maxStages = 0);
};
-} // End anonymous namespace.
+} // end anonymous namespace
#ifndef NDEBUG
// To enable debugging, run llvm-tblgen with: "-debug-only dfa-emitter".
@@ -305,7 +306,7 @@ void dbgsIndent(unsigned indent) {
DEBUG(dbgs() << " ");
}
}
-#endif
+#endif // NDEBUG
//
// Constructors and destructors for State and DFA
@@ -454,7 +455,6 @@ void State::AddInsnClassStages(std::vector<unsigned> &InsnClass,
}
}
-
//
// canMaybeAddInsnClass - Quickly verifies if an instruction of type InsnClass
// may be a valid transition from this state i.e., can an instruction of type
@@ -505,7 +505,6 @@ bool State::canMaybeAddInsnClass(std::vector<unsigned> &InsnClass,
return false;
}
-
const State &DFA::newState() {
auto IterPair = states.insert(State());
assert(IterPair.second && "State already exists");
@@ -518,7 +517,6 @@ DFAPacketizerEmitter::DFAPacketizerEmitter(RecordKeeper &R):
TargetName(CodeGenTarget(R).getName()),
allInsnClasses(), Records(R) {}
-
//
// writeTableAndAPI - Print out a table representing the DFA and the
// associated API to create a DFA packetizer.
@@ -626,7 +624,6 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName,
OS << "};\n";
OS << "} // namespace\n";
-
//
// Emit DFA Packetizer tables if the target is a VLIW machine.
//
@@ -640,7 +637,6 @@ void DFA::writeTableAndAPI(raw_ostream &OS, const std::string &TargetName,
OS << "} // End llvm namespace \n";
}
-
//
// collectAllFuncUnits - Construct a map of function unit names to bits.
//
@@ -713,7 +709,7 @@ int DFAPacketizerEmitter::collectAllComboFuncs(
Record *ComboFunc = FuncData->getValueAsDef("TheComboFunc");
const std::vector<Record*> &FuncList =
FuncData->getValueAsListOfDefs("FuncList");
- std::string ComboFuncName = ComboFunc->getName();
+ const std::string &ComboFuncName = ComboFunc->getName();
unsigned ComboBit = FUNameToBitsMap[ComboFuncName];
unsigned ComboResources = ComboBit;
DEBUG(dbgs() << " combo: " << ComboFuncName
@@ -735,7 +731,6 @@ int DFAPacketizerEmitter::collectAllComboFuncs(
return numCombos;
}
-
//
// collectOneInsnClass - Populate allInsnClasses with one instruction class
//
@@ -940,7 +935,7 @@ void DFAPacketizerEmitter::run(raw_ostream &OS) {
//
if (!current->hasTransition(InsnClass) &&
current->canMaybeAddInsnClass(InsnClass, ComboBitToBitsMap)) {
- const State *NewState = NULL;
+ const State *NewState = nullptr;
current->AddInsnClass(InsnClass, ComboBitToBitsMap, NewStateResources);
if (NewStateResources.size() == 0) {
DEBUG(dbgs() << " Skipped - no new states generated\n");
@@ -994,4 +989,4 @@ void EmitDFAPacketizer(RecordKeeper &RK, raw_ostream &OS) {
DFAPacketizerEmitter(RK).run(OS);
}
-} // End llvm namespace
+} // end namespaec llvm
diff --git a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
index e859527..44815b0 100644
--- a/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/DisassemblerEmitter.cpp
@@ -96,12 +96,11 @@ using namespace llvm::X86Disassembler;
namespace llvm {
extern void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
- std::string PredicateNamespace,
- std::string GPrefix,
- std::string GPostfix,
- std::string ROK,
- std::string RFail,
- std::string L);
+ 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);
@@ -111,7 +110,7 @@ void EmitDisassembler(RecordKeeper &Records, raw_ostream &OS) {
if (Target.getName() == "X86") {
DisassemblerTables Tables;
- const std::vector<const CodeGenInstruction*> &numberedInstructions =
+ ArrayRef<const CodeGenInstruction*> numberedInstructions =
Target.getInstructionsByEnumValue();
for (unsigned i = 0, e = numberedInstructions.size(); i != e; ++i)
diff --git a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
index 748c923..debb12c 100644
--- a/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/FastISelEmitter.cpp
@@ -18,13 +18,13 @@
//===----------------------------------------------------------------------===//
#include "CodeGenDAGPatterns.h"
-#include "llvm/ADT/SmallString.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;
@@ -417,9 +417,7 @@ static std::string getLegalCName(std::string OpName) {
return OpName;
}
-FastISelMap::FastISelMap(std::string instns)
- : InstNS(instns) {
-}
+FastISelMap::FastISelMap(std::string instns) : InstNS(std::move(instns)) {}
static std::string PhyRegForNode(TreePatternNode *Op,
const CodeGenTarget &Target) {
diff --git a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
index 8ca4a1b..0506400 100644
--- a/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/FixedLenDecoderEmitter.cpp
@@ -28,6 +28,7 @@
#include "llvm/TableGen/Record.h"
#include <map>
#include <string>
+#include <utility>
#include <vector>
using namespace llvm;
@@ -47,7 +48,7 @@ struct OperandInfo {
bool HasCompleteDecoder;
OperandInfo(std::string D, bool HCD)
- : Decoder(D), HasCompleteDecoder(HCD) { }
+ : Decoder(std::move(D)), HasCompleteDecoder(HCD) {}
void addField(unsigned Base, unsigned Width, unsigned Offset) {
Fields.push_back(EncodingField(Base, Width, Offset));
@@ -78,22 +79,21 @@ struct DecoderTableInfo {
namespace {
class FixedLenDecoderEmitter {
- const std::vector<const CodeGenInstruction*> *NumberedInstructions;
+ 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 (",
+ 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(PredicateNamespace),
- GuardPrefix(GPrefix), GuardPostfix(GPostfix),
- ReturnOK(ROK), ReturnFail(RFail), Locals(L) {}
+ 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,
@@ -306,7 +306,7 @@ protected:
friend class Filter;
// Vector of codegen instructions to choose our filter.
- const std::vector<const CodeGenInstruction*> &AllInstructions;
+ ArrayRef<const CodeGenInstruction *> AllInstructions;
// Vector of uid's for this filter chooser to work on.
const std::vector<unsigned> &Opcodes;
@@ -337,7 +337,7 @@ protected:
void operator=(const FilterChooser &) = delete;
public:
- FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
+ FilterChooser(ArrayRef<const CodeGenInstruction *> Insts,
const std::vector<unsigned> &IDs,
const std::map<unsigned, std::vector<OperandInfo> > &Ops,
unsigned BW,
@@ -348,7 +348,7 @@ public:
doFilter();
}
- FilterChooser(const std::vector<const CodeGenInstruction*> &Insts,
+ 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,
@@ -410,9 +410,6 @@ protected:
return Filters[BestIndex];
}
- // Called from Filter::recurse() when singleton exists. For debug purpose.
- void SingletonExists(unsigned Opc) const;
-
bool PositionFiltered(unsigned i) const {
return ValueSet(FilterBitValues[i]);
}
@@ -559,7 +556,6 @@ void Filter::recurse() {
// No need to recurse for a singleton filtered instruction.
// See also Filter::emit*().
if (getNumFiltered() == 1) {
- //Owner->SingletonExists(LastOpcFiltered);
assert(FilterChooserMap.size() == 1);
return;
}
@@ -732,15 +728,15 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
OS.indent(Indentation) << "MCD::OPC_FilterValue, ";
// The filter value is ULEB128 encoded.
while (*I >= 128)
- OS << utostr(*I++) << ", ";
- OS << utostr(*I++) << ", ";
+ OS << (unsigned)*I++ << ", ";
+ OS << (unsigned)*I++ << ", ";
// 16-bit numtoskip value.
uint8_t Byte = *I++;
uint32_t NumToSkip = Byte;
- OS << utostr(Byte) << ", ";
+ OS << (unsigned)Byte << ", ";
Byte = *I++;
- OS << utostr(Byte) << ", ";
+ OS << (unsigned)Byte << ", ";
NumToSkip |= Byte << 8;
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -753,14 +749,14 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
<< Len << ", ";// << Val << ", " << NumToSkip << ",\n";
// ULEB128 encoded field value.
for (; *I >= 128; ++I)
- OS << utostr(*I) << ", ";
- OS << utostr(*I++) << ", ";
+ OS << (unsigned)*I << ", ";
+ OS << (unsigned)*I++ << ", ";
// 16-bit numtoskip value.
uint8_t Byte = *I++;
uint32_t NumToSkip = Byte;
- OS << utostr(Byte) << ", ";
+ OS << (unsigned)Byte << ", ";
Byte = *I++;
- OS << utostr(Byte) << ", ";
+ OS << (unsigned)Byte << ", ";
NumToSkip |= Byte << 8;
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -769,15 +765,15 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
++I;
OS.indent(Indentation) << "MCD::OPC_CheckPredicate, ";
for (; *I >= 128; ++I)
- OS << utostr(*I) << ", ";
- OS << utostr(*I++) << ", ";
+ OS << (unsigned)*I << ", ";
+ OS << (unsigned)*I++ << ", ";
// 16-bit numtoskip value.
uint8_t Byte = *I++;
uint32_t NumToSkip = Byte;
- OS << utostr(Byte) << ", ";
+ OS << (unsigned)Byte << ", ";
Byte = *I++;
- OS << utostr(Byte) << ", ";
+ OS << (unsigned)Byte << ", ";
NumToSkip |= Byte << 8;
OS << "// Skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
@@ -796,17 +792,17 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
OS.indent(Indentation) << "MCD::OPC_" << (IsTry ? "Try" : "")
<< "Decode, ";
for (p = Buffer; *p >= 128; ++p)
- OS << utostr(*p) << ", ";
- OS << utostr(*p) << ", ";
+ OS << (unsigned)*p << ", ";
+ OS << (unsigned)*p << ", ";
// Decoder index.
for (; *I >= 128; ++I)
- OS << utostr(*I) << ", ";
- OS << utostr(*I++) << ", ";
+ OS << (unsigned)*I << ", ";
+ OS << (unsigned)*I++ << ", ";
if (!IsTry) {
OS << "// Opcode: "
- << NumberedInstructions->at(Opc)->TheDef->getName() << "\n";
+ << NumberedInstructions[Opc]->TheDef->getName() << "\n";
break;
}
@@ -815,13 +811,13 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
// 16-bit numtoskip value.
uint8_t Byte = *I++;
uint32_t NumToSkip = Byte;
- OS << utostr(Byte) << ", ";
+ OS << (unsigned)Byte << ", ";
Byte = *I++;
- OS << utostr(Byte) << ", ";
+ OS << (unsigned)Byte << ", ";
NumToSkip |= Byte << 8;
OS << "// Opcode: "
- << NumberedInstructions->at(Opc)->TheDef->getName()
+ << NumberedInstructions[Opc]->TheDef->getName()
<< ", skip to: " << ((I - Table.begin()) + NumToSkip) << "\n";
break;
}
@@ -832,22 +828,28 @@ void FixedLenDecoderEmitter::emitTable(formatted_raw_ostream &OS,
uint64_t Value = 0;
unsigned Shift = 0;
do {
- OS << ", " << utostr(*I);
+ OS << ", " << (unsigned)*I;
Value += (*I & 0x7f) << Shift;
Shift += 7;
} while (*I++ >= 128);
- if (Value > 127)
- OS << " /* 0x" << utohexstr(Value) << " */";
+ if (Value > 127) {
+ OS << " /* 0x";
+ OS.write_hex(Value);
+ OS << " */";
+ }
// Negative mask
Value = 0;
Shift = 0;
do {
- OS << ", " << utostr(*I);
+ OS << ", " << (unsigned)*I;
Value += (*I & 0x7f) << Shift;
Shift += 7;
} while (*I++ >= 128);
- if (Value > 127)
- OS << " /* 0x" << utohexstr(Value) << " */";
+ if (Value > 127) {
+ OS << " /* 0x";
+ OS.write_hex(Value);
+ OS << " */";
+ }
OS << ",\n";
break;
}
@@ -971,30 +973,6 @@ void FilterChooser::dumpStack(raw_ostream &o, const char *prefix) const {
}
}
-// Called from Filter::recurse() when singleton exists. For debug purpose.
-void FilterChooser::SingletonExists(unsigned Opc) const {
- insn_t Insn0;
- insnWithID(Insn0, Opc);
-
- errs() << "Singleton exists: " << nameWithID(Opc)
- << " with its decoding dominating ";
- for (unsigned i = 0; i < Opcodes.size(); ++i) {
- if (Opcodes[i] == Opc) continue;
- errs() << nameWithID(Opcodes[i]) << ' ';
- }
- errs() << '\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';
- }
-}
-
// 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
@@ -2250,13 +2228,13 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
Target.reverseBitsForLittleEndianEncoding();
// Parameterize the decoders based on namespace and instruction width.
- NumberedInstructions = &Target.getInstructionsByEnumValue();
+ 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->at(i);
+ 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" ||
@@ -2277,7 +2255,7 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
DecoderTableInfo TableInfo;
for (const auto &Opc : OpcMap) {
// Emit the decoder for this namespace+width combination.
- FilterChooser FC(*NumberedInstructions, Opc.second, Operands,
+ FilterChooser FC(NumberedInstructions, Opc.second, Operands,
8*Opc.first.second, this);
// The decode table is cleared for each top level decoder function. The
@@ -2318,12 +2296,10 @@ void FixedLenDecoderEmitter::run(raw_ostream &o) {
namespace llvm {
void EmitFixedLenDecoder(RecordKeeper &RK, raw_ostream &OS,
- std::string PredicateNamespace,
- std::string GPrefix,
- std::string GPostfix,
- std::string ROK,
- std::string RFail,
- std::string L) {
+ 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);
}
diff --git a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
index a658339..02461cc 100644
--- a/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/InstrInfoEmitter.cpp
@@ -59,12 +59,12 @@ private:
raw_ostream &OS);
void emitOperandTypesEnum(raw_ostream &OS, const CodeGenTarget &Target);
void initOperandMapData(
- const std::vector<const CodeGenInstruction *> &NumberedInstructions,
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions,
const std::string &Namespace,
std::map<std::string, unsigned> &Operands,
OpNameMapTy &OperandMap);
void emitOperandNameMappings(raw_ostream &OS, const CodeGenTarget &Target,
- const std::vector<const CodeGenInstruction*> &NumberedInstructions);
+ ArrayRef<const CodeGenInstruction*> NumberedInstructions);
// Operand information.
void EmitOperandInfo(raw_ostream &OS, OperandInfoMapTy &OperandInfoIDs);
@@ -75,8 +75,8 @@ private:
static void PrintDefList(const std::vector<Record*> &Uses,
unsigned Num, raw_ostream &OS) {
OS << "static const MCPhysReg ImplicitList" << Num << "[] = { ";
- for (unsigned i = 0, e = Uses.size(); i != e; ++i)
- OS << getQualifiedName(Uses[i]) << ", ";
+ for (Record *U : Uses)
+ OS << getQualifiedName(U) << ", ";
OS << "0 };\n";
}
@@ -177,7 +177,7 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
OS << "\n";
const CodeGenTarget &Target = CDP.getTargetInfo();
- for (const CodeGenInstruction *Inst : Target.instructions()) {
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue()) {
std::vector<std::string> OperandInfo = GetOperandInfo(*Inst);
unsigned &N = OperandInfoIDs[OperandInfo];
if (N != 0) continue;
@@ -198,7 +198,7 @@ void InstrInfoEmitter::EmitOperandInfo(raw_ostream &OS,
/// each instructions. This is used to generate the OperandMap table as
/// well as the getNamedOperandIdx() function.
void InstrInfoEmitter::initOperandMapData(
- const std::vector<const CodeGenInstruction *> &NumberedInstructions,
+ ArrayRef<const CodeGenInstruction *> NumberedInstructions,
const std::string &Namespace,
std::map<std::string, unsigned> &Operands,
OpNameMapTy &OperandMap) {
@@ -234,7 +234,7 @@ void InstrInfoEmitter::initOperandMapData(
/// OpName enum
void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
const CodeGenTarget &Target,
- const std::vector<const CodeGenInstruction*> &NumberedInstructions) {
+ ArrayRef<const CodeGenInstruction*> NumberedInstructions) {
const std::string &Namespace = Target.getInstNamespace();
std::string OpNameNS = "OpName";
@@ -249,7 +249,7 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
OS << "#undef GET_INSTRINFO_OPERAND_ENUM\n";
OS << "namespace llvm {\n";
OS << "namespace " << Namespace << " {\n";
- OS << "namespace " << OpNameNS << " { \n";
+ OS << "namespace " << OpNameNS << " {\n";
OS << "enum {\n";
for (const auto &Op : Operands)
OS << " " << Op.first << " = " << Op.second << ",\n";
@@ -259,7 +259,7 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
OS << "} // end namespace OpName\n";
OS << "} // end namespace " << Namespace << "\n";
OS << "} // end namespace llvm\n";
- OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n";
+ OS << "#endif //GET_INSTRINFO_OPERAND_ENUM\n\n";
OS << "#ifdef GET_INSTRINFO_NAMED_OPS\n";
OS << "#undef GET_INSTRINFO_NAMED_OPS\n";
@@ -299,7 +299,7 @@ void InstrInfoEmitter::emitOperandNameMappings(raw_ostream &OS,
OS << "}\n";
OS << "} // end namespace " << Namespace << "\n";
OS << "} // end namespace llvm\n";
- OS << "#endif //GET_INSTRINFO_NAMED_OPS\n";
+ OS << "#endif //GET_INSTRINFO_NAMED_OPS\n\n";
}
@@ -312,11 +312,11 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
const std::string &Namespace = Target.getInstNamespace();
std::vector<Record *> Operands = Records.getAllDerivedDefinitions("Operand");
- OS << "\n#ifdef GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
+ 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 << "namespace OpTypes {\n";
OS << "enum OperandType {\n";
unsigned EnumVal = 0;
@@ -330,7 +330,7 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
OS << "} // end namespace OpTypes\n";
OS << "} // end namespace " << Namespace << "\n";
OS << "} // end namespace llvm\n";
- OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n";
+ OS << "#endif // GET_INSTRINFO_OPERAND_TYPES_ENUM\n\n";
}
//===----------------------------------------------------------------------===//
@@ -339,12 +339,10 @@ void InstrInfoEmitter::emitOperandTypesEnum(raw_ostream &OS,
// run - Emit the main instruction description records for the target...
void InstrInfoEmitter::run(raw_ostream &OS) {
- emitSourceFileHeader("Target Instruction Enum Values", OS);
+ emitSourceFileHeader("Target Instruction Enum Values and Descriptors", OS);
emitEnums(OS);
- emitSourceFileHeader("Target Instruction Descriptors", OS);
-
- OS << "\n#ifdef GET_INSTRINFO_MC_DESC\n";
+ OS << "#ifdef GET_INSTRINFO_MC_DESC\n";
OS << "#undef GET_INSTRINFO_MC_DESC\n";
OS << "namespace llvm {\n\n";
@@ -358,7 +356,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
unsigned ListNumber = 0;
// Emit all of the instruction's implicit uses and defs.
- for (const CodeGenInstruction *II : Target.instructions()) {
+ for (const CodeGenInstruction *II : Target.getInstructionsByEnumValue()) {
Record *Inst = II->TheDef;
std::vector<Record*> Uses = Inst->getValueAsListOfDefs("Uses");
if (!Uses.empty()) {
@@ -380,7 +378,7 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
// Emit all of the MCInstrDesc records in their ENUM ordering.
//
OS << "\nextern const MCInstrDesc " << TargetName << "Insts[] = {\n";
- const std::vector<const CodeGenInstruction*> &NumberedInstructions =
+ ArrayRef<const CodeGenInstruction*> NumberedInstructions =
Target.getInstructionsByEnumValue();
SequenceToOffsetTable<std::string> InstrNames;
@@ -418,26 +416,26 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
<< TargetName << "InstrNameIndices, " << TargetName << "InstrNameData, "
<< NumberedInstructions.size() << ");\n}\n\n";
- OS << "} // end llvm namespace \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 << "\n#ifdef GET_INSTRINFO_HEADER\n";
+ 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);\n"
+ << "(int CFSetupOpcode = -1, int CFDestroyOpcode = -1, int CatchRetOpcode = -1, int ReturnOpcode = -1);\n"
<< " ~" << ClassName << "() override {}\n"
<< "};\n";
- OS << "} // end llvm namespace \n";
+ OS << "} // end llvm namespace\n";
OS << "#endif // GET_INSTRINFO_HEADER\n\n";
- OS << "\n#ifdef GET_INSTRINFO_CTOR_DTOR\n";
+ OS << "#ifdef GET_INSTRINFO_CTOR_DTOR\n";
OS << "#undef GET_INSTRINFO_CTOR_DTOR\n";
OS << "namespace llvm {\n";
@@ -445,12 +443,12 @@ void InstrInfoEmitter::run(raw_ostream &OS) {
OS << "extern const unsigned " << TargetName << "InstrNameIndices[];\n";
OS << "extern const char " << TargetName << "InstrNameData[];\n";
OS << ClassName << "::" << ClassName
- << "(int CFSetupOpcode, int CFDestroyOpcode, int CatchRetOpcode)\n"
- << " : TargetInstrInfo(CFSetupOpcode, CFDestroyOpcode, CatchRetOpcode) {\n"
+ << "(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 << "} // end llvm namespace\n";
OS << "#endif // GET_INSTRINFO_CTOR_DTOR\n\n";
@@ -564,7 +562,7 @@ void InstrInfoEmitter::emitRecord(const CodeGenInstruction &Inst, unsigned Num,
// emitEnums - Print out enum values for all of the instructions.
void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
- OS << "\n#ifdef GET_INSTRINFO_ENUM\n";
+ OS << "#ifdef GET_INSTRINFO_ENUM\n";
OS << "#undef GET_INSTRINFO_ENUM\n";
OS << "namespace llvm {\n\n";
@@ -577,26 +575,23 @@ void InstrInfoEmitter::emitEnums(raw_ostream &OS) {
if (Namespace.empty())
PrintFatalError("No instructions defined!");
- const std::vector<const CodeGenInstruction*> &NumberedInstructions =
- Target.getInstructionsByEnumValue();
-
OS << "namespace " << Namespace << " {\n";
OS << " enum {\n";
unsigned Num = 0;
- for (const CodeGenInstruction *Inst : NumberedInstructions)
+ for (const CodeGenInstruction *Inst : Target.getInstructionsByEnumValue())
OS << " " << Inst->TheDef->getName() << "\t= " << Num++ << ",\n";
- OS << " INSTRUCTION_LIST_END = " << NumberedInstructions.size() << "\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 = " << SchedModels.numInstrSchedClasses() << "\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 << "} // end llvm namespace\n";
OS << "#endif // GET_INSTRINFO_ENUM\n\n";
}
diff --git a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
index 42a6a15..a676159 100644
--- a/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/IntrinsicEmitter.cpp
@@ -20,6 +20,7 @@
#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;
@@ -37,23 +38,16 @@ public:
void EmitPrefix(raw_ostream &OS);
- void EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS);
-
- void EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS);
- void EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
+ 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 std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS);
- void EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS);
- void EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS);
- void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
+ void EmitIntrinsicToOverloadTable(const CodeGenIntrinsicTable &Ints,
raw_ostream &OS);
- void EmitIntrinsicToMSBuiltinMap(const std::vector<CodeGenIntrinsic> &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
@@ -65,7 +59,7 @@ public:
void IntrinsicEmitter::run(raw_ostream &OS) {
emitSourceFileHeader("Intrinsic Function Source Fragment", OS);
- std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly);
+ CodeGenIntrinsicTable Ints(Records, TargetOnly);
if (TargetOnly && !Ints.empty())
TargetPrefix = Ints[0].TargetPrefix;
@@ -75,26 +69,29 @@ void IntrinsicEmitter::run(raw_ostream &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 function name recognizer.
- EmitFnNameRecognizer(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.
- EmitIntrinsicToGCCBuiltinMap(Ints, OS);
+ // Individual targets don't need GCC builtin name mappings.
+ if (!TargetOnly) {
+ // Emit code to translate GCC builtins into LLVM intrinsics.
+ EmitIntrinsicToBuiltinMap(Ints, true, OS);
- // Emit code to translate MS builtins into LLVM intrinsics.
- EmitIntrinsicToMSBuiltinMap(Ints, OS);
+ // Emit code to translate MS builtins into LLVM intrinsics.
+ EmitIntrinsicToBuiltinMap(Ints, false, OS);
+ }
EmitSuffix(OS);
}
@@ -117,7 +114,7 @@ void IntrinsicEmitter::EmitSuffix(raw_ostream &OS) {
"#endif\n\n";
}
-void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
+void IntrinsicEmitter::EmitEnumInfo(const CodeGenIntrinsicTable &Ints,
raw_ostream &OS) {
OS << "// Enum values for Intrinsics.h\n";
OS << "#ifdef GET_INTRINSIC_ENUM_VALUES\n";
@@ -131,64 +128,25 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector<CodeGenIntrinsic> &Ints,
OS << "#endif\n\n";
}
-void IntrinsicEmitter::
-EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS) {
- // Build a 'first character of function name' -> intrinsic # mapping.
- std::map<char, std::vector<unsigned> > IntMapping;
- for (unsigned i = 0, e = Ints.size(); i != e; ++i)
- IntMapping[Ints[i].Name[5]].push_back(i);
-
- OS << "// Function name -> enum value recognizer code.\n";
- OS << "#ifdef GET_FUNCTION_RECOGNIZER\n";
- OS << " StringRef NameR(Name+6, Len-6); // Skip over 'llvm.'\n";
- OS << " switch (Name[5]) { // Dispatch on first letter.\n";
- OS << " default: break;\n";
- // Emit the intrinsic matching stuff by first letter.
- for (std::map<char, std::vector<unsigned> >::iterator I = IntMapping.begin(),
- E = IntMapping.end(); I != E; ++I) {
- OS << " case '" << I->first << "':\n";
- std::vector<unsigned> &IntList = I->second;
-
- // Sort in reverse order of intrinsic name so "abc.def" appears after
- // "abd.def.ghi" in the overridden name matcher
- std::sort(IntList.begin(), IntList.end(), [&](unsigned i, unsigned j) {
- return Ints[i].Name > Ints[j].Name;
- });
-
- // Emit all the overloaded intrinsics first, build a table of the
- // non-overloaded ones.
- std::vector<StringMatcher::StringPair> MatchTable;
-
- for (unsigned i = 0, e = IntList.size(); i != e; ++i) {
- unsigned IntNo = IntList[i];
- std::string Result = "return " + TargetPrefix + "Intrinsic::" +
- Ints[IntNo].EnumName + ";";
-
- if (!Ints[IntNo].isOverloaded) {
- MatchTable.push_back(std::make_pair(Ints[IntNo].Name.substr(6),Result));
- continue;
- }
-
- // For overloaded intrinsics, only the prefix needs to match
- std::string TheStr = Ints[IntNo].Name.substr(6);
- TheStr += '.'; // Require "bswap." instead of bswap.
- OS << " if (NameR.startswith(\"" << TheStr << "\")) "
- << Result << '\n';
- }
-
- // Emit the matcher logic for the fixed length strings.
- StringMatcher("NameR", MatchTable, OS).Emit(1);
- OS << " break; // end of '" << I->first << "' case.\n";
- }
-
- OS << " }\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"
+ << " StringRef Name;\n"
+ << " size_t Offset;\n"
+ << " size_t Count;\n"
+ << "};\n";
+ OS << "static const IntrinsicTargetInfo TargetInfos[] = {\n";
+ for (auto Target : Ints.Targets)
+ OS << " {\"" << Target.Name << "\", " << Target.Offset << ", "
+ << Target.Count << "},\n";
+ OS << "};\n";
OS << "#endif\n\n";
}
-void IntrinsicEmitter::
-EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS) {
+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";
@@ -197,9 +155,8 @@ EmitIntrinsicToNameTable(const std::vector<CodeGenIntrinsic> &Ints,
OS << "#endif\n\n";
}
-void IntrinsicEmitter::
-EmitIntrinsicToOverloadTable(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS) {
+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";
@@ -421,7 +378,7 @@ static void printIITEntry(raw_ostream &OS, unsigned char X) {
OS << (unsigned)X;
}
-void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
+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.
@@ -520,8 +477,8 @@ struct AttributeComparator {
return R->isConvergent;
// Try to order by readonly/readnone attribute.
- CodeGenIntrinsic::ModRefKind LK = L->ModRef;
- CodeGenIntrinsic::ModRefKind RK = R->ModRef;
+ CodeGenIntrinsic::ModRefBehavior LK = L->ModRef;
+ CodeGenIntrinsic::ModRefBehavior RK = R->ModRef;
if (LK != RK) return (LK > RK);
// Order by argument attributes.
@@ -532,8 +489,8 @@ struct AttributeComparator {
} // End anonymous namespace
/// EmitAttributes - This emits the Intrinsic::getAttributes method.
-void IntrinsicEmitter::
-EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
+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)
@@ -606,12 +563,24 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &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 << ",";
@@ -674,6 +643,17 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
OS << ",";
OS << "Attribute::ReadOnly";
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::ReadWriteArgMem:
if (addComma)
OS << ",";
@@ -704,56 +684,57 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n";
}
-/// EmitTargetBuiltins - All of the builtins in the specified map are for the
-/// same target, and we already checked it.
-static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
- const std::string &TargetPrefix,
- raw_ostream &OS) {
-
- std::vector<StringMatcher::StringPair> Results;
-
- for (std::map<std::string, std::string>::const_iterator I = BIM.begin(),
- E = BIM.end(); I != E; ++I) {
- std::string ResultCode =
- "return " + TargetPrefix + "Intrinsic::" + I->second + ";";
- Results.emplace_back(I->first, ResultCode);
- }
-
- StringMatcher("BuiltinName", Results, OS).Emit();
-}
-
-
-void IntrinsicEmitter::
-EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS) {
- typedef std::map<std::string, std::map<std::string, std::string> > BIMTy;
+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) {
- if (!Ints[i].GCCBuiltinName.empty()) {
+ 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];
+ std::map<std::string, std::string> &BIM =
+ BuiltinMap[Ints[i].TargetPrefix];
- if (!BIM.insert(std::make_pair(Ints[i].GCCBuiltinName,
- Ints[i].EnumName)).second)
+ if (!BIM.insert(std::make_pair(BuiltinName, Ints[i].EnumName)).second)
PrintFatalError("Intrinsic '" + Ints[i].TheDef->getName() +
- "': duplicate GCC builtin name!");
+ "': duplicate " + CompilerName + " builtin name!");
+ Table.GetOrAddStringOffset(BuiltinName);
}
}
- OS << "// Get the LLVM intrinsic that corresponds to a GCC builtin.\n";
- OS << "// This is used by the C front-end. The GCC builtin name is passed\n";
+ 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_GCC_BUILTIN\n";
+ OS << "#ifdef GET_LLVM_INTRINSIC_FOR_" << CompilerName << "_BUILTIN\n";
if (TargetOnly) {
OS << "static " << TargetPrefix << "Intrinsic::ID "
- << "getIntrinsicForGCCBuiltin(const char "
+ << "getIntrinsicFor" << CompilerName << "Builtin(const char "
<< "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
} else {
- OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
+ OS << "Intrinsic::ID Intrinsic::getIntrinsicFor" << CompilerName
+ << "Builtin(const char "
<< "*TargetPrefixStr, const char *BuiltinNameStr) {\n";
}
+ 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<(const char *RHS) const {\n";
+ OS << " return strcmp(getName(), RHS) < 0;\n";
+ OS << " }\n";
+ OS << " };\n";
+
OS << " StringRef BuiltinName(BuiltinNameStr);\n";
OS << " StringRef TargetPrefix(TargetPrefixStr);\n\n";
@@ -768,7 +749,18 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
OS << "{\n";
// Emit the comparisons for this target prefix.
- EmitTargetBuiltins(I->second, TargetPrefix, OS);
+ 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 << " strcmp(I->getName(), BuiltinNameStr) == 0)\n";
+ OS << " return I->IntrinID;\n";
OS << " }\n";
}
OS << " return ";
@@ -779,55 +771,6 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
OS << "#endif\n\n";
}
-void IntrinsicEmitter::
-EmitIntrinsicToMSBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS) {
- std::map<std::string, std::map<std::string, std::string>> TargetBuiltins;
-
- for (const auto &Intrinsic : Ints) {
- if (Intrinsic.MSBuiltinName.empty())
- continue;
-
- auto &Builtins = TargetBuiltins[Intrinsic.TargetPrefix];
- if (!Builtins.insert(std::make_pair(Intrinsic.MSBuiltinName,
- Intrinsic.EnumName)).second)
- PrintFatalError("Intrinsic '" + Intrinsic.TheDef->getName() + "': "
- "duplicate MS builtin name!");
- }
-
- OS << "// Get the LLVM intrinsic that corresponds to a MS builtin.\n"
- "// This is used by the C front-end. The MS builtin name is passed\n"
- "// in as a BuiltinName, and a target prefix (e.g. 'arm') is passed\n"
- "// in as a TargetPrefix. The result is assigned to 'IntrinsicID'.\n"
- "#ifdef GET_LLVM_INTRINSIC_FOR_MS_BUILTIN\n";
-
- OS << (TargetOnly ? "static " + TargetPrefix : "") << "Intrinsic::ID "
- << (TargetOnly ? "" : "Intrinsic::")
- << "getIntrinsicForMSBuiltin(const char *TP, const char *BN) {\n";
- OS << " StringRef BuiltinName(BN);\n"
- " StringRef TargetPrefix(TP);\n"
- "\n";
-
- for (const auto &Builtins : TargetBuiltins) {
- OS << " ";
- if (Builtins.first.empty())
- OS << "/* Target Independent Builtins */ ";
- else
- OS << "if (TargetPrefix == \"" << Builtins.first << "\") ";
- OS << "{\n";
- EmitTargetBuiltins(Builtins.second, TargetPrefix, OS);
- OS << "}";
- }
-
- 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/RegisterInfoEmitter.cpp b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
index b727df7..9bb988f 100644
--- a/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/RegisterInfoEmitter.cpp
@@ -16,22 +16,38 @@
#include "CodeGenRegisters.h"
#include "CodeGenTarget.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/StringExtras.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) {}
@@ -65,7 +81,8 @@ private:
void emitComposeSubRegIndexLaneMask(raw_ostream &OS, CodeGenRegBank &RegBank,
const std::string &ClassName);
};
-} // End anonymous namespace
+
+} // end anonymous namespace
// runEnums - Print out enum values for all of the registers.
void RegisterInfoEmitter::runEnums(raw_ostream &OS,
@@ -81,7 +98,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
emitSourceFileHeader("Target Register Enum Values", OS);
OS << "\n#ifdef GET_REGINFO_ENUM\n";
- OS << "#undef GET_REGINFO_ENUM\n";
+ OS << "#undef GET_REGINFO_ENUM\n\n";
OS << "namespace llvm {\n\n";
@@ -100,7 +117,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << " NUM_TARGET_REGS \t// " << Registers.size()+1 << "\n";
OS << "};\n";
if (!Namespace.empty())
- OS << "}\n";
+ OS << "} // end namespace " << Namespace << "\n";
const auto &RegisterClasses = Bank.getRegClasses();
if (!RegisterClasses.empty()) {
@@ -109,7 +126,7 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
assert(RegisterClasses.size() <= 0xffff &&
"Too many register classes to fit in tables");
- OS << "\n// Register classes\n";
+ OS << "\n// Register classes\n\n";
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
OS << "enum {\n";
@@ -118,14 +135,14 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
<< " = " << RC.EnumValue << ",\n";
OS << "\n };\n";
if (!Namespace.empty())
- OS << "}\n";
+ 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";
+ OS << "\n// Register alternate name indices\n\n";
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
OS << "enum {\n";
@@ -134,12 +151,12 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << " NUM_TARGET_REG_ALT_NAMES = " << RegAltNameIndices.size() << "\n";
OS << "};\n";
if (!Namespace.empty())
- OS << "}\n";
+ OS << "} // end namespace " << Namespace << "\n\n";
}
auto &SubRegIndices = Bank.getSubRegIndices();
if (!SubRegIndices.empty()) {
- OS << "\n// Subregister indices\n";
+ OS << "\n// Subregister indices\n\n";
std::string Namespace = SubRegIndices.front().getNamespace();
if (!Namespace.empty())
OS << "namespace " << Namespace << " {\n";
@@ -149,10 +166,10 @@ void RegisterInfoEmitter::runEnums(raw_ostream &OS,
OS << " " << Idx.getName() << ",\t// " << ++i << "\n";
OS << " NUM_TARGET_SUBREGS\n};\n";
if (!Namespace.empty())
- OS << "}\n";
+ OS << "} // end namespace " << Namespace << "\n\n";
}
- OS << "} // End llvm namespace\n";
+ OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_REGINFO_ENUM\n\n";
}
@@ -728,15 +745,11 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
SubReg2SequenceIndexMap.push_back(Found);
}
- OS << "unsigned " << ClName
- << "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, unsigned LaneMask)"
- " const {\n";
-
OS << " struct MaskRolOp {\n"
" unsigned Mask;\n"
" uint8_t RotateLeft;\n"
" };\n"
- " static const MaskRolOp Seqs[] = {\n";
+ " static const MaskRolOp LaneMaskComposeSequences[] = {\n";
unsigned Idx = 0;
for (size_t s = 0, se = Sequences.size(); s != se; ++s) {
OS << " ";
@@ -756,24 +769,43 @@ RegisterInfoEmitter::emitComposeSubRegIndexLaneMask(raw_ostream &OS,
for (size_t i = 0, e = SubRegIndices.size(); i != e; ++i) {
OS << " ";
unsigned Idx = SubReg2SequenceIndexMap[i];
- OS << format("&Seqs[%u]", Idx);
+ OS << format("&LaneMaskComposeSequences[%u]", Idx);
if (i+1 != e)
OS << ",";
OS << " // to " << SubRegIndices[i].getName() << "\n";
}
OS << " };\n\n";
- OS << " --IdxA; assert(IdxA < " << SubRegIndices.size()
+ OS << "LaneBitmask " << ClName
+ << "::composeSubRegIndexLaneMaskImpl(unsigned IdxA, LaneBitmask LaneMask)"
+ " const {\n"
+ " --IdxA; assert(IdxA < " << SubRegIndices.size()
<< " && \"Subregister index out of bounds\");\n"
- " unsigned Result = 0;\n"
+ " LaneBitmask Result = 0;\n"
" for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask != 0; ++Ops)"
" {\n"
- " unsigned Masked = LaneMask & Ops->Mask;\n"
+ " LaneBitmask Masked = LaneMask & Ops->Mask;\n"
" Result |= (Masked << Ops->RotateLeft) & 0xFFFFFFFF;\n"
" Result |= (Masked >> ((32 - Ops->RotateLeft) & 0x1F));\n"
" }\n"
" return Result;\n"
- "}\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 = 0;\n"
+ " for (const MaskRolOp *Ops = CompositeSequences[IdxA]; Ops->Mask != 0; ++Ops)"
+ " {\n"
+ " LaneBitmask Rotated = (LaneMask >> Ops->RotateLeft) |\n"
+ " ((LaneMask << ((32 - Ops->RotateLeft) & 0x1F)) & 0xFFFFFFFF);\n"
+ " Result |= Rotated & Ops->Mask;\n"
+ " }\n"
+ " return Result;\n"
+ "}\n\n";
}
//
@@ -785,7 +817,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
emitSourceFileHeader("MC Register Information", OS);
OS << "\n#ifdef GET_REGINFO_MC_DESC\n";
- OS << "#undef GET_REGINFO_MC_DESC\n";
+ OS << "#undef GET_REGINFO_MC_DESC\n\n";
const auto &Regs = RegBank.getRegisters();
@@ -958,7 +990,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
ArrayRef<Record*> Order = RC.getOrder();
// Give the register class a legal C name if it's anonymous.
- std::string Name = RC.getName();
+ const std::string &Name = RC.getName();
RegClassStrings.add(Name);
@@ -984,7 +1016,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "\n };\n\n";
}
- OS << "}\n\n";
+ OS << "} // end anonymous namespace\n\n";
RegClassStrings.layout();
OS << "extern const char " << TargetName << "RegClassStrings[] = {\n";
@@ -1008,7 +1040,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
<< RC.SpillSize/8 << ", "
<< RC.SpillAlignment/8 << ", "
<< RC.CopyCost << ", "
- << RC.Allocatable << " },\n";
+ << ( RC.Allocatable ? "true" : "false" ) << " },\n";
}
OS << "};\n\n";
@@ -1051,7 +1083,7 @@ RegisterInfoEmitter::runMCDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "}\n\n";
- OS << "} // End llvm namespace\n";
+ OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_REGINFO_MC_DESC\n\n";
}
@@ -1061,7 +1093,7 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
emitSourceFileHeader("Register Information Header Fragment", OS);
OS << "\n#ifdef GET_REGINFO_HEADER\n";
- OS << "#undef GET_REGINFO_HEADER\n";
+ OS << "#undef GET_REGINFO_HEADER\n\n";
const std::string &TargetName = Target.getName();
std::string ClassName = TargetName + "GenRegisterInfo";
@@ -1078,8 +1110,10 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
if (!RegBank.getSubRegIndices().empty()) {
OS << " unsigned composeSubRegIndicesImpl"
<< "(unsigned, unsigned) const override;\n"
- << " unsigned composeSubRegIndexLaneMaskImpl"
- << "(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";
}
@@ -1113,9 +1147,9 @@ RegisterInfoEmitter::runTargetHeader(raw_ostream &OS, CodeGenTarget &Target,
// Output the extern for the instance.
OS << " extern const TargetRegisterClass " << Name << "RegClass;\n";
}
- OS << "} // end of namespace " << TargetName << "\n\n";
+ OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n\n";
}
- OS << "} // End llvm namespace\n";
+ OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_REGINFO_HEADER\n\n";
}
@@ -1128,7 +1162,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
emitSourceFileHeader("Target Register and Register Classes Information", OS);
OS << "\n#ifdef GET_REGINFO_TARGET_DESC\n";
- OS << "#undef GET_REGINFO_TARGET_DESC\n";
+ OS << "#undef GET_REGINFO_TARGET_DESC\n\n";
OS << "namespace llvm {\n\n";
@@ -1294,7 +1328,9 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< format("0x%08x,\n ", RC.LaneMask)
<< (unsigned)RC.AllocationPriority << ",\n "
<< (RC.HasDisjunctSubRegs?"true":"false")
- << ", /* HasDisjunctSubRegs */\n ";
+ << ", /* HasDisjunctSubRegs */\n "
+ << (RC.CoveredBySubRegs?"true":"false")
+ << ", /* CoveredBySubRegs */\n ";
if (RC.getSuperClasses().empty())
OS << "NullRegClasses,\n ";
else
@@ -1306,7 +1342,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << " };\n\n";
}
- OS << "}\n";
+ OS << "} // end namespace " << RegisterClasses.front().Namespace << "\n";
}
OS << "\nnamespace {\n";
@@ -1314,19 +1350,20 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
for (const auto &RC : RegisterClasses)
OS << " &" << RC.getQualifiedName() << "RegClass,\n";
OS << " };\n";
- OS << "}\n"; // End of anonymous namespace...
+ 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, 0 },\n";
+ OS << " { 0, false },\n";
const auto &Regs = RegBank.getRegisters();
for (const auto &Reg : Regs) {
OS << " { ";
OS << Reg.CostPerUse << ", "
- << int(AllocatableRegs.count(Reg.TheDef)) << " },\n";
+ << ( AllocatableRegs.count(Reg.TheDef) != 0 ? "true" : "false" )
+ << " },\n";
}
OS << "};\n"; // End of register descriptors...
@@ -1414,7 +1451,6 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
OS << "}\n\n";
-
// Emit CalleeSavedRegs information.
std::vector<Record*> CSRSets =
Records.getAllDerivedDefinitions("CalleeSavedRegs");
@@ -1482,7 +1518,7 @@ RegisterInfoEmitter::runTargetDesc(raw_ostream &OS, CodeGenTarget &Target,
<< " MF.getSubtarget().getFrameLowering());\n"
<< "}\n\n";
- OS << "} // End llvm namespace\n";
+ OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_REGINFO_TARGET_DESC\n\n";
}
@@ -1503,4 +1539,4 @@ void EmitRegisterInfo(RecordKeeper &RK, raw_ostream &OS) {
RegisterInfoEmitter(RK).run(OS);
}
-} // End llvm namespace
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp b/contrib/llvm/utils/TableGen/SearchableTableEmitter.cpp
new file mode 100644
index 0000000..8c1b880
--- /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.data(), 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 StringRef(LHS.first) < StringRef(RHS.first);\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
index 66506ea..e026b1c 100644
--- a/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h
+++ b/contrib/llvm/utils/TableGen/SequenceToOffsetTable.h
@@ -22,7 +22,6 @@
#include <cctype>
#include <functional>
#include <map>
-#include <vector>
namespace llvm {
diff --git a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
index d056de0..2288821 100644
--- a/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
+++ b/contrib/llvm/utils/TableGen/SubtargetEmitter.cpp
@@ -13,16 +13,20 @@
#include "CodeGenTarget.h"
#include "CodeGenSchedule.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/StringExtras.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 <map>
#include <string>
#include <vector>
@@ -32,6 +36,7 @@ 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
@@ -64,7 +69,7 @@ class SubtargetEmitter {
CodeGenSchedModels &SchedModels;
std::string Target;
- void Enumeration(raw_ostream &OS, const char *ClassName);
+ void Enumeration(raw_ostream &OS);
unsigned FeatureKeyValues(raw_ostream &OS);
unsigned CPUKeyValues(raw_ostream &OS);
void FormItineraryStageString(const std::string &Names,
@@ -96,7 +101,7 @@ class SubtargetEmitter {
void EmitSchedClassTables(SchedClassTables &SchedTables, raw_ostream &OS);
void EmitProcessorModels(raw_ostream &OS);
void EmitProcessorLookup(raw_ostream &OS);
- void EmitSchedModelHelpers(std::string ClassName, 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);
@@ -107,15 +112,16 @@ public:
void run(raw_ostream &o);
};
+
} // end anonymous namespace
//
// Enumeration - Emit the specified class as an enumeration.
//
-void SubtargetEmitter::Enumeration(raw_ostream &OS,
- const char *ClassName) {
+void SubtargetEmitter::Enumeration(raw_ostream &OS) {
// Get all records of class and sort
- std::vector<Record*> DefList = Records.getAllDerivedDefinitions(ClassName);
+ std::vector<Record*> DefList =
+ Records.getAllDerivedDefinitions("SubtargetFeature");
std::sort(DefList.begin(), DefList.end(), LessRecord());
unsigned N = DefList.size();
@@ -126,8 +132,8 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS,
OS << "namespace " << Target << " {\n";
- // Open enumeration. Use a 64-bit underlying type.
- OS << "enum : uint64_t {\n";
+ // Open enumeration.
+ OS << "enum {\n";
// For each record
for (unsigned i = 0; i < N;) {
@@ -142,7 +148,8 @@ void SubtargetEmitter::Enumeration(raw_ostream &OS,
}
// Close enumeration and namespace
- OS << "};\n}\n";
+ OS << "};\n";
+ OS << "} // end namespace " << Target << "\n";
}
//
@@ -357,17 +364,16 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
SmallPtrSet<Record*, 8> ItinsDefSet;
// Emit functional units for all the itineraries.
- for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
- PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
+ for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
- if (!ItinsDefSet.insert(PI->ItinsDef).second)
+ if (!ItinsDefSet.insert(ProcModel.ItinsDef).second)
continue;
- std::vector<Record*> FUs = PI->ItinsDef->getValueAsListOfDefs("FU");
+ std::vector<Record*> FUs = ProcModel.ItinsDef->getValueAsListOfDefs("FU");
if (FUs.empty())
continue;
- const std::string &Name = PI->ItinsDef->getName();
+ const std::string &Name = ProcModel.ItinsDef->getName();
OS << "\n// Functional units for \"" << Name << "\"\n"
<< "namespace " << Name << "FU {\n";
@@ -375,9 +381,9 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
OS << " const unsigned " << FUs[j]->getName()
<< " = 1 << " << j << ";\n";
- OS << "}\n";
+ OS << "} // end namespace " << Name << "FU\n";
- std::vector<Record*> BPs = PI->ItinsDef->getValueAsListOfDefs("BP");
+ std::vector<Record*> BPs = ProcModel.ItinsDef->getValueAsListOfDefs("BP");
if (!BPs.empty()) {
OS << "\n// Pipeline forwarding pathes for itineraries \"" << Name
<< "\"\n" << "namespace " << Name << "Bypass {\n";
@@ -387,7 +393,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
OS << " const unsigned " << BPs[j]->getName()
<< " = 1 << " << j << ";\n";
- OS << "}\n";
+ OS << "} // end namespace " << Name << "Bypass\n";
}
}
@@ -411,10 +417,7 @@ EmitStageAndOperandCycleData(raw_ostream &OS,
// object with computed offsets to the ProcItinLists result.
unsigned StageCount = 1, OperandCycleCount = 1;
std::map<std::string, unsigned> ItinStageMap, ItinOperandMap;
- for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
- PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
- const CodeGenProcModel &ProcModel = *PI;
-
+ for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
// Add process itinerary to the list.
ProcItinLists.resize(ProcItinLists.size()+1);
@@ -612,9 +615,8 @@ void SubtargetEmitter::EmitProcessorResources(const CodeGenProcModel &ProcModel,
int BufferSize = PRDef->getValueAsInt("BufferSize");
if (PRDef->isSubClassOf("ProcResGroup")) {
RecVec ResUnits = PRDef->getValueAsListOfDefs("Resources");
- for (RecIter RUI = ResUnits.begin(), RUE = ResUnits.end();
- RUI != RUE; ++RUI) {
- NumUnits += (*RUI)->getValueAsInt("NumUnits");
+ for (Record *RU : ResUnits) {
+ NumUnits += RU->getValueAsInt("NumUnits");
}
}
else {
@@ -652,10 +654,9 @@ Record *SubtargetEmitter::FindWriteResources(
return SchedWrite.TheDef;
Record *AliasDef = nullptr;
- for (RecIter AI = SchedWrite.Aliases.begin(), AE = SchedWrite.Aliases.end();
- AI != AE; ++AI) {
+ for (Record *A : SchedWrite.Aliases) {
const CodeGenSchedRW &AliasRW =
- SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
+ SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
@@ -672,18 +673,17 @@ Record *SubtargetEmitter::FindWriteResources(
// Check this processor's list of write resources.
Record *ResDef = nullptr;
- for (RecIter WRI = ProcModel.WriteResDefs.begin(),
- WRE = ProcModel.WriteResDefs.end(); WRI != WRE; ++WRI) {
- if (!(*WRI)->isSubClassOf("WriteRes"))
+ for (Record *WR : ProcModel.WriteResDefs) {
+ if (!WR->isSubClassOf("WriteRes"))
continue;
- if (AliasDef == (*WRI)->getValueAsDef("WriteType")
- || SchedWrite.TheDef == (*WRI)->getValueAsDef("WriteType")) {
+ if (AliasDef == WR->getValueAsDef("WriteType")
+ || SchedWrite.TheDef == WR->getValueAsDef("WriteType")) {
if (ResDef) {
- PrintFatalError((*WRI)->getLoc(), "Resources are defined for both "
+ PrintFatalError(WR->getLoc(), "Resources are defined for both "
"SchedWrite and its alias on processor " +
ProcModel.ModelName);
}
- ResDef = *WRI;
+ ResDef = WR;
}
}
// TODO: If ProcModel has a base model (previous generation processor),
@@ -706,10 +706,9 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
// Check this processor's list of aliases for SchedRead.
Record *AliasDef = nullptr;
- for (RecIter AI = SchedRead.Aliases.begin(), AE = SchedRead.Aliases.end();
- AI != AE; ++AI) {
+ for (Record *A : SchedRead.Aliases) {
const CodeGenSchedRW &AliasRW =
- SchedModels.getSchedRW((*AI)->getValueAsDef("AliasRW"));
+ SchedModels.getSchedRW(A->getValueAsDef("AliasRW"));
if (AliasRW.TheDef->getValueInit("SchedModel")->isComplete()) {
Record *ModelDef = AliasRW.TheDef->getValueAsDef("SchedModel");
if (&SchedModels.getProcModel(ModelDef) != &ProcModel)
@@ -726,18 +725,17 @@ Record *SubtargetEmitter::FindReadAdvance(const CodeGenSchedRW &SchedRead,
// Check this processor's ReadAdvanceList.
Record *ResDef = nullptr;
- for (RecIter RAI = ProcModel.ReadAdvanceDefs.begin(),
- RAE = ProcModel.ReadAdvanceDefs.end(); RAI != RAE; ++RAI) {
- if (!(*RAI)->isSubClassOf("ReadAdvance"))
+ for (Record *RA : ProcModel.ReadAdvanceDefs) {
+ if (!RA->isSubClassOf("ReadAdvance"))
continue;
- if (AliasDef == (*RAI)->getValueAsDef("ReadType")
- || SchedRead.TheDef == (*RAI)->getValueAsDef("ReadType")) {
+ if (AliasDef == RA->getValueAsDef("ReadType")
+ || SchedRead.TheDef == RA->getValueAsDef("ReadType")) {
if (ResDef) {
- PrintFatalError((*RAI)->getLoc(), "Resources are defined for both "
+ PrintFatalError(RA->getLoc(), "Resources are defined for both "
"SchedRead and its alias on processor " +
ProcModel.ModelName);
}
- ResDef = *RAI;
+ ResDef = RA;
}
}
// TODO: If ProcModel has a base model (previous generation processor),
@@ -779,12 +777,10 @@ void SubtargetEmitter::ExpandProcResources(RecVec &PRVec,
SubDef = SuperDef;
}
}
- for (RecIter PRI = PM.ProcResourceDefs.begin(),
- PRE = PM.ProcResourceDefs.end();
- PRI != PRE; ++PRI) {
- if (*PRI == PRDef || !(*PRI)->isSubClassOf("ProcResGroup"))
+ for (Record *PR : PM.ProcResourceDefs) {
+ if (PR == PRDef || !PR->isSubClassOf("ProcResGroup"))
continue;
- RecVec SuperResources = (*PRI)->getValueAsListOfDefs("Resources");
+ RecVec SuperResources = PR->getValueAsListOfDefs("Resources");
RecIter SubI = SubResources.begin(), SubE = SubResources.end();
for( ; SubI != SubE; ++SubI) {
if (std::find(SuperResources.begin(), SuperResources.end(), *SubI)
@@ -793,7 +789,7 @@ void SubtargetEmitter::ExpandProcResources(RecVec &PRVec,
}
}
if (SubI == SubE) {
- PRVec.push_back(*PRI);
+ PRVec.push_back(PR);
Cycles.push_back(Cycles[i]);
}
}
@@ -809,9 +805,8 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
return;
std::vector<MCSchedClassDesc> &SCTab = SchedTables.ProcSchedClasses.back();
- for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
- SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
- DEBUG(SCI->dump(&SchedModels));
+ for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) {
+ DEBUG(SC.dump(&SchedModels));
SCTab.resize(SCTab.size() + 1);
MCSchedClassDesc &SCDesc = SCTab.back();
@@ -826,7 +821,7 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
// A Variant SchedClass has no resources of its own.
bool HasVariants = false;
for (std::vector<CodeGenSchedTransition>::const_iterator
- TI = SCI->Transitions.begin(), TE = SCI->Transitions.end();
+ TI = SC.Transitions.begin(), TE = SC.Transitions.end();
TI != TE; ++TI) {
if (TI->ProcIndices[0] == 0) {
HasVariants = true;
@@ -847,24 +842,23 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
// 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(!SCI->ProcIndices.empty() && "expect at least one procidx");
- if (SCI->ProcIndices[0] != 0) {
- IdxIter PIPos = std::find(SCI->ProcIndices.begin(),
- SCI->ProcIndices.end(), ProcModel.Index);
- if (PIPos == SCI->ProcIndices.end())
+ assert(!SC.ProcIndices.empty() && "expect at least one procidx");
+ if (SC.ProcIndices[0] != 0) {
+ IdxIter PIPos = std::find(SC.ProcIndices.begin(),
+ SC.ProcIndices.end(), ProcModel.Index);
+ if (PIPos == SC.ProcIndices.end())
continue;
}
- IdxVec Writes = SCI->Writes;
- IdxVec Reads = SCI->Reads;
- if (!SCI->InstRWs.empty()) {
+ 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 (RecIter RWI = SCI->InstRWs.begin(), RWE = SCI->InstRWs.end();
- RWI != RWE; ++RWI) {
- Record *RWModelDef = (*RWI)->getValueAsDef("SchedModel");
+ for (Record *RW : SC.InstRWs) {
+ Record *RWModelDef = RW->getValueAsDef("SchedModel");
if (&ProcModel == &SchedModels.getProcModel(RWModelDef)) {
- RWDef = *RWI;
+ RWDef = RW;
break;
}
}
@@ -877,19 +871,18 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
}
if (Writes.empty()) {
// Check this processor's itinerary class resources.
- for (RecIter II = ProcModel.ItinRWDefs.begin(),
- IE = ProcModel.ItinRWDefs.end(); II != IE; ++II) {
- RecVec Matched = (*II)->getValueAsListOfDefs("MatchedItinClasses");
- if (std::find(Matched.begin(), Matched.end(), SCI->ItinClassDef)
+ for (Record *I : ProcModel.ItinRWDefs) {
+ RecVec Matched = I->getValueAsListOfDefs("MatchedItinClasses");
+ if (std::find(Matched.begin(), Matched.end(), SC.ItinClassDef)
!= Matched.end()) {
- SchedModels.findRWs((*II)->getValueAsListOfDefs("OperandReadWrites"),
+ SchedModels.findRWs(I->getValueAsListOfDefs("OperandReadWrites"),
Writes, Reads);
break;
}
}
if (Writes.empty()) {
DEBUG(dbgs() << ProcModel.ModelName
- << " does not have resources for class " << SCI->Name << '\n');
+ << " does not have resources for class " << SC.Name << '\n');
}
}
// Sum resources across all operand writes.
@@ -897,9 +890,9 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
std::vector<MCWriteLatencyEntry> WriteLatencies;
std::vector<std::string> WriterNames;
std::vector<MCReadAdvanceEntry> ReadAdvanceEntries;
- for (IdxIter WI = Writes.begin(), WE = Writes.end(); WI != WE; ++WI) {
+ for (unsigned W : Writes) {
IdxVec WriteSeq;
- SchedModels.expandRWSeqForProc(*WI, WriteSeq, /*IsRead=*/false,
+ SchedModels.expandRWSeqForProc(W, WriteSeq, /*IsRead=*/false,
ProcModel);
// For each operand, create a latency entry.
@@ -915,11 +908,10 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
}
WLEntry.WriteResourceID = WriteID;
- for (IdxIter WSI = WriteSeq.begin(), WSE = WriteSeq.end();
- WSI != WSE; ++WSI) {
+ for (unsigned WS : WriteSeq) {
Record *WriteRes =
- FindWriteResources(SchedModels.getSchedWrite(*WSI), ProcModel);
+ FindWriteResources(SchedModels.getSchedWrite(WS), ProcModel);
// Mark the parent class as invalid for unsupported write types.
if (WriteRes->getValueAsBit("Unsupported")) {
@@ -981,16 +973,15 @@ void SubtargetEmitter::GenSchedClassTables(const CodeGenProcModel &ProcModel,
if (ValidWrites.empty())
WriteIDs.push_back(0);
else {
- for (RecIter VWI = ValidWrites.begin(), VWE = ValidWrites.end();
- VWI != VWE; ++VWI) {
- WriteIDs.push_back(SchedModels.getSchedRWIdx(*VWI, /*IsRead=*/false));
+ for (Record *VW : ValidWrites) {
+ WriteIDs.push_back(SchedModels.getSchedRWIdx(VW, /*IsRead=*/false));
}
}
std::sort(WriteIDs.begin(), WriteIDs.end());
- for(IdxIter WI = WriteIDs.begin(), WE = WriteIDs.end(); WI != WE; ++WI) {
+ for(unsigned W : WriteIDs) {
MCReadAdvanceEntry RAEntry;
RAEntry.UseIdx = UseIdx;
- RAEntry.WriteResourceID = *WI;
+ RAEntry.WriteResourceID = W;
RAEntry.Cycles = ReadAdvance->getValueAsInt("Cycles");
ReadAdvanceEntries.push_back(RAEntry);
}
@@ -1130,7 +1121,7 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
&& "invalid class not first");
OS << " {DBGFIELD(\"InvalidSchedClass\") "
<< MCSchedClassDesc::InvalidNumMicroOps
- << ", 0, 0, 0, 0, 0, 0, 0, 0},\n";
+ << ", false, false, 0, 0, 0, 0, 0, 0},\n";
for (unsigned SCIdx = 1, SCEnd = SCTab.size(); SCIdx != SCEnd; ++SCIdx) {
MCSchedClassDesc &MCDesc = SCTab[SCIdx];
@@ -1139,7 +1130,8 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
if (SchedClass.Name.size() < 18)
OS.indent(18 - SchedClass.Name.size());
OS << MCDesc.NumMicroOps
- << ", " << MCDesc.BeginGroup << ", " << MCDesc.EndGroup
+ << ", " << ( MCDesc.BeginGroup ? "true" : "false" )
+ << ", " << ( MCDesc.EndGroup ? "true" : "false" )
<< ", " << format("%2d", MCDesc.WriteProcResIdx)
<< ", " << MCDesc.NumWriteProcResEntries
<< ", " << format("%2d", MCDesc.WriteLatencyIdx)
@@ -1156,45 +1148,48 @@ void SubtargetEmitter::EmitSchedClassTables(SchedClassTables &SchedTables,
void SubtargetEmitter::EmitProcessorModels(raw_ostream &OS) {
// For each processor model.
- for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
- PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
+ for (const CodeGenProcModel &PM : SchedModels.procModels()) {
// Emit processor resource table.
- if (PI->hasInstrSchedModel())
- EmitProcessorResources(*PI, OS);
- else if(!PI->ProcResourceDefs.empty())
- PrintFatalError(PI->ModelDef->getLoc(), "SchedMachineModel defines "
+ 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 " << PI->ModelName << " = {\n";
- EmitProcessorProp(OS, PI->ModelDef, "IssueWidth", ',');
- EmitProcessorProp(OS, PI->ModelDef, "MicroOpBufferSize", ',');
- EmitProcessorProp(OS, PI->ModelDef, "LoopMicroOpBufferSize", ',');
- EmitProcessorProp(OS, PI->ModelDef, "LoadLatency", ',');
- EmitProcessorProp(OS, PI->ModelDef, "HighLatency", ',');
- EmitProcessorProp(OS, PI->ModelDef, "MispredictPenalty", ',');
-
- OS << " " << (bool)(PI->ModelDef ?
- PI->ModelDef->getValueAsBit("PostRAScheduler") : 0)
- << ", // " << "PostRAScheduler\n";
-
- OS << " " << (bool)(PI->ModelDef ?
- PI->ModelDef->getValueAsBit("CompleteModel") : 0)
- << ", // " << "CompleteModel\n";
-
- OS << " " << PI->Index << ", // Processor ID\n";
- if (PI->hasInstrSchedModel())
- OS << " " << PI->ModelName << "ProcResources" << ",\n"
- << " " << PI->ModelName << "SchedClasses" << ",\n"
- << " " << PI->ProcResourceDefs.size()+1 << ",\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 (PI->hasItineraries())
- OS << " " << PI->ItinsDef->getName() << "};\n";
+ if (PM.hasItineraries())
+ OS << " " << PM.ItinsDef->getName() << "};\n";
else
OS << " nullptr}; // No Itinerary\n";
}
@@ -1260,9 +1255,8 @@ void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
<< "// Data tables for the new per-operand machine model.\n";
SchedClassTables SchedTables;
- for (CodeGenSchedModels::ProcIter PI = SchedModels.procModelBegin(),
- PE = SchedModels.procModelEnd(); PI != PE; ++PI) {
- GenSchedClassTables(*PI, SchedTables);
+ for (const CodeGenProcModel &ProcModel : SchedModels.procModels()) {
+ GenSchedClassTables(ProcModel, SchedTables);
}
EmitSchedClassTables(SchedTables, OS);
@@ -1274,7 +1268,7 @@ void SubtargetEmitter::EmitSchedModel(raw_ostream &OS) {
OS << "#undef DBGFIELD";
}
-void SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName,
+void SubtargetEmitter::EmitSchedModelHelpers(const std::string &ClassName,
raw_ostream &OS) {
OS << "unsigned " << ClassName
<< "\n::resolveSchedClass(unsigned SchedClass, const MachineInstr *MI,"
@@ -1282,60 +1276,52 @@ void SubtargetEmitter::EmitSchedModelHelpers(std::string ClassName,
std::vector<Record*> Prologs = Records.getAllDerivedDefinitions("PredicateProlog");
std::sort(Prologs.begin(), Prologs.end(), LessRecord());
- for (std::vector<Record*>::const_iterator
- PI = Prologs.begin(), PE = Prologs.end(); PI != PE; ++PI) {
- OS << (*PI)->getValueAsString("Code") << '\n';
+ for (Record *P : Prologs) {
+ OS << P->getValueAsString("Code") << '\n';
}
IdxVec VariantClasses;
- for (CodeGenSchedModels::SchedClassIter SCI = SchedModels.schedClassBegin(),
- SCE = SchedModels.schedClassEnd(); SCI != SCE; ++SCI) {
- if (SCI->Transitions.empty())
+ for (const CodeGenSchedClass &SC : SchedModels.schedClasses()) {
+ if (SC.Transitions.empty())
continue;
- VariantClasses.push_back(SCI->Index);
+ VariantClasses.push_back(SC.Index);
}
if (!VariantClasses.empty()) {
OS << " switch (SchedClass) {\n";
- for (IdxIter VCI = VariantClasses.begin(), VCE = VariantClasses.end();
- VCI != VCE; ++VCI) {
- const CodeGenSchedClass &SC = SchedModels.getSchedClass(*VCI);
- OS << " case " << *VCI << ": // " << SC.Name << '\n';
+ for (unsigned VC : VariantClasses) {
+ const CodeGenSchedClass &SC = SchedModels.getSchedClass(VC);
+ OS << " case " << VC << ": // " << SC.Name << '\n';
IdxVec ProcIndices;
- for (std::vector<CodeGenSchedTransition>::const_iterator
- TI = SC.Transitions.begin(), TE = SC.Transitions.end();
- TI != TE; ++TI) {
+ for (const CodeGenSchedTransition &T : SC.Transitions) {
IdxVec PI;
- std::set_union(TI->ProcIndices.begin(), TI->ProcIndices.end(),
+ std::set_union(T.ProcIndices.begin(), T.ProcIndices.end(),
ProcIndices.begin(), ProcIndices.end(),
std::back_inserter(PI));
ProcIndices.swap(PI);
}
- for (IdxIter PI = ProcIndices.begin(), PE = ProcIndices.end();
- PI != PE; ++PI) {
+ for (unsigned PI : ProcIndices) {
OS << " ";
- if (*PI != 0)
- OS << "if (SchedModel->getProcessorID() == " << *PI << ") ";
- OS << "{ // " << (SchedModels.procModelBegin() + *PI)->ModelName
+ if (PI != 0)
+ OS << "if (SchedModel->getProcessorID() == " << PI << ") ";
+ OS << "{ // " << (SchedModels.procModelBegin() + PI)->ModelName
<< '\n';
- for (std::vector<CodeGenSchedTransition>::const_iterator
- TI = SC.Transitions.begin(), TE = SC.Transitions.end();
- TI != TE; ++TI) {
- if (*PI != 0 && !std::count(TI->ProcIndices.begin(),
- TI->ProcIndices.end(), *PI)) {
+ for (const CodeGenSchedTransition &T : SC.Transitions) {
+ if (PI != 0 && !std::count(T.ProcIndices.begin(),
+ T.ProcIndices.end(), PI)) {
continue;
}
OS << " if (";
- for (RecIter RI = TI->PredTerm.begin(), RE = TI->PredTerm.end();
+ for (RecIter RI = T.PredTerm.begin(), RE = T.PredTerm.end();
RI != RE; ++RI) {
- if (RI != TI->PredTerm.begin())
+ if (RI != T.PredTerm.begin())
OS << "\n && ";
OS << "(" << (*RI)->getValueAsString("Predicate") << ")";
}
OS << ")\n"
- << " return " << TI->ToClassIdx << "; // "
- << SchedModels.getSchedClass(TI->ToClassIdx).Name << '\n';
+ << " return " << T.ToClassIdx << "; // "
+ << SchedModels.getSchedClass(T.ToClassIdx).Name << '\n';
}
OS << " }\n";
- if (*PI == 0)
+ if (PI == 0)
break;
}
if (SC.isInferred())
@@ -1375,9 +1361,8 @@ void SubtargetEmitter::ParseFeaturesFunction(raw_ostream &OS,
OS << " InitMCProcessorInfo(CPU, FS);\n"
<< " const FeatureBitset& Bits = getFeatureBits();\n";
- for (unsigned i = 0; i < Features.size(); i++) {
+ for (Record *R : Features) {
// Next record
- Record *R = Features[i];
const std::string &Instance = R->getName();
const std::string &Value = R->getValueAsString("Value");
const std::string &Attribute = R->getValueAsString("Attribute");
@@ -1403,15 +1388,15 @@ 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";
+ OS << "#undef GET_SUBTARGETINFO_ENUM\n\n";
OS << "namespace llvm {\n";
- Enumeration(OS, "SubtargetFeature");
- OS << "} // end llvm namespace\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";
+ OS << "#undef GET_SUBTARGETINFO_MC_DESC\n\n";
OS << "namespace llvm {\n";
#if 0
@@ -1424,7 +1409,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
EmitSchedModel(OS);
OS << "\n";
#if 0
- OS << "}\n";
+ OS << "} // end anonymous namespace\n\n";
#endif
// MCInstrInfo initialization routine.
@@ -1454,22 +1439,22 @@ void SubtargetEmitter::run(raw_ostream &OS) {
OS << "0, 0, 0";
OS << ");\n}\n\n";
- OS << "} // end llvm namespace\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";
+ OS << "#undef GET_SUBTARGETINFO_TARGET_DESC\n\n";
OS << "#include \"llvm/Support/Debug.h\"\n";
- OS << "#include \"llvm/Support/raw_ostream.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";
+ OS << "#undef GET_SUBTARGETINFO_HEADER\n\n";
std::string ClassName = Target + "GenSubtargetInfo";
OS << "namespace llvm {\n";
@@ -1484,14 +1469,14 @@ void SubtargetEmitter::run(raw_ostream &OS) {
<< " DFAPacketizer *createDFAPacketizer(const InstrItineraryData *IID)"
<< " const;\n"
<< "};\n";
- OS << "} // end llvm namespace\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";
+ OS << "#undef GET_SUBTARGETINFO_CTOR\n\n";
- OS << "#include \"llvm/CodeGen/TargetSchedule.h\"\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";
@@ -1536,7 +1521,7 @@ void SubtargetEmitter::run(raw_ostream &OS) {
EmitSchedModelHelpers(ClassName, OS);
- OS << "} // end llvm namespace\n";
+ OS << "} // end namespace llvm\n\n";
OS << "#endif // GET_SUBTARGETINFO_CTOR\n\n";
}
@@ -1548,4 +1533,4 @@ void EmitSubtarget(RecordKeeper &RK, raw_ostream &OS) {
SubtargetEmitter(RK, CGTarget).run(OS);
}
-} // end llvm namespace
+} // end namespace llvm
diff --git a/contrib/llvm/utils/TableGen/TableGen.cpp b/contrib/llvm/utils/TableGen/TableGen.cpp
index bcc594d..24dbe5d 100644
--- a/contrib/llvm/utils/TableGen/TableGen.cpp
+++ b/contrib/llvm/utils/TableGen/TableGen.cpp
@@ -43,7 +43,8 @@ enum ActionType {
PrintSets,
GenOptParserDefs,
GenCTags,
- GenAttributes
+ GenAttributes,
+ GenSearchableTables,
};
namespace {
@@ -89,6 +90,8 @@ namespace {
"Generate ctags-compatible index"),
clEnumValN(GenAttributes, "gen-attrs",
"Generate attributes"),
+ clEnumValN(GenSearchableTables, "gen-searchable-tables",
+ "Generate generic binary-searchable table"),
clEnumValEnd));
cl::opt<std::string>
@@ -172,6 +175,9 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
case GenAttributes:
EmitAttributes(Records, OS);
break;
+ case GenSearchableTables:
+ EmitSearchableTables(Records, OS);
+ break;
}
return false;
@@ -179,7 +185,7 @@ bool LLVMTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
}
int main(int argc, char **argv) {
- sys::PrintStackTraceOnErrorSignal();
+ sys::PrintStackTraceOnErrorSignal(argv[0]);
PrettyStackTraceProgram X(argc, argv);
cl::ParseCommandLineOptions(argc, argv);
diff --git a/contrib/llvm/utils/TableGen/TableGenBackends.h b/contrib/llvm/utils/TableGen/TableGenBackends.h
index d9dd3d1..51e017f 100644
--- a/contrib/llvm/utils/TableGen/TableGenBackends.h
+++ b/contrib/llvm/utils/TableGen/TableGenBackends.h
@@ -79,6 +79,7 @@ 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);
} // End llvm namespace
diff --git a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp
index ad36dc4..5b710e4 100644
--- a/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp
+++ b/contrib/llvm/utils/TableGen/X86DisassemblerTables.cpp
@@ -285,7 +285,7 @@ static inline bool inheritsFrom(InstructionContext child,
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_K_B:
case IC_EVEX_L_W_XS_K:
case IC_EVEX_L_W_XS_B:
case IC_EVEX_L_W_XS_K_B:
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
index 8a5ae12..ca937d0 100644
--- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.cpp
@@ -225,7 +225,6 @@ RecognizableInstr::RecognizableInstr(DisassemblerTables &tables,
CD8_Scale = byteFromRec(Rec, "CD8_Scale");
Name = Rec->getName();
- AsmString = Rec->getValueAsString("AsmString");
Operands = &insn.Operands.OperandList;
@@ -477,7 +476,7 @@ void RecognizableInstr::adjustOperandEncoding(OperandEncoding &encoding) {
void RecognizableInstr::handleOperand(bool optional, unsigned &operandIndex,
unsigned &physicalOperandIndex,
- unsigned &numPhysicalOperands,
+ unsigned numPhysicalOperands,
const unsigned *operandMapping,
OperandEncoding (*encodingFromString)
(const std::string&,
@@ -562,6 +561,7 @@ void RecognizableInstr::emitInstructionSpecifier() {
// 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;
@@ -569,6 +569,7 @@ void RecognizableInstr::emitInstructionSpecifier() {
++additionalOperands;
if (HasEVEX_K)
++additionalOperands;
+#endif
switch (Form) {
default: llvm_unreachable("Unhandled form");
@@ -584,11 +585,9 @@ void RecognizableInstr::emitInstructionSpecifier() {
return;
case X86Local::RawFrm:
// Operand 1 (optional) is an address or immediate.
- // Operand 2 (optional) is an immediate.
- assert(numPhysicalOperands <= 2 &&
+ assert(numPhysicalOperands <= 1 &&
"Unexpected number of operands for RawFrm");
HANDLE_OPTIONAL(relocation)
- HANDLE_OPTIONAL(immediate)
break;
case X86Local::RawFrmMemOffs:
// Operand 1 is an address.
@@ -800,8 +799,8 @@ void RecognizableInstr::emitInstructionSpecifier() {
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:
+ case X86Local::MRM_FB: case X86Local::MRM_FC: case X86Local::MRM_FD:
+ case X86Local::MRM_FE: case X86Local::MRM_FF:
// Ignored.
break;
}
@@ -1024,19 +1023,19 @@ OperandType RecognizableInstr::typeFromString(const std::string &s,
TYPE("VK32WM", TYPE_VK32)
TYPE("VK64", TYPE_VK64)
TYPE("VK64WM", TYPE_VK64)
- TYPE("GR16_NOAX", TYPE_Rv)
TYPE("GR32_NOAX", TYPE_Rv)
- TYPE("GR64_NOAX", TYPE_R64)
- TYPE("vx32mem", TYPE_M32)
- TYPE("vx32xmem", TYPE_M32)
- TYPE("vy32mem", TYPE_M32)
- TYPE("vy32xmem", TYPE_M32)
- TYPE("vz32mem", TYPE_M32)
TYPE("vx64mem", TYPE_M64)
+ TYPE("vx128mem", TYPE_M128)
+ TYPE("vx256mem", TYPE_M256)
+ TYPE("vy128mem", TYPE_M128)
+ TYPE("vy256mem", TYPE_M256)
TYPE("vx64xmem", TYPE_M64)
- TYPE("vy64mem", TYPE_M64)
- TYPE("vy64xmem", TYPE_M64)
- TYPE("vz64mem", TYPE_M64)
+ TYPE("vx128xmem", TYPE_M128)
+ TYPE("vx256xmem", TYPE_M256)
+ TYPE("vy128xmem", TYPE_M128)
+ TYPE("vy256xmem", TYPE_M256)
+ TYPE("vy512mem", TYPE_M512)
+ TYPE("vz512mem", TYPE_M512)
TYPE("BNDR", TYPE_BNDR)
errs() << "Unhandled type string " << s << "\n";
llvm_unreachable("Unhandled type string");
@@ -1220,16 +1219,18 @@ RecognizableInstr::memoryEncodingFromString(const std::string &s,
ENCODING("opaque48mem", ENCODING_RM)
ENCODING("opaque80mem", ENCODING_RM)
ENCODING("opaque512mem", ENCODING_RM)
- ENCODING("vx32mem", ENCODING_RM)
- ENCODING("vx32xmem", ENCODING_RM)
- ENCODING("vy32mem", ENCODING_RM)
- ENCODING("vy32xmem", ENCODING_RM)
- ENCODING("vz32mem", ENCODING_RM)
ENCODING("vx64mem", ENCODING_RM)
+ ENCODING("vx128mem", ENCODING_RM)
+ ENCODING("vx256mem", ENCODING_RM)
+ ENCODING("vy128mem", ENCODING_RM)
+ ENCODING("vy256mem", ENCODING_RM)
ENCODING("vx64xmem", ENCODING_RM)
- ENCODING("vy64mem", ENCODING_RM)
- ENCODING("vy64xmem", ENCODING_RM)
- ENCODING("vz64mem", ENCODING_RM)
+ ENCODING("vx128xmem", ENCODING_RM)
+ ENCODING("vx256xmem", ENCODING_RM)
+ ENCODING("vy128xmem", ENCODING_RM)
+ ENCODING("vy256xmem", ENCODING_RM)
+ ENCODING("vy512mem", ENCODING_RM)
+ ENCODING("vz512mem", ENCODING_RM)
errs() << "Unhandled memory encoding " << s << "\n";
llvm_unreachable("Unhandled memory encoding");
}
@@ -1288,9 +1289,7 @@ RecognizableInstr::opcodeModifierEncodingFromString(const std::string &s,
ENCODING("GR64", ENCODING_RO)
ENCODING("GR16", ENCODING_Rv)
ENCODING("GR8", ENCODING_RB)
- ENCODING("GR16_NOAX", ENCODING_Rv)
ENCODING("GR32_NOAX", ENCODING_Rv)
- ENCODING("GR64_NOAX", ENCODING_RO)
errs() << "Unhandled opcode modifier encoding " << s << "\n";
llvm_unreachable("Unhandled opcode modifier encoding");
}
diff --git a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
index 28e1053..f6f5006 100644
--- a/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
+++ b/contrib/llvm/utils/TableGen/X86RecognizableInstr.h
@@ -19,7 +19,6 @@
#include "CodeGenTarget.h"
#include "X86DisassemblerTables.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/TableGen/Record.h"
@@ -87,8 +86,6 @@ private:
/// The instruction name as listed in the tables
std::string Name;
- /// The AT&T AsmString for the instruction
- std::string AsmString;
/// Indicates whether the instruction should be emitted into the decode
/// tables; regardless, it will be emitted into the instruction info table
@@ -179,7 +176,7 @@ private:
void handleOperand(bool optional,
unsigned &operandIndex,
unsigned &physicalOperandIndex,
- unsigned &numPhysicalOperands,
+ unsigned numPhysicalOperands,
const unsigned *operandMapping,
OperandEncoding (*encodingFromString)
(const std::string&,
diff --git a/contrib/llvm/utils/TableGen/module.modulemap b/contrib/llvm/utils/TableGen/module.modulemap
deleted file mode 100644
index 8871bbf..0000000
--- a/contrib/llvm/utils/TableGen/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module TableGen {
- umbrella "."
- module * { export * }
-}
OpenPOWER on IntegriCloud