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
{};
201 nir_load_var_volatile(nir_builder
*b
, nir_variable
*var
)
203 return nir_load_deref_with_access(b
, nir_build_deref_var(b
, var
),
208 nir_store_var_volatile(nir_builder
*b
, nir_variable
*var
,
209 nir_ssa_def
*value
, nir_component_mask_t writemask
)
211 nir_store_deref_with_access(b
, nir_build_deref_var(b
, var
),
212 value
, writemask
, ACCESS_VOLATILE
);
215 TEST_F(nir_redundant_load_vars_test
, duplicated_load
)
217 /* Load a variable twice in the same block. One should be removed. */
219 nir_variable
*in
= create_int(nir_var_shader_in
, "in");
220 nir_variable
**out
= create_many_int(nir_var_shader_out
, "out", 2);
222 nir_store_var(b
, out
[0], nir_load_var(b
, in
), 1);
223 nir_store_var(b
, out
[1], nir_load_var(b
, in
), 1);
225 nir_validate_shader(b
->shader
, NULL
);
227 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
229 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
230 EXPECT_TRUE(progress
);
232 nir_validate_shader(b
->shader
, NULL
);
234 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
237 TEST_F(nir_redundant_load_vars_test
, duplicated_load_volatile
)
239 /* Load a variable twice in the same block. One should be removed. */
241 nir_variable
*in
= create_int(nir_var_shader_in
, "in");
242 nir_variable
**out
= create_many_int(nir_var_shader_out
, "out", 3);
244 /* Volatile prevents us from eliminating a load by combining it with
245 * another. It shouldn't however, prevent us from combing other
246 * non-volatile loads.
248 nir_store_var(b
, out
[0], nir_load_var(b
, in
), 1);
249 nir_store_var(b
, out
[1], nir_load_var_volatile(b
, in
), 1);
250 nir_store_var(b
, out
[2], nir_load_var(b
, in
), 1);
252 nir_validate_shader(b
->shader
, NULL
);
254 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 3);
256 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
257 EXPECT_TRUE(progress
);
259 nir_validate_shader(b
->shader
, NULL
);
261 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
263 nir_intrinsic_instr
*first_store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
264 ASSERT_TRUE(first_store
->src
[1].is_ssa
);
266 nir_intrinsic_instr
*third_store
= get_intrinsic(nir_intrinsic_store_deref
, 2);
267 ASSERT_TRUE(third_store
->src
[1].is_ssa
);
269 EXPECT_EQ(first_store
->src
[1].ssa
, third_store
->src
[1].ssa
);
272 TEST_F(nir_redundant_load_vars_test
, duplicated_load_in_two_blocks
)
274 /* Load a variable twice in different blocks. One should be removed. */
276 nir_variable
*in
= create_int(nir_var_shader_in
, "in");
277 nir_variable
**out
= create_many_int(nir_var_shader_out
, "out", 2);
279 nir_store_var(b
, out
[0], nir_load_var(b
, in
), 1);
281 /* Forces the stores to be in different blocks. */
282 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
284 nir_store_var(b
, out
[1], nir_load_var(b
, in
), 1);
286 nir_validate_shader(b
->shader
, NULL
);
288 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
290 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
291 EXPECT_TRUE(progress
);
293 nir_validate_shader(b
->shader
, NULL
);
295 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
298 TEST_F(nir_redundant_load_vars_test
, invalidate_inside_if_block
)
300 /* Load variables, then write to some of then in different branches of the
301 * if statement. They should be invalidated accordingly.
304 nir_variable
**g
= create_many_int(nir_var_shader_temp
, "g", 3);
305 nir_variable
**out
= create_many_int(nir_var_shader_out
, "out", 3);
307 nir_load_var(b
, g
[0]);
308 nir_load_var(b
, g
[1]);
309 nir_load_var(b
, g
[2]);
311 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
312 nir_store_var(b
, g
[0], nir_imm_int(b
, 10), 1);
314 nir_push_else(b
, if_stmt
);
315 nir_store_var(b
, g
[1], nir_imm_int(b
, 20), 1);
317 nir_pop_if(b
, if_stmt
);
319 nir_store_var(b
, out
[0], nir_load_var(b
, g
[0]), 1);
320 nir_store_var(b
, out
[1], nir_load_var(b
, g
[1]), 1);
321 nir_store_var(b
, out
[2], nir_load_var(b
, g
[2]), 1);
323 nir_validate_shader(b
->shader
, NULL
);
325 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
326 EXPECT_TRUE(progress
);
328 /* There are 3 initial loads, plus 2 loads for the values invalidated
329 * inside the if statement.
331 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 5);
333 /* We only load g[2] once. */
334 unsigned g2_load_count
= 0;
335 for (int i
= 0; i
< 5; i
++) {
336 nir_intrinsic_instr
*load
= get_intrinsic(nir_intrinsic_load_deref
, i
);
337 if (nir_intrinsic_get_var(load
, 0) == g
[2])
340 EXPECT_EQ(g2_load_count
, 1);
343 TEST_F(nir_redundant_load_vars_test
, invalidate_live_load_in_the_end_of_loop
)
345 /* Invalidating a load in the end of loop body will apply to the whole loop
349 nir_variable
*v
= create_int(nir_var_mem_ssbo
, "v");
353 nir_loop
*loop
= nir_push_loop(b
);
355 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
356 nir_jump(b
, nir_jump_break
);
357 nir_pop_if(b
, if_stmt
);
360 nir_store_var(b
, v
, nir_imm_int(b
, 10), 1);
362 nir_pop_loop(b
, loop
);
364 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
365 ASSERT_FALSE(progress
);
368 TEST_F(nir_copy_prop_vars_test
, simple_copies
)
370 nir_variable
*in
= create_int(nir_var_shader_in
, "in");
371 nir_variable
*temp
= create_int(nir_var_function_temp
, "temp");
372 nir_variable
*out
= create_int(nir_var_shader_out
, "out");
374 nir_copy_var(b
, temp
, in
);
375 nir_copy_var(b
, out
, temp
);
377 nir_validate_shader(b
->shader
, NULL
);
379 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
380 EXPECT_TRUE(progress
);
382 nir_validate_shader(b
->shader
, NULL
);
384 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref
), 2);
386 nir_intrinsic_instr
*first_copy
= get_intrinsic(nir_intrinsic_copy_deref
, 0);
387 ASSERT_TRUE(first_copy
->src
[1].is_ssa
);
389 nir_intrinsic_instr
*second_copy
= get_intrinsic(nir_intrinsic_copy_deref
, 1);
390 ASSERT_TRUE(second_copy
->src
[1].is_ssa
);
392 EXPECT_EQ(first_copy
->src
[1].ssa
, second_copy
->src
[1].ssa
);
395 TEST_F(nir_copy_prop_vars_test
, self_copy
)
397 nir_variable
*v
= create_int(nir_var_mem_ssbo
, "v");
399 nir_copy_var(b
, v
, v
);
401 nir_validate_shader(b
->shader
, NULL
);
403 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
404 EXPECT_TRUE(progress
);
406 nir_validate_shader(b
->shader
, NULL
);
408 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref
), 0);
411 TEST_F(nir_copy_prop_vars_test
, simple_store_load
)
413 nir_variable
**v
= create_many_ivec2(nir_var_function_temp
, "v", 2);
414 unsigned mask
= 1 | 2;
416 nir_ssa_def
*stored_value
= nir_imm_ivec2(b
, 10, 20);
417 nir_store_var(b
, v
[0], stored_value
, mask
);
419 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
420 nir_store_var(b
, v
[1], read_value
, mask
);
422 nir_validate_shader(b
->shader
, NULL
);
424 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
425 EXPECT_TRUE(progress
);
427 nir_validate_shader(b
->shader
, NULL
);
429 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
431 for (int i
= 0; i
< 2; i
++) {
432 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, i
);
433 ASSERT_TRUE(store
->src
[1].is_ssa
);
434 EXPECT_EQ(store
->src
[1].ssa
, stored_value
);
438 TEST_F(nir_copy_prop_vars_test
, store_store_load
)
440 nir_variable
**v
= create_many_ivec2(nir_var_function_temp
, "v", 2);
441 unsigned mask
= 1 | 2;
443 nir_ssa_def
*first_value
= nir_imm_ivec2(b
, 10, 20);
444 nir_store_var(b
, v
[0], first_value
, mask
);
446 nir_ssa_def
*second_value
= nir_imm_ivec2(b
, 30, 40);
447 nir_store_var(b
, v
[0], second_value
, mask
);
449 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
450 nir_store_var(b
, v
[1], read_value
, mask
);
452 nir_validate_shader(b
->shader
, NULL
);
454 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
455 EXPECT_TRUE(progress
);
457 nir_validate_shader(b
->shader
, NULL
);
459 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
461 /* Store to v[1] should use second_value directly. */
462 nir_intrinsic_instr
*store_to_v1
= get_intrinsic(nir_intrinsic_store_deref
, 2);
463 ASSERT_EQ(nir_intrinsic_get_var(store_to_v1
, 0), v
[1]);
464 ASSERT_TRUE(store_to_v1
->src
[1].is_ssa
);
465 EXPECT_EQ(store_to_v1
->src
[1].ssa
, second_value
);
468 TEST_F(nir_copy_prop_vars_test
, store_store_load_different_components
)
470 nir_variable
**v
= create_many_ivec2(nir_var_function_temp
, "v", 2);
472 nir_ssa_def
*first_value
= nir_imm_ivec2(b
, 10, 20);
473 nir_store_var(b
, v
[0], first_value
, 1 << 1);
475 nir_ssa_def
*second_value
= nir_imm_ivec2(b
, 30, 40);
476 nir_store_var(b
, v
[0], second_value
, 1 << 0);
478 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
479 nir_store_var(b
, v
[1], read_value
, 1 << 1);
481 nir_validate_shader(b
->shader
, NULL
);
483 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
484 EXPECT_TRUE(progress
);
486 nir_validate_shader(b
->shader
, NULL
);
488 nir_opt_constant_folding(b
->shader
);
489 nir_validate_shader(b
->shader
, NULL
);
491 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
493 /* Store to v[1] should use first_value directly. The write of
494 * second_value did not overwrite the component it uses.
496 nir_intrinsic_instr
*store_to_v1
= get_intrinsic(nir_intrinsic_store_deref
, 2);
497 ASSERT_EQ(nir_intrinsic_get_var(store_to_v1
, 0), v
[1]);
498 ASSERT_EQ(nir_src_comp_as_uint(store_to_v1
->src
[1], 1), 20);
501 TEST_F(nir_copy_prop_vars_test
, store_store_load_different_components_in_many_blocks
)
503 nir_variable
**v
= create_many_ivec2(nir_var_function_temp
, "v", 2);
505 nir_ssa_def
*first_value
= nir_imm_ivec2(b
, 10, 20);
506 nir_store_var(b
, v
[0], first_value
, 1 << 1);
508 /* Adding an if statement will cause blocks to be created. */
509 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
511 nir_ssa_def
*second_value
= nir_imm_ivec2(b
, 30, 40);
512 nir_store_var(b
, v
[0], second_value
, 1 << 0);
514 /* Adding an if statement will cause blocks to be created. */
515 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
517 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
518 nir_store_var(b
, v
[1], read_value
, 1 << 1);
520 nir_validate_shader(b
->shader
, NULL
);
522 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
523 EXPECT_TRUE(progress
);
525 nir_validate_shader(b
->shader
, NULL
);
527 nir_opt_constant_folding(b
->shader
);
528 nir_validate_shader(b
->shader
, NULL
);
530 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
532 /* Store to v[1] should use first_value directly. The write of
533 * second_value did not overwrite the component it uses.
535 nir_intrinsic_instr
*store_to_v1
= get_intrinsic(nir_intrinsic_store_deref
, 2);
536 ASSERT_EQ(nir_intrinsic_get_var(store_to_v1
, 0), v
[1]);
537 ASSERT_EQ(nir_src_comp_as_uint(store_to_v1
->src
[1], 1), 20);
540 TEST_F(nir_copy_prop_vars_test
, store_volatile
)
542 nir_variable
**v
= create_many_ivec2(nir_var_function_temp
, "v", 2);
543 unsigned mask
= 1 | 2;
545 nir_ssa_def
*first_value
= nir_imm_ivec2(b
, 10, 20);
546 nir_store_var(b
, v
[0], first_value
, mask
);
548 nir_ssa_def
*second_value
= nir_imm_ivec2(b
, 30, 40);
549 nir_store_var_volatile(b
, v
[0], second_value
, mask
);
551 nir_ssa_def
*third_value
= nir_imm_ivec2(b
, 50, 60);
552 nir_store_var(b
, v
[0], third_value
, mask
);
554 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
555 nir_store_var(b
, v
[1], read_value
, mask
);
557 nir_validate_shader(b
->shader
, NULL
);
559 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
560 EXPECT_TRUE(progress
);
562 nir_validate_shader(b
->shader
, NULL
);
564 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 4);
566 /* Our approach here is a bit scorched-earth. We expect the volatile store
567 * in the middle to cause both that store and the one before it to be kept.
568 * Technically, volatile only prevents combining the volatile store with
569 * another store and one could argue that the store before the volatile and
570 * the one after it could be combined. However, it seems safer to just
571 * treat a volatile store like an atomic and prevent any combining across
574 nir_intrinsic_instr
*store_to_v1
= get_intrinsic(nir_intrinsic_store_deref
, 3);
575 ASSERT_EQ(nir_intrinsic_get_var(store_to_v1
, 0), v
[1]);
576 ASSERT_TRUE(store_to_v1
->src
[1].is_ssa
);
577 EXPECT_EQ(store_to_v1
->src
[1].ssa
, third_value
);
580 TEST_F(nir_copy_prop_vars_test
, self_copy_volatile
)
582 nir_variable
*v
= create_int(nir_var_mem_ssbo
, "v");
584 nir_copy_var(b
, v
, v
);
585 nir_copy_deref_with_access(b
, nir_build_deref_var(b
, v
),
586 nir_build_deref_var(b
, v
),
587 (gl_access_qualifier
)0, ACCESS_VOLATILE
);
588 nir_copy_deref_with_access(b
, nir_build_deref_var(b
, v
),
589 nir_build_deref_var(b
, v
),
590 ACCESS_VOLATILE
, (gl_access_qualifier
)0);
591 nir_copy_var(b
, v
, v
);
593 nir_validate_shader(b
->shader
, NULL
);
595 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
596 EXPECT_TRUE(progress
);
598 nir_validate_shader(b
->shader
, NULL
);
600 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref
), 2);
602 /* Store to v[1] should use second_value directly. */
603 nir_intrinsic_instr
*first
= get_intrinsic(nir_intrinsic_copy_deref
, 0);
604 nir_intrinsic_instr
*second
= get_intrinsic(nir_intrinsic_copy_deref
, 1);
605 ASSERT_EQ(nir_intrinsic_src_access(first
), ACCESS_VOLATILE
);
606 ASSERT_EQ(nir_intrinsic_dst_access(first
), (gl_access_qualifier
)0);
607 ASSERT_EQ(nir_intrinsic_src_access(second
), (gl_access_qualifier
)0);
608 ASSERT_EQ(nir_intrinsic_dst_access(second
), ACCESS_VOLATILE
);
611 TEST_F(nir_copy_prop_vars_test
, memory_barrier_in_two_blocks
)
613 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 4);
615 nir_store_var(b
, v
[0], nir_imm_int(b
, 1), 1);
616 nir_store_var(b
, v
[1], nir_imm_int(b
, 2), 1);
618 /* Split into many blocks. */
619 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
621 nir_store_var(b
, v
[2], nir_load_var(b
, v
[0]), 1);
623 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQ_REL
,
626 nir_store_var(b
, v
[3], nir_load_var(b
, v
[1]), 1);
628 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
629 ASSERT_TRUE(progress
);
631 /* Only the second load will remain after the optimization. */
632 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_load_deref
));
633 nir_intrinsic_instr
*load
= get_intrinsic(nir_intrinsic_load_deref
, 0);
634 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), v
[1]);
637 TEST_F(nir_redundant_load_vars_test
, acquire_barrier_prevents_load_removal
)
639 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 1);
641 nir_load_var(b
, x
[0]);
643 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
646 nir_load_var(b
, x
[0]);
648 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
649 ASSERT_FALSE(progress
);
651 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref
));
654 TEST_F(nir_redundant_load_vars_test
, acquire_barrier_prevents_same_mode_load_removal
)
656 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
658 nir_load_var(b
, x
[0]);
659 nir_load_var(b
, x
[1]);
661 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
664 nir_load_var(b
, x
[0]);
665 nir_load_var(b
, x
[1]);
667 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
668 ASSERT_FALSE(progress
);
670 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_load_deref
));
673 TEST_F(nir_redundant_load_vars_test
, acquire_barrier_allows_different_mode_load_removal
)
675 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
676 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 2);
678 nir_load_var(b
, x
[0]);
679 nir_load_var(b
, x
[1]);
680 nir_load_var(b
, y
[0]);
681 nir_load_var(b
, y
[1]);
683 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
686 nir_load_var(b
, x
[0]);
687 nir_load_var(b
, x
[1]);
688 nir_load_var(b
, y
[0]);
689 nir_load_var(b
, y
[1]);
691 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
692 ASSERT_TRUE(progress
);
694 ASSERT_EQ(6, count_intrinsics(nir_intrinsic_load_deref
));
696 nir_intrinsic_instr
*load
;
698 load
= get_intrinsic(nir_intrinsic_load_deref
, 0);
699 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[0]);
700 load
= get_intrinsic(nir_intrinsic_load_deref
, 1);
701 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[1]);
703 load
= get_intrinsic(nir_intrinsic_load_deref
, 2);
704 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), y
[0]);
705 load
= get_intrinsic(nir_intrinsic_load_deref
, 3);
706 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), y
[1]);
708 load
= get_intrinsic(nir_intrinsic_load_deref
, 4);
709 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[0]);
710 load
= get_intrinsic(nir_intrinsic_load_deref
, 5);
711 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[1]);
714 TEST_F(nir_redundant_load_vars_test
, release_barrier_allows_load_removal
)
716 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 1);
718 nir_load_var(b
, x
[0]);
720 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
723 nir_load_var(b
, x
[0]);
725 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
726 ASSERT_TRUE(progress
);
728 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_load_deref
));
731 TEST_F(nir_redundant_load_vars_test
, release_barrier_allows_same_mode_load_removal
)
733 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
735 nir_load_var(b
, x
[0]);
736 nir_load_var(b
, x
[1]);
738 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
741 nir_load_var(b
, x
[0]);
742 nir_load_var(b
, x
[1]);
744 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
745 ASSERT_TRUE(progress
);
747 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref
));
750 TEST_F(nir_redundant_load_vars_test
, release_barrier_allows_different_mode_load_removal
)
752 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
753 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 2);
755 nir_load_var(b
, x
[0]);
756 nir_load_var(b
, x
[1]);
757 nir_load_var(b
, y
[0]);
758 nir_load_var(b
, y
[1]);
760 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
763 nir_load_var(b
, x
[0]);
764 nir_load_var(b
, x
[1]);
765 nir_load_var(b
, y
[0]);
766 nir_load_var(b
, y
[1]);
768 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
769 ASSERT_TRUE(progress
);
771 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_load_deref
));
773 nir_intrinsic_instr
*load
;
775 load
= get_intrinsic(nir_intrinsic_load_deref
, 0);
776 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[0]);
777 load
= get_intrinsic(nir_intrinsic_load_deref
, 1);
778 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[1]);
780 load
= get_intrinsic(nir_intrinsic_load_deref
, 2);
781 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), y
[0]);
782 load
= get_intrinsic(nir_intrinsic_load_deref
, 3);
783 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), y
[1]);
786 TEST_F(nir_copy_prop_vars_test
, acquire_barrier_prevents_propagation
)
788 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 1);
790 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
792 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
795 nir_load_var(b
, x
[0]);
797 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
798 ASSERT_FALSE(progress
);
800 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
801 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_load_deref
));
804 TEST_F(nir_copy_prop_vars_test
, acquire_barrier_prevents_same_mode_propagation
)
806 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
808 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
809 nir_store_var(b
, x
[1], nir_imm_int(b
, 20), 1);
811 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
814 nir_load_var(b
, x
[0]);
815 nir_load_var(b
, x
[1]);
817 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
818 ASSERT_FALSE(progress
);
820 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_store_deref
));
821 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref
));
824 TEST_F(nir_copy_prop_vars_test
, acquire_barrier_allows_different_mode_propagation
)
826 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
827 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 2);
829 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
830 nir_store_var(b
, x
[1], nir_imm_int(b
, 20), 1);
831 nir_store_var(b
, y
[0], nir_imm_int(b
, 30), 1);
832 nir_store_var(b
, y
[1], nir_imm_int(b
, 40), 1);
834 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
837 nir_load_var(b
, x
[0]);
838 nir_load_var(b
, x
[1]);
839 nir_load_var(b
, y
[0]);
840 nir_load_var(b
, y
[1]);
842 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
843 ASSERT_TRUE(progress
);
845 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_store_deref
));
846 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_load_deref
));
848 nir_intrinsic_instr
*store
;
850 store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
851 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), x
[0]);
852 store
= get_intrinsic(nir_intrinsic_store_deref
, 1);
853 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), x
[1]);
855 store
= get_intrinsic(nir_intrinsic_store_deref
, 2);
856 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), y
[0]);
857 store
= get_intrinsic(nir_intrinsic_store_deref
, 3);
858 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), y
[1]);
860 nir_intrinsic_instr
*load
;
862 load
= get_intrinsic(nir_intrinsic_load_deref
, 0);
863 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[0]);
864 load
= get_intrinsic(nir_intrinsic_load_deref
, 1);
865 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), x
[1]);
868 TEST_F(nir_copy_prop_vars_test
, release_barrier_allows_propagation
)
870 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 1);
872 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
874 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
877 nir_load_var(b
, x
[0]);
879 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
880 ASSERT_TRUE(progress
);
882 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
885 TEST_F(nir_copy_prop_vars_test
, release_barrier_allows_same_mode_propagation
)
887 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
889 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
890 nir_store_var(b
, x
[1], nir_imm_int(b
, 20), 1);
892 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
895 nir_load_var(b
, x
[0]);
896 nir_load_var(b
, x
[1]);
898 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
899 ASSERT_TRUE(progress
);
901 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_store_deref
));
902 ASSERT_EQ(0, count_intrinsics(nir_intrinsic_load_deref
));
905 TEST_F(nir_copy_prop_vars_test
, release_barrier_allows_different_mode_propagation
)
907 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
908 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 2);
910 nir_store_var(b
, x
[0], nir_imm_int(b
, 10), 1);
911 nir_store_var(b
, x
[1], nir_imm_int(b
, 20), 1);
912 nir_store_var(b
, y
[0], nir_imm_int(b
, 30), 1);
913 nir_store_var(b
, y
[1], nir_imm_int(b
, 40), 1);
915 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
918 nir_load_var(b
, x
[0]);
919 nir_load_var(b
, x
[1]);
920 nir_load_var(b
, y
[0]);
921 nir_load_var(b
, y
[1]);
923 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
924 ASSERT_TRUE(progress
);
926 ASSERT_EQ(4, count_intrinsics(nir_intrinsic_store_deref
));
927 ASSERT_EQ(0, count_intrinsics(nir_intrinsic_load_deref
));
929 nir_intrinsic_instr
*store
;
931 store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
932 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), x
[0]);
933 store
= get_intrinsic(nir_intrinsic_store_deref
, 1);
934 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), x
[1]);
936 store
= get_intrinsic(nir_intrinsic_store_deref
, 2);
937 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), y
[0]);
938 store
= get_intrinsic(nir_intrinsic_store_deref
, 3);
939 ASSERT_EQ(nir_intrinsic_get_var(store
, 0), y
[1]);
942 TEST_F(nir_copy_prop_vars_test
, acquire_barrier_prevents_propagation_from_copy
)
944 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 3);
946 nir_copy_var(b
, x
[1], x
[0]);
948 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
951 nir_copy_var(b
, x
[2], x
[1]);
953 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
954 ASSERT_FALSE(progress
);
956 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref
));
958 nir_intrinsic_instr
*copy
;
960 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 0);
961 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
963 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 1);
964 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[1]);
967 TEST_F(nir_copy_prop_vars_test
, acquire_barrier_prevents_propagation_from_copy_to_different_mode
)
969 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
970 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 1);
972 nir_copy_var(b
, y
[0], x
[0]);
974 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQUIRE
,
977 nir_copy_var(b
, x
[1], y
[0]);
979 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
980 ASSERT_FALSE(progress
);
982 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref
));
984 nir_intrinsic_instr
*copy
;
986 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 0);
987 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
989 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 1);
990 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), y
[0]);
993 TEST_F(nir_copy_prop_vars_test
, release_barrier_allows_propagation_from_copy
)
995 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 3);
997 nir_copy_var(b
, x
[1], x
[0]);
999 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
1002 nir_copy_var(b
, x
[2], x
[1]);
1004 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1005 ASSERT_TRUE(progress
);
1007 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref
));
1009 nir_intrinsic_instr
*copy
;
1011 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 0);
1012 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
1014 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 1);
1015 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
1018 TEST_F(nir_copy_prop_vars_test
, release_barrier_allows_propagation_from_copy_to_different_mode
)
1020 nir_variable
**x
= create_many_int(nir_var_mem_ssbo
, "x", 2);
1021 nir_variable
**y
= create_many_int(nir_var_mem_shared
, "y", 1);
1023 nir_copy_var(b
, y
[0], x
[0]);
1025 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_RELEASE
,
1028 nir_copy_var(b
, x
[1], y
[0]);
1030 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1031 ASSERT_TRUE(progress
);
1033 ASSERT_EQ(2, count_intrinsics(nir_intrinsic_copy_deref
));
1035 nir_intrinsic_instr
*copy
;
1037 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 0);
1038 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
1040 copy
= get_intrinsic(nir_intrinsic_copy_deref
, 1);
1041 ASSERT_EQ(nir_intrinsic_get_var(copy
, 1), x
[0]);
1044 TEST_F(nir_copy_prop_vars_test
, simple_store_load_in_two_blocks
)
1046 nir_variable
**v
= create_many_ivec2(nir_var_function_temp
, "v", 2);
1047 unsigned mask
= 1 | 2;
1049 nir_ssa_def
*stored_value
= nir_imm_ivec2(b
, 10, 20);
1050 nir_store_var(b
, v
[0], stored_value
, mask
);
1052 /* Adding an if statement will cause blocks to be created. */
1053 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
1055 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
1056 nir_store_var(b
, v
[1], read_value
, mask
);
1058 nir_validate_shader(b
->shader
, NULL
);
1060 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1061 EXPECT_TRUE(progress
);
1063 nir_validate_shader(b
->shader
, NULL
);
1065 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1067 for (int i
= 0; i
< 2; i
++) {
1068 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, i
);
1069 ASSERT_TRUE(store
->src
[1].is_ssa
);
1070 EXPECT_EQ(store
->src
[1].ssa
, stored_value
);
1074 TEST_F(nir_copy_prop_vars_test
, load_direct_array_deref_on_vector_reuses_previous_load
)
1076 nir_variable
*in0
= create_ivec2(nir_var_mem_ssbo
, "in0");
1077 nir_variable
*in1
= create_ivec2(nir_var_mem_ssbo
, "in1");
1078 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
1079 nir_variable
*out
= create_int(nir_var_mem_ssbo
, "out");
1081 nir_store_var(b
, vec
, nir_load_var(b
, in0
), 1 << 0);
1082 nir_store_var(b
, vec
, nir_load_var(b
, in1
), 1 << 1);
1084 /* This load will be dropped, as vec.y (or vec[1]) is already known. */
1085 nir_deref_instr
*deref
=
1086 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 1);
1087 nir_ssa_def
*loaded_from_deref
= nir_load_deref(b
, deref
);
1089 /* This store should use the value loaded from in1. */
1090 nir_store_var(b
, out
, loaded_from_deref
, 1 << 0);
1092 nir_validate_shader(b
->shader
, NULL
);
1093 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 3);
1094 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
1096 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1097 EXPECT_TRUE(progress
);
1099 nir_validate_shader(b
->shader
, NULL
);
1100 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
1101 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
1103 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 2);
1104 ASSERT_TRUE(store
->src
[1].is_ssa
);
1106 /* NOTE: The ALU instruction is how we get the vec.y. */
1107 ASSERT_TRUE(nir_src_as_alu_instr(store
->src
[1]));
1110 TEST_F(nir_copy_prop_vars_test
, load_direct_array_deref_on_vector_reuses_previous_copy
)
1112 nir_variable
*in0
= create_ivec2(nir_var_mem_ssbo
, "in0");
1113 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
1115 nir_copy_var(b
, vec
, in0
);
1117 /* This load will be replaced with one from in0. */
1118 nir_deref_instr
*deref
=
1119 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 1);
1120 nir_load_deref(b
, deref
);
1122 nir_validate_shader(b
->shader
, NULL
);
1124 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1125 EXPECT_TRUE(progress
);
1127 nir_validate_shader(b
->shader
, NULL
);
1128 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
1130 nir_intrinsic_instr
*load
= get_intrinsic(nir_intrinsic_load_deref
, 0);
1131 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), in0
);
1134 TEST_F(nir_copy_prop_vars_test
, load_direct_array_deref_on_vector_gets_reused
)
1136 nir_variable
*in0
= create_ivec2(nir_var_mem_ssbo
, "in0");
1137 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
1138 nir_variable
*out
= create_ivec2(nir_var_mem_ssbo
, "out");
1140 /* Loading "vec[1]" deref will save the information about vec.y. */
1141 nir_deref_instr
*deref
=
1142 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 1);
1143 nir_load_deref(b
, deref
);
1145 /* Store to vec.x. */
1146 nir_store_var(b
, vec
, nir_load_var(b
, in0
), 1 << 0);
1148 /* This load will be dropped, since both vec.x and vec.y are known. */
1149 nir_ssa_def
*loaded_from_vec
= nir_load_var(b
, vec
);
1150 nir_store_var(b
, out
, loaded_from_vec
, 0x3);
1152 nir_validate_shader(b
->shader
, NULL
);
1153 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 3);
1154 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1156 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1157 EXPECT_TRUE(progress
);
1159 nir_validate_shader(b
->shader
, NULL
);
1160 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
1161 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1163 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1164 ASSERT_TRUE(store
->src
[1].is_ssa
);
1165 ASSERT_TRUE(nir_src_as_alu_instr(store
->src
[1]));
1168 TEST_F(nir_copy_prop_vars_test
, store_load_direct_array_deref_on_vector
)
1170 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
1171 nir_variable
*out0
= create_int(nir_var_mem_ssbo
, "out0");
1172 nir_variable
*out1
= create_ivec2(nir_var_mem_ssbo
, "out1");
1174 /* Store to "vec[1]" and "vec[0]". */
1175 nir_deref_instr
*store_deref_y
=
1176 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 1);
1177 nir_store_deref(b
, store_deref_y
, nir_imm_int(b
, 20), 1);
1179 nir_deref_instr
*store_deref_x
=
1180 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 0);
1181 nir_store_deref(b
, store_deref_x
, nir_imm_int(b
, 10), 1);
1183 /* Both loads below will be dropped, because the values are already known. */
1184 nir_deref_instr
*load_deref_y
=
1185 nir_build_deref_array_imm(b
, nir_build_deref_var(b
, vec
), 1);
1186 nir_store_var(b
, out0
, nir_load_deref(b
, load_deref_y
), 1);
1188 nir_store_var(b
, out1
, nir_load_var(b
, vec
), 1);
1190 nir_validate_shader(b
->shader
, NULL
);
1191 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
1192 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 4);
1194 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1195 EXPECT_TRUE(progress
);
1197 nir_validate_shader(b
->shader
, NULL
);
1198 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 0);
1199 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 4);
1201 /* Third store will just use the value from first store. */
1202 nir_intrinsic_instr
*first_store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1203 nir_intrinsic_instr
*third_store
= get_intrinsic(nir_intrinsic_store_deref
, 2);
1204 ASSERT_TRUE(third_store
->src
[1].is_ssa
);
1205 EXPECT_EQ(third_store
->src
[1].ssa
, first_store
->src
[1].ssa
);
1207 /* Fourth store will compose first and second store values. */
1208 nir_intrinsic_instr
*fourth_store
= get_intrinsic(nir_intrinsic_store_deref
, 3);
1209 ASSERT_TRUE(fourth_store
->src
[1].is_ssa
);
1210 EXPECT_TRUE(nir_src_as_alu_instr(fourth_store
->src
[1]));
1213 TEST_F(nir_copy_prop_vars_test
, store_load_indirect_array_deref_on_vector
)
1215 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
1216 nir_variable
*idx
= create_int(nir_var_mem_ssbo
, "idx");
1217 nir_variable
*out
= create_int(nir_var_mem_ssbo
, "out");
1219 nir_ssa_def
*idx_ssa
= nir_load_var(b
, idx
);
1221 /* Store to vec[idx]. */
1222 nir_deref_instr
*store_deref
=
1223 nir_build_deref_array(b
, nir_build_deref_var(b
, vec
), idx_ssa
);
1224 nir_store_deref(b
, store_deref
, nir_imm_int(b
, 20), 1);
1226 /* Load from vec[idx] to store in out. This load should be dropped. */
1227 nir_deref_instr
*load_deref
=
1228 nir_build_deref_array(b
, nir_build_deref_var(b
, vec
), idx_ssa
);
1229 nir_store_var(b
, out
, nir_load_deref(b
, load_deref
), 1);
1231 nir_validate_shader(b
->shader
, NULL
);
1232 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
1233 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1235 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1236 EXPECT_TRUE(progress
);
1238 nir_validate_shader(b
->shader
, NULL
);
1239 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
1240 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1242 /* Store to vec[idx] propagated to out. */
1243 nir_intrinsic_instr
*first
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1244 nir_intrinsic_instr
*second
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1245 ASSERT_TRUE(first
->src
[1].is_ssa
);
1246 ASSERT_TRUE(second
->src
[1].is_ssa
);
1247 EXPECT_EQ(first
->src
[1].ssa
, second
->src
[1].ssa
);
1250 TEST_F(nir_copy_prop_vars_test
, store_load_direct_and_indirect_array_deref_on_vector
)
1252 nir_variable
*vec
= create_ivec2(nir_var_mem_ssbo
, "vec");
1253 nir_variable
*idx
= create_int(nir_var_mem_ssbo
, "idx");
1254 nir_variable
**out
= create_many_int(nir_var_mem_ssbo
, "out", 2);
1256 nir_ssa_def
*idx_ssa
= nir_load_var(b
, idx
);
1259 nir_store_var(b
, vec
, nir_imm_ivec2(b
, 10, 10), 1 | 2);
1261 /* Load from vec[idx]. This load is currently not dropped. */
1262 nir_deref_instr
*indirect
=
1263 nir_build_deref_array(b
, nir_build_deref_var(b
, vec
), idx_ssa
);
1264 nir_store_var(b
, out
[0], nir_load_deref(b
, indirect
), 1);
1266 /* Load from vec[idx] again. This load should be dropped. */
1267 nir_store_var(b
, out
[1], nir_load_deref(b
, indirect
), 1);
1269 nir_validate_shader(b
->shader
, NULL
);
1270 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 3);
1271 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
1273 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1274 EXPECT_TRUE(progress
);
1276 nir_validate_shader(b
->shader
, NULL
);
1277 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
1278 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
1280 /* Store to vec[idx] propagated to out. */
1281 nir_intrinsic_instr
*second
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1282 nir_intrinsic_instr
*third
= get_intrinsic(nir_intrinsic_store_deref
, 2);
1283 ASSERT_TRUE(second
->src
[1].is_ssa
);
1284 ASSERT_TRUE(third
->src
[1].is_ssa
);
1285 EXPECT_EQ(second
->src
[1].ssa
, third
->src
[1].ssa
);
1288 TEST_F(nir_copy_prop_vars_test
, store_load_indirect_array_deref
)
1290 nir_variable
*arr
= create_var(nir_var_mem_ssbo
,
1291 glsl_array_type(glsl_int_type(), 10, 0),
1293 nir_variable
*idx
= create_int(nir_var_mem_ssbo
, "idx");
1294 nir_variable
*out
= create_int(nir_var_mem_ssbo
, "out");
1296 nir_ssa_def
*idx_ssa
= nir_load_var(b
, idx
);
1298 /* Store to arr[idx]. */
1299 nir_deref_instr
*store_deref
=
1300 nir_build_deref_array(b
, nir_build_deref_var(b
, arr
), idx_ssa
);
1301 nir_store_deref(b
, store_deref
, nir_imm_int(b
, 20), 1);
1303 /* Load from arr[idx] to store in out. This load should be dropped. */
1304 nir_deref_instr
*load_deref
=
1305 nir_build_deref_array(b
, nir_build_deref_var(b
, arr
), idx_ssa
);
1306 nir_store_var(b
, out
, nir_load_deref(b
, load_deref
), 1);
1308 nir_validate_shader(b
->shader
, NULL
);
1309 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
1310 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1312 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
1313 EXPECT_TRUE(progress
);
1315 nir_validate_shader(b
->shader
, NULL
);
1316 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
1317 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
1319 /* Store to arr[idx] propagated to out. */
1320 nir_intrinsic_instr
*first
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1321 nir_intrinsic_instr
*second
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1322 ASSERT_TRUE(first
->src
[1].is_ssa
);
1323 ASSERT_TRUE(second
->src
[1].is_ssa
);
1324 EXPECT_EQ(first
->src
[1].ssa
, second
->src
[1].ssa
);
1327 TEST_F(nir_dead_write_vars_test
, no_dead_writes_in_block
)
1329 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 2);
1331 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1333 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1334 ASSERT_FALSE(progress
);
1337 TEST_F(nir_dead_write_vars_test
, no_dead_writes_different_components_in_block
)
1339 nir_variable
**v
= create_many_ivec2(nir_var_mem_ssbo
, "v", 3);
1341 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1 << 0);
1342 nir_store_var(b
, v
[0], nir_load_var(b
, v
[2]), 1 << 1);
1344 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1345 ASSERT_FALSE(progress
);
1348 TEST_F(nir_dead_write_vars_test
, volatile_write
)
1350 nir_variable
*v
= create_int(nir_var_mem_ssbo
, "v");
1352 nir_store_var(b
, v
, nir_imm_int(b
, 0), 0x1);
1353 nir_store_var_volatile(b
, v
, nir_imm_int(b
, 1), 0x1);
1354 nir_store_var(b
, v
, nir_imm_int(b
, 2), 0x1);
1356 /* Our approach here is a bit scorched-earth. We expect the volatile store
1357 * in the middle to cause both that store and the one before it to be kept.
1358 * Technically, volatile only prevents combining the volatile store with
1359 * another store and one could argue that the store before the volatile and
1360 * the one after it could be combined. However, it seems safer to just
1361 * treat a volatile store like an atomic and prevent any combining across
1364 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1365 ASSERT_FALSE(progress
);
1368 TEST_F(nir_dead_write_vars_test
, volatile_copies
)
1370 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 2);
1372 nir_copy_var(b
, v
[0], v
[1]);
1373 nir_copy_deref_with_access(b
, nir_build_deref_var(b
, v
[0]),
1374 nir_build_deref_var(b
, v
[1]),
1375 ACCESS_VOLATILE
, (gl_access_qualifier
)0);
1376 nir_copy_var(b
, v
[0], v
[1]);
1378 /* Our approach here is a bit scorched-earth. We expect the volatile store
1379 * in the middle to cause both that store and the one before it to be kept.
1380 * Technically, volatile only prevents combining the volatile store with
1381 * another store and one could argue that the store before the volatile and
1382 * the one after it could be combined. However, it seems safer to just
1383 * treat a volatile store like an atomic and prevent any combining across
1386 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1387 ASSERT_FALSE(progress
);
1390 TEST_F(nir_dead_write_vars_test
, no_dead_writes_in_if_statement
)
1392 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 6);
1394 nir_store_var(b
, v
[2], nir_load_var(b
, v
[0]), 1);
1395 nir_store_var(b
, v
[3], nir_load_var(b
, v
[1]), 1);
1397 /* Each arm of the if statement will overwrite one store. */
1398 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
1399 nir_store_var(b
, v
[2], nir_load_var(b
, v
[4]), 1);
1401 nir_push_else(b
, if_stmt
);
1402 nir_store_var(b
, v
[3], nir_load_var(b
, v
[5]), 1);
1404 nir_pop_if(b
, if_stmt
);
1406 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1407 ASSERT_FALSE(progress
);
1410 TEST_F(nir_dead_write_vars_test
, no_dead_writes_in_loop_statement
)
1412 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 3);
1414 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1416 /* Loop will write other value. Since it might not be executed, it doesn't
1417 * kill the first write.
1419 nir_loop
*loop
= nir_push_loop(b
);
1421 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
1422 nir_jump(b
, nir_jump_break
);
1423 nir_pop_if(b
, if_stmt
);
1425 nir_store_var(b
, v
[0], nir_load_var(b
, v
[2]), 1);
1426 nir_pop_loop(b
, loop
);
1428 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1429 ASSERT_FALSE(progress
);
1432 TEST_F(nir_dead_write_vars_test
, dead_write_in_block
)
1434 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 3);
1436 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1437 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
1438 nir_store_var(b
, v
[0], load_v2
, 1);
1440 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1441 ASSERT_TRUE(progress
);
1443 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
1445 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1446 ASSERT_TRUE(store
->src
[1].is_ssa
);
1447 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
1450 TEST_F(nir_dead_write_vars_test
, dead_write_components_in_block
)
1452 nir_variable
**v
= create_many_ivec2(nir_var_mem_ssbo
, "v", 3);
1454 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1 << 0);
1455 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
1456 nir_store_var(b
, v
[0], load_v2
, 1 << 0);
1458 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1459 ASSERT_TRUE(progress
);
1461 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
1463 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1464 ASSERT_TRUE(store
->src
[1].is_ssa
);
1465 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
1469 /* TODO: The DISABLED tests below depend on the dead write removal be able to
1470 * identify dead writes between multiple blocks. This is still not
1474 TEST_F(nir_dead_write_vars_test
, DISABLED_dead_write_in_two_blocks
)
1476 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 3);
1478 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1479 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
1481 /* Causes the stores to be in different blocks. */
1482 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
1484 nir_store_var(b
, v
[0], load_v2
, 1);
1486 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1487 ASSERT_TRUE(progress
);
1489 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
1491 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1492 ASSERT_TRUE(store
->src
[1].is_ssa
);
1493 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
1496 TEST_F(nir_dead_write_vars_test
, DISABLED_dead_write_components_in_two_blocks
)
1498 nir_variable
**v
= create_many_ivec2(nir_var_mem_ssbo
, "v", 3);
1500 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1 << 0);
1502 /* Causes the stores to be in different blocks. */
1503 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
1505 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
1506 nir_store_var(b
, v
[0], load_v2
, 1 << 0);
1508 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1509 ASSERT_TRUE(progress
);
1511 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
1513 nir_intrinsic_instr
*store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1514 ASSERT_TRUE(store
->src
[1].is_ssa
);
1515 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
1518 TEST_F(nir_dead_write_vars_test
, DISABLED_dead_writes_in_if_statement
)
1520 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 4);
1522 /* Both branches will overwrite, making the previous store dead. */
1523 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1525 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
1526 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
1527 nir_store_var(b
, v
[0], load_v2
, 1);
1529 nir_push_else(b
, if_stmt
);
1530 nir_ssa_def
*load_v3
= nir_load_var(b
, v
[3]);
1531 nir_store_var(b
, v
[0], load_v3
, 1);
1533 nir_pop_if(b
, if_stmt
);
1535 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1536 ASSERT_TRUE(progress
);
1537 EXPECT_EQ(2, count_intrinsics(nir_intrinsic_store_deref
));
1539 nir_intrinsic_instr
*first_store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1540 ASSERT_TRUE(first_store
->src
[1].is_ssa
);
1541 EXPECT_EQ(first_store
->src
[1].ssa
, load_v2
);
1543 nir_intrinsic_instr
*second_store
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1544 ASSERT_TRUE(second_store
->src
[1].is_ssa
);
1545 EXPECT_EQ(second_store
->src
[1].ssa
, load_v3
);
1548 TEST_F(nir_dead_write_vars_test
, DISABLED_memory_barrier_in_two_blocks
)
1550 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 2);
1552 nir_store_var(b
, v
[0], nir_imm_int(b
, 1), 1);
1553 nir_store_var(b
, v
[1], nir_imm_int(b
, 2), 1);
1555 /* Split into many blocks. */
1556 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
1558 /* Because it is before the barrier, this will kill the previous store to that target. */
1559 nir_store_var(b
, v
[0], nir_imm_int(b
, 3), 1);
1561 nir_scoped_memory_barrier(b
, NIR_SCOPE_DEVICE
, NIR_MEMORY_ACQ_REL
,
1564 nir_store_var(b
, v
[1], nir_imm_int(b
, 4), 1);
1566 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1567 ASSERT_TRUE(progress
);
1569 EXPECT_EQ(3, count_intrinsics(nir_intrinsic_store_deref
));
1572 TEST_F(nir_dead_write_vars_test
, DISABLED_unrelated_barrier_in_two_blocks
)
1574 nir_variable
**v
= create_many_int(nir_var_mem_ssbo
, "v", 3);
1575 nir_variable
*out
= create_int(nir_var_shader_out
, "out");
1577 nir_store_var(b
, out
, nir_load_var(b
, v
[1]), 1);
1578 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
1580 /* Split into many blocks. */
1581 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
1583 /* Emit vertex will ensure writes to output variables are considered used,
1584 * but should not affect other types of variables. */
1586 nir_builder_instr_insert(b
, &nir_intrinsic_instr_create(b
->shader
, nir_intrinsic_emit_vertex
)->instr
);
1588 nir_store_var(b
, out
, nir_load_var(b
, v
[2]), 1);
1589 nir_store_var(b
, v
[0], nir_load_var(b
, v
[2]), 1);
1591 bool progress
= nir_opt_dead_write_vars(b
->shader
);
1592 ASSERT_TRUE(progress
);
1594 /* Verify the first write to v[0] was removed. */
1595 EXPECT_EQ(3, count_intrinsics(nir_intrinsic_store_deref
));
1597 nir_intrinsic_instr
*first_store
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1598 EXPECT_EQ(nir_intrinsic_get_var(first_store
, 0), out
);
1600 nir_intrinsic_instr
*second_store
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1601 EXPECT_EQ(nir_intrinsic_get_var(second_store
, 0), out
);
1603 nir_intrinsic_instr
*third_store
= get_intrinsic(nir_intrinsic_store_deref
, 2);
1604 EXPECT_EQ(nir_intrinsic_get_var(third_store
, 0), v
[0]);
1607 TEST_F(nir_combine_stores_test
, non_overlapping_stores
)
1609 nir_variable
**v
= create_many_ivec4(nir_var_mem_ssbo
, "v", 4);
1610 nir_variable
*out
= create_ivec4(nir_var_shader_out
, "out");
1612 for (int i
= 0; i
< 4; i
++)
1613 nir_store_var(b
, out
, nir_load_var(b
, v
[i
]), 1 << i
);
1615 nir_validate_shader(b
->shader
, NULL
);
1617 bool progress
= nir_opt_combine_stores(b
->shader
, nir_var_shader_out
);
1618 ASSERT_TRUE(progress
);
1620 nir_validate_shader(b
->shader
, NULL
);
1622 /* Clean up to verify from where the values in combined store are coming. */
1623 nir_copy_prop(b
->shader
);
1624 nir_opt_dce(b
->shader
);
1626 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 1);
1627 nir_intrinsic_instr
*combined
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1628 ASSERT_EQ(nir_intrinsic_write_mask(combined
), 0xf);
1629 ASSERT_EQ(nir_intrinsic_get_var(combined
, 0), out
);
1631 nir_alu_instr
*vec
= nir_src_as_alu_instr(combined
->src
[1]);
1633 for (int i
= 0; i
< 4; i
++) {
1634 nir_intrinsic_instr
*load
= nir_src_as_intrinsic(vec
->src
[i
].src
);
1635 ASSERT_EQ(load
->intrinsic
, nir_intrinsic_load_deref
);
1636 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), v
[i
])
1637 << "Source value for component " << i
<< " of store is wrong";
1638 ASSERT_EQ(vec
->src
[i
].swizzle
[0], i
)
1639 << "Source component for component " << i
<< " of store is wrong";
1643 TEST_F(nir_combine_stores_test
, overlapping_stores
)
1645 nir_variable
**v
= create_many_ivec4(nir_var_mem_ssbo
, "v", 3);
1646 nir_variable
*out
= create_ivec4(nir_var_shader_out
, "out");
1648 /* Make stores with xy, yz and zw masks. */
1649 for (int i
= 0; i
< 3; i
++) {
1650 nir_component_mask_t mask
= (1 << i
) | (1 << (i
+ 1));
1651 nir_store_var(b
, out
, nir_load_var(b
, v
[i
]), mask
);
1654 nir_validate_shader(b
->shader
, NULL
);
1656 bool progress
= nir_opt_combine_stores(b
->shader
, nir_var_shader_out
);
1657 ASSERT_TRUE(progress
);
1659 nir_validate_shader(b
->shader
, NULL
);
1661 /* Clean up to verify from where the values in combined store are coming. */
1662 nir_copy_prop(b
->shader
);
1663 nir_opt_dce(b
->shader
);
1665 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 1);
1666 nir_intrinsic_instr
*combined
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1667 ASSERT_EQ(nir_intrinsic_write_mask(combined
), 0xf);
1668 ASSERT_EQ(nir_intrinsic_get_var(combined
, 0), out
);
1670 nir_alu_instr
*vec
= nir_src_as_alu_instr(combined
->src
[1]);
1673 /* Component x comes from v[0]. */
1674 nir_intrinsic_instr
*load_for_x
= nir_src_as_intrinsic(vec
->src
[0].src
);
1675 ASSERT_EQ(nir_intrinsic_get_var(load_for_x
, 0), v
[0]);
1676 ASSERT_EQ(vec
->src
[0].swizzle
[0], 0);
1678 /* Component y comes from v[1]. */
1679 nir_intrinsic_instr
*load_for_y
= nir_src_as_intrinsic(vec
->src
[1].src
);
1680 ASSERT_EQ(nir_intrinsic_get_var(load_for_y
, 0), v
[1]);
1681 ASSERT_EQ(vec
->src
[1].swizzle
[0], 1);
1683 /* Components z and w come from v[2]. */
1684 nir_intrinsic_instr
*load_for_z
= nir_src_as_intrinsic(vec
->src
[2].src
);
1685 nir_intrinsic_instr
*load_for_w
= nir_src_as_intrinsic(vec
->src
[3].src
);
1686 ASSERT_EQ(load_for_z
, load_for_w
);
1687 ASSERT_EQ(nir_intrinsic_get_var(load_for_z
, 0), v
[2]);
1688 ASSERT_EQ(vec
->src
[2].swizzle
[0], 2);
1689 ASSERT_EQ(vec
->src
[3].swizzle
[0], 3);
1692 TEST_F(nir_combine_stores_test
, direct_array_derefs
)
1694 nir_variable
**v
= create_many_ivec4(nir_var_mem_ssbo
, "vec", 2);
1695 nir_variable
**s
= create_many_int(nir_var_mem_ssbo
, "scalar", 2);
1696 nir_variable
*out
= create_ivec4(nir_var_mem_ssbo
, "out");
1698 nir_deref_instr
*out_deref
= nir_build_deref_var(b
, out
);
1700 /* Store to vector with mask x. */
1701 nir_store_deref(b
, out_deref
, nir_load_var(b
, v
[0]),
1704 /* Store to vector with mask yz. */
1705 nir_store_deref(b
, out_deref
, nir_load_var(b
, v
[1]),
1706 (1 << 2) | (1 << 1));
1708 /* Store to vector[2], overlapping with previous store. */
1710 nir_build_deref_array_imm(b
, out_deref
, 2),
1711 nir_load_var(b
, s
[0]),
1714 /* Store to vector[3], no overlap. */
1716 nir_build_deref_array_imm(b
, out_deref
, 3),
1717 nir_load_var(b
, s
[1]),
1720 nir_validate_shader(b
->shader
, NULL
);
1722 bool progress
= nir_opt_combine_stores(b
->shader
, nir_var_mem_ssbo
);
1723 ASSERT_TRUE(progress
);
1725 nir_validate_shader(b
->shader
, NULL
);
1727 /* Clean up to verify from where the values in combined store are coming. */
1728 nir_copy_prop(b
->shader
);
1729 nir_opt_dce(b
->shader
);
1731 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 1);
1732 nir_intrinsic_instr
*combined
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1733 ASSERT_EQ(nir_intrinsic_write_mask(combined
), 0xf);
1734 ASSERT_EQ(nir_intrinsic_get_var(combined
, 0), out
);
1736 nir_alu_instr
*vec
= nir_src_as_alu_instr(combined
->src
[1]);
1739 /* Component x comes from v[0]. */
1740 nir_intrinsic_instr
*load_for_x
= nir_src_as_intrinsic(vec
->src
[0].src
);
1741 ASSERT_EQ(nir_intrinsic_get_var(load_for_x
, 0), v
[0]);
1742 ASSERT_EQ(vec
->src
[0].swizzle
[0], 0);
1744 /* Component y comes from v[1]. */
1745 nir_intrinsic_instr
*load_for_y
= nir_src_as_intrinsic(vec
->src
[1].src
);
1746 ASSERT_EQ(nir_intrinsic_get_var(load_for_y
, 0), v
[1]);
1747 ASSERT_EQ(vec
->src
[1].swizzle
[0], 1);
1749 /* Components z comes from s[0]. */
1750 nir_intrinsic_instr
*load_for_z
= nir_src_as_intrinsic(vec
->src
[2].src
);
1751 ASSERT_EQ(nir_intrinsic_get_var(load_for_z
, 0), s
[0]);
1752 ASSERT_EQ(vec
->src
[2].swizzle
[0], 0);
1754 /* Component w comes from s[1]. */
1755 nir_intrinsic_instr
*load_for_w
= nir_src_as_intrinsic(vec
->src
[3].src
);
1756 ASSERT_EQ(nir_intrinsic_get_var(load_for_w
, 0), s
[1]);
1757 ASSERT_EQ(vec
->src
[3].swizzle
[0], 0);
1761 vec_src_comp_as_int(nir_src src
, unsigned comp
)
1763 if (nir_src_is_const(src
))
1764 return nir_src_comp_as_int(src
, comp
);
1767 nir_ssa_scalar s
= { src
.ssa
, comp
};
1768 assert(nir_op_is_vec(nir_ssa_scalar_alu_op(s
)));
1769 return nir_ssa_scalar_as_int(nir_ssa_scalar_chase_alu_src(s
, comp
));
1772 TEST_F(nir_combine_stores_test
, store_volatile
)
1774 nir_variable
*out
= create_ivec4(nir_var_shader_out
, "out");
1776 nir_store_var(b
, out
, nir_imm_ivec4(b
, 0, 0, 0, 0), 1 << 0);
1777 nir_store_var(b
, out
, nir_imm_ivec4(b
, 1, 1, 1, 1), 1 << 1);
1778 nir_store_var_volatile(b
, out
, nir_imm_ivec4(b
, -1, -2, -3, -4), 0xf);
1779 nir_store_var(b
, out
, nir_imm_ivec4(b
, 2, 2, 2, 2), 1 << 2);
1780 nir_store_var(b
, out
, nir_imm_ivec4(b
, 3, 3, 3, 3), 1 << 3);
1782 nir_validate_shader(b
->shader
, NULL
);
1784 bool progress
= nir_opt_combine_stores(b
->shader
, nir_var_shader_out
);
1785 ASSERT_TRUE(progress
);
1787 nir_validate_shader(b
->shader
, NULL
);
1789 /* Clean up the stored values */
1790 nir_opt_constant_folding(b
->shader
);
1791 nir_opt_dce(b
->shader
);
1793 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 3);
1795 nir_intrinsic_instr
*first
= get_intrinsic(nir_intrinsic_store_deref
, 0);
1796 ASSERT_EQ(nir_intrinsic_write_mask(first
), 0x3);
1797 ASSERT_EQ(vec_src_comp_as_int(first
->src
[1], 0), 0);
1798 ASSERT_EQ(vec_src_comp_as_int(first
->src
[1], 1), 1);
1800 nir_intrinsic_instr
*second
= get_intrinsic(nir_intrinsic_store_deref
, 1);
1801 ASSERT_EQ(nir_intrinsic_write_mask(second
), 0xf);
1802 ASSERT_EQ(vec_src_comp_as_int(second
->src
[1], 0), -1);
1803 ASSERT_EQ(vec_src_comp_as_int(second
->src
[1], 1), -2);
1804 ASSERT_EQ(vec_src_comp_as_int(second
->src
[1], 2), -3);
1805 ASSERT_EQ(vec_src_comp_as_int(second
->src
[1], 3), -4);
1807 nir_intrinsic_instr
*third
= get_intrinsic(nir_intrinsic_store_deref
, 2);
1808 ASSERT_EQ(nir_intrinsic_write_mask(third
), 0xc);
1809 ASSERT_EQ(vec_src_comp_as_int(third
->src
[1], 2), 2);
1810 ASSERT_EQ(vec_src_comp_as_int(third
->src
[1], 3), 3);
1813 TEST_F(nir_split_vars_test
, simple_split
)
1815 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1816 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1818 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1819 for (int i
= 0; i
< 4; i
++)
1820 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1822 nir_validate_shader(b
->shader
, NULL
);
1823 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
1824 ASSERT_EQ(count_function_temp_vars(), 1);
1826 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1827 EXPECT_TRUE(progress
);
1829 nir_validate_shader(b
->shader
, NULL
);
1830 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1831 ASSERT_EQ(count_function_temp_vars(), 4);
1834 TEST_F(nir_split_vars_test
, simple_no_split_array_struct
)
1836 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1837 struct glsl_struct_field field
;
1839 field
.type
= glsl_float_type();
1840 field
.name
= ralloc_asprintf(b
, "field1");
1841 field
.location
= -1;
1844 const struct glsl_type
*st_type
= glsl_struct_type(&field
, 1, "struct", false);
1845 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(st_type
, 4, 0),
1848 nir_variable
*temp2
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0), "temp2");
1850 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1851 nir_deref_instr
*temp2_deref
= nir_build_deref_var(b
, temp2
);
1852 for (int i
= 0; i
< 4; i
++)
1853 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp2_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1855 for (int i
= 0; i
< 4; i
++)
1856 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);
1858 nir_validate_shader(b
->shader
, NULL
);
1859 ASSERT_EQ(count_derefs(nir_deref_type_array
), 8);
1860 ASSERT_EQ(count_derefs(nir_deref_type_struct
), 4);
1861 ASSERT_EQ(count_function_temp_vars(), 2);
1863 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1864 EXPECT_TRUE(progress
);
1866 nir_validate_shader(b
->shader
, NULL
);
1868 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
1869 ASSERT_EQ(count_derefs(nir_deref_type_struct
), 4);
1870 for (int i
= 0; i
< 4; i
++) {
1871 nir_deref_instr
*deref
= get_deref(nir_deref_type_array
, i
);
1873 ASSERT_TRUE(glsl_type_is_struct(deref
->type
));
1876 ASSERT_EQ(count_function_temp_vars(), 5);
1879 TEST_F(nir_split_vars_test
, simple_split_shader_temp
)
1881 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1882 nir_variable
*temp
= create_var(nir_var_shader_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1884 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1886 for (int i
= 0; i
< 4; i
++)
1887 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1889 nir_validate_shader(b
->shader
, NULL
);
1890 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
1891 ASSERT_EQ(count_shader_temp_vars(), 1);
1893 bool progress
= nir_split_array_vars(b
->shader
, nir_var_shader_temp
);
1894 EXPECT_TRUE(progress
);
1896 nir_validate_shader(b
->shader
, NULL
);
1897 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1898 ASSERT_EQ(count_shader_temp_vars(), 4);
1901 TEST_F(nir_split_vars_test
, simple_oob
)
1903 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 6);
1904 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1906 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1908 for (int i
= 0; i
< 6; i
++)
1909 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1911 nir_validate_shader(b
->shader
, NULL
);
1912 ASSERT_EQ(count_derefs(nir_deref_type_array
), 6);
1913 ASSERT_EQ(count_function_temp_vars(), 1);
1915 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1916 EXPECT_TRUE(progress
);
1918 nir_validate_shader(b
->shader
, NULL
);
1919 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1920 ASSERT_EQ(count_function_temp_vars(), 4);
1923 TEST_F(nir_split_vars_test
, simple_unused
)
1925 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 2);
1926 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1928 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1930 for (int i
= 0; i
< 2; i
++)
1931 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
1933 nir_validate_shader(b
->shader
, NULL
);
1934 ASSERT_EQ(count_derefs(nir_deref_type_array
), 2);
1935 ASSERT_EQ(count_function_temp_vars(), 1);
1937 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1938 EXPECT_TRUE(progress
);
1940 nir_validate_shader(b
->shader
, NULL
);
1941 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1942 /* this pass doesn't remove the unused ones */
1943 ASSERT_EQ(count_function_temp_vars(), 4);
1946 TEST_F(nir_split_vars_test
, two_level_split
)
1948 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1949 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_array_type(glsl_int_type(), 4, 0), 4, 0),
1951 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1952 for (int i
= 0; i
< 4; i
++) {
1953 nir_deref_instr
*level0
= nir_build_deref_array_imm(b
, temp_deref
, i
);
1954 for (int j
= 0; j
< 4; j
++) {
1955 nir_deref_instr
*level1
= nir_build_deref_array_imm(b
, level0
, j
);
1956 nir_store_deref(b
, level1
, nir_load_var(b
, in
[i
]), 1);
1960 nir_validate_shader(b
->shader
, NULL
);
1961 ASSERT_EQ(count_derefs(nir_deref_type_array
), 20);
1962 ASSERT_EQ(count_function_temp_vars(), 1);
1964 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1965 EXPECT_TRUE(progress
);
1967 nir_validate_shader(b
->shader
, NULL
);
1968 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
1969 ASSERT_EQ(count_function_temp_vars(), 16);
1972 TEST_F(nir_split_vars_test
, simple_dont_split
)
1974 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
1975 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
1977 nir_variable
*ind
= create_int(nir_var_shader_in
, "ind");
1979 nir_deref_instr
*ind_deref
= nir_build_deref_var(b
, ind
);
1980 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
1982 for (int i
= 0; i
< 4; i
++)
1983 nir_store_deref(b
, nir_build_deref_array(b
, temp_deref
, &ind_deref
->dest
.ssa
), nir_load_var(b
, in
[i
]), 1);
1985 nir_validate_shader(b
->shader
, NULL
);
1986 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
1987 ASSERT_EQ(count_function_temp_vars(), 1);
1989 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
1990 EXPECT_FALSE(progress
);
1992 nir_validate_shader(b
->shader
, NULL
);
1993 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
1994 ASSERT_EQ(count_function_temp_vars(), 1);
1997 TEST_F(nir_split_vars_test
, twolevel_dont_split_lvl_0
)
1999 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
2000 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_array_type(glsl_int_type(), 6, 0), 4, 0),
2002 nir_variable
*ind
= create_int(nir_var_shader_in
, "ind");
2004 nir_deref_instr
*ind_deref
= nir_build_deref_var(b
, ind
);
2005 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
2007 for (int i
= 0; i
< 4; i
++) {
2008 nir_deref_instr
*level0
= nir_build_deref_array(b
, temp_deref
, &ind_deref
->dest
.ssa
);
2009 for (int j
= 0; j
< 6; j
++) {
2010 nir_deref_instr
*level1
= nir_build_deref_array_imm(b
, level0
, j
);
2011 nir_store_deref(b
, level1
, nir_load_var(b
, in
[i
]), 1);
2015 nir_validate_shader(b
->shader
, NULL
);
2016 ASSERT_EQ(count_derefs(nir_deref_type_array
), 28);
2017 ASSERT_EQ(count_function_temp_vars(), 1);
2019 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
2020 EXPECT_TRUE(progress
);
2022 nir_validate_shader(b
->shader
, NULL
);
2023 ASSERT_EQ(count_derefs(nir_deref_type_array
), 24);
2024 ASSERT_EQ(count_function_temp_vars(), 6);
2027 TEST_F(nir_split_vars_test
, twolevel_dont_split_lvl_1
)
2029 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 6);
2030 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_array_type(glsl_int_type(), 6, 0), 4, 0),
2032 nir_variable
*ind
= create_int(nir_var_shader_in
, "ind");
2034 nir_deref_instr
*ind_deref
= nir_build_deref_var(b
, ind
);
2035 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
2037 for (int i
= 0; i
< 4; i
++) {
2038 nir_deref_instr
*level0
= nir_build_deref_array_imm(b
, temp_deref
, i
);
2039 for (int j
= 0; j
< 6; j
++) {
2040 /* just add the inner index to get some different derefs */
2041 nir_deref_instr
*level1
= nir_build_deref_array(b
, level0
, nir_iadd(b
, &ind_deref
->dest
.ssa
, nir_imm_int(b
, j
)));
2042 nir_store_deref(b
, level1
, nir_load_var(b
, in
[i
]), 1);
2046 nir_validate_shader(b
->shader
, NULL
);
2047 ASSERT_EQ(count_derefs(nir_deref_type_array
), 28);
2048 ASSERT_EQ(count_function_temp_vars(), 1);
2050 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
2051 EXPECT_TRUE(progress
);
2053 nir_validate_shader(b
->shader
, NULL
);
2054 ASSERT_EQ(count_derefs(nir_deref_type_array
), 24);
2055 ASSERT_EQ(count_function_temp_vars(), 4);
2058 TEST_F(nir_split_vars_test
, split_multiple_store
)
2060 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
2061 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
2063 nir_variable
*temp2
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
2066 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
2067 nir_deref_instr
*temp2_deref
= nir_build_deref_var(b
, temp2
);
2069 for (int i
= 0; i
< 4; i
++)
2070 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
2072 for (int i
= 0; i
< 4; i
++)
2073 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp2_deref
, i
), nir_load_var(b
, in
[i
]), 1);
2075 nir_validate_shader(b
->shader
, NULL
);
2076 ASSERT_EQ(count_derefs(nir_deref_type_array
), 8);
2077 ASSERT_EQ(count_function_temp_vars(), 2);
2079 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
2080 EXPECT_TRUE(progress
);
2082 nir_validate_shader(b
->shader
, NULL
);
2083 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
2084 ASSERT_EQ(count_function_temp_vars(), 8);
2087 TEST_F(nir_split_vars_test
, split_load_store
)
2089 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
2090 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
2092 nir_variable
*temp2
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
2095 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
2096 nir_deref_instr
*temp2_deref
= nir_build_deref_var(b
, temp2
);
2098 for (int i
= 0; i
< 4; i
++)
2099 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
2101 for (int i
= 0; i
< 4; i
++) {
2102 nir_deref_instr
*store_deref
= nir_build_deref_array_imm(b
, temp2_deref
, i
);
2103 nir_deref_instr
*load_deref
= nir_build_deref_array_imm(b
, temp_deref
, i
);
2104 nir_store_deref(b
, store_deref
, nir_load_deref(b
, load_deref
), 1);
2107 nir_validate_shader(b
->shader
, NULL
);
2108 ASSERT_EQ(count_derefs(nir_deref_type_array
), 12);
2109 ASSERT_EQ(count_function_temp_vars(), 2);
2111 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
2112 EXPECT_TRUE(progress
);
2114 nir_validate_shader(b
->shader
, NULL
);
2115 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
2116 ASSERT_EQ(count_function_temp_vars(), 8);
2119 TEST_F(nir_split_vars_test
, split_copy
)
2121 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
2122 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
2124 nir_variable
*temp2
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
2127 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
2128 nir_deref_instr
*temp2_deref
= nir_build_deref_var(b
, temp2
);
2130 for (int i
= 0; i
< 4; i
++)
2131 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
2133 for (int i
= 0; i
< 4; i
++) {
2134 nir_deref_instr
*store_deref
= nir_build_deref_array_imm(b
, temp2_deref
, i
);
2135 nir_deref_instr
*load_deref
= nir_build_deref_array_imm(b
, temp_deref
, i
);
2136 nir_copy_deref(b
, store_deref
, load_deref
);
2139 nir_validate_shader(b
->shader
, NULL
);
2140 ASSERT_EQ(count_derefs(nir_deref_type_array
), 12);
2141 ASSERT_EQ(count_function_temp_vars(), 2);
2143 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
2144 EXPECT_TRUE(progress
);
2146 nir_validate_shader(b
->shader
, NULL
);
2147 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
2148 ASSERT_EQ(count_function_temp_vars(), 8);
2151 TEST_F(nir_split_vars_test
, split_wildcard_copy
)
2153 nir_variable
**in
= create_many_int(nir_var_shader_in
, "in", 4);
2154 nir_variable
*temp
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
2156 nir_variable
*temp2
= create_var(nir_var_function_temp
, glsl_array_type(glsl_int_type(), 4, 0),
2159 nir_deref_instr
*temp_deref
= nir_build_deref_var(b
, temp
);
2160 nir_deref_instr
*temp2_deref
= nir_build_deref_var(b
, temp2
);
2162 for (int i
= 0; i
< 4; i
++)
2163 nir_store_deref(b
, nir_build_deref_array_imm(b
, temp_deref
, i
), nir_load_var(b
, in
[i
]), 1);
2165 nir_deref_instr
*src_wildcard
= nir_build_deref_array_wildcard(b
, temp_deref
);
2166 nir_deref_instr
*dst_wildcard
= nir_build_deref_array_wildcard(b
, temp2_deref
);
2168 nir_copy_deref(b
, dst_wildcard
, src_wildcard
);
2170 nir_validate_shader(b
->shader
, NULL
);
2171 ASSERT_EQ(count_derefs(nir_deref_type_array
), 4);
2172 ASSERT_EQ(count_derefs(nir_deref_type_array_wildcard
), 2);
2173 ASSERT_EQ(count_function_temp_vars(), 2);
2174 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref
), 1);
2176 bool progress
= nir_split_array_vars(b
->shader
, nir_var_function_temp
);
2177 EXPECT_TRUE(progress
);
2179 nir_validate_shader(b
->shader
, NULL
);
2180 ASSERT_EQ(count_derefs(nir_deref_type_array
), 0);
2181 ASSERT_EQ(count_derefs(nir_deref_type_array_wildcard
), 0);
2182 ASSERT_EQ(count_function_temp_vars(), 8);
2183 ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref
), 4);