nir: rename nir_var_private to nir_var_shader_temp
[mesa.git] / src / compiler / nir / tests / vars_tests.cpp
1 /*
2 * Copyright © 2018 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <gtest/gtest.h>
25
26 #include "nir.h"
27 #include "nir_builder.h"
28
29 namespace {
30
31 class nir_vars_test : public ::testing::Test {
32 protected:
33 nir_vars_test();
34 ~nir_vars_test();
35
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);
40 }
41
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);
47 }
48
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));
53 return result;
54 }
55
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));
60 return result;
61 }
62
63 unsigned count_intrinsics(nir_intrinsic_op intrinsic);
64
65 nir_intrinsic_instr *find_next_intrinsic(nir_intrinsic_op intrinsic,
66 nir_intrinsic_instr *after);
67
68 void *mem_ctx;
69 void *lin_ctx;
70
71 nir_builder *b;
72 };
73
74 nir_vars_test::nir_vars_test()
75 {
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);
81 }
82
83 nir_vars_test::~nir_vars_test()
84 {
85 if (HasFailure()) {
86 printf("\nShader from the failed test:\n\n");
87 nir_print_shader(b->shader, stdout);
88 }
89
90 ralloc_free(mem_ctx);
91 }
92
93 unsigned
94 nir_vars_test::count_intrinsics(nir_intrinsic_op intrinsic)
95 {
96 unsigned count = 0;
97 nir_foreach_block(block, b->impl) {
98 nir_foreach_instr(instr, block) {
99 if (instr->type != nir_instr_type_intrinsic)
100 continue;
101 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
102 if (intrin->intrinsic == intrinsic)
103 count++;
104 }
105 }
106 return count;
107 }
108
109 nir_intrinsic_instr *
110 nir_vars_test::find_next_intrinsic(nir_intrinsic_op intrinsic,
111 nir_intrinsic_instr *after)
112 {
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)
117 continue;
118 nir_foreach_instr(instr, block) {
119 if (instr->type != nir_instr_type_intrinsic)
120 continue;
121 nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
122 if (!seen) {
123 seen = (after == intrin);
124 continue;
125 }
126 if (intrin->intrinsic == intrinsic)
127 return intrin;
128 }
129 }
130 return NULL;
131 }
132
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 {};
137
138 } // namespace
139
140 TEST_F(nir_redundant_load_vars_test, duplicated_load)
141 {
142 /* Load a variable twice in the same block. One should be removed. */
143
144 nir_variable *in = create_int(nir_var_shader_in, "in");
145 nir_variable **out = create_many_int(nir_var_shader_out, "out", 2);
146
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);
149
150 nir_validate_shader(b->shader, NULL);
151
152 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 2);
153
154 bool progress = nir_opt_copy_prop_vars(b->shader);
155 EXPECT_TRUE(progress);
156
157 nir_validate_shader(b->shader, NULL);
158
159 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1);
160 }
161
162 TEST_F(nir_redundant_load_vars_test, duplicated_load_in_two_blocks)
163 {
164 /* Load a variable twice in different blocks. One should be removed. */
165
166 nir_variable *in = create_int(nir_var_shader_in, "in");
167 nir_variable **out = create_many_int(nir_var_shader_out, "out", 2);
168
169 nir_store_var(b, out[0], nir_load_var(b, in), 1);
170
171 /* Forces the stores to be in different blocks. */
172 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0)));
173
174 nir_store_var(b, out[1], nir_load_var(b, in), 1);
175
176 nir_validate_shader(b->shader, NULL);
177
178 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 2);
179
180 bool progress = nir_opt_copy_prop_vars(b->shader);
181 EXPECT_TRUE(progress);
182
183 nir_validate_shader(b->shader, NULL);
184
185 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 1);
186 }
187
188 TEST_F(nir_redundant_load_vars_test, invalidate_inside_if_block)
189 {
190 /* Load variables, then write to some of then in different branches of the
191 * if statement. They should be invalidated accordingly.
192 */
193
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);
196
197 nir_load_var(b, g[0]);
198 nir_load_var(b, g[1]);
199 nir_load_var(b, g[2]);
200
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);
203
204 nir_push_else(b, if_stmt);
205 nir_store_var(b, g[1], nir_imm_int(b, 20), 1);
206
207 nir_pop_if(b, if_stmt);
208
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);
212
213 nir_validate_shader(b->shader, NULL);
214
215 bool progress = nir_opt_copy_prop_vars(b->shader);
216 EXPECT_TRUE(progress);
217
218 /* There are 3 initial loads, plus 2 loads for the values invalidated
219 * inside the if statement.
220 */
221 ASSERT_EQ(count_intrinsics(nir_intrinsic_load_deref), 5);
222
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])
229 g2_load_count++;
230 }
231 EXPECT_EQ(g2_load_count, 1);
232 }
233
234 TEST_F(nir_redundant_load_vars_test, invalidate_live_load_in_the_end_of_loop)
235 {
236 /* Invalidating a load in the end of loop body will apply to the whole loop
237 * body.
238 */
239
240 nir_variable *v = create_int(nir_var_ssbo, "v");
241
242 nir_load_var(b, v);
243
244 nir_loop *loop = nir_push_loop(b);
245
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);
249
250 nir_load_var(b, v);
251 nir_store_var(b, v, nir_imm_int(b, 10), 1);
252
253 nir_pop_loop(b, loop);
254
255 bool progress = nir_opt_copy_prop_vars(b->shader);
256 ASSERT_FALSE(progress);
257 }
258
259 TEST_F(nir_copy_prop_vars_test, simple_copies)
260 {
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");
264
265 nir_copy_var(b, temp, in);
266 nir_copy_var(b, out, temp);
267
268 nir_validate_shader(b->shader, NULL);
269
270 bool progress = nir_opt_copy_prop_vars(b->shader);
271 EXPECT_TRUE(progress);
272
273 nir_validate_shader(b->shader, NULL);
274
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;
279
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);
283 }
284
285 TEST_F(nir_copy_prop_vars_test, simple_store_load)
286 {
287 nir_variable **v = create_many_ivec2(nir_var_function, "v", 2);
288 unsigned mask = 1 | 2;
289
290 nir_ssa_def *stored_value = nir_imm_ivec2(b, 10, 20);
291 nir_store_var(b, v[0], stored_value, mask);
292
293 nir_ssa_def *read_value = nir_load_var(b, v[0]);
294 nir_store_var(b, v[1], read_value, mask);
295
296 nir_validate_shader(b->shader, NULL);
297
298 bool progress = nir_opt_copy_prop_vars(b->shader);
299 EXPECT_TRUE(progress);
300
301 nir_validate_shader(b->shader, NULL);
302
303 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 2);
304
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);
310 }
311 }
312
313 TEST_F(nir_copy_prop_vars_test, store_store_load)
314 {
315 nir_variable **v = create_many_ivec2(nir_var_function, "v", 2);
316 unsigned mask = 1 | 2;
317
318 nir_ssa_def *first_value = nir_imm_ivec2(b, 10, 20);
319 nir_store_var(b, v[0], first_value, mask);
320
321 nir_ssa_def *second_value = nir_imm_ivec2(b, 30, 40);
322 nir_store_var(b, v[0], second_value, mask);
323
324 nir_ssa_def *read_value = nir_load_var(b, v[0]);
325 nir_store_var(b, v[1], read_value, mask);
326
327 nir_validate_shader(b->shader, NULL);
328
329 bool progress = nir_opt_copy_prop_vars(b->shader);
330 EXPECT_TRUE(progress);
331
332 nir_validate_shader(b->shader, NULL);
333
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);
340 break;
341 }
342 }
343 EXPECT_TRUE(store_to_v1);
344 }
345
346 TEST_F(nir_copy_prop_vars_test, store_store_load_different_components)
347 {
348 nir_variable **v = create_many_ivec2(nir_var_function, "v", 2);
349
350 nir_ssa_def *first_value = nir_imm_ivec2(b, 10, 20);
351 nir_store_var(b, v[0], first_value, 1 << 1);
352
353 nir_ssa_def *second_value = nir_imm_ivec2(b, 30, 40);
354 nir_store_var(b, v[0], second_value, 1 << 0);
355
356 nir_ssa_def *read_value = nir_load_var(b, v[0]);
357 nir_store_var(b, v[1], read_value, 1 << 1);
358
359 nir_validate_shader(b->shader, NULL);
360
361 bool progress = nir_opt_copy_prop_vars(b->shader);
362 EXPECT_TRUE(progress);
363
364 nir_validate_shader(b->shader, NULL);
365
366 nir_opt_constant_folding(b->shader);
367 nir_validate_shader(b->shader, NULL);
368
369 /* Store to v[1] should use first_value directly. The write of
370 * second_value did not overwrite the component it uses.
371 */
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);
376
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);
379 break;
380 }
381 }
382 EXPECT_TRUE(store_to_v1);
383 }
384
385 TEST_F(nir_copy_prop_vars_test, store_store_load_different_components_in_many_blocks)
386 {
387 nir_variable **v = create_many_ivec2(nir_var_function, "v", 2);
388
389 nir_ssa_def *first_value = nir_imm_ivec2(b, 10, 20);
390 nir_store_var(b, v[0], first_value, 1 << 1);
391
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)));
394
395 nir_ssa_def *second_value = nir_imm_ivec2(b, 30, 40);
396 nir_store_var(b, v[0], second_value, 1 << 0);
397
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)));
400
401 nir_ssa_def *read_value = nir_load_var(b, v[0]);
402 nir_store_var(b, v[1], read_value, 1 << 1);
403
404 nir_validate_shader(b->shader, NULL);
405
406 nir_print_shader(b->shader, stdout);
407
408 bool progress = nir_opt_copy_prop_vars(b->shader);
409 EXPECT_TRUE(progress);
410
411 nir_print_shader(b->shader, stdout);
412
413 nir_validate_shader(b->shader, NULL);
414
415 nir_opt_constant_folding(b->shader);
416 nir_validate_shader(b->shader, NULL);
417
418 /* Store to v[1] should use first_value directly. The write of
419 * second_value did not overwrite the component it uses.
420 */
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);
425
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);
428 break;
429 }
430 }
431 EXPECT_TRUE(store_to_v1);
432 }
433
434 TEST_F(nir_copy_prop_vars_test, memory_barrier_in_two_blocks)
435 {
436 nir_variable **v = create_many_int(nir_var_ssbo, "v", 4);
437
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);
440
441 /* Split into many blocks. */
442 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0)));
443
444 nir_store_var(b, v[2], nir_load_var(b, v[0]), 1);
445
446 nir_builder_instr_insert(b, &nir_intrinsic_instr_create(b->shader, nir_intrinsic_memory_barrier)->instr);
447
448 nir_store_var(b, v[3], nir_load_var(b, v[1]), 1);
449
450 bool progress = nir_opt_copy_prop_vars(b->shader);
451 ASSERT_TRUE(progress);
452
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]);
458 }
459
460 TEST_F(nir_copy_prop_vars_test, simple_store_load_in_two_blocks)
461 {
462 nir_variable **v = create_many_ivec2(nir_var_function, "v", 2);
463 unsigned mask = 1 | 2;
464
465 nir_ssa_def *stored_value = nir_imm_ivec2(b, 10, 20);
466 nir_store_var(b, v[0], stored_value, mask);
467
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)));
470
471 nir_ssa_def *read_value = nir_load_var(b, v[0]);
472 nir_store_var(b, v[1], read_value, mask);
473
474 nir_validate_shader(b->shader, NULL);
475
476 bool progress = nir_opt_copy_prop_vars(b->shader);
477 EXPECT_TRUE(progress);
478
479 nir_validate_shader(b->shader, NULL);
480
481 ASSERT_EQ(count_intrinsics(nir_intrinsic_store_deref), 2);
482
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);
488 }
489 }
490
491 TEST_F(nir_dead_write_vars_test, no_dead_writes_in_block)
492 {
493 nir_variable **v = create_many_int(nir_var_ssbo, "v", 2);
494
495 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1);
496
497 bool progress = nir_opt_dead_write_vars(b->shader);
498 ASSERT_FALSE(progress);
499 }
500
501 TEST_F(nir_dead_write_vars_test, no_dead_writes_different_components_in_block)
502 {
503 nir_variable **v = create_many_ivec2(nir_var_ssbo, "v", 3);
504
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);
507
508 bool progress = nir_opt_dead_write_vars(b->shader);
509 ASSERT_FALSE(progress);
510 }
511
512 TEST_F(nir_dead_write_vars_test, no_dead_writes_in_if_statement)
513 {
514 nir_variable **v = create_many_int(nir_var_ssbo, "v", 6);
515
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);
518
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);
522
523 nir_push_else(b, if_stmt);
524 nir_store_var(b, v[3], nir_load_var(b, v[5]), 1);
525
526 nir_pop_if(b, if_stmt);
527
528 bool progress = nir_opt_dead_write_vars(b->shader);
529 ASSERT_FALSE(progress);
530 }
531
532 TEST_F(nir_dead_write_vars_test, no_dead_writes_in_loop_statement)
533 {
534 nir_variable **v = create_many_int(nir_var_ssbo, "v", 3);
535
536 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1);
537
538 /* Loop will write other value. Since it might not be executed, it doesn't
539 * kill the first write.
540 */
541 nir_loop *loop = nir_push_loop(b);
542
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);
546
547 nir_store_var(b, v[0], nir_load_var(b, v[2]), 1);
548 nir_pop_loop(b, loop);
549
550 bool progress = nir_opt_dead_write_vars(b->shader);
551 ASSERT_FALSE(progress);
552 }
553
554 TEST_F(nir_dead_write_vars_test, dead_write_in_block)
555 {
556 nir_variable **v = create_many_int(nir_var_ssbo, "v", 3);
557
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);
561
562 bool progress = nir_opt_dead_write_vars(b->shader);
563 ASSERT_TRUE(progress);
564
565 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref));
566
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);
570 }
571
572 TEST_F(nir_dead_write_vars_test, dead_write_components_in_block)
573 {
574 nir_variable **v = create_many_ivec2(nir_var_ssbo, "v", 3);
575
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);
579
580 bool progress = nir_opt_dead_write_vars(b->shader);
581 ASSERT_TRUE(progress);
582
583 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref));
584
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);
588 }
589
590
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
593 * implemented.
594 */
595
596 TEST_F(nir_dead_write_vars_test, DISABLED_dead_write_in_two_blocks)
597 {
598 nir_variable **v = create_many_int(nir_var_ssbo, "v", 3);
599
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]);
602
603 /* Causes the stores to be in different blocks. */
604 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0)));
605
606 nir_store_var(b, v[0], load_v2, 1);
607
608 bool progress = nir_opt_dead_write_vars(b->shader);
609 ASSERT_TRUE(progress);
610
611 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref));
612
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);
616 }
617
618 TEST_F(nir_dead_write_vars_test, DISABLED_dead_write_components_in_two_blocks)
619 {
620 nir_variable **v = create_many_ivec2(nir_var_ssbo, "v", 3);
621
622 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1 << 0);
623
624 /* Causes the stores to be in different blocks. */
625 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0)));
626
627 nir_ssa_def *load_v2 = nir_load_var(b, v[2]);
628 nir_store_var(b, v[0], load_v2, 1 << 0);
629
630 bool progress = nir_opt_dead_write_vars(b->shader);
631 ASSERT_TRUE(progress);
632
633 EXPECT_EQ(1, count_intrinsics(nir_intrinsic_store_deref));
634
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);
638 }
639
640 TEST_F(nir_dead_write_vars_test, DISABLED_dead_writes_in_if_statement)
641 {
642 nir_variable **v = create_many_int(nir_var_ssbo, "v", 4);
643
644 /* Both branches will overwrite, making the previous store dead. */
645 nir_store_var(b, v[0], nir_load_var(b, v[1]), 1);
646
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);
650
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);
654
655 nir_pop_if(b, if_stmt);
656
657 bool progress = nir_opt_dead_write_vars(b->shader);
658 ASSERT_TRUE(progress);
659 EXPECT_EQ(2, count_intrinsics(nir_intrinsic_store_deref));
660
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);
665
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);
669 }
670
671 TEST_F(nir_dead_write_vars_test, DISABLED_memory_barrier_in_two_blocks)
672 {
673 nir_variable **v = create_many_int(nir_var_ssbo, "v", 2);
674
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);
677
678 /* Split into many blocks. */
679 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0)));
680
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);
683
684 nir_builder_instr_insert(b, &nir_intrinsic_instr_create(b->shader, nir_intrinsic_memory_barrier)->instr);
685
686 nir_store_var(b, v[1], nir_imm_int(b, 4), 1);
687
688 bool progress = nir_opt_dead_write_vars(b->shader);
689 ASSERT_TRUE(progress);
690
691 EXPECT_EQ(3, count_intrinsics(nir_intrinsic_store_deref));
692 }
693
694 TEST_F(nir_dead_write_vars_test, DISABLED_unrelated_barrier_in_two_blocks)
695 {
696 nir_variable **v = create_many_int(nir_var_ssbo, "v", 3);
697 nir_variable *out = create_int(nir_var_shader_out, "out");
698
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);
701
702 /* Split into many blocks. */
703 nir_pop_if(b, nir_push_if(b, nir_imm_int(b, 0)));
704
705 /* Emit vertex will ensure writes to output variables are considered used,
706 * but should not affect other types of variables. */
707
708 nir_builder_instr_insert(b, &nir_intrinsic_instr_create(b->shader, nir_intrinsic_emit_vertex)->instr);
709
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);
712
713 bool progress = nir_opt_dead_write_vars(b->shader);
714 ASSERT_TRUE(progress);
715
716 /* Verify the first write to v[0] was removed. */
717 EXPECT_EQ(3, count_intrinsics(nir_intrinsic_store_deref));
718
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]);
726 }