162735694a1dfc09a16ea32312877cd49c7982118Eric Anholt/*
262735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * Copyright © 2010 Intel Corporation
362735694a1dfc09a16ea32312877cd49c7982118Eric Anholt *
462735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * Permission is hereby granted, free of charge, to any person obtaining a
562735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * copy of this software and associated documentation files (the "Software"),
662735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * to deal in the Software without restriction, including without limitation
762735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * the rights to use, copy, modify, merge, publish, distribute, sublicense,
862735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * and/or sell copies of the Software, and to permit persons to whom the
962735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * Software is furnished to do so, subject to the following conditions:
1062735694a1dfc09a16ea32312877cd49c7982118Eric Anholt *
1162735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * The above copyright notice and this permission notice (including the next
1262735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * paragraph) shall be included in all copies or substantial portions of the
1362735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * Software.
1462735694a1dfc09a16ea32312877cd49c7982118Eric Anholt *
1562735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1662735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1762735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1862735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1962735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2062735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
2162735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * DEALINGS IN THE SOFTWARE.
2262735694a1dfc09a16ea32312877cd49c7982118Eric Anholt */
2362735694a1dfc09a16ea32312877cd49c7982118Eric Anholt
2462735694a1dfc09a16ea32312877cd49c7982118Eric Anholt/**
25df883eb1575a740bf91e01cbe2eaa4dbc1f9f154Chad Versace * \file opt_constant_folding.cpp
2662735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * Replace constant-valued expressions with references to constant values.
2762735694a1dfc09a16ea32312877cd49c7982118Eric Anholt */
2862735694a1dfc09a16ea32312877cd49c7982118Eric Anholt
2962735694a1dfc09a16ea32312877cd49c7982118Eric Anholt#include "ir.h"
3062735694a1dfc09a16ea32312877cd49c7982118Eric Anholt#include "ir_visitor.h"
316606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt#include "ir_rvalue_visitor.h"
32bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt#include "ir_optimization.h"
3362735694a1dfc09a16ea32312877cd49c7982118Eric Anholt#include "glsl_types.h"
3462735694a1dfc09a16ea32312877cd49c7982118Eric Anholt
35337d9c955b070224f7278524af54ddacd8bb0f17Eric Anholtnamespace {
36337d9c955b070224f7278524af54ddacd8bb0f17Eric Anholt
3762735694a1dfc09a16ea32312877cd49c7982118Eric Anholt/**
3862735694a1dfc09a16ea32312877cd49c7982118Eric Anholt * Visitor class for replacing expressions with ir_constant values.
3962735694a1dfc09a16ea32312877cd49c7982118Eric Anholt */
4062735694a1dfc09a16ea32312877cd49c7982118Eric Anholt
416606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholtclass ir_constant_folding_visitor : public ir_rvalue_visitor {
42bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholtpublic:
43bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt   ir_constant_folding_visitor()
44bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt   {
456ecf62f673bf90d0969f8db032781b49a988975aEric Anholt      this->progress = false;
46bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt   }
47bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt
48bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt   virtual ~ir_constant_folding_visitor()
49bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt   {
50bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt      /* empty */
51bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt   }
52bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt
536606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt   virtual ir_visitor_status visit_enter(ir_assignment *ir);
54428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt   virtual ir_visitor_status visit_enter(ir_call *ir);
553d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt
566606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt   virtual void handle_rvalue(ir_rvalue **rvalue);
576ecf62f673bf90d0969f8db032781b49a988975aEric Anholt
586ecf62f673bf90d0969f8db032781b49a988975aEric Anholt   bool progress;
59bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt};
60bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt
61337d9c955b070224f7278524af54ddacd8bb0f17Eric Anholt} /* unnamed namespace */
62337d9c955b070224f7278524af54ddacd8bb0f17Eric Anholt
6362735694a1dfc09a16ea32312877cd49c7982118Eric Anholtvoid
646606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholtir_constant_folding_visitor::handle_rvalue(ir_rvalue **rvalue)
653d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt{
668dbdcb0b43c8749018ff62dd5751190e54fe2445Eric Anholt   if (*rvalue == NULL || (*rvalue)->ir_type == ir_type_constant)
673d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt      return;
683d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt
692db7bb9c665d13fd067109b1171eedd92764791dEric Anholt   /* Note that we do rvalue visitoring on leaving.  So if an
702db7bb9c665d13fd067109b1171eedd92764791dEric Anholt    * expression has a non-constant operand, no need to go looking
712db7bb9c665d13fd067109b1171eedd92764791dEric Anholt    * down it to find if it's constant.  This cuts the time of this
722db7bb9c665d13fd067109b1171eedd92764791dEric Anholt    * pass down drastically.
732db7bb9c665d13fd067109b1171eedd92764791dEric Anholt    */
742db7bb9c665d13fd067109b1171eedd92764791dEric Anholt   ir_expression *expr = (*rvalue)->as_expression();
752db7bb9c665d13fd067109b1171eedd92764791dEric Anholt   if (expr) {
762db7bb9c665d13fd067109b1171eedd92764791dEric Anholt      for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
772db7bb9c665d13fd067109b1171eedd92764791dEric Anholt	 if (!expr->operands[i]->as_constant())
782db7bb9c665d13fd067109b1171eedd92764791dEric Anholt	    return;
792db7bb9c665d13fd067109b1171eedd92764791dEric Anholt      }
802db7bb9c665d13fd067109b1171eedd92764791dEric Anholt   }
812db7bb9c665d13fd067109b1171eedd92764791dEric Anholt
823d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt   ir_constant *constant = (*rvalue)->constant_expression_value();
833d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt   if (constant) {
843d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt      *rvalue = constant;
856ecf62f673bf90d0969f8db032781b49a988975aEric Anholt      this->progress = true;
863d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt   } else {
873d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt      (*rvalue)->accept(this);
883d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt   }
893d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt}
903d23f0a90c982ad43a6f18ef69a23b2fcdb1d1d2Eric Anholt
916606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholtir_visitor_status
926606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholtir_constant_folding_visitor::visit_enter(ir_assignment *ir)
9362735694a1dfc09a16ea32312877cd49c7982118Eric Anholt{
946606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt   ir->rhs->accept(this);
956606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt   handle_rvalue(&ir->rhs);
9614f8e16132409f38656e4874aa53bc471977f9adEric Anholt
9714f8e16132409f38656e4874aa53bc471977f9adEric Anholt   if (ir->condition) {
986606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt      ir->condition->accept(this);
996606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt      handle_rvalue(&ir->condition);
1006606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt
1016606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt      ir_constant *const_val = ir->condition->as_constant();
10214f8e16132409f38656e4874aa53bc471977f9adEric Anholt      /* If the condition is constant, either remove the condition or
10314f8e16132409f38656e4874aa53bc471977f9adEric Anholt       * remove the never-executed assignment.
10414f8e16132409f38656e4874aa53bc471977f9adEric Anholt       */
10514f8e16132409f38656e4874aa53bc471977f9adEric Anholt      if (const_val) {
10614f8e16132409f38656e4874aa53bc471977f9adEric Anholt	 if (const_val->value.b[0])
10714f8e16132409f38656e4874aa53bc471977f9adEric Anholt	    ir->condition = NULL;
10814f8e16132409f38656e4874aa53bc471977f9adEric Anholt	 else
10914f8e16132409f38656e4874aa53bc471977f9adEric Anholt	    ir->remove();
1108dbdcb0b43c8749018ff62dd5751190e54fe2445Eric Anholt	 this->progress = true;
11114f8e16132409f38656e4874aa53bc471977f9adEric Anholt      }
11214f8e16132409f38656e4874aa53bc471977f9adEric Anholt   }
11362735694a1dfc09a16ea32312877cd49c7982118Eric Anholt
1146606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt   /* Don't descend into the LHS because we want it to stay as a
1156606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt    * variable dereference.  FINISHME: We probably should to get array
1166606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt    * indices though.
1176606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt    */
1186606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt   return visit_continue_with_parent;
119f8e31e00b1078dc28187a43a1ab8949e154e7533Ian Romanick}
120bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt
121428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholtir_visitor_status
122428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholtir_constant_folding_visitor::visit_enter(ir_call *ir)
123428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt{
124d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke   /* Attempt to constant fold parameters */
12582065fa20ee3f2880a070f1f4f75509b910ceddeKenneth Graunke   exec_list_iterator sig_iter = ir->callee->parameters.iterator();
126428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt   foreach_iter(exec_list_iterator, iter, *ir) {
127428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt      ir_rvalue *param_rval = (ir_rvalue *)iter.get();
128428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt      ir_variable *sig_param = (ir_variable *)sig_iter.get();
129428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt
130819d57fce94b20fa0d34da6f037f0a53c4a5bdc2Kenneth Graunke      if (sig_param->mode == ir_var_in || sig_param->mode == ir_var_const_in) {
131428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt	 ir_rvalue *new_param = param_rval;
132428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt
133428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt	 handle_rvalue(&new_param);
134428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt	 if (new_param != param_rval) {
135428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt	    param_rval->replace_with(new_param);
136428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt	 }
137428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt      }
138ea709696185846c876581e1c41a21921826823ecEric Anholt      sig_iter.next();
139428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt   }
140428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt
141d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke   /* Next, see if the call can be replaced with an assignment of a constant */
142d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke   ir_constant *const_val = ir->constant_expression_value();
143d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke
144d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke   if (const_val != NULL) {
145d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke      ir_assignment *assignment =
146d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke	 new(ralloc_parent(ir)) ir_assignment(ir->return_deref, const_val);
147d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke      ir->replace_with(assignment);
148d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke   }
149d884f60861f270cdcf7d9d47765efcf1e1de30b6Kenneth Graunke
150428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt   return visit_continue_with_parent;
151428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt}
152428a3cd2d537a42c8a01765a5a53dca139e07443Eric Anholt
153bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholtbool
154bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholtdo_constant_folding(exec_list *instructions)
155bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt{
156bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt   ir_constant_folding_visitor constant_folding;
157bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt
1586606fde3ec18288ecc4c6ce6d3fd32224a6c5248Eric Anholt   visit_list_elements(&constant_folding, instructions);
159bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt
1606ecf62f673bf90d0969f8db032781b49a988975aEric Anholt   return constant_folding.progress;
161bdd9b1f3ffa2a195d983816adfeca20480256119Eric Anholt}
162