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. --- 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: -- 2.13.5 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev