diff --git a/.pick_status.json b/.pick_status.json index 855c41a7b22..19905c73560 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -134,7 +134,7 @@ "description": "ir3: add ir3_cursor/ir3_builder helpers", "nominated": true, "nomination_type": 1, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "613eaac7b53bfbfcd6ef536412be6c9c63cdea4f", "notes": null diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c index 66479bd68a2..cc54d8434f1 100644 --- a/src/freedreno/ir3/ir3.c +++ b/src/freedreno/ir3/ir3.c @@ -483,18 +483,26 @@ reg_create(struct ir3 *shader, int num, int flags) } static void -insert_instr(struct ir3_block *block, struct ir3_instruction *instr, - bool at_end) +insert_instr(struct ir3_cursor cursor, struct ir3_instruction *instr) { - struct ir3 *shader = block->shader; + struct ir3 *shader = instr->block->shader; instr->serialno = ++shader->instr_count; - struct ir3_instruction *terminator = ir3_block_get_terminator(block); - list_addtail(&instr->node, &block->instr_list); - - if (!at_end && terminator) - ir3_instr_move_before(instr, terminator); + switch (cursor.option) { + case IR3_CURSOR_BEFORE_BLOCK: + list_add(&instr->node, &cursor.block->instr_list); + break; + case IR3_CURSOR_AFTER_BLOCK: + list_addtail(&instr->node, &cursor.block->instr_list); + break; + case IR3_CURSOR_BEFORE_INSTR: + list_addtail(&instr->node, &cursor.instr->node); + break; + case IR3_CURSOR_AFTER_INSTR: + list_add(&instr->node, &cursor.instr->node); + break; + } if (is_input(instr)) array_insert(shader, shader->baryfs, instr); @@ -641,17 +649,6 @@ instr_create(struct ir3_block *block, opc_t opc, int ndst, int nsrc) return instr; } -static struct ir3_instruction * -instr_create_impl(struct ir3_block *block, opc_t opc, int ndst, int nsrc, - bool at_end) -{ - struct ir3_instruction *instr = instr_create(block, opc, ndst, nsrc); - instr->block = block; - instr->opc = opc; - insert_instr(block, instr, at_end); - return instr; -} - static void add_to_address_users(struct ir3_instruction *instr) { @@ -669,16 +666,51 @@ add_to_address_users(struct ir3_instruction *instr) } } +static struct ir3_block * +get_block(struct ir3_cursor cursor) +{ + switch (cursor.option) { + case IR3_CURSOR_BEFORE_BLOCK: + case IR3_CURSOR_AFTER_BLOCK: + return cursor.block; + case IR3_CURSOR_BEFORE_INSTR: + case IR3_CURSOR_AFTER_INSTR: + return cursor.instr->block; + } + + unreachable("illegal cursor option"); +} + +struct ir3_instruction * +ir3_instr_create_at(struct ir3_cursor cursor, opc_t opc, int ndst, int nsrc) +{ + struct ir3_block *block = get_block(cursor); + struct ir3_instruction *instr = instr_create(block, opc, ndst, nsrc); + instr->block = block; + instr->opc = opc; + insert_instr(cursor, instr); + return instr; +} + +struct ir3_instruction * +ir3_build_instr(struct ir3_builder *builder, opc_t opc, int ndst, int nsrc) +{ + struct ir3_instruction *instr = + ir3_instr_create_at(builder->cursor, opc, ndst, nsrc); + builder->cursor = ir3_after_instr(instr); + return instr; +} + struct ir3_instruction * ir3_instr_create(struct ir3_block *block, opc_t opc, int ndst, int nsrc) { - return instr_create_impl(block, opc, ndst, nsrc, false); + return ir3_instr_create_at(ir3_before_terminator(block), opc, ndst, nsrc); } struct ir3_instruction * ir3_instr_create_at_end(struct ir3_block *block, opc_t opc, int ndst, int nsrc) { - return instr_create_impl(block, opc, ndst, nsrc, true); + return ir3_instr_create_at(ir3_after_block(block), opc, ndst, nsrc); } struct ir3_instruction * @@ -694,7 +726,7 @@ ir3_instr_clone(struct ir3_instruction *instr) new_instr->dsts = dsts; new_instr->srcs = srcs; - insert_instr(instr->block, new_instr, false); + insert_instr(ir3_before_terminator(instr->block), new_instr); /* clone registers: */ new_instr->dsts_count = 0; diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index e563ff29f87..e4392440424 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -675,6 +675,25 @@ struct ir3_block { #endif }; +enum ir3_cursor_option { + IR3_CURSOR_BEFORE_BLOCK, + IR3_CURSOR_AFTER_BLOCK, + IR3_CURSOR_BEFORE_INSTR, + IR3_CURSOR_AFTER_INSTR, +}; + +struct ir3_cursor { + enum ir3_cursor_option option; + union { + struct ir3_block *block; + struct ir3_instruction *instr; + }; +}; + +struct ir3_builder { + struct ir3_cursor cursor; +}; + static inline uint32_t block_id(struct ir3_block *block) { @@ -751,6 +770,10 @@ bool ir3_should_double_threadsize(struct ir3_shader_variant *v, struct ir3_block *ir3_block_create(struct ir3 *shader); +struct ir3_instruction *ir3_build_instr(struct ir3_builder *builder, opc_t opc, + int ndst, int nsrc); +struct ir3_instruction *ir3_instr_create_at(struct ir3_cursor cursor, opc_t opc, + int ndst, int nsrc); struct ir3_instruction *ir3_instr_create(struct ir3_block *block, opc_t opc, int ndst, int nsrc); struct ir3_instruction *ir3_instr_create_at_end(struct ir3_block *block, @@ -2073,6 +2096,79 @@ ir3_has_latency_to_hide(struct ir3 *ir) return false; } +static inline struct ir3_cursor +ir3_before_block(struct ir3_block *block) +{ + assert(block); + struct ir3_cursor cursor; + cursor.option = IR3_CURSOR_BEFORE_BLOCK; + cursor.block = block; + return cursor; +} + +static inline struct ir3_cursor +ir3_after_block(struct ir3_block *block) +{ + assert(block); + struct ir3_cursor cursor; + cursor.option = IR3_CURSOR_AFTER_BLOCK; + cursor.block = block; + return cursor; +} + +static inline struct ir3_cursor +ir3_before_instr(struct ir3_instruction *instr) +{ + assert(instr); + struct ir3_cursor cursor; + cursor.option = IR3_CURSOR_BEFORE_INSTR; + cursor.instr = instr; + return cursor; +} + +static inline struct ir3_cursor +ir3_after_instr(struct ir3_instruction *instr) +{ + assert(instr); + struct ir3_cursor cursor; + cursor.option = IR3_CURSOR_AFTER_INSTR; + cursor.instr = instr; + return cursor; +} + +static inline struct ir3_cursor +ir3_before_terminator(struct ir3_block *block) +{ + assert(block); + struct ir3_instruction *terminator = ir3_block_get_terminator(block); + + if (terminator) + return ir3_before_instr(terminator); + return ir3_after_block(block); +} + +static inline struct ir3_cursor +ir3_after_phis(struct ir3_block *block) +{ + assert(block); + + foreach_instr (instr, &block->instr_list) { + if (instr->opc != OPC_META_PHI) + return ir3_before_instr(instr); + } + + return ir3_after_block(block); +} + +static inline struct ir3_builder +ir3_builder_at(struct ir3_cursor cursor) +{ + struct ir3_builder builder; + builder.cursor = cursor; + return builder; +} + + /* ************************************************************************* */ /* instruction helpers */