[Mesa-dev] [PATCH 2/6] glsl: Split arrays even in the presence of whole-array copies.
Timothy Arceri
timothy.arceri at collabora.com
Wed Jun 22 04:23:00 UTC 2016
On Tue, 2016-06-21 at 20:02 -0700, Kenneth Graunke wrote:
> Previously, we failed to split constant arrays. Code such as
>
> int[2] numbers = int[](1, 2);
>
> would generates a whole-array assignment:
>
> (assign () (var_ref numbers)
> (constant (array int 4) (constant int 1) (constant int
> 2)))
>
> opt_array_splitting generally tried to visit ir_dereference_array
> nodes,
> and avoid recursing into the inner ir_dereference_variable. So if it
> ever saw a ir_dereference_variable, it assumed this was a whole-array
> read and bailed. However, in the above case, there's no array deref,
> and we can totally handle it - we just have to "unroll" the
> assignment,
> creating assignments for each element.
>
> This was mitigated by the fact that we constant propagate whole
> arrays,
> so a dereference of a single component would usually get the desired
> single value anyway. However, I plan to stop doing that shortly;
> early experiments with disabling constant propagation of arrays
> revealed this shortcoming.
>
> This patch causes some arrays in Gl32GSCloth's geometry shaders to be
> split, which allows other optimizations to eliminate unused GS
> inputs.
> The VS then doesn't have to write them, which eliminates the entire
> VS
> (5 -> 2 instructions). It still renders correctly.
>
> No other change in shader-db.
>
> Cc: mesa-stable at lists.freedesktop.org
> Signed-off-by: Kenneth Graunke <kenneth at whitecape.org>
> ---
> src/compiler/glsl/opt_array_splitting.cpp | 56
> +++++++++++++++++++++++++++++++
> 1 file changed, 56 insertions(+)
>
> diff --git a/src/compiler/glsl/opt_array_splitting.cpp
> b/src/compiler/glsl/opt_array_splitting.cpp
> index a294da5..9faeb87 100644
> --- a/src/compiler/glsl/opt_array_splitting.cpp
> +++ b/src/compiler/glsl/opt_array_splitting.cpp
> @@ -93,6 +93,7 @@ public:
> {
> this->mem_ctx = ralloc_context(NULL);
> this->variable_list.make_empty();
> + this->in_whole_array_copy = false;
> }
>
> ~ir_array_reference_visitor(void)
> @@ -104,6 +105,8 @@ public:
>
> virtual ir_visitor_status visit(ir_variable *);
> virtual ir_visitor_status visit(ir_dereference_variable *);
> + virtual ir_visitor_status visit_enter(ir_assignment *);
> + virtual ir_visitor_status visit_leave(ir_assignment *);
> virtual ir_visitor_status visit_enter(ir_dereference_array *);
> virtual ir_visitor_status visit_enter(ir_function_signature *);
>
> @@ -113,6 +116,8 @@ public:
> exec_list variable_list;
>
> void *mem_ctx;
> +
> + bool in_whole_array_copy;
> };
>
> } /* namespace */
> @@ -158,10 +163,34 @@ ir_array_reference_visitor::visit(ir_variable
> *ir)
> }
>
> ir_visitor_status
> +ir_array_reference_visitor::visit_enter(ir_assignment *ir)
> +{
> + in_whole_array_copy =
> + ir->lhs->type->is_array() && !ir->lhs->type-
> >is_array_of_arrays() &&
> + ir->whole_variable_written();
Maybe a TODO for AoA support? I assume we would just need to do some
kind of recersive call in the new code below or is there more to it? If
there is more to it?
> +
> + return visit_continue;
> +}
> +
> +ir_visitor_status
> +ir_array_reference_visitor::visit_leave(ir_assignment *ir)
> +{
> + in_whole_array_copy = false;
> +
> + return visit_continue;
> +}
> +
> +ir_visitor_status
> ir_array_reference_visitor::visit(ir_dereference_variable *ir)
> {
> variable_entry *entry = this->get_variable_entry(ir->var);
>
> + /* Ignore whole-array assignments on the LHS. We can split those
> + * by "unrolling" the assignment into component-wise assignments.
> + */
Instead of ignore maybe "Allow" or "Allow splitting of" or something
like that I think makes it easier to understand whats going on.
Otherwise patch 1-2 are:
Reviewed-by: Timothy Arceri <timothy.arceri at collabora.com>
> + if (in_assignee && in_whole_array_copy)
> + return visit_continue;
> +
> /* If we made it to here without seeing an ir_dereference_array,
> * then the dereference of this array didn't have a constant
> index
> * (see the visit_continue_with_parent below), so we can't split
> @@ -350,6 +379,33 @@
> ir_array_splitting_visitor::visit_leave(ir_assignment *ir)
> */
> ir_rvalue *lhs = ir->lhs;
>
> + /* "Unroll" any whole array assignments, creating assignments for
> + * each array element. Then, do splitting on each new
> assignment.
> + */
> + if (lhs->type->is_array() && ir->whole_variable_written() &&
> + get_splitting_entry(ir->whole_variable_written())) {
> + void *mem_ctx = ralloc_parent(ir);
> +
> + for (unsigned i = 0; i < lhs->type->length; i++) {
> + ir_rvalue *lhs_i =
> + new(mem_ctx) ir_dereference_array(ir->lhs-
> >clone(mem_ctx, NULL),
> + new(mem_ctx)
> ir_constant(i));
> + ir_rvalue *rhs_i =
> + new(mem_ctx) ir_dereference_array(ir->rhs-
> >clone(mem_ctx, NULL),
> + new(mem_ctx)
> ir_constant(i));
> + ir_rvalue *condition_i =
> + ir->condition ? ir->condition->clone(mem_ctx, NULL) :
> NULL;
> +
> + ir_assignment *assign_i =
> + new(mem_ctx) ir_assignment(lhs_i, rhs_i, condition_i);
> +
> + ir->insert_before(assign_i);
> + assign_i->accept(this);
> + }
> + ir->remove();
> + return visit_continue;
> + }
> +
> handle_rvalue(&lhs);
> ir->lhs = lhs->as_dereference();
>
More information about the mesa-dev
mailing list