static void add_cf_node(nir_cf_node *cf, struct set *invariants) { if (cf->type == nir_cf_node_if) { nir_if *if_stmt = nir_cf_node_as_if(cf); add_src(&if_stmt->condition, invariants); } if (cf->parent) add_cf_node(cf->parent, invariants); }
static bool dead_cf_list(struct exec_list *list, bool *list_ends_in_jump) { bool progress = false; *list_ends_in_jump = false; nir_cf_node *prev = NULL; foreach_list_typed(nir_cf_node, cur, node, list) { switch (cur->type) { case nir_cf_node_block: { nir_block *block = nir_cf_node_as_block(cur); if (dead_cf_block(block)) { /* We just deleted the if or loop after this block, so we may have * deleted the block before or after it -- which one is an * implementation detail. Therefore, to recover the place we were * at, we have to use the previous cf_node. */ if (prev) { cur = nir_cf_node_next(prev); } else { cur = exec_node_data(nir_cf_node, exec_list_get_head(list), node); } block = nir_cf_node_as_block(cur); progress = true; } if (ends_in_jump(block)) { *list_ends_in_jump = true; if (!exec_node_is_tail_sentinel(cur->node.next)) { remove_after_cf_node(cur); return true; } } break; } case nir_cf_node_if: { nir_if *if_stmt = nir_cf_node_as_if(cur); bool then_ends_in_jump, else_ends_in_jump; progress |= dead_cf_list(&if_stmt->then_list, &then_ends_in_jump); progress |= dead_cf_list(&if_stmt->else_list, &else_ends_in_jump); if (then_ends_in_jump && else_ends_in_jump) { *list_ends_in_jump = true; nir_block *next = nir_cf_node_as_block(nir_cf_node_next(cur)); if (!exec_list_is_empty(&next->instr_list) || !exec_node_is_tail_sentinel(next->cf_node.node.next)) { remove_after_cf_node(cur); return true; } } break; } case nir_cf_node_loop: { nir_loop *loop = nir_cf_node_as_loop(cur); bool dummy; progress |= dead_cf_list(&loop->body, &dummy); break; } default: unreachable("unknown cf node type"); } prev = cur; } return progress; }