Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /* -*- c++ -*- */
  2. /*
  3.  * Copyright © 2010 Intel Corporation
  4.  *
  5.  * Permission is hereby granted, free of charge, to any person obtaining a
  6.  * copy of this software and associated documentation files (the "Software"),
  7.  * to deal in the Software without restriction, including without limitation
  8.  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  9.  * and/or sell copies of the Software, and to permit persons to whom the
  10.  * Software is furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice (including the next
  13.  * paragraph) shall be included in all copies or substantial portions of the
  14.  * Software.
  15.  *
  16.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17.  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18.  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19.  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20.  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  21.  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  22.  * DEALINGS IN THE SOFTWARE.
  23.  */
  24.  
  25. #pragma once
  26. #ifndef LOOP_ANALYSIS_H
  27. #define LOOP_ANALYSIS_H
  28.  
  29. #include "ir.h"
  30. #include "program/hash_table.h"
  31.  
  32. /**
  33.  * Analyze and classify all variables used in all loops in the instruction list
  34.  */
  35. extern class loop_state *
  36. analyze_loop_variables(exec_list *instructions);
  37.  
  38.  
  39. /**
  40.  * Fill in loop control fields
  41.  *
  42.  * Based on analysis of loop variables, this function tries to remove
  43.  * redundant sequences in the loop of the form
  44.  *
  45.  *  (if (expression bool ...) (break))
  46.  *
  47.  * For example, if it is provable that one loop exit condition will
  48.  * always be satisfied before another, the unnecessary exit condition will be
  49.  * removed.
  50.  */
  51. extern bool
  52. set_loop_controls(exec_list *instructions, loop_state *ls);
  53.  
  54.  
  55. extern bool
  56. unroll_loops(exec_list *instructions, loop_state *ls,
  57.              const struct gl_shader_compiler_options *options);
  58.  
  59. ir_rvalue *
  60. find_initial_value(ir_loop *loop, ir_variable *var);
  61.  
  62. int
  63. calculate_iterations(ir_rvalue *from, ir_rvalue *to, ir_rvalue *increment,
  64.                      enum ir_expression_operation op);
  65.  
  66.  
  67. /**
  68.  * Tracking for all variables used in a loop
  69.  */
  70. class loop_variable_state : public exec_node {
  71. public:
  72.    class loop_variable *get(const ir_variable *);
  73.    class loop_variable *insert(ir_variable *);
  74.    class loop_variable *get_or_insert(ir_variable *, bool in_assignee);
  75.    class loop_terminator *insert(ir_if *);
  76.  
  77.  
  78.    /**
  79.     * Variables that have not yet been classified
  80.     */
  81.    exec_list variables;
  82.  
  83.    /**
  84.     * Variables whose values are constant within the body of the loop
  85.     *
  86.     * This list contains \c loop_variable objects.
  87.     */
  88.    exec_list constants;
  89.  
  90.    /**
  91.     * Induction variables for this loop
  92.     *
  93.     * This list contains \c loop_variable objects.
  94.     */
  95.    exec_list induction_variables;
  96.  
  97.    /**
  98.     * Simple if-statements that lead to the termination of the loop
  99.     *
  100.     * This list contains \c loop_terminator objects.
  101.     *
  102.     * \sa is_loop_terminator
  103.     */
  104.    exec_list terminators;
  105.  
  106.    /**
  107.     * If any of the terminators in \c terminators leads to termination of the
  108.     * loop after a constant number of iterations, this is the terminator that
  109.     * leads to termination after the smallest number of iterations.  Otherwise
  110.     * NULL.
  111.     */
  112.    loop_terminator *limiting_terminator;
  113.  
  114.    /**
  115.     * Hash table containing all variables accessed in this loop
  116.     */
  117.    hash_table *var_hash;
  118.  
  119.    /**
  120.     * Number of ir_loop_jump instructions that operate on this loop
  121.     */
  122.    unsigned num_loop_jumps;
  123.  
  124.    /**
  125.     * Whether this loop contains any function calls.
  126.     */
  127.    bool contains_calls;
  128.  
  129.    loop_variable_state()
  130.    {
  131.       this->num_loop_jumps = 0;
  132.       this->contains_calls = false;
  133.       this->var_hash = hash_table_ctor(0, hash_table_pointer_hash,
  134.                                        hash_table_pointer_compare);
  135.       this->limiting_terminator = NULL;
  136.    }
  137.  
  138.    ~loop_variable_state()
  139.    {
  140.       hash_table_dtor(this->var_hash);
  141.    }
  142.  
  143.    DECLARE_RALLOC_CXX_OPERATORS(loop_variable_state)
  144. };
  145.  
  146.  
  147. class loop_variable : public exec_node {
  148. public:
  149.    /** The variable in question. */
  150.    ir_variable *var;
  151.  
  152.    /** Is the variable read in the loop before it is written? */
  153.    bool read_before_write;
  154.  
  155.    /** Are all variables in the RHS of the assignment loop constants? */
  156.    bool rhs_clean;
  157.  
  158.    /**
  159.     * Is there an assignment to the variable that is conditional, or inside a
  160.     * nested loop?
  161.     */
  162.    bool conditional_or_nested_assignment;
  163.  
  164.    /** Reference to the first assignment to the variable in the loop body. */
  165.    ir_assignment *first_assignment;
  166.  
  167.    /** Number of assignments to the variable in the loop body. */
  168.    unsigned num_assignments;
  169.  
  170.    /**
  171.     * Increment value for a loop induction variable
  172.     *
  173.     * If this is a loop induction variable, the amount by which the variable
  174.     * is incremented on each iteration through the loop.
  175.     *
  176.     * If this is not a loop induction variable, NULL.
  177.     */
  178.    ir_rvalue *increment;
  179.  
  180.  
  181.    inline bool is_induction_var() const
  182.    {
  183.       /* Induction variables always have a non-null increment, and vice
  184.        * versa.
  185.        */
  186.       return this->increment != NULL;
  187.    }
  188.  
  189.  
  190.    inline bool is_loop_constant() const
  191.    {
  192.       const bool is_const = (this->num_assignments == 0)
  193.          || (((this->num_assignments == 1)
  194.              && !this->conditional_or_nested_assignment
  195.              && !this->read_before_write
  196.              && this->rhs_clean) || this->var->data.read_only);
  197.  
  198.       /* If the RHS of *the* assignment is clean, then there must be exactly
  199.        * one assignment of the variable.
  200.        */
  201.       assert((this->rhs_clean && (this->num_assignments == 1))
  202.              || !this->rhs_clean);
  203.  
  204.       return is_const;
  205.    }
  206.  
  207.    void record_reference(bool in_assignee,
  208.                          bool in_conditional_code_or_nested_loop,
  209.                          ir_assignment *current_assignment);
  210. };
  211.  
  212.  
  213. class loop_terminator : public exec_node {
  214. public:
  215.    loop_terminator()
  216.       : ir(NULL), iterations(-1)
  217.    {
  218.    }
  219.  
  220.    /**
  221.     * Statement which terminates the loop.
  222.     */
  223.    ir_if *ir;
  224.  
  225.    /**
  226.     * The number of iterations after which the terminator is known to
  227.     * terminate the loop (if that is a fixed value).  Otherwise -1.
  228.     */
  229.    int iterations;
  230. };
  231.  
  232.  
  233. class loop_state {
  234. public:
  235.    ~loop_state();
  236.  
  237.    /**
  238.     * Get the loop variable state data for a particular loop
  239.     */
  240.    loop_variable_state *get(const ir_loop *);
  241.  
  242.    loop_variable_state *insert(ir_loop *ir);
  243.  
  244.    bool loop_found;
  245.  
  246. private:
  247.    loop_state();
  248.  
  249.    /**
  250.     * Hash table containing all loops that have been analyzed.
  251.     */
  252.    hash_table *ht;
  253.  
  254.    void *mem_ctx;
  255.  
  256.    friend loop_state *analyze_loop_variables(exec_list *instructions);
  257. };
  258.  
  259. #endif /* LOOP_ANALYSIS_H */
  260.