summaryrefslogtreecommitdiffstats
path: root/src/util
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2015-08-25 17:12:03 -0700
committerJason Ekstrand <[email protected]>2015-08-25 18:41:21 -0700
commit9b387b5d3f4103c51079ea5298d33086af6da433 (patch)
tree4127f2284b6b4a5746bbc01bbfc6a97305057cb4 /src/util
parent5360edcb304e147341b934567f3bbf40e9d5a3b5 (diff)
parent1d2a844e7d55645ea3d24fb589bec03695b3d2b1 (diff)
Merge remote-tracking branch 'mesa-public/master' into vulkan
Diffstat (limited to 'src/util')
-rw-r--r--src/util/bitset.h36
-rw-r--r--src/util/register_allocate.c62
-rw-r--r--src/util/register_allocate.h4
-rw-r--r--src/util/rounding.h3
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 = &regs->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 = &regs->regs[r];
+ BITSET_WORD tmp;
+ int c;
+
+ BITSET_FOREACH_SET(c, tmp, reg->conflicts, regs->count) {
+ struct ra_reg *other = &regs->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>