2 * Copyright © 2018 Intel Corporation
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:
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
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.
24 #include <gtest/gtest.h>
27 #include "nir_builder.h"
31 class nir_vars_test
: public ::testing::Test
{
36 nir_variable
*create_var(nir_variable_mode mode
, const glsl_type
*type
,
38 if (mode
== nir_var_function_temp
)
39 return nir_local_variable_create(b
->impl
, type
, name
);
41 return nir_variable_create(b
->shader
, mode
, type
, name
);
44 nir_variable
*create_int(nir_variable_mode mode
, const char *name
) {
45 return create_var(mode
, glsl_int_type(), name
);
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
);
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
);
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
));
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
));
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
));
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
);
83 unsigned count_shader_temp_vars(void) {
84 return exec_list_length(&b
->shader
->globals
);
87 nir_intrinsic_instr
*get_intrinsic(nir_intrinsic_op intrinsic
,
90 nir_deref_instr
*get_deref(nir_deref_type deref_type
,
98 nir_vars_test::nir_vars_test()
100 glsl_type_singleton_init_or_ref();
102 mem_ctx
= ralloc_context(NULL
);
103 lin_ctx
= linear_alloc_parent(mem_ctx
, 0);
104 static const nir_shader_compiler_options options
= { };
105 b
= rzalloc(mem_ctx
, nir_builder
);
106 nir_builder_init_simple_shader(b
, mem_ctx
, MESA_SHADER_COMPUTE
, &options
);
109 nir_vars_test::~nir_vars_test()
112 printf("\nShader from the failed test:\n\n");
113 nir_print_shader(b
->shader
, stdout
);
116 ralloc_free(mem_ctx
);
118 glsl_type_singleton_decref();
122 nir_vars_test::count_intrinsics(nir_intrinsic_op intrinsic
)
125 nir_foreach_block(block
, b
->impl
) {
126 nir_foreach_instr(instr
, block
) {
127 if (instr
->type
!= nir_instr_type_intrinsic
)
129 nir_intrinsic_instr
*intrin
= nir_instr_as_intrinsic(instr
);
130 if (intrin
->intrinsic
== intrinsic
)
138 nir_vars_test::count_derefs(nir_deref_type deref_type
)
141 nir_foreach_block(block
, b
->impl
) {
142 nir_foreach_instr(instr
, block
) {
143 if (instr
->type
!= nir_instr_type_deref
)
145 nir_deref_instr
*intrin
= nir_instr_as_deref(instr
);
146 if (intrin
->deref_type
== deref_type
)
153 nir_intrinsic_instr
*
154 nir_vars_test::get_intrinsic(nir_intrinsic_op intrinsic
,
157 nir_foreach_block(block
, b
->impl
) {
158 nir_foreach_instr(instr
, block
) {
159 if (instr
->type
!= nir_instr_type_intrinsic
)
161 nir_intrinsic_instr
*intrin
= nir_instr_as_intrinsic(instr
);
162 if (intrin
->intrinsic
== intrinsic
) {
173 nir_vars_test::get_deref(nir_deref_type deref_type
,
176 nir_foreach_block(block
, b
->impl
) {
177 nir_foreach_instr(instr
, block
) {
178 if (instr
->type
!= nir_instr_type_deref
)
180 nir_deref_instr
*deref
= nir_instr_as_deref(instr
);
181 if (deref
->deref_type
== deref_type
) {
191 /* Allow grouping the tests while still sharing the helpers. */
192 class nir_redundant_load_vars_test
: public nir_vars_test
{};
193 class nir_copy_prop_vars_test
: public nir_vars_test
{};
194 class nir_dead_write_vars_test
: public nir_vars_test
{};
195 class nir_combine_stores_test
: public nir_vars_test
{};
196 class nir_split_vars_test
: public nir_vars_test
{};
200 TEST_F(nir_redundant_load_vars_test
, duplicated_load
)
202 /* Load a variable twice in the same block. One should be removed. */
204 nir_variable
*in
= create_int(nir_var_shader_in
, "in");
205 nir_variable
**out
= create_many_int(nir_var_shader_out
, "out", 2);
207 nir_store_var(b
, out
[0], nir_load_var(b
, in
), 1);
208 nir_store_var(b
, out
[1], nir_load_var(b
, in
), 1);
210 nir_validate_shader(b
->shader
, NULL
);
212 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
214 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
215 EXPECT_TRUE(progress
);
217 nir_validate_shader(b
->shader
, NULL
);
219 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
222 TEST_F(nir_redundant_load_vars_test
, duplicated_load_in_two_blocks
)
224 /* Load a variable twice in different blocks. One should be removed. */
226 nir_variable
*in
= create_int(nir_var_shader_in
, "in");
227 nir_variable
**out
= create_many_int(nir_var_shader_out
, "out", 2);
229 nir_store_var(b
, out
[0], nir_load_var(b
, in
), 1);
231 /* Forces the stores to be in different blocks. */
232 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
234 nir_store_var(b
, out
[1], nir_load_var(b
, in
), 1);
236 nir_validate_shader(b
->shader
, NULL
);
238 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
240 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
241 EXPECT_TRUE(progress
);
243 nir_validate_shader(b
->shader
, NULL
);
245 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
248 TEST_F(nir_redundant_load_vars_test
, invalidate_inside_if_block
)
250 /* Load variables, then write to some of then in different branches of the
251 * if statement. They should be invalidated accordingly.
254 nir_variable
**g
= create_many_int(nir_var_shader_temp
, "g", 3);
255 nir_variable
**out
= create_many_int(nir_var_shader_out
, "out", 3);
257 nir_load_var(b
, g
[0]);
258 nir_load_var(b
, g
[1]);
259 nir_load_var(b
, g
[2]);
261 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
262 nir_store_var(b
, g
[0], nir_imm_int(b
, 10), 1);
264 nir_push_else(b
, if_stmt
);
265 nir_store_var(b
, g
[1], nir_imm_int(b
, 20), 1);
267 nir_pop_if(b
, if_stmt
);
269 nir_store_var(b
, out
[0], nir_load_var(b
, g
[0]), 1);
270 nir_store_var(b
, out
[1], nir_load_var(b
, g
[1]), 1);
271 nir_store_var(b
, out
[2], nir_load_var(b
, g
[2]), 1);
273 nir_validate_shader(b
->shader
, NULL
);
275 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
276 EXPECT_TRUE(progress
);
278 /* There are 3 initial loads, plus 2 loads for the values invalidated
279 * inside the if statement.
281 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 5);
283 /* We only load g[2] once. */
284 unsigned g2_load_count
= 0;
285 for (int i
= 0; i
< 5; i
++) {
286 nir_intrinsic_instr
*load
= get_intrinsic(nir_intrinsic_load_deref
, i
);
287 if (nir_intrinsic_get_var(load
, 0) == g
[2])
290 EXPECT_EQ(g2_load_count
, 1);
293 TEST_F(nir_redundant_load_vars_test
, invalidate_live_load_in_the_end_of_loop
)
295 /* Invalidating a load in the end of loop body will apply to the whole loop
299 nir_variable
*v
= create_int(nir_var_mem_ssbo
, "v");
303 nir_loop
*loop
= nir_push_loop(b
);
305 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
306 nir_jump(b
, nir_jump_break
);
307 nir_pop_if(b
, if_stmt
);
310 nir_store_var(b
, v
, nir_imm_int(b
, 10), 1);
312 nir_pop_loop(b
, loop
);
314 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
315 ASSERT_FALSE(progress
);
318 TEST_F(nir_copy_prop_vars_test
, simple_copies
)
320 nir_variable
*in
= create_int(nir_var_shader_in
, "in");
321 nir_variable
*temp
= create_int(nir_var_function_temp
, "temp");
322 nir_variable
*out
= create_int(nir_var_shader_out
, "out");
324 nir_copy_var(b
, temp
, in
);
325 nir_copy_var(b
, out
, temp
);
327 nir_validate_shader(b
->shader
, NULL
);
329 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
330 EXPECT_TRUE(progress
);
332 nir_validate_shader(b
->shader
, NULL
);
334 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref
), 2);
336 nir_intrinsic_instr
*first_copy
= get_intrinsic(nir_intrinsic_copy_deref
, 0);
337 ASSERT_TRUE(first_copy
->src
[1].is_ssa
);
339 nir_intrinsic_instr
*second_copy
= get_intrinsic(nir_intrinsic_copy_deref
, 1);
340 ASSERT_TRUE(second_copy
->src
[1].is_ssa
);
342 EXPECT_EQ(first_copy
->src
[1].ssa
, second_copy
->src
[1].ssa
);
345 TEST_F(nir_copy_prop_vars_test
, simple_store_load
)
347 nir_variable
**v
= create_many_ivec2(nir_var_function_temp
, "v", 2);
348 unsigned mask
= 1 | 2;
350 nir_ssa_def
*stored_value
= nir_imm_ivec2(b
, 10, 20);
351 nir_store_var(b
, v
[0], stored_value
, mask
);
353 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
354 nir_store_var(b
, v
[1], read_value
, mask
);
356 nir_validate_shader(b
->shader
, NULL
);
358 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
359 EXPECT_TRUE(progress
);
361 nir_validate_shader(b
->shader
, NULL
);
363 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
365 for (int i
= 0; i
< 2; i
++) {
366 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, i
);
367 ASSERT_TRUE(store
->src
[1].is_ssa
);
368 EXPECT_EQ(store
->src
[1].ssa
, stored_value
);
372 TEST_F(nir_copy_prop_vars_test
, store_store_load
)
374 nir_variable
**v
= create_many_ivec2(nir_var_function_temp
, "v", 2);
375 unsigned mask
= 1 | 2;
377 nir_ssa_def
*first_value
= nir_imm_ivec2(b
, 10, 20);
378 nir_store_var(b
, v
[0], first_value
, mask
);
380 nir_ssa_def
*second_value
= nir_imm_ivec2(b
, 30, 40);
381 nir_store_var(b
, v
[0], second_value
, mask
);
383 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
384 nir_store_var(b
, v
[1], read_value
, mask
);
386 nir_validate_shader(b
->shader
, NULL
);
388 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
389 EXPECT_TRUE(progress
);
391 nir_validate_shader(b
->shader
, NULL
);
393 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
395 /* Store to v[1] should use second_value directly. */
396 nir_intrinsic_instr
*store_to_v1
= get_intrinsic(nir_intrinsic_store_deref
, 2);
397 ASSERT_EQ(nir_intrinsic_get_var(store_to_v1
, 0), v
[1]);
398 ASSERT_TRUE(store_to_v1
->src
[1].is_ssa
);
399 EXPECT_EQ(store_to_v1
->src
[1].ssa
, second_value
);
402 TEST_F(nir_copy_prop_vars_test
, store_store_load_different_components
)
404 nir_variable
**v
= create_many_ivec2(nir_var_function_temp
, "v", 2);
406 nir_ssa_def
*first_value
= nir_imm_ivec2(b
, 10, 20);
407 nir_store_var(b
, v
[0], first_value
, 1 << 1);
409 nir_ssa_def
*second_value
= nir_imm_ivec2(b
, 30, 40);
410 nir_store_var(b
, v
[0], second_value
, 1 << 0);
412 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
413 nir_store_var(b
, v
[1], read_value
, 1 << 1);
415 nir_validate_shader(b
->shader
, NULL
);
417 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
418 EXPECT_TRUE(progress
);
420 nir_validate_shader(b
->shader
, NULL
);
422 nir_opt_constant_folding(b
->shader
);
423 nir_validate_shader(b
->shader
, NULL
);
425 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
427 /* Store to v[1] should use first_value directly. The write of
428 * second_value did not overwrite the component it uses.
430 nir_intrinsic_instr
*store_to_v1
= get_intrinsic(nir_intrinsic_store_deref
, 2);
431 ASSERT_EQ(nir_intrinsic_get_var(store_to_v1
, 0), v
[1]);
432 ASSERT_EQ(nir_src_comp_as_uint(store_to_v1
->src
[1], 1), 20);
435 TEST_F(nir_copy_prop_vars_test
, store_store_load_different_components_in_many_blocks
)
437 nir_variable
**v
= create_many_ivec2(nir_var_function_temp
, "v", 2);
439 nir_ssa_def
*first_value
= nir_imm_ivec2(b
, 10, 20);
440 nir_store_var(b
, v
[0], first_value
, 1 << 1);
442 /* Adding an if statement will cause blocks to be created. */
443 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
445 nir_ssa_def
*second_value
= nir_imm_ivec2(b
, 30, 40);
446 nir_store_var(b
, v
[0], second_value
, 1 << 0);
448 /* Adding an if statement will cause blocks to be created. */
449 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
451 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
452 nir_store_var(b
, v
[1], read_value
, 1 << 1);
454 nir_validate_shader(b
->shader
, NULL
);
456 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
457 EXPECT_TRUE(progress
);
459 nir_validate_shader(b
->shader
, NULL
);
461 nir_opt_constant_folding(b
->shader
);
462 nir_validate_shader(b
->shader
, NULL
);
464 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
466 /* Store to v[1] should use first_value directly. The write of
467 * second_value did not overwrite the component it uses.
469 nir_intrinsic_instr
*store_to_v1
= get_intrinsic(nir_intrinsic_store_deref
, 2);
470 ASSERT_EQ(nir_intrinsic_get_var(store_to_v1
, 0), v
[1]);
471 ASSERT_EQ(nir_src_comp_as_uint(store_to_v1
->src
[1], 1), 20);
474 TEST_F(nir_copy_prop_vars_test
, memory_barrier_in_two_blocks
)
476 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 4);
478 nir_store_var(b
, v
[0], nir_imm_int(b
, 1), 1);
479 nir_store_var(b
, v
[1], nir_imm_int(b
, 2), 1);
481 /* Split into many blocks. */
482 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
484 nir_store_var(b
, v
[2], nir_load_var(b
, v
[0]), 1);
486 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQ_REL
,
489 nir_store_var(b
, v
[3], nir_load_var(b
, v
[1]), 1);
491 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
492 ASSERT_TRUE(progress
);
494 /* Only the second load will remain after the optimization. */
495 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_load_deref
));
496 nir_intrinsic_instr
*load
= get_intrinsic(nir_intrinsic_load_deref
, 0);
497 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), v
[1]);
500 TEST_F(nir_redundant_load_vars_test
, acquire_barrier_prevents_load_removal
)
502 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 1);
504 nir_load_var(b
, x
[0]);
506 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
509 nir_load_var(b
, x
[0]);
511 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
512 ASSERT_FALSE(progress
);
514 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref
));
517 TEST_F(nir_redundant_load_vars_test
, acquire_barrier_prevents_same_mode_load_removal
)
519 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
521 nir_load_var(b
, x
[0]);
522 nir_load_var(b
, x
[1]);
524 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
527 nir_load_var(b
, x
[0]);
528 nir_load_var(b
, x
[1]);
530 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
531 ASSERT_FALSE(progress
);
533 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_load_deref
));
536 TEST_F(nir_redundant_load_vars_test
, acquire_barrier_allows_different_mode_load_removal
)
538 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
539 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 2);
541 nir_load_var(b
, x
[0]);
542 nir_load_var(b
, x
[1]);
543 nir_load_var(b
, y
[0]);
544 nir_load_var(b
, y
[1]);
546 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
549 nir_load_var(b
, x
[0]);
550 nir_load_var(b
, x
[1]);
551 nir_load_var(b
, y
[0]);
552 nir_load_var(b
, y
[1]);
554 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
555 ASSERT_TRUE(progress
);
557 ASSERT_EQ(6, count_intrinsics(nir_intrinsic_load_deref
));
559 nir_intrinsic_instr
*load
;
561 load
= get_intrinsic(nir_intrinsic_load_deref
, 0);
562 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[0]);
563 load
= get_intrinsic(nir_intrinsic_load_deref
, 1);
564 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[1]);
566 load
= get_intrinsic(nir_intrinsic_load_deref
, 2);
567 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), y
[0]);
568 load
= get_intrinsic(nir_intrinsic_load_deref
, 3);
569 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), y
[1]);
571 load
= get_intrinsic(nir_intrinsic_load_deref
, 4);
572 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[0]);
573 load
= get_intrinsic(nir_intrinsic_load_deref
, 5);
574 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[1]);
577 TEST_F(nir_redundant_load_vars_test
, release_barrier_allows_load_removal
)
579 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 1);
581 nir_load_var(b
, x
[0]);
583 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
586 nir_load_var(b
, x
[0]);
588 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
589 ASSERT_TRUE(progress
);
591 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_load_deref
));
594 TEST_F(nir_redundant_load_vars_test
, release_barrier_allows_same_mode_load_removal
)
596 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
598 nir_load_var(b
, x
[0]);
599 nir_load_var(b
, x
[1]);
601 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
604 nir_load_var(b
, x
[0]);
605 nir_load_var(b
, x
[1]);
607 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
608 ASSERT_TRUE(progress
);
610 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref
));
613 TEST_F(nir_redundant_load_vars_test
, release_barrier_allows_different_mode_load_removal
)
615 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
616 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 2);
618 nir_load_var(b
, x
[0]);
619 nir_load_var(b
, x
[1]);
620 nir_load_var(b
, y
[0]);
621 nir_load_var(b
, y
[1]);
623 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
626 nir_load_var(b
, x
[0]);
627 nir_load_var(b
, x
[1]);
628 nir_load_var(b
, y
[0]);
629 nir_load_var(b
, y
[1]);
631 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
632 ASSERT_TRUE(progress
);
634 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_load_deref
));
636 nir_intrinsic_instr
*load
;
638 load
= get_intrinsic(nir_intrinsic_load_deref
, 0);
639 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[0]);
640 load
= get_intrinsic(nir_intrinsic_load_deref
, 1);
641 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[1]);
643 load
= get_intrinsic(nir_intrinsic_load_deref
, 2);
644 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), y
[0]);
645 load
= get_intrinsic(nir_intrinsic_load_deref
, 3);
646 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), y
[1]);
649 TEST_F(nir_copy_prop_vars_test
, acquire_barrier_prevents_propagation
)
651 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 1);
653 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
655 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
658 nir_load_var(b
, x
[0]);
660 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
661 ASSERT_FALSE(progress
);
663 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
664 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_load_deref
));
667 TEST_F(nir_copy_prop_vars_test
, acquire_barrier_prevents_same_mode_propagation
)
669 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
671 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
672 nir_store_var(b
, x
[1], nir_imm_int(b
, 20), 1);
674 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
677 nir_load_var(b
, x
[0]);
678 nir_load_var(b
, x
[1]);
680 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
681 ASSERT_FALSE(progress
);
683 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_store_deref
));
684 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref
));
687 TEST_F(nir_copy_prop_vars_test
, acquire_barrier_allows_different_mode_propagation
)
689 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
690 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 2);
692 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
693 nir_store_var(b
, x
[1], nir_imm_int(b
, 20), 1);
694 nir_store_var(b
, y
[0], nir_imm_int(b
, 30), 1);
695 nir_store_var(b
, y
[1], nir_imm_int(b
, 40), 1);
697 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
700 nir_load_var(b
, x
[0]);
701 nir_load_var(b
, x
[1]);
702 nir_load_var(b
, y
[0]);
703 nir_load_var(b
, y
[1]);
705 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
706 ASSERT_TRUE(progress
);
708 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_store_deref
));
709 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref
));
711 nir_intrinsic_instr
*store
;
713 store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
714 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), x
[0]);
715 store
= get_intrinsic(nir_intrinsic_store_deref
, 1);
716 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), x
[1]);
718 store
= get_intrinsic(nir_intrinsic_store_deref
, 2);
719 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), y
[0]);
720 store
= get_intrinsic(nir_intrinsic_store_deref
, 3);
721 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), y
[1]);
723 nir_intrinsic_instr
*load
;
725 load
= get_intrinsic(nir_intrinsic_load_deref
, 0);
726 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[0]);
727 load
= get_intrinsic(nir_intrinsic_load_deref
, 1);
728 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[1]);
731 TEST_F(nir_copy_prop_vars_test
, release_barrier_allows_propagation
)
733 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 1);
735 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
737 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
740 nir_load_var(b
, x
[0]);
742 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
743 ASSERT_TRUE(progress
);
745 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
748 TEST_F(nir_copy_prop_vars_test
, release_barrier_allows_same_mode_propagation
)
750 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
752 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
753 nir_store_var(b
, x
[1], nir_imm_int(b
, 20), 1);
755 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
758 nir_load_var(b
, x
[0]);
759 nir_load_var(b
, x
[1]);
761 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
762 ASSERT_TRUE(progress
);
764 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_store_deref
));
765 ASSERT_EQ(0, count_intrinsics(nir_intrinsic_load_deref
));
768 TEST_F(nir_copy_prop_vars_test
, release_barrier_allows_different_mode_propagation
)
770 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
771 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 2);
773 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
774 nir_store_var(b
, x
[1], nir_imm_int(b
, 20), 1);
775 nir_store_var(b
, y
[0], nir_imm_int(b
, 30), 1);
776 nir_store_var(b
, y
[1], nir_imm_int(b
, 40), 1);
778 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
781 nir_load_var(b
, x
[0]);
782 nir_load_var(b
, x
[1]);
783 nir_load_var(b
, y
[0]);
784 nir_load_var(b
, y
[1]);
786 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
787 ASSERT_TRUE(progress
);
789 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_store_deref
));
790 ASSERT_EQ(0, count_intrinsics(nir_intrinsic_load_deref
));
792 nir_intrinsic_instr
*store
;
794 store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
795 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), x
[0]);
796 store
= get_intrinsic(nir_intrinsic_store_deref
, 1);
797 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), x
[1]);
799 store
= get_intrinsic(nir_intrinsic_store_deref
, 2);
800 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), y
[0]);
801 store
= get_intrinsic(nir_intrinsic_store_deref
, 3);
802 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), y
[1]);
805 TEST_F(nir_copy_prop_vars_test
, acquire_barrier_prevents_propagation_from_copy
)
807 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 3);
809 nir_copy_var(b
, x
[1], x
[0]);
811 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
814 nir_copy_var(b
, x
[2], x
[1]);
816 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
817 ASSERT_FALSE(progress
);
819 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref
));
821 nir_intrinsic_instr
*copy
;
823 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 0);
824 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
826 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 1);
827 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[1]);
830 TEST_F(nir_copy_prop_vars_test
, acquire_barrier_prevents_propagation_from_copy_to_different_mode
)
832 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
833 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 1);
835 nir_copy_var(b
, y
[0], x
[0]);
837 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
840 nir_copy_var(b
, x
[1], y
[0]);
842 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
843 ASSERT_FALSE(progress
);
845 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref
));
847 nir_intrinsic_instr
*copy
;
849 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 0);
850 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
852 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 1);
853 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), y
[0]);
856 TEST_F(nir_copy_prop_vars_test
, release_barrier_allows_propagation_from_copy
)
858 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 3);
860 nir_copy_var(b
, x
[1], x
[0]);
862 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
865 nir_copy_var(b
, x
[2], x
[1]);
867 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
868 ASSERT_TRUE(progress
);
870 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref
));
872 nir_intrinsic_instr
*copy
;
874 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 0);
875 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
877 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 1);
878 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
881 TEST_F(nir_copy_prop_vars_test
, release_barrier_allows_propagation_from_copy_to_different_mode
)
883 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
884 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 1);
886 nir_copy_var(b
, y
[0], x
[0]);
888 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
891 nir_copy_var(b
, x
[1], y
[0]);
893 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
894 ASSERT_TRUE(progress
);
896 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref
));
898 nir_intrinsic_instr
*copy
;
900 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 0);
901 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
903 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 1);
904 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
907 TEST_F(nir_copy_prop_vars_test
, simple_store_load_in_two_blocks
)
909 nir_variable
**v
= create_many_ivec2(nir_var_function_temp
, "v", 2);
910 unsigned mask
= 1 | 2;
912 nir_ssa_def
*stored_value
= nir_imm_ivec2(b
, 10, 20);
913 nir_store_var(b
, v
[0], stored_value
, mask
);
915 /* Adding an if statement will cause blocks to be created. */
916 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
918 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
919 nir_store_var(b
, v
[1], read_value
, mask
);
921 nir_validate_shader(b
->shader
, NULL
);
923 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
924 EXPECT_TRUE(progress
);
926 nir_validate_shader(b
->shader
, NULL
);
928 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
930 for (int i
= 0; i
< 2; i
++) {
931 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, i
);
932 ASSERT_TRUE(store
->src
[1].is_ssa
);
933 EXPECT_EQ(store
->src
[1].ssa
, stored_value
);
937 TEST_F(nir_copy_prop_vars_test
, load_direct_array_deref_on_vector_reuses_previous_load
)
939 nir_variable
*in0
= create_ivec2(nir_var_mem_ssbo
, "in0");
940 nir_variable
*in1
= create_ivec2(nir_var_mem_ssbo
, "in1");
941 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
942 nir_variable
*out
= create_int(nir_var_mem_ssbo
, "out");
944 nir_store_var(b
, vec
, nir_load_var(b
, in0
), 1 << 0);
945 nir_store_var(b
, vec
, nir_load_var(b
, in1
), 1 << 1);
947 /* This load will be dropped, as vec.y (or vec[1]) is already known. */
948 nir_deref_instr
*deref
=
949 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 1);
950 nir_ssa_def
*loaded_from_deref
= nir_load_deref(b
, deref
);
952 /* This store should use the value loaded from in1. */
953 nir_store_var(b
, out
, loaded_from_deref
, 1 << 0);
955 nir_validate_shader(b
->shader
, NULL
);
956 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 3);
957 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
959 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
960 EXPECT_TRUE(progress
);
962 nir_validate_shader(b
->shader
, NULL
);
963 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
964 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
966 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 2);
967 ASSERT_TRUE(store
->src
[1].is_ssa
);
969 /* NOTE: The ALU instruction is how we get the vec.y. */
970 ASSERT_TRUE(nir_src_as_alu_instr(store
->src
[1]));
973 TEST_F(nir_copy_prop_vars_test
, load_direct_array_deref_on_vector_reuses_previous_copy
)
975 nir_variable
*in0
= create_ivec2(nir_var_mem_ssbo
, "in0");
976 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
978 nir_copy_var(b
, vec
, in0
);
980 /* This load will be replaced with one from in0. */
981 nir_deref_instr
*deref
=
982 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 1);
983 nir_load_deref(b
, deref
);
985 nir_validate_shader(b
->shader
, NULL
);
987 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
988 EXPECT_TRUE(progress
);
990 nir_validate_shader(b
->shader
, NULL
);
991 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
993 nir_intrinsic_instr
*load
= get_intrinsic(nir_intrinsic_load_deref
, 0);
994 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), in0
);
997 TEST_F(nir_copy_prop_vars_test
, load_direct_array_deref_on_vector_gets_reused
)
999 nir_variable
*in0
= create_ivec2(nir_var_mem_ssbo
, "in0");
1000 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
1001 nir_variable
*out
= create_ivec2(nir_var_mem_ssbo
, "out");
1003 /* Loading "vec[1]" deref will save the information about vec.y. */
1004 nir_deref_instr
*deref
=
1005 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 1);
1006 nir_load_deref(b
, deref
);
1008 /* Store to vec.x. */
1009 nir_store_var(b
, vec
, nir_load_var(b
, in0
), 1 << 0);
1011 /* This load will be dropped, since both vec.x and vec.y are known. */
1012 nir_ssa_def
*loaded_from_vec
= nir_load_var(b
, vec
);
1013 nir_store_var(b
, out
, loaded_from_vec
, 0x3);
1015 nir_validate_shader(b
->shader
, NULL
);
1016 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 3);
1017 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1019 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1020 EXPECT_TRUE(progress
);
1022 nir_validate_shader(b
->shader
, NULL
);
1023 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
1024 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1026 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1027 ASSERT_TRUE(store
->src
[1].is_ssa
);
1028 ASSERT_TRUE(nir_src_as_alu_instr(store
->src
[1]));
1031 TEST_F(nir_copy_prop_vars_test
, store_load_direct_array_deref_on_vector
)
1033 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
1034 nir_variable
*out0
= create_int(nir_var_mem_ssbo
, "out0");
1035 nir_variable
*out1
= create_ivec2(nir_var_mem_ssbo
, "out1");
1037 /* Store to "vec[1]" and "vec[0]". */
1038 nir_deref_instr
*store_deref_y
=
1039 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 1);
1040 nir_store_deref(b
, store_deref_y
, nir_imm_int(b
, 20), 1);
1042 nir_deref_instr
*store_deref_x
=
1043 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 0);
1044 nir_store_deref(b
, store_deref_x
, nir_imm_int(b
, 10), 1);
1046 /* Both loads below will be dropped, because the values are already known. */
1047 nir_deref_instr
*load_deref_y
=
1048 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 1);
1049 nir_store_var(b
, out0
, nir_load_deref(b
, load_deref_y
), 1);
1051 nir_store_var(b
, out1
, nir_load_var(b
, vec
), 1);
1053 nir_validate_shader(b
->shader
, NULL
);
1054 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
1055 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 4);
1057 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1058 EXPECT_TRUE(progress
);
1060 nir_validate_shader(b
->shader
, NULL
);
1061 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 0);
1062 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 4);
1064 /* Third store will just use the value from first store. */
1065 nir_intrinsic_instr
*first_store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1066 nir_intrinsic_instr
*third_store
= get_intrinsic(nir_intrinsic_store_deref
, 2);
1067 ASSERT_TRUE(third_store
->src
[1].is_ssa
);
1068 EXPECT_EQ(third_store
->src
[1].ssa
, first_store
->src
[1].ssa
);
1070 /* Fourth store will compose first and second store values. */
1071 nir_intrinsic_instr
*fourth_store
= get_intrinsic(nir_intrinsic_store_deref
, 3);
1072 ASSERT_TRUE(fourth_store
->src
[1].is_ssa
);
1073 EXPECT_TRUE(nir_src_as_alu_instr(fourth_store
->src
[1]));
1076 TEST_F(nir_copy_prop_vars_test
, store_load_indirect_array_deref_on_vector
)
1078 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
1079 nir_variable
*idx
= create_int(nir_var_mem_ssbo
, "idx");
1080 nir_variable
*out
= create_int(nir_var_mem_ssbo
, "out");
1082 nir_ssa_def
*idx_ssa
= nir_load_var(b
, idx
);
1084 /* Store to vec[idx]. */
1085 nir_deref_instr
*store_deref
=
1086 nir_build_deref_array(b
, nir_build_deref_var(b
, vec
), idx_ssa
);
1087 nir_store_deref(b
, store_deref
, nir_imm_int(b
, 20), 1);
1089 /* Load from vec[idx] to store in out. This load should be dropped. */
1090 nir_deref_instr
*load_deref
=
1091 nir_build_deref_array(b
, nir_build_deref_var(b
, vec
), idx_ssa
);
1092 nir_store_var(b
, out
, nir_load_deref(b
, load_deref
), 1);
1094 nir_validate_shader(b
->shader
, NULL
);
1095 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
1096 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1098 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1099 EXPECT_TRUE(progress
);
1101 nir_validate_shader(b
->shader
, NULL
);
1102 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
1103 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1105 /* Store to vec[idx] propagated to out. */
1106 nir_intrinsic_instr
*first
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1107 nir_intrinsic_instr
*second
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1108 ASSERT_TRUE(first
->src
[1].is_ssa
);
1109 ASSERT_TRUE(second
->src
[1].is_ssa
);
1110 EXPECT_EQ(first
->src
[1].ssa
, second
->src
[1].ssa
);
1113 TEST_F(nir_copy_prop_vars_test
, store_load_direct_and_indirect_array_deref_on_vector
)
1115 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
1116 nir_variable
*idx
= create_int(nir_var_mem_ssbo
, "idx");
1117 nir_variable
**out
= create_many_int(nir_var_mem_ssbo
, "out", 2);
1119 nir_ssa_def
*idx_ssa
= nir_load_var(b
, idx
);
1122 nir_store_var(b
, vec
, nir_imm_ivec2(b
, 10, 10), 1 | 2);
1124 /* Load from vec[idx]. This load is currently not dropped. */
1125 nir_deref_instr
*indirect
=
1126 nir_build_deref_array(b
, nir_build_deref_var(b
, vec
), idx_ssa
);
1127 nir_store_var(b
, out
[0], nir_load_deref(b
, indirect
), 1);
1129 /* Load from vec[idx] again. This load should be dropped. */
1130 nir_store_var(b
, out
[1], nir_load_deref(b
, indirect
), 1);
1132 nir_validate_shader(b
->shader
, NULL
);
1133 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 3);
1134 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
1136 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1137 EXPECT_TRUE(progress
);
1139 nir_validate_shader(b
->shader
, NULL
);
1140 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
1141 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
1143 /* Store to vec[idx] propagated to out. */
1144 nir_intrinsic_instr
*second
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1145 nir_intrinsic_instr
*third
= get_intrinsic(nir_intrinsic_store_deref
, 2);
1146 ASSERT_TRUE(second
->src
[1].is_ssa
);
1147 ASSERT_TRUE(third
->src
[1].is_ssa
);
1148 EXPECT_EQ(second
->src
[1].ssa
, third
->src
[1].ssa
);
1151 TEST_F(nir_copy_prop_vars_test
, store_load_indirect_array_deref
)
1153 nir_variable
*arr
= create_var(nir_var_mem_ssbo
,
1154 glsl_array_type(glsl_int_type(), 10, 0),
1156 nir_variable
*idx
= create_int(nir_var_mem_ssbo
, "idx");
1157 nir_variable
*out
= create_int(nir_var_mem_ssbo
, "out");
1159 nir_ssa_def
*idx_ssa
= nir_load_var(b
, idx
);
1161 /* Store to arr[idx]. */
1162 nir_deref_instr
*store_deref
=
1163 nir_build_deref_array(b
, nir_build_deref_var(b
, arr
), idx_ssa
);
1164 nir_store_deref(b
, store_deref
, nir_imm_int(b
, 20), 1);
1166 /* Load from arr[idx] to store in out. This load should be dropped. */
1167 nir_deref_instr
*load_deref
=
1168 nir_build_deref_array(b
, nir_build_deref_var(b
, arr
), idx_ssa
);
1169 nir_store_var(b
, out
, nir_load_deref(b
, load_deref
), 1);
1171 nir_validate_shader(b
->shader
, NULL
);
1172 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
1173 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1175 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1176 EXPECT_TRUE(progress
);
1178 nir_validate_shader(b
->shader
, NULL
);
1179 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
1180 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1182 /* Store to arr[idx] propagated to out. */
1183 nir_intrinsic_instr
*first
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1184 nir_intrinsic_instr
*second
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1185 ASSERT_TRUE(first
->src
[1].is_ssa
);
1186 ASSERT_TRUE(second
->src
[1].is_ssa
);
1187 EXPECT_EQ(first
->src
[1].ssa
, second
->src
[1].ssa
);
1190 TEST_F(nir_dead_write_vars_test
, no_dead_writes_in_block
)
1192 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 2);
1194 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1196 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1197 ASSERT_FALSE(progress
);
1200 TEST_F(nir_dead_write_vars_test
, no_dead_writes_different_components_in_block
)
1202 nir_variable
**v
= create_many_ivec2(nir_var_mem_ssbo
, "v", 3);
1204 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1 << 0);
1205 nir_store_var(b
, v
[0], nir_load_var(b
, v
[2]), 1 << 1);
1207 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1208 ASSERT_FALSE(progress
);
1211 TEST_F(nir_dead_write_vars_test
, no_dead_writes_in_if_statement
)
1213 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 6);
1215 nir_store_var(b
, v
[2], nir_load_var(b
, v
[0]), 1);
1216 nir_store_var(b
, v
[3], nir_load_var(b
, v
[1]), 1);
1218 /* Each arm of the if statement will overwrite one store. */
1219 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
1220 nir_store_var(b
, v
[2], nir_load_var(b
, v
[4]), 1);
1222 nir_push_else(b
, if_stmt
);
1223 nir_store_var(b
, v
[3], nir_load_var(b
, v
[5]), 1);
1225 nir_pop_if(b
, if_stmt
);
1227 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1228 ASSERT_FALSE(progress
);
1231 TEST_F(nir_dead_write_vars_test
, no_dead_writes_in_loop_statement
)
1233 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 3);
1235 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1237 /* Loop will write other value. Since it might not be executed, it doesn't
1238 * kill the first write.
1240 nir_loop
*loop
= nir_push_loop(b
);
1242 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
1243 nir_jump(b
, nir_jump_break
);
1244 nir_pop_if(b
, if_stmt
);
1246 nir_store_var(b
, v
[0], nir_load_var(b
, v
[2]), 1);
1247 nir_pop_loop(b
, loop
);
1249 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1250 ASSERT_FALSE(progress
);
1253 TEST_F(nir_dead_write_vars_test
, dead_write_in_block
)
1255 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 3);
1257 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1258 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
1259 nir_store_var(b
, v
[0], load_v2
, 1);
1261 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1262 ASSERT_TRUE(progress
);
1264 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
1266 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1267 ASSERT_TRUE(store
->src
[1].is_ssa
);
1268 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
1271 TEST_F(nir_dead_write_vars_test
, dead_write_components_in_block
)
1273 nir_variable
**v
= create_many_ivec2(nir_var_mem_ssbo
, "v", 3);
1275 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1 << 0);
1276 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
1277 nir_store_var(b
, v
[0], load_v2
, 1 << 0);
1279 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1280 ASSERT_TRUE(progress
);
1282 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
1284 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1285 ASSERT_TRUE(store
->src
[1].is_ssa
);
1286 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
1290 /* TODO: The DISABLED tests below depend on the dead write removal be able to
1291 * identify dead writes between multiple blocks. This is still not
1295 TEST_F(nir_dead_write_vars_test
, DISABLED_dead_write_in_two_blocks
)
1297 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 3);
1299 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1300 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
1302 /* Causes the stores to be in different blocks. */
1303 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
1305 nir_store_var(b
, v
[0], load_v2
, 1);
1307 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1308 ASSERT_TRUE(progress
);
1310 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
1312 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1313 ASSERT_TRUE(store
->src
[1].is_ssa
);
1314 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
1317 TEST_F(nir_dead_write_vars_test
, DISABLED_dead_write_components_in_two_blocks
)
1319 nir_variable
**v
= create_many_ivec2(nir_var_mem_ssbo
, "v", 3);
1321 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1 << 0);
1323 /* Causes the stores to be in different blocks. */
1324 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
1326 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
1327 nir_store_var(b
, v
[0], load_v2
, 1 << 0);
1329 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1330 ASSERT_TRUE(progress
);
1332 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
1334 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1335 ASSERT_TRUE(store
->src
[1].is_ssa
);
1336 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
1339 TEST_F(nir_dead_write_vars_test
, DISABLED_dead_writes_in_if_statement
)
1341 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 4);
1343 /* Both branches will overwrite, making the previous store dead. */
1344 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1346 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
1347 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
1348 nir_store_var(b
, v
[0], load_v2
, 1);
1350 nir_push_else(b
, if_stmt
);
1351 nir_ssa_def
*load_v3
= nir_load_var(b
, v
[3]);
1352 nir_store_var(b
, v
[0], load_v3
, 1);
1354 nir_pop_if(b
, if_stmt
);
1356 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1357 ASSERT_TRUE(progress
);
1358 EXPECT_EQ(2, count_intrinsics(nir_intrinsic_store_deref
));
1360 nir_intrinsic_instr
*first_store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1361 ASSERT_TRUE(first_store
->src
[1].is_ssa
);
1362 EXPECT_EQ(first_store
->src
[1].ssa
, load_v2
);
1364 nir_intrinsic_instr
*second_store
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1365 ASSERT_TRUE(second_store
->src
[1].is_ssa
);
1366 EXPECT_EQ(second_store
->src
[1].ssa
, load_v3
);
1369 TEST_F(nir_dead_write_vars_test
, DISABLED_memory_barrier_in_two_blocks
)
1371 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 2);
1373 nir_store_var(b
, v
[0], nir_imm_int(b
, 1), 1);
1374 nir_store_var(b
, v
[1], nir_imm_int(b
, 2), 1);
1376 /* Split into many blocks. */
1377 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
1379 /* Because it is before the barrier, this will kill the previous store to that target. */
1380 nir_store_var(b
, v
[0], nir_imm_int(b
, 3), 1);
1382 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQ_REL
,
1385 nir_store_var(b
, v
[1], nir_imm_int(b
, 4), 1);
1387 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1388 ASSERT_TRUE(progress
);
1390 EXPECT_EQ(3, count_intrinsics(nir_intrinsic_store_deref
));
1393 TEST_F(nir_dead_write_vars_test
, DISABLED_unrelated_barrier_in_two_blocks
)
1395 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 3);
1396 nir_variable
*out
= create_int(nir_var_shader_out
, "out");
1398 nir_store_var(b
, out
, nir_load_var(b
, v
[1]), 1);
1399 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1401 /* Split into many blocks. */
1402 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
1404 /* Emit vertex will ensure writes to output variables are considered used,
1405 * but should not affect other types of variables. */
1407 nir_builder_instr_insert(b
, &nir_intrinsic_instr_create(b
->shader
, nir_intrinsic_emit_vertex
)->instr
);
1409 nir_store_var(b
, out
, nir_load_var(b
, v
[2]), 1);
1410 nir_store_var(b
, v
[0], nir_load_var(b
, v
[2]), 1);
1412 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1413 ASSERT_TRUE(progress
);
1415 /* Verify the first write to v[0] was removed. */
1416 EXPECT_EQ(3, count_intrinsics(nir_intrinsic_store_deref
));
1418 nir_intrinsic_instr
*first_store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1419 EXPECT_EQ(nir_intrinsic_get_var(first_store
, 0), out
);
1421 nir_intrinsic_instr
*second_store
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1422 EXPECT_EQ(nir_intrinsic_get_var(second_store
, 0), out
);
1424 nir_intrinsic_instr
*third_store
= get_intrinsic(nir_intrinsic_store_deref
, 2);
1425 EXPECT_EQ(nir_intrinsic_get_var(third_store
, 0), v
[0]);
1428 TEST_F(nir_combine_stores_test
, non_overlapping_stores
)
1430 nir_variable
**v
= create_many_ivec4(nir_var_mem_ssbo
, "v", 4);
1431 nir_variable
*out
= create_ivec4(nir_var_shader_out
, "out");
1433 for (int i
= 0; i
< 4; i
++)
1434 nir_store_var(b
, out
, nir_load_var(b
, v
[i
]), 1 << i
);
1436 nir_validate_shader(b
->shader
, NULL
);
1438 bool progress
= nir_opt_combine_stores(b
->shader
, nir_var_shader_out
);
1439 ASSERT_TRUE(progress
);
1441 nir_validate_shader(b
->shader
, NULL
);
1443 /* Clean up to verify from where the values in combined store are coming. */
1444 nir_copy_prop(b
->shader
);
1445 nir_opt_dce(b
->shader
);
1447 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 1);
1448 nir_intrinsic_instr
*combined
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1449 ASSERT_EQ(nir_intrinsic_write_mask(combined
), 0xf);
1450 ASSERT_EQ(nir_intrinsic_get_var(combined
, 0), out
);
1452 nir_alu_instr
*vec
= nir_src_as_alu_instr(combined
->src
[1]);
1454 for (int i
= 0; i
< 4; i
++) {
1455 nir_intrinsic_instr
*load
= nir_src_as_intrinsic(vec
->src
[i
].src
);
1456 ASSERT_EQ(load
->intrinsic
, nir_intrinsic_load_deref
);
1457 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), v
[i
])
1458 << "Source value for component " << i
<< " of store is wrong";
1459 ASSERT_EQ(vec
->src
[i
].swizzle
[0], i
)
1460 << "Source component for component " << i
<< " of store is wrong";
1464 TEST_F(nir_combine_stores_test
, overlapping_stores
)
1466 nir_variable
**v
= create_many_ivec4(nir_var_mem_ssbo
, "v", 3);
1467 nir_variable
*out
= create_ivec4(nir_var_shader_out
, "out");
1469 /* Make stores with xy, yz and zw masks. */
1470 for (int i
= 0; i
< 3; i
++) {
1471 nir_component_mask_t mask
= (1 << i
) | (1 << (i
+ 1));
1472 nir_store_var(b
, out
, nir_load_var(b
, v
[i
]), mask
);
1475 nir_validate_shader(b
->shader
, NULL
);
1477 bool progress
= nir_opt_combine_stores(b
->shader
, nir_var_shader_out
);
1478 ASSERT_TRUE(progress
);
1480 nir_validate_shader(b
->shader
, NULL
);
1482 /* Clean up to verify from where the values in combined store are coming. */
1483 nir_copy_prop(b
->shader
);
1484 nir_opt_dce(b
->shader
);
1486 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 1);
1487 nir_intrinsic_instr
*combined
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1488 ASSERT_EQ(nir_intrinsic_write_mask(combined
), 0xf);
1489 ASSERT_EQ(nir_intrinsic_get_var(combined
, 0), out
);
1491 nir_alu_instr
*vec
= nir_src_as_alu_instr(combined
->src
[1]);
1494 /* Component x comes from v[0]. */
1495 nir_intrinsic_instr
*load_for_x
= nir_src_as_intrinsic(vec
->src
[0].src
);
1496 ASSERT_EQ(nir_intrinsic_get_var(load_for_x
, 0), v
[0]);
1497 ASSERT_EQ(vec
->src
[0].swizzle
[0], 0);
1499 /* Component y comes from v[1]. */
1500 nir_intrinsic_instr
*load_for_y
= nir_src_as_intrinsic(vec
->src
[1].src
);
1501 ASSERT_EQ(nir_intrinsic_get_var(load_for_y
, 0), v
[1]);
1502 ASSERT_EQ(vec
->src
[1].swizzle
[0], 1);
1504 /* Components z and w come from v[2]. */
1505 nir_intrinsic_instr
*load_for_z
= nir_src_as_intrinsic(vec
->src
[2].src
);
1506 nir_intrinsic_instr
*load_for_w
= nir_src_as_intrinsic(vec
->src
[3].src
);
1507 ASSERT_EQ(load_for_z
, load_for_w
);
1508 ASSERT_EQ(nir_intrinsic_get_var(load_for_z
, 0), v
[2]);
1509 ASSERT_EQ(vec
->src
[2].swizzle
[0], 2);
1510 ASSERT_EQ(vec
->src
[3].swizzle
[0], 3);
1513 TEST_F(nir_combine_stores_test
, direct_array_derefs
)
1515 nir_variable
**v
= create_many_ivec4(nir_var_mem_ssbo
, "vec", 2);
1516 nir_variable
**s
= create_many_int(nir_var_mem_ssbo
, "scalar", 2);
1517 nir_variable
*out
= create_ivec4(nir_var_mem_ssbo
, "out");
1519 nir_deref_instr
*out_deref
= nir_build_deref_var(b
, out
);
1521 /* Store to vector with mask x. */
1522 nir_store_deref(b
, out_deref
, nir_load_var(b
, v
[0]),
1525 /* Store to vector with mask yz. */
1526 nir_store_deref(b
, out_deref
, nir_load_var(b
, v
[1]),
1527 (1 << 2) | (1 << 1));
1529 /* Store to vector[2], overlapping with previous store. */
1531 nir_build_deref_array_imm(b
, out_deref
, 2),
1532 nir_load_var(b
, s
[0]),
1535 /* Store to vector[3], no overlap. */
1537 nir_build_deref_array_imm(b
, out_deref
, 3),
1538 nir_load_var(b
, s
[1]),
1541 nir_validate_shader(b
->shader
, NULL
);
1543 bool progress
= nir_opt_combine_stores(b
->shader
, nir_var_mem_ssbo
);
1544 ASSERT_TRUE(progress
);
1546 nir_validate_shader(b
->shader
, NULL
);
1548 /* Clean up to verify from where the values in combined store are coming. */
1549 nir_copy_prop(b
->shader
);
1550 nir_opt_dce(b
->shader
);
1552 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 1);
1553 nir_intrinsic_instr
*combined
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1554 ASSERT_EQ(nir_intrinsic_write_mask(combined
), 0xf);
1555 ASSERT_EQ(nir_intrinsic_get_var(combined
, 0), out
);
1557 nir_alu_instr
*vec
= nir_src_as_alu_instr(combined
->src
[1]);
1560 /* Component x comes from v[0]. */
1561 nir_intrinsic_instr
*load_for_x
= nir_src_as_intrinsic(vec
->src
[0].src
);
1562 ASSERT_EQ(nir_intrinsic_get_var(load_for_x
, 0), v
[0]);
1563 ASSERT_EQ(vec
->src
[0].swizzle
[0], 0);
1565 /* Component y comes from v[1]. */
1566 nir_intrinsic_instr
*load_for_y
= nir_src_as_intrinsic(vec
->src
[1].src
);
1567 ASSERT_EQ(nir_intrinsic_get_var(load_for_y
, 0), v
[1]);
1568 ASSERT_EQ(vec
->src
[1].swizzle
[0], 1);
1570 /* Components z comes from s[0]. */
1571 nir_intrinsic_instr
*load_for_z
= nir_src_as_intrinsic(vec
->src
[2].src
);
1572 ASSERT_EQ(nir_intrinsic_get_var(load_for_z
, 0), s
[0]);
1573 ASSERT_EQ(vec
->src
[2].swizzle
[0], 0);
1575 /* Component w comes from s[1]. */
1576 nir_intrinsic_instr
*load_for_w
= nir_src_as_intrinsic(vec
->src
[3].src
);
1577 ASSERT_EQ(nir_intrinsic_get_var(load_for_w
, 0), s
[1]);
1578 ASSERT_EQ(vec
->src
[3].swizzle
[0], 0);
1581 TEST_F(nir_split_vars_test
, simple_split
)
1583 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1584 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1586 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1587 for (int i
= 0; i
< 4; i
++)
1588 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1590 nir_validate_shader(b
->shader
, NULL
);
1591 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
1592 ASSERT_EQ(count_function_temp_vars(), 1);
1594 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1595 EXPECT_TRUE(progress
);
1597 nir_validate_shader(b
->shader
, NULL
);
1598 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1599 ASSERT_EQ(count_function_temp_vars(), 4);
1602 TEST_F(nir_split_vars_test
, simple_no_split_array_struct
)
1604 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1605 struct glsl_struct_field field
;
1607 field
.type
= glsl_float_type();
1608 field
.name
= ralloc_asprintf(b
, "field1");
1609 field
.location
= -1;
1612 const struct glsl_type
*st_type
= glsl_struct_type(&field
, 1, "struct", false);
1613 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(st_type
, 4, 0),
1616 nir_variable
*temp2
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0), "temp2");
1618 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1619 nir_deref_instr
*temp2_deref
= nir_build_deref_var(b
, temp2
);
1620 for (int i
= 0; i
< 4; i
++)
1621 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp2_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1623 for (int i
= 0; i
< 4; i
++)
1624 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);
1626 nir_validate_shader(b
->shader
, NULL
);
1627 ASSERT_EQ(count_derefs(nir_deref_type_array
), 8);
1628 ASSERT_EQ(count_derefs(nir_deref_type_struct
), 4);
1629 ASSERT_EQ(count_function_temp_vars(), 2);
1631 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1632 EXPECT_TRUE(progress
);
1634 nir_validate_shader(b
->shader
, NULL
);
1636 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
1637 ASSERT_EQ(count_derefs(nir_deref_type_struct
), 4);
1638 for (int i
= 0; i
< 4; i
++) {
1639 nir_deref_instr
*deref
= get_deref(nir_deref_type_array
, i
);
1641 ASSERT_TRUE(glsl_type_is_struct(deref
->type
));
1644 ASSERT_EQ(count_function_temp_vars(), 5);
1647 TEST_F(nir_split_vars_test
, simple_split_shader_temp
)
1649 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1650 nir_variable
*temp
= create_var(nir_var_shader_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1652 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1654 for (int i
= 0; i
< 4; i
++)
1655 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1657 nir_validate_shader(b
->shader
, NULL
);
1658 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
1659 ASSERT_EQ(count_shader_temp_vars(), 1);
1661 bool progress
= nir_split_array_vars(b
->shader
, nir_var_shader_temp
);
1662 EXPECT_TRUE(progress
);
1664 nir_validate_shader(b
->shader
, NULL
);
1665 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1666 ASSERT_EQ(count_shader_temp_vars(), 4);
1669 TEST_F(nir_split_vars_test
, simple_oob
)
1671 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 6);
1672 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1674 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1676 for (int i
= 0; i
< 6; i
++)
1677 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1679 nir_validate_shader(b
->shader
, NULL
);
1680 ASSERT_EQ(count_derefs(nir_deref_type_array
), 6);
1681 ASSERT_EQ(count_function_temp_vars(), 1);
1683 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1684 EXPECT_TRUE(progress
);
1686 nir_validate_shader(b
->shader
, NULL
);
1687 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1688 ASSERT_EQ(count_function_temp_vars(), 4);
1691 TEST_F(nir_split_vars_test
, simple_unused
)
1693 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 2);
1694 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1696 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1698 for (int i
= 0; i
< 2; i
++)
1699 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1701 nir_validate_shader(b
->shader
, NULL
);
1702 ASSERT_EQ(count_derefs(nir_deref_type_array
), 2);
1703 ASSERT_EQ(count_function_temp_vars(), 1);
1705 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1706 EXPECT_TRUE(progress
);
1708 nir_validate_shader(b
->shader
, NULL
);
1709 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1710 /* this pass doesn't remove the unused ones */
1711 ASSERT_EQ(count_function_temp_vars(), 4);
1714 TEST_F(nir_split_vars_test
, two_level_split
)
1716 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1717 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_array_type(glsl_int_type(), 4, 0), 4, 0),
1719 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1720 for (int i
= 0; i
< 4; i
++) {
1721 nir_deref_instr
*level0
= nir_build_deref_array_imm(b
, temp_deref
, i
);
1722 for (int j
= 0; j
< 4; j
++) {
1723 nir_deref_instr
*level1
= nir_build_deref_array_imm(b
, level0
, j
);
1724 nir_store_deref(b
, level1
, nir_load_var(b
, in
[i
]), 1);
1728 nir_validate_shader(b
->shader
, NULL
);
1729 ASSERT_EQ(count_derefs(nir_deref_type_array
), 20);
1730 ASSERT_EQ(count_function_temp_vars(), 1);
1732 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1733 EXPECT_TRUE(progress
);
1735 nir_validate_shader(b
->shader
, NULL
);
1736 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1737 ASSERT_EQ(count_function_temp_vars(), 16);
1740 TEST_F(nir_split_vars_test
, simple_dont_split
)
1742 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1743 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1745 nir_variable
*ind
= create_int(nir_var_shader_in
, "ind");
1747 nir_deref_instr
*ind_deref
= nir_build_deref_var(b
, ind
);
1748 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1750 for (int i
= 0; i
< 4; i
++)
1751 nir_store_deref(b
, nir_build_deref_array(b
, temp_deref
, &ind_deref
->dest
.ssa
), nir_load_var(b
, in
[i
]), 1);
1753 nir_validate_shader(b
->shader
, NULL
);
1754 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
1755 ASSERT_EQ(count_function_temp_vars(), 1);
1757 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1758 EXPECT_FALSE(progress
);
1760 nir_validate_shader(b
->shader
, NULL
);
1761 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
1762 ASSERT_EQ(count_function_temp_vars(), 1);
1765 TEST_F(nir_split_vars_test
, twolevel_dont_split_lvl_0
)
1767 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1768 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_array_type(glsl_int_type(), 6, 0), 4, 0),
1770 nir_variable
*ind
= create_int(nir_var_shader_in
, "ind");
1772 nir_deref_instr
*ind_deref
= nir_build_deref_var(b
, ind
);
1773 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1775 for (int i
= 0; i
< 4; i
++) {
1776 nir_deref_instr
*level0
= nir_build_deref_array(b
, temp_deref
, &ind_deref
->dest
.ssa
);
1777 for (int j
= 0; j
< 6; j
++) {
1778 nir_deref_instr
*level1
= nir_build_deref_array_imm(b
, level0
, j
);
1779 nir_store_deref(b
, level1
, nir_load_var(b
, in
[i
]), 1);
1783 nir_validate_shader(b
->shader
, NULL
);
1784 ASSERT_EQ(count_derefs(nir_deref_type_array
), 28);
1785 ASSERT_EQ(count_function_temp_vars(), 1);
1787 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1788 EXPECT_TRUE(progress
);
1790 nir_validate_shader(b
->shader
, NULL
);
1791 ASSERT_EQ(count_derefs(nir_deref_type_array
), 24);
1792 ASSERT_EQ(count_function_temp_vars(), 6);
1795 TEST_F(nir_split_vars_test
, twolevel_dont_split_lvl_1
)
1797 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 6);
1798 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_array_type(glsl_int_type(), 6, 0), 4, 0),
1800 nir_variable
*ind
= create_int(nir_var_shader_in
, "ind");
1802 nir_deref_instr
*ind_deref
= nir_build_deref_var(b
, ind
);
1803 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1805 for (int i
= 0; i
< 4; i
++) {
1806 nir_deref_instr
*level0
= nir_build_deref_array_imm(b
, temp_deref
, i
);
1807 for (int j
= 0; j
< 6; j
++) {
1808 /* just add the inner index to get some different derefs */
1809 nir_deref_instr
*level1
= nir_build_deref_array(b
, level0
, nir_iadd(b
, &ind_deref
->dest
.ssa
, nir_imm_int(b
, j
)));
1810 nir_store_deref(b
, level1
, nir_load_var(b
, in
[i
]), 1);
1814 nir_validate_shader(b
->shader
, NULL
);
1815 ASSERT_EQ(count_derefs(nir_deref_type_array
), 28);
1816 ASSERT_EQ(count_function_temp_vars(), 1);
1818 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1819 EXPECT_TRUE(progress
);
1821 nir_validate_shader(b
->shader
, NULL
);
1822 ASSERT_EQ(count_derefs(nir_deref_type_array
), 24);
1823 ASSERT_EQ(count_function_temp_vars(), 4);
1826 TEST_F(nir_split_vars_test
, split_multiple_store
)
1828 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1829 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1831 nir_variable
*temp2
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1834 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1835 nir_deref_instr
*temp2_deref
= nir_build_deref_var(b
, temp2
);
1837 for (int i
= 0; i
< 4; i
++)
1838 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1840 for (int i
= 0; i
< 4; i
++)
1841 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp2_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1843 nir_validate_shader(b
->shader
, NULL
);
1844 ASSERT_EQ(count_derefs(nir_deref_type_array
), 8);
1845 ASSERT_EQ(count_function_temp_vars(), 2);
1847 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1848 EXPECT_TRUE(progress
);
1850 nir_validate_shader(b
->shader
, NULL
);
1851 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1852 ASSERT_EQ(count_function_temp_vars(), 8);
1855 TEST_F(nir_split_vars_test
, split_load_store
)
1857 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1858 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1860 nir_variable
*temp2
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1863 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1864 nir_deref_instr
*temp2_deref
= nir_build_deref_var(b
, temp2
);
1866 for (int i
= 0; i
< 4; i
++)
1867 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1869 for (int i
= 0; i
< 4; i
++) {
1870 nir_deref_instr
*store_deref
= nir_build_deref_array_imm(b
, temp2_deref
, i
);
1871 nir_deref_instr
*load_deref
= nir_build_deref_array_imm(b
, temp_deref
, i
);
1872 nir_store_deref(b
, store_deref
, nir_load_deref(b
, load_deref
), 1);
1875 nir_validate_shader(b
->shader
, NULL
);
1876 ASSERT_EQ(count_derefs(nir_deref_type_array
), 12);
1877 ASSERT_EQ(count_function_temp_vars(), 2);
1879 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1880 EXPECT_TRUE(progress
);
1882 nir_validate_shader(b
->shader
, NULL
);
1883 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1884 ASSERT_EQ(count_function_temp_vars(), 8);
1887 TEST_F(nir_split_vars_test
, split_copy
)
1889 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1890 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1892 nir_variable
*temp2
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1895 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1896 nir_deref_instr
*temp2_deref
= nir_build_deref_var(b
, temp2
);
1898 for (int i
= 0; i
< 4; i
++)
1899 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1901 for (int i
= 0; i
< 4; i
++) {
1902 nir_deref_instr
*store_deref
= nir_build_deref_array_imm(b
, temp2_deref
, i
);
1903 nir_deref_instr
*load_deref
= nir_build_deref_array_imm(b
, temp_deref
, i
);
1904 nir_copy_deref(b
, store_deref
, load_deref
);
1907 nir_validate_shader(b
->shader
, NULL
);
1908 ASSERT_EQ(count_derefs(nir_deref_type_array
), 12);
1909 ASSERT_EQ(count_function_temp_vars(), 2);
1911 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1912 EXPECT_TRUE(progress
);
1914 nir_validate_shader(b
->shader
, NULL
);
1915 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1916 ASSERT_EQ(count_function_temp_vars(), 8);
1919 TEST_F(nir_split_vars_test
, split_wildcard_copy
)
1921 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1922 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1924 nir_variable
*temp2
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1927 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1928 nir_deref_instr
*temp2_deref
= nir_build_deref_var(b
, temp2
);
1930 for (int i
= 0; i
< 4; i
++)
1931 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1933 nir_deref_instr
*src_wildcard
= nir_build_deref_array_wildcard(b
, temp_deref
);
1934 nir_deref_instr
*dst_wildcard
= nir_build_deref_array_wildcard(b
, temp2_deref
);
1936 nir_copy_deref(b
, dst_wildcard
, src_wildcard
);
1938 nir_validate_shader(b
->shader
, NULL
);
1939 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
1940 ASSERT_EQ(count_derefs(nir_deref_type_array_wildcard
), 2);
1941 ASSERT_EQ(count_function_temp_vars(), 2);
1942 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref
), 1);
1944 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1945 EXPECT_TRUE(progress
);
1947 nir_validate_shader(b
->shader
, NULL
);
1948 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1949 ASSERT_EQ(count_derefs(nir_deref_type_array_wildcard
), 0);
1950 ASSERT_EQ(count_function_temp_vars(), 8);
1951 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref
), 4);