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:
parent
c81d681742
commit
d721348dcd
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]) {
|
||||
|
|
Loading…
Reference in New Issue