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