| /* |
| * 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(); |
| virtual void TearDown(); |
| |
| public: |
| struct brw_compiler *compiler; |
| struct gen_device_info *devinfo; |
| void *ctx; |
| struct brw_wm_prog_data *prog_data; |
| struct gl_shader_program *shader_prog; |
| fs_visitor *v; |
| }; |
| |
| void scoreboard_test::SetUp() |
| { |
| ctx = ralloc_context(NULL); |
| compiler = rzalloc(ctx, struct brw_compiler); |
| devinfo = rzalloc(ctx, struct gen_device_info); |
| compiler->devinfo = devinfo; |
| |
| prog_data = ralloc(ctx, struct brw_wm_prog_data); |
| nir_shader *shader = |
| nir_shader_create(ctx, MESA_SHADER_FRAGMENT, NULL, NULL); |
| |
| v = new fs_visitor(compiler, NULL, ctx, NULL, &prog_data->base, shader, 8, -1, false); |
| |
| devinfo->ver = 12; |
| devinfo->verx10 = devinfo->ver * 10; |
| } |
| |
| void scoreboard_test::TearDown() |
| { |
| delete v; |
| v = NULL; |
| |
| ralloc_free(ctx); |
| ctx = NULL; |
| } |
| |
| 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->lower_scoreboard(); |
| |
| if (print) { |
| fprintf(stderr, "\n= After =\n"); |
| v->cfg->dump(); |
| } |
| } |
| |
| 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)); |
| } |