| /* |
| * 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); |
| } |