160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt/* 260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * Copyright © 2010 Intel Corporation 360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * 460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * Permission is hereby granted, free of charge, to any person obtaining a 560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * copy of this software and associated documentation files (the "Software"), 660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * to deal in the Software without restriction, including without limitation 760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * and/or sell copies of the Software, and to permit persons to whom the 960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * Software is furnished to do so, subject to the following conditions: 1060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * 1160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * The above copyright notice and this permission notice (including the next 1260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * paragraph) shall be included in all copies or substantial portions of the 1360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * Software. 1460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * 1560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 1960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 2060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 2160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * DEALINGS IN THE SOFTWARE. 2260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt */ 2360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 2460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt/** 2560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * \file opt_array_splitting.cpp 2660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * 2760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * If an array is always dereferenced with a constant index, then 2860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * split it apart into its elements, making it more amenable to other 2960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * optimization passes. 3060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * 3160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * This skips uniform/varying arrays, which would need careful 3260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * handling due to their ir->location fields tying them to the GL API 3360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * and other shader stages. 3460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt */ 3560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 3660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt#include "ir.h" 3760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt#include "ir_visitor.h" 3860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt#include "ir_rvalue_visitor.h" 3960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt#include "ir_print_visitor.h" 4060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt#include "glsl_types.h" 4160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 4260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtstatic bool debug = false; 4360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 4460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtnamespace opt_array_splitting { 4560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 4660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtclass variable_entry : public exec_node 4760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt{ 4860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtpublic: 4960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry(ir_variable *var) 5060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt { 5160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt this->var = var; 52538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt this->split = true; 5360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt this->declaration = false; 5460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt this->components = NULL; 5560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt this->mem_ctx = NULL; 563bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt if (var->type->is_array()) 573bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt this->size = var->type->length; 583bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt else 593bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt this->size = var->type->matrix_columns; 6060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 6160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 6260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_variable *var; /* The key: the variable's pointer. */ 633bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt unsigned size; /* array length or matrix columns */ 6460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 65538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt /** Whether this array should be split or not. */ 66538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt bool split; 6760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 686de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt /* If the variable had a decl we can work with in the instruction 696de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt * stream. We can't do splitting on function arguments, which 706de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt * don't get this variable set. 716de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt */ 726de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt bool declaration; 7360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 7460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_variable **components; 7560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 7660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt /** ralloc_parent(this->var) -- the shader's talloc context. */ 7760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt void *mem_ctx; 7860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt}; 7960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 8060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt} /* namespace */ 8160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtusing namespace opt_array_splitting; 8260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 8360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt/** 8460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * This class does a walk over the tree, coming up with the set of 8560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * variables that could be split by looking to see if they are arrays 8660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * that are only ever constant-index dereferenced. 8760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt */ 8860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtclass ir_array_reference_visitor : public ir_hierarchical_visitor { 8960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtpublic: 9060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_array_reference_visitor(void) 9160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt { 9260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt this->mem_ctx = ralloc_context(NULL); 9360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt this->variable_list.make_empty(); 9460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 9560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 9660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ~ir_array_reference_visitor(void) 9760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt { 9860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ralloc_free(mem_ctx); 9960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 10060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 10160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt bool get_split_list(exec_list *instructions, bool linked); 10260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 10360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt virtual ir_visitor_status visit(ir_variable *); 10460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt virtual ir_visitor_status visit(ir_dereference_variable *); 10560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt virtual ir_visitor_status visit_enter(ir_dereference_array *); 1066de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt virtual ir_visitor_status visit_enter(ir_function_signature *); 10760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 10860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *get_variable_entry(ir_variable *var); 10960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 11060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt /* List of variable_entry */ 11160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt exec_list variable_list; 11260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 11360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt void *mem_ctx; 11460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt}; 11560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 11660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtvariable_entry * 11760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_array_reference_visitor::get_variable_entry(ir_variable *var) 11860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt{ 11960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt assert(var); 12060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 12160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (var->mode != ir_var_auto && 12260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt var->mode != ir_var_temporary) 12360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return NULL; 12460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 1253bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt if (!(var->type->is_array() || var->type->is_matrix())) 12660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return NULL; 12760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 12860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt /* If the array hasn't been sized yet, we can't split it. After 12960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * linking, this should be resolved. 13060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt */ 1313bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt if (var->type->is_array() && var->type->length == 0) 13260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return NULL; 13360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 13460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt foreach_iter(exec_list_iterator, iter, this->variable_list) { 13560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *entry = (variable_entry *)iter.get(); 13660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (entry->var == var) 13760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return entry; 13860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 13960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 14060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *entry = new(mem_ctx) variable_entry(var); 14160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt this->variable_list.push_tail(entry); 14260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return entry; 14360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt} 14460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 14560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 14660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_visitor_status 14760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_array_reference_visitor::visit(ir_variable *ir) 14860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt{ 14960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *entry = this->get_variable_entry(ir); 15060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 15160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (entry) 15260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt entry->declaration = true; 15360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 15460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return visit_continue; 15560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt} 15660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 15760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_visitor_status 15860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_array_reference_visitor::visit(ir_dereference_variable *ir) 15960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt{ 16060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *entry = this->get_variable_entry(ir->var); 16160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 162538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt /* If we made it to here without seeing an ir_dereference_array, 163538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt * then the dereference of this array didn't have a constant index 164538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt * (see the visit_continue_with_parent below), so we can't split 165538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt * the variable. 16660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt */ 16760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (entry) 168538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt entry->split = false; 16960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 17060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return visit_continue; 17160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt} 17260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 17360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_visitor_status 17460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_array_reference_visitor::visit_enter(ir_dereference_array *ir) 17560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt{ 17660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_dereference_variable *deref = ir->array->as_dereference_variable(); 17760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (!deref) 17860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return visit_continue; 17960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 18060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *entry = this->get_variable_entry(deref->var); 18160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 182538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt /* If the access to the array has a variable index, we wouldn't 183538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt * know which split variable this dereference should go to. 184538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt */ 18560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (entry && !ir->array_index->as_constant()) 186538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt entry->split = false; 18760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 18860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return visit_continue_with_parent; 18960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt} 19060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 1916de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholtir_visitor_status 1926de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholtir_array_reference_visitor::visit_enter(ir_function_signature *ir) 1936de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt{ 1946de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt /* We don't have logic for array-splitting function arguments, 1956de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt * so just look at the body instructions and not the parameter 1966de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt * declarations. 1976de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt */ 1986de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt visit_list_elements(this, &ir->body); 1996de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt return visit_continue_with_parent; 2006de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt} 2016de5da079682efd3f8887d3e0a7add7e70a5433dEric Anholt 20260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtbool 20360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_array_reference_visitor::get_split_list(exec_list *instructions, 20460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt bool linked) 20560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt{ 20660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt visit_list_elements(this, instructions); 20760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 20860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt /* If the shaders aren't linked yet, we can't mess with global 20960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * declarations, which need to be matched by name across shaders. 21060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt */ 21160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (!linked) { 21260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt foreach_list(node, instructions) { 21360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_variable *var = ((ir_instruction *)node)->as_variable(); 21460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (var) { 21560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *entry = get_variable_entry(var); 21660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (entry) 21760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt entry->remove(); 21860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 21960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 22060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 22160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 22260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt /* Trim out variables we found that we can't split. */ 22360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt foreach_iter(exec_list_iterator, iter, variable_list) { 22460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *entry = (variable_entry *)iter.get(); 22560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 22660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (debug) { 227538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt printf("array %s@%p: decl %d, split %d\n", 22860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt entry->var->name, (void *) entry->var, entry->declaration, 229538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt entry->split); 23060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 23160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 232538ba0a36373d7d0bd047e6fc4ef4e6e8d8bb8d7Eric Anholt if (!(entry->declaration && entry->split)) { 23360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt entry->remove(); 23460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 23560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 23660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 23760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return !variable_list.is_empty(); 23860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt} 23960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 24036a8c9caafef79524920120286649a0f53fe5228Eric Anholt/** 24136a8c9caafef79524920120286649a0f53fe5228Eric Anholt * This class rewrites the dereferences of arrays that have been split 24236a8c9caafef79524920120286649a0f53fe5228Eric Anholt * to use the newly created ir_variables for each component. 24336a8c9caafef79524920120286649a0f53fe5228Eric Anholt */ 24460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtclass ir_array_splitting_visitor : public ir_rvalue_visitor { 24560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtpublic: 24660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_array_splitting_visitor(exec_list *vars) 24760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt { 24860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt this->variable_list = vars; 24960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 25060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 25160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt virtual ~ir_array_splitting_visitor() 25260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt { 25360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 25460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 25560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt virtual ir_visitor_status visit_leave(ir_assignment *); 25660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 25760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt void split_deref(ir_dereference **deref); 25860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt void handle_rvalue(ir_rvalue **rvalue); 25960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *get_splitting_entry(ir_variable *var); 26060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 26160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt exec_list *variable_list; 26260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt}; 26360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 26460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtvariable_entry * 26560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_array_splitting_visitor::get_splitting_entry(ir_variable *var) 26660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt{ 26760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt assert(var); 26860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 26960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt foreach_iter(exec_list_iterator, iter, *this->variable_list) { 27060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *entry = (variable_entry *)iter.get(); 27160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (entry->var == var) { 27260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return entry; 27360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 27460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 27560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 27660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return NULL; 27760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt} 27860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 27960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtvoid 28060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_array_splitting_visitor::split_deref(ir_dereference **deref) 28160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt{ 28260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_dereference_array *deref_array = (*deref)->as_dereference_array(); 28360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (!deref_array) 28460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return; 28560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 28660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_dereference_variable *deref_var = deref_array->array->as_dereference_variable(); 28760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (!deref_var) 28860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return; 28960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_variable *var = deref_var->var; 29060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 29160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *entry = get_splitting_entry(var); 29260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (!entry) 29360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return; 29460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 29560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_constant *constant = deref_array->array_index->as_constant(); 29660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt assert(constant); 29760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 2983bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt if (constant->value.i[0] < (int)entry->size) { 29960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt *deref = new(entry->mem_ctx) 30060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_dereference_variable(entry->components[constant->value.i[0]]); 30160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } else { 30260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt /* There was a constant array access beyond the end of the 30360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * array. This might have happened due to constant folding 30460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * after the initial parse. This produces an undefined value, 30560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * but shouldn't crash. Just give them an uninitialized 30660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * variable. 30760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt */ 30860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_variable *temp = new(entry->mem_ctx) ir_variable(deref_array->type, 30960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt "undef", 31060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_var_temporary); 31160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt entry->components[0]->insert_before(temp); 31260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt *deref = new(entry->mem_ctx) ir_dereference_variable(temp); 31360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 31460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt} 31560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 31660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtvoid 31760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_array_splitting_visitor::handle_rvalue(ir_rvalue **rvalue) 31860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt{ 31960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (!*rvalue) 32060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return; 32160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 32260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_dereference *deref = (*rvalue)->as_dereference(); 32360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 32460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (!deref) 32560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return; 32660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 32760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt split_deref(&deref); 32860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt *rvalue = deref; 32960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt} 33060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 33160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_visitor_status 33260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtir_array_splitting_visitor::visit_leave(ir_assignment *ir) 33360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt{ 33460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt /* The normal rvalue visitor skips the LHS of assignments, but we 33560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * need to process those just the same. 33660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt */ 33760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_rvalue *lhs = ir->lhs; 33860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 33960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt handle_rvalue(&lhs); 34060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir->lhs = lhs->as_dereference(); 34160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 34260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir->lhs->accept(this); 34360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 34460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt handle_rvalue(&ir->rhs); 34560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir->rhs->accept(this); 34660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 34760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (ir->condition) { 34860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt handle_rvalue(&ir->condition); 34960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir->condition->accept(this); 35060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 35160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 35260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return visit_continue; 35360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt} 35460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 35560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtbool 35660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholtoptimize_split_arrays(exec_list *instructions, bool linked) 35760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt{ 35860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_array_reference_visitor refs; 35960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (!refs.get_split_list(instructions, linked)) 36060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return false; 36160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 36260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt void *mem_ctx = ralloc_context(NULL); 36360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 36460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt /* Replace the decls of the arrays to be split with their split 36560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt * components. 36660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt */ 36760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt foreach_iter(exec_list_iterator, iter, refs.variable_list) { 36860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt variable_entry *entry = (variable_entry *)iter.get(); 36960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt const struct glsl_type *type = entry->var->type; 3703bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt const struct glsl_type *subtype; 3713bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt 3723bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt if (type->is_matrix()) 373c07290ddb2bf3095b9f5a1e0b33697999834fa0eEric Anholt subtype = type->column_type(); 3743bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt else 3753bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt subtype = type->fields.array; 37660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 37760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt entry->mem_ctx = ralloc_parent(entry->var); 37860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 37960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt entry->components = ralloc_array(mem_ctx, 38060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_variable *, 3813bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt entry->size); 38260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 3833bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt for (unsigned int i = 0; i < entry->size; i++) { 38460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt const char *name = ralloc_asprintf(mem_ctx, "%s_%d", 38560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt entry->var->name, i); 38660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 38760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt entry->components[i] = 3883bdccbc3e0185fbca16eada2a76f55c6e3f867b5Eric Anholt new(entry->mem_ctx) ir_variable(subtype, name, ir_var_temporary); 38960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt entry->var->insert_before(entry->components[i]); 39060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 39160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 39260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt entry->var->remove(); 39360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt } 39460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 39560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ir_array_splitting_visitor split(&refs.variable_list); 39660177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt visit_list_elements(&split, instructions); 39760177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 39860177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt if (debug) 39960177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt _mesa_print_ir(instructions, NULL); 40060177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 40160177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt ralloc_free(mem_ctx); 40260177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 40360177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt return true; 40460177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt 40560177d5e2aec07ed6386a6935b118a356d58c4ecEric Anholt} 406