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;
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.
{
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],
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);
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;