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_int(nir_variable_mode mode
, const char *name
) {
37 if (mode
== nir_var_function
)
38 return nir_local_variable_create(b
->impl
, glsl_int_type(), name
);
39 return nir_variable_create(b
->shader
, mode
, glsl_int_type(), name
);
42 nir_variable
*create_ivec2(nir_variable_mode mode
, const char *name
) {
43 const glsl_type
*var_type
= glsl_vector_type(GLSL_TYPE_INT
, 2);
44 if (mode
== nir_var_function
)
45 return nir_local_variable_create(b
->impl
, var_type
, name
);
46 return nir_variable_create(b
->shader
, mode
, var_type
, name
);
49 nir_variable
**create_many_int(nir_variable_mode mode
, const char *prefix
, unsigned count
) {
50 nir_variable
**result
= (nir_variable
**)linear_alloc_child(lin_ctx
, sizeof(nir_variable
*) * count
);
51 for (unsigned i
= 0; i
< count
; i
++)
52 result
[i
] = create_int(mode
, linear_asprintf(lin_ctx
, "%s%u", prefix
, i
));
56 nir_variable
**create_many_ivec2(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_ivec2(mode
, linear_asprintf(lin_ctx
, "%s%u", prefix
, i
));
63 unsigned count_intrinsics(nir_intrinsic_op intrinsic
);
65 nir_intrinsic_instr
*find_next_intrinsic(nir_intrinsic_op intrinsic
,
66 nir_intrinsic_instr
*after
);
74 nir_vars_test::nir_vars_test()
76 mem_ctx
= ralloc_context(NULL
);
77 lin_ctx
= linear_alloc_parent(mem_ctx
, 0);
78 static const nir_shader_compiler_options options
= { };
79 b
= rzalloc(mem_ctx
, nir_builder
);
80 nir_builder_init_simple_shader(b
, mem_ctx
, MESA_SHADER_FRAGMENT
, &options
);
83 nir_vars_test::~nir_vars_test()
86 printf("\nShader from the failed test:\n\n");
87 nir_print_shader(b
->shader
, stdout
);
94 nir_vars_test::count_intrinsics(nir_intrinsic_op intrinsic
)
97 nir_foreach_block(block
, b
->impl
) {
98 nir_foreach_instr(instr
, block
) {
99 if (instr
->type
!= nir_instr_type_intrinsic
)
101 nir_intrinsic_instr
*intrin
= nir_instr_as_intrinsic(instr
);
102 if (intrin
->intrinsic
== intrinsic
)
109 nir_intrinsic_instr
*
110 nir_vars_test::find_next_intrinsic(nir_intrinsic_op intrinsic
,
111 nir_intrinsic_instr
*after
)
113 bool seen
= after
== NULL
;
114 nir_foreach_block(block
, b
->impl
) {
115 /* Skip blocks before the 'after' instruction. */
116 if (!seen
&& block
!= after
->instr
.block
)
118 nir_foreach_instr(instr
, block
) {
119 if (instr
->type
!= nir_instr_type_intrinsic
)
121 nir_intrinsic_instr
*intrin
= nir_instr_as_intrinsic(instr
);
123 seen
= (after
== intrin
);
126 if (intrin
->intrinsic
== intrinsic
)
133 /* Allow grouping the tests while still sharing the helpers. */
134 class nir_redundant_load_vars_test
: public nir_vars_test
{};
135 class nir_copy_prop_vars_test
: public nir_vars_test
{};
136 class nir_dead_write_vars_test
: public nir_vars_test
{};
140 TEST_F(nir_redundant_load_vars_test
, duplicated_load
)
142 /* Load a variable twice in the same block. One should be removed. */
144 nir_variable
*in
= create_int(nir_var_shader_in
, "in");
145 nir_variable
**out
= create_many_int(nir_var_shader_out
, "out", 2);
147 nir_store_var(b
, out
[0], nir_load_var(b
, in
), 1);
148 nir_store_var(b
, out
[1], nir_load_var(b
, in
), 1);
150 nir_validate_shader(b
->shader
, NULL
);
152 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
154 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
155 EXPECT_TRUE(progress
);
157 nir_validate_shader(b
->shader
, NULL
);
159 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
162 TEST_F(nir_redundant_load_vars_test
, duplicated_load_in_two_blocks
)
164 /* Load a variable twice in different blocks. One should be removed. */
166 nir_variable
*in
= create_int(nir_var_shader_in
, "in");
167 nir_variable
**out
= create_many_int(nir_var_shader_out
, "out", 2);
169 nir_store_var(b
, out
[0], nir_load_var(b
, in
), 1);
171 /* Forces the stores to be in different blocks. */
172 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
174 nir_store_var(b
, out
[1], nir_load_var(b
, in
), 1);
176 nir_validate_shader(b
->shader
, NULL
);
178 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 2);
180 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
181 EXPECT_TRUE(progress
);
183 nir_validate_shader(b
->shader
, NULL
);
185 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 1);
188 TEST_F(nir_redundant_load_vars_test
, invalidate_inside_if_block
)
190 /* Load variables, then write to some of then in different branches of the
191 * if statement. They should be invalidated accordingly.
194 nir_variable
**g
= create_many_int(nir_var_shader_temp
, "g", 3);
195 nir_variable
**out
= create_many_int(nir_var_shader_out
, "out", 3);
197 nir_load_var(b
, g
[0]);
198 nir_load_var(b
, g
[1]);
199 nir_load_var(b
, g
[2]);
201 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
202 nir_store_var(b
, g
[0], nir_imm_int(b
, 10), 1);
204 nir_push_else(b
, if_stmt
);
205 nir_store_var(b
, g
[1], nir_imm_int(b
, 20), 1);
207 nir_pop_if(b
, if_stmt
);
209 nir_store_var(b
, out
[0], nir_load_var(b
, g
[0]), 1);
210 nir_store_var(b
, out
[1], nir_load_var(b
, g
[1]), 1);
211 nir_store_var(b
, out
[2], nir_load_var(b
, g
[2]), 1);
213 nir_validate_shader(b
->shader
, NULL
);
215 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
216 EXPECT_TRUE(progress
);
218 /* There are 3 initial loads, plus 2 loads for the values invalidated
219 * inside the if statement.
221 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref
), 5);
223 /* We only load g[2] once. */
224 unsigned g2_load_count
= 0;
225 nir_intrinsic_instr
*load
= NULL
;
226 for (int i
= 0; i
< 5; i
++) {
227 load
= find_next_intrinsic(nir_intrinsic_load_deref
, load
);
228 if (nir_intrinsic_get_var(load
, 0) == g
[2])
231 EXPECT_EQ(g2_load_count
, 1);
234 TEST_F(nir_redundant_load_vars_test
, invalidate_live_load_in_the_end_of_loop
)
236 /* Invalidating a load in the end of loop body will apply to the whole loop
240 nir_variable
*v
= create_int(nir_var_ssbo
, "v");
244 nir_loop
*loop
= nir_push_loop(b
);
246 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
247 nir_jump(b
, nir_jump_break
);
248 nir_pop_if(b
, if_stmt
);
251 nir_store_var(b
, v
, nir_imm_int(b
, 10), 1);
253 nir_pop_loop(b
, loop
);
255 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
256 ASSERT_FALSE(progress
);
259 TEST_F(nir_copy_prop_vars_test
, simple_copies
)
261 nir_variable
*in
= create_int(nir_var_shader_in
, "in");
262 nir_variable
*temp
= create_int(nir_var_function
, "temp");
263 nir_variable
*out
= create_int(nir_var_shader_out
, "out");
265 nir_copy_var(b
, temp
, in
);
266 nir_copy_var(b
, out
, temp
);
268 nir_validate_shader(b
->shader
, NULL
);
270 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
271 EXPECT_TRUE(progress
);
273 nir_validate_shader(b
->shader
, NULL
);
275 nir_intrinsic_instr
*copy
= NULL
;
276 copy
= find_next_intrinsic(nir_intrinsic_copy_deref
, copy
);
277 ASSERT_TRUE(copy
->src
[1].is_ssa
);
278 nir_ssa_def
*first_src
= copy
->src
[1].ssa
;
280 copy
= find_next_intrinsic(nir_intrinsic_copy_deref
, copy
);
281 ASSERT_TRUE(copy
->src
[1].is_ssa
);
282 EXPECT_EQ(copy
->src
[1].ssa
, first_src
);
285 TEST_F(nir_copy_prop_vars_test
, simple_store_load
)
287 nir_variable
**v
= create_many_ivec2(nir_var_function
, "v", 2);
288 unsigned mask
= 1 | 2;
290 nir_ssa_def
*stored_value
= nir_imm_ivec2(b
, 10, 20);
291 nir_store_var(b
, v
[0], stored_value
, mask
);
293 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
294 nir_store_var(b
, v
[1], read_value
, mask
);
296 nir_validate_shader(b
->shader
, NULL
);
298 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
299 EXPECT_TRUE(progress
);
301 nir_validate_shader(b
->shader
, NULL
);
303 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
305 nir_intrinsic_instr
*store
= NULL
;
306 for (int i
= 0; i
< 2; i
++) {
307 store
= find_next_intrinsic(nir_intrinsic_store_deref
, store
);
308 ASSERT_TRUE(store
->src
[1].is_ssa
);
309 EXPECT_EQ(store
->src
[1].ssa
, stored_value
);
313 TEST_F(nir_copy_prop_vars_test
, store_store_load
)
315 nir_variable
**v
= create_many_ivec2(nir_var_function
, "v", 2);
316 unsigned mask
= 1 | 2;
318 nir_ssa_def
*first_value
= nir_imm_ivec2(b
, 10, 20);
319 nir_store_var(b
, v
[0], first_value
, mask
);
321 nir_ssa_def
*second_value
= nir_imm_ivec2(b
, 30, 40);
322 nir_store_var(b
, v
[0], second_value
, mask
);
324 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
325 nir_store_var(b
, v
[1], read_value
, mask
);
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 /* Store to v[1] should use second_value directly. */
335 nir_intrinsic_instr
*store_to_v1
= NULL
;
336 while ((store_to_v1
= find_next_intrinsic(nir_intrinsic_store_deref
, store_to_v1
)) != NULL
) {
337 if (nir_intrinsic_get_var(store_to_v1
, 0) == v
[1]) {
338 ASSERT_TRUE(store_to_v1
->src
[1].is_ssa
);
339 EXPECT_EQ(store_to_v1
->src
[1].ssa
, second_value
);
343 EXPECT_TRUE(store_to_v1
);
346 TEST_F(nir_copy_prop_vars_test
, store_store_load_different_components
)
348 nir_variable
**v
= create_many_ivec2(nir_var_function
, "v", 2);
350 nir_ssa_def
*first_value
= nir_imm_ivec2(b
, 10, 20);
351 nir_store_var(b
, v
[0], first_value
, 1 << 1);
353 nir_ssa_def
*second_value
= nir_imm_ivec2(b
, 30, 40);
354 nir_store_var(b
, v
[0], second_value
, 1 << 0);
356 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
357 nir_store_var(b
, v
[1], read_value
, 1 << 1);
359 nir_validate_shader(b
->shader
, NULL
);
361 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
362 EXPECT_TRUE(progress
);
364 nir_validate_shader(b
->shader
, NULL
);
366 nir_opt_constant_folding(b
->shader
);
367 nir_validate_shader(b
->shader
, NULL
);
369 /* Store to v[1] should use first_value directly. The write of
370 * second_value did not overwrite the component it uses.
372 nir_intrinsic_instr
*store_to_v1
= NULL
;
373 while ((store_to_v1
= find_next_intrinsic(nir_intrinsic_store_deref
, store_to_v1
)) != NULL
) {
374 if (nir_intrinsic_get_var(store_to_v1
, 0) == v
[1]) {
375 ASSERT_TRUE(store_to_v1
->src
[1].is_ssa
);
377 ASSERT_TRUE(nir_src_is_const(store_to_v1
->src
[1]));
378 ASSERT_EQ(nir_src_comp_as_uint(store_to_v1
->src
[1], 1), 20);
382 EXPECT_TRUE(store_to_v1
);
385 TEST_F(nir_copy_prop_vars_test
, store_store_load_different_components_in_many_blocks
)
387 nir_variable
**v
= create_many_ivec2(nir_var_function
, "v", 2);
389 nir_ssa_def
*first_value
= nir_imm_ivec2(b
, 10, 20);
390 nir_store_var(b
, v
[0], first_value
, 1 << 1);
392 /* Adding an if statement will cause blocks to be created. */
393 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
395 nir_ssa_def
*second_value
= nir_imm_ivec2(b
, 30, 40);
396 nir_store_var(b
, v
[0], second_value
, 1 << 0);
398 /* Adding an if statement will cause blocks to be created. */
399 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
401 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
402 nir_store_var(b
, v
[1], read_value
, 1 << 1);
404 nir_validate_shader(b
->shader
, NULL
);
406 nir_print_shader(b
->shader
, stdout
);
408 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
409 EXPECT_TRUE(progress
);
411 nir_print_shader(b
->shader
, stdout
);
413 nir_validate_shader(b
->shader
, NULL
);
415 nir_opt_constant_folding(b
->shader
);
416 nir_validate_shader(b
->shader
, NULL
);
418 /* Store to v[1] should use first_value directly. The write of
419 * second_value did not overwrite the component it uses.
421 nir_intrinsic_instr
*store_to_v1
= NULL
;
422 while ((store_to_v1
= find_next_intrinsic(nir_intrinsic_store_deref
, store_to_v1
)) != NULL
) {
423 if (nir_intrinsic_get_var(store_to_v1
, 0) == v
[1]) {
424 ASSERT_TRUE(store_to_v1
->src
[1].is_ssa
);
426 ASSERT_TRUE(nir_src_is_const(store_to_v1
->src
[1]));
427 ASSERT_EQ(nir_src_comp_as_uint(store_to_v1
->src
[1], 1), 20);
431 EXPECT_TRUE(store_to_v1
);
434 TEST_F(nir_copy_prop_vars_test
, memory_barrier_in_two_blocks
)
436 nir_variable
**v
= create_many_int(nir_var_ssbo
, "v", 4);
438 nir_store_var(b
, v
[0], nir_imm_int(b
, 1), 1);
439 nir_store_var(b
, v
[1], nir_imm_int(b
, 2), 1);
441 /* Split into many blocks. */
442 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
444 nir_store_var(b
, v
[2], nir_load_var(b
, v
[0]), 1);
446 nir_builder_instr_insert(b
, &nir_intrinsic_instr_create(b
->shader
, nir_intrinsic_memory_barrier
)->instr
);
448 nir_store_var(b
, v
[3], nir_load_var(b
, v
[1]), 1);
450 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
451 ASSERT_TRUE(progress
);
453 /* Only the second load will remain after the optimization. */
454 ASSERT_EQ(1, count_intrinsics(nir_intrinsic_load_deref
));
455 nir_intrinsic_instr
*load
= NULL
;
456 load
= find_next_intrinsic(nir_intrinsic_load_deref
, load
);
457 ASSERT_EQ(nir_intrinsic_get_var(load
, 0), v
[1]);
460 TEST_F(nir_copy_prop_vars_test
, simple_store_load_in_two_blocks
)
462 nir_variable
**v
= create_many_ivec2(nir_var_function
, "v", 2);
463 unsigned mask
= 1 | 2;
465 nir_ssa_def
*stored_value
= nir_imm_ivec2(b
, 10, 20);
466 nir_store_var(b
, v
[0], stored_value
, mask
);
468 /* Adding an if statement will cause blocks to be created. */
469 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
471 nir_ssa_def
*read_value
= nir_load_var(b
, v
[0]);
472 nir_store_var(b
, v
[1], read_value
, mask
);
474 nir_validate_shader(b
->shader
, NULL
);
476 bool progress
= nir_opt_copy_prop_vars(b
->shader
);
477 EXPECT_TRUE(progress
);
479 nir_validate_shader(b
->shader
, NULL
);
481 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref
), 2);
483 nir_intrinsic_instr
*store
= NULL
;
484 for (int i
= 0; i
< 2; i
++) {
485 store
= find_next_intrinsic(nir_intrinsic_store_deref
, store
);
486 ASSERT_TRUE(store
->src
[1].is_ssa
);
487 EXPECT_EQ(store
->src
[1].ssa
, stored_value
);
491 TEST_F(nir_dead_write_vars_test
, no_dead_writes_in_block
)
493 nir_variable
**v
= create_many_int(nir_var_ssbo
, "v", 2);
495 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
497 bool progress
= nir_opt_dead_write_vars(b
->shader
);
498 ASSERT_FALSE(progress
);
501 TEST_F(nir_dead_write_vars_test
, no_dead_writes_different_components_in_block
)
503 nir_variable
**v
= create_many_ivec2(nir_var_ssbo
, "v", 3);
505 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1 << 0);
506 nir_store_var(b
, v
[0], nir_load_var(b
, v
[2]), 1 << 1);
508 bool progress
= nir_opt_dead_write_vars(b
->shader
);
509 ASSERT_FALSE(progress
);
512 TEST_F(nir_dead_write_vars_test
, no_dead_writes_in_if_statement
)
514 nir_variable
**v
= create_many_int(nir_var_ssbo
, "v", 6);
516 nir_store_var(b
, v
[2], nir_load_var(b
, v
[0]), 1);
517 nir_store_var(b
, v
[3], nir_load_var(b
, v
[1]), 1);
519 /* Each arm of the if statement will overwrite one store. */
520 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
521 nir_store_var(b
, v
[2], nir_load_var(b
, v
[4]), 1);
523 nir_push_else(b
, if_stmt
);
524 nir_store_var(b
, v
[3], nir_load_var(b
, v
[5]), 1);
526 nir_pop_if(b
, if_stmt
);
528 bool progress
= nir_opt_dead_write_vars(b
->shader
);
529 ASSERT_FALSE(progress
);
532 TEST_F(nir_dead_write_vars_test
, no_dead_writes_in_loop_statement
)
534 nir_variable
**v
= create_many_int(nir_var_ssbo
, "v", 3);
536 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
538 /* Loop will write other value. Since it might not be executed, it doesn't
539 * kill the first write.
541 nir_loop
*loop
= nir_push_loop(b
);
543 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
544 nir_jump(b
, nir_jump_break
);
545 nir_pop_if(b
, if_stmt
);
547 nir_store_var(b
, v
[0], nir_load_var(b
, v
[2]), 1);
548 nir_pop_loop(b
, loop
);
550 bool progress
= nir_opt_dead_write_vars(b
->shader
);
551 ASSERT_FALSE(progress
);
554 TEST_F(nir_dead_write_vars_test
, dead_write_in_block
)
556 nir_variable
**v
= create_many_int(nir_var_ssbo
, "v", 3);
558 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
559 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
560 nir_store_var(b
, v
[0], load_v2
, 1);
562 bool progress
= nir_opt_dead_write_vars(b
->shader
);
563 ASSERT_TRUE(progress
);
565 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
567 nir_intrinsic_instr
*store
= find_next_intrinsic(nir_intrinsic_store_deref
, NULL
);
568 ASSERT_TRUE(store
->src
[1].is_ssa
);
569 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
572 TEST_F(nir_dead_write_vars_test
, dead_write_components_in_block
)
574 nir_variable
**v
= create_many_ivec2(nir_var_ssbo
, "v", 3);
576 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1 << 0);
577 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
578 nir_store_var(b
, v
[0], load_v2
, 1 << 0);
580 bool progress
= nir_opt_dead_write_vars(b
->shader
);
581 ASSERT_TRUE(progress
);
583 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
585 nir_intrinsic_instr
*store
= find_next_intrinsic(nir_intrinsic_store_deref
, NULL
);
586 ASSERT_TRUE(store
->src
[1].is_ssa
);
587 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
591 /* TODO: The DISABLED tests below depend on the dead write removal be able to
592 * identify dead writes between multiple blocks. This is still not
596 TEST_F(nir_dead_write_vars_test
, DISABLED_dead_write_in_two_blocks
)
598 nir_variable
**v
= create_many_int(nir_var_ssbo
, "v", 3);
600 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
601 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
603 /* Causes the stores to be in different blocks. */
604 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
606 nir_store_var(b
, v
[0], load_v2
, 1);
608 bool progress
= nir_opt_dead_write_vars(b
->shader
);
609 ASSERT_TRUE(progress
);
611 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
613 nir_intrinsic_instr
*store
= find_next_intrinsic(nir_intrinsic_store_deref
, NULL
);
614 ASSERT_TRUE(store
->src
[1].is_ssa
);
615 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
618 TEST_F(nir_dead_write_vars_test
, DISABLED_dead_write_components_in_two_blocks
)
620 nir_variable
**v
= create_many_ivec2(nir_var_ssbo
, "v", 3);
622 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1 << 0);
624 /* Causes the stores to be in different blocks. */
625 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
627 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
628 nir_store_var(b
, v
[0], load_v2
, 1 << 0);
630 bool progress
= nir_opt_dead_write_vars(b
->shader
);
631 ASSERT_TRUE(progress
);
633 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref
));
635 nir_intrinsic_instr
*store
= find_next_intrinsic(nir_intrinsic_store_deref
, NULL
);
636 ASSERT_TRUE(store
->src
[1].is_ssa
);
637 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
640 TEST_F(nir_dead_write_vars_test
, DISABLED_dead_writes_in_if_statement
)
642 nir_variable
**v
= create_many_int(nir_var_ssbo
, "v", 4);
644 /* Both branches will overwrite, making the previous store dead. */
645 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
647 nir_if
*if_stmt
= nir_push_if(b
, nir_imm_int(b
, 0));
648 nir_ssa_def
*load_v2
= nir_load_var(b
, v
[2]);
649 nir_store_var(b
, v
[0], load_v2
, 1);
651 nir_push_else(b
, if_stmt
);
652 nir_ssa_def
*load_v3
= nir_load_var(b
, v
[3]);
653 nir_store_var(b
, v
[0], load_v3
, 1);
655 nir_pop_if(b
, if_stmt
);
657 bool progress
= nir_opt_dead_write_vars(b
->shader
);
658 ASSERT_TRUE(progress
);
659 EXPECT_EQ(2, count_intrinsics(nir_intrinsic_store_deref
));
661 nir_intrinsic_instr
*store
= NULL
;
662 store
= find_next_intrinsic(nir_intrinsic_store_deref
, store
);
663 ASSERT_TRUE(store
->src
[1].is_ssa
);
664 EXPECT_EQ(store
->src
[1].ssa
, load_v2
);
666 store
= find_next_intrinsic(nir_intrinsic_store_deref
, store
);
667 ASSERT_TRUE(store
->src
[1].is_ssa
);
668 EXPECT_EQ(store
->src
[1].ssa
, load_v3
);
671 TEST_F(nir_dead_write_vars_test
, DISABLED_memory_barrier_in_two_blocks
)
673 nir_variable
**v
= create_many_int(nir_var_ssbo
, "v", 2);
675 nir_store_var(b
, v
[0], nir_imm_int(b
, 1), 1);
676 nir_store_var(b
, v
[1], nir_imm_int(b
, 2), 1);
678 /* Split into many blocks. */
679 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
681 /* Because it is before the barrier, this will kill the previous store to that target. */
682 nir_store_var(b
, v
[0], nir_imm_int(b
, 3), 1);
684 nir_builder_instr_insert(b
, &nir_intrinsic_instr_create(b
->shader
, nir_intrinsic_memory_barrier
)->instr
);
686 nir_store_var(b
, v
[1], nir_imm_int(b
, 4), 1);
688 bool progress
= nir_opt_dead_write_vars(b
->shader
);
689 ASSERT_TRUE(progress
);
691 EXPECT_EQ(3, count_intrinsics(nir_intrinsic_store_deref
));
694 TEST_F(nir_dead_write_vars_test
, DISABLED_unrelated_barrier_in_two_blocks
)
696 nir_variable
**v
= create_many_int(nir_var_ssbo
, "v", 3);
697 nir_variable
*out
= create_int(nir_var_shader_out
, "out");
699 nir_store_var(b
, out
, nir_load_var(b
, v
[1]), 1);
700 nir_store_var(b
, v
[0], nir_load_var(b
, v
[1]), 1);
702 /* Split into many blocks. */
703 nir_pop_if(b
, nir_push_if(b
, nir_imm_int(b
, 0)));
705 /* Emit vertex will ensure writes to output variables are considered used,
706 * but should not affect other types of variables. */
708 nir_builder_instr_insert(b
, &nir_intrinsic_instr_create(b
->shader
, nir_intrinsic_emit_vertex
)->instr
);
710 nir_store_var(b
, out
, nir_load_var(b
, v
[2]), 1);
711 nir_store_var(b
, v
[0], nir_load_var(b
, v
[2]), 1);
713 bool progress
= nir_opt_dead_write_vars(b
->shader
);
714 ASSERT_TRUE(progress
);
716 /* Verify the first write to v[0] was removed. */
717 EXPECT_EQ(3, count_intrinsics(nir_intrinsic_store_deref
));
719 nir_intrinsic_instr
*store
= NULL
;
720 store
= find_next_intrinsic(nir_intrinsic_store_deref
, store
);
721 EXPECT_EQ(nir_intrinsic_get_var(store
, 0), out
);
722 store
= find_next_intrinsic(nir_intrinsic_store_deref
, store
);
723 EXPECT_EQ(nir_intrinsic_get_var(store
, 0), out
);
724 store
= find_next_intrinsic(nir_intrinsic_store_deref
, store
);
725 EXPECT_EQ(nir_intrinsic_get_var(store
, 0), v
[0]);