diff options
author | Jason Ekstrand <[email protected]> | 2015-08-25 17:12:03 -0700 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2015-08-25 18:41:21 -0700 |
commit | 9b387b5d3f4103c51079ea5298d33086af6da433 (patch) | |
tree | 4127f2284b6b4a5746bbc01bbfc6a97305057cb4 /src/util | |
parent | 5360edcb304e147341b934567f3bbf40e9d5a3b5 (diff) | |
parent | 1d2a844e7d55645ea3d24fb589bec03695b3d2b1 (diff) |
Merge remote-tracking branch 'mesa-public/master' into vulkan
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/bitset.h | 36 | ||||
-rw-r--r-- | src/util/register_allocate.c | 62 | ||||
-rw-r--r-- | src/util/register_allocate.h | 4 | ||||
-rw-r--r-- | src/util/rounding.h | 3 |
4 files changed, 87 insertions, 18 deletions
diff --git a/src/util/bitset.h b/src/util/bitset.h index febcddefd97..c452819414f 100644 --- a/src/util/bitset.h +++ b/src/util/bitset.h @@ -96,4 +96,40 @@ __bitset_ffs(const BITSET_WORD *x, int n) #define BITSET_FFS(x) __bitset_ffs(x, ARRAY_SIZE(x)) +static inline unsigned +__bitset_next_set(unsigned i, BITSET_WORD *tmp, + BITSET_WORD *set, unsigned size) +{ + unsigned bit, word; + + /* NOTE: The initial conditions for this function are very specific. At + * the start of the loop, the tmp variable must be set to *set and the + * initial i value set to 0. This way, if there is a bit set in the first + * word, we ignore the i-value and just grab that bit (so 0 is ok, even + * though 0 may be returned). If the first word is 0, then the value of + * `word` will be 0 and we will go on to look at the second word. + */ + word = BITSET_BITWORD(i); + while (*tmp == 0) { + word++; + + if (word >= BITSET_WORDS(size)) + return size; + + *tmp = set[word]; + } + + /* Find the next set bit in the non-zero word */ + bit = ffs(*tmp) - 1; + + /* Unset the bit */ + *tmp &= ~(1ull << bit); + + return word * BITSET_WORDBITS + bit; +} + +#define BITSET_FOREACH_SET(__i, __tmp, __set, __size) \ + for (__tmp = *(__set), __i = 0; \ + (__i = __bitset_next_set(__i, &__tmp, __set, __size)) < __size;) + #endif diff --git a/src/util/register_allocate.c b/src/util/register_allocate.c index 436e008b01a..8af93c0406c 100644 --- a/src/util/register_allocate.c +++ b/src/util/register_allocate.c @@ -183,7 +183,7 @@ struct ra_graph { * using ralloc_free(). */ struct ra_regs * -ra_alloc_reg_set(void *mem_ctx, unsigned int count) +ra_alloc_reg_set(void *mem_ctx, unsigned int count, bool need_conflict_lists) { unsigned int i; struct ra_regs *regs; @@ -197,9 +197,15 @@ ra_alloc_reg_set(void *mem_ctx, unsigned int count) BITSET_WORDS(count)); BITSET_SET(regs->regs[i].conflicts, i); - regs->regs[i].conflict_list = ralloc_array(regs->regs, unsigned int, 4); - regs->regs[i].conflict_list_size = 4; - regs->regs[i].conflict_list[0] = i; + if (need_conflict_lists) { + regs->regs[i].conflict_list = ralloc_array(regs->regs, + unsigned int, 4); + regs->regs[i].conflict_list_size = 4; + regs->regs[i].conflict_list[0] = i; + } else { + regs->regs[i].conflict_list = NULL; + regs->regs[i].conflict_list_size = 0; + } regs->regs[i].num_conflicts = 1; } @@ -227,12 +233,14 @@ ra_add_conflict_list(struct ra_regs *regs, unsigned int r1, unsigned int r2) { struct ra_reg *reg1 = ®s->regs[r1]; - if (reg1->conflict_list_size == reg1->num_conflicts) { - reg1->conflict_list_size *= 2; - reg1->conflict_list = reralloc(regs->regs, reg1->conflict_list, - unsigned int, reg1->conflict_list_size); + if (reg1->conflict_list) { + if (reg1->conflict_list_size == reg1->num_conflicts) { + reg1->conflict_list_size *= 2; + reg1->conflict_list = reralloc(regs->regs, reg1->conflict_list, + unsigned int, reg1->conflict_list_size); + } + reg1->conflict_list[reg1->num_conflicts++] = r2; } - reg1->conflict_list[reg1->num_conflicts++] = r2; BITSET_SET(reg1->conflicts, r2); } @@ -255,7 +263,7 @@ ra_add_reg_conflict(struct ra_regs *regs, unsigned int r1, unsigned int r2) */ void ra_add_transitive_reg_conflict(struct ra_regs *regs, - unsigned int base_reg, unsigned int reg) + unsigned int base_reg, unsigned int reg) { unsigned int i; @@ -266,13 +274,37 @@ ra_add_transitive_reg_conflict(struct ra_regs *regs, } } +/** + * Makes every conflict on the given register transitive. In other words, + * every register that conflicts with r will now conflict with every other + * register conflicting with r. + * + * This can simplify code for setting up multiple register classes + * which are aggregates of some base hardware registers, compared to + * explicitly using ra_add_reg_conflict. + */ +void +ra_make_reg_conflicts_transitive(struct ra_regs *regs, unsigned int r) +{ + struct ra_reg *reg = ®s->regs[r]; + BITSET_WORD tmp; + int c; + + BITSET_FOREACH_SET(c, tmp, reg->conflicts, regs->count) { + struct ra_reg *other = ®s->regs[c]; + unsigned i; + for (i = 0; i < BITSET_WORDS(regs->count); i++) + other->conflicts[i] |= reg->conflicts[i]; + } +} + unsigned int ra_alloc_reg_class(struct ra_regs *regs) { struct ra_class *class; regs->classes = reralloc(regs->regs, regs->classes, struct ra_class *, - regs->class_count + 1); + regs->class_count + 1); class = rzalloc(regs, struct ra_class); regs->classes[regs->class_count] = class; @@ -319,7 +351,7 @@ ra_set_finalize(struct ra_regs *regs, unsigned int **q_values) for (b = 0; b < regs->class_count; b++) { for (c = 0; c < regs->class_count; c++) { regs->classes[b]->q[c] = q_values[b][c]; - } + } } } else { /* Compute, for each class B and C, how many regs of B an @@ -410,14 +442,14 @@ ra_alloc_interference_graph(struct ra_regs *regs, unsigned int count) void ra_set_node_class(struct ra_graph *g, - unsigned int n, unsigned int class) + unsigned int n, unsigned int class) { g->nodes[n].class = class; } void ra_add_node_interference(struct ra_graph *g, - unsigned int n1, unsigned int n2) + unsigned int n1, unsigned int n2) { if (!BITSET_TEST(g->nodes[n1].adjacency, n2)) { ra_add_node_adjacency(g, n1, n2); @@ -445,7 +477,7 @@ decrement_q(struct ra_graph *g, unsigned int n) if (n != n2 && !g->nodes[n2].in_stack) { assert(g->nodes[n2].q_total >= g->regs->classes[n2_class]->q[n_class]); - g->nodes[n2].q_total -= g->regs->classes[n2_class]->q[n_class]; + g->nodes[n2].q_total -= g->regs->classes[n2_class]->q[n_class]; } } } diff --git a/src/util/register_allocate.h b/src/util/register_allocate.h index 61f182eff49..628d2bbbced 100644 --- a/src/util/register_allocate.h +++ b/src/util/register_allocate.h @@ -44,13 +44,15 @@ struct ra_regs; * registers, such as aligned register pairs that conflict with the * two real registers from which they are composed. */ -struct ra_regs *ra_alloc_reg_set(void *mem_ctx, unsigned int count); +struct ra_regs *ra_alloc_reg_set(void *mem_ctx, unsigned int count, + bool need_conflict_lists); void ra_set_allocate_round_robin(struct ra_regs *regs); unsigned int ra_alloc_reg_class(struct ra_regs *regs); void ra_add_reg_conflict(struct ra_regs *regs, unsigned int r1, unsigned int r2); void ra_add_transitive_reg_conflict(struct ra_regs *regs, unsigned int base_reg, unsigned int reg); +void ra_make_reg_conflicts_transitive(struct ra_regs *regs, unsigned int reg); void ra_class_add_reg(struct ra_regs *regs, unsigned int c, unsigned int reg); void ra_set_num_conflicts(struct ra_regs *regs, unsigned int class_a, unsigned int class_b, unsigned int num_conflicts); diff --git a/src/util/rounding.h b/src/util/rounding.h index 7b5608b8a78..afb38fbdb56 100644 --- a/src/util/rounding.h +++ b/src/util/rounding.h @@ -24,9 +24,8 @@ #ifndef _ROUNDING_H #define _ROUNDING_H -#include "c99_compat.h" // inline +#include "c99_math.h" -#include <math.h> #include <limits.h> #include <stdint.h> |