Re: [Mesa-dev] [PATCH v2.1 6/11] nir: Add an array splitting pass

2018-08-20 Thread Caio Marcelo de Oliveira Filho
On Mon, Jul 30, 2018 at 09:16:42AM -0700, Jason Ekstrand wrote:
> This pass looks for array variables where at least one level of the
> array is never indirected and splits it into multiple smaller variables.
> 
> This pass doesn't really do much now because nir_lower_vars_to_ssa can
> already see through arrays of arrays and can detect indirects on just
> one level or even see that arr[i][0][5] does not alias arr[i][1][j].
> This pass exists to help other passes more easily see through arrays of
> arrays.  If a back-end does implement arrays using scratch or indirects
> on registers, having more smaller arrays is likely to have better memory
> efficiency.
> 
> v2 (Jason Ekstrand):
>  - Better comments and naming (some from Caio)
>  - Rework to use one hash map instead of two

The rework reads better.  Thanks.


> v2.1 (Jason Ekstrand):
>  - Fix a couple of bugs that were added in the rework including one
>which basically prevented it from running
> ---
>  src/compiler/nir/nir.h|   1 +
>  src/compiler/nir/nir_split_vars.c | 583 ++
>  2 files changed, 584 insertions(+)


This patch is

Reviewed-by: Caio Marcelo de Oliveira Filho 

___
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/mesa-dev


[Mesa-dev] [PATCH v2.1 6/11] nir: Add an array splitting pass

2018-07-30 Thread Jason Ekstrand
This pass looks for array variables where at least one level of the
array is never indirected and splits it into multiple smaller variables.

This pass doesn't really do much now because nir_lower_vars_to_ssa can
already see through arrays of arrays and can detect indirects on just
one level or even see that arr[i][0][5] does not alias arr[i][1][j].
This pass exists to help other passes more easily see through arrays of
arrays.  If a back-end does implement arrays using scratch or indirects
on registers, having more smaller arrays is likely to have better memory
efficiency.

v2 (Jason Ekstrand):
 - Better comments and naming (some from Caio)
 - Rework to use one hash map instead of two

v2.1 (Jason Ekstrand):
 - Fix a couple of bugs that were added in the rework including one
   which basically prevented it from running
---
 src/compiler/nir/nir.h|   1 +
 src/compiler/nir/nir_split_vars.c | 583 ++
 2 files changed, 584 insertions(+)

diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 774de8b0eea..71e169b4be2 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -2610,6 +2610,7 @@ void nir_dump_cfg(nir_shader *shader, FILE *fp);
 
 int nir_gs_count_vertices(const nir_shader *shader);
 
+bool nir_split_array_vars(nir_shader *shader, nir_variable_mode modes);
 bool nir_split_var_copies(nir_shader *shader);
 bool nir_split_per_member_structs(nir_shader *shader);
 bool nir_split_struct_vars(nir_shader *shader, nir_variable_mode modes);
diff --git a/src/compiler/nir/nir_split_vars.c 
b/src/compiler/nir/nir_split_vars.c
index 1f59ac2f5e7..6f933419fd2 100644
--- a/src/compiler/nir/nir_split_vars.c
+++ b/src/compiler/nir/nir_split_vars.c
@@ -24,6 +24,7 @@
 #include "nir.h"
 #include "nir_builder.h"
 #include "nir_deref.h"
+#include "nir_vla.h"
 
 struct split_var_state {
void *mem_ctx;
@@ -57,6 +58,23 @@ wrap_type_in_array(const struct glsl_type *type,
return glsl_array_type(elem_type, glsl_get_length(array_type));
 }
 
+static int
+num_array_levels_in_array_of_vector_type(const struct glsl_type *type)
+{
+   int num_levels = 0;
+   while (true) {
+  if (glsl_type_is_array_or_matrix(type)) {
+ num_levels++;
+ type = glsl_get_array_element(type);
+  } else if (glsl_type_is_vector_or_scalar(type)) {
+ return num_levels;
+  } else {
+ /* Not an array of vectors */
+ return -1;
+  }
+   }
+}
+
 static void
 init_field_for_type(struct field *field, struct field *parent,
 const struct glsl_type *type,
@@ -269,3 +287,568 @@ nir_split_struct_vars(nir_shader *shader, 
nir_variable_mode modes)
 
return progress;
 }
+
+struct array_level_info {
+   unsigned array_len;
+   bool split;
+};
+
+struct array_split {
+   /* Only set if this is the tail end of the splitting */
+   nir_variable *var;
+
+   unsigned num_splits;
+   struct array_split *splits;
+};
+
+struct array_var_info {
+   nir_variable *base_var;
+
+   const struct glsl_type *split_var_type;
+
+   bool split_var;
+   struct array_split root_split;
+
+   unsigned num_levels;
+   struct array_level_info levels[0];
+};
+
+static bool
+init_var_list_array_infos(struct exec_list *vars,
+  struct hash_table *var_info_map,
+  void *mem_ctx)
+{
+   bool has_array = false;
+
+   nir_foreach_variable(var, vars) {
+  int num_levels = num_array_levels_in_array_of_vector_type(var->type);
+  if (num_levels <= 0)
+ continue;
+
+  struct array_var_info *info =
+ rzalloc_size(mem_ctx, sizeof(*info) +
+   num_levels * sizeof(info->levels[0]));
+
+  info->base_var = var;
+  info->num_levels = num_levels;
+
+  const struct glsl_type *type = var->type;
+  for (int i = 0; i < num_levels; i++) {
+ info->levels[i].array_len = glsl_get_length(type);
+ type = glsl_get_array_element(type);
+
+ /* All levels start out initially as split */
+ info->levels[i].split = true;
+  }
+
+  _mesa_hash_table_insert(var_info_map, var, info);
+  has_array = true;
+   }
+
+   return has_array;
+}
+
+static struct array_var_info *
+get_array_var_info(nir_variable *var,
+   struct hash_table *var_info_map)
+{
+   struct hash_entry *entry =
+  _mesa_hash_table_search(var_info_map, var);
+   return entry ? entry->data : NULL;
+}
+
+static struct array_var_info *
+get_array_deref_info(nir_deref_instr *deref,
+ struct hash_table *var_info_map,
+ nir_variable_mode modes)
+{
+   if (!(deref->mode & modes))
+  return NULL;
+
+   return get_array_var_info(nir_deref_instr_get_variable(deref),
+ var_info_map);
+}
+
+static void
+mark_array_deref_used(nir_deref_instr *deref,
+  struct hash_table *var_info_map,
+  nir_variable_mode modes,
+  void *mem_ct