* needs to be predicated on the return flag variable.
*/
bool has_predicated_return;
+
+ bool removed_unreachable_code;
};
static bool lower_returns_in_cf_list(struct exec_list *cf_list,
nir_builder *b = &state->builder;
b->cursor = nir_after_cf_node_and_phis(node);
- if (nir_cursors_equal(b->cursor, nir_after_cf_list(state->cf_list)))
+ if (!state->loop && nir_cursors_equal(b->cursor, nir_after_cf_list(state->cf_list)))
return; /* Nothing to predicate */
assert(state->return_flag);
*/
return false;
} else {
+ state->removed_unreachable_code = true;
nir_cf_delete(&list);
- return true;
+ return false;
}
}
nir_instr_remove(&jump->instr);
+ /* If this is a return in the last block of the function there is nothing
+ * more to do once its removed.
+ */
+ if (block == nir_impl_last_block(state->builder.impl))
+ return true;
+
nir_builder *b = &state->builder;
/* Set the return flag */
/* Initialize the variable to 0 */
b->cursor = nir_before_cf_list(&b->impl->body);
- nir_store_var(b, state->return_flag, nir_imm_int(b, NIR_FALSE), 1);
+ nir_store_var(b, state->return_flag, nir_imm_false(b), 1);
}
b->cursor = nir_after_block(block);
- nir_store_var(b, state->return_flag, nir_imm_int(b, NIR_TRUE), 1);
+ nir_store_var(b, state->return_flag, nir_imm_true(b), 1);
if (state->loop) {
/* We're in a loop; we need to break out of it. */
state.loop = NULL;
state.return_flag = NULL;
state.has_predicated_return = false;
+ state.removed_unreachable_code = false;
nir_builder_init(&state.builder, impl);
bool progress = lower_returns_in_cf_list(&impl->body, &state);
+ progress = progress || state.removed_unreachable_code;
if (progress) {
nir_metadata_preserve(impl, nir_metadata_none);
nir_repair_ssa_impl(impl);
+ } else {
+#ifndef NDEBUG
+ impl->valid_metadata &= ~nir_metadata_not_properly_reset;
+#endif
}
return progress;