diff --git a/src/imagination/pco/pco_internal.h b/src/imagination/pco/pco_internal.h index 8fa174693f9..0c25ca57751 100644 --- a/src/imagination/pco/pco_internal.h +++ b/src/imagination/pco/pco_internal.h @@ -1434,6 +1434,38 @@ static inline enum pco_io pco_ref_get_io(pco_ref ref) return ref.val; } +/** + * \brief Returns the movw01 value of an I/O reference type. + * + * \param[in] ref Reference. + * \return movw01 value. + */ +static inline enum pco_movw01 pco_ref_get_movw01(pco_ref ref) +{ + /* Default/unused case. */ + if (pco_ref_is_null(ref)) + return PCO_MOVW01_FT0; + + switch (pco_ref_get_io(ref)) { + case PCO_IO_FT0: + return PCO_MOVW01_FT0; + + case PCO_IO_FT1: + return PCO_MOVW01_FT1; + + case PCO_IO_FT2: + return PCO_MOVW01_FT2; + + case PCO_IO_FTE: + return PCO_MOVW01_FTE; + + default: + break; + } + + unreachable(); +} + /** * \brief Returns the predicate from its reference type. * diff --git a/src/imagination/pco/pco_map.py b/src/imagination/pco/pco_map.py index e225095b36c..d96545714c1 100644 --- a/src/imagination/pco/pco_map.py +++ b/src/imagination/pco/pco_map.py @@ -163,6 +163,36 @@ enum_map(OM_SCHED.t, F_SCHED_CTRL, [ ('wdf', 'wdf'), ]) +enum_map(OM_TST_OP_MAIN.t, F_TST_OP, [ + ('zero', 'z'), + ('gzero', 'gz'), + ('gezero', 'gez'), + ('carry', 'c'), + ('equal', 'e'), + ('greater', 'g'), + ('gequal', 'ge'), + ('notequal', 'ne'), + ('less', 'l'), + ('lequal', 'le'), +]) + +enum_map(OM_TST_TYPE_MAIN.t, F_TST_TYPE, [ + ('f32', 'f32'), + ('u16', 'u16'), + ('s16', 's16'), + ('u8', 'u8'), + ('s8', 's8'), + ('u32', 'u32'), + ('s32', 's32'), +]) + +enum_map(RM_ELEM.t, F_MASKW0, [ + ('e0', 'e0'), + ('e1', 'e1'), + ('e2', 'e2'), + ('e3', 'e3'), +], pass_zero=['e0', 'e1', 'e2', 'e3']) + encode_maps = {} group_maps = {} @@ -598,6 +628,48 @@ encode_map(O_PCK, ] ) +encode_map(O_TST, + encodings=[ + (I_TST_EXT, [ + ('tst_op', OM_TST_OP_MAIN), + ('pwen', ('!pco_ref_is_null', 'dest[1]')), + ('type', OM_TST_TYPE_MAIN), + ('p2end', OM_PHASE2END), + ('elem', (RM_ELEM, 'src[0]')) + ]), + (I_TST, [ + ('tst_op', OM_TST_OP_MAIN), + ('pwen', ('!pco_ref_is_null', 'dest[1]')), + ], [ + (OM_TST_OP_MAIN, '<= PCO_TST_OP_MAIN_NOTEQUAL'), + (OM_TST_TYPE_MAIN, '== PCO_TST_TYPE_MAIN_F32'), + (OM_PHASE2END, '== false'), + (OM_TST_TYPE_MAIN, '== PCO_TST_TYPE_MAIN_F32'), + (RM_ELEM, 'src[0]', '== 0'), + (RM_ELEM, 'src[1]', '== 0'), + ]) + ] +) + +encode_map(O_MOVC, + encodings=[ + (I_MOVC_EXT, [ + ('movw0', ('pco_ref_get_movw01', 'src[1]')), + ('movw1', ('pco_ref_get_movw01', 'src[3]')), + ('maskw0', (RM_ELEM, 'dest[0]')), + ('aw', False), + ('p2end', OM_PHASE2END) + ]), + (I_MOVC, [ + ('movw0', ('pco_ref_get_movw01', 'src[1]')), + ('movw1', ('pco_ref_get_movw01', 'src[3]')), + ], [ + (RM_ELEM, 'dest[0]', '== 0b1111'), + (OM_PHASE2END, '== false'), + ]) + ] +) + encode_map(O_UVSW_WRITE, encodings=[ (I_UVSW_WRITE_IMM, [ @@ -822,6 +894,40 @@ group_map(O_PCK, dests=[('w[0]', ('2_pck', 'dest[0]'), 'ft2')] ) +group_map(O_SCMP, + hdr=(I_IGRP_HDR_MAIN, [ + ('oporg', 'p0_p1_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]']), + ('1', O_MBYP, ['ft1'], ['src[1]']), + ('2_tst', O_TST, ['ftt', '_'], ['is1', 'is2'], [(OM_TST_OP_MAIN, OM_TST_OP_MAIN), (OM_TST_TYPE_MAIN, 'f32')]), + ('2_pck', O_PCK, ['ft2'], ['_'], [(OM_PCK_FMT, 'one')]), + ('2_mov', O_MOVC, ['dest[0]', '_'], ['ftt', 'ft2', 'is4', '_', '_']) + ], + srcs=[ + ('s[0]', ('0', 'src[0]'), 's0'), + ('s[1]', 'pco_zero'), + ('s[3]', ('1', 'src[0]'), 's3'), + ], + iss=[ + ('is[0]', 's1'), + ('is[1]', 'ft0'), + ('is[2]', 'ft1'), + ('is[4]', 'fte'), + ], + dests=[ + ('w[0]', ('2_mov', 'dest[0]'), 'w0'), + ] +) + group_map(O_UVSW_WRITE, hdr=(I_IGRP_HDR_MAIN, [ ('oporg', 'be'), diff --git a/src/imagination/pco/pco_nir.c b/src/imagination/pco/pco_nir.c index 14c683ca828..aa89be5956b 100644 --- a/src/imagination/pco/pco_nir.c +++ b/src/imagination/pco/pco_nir.c @@ -25,6 +25,8 @@ static const struct spirv_to_nir_options pco_base_spirv_options = { static const nir_shader_compiler_options pco_base_nir_options = { .fuse_ffma32 = true, + .has_fused_comp_and_csel = true, + .lower_fdiv = true, .lower_fquantize2f16 = true, .lower_layer_fs_input_to_sysval = true, diff --git a/src/imagination/pco/pco_ops.py b/src/imagination/pco/pco_ops.py index 2a748fb4f2a..1c41172b34e 100644 --- a/src/imagination/pco/pco_ops.py +++ b/src/imagination/pco/pco_ops.py @@ -141,6 +141,15 @@ OM_LP = op_mod('lp', BaseType.bool) OM_SCALE = op_mod('scale', BaseType.bool) OM_ROUNDZERO = op_mod('roundzero', BaseType.bool) OM_S = op_mod('s', BaseType.bool) +OM_TST_TYPE_MAIN = op_mod_enum('tst_type_main', [ + 'f32', + 'u16', + 's16', + 'u8', + 's8', + 'u32', + 's32', +]) OM_TST_OP_MAIN = op_mod_enum('tst_op_main', [ ('zero', 'z'), ('gzero', 'gz'), @@ -281,6 +290,9 @@ O_FRCP = hw_op('frcp', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]]) O_MBYP = hw_op('mbyp', OM_ALU, 1, 1, [], [[RM_ABS, RM_NEG]]) O_PCK = hw_op('pck', 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]]) + # TODO # O_PCK_ELEM = pseudo_op('pck.elem', OM_ALU_RPT1 + [OM_PCK_FMT, OM_ROUNDZERO, OM_SCALE], 1, 2) @@ -310,6 +322,9 @@ O_DITRP = hw_op('ditrp', [OM_EXEC_CND, OM_ITR_MODE, OM_SAT, OM_SCHED, OM_F16], 1 O_DITRP_WRITE = hw_op('ditrp.write', [OM_EXEC_CND, OM_ITR_MODE, OM_SAT, OM_SCHED, OM_F16], 1, 4) O_DITRP_READ = hw_op('ditrp.read', [OM_EXEC_CND, OM_ITR_MODE, OM_SAT, OM_SCHED, OM_F16], 1, 3) +# Combination (> 1 instructions per group). +O_SCMP = hw_op('scmp', OM_ALU + [OM_TST_OP_MAIN], 1, 2, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]]) + # Pseudo-ops (unmapped). O_NEG = pseudo_op('neg', OM_ALU, 1, 1) O_ABS = pseudo_op('abs', OM_ALU, 1, 1) diff --git a/src/imagination/pco/pco_trans_nir.c b/src/imagination/pco/pco_trans_nir.c index 92e9b5c7c64..a78752ae142 100644 --- a/src/imagination/pco/pco_trans_nir.c +++ b/src/imagination/pco/pco_trans_nir.c @@ -603,6 +603,44 @@ static pco_instr *pco_trans_nir_vec(trans_ctx *tctx, return instr; } +/** + * \brief Translates a NIR float set-on comparison into PCO. + * + * \param[in,out] tctx Translation context. + * \param[in] op The NIR op. + * \param[in] dest Instruction destination. + * \param[in] src0 First comparison source. + * \param[in] src1 Second comparison source. + * \return The translated PCO instruction. + */ +static pco_instr * +trans_scmp(trans_ctx *tctx, nir_op op, pco_ref dest, pco_ref src0, pco_ref src1) +{ + enum pco_tst_op_main tst_op_main; + switch (op) { + case nir_op_slt: + tst_op_main = PCO_TST_OP_MAIN_LESS; + break; + + case nir_op_sge: + tst_op_main = PCO_TST_OP_MAIN_GEQUAL; + break; + + case nir_op_seq: + tst_op_main = PCO_TST_OP_MAIN_EQUAL; + break; + + case nir_op_sne: + tst_op_main = PCO_TST_OP_MAIN_NOTEQUAL; + break; + + default: + unreachable(); + } + + return pco_scmp(&tctx->b, dest, src0, src1, .tst_op_main = tst_op_main); +} + /** * \brief Translates a NIR alu instruction into PCO. * @@ -651,6 +689,13 @@ static pco_instr *trans_alu(trans_ctx *tctx, nir_alu_instr *alu) instr = pco_frcp(&tctx->b, dest, src[0]); break; + case nir_op_slt: + case nir_op_sge: + case nir_op_seq: + case nir_op_sne: + instr = trans_scmp(tctx, alu->op, dest, src[0], src[1]); + break; + case nir_op_pack_unorm_4x8: instr = pco_pck(&tctx->b, dest,