From: Emma Anholt Date: Fri, 17 Dec 2021 20:41:10 +0000 (-0800) Subject: glsl: Delete the vectorization opt pass. X-Git-Tag: upstream/22.3.5~14604 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c2ead6c9b56753bd1cf4bd12eaeb0d3f3530131c;p=platform%2Fupstream%2Fmesa.git 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 . Reviewed-by: Marek Olšák Part-of: --- diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp index 2495fbb..a2a4a37 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 a82b84b..f86298f 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 a686540..b792ca8 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 88318cd..0000000 --- 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; -}