diff options
Diffstat (limited to 'utils/TableGen')
-rw-r--r-- | utils/TableGen/DAGISelMatcher.h | 26 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcherEmitter.cpp | 59 | ||||
-rw-r--r-- | utils/TableGen/DAGISelMatcherGen.cpp | 102 | ||||
-rw-r--r-- | utils/TableGen/LLVMCConfigurationEmitter.cpp | 76 |
4 files changed, 190 insertions, 73 deletions
diff --git a/utils/TableGen/DAGISelMatcher.h b/utils/TableGen/DAGISelMatcher.h index c2e8171..7955c7e 100644 --- a/utils/TableGen/DAGISelMatcher.h +++ b/utils/TableGen/DAGISelMatcher.h @@ -609,11 +609,28 @@ private: /// the current node. class CheckComplexPatMatcher : public Matcher { const ComplexPattern &Pattern; + + /// MatchNumber - This is the recorded nodes slot that contains the node we want to + /// match against. + unsigned MatchNumber; + + /// Name - The name of the node we're matching, for comment emission. + std::string Name; + + /// FirstResult - This is the first slot in the RecordedNodes list that the + /// result of the match populates. + unsigned FirstResult; public: - CheckComplexPatMatcher(const ComplexPattern &pattern) - : Matcher(CheckComplexPat), Pattern(pattern) {} + CheckComplexPatMatcher(const ComplexPattern &pattern, unsigned matchnumber, + const std::string &name, unsigned firstresult) + : Matcher(CheckComplexPat), Pattern(pattern), MatchNumber(matchnumber), + Name(name), FirstResult(firstresult) {} const ComplexPattern &getPattern() const { return Pattern; } + unsigned getMatchNumber() const { return MatchNumber; } + + const std::string getName() const { return Name; } + unsigned getFirstResult() const { return FirstResult; } static inline bool classof(const Matcher *N) { return N->getKind() == CheckComplexPat; @@ -625,10 +642,11 @@ public: private: virtual void printImpl(raw_ostream &OS, unsigned indent) const; virtual bool isEqualImpl(const Matcher *M) const { - return &cast<CheckComplexPatMatcher>(M)->Pattern == &Pattern; + return &cast<CheckComplexPatMatcher>(M)->Pattern == &Pattern && + cast<CheckComplexPatMatcher>(M)->MatchNumber == MatchNumber; } virtual unsigned getHashImpl() const { - return (unsigned)(intptr_t)&Pattern; + return (unsigned)(intptr_t)&Pattern ^ MatchNumber; } }; diff --git a/utils/TableGen/DAGISelMatcherEmitter.cpp b/utils/TableGen/DAGISelMatcherEmitter.cpp index 1f04050..cabf2d4 100644 --- a/utils/TableGen/DAGISelMatcherEmitter.cpp +++ b/utils/TableGen/DAGISelMatcherEmitter.cpp @@ -42,8 +42,6 @@ class MatcherTableEmitter { DenseMap<Record*, unsigned> NodeXFormMap; std::vector<Record*> NodeXForms; - // Per opcode frequence count. - std::vector<unsigned> Histogram; public: MatcherTableEmitter() {} @@ -53,7 +51,7 @@ public: void EmitPredicateFunctions(const CodeGenDAGPatterns &CGP, formatted_raw_ostream &OS); - void EmitHistogram(formatted_raw_ostream &OS); + void EmitHistogram(const Matcher *N, formatted_raw_ostream &OS); private: unsigned EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, formatted_raw_ostream &OS); @@ -370,17 +368,22 @@ EmitMatcher(const Matcher *N, unsigned Indent, unsigned CurrentIdx, return 2; case Matcher::CheckComplexPat: { - const ComplexPattern &Pattern = - cast<CheckComplexPatMatcher>(N)->getPattern(); - OS << "OPC_CheckComplexPat, " << getComplexPat(Pattern) << ','; + const CheckComplexPatMatcher *CCPM = cast<CheckComplexPatMatcher>(N); + const ComplexPattern &Pattern = CCPM->getPattern(); + OS << "OPC_CheckComplexPat, /*CP*/" << getComplexPat(Pattern) << ", /*#*/" + << CCPM->getMatchNumber() << ','; + if (!OmitComments) { OS.PadToColumn(CommentIndent) << "// " << Pattern.getSelectFunc(); - OS << ": " << Pattern.getNumOperands() << " operands"; + OS << ":$" << CCPM->getName(); + for (unsigned i = 0, e = Pattern.getNumOperands(); i != e; ++i) + OS << " #" << CCPM->getFirstResult()+i; + if (Pattern.hasProperty(SDNPHasChain)) - OS << " + chain result and input"; + OS << " + chain result"; } OS << '\n'; - return 2; + return 3; } case Matcher::CheckAndImm: { @@ -549,9 +552,6 @@ EmitMatcherList(const Matcher *N, unsigned Indent, unsigned CurrentIdx, formatted_raw_ostream &OS) { unsigned Size = 0; while (N) { - if (unsigned(N->getKind()) >= Histogram.size()) - Histogram.resize(N->getKind()+1); - Histogram[N->getKind()]++; if (!OmitComments) OS << "/*" << CurrentIdx << "*/"; unsigned MatcherSize = EmitMatcher(N, Indent, CurrentIdx, OS); @@ -676,11 +676,38 @@ void MatcherTableEmitter::EmitPredicateFunctions(const CodeGenDAGPatterns &CGP, } } -void MatcherTableEmitter::EmitHistogram(formatted_raw_ostream &OS) { +static void BuildHistogram(const Matcher *M, std::vector<unsigned> &OpcodeFreq){ + for (; M != 0; M = M->getNext()) { + // Count this node. + if (unsigned(M->getKind()) >= OpcodeFreq.size()) + OpcodeFreq.resize(M->getKind()+1); + OpcodeFreq[M->getKind()]++; + + // Handle recursive nodes. + if (const ScopeMatcher *SM = dyn_cast<ScopeMatcher>(M)) { + for (unsigned i = 0, e = SM->getNumChildren(); i != e; ++i) + BuildHistogram(SM->getChild(i), OpcodeFreq); + } else if (const SwitchOpcodeMatcher *SOM = + dyn_cast<SwitchOpcodeMatcher>(M)) { + for (unsigned i = 0, e = SOM->getNumCases(); i != e; ++i) + BuildHistogram(SOM->getCaseMatcher(i), OpcodeFreq); + } else if (const SwitchTypeMatcher *STM = dyn_cast<SwitchTypeMatcher>(M)) { + for (unsigned i = 0, e = STM->getNumCases(); i != e; ++i) + BuildHistogram(STM->getCaseMatcher(i), OpcodeFreq); + } + } +} + +void MatcherTableEmitter::EmitHistogram(const Matcher *M, + formatted_raw_ostream &OS) { if (OmitComments) return; + + std::vector<unsigned> OpcodeFreq; + BuildHistogram(M, OpcodeFreq); + OS << " // Opcode Histogram:\n"; - for (unsigned i = 0, e = Histogram.size(); i != e; ++i) { + for (unsigned i = 0, e = OpcodeFreq.size(); i != e; ++i) { OS << " // #"; switch ((Matcher::KindTy)i) { case Matcher::Scope: OS << "OPC_Scope"; break; @@ -720,7 +747,7 @@ void MatcherTableEmitter::EmitHistogram(formatted_raw_ostream &OS) { case Matcher::CompleteMatch: OS << "OPC_CompleteMatch"; break; } - OS.PadToColumn(40) << " = " << Histogram[i] << '\n'; + OS.PadToColumn(40) << " = " << OpcodeFreq[i] << '\n'; } OS << '\n'; } @@ -741,7 +768,7 @@ void llvm::EmitMatcherTable(const Matcher *TheMatcher, unsigned TotalSize = MatcherEmitter.EmitMatcherList(TheMatcher, 5, 0, OS); OS << " 0\n }; // Total Array size is " << (TotalSize+1) << " bytes\n\n"; - MatcherEmitter.EmitHistogram(OS); + MatcherEmitter.EmitHistogram(TheMatcher, OS); OS << " #undef TARGET_OPCODE\n"; OS << " return SelectCodeCommon(N, MatcherTable,sizeof(MatcherTable));\n}\n"; diff --git a/utils/TableGen/DAGISelMatcherGen.cpp b/utils/TableGen/DAGISelMatcherGen.cpp index 4482803..5488853 100644 --- a/utils/TableGen/DAGISelMatcherGen.cpp +++ b/utils/TableGen/DAGISelMatcherGen.cpp @@ -72,6 +72,14 @@ namespace { /// nodes array of all of the recorded input nodes that have flag results. SmallVector<unsigned, 2> MatchedFlagResultNodes; + /// MatchedComplexPatterns - This maintains a list of all of the + /// ComplexPatterns that we need to check. The patterns are known to have + /// names which were recorded. The second element of each pair is the first + /// slot number that the OPC_CheckComplexPat opcode drops the matched + /// results into. + SmallVector<std::pair<const TreePatternNode*, + unsigned>, 2> MatchedComplexPatterns; + /// PhysRegInputs - List list has an entry for each explicitly specified /// physreg input to the pattern. The first elt is the Register node, the /// second is the recorded slot number the input pattern match saved it in. @@ -247,30 +255,9 @@ void MatcherGen::EmitLeafMatchCode(const TreePatternNode *N) { exit(1); } - // Handle complex pattern. - const ComplexPattern &CP = CGP.getComplexPattern(LeafRec); - - // Emit a CheckComplexPat operation, which does the match (aborting if it - // fails) and pushes the matched operands onto the recorded nodes list. - AddMatcher(new CheckComplexPatMatcher(CP)); - - // Record the right number of operands. - NextRecordedOperandNo += CP.getNumOperands(); - if (CP.hasProperty(SDNPHasChain)) - ++NextRecordedOperandNo; // Chained node operand. - - // If the complex pattern has a chain, then we need to keep track of the - // fact that we just recorded a chain input. The chain input will be - // matched as the last operand of the predicate if it was successful. - if (CP.hasProperty(SDNPHasChain)) { - // It is the last operand recorded. - assert(NextRecordedOperandNo > 1 && - "Should have recorded input/result chains at least!"); - MatchedChainNodes.push_back(NextRecordedOperandNo-1); - } - - // TODO: Complex patterns can't have output flags, if they did, we'd want - // to record them. + // Remember this ComplexPattern so that we can emit it after all the other + // structural matches are done. + MatchedComplexPatterns.push_back(std::make_pair(N, 0)); return; } @@ -484,17 +471,56 @@ bool MatcherGen::EmitMatcherCode(unsigned Variant) { if (Variant != 0) return true; } + // Emit the matcher for the pattern structure and types. + EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes); + // If the pattern has a predicate on it (e.g. only enabled when a subtarget // feature is around, do the check). - // FIXME: This should get emitted after the match code below to encourage - // sharing. This can't happen until we get an X86ISD::AddrMode node made by - // dag combine, eliminating the horrible side-effect-full stuff from - // X86's MatchAddress. if (!Pattern.getPredicateCheck().empty()) AddMatcher(new CheckPatternPredicateMatcher(Pattern.getPredicateCheck())); - - // Emit the matcher for the pattern structure and types. - EmitMatchCode(Pattern.getSrcPattern(), PatWithNoTypes); + + // Now that we've completed the structural type match, emit any ComplexPattern + // checks (e.g. addrmode matches). We emit this after the structural match + // because they are generally more expensive to evaluate and more difficult to + // factor. + for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) { + const TreePatternNode *N = MatchedComplexPatterns[i].first; + + // Remember where the results of this match get stuck. + MatchedComplexPatterns[i].second = NextRecordedOperandNo; + + // Get the slot we recorded the value in from the name on the node. + unsigned RecNodeEntry = VariableMap[N->getName()]; + assert(!N->getName().empty() && RecNodeEntry && + "Complex pattern should have a name and slot"); + --RecNodeEntry; // Entries in VariableMap are biased. + + const ComplexPattern &CP = + CGP.getComplexPattern(((DefInit*)N->getLeafValue())->getDef()); + + // Emit a CheckComplexPat operation, which does the match (aborting if it + // fails) and pushes the matched operands onto the recorded nodes list. + AddMatcher(new CheckComplexPatMatcher(CP, RecNodeEntry, + N->getName(), NextRecordedOperandNo)); + + // Record the right number of operands. + NextRecordedOperandNo += CP.getNumOperands(); + if (CP.hasProperty(SDNPHasChain)) { + // If the complex pattern has a chain, then we need to keep track of the + // fact that we just recorded a chain input. The chain input will be + // matched as the last operand of the predicate if it was successful. + ++NextRecordedOperandNo; // Chained node operand. + + // It is the last operand recorded. + assert(NextRecordedOperandNo > 1 && + "Should have recorded input/result chains at least!"); + MatchedChainNodes.push_back(NextRecordedOperandNo-1); + } + + // TODO: Complex patterns can't have output flags, if they did, we'd want + // to record them. + } + return false; } @@ -507,18 +533,26 @@ void MatcherGen::EmitResultOfNamedOperand(const TreePatternNode *N, SmallVectorImpl<unsigned> &ResultOps){ assert(!N->getName().empty() && "Operand not named!"); - unsigned SlotNo = getNamedArgumentSlot(N->getName()); - // A reference to a complex pattern gets all of the results of the complex // pattern's match. if (const ComplexPattern *CP = N->getComplexPatternInfo(CGP)) { + unsigned SlotNo = 0; + for (unsigned i = 0, e = MatchedComplexPatterns.size(); i != e; ++i) + if (MatchedComplexPatterns[i].first->getName() == N->getName()) { + SlotNo = MatchedComplexPatterns[i].second; + break; + } + assert(SlotNo != 0 && "Didn't get a slot number assigned?"); + // The first slot entry is the node itself, the subsequent entries are the // matched values. for (unsigned i = 0, e = CP->getNumOperands(); i != e; ++i) - ResultOps.push_back(SlotNo+i+1); + ResultOps.push_back(SlotNo+i); return; } + unsigned SlotNo = getNamedArgumentSlot(N->getName()); + // If this is an 'imm' or 'fpimm' node, make sure to convert it to the target // version of the immediate so that it doesn't get selected due to some other // node use. diff --git a/utils/TableGen/LLVMCConfigurationEmitter.cpp b/utils/TableGen/LLVMCConfigurationEmitter.cpp index db59053..da2d54f 100644 --- a/utils/TableGen/LLVMCConfigurationEmitter.cpp +++ b/utils/TableGen/LLVMCConfigurationEmitter.cpp @@ -230,7 +230,8 @@ namespace OptionDescriptionFlags { enum OptionDescriptionFlags { Required = 0x1, Hidden = 0x2, ReallyHidden = 0x4, Extern = 0x8, OneOrMore = 0x10, Optional = 0x20, - CommaSeparated = 0x40, ForwardNotSplit = 0x80 }; + CommaSeparated = 0x40, ForwardNotSplit = 0x80, + ZeroOrMore = 0x100 }; } /// OptionDescription - Represents data contained in a single @@ -260,6 +261,9 @@ struct OptionDescription { /// Merge - Merge two option descriptions. void Merge (const OptionDescription& other); + /// CheckConsistency - Check that the flags are consistent. + void CheckConsistency() const; + // Misc convenient getters/setters. bool isAlias() const; @@ -281,6 +285,9 @@ struct OptionDescription { bool isOneOrMore() const; void setOneOrMore(); + bool isZeroOrMore() const; + void setZeroOrMore(); + bool isOptional() const; void setOptional(); @@ -301,6 +308,20 @@ struct OptionDescription { }; +void OptionDescription::CheckConsistency() const { + unsigned i = 0; + + i += this->isRequired(); + i += this->isOptional(); + i += this->isOneOrMore(); + i += this->isZeroOrMore(); + + if (i > 1) { + throw "Only one of (required), (optional), (one_or_more) or " + "(zero_or_more) properties is allowed!"; + } +} + void OptionDescription::Merge (const OptionDescription& other) { if (other.Type != Type) @@ -359,6 +380,13 @@ void OptionDescription::setOneOrMore() { Flags |= OptionDescriptionFlags::OneOrMore; } +bool OptionDescription::isZeroOrMore() const { + return Flags & OptionDescriptionFlags::ZeroOrMore; +} +void OptionDescription::setZeroOrMore() { + Flags |= OptionDescriptionFlags::ZeroOrMore; +} + bool OptionDescription::isOptional() const { return Flags & OptionDescriptionFlags::Optional; } @@ -593,6 +621,7 @@ public: AddHandler("init", &CollectOptionProperties::onInit); AddHandler("multi_val", &CollectOptionProperties::onMultiVal); AddHandler("one_or_more", &CollectOptionProperties::onOneOrMore); + AddHandler("zero_or_more", &CollectOptionProperties::onZeroOrMore); AddHandler("really_hidden", &CollectOptionProperties::onReallyHidden); AddHandler("required", &CollectOptionProperties::onRequired); AddHandler("optional", &CollectOptionProperties::onOptional); @@ -651,10 +680,9 @@ private: void onRequired (const DagInit& d) { CheckNumberOfArguments(d, 0); - if (optDesc_.isOneOrMore() || optDesc_.isOptional()) - throw "Only one of (required), (optional) or " - "(one_or_more) properties is allowed!"; + optDesc_.setRequired(); + optDesc_.CheckConsistency(); } void onInit (const DagInit& d) { @@ -673,24 +701,31 @@ private: void onOneOrMore (const DagInit& d) { CheckNumberOfArguments(d, 0); - if (optDesc_.isRequired() || optDesc_.isOptional()) - throw "Only one of (required), (optional) or " - "(one_or_more) properties is allowed!"; - if (!OptionType::IsList(optDesc_.Type)) - llvm::errs() << "Warning: specifying the 'one_or_more' property " - "on a non-list option will have no effect.\n"; + optDesc_.setOneOrMore(); + optDesc_.CheckConsistency(); + } + + void onZeroOrMore (const DagInit& d) { + CheckNumberOfArguments(d, 0); + + if (OptionType::IsList(optDesc_.Type)) + llvm::errs() << "Warning: specifying the 'zero_or_more' property " + "on a list option has no effect.\n"; + + optDesc_.setZeroOrMore(); + optDesc_.CheckConsistency(); } void onOptional (const DagInit& d) { CheckNumberOfArguments(d, 0); - if (optDesc_.isRequired() || optDesc_.isOneOrMore()) - throw "Only one of (required), (optional) or " - "(one_or_more) properties is allowed!"; + if (!OptionType::IsList(optDesc_.Type)) llvm::errs() << "Warning: specifying the 'optional' property" - "on a non-list option will have no effect.\n"; + "on a non-list option has no effect.\n"; + optDesc_.setOptional(); + optDesc_.CheckConsistency(); } void onMultiVal (const DagInit& d) { @@ -2323,12 +2358,15 @@ void EmitOptionDefinitions (const OptionDescriptions& descs, else O << ", cl::Required"; } - else if (val.isOneOrMore() && val.isList()) { - O << ", cl::OneOrMore"; - } - else if (val.isOptional() && val.isList()) { + + if (val.isOptional()) O << ", cl::Optional"; - } + + if (val.isOneOrMore()) + O << ", cl::OneOrMore"; + + if (val.isZeroOrMore()) + O << ", cl::ZeroOrMore"; if (val.isReallyHidden()) O << ", cl::ReallyHidden"; |