ir3: allow liveness calculation for different register types

This allows us to only calculate the liveness for predicate registers
during predicate RA.

Signed-off-by: Job Noorman <jnoorman@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27411>
This commit is contained in:
Job Noorman 2024-02-01 14:51:19 +01:00 committed by Marge Bot
parent 49b2fbe2f0
commit f55a44d88b
4 changed files with 34 additions and 9 deletions

View File

@ -226,8 +226,10 @@ ForEachMacros:
- foreach_sched_node
- foreach_src
- foreach_src_n
- foreach_src_if
- foreach_dst
- foreach_dst_n
- foreach_dst_if
- ra_foreach_dst
- ra_foreach_src
- ra_foreach_src_rev

View File

@ -1731,6 +1731,10 @@ ir3_try_swap_signedness(opc_t opc, bool *can_swap)
/* iterator for an instructions's sources (reg): */
#define foreach_src(__srcreg, __instr) foreach_src_n (__srcreg, __i, __instr)
#define foreach_src_if(__srcreg, __instr, __filter) \
foreach_src (__srcreg, __instr) \
if (__filter(__srcreg))
/* iterator for an instructions's destinations (reg), also returns dst #: */
#define foreach_dst_n(__dstreg, __n, __instr) \
if ((__instr)->dsts_count) \
@ -1743,6 +1747,10 @@ ir3_try_swap_signedness(opc_t opc, bool *can_swap)
/* iterator for an instructions's destinations (reg): */
#define foreach_dst(__dstreg, __instr) foreach_dst_n (__dstreg, __i, __instr)
#define foreach_dst_if(__dstreg, __instr, __filter) \
foreach_dst (__dstreg, __instr) \
if (__filter(__dstreg))
static inline unsigned
__ssa_src_cnt(struct ir3_instruction *instr)
{

View File

@ -37,14 +37,15 @@
static bool
compute_block_liveness(struct ir3_liveness *live, struct ir3_block *block,
BITSET_WORD *tmp_live, unsigned bitset_words)
BITSET_WORD *tmp_live, unsigned bitset_words,
reg_filter_cb filter_src, reg_filter_cb filter_dst)
{
memcpy(tmp_live, live->live_out[block->index],
bitset_words * sizeof(BITSET_WORD));
/* Process instructions */
foreach_instr_rev (instr, &block->instr_list) {
ra_foreach_dst (dst, instr) {
foreach_dst_if (dst, instr, filter_dst) {
if (BITSET_TEST(tmp_live, dst->name))
dst->flags &= ~IR3_REG_UNUSED;
else
@ -54,18 +55,19 @@ compute_block_liveness(struct ir3_liveness *live, struct ir3_block *block,
/* Phi node uses occur after the predecessor block */
if (instr->opc != OPC_META_PHI) {
ra_foreach_src (src, instr) {
foreach_src_if (src, instr, filter_src) {
if (BITSET_TEST(tmp_live, src->def->name))
src->flags &= ~IR3_REG_KILL;
else
src->flags |= IR3_REG_KILL;
}
ra_foreach_src (src, instr) {
foreach_src_if (src, instr, filter_src) {
if (BITSET_TEST(tmp_live, src->def->name))
src->flags &= ~IR3_REG_FIRST_KILL;
else
src->flags |= IR3_REG_FIRST_KILL;
assert(src->def->name != 0);
BITSET_SET(tmp_live, src->def->name);
}
}
@ -89,6 +91,8 @@ compute_block_liveness(struct ir3_liveness *live, struct ir3_block *block,
break;
if (!phi->srcs[i]->def)
continue;
if (!filter_dst(phi->srcs[i]))
continue;
unsigned name = phi->srcs[i]->def->name;
if (!BITSET_TEST(live->live_out[pred->index], name)) {
progress = true;
@ -115,7 +119,8 @@ compute_block_liveness(struct ir3_liveness *live, struct ir3_block *block,
}
struct ir3_liveness *
ir3_calc_liveness(void *mem_ctx, struct ir3 *ir)
ir3_calc_liveness_for(void *mem_ctx, struct ir3 *ir, reg_filter_cb filter_src,
reg_filter_cb filter_dst)
{
struct ir3_liveness *live = rzalloc(mem_ctx, struct ir3_liveness);
@ -129,7 +134,7 @@ ir3_calc_liveness(void *mem_ctx, struct ir3 *ir)
foreach_block (block, &ir->block_list) {
block->index = block_count++;
foreach_instr (instr, &block->instr_list) {
ra_foreach_dst (dst, instr) {
foreach_dst_if (dst, instr, filter_dst) {
dst->name = live->definitions_count;
array_insert(live, live->definitions, dst);
}
@ -155,8 +160,8 @@ ir3_calc_liveness(void *mem_ctx, struct ir3 *ir)
while (progress) {
progress = false;
foreach_block_rev (block, &ir->block_list) {
progress |=
compute_block_liveness(live, block, tmp_live, bitset_words);
progress |= compute_block_liveness(live, block, tmp_live, bitset_words,
filter_src, filter_dst);
}
}

View File

@ -143,7 +143,17 @@ struct ir3_liveness {
DECLARE_ARRAY(BITSET_WORD *, live_in);
};
struct ir3_liveness *ir3_calc_liveness(void *mem_ctx, struct ir3 *ir);
typedef bool (*reg_filter_cb)(const struct ir3_register *);
struct ir3_liveness *ir3_calc_liveness_for(void *mem_ctx, struct ir3 *ir,
reg_filter_cb filter_src,
reg_filter_cb filter_dst);
static inline struct ir3_liveness *
ir3_calc_liveness(void *mem_ctx, struct ir3 *ir)
{
return ir3_calc_liveness_for(mem_ctx, ir, ra_reg_is_src, ra_reg_is_dst);
}
bool ir3_def_live_after(struct ir3_liveness *live, struct ir3_register *def,
struct ir3_instruction *instr);