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