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" #include "agx_compiler.h"
static inline agx_instr * 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->op = op;
I->nr_dests = nr_dests;
I->nr_srcs = nr_srcs;
return I; return I;
} }
@@ -41,11 +50,17 @@ agx_alloc_instr(agx_builder *b, enum agx_opcode op)
srcs = op.srcs srcs = op.srcs
imms = op.imms imms = op.imms
suffix = "_to" if dests > 0 else "" 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 * static inline agx_instr *
agx_${opcode}${suffix}(agx_builder *b agx_${opcode}${suffix}(agx_builder *b
% if op.variable_dests:
, unsigned nr_dests
% endif
% for dest in range(dests): % for dest in range(dests):
, agx_index dst${dest} , agx_index dst${dest}
% endfor % endfor
@@ -63,23 +78,15 @@ agx_${opcode}${suffix}(agx_builder *b
% endfor % 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): % for dest in range(dests):
I->dest[${dest}] = dst${dest}; I->dest[${dest}] = dst${dest};
% endfor % 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): % for src in range(srcs):
I->src[${src}] = src${src}; I->src[${src}] = src${src};
% endfor % endfor
% endif
% for imm in imms: % for imm in imms:
I->${imm.name} = ${imm.name}; I->${imm.name} = ${imm.name};
@@ -89,7 +96,7 @@ agx_${opcode}${suffix}(agx_builder *b
return I; 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 static inline agx_index
agx_${opcode}(agx_builder *b agx_${opcode}(agx_builder *b

View File

@@ -1207,7 +1207,8 @@ agx_emit_jump(agx_builder *b, nir_jump_instr *instr)
static void static void
agx_emit_phi(agx_builder *b, nir_phi_instr *instr) 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 */ /* Deferred */
I->phi = instr; 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 */ /* Guaranteed by lower_phis_to_scalar */
assert(phi->dest.ssa.num_components == 1); 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) { nir_foreach_phi_src(src, phi) {
agx_block *pred = agx_from_nir_block(ctx, src->pred); agx_block *pred = agx_from_nir_block(ctx, src->pred);
unsigned i = agx_predecessor_index(block, pred); unsigned i = agx_predecessor_index(block, pred);

View File

@@ -288,12 +288,13 @@ typedef struct {
nir_phi_instr *phi; nir_phi_instr *phi;
}; };
/* Data flow */
agx_index *dest;
enum agx_opcode op; enum agx_opcode op;
/* Data flow */ uint8_t nr_dests;
agx_index dest[AGX_MAX_DESTS]; uint8_t nr_srcs;
unsigned nr_srcs;
union { union {
uint32_t imm; 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) for (unsigned v = 0; v < ins->nr_srcs; ++v)
#define agx_foreach_dest(ins, 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 */ /* 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) \ #define agx_foreach_phi_in_block(block, v) \

View File

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

View File

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

View File

@@ -58,7 +58,7 @@ agx_test_builder(void *memctx)
static inline bool static inline bool
agx_instr_equal(agx_instr *A, agx_instr *B) 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) if (A->nr_srcs != B->nr_srcs)
return false; 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))) if (memcmp(A->src, B->src, A->nr_srcs * sizeof(agx_index)))
return false; 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, return memcmp((uint8_t *) A + pointers,
(uint8_t *) B + pointers, (uint8_t *) B + pointers,
sizeof(agx_instr) - pointers) == 0; sizeof(agx_instr) - pointers) == 0;