Home | History | Annotate | Download | only in glsl
      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 "util/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 = _mesa_hash_table_create(NULL, _mesa_hash_pointer,
    134                                                _mesa_key_pointer_equal);
    135       this->limiting_terminator = NULL;
    136    }
    137 
    138    ~loop_variable_state()
    139    {
    140       _mesa_hash_table_destroy(this->var_hash, NULL);
    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