Home | History | Annotate | Download | only in i965
      1 /*
      2  * Copyright  2015 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     21  * IN THE SOFTWARE.
     22  *
     23  * Based on test_fs_cmod_propagation.cpp
     24  */
     25 
     26 #include <gtest/gtest.h>
     27 #include "brw_vec4.h"
     28 #include "brw_vec4_builder.h"
     29 #include "brw_cfg.h"
     30 #include "program/program.h"
     31 
     32 using namespace brw;
     33 
     34 class cmod_propagation_test : public ::testing::Test {
     35    virtual void SetUp();
     36 
     37 public:
     38    struct brw_compiler *compiler;
     39    struct gen_device_info *devinfo;
     40    struct gl_context *ctx;
     41    struct gl_shader_program *shader_prog;
     42    struct brw_vue_prog_data *prog_data;
     43    vec4_visitor *v;
     44 };
     45 
     46 class cmod_propagation_vec4_visitor : public vec4_visitor
     47 {
     48 public:
     49    cmod_propagation_vec4_visitor(struct brw_compiler *compiler,
     50                                  nir_shader *shader,
     51                                  struct brw_vue_prog_data *prog_data)
     52       : vec4_visitor(compiler, NULL, NULL, prog_data, shader, NULL,
     53                      false, -1)
     54       {
     55          prog_data->dispatch_mode = DISPATCH_MODE_4X2_DUAL_OBJECT;
     56       }
     57 
     58 protected:
     59    /* Dummy implementation for pure virtual methods */
     60    virtual dst_reg *make_reg_for_system_value(int location)
     61    {
     62       unreachable("Not reached");
     63    }
     64 
     65    virtual void setup_payload()
     66    {
     67       unreachable("Not reached");
     68    }
     69 
     70    virtual void emit_prolog()
     71    {
     72       unreachable("Not reached");
     73    }
     74 
     75    virtual void emit_program_code()
     76    {
     77       unreachable("Not reached");
     78    }
     79 
     80    virtual void emit_thread_end()
     81    {
     82       unreachable("Not reached");
     83    }
     84 
     85    virtual void emit_urb_write_header(int mrf)
     86    {
     87       unreachable("Not reached");
     88    }
     89 
     90    virtual vec4_instruction *emit_urb_write_opcode(bool complete)
     91    {
     92       unreachable("Not reached");
     93    }
     94 };
     95 
     96 
     97 void cmod_propagation_test::SetUp()
     98 {
     99    ctx = (struct gl_context *)calloc(1, sizeof(*ctx));
    100    compiler = (struct brw_compiler *)calloc(1, sizeof(*compiler));
    101    devinfo = (struct gen_device_info *)calloc(1, sizeof(*devinfo));
    102    prog_data = (struct brw_vue_prog_data *)calloc(1, sizeof(*prog_data));
    103    compiler->devinfo = devinfo;
    104 
    105    nir_shader *shader =
    106       nir_shader_create(NULL, MESA_SHADER_VERTEX, NULL, NULL);
    107 
    108    v = new cmod_propagation_vec4_visitor(compiler, shader, prog_data);
    109 
    110    devinfo->gen = 4;
    111 }
    112 
    113 static vec4_instruction *
    114 instruction(bblock_t *block, int num)
    115 {
    116    vec4_instruction *inst = (vec4_instruction *)block->start();
    117    for (int i = 0; i < num; i++) {
    118       inst = (vec4_instruction *)inst->next;
    119    }
    120    return inst;
    121 }
    122 
    123 static bool
    124 cmod_propagation(vec4_visitor *v)
    125 {
    126    const bool print = getenv("TEST_DEBUG");
    127 
    128    if (print) {
    129       fprintf(stderr, "= Before =\n");
    130       v->dump_instructions();
    131    }
    132 
    133    bool ret = v->opt_cmod_propagation();
    134 
    135    if (print) {
    136       fprintf(stderr, "\n= After =\n");
    137       v->dump_instructions();
    138    }
    139 
    140    return ret;
    141 }
    142 
    143 TEST_F(cmod_propagation_test, basic)
    144 {
    145    const vec4_builder bld = vec4_builder(v).at_end();
    146    dst_reg dest = dst_reg(v, glsl_type::float_type);
    147    src_reg src0 = src_reg(v, glsl_type::float_type);
    148    src_reg src1 = src_reg(v, glsl_type::float_type);
    149    src_reg zero(brw_imm_f(0.0f));
    150    dst_reg dest_null = bld.null_reg_f();
    151    dest_null.writemask = WRITEMASK_X;
    152 
    153    bld.ADD(dest, src0, src1);
    154    bld.CMP(dest_null, src_reg(dest), zero, BRW_CONDITIONAL_GE);
    155 
    156    /* = Before =
    157     *
    158     * 0: add        dest.x  src0.xxxx  src1.xxxx
    159     * 1: cmp.ge.f0  null.x  dest.xxxx  0.0f
    160     *
    161     * = After =
    162     * 0: add.ge.f0  dest.x  src0.xxxx  src1.xxxx
    163     */
    164 
    165    v->calculate_cfg();
    166    bblock_t *block0 = v->cfg->blocks[0];
    167 
    168    EXPECT_EQ(0, block0->start_ip);
    169    EXPECT_EQ(1, block0->end_ip);
    170 
    171    EXPECT_TRUE(cmod_propagation(v));
    172 
    173    ASSERT_EQ(0, block0->start_ip);
    174    ASSERT_EQ(0, block0->end_ip);
    175    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
    176    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
    177 }
    178 
    179 TEST_F(cmod_propagation_test, basic_different_dst_writemask)
    180 {
    181    const vec4_builder bld = vec4_builder(v).at_end();
    182    dst_reg dest = dst_reg(v, glsl_type::float_type);
    183    src_reg src0 = src_reg(v, glsl_type::float_type);
    184    src_reg src1 = src_reg(v, glsl_type::float_type);
    185    src_reg zero(brw_imm_f(0.0f));
    186    dst_reg dest_null = bld.null_reg_f();
    187 
    188    bld.ADD(dest, src0, src1);
    189    bld.CMP(dest_null, src_reg(dest), zero, BRW_CONDITIONAL_GE);
    190 
    191    /* = Before =
    192     *
    193     * 0: add        dest.x     src0  src1
    194     * 1: cmp.ge.f0  null.xyzw  dest  0.0f
    195     *
    196     * = After =
    197     * (no changes)
    198     */
    199 
    200    v->calculate_cfg();
    201    bblock_t *block0 = v->cfg->blocks[0];
    202 
    203    EXPECT_EQ(0, block0->start_ip);
    204    EXPECT_EQ(1, block0->end_ip);
    205 
    206    EXPECT_FALSE(cmod_propagation(v));
    207 
    208    ASSERT_EQ(0, block0->start_ip);
    209    ASSERT_EQ(1, block0->end_ip);
    210    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
    211    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
    212    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
    213    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
    214 }
    215 
    216 TEST_F(cmod_propagation_test, andz_one)
    217 {
    218    const vec4_builder bld = vec4_builder(v).at_end();
    219    dst_reg dest = dst_reg(v, glsl_type::int_type);
    220    src_reg src0 = src_reg(v, glsl_type::float_type);
    221    src_reg zero(brw_imm_f(0.0f));
    222    src_reg one(brw_imm_d(1));
    223 
    224    bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
    225    set_condmod(BRW_CONDITIONAL_Z,
    226                bld.AND(bld.null_reg_d(), src_reg(dest), one));
    227 
    228    /* = Before =
    229     * 0: cmp.l.f0     dest:F  src0:F  0F
    230     * 1: and.z.f0     null:D  dest:D  1D
    231     *
    232     * = After =
    233     * (no changes)
    234     */
    235 
    236    v->calculate_cfg();
    237    bblock_t *block0 = v->cfg->blocks[0];
    238 
    239    EXPECT_EQ(0, block0->start_ip);
    240    EXPECT_EQ(1, block0->end_ip);
    241 
    242    EXPECT_FALSE(cmod_propagation(v));
    243 
    244    ASSERT_EQ(0, block0->start_ip);
    245    ASSERT_EQ(1, block0->end_ip);
    246    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
    247    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
    248    EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
    249    EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
    250 }
    251 
    252 TEST_F(cmod_propagation_test, non_cmod_instruction)
    253 {
    254    const vec4_builder bld = vec4_builder(v).at_end();
    255    dst_reg dest = dst_reg(v, glsl_type::uint_type);
    256    src_reg src0 = src_reg(v, glsl_type::uint_type);
    257    src_reg zero(brw_imm_ud(0u));
    258    bld.FBL(dest, src0);
    259    bld.CMP(bld.null_reg_ud(), src_reg(dest), zero, BRW_CONDITIONAL_GE);
    260 
    261    /* = Before =
    262     *
    263     * 0: fbl        dest  src0
    264     * 1: cmp.ge.f0  null  dest  0u
    265     *
    266     * = After =
    267     * (no changes)
    268     */
    269 
    270    v->calculate_cfg();
    271    bblock_t *block0 = v->cfg->blocks[0];
    272 
    273    EXPECT_EQ(0, block0->start_ip);
    274    EXPECT_EQ(1, block0->end_ip);
    275 
    276    EXPECT_FALSE(cmod_propagation(v));
    277 
    278    ASSERT_EQ(0, block0->start_ip);
    279    ASSERT_EQ(1, block0->end_ip);
    280    EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode);
    281    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
    282    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
    283 }
    284 
    285 TEST_F(cmod_propagation_test, intervening_flag_write)
    286 {
    287    const vec4_builder bld = vec4_builder(v).at_end();
    288    dst_reg dest = dst_reg(v, glsl_type::float_type);
    289    src_reg src0 = src_reg(v, glsl_type::float_type);
    290    src_reg src1 = src_reg(v, glsl_type::float_type);
    291    src_reg src2 = src_reg(v, glsl_type::float_type);
    292    src_reg zero(brw_imm_f(0.0f));
    293    bld.ADD(dest, src0, src1);
    294    bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE);
    295    bld.CMP(bld.null_reg_f(), src_reg(dest), zero, BRW_CONDITIONAL_GE);
    296 
    297    /* = Before =
    298     *
    299     * 0: add        dest  src0  src1
    300     * 1: cmp.ge.f0  null  src2  0.0f
    301     * 2: cmp.ge.f0  null  dest  0.0f
    302     *
    303     * = After =
    304     * (no changes)
    305     */
    306 
    307    v->calculate_cfg();
    308    bblock_t *block0 = v->cfg->blocks[0];
    309 
    310    EXPECT_EQ(0, block0->start_ip);
    311    EXPECT_EQ(2, block0->end_ip);
    312 
    313    EXPECT_FALSE(cmod_propagation(v));
    314 
    315    ASSERT_EQ(0, block0->start_ip);
    316    ASSERT_EQ(2, block0->end_ip);
    317    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
    318    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
    319    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
    320    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
    321    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
    322 }
    323 
    324 TEST_F(cmod_propagation_test, intervening_flag_read)
    325 {
    326    const vec4_builder bld = vec4_builder(v).at_end();
    327    dst_reg dest0 = dst_reg(v, glsl_type::float_type);
    328    dst_reg dest1 = dst_reg(v, glsl_type::float_type);
    329    src_reg src0 = src_reg(v, glsl_type::float_type);
    330    src_reg src1 = src_reg(v, glsl_type::float_type);
    331    src_reg src2 = src_reg(v, glsl_type::float_type);
    332    src_reg zero(brw_imm_f(0.0f));
    333    bld.ADD(dest0, src0, src1);
    334    set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
    335    bld.CMP(bld.null_reg_f(), src_reg(dest0), zero, BRW_CONDITIONAL_GE);
    336 
    337    /* = Before =
    338     *
    339     * 0: add        dest0 src0  src1
    340     * 1: (+f0) sel  dest1 src2  0.0f
    341     * 2: cmp.ge.f0  null  dest0 0.0f
    342     *
    343     * = After =
    344     * (no changes)
    345     */
    346 
    347    v->calculate_cfg();
    348    bblock_t *block0 = v->cfg->blocks[0];
    349 
    350    EXPECT_EQ(0, block0->start_ip);
    351    EXPECT_EQ(2, block0->end_ip);
    352 
    353    EXPECT_FALSE(cmod_propagation(v));
    354 
    355    ASSERT_EQ(0, block0->start_ip);
    356    ASSERT_EQ(2, block0->end_ip);
    357    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
    358    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
    359    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
    360    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
    361    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
    362 }
    363 
    364 TEST_F(cmod_propagation_test, intervening_dest_write)
    365 {
    366    const vec4_builder bld = vec4_builder(v).at_end();
    367    dst_reg dest = dst_reg(v, glsl_type::vec4_type);
    368    src_reg src0 = src_reg(v, glsl_type::float_type);
    369    src_reg src1 = src_reg(v, glsl_type::float_type);
    370    src_reg src2 = src_reg(v, glsl_type::vec2_type);
    371    src_reg zero(brw_imm_f(0.0f));
    372    bld.ADD(offset(dest, 8, 2), src0, src1);
    373    bld.emit(SHADER_OPCODE_TEX, dest, src2)
    374       ->size_written = 4 * REG_SIZE;
    375    bld.CMP(bld.null_reg_f(), offset(src_reg(dest), 8, 2), zero, BRW_CONDITIONAL_GE);
    376 
    377    /* = Before =
    378     *
    379     * 0: add        dest+2  src0    src1
    380     * 1: tex rlen 4 dest+0  src2
    381     * 2: cmp.ge.f0  null    dest+2  0.0f
    382     *
    383     * = After =
    384     * (no changes)
    385     */
    386 
    387    v->calculate_cfg();
    388    bblock_t *block0 = v->cfg->blocks[0];
    389 
    390    EXPECT_EQ(0, block0->start_ip);
    391    EXPECT_EQ(2, block0->end_ip);
    392 
    393    EXPECT_FALSE(cmod_propagation(v));
    394 
    395    ASSERT_EQ(0, block0->start_ip);
    396    ASSERT_EQ(2, block0->end_ip);
    397    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
    398    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
    399    EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
    400    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
    401    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
    402    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
    403 }
    404 
    405 TEST_F(cmod_propagation_test, intervening_flag_read_same_value)
    406 {
    407    const vec4_builder bld = vec4_builder(v).at_end();
    408    dst_reg dest0 = dst_reg(v, glsl_type::float_type);
    409    dst_reg dest1 = dst_reg(v, glsl_type::float_type);
    410    src_reg src0 = src_reg(v, glsl_type::float_type);
    411    src_reg src1 = src_reg(v, glsl_type::float_type);
    412    src_reg src2 = src_reg(v, glsl_type::float_type);
    413    src_reg zero(brw_imm_f(0.0f));
    414    dst_reg dest_null = bld.null_reg_f();
    415    dest_null.writemask = WRITEMASK_X;
    416 
    417    set_condmod(BRW_CONDITIONAL_GE, bld.ADD(dest0, src0, src1));
    418    set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
    419    bld.CMP(dest_null, src_reg(dest0), zero, BRW_CONDITIONAL_GE);
    420 
    421    /* = Before =
    422     *
    423     * 0: add.ge.f0  dest0   src0  src1
    424     * 1: (+f0) sel  dest1   src2  0.0f
    425     * 2: cmp.ge.f0  null.x  dest0 0.0f
    426     *
    427     * = After =
    428     * 0: add.ge.f0  dest0 src0  src1
    429     * 1: (+f0) sel  dest1 src2  0.0f
    430     */
    431 
    432    v->calculate_cfg();
    433    bblock_t *block0 = v->cfg->blocks[0];
    434 
    435    EXPECT_EQ(0, block0->start_ip);
    436    EXPECT_EQ(2, block0->end_ip);
    437 
    438    EXPECT_TRUE(cmod_propagation(v));
    439    ASSERT_EQ(0, block0->start_ip);
    440    ASSERT_EQ(1, block0->end_ip);
    441    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
    442    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
    443    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
    444    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
    445 }
    446 
    447 TEST_F(cmod_propagation_test, negate)
    448 {
    449    const vec4_builder bld = vec4_builder(v).at_end();
    450    dst_reg dest = dst_reg(v, glsl_type::float_type);
    451    src_reg src0 = src_reg(v, glsl_type::float_type);
    452    src_reg src1 = src_reg(v, glsl_type::float_type);
    453    src_reg zero(brw_imm_f(0.0f));
    454    bld.ADD(dest, src0, src1);
    455    src_reg tmp_src = src_reg(dest);
    456    tmp_src.negate = true;
    457    dst_reg dest_null = bld.null_reg_f();
    458    dest_null.writemask = WRITEMASK_X;
    459    bld.CMP(dest_null, tmp_src, zero, BRW_CONDITIONAL_GE);
    460 
    461    /* = Before =
    462     *
    463     * 0: add        dest     src0  src1
    464     * 1: cmp.ge.f0  null.x  -dest 0.0f
    465     *
    466     * = After =
    467     * 0: add.le.f0  dest     src0  src1
    468     */
    469 
    470    v->calculate_cfg();
    471    bblock_t *block0 = v->cfg->blocks[0];
    472 
    473    EXPECT_EQ(0, block0->start_ip);
    474    EXPECT_EQ(1, block0->end_ip);
    475 
    476    EXPECT_TRUE(cmod_propagation(v));
    477    EXPECT_EQ(0, block0->start_ip);
    478    EXPECT_EQ(0, block0->end_ip);
    479    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
    480    EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
    481 }
    482 
    483 TEST_F(cmod_propagation_test, movnz)
    484 {
    485    const vec4_builder bld = vec4_builder(v).at_end();
    486    dst_reg dest = dst_reg(v, glsl_type::float_type);
    487    src_reg src0 = src_reg(v, glsl_type::float_type);
    488    src_reg src1 = src_reg(v, glsl_type::float_type);
    489    dst_reg dest_null = bld.null_reg_f();
    490    dest_null.writemask = WRITEMASK_X;
    491 
    492    bld.CMP(dest, src0, src1, BRW_CONDITIONAL_L);
    493    set_condmod(BRW_CONDITIONAL_NZ,
    494                bld.MOV(dest_null, src_reg(dest)));
    495 
    496    /* = Before =
    497     *
    498     * 0: cmp.l.f0  dest:F  src0:F  src1:F
    499     * 1: mov.nz.f0 null.x  dest:F
    500     *
    501     * = After =
    502     * 0: cmp.l.f0  dest  src0:F  src1:F
    503     */
    504 
    505    v->calculate_cfg();
    506    bblock_t *block0 = v->cfg->blocks[0];
    507 
    508    EXPECT_EQ(0, block0->start_ip);
    509    EXPECT_EQ(1, block0->end_ip);
    510 
    511    EXPECT_TRUE(cmod_propagation(v));
    512 
    513    ASSERT_EQ(0, block0->start_ip);
    514    ASSERT_EQ(0, block0->end_ip);
    515    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
    516    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
    517 }
    518 
    519 TEST_F(cmod_propagation_test, different_types_cmod_with_zero)
    520 {
    521    const vec4_builder bld = vec4_builder(v).at_end();
    522    dst_reg dest = dst_reg(v, glsl_type::int_type);
    523    src_reg src0 = src_reg(v, glsl_type::int_type);
    524    src_reg src1 = src_reg(v, glsl_type::int_type);
    525    src_reg zero(brw_imm_f(0.0f));
    526    bld.ADD(dest, src0, src1);
    527    bld.CMP(bld.null_reg_f(), retype(src_reg(dest), BRW_REGISTER_TYPE_F), zero,
    528            BRW_CONDITIONAL_GE);
    529 
    530    /* = Before =
    531     *
    532     * 0: add        dest:D  src0:D  src1:D
    533     * 1: cmp.ge.f0  null:F  dest:F  0.0f
    534     *
    535     * = After =
    536     * (no changes)
    537     */
    538 
    539    v->calculate_cfg();
    540    bblock_t *block0 = v->cfg->blocks[0];
    541 
    542    EXPECT_EQ(0, block0->start_ip);
    543    EXPECT_EQ(1, block0->end_ip);
    544 
    545    EXPECT_FALSE(cmod_propagation(v));
    546 
    547    ASSERT_EQ(0, block0->start_ip);
    548    ASSERT_EQ(1, block0->end_ip);
    549    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
    550    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
    551    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
    552 }
    553 
    554 TEST_F(cmod_propagation_test, andnz_non_one)
    555 {
    556    const vec4_builder bld = vec4_builder(v).at_end();
    557    dst_reg dest = dst_reg(v, glsl_type::int_type);
    558    src_reg src0 = src_reg(v, glsl_type::float_type);
    559    src_reg zero(brw_imm_f(0.0f));
    560    src_reg nonone(brw_imm_d(38));
    561 
    562    bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
    563    set_condmod(BRW_CONDITIONAL_NZ,
    564                bld.AND(bld.null_reg_d(), src_reg(dest), nonone));
    565 
    566    /* = Before =
    567     * 0: cmp.l.f0     dest:F  src0:F  0F
    568     * 1: and.nz.f0    null:D  dest:D  38D
    569     *
    570     * = After =
    571     * (no changes)
    572     */
    573 
    574    v->calculate_cfg();
    575    bblock_t *block0 = v->cfg->blocks[0];
    576 
    577    EXPECT_EQ(0, block0->start_ip);
    578    EXPECT_EQ(1, block0->end_ip);
    579 
    580    EXPECT_FALSE(cmod_propagation(v));
    581 
    582    ASSERT_EQ(0, block0->start_ip);
    583    ASSERT_EQ(1, block0->end_ip);
    584    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
    585    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
    586    EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
    587    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
    588 }
    589 
    590 /* Note that basic is using glsl_type:float types, while this one is using
    591  * glsl_type::vec4 */
    592 TEST_F(cmod_propagation_test, basic_vec4)
    593 {
    594    const vec4_builder bld = vec4_builder(v).at_end();
    595    dst_reg dest = dst_reg(v, glsl_type::vec4_type);
    596    src_reg src0 = src_reg(v, glsl_type::vec4_type);
    597    src_reg src1 = src_reg(v, glsl_type::vec4_type);
    598    src_reg zero(brw_imm_f(0.0f));
    599 
    600    bld.MUL(dest, src0, src1);
    601    bld.CMP(bld.null_reg_f(), src_reg(dest), zero, BRW_CONDITIONAL_NZ);
    602 
    603    /* = Before =
    604     * 0: mul         dest.xyzw  src0.xyzw  src1.xyzw
    605     * 1: cmp.nz.f0.0 null.xyzw  dest.xyzw  0.0f
    606     *
    607     * = After =
    608     * 0: mul.nz.f0.0 dest.xyzw  src0.xyzw  src1.xyzw
    609     */
    610 
    611    v->calculate_cfg();
    612    bblock_t *block0 = v->cfg->blocks[0];
    613 
    614    EXPECT_EQ(0, block0->start_ip);
    615    EXPECT_EQ(1, block0->end_ip);
    616 
    617    EXPECT_TRUE(cmod_propagation(v));
    618 
    619    ASSERT_EQ(0, block0->start_ip);
    620    ASSERT_EQ(0, block0->end_ip);
    621    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
    622    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
    623 }
    624 
    625 TEST_F(cmod_propagation_test, basic_vec4_different_dst_writemask)
    626 {
    627    const vec4_builder bld = vec4_builder(v).at_end();
    628    dst_reg dest = dst_reg(v, glsl_type::vec4_type);
    629    dest.writemask = WRITEMASK_X;
    630    src_reg src0 = src_reg(v, glsl_type::vec4_type);
    631    src_reg src1 = src_reg(v, glsl_type::vec4_type);
    632    src_reg zero(brw_imm_f(0.0f));
    633    dst_reg dest_null = bld.null_reg_f();
    634 
    635    bld.MUL(dest, src0, src1);
    636    bld.CMP(dest_null, src_reg(dest), zero, BRW_CONDITIONAL_NZ);
    637 
    638    /* = Before =
    639     * 0: mul         dest.x  src0  src1
    640     * 1: cmp.nz.f0.0 null    dest  0.0f
    641     *
    642     * = After =
    643     * (no changes)
    644     */
    645 
    646    v->calculate_cfg();
    647    bblock_t *block0 = v->cfg->blocks[0];
    648 
    649    EXPECT_EQ(0, block0->start_ip);
    650    EXPECT_EQ(1, block0->end_ip);
    651 
    652    EXPECT_FALSE(cmod_propagation(v));
    653 
    654    ASSERT_EQ(0, block0->start_ip);
    655    ASSERT_EQ(1, block0->end_ip);
    656    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
    657    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
    658    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
    659    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
    660 }
    661 
    662 TEST_F(cmod_propagation_test, mad_one_component_vec4)
    663 {
    664    const vec4_builder bld = vec4_builder(v).at_end();
    665    dst_reg dest = dst_reg(v, glsl_type::vec4_type);
    666    dest.writemask = WRITEMASK_X;
    667    src_reg src0 = src_reg(v, glsl_type::vec4_type);
    668    src_reg src1 = src_reg(v, glsl_type::vec4_type);
    669    src_reg src2 = src_reg(v, glsl_type::vec4_type);
    670    src0.swizzle = src1.swizzle = src2.swizzle = BRW_SWIZZLE_XXXX;
    671    src2.negate = true;
    672    src_reg zero(brw_imm_f(0.0f));
    673    src_reg tmp(dest);
    674    tmp.swizzle = BRW_SWIZZLE_XXXX;
    675    dst_reg dest_null = bld.null_reg_f();
    676    dest_null.writemask = WRITEMASK_X;
    677 
    678    bld.MAD(dest, src0, src1, src2);
    679    bld.CMP(dest_null, tmp, zero, BRW_CONDITIONAL_L);
    680 
    681    /* = Before =
    682     *
    683     * 0: mad         dest.x:F  src0.xxxx:F  src10.xxxx:F  -src2.xxxx:F
    684     * 1: cmp.l.f0.0  null.x:F  dest.xxxx:F  0.0f
    685     *
    686     * = After =
    687     * 0: mad.l.f0    dest.x:F  src0.xxxx:F  src10.xxxx:F  -src2.xxxx:F
    688     */
    689 
    690    v->calculate_cfg();
    691    bblock_t *block0 = v->cfg->blocks[0];
    692 
    693    EXPECT_EQ(0, block0->start_ip);
    694    EXPECT_EQ(1, block0->end_ip);
    695 
    696    EXPECT_TRUE(cmod_propagation(v));
    697 
    698    ASSERT_EQ(0, block0->start_ip);
    699    ASSERT_EQ(0, block0->end_ip);
    700    EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode);
    701    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
    702 }
    703 
    704 TEST_F(cmod_propagation_test, mad_more_one_component_vec4)
    705 {
    706    const vec4_builder bld = vec4_builder(v).at_end();
    707    dst_reg dest = dst_reg(v, glsl_type::vec4_type);
    708    dest.writemask = WRITEMASK_XW;
    709    src_reg src0 = src_reg(v, glsl_type::vec4_type);
    710    src_reg src1 = src_reg(v, glsl_type::vec4_type);
    711    src_reg src2 = src_reg(v, glsl_type::vec4_type);
    712    src0.swizzle = src1.swizzle = src2.swizzle = BRW_SWIZZLE_XXXX;
    713    src2.negate = true;
    714    src_reg zero(brw_imm_f(0.0f));
    715    src_reg tmp(dest);
    716    tmp.swizzle = BRW_SWIZZLE_XXXX;
    717    dst_reg dest_null = bld.null_reg_f();
    718 
    719    bld.MAD(dest, src0, src1, src2);
    720    bld.CMP(dest_null, tmp, zero, BRW_CONDITIONAL_L);
    721 
    722    /* = Before =
    723     *
    724     * 0: mad         dest.xw:F  src0.xxxx:F  src10.xxxx:F  -src2.xxxx:F
    725     * 1: cmp.l.f0.0  null:F  dest.xxxx:F  zeroF
    726     *
    727     * = After =
    728     * (No changes)
    729     */
    730 
    731    v->calculate_cfg();
    732    bblock_t *block0 = v->cfg->blocks[0];
    733 
    734    EXPECT_EQ(0, block0->start_ip);
    735    EXPECT_EQ(1, block0->end_ip);
    736 
    737    EXPECT_FALSE(cmod_propagation(v));
    738 
    739    ASSERT_EQ(0, block0->start_ip);
    740    ASSERT_EQ(1, block0->end_ip);
    741    EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode);
    742    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
    743    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
    744    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
    745 }
    746 
    747 TEST_F(cmod_propagation_test, cmp_mov_vec4)
    748 {
    749    const vec4_builder bld = vec4_builder(v).at_end();
    750    dst_reg dest = dst_reg(v, glsl_type::ivec4_type);
    751    dest.writemask = WRITEMASK_X;
    752    src_reg src0 = src_reg(v, glsl_type::ivec4_type);
    753    src0.swizzle = BRW_SWIZZLE_XXXX;
    754    src0.file = UNIFORM;
    755    src_reg nonone = retype(brw_imm_d(16), BRW_REGISTER_TYPE_D);
    756    src_reg mov_src = src_reg(dest);
    757    mov_src.swizzle = BRW_SWIZZLE_XXXX;
    758    dst_reg dest_null = bld.null_reg_d();
    759    dest_null.writemask = WRITEMASK_X;
    760 
    761    bld.CMP(dest, src0, nonone, BRW_CONDITIONAL_GE);
    762    set_condmod(BRW_CONDITIONAL_NZ,
    763                bld.MOV(dest_null, mov_src));
    764 
    765    /* = Before =
    766     *
    767     * 0: cmp.ge.f0  dest.x:D  u.xxxx:D  16D
    768     * 1: mov.nz.f0  null.x:D  dest.xxxx:D
    769     *
    770     * = After =
    771     * 0: cmp.ge.f0  dest.x:D  u.xxxx:D  16D
    772     */
    773 
    774    v->calculate_cfg();
    775    bblock_t *block0 = v->cfg->blocks[0];
    776 
    777    EXPECT_EQ(0, block0->start_ip);
    778    EXPECT_EQ(1, block0->end_ip);
    779 
    780    EXPECT_TRUE(cmod_propagation(v));
    781 
    782    ASSERT_EQ(0, block0->start_ip);
    783    ASSERT_EQ(0, block0->end_ip);
    784    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
    785    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
    786 }
    787 
    788 TEST_F(cmod_propagation_test, mul_cmp_different_channels_vec4)
    789 {
    790    const vec4_builder bld = vec4_builder(v).at_end();
    791    dst_reg dest = dst_reg(v, glsl_type::vec4_type);
    792    src_reg src0 = src_reg(v, glsl_type::vec4_type);
    793    src_reg src1 = src_reg(v, glsl_type::vec4_type);
    794    src_reg zero(brw_imm_f(0.0f));
    795    src_reg cmp_src = src_reg(dest);
    796    cmp_src.swizzle = BRW_SWIZZLE4(0,1,3,2);
    797 
    798    bld.MUL(dest, src0, src1);
    799    bld.CMP(bld.null_reg_f(), cmp_src, zero, BRW_CONDITIONAL_NZ);
    800 
    801    /* = Before =
    802     * 0: mul         dest  src0       src1
    803     * 1: cmp.nz.f0.0 null  dest.xywz  0.0f
    804     *
    805     * = After =
    806     * (No changes)
    807     */
    808 
    809    v->calculate_cfg();
    810    bblock_t *block0 = v->cfg->blocks[0];
    811 
    812    EXPECT_EQ(0, block0->start_ip);
    813    EXPECT_EQ(1, block0->end_ip);
    814 
    815    EXPECT_FALSE(cmod_propagation(v));
    816 
    817    ASSERT_EQ(0, block0->start_ip);
    818    ASSERT_EQ(1, block0->end_ip);
    819    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
    820    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
    821    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
    822    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
    823 }
    824