Mesa (master): freedreno/ir3: fix failed assert in grouping

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


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

Author: Rob Clark <robclark at freedesktop.org>
Date:   Tue Feb 10 04:42:32 2015 -0500

freedreno/ir3: fix failed assert in grouping

Turns out there are scenarios where we need to insert mov's in "front"
of an input.  Triggered by shaders like:

  VERT
  DCL IN[0]
  DCL IN[1]
  DCL OUT[0], POSITION
  DCL OUT[1], GENERIC[9]
  DCL SAMP[0]
  DCL TEMP[0], LOCAL
    0: MOV TEMP[0].xy, IN[1].xyyy
    1: MOV TEMP[0].w, IN[1].wwww
    2: TXF TEMP[0], TEMP[0], SAMP[0], 1D_ARRAY
    3: MOV OUT[1], TEMP[0]
    4: MOV OUT[0], IN[0]
    5: END

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

---

 src/gallium/drivers/freedreno/ir3/ir3_group.c |   71 +++++++++++++++----------
 1 file changed, 44 insertions(+), 27 deletions(-)

diff --git a/src/gallium/drivers/freedreno/ir3/ir3_group.c b/src/gallium/drivers/freedreno/ir3/ir3_group.c
index da2142e..a571e2e 100644
--- a/src/gallium/drivers/freedreno/ir3/ir3_group.c
+++ b/src/gallium/drivers/freedreno/ir3/ir3_group.c
@@ -50,40 +50,72 @@ static bool check_stop(struct ir3_instruction *instr)
 	return false;
 }
 
+static struct ir3_instruction * create_mov(struct ir3_instruction *instr)
+{
+	struct ir3_instruction *mov;
+
+	mov = ir3_instr_create(instr->block, 1, 0);
+	mov->cat1.src_type = TYPE_F32;
+	mov->cat1.dst_type = TYPE_F32;
+	ir3_reg_create(mov, 0, 0);    /* dst */
+	ir3_reg_create(mov, 0, IR3_REG_SSA)->instr = instr;
+
+	return mov;
+}
+
 /* bleh.. we need to do the same group_n() thing for both inputs/outputs
  * (where we have a simple instr[] array), and fanin nodes (where we have
  * an extra indirection via reg->instr).
  */
 struct group_ops {
 	struct ir3_instruction *(*get)(void *arr, int idx);
-	void (*set)(void *arr, int idx, struct ir3_instruction *instr);
+	void (*insert_mov)(void *arr, int idx, struct ir3_instruction *instr);
 };
 
 static struct ir3_instruction *arr_get(void *arr, int idx)
 {
 	return ((struct ir3_instruction **)arr)[idx];
 }
-static void arr_set_out(void *arr, int idx, struct ir3_instruction *instr)
+static void arr_insert_mov_out(void *arr, int idx, struct ir3_instruction *instr)
 {
-	((struct ir3_instruction **)arr)[idx] = instr;
+	((struct ir3_instruction **)arr)[idx] = create_mov(instr);
 }
-static void arr_set_in(void *arr, int idx, struct ir3_instruction *instr)
+static void arr_insert_mov_in(void *arr, int idx, struct ir3_instruction *instr)
 {
-	debug_printf("cannot insert mov before input!\n");
-	debug_assert(0);
+	/* so, we can't insert a mov in front of a meta:in.. and the downstream
+	 * instruction already has a pointer to 'instr'.  So we cheat a bit and
+	 * morph the meta:in instruction into a mov and insert a new meta:in
+	 * in front.
+	 */
+	struct ir3_instruction *in;
+
+	debug_assert(instr->regs_count == 1);
+
+	in = ir3_instr_create(instr->block, -1, OPC_META_INPUT);
+	in->inout.block = instr->block;
+	ir3_reg_create(in, instr->regs[0]->num, 0);
+
+	/* create src reg for meta:in and fixup to now be a mov: */
+	ir3_reg_create(instr, 0, IR3_REG_SSA)->instr = in;
+	instr->category = 1;
+	instr->opc = 0;
+	instr->cat1.src_type = TYPE_F32;
+	instr->cat1.dst_type = TYPE_F32;
+
+	((struct ir3_instruction **)arr)[idx] = in;
 }
-static struct group_ops arr_ops_out = { arr_get, arr_set_out };
-static struct group_ops arr_ops_in = { arr_get, arr_set_in };
+static struct group_ops arr_ops_out = { arr_get, arr_insert_mov_out };
+static struct group_ops arr_ops_in = { arr_get, arr_insert_mov_in };
 
 static struct ir3_instruction *instr_get(void *arr, int idx)
 {
 	return ssa(((struct ir3_instruction *)arr)->regs[idx+1]);
 }
-static void instr_set(void *arr, int idx, struct ir3_instruction *instr)
+static void instr_insert_mov(void *arr, int idx, struct ir3_instruction *instr)
 {
-	((struct ir3_instruction *)arr)->regs[idx+1]->instr = instr;
+	((struct ir3_instruction *)arr)->regs[idx+1]->instr = create_mov(instr);
 }
-static struct group_ops instr_ops = { instr_get, instr_set };
+static struct group_ops instr_ops = { instr_get, instr_insert_mov };
 
 
 
@@ -92,20 +124,6 @@ static bool conflicts(struct ir3_instruction *a, struct ir3_instruction *b)
 	return (a && b) && (a != b);
 }
 
-static struct ir3_instruction *
-create_mov(struct ir3_instruction *instr)
-{
-	struct ir3_instruction *mov;
-
-	mov = ir3_instr_create(instr->block, 1, 0);
-	mov->cat1.src_type = TYPE_F32;
-	mov->cat1.dst_type = TYPE_F32;
-	ir3_reg_create(mov, 0, 0);    /* dst */
-	ir3_reg_create(mov, 0, IR3_REG_SSA)->instr = instr;
-
-	return mov;
-}
-
 static void group_n(struct group_ops *ops, void *arr, unsigned n)
 {
 	unsigned i, j;
@@ -135,8 +153,7 @@ restart:
 					conflict = true;
 
 			if (conflict) {
-				instr = create_mov(instr);
-				ops->set(arr, i, instr);
+				ops->insert_mov(arr, i, instr);
 				/* inserting the mov may have caused a conflict
 				 * against the previous:
 				 */




More information about the mesa-commit mailing list