From 8d8f80af3a17354508f2ec9d6559c915d5be351d Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 14 Jan 2019 11:36:23 -0800 Subject: [PATCH] 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: 8fb8ebfbb05 ("intel/compiler: More peephole select") Reviewed-by: Timothy Arceri --- src/compiler/nir/nir_opt_if.c | 52 ++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/src/compiler/nir/nir_opt_if.c b/src/compiler/nir/nir_opt_if.c index c2f945d4d59..c54d4a20f4c 100644 --- a/src/compiler/nir/nir_opt_if.c +++ b/src/compiler/nir/nir_opt_if.c @@ -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.