vars_tests.cpp revision 7ec681f3
1/* 2 * Copyright © 2018 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 * DEALINGS IN THE SOFTWARE. 22 */ 23 24#include <gtest/gtest.h> 25 26#include "nir.h" 27#include "nir_builder.h" 28 29namespace { 30 31class nir_vars_test : public ::testing::Test { 32protected: 33 nir_vars_test(); 34 ~nir_vars_test(); 35 36 nir_variable *create_var(nir_variable_mode mode, const glsl_type *type, 37 const char *name) { 38 if (mode == nir_var_function_temp) 39 return nir_local_variable_create(b->impl, type, name); 40 else 41 return nir_variable_create(b->shader, mode, type, name); 42 } 43 44 nir_variable *create_int(nir_variable_mode mode, const char *name) { 45 return create_var(mode, glsl_int_type(), name); 46 } 47 48 nir_variable *create_ivec2(nir_variable_mode mode, const char *name) { 49 return create_var(mode, glsl_vector_type(GLSL_TYPE_INT, 2), name); 50 } 51 52 nir_variable *create_ivec4(nir_variable_mode mode, const char *name) { 53 return create_var(mode, glsl_vector_type(GLSL_TYPE_INT, 4), name); 54 } 55 56 nir_variable **create_many_int(nir_variable_mode mode, const char *prefix, unsigned count) { 57 nir_variable **result = (nir_variable **)linear_alloc_child(lin_ctx, sizeof(nir_variable *) * count); 58 for (unsigned i = 0; i < count; i++) 59 result[i] = create_int(mode, linear_asprintf(lin_ctx, "%s%u", prefix, i)); 60 return result; 61 } 62 63 nir_variable **create_many_ivec2(nir_variable_mode mode, const char *prefix, unsigned count) { 64 nir_variable **result = (nir_variable **)linear_alloc_child(lin_ctx, sizeof(nir_variable *) * count); 65 for (unsigned i = 0; i < count; i++) 66 result[i] = create_ivec2(mode, linear_asprintf(lin_ctx, "%s%u", prefix, i)); 67 return result; 68 } 69 70 nir_variable **create_many_ivec4(nir_variable_mode mode, const char *prefix, unsigned count) { 71 nir_variable **result = (nir_variable **)linear_alloc_child(lin_ctx, sizeof(nir_variable *) * count); 72 for (unsigned i = 0; i < count; i++) 73 result[i] = create_ivec4(mode, linear_asprintf(lin_ctx, "%s%u", prefix, i)); 74 return result; 75 } 76 77 unsigned count_derefs(nir_deref_type deref_type); 78 unsigned count_intrinsics(nir_intrinsic_op intrinsic); 79 unsigned count_function_temp_vars(void) { 80 return exec_list_length(&b->impl->locals); 81 } 82 83 unsigned count_shader_temp_vars(void) { 84 unsigned count = 0; 85 nir_foreach_variable_with_modes(var, b->shader, nir_var_shader_temp) 86 count++; 87 return count; 88 } 89 90 nir_intrinsic_instr *get_intrinsic(nir_intrinsic_op intrinsic, 91 unsigned index); 92 93 nir_deref_instr *get_deref(nir_deref_type deref_type, 94 unsigned index); 95 void *lin_ctx; 96 97 nir_builder *b, _b; 98}; 99 100nir_vars_test::nir_vars_test() 101{ 102 glsl_type_singleton_init_or_ref(); 103 104 static const nir_shader_compiler_options options = { }; 105 _b = nir_builder_init_simple_shader(MESA_SHADER_COMPUTE, &options, 106 "vars test"); 107 b = &_b; 108 lin_ctx = linear_alloc_parent(b->shader, 0); 109} 110 111nir_vars_test::~nir_vars_test() 112{ 113 if (HasFailure()) { 114 printf("\nShader from the failed test:\n\n"); 115 nir_print_shader(b->shader, stdout); 116 } 117 118 ralloc_free(b->shader); 119 120 glsl_type_singleton_decref(); 121} 122 123unsigned 124nir_vars_test::count_intrinsics(nir_intrinsic_op intrinsic) 125{ 126 unsigned count = 0; 127 nir_foreach_block(block, b->impl) { 128 nir_foreach_instr(instr, block) { 129 if (instr->type != nir_instr_type_intrinsic) 130 continue; 131 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); 132 if (intrin->intrinsic == intrinsic) 133 count++; 134 } 135 } 136 return count; 137} 138 139unsigned 140nir_vars_test::count_derefs(nir_deref_type deref_type) 141{ 142 unsigned count = 0; 143 nir_foreach_block(block, b->impl) { 144 nir_foreach_instr(instr, block) { 145 if (instr->type != nir_instr_type_deref) 146 continue; 147 nir_deref_instr *intrin = nir_instr_as_deref(instr); 148 if (intrin->deref_type == deref_type) 149 count++; 150 } 151 } 152 return count; 153} 154 155nir_intrinsic_instr * 156nir_vars_test::get_intrinsic(nir_intrinsic_op intrinsic, 157 unsigned index) 158{ 159 nir_foreach_block(block, b->impl) { 160 nir_foreach_instr(instr, block) { 161 if (instr->type != nir_instr_type_intrinsic) 162 continue; 163 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr); 164 if (intrin->intrinsic == intrinsic) { 165 if (index == 0) 166 return intrin; 167 index--; 168 } 169 } 170 } 171 return NULL; 172} 173 174nir_deref_instr * 175nir_vars_test::get_deref(nir_deref_type deref_type, 176 unsigned index) 177{ 178 nir_foreach_block(block, b->impl) { 179 nir_foreach_instr(instr, block) { 180 if (instr->type != nir_instr_type_deref) 181 continue; 182 nir_deref_instr *deref = nir_instr_as_deref(instr); 183 if (deref->deref_type == deref_type) { 184 if (index == 0) 185 return deref; 186 index--; 187 } 188 } 189 } 190 return NULL; 191} 192 193/* Allow grouping the tests while still sharing the helpers. */ 194class nir_redundant_load_vars_test : public nir_vars_test {}; 195class nir_copy_prop_vars_test : public nir_vars_test {}; 196class nir_dead_write_vars_test : public nir_vars_test {}; 197class nir_combine_stores_test : public nir_vars_test {}; 198class nir_split_vars_test : public nir_vars_test {}; 199class nir_remove_dead_variables_test : public nir_vars_test {}; 200 201} // namespace 202 203static nir_ssa_def * 204nir_load_var_volatile(nir_builder *b, nir_variable *var) 205{ 206 return nir_load_deref_with_access(b, nir_build_deref_var(b, var), 207 ACCESS_VOLATILE); 208} 209 210static void 211nir_store_var_volatile(nir_builder *b, nir_variable *var, 212 nir_ssa_def *value, nir_component_mask_t writemask) 213{ 214 nir_store_deref_with_access(b, nir_build_deref_var(b, var), 215 value, writemask, ACCESS_VOLATILE); 216} 217 218TEST_F(nir_redundant_load_vars_test, duplicated_load) 219{ 220 /* Load a variable twice in the same block. One should be removed. */ 221 222 nir_variable *in = create_int(nir_var_mem_ssbo, "in"); 223 nir_variable **out = create_many_int(nir_var_shader_out, "out", 2); 224 225 nir_store_var(b, out[0], nir_load_var(b, in), 1); 226 nir_store_var(b, out[1], nir_load_var(b, in), 1); 227 228 nir_validate_shader(b->shader, NULL); 229 230 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 2); 231 232 bool progress = nir_opt_copy_prop_vars(b->shader); 233 EXPECT_TRUE(progress); 234 235 nir_validate_shader(b->shader, NULL); 236 237 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1); 238} 239 240TEST_F(nir_redundant_load_vars_test, duplicated_load_volatile) 241{ 242 /* Load a variable twice in the same block. One should be removed. */ 243 244 nir_variable *in = create_int(nir_var_mem_ssbo, "in"); 245 nir_variable **out = create_many_int(nir_var_shader_out, "out", 3); 246 247 /* Volatile prevents us from eliminating a load by combining it with 248 * another. It shouldn't however, prevent us from combing other 249 * non-volatile loads. 250 */ 251 nir_store_var(b, out[0], nir_load_var(b, in), 1); 252 nir_store_var(b, out[1], nir_load_var_volatile(b, in), 1); 253 nir_store_var(b, out[2], nir_load_var(b, in), 1); 254 255 nir_validate_shader(b->shader, NULL); 256 257 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 3); 258 259 bool progress = nir_opt_copy_prop_vars(b->shader); 260 EXPECT_TRUE(progress); 261 262 nir_validate_shader(b->shader, NULL); 263 264 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 2); 265 266 nir_intrinsic_instr *first_store = get_intrinsic(nir_intrinsic_store_deref, 0); 267 ASSERT_TRUE(first_store->src[1].is_ssa); 268 269 nir_intrinsic_instr *third_store = get_intrinsic(nir_intrinsic_store_deref, 2); 270 ASSERT_TRUE(third_store->src[1].is_ssa); 271 272 EXPECT_EQ(first_store->src[1].ssa, third_store->src[1].ssa); 273} 274 275TEST_F(nir_redundant_load_vars_test, duplicated_load_in_two_blocks) 276{ 277 /* Load a variable twice in different blocks. One should be removed. */ 278 279 nir_variable *in = create_int(nir_var_mem_ssbo, "in"); 280 nir_variable **out = create_many_int(nir_var_shader_out, "out", 2); 281 282 nir_store_var(b, out[0], nir_load_var(b, in), 1); 283 284 /* Forces the stores to be in different blocks. */ 285 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0))); 286 287 nir_store_var(b, out[1], nir_load_var(b, in), 1); 288 289 nir_validate_shader(b->shader, NULL); 290 291 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 2); 292 293 bool progress = nir_opt_copy_prop_vars(b->shader); 294 EXPECT_TRUE(progress); 295 296 nir_validate_shader(b->shader, NULL); 297 298 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1); 299} 300 301TEST_F(nir_redundant_load_vars_test, invalidate_inside_if_block) 302{ 303 /* Load variables, then write to some of then in different branches of the 304 * if statement. They should be invalidated accordingly. 305 */ 306 307 nir_variable **g = create_many_int(nir_var_shader_temp, "g", 3); 308 nir_variable **out = create_many_int(nir_var_shader_out, "out", 3); 309 310 nir_load_var(b, g[0]); 311 nir_load_var(b, g[1]); 312 nir_load_var(b, g[2]); 313 314 nir_if *if_stmt = nir_push_if(b, nir_imm_int(b, 0)); 315 nir_store_var(b, g[0], nir_imm_int(b, 10), 1); 316 317 nir_push_else(b, if_stmt); 318 nir_store_var(b, g[1], nir_imm_int(b, 20), 1); 319 320 nir_pop_if(b, if_stmt); 321 322 nir_store_var(b, out[0], nir_load_var(b, g[0]), 1); 323 nir_store_var(b, out[1], nir_load_var(b, g[1]), 1); 324 nir_store_var(b, out[2], nir_load_var(b, g[2]), 1); 325 326 nir_validate_shader(b->shader, NULL); 327 328 bool progress = nir_opt_copy_prop_vars(b->shader); 329 EXPECT_TRUE(progress); 330 331 /* There are 3 initial loads, plus 2 loads for the values invalidated 332 * inside the if statement. 333 */ 334 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 5); 335 336 /* We only load g[2] once. */ 337 unsigned g2_load_count = 0; 338 for (int i = 0; i < 5; i++) { 339 nir_intrinsic_instr *load = get_intrinsic(nir_intrinsic_load_deref, i); 340 if (nir_intrinsic_get_var(load, 0) == g[2]) 341 g2_load_count++; 342 } 343 EXPECT_EQ(g2_load_count, 1); 344} 345 346TEST_F(nir_redundant_load_vars_test, invalidate_live_load_in_the_end_of_loop) 347{ 348 /* Invalidating a load in the end of loop body will apply to the whole loop 349 * body. 350 */ 351 352 nir_variable *v = create_int(nir_var_mem_ssbo, "v"); 353 354 nir_load_var(b, v); 355 356 nir_loop *loop = nir_push_loop(b); 357 358 nir_if *if_stmt = nir_push_if(b, nir_imm_int(b, 0)); 359 nir_jump(b, nir_jump_break); 360 nir_pop_if(b, if_stmt); 361 362 nir_load_var(b, v); 363 nir_store_var(b, v, nir_imm_int(b, 10), 1); 364 365 nir_pop_loop(b, loop); 366 367 bool progress = nir_opt_copy_prop_vars(b->shader); 368 ASSERT_FALSE(progress); 369} 370 371TEST_F(nir_copy_prop_vars_test, simple_copies) 372{ 373 nir_variable *in = create_int(nir_var_shader_in, "in"); 374 nir_variable *temp = create_int(nir_var_function_temp, "temp"); 375 nir_variable *out = create_int(nir_var_shader_out, "out"); 376 377 nir_copy_var(b, temp, in); 378 nir_copy_var(b, out, temp); 379 380 nir_validate_shader(b->shader, NULL); 381 382 bool progress = nir_opt_copy_prop_vars(b->shader); 383 EXPECT_TRUE(progress); 384 385 nir_validate_shader(b->shader, NULL); 386 387 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref), 2); 388 389 nir_intrinsic_instr *first_copy = get_intrinsic(nir_intrinsic_copy_deref, 0); 390 ASSERT_TRUE(first_copy->src[1].is_ssa); 391 392 nir_intrinsic_instr *second_copy = get_intrinsic(nir_intrinsic_copy_deref, 1); 393 ASSERT_TRUE(second_copy->src[1].is_ssa); 394 395 EXPECT_EQ(first_copy->src[1].ssa, second_copy->src[1].ssa); 396} 397 398TEST_F(nir_copy_prop_vars_test, self_copy) 399{ 400 nir_variable *v = create_int(nir_var_mem_ssbo, "v"); 401 402 nir_copy_var(b, v, v); 403 404 nir_validate_shader(b->shader, NULL); 405 406 bool progress = nir_opt_copy_prop_vars(b->shader); 407 EXPECT_TRUE(progress); 408 409 nir_validate_shader(b->shader, NULL); 410 411 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref), 0); 412} 413 414TEST_F(nir_copy_prop_vars_test, simple_store_load) 415{ 416 nir_variable **v = create_many_ivec2(nir_var_function_temp, "v", 2); 417 unsigned mask = 1 | 2; 418 419 nir_ssa_def *stored_value = nir_imm_ivec2(b, 10, 20); 420 nir_store_var(b, v[0], stored_value, mask); 421 422 nir_ssa_def *read_value = nir_load_var(b, v[0]); 423 nir_store_var(b, v[1], read_value, mask); 424 425 nir_validate_shader(b->shader, NULL); 426 427 bool progress = nir_opt_copy_prop_vars(b->shader); 428 EXPECT_TRUE(progress); 429 430 nir_validate_shader(b->shader, NULL); 431 432 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 2); 433 434 for (int i = 0; i < 2; i++) { 435 nir_intrinsic_instr *store = get_intrinsic(nir_intrinsic_store_deref, i); 436 ASSERT_TRUE(store->src[1].is_ssa); 437 EXPECT_EQ(store->src[1].ssa, stored_value); 438 } 439} 440 441TEST_F(nir_copy_prop_vars_test, store_store_load) 442{ 443 nir_variable **v = create_many_ivec2(nir_var_function_temp, "v", 2); 444 unsigned mask = 1 | 2; 445 446 nir_ssa_def *first_value = nir_imm_ivec2(b, 10, 20); 447 nir_store_var(b, v[0], first_value, mask); 448 449 nir_ssa_def *second_value = nir_imm_ivec2(b, 30, 40); 450 nir_store_var(b, v[0], second_value, mask); 451 452 nir_ssa_def *read_value = nir_load_var(b, v[0]); 453 nir_store_var(b, v[1], read_value, mask); 454 455 nir_validate_shader(b->shader, NULL); 456 457 bool progress = nir_opt_copy_prop_vars(b->shader); 458 EXPECT_TRUE(progress); 459 460 nir_validate_shader(b->shader, NULL); 461 462 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3); 463 464 /* Store to v[1] should use second_value directly. */ 465 nir_intrinsic_instr *store_to_v1 = get_intrinsic(nir_intrinsic_store_deref, 2); 466 ASSERT_EQ(nir_intrinsic_get_var(store_to_v1, 0), v[1]); 467 ASSERT_TRUE(store_to_v1->src[1].is_ssa); 468 EXPECT_EQ(store_to_v1->src[1].ssa, second_value); 469} 470 471TEST_F(nir_copy_prop_vars_test, store_store_load_different_components) 472{ 473 nir_variable **v = create_many_ivec2(nir_var_function_temp, "v", 2); 474 475 nir_ssa_def *first_value = nir_imm_ivec2(b, 10, 20); 476 nir_store_var(b, v[0], first_value, 1 << 1); 477 478 nir_ssa_def *second_value = nir_imm_ivec2(b, 30, 40); 479 nir_store_var(b, v[0], second_value, 1 << 0); 480 481 nir_ssa_def *read_value = nir_load_var(b, v[0]); 482 nir_store_var(b, v[1], read_value, 1 << 1); 483 484 nir_validate_shader(b->shader, NULL); 485 486 bool progress = nir_opt_copy_prop_vars(b->shader); 487 EXPECT_TRUE(progress); 488 489 nir_validate_shader(b->shader, NULL); 490 491 nir_opt_constant_folding(b->shader); 492 nir_validate_shader(b->shader, NULL); 493 494 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3); 495 496 /* Store to v[1] should use first_value directly. The write of 497 * second_value did not overwrite the component it uses. 498 */ 499 nir_intrinsic_instr *store_to_v1 = get_intrinsic(nir_intrinsic_store_deref, 2); 500 ASSERT_EQ(nir_intrinsic_get_var(store_to_v1, 0), v[1]); 501 ASSERT_EQ(nir_src_comp_as_uint(store_to_v1->src[1], 1), 20); 502} 503 504TEST_F(nir_copy_prop_vars_test, store_store_load_different_components_in_many_blocks) 505{ 506 nir_variable **v = create_many_ivec2(nir_var_function_temp, "v", 2); 507 508 nir_ssa_def *first_value = nir_imm_ivec2(b, 10, 20); 509 nir_store_var(b, v[0], first_value, 1 << 1); 510 511 /* Adding an if statement will cause blocks to be created. */ 512 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0))); 513 514 nir_ssa_def *second_value = nir_imm_ivec2(b, 30, 40); 515 nir_store_var(b, v[0], second_value, 1 << 0); 516 517 /* Adding an if statement will cause blocks to be created. */ 518 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0))); 519 520 nir_ssa_def *read_value = nir_load_var(b, v[0]); 521 nir_store_var(b, v[1], read_value, 1 << 1); 522 523 nir_validate_shader(b->shader, NULL); 524 525 bool progress = nir_opt_copy_prop_vars(b->shader); 526 EXPECT_TRUE(progress); 527 528 nir_validate_shader(b->shader, NULL); 529 530 nir_opt_constant_folding(b->shader); 531 nir_validate_shader(b->shader, NULL); 532 533 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3); 534 535 /* Store to v[1] should use first_value directly. The write of 536 * second_value did not overwrite the component it uses. 537 */ 538 nir_intrinsic_instr *store_to_v1 = get_intrinsic(nir_intrinsic_store_deref, 2); 539 ASSERT_EQ(nir_intrinsic_get_var(store_to_v1, 0), v[1]); 540 ASSERT_EQ(nir_src_comp_as_uint(store_to_v1->src[1], 1), 20); 541} 542 543TEST_F(nir_copy_prop_vars_test, store_volatile) 544{ 545 nir_variable **v = create_many_ivec2(nir_var_function_temp, "v", 2); 546 unsigned mask = 1 | 2; 547 548 nir_ssa_def *first_value = nir_imm_ivec2(b, 10, 20); 549 nir_store_var(b, v[0], first_value, mask); 550 551 nir_ssa_def *second_value = nir_imm_ivec2(b, 30, 40); 552 nir_store_var_volatile(b, v[0], second_value, mask); 553 554 nir_ssa_def *third_value = nir_imm_ivec2(b, 50, 60); 555 nir_store_var(b, v[0], third_value, mask); 556 557 nir_ssa_def *read_value = nir_load_var(b, v[0]); 558 nir_store_var(b, v[1], read_value, mask); 559 560 nir_validate_shader(b->shader, NULL); 561 562 bool progress = nir_opt_copy_prop_vars(b->shader); 563 EXPECT_TRUE(progress); 564 565 nir_validate_shader(b->shader, NULL); 566 567 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 4); 568 569 /* Our approach here is a bit scorched-earth. We expect the volatile store 570 * in the middle to cause both that store and the one before it to be kept. 571 * Technically, volatile only prevents combining the volatile store with 572 * another store and one could argue that the store before the volatile and 573 * the one after it could be combined. However, it seems safer to just 574 * treat a volatile store like an atomic and prevent any combining across 575 * it. 576 */ 577 nir_intrinsic_instr *store_to_v1 = get_intrinsic(nir_intrinsic_store_deref, 3); 578 ASSERT_EQ(nir_intrinsic_get_var(store_to_v1, 0), v[1]); 579 ASSERT_TRUE(store_to_v1->src[1].is_ssa); 580 EXPECT_EQ(store_to_v1->src[1].ssa, third_value); 581} 582 583TEST_F(nir_copy_prop_vars_test, self_copy_volatile) 584{ 585 nir_variable *v = create_int(nir_var_mem_ssbo, "v"); 586 587 nir_copy_var(b, v, v); 588 nir_copy_deref_with_access(b, nir_build_deref_var(b, v), 589 nir_build_deref_var(b, v), 590 (gl_access_qualifier)0, ACCESS_VOLATILE); 591 nir_copy_deref_with_access(b, nir_build_deref_var(b, v), 592 nir_build_deref_var(b, v), 593 ACCESS_VOLATILE, (gl_access_qualifier)0); 594 nir_copy_var(b, v, v); 595 596 nir_validate_shader(b->shader, NULL); 597 598 bool progress = nir_opt_copy_prop_vars(b->shader); 599 EXPECT_TRUE(progress); 600 601 nir_validate_shader(b->shader, NULL); 602 603 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref), 2); 604 605 /* Store to v[1] should use second_value directly. */ 606 nir_intrinsic_instr *first = get_intrinsic(nir_intrinsic_copy_deref, 0); 607 nir_intrinsic_instr *second = get_intrinsic(nir_intrinsic_copy_deref, 1); 608 ASSERT_EQ(nir_intrinsic_src_access(first), ACCESS_VOLATILE); 609 ASSERT_EQ(nir_intrinsic_dst_access(first), (gl_access_qualifier)0); 610 ASSERT_EQ(nir_intrinsic_src_access(second), (gl_access_qualifier)0); 611 ASSERT_EQ(nir_intrinsic_dst_access(second), ACCESS_VOLATILE); 612} 613 614TEST_F(nir_copy_prop_vars_test, memory_barrier_in_two_blocks) 615{ 616 nir_variable **v = create_many_int(nir_var_mem_ssbo, "v", 4); 617 618 nir_store_var(b, v[0], nir_imm_int(b, 1), 1); 619 nir_store_var(b, v[1], nir_imm_int(b, 2), 1); 620 621 /* Split into many blocks. */ 622 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0))); 623 624 nir_store_var(b, v[2], nir_load_var(b, v[0]), 1); 625 626 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_ACQ_REL, 627 nir_var_mem_ssbo); 628 629 nir_store_var(b, v[3], nir_load_var(b, v[1]), 1); 630 631 bool progress = nir_opt_copy_prop_vars(b->shader); 632 ASSERT_TRUE(progress); 633 634 /* Only the second load will remain after the optimization. */ 635 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_load_deref)); 636 nir_intrinsic_instr *load = get_intrinsic(nir_intrinsic_load_deref, 0); 637 ASSERT_EQ(nir_intrinsic_get_var(load, 0), v[1]); 638} 639 640TEST_F(nir_redundant_load_vars_test, acquire_barrier_prevents_load_removal) 641{ 642 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 1); 643 644 nir_load_var(b, x[0]); 645 646 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_ACQUIRE, 647 nir_var_mem_ssbo); 648 649 nir_load_var(b, x[0]); 650 651 bool progress = nir_opt_copy_prop_vars(b->shader); 652 ASSERT_FALSE(progress); 653 654 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref)); 655} 656 657TEST_F(nir_redundant_load_vars_test, acquire_barrier_prevents_same_mode_load_removal) 658{ 659 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 2); 660 661 nir_load_var(b, x[0]); 662 nir_load_var(b, x[1]); 663 664 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_ACQUIRE, 665 nir_var_mem_ssbo); 666 667 nir_load_var(b, x[0]); 668 nir_load_var(b, x[1]); 669 670 bool progress = nir_opt_copy_prop_vars(b->shader); 671 ASSERT_FALSE(progress); 672 673 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_load_deref)); 674} 675 676TEST_F(nir_redundant_load_vars_test, acquire_barrier_allows_different_mode_load_removal) 677{ 678 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 2); 679 nir_variable **y = create_many_int(nir_var_mem_shared, "y", 2); 680 681 nir_load_var(b, x[0]); 682 nir_load_var(b, x[1]); 683 nir_load_var(b, y[0]); 684 nir_load_var(b, y[1]); 685 686 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_ACQUIRE, 687 nir_var_mem_ssbo); 688 689 nir_load_var(b, x[0]); 690 nir_load_var(b, x[1]); 691 nir_load_var(b, y[0]); 692 nir_load_var(b, y[1]); 693 694 bool progress = nir_opt_copy_prop_vars(b->shader); 695 ASSERT_TRUE(progress); 696 697 ASSERT_EQ(6, count_intrinsics(nir_intrinsic_load_deref)); 698 699 nir_intrinsic_instr *load; 700 701 load = get_intrinsic(nir_intrinsic_load_deref, 0); 702 ASSERT_EQ(nir_intrinsic_get_var(load, 0), x[0]); 703 load = get_intrinsic(nir_intrinsic_load_deref, 1); 704 ASSERT_EQ(nir_intrinsic_get_var(load, 0), x[1]); 705 706 load = get_intrinsic(nir_intrinsic_load_deref, 2); 707 ASSERT_EQ(nir_intrinsic_get_var(load, 0), y[0]); 708 load = get_intrinsic(nir_intrinsic_load_deref, 3); 709 ASSERT_EQ(nir_intrinsic_get_var(load, 0), y[1]); 710 711 load = get_intrinsic(nir_intrinsic_load_deref, 4); 712 ASSERT_EQ(nir_intrinsic_get_var(load, 0), x[0]); 713 load = get_intrinsic(nir_intrinsic_load_deref, 5); 714 ASSERT_EQ(nir_intrinsic_get_var(load, 0), x[1]); 715} 716 717TEST_F(nir_redundant_load_vars_test, release_barrier_allows_load_removal) 718{ 719 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 1); 720 721 nir_load_var(b, x[0]); 722 723 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_RELEASE, 724 nir_var_mem_ssbo); 725 726 nir_load_var(b, x[0]); 727 728 bool progress = nir_opt_copy_prop_vars(b->shader); 729 ASSERT_TRUE(progress); 730 731 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_load_deref)); 732} 733 734TEST_F(nir_redundant_load_vars_test, release_barrier_allows_same_mode_load_removal) 735{ 736 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 2); 737 738 nir_load_var(b, x[0]); 739 nir_load_var(b, x[1]); 740 741 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_RELEASE, 742 nir_var_mem_ssbo); 743 744 nir_load_var(b, x[0]); 745 nir_load_var(b, x[1]); 746 747 bool progress = nir_opt_copy_prop_vars(b->shader); 748 ASSERT_TRUE(progress); 749 750 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref)); 751} 752 753TEST_F(nir_redundant_load_vars_test, release_barrier_allows_different_mode_load_removal) 754{ 755 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 2); 756 nir_variable **y = create_many_int(nir_var_mem_shared, "y", 2); 757 758 nir_load_var(b, x[0]); 759 nir_load_var(b, x[1]); 760 nir_load_var(b, y[0]); 761 nir_load_var(b, y[1]); 762 763 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_RELEASE, 764 nir_var_mem_ssbo); 765 766 nir_load_var(b, x[0]); 767 nir_load_var(b, x[1]); 768 nir_load_var(b, y[0]); 769 nir_load_var(b, y[1]); 770 771 bool progress = nir_opt_copy_prop_vars(b->shader); 772 ASSERT_TRUE(progress); 773 774 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_load_deref)); 775 776 nir_intrinsic_instr *load; 777 778 load = get_intrinsic(nir_intrinsic_load_deref, 0); 779 ASSERT_EQ(nir_intrinsic_get_var(load, 0), x[0]); 780 load = get_intrinsic(nir_intrinsic_load_deref, 1); 781 ASSERT_EQ(nir_intrinsic_get_var(load, 0), x[1]); 782 783 load = get_intrinsic(nir_intrinsic_load_deref, 2); 784 ASSERT_EQ(nir_intrinsic_get_var(load, 0), y[0]); 785 load = get_intrinsic(nir_intrinsic_load_deref, 3); 786 ASSERT_EQ(nir_intrinsic_get_var(load, 0), y[1]); 787} 788 789TEST_F(nir_copy_prop_vars_test, acquire_barrier_prevents_propagation) 790{ 791 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 1); 792 793 nir_store_var(b, x[0], nir_imm_int(b, 10), 1); 794 795 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_ACQUIRE, 796 nir_var_mem_ssbo); 797 798 nir_load_var(b, x[0]); 799 800 bool progress = nir_opt_copy_prop_vars(b->shader); 801 ASSERT_FALSE(progress); 802 803 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_store_deref)); 804 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_load_deref)); 805} 806 807TEST_F(nir_copy_prop_vars_test, acquire_barrier_prevents_same_mode_propagation) 808{ 809 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 2); 810 811 nir_store_var(b, x[0], nir_imm_int(b, 10), 1); 812 nir_store_var(b, x[1], nir_imm_int(b, 20), 1); 813 814 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_ACQUIRE, 815 nir_var_mem_ssbo); 816 817 nir_load_var(b, x[0]); 818 nir_load_var(b, x[1]); 819 820 bool progress = nir_opt_copy_prop_vars(b->shader); 821 ASSERT_FALSE(progress); 822 823 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_store_deref)); 824 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref)); 825} 826 827TEST_F(nir_copy_prop_vars_test, acquire_barrier_allows_different_mode_propagation) 828{ 829 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 2); 830 nir_variable **y = create_many_int(nir_var_mem_shared, "y", 2); 831 832 nir_store_var(b, x[0], nir_imm_int(b, 10), 1); 833 nir_store_var(b, x[1], nir_imm_int(b, 20), 1); 834 nir_store_var(b, y[0], nir_imm_int(b, 30), 1); 835 nir_store_var(b, y[1], nir_imm_int(b, 40), 1); 836 837 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_ACQUIRE, 838 nir_var_mem_ssbo); 839 840 nir_load_var(b, x[0]); 841 nir_load_var(b, x[1]); 842 nir_load_var(b, y[0]); 843 nir_load_var(b, y[1]); 844 845 bool progress = nir_opt_copy_prop_vars(b->shader); 846 ASSERT_TRUE(progress); 847 848 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_store_deref)); 849 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref)); 850 851 nir_intrinsic_instr *store; 852 853 store = get_intrinsic(nir_intrinsic_store_deref, 0); 854 ASSERT_EQ(nir_intrinsic_get_var(store, 0), x[0]); 855 store = get_intrinsic(nir_intrinsic_store_deref, 1); 856 ASSERT_EQ(nir_intrinsic_get_var(store, 0), x[1]); 857 858 store = get_intrinsic(nir_intrinsic_store_deref, 2); 859 ASSERT_EQ(nir_intrinsic_get_var(store, 0), y[0]); 860 store = get_intrinsic(nir_intrinsic_store_deref, 3); 861 ASSERT_EQ(nir_intrinsic_get_var(store, 0), y[1]); 862 863 nir_intrinsic_instr *load; 864 865 load = get_intrinsic(nir_intrinsic_load_deref, 0); 866 ASSERT_EQ(nir_intrinsic_get_var(load, 0), x[0]); 867 load = get_intrinsic(nir_intrinsic_load_deref, 1); 868 ASSERT_EQ(nir_intrinsic_get_var(load, 0), x[1]); 869} 870 871TEST_F(nir_copy_prop_vars_test, release_barrier_allows_propagation) 872{ 873 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 1); 874 875 nir_store_var(b, x[0], nir_imm_int(b, 10), 1); 876 877 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_RELEASE, 878 nir_var_mem_ssbo); 879 880 nir_load_var(b, x[0]); 881 882 bool progress = nir_opt_copy_prop_vars(b->shader); 883 ASSERT_TRUE(progress); 884 885 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_store_deref)); 886} 887 888TEST_F(nir_copy_prop_vars_test, release_barrier_allows_same_mode_propagation) 889{ 890 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 2); 891 892 nir_store_var(b, x[0], nir_imm_int(b, 10), 1); 893 nir_store_var(b, x[1], nir_imm_int(b, 20), 1); 894 895 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_RELEASE, 896 nir_var_mem_ssbo); 897 898 nir_load_var(b, x[0]); 899 nir_load_var(b, x[1]); 900 901 bool progress = nir_opt_copy_prop_vars(b->shader); 902 ASSERT_TRUE(progress); 903 904 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_store_deref)); 905 ASSERT_EQ(0, count_intrinsics(nir_intrinsic_load_deref)); 906} 907 908TEST_F(nir_copy_prop_vars_test, release_barrier_allows_different_mode_propagation) 909{ 910 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 2); 911 nir_variable **y = create_many_int(nir_var_mem_shared, "y", 2); 912 913 nir_store_var(b, x[0], nir_imm_int(b, 10), 1); 914 nir_store_var(b, x[1], nir_imm_int(b, 20), 1); 915 nir_store_var(b, y[0], nir_imm_int(b, 30), 1); 916 nir_store_var(b, y[1], nir_imm_int(b, 40), 1); 917 918 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_RELEASE, 919 nir_var_mem_ssbo); 920 921 nir_load_var(b, x[0]); 922 nir_load_var(b, x[1]); 923 nir_load_var(b, y[0]); 924 nir_load_var(b, y[1]); 925 926 bool progress = nir_opt_copy_prop_vars(b->shader); 927 ASSERT_TRUE(progress); 928 929 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_store_deref)); 930 ASSERT_EQ(0, count_intrinsics(nir_intrinsic_load_deref)); 931 932 nir_intrinsic_instr *store; 933 934 store = get_intrinsic(nir_intrinsic_store_deref, 0); 935 ASSERT_EQ(nir_intrinsic_get_var(store, 0), x[0]); 936 store = get_intrinsic(nir_intrinsic_store_deref, 1); 937 ASSERT_EQ(nir_intrinsic_get_var(store, 0), x[1]); 938 939 store = get_intrinsic(nir_intrinsic_store_deref, 2); 940 ASSERT_EQ(nir_intrinsic_get_var(store, 0), y[0]); 941 store = get_intrinsic(nir_intrinsic_store_deref, 3); 942 ASSERT_EQ(nir_intrinsic_get_var(store, 0), y[1]); 943} 944 945TEST_F(nir_copy_prop_vars_test, acquire_barrier_prevents_propagation_from_copy) 946{ 947 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 3); 948 949 nir_copy_var(b, x[1], x[0]); 950 951 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_ACQUIRE, 952 nir_var_mem_ssbo); 953 954 nir_copy_var(b, x[2], x[1]); 955 956 bool progress = nir_opt_copy_prop_vars(b->shader); 957 ASSERT_FALSE(progress); 958 959 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref)); 960 961 nir_intrinsic_instr *copy; 962 963 copy = get_intrinsic(nir_intrinsic_copy_deref, 0); 964 ASSERT_EQ(nir_intrinsic_get_var(copy, 1), x[0]); 965 966 copy = get_intrinsic(nir_intrinsic_copy_deref, 1); 967 ASSERT_EQ(nir_intrinsic_get_var(copy, 1), x[1]); 968} 969 970TEST_F(nir_copy_prop_vars_test, acquire_barrier_prevents_propagation_from_copy_to_different_mode) 971{ 972 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 2); 973 nir_variable **y = create_many_int(nir_var_mem_shared, "y", 1); 974 975 nir_copy_var(b, y[0], x[0]); 976 977 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_ACQUIRE, 978 nir_var_mem_ssbo); 979 980 nir_copy_var(b, x[1], y[0]); 981 982 bool progress = nir_opt_copy_prop_vars(b->shader); 983 ASSERT_FALSE(progress); 984 985 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref)); 986 987 nir_intrinsic_instr *copy; 988 989 copy = get_intrinsic(nir_intrinsic_copy_deref, 0); 990 ASSERT_EQ(nir_intrinsic_get_var(copy, 1), x[0]); 991 992 copy = get_intrinsic(nir_intrinsic_copy_deref, 1); 993 ASSERT_EQ(nir_intrinsic_get_var(copy, 1), y[0]); 994} 995 996TEST_F(nir_copy_prop_vars_test, release_barrier_allows_propagation_from_copy) 997{ 998 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 3); 999 1000 nir_copy_var(b, x[1], x[0]); 1001 1002 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_RELEASE, 1003 nir_var_mem_ssbo); 1004 1005 nir_copy_var(b, x[2], x[1]); 1006 1007 bool progress = nir_opt_copy_prop_vars(b->shader); 1008 ASSERT_TRUE(progress); 1009 1010 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref)); 1011 1012 nir_intrinsic_instr *copy; 1013 1014 copy = get_intrinsic(nir_intrinsic_copy_deref, 0); 1015 ASSERT_EQ(nir_intrinsic_get_var(copy, 1), x[0]); 1016 1017 copy = get_intrinsic(nir_intrinsic_copy_deref, 1); 1018 ASSERT_EQ(nir_intrinsic_get_var(copy, 1), x[0]); 1019} 1020 1021TEST_F(nir_copy_prop_vars_test, release_barrier_allows_propagation_from_copy_to_different_mode) 1022{ 1023 nir_variable **x = create_many_int(nir_var_mem_ssbo, "x", 2); 1024 nir_variable **y = create_many_int(nir_var_mem_shared, "y", 1); 1025 1026 nir_copy_var(b, y[0], x[0]); 1027 1028 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_RELEASE, 1029 nir_var_mem_ssbo); 1030 1031 nir_copy_var(b, x[1], y[0]); 1032 1033 bool progress = nir_opt_copy_prop_vars(b->shader); 1034 ASSERT_TRUE(progress); 1035 1036 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref)); 1037 1038 nir_intrinsic_instr *copy; 1039 1040 copy = get_intrinsic(nir_intrinsic_copy_deref, 0); 1041 ASSERT_EQ(nir_intrinsic_get_var(copy, 1), x[0]); 1042 1043 copy = get_intrinsic(nir_intrinsic_copy_deref, 1); 1044 ASSERT_EQ(nir_intrinsic_get_var(copy, 1), x[0]); 1045} 1046 1047TEST_F(nir_copy_prop_vars_test, simple_store_load_in_two_blocks) 1048{ 1049 nir_variable **v = create_many_ivec2(nir_var_function_temp, "v", 2); 1050 unsigned mask = 1 | 2; 1051 1052 nir_ssa_def *stored_value = nir_imm_ivec2(b, 10, 20); 1053 nir_store_var(b, v[0], stored_value, mask); 1054 1055 /* Adding an if statement will cause blocks to be created. */ 1056 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0))); 1057 1058 nir_ssa_def *read_value = nir_load_var(b, v[0]); 1059 nir_store_var(b, v[1], read_value, mask); 1060 1061 nir_validate_shader(b->shader, NULL); 1062 1063 bool progress = nir_opt_copy_prop_vars(b->shader); 1064 EXPECT_TRUE(progress); 1065 1066 nir_validate_shader(b->shader, NULL); 1067 1068 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 2); 1069 1070 for (int i = 0; i < 2; i++) { 1071 nir_intrinsic_instr *store = get_intrinsic(nir_intrinsic_store_deref, i); 1072 ASSERT_TRUE(store->src[1].is_ssa); 1073 EXPECT_EQ(store->src[1].ssa, stored_value); 1074 } 1075} 1076 1077TEST_F(nir_copy_prop_vars_test, load_direct_array_deref_on_vector_reuses_previous_load) 1078{ 1079 nir_variable *in0 = create_ivec2(nir_var_mem_ssbo, "in0"); 1080 nir_variable *in1 = create_ivec2(nir_var_mem_ssbo, "in1"); 1081 nir_variable *vec = create_ivec2(nir_var_mem_ssbo, "vec"); 1082 nir_variable *out = create_int(nir_var_mem_ssbo, "out"); 1083 1084 nir_store_var(b, vec, nir_load_var(b, in0), 1 << 0); 1085 nir_store_var(b, vec, nir_load_var(b, in1), 1 << 1); 1086 1087 /* This load will be dropped, as vec.y (or vec[1]) is already known. */ 1088 nir_deref_instr *deref = 1089 nir_build_deref_array_imm(b, nir_build_deref_var(b, vec), 1); 1090 nir_ssa_def *loaded_from_deref = nir_load_deref(b, deref); 1091 1092 /* This store should use the value loaded from in1. */ 1093 nir_store_var(b, out, loaded_from_deref, 1 << 0); 1094 1095 nir_validate_shader(b->shader, NULL); 1096 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 3); 1097 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3); 1098 1099 bool progress = nir_opt_copy_prop_vars(b->shader); 1100 EXPECT_TRUE(progress); 1101 1102 nir_validate_shader(b->shader, NULL); 1103 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 2); 1104 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3); 1105 1106 nir_intrinsic_instr *store = get_intrinsic(nir_intrinsic_store_deref, 2); 1107 ASSERT_TRUE(store->src[1].is_ssa); 1108 1109 /* NOTE: The ALU instruction is how we get the vec.y. */ 1110 ASSERT_TRUE(nir_src_as_alu_instr(store->src[1])); 1111} 1112 1113TEST_F(nir_copy_prop_vars_test, load_direct_array_deref_on_vector_reuses_previous_copy) 1114{ 1115 nir_variable *in0 = create_ivec2(nir_var_mem_ssbo, "in0"); 1116 nir_variable *vec = create_ivec2(nir_var_mem_ssbo, "vec"); 1117 1118 nir_copy_var(b, vec, in0); 1119 1120 /* This load will be replaced with one from in0. */ 1121 nir_deref_instr *deref = 1122 nir_build_deref_array_imm(b, nir_build_deref_var(b, vec), 1); 1123 nir_load_deref(b, deref); 1124 1125 nir_validate_shader(b->shader, NULL); 1126 1127 bool progress = nir_opt_copy_prop_vars(b->shader); 1128 EXPECT_TRUE(progress); 1129 1130 nir_validate_shader(b->shader, NULL); 1131 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1); 1132 1133 nir_intrinsic_instr *load = get_intrinsic(nir_intrinsic_load_deref, 0); 1134 ASSERT_EQ(nir_intrinsic_get_var(load, 0), in0); 1135} 1136 1137TEST_F(nir_copy_prop_vars_test, load_direct_array_deref_on_vector_gets_reused) 1138{ 1139 nir_variable *in0 = create_ivec2(nir_var_mem_ssbo, "in0"); 1140 nir_variable *vec = create_ivec2(nir_var_mem_ssbo, "vec"); 1141 nir_variable *out = create_ivec2(nir_var_mem_ssbo, "out"); 1142 1143 /* Loading "vec[1]" deref will save the information about vec.y. */ 1144 nir_deref_instr *deref = 1145 nir_build_deref_array_imm(b, nir_build_deref_var(b, vec), 1); 1146 nir_load_deref(b, deref); 1147 1148 /* Store to vec.x. */ 1149 nir_store_var(b, vec, nir_load_var(b, in0), 1 << 0); 1150 1151 /* This load will be dropped, since both vec.x and vec.y are known. */ 1152 nir_ssa_def *loaded_from_vec = nir_load_var(b, vec); 1153 nir_store_var(b, out, loaded_from_vec, 0x3); 1154 1155 nir_validate_shader(b->shader, NULL); 1156 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 3); 1157 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 2); 1158 1159 bool progress = nir_opt_copy_prop_vars(b->shader); 1160 EXPECT_TRUE(progress); 1161 1162 nir_validate_shader(b->shader, NULL); 1163 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 2); 1164 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 2); 1165 1166 nir_intrinsic_instr *store = get_intrinsic(nir_intrinsic_store_deref, 1); 1167 ASSERT_TRUE(store->src[1].is_ssa); 1168 ASSERT_TRUE(nir_src_as_alu_instr(store->src[1])); 1169} 1170 1171TEST_F(nir_copy_prop_vars_test, store_load_direct_array_deref_on_vector) 1172{ 1173 nir_variable *vec = create_ivec2(nir_var_mem_ssbo, "vec"); 1174 nir_variable *out0 = create_int(nir_var_mem_ssbo, "out0"); 1175 nir_variable *out1 = create_ivec2(nir_var_mem_ssbo, "out1"); 1176 1177 /* Store to "vec[1]" and "vec[0]". */ 1178 nir_deref_instr *store_deref_y = 1179 nir_build_deref_array_imm(b, nir_build_deref_var(b, vec), 1); 1180 nir_store_deref(b, store_deref_y, nir_imm_int(b, 20), 1); 1181 1182 nir_deref_instr *store_deref_x = 1183 nir_build_deref_array_imm(b, nir_build_deref_var(b, vec), 0); 1184 nir_store_deref(b, store_deref_x, nir_imm_int(b, 10), 1); 1185 1186 /* Both loads below will be dropped, because the values are already known. */ 1187 nir_deref_instr *load_deref_y = 1188 nir_build_deref_array_imm(b, nir_build_deref_var(b, vec), 1); 1189 nir_store_var(b, out0, nir_load_deref(b, load_deref_y), 1); 1190 1191 nir_store_var(b, out1, nir_load_var(b, vec), 1); 1192 1193 nir_validate_shader(b->shader, NULL); 1194 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 2); 1195 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 4); 1196 1197 bool progress = nir_opt_copy_prop_vars(b->shader); 1198 EXPECT_TRUE(progress); 1199 1200 nir_validate_shader(b->shader, NULL); 1201 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 0); 1202 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 4); 1203 1204 /* Third store will just use the value from first store. */ 1205 nir_intrinsic_instr *first_store = get_intrinsic(nir_intrinsic_store_deref, 0); 1206 nir_intrinsic_instr *third_store = get_intrinsic(nir_intrinsic_store_deref, 2); 1207 ASSERT_TRUE(third_store->src[1].is_ssa); 1208 EXPECT_EQ(third_store->src[1].ssa, first_store->src[1].ssa); 1209 1210 /* Fourth store will compose first and second store values. */ 1211 nir_intrinsic_instr *fourth_store = get_intrinsic(nir_intrinsic_store_deref, 3); 1212 ASSERT_TRUE(fourth_store->src[1].is_ssa); 1213 EXPECT_TRUE(nir_src_as_alu_instr(fourth_store->src[1])); 1214} 1215 1216TEST_F(nir_copy_prop_vars_test, store_load_indirect_array_deref_on_vector) 1217{ 1218 nir_variable *vec = create_ivec2(nir_var_mem_ssbo, "vec"); 1219 nir_variable *idx = create_int(nir_var_mem_ssbo, "idx"); 1220 nir_variable *out = create_int(nir_var_mem_ssbo, "out"); 1221 1222 nir_ssa_def *idx_ssa = nir_load_var(b, idx); 1223 1224 /* Store to vec[idx]. */ 1225 nir_deref_instr *store_deref = 1226 nir_build_deref_array(b, nir_build_deref_var(b, vec), idx_ssa); 1227 nir_store_deref(b, store_deref, nir_imm_int(b, 20), 1); 1228 1229 /* Load from vec[idx] to store in out. This load should be dropped. */ 1230 nir_deref_instr *load_deref = 1231 nir_build_deref_array(b, nir_build_deref_var(b, vec), idx_ssa); 1232 nir_store_var(b, out, nir_load_deref(b, load_deref), 1); 1233 1234 nir_validate_shader(b->shader, NULL); 1235 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 2); 1236 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 2); 1237 1238 bool progress = nir_opt_copy_prop_vars(b->shader); 1239 EXPECT_TRUE(progress); 1240 1241 nir_validate_shader(b->shader, NULL); 1242 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1); 1243 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 2); 1244 1245 /* Store to vec[idx] propagated to out. */ 1246 nir_intrinsic_instr *first = get_intrinsic(nir_intrinsic_store_deref, 0); 1247 nir_intrinsic_instr *second = get_intrinsic(nir_intrinsic_store_deref, 1); 1248 ASSERT_TRUE(first->src[1].is_ssa); 1249 ASSERT_TRUE(second->src[1].is_ssa); 1250 EXPECT_EQ(first->src[1].ssa, second->src[1].ssa); 1251} 1252 1253TEST_F(nir_copy_prop_vars_test, store_load_direct_and_indirect_array_deref_on_vector) 1254{ 1255 nir_variable *vec = create_ivec2(nir_var_mem_ssbo, "vec"); 1256 nir_variable *idx = create_int(nir_var_mem_ssbo, "idx"); 1257 nir_variable **out = create_many_int(nir_var_mem_ssbo, "out", 2); 1258 1259 nir_ssa_def *idx_ssa = nir_load_var(b, idx); 1260 1261 /* Store to vec. */ 1262 nir_store_var(b, vec, nir_imm_ivec2(b, 10, 10), 1 | 2); 1263 1264 /* Load from vec[idx]. This load is currently not dropped. */ 1265 nir_deref_instr *indirect = 1266 nir_build_deref_array(b, nir_build_deref_var(b, vec), idx_ssa); 1267 nir_store_var(b, out[0], nir_load_deref(b, indirect), 1); 1268 1269 /* Load from vec[idx] again. This load should be dropped. */ 1270 nir_store_var(b, out[1], nir_load_deref(b, indirect), 1); 1271 1272 nir_validate_shader(b->shader, NULL); 1273 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 3); 1274 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3); 1275 1276 bool progress = nir_opt_copy_prop_vars(b->shader); 1277 EXPECT_TRUE(progress); 1278 1279 nir_validate_shader(b->shader, NULL); 1280 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 2); 1281 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3); 1282 1283 /* Store to vec[idx] propagated to out. */ 1284 nir_intrinsic_instr *second = get_intrinsic(nir_intrinsic_store_deref, 1); 1285 nir_intrinsic_instr *third = get_intrinsic(nir_intrinsic_store_deref, 2); 1286 ASSERT_TRUE(second->src[1].is_ssa); 1287 ASSERT_TRUE(third->src[1].is_ssa); 1288 EXPECT_EQ(second->src[1].ssa, third->src[1].ssa); 1289} 1290 1291TEST_F(nir_copy_prop_vars_test, store_load_indirect_array_deref) 1292{ 1293 nir_variable *arr = create_var(nir_var_mem_ssbo, 1294 glsl_array_type(glsl_int_type(), 10, 0), 1295 "arr"); 1296 nir_variable *idx = create_int(nir_var_mem_ssbo, "idx"); 1297 nir_variable *out = create_int(nir_var_mem_ssbo, "out"); 1298 1299 nir_ssa_def *idx_ssa = nir_load_var(b, idx); 1300 1301 /* Store to arr[idx]. */ 1302 nir_deref_instr *store_deref = 1303 nir_build_deref_array(b, nir_build_deref_var(b, arr), idx_ssa); 1304 nir_store_deref(b, store_deref, nir_imm_int(b, 20), 1); 1305 1306 /* Load from arr[idx] to store in out. This load should be dropped. */ 1307 nir_deref_instr *load_deref = 1308 nir_build_deref_array(b, nir_build_deref_var(b, arr), idx_ssa); 1309 nir_store_var(b, out, nir_load_deref(b, load_deref), 1); 1310 1311 nir_validate_shader(b->shader, NULL); 1312 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 2); 1313 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 2); 1314 1315 bool progress = nir_opt_copy_prop_vars(b->shader); 1316 EXPECT_TRUE(progress); 1317 1318 nir_validate_shader(b->shader, NULL); 1319 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1); 1320 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 2); 1321 1322 /* Store to arr[idx] propagated to out. */ 1323 nir_intrinsic_instr *first = get_intrinsic(nir_intrinsic_store_deref, 0); 1324 nir_intrinsic_instr *second = get_intrinsic(nir_intrinsic_store_deref, 1); 1325 ASSERT_TRUE(first->src[1].is_ssa); 1326 ASSERT_TRUE(second->src[1].is_ssa); 1327 EXPECT_EQ(first->src[1].ssa, second->src[1].ssa); 1328} 1329 1330TEST_F(nir_dead_write_vars_test, no_dead_writes_in_block) 1331{ 1332 nir_variable **v = create_many_int(nir_var_mem_ssbo, "v", 2); 1333 1334 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1); 1335 1336 bool progress = nir_opt_dead_write_vars(b->shader); 1337 ASSERT_FALSE(progress); 1338} 1339 1340TEST_F(nir_dead_write_vars_test, no_dead_writes_different_components_in_block) 1341{ 1342 nir_variable **v = create_many_ivec2(nir_var_mem_ssbo, "v", 3); 1343 1344 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1 << 0); 1345 nir_store_var(b, v[0], nir_load_var(b, v[2]), 1 << 1); 1346 1347 bool progress = nir_opt_dead_write_vars(b->shader); 1348 ASSERT_FALSE(progress); 1349} 1350 1351TEST_F(nir_dead_write_vars_test, volatile_write) 1352{ 1353 nir_variable *v = create_int(nir_var_mem_ssbo, "v"); 1354 1355 nir_store_var(b, v, nir_imm_int(b, 0), 0x1); 1356 nir_store_var_volatile(b, v, nir_imm_int(b, 1), 0x1); 1357 nir_store_var(b, v, nir_imm_int(b, 2), 0x1); 1358 1359 /* Our approach here is a bit scorched-earth. We expect the volatile store 1360 * in the middle to cause both that store and the one before it to be kept. 1361 * Technically, volatile only prevents combining the volatile store with 1362 * another store and one could argue that the store before the volatile and 1363 * the one after it could be combined. However, it seems safer to just 1364 * treat a volatile store like an atomic and prevent any combining across 1365 * it. 1366 */ 1367 bool progress = nir_opt_dead_write_vars(b->shader); 1368 ASSERT_FALSE(progress); 1369} 1370 1371TEST_F(nir_dead_write_vars_test, volatile_copies) 1372{ 1373 nir_variable **v = create_many_int(nir_var_mem_ssbo, "v", 2); 1374 1375 nir_copy_var(b, v[0], v[1]); 1376 nir_copy_deref_with_access(b, nir_build_deref_var(b, v[0]), 1377 nir_build_deref_var(b, v[1]), 1378 ACCESS_VOLATILE, (gl_access_qualifier)0); 1379 nir_copy_var(b, v[0], v[1]); 1380 1381 /* Our approach here is a bit scorched-earth. We expect the volatile store 1382 * in the middle to cause both that store and the one before it to be kept. 1383 * Technically, volatile only prevents combining the volatile store with 1384 * another store and one could argue that the store before the volatile and 1385 * the one after it could be combined. However, it seems safer to just 1386 * treat a volatile store like an atomic and prevent any combining across 1387 * it. 1388 */ 1389 bool progress = nir_opt_dead_write_vars(b->shader); 1390 ASSERT_FALSE(progress); 1391} 1392 1393TEST_F(nir_dead_write_vars_test, no_dead_writes_in_if_statement) 1394{ 1395 nir_variable **v = create_many_int(nir_var_mem_ssbo, "v", 6); 1396 1397 nir_store_var(b, v[2], nir_load_var(b, v[0]), 1); 1398 nir_store_var(b, v[3], nir_load_var(b, v[1]), 1); 1399 1400 /* Each arm of the if statement will overwrite one store. */ 1401 nir_if *if_stmt = nir_push_if(b, nir_imm_int(b, 0)); 1402 nir_store_var(b, v[2], nir_load_var(b, v[4]), 1); 1403 1404 nir_push_else(b, if_stmt); 1405 nir_store_var(b, v[3], nir_load_var(b, v[5]), 1); 1406 1407 nir_pop_if(b, if_stmt); 1408 1409 bool progress = nir_opt_dead_write_vars(b->shader); 1410 ASSERT_FALSE(progress); 1411} 1412 1413TEST_F(nir_dead_write_vars_test, no_dead_writes_in_loop_statement) 1414{ 1415 nir_variable **v = create_many_int(nir_var_mem_ssbo, "v", 3); 1416 1417 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1); 1418 1419 /* Loop will write other value. Since it might not be executed, it doesn't 1420 * kill the first write. 1421 */ 1422 nir_loop *loop = nir_push_loop(b); 1423 1424 nir_if *if_stmt = nir_push_if(b, nir_imm_int(b, 0)); 1425 nir_jump(b, nir_jump_break); 1426 nir_pop_if(b, if_stmt); 1427 1428 nir_store_var(b, v[0], nir_load_var(b, v[2]), 1); 1429 nir_pop_loop(b, loop); 1430 1431 bool progress = nir_opt_dead_write_vars(b->shader); 1432 ASSERT_FALSE(progress); 1433} 1434 1435TEST_F(nir_dead_write_vars_test, dead_write_in_block) 1436{ 1437 nir_variable **v = create_many_int(nir_var_mem_ssbo, "v", 3); 1438 1439 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1); 1440 nir_ssa_def *load_v2 = nir_load_var(b, v[2]); 1441 nir_store_var(b, v[0], load_v2, 1); 1442 1443 bool progress = nir_opt_dead_write_vars(b->shader); 1444 ASSERT_TRUE(progress); 1445 1446 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref)); 1447 1448 nir_intrinsic_instr *store = get_intrinsic(nir_intrinsic_store_deref, 0); 1449 ASSERT_TRUE(store->src[1].is_ssa); 1450 EXPECT_EQ(store->src[1].ssa, load_v2); 1451} 1452 1453TEST_F(nir_dead_write_vars_test, dead_write_components_in_block) 1454{ 1455 nir_variable **v = create_many_ivec2(nir_var_mem_ssbo, "v", 3); 1456 1457 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1 << 0); 1458 nir_ssa_def *load_v2 = nir_load_var(b, v[2]); 1459 nir_store_var(b, v[0], load_v2, 1 << 0); 1460 1461 bool progress = nir_opt_dead_write_vars(b->shader); 1462 ASSERT_TRUE(progress); 1463 1464 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref)); 1465 1466 nir_intrinsic_instr *store = get_intrinsic(nir_intrinsic_store_deref, 0); 1467 ASSERT_TRUE(store->src[1].is_ssa); 1468 EXPECT_EQ(store->src[1].ssa, load_v2); 1469} 1470 1471 1472/* TODO: The DISABLED tests below depend on the dead write removal be able to 1473 * identify dead writes between multiple blocks. This is still not 1474 * implemented. 1475 */ 1476 1477TEST_F(nir_dead_write_vars_test, DISABLED_dead_write_in_two_blocks) 1478{ 1479 nir_variable **v = create_many_int(nir_var_mem_ssbo, "v", 3); 1480 1481 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1); 1482 nir_ssa_def *load_v2 = nir_load_var(b, v[2]); 1483 1484 /* Causes the stores to be in different blocks. */ 1485 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0))); 1486 1487 nir_store_var(b, v[0], load_v2, 1); 1488 1489 bool progress = nir_opt_dead_write_vars(b->shader); 1490 ASSERT_TRUE(progress); 1491 1492 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref)); 1493 1494 nir_intrinsic_instr *store = get_intrinsic(nir_intrinsic_store_deref, 0); 1495 ASSERT_TRUE(store->src[1].is_ssa); 1496 EXPECT_EQ(store->src[1].ssa, load_v2); 1497} 1498 1499TEST_F(nir_dead_write_vars_test, DISABLED_dead_write_components_in_two_blocks) 1500{ 1501 nir_variable **v = create_many_ivec2(nir_var_mem_ssbo, "v", 3); 1502 1503 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1 << 0); 1504 1505 /* Causes the stores to be in different blocks. */ 1506 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0))); 1507 1508 nir_ssa_def *load_v2 = nir_load_var(b, v[2]); 1509 nir_store_var(b, v[0], load_v2, 1 << 0); 1510 1511 bool progress = nir_opt_dead_write_vars(b->shader); 1512 ASSERT_TRUE(progress); 1513 1514 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref)); 1515 1516 nir_intrinsic_instr *store = get_intrinsic(nir_intrinsic_store_deref, 0); 1517 ASSERT_TRUE(store->src[1].is_ssa); 1518 EXPECT_EQ(store->src[1].ssa, load_v2); 1519} 1520 1521TEST_F(nir_dead_write_vars_test, DISABLED_dead_writes_in_if_statement) 1522{ 1523 nir_variable **v = create_many_int(nir_var_mem_ssbo, "v", 4); 1524 1525 /* Both branches will overwrite, making the previous store dead. */ 1526 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1); 1527 1528 nir_if *if_stmt = nir_push_if(b, nir_imm_int(b, 0)); 1529 nir_ssa_def *load_v2 = nir_load_var(b, v[2]); 1530 nir_store_var(b, v[0], load_v2, 1); 1531 1532 nir_push_else(b, if_stmt); 1533 nir_ssa_def *load_v3 = nir_load_var(b, v[3]); 1534 nir_store_var(b, v[0], load_v3, 1); 1535 1536 nir_pop_if(b, if_stmt); 1537 1538 bool progress = nir_opt_dead_write_vars(b->shader); 1539 ASSERT_TRUE(progress); 1540 EXPECT_EQ(2, count_intrinsics(nir_intrinsic_store_deref)); 1541 1542 nir_intrinsic_instr *first_store = get_intrinsic(nir_intrinsic_store_deref, 0); 1543 ASSERT_TRUE(first_store->src[1].is_ssa); 1544 EXPECT_EQ(first_store->src[1].ssa, load_v2); 1545 1546 nir_intrinsic_instr *second_store = get_intrinsic(nir_intrinsic_store_deref, 1); 1547 ASSERT_TRUE(second_store->src[1].is_ssa); 1548 EXPECT_EQ(second_store->src[1].ssa, load_v3); 1549} 1550 1551TEST_F(nir_dead_write_vars_test, DISABLED_memory_barrier_in_two_blocks) 1552{ 1553 nir_variable **v = create_many_int(nir_var_mem_ssbo, "v", 2); 1554 1555 nir_store_var(b, v[0], nir_imm_int(b, 1), 1); 1556 nir_store_var(b, v[1], nir_imm_int(b, 2), 1); 1557 1558 /* Split into many blocks. */ 1559 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0))); 1560 1561 /* Because it is before the barrier, this will kill the previous store to that target. */ 1562 nir_store_var(b, v[0], nir_imm_int(b, 3), 1); 1563 1564 nir_scoped_memory_barrier(b, NIR_SCOPE_DEVICE, NIR_MEMORY_ACQ_REL, 1565 nir_var_mem_ssbo); 1566 1567 nir_store_var(b, v[1], nir_imm_int(b, 4), 1); 1568 1569 bool progress = nir_opt_dead_write_vars(b->shader); 1570 ASSERT_TRUE(progress); 1571 1572 EXPECT_EQ(3, count_intrinsics(nir_intrinsic_store_deref)); 1573} 1574 1575TEST_F(nir_dead_write_vars_test, DISABLED_unrelated_barrier_in_two_blocks) 1576{ 1577 nir_variable **v = create_many_int(nir_var_mem_ssbo, "v", 3); 1578 nir_variable *out = create_int(nir_var_shader_out, "out"); 1579 1580 nir_store_var(b, out, nir_load_var(b, v[1]), 1); 1581 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1); 1582 1583 /* Split into many blocks. */ 1584 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0))); 1585 1586 /* Emit vertex will ensure writes to output variables are considered used, 1587 * but should not affect other types of variables. */ 1588 1589 nir_emit_vertex(b); 1590 1591 nir_store_var(b, out, nir_load_var(b, v[2]), 1); 1592 nir_store_var(b, v[0], nir_load_var(b, v[2]), 1); 1593 1594 bool progress = nir_opt_dead_write_vars(b->shader); 1595 ASSERT_TRUE(progress); 1596 1597 /* Verify the first write to v[0] was removed. */ 1598 EXPECT_EQ(3, count_intrinsics(nir_intrinsic_store_deref)); 1599 1600 nir_intrinsic_instr *first_store = get_intrinsic(nir_intrinsic_store_deref, 0); 1601 EXPECT_EQ(nir_intrinsic_get_var(first_store, 0), out); 1602 1603 nir_intrinsic_instr *second_store = get_intrinsic(nir_intrinsic_store_deref, 1); 1604 EXPECT_EQ(nir_intrinsic_get_var(second_store, 0), out); 1605 1606 nir_intrinsic_instr *third_store = get_intrinsic(nir_intrinsic_store_deref, 2); 1607 EXPECT_EQ(nir_intrinsic_get_var(third_store, 0), v[0]); 1608} 1609 1610TEST_F(nir_combine_stores_test, non_overlapping_stores) 1611{ 1612 nir_variable **v = create_many_ivec4(nir_var_mem_ssbo, "v", 4); 1613 nir_variable *out = create_ivec4(nir_var_shader_out, "out"); 1614 1615 for (int i = 0; i < 4; i++) 1616 nir_store_var(b, out, nir_load_var(b, v[i]), 1 << i); 1617 1618 nir_validate_shader(b->shader, NULL); 1619 1620 bool progress = nir_opt_combine_stores(b->shader, nir_var_shader_out); 1621 ASSERT_TRUE(progress); 1622 1623 nir_validate_shader(b->shader, NULL); 1624 1625 /* Clean up to verify from where the values in combined store are coming. */ 1626 nir_copy_prop(b->shader); 1627 nir_opt_dce(b->shader); 1628 1629 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 1); 1630 nir_intrinsic_instr *combined = get_intrinsic(nir_intrinsic_store_deref, 0); 1631 ASSERT_EQ(nir_intrinsic_write_mask(combined), 0xf); 1632 ASSERT_EQ(nir_intrinsic_get_var(combined, 0), out); 1633 1634 nir_alu_instr *vec = nir_src_as_alu_instr(combined->src[1]); 1635 ASSERT_TRUE(vec); 1636 for (int i = 0; i < 4; i++) { 1637 nir_intrinsic_instr *load = nir_src_as_intrinsic(vec->src[i].src); 1638 ASSERT_EQ(load->intrinsic, nir_intrinsic_load_deref); 1639 ASSERT_EQ(nir_intrinsic_get_var(load, 0), v[i]) 1640 << "Source value for component " << i << " of store is wrong"; 1641 ASSERT_EQ(vec->src[i].swizzle[0], i) 1642 << "Source component for component " << i << " of store is wrong"; 1643 } 1644} 1645 1646TEST_F(nir_combine_stores_test, overlapping_stores) 1647{ 1648 nir_variable **v = create_many_ivec4(nir_var_mem_ssbo, "v", 3); 1649 nir_variable *out = create_ivec4(nir_var_shader_out, "out"); 1650 1651 /* Make stores with xy, yz and zw masks. */ 1652 for (int i = 0; i < 3; i++) { 1653 nir_component_mask_t mask = (1 << i) | (1 << (i + 1)); 1654 nir_store_var(b, out, nir_load_var(b, v[i]), mask); 1655 } 1656 1657 nir_validate_shader(b->shader, NULL); 1658 1659 bool progress = nir_opt_combine_stores(b->shader, nir_var_shader_out); 1660 ASSERT_TRUE(progress); 1661 1662 nir_validate_shader(b->shader, NULL); 1663 1664 /* Clean up to verify from where the values in combined store are coming. */ 1665 nir_copy_prop(b->shader); 1666 nir_opt_dce(b->shader); 1667 1668 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 1); 1669 nir_intrinsic_instr *combined = get_intrinsic(nir_intrinsic_store_deref, 0); 1670 ASSERT_EQ(nir_intrinsic_write_mask(combined), 0xf); 1671 ASSERT_EQ(nir_intrinsic_get_var(combined, 0), out); 1672 1673 nir_alu_instr *vec = nir_src_as_alu_instr(combined->src[1]); 1674 ASSERT_TRUE(vec); 1675 1676 /* Component x comes from v[0]. */ 1677 nir_intrinsic_instr *load_for_x = nir_src_as_intrinsic(vec->src[0].src); 1678 ASSERT_EQ(nir_intrinsic_get_var(load_for_x, 0), v[0]); 1679 ASSERT_EQ(vec->src[0].swizzle[0], 0); 1680 1681 /* Component y comes from v[1]. */ 1682 nir_intrinsic_instr *load_for_y = nir_src_as_intrinsic(vec->src[1].src); 1683 ASSERT_EQ(nir_intrinsic_get_var(load_for_y, 0), v[1]); 1684 ASSERT_EQ(vec->src[1].swizzle[0], 1); 1685 1686 /* Components z and w come from v[2]. */ 1687 nir_intrinsic_instr *load_for_z = nir_src_as_intrinsic(vec->src[2].src); 1688 nir_intrinsic_instr *load_for_w = nir_src_as_intrinsic(vec->src[3].src); 1689 ASSERT_EQ(load_for_z, load_for_w); 1690 ASSERT_EQ(nir_intrinsic_get_var(load_for_z, 0), v[2]); 1691 ASSERT_EQ(vec->src[2].swizzle[0], 2); 1692 ASSERT_EQ(vec->src[3].swizzle[0], 3); 1693} 1694 1695TEST_F(nir_combine_stores_test, direct_array_derefs) 1696{ 1697 nir_variable **v = create_many_ivec4(nir_var_mem_ssbo, "vec", 2); 1698 nir_variable **s = create_many_int(nir_var_mem_ssbo, "scalar", 2); 1699 nir_variable *out = create_ivec4(nir_var_mem_ssbo, "out"); 1700 1701 nir_deref_instr *out_deref = nir_build_deref_var(b, out); 1702 1703 /* Store to vector with mask x. */ 1704 nir_store_deref(b, out_deref, nir_load_var(b, v[0]), 1705 1 << 0); 1706 1707 /* Store to vector with mask yz. */ 1708 nir_store_deref(b, out_deref, nir_load_var(b, v[1]), 1709 (1 << 2) | (1 << 1)); 1710 1711 /* Store to vector[2], overlapping with previous store. */ 1712 nir_store_deref(b, 1713 nir_build_deref_array_imm(b, out_deref, 2), 1714 nir_load_var(b, s[0]), 1715 1 << 0); 1716 1717 /* Store to vector[3], no overlap. */ 1718 nir_store_deref(b, 1719 nir_build_deref_array_imm(b, out_deref, 3), 1720 nir_load_var(b, s[1]), 1721 1 << 0); 1722 1723 nir_validate_shader(b->shader, NULL); 1724 1725 bool progress = nir_opt_combine_stores(b->shader, nir_var_mem_ssbo); 1726 ASSERT_TRUE(progress); 1727 1728 nir_validate_shader(b->shader, NULL); 1729 1730 /* Clean up to verify from where the values in combined store are coming. */ 1731 nir_copy_prop(b->shader); 1732 nir_opt_dce(b->shader); 1733 1734 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 1); 1735 nir_intrinsic_instr *combined = get_intrinsic(nir_intrinsic_store_deref, 0); 1736 ASSERT_EQ(nir_intrinsic_write_mask(combined), 0xf); 1737 ASSERT_EQ(nir_intrinsic_get_var(combined, 0), out); 1738 1739 nir_alu_instr *vec = nir_src_as_alu_instr(combined->src[1]); 1740 ASSERT_TRUE(vec); 1741 1742 /* Component x comes from v[0]. */ 1743 nir_intrinsic_instr *load_for_x = nir_src_as_intrinsic(vec->src[0].src); 1744 ASSERT_EQ(nir_intrinsic_get_var(load_for_x, 0), v[0]); 1745 ASSERT_EQ(vec->src[0].swizzle[0], 0); 1746 1747 /* Component y comes from v[1]. */ 1748 nir_intrinsic_instr *load_for_y = nir_src_as_intrinsic(vec->src[1].src); 1749 ASSERT_EQ(nir_intrinsic_get_var(load_for_y, 0), v[1]); 1750 ASSERT_EQ(vec->src[1].swizzle[0], 1); 1751 1752 /* Components z comes from s[0]. */ 1753 nir_intrinsic_instr *load_for_z = nir_src_as_intrinsic(vec->src[2].src); 1754 ASSERT_EQ(nir_intrinsic_get_var(load_for_z, 0), s[0]); 1755 ASSERT_EQ(vec->src[2].swizzle[0], 0); 1756 1757 /* Component w comes from s[1]. */ 1758 nir_intrinsic_instr *load_for_w = nir_src_as_intrinsic(vec->src[3].src); 1759 ASSERT_EQ(nir_intrinsic_get_var(load_for_w, 0), s[1]); 1760 ASSERT_EQ(vec->src[3].swizzle[0], 0); 1761} 1762 1763static int64_t 1764vec_src_comp_as_int(nir_src src, unsigned comp) 1765{ 1766 if (nir_src_is_const(src)) 1767 return nir_src_comp_as_int(src, comp); 1768 1769 assert(src.is_ssa); 1770 nir_ssa_scalar s = { src.ssa, comp }; 1771 assert(nir_op_is_vec(nir_ssa_scalar_alu_op(s))); 1772 return nir_ssa_scalar_as_int(nir_ssa_scalar_chase_alu_src(s, comp)); 1773} 1774 1775TEST_F(nir_combine_stores_test, store_volatile) 1776{ 1777 nir_variable *out = create_ivec4(nir_var_shader_out, "out"); 1778 1779 nir_store_var(b, out, nir_imm_ivec4(b, 0, 0, 0, 0), 1 << 0); 1780 nir_store_var(b, out, nir_imm_ivec4(b, 1, 1, 1, 1), 1 << 1); 1781 nir_store_var_volatile(b, out, nir_imm_ivec4(b, -1, -2, -3, -4), 0xf); 1782 nir_store_var(b, out, nir_imm_ivec4(b, 2, 2, 2, 2), 1 << 2); 1783 nir_store_var(b, out, nir_imm_ivec4(b, 3, 3, 3, 3), 1 << 3); 1784 1785 nir_validate_shader(b->shader, NULL); 1786 1787 bool progress = nir_opt_combine_stores(b->shader, nir_var_shader_out); 1788 ASSERT_TRUE(progress); 1789 1790 nir_validate_shader(b->shader, NULL); 1791 1792 /* Clean up the stored values */ 1793 nir_opt_constant_folding(b->shader); 1794 nir_opt_dce(b->shader); 1795 1796 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 3); 1797 1798 nir_intrinsic_instr *first = get_intrinsic(nir_intrinsic_store_deref, 0); 1799 ASSERT_EQ(nir_intrinsic_write_mask(first), 0x3); 1800 ASSERT_EQ(vec_src_comp_as_int(first->src[1], 0), 0); 1801 ASSERT_EQ(vec_src_comp_as_int(first->src[1], 1), 1); 1802 1803 nir_intrinsic_instr *second = get_intrinsic(nir_intrinsic_store_deref, 1); 1804 ASSERT_EQ(nir_intrinsic_write_mask(second), 0xf); 1805 ASSERT_EQ(vec_src_comp_as_int(second->src[1], 0), -1); 1806 ASSERT_EQ(vec_src_comp_as_int(second->src[1], 1), -2); 1807 ASSERT_EQ(vec_src_comp_as_int(second->src[1], 2), -3); 1808 ASSERT_EQ(vec_src_comp_as_int(second->src[1], 3), -4); 1809 1810 nir_intrinsic_instr *third = get_intrinsic(nir_intrinsic_store_deref, 2); 1811 ASSERT_EQ(nir_intrinsic_write_mask(third), 0xc); 1812 ASSERT_EQ(vec_src_comp_as_int(third->src[1], 2), 2); 1813 ASSERT_EQ(vec_src_comp_as_int(third->src[1], 3), 3); 1814} 1815 1816TEST_F(nir_split_vars_test, simple_split) 1817{ 1818 nir_variable **in = create_many_int(nir_var_shader_in, "in", 4); 1819 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 1820 "temp"); 1821 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 1822 for (int i = 0; i < 4; i++) 1823 nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1); 1824 1825 nir_validate_shader(b->shader, NULL); 1826 ASSERT_EQ(count_derefs(nir_deref_type_array), 4); 1827 ASSERT_EQ(count_function_temp_vars(), 1); 1828 1829 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 1830 EXPECT_TRUE(progress); 1831 1832 nir_validate_shader(b->shader, NULL); 1833 ASSERT_EQ(count_derefs(nir_deref_type_array), 0); 1834 ASSERT_EQ(count_function_temp_vars(), 4); 1835} 1836 1837TEST_F(nir_split_vars_test, simple_no_split_array_struct) 1838{ 1839 nir_variable **in = create_many_int(nir_var_shader_in, "in", 4); 1840 struct glsl_struct_field field; 1841 1842 field.type = glsl_float_type(); 1843 field.name = ralloc_asprintf(b->shader, "field1"); 1844 field.location = -1; 1845 field.offset = 0; 1846 1847 const struct glsl_type *st_type = glsl_struct_type(&field, 1, "struct", false); 1848 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(st_type, 4, 0), 1849 "temp"); 1850 1851 nir_variable *temp2 = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), "temp2"); 1852 1853 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 1854 nir_deref_instr *temp2_deref = nir_build_deref_var(b, temp2); 1855 for (int i = 0; i < 4; i++) 1856 nir_store_deref(b, nir_build_deref_array_imm(b, temp2_deref, i), nir_load_var(b, in[i]), 1); 1857 1858 for (int i = 0; i < 4; i++) 1859 nir_store_deref(b, nir_build_deref_struct(b, nir_build_deref_array_imm(b, temp_deref, i), 0), nir_load_var(b, in[i]), 1); 1860 1861 nir_validate_shader(b->shader, NULL); 1862 ASSERT_EQ(count_derefs(nir_deref_type_array), 8); 1863 ASSERT_EQ(count_derefs(nir_deref_type_struct), 4); 1864 ASSERT_EQ(count_function_temp_vars(), 2); 1865 1866 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 1867 EXPECT_TRUE(progress); 1868 1869 nir_validate_shader(b->shader, NULL); 1870 1871 ASSERT_EQ(count_derefs(nir_deref_type_array), 4); 1872 ASSERT_EQ(count_derefs(nir_deref_type_struct), 4); 1873 for (int i = 0; i < 4; i++) { 1874 nir_deref_instr *deref = get_deref(nir_deref_type_array, i); 1875 ASSERT_TRUE(deref); 1876 ASSERT_TRUE(glsl_type_is_struct(deref->type)); 1877 } 1878 1879 ASSERT_EQ(count_function_temp_vars(), 5); 1880} 1881 1882TEST_F(nir_split_vars_test, simple_split_shader_temp) 1883{ 1884 nir_variable **in = create_many_int(nir_var_shader_in, "in", 4); 1885 nir_variable *temp = create_var(nir_var_shader_temp, glsl_array_type(glsl_int_type(), 4, 0), 1886 "temp"); 1887 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 1888 1889 for (int i = 0; i < 4; i++) 1890 nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1); 1891 1892 nir_validate_shader(b->shader, NULL); 1893 ASSERT_EQ(count_derefs(nir_deref_type_array), 4); 1894 ASSERT_EQ(count_shader_temp_vars(), 1); 1895 1896 bool progress = nir_split_array_vars(b->shader, nir_var_shader_temp); 1897 EXPECT_TRUE(progress); 1898 1899 nir_validate_shader(b->shader, NULL); 1900 ASSERT_EQ(count_derefs(nir_deref_type_array), 0); 1901 ASSERT_EQ(count_shader_temp_vars(), 4); 1902} 1903 1904TEST_F(nir_split_vars_test, simple_oob) 1905{ 1906 nir_variable **in = create_many_int(nir_var_shader_in, "in", 6); 1907 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 1908 "temp"); 1909 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 1910 1911 for (int i = 0; i < 6; i++) 1912 nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1); 1913 1914 nir_validate_shader(b->shader, NULL); 1915 ASSERT_EQ(count_derefs(nir_deref_type_array), 6); 1916 ASSERT_EQ(count_function_temp_vars(), 1); 1917 1918 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 1919 EXPECT_TRUE(progress); 1920 1921 nir_validate_shader(b->shader, NULL); 1922 ASSERT_EQ(count_derefs(nir_deref_type_array), 0); 1923 ASSERT_EQ(count_function_temp_vars(), 4); 1924} 1925 1926TEST_F(nir_split_vars_test, simple_unused) 1927{ 1928 nir_variable **in = create_many_int(nir_var_shader_in, "in", 2); 1929 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 1930 "temp"); 1931 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 1932 1933 for (int i = 0; i < 2; i++) 1934 nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1); 1935 1936 nir_validate_shader(b->shader, NULL); 1937 ASSERT_EQ(count_derefs(nir_deref_type_array), 2); 1938 ASSERT_EQ(count_function_temp_vars(), 1); 1939 1940 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 1941 EXPECT_TRUE(progress); 1942 1943 nir_validate_shader(b->shader, NULL); 1944 ASSERT_EQ(count_derefs(nir_deref_type_array), 0); 1945 /* this pass doesn't remove the unused ones */ 1946 ASSERT_EQ(count_function_temp_vars(), 4); 1947} 1948 1949TEST_F(nir_split_vars_test, two_level_split) 1950{ 1951 nir_variable **in = create_many_int(nir_var_shader_in, "in", 4); 1952 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_array_type(glsl_int_type(), 4, 0), 4, 0), 1953 "temp"); 1954 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 1955 for (int i = 0; i < 4; i++) { 1956 nir_deref_instr *level0 = nir_build_deref_array_imm(b, temp_deref, i); 1957 for (int j = 0; j < 4; j++) { 1958 nir_deref_instr *level1 = nir_build_deref_array_imm(b, level0, j); 1959 nir_store_deref(b, level1, nir_load_var(b, in[i]), 1); 1960 } 1961 } 1962 1963 nir_validate_shader(b->shader, NULL); 1964 ASSERT_EQ(count_derefs(nir_deref_type_array), 20); 1965 ASSERT_EQ(count_function_temp_vars(), 1); 1966 1967 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 1968 EXPECT_TRUE(progress); 1969 1970 nir_validate_shader(b->shader, NULL); 1971 ASSERT_EQ(count_derefs(nir_deref_type_array), 0); 1972 ASSERT_EQ(count_function_temp_vars(), 16); 1973} 1974 1975TEST_F(nir_split_vars_test, simple_dont_split) 1976{ 1977 nir_variable **in = create_many_int(nir_var_shader_in, "in", 4); 1978 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 1979 "temp"); 1980 nir_variable *ind = create_int(nir_var_shader_in, "ind"); 1981 1982 nir_deref_instr *ind_deref = nir_build_deref_var(b, ind); 1983 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 1984 1985 for (int i = 0; i < 4; i++) 1986 nir_store_deref(b, nir_build_deref_array(b, temp_deref, &ind_deref->dest.ssa), nir_load_var(b, in[i]), 1); 1987 1988 nir_validate_shader(b->shader, NULL); 1989 ASSERT_EQ(count_derefs(nir_deref_type_array), 4); 1990 ASSERT_EQ(count_function_temp_vars(), 1); 1991 1992 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 1993 EXPECT_FALSE(progress); 1994 1995 nir_validate_shader(b->shader, NULL); 1996 ASSERT_EQ(count_derefs(nir_deref_type_array), 4); 1997 ASSERT_EQ(count_function_temp_vars(), 1); 1998} 1999 2000TEST_F(nir_split_vars_test, twolevel_dont_split_lvl_0) 2001{ 2002 nir_variable **in = create_many_int(nir_var_shader_in, "in", 4); 2003 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_array_type(glsl_int_type(), 6, 0), 4, 0), 2004 "temp"); 2005 nir_variable *ind = create_int(nir_var_shader_in, "ind"); 2006 2007 nir_deref_instr *ind_deref = nir_build_deref_var(b, ind); 2008 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 2009 2010 for (int i = 0; i < 4; i++) { 2011 nir_deref_instr *level0 = nir_build_deref_array(b, temp_deref, &ind_deref->dest.ssa); 2012 for (int j = 0; j < 6; j++) { 2013 nir_deref_instr *level1 = nir_build_deref_array_imm(b, level0, j); 2014 nir_store_deref(b, level1, nir_load_var(b, in[i]), 1); 2015 } 2016 } 2017 2018 nir_validate_shader(b->shader, NULL); 2019 ASSERT_EQ(count_derefs(nir_deref_type_array), 28); 2020 ASSERT_EQ(count_function_temp_vars(), 1); 2021 2022 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 2023 EXPECT_TRUE(progress); 2024 2025 nir_validate_shader(b->shader, NULL); 2026 ASSERT_EQ(count_derefs(nir_deref_type_array), 24); 2027 ASSERT_EQ(count_function_temp_vars(), 6); 2028} 2029 2030TEST_F(nir_split_vars_test, twolevel_dont_split_lvl_1) 2031{ 2032 nir_variable **in = create_many_int(nir_var_shader_in, "in", 6); 2033 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_array_type(glsl_int_type(), 6, 0), 4, 0), 2034 "temp"); 2035 nir_variable *ind = create_int(nir_var_shader_in, "ind"); 2036 2037 nir_deref_instr *ind_deref = nir_build_deref_var(b, ind); 2038 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 2039 2040 for (int i = 0; i < 4; i++) { 2041 nir_deref_instr *level0 = nir_build_deref_array_imm(b, temp_deref, i); 2042 for (int j = 0; j < 6; j++) { 2043 /* just add the inner index to get some different derefs */ 2044 nir_deref_instr *level1 = nir_build_deref_array(b, level0, nir_iadd(b, &ind_deref->dest.ssa, nir_imm_int(b, j))); 2045 nir_store_deref(b, level1, nir_load_var(b, in[i]), 1); 2046 } 2047 } 2048 2049 nir_validate_shader(b->shader, NULL); 2050 ASSERT_EQ(count_derefs(nir_deref_type_array), 28); 2051 ASSERT_EQ(count_function_temp_vars(), 1); 2052 2053 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 2054 EXPECT_TRUE(progress); 2055 2056 nir_validate_shader(b->shader, NULL); 2057 ASSERT_EQ(count_derefs(nir_deref_type_array), 24); 2058 ASSERT_EQ(count_function_temp_vars(), 4); 2059} 2060 2061TEST_F(nir_split_vars_test, split_multiple_store) 2062{ 2063 nir_variable **in = create_many_int(nir_var_shader_in, "in", 4); 2064 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 2065 "temp"); 2066 nir_variable *temp2 = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 2067 "temp2"); 2068 2069 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 2070 nir_deref_instr *temp2_deref = nir_build_deref_var(b, temp2); 2071 2072 for (int i = 0; i < 4; i++) 2073 nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1); 2074 2075 for (int i = 0; i < 4; i++) 2076 nir_store_deref(b, nir_build_deref_array_imm(b, temp2_deref, i), nir_load_var(b, in[i]), 1); 2077 2078 nir_validate_shader(b->shader, NULL); 2079 ASSERT_EQ(count_derefs(nir_deref_type_array), 8); 2080 ASSERT_EQ(count_function_temp_vars(), 2); 2081 2082 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 2083 EXPECT_TRUE(progress); 2084 2085 nir_validate_shader(b->shader, NULL); 2086 ASSERT_EQ(count_derefs(nir_deref_type_array), 0); 2087 ASSERT_EQ(count_function_temp_vars(), 8); 2088} 2089 2090TEST_F(nir_split_vars_test, split_load_store) 2091{ 2092 nir_variable **in = create_many_int(nir_var_shader_in, "in", 4); 2093 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 2094 "temp"); 2095 nir_variable *temp2 = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 2096 "temp2"); 2097 2098 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 2099 nir_deref_instr *temp2_deref = nir_build_deref_var(b, temp2); 2100 2101 for (int i = 0; i < 4; i++) 2102 nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1); 2103 2104 for (int i = 0; i < 4; i++) { 2105 nir_deref_instr *store_deref = nir_build_deref_array_imm(b, temp2_deref, i); 2106 nir_deref_instr *load_deref = nir_build_deref_array_imm(b, temp_deref, i); 2107 nir_store_deref(b, store_deref, nir_load_deref(b, load_deref), 1); 2108 } 2109 2110 nir_validate_shader(b->shader, NULL); 2111 ASSERT_EQ(count_derefs(nir_deref_type_array), 12); 2112 ASSERT_EQ(count_function_temp_vars(), 2); 2113 2114 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 2115 EXPECT_TRUE(progress); 2116 2117 nir_validate_shader(b->shader, NULL); 2118 ASSERT_EQ(count_derefs(nir_deref_type_array), 0); 2119 ASSERT_EQ(count_function_temp_vars(), 8); 2120} 2121 2122TEST_F(nir_split_vars_test, split_copy) 2123{ 2124 nir_variable **in = create_many_int(nir_var_shader_in, "in", 4); 2125 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 2126 "temp"); 2127 nir_variable *temp2 = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 2128 "temp2"); 2129 2130 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 2131 nir_deref_instr *temp2_deref = nir_build_deref_var(b, temp2); 2132 2133 for (int i = 0; i < 4; i++) 2134 nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1); 2135 2136 for (int i = 0; i < 4; i++) { 2137 nir_deref_instr *store_deref = nir_build_deref_array_imm(b, temp2_deref, i); 2138 nir_deref_instr *load_deref = nir_build_deref_array_imm(b, temp_deref, i); 2139 nir_copy_deref(b, store_deref, load_deref); 2140 } 2141 2142 nir_validate_shader(b->shader, NULL); 2143 ASSERT_EQ(count_derefs(nir_deref_type_array), 12); 2144 ASSERT_EQ(count_function_temp_vars(), 2); 2145 2146 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 2147 EXPECT_TRUE(progress); 2148 2149 nir_validate_shader(b->shader, NULL); 2150 ASSERT_EQ(count_derefs(nir_deref_type_array), 0); 2151 ASSERT_EQ(count_function_temp_vars(), 8); 2152} 2153 2154TEST_F(nir_split_vars_test, split_wildcard_copy) 2155{ 2156 nir_variable **in = create_many_int(nir_var_shader_in, "in", 4); 2157 nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 2158 "temp"); 2159 nir_variable *temp2 = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), 2160 "temp2"); 2161 2162 nir_deref_instr *temp_deref = nir_build_deref_var(b, temp); 2163 nir_deref_instr *temp2_deref = nir_build_deref_var(b, temp2); 2164 2165 for (int i = 0; i < 4; i++) 2166 nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1); 2167 2168 nir_deref_instr *src_wildcard = nir_build_deref_array_wildcard(b, temp_deref); 2169 nir_deref_instr *dst_wildcard = nir_build_deref_array_wildcard(b, temp2_deref); 2170 2171 nir_copy_deref(b, dst_wildcard, src_wildcard); 2172 2173 nir_validate_shader(b->shader, NULL); 2174 ASSERT_EQ(count_derefs(nir_deref_type_array), 4); 2175 ASSERT_EQ(count_derefs(nir_deref_type_array_wildcard), 2); 2176 ASSERT_EQ(count_function_temp_vars(), 2); 2177 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref), 1); 2178 2179 bool progress = nir_split_array_vars(b->shader, nir_var_function_temp); 2180 EXPECT_TRUE(progress); 2181 2182 nir_validate_shader(b->shader, NULL); 2183 ASSERT_EQ(count_derefs(nir_deref_type_array), 0); 2184 ASSERT_EQ(count_derefs(nir_deref_type_array_wildcard), 0); 2185 ASSERT_EQ(count_function_temp_vars(), 8); 2186 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref), 4); 2187} 2188 2189TEST_F(nir_remove_dead_variables_test, pointer_initializer_used) 2190{ 2191 nir_variable *x = create_int(nir_var_shader_temp, "x"); 2192 nir_variable *y = create_int(nir_var_shader_temp, "y"); 2193 y->pointer_initializer = x; 2194 nir_variable *out = create_int(nir_var_shader_out, "out"); 2195 2196 nir_validate_shader(b->shader, NULL); 2197 2198 nir_copy_var(b, out, y); 2199 2200 bool progress = nir_remove_dead_variables(b->shader, nir_var_all, NULL); 2201 EXPECT_FALSE(progress); 2202 2203 nir_validate_shader(b->shader, NULL); 2204 2205 unsigned count = 0; 2206 nir_foreach_variable_in_shader(var, b->shader) 2207 count++; 2208 2209 ASSERT_EQ(count, 3); 2210} 2211 2212TEST_F(nir_remove_dead_variables_test, pointer_initializer_dead) 2213{ 2214 nir_variable *x = create_int(nir_var_shader_temp, "x"); 2215 nir_variable *y = create_int(nir_var_shader_temp, "y"); 2216 nir_variable *z = create_int(nir_var_shader_temp, "z"); 2217 y->pointer_initializer = x; 2218 z->pointer_initializer = y; 2219 2220 nir_validate_shader(b->shader, NULL); 2221 2222 bool progress = nir_remove_dead_variables(b->shader, nir_var_all, NULL); 2223 EXPECT_TRUE(progress); 2224 2225 nir_validate_shader(b->shader, NULL); 2226 2227 unsigned count = 0; 2228 nir_foreach_variable_in_shader(var, b->shader) 2229 count++; 2230 2231 ASSERT_EQ(count, 0); 2232} 2233 2234 2235