nir/test: add split vars tests (v2)
authorDave Airlie <airlied@redhat.com>
Mon, 13 May 2019 04:19:15 +0000 (14:19 +1000)
committerDave Airlie <airlied@redhat.com>
Tue, 21 May 2019 03:43:28 +0000 (13:43 +1000)
This just adds some split var splitting tests, it verifies
by counting derefs and local vars.

a basic load from inputs, store to array,
same as before but with a shader temp
struct { float } [4] don't split test
a basic load from inputs, with some out of band loads.
a load/store of only half the array
two level array, load from inputs store to all levels
a basic load from inputs with an indirect store to array.
two level array, indirect store to lvl 0
two level array, indirect store to lvl 1
load from inputs, store to array twice
load from input, store to array, load from array, store to another array.
load and from input and copy deref to array
create wildcard derefs, and do a copy

v2: use array_imm helpers, move derefs out of loops,
rename toplevel/secondlevel, use ints, fix lvl1 don't split test,
rename globabls to shader_temp, add comment, check the derefs type

Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
src/compiler/nir/tests/vars_tests.cpp

index 06e5dbc8ba7a1198e2d9b233890376fa40ff211c..25be8dbba167bdc2e3c611c4a704b998a7afcd23 100644 (file)
@@ -74,11 +74,21 @@ protected:
       return result;
    }
 
+   unsigned count_derefs(nir_deref_type deref_type);
    unsigned count_intrinsics(nir_intrinsic_op intrinsic);
+   unsigned count_function_temp_vars(void) {
+      return exec_list_length(&b->impl->locals);
+   }
+
+   unsigned count_shader_temp_vars(void) {
+      return exec_list_length(&b->shader->globals);
+   }
 
    nir_intrinsic_instr *get_intrinsic(nir_intrinsic_op intrinsic,
                                       unsigned index);
 
+   nir_deref_instr *get_deref(nir_deref_type deref_type,
+                              unsigned index);
    void *mem_ctx;
    void *lin_ctx;
 
@@ -120,6 +130,22 @@ nir_vars_test::count_intrinsics(nir_intrinsic_op intrinsic)
    return count;
 }
 
+unsigned
+nir_vars_test::count_derefs(nir_deref_type deref_type)
+{
+   unsigned count = 0;
+   nir_foreach_block(block, b->impl) {
+      nir_foreach_instr(instr, block) {
+         if (instr->type != nir_instr_type_deref)
+            continue;
+         nir_deref_instr *intrin = nir_instr_as_deref(instr);
+         if (intrin->deref_type == deref_type)
+            count++;
+      }
+   }
+   return count;
+}
+
 nir_intrinsic_instr *
 nir_vars_test::get_intrinsic(nir_intrinsic_op intrinsic,
                              unsigned index)
@@ -139,12 +165,31 @@ nir_vars_test::get_intrinsic(nir_intrinsic_op intrinsic,
    return NULL;
 }
 
+nir_deref_instr *
+nir_vars_test::get_deref(nir_deref_type deref_type,
+                         unsigned index)
+{
+   nir_foreach_block(block, b->impl) {
+      nir_foreach_instr(instr, block) {
+         if (instr->type != nir_instr_type_deref)
+            continue;
+         nir_deref_instr *deref = nir_instr_as_deref(instr);
+         if (deref->deref_type == deref_type) {
+            if (index == 0)
+               return deref;
+            index--;
+         }
+      }
+   }
+   return NULL;
+}
+
 /* Allow grouping the tests while still sharing the helpers. */
 class nir_redundant_load_vars_test : public nir_vars_test {};
 class nir_copy_prop_vars_test : public nir_vars_test {};
 class nir_dead_write_vars_test : public nir_vars_test {};
 class nir_combine_stores_test : public nir_vars_test {};
-
+class nir_split_vars_test : public nir_vars_test {};
 } // namespace
 
 TEST_F(nir_redundant_load_vars_test, duplicated_load)
@@ -1118,3 +1163,376 @@ TEST_F(nir_combine_stores_test, direct_array_derefs)
    ASSERT_EQ(nir_intrinsic_get_var(load_for_w, 0), s[1]);
    ASSERT_EQ(vec->src[3].swizzle[0], 0);
 }
+
+TEST_F(nir_split_vars_test, simple_split)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 4);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                   "temp");
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+   for (int i = 0; i < 4; i++)
+      nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 4);
+   ASSERT_EQ(count_function_temp_vars(), 1);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 0);
+   ASSERT_EQ(count_function_temp_vars(), 4);
+}
+
+TEST_F(nir_split_vars_test, simple_no_split_array_struct)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 4);
+   struct glsl_struct_field field;
+
+   field.type = glsl_float_type();
+   field.name = ralloc_asprintf(b, "field1");
+   field.location = -1;
+   field.offset = 0;
+
+   const struct glsl_type *st_type = glsl_struct_type(&field, 1, "struct", false);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(st_type, 4, 0),
+                                   "temp");
+
+   nir_variable *temp2 = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0), "temp2");
+
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+   nir_deref_instr *temp2_deref = nir_build_deref_var(b, temp2);
+   for (int i = 0; i < 4; i++)
+      nir_store_deref(b, nir_build_deref_array_imm(b, temp2_deref, i), nir_load_var(b, in[i]), 1);
+
+   for (int i = 0; i < 4; i++)
+      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);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 8);
+   ASSERT_EQ(count_derefs(nir_deref_type_struct), 4);
+   ASSERT_EQ(count_function_temp_vars(), 2);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 4);
+   ASSERT_EQ(count_derefs(nir_deref_type_struct), 4);
+   for (int i = 0; i < 4; i++) {
+      nir_deref_instr *deref = get_deref(nir_deref_type_array, i);
+      ASSERT_TRUE(deref);
+      ASSERT_TRUE(glsl_type_is_struct(deref->type));
+   }
+
+   ASSERT_EQ(count_function_temp_vars(), 5);
+}
+
+TEST_F(nir_split_vars_test, simple_split_shader_temp)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 4);
+   nir_variable *temp = create_var(nir_var_shader_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                   "temp");
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+
+   for (int i = 0; i < 4; i++)
+      nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 4);
+   ASSERT_EQ(count_shader_temp_vars(), 1);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_shader_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 0);
+   ASSERT_EQ(count_shader_temp_vars(), 4);
+}
+
+TEST_F(nir_split_vars_test, simple_oob)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 6);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                   "temp");
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+
+   for (int i = 0; i < 6; i++)
+      nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 6);
+   ASSERT_EQ(count_function_temp_vars(), 1);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 0);
+   ASSERT_EQ(count_function_temp_vars(), 4);
+}
+
+TEST_F(nir_split_vars_test, simple_unused)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 2);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                   "temp");
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+
+   for (int i = 0; i < 2; i++)
+      nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 2);
+   ASSERT_EQ(count_function_temp_vars(), 1);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 0);
+   /* this pass doesn't remove the unused ones */
+   ASSERT_EQ(count_function_temp_vars(), 4);
+}
+
+TEST_F(nir_split_vars_test, two_level_split)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 4);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_array_type(glsl_int_type(), 4, 0), 4, 0),
+                                   "temp");
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+   for (int i = 0; i < 4; i++) {
+      nir_deref_instr *level0 = nir_build_deref_array_imm(b, temp_deref, i);
+      for (int j = 0; j < 4; j++) {
+         nir_deref_instr *level1 = nir_build_deref_array_imm(b, level0, j);
+         nir_store_deref(b, level1, nir_load_var(b, in[i]), 1);
+      }
+   }
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 20);
+   ASSERT_EQ(count_function_temp_vars(), 1);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 0);
+   ASSERT_EQ(count_function_temp_vars(), 16);
+}
+
+TEST_F(nir_split_vars_test, simple_dont_split)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 4);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                   "temp");
+   nir_variable *ind = create_int(nir_var_shader_in, "ind");
+
+   nir_deref_instr *ind_deref = nir_build_deref_var(b, ind);
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+
+   for (int i = 0; i < 4; i++)
+      nir_store_deref(b, nir_build_deref_array(b, temp_deref, &ind_deref->dest.ssa), nir_load_var(b, in[i]), 1);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 4);
+   ASSERT_EQ(count_function_temp_vars(), 1);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_FALSE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 4);
+   ASSERT_EQ(count_function_temp_vars(), 1);
+}
+
+TEST_F(nir_split_vars_test, twolevel_dont_split_lvl_0)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 4);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_array_type(glsl_int_type(), 6, 0), 4, 0),
+                                   "temp");
+   nir_variable *ind = create_int(nir_var_shader_in, "ind");
+
+   nir_deref_instr *ind_deref = nir_build_deref_var(b, ind);
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+
+   for (int i = 0; i < 4; i++) {
+      nir_deref_instr *level0 = nir_build_deref_array(b, temp_deref, &ind_deref->dest.ssa);
+      for (int j = 0; j < 6; j++) {
+         nir_deref_instr *level1 = nir_build_deref_array_imm(b, level0, j);
+         nir_store_deref(b, level1, nir_load_var(b, in[i]), 1);
+      }
+   }
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 28);
+   ASSERT_EQ(count_function_temp_vars(), 1);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 24);
+   ASSERT_EQ(count_function_temp_vars(), 6);
+}
+
+TEST_F(nir_split_vars_test, twolevel_dont_split_lvl_1)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 6);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_array_type(glsl_int_type(), 6, 0), 4, 0),
+                                   "temp");
+   nir_variable *ind = create_int(nir_var_shader_in, "ind");
+
+   nir_deref_instr *ind_deref = nir_build_deref_var(b, ind);
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+
+   for (int i = 0; i < 4; i++) {
+      nir_deref_instr *level0 = nir_build_deref_array_imm(b, temp_deref, i);
+      for (int j = 0; j < 6; j++) {
+         /* just add the inner index to get some different derefs */
+         nir_deref_instr *level1 = nir_build_deref_array(b, level0, nir_iadd(b, &ind_deref->dest.ssa, nir_imm_int(b, j)));
+         nir_store_deref(b, level1, nir_load_var(b, in[i]), 1);
+      }
+   }
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 28);
+   ASSERT_EQ(count_function_temp_vars(), 1);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 24);
+   ASSERT_EQ(count_function_temp_vars(), 4);
+}
+
+TEST_F(nir_split_vars_test, split_multiple_store)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 4);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                   "temp");
+   nir_variable *temp2 = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                    "temp2");
+
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+   nir_deref_instr *temp2_deref = nir_build_deref_var(b, temp2);
+
+   for (int i = 0; i < 4; i++)
+      nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1);
+
+   for (int i = 0; i < 4; i++)
+      nir_store_deref(b, nir_build_deref_array_imm(b, temp2_deref, i), nir_load_var(b, in[i]), 1);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 8);
+   ASSERT_EQ(count_function_temp_vars(), 2);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 0);
+   ASSERT_EQ(count_function_temp_vars(), 8);
+}
+
+TEST_F(nir_split_vars_test, split_load_store)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 4);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                   "temp");
+   nir_variable *temp2 = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                    "temp2");
+
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+   nir_deref_instr *temp2_deref = nir_build_deref_var(b, temp2);
+
+   for (int i = 0; i < 4; i++)
+      nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1);
+
+   for (int i = 0; i < 4; i++) {
+      nir_deref_instr *store_deref = nir_build_deref_array_imm(b, temp2_deref, i);
+      nir_deref_instr *load_deref = nir_build_deref_array_imm(b, temp_deref, i);
+      nir_store_deref(b, store_deref, nir_load_deref(b, load_deref), 1);
+   }
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 12);
+   ASSERT_EQ(count_function_temp_vars(), 2);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 0);
+   ASSERT_EQ(count_function_temp_vars(), 8);
+}
+
+TEST_F(nir_split_vars_test, split_copy)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 4);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                   "temp");
+   nir_variable *temp2 = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                    "temp2");
+
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+   nir_deref_instr *temp2_deref = nir_build_deref_var(b, temp2);
+
+   for (int i = 0; i < 4; i++)
+      nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1);
+
+   for (int i = 0; i < 4; i++) {
+      nir_deref_instr *store_deref = nir_build_deref_array_imm(b, temp2_deref, i);
+      nir_deref_instr *load_deref = nir_build_deref_array_imm(b, temp_deref, i);
+      nir_copy_deref(b, store_deref, load_deref);
+   }
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 12);
+   ASSERT_EQ(count_function_temp_vars(), 2);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 0);
+   ASSERT_EQ(count_function_temp_vars(), 8);
+}
+
+TEST_F(nir_split_vars_test, split_wildcard_copy)
+{
+   nir_variable **in = create_many_int(nir_var_shader_in, "in", 4);
+   nir_variable *temp = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                   "temp");
+   nir_variable *temp2 = create_var(nir_var_function_temp, glsl_array_type(glsl_int_type(), 4, 0),
+                                    "temp2");
+
+   nir_deref_instr *temp_deref = nir_build_deref_var(b, temp);
+   nir_deref_instr *temp2_deref = nir_build_deref_var(b, temp2);
+
+   for (int i = 0; i < 4; i++)
+      nir_store_deref(b, nir_build_deref_array_imm(b, temp_deref, i), nir_load_var(b, in[i]), 1);
+
+   nir_deref_instr *src_wildcard = nir_build_deref_array_wildcard(b, temp_deref);
+   nir_deref_instr *dst_wildcard = nir_build_deref_array_wildcard(b, temp2_deref);
+
+   nir_copy_deref(b, dst_wildcard, src_wildcard);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 4);
+   ASSERT_EQ(count_derefs(nir_deref_type_array_wildcard), 2);
+   ASSERT_EQ(count_function_temp_vars(), 2);
+   ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref), 1);
+
+   bool progress = nir_split_array_vars(b->shader, nir_var_function_temp);
+   EXPECT_TRUE(progress);
+
+   nir_validate_shader(b->shader, NULL);
+   ASSERT_EQ(count_derefs(nir_deref_type_array), 0);
+   ASSERT_EQ(count_derefs(nir_deref_type_array_wildcard), 0);
+   ASSERT_EQ(count_function_temp_vars(), 8);
+   ASSERT_EQ(count_intrinsics(nir_intrinsic_copy_deref), 4);
+}