nir: Refactor code that checks phi nodes in opt_peel_loop_initial_if
authorIan Romanick <ian.d.romanick@intel.com>
Mon, 14 Jan 2019 19:36:23 +0000 (11:36 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Fri, 8 Feb 2019 18:37:06 +0000 (10:37 -0800)
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 <tarceri@itsqueeze.com>
src/compiler/nir/nir_opt_if.c

index c2f945d..c54d4a2 100644 (file)
@@ -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.