mesa/src/intel/compiler/elk/elk_test_predicated_break.cpp
Caio Oliveira 6648e0ebd3 intel/elk: Rename symbols
Either replace the BRW prefix with ELK or add an extra ELK prefix.  Used
the following sed script to perform the renames in this patch:

```
    # Simple prefix changes.
    s/\<BRW_/ELK_/g
    s/\<brw_/elk_/g
    s/nir_to_brw/nir_to_elk/g
    s/\<as_brw_reg\>/as_elk_reg/g
    s/\<_brw_/_elk_/g

    # Add prefix to various symbols.
    #
    # Initially I've considered using C++ namespaces here, but in various
    # cases the structs or functions had to be also visible from C code.
    # So added explicit prefix instead.
    s/\<backend_instruction/elk_\0/g
    s/\<backend_reg/elk_\0/g
    s/\<backend_shader/elk_\0/g
    s/\<bblock_t\>/elk_\0/g
    s/\<bblock_link\>/elk_\0/g
    s/\<cfg_t\>/elk_\0/g
    s/\<fs_visitor\>/elk_\0/g
    s/\<fs_reg\>/elk_\0/g
    s/\<fs_instruction_scheduler\>/elk_\0/g
    s/\<vec4_instruction_scheduler\>/elk_\0/g
    s/\<instruction_scheduler\>/elk_\0/g
    s/\<schedule_node\>/elk_\0/g
    s/\<schedule_node_child\>/elk_\0/g
    s/\<\([a-z]*_\)\?thread_payload\>/elk_\1thread_payload/g
    s/\<fs_generator\>/elk_\0/g
    s/\<fs_inst\>/elk_\0/g
    s/\<fs_reg_alloc\>/elk_\0/g
    s/\<disasm_info\>/elk_\0/g
    s/\<gfx._math\>/elk_\0/g
    s/\<gfx7_block_read_scratch\>/elk_\0/g
    s/\<gfx6_IF\>/elk_\0/g
    s/\<gfx9_fb_READ\>/elk_\0/g
    s/\<gfx6_resolve_implied_move\>/elk_\0/g

    # Opcodes.
    s/\<opcode op\>/elk_\0/g
    s/\<opcode mov_op\>/elk_\0/g
    s/\<opcode opcode\>/elk_\0/g
    s/enum opcode\>/enum elk_opcode/g
    s/static opcode\>/static elk_opcode/g
    s/\<opcode elk_op/elk_opcode elk_op/g
    s/struct opcode_desc/struct elk_opcode_desc/g
    s/NUM_BRW_OPCODES/NUM_ELK_OPCODES/g
    s/\<.._OPCODE_/ELK_\0/g
    s/\<T.._OPCODE_/ELK_\0/g
    s/\<VEC4_OPCODE_/ELK_\0/g
    s/\<VEC4_...\?_OPCODE_/ELK_\0/g
    s/\<SHADER_OPCODE_/ELK_\0/g

    # Remaining specific cases.
    s/\<wm_prog_data_barycentric_modes\>/elk_\0/g
    s/\<encode_slm_size\>/elk_\0/g
    s/\<intel_calculate_slm_size\>/elk_\0/g
    s/\<gfx6_gather_sampler_wa\>/elk_\0/g
    s/\<is_3src\>/elk_\0/g
    s/\<WA_/ELK_\0/g
    s/\<conditional_modifier\>/elk_\0/g
    s/\<pred_ctrl_align16\>/elk_\0/g
    s/\<shuffle_from_32bit_read\>/elk_\0/g
    s/\<shuffle_src_to_dst\>/elk_\0/g
    s/\<setup_imm_..\?\>/elk_\0/g

    s/\<opt_predicated_break\>/elk_\0/g
    s/\<has_bank_conflict\>/elk_\0/g
    s/\<dead_control_flow_eliminate\>/elk_\0/g

    s/\<disasm_new_inst_group\>/elk_\0/g
    s/\<disasm_initialize\>/elk_\0/g
    s/\<dump_assembly\>/elk_\0/g
    s/\<disasm_insert_error\>/elk_\0/g
    s/\<disasm_annotate\>/elk_\0/g

    s/\<enum lsc_opcode\>/enum elk_lsc_opcode/g
    s/\<lsc_opcode_/elk_lsc_opcode_/g
    s/\<lsc_aop_[a-z_]\+\>/elk_\0/g

    s/\<type_size_vec4\>/elk_\0/g
    s/\<type_size_dvec4\>/elk_\0/g
    s/\<type_size_xvec4\>/elk_\0/g
    s/\<type_size_[a-z4]\+_bytes\>/elk_\0/g

    s/\<gfx12_systolic_depth\>/elk_\0/g
```

Acked-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27563>
2024-02-24 00:24:31 +00:00

340 lines
8.2 KiB
C++

/*
* Copyright (c) 2023 Intel Corporation
* SPDX-License-Identifier: MIT
*/
#include <gtest/gtest.h>
#include "elk_fs.h"
#include "elk_fs_builder.h"
#include "elk_cfg.h"
using namespace elk;
class PredicatedBreakTest : public ::testing::Test {
virtual void SetUp();
virtual void TearDown();
public:
bool debug;
void *mem_ctx;
elk_compiler compiler;
elk_compile_params params;
intel_device_info devinfo;
struct elk_wm_prog_data prog_data;
struct gl_shader_program *shader_prog;
elk_fs_visitor *shader_a;
elk_fs_visitor *shader_b;
bool elk_opt_predicated_break(elk_fs_visitor *s);
};
void
PredicatedBreakTest::SetUp()
{
debug = getenv("TEST_DEBUG");
mem_ctx = ralloc_context(NULL);
devinfo = {};
devinfo.ver = 9;
devinfo.verx10 = 90;
compiler = {};
compiler.devinfo = &devinfo;
elk_init_isa_info(&compiler.isa, &devinfo);
params = {};
params.mem_ctx = mem_ctx;
prog_data = {};
nir_shader *nir =
nir_shader_create(mem_ctx, MESA_SHADER_FRAGMENT, NULL, NULL);
shader_a = new elk_fs_visitor(&compiler, &params, NULL,
&prog_data.base, nir, 8, false, false);
shader_b = new elk_fs_visitor(&compiler, &params, NULL,
&prog_data.base, nir, 8, false, false);
}
void
PredicatedBreakTest::TearDown()
{
delete shader_a;
delete shader_b;
ralloc_free(mem_ctx);
mem_ctx = NULL;
}
bool
PredicatedBreakTest::elk_opt_predicated_break(elk_fs_visitor *s)
{
const bool print = getenv("TEST_DEBUG");
if (print) {
fprintf(stderr, "= Before =\n");
s->cfg->dump();
}
bool ret = ::elk_opt_predicated_break(s);
if (print) {
fprintf(stderr, "\n= After =\n");
s->cfg->dump();
}
return ret;
}
static fs_builder
make_builder(elk_fs_visitor *s)
{
return fs_builder(s, s->dispatch_width).at_end();
}
static testing::AssertionResult
shaders_match(const char *a_expr, const char *b_expr,
elk_fs_visitor *a, elk_fs_visitor *b)
{
/* Using the CFG string dump for this. Not ideal but it is
* convenient that covers some CFG information, helping to
* check if the optimization is keeping the CFG valid.
*/
char *a_str = NULL;
size_t a_size = 0;
FILE *a_file = open_memstream(&a_str, &a_size);
a->cfg->dump(a_file);
fclose(a_file);
char *b_str = NULL;
size_t b_size = 0;
FILE *b_file = open_memstream(&b_str, &b_size);
b->cfg->dump(b_file);
fclose(b_file);
if (a_size != b_size || strcmp(a_str, b_str) != 0) {
std::stringstream result;
result << "Shaders don't match.\n\n"
<< a_expr << " is:\n\n" << a_str
<< "\n---\n"
<< b_expr << " is:\n\n" << b_str
<< "\n";
free(a_str);
free(b_str);
return testing::AssertionFailure() << result.str();
}
free(a_str);
free(b_str);
return testing::AssertionSuccess();
}
#define ASSERT_SHADERS_MATCH(a, b) ASSERT_PRED_FORMAT2(shaders_match, a, b)
TEST_F(PredicatedBreakTest, TopBreakWithoutContinue)
{
fs_builder a = make_builder(shader_a);
fs_builder b = make_builder(shader_b);
elk_fs_reg r1 = elk_vec8_grf(1, 0);
elk_fs_reg r2 = elk_vec8_grf(2, 0);
elk_fs_reg r3 = elk_vec8_grf(3, 0);
a.DO();
a.CMP(r1, r2, r3, ELK_CONDITIONAL_NZ);
a.IF(ELK_PREDICATE_NORMAL);
a.BREAK();
a.ENDIF();
a.ADD(r1, r2, r3);
a.WHILE();
a.NOP(); /* There's always going to be something after a WHILE. */
shader_a->calculate_cfg();
/* The IF/ENDIF around the BREAK is expected to be removed. */
bool progress = elk_opt_predicated_break(shader_a);
EXPECT_TRUE(progress);
b.DO();
b.CMP(r1, r2, r3, ELK_CONDITIONAL_NZ);
b.BREAK()->predicate = ELK_PREDICATE_NORMAL;
b.ADD(r1, r2, r3);
b.WHILE();
b.NOP();
shader_b->calculate_cfg();
ASSERT_SHADERS_MATCH(shader_a, shader_b);
}
TEST_F(PredicatedBreakTest, TopBreakWithContinue)
{
fs_builder a = make_builder(shader_a);
fs_builder b = make_builder(shader_b);
elk_fs_reg r1 = elk_vec8_grf(1, 0);
elk_fs_reg r2 = elk_vec8_grf(2, 0);
elk_fs_reg r3 = elk_vec8_grf(3, 0);
a.DO();
a.CMP(r1, r2, r3, ELK_CONDITIONAL_NZ);
a.IF(ELK_PREDICATE_NORMAL);
a.BREAK();
a.ENDIF();
a.ADD(r1, r2, r3);
a.CMP(r1, r2, r3, ELK_CONDITIONAL_GE);
a.IF(ELK_PREDICATE_NORMAL);
a.CONTINUE();
a.ENDIF();
a.MUL(r1, r2, r3);
a.WHILE();
a.NOP(); /* There's always going to be something after a WHILE. */
shader_a->calculate_cfg();
/* The IF/ENDIF around the BREAK and the CONTINUE are expected to be
* removed.
*/
bool progress = elk_opt_predicated_break(shader_a);
EXPECT_TRUE(progress);
b.DO();
b.CMP(r1, r2, r3, ELK_CONDITIONAL_NZ);
b.BREAK()->predicate = ELK_PREDICATE_NORMAL;
b.ADD(r1, r2, r3);
b.CMP(r1, r2, r3, ELK_CONDITIONAL_GE);
b.CONTINUE()->predicate = ELK_PREDICATE_NORMAL;
b.MUL(r1, r2, r3);
b.WHILE();
b.NOP();
shader_b->calculate_cfg();
ASSERT_SHADERS_MATCH(shader_a, shader_b);
}
TEST_F(PredicatedBreakTest, DISABLED_BottomBreakWithoutContinue)
{
fs_builder a = make_builder(shader_a);
fs_builder b = make_builder(shader_b);
elk_fs_reg r1 = elk_vec8_grf(1, 0);
elk_fs_reg r2 = elk_vec8_grf(2, 0);
elk_fs_reg r3 = elk_vec8_grf(3, 0);
a.DO();
a.ADD(r1, r2, r3);
a.CMP(r1, r2, r3, ELK_CONDITIONAL_NZ);
a.IF(ELK_PREDICATE_NORMAL);
a.BREAK();
a.ENDIF();
a.WHILE();
a.NOP(); /* There's always going to be something after a WHILE. */
shader_a->calculate_cfg();
/* BREAK is the only way to exit the loop, so expect to remove the
* IF/BREAK/ENDIF and add a predicate to WHILE.
*/
bool progress = elk_opt_predicated_break(shader_a);
EXPECT_TRUE(progress);
b.DO();
b.ADD(r1, r2, r3);
b.CMP(r1, r2, r3, ELK_CONDITIONAL_NZ);
auto w = b.WHILE();
w->predicate = ELK_PREDICATE_NORMAL;
w->predicate_inverse = true;
b.NOP();
shader_b->calculate_cfg();
ASSERT_SHADERS_MATCH(shader_a, shader_b);
}
TEST_F(PredicatedBreakTest, BottomBreakWithContinue)
{
fs_builder a = make_builder(shader_a);
fs_builder b = make_builder(shader_b);
elk_fs_reg r1 = elk_vec8_grf(1, 0);
elk_fs_reg r2 = elk_vec8_grf(2, 0);
elk_fs_reg r3 = elk_vec8_grf(3, 0);
a.DO();
a.ADD(r1, r2, r3);
a.CMP(r1, r2, r3, ELK_CONDITIONAL_GE);
a.IF(ELK_PREDICATE_NORMAL);
a.CONTINUE();
a.ENDIF();
a.MUL(r1, r2, r3);
a.CMP(r1, r2, r3, ELK_CONDITIONAL_NZ);
a.IF(ELK_PREDICATE_NORMAL);
a.BREAK();
a.ENDIF();
a.WHILE();
a.NOP(); /* There's always going to be something after a WHILE. */
shader_a->calculate_cfg();
/* With a CONTINUE, the BREAK can't be removed, but still remove the
* IF/ENDIF around both of them.
*/
bool progress = elk_opt_predicated_break(shader_a);
EXPECT_TRUE(progress);
b.DO();
b.ADD(r1, r2, r3);
b.CMP(r1, r2, r3, ELK_CONDITIONAL_GE);
b.CONTINUE()->predicate = ELK_PREDICATE_NORMAL;
b.MUL(r1, r2, r3);
b.CMP(r1, r2, r3, ELK_CONDITIONAL_NZ);
b.BREAK()->predicate = ELK_PREDICATE_NORMAL;
b.WHILE();
b.NOP();
shader_b->calculate_cfg();
ASSERT_SHADERS_MATCH(shader_a, shader_b);
}
TEST_F(PredicatedBreakTest, TwoBreaks)
{
fs_builder a = make_builder(shader_a);
fs_builder b = make_builder(shader_b);
elk_fs_reg r1 = elk_vec8_grf(1, 0);
elk_fs_reg r2 = elk_vec8_grf(2, 0);
elk_fs_reg r3 = elk_vec8_grf(3, 0);
a.DO();
a.ADD(r1, r2, r3);
a.CMP(r1, r2, r3, ELK_CONDITIONAL_NZ);
a.IF(ELK_PREDICATE_NORMAL);
a.BREAK();
a.ENDIF();
a.MUL(r1, r2, r3);
a.CMP(r1, r2, r3, ELK_CONDITIONAL_GE);
a.IF(ELK_PREDICATE_NORMAL);
a.BREAK();
a.ENDIF();
a.AND(r1, r2, r3);
a.WHILE();
a.NOP(); /* There's always going to be something after a WHILE. */
shader_a->calculate_cfg();
/* The IF/ENDIF around the breaks are expected to be removed. */
bool progress = elk_opt_predicated_break(shader_a);
EXPECT_TRUE(progress);
b.DO();
b.ADD(r1, r2, r3);
b.CMP(r1, r2, r3, ELK_CONDITIONAL_NZ);
b.BREAK()->predicate = ELK_PREDICATE_NORMAL;
b.MUL(r1, r2, r3);
b.CMP(r1, r2, r3, ELK_CONDITIONAL_GE);
b.BREAK()->predicate = ELK_PREDICATE_NORMAL;
b.AND(r1, r2, r3);
b.WHILE();
b.NOP(); /* There's always going to be something after a WHILE. */
shader_b->calculate_cfg();
ASSERT_SHADERS_MATCH(shader_a, shader_b);
}