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) {
last_inst->dst.index = qregs[chan].index;
/* Set the flags to the current exec mask. To insert
* the flags push, we temporarily remove our SSA
* instruction.
/* Set the flags to the current exec mask.
*/
list_del(&last_inst->link);
c->cursor = vir_before_inst(last_inst);
vir_PF(c, c->execute, V3D_QPU_PF_PUSHZ);
list_addtail(&last_inst->link,
&c->cur_block->instructions);
c->cursor = vir_after_inst(last_inst);
vir_set_cond(last_inst, V3D_QPU_COND_IFA);
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
* setup.
@ -500,6 +542,7 @@ struct v3d_compile {
struct qreg undef;
uint32_t num_temps;
struct vir_cursor cursor;
struct list_head blocks;
int next_block_index;
struct qblock *cur_block;

View File

@ -418,7 +418,16 @@ vir_branch_inst(enum v3d_qpu_branch_cond cond, struct qreg src)
static void
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. */
@ -468,6 +477,7 @@ void
vir_set_emit_block(struct v3d_compile *c, struct qblock *block)
{
c->cur_block = block;
c->cursor = vir_after_block(block);
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)
c->defs[qinst->dst.index] = NULL;
assert(&qinst->link != c->cursor.link);
list_del(&qinst->link);
free(qinst);
}
@ -818,6 +830,10 @@ vir_follow_movs(struct v3d_compile *c, struct qreg reg)
void
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) {
while (!list_empty(&block->instructions)) {
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;
if (!list_empty(&c->cur_block->instructions))
if (!list_empty(&c->cur_block->instructions)) {
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 ||
!c->defs[src.index] ||
last_inst != c->defs[src.index]) {