diff --git a/src/imagination/pco/pco_legalize.c b/src/imagination/pco/pco_legalize.c index 8d644a78245..be64a3d5706 100644 --- a/src/imagination/pco/pco_legalize.c +++ b/src/imagination/pco/pco_legalize.c @@ -155,6 +155,29 @@ static inline bool xfer_op_mods(pco_instr *dest, pco_instr *src) return all_xfered; } +/** + * \brief Legalize fence pseudo instruction. + * + * \param[in,out] instr PCO instr. + * \return True if progress was made. + */ +static bool legalize_fence(pco_instr *instr) +{ + if (instr->op != PCO_OP_FENCE) + return false; + + pco_builder b = + pco_builder_create(instr->parent_func, pco_cursor_before_instr(instr)); + + pco_flush_p0(&b); + pco_br_next(&b, .exec_cnd = PCO_EXEC_CND_E1_Z1); + pco_br_next(&b, .exec_cnd = PCO_EXEC_CND_E1_Z0); + + pco_instr_delete(instr); + + return true; +} + static bool legalize_pseudo(pco_instr *instr) { switch (instr->op) { @@ -396,6 +419,12 @@ static bool try_legalize_large_hwreg_offsets(pco_instr *instr, return true; } +/** + * \brief Insert pseudo fences around DITR and DITRP instructions. + * + * \param[in,out] instr PCO instr. + * \return True if progress was made. + */ static bool try_legalize_ditr_fence(pco_instr *instr) { if (instr->op != PCO_OP_DITR && instr->op != PCO_OP_DITRP) @@ -403,14 +432,10 @@ static bool try_legalize_ditr_fence(pco_instr *instr) pco_builder b = pco_builder_create(instr->parent_func, pco_cursor_before_instr(instr)); - pco_flush_p0(&b); - pco_br_next(&b, .exec_cnd = PCO_EXEC_CND_E1_Z1); - pco_br_next(&b, .exec_cnd = PCO_EXEC_CND_E1_Z0); + pco_fence(&b); b.cursor = pco_cursor_after_instr(instr); - pco_flush_p0(&b); - pco_br_next(&b, .exec_cnd = PCO_EXEC_CND_E1_Z1); - pco_br_next(&b, .exec_cnd = PCO_EXEC_CND_E1_Z0); + pco_fence(&b); return true; } @@ -457,6 +482,12 @@ bool pco_legalize(pco_shader *shader) } } + pco_foreach_func_in_shader (func, shader) { + pco_foreach_instr_in_func_safe (instr, func) { + progress |= legalize_fence(instr); + } + } + shader->is_legalized = true; return progress; } @@ -479,5 +510,10 @@ bool pco_post_ra_legalize(pco_shader *shader) } } + pco_foreach_func_in_shader (func, shader) { + pco_foreach_instr_in_func_safe (instr, func) { + progress |= legalize_fence(instr); + } + } return progress; } diff --git a/src/imagination/pco/pco_ops.py b/src/imagination/pco/pco_ops.py index 797b9236910..203b8d2c6d7 100644 --- a/src/imagination/pco/pco_ops.py +++ b/src/imagination/pco/pco_ops.py @@ -518,6 +518,7 @@ O_MOV = pseudo_op('mov', OM_ALU, 1, 1) O_MOV_OFFSET = pseudo_op('mov.offset', OM_ALU + [OM_OFFSET_SD], 1, 2) O_VEC = pseudo_op('vec', [OM_EXEC_CND], 1, VARIABLE) O_COMP = pseudo_op('comp', [], 1, 2) +O_FENCE = pseudo_op('fence') O_OP_ATOMIC_OFFSET = pseudo_op('op.atomic.offset', OM_ALU_ATOMEXT + [OM_ATOM_OP], 2, 4, [], [[RM_ABS, RM_NEG], [RM_ABS, RM_NEG]])