2014-11-05 16:13:59 -08:00
|
|
|
/*
|
|
|
|
|
* Copyright © 2015 Intel Corporation
|
|
|
|
|
*
|
|
|
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
|
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
|
|
|
* to deal in the Software without restriction, including without limitation
|
|
|
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
|
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
|
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
|
|
|
*
|
|
|
|
|
* The above copyright notice and this permission notice (including the next
|
|
|
|
|
* paragraph) shall be included in all copies or substantial portions of the
|
|
|
|
|
* Software.
|
|
|
|
|
*
|
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
|
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
|
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
|
|
|
* IN THE SOFTWARE.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
|
#include "brw_fs.h"
|
|
|
|
|
#include "brw_cfg.h"
|
|
|
|
|
#include "program/program.h"
|
|
|
|
|
|
2015-06-03 18:16:30 +03:00
|
|
|
using namespace brw;
|
|
|
|
|
|
2014-11-05 16:13:59 -08:00
|
|
|
class cmod_propagation_test : public ::testing::Test {
|
|
|
|
|
virtual void SetUp();
|
2021-02-10 16:43:08 +01:00
|
|
|
virtual void TearDown();
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
public:
|
2015-06-22 17:17:56 -07:00
|
|
|
struct brw_compiler *compiler;
|
2021-04-05 13:19:39 -07:00
|
|
|
struct intel_device_info *devinfo;
|
2021-02-10 16:43:08 +01:00
|
|
|
void *ctx;
|
2014-11-05 16:13:59 -08:00
|
|
|
struct brw_wm_prog_data *prog_data;
|
|
|
|
|
struct gl_shader_program *shader_prog;
|
|
|
|
|
fs_visitor *v;
|
2019-03-11 15:49:26 -07:00
|
|
|
|
2021-08-17 16:04:09 -07:00
|
|
|
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);
|
|
|
|
|
|
2021-07-21 13:56:34 -07:00
|
|
|
void test_saturate_prop(enum brw_conditional_mod before,
|
|
|
|
|
enum brw_conditional_mod after,
|
|
|
|
|
enum opcode op,
|
|
|
|
|
enum brw_reg_type add_type,
|
|
|
|
|
enum brw_reg_type op_type,
|
|
|
|
|
bool expected_cmod_prop_progress);
|
2014-11-05 16:13:59 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
class cmod_propagation_fs_visitor : public fs_visitor
|
|
|
|
|
{
|
|
|
|
|
public:
|
2015-06-22 17:17:56 -07:00
|
|
|
cmod_propagation_fs_visitor(struct brw_compiler *compiler,
|
2021-02-10 16:43:08 +01:00
|
|
|
void *mem_ctx,
|
2014-11-05 16:13:59 -08:00
|
|
|
struct brw_wm_prog_data *prog_data,
|
2015-10-01 15:21:57 -07:00
|
|
|
nir_shader *shader)
|
2021-02-10 16:43:08 +01:00
|
|
|
: fs_visitor(compiler, NULL, mem_ctx, NULL,
|
2021-03-23 11:31:51 -07:00
|
|
|
&prog_data->base, shader, 8, -1, false) {}
|
2014-11-05 16:13:59 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void cmod_propagation_test::SetUp()
|
|
|
|
|
{
|
2021-02-10 16:43:08 +01:00
|
|
|
ctx = ralloc_context(NULL);
|
|
|
|
|
compiler = rzalloc(ctx, struct brw_compiler);
|
2021-04-05 13:19:39 -07:00
|
|
|
devinfo = rzalloc(ctx, struct intel_device_info);
|
2015-06-22 17:17:56 -07:00
|
|
|
compiler->devinfo = devinfo;
|
2014-11-05 16:13:59 -08:00
|
|
|
|
2021-02-10 16:43:08 +01:00
|
|
|
prog_data = ralloc(ctx, struct brw_wm_prog_data);
|
2016-10-13 11:41:23 +11:00
|
|
|
nir_shader *shader =
|
2021-02-10 16:43:08 +01:00
|
|
|
nir_shader_create(ctx, MESA_SHADER_FRAGMENT, NULL, NULL);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
2021-02-10 16:43:08 +01:00
|
|
|
v = new cmod_propagation_fs_visitor(compiler, ctx, prog_data, shader);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
2021-03-29 14:41:58 -07:00
|
|
|
devinfo->ver = 7;
|
|
|
|
|
devinfo->verx10 = devinfo->ver * 10;
|
2014-11-05 16:13:59 -08:00
|
|
|
}
|
|
|
|
|
|
2021-02-10 16:43:08 +01:00
|
|
|
void cmod_propagation_test::TearDown()
|
|
|
|
|
{
|
|
|
|
|
delete v;
|
|
|
|
|
v = NULL;
|
|
|
|
|
|
|
|
|
|
ralloc_free(ctx);
|
|
|
|
|
ctx = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-05 16:13:59 -08:00
|
|
|
static fs_inst *
|
|
|
|
|
instruction(bblock_t *block, int num)
|
|
|
|
|
{
|
|
|
|
|
fs_inst *inst = (fs_inst *)block->start();
|
|
|
|
|
for (int i = 0; i < num; i++) {
|
|
|
|
|
inst = (fs_inst *)inst->next;
|
|
|
|
|
}
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
cmod_propagation(fs_visitor *v)
|
|
|
|
|
{
|
2015-10-01 16:41:30 +02:00
|
|
|
const bool print = getenv("TEST_DEBUG");
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
if (print) {
|
|
|
|
|
fprintf(stderr, "= Before =\n");
|
2020-03-06 13:34:13 -08:00
|
|
|
v->cfg->dump();
|
2014-11-05 16:13:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool ret = v->opt_cmod_propagation();
|
|
|
|
|
|
|
|
|
|
if (print) {
|
|
|
|
|
fprintf(stderr, "\n= After =\n");
|
2020-03-06 13:34:13 -08:00
|
|
|
v->cfg->dump();
|
2014-11-05 16:13:59 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, basic)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest src0 src1
|
|
|
|
|
* 1: cmp.ge.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.ge.f0(8) dest src0 src1
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
intel/fs: Fix flag_subreg handling in cmod propagation
There were two errors. First, the pass could propagate conditional
modifiers from an instruction that writes on flag register to an
instruction that writes a different flag register. For example,
cmp.nz.f0.0(16) null:F, vgrf6:F, vgrf5:F
cmp.nz.f0.1(16) null:F, vgrf6:F, vgrf5:F
could be come
cmp.nz.f0.0(16) null:F, vgrf6:F, vgrf5:F
Second, if an instruction writes f0.1 has it's condition propagated, the
modified instruction will incorrectly write flag f0.0. For example,
linterp(16) vgrf6:F, g2:F, attr0:F
cmp.z.f0.1(16) null:F, vgrf6:F, vgrf5:F
(-f0.1) discard_jump(16) (null):UD
could become
linterp.z.f0.0(16) vgrf6:F, g2:F, attr0:F
(-f0.1) discard_jump(16) (null):UD
None of these cases will occur currently. The only time we use f0.1 is
for generating discard intrinsics. In all those cases, we generate a
squence like:
cmp.nz.f0.0(16) vgrf7:F, vgrf6:F, vgrf5:F
(+f0.1) cmp.z(16) null:D, vgrf7:D, 0d
(-f0.1) discard_jump(16) (null):UD
Due to the mixed types and incompatible conditions, this sequence would
never see any cmod propagation. The next patch will change this.
No shader-db changes on any Intel platform.
v2: Fix typo in comment in test case subtract_delete_compare_other_flag.
Noticed by Caio.
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2019-05-22 10:18:06 -07:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-05 16:13:59 -08:00
|
|
|
TEST_F(cmod_propagation_test, cmp_nonzero)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg nonzero(brw_imm_f(1.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), dest, nonzero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest src0 src1
|
|
|
|
|
* 1: cmp.ge.f0(8) null dest 1.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, non_cmod_instruction)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::uint_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::uint_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_ud(0u));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.FBL(dest, src0);
|
|
|
|
|
bld.CMP(bld.null_reg_ud(), dest, zero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: fbl(8) dest src0
|
|
|
|
|
* 1: cmp.ge.f0(8) null dest 0u
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, intervening_flag_write)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src2 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest src0 src1
|
|
|
|
|
* 1: cmp.ge.f0(8) null src2 0.0f
|
|
|
|
|
* 2: cmp.ge.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-22 12:32:03 -07:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-05 16:13:59 -08:00
|
|
|
TEST_F(cmod_propagation_test, intervening_flag_read)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src2 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest0, src0, src1);
|
|
|
|
|
set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest0 src0 src1
|
|
|
|
|
* 1: (+f0) sel(8) dest1 src2 0.0f
|
|
|
|
|
* 2: cmp.ge.f0(8) null dest0 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-22 12:32:03 -07:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-05 16:13:59 -08:00
|
|
|
TEST_F(cmod_propagation_test, intervening_dest_write)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-11-05 16:13:59 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::vec4_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src2 = v->vgrf(glsl_type::vec2_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-18 12:07:27 -07:00
|
|
|
bld.ADD(offset(dest, bld, 2), src0, src1);
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.emit(SHADER_OPCODE_TEX, dest, src2)
|
2016-09-07 13:38:20 -07:00
|
|
|
->size_written = 4 * REG_SIZE;
|
2015-06-18 12:07:27 -07:00
|
|
|
bld.CMP(bld.null_reg_f(), offset(dest, bld, 2), zero, BRW_CONDITIONAL_GE);
|
2014-11-05 16:13:59 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest+2 src0 src1
|
|
|
|
|
* 1: tex(8) rlen 4 dest+0 src2
|
|
|
|
|
* 2: cmp.ge.f0(8) null dest+2 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
|
|
|
|
|
}
|
2015-01-03 12:18:15 -08:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, intervening_flag_read_same_value)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2015-01-03 12:18:15 -08:00
|
|
|
fs_reg dest0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src2 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
set_condmod(BRW_CONDITIONAL_GE, bld.ADD(dest0, src0, src1));
|
|
|
|
|
set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
|
2015-01-03 12:18:15 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add.ge.f0(8) dest0 src0 src1
|
|
|
|
|
* 1: (+f0) sel(8) dest1 src2 0.0f
|
|
|
|
|
* 2: cmp.ge.f0(8) null dest0 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.ge.f0(8) dest0 src0 src1
|
|
|
|
|
* 1: (+f0) sel(8) dest1 src2 0.0f
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
|
|
|
|
|
}
|
2014-12-30 12:18:57 -08:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, negate)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2014-12-30 12:18:57 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest, src0, src1);
|
2014-12-30 12:18:57 -08:00
|
|
|
dest.negate = true;
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
|
2014-12-30 12:18:57 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest src0 src1
|
|
|
|
|
* 1: cmp.ge.f0(8) null -dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.le.f0(8) dest src0 src1
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
i965/fs: Add support for removing MOV.NZ instructions.
For some reason, we occasionally write the flag register with a MOV.NZ
instruction:
add(8) g25<1>F -g6<0,1,0>F g15<8,8,1>F
cmp.l.f0(8) g26<1>D g25<8,8,1>F 0F
mov.nz.f0(8) null g26<8,8,1>D
A MOV.NZ instruction on the result of a CMP is like comparing for
equality with true in C. It's useless. Removing it allows us to
generate:
add.l.f0(8) null -g6<0,1,0>F g15<8,8,1>F
total instructions in shared programs: 5955701 -> 5951657 (-0.07%)
instructions in affected programs: 302910 -> 298866 (-1.34%)
GAINED: 1
LOST: 0
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2014-12-30 17:19:41 -08:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, movnz)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
i965/fs: Add support for removing MOV.NZ instructions.
For some reason, we occasionally write the flag register with a MOV.NZ
instruction:
add(8) g25<1>F -g6<0,1,0>F g15<8,8,1>F
cmp.l.f0(8) g26<1>D g25<8,8,1>F 0F
mov.nz.f0(8) null g26<8,8,1>D
A MOV.NZ instruction on the result of a CMP is like comparing for
equality with true in C. It's useless. Removing it allows us to
generate:
add.l.f0(8) null -g6<0,1,0>F g15<8,8,1>F
total instructions in shared programs: 5955701 -> 5951657 (-0.07%)
instructions in affected programs: 302910 -> 298866 (-1.34%)
GAINED: 1
LOST: 0
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2014-12-30 17:19:41 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.CMP(dest, src0, src1, BRW_CONDITIONAL_GE);
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_NZ,
|
|
|
|
|
bld.MOV(bld.null_reg_f(), dest));
|
i965/fs: Add support for removing MOV.NZ instructions.
For some reason, we occasionally write the flag register with a MOV.NZ
instruction:
add(8) g25<1>F -g6<0,1,0>F g15<8,8,1>F
cmp.l.f0(8) g26<1>D g25<8,8,1>F 0F
mov.nz.f0(8) null g26<8,8,1>D
A MOV.NZ instruction on the result of a CMP is like comparing for
equality with true in C. It's useless. Removing it allows us to
generate:
add.l.f0(8) null -g6<0,1,0>F g15<8,8,1>F
total instructions in shared programs: 5955701 -> 5951657 (-0.07%)
instructions in affected programs: 302910 -> 298866 (-1.34%)
GAINED: 1
LOST: 0
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
2014-12-30 17:19:41 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: cmp.ge.f0(8) dest src0 src1
|
|
|
|
|
* 1: mov.nz.f0(8) null dest
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: cmp.ge.f0(8) dest src0 src1
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
2015-02-27 10:22:21 -08:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, different_types_cmod_with_zero)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
2015-02-27 10:22:21 -08:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::int_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::int_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::int_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), retype(dest, BRW_REGISTER_TYPE_F), zero,
|
|
|
|
|
BRW_CONDITIONAL_GE);
|
2015-02-27 10:22:21 -08:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add(8) dest:D src0:D src1:D
|
|
|
|
|
* 1: cmp.ge.f0(8) null:F dest:F 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, andnz_one)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::int_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
|
|
|
|
fs_reg one(brw_imm_d(1));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_NZ,
|
|
|
|
|
bld.AND(bld.null_reg_d(), dest, one));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: cmp.l.f0(8) dest:F src0:F 0F
|
|
|
|
|
* 1: and.nz.f0(8) null:D dest:D 1D
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: cmp.l.f0(8) dest:F src0:F 0F
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_TRUE(retype(dest, BRW_REGISTER_TYPE_F)
|
|
|
|
|
.equals(instruction(block0, 0)->dst));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, andnz_non_one)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::int_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
|
|
|
|
fs_reg nonone(brw_imm_d(38));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_NZ,
|
|
|
|
|
bld.AND(bld.null_reg_d(), dest, nonone));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: cmp.l.f0(8) dest:F src0:F 0F
|
|
|
|
|
* 1: and.nz.f0(8) null:D dest:D 38D
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
2015-06-03 18:16:30 +03:00
|
|
|
const fs_builder &bld = v->bld;
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
fs_reg dest = v->vgrf(glsl_type::int_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
2015-11-02 11:26:16 -08:00
|
|
|
fs_reg zero(brw_imm_f(0.0f));
|
|
|
|
|
fs_reg one(brw_imm_d(1));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
2015-06-03 18:16:30 +03:00
|
|
|
bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_Z,
|
|
|
|
|
bld.AND(bld.null_reg_d(), dest, one));
|
i965/fs: Handle CMP.nz ... 0 and AND.nz ... 1 similarly in cmod propagation
Espically on platforms that do not natively generate 0u and ~0u for
Boolean results, we generate a lot of sequences where a CMP is
followed by an AND with 1. emit_bool_to_cond_code does this, for
example. On ILK, this results in a sequence like:
add(8) g3<1>F g8<8,8,1>F -g4<0,1,0>F
cmp.l.f0(8) g3<1>D g3<8,8,1>F 0F
and.nz.f0(8) null g3<8,8,1>D 1D
(+f0) iff(8) Jump: 6
The AND.nz is obviously redundant. By propagating the cmod, we can
instead generate
add.l.f0(8) null g8<8,8,1>F -g4<0,1,0>F
(+f0) iff(8) Jump: 6
Existing code already handles the propagation from the CMP to the ADD.
Shader-db results:
GM45 (0x2A42):
total instructions in shared programs: 3550829 -> 3550788 (-0.00%)
instructions in affected programs: 10028 -> 9987 (-0.41%)
helped: 24
Iron Lake (0x0046):
total instructions in shared programs: 4993146 -> 4993105 (-0.00%)
instructions in affected programs: 9675 -> 9634 (-0.42%)
helped: 24
Ivy Bridge (0x0166):
total instructions in shared programs: 6291870 -> 6291794 (-0.00%)
instructions in affected programs: 17914 -> 17838 (-0.42%)
helped: 48
Haswell (0x0426):
total instructions in shared programs: 5779256 -> 5779180 (-0.00%)
instructions in affected programs: 16694 -> 16618 (-0.46%)
helped: 48
Broadwell (0x162E):
total instructions in shared programs: 6823088 -> 6823014 (-0.00%)
instructions in affected programs: 15824 -> 15750 (-0.47%)
helped: 46
No chage on Sandy Bridge or on any platform when NIR is used.
v2: Add unit tests suggested by Matt. Remove spurious writes_flag()
check on scan_inst when scan_inst is known to be BRW_OPCODE_CMP (also
suggested by Matt).
v3: Fix some comments and remove some explicit int() casts in fs_reg
constructors in the unit tests. Both suggested by Matt.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2015-02-03 21:12:28 +02:00
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: cmp.l.f0(8) dest:F src0:F 0F
|
|
|
|
|
* 1: and.z.f0(8) null:D dest:D 1D
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
i965/fs: Propagate conditional modifiers from compares to adds
The math inside the add and the cmp in this instruction sequence is the
same. We can utilize this to eliminate the compare.
add(8) g5<1>F g2<8,8,1>F g64.5<0,1,0>F { align1 1Q compacted };
cmp.z.f0(8) null<1>F g2<8,8,1>F -g64.5<0,1,0>F { align1 1Q switch };
(-f0) sel(8) g8<1>F (abs)g5<8,8,1>F 3e-37F { align1 1Q };
This is reduced to:
add.z.f0(8) g5<1>F g2<8,8,1>F g64.5<0,1,0>F { align1 1Q compacted };
(-f0) sel(8) g8<1>F (abs)g5<8,8,1>F 3e-37F { align1 1Q };
This optimization pass could do even better. The nature of converting
vectorized code from the GLSL front end to scalar code in NIR results in
sequences like:
add(8) g7<1>F g4<8,8,1>F g64.5<0,1,0>F { align1 1Q compacted };
add(8) g6<1>F g3<8,8,1>F g64.5<0,1,0>F { align1 1Q compacted };
add(8) g5<1>F g2<8,8,1>F g64.5<0,1,0>F { align1 1Q compacted };
cmp.z.f0(8) null<1>F g2<8,8,1>F -g64.5<0,1,0>F { align1 1Q switch };
(-f0) sel(8) g8<1>F (abs)g5<8,8,1>F 3e-37F { align1 1Q };
cmp.z.f0(8) null<1>F g3<8,8,1>F -g64.5<0,1,0>F { align1 1Q switch };
(-f0) sel(8) g10<1>F (abs)g6<8,8,1>F 3e-37F { align1 1Q };
cmp.z.f0(8) null<1>F g4<8,8,1>F -g64.5<0,1,0>F { align1 1Q switch };
(-f0) sel(8) g12<1>F (abs)g7<8,8,1>F 3e-37F { align1 1Q };
In this sequence, only the first cmp.z is removed. With different
scheduling, all 3 could get removed.
Skylake
total instructions in shared programs: 14407009 -> 14400173 (-0.05%)
instructions in affected programs: 1307274 -> 1300438 (-0.52%)
helped: 4880
HURT: 0
helped stats (abs) min: 1 max: 33 x̄: 1.40 x̃: 1
helped stats (rel) min: 0.03% max: 8.70% x̄: 0.70% x̃: 0.52%
95% mean confidence interval for instructions value: -1.45 -1.35
95% mean confidence interval for instructions %-change: -0.72% -0.69%
Instructions are helped.
total cycles in shared programs: 532943169 -> 532923528 (<.01%)
cycles in affected programs: 14065798 -> 14046157 (-0.14%)
helped: 2703
HURT: 339
helped stats (abs) min: 1 max: 1062 x̄: 12.27 x̃: 2
helped stats (rel) min: <.01% max: 28.72% x̄: 0.38% x̃: 0.21%
HURT stats (abs) min: 1 max: 739 x̄: 39.86 x̃: 12
HURT stats (rel) min: 0.02% max: 27.69% x̄: 1.38% x̃: 0.41%
95% mean confidence interval for cycles value: -8.66 -4.26
95% mean confidence interval for cycles %-change: -0.24% -0.14%
Cycles are helped.
LOST: 0
GAINED: 1
Broadwell
total instructions in shared programs: 14719636 -> 14712949 (-0.05%)
instructions in affected programs: 1288188 -> 1281501 (-0.52%)
helped: 4845
HURT: 0
helped stats (abs) min: 1 max: 33 x̄: 1.38 x̃: 1
helped stats (rel) min: 0.03% max: 8.00% x̄: 0.70% x̃: 0.52%
95% mean confidence interval for instructions value: -1.43 -1.33
95% mean confidence interval for instructions %-change: -0.72% -0.68%
Instructions are helped.
total cycles in shared programs: 559599253 -> 559581699 (<.01%)
cycles in affected programs: 13315565 -> 13298011 (-0.13%)
helped: 2600
HURT: 269
helped stats (abs) min: 1 max: 2128 x̄: 12.24 x̃: 2
helped stats (rel) min: <.01% max: 23.95% x̄: 0.41% x̃: 0.20%
HURT stats (abs) min: 1 max: 790 x̄: 53.07 x̃: 20
HURT stats (rel) min: 0.02% max: 15.96% x̄: 1.55% x̃: 0.75%
95% mean confidence interval for cycles value: -8.47 -3.77
95% mean confidence interval for cycles %-change: -0.27% -0.18%
Cycles are helped.
LOST: 0
GAINED: 8
Haswell
total instructions in shared programs: 12978609 -> 12973483 (-0.04%)
instructions in affected programs: 932921 -> 927795 (-0.55%)
helped: 3480
HURT: 0
helped stats (abs) min: 1 max: 33 x̄: 1.47 x̃: 1
helped stats (rel) min: 0.03% max: 7.84% x̄: 0.78% x̃: 0.58%
95% mean confidence interval for instructions value: -1.53 -1.42
95% mean confidence interval for instructions %-change: -0.80% -0.75%
Instructions are helped.
total cycles in shared programs: 410270788 -> 410250531 (<.01%)
cycles in affected programs: 10986161 -> 10965904 (-0.18%)
helped: 2087
HURT: 254
helped stats (abs) min: 1 max: 2672 x̄: 14.63 x̃: 4
helped stats (rel) min: <.01% max: 39.61% x̄: 0.42% x̃: 0.21%
HURT stats (abs) min: 1 max: 519 x̄: 40.49 x̃: 16
HURT stats (rel) min: 0.01% max: 12.83% x̄: 1.20% x̃: 0.47%
95% mean confidence interval for cycles value: -12.82 -4.49
95% mean confidence interval for cycles %-change: -0.31% -0.18%
Cycles are helped.
LOST: 0
GAINED: 5
Ivy Bridge
total instructions in shared programs: 11686082 -> 11681548 (-0.04%)
instructions in affected programs: 937696 -> 933162 (-0.48%)
helped: 3150
HURT: 0
helped stats (abs) min: 1 max: 33 x̄: 1.44 x̃: 1
helped stats (rel) min: 0.03% max: 7.84% x̄: 0.69% x̃: 0.49%
95% mean confidence interval for instructions value: -1.49 -1.38
95% mean confidence interval for instructions %-change: -0.71% -0.67%
Instructions are helped.
total cycles in shared programs: 257514962 -> 257492471 (<.01%)
cycles in affected programs: 11524149 -> 11501658 (-0.20%)
helped: 1970
HURT: 239
helped stats (abs) min: 1 max: 3525 x̄: 17.48 x̃: 3
helped stats (rel) min: <.01% max: 49.60% x̄: 0.46% x̃: 0.17%
HURT stats (abs) min: 1 max: 1358 x̄: 50.00 x̃: 15
HURT stats (rel) min: 0.02% max: 59.88% x̄: 1.84% x̃: 0.65%
95% mean confidence interval for cycles value: -17.01 -3.35
95% mean confidence interval for cycles %-change: -0.33% -0.08%
Cycles are helped.
LOST: 9
GAINED: 1
Sandy Bridge
total instructions in shared programs: 10432841 -> 10429893 (-0.03%)
instructions in affected programs: 685071 -> 682123 (-0.43%)
helped: 2453
HURT: 0
helped stats (abs) min: 1 max: 9 x̄: 1.20 x̃: 1
helped stats (rel) min: 0.02% max: 7.55% x̄: 0.64% x̃: 0.46%
95% mean confidence interval for instructions value: -1.23 -1.17
95% mean confidence interval for instructions %-change: -0.67% -0.62%
Instructions are helped.
total cycles in shared programs: 146133660 -> 146134195 (<.01%)
cycles in affected programs: 3991634 -> 3992169 (0.01%)
helped: 1237
HURT: 153
helped stats (abs) min: 1 max: 2853 x̄: 6.93 x̃: 2
helped stats (rel) min: <.01% max: 29.00% x̄: 0.24% x̃: 0.14%
HURT stats (abs) min: 1 max: 1740 x̄: 59.56 x̃: 12
HURT stats (rel) min: 0.03% max: 78.98% x̄: 1.96% x̃: 0.42%
95% mean confidence interval for cycles value: -5.13 5.90
95% mean confidence interval for cycles %-change: -0.17% 0.16%
Inconclusive result (value mean confidence interval includes 0).
LOST: 0
GAINED: 1
GM45 and Iron Lake had similar results (GM45 shown):
total instructions in shared programs: 4800332 -> 4798380 (-0.04%)
instructions in affected programs: 565995 -> 564043 (-0.34%)
helped: 1451
HURT: 0
helped stats (abs) min: 1 max: 20 x̄: 1.35 x̃: 1
helped stats (rel) min: 0.05% max: 5.26% x̄: 0.47% x̃: 0.31%
95% mean confidence interval for instructions value: -1.40 -1.29
95% mean confidence interval for instructions %-change: -0.50% -0.45%
Instructions are helped.
total cycles in shared programs: 122032318 -> 122027798 (<.01%)
cycles in affected programs: 8334868 -> 8330348 (-0.05%)
helped: 1029
HURT: 1
helped stats (abs) min: 2 max: 40 x̄: 4.43 x̃: 2
helped stats (rel) min: <.01% max: 1.83% x̄: 0.09% x̃: 0.04%
HURT stats (abs) min: 38 max: 38 x̄: 38.00 x̃: 38
HURT stats (rel) min: 0.25% max: 0.25% x̄: 0.25% x̃: 0.25%
95% mean confidence interval for cycles value: -4.70 -4.08
95% mean confidence interval for cycles %-change: -0.09% -0.08%
Cycles are helped.
Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2018-03-09 13:45:01 -08:00
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, add_not_merge_with_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* The addition and the implicit subtraction in the compare do not compute
|
|
|
|
|
* related values.
|
|
|
|
|
*
|
|
|
|
|
* = Before =
|
|
|
|
|
* 0: add(8) dest:F src0:F src1:F
|
|
|
|
|
* 1: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_merge_with_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest, src0, negate(src1));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest:F src0:F -src1:F
|
|
|
|
|
* 1: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.l.f0(8) dest:F src0:F -src1:F
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_immediate_merge_with_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg one(brw_imm_f(1.0f));
|
|
|
|
|
fs_reg negative_one(brw_imm_f(-1.0f));
|
|
|
|
|
|
|
|
|
|
bld.ADD(dest, src0, negative_one);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, one, BRW_CONDITIONAL_NZ);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest:F src0:F -1.0f
|
|
|
|
|
* 1: cmp.nz.f0(8) null:F src0:F 1.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.nz.f0(8) dest:F src0:F -1.0f
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_merge_with_compare_intervening_add)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest0, src0, negate(src1));
|
|
|
|
|
bld.ADD(dest1, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: add(8) dest1:F src0:F src1:F
|
|
|
|
|
* 2: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.l.f0(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: add(8) dest1:F src0:F src1:F
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_partial_write)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest0, src0, negate(src1));
|
|
|
|
|
set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, src0, negate(src1)));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: (+f0) add(8) dest1:F src0:F -src1:F
|
|
|
|
|
* 2: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_add)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest0, src0, negate(src1));
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_EQ, bld.ADD(dest1, src0, src1));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: add.z.f0(8) dest1:F src0:F src1:F
|
|
|
|
|
* 2: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* (no changes)
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_FALSE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, add_merge_with_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest, src0, src1);
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, negate(src1), BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add(8) dest:F src0:F src1:F
|
|
|
|
|
* 1: cmp.l.f0(8) null:F src0:F -src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.l.f0(8) dest:F src0:F src1:F
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, negative_subtract_merge_with_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
bld.ADD(dest, src1, negate(src0));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* The result of the subtract is the negatiion of the result of the
|
|
|
|
|
* implicit subtract in the compare, so the condition must change.
|
|
|
|
|
*
|
|
|
|
|
* = Before =
|
|
|
|
|
* 0: add(8) dest:F src1:F -src0:F
|
|
|
|
|
* 1: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.g.f0(8) dest:F src0:F -src1:F
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, subtract_delete_compare)
|
|
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
|
|
|
|
fs_reg dest = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg dest1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src0 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src1 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
fs_reg src2 = v->vgrf(glsl_type::float_type);
|
|
|
|
|
|
|
|
|
|
set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)));
|
|
|
|
|
set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2));
|
|
|
|
|
bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
|
|
|
|
|
|
|
|
|
|
/* = Before =
|
|
|
|
|
* 0: add.l.f0(8) dest0:F src0:F -src1:F
|
|
|
|
|
* 1: (+f0) mov(0) dest1:F src2:F
|
|
|
|
|
* 2: cmp.l.f0(8) null:F src0:F src1:F
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.l.f0(8) dest:F src0:F -src1:F
|
|
|
|
|
* 1: (+f0) mov(0) dest1:F src2:F
|
|
|
|
|
*/
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(2, block0->end_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_TRUE(cmod_propagation(v));
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
|
|
|
|
|
EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
|
|
|
|
|
}
|
|
|
|
|
|
intel/fs: Fix flag_subreg handling in cmod propagation
There were two errors. First, the pass could propagate conditional
modifiers from an instruction that writes on flag register to an
instruction that writes a different flag register. For example,
cmp.nz.f0.0(16) null:F, vgrf6:F, vgrf5:F
cmp.nz.f0.1(16) null:F, vgrf6:F, vgrf5:F
could be come
cmp.nz.f0.0(16) null:F, vgrf6:F, vgrf5:F
Second, if an instruction writes f0.1 has it's condition propagated, the
modified instruction will incorrectly write flag f0.0. For example,
linterp(16) vgrf6:F, g2:F, attr0:F
cmp.z.f0.1(16) null:F, vgrf6:F, vgrf5:F
(-f0.1) discard_jump(16) (null):UD
could become
linterp.z.f0.0(16) vgrf6:F, g2:F, attr0:F
(-f0.1) discard_jump(16) (null):UD
None of these cases will occur currently. The only time we use f0.1 is
for generating discard intrinsics. In all those cases, we generate a
squence like:
cmp.nz.f0.0(16) vgrf7:F, vgrf6:F, vgrf5:F
(+f0.1) cmp.z(16) null:D, vgrf7:D, 0d
(-f0.1) discard_jump(16) (null):UD
Due to the mixed types and incompatible conditions, this sequence would
never see any cmod propagation. The next patch will change this.
No shader-db changes on any Intel platform.
v2: Fix typo in comment in test case subtract_delete_compare_other_flag.
Noticed by Caio.
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2019-05-22 10:18:06 -07:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-22 12:32:03 -07:00
|
|
|
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);
|
|
|
|
|
}
|
2019-02-11 13:41:32 -08:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2019-03-11 15:49:26 -07:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-08-17 16:04:09 -07:00
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*/
|
|
|
|
|
test_mov_prop(BRW_CONDITIONAL_Z,
|
|
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*/
|
|
|
|
|
test_mov_prop(BRW_CONDITIONAL_L,
|
|
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*/
|
|
|
|
|
test_mov_prop(BRW_CONDITIONAL_G,
|
|
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*/
|
|
|
|
|
test_mov_prop(BRW_CONDITIONAL_LE,
|
|
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*/
|
|
|
|
|
test_mov_prop(BRW_CONDITIONAL_GE,
|
|
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*/
|
|
|
|
|
test_mov_prop(BRW_CONDITIONAL_Z,
|
|
|
|
|
BRW_REGISTER_TYPE_D,
|
|
|
|
|
BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*/
|
|
|
|
|
test_mov_prop(BRW_CONDITIONAL_L,
|
|
|
|
|
BRW_REGISTER_TYPE_D,
|
|
|
|
|
BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*/
|
|
|
|
|
test_mov_prop(BRW_CONDITIONAL_G,
|
|
|
|
|
BRW_REGISTER_TYPE_D,
|
|
|
|
|
BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*/
|
|
|
|
|
test_mov_prop(BRW_CONDITIONAL_LE,
|
|
|
|
|
BRW_REGISTER_TYPE_D,
|
|
|
|
|
BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*/
|
|
|
|
|
test_mov_prop(BRW_CONDITIONAL_GE,
|
|
|
|
|
BRW_REGISTER_TYPE_D,
|
|
|
|
|
BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* In spite of the type conversion, the Z test would be safe to propagate.
|
|
|
|
|
*/
|
|
|
|
|
test_mov_prop(BRW_CONDITIONAL_Z,
|
|
|
|
|
BRW_REGISTER_TYPE_D,
|
|
|
|
|
BRW_REGISTER_TYPE_UD,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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 =
|
|
|
|
|
* No changes. cmod propagation bails on every MOV except MOV.NZ.
|
|
|
|
|
*
|
|
|
|
|
* 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);
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-11 15:49:26 -07:00
|
|
|
void
|
2021-07-21 13:56:34 -07:00
|
|
|
cmod_propagation_test::test_saturate_prop(enum brw_conditional_mod before,
|
|
|
|
|
enum brw_conditional_mod after,
|
|
|
|
|
enum opcode op,
|
|
|
|
|
enum brw_reg_type add_type,
|
|
|
|
|
enum brw_reg_type op_type,
|
|
|
|
|
bool expected_cmod_prop_progress)
|
2019-03-11 15:49:26 -07:00
|
|
|
{
|
|
|
|
|
const fs_builder &bld = v->bld;
|
2021-07-21 13:56:34 -07:00
|
|
|
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));
|
2019-03-11 15:49:26 -07:00
|
|
|
|
|
|
|
|
bld.ADD(dest, src0, src1)->saturate = true;
|
|
|
|
|
|
|
|
|
|
assert(op == BRW_OPCODE_CMP || op == BRW_OPCODE_MOV);
|
2021-07-21 13:56:34 -07:00
|
|
|
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;
|
|
|
|
|
}
|
2019-03-11 15:49:26 -07:00
|
|
|
|
|
|
|
|
v->calculate_cfg();
|
|
|
|
|
bblock_t *block0 = v->cfg->blocks[0];
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
EXPECT_EQ(1, block0->end_ip);
|
|
|
|
|
|
2021-07-21 13:56:34 -07:00
|
|
|
EXPECT_EQ(expected_cmod_prop_progress, cmod_propagation(v));
|
2019-03-11 15:49:26 -07:00
|
|
|
EXPECT_EQ(0, block0->start_ip);
|
|
|
|
|
|
|
|
|
|
EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
|
2021-07-21 13:56:34 -07:00
|
|
|
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);
|
2019-03-11 15:49:26 -07:00
|
|
|
EXPECT_TRUE(instruction(block0, 0)->saturate);
|
2021-07-21 13:56:34 -07:00
|
|
|
|
|
|
|
|
if (expected_cmod_prop_progress) {
|
|
|
|
|
EXPECT_EQ(0, block0->end_ip);
|
|
|
|
|
EXPECT_EQ(after, 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);
|
|
|
|
|
}
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, float_saturate_nz_cmp)
|
|
|
|
|
{
|
|
|
|
|
/* 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: cmp.nz.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.sat.g.f0(8) dest src0 src1
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_CONDITIONAL_G,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
true);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, float_saturate_nz_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.nz.f0(8) null dest
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.sat.g.f0(8) dest src0 src1
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_CONDITIONAL_G,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
true);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, float_saturate_z_cmp)
|
|
|
|
|
{
|
|
|
|
|
/* 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: cmp.z.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.sat.le.f0(8) dest src0 src1
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_Z, BRW_CONDITIONAL_LE,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
true);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, float_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 =
|
|
|
|
|
* 0: add.sat.le.f0(8) dest src0 src1
|
|
|
|
|
*/
|
|
|
|
|
#if 1
|
|
|
|
|
/* cmod propagation bails on every MOV except MOV.NZ. */
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_Z, BRW_CONDITIONAL_Z,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
#else
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_Z, BRW_CONDITIONAL_LE,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
true);
|
2019-03-11 15:49:26 -07:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, float_saturate_g_cmp)
|
|
|
|
|
{
|
|
|
|
|
/* 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: cmp.g.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.sat.g.f0(8) dest src0 src1
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_G, BRW_CONDITIONAL_G,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
true);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, float_saturate_g_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.g.f0(8) null dest
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.sat.g.f0(8) dest src0 src1
|
|
|
|
|
*/
|
|
|
|
|
#if 1
|
|
|
|
|
/* cmod propagation bails on every MOV except MOV.NZ. */
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_G, BRW_CONDITIONAL_G,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
#else
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_G, BRW_CONDITIONAL_G,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
true);
|
2019-03-11 15:49:26 -07:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, float_saturate_le_cmp)
|
|
|
|
|
{
|
|
|
|
|
/* 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: cmp.le.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.sat.le.f0(8) dest src0 src1
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_LE, BRW_CONDITIONAL_LE,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
true);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, float_saturate_le_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.le.f0(8) null dest
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* 0: add.sat.le.f0(8) dest src0 src1
|
|
|
|
|
*/
|
|
|
|
|
#if 1
|
|
|
|
|
/* cmod propagation bails on every MOV except MOV.NZ. */
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_LE, BRW_CONDITIONAL_LE,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
#else
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_LE, BRW_CONDITIONAL_LE,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
true);
|
2019-03-11 15:49:26 -07:00
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, float_saturate_l_cmp)
|
|
|
|
|
{
|
|
|
|
|
/* With the saturate modifier, the comparison happens before clamping to
|
|
|
|
|
* [0, 1]. There is no before / after equivalence for (sat(x) < 0).
|
|
|
|
|
*
|
|
|
|
|
* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add.sat(8) dest src0 src1
|
|
|
|
|
* 1: cmp.l.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* No change
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_L, BRW_CONDITIONAL_L,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
|
TEST_F(cmod_propagation_test, float_saturate_l_mov)
|
|
|
|
|
{
|
|
|
|
|
/* With the saturate modifier, the comparison happens before clamping to
|
|
|
|
|
* [0, 1]. There is no before / after equivalence for (sat(x) < 0).
|
|
|
|
|
*
|
|
|
|
|
* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add.sat(8) dest src0 src1
|
|
|
|
|
* 1: mov.l.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* No change
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_L, BRW_CONDITIONAL_L,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, float_saturate_ge_cmp)
|
|
|
|
|
{
|
|
|
|
|
/* With the saturate modifier, the comparison happens before clamping to
|
|
|
|
|
* [0, 1]. There is no before / after equivalence for (sat(x) >= 0).
|
|
|
|
|
*
|
|
|
|
|
* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add.sat(8) dest src0 src1
|
|
|
|
|
* 1: cmp.ge.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* No change
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_GE, BRW_CONDITIONAL_GE,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(cmod_propagation_test, float_saturate_ge_mov)
|
|
|
|
|
{
|
|
|
|
|
/* With the saturate modifier, the comparison happens before clamping to
|
|
|
|
|
* [0, 1]. There is no before / after equivalence for (sat(x) >= 0).
|
|
|
|
|
*
|
|
|
|
|
* = Before =
|
|
|
|
|
*
|
|
|
|
|
* 0: add.sat(8) dest src0 src1
|
|
|
|
|
* 1: mov.ge.f0(8) null dest 0.0f
|
|
|
|
|
*
|
|
|
|
|
* = After =
|
|
|
|
|
* No change
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_GE, BRW_CONDITIONAL_GE,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_CONDITIONAL_NZ,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_CONDITIONAL_NZ,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_Z, BRW_CONDITIONAL_Z,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_Z, BRW_CONDITIONAL_Z,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_G, BRW_CONDITIONAL_G,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_G, BRW_CONDITIONAL_G,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_LE, BRW_CONDITIONAL_LE,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_LE, BRW_CONDITIONAL_LE,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_L, BRW_CONDITIONAL_L,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_L, BRW_CONDITIONAL_L,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_GE, BRW_CONDITIONAL_GE,
|
|
|
|
|
BRW_OPCODE_CMP,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
*/
|
2021-07-21 13:56:34 -07:00
|
|
|
test_saturate_prop(BRW_CONDITIONAL_GE, BRW_CONDITIONAL_GE,
|
|
|
|
|
BRW_OPCODE_MOV,
|
|
|
|
|
BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
|
|
|
|
|
false);
|
2019-03-11 15:49:26 -07:00
|
|
|
}
|
2019-05-22 11:06:19 -07:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
intel/fs: Fix flag_subreg handling in cmod propagation
There were two errors. First, the pass could propagate conditional
modifiers from an instruction that writes on flag register to an
instruction that writes a different flag register. For example,
cmp.nz.f0.0(16) null:F, vgrf6:F, vgrf5:F
cmp.nz.f0.1(16) null:F, vgrf6:F, vgrf5:F
could be come
cmp.nz.f0.0(16) null:F, vgrf6:F, vgrf5:F
Second, if an instruction writes f0.1 has it's condition propagated, the
modified instruction will incorrectly write flag f0.0. For example,
linterp(16) vgrf6:F, g2:F, attr0:F
cmp.z.f0.1(16) null:F, vgrf6:F, vgrf5:F
(-f0.1) discard_jump(16) (null):UD
could become
linterp.z.f0.0(16) vgrf6:F, g2:F, attr0:F
(-f0.1) discard_jump(16) (null):UD
None of these cases will occur currently. The only time we use f0.1 is
for generating discard intrinsics. In all those cases, we generate a
squence like:
cmp.nz.f0.0(16) vgrf7:F, vgrf6:F, vgrf5:F
(+f0.1) cmp.z(16) null:D, vgrf7:D, 0d
(-f0.1) discard_jump(16) (null):UD
Due to the mixed types and incompatible conditions, this sequence would
never see any cmod propagation. The next patch will change this.
No shader-db changes on any Intel platform.
v2: Fix typo in comment in test case subtract_delete_compare_other_flag.
Noticed by Caio.
Reviewed-by: Caio Marcelo de Oliveira Filho <caio.oliveira@intel.com>
Reviewed-by: Matt Turner <mattst88@gmail.com>
2019-05-22 10:18:06 -07:00
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2019-05-22 11:06:19 -07:00
|
|
|
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);
|
|
|
|
|
}
|
2019-05-22 12:32:03 -07:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
2020-03-12 19:42:37 +02:00
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|