blob: bb776b32b52a5104a8fee9addb63660bb2337f83 [file] [log] [blame]
/*
* Copyright © 2025 Intel Corporation
* SPDX-License-Identifier: MIT
*/
#include "test_helpers.h"
#include "brw_builder.h"
std::string
brw_shader_to_string(brw_shader *s)
{
if (!s->cfg)
brw_calculate_cfg(*s);
char *str = NULL;
size_t size = 0;
FILE *f = open_memstream(&str, &size);
brw_print_instructions(*s, f);
fclose(f);
std::string result(str);
free(str);
return result;
}
void
brw_reindex_vgrfs(brw_shader *s)
{
struct Entry {
int new_nr;
int size;
bool valid;
};
unsigned next_nr = 0;
Entry *map = rzalloc_array(NULL, Entry, s->alloc.count);
/* Build map and update references to VGRFs instructions as
* they are seen. First destination then sources.
*/
foreach_block_and_inst(block, brw_inst, inst, s->cfg) {
if (inst->dst.file == VGRF) {
Entry &entry = map[inst->dst.nr];
if (!entry.valid) {
entry.new_nr = next_nr++;
entry.size = s->alloc.sizes[inst->dst.nr];
entry.valid = true;
}
inst->dst.nr = entry.new_nr;
}
for (int i = 0; i < inst->sources; i++) {
if (inst->src[i].file == VGRF) {
Entry &entry = map[inst->src[i].nr];
if (!entry.valid) {
entry.new_nr = next_nr++;
entry.size = s->alloc.sizes[inst->src[i].nr];
entry.valid = true;
}
inst->src[i].nr = entry.new_nr;
}
}
}
/* Move unused entries to the end. */
for (unsigned i = 0; i < s->alloc.count; i++) {
Entry &entry = map[i];
if (!entry.valid) {
entry.new_nr = next_nr++;
entry.size = s->alloc.sizes[i];
entry.valid = true;
}
}
assert(next_nr == s->alloc.count);
/* Update sizes. */
for (unsigned i = 0; i < s->alloc.count; i++)
s->alloc.sizes[map[i].new_nr] = map[i].size;
ralloc_free(map);
s->invalidate_analysis(BRW_DEPENDENCY_VARIABLES);
}
void
EXPECT_SHADERS_MATCH(brw_shader *a, brw_shader *b)
{
if (!a->cfg)
brw_calculate_cfg(*a);
if (!b->cfg)
brw_calculate_cfg(*b);
brw_validate(*a);
brw_validate(*b);
brw_reindex_vgrfs(a);
brw_reindex_vgrfs(b);
std::string sa = brw_shader_to_string(a);
std::string sb = brw_shader_to_string(b);
EXPECT_EQ(sa, sb);
}
class TestHelpers : public brw_shader_pass_test {};
TEST_F(TestHelpers, ReindexVGRFsDestinations)
{
brw_builder bld = make_shader();
brw_reg d = bld.vgrf(BRW_TYPE_UD);
brw_reg c = bld.vgrf(BRW_TYPE_UD);
brw_reg b = bld.vgrf(BRW_TYPE_UD);
brw_reg a = bld.vgrf(BRW_TYPE_UD);
brw_inst *mov_a = bld.MOV(a, brw_vec8_grf(0, 0));
brw_inst *mov_b = bld.MOV(b, a);
brw_inst *mov_c = bld.MOV(c, b);
brw_inst *add_d = bld.ADD(d, a, b);
EXPECT_EQ(mov_a->dst.nr, 3);
EXPECT_EQ(mov_b->dst.nr, 2);
EXPECT_EQ(mov_c->dst.nr, 1);
EXPECT_EQ(add_d->dst.nr, 0);
brw_calculate_cfg(*bld.shader);
brw_reindex_vgrfs(bld.shader);
EXPECT_EQ(mov_a->dst.nr, 0);
EXPECT_EQ(mov_b->dst.nr, 1);
EXPECT_EQ(mov_c->dst.nr, 2);
EXPECT_EQ(add_d->dst.nr, 3);
}
TEST_F(TestHelpers, ReindexVGRFsSources)
{
brw_builder bld = make_shader();
brw_reg d = bld.vgrf(BRW_TYPE_UD);
brw_reg c = bld.vgrf(BRW_TYPE_UD);
brw_reg b = bld.vgrf(BRW_TYPE_UD);
brw_reg a = bld.vgrf(BRW_TYPE_UD);
brw_inst *mov_a = bld.MOV(brw_vec8_grf(0, 0), a);
brw_inst *mov_b = bld.MOV(brw_vec8_grf(7, 0), b);
brw_inst *add_cd = bld.ADD(brw_vec8_grf(14, 0), c, d);
EXPECT_EQ(mov_a->src[0].nr, 3);
EXPECT_EQ(mov_b->src[0].nr, 2);
EXPECT_EQ(add_cd->src[0].nr, 1);
EXPECT_EQ(add_cd->src[1].nr, 0);
brw_calculate_cfg(*bld.shader);
brw_reindex_vgrfs(bld.shader);
EXPECT_EQ(mov_a->src[0].nr, 0);
EXPECT_EQ(mov_b->src[0].nr, 1);
EXPECT_EQ(add_cd->src[0].nr, 2);
EXPECT_EQ(add_cd->src[1].nr, 3);
}
TEST_F(TestHelpers, ReindexVGRFsIncludesSizes)
{
brw_builder bld = make_shader();
brw_reg d = bld.vgrf(BRW_TYPE_UD, 1);
brw_reg c = bld.vgrf(BRW_TYPE_UD, 6);
brw_reg b = bld.vgrf(BRW_TYPE_UD, 8);
brw_reg a = bld.vgrf(BRW_TYPE_UD, 2);
brw_inst *mov_a = bld.MOV(a, brw_imm_d(2222));
brw_inst *mov_b = bld.MOV(b, brw_imm_d(8888));
brw_inst *mov_c = bld.MOV(c, brw_imm_d(6666));
brw_inst *mov_d = bld.MOV(d, brw_imm_d(1111));
EXPECT_EQ(mov_a->dst.nr, 3);
EXPECT_EQ(mov_b->dst.nr, 2);
EXPECT_EQ(mov_c->dst.nr, 1);
EXPECT_EQ(mov_d->dst.nr, 0);
brw_calculate_cfg(*bld.shader);
brw_reindex_vgrfs(bld.shader);
EXPECT_EQ(mov_a->dst.nr, 0);
EXPECT_EQ(mov_b->dst.nr, 1);
EXPECT_EQ(mov_c->dst.nr, 2);
EXPECT_EQ(mov_d->dst.nr, 3);
brw_shader *s = bld.shader;
EXPECT_EQ(s->alloc.count, 4);
EXPECT_EQ(s->alloc.sizes[0], 2);
EXPECT_EQ(s->alloc.sizes[1], 8);
EXPECT_EQ(s->alloc.sizes[2], 6);
EXPECT_EQ(s->alloc.sizes[3], 1);
}
TEST_F(TestHelpers, ReindexVGRFsUnusedAreMovedToTheEnd)
{
brw_builder bld = make_shader();
brw_reg a = bld.vgrf(BRW_TYPE_UD, 4);
UNUSED brw_reg b = bld.vgrf(BRW_TYPE_UD, 6);
brw_reg c = bld.vgrf(BRW_TYPE_UD, 8);
brw_inst *add = bld.ADD(a, a, c);
brw_calculate_cfg(*bld.shader);
brw_reindex_vgrfs(bld.shader);
EXPECT_EQ(add->src[0].nr, 0);
EXPECT_EQ(add->src[1].nr, 1);
brw_shader *s = bld.shader;
EXPECT_EQ(s->alloc.count, 3);
EXPECT_EQ(s->alloc.sizes[0], 4);
EXPECT_EQ(s->alloc.sizes[1], 8);
EXPECT_EQ(s->alloc.sizes[2], 6);
}
TEST_F(TestHelpers, MatchShadersSameStructureDifferentNumbers)
{
brw_builder a = make_shader();
brw_builder b = make_shader();
int nr_from_a;
int nr_from_b;
/* Build using the builder automatic allocations. */
{
brw_inst *add = NULL;
brw_reg src0 = a.MOV(brw_ud8_grf(1, 0));
brw_reg src1 = a.MOV(brw_ud8_grf(7, 0));
a.ADD(src0, src1, &add);
EXPECT_EQ(add->dst.file, VGRF);
nr_from_a = add->dst.nr;
}
/* Build using explicitly created VGRFs. */
{
brw_reg dst = b.vgrf(BRW_TYPE_UD);
brw_reg src0 = b.vgrf(BRW_TYPE_UD);
brw_reg src1 = b.vgrf(BRW_TYPE_UD);
b.MOV(src0, brw_ud8_grf(1, 0));
b.MOV(src1, brw_ud8_grf(7, 0));
b.ADD(dst, src0, src1);
nr_from_b = dst.nr;
}
EXPECT_NE(nr_from_a, nr_from_b);
EXPECT_SHADERS_MATCH(a, b);
}