1c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt/* 2c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * Copyright © 2010 Intel Corporation 3c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * 4c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * Permission is hereby granted, free of charge, to any person obtaining a 5c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * copy of this software and associated documentation files (the "Software"), 6c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * to deal in the Software without restriction, including without limitation 7c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * and/or sell copies of the Software, and to permit persons to whom the 9c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * Software is furnished to do so, subject to the following conditions: 10c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * 11c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * The above copyright notice and this permission notice (including the next 12c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * paragraph) shall be included in all copies or substantial portions of the 13c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * Software. 14c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * 15c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * DEALINGS IN THE SOFTWARE. 22c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt */ 23c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 24c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt/** 25c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * \file brw_wm_vector_splitting.cpp 26c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * 27c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * If a vector is only ever referenced by its components, then 28c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * split those components out to individual variables so they can be 29c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * handled normally by other optimization passes. 30c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * 31c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * This skips vectors in uniforms and varyings, which need to be 32c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * accessible as vectors for their access by the GL. Also, vector 33c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * results of non-variable-derefs in assignments aren't handled 34c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * because to do so we would have to store the vector result to a 35c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * temporary in order to unload each channel, and to do so would just 36c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * loop us back to where we started. For the 965, this is exactly the 37c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * behavior we want for the results of texture lookups, but probably not for 38c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt */ 39c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 40c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtextern "C" { 41c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt#include "main/core.h" 42c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt#include "intel_context.h" 43c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt} 442f0edc60f4bd2ae5999a6afa656e3bb3f181bf0fChad Versace#include "glsl/ir.h" 452f0edc60f4bd2ae5999a6afa656e3bb3f181bf0fChad Versace#include "glsl/ir_visitor.h" 462f0edc60f4bd2ae5999a6afa656e3bb3f181bf0fChad Versace#include "glsl/ir_print_visitor.h" 472f0edc60f4bd2ae5999a6afa656e3bb3f181bf0fChad Versace#include "glsl/ir_rvalue_visitor.h" 482f0edc60f4bd2ae5999a6afa656e3bb3f181bf0fChad Versace#include "glsl/glsl_types.h" 49c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 50c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtstatic bool debug = false; 51c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 52c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtclass variable_entry : public exec_node 53c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt{ 54c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtpublic: 55c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt variable_entry(ir_variable *var) 56c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt { 57c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt this->var = var; 58c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt this->whole_vector_access = 0; 59c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt this->declaration = false; 60c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt this->mem_ctx = NULL; 61c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 62c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 63c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_variable *var; /* The key: the variable's pointer. */ 64c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 65c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt /** Number of times the variable is referenced, including assignments. */ 66c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt unsigned whole_vector_access; 67c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 68c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt bool declaration; /* If the variable had a decl in the instruction stream */ 69c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 70c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_variable *components[4]; 71c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 72d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke /** ralloc_parent(this->var) -- the shader's ralloc context. */ 73c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt void *mem_ctx; 74c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt}; 75c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 76c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtclass ir_vector_reference_visitor : public ir_hierarchical_visitor { 77c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtpublic: 78c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_vector_reference_visitor(void) 79c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt { 80d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke this->mem_ctx = ralloc_context(NULL); 81c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt this->variable_list.make_empty(); 82c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 83c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 84c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ~ir_vector_reference_visitor(void) 85c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt { 86d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke ralloc_free(mem_ctx); 87c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 88c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 89c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt virtual ir_visitor_status visit(ir_variable *); 90c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt virtual ir_visitor_status visit(ir_dereference_variable *); 91c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt virtual ir_visitor_status visit_enter(ir_swizzle *); 92c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt virtual ir_visitor_status visit_enter(ir_assignment *); 93c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt virtual ir_visitor_status visit_enter(ir_function_signature *); 94c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 95c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt variable_entry *get_variable_entry(ir_variable *var); 96c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 97c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt /* List of variable_entry */ 98c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt exec_list variable_list; 99c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 100c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt void *mem_ctx; 101c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt}; 102c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 103c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtvariable_entry * 104c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_vector_reference_visitor::get_variable_entry(ir_variable *var) 105c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt{ 106c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt assert(var); 107c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 108c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (!var->type->is_vector()) 109c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return NULL; 110c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 111c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt switch (var->mode) { 112c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt case ir_var_uniform: 113c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt case ir_var_in: 114c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt case ir_var_out: 115c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt case ir_var_inout: 116c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt /* Can't split varyings or uniforms. Function in/outs won't get split 117c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * either, so don't care about the ambiguity. 118c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt */ 119c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return NULL; 120c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt case ir_var_auto: 121c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt case ir_var_temporary: 122c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt break; 123c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 124c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 12544ffb4ae207e48f78fae55925601b8708ed09c1dEric Anholt foreach_list(node, &this->variable_list) { 12644ffb4ae207e48f78fae55925601b8708ed09c1dEric Anholt variable_entry *entry = (variable_entry *)node; 127c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (entry->var == var) 128c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return entry; 129c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 130c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 131c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt variable_entry *entry = new(mem_ctx) variable_entry(var); 132c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt this->variable_list.push_tail(entry); 133c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return entry; 134c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt} 135c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 136c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 137c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_visitor_status 138c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_vector_reference_visitor::visit(ir_variable *ir) 139c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt{ 140c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt variable_entry *entry = this->get_variable_entry(ir); 141c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 142c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (entry) 143c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt entry->declaration = true; 144c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 145c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return visit_continue; 146c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt} 147c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 148c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_visitor_status 149c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_vector_reference_visitor::visit(ir_dereference_variable *ir) 150c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt{ 151c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_variable *const var = ir->var; 152c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt variable_entry *entry = this->get_variable_entry(var); 153c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 154c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (entry) 155c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt entry->whole_vector_access++; 156c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 157c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return visit_continue; 158c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt} 159c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 160c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_visitor_status 161c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_vector_reference_visitor::visit_enter(ir_swizzle *ir) 162c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt{ 163c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt /* Don't descend into a vector ir_dereference_variable below. */ 164c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (ir->val->as_dereference_variable() && ir->type->is_scalar()) 165c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return visit_continue_with_parent; 166c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 167c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return visit_continue; 168c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt} 169c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 170c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_visitor_status 171c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_vector_reference_visitor::visit_enter(ir_assignment *ir) 172c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt{ 173c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (ir->lhs->as_dereference_variable() && 174c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir->rhs->as_dereference_variable() && 175c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt !ir->condition) { 176c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt /* We'll split copies of a vector to copies of channels, so don't 177c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * descend to the ir_dereference_variables. 178c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt */ 179c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return visit_continue_with_parent; 180c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 181c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (ir->lhs->as_dereference_variable() && 182c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt is_power_of_two(ir->write_mask) && 183c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt !ir->condition) { 184c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt /* If we're writing just a channel, then channel-splitting the LHS is OK. 185c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt */ 186c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir->rhs->accept(this); 187c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return visit_continue_with_parent; 188c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 189c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return visit_continue; 190c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt} 191c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 192c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_visitor_status 193c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_vector_reference_visitor::visit_enter(ir_function_signature *ir) 194c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt{ 195c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt /* We don't want to descend into the function parameters and 196c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * split them, so just accept the body here. 197c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt */ 198c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt visit_list_elements(this, &ir->body); 199c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return visit_continue_with_parent; 200c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt} 201c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 202c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtclass ir_vector_splitting_visitor : public ir_rvalue_visitor { 203c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtpublic: 204c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_vector_splitting_visitor(exec_list *vars) 205c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt { 206c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt this->variable_list = vars; 207c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 208c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 209c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt virtual ir_visitor_status visit_leave(ir_assignment *); 210c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 211c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt void handle_rvalue(ir_rvalue **rvalue); 2124abba27ae06b21111adfa1c0446b38d57b61e947Kenneth Graunke variable_entry *get_splitting_entry(ir_variable *var); 213c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 214c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt exec_list *variable_list; 215c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt}; 216c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 2174abba27ae06b21111adfa1c0446b38d57b61e947Kenneth Graunkevariable_entry * 218c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_vector_splitting_visitor::get_splitting_entry(ir_variable *var) 219c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt{ 220c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt assert(var); 221c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 222c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (!var->type->is_vector()) 223c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return NULL; 224c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 22544ffb4ae207e48f78fae55925601b8708ed09c1dEric Anholt foreach_list(node, &*this->variable_list) { 22644ffb4ae207e48f78fae55925601b8708ed09c1dEric Anholt variable_entry *entry = (variable_entry *)node; 227c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (entry->var == var) { 228c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return entry; 229c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 230c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 231c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 232c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return NULL; 233c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt} 234c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 235c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtvoid 236c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_vector_splitting_visitor::handle_rvalue(ir_rvalue **rvalue) 237c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt{ 238c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (!*rvalue) 239c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return; 240c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 241c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_swizzle *swiz = (*rvalue)->as_swizzle(); 242c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (!swiz || !swiz->type->is_scalar()) 243c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return; 244c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 245c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_dereference_variable *deref_var = swiz->val->as_dereference_variable(); 246c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (!deref_var) 247c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return; 248c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 249c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt variable_entry *entry = get_splitting_entry(deref_var->var); 250c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (!entry) 251c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return; 252c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 253c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_variable *var = entry->components[swiz->mask.x]; 254c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt *rvalue = new(entry->mem_ctx) ir_dereference_variable(var); 255c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt} 256c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 257c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_visitor_status 258c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtir_vector_splitting_visitor::visit_leave(ir_assignment *ir) 259c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt{ 260c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_dereference_variable *lhs_deref = ir->lhs->as_dereference_variable(); 261c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_dereference_variable *rhs_deref = ir->rhs->as_dereference_variable(); 262c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt variable_entry *lhs = lhs_deref ? get_splitting_entry(lhs_deref->var) : NULL; 263c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt variable_entry *rhs = rhs_deref ? get_splitting_entry(rhs_deref->var) : NULL; 264c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 265c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (lhs_deref && rhs_deref && (lhs || rhs) && !ir->condition) { 2663610e0c1a0edc87cef32b7d5d3f4d9004e31f6c4Eric Anholt unsigned int rhs_chan = 0; 2673610e0c1a0edc87cef32b7d5d3f4d9004e31f6c4Eric Anholt 268c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt /* Straight assignment of vector variables. */ 2693610e0c1a0edc87cef32b7d5d3f4d9004e31f6c4Eric Anholt for (unsigned int i = 0; i < ir->lhs->type->vector_elements; i++) { 270c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_dereference *new_lhs; 271c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_rvalue *new_rhs; 272c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt void *mem_ctx = lhs ? lhs->mem_ctx : rhs->mem_ctx; 273c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt unsigned int writemask; 274c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 275ac3d5beb0b20eb369b188aaf7b78f935969f3b62Eric Anholt if (!(ir->write_mask & (1 << i))) 276ac3d5beb0b20eb369b188aaf7b78f935969f3b62Eric Anholt continue; 277ac3d5beb0b20eb369b188aaf7b78f935969f3b62Eric Anholt 278c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (lhs) { 279c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt new_lhs = new(mem_ctx) ir_dereference_variable(lhs->components[i]); 280ac3d5beb0b20eb369b188aaf7b78f935969f3b62Eric Anholt writemask = 1; 281c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } else { 282c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt new_lhs = ir->lhs->clone(mem_ctx, NULL); 283ac3d5beb0b20eb369b188aaf7b78f935969f3b62Eric Anholt writemask = 1 << i; 284c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 285c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 286c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (rhs) { 2873610e0c1a0edc87cef32b7d5d3f4d9004e31f6c4Eric Anholt new_rhs = 2883610e0c1a0edc87cef32b7d5d3f4d9004e31f6c4Eric Anholt new(mem_ctx) ir_dereference_variable(rhs->components[rhs_chan]); 289c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } else { 290c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt new_rhs = new(mem_ctx) ir_swizzle(ir->rhs->clone(mem_ctx, NULL), 2913610e0c1a0edc87cef32b7d5d3f4d9004e31f6c4Eric Anholt rhs_chan, 0, 0, 0, 1); 292c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 293c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 294c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir->insert_before(new(mem_ctx) ir_assignment(new_lhs, 295c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt new_rhs, 296c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt NULL, writemask)); 2973610e0c1a0edc87cef32b7d5d3f4d9004e31f6c4Eric Anholt 2983610e0c1a0edc87cef32b7d5d3f4d9004e31f6c4Eric Anholt rhs_chan++; 299c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 300c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir->remove(); 301c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } else if (lhs) { 3023da98c1ca530cba9907735e6bf397017ffc8bd77Eric Anholt void *mem_ctx = lhs->mem_ctx; 303c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt int elem = -1; 304c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 305c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt switch (ir->write_mask) { 306c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt case (1 << 0): 307c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt elem = 0; 308c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt break; 309c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt case (1 << 1): 310c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt elem = 1; 311c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt break; 312c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt case (1 << 2): 313c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt elem = 2; 314c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt break; 315c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt case (1 << 3): 316c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt elem = 3; 317c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt break; 318c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt default: 319c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir->print(); 320c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt assert(!"not reached: non-channelwise dereference of LHS."); 321c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 322c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 323c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir->lhs = new(mem_ctx) ir_dereference_variable(lhs->components[elem]); 324c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir->write_mask = (1 << 0); 325c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 326c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt handle_rvalue(&ir->rhs); 327c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } else { 328c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt handle_rvalue(&ir->rhs); 329c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 330c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 331c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt handle_rvalue(&ir->condition); 332c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 333c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return visit_continue; 334c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt} 335c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 336c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtbool 337c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholtbrw_do_vector_splitting(exec_list *instructions) 338c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt{ 339c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_vector_reference_visitor refs; 340c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 341c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt visit_list_elements(&refs, instructions); 342c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 343c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt /* Trim out variables we can't split. */ 34444ffb4ae207e48f78fae55925601b8708ed09c1dEric Anholt foreach_list_safe(node, &refs.variable_list) { 34544ffb4ae207e48f78fae55925601b8708ed09c1dEric Anholt variable_entry *entry = (variable_entry *)node; 346c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 347c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (debug) { 348c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt printf("vector %s@%p: decl %d, whole_access %d\n", 349c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt entry->var->name, (void *) entry->var, entry->declaration, 350c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt entry->whole_vector_access); 351c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 352c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 353c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (!entry->declaration || entry->whole_vector_access) { 354c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt entry->remove(); 355c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 356c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 357c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 358c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt if (refs.variable_list.is_empty()) 359c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return false; 360c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 361d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke void *mem_ctx = ralloc_context(NULL); 362c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 363c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt /* Replace the decls of the vectors to be split with their split 364c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt * components. 365c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt */ 36644ffb4ae207e48f78fae55925601b8708ed09c1dEric Anholt foreach_list(node, &refs.variable_list) { 36744ffb4ae207e48f78fae55925601b8708ed09c1dEric Anholt variable_entry *entry = (variable_entry *)node; 368c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt const struct glsl_type *type; 369c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt type = glsl_type::get_instance(entry->var->type->base_type, 1, 1); 370c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 371d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke entry->mem_ctx = ralloc_parent(entry->var); 372c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 373c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt for (unsigned int i = 0; i < entry->var->type->vector_elements; i++) { 374d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke const char *name = ralloc_asprintf(mem_ctx, "%s_%c", 375c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt entry->var->name, 376c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt "xyzw"[i]); 377c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 378c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt entry->components[i] = new(entry->mem_ctx) ir_variable(type, name, 379c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_var_temporary); 380c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt entry->var->insert_before(entry->components[i]); 381c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 382c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 383c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt entry->var->remove(); 384c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt } 385c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 386c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt ir_vector_splitting_visitor split(&refs.variable_list); 387c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt visit_list_elements(&split, instructions); 388c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 389d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke ralloc_free(mem_ctx); 390c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt 391c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt return true; 392c1dfdcb93a8991788032d4906c5bf1a5b48cdc48Eric Anholt} 393