aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/freedreno/ir3/ir3_ra.c32
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;
+ }
+ }
}
}
}