pan/bi: Add bi_instr_schedulable predicate
Using the previously defined checks for architectural scheduling constraints, define one top-level predicate to check if an instruction on the worklist is ready for scheduling. Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com> Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8354>
This commit is contained in:
parent
2537a53d5c
commit
a303076c1a
|
@ -677,6 +677,94 @@ bi_writes_reg(bi_instr *instr)
|
||||||
!bi_opcode_props[instr->op].sr_write);
|
!bi_opcode_props[instr->op].sr_write);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Instruction placement entails two questions: what subset of instructions in
|
||||||
|
* the block can legally be scheduled? and of those which is the best? That is,
|
||||||
|
* we seek to maximize a cost function on a subset of the worklist satisfying a
|
||||||
|
* particular predicate. The necessary predicate is determined entirely by
|
||||||
|
* Bifrost's architectural limitations and is described in the accompanying
|
||||||
|
* whitepaper. The cost function is a heuristic. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
bi_instr_schedulable(bi_instr *instr,
|
||||||
|
struct bi_clause_state *clause,
|
||||||
|
struct bi_tuple_state *tuple,
|
||||||
|
bool fma)
|
||||||
|
{
|
||||||
|
/* The units must match */
|
||||||
|
if ((fma && !bi_can_fma(instr)) || (!fma && !bi_can_add(instr)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* There can only be one message-passing instruction per clause */
|
||||||
|
if (bi_must_message(instr) && clause->message)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Some instructions have placement requirements */
|
||||||
|
if (bi_must_last(instr) && !tuple->last)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Message-passing instructions are not guaranteed write within the
|
||||||
|
* same clause (most likely they will not), so if a later instruction
|
||||||
|
* in the clause reads from the destination, the message-passing
|
||||||
|
* instruction can't be scheduled */
|
||||||
|
if (bi_opcode_props[instr->op].sr_write) {
|
||||||
|
for (unsigned i = 0; i < clause->read_count; ++i) {
|
||||||
|
if (bi_is_equiv(instr->dest[0], clause->reads[i]))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If FAU is already assigned, we may not disrupt that. Do a
|
||||||
|
* non-disruptive test update */
|
||||||
|
if (!bi_update_fau(clause, tuple, instr, fma, false))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* If this choice of FMA would force a staging passthrough, the ADD
|
||||||
|
* instruction must support such a passthrough */
|
||||||
|
if (tuple->add && bi_has_staging_passthrough_hazard(instr->dest[0], tuple->add))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* If this choice of destination would force a cross-tuple passthrough, the next tuple must support that */
|
||||||
|
if (tuple->prev && bi_has_cross_passthrough_hazard(tuple->prev, instr))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Register file writes are limited, TODO don't count tempable things */
|
||||||
|
unsigned total_writes = tuple->reg.nr_writes;
|
||||||
|
|
||||||
|
if (bi_writes_reg(instr))
|
||||||
|
total_writes++;
|
||||||
|
|
||||||
|
/* Last tuple in a clause can only write a single value */
|
||||||
|
if (tuple->last && total_writes > 1)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Register file reads are limited, so count unique */
|
||||||
|
|
||||||
|
unsigned unique_new_srcs = 0;
|
||||||
|
|
||||||
|
bi_foreach_src(instr, s) {
|
||||||
|
if (bi_tuple_is_new_src(instr, &tuple->reg, s))
|
||||||
|
unique_new_srcs++;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned total_srcs = tuple->reg.nr_reads + unique_new_srcs;
|
||||||
|
|
||||||
|
/* TODO: spill to moves */
|
||||||
|
if (total_srcs > 3)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* Count effective reads for the successor */
|
||||||
|
unsigned succ_reads = bi_count_succ_reads(instr->dest[0],
|
||||||
|
tuple->add ? tuple->add->dest[0] : bi_null(),
|
||||||
|
tuple->prev_reads, tuple->nr_prev_reads);
|
||||||
|
|
||||||
|
/* Successor must satisfy R+W <= 4, so we require W <= 4-R */
|
||||||
|
if (total_writes > MAX2(4 - (signed) succ_reads, 0))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
||||||
static bi_builder *
|
static bi_builder *
|
||||||
|
|
Loading…
Reference in New Issue