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:

committed by
Marge Bot

parent
544c60a132
commit
7c9fba34bc
@@ -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
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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) \
|
||||
|
@@ -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);
|
||||
}
|
||||
}
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user