ir3: teach backend about alias
Take the properties of alias.{rt,tex} and its registers into account:
- Don't count alias registers for GPR usage;
- Allow all immediates in alias regs;
- Fix properties like is_barrier and (ss) support;
- alias.rt dst is not a GPR, don't use it in legalize/postsched to track
dependencies;
Signed-off-by: Job Noorman <jnoorman@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31222>
This commit is contained in:
+21
-3
@@ -275,21 +275,39 @@ ir3_collect_info(struct ir3_shader_variant *v)
|
||||
bool in_preamble = false;
|
||||
bool has_eq = false;
|
||||
|
||||
/* Track which registers are currently aliases because they shouldn't be
|
||||
* included in the GPR footprint.
|
||||
*/
|
||||
regmask_t aliases;
|
||||
|
||||
/* Full and half aliases do not overlap so treat them as !mergedregs. */
|
||||
regmask_init(&aliases, false);
|
||||
|
||||
foreach_block (block, &shader->block_list) {
|
||||
int sfu_delay = 0, mem_delay = 0;
|
||||
|
||||
foreach_instr (instr, &block->instr_list) {
|
||||
|
||||
foreach_src (reg, instr) {
|
||||
collect_reg_info(instr, reg, info);
|
||||
if (!is_reg_gpr(reg) || !regmask_get(&aliases, reg)) {
|
||||
collect_reg_info(instr, reg, info);
|
||||
}
|
||||
}
|
||||
|
||||
foreach_dst (reg, instr) {
|
||||
if (is_dest_gpr(reg)) {
|
||||
if (instr->opc == OPC_ALIAS &&
|
||||
instr->cat7.alias_scope == ALIAS_TEX) {
|
||||
regmask_set(&aliases, instr->dsts[0]);
|
||||
} else if (is_dest_gpr(reg)) {
|
||||
collect_reg_info(instr, reg, info);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_tex(instr)) {
|
||||
/* All aliases are cleared after they are used. */
|
||||
regmask_init(&aliases, false);
|
||||
}
|
||||
|
||||
if ((instr->opc == OPC_STP || instr->opc == OPC_LDP)) {
|
||||
unsigned components = instr->srcs[2]->uim_val;
|
||||
|
||||
@@ -1479,7 +1497,7 @@ ir3_valid_flags(struct ir3_instruction *instr, unsigned n, unsigned flags)
|
||||
bool
|
||||
ir3_valid_immediate(struct ir3_instruction *instr, int32_t immed)
|
||||
{
|
||||
if (instr->opc == OPC_MOV || is_meta(instr))
|
||||
if (instr->opc == OPC_MOV || is_meta(instr) || instr->opc == OPC_ALIAS)
|
||||
return true;
|
||||
|
||||
if (is_mem(instr)) {
|
||||
|
||||
+21
-2
@@ -159,6 +159,17 @@ typedef enum ir3_register_flags {
|
||||
|
||||
/* Render target dst. Only used by alias.rt. */
|
||||
IR3_REG_RT = BIT(20),
|
||||
|
||||
/* Register that is initialized using alias.tex (or will be once the
|
||||
* alias.tex instructions are inserted). Before alias.tex is inserted, alias
|
||||
* registers may contain things that are normally not allowed by the owning
|
||||
* instruction (e.g., consts or immediates) because they will be replaced by
|
||||
* GPRs later.
|
||||
* Note that if wrmask > 1, this will be set if any of the registers is an
|
||||
* alias, even though not all of them may be. We currently have no way to
|
||||
* tell which ones are actual aliases.
|
||||
*/
|
||||
IR3_REG_ALIAS = BIT(21),
|
||||
} ir3_register_flags;
|
||||
|
||||
struct ir3_register {
|
||||
@@ -1148,7 +1159,7 @@ is_mem(struct ir3_instruction *instr)
|
||||
static inline bool
|
||||
is_barrier(struct ir3_instruction *instr)
|
||||
{
|
||||
return (opc_cat(instr->opc) == 7);
|
||||
return (opc_cat(instr->opc) == 7) && instr->opc != OPC_ALIAS;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
@@ -1418,8 +1429,10 @@ dest_regs(struct ir3_instruction *instr)
|
||||
static inline bool
|
||||
is_reg_gpr(const struct ir3_register *reg)
|
||||
{
|
||||
if (reg->flags & (IR3_REG_CONST | IR3_REG_IMMED | IR3_REG_PREDICATE))
|
||||
if (reg->flags &
|
||||
(IR3_REG_CONST | IR3_REG_IMMED | IR3_REG_PREDICATE | IR3_REG_RT)) {
|
||||
return false;
|
||||
}
|
||||
if (reg_num(reg) == REG_A0)
|
||||
return false;
|
||||
if (!(reg->flags & (IR3_REG_SSA | IR3_REG_RELATIV)) &&
|
||||
@@ -2091,6 +2104,12 @@ needs_ss(const struct ir3_compiler *compiler, struct ir3_instruction *producer,
|
||||
return is_ss_producer(producer);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
supports_ss(struct ir3_instruction *instr)
|
||||
{
|
||||
return opc_cat(instr->opc) < 5 || instr->opc == OPC_ALIAS;
|
||||
}
|
||||
|
||||
/* The soft delay for approximating the cost of (ss). */
|
||||
static inline unsigned
|
||||
soft_ss_delay(struct ir3_instruction *instr)
|
||||
|
||||
@@ -231,6 +231,9 @@ delay_update(struct ir3_legalize_state *state,
|
||||
return;
|
||||
|
||||
foreach_dst_n (dst, n, instr) {
|
||||
if (dst->flags & IR3_REG_RT)
|
||||
continue;
|
||||
|
||||
unsigned elems = post_ra_reg_elems(dst);
|
||||
unsigned num = post_ra_reg_num(dst);
|
||||
unsigned dst_cycle = cycle;
|
||||
@@ -523,6 +526,8 @@ legalize_block(struct ir3_legalize_ctx *ctx, struct ir3_block *block)
|
||||
}
|
||||
|
||||
foreach_dst (reg, n) {
|
||||
if (reg->flags & IR3_REG_RT)
|
||||
continue;
|
||||
if (needs_ss_war(state, reg, n_is_scalar_alu)) {
|
||||
apply_ss(n, state, mergedregs);
|
||||
last_input_needs_ss = false;
|
||||
@@ -540,7 +545,7 @@ legalize_block(struct ir3_legalize_ctx *ctx, struct ir3_block *block)
|
||||
* clever if we were aware of this during scheduling, but
|
||||
* this should be a pretty rare case:
|
||||
*/
|
||||
if ((n->flags & IR3_INSTR_SS) && (opc_cat(n->opc) >= 5)) {
|
||||
if ((n->flags & IR3_INSTR_SS) && !supports_ss(n)) {
|
||||
struct ir3_instruction *nop;
|
||||
nop = ir3_NOP(&build);
|
||||
nop->flags |= IR3_INSTR_SS;
|
||||
|
||||
@@ -488,6 +488,8 @@ calculate_deps(struct ir3_postsched_deps_state *state,
|
||||
foreach_dst_n (reg, i, node->instr) {
|
||||
if (reg->wrmask == 0)
|
||||
continue;
|
||||
if (reg->flags & IR3_REG_RT)
|
||||
continue;
|
||||
if (reg->flags & IR3_REG_RELATIV) {
|
||||
/* mark the entire array as written: */
|
||||
for (unsigned j = 0; j < reg->size; j++) {
|
||||
|
||||
@@ -66,7 +66,7 @@ static void
|
||||
validate_src(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr,
|
||||
struct ir3_register *reg)
|
||||
{
|
||||
if (reg->flags & IR3_REG_IMMED)
|
||||
if ((reg->flags & IR3_REG_IMMED) && !(reg->flags & IR3_REG_ALIAS))
|
||||
validate_assert(ctx, ir3_valid_immediate(instr, reg->iim_val));
|
||||
|
||||
if (!(reg->flags & IR3_REG_SSA) || !reg->def)
|
||||
|
||||
Reference in New Issue
Block a user