84
84
opt_constant_if(nir_if *if_stmt, bool condition)
86
/* First, we need to remove any phi nodes after the if by rewriting uses to
87
* point to the correct source.
89
nir_block *after = nir_cf_node_as_block(nir_cf_node_next(&if_stmt->cf_node));
90
86
nir_block *last_block = condition ? nir_if_last_then_block(if_stmt)
91
87
: nir_if_last_else_block(if_stmt);
93
nir_foreach_instr_safe(instr, after) {
94
if (instr->type != nir_instr_type_phi)
97
nir_phi_instr *phi = nir_instr_as_phi(instr);
98
nir_ssa_def *def = NULL;
99
nir_foreach_phi_src(phi_src, phi) {
100
if (phi_src->pred != last_block)
103
assert(phi_src->src.is_ssa);
104
def = phi_src->src.ssa;
108
assert(phi->dest.is_ssa);
109
nir_ssa_def_rewrite_uses(&phi->dest.ssa, def);
110
nir_instr_remove(instr);
113
89
/* The control flow list we're about to paste in may include a jump at the
114
90
* end, and in that case we have to delete the rest of the control flow
115
91
* list after the if since it's unreachable and the validator will balk if
119
if (!exec_list_is_empty(&last_block->instr_list)) {
120
nir_instr *last_instr = nir_block_last_instr(last_block);
121
if (last_instr->type == nir_instr_type_jump)
122
remove_after_cf_node(&if_stmt->cf_node);
95
if (nir_block_ends_in_jump(last_block)) {
96
remove_after_cf_node(&if_stmt->cf_node);
98
/* Remove any phi nodes after the if by rewriting uses to point to the
101
nir_block *after = nir_cf_node_as_block(nir_cf_node_next(&if_stmt->cf_node));
102
nir_foreach_phi_safe(phi, after) {
103
nir_ssa_def *def = NULL;
104
nir_foreach_phi_src(phi_src, phi) {
105
if (phi_src->pred != last_block)
108
assert(phi_src->src.is_ssa);
109
def = phi_src->src.ssa;
113
assert(phi->dest.is_ssa);
114
nir_ssa_def_rewrite_uses(&phi->dest.ssa, def);
115
nir_instr_remove(&phi->instr);
125
119
/* Finally, actually paste in the then or else branch and delete the if. */
282
276
dead_cf_block(nir_block *block)
278
/* opt_constant_if() doesn't handle this case. */
279
if (nir_block_ends_in_jump(block) &&
280
!exec_node_is_tail_sentinel(block->cf_node.node.next)) {
281
remove_after_cf_node(&block->cf_node);
284
285
nir_if *following_if = nir_block_get_following_if(block);
285
286
if (following_if) {
286
287
if (nir_src_is_const(following_if->condition)) {
317
318
switch (cur->type) {
318
319
case nir_cf_node_block: {
319
320
nir_block *block = nir_cf_node_as_block(cur);
320
if (dead_cf_block(block)) {
321
/* We just deleted the if or loop after this block, so we may have
322
* deleted the block before or after it -- which one is an
323
* implementation detail. Therefore, to recover the place we were
324
* at, we have to use the previous cf_node.
321
while (dead_cf_block(block)) {
322
/* We just deleted the if or loop after this block.
323
* nir_cf_node_remove may have deleted the block before
324
* or after it -- which one is an implementation detail.
325
* Therefore, to recover the place we were at, we have
326
* to use the previous cf_node.
339
341
if (nir_block_ends_in_jump(block)) {
342
assert(exec_node_is_tail_sentinel(cur->node.next));
340
343
*list_ends_in_jump = true;
342
if (!exec_node_is_tail_sentinel(cur->node.next)) {
343
remove_after_cf_node(cur);
403
401
nir_metadata_preserve(impl, nir_metadata_none);
402
nir_rematerialize_derefs_in_use_blocks_impl(impl);
405
404
/* The CF manipulation code called by this pass is smart enough to keep
406
405
* from breaking any SSA use/def chains by replacing any uses of removed
425
424
bool progress = false;
427
nir_foreach_function(function, shader)
429
progress |= opt_dead_cf_impl(function->impl);
426
nir_foreach_function_impl(impl, shader)
427
progress |= opt_dead_cf_impl(impl);