summaryrefslogtreecommitdiff
path: root/utils/TableGen/AsmMatcherEmitter.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2010-07-19 05:44:09 +0000
committerDaniel Dunbar <daniel@zuster.org>2010-07-19 05:44:09 +0000
commit54074b5f04f5affc77b5c6f3e5d8062b50384831 (patch)
tree9842503592f0e7c5006a73805f892c29cb51ba69 /utils/TableGen/AsmMatcherEmitter.cpp
parent24fdd27683960157eaed38a18d95958873f74959 (diff)
downloadllvm-54074b5f04f5affc77b5c6f3e5d8062b50384831.tar.gz
llvm-54074b5f04f5affc77b5c6f3e5d8062b50384831.tar.bz2
llvm-54074b5f04f5affc77b5c6f3e5d8062b50384831.tar.xz
TblGen/AsmMatcher: Add support for honoring instruction Requires<[]> attributes as part of the matcher.
- Currently includes a hack to limit ourselves to "In32BitMode" and "In64BitMode", because we don't have the other infrastructure to properly deal with setting SSE, etc. features on X86. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108677 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'utils/TableGen/AsmMatcherEmitter.cpp')
-rw-r--r--utils/TableGen/AsmMatcherEmitter.cpp138
1 files changed, 136 insertions, 2 deletions
diff --git a/utils/TableGen/AsmMatcherEmitter.cpp b/utils/TableGen/AsmMatcherEmitter.cpp
index e1aa2bc70f..08a430dc92 100644
--- a/utils/TableGen/AsmMatcherEmitter.cpp
+++ b/utils/TableGen/AsmMatcherEmitter.cpp
@@ -271,6 +271,8 @@ static bool IsAssemblerInstruction(StringRef Name,
namespace {
+struct SubtargetFeatureInfo;
+
/// ClassInfo - Helper class for storing the information about a particular
/// class of operands which can be matched.
struct ClassInfo {
@@ -444,6 +446,9 @@ struct InstructionInfo {
/// Operands - The operands that this instruction matches.
SmallVector<Operand, 4> Operands;
+ /// Predicates - The required subtarget features to match this instruction.
+ SmallVector<SubtargetFeatureInfo*, 4> RequiredFeatures;
+
/// ConversionFnKind - The enum value which is passed to the generated
/// ConvertToMCInst to convert parsed operands into an MCInst for this
/// function.
@@ -505,6 +510,19 @@ public:
void dump();
};
+/// SubtargetFeatureInfo - Helper class for storing information on a subtarget
+/// feature which participates in instruction matching.
+struct SubtargetFeatureInfo {
+ /// \brief The predicate record for this feature.
+ Record *TheDef;
+
+ /// \brief An unique index assigned to represent this feature.
+ unsigned Index;
+
+ /// \brief The name of the enumerated constant identifying this feature.
+ std::string EnumName;
+};
+
class AsmMatcherInfo {
public:
/// The tablegen AsmParser record.
@@ -525,6 +543,9 @@ public:
/// Map of Register records to their class information.
std::map<Record*, ClassInfo*> RegisterClasses;
+ /// Map of Predicate records to their subtarget information.
+ std::map<Record*, SubtargetFeatureInfo*> SubtargetFeatures;
+
private:
/// Map of token to class information which has already been constructed.
std::map<std::string, ClassInfo*> TokenClasses;
@@ -543,6 +564,23 @@ private:
ClassInfo *getOperandClass(StringRef Token,
const CodeGenInstruction::OperandInfo &OI);
+ /// getSubtargetFeature - Lookup or create the subtarget feature info for the
+ /// given operand.
+ SubtargetFeatureInfo *getSubtargetFeature(Record *Def) {
+ assert(Def->isSubClassOf("Predicate") && "Invalid predicate type!");
+
+ SubtargetFeatureInfo *&Entry = SubtargetFeatures[Def];
+ if (!Entry) {
+ Entry = new SubtargetFeatureInfo;
+ Entry->TheDef = Def;
+ Entry->Index = SubtargetFeatures.size() - 1;
+ Entry->EnumName = "Feature_" + Def->getName();
+ assert(Entry->Index < 32 && "Too many subtarget features!");
+ }
+
+ return Entry;
+ }
+
/// BuildRegisterClasses - Build the ClassInfo* instances for register
/// classes.
void BuildRegisterClasses(CodeGenTarget &Target,
@@ -903,7 +941,31 @@ void AsmMatcherInfo::BuildInfo(CodeGenTarget &Target) {
}
}
}
-
+
+ // Compute the require features.
+ ListInit *Predicates = CGI.TheDef->getValueAsListInit("Predicates");
+ for (unsigned i = 0, e = Predicates->getSize(); i != e; ++i) {
+ if (DefInit *Pred = dynamic_cast<DefInit*>(Predicates->getElement(i))) {
+ // Ignore OptForSize and OptForSpeed, they aren't really requirements,
+ // rather they are hints to isel.
+ //
+ // FIXME: Find better way to model this.
+ if (Pred->getDef()->getName() == "OptForSize" ||
+ Pred->getDef()->getName() == "OptForSpeed")
+ continue;
+
+ // FIXME: Total hack; for now, we just limit ourselves to In32BitMode
+ // and In64BitMode, because we aren't going to have the right feature
+ // masks for SSE and friends. We need to decide what we are going to do
+ // about CPU subtypes to implement this the right way.
+ if (Pred->getDef()->getName() != "In32BitMode" &&
+ Pred->getDef()->getName() != "In64BitMode")
+ continue;
+
+ II->RequiredFeatures.push_back(getSubtargetFeature(Pred->getDef()));
+ }
+ }
+
Instructions.push_back(II.take());
}
@@ -1499,6 +1561,48 @@ static void EmitMatchRegisterName(CodeGenTarget &Target, Record *AsmParser,
OS << "}\n\n";
}
+/// EmitSubtargetFeatureFlagEnumeration - Emit the subtarget feature flag
+/// definitions.
+static void EmitSubtargetFeatureFlagEnumeration(CodeGenTarget &Target,
+ AsmMatcherInfo &Info,
+ raw_ostream &OS) {
+ OS << "// Flags for subtarget features that participate in "
+ << "instruction matching.\n";
+ OS << "enum SubtargetFeatureFlag {\n";
+ for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator
+ it = Info.SubtargetFeatures.begin(),
+ ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
+ SubtargetFeatureInfo &SFI = *it->second;
+ OS << " " << SFI.EnumName << " = (1 << " << SFI.Index << "),\n";
+ }
+ OS << " Feature_None = 0\n";
+ OS << "};\n\n";
+}
+
+/// EmitComputeAvailableFeatures - Emit the function to compute the list of
+/// available features given a subtarget.
+static void EmitComputeAvailableFeatures(CodeGenTarget &Target,
+ AsmMatcherInfo &Info,
+ raw_ostream &OS) {
+ std::string ClassName =
+ Info.AsmParser->getValueAsString("AsmParserClassName");
+
+ OS << "unsigned " << Target.getName() << ClassName << "::\n"
+ << "ComputeAvailableFeatures(const " << Target.getName()
+ << "Subtarget *Subtarget) const {\n";
+ OS << " unsigned Features = 0;\n";
+ for (std::map<Record*, SubtargetFeatureInfo*>::const_iterator
+ it = Info.SubtargetFeatures.begin(),
+ ie = Info.SubtargetFeatures.end(); it != ie; ++it) {
+ SubtargetFeatureInfo &SFI = *it->second;
+ OS << " if (" << SFI.TheDef->getValueAsString("CondString")
+ << ")\n";
+ OS << " Features |= " << SFI.EnumName << ";\n";
+ }
+ OS << " return Features;\n";
+ OS << "}\n\n";
+}
+
void AsmMatcherEmitter::run(raw_ostream &OS) {
CodeGenTarget Target;
Record *AsmParser = Target.getAsmParser();
@@ -1550,6 +1654,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
EmitSourceFileHeader("Assembly Matcher Source Fragment", OS);
+ // Emit the subtarget feature enumeration.
+ EmitSubtargetFeatureFlagEnumeration(Target, Info, OS);
+
// Emit the function to match a register name to number.
EmitMatchRegisterName(Target, AsmParser, OS);
@@ -1570,6 +1677,9 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
// Emit the subclass predicate routine.
EmitIsSubclass(Target, Info.Classes, OS);
+ // Emit the available features compute function.
+ EmitComputeAvailableFeatures(Target, Info, OS);
+
// Finally, build the match function.
size_t MaxNumOperands = 0;
@@ -1600,6 +1710,7 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " unsigned Opcode;\n";
OS << " ConversionKind ConvertFn;\n";
OS << " MatchClassKind Classes[" << MaxNumOperands << "];\n";
+ OS << " unsigned RequiredFeatures;\n";
OS << " } MatchTable[" << Info.Instructions.size() << "] = {\n";
for (std::vector<InstructionInfo*>::const_iterator it =
@@ -1615,11 +1726,27 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
if (i) OS << ", ";
OS << Op.Class->Name;
}
- OS << " } },\n";
+ OS << " }, ";
+
+ // Write the required features mask.
+ if (!II.RequiredFeatures.empty()) {
+ for (unsigned i = 0, e = II.RequiredFeatures.size(); i != e; ++i) {
+ if (i) OS << "|";
+ OS << II.RequiredFeatures[i]->EnumName;
+ }
+ } else
+ OS << "0";
+
+ OS << "},\n";
}
OS << " };\n\n";
+
+ // Emit code to get the available features.
+ OS << " // Get the current feature set.\n";
+ OS << " unsigned AvailableFeatures = getAvailableFeatures();\n\n";
+
// Emit code to compute the class list for this operand vector.
OS << " // Eliminate obvious mismatches.\n";
OS << " if (Operands.size() > " << MaxNumOperands << ")\n";
@@ -1645,6 +1772,13 @@ void AsmMatcherEmitter::run(raw_ostream &OS) {
OS << " for (const MatchEntry *it = MatchTable, "
<< "*ie = MatchTable + " << Info.Instructions.size()
<< "; it != ie; ++it) {\n";
+
+ // Emit check that the required features are available.
+ OS << " if ((AvailableFeatures & it->RequiredFeatures) "
+ << "!= it->RequiredFeatures)\n";
+ OS << " continue;\n";
+
+ // Emit check that the subclasses match.
for (unsigned i = 0; i != MaxNumOperands; ++i) {
OS << " if (!IsSubclass(Classes["
<< i << "], it->Classes[" << i << "]))\n";