ir_expression_flattening.cpp revision 5723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8
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 *
300d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * This is used for automatic function inlining, where we want to take
310d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * an expression containing a call and move the call out to its own
320d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * assignment so that we can inline it at the appropriate place in the
330d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt * instruction stream.
340d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt */
350d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
360d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt#include "ir.h"
370d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt#include "ir_visitor.h"
380d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt#include "ir_expression_flattening.h"
390d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt#include "glsl_types.h"
400d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
414b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanickclass ir_expression_flattening_visitor : public ir_hierarchical_visitor {
420d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholtpublic:
430d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   ir_expression_flattening_visitor(ir_instruction *base_ir,
440d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt				    bool (*predicate)(ir_instruction *ir))
450d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   {
460d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt      this->base_ir = base_ir;
470d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt      this->predicate = predicate;
480d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   }
490d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
500d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   virtual ~ir_expression_flattening_visitor()
510d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   {
520d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt      /* empty */
530d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   }
540d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
554b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick   virtual ir_visitor_status visit_enter(ir_call *);
564b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick   virtual ir_visitor_status visit_enter(ir_return *);
57459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt   virtual ir_visitor_status visit_enter(ir_function_signature *);
58459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt   virtual ir_visitor_status visit_enter(ir_if *);
59459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt   virtual ir_visitor_status visit_enter(ir_loop *);
605723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt   virtual ir_visitor_status visit_leave(ir_assignment *);
614b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick   virtual ir_visitor_status visit_leave(ir_expression *);
62f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   virtual ir_visitor_status visit_leave(ir_swizzle *);
630d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
645723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt   ir_rvalue *operand_to_temp(ir_rvalue *val);
650d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   bool (*predicate)(ir_instruction *ir);
660d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   ir_instruction *base_ir;
670d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt};
680d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
690d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholtvoid
700d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholtdo_expression_flattening(exec_list *instructions,
710d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt			 bool (*predicate)(ir_instruction *ir))
720d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt{
730d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   foreach_iter(exec_list_iterator, iter, *instructions) {
740d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt      ir_instruction *ir = (ir_instruction *)iter.get();
750d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
760d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt      ir_expression_flattening_visitor v(ir, predicate);
770d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt      ir->accept(&v);
780d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   }
790d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt}
800d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
81f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt
825723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholtir_rvalue *
835723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholtir_expression_flattening_visitor::operand_to_temp(ir_rvalue *ir)
84f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt{
851660a2954797e056caba319c5d6c70b0d4be22feCarl Worth   void *ctx = talloc_parent(base_ir);
86f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   ir_variable *var;
87f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   ir_assignment *assign;
88f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt
895723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt   if (!this->predicate(ir))
905723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt      return ir;
915723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt
921660a2954797e056caba319c5d6c70b0d4be22feCarl Worth   var = new(ctx) ir_variable(ir->type, "flattening_tmp");
93f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   base_ir->insert_before(var);
94f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt
951660a2954797e056caba319c5d6c70b0d4be22feCarl Worth   assign = new(ctx) ir_assignment(new(ctx) ir_dereference_variable(var),
961660a2954797e056caba319c5d6c70b0d4be22feCarl Worth				   ir,
971660a2954797e056caba319c5d6c70b0d4be22feCarl Worth				   NULL);
98f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   base_ir->insert_before(assign);
99f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt
1001660a2954797e056caba319c5d6c70b0d4be22feCarl Worth   return new(ctx) ir_dereference_variable(var);
101f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt}
102f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt
1034b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanickir_visitor_status
104459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholtir_expression_flattening_visitor::visit_enter(ir_function_signature *ir)
105459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt{
106459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt   do_expression_flattening(&ir->body, this->predicate);
107459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt
108459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt   return visit_continue_with_parent;
109459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt}
110459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt
111459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholtir_visitor_status
112459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholtir_expression_flattening_visitor::visit_enter(ir_loop *ir)
113459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt{
114459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt   do_expression_flattening(&ir->body_instructions, this->predicate);
115459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt
116459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt   return visit_continue_with_parent;
117459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt}
118459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt
119459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholtir_visitor_status
120459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholtir_expression_flattening_visitor::visit_enter(ir_if *ir)
121459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt{
122459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt   ir->condition->accept(this);
123459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt
124459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt   do_expression_flattening(&ir->then_instructions, this->predicate);
125459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt   do_expression_flattening(&ir->else_instructions, this->predicate);
126459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt
127459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt   return visit_continue_with_parent;
128459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt}
129459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholt
130459e4a286cce4fa8d52e4f6e157f4c6df46de695Eric Anholtir_visitor_status
1314b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanickir_expression_flattening_visitor::visit_leave(ir_expression *ir)
1320d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt{
1330d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   unsigned int operand;
1340d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
1350d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   for (operand = 0; operand < ir->get_num_operands(); operand++) {
1360d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt      /* If the operand matches the predicate, then we'll assign its
1370d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt       * value to a temporary and deref the temporary as the operand.
1380d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt       */
1395723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt      ir->operands[operand] = operand_to_temp(ir->operands[operand]);
1400d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   }
1410d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
1424b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick   return visit_continue;
143c7b1046a9fa6da916f11fb9e43d61fd772470183Ian Romanick}
144c7b1046a9fa6da916f11fb9e43d61fd772470183Ian Romanick
145f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholtir_visitor_status
1465723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholtir_expression_flattening_visitor::visit_leave(ir_assignment *ir)
1475723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt{
1485723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt   ir->rhs = operand_to_temp(ir->rhs);
1495723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt   if (ir->condition)
1505723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt      ir->condition = operand_to_temp(ir->condition);
1515723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt
1525723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt   return visit_continue;
1535723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt}
1545723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt
1555723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholtir_visitor_status
156f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholtir_expression_flattening_visitor::visit_leave(ir_swizzle *ir)
157f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt{
158f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   if (this->predicate(ir->val)) {
1595723e5bb8b73cd2a3b77d750972e3d0b4d0d0ff8Eric Anholt      ir->val = operand_to_temp(ir->val);
160f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   }
161f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt
162f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt   return visit_continue;
163f8bb17260a6afb48534ec70dc9d5584851d7e3c2Eric Anholt}
164c7b1046a9fa6da916f11fb9e43d61fd772470183Ian Romanick
1654b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanickir_visitor_status
1664b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanickir_expression_flattening_visitor::visit_enter(ir_call *ir)
1670d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt{
1684b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick   /* FINISHME: Why not process the call parameters? (Same behavior as original
1694b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick    * FINISHME: code.)
1704b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick    */
1710d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   (void) ir;
1724b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick   return visit_continue_with_parent;
1730d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt}
1740d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
1750d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt
1764b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanickir_visitor_status
1774b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanickir_expression_flattening_visitor::visit_enter(ir_return *ir)
1780d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt{
1794b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick   /* FINISHME: Why not process the return value? (Same behavior as original
1804b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick    * FINISHME: code.)
1814b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick    */
1820d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt   (void) ir;
1834b389492b9d4c28cacc1d297b3f2da1d6819edaeIan Romanick   return visit_continue_with_parent;
1840d42321ec1aaeaf60ee2dd8b1872182065ebc057Eric Anholt}
185