pco: add virtual register support
Signed-off-by: Simon Perretta <simon.perretta@imgtec.com> Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36412>
This commit is contained in:
committed by
Marge Bot
parent
d5e464ffc7
commit
2db53101c1
@@ -264,6 +264,8 @@ ForEachMacros: [
|
||||
'pco_foreach_instr_dest_from',
|
||||
'pco_foreach_instr_dest_ssa',
|
||||
'pco_foreach_instr_dest_ssa_from',
|
||||
'pco_foreach_instr_dest_vreg',
|
||||
'pco_foreach_instr_dest_vreg_ssa',
|
||||
'pco_foreach_instr_in_block',
|
||||
'pco_foreach_instr_in_block_from',
|
||||
'pco_foreach_instr_in_block_from_rev',
|
||||
@@ -282,6 +284,8 @@ ForEachMacros: [
|
||||
'pco_foreach_instr_src_from',
|
||||
'pco_foreach_instr_src_ssa',
|
||||
'pco_foreach_instr_src_ssa_from',
|
||||
'pco_foreach_instr_src_vreg',
|
||||
'pco_foreach_instr_src_vreg_ssa',
|
||||
'pco_foreach_loop_in_func',
|
||||
'pco_foreach_loop_in_func_from',
|
||||
'pco_foreach_loop_in_func_from_rev',
|
||||
|
||||
@@ -340,6 +340,7 @@ typedef struct _pco_func {
|
||||
struct hash_table_u64 *vec_infos;
|
||||
|
||||
unsigned next_ssa; /** Next SSA node index. */
|
||||
unsigned next_vreg; /** Next virtual register index. */
|
||||
unsigned next_instr; /** Next instruction index. */
|
||||
unsigned next_igrp; /** Next igrp index. */
|
||||
unsigned next_block; /** Next block index. */
|
||||
@@ -638,6 +639,14 @@ PCO_DEFINE_CAST(pco_cf_node_as_func,
|
||||
pco_foreach_instr_dest_from (pdest, instr, pdest_from) \
|
||||
if (pco_ref_is_ssa(*pdest))
|
||||
|
||||
#define pco_foreach_instr_dest_vreg(pdest, instr) \
|
||||
pco_foreach_instr_dest (pdest, instr) \
|
||||
if (pco_ref_is_vreg(*pdest))
|
||||
|
||||
#define pco_foreach_instr_dest_vreg_ssa(pdest, instr) \
|
||||
pco_foreach_instr_dest (pdest, instr) \
|
||||
if (pco_ref_is_vreg(*pdest) || pco_ref_is_ssa(*pdest))
|
||||
|
||||
#define pco_foreach_instr_src(psrc, instr) \
|
||||
for (pco_ref *psrc = &instr->src[0]; psrc < &instr->src[instr->num_srcs]; \
|
||||
++psrc)
|
||||
@@ -654,6 +663,14 @@ PCO_DEFINE_CAST(pco_cf_node_as_func,
|
||||
pco_foreach_instr_src_from (psrc, instr, psrc_from) \
|
||||
if (pco_ref_is_ssa(*psrc))
|
||||
|
||||
#define pco_foreach_instr_src_vreg(psrc, instr) \
|
||||
pco_foreach_instr_src (psrc, instr) \
|
||||
if (pco_ref_is_vreg(*psrc))
|
||||
|
||||
#define pco_foreach_instr_src_vreg_ssa(psrc, instr) \
|
||||
pco_foreach_instr_src (psrc, instr) \
|
||||
if (pco_ref_is_vreg(*psrc) || pco_ref_is_ssa(*psrc))
|
||||
|
||||
#define pco_cf_node_head(list) exec_node_data_head(pco_cf_node, list, node)
|
||||
#define pco_cf_node_tail(list) exec_node_data_tail(pco_cf_node, list, node)
|
||||
#define pco_cf_node_next(cf_node) \
|
||||
@@ -1574,6 +1591,17 @@ static inline bool pco_ref_is_ssa(pco_ref ref)
|
||||
return ref.type == PCO_REF_TYPE_SSA;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns whether a reference is a virtual register.
|
||||
*
|
||||
* \param[in] ref PCO reference.
|
||||
* \return True if the reference is a virtual register.
|
||||
*/
|
||||
static inline bool pco_ref_is_vreg(pco_ref ref)
|
||||
{
|
||||
return ref.type == PCO_REF_TYPE_REG && ref.reg_class == PCO_REG_CLASS_VIRT;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns whether a reference is a register.
|
||||
*
|
||||
@@ -2012,6 +2040,17 @@ static inline pco_ref pco_ref_vreg(unsigned index)
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Builds and returns a new virtual register.
|
||||
*
|
||||
* \param[in,out] func The function.
|
||||
* \return Virtual register reference.
|
||||
*/
|
||||
static inline pco_ref pco_ref_new_vreg(pco_func *func)
|
||||
{
|
||||
return pco_ref_vreg(func->next_vreg++);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Builds and returns a scalar hardware register reference.
|
||||
*
|
||||
|
||||
@@ -79,23 +79,32 @@ static bool pco_ra_func(pco_func *func,
|
||||
* TODO: track successors/predecessors.
|
||||
*/
|
||||
|
||||
unsigned num_ssas = func->next_ssa;
|
||||
unsigned num_vregs = func->next_vreg;
|
||||
unsigned num_vars = num_ssas + num_vregs;
|
||||
|
||||
/* Collect used bit sizes. */
|
||||
uint8_t ssa_bits = 0;
|
||||
uint8_t used_bits = 0;
|
||||
pco_foreach_instr_in_func (instr, func) {
|
||||
pco_foreach_instr_dest_ssa (pdest, instr) {
|
||||
ssa_bits |= (1 << pdest->bits);
|
||||
used_bits |= (1 << pdest->bits);
|
||||
}
|
||||
}
|
||||
|
||||
/* vregs are always 32x1. */
|
||||
if (num_vregs > 0) {
|
||||
used_bits |= (1 << PCO_BITS_32);
|
||||
}
|
||||
|
||||
/* No registers to allocate. */
|
||||
if (!ssa_bits)
|
||||
if (!used_bits)
|
||||
return false;
|
||||
|
||||
/* 64-bit SSA should've been lowered by now. */
|
||||
assert(!(ssa_bits & (1 << PCO_BITS_64)));
|
||||
/* 64-bit vars should've been lowered by now. */
|
||||
assert(!(used_bits & (1 << PCO_BITS_64)));
|
||||
|
||||
/* TODO: support multiple bit sizes. */
|
||||
bool only_32bit = ssa_bits == (1 << PCO_BITS_32);
|
||||
bool only_32bit = used_bits == (1 << PCO_BITS_32);
|
||||
assert(only_32bit);
|
||||
|
||||
struct ra_regs *ra_regs =
|
||||
@@ -181,6 +190,14 @@ static bool pco_ra_func(pco_func *func,
|
||||
}
|
||||
}
|
||||
|
||||
/* vregs are always 32x1. */
|
||||
if (num_vregs > 0) {
|
||||
if (!_mesa_hash_table_u64_search(ra_classes, 1)) {
|
||||
struct ra_class *ra_class = ra_alloc_contig_reg_class(ra_regs, 1);
|
||||
_mesa_hash_table_u64_insert(ra_classes, 1, ra_class);
|
||||
}
|
||||
}
|
||||
|
||||
/* Assign registers to classes. */
|
||||
hash_table_u64_foreach (ra_classes, entry) {
|
||||
const unsigned stride = entry.key;
|
||||
@@ -192,15 +209,14 @@ static bool pco_ra_func(pco_func *func,
|
||||
|
||||
ra_set_finalize(ra_regs, NULL);
|
||||
|
||||
struct ra_graph *ra_graph =
|
||||
ra_alloc_interference_graph(ra_regs, func->next_ssa);
|
||||
struct ra_graph *ra_graph = ra_alloc_interference_graph(ra_regs, num_vars);
|
||||
ralloc_steal(ra_regs, ra_graph);
|
||||
|
||||
/* Allocate and calculate live ranges. */
|
||||
struct live_range *live_ranges =
|
||||
rzalloc_array_size(ra_regs, sizeof(*live_ranges), func->next_ssa);
|
||||
rzalloc_array_size(ra_regs, sizeof(*live_ranges), num_vars);
|
||||
|
||||
for (unsigned u = 0; u < func->next_ssa; ++u)
|
||||
for (unsigned u = 0; u < num_vars; ++u)
|
||||
live_ranges[u].start = ~0U;
|
||||
|
||||
pco_foreach_instr_in_func (instr, func) {
|
||||
@@ -238,16 +254,44 @@ static bool pco_ra_func(pco_func *func,
|
||||
live_ranges[src.val].end =
|
||||
MAX2(live_ranges[src.val].end, instr->index);
|
||||
}
|
||||
|
||||
pco_foreach_instr_dest_vreg (pdest, instr) {
|
||||
pco_ref dest = *pdest;
|
||||
|
||||
/* Place vregs after ssa vars. */
|
||||
dest.val += num_ssas;
|
||||
|
||||
live_ranges[dest.val].start =
|
||||
MIN2(live_ranges[dest.val].start, instr->index);
|
||||
|
||||
/* Set class if it hasn't already been set up in an override. */
|
||||
unsigned chans = pco_ref_get_chans(dest);
|
||||
struct ra_class *ra_class =
|
||||
_mesa_hash_table_u64_search(ra_classes, chans);
|
||||
assert(ra_class);
|
||||
|
||||
ra_set_node_class(ra_graph, dest.val, ra_class);
|
||||
}
|
||||
|
||||
pco_foreach_instr_src_vreg (psrc, instr) {
|
||||
pco_ref src = *psrc;
|
||||
|
||||
/* Place vregs after ssa vars. */
|
||||
src.val += num_ssas;
|
||||
|
||||
live_ranges[src.val].end =
|
||||
MAX2(live_ranges[src.val].end, instr->index);
|
||||
}
|
||||
}
|
||||
|
||||
/* Build interference graph from overlapping live ranges. */
|
||||
for (unsigned ssa0 = 0; ssa0 < func->next_ssa; ++ssa0) {
|
||||
for (unsigned ssa1 = ssa0 + 1; ssa1 < func->next_ssa; ++ssa1) {
|
||||
for (unsigned var0 = 0; var0 < num_vars; ++var0) {
|
||||
for (unsigned var1 = var0 + 1; var1 < num_vars; ++var1) {
|
||||
/* If the live ranges overlap, the register nodes interfere. */
|
||||
if ((live_ranges[ssa0].start != ~0U && live_ranges[ssa1].end != ~0U) &&
|
||||
!(live_ranges[ssa0].start >= live_ranges[ssa1].end ||
|
||||
live_ranges[ssa1].start >= live_ranges[ssa0].end)) {
|
||||
ra_add_node_interference(ra_graph, ssa0, ssa1);
|
||||
if ((live_ranges[var0].start != ~0U && live_ranges[var1].end != ~0U) &&
|
||||
!(live_ranges[var0].start >= live_ranges[var1].end ||
|
||||
live_ranges[var1].start >= live_ranges[var0].end)) {
|
||||
ra_add_node_interference(ra_graph, var0, var1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -258,8 +302,12 @@ static bool pco_ra_func(pco_func *func,
|
||||
|
||||
if (PCO_DEBUG_PRINT(RA)) {
|
||||
printf("RA live ranges:\n");
|
||||
for (unsigned u = 0; u < func->next_ssa; ++u)
|
||||
printf(" %%%u: %u, %u\n", u, live_ranges[u].start, live_ranges[u].end);
|
||||
for (unsigned u = 0; u < num_vars; ++u)
|
||||
printf(" %c%u: %u, %u\n",
|
||||
u >= num_ssas ? '$' : '%',
|
||||
u >= num_ssas ? u - num_ssas : u,
|
||||
live_ranges[u].start,
|
||||
live_ranges[u].end);
|
||||
|
||||
if (_mesa_hash_table_u64_num_entries(overrides)) {
|
||||
printf("RA overrides:\n");
|
||||
@@ -273,7 +321,7 @@ static bool pco_ra_func(pco_func *func,
|
||||
}
|
||||
}
|
||||
|
||||
/* Replace SSA regs with allocated registers. */
|
||||
/* Replace vars with allocated registers. */
|
||||
unsigned temps = 0;
|
||||
unsigned vtxins = 0;
|
||||
unsigned interns = 0;
|
||||
@@ -360,6 +408,24 @@ static bool pco_ra_func(pco_func *func,
|
||||
psrc->reg_class = PCO_REG_CLASS_TEMP;
|
||||
psrc->val = val;
|
||||
}
|
||||
|
||||
pco_foreach_instr_dest_vreg (pdest, instr) {
|
||||
unsigned val = ra_get_node_reg(ra_graph, pdest->val + num_ssas);
|
||||
unsigned dest_temps = val + 1;
|
||||
|
||||
pdest->type = PCO_REF_TYPE_REG;
|
||||
pdest->reg_class = PCO_REG_CLASS_TEMP;
|
||||
pdest->val = val;
|
||||
temps = MAX2(temps, dest_temps);
|
||||
}
|
||||
|
||||
pco_foreach_instr_src_vreg (psrc, instr) {
|
||||
unsigned val = ra_get_node_reg(ra_graph, psrc->val + num_ssas);
|
||||
|
||||
psrc->type = PCO_REF_TYPE_REG;
|
||||
psrc->reg_class = PCO_REG_CLASS_TEMP;
|
||||
psrc->val = val;
|
||||
}
|
||||
}
|
||||
|
||||
ralloc_free(ra_regs);
|
||||
@@ -367,10 +433,13 @@ static bool pco_ra_func(pco_func *func,
|
||||
func->temps = temps;
|
||||
|
||||
if (PCO_DEBUG_PRINT(RA)) {
|
||||
printf("RA allocated %u temps, %u vtxins, %u interns.\n",
|
||||
temps,
|
||||
vtxins,
|
||||
interns);
|
||||
printf(
|
||||
"RA allocated %u temps, %u vtxins, %u interns from %u SSA vars, %u vregs.\n",
|
||||
temps,
|
||||
vtxins,
|
||||
interns,
|
||||
num_ssas,
|
||||
num_vregs);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user