From c0d6be11d6bce38c014524b2a7bf0c8fcebccece Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Thu, 14 Feb 2019 09:46:06 -0500 Subject: [PATCH] freedreno/ir3: fix varying packing vs. tex sharp edge We probably need to rethink how we detect which instruction first defines higher register classes. But for now, this at least fixes the symptom. Signed-off-by: Rob Clark --- src/freedreno/ir3/ir3_ra.c | 32 ++++++++++++++++++++++++++++++-- 1 file 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; + } + } } } } -- 2.30.2