Path: blob/21.2-virgl/src/compiler/glsl/ir_array_refcount.cpp
4545 views
/*1* Copyright © 2016 Intel Corporation2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*/2223/**24* \file ir_array_refcount.cpp25*26* Provides a visitor which produces a list of variables referenced.27*/2829#include "ir.h"30#include "ir_visitor.h"31#include "ir_array_refcount.h"32#include "compiler/glsl_types.h"33#include "util/hash_table.h"3435ir_array_refcount_visitor::ir_array_refcount_visitor()36: last_array_deref(0), derefs(0), num_derefs(0), derefs_size(0)37{38this->mem_ctx = ralloc_context(NULL);39this->ht = _mesa_pointer_hash_table_create(NULL);40}4142static void43free_entry(struct hash_entry *entry)44{45ir_array_refcount_entry *ivre = (ir_array_refcount_entry *) entry->data;46delete ivre;47}4849ir_array_refcount_visitor::~ir_array_refcount_visitor()50{51ralloc_free(this->mem_ctx);52_mesa_hash_table_destroy(this->ht, free_entry);53}5455ir_array_refcount_entry::ir_array_refcount_entry(ir_variable *var)56: var(var), is_referenced(false)57{58num_bits = MAX2(1, var->type->arrays_of_arrays_size());59bits = new BITSET_WORD[BITSET_WORDS(num_bits)];60memset(bits, 0, BITSET_WORDS(num_bits) * sizeof(bits[0]));6162/* Count the "depth" of the arrays-of-arrays. */63array_depth = 0;64for (const glsl_type *type = var->type;65type->is_array();66type = type->fields.array) {67array_depth++;68}69}707172ir_array_refcount_entry::~ir_array_refcount_entry()73{74delete [] bits;75}7677ir_array_refcount_entry *78ir_array_refcount_visitor::get_variable_entry(ir_variable *var)79{80assert(var);8182struct hash_entry *e = _mesa_hash_table_search(this->ht, var);83if (e)84return (ir_array_refcount_entry *)e->data;8586ir_array_refcount_entry *entry = new ir_array_refcount_entry(var);87_mesa_hash_table_insert(this->ht, var, entry);8889return entry;90}919293array_deref_range *94ir_array_refcount_visitor::get_array_deref()95{96if ((num_derefs + 1) * sizeof(array_deref_range) > derefs_size) {97void *ptr = reralloc_size(mem_ctx, derefs, derefs_size + 4096);9899if (ptr == NULL)100return NULL;101102derefs_size += 4096;103derefs = (array_deref_range *)ptr;104}105106array_deref_range *d = &derefs[num_derefs];107num_derefs++;108109return d;110}111112ir_visitor_status113ir_array_refcount_visitor::visit_enter(ir_dereference_array *ir)114{115/* It could also be a vector or a matrix. Individual elements of vectors116* are natrices are not tracked, so bail.117*/118if (!ir->array->type->is_array())119return visit_continue;120121/* If this array dereference is a child of an array dereference that was122* already visited, just continue on. Otherwise, for an arrays-of-arrays123* dereference like x[1][2][3][4], we'd process the [1][2][3][4] sequence,124* the [1][2][3] sequence, the [1][2] sequence, and the [1] sequence. This125* ensures that we only process the full sequence.126*/127if (last_array_deref && last_array_deref->array == ir) {128last_array_deref = ir;129return visit_continue;130}131132last_array_deref = ir;133134num_derefs = 0;135136ir_rvalue *rv = ir;137while (rv->ir_type == ir_type_dereference_array) {138ir_dereference_array *const deref = rv->as_dereference_array();139140assert(deref != NULL);141assert(deref->array->type->is_array());142143ir_rvalue *const array = deref->array;144const ir_constant *const idx = deref->array_index->as_constant();145array_deref_range *const dr = get_array_deref();146147dr->size = array->type->array_size();148149if (idx != NULL) {150dr->index = idx->get_int_component(0);151} else {152/* An unsized array can occur at the end of an SSBO. We can't track153* accesses to such an array, so bail.154*/155if (array->type->array_size() == 0)156return visit_continue;157158dr->index = dr->size;159}160161rv = array;162}163164ir_dereference_variable *const var_deref = rv->as_dereference_variable();165166/* If the array being dereferenced is not a variable, bail. At the very167* least, ir_constant and ir_dereference_record are possible.168*/169if (var_deref == NULL)170return visit_continue;171172ir_array_refcount_entry *const entry =173this->get_variable_entry(var_deref->var);174175if (entry == NULL)176return visit_stop;177178link_util_mark_array_elements_referenced(derefs, num_derefs,179entry->array_depth,180entry->bits);181182return visit_continue;183}184185186ir_visitor_status187ir_array_refcount_visitor::visit(ir_dereference_variable *ir)188{189ir_variable *const var = ir->variable_referenced();190ir_array_refcount_entry *entry = this->get_variable_entry(var);191192entry->is_referenced = true;193194return visit_continue;195}196197198ir_visitor_status199ir_array_refcount_visitor::visit_enter(ir_function_signature *ir)200{201/* We don't want to descend into the function parameters and202* dead-code eliminate them, so just accept the body here.203*/204visit_list_elements(this, &ir->body);205return visit_continue_with_parent;206}207208209