Mesa (master): freedreno/ir3: handle half registers for arrays during register allocation.

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Feb 24 17:42:03 UTC 2020


Module: Mesa
Branch: master
Commit: c822460f851ae6f3c74a01b9eec9ea924a0de12d
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=c822460f851ae6f3c74a01b9eec9ea924a0de12d

Author: Hyunjun Ko <zzoon at igalia.com>
Date:   Mon Nov 18 09:54:09 2019 +0000

freedreno/ir3: handle half registers for arrays during register allocation.

So far we only handle full regs of arrays during pre-allocation.
This patch is to handle half regs of arrays and also consider the size
of half regs when finding out conflicts.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3822>

---

 src/freedreno/ir3/ir3.h         |  3 +++
 src/freedreno/ir3/ir3_context.c |  1 +
 src/freedreno/ir3/ir3_ra.c      | 43 ++++++++++++++++++++++++++++++++---------
 3 files changed, 38 insertions(+), 9 deletions(-)

diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h
index fc82932ba22..f927d1ff204 100644
--- a/src/freedreno/ir3/ir3.h
+++ b/src/freedreno/ir3/ir3.h
@@ -500,6 +500,9 @@ struct ir3_array {
 	unsigned base;      /* base vreg name */
 	unsigned reg;       /* base physical reg */
 	uint16_t start_ip, end_ip;
+
+	/* Indicates if half-precision */
+	bool half;
 };
 
 struct ir3_array * ir3_lookup_array(struct ir3 *ir, unsigned id);
diff --git a/src/freedreno/ir3/ir3_context.c b/src/freedreno/ir3/ir3_context.c
index b44dc4a67f3..b8ec4a7da44 100644
--- a/src/freedreno/ir3/ir3_context.c
+++ b/src/freedreno/ir3/ir3_context.c
@@ -525,6 +525,7 @@ ir3_create_array_load(struct ir3_context *ctx, struct ir3_array *arr, int n,
 		mov->cat1.src_type = TYPE_U16;
 		mov->cat1.dst_type = TYPE_U16;
 		flags |= IR3_REG_HALF;
+		arr->half = true;
 	} else {
 		mov->cat1.src_type = TYPE_U32;
 		mov->cat1.dst_type = TYPE_U32;
diff --git a/src/freedreno/ir3/ir3_ra.c b/src/freedreno/ir3/ir3_ra.c
index f04db4f29ac..6d32c0d08e0 100644
--- a/src/freedreno/ir3/ir3_ra.c
+++ b/src/freedreno/ir3/ir3_ra.c
@@ -366,6 +366,15 @@ is_high(struct ir3_instruction *instr)
 	return !!(instr->regs[0]->flags & IR3_REG_HIGH);
 }
 
+static unsigned
+reg_size_for_array(struct ir3_array *arr)
+{
+	if (arr->half)
+		return DIV_ROUND_UP(arr->length, 2);
+
+	return arr->length;
+}
+
 static int
 size_to_class(unsigned sz, bool half, bool high)
 {
@@ -665,8 +674,8 @@ ra_init(struct ir3_ra_ctx *ctx)
 	base = ctx->class_base[total_class_count];
 	foreach_array (arr, &ctx->ir->array_list) {
 		arr->base = base;
-		ctx->class_alloc_count[total_class_count] += arr->length;
-		base += arr->length;
+		ctx->class_alloc_count[total_class_count] += reg_size_for_array(arr);
+		base += reg_size_for_array(arr);
 	}
 	ctx->alloc_count += ctx->class_alloc_count[total_class_count];
 
@@ -791,7 +800,10 @@ ra_block_compute_live_ranges(struct ir3_ra_ctx *ctx, struct ir3_block *block)
 				 */
 				for (i = 0; i < arr->length; i++) {
 					unsigned name = arr->base + i;
-					ra_set_node_class(ctx->g, name, ctx->set->classes[0]);
+					if(arr->half)
+						ra_set_node_class(ctx->g, name, ctx->set->half_classes[0]);
+					else
+						ra_set_node_class(ctx->g, name, ctx->set->classes[0]);
 				}
 
 				/* indirect write is treated like a write to all array
@@ -1333,9 +1345,9 @@ retry:
 			/* 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 + arr->length,
-					arr2->reg, arr2->reg + arr2->length)) {
-				base = MAX2(base, arr2->reg + arr2->length);
+				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));
 				goto retry;
 			}
 		}
@@ -1361,7 +1373,7 @@ retry:
 			 */
 			if (intersects(arr->start_ip, arr->end_ip,
 							ctx->def[name], ctx->use[name]) &&
-					intersects(base, base + arr->length,
+					intersects(base, base + reg_size_for_array(arr),
 							regid, regid + class_sizes[id->cls])) {
 				base = MAX2(base, regid + class_sizes[id->cls]);
 				goto retry;
@@ -1373,9 +1385,22 @@ retry:
 		for (unsigned i = 0; i < arr->length; i++) {
 			unsigned name, reg;
 
-			name = arr->base + i;
-			reg = ctx->set->gpr_to_ra_reg[0][base++];
+			if (arr->half) {
+				/* Doesn't need to do this on older generations than a6xx,
+				 * since there's no conflict between full regs and half regs
+				 * on them.
+				 *
+				 * TODO Presumably "base" could start from 0 respectively
+				 * for half regs of arrays on older generations.
+				 */
+				unsigned base_half = base * 2 + i;
+				reg = ctx->set->gpr_to_ra_reg[0+HALF_OFFSET][base_half];
+				base = base_half / 2 + 1;
+			} else {
+				reg = ctx->set->gpr_to_ra_reg[0][base++];
+			}
 
+			name = arr->base + i;
 			ra_set_node_reg(ctx->g, name, reg);
 		}
 	}



More information about the mesa-commit mailing list