From 6f0d595bb521f157c19f613ac99f66f6961601d7 Mon Sep 17 00:00:00 2001 From: Job Noorman Date: Mon, 17 Jun 2024 11:34:26 +0200 Subject: [PATCH] ir3: add ir3_cursor/ir3_builder helpers Whenever instructions need to be created at specific locations, ir3 often passes around an instruction pointer. When set, new instructions are added before or after it (depending on the context). When NULL, new instructions are added at the end of the block. This whole scheme is confusing. This patch adds ir3_cursor and ir3_builder structs and the associated helper functions. The API mirrors the one from nir_cursor/nir_builder. This patch does not refactor existing code to use the new API. This will happen in future patches. Fixes: 613eaac7b53 ("ir3: Initial support for spilling non-shared registers") Signed-off-by: Job Noorman Part-of: (cherry picked from commit 1972db36c6eab65a2f48bc2b1397fab8d74e0088) --- .pick_status.json | 2 +- src/freedreno/ir3/ir3.c | 76 ++++++++++++++++++++++---------- src/freedreno/ir3/ir3.h | 96 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 151 insertions(+), 23 deletions(-) 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 */