2010-09-27 20:34:33 +01:00
|
|
|
/*
|
|
|
|
* Copyright © 2010 Intel Corporation
|
|
|
|
*
|
|
|
|
* 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:
|
|
|
|
* Eric Anholt <eric@anholt.net>
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2017-03-20 16:04:40 +00:00
|
|
|
#ifndef REGISTER_ALLOCATE_H
|
|
|
|
#define REGISTER_ALLOCATE_H
|
2014-03-18 17:55:50 +00:00
|
|
|
|
2017-03-20 16:04:40 +00:00
|
|
|
#include <stdbool.h>
|
2015-10-23 22:12:27 +01:00
|
|
|
#include "util/bitset.h"
|
2015-03-05 00:37:29 +00:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
extern "C" {
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2010-09-27 20:34:33 +01:00
|
|
|
struct ra_class;
|
|
|
|
struct ra_regs;
|
|
|
|
|
2019-09-18 20:57:11 +01:00
|
|
|
struct blob;
|
|
|
|
struct blob_reader;
|
|
|
|
|
2010-09-27 20:34:33 +01:00
|
|
|
/* @{
|
|
|
|
* Register set setup.
|
|
|
|
*
|
|
|
|
* This should be done once at backend initializaion, as
|
|
|
|
* ra_set_finalize is O(r^2*c^2). The registers may be virtual
|
|
|
|
* registers, such as aligned register pairs that conflict with the
|
|
|
|
* two real registers from which they are composed.
|
|
|
|
*/
|
2015-08-15 17:58:32 +01:00
|
|
|
struct ra_regs *ra_alloc_reg_set(void *mem_ctx, unsigned int count,
|
|
|
|
bool need_conflict_lists);
|
2012-12-01 00:34:09 +00:00
|
|
|
void ra_set_allocate_round_robin(struct ra_regs *regs);
|
2021-03-04 23:14:15 +00:00
|
|
|
struct ra_class *ra_alloc_reg_class(struct ra_regs *regs);
|
ra: Add fast-path support for register classes of contiguous regs.
In the fully general case of register classes, to expose an allocation
class of unaligned 2-contiguous-regs allocations, for example, you'd have
your base individual regs (128 on intel), and another set of 127 regs that
each conflicted with the corresponding pair of the base regs. Single-reg
nodes would allocate in the 128, and double-reg nodes would allocate in
the 127 and the user would remap from the 127 down to the base regs with
some irritating table.
If you need many different contiguous allocation sizes (16 is a pretty
common number across drivers), your number of regs explodes, wasting
memory and making the q computation expensive at startup.
If all the user has is contiguous-reg classes, we can easily compute the q
value up front (as found in the intel driver and nouveau, for example),
and we only have to change a couple of places in the conflict-checking
logic so the contiguous-reg classes can use the base registers.
Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9437>
2021-03-04 21:51:36 +00:00
|
|
|
struct ra_class *ra_alloc_contig_reg_class(struct ra_regs *regs, int contig_len);
|
2021-03-04 23:14:15 +00:00
|
|
|
unsigned int ra_class_index(struct ra_class *c);
|
2010-09-27 20:34:33 +01:00
|
|
|
void ra_add_reg_conflict(struct ra_regs *regs,
|
2019-05-09 15:46:41 +01:00
|
|
|
unsigned int r1, unsigned int r2);
|
2011-05-04 21:27:33 +01:00
|
|
|
void ra_add_transitive_reg_conflict(struct ra_regs *regs,
|
2019-05-09 15:46:41 +01:00
|
|
|
unsigned int base_reg, unsigned int reg);
|
2020-01-09 17:37:35 +00:00
|
|
|
|
|
|
|
void
|
|
|
|
ra_add_transitive_reg_pair_conflict(struct ra_regs *regs,
|
|
|
|
unsigned int base_reg, unsigned int reg0, unsigned int reg1);
|
|
|
|
|
2015-08-15 17:43:05 +01:00
|
|
|
void ra_make_reg_conflicts_transitive(struct ra_regs *regs, unsigned int reg);
|
2021-03-04 23:14:15 +00:00
|
|
|
void ra_class_add_reg(struct ra_class *c, unsigned int reg);
|
|
|
|
struct ra_class *ra_get_class_from_index(struct ra_regs *regs, unsigned int c);
|
2012-09-03 15:43:45 +01:00
|
|
|
void ra_set_num_conflicts(struct ra_regs *regs, unsigned int class_a,
|
|
|
|
unsigned int class_b, unsigned int num_conflicts);
|
|
|
|
void ra_set_finalize(struct ra_regs *regs, unsigned int **conflicts);
|
2019-09-18 20:57:11 +01:00
|
|
|
|
|
|
|
void ra_set_serialize(const struct ra_regs *regs, struct blob *blob);
|
|
|
|
struct ra_regs *ra_set_deserialize(void *mem_ctx, struct blob_reader *blob);
|
2010-09-27 20:34:33 +01:00
|
|
|
/** @} */
|
|
|
|
|
|
|
|
/** @{ Interference graph setup.
|
|
|
|
*
|
|
|
|
* Each interference graph node is a virtual variable in the IL. It
|
|
|
|
* is up to the user to ra_set_node_class() for the virtual variable,
|
|
|
|
* and compute live ranges and ra_node_interfere() between conflicting
|
2014-09-06 01:59:31 +01:00
|
|
|
* live ranges. Note that an interference *must not* be added between
|
|
|
|
* two nodes if their classes haven't been assigned yet. The user
|
|
|
|
* should set the class of each node before building the interference
|
|
|
|
* graph.
|
2010-09-27 20:34:33 +01:00
|
|
|
*/
|
|
|
|
struct ra_graph *ra_alloc_interference_graph(struct ra_regs *regs,
|
2019-05-09 15:46:41 +01:00
|
|
|
unsigned int count);
|
2019-05-10 00:53:04 +01:00
|
|
|
void ra_resize_interference_graph(struct ra_graph *g, unsigned int count);
|
2021-03-04 23:14:15 +00:00
|
|
|
void ra_set_node_class(struct ra_graph *g, unsigned int n, struct ra_class *c);
|
|
|
|
struct ra_class *ra_get_node_class(struct ra_graph *g, unsigned int n);
|
|
|
|
unsigned int ra_add_node(struct ra_graph *g, struct ra_class *c);
|
2020-02-28 18:06:54 +00:00
|
|
|
|
|
|
|
/** @{ Register selection callback.
|
|
|
|
*
|
|
|
|
* The register allocator can use either one of two built-in register
|
|
|
|
* selection behaviors (ie. lowest-available or round-robin), or the
|
|
|
|
* user can implement it's own selection policy by setting an register
|
|
|
|
* selection callback. The parameters to the callback are:
|
|
|
|
*
|
|
|
|
* - n the graph node, ie. the virtual variable to select a
|
|
|
|
* register for
|
|
|
|
* - regs bitset of available registers to choose; this bitset
|
|
|
|
* contains *all* registers, but registers of different
|
|
|
|
* classes will not have their corresponding bit set.
|
|
|
|
* - data callback data specified in ra_set_select_reg_callback()
|
|
|
|
*/
|
|
|
|
typedef unsigned int (*ra_select_reg_callback)(
|
|
|
|
unsigned int n, /* virtual variable to choose a physical reg for */
|
|
|
|
BITSET_WORD *regs, /* available physical regs to choose from */
|
|
|
|
void *data);
|
|
|
|
|
2015-10-23 22:12:27 +01:00
|
|
|
void ra_set_select_reg_callback(struct ra_graph *g,
|
2020-02-28 18:06:54 +00:00
|
|
|
ra_select_reg_callback callback,
|
2015-10-23 22:12:27 +01:00
|
|
|
void *data);
|
2010-09-27 20:34:33 +01:00
|
|
|
void ra_add_node_interference(struct ra_graph *g,
|
2019-05-09 15:46:41 +01:00
|
|
|
unsigned int n1, unsigned int n2);
|
2019-05-07 23:16:58 +01:00
|
|
|
void ra_reset_node_interference(struct ra_graph *g, unsigned int n);
|
2010-09-27 20:34:33 +01:00
|
|
|
/** @} */
|
|
|
|
|
|
|
|
/** @{ Graph-coloring register allocation */
|
2014-08-01 02:57:20 +01:00
|
|
|
bool ra_allocate(struct ra_graph *g);
|
2010-09-27 20:34:33 +01:00
|
|
|
|
2020-03-09 21:20:50 +00:00
|
|
|
#define NO_REG ~0U
|
|
|
|
/**
|
|
|
|
* Returns NO_REG for a node that has not (yet) been assigned.
|
|
|
|
*/
|
2010-09-27 20:34:33 +01:00
|
|
|
unsigned int ra_get_node_reg(struct ra_graph *g, unsigned int n);
|
2011-03-27 06:56:08 +01:00
|
|
|
void ra_set_node_reg(struct ra_graph * g, unsigned int n, unsigned int reg);
|
2010-10-19 17:25:51 +01:00
|
|
|
void ra_set_node_spill_cost(struct ra_graph *g, unsigned int n, float cost);
|
|
|
|
int ra_get_best_spill_node(struct ra_graph *g);
|
2010-09-27 20:34:33 +01:00
|
|
|
/** @} */
|
|
|
|
|
2015-03-05 00:37:29 +00:00
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
} // extern "C"
|
|
|
|
#endif
|
2017-03-20 16:04:40 +00:00
|
|
|
|
|
|
|
#endif /* REGISTER_ALLOCATE_H */
|