Mesa (master): freedreno/ir3: drop deref nodes

Rob Clark robclark at kemper.freedesktop.org
Sun Mar 8 21:57:11 UTC 2015


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

Author: Rob Clark <robclark at freedesktop.org>
Date:   Wed Feb  4 16:07:44 2015 -0500

freedreno/ir3: drop deref nodes

The meta-deref instruction doesn't really do what we need for relative
destination.  Instead, since each instruction can reference at most a
single address value, track the dependency on the address register via
instr->address.  This lets us express the dependency regardless of
whether it is used for dst and/or src.

The foreach_ssa_src{_n} iterator macros now also iterates the address
register so, at least in SSA form, the address register behaves as an
additional virtual src to the instruction.  Which is pretty much what
we want, as far as scheduling/etc.

TODO:
For now, the foreach_src{_n} iterators are unchanged.  We could wrap
the address in an ir3_register and make the foreach_src_{_n} iterators
behave the same way.  But that seems unnecessary at this point, since
we mainly care about the address dependency when in SSA form.

Signed-off-by: Rob Clark <robclark at freedesktop.org>

---

 src/gallium/drivers/freedreno/ir3/instr-a3xx.h   |    3 --
 src/gallium/drivers/freedreno/ir3/ir3.h          |   35 ++++++++--------
 src/gallium/drivers/freedreno/ir3/ir3_compiler.c |   46 ++++++----------------
 src/gallium/drivers/freedreno/ir3/ir3_cp.c       |    3 ++
 src/gallium/drivers/freedreno/ir3/ir3_dump.c     |   16 ++++----
 src/gallium/drivers/freedreno/ir3/ir3_ra.c       |   19 ++++-----
 src/gallium/drivers/freedreno/ir3/ir3_sched.c    |   11 +-----
 7 files changed, 53 insertions(+), 80 deletions(-)

diff --git a/src/gallium/drivers/freedreno/ir3/instr-a3xx.h b/src/gallium/drivers/freedreno/ir3/instr-a3xx.h
index b7e19c8..c685fb1 100644
--- a/src/gallium/drivers/freedreno/ir3/instr-a3xx.h
+++ b/src/gallium/drivers/freedreno/ir3/instr-a3xx.h
@@ -204,9 +204,6 @@ typedef enum {
 	/* branches/flow control */
 	OPC_META_FLOW = 4,
 	OPC_META_PHI = 5,
-	/* relative addressing */
-	OPC_META_DEREF = 6,
-
 
 } opc_t;
 
diff --git a/src/gallium/drivers/freedreno/ir3/ir3.h b/src/gallium/drivers/freedreno/ir3/ir3.h
index 3d3ad07..3093285 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3.h
+++ b/src/gallium/drivers/freedreno/ir3/ir3.h
@@ -79,18 +79,19 @@ struct ir3_register {
 		 * the component is in the low two bits of the reg #, so
 		 * rN.x becomes: (N << 2) | x
 		 */
-		int num;
+		int   num;
 		/* immediate: */
-		int     iim_val;
-		float   fim_val;
+		int   iim_val;
+		float fim_val;
 		/* relative: */
-		int offset;
-		/* for IR3_REG_SSA, src registers contain ptr back to
-		 * assigning instruction.
-		 */
-		struct ir3_instruction *instr;
+		int   offset;
 	};
 
+	/* for IR3_REG_SSA, src registers contain ptr back to
+	 * assigning instruction.
+	 */
+	struct ir3_instruction *instr;
+
 	union {
 		/* used for cat5 instructions, but also for internal/IR level
 		 * tracking of what registers are read/written by an instruction.
@@ -209,9 +210,6 @@ struct ir3_instruction {
 		struct {
 			struct ir3_block *block;
 		} inout;
-		struct {
-			int off;              /* offset relative to addr reg */
-		} deref;
 
 		/* XXX keep this as big as all other union members! */
 		uint32_t info[3];
@@ -260,6 +258,12 @@ struct ir3_instruction {
 		struct ir3_instruction *left, *right;
 		uint16_t left_cnt, right_cnt;
 	} cp;
+
+	/* an instruction can reference at most one address register amongst
+	 * it's src/dst registers.  Beyond that, you need to insert mov's.
+	 */
+	struct ir3_instruction *address;
+
 	struct ir3_instruction *next;
 #ifdef DEBUG
 	uint32_t serialno;
@@ -445,11 +449,6 @@ static inline bool is_meta(struct ir3_instruction *instr)
 	return (instr->category == -1);
 }
 
-static inline bool is_addr(struct ir3_instruction *instr)
-{
-	return is_meta(instr) && (instr->opc == OPC_META_DEREF);
-}
-
 static inline bool writes_addr(struct ir3_instruction *instr)
 {
 	if (instr->regs_count > 0) {
@@ -499,11 +498,15 @@ static inline bool reg_gpr(struct ir3_register *r)
 
 static inline unsigned __ssa_src_cnt(struct ir3_instruction *instr)
 {
+	if (instr->address)
+		return instr->regs_count + 1;
 	return instr->regs_count;
 }
 
 static inline struct ir3_instruction * __ssa_src_n(struct ir3_instruction *instr, unsigned n)
 {
+	if (n == (instr->regs_count + 0))
+		return instr->address;
 	return ssa(instr->regs[n]);
 }
 
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_compiler.c b/src/gallium/drivers/freedreno/ir3/ir3_compiler.c
index 8551eeb..4b73390 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_compiler.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_compiler.c
@@ -624,16 +624,18 @@ ssa_src(struct ir3_compile_context *ctx, struct ir3_register *reg,
 		 * we must generate a fanin instruction to collect all possible
 		 * array elements that the instruction could address together:
 		 */
-		unsigned i, j, aid = src_array_id(ctx, src);
+		unsigned aid   = src_array_id(ctx, src);
+		unsigned first = ctx->array[aid].first;
+		unsigned last  = ctx->array[aid].last;
+		unsigned off   = src->Index - first; /* vec4 offset */
+		unsigned i, j;
+
+		reg->size = 4 * (1 + last - first);
+		reg->offset = regid(off, chan);
 
 		if (ctx->array[aid].fanin) {
 			instr = ctx->array[aid].fanin;
 		} else {
-			unsigned first, last;
-
-			first = ctx->array[aid].first;
-			last  = ctx->array[aid].last;
-
 			instr = ir3_instr_create2(ctx->block, -1, OPC_META_FI,
 					1 + (4 * (last + 1 - first)));
 			ir3_reg_create(instr, 0, 0);
@@ -756,7 +758,6 @@ add_src_reg_wrmask(struct ir3_compile_context *ctx,
 {
 	unsigned flags = 0, num = 0;
 	struct ir3_register *reg;
-	struct ir3_instruction *orig = NULL;
 
 	switch (src->File) {
 	case TGSI_FILE_IMMEDIATE:
@@ -815,28 +816,15 @@ add_src_reg_wrmask(struct ir3_compile_context *ctx,
 		/* shouldn't happen, and we can't cope with it below: */
 		compile_assert(ctx, wrmask == 0x1);
 
-		/* wrap in a meta-deref to track both the src and address: */
-		orig = instr;
-
-		instr = ir3_instr_create(ctx->block, -1, OPC_META_DEREF);
-		ir3_reg_create(instr, 0, 0);
-		ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = ctx->block->address;
+		compile_assert(ctx, ctx->block->address);
+		if (instr->address)
+			compile_assert(ctx, ctx->block->address == instr->address);
 
-		if (src->File != TGSI_FILE_CONSTANT) {
-			unsigned aid = src_array_id(ctx, src);
-			unsigned off = src->Index - ctx->array[aid].first; /* vec4 offset */
-			instr->deref.off = regid(off, chan);
-		}
+		instr->address = ctx->block->address;
 	}
 
 	reg = ir3_reg_create(instr, regid(num, chan), flags);
-
-	if (src->Indirect && (src->File != TGSI_FILE_CONSTANT)) {
-		unsigned aid = src_array_id(ctx, src);
-		reg->size = 4 * (1 + ctx->array[aid].last - ctx->array[aid].first);
-	} else {
-		reg->wrmask = wrmask;
-	}
+	reg->wrmask = wrmask;
 
 	if (wrmask == 0x1) {
 		/* normal case */
@@ -872,14 +860,6 @@ add_src_reg_wrmask(struct ir3_compile_context *ctx,
 		reg->instr = collect;
 	}
 
-	if (src->Indirect) {
-		unsigned size = reg->size;
-
-		reg = ir3_reg_create(orig, 0, flags | IR3_REG_SSA);
-		reg->instr = instr;
-		reg->size = size;
-	}
-
 	return reg;
 }
 
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_cp.c b/src/gallium/drivers/freedreno/ir3/ir3_cp.c
index b70aba9..898ed70 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_cp.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_cp.c
@@ -95,6 +95,9 @@ instr_cp(struct ir3_instruction *instr)
 		foreach_src(reg, instr)
 			if (reg->flags & IR3_REG_SSA)
 				reg->instr = instr_cp(reg->instr);
+
+		if (instr->address)
+			instr->address = instr_cp(instr->address);
 	}
 
 	return instr;
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_dump.c b/src/gallium/drivers/freedreno/ir3/ir3_dump.c
index 42a38d7..a846777 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_dump.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_dump.c
@@ -58,9 +58,6 @@ static void dump_instr_name(struct ir3_dump_ctx *ctx,
 		case OPC_META_PHI:
 			fprintf(ctx->f, "Φ");
 			break;
-		case OPC_META_DEREF:
-			fprintf(ctx->f, "(*)");
-			break;
 		default:
 			/* shouldn't hit here.. just for debugging: */
 			switch (instr->opc) {
@@ -171,8 +168,7 @@ static void dump_instr(struct ir3_dump_ctx *ctx,
 				ir3_block_dump(ctx, instr->flow.else_block, "else");
 			if (reg->flags & IR3_REG_SSA)
 				dump_instr(ctx, reg->instr);
-		} else if ((instr->opc == OPC_META_PHI) ||
-				(instr->opc == OPC_META_DEREF)) {
+		} else if (instr->opc == OPC_META_PHI) {
 			/* treat like a normal instruction: */
 			ir3_instr_dump(ctx, instr);
 		}
@@ -234,8 +230,7 @@ static void dump_link2(struct ir3_dump_ctx *ctx,
 			printdef(ctx, defer, "output%lx:<out%u>:w -> %s",
 					PTRID(instr->inout.block),
 					instr->regs[0]->num, target);
-		} else if ((instr->opc == OPC_META_PHI) ||
-				(instr->opc == OPC_META_DEREF)) {
+		} else if (instr->opc == OPC_META_PHI) {
 			/* treat like a normal instruction: */
 			printdef(ctx, defer, "instr%lx:<dst0> -> %s", PTRID(instr), target);
 		}
@@ -412,6 +407,13 @@ ir3_dump_instr_single(struct ir3_instruction *instr)
 		dump_reg_name(&ctx, reg, !!i);
 	}
 
+	if (instr->address) {
+		fprintf(ctx.f, ", address=_");
+		fprintf(ctx.f, "[");
+		dump_instr_name(&ctx, instr->address);
+		fprintf(ctx.f, "]");
+	}
+
 	if (is_meta(instr) && (instr->opc == OPC_META_FO))
 		printf(", off=%d", instr->fo.off);
 
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_ra.c b/src/gallium/drivers/freedreno/ir3/ir3_ra.c
index 03180b1..0f6d40f 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_ra.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_ra.c
@@ -357,6 +357,11 @@ static void instr_assign(struct ir3_ra_ctx *ctx,
 static void instr_assign_src(struct ir3_ra_ctx *ctx,
 		struct ir3_instruction *instr, unsigned r, unsigned name)
 {
+	struct ir3_register *reg = instr->regs[r];
+
+	if (reg->flags & IR3_REG_RELATIV)
+		name += reg->offset;
+
 	reg_assign(instr, r, name);
 
 	if (is_meta(instr)) {
@@ -372,14 +377,6 @@ static void instr_assign_src(struct ir3_ra_ctx *ctx,
 		case OPC_META_FI:
 			instr_assign(ctx, instr, name - (r - 1));
 			return;
-		case OPC_META_DEREF:
-			/* first arg of meta:deref is the addr reg (do not
-			 * propagate), 2nd is actual src (fanin) which does
-			 * get propagated)
-			 */
-			if (r == 2)
-				instr_assign(ctx, instr, name + instr->deref.off);
-			break;
 		default:
 			break;
 		}
@@ -392,6 +389,9 @@ static void instr_assign(struct ir3_ra_ctx *ctx,
 	struct ir3_instruction *n, *src;
 	struct ir3_register *reg = instr->regs[0];
 
+	if ((reg->flags & IR3_REG_RELATIV))
+		name += reg->offset;
+
 	/* check if already assigned: */
 	if (!(reg->flags & IR3_REG_SSA)) {
 		/* ... and if so, sanity check: */
@@ -484,9 +484,6 @@ static void instr_alloc_and_assign(struct ir3_ra_ctx *ctx,
 	/* allocate register(s): */
 	if (name >= 0) {
 		/* already partially assigned, just finish the job */
-	} else if (is_addr(instr)) {
-		debug_assert(!instr->cp.right);
-		name = instr->regs[2]->num + instr->deref.off;
 	} else if (reg_gpr(dst)) {
 		int size;
 		/* number of consecutive registers to assign: */
diff --git a/src/gallium/drivers/freedreno/ir3/ir3_sched.c b/src/gallium/drivers/freedreno/ir3/ir3_sched.c
index 1288452..909ecc2 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_sched.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_sched.c
@@ -292,16 +292,7 @@ static struct ir3_instruction * reverse(struct ir3_instruction *instr)
 static bool uses_current_addr(struct ir3_sched_ctx *ctx,
 		struct ir3_instruction *instr)
 {
-	struct ir3_instruction *src;
-	foreach_ssa_src(src, instr) {
-		if (is_addr(src)) {
-			struct ir3_instruction *addr =
-				src->regs[1]->instr; /* the mova */
-			if (ctx->addr == addr)
-				return true;
-		}
-	}
-	return false;
+	return instr->address && (ctx->addr == instr->address);
 }
 
 static bool uses_current_pred(struct ir3_sched_ctx *ctx,




More information about the mesa-commit mailing list