agx: Pass agx_index to agx_copy

More straightforward interface and will allow including immediates later
if we want to.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19590>
This commit is contained in:
Alyssa Rosenzweig
2022-10-26 21:16:11 -04:00
committed by Marge Bot
parent 023f27fada
commit 98f0ebf264
4 changed files with 64 additions and 82 deletions

View File

@@ -779,12 +779,8 @@ struct agx_copy {
/* Base register destination of the copy */ /* Base register destination of the copy */
unsigned dest; unsigned dest;
/* Base register source (or uniform base) of the copy */ /* Source of the copy */
unsigned src; agx_index src;
bool is_uniform;
/* Size of the copy */
enum agx_size size;
/* Whether the copy has been handled. Callers must leave to false. */ /* Whether the copy has been handled. Callers must leave to false. */
bool done; bool done;

View File

@@ -40,31 +40,22 @@
* We only handles register-register copies, not general agx_index sources. This * We only handles register-register copies, not general agx_index sources. This
* suffices for its internal use for register allocation. * suffices for its internal use for register allocation.
*/ */
static agx_index
copy_src(const struct agx_copy *copy)
{
if (copy->is_uniform)
return agx_uniform(copy->src, copy->size);
else
return agx_register(copy->src, copy->size);
}
static void static void
do_copy(agx_builder *b, const struct agx_copy *copy) do_copy(agx_builder *b, const struct agx_copy *copy)
{ {
agx_mov_to(b, agx_register(copy->dest, copy->size), copy_src(copy)); agx_mov_to(b, agx_register(copy->dest, copy->src.size), copy->src);
} }
static void static void
do_swap(agx_builder *b, const struct agx_copy *copy) do_swap(agx_builder *b, const struct agx_copy *copy)
{ {
assert(!copy->is_uniform && "cannot swap uniform with GPR"); assert(copy->src.type == AGX_INDEX_REGISTER && "only GPRs are swapped");
if (copy->dest == copy->src) if (copy->dest == copy->src.value)
return; return;
agx_index x = agx_register(copy->dest, copy->size); agx_index x = agx_register(copy->dest, copy->src.size);
agx_index y = copy_src(copy); agx_index y = copy->src;
agx_xor_to(b, x, x, y); agx_xor_to(b, x, x, y);
agx_xor_to(b, y, x, y); agx_xor_to(b, y, x, y);
@@ -90,7 +81,7 @@ struct copy_ctx {
static bool static bool
entry_blocked(struct agx_copy *entry, struct copy_ctx *ctx) entry_blocked(struct agx_copy *entry, struct copy_ctx *ctx)
{ {
for (unsigned i = 0; i < agx_size_align_16(entry->size); i++) { for (unsigned i = 0; i < agx_size_align_16(entry->src.size); i++) {
if (ctx->physreg_use_count[entry->dest + i] != 0) if (ctx->physreg_use_count[entry->dest + i] != 0)
return true; return true;
} }
@@ -101,7 +92,7 @@ entry_blocked(struct agx_copy *entry, struct copy_ctx *ctx)
static bool static bool
is_real(struct agx_copy *entry) is_real(struct agx_copy *entry)
{ {
return !entry->is_uniform; return entry->src.type == AGX_INDEX_REGISTER;
} }
/* TODO: Generalize to other bit sizes */ /* TODO: Generalize to other bit sizes */
@@ -110,14 +101,15 @@ split_32bit_copy(struct copy_ctx *ctx, struct agx_copy *entry)
{ {
assert(!entry->done); assert(!entry->done);
assert(is_real(entry)); assert(is_real(entry));
assert(agx_size_align_16(entry->size) == 2); assert(agx_size_align_16(entry->src.size) == 2);
struct agx_copy *new_entry = &ctx->entries[ctx->entry_count++]; struct agx_copy *new_entry = &ctx->entries[ctx->entry_count++];
new_entry->dest = entry->dest + 1; new_entry->dest = entry->dest + 1;
new_entry->src = entry->src + 1; new_entry->src = entry->src;
new_entry->src.value += 1;
new_entry->done = false; new_entry->done = false;
entry->size = AGX_SIZE_16; entry->src.size = AGX_SIZE_16;
new_entry->size = AGX_SIZE_16; new_entry->src.size = AGX_SIZE_16;
ctx->physreg_dest[entry->dest + 1] = new_entry; ctx->physreg_dest[entry->dest + 1] = new_entry;
} }
@@ -141,9 +133,9 @@ agx_emit_parallel_copies(agx_builder *b,
ctx->entries[i] = *entry; ctx->entries[i] = *entry;
for (unsigned j = 0; j < agx_size_align_16(entry->size); j++) { for (unsigned j = 0; j < agx_size_align_16(entry->src.size); j++) {
if (is_real(entry)) if (is_real(entry))
ctx->physreg_use_count[entry->src + j]++; ctx->physreg_use_count[entry->src.value + j]++;
/* Copies should not have overlapping destinations. */ /* Copies should not have overlapping destinations. */
assert(!ctx->physreg_dest[entry->dest + j]); assert(!ctx->physreg_dest[entry->dest + j]);
@@ -170,9 +162,9 @@ agx_emit_parallel_copies(agx_builder *b,
entry->done = true; entry->done = true;
progress = true; progress = true;
do_copy(b, entry); do_copy(b, entry);
for (unsigned j = 0; j < agx_size_align_16(entry->size); j++) { for (unsigned j = 0; j < agx_size_align_16(entry->src.size); j++) {
if (is_real(entry)) if (is_real(entry))
ctx->physreg_use_count[entry->src + j]--; ctx->physreg_use_count[entry->src.value + j]--;
ctx->physreg_dest[entry->dest + j] = NULL; ctx->physreg_dest[entry->dest + j] = NULL;
} }
} }
@@ -193,7 +185,7 @@ agx_emit_parallel_copies(agx_builder *b,
*/ */
for (unsigned i = 0; i < ctx->entry_count; i++) { for (unsigned i = 0; i < ctx->entry_count; i++) {
struct agx_copy *entry = &ctx->entries[i]; struct agx_copy *entry = &ctx->entries[i];
if (entry->done || (agx_size_align_16(entry->size) != 2)) if (entry->done || (agx_size_align_16(entry->src.size) != 2))
continue; continue;
if (((ctx->physreg_use_count[entry->dest] == 0 || if (((ctx->physreg_use_count[entry->dest] == 0 ||
@@ -249,7 +241,7 @@ agx_emit_parallel_copies(agx_builder *b,
assert(is_real(entry)); assert(is_real(entry));
/* catch trivial copies */ /* catch trivial copies */
if (entry->dest == entry->src) { if (entry->dest == entry->src.value) {
entry->done = true; entry->done = true;
continue; continue;
} }
@@ -259,16 +251,16 @@ agx_emit_parallel_copies(agx_builder *b,
/* Split any blocking copies whose sources are only partially /* Split any blocking copies whose sources are only partially
* contained within our destination. * contained within our destination.
*/ */
if (agx_size_align_16(entry->size) == 1) { if (agx_size_align_16(entry->src.size) == 1) {
for (unsigned j = 0; j < ctx->entry_count; j++) { for (unsigned j = 0; j < ctx->entry_count; j++) {
struct agx_copy *blocking = &ctx->entries[j]; struct agx_copy *blocking = &ctx->entries[j];
if (blocking->done) if (blocking->done)
continue; continue;
if (blocking->src <= entry->dest && if (blocking->src.value <= entry->dest &&
blocking->src + 1 >= entry->dest && blocking->src.value + 1 >= entry->dest &&
agx_size_align_16(blocking->size) == 2) { agx_size_align_16(blocking->src.size) == 2) {
split_32bit_copy(ctx, blocking); split_32bit_copy(ctx, blocking);
} }
} }
@@ -281,9 +273,9 @@ agx_emit_parallel_copies(agx_builder *b,
*/ */
for (unsigned j = 0; j < ctx->entry_count; j++) { for (unsigned j = 0; j < ctx->entry_count; j++) {
struct agx_copy *blocking = &ctx->entries[j]; struct agx_copy *blocking = &ctx->entries[j];
if (blocking->src >= entry->dest && if (blocking->src.value >= entry->dest &&
blocking->src < entry->dest + agx_size_align_16(entry->size)) { blocking->src.value < entry->dest + agx_size_align_16(entry->src.size)) {
blocking->src = entry->src + (blocking->src - entry->dest); blocking->src.value = entry->src.value + (blocking->src.value - entry->dest);
} }
} }

View File

@@ -359,8 +359,7 @@ agx_insert_parallel_copies(agx_context *ctx, agx_block *block)
copies[i++] = (struct agx_copy) { copies[i++] = (struct agx_copy) {
.dest = dest.value, .dest = dest.value,
.src = src.value, .src = src,
.size = src.size
}; };
} }
@@ -444,13 +443,9 @@ agx_ra(agx_context *ctx)
if (agx_is_null(ins->src[i])) continue; if (agx_is_null(ins->src[i])) continue;
assert(ins->src[i].size == ins->dest[0].size); assert(ins->src[i].size == ins->dest[0].size);
bool is_uniform = ins->src[i].type == AGX_INDEX_UNIFORM;
copies[n++] = (struct agx_copy) { copies[n++] = (struct agx_copy) {
.dest = base + (i * width), .dest = base + (i * width),
.is_uniform = is_uniform, .src = ins->src[i]
.src = is_uniform ? ins->src[i].value : agx_index_to_reg(ssa_to_reg, ins->src[i]),
.size = ins->src[i].size
}; };
} }
@@ -473,8 +468,7 @@ agx_ra(agx_context *ctx)
copies[n++] = (struct agx_copy) { copies[n++] = (struct agx_copy) {
.dest = agx_index_to_reg(ssa_to_reg, ins->dest[i]), .dest = agx_index_to_reg(ssa_to_reg, ins->dest[i]),
.src = base + (i * width), .src = agx_register(base + (i * width), ins->dest[i].size)
.size = ins->dest[i].size
}; };
} }

View File

@@ -62,8 +62,8 @@ protected:
TEST_F(LowerParallelCopy, UnrelatedCopies) { TEST_F(LowerParallelCopy, UnrelatedCopies) {
struct agx_copy test_1[] = { struct agx_copy test_1[] = {
{ .dest = 0, .src = 2, .size = AGX_SIZE_32 }, { .dest = 0, .src = agx_register(2, AGX_SIZE_32) },
{ .dest = 4, .src = 6, .size = AGX_SIZE_32 }, { .dest = 4, .src = agx_register(6, AGX_SIZE_32) },
}; };
CASE(test_1, { CASE(test_1, {
@@ -72,8 +72,8 @@ TEST_F(LowerParallelCopy, UnrelatedCopies) {
}); });
struct agx_copy test_2[] = { struct agx_copy test_2[] = {
{ .dest = 0, .src = 1, .size = AGX_SIZE_16 }, { .dest = 0, .src = agx_register(1, AGX_SIZE_16) },
{ .dest = 4, .src = 5, .size = AGX_SIZE_16 }, { .dest = 4, .src = agx_register(5, AGX_SIZE_16) },
}; };
CASE(test_2, { CASE(test_2, {
@@ -85,8 +85,8 @@ TEST_F(LowerParallelCopy, UnrelatedCopies) {
TEST_F(LowerParallelCopy, RelatedSource) TEST_F(LowerParallelCopy, RelatedSource)
{ {
struct agx_copy test_1[] = { struct agx_copy test_1[] = {
{ .dest = 0, .src = 2, .size = AGX_SIZE_32 }, { .dest = 0, .src = agx_register(2, AGX_SIZE_32) },
{ .dest = 4, .src = 2, .size = AGX_SIZE_32 }, { .dest = 4, .src = agx_register(2, AGX_SIZE_32) },
}; };
CASE(test_1, { CASE(test_1, {
@@ -95,8 +95,8 @@ TEST_F(LowerParallelCopy, RelatedSource)
}); });
struct agx_copy test_2[] = { struct agx_copy test_2[] = {
{ .dest = 0, .src = 1, .size = AGX_SIZE_16 }, { .dest = 0, .src = agx_register(1, AGX_SIZE_16) },
{ .dest = 4, .src = 1, .size = AGX_SIZE_16 }, { .dest = 4, .src = agx_register(1, AGX_SIZE_16) },
}; };
CASE(test_2, { CASE(test_2, {
@@ -108,8 +108,8 @@ TEST_F(LowerParallelCopy, RelatedSource)
TEST_F(LowerParallelCopy, DependentCopies) TEST_F(LowerParallelCopy, DependentCopies)
{ {
struct agx_copy test_1[] = { struct agx_copy test_1[] = {
{ .dest = 0, .src = 2, .size = AGX_SIZE_32 }, { .dest = 0, .src = agx_register(2, AGX_SIZE_32) },
{ .dest = 4, .src = 0, .size = AGX_SIZE_32 }, { .dest = 4, .src = agx_register(0, AGX_SIZE_32) },
}; };
CASE(test_1, { CASE(test_1, {
@@ -118,8 +118,8 @@ TEST_F(LowerParallelCopy, DependentCopies)
}); });
struct agx_copy test_2[] = { struct agx_copy test_2[] = {
{ .dest = 0, .src = 1, .size = AGX_SIZE_16 }, { .dest = 0, .src = agx_register(1, AGX_SIZE_16) },
{ .dest = 4, .src = 0, .size = AGX_SIZE_16 }, { .dest = 4, .src = agx_register(0, AGX_SIZE_16) },
}; };
CASE(test_2, { CASE(test_2, {
@@ -131,10 +131,10 @@ TEST_F(LowerParallelCopy, DependentCopies)
TEST_F(LowerParallelCopy, ManyDependentCopies) TEST_F(LowerParallelCopy, ManyDependentCopies)
{ {
struct agx_copy test_1[] = { struct agx_copy test_1[] = {
{ .dest = 0, .src = 2, .size = AGX_SIZE_32 }, { .dest = 0, .src = agx_register(2, AGX_SIZE_32) },
{ .dest = 4, .src = 0, .size = AGX_SIZE_32 }, { .dest = 4, .src = agx_register(0, AGX_SIZE_32) },
{ .dest = 8, .src = 6, .size = AGX_SIZE_32 }, { .dest = 8, .src = agx_register(6, AGX_SIZE_32) },
{ .dest = 6, .src = 4, .size = AGX_SIZE_32 }, { .dest = 6, .src = agx_register(4, AGX_SIZE_32) },
}; };
CASE(test_1, { CASE(test_1, {
@@ -145,10 +145,10 @@ TEST_F(LowerParallelCopy, ManyDependentCopies)
}); });
struct agx_copy test_2[] = { struct agx_copy test_2[] = {
{ .dest = 0, .src = 1, .size = AGX_SIZE_16 }, { .dest = 0, .src = agx_register(1, AGX_SIZE_16) },
{ .dest = 2, .src = 0, .size = AGX_SIZE_16 }, { .dest = 2, .src = agx_register(0, AGX_SIZE_16) },
{ .dest = 4, .src = 3, .size = AGX_SIZE_16 }, { .dest = 4, .src = agx_register(3, AGX_SIZE_16) },
{ .dest = 3, .src = 2, .size = AGX_SIZE_16 }, { .dest = 3, .src = agx_register(2, AGX_SIZE_16) },
}; };
CASE(test_2, { CASE(test_2, {
@@ -161,8 +161,8 @@ TEST_F(LowerParallelCopy, ManyDependentCopies)
TEST_F(LowerParallelCopy, Swap) { TEST_F(LowerParallelCopy, Swap) {
struct agx_copy test_1[] = { struct agx_copy test_1[] = {
{ .dest = 0, .src = 2, .size = AGX_SIZE_32 }, { .dest = 0, .src = agx_register(2, AGX_SIZE_32) },
{ .dest = 2, .src = 0, .size = AGX_SIZE_32 }, { .dest = 2, .src = agx_register(0, AGX_SIZE_32) },
}; };
CASE(test_1, { CASE(test_1, {
@@ -170,8 +170,8 @@ TEST_F(LowerParallelCopy, Swap) {
}); });
struct agx_copy test_2[] = { struct agx_copy test_2[] = {
{ .dest = 0, .src = 1, .size = AGX_SIZE_16 }, { .dest = 0, .src = agx_register(1, AGX_SIZE_16) },
{ .dest = 1, .src = 0, .size = AGX_SIZE_16 }, { .dest = 1, .src = agx_register(0, AGX_SIZE_16) },
}; };
CASE(test_2, { CASE(test_2, {
@@ -181,9 +181,9 @@ TEST_F(LowerParallelCopy, Swap) {
TEST_F(LowerParallelCopy, Cycle3) { TEST_F(LowerParallelCopy, Cycle3) {
struct agx_copy test[] = { struct agx_copy test[] = {
{ .dest = 0, .src = 1, .size = AGX_SIZE_16 }, { .dest = 0, .src = agx_register(1, AGX_SIZE_16) },
{ .dest = 1, .src = 2, .size = AGX_SIZE_16 }, { .dest = 1, .src = agx_register(2, AGX_SIZE_16) },
{ .dest = 2, .src = 0, .size = AGX_SIZE_16 }, { .dest = 2, .src = agx_register(0, AGX_SIZE_16) },
}; };
/* XXX: requires 6 instructions. if we had a temp free, could do it in 4 */ /* XXX: requires 6 instructions. if we had a temp free, could do it in 4 */
@@ -196,10 +196,10 @@ TEST_F(LowerParallelCopy, Cycle3) {
/* Test case from Hack et al */ /* Test case from Hack et al */
TEST_F(LowerParallelCopy, TwoSwaps) { TEST_F(LowerParallelCopy, TwoSwaps) {
struct agx_copy test[] = { struct agx_copy test[] = {
{ .dest = 4, .src = 2, .size = AGX_SIZE_32 }, { .dest = 4, .src = agx_register(2, AGX_SIZE_32) },
{ .dest = 6, .src = 4, .size = AGX_SIZE_32 }, { .dest = 6, .src = agx_register(4, AGX_SIZE_32) },
{ .dest = 2, .src = 6, .size = AGX_SIZE_32 }, { .dest = 2, .src = agx_register(6, AGX_SIZE_32) },
{ .dest = 8, .src = 8, .size = AGX_SIZE_32 }, { .dest = 8, .src = agx_register(8, AGX_SIZE_32) },
}; };
CASE(test, { CASE(test, {
@@ -211,9 +211,9 @@ TEST_F(LowerParallelCopy, TwoSwaps) {
#if 0 #if 0
TEST_F(LowerParallelCopy, LooksLikeASwap) { TEST_F(LowerParallelCopy, LooksLikeASwap) {
struct agx_copy test[] = { struct agx_copy test[] = {
{ .dest = 0, .src = 2, .size = AGX_SIZE_32 }, { .dest = 0, .src = agx_register(2, AGX_SIZE_32) },
{ .dest = 2, .src = 0, .size = AGX_SIZE_32 }, { .dest = 2, .src = agx_register(0, AGX_SIZE_32) },
{ .dest = 4, .src = 2, .size = AGX_SIZE_32 }, { .dest = 4, .src = agx_register(2, AGX_SIZE_32) },
}; };
CASE(test, { CASE(test, {