panfrost: Move lcra to panfrost/util
authorAlyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Thu, 12 Mar 2020 00:08:03 +0000 (20:08 -0400)
committerMarge Bot <eric+marge@anholt.net>
Thu, 12 Mar 2020 12:41:08 +0000 (12:41 +0000)
We'll want to use it for the Bifrost RA as well.

Signed-off-by: Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4158>

src/panfrost/Makefile.sources
src/panfrost/midgard/compiler.h
src/panfrost/midgard/lcra.c [deleted file]
src/panfrost/midgard/lcra.h [deleted file]
src/panfrost/midgard/meson.build
src/panfrost/midgard/midgard_ra.c
src/panfrost/util/lcra.c [new file with mode: 0644]
src/panfrost/util/lcra.h [new file with mode: 0644]
src/panfrost/util/meson.build

index fd58252345a065973f715e7152970a18ecabfc47..212a1d7e5400bbf7c6d41a1cfeb6ea21994e0d0d 100644 (file)
@@ -54,7 +54,6 @@ midgard_FILES := \
         midgard/mir_promote_uniforms.c \
         midgard/mir_squeeze.c \
         midgard/nir_undef_to_zero.c \
-        midgard/lcra.c
 
 shared_FILES := \
         shared/pan_minmax_cache.c \
index 6614439fbfb551939702826325bfbd00ca9b765d..bc43309c7a16452b379c8f5d86423da32e0b05ae 100644 (file)
@@ -28,7 +28,6 @@
 #include "helpers.h"
 #include "midgard_compile.h"
 #include "midgard_ops.h"
-#include "lcra.h"
 
 #include "util/hash_table.h"
 #include "util/u_dynarray.h"
@@ -39,6 +38,7 @@
 #include "compiler/nir_types.h"
 #include "compiler/nir/nir.h"
 #include "panfrost/util/pan_ir.h"
+#include "panfrost/util/lcra.h"
 
 /* Forward declare */
 struct midgard_block;
diff --git a/src/panfrost/midgard/lcra.c b/src/panfrost/midgard/lcra.c
deleted file mode 100644 (file)
index 28f9a73..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * Copyright (C) 2019 Collabora, Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors (Collabora):
- *      Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
- */
-
-#include <stdio.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include "util/macros.h"
-#include "util/u_math.h"
-#include "lcra.h"
-
-/* This module is the reference implementation of "Linearly Constrained
- * Register Allocation". The paper is available in PDF form
- * (https://people.collabora.com/~alyssa/LCRA.pdf) as well as Markdown+LaTeX
- * (https://gitlab.freedesktop.org/alyssa/lcra/blob/master/LCRA.md)
- */
-
-struct lcra_state *
-lcra_alloc_equations(
-                unsigned node_count,
-                unsigned min_alignment, unsigned max_alignment,
-                unsigned bound, unsigned class_count)
-{
-        struct lcra_state *l = calloc(1, sizeof(*l));
-
-        l->node_count = node_count;
-        l->class_count = class_count;
-        l->bound = bound;
-
-        l->alignment = calloc(sizeof(l->alignment[0]), node_count);
-        l->linear = calloc(sizeof(l->linear[0]), node_count * node_count);
-        l->modulus = calloc(sizeof(l->modulus[0]), node_count);
-        l->class = calloc(sizeof(l->class[0]), node_count);
-        l->class_start = calloc(sizeof(l->class_start[0]), class_count);
-        l->class_disjoint = calloc(sizeof(l->class_disjoint[0]), class_count * class_count);
-        l->class_size = calloc(sizeof(l->class_size[0]), class_count);
-        l->spill_cost = calloc(sizeof(l->spill_cost[0]), node_count);
-        l->solutions = calloc(sizeof(l->solutions[0]), node_count);
-
-        memset(l->solutions, ~0, sizeof(l->solutions[0]) * node_count);
-
-        return l;
-}
-
-void
-lcra_free(struct lcra_state *l)
-{
-        if (!l)
-                return;
-
-        free(l->alignment);
-        free(l->linear);
-        free(l->modulus);
-        free(l->class);
-        free(l->class_start);
-        free(l->class_disjoint);
-        free(l->class_size);
-        free(l->spill_cost);
-        free(l->solutions);
-
-        free(l);
-}
-
-void
-lcra_set_alignment(struct lcra_state *l, unsigned node, unsigned align_log2)
-{
-        l->alignment[node] = align_log2 + 1;
-}
-
-void
-lcra_set_disjoint_class(struct lcra_state *l, unsigned c1, unsigned c2)
-{
-        l->class_disjoint[(c1 * l->class_count) + c2] = true;
-        l->class_disjoint[(c2 * l->class_count) + c1] = true;
-}
-
-void
-lcra_restrict_range(struct lcra_state *l, unsigned node, unsigned len)
-{
-        if (node < l->node_count && l->alignment[node])
-                l->modulus[node] = DIV_ROUND_UP(l->bound - len + 1, 1 << (l->alignment[node] - 1));
-}
-
-void
-lcra_add_node_interference(struct lcra_state *l, unsigned i, unsigned cmask_i, unsigned j, unsigned cmask_j)
-{
-        if (i == j)
-                return;
-
-        if (l->class_disjoint[(l->class[i] * l->class_count) + l->class[j]])
-                return;
-
-        uint32_t constraint_fw = 0;
-        uint32_t constraint_bw = 0;
-
-        for (unsigned D = 0; D < 16; ++D) {
-                if (cmask_i & (cmask_j << D)) {
-                        constraint_bw |= (1 << (15 + D));
-                        constraint_fw |= (1 << (15 - D));
-                }
-
-                if (cmask_i & (cmask_j >> D)) {
-                        constraint_fw |= (1 << (15 + D));
-                        constraint_bw |= (1 << (15 - D));
-                }
-        }
-
-        l->linear[j * l->node_count + i] |= constraint_fw;
-        l->linear[i * l->node_count + j] |= constraint_bw;
-}
-
-static bool
-lcra_test_linear(struct lcra_state *l, unsigned *solutions, unsigned i)
-{
-        unsigned *row = &l->linear[i * l->node_count];
-        signed constant = solutions[i];
-
-        for (unsigned j = 0; j < l->node_count; ++j) {
-                if (solutions[j] == ~0) continue;
-
-                signed lhs = solutions[j] - constant;
-
-                if (lhs < -15 || lhs > 15)
-                        continue;
-
-                if (row[j] & (1 << (lhs + 15)))
-                        return false;
-        }
-
-        return true;
-}
-
-bool
-lcra_solve(struct lcra_state *l)
-{
-        for (unsigned step = 0; step < l->node_count; ++step) {
-                if (l->solutions[step] != ~0) continue;
-                if (l->alignment[step] == 0) continue;
-
-                unsigned _class = l->class[step];
-                unsigned class_start = l->class_start[_class];
-
-                unsigned shift = l->alignment[step] - 1;
-
-                unsigned P = l->bound >> shift;
-                unsigned Q = l->modulus[step];
-                unsigned r_max = l->class_size[_class];
-                unsigned k_max = r_max >> shift;
-                unsigned m_max = k_max / P;
-                bool succ = false;
-
-                for (unsigned m = 0; m < m_max; ++m) {
-                        for (unsigned n = 0; n < Q; ++n) {
-                                l->solutions[step] = ((m * P + n) << shift) + class_start;
-                                succ = lcra_test_linear(l, l->solutions, step);
-
-                                if (succ) break;
-                        }
-
-                        if (succ) break;
-                }
-
-                /* Out of registers - prepare to spill */
-                if (!succ) {
-                        l->spill_class = l->class[step];
-                        return false;
-                }
-        }
-
-        return true;
-}
-
-/* Register spilling is implemented with a cost-benefit system. Costs are set
- * by the user. Benefits are calculated from the constraints. */
-
-void
-lcra_set_node_spill_cost(struct lcra_state *l, unsigned node, signed cost)
-{
-        if (node < l->node_count)
-                l->spill_cost[node] = cost;
-}
-
-/* Count along the lower triangle */
-
-static unsigned
-lcra_count_constraints(struct lcra_state *l, unsigned i)
-{
-        unsigned count = 0;
-        unsigned *constraints = &l->linear[i * l->node_count];
-
-        for (unsigned j = 0; j < i; ++j)
-                count += util_bitcount(constraints[j]);
-
-        return count;
-}
-
-signed
-lcra_get_best_spill_node(struct lcra_state *l)
-{
-        float best_benefit = -1.0;
-        signed best_node = -1;
-
-        for (unsigned i = 0; i < l->node_count; ++i) {
-                /* Find spillable nodes */
-                if (l->class[i] != l->spill_class) continue;
-                if (l->spill_cost[i] < 0) continue;
-
-                /* Adapted from Chaitin's heuristic */
-                float constraints = lcra_count_constraints(l, i);
-                float cost = (l->spill_cost[i] + 1);
-                float benefit = constraints / cost;
-
-                if (benefit > best_benefit) {
-                        best_benefit = benefit;
-                        best_node = i;
-                }
-        }
-
-        return best_node;
-}
diff --git a/src/panfrost/midgard/lcra.h b/src/panfrost/midgard/lcra.h
deleted file mode 100644 (file)
index 68afc4a..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright (C) 2019 Collabora, Ltd.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- *
- * Authors (Collabora):
- *      Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
- */
-
-#ifndef __LCRA_H
-#define __LCRA_H
-
-#include <stdbool.h>
-#include <stdint.h>
-
-struct lcra_state {
-        unsigned node_count;
-
-        /* Word boundary where vectors can't cross */
-        unsigned bound;
-        
-        /* Alignment for node in log2(bytes)+1. Since alignment must be
-         * non-negative power-of-two, the elements are strictly positive
-         * integers. Zero is the sentinel for a missing node */
-        unsigned *alignment;
-
-        /* Linear constraints imposed. Nested array sized upfront, organized as
-         * linear[node_left][node_right]. That is, calculate indices as:
-         *
-         * Each element is itself a bit field denoting whether (c_j - c_i) bias
-         * is present or not, including negative biases.
-         *
-         * Note for Midgard, there are 16 components so the bias is in range
-         * [-15, 15] so encoded by 32-bit field. */
-
-        uint32_t *linear;
-
-        /* Per node max modulus constraints */
-        uint8_t *modulus;
-
-        /* Classes allow nodes to be partitioned with a starting register.
-         * Classes cannot interfere; that is, they are true partitions in the
-         * usual sense of the word. class_count is the number of classes.
-         * class[] is indexed by a node to get the mapped class. class_start is
-         * biased to all solutions in the class. */
-
-        unsigned class_count;
-        unsigned *class;
-        unsigned *class_start;
-        unsigned *class_size;
-        bool *class_disjoint;
-
-        /* Before solving, forced registers; after solving, solutions. */
-        unsigned *solutions;
-
-        /* For register spilling, the costs to spill nodes (as set by the user)
-         * are in spill_cost[], negative if a node is unspillable. Internally,
-         * spill_class specifies which class to spill (whichever class failed
-         * to allocate) */
-
-        signed *spill_cost;
-        unsigned spill_class;
-};
-
-struct lcra_state *
-lcra_alloc_equations(
-                unsigned node_count,
-                unsigned min_alignment, unsigned max_alignment,
-                unsigned bound, unsigned class_count);
-
-void
-lcra_free(struct lcra_state *l);
-
-void
-lcra_set_disjoint_class(struct lcra_state *l, unsigned c1, unsigned c2);
-
-void
-lcra_set_alignment(struct lcra_state *l, unsigned node, unsigned align_log2);
-
-void
-lcra_restrict_range(struct lcra_state *l, unsigned node, unsigned len);
-
-void
-lcra_add_node_interference(struct lcra_state *l, unsigned i, unsigned cmask_i, unsigned j, unsigned cmask_j);
-
-bool
-lcra_solve(struct lcra_state *l);
-
-void
-lcra_set_node_spill_cost(struct lcra_state *l, unsigned node, signed cost);
-
-signed
-lcra_get_best_spill_node(struct lcra_state *l);
-
-#endif
index ba69b3fe55a2b334ed15bd026a04ddcee3bdae02..8b93b4fa128ee2f48381dd81db055fee972ddbb5 100644 (file)
@@ -41,7 +41,6 @@ libpanfrost_midgard_files = files(
   'midgard_errata_lod.c',
   'nir_undef_to_zero.c',
   'disassemble.c',
-  'lcra.c'
 )
 
 midgard_nir_algebraic_c = custom_target(
index ae6d0efc6d2ad4ff62c113b886a3b35531c18831..48122c4967a3bb9c31c9e513c99e4f60a25778d4 100644 (file)
@@ -26,7 +26,6 @@
 #include "midgard_ops.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
-#include "lcra.h"
 #include "midgard_quirks.h"
 
 struct phys_reg {
diff --git a/src/panfrost/util/lcra.c b/src/panfrost/util/lcra.c
new file mode 100644 (file)
index 0000000..28f9a73
--- /dev/null
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2019 Collabora, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors (Collabora):
+ *      Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
+ */
+
+#include <stdio.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include "util/macros.h"
+#include "util/u_math.h"
+#include "lcra.h"
+
+/* This module is the reference implementation of "Linearly Constrained
+ * Register Allocation". The paper is available in PDF form
+ * (https://people.collabora.com/~alyssa/LCRA.pdf) as well as Markdown+LaTeX
+ * (https://gitlab.freedesktop.org/alyssa/lcra/blob/master/LCRA.md)
+ */
+
+struct lcra_state *
+lcra_alloc_equations(
+                unsigned node_count,
+                unsigned min_alignment, unsigned max_alignment,
+                unsigned bound, unsigned class_count)
+{
+        struct lcra_state *l = calloc(1, sizeof(*l));
+
+        l->node_count = node_count;
+        l->class_count = class_count;
+        l->bound = bound;
+
+        l->alignment = calloc(sizeof(l->alignment[0]), node_count);
+        l->linear = calloc(sizeof(l->linear[0]), node_count * node_count);
+        l->modulus = calloc(sizeof(l->modulus[0]), node_count);
+        l->class = calloc(sizeof(l->class[0]), node_count);
+        l->class_start = calloc(sizeof(l->class_start[0]), class_count);
+        l->class_disjoint = calloc(sizeof(l->class_disjoint[0]), class_count * class_count);
+        l->class_size = calloc(sizeof(l->class_size[0]), class_count);
+        l->spill_cost = calloc(sizeof(l->spill_cost[0]), node_count);
+        l->solutions = calloc(sizeof(l->solutions[0]), node_count);
+
+        memset(l->solutions, ~0, sizeof(l->solutions[0]) * node_count);
+
+        return l;
+}
+
+void
+lcra_free(struct lcra_state *l)
+{
+        if (!l)
+                return;
+
+        free(l->alignment);
+        free(l->linear);
+        free(l->modulus);
+        free(l->class);
+        free(l->class_start);
+        free(l->class_disjoint);
+        free(l->class_size);
+        free(l->spill_cost);
+        free(l->solutions);
+
+        free(l);
+}
+
+void
+lcra_set_alignment(struct lcra_state *l, unsigned node, unsigned align_log2)
+{
+        l->alignment[node] = align_log2 + 1;
+}
+
+void
+lcra_set_disjoint_class(struct lcra_state *l, unsigned c1, unsigned c2)
+{
+        l->class_disjoint[(c1 * l->class_count) + c2] = true;
+        l->class_disjoint[(c2 * l->class_count) + c1] = true;
+}
+
+void
+lcra_restrict_range(struct lcra_state *l, unsigned node, unsigned len)
+{
+        if (node < l->node_count && l->alignment[node])
+                l->modulus[node] = DIV_ROUND_UP(l->bound - len + 1, 1 << (l->alignment[node] - 1));
+}
+
+void
+lcra_add_node_interference(struct lcra_state *l, unsigned i, unsigned cmask_i, unsigned j, unsigned cmask_j)
+{
+        if (i == j)
+                return;
+
+        if (l->class_disjoint[(l->class[i] * l->class_count) + l->class[j]])
+                return;
+
+        uint32_t constraint_fw = 0;
+        uint32_t constraint_bw = 0;
+
+        for (unsigned D = 0; D < 16; ++D) {
+                if (cmask_i & (cmask_j << D)) {
+                        constraint_bw |= (1 << (15 + D));
+                        constraint_fw |= (1 << (15 - D));
+                }
+
+                if (cmask_i & (cmask_j >> D)) {
+                        constraint_fw |= (1 << (15 + D));
+                        constraint_bw |= (1 << (15 - D));
+                }
+        }
+
+        l->linear[j * l->node_count + i] |= constraint_fw;
+        l->linear[i * l->node_count + j] |= constraint_bw;
+}
+
+static bool
+lcra_test_linear(struct lcra_state *l, unsigned *solutions, unsigned i)
+{
+        unsigned *row = &l->linear[i * l->node_count];
+        signed constant = solutions[i];
+
+        for (unsigned j = 0; j < l->node_count; ++j) {
+                if (solutions[j] == ~0) continue;
+
+                signed lhs = solutions[j] - constant;
+
+                if (lhs < -15 || lhs > 15)
+                        continue;
+
+                if (row[j] & (1 << (lhs + 15)))
+                        return false;
+        }
+
+        return true;
+}
+
+bool
+lcra_solve(struct lcra_state *l)
+{
+        for (unsigned step = 0; step < l->node_count; ++step) {
+                if (l->solutions[step] != ~0) continue;
+                if (l->alignment[step] == 0) continue;
+
+                unsigned _class = l->class[step];
+                unsigned class_start = l->class_start[_class];
+
+                unsigned shift = l->alignment[step] - 1;
+
+                unsigned P = l->bound >> shift;
+                unsigned Q = l->modulus[step];
+                unsigned r_max = l->class_size[_class];
+                unsigned k_max = r_max >> shift;
+                unsigned m_max = k_max / P;
+                bool succ = false;
+
+                for (unsigned m = 0; m < m_max; ++m) {
+                        for (unsigned n = 0; n < Q; ++n) {
+                                l->solutions[step] = ((m * P + n) << shift) + class_start;
+                                succ = lcra_test_linear(l, l->solutions, step);
+
+                                if (succ) break;
+                        }
+
+                        if (succ) break;
+                }
+
+                /* Out of registers - prepare to spill */
+                if (!succ) {
+                        l->spill_class = l->class[step];
+                        return false;
+                }
+        }
+
+        return true;
+}
+
+/* Register spilling is implemented with a cost-benefit system. Costs are set
+ * by the user. Benefits are calculated from the constraints. */
+
+void
+lcra_set_node_spill_cost(struct lcra_state *l, unsigned node, signed cost)
+{
+        if (node < l->node_count)
+                l->spill_cost[node] = cost;
+}
+
+/* Count along the lower triangle */
+
+static unsigned
+lcra_count_constraints(struct lcra_state *l, unsigned i)
+{
+        unsigned count = 0;
+        unsigned *constraints = &l->linear[i * l->node_count];
+
+        for (unsigned j = 0; j < i; ++j)
+                count += util_bitcount(constraints[j]);
+
+        return count;
+}
+
+signed
+lcra_get_best_spill_node(struct lcra_state *l)
+{
+        float best_benefit = -1.0;
+        signed best_node = -1;
+
+        for (unsigned i = 0; i < l->node_count; ++i) {
+                /* Find spillable nodes */
+                if (l->class[i] != l->spill_class) continue;
+                if (l->spill_cost[i] < 0) continue;
+
+                /* Adapted from Chaitin's heuristic */
+                float constraints = lcra_count_constraints(l, i);
+                float cost = (l->spill_cost[i] + 1);
+                float benefit = constraints / cost;
+
+                if (benefit > best_benefit) {
+                        best_benefit = benefit;
+                        best_node = i;
+                }
+        }
+
+        return best_node;
+}
diff --git a/src/panfrost/util/lcra.h b/src/panfrost/util/lcra.h
new file mode 100644 (file)
index 0000000..68afc4a
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2019 Collabora, Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors (Collabora):
+ *      Alyssa Rosenzweig <alyssa.rosenzweig@collabora.com>
+ */
+
+#ifndef __LCRA_H
+#define __LCRA_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+struct lcra_state {
+        unsigned node_count;
+
+        /* Word boundary where vectors can't cross */
+        unsigned bound;
+        
+        /* Alignment for node in log2(bytes)+1. Since alignment must be
+         * non-negative power-of-two, the elements are strictly positive
+         * integers. Zero is the sentinel for a missing node */
+        unsigned *alignment;
+
+        /* Linear constraints imposed. Nested array sized upfront, organized as
+         * linear[node_left][node_right]. That is, calculate indices as:
+         *
+         * Each element is itself a bit field denoting whether (c_j - c_i) bias
+         * is present or not, including negative biases.
+         *
+         * Note for Midgard, there are 16 components so the bias is in range
+         * [-15, 15] so encoded by 32-bit field. */
+
+        uint32_t *linear;
+
+        /* Per node max modulus constraints */
+        uint8_t *modulus;
+
+        /* Classes allow nodes to be partitioned with a starting register.
+         * Classes cannot interfere; that is, they are true partitions in the
+         * usual sense of the word. class_count is the number of classes.
+         * class[] is indexed by a node to get the mapped class. class_start is
+         * biased to all solutions in the class. */
+
+        unsigned class_count;
+        unsigned *class;
+        unsigned *class_start;
+        unsigned *class_size;
+        bool *class_disjoint;
+
+        /* Before solving, forced registers; after solving, solutions. */
+        unsigned *solutions;
+
+        /* For register spilling, the costs to spill nodes (as set by the user)
+         * are in spill_cost[], negative if a node is unspillable. Internally,
+         * spill_class specifies which class to spill (whichever class failed
+         * to allocate) */
+
+        signed *spill_cost;
+        unsigned spill_class;
+};
+
+struct lcra_state *
+lcra_alloc_equations(
+                unsigned node_count,
+                unsigned min_alignment, unsigned max_alignment,
+                unsigned bound, unsigned class_count);
+
+void
+lcra_free(struct lcra_state *l);
+
+void
+lcra_set_disjoint_class(struct lcra_state *l, unsigned c1, unsigned c2);
+
+void
+lcra_set_alignment(struct lcra_state *l, unsigned node, unsigned align_log2);
+
+void
+lcra_restrict_range(struct lcra_state *l, unsigned node, unsigned len);
+
+void
+lcra_add_node_interference(struct lcra_state *l, unsigned i, unsigned cmask_i, unsigned j, unsigned cmask_j);
+
+bool
+lcra_solve(struct lcra_state *l);
+
+void
+lcra_set_node_spill_cost(struct lcra_state *l, unsigned node, signed cost);
+
+signed
+lcra_get_best_spill_node(struct lcra_state *l);
+
+#endif
index 76e2249b60e51a5d14337a36f1d337ad188a8774..a39ad5130bbb5da15bfb3e95e3ef8c77f928101f 100644 (file)
@@ -20,6 +20,8 @@
 # SOFTWARE.
 
 libpanfrost_util_files = files(
+  'lcra.c',
+  'lcra.h',
   'pan_ir.c',
   'pan_ir.h',
   'pan_liveness.c',