[llvm] r294706 - [GlobalISel] Return an Expected<RuleMatcher> for each SDAG pattern. NFC.
Ahmed Bougacha via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 9 20:00:18 PST 2017
Author: ab
Date: Thu Feb 9 22:00:17 2017
New Revision: 294706
URL: http://llvm.org/viewvc/llvm-project?rev=294706&view=rev
Log:
[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
Modified:
llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
Modified: llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp?rev=294706&r1=294705&r2=294706&view=diff
==============================================================================
--- llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp (original)
+++ llvm/trunk/utils/TableGen/GlobalISelEmitter.cpp Thu Feb 9 22:00:17 2017
@@ -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> WarnOnSkippedPatter
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(Rec
//===- 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 Pa
// 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 Pa
// 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 Pa
// 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 Pa
// 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 Pa
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 Pa
++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
// 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 {
More information about the llvm-commits
mailing list