From: Ulya Trofimovich <skvadrik@gmail.com> Date: Sun, 2 Jul 2017 08:05:29 +0000 (+0100) Subject: Allow trivial cycles (of length 1) in tag commands. X-Git-Tag: 1.0~39^2~36 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7897755dc2943110698806239bf3ff9da232d94f;p=re2c Allow trivial cycles (of length 1) in tag commands. We forbid cycles of length 2 or more because they would need temporary variable local to the basic block, which would complicate liveness analysis. However, trivial cycles don't need a temporary. --- diff --git a/re2c/src/dfa/find_state.cc b/re2c/src/dfa/find_state.cc index aed43b9d..7f667fe7 100644 --- a/re2c/src/dfa/find_state.cc +++ b/re2c/src/dfa/find_state.cc @@ -183,10 +183,10 @@ bool kernels_t::operator()(const kernel_t *k1, const kernel_t *k2) *pacts = copy; // see note [topological ordering of copy commands] - const bool acyclic = tcmd_t::topsort(pacts, indeg); + const bool nontrivial_cycles = tcmd_t::topsort(pacts, indeg); // in case of cycles restore 'save' commands and fail - if (!acyclic) { + if (nontrivial_cycles) { pa = pacts; for (size_t i = 0; i < nact; ++i) { *pa = a = actnext[i]; @@ -196,7 +196,7 @@ bool kernels_t::operator()(const kernel_t *k1, const kernel_t *k2) *pa = NULL; } - return acyclic; + return !nontrivial_cycles; } kernels_t::kernels_t(Tagpool &tagp, tcpool_t &tcp, const std::vector<Tag> &ts) diff --git a/re2c/src/dfa/tcmd.cc b/re2c/src/dfa/tcmd.cc index 36079270..d7e142eb 100644 --- a/re2c/src/dfa/tcmd.cc +++ b/re2c/src/dfa/tcmd.cc @@ -32,8 +32,12 @@ bool tcmd_t::equal_history(const tagver_t *h, const tagver_t *g) * overwrites 'y' before its precious value is copied to 'x'). * * To avoid overwrites, commands should be topologically sorted. - * Cycles of length 2 are not allowed by construction; cycles of - * length 3 or more are left as is. + * The algorithm detects cycles and terminates; non-trivial cycles + * (induced by 2 or more nodes) are reported. We don't care about + * trivial cycles (loopbacks), because they can be implemented without + * temporary variable. Non-trivial cycles need a new temporary variable + * local to the given basic block, which makes liveness analysis more + * complex (so we simply forbid such mappings). * * For the purpose of topsort, we treat commands as arcs of directed * acyclic graph: command 'x = y' yields arc X -> Y. Topsort works @@ -72,7 +76,7 @@ bool tcmd_t::topsort(tcmd_t **phead, uint32_t *indeg) tcmd_t *x0 = *phead, **px, *x, *y0 = NULL, **py, **py1; - bool acyclic = true; + bool nontrivial_cycles = false; // initialize in-degree for (x = x0; x; x = x->next) { @@ -102,14 +106,16 @@ bool tcmd_t::topsort(tcmd_t **phead, uint32_t *indeg) // only cycles left if (py == py1) { - acyclic = false; + // look for cycles of length 2 or more + for (x = x0; x && x->lhs == x->rhs; x = x->next); + nontrivial_cycles = x != NULL; break; } } *py = x0; *phead = y0; - return acyclic; + return nontrivial_cycles; } tcpool_t::tcpool_t()