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. #include <limits.h>
  25. #include "main/compiler.h"
  26. #include "glsl_types.h"
  27. #include "loop_analysis.h"
  28. #include "ir_hierarchical_visitor.h"
  29.  
  30. /**
  31.  * Find an initializer of a variable outside a loop
  32.  *
  33.  * Works backwards from the loop to find the pre-loop value of the variable.
  34.  * This is used, for example, to find the initial value of loop induction
  35.  * variables.
  36.  *
  37.  * \param loop  Loop where \c var is an induction variable
  38.  * \param var   Variable whose initializer is to be found
  39.  *
  40.  * \return
  41.  * The \c ir_rvalue assigned to the variable outside the loop.  May return
  42.  * \c NULL if no initializer can be found.
  43.  */
  44. ir_rvalue *
  45. find_initial_value(ir_loop *loop, ir_variable *var)
  46. {
  47.    for (exec_node *node = loop->prev;
  48.         !node->is_head_sentinel();
  49.         node = node->prev) {
  50.       ir_instruction *ir = (ir_instruction *) node;
  51.  
  52.       switch (ir->ir_type) {
  53.       case ir_type_call:
  54.       case ir_type_loop:
  55.       case ir_type_loop_jump:
  56.       case ir_type_return:
  57.       case ir_type_if:
  58.          return NULL;
  59.  
  60.       case ir_type_function:
  61.       case ir_type_function_signature:
  62.          assert(!"Should not get here.");
  63.          return NULL;
  64.  
  65.       case ir_type_assignment: {
  66.          ir_assignment *assign = ir->as_assignment();
  67.          ir_variable *assignee = assign->lhs->whole_variable_referenced();
  68.  
  69.          if (assignee == var)
  70.             return (assign->condition != NULL) ? NULL : assign->rhs;
  71.  
  72.          break;
  73.       }
  74.  
  75.       default:
  76.          break;
  77.       }
  78.    }
  79.  
  80.    return NULL;
  81. }
  82.  
  83.  
  84. int
  85. calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
  86.                      enum ir_expression_operation op)
  87. {
  88.    if (from == NULL || to == NULL || increment == NULL)
  89.       return -1;
  90.  
  91.    void *mem_ctx = ralloc_context(NULL);
  92.  
  93.    ir_expression *const sub =
  94.       new(mem_ctx) ir_expression(ir_binop_sub, from->type, to, from);
  95.  
  96.    ir_expression *const div =
  97.       new(mem_ctx) ir_expression(ir_binop_div, sub->type, sub, increment);
  98.  
  99.    ir_constant *iter = div->constant_expression_value();
  100.  
  101.    if (iter == NULL)
  102.       return -1;
  103.  
  104.    if (!iter->type->is_integer()) {
  105.       ir_rvalue *cast =
  106.          new(mem_ctx) ir_expression(ir_unop_f2i, glsl_type::int_type, iter,
  107.                                     NULL);
  108.  
  109.       iter = cast->constant_expression_value();
  110.    }
  111.  
  112.    int iter_value = iter->get_int_component(0);
  113.  
  114.    /* Make sure that the calculated number of iterations satisfies the exit
  115.     * condition.  This is needed to catch off-by-one errors and some types of
  116.     * ill-formed loops.  For example, we need to detect that the following
  117.     * loop does not have a maximum iteration count.
  118.     *
  119.     *    for (float x = 0.0; x != 0.9; x += 0.2)
  120.     *        ;
  121.     */
  122.    const int bias[] = { -1, 0, 1 };
  123.    bool valid_loop = false;
  124.  
  125.    for (unsigned i = 0; i < Elements(bias); i++) {
  126.       iter = (increment->type->is_integer())
  127.          ? new(mem_ctx) ir_constant(iter_value + bias[i])
  128.          : new(mem_ctx) ir_constant(float(iter_value + bias[i]));
  129.  
  130.       ir_expression *const mul =
  131.          new(mem_ctx) ir_expression(ir_binop_mul, increment->type, iter,
  132.                                     increment);
  133.  
  134.       ir_expression *const add =
  135.          new(mem_ctx) ir_expression(ir_binop_add, mul->type, mul, from);
  136.  
  137.       ir_expression *const cmp =
  138.          new(mem_ctx) ir_expression(op, glsl_type::bool_type, add, to);
  139.  
  140.       ir_constant *const cmp_result = cmp->constant_expression_value();
  141.  
  142.       assert(cmp_result != NULL);
  143.       if (cmp_result->get_bool_component(0)) {
  144.          iter_value += bias[i];
  145.          valid_loop = true;
  146.          break;
  147.       }
  148.    }
  149.  
  150.    ralloc_free(mem_ctx);
  151.    return (valid_loop) ? iter_value : -1;
  152. }
  153.  
  154.  
  155. class loop_control_visitor : public ir_hierarchical_visitor {
  156. public:
  157.    loop_control_visitor(loop_state *state)
  158.    {
  159.       this->state = state;
  160.       this->progress = false;
  161.    }
  162.  
  163.    virtual ir_visitor_status visit_leave(ir_loop *ir);
  164.  
  165.    loop_state *state;
  166.  
  167.    bool progress;
  168. };
  169.  
  170.  
  171. ir_visitor_status
  172. loop_control_visitor::visit_leave(ir_loop *ir)
  173. {
  174.    loop_variable_state *const ls = this->state->get(ir);
  175.  
  176.    /* If we've entered a loop that hasn't been analyzed, something really,
  177.     * really bad has happened.
  178.     */
  179.    if (ls == NULL) {
  180.       assert(ls != NULL);
  181.       return visit_continue;
  182.    }
  183.  
  184.    /* Search the loop terminating conditions for one of the form 'i < c' where
  185.     * i is a loop induction variable, c is a constant, and < is any relative
  186.     * operator.
  187.     */
  188.    int max_iterations = ls->max_iterations;
  189.  
  190.    if(ir->from && ir->to && ir->increment)
  191.       max_iterations = calculate_iterations(ir->from, ir->to, ir->increment, (ir_expression_operation)ir->cmp);
  192.  
  193.    if(max_iterations < 0)
  194.       max_iterations = INT_MAX;
  195.  
  196.    foreach_list(node, &ls->terminators) {
  197.       loop_terminator *t = (loop_terminator *) node;
  198.       ir_if *if_stmt = t->ir;
  199.  
  200.       /* If-statements can be either 'if (expr)' or 'if (deref)'.  We only care
  201.        * about the former here.
  202.        */
  203.       ir_expression *cond = if_stmt->condition->as_expression();
  204.       if (cond == NULL)
  205.          continue;
  206.  
  207.       switch (cond->operation) {
  208.       case ir_binop_less:
  209.       case ir_binop_greater:
  210.       case ir_binop_lequal:
  211.       case ir_binop_gequal: {
  212.          /* The expressions that we care about will either be of the form
  213.           * 'counter < limit' or 'limit < counter'.  Figure out which is
  214.           * which.
  215.           */
  216.          ir_rvalue *counter = cond->operands[0]->as_dereference_variable();
  217.          ir_constant *limit = cond->operands[1]->as_constant();
  218.          enum ir_expression_operation cmp = cond->operation;
  219.  
  220.          if (limit == NULL) {
  221.             counter = cond->operands[1]->as_dereference_variable();
  222.             limit = cond->operands[0]->as_constant();
  223.  
  224.             switch (cmp) {
  225.             case ir_binop_less:    cmp = ir_binop_greater; break;
  226.             case ir_binop_greater: cmp = ir_binop_less;    break;
  227.             case ir_binop_lequal:  cmp = ir_binop_gequal;  break;
  228.             case ir_binop_gequal:  cmp = ir_binop_lequal;  break;
  229.             default: assert(!"Should not get here.");
  230.             }
  231.          }
  232.  
  233.          if ((counter == NULL) || (limit == NULL))
  234.             break;
  235.  
  236.          ir_variable *var = counter->variable_referenced();
  237.  
  238.          ir_rvalue *init = find_initial_value(ir, var);
  239.  
  240.          foreach_list(iv_node, &ls->induction_variables) {
  241.             loop_variable *lv = (loop_variable *) iv_node;
  242.  
  243.             if (lv->var == var) {
  244.                const int iterations = calculate_iterations(init, limit,
  245.                                                            lv->increment,
  246.                                                            cmp);
  247.                if (iterations >= 0) {
  248.                   /* If the new iteration count is lower than the previously
  249.                    * believed iteration count, update the loop control values.
  250.                    */
  251.                   if (iterations < max_iterations) {
  252.                      ir->from = init->clone(ir, NULL);
  253.                      ir->to = limit->clone(ir, NULL);
  254.                      ir->increment = lv->increment->clone(ir, NULL);
  255.                      ir->counter = lv->var;
  256.                      ir->cmp = cmp;
  257.  
  258.                      max_iterations = iterations;
  259.                   }
  260.  
  261.                   /* Remove the conditional break statement.  The loop
  262.                    * controls are now set such that the exit condition will be
  263.                    * satisfied.
  264.                    */
  265.                   if_stmt->remove();
  266.  
  267.                   assert(ls->num_loop_jumps > 0);
  268.                   ls->num_loop_jumps--;
  269.  
  270.                   this->progress = true;
  271.                }
  272.  
  273.                break;
  274.             }
  275.          }
  276.          break;
  277.       }
  278.  
  279.       default:
  280.          break;
  281.       }
  282.    }
  283.  
  284.    /* If we have proven the one of the loop exit conditions is satisifed before
  285.     * running the loop once, remove the loop.
  286.     */
  287.    if (max_iterations == 0)
  288.       ir->remove();
  289.    else
  290.       ls->max_iterations = max_iterations;
  291.  
  292.    return visit_continue;
  293. }
  294.  
  295.  
  296. bool
  297. set_loop_controls(exec_list *instructions, loop_state *ls)
  298. {
  299.    loop_control_visitor v(ls);
  300.  
  301.    v.run(instructions);
  302.  
  303.    return v.progress;
  304. }
  305.