]> granicus.if.org Git - re2c/commitdiff
Allow trivial cycles (of length 1) in tag commands.
authorUlya Trofimovich <skvadrik@gmail.com>
Sun, 2 Jul 2017 08:05:29 +0000 (09:05 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Sun, 2 Jul 2017 08:05:29 +0000 (09:05 +0100)
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.

re2c/src/dfa/find_state.cc
re2c/src/dfa/tcmd.cc

index aed43b9d645322cdbe6187a7defc02f75af7b3b4..7f667fe7b3ef595ac0cd4fca5e1ed2482c419c2c 100644 (file)
@@ -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)
index 36079270c86c484200f71ee850597ec21b8cc50c..d7e142ebec547ab21a8668c364cd245eabf76105 100644 (file)
@@ -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()