blob: d8106ab924d1eb68e0a295423ffffb52c93283bb [file] [log] [blame] [edit]
/*
* Copyright 2021 Collabora, Ltd.
* SPDX-License-Identifier: MIT
*/
#include "agx_builder.h"
#include "agx_compiler.h"
#include "agx_test.h"
#include <gtest/gtest.h>
#define CASE(copies, expected) \
do { \
agx_builder *A = agx_test_builder(mem_ctx); \
agx_builder *B = agx_test_builder(mem_ctx); \
\
A->shader->scratch_size = 2000; \
agx_emit_parallel_copies(A, copies, ARRAY_SIZE(copies)); \
\
{ \
agx_builder *b = B; \
expected; \
} \
\
ASSERT_SHADER_EQUAL(A->shader, B->shader); \
} while (0)
static inline void
extr_swap(agx_builder *b, agx_index x)
{
x.size = AGX_SIZE_32;
agx_extr_to(b, x, x, x, agx_immediate(16), 0);
}
static inline void
xor_swap(agx_builder *b, agx_index x, agx_index y)
{
agx_xor_to(b, x, x, y);
agx_xor_to(b, y, x, y);
agx_xor_to(b, x, x, y);
}
class LowerParallelCopy : public testing::Test {
protected:
LowerParallelCopy()
{
mem_ctx = ralloc_context(NULL);
}
~LowerParallelCopy()
{
ralloc_free(mem_ctx);
}
void *mem_ctx;
};
TEST_F(LowerParallelCopy, UnrelatedCopies)
{
struct agx_copy test_1[] = {
{.dest = 0, .src = agx_register(2, AGX_SIZE_32)},
{.dest = 4, .src = agx_register(6, AGX_SIZE_32)},
};
CASE(test_1, {
agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(6, AGX_SIZE_32));
});
struct agx_copy test_2[] = {
{.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
{.dest = 4, .src = agx_register(5, AGX_SIZE_16)},
};
CASE(test_2, {
agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(5, AGX_SIZE_16));
});
}
TEST_F(LowerParallelCopy, RelatedSource)
{
struct agx_copy test_1[] = {
{.dest = 0, .src = agx_register(2, AGX_SIZE_32)},
{.dest = 4, .src = agx_register(2, AGX_SIZE_32)},
};
CASE(test_1, {
agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
});
struct agx_copy test_2[] = {
{.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
{.dest = 4, .src = agx_register(1, AGX_SIZE_16)},
};
CASE(test_2, {
agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
});
}
TEST_F(LowerParallelCopy, DependentCopies)
{
struct agx_copy test_1[] = {
{.dest = 0, .src = agx_register(2, AGX_SIZE_32)},
{.dest = 4, .src = agx_register(0, AGX_SIZE_32)},
};
CASE(test_1, {
agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(0, AGX_SIZE_32));
agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
});
struct agx_copy test_2[] = {
{.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
{.dest = 4, .src = agx_register(0, AGX_SIZE_16)},
};
CASE(test_2, {
agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(0, AGX_SIZE_16));
agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
});
}
TEST_F(LowerParallelCopy, ManyDependentCopies)
{
struct agx_copy test_1[] = {
{.dest = 0, .src = agx_register(2, AGX_SIZE_32)},
{.dest = 4, .src = agx_register(0, AGX_SIZE_32)},
{.dest = 8, .src = agx_register(6, AGX_SIZE_32)},
{.dest = 6, .src = agx_register(4, AGX_SIZE_32)},
};
CASE(test_1, {
agx_mov_to(b, agx_register(8, AGX_SIZE_32), agx_register(6, AGX_SIZE_32));
agx_mov_to(b, agx_register(6, AGX_SIZE_32), agx_register(4, AGX_SIZE_32));
agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(0, AGX_SIZE_32));
agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
});
struct agx_copy test_2[] = {
{.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
{.dest = 2, .src = agx_register(0, AGX_SIZE_16)},
{.dest = 4, .src = agx_register(3, AGX_SIZE_16)},
{.dest = 3, .src = agx_register(2, AGX_SIZE_16)},
};
CASE(test_2, {
agx_mov_to(b, agx_register(4, AGX_SIZE_16), agx_register(3, AGX_SIZE_16));
agx_mov_to(b, agx_register(3, AGX_SIZE_16), agx_register(2, AGX_SIZE_16));
agx_mov_to(b, agx_register(2, AGX_SIZE_16), agx_register(0, AGX_SIZE_16));
agx_mov_to(b, agx_register(0, AGX_SIZE_16), agx_register(1, AGX_SIZE_16));
});
}
TEST_F(LowerParallelCopy, Swap)
{
struct agx_copy test_1[] = {
{.dest = 0, .src = agx_register(2, AGX_SIZE_32)},
{.dest = 2, .src = agx_register(0, AGX_SIZE_32)},
};
CASE(test_1, {
xor_swap(b, agx_register(0, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
});
struct agx_copy test_2[] = {
{.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
{.dest = 1, .src = agx_register(0, AGX_SIZE_16)},
};
CASE(test_2, { extr_swap(b, agx_register(0, AGX_SIZE_16)); });
}
TEST_F(LowerParallelCopy, Cycle3)
{
struct agx_copy test[] = {
{.dest = 0, .src = agx_register(1, AGX_SIZE_16)},
{.dest = 1, .src = agx_register(2, AGX_SIZE_16)},
{.dest = 2, .src = agx_register(0, AGX_SIZE_16)},
};
CASE(test, {
extr_swap(b, agx_register(0, AGX_SIZE_16));
xor_swap(b, agx_register(1, AGX_SIZE_16), agx_register(2, AGX_SIZE_16));
});
}
TEST_F(LowerParallelCopy, Immediate64)
{
agx_index imm = agx_immediate(10);
imm.size = AGX_SIZE_64;
struct agx_copy test_1[] = {
{.dest = 4, .src = imm},
};
CASE(test_1, {
agx_mov_imm_to(b, agx_register(4, AGX_SIZE_32), 10);
agx_mov_imm_to(b, agx_register(6, AGX_SIZE_32), 0);
});
}
/* Test case from Hack et al */
TEST_F(LowerParallelCopy, TwoSwaps)
{
struct agx_copy test[] = {
{.dest = 4, .src = agx_register(2, AGX_SIZE_32)},
{.dest = 6, .src = agx_register(4, AGX_SIZE_32)},
{.dest = 2, .src = agx_register(6, AGX_SIZE_32)},
{.dest = 8, .src = agx_register(8, AGX_SIZE_32)},
};
CASE(test, {
xor_swap(b, agx_register(4, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
xor_swap(b, agx_register(6, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
});
}
TEST_F(LowerParallelCopy, VectorizeAlignedHalfRegs)
{
struct agx_copy test[] = {
{.dest = 0, .src = agx_register(10, AGX_SIZE_16)},
{.dest = 1, .src = agx_register(11, AGX_SIZE_16)},
{.dest = 2, .src = agx_uniform(8, AGX_SIZE_16)},
{.dest = 3, .src = agx_uniform(9, AGX_SIZE_16)},
};
CASE(test, {
agx_mov_to(b, agx_register(0, AGX_SIZE_32),
agx_register(10, AGX_SIZE_32));
agx_mov_to(b, agx_register(2, AGX_SIZE_32), agx_uniform(8, AGX_SIZE_32));
});
}
TEST_F(LowerParallelCopy, StackCopies)
{
struct agx_copy test[] = {
{.dest = 21, .dest_mem = true, .src = agx_register(20, AGX_SIZE_16)},
{.dest = 22, .dest_mem = true, .src = agx_register(22, AGX_SIZE_32)},
{.dest = 0, .src = agx_memory_register(10, AGX_SIZE_16)},
{.dest = 1, .src = agx_memory_register(11, AGX_SIZE_16)},
{.dest = 0, .dest_mem = true, .src = agx_memory_register(12, AGX_SIZE_16)},
{.dest = 1, .dest_mem = true, .src = agx_memory_register(13, AGX_SIZE_16)},
{.dest = 2,
.dest_mem = true,
.src = agx_memory_register(804, AGX_SIZE_32)},
{.dest = 804,
.dest_mem = true,
.src = agx_memory_register(2, AGX_SIZE_32)},
{.dest = 807,
.dest_mem = true,
.src = agx_memory_register(808, AGX_SIZE_16)},
{.dest = 808,
.dest_mem = true,
.src = agx_memory_register(807, AGX_SIZE_16)},
};
CASE(test, {
/* Vectorized fill */
agx_mov_to(b, agx_register(0, AGX_SIZE_32),
agx_memory_register(10, AGX_SIZE_32));
/* Regular spills */
agx_mov_to(b, agx_memory_register(21, AGX_SIZE_16),
agx_register(20, AGX_SIZE_16));
agx_mov_to(b, agx_memory_register(22, AGX_SIZE_32),
agx_register(22, AGX_SIZE_32));
/* Vectorized stack->stack copy */
agx_mov_to(b, agx_memory_register(1000, AGX_SIZE_32),
agx_register(0, AGX_SIZE_32));
agx_mov_to(b, agx_register(0, AGX_SIZE_32),
agx_memory_register(12, AGX_SIZE_32));
agx_mov_to(b, agx_memory_register(0, AGX_SIZE_32),
agx_register(0, AGX_SIZE_32));
agx_mov_to(b, agx_register(0, AGX_SIZE_32),
agx_memory_register(1000, AGX_SIZE_32));
/* Stack swap: 32-bit */
agx_index temp1 = agx_register(0, AGX_SIZE_32);
agx_index temp2 = agx_register(2, AGX_SIZE_32);
agx_index spilled_gpr_vec2 = agx_register(0, AGX_SIZE_32);
agx_index scratch_vec2 = agx_memory_register(1000, AGX_SIZE_32);
spilled_gpr_vec2.channels_m1++;
scratch_vec2.channels_m1++;
agx_mov_to(b, scratch_vec2, spilled_gpr_vec2);
agx_mov_to(b, temp1, agx_memory_register(2, AGX_SIZE_32));
agx_mov_to(b, temp2, agx_memory_register(804, AGX_SIZE_32));
agx_mov_to(b, agx_memory_register(804, AGX_SIZE_32), temp1);
agx_mov_to(b, agx_memory_register(2, AGX_SIZE_32), temp2);
agx_mov_to(b, spilled_gpr_vec2, scratch_vec2);
/* Stack swap: 16-bit */
spilled_gpr_vec2.size = AGX_SIZE_16;
scratch_vec2.size = AGX_SIZE_16;
temp1.size = AGX_SIZE_16;
temp2.size = AGX_SIZE_16;
agx_mov_to(b, scratch_vec2, spilled_gpr_vec2);
agx_mov_to(b, temp1, agx_memory_register(807, AGX_SIZE_16));
agx_mov_to(b, temp2, agx_memory_register(808, AGX_SIZE_16));
agx_mov_to(b, agx_memory_register(808, AGX_SIZE_16), temp1);
agx_mov_to(b, agx_memory_register(807, AGX_SIZE_16), temp2);
agx_mov_to(b, spilled_gpr_vec2, scratch_vec2);
});
}
#if 0
TEST_F(LowerParallelCopy, LooksLikeASwap) {
struct agx_copy test[] = {
{ .dest = 0, .src = agx_register(2, AGX_SIZE_32) },
{ .dest = 2, .src = agx_register(0, AGX_SIZE_32) },
{ .dest = 4, .src = agx_register(2, AGX_SIZE_32) },
};
CASE(test, {
agx_mov_to(b, agx_register(4, AGX_SIZE_32), agx_register(2, AGX_SIZE_32));
agx_mov_to(b, agx_register(2, AGX_SIZE_32), agx_register(0, AGX_SIZE_32));
agx_mov_to(b, agx_register(0, AGX_SIZE_32), agx_register(4, AGX_SIZE_32));
});
}
#endif