11591693c7b415e9869157c711fe11263c95d74eDavid Li/*
21591693c7b415e9869157c711fe11263c95d74eDavid Li * Copyright © 2010 Intel Corporation
31591693c7b415e9869157c711fe11263c95d74eDavid Li *
41591693c7b415e9869157c711fe11263c95d74eDavid Li * Permission is hereby granted, free of charge, to any person obtaining a
51591693c7b415e9869157c711fe11263c95d74eDavid Li * copy of this software and associated documentation files (the "Software"),
61591693c7b415e9869157c711fe11263c95d74eDavid Li * to deal in the Software without restriction, including without limitation
71591693c7b415e9869157c711fe11263c95d74eDavid Li * the rights to use, copy, modify, merge, publish, distribute, sublicense,
81591693c7b415e9869157c711fe11263c95d74eDavid Li * and/or sell copies of the Software, and to permit persons to whom the
91591693c7b415e9869157c711fe11263c95d74eDavid Li * Software is furnished to do so, subject to the following conditions:
101591693c7b415e9869157c711fe11263c95d74eDavid Li *
111591693c7b415e9869157c711fe11263c95d74eDavid Li * The above copyright notice and this permission notice (including the next
121591693c7b415e9869157c711fe11263c95d74eDavid Li * paragraph) shall be included in all copies or substantial portions of the
131591693c7b415e9869157c711fe11263c95d74eDavid Li * Software.
141591693c7b415e9869157c711fe11263c95d74eDavid Li *
151591693c7b415e9869157c711fe11263c95d74eDavid Li * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
161591693c7b415e9869157c711fe11263c95d74eDavid Li * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
171591693c7b415e9869157c711fe11263c95d74eDavid Li * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
181591693c7b415e9869157c711fe11263c95d74eDavid Li * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
191591693c7b415e9869157c711fe11263c95d74eDavid Li * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
201591693c7b415e9869157c711fe11263c95d74eDavid Li * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
211591693c7b415e9869157c711fe11263c95d74eDavid Li * DEALINGS IN THE SOFTWARE.
221591693c7b415e9869157c711fe11263c95d74eDavid Li */
231591693c7b415e9869157c711fe11263c95d74eDavid Li
241591693c7b415e9869157c711fe11263c95d74eDavid Li/**
251591693c7b415e9869157c711fe11263c95d74eDavid Li * \file opt_structure_splitting.cpp
261591693c7b415e9869157c711fe11263c95d74eDavid Li *
271591693c7b415e9869157c711fe11263c95d74eDavid Li * If a structure is only ever referenced by its components, then
281591693c7b415e9869157c711fe11263c95d74eDavid Li * split those components out to individual variables so they can be
291591693c7b415e9869157c711fe11263c95d74eDavid Li * handled normally by other optimization passes.
301591693c7b415e9869157c711fe11263c95d74eDavid Li *
311591693c7b415e9869157c711fe11263c95d74eDavid Li * This skips structures like uniforms, which need to be accessible as
321591693c7b415e9869157c711fe11263c95d74eDavid Li * structures for their access by the GL.
331591693c7b415e9869157c711fe11263c95d74eDavid Li */
341591693c7b415e9869157c711fe11263c95d74eDavid Li
351591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir.h"
361591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_visitor.h"
371591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_print_visitor.h"
381591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_rvalue_visitor.h"
391591693c7b415e9869157c711fe11263c95d74eDavid Li#include "glsl_types.h"
401591693c7b415e9869157c711fe11263c95d74eDavid Li
411591693c7b415e9869157c711fe11263c95d74eDavid Listatic bool debug = false;
421591693c7b415e9869157c711fe11263c95d74eDavid Li
431591693c7b415e9869157c711fe11263c95d74eDavid Li// XXX using variable_entry2 here to avoid collision (MSVC multiply-defined
441591693c7b415e9869157c711fe11263c95d74eDavid Li// function) with the variable_entry class seen in ir_variable_refcount.h
451591693c7b415e9869157c711fe11263c95d74eDavid Li// Perhaps we can use the one in ir_variable_refcount.h and make this class
461591693c7b415e9869157c711fe11263c95d74eDavid Li// here go away?
471591693c7b415e9869157c711fe11263c95d74eDavid Liclass variable_entry2 : public exec_node
481591693c7b415e9869157c711fe11263c95d74eDavid Li{
491591693c7b415e9869157c711fe11263c95d74eDavid Lipublic:
501591693c7b415e9869157c711fe11263c95d74eDavid Li   variable_entry2(ir_variable *var)
511591693c7b415e9869157c711fe11263c95d74eDavid Li   {
521591693c7b415e9869157c711fe11263c95d74eDavid Li      this->var = var;
531591693c7b415e9869157c711fe11263c95d74eDavid Li      this->whole_structure_access = 0;
541591693c7b415e9869157c711fe11263c95d74eDavid Li      this->declaration = false;
551591693c7b415e9869157c711fe11263c95d74eDavid Li      this->components = NULL;
561591693c7b415e9869157c711fe11263c95d74eDavid Li      this->mem_ctx = NULL;
571591693c7b415e9869157c711fe11263c95d74eDavid Li   }
581591693c7b415e9869157c711fe11263c95d74eDavid Li
591591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable *var; /* The key: the variable's pointer. */
601591693c7b415e9869157c711fe11263c95d74eDavid Li
611591693c7b415e9869157c711fe11263c95d74eDavid Li   /** Number of times the variable is referenced, including assignments. */
621591693c7b415e9869157c711fe11263c95d74eDavid Li   unsigned whole_structure_access;
631591693c7b415e9869157c711fe11263c95d74eDavid Li
641591693c7b415e9869157c711fe11263c95d74eDavid Li   bool declaration; /* If the variable had a decl in the instruction stream */
651591693c7b415e9869157c711fe11263c95d74eDavid Li
661591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable **components;
671591693c7b415e9869157c711fe11263c95d74eDavid Li
68d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li   /** hieralloc_parent(this->var) -- the shader's hieralloc context. */
691591693c7b415e9869157c711fe11263c95d74eDavid Li   void *mem_ctx;
701591693c7b415e9869157c711fe11263c95d74eDavid Li};
711591693c7b415e9869157c711fe11263c95d74eDavid Li
721591693c7b415e9869157c711fe11263c95d74eDavid Li
731591693c7b415e9869157c711fe11263c95d74eDavid Liclass ir_structure_reference_visitor : public ir_hierarchical_visitor {
741591693c7b415e9869157c711fe11263c95d74eDavid Lipublic:
751591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_structure_reference_visitor(void)
761591693c7b415e9869157c711fe11263c95d74eDavid Li   {
77d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li      this->mem_ctx = hieralloc_new(NULL);
781591693c7b415e9869157c711fe11263c95d74eDavid Li      this->variable_list.make_empty();
791591693c7b415e9869157c711fe11263c95d74eDavid Li   }
801591693c7b415e9869157c711fe11263c95d74eDavid Li
811591693c7b415e9869157c711fe11263c95d74eDavid Li   ~ir_structure_reference_visitor(void)
821591693c7b415e9869157c711fe11263c95d74eDavid Li   {
83d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li      hieralloc_free(mem_ctx);
841591693c7b415e9869157c711fe11263c95d74eDavid Li   }
851591693c7b415e9869157c711fe11263c95d74eDavid Li
861591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit(ir_variable *);
871591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit(ir_dereference_variable *);
881591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(ir_dereference_record *);
891591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(ir_assignment *);
901591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(ir_function_signature *);
911591693c7b415e9869157c711fe11263c95d74eDavid Li
921591693c7b415e9869157c711fe11263c95d74eDavid Li   variable_entry2 *get_variable_entry2(ir_variable *var);
931591693c7b415e9869157c711fe11263c95d74eDavid Li
941591693c7b415e9869157c711fe11263c95d74eDavid Li   /* List of variable_entry */
951591693c7b415e9869157c711fe11263c95d74eDavid Li   exec_list variable_list;
961591693c7b415e9869157c711fe11263c95d74eDavid Li
971591693c7b415e9869157c711fe11263c95d74eDavid Li   void *mem_ctx;
981591693c7b415e9869157c711fe11263c95d74eDavid Li};
991591693c7b415e9869157c711fe11263c95d74eDavid Li
1001591693c7b415e9869157c711fe11263c95d74eDavid Livariable_entry2 *
1011591693c7b415e9869157c711fe11263c95d74eDavid Liir_structure_reference_visitor::get_variable_entry2(ir_variable *var)
1021591693c7b415e9869157c711fe11263c95d74eDavid Li{
1031591693c7b415e9869157c711fe11263c95d74eDavid Li   assert(var);
1041591693c7b415e9869157c711fe11263c95d74eDavid Li
1051591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!var->type->is_record() || var->mode == ir_var_uniform)
1061591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
1071591693c7b415e9869157c711fe11263c95d74eDavid Li
1081591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, iter, this->variable_list) {
1091591693c7b415e9869157c711fe11263c95d74eDavid Li      variable_entry2 *entry = (variable_entry2 *)iter.get();
1101591693c7b415e9869157c711fe11263c95d74eDavid Li      if (entry->var == var)
1111591693c7b415e9869157c711fe11263c95d74eDavid Li	 return entry;
1121591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1131591693c7b415e9869157c711fe11263c95d74eDavid Li
1141591693c7b415e9869157c711fe11263c95d74eDavid Li   variable_entry2 *entry = new(mem_ctx) variable_entry2(var);
1151591693c7b415e9869157c711fe11263c95d74eDavid Li   this->variable_list.push_tail(entry);
1161591693c7b415e9869157c711fe11263c95d74eDavid Li   return entry;
1171591693c7b415e9869157c711fe11263c95d74eDavid Li}
1181591693c7b415e9869157c711fe11263c95d74eDavid Li
1191591693c7b415e9869157c711fe11263c95d74eDavid Li
1201591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
1211591693c7b415e9869157c711fe11263c95d74eDavid Liir_structure_reference_visitor::visit(ir_variable *ir)
1221591693c7b415e9869157c711fe11263c95d74eDavid Li{
1231591693c7b415e9869157c711fe11263c95d74eDavid Li   variable_entry2 *entry = this->get_variable_entry2(ir);
1241591693c7b415e9869157c711fe11263c95d74eDavid Li
1251591693c7b415e9869157c711fe11263c95d74eDavid Li   if (entry)
1261591693c7b415e9869157c711fe11263c95d74eDavid Li      entry->declaration = true;
1271591693c7b415e9869157c711fe11263c95d74eDavid Li
1281591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
1291591693c7b415e9869157c711fe11263c95d74eDavid Li}
1301591693c7b415e9869157c711fe11263c95d74eDavid Li
1311591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
1321591693c7b415e9869157c711fe11263c95d74eDavid Liir_structure_reference_visitor::visit(ir_dereference_variable *ir)
1331591693c7b415e9869157c711fe11263c95d74eDavid Li{
1341591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable *const var = ir->variable_referenced();
1351591693c7b415e9869157c711fe11263c95d74eDavid Li   variable_entry2 *entry = this->get_variable_entry2(var);
1361591693c7b415e9869157c711fe11263c95d74eDavid Li
1371591693c7b415e9869157c711fe11263c95d74eDavid Li   if (entry)
1381591693c7b415e9869157c711fe11263c95d74eDavid Li      entry->whole_structure_access++;
1391591693c7b415e9869157c711fe11263c95d74eDavid Li
1401591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
1411591693c7b415e9869157c711fe11263c95d74eDavid Li}
1421591693c7b415e9869157c711fe11263c95d74eDavid Li
1431591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
1441591693c7b415e9869157c711fe11263c95d74eDavid Liir_structure_reference_visitor::visit_enter(ir_dereference_record *ir)
1451591693c7b415e9869157c711fe11263c95d74eDavid Li{
1461591693c7b415e9869157c711fe11263c95d74eDavid Li   (void) ir;
1471591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Don't descend into the ir_dereference_variable below. */
1481591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue_with_parent;
1491591693c7b415e9869157c711fe11263c95d74eDavid Li}
1501591693c7b415e9869157c711fe11263c95d74eDavid Li
1511591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
1521591693c7b415e9869157c711fe11263c95d74eDavid Liir_structure_reference_visitor::visit_enter(ir_assignment *ir)
1531591693c7b415e9869157c711fe11263c95d74eDavid Li{
1541591693c7b415e9869157c711fe11263c95d74eDavid Li   if (ir->lhs->as_dereference_variable() &&
1551591693c7b415e9869157c711fe11263c95d74eDavid Li       ir->rhs->as_dereference_variable() &&
1561591693c7b415e9869157c711fe11263c95d74eDavid Li       !ir->condition) {
1571591693c7b415e9869157c711fe11263c95d74eDavid Li      /* We'll split copies of a structure to copies of components, so don't
1581591693c7b415e9869157c711fe11263c95d74eDavid Li       * descend to the ir_dereference_variables.
1591591693c7b415e9869157c711fe11263c95d74eDavid Li       */
1601591693c7b415e9869157c711fe11263c95d74eDavid Li      return visit_continue_with_parent;
1611591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1621591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
1631591693c7b415e9869157c711fe11263c95d74eDavid Li}
1641591693c7b415e9869157c711fe11263c95d74eDavid Li
1651591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
1661591693c7b415e9869157c711fe11263c95d74eDavid Liir_structure_reference_visitor::visit_enter(ir_function_signature *ir)
1671591693c7b415e9869157c711fe11263c95d74eDavid Li{
1681591693c7b415e9869157c711fe11263c95d74eDavid Li   /* We don't want to descend into the function parameters and
1691591693c7b415e9869157c711fe11263c95d74eDavid Li    * dead-code eliminate them, so just accept the body here.
1701591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1711591693c7b415e9869157c711fe11263c95d74eDavid Li   visit_list_elements(this, &ir->body);
1721591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue_with_parent;
1731591693c7b415e9869157c711fe11263c95d74eDavid Li}
1741591693c7b415e9869157c711fe11263c95d74eDavid Li
1751591693c7b415e9869157c711fe11263c95d74eDavid Liclass ir_structure_splitting_visitor : public ir_rvalue_visitor {
1761591693c7b415e9869157c711fe11263c95d74eDavid Lipublic:
1771591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_structure_splitting_visitor(exec_list *vars)
1781591693c7b415e9869157c711fe11263c95d74eDavid Li   {
1791591693c7b415e9869157c711fe11263c95d74eDavid Li      this->variable_list = vars;
1801591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1811591693c7b415e9869157c711fe11263c95d74eDavid Li
1821591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ~ir_structure_splitting_visitor()
1831591693c7b415e9869157c711fe11263c95d74eDavid Li   {
1841591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1851591693c7b415e9869157c711fe11263c95d74eDavid Li
1861591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(ir_assignment *);
1871591693c7b415e9869157c711fe11263c95d74eDavid Li
1881591693c7b415e9869157c711fe11263c95d74eDavid Li   void split_deref(ir_dereference **deref);
1891591693c7b415e9869157c711fe11263c95d74eDavid Li   void handle_rvalue(ir_rvalue **rvalue);
1901591693c7b415e9869157c711fe11263c95d74eDavid Li   variable_entry2 *get_splitting_entry(ir_variable *var);
1911591693c7b415e9869157c711fe11263c95d74eDavid Li
1921591693c7b415e9869157c711fe11263c95d74eDavid Li   exec_list *variable_list;
1931591693c7b415e9869157c711fe11263c95d74eDavid Li   void *mem_ctx;
1941591693c7b415e9869157c711fe11263c95d74eDavid Li};
1951591693c7b415e9869157c711fe11263c95d74eDavid Li
1961591693c7b415e9869157c711fe11263c95d74eDavid Livariable_entry2 *
1971591693c7b415e9869157c711fe11263c95d74eDavid Liir_structure_splitting_visitor::get_splitting_entry(ir_variable *var)
1981591693c7b415e9869157c711fe11263c95d74eDavid Li{
1991591693c7b415e9869157c711fe11263c95d74eDavid Li   assert(var);
2001591693c7b415e9869157c711fe11263c95d74eDavid Li
2011591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!var->type->is_record())
2021591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
2031591693c7b415e9869157c711fe11263c95d74eDavid Li
2041591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, iter, *this->variable_list) {
2051591693c7b415e9869157c711fe11263c95d74eDavid Li      variable_entry2 *entry = (variable_entry2 *)iter.get();
2061591693c7b415e9869157c711fe11263c95d74eDavid Li      if (entry->var == var) {
2071591693c7b415e9869157c711fe11263c95d74eDavid Li	 return entry;
2081591693c7b415e9869157c711fe11263c95d74eDavid Li      }
2091591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2101591693c7b415e9869157c711fe11263c95d74eDavid Li
2111591693c7b415e9869157c711fe11263c95d74eDavid Li   return NULL;
2121591693c7b415e9869157c711fe11263c95d74eDavid Li}
2131591693c7b415e9869157c711fe11263c95d74eDavid Li
2141591693c7b415e9869157c711fe11263c95d74eDavid Livoid
2151591693c7b415e9869157c711fe11263c95d74eDavid Liir_structure_splitting_visitor::split_deref(ir_dereference **deref)
2161591693c7b415e9869157c711fe11263c95d74eDavid Li{
2171591693c7b415e9869157c711fe11263c95d74eDavid Li   if ((*deref)->ir_type != ir_type_dereference_record)
2181591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
2191591693c7b415e9869157c711fe11263c95d74eDavid Li
2201591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference_record *deref_record = (ir_dereference_record *)*deref;
2211591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference_variable *deref_var = deref_record->record->as_dereference_variable();
2221591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!deref_var)
2231591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
2241591693c7b415e9869157c711fe11263c95d74eDavid Li
2251591693c7b415e9869157c711fe11263c95d74eDavid Li   variable_entry2 *entry = get_splitting_entry(deref_var->var);
2261591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!entry)
2271591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
2281591693c7b415e9869157c711fe11263c95d74eDavid Li
2291591693c7b415e9869157c711fe11263c95d74eDavid Li   unsigned int i;
2301591693c7b415e9869157c711fe11263c95d74eDavid Li   for (i = 0; i < entry->var->type->length; i++) {
2311591693c7b415e9869157c711fe11263c95d74eDavid Li      if (strcmp(deref_record->field,
2321591693c7b415e9869157c711fe11263c95d74eDavid Li		 entry->var->type->fields.structure[i].name) == 0)
2331591693c7b415e9869157c711fe11263c95d74eDavid Li	 break;
2341591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2351591693c7b415e9869157c711fe11263c95d74eDavid Li   assert(i != entry->var->type->length);
2361591693c7b415e9869157c711fe11263c95d74eDavid Li
2371591693c7b415e9869157c711fe11263c95d74eDavid Li   *deref = new(entry->mem_ctx) ir_dereference_variable(entry->components[i]);
2381591693c7b415e9869157c711fe11263c95d74eDavid Li}
2391591693c7b415e9869157c711fe11263c95d74eDavid Li
2401591693c7b415e9869157c711fe11263c95d74eDavid Livoid
2411591693c7b415e9869157c711fe11263c95d74eDavid Liir_structure_splitting_visitor::handle_rvalue(ir_rvalue **rvalue)
2421591693c7b415e9869157c711fe11263c95d74eDavid Li{
2431591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!*rvalue)
2441591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
2451591693c7b415e9869157c711fe11263c95d74eDavid Li
2461591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference *deref = (*rvalue)->as_dereference();
2471591693c7b415e9869157c711fe11263c95d74eDavid Li
2481591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!deref)
2491591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
2501591693c7b415e9869157c711fe11263c95d74eDavid Li
2511591693c7b415e9869157c711fe11263c95d74eDavid Li   split_deref(&deref);
2521591693c7b415e9869157c711fe11263c95d74eDavid Li   *rvalue = deref;
2531591693c7b415e9869157c711fe11263c95d74eDavid Li}
2541591693c7b415e9869157c711fe11263c95d74eDavid Li
2551591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
2561591693c7b415e9869157c711fe11263c95d74eDavid Liir_structure_splitting_visitor::visit_leave(ir_assignment *ir)
2571591693c7b415e9869157c711fe11263c95d74eDavid Li{
2581591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference_variable *lhs_deref = ir->lhs->as_dereference_variable();
2591591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference_variable *rhs_deref = ir->rhs->as_dereference_variable();
2601591693c7b415e9869157c711fe11263c95d74eDavid Li   variable_entry2 *lhs_entry = lhs_deref ? get_splitting_entry(lhs_deref->var) : NULL;
2611591693c7b415e9869157c711fe11263c95d74eDavid Li   variable_entry2 *rhs_entry = rhs_deref ? get_splitting_entry(rhs_deref->var) : NULL;
2621591693c7b415e9869157c711fe11263c95d74eDavid Li   const glsl_type *type = ir->rhs->type;
2631591693c7b415e9869157c711fe11263c95d74eDavid Li
2641591693c7b415e9869157c711fe11263c95d74eDavid Li   if ((lhs_entry || rhs_entry) && !ir->condition) {
2651591693c7b415e9869157c711fe11263c95d74eDavid Li      for (unsigned int i = 0; i < type->length; i++) {
2661591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_dereference *new_lhs, *new_rhs;
2671591693c7b415e9869157c711fe11263c95d74eDavid Li	 void *mem_ctx = lhs_entry ? lhs_entry->mem_ctx : rhs_entry->mem_ctx;
2681591693c7b415e9869157c711fe11263c95d74eDavid Li
2691591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (lhs_entry) {
2701591693c7b415e9869157c711fe11263c95d74eDavid Li	    new_lhs = new(mem_ctx) ir_dereference_variable(lhs_entry->components[i]);
2711591693c7b415e9869157c711fe11263c95d74eDavid Li	 } else {
2721591693c7b415e9869157c711fe11263c95d74eDavid Li	    new_lhs = new(mem_ctx)
2731591693c7b415e9869157c711fe11263c95d74eDavid Li	       ir_dereference_record(ir->lhs->clone(mem_ctx, NULL),
2741591693c7b415e9869157c711fe11263c95d74eDavid Li				     type->fields.structure[i].name);
2751591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
2761591693c7b415e9869157c711fe11263c95d74eDavid Li
2771591693c7b415e9869157c711fe11263c95d74eDavid Li	 if (rhs_entry) {
2781591693c7b415e9869157c711fe11263c95d74eDavid Li	    new_rhs = new(mem_ctx) ir_dereference_variable(rhs_entry->components[i]);
2791591693c7b415e9869157c711fe11263c95d74eDavid Li	 } else {
2801591693c7b415e9869157c711fe11263c95d74eDavid Li	    new_rhs = new(mem_ctx)
2811591693c7b415e9869157c711fe11263c95d74eDavid Li	       ir_dereference_record(ir->rhs->clone(mem_ctx, NULL),
2821591693c7b415e9869157c711fe11263c95d74eDavid Li				     type->fields.structure[i].name);
2831591693c7b415e9869157c711fe11263c95d74eDavid Li	 }
2841591693c7b415e9869157c711fe11263c95d74eDavid Li
2851591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir->insert_before(new(mem_ctx) ir_assignment(new_lhs,
2861591693c7b415e9869157c711fe11263c95d74eDavid Li						      new_rhs,
2871591693c7b415e9869157c711fe11263c95d74eDavid Li						      NULL));
2881591693c7b415e9869157c711fe11263c95d74eDavid Li      }
2891591693c7b415e9869157c711fe11263c95d74eDavid Li      ir->remove();
2901591693c7b415e9869157c711fe11263c95d74eDavid Li   } else {
2911591693c7b415e9869157c711fe11263c95d74eDavid Li      handle_rvalue(&ir->rhs);
2921591693c7b415e9869157c711fe11263c95d74eDavid Li      split_deref(&ir->lhs);
2931591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2941591693c7b415e9869157c711fe11263c95d74eDavid Li
2951591693c7b415e9869157c711fe11263c95d74eDavid Li   handle_rvalue(&ir->condition);
2961591693c7b415e9869157c711fe11263c95d74eDavid Li
2971591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
2981591693c7b415e9869157c711fe11263c95d74eDavid Li}
2991591693c7b415e9869157c711fe11263c95d74eDavid Li
3001591693c7b415e9869157c711fe11263c95d74eDavid Libool
3011591693c7b415e9869157c711fe11263c95d74eDavid Lido_structure_splitting(exec_list *instructions)
3021591693c7b415e9869157c711fe11263c95d74eDavid Li{
3031591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_structure_reference_visitor refs;
3041591693c7b415e9869157c711fe11263c95d74eDavid Li
3051591693c7b415e9869157c711fe11263c95d74eDavid Li   visit_list_elements(&refs, instructions);
3061591693c7b415e9869157c711fe11263c95d74eDavid Li
3071591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Trim out variables we can't split. */
3081591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
3091591693c7b415e9869157c711fe11263c95d74eDavid Li      variable_entry2 *entry = (variable_entry2 *)iter.get();
3101591693c7b415e9869157c711fe11263c95d74eDavid Li
3111591693c7b415e9869157c711fe11263c95d74eDavid Li      if (debug) {
3121591693c7b415e9869157c711fe11263c95d74eDavid Li	 printf("structure %s@%p: decl %d, whole_access %d\n",
3131591693c7b415e9869157c711fe11263c95d74eDavid Li		entry->var->name, (void *) entry->var, entry->declaration,
3141591693c7b415e9869157c711fe11263c95d74eDavid Li		entry->whole_structure_access);
3151591693c7b415e9869157c711fe11263c95d74eDavid Li      }
3161591693c7b415e9869157c711fe11263c95d74eDavid Li
3171591693c7b415e9869157c711fe11263c95d74eDavid Li      if (!entry->declaration || entry->whole_structure_access) {
3181591693c7b415e9869157c711fe11263c95d74eDavid Li	 entry->remove();
3191591693c7b415e9869157c711fe11263c95d74eDavid Li      }
3201591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3211591693c7b415e9869157c711fe11263c95d74eDavid Li
3221591693c7b415e9869157c711fe11263c95d74eDavid Li   if (refs.variable_list.is_empty())
3231591693c7b415e9869157c711fe11263c95d74eDavid Li      return false;
3241591693c7b415e9869157c711fe11263c95d74eDavid Li
325d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li   void *mem_ctx = hieralloc_new(NULL);
3261591693c7b415e9869157c711fe11263c95d74eDavid Li
3271591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Replace the decls of the structures to be split with their split
3281591693c7b415e9869157c711fe11263c95d74eDavid Li    * components.
3291591693c7b415e9869157c711fe11263c95d74eDavid Li    */
3301591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, iter, refs.variable_list) {
3311591693c7b415e9869157c711fe11263c95d74eDavid Li      variable_entry2 *entry = (variable_entry2 *)iter.get();
3321591693c7b415e9869157c711fe11263c95d74eDavid Li      const struct glsl_type *type = entry->var->type;
3331591693c7b415e9869157c711fe11263c95d74eDavid Li
334d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li      entry->mem_ctx = hieralloc_parent(entry->var);
3351591693c7b415e9869157c711fe11263c95d74eDavid Li
336d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li      entry->components = hieralloc_array(mem_ctx,
3371591693c7b415e9869157c711fe11263c95d74eDavid Li				       ir_variable *,
3381591693c7b415e9869157c711fe11263c95d74eDavid Li				       type->length);
3391591693c7b415e9869157c711fe11263c95d74eDavid Li
3401591693c7b415e9869157c711fe11263c95d74eDavid Li      for (unsigned int i = 0; i < entry->var->type->length; i++) {
341d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li	 const char *name = hieralloc_asprintf(mem_ctx, "%s_%s",
3421591693c7b415e9869157c711fe11263c95d74eDavid Li					    entry->var->name,
3431591693c7b415e9869157c711fe11263c95d74eDavid Li					    type->fields.structure[i].name);
3441591693c7b415e9869157c711fe11263c95d74eDavid Li
3451591693c7b415e9869157c711fe11263c95d74eDavid Li	 entry->components[i] =
3461591693c7b415e9869157c711fe11263c95d74eDavid Li	    new(entry->mem_ctx) ir_variable(type->fields.structure[i].type,
3471591693c7b415e9869157c711fe11263c95d74eDavid Li					    name,
3481591693c7b415e9869157c711fe11263c95d74eDavid Li					    ir_var_temporary);
3491591693c7b415e9869157c711fe11263c95d74eDavid Li	 entry->var->insert_before(entry->components[i]);
3501591693c7b415e9869157c711fe11263c95d74eDavid Li      }
3511591693c7b415e9869157c711fe11263c95d74eDavid Li
3521591693c7b415e9869157c711fe11263c95d74eDavid Li      entry->var->remove();
3531591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3541591693c7b415e9869157c711fe11263c95d74eDavid Li
3551591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_structure_splitting_visitor split(&refs.variable_list);
3561591693c7b415e9869157c711fe11263c95d74eDavid Li   visit_list_elements(&split, instructions);
3571591693c7b415e9869157c711fe11263c95d74eDavid Li
358d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li   hieralloc_free(mem_ctx);
3591591693c7b415e9869157c711fe11263c95d74eDavid Li
3601591693c7b415e9869157c711fe11263c95d74eDavid Li   return true;
3611591693c7b415e9869157c711fe11263c95d74eDavid Li}
362