From: Rob Clark Date: Tue, 10 Feb 2015 09:42:32 +0000 (-0500) Subject: freedreno/ir3: fix failed assert in grouping X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=27648efa2070e8db111908314d8b924d3717dbb0;p=mesa.git 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 --- diff --git a/src/gallium/drivers/freedreno/ir3/ir3_group.c b/src/gallium/drivers/freedreno/ir3/ir3_group.c index da2142e69a8..a571e2e8eea 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: */