aboutsummaryrefslogtreecommitdiff
path: root/utils/TableGen
diff options
context:
space:
mode:
Diffstat (limited to 'utils/TableGen')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp365
-rw-r--r--utils/TableGen/AsmWriterEmitter.cpp252
-rw-r--r--utils/TableGen/AsmWriterInst.cpp19
-rw-r--r--utils/TableGen/AsmWriterInst.h29
-rw-r--r--utils/TableGen/Attributes.cpp23
-rw-r--r--utils/TableGen/CMakeLists.txt1
-rw-r--r--utils/TableGen/CodeEmitterGen.cpp9
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp23
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h4
-rw-r--r--utils/TableGen/CodeGenInstruction.cpp5
-rw-r--r--utils/TableGen/CodeGenInstruction.h7
-rw-r--r--utils/TableGen/CodeGenIntrinsics.h191
-rw-r--r--utils/TableGen/CodeGenMapTable.cpp33
-rw-r--r--utils/TableGen/CodeGenRegisters.cpp102
-rw-r--r--utils/TableGen/CodeGenRegisters.h6
-rw-r--r--utils/TableGen/CodeGenSchedule.cpp101
-rw-r--r--utils/TableGen/CodeGenSchedule.h15
-rw-r--r--utils/TableGen/CodeGenTarget.cpp64
-rw-r--r--utils/TableGen/CodeGenTarget.h15
-rw-r--r--utils/TableGen/DAGISelMatcher.cpp64
-rw-r--r--utils/TableGen/DAGISelMatcher.h125
-rw-r--r--utils/TableGen/DAGISelMatcherEmitter.cpp49
-rw-r--r--utils/TableGen/DAGISelMatcherGen.cpp16
-rw-r--r--utils/TableGen/DAGISelMatcherOpt.cpp83
-rw-r--r--utils/TableGen/DFAPacketizerEmitter.cpp27
-rw-r--r--utils/TableGen/DisassemblerEmitter.cpp13
-rw-r--r--utils/TableGen/FastISelEmitter.cpp6
-rw-r--r--utils/TableGen/FixedLenDecoderEmitter.cpp134
-rw-r--r--utils/TableGen/InstrInfoEmitter.cpp65
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp283
-rw-r--r--utils/TableGen/Makefile18
-rw-r--r--utils/TableGen/RegisterInfoEmitter.cpp116
-rw-r--r--utils/TableGen/SearchableTableEmitter.cpp320
-rw-r--r--utils/TableGen/SequenceToOffsetTable.h1
-rw-r--r--utils/TableGen/SubtargetEmitter.cpp311
-rw-r--r--utils/TableGen/TableGen.cpp10
-rw-r--r--utils/TableGen/TableGenBackends.h1
-rw-r--r--utils/TableGen/X86DisassemblerTables.cpp2
-rw-r--r--utils/TableGen/X86RecognizableInstr.cpp53
-rw-r--r--utils/TableGen/X86RecognizableInstr.h5
-rw-r--r--utils/TableGen/module.modulemap4
41 files changed, 1663 insertions, 1307 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index 6e9a9484dc88..76228e0b6581 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/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/utils/TableGen/AsmWriterEmitter.cpp b/utils/TableGen/AsmWriterEmitter.cpp
index cf7cbd962865..fc2138f7e8ea 100644
--- a/utils/TableGen/AsmWriterEmitter.cpp
+++ b/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/utils/TableGen/AsmWriterInst.cpp b/utils/TableGen/AsmWriterInst.cpp
index 5b09765a2756..2c19e5d663d6 100644
--- a/utils/TableGen/AsmWriterInst.cpp
+++ b/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/utils/TableGen/AsmWriterInst.h b/utils/TableGen/AsmWriterInst.h
index a597e6ba1a55..708f23cb5b0e 100644
--- a/utils/TableGen/AsmWriterInst.h
+++ b/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/utils/TableGen/Attributes.cpp b/utils/TableGen/Attributes.cpp
index 7b001bf14de5..58dbe5767ada 100644
--- a/utils/TableGen/Attributes.cpp
+++ b/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/utils/TableGen/CMakeLists.txt b/utils/TableGen/CMakeLists.txt
index eef1540424dd..e8fe30f5ac70 100644
--- a/utils/TableGen/CMakeLists.txt
+++ b/utils/TableGen/CMakeLists.txt
@@ -27,6 +27,7 @@ add_tablegen(llvm-tblgen LLVM
OptParserEmitter.cpp
PseudoLoweringEmitter.cpp
RegisterInfoEmitter.cpp
+ SearchableTableEmitter.cpp
SubtargetEmitter.cpp
TableGen.cpp
X86DisassemblerTables.cpp
diff --git a/utils/TableGen/CodeEmitterGen.cpp b/utils/TableGen/CodeEmitterGen.cpp
index 46fcdf5e96ff..400913e32745 100644
--- a/utils/TableGen/CodeEmitterGen.cpp
+++ b/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/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index 3ebe51e05121..307a95373c9d 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/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/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index 76c9cefea50f..819c4b8492cb 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/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/utils/TableGen/CodeGenInstruction.cpp b/utils/TableGen/CodeGenInstruction.cpp
index 366e8ec7fac1..ec802363030e 100644
--- a/utils/TableGen/CodeGenInstruction.cpp
+++ b/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/utils/TableGen/CodeGenInstruction.h b/utils/TableGen/CodeGenInstruction.h
index 8f01abd5403c..8e5a03d7b743 100644
--- a/utils/TableGen/CodeGenInstruction.h
+++ b/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/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h
index 7bdb7e1bc537..ea3ec67d62ed 100644
--- a/utils/TableGen/CodeGenIntrinsics.h
+++ b/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/utils/TableGen/CodeGenMapTable.cpp b/utils/TableGen/CodeGenMapTable.cpp
index f66dd082709b..527f530da479 100644
--- a/utils/TableGen/CodeGenMapTable.cpp
+++ b/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/utils/TableGen/CodeGenRegisters.cpp b/utils/TableGen/CodeGenRegisters.cpp
index ca316e96a21a..626144fbe855 100644
--- a/utils/TableGen/CodeGenRegisters.cpp
+++ b/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/utils/TableGen/CodeGenRegisters.h b/utils/TableGen/CodeGenRegisters.h
index dc441436537d..b8d47aa4ff82 100644
--- a/utils/TableGen/CodeGenRegisters.h
+++ b/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/utils/TableGen/CodeGenSchedule.cpp b/utils/TableGen/CodeGenSchedule.cpp
index c98f62345342..d1b141e3160f 100644
--- a/utils/TableGen/CodeGenSchedule.cpp
+++ b/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/utils/TableGen/CodeGenSchedule.h b/utils/TableGen/CodeGenSchedule.h
index f5c50c992a92..755ffd25b0cb 100644
--- a/utils/TableGen/CodeGenSchedule.h
+++ b/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/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index aaad4225ace8..245b9eeeed85 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/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/utils/TableGen/CodeGenTarget.h b/utils/TableGen/CodeGenTarget.h
index cf4a0bbe5bd9..85a8c1b18878 100644
--- a/utils/TableGen/CodeGenTarget.h
+++ b/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/utils/TableGen/DAGISelMatcher.cpp b/utils/TableGen/DAGISelMatcher.cpp
index 9c4079906a38..6ac3958e0f43 100644
--- a/utils/TableGen/DAGISelMatcher.cpp
+++ b/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/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h
index a8a6ba5c32e1..6bda9ca5f96f 100644
--- a/utils/TableGen/DAGISelMatcher.h
+++ b/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/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp
index 26f53dca6361..d30fc5131cba 100644
--- a/utils/TableGen/DAGISelMatcherEmitter.cpp
+++ b/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/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp
index 9663b71d6620..4110e9725b5a 100644
--- a/utils/TableGen/DAGISelMatcherGen.cpp
+++ b/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/utils/TableGen/DAGISelMatcherOpt.cpp b/utils/TableGen/DAGISelMatcherOpt.cpp
index c9ee371e3e2f..ad385fac0438 100644
--- a/utils/TableGen/DAGISelMatcherOpt.cpp
+++ b/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/utils/TableGen/DFAPacketizerEmitter.cpp b/utils/TableGen/DFAPacketizerEmitter.cpp
index 77afff7ab5c2..e31caaf3c98c 100644
--- a/utils/TableGen/DFAPacketizerEmitter.cpp
+++ b/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/utils/TableGen/DisassemblerEmitter.cpp b/utils/TableGen/DisassemblerEmitter.cpp
index e8595271bcce..44815b05f274 100644
--- a/utils/TableGen/DisassemblerEmitter.cpp
+++ b/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/utils/TableGen/FastISelEmitter.cpp b/utils/TableGen/FastISelEmitter.cpp
index 748c92347783..debb12c4f511 100644
--- a/utils/TableGen/FastISelEmitter.cpp
+++ b/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/utils/TableGen/FixedLenDecoderEmitter.cpp b/utils/TableGen/FixedLenDecoderEmitter.cpp
index 8ca4a1bf5404..0506400b90f6 100644
--- a/utils/TableGen/FixedLenDecoderEmitter.cpp
+++ b/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/utils/TableGen/InstrInfoEmitter.cpp b/utils/TableGen/InstrInfoEmitter.cpp
index a6583399fa20..02461cc0508d 100644
--- a/utils/TableGen/InstrInfoEmitter.cpp
+++ b/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/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index 42a6a152f55e..a676159e494b 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/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/utils/TableGen/Makefile b/utils/TableGen/Makefile
deleted file mode 100644
index 9bfd94b7576b..000000000000
--- a/utils/TableGen/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-##===- utils/TableGen/Makefile -----------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../..
-TOOLNAME = llvm-tblgen
-USEDLIBS = LLVMTableGen.a LLVMSupport.a
-
-# This tool has no plugins, optimize startup time.
-TOOL_NO_EXPORTS = 1
-
-include $(LEVEL)/Makefile.common
-
diff --git a/utils/TableGen/RegisterInfoEmitter.cpp b/utils/TableGen/RegisterInfoEmitter.cpp
index b727df75626f..9bb988f30f18 100644
--- a/utils/TableGen/RegisterInfoEmitter.cpp
+++ b/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/utils/TableGen/SearchableTableEmitter.cpp b/utils/TableGen/SearchableTableEmitter.cpp
new file mode 100644
index 000000000000..8c1b8804d174
--- /dev/null
+++ b/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/utils/TableGen/SequenceToOffsetTable.h b/utils/TableGen/SequenceToOffsetTable.h
index 66506ea0638f..e026b1c9fbf0 100644
--- a/utils/TableGen/SequenceToOffsetTable.h
+++ b/utils/TableGen/SequenceToOffsetTable.h
@@ -22,7 +22,6 @@
#include <cctype>
#include <functional>
#include <map>
-#include <vector>
namespace llvm {
diff --git a/utils/TableGen/SubtargetEmitter.cpp b/utils/TableGen/SubtargetEmitter.cpp
index d056de003e18..228882177bdf 100644
--- a/utils/TableGen/SubtargetEmitter.cpp
+++ b/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/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index bcc594d69a1d..24dbe5d3a280 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/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/utils/TableGen/TableGenBackends.h b/utils/TableGen/TableGenBackends.h
index d9dd3d157697..51e017fe6594 100644
--- a/utils/TableGen/TableGenBackends.h
+++ b/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/utils/TableGen/X86DisassemblerTables.cpp b/utils/TableGen/X86DisassemblerTables.cpp
index ad36dc427a56..5b710e446150 100644
--- a/utils/TableGen/X86DisassemblerTables.cpp
+++ b/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/utils/TableGen/X86RecognizableInstr.cpp b/utils/TableGen/X86RecognizableInstr.cpp
index 8a5ae12f67fb..ca937d09726d 100644
--- a/utils/TableGen/X86RecognizableInstr.cpp
+++ b/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/utils/TableGen/X86RecognizableInstr.h b/utils/TableGen/X86RecognizableInstr.h
index 28e10535508d..f6f50065f704 100644
--- a/utils/TableGen/X86RecognizableInstr.h
+++ b/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/utils/TableGen/module.modulemap b/utils/TableGen/module.modulemap
deleted file mode 100644
index 8871bbfd4a2f..000000000000
--- a/utils/TableGen/module.modulemap
+++ /dev/null
@@ -1,4 +0,0 @@
-module TableGen {
- umbrella "."
- module * { export * }
-}