|
|
@@ -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; |