1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright © 2010 Intel Corporation 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"), 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions: 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the next 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * paragraph) shall be included in all copies or substantial portions of the 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software. 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DEALINGS IN THE SOFTWARE. 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \file opt_array_splitting.cpp 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If an array is always dereferenced with a constant index, then 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * split it apart into its elements, making it more amenable to other 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * optimization passes. 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This skips uniform/varying arrays, which would need careful 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * handling due to their ir->location fields tying them to the GL API 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and other shader stages. 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir.h" 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_visitor.h" 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_rvalue_visitor.h" 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_print_visitor.h" 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "glsl_types.h" 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool debug = false; 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgnamespace opt_array_splitting { 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass variable_entry : public exec_node 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic: 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry(ir_variable *var) 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->var = var; 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->split = true; 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->declaration = false; 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->components = NULL; 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->mem_ctx = NULL; 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->type->is_array()) 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->size = var->type->length; 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->size = var->type->matrix_columns; 60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var; /* The key: the variable's pointer. */ 63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org unsigned size; /* array length or matrix columns */ 64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** Whether this array should be split or not. */ 66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool split; 67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If the variable had a decl we can work with in the instruction 69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * stream. We can't do splitting on function arguments, which 70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * don't get this variable set. 71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool declaration; 73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable **components; 75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /** ralloc_parent(this->var) -- the shader's talloc context. */ 77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void *mem_ctx; 78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} /* namespace */ 81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgusing namespace opt_array_splitting; 82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This class does a walk over the tree, coming up with the set of 85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * variables that could be split by looking to see if they are arrays 86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * that are only ever constant-index dereferenced. 87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ir_array_reference_visitor : public ir_hierarchical_visitor { 89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic: 90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_array_reference_visitor(void) 91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->mem_ctx = ralloc_context(NULL); 93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->variable_list.make_empty(); 94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ~ir_array_reference_visitor(void) 97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_free(mem_ctx); 99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool get_split_list(exec_list *instructions, bool linked); 102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit(ir_variable *); 104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit(ir_dereference_variable *); 105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit_enter(ir_dereference_array *); 106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit_enter(ir_function_signature *); 107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *get_variable_entry(ir_variable *var); 109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* List of variable_entry */ 111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exec_list variable_list; 112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void *mem_ctx; 114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvariable_entry * 117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_array_reference_visitor::get_variable_entry(ir_variable *var) 118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(var); 120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->mode != ir_var_auto && 122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org var->mode != ir_var_temporary) 123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!(var->type->is_array() || var->type->is_matrix())) 126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If the array hasn't been sized yet, we can't split it. After 129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * linking, this should be resolved. 130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var->type->is_array() && var->type->length == 0) 132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_iter(exec_list_iterator, iter, this->variable_list) { 135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *entry = (variable_entry *)iter.get(); 136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (entry->var == var) 137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return entry; 138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *entry = new(mem_ctx) variable_entry(var); 141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->variable_list.push_tail(entry); 142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return entry; 143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status 147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_array_reference_visitor::visit(ir_variable *ir) 148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *entry = this->get_variable_entry(ir); 150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (entry) 152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->declaration = true; 153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status 158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_array_reference_visitor::visit(ir_dereference_variable *ir) 159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *entry = this->get_variable_entry(ir->var); 161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If we made it to here without seeing an ir_dereference_array, 163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * then the dereference of this array didn't have a constant index 164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * (see the visit_continue_with_parent below), so we can't split 165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the variable. 166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (entry) 168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->split = false; 169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status 174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_array_reference_visitor::visit_enter(ir_dereference_array *ir) 175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_dereference_variable *deref = ir->array->as_dereference_variable(); 177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!deref) 178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *entry = this->get_variable_entry(deref->var); 181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If the access to the array has a variable index, we wouldn't 183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * know which split variable this dereference should go to. 184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (entry && !ir->array_index->as_constant()) 186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->split = false; 187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue_with_parent; 189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status 192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_array_reference_visitor::visit_enter(ir_function_signature *ir) 193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* We don't have logic for array-splitting function arguments, 195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * so just look at the body instructions and not the parameter 196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * declarations. 197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org visit_list_elements(this, &ir->body); 199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue_with_parent; 200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_array_reference_visitor::get_split_list(exec_list *instructions, 204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org bool linked) 205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org visit_list_elements(this, instructions); 207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* If the shaders aren't linked yet, we can't mess with global 209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * declarations, which need to be matched by name across shaders. 210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!linked) { 212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_list(node, instructions) { 213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var = ((ir_instruction *)node)->as_variable(); 214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (var) { 215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *entry = get_variable_entry(var); 216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (entry) 217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->remove(); 218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Trim out variables we found that we can't split. */ 223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_iter(exec_list_iterator, iter, variable_list) { 224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *entry = (variable_entry *)iter.get(); 225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (debug) { 227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org printf("array %s@%p: decl %d, split %d\n", 228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->var->name, (void *) entry->var, entry->declaration, 229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->split); 230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!(entry->declaration && entry->split)) { 233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->remove(); 234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return !variable_list.is_empty(); 238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/** 241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This class rewrites the dereferences of arrays that have been split 242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to use the newly created ir_variables for each component. 243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass ir_array_splitting_visitor : public ir_rvalue_visitor { 245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic: 246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_array_splitting_visitor(exec_list *vars) 247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org this->variable_list = vars; 249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ~ir_array_splitting_visitor() 252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org { 253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org virtual ir_visitor_status visit_leave(ir_assignment *); 256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void split_deref(ir_dereference **deref); 258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void handle_rvalue(ir_rvalue **rvalue); 259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *get_splitting_entry(ir_variable *var); 260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org exec_list *variable_list; 262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}; 263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvariable_entry * 265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_array_splitting_visitor::get_splitting_entry(ir_variable *var) 266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(var); 268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_iter(exec_list_iterator, iter, *this->variable_list) { 270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *entry = (variable_entry *)iter.get(); 271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (entry->var == var) { 272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return entry; 273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return NULL; 277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_array_splitting_visitor::split_deref(ir_dereference **deref) 281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_dereference_array *deref_array = (*deref)->as_dereference_array(); 283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!deref_array) 284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_dereference_variable *deref_var = deref_array->array->as_dereference_variable(); 287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!deref_var) 288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *var = deref_var->var; 290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *entry = get_splitting_entry(var); 292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!entry) 293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_constant *constant = deref_array->array_index->as_constant(); 296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org assert(constant); 297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (constant->value.i[0] < (int)entry->size) { 299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *deref = new(entry->mem_ctx) 300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_dereference_variable(entry->components[constant->value.i[0]]); 301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } else { 302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* There was a constant array access beyond the end of the 303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * array. This might have happened due to constant folding 304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * after the initial parse. This produces an undefined value, 305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * but shouldn't crash. Just give them an uninitialized 306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * variable. 307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *temp = new(entry->mem_ctx) ir_variable(deref_array->type, 309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org "undef", 310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_var_temporary); 311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->components[0]->insert_before(temp); 312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *deref = new(entry->mem_ctx) ir_dereference_variable(temp); 313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid 317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_array_splitting_visitor::handle_rvalue(ir_rvalue **rvalue) 318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!*rvalue) 320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_dereference *deref = (*rvalue)->as_dereference(); 323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!deref) 325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return; 326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org split_deref(&deref); 328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *rvalue = deref; 329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_visitor_status 332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgir_array_splitting_visitor::visit_leave(ir_assignment *ir) 333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* The normal rvalue visitor skips the LHS of assignments, but we 335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * need to process those just the same. 336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_rvalue *lhs = ir->lhs; 338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org handle_rvalue(&lhs); 340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir->lhs = lhs->as_dereference(); 341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir->lhs->accept(this); 343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org handle_rvalue(&ir->rhs); 345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir->rhs->accept(this); 346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (ir->condition) { 348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org handle_rvalue(&ir->condition); 349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir->condition->accept(this); 350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return visit_continue; 353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool 356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgoptimize_split_arrays(exec_list *instructions, bool linked) 357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{ 358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_array_reference_visitor refs; 359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (!refs.get_split_list(instructions, linked)) 360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return false; 361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org void *mem_ctx = ralloc_context(NULL); 363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org /* Replace the decls of the arrays to be split with their split 365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * components. 366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org foreach_iter(exec_list_iterator, iter, refs.variable_list) { 368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org variable_entry *entry = (variable_entry *)iter.get(); 369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const struct glsl_type *type = entry->var->type; 370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const struct glsl_type *subtype; 371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (type->is_matrix()) 373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org subtype = type->column_type(); 374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org else 375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org subtype = type->fields.array; 376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->mem_ctx = ralloc_parent(entry->var); 378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->components = ralloc_array(mem_ctx, 380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_variable *, 381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->size); 382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org for (unsigned int i = 0; i < entry->size; i++) { 384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org const char *name = ralloc_asprintf(mem_ctx, "%s_%d", 385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->var->name, i); 386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->components[i] = 388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org new(entry->mem_ctx) ir_variable(subtype, name, ir_var_temporary); 389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->var->insert_before(entry->components[i]); 390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org entry->var->remove(); 393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org } 394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ir_array_splitting_visitor split(&refs.variable_list); 396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org visit_list_elements(&split, instructions); 397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org if (debug) 399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org _mesa_print_ir(instructions, NULL); 400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org ralloc_free(mem_ctx); 402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org return true; 404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org} 406