aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/intel/compiler/meson.build2
-rw-r--r--src/intel/compiler/test_fs_scoreboard.cpp863
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));
+}