]> granicus.if.org Git - re2c/commitdiff
Fixed liveness analysis inside of basic block.
authorUlya Trofimovich <skvadrik@gmail.com>
Tue, 4 Apr 2017 12:41:41 +0000 (13:41 +0100)
committerUlya Trofimovich <skvadrik@gmail.com>
Tue, 4 Apr 2017 12:41:41 +0000 (13:41 +0100)
Liveness flows backwards through basic block, so it should be
propagated backwards starting with live-out set and applying
commands one by one in reverse order.

re2c/src/dfa/cfg/cfg.h
re2c/src/dfa/cfg/dce.cc
re2c/src/dfa/cfg/interfere.cc
re2c/src/dfa/cfg/liveanal.cc

index 1b9613ef178d8bffbdf56295a2d51522a2ad9216..7c314b99d576bb08fe9fe5dac0d41bc14daa8315 100644 (file)
@@ -31,6 +31,7 @@ struct cfg_t
        ~cfg_t();
        static tagver_t compact(const cfg_t &cfg, tagver_t *ver2new);
        static void liveness_analysis(const cfg_t &cfg, bool *live);
+       static void live_through_bblock(const tcmd_t *cmd, bool *live);
        static void dead_code_elimination(cfg_t &cfg, const bool *live);
        static void interference(const cfg_t &cfg, const bool *live, bool *interf);
        static tagver_t variable_allocation(const cfg_t &cfg, const bool *interf, tagver_t *ver2new);
index 73f4639e4b42cb2bae65e36141c19621eabec428..d4bc2cb89b9b00ffb05bb7a0a0691d9129341ab0 100644 (file)
@@ -9,6 +9,8 @@ void cfg_t::dead_code_elimination(cfg_t &cfg, const bool *live)
        // final and fallback tags can't be dead by construction
        cfg_bb_t *b = cfg.bblocks, *e = b + cfg.nbbarc;
 
+       // ignore possible local liveness inside of bblock:
+       // by construction we have no versions local to bblock
        for (; b < e; ++b, live += nver) {
                for (tcmd_t *p, **pp = &b->cmd; (p = *pp);) {
                        if (!live[p->lhs]) {
index fc4efbc15f6ffa97508207132f1adbb2b7ba20d4..a83961f16e23c7ceb790245addac378bb3a92d27 100644 (file)
@@ -28,25 +28,21 @@ void interfere(const tcmd_t *cmd, const bool *live, bool *interf,
 {
        // LHS of each command iterferes with all tags that are alive after
        // this command except its RHS and tags that are are assigned to
-       // the same RHS by subsequent commands.
+       // the same RHS by other commands in this block.
        memcpy(buf1, live, nver * sizeof(bool));
        for (const tcmd_t *p = cmd; p; p = p->next) {
                const tagver_t r = p->rhs;
 
-               // alive after this command: RHSs of subsequent commands
-               // and all tags alive after this basic block
+               // alive after this command
                memcpy(buf2, buf1, nver * sizeof(bool));
-               for (const tcmd_t *q = p->next; q; q = q->next) {
-                       const tagver_t v = q->rhs;
-                       if (v != r && tcmd_t::iscopy(v)) {
-                               buf2[v] = true;
-                       }
-               }
+               cfg_t::live_through_bblock(p->next, buf2);
 
-               // exclude: tags equal to RHS of this command
+               // exclude RHS
                if (tcmd_t::iscopy(r)) {
                        buf2[r] = false;
                }
+
+               // exclude tags assigned to the same RHS
                for (const tcmd_t *q = cmd; q; q = q->next) {
                        if (q->rhs == r) {
                                buf2[q->lhs] = false;
index c88f0ccc9f33c20f86688cb08ff627c7a6287a8d..efe65d9ef84a65e53f7a65ba0a280b47cd0b26b7 100644 (file)
@@ -23,6 +23,19 @@ static cfg_ix_t *postorder(const cfg_t &cfg, bool *done,
        return ++ord;
 }
 
+void cfg_t::live_through_bblock(const tcmd_t *cmd, bool *live)
+{
+       if (!cmd) return;
+
+       live_through_bblock(cmd->next, live);
+
+       const tagver_t l = cmd->lhs, r = cmd->rhs;
+       if (live[l] && tcmd_t::iscopy(r)) {
+               live[r] = true;
+       }
+       live[l] = false;
+}
+
 void cfg_t::liveness_analysis(const cfg_t &cfg, bool *live)
 {
        const std::vector<Tag> &tags = cfg.dfa.tags;
@@ -84,15 +97,7 @@ void cfg_t::liveness_analysis(const cfg_t &cfg, bool *live)
                                const tcmd_t *cmd = cfg.bblocks[*j].cmd;
                                memcpy(buf2, l, nver * sizeof(bool));
 
-                               // need two passes: same version may occur as both LHS and RHS
-                               for (const tcmd_t *p = cmd; p; p = p->next) {
-                                       buf2[p->lhs] = false;
-                               }
-                               for (const tcmd_t *p = cmd; p; p = p->next) {
-                                       if (l[p->lhs] && tcmd_t::iscopy(p->rhs)) {
-                                               buf2[p->rhs] = true;
-                                       }
-                               }
+                               cfg_t::live_through_bblock(cmd, buf2);
 
                                for (size_t v = 0; v < nver; ++v) {
                                        buf1[v] |= buf2[v];
@@ -131,12 +136,14 @@ void cfg_t::liveness_analysis(const cfg_t &cfg, bool *live)
                }
 
                // need two passes: same version may occur as both LHS and RHS
+               // not the same as backward propagation of liveness through bblock
                for (const tcmd_t *p = b->cmd; p; p = p->next) {
                        buf1[p->lhs] = false;
                }
                for (const tcmd_t *p = b->cmd; p; p = p->next) {
-                       if (tcmd_t::iscopy(p->rhs)) {
-                               buf1[p->rhs] = true;
+                       const tagver_t v = p->rhs;
+                       if (tcmd_t::iscopy(v)) {
+                               buf1[v] = true;
                        }
                }