summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEric Anholt <[email protected]>2018-03-13 15:41:16 -0700
committerEric Anholt <[email protected]>2018-03-19 16:42:59 -0700
commitd721348dcdb3658572c5952563d1f4d1ca0321af (patch)
tree901576d03741c12c62f5a092b3df49872a77df93 /src
parentc81d6817422c83ba990fac19b165d4dedb1150fe (diff)
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.
Diffstat (limited to 'src')
-rw-r--r--src/broadcom/compiler/nir_to_vir.c9
-rw-r--r--src/broadcom/compiler/v3d_compiler.h43
-rw-r--r--src/broadcom/compiler/vir.c29
3 files changed, 73 insertions, 8 deletions
diff --git a/src/broadcom/compiler/nir_to_vir.c b/src/broadcom/compiler/nir_to_vir.c
index 61486870dcf..c1ba1e3049d 100644
--- a/src/broadcom/compiler/nir_to_vir.c
+++ b/src/broadcom/compiler/nir_to_vir.c
@@ -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;
diff --git a/src/broadcom/compiler/v3d_compiler.h b/src/broadcom/compiler/v3d_compiler.h
index f777cfcd87b..fdf1b131978 100644
--- a/src/broadcom/compiler/v3d_compiler.h
+++ b/src/broadcom/compiler/v3d_compiler.h
@@ -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;
diff --git a/src/broadcom/compiler/vir.c b/src/broadcom/compiler/vir.c
index 7ea431036ef..0b2bbf0e794 100644
--- a/src/broadcom/compiler/vir.c
+++ b/src/broadcom/compiler/vir.c
@@ -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]) {