[Mesa-dev] [PATCH] glsl: Detect do-while-false loops and unroll them

Timothy Arceri timothy.arceri at collabora.com
Mon Feb 22 23:26:37 UTC 2016


On Mon, 2016-02-22 at 11:42 -0800, Ian Romanick wrote:
> From: Ian Romanick <ian.d.romanick at intel.com>
> 
> Previously loops like
> 
>    do {
>       // ...
>    } while (false);
> 
> that did not have any other loop-branch instructions would not be
> unrolled.  This is commonly used to wrap multiline preprocessor
> macros.
> 
> This produces IR like
> 
>     (loop (
>        ...
>        break
>     ))
> 
> Since limiting_terminator was NULL, the loop unroller would
> throw up its hands and say, "I don't know how many iterations.  How
> can I unroll this?"
> 
> We can detect this another way.  If there is no limiting_terminator
> and the only loop-branch is a break as the last IR, there's only one
> iteration.
> 
> On my very old checkout of shader-db,

I ran it on a recent version and this was still the only shader to hit
this.

>  this removes a loop from Orbital
> Explorer, but it does not otherwise affect the shader.  The loop
> removed
> is the one the compiler inserts surrounding the switch statement.
> 
> This change does prevent some seriously bad code generation in some
> patches to meta shaders that I recently sent out for review.
> 
> Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>

Reviewed-by: Timothy Arceri <timothy.arceri at collabora.com>

> ---
>  src/compiler/glsl/loop_unroll.cpp | 30 ++++++++++++++++++++++++++---
> -
>  1 file changed, 26 insertions(+), 4 deletions(-)
> 
> diff --git a/src/compiler/glsl/loop_unroll.cpp
> b/src/compiler/glsl/loop_unroll.cpp
> index aea2743c..bc377df 100644
> --- a/src/compiler/glsl/loop_unroll.cpp
> +++ b/src/compiler/glsl/loop_unroll.cpp
> @@ -315,11 +315,33 @@ loop_unroll_visitor::visit_leave(ir_loop *ir)
>        return visit_continue;
>     }
>  
> -   /* Don't try to unroll loops where the number of iterations is
> not known
> -    * at compile-time.
> -    */
> -   if (ls->limiting_terminator == NULL)
> +   if (ls->limiting_terminator == NULL) {
> +      ir_instruction *last_ir =
> +         (ir_instruction *) ir->body_instructions.get_tail();
> +
> +      /* If a loop has no induction variable and the last
> instruction is
> +       * a break, unroll the loop with a count of 1.  This is the
> classic
> +       *
> +       *    do {
> +       *        // ...
> +       *    } while (false)
> +       *
> +       * that is used to wrap multi-line macros.
> +       *
> +       * If num_loop_jumps is not zero, last_ir cannot be NULL...
> there has to
> +       * be at least num_loop_jumps instructions in the loop.
> +       */
> +      if (ls->num_loop_jumps == 1 && is_break(last_ir)) {
> +         last_ir->remove();
> +
> +         simple_unroll(ir, 1);
> +      }
> +
> +      /* Don't try to unroll loops where the number of iterations is
> not known
> +       * at compile-time.
> +       */
>        return visit_continue;
> +   }
>  
>     iterations = ls->limiting_terminator->iterations;
>  


More information about the mesa-dev mailing list