agx: Switch to dynamic allocation of srcs/dests

So we can handle parallel copies later.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18804>
This commit is contained in:
Alyssa Rosenzweig
2022-09-22 22:35:43 -04:00
committed by Marge Bot
parent 544c60a132
commit 7c9fba34bc
6 changed files with 59 additions and 52 deletions

View File

@@ -27,10 +27,19 @@ template = """/*
#include "agx_compiler.h"
static inline agx_instr *
agx_alloc_instr(agx_builder *b, enum agx_opcode op)
agx_alloc_instr(agx_builder *b, enum agx_opcode op, uint8_t nr_dests, uint8_t nr_srcs)
{
agx_instr *I = rzalloc(b->shader, agx_instr);
size_t size = sizeof(agx_instr);
size += sizeof(agx_index) * nr_dests;
size += sizeof(agx_index) * nr_srcs;
agx_instr *I = (agx_instr *) rzalloc_size(b->shader, size);
I->dest = (agx_index *) (I + 1);
I->src = I->dest + nr_dests;
I->op = op;
I->nr_dests = nr_dests;
I->nr_srcs = nr_srcs;
return I;
}
@@ -41,11 +50,17 @@ agx_alloc_instr(agx_builder *b, enum agx_opcode op)
srcs = op.srcs
imms = op.imms
suffix = "_to" if dests > 0 else ""
nr_dests = "nr_dests" if op.variable_dests else str(dests)
nr_srcs = "nr_srcs" if op.variable_srcs else str(srcs)
%>
static inline agx_instr *
agx_${opcode}${suffix}(agx_builder *b
% if op.variable_dests:
, unsigned nr_dests
% endif
% for dest in range(dests):
, agx_index dst${dest}
% endfor
@@ -63,23 +78,15 @@ agx_${opcode}${suffix}(agx_builder *b
% endfor
) {
agx_instr *I = agx_alloc_instr(b, AGX_OPCODE_${opcode.upper()});
agx_instr *I = agx_alloc_instr(b, AGX_OPCODE_${opcode.upper()}, ${nr_dests}, ${nr_srcs});
% for dest in range(dests):
I->dest[${dest}] = dst${dest};
% endfor
% if op.variable_srcs:
I->src = ralloc_array(I, agx_index, nr_srcs);
I->nr_srcs = nr_srcs;
% elif srcs > 0:
I->src = ralloc_array(I, agx_index, ${srcs});
I->nr_srcs = ${srcs};
% for src in range(srcs):
I->src[${src}] = src${src};
% endfor
% endif
% for imm in imms:
I->${imm.name} = ${imm.name};
@@ -89,7 +96,7 @@ agx_${opcode}${suffix}(agx_builder *b
return I;
}
% if dests == 1 and not op.variable_srcs:
% if dests == 1 and not op.variable_srcs and not op.variable_dests:
static inline agx_index
agx_${opcode}(agx_builder *b

View File

@@ -1207,7 +1207,8 @@ agx_emit_jump(agx_builder *b, nir_jump_instr *instr)
static void
agx_emit_phi(agx_builder *b, nir_phi_instr *instr)
{
agx_instr *I = agx_phi_to(b, agx_dest_index(&instr->dest));
agx_instr *I = agx_phi_to(b, agx_dest_index(&instr->dest),
exec_list_length(&instr->srcs));
/* Deferred */
I->phi = instr;
@@ -1230,9 +1231,6 @@ agx_emit_phi_deferred(agx_context *ctx, agx_block *block, agx_instr *I)
/* Guaranteed by lower_phis_to_scalar */
assert(phi->dest.ssa.num_components == 1);
I->nr_srcs = exec_list_length(&phi->srcs);
I->src = rzalloc_array(I, agx_index, I->nr_srcs);
nir_foreach_phi_src(src, phi) {
agx_block *pred = agx_from_nir_block(ctx, src->pred);
unsigned i = agx_predecessor_index(block, pred);

View File

@@ -288,12 +288,13 @@ typedef struct {
nir_phi_instr *phi;
};
/* Data flow */
agx_index *dest;
enum agx_opcode op;
/* Data flow */
agx_index dest[AGX_MAX_DESTS];
unsigned nr_srcs;
uint8_t nr_dests;
uint8_t nr_srcs;
union {
uint32_t imm;
@@ -534,7 +535,7 @@ agx_vec_for_intr(agx_context *ctx, nir_intrinsic_instr *instr)
for (unsigned v = 0; v < ins->nr_srcs; ++v)
#define agx_foreach_dest(ins, v) \
for (unsigned v = 0; v < ARRAY_SIZE(ins->dest); ++v)
for (unsigned v = 0; v < ins->nr_dests; ++v)
/* Phis only come at the start so we stop as soon as we hit a non-phi */
#define agx_foreach_phi_in_block(block, v) \

View File

@@ -25,40 +25,38 @@
#include "agx_builder.h"
/* Lower pseudo instructions created during optimization. */
static void
agx_lower_to_unary_bitop(agx_instr *I, enum agx_bitop_table table)
static agx_instr *
lower(agx_builder *b, agx_instr *I)
{
I->op = AGX_OPCODE_BITOP;
I->truth_table = table;
switch (I->op) {
/* Allocate extra source */
I->src = reralloc_array_size(I, I->src, sizeof(agx_index), I->nr_srcs++);
I->src[1] = agx_zero();
/* Various instructions are implemented as bitwise truth tables */
case AGX_OPCODE_MOV:
return agx_bitop_to(b, I->dest[0], I->src[0], agx_zero(), AGX_BITOP_MOV);
case AGX_OPCODE_NOT:
return agx_bitop_to(b, I->dest[0], I->src[0], agx_zero(), AGX_BITOP_NOT);
case AGX_OPCODE_AND:
return agx_bitop_to(b, I->dest[0], I->src[0], I->src[1], AGX_BITOP_AND);
case AGX_OPCODE_XOR:
return agx_bitop_to(b, I->dest[0], I->src[0], I->src[1], AGX_BITOP_XOR);
case AGX_OPCODE_OR:
return agx_bitop_to(b, I->dest[0], I->src[0], I->src[1], AGX_BITOP_OR);
default: return NULL;
}
static void
agx_lower_to_binary_bitop(agx_instr *I, enum agx_bitop_table table)
{
I->op = AGX_OPCODE_BITOP;
I->truth_table = table;
}
void
agx_lower_pseudo(agx_context *ctx)
{
agx_foreach_instr_global(ctx, I) {
switch (I->op) {
agx_foreach_instr_global_safe(ctx, I) {
agx_builder b = agx_init_builder(ctx, agx_before_instr(I));
/* Various instructions are implemented as bitwise truth tables */
case AGX_OPCODE_MOV: agx_lower_to_unary_bitop(I, AGX_BITOP_MOV); break;
case AGX_OPCODE_NOT: agx_lower_to_unary_bitop(I, AGX_BITOP_NOT); break;
case AGX_OPCODE_AND: agx_lower_to_binary_bitop(I, AGX_BITOP_AND); break;
case AGX_OPCODE_XOR: agx_lower_to_binary_bitop(I, AGX_BITOP_XOR); break;
case AGX_OPCODE_OR: agx_lower_to_binary_bitop(I, AGX_BITOP_OR); break;
default:
break;
}
if (lower(&b, I))
agx_remove_instruction(I);
}
}

View File

@@ -267,9 +267,6 @@ op("logical_end", _, dests = 0, srcs = 0, can_eliminate = False)
op("combine", _, srcs = VARIABLE)
op("split", _, srcs = 1, dests = 4)
# Phis are special-cased in the IR as they (uniquely) can take an unbounded
# number of source.
op("phi", _, srcs = 0)
op("phi", _, srcs = VARIABLE)
op("unit_test", _, dests = 0, srcs = 1, can_eliminate = False)

View File

@@ -58,7 +58,7 @@ agx_test_builder(void *memctx)
static inline bool
agx_instr_equal(agx_instr *A, agx_instr *B)
{
unsigned pointers = sizeof(struct list_head) + sizeof(agx_index *);
unsigned pointers = sizeof(struct list_head) + sizeof(agx_index *) * 2;
if (A->nr_srcs != B->nr_srcs)
return false;
@@ -66,6 +66,12 @@ agx_instr_equal(agx_instr *A, agx_instr *B)
if (memcmp(A->src, B->src, A->nr_srcs * sizeof(agx_index)))
return false;
if (A->nr_dests != B->nr_dests)
return false;
if (memcmp(A->dest, B->dest, A->nr_dests * sizeof(agx_index)))
return false;
return memcmp((uint8_t *) A + pointers,
(uint8_t *) B + pointers,
sizeof(agx_instr) - pointers) == 0;