diff options
| author | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2017-02-10 04:00:17 +0000 |
|---|---|---|
| committer | Ahmed Bougacha <ahmed.bougacha@gmail.com> | 2017-02-10 04:00:17 +0000 |
| commit | 982c5eb396a9a30b5dd17ac71fab9a9860317e85 (patch) | |
| tree | 9b95aede39eecc48d84576fdf4b7796594fed580 | |
| parent | fb9ae0e3fe98c7fb8e8c2f956c0907b437cb7c48 (diff) | |
| download | bcm5719-llvm-982c5eb396a9a30b5dd17ac71fab9a9860317e85.tar.gz bcm5719-llvm-982c5eb396a9a30b5dd17ac71fab9a9860317e85.zip | |
[GlobalISel] Return an Expected<RuleMatcher> for each SDAG pattern. NFC.
Instead of emitting the matcher code directly, return the rule matcher
and the skip reason as an Expected<RuleMatcher>.
This will let us record all matchers and process them before emission.
It's a somewhat unconventional use of Error, but it's nicer than, say,
std::pair, because of the bool conversions.
Differential Revision: https://reviews.llvm.org/D29743
llvm-svn: 294706
| -rw-r--r-- | llvm/utils/TableGen/GlobalISelEmitter.cpp | 118 |
1 files changed, 63 insertions, 55 deletions
diff --git a/llvm/utils/TableGen/GlobalISelEmitter.cpp b/llvm/utils/TableGen/GlobalISelEmitter.cpp index 9dac9e0e093..a31fba7f212 100644 --- a/llvm/utils/TableGen/GlobalISelEmitter.cpp +++ b/llvm/utils/TableGen/GlobalISelEmitter.cpp @@ -35,6 +35,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/CodeGen/MachineValueType.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Error.h" #include "llvm/TableGen/Error.h" #include "llvm/TableGen/Record.h" #include "llvm/TableGen/TableGenBackend.h" @@ -54,35 +55,7 @@ static cl::opt<bool> WarnOnSkippedPatterns( cl::init(false)); namespace { - -class GlobalISelEmitter { -public: - explicit GlobalISelEmitter(RecordKeeper &RK); - void run(raw_ostream &OS); - -private: - const RecordKeeper &RK; - const CodeGenDAGPatterns CGP; - const CodeGenTarget &Target; - - /// Keep track of the equivalence between SDNodes and Instruction. - /// This is defined using 'GINodeEquiv' in the target description. - DenseMap<Record *, const CodeGenInstruction *> NodeEquivs; - - void gatherNodeEquivs(); - const CodeGenInstruction *findNodeEquiv(Record *N); - - struct SkipReason { - std::string Reason; - }; - - /// Analyze pattern \p P, possibly emitting matching code for it to \p OS. - /// Otherwise, return a reason why this pattern was skipped for emission. - Optional<SkipReason> runOnPattern(const PatternToMatch &P, - raw_ostream &OS); -}; - -} // end anonymous namespace +class RuleMatcher; //===- Helper functions ---------------------------------------------------===// @@ -381,6 +354,28 @@ public: //===- GlobalISelEmitter class --------------------------------------------===// +class GlobalISelEmitter { +public: + explicit GlobalISelEmitter(RecordKeeper &RK); + void run(raw_ostream &OS); + +private: + const RecordKeeper &RK; + const CodeGenDAGPatterns CGP; + const CodeGenTarget &Target; + + /// Keep track of the equivalence between SDNodes and Instruction. + /// This is defined using 'GINodeEquiv' in the target description. + DenseMap<Record *, const CodeGenInstruction *> NodeEquivs; + + void gatherNodeEquivs(); + const CodeGenInstruction *findNodeEquiv(Record *N); + + /// Analyze pattern \p P, returning a matcher for it if possible. + /// Otherwise, return an Error explaining why we don't support it. + Expected<RuleMatcher> runOnPattern(const PatternToMatch &P); +}; + void GlobalISelEmitter::gatherNodeEquivs() { assert(NodeEquivs.empty()); for (Record *Equiv : RK.getAllDerivedDefinitions("GINodeEquiv")) @@ -397,9 +392,12 @@ GlobalISelEmitter::GlobalISelEmitter(RecordKeeper &RK) //===- Emitter ------------------------------------------------------------===// -Optional<GlobalISelEmitter::SkipReason> -GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) { +/// Helper function to let the emitter report skip reason error messages. +static Error failedImport(const Twine &Reason) { + return make_error<StringError>(Reason, inconvertibleErrorCode()); +} +Expected<RuleMatcher> GlobalISelEmitter::runOnPattern(const PatternToMatch &P) { // Keep track of the matchers and actions to emit. RuleMatcher M; M.addAction<DebugCommentAction>(P); @@ -407,11 +405,11 @@ GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) { // First, analyze the whole pattern. // If the entire pattern has a predicate (e.g., target features), ignore it. if (!P.getPredicates()->getValues().empty()) - return SkipReason{"Pattern has a predicate"}; + return failedImport("Pattern has a predicate"); // Physreg imp-defs require additional logic. Ignore the pattern. if (!P.getDstRegs().empty()) - return SkipReason{"Pattern defines a physical register"}; + return failedImport("Pattern defines a physical register"); // Next, analyze the pattern operators. TreePatternNode *Src = P.getSrcPattern(); @@ -419,19 +417,19 @@ GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) { // If the root of either pattern isn't a simple operator, ignore it. if (!isTrivialOperatorNode(Dst)) - return SkipReason{"Dst pattern root isn't a trivial operator"}; + return failedImport("Dst pattern root isn't a trivial operator"); if (!isTrivialOperatorNode(Src)) - return SkipReason{"Src pattern root isn't a trivial operator"}; + return failedImport("Src pattern root isn't a trivial operator"); Record *DstOp = Dst->getOperator(); if (!DstOp->isSubClassOf("Instruction")) - return SkipReason{"Pattern operator isn't an instruction"}; + return failedImport("Pattern operator isn't an instruction"); auto &DstI = Target.getInstruction(DstOp); auto SrcGIOrNull = findNodeEquiv(Src->getOperator()); if (!SrcGIOrNull) - return SkipReason{"Pattern operator lacks an equivalent Instruction"}; + return failedImport("Pattern operator lacks an equivalent Instruction"); auto &SrcGI = *SrcGIOrNull; // The operators look good: match the opcode and mutate it to the new one. @@ -442,22 +440,22 @@ GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) { // Next, analyze the children, only accepting patterns that don't require // any change to operands. if (Src->getNumChildren() != Dst->getNumChildren()) - return SkipReason{"Src/dst patterns have a different # of children"}; + return failedImport("Src/dst patterns have a different # of children"); unsigned OpIdx = 0; // Start with the defined operands (i.e., the results of the root operator). if (DstI.Operands.NumDefs != Src->getExtTypes().size()) - return SkipReason{"Src pattern results and dst MI defs are different"}; + return failedImport("Src pattern results and dst MI defs are different"); for (const EEVT::TypeSet &Ty : Src->getExtTypes()) { Record *DstIOpRec = DstI.Operands[OpIdx].Rec; if (!DstIOpRec->isSubClassOf("RegisterClass")) - return SkipReason{"Dst MI def isn't a register class"}; + return failedImport("Dst MI def isn't a register class"); auto OpTyOrNone = MVTToLLT(Ty.getConcrete()); if (!OpTyOrNone) - return SkipReason{"Dst operand has an unsupported type"}; + return failedImport("Dst operand has an unsupported type"); OperandMatcher &OM = InsnMatcher.addOperand(OpIdx); OM.addPredicate<LLTOperandMatcher>(*OpTyOrNone); @@ -473,14 +471,14 @@ GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) { // Patterns can reorder operands. Ignore those for now. if (SrcChild->getName() != DstChild->getName()) - return SkipReason{"Src/dst pattern children not in same order"}; + return failedImport("Src/dst pattern children not in same order"); // The only non-leaf child we accept is 'bb': it's an operator because // BasicBlockSDNode isn't inline, but in MI it's just another operand. if (!SrcChild->isLeaf()) { if (DstChild->isLeaf() || SrcChild->getOperator() != DstChild->getOperator()) - return SkipReason{"Src/dst pattern child operator mismatch"}; + return failedImport("Src/dst pattern child operator mismatch"); if (SrcChild->getOperator()->isSubClassOf("SDNode")) { auto &ChildSDNI = CGP.getSDNodeInfo(SrcChild->getOperator()); @@ -489,26 +487,26 @@ GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) { continue; } } - return SkipReason{"Src pattern child isn't a leaf node"}; + return failedImport("Src pattern child isn't a leaf node"); } if (SrcChild->getLeafValue() != DstChild->getLeafValue()) - return SkipReason{"Src/dst pattern child leaf mismatch"}; + return failedImport("Src/dst pattern child leaf mismatch"); // Otherwise, we're looking for a bog-standard RegisterClass operand. if (SrcChild->hasAnyPredicate()) - return SkipReason{"Src pattern child has predicate"}; + return failedImport("Src pattern child has predicate"); auto *ChildRec = cast<DefInit>(SrcChild->getLeafValue())->getDef(); if (!ChildRec->isSubClassOf("RegisterClass")) - return SkipReason{"Src pattern child isn't a RegisterClass"}; + return failedImport("Src pattern child isn't a RegisterClass"); ArrayRef<EEVT::TypeSet> ChildTypes = SrcChild->getExtTypes(); if (ChildTypes.size() != 1) - return SkipReason{"Src pattern child has multiple results"}; + return failedImport("Src pattern child has multiple results"); auto OpTyOrNone = MVTToLLT(ChildTypes.front().getConcrete()); if (!OpTyOrNone) - return SkipReason{"Src operand has an unsupported type"}; + return failedImport("Src operand has an unsupported type"); OperandMatcher &OM = InsnMatcher.addOperand(OpIdx); OM.addPredicate<LLTOperandMatcher>(*OpTyOrNone); @@ -517,10 +515,8 @@ GlobalISelEmitter::runOnPattern(const PatternToMatch &P, raw_ostream &OS) { ++OpIdx; } - // We're done with this pattern! Emit the processed result. - M.emit(OS); - ++NumPatternEmitted; - return None; + // We're done with this pattern! It's eligible for GISel emission; return it. + return std::move(M); } void GlobalISelEmitter::run(raw_ostream &OS) { @@ -537,18 +533,30 @@ void GlobalISelEmitter::run(raw_ostream &OS) { // Look through the SelectionDAG patterns we found, possibly emitting some. for (const PatternToMatch &Pat : CGP.ptms()) { ++NumPatternTotal; - if (auto SkipReason = runOnPattern(Pat, OS)) { + auto MatcherOrErr = runOnPattern(Pat); + + // The pattern analysis can fail, indicating an unsupported pattern. + // Report that if we've been asked to do so. + if (auto Err = MatcherOrErr.takeError()) { if (WarnOnSkippedPatterns) { PrintWarning(Pat.getSrcRecord()->getLoc(), - "Skipped pattern: " + SkipReason->Reason); + "Skipped pattern: " + toString(std::move(Err))); + } else { + consumeError(std::move(Err)); } ++NumPatternSkipped; + continue; } + + MatcherOrErr->emit(OS); + ++NumPatternEmitted; } OS << " return false;\n}\n"; } +} // end anonymous namespace + //===----------------------------------------------------------------------===// namespace llvm { |

