On 22/09/17 01:51, Michael Schellenberger Costa wrote:
Out of curriosity what about decrement and other shenanigans?

My commit message is a little misleading. The method in which the induction var changes doesn't matter, we just check if something was assigned to it (we trust the rest of the analysis code to do its job and make sure its a valid induction var). If there was an assignment before the terminator is checked we reduce the iteration count of the loop, again the way in which the induction variable is changed is irrelevant we simple reduce the number of passes over the loop by 1.

Hope this makes sense.

Tim


--Michael


Am 21.09.2017 um 12:55 schrieb Timothy Arceri:
do-while loops can increment the starting value before the
condition is checked. e.g.

   do {
     ndx++;
   } while (ndx < 3);

This commit changes the code to detect this and reduces the
iteration count by 1 if found.

V2: fix terminator spelling

Reviewed-by: Nicolai Hähnle <nicolai.haeh...@amd.com>
Reviewed-by: Elie Tournier <elie.tourn...@collabora.com>
---
  src/compiler/glsl/loop_analysis.cpp | 38 +++++++++++++++++++++++++++++++++++++
  1 file changed, 38 insertions(+)

diff --git a/src/compiler/glsl/loop_analysis.cpp b/src/compiler/glsl/loop_analysis.cpp
index 81a07f78f8..78279844dc 100644
--- a/src/compiler/glsl/loop_analysis.cpp
+++ b/src/compiler/glsl/loop_analysis.cpp
@@ -164,20 +164,54 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
           iter_value += bias[i];
           valid_loop = true;
           break;
        }
     }
     ralloc_free(mem_ctx);
     return (valid_loop) ? iter_value : -1;
  }
+static bool
+incremented_before_terminator(ir_loop *loop, ir_variable *var,
+                              ir_if *terminator)
+{
+   for (exec_node *node = loop->body_instructions.get_head();
+        !node->is_tail_sentinel();
+        node = node->get_next()) {
+      ir_instruction *ir = (ir_instruction *) node;
+
+      switch (ir->ir_type) {
+      case ir_type_if:
+         if (ir->as_if() == terminator)
+            return false;
+         break;
+
+      case ir_type_assignment: {
+         ir_assignment *assign = ir->as_assignment();
+         ir_variable *assignee = assign->lhs->whole_variable_referenced();
+
+         if (assignee == var) {
+            assert(assign->condition == NULL);
+            return true;
+         }
+
+         break;
+      }
+
+      default:
+         break;
+      }
+   }
+
+   unreachable("Unable to find induction variable");
+}
  /**
   * Record the fact that the given loop variable was referenced inside the loop.
   *
   * \arg in_assignee is true if the reference was on the LHS of an assignment.
   *
   * \arg in_conditional_code_or_nested_loop is true if the reference occurred
   * inside an if statement or a nested loop.
   *
   * \arg current_assignment is the ir_assignment node that the loop variable is
@@ -575,20 +609,24 @@ loop_analysis::visit_leave(ir_loop *ir)
       ir_variable *var = counter->variable_referenced();
       ir_rvalue *init = find_initial_value(ir, var);
           loop_variable *lv = ls->get(var);
           if (lv != NULL && lv->is_induction_var()) {
              t->iterations = calculate_iterations(init, limit, lv->increment,
                                                   cmp);
+            if (incremented_before_terminator(ir, var, t->ir)) {
+               t->iterations--;
+            }
+
              if (t->iterations >= 0 &&
                  (ls->limiting_terminator == NULL ||
                   t->iterations < ls->limiting_terminator->iterations)) {
                 ls->limiting_terminator = t;
              }
           }
           break;
        }
        default:

_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to