[Mesa-dev] [PATCH] glsl: Make copy propagation not panic when it sees an intrinsic.

Matt Turner mattst88 at gmail.com
Sat Dec 10 20:37:16 UTC 2016


On Fri, Dec 9, 2016 at 8:28 PM, Kenneth Graunke <kenneth at whitecape.org> wrote:
> A number of games have large arrays of constants, which we promote to
> uniforms.  This introduces copies from the uniform array to the original
> temporary array.  Normally, copy propagation eliminates those copies,
> making everything refer to the uniform array directly.
>
> A number of shaders in "Deus Ex: Mankind Divided" recently exposed a
> limitation of copy propagation - if we had any intrinsics (i.e. image
> access in a compute shader), we weren't able to get rid of these copies.
>
> That meant that any variable indexing remained on the temporary array
> rather being moved to the uniform array.  i965's scalar backend
> currently doesn't support indirect addressing of temporary arrays,
> which meant lowering it to if-ladders.  This was horrible.
>
> On Skylake:
>
> total instructions in shared programs: 13700090 -> 13654519 (-0.33%)
> instructions in affected programs: 56438 -> 10867 (-80.75%)

Wow!

> helped: 14
> HURT: 0
>
> total cycles in shared programs: 288879704 -> 291270232 (0.83%)
> cycles in affected programs: 12758080 -> 15148608 (18.74%)

... that seems nuts?

Any idea what's going on with the cycle counts?

> helped: 6
> HURT: 8
>
> All shaders helped are compute shaders in Tomb Raider or Deus Ex.
>
> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
>  src/compiler/glsl/opt_copy_propagation.cpp | 31 ++++++++++++++++++++++++++----
>  1 file changed, 27 insertions(+), 4 deletions(-)
>
> diff --git a/src/compiler/glsl/opt_copy_propagation.cpp b/src/compiler/glsl/opt_copy_propagation.cpp
> index 247c498..2240421 100644
> --- a/src/compiler/glsl/opt_copy_propagation.cpp
> +++ b/src/compiler/glsl/opt_copy_propagation.cpp
> @@ -186,11 +186,34 @@ ir_copy_propagation_visitor::visit_enter(ir_call *ir)
>        }
>     }
>
> -   /* Since we're unlinked, we don't (necessarily) know the side effects of
> -    * this call.  So kill all copies.
> +   /* Since this pass can run when unlinked, we don't (necessarily) know
> +    * the side effects of calls.  (When linked, most calls are inlined
> +    * anyway, so it doesn't matter much.)
> +    *
> +    * One place where this does matter is IR intrinsics.  They're never
> +    * inlined.  We also know what they do - while some have side effects
> +    * (such as image writes), none edit random global variables.  So we
> +    * can assume they're side-effect free (other than the return value
> +    * and out parameters).
>      */
> -   _mesa_hash_table_clear(acp, NULL);
> -   this->killed_all = true;
> +   if (!ir->callee->is_intrinsic()) {
> +      _mesa_hash_table_clear(acp, NULL);
> +      this->killed_all = true;
> +   } else {
> +      if (ir->return_deref)
> +         kill(ir->return_deref->var);
> +
> +      foreach_two_lists(formal_node, &ir->callee->parameters,
> +                        actual_node, &ir->actual_parameters) {
> +         ir_variable *sig_param = (ir_variable *) formal_node;
> +         if (sig_param->data.mode == ir_var_function_out ||
> +             sig_param->data.mode == ir_var_function_inout) {
> +            ir_rvalue *ir = (ir_rvalue *) actual_node;
> +            ir_variable *var = ir->variable_referenced();
> +            kill(var);
> +         }
> +      }
> +   }

Looks correct to me.


More information about the mesa-dev mailing list