[llvm] 10b4aec - Revert "Avoid creating an immutable map in the Automaton class."

Dmitri Gribenko via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 17 01:23:08 PST 2020


Author: Dmitri Gribenko
Date: 2020-01-17T10:20:36+01:00
New Revision: 10b4aece528936bb7f75a9758ae95c61b6434d2f

URL: https://github.com/llvm/llvm-project/commit/10b4aece528936bb7f75a9758ae95c61b6434d2f
DIFF: https://github.com/llvm/llvm-project/commit/10b4aece528936bb7f75a9758ae95c61b6434d2f.diff

LOG: Revert "Avoid creating an immutable map in the Automaton class."

This reverts commit 051d330314cb1f175025ca37da8e5e1d851e1790. It broke
buildbots, for example,
http://lab.llvm.org:8011/builders/clang-x86_64-debian-fast/builds/21908.

Added: 
    

Modified: 
    llvm/include/llvm/Support/Automaton.h
    llvm/utils/TableGen/DFAEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/Automaton.h b/llvm/include/llvm/Support/Automaton.h
index e945d74f936f..c2b921311a8c 100644
--- a/llvm/include/llvm/Support/Automaton.h
+++ b/llvm/include/llvm/Support/Automaton.h
@@ -154,42 +154,29 @@ class NfaTranscriber {
 };
 } // namespace internal
 
-// Type representing a transition in the DFA state.
-// The action type can be a custom type.
-template <typename ActionT> struct TransitionType {
-  using StateT = unsigned;
-  StateT FromDfaState; // The transitioned-from DFA state.
-  ActionT Action;      // The input symbol that causes this transition.
-  StateT ToDfaState;   // The transitioned-to DFA state.
-  unsigned InfoIdx;    // Start index into TransitionInfo.
-};
-
 /// A deterministic finite-state automaton. The automaton is defined in
 /// TableGen; this object drives an automaton defined by tblgen-emitted tables.
 ///
 /// An automaton accepts a sequence of input tokens ("actions"). This class is
 /// templated on the type of these actions.
 template <typename ActionT> class Automaton {
-  using TransitionT = TransitionType<ActionT>;
-  using TransitionKeyT = std::pair<decltype(TransitionT::FromDfaState),
-                                   decltype(TransitionT::Action)>;
-  using StateT = typename TransitionT::StateT;
   /// Map from {State, Action} to {NewState, TransitionInfoIdx}.
   /// TransitionInfoIdx is used by the DfaTranscriber to analyze the transition.
-  ArrayRef<TransitionT> TransitionMap;
+  /// FIXME: This uses a std::map because ActionT can be a pair type including
+  /// an enum. In particular DenseMapInfo<ActionT> must be defined to use
+  /// DenseMap here.
+  /// This is a shared_ptr to allow very quick copy-construction of Automata; this
+  /// state is immutable after construction so this is safe.
+  using MapTy = std::map<std::pair<uint64_t, ActionT>, std::pair<uint64_t, unsigned>>;
+  std::shared_ptr<MapTy> M;
   /// An optional transcription object. This uses much more state than simply
   /// traversing the DFA for acceptance, so is heap allocated.
   std::shared_ptr<internal::NfaTranscriber> Transcriber;
   /// The initial DFA state is 1.
-  StateT State = 1;
+  uint64_t State = 1;
   /// True if we should transcribe and false if not (even if Transcriber is defined).
   bool Transcribe;
 
-  static bool transitionLessThan(const TransitionT &A,
-                                 const TransitionKeyT &B) {
-    return std::make_pair(A.FromDfaState, A.Action) < B;
-  }
-
 public:
   /// Create an automaton.
   /// \param Transitions The Transitions table as created by TableGen. Note that
@@ -202,24 +189,21 @@ template <typename ActionT> class Automaton {
   /// NFA taken by the DFA. NOTE: This is substantially more work than simply
   /// driving the DFA, so unless you require the getPaths() method leave this
   /// empty.
-  Automaton(ArrayRef<TransitionT> Transitions,
+  template <typename InfoT>
+  Automaton(ArrayRef<InfoT> Transitions,
             ArrayRef<NfaStatePair> TranscriptionTable = {}) {
     if (!TranscriptionTable.empty())
       Transcriber =
           std::make_shared<internal::NfaTranscriber>(TranscriptionTable);
     Transcribe = Transcriber != nullptr;
-    TransitionMap = Transitions;
-    assert(std::is_sorted(TransitionMap.begin(), TransitionMap.end(),
-                          [](const TransitionT &A, const TransitionT &B) {
-                            return std::make_pair(A.FromDfaState, A.Action) <
-                                   std::make_pair(B.FromDfaState, B.Action);
-                          }) &&
-           "The transitions array is expected to be sorted by FromDfaState and "
-           "Action");
+    M = std::make_shared<MapTy>();
+    for (const auto &I : Transitions)
+      // Greedily read and cache the transition table.
+      M->emplace(std::make_pair(I.FromDfaState, I.Action),
+                 std::make_pair(I.ToDfaState, I.InfoIdx));
   }
   Automaton(const Automaton &Other)
-      : TransitionMap(Other.TransitionMap), State(Other.State),
-        Transcribe(Other.Transcribe) {
+      : M(Other.M), State(Other.State), Transcribe(Other.Transcribe) {
     // Transcriber is not thread-safe, so create a new instance on copy.
     if (Other.Transcriber)
       Transcriber = std::make_shared<internal::NfaTranscriber>(
@@ -249,22 +233,19 @@ template <typename ActionT> class Automaton {
   /// If this function returns false, all methods are undefined until reset() is
   /// called.
   bool add(const ActionT &A) {
-    auto I = lower_bound(TransitionMap.begin(), TransitionMap.end(),
-                         std::make_pair(State, A), transitionLessThan);
-    if (I == TransitionMap.end() || State != I->FromDfaState || A != I->Action)
+    auto I = M->find({State, A});
+    if (I == M->end())
       return false;
     if (Transcriber && Transcribe)
-      Transcriber->transition(I->InfoIdx);
-    State = I->ToDfaState;
+      Transcriber->transition(I->second.second);
+    State = I->second.first;
     return true;
   }
 
   /// Return true if the automaton can be transitioned based on input symbol A.
   bool canAdd(const ActionT &A) {
-    auto I = lower_bound(TransitionMap.begin(), TransitionMap.end(),
-                         std::make_pair(State, A), transitionLessThan);
-    return I != TransitionMap.end() && State == I->FromDfaState &&
-           A == I->Action;
+    auto I = M->find({State, A});
+    return I != M->end();
   }
 
   /// Obtain a set of possible paths through the input nondeterministic

diff  --git a/llvm/utils/TableGen/DFAEmitter.cpp b/llvm/utils/TableGen/DFAEmitter.cpp
index af05551c7c32..dd3db7c150ba 100644
--- a/llvm/utils/TableGen/DFAEmitter.cpp
+++ b/llvm/utils/TableGen/DFAEmitter.cpp
@@ -131,9 +131,15 @@ void DfaEmitter::emit(StringRef Name, raw_ostream &OS) {
   OS << "}};\n\n";
 
   OS << "// A transition in the generated " << Name << " DFA.\n";
-  OS << "using " << Name << "Transition = TransitionType<";
+  OS << "struct " << Name << "Transition {\n";
+  OS << "  unsigned FromDfaState; // The transitioned-from DFA state.\n";
+  OS << "  ";
   printActionType(OS);
-  OS << ">;\n\n";
+  OS << " Action;       // The input symbol that causes this transition.\n";
+  OS << "  unsigned ToDfaState;   // The transitioned-to DFA state.\n";
+  OS << "  unsigned InfoIdx;      // Start index into " << Name
+     << "TransitionInfo.\n";
+  OS << "};\n\n";
 
   OS << "// A table of DFA transitions, ordered by {FromDfaState, Action}.\n";
   OS << "// The initial state is 1, not zero.\n";


        


More information about the llvm-commits mailing list