diff --git a/src/broadcom/compiler/meson.build b/src/broadcom/compiler/meson.build index 913e13f9480..9380841cace 100644 --- a/src/broadcom/compiler/meson.build +++ b/src/broadcom/compiler/meson.build @@ -11,6 +11,7 @@ libbroadcom_compiler_files = files( 'vir_opt_copy_propagate.c', 'vir_opt_dead_code.c', 'vir_opt_redundant_flags.c', + 'vir_opt_redundant_setnnmode.c', 'vir_opt_small_immediates.c', 'vir_register_allocate.c', 'vir_to_qpu.c', diff --git a/src/broadcom/compiler/v3d_compiler.h b/src/broadcom/compiler/v3d_compiler.h index 0b6ebeae86d..b4b289636c0 100644 --- a/src/broadcom/compiler/v3d_compiler.h +++ b/src/broadcom/compiler/v3d_compiler.h @@ -1222,6 +1222,7 @@ bool vir_opt_small_immediates(struct v3d_compile *c); bool vir_opt_vpm(struct v3d_compile *c); bool vir_opt_constant_alu(struct v3d_compile *c); bool vir_opt_alu(struct v3d_compile *c); +bool vir_opt_redundant_setnnmode(struct v3d_compile *c); bool v3d_nir_lower_io(nir_shader *s, struct v3d_compile *c); bool v3d_nir_lower_line_smooth(nir_shader *shader); bool v3d_nir_lower_logic_ops(nir_shader *s, struct v3d_compile *c); diff --git a/src/broadcom/compiler/vir.c b/src/broadcom/compiler/vir.c index d2c3615b7a2..866cdcb2673 100644 --- a/src/broadcom/compiler/vir.c +++ b/src/broadcom/compiler/vir.c @@ -2539,6 +2539,7 @@ vir_optimize(struct v3d_compile *c) OPTPASS(vir_opt_small_immediates); OPTPASS(vir_opt_constant_alu); OPTPASS(vir_opt_alu); + OPTPASS(vir_opt_redundant_setnnmode); if (!progress) break; diff --git a/src/broadcom/compiler/vir_opt_redundant_setnnmode.c b/src/broadcom/compiler/vir_opt_redundant_setnnmode.c new file mode 100644 index 00000000000..b7164c547fe --- /dev/null +++ b/src/broadcom/compiler/vir_opt_redundant_setnnmode.c @@ -0,0 +1,86 @@ +/* + * Copyright © 2026 Raspberry Pi Ltd + * + * 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 vir_opt_redundant_setnnmode.c + * + * Eliminates redundant setnnmode instructions within basic blocks. + * + * When multiple dot products use the same signedness mode, the compiler emits + * one setnnmode per dot product. This pass tracks the current NN mode per + * basic block and removes duplicates. + */ + +#include "v3d_compiler.h" + +static bool +is_setnnmode_op(enum v3d_qpu_add_op op) +{ + switch (op) { + case V3D_QPU_A_SETNNMODE_UU: + case V3D_QPU_A_SETNNMODE_SU: + case V3D_QPU_A_SETNNMODE_US: + case V3D_QPU_A_SETNNMODE_SS: + return true; + default: + return false; + } +} + +static bool +vir_opt_redundant_setnnmode_block(struct v3d_compile *c, struct qblock *block) +{ + bool progress = false; + enum v3d_qpu_add_op current_mode = V3D_QPU_A_NOP; + c->cur_block = block; + vir_for_each_inst_safe(inst, block) { + if (inst->qpu.type != V3D_QPU_INSTR_TYPE_ALU) + continue; + + enum v3d_qpu_add_op op = inst->qpu.alu.add.op; + + if (!is_setnnmode_op(op)) + continue; + + if (op == current_mode) { + vir_remove_instruction(c, inst); + progress = true; + } else { + current_mode = op; + } + } + + return progress; +} + +bool +vir_opt_redundant_setnnmode(struct v3d_compile *c) +{ + bool progress = false; + + vir_for_each_block(block, c) { + progress = vir_opt_redundant_setnnmode_block(c, block) || progress; + } + + return progress; +}