[Mesa-dev] [PATCH 3/5] glsl: Extend the array splitting optimization pass to matrices.

Kenneth Graunke kenneth at whitecape.org
Wed Apr 11 17:04:29 PDT 2012


On 03/26/2012 01:59 PM, Eric Anholt wrote:
> This should fit in well with our lower_mat_op_to_vec code: now, in
> addition to having expressions on each column of a matrix, we also
> split the columns to separate variables so they can be tracked
> individually by the copy propagation, dead code, and other passes.
>
> This optimizes out some more code generation in unigine and gstreamer
> shaders.
>
> Total instructions: 269342 ->  269270
> 14/2148 programs affected (0.7%)
> 2226 ->  2154 instructions in affected programs (3.2% reduction)
> ---
>   src/glsl/opt_array_splitting.cpp |   29 ++++++++++++++++++-----------
>   1 files changed, 18 insertions(+), 11 deletions(-)
>
> diff --git a/src/glsl/opt_array_splitting.cpp b/src/glsl/opt_array_splitting.cpp
> index 1e278c1..f11b516 100644
> --- a/src/glsl/opt_array_splitting.cpp
> +++ b/src/glsl/opt_array_splitting.cpp
> @@ -53,9 +53,14 @@ public:
>         this->declaration = false;
>         this->components = NULL;
>         this->mem_ctx = NULL;
> +      if (var->type->is_array())
> +	 this->size = var->type->length;
> +      else
> +	 this->size = var->type->matrix_columns;
>      }
>
>      ir_variable *var; /* The key: the variable's pointer. */
> +   unsigned size; /* array length or matrix columns */
>
>      /** Number of times the variable is referenced, including assignments. */
>      unsigned whole_array_access;
> @@ -112,13 +117,13 @@ ir_array_reference_visitor::get_variable_entry(ir_variable *var)
>          var->mode != ir_var_temporary)
>         return NULL;
>
> -   if (!var->type->is_array())
> +   if (!(var->type->is_array() || var->type->is_matrix()))
>         return NULL;
>
>      /* If the array hasn't been sized yet, we can't split it.  After
>       * linking, this should be resolved.
>       */
> -   if (var->type->length == 0)
> +   if (var->type->is_array()&&  var->type->length == 0)
>         return NULL;
>
>      foreach_iter(exec_list_iterator, iter, this->variable_list) {
> @@ -239,9 +244,6 @@ ir_array_splitting_visitor::get_splitting_entry(ir_variable *var)
>   {
>      assert(var);
>
> -   if (!var->type->is_array())
> -      return NULL;
> -
>      foreach_iter(exec_list_iterator, iter, *this->variable_list) {
>         variable_entry *entry = (variable_entry *)iter.get();
>         if (entry->var == var) {
> @@ -271,7 +273,7 @@ ir_array_splitting_visitor::split_deref(ir_dereference **deref)
>      ir_constant *constant = deref_array->array_index->as_constant();
>      assert(constant);
>
> -   if (constant->value.i[0]<  (int)var->type->length) {
> +   if (constant->value.i[0]<  (int)entry->size) {
>         *deref = new(entry->mem_ctx)
>   	 ir_dereference_variable(entry->components[constant->value.i[0]]);
>      } else {
> @@ -343,21 +345,26 @@ optimize_split_arrays(exec_list *instructions, bool linked)
>      foreach_iter(exec_list_iterator, iter, refs.variable_list) {
>         variable_entry *entry = (variable_entry *)iter.get();
>         const struct glsl_type *type = entry->var->type;
> +      const struct glsl_type *subtype;
> +
> +      if (type->is_matrix())
> +	 subtype = glsl_type::get_instance(GLSL_TYPE_FLOAT,
> +					   type->vector_elements, 1);
> +      else
> +	 subtype = type->fields.array;

If you want, you could just do:
       subtype = type->is_array() ? type->fields.array : 
type->column_type();

>
>         entry->mem_ctx = ralloc_parent(entry->var);
>
>         entry->components = ralloc_array(mem_ctx,
>   				       ir_variable *,
> -				       type->length);
> +				       entry->size);
>
> -      for (unsigned int i = 0; i<  type->length; i++) {
> +      for (unsigned int i = 0; i<  entry->size; i++) {
>   	 const char *name = ralloc_asprintf(mem_ctx, "%s_%d",
>   					    entry->var->name, i);
>
>   	 entry->components[i] =
> -	    new(entry->mem_ctx) ir_variable(type->fields.array,
> -					    name,
> -					    ir_var_temporary);
> +	    new(entry->mem_ctx) ir_variable(subtype, name, ir_var_temporary);
>   	 entry->var->insert_before(entry->components[i]);
>         }
>

Looks great!
Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>


More information about the mesa-dev mailing list