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