diff options
author | Timothy Arceri <[email protected]> | 2017-09-21 13:55:56 +1000 |
---|---|---|
committer | Timothy Arceri <[email protected]> | 2017-10-10 10:05:37 +1100 |
commit | d24e16fe1f63d8f666dd57cfddf8340d439b391a (patch) | |
tree | 12f1fb8a784408c265252629832509782c72cb55 /src/compiler/glsl/loop_analysis.cpp | |
parent | ab23b759f241a4e2247efa28bd28a5f20149c70b (diff) |
glsl: check if induction var incremented before use in terminator
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 <[email protected]>
Reviewed-by: Elie Tournier <[email protected]>
Tested-by: Dieter Nützel <[email protected]>
Diffstat (limited to 'src/compiler/glsl/loop_analysis.cpp')
-rw-r--r-- | src/compiler/glsl/loop_analysis.cpp | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/src/compiler/glsl/loop_analysis.cpp b/src/compiler/glsl/loop_analysis.cpp index 81a07f78f8f..78279844dc8 100644 --- a/src/compiler/glsl/loop_analysis.cpp +++ b/src/compiler/glsl/loop_analysis.cpp @@ -171,6 +171,40 @@ calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment, 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. @@ -582,6 +616,10 @@ loop_analysis::visit_leave(ir_loop *ir) 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)) { |