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: 613eaac7b5 ("ir3: Initial support for spilling non-shared registers")
Signed-off-by: Job Noorman <jnoorman@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29497>
(cherry picked from commit 1972db36c6)
This commit is contained in:
Job Noorman 2024-06-17 11:34:26 +02:00 committed by Eric Engestrom
parent 4e9a52ffc7
commit 6f0d595bb5
3 changed files with 151 additions and 23 deletions

View file

@ -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

View file

@ -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;

View file

@ -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 */