freedreno/ir3: fix varying packing vs. tex sharp edge
authorRob Clark <robdclark@gmail.com>
Thu, 14 Feb 2019 14:46:06 +0000 (09:46 -0500)
committerRob Clark <robdclark@gmail.com>
Sat, 16 Feb 2019 21:26:14 +0000 (16:26 -0500)
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 <robdclark@gmail.com>
src/freedreno/ir3/ir3_ra.c

index f951acd5eefb2d481a157948bf34d009c788e5c1..a9e1894a3504ae997411e9ffe86ecb000db631b4 100644 (file)
@@ -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;
+                               }
+                       }
                }
        }
 }