Mesa (main): nir/shrink_vectors: shrink vecN properly

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Jul 26 09:59:26 UTC 2021


Module: Mesa
Branch: main
Commit: bc500da67d3544af821d8b088760db251fb6a42e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=bc500da67d3544af821d8b088760db251fb6a42e

Author: Daniel Schürmann <daniel at schuermann.dev>
Date:   Mon Jul 12 11:00:29 2021 +0200

nir/shrink_vectors: shrink vecN properly

This patch allows to shrink vecN instructions where
one or more components at any position are unused.

Stat changes for softpipe:
total instructions in shared programs: 2986101 -> 2985416 (-0.02%)
instructions in affected programs: 51216 -> 50531 (-1.34%)

Reviewed-by: Emma Anholt <emma at anholt.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11411>

---

 src/compiler/nir/nir_opt_shrink_vectors.c | 128 ++++++++++++++----------------
 1 file changed, 61 insertions(+), 67 deletions(-)

diff --git a/src/compiler/nir/nir_opt_shrink_vectors.c b/src/compiler/nir/nir_opt_shrink_vectors.c
index c1283d335e3..614f36c3541 100644
--- a/src/compiler/nir/nir_opt_shrink_vectors.c
+++ b/src/compiler/nir/nir_opt_shrink_vectors.c
@@ -79,28 +79,58 @@ opt_shrink_vectors_alu(nir_builder *b, nir_alu_instr *instr)
    if (def->num_components == 1)
       return false;
 
-   if (nir_op_infos[instr->op].output_size == 0) {
-      /* don't remove any channels if used by an intrinsic */
-      nir_foreach_use_safe(use_src, def) {
-         if (use_src->parent_instr->type == nir_instr_type_intrinsic)
+   bool is_vec = false;
+   switch (instr->op) {
+      /* don't use nir_op_is_vec() as not all vector sizes are supported. */
+      case nir_op_vec4:
+      case nir_op_vec3:
+      case nir_op_vec2:
+         is_vec = true;
+         break;
+      default:
+         if (nir_op_infos[instr->op].output_size != 0)
             return false;
-      }
+         break;
+   }
 
-      unsigned mask = nir_ssa_def_components_read(def);
-      unsigned last_bit = util_last_bit(mask);
-      unsigned num_components = util_bitcount(mask);
-      if (mask == 0 || num_components == def->num_components)
+   /* don't remove any channels if used by an intrinsic */
+   nir_foreach_use(use_src, def) {
+      if (use_src->parent_instr->type == nir_instr_type_intrinsic)
          return false;
+   }
 
-      const bool is_bitfield_mask = last_bit == num_components;
+   unsigned mask = nir_ssa_def_components_read(def);
+   unsigned last_bit = util_last_bit(mask);
+   unsigned num_components = util_bitcount(mask);
 
-      if (is_bitfield_mask) {
-         /* just reduce the number of components and return */
-         def->num_components = num_components;
-         instr->dest.write_mask = mask;
-         return true;
+   /* return, if there is nothing to do */
+   if (mask == 0 || num_components == def->num_components)
+      return false;
+
+   const bool is_bitfield_mask = last_bit == num_components;
+
+   if (is_vec) {
+      /* replace vecN with smaller version */
+      nir_ssa_def *srcs[NIR_MAX_VEC_COMPONENTS] = { 0 };
+      unsigned index = 0;
+      for (int i = 0; i < last_bit; i++) {
+         if ((mask >> i) & 0x1)
+            srcs[index++] = nir_ssa_for_alu_src(b, instr, i);
       }
+      assert(index == num_components);
+      nir_ssa_def *new_vec = nir_vec(b, srcs, num_components);
+      nir_ssa_def_rewrite_uses(def, new_vec);
+      def = new_vec;
+   }
 
+   if (is_bitfield_mask) {
+      /* just reduce the number of components and return */
+      def->num_components = num_components;
+      instr->dest.write_mask = mask;
+      return true;
+   }
+
+   if (!is_vec) {
       /* update sources */
       for (int i = 0; i < nir_op_infos[instr->op].num_inputs; i++) {
          unsigned index = 0;
@@ -111,65 +141,29 @@ opt_shrink_vectors_alu(nir_builder *b, nir_alu_instr *instr)
          assert(index == num_components);
       }
 
-      /* compute new dest swizzles */
-      uint8_t reswizzle[NIR_MAX_VEC_COMPONENTS] = { 0 };
-      unsigned index = 0;
-      for (int i = 0; i < def->num_components; i++) {
-         if ((mask >> i) & 0x1)
-            reswizzle[i] = index++;
-      }
-      assert(index == num_components);
-
       /* update dest */
       def->num_components = num_components;
       instr->dest.write_mask = BITFIELD_MASK(num_components);
+   }
 
-      /* update uses */
-      nir_foreach_use(use_src, def) {
-         assert(use_src->parent_instr->type == nir_instr_type_alu);
-         nir_alu_src *alu_src = (nir_alu_src*)use_src;
-         for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++)
-            alu_src->swizzle[i] = reswizzle[alu_src->swizzle[i]];
-      }
-
-      return true;
-   } else {
-
-      switch (instr->op) {
-      case nir_op_vec4:
-      case nir_op_vec3:
-      case nir_op_vec2: {
-         /* don't remove any channels if used by an intrinsic */
-         nir_foreach_use(use_src, def) {
-            if (use_src->parent_instr->type == nir_instr_type_intrinsic)
-               return false;
-         }
-
-         unsigned mask = nir_ssa_def_components_read(def);
-
-         /* If nothing was read, leave it up to DCE. */
-         if (mask == 0)
-            return false;
-
-         int last_bit = util_last_bit(mask);
-         if (last_bit < def->num_components) {
-            nir_ssa_def *srcs[NIR_MAX_VEC_COMPONENTS] = { 0 };
-            for (int i = 0; i < last_bit; i++)
-               srcs[i] = nir_ssa_for_alu_src(b, instr, i);
-
-            nir_ssa_def *new_vec = nir_vec(b, srcs, last_bit);
-            nir_ssa_def_rewrite_uses(def, new_vec);
-            return true;
-         }
-         break;
-      }
+   /* compute new dest swizzles */
+   uint8_t reswizzle[NIR_MAX_VEC_COMPONENTS] = { 0 };
+   unsigned index = 0;
+   for (int i = 0; i < last_bit; i++) {
+      if ((mask >> i) & 0x1)
+         reswizzle[i] = index++;
+   }
+   assert(index == num_components);
 
-      default:
-         break;
-      }
+   /* update uses */
+   nir_foreach_use(use_src, def) {
+      assert(use_src->parent_instr->type == nir_instr_type_alu);
+      nir_alu_src *alu_src = (nir_alu_src*)use_src;
+      for (unsigned i = 0; i < NIR_MAX_VEC_COMPONENTS; i++)
+         alu_src->swizzle[i] = reswizzle[alu_src->swizzle[i]];
    }
 
-   return false;
+   return true;
 }
 
 static bool



More information about the mesa-commit mailing list