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_function_inlining.cpp
261591693c7b415e9869157c711fe11263c95d74eDavid Li *
271591693c7b415e9869157c711fe11263c95d74eDavid Li * Replaces calls to functions with the body of the function.
281591693c7b415e9869157c711fe11263c95d74eDavid Li */
291591693c7b415e9869157c711fe11263c95d74eDavid Li
301591693c7b415e9869157c711fe11263c95d74eDavid Li#include <inttypes.h>
311591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir.h"
321591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_visitor.h"
331591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_function_inlining.h"
341591693c7b415e9869157c711fe11263c95d74eDavid Li#include "ir_expression_flattening.h"
351591693c7b415e9869157c711fe11263c95d74eDavid Li#include "glsl_types.h"
361591693c7b415e9869157c711fe11263c95d74eDavid Li#include "program/hash_table.h"
371591693c7b415e9869157c711fe11263c95d74eDavid Li
381591693c7b415e9869157c711fe11263c95d74eDavid Listatic void
391591693c7b415e9869157c711fe11263c95d74eDavid Lido_sampler_replacement(exec_list *instructions,
401591693c7b415e9869157c711fe11263c95d74eDavid Li		       ir_variable *sampler,
411591693c7b415e9869157c711fe11263c95d74eDavid Li		       ir_dereference *deref);
421591693c7b415e9869157c711fe11263c95d74eDavid Li
431591693c7b415e9869157c711fe11263c95d74eDavid Liclass ir_function_inlining_visitor : public ir_hierarchical_visitor {
441591693c7b415e9869157c711fe11263c95d74eDavid Lipublic:
451591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_function_inlining_visitor()
461591693c7b415e9869157c711fe11263c95d74eDavid Li   {
471591693c7b415e9869157c711fe11263c95d74eDavid Li      progress = false;
481591693c7b415e9869157c711fe11263c95d74eDavid Li   }
491591693c7b415e9869157c711fe11263c95d74eDavid Li
501591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ~ir_function_inlining_visitor()
511591693c7b415e9869157c711fe11263c95d74eDavid Li   {
521591693c7b415e9869157c711fe11263c95d74eDavid Li      /* empty */
531591693c7b415e9869157c711fe11263c95d74eDavid Li   }
541591693c7b415e9869157c711fe11263c95d74eDavid Li
551591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(ir_expression *);
561591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(ir_call *);
571591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(ir_assignment *);
581591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(ir_return *);
591591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(ir_texture *);
601591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_enter(ir_swizzle *);
611591693c7b415e9869157c711fe11263c95d74eDavid Li
621591693c7b415e9869157c711fe11263c95d74eDavid Li   bool progress;
631591693c7b415e9869157c711fe11263c95d74eDavid Li};
641591693c7b415e9869157c711fe11263c95d74eDavid Li
651591693c7b415e9869157c711fe11263c95d74eDavid Li
661591693c7b415e9869157c711fe11263c95d74eDavid Libool
671591693c7b415e9869157c711fe11263c95d74eDavid Liautomatic_inlining_predicate(ir_instruction *ir)
681591693c7b415e9869157c711fe11263c95d74eDavid Li{
691591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_call *call = ir->as_call();
701591693c7b415e9869157c711fe11263c95d74eDavid Li
711591693c7b415e9869157c711fe11263c95d74eDavid Li   if (call && can_inline(call))
721591693c7b415e9869157c711fe11263c95d74eDavid Li      return true;
731591693c7b415e9869157c711fe11263c95d74eDavid Li
741591693c7b415e9869157c711fe11263c95d74eDavid Li   return false;
751591693c7b415e9869157c711fe11263c95d74eDavid Li}
761591693c7b415e9869157c711fe11263c95d74eDavid Li
771591693c7b415e9869157c711fe11263c95d74eDavid Libool
781591693c7b415e9869157c711fe11263c95d74eDavid Lido_function_inlining(exec_list *instructions)
791591693c7b415e9869157c711fe11263c95d74eDavid Li{
801591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_function_inlining_visitor v;
811591693c7b415e9869157c711fe11263c95d74eDavid Li
821591693c7b415e9869157c711fe11263c95d74eDavid Li   do_expression_flattening(instructions, automatic_inlining_predicate);
831591693c7b415e9869157c711fe11263c95d74eDavid Li
841591693c7b415e9869157c711fe11263c95d74eDavid Li   v.run(instructions);
851591693c7b415e9869157c711fe11263c95d74eDavid Li
861591693c7b415e9869157c711fe11263c95d74eDavid Li   return v.progress;
871591693c7b415e9869157c711fe11263c95d74eDavid Li}
881591693c7b415e9869157c711fe11263c95d74eDavid Li
891591693c7b415e9869157c711fe11263c95d74eDavid Listatic void
901591693c7b415e9869157c711fe11263c95d74eDavid Lireplace_return_with_assignment(ir_instruction *ir, void *data)
911591693c7b415e9869157c711fe11263c95d74eDavid Li{
92d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li   void *ctx = hieralloc_parent(ir);
931591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable *retval = (ir_variable *)data;
941591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_return *ret = ir->as_return();
951591693c7b415e9869157c711fe11263c95d74eDavid Li
961591693c7b415e9869157c711fe11263c95d74eDavid Li   if (ret) {
971591693c7b415e9869157c711fe11263c95d74eDavid Li      if (ret->value) {
981591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_rvalue *lhs = new(ctx) ir_dereference_variable(retval);
991591693c7b415e9869157c711fe11263c95d74eDavid Li	 ret->replace_with(new(ctx) ir_assignment(lhs, ret->value, NULL));
1001591693c7b415e9869157c711fe11263c95d74eDavid Li      } else {
1011591693c7b415e9869157c711fe11263c95d74eDavid Li	 /* un-valued return has to be the last return, or we shouldn't
1021591693c7b415e9869157c711fe11263c95d74eDavid Li	  * have reached here. (see can_inline()).
1031591693c7b415e9869157c711fe11263c95d74eDavid Li	  */
1041591693c7b415e9869157c711fe11263c95d74eDavid Li	 assert(ret->next->is_tail_sentinel());
1051591693c7b415e9869157c711fe11263c95d74eDavid Li	 ret->remove();
1061591693c7b415e9869157c711fe11263c95d74eDavid Li      }
1071591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1081591693c7b415e9869157c711fe11263c95d74eDavid Li}
1091591693c7b415e9869157c711fe11263c95d74eDavid Li
1101591693c7b415e9869157c711fe11263c95d74eDavid Liir_rvalue *
1111591693c7b415e9869157c711fe11263c95d74eDavid Liir_call::generate_inline(ir_instruction *next_ir)
1121591693c7b415e9869157c711fe11263c95d74eDavid Li{
113d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li   void *ctx = hieralloc_parent(this);
1141591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable **parameters;
1151591693c7b415e9869157c711fe11263c95d74eDavid Li   int num_parameters;
1161591693c7b415e9869157c711fe11263c95d74eDavid Li   int i;
1171591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable *retval = NULL;
1181591693c7b415e9869157c711fe11263c95d74eDavid Li   struct hash_table *ht;
1191591693c7b415e9869157c711fe11263c95d74eDavid Li
1201591693c7b415e9869157c711fe11263c95d74eDavid Li   ht = hash_table_ctor(0, hash_table_pointer_hash, hash_table_pointer_compare);
1211591693c7b415e9869157c711fe11263c95d74eDavid Li
1221591693c7b415e9869157c711fe11263c95d74eDavid Li   num_parameters = 0;
1231591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, iter_sig, this->callee->parameters)
1241591693c7b415e9869157c711fe11263c95d74eDavid Li      num_parameters++;
1251591693c7b415e9869157c711fe11263c95d74eDavid Li
1261591693c7b415e9869157c711fe11263c95d74eDavid Li   parameters = new ir_variable *[num_parameters];
1271591693c7b415e9869157c711fe11263c95d74eDavid Li
1281591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Generate storage for the return value. */
1291591693c7b415e9869157c711fe11263c95d74eDavid Li   if (this->callee->return_type) {
1301591693c7b415e9869157c711fe11263c95d74eDavid Li      retval = new(ctx) ir_variable(this->callee->return_type, "_ret_val",
1311591693c7b415e9869157c711fe11263c95d74eDavid Li				    ir_var_auto);
1321591693c7b415e9869157c711fe11263c95d74eDavid Li      next_ir->insert_before(retval);
1331591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1341591693c7b415e9869157c711fe11263c95d74eDavid Li
1351591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Generate the declarations for the parameters to our inlined code,
1361591693c7b415e9869157c711fe11263c95d74eDavid Li    * and set up the mapping of real function body variables to ours.
1371591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1381591693c7b415e9869157c711fe11263c95d74eDavid Li   i = 0;
1391591693c7b415e9869157c711fe11263c95d74eDavid Li   exec_list_iterator sig_param_iter = this->callee->parameters.iterator();
1401591693c7b415e9869157c711fe11263c95d74eDavid Li   exec_list_iterator param_iter = this->actual_parameters.iterator();
1411591693c7b415e9869157c711fe11263c95d74eDavid Li   for (i = 0; i < num_parameters; i++) {
1421591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
1431591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_rvalue *param = (ir_rvalue *) param_iter.get();
1441591693c7b415e9869157c711fe11263c95d74eDavid Li
1451591693c7b415e9869157c711fe11263c95d74eDavid Li      /* Generate a new variable for the parameter. */
1461591693c7b415e9869157c711fe11263c95d74eDavid Li      if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) {
1471591693c7b415e9869157c711fe11263c95d74eDavid Li	 /* For samplers, we want the inlined sampler references
1481591693c7b415e9869157c711fe11263c95d74eDavid Li	  * referencing the passed in sampler variable, since that
1491591693c7b415e9869157c711fe11263c95d74eDavid Li	  * will have the location information, which an assignment of
1501591693c7b415e9869157c711fe11263c95d74eDavid Li	  * a sampler wouldn't.  Fix it up below.
1511591693c7b415e9869157c711fe11263c95d74eDavid Li	  */
1521591693c7b415e9869157c711fe11263c95d74eDavid Li	 parameters[i] = NULL;
1531591693c7b415e9869157c711fe11263c95d74eDavid Li      } else {
1541591693c7b415e9869157c711fe11263c95d74eDavid Li	 parameters[i] = sig_param->clone(ctx, ht);
1551591693c7b415e9869157c711fe11263c95d74eDavid Li	 parameters[i]->mode = ir_var_auto;
1561591693c7b415e9869157c711fe11263c95d74eDavid Li
1571591693c7b415e9869157c711fe11263c95d74eDavid Li	 /* Remove the read-only decoration becuase we're going to write
1581591693c7b415e9869157c711fe11263c95d74eDavid Li	  * directly to this variable.  If the cloned variable is left
1591591693c7b415e9869157c711fe11263c95d74eDavid Li	  * read-only and the inlined function is inside a loop, the loop
1601591693c7b415e9869157c711fe11263c95d74eDavid Li	  * analysis code will get confused.
1611591693c7b415e9869157c711fe11263c95d74eDavid Li	  */
1621591693c7b415e9869157c711fe11263c95d74eDavid Li	 parameters[i]->read_only = false;
1631591693c7b415e9869157c711fe11263c95d74eDavid Li	 next_ir->insert_before(parameters[i]);
1641591693c7b415e9869157c711fe11263c95d74eDavid Li      }
1651591693c7b415e9869157c711fe11263c95d74eDavid Li
1661591693c7b415e9869157c711fe11263c95d74eDavid Li      /* Move the actual param into our param variable if it's an 'in' type. */
1671591693c7b415e9869157c711fe11263c95d74eDavid Li      if (parameters[i] && (sig_param->mode == ir_var_in ||
1681591693c7b415e9869157c711fe11263c95d74eDavid Li			    sig_param->mode == ir_var_inout)) {
1691591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_assignment *assign;
1701591693c7b415e9869157c711fe11263c95d74eDavid Li
1711591693c7b415e9869157c711fe11263c95d74eDavid Li	 assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(parameters[i]),
1721591693c7b415e9869157c711fe11263c95d74eDavid Li					 param, NULL);
1731591693c7b415e9869157c711fe11263c95d74eDavid Li	 next_ir->insert_before(assign);
1741591693c7b415e9869157c711fe11263c95d74eDavid Li      }
1751591693c7b415e9869157c711fe11263c95d74eDavid Li
1761591693c7b415e9869157c711fe11263c95d74eDavid Li      sig_param_iter.next();
1771591693c7b415e9869157c711fe11263c95d74eDavid Li      param_iter.next();
1781591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1791591693c7b415e9869157c711fe11263c95d74eDavid Li
1801591693c7b415e9869157c711fe11263c95d74eDavid Li   exec_list new_instructions;
1811591693c7b415e9869157c711fe11263c95d74eDavid Li
1821591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Generate the inlined body of the function to a new list */
1831591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, iter, callee->body) {
1841591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_instruction *ir = (ir_instruction *)iter.get();
1851591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_instruction *new_ir = ir->clone(ctx, ht);
1861591693c7b415e9869157c711fe11263c95d74eDavid Li
1871591693c7b415e9869157c711fe11263c95d74eDavid Li      new_instructions.push_tail(new_ir);
1881591693c7b415e9869157c711fe11263c95d74eDavid Li      visit_tree(new_ir, replace_return_with_assignment, retval);
1891591693c7b415e9869157c711fe11263c95d74eDavid Li   }
1901591693c7b415e9869157c711fe11263c95d74eDavid Li
1911591693c7b415e9869157c711fe11263c95d74eDavid Li   /* If any samplers were passed in, replace any deref of the sampler
1921591693c7b415e9869157c711fe11263c95d74eDavid Li    * with a deref of the sampler argument.
1931591693c7b415e9869157c711fe11263c95d74eDavid Li    */
1941591693c7b415e9869157c711fe11263c95d74eDavid Li   param_iter = this->actual_parameters.iterator();
1951591693c7b415e9869157c711fe11263c95d74eDavid Li   sig_param_iter = this->callee->parameters.iterator();
1961591693c7b415e9869157c711fe11263c95d74eDavid Li   for (i = 0; i < num_parameters; i++) {
1971591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_instruction *const param = (ir_instruction *) param_iter.get();
1981591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_variable *sig_param = (ir_variable *) sig_param_iter.get();
1991591693c7b415e9869157c711fe11263c95d74eDavid Li
2001591693c7b415e9869157c711fe11263c95d74eDavid Li      if (sig_param->type->base_type == GLSL_TYPE_SAMPLER) {
2011591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_dereference *deref = param->as_dereference();
2021591693c7b415e9869157c711fe11263c95d74eDavid Li
2031591693c7b415e9869157c711fe11263c95d74eDavid Li	 assert(deref);
2041591693c7b415e9869157c711fe11263c95d74eDavid Li	 do_sampler_replacement(&new_instructions, sig_param, deref);
2051591693c7b415e9869157c711fe11263c95d74eDavid Li      }
2061591693c7b415e9869157c711fe11263c95d74eDavid Li      param_iter.next();
2071591693c7b415e9869157c711fe11263c95d74eDavid Li      sig_param_iter.next();
2081591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2091591693c7b415e9869157c711fe11263c95d74eDavid Li
2101591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Now push those new instructions in. */
2111591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, iter, new_instructions) {
2121591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_instruction *ir = (ir_instruction *)iter.get();
2131591693c7b415e9869157c711fe11263c95d74eDavid Li      next_ir->insert_before(ir);
2141591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2151591693c7b415e9869157c711fe11263c95d74eDavid Li
2161591693c7b415e9869157c711fe11263c95d74eDavid Li   /* Copy back the value of any 'out' parameters from the function body
2171591693c7b415e9869157c711fe11263c95d74eDavid Li    * variables to our own.
2181591693c7b415e9869157c711fe11263c95d74eDavid Li    */
2191591693c7b415e9869157c711fe11263c95d74eDavid Li   i = 0;
2201591693c7b415e9869157c711fe11263c95d74eDavid Li   param_iter = this->actual_parameters.iterator();
2211591693c7b415e9869157c711fe11263c95d74eDavid Li   sig_param_iter = this->callee->parameters.iterator();
2221591693c7b415e9869157c711fe11263c95d74eDavid Li   for (i = 0; i < num_parameters; i++) {
2231591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_instruction *const param = (ir_instruction *) param_iter.get();
2241591693c7b415e9869157c711fe11263c95d74eDavid Li      const ir_variable *const sig_param = (ir_variable *) sig_param_iter.get();
2251591693c7b415e9869157c711fe11263c95d74eDavid Li
2261591693c7b415e9869157c711fe11263c95d74eDavid Li      /* Move our param variable into the actual param if it's an 'out' type. */
2271591693c7b415e9869157c711fe11263c95d74eDavid Li      if (parameters[i] && (sig_param->mode == ir_var_out ||
2281591693c7b415e9869157c711fe11263c95d74eDavid Li			    sig_param->mode == ir_var_inout)) {
2291591693c7b415e9869157c711fe11263c95d74eDavid Li	 ir_assignment *assign;
2301591693c7b415e9869157c711fe11263c95d74eDavid Li
2311591693c7b415e9869157c711fe11263c95d74eDavid Li	 assign = new(ctx) ir_assignment(param->clone(ctx, NULL)->as_rvalue(),
2321591693c7b415e9869157c711fe11263c95d74eDavid Li					 new(ctx) ir_dereference_variable(parameters[i]),
2331591693c7b415e9869157c711fe11263c95d74eDavid Li					 NULL);
2341591693c7b415e9869157c711fe11263c95d74eDavid Li	 next_ir->insert_before(assign);
2351591693c7b415e9869157c711fe11263c95d74eDavid Li      }
2361591693c7b415e9869157c711fe11263c95d74eDavid Li
2371591693c7b415e9869157c711fe11263c95d74eDavid Li      param_iter.next();
2381591693c7b415e9869157c711fe11263c95d74eDavid Li      sig_param_iter.next();
2391591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2401591693c7b415e9869157c711fe11263c95d74eDavid Li
2411591693c7b415e9869157c711fe11263c95d74eDavid Li   delete [] parameters;
2421591693c7b415e9869157c711fe11263c95d74eDavid Li
2431591693c7b415e9869157c711fe11263c95d74eDavid Li   hash_table_dtor(ht);
2441591693c7b415e9869157c711fe11263c95d74eDavid Li
2451591693c7b415e9869157c711fe11263c95d74eDavid Li   if (retval)
2461591693c7b415e9869157c711fe11263c95d74eDavid Li      return new(ctx) ir_dereference_variable(retval);
2471591693c7b415e9869157c711fe11263c95d74eDavid Li   else
2481591693c7b415e9869157c711fe11263c95d74eDavid Li      return NULL;
2491591693c7b415e9869157c711fe11263c95d74eDavid Li}
2501591693c7b415e9869157c711fe11263c95d74eDavid Li
2511591693c7b415e9869157c711fe11263c95d74eDavid Li
2521591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
2531591693c7b415e9869157c711fe11263c95d74eDavid Liir_function_inlining_visitor::visit_enter(ir_expression *ir)
2541591693c7b415e9869157c711fe11263c95d74eDavid Li{
2551591693c7b415e9869157c711fe11263c95d74eDavid Li   (void) ir;
2561591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue_with_parent;
2571591693c7b415e9869157c711fe11263c95d74eDavid Li}
2581591693c7b415e9869157c711fe11263c95d74eDavid Li
2591591693c7b415e9869157c711fe11263c95d74eDavid Li
2601591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
2611591693c7b415e9869157c711fe11263c95d74eDavid Liir_function_inlining_visitor::visit_enter(ir_return *ir)
2621591693c7b415e9869157c711fe11263c95d74eDavid Li{
2631591693c7b415e9869157c711fe11263c95d74eDavid Li   (void) ir;
2641591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue_with_parent;
2651591693c7b415e9869157c711fe11263c95d74eDavid Li}
2661591693c7b415e9869157c711fe11263c95d74eDavid Li
2671591693c7b415e9869157c711fe11263c95d74eDavid Li
2681591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
2691591693c7b415e9869157c711fe11263c95d74eDavid Liir_function_inlining_visitor::visit_enter(ir_texture *ir)
2701591693c7b415e9869157c711fe11263c95d74eDavid Li{
2711591693c7b415e9869157c711fe11263c95d74eDavid Li   (void) ir;
2721591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue_with_parent;
2731591693c7b415e9869157c711fe11263c95d74eDavid Li}
2741591693c7b415e9869157c711fe11263c95d74eDavid Li
2751591693c7b415e9869157c711fe11263c95d74eDavid Li
2761591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
2771591693c7b415e9869157c711fe11263c95d74eDavid Liir_function_inlining_visitor::visit_enter(ir_swizzle *ir)
2781591693c7b415e9869157c711fe11263c95d74eDavid Li{
2791591693c7b415e9869157c711fe11263c95d74eDavid Li   (void) ir;
2801591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue_with_parent;
2811591693c7b415e9869157c711fe11263c95d74eDavid Li}
2821591693c7b415e9869157c711fe11263c95d74eDavid Li
2831591693c7b415e9869157c711fe11263c95d74eDavid Li
2841591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
2851591693c7b415e9869157c711fe11263c95d74eDavid Liir_function_inlining_visitor::visit_enter(ir_call *ir)
2861591693c7b415e9869157c711fe11263c95d74eDavid Li{
2871591693c7b415e9869157c711fe11263c95d74eDavid Li   if (can_inline(ir)) {
2881591693c7b415e9869157c711fe11263c95d74eDavid Li      /* If the call was part of some tree, then it should have been
2891591693c7b415e9869157c711fe11263c95d74eDavid Li       * flattened out or we shouldn't have seen it because of a
2901591693c7b415e9869157c711fe11263c95d74eDavid Li       * visit_continue_with_parent in this visitor.
2911591693c7b415e9869157c711fe11263c95d74eDavid Li       */
2921591693c7b415e9869157c711fe11263c95d74eDavid Li      assert(ir == base_ir);
2931591693c7b415e9869157c711fe11263c95d74eDavid Li
2941591693c7b415e9869157c711fe11263c95d74eDavid Li      (void) ir->generate_inline(ir);
2951591693c7b415e9869157c711fe11263c95d74eDavid Li      ir->remove();
2961591693c7b415e9869157c711fe11263c95d74eDavid Li      this->progress = true;
2971591693c7b415e9869157c711fe11263c95d74eDavid Li   }
2981591693c7b415e9869157c711fe11263c95d74eDavid Li
2991591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
3001591693c7b415e9869157c711fe11263c95d74eDavid Li}
3011591693c7b415e9869157c711fe11263c95d74eDavid Li
3021591693c7b415e9869157c711fe11263c95d74eDavid Li
3031591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
3041591693c7b415e9869157c711fe11263c95d74eDavid Liir_function_inlining_visitor::visit_enter(ir_assignment *ir)
3051591693c7b415e9869157c711fe11263c95d74eDavid Li{
3061591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_call *call = ir->rhs->as_call();
3071591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!call || !can_inline(call))
3081591693c7b415e9869157c711fe11263c95d74eDavid Li      return visit_continue;
3091591693c7b415e9869157c711fe11263c95d74eDavid Li
3101591693c7b415e9869157c711fe11263c95d74eDavid Li   /* generates the parameter setup, function body, and returns the return
3111591693c7b415e9869157c711fe11263c95d74eDavid Li    * value of the function
3121591693c7b415e9869157c711fe11263c95d74eDavid Li    */
3131591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_rvalue *rhs = call->generate_inline(ir);
3141591693c7b415e9869157c711fe11263c95d74eDavid Li   assert(rhs);
3151591693c7b415e9869157c711fe11263c95d74eDavid Li
3161591693c7b415e9869157c711fe11263c95d74eDavid Li   ir->rhs = rhs;
3171591693c7b415e9869157c711fe11263c95d74eDavid Li   this->progress = true;
3181591693c7b415e9869157c711fe11263c95d74eDavid Li
3191591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
3201591693c7b415e9869157c711fe11263c95d74eDavid Li}
3211591693c7b415e9869157c711fe11263c95d74eDavid Li
3221591693c7b415e9869157c711fe11263c95d74eDavid Li/**
3231591693c7b415e9869157c711fe11263c95d74eDavid Li * Replaces references to the "sampler" variable with a clone of "deref."
3241591693c7b415e9869157c711fe11263c95d74eDavid Li *
3251591693c7b415e9869157c711fe11263c95d74eDavid Li * From the spec, samplers can appear in the tree as function
3261591693c7b415e9869157c711fe11263c95d74eDavid Li * (non-out) parameters and as the result of array indexing and
3271591693c7b415e9869157c711fe11263c95d74eDavid Li * structure field selection.  In our builtin implementation, they
3281591693c7b415e9869157c711fe11263c95d74eDavid Li * also appear in the sampler field of an ir_tex instruction.
3291591693c7b415e9869157c711fe11263c95d74eDavid Li */
3301591693c7b415e9869157c711fe11263c95d74eDavid Li
3311591693c7b415e9869157c711fe11263c95d74eDavid Liclass ir_sampler_replacement_visitor : public ir_hierarchical_visitor {
3321591693c7b415e9869157c711fe11263c95d74eDavid Lipublic:
3331591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_sampler_replacement_visitor(ir_variable *sampler, ir_dereference *deref)
3341591693c7b415e9869157c711fe11263c95d74eDavid Li   {
3351591693c7b415e9869157c711fe11263c95d74eDavid Li      this->sampler = sampler;
3361591693c7b415e9869157c711fe11263c95d74eDavid Li      this->deref = deref;
3371591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3381591693c7b415e9869157c711fe11263c95d74eDavid Li
3391591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ~ir_sampler_replacement_visitor()
3401591693c7b415e9869157c711fe11263c95d74eDavid Li   {
3411591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3421591693c7b415e9869157c711fe11263c95d74eDavid Li
3431591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(ir_call *);
3441591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(ir_dereference_array *);
3451591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(ir_dereference_record *);
3461591693c7b415e9869157c711fe11263c95d74eDavid Li   virtual ir_visitor_status visit_leave(ir_texture *);
3471591693c7b415e9869157c711fe11263c95d74eDavid Li
3481591693c7b415e9869157c711fe11263c95d74eDavid Li   void replace_deref(ir_dereference **deref);
3491591693c7b415e9869157c711fe11263c95d74eDavid Li   void replace_rvalue(ir_rvalue **rvalue);
3501591693c7b415e9869157c711fe11263c95d74eDavid Li
3511591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_variable *sampler;
3521591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference *deref;
3531591693c7b415e9869157c711fe11263c95d74eDavid Li};
3541591693c7b415e9869157c711fe11263c95d74eDavid Li
3551591693c7b415e9869157c711fe11263c95d74eDavid Livoid
3561591693c7b415e9869157c711fe11263c95d74eDavid Liir_sampler_replacement_visitor::replace_deref(ir_dereference **deref)
3571591693c7b415e9869157c711fe11263c95d74eDavid Li{
3581591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference_variable *deref_var = (*deref)->as_dereference_variable();
3591591693c7b415e9869157c711fe11263c95d74eDavid Li   if (deref_var && deref_var->var == this->sampler) {
360d50d9a90a0df4d706421850e17c0fbd85bf710eeDavid Li      *deref = this->deref->clone(hieralloc_parent(*deref), NULL);
3611591693c7b415e9869157c711fe11263c95d74eDavid Li   }
3621591693c7b415e9869157c711fe11263c95d74eDavid Li}
3631591693c7b415e9869157c711fe11263c95d74eDavid Li
3641591693c7b415e9869157c711fe11263c95d74eDavid Livoid
3651591693c7b415e9869157c711fe11263c95d74eDavid Liir_sampler_replacement_visitor::replace_rvalue(ir_rvalue **rvalue)
3661591693c7b415e9869157c711fe11263c95d74eDavid Li{
3671591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!*rvalue)
3681591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
3691591693c7b415e9869157c711fe11263c95d74eDavid Li
3701591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_dereference *deref = (*rvalue)->as_dereference();
3711591693c7b415e9869157c711fe11263c95d74eDavid Li
3721591693c7b415e9869157c711fe11263c95d74eDavid Li   if (!deref)
3731591693c7b415e9869157c711fe11263c95d74eDavid Li      return;
3741591693c7b415e9869157c711fe11263c95d74eDavid Li
3751591693c7b415e9869157c711fe11263c95d74eDavid Li   replace_deref(&deref);
3761591693c7b415e9869157c711fe11263c95d74eDavid Li   *rvalue = deref;
3771591693c7b415e9869157c711fe11263c95d74eDavid Li}
3781591693c7b415e9869157c711fe11263c95d74eDavid Li
3791591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
3801591693c7b415e9869157c711fe11263c95d74eDavid Liir_sampler_replacement_visitor::visit_leave(ir_texture *ir)
3811591693c7b415e9869157c711fe11263c95d74eDavid Li{
3821591693c7b415e9869157c711fe11263c95d74eDavid Li   replace_deref(&ir->sampler);
3831591693c7b415e9869157c711fe11263c95d74eDavid Li
3841591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
3851591693c7b415e9869157c711fe11263c95d74eDavid Li}
3861591693c7b415e9869157c711fe11263c95d74eDavid Li
3871591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
3881591693c7b415e9869157c711fe11263c95d74eDavid Liir_sampler_replacement_visitor::visit_leave(ir_dereference_array *ir)
3891591693c7b415e9869157c711fe11263c95d74eDavid Li{
3901591693c7b415e9869157c711fe11263c95d74eDavid Li   replace_rvalue(&ir->array);
3911591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
3921591693c7b415e9869157c711fe11263c95d74eDavid Li}
3931591693c7b415e9869157c711fe11263c95d74eDavid Li
3941591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
3951591693c7b415e9869157c711fe11263c95d74eDavid Liir_sampler_replacement_visitor::visit_leave(ir_dereference_record *ir)
3961591693c7b415e9869157c711fe11263c95d74eDavid Li{
3971591693c7b415e9869157c711fe11263c95d74eDavid Li   replace_rvalue(&ir->record);
3981591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
3991591693c7b415e9869157c711fe11263c95d74eDavid Li}
4001591693c7b415e9869157c711fe11263c95d74eDavid Li
4011591693c7b415e9869157c711fe11263c95d74eDavid Liir_visitor_status
4021591693c7b415e9869157c711fe11263c95d74eDavid Liir_sampler_replacement_visitor::visit_leave(ir_call *ir)
4031591693c7b415e9869157c711fe11263c95d74eDavid Li{
4041591693c7b415e9869157c711fe11263c95d74eDavid Li   foreach_iter(exec_list_iterator, iter, *ir) {
4051591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_rvalue *param = (ir_rvalue *)iter.get();
4061591693c7b415e9869157c711fe11263c95d74eDavid Li      ir_rvalue *new_param = param;
4071591693c7b415e9869157c711fe11263c95d74eDavid Li      replace_rvalue(&new_param);
4081591693c7b415e9869157c711fe11263c95d74eDavid Li
4091591693c7b415e9869157c711fe11263c95d74eDavid Li      if (new_param != param) {
4101591693c7b415e9869157c711fe11263c95d74eDavid Li	 param->replace_with(new_param);
4111591693c7b415e9869157c711fe11263c95d74eDavid Li      }
4121591693c7b415e9869157c711fe11263c95d74eDavid Li   }
4131591693c7b415e9869157c711fe11263c95d74eDavid Li   return visit_continue;
4141591693c7b415e9869157c711fe11263c95d74eDavid Li}
4151591693c7b415e9869157c711fe11263c95d74eDavid Li
4161591693c7b415e9869157c711fe11263c95d74eDavid Listatic void
4171591693c7b415e9869157c711fe11263c95d74eDavid Lido_sampler_replacement(exec_list *instructions,
4181591693c7b415e9869157c711fe11263c95d74eDavid Li		       ir_variable *sampler,
4191591693c7b415e9869157c711fe11263c95d74eDavid Li		       ir_dereference *deref)
4201591693c7b415e9869157c711fe11263c95d74eDavid Li{
4211591693c7b415e9869157c711fe11263c95d74eDavid Li   ir_sampler_replacement_visitor v(sampler, deref);
4221591693c7b415e9869157c711fe11263c95d74eDavid Li
4231591693c7b415e9869157c711fe11263c95d74eDavid Li   visit_list_elements(&v, instructions);
4241591693c7b415e9869157c711fe11263c95d74eDavid Li}
425