diff options
author | Eric Anholt <[email protected]> | 2016-07-08 15:42:15 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2016-07-12 15:47:26 -0700 |
commit | 6c1f834a237540c344fa794d60501a69bf066fb5 (patch) | |
tree | 14913f99b70ede78bfb2da9e1eeb6276c3569fd1 | |
parent | d3cdbf6fd817ae5e7a8a72bcc3f43cc1b04a709b (diff) |
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.
-rw-r--r-- | src/gallium/drivers/vc4/vc4_opt_dead_code.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_opt_peephole_sf.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qir.c | 79 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qir.h | 50 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qir_schedule.c | 5 |
6 files changed, 122 insertions, 20 deletions
diff --git a/src/gallium/drivers/vc4/vc4_opt_dead_code.c b/src/gallium/drivers/vc4/vc4_opt_dead_code.c index 0256159fc69..26fa3ed5435 100644 --- a/src/gallium/drivers/vc4/vc4_opt_dead_code.c +++ b/src/gallium/drivers/vc4/vc4_opt_dead_code.c @@ -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 && diff --git a/src/gallium/drivers/vc4/vc4_opt_peephole_sf.c b/src/gallium/drivers/vc4/vc4_opt_peephole_sf.c index 5536f8dd204..414a9ef1eb3 100644 --- a/src/gallium/drivers/vc4/vc4_opt_peephole_sf.c +++ b/src/gallium/drivers/vc4/vc4_opt_peephole_sf.c @@ -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. diff --git a/src/gallium/drivers/vc4/vc4_qir.c b/src/gallium/drivers/vc4/vc4_qir.c index 5d5ba1f0e13..c23b3326f82 100644 --- a/src/gallium/drivers/vc4/vc4_qir.c +++ b/src/gallium/drivers/vc4/vc4_qir.c @@ -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; } diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h index 315f403e43b..f3e65756f64 100644 --- a/src/gallium/drivers/vc4/vc4_qir.h +++ b/src/gallium/drivers/vc4/vc4_qir.h @@ -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 */ diff --git a/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c b/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c index 9f782dfc7df..7c8cbd14666 100644 --- a/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c +++ b/src/gallium/drivers/vc4/vc4_qir_lower_uniforms.c @@ -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); diff --git a/src/gallium/drivers/vc4/vc4_qir_schedule.c b/src/gallium/drivers/vc4/vc4_qir_schedule.c index c86df8359de..d105ff45ce6 100644 --- a/src/gallium/drivers/vc4/vc4_qir_schedule.c +++ b/src/gallium/drivers/vc4/vc4_qir_schedule.c @@ -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; |