X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fcompiler%2Fnir%2Fnir_lower_goto_ifs.c;h=44eaf729ec522a4e0ecb78a413cc5705035c0312;hb=HEAD;hp=e9a137d122bae73c359b926477742686b094437a;hpb=d2bf850672bb3691044d773c9fd96d0e80c7fcf3;p=mesa.git diff --git a/src/compiler/nir/nir_lower_goto_ifs.c b/src/compiler/nir/nir_lower_goto_ifs.c index e9a137d122b..44eaf729ec5 100644 --- a/src/compiler/nir/nir_lower_goto_ifs.c +++ b/src/compiler/nir/nir_lower_goto_ifs.c @@ -25,6 +25,8 @@ #include "nir_builder.h" #include "nir_vla.h" +#define NIR_LOWER_GOTO_IFS_DEBUG 0 + struct path { /** Set of blocks which this path represents * @@ -48,6 +50,7 @@ struct path_fork { }; struct routes { + struct set *outside; struct path regular; struct path brk; struct path cont; @@ -66,6 +69,9 @@ struct strct_lvl { /** Reach set from inside_outside if irreducable */ struct set *reach; + /** Outside set from inside_outside if irreducable */ + struct set *outside; + /** True if a skip region starts with this level */ bool skip_start; @@ -79,11 +85,26 @@ struct strct_lvl { static int nir_block_ptr_cmp(const void *_a, const void *_b) { - nir_block *const *a = _a; - nir_block *const *b = _b; + const nir_block *const *a = _a; + const nir_block *const *b = _b; return (int)(*a)->index - (int)(*b)->index; } +static void +print_block_set(const struct set *set) +{ + printf("{ "); + if (set != NULL) { + unsigned count = 0; + set_foreach(set, entry) { + if (count++) + printf(", "); + printf("%u", ((nir_block *)entry->key)->index); + } + } + printf(" }\n"); +} + /** Return a sorted array of blocks for a set * * Hash set ordering is non-deterministic. We hash based on pointers and so, @@ -270,8 +291,27 @@ fork_reachable(struct path_fork *fork) static void loop_routing_start(struct routes *routing, nir_builder *b, struct path loop_path, struct set *reach, - void *mem_ctx) + struct set *outside, void *mem_ctx) { + if (NIR_LOWER_GOTO_IFS_DEBUG) { + printf("loop_routing_start:\n"); + printf(" reach = "); + print_block_set(reach); + printf(" outside = "); + print_block_set(outside); + printf(" loop_path.reachable = "); + print_block_set(loop_path.reachable); + printf(" routing->outside = "); + print_block_set(routing->outside); + printf(" routing->regular.reachable = "); + print_block_set(routing->regular.reachable); + printf(" routing->brk.reachable = "); + print_block_set(routing->brk.reachable); + printf(" routing->cont.reachable = "); + print_block_set(routing->cont.reachable); + printf("\n"); + } + struct routes *routing_backup = ralloc(mem_ctx, struct routes); *routing_backup = *routing; bool break_needed = false; @@ -290,6 +330,12 @@ loop_routing_start(struct routes *routing, nir_builder *b, continue_needed = true; } + if (outside && outside->entries) { + routing->outside = _mesa_set_clone(routing->outside, routing); + set_foreach(outside, entry) + _mesa_set_add_pre_hashed(routing->outside, entry->hash, entry->key); + } + routing->brk = routing_backup->regular; routing->cont = loop_path; routing->regular = loop_path; @@ -401,6 +447,20 @@ inside_outside(nir_block *block, struct set *loop_heads, struct set *outside, _mesa_set_add(remaining, block->dom_children[i]); } + + if (NIR_LOWER_GOTO_IFS_DEBUG) { + printf("inside_outside(%u):\n", block->index); + printf(" loop_heads = "); + print_block_set(loop_heads); + printf(" reach = "); + print_block_set(reach); + printf(" brk_reach = "); + print_block_set(brk_reachable); + printf(" remaining = "); + print_block_set(remaining); + printf("\n"); + } + bool progress = true; while (remaining->entries && progress) { progress = false; @@ -446,6 +506,13 @@ inside_outside(nir_block *block, struct set *loop_heads, struct set *outside, _mesa_set_add(reach, block->successors[i]); } } + + if (NIR_LOWER_GOTO_IFS_DEBUG) { + printf("outside(%u) = ", block->index); + print_block_set(outside); + printf("reach(%u) = ", block->index); + print_block_set(reach); + } } static struct path_fork * @@ -561,6 +628,7 @@ handle_irreducible(struct set *remaining, struct strct_lvl *curr_level, inside_outside((nir_block *) entry->key, loop_heads, remaining, curr_level->reach, brk_reachable, mem_ctx); } + curr_level->outside = remaining; _mesa_set_destroy(loop_heads, NULL); } @@ -600,10 +668,21 @@ handle_irreducible(struct set *remaining, struct strct_lvl *curr_level, * zeroth level */ static void -organize_levels(struct list_head *levels, struct set *remaining, +organize_levels(struct list_head *levels, struct set *children, struct set *reach, struct routes *routing, nir_function_impl *impl, bool is_domminated, void *mem_ctx) { + if (NIR_LOWER_GOTO_IFS_DEBUG) { + printf("organize_levels:\n"); + printf(" children = "); + print_block_set(children); + printf(" reach = "); + print_block_set(reach); + } + + /* Duplicate remaining because we're going to destroy it */ + struct set *remaining = _mesa_set_clone(children, mem_ctx); + /* blocks that can be reached by the remaining blocks */ struct set *remaining_frontier = _mesa_pointer_set_create(mem_ctx); @@ -697,6 +776,15 @@ organize_levels(struct list_head *levels, struct set *remaining, list_addtail(&curr_level->link, levels); } + if (NIR_LOWER_GOTO_IFS_DEBUG) { + printf(" levels:\n"); + list_for_each_entry(struct strct_lvl, level, levels, link) { + printf(" "); + print_block_set(level->blocks); + } + printf("\n"); + } + if (skip_targets->entries) list_last_entry(levels, struct strct_lvl, link)->skip_end = 1; @@ -771,8 +859,10 @@ plant_levels(struct list_head *levels, struct routes *routing, } struct path in_path = routing->regular; routing->regular = level->out_path; - if (level->irreducible) - loop_routing_start(routing, b, in_path, level->reach, mem_ctx); + if (level->irreducible) { + loop_routing_start(routing, b, in_path, level->reach, + level->outside, mem_ctx); + } select_blocks(routing, b, in_path, mem_ctx); if (level->irreducible) loop_routing_end(routing, b); @@ -791,7 +881,7 @@ nir_structurize(struct routes *routing, nir_builder *b, nir_block *block, { struct set *remaining = _mesa_pointer_set_create(mem_ctx); for (int i = 0; i < block->num_dom_children; i++) { - if (!_mesa_set_search(routing->brk.reachable, block->dom_children[i])) + if (!_mesa_set_search(routing->outside, block->dom_children[i])) _mesa_set_add(remaining, block->dom_children[i]); } @@ -819,7 +909,7 @@ nir_structurize(struct routes *routing, nir_builder *b, nir_block *block, }; _mesa_set_add(loop_path.reachable, block); - loop_routing_start(routing, b, loop_path, reach, mem_ctx); + loop_routing_start(routing, b, loop_path, reach, outside, mem_ctx); } struct set *reach = _mesa_pointer_set_create(mem_ctx); @@ -890,6 +980,7 @@ nir_lower_goto_ifs_impl(nir_function_impl *impl) struct routes *routing = ralloc(mem_ctx, struct routes); *routing = (struct routes) { + .outside = empty_set, .regular.reachable = end_set, .brk.reachable = empty_set, .cont.reachable = empty_set,