Mesa (main): glsl: Delete the vectorization opt pass.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Dec 21 00:42:22 UTC 2021


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

Author: Emma Anholt <emma at anholt.net>
Date:   Fri Dec 17 12:41:10 2021 -0800

glsl: Delete the vectorization opt pass.

Nothing uses it, and i965 was the last thing to.  Even if I enable it for
softpipe or crocus, it quickly causes NIR validation failures in shader-db
from swizzles outside the bounds of vectors.  Retire it in favor of
nir_opt_vectorize().

Reviewed-by: Alyssa Rosenzweig <alyssa at collabora.com>.
Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14249>

---

 src/compiler/glsl/glsl_parser_extras.cpp |   4 -
 src/compiler/glsl/ir_optimization.h      |   1 -
 src/compiler/glsl/meson.build            |   1 -
 src/compiler/glsl/opt_vectorize.cpp      | 407 -------------------------------
 4 files changed, 413 deletions(-)

diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp
index 2495fbb7cf3..a2a4a37e5c6 100644
--- a/src/compiler/glsl/glsl_parser_extras.cpp
+++ b/src/compiler/glsl/glsl_parser_extras.cpp
@@ -2388,10 +2388,6 @@ do_common_optimization(exec_list *ir, bool linked,
    if (options->OptimizeForAOS && !linked)
       OPT(opt_flip_matrices, ir);
 
-   if (linked && options->OptimizeForAOS) {
-      OPT(do_vectorize, ir);
-   }
-
    if (linked)
       OPT(do_dead_code, ir, uniform_locations_assigned);
    else
diff --git a/src/compiler/glsl/ir_optimization.h b/src/compiler/glsl/ir_optimization.h
index a82b84b52ae..f86298f5cc5 100644
--- a/src/compiler/glsl/ir_optimization.h
+++ b/src/compiler/glsl/ir_optimization.h
@@ -127,7 +127,6 @@ bool do_mat_op_to_vec(exec_list *instructions);
 bool do_minmax_prune(exec_list *instructions);
 bool do_structure_splitting(exec_list *instructions);
 bool optimize_swizzles(exec_list *instructions);
-bool do_vectorize(exec_list *instructions);
 bool do_tree_grafting(exec_list *instructions);
 bool do_vec_index_to_cond_assign(exec_list *instructions);
 bool do_vec_index_to_swizzle(exec_list *instructions);
diff --git a/src/compiler/glsl/meson.build b/src/compiler/glsl/meson.build
index a6865406c61..b792ca83e7f 100644
--- a/src/compiler/glsl/meson.build
+++ b/src/compiler/glsl/meson.build
@@ -208,7 +208,6 @@ files_libglsl = files(
   'opt_structure_splitting.cpp',
   'opt_swizzle.cpp',
   'opt_tree_grafting.cpp',
-  'opt_vectorize.cpp',
   'program.h',
   'propagate_invariance.cpp',
   's_expression.cpp',
diff --git a/src/compiler/glsl/opt_vectorize.cpp b/src/compiler/glsl/opt_vectorize.cpp
deleted file mode 100644
index 88318cd8a6e..00000000000
--- a/src/compiler/glsl/opt_vectorize.cpp
+++ /dev/null
@@ -1,407 +0,0 @@
-/*
- * Copyright © 2013 Intel Corporation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
-
-/**
- * \file opt_vectorize.cpp
- *
- * Combines scalar assignments of the same expression (modulo swizzle) to
- * multiple channels of the same variable into a single vectorized expression
- * and assignment.
- *
- * Many generated shaders contain scalarized code. That is, they contain
- *
- * r1.x = log2(v0.x);
- * r1.y = log2(v0.y);
- * r1.z = log2(v0.z);
- *
- * rather than
- *
- * r1.xyz = log2(v0.xyz);
- *
- * We look for consecutive assignments of the same expression (modulo swizzle)
- * to each channel of the same variable.
- *
- * For instance, we want to convert these three scalar operations
- *
- * (assign (x) (var_ref r1) (expression float log2 (swiz x (var_ref v0))))
- * (assign (y) (var_ref r1) (expression float log2 (swiz y (var_ref v0))))
- * (assign (z) (var_ref r1) (expression float log2 (swiz z (var_ref v0))))
- *
- * into a single vector operation
- *
- * (assign (xyz) (var_ref r1) (expression vec3 log2 (swiz xyz (var_ref v0))))
- */
-
-#include "ir.h"
-#include "ir_visitor.h"
-#include "ir_optimization.h"
-#include "compiler/glsl_types.h"
-#include "program/prog_instruction.h"
-
-namespace {
-
-class ir_vectorize_visitor : public ir_hierarchical_visitor {
-public:
-   void clear()
-   {
-      assignment[0] = NULL;
-      assignment[1] = NULL;
-      assignment[2] = NULL;
-      assignment[3] = NULL;
-      current_assignment = NULL;
-      last_assignment = NULL;
-      channels = 0;
-      has_swizzle = false;
-   }
-
-   ir_vectorize_visitor()
-   {
-      clear();
-      progress = false;
-   }
-
-   virtual ir_visitor_status visit_enter(ir_assignment *);
-   virtual ir_visitor_status visit_enter(ir_swizzle *);
-   virtual ir_visitor_status visit_enter(ir_dereference_array *);
-   virtual ir_visitor_status visit_enter(ir_expression *);
-   virtual ir_visitor_status visit_enter(ir_if *);
-   virtual ir_visitor_status visit_enter(ir_loop *);
-   virtual ir_visitor_status visit_enter(ir_texture *);
-
-   virtual ir_visitor_status visit_leave(ir_assignment *);
-
-   void try_vectorize();
-
-   ir_assignment *assignment[4];
-   ir_assignment *current_assignment, *last_assignment;
-   unsigned channels;
-   bool has_swizzle;
-
-   bool progress;
-};
-
-} /* unnamed namespace */
-
-/**
- * Rewrites the swizzles and types of a right-hand side of an assignment.
- *
- * From the example above, this function would be called (by visit_tree()) on
- * the nodes of the tree (expression float log2 (swiz z   (var_ref v0))),
- * rewriting it into     (expression vec3  log2 (swiz xyz (var_ref v0))).
- *
- * The function operates on ir_expressions (and its operands) and ir_swizzles.
- * For expressions it sets a new type and swizzles any non-expression and non-
- * swizzle scalar operands into appropriately sized vector arguments. For
- * example, if combining
- *
- * (assign (x) (var_ref r1) (expression float + (swiz x (var_ref v0) (var_ref v1))))
- * (assign (y) (var_ref r1) (expression float + (swiz y (var_ref v0) (var_ref v1))))
- *
- * where v1 is a scalar, rewrite_swizzle() would insert a swizzle on
- * (var_ref v1) such that the final result was
- *
- * (assign (xy) (var_ref r1) (expression vec2 + (swiz xy (var_ref v0))
- *                                              (swiz xx (var_ref v1))))
- *
- * For swizzles, it sets a new type, and if the variable being swizzled is a
- * vector it overwrites the swizzle mask with the ir_swizzle_mask passed as the
- * data parameter. If the swizzled variable is scalar, then the swizzle was
- * added by an earlier call to rewrite_swizzle() on an expression, so the
- * mask should not be modified.
- */
-static void
-rewrite_swizzle(ir_instruction *ir, void *data)
-{
-   ir_swizzle_mask *mask = (ir_swizzle_mask *)data;
-
-   switch (ir->ir_type) {
-   case ir_type_swizzle: {
-      ir_swizzle *swz = (ir_swizzle *)ir;
-      if (swz->val->type->is_vector()) {
-         swz->mask = *mask;
-      }
-      swz->type = glsl_type::get_instance(swz->type->base_type,
-                                          mask->num_components, 1);
-      break;
-   }
-   case ir_type_expression: {
-      ir_expression *expr = (ir_expression *)ir;
-      expr->type = glsl_type::get_instance(expr->type->base_type,
-                                           mask->num_components, 1);
-      for (unsigned i = 0; i < 4; i++) {
-         if (expr->operands[i]) {
-            ir_rvalue *rval = expr->operands[i]->as_rvalue();
-            if (rval && rval->type->is_scalar() &&
-                !rval->as_expression() && !rval->as_swizzle()) {
-               expr->operands[i] = new(ir) ir_swizzle(rval, 0, 0, 0, 0,
-                                                      mask->num_components);
-            }
-         }
-      }
-      break;
-   }
-   default:
-      break;
-   }
-}
-
-/**
- * Attempt to vectorize the previously saved assignments, and clear them from
- * consideration.
- *
- * If the assignments are able to be combined, it modifies in-place the last
- * assignment seen to be an equivalent vector form of the scalar assignments.
- * It then removes the other now obsolete scalar assignments.
- */
-void
-ir_vectorize_visitor::try_vectorize()
-{
-   if (this->last_assignment && this->channels > 1) {
-      ir_swizzle_mask mask = {0, 0, 0, 0, channels, 0};
-
-      this->last_assignment->write_mask = 0;
-
-      for (unsigned i = 0, j = 0; i < 4; i++) {
-         if (this->assignment[i]) {
-            this->last_assignment->write_mask |= 1 << i;
-
-            if (this->assignment[i] != this->last_assignment) {
-               this->assignment[i]->remove();
-            }
-
-            switch (j) {
-            case 0: mask.x = i; break;
-            case 1: mask.y = i; break;
-            case 2: mask.z = i; break;
-            case 3: mask.w = i; break;
-            }
-
-            j++;
-         }
-      }
-
-      visit_tree(this->last_assignment->rhs, rewrite_swizzle, &mask);
-
-      this->progress = true;
-   }
-   clear();
-}
-
-/**
- * Returns whether the write mask is a single channel.
- */
-static bool
-single_channel_write_mask(unsigned write_mask)
-{
-   return write_mask != 0 && (write_mask & (write_mask - 1)) == 0;
-}
-
-/**
- * Translates single-channeled write mask to single-channeled swizzle.
- */
-static unsigned
-write_mask_to_swizzle(unsigned write_mask)
-{
-   switch (write_mask) {
-   case WRITEMASK_X: return SWIZZLE_X;
-   case WRITEMASK_Y: return SWIZZLE_Y;
-   case WRITEMASK_Z: return SWIZZLE_Z;
-   case WRITEMASK_W: return SWIZZLE_W;
-   }
-   unreachable("not reached");
-}
-
-/**
- * Returns whether a single-channeled write mask matches a swizzle.
- */
-static bool
-write_mask_matches_swizzle(unsigned write_mask,
-                           const ir_swizzle *swz)
-{
-   return ((write_mask == WRITEMASK_X && swz->mask.x == SWIZZLE_X) ||
-           (write_mask == WRITEMASK_Y && swz->mask.x == SWIZZLE_Y) ||
-           (write_mask == WRITEMASK_Z && swz->mask.x == SWIZZLE_Z) ||
-           (write_mask == WRITEMASK_W && swz->mask.x == SWIZZLE_W));
-}
-
-/**
- * Upon entering an ir_assignment, attempt to vectorize the currently tracked
- * assignments if the current assignment is not suitable. Keep a pointer to
- * the current assignment.
- */
-ir_visitor_status
-ir_vectorize_visitor::visit_enter(ir_assignment *ir)
-{
-   ir_dereference *lhs = this->last_assignment != NULL ?
-                         this->last_assignment->lhs : NULL;
-   ir_rvalue *rhs = this->last_assignment != NULL ?
-                    this->last_assignment->rhs : NULL;
-
-   if (ir->condition ||
-       this->channels >= 4 ||
-       !single_channel_write_mask(ir->write_mask) ||
-       this->assignment[write_mask_to_swizzle(ir->write_mask)] != NULL ||
-       (lhs && !ir->lhs->equals(lhs)) ||
-       (rhs && !ir->rhs->equals(rhs, ir_type_swizzle))) {
-      try_vectorize();
-   }
-
-   this->current_assignment = ir;
-
-   return visit_continue;
-}
-
-/**
- * Upon entering an ir_swizzle, set ::has_swizzle if we're visiting from an
- * ir_assignment (i.e., that ::current_assignment is set) and the swizzle mask
- * matches the current assignment's write mask.
- *
- * If the write mask doesn't match the swizzle mask, remove the current
- * assignment from further consideration.
- */
-ir_visitor_status
-ir_vectorize_visitor::visit_enter(ir_swizzle *ir)
-{
-   if (this->current_assignment) {
-      if (write_mask_matches_swizzle(this->current_assignment->write_mask, ir)) {
-         this->has_swizzle = true;
-      } else {
-         this->current_assignment = NULL;
-      }
-   }
-   return visit_continue;
-}
-
-/* Upon entering an ir_array_dereference, remove the current assignment from
- * further consideration. Since the index of an array dereference must scalar,
- * we are not able to vectorize it.
- *
- * FINISHME: If all of scalar indices are identical we could vectorize.
- */
-ir_visitor_status
-ir_vectorize_visitor::visit_enter(ir_dereference_array *)
-{
-   this->current_assignment = NULL;
-   return visit_continue_with_parent;
-}
-
-/**
- * Upon entering an ir_expression, remove the current assignment from further
- * consideration if the expression operates horizontally on vectors.
- */
-ir_visitor_status
-ir_vectorize_visitor::visit_enter(ir_expression *ir)
-{
-   if (ir->is_horizontal()) {
-      this->current_assignment = NULL;
-      return visit_continue_with_parent;
-   }
-   return visit_continue;
-}
-
-/* Since there is no statement to visit between the "then" and "else"
- * instructions try to vectorize before, in between, and after them to avoid
- * combining statements from different basic blocks.
- */
-ir_visitor_status
-ir_vectorize_visitor::visit_enter(ir_if *ir)
-{
-   try_vectorize();
-
-   visit_list_elements(this, &ir->then_instructions);
-   try_vectorize();
-
-   visit_list_elements(this, &ir->else_instructions);
-   try_vectorize();
-
-   return visit_continue_with_parent;
-}
-
-/* Since there is no statement to visit between the instructions in the body of
- * the loop and the instructions after it try to vectorize before and after the
- * body to avoid combining statements from different basic blocks.
- */
-ir_visitor_status
-ir_vectorize_visitor::visit_enter(ir_loop *ir)
-{
-   try_vectorize();
-
-   visit_list_elements(this, &ir->body_instructions);
-   try_vectorize();
-
-   return visit_continue_with_parent;
-}
-
-/**
- * Upon entering an ir_texture, remove the current assignment from
- * further consideration. Vectorizing multiple texture lookups into one
- * is wrong.
- */
-ir_visitor_status
-ir_vectorize_visitor::visit_enter(ir_texture *)
-{
-   this->current_assignment = NULL;
-   return visit_continue_with_parent;
-}
-
-/**
- * Upon leaving an ir_assignment, save a pointer to it in ::assignment[] if
- * the swizzle mask(s) found were appropriate. Also save a pointer in
- * ::last_assignment so that we can compare future assignments with it.
- *
- * Finally, clear ::current_assignment and ::has_swizzle.
- */
-ir_visitor_status
-ir_vectorize_visitor::visit_leave(ir_assignment *ir)
-{
-   if (this->has_swizzle && this->current_assignment) {
-      assert(this->current_assignment == ir);
-
-      unsigned channel = write_mask_to_swizzle(this->current_assignment->write_mask);
-      this->assignment[channel] = ir;
-      this->channels++;
-
-      this->last_assignment = this->current_assignment;
-   }
-   this->current_assignment = NULL;
-   this->has_swizzle = false;
-   return visit_continue;
-}
-
-/**
- * Combines scalar assignments of the same expression (modulo swizzle) to
- * multiple channels of the same variable into a single vectorized expression
- * and assignment.
- */
-bool
-do_vectorize(exec_list *instructions)
-{
-   ir_vectorize_visitor v;
-
-   v.run(instructions);
-
-   /* Try to vectorize the last assignments seen. */
-   v.try_vectorize();
-
-   return v.progress;
-}



More information about the mesa-commit mailing list