From 912ad09112556d69e3c5fc75bf64416270b4602f Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Fri, 17 Jul 2020 11:06:55 -0700 Subject: [PATCH] freedreno/ir3/ra: fix array conflicts for split/merged Properly handle the difference between split and merged register file when determining where arrays can fit without conflicting with other arrays or pre-colored instructions. 1) if not mergedregs, only consider other things with same precision as potentially conflicting 2) if mergedregs, calculate everything in therms of half-regs and convert back to fullregs in the end Signed-off-by: Rob Clark Part-of: --- src/freedreno/ir3/ir3_ra.c | 79 +++++++++++++++++++++++++++++--------- 1 file changed, 61 insertions(+), 18 deletions(-) diff --git a/src/freedreno/ir3/ir3_ra.c b/src/freedreno/ir3/ir3_ra.c index 156299fc18e..abf665288fd 100644 --- a/src/freedreno/ir3/ir3_ra.c +++ b/src/freedreno/ir3/ir3_ra.c @@ -115,15 +115,6 @@ intersects(unsigned a_start, unsigned a_end, unsigned b_start, unsigned b_end) return !((a_start >= b_end) || (b_start >= a_end)); } -static unsigned -reg_size_for_array(struct ir3_array *arr) -{ - if (arr->half) - return DIV_ROUND_UP(arr->length, 2); - - return arr->length; -} - static bool instr_before(struct ir3_instruction *a, struct ir3_instruction *b) { @@ -1246,6 +1237,15 @@ static void assign_arr_base(struct ir3_ra_ctx *ctx, struct ir3_array *arr, struct ir3_instruction **precolor, unsigned nprecolor) { + /* In the mergedregs case, we convert full precision arrays + * to their effective half-precision base, and find conflicts + * amongst all other arrays/inputs. + * + * In the splitregs case (halfreg file and fullreg file do + * not conflict), we ignore arrays and other pre-colors that + * are not the same precision. + */ + bool mergedregs = ctx->v->mergedregs; unsigned base = 0; /* figure out what else we conflict with which has already @@ -1255,14 +1255,34 @@ retry: foreach_array (arr2, &ctx->ir->array_list) { if (arr2 == arr) break; - if (arr2->end_ip == 0) + ra_assert(ctx, arr2->start_ip <= arr2->end_ip); + + unsigned base2 = arr2->reg; + unsigned len2 = arr2->length; + unsigned len = arr->length; + + if (mergedregs) { + /* convert into half-reg space: */ + if (!arr2->half) { + base2 *= 2; + len2 *= 2; + } + if (!arr->half) { + len *= 2; + } + } else if (arr2->half != arr->half) { + /* for split-register-file mode, we only conflict with + * other arrays of same precision: + */ continue; + } + /* if it intersects with liverange AND register range.. */ if (intersects(arr->start_ip, arr->end_ip, arr2->start_ip, arr2->end_ip) && - intersects(base, base + reg_size_for_array(arr), - arr2->reg, arr2->reg + reg_size_for_array(arr2))) { - base = MAX2(base, arr2->reg + reg_size_for_array(arr2)); + intersects(base, base + len, + base2, base2 + len2)) { + base = MAX2(base, base2 + len2); goto retry; } } @@ -1280,21 +1300,44 @@ retry: if (id->off > 0) continue; - unsigned name = ra_name(ctx, id); - unsigned regid = instr->regs[0]->num; + unsigned name = ra_name(ctx, id); + unsigned regid = instr->regs[0]->num; + unsigned reglen = class_sizes[id->cls]; + unsigned len = arr->length; + + if (mergedregs) { + /* convert into half-reg space: */ + if (!is_half(instr)) { + regid *= 2; + reglen *= 2; + } + if (!arr->half) { + len *= 2; + } + } else if (is_half(instr) != arr->half) { + /* for split-register-file mode, we only conflict with + * other arrays of same precision: + */ + continue; + } /* Check if array intersects with liverange AND register * range of the input: */ if (intersects(arr->start_ip, arr->end_ip, ctx->def[name], ctx->use[name]) && - intersects(base, base + reg_size_for_array(arr), - regid, regid + class_sizes[id->cls])) { - base = MAX2(base, regid + class_sizes[id->cls]); + intersects(base, base + len, + regid, regid + reglen)) { + base = MAX2(base, regid + reglen); goto retry; } } + /* convert back from half-reg space to fullreg space: */ + if (mergedregs && !arr->half) { + base = DIV_ROUND_UP(base, 2); + } + arr->reg = base; } -- 2.30.2