nir: Refactor code that checks phi nodes in opt_peel_loop_initial_if

This will be used in a couple more places soon.

The function name is... horribly long.  Neither Matt nor I could think
of any thing that was shorter and still more descriptive than
"is_phi_foo".  I'm willing to entertain suggestions.

Fixes: 8fb8ebfbb0 ("intel/compiler: More peephole select")
Reviewed-by: Timothy Arceri <tarceri@itsqueeze.com>
This commit is contained in:
Ian Romanick 2019-01-14 11:36:23 -08:00
parent 4d65d2b12e
commit 8d8f80af3a
1 changed files with 36 additions and 16 deletions

View File

@ -48,6 +48,37 @@ find_continue_block(nir_loop *loop)
unreachable("Continue block not found!");
}
/**
* Does a phi have one constant value from outside a loop and one from inside?
*/
static bool
phi_has_constant_from_outside_and_one_from_inside_loop(nir_phi_instr *phi,
const nir_block *continue_block,
uint32_t *entry_val,
uint32_t *continue_val)
{
/* We already know we have exactly one continue */
assert(exec_list_length(&phi->srcs) == 2);
*entry_val = 0;
*continue_val = 0;
nir_foreach_phi_src(src, phi) {
assert(src->src.is_ssa);
nir_const_value *const_src = nir_src_as_const_value(src->src);
if (!const_src)
return false;
if (src->pred == continue_block) {
*continue_val = const_src->u32[0];
} else {
*entry_val = const_src->u32[0];
}
}
return true;
}
/**
* This optimization detects if statements at the tops of loops where the
* condition is a phi node of two constants and moves half of the if to above
@ -136,23 +167,12 @@ opt_peel_loop_initial_if(nir_loop *loop)
if (cond->parent_instr->block != header_block)
return false;
/* We already know we have exactly one continue */
assert(exec_list_length(&cond_phi->srcs) == 2);
uint32_t entry_val = 0, continue_val = 0;
nir_foreach_phi_src(src, cond_phi) {
assert(src->src.is_ssa);
nir_const_value *const_src = nir_src_as_const_value(src->src);
if (!const_src)
return false;
if (src->pred == continue_block) {
continue_val = const_src->u32[0];
} else {
assert(src->pred == prev_block);
entry_val = const_src->u32[0];
}
}
if (!phi_has_constant_from_outside_and_one_from_inside_loop(cond_phi,
continue_block,
&entry_val,
&continue_val))
return false;
/* If they both execute or both don't execute, this is a job for
* nir_dead_cf, not this pass.