diff --git a/src/freedreno/ir3/ir3_context.c b/src/freedreno/ir3/ir3_context.c index 50d35386fd8..151eed319da 100644 --- a/src/freedreno/ir3/ir3_context.c +++ b/src/freedreno/ir3/ir3_context.c @@ -437,7 +437,18 @@ ir3_get_predicate(struct ir3_context *ctx, struct ir3_instruction *src) /* condition always goes in predicate register: */ cond->dsts[0]->flags |= IR3_REG_PREDICATE; - cond->dsts[0]->flags &= ~IR3_REG_SHARED; + + /* The builders will mark the dst as shared when both srcs are shared. + * Predicates can't be shared but do support the scalar ALU when marked as + * uniform. + */ + if (cond->dsts[0]->flags & IR3_REG_SHARED) { + cond->dsts[0]->flags &= ~IR3_REG_SHARED; + + if (ctx->compiler->has_scalar_predicates) { + cond->dsts[0]->flags |= IR3_REG_UNIFORM; + } + } _mesa_hash_table_insert(ctx->predicate_conversions, src, cond); return cond; diff --git a/src/freedreno/ir3/ir3_opt_predicates.c b/src/freedreno/ir3/ir3_opt_predicates.c index 976a3d19374..c578ec35f57 100644 --- a/src/freedreno/ir3/ir3_opt_predicates.c +++ b/src/freedreno/ir3/ir3_opt_predicates.c @@ -31,16 +31,23 @@ struct opt_predicates_ctx { }; static bool -is_shared_or_const(struct ir3_register *reg) +cat2_all_srcs_have_flag(struct ir3_instruction *instr, unsigned flags) { - return reg->flags & (IR3_REG_CONST | IR3_REG_SHARED); + return (instr->srcs[0]->flags & flags) && + (instr->srcs_count == 1 || (instr->srcs[1]->flags & flags)); } static bool cat2_needs_scalar_alu(struct ir3_instruction *instr) { - return is_shared_or_const(instr->srcs[0]) && - (instr->srcs_count == 1 || is_shared_or_const(instr->srcs[1])); + return cat2_all_srcs_have_flag(instr, IR3_REG_CONST | IR3_REG_SHARED); +} + +static bool +cat2_may_use_scalar_alu(struct ir3_instruction *instr) +{ + return cat2_all_srcs_have_flag( + instr, IR3_REG_CONST | IR3_REG_SHARED | IR3_REG_IMMED); } static struct ir3_instruction * @@ -58,6 +65,12 @@ clone_with_predicate_dst(struct opt_predicates_ctx *ctx, ir3_instr_move_after(clone, instr); clone->dsts[0]->flags |= IR3_REG_PREDICATE; clone->dsts[0]->flags &= ~(IR3_REG_HALF | IR3_REG_SHARED); + + if (ctx->ir->compiler->has_scalar_predicates && opc_cat(instr->opc) == 2 && + cat2_may_use_scalar_alu(instr)) { + clone->dsts[0]->flags |= IR3_REG_UNIFORM; + } + _mesa_hash_table_insert(ctx->predicate_clones, instr, clone); return clone; } @@ -70,14 +83,16 @@ can_write_predicate(struct opt_predicates_ctx *ctx, case OPC_CMPS_S: case OPC_CMPS_U: case OPC_CMPS_F: - return !cat2_needs_scalar_alu(instr); + return !cat2_needs_scalar_alu(instr) || + ctx->ir->compiler->has_scalar_predicates; case OPC_AND_B: case OPC_OR_B: case OPC_NOT_B: case OPC_XOR_B: case OPC_GETBIT_B: return ctx->ir->compiler->bitops_can_write_predicates && - !cat2_needs_scalar_alu(instr); + (!cat2_needs_scalar_alu(instr) || + ctx->ir->compiler->has_scalar_predicates); default: return false; }