summaryrefslogtreecommitdiffstats
path: root/src/compiler/glsl
diff options
context:
space:
mode:
authorTimothy Arceri <[email protected]>2017-09-21 13:55:56 +1000
committerTimothy Arceri <[email protected]>2017-10-10 10:05:37 +1100
commitd24e16fe1f63d8f666dd57cfddf8340d439b391a (patch)
tree12f1fb8a784408c265252629832509782c72cb55 /src/compiler/glsl
parentab23b759f241a4e2247efa28bd28a5f20149c70b (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')
-rw-r--r--src/compiler/glsl/loop_analysis.cpp38
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)) {