glsl: move loop analysis helpers to loop_analysis.cpp
authorTimothy Arceri <tarceri@itsqueeze.com>
Tue, 19 Sep 2017 02:14:11 +0000 (12:14 +1000)
committerTimothy Arceri <tarceri@itsqueeze.com>
Thu, 21 Sep 2017 01:56:13 +0000 (11:56 +1000)
Reviewed-by: Thomas Helland <thomashelland90@gmail.com>
src/compiler/glsl/loop_analysis.cpp
src/compiler/glsl/loop_analysis.h
src/compiler/glsl/loop_controls.cpp

index b9bae435368b02d2127148cc8c3e2ab5bb27f811..81a07f78f8f7532756a30de3e7986fb029d61040 100644 (file)
@@ -32,6 +32,145 @@ static bool all_expression_operands_are_loop_constant(ir_rvalue *,
 
 static ir_rvalue *get_basic_induction_increment(ir_assignment *, hash_table *);
 
+/**
+ * Find an initializer of a variable outside a loop
+ *
+ * Works backwards from the loop to find the pre-loop value of the variable.
+ * This is used, for example, to find the initial value of loop induction
+ * variables.
+ *
+ * \param loop  Loop where \c var is an induction variable
+ * \param var   Variable whose initializer is to be found
+ *
+ * \return
+ * The \c ir_rvalue assigned to the variable outside the loop.  May return
+ * \c NULL if no initializer can be found.
+ */
+static ir_rvalue *
+find_initial_value(ir_loop *loop, ir_variable *var)
+{
+   for (exec_node *node = loop->prev; !node->is_head_sentinel();
+        node = node->prev) {
+      ir_instruction *ir = (ir_instruction *) node;
+
+      switch (ir->ir_type) {
+      case ir_type_call:
+      case ir_type_loop:
+      case ir_type_loop_jump:
+      case ir_type_return:
+      case ir_type_if:
+         return NULL;
+
+      case ir_type_function:
+      case ir_type_function_signature:
+         assert(!"Should not get here.");
+         return NULL;
+
+      case ir_type_assignment: {
+         ir_assignment *assign = ir->as_assignment();
+         ir_variable *assignee = assign->lhs->whole_variable_referenced();
+
+         if (assignee == var)
+            return (assign->condition != NULL) ? NULL : assign->rhs;
+
+         break;
+      }
+
+      default:
+         break;
+      }
+   }
+
+   return NULL;
+}
+
+
+static int
+calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
+                     enum ir_expression_operation op)
+{
+   if (from == NULL || to == NULL || increment == NULL)
+      return -1;
+
+   void *mem_ctx = ralloc_context(NULL);
+
+   ir_expression *const sub =
+      new(mem_ctx) ir_expression(ir_binop_sub, from->type, to, from);
+
+   ir_expression *const div =
+      new(mem_ctx) ir_expression(ir_binop_div, sub->type, sub, increment);
+
+   ir_constant *iter = div->constant_expression_value(mem_ctx);
+   if (iter == NULL) {
+      ralloc_free(mem_ctx);
+      return -1;
+   }
+
+   if (!iter->type->is_integer()) {
+      const ir_expression_operation op = iter->type->is_double()
+         ? ir_unop_d2i : ir_unop_f2i;
+      ir_rvalue *cast =
+         new(mem_ctx) ir_expression(op, glsl_type::int_type, iter, NULL);
+
+      iter = cast->constant_expression_value(mem_ctx);
+   }
+
+   int iter_value = iter->get_int_component(0);
+
+   /* Make sure that the calculated number of iterations satisfies the exit
+    * condition.  This is needed to catch off-by-one errors and some types of
+    * ill-formed loops.  For example, we need to detect that the following
+    * loop does not have a maximum iteration count.
+    *
+    *    for (float x = 0.0; x != 0.9; x += 0.2)
+    *        ;
+    */
+   const int bias[] = { -1, 0, 1 };
+   bool valid_loop = false;
+
+   for (unsigned i = 0; i < ARRAY_SIZE(bias); i++) {
+      /* Increment may be of type int, uint or float. */
+      switch (increment->type->base_type) {
+      case GLSL_TYPE_INT:
+         iter = new(mem_ctx) ir_constant(iter_value + bias[i]);
+         break;
+      case GLSL_TYPE_UINT:
+         iter = new(mem_ctx) ir_constant(unsigned(iter_value + bias[i]));
+         break;
+      case GLSL_TYPE_FLOAT:
+         iter = new(mem_ctx) ir_constant(float(iter_value + bias[i]));
+         break;
+      case GLSL_TYPE_DOUBLE:
+         iter = new(mem_ctx) ir_constant(double(iter_value + bias[i]));
+         break;
+      default:
+          unreachable("Unsupported type for loop iterator.");
+      }
+
+      ir_expression *const mul =
+         new(mem_ctx) ir_expression(ir_binop_mul, increment->type, iter,
+                                    increment);
+
+      ir_expression *const add =
+         new(mem_ctx) ir_expression(ir_binop_add, mul->type, mul, from);
+
+      ir_expression *const cmp =
+         new(mem_ctx) ir_expression(op, glsl_type::bool_type, add, to);
+
+      ir_constant *const cmp_result = cmp->constant_expression_value(mem_ctx);
+
+      assert(cmp_result != NULL);
+      if (cmp_result->get_bool_component(0)) {
+         iter_value += bias[i];
+         valid_loop = true;
+         break;
+      }
+   }
+
+   ralloc_free(mem_ctx);
+   return (valid_loop) ? iter_value : -1;
+}
+
 
 /**
  * Record the fact that the given loop variable was referenced inside the loop.
index 2894c6359be8f77e7fa02853a1cf27646027275b..e2eff9dbaed6c1baaf6b2ef283abca55f0879c29 100644 (file)
@@ -55,13 +55,6 @@ extern bool
 unroll_loops(exec_list *instructions, loop_state *ls,
              const struct gl_shader_compiler_options *options);
 
-ir_rvalue *
-find_initial_value(ir_loop *loop, ir_variable *var);
-
-int
-calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
-                    enum ir_expression_operation op);
-
 
 /**
  * Tracking for all variables used in a loop
index 895954fc2d141c78908a3122f4d89ed7681b75c6..ad4aa18941143fab038835504c13ea8785128e07 100644 (file)
 #include "loop_analysis.h"
 #include "ir_hierarchical_visitor.h"
 
-/**
- * Find an initializer of a variable outside a loop
- *
- * Works backwards from the loop to find the pre-loop value of the variable.
- * This is used, for example, to find the initial value of loop induction
- * variables.
- *
- * \param loop  Loop where \c var is an induction variable
- * \param var   Variable whose initializer is to be found
- *
- * \return
- * The \c ir_rvalue assigned to the variable outside the loop.  May return
- * \c NULL if no initializer can be found.
- */
-ir_rvalue *
-find_initial_value(ir_loop *loop, ir_variable *var)
-{
-   for (exec_node *node = loop->prev;
-       !node->is_head_sentinel();
-       node = node->prev) {
-      ir_instruction *ir = (ir_instruction *) node;
-
-      switch (ir->ir_type) {
-      case ir_type_call:
-      case ir_type_loop:
-      case ir_type_loop_jump:
-      case ir_type_return:
-      case ir_type_if:
-        return NULL;
-
-      case ir_type_function:
-      case ir_type_function_signature:
-        assert(!"Should not get here.");
-        return NULL;
-
-      case ir_type_assignment: {
-        ir_assignment *assign = ir->as_assignment();
-        ir_variable *assignee = assign->lhs->whole_variable_referenced();
-
-        if (assignee == var)
-           return (assign->condition != NULL) ? NULL : assign->rhs;
-
-        break;
-      }
-
-      default:
-        break;
-      }
-   }
-
-   return NULL;
-}
-
-
-int
-calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
-                    enum ir_expression_operation op)
-{
-   if (from == NULL || to == NULL || increment == NULL)
-      return -1;
-
-   void *mem_ctx = ralloc_context(NULL);
-
-   ir_expression *const sub =
-      new(mem_ctx) ir_expression(ir_binop_sub, from->type, to, from);
-
-   ir_expression *const div =
-      new(mem_ctx) ir_expression(ir_binop_div, sub->type, sub, increment);
-
-   ir_constant *iter = div->constant_expression_value(mem_ctx);
-   if (iter == NULL) {
-      ralloc_free(mem_ctx);
-      return -1;
-   }
-
-   if (!iter->type->is_integer()) {
-      const ir_expression_operation op = iter->type->is_double()
-         ? ir_unop_d2i : ir_unop_f2i;
-      ir_rvalue *cast =
-         new(mem_ctx) ir_expression(op, glsl_type::int_type, iter, NULL);
-
-      iter = cast->constant_expression_value(mem_ctx);
-   }
-
-   int iter_value = iter->get_int_component(0);
-
-   /* Make sure that the calculated number of iterations satisfies the exit
-    * condition.  This is needed to catch off-by-one errors and some types of
-    * ill-formed loops.  For example, we need to detect that the following
-    * loop does not have a maximum iteration count.
-    *
-    *    for (float x = 0.0; x != 0.9; x += 0.2)
-    *        ;
-    */
-   const int bias[] = { -1, 0, 1 };
-   bool valid_loop = false;
-
-   for (unsigned i = 0; i < ARRAY_SIZE(bias); i++) {
-      /* Increment may be of type int, uint or float. */
-      switch (increment->type->base_type) {
-      case GLSL_TYPE_INT:
-         iter = new(mem_ctx) ir_constant(iter_value + bias[i]);
-         break;
-      case GLSL_TYPE_UINT:
-         iter = new(mem_ctx) ir_constant(unsigned(iter_value + bias[i]));
-         break;
-      case GLSL_TYPE_FLOAT:
-         iter = new(mem_ctx) ir_constant(float(iter_value + bias[i]));
-         break;
-      case GLSL_TYPE_DOUBLE:
-         iter = new(mem_ctx) ir_constant(double(iter_value + bias[i]));
-         break;
-      default:
-          unreachable("Unsupported type for loop iterator.");
-      }
-
-      ir_expression *const mul =
-        new(mem_ctx) ir_expression(ir_binop_mul, increment->type, iter,
-                                   increment);
-
-      ir_expression *const add =
-        new(mem_ctx) ir_expression(ir_binop_add, mul->type, mul, from);
-
-      ir_expression *const cmp =
-        new(mem_ctx) ir_expression(op, glsl_type::bool_type, add, to);
-
-      ir_constant *const cmp_result = cmp->constant_expression_value(mem_ctx);
-
-      assert(cmp_result != NULL);
-      if (cmp_result->get_bool_component(0)) {
-        iter_value += bias[i];
-        valid_loop = true;
-        break;
-      }
-   }
-
-   ralloc_free(mem_ctx);
-   return (valid_loop) ? iter_value : -1;
-}
 
 namespace {