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