[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