freedreno/ir3: handle "holes" in inputs

If, for example, only the x/y/w components of in.xyzw are actually used,
we still need to have a group of four registers and assign all four
components.  The hardware can't write in.xy and in.w to discontiguous
registers.  To handle this, pad with a dummy NOP instruction, to keep
the neighbor chain contiguous.

This fixes a problem noticed with firefox OMTC.

Signed-off-by: Rob Clark <robclark@freedesktop.org>
This commit is contained in:
Rob Clark
2015-01-12 23:32:25 -05:00
parent b6819cd554
commit 876550ff97
+31 -1
View File
@@ -187,6 +187,36 @@ static void instr_find_neighbors(struct ir3_instruction *instr)
}
}
/* a bit of sadness.. we can't have "holes" in inputs from PoV of
* register assignment, they still need to be grouped together. So
* we need to insert dummy/padding instruction for grouping, and
* then take it back out again before anyone notices.
*/
static void pad_and_group_input(struct ir3_instruction **input, unsigned n)
{
int i, mask = 0;
struct ir3_block *block = NULL;
for (i = n - 1; i >= 0; i--) {
struct ir3_instruction *instr = input[i];
if (instr) {
block = instr->block;
} else if (block) {
instr = ir3_instr_create(block, 0, OPC_NOP);
ir3_reg_create(instr, 0, IR3_REG_SSA); /* dst */
input[i] = instr;
mask |= (1 << i);
}
}
group_n(&arr_ops_in, input, n);
for (i = 0; i < n; i++) {
if (mask & (1 << i))
input[i] = NULL;
}
}
static void block_find_neighbors(struct ir3_block *block)
{
unsigned i;
@@ -214,7 +244,7 @@ static void block_find_neighbors(struct ir3_block *block)
* on vec4 boundaries
*/
for (i = 0; i < block->ninputs; i += 4)
group_n(&arr_ops_in, &block->inputs[i], 4);
pad_and_group_input(&block->inputs[i], 4);
for (i = 0; i < block->noutputs; i += 4)
group_n(&arr_ops_out, &block->outputs[i], 4);