From 66500c28d257edf72b41422b3e12376f78e8ff00 Mon Sep 17 00:00:00 2001 From: Simon Perretta Date: Fri, 17 Feb 2023 17:29:08 +0000 Subject: [PATCH] pvr: Add late op lowering pass and conditional execution Signed-off-by: Simon Perretta Acked-by: Frank Binns Part-of: --- src/imagination/rogue/meson.build | 1 + .../rogue/passes/rogue_lower_late_ops.c | 101 +++++++++++++++++++++ .../rogue/passes/rogue_schedule_instr_groups.c | 14 ++- src/imagination/rogue/rogue.c | 1 + src/imagination/rogue/rogue.h | 2 + src/imagination/rogue/rogue_compile.c | 1 + 6 files changed, 116 insertions(+), 4 deletions(-) create mode 100644 src/imagination/rogue/passes/rogue_lower_late_ops.c diff --git a/src/imagination/rogue/meson.build b/src/imagination/rogue/meson.build index 855f029..bb10220 100644 --- a/src/imagination/rogue/meson.build +++ b/src/imagination/rogue/meson.build @@ -44,6 +44,7 @@ libpowervr_rogue_files = files( 'passes/rogue_constreg.c', 'passes/rogue_copy_prop.c', 'passes/rogue_dce.c', + 'passes/rogue_lower_late_ops.c', 'passes/rogue_lower_pseudo_ops.c', 'passes/rogue_regalloc.c', 'passes/rogue_schedule_instr_groups.c', diff --git a/src/imagination/rogue/passes/rogue_lower_late_ops.c b/src/imagination/rogue/passes/rogue_lower_late_ops.c new file mode 100644 index 0000000..833d1d2 --- /dev/null +++ b/src/imagination/rogue/passes/rogue_lower_late_ops.c @@ -0,0 +1,101 @@ +/* + * Copyright © 2023 Imagination Technologies 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. + */ + +#include "rogue.h" +#include "rogue_builder.h" +#include "util/macros.h" + +#include + +/** + * \file rogue_lower_late_ops.c + * + * \brief Contains the rogue_lower_late_ops pass. + */ + +/* TODO NEXT!: Check if registers are being written to that require special + * behaviour, like vertex out. + */ +/* TODO NEXT!: Make sure that SSA regs aren't being used, late passes must + * happen after SSA. + */ +static inline bool rogue_lower_CMOV(rogue_builder *b, rogue_alu_instr *cmov) +{ + rogue_instr *instr_true = + &rogue_MBYP(b, cmov->dst[0].ref, cmov->src[1].ref)->instr; + rogue_instr *instr_false = + &rogue_MBYP(b, cmov->dst[0].ref, cmov->src[2].ref)->instr; + + rogue_set_instr_exec_cond(instr_true, ROGUE_EXEC_COND_P0_TRUE); + rogue_set_instr_exec_cond(instr_false, ROGUE_EXEC_COND_P0_FALSE); + + rogue_merge_instr_comment(instr_true, &cmov->instr, "cmov (true)"); + rogue_merge_instr_comment(instr_false, &cmov->instr, "cmov (false)"); + + rogue_instr_delete(&cmov->instr); + + return true; +} + +static inline bool rogue_lower_alu_instr(rogue_builder *b, rogue_alu_instr *alu) +{ + switch (alu->op) { + case ROGUE_ALU_OP_CMOV: + return rogue_lower_CMOV(b, alu); + + default: + break; + } + + return false; +} + +PUBLIC +bool rogue_lower_late_ops(rogue_shader *shader) +{ + if (shader->is_grouped) + return false; + + bool progress = false; + + rogue_builder b; + rogue_builder_init(&b, shader); + + rogue_foreach_instr_in_shader_safe (instr, shader) { + /* Skip real ops. */ + if (rogue_instr_supported_phases(instr)) + continue; + + b.cursor = rogue_cursor_before_instr(instr); + switch (instr->type) { + case ROGUE_INSTR_TYPE_ALU: + progress |= rogue_lower_alu_instr(&b, rogue_instr_as_alu(instr)); + break; + + default: + continue; + } + } + + return progress; +} diff --git a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c index 77719c7..c4fb63d 100644 --- a/src/imagination/rogue/passes/rogue_schedule_instr_groups.c +++ b/src/imagination/rogue/passes/rogue_schedule_instr_groups.c @@ -287,9 +287,13 @@ static inline void rogue_instr_group_put(rogue_instr *instr, /* Set end flag. */ group->header.end = instr->end; + /* Ensure we're not mixing and matching execution conditions! */ + assert(group->header.exec_cond == ROGUE_EXEC_COND_INVALID || + group->header.exec_cond == instr->exec_cond); + /* Set conditional execution flag. */ - /* TODO: Set this from the instruction. */ - group->header.exec_cond = ROGUE_EXEC_COND_PE_TRUE; + group->header.exec_cond = instr->exec_cond; + instr->exec_cond = ROGUE_EXEC_COND_INVALID; /* Lower I/O to sources/destinations/ISS. */ rogue_lower_instr_group_io(instr, group); @@ -366,8 +370,10 @@ static void rogue_calc_dsts_size(rogue_instr_group *group) { const rogue_instr_group_io_sel *io_sel = &group->io_sel; - unsigned num_dsts = !rogue_ref_is_null(&io_sel->dsts[0]) + - !rogue_ref_is_null(&io_sel->dsts[1]); + unsigned num_dsts = (!rogue_ref_is_null(&io_sel->dsts[0]) && + !rogue_ref_is_io_none(&io_sel->dsts[0])) + + (!rogue_ref_is_null(&io_sel->dsts[1]) && + !rogue_ref_is_io_none(&io_sel->dsts[1])); unsigned bank_bits[ROGUE_ISA_DSTS] = { 0 }; unsigned index_bits[ROGUE_ISA_DSTS] = { 0 }; diff --git a/src/imagination/rogue/rogue.c b/src/imagination/rogue/rogue.c index c3563f3..9e5c54d 100644 --- a/src/imagination/rogue/rogue.c +++ b/src/imagination/rogue/rogue.c @@ -632,6 +632,7 @@ static inline void rogue_instr_init(rogue_instr *instr, rogue_block *block) { instr->type = type; + instr->exec_cond = ROGUE_EXEC_COND_PE_TRUE; instr->repeat = 1; instr->index = block->shader->next_instr++; instr->block = block; diff --git a/src/imagination/rogue/rogue.h b/src/imagination/rogue/rogue.h index d66be6c..e9b22c1 100644 --- a/src/imagination/rogue/rogue.h +++ b/src/imagination/rogue/rogue.h @@ -2738,6 +2738,8 @@ bool rogue_copy_prop(rogue_shader *shader); bool rogue_dce(rogue_shader *shader); +bool rogue_lower_late_ops(rogue_shader *shader); + bool rogue_lower_pseudo_ops(rogue_shader *shader); bool rogue_regalloc(rogue_shader *shader); diff --git a/src/imagination/rogue/rogue_compile.c b/src/imagination/rogue/rogue_compile.c index f6bdf5c..1beeccb 100644 --- a/src/imagination/rogue/rogue_compile.c +++ b/src/imagination/rogue/rogue_compile.c @@ -806,6 +806,7 @@ void rogue_shader_passes(rogue_shader *shader) ROGUE_PASS_V(shader, rogue_schedule_uvsw, false); ROGUE_PASS_V(shader, rogue_trim); ROGUE_PASS_V(shader, rogue_regalloc); + ROGUE_PASS_V(shader, rogue_lower_late_ops); ROGUE_PASS_V(shader, rogue_dce); ROGUE_PASS_V(shader, rogue_schedule_instr_groups, false); -- 2.7.4