[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