On 14.09.2017 06:47, Timothy Arceri wrote:
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.

With Eric's remark fixes, this patch is

Reviewed-by: Nicolai Hähnle <nicolai.haeh...@amd.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 b9bae43536..8a0425d185 100644
--- a/src/compiler/glsl/loop_analysis.cpp
+++ b/src/compiler/glsl/loop_analysis.cpp
@@ -25,20 +25,54 @@
  #include "loop_analysis.h"
  #include "ir_hierarchical_visitor.h"
static bool is_loop_terminator(ir_if *ir); static bool all_expression_operands_are_loop_constant(ir_rvalue *,
                                                      hash_table *);
static ir_rvalue *get_basic_induction_increment(ir_assignment *, hash_table *); +static bool
+incremented_before_termionator(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
@@ -436,20 +470,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_termionator(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:



--
Lerne, wie die Welt wirklich ist,
Aber vergiss niemals, wie sie sein sollte.
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to