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