Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | 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. /**
  36.  * Visitor class for replacing expressions with ir_constant values.
  37.  */
  38.  
  39. class ir_constant_folding_visitor : public ir_rvalue_visitor {
  40. public:
  41.    ir_constant_folding_visitor()
  42.    {
  43.       this->progress = false;
  44.    }
  45.  
  46.    virtual ~ir_constant_folding_visitor()
  47.    {
  48.       /* empty */
  49.    }
  50.  
  51.    virtual ir_visitor_status visit_enter(ir_assignment *ir);
  52.    virtual ir_visitor_status visit_enter(ir_call *ir);
  53.  
  54.    virtual void handle_rvalue(ir_rvalue **rvalue);
  55.  
  56.    bool progress;
  57. };
  58.  
  59. void
  60. ir_constant_folding_visitor::handle_rvalue(ir_rvalue **rvalue)
  61. {
  62.    if (*rvalue == NULL || (*rvalue)->ir_type == ir_type_constant)
  63.       return;
  64.  
  65.    /* Note that we do rvalue visitoring on leaving.  So if an
  66.     * expression has a non-constant operand, no need to go looking
  67.     * down it to find if it's constant.  This cuts the time of this
  68.     * pass down drastically.
  69.     */
  70.    ir_expression *expr = (*rvalue)->as_expression();
  71.    if (expr) {
  72.       for (unsigned int i = 0; i < expr->get_num_operands(); i++) {
  73.          if (!expr->operands[i]->as_constant())
  74.             return;
  75.       }
  76.    }
  77.  
  78.    ir_constant *constant = (*rvalue)->constant_expression_value();
  79.    if (constant) {
  80.       *rvalue = constant;
  81.       this->progress = true;
  82.    } else {
  83.       (*rvalue)->accept(this);
  84.    }
  85. }
  86.  
  87. ir_visitor_status
  88. ir_constant_folding_visitor::visit_enter(ir_assignment *ir)
  89. {
  90.    ir->rhs->accept(this);
  91.    handle_rvalue(&ir->rhs);
  92.  
  93.    if (ir->condition) {
  94.       ir->condition->accept(this);
  95.       handle_rvalue(&ir->condition);
  96.  
  97.       ir_constant *const_val = ir->condition->as_constant();
  98.       /* If the condition is constant, either remove the condition or
  99.        * remove the never-executed assignment.
  100.        */
  101.       if (const_val) {
  102.          if (const_val->value.b[0])
  103.             ir->condition = NULL;
  104.          else
  105.             ir->remove();
  106.          this->progress = true;
  107.       }
  108.    }
  109.  
  110.    /* Don't descend into the LHS because we want it to stay as a
  111.     * variable dereference.  FINISHME: We probably should to get array
  112.     * indices though.
  113.     */
  114.    return visit_continue_with_parent;
  115. }
  116.  
  117. ir_visitor_status
  118. ir_constant_folding_visitor::visit_enter(ir_call *ir)
  119. {
  120.    exec_list_iterator sig_iter = ir->get_callee()->parameters.iterator();
  121.    foreach_iter(exec_list_iterator, iter, *ir) {
  122.       ir_rvalue *param_rval = (ir_rvalue *)iter.get();
  123.       ir_variable *sig_param = (ir_variable *)sig_iter.get();
  124.  
  125.       if (sig_param->mode == ir_var_in) {
  126.          ir_rvalue *new_param = param_rval;
  127.  
  128.          handle_rvalue(&new_param);
  129.          if (new_param != param_rval) {
  130.             param_rval->replace_with(new_param);
  131.          }
  132.       }
  133.       sig_iter.next();
  134.    }
  135.  
  136.    return visit_continue_with_parent;
  137. }
  138.  
  139. bool
  140. do_constant_folding(exec_list *instructions)
  141. {
  142.    ir_constant_folding_visitor constant_folding;
  143.  
  144.    visit_list_elements(&constant_folding, instructions);
  145.  
  146.    return constant_folding.progress;
  147. }
  148.