diff options
author | Ian Romanick <[email protected]> | 2016-12-15 14:26:24 -0800 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2016-12-19 15:55:43 -0800 |
commit | d32956935edf06c8ae6872c707bc65187b4a1d15 (patch) | |
tree | d796b8c3644d6d375caea13725ffe922ba87dcaf /src/compiler/glsl/ir_array_refcount.cpp | |
parent | e92935089bd9a987027d1f0791e7298bb3a57113 (diff) |
glsl: Walk a list of ir_dereference_array to mark array elements as accessed
Signed-off-by: Ian Romanick <[email protected]>
Cc: [email protected]
Reviewed-by: Kenneth Graunke <[email protected]>
Diffstat (limited to 'src/compiler/glsl/ir_array_refcount.cpp')
-rw-r--r-- | src/compiler/glsl/ir_array_refcount.cpp | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/src/compiler/glsl/ir_array_refcount.cpp b/src/compiler/glsl/ir_array_refcount.cpp index 7627fa13bd2..1a46b2185d4 100644 --- a/src/compiler/glsl/ir_array_refcount.cpp +++ b/src/compiler/glsl/ir_array_refcount.cpp @@ -34,7 +34,7 @@ #include "util/hash_table.h" ir_array_refcount_visitor::ir_array_refcount_visitor() - : derefs(0), num_derefs(0), derefs_size(0) + : last_array_deref(0), derefs(0), num_derefs(0), derefs_size(0) { this->mem_ctx = ralloc_context(NULL); this->ht = _mesa_hash_table_create(NULL, _mesa_hash_pointer, @@ -159,6 +159,77 @@ ir_array_refcount_visitor::get_array_deref() return d; } +ir_visitor_status +ir_array_refcount_visitor::visit_enter(ir_dereference_array *ir) +{ + /* It could also be a vector or a matrix. Individual elements of vectors + * are natrices are not tracked, so bail. + */ + if (!ir->array->type->is_array()) + return visit_continue; + + /* If this array dereference is a child of an array dereference that was + * already visited, just continue on. Otherwise, for an arrays-of-arrays + * dereference like x[1][2][3][4], we'd process the [1][2][3][4] sequence, + * the [1][2][3] sequence, the [1][2] sequence, and the [1] sequence. This + * ensures that we only process the full sequence. + */ + if (last_array_deref && last_array_deref->array == ir) { + last_array_deref = ir; + return visit_continue; + } + + last_array_deref = ir; + + num_derefs = 0; + + ir_rvalue *rv = ir; + while (rv->ir_type == ir_type_dereference_array) { + ir_dereference_array *const deref = rv->as_dereference_array(); + + assert(deref != NULL); + assert(deref->array->type->is_array()); + + ir_rvalue *const array = deref->array; + const ir_constant *const idx = deref->array_index->as_constant(); + array_deref_range *const dr = get_array_deref(); + + dr->size = array->type->array_size(); + + if (idx != NULL) { + dr->index = idx->get_int_component(0); + } else { + /* An unsized array can occur at the end of an SSBO. We can't track + * accesses to such an array, so bail. + */ + if (array->type->array_size() == 0) + return visit_continue; + + dr->index = dr->size; + } + + rv = array; + } + + ir_dereference_variable *const var_deref = rv->as_dereference_variable(); + + /* If the array being dereferenced is not a variable, bail. At the very + * least, ir_constant and ir_dereference_record are possible. + */ + if (var_deref == NULL) + return visit_continue; + + ir_array_refcount_entry *const entry = + this->get_variable_entry(var_deref->var); + + if (entry == NULL) + return visit_stop; + + entry->mark_array_elements_referenced(derefs, num_derefs); + + return visit_continue; +} + ir_visitor_status ir_array_refcount_visitor::visit(ir_dereference_variable *ir) |