Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

glsl: Avoid excessive loop unrolling.

Avoid unrollong loops that are either nested loops or
where the loop body times the unroll count is huge.

The change is far from being perfect but it extends the
loop unrolling decision heuristic by some additional
safeguard. In particular this cuts down compilation of
a shader precomputing atmospheric scattering integral
tables containing two nesting levels in a loop from
something way beyond some minutes (I never waited for
it to finish) to some fractions of a second.

This fixes piglit tests glsl-fs-unroll-explosion and
glsl-vs-unroll-explosion on r600g.

Reviewed-by: Eric Anholt <>
Signed-off-by: Mathias Fröhlich <>
  • Loading branch information...
commit 67007080b716c7e51039a381f407ababd68230f7 1 parent ea228d9
Mathias Fröhlich authored
Showing with 15 additions and 0 deletions.
  1. +15 −0 src/glsl/loop_unroll.cpp
15 src/glsl/loop_unroll.cpp
@@ -56,6 +56,7 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
loop_variable_state *const ls = this->state->get(ir);
int iterations;
+ unsigned ir_count;
/* If we've entered a loop that hasn't been analyzed, something really,
* really bad has happened.
@@ -78,6 +79,20 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
if (iterations > (int) max_iterations)
return visit_continue;
+ /* Don't try to unroll nested loops and loops with a huge body.
+ */
+ ir_count = 0;
+ foreach_list(node, &ir->body_instructions) {
+ ++ir_count;
+ /* If the loop body gets to huge, do not unroll. */
+ if (5*max_iterations < ir_count*iterations)
+ return visit_continue;
+ /* Do not unroll loops with child loop nodes. */
+ if (((ir_instruction *) node)->as_loop())
+ return visit_continue;
+ }
if (ls->num_loop_jumps > 1)
return visit_continue;
else if (ls->num_loop_jumps) {
Please sign in to comment.
Something went wrong with that request. Please try again.