mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 07:00:12 +01:00
When building the CFG the instructions are taken of the list in
fs_visitor and added to the lists inside each block. The single
"exec_node" in the instruction is used for those memberships.
In the case the pass rebuilt the CFG, it had no instructions, so
calculate_cfg() had nothing to work with. For now fix the bug by
pulling all the instructions back to the original list.
We can do better here, but punting until upcoming work on
CFG itself.
Issue found in an unpublished CTS test. Small reproduction in our
unit tests now enabled.
Fixes: 65237f8bbc ("intel/fs: Don't add MOV instructions to DO blocks in combine constants")
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27131>
130 lines
2.9 KiB
C++
130 lines
2.9 KiB
C++
/*
|
|
* Copyright (c) 2024 Intel Corporation
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include <gtest/gtest.h>
|
|
#include "brw_fs.h"
|
|
#include "brw_fs_builder.h"
|
|
#include "brw_cfg.h"
|
|
|
|
using namespace brw;
|
|
|
|
struct FSCombineConstantsTest : public ::testing::Test {
|
|
FSCombineConstantsTest() {
|
|
mem_ctx = ralloc_context(NULL);
|
|
|
|
devinfo = {};
|
|
devinfo.ver = 9;
|
|
devinfo.verx10 = 90;
|
|
|
|
compiler = {};
|
|
compiler.devinfo = &devinfo;
|
|
brw_init_isa_info(&compiler.isa, &devinfo);
|
|
|
|
params = {};
|
|
params.mem_ctx = mem_ctx;
|
|
|
|
prog_data = {};
|
|
nir_shader *nir =
|
|
nir_shader_create(mem_ctx, MESA_SHADER_COMPUTE, NULL, NULL);
|
|
|
|
shader = new fs_visitor(&compiler, ¶ms, NULL,
|
|
&prog_data.base, nir, 8, false, false);
|
|
}
|
|
|
|
~FSCombineConstantsTest() override {
|
|
delete shader;
|
|
ralloc_free(mem_ctx);
|
|
mem_ctx = NULL;
|
|
}
|
|
|
|
void *mem_ctx;
|
|
brw_compiler compiler;
|
|
brw_compile_params params;
|
|
intel_device_info devinfo;
|
|
struct brw_wm_prog_data prog_data;
|
|
struct gl_shader_program *shader_prog;
|
|
|
|
fs_visitor *shader;
|
|
|
|
bool opt_combine_constants(fs_visitor *s) {
|
|
const bool print = getenv("TEST_DEBUG");
|
|
|
|
if (print) {
|
|
fprintf(stderr, "= Before =\n");
|
|
s->cfg->dump();
|
|
}
|
|
|
|
bool ret = s->opt_combine_constants();
|
|
|
|
if (print) {
|
|
fprintf(stderr, "\n= After =\n");
|
|
s->cfg->dump();
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
};
|
|
|
|
static fs_builder
|
|
make_builder(fs_visitor *s)
|
|
{
|
|
return fs_builder(s, s->dispatch_width).at_end();
|
|
}
|
|
|
|
TEST_F(FSCombineConstantsTest, Simple)
|
|
{
|
|
fs_builder bld = make_builder(shader);
|
|
|
|
fs_reg r = brw_vec8_grf(1, 0);
|
|
fs_reg imm_a = brw_imm_ud(1);
|
|
fs_reg imm_b = brw_imm_ud(2);
|
|
|
|
bld.SEL(r, imm_a, imm_b);
|
|
shader->calculate_cfg();
|
|
|
|
bool progress = opt_combine_constants(shader);
|
|
ASSERT_TRUE(progress);
|
|
|
|
ASSERT_EQ(shader->cfg->num_blocks, 1);
|
|
bblock_t *block = cfg_first_block(shader->cfg);
|
|
ASSERT_NE(block, nullptr);
|
|
|
|
/* We can do better but for now sanity check that
|
|
* there's a MOV and a SEL.
|
|
*/
|
|
ASSERT_EQ(bblock_start(block)->opcode, BRW_OPCODE_MOV);
|
|
ASSERT_EQ(bblock_end(block)->opcode, BRW_OPCODE_SEL);
|
|
}
|
|
|
|
TEST_F(FSCombineConstantsTest, DoContainingDo)
|
|
{
|
|
fs_builder bld = make_builder(shader);
|
|
|
|
fs_reg r1 = brw_vec8_grf(1, 0);
|
|
fs_reg r2 = brw_vec8_grf(2, 0);
|
|
fs_reg imm_a = brw_imm_ud(1);
|
|
fs_reg imm_b = brw_imm_ud(2);
|
|
|
|
bld.DO();
|
|
bld.DO();
|
|
bld.SEL(r1, imm_a, imm_b);
|
|
bld.WHILE();
|
|
bld.WHILE();
|
|
bld.SEL(r2, imm_a, imm_b);
|
|
shader->calculate_cfg();
|
|
|
|
unsigned original_num_blocks = shader->cfg->num_blocks;
|
|
|
|
bool progress = opt_combine_constants(shader);
|
|
ASSERT_TRUE(progress);
|
|
|
|
/* We can do better but for now sanity check there's
|
|
* enough blocks, since the original issue motivating this
|
|
* test is that the shader would be empty.
|
|
*/
|
|
ASSERT_GE(shader->cfg->num_blocks, original_num_blocks);
|
|
shader->validate();
|
|
}
|
|
|