diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/freedreno/ir3/ir3_ra.c | 32 |
1 files changed, 30 insertions, 2 deletions
diff --git a/src/freedreno/ir3/ir3_ra.c b/src/freedreno/ir3/ir3_ra.c index f951acd5eef..a9e1894a350 100644 --- a/src/freedreno/ir3/ir3_ra.c +++ b/src/freedreno/ir3/ir3_ra.c @@ -503,8 +503,8 @@ get_definer(struct ir3_ra_ctx *ctx, struct ir3_instruction *instr, *sz = MAX2(*sz, dsz); - debug_assert(instr->opc == OPC_META_FO); - *off = MAX2(*off, instr->fo.off); + if (instr->opc == OPC_META_FO) + *off = MAX2(*off, instr->fo.off); d = dd; } @@ -531,8 +531,36 @@ ra_block_find_definers(struct ir3_ra_ctx *ctx, struct ir3_block *block) } else if (instr->regs[0]->flags & IR3_REG_ARRAY) { id->cls = total_class_count; } else { + /* and the normal case: */ id->defn = get_definer(ctx, instr, &id->sz, &id->off); id->cls = size_to_class(id->sz, is_half(id->defn), is_high(id->defn)); + + /* this is a bit of duct-tape.. if we have a scenario like: + * + * sam (f32)(x) out.x, ... + * sam (f32)(x) out.y, ... + * + * Then the fanout/split meta instructions for the two different + * tex instructions end up grouped as left/right neighbors. The + * upshot is that in when you get_definer() on one of the meta:fo's + * you get definer as the first sam with sz=2, but when you call + * get_definer() on the either of the sam's you get itself as the + * definer with sz=1. + * + * (We actually avoid this scenario exactly, the neighbor links + * prevent one of the output mov's from being eliminated, so this + * hack should be enough. But probably we need to rethink how we + * find the "defining" instruction.) + * + * TODO how do we figure out offset properly... + */ + if (id->defn != instr) { + struct ir3_ra_instr_data *did = &ctx->instrd[id->defn->ip]; + if (did->sz < id->sz) { + did->sz = id->sz; + did->cls = id->cls; + } + } } } } |