summaryrefslogtreecommitdiffstats
path: root/src/compiler
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2019-01-14 11:36:23 -0800
committerIan Romanick <[email protected]>2019-02-08 10:37:06 -0800
commit8d8f80af3a17354508f2ec9d6559c915d5be351d (patch)
tree7c5a452bbf7e76e75c7a4ba2df4c900a08d5d0a3 /src/compiler
parent4d65d2b12ee261a3e37f197bcf5c4ac1807fc9d1 (diff)
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 <[email protected]>
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/nir/nir_opt_if.c52
1 files 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
@@ -49,6 +49,37 @@ find_continue_block(nir_loop *loop)
}
/**
+ * 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
* the loop and the other half of the if to the end of the loop. A simple for
@@ -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.