agx: make vec widths explicit in IR

no functional changes.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26963>
This commit is contained in:
Alyssa Rosenzweig 2023-12-24 12:26:54 -04:00
parent caee8a3114
commit f0b8d933fc
4 changed files with 69 additions and 31 deletions

View file

@ -215,7 +215,7 @@ agx_emit_collect_to(agx_builder *b, agx_index dst, unsigned nr_srcs,
static agx_index
agx_emit_collect(agx_builder *b, unsigned nr_srcs, agx_index *srcs)
{
agx_index dst = agx_temp(b->shader, srcs[0].size);
agx_index dst = agx_vec_temp(b->shader, srcs[0].size, nr_srcs);
agx_emit_collect_to(b, dst, nr_srcs, srcs);
return dst;
}
@ -667,6 +667,7 @@ agx_emit_block_image_store(agx_builder *b, nir_intrinsic_instr *instr)
* logically to ensure alignment.
*/
offset = agx_vec2(b, offset, agx_undef(AGX_SIZE_16));
offset.channels_m1--;
offset.size = AGX_SIZE_32;
/* Modified coordinate descriptor */
@ -944,6 +945,7 @@ agx_emit_image_load(agx_builder *b, agx_index dst, nir_intrinsic_instr *intr)
assert(ms_index.size == AGX_SIZE_16);
agx_index vec = agx_vec2(b, ms_index, layer);
vec.size = AGX_SIZE_32;
vec.channels_m1 = 1 - 1;
coord[coord_comps++] = vec;
} else if (is_ms) {
agx_index tmp = agx_temp(b->shader, AGX_SIZE_32);
@ -960,7 +962,7 @@ agx_emit_image_load(agx_builder *b, agx_index dst, nir_intrinsic_instr *intr)
}
agx_index coords = agx_emit_collect(b, coord_comps, coord);
agx_index tmp = agx_temp(b->shader, dst.size);
agx_index tmp = agx_vec_temp(b->shader, dst.size, 4);
agx_instr *I = agx_image_load_to(
b, tmp, coords, lod, bindless, texture, agx_txf_sampler(b->shader),
@ -1816,7 +1818,7 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr)
agx_index index2 = agx_src_index(&instr->src[y_idx].src);
/* We explicitly don't cache about the split cache for this */
lod = agx_temp(b->shader, AGX_SIZE_32);
lod = agx_vec_temp(b->shader, AGX_SIZE_32, 2 * n);
agx_instr *I = agx_collect_to(b, lod, 2 * n);
for (unsigned i = 0; i < n; ++i) {
@ -1848,7 +1850,7 @@ agx_emit_tex(agx_builder *b, nir_tex_instr *instr)
else if (!agx_is_null(compare))
compare_offset = compare;
agx_index tmp = agx_temp(b->shader, dst.size);
agx_index tmp = agx_vec_temp(b->shader, dst.size, 4);
agx_instr *I = agx_texture_sample_to(
b, tmp, coords, lod, bindless, texture, sampler, compare_offset,
agx_tex_dim(instr->sampler_dim, instr->is_array),

View file

@ -56,7 +56,7 @@ agx_size_align_16(enum agx_size size)
typedef struct {
/* Sufficient for as many SSA values as we need. Immediates and uniforms fit
* in 16-bits */
unsigned value : 22;
unsigned value : 19;
/* Indicates that this source kills the referenced value (because it is the
* last use in a block and the source is not live after the block). Set by
@ -71,20 +71,34 @@ typedef struct {
bool abs : 1;
bool neg : 1;
unsigned channels_m1 : 3;
enum agx_size size : 2;
enum agx_index_type type : 3;
} agx_index;
static inline unsigned
agx_channels(agx_index idx)
{
return idx.channels_m1 + 1;
}
static inline agx_index
agx_get_index(unsigned value, enum agx_size size)
agx_get_vec_index(unsigned value, enum agx_size size, unsigned channels)
{
return (agx_index){
.value = value,
.channels_m1 = channels - 1,
.size = size,
.type = AGX_INDEX_NORMAL,
};
}
static inline agx_index
agx_get_index(unsigned value, enum agx_size size)
{
return agx_get_vec_index(value, size, 1);
}
static inline agx_index
agx_immediate(uint32_t imm)
{
@ -117,6 +131,19 @@ agx_register(uint32_t imm, enum agx_size size)
};
}
static inline agx_index
agx_register_like(uint32_t imm, agx_index like)
{
assert(imm < AGX_NUM_REGS);
return (agx_index){
.value = imm,
.channels_m1 = like.channels_m1,
.size = like.size,
.type = AGX_INDEX_REGISTER,
};
}
static inline agx_index
agx_undef(enum agx_size size)
{
@ -442,6 +469,12 @@ agx_remove_instruction(agx_instr *ins)
list_del(&ins->link);
}
static inline agx_index
agx_vec_temp(agx_context *ctx, enum agx_size size, unsigned channels)
{
return agx_get_vec_index(ctx->alloc++, size, channels);
}
static inline agx_index
agx_temp(agx_context *ctx, enum agx_size size)
{
@ -468,7 +501,8 @@ agx_size_for_bits(unsigned bits)
static inline agx_index
agx_def_index(nir_def *ssa)
{
return agx_get_index(ssa->index, agx_size_for_bits(ssa->bit_size));
return agx_get_vec_index(ssa->index, agx_size_for_bits(ssa->bit_size),
ssa->num_components);
}
static inline agx_index
@ -480,7 +514,8 @@ agx_src_index(nir_src *src)
static inline agx_index
agx_vec_for_def(agx_context *ctx, nir_def *def)
{
return agx_temp(ctx, agx_size_for_bits(def->bit_size));
return agx_vec_temp(ctx, agx_size_for_bits(def->bit_size),
def->num_components);
}
static inline agx_index

View file

@ -758,7 +758,7 @@ agx_set_sources(struct ra_ctx *rctx, agx_instr *I)
assert(BITSET_TEST(rctx->visited, I->src[s].value) && "no phis");
unsigned v = rctx->ssa_to_reg[I->src[s].value];
agx_replace_src(I, s, agx_register(v, I->src[s].size));
agx_replace_src(I, s, agx_register_like(v, I->src[s]));
}
}
@ -768,7 +768,7 @@ agx_set_dests(struct ra_ctx *rctx, agx_instr *I)
agx_foreach_ssa_dest(I, s) {
unsigned v = rctx->ssa_to_reg[I->dest[s].value];
I->dest[s] =
agx_replace_index(I->dest[s], agx_register(v, I->dest[s].size));
agx_replace_index(I->dest[s], agx_register_like(v, I->dest[s]));
}
}
@ -1243,6 +1243,7 @@ agx_ra(agx_context *ctx)
agx_index src = ins->src[0];
src.size = ins->dest[i].size;
src.channels_m1 = 0;
src.value += (i * width);
copies[n++] = (struct agx_copy){

View file

@ -123,45 +123,45 @@ agx_validate_defs(agx_instr *I, BITSET_WORD *defs)
return true;
}
/*
* Type check the dimensionality of sources and destinations. This occurs in two
* passes, first to gather all destination sizes, second to validate all source
* sizes. Depends on SSA form.
*/
/* Type check the dimensionality of sources and destinations. */
static bool
agx_validate_width(agx_context *ctx)
{
bool succ = true;
uint8_t *width = calloc(ctx->alloc, sizeof(uint8_t));
agx_foreach_instr_global(ctx, I) {
agx_foreach_dest(I, d) {
if (I->dest[d].type != AGX_INDEX_NORMAL)
unsigned exp = agx_write_registers(I, d);
unsigned act =
agx_channels(I->dest[d]) * agx_size_align_16(I->dest[d].size);
if (exp != act) {
succ = false;
fprintf(stderr, "destination %u, expected width %u, got width %u\n",
d, exp, act);
agx_print_instr(I, stderr);
fprintf(stderr, "\n");
}
}
agx_foreach_src(I, s) {
if (I->src[s].type == AGX_INDEX_NULL)
continue;
unsigned v = I->dest[d].value;
assert(width[v] == 0 && "broken SSA");
unsigned exp = agx_read_registers(I, s);
unsigned act =
agx_channels(I->src[s]) * agx_size_align_16(I->src[s].size);
width[v] = agx_write_registers(I, d);
}
}
agx_foreach_instr_global(ctx, I) {
agx_foreach_ssa_src(I, s) {
unsigned v = I->src[s].value;
unsigned n = agx_read_registers(I, s);
if (width[v] != n) {
if (exp != act) {
succ = false;
fprintf(stderr, "source %u, expected width %u, got width %u\n", s,
n, width[v]);
exp, act);
agx_print_instr(I, stderr);
fprintf(stderr, "\n");
}
}
}
free(width);
return succ;
}