2014-11-05 16:13:59 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2015 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"
|
|
|
|
|
|
2015-06-03 18:16:30 +03:00
|
|
|
using namespace brw;
|
|
|
|
|
|
2014-11-05 16:13:59 -08:00
|
|
|
class cmod_propagation_test : public ::testing::Test {
|
|
|
|
|
virtual void SetUp();
|
|
|
|
|
|
|
|
|
|
public:
|
2015-06-22 17:17:56 -07:00
|
|
|
struct brw_compiler *compiler;
|
2016-08-22 15:01:08 -07:00
|
|
|
struct gen_device_info *devinfo;
|
2014-11-05 16:13:59 -08:00
|
|
|
struct gl_context *ctx;
|
|
|
|
|
struct brw_wm_prog_data *prog_data;
|
|
|
|
|
struct gl_shader_program *shader_prog;
|
|
|
|
|
fs_visitor *v;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class cmod_propagation_fs_visitor : public fs_visitor
|
|
|
|
|
{
|
|
|
|
|
public:
|
2015-06-22 17:17:56 -07:00
|
|
|
cmod_propagation_fs_visitor(struct brw_compiler *compiler,
|
2014-11-05 16:13:59 -08:00
|
|
|
struct brw_wm_prog_data *prog_data,
|
2015-10-01 15:21:57 -07:00
|
|
|
nir_shader *shader)
|
|
|
|
|
: fs_visitor(compiler, NULL, NULL, NULL,
|
|
|
|
|
&prog_data->base, (struct gl_program *) NULL,
|
|
|
|
|
shader, 8, -1) {}
|
2014-11-05 16:13:59 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cmod_propagation_test::SetUp()
|
|
|
|
|
{
|
2015-06-22 17:17:56 -07:00
|
|
|
ctx = (struct gl_context *)calloc(1, sizeof(*ctx));
|
|
|
|
|
compiler = (struct brw_compiler *)calloc(1, sizeof(*compiler));
|
2016-08-22 15:01:08 -07:00
|
|
|
devinfo = (struct gen_device_info *)calloc(1, sizeof(*devinfo));
|
2015-06-22 17:17:56 -07:00
|
|
|
compiler->devinfo = devinfo;
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
prog_data = ralloc(NULL, struct brw_wm_prog_data);
|
2016-10-13 11:41:23 +11:00
|
|
|
nir_shader *shader =
|
|
|
|
|
nir_shader_create(NULL, MESA_SHADER_FRAGMENT, NULL, NULL);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
2015-10-01 15:21:57 -07:00
|
|
|
v = new cmod_propagation_fs_visitor(compiler, prog_data, shader);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
2019-02-11 12:23:16 -08:00
|
|
|
devinfo->gen = 7;
|
2014-11-05 16:13:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 bool
|
|
|
|
|
cmod_propagation(fs_visitor *v)
|
|
|
|
|
{
|
2015-10-01 16:41:30 +02:00
|
|
|
const bool print = getenv("TEST_DEBUG");
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
if (print) {
|
|
|
|
|
fprintf(stderr, "= Before =\n");
|
|
|
|
|
v->cfg->dump(v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ret = v->opt_cmod_propagation();
|
|
|
|
|
|
|
|
|
|
if (print) {
|
|
|
|
|
fprintf(stderr, "\n= After =\n");
|
|
|
|
|
v->cfg->dump(v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, basic)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest src0 src1
|
|
|
|
|
* 1: cmp.ge.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.ge.f0(8) dest src0 src1
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, cmp_nonzero)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg nonzero(brw_imm_f(1.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), dest, nonzero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest src0 src1
|
|
|
|
|
* 1: cmp.ge.f0(8) null dest 1.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, non_cmod_instruction)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::uint_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::uint_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_ud(0u));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.FBL(dest, src0);
|
|
|
|
|
bld.CMP(bld.null_reg_ud(), dest, zero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: fbl(8) dest src0
|
|
|
|
|
* 1: cmp.ge.f0(8) null dest 0u
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, intervening_flag_write)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src2 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest src0 src1
|
|
|
|
|
* 1: cmp.ge.f0(8) null src2 0.0f
|
|
|
|
|
* 2: cmp.ge.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, intervening_flag_read)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src2 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest0, src0, src1);
|
|
|
|
|
set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest0 src0 src1
|
|
|
|
|
* 1: (+f0) sel(8) dest1 src2 0.0f
|
|
|
|
|
* 2: cmp.ge.f0(8) null dest0 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, intervening_dest_write)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::vec4_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src2 = v->vgrf(glsl_type::vec2_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-18 12:07:27 -07:00
|
|
|
bld.ADD(offset(dest, bld, 2), src0, src1);
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.emit(SHADER_OPCODE_TEX, dest, src2)
|
2016-09-07 13:38:20 -07:00
|
|
|
->size_written = 4 * REG_SIZE;
|
2015-06-18 12:07:27 -07:00
|
|
|
bld.CMP(bld.null_reg_f(), offset(dest, bld, 2), zero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest+2 src0 src1
|
|
|
|
|
* 1: tex(8) rlen 4 dest+0 src2
|
|
|
|
|
* 2: cmp.ge.f0(8) null dest+2 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
|
|
|
|
|
}
|
2015-01-03 12:18:15 -08:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, intervening_flag_read_same_value)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2015-01-03 12:18:15 -08:00
|
|
|
fs_reg dest0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src2 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
set_condmod(BRW_CONDITIONAL_GE, bld.ADD(dest0, src0, src1));
|
|
|
|
|
set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
|
2015-01-03 12:18:15 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add.ge.f0(8) dest0 src0 src1
|
|
|
|
|
* 1: (+f0) sel(8) dest1 src2 0.0f
|
|
|
|
|
* 2: cmp.ge.f0(8) null dest0 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.ge.f0(8) dest0 src0 src1
|
|
|
|
|
* 1: (+f0) sel(8) dest1 src2 0.0f
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
|
|
|
|
|
}
|
2014-12-30 12:18:57 -08:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, negate)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-12-30 12:18:57 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest, src0, src1);
|
2014-12-30 12:18:57 -08:00
|
|
|
dest.negate = true;
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
|
2014-12-30 12:18:57 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest src0 src1
|
|
|
|
|
* 1: cmp.ge.f0(8) null -dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.le.f0(8) dest src0 src1
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
i965/fs: Add support for removing MOV.NZ instructions.
For some reason, we occasionally write the flag register with a MOV.NZ
instruction:
add(8) g25<1>F -g6<0,1,0>F g15<8,8,1>F
cmp.l.f0(8) g26<1>D g25<8,8,1>F 0F
mov.nz.f0(8) null g26<8,8,1>D
A MOV.NZ instruction on the result of a CMP is like comparing for
equality with true in C. It's useless. Removing it allows us to
generate:
add.l.f0(8) null -g6<0,1,0>F g15<8,8,1>F
total instructions in shared programs: 5955701 -> 5951657 (-0.07%)
instructions in affected programs: 302910 -> 298866 (-1.34%)
GAINED: 1
LOST: 0
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2014-12-30 17:19:41 -08:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, movnz)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
i965/fs: Add support for removing MOV.NZ instructions.
For some reason, we occasionally write the flag register with a MOV.NZ
instruction:
add(8) g25<1>F -g6<0,1,0>F g15<8,8,1>F
cmp.l.f0(8) g26<1>D g25<8,8,1>F 0F
mov.nz.f0(8) null g26<8,8,1>D
A MOV.NZ instruction on the result of a CMP is like comparing for
equality with true in C. It's useless. Removing it allows us to
generate:
add.l.f0(8) null -g6<0,1,0>F g15<8,8,1>F
total instructions in shared programs: 5955701 -> 5951657 (-0.07%)
instructions in affected programs: 302910 -> 298866 (-1.34%)
GAINED: 1
LOST: 0
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2014-12-30 17:19:41 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.CMP(dest, src0, src1, BRW_CONDITIONAL_GE);
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_NZ,
|
|
|
|
|
bld.MOV(bld.null_reg_f(), dest));
|
i965/fs: Add support for removing MOV.NZ instructions.
For some reason, we occasionally write the flag register with a MOV.NZ
instruction:
add(8) g25<1>F -g6<0,1,0>F g15<8,8,1>F
cmp.l.f0(8) g26<1>D g25<8,8,1>F 0F
mov.nz.f0(8) null g26<8,8,1>D
A MOV.NZ instruction on the result of a CMP is like comparing for
equality with true in C. It's useless. Removing it allows us to
generate:
add.l.f0(8) null -g6<0,1,0>F g15<8,8,1>F
total instructions in shared programs: 5955701 -> 5951657 (-0.07%)
instructions in affected programs: 302910 -> 298866 (-1.34%)
GAINED: 1
LOST: 0
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2014-12-30 17:19:41 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: cmp.ge.f0(8) dest src0 src1
|
|
|
|
|
* 1: mov.nz.f0(8) null dest
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: cmp.ge.f0(8) dest src0 src1
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
2015-02-27 10:22:21 -08:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, different_types_cmod_with_zero)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2015-02-27 10:22:21 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::int_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::int_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::int_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), retype(dest, BRW_REGISTER_TYPE_F), zero,
|
|
|
|
|
BRW_CONDITIONAL_GE);
|
2015-02-27 10:22:21 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest:D src0:D src1:D
|
|
|
|
|
* 1: cmp.ge.f0(8) null:F dest:F 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, andnz_one)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::int_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
|
|
|
|
fs_reg one(brw_imm_d(1));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_NZ,
|
|
|
|
|
bld.AND(bld.null_reg_d(), dest, one));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: cmp.l.f0(8) dest:F src0:F 0F
|
|
|
|
|
* 1: and.nz.f0(8) null:D dest:D 1D
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: cmp.l.f0(8) dest:F src0:F 0F
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_TRUE(retype(dest, BRW_REGISTER_TYPE_F)
|
|
|
|
|
.equals(instruction(block0, 0)->dst));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, andnz_non_one)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::int_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
|
|
|
|
fs_reg nonone(brw_imm_d(38));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_NZ,
|
|
|
|
|
bld.AND(bld.null_reg_d(), dest, nonone));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: cmp.l.f0(8) dest:F src0:F 0F
|
|
|
|
|
* 1: and.nz.f0(8) null:D dest:D 38D
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, andz_one)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::int_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
|
|
|
|
fs_reg one(brw_imm_d(1));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_Z,
|
|
|
|
|
bld.AND(bld.null_reg_d(), dest, one));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: cmp.l.f0(8) dest:F src0:F 0F
|
|
|
|
|
* 1: and.z.f0(8) null:D dest:D 1D
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
i965/fs: Propagate conditional modifiers from compares to adds
The math inside the add and the cmp in this instruction sequence is the
same. We can utilize this to eliminate the compare.
add(8) g5<1>F g2<8,8,1>F g64.5<0,1,0>F { align1 1Q compacted };
cmp.z.f0(8) null<1>F g2<8,8,1>F -g64.5<0,1,0>F { align1 1Q switch };
(-f0) sel(8) g8<1>F (abs)g5<8,8,1>F 3e-37F { align1 1Q };
This is reduced to:
add.z.f0(8) g5<1>F g2<8,8,1>F g64.5<0,1,0>F { align1 1Q compacted };
(-f0) sel(8) g8<1>F (abs)g5<8,8,1>F 3e-37F { align1 1Q };
This optimization pass could do even better. The nature of converting
vectorized code from the GLSL front end to scalar code in NIR results in
sequences like:
add(8) g7<1>F g4<8,8,1>F g64.5<0,1,0>F { align1 1Q compacted };
add(8) g6<1>F g3<8,8,1>F g64.5<0,1,0>F { align1 1Q compacted };
add(8) g5<1>F g2<8,8,1>F g64.5<0,1,0>F { align1 1Q compacted };
cmp.z.f0(8) null<1>F g2<8,8,1>F -g64.5<0,1,0>F { align1 1Q switch };
(-f0) sel(8) g8<1>F (abs)g5<8,8,1>F 3e-37F { align1 1Q };
cmp.z.f0(8) null<1>F g3<8,8,1>F -g64.5<0,1,0>F { align1 1Q switch };
(-f0) sel(8) g10<1>F (abs)g6<8,8,1>F 3e-37F { align1 1Q };
cmp.z.f0(8) null<1>F g4<8,8,1>F -g64.5<0,1,0>F { align1 1Q switch };
(-f0) sel(8) g12<1>F (abs)g7<8,8,1>F 3e-37F { align1 1Q };
In this sequence, only the first cmp.z is removed. With different
scheduling, all 3 could get removed.
Skylake
total instructions in shared programs: 14407009 -> 14400173 (-0.05%)
instructions in affected programs: 1307274 -> 1300438 (-0.52%)
helped: 4880
HURT: 0
helped stats (abs) min: 1 max: 33 x̄: 1.40 x̃: 1
helped stats (rel) min: 0.03% max: 8.70% x̄: 0.70% x̃: 0.52%
95% mean confidence interval for instructions value: -1.45 -1.35
95% mean confidence interval for instructions %-change: -0.72% -0.69%
Instructions are helped.
total cycles in shared programs: 532943169 -> 532923528 (<.01%)
cycles in affected programs: 14065798 -> 14046157 (-0.14%)
helped: 2703
HURT: 339
helped stats (abs) min: 1 max: 1062 x̄: 12.27 x̃: 2
helped stats (rel) min: <.01% max: 28.72% x̄: 0.38% x̃: 0.21%
HURT stats (abs) min: 1 max: 739 x̄: 39.86 x̃: 12
HURT stats (rel) min: 0.02% max: 27.69% x̄: 1.38% x̃: 0.41%
95% mean confidence interval for cycles value: -8.66 -4.26
95% mean confidence interval for cycles %-change: -0.24% -0.14%
Cycles are helped.
LOST: 0
GAINED: 1
Broadwell
total instructions in shared programs: 14719636 -> 14712949 (-0.05%)
instructions in affected programs: 1288188 -> 1281501 (-0.52%)
helped: 4845
HURT: 0
helped stats (abs) min: 1 max: 33 x̄: 1.38 x̃: 1
helped stats (rel) min: 0.03% max: 8.00% x̄: 0.70% x̃: 0.52%
95% mean confidence interval for instructions value: -1.43 -1.33
95% mean confidence interval for instructions %-change: -0.72% -0.68%
Instructions are helped.
total cycles in shared programs: 559599253 -> 559581699 (<.01%)
cycles in affected programs: 13315565 -> 13298011 (-0.13%)
helped: 2600
HURT: 269
helped stats (abs) min: 1 max: 2128 x̄: 12.24 x̃: 2
helped stats (rel) min: <.01% max: 23.95% x̄: 0.41% x̃: 0.20%
HURT stats (abs) min: 1 max: 790 x̄: 53.07 x̃: 20
HURT stats (rel) min: 0.02% max: 15.96% x̄: 1.55% x̃: 0.75%
95% mean confidence interval for cycles value: -8.47 -3.77
95% mean confidence interval for cycles %-change: -0.27% -0.18%
Cycles are helped.
LOST: 0
GAINED: 8
Haswell
total instructions in shared programs: 12978609 -> 12973483 (-0.04%)
instructions in affected programs: 932921 -> 927795 (-0.55%)
helped: 3480
HURT: 0
helped stats (abs) min: 1 max: 33 x̄: 1.47 x̃: 1
helped stats (rel) min: 0.03% max: 7.84% x̄: 0.78% x̃: 0.58%
95% mean confidence interval for instructions value: -1.53 -1.42
95% mean confidence interval for instructions %-change: -0.80% -0.75%
Instructions are helped.
total cycles in shared programs: 410270788 -> 410250531 (<.01%)
cycles in affected programs: 10986161 -> 10965904 (-0.18%)
helped: 2087
HURT: 254
helped stats (abs) min: 1 max: 2672 x̄: 14.63 x̃: 4
helped stats (rel) min: <.01% max: 39.61% x̄: 0.42% x̃: 0.21%
HURT stats (abs) min: 1 max: 519 x̄: 40.49 x̃: 16
HURT stats (rel) min: 0.01% max: 12.83% x̄: 1.20% x̃: 0.47%
95% mean confidence interval for cycles value: -12.82 -4.49
95% mean confidence interval for cycles %-change: -0.31% -0.18%
Cycles are helped.
LOST: 0
GAINED: 5
Ivy Bridge
total instructions in shared programs: 11686082 -> 11681548 (-0.04%)
instructions in affected programs: 937696 -> 933162 (-0.48%)
helped: 3150
HURT: 0
helped stats (abs) min: 1 max: 33 x̄: 1.44 x̃: 1
helped stats (rel) min: 0.03% max: 7.84% x̄: 0.69% x̃: 0.49%
95% mean confidence interval for instructions value: -1.49 -1.38
95% mean confidence interval for instructions %-change: -0.71% -0.67%
Instructions are helped.
total cycles in shared programs: 257514962 -> 257492471 (<.01%)
cycles in affected programs: 11524149 -> 11501658 (-0.20%)
helped: 1970
HURT: 239
helped stats (abs) min: 1 max: 3525 x̄: 17.48 x̃: 3
helped stats (rel) min: <.01% max: 49.60% x̄: 0.46% x̃: 0.17%
HURT stats (abs) min: 1 max: 1358 x̄: 50.00 x̃: 15
HURT stats (rel) min: 0.02% max: 59.88% x̄: 1.84% x̃: 0.65%
95% mean confidence interval for cycles value: -17.01 -3.35
95% mean confidence interval for cycles %-change: -0.33% -0.08%
Cycles are helped.
LOST: 9
GAINED: 1
Sandy Bridge
total instructions in shared programs: 10432841 -> 10429893 (-0.03%)
instructions in affected programs: 685071 -> 682123 (-0.43%)
helped: 2453
HURT: 0
helped stats (abs) min: 1 max: 9 x̄: 1.20 x̃: 1
helped stats (rel) min: 0.02% max: 7.55% x̄: 0.64% x̃: 0.46%
95% mean confidence interval for instructions value: -1.23 -1.17
95% mean confidence interval for instructions %-change: -0.67% -0.62%
Instructions are helped.
total cycles in shared programs: 146133660 -> 146134195 (<.01%)
cycles in affected programs: 3991634 -> 3992169 (0.01%)
helped: 1237
HURT: 153
helped stats (abs) min: 1 max: 2853 x̄: 6.93 x̃: 2
helped stats (rel) min: <.01% max: 29.00% x̄: 0.24% x̃: 0.14%
HURT stats (abs) min: 1 max: 1740 x̄: 59.56 x̃: 12
HURT stats (rel) min: 0.03% max: 78.98% x̄: 1.96% x̃: 0.42%
95% mean confidence interval for cycles value: -5.13 5.90
95% mean confidence interval for cycles %-change: -0.17% 0.16%
Inconclusive result (value mean confidence interval includes 0).
LOST: 0
GAINED: 1
GM45 and Iron Lake had similar results (GM45 shown):
total instructions in shared programs: 4800332 -> 4798380 (-0.04%)
instructions in affected programs: 565995 -> 564043 (-0.34%)
helped: 1451
HURT: 0
helped stats (abs) min: 1 max: 20 x̄: 1.35 x̃: 1
helped stats (rel) min: 0.05% max: 5.26% x̄: 0.47% x̃: 0.31%
95% mean confidence interval for instructions value: -1.40 -1.29
95% mean confidence interval for instructions %-change: -0.50% -0.45%
Instructions are helped.
total cycles in shared programs: 122032318 -> 122027798 (<.01%)
cycles in affected programs: 8334868 -> 8330348 (-0.05%)
helped: 1029
HURT: 1
helped stats (abs) min: 2 max: 40 x̄: 4.43 x̃: 2
helped stats (rel) min: <.01% max: 1.83% x̄: 0.09% x̃: 0.04%
HURT stats (abs) min: 38 max: 38 x̄: 38.00 x̃: 38
HURT stats (rel) min: 0.25% max: 0.25% x̄: 0.25% x̃: 0.25%
95% mean confidence interval for cycles value: -4.70 -4.08
95% mean confidence interval for cycles %-change: -0.09% -0.08%
Cycles are helped.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2018-03-09 13:45:01 -08:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, add_not_merge_with_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* The addition and the implicit subtraction in the compare do not compute
|
|
|
|
|
* related values.
|
|
|
|
|
*
|
|
|
|
|
* = Before =
|
|
|
|
|
* 0: add(8) dest:F src0:F src1:F
|
|
|
|
|
* 1: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_merge_with_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest, src0, negate(src1));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest:F src0:F -src1:F
|
|
|
|
|
* 1: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.l.f0(8) dest:F src0:F -src1:F
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_immediate_merge_with_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg one(brw_imm_f(1.0f));
|
|
|
|
|
fs_reg negative_one(brw_imm_f(-1.0f));
|
|
|
|
|
|
|
|
|
|
bld.ADD(dest, src0, negative_one);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, one, BRW_CONDITIONAL_NZ);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest:F src0:F -1.0f
|
|
|
|
|
* 1: cmp.nz.f0(8) null:F src0:F 1.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.nz.f0(8) dest:F src0:F -1.0f
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_merge_with_compare_intervening_add)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest0, src0, negate(src1));
|
|
|
|
|
bld.ADD(dest1, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: add(8) dest1:F src0:F src1:F
|
|
|
|
|
* 2: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.l.f0(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: add(8) dest1:F src0:F src1:F
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_partial_write)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest0, src0, negate(src1));
|
|
|
|
|
set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, src0, negate(src1)));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: (+f0) add(8) dest1:F src0:F -src1:F
|
|
|
|
|
* 2: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_add)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest0, src0, negate(src1));
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_EQ, bld.ADD(dest1, src0, src1));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: add.z.f0(8) dest1:F src0:F src1:F
|
|
|
|
|
* 2: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, add_merge_with_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, negate(src1), BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest:F src0:F src1:F
|
|
|
|
|
* 1: cmp.l.f0(8) null:F src0:F -src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.l.f0(8) dest:F src0:F src1:F
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, negative_subtract_merge_with_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest, src1, negate(src0));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* The result of the subtract is the negatiion of the result of the
|
|
|
|
|
* implicit subtract in the compare, so the condition must change.
|
|
|
|
|
*
|
|
|
|
|
* = Before =
|
|
|
|
|
* 0: add(8) dest:F src1:F -src0:F
|
|
|
|
|
* 1: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.g.f0(8) dest:F src0:F -src1:F
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_delete_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src2 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)));
|
|
|
|
|
set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add.l.f0(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: (+f0) mov(0) dest1:F src2:F
|
|
|
|
|
* 2: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.l.f0(8) dest:F src0:F -src1:F
|
|
|
|
|
* 1: (+f0) mov(0) dest1:F src2:F
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_delete_compare_derp)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest0, src0, negate(src1)));
|
|
|
|
|
set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, negate(src0), src1));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add.l.f0(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: (+f0) add(0) dest1:F -src0:F src1:F
|
|
|
|
|
* 2: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.l.f0(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: (+f0) add(0) dest1:F -src0:F src1:F
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
|
|
|
|
|
}
|