1a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri/*
2a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * Copyright © 2010 Luca Barbieri
3a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri *
4a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * Permission is hereby granted, free of charge, to any person obtaining a
5a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * copy of this software and associated documentation files (the "Software"),
6a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * to deal in the Software without restriction, including without limitation
7a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * and/or sell copies of the Software, and to permit persons to whom the
9a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * Software is furnished to do so, subject to the following conditions:
10a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri *
11a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * The above copyright notice and this permission notice (including the next
12a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * paragraph) shall be included in all copies or substantial portions of the
13a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * Software.
14a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri *
15a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * DEALINGS IN THE SOFTWARE.
22a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri */
23a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
24a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri/**
25a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * \file lower_variable_index_to_cond_assign.cpp
26a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri *
27a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * Turns non-constant indexing into array types to a series of
28a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * conditional moves of each element into a temporary.
29a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri *
30a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * Pre-DX10 GPUs often don't have a native way to do this operation,
31a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * and this works around that.
321731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick *
331731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * The lowering process proceeds as follows.  Each non-constant index
341731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * found in an r-value is converted to a canonical form \c array[i].  Each
351731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * element of the array is conditionally assigned to a temporary by comparing
361731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * \c i to a constant index.  This is done by cloning the canonical form and
371731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * replacing all occurances of \c i with a constant.  Each remaining occurance
381731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * of the canonical form in the IR is replaced with a dereference of the
391731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * temporary variable.
401731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick *
411731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * L-values with non-constant indices are handled similarly.  In this case,
421731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * the RHS of the assignment is assigned to a temporary.  The non-constant
431731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * index is replace with the canonical form (just like for r-values).  The
441731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * temporary is conditionally assigned to each element of the canonical form
451731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * by comparing \c i with each index.  The same clone-and-replace scheme is
461731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * used.
47a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri */
48a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
49a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri#include "ir.h"
50a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri#include "ir_rvalue_visitor.h"
51a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri#include "ir_optimization.h"
52a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri#include "glsl_types.h"
53a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri#include "main/macros.h"
54a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
5590cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick/**
5690cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick * Generate a comparison value for a block of indices
5790cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick *
5890cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick * Lowering passes for non-constant indexing of arrays, matrices, or vectors
5990cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick * can use this to generate blocks of index comparison values.
6090cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick *
6190cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick * \param instructions  List where new instructions will be appended
6290cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick * \param index         \c ir_variable containing the desired index
6390cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick * \param base          Base value for this block of comparisons
6490cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick * \param components    Number of unique index values to compare.  This must
6590cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick *                      be on the range [1, 4].
6690cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick * \param mem_ctx       ralloc memory context to be used for all allocations.
6790cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick *
6890cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick * \returns
6990cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick * An \c ir_rvalue that \b must be cloned for each use in conditional
7090cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick * assignments, etc.
7190cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick */
7290cc372400e1f5869baabd841823bbf9296d7b01Ian Romanickir_rvalue *
7390cc372400e1f5869baabd841823bbf9296d7b01Ian Romanickcompare_index_block(exec_list *instructions, ir_variable *index,
7490cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick		    unsigned base, unsigned components, void *mem_ctx)
7590cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick{
7690cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   ir_rvalue *broadcast_index = new(mem_ctx) ir_dereference_variable(index);
7790cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick
7890cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   assert(index->type->is_scalar());
7990cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   assert(index->type->base_type == GLSL_TYPE_INT);
8090cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   assert(components >= 1 && components <= 4);
8190cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick
8290cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   if (components > 1) {
8390cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick      const ir_swizzle_mask m = { 0, 0, 0, 0, components, false };
8490cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick      broadcast_index = new(mem_ctx) ir_swizzle(broadcast_index, m);
8590cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   }
8690cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick
8790cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   /* Compare the desired index value with the next block of four indices.
8890cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick    */
8990cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   ir_constant_data test_indices_data;
9090cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   memset(&test_indices_data, 0, sizeof(test_indices_data));
9190cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   test_indices_data.i[0] = base;
9290cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   test_indices_data.i[1] = base + 1;
9390cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   test_indices_data.i[2] = base + 2;
9490cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   test_indices_data.i[3] = base + 3;
9590cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick
9690cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   ir_constant *const test_indices =
9790cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick      new(mem_ctx) ir_constant(broadcast_index->type,
9890cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick			       &test_indices_data);
9990cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick
10090cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   ir_rvalue *const condition_val =
10190cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick      new(mem_ctx) ir_expression(ir_binop_equal,
10290cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick				 &glsl_type::bool_type[components - 1],
10390cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick				 broadcast_index,
10490cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick				 test_indices);
10590cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick
10690cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   ir_variable *const condition =
10790cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick      new(mem_ctx) ir_variable(condition_val->type,
10890cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick			       "dereference_condition",
10990cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick			       ir_var_temporary);
11090cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   instructions->push_tail(condition);
11190cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick
11290cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   ir_rvalue *const cond_deref =
11390cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick      new(mem_ctx) ir_dereference_variable(condition);
11490cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   instructions->push_tail(new(mem_ctx) ir_assignment(cond_deref, condition_val, 0));
11590cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick
11690cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick   return cond_deref;
11790cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick}
11890cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick
1198d5f3cef795428d7a95120416122a39c10cff11cIan Romanickstatic inline bool
120f75c2d53146ea14f8dfedcc5b7a4704278ba0792Kenneth Graunkeis_array_or_matrix(const ir_rvalue *ir)
1218d5f3cef795428d7a95120416122a39c10cff11cIan Romanick{
1228d5f3cef795428d7a95120416122a39c10cff11cIan Romanick   return (ir->type->is_array() || ir->type->is_matrix());
1238d5f3cef795428d7a95120416122a39c10cff11cIan Romanick}
1248d5f3cef795428d7a95120416122a39c10cff11cIan Romanick
1251731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick/**
1261731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * Replace a dereference of a variable with a specified r-value
1271731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick *
1281731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * Each time a dereference of the specified value is replaced, the r-value
1291731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * tree is cloned.
1301731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick */
1311731ac308631138ca98d34e8b7070c6e3f981939Ian Romanickclass deref_replacer : public ir_rvalue_visitor {
1321731ac308631138ca98d34e8b7070c6e3f981939Ian Romanickpublic:
1331731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   deref_replacer(const ir_variable *variable_to_replace, ir_rvalue *value)
1341731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      : variable_to_replace(variable_to_replace), value(value),
1351731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick	progress(false)
1361731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   {
1371731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      assert(this->variable_to_replace != NULL);
1381731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      assert(this->value != NULL);
1391731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   }
1401731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick
1411731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   virtual void handle_rvalue(ir_rvalue **rvalue)
1421731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   {
1431731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      ir_dereference_variable *const dv = (*rvalue)->as_dereference_variable();
1441731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick
1451731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      if ((dv != NULL) && (dv->var == this->variable_to_replace)) {
1461731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick	 this->progress = true;
1471731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick	 *rvalue = this->value->clone(ralloc_parent(*rvalue), NULL);
1481731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      }
1491731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   }
1501731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick
1511731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   const ir_variable *variable_to_replace;
1521731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   ir_rvalue *value;
1531731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   bool progress;
1541731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick};
1551731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick
1561731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick/**
1571731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick * Find a variable index dereference of an array in an rvalue tree
1581731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick */
1591731ac308631138ca98d34e8b7070c6e3f981939Ian Romanickclass find_variable_index : public ir_hierarchical_visitor {
1601731ac308631138ca98d34e8b7070c6e3f981939Ian Romanickpublic:
1611731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   find_variable_index()
1621731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      : deref(NULL)
1631731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   {
1641731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      /* empty */
1651731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   }
1661731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick
1671731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   virtual ir_visitor_status visit_enter(ir_dereference_array *ir)
1681731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   {
1691731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      if (is_array_or_matrix(ir->array)
1701731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick	  && (ir->array_index->as_constant() == NULL)) {
1711731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick	 this->deref = ir;
1721731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick	 return visit_stop;
1731731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      }
1741731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick
1751731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      return visit_continue;
1761731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   }
1771731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick
1781731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   /**
1791731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick    * First array dereference found in the tree that has a non-constant index.
1801731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick    */
1811731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   ir_dereference_array *deref;
1821731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick};
1831731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick
184a47539c7a155475de00fa812842721d239abb3f4Luca Barbieristruct assignment_generator
185a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri{
186a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   ir_instruction* base_ir;
1871731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   ir_dereference *rvalue;
1881731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   ir_variable *old_index;
189a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   bool is_write;
190c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt   unsigned int write_mask;
191a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   ir_variable* var;
192a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
193a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   assignment_generator()
194a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   {
195a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   }
196a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
197a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   void generate(unsigned i, ir_rvalue* condition, exec_list *list) const
198a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   {
199a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      /* Just clone the rest of the deref chain when trying to get at the
200a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri       * underlying variable.
201a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri       */
202d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke      void *mem_ctx = ralloc_parent(base_ir);
203a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
2041731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      /* Clone the old r-value in its entirety.  Then replace any occurances of
2051731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick       * the old variable index with the new constant index.
2061731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick       */
2071731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      ir_dereference *element = this->rvalue->clone(mem_ctx, NULL);
2081731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      ir_constant *const index = new(mem_ctx) ir_constant(i);
2091731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      deref_replacer r(this->old_index, index);
2101731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      element->accept(&r);
2111731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      assert(r.progress);
2121731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick
2131731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      /* Generate a conditional assignment to (or from) the constant indexed
2141731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick       * array dereference.
2151731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick       */
2161731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      ir_rvalue *variable = new(mem_ctx) ir_dereference_variable(this->var);
2171731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      ir_assignment *const assignment = (is_write)
2181731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick	 ? new(mem_ctx) ir_assignment(element, variable, condition, write_mask)
2191731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick	 : new(mem_ctx) ir_assignment(variable, element, condition);
220a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
221a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      list->push_tail(assignment);
222a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   }
223a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri};
224a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
225a47539c7a155475de00fa812842721d239abb3f4Luca Barbieristruct switch_generator
226a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri{
227a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   /* make TFunction a template parameter if you need to use other generators */
228a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   typedef assignment_generator TFunction;
229a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   const TFunction& generator;
230a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
231a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   ir_variable* index;
232a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   unsigned linear_sequence_max_length;
233a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   unsigned condition_components;
234a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
235a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   void *mem_ctx;
236a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
237a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   switch_generator(const TFunction& generator, ir_variable *index,
238a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri		    unsigned linear_sequence_max_length,
239a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri		    unsigned condition_components)
240a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      : generator(generator), index(index),
241a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	linear_sequence_max_length(linear_sequence_max_length),
242a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	condition_components(condition_components)
243a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   {
244d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke      this->mem_ctx = ralloc_parent(index);
245a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   }
246a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
247a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   void linear_sequence(unsigned begin, unsigned end, exec_list *list)
248a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   {
249a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      if (begin == end)
250a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         return;
251a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
252a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      /* If the array access is a read, read the first element of this subregion
253a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri       * unconditionally.  The remaining tests will possibly overwrite this
254a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri       * value with one of the other array elements.
255a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri       *
256a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri       * This optimization cannot be done for writes because it will cause the
257a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri       * first element of the subregion to be written possibly *in addition* to
258a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri       * one of the other elements.
259a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri       */
260a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      unsigned first;
261a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      if (!this->generator.is_write) {
262a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	 this->generator.generate(begin, 0, list);
263a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	 first = begin + 1;
264a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      } else {
265a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	 first = begin;
266a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      }
267a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
268a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      for (unsigned i = first; i < end; i += 4) {
269a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         const unsigned comps = MIN2(condition_components, end - i);
270a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
271a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	 ir_rvalue *const cond_deref =
27290cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick	    compare_index_block(list, index, i, comps, this->mem_ctx);
273a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
274a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         if (comps == 1) {
27590cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick            this->generator.generate(i, cond_deref->clone(this->mem_ctx, NULL),
27690cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick				     list);
277a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         } else {
278a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri            for (unsigned j = 0; j < comps; j++) {
279a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	       ir_rvalue *const cond_swiz =
28090cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick		  new(this->mem_ctx) ir_swizzle(cond_deref->clone(this->mem_ctx, NULL),
28190cc372400e1f5869baabd841823bbf9296d7b01Ian Romanick						j, 0, 0, 0, 1);
282a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
283a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri               this->generator.generate(i + j, cond_swiz, list);
284a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri            }
285a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         }
286a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      }
287a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   }
288a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
289a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   void bisect(unsigned begin, unsigned end, exec_list *list)
290a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   {
291a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      unsigned middle = (begin + end) >> 1;
292a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
293a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      assert(index->type->is_integer());
294a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
295a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      ir_constant *const middle_c = (index->type->base_type == GLSL_TYPE_UINT)
296a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	 ? new(this->mem_ctx) ir_constant((unsigned)middle)
297a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         : new(this->mem_ctx) ir_constant((int)middle);
298a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
299a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
300a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      ir_dereference_variable *deref =
301a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	 new(this->mem_ctx) ir_dereference_variable(this->index);
302a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
303a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      ir_expression *less =
304a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	 new(this->mem_ctx) ir_expression(ir_binop_less, glsl_type::bool_type,
305a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri					  deref, middle_c);
306a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
307a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      ir_if *if_less = new(this->mem_ctx) ir_if(less);
308a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
309a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      generate(begin, middle, &if_less->then_instructions);
310a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      generate(middle, end, &if_less->else_instructions);
311a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
312a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      list->push_tail(if_less);
313a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   }
314a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
315a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   void generate(unsigned begin, unsigned end, exec_list *list)
316a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   {
317a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      unsigned length = end - begin;
318a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      if (length <= this->linear_sequence_max_length)
319a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         return linear_sequence(begin, end, list);
320a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      else
321a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         return bisect(begin, end, list);
322a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   }
323a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri};
324a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
325a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri/**
326a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri * Visitor class for replacing expressions with ir_constant values.
327a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri */
328a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
329a47539c7a155475de00fa812842721d239abb3f4Luca Barbiericlass variable_index_to_cond_assign_visitor : public ir_rvalue_visitor {
330a47539c7a155475de00fa812842721d239abb3f4Luca Barbieripublic:
331a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick   variable_index_to_cond_assign_visitor(bool lower_input,
332a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick					 bool lower_output,
333a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick					 bool lower_temp,
334a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick					 bool lower_uniform)
335a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   {
336a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      this->progress = false;
337a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      this->lower_inputs = lower_input;
338a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      this->lower_outputs = lower_output;
339a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      this->lower_temps = lower_temp;
340a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      this->lower_uniforms = lower_uniform;
341a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   }
342a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
343a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   bool progress;
344a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick   bool lower_inputs;
345a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick   bool lower_outputs;
346a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick   bool lower_temps;
347a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick   bool lower_uniforms;
348a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
349d2296e784aa8fad81c4910dcbbf61e826ce9a06aIan Romanick   bool storage_type_needs_lowering(ir_dereference_array *deref) const
350a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick   {
351156f85336f80d542569f0b0182bd27c7f3218e70Ian Romanick      /* If a variable isn't eventually the target of this dereference, then
352156f85336f80d542569f0b0182bd27c7f3218e70Ian Romanick       * it must be a constant or some sort of anonymous temporary storage.
353156f85336f80d542569f0b0182bd27c7f3218e70Ian Romanick       *
354156f85336f80d542569f0b0182bd27c7f3218e70Ian Romanick       * FINISHME: Is this correct?  Most drivers treat arrays of constants as
355156f85336f80d542569f0b0182bd27c7f3218e70Ian Romanick       * FINISHME: uniforms.  It seems like this should do the same.
356156f85336f80d542569f0b0182bd27c7f3218e70Ian Romanick       */
357156f85336f80d542569f0b0182bd27c7f3218e70Ian Romanick      const ir_variable *const var = deref->array->variable_referenced();
358156f85336f80d542569f0b0182bd27c7f3218e70Ian Romanick      if (var == NULL)
359a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick	 return this->lower_temps;
360a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick
361a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      switch (var->mode) {
362a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      case ir_var_auto:
363a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      case ir_var_temporary:
364a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick	 return this->lower_temps;
365a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      case ir_var_uniform:
366a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick	 return this->lower_uniforms;
367a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      case ir_var_in:
368819d57fce94b20fa0d34da6f037f0a53c4a5bdc2Kenneth Graunke      case ir_var_const_in:
369a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick	 return (var->location == -1) ? this->lower_temps : this->lower_inputs;
370a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      case ir_var_out:
371a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick	 return (var->location == -1) ? this->lower_temps : this->lower_outputs;
372a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      case ir_var_inout:
373a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick	 return this->lower_temps;
374a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      }
375a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick
376a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      assert(!"Should not get here.");
377a822ae3f1a14ddd00a6368d767213ea42d00e7fbVinson Lee      return false;
378a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick   }
379a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick
380d2296e784aa8fad81c4910dcbbf61e826ce9a06aIan Romanick   bool needs_lowering(ir_dereference_array *deref) const
381d2296e784aa8fad81c4910dcbbf61e826ce9a06aIan Romanick   {
382d2296e784aa8fad81c4910dcbbf61e826ce9a06aIan Romanick      if (deref == NULL || deref->array_index->as_constant()
383d2296e784aa8fad81c4910dcbbf61e826ce9a06aIan Romanick	  || !is_array_or_matrix(deref->array))
384d2296e784aa8fad81c4910dcbbf61e826ce9a06aIan Romanick	 return false;
385d2296e784aa8fad81c4910dcbbf61e826ce9a06aIan Romanick
386d2296e784aa8fad81c4910dcbbf61e826ce9a06aIan Romanick      return this->storage_type_needs_lowering(deref);
387d2296e784aa8fad81c4910dcbbf61e826ce9a06aIan Romanick   }
388d2296e784aa8fad81c4910dcbbf61e826ce9a06aIan Romanick
389a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   ir_variable *convert_dereference_array(ir_dereference_array *orig_deref,
3901731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick					  ir_assignment* orig_assign,
3911731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick					  ir_dereference *orig_base)
392a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   {
3936e4fe39da26bf101f5fe1103ba426c0903445352Ian Romanick      assert(is_array_or_matrix(orig_deref->array));
3946e4fe39da26bf101f5fe1103ba426c0903445352Ian Romanick
3956e4fe39da26bf101f5fe1103ba426c0903445352Ian Romanick      const unsigned length = (orig_deref->array->type->is_array())
3966e4fe39da26bf101f5fe1103ba426c0903445352Ian Romanick         ? orig_deref->array->type->length
3976e4fe39da26bf101f5fe1103ba426c0903445352Ian Romanick         : orig_deref->array->type->matrix_columns;
398a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
399d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke      void *const mem_ctx = ralloc_parent(base_ir);
400a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
401c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt      /* Temporary storage for either the result of the dereference of
402c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt       * the array, or the RHS that's being assigned into the
403c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt       * dereference of the array.
404c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt       */
405c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt      ir_variable *var;
406c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt
407c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt      if (orig_assign) {
408c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt	 var = new(mem_ctx) ir_variable(orig_assign->rhs->type,
409c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt					"dereference_array_value",
410c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt					ir_var_temporary);
411c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt	 base_ir->insert_before(var);
412c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt
413a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	 ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(var);
414c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt	 ir_assignment *assign = new(mem_ctx) ir_assignment(lhs,
415c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt							    orig_assign->rhs,
416c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt							    NULL);
417a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
418a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         base_ir->insert_before(assign);
419c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt      } else {
420c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt	 var = new(mem_ctx) ir_variable(orig_deref->type,
421c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt					"dereference_array_value",
422c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt					ir_var_temporary);
423c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt	 base_ir->insert_before(var);
424a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      }
425a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
426a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      /* Store the index to a temporary to avoid reusing its tree. */
427a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      ir_variable *index =
428a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	 new(mem_ctx) ir_variable(orig_deref->array_index->type,
429a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri				  "dereference_array_index", ir_var_temporary);
430a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      base_ir->insert_before(index);
431a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
432a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      ir_dereference *lhs = new(mem_ctx) ir_dereference_variable(index);
433a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      ir_assignment *assign =
434a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri	 new(mem_ctx) ir_assignment(lhs, orig_deref->array_index, NULL);
435a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      base_ir->insert_before(assign);
436a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
4371731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      orig_deref->array_index = lhs->clone(mem_ctx, NULL);
4381731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick
439a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      assignment_generator ag;
4401731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      ag.rvalue = orig_base;
441a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      ag.base_ir = base_ir;
4421731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      ag.old_index = index;
443a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      ag.var = var;
444c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt      if (orig_assign) {
445c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt	 ag.is_write = true;
446c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt	 ag.write_mask = orig_assign->write_mask;
447c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt      } else {
448c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt	 ag.is_write = false;
449c00bc13564e432c496aa685d7b3ca7c60165be02Eric Anholt      }
450a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
451a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      switch_generator sg(ag, index, 4, 4);
452a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
4535f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick      /* If the original assignment has a condition, respect that original
4545f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick       * condition!  This is acomplished by wrapping the new conditional
4555f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick       * assignments in an if-statement that uses the original condition.
4565f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick       */
4575f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick      if ((orig_assign != NULL) && (orig_assign->condition != NULL)) {
4585f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick	 /* No need to clone the condition because the IR that it hangs on is
4595f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick	  * going to be removed from the instruction sequence.
4605f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick	  */
4615f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick	 ir_if *if_stmt = new(mem_ctx) ir_if(orig_assign->condition);
4625f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick
4635f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick	 sg.generate(0, length, &if_stmt->then_instructions);
4645f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick	 base_ir->insert_before(if_stmt);
4655f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick      } else {
4665f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick	 exec_list list;
4675f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick
4685f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick	 sg.generate(0, length, &list);
4695f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick	 base_ir->insert_before(&list);
4705f83dfe5b70337bcffe215f7c32d0b862b5e7a3bIan Romanick      }
471a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
472a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      return var;
473a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   }
474a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
475a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   virtual void handle_rvalue(ir_rvalue **pir)
476a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   {
4771731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      if (this->in_assignee)
4781731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick	 return;
4791731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick
480a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      if (!*pir)
481a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         return;
482a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
483a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      ir_dereference_array* orig_deref = (*pir)->as_dereference_array();
484a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick      if (needs_lowering(orig_deref)) {
4851731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick         ir_variable *var =
4861731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick	    convert_dereference_array(orig_deref, NULL, orig_deref);
487a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         assert(var);
488d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke         *pir = new(ralloc_parent(base_ir)) ir_dereference_variable(var);
489a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         this->progress = true;
490a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      }
491a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   }
492a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
493a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   ir_visitor_status
494a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   visit_leave(ir_assignment *ir)
495a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   {
496a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      ir_rvalue_visitor::visit_leave(ir);
497a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
4981731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      find_variable_index f;
4991731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      ir->lhs->accept(&f);
500a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
5011731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      if ((f.deref != NULL) && storage_type_needs_lowering(f.deref)) {
5021731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick         convert_dereference_array(f.deref, ir, ir->lhs);
503a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         ir->remove();
504a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri         this->progress = true;
505a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      }
506a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
507a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri      return visit_continue;
508a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri   }
509a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri};
510a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
511a47539c7a155475de00fa812842721d239abb3f4Luca Barbieribool
512a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanicklower_variable_index_to_cond_assign(exec_list *instructions,
513a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick				    bool lower_input,
514a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick				    bool lower_output,
515a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick				    bool lower_temp,
516a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick				    bool lower_uniform)
517a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri{
518a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick   variable_index_to_cond_assign_visitor v(lower_input,
519a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick					   lower_output,
520a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick					   lower_temp,
521a6ecd1c3724a78b76ab9e81ea39632f1279021f8Ian Romanick					   lower_uniform);
522a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
5231731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   /* Continue lowering until no progress is made.  If there are multiple
5241731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick    * levels of indirection (e.g., non-constant indexing of array elements and
5251731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick    * matrix columns of an array of matrix), each pass will only lower one
5261731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick    * level of indirection.
5271731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick    */
528c1e591eed41b45c0fcf1dcac8b1b8aaeb6237a38Ian Romanick   bool progress_ever = false;
5291731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   do {
5301731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      v.progress = false;
5311731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick      visit_list_elements(&v, instructions);
532c1e591eed41b45c0fcf1dcac8b1b8aaeb6237a38Ian Romanick      progress_ever = v.progress || progress_ever;
5331731ac308631138ca98d34e8b7070c6e3f981939Ian Romanick   } while (v.progress);
534a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri
535c1e591eed41b45c0fcf1dcac8b1b8aaeb6237a38Ian Romanick   return progress_ever;
536a47539c7a155475de00fa812842721d239abb3f4Luca Barbieri}
537