mesa/src/intel/compiler/test_fs_cmod_propagation.cpp

3219 lines
98 KiB
C++
Raw Normal View History

/*
* 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"
using namespace brw;
class cmod_propagation_test : public ::testing::Test {
virtual void SetUp();
virtual void TearDown();
public:
struct brw_compiler *compiler;
struct intel_device_info *devinfo;
void *ctx;
struct brw_wm_prog_data *prog_data;
struct gl_shader_program *shader_prog;
fs_visitor *v;
void test_mov_prop(enum brw_conditional_mod cmod,
enum brw_reg_type add_type,
enum brw_reg_type mov_dst_type,
bool expected_cmod_prop_progress);
void test_saturate_prop(enum brw_conditional_mod before,
enum opcode op,
enum brw_reg_type add_type,
enum brw_reg_type op_type,
bool expected_cmod_prop_progress);
};
class cmod_propagation_fs_visitor : public fs_visitor
{
public:
cmod_propagation_fs_visitor(struct brw_compiler *compiler,
void *mem_ctx,
struct brw_wm_prog_data *prog_data,
nir_shader *shader)
: fs_visitor(compiler, NULL, mem_ctx, NULL,
&prog_data->base, shader, 8, -1, false) {}
};
void cmod_propagation_test::SetUp()
{
ctx = ralloc_context(NULL);
compiler = rzalloc(ctx, struct brw_compiler);
devinfo = rzalloc(ctx, struct intel_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 cmod_propagation_fs_visitor(compiler, ctx, prog_data, shader);
devinfo->ver = 7;
devinfo->verx10 = devinfo->ver * 10;
}
void cmod_propagation_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 bool
cmod_propagation(fs_visitor *v)
{
const bool print = getenv("TEST_DEBUG");
if (print) {
fprintf(stderr, "= Before =\n");
v->cfg->dump();
}
bool ret = v->opt_cmod_propagation();
if (print) {
fprintf(stderr, "\n= After =\n");
v->cfg->dump();
}
return ret;
}
TEST_F(cmod_propagation_test, basic)
{
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);
fs_reg zero(brw_imm_f(0.0f));
bld.ADD(dest, src0, src1);
bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
/* = 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, basic_other_flag)
{
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);
fs_reg zero(brw_imm_f(0.0f));
bld.ADD(dest, src0, src1);
bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE)
->flag_subreg = 1;
/* = Before =
*
* 0: add(8) dest src0 src1
* 1: cmp.ge.f0.1(8) null dest 0.0f
*
* = After =
* 0: add.ge.f0.1(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(1, instruction(block0, 0)->flag_subreg);
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
}
TEST_F(cmod_propagation_test, cmp_nonzero)
{
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);
fs_reg nonzero(brw_imm_f(1.0f));
bld.ADD(dest, src0, src1);
bld.CMP(bld.null_reg_f(), dest, nonzero, BRW_CONDITIONAL_GE);
/* = 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)
{
const fs_builder &bld = v->bld;
fs_reg dest = v->vgrf(glsl_type::uint_type);
fs_reg src0 = v->vgrf(glsl_type::uint_type);
fs_reg zero(brw_imm_ud(0u));
bld.FBL(dest, src0);
bld.CMP(bld.null_reg_ud(), dest, zero, BRW_CONDITIONAL_GE);
/* = 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)
{
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);
fs_reg src2 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
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);
/* = 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_mismatch_flag_write)
{
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);
fs_reg src2 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
bld.ADD(dest, src0, src1);
bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE)
->flag_subreg = 1;
bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
/* = Before =
*
* 0: add(8) dest src0 src1
* 1: cmp.ge.f0.1(8) null src2 0.0f
* 2: cmp.ge.f0(8) null dest 0.0f
*
* = After =
* 0: add.ge.f0(8) dest src0 src1
* 1: cmp.ge.f0.1(8) null 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(0, instruction(block0, 0)->flag_subreg);
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
}
TEST_F(cmod_propagation_test, intervening_flag_read)
{
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);
fs_reg src2 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
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);
/* = 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_mismatch_flag_read)
{
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);
fs_reg src2 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
bld.ADD(dest0, src0, src1);
set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
->flag_subreg = 1;
bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
/* = Before =
*
* 0: add(8) dest0 src0 src1
* 1: (+f0.1) 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.1) 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(0, instruction(block0, 0)->flag_subreg);
EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
}
TEST_F(cmod_propagation_test, intervening_dest_write)
{
const fs_builder &bld = v->bld;
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);
fs_reg zero(brw_imm_f(0.0f));
bld.ADD(offset(dest, bld, 2), src0, src1);
bld.emit(SHADER_OPCODE_TEX, dest, src2)
->size_written = 4 * REG_SIZE;
bld.CMP(bld.null_reg_f(), offset(dest, bld, 2), zero, BRW_CONDITIONAL_GE);
/* = 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);
}
TEST_F(cmod_propagation_test, intervening_flag_read_same_value)
{
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);
fs_reg src2 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
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);
/* = 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);
}
TEST_F(cmod_propagation_test, negate)
{
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);
fs_reg zero(brw_imm_f(0.0f));
bld.ADD(dest, src0, src1);
dest.negate = true;
bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
/* = 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);
}
TEST_F(cmod_propagation_test, movnz)
{
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.CMP(dest, src0, src1, BRW_CONDITIONAL_GE);
set_condmod(BRW_CONDITIONAL_NZ,
bld.MOV(bld.null_reg_f(), dest));
/* = 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);
}
TEST_F(cmod_propagation_test, different_types_cmod_with_zero)
{
const fs_builder &bld = v->bld;
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);
fs_reg zero(brw_imm_f(0.0f));
bld.ADD(dest, src0, src1);
bld.CMP(bld.null_reg_f(), retype(dest, BRW_REGISTER_TYPE_F), zero,
BRW_CONDITIONAL_GE);
/* = 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)
{
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);
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
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)
{
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);
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
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);
}
intel/compiler: fix cmod propagation optimisations Knowing following: - CMP writes to flag register the result of applying cmod to the `src0 - src1`. After that it stores the same value to dst. Other instructions first store their result to dst, and then store cmod(dst) to the flag register. - inst is either CMP or MOV - inst->dst is null - inst->src[0] overlaps with scan_inst->dst - inst->src[1] is zero - scan_inst wrote to a flag register There can be three possible paths: - scan_inst is CMP: Considering that src0 is either 0x0 (false), or 0xffffffff (true), and src1 is 0x0: - If inst's cmod is NZ, we can always remove scan_inst: NZ is invariant for false and true. This holds even if src0 is NaN: .nz is the only cmod, that returns true for NaN. - .g is invariant if src0 has a UD type - .l is invariant if src0 has a D type - scan_inst and inst have the same cmod: If scan_inst is anything than CMP, it already wrote the appropriate value to the flag register. - else: We can change cmod of scan_inst to that of inst, and remove inst. It is valid as long as we make sure that no instruction uses the flag register between scan_inst and inst. Nine new cmod_propagation unit tests: - cmp_cmpnz - cmp_cmpg - plnnz_cmpnz - plnnz_cmpz (*) - plnnz_sel_cmpz - cmp_cmpg_D - cmp_cmpg_UD (*) - cmp_cmpl_D (*) - cmp_cmpl_UD (*) this would fail without changes to brw_fs_cmod_propagation. This fixes optimisation that used to be illegal (see issue #2154) = Before = 0: linterp.z.f0.0(8) vgrf0:F, g2:F, attr0<0>:F 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f = After = 0: linterp.z.f0.0(8) vgrf0:F, g2:F, attr0<0>:F Now it is optimised as such (note change of cmod in line 0): = Before = 0: linterp.z.f0.0(8) vgrf0:F, g2:F, attr0<0>:F 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f = After = 0: linterp.nz.f0.0(8) vgrf0:F, g2:F, attr0<0>:F No shaderdb changes Closes: https://gitlab.freedesktop.org/mesa/mesa/issues/2154 Signed-off-by: Yevhenii Kolesnikov <yevhenii.kolesnikov@globallogic.com> Reviewed-by: Matt Turner <mattst88@gmail.com> Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3348> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/3348>
2020-01-03 16:37:00 +02:00
TEST_F(cmod_propagation_test, cmp_cmpnz)
{
const fs_builder &bld = v->bld;
fs_reg dst0 = v->vgrf(glsl_type::float_type);
fs_reg src0 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0));
bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_NZ);
/* = Before =
* 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
* 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f
*
* = After =
* 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
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_NZ, instruction(block0, 0)->conditional_mod);
}
TEST_F(cmod_propagation_test, cmp_cmpg)
{
const fs_builder &bld = v->bld;
fs_reg dst0 = v->vgrf(glsl_type::float_type);
fs_reg src0 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0));
bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_G);
/* = Before =
* 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
* 1: cmp.g.f0.0(8) null:F, vgrf0:F, 0f
*
* = After =
* (no changes)
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
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_NZ, instruction(block0, 0)->conditional_mod);
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 1)->conditional_mod);
}
TEST_F(cmod_propagation_test, plnnz_cmpnz)
{
const fs_builder &bld = v->bld;
fs_reg dst0 = v->vgrf(glsl_type::float_type);
fs_reg src0 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0));
set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_NZ);
/* = Before =
* 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
* 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f
*
* = After =
* 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
EXPECT_TRUE(cmod_propagation(v));
EXPECT_EQ(0, block0->start_ip);
EXPECT_EQ(0, block0->end_ip);
EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
}
TEST_F(cmod_propagation_test, plnnz_cmpz)
{
const fs_builder &bld = v->bld;
fs_reg dst0 = v->vgrf(glsl_type::float_type);
fs_reg src0 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0));
set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_Z);
/* = Before =
* 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
* 1: cmp.z.f0.0(8) null:F, vgrf0:F, 0f
*
* = After =
* 0: pln.z.f0.0(8) vgrf0:F, vgrf1:F, 0f
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
EXPECT_TRUE(cmod_propagation(v));
EXPECT_EQ(0, block0->start_ip);
EXPECT_EQ(0, block0->end_ip);
EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
}
TEST_F(cmod_propagation_test, plnnz_sel_cmpz)
{
const fs_builder &bld = v->bld;
fs_reg dst0 = v->vgrf(glsl_type::float_type);
fs_reg dst1 = v->vgrf(glsl_type::float_type);
fs_reg src0 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0));
set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dst1, src0, zero));
bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_Z);
/* = Before =
* 0: pln.nz.f0.0(8) vgrf0:F, vgrf2:F, 0f
* 1: (+f0.0) sel(8) vgrf1:F, vgrf2:F, 0f
* 2: cmp.z.f0.0(8) null:F, vgrf0:F, 0f
*
* = After =
* (no changes)
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
EXPECT_FALSE(cmod_propagation(v));
EXPECT_EQ(0, block0->start_ip);
EXPECT_EQ(2, block0->end_ip);
EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
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_Z, instruction(block0, 2)->conditional_mod);
}
TEST_F(cmod_propagation_test, cmp_cmpg_D)
{
const fs_builder &bld = v->bld;
fs_reg dst0 = v->vgrf(glsl_type::int_type);
fs_reg src0 = v->vgrf(glsl_type::int_type);
fs_reg zero(brw_imm_d(0));
fs_reg one(brw_imm_d(1));
bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
bld.CMP(bld.null_reg_d(), dst0, zero, BRW_CONDITIONAL_G);
/* = Before =
* 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
* 1: cmp.g.f0.0(8) null:D, vgrf0:D, 0d
*
* = After =
* (no changes)
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
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_NZ, instruction(block0, 0)->conditional_mod);
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 1)->conditional_mod);
}
TEST_F(cmod_propagation_test, cmp_cmpg_UD)
{
const fs_builder &bld = v->bld;
fs_reg dst0 = v->vgrf(glsl_type::uint_type);
fs_reg src0 = v->vgrf(glsl_type::uint_type);
fs_reg zero(brw_imm_ud(0));
bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
bld.CMP(bld.null_reg_ud(), dst0, zero, BRW_CONDITIONAL_G);
/* = Before =
* 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
* 1: cmp.g.f0.0(8) null:UD, vgrf0:UD, 0u
*
* = After =
* 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
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_NZ, instruction(block0, 0)->conditional_mod);
}
TEST_F(cmod_propagation_test, cmp_cmpl_D)
{
const fs_builder &bld = v->bld;
fs_reg dst0 = v->vgrf(glsl_type::int_type);
fs_reg src0 = v->vgrf(glsl_type::int_type);
fs_reg zero(brw_imm_d(0));
bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
bld.CMP(bld.null_reg_d(), dst0, zero, BRW_CONDITIONAL_L);
/* = Before =
* 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
* 1: cmp.l.f0.0(8) null:D, vgrf0:D, 0d
*
* = After =
* 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
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_NZ, instruction(block0, 0)->conditional_mod);
}
TEST_F(cmod_propagation_test, cmp_cmpl_UD)
{
const fs_builder &bld = v->bld;
fs_reg dst0 = v->vgrf(glsl_type::uint_type);
fs_reg src0 = v->vgrf(glsl_type::uint_type);
fs_reg zero(brw_imm_ud(0));
bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
bld.CMP(bld.null_reg_ud(), dst0, zero, BRW_CONDITIONAL_L);
/* = Before =
* 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
* 1: cmp.l.f0.0(8) null:UD, vgrf0:UD, 0u
*
* = After =
* (no changes)
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
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_NZ, instruction(block0, 0)->conditional_mod);
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_L, 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, andz_one)
{
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);
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
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_other_flag)
{
/* This test is the same as subtract_delete_compare but it explicitly used
* flag f0.1 for the subtraction and the comparison.
*/
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)))
->flag_subreg = 1;
set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2));
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
->flag_subreg = 1;
/* = Before =
* 0: add.l.f0.1(8) dest0:F src0:F -src1:F
* 1: (+f0) mov(0) dest1:F src2:F
* 2: cmp.l.f0.1(8) null:F src0:F src1:F
*
* = After =
* 0: add.l.f0.1(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(1, instruction(block0, 0)->flag_subreg);
EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
}
TEST_F(cmod_propagation_test, subtract_to_mismatch_flag)
{
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);
set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)));
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
->flag_subreg = 1;
/* = Before =
* 0: add.l.f0(8) dest0:F src0:F -src1:F
* 1: cmp.l.f0.1(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_L, instruction(block0, 0)->conditional_mod);
EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
}
TEST_F(cmod_propagation_test,
subtract_merge_with_compare_intervening_mismatch_flag_write)
{
const fs_builder &bld = v->bld;
fs_reg dest0 = 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.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
->flag_subreg = 1;
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
/* = Before =
* 0: add(8) dest0:F src0:F -src1:F
* 1: cmp.l.f0.1(8) null: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: cmp.l.f0.1(8) null:F src0:F src1:F
*
* NOTE: Another perfectly valid after sequence would be:
*
* 0: add.f0.1(8) dest0:F src0:F -src1:F
* 1: cmp.l.f0(8) null:F src0:F src1:F
*
* However, the optimization pass starts at the end of the basic block.
* Because of this, the cmp.l.f0 will always be chosen. If the pass
* changes its strategy, this test will also need to change.
*/
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(0, instruction(block0, 0)->flag_subreg);
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
}
TEST_F(cmod_propagation_test,
subtract_merge_with_compare_intervening_mismatch_flag_read)
{
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);
fs_reg src2 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
bld.ADD(dest0, src0, negate(src1));
set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
->flag_subreg = 1;
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
/* = Before =
* 0: add(8) dest0:F src0:F -src1:F
* 1: (+f0.1) sel(8) dest1 src2 0.0f
* 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.1) 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_L, instruction(block0, 0)->conditional_mod);
EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
}
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, 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);
}
TEST_F(cmod_propagation_test, signed_unsigned_comparison_mismatch)
{
const fs_builder &bld = v->bld;
fs_reg dest0 = v->vgrf(glsl_type::int_type);
fs_reg src0 = v->vgrf(glsl_type::int_type);
src0.type = BRW_REGISTER_TYPE_W;
bld.ASR(dest0, negate(src0), brw_imm_d(15));
bld.CMP(bld.null_reg_ud(), retype(dest0, BRW_REGISTER_TYPE_UD),
brw_imm_ud(0u), BRW_CONDITIONAL_LE);
/* = Before =
* 0: asr(8) dest:D -src0:W 15D
* 1: cmp.le.f0(8) null:UD dest:UD 0UD
*
* = 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_ASR, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 1)->conditional_mod);
}
intel/fs: Fix a cmod prop bug when the source type of a mov doesn't match the dest type of scan_inst We were previously operating with the mindset "a MOV is just a compare with zero." As a result, we were trying to share as much code between the MOV path and the CMP path as possible. However, MOV instructions can perform type conversions that affect the result of the comparison. There was some code added to better handle this for cases like and(16) g31<1>UD g20<8,8,1>UD g22<8,8,1>UD mov.nz.f0(16) null<1>F g31<8,8,1>D The flaw in these changed special cases is that it allowed things like or(8) dest:D src0:D src1:D mov.nz(8) null:D dest:F Because both destinations were integer types, the propagation was allowed. The source type of the MOV and the destination type of the OR do not match, so type conversion rules have to be accounted for. My solution was to just split the MOV and non-MOV paths with completely separate checks. The "else" path in this commit is basically the old code with the BRW_OPCODE_MOV special case removed. The new MOV code further splits into "destination of scan_inst is float" and "destination of scan_inst is integer" paths. For each case I enumerate the rules that I belive apply. For the integer path, only the "Z or NZ" rules are listed as only NZ is currently allowed (hence the conditional_mod assertion in that path). A later commit relaxes this and adds the rule. The new rules slightly relax one of the previous rules. Previously the sizes of the MOV destination and the MOV source had to be the same. In some cases now the sizes can be different by the following conditions: - Floating point to integer conversion are not allowed. - If the conversion is integer to floating point, the size of the floating point value does not matter as it will not affect the comparison result. - If the conversion is float to float, the size of the destination must be greater than or equal to the size of the source. - If the conversion is integer to integer, the size of the destination must be greater than or equal to the size of the source. Reviewed-by: Kenneth Graunke <kenneth@whitecape.org> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 17:15:03 -07:00
TEST_F(cmod_propagation_test, ior_f2i_nz)
{
const fs_builder &bld = v->bld;
fs_reg dest = bld.vgrf(BRW_REGISTER_TYPE_D);
fs_reg src0 = bld.vgrf(BRW_REGISTER_TYPE_D);
fs_reg src1 = bld.vgrf(BRW_REGISTER_TYPE_D);
bld.OR(dest, src0, src1);
bld.MOV(bld.null_reg_d(), retype(dest, BRW_REGISTER_TYPE_F))
->conditional_mod = BRW_CONDITIONAL_NZ;
/* = Before =
* 0: or(8) dest:D src0:D src1:D
* 1: mov.nz(8) null:D dest:F
*
* = After =
* No changes.
*
* If src0 = 0x30000000 and src1 = 0x0f000000, then the value stored in
* dest, interpreted as floating point, is 0.5. This bit pattern is not
* zero, but after the float-to-integer conversion, the value is zero.
*/
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(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
/* This is ASSERT_EQ because if end_ip is 0, the instruction(block0, 1)
* calls will not work properly, and the test will give weird results.
*/
ASSERT_EQ(1, block0->end_ip);
EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
}
void
cmod_propagation_test::test_mov_prop(enum brw_conditional_mod cmod,
enum brw_reg_type add_type,
enum brw_reg_type mov_dst_type,
bool expected_cmod_prop_progress)
{
const fs_builder &bld = v->bld;
fs_reg dest = bld.vgrf(add_type);
fs_reg src0 = bld.vgrf(add_type);
fs_reg src1 = bld.vgrf(add_type);
bld.ADD(dest, src0, src1);
bld.MOV(retype(bld.null_reg_ud(), mov_dst_type), dest)
->conditional_mod = cmod;
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
EXPECT_EQ(0, block0->start_ip);
EXPECT_EQ(1, block0->end_ip);
EXPECT_EQ(expected_cmod_prop_progress, cmod_propagation(v));
const enum brw_conditional_mod add_cmod =
expected_cmod_prop_progress ? cmod : BRW_CONDITIONAL_NONE;
EXPECT_EQ(0, block0->start_ip);
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
EXPECT_EQ(add_cmod, instruction(block0, 0)->conditional_mod);
if (expected_cmod_prop_progress) {
EXPECT_EQ(0, block0->end_ip);
} else {
/* This is ASSERT_EQ because if end_ip is 0, the instruction(block0, 1)
* calls will not work properly, and the test will give weird results.
*/
ASSERT_EQ(1, block0->end_ip);
EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
EXPECT_EQ(cmod, instruction(block0, 1)->conditional_mod);
}
}
TEST_F(cmod_propagation_test, fadd_fmov_nz)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.nz(8) null:F dest:F
*
* = After =
* 0: add.nz(8) dest:F src0:F src1:F
*/
test_mov_prop(BRW_CONDITIONAL_NZ,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, fadd_fmov_z)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.z(8) null:F dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* 0: add.z(8) dest:F src0:F src1:F
*/
test_mov_prop(BRW_CONDITIONAL_Z,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_F,
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
true);
}
TEST_F(cmod_propagation_test, fadd_fmov_l)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.l(8) null:F dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* 0: add.l(8) dest:F src0:F src1:F
*/
test_mov_prop(BRW_CONDITIONAL_L,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_F,
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
true);
}
TEST_F(cmod_propagation_test, fadd_fmov_g)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.g(8) null:F dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* 0: add.g(8) dest:F src0:F src1:F
*/
test_mov_prop(BRW_CONDITIONAL_G,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_F,
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
true);
}
TEST_F(cmod_propagation_test, fadd_fmov_le)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.le(8) null:F dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* 0: add.le(8) dest:F src0:F src1:F
*/
test_mov_prop(BRW_CONDITIONAL_LE,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_F,
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
true);
}
TEST_F(cmod_propagation_test, fadd_fmov_ge)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.ge(8) null:F dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* 0: add.ge(8) dest:F src0:F src1:F
*/
test_mov_prop(BRW_CONDITIONAL_GE,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_F,
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
true);
}
TEST_F(cmod_propagation_test, iadd_imov_nz)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.nz(8) null:D dest:D
*
* = After =
* 0: add.nz(8) dest:D src0:D src1:D
*/
test_mov_prop(BRW_CONDITIONAL_NZ,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_D,
true);
}
TEST_F(cmod_propagation_test, iadd_imov_z)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.z(8) null:D dest:D
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* 0: add.z(8) dest:D src0:D src1:D
*/
test_mov_prop(BRW_CONDITIONAL_Z,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_D,
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
true);
}
TEST_F(cmod_propagation_test, iadd_imov_l)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.l(8) null:D dest:D
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* 0: add.l(8) dest:D src0:D src1:D
*/
test_mov_prop(BRW_CONDITIONAL_L,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_D,
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
true);
}
TEST_F(cmod_propagation_test, iadd_imov_g)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.g(8) null:D dest:D
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* 0: add.g(8) dest:D src0:D src1:D
*/
test_mov_prop(BRW_CONDITIONAL_G,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_D,
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
true);
}
TEST_F(cmod_propagation_test, iadd_imov_le)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.le(8) null:D dest:D
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* 0: add.le(8) dest:D src0:D src1:D
*/
test_mov_prop(BRW_CONDITIONAL_LE,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_D,
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
true);
}
TEST_F(cmod_propagation_test, iadd_imov_ge)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.ge(8) null:D dest:D
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* 0: add.ge(8) dest:D src0:D src1:D
*/
test_mov_prop(BRW_CONDITIONAL_GE,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_D,
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
true);
}
TEST_F(cmod_propagation_test, iadd_umov_nz)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.nz(8) null:UD dest:D
*
* = After =
* 0: add.nz(8) dest:D src0:D src1:D
*/
test_mov_prop(BRW_CONDITIONAL_NZ,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_UD,
true);
}
TEST_F(cmod_propagation_test, iadd_umov_z)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.z(8) null:UD dest:D
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* 0: add.z(8) dest:D src0:D src1:D
*/
test_mov_prop(BRW_CONDITIONAL_Z,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_UD,
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
true);
}
TEST_F(cmod_propagation_test, iadd_umov_l)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.l(8) null:UD dest:D
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* Due to the signed-to-usigned type conversion, the conditional modifier
* cannot be propagated to the ADD without changing at least the
* destination type of the add.
*
* This particular tests is a little silly. Unsigned less than zero is a
* contradiction, and earlier optimization passes should have eliminated
* it.
*/
test_mov_prop(BRW_CONDITIONAL_L,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_UD,
false);
}
TEST_F(cmod_propagation_test, iadd_umov_g)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.g(8) null:UD dest:D
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* In spite of the type conversion, this could be made to work by
* propagating NZ instead of G to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_G,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_UD,
false);
}
TEST_F(cmod_propagation_test, iadd_umov_le)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.le(8) null:UD dest:D
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* In spite of the type conversion, this could be made to work by
* propagating Z instead of LE to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_LE,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_UD,
false);
}
TEST_F(cmod_propagation_test, iadd_umov_ge)
{
/* = Before =
* 0: add(8) dest:D src0:D src1:D
* 1: mov.ge(8) null:UD dest:D
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* Due to the signed-to-usigned type conversion, the conditional modifier
* cannot be propagated to the ADD without changing at least the
* destination type of the add.
*
* This particular tests is a little silly. Unsigned greater than or equal
* to zero is a tautology, and earlier optimization passes should have
* eliminated it.
*/
test_mov_prop(BRW_CONDITIONAL_GE,
BRW_REGISTER_TYPE_D,
BRW_REGISTER_TYPE_UD,
false);
}
TEST_F(cmod_propagation_test, fadd_f2u_nz)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.nz(8) null:UD dest:F
*
* = After =
* No changes. The MOV changes the type from float to unsigned integer.
* If dest is in the range [-Inf, 1), the conversion will clamp it to zero.
* If dest is NaN, the conversion will also clamp it to zero. It is not
* safe to propagate the NZ back to the ADD.
*
* It's tempting to try to propagate G to the ADD in place of the NZ. This
* fails for values (0, 1). For example, if dest is 0.5, add.g would set
* the flag, but mov.nz would not because the 0.5 would get rounded down to
* zero.
*/
test_mov_prop(BRW_CONDITIONAL_NZ,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_UD,
false);
}
TEST_F(cmod_propagation_test, fadd_f2u_z)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.z(8) null:UD dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* The MOV changes the type from float to unsigned integer. If dest is in
* the range [-Inf, 1), the conversion will clamp it to zero. If dest is
* NaN, the conversion will also clamp it to zero. It is not safe to
* propagate the Z back to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_Z,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_UD,
false);
}
TEST_F(cmod_propagation_test, fadd_f2u_l)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.l(8) null:UD dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* The MOV changes the type from float to unsigned integer. If dest is in
* the range [-Inf, 1), the conversion will clamp it to zero. If dest is
* NaN, the conversion will also clamp it to zero. It is not safe to
* propagate the L back to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_L,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_UD,
false);
}
TEST_F(cmod_propagation_test, fadd_f2u_g)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.g(8) null:UD dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* The MOV changes the type from float to unsigned integer. If dest is in
* the range [-Inf, 1), the conversion will clamp it to zero. If dest is
* NaN, the conversion will also clamp it to zero. It is not safe to
* propagate the G back to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_G,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_UD,
false);
}
TEST_F(cmod_propagation_test, fadd_f2u_le)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.le(8) null:UD dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* The MOV changes the type from float to unsigned integer. If dest is in
* the range [-Inf, 1), the conversion will clamp it to zero. If dest is
* NaN, the conversion will also clamp it to zero. It is not safe to
* propagate the LE back to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_LE,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_UD,
false);
}
TEST_F(cmod_propagation_test, fadd_f2u_ge)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.ge(8) null:UD dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* The MOV changes the type from float to unsigned integer. If dest is in
* the range [-Inf, 1), the conversion will clamp it to zero. If dest is
* NaN, the conversion will also clamp it to zero. It is not safe to
* propagate the GE back to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_GE,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_UD,
false);
}
TEST_F(cmod_propagation_test, fadd_f2i_nz)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.nz(8) null:D dest:F
*
* = After =
* No changes. The MOV changes the type from float to signed integer. If
* dest is in the range (-1, 1), the conversion will clamp it to zero. If
* dest is NaN, the conversion will also clamp it to zero. It is not safe
* to propagate the NZ back to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_NZ,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, fadd_f2i_z)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.z(8) null:D dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* The MOV changes the type from float to signed integer. If dest is in
* the range (-1, 1), the conversion will clamp it to zero. If dest is
* NaN, the conversion will also clamp it to zero. It is not safe to
* propagate the Z back to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_Z,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, fadd_f2i_l)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.l(8) null:D dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* The MOV changes the type from float to signed integer. If dest is in
* the range (-1, 1), the conversion will clamp it to zero. If dest is
* NaN, the conversion will also clamp it to zero. It is not safe to
* propagate the L back to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_L,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, fadd_f2i_g)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.g(8) null:D dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* The MOV changes the type from float to signed integer. If dest is in
* the range (-1, 1), the conversion will clamp it to zero. If dest is
* NaN, the conversion will also clamp it to zero. It is not safe to
* propagate the G back to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_G,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, fadd_f2i_le)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.le(8) null:D dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* The MOV changes the type from float to signed integer. If dest is in
* the range (-1, 1), the conversion will clamp it to zero. If dest is
* NaN, the conversion will also clamp it to zero. It is not safe to
* propagate the LE back to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_LE,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, fadd_f2i_ge)
{
/* = Before =
* 0: add(8) dest:F src0:F src1:F
* 1: mov.ge(8) null:D dest:F
*
* = After =
intel/fs: cmod propagate from MOV with any condition There were tests related to propagating conditional modifiers from a MOV to an instruction with a .SAT modifier for a very long time, but they were #if'ed out. There are restrictions later in the function that limit the kinds of MOV instructions that can propagate. This avoids the dangers of type-converting MOVs that may generate flags in different ways. v2: Update the added comment to look more like the existing comment. That makes the small differences between the two cases more obvious. Noticed by Marcin. All Intel platforms had similar results. (Ice Lake shown) total instructions in shared programs: 19827127 -> 19826924 (<.01%) instructions in affected programs: 62024 -> 61821 (-0.33%) helped: 201 HURT: 0 helped stats (abs) min: 1 max: 2 x̄: 1.01 x̃: 1 helped stats (rel) min: 0.13% max: 0.60% x̄: 0.35% x̃: 0.36% 95% mean confidence interval for instructions value: -1.02 -1.00 95% mean confidence interval for instructions %-change: -0.36% -0.34% Instructions are helped. total cycles in shared programs: 954655879 -> 954655356 (<.01%) cycles in affected programs: 1212877 -> 1212354 (-0.04%) helped: 155 HURT: 6 helped stats (abs) min: 1 max: 6 x̄: 3.65 x̃: 4 helped stats (rel) min: <.01% max: 0.17% x̄: 0.07% x̃: 0.07% HURT stats (abs) min: 2 max: 12 x̄: 7.00 x̃: 8 HURT stats (rel) min: 0.04% max: 0.23% x̄: 0.14% x̃: 0.15% 95% mean confidence interval for cycles value: -3.60 -2.90 95% mean confidence interval for cycles %-change: -0.07% -0.05% Cycles are helped. Reviewed-by: Marcin Ślusarz <marcin.slusarz@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12045>
2021-08-17 16:09:11 -07:00
* No changes.
*
* The MOV changes the type from float to signed integer. If dest is in
* the range (-1, 1), the conversion will clamp it to zero. If dest is
* NaN, the conversion will also clamp it to zero. It is not safe to
* propagate the GE back to the ADD.
*/
test_mov_prop(BRW_CONDITIONAL_GE,
BRW_REGISTER_TYPE_F,
BRW_REGISTER_TYPE_D,
false);
}
void
cmod_propagation_test::test_saturate_prop(enum brw_conditional_mod before,
enum opcode op,
enum brw_reg_type add_type,
enum brw_reg_type op_type,
bool expected_cmod_prop_progress)
{
const fs_builder &bld = v->bld;
fs_reg dest = bld.vgrf(add_type);
fs_reg src0 = bld.vgrf(add_type);
fs_reg src1 = bld.vgrf(add_type);
fs_reg zero(brw_imm_ud(0));
bld.ADD(dest, src0, src1)->saturate = true;
assert(op == BRW_OPCODE_CMP || op == BRW_OPCODE_MOV);
if (op == BRW_OPCODE_CMP) {
bld.CMP(bld.vgrf(op_type, 0),
retype(dest, op_type),
retype(zero, op_type),
before);
} else {
bld.MOV(bld.vgrf(op_type, 0), retype(dest, op_type))
->conditional_mod = before;
}
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
EXPECT_EQ(0, block0->start_ip);
EXPECT_EQ(1, block0->end_ip);
EXPECT_EQ(expected_cmod_prop_progress, cmod_propagation(v));
EXPECT_EQ(0, block0->start_ip);
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
EXPECT_EQ(add_type, instruction(block0, 0)->dst.type);
EXPECT_EQ(add_type, instruction(block0, 0)->src[0].type);
EXPECT_EQ(add_type, instruction(block0, 0)->src[1].type);
EXPECT_TRUE(instruction(block0, 0)->saturate);
if (expected_cmod_prop_progress) {
EXPECT_EQ(0, block0->end_ip);
EXPECT_EQ(before, instruction(block0, 0)->conditional_mod);
} else {
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
/* This is ASSERT_EQ because if end_ip is 0, the instruction(block0, 1)
* calls will not work properly, and the test will give weird results.
*/
ASSERT_EQ(1, block0->end_ip);
EXPECT_EQ(op, instruction(block0, 1)->opcode);
EXPECT_EQ(op_type, instruction(block0, 1)->dst.type);
EXPECT_EQ(op_type, instruction(block0, 1)->src[0].type);
EXPECT_FALSE(instruction(block0, 1)->saturate);
EXPECT_EQ(before, instruction(block0, 1)->conditional_mod);
}
}
TEST_F(cmod_propagation_test, float_saturate_nz_cmp)
{
/* With the saturate modifier, the comparison happens after clamping to
* [0, 1].
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.nz.f0(8) null dest 0.0f
*
* = After =
* 0: add.sat.nz.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, float_saturate_nz_mov)
{
/* With the saturate modifier, the comparison happens after clamping to
* [0, 1].
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.nz.f0(8) null dest
*
* = After =
* 0: add.sat.nz.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, float_saturate_z_cmp)
{
/* With the saturate modifier, the comparison happens after clamping to
* [0, 1].
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.z.f0(8) null dest 0.0f
*
* = After =
* 0: add.sat.z.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, float_saturate_z_mov)
{
/* With the saturate modifier, the comparison happens after clamping to
* [0, 1].
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.z.f0(8) null dest
*
* = After =
* 0: add.sat.z.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, float_saturate_g_cmp)
{
/* With the saturate modifier, the comparison happens after clamping to
* [0, 1].
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.g.f0(8) null dest 0.0f
*
* = After =
* 0: add.sat.g.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, float_saturate_g_mov)
{
/* With the saturate modifier, the comparison happens after clamping to
* [0, 1].
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.g.f0(8) null dest
*
* = After =
* 0: add.sat.g.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, float_saturate_le_cmp)
{
/* With the saturate modifier, the comparison happens after clamping to
* [0, 1].
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.le.f0(8) null dest 0.0f
*
* = After =
* 0: add.sat.le.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, float_saturate_le_mov)
{
/* With the saturate modifier, the comparison happens after clamping to
* [0, 1]. (sat(x) <= 0) == (x <= 0).
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.le.f0(8) null dest
*
* = After =
* 0: add.sat.le.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, float_saturate_l_cmp)
{
/* With the saturate modifier, the comparison happens after clamping to
* [0, 1].
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.l.f0(8) null dest 0.0f
*
* = After =
* 0: add.sat.l.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, float_saturate_l_mov)
{
/* With the saturate modifier, the comparison happens after clamping to
* [0, 1].
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.l.f0(8) null dest
*
* = After =
* 0: add.sat.l.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, float_saturate_ge_cmp)
{
/* With the saturate modifier, the comparison happens after clamping to
* [0, 1].
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.ge.f0(8) null dest 0.0f
*
* = After =
* 0: add.sat.ge.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, float_saturate_ge_mov)
{
/* With the saturate modifier, the comparison happens before clamping to
* [0, 1].
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.ge.f0(8) null dest
*
* = After =
* 0: add.sat.ge.f0(8) dest src0 src1
*/
test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
true);
}
TEST_F(cmod_propagation_test, int_saturate_nz_cmp)
{
/* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.nz.f0(8) null dest 0
*
* = After =
* No change.
*/
test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, int_saturate_nz_mov)
{
/* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.nz.f0(8) null dest
*
* = After =
* No change.
*/
test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, int_saturate_z_cmp)
{
/* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.z.f0(8) null dest 0
*
* = After =
* No change.
*/
test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, int_saturate_z_mov)
{
/* With the saturate modifier, the comparison happens before clamping to
* [0, 1]. (sat(x) == 0) == (x <= 0).
*
* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.z.f0(8) null dest
*
* = After =
* No change.
*/
test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, int_saturate_g_cmp)
{
/* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.g.f0(8) null dest 0
*
* = After =
* No change.
*/
test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, int_saturate_g_mov)
{
/* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.g.f0(8) null dest
*
* = After =
* No change.
*/
test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, int_saturate_le_cmp)
{
/* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.le.f0(8) null dest 0
*
* = After =
* No change.
*/
test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, int_saturate_le_mov)
{
/* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.le.f0(8) null dest
*
* = After =
* No change.
*/
test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, int_saturate_l_cmp)
{
/* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.l.f0(8) null dest 0
*
* = After =
* No change
*/
test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, int_saturate_l_mov)
{
/* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.l.f0(8) null dest 0
*
* = After =
* No change
*/
test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, int_saturate_ge_cmp)
{
/* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: cmp.ge.f0(8) null dest 0
*
* = After =
* No change
*/
test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_CMP,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, int_saturate_ge_mov)
{
/* = Before =
*
* 0: add.sat(8) dest src0 src1
* 1: mov.ge.f0(8) null dest
*
* = After =
* No change
*/
test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_MOV,
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
false);
}
TEST_F(cmod_propagation_test, not_to_or)
{
/* Exercise propagation of conditional modifier from a NOT instruction to
* another ALU instruction as performed by cmod_propagate_not.
*/
const fs_builder &bld = v->bld;
fs_reg dest = v->vgrf(glsl_type::uint_type);
fs_reg src0 = v->vgrf(glsl_type::uint_type);
fs_reg src1 = v->vgrf(glsl_type::uint_type);
bld.OR(dest, src0, src1);
set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
/* = Before =
*
* 0: or(8) dest src0 src1
* 1: not.nz.f0(8) null dest
*
* = After =
* 0: or.z.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_OR, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
}
TEST_F(cmod_propagation_test, not_to_and)
{
/* Exercise propagation of conditional modifier from a NOT instruction to
* another ALU instruction as performed by cmod_propagate_not.
*/
const fs_builder &bld = v->bld;
fs_reg dest = v->vgrf(glsl_type::uint_type);
fs_reg src0 = v->vgrf(glsl_type::uint_type);
fs_reg src1 = v->vgrf(glsl_type::uint_type);
bld.AND(dest, src0, src1);
set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
/* = Before =
*
* 0: and(8) dest src0 src1
* 1: not.nz.f0(8) null dest
*
* = After =
* 0: and.z.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_AND, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
}
TEST_F(cmod_propagation_test, not_to_uadd)
{
/* Exercise propagation of conditional modifier from a NOT instruction to
* another ALU instruction as performed by cmod_propagate_not.
*
* The optimization pass currently restricts to just OR and AND. It's
* possible that this is too restrictive, and the actual, necessary
* restriction is just the the destination type of the ALU instruction is
* the same as the source type of the NOT instruction.
*/
const fs_builder &bld = v->bld;
fs_reg dest = v->vgrf(glsl_type::uint_type);
fs_reg src0 = v->vgrf(glsl_type::uint_type);
fs_reg src1 = v->vgrf(glsl_type::uint_type);
bld.ADD(dest, src0, src1);
set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
/* = Before =
*
* 0: add(8) dest src0 src1
* 1: not.nz.f0(8) null dest
*
* = 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_NOT, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
}
TEST_F(cmod_propagation_test, not_to_fadd_to_ud)
{
/* Exercise propagation of conditional modifier from a NOT instruction to
* another ALU instruction as performed by cmod_propagate_not.
*
* The optimization pass currently restricts to just OR and AND. It's
* possible that this is too restrictive, and the actual, necessary
* restriction is just the the destination type of the ALU instruction is
* the same as the source type of the NOT instruction.
*/
const fs_builder &bld = v->bld;
fs_reg dest = v->vgrf(glsl_type::uint_type);
fs_reg src0 = v->vgrf(glsl_type::float_type);
fs_reg src1 = v->vgrf(glsl_type::float_type);
bld.ADD(dest, src0, src1);
set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
/* = Before =
*
* 0: add(8) dest.ud src0.f src1.f
* 1: not.nz.f0(8) null dest.ud
*
* = 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_NOT, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
}
TEST_F(cmod_propagation_test, not_to_fadd)
{
/* Exercise propagation of conditional modifier from a NOT instruction to
* another ALU instruction as performed by cmod_propagate_not.
*
* The optimization pass currently restricts to just OR and AND. It's
* possible that this is too restrictive, and the actual, necessary
* restriction is just the the destination type of the ALU instruction is
* the same as the source type of the NOT instruction.
*/
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);
set_condmod(BRW_CONDITIONAL_NZ,
bld.NOT(bld.null_reg_ud(),
retype(dest, BRW_REGISTER_TYPE_UD)));
/* = Before =
*
* 0: add(8) dest.f src0.f src1.f
* 1: not.nz.f0(8) null dest.ud
*
* = 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_NOT, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
}
TEST_F(cmod_propagation_test, not_to_or_intervening_flag_read_compatible_value)
{
/* Exercise propagation of conditional modifier from a NOT instruction to
* another ALU instruction as performed by cmod_propagate_not.
*/
const fs_builder &bld = v->bld;
fs_reg dest0 = v->vgrf(glsl_type::uint_type);
fs_reg dest1 = v->vgrf(glsl_type::float_type);
fs_reg src0 = v->vgrf(glsl_type::uint_type);
fs_reg src1 = v->vgrf(glsl_type::uint_type);
fs_reg src2 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest0, src0, src1));
set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
/* = Before =
*
* 0: or.z.f0(8) dest0 src0 src1
* 1: (+f0) sel(8) dest1 src2 0.0f
* 2: not.nz.f0(8) null dest0
*
* = After =
* 0: or.z.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_OR, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
}
TEST_F(cmod_propagation_test,
not_to_or_intervening_flag_read_compatible_value_mismatch_flag)
{
/* Exercise propagation of conditional modifier from a NOT instruction to
* another ALU instruction as performed by cmod_propagate_not.
*/
const fs_builder &bld = v->bld;
fs_reg dest0 = v->vgrf(glsl_type::uint_type);
fs_reg dest1 = v->vgrf(glsl_type::float_type);
fs_reg src0 = v->vgrf(glsl_type::uint_type);
fs_reg src1 = v->vgrf(glsl_type::uint_type);
fs_reg src2 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest0, src0, src1))
->flag_subreg = 1;
set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
/* = Before =
*
* 0: or.z.f0.1(8) dest0 src0 src1
* 1: (+f0) sel(8) dest1 src2 0.0f
* 2: not.nz.f0(8) null dest0
*
* = 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_OR, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
EXPECT_EQ(1, instruction(block0, 0)->flag_subreg);
EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 2)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 2)->conditional_mod);
EXPECT_EQ(0, instruction(block0, 2)->flag_subreg);
}
TEST_F(cmod_propagation_test, not_to_or_intervening_flag_read_incompatible_value)
{
/* Exercise propagation of conditional modifier from a NOT instruction to
* another ALU instruction as performed by cmod_propagate_not.
*/
const fs_builder &bld = v->bld;
fs_reg dest0 = v->vgrf(glsl_type::uint_type);
fs_reg dest1 = v->vgrf(glsl_type::float_type);
fs_reg src0 = v->vgrf(glsl_type::uint_type);
fs_reg src1 = v->vgrf(glsl_type::uint_type);
fs_reg src2 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
set_condmod(BRW_CONDITIONAL_NZ, bld.OR(dest0, src0, src1));
set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
/* = Before =
*
* 0: or.nz.f0(8) dest0 src0 src1
* 1: (+f0) sel(8) dest1 src2 0.0f
* 2: not.nz.f0(8) null dest0
*
* = 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_OR, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 2)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 2)->conditional_mod);
}
TEST_F(cmod_propagation_test, not_to_or_intervening_mismatch_flag_write)
{
/* Exercise propagation of conditional modifier from a NOT instruction to
* another ALU instruction as performed by cmod_propagate_not.
*/
const fs_builder &bld = v->bld;
fs_reg dest0 = v->vgrf(glsl_type::uint_type);
fs_reg dest1 = v->vgrf(glsl_type::uint_type);
fs_reg src0 = v->vgrf(glsl_type::uint_type);
fs_reg src1 = v->vgrf(glsl_type::uint_type);
bld.OR(dest0, src0, src1);
set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest1, src0, src1))
->flag_subreg = 1;
set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
/* = Before =
*
* 0: or(8) dest0 src0 src1
* 1: or.z.f0.1(8) dest1 src0 src1
* 2: not.nz.f0(8) null dest0
*
* = After =
* 0: or.z.f0(8) dest0 src0 src1
* 1: or.z.f0.1(8) dest1 src0 src1
*/
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_OR, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 1)->conditional_mod);
EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
}
TEST_F(cmod_propagation_test, not_to_or_intervening_mismatch_flag_read)
{
/* Exercise propagation of conditional modifier from a NOT instruction to
* another ALU instruction as performed by cmod_propagate_not.
*/
const fs_builder &bld = v->bld;
fs_reg dest0 = v->vgrf(glsl_type::uint_type);
fs_reg dest1 = v->vgrf(glsl_type::float_type);
fs_reg src0 = v->vgrf(glsl_type::uint_type);
fs_reg src1 = v->vgrf(glsl_type::uint_type);
fs_reg src2 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
bld.OR(dest0, src0, src1);
set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
->flag_subreg = 1;
set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
/* = Before =
*
* 0: or(8) dest0 src0 src1
* 1: (+f0.1) sel(8) dest1 src2 0.0f
* 2: not.nz.f0(8) null dest0
*
* = After =
* 0: or.z.f0(8) dest0 src0 src1
* 1: (+f0.1) 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_OR, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
}
TEST_F(cmod_propagation_test, cmp_to_add_float_e)
{
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 neg10(brw_imm_f(-10.0f));
fs_reg pos10(brw_imm_f(10.0f));
bld.ADD(dest, src0, neg10)->saturate = true;
bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_EQ);
/* = Before =
* 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
* 1: cmp.z.f0.0(8) null:F, vgrf1:F, 10f
*
* = After =
* (no changes)
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
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_EQ, instruction(block0, 1)->conditional_mod);
}
TEST_F(cmod_propagation_test, cmp_to_add_float_g)
{
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 neg10(brw_imm_f(-10.0f));
fs_reg pos10(brw_imm_f(10.0f));
bld.ADD(dest, src0, neg10)->saturate = true;
bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_G);
/* = Before =
* 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
* 1: cmp.g.f0.0(8) null:F, vgrf1:F, 10f
*
* = After =
* 0: add.sat.g.f0.0(8) vgrf0:F, vgrf1:F, -10f
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
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, cmp_to_add_float_le)
{
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 neg10(brw_imm_f(-10.0f));
fs_reg pos10(brw_imm_f(10.0f));
bld.ADD(dest, src0, neg10)->saturate = true;
bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_LE);
/* = Before =
* 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
* 1: cmp.le.f0.0(8) null:F, vgrf1:F, 10f
*
* = After =
* 0: add.sat.le.f0.0(8) vgrf0:F, vgrf1:F, -10f
*/
v->calculate_cfg();
bblock_t *block0 = v->cfg->blocks[0];
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);
}
intel/fs: sel.cond writes the flags on Gfx4 and Gfx5 On Gfx4 and Gfx5, sel.l (for min) and sel.ge (for max) are implemented using a separte cmpn and sel instruction. This lowering occurs in fs_vistor::lower_minmax which is called very, very late... a long, long time after the first calls to opt_cmod_propagation. As a result, conditional modifiers can be incorrectly propagated across sel.cond on those platforms. No tests were affected by this change, and I find that quite shocking. After just changing flags_written(), all of the atan tests started failing on ILK. That required the change in cmod_propagatin (and the addition of the prop_across_into_sel_gfx5 unit test). Shader-db results for ILK and GM45 are below. I looked at a couple before and after shaders... and every case that I looked at had experienced incorrect cmod propagation. This affected a LOT of apps! Euro Truck Simulator 2, The Talos Principle, Serious Sam 3, Sanctum 2, Gang Beasts, and on and on... :( I discovered this bug while working on a couple new optimization passes. One of the passes attempts to remove condition modifiers that are never used. The pass made no progress except on ILK and GM45. After investigating a couple of the affected shaders, I noticed that the code in those shaders looked wrong... investigation led to this cause. v2: Trivial changes in the unit tests. v3: Fix type in comment in unit tests. Noticed by Jason and Priit. v4: Tweak handling of BRW_OPCODE_SEL special case. Suggested by Jason. Fixes: df1aec763eb ("i965/fs: Define methods to calculate the flag subset read or written by an fs_inst.") Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> Tested-by: Dave Airlie <airlied@redhat.com> Iron Lake total instructions in shared programs: 8180493 -> 8181781 (0.02%) instructions in affected programs: 541796 -> 543084 (0.24%) helped: 28 HURT: 1158 helped stats (abs) min: 1 max: 1 x̄: 1.00 x̃: 1 helped stats (rel) min: 0.35% max: 0.86% x̄: 0.53% x̃: 0.50% HURT stats (abs) min: 1 max: 3 x̄: 1.14 x̃: 1 HURT stats (rel) min: 0.12% max: 4.00% x̄: 0.37% x̃: 0.23% 95% mean confidence interval for instructions value: 1.06 1.11 95% mean confidence interval for instructions %-change: 0.31% 0.38% Instructions are HURT. total cycles in shared programs: 239420470 -> 239421690 (<.01%) cycles in affected programs: 2925992 -> 2927212 (0.04%) helped: 49 HURT: 157 helped stats (abs) min: 2 max: 284 x̄: 62.69 x̃: 70 helped stats (rel) min: 0.04% max: 6.20% x̄: 1.68% x̃: 1.96% HURT stats (abs) min: 2 max: 48 x̄: 27.34 x̃: 24 HURT stats (rel) min: 0.02% max: 2.91% x̄: 0.31% x̃: 0.20% 95% mean confidence interval for cycles value: -0.80 12.64 95% mean confidence interval for cycles %-change: -0.31% <.01% Inconclusive result (value mean confidence interval includes 0). GM45 total instructions in shared programs: 4985517 -> 4986207 (0.01%) instructions in affected programs: 306935 -> 307625 (0.22%) helped: 14 HURT: 625 helped stats (abs) min: 1 max: 1 x̄: 1.00 x̃: 1 helped stats (rel) min: 0.35% max: 0.82% x̄: 0.52% x̃: 0.49% HURT stats (abs) min: 1 max: 3 x̄: 1.13 x̃: 1 HURT stats (rel) min: 0.12% max: 3.90% x̄: 0.34% x̃: 0.22% 95% mean confidence interval for instructions value: 1.04 1.12 95% mean confidence interval for instructions %-change: 0.29% 0.36% Instructions are HURT. total cycles in shared programs: 153827268 -> 153828052 (<.01%) cycles in affected programs: 1669290 -> 1670074 (0.05%) helped: 24 HURT: 84 helped stats (abs) min: 2 max: 232 x̄: 64.33 x̃: 67 helped stats (rel) min: 0.04% max: 4.62% x̄: 1.60% x̃: 1.94% HURT stats (abs) min: 2 max: 48 x̄: 27.71 x̃: 24 HURT stats (rel) min: 0.02% max: 2.66% x̄: 0.34% x̃: 0.14% 95% mean confidence interval for cycles value: -1.94 16.46 95% mean confidence interval for cycles %-change: -0.29% 0.11% Inconclusive result (value mean confidence interval includes 0). Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12191>
2021-08-02 21:33:17 -07:00
TEST_F(cmod_propagation_test, prop_across_sel_gfx7)
{
const fs_builder &bld = v->bld;
fs_reg dest1 = v->vgrf(glsl_type::float_type);
fs_reg dest2 = 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);
fs_reg src3 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
bld.ADD(dest1, src0, src1);
bld.emit_minmax(dest2, src2, src3, BRW_CONDITIONAL_GE);
bld.CMP(bld.null_reg_f(), dest1, zero, BRW_CONDITIONAL_GE);
/* = Before =
*
* 0: add(8) dest1 src0 src1
* 1: sel.ge(8) dest2 src2 src3
* 2: cmp.ge.f0(8) null dest1 0.0f
*
* = After =
* 0: add.ge.f0(8) dest1 src0 src1
* 1: sel.ge(8) dest2 src2 src3
*/
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_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
}
TEST_F(cmod_propagation_test, prop_across_sel_gfx5)
{
devinfo->ver = 5;
devinfo->verx10 = devinfo->ver * 10;
const fs_builder &bld = v->bld;
fs_reg dest1 = v->vgrf(glsl_type::float_type);
fs_reg dest2 = 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);
fs_reg src3 = v->vgrf(glsl_type::float_type);
fs_reg zero(brw_imm_f(0.0f));
bld.ADD(dest1, src0, src1);
bld.emit_minmax(dest2, src2, src3, BRW_CONDITIONAL_GE);
bld.CMP(bld.null_reg_f(), dest1, zero, BRW_CONDITIONAL_GE);
/* = Before =
*
* 0: add(8) dest1 src0 src1
* 1: sel.ge(8) dest2 src2 src3
* 2: cmp.ge.f0(8) null dest1 0.0f
*
* = After =
* (no changes)
*
* On Gfx4 and Gfx5, sel.l (for min) and sel.ge (for max) are implemented
* using a separate cmpn and sel instruction. This lowering occurs in
* fs_vistor::lower_minmax which is called a long time after the first
* calls to cmod_propagation.
*/
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_SEL, 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, prop_into_sel_gfx5)
{
devinfo->ver = 5;
devinfo->verx10 = devinfo->ver * 10;
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);
fs_reg zero(brw_imm_f(0.0f));
bld.emit_minmax(dest, src0, src1, BRW_CONDITIONAL_GE);
bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
/* = Before =
*
* 0: sel.ge(8) dest src0 src1
* 1: cmp.ge.f0(8) null dest 0.0f
*
* = After =
* (no changes)
*
* Do not copy propagate into a sel.cond instruction. While it does modify
* the flags, the flags are not based on the result compared with zero (as
* with most other instructions). The result is based on the sources
* compared with each other (like cmp.cond).
*/
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_SEL, instruction(block0, 0)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
}