summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/loop_unroll.cpp13
1 files changed, 12 insertions, 1 deletions
diff --git a/src/glsl/loop_unroll.cpp b/src/glsl/loop_unroll.cpp
index ce795f6cd24..635e1dd99cd 100644
--- a/src/glsl/loop_unroll.cpp
+++ b/src/glsl/loop_unroll.cpp
@@ -64,6 +64,7 @@ class loop_unroll_count : public ir_hierarchical_visitor {
public:
int nodes;
bool unsupported_variable_indexing;
+ bool array_indexed_by_induction_var_with_exact_iterations;
/* If there are nested loops, the node count will be inaccurate. */
bool nested_loop;
@@ -74,6 +75,7 @@ public:
nodes = 0;
nested_loop = false;
unsupported_variable_indexing = false;
+ array_indexed_by_induction_var_with_exact_iterations = false;
run(list);
}
@@ -112,6 +114,14 @@ public:
ir_variable *array = ir->array->variable_referenced();
loop_variable *lv = ls->get(ir->array_index->variable_referenced());
if (array && lv && lv->is_induction_var()) {
+ /* If an array is indexed by a loop induction variable, and the
+ * array size is exactly the number of loop iterations, this is
+ * probably a simple for-loop trying to access each element in
+ * turn; the application may expect it to be unrolled.
+ */
+ if (int(array->type->length) == ls->limiting_terminator->iterations)
+ array_indexed_by_induction_var_with_exact_iterations = true;
+
switch (array->data.mode) {
case ir_var_auto:
case ir_var_temporary:
@@ -314,7 +324,8 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
bool loop_too_large =
count.nested_loop || count.nodes * iterations > max_iterations * 5;
- if (loop_too_large && !count.unsupported_variable_indexing)
+ if (loop_too_large && !count.unsupported_variable_indexing &&
+ !count.array_indexed_by_induction_var_with_exact_iterations)
return visit_continue;
/* Note: the limiting terminator contributes 1 to ls->num_loop_jumps.