From 9cccb89dbc8d7c48af9c683167baadcdbfdd11d7 Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Sat, 14 Oct 2023 16:03:14 -0700 Subject: [PATCH] util/ra: Don't store a pointer to graph per ra_node Each node stores a list of adjacent nodes. This was handled by util_dynarray, however each of those hold an extra pointer for the ra_graph (which serves as mem_ctx for that). Since the usage here is very simple, we just handle the array growth manually. For now keep using the same initial size as was being used by dynarray. Reviewed-by: Matt Turner Part-of: --- src/util/register_allocate.c | 49 +++++++++++++++++---------- src/util/register_allocate_internal.h | 8 ++++- 2 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/util/register_allocate.c b/src/util/register_allocate.c index ac75e917020..2c2c3fd2bcf 100644 --- a/src/util/register_allocate.c +++ b/src/util/register_allocate.c @@ -517,7 +517,12 @@ ra_add_node_adjacency(struct ra_graph *g, unsigned int n1, unsigned int n2) int n2_class = g->nodes[n2].class; g->nodes[n1].q_total += g->regs->classes[n1_class]->q[n2_class]; - util_dynarray_append(&g->nodes[n1].adjacency_list, unsigned int, n2); + struct ra_list *adj = &g->nodes[n1].adjacency; + if (adj->size == adj->cap) { + adj->cap = MAX2(16, adj->cap * 2); + adj->elems = reralloc(g, adj->elems, unsigned int, adj->cap); + } + adj->elems[adj->size++] = n2; } static void @@ -530,8 +535,14 @@ ra_node_remove_adjacency(struct ra_graph *g, unsigned int n1, unsigned int n2) int n2_class = g->nodes[n2].class; g->nodes[n1].q_total -= g->regs->classes[n1_class]->q[n2_class]; - util_dynarray_delete_unordered(&g->nodes[n1].adjacency_list, unsigned int, - n2); + struct ra_list *adj = &g->nodes[n1].adjacency; + for (unsigned i = 0; i < adj->size; i++) { + if (adj->elems[i] == n2) { + adj->elems[i] = adj->elems[adj->size - 1]; + adj->size--; + break; + } + } } static void @@ -554,7 +565,6 @@ ra_realloc_interference_graph(struct ra_graph *g, unsigned int alloc) /* Initialize new nodes. */ for (unsigned i = g->alloc; i < alloc; i++) { struct ra_node* node = g->nodes + i; - util_dynarray_init(&node->adjacency_list, g); node->q_total = 0; node->reg = NO_REG; g->nodes_extra[i].forced_reg = NO_REG; @@ -647,11 +657,12 @@ ra_add_node_interference(struct ra_graph *g, void ra_reset_node_interference(struct ra_graph *g, unsigned int n) { - util_dynarray_foreach(&g->nodes[n].adjacency_list, unsigned int, n2p) { - ra_node_remove_adjacency(g, *n2p, n); - } + struct ra_list *adj = &g->nodes[n].adjacency; - util_dynarray_clear(&g->nodes[n].adjacency_list); + for (unsigned i = 0; i < adj->size; i++) + ra_node_remove_adjacency(g, adj->elems[i], n); + + adj->size = 0; } static void @@ -684,8 +695,9 @@ add_node_to_stack(struct ra_graph *g, unsigned int n) assert(!BITSET_TEST(g->tmp.in_stack, n)); - util_dynarray_foreach(&g->nodes[n].adjacency_list, unsigned int, n2p) { - unsigned int n2 = *n2p; + struct ra_list *adj = &g->nodes[n].adjacency; + for (unsigned i = 0; i < adj->size; i++) { + unsigned int n2 = adj->elems[i]; unsigned int n2_class = g->nodes[n2].class; if (!BITSET_TEST(g->tmp.in_stack, n2) && @@ -833,8 +845,9 @@ ra_class_allocations_conflict(struct ra_class *c1, unsigned int r1, static struct ra_node * ra_find_conflicting_neighbor(struct ra_graph *g, unsigned int n, unsigned int r) { - util_dynarray_foreach(&g->nodes[n].adjacency_list, unsigned int, n2p) { - unsigned int n2 = *n2p; + struct ra_list *adj = &g->nodes[n].adjacency; + for (unsigned i = 0; i < adj->size; i++) { + unsigned int n2 = adj->elems[i]; /* If our adjacent node is in the stack, it's not allocated yet. */ if (!BITSET_TEST(g->tmp.in_stack, n2) && @@ -864,11 +877,12 @@ ra_compute_available_regs(struct ra_graph *g, unsigned int n, BITSET_WORD *regs) /* Remove any regs that conflict with nodes that we're adjacent to and have * already colored. */ - util_dynarray_foreach(&g->nodes[n].adjacency_list, unsigned int, n2p) { - struct ra_node *n2 = &g->nodes[*n2p]; + struct ra_list *adj = &g->nodes[n].adjacency; + for (unsigned i = 0; i < adj->size; i++) { + struct ra_node *n2 = &g->nodes[adj->elems[i]]; struct ra_class *n2c = g->regs->classes[n2->class]; - if (!BITSET_TEST(g->tmp.in_stack, *n2p)) { + if (!BITSET_TEST(g->tmp.in_stack, adj->elems[i])) { if (c->contig_len) { int start = MAX2(0, (int)n2->reg - c->contig_len + 1); int end = MIN2(g->regs->count, n2->reg + n2c->contig_len); @@ -1022,8 +1036,9 @@ ra_get_spill_benefit(struct ra_graph *g, unsigned int n) * "count number of edges" approach of traditional graph coloring, * but takes classes into account. */ - util_dynarray_foreach(&g->nodes[n].adjacency_list, unsigned int, n2p) { - unsigned int n2 = *n2p; + struct ra_list *adj = &g->nodes[n].adjacency; + for (unsigned i = 0; i < adj->size; i++) { + unsigned int n2 = adj->elems[i]; unsigned int n2_class = g->nodes[n2].class; benefit += ((float)g->regs->classes[n_class]->q[n2_class] / g->regs->classes[n_class]->p); diff --git a/src/util/register_allocate_internal.h b/src/util/register_allocate_internal.h index 4620d5f64f8..2e5f1e027a0 100644 --- a/src/util/register_allocate_internal.h +++ b/src/util/register_allocate_internal.h @@ -38,6 +38,12 @@ extern "C" { #define class klass #endif +struct ra_list { + unsigned int *elems; + unsigned int size; + unsigned int cap; +}; + struct ra_reg { BITSET_WORD *conflicts; struct util_dynarray conflict_list; @@ -92,7 +98,7 @@ struct ra_node { * List of which nodes this node interferes with. This should be * symmetric with the other node. */ - struct util_dynarray adjacency_list; + struct ra_list adjacency; /** @} */ unsigned int class;