diff options
Diffstat (limited to 'src/broadcom')
-rw-r--r-- | src/broadcom/compiler/v3d_compiler.h | 2 | ||||
-rw-r--r-- | src/broadcom/compiler/vir_live_variables.c | 45 |
2 files changed, 43 insertions, 4 deletions
diff --git a/src/broadcom/compiler/v3d_compiler.h b/src/broadcom/compiler/v3d_compiler.h index 5984d3ef5fe..75dff07404e 100644 --- a/src/broadcom/compiler/v3d_compiler.h +++ b/src/broadcom/compiler/v3d_compiler.h @@ -419,6 +419,8 @@ struct qblock { /** @{ used by v3d_vir_live_variables.c */ BITSET_WORD *def; + BITSET_WORD *defin; + BITSET_WORD *defout; BITSET_WORD *use; BITSET_WORD *live_in; BITSET_WORD *live_out; diff --git a/src/broadcom/compiler/vir_live_variables.c b/src/broadcom/compiler/vir_live_variables.c index 2879e23b43c..cba4000fd1d 100644 --- a/src/broadcom/compiler/vir_live_variables.c +++ b/src/broadcom/compiler/vir_live_variables.c @@ -109,8 +109,11 @@ vir_setup_def(struct v3d_compile *c, struct qblock *block, int ip, c->temp_start[var] = MIN2(c->temp_start[var], ip); c->temp_end[var] = MAX2(c->temp_end[var], ip); - /* If we've already tracked this as a def, or already used it within - * the block, there's nothing to do. + /* Mark the block as having a (partial) def of the var. */ + BITSET_SET(block->defout, var); + + /* If we've already tracked this as a def that screens off previous + * uses, or already used it within the block, there's nothing to do. */ if (BITSET_TEST(block->use, var) || BITSET_TEST(block->def, var)) return; @@ -278,6 +281,33 @@ vir_live_variables_dataflow(struct v3d_compile *c, int bitset_words) return cont; } +static bool +vir_live_variables_defin_defout_dataflow(struct v3d_compile *c, int bitset_words) +{ + bool cont = false; + + vir_for_each_block_rev(block, c) { + /* Propagate defin/defout down the successors to produce the + * union of blocks with a reachable (partial) definition of + * the var. + * + * This keeps a conditional first write to a reg from + * extending its lifetime back to the start of the program. + */ + vir_for_each_successor(succ, block) { + for (int i = 0; i < bitset_words; i++) { + BITSET_WORD new_def = (block->defout[i] & + ~succ->defin[i]); + succ->defin[i] |= new_def; + succ->defout[i] |= new_def; + cont |= new_def; + } + } + } + + return cont; +} + /** * Extend the start/end ranges for each variable to account for the * new information calculated from control flow. @@ -287,14 +317,16 @@ vir_compute_start_end(struct v3d_compile *c, int num_vars) { vir_for_each_block(block, c) { for (int i = 0; i < num_vars; i++) { - if (BITSET_TEST(block->live_in, i)) { + if (BITSET_TEST(block->live_in, i) && + BITSET_TEST(block->defin, i)) { c->temp_start[i] = MIN2(c->temp_start[i], block->start_ip); c->temp_end[i] = MAX2(c->temp_end[i], block->start_ip); } - if (BITSET_TEST(block->live_out, i)) { + if (BITSET_TEST(block->live_out, i) && + BITSET_TEST(block->defout, i)) { c->temp_start[i] = MIN2(c->temp_start[i], block->end_ip); c->temp_end[i] = MAX2(c->temp_end[i], @@ -334,6 +366,8 @@ vir_calculate_live_intervals(struct v3d_compile *c) vir_for_each_block(block, c) { block->def = rzalloc_array(c, BITSET_WORD, bitset_words); + block->defin = rzalloc_array(c, BITSET_WORD, bitset_words); + block->defout = rzalloc_array(c, BITSET_WORD, bitset_words); block->use = rzalloc_array(c, BITSET_WORD, bitset_words); block->live_in = rzalloc_array(c, BITSET_WORD, bitset_words); block->live_out = rzalloc_array(c, BITSET_WORD, bitset_words); @@ -344,6 +378,9 @@ vir_calculate_live_intervals(struct v3d_compile *c) while (vir_live_variables_dataflow(c, bitset_words)) ; + while (vir_live_variables_defin_defout_dataflow(c, bitset_words)) + ; + vir_compute_start_end(c, c->num_temps); c->live_intervals_valid = true; |