mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-07 00:38:48 +02:00
vc4: Create a basic block structure and move the instructions into it.
The optimization passes and scheduling aren't actually ready for multiple blocks with control flow yet (as seen by the "cur_block" references in them instead of iterating over blocks), but this creates the structures necessary for converting them.
This commit is contained in:
parent
d3cdbf6fd8
commit
6c1f834a23
6 changed files with 122 additions and 20 deletions
|
|
@ -83,7 +83,8 @@ qir_opt_dead_code(struct vc4_compile *c)
|
|||
bool progress = false;
|
||||
bool *used = calloc(c->num_temps, sizeof(bool));
|
||||
|
||||
list_for_each_entry_safe_rev(struct qinst, inst, &c->instructions,
|
||||
list_for_each_entry_safe_rev(struct qinst, inst,
|
||||
&c->cur_block->instructions,
|
||||
link) {
|
||||
if ((inst->dst.file == QFILE_NULL ||
|
||||
(inst->dst.file == QFILE_TEMP &&
|
||||
|
|
|
|||
|
|
@ -116,7 +116,8 @@ qir_opt_peephole_sf(struct vc4_compile *c)
|
|||
/* Walk the block from bottom to top, tracking if the SF is used, and
|
||||
* removing unused or repeated ones.
|
||||
*/
|
||||
list_for_each_entry_rev(struct qinst, inst, &c->instructions, link) {
|
||||
list_for_each_entry_rev(struct qinst, inst, &c->cur_block->instructions,
|
||||
link) {
|
||||
if (inst->sf) {
|
||||
if (!sf_live) {
|
||||
/* Our instruction's SF isn't read, so drop it.
|
||||
|
|
|
|||
|
|
@ -314,9 +314,12 @@ qir_dump_inst(struct vc4_compile *c, struct qinst *inst)
|
|||
void
|
||||
qir_dump(struct vc4_compile *c)
|
||||
{
|
||||
list_for_each_entry(struct qinst, inst, &c->instructions, link) {
|
||||
qir_dump_inst(c, inst);
|
||||
fprintf(stderr, "\n");
|
||||
qir_for_each_block(block, c) {
|
||||
fprintf(stderr, "BLOCK %d:\n", block->index);
|
||||
qir_for_each_inst(inst, block) {
|
||||
qir_dump_inst(c, inst);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -379,7 +382,7 @@ qir_inst4(enum qop op, struct qreg dst,
|
|||
static void
|
||||
qir_emit(struct vc4_compile *c, struct qinst *inst)
|
||||
{
|
||||
list_addtail(&inst->link, &c->instructions);
|
||||
list_addtail(&inst->link, &c->cur_block->instructions);
|
||||
}
|
||||
|
||||
/* Updates inst to write to a new temporary, emits it, and notes the def. */
|
||||
|
|
@ -415,12 +418,60 @@ qir_reg_equals(struct qreg a, struct qreg b)
|
|||
return a.file == b.file && a.index == b.index && a.pack == b.pack;
|
||||
}
|
||||
|
||||
struct qblock *
|
||||
qir_new_block(struct vc4_compile *c)
|
||||
{
|
||||
struct qblock *block = rzalloc(c, struct qblock);
|
||||
|
||||
list_inithead(&block->instructions);
|
||||
|
||||
block->predecessors = _mesa_set_create(block,
|
||||
_mesa_hash_pointer,
|
||||
_mesa_key_pointer_equal);
|
||||
|
||||
block->index = c->next_block_index++;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
void
|
||||
qir_set_emit_block(struct vc4_compile *c, struct qblock *block)
|
||||
{
|
||||
c->cur_block = block;
|
||||
list_addtail(&block->link, &c->blocks);
|
||||
}
|
||||
|
||||
struct qblock *
|
||||
qir_entry_block(struct vc4_compile *c)
|
||||
{
|
||||
return list_first_entry(&c->blocks, struct qblock, link);
|
||||
}
|
||||
|
||||
struct qblock *
|
||||
qir_exit_block(struct vc4_compile *c)
|
||||
{
|
||||
return list_last_entry(&c->blocks, struct qblock, link);
|
||||
}
|
||||
|
||||
void
|
||||
qir_link_blocks(struct qblock *predecessor, struct qblock *successor)
|
||||
{
|
||||
_mesa_set_add(successor->predecessors, predecessor);
|
||||
if (predecessor->successors[0]) {
|
||||
assert(!predecessor->successors[1]);
|
||||
predecessor->successors[1] = successor;
|
||||
} else {
|
||||
predecessor->successors[0] = successor;
|
||||
}
|
||||
}
|
||||
|
||||
struct vc4_compile *
|
||||
qir_compile_init(void)
|
||||
{
|
||||
struct vc4_compile *c = rzalloc(NULL, struct vc4_compile);
|
||||
|
||||
list_inithead(&c->instructions);
|
||||
list_inithead(&c->blocks);
|
||||
qir_set_emit_block(c, qir_new_block(c));
|
||||
|
||||
c->output_position_index = -1;
|
||||
c->output_color_index = -1;
|
||||
|
|
@ -466,10 +517,13 @@ qir_follow_movs(struct vc4_compile *c, struct qreg reg)
|
|||
void
|
||||
qir_compile_destroy(struct vc4_compile *c)
|
||||
{
|
||||
while (!list_empty(&c->instructions)) {
|
||||
struct qinst *qinst =
|
||||
(struct qinst *)c->instructions.next;
|
||||
qir_remove_instruction(c, qinst);
|
||||
qir_for_each_block(block, c) {
|
||||
while (!list_empty(&block->instructions)) {
|
||||
struct qinst *qinst =
|
||||
list_first_entry(&block->instructions,
|
||||
struct qinst, link);
|
||||
qir_remove_instruction(c, qinst);
|
||||
}
|
||||
}
|
||||
|
||||
ralloc_free(c);
|
||||
|
|
@ -523,8 +577,9 @@ void
|
|||
qir_SF(struct vc4_compile *c, struct qreg src)
|
||||
{
|
||||
struct qinst *last_inst = NULL;
|
||||
if (!list_empty(&c->instructions))
|
||||
last_inst = (struct qinst *)c->instructions.prev;
|
||||
|
||||
if (!list_empty(&c->cur_block->instructions))
|
||||
last_inst = (struct qinst *)c->cur_block->instructions.prev;
|
||||
|
||||
/* We don't have any way to guess which kind of MOV is implied. */
|
||||
assert(!src.pack);
|
||||
|
|
@ -533,7 +588,7 @@ qir_SF(struct vc4_compile *c, struct qreg src)
|
|||
!c->defs[src.index] ||
|
||||
last_inst != c->defs[src.index]) {
|
||||
last_inst = qir_MOV_dest(c, qir_reg(QFILE_NULL, 0), src);
|
||||
last_inst = (struct qinst *)c->instructions.prev;
|
||||
last_inst = (struct qinst *)c->cur_block->instructions.prev;
|
||||
}
|
||||
last_inst->sf = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -343,6 +343,18 @@ struct vc4_vs_key {
|
|||
bool clamp_color;
|
||||
};
|
||||
|
||||
/** A basic block of QIR intructions. */
|
||||
struct qblock {
|
||||
struct list_head link;
|
||||
|
||||
struct list_head instructions;
|
||||
|
||||
struct set *predecessors;
|
||||
struct qblock *successors[2];
|
||||
|
||||
int index;
|
||||
};
|
||||
|
||||
struct vc4_compile {
|
||||
struct vc4_context *vc4;
|
||||
nir_shader *s;
|
||||
|
|
@ -424,7 +436,10 @@ struct vc4_compile {
|
|||
struct qreg undef;
|
||||
enum qstage stage;
|
||||
uint32_t num_temps;
|
||||
struct list_head instructions;
|
||||
|
||||
struct list_head blocks;
|
||||
int next_block_index;
|
||||
struct qblock *cur_block;
|
||||
|
||||
struct list_head qpu_inst_list;
|
||||
uint64_t *qpu_insts;
|
||||
|
|
@ -450,6 +465,11 @@ struct vc4_compile {
|
|||
|
||||
struct vc4_compile *qir_compile_init(void);
|
||||
void qir_compile_destroy(struct vc4_compile *c);
|
||||
struct qblock *qir_new_block(struct vc4_compile *c);
|
||||
void qir_set_emit_block(struct vc4_compile *c, struct qblock *block);
|
||||
void qir_link_blocks(struct qblock *predecessor, struct qblock *successor);
|
||||
struct qblock *qir_entry_block(struct vc4_compile *c);
|
||||
struct qblock *qir_exit_block(struct vc4_compile *c);
|
||||
struct qinst *qir_inst(enum qop op, struct qreg dst,
|
||||
struct qreg src0, struct qreg src1);
|
||||
struct qinst *qir_inst4(enum qop op, struct qreg dst,
|
||||
|
|
@ -587,7 +607,8 @@ qir_##name(struct vc4_compile *c) \
|
|||
*payload = qir_get_temp(c); \
|
||||
struct qinst *inst = qir_inst(QOP_##name, *payload, \
|
||||
c->undef, c->undef); \
|
||||
list_add(&inst->link, &c->instructions); \
|
||||
struct qblock *entry = qir_entry_block(c); \
|
||||
list_add(&inst->link, &entry->instructions); \
|
||||
c->defs[payload->index] = inst; \
|
||||
return *payload; \
|
||||
}
|
||||
|
|
@ -719,7 +740,30 @@ qir_LOAD_IMM(struct vc4_compile *c, uint32_t val)
|
|||
qir_reg(QFILE_LOAD_IMM, val), c->undef));
|
||||
}
|
||||
|
||||
#define qir_for_each_block(block, c) \
|
||||
list_for_each_entry(struct qblock, block, &c->blocks, link)
|
||||
|
||||
#define qir_for_each_block_rev(block, c) \
|
||||
list_for_each_entry_rev(struct qblock, block, &c->blocks, link)
|
||||
|
||||
/* Loop over the non-NULL members of the successors array. */
|
||||
#define qir_for_each_successor(succ, block) \
|
||||
for (struct qblock *succ = block->successors[0]; \
|
||||
succ != NULL; \
|
||||
succ = (succ == block->successors[1] ? NULL : \
|
||||
block->successors[1]))
|
||||
|
||||
#define qir_for_each_inst(inst, block) \
|
||||
list_for_each_entry(struct qinst, inst, &block->instructions, link)
|
||||
|
||||
#define qir_for_each_inst_rev(inst, block) \
|
||||
list_for_each_entry_rev(struct qinst, inst, &block->instructions, link)
|
||||
|
||||
#define qir_for_each_inst_safe(inst, block) \
|
||||
list_for_each_entry_safe(struct qinst, inst, &block->instructions, link)
|
||||
|
||||
#define qir_for_each_inst_inorder(inst, c) \
|
||||
list_for_each_entry(struct qinst, inst, &c->instructions, link)
|
||||
qir_for_each_block(_block, c) \
|
||||
qir_for_each_inst(inst, _block)
|
||||
|
||||
#endif /* VC4_QIR_H */
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ qir_lower_uniforms(struct vc4_compile *c)
|
|||
struct qreg temp = qir_get_temp(c);
|
||||
struct qreg unif = qir_reg(QFILE_UNIF, max_index);
|
||||
struct qinst *mov = qir_inst(QOP_MOV, temp, unif, c->undef);
|
||||
list_add(&mov->link, &c->instructions);
|
||||
list_add(&mov->link, &c->cur_block->instructions);
|
||||
c->defs[temp.index] = mov;
|
||||
qir_for_each_inst_inorder(inst, c) {
|
||||
uint32_t nsrc = qir_get_op_nsrc(inst->op);
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ schedule_instructions(struct vc4_compile *c, struct schedule_state *state)
|
|||
|
||||
/* Schedule this instruction back onto the QIR list. */
|
||||
list_del(&chosen->link);
|
||||
list_add(&inst->link, &c->instructions);
|
||||
list_add(&inst->link, &c->cur_block->instructions);
|
||||
|
||||
/* Now that we've scheduled a new instruction, some of its
|
||||
* children can be promoted to the list of instructions ready to
|
||||
|
|
@ -597,7 +597,8 @@ qir_schedule_instructions(struct vc4_compile *c)
|
|||
list_inithead(&state.worklist);
|
||||
|
||||
/* Wrap each instruction in a scheduler structure. */
|
||||
list_for_each_entry_safe(struct qinst, inst, &c->instructions, link) {
|
||||
list_for_each_entry_safe(struct qinst, inst,
|
||||
&c->cur_block->instructions, link) {
|
||||
struct schedule_node *n = rzalloc(mem_ctx, struct schedule_node);
|
||||
|
||||
n->inst = inst;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue