diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/intel/compiler/meson.build | 2 | ||||
-rw-r--r-- | src/intel/compiler/test_fs_scoreboard.cpp | 863 |
2 files changed, 864 insertions, 1 deletions
diff --git a/src/intel/compiler/meson.build b/src/intel/compiler/meson.build index 0a782fa70f1..2d938bc48b2 100644 --- a/src/intel/compiler/meson.build +++ b/src/intel/compiler/meson.build @@ -148,7 +148,7 @@ if with_tests 'fs_saturate_propagation', 'vf_float_conversions', 'vec4_register_coalesce', 'vec4_copy_propagation', 'vec4_cmod_propagation', 'vec4_dead_code_eliminate', - 'eu_compact', 'eu_validate'] + 'eu_compact', 'eu_validate', 'fs_scoreboard'] test( t, executable( diff --git a/src/intel/compiler/test_fs_scoreboard.cpp b/src/intel/compiler/test_fs_scoreboard.cpp new file mode 100644 index 00000000000..4c6acfaf201 --- /dev/null +++ b/src/intel/compiler/test_fs_scoreboard.cpp @@ -0,0 +1,863 @@ +/* + * Copyright © 2019 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include <gtest/gtest.h> +#include "brw_fs.h" +#include "brw_cfg.h" +#include "program/program.h" + +using namespace brw; + +class scoreboard_test : public ::testing::Test { + virtual void SetUp(); + +public: + struct brw_compiler *compiler; + struct gen_device_info *devinfo; + struct gl_context *ctx; + struct brw_wm_prog_data *prog_data; + struct gl_shader_program *shader_prog; + fs_visitor *v; +}; + +void scoreboard_test::SetUp() +{ + ctx = (struct gl_context *)calloc(1, sizeof(*ctx)); + compiler = (struct brw_compiler *)calloc(1, sizeof(*compiler)); + devinfo = (struct gen_device_info *)calloc(1, sizeof(*devinfo)); + compiler->devinfo = devinfo; + + prog_data = ralloc(NULL, struct brw_wm_prog_data); + nir_shader *shader = + nir_shader_create(NULL, MESA_SHADER_FRAGMENT, NULL, NULL); + + v = new fs_visitor(compiler, NULL, NULL, NULL, &prog_data->base, shader, 8, -1); + + devinfo->gen = 12; +} + +static fs_inst * +instruction(bblock_t *block, int num) +{ + fs_inst *inst = (fs_inst *)block->start(); + for (int i = 0; i < num; i++) { + inst = (fs_inst *)inst->next; + } + return inst; +} + +static void +lower_scoreboard(fs_visitor *v) +{ + const bool print = getenv("TEST_DEBUG"); + + if (print) { + fprintf(stderr, "= Before =\n"); + v->cfg->dump(v); + } + + v->lower_scoreboard(); + + if (print) { + fprintf(stderr, "\n= After =\n"); + v->cfg->dump(v); + } +} + +fs_inst * +emit_SEND(const fs_builder &bld, const fs_reg &dst, + const fs_reg &desc, const fs_reg &payload) +{ + fs_inst *inst = bld.emit(SHADER_OPCODE_SEND, dst, desc, desc, payload); + inst->mlen = 1; + return inst; +} + +bool operator ==(const tgl_swsb &a, const tgl_swsb &b) +{ + return a.mode == b.mode && + a.regdist == b.regdist && + (a.mode == TGL_SBID_NULL || a.sbid == b.sbid); +} + +std::ostream &operator<<(std::ostream &os, const tgl_swsb &swsb) { + if (swsb.regdist) + os << "@" << swsb.regdist; + + if (swsb.mode) { + if (swsb.regdist) + os << " "; + os << "$" << swsb.sbid; + if (swsb.mode & TGL_SBID_DST) + os << ".dst"; + if (swsb.mode & TGL_SBID_SRC) + os << ".src"; + } + + return os; +} + +TEST_F(scoreboard_test, RAW_inorder_inorder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + fs_reg y = v->vgrf(glsl_type::int_type); + bld.ADD( x, g[1], g[2]); + bld.MUL( y, g[3], g[4]); + bld.AND(g[5], x, y); + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_regdist(1)); +} + +TEST_F(scoreboard_test, RAW_inorder_outoforder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.ADD( x, g[1], g[2]); + bld.MUL( g[3], g[4], g[5]); + emit_SEND(bld, g[6], g[7], x); + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 2)->sched, + (tgl_swsb { .regdist = 2, .sbid = 0, .mode = TGL_SBID_SET })); +} + +TEST_F(scoreboard_test, RAW_outoforder_inorder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + fs_reg y = v->vgrf(glsl_type::int_type); + emit_SEND(bld, x, g[1], g[2]); + bld.MUL( y, g[3], g[4]); + bld.AND( g[5], x, y); + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0)); + EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 2)->sched, + (tgl_swsb { .regdist = 1, .sbid = 0, .mode = TGL_SBID_DST })); +} + +TEST_F(scoreboard_test, RAW_outoforder_outoforder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + /* The second SEND depends on the first, and would need to refer to two + * SBIDs. Since it is not possible we expect a SYNC instruction to be + * added. + */ + fs_reg x = v->vgrf(glsl_type::int_type); + emit_SEND(bld, x, g[1], g[2]); + emit_SEND(bld, g[3], x, g[4])->sfid++; + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(1, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0)); + + fs_inst *sync = instruction(block0, 1); + EXPECT_EQ(sync->opcode, BRW_OPCODE_SYNC); + EXPECT_EQ(sync->sched, tgl_swsb_sbid(TGL_SBID_DST, 0)); + + EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_sbid(TGL_SBID_SET, 1)); +} + +TEST_F(scoreboard_test, WAR_inorder_inorder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.ADD(g[1], x, g[2]); + bld.MUL(g[3], g[4], g[5]); + bld.AND( x, g[6], g[7]); + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_null()); +} + +TEST_F(scoreboard_test, WAR_inorder_outoforder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.ADD( g[1], x, g[2]); + bld.MUL( g[3], g[4], g[5]); + emit_SEND(bld, x, g[6], g[7]); + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 2)->sched, + (tgl_swsb { .regdist = 2, .sbid = 0, .mode = TGL_SBID_SET })); +} + +TEST_F(scoreboard_test, WAR_outoforder_inorder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + emit_SEND(bld, g[1], g[2], x); + bld.MUL( g[4], g[5], g[6]); + bld.AND( x, g[7], g[8]); + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0)); + EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_sbid(TGL_SBID_SRC, 0)); +} + +TEST_F(scoreboard_test, WAR_outoforder_outoforder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + emit_SEND(bld, g[1], g[2], x); + emit_SEND(bld, x, g[3], g[4])->sfid++; + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(1, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0)); + + fs_inst *sync = instruction(block0, 1); + EXPECT_EQ(sync->opcode, BRW_OPCODE_SYNC); + EXPECT_EQ(sync->sched, tgl_swsb_sbid(TGL_SBID_SRC, 0)); + + EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_sbid(TGL_SBID_SET, 1)); +} + +TEST_F(scoreboard_test, WAW_inorder_inorder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.ADD( x, g[1], g[2]); + bld.MUL(g[3], g[4], g[5]); + bld.AND( x, g[6], g[7]); + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null()); + + /* NOTE: We only need this RegDist if a long instruction is followed by a + * short one. The pass is currently conservative about this and adding the + * annotation. + */ + EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_regdist(2)); +} + +TEST_F(scoreboard_test, WAW_inorder_outoforder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.ADD( x, g[1], g[2]); + bld.MUL( g[3], g[4], g[5]); + emit_SEND(bld, x, g[6], g[7]); + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 2)->sched, + (tgl_swsb { .regdist = 2, .sbid = 0, .mode = TGL_SBID_SET })); +} + +TEST_F(scoreboard_test, WAW_outoforder_inorder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + emit_SEND(bld, x, g[1], g[2]); + bld.MUL( g[3], g[4], g[5]); + bld.AND( x, g[6], g[7]); + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0)); + EXPECT_EQ(instruction(block0, 1)->sched, tgl_swsb_null()); + EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_sbid(TGL_SBID_DST, 0)); +} + +TEST_F(scoreboard_test, WAW_outoforder_outoforder) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + emit_SEND(bld, x, g[1], g[2]); + emit_SEND(bld, x, g[3], g[4])->sfid++; + + v->calculate_cfg(); + bblock_t *block0 = v->cfg->blocks[0]; + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(1, block0->end_ip); + + lower_scoreboard(v); + ASSERT_EQ(0, block0->start_ip); + ASSERT_EQ(2, block0->end_ip); + + EXPECT_EQ(instruction(block0, 0)->sched, tgl_swsb_sbid(TGL_SBID_SET, 0)); + + fs_inst *sync = instruction(block0, 1); + EXPECT_EQ(sync->opcode, BRW_OPCODE_SYNC); + EXPECT_EQ(sync->sched, tgl_swsb_sbid(TGL_SBID_DST, 0)); + + EXPECT_EQ(instruction(block0, 2)->sched, tgl_swsb_sbid(TGL_SBID_SET, 1)); +} + + +TEST_F(scoreboard_test, loop1) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.XOR( x, g[1], g[2]); + + bld.emit(BRW_OPCODE_DO); + + bld.ADD( x, g[1], g[2]); + bld.emit(BRW_OPCODE_WHILE)->predicate = BRW_PREDICATE_NORMAL; + + bld.MUL( x, g[1], g[2]); + + v->calculate_cfg(); + lower_scoreboard(v); + + bblock_t *body = v->cfg->blocks[2]; + fs_inst *add = instruction(body, 0); + EXPECT_EQ(add->opcode, BRW_OPCODE_ADD); + EXPECT_EQ(add->sched, tgl_swsb_regdist(1)); + + bblock_t *last_block = v->cfg->blocks[3]; + fs_inst *mul = instruction(last_block, 0); + EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL); + EXPECT_EQ(mul->sched, tgl_swsb_regdist(1)); +} + +TEST_F(scoreboard_test, loop2) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.XOR( x, g[1], g[2]); + bld.XOR(g[3], g[1], g[2]); + bld.XOR(g[4], g[1], g[2]); + bld.XOR(g[5], g[1], g[2]); + + bld.emit(BRW_OPCODE_DO); + + bld.ADD( x, g[1], g[2]); + bld.emit(BRW_OPCODE_WHILE)->predicate = BRW_PREDICATE_NORMAL; + + bld.MUL( x, g[1], g[2]); + + v->calculate_cfg(); + lower_scoreboard(v); + + /* Now the write in ADD has the tightest RegDist for both ADD and MUL. */ + + bblock_t *body = v->cfg->blocks[2]; + fs_inst *add = instruction(body, 0); + EXPECT_EQ(add->opcode, BRW_OPCODE_ADD); + EXPECT_EQ(add->sched, tgl_swsb_regdist(2)); + + bblock_t *last_block = v->cfg->blocks[3]; + fs_inst *mul = instruction(last_block, 0); + EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL); + EXPECT_EQ(mul->sched, tgl_swsb_regdist(2)); +} + +TEST_F(scoreboard_test, loop3) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.XOR( x, g[1], g[2]); + + bld.emit(BRW_OPCODE_DO); + + /* For the ADD in the loop body this extra distance will always apply. */ + bld.XOR(g[3], g[1], g[2]); + bld.XOR(g[4], g[1], g[2]); + bld.XOR(g[5], g[1], g[2]); + bld.XOR(g[6], g[1], g[2]); + + bld.ADD( x, g[1], g[2]); + bld.emit(BRW_OPCODE_WHILE)->predicate = BRW_PREDICATE_NORMAL; + + bld.MUL( x, g[1], g[2]); + + v->calculate_cfg(); + lower_scoreboard(v); + + bblock_t *body = v->cfg->blocks[2]; + fs_inst *add = instruction(body, 4); + EXPECT_EQ(add->opcode, BRW_OPCODE_ADD); + EXPECT_EQ(add->sched, tgl_swsb_regdist(5)); + + bblock_t *last_block = v->cfg->blocks[3]; + fs_inst *mul = instruction(last_block, 0); + EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL); + EXPECT_EQ(mul->sched, tgl_swsb_regdist(1)); +} + + +TEST_F(scoreboard_test, conditional1) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.XOR( x, g[1], g[2]); + bld.emit(BRW_OPCODE_IF); + + bld.ADD( x, g[1], g[2]); + + bld.emit(BRW_OPCODE_ENDIF); + bld.MUL( x, g[1], g[2]); + + v->calculate_cfg(); + lower_scoreboard(v); + + bblock_t *body = v->cfg->blocks[1]; + fs_inst *add = instruction(body, 0); + EXPECT_EQ(add->opcode, BRW_OPCODE_ADD); + EXPECT_EQ(add->sched, tgl_swsb_regdist(2)); + + bblock_t *last_block = v->cfg->blocks[2]; + fs_inst *mul = instruction(last_block, 1); + EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL); + EXPECT_EQ(mul->sched, tgl_swsb_regdist(2)); +} + +TEST_F(scoreboard_test, conditional2) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.XOR( x, g[1], g[2]); + bld.XOR(g[3], g[1], g[2]); + bld.XOR(g[4], g[1], g[2]); + bld.XOR(g[5], g[1], g[2]); + bld.emit(BRW_OPCODE_IF); + + bld.ADD( x, g[1], g[2]); + + bld.emit(BRW_OPCODE_ENDIF); + bld.MUL( x, g[1], g[2]); + + v->calculate_cfg(); + lower_scoreboard(v); + + bblock_t *body = v->cfg->blocks[1]; + fs_inst *add = instruction(body, 0); + EXPECT_EQ(add->opcode, BRW_OPCODE_ADD); + EXPECT_EQ(add->sched, tgl_swsb_regdist(5)); + + bblock_t *last_block = v->cfg->blocks[2]; + fs_inst *mul = instruction(last_block, 1); + EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL); + EXPECT_EQ(mul->sched, tgl_swsb_regdist(2)); +} + +TEST_F(scoreboard_test, conditional3) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.XOR( x, g[1], g[2]); + bld.emit(BRW_OPCODE_IF); + + bld.XOR(g[3], g[1], g[2]); + bld.XOR(g[4], g[1], g[2]); + bld.XOR(g[5], g[1], g[2]); + bld.ADD( x, g[1], g[2]); + + bld.emit(BRW_OPCODE_ENDIF); + bld.MUL( x, g[1], g[2]); + + v->calculate_cfg(); + lower_scoreboard(v); + + bblock_t *body = v->cfg->blocks[1]; + fs_inst *add = instruction(body, 3); + EXPECT_EQ(add->opcode, BRW_OPCODE_ADD); + EXPECT_EQ(add->sched, tgl_swsb_regdist(5)); + + bblock_t *last_block = v->cfg->blocks[2]; + fs_inst *mul = instruction(last_block, 1); + EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL); + EXPECT_EQ(mul->sched, tgl_swsb_regdist(2)); +} + +TEST_F(scoreboard_test, conditional4) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.XOR( x, g[1], g[2]); + bld.emit(BRW_OPCODE_IF); + + bld.ADD( x, g[1], g[2]); + bld.XOR(g[3], g[1], g[2]); + bld.XOR(g[4], g[1], g[2]); + bld.XOR(g[5], g[1], g[2]); + + bld.emit(BRW_OPCODE_ENDIF); + bld.MUL( x, g[1], g[2]); + + v->calculate_cfg(); + lower_scoreboard(v); + + bblock_t *body = v->cfg->blocks[1]; + fs_inst *add = instruction(body, 0); + EXPECT_EQ(add->opcode, BRW_OPCODE_ADD); + EXPECT_EQ(add->sched, tgl_swsb_regdist(2)); + + bblock_t *last_block = v->cfg->blocks[2]; + fs_inst *mul = instruction(last_block, 1); + EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL); + EXPECT_EQ(mul->sched, tgl_swsb_regdist(3)); +} + +TEST_F(scoreboard_test, conditional5) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.XOR( x, g[1], g[2]); + bld.emit(BRW_OPCODE_IF); + + bld.ADD( x, g[1], g[2]); + bld.emit(BRW_OPCODE_ELSE); + + bld.ROL( x, g[1], g[2]); + + bld.emit(BRW_OPCODE_ENDIF); + bld.MUL( x, g[1], g[2]); + + v->calculate_cfg(); + lower_scoreboard(v); + + bblock_t *then_body = v->cfg->blocks[1]; + fs_inst *add = instruction(then_body, 0); + EXPECT_EQ(add->opcode, BRW_OPCODE_ADD); + EXPECT_EQ(add->sched, tgl_swsb_regdist(2)); + + bblock_t *else_body = v->cfg->blocks[2]; + fs_inst *rol = instruction(else_body, 0); + EXPECT_EQ(rol->opcode, BRW_OPCODE_ROL); + EXPECT_EQ(rol->sched, tgl_swsb_regdist(2)); + + bblock_t *last_block = v->cfg->blocks[3]; + fs_inst *mul = instruction(last_block, 1); + EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL); + EXPECT_EQ(mul->sched, tgl_swsb_regdist(2)); +} + +TEST_F(scoreboard_test, conditional6) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.XOR( x, g[1], g[2]); + bld.emit(BRW_OPCODE_IF); + + bld.XOR(g[3], g[1], g[2]); + bld.XOR(g[4], g[1], g[2]); + bld.XOR(g[5], g[1], g[2]); + bld.ADD( x, g[1], g[2]); + bld.emit(BRW_OPCODE_ELSE); + + bld.XOR(g[6], g[1], g[2]); + bld.XOR(g[7], g[1], g[2]); + bld.XOR(g[8], g[1], g[2]); + bld.XOR(g[9], g[1], g[2]); + bld.ROL( x, g[1], g[2]); + + bld.emit(BRW_OPCODE_ENDIF); + bld.MUL( x, g[1], g[2]); + + v->calculate_cfg(); + lower_scoreboard(v); + + bblock_t *then_body = v->cfg->blocks[1]; + fs_inst *add = instruction(then_body, 3); + EXPECT_EQ(add->opcode, BRW_OPCODE_ADD); + EXPECT_EQ(add->sched, tgl_swsb_regdist(5)); + + bblock_t *else_body = v->cfg->blocks[2]; + fs_inst *rol = instruction(else_body, 4); + EXPECT_EQ(rol->opcode, BRW_OPCODE_ROL); + EXPECT_EQ(rol->sched, tgl_swsb_regdist(6)); + + bblock_t *last_block = v->cfg->blocks[3]; + fs_inst *mul = instruction(last_block, 1); + EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL); + EXPECT_EQ(mul->sched, tgl_swsb_regdist(2)); +} + +TEST_F(scoreboard_test, conditional7) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.XOR( x, g[1], g[2]); + bld.emit(BRW_OPCODE_IF); + + bld.ADD( x, g[1], g[2]); + bld.XOR(g[3], g[1], g[2]); + bld.XOR(g[4], g[1], g[2]); + bld.XOR(g[5], g[1], g[2]); + bld.emit(BRW_OPCODE_ELSE); + + bld.ROL( x, g[1], g[2]); + bld.XOR(g[6], g[1], g[2]); + bld.XOR(g[7], g[1], g[2]); + bld.XOR(g[8], g[1], g[2]); + bld.XOR(g[9], g[1], g[2]); + + bld.emit(BRW_OPCODE_ENDIF); + bld.MUL( x, g[1], g[2]); + + v->calculate_cfg(); + lower_scoreboard(v); + + bblock_t *then_body = v->cfg->blocks[1]; + fs_inst *add = instruction(then_body, 0); + EXPECT_EQ(add->opcode, BRW_OPCODE_ADD); + EXPECT_EQ(add->sched, tgl_swsb_regdist(2)); + + bblock_t *else_body = v->cfg->blocks[2]; + fs_inst *rol = instruction(else_body, 0); + EXPECT_EQ(rol->opcode, BRW_OPCODE_ROL); + EXPECT_EQ(rol->sched, tgl_swsb_regdist(2)); + + bblock_t *last_block = v->cfg->blocks[3]; + fs_inst *mul = instruction(last_block, 1); + EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL); + EXPECT_EQ(mul->sched, tgl_swsb_regdist(6)); +} + +TEST_F(scoreboard_test, conditional8) +{ + const fs_builder &bld = v->bld; + fs_reg g[16]; + for (unsigned i = 0; i < ARRAY_SIZE(g); i++) + g[i] = v->vgrf(glsl_type::int_type); + + fs_reg x = v->vgrf(glsl_type::int_type); + bld.XOR( x, g[1], g[2]); + bld.XOR(g[3], g[1], g[2]); + bld.XOR(g[4], g[1], g[2]); + bld.XOR(g[5], g[1], g[2]); + bld.XOR(g[6], g[1], g[2]); + bld.XOR(g[7], g[1], g[2]); + bld.emit(BRW_OPCODE_IF); + + bld.ADD( x, g[1], g[2]); + bld.emit(BRW_OPCODE_ELSE); + + bld.ROL( x, g[1], g[2]); + + bld.emit(BRW_OPCODE_ENDIF); + bld.MUL( x, g[1], g[2]); + + v->calculate_cfg(); + lower_scoreboard(v); + + bblock_t *then_body = v->cfg->blocks[1]; + fs_inst *add = instruction(then_body, 0); + EXPECT_EQ(add->opcode, BRW_OPCODE_ADD); + EXPECT_EQ(add->sched, tgl_swsb_regdist(7)); + + /* Note that the ROL will have RegDist 2 and not 7, illustrating the + * physical CFG edge between the then-block and the else-block. + */ + bblock_t *else_body = v->cfg->blocks[2]; + fs_inst *rol = instruction(else_body, 0); + EXPECT_EQ(rol->opcode, BRW_OPCODE_ROL); + EXPECT_EQ(rol->sched, tgl_swsb_regdist(2)); + + bblock_t *last_block = v->cfg->blocks[3]; + fs_inst *mul = instruction(last_block, 1); + EXPECT_EQ(mul->opcode, BRW_OPCODE_MUL); + EXPECT_EQ(mul->sched, tgl_swsb_regdist(2)); +} |