Home | History | Annotate | Download | only in glsl
      1 /*
      2  * Copyright  2016 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 ir_array_refcount.h
     26  *
     27  * Provides a visitor which produces a list of variables referenced.
     28  */
     29 
     30 #include "ir.h"
     31 #include "ir_visitor.h"
     32 #include "compiler/glsl_types.h"
     33 #include "util/bitset.h"
     34 
     35 /**
     36  * Describes an access of an array element or an access of the whole array
     37  */
     38 struct array_deref_range {
     39    /**
     40     * Index that was accessed.
     41     *
     42     * All valid array indices are less than the size of the array.  If index
     43     * is equal to the size of the array, this means the entire array has been
     44     * accessed (e.g., due to use of a non-constant index).
     45     */
     46    unsigned index;
     47 
     48    /** Size of the array.  Used for offset calculations. */
     49    unsigned size;
     50 };
     51 
     52 class ir_array_refcount_entry
     53 {
     54 public:
     55    ir_array_refcount_entry(ir_variable *var);
     56    ~ir_array_refcount_entry();
     57 
     58    ir_variable *var; /* The key: the variable's pointer. */
     59 
     60    /** Has the variable been referenced? */
     61    bool is_referenced;
     62 
     63    /**
     64     * Mark a set of array elements as accessed.
     65     *
     66     * If every \c array_deref_range is for a single index, only a single
     67     * element will be marked.  If any \c array_deref_range is for an entire
     68     * array-of-, then multiple elements will be marked.
     69     *
     70     * Items in the \c array_deref_range list appear in least- to
     71     * most-significant order.  This is the \b opposite order the indices
     72     * appear in the GLSL shader text.  An array access like
     73     *
     74     *     x = y[1][i][3];
     75     *
     76     * would appear as
     77     *
     78     *     { { 3, n }, { m, m }, { 1, p } }
     79     *
     80     * where n, m, and p are the sizes of the arrays-of-arrays.
     81     *
     82     * The set of marked array elements can later be queried by
     83     * \c ::is_linearized_index_referenced.
     84     *
     85     * \param dr     List of array_deref_range elements to be processed.
     86     * \param count  Number of array_deref_range elements to be processed.
     87     */
     88    void mark_array_elements_referenced(const array_deref_range *dr,
     89                                        unsigned count);
     90 
     91    /** Has a linearized array index been referenced? */
     92    bool is_linearized_index_referenced(unsigned linearized_index) const
     93    {
     94       assert(bits != 0);
     95       assert(linearized_index <= num_bits);
     96 
     97       return BITSET_TEST(bits, linearized_index);
     98    }
     99 
    100 private:
    101    /** Set of bit-flags to note which array elements have been accessed. */
    102    BITSET_WORD *bits;
    103 
    104    /**
    105     * Total number of bits referenced by \c bits.
    106     *
    107     * Also the total number of array(s-of-arrays) elements of \c var.
    108     */
    109    unsigned num_bits;
    110 
    111    /** Count of nested arrays in the type. */
    112    unsigned array_depth;
    113 
    114    /**
    115     * Recursive part of the public mark_array_elements_referenced method.
    116     *
    117     * The recursion occurs when an entire array-of- is accessed.  See the
    118     * implementation for more details.
    119     *
    120     * \param dr                List of array_deref_range elements to be
    121     *                          processed.
    122     * \param count             Number of array_deref_range elements to be
    123     *                          processed.
    124     * \param scale             Current offset scale.
    125     * \param linearized_index  Current accumulated linearized array index.
    126     */
    127    void mark_array_elements_referenced(const array_deref_range *dr,
    128                                        unsigned count,
    129                                        unsigned scale,
    130                                        unsigned linearized_index);
    131 
    132    friend class array_refcount_test;
    133 };
    134 
    135 class ir_array_refcount_visitor : public ir_hierarchical_visitor {
    136 public:
    137    ir_array_refcount_visitor(void);
    138    ~ir_array_refcount_visitor(void);
    139 
    140    virtual ir_visitor_status visit(ir_dereference_variable *);
    141 
    142    virtual ir_visitor_status visit_enter(ir_function_signature *);
    143    virtual ir_visitor_status visit_enter(ir_dereference_array *);
    144 
    145    /**
    146     * Find variable in the hash table, and insert it if not present
    147     */
    148    ir_array_refcount_entry *get_variable_entry(ir_variable *var);
    149 
    150    /**
    151     * Hash table mapping ir_variable to ir_array_refcount_entry.
    152     */
    153    struct hash_table *ht;
    154 
    155    void *mem_ctx;
    156 
    157 private:
    158    /** Get an array_deref_range element from private tracking. */
    159    array_deref_range *get_array_deref();
    160 
    161    /**
    162     * Last ir_dereference_array that was visited
    163     *
    164     * Used to prevent some redundant calculations.
    165     *
    166     * \sa ::visit_enter(ir_dereference_array *)
    167     */
    168    ir_dereference_array *last_array_deref;
    169 
    170    /**
    171     * \name array_deref_range tracking
    172     */
    173    /*@{*/
    174    /** Currently allocated block of derefs. */
    175    array_deref_range *derefs;
    176 
    177    /** Number of derefs used in current processing. */
    178    unsigned num_derefs;
    179 
    180    /** Size of the derefs buffer in bytes. */
    181    unsigned derefs_size;
    182    /*@}*/
    183 };
    184