agx: Handle type-changing splits

If we want to break down a 64-bit value into its 32-bit halves, we want
to be able to use a split for this:

   lo, hi = split long

Extend the RA to handle this case.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17198>
This commit is contained in:
Alyssa Rosenzweig 2022-08-07 14:16:43 -04:00
parent f86ad382c5
commit c1900cb951

View file

@ -61,6 +61,24 @@ agx_write_registers(agx_instr *I, unsigned d)
}
}
static inline enum agx_size
agx_split_width(const agx_instr *I)
{
enum agx_size width = ~0;
agx_foreach_dest(I, d) {
if (agx_is_null(I->dest[d]))
continue;
else if (width != ~0)
assert(width == I->dest[d].size);
else
width = I->dest[d].size;
}
assert(width != ~0 && "should have been DCE'd");
return width;
}
static unsigned
agx_assign_regs(BITSET_WORD *used_regs, unsigned count, unsigned align, unsigned max)
{
@ -114,7 +132,7 @@ agx_ra_assign_local(agx_block *block, uint8_t *ssa_to_reg, uint8_t *ncomps)
if (I->op == AGX_OPCODE_P_SPLIT && I->src[0].kill) {
unsigned reg = ssa_to_reg[I->src[0].value];
unsigned length = ncomps[I->src[0].value];
unsigned width = agx_size_align_16(I->src[0].size);
unsigned width = agx_size_align_16(agx_split_width(I));
unsigned count = length / width;
agx_foreach_dest(I, d) {
@ -339,7 +357,7 @@ agx_ra(agx_context *ctx)
continue;
} else if (ins->op == AGX_OPCODE_P_SPLIT) {
unsigned base = agx_index_to_reg(ssa_to_reg, ins->src[0]);
unsigned width = agx_size_align_16(ins->src[0].size);
unsigned width = agx_size_align_16(agx_split_width(ins));
struct agx_copy copies[4];
unsigned n = 0;
@ -347,7 +365,6 @@ agx_ra(agx_context *ctx)
/* Move the sources */
for (unsigned i = 0; i < 4; ++i) {
if (agx_is_null(ins->dest[i])) continue;
assert(ins->dest[i].size == ins->src[0].size);
copies[n++] = (struct agx_copy) {
.dest = agx_index_to_reg(ssa_to_reg, ins->dest[i]),