free(texw);
}
-/* We register allocate after scheduling, so we need to ensure instructions
- * executing in parallel within a segment of a bundle don't clobber each
- * other's registers. This is mostly a non-issue thanks to scheduling, but
- * there are edge cases. In particular, after a register is written in a
- * segment, it interferes with anything reading. */
-
-static void
-mir_compute_segment_interference(
- compiler_context *ctx,
- struct lcra_state *l,
- midgard_bundle *bun,
- unsigned pivot,
- unsigned i)
-{
- for (unsigned j = pivot; j < i; ++j) {
- mir_foreach_src(bun->instructions[j], s) {
- if (bun->instructions[j]->src[s] >= ctx->temp_count)
- continue;
-
- for (unsigned q = pivot; q < i; ++q) {
- if (bun->instructions[q]->dest >= ctx->temp_count)
- continue;
-
- /* See dEQP-GLES2.functional.shaders.return.output_write_in_func_dynamic_fragment */
-
- if (q >= j) {
- if (!(bun->instructions[j]->unit == UNIT_SMUL && bun->instructions[q]->unit == UNIT_VLUT))
- continue;
- }
-
- unsigned mask = mir_bytemask(bun->instructions[q]);
- unsigned rmask = mir_bytemask_of_read_components(bun->instructions[j], bun->instructions[j]->src[s]);
- lcra_add_node_interference(l, bun->instructions[q]->dest, mask, bun->instructions[j]->src[s], rmask);
- }
- }
- }
-}
-
-static void
-mir_compute_bundle_interference(
- compiler_context *ctx,
- struct lcra_state *l,
- midgard_bundle *bun)
-{
- if (!IS_ALU(bun->tag))
- return;
-
- bool old = bun->instructions[0]->unit >= UNIT_VADD;
- unsigned pivot = 0;
-
- for (unsigned i = 1; i < bun->instruction_count; ++i) {
- bool new = bun->instructions[i]->unit >= UNIT_VADD;
-
- if (old != new) {
- mir_compute_segment_interference(ctx, l, bun, 0, i);
- pivot = i;
- break;
- }
- }
-
- mir_compute_segment_interference(ctx, l, bun, pivot, bun->instruction_count);
-}
-
static void
mir_compute_interference(
compiler_context *ctx,
mir_liveness_ins_update(live, ins, ctx->temp_count);
}
- mir_foreach_bundle_in_block(blk, bun)
- mir_compute_bundle_interference(ctx, l, bun);
-
free(live);
}
}