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
29namespace {
30
31class nir_vars_test : public ::testing::Test {
32protected:
33   nir_vars_test();
34   ~nir_vars_test();
35
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
44   nir_variable *create_int(nir_variable_mode mode, const char *name) {
45      return create_var(mode, glsl_int_type(), name);
46   }
47
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
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
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
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
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);
79   unsigned count_function_temp_vars(void) {
80      return exec_list_length(&b->impl->locals);
81   }
82
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
100nir_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
111nir_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
123unsigned
124nir_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
139unsigned
140nir_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
155nir_intrinsic_instr *
156nir_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
174nir_deref_instr *
175nir_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. */
194class nir_redundant_load_vars_test : public nir_vars_test {};
195class nir_copy_prop_vars_test : public nir_vars_test {};
196class nir_dead_write_vars_test : public nir_vars_test {};
197class nir_combine_stores_test : public nir_vars_test {};
198class nir_split_vars_test : public nir_vars_test {};
199class nir_remove_dead_variables_test : public nir_vars_test {};
200
201} // namespace
202
203static nir_ssa_def *
204nir_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
210static void
211nir_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
218TEST_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
240TEST_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
275TEST_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
301TEST_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
346TEST_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
371TEST_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
398TEST_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
414TEST_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
441TEST_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
471TEST_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
504TEST_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
543TEST_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
583TEST_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
614TEST_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
640TEST_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
657TEST_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
676TEST_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
717TEST_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
734TEST_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
753TEST_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
789TEST_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
807TEST_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
827TEST_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
871TEST_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
888TEST_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
908TEST_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
945TEST_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
970TEST_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
996TEST_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
1021TEST_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
1047TEST_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
1077TEST_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
1113TEST_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
1137TEST_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
1171TEST_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
1216TEST_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
1253TEST_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
1291TEST_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
1330TEST_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
1377TEST_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
1416TEST_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
1460TEST_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
1510TEST_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
1552TEST_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
1562TEST_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
1573TEST_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
1593TEST_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
1615TEST_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
1635TEST_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
1657TEST_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
1675TEST_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
1699TEST_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
1721TEST_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
1743TEST_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
1773TEST_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
1797TEST_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
1832TEST_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
1868TEST_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
1917TEST_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
1985static int64_t
1986vec_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
1997TEST_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
2038TEST_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
2059TEST_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
2104TEST_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
2126TEST_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
2148TEST_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
2171TEST_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
2197TEST_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
2222TEST_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
2252TEST_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
2283TEST_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
2312TEST_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
2344TEST_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
2376TEST_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
2411TEST_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
2434TEST_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