Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright © 2010 Intel Corporation
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a
  5.  * copy of this software and associated documentation files (the "Software"),
  6.  * to deal in the Software without restriction, including without limitation
  7.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8.  * and/or sell copies of the Software, and to permit persons to whom the
  9.  * Software is furnished to do so, subject to the following conditions:
  10.  *
  11.  * The above copyright notice and this permission notice (including the next
  12.  * paragraph) shall be included in all copies or substantial portions of the
  13.  * Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  18.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  21.  * DEALINGS IN THE SOFTWARE.
  22.  */
  23.  
  24. /**
  25.  * \file opt_constant_folding.cpp
  26.  * Replace constant-valued expressions with references to constant values.
  27.  */
  28.  
  29. #include "ir.h"
  30. #include "ir_visitor.h"
  31. #include "ir_rvalue_visitor.h"
  32. #include "ir_optimization.h"
  33. #include "glsl_types.h"
  34.  
  35. namespace {
  36.  
  37. /**
  38.  * Visitor class for replacing expressions with ir_constant values.
  39.  */
  40.  
  41. class ir_constant_folding_visitor : public ir_rvalue_visitor {
  42. public:
  43.    ir_constant_folding_visitor()
  44.    {
  45.       this->progress = false;
  46.    }
  47.  
  48.    virtual ~ir_constant_folding_visitor()
  49.    {
  50.       /* empty */
  51.    }
  52.  
  53.    virtual ir_visitor_status visit_enter(ir_assignment *ir);
  54.    virtual ir_visitor_status visit_enter(ir_call *ir);
  55.  
  56.    virtual void handle_rvalue(ir_rvalue **rvalue);
  57.  
  58.    bool progress;
  59. };
  60.  
  61. } /* unnamed namespace */
  62.  
  63. void
  64. ir_constant_folding_visitor::handle_rvalue(ir_rvalue **rvalue)
  65. {
  66.    if (*rvalue == NULL || (*rvalue)->ir_type == ir_type_constant)
  67.       return;
  68.  
  69.    /* Note that we do rvalue visitoring on leaving.  So if an
  70.     * expression has a non-constant operand, no need to go looking
  71.     * down it to find if it's constant.  This cuts the time of this
  72.     * pass down drastically.
  73.     */
  74.    ir_expression *expr = (*rvalue)->as_expression();
  75.    if (expr) {
  76.       for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
  77.          if (!expr->operands[i]->as_constant())
  78.             return;
  79.       }
  80.    }
  81.  
  82.    ir_constant *constant = (*rvalue)->constant_expression_value();
  83.    if (constant) {
  84.       *rvalue = constant;
  85.       this->progress = true;
  86.    } else {
  87.       (*rvalue)->accept(this);
  88.    }
  89. }
  90.  
  91. ir_visitor_status
  92. ir_constant_folding_visitor::visit_enter(ir_assignment *ir)
  93. {
  94.    ir->rhs->accept(this);
  95.    handle_rvalue(&ir->rhs);
  96.  
  97.    if (ir->condition) {
  98.       ir->condition->accept(this);
  99.       handle_rvalue(&ir->condition);
  100.  
  101.       ir_constant *const_val = ir->condition->as_constant();
  102.       /* If the condition is constant, either remove the condition or
  103.        * remove the never-executed assignment.
  104.        */
  105.       if (const_val) {
  106.          if (const_val->value.b[0])
  107.             ir->condition = NULL;
  108.          else
  109.             ir->remove();
  110.          this->progress = true;
  111.       }
  112.    }
  113.  
  114.    /* Don't descend into the LHS because we want it to stay as a
  115.     * variable dereference.  FINISHME: We probably should to get array
  116.     * indices though.
  117.     */
  118.    return visit_continue_with_parent;
  119. }
  120.  
  121. ir_visitor_status
  122. ir_constant_folding_visitor::visit_enter(ir_call *ir)
  123. {
  124.    /* Attempt to constant fold parameters */
  125.    exec_list_iterator sig_iter = ir->callee->parameters.iterator();
  126.    foreach_iter(exec_list_iterator, iter, *ir) {
  127.       ir_rvalue *param_rval = (ir_rvalue *)iter.get();
  128.       ir_variable *sig_param = (ir_variable *)sig_iter.get();
  129.  
  130.       if (sig_param->mode == ir_var_function_in
  131.           || sig_param->mode == ir_var_const_in) {
  132.          ir_rvalue *new_param = param_rval;
  133.  
  134.          handle_rvalue(&new_param);
  135.          if (new_param != param_rval) {
  136.             param_rval->replace_with(new_param);
  137.          }
  138.       }
  139.       sig_iter.next();
  140.    }
  141.  
  142.    /* Next, see if the call can be replaced with an assignment of a constant */
  143.    ir_constant *const_val = ir->constant_expression_value();
  144.  
  145.    if (const_val != NULL) {
  146.       ir_assignment *assignment =
  147.          new(ralloc_parent(ir)) ir_assignment(ir->return_deref, const_val);
  148.       ir->replace_with(assignment);
  149.    }
  150.  
  151.    return visit_continue_with_parent;
  152. }
  153.  
  154. bool
  155. do_constant_folding(exec_list *instructions)
  156. {
  157.    ir_constant_folding_visitor constant_folding;
  158.  
  159.    visit_list_elements(&constant_folding, instructions);
  160.  
  161.    return constant_folding.progress;
  162. }
  163.