pco: initial legalize pass/validation to handle hw restrictions
Signed-off-by: Simon Perretta <simon.perretta@imgtec.com> Acked-by: Frank Binns <frank.binns@imgtec.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33998>
This commit is contained in:
committed by
Marge Bot
parent
4402649b01
commit
05912bcb60
@@ -12,6 +12,7 @@ libpowervr_compiler_files = files(
|
||||
'pco_group_instrs.c',
|
||||
'pco_index.c',
|
||||
'pco_ir.c',
|
||||
'pco_legalize.c',
|
||||
'pco_nir.c',
|
||||
'pco_nir_pvfio.c',
|
||||
'pco_opt.c',
|
||||
|
||||
@@ -337,6 +337,7 @@ typedef struct _pco_shader {
|
||||
const char *name; /** Shader name. */
|
||||
bool is_internal; /** Whether this is an internal shader. */
|
||||
bool is_grouped; /** Whether the shader uses igrps. */
|
||||
bool is_legalized; /** Whether the shader has been legalized. */
|
||||
|
||||
struct list_head funcs; /** List of functions. */
|
||||
unsigned next_func; /** Next function index. */
|
||||
@@ -1112,6 +1113,7 @@ bool pco_dce(pco_shader *shader);
|
||||
bool pco_end(pco_shader *shader);
|
||||
bool pco_group_instrs(pco_shader *shader);
|
||||
bool pco_index(pco_shader *shader, bool skip_ssa);
|
||||
bool pco_legalize(pco_shader *shader);
|
||||
bool pco_nir_pfo(nir_shader *nir, pco_fs_data *fs);
|
||||
bool pco_nir_pvi(nir_shader *nir, pco_vs_data *vs);
|
||||
bool pco_opt(pco_shader *shader);
|
||||
@@ -1946,6 +1948,47 @@ static inline bool pco_refs_are_equal(pco_ref ref0, pco_ref ref1)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Checks a reference has a valid hardware source mapping.
|
||||
*
|
||||
* \param[in] ref Reference.
|
||||
* \param[in] mapped_src Hardware source mapping.
|
||||
* \param[out] needs_s124 Whether the mapping needs to use S{1,2,4}
|
||||
* rather than S{0,2,3}.
|
||||
* \return True if the mapping is valid.
|
||||
*/
|
||||
static inline bool
|
||||
ref_src_map_valid(pco_ref ref, enum pco_io mapped_src, bool *needs_s124)
|
||||
{
|
||||
if (needs_s124)
|
||||
*needs_s124 = false;
|
||||
|
||||
/* Restrictions only apply to hardware registers. */
|
||||
if (!pco_ref_is_idx_reg(ref) && !pco_ref_is_reg(ref))
|
||||
return true;
|
||||
|
||||
switch (pco_ref_get_reg_class(ref)) {
|
||||
case PCO_REG_CLASS_COEFF:
|
||||
case PCO_REG_CLASS_SHARED:
|
||||
case PCO_REG_CLASS_INDEX:
|
||||
case PCO_REG_CLASS_PIXOUT:
|
||||
return (mapped_src == PCO_IO_S0) || (mapped_src == PCO_IO_S2) ||
|
||||
(mapped_src == PCO_IO_S3);
|
||||
|
||||
case PCO_REG_CLASS_SPEC:
|
||||
if (needs_s124)
|
||||
*needs_s124 = true;
|
||||
|
||||
return (mapped_src == PCO_IO_S1) || (mapped_src == PCO_IO_S2) ||
|
||||
(mapped_src == PCO_IO_S4);
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns whether none of the lower/upper sources in an instruction
|
||||
* group are set.
|
||||
|
||||
@@ -60,6 +60,7 @@ void pco_process_ir(pco_ctx *ctx, pco_shader *shader)
|
||||
* time a drc result is used.
|
||||
*/
|
||||
PCO_PASS(_, shader, pco_schedule);
|
||||
PCO_PASS(_, shader, pco_legalize);
|
||||
PCO_PASS(_, shader, pco_ra);
|
||||
PCO_PASS(_, shader, pco_end);
|
||||
PCO_PASS(_, shader, pco_group_instrs);
|
||||
|
||||
136
src/imagination/pco/pco_legalize.c
Normal file
136
src/imagination/pco/pco_legalize.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright © 2025 Imagination Technologies Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file pco_legalize.c
|
||||
*
|
||||
* \brief PCO legalizing pass.
|
||||
*/
|
||||
|
||||
#include "pco.h"
|
||||
#include "pco_builder.h"
|
||||
#include "pco_internal.h"
|
||||
#include "util/macros.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* \brief Insert a mov to legalize how a hardware register is referenced.
|
||||
*
|
||||
* \param[in,out] instr PCO instr.
|
||||
* \param[in,out] ref Reference to be legalized.
|
||||
* \param[in] needs_s124 Whether the mapping needs to use S{1,2,4}
|
||||
* rather than S{0,2,3}.
|
||||
* \return True if progress was made.
|
||||
*/
|
||||
static void insert_mov_ref(pco_instr *instr, pco_ref *ref, bool needs_s124)
|
||||
{
|
||||
assert(pco_ref_is_scalar(*ref));
|
||||
pco_ref new_ref = pco_ref_new_ssa(instr->parent_func,
|
||||
pco_ref_get_bits(*ref),
|
||||
pco_ref_get_chans(*ref));
|
||||
|
||||
pco_ref_xfer_mods(&new_ref, ref, true);
|
||||
|
||||
pco_builder b =
|
||||
pco_builder_create(instr->parent_func, pco_cursor_before_instr(instr));
|
||||
|
||||
if (needs_s124)
|
||||
pco_movs1(&b, new_ref, *ref);
|
||||
else
|
||||
pco_mbyp(&b, new_ref, *ref);
|
||||
|
||||
*ref = new_ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Try to legalize an instruction's hardware source mappings.
|
||||
*
|
||||
* \param[in,out] instr PCO instr.
|
||||
* \param[in] info PCO op info.
|
||||
* \return True if progress was made.
|
||||
*/
|
||||
static bool try_legalize_src_mappings(pco_instr *instr,
|
||||
const struct pco_op_info *info)
|
||||
{
|
||||
bool progress = false;
|
||||
bool needs_s124;
|
||||
|
||||
/* Check dests. */
|
||||
pco_foreach_instr_dest (pdest, instr) {
|
||||
unsigned dest_index = pdest - instr->dest;
|
||||
if (!info->dest_intrn_map[dest_index])
|
||||
continue;
|
||||
|
||||
enum pco_io mapped_src = PCO_IO_S0 + info->dest_intrn_map[dest_index] - 1;
|
||||
|
||||
if (ref_src_map_valid(*pdest, mapped_src, &needs_s124))
|
||||
continue;
|
||||
|
||||
insert_mov_ref(instr, pdest, needs_s124);
|
||||
progress = true;
|
||||
}
|
||||
|
||||
/* Check srcs. */
|
||||
pco_foreach_instr_src (psrc, instr) {
|
||||
unsigned src_index = psrc - instr->src;
|
||||
if (!info->src_intrn_map[src_index])
|
||||
continue;
|
||||
|
||||
enum pco_io mapped_src = PCO_IO_S0 + info->src_intrn_map[src_index] - 1;
|
||||
|
||||
if (ref_src_map_valid(*psrc, mapped_src, &needs_s124))
|
||||
continue;
|
||||
|
||||
insert_mov_ref(instr, psrc, needs_s124);
|
||||
progress = true;
|
||||
}
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Try to legalizes an instruction.
|
||||
*
|
||||
* \param[in,out] instr PCO instr.
|
||||
* \return True if progress was made.
|
||||
*/
|
||||
static bool try_legalize(pco_instr *instr)
|
||||
{
|
||||
const struct pco_op_info *info = &pco_op_info[instr->op];
|
||||
bool progress = false;
|
||||
|
||||
/* Skip pseudo instructions. */
|
||||
if (info->type == PCO_OP_TYPE_PSEUDO)
|
||||
return false;
|
||||
|
||||
progress |= try_legalize_src_mappings(instr, info);
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Legalizes instructions where additional restrictions apply.
|
||||
*
|
||||
* \param[in,out] shader PCO shader.
|
||||
* \return True if the pass made progress.
|
||||
*/
|
||||
bool pco_legalize(pco_shader *shader)
|
||||
{
|
||||
bool progress = false;
|
||||
|
||||
assert(!shader->is_grouped);
|
||||
assert(!shader->is_legalized);
|
||||
|
||||
pco_foreach_func_in_shader (func, shader) {
|
||||
pco_foreach_instr_in_func_safe (instr, func) {
|
||||
progress |= try_legalize(instr);
|
||||
}
|
||||
}
|
||||
|
||||
shader->is_legalized = true;
|
||||
return progress;
|
||||
}
|
||||
@@ -781,6 +781,18 @@ encode_map(O_MOVC,
|
||||
]
|
||||
)
|
||||
|
||||
encode_map(O_MOVWM,
|
||||
encodings=[
|
||||
(I_MOVC_EXT, [
|
||||
('movw0', ('pco_ref_get_movw01', SRC(0))),
|
||||
('movw1', 0),
|
||||
('maskw0', (RM_ELEM, DEST(0))),
|
||||
('aw', True),
|
||||
('p2end', OM_PHASE2END)
|
||||
])
|
||||
]
|
||||
)
|
||||
|
||||
encode_map(O_ADD64_32,
|
||||
encodings=[
|
||||
(I_INT32_64_EXT, [
|
||||
@@ -1082,6 +1094,52 @@ group_map(O_UNPCK,
|
||||
dests=[('w[0]', ('0', DEST(0)), 'ft0')]
|
||||
)
|
||||
|
||||
group_map(O_MOVWM,
|
||||
hdr=(I_IGRP_HDR_MAIN, [
|
||||
('oporg', 'p0_p2'),
|
||||
('olchk', OM_OLCHK),
|
||||
('w1p', False),
|
||||
('w0p', True),
|
||||
('cc', OM_EXEC_CND),
|
||||
('end', OM_END),
|
||||
('atom', OM_ATOM),
|
||||
('rpt', OM_RPT)
|
||||
]),
|
||||
enc_ops=[
|
||||
('0', O_MBYP, ['ft0'], [SRC(0)]),
|
||||
('2_mov', O_MOVWM, [DEST(0)], ['ft0', SRC(1)], [(OM_PHASE2END, OM_PHASE2END)])
|
||||
],
|
||||
srcs=[
|
||||
('s[0]', ('0', SRC(0)), 's0'),
|
||||
('s[1]', ('2_mov', SRC(1)), 'is4')
|
||||
],
|
||||
iss=[
|
||||
('is[0]', 's1'),
|
||||
('is[4]', 'fte')
|
||||
],
|
||||
dests=[('w[0]', ('2_mov', DEST(0)), 'w0')]
|
||||
)
|
||||
|
||||
group_map(O_MOVS1,
|
||||
hdr=(I_IGRP_HDR_MAIN, [
|
||||
('oporg', 'p2'),
|
||||
('olchk', OM_OLCHK),
|
||||
('w1p', False),
|
||||
('w0p', True),
|
||||
('cc', OM_EXEC_CND),
|
||||
('end', OM_END),
|
||||
('atom', OM_ATOM),
|
||||
('rpt', OM_RPT)
|
||||
]),
|
||||
enc_ops=[('2_mov', O_MOVWM, [DEST(0)], [SRC(0), 'is4'], [(OM_PHASE2END, True)])],
|
||||
srcs=[('s[1]', ('2_mov', SRC(0)), 'fte')],
|
||||
iss=[
|
||||
('is[0]', 's1'),
|
||||
('is[4]', 'fte')
|
||||
],
|
||||
dests=[('w[0]', ('2_mov', DEST(0)), 'w0')]
|
||||
)
|
||||
|
||||
group_map(O_ADD64_32,
|
||||
hdr=(I_IGRP_HDR_MAIN, [
|
||||
('oporg', 'p0'),
|
||||
|
||||
@@ -303,6 +303,9 @@ O_UNPCK = hw_op('unpck', OM_ALU + [OM_PCK_FMT, OM_ROUNDZERO, OM_SCALE], 1, 1, []
|
||||
O_TST = hw_direct_op('tst', [OM_TST_OP_MAIN, OM_PHASE2END, OM_TST_TYPE_MAIN], 2, 2, [], [[RM_ELEM], [RM_ELEM]])
|
||||
O_MOVC = hw_direct_op('movc', [OM_PHASE2END], 2, 5, [[RM_ELEM]])
|
||||
|
||||
O_MOVWM = hw_op('movwm', OM_ALU + [OM_PHASE2END], 1, 2, [[RM_ELEM]])
|
||||
O_MOVS1 = hw_op('movs1', OM_ALU, 1, 1)
|
||||
|
||||
# TODO
|
||||
# O_PCK_ELEM = pseudo_op('pck.elem', OM_ALU_RPT1 + [OM_PCK_FMT, OM_ROUNDZERO, OM_SCALE], 1, 2)
|
||||
|
||||
|
||||
@@ -152,12 +152,85 @@ static void pco_validate_ssa(struct val_state *state)
|
||||
"SSA destination defined to more than once");
|
||||
BITSET_SET(ssa_writes, pdest->val);
|
||||
}
|
||||
|
||||
state->instr = NULL;
|
||||
state->cf_node = NULL;
|
||||
}
|
||||
|
||||
ralloc_free(ssa_writes);
|
||||
|
||||
state->func = NULL;
|
||||
state->ref = NULL;
|
||||
state->ref_cursor = REF_CURSOR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Validates hardware source mappings.
|
||||
*
|
||||
* \param[in,out] state Validation state.
|
||||
*/
|
||||
static void pco_validate_src_maps(struct val_state *state)
|
||||
{
|
||||
/* Only check after the legalize pass has run. */
|
||||
if (!state->shader->is_legalized)
|
||||
return;
|
||||
|
||||
bool needs_s124;
|
||||
pco_foreach_func_in_shader (func, state->shader) {
|
||||
state->func = func;
|
||||
|
||||
pco_foreach_instr_in_func (instr, func) {
|
||||
const struct pco_op_info *info = &pco_op_info[instr->op];
|
||||
if (info->type == PCO_OP_TYPE_PSEUDO)
|
||||
continue;
|
||||
|
||||
state->cf_node = &instr->parent_block->cf_node;
|
||||
state->instr = instr;
|
||||
|
||||
state->ref_cursor = REF_CURSOR_INSTR_DEST;
|
||||
pco_foreach_instr_dest (pdest, instr) {
|
||||
state->ref = pdest;
|
||||
unsigned dest_index = pdest - instr->dest;
|
||||
|
||||
if (!info->dest_intrn_map[dest_index])
|
||||
continue;
|
||||
|
||||
enum pco_io mapped_src =
|
||||
PCO_IO_S0 + info->dest_intrn_map[dest_index] - 1;
|
||||
|
||||
bool valid = ref_src_map_valid(*pdest, mapped_src, &needs_s124);
|
||||
PCO_ASSERT(state,
|
||||
valid,
|
||||
"HW register reference should be mapped to %s",
|
||||
needs_s124 ? "S1/S2/S4" : "S0/S2/S3");
|
||||
}
|
||||
|
||||
state->ref_cursor = REF_CURSOR_INSTR_SRC;
|
||||
pco_foreach_instr_src (psrc, instr) {
|
||||
state->ref = psrc;
|
||||
unsigned src_index = psrc - instr->src;
|
||||
|
||||
if (!info->src_intrn_map[src_index])
|
||||
continue;
|
||||
|
||||
enum pco_io mapped_src =
|
||||
PCO_IO_S0 + info->src_intrn_map[src_index] - 1;
|
||||
|
||||
bool valid = ref_src_map_valid(*psrc, mapped_src, &needs_s124);
|
||||
PCO_ASSERT(state,
|
||||
valid,
|
||||
"HW register reference should be mapped to %s",
|
||||
needs_s124 ? "S1/S2/S4" : "S0/S2/S3");
|
||||
}
|
||||
|
||||
state->instr = NULL;
|
||||
state->cf_node = NULL;
|
||||
}
|
||||
|
||||
state->func = NULL;
|
||||
state->ref = NULL;
|
||||
state->ref_cursor = REF_CURSOR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,8 +252,10 @@ void pco_validate_shader(UNUSED pco_shader *shader, UNUSED const char *when)
|
||||
.phase = -1,
|
||||
};
|
||||
|
||||
if (!shader->is_grouped)
|
||||
if (!shader->is_grouped) {
|
||||
pco_validate_ssa(&state);
|
||||
pco_validate_src_maps(&state);
|
||||
}
|
||||
|
||||
puts("finishme: pco_validate_shader");
|
||||
#endif /* NDEBUG */
|
||||
|
||||
Reference in New Issue
Block a user