From: Ulya Trofimovich Date: Tue, 4 Apr 2017 12:41:41 +0000 (+0100) Subject: Fixed liveness analysis inside of basic block. X-Git-Tag: 1.0~39^2~86 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=55853fdc015c2c65a397165c7ef791662f6a063c;p=re2c Fixed liveness analysis inside of basic block. 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. --- diff --git a/re2c/src/dfa/cfg/cfg.h b/re2c/src/dfa/cfg/cfg.h index 1b9613ef..7c314b99 100644 --- a/re2c/src/dfa/cfg/cfg.h +++ b/re2c/src/dfa/cfg/cfg.h @@ -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); diff --git a/re2c/src/dfa/cfg/dce.cc b/re2c/src/dfa/cfg/dce.cc index 73f4639e..d4bc2cb8 100644 --- a/re2c/src/dfa/cfg/dce.cc +++ b/re2c/src/dfa/cfg/dce.cc @@ -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]) { diff --git a/re2c/src/dfa/cfg/interfere.cc b/re2c/src/dfa/cfg/interfere.cc index fc4efbc1..a83961f1 100644 --- a/re2c/src/dfa/cfg/interfere.cc +++ b/re2c/src/dfa/cfg/interfere.cc @@ -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; diff --git a/re2c/src/dfa/cfg/liveanal.cc b/re2c/src/dfa/cfg/liveanal.cc index c88f0ccc..efe65d9e 100644 --- a/re2c/src/dfa/cfg/liveanal.cc +++ b/re2c/src/dfa/cfg/liveanal.cc @@ -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 &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; } }