From dd3179aff0c1d38060836f926e9d5d21edbd3eae Mon Sep 17 00:00:00 2001 From: Emma Anholt Date: Tue, 12 Apr 2022 10:46:42 -0700 Subject: [PATCH] glsl: Remove unused lower_variable_index_to_cond_assign. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's been replaced by nir_lower_indirect_derefs(). Reviewed-by: Marek Olšák Part-of: --- src/compiler/glsl/ir_optimization.h | 3 - src/compiler/glsl/loop_unroll.cpp | 2 +- .../lower_variable_index_to_cond_assign.cpp | 455 ------------------ src/compiler/glsl/meson.build | 1 - src/compiler/glsl/test_optpass.cpp | 6 - 5 files changed, 1 insertion(+), 466 deletions(-) delete mode 100644 src/compiler/glsl/lower_variable_index_to_cond_assign.cpp diff --git a/src/compiler/glsl/ir_optimization.h b/src/compiler/glsl/ir_optimization.h index d40617510ba..e1bb1da6a2f 100644 --- a/src/compiler/glsl/ir_optimization.h +++ b/src/compiler/glsl/ir_optimization.h @@ -127,9 +127,6 @@ bool do_vec_index_to_swizzle(exec_list *instructions); bool lower_discard(exec_list *instructions); void lower_discard_flow(exec_list *instructions); bool lower_instructions(exec_list *instructions, unsigned what_to_lower); -bool lower_variable_index_to_cond_assign(gl_shader_stage stage, - exec_list *instructions, bool lower_input, bool lower_output, - bool lower_temp, bool lower_uniform); bool lower_quadop_vector(exec_list *instructions); bool lower_const_arrays_to_uniforms(exec_list *instructions, unsigned stage, unsigned max_uniform_components); bool lower_clip_cull_distance(struct gl_shader_program *prog, diff --git a/src/compiler/glsl/loop_unroll.cpp b/src/compiler/glsl/loop_unroll.cpp index 04b8b4f496d..452b06502a2 100644 --- a/src/compiler/glsl/loop_unroll.cpp +++ b/src/compiler/glsl/loop_unroll.cpp @@ -110,7 +110,7 @@ public: * Unrolling the loop may convert that access into constant-indexing. * * Many drivers don't support particular kinds of variable indexing, - * and have to resort to using lower_variable_index_to_cond_assign to + * and have to resort to using nir_lower_indirect_derefs to * handle it. This results in huge amounts of horrible code, so we'd * like to avoid that if possible. Here, we just note that it will * happen. diff --git a/src/compiler/glsl/lower_variable_index_to_cond_assign.cpp b/src/compiler/glsl/lower_variable_index_to_cond_assign.cpp deleted file mode 100644 index 4e7761e756b..00000000000 --- a/src/compiler/glsl/lower_variable_index_to_cond_assign.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright © 2010 Luca Barbieri - * - * 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 lower_variable_index_to_cond_assign.cpp - * - * Turns non-constant indexing into array types to a series of - * conditional moves of each element into a temporary. - * - * Pre-DX10 GPUs often don't have a native way to do this operation, - * and this works around that. - * - * The lowering process proceeds as follows. Each non-constant index - * found in an r-value is converted to a canonical form \c array[i]. Each - * element of the array is conditionally assigned to a temporary by comparing - * \c i to a constant index. This is done by cloning the canonical form and - * replacing all occurances of \c i with a constant. Each remaining occurance - * of the canonical form in the IR is replaced with a dereference of the - * temporary variable. - * - * L-values with non-constant indices are handled similarly. In this case, - * the RHS of the assignment is assigned to a temporary. The non-constant - * index is replace with the canonical form (just like for r-values). The - * temporary is conditionally assigned to each element of the canonical form - * by comparing \c i with each index. The same clone-and-replace scheme is - * used. - */ - -#include "ir.h" -#include "ir_rvalue_visitor.h" -#include "ir_optimization.h" -#include "compiler/glsl_types.h" -#include "main/macros.h" -#include "program/prog_instruction.h" /* For SWIZZLE_XXXX */ -#include "ir_builder.h" - -using namespace ir_builder; - -static inline bool -is_array_or_matrix(const ir_rvalue *ir) -{ - return (ir->type->is_array() || ir->type->is_matrix()); -} - -namespace { -/** - * Replace a dereference of a variable with a specified r-value - * - * Each time a dereference of the specified value is replaced, the r-value - * tree is cloned. - */ -class deref_replacer : public ir_rvalue_visitor { -public: - deref_replacer(const ir_variable *variable_to_replace, ir_rvalue *value) - : variable_to_replace(variable_to_replace), value(value), - progress(false) - { - assert(this->variable_to_replace != NULL); - assert(this->value != NULL); - } - - virtual void handle_rvalue(ir_rvalue **rvalue) - { - ir_dereference_variable *const dv = (*rvalue)->as_dereference_variable(); - - if (dv != NULL && dv->var == this->variable_to_replace) { - this->progress = true; - *rvalue = this->value->clone(ralloc_parent(*rvalue), NULL); - } - } - - const ir_variable *variable_to_replace; - ir_rvalue *value; - bool progress; -}; - -/** - * Find a variable index dereference of an array in an rvalue tree - */ -class find_variable_index : public ir_hierarchical_visitor { -public: - find_variable_index() - : deref(NULL) - { - /* empty */ - } - - virtual ir_visitor_status visit_enter(ir_dereference_array *ir) - { - if (is_array_or_matrix(ir->array) && - ir->array_index->as_constant() == NULL) { - this->deref = ir; - return visit_stop; - } - - return visit_continue; - } - - /** - * First array dereference found in the tree that has a non-constant index. - */ - ir_dereference_array *deref; -}; - -struct assignment_generator -{ - ir_instruction* base_ir; - ir_dereference *rvalue; - ir_variable *old_index; - bool is_write; - unsigned int write_mask; - ir_variable* var; - - assignment_generator() - : base_ir(NULL), - rvalue(NULL), - old_index(NULL), - is_write(false), - write_mask(0), - var(NULL) - { - } - - void generate(unsigned i, ir_factory &body) const - { - /* Clone the old r-value in its entirety. Then replace any occurances of - * the old variable index with the new constant index. - */ - ir_dereference *element = this->rvalue->clone(body.mem_ctx, NULL); - ir_constant *const index = body.constant(i); - deref_replacer r(this->old_index, index); - element->accept(&r); - assert(r.progress); - - ir_assignment *const assignment = (is_write) - ? assign(element, this->var, write_mask) - : assign(this->var, element); - - body.emit(assignment); - } -}; - -struct switch_generator -{ - /* make TFunction a template parameter if you need to use other generators */ - typedef assignment_generator TFunction; - const TFunction& generator; - - ir_variable* index; - - void *mem_ctx; - - switch_generator(const TFunction& generator, ir_variable *index) - : generator(generator), index(index) - { - this->mem_ctx = ralloc_parent(index); - } - - void bisect(unsigned begin, unsigned end, ir_factory &body) - { - unsigned middle = (begin + end) >> 1; - - assert(index->type->is_integer_32()); - - ir_constant *const middle_c = (index->type->base_type == GLSL_TYPE_UINT) - ? new(body.mem_ctx) ir_constant((unsigned)middle) - : new(body.mem_ctx) ir_constant((int)middle); - - ir_if *if_less = new(body.mem_ctx) ir_if(less(this->index, middle_c)); - - ir_factory then_body(&if_less->then_instructions, body.mem_ctx); - ir_factory else_body(&if_less->else_instructions, body.mem_ctx); - generate(begin, middle, then_body); - generate(middle, end, else_body); - - body.emit(if_less); - } - - void generate(unsigned begin, unsigned end, ir_factory &body) - { - if (begin == end) - return; - - unsigned length = end - begin; - if (length == 1) - generator.generate(begin, body); - else - bisect(begin, end, body); - } -}; - -/** - * Visitor class for replacing expressions with ir_constant values. - */ - -class variable_index_to_cond_assign_visitor : public ir_rvalue_visitor { -public: - variable_index_to_cond_assign_visitor(gl_shader_stage stage, - bool lower_input, - bool lower_output, - bool lower_temp, - bool lower_uniform) - : progress(false), stage(stage), lower_inputs(lower_input), - lower_outputs(lower_output), lower_temps(lower_temp), - lower_uniforms(lower_uniform) - { - /* empty */ - } - - bool progress; - - gl_shader_stage stage; - bool lower_inputs; - bool lower_outputs; - bool lower_temps; - bool lower_uniforms; - - bool storage_type_needs_lowering(ir_dereference_array *deref) const - { - /* If a variable isn't eventually the target of this dereference, then - * it must be a constant or some sort of anonymous temporary storage. - * - * FINISHME: Is this correct? Most drivers treat arrays of constants as - * FINISHME: uniforms. It seems like this should do the same. - */ - const ir_variable *const var = deref->array->variable_referenced(); - if (var == NULL) - return this->lower_temps; - - switch (var->data.mode) { - case ir_var_auto: - case ir_var_temporary: - return this->lower_temps; - - case ir_var_uniform: - case ir_var_shader_storage: - return this->lower_uniforms; - - case ir_var_shader_shared: - return false; - - case ir_var_function_in: - case ir_var_const_in: - return this->lower_temps; - - case ir_var_system_value: - /* There are only a few system values that have array types: - * - * gl_TessLevelInner[] - * gl_TessLevelOuter[] - * gl_SampleMaskIn[] - * - * The tessellation factor arrays are lowered to vec4/vec2s - * by lower_tess_level() before this pass occurs, so we'll - * never see them here. - * - * The only remaining case is gl_SampleMaskIn[], which has - * a length of ceil(ctx->Const.MaxSamples / 32). Most hardware - * supports no more than 32 samples, in which case our lowering - * produces a single read of gl_SampleMaskIn[0]. Even with 64x - * MSAA, the array length is only 2, so the lowering is fairly - * efficient. Therefore, lower unconditionally. - */ - return true; - - case ir_var_shader_in: - /* The input array size is unknown at compiler time for non-patch - * inputs in TCS and TES. The arrays are sized to - * the implementation-dependent limit "gl_MaxPatchVertices", but - * the real size is stored in the "gl_PatchVerticesIn" built-in - * uniform. - * - * The TCS input array size is specified by - * glPatchParameteri(GL_PATCH_VERTICES). - * - * The TES input array size is specified by the "vertices" output - * layout qualifier in TCS. - */ - if ((stage == MESA_SHADER_TESS_CTRL || - stage == MESA_SHADER_TESS_EVAL) && !var->data.patch) - return false; - return this->lower_inputs; - - case ir_var_function_out: - /* TCS non-patch outputs can only be indexed with "gl_InvocationID". - * Other expressions are not allowed. - */ - if (stage == MESA_SHADER_TESS_CTRL && !var->data.patch) - return false; - return this->lower_temps; - - case ir_var_shader_out: - return this->lower_outputs; - - case ir_var_function_inout: - return this->lower_temps; - } - - assert(!"Should not get here."); - return false; - } - - bool needs_lowering(ir_dereference_array *deref) const - { - if (deref == NULL || deref->array_index->as_constant() || - !is_array_or_matrix(deref->array)) - return false; - - return this->storage_type_needs_lowering(deref); - } - - ir_variable *convert_dereference_array(ir_dereference_array *orig_deref, - ir_assignment* orig_assign, - ir_dereference *orig_base) - { - void *const mem_ctx = ralloc_parent(base_ir); - exec_list list; - ir_factory body(&list, mem_ctx); - - assert(is_array_or_matrix(orig_deref->array)); - - const unsigned length = (orig_deref->array->type->is_array()) - ? orig_deref->array->type->length - : orig_deref->array->type->matrix_columns; - - /* Temporary storage for either the result of the dereference of - * the array, or the RHS that's being assigned into the - * dereference of the array. - */ - ir_variable *var; - - if (orig_assign) { - var = body.make_temp(orig_assign->rhs->type, - "dereference_array_value"); - - body.emit(assign(var, orig_assign->rhs)); - } else { - var = body.make_temp(orig_deref->type, - "dereference_array_value"); - } - - /* Store the index to a temporary to avoid reusing its tree. */ - ir_variable *index = body.make_temp(orig_deref->array_index->type, - "dereference_array_index"); - - body.emit(assign(index, orig_deref->array_index)); - - orig_deref->array_index = deref(index).val; - - assignment_generator ag; - ag.rvalue = orig_base; - ag.base_ir = base_ir; - ag.old_index = index; - ag.var = var; - if (orig_assign) { - ag.is_write = true; - ag.write_mask = orig_assign->write_mask; - } else { - ag.is_write = false; - } - - switch_generator sg(ag, index); - - sg.generate(0, length, body); - - base_ir->insert_before(&list); - return var; - } - - virtual void handle_rvalue(ir_rvalue **pir) - { - if (this->in_assignee) - return; - - if (!*pir) - return; - - ir_dereference_array* orig_deref = (*pir)->as_dereference_array(); - if (needs_lowering(orig_deref)) { - ir_variable *var = - convert_dereference_array(orig_deref, NULL, orig_deref); - assert(var); - *pir = new(ralloc_parent(base_ir)) ir_dereference_variable(var); - this->progress = true; - } - } - - ir_visitor_status - visit_leave(ir_assignment *ir) - { - ir_rvalue_visitor::visit_leave(ir); - - find_variable_index f; - ir->lhs->accept(&f); - - if (f.deref != NULL && storage_type_needs_lowering(f.deref)) { - convert_dereference_array(f.deref, ir, ir->lhs); - ir->remove(); - this->progress = true; - } - - return visit_continue; - } -}; - -} /* anonymous namespace */ - -bool -lower_variable_index_to_cond_assign(gl_shader_stage stage, - exec_list *instructions, - bool lower_input, - bool lower_output, - bool lower_temp, - bool lower_uniform) -{ - variable_index_to_cond_assign_visitor v(stage, - lower_input, - lower_output, - lower_temp, - lower_uniform); - - /* Continue lowering until no progress is made. If there are multiple - * levels of indirection (e.g., non-constant indexing of array elements and - * matrix columns of an array of matrix), each pass will only lower one - * level of indirection. - */ - bool progress_ever = false; - do { - v.progress = false; - visit_list_elements(&v, instructions); - progress_ever = v.progress || progress_ever; - } while (v.progress); - - return progress_ever; -} diff --git a/src/compiler/glsl/meson.build b/src/compiler/glsl/meson.build index 33f523f019f..3a4ca70e65e 100644 --- a/src/compiler/glsl/meson.build +++ b/src/compiler/glsl/meson.build @@ -172,7 +172,6 @@ files_libglsl = files( 'lower_precision.cpp', 'lower_subroutine.cpp', 'lower_tess_level.cpp', - 'lower_variable_index_to_cond_assign.cpp', 'lower_vec_index_to_cond_assign.cpp', 'lower_vec_index_to_swizzle.cpp', 'lower_vector.cpp', diff --git a/src/compiler/glsl/test_optpass.cpp b/src/compiler/glsl/test_optpass.cpp index 6fad23efa8e..3d34a6ddebe 100644 --- a/src/compiler/glsl/test_optpass.cpp +++ b/src/compiler/glsl/test_optpass.cpp @@ -110,12 +110,6 @@ do_optimization(struct exec_list *ir, const char *optimization, } else if (sscanf(optimization, "lower_instructions ( %d ) ", &int_0) == 1) { return lower_instructions(ir, int_0); - } else if (sscanf(optimization, "lower_variable_index_to_cond_assign " - "( %d , %d , %d , %d ) ", &int_0, &int_1, &int_2, - &int_3) == 4) { - return lower_variable_index_to_cond_assign(MESA_SHADER_VERTEX, ir, - int_0 != 0, int_1 != 0, - int_2 != 0, int_3 != 0); } else if (sscanf(optimization, "lower_quadop_vector") == 1) { return lower_quadop_vector(ir); } else {