agx: Preload vertex/instance ID only at start

This means we don't reserve the registers, which improves RA
considerably. Using a special preload psuedo-op instead of a regular
move allows us to constrain semantics and gaurantee coalescing.

shader-db on glmark2 subset:

total instructions in shared programs: 6448 -> 6442 (-0.09%)
instructions in affected programs: 230 -> 224 (-2.61%)
helped: 4
HURT: 0

total bytes in shared programs: 42232 -> 42196 (-0.09%)
bytes in affected programs: 1530 -> 1494 (-2.35%)
helped: 4
HURT: 0

total halfregs in shared programs: 2291 -> 1926 (-15.93%)
halfregs in affected programs: 2185 -> 1820 (-16.70%)
helped: 75
HURT: 0

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-23 17:27:43 -04:00
committed by Marge Bot
parent f665229d77
commit c9a96d4615
5 changed files with 111 additions and 18 deletions

View File

@@ -396,6 +396,11 @@ typedef struct {
* components, populated by a split. */
struct hash_table_u64 *allocated_vec;
/* During instruction selection, preloaded values,
* or NULL if it hasn't been preloaded
*/
agx_index vertex_id, instance_id;
/* Stats for shader-db */
unsigned loop_count;
unsigned spills;
@@ -456,6 +461,20 @@ agx_vec_for_intr(agx_context *ctx, nir_intrinsic_instr *instr)
return agx_vec_for_dest(ctx, &instr->dest);
}
static inline unsigned
agx_num_predecessors(agx_block *block)
{
return util_dynarray_num_elements(&block->predecessors, agx_block *);
}
static inline agx_block *
agx_start_block(agx_context *ctx)
{
agx_block *first = list_first_entry(&ctx->blocks, agx_block, link);
assert(agx_num_predecessors(first) == 0);
return first;
}
/* Iterators for AGX IR */
#define agx_foreach_block(ctx, v) \
@@ -650,6 +669,25 @@ agx_after_block_logical(agx_block *block)
return agx_after_block(block);
}
static inline agx_cursor
agx_before_nonempty_block(agx_block *block)
{
agx_instr *I = list_first_entry(&block->instructions, agx_instr, link);
assert(I != NULL);
return agx_before_instr(I);
}
static inline agx_cursor
agx_before_block(agx_block *block)
{
if (list_is_empty(&block->instructions))
return agx_after_block(block);
else
return agx_before_nonempty_block(block);
}
/* IR builder in terms of cursor infrastructure */
typedef struct {