10d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt/*
20d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * Copyright © 2010 Intel Corporation
30d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt *
40d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * Permission is hereby granted, free of charge, to any person obtaining a
50d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * copy of this software and associated documentation files (the "Software"),
60d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * to deal in the Software without restriction, including without limitation
70d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
80d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * and/or sell copies of the Software, and to permit persons to whom the
90d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * Software is furnished to do so, subject to the following conditions:
100d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt *
110d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * The above copyright notice and this permission notice (including the next
120d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * paragraph) shall be included in all copies or substantial portions of the
130d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * Software.
140d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt *
150d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
160d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
170d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
180d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
190d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
200d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
210d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * DEALINGS IN THE SOFTWARE.
220d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt */
230d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
240d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt/**
250d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * \file ir_expression_flattening.cpp
260d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt *
270d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * Takes the leaves of expression trees and makes them dereferences of
280d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * assignments of the leaves to temporaries, according to a predicate.
290d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt *
30ced54dcf9b496dbe0bf254673ecee37014c1ee3bKenneth Graunke * This is used for breaking down matrix operations, where it's easier to
31ced54dcf9b496dbe0bf254673ecee37014c1ee3bKenneth Graunke * create a temporary and work on each of its vector components individually.
320d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt */
330d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
340d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt#include "ir.h"
350d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt#include "ir_visitor.h"
369fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholt#include "ir_rvalue_visitor.h"
370d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt#include "ir_expression_flattening.h"
380d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt#include "glsl_types.h"
390d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
409fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholtclass ir_expression_flattening_visitor : public ir_rvalue_visitor {
410d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholtpublic:
429fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholt   ir_expression_flattening_visitor(bool (*predicate)(ir_instruction *ir))
430d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   {
440d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt      this->predicate = predicate;
450d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   }
460d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
470d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   virtual ~ir_expression_flattening_visitor()
480d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   {
490d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt      /* empty */
500d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   }
510d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
529fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholt   void handle_rvalue(ir_rvalue **rvalue);
530d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   bool (*predicate)(ir_instruction *ir);
540d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt};
550d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
560d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholtvoid
570d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholtdo_expression_flattening(exec_list *instructions,
580d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt			 bool (*predicate)(ir_instruction *ir))
590d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt{
609fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholt   ir_expression_flattening_visitor v(predicate);
619fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholt
620d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   foreach_iter(exec_list_iterator, iter, *instructions) {
630d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt      ir_instruction *ir = (ir_instruction *)iter.get();
640d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
650d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt      ir->accept(&v);
660d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   }
670d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt}
680d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
699fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholtvoid
709fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholtir_expression_flattening_visitor::handle_rvalue(ir_rvalue **rvalue)
71f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt{
72f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   ir_variable *var;
73f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   ir_assignment *assign;
749fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholt   ir_rvalue *ir = *rvalue;
759fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholt
769fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholt   if (!ir || !this->predicate(ir))
779fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholt      return;
78f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt
79d3073f58c17d8675a2ecdd5dfa83e5520c78e1a8Kenneth Graunke   void *ctx = ralloc_parent(ir);
805723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt
817e2aa91507a5883e33473e0a94215ee3985baad1Ian Romanick   var = new(ctx) ir_variable(ir->type, "flattening_tmp", ir_var_temporary);
82f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   base_ir->insert_before(var);
83f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt
841660a2954797e056caba319c5d6c70b0d4be22feCarl Worth   assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
851660a2954797e056caba319c5d6c70b0d4be22feCarl Worth				   ir,
861660a2954797e056caba319c5d6c70b0d4be22feCarl Worth				   NULL);
87f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   base_ir->insert_before(assign);
88f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt
899fd2a8d6923a8a7218a714622586bb1dbaaebad5Eric Anholt   *rvalue = new(ctx) ir_dereference_variable(var);
900d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt}
91