From dd55bd8f68810a58257f05aa41e0ef206836b39e Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Fri, 29 Jan 2021 15:31:52 +0100 Subject: [PATCH] ir3: Make predecessors an array We need a stable order in order to create phi instructions. In the future we can make this more sophisticated in order to make manipulating the CFG easier, but for now that only happens after RA, so we won't have to worry about it. Part-of: --- src/freedreno/ir3/ir3.c | 33 +++++++++++++++++++++++++++- src/freedreno/ir3/ir3.h | 6 ++++- src/freedreno/ir3/ir3_compiler_nir.c | 2 +- src/freedreno/ir3/ir3_delay.c | 8 +++---- src/freedreno/ir3/ir3_legalize.c | 21 +++++++++--------- src/freedreno/ir3/ir3_print.c | 12 ++++------ 6 files changed, 56 insertions(+), 26 deletions(-) diff --git a/src/freedreno/ir3/ir3.c b/src/freedreno/ir3/ir3.c index 9dca30d54f6..aac729f9d57 100644 --- a/src/freedreno/ir3/ir3.c +++ b/src/freedreno/ir3/ir3.c @@ -352,10 +352,41 @@ struct ir3_block * ir3_block_create(struct ir3 *shader) block->shader = shader; list_inithead(&block->node); list_inithead(&block->instr_list); - block->predecessors = _mesa_pointer_set_create(block); return block; } + +void ir3_block_add_predecessor(struct ir3_block *block, struct ir3_block *pred) +{ + array_insert(block, block->predecessors, pred); +} + +void ir3_block_remove_predecessor(struct ir3_block *block, struct ir3_block *pred) +{ + for (unsigned i = 0; i < block->predecessors_count; i++) { + if (block->predecessors[i] == pred) { + if (i < block->predecessors_count - 1) { + block->predecessors[i] = + block->predecessors[block->predecessors_count - 1]; + } + + block->predecessors_count--; + return; + } + } +} + +unsigned ir3_block_get_pred_index(struct ir3_block *block, struct ir3_block *pred) +{ + for (unsigned i = 0; i < block->predecessors_count; i++) { + if (block->predecessors[i] == pred) { + return i; + } + } + + unreachable("ir3_block_get_pred_index() invalid predecessor"); +} + static struct ir3_instruction *instr_create(struct ir3_block *block, int nreg) { struct ir3_instruction *instr; diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index 43056371f63..bcac2103e74 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -550,7 +550,7 @@ struct ir3_block { struct ir3_instruction *condition; struct ir3_block *successors[2]; - struct set *predecessors; /* set of ir3_block */ + DECLARE_ARRAY(struct ir3_block *, predecessors); uint16_t start_ip, end_ip; @@ -579,6 +579,10 @@ block_id(struct ir3_block *block) #endif } +void ir3_block_add_predecessor(struct ir3_block *block, struct ir3_block *pred); +void ir3_block_remove_predecessor(struct ir3_block *block, struct ir3_block *pred); +unsigned ir3_block_get_pred_index(struct ir3_block *block, struct ir3_block *pred); + struct ir3_shader_variant; struct ir3 * ir3_create(struct ir3_compiler *compiler, struct ir3_shader_variant *v); diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index 3c466fca4b5..883f0314539 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -2959,7 +2959,7 @@ setup_predecessors(struct ir3 *ir) foreach_block(block, &ir->block_list) { for (int i = 0; i < ARRAY_SIZE(block->successors); i++) { if (block->successors[i]) - _mesa_set_add(block->successors[i]->predecessors, block); + ir3_block_add_predecessor(block->successors[i], block); } } } diff --git a/src/freedreno/ir3/ir3_delay.c b/src/freedreno/ir3/ir3_delay.c index ae93866602d..c85b9c8a383 100644 --- a/src/freedreno/ir3/ir3_delay.c +++ b/src/freedreno/ir3/ir3_delay.c @@ -149,8 +149,8 @@ distance(struct ir3_block *block, struct ir3_instruction *instr, /* (ab)use block->data to prevent recursion: */ block->data = block; - set_foreach (block->predecessors, entry) { - struct ir3_block *pred = (struct ir3_block *)entry->key; + for (unsigned i = 0; i < block->predecessors_count; i++) { + struct ir3_block *pred = block->predecessors[i]; unsigned n; n = distance(pred, instr, min, pred); @@ -288,8 +288,8 @@ delay_calc_array(struct ir3_block *block, unsigned array_id, /* (ab)use block->data to prevent recursion: */ block->data = block; - set_foreach (block->predecessors, entry) { - struct ir3_block *pred = (struct ir3_block *)entry->key; + for (unsigned i = 0; i < block->predecessors_count; i++) { + struct ir3_block *pred = block->predecessors[i]; unsigned delay = delay_calc_array(pred, array_id, consumer, srcn, soft, pred, maxd); diff --git a/src/freedreno/ir3/ir3_legalize.c b/src/freedreno/ir3/ir3_legalize.c index 1defd2874fb..72073f61a0c 100644 --- a/src/freedreno/ir3/ir3_legalize.c +++ b/src/freedreno/ir3/ir3_legalize.c @@ -97,8 +97,8 @@ legalize_block(struct ir3_legalize_ctx *ctx, struct ir3_block *block) bool mergedregs = ctx->so->mergedregs; /* our input state is the OR of all predecessor blocks' state: */ - set_foreach(block->predecessors, entry) { - struct ir3_block *predecessor = (struct ir3_block *)entry->key; + for (unsigned i = 0; i < block->predecessors_count; i++) { + struct ir3_block *predecessor = block->predecessors[i]; struct ir3_legalize_block_data *pbd = predecessor->data; struct ir3_legalize_state *pstate = &pbd->state; @@ -480,7 +480,7 @@ remove_unused_block(struct ir3_block *old_target) for (unsigned i = 0; i < ARRAY_SIZE(old_target->successors); i++) { if (old_target->successors[i]) { struct ir3_block *succ = old_target->successors[i]; - _mesa_set_remove_key(succ->predecessors, old_target); + ir3_block_remove_predecessor(succ, old_target); } } } @@ -500,13 +500,12 @@ retarget_jump(struct ir3_instruction *instr, struct ir3_block *new_target) } /* update new target's predecessors: */ - _mesa_set_add(new_target->predecessors, cur_block); + ir3_block_add_predecessor(new_target, cur_block); /* and remove old_target's predecessor: */ - debug_assert(_mesa_set_search(old_target->predecessors, cur_block)); - _mesa_set_remove_key(old_target->predecessors, cur_block); + ir3_block_remove_predecessor(old_target, cur_block); - if (old_target->predecessors->entries == 0) + if (old_target->predecessors_count == 0) remove_unused_block(old_target); instr->cat0.target = new_target; @@ -588,17 +587,17 @@ static void mark_xvergence_points(struct ir3 *ir) { foreach_block (block, &ir->block_list) { - if (block->predecessors->entries > 1) { + if (block->predecessors_count > 1) { /* if a block has more than one possible predecessor, then * the first instruction is a convergence point. */ mark_jp(block); - } else if (block->predecessors->entries == 1) { + } else if (block->predecessors_count == 1) { /* If a block has one predecessor, which has multiple possible * successors, it is a divergence point. */ - set_foreach(block->predecessors, entry) { - struct ir3_block *predecessor = (struct ir3_block *)entry->key; + for (unsigned i = 0; i < block->predecessors_count; i++) { + struct ir3_block *predecessor = block->predecessors[i]; if (predecessor->successors[1]) { mark_jp(block); } diff --git a/src/freedreno/ir3/ir3_print.c b/src/freedreno/ir3/ir3_print.c index 3d24036f7ff..1f60b4dfaf4 100644 --- a/src/freedreno/ir3/ir3_print.c +++ b/src/freedreno/ir3/ir3_print.c @@ -355,16 +355,12 @@ print_block(struct ir3_block *block, int lvl) { tab(lvl); printf("block%u {\n", block_id(block)); - /* computerator (ir3 assembler) doesn't really use blocks for flow - * control, so block->predecessors will be null. - */ - if (block->predecessors && block->predecessors->entries > 0) { - unsigned i = 0; + if (block->predecessors_count > 0) { tab(lvl+1); printf("pred: "); - set_foreach (block->predecessors, entry) { - struct ir3_block *pred = (struct ir3_block *)entry->key; - if (i++) + for (unsigned i = 0; i < block->predecessors_count; i++) { + struct ir3_block *pred = block->predecessors[i]; + if (i != 0) printf(", "); printf("block%u", block_id(pred)); }