[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