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