Home | History | Annotate | Download | only in tests
      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 #include <gtest/gtest.h>
     24 #include "ir.h"
     25 #include "ir_array_refcount.h"
     26 #include "ir_builder.h"
     27 #include "util/hash_table.h"
     28 
     29 using namespace ir_builder;
     30 
     31 class array_refcount_test : public ::testing::Test {
     32 public:
     33    virtual void SetUp();
     34    virtual void TearDown();
     35 
     36    exec_list instructions;
     37    ir_factory *body;
     38    void *mem_ctx;
     39 
     40    /**
     41     * glsl_type for a vec4[3][4][5].
     42     *
     43     * The exceptionally verbose name is picked because it matches the syntax
     44     * of http://cdecl.org/.
     45     */
     46    const glsl_type *array_3_of_array_4_of_array_5_of_vec4;
     47 
     48    /**
     49     * glsl_type for a int[3].
     50     *
     51     * The exceptionally verbose name is picked because it matches the syntax
     52     * of http://cdecl.org/.
     53     */
     54    const glsl_type *array_3_of_int;
     55 
     56    /**
     57     * Wrapper to access private member "bits" of ir_array_refcount_entry
     58     *
     59     * The test class is a friend to ir_array_refcount_entry, but the
     60     * individual tests are not part of the class.  Since the friendliness of
     61     * the test class does not extend to the tests, provide a wrapper.
     62     */
     63    const BITSET_WORD *get_bits(const ir_array_refcount_entry &entry)
     64    {
     65       return entry.bits;
     66    }
     67 
     68    /**
     69     * Wrapper to access private member "num_bits" of ir_array_refcount_entry
     70     *
     71     * The test class is a friend to ir_array_refcount_entry, but the
     72     * individual tests are not part of the class.  Since the friendliness of
     73     * the test class does not extend to the tests, provide a wrapper.
     74     */
     75    unsigned get_num_bits(const ir_array_refcount_entry &entry)
     76    {
     77       return entry.num_bits;
     78    }
     79 
     80    /**
     81     * Wrapper to access private member "array_depth" of ir_array_refcount_entry
     82     *
     83     * The test class is a friend to ir_array_refcount_entry, but the
     84     * individual tests are not part of the class.  Since the friendliness of
     85     * the test class does not extend to the tests, provide a wrapper.
     86     */
     87    unsigned get_array_depth(const ir_array_refcount_entry &entry)
     88    {
     89       return entry.array_depth;
     90    }
     91 };
     92 
     93 void
     94 array_refcount_test::SetUp()
     95 {
     96    mem_ctx = ralloc_context(NULL);
     97 
     98    instructions.make_empty();
     99    body = new ir_factory(&instructions, mem_ctx);
    100 
    101    /* The type of vec4 x[3][4][5]; */
    102    const glsl_type *const array_5_of_vec4 =
    103       glsl_type::get_array_instance(glsl_type::vec4_type, 5);
    104    const glsl_type *const array_4_of_array_5_of_vec4 =
    105       glsl_type::get_array_instance(array_5_of_vec4, 4);
    106    array_3_of_array_4_of_array_5_of_vec4 =
    107       glsl_type::get_array_instance(array_4_of_array_5_of_vec4, 3);
    108 
    109    array_3_of_int = glsl_type::get_array_instance(glsl_type::int_type, 3);
    110 }
    111 
    112 void
    113 array_refcount_test::TearDown()
    114 {
    115    delete body;
    116    body = NULL;
    117 
    118    ralloc_free(mem_ctx);
    119    mem_ctx = NULL;
    120 }
    121 
    122 static operand
    123 deref_array(operand array, operand index)
    124 {
    125    void *mem_ctx = ralloc_parent(array.val);
    126 
    127    ir_rvalue *val = new(mem_ctx) ir_dereference_array(array.val, index.val);
    128 
    129    return operand(val);
    130 }
    131 
    132 static operand
    133 deref_struct(operand s, const char *field)
    134 {
    135    void *mem_ctx = ralloc_parent(s.val);
    136 
    137    ir_rvalue *val = new(mem_ctx) ir_dereference_record(s.val, field);
    138 
    139    return operand(val);
    140 }
    141 
    142 /**
    143  * Verify that only the specified set of ir_variables exists in the hash table
    144  */
    145 static void
    146 validate_variables_in_hash_table(struct hash_table *ht,
    147                                  unsigned count,
    148                                  ...)
    149 {
    150    ir_variable **vars = new ir_variable *[count];
    151    va_list args;
    152 
    153    /* Make a copy of the list of expected ir_variables.  The copied list can
    154     * be modified during the checking.
    155     */
    156    va_start(args, count);
    157 
    158    for (unsigned i = 0; i < count; i++)
    159       vars[i] = va_arg(args, ir_variable *);
    160 
    161    va_end(args);
    162 
    163    struct hash_entry *entry;
    164    hash_table_foreach(ht, entry) {
    165       const ir_instruction *const ir = (ir_instruction *) entry->key;
    166       const ir_variable *const v = ir->as_variable();
    167 
    168       if (v == NULL) {
    169          ADD_FAILURE() << "Invalid junk in hash table: ir_type = "
    170                        << ir->ir_type << ", address = "
    171                        << (void *) ir;
    172          continue;
    173       }
    174 
    175       unsigned i;
    176       for (i = 0; i < count; i++) {
    177          if (vars[i] == NULL)
    178             continue;
    179 
    180          if (vars[i] == v)
    181             break;
    182       }
    183 
    184       if (i == count) {
    185             ADD_FAILURE() << "Invalid variable in hash table: \""
    186                           << v->name << "\"";
    187       } else {
    188          /* As each variable is encountered, remove it from the set.  Don't
    189           * bother compacting the set because we don't care about
    190           * performance here.
    191           */
    192          vars[i] = NULL;
    193       }
    194    }
    195 
    196    /* Check that there's nothing left in the set. */
    197    for (unsigned i = 0; i < count; i++) {
    198       if (vars[i] != NULL) {
    199          ADD_FAILURE() << "Variable was not in the hash table: \""
    200                           << vars[i]->name << "\"";
    201       }
    202    }
    203 
    204    delete [] vars;
    205 }
    206 
    207 TEST_F(array_refcount_test, ir_array_refcount_entry_initial_state_for_scalar)
    208 {
    209    ir_variable *const var =
    210       new(mem_ctx) ir_variable(glsl_type::int_type, "a", ir_var_auto);
    211 
    212    ir_array_refcount_entry entry(var);
    213 
    214    ASSERT_NE((void *)0, get_bits(entry));
    215    EXPECT_FALSE(entry.is_referenced);
    216    EXPECT_EQ(1, get_num_bits(entry));
    217    EXPECT_EQ(0, get_array_depth(entry));
    218    EXPECT_FALSE(entry.is_linearized_index_referenced(0));
    219 }
    220 
    221 TEST_F(array_refcount_test, ir_array_refcount_entry_initial_state_for_vector)
    222 {
    223    ir_variable *const var =
    224       new(mem_ctx) ir_variable(glsl_type::vec4_type, "a", ir_var_auto);
    225 
    226    ir_array_refcount_entry entry(var);
    227 
    228    ASSERT_NE((void *)0, get_bits(entry));
    229    EXPECT_FALSE(entry.is_referenced);
    230    EXPECT_EQ(1, get_num_bits(entry));
    231    EXPECT_EQ(0, get_array_depth(entry));
    232    EXPECT_FALSE(entry.is_linearized_index_referenced(0));
    233 }
    234 
    235 TEST_F(array_refcount_test, ir_array_refcount_entry_initial_state_for_matrix)
    236 {
    237    ir_variable *const var =
    238       new(mem_ctx) ir_variable(glsl_type::mat4_type, "a", ir_var_auto);
    239 
    240    ir_array_refcount_entry entry(var);
    241 
    242    ASSERT_NE((void *)0, get_bits(entry));
    243    EXPECT_FALSE(entry.is_referenced);
    244    EXPECT_EQ(1, get_num_bits(entry));
    245    EXPECT_EQ(0, get_array_depth(entry));
    246    EXPECT_FALSE(entry.is_linearized_index_referenced(0));
    247 }
    248 
    249 TEST_F(array_refcount_test, ir_array_refcount_entry_initial_state_for_array)
    250 {
    251    ir_variable *const var =
    252       new(mem_ctx) ir_variable(array_3_of_array_4_of_array_5_of_vec4,
    253                                "a",
    254                                ir_var_auto);
    255    const unsigned total_elements = var->type->arrays_of_arrays_size();
    256 
    257    ir_array_refcount_entry entry(var);
    258 
    259    ASSERT_NE((void *)0, get_bits(entry));
    260    EXPECT_FALSE(entry.is_referenced);
    261    EXPECT_EQ(total_elements, get_num_bits(entry));
    262    EXPECT_EQ(3, get_array_depth(entry));
    263 
    264    for (unsigned i = 0; i < total_elements; i++)
    265       EXPECT_FALSE(entry.is_linearized_index_referenced(i)) << "index = " << i;
    266 }
    267 
    268 TEST_F(array_refcount_test, mark_array_elements_referenced_simple)
    269 {
    270    ir_variable *const var =
    271       new(mem_ctx) ir_variable(array_3_of_array_4_of_array_5_of_vec4,
    272                                "a",
    273                                ir_var_auto);
    274    const unsigned total_elements = var->type->arrays_of_arrays_size();
    275 
    276    ir_array_refcount_entry entry(var);
    277 
    278    static const array_deref_range dr[] = {
    279       { 0, 5 }, { 1, 4 }, { 2, 3 }
    280    };
    281    const unsigned accessed_element = 0 + (1 * 5) + (2 * 4 * 5);
    282 
    283    entry.mark_array_elements_referenced(dr, 3);
    284 
    285    for (unsigned i = 0; i < total_elements; i++)
    286       EXPECT_EQ(i == accessed_element, entry.is_linearized_index_referenced(i));
    287 }
    288 
    289 TEST_F(array_refcount_test, mark_array_elements_referenced_whole_first_array)
    290 {
    291    ir_variable *const var =
    292       new(mem_ctx) ir_variable(array_3_of_array_4_of_array_5_of_vec4,
    293                                "a",
    294                                ir_var_auto);
    295 
    296    ir_array_refcount_entry entry(var);
    297 
    298    static const array_deref_range dr[] = {
    299       { 0, 5 }, { 1, 4 }, { 3, 3 }
    300    };
    301 
    302    entry.mark_array_elements_referenced(dr, 3);
    303 
    304    for (unsigned i = 0; i < 3; i++) {
    305       for (unsigned j = 0; j < 4; j++) {
    306          for (unsigned k = 0; k < 5; k++) {
    307             const bool accessed = (j == 1) && (k == 0);
    308             const unsigned linearized_index = k + (j * 5) + (i * 4 * 5);
    309 
    310             EXPECT_EQ(accessed,
    311                       entry.is_linearized_index_referenced(linearized_index));
    312          }
    313       }
    314    }
    315 }
    316 
    317 TEST_F(array_refcount_test, mark_array_elements_referenced_whole_second_array)
    318 {
    319    ir_variable *const var =
    320       new(mem_ctx) ir_variable(array_3_of_array_4_of_array_5_of_vec4,
    321                                "a",
    322                                ir_var_auto);
    323 
    324    ir_array_refcount_entry entry(var);
    325 
    326    static const array_deref_range dr[] = {
    327       { 0, 5 }, { 4, 4 }, { 1, 3 }
    328    };
    329 
    330    entry.mark_array_elements_referenced(dr, 3);
    331 
    332    for (unsigned i = 0; i < 3; i++) {
    333       for (unsigned j = 0; j < 4; j++) {
    334          for (unsigned k = 0; k < 5; k++) {
    335             const bool accessed = (i == 1) && (k == 0);
    336             const unsigned linearized_index = k + (j * 5) + (i * 4 * 5);
    337 
    338             EXPECT_EQ(accessed,
    339                       entry.is_linearized_index_referenced(linearized_index));
    340          }
    341       }
    342    }
    343 }
    344 
    345 TEST_F(array_refcount_test, mark_array_elements_referenced_whole_third_array)
    346 {
    347    ir_variable *const var =
    348       new(mem_ctx) ir_variable(array_3_of_array_4_of_array_5_of_vec4,
    349                                "a",
    350                                ir_var_auto);
    351 
    352    ir_array_refcount_entry entry(var);
    353 
    354    static const array_deref_range dr[] = {
    355       { 5, 5 }, { 2, 4 }, { 1, 3 }
    356    };
    357 
    358    entry.mark_array_elements_referenced(dr, 3);
    359 
    360    for (unsigned i = 0; i < 3; i++) {
    361       for (unsigned j = 0; j < 4; j++) {
    362          for (unsigned k = 0; k < 5; k++) {
    363             const bool accessed = (i == 1) && (j == 2);
    364             const unsigned linearized_index = k + (j * 5) + (i * 4 * 5);
    365 
    366             EXPECT_EQ(accessed,
    367                       entry.is_linearized_index_referenced(linearized_index));
    368          }
    369       }
    370    }
    371 }
    372 
    373 TEST_F(array_refcount_test, mark_array_elements_referenced_whole_first_and_third_arrays)
    374 {
    375    ir_variable *const var =
    376       new(mem_ctx) ir_variable(array_3_of_array_4_of_array_5_of_vec4,
    377                                "a",
    378                                ir_var_auto);
    379 
    380    ir_array_refcount_entry entry(var);
    381 
    382    static const array_deref_range dr[] = {
    383       { 5, 5 }, { 3, 4 }, { 3, 3 }
    384    };
    385 
    386    entry.mark_array_elements_referenced(dr, 3);
    387 
    388    for (unsigned i = 0; i < 3; i++) {
    389       for (unsigned j = 0; j < 4; j++) {
    390          for (unsigned k = 0; k < 5; k++) {
    391             const bool accessed = (j == 3);
    392             const unsigned linearized_index = k + (j * 5) + (i * 4 * 5);
    393 
    394             EXPECT_EQ(accessed,
    395                       entry.is_linearized_index_referenced(linearized_index));
    396          }
    397       }
    398    }
    399 }
    400 
    401 TEST_F(array_refcount_test, do_not_process_vector_indexing)
    402 {
    403    /* Vectors and matrices can also be indexed in much the same manner as
    404     * arrays.  The visitor should not try to track per-element accesses to
    405     * these types.
    406     */
    407    ir_variable *var_a = new(mem_ctx) ir_variable(glsl_type::float_type,
    408                                                  "a",
    409                                                  ir_var_auto);
    410    ir_variable *var_b = new(mem_ctx) ir_variable(glsl_type::int_type,
    411                                                  "b",
    412                                                  ir_var_auto);
    413    ir_variable *var_c = new(mem_ctx) ir_variable(glsl_type::vec4_type,
    414                                                  "c",
    415                                                  ir_var_auto);
    416 
    417    body->emit(assign(var_a, deref_array(var_c, var_b)));
    418 
    419    ir_array_refcount_visitor v;
    420 
    421    visit_list_elements(&v, &instructions);
    422 
    423    ir_array_refcount_entry *entry_a = v.get_variable_entry(var_a);
    424    ir_array_refcount_entry *entry_b = v.get_variable_entry(var_b);
    425    ir_array_refcount_entry *entry_c = v.get_variable_entry(var_c);
    426 
    427    EXPECT_TRUE(entry_a->is_referenced);
    428    EXPECT_TRUE(entry_b->is_referenced);
    429    EXPECT_TRUE(entry_c->is_referenced);
    430 
    431    /* As validated by previous tests, for non-array types, num_bits is 1. */
    432    ASSERT_EQ(1, get_num_bits(*entry_c));
    433    EXPECT_FALSE(entry_c->is_linearized_index_referenced(0));
    434 }
    435 
    436 TEST_F(array_refcount_test, do_not_process_matrix_indexing)
    437 {
    438    /* Vectors and matrices can also be indexed in much the same manner as
    439     * arrays.  The visitor should not try to track per-element accesses to
    440     * these types.
    441     */
    442    ir_variable *var_a = new(mem_ctx) ir_variable(glsl_type::vec4_type,
    443                                                  "a",
    444                                                  ir_var_auto);
    445    ir_variable *var_b = new(mem_ctx) ir_variable(glsl_type::int_type,
    446                                                  "b",
    447                                                  ir_var_auto);
    448    ir_variable *var_c = new(mem_ctx) ir_variable(glsl_type::mat4_type,
    449                                                  "c",
    450                                                  ir_var_auto);
    451 
    452    body->emit(assign(var_a, deref_array(var_c, var_b)));
    453 
    454    ir_array_refcount_visitor v;
    455 
    456    visit_list_elements(&v, &instructions);
    457 
    458    ir_array_refcount_entry *entry_a = v.get_variable_entry(var_a);
    459    ir_array_refcount_entry *entry_b = v.get_variable_entry(var_b);
    460    ir_array_refcount_entry *entry_c = v.get_variable_entry(var_c);
    461 
    462    EXPECT_TRUE(entry_a->is_referenced);
    463    EXPECT_TRUE(entry_b->is_referenced);
    464    EXPECT_TRUE(entry_c->is_referenced);
    465 
    466    /* As validated by previous tests, for non-array types, num_bits is 1. */
    467    ASSERT_EQ(1, get_num_bits(*entry_c));
    468    EXPECT_FALSE(entry_c->is_linearized_index_referenced(0));
    469 }
    470 
    471 TEST_F(array_refcount_test, do_not_process_array_inside_structure)
    472 {
    473    /* Structures can contain arrays.  The visitor should not try to track
    474     * per-element accesses to arrays contained inside structures.
    475     */
    476    const glsl_struct_field fields[] = {
    477       glsl_struct_field(array_3_of_int, "i"),
    478    };
    479 
    480    const glsl_type *const record_of_array_3_of_int =
    481       glsl_type::get_record_instance(fields, ARRAY_SIZE(fields), "S");
    482 
    483    ir_variable *var_a = new(mem_ctx) ir_variable(glsl_type::int_type,
    484                                                  "a",
    485                                                  ir_var_auto);
    486 
    487    ir_variable *var_b = new(mem_ctx) ir_variable(record_of_array_3_of_int,
    488                                                  "b",
    489                                                  ir_var_auto);
    490 
    491    /* a = b.i[2] */
    492    body->emit(assign(var_a,
    493                      deref_array(
    494                         deref_struct(var_b, "i"),
    495                         body->constant(int(2)))));
    496 
    497    ir_array_refcount_visitor v;
    498 
    499    visit_list_elements(&v, &instructions);
    500 
    501    ir_array_refcount_entry *entry_a = v.get_variable_entry(var_a);
    502    ir_array_refcount_entry *entry_b = v.get_variable_entry(var_b);
    503 
    504    EXPECT_TRUE(entry_a->is_referenced);
    505    EXPECT_TRUE(entry_b->is_referenced);
    506 
    507    ASSERT_EQ(1, get_num_bits(*entry_b));
    508    EXPECT_FALSE(entry_b->is_linearized_index_referenced(0));
    509 
    510    validate_variables_in_hash_table(v.ht, 2, var_a, var_b);
    511 }
    512 
    513 TEST_F(array_refcount_test, visit_simple_indexing)
    514 {
    515    ir_variable *var_a = new(mem_ctx) ir_variable(glsl_type::vec4_type,
    516                                                  "a",
    517                                                  ir_var_auto);
    518    ir_variable *var_b = new(mem_ctx) ir_variable(array_3_of_array_4_of_array_5_of_vec4,
    519                                                  "b",
    520                                                  ir_var_auto);
    521 
    522    /* a = b[2][1][0] */
    523    body->emit(assign(var_a,
    524                      deref_array(
    525                         deref_array(
    526                            deref_array(var_b, body->constant(int(2))),
    527                            body->constant(int(1))),
    528                         body->constant(int(0)))));
    529 
    530    ir_array_refcount_visitor v;
    531 
    532    visit_list_elements(&v, &instructions);
    533 
    534    const unsigned accessed_element = 0 + (1 * 5) + (2 * 4 * 5);
    535    ir_array_refcount_entry *entry_b = v.get_variable_entry(var_b);
    536    const unsigned total_elements = var_b->type->arrays_of_arrays_size();
    537 
    538    for (unsigned i = 0; i < total_elements; i++)
    539       EXPECT_EQ(i == accessed_element, entry_b->is_linearized_index_referenced(i)) <<
    540          "i = " << i;
    541 
    542    validate_variables_in_hash_table(v.ht, 2, var_a, var_b);
    543 }
    544 
    545 TEST_F(array_refcount_test, visit_whole_second_array_indexing)
    546 {
    547    ir_variable *var_a = new(mem_ctx) ir_variable(glsl_type::vec4_type,
    548                                                  "a",
    549                                                  ir_var_auto);
    550    ir_variable *var_b = new(mem_ctx) ir_variable(array_3_of_array_4_of_array_5_of_vec4,
    551                                                  "b",
    552                                                  ir_var_auto);
    553    ir_variable *var_i = new(mem_ctx) ir_variable(glsl_type::int_type,
    554                                                  "i",
    555                                                  ir_var_auto);
    556 
    557    /* a = b[2][i][1] */
    558    body->emit(assign(var_a,
    559                      deref_array(
    560                         deref_array(
    561                            deref_array(var_b, body->constant(int(2))),
    562                            var_i),
    563                         body->constant(int(1)))));
    564 
    565    ir_array_refcount_visitor v;
    566 
    567    visit_list_elements(&v, &instructions);
    568 
    569    ir_array_refcount_entry *const entry_b = v.get_variable_entry(var_b);
    570    for (unsigned i = 0; i < 3; i++) {
    571       for (unsigned j = 0; j < 4; j++) {
    572          for (unsigned k = 0; k < 5; k++) {
    573             const bool accessed = (i == 2) && (k == 1);
    574             const unsigned linearized_index = k + (j * 5) + (i * 4 * 5);
    575 
    576             EXPECT_EQ(accessed,
    577                       entry_b->is_linearized_index_referenced(linearized_index)) <<
    578                "i = " << i;
    579          }
    580       }
    581    }
    582 
    583    validate_variables_in_hash_table(v.ht, 3, var_a, var_b, var_i);
    584 }
    585 
    586 TEST_F(array_refcount_test, visit_array_indexing_an_array)
    587 {
    588    ir_variable *var_a = new(mem_ctx) ir_variable(glsl_type::vec4_type,
    589                                                  "a",
    590                                                  ir_var_auto);
    591    ir_variable *var_b = new(mem_ctx) ir_variable(array_3_of_array_4_of_array_5_of_vec4,
    592                                                  "b",
    593                                                  ir_var_auto);
    594    ir_variable *var_c = new(mem_ctx) ir_variable(array_3_of_int,
    595                                                  "c",
    596                                                  ir_var_auto);
    597    ir_variable *var_i = new(mem_ctx) ir_variable(glsl_type::int_type,
    598                                                  "i",
    599                                                  ir_var_auto);
    600 
    601    /* a = b[2][3][c[i]] */
    602    body->emit(assign(var_a,
    603                      deref_array(
    604                         deref_array(
    605                            deref_array(var_b, body->constant(int(2))),
    606                            body->constant(int(3))),
    607                         deref_array(var_c, var_i))));
    608 
    609    ir_array_refcount_visitor v;
    610 
    611    visit_list_elements(&v, &instructions);
    612 
    613    ir_array_refcount_entry *const entry_b = v.get_variable_entry(var_b);
    614 
    615    for (unsigned i = 0; i < 3; i++) {
    616       for (unsigned j = 0; j < 4; j++) {
    617          for (unsigned k = 0; k < 5; k++) {
    618             const bool accessed = (i == 2) && (j == 3);
    619             const unsigned linearized_index = k + (j * 5) + (i * 4 * 5);
    620 
    621             EXPECT_EQ(accessed,
    622                       entry_b->is_linearized_index_referenced(linearized_index)) <<
    623                "array b[" << i << "][" << j << "][" << k << "], " <<
    624                "linear index = " << linearized_index;
    625          }
    626       }
    627    }
    628 
    629    ir_array_refcount_entry *const entry_c = v.get_variable_entry(var_c);
    630 
    631    for (unsigned i = 0; i < var_c->type->array_size(); i++) {
    632       EXPECT_EQ(true, entry_c->is_linearized_index_referenced(i)) <<
    633          "array c, i = " << i;
    634    }
    635 
    636    validate_variables_in_hash_table(v.ht, 4, var_a, var_b, var_c, var_i);
    637 }
    638 
    639 TEST_F(array_refcount_test, visit_array_indexing_with_itself)
    640 {
    641    const glsl_type *const array_2_of_array_3_of_int =
    642       glsl_type::get_array_instance(array_3_of_int, 2);
    643 
    644    const glsl_type *const array_2_of_array_2_of_array_3_of_int =
    645       glsl_type::get_array_instance(array_2_of_array_3_of_int, 2);
    646 
    647    ir_variable *var_a = new(mem_ctx) ir_variable(glsl_type::int_type,
    648                                                  "a",
    649                                                  ir_var_auto);
    650    ir_variable *var_b = new(mem_ctx) ir_variable(array_2_of_array_2_of_array_3_of_int,
    651                                                  "b",
    652                                                  ir_var_auto);
    653 
    654    /* Given GLSL code:
    655     *
    656     *    int b[2][2][3];
    657     *    a = b[ b[0][0][0] ][ b[ b[0][1][0] ][ b[1][0][0] ][1] ][2]
    658     *
    659     * b[0][0][0], b[0][1][0], and b[1][0][0] are trivially accessed.
    660     *
    661     * b[*][*][1] and b[*][*][2] are accessed.
    662     *
    663     * Only b[1][1][0] is not accessed.
    664     */
    665    operand b000 = deref_array(
    666       deref_array(
    667          deref_array(var_b, body->constant(int(0))),
    668          body->constant(int(0))),
    669       body->constant(int(0)));
    670 
    671    operand b010 = deref_array(
    672       deref_array(
    673          deref_array(var_b, body->constant(int(0))),
    674          body->constant(int(1))),
    675       body->constant(int(0)));
    676 
    677    operand b100 = deref_array(
    678       deref_array(
    679          deref_array(var_b, body->constant(int(1))),
    680          body->constant(int(0))),
    681       body->constant(int(0)));
    682 
    683    operand b_b010_b100_1 = deref_array(
    684       deref_array(
    685          deref_array(var_b, b010),
    686          b100),
    687       body->constant(int(1)));
    688 
    689    body->emit(assign(var_a,
    690                      deref_array(
    691                         deref_array(
    692                            deref_array(var_b, b000),
    693                            b_b010_b100_1),
    694                         body->constant(int(2)))));
    695 
    696    ir_array_refcount_visitor v;
    697 
    698    visit_list_elements(&v, &instructions);
    699 
    700    ir_array_refcount_entry *const entry_b = v.get_variable_entry(var_b);
    701 
    702    for (unsigned i = 0; i < 2; i++) {
    703       for (unsigned j = 0; j < 2; j++) {
    704          for (unsigned k = 0; k < 3; k++) {
    705             const bool accessed = !(i == 1 && j == 1 && k == 0);
    706             const unsigned linearized_index = k + (j * 3) + (i * 2 * 3);
    707 
    708             EXPECT_EQ(accessed,
    709                       entry_b->is_linearized_index_referenced(linearized_index)) <<
    710                "array b[" << i << "][" << j << "][" << k << "], " <<
    711                "linear index = " << linearized_index;
    712          }
    713       }
    714    }
    715 
    716    validate_variables_in_hash_table(v.ht, 2, var_a, var_b);
    717 }
    718