broadcom/vc5: Add cursors to the compiler infrastructure, like NIR's.

This will let me do lowering late in compilation using the same
instruction builder as we use in nir_to_vir.
This commit is contained in:
Eric Anholt 2018-03-13 15:41:16 -07:00
parent c81d681742
commit d721348dcd
3 changed files with 73 additions and 8 deletions

View File

@ -198,14 +198,11 @@ ntq_store_dest(struct v3d_compile *c, nir_dest *dest, int chan,
if (c->execute.file != QFILE_NULL) { if (c->execute.file != QFILE_NULL) {
last_inst->dst.index = qregs[chan].index; last_inst->dst.index = qregs[chan].index;
/* Set the flags to the current exec mask. To insert /* Set the flags to the current exec mask.
* the flags push, we temporarily remove our SSA
* instruction.
*/ */
list_del(&last_inst->link); c->cursor = vir_before_inst(last_inst);
vir_PF(c, c->execute, V3D_QPU_PF_PUSHZ); vir_PF(c, c->execute, V3D_QPU_PF_PUSHZ);
list_addtail(&last_inst->link, c->cursor = vir_after_inst(last_inst);
&c->cur_block->instructions);
vir_set_cond(last_inst, V3D_QPU_COND_IFA); vir_set_cond(last_inst, V3D_QPU_COND_IFA);
last_inst->cond_is_exec_mask = true; last_inst->cond_is_exec_mask = true;

View File

@ -384,6 +384,48 @@ struct qblock {
/** @} */ /** @} */
}; };
/** Which util/list.h add mode we should use when inserting an instruction. */
enum vir_cursor_mode {
vir_cursor_add,
vir_cursor_addtail,
};
/**
* Tracking structure for where new instructions should be inserted. Create
* with one of the vir_after_inst()-style helper functions.
*
* This does not protect against removal of the block or instruction, so we
* have an assert in instruction removal to try to catch it.
*/
struct vir_cursor {
enum vir_cursor_mode mode;
struct list_head *link;
};
static inline struct vir_cursor
vir_before_inst(struct qinst *inst)
{
return (struct vir_cursor){ vir_cursor_addtail, &inst->link };
}
static inline struct vir_cursor
vir_after_inst(struct qinst *inst)
{
return (struct vir_cursor){ vir_cursor_add, &inst->link };
}
static inline struct vir_cursor
vir_before_block(struct qblock *block)
{
return (struct vir_cursor){ vir_cursor_add, &block->instructions };
}
static inline struct vir_cursor
vir_after_block(struct qblock *block)
{
return (struct vir_cursor){ vir_cursor_addtail, &block->instructions };
}
/** /**
* Compiler state saved across compiler invocations, for any expensive global * Compiler state saved across compiler invocations, for any expensive global
* setup. * setup.
@ -500,6 +542,7 @@ struct v3d_compile {
struct qreg undef; struct qreg undef;
uint32_t num_temps; uint32_t num_temps;
struct vir_cursor cursor;
struct list_head blocks; struct list_head blocks;
int next_block_index; int next_block_index;
struct qblock *cur_block; struct qblock *cur_block;

View File

@ -418,7 +418,16 @@ vir_branch_inst(enum v3d_qpu_branch_cond cond, struct qreg src)
static void static void
vir_emit(struct v3d_compile *c, struct qinst *inst) vir_emit(struct v3d_compile *c, struct qinst *inst)
{ {
list_addtail(&inst->link, &c->cur_block->instructions); switch (c->cursor.mode) {
case vir_cursor_add:
list_add(&inst->link, c->cursor.link);
break;
case vir_cursor_addtail:
list_addtail(&inst->link, c->cursor.link);
break;
}
c->cursor = vir_after_inst(inst);
} }
/* Updates inst to write to a new temporary, emits it, and notes the def. */ /* Updates inst to write to a new temporary, emits it, and notes the def. */
@ -468,6 +477,7 @@ void
vir_set_emit_block(struct v3d_compile *c, struct qblock *block) vir_set_emit_block(struct v3d_compile *c, struct qblock *block)
{ {
c->cur_block = block; c->cur_block = block;
c->cursor = vir_after_block(block);
list_addtail(&block->link, &c->blocks); list_addtail(&block->link, &c->blocks);
} }
@ -791,6 +801,8 @@ vir_remove_instruction(struct v3d_compile *c, struct qinst *qinst)
if (qinst->dst.file == QFILE_TEMP) if (qinst->dst.file == QFILE_TEMP)
c->defs[qinst->dst.index] = NULL; c->defs[qinst->dst.index] = NULL;
assert(&qinst->link != c->cursor.link);
list_del(&qinst->link); list_del(&qinst->link);
free(qinst); free(qinst);
} }
@ -818,6 +830,10 @@ vir_follow_movs(struct v3d_compile *c, struct qreg reg)
void void
vir_compile_destroy(struct v3d_compile *c) vir_compile_destroy(struct v3d_compile *c)
{ {
/* Defuse the assert that we aren't removing the cursor's instruction.
*/
c->cursor.link = NULL;
vir_for_each_block(block, c) { vir_for_each_block(block, c) {
while (!list_empty(&block->instructions)) { while (!list_empty(&block->instructions)) {
struct qinst *qinst = struct qinst *qinst =
@ -867,9 +883,18 @@ vir_PF(struct v3d_compile *c, struct qreg src, enum v3d_qpu_pf pf)
{ {
struct qinst *last_inst = NULL; struct qinst *last_inst = NULL;
if (!list_empty(&c->cur_block->instructions)) if (!list_empty(&c->cur_block->instructions)) {
last_inst = (struct qinst *)c->cur_block->instructions.prev; last_inst = (struct qinst *)c->cur_block->instructions.prev;
/* Can't stuff the PF into the last last inst if our cursor
* isn't pointing after it.
*/
struct vir_cursor after_inst = vir_after_inst(last_inst);
if (c->cursor.mode != after_inst.mode ||
c->cursor.link != after_inst.link)
last_inst = NULL;
}
if (src.file != QFILE_TEMP || if (src.file != QFILE_TEMP ||
!c->defs[src.index] || !c->defs[src.index] ||
last_inst != c->defs[src.index]) { last_inst != c->defs[src.index]) {