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 
24 #include <gtest/gtest.h>
25 #include "brw_fs.h"
26 #include "brw_cfg.h"
27 #include "program/program.h"
28 
29 using namespace brw;
30 
31 class cmod_propagation_test : public ::testing::Test {
32    virtual void SetUp();
33    virtual void TearDown();
34 
35 public:
36    struct brw_compiler *compiler;
37    struct intel_device_info *devinfo;
38    void *ctx;
39    struct brw_wm_prog_data *prog_data;
40    struct gl_shader_program *shader_prog;
41    fs_visitor *v;
42 
43    void test_mov_prop(enum brw_conditional_mod cmod,
44                       enum brw_reg_type add_type,
45                       enum brw_reg_type mov_dst_type,
46                       bool expected_cmod_prop_progress);
47 
48    void test_saturate_prop(enum brw_conditional_mod before,
49                            enum opcode op,
50                            enum brw_reg_type add_type,
51                            enum brw_reg_type op_type,
52                            bool expected_cmod_prop_progress);
53 };
54 
55 class cmod_propagation_fs_visitor : public fs_visitor
56 {
57 public:
cmod_propagation_fs_visitor(struct brw_compiler * compiler,void * mem_ctx,struct brw_wm_prog_data * prog_data,nir_shader * shader)58    cmod_propagation_fs_visitor(struct brw_compiler *compiler,
59                                void *mem_ctx,
60                                struct brw_wm_prog_data *prog_data,
61                                nir_shader *shader)
62       : fs_visitor(compiler, NULL, mem_ctx, NULL,
63                    &prog_data->base, shader, 8, false) {}
64 };
65 
66 
SetUp()67 void cmod_propagation_test::SetUp()
68 {
69    ctx = ralloc_context(NULL);
70    compiler = rzalloc(ctx, struct brw_compiler);
71    devinfo = rzalloc(ctx, struct intel_device_info);
72    compiler->devinfo = devinfo;
73 
74    prog_data = ralloc(ctx, struct brw_wm_prog_data);
75    nir_shader *shader =
76       nir_shader_create(ctx, MESA_SHADER_FRAGMENT, NULL, NULL);
77 
78    v = new cmod_propagation_fs_visitor(compiler, ctx, prog_data, shader);
79 
80    devinfo->ver = 7;
81    devinfo->verx10 = devinfo->ver * 10;
82 }
83 
TearDown()84 void cmod_propagation_test::TearDown()
85 {
86    delete v;
87    v = NULL;
88 
89    ralloc_free(ctx);
90    ctx = NULL;
91 }
92 
93 static fs_inst *
instruction(bblock_t * block,int num)94 instruction(bblock_t *block, int num)
95 {
96    fs_inst *inst = (fs_inst *)block->start();
97    for (int i = 0; i < num; i++) {
98       inst = (fs_inst *)inst->next;
99    }
100    return inst;
101 }
102 
103 static bool
cmod_propagation(fs_visitor * v)104 cmod_propagation(fs_visitor *v)
105 {
106    const bool print = getenv("TEST_DEBUG");
107 
108    if (print) {
109       fprintf(stderr, "= Before =\n");
110       v->cfg->dump();
111    }
112 
113    bool ret = v->opt_cmod_propagation();
114 
115    if (print) {
116       fprintf(stderr, "\n= After =\n");
117       v->cfg->dump();
118    }
119 
120    return ret;
121 }
122 
TEST_F(cmod_propagation_test,basic)123 TEST_F(cmod_propagation_test, basic)
124 {
125    const fs_builder &bld = v->bld;
126    fs_reg dest = v->vgrf(glsl_type::float_type);
127    fs_reg src0 = v->vgrf(glsl_type::float_type);
128    fs_reg src1 = v->vgrf(glsl_type::float_type);
129    fs_reg zero(brw_imm_f(0.0f));
130    bld.ADD(dest, src0, src1);
131    bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
132 
133    /* = Before =
134     *
135     * 0: add(8)        dest  src0  src1
136     * 1: cmp.ge.f0(8)  null  dest  0.0f
137     *
138     * = After =
139     * 0: add.ge.f0(8)  dest  src0  src1
140     */
141 
142    v->calculate_cfg();
143    bblock_t *block0 = v->cfg->blocks[0];
144 
145    EXPECT_EQ(0, block0->start_ip);
146    EXPECT_EQ(1, block0->end_ip);
147 
148    EXPECT_TRUE(cmod_propagation(v));
149    EXPECT_EQ(0, block0->start_ip);
150    EXPECT_EQ(0, block0->end_ip);
151    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
152    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
153 }
154 
TEST_F(cmod_propagation_test,basic_other_flag)155 TEST_F(cmod_propagation_test, basic_other_flag)
156 {
157    const fs_builder &bld = v->bld;
158    fs_reg dest = v->vgrf(glsl_type::float_type);
159    fs_reg src0 = v->vgrf(glsl_type::float_type);
160    fs_reg src1 = v->vgrf(glsl_type::float_type);
161    fs_reg zero(brw_imm_f(0.0f));
162    bld.ADD(dest, src0, src1);
163    bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE)
164       ->flag_subreg = 1;
165 
166    /* = Before =
167     *
168     * 0: add(8)         dest  src0  src1
169     * 1: cmp.ge.f0.1(8) null  dest  0.0f
170     *
171     * = After =
172     * 0: add.ge.f0.1(8) dest  src0  src1
173     */
174 
175    v->calculate_cfg();
176    bblock_t *block0 = v->cfg->blocks[0];
177 
178    EXPECT_EQ(0, block0->start_ip);
179    EXPECT_EQ(1, block0->end_ip);
180 
181    EXPECT_TRUE(cmod_propagation(v));
182    EXPECT_EQ(0, block0->start_ip);
183    EXPECT_EQ(0, block0->end_ip);
184    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
185    EXPECT_EQ(1, instruction(block0, 0)->flag_subreg);
186    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
187 }
188 
TEST_F(cmod_propagation_test,cmp_nonzero)189 TEST_F(cmod_propagation_test, cmp_nonzero)
190 {
191    const fs_builder &bld = v->bld;
192    fs_reg dest = v->vgrf(glsl_type::float_type);
193    fs_reg src0 = v->vgrf(glsl_type::float_type);
194    fs_reg src1 = v->vgrf(glsl_type::float_type);
195    fs_reg nonzero(brw_imm_f(1.0f));
196    bld.ADD(dest, src0, src1);
197    bld.CMP(bld.null_reg_f(), dest, nonzero, BRW_CONDITIONAL_GE);
198 
199    /* = Before =
200     *
201     * 0: add(8)        dest  src0  src1
202     * 1: cmp.ge.f0(8)  null  dest  1.0f
203     *
204     * = After =
205     * (no changes)
206     */
207 
208    v->calculate_cfg();
209    bblock_t *block0 = v->cfg->blocks[0];
210 
211    EXPECT_EQ(0, block0->start_ip);
212    EXPECT_EQ(1, block0->end_ip);
213 
214    EXPECT_FALSE(cmod_propagation(v));
215    EXPECT_EQ(0, block0->start_ip);
216    EXPECT_EQ(1, block0->end_ip);
217    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
218    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
219    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
220 }
221 
TEST_F(cmod_propagation_test,non_cmod_instruction)222 TEST_F(cmod_propagation_test, non_cmod_instruction)
223 {
224    const fs_builder &bld = v->bld;
225    fs_reg dest = v->vgrf(glsl_type::uint_type);
226    fs_reg src0 = v->vgrf(glsl_type::uint_type);
227    fs_reg zero(brw_imm_ud(0u));
228    bld.FBL(dest, src0);
229    bld.CMP(bld.null_reg_ud(), dest, zero, BRW_CONDITIONAL_GE);
230 
231    /* = Before =
232     *
233     * 0: fbl(8)        dest  src0
234     * 1: cmp.ge.f0(8)  null  dest  0u
235     *
236     * = After =
237     * (no changes)
238     */
239 
240    v->calculate_cfg();
241    bblock_t *block0 = v->cfg->blocks[0];
242 
243    EXPECT_EQ(0, block0->start_ip);
244    EXPECT_EQ(1, block0->end_ip);
245 
246    EXPECT_FALSE(cmod_propagation(v));
247    EXPECT_EQ(0, block0->start_ip);
248    EXPECT_EQ(1, block0->end_ip);
249    EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode);
250    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
251    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
252 }
253 
TEST_F(cmod_propagation_test,non_cmod_livechannel)254 TEST_F(cmod_propagation_test, non_cmod_livechannel)
255 {
256    const fs_builder &bld = v->bld;
257    fs_reg dest = v->vgrf(glsl_type::uint_type);
258    fs_reg zero(brw_imm_d(0));
259    bld.emit(SHADER_OPCODE_FIND_LIVE_CHANNEL, dest)->exec_size = 32;
260    bld.CMP(bld.null_reg_d(), dest, zero, BRW_CONDITIONAL_Z)->exec_size = 32;
261 
262    /* = Before =
263     *
264     * 0: find_live_channel(32) dest
265     * 1: cmp.z.f0.0(32)   null dest 0d
266     *
267     *
268     * = After =
269     * (no changes)
270     */
271 
272    v->calculate_cfg();
273    bblock_t *block0 = v->cfg->blocks[0];
274 
275    EXPECT_EQ(0, block0->start_ip);
276    EXPECT_EQ(1, block0->end_ip);
277 
278    EXPECT_FALSE(cmod_propagation(v));
279    EXPECT_EQ(0, block0->start_ip);
280    EXPECT_EQ(1, block0->end_ip);
281    EXPECT_EQ(SHADER_OPCODE_FIND_LIVE_CHANNEL, instruction(block0, 0)->opcode);
282    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
283    EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 1)->conditional_mod);
284 }
285 
TEST_F(cmod_propagation_test,intervening_flag_write)286 TEST_F(cmod_propagation_test, intervening_flag_write)
287 {
288    const fs_builder &bld = v->bld;
289    fs_reg dest = v->vgrf(glsl_type::float_type);
290    fs_reg src0 = v->vgrf(glsl_type::float_type);
291    fs_reg src1 = v->vgrf(glsl_type::float_type);
292    fs_reg src2 = v->vgrf(glsl_type::float_type);
293    fs_reg zero(brw_imm_f(0.0f));
294    bld.ADD(dest, src0, src1);
295    bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE);
296    bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
297 
298    /* = Before =
299     *
300     * 0: add(8)        dest  src0  src1
301     * 1: cmp.ge.f0(8)  null  src2  0.0f
302     * 2: cmp.ge.f0(8)  null  dest  0.0f
303     *
304     * = After =
305     * (no changes)
306     */
307 
308    v->calculate_cfg();
309    bblock_t *block0 = v->cfg->blocks[0];
310 
311    EXPECT_EQ(0, block0->start_ip);
312    EXPECT_EQ(2, block0->end_ip);
313 
314    EXPECT_FALSE(cmod_propagation(v));
315    EXPECT_EQ(0, block0->start_ip);
316    EXPECT_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 
TEST_F(cmod_propagation_test,intervening_mismatch_flag_write)324 TEST_F(cmod_propagation_test, intervening_mismatch_flag_write)
325 {
326    const fs_builder &bld = v->bld;
327    fs_reg dest = v->vgrf(glsl_type::float_type);
328    fs_reg src0 = v->vgrf(glsl_type::float_type);
329    fs_reg src1 = v->vgrf(glsl_type::float_type);
330    fs_reg src2 = v->vgrf(glsl_type::float_type);
331    fs_reg zero(brw_imm_f(0.0f));
332    bld.ADD(dest, src0, src1);
333    bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE)
334       ->flag_subreg = 1;
335    bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
336 
337    /* = Before =
338     *
339     * 0: add(8)         dest  src0  src1
340     * 1: cmp.ge.f0.1(8) null  src2  0.0f
341     * 2: cmp.ge.f0(8)   null  dest  0.0f
342     *
343     * = After =
344     * 0: add.ge.f0(8)   dest  src0  src1
345     * 1: cmp.ge.f0.1(8) null  src2  0.0f
346     */
347 
348    v->calculate_cfg();
349    bblock_t *block0 = v->cfg->blocks[0];
350 
351    EXPECT_EQ(0, block0->start_ip);
352    EXPECT_EQ(2, block0->end_ip);
353 
354    EXPECT_TRUE(cmod_propagation(v));
355    EXPECT_EQ(0, block0->start_ip);
356    EXPECT_EQ(1, block0->end_ip);
357    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
358    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
359    EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
360    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
361    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
362    EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
363 }
364 
TEST_F(cmod_propagation_test,intervening_flag_read)365 TEST_F(cmod_propagation_test, intervening_flag_read)
366 {
367    const fs_builder &bld = v->bld;
368    fs_reg dest0 = v->vgrf(glsl_type::float_type);
369    fs_reg dest1 = v->vgrf(glsl_type::float_type);
370    fs_reg src0 = v->vgrf(glsl_type::float_type);
371    fs_reg src1 = v->vgrf(glsl_type::float_type);
372    fs_reg src2 = v->vgrf(glsl_type::float_type);
373    fs_reg zero(brw_imm_f(0.0f));
374    bld.ADD(dest0, src0, src1);
375    set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
376    bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
377 
378    /* = Before =
379     *
380     * 0: add(8)        dest0 src0  src1
381     * 1: (+f0) sel(8)  dest1 src2  0.0f
382     * 2: cmp.ge.f0(8)  null  dest0 0.0f
383     *
384     * = After =
385     * (no changes)
386     */
387 
388    v->calculate_cfg();
389    bblock_t *block0 = v->cfg->blocks[0];
390 
391    EXPECT_EQ(0, block0->start_ip);
392    EXPECT_EQ(2, block0->end_ip);
393 
394    EXPECT_FALSE(cmod_propagation(v));
395    EXPECT_EQ(0, block0->start_ip);
396    EXPECT_EQ(2, block0->end_ip);
397    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
398    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
399    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
400    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
401    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
402 }
403 
TEST_F(cmod_propagation_test,intervening_mismatch_flag_read)404 TEST_F(cmod_propagation_test, intervening_mismatch_flag_read)
405 {
406    const fs_builder &bld = v->bld;
407    fs_reg dest0 = v->vgrf(glsl_type::float_type);
408    fs_reg dest1 = v->vgrf(glsl_type::float_type);
409    fs_reg src0 = v->vgrf(glsl_type::float_type);
410    fs_reg src1 = v->vgrf(glsl_type::float_type);
411    fs_reg src2 = v->vgrf(glsl_type::float_type);
412    fs_reg zero(brw_imm_f(0.0f));
413    bld.ADD(dest0, src0, src1);
414    set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
415       ->flag_subreg = 1;
416    bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
417 
418    /* = Before =
419     *
420     * 0: add(8)         dest0 src0  src1
421     * 1: (+f0.1) sel(8) dest1 src2  0.0f
422     * 2: cmp.ge.f0(8)   null  dest0 0.0f
423     *
424     * = After =
425     * 0: add.ge.f0(8)   dest0 src0  src1
426     * 1: (+f0.1) sel(8) dest1 src2  0.0f
427     */
428 
429    v->calculate_cfg();
430    bblock_t *block0 = v->cfg->blocks[0];
431 
432    EXPECT_EQ(0, block0->start_ip);
433    EXPECT_EQ(2, block0->end_ip);
434 
435    EXPECT_TRUE(cmod_propagation(v));
436    EXPECT_EQ(0, block0->start_ip);
437    EXPECT_EQ(1, block0->end_ip);
438    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
439    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
440    EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
441    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
442    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
443    EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
444 }
445 
TEST_F(cmod_propagation_test,intervening_dest_write)446 TEST_F(cmod_propagation_test, intervening_dest_write)
447 {
448    const fs_builder &bld = v->bld;
449    fs_reg dest = v->vgrf(glsl_type::vec4_type);
450    fs_reg src0 = v->vgrf(glsl_type::float_type);
451    fs_reg src1 = v->vgrf(glsl_type::float_type);
452    fs_reg src2 = v->vgrf(glsl_type::vec2_type);
453    fs_reg zero(brw_imm_f(0.0f));
454    bld.ADD(offset(dest, bld, 2), src0, src1);
455    bld.emit(SHADER_OPCODE_TEX, dest, src2)
456       ->size_written = 4 * REG_SIZE;
457    bld.CMP(bld.null_reg_f(), offset(dest, bld, 2), zero, BRW_CONDITIONAL_GE);
458 
459    /* = Before =
460     *
461     * 0: add(8)        dest+2  src0    src1
462     * 1: tex(8) rlen 4 dest+0  src2
463     * 2: cmp.ge.f0(8)  null    dest+2  0.0f
464     *
465     * = After =
466     * (no changes)
467     */
468 
469    v->calculate_cfg();
470    bblock_t *block0 = v->cfg->blocks[0];
471 
472    EXPECT_EQ(0, block0->start_ip);
473    EXPECT_EQ(2, block0->end_ip);
474 
475    EXPECT_FALSE(cmod_propagation(v));
476    EXPECT_EQ(0, block0->start_ip);
477    EXPECT_EQ(2, block0->end_ip);
478    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
479    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
480    EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
481    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
482    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
483    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
484 }
485 
TEST_F(cmod_propagation_test,intervening_flag_read_same_value)486 TEST_F(cmod_propagation_test, intervening_flag_read_same_value)
487 {
488    const fs_builder &bld = v->bld;
489    fs_reg dest0 = v->vgrf(glsl_type::float_type);
490    fs_reg dest1 = v->vgrf(glsl_type::float_type);
491    fs_reg src0 = v->vgrf(glsl_type::float_type);
492    fs_reg src1 = v->vgrf(glsl_type::float_type);
493    fs_reg src2 = v->vgrf(glsl_type::float_type);
494    fs_reg zero(brw_imm_f(0.0f));
495    set_condmod(BRW_CONDITIONAL_GE, bld.ADD(dest0, src0, src1));
496    set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
497    bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
498 
499    /* = Before =
500     *
501     * 0: add.ge.f0(8)  dest0 src0  src1
502     * 1: (+f0) sel(8)  dest1 src2  0.0f
503     * 2: cmp.ge.f0(8)  null  dest0 0.0f
504     *
505     * = After =
506     * 0: add.ge.f0(8)  dest0 src0  src1
507     * 1: (+f0) sel(8)  dest1 src2  0.0f
508     */
509 
510    v->calculate_cfg();
511    bblock_t *block0 = v->cfg->blocks[0];
512 
513    EXPECT_EQ(0, block0->start_ip);
514    EXPECT_EQ(2, block0->end_ip);
515 
516    EXPECT_TRUE(cmod_propagation(v));
517    EXPECT_EQ(0, block0->start_ip);
518    EXPECT_EQ(1, block0->end_ip);
519    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
520    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
521    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
522    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
523 }
524 
TEST_F(cmod_propagation_test,negate)525 TEST_F(cmod_propagation_test, negate)
526 {
527    const fs_builder &bld = v->bld;
528    fs_reg dest = v->vgrf(glsl_type::float_type);
529    fs_reg src0 = v->vgrf(glsl_type::float_type);
530    fs_reg src1 = v->vgrf(glsl_type::float_type);
531    fs_reg zero(brw_imm_f(0.0f));
532    bld.ADD(dest, src0, src1);
533    dest.negate = true;
534    bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
535 
536    /* = Before =
537     *
538     * 0: add(8)        dest  src0  src1
539     * 1: cmp.ge.f0(8)  null  -dest 0.0f
540     *
541     * = After =
542     * 0: add.le.f0(8)  dest  src0  src1
543     */
544 
545    v->calculate_cfg();
546    bblock_t *block0 = v->cfg->blocks[0];
547 
548    EXPECT_EQ(0, block0->start_ip);
549    EXPECT_EQ(1, block0->end_ip);
550 
551    EXPECT_TRUE(cmod_propagation(v));
552    EXPECT_EQ(0, block0->start_ip);
553    EXPECT_EQ(0, block0->end_ip);
554    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
555    EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
556 }
557 
TEST_F(cmod_propagation_test,movnz)558 TEST_F(cmod_propagation_test, movnz)
559 {
560    const fs_builder &bld = v->bld;
561    fs_reg dest = v->vgrf(glsl_type::float_type);
562    fs_reg src0 = v->vgrf(glsl_type::float_type);
563    fs_reg src1 = v->vgrf(glsl_type::float_type);
564    bld.CMP(dest, src0, src1, BRW_CONDITIONAL_GE);
565    set_condmod(BRW_CONDITIONAL_NZ,
566                bld.MOV(bld.null_reg_f(), dest));
567 
568    /* = Before =
569     *
570     * 0: cmp.ge.f0(8)  dest  src0  src1
571     * 1: mov.nz.f0(8)  null  dest
572     *
573     * = After =
574     * 0: cmp.ge.f0(8)  dest  src0  src1
575     */
576 
577    v->calculate_cfg();
578    bblock_t *block0 = v->cfg->blocks[0];
579 
580    EXPECT_EQ(0, block0->start_ip);
581    EXPECT_EQ(1, block0->end_ip);
582 
583    EXPECT_TRUE(cmod_propagation(v));
584    EXPECT_EQ(0, block0->start_ip);
585    EXPECT_EQ(0, block0->end_ip);
586    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
587    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
588 }
589 
TEST_F(cmod_propagation_test,different_types_cmod_with_zero)590 TEST_F(cmod_propagation_test, different_types_cmod_with_zero)
591 {
592    const fs_builder &bld = v->bld;
593    fs_reg dest = v->vgrf(glsl_type::int_type);
594    fs_reg src0 = v->vgrf(glsl_type::int_type);
595    fs_reg src1 = v->vgrf(glsl_type::int_type);
596    fs_reg zero(brw_imm_f(0.0f));
597    bld.ADD(dest, src0, src1);
598    bld.CMP(bld.null_reg_f(), retype(dest, BRW_REGISTER_TYPE_F), zero,
599            BRW_CONDITIONAL_GE);
600 
601    /* = Before =
602     *
603     * 0: add(8)        dest:D  src0:D  src1:D
604     * 1: cmp.ge.f0(8)  null:F  dest:F  0.0f
605     *
606     * = After =
607     * (no changes)
608     */
609 
610    v->calculate_cfg();
611    bblock_t *block0 = v->cfg->blocks[0];
612 
613    EXPECT_EQ(0, block0->start_ip);
614    EXPECT_EQ(1, block0->end_ip);
615 
616    EXPECT_FALSE(cmod_propagation(v));
617    EXPECT_EQ(0, block0->start_ip);
618    EXPECT_EQ(1, block0->end_ip);
619    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
620    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
621    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
622 }
623 
TEST_F(cmod_propagation_test,andnz_one)624 TEST_F(cmod_propagation_test, andnz_one)
625 {
626    const fs_builder &bld = v->bld;
627    fs_reg dest = v->vgrf(glsl_type::int_type);
628    fs_reg src0 = v->vgrf(glsl_type::float_type);
629    fs_reg zero(brw_imm_f(0.0f));
630    fs_reg one(brw_imm_d(1));
631 
632    bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
633    set_condmod(BRW_CONDITIONAL_NZ,
634                bld.AND(bld.null_reg_d(), dest, one));
635 
636    /* = Before =
637     * 0: cmp.l.f0(8)     dest:F  src0:F  0F
638     * 1: and.nz.f0(8)    null:D  dest:D  1D
639     *
640     * = After =
641     * 0: cmp.l.f0(8)     dest:F  src0:F  0F
642     */
643 
644    v->calculate_cfg();
645    bblock_t *block0 = v->cfg->blocks[0];
646 
647    EXPECT_EQ(0, block0->start_ip);
648    EXPECT_EQ(1, block0->end_ip);
649 
650    EXPECT_TRUE(cmod_propagation(v));
651    EXPECT_EQ(0, block0->start_ip);
652    EXPECT_EQ(0, block0->end_ip);
653    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
654    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
655    EXPECT_TRUE(retype(dest, BRW_REGISTER_TYPE_F)
656                .equals(instruction(block0, 0)->dst));
657 }
658 
TEST_F(cmod_propagation_test,andnz_non_one)659 TEST_F(cmod_propagation_test, andnz_non_one)
660 {
661    const fs_builder &bld = v->bld;
662    fs_reg dest = v->vgrf(glsl_type::int_type);
663    fs_reg src0 = v->vgrf(glsl_type::float_type);
664    fs_reg zero(brw_imm_f(0.0f));
665    fs_reg nonone(brw_imm_d(38));
666 
667    bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
668    set_condmod(BRW_CONDITIONAL_NZ,
669                bld.AND(bld.null_reg_d(), dest, nonone));
670 
671    /* = Before =
672     * 0: cmp.l.f0(8)     dest:F  src0:F  0F
673     * 1: and.nz.f0(8)    null:D  dest:D  38D
674     *
675     * = After =
676     * (no changes)
677     */
678 
679    v->calculate_cfg();
680    bblock_t *block0 = v->cfg->blocks[0];
681 
682    EXPECT_EQ(0, block0->start_ip);
683    EXPECT_EQ(1, block0->end_ip);
684 
685    EXPECT_FALSE(cmod_propagation(v));
686    EXPECT_EQ(0, block0->start_ip);
687    EXPECT_EQ(1, block0->end_ip);
688    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
689    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
690    EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
691    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
692 }
693 
TEST_F(cmod_propagation_test,cmp_cmpnz)694 TEST_F(cmod_propagation_test, cmp_cmpnz)
695 {
696    const fs_builder &bld = v->bld;
697 
698    fs_reg dst0 = v->vgrf(glsl_type::float_type);
699    fs_reg src0 = v->vgrf(glsl_type::float_type);
700    fs_reg zero(brw_imm_f(0));
701 
702    bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
703    bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_NZ);
704 
705    /* = Before =
706     * 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
707     * 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f
708     *
709     * = After =
710     * 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
711     */
712 
713    v->calculate_cfg();
714    bblock_t *block0 = v->cfg->blocks[0];
715 
716    EXPECT_TRUE(cmod_propagation(v));
717    EXPECT_EQ(0, block0->start_ip);
718    EXPECT_EQ(0, block0->end_ip);
719    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
720    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
721 }
722 
TEST_F(cmod_propagation_test,cmp_cmpg)723 TEST_F(cmod_propagation_test, cmp_cmpg)
724 {
725    const fs_builder &bld = v->bld;
726 
727    fs_reg dst0 = v->vgrf(glsl_type::float_type);
728    fs_reg src0 = v->vgrf(glsl_type::float_type);
729    fs_reg zero(brw_imm_f(0));
730 
731    bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
732    bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_G);
733 
734    /* = Before =
735     * 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
736     * 1: cmp.g.f0.0(8) null:F, vgrf0:F, 0f
737     *
738     * = After =
739     * (no changes)
740     */
741 
742    v->calculate_cfg();
743    bblock_t *block0 = v->cfg->blocks[0];
744 
745    EXPECT_FALSE(cmod_propagation(v));
746    EXPECT_EQ(0, block0->start_ip);
747    EXPECT_EQ(1, block0->end_ip);
748    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
749    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
750    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
751    EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 1)->conditional_mod);
752 }
753 
TEST_F(cmod_propagation_test,plnnz_cmpnz)754 TEST_F(cmod_propagation_test, plnnz_cmpnz)
755 {
756    const fs_builder &bld = v->bld;
757 
758    fs_reg dst0 = v->vgrf(glsl_type::float_type);
759    fs_reg src0 = v->vgrf(glsl_type::float_type);
760    fs_reg zero(brw_imm_f(0));
761 
762    set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
763    bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_NZ);
764 
765    /* = Before =
766     * 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
767     * 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f
768     *
769     * = After =
770     * 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
771     */
772 
773    v->calculate_cfg();
774    bblock_t *block0 = v->cfg->blocks[0];
775 
776    EXPECT_TRUE(cmod_propagation(v));
777    EXPECT_EQ(0, block0->start_ip);
778    EXPECT_EQ(0, block0->end_ip);
779    EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
780    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
781 }
782 
TEST_F(cmod_propagation_test,plnnz_cmpz)783 TEST_F(cmod_propagation_test, plnnz_cmpz)
784 {
785    const fs_builder &bld = v->bld;
786 
787    fs_reg dst0 = v->vgrf(glsl_type::float_type);
788    fs_reg src0 = v->vgrf(glsl_type::float_type);
789    fs_reg zero(brw_imm_f(0));
790 
791    set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
792    bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_Z);
793 
794    /* = Before =
795     * 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
796     * 1: cmp.z.f0.0(8) null:F, vgrf0:F, 0f
797     *
798     * = After =
799     * 0: pln.z.f0.0(8) vgrf0:F, vgrf1:F, 0f
800     */
801 
802    v->calculate_cfg();
803    bblock_t *block0 = v->cfg->blocks[0];
804 
805    EXPECT_TRUE(cmod_propagation(v));
806    EXPECT_EQ(0, block0->start_ip);
807    EXPECT_EQ(0, block0->end_ip);
808    EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
809    EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
810 }
811 
TEST_F(cmod_propagation_test,plnnz_sel_cmpz)812 TEST_F(cmod_propagation_test, plnnz_sel_cmpz)
813 {
814    const fs_builder &bld = v->bld;
815 
816    fs_reg dst0 = v->vgrf(glsl_type::float_type);
817    fs_reg dst1 = v->vgrf(glsl_type::float_type);
818    fs_reg src0 = v->vgrf(glsl_type::float_type);
819    fs_reg zero(brw_imm_f(0));
820 
821    set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
822    set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dst1, src0, zero));
823    bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_Z);
824 
825    /* = Before =
826     * 0: pln.nz.f0.0(8) vgrf0:F, vgrf2:F, 0f
827     * 1: (+f0.0) sel(8) vgrf1:F, vgrf2:F, 0f
828     * 2: cmp.z.f0.0(8) null:F, vgrf0:F, 0f
829     *
830     * = After =
831     * (no changes)
832     */
833 
834    v->calculate_cfg();
835    bblock_t *block0 = v->cfg->blocks[0];
836 
837    EXPECT_FALSE(cmod_propagation(v));
838    EXPECT_EQ(0, block0->start_ip);
839    EXPECT_EQ(2, block0->end_ip);
840    EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
841    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
842    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
843    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
844    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
845    EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 2)->conditional_mod);
846 }
847 
TEST_F(cmod_propagation_test,cmp_cmpg_D)848 TEST_F(cmod_propagation_test, cmp_cmpg_D)
849 {
850    const fs_builder &bld = v->bld;
851 
852    fs_reg dst0 = v->vgrf(glsl_type::int_type);
853    fs_reg src0 = v->vgrf(glsl_type::int_type);
854    fs_reg zero(brw_imm_d(0));
855    fs_reg one(brw_imm_d(1));
856 
857    bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
858    bld.CMP(bld.null_reg_d(), dst0, zero, BRW_CONDITIONAL_G);
859 
860    /* = Before =
861     * 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
862     * 1: cmp.g.f0.0(8) null:D, vgrf0:D, 0d
863     *
864     * = After =
865     * (no changes)
866     */
867 
868    v->calculate_cfg();
869    bblock_t *block0 = v->cfg->blocks[0];
870 
871    EXPECT_FALSE(cmod_propagation(v));
872    EXPECT_EQ(0, block0->start_ip);
873    EXPECT_EQ(1, block0->end_ip);
874    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
875    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
876    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
877    EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 1)->conditional_mod);
878 }
879 
TEST_F(cmod_propagation_test,cmp_cmpg_UD)880 TEST_F(cmod_propagation_test, cmp_cmpg_UD)
881 {
882    const fs_builder &bld = v->bld;
883 
884    fs_reg dst0 = v->vgrf(glsl_type::uint_type);
885    fs_reg src0 = v->vgrf(glsl_type::uint_type);
886    fs_reg zero(brw_imm_ud(0));
887 
888    bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
889    bld.CMP(bld.null_reg_ud(), dst0, zero, BRW_CONDITIONAL_G);
890 
891    /* = Before =
892     * 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
893     * 1: cmp.g.f0.0(8) null:UD, vgrf0:UD, 0u
894     *
895     * = After =
896     * 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
897     */
898 
899    v->calculate_cfg();
900    bblock_t *block0 = v->cfg->blocks[0];
901 
902    EXPECT_TRUE(cmod_propagation(v));
903    EXPECT_EQ(0, block0->start_ip);
904    EXPECT_EQ(0, block0->end_ip);
905    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
906    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
907 }
908 
TEST_F(cmod_propagation_test,cmp_cmpl_D)909 TEST_F(cmod_propagation_test, cmp_cmpl_D)
910 {
911    const fs_builder &bld = v->bld;
912 
913    fs_reg dst0 = v->vgrf(glsl_type::int_type);
914    fs_reg src0 = v->vgrf(glsl_type::int_type);
915    fs_reg zero(brw_imm_d(0));
916 
917    bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
918    bld.CMP(bld.null_reg_d(), dst0, zero, BRW_CONDITIONAL_L);
919 
920    /* = Before =
921     * 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
922     * 1: cmp.l.f0.0(8) null:D, vgrf0:D, 0d
923     *
924     * = After =
925     * 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
926     */
927 
928    v->calculate_cfg();
929    bblock_t *block0 = v->cfg->blocks[0];
930 
931    EXPECT_TRUE(cmod_propagation(v));
932    EXPECT_EQ(0, block0->start_ip);
933    EXPECT_EQ(0, block0->end_ip);
934    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
935    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
936 }
937 
TEST_F(cmod_propagation_test,cmp_cmpl_UD)938 TEST_F(cmod_propagation_test, cmp_cmpl_UD)
939 {
940    const fs_builder &bld = v->bld;
941 
942    fs_reg dst0 = v->vgrf(glsl_type::uint_type);
943    fs_reg src0 = v->vgrf(glsl_type::uint_type);
944    fs_reg zero(brw_imm_ud(0));
945 
946    bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
947    bld.CMP(bld.null_reg_ud(), dst0, zero, BRW_CONDITIONAL_L);
948 
949    /* = Before =
950     * 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
951     * 1: cmp.l.f0.0(8) null:UD, vgrf0:UD, 0u
952     *
953     * = After =
954     * (no changes)
955     */
956 
957    v->calculate_cfg();
958    bblock_t *block0 = v->cfg->blocks[0];
959 
960    EXPECT_FALSE(cmod_propagation(v));
961    EXPECT_EQ(0, block0->start_ip);
962    EXPECT_EQ(1, block0->end_ip);
963    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
964    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
965    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
966    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
967 }
968 
TEST_F(cmod_propagation_test,andz_one)969 TEST_F(cmod_propagation_test, andz_one)
970 {
971    const fs_builder &bld = v->bld;
972    fs_reg dest = v->vgrf(glsl_type::int_type);
973    fs_reg src0 = v->vgrf(glsl_type::float_type);
974    fs_reg zero(brw_imm_f(0.0f));
975    fs_reg one(brw_imm_d(1));
976 
977    bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
978    set_condmod(BRW_CONDITIONAL_Z,
979                bld.AND(bld.null_reg_d(), dest, one));
980 
981    /* = Before =
982     * 0: cmp.l.f0(8)     dest:F  src0:F  0F
983     * 1: and.z.f0(8)     null:D  dest:D  1D
984     *
985     * = After =
986     * (no changes)
987     */
988 
989    v->calculate_cfg();
990    bblock_t *block0 = v->cfg->blocks[0];
991 
992    EXPECT_EQ(0, block0->start_ip);
993    EXPECT_EQ(1, block0->end_ip);
994 
995    EXPECT_FALSE(cmod_propagation(v));
996    EXPECT_EQ(0, block0->start_ip);
997    EXPECT_EQ(1, block0->end_ip);
998    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
999    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1000    EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
1001    EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
1002 }
1003 
TEST_F(cmod_propagation_test,add_not_merge_with_compare)1004 TEST_F(cmod_propagation_test, add_not_merge_with_compare)
1005 {
1006    const fs_builder &bld = v->bld;
1007    fs_reg dest = v->vgrf(glsl_type::float_type);
1008    fs_reg src0 = v->vgrf(glsl_type::float_type);
1009    fs_reg src1 = v->vgrf(glsl_type::float_type);
1010    bld.ADD(dest, src0, src1);
1011    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1012 
1013    /* The addition and the implicit subtraction in the compare do not compute
1014     * related values.
1015     *
1016     * = Before =
1017     * 0: add(8)          dest:F  src0:F  src1:F
1018     * 1: cmp.l.f0(8)     null:F  src0:F  src1:F
1019     *
1020     * = After =
1021     * (no changes)
1022     */
1023    v->calculate_cfg();
1024    bblock_t *block0 = v->cfg->blocks[0];
1025 
1026    EXPECT_EQ(0, block0->start_ip);
1027    EXPECT_EQ(1, block0->end_ip);
1028 
1029    EXPECT_FALSE(cmod_propagation(v));
1030    EXPECT_EQ(0, block0->start_ip);
1031    EXPECT_EQ(1, block0->end_ip);
1032    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1033    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1034    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
1035    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
1036 }
1037 
TEST_F(cmod_propagation_test,subtract_merge_with_compare)1038 TEST_F(cmod_propagation_test, subtract_merge_with_compare)
1039 {
1040    const fs_builder &bld = v->bld;
1041    fs_reg dest = v->vgrf(glsl_type::float_type);
1042    fs_reg src0 = v->vgrf(glsl_type::float_type);
1043    fs_reg src1 = v->vgrf(glsl_type::float_type);
1044    bld.ADD(dest, src0, negate(src1));
1045    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1046 
1047    /* = Before =
1048     * 0: add(8)          dest:F  src0:F  -src1:F
1049     * 1: cmp.l.f0(8)     null:F  src0:F  src1:F
1050     *
1051     * = After =
1052     * 0: add.l.f0(8)     dest:F  src0:F  -src1:F
1053     */
1054    v->calculate_cfg();
1055    bblock_t *block0 = v->cfg->blocks[0];
1056 
1057    EXPECT_EQ(0, block0->start_ip);
1058    EXPECT_EQ(1, block0->end_ip);
1059 
1060    EXPECT_TRUE(cmod_propagation(v));
1061    EXPECT_EQ(0, block0->start_ip);
1062    EXPECT_EQ(0, block0->end_ip);
1063    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1064    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1065 }
1066 
TEST_F(cmod_propagation_test,subtract_immediate_merge_with_compare)1067 TEST_F(cmod_propagation_test, subtract_immediate_merge_with_compare)
1068 {
1069    const fs_builder &bld = v->bld;
1070    fs_reg dest = v->vgrf(glsl_type::float_type);
1071    fs_reg src0 = v->vgrf(glsl_type::float_type);
1072    fs_reg one(brw_imm_f(1.0f));
1073    fs_reg negative_one(brw_imm_f(-1.0f));
1074 
1075    bld.ADD(dest, src0, negative_one);
1076    bld.CMP(bld.null_reg_f(), src0, one, BRW_CONDITIONAL_NZ);
1077 
1078    /* = Before =
1079     * 0: add(8)          dest:F  src0:F  -1.0f
1080     * 1: cmp.nz.f0(8)    null:F  src0:F  1.0f
1081     *
1082     * = After =
1083     * 0: add.nz.f0(8)    dest:F  src0:F  -1.0f
1084     */
1085    v->calculate_cfg();
1086    bblock_t *block0 = v->cfg->blocks[0];
1087 
1088    EXPECT_EQ(0, block0->start_ip);
1089    EXPECT_EQ(1, block0->end_ip);
1090 
1091    EXPECT_TRUE(cmod_propagation(v));
1092    EXPECT_EQ(0, block0->start_ip);
1093    EXPECT_EQ(0, block0->end_ip);
1094    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1095    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
1096 }
1097 
TEST_F(cmod_propagation_test,subtract_merge_with_compare_intervening_add)1098 TEST_F(cmod_propagation_test, subtract_merge_with_compare_intervening_add)
1099 {
1100    const fs_builder &bld = v->bld;
1101    fs_reg dest0 = v->vgrf(glsl_type::float_type);
1102    fs_reg dest1 = v->vgrf(glsl_type::float_type);
1103    fs_reg src0 = v->vgrf(glsl_type::float_type);
1104    fs_reg src1 = v->vgrf(glsl_type::float_type);
1105    bld.ADD(dest0, src0, negate(src1));
1106    bld.ADD(dest1, src0, src1);
1107    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1108 
1109    /* = Before =
1110     * 0: add(8)          dest0:F src0:F  -src1:F
1111     * 1: add(8)          dest1:F src0:F  src1:F
1112     * 2: cmp.l.f0(8)     null:F  src0:F  src1:F
1113     *
1114     * = After =
1115     * 0: add.l.f0(8)     dest0:F src0:F  -src1:F
1116     * 1: add(8)          dest1:F src0:F  src1:F
1117     */
1118    v->calculate_cfg();
1119    bblock_t *block0 = v->cfg->blocks[0];
1120 
1121    EXPECT_EQ(0, block0->start_ip);
1122    EXPECT_EQ(2, block0->end_ip);
1123 
1124    EXPECT_TRUE(cmod_propagation(v));
1125    EXPECT_EQ(0, block0->start_ip);
1126    EXPECT_EQ(1, block0->end_ip);
1127    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1128    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1129    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1130    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
1131 }
1132 
TEST_F(cmod_propagation_test,subtract_not_merge_with_compare_intervening_partial_write)1133 TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_partial_write)
1134 {
1135    const fs_builder &bld = v->bld;
1136    fs_reg dest0 = v->vgrf(glsl_type::float_type);
1137    fs_reg dest1 = v->vgrf(glsl_type::float_type);
1138    fs_reg src0 = v->vgrf(glsl_type::float_type);
1139    fs_reg src1 = v->vgrf(glsl_type::float_type);
1140    bld.ADD(dest0, src0, negate(src1));
1141    set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, src0, negate(src1)));
1142    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1143 
1144    /* = Before =
1145     * 0: add(8)          dest0:F src0:F  -src1:F
1146     * 1: (+f0) add(8)    dest1:F src0:F  -src1:F
1147     * 2: cmp.l.f0(8)     null:F  src0:F  src1:F
1148     *
1149     * = After =
1150     * (no changes)
1151     */
1152    v->calculate_cfg();
1153    bblock_t *block0 = v->cfg->blocks[0];
1154 
1155    EXPECT_EQ(0, block0->start_ip);
1156    EXPECT_EQ(2, block0->end_ip);
1157 
1158    EXPECT_FALSE(cmod_propagation(v));
1159    EXPECT_EQ(0, block0->start_ip);
1160    EXPECT_EQ(2, block0->end_ip);
1161    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1162    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1163    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1164    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
1165    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
1166    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
1167 }
1168 
TEST_F(cmod_propagation_test,subtract_not_merge_with_compare_intervening_add)1169 TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_add)
1170 {
1171    const fs_builder &bld = v->bld;
1172    fs_reg dest0 = v->vgrf(glsl_type::float_type);
1173    fs_reg dest1 = v->vgrf(glsl_type::float_type);
1174    fs_reg src0 = v->vgrf(glsl_type::float_type);
1175    fs_reg src1 = v->vgrf(glsl_type::float_type);
1176    bld.ADD(dest0, src0, negate(src1));
1177    set_condmod(BRW_CONDITIONAL_EQ, bld.ADD(dest1, src0, src1));
1178    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1179 
1180    /* = Before =
1181     * 0: add(8)          dest0:F src0:F  -src1:F
1182     * 1: add.z.f0(8)     dest1:F src0:F  src1:F
1183     * 2: cmp.l.f0(8)     null:F  src0:F  src1:F
1184     *
1185     * = After =
1186     * (no changes)
1187     */
1188    v->calculate_cfg();
1189    bblock_t *block0 = v->cfg->blocks[0];
1190 
1191    EXPECT_EQ(0, block0->start_ip);
1192    EXPECT_EQ(2, block0->end_ip);
1193 
1194    EXPECT_FALSE(cmod_propagation(v));
1195    EXPECT_EQ(0, block0->start_ip);
1196    EXPECT_EQ(2, block0->end_ip);
1197    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1198    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1199    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1200    EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
1201    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
1202    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
1203 }
1204 
TEST_F(cmod_propagation_test,add_merge_with_compare)1205 TEST_F(cmod_propagation_test, add_merge_with_compare)
1206 {
1207    const fs_builder &bld = v->bld;
1208    fs_reg dest = v->vgrf(glsl_type::float_type);
1209    fs_reg src0 = v->vgrf(glsl_type::float_type);
1210    fs_reg src1 = v->vgrf(glsl_type::float_type);
1211    bld.ADD(dest, src0, src1);
1212    bld.CMP(bld.null_reg_f(), src0, negate(src1), BRW_CONDITIONAL_L);
1213 
1214    /* = Before =
1215     * 0: add(8)          dest:F  src0:F  src1:F
1216     * 1: cmp.l.f0(8)     null:F  src0:F  -src1:F
1217     *
1218     * = After =
1219     * 0: add.l.f0(8)     dest:F  src0:F  src1:F
1220     */
1221    v->calculate_cfg();
1222    bblock_t *block0 = v->cfg->blocks[0];
1223 
1224    EXPECT_EQ(0, block0->start_ip);
1225    EXPECT_EQ(1, block0->end_ip);
1226 
1227    EXPECT_TRUE(cmod_propagation(v));
1228    EXPECT_EQ(0, block0->start_ip);
1229    EXPECT_EQ(0, block0->end_ip);
1230    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1231    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1232 }
1233 
TEST_F(cmod_propagation_test,negative_subtract_merge_with_compare)1234 TEST_F(cmod_propagation_test, negative_subtract_merge_with_compare)
1235 {
1236    const fs_builder &bld = v->bld;
1237    fs_reg dest = v->vgrf(glsl_type::float_type);
1238    fs_reg src0 = v->vgrf(glsl_type::float_type);
1239    fs_reg src1 = v->vgrf(glsl_type::float_type);
1240    bld.ADD(dest, src1, negate(src0));
1241    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1242 
1243    /* The result of the subtract is the negatiion of the result of the
1244     * implicit subtract in the compare, so the condition must change.
1245     *
1246     * = Before =
1247     * 0: add(8)          dest:F  src1:F  -src0:F
1248     * 1: cmp.l.f0(8)     null:F  src0:F  src1:F
1249     *
1250     * = After =
1251     * 0: add.g.f0(8)     dest:F  src0:F  -src1:F
1252     */
1253    v->calculate_cfg();
1254    bblock_t *block0 = v->cfg->blocks[0];
1255 
1256    EXPECT_EQ(0, block0->start_ip);
1257    EXPECT_EQ(1, block0->end_ip);
1258 
1259    EXPECT_TRUE(cmod_propagation(v));
1260    EXPECT_EQ(0, block0->start_ip);
1261    EXPECT_EQ(0, block0->end_ip);
1262    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1263    EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod);
1264 }
1265 
TEST_F(cmod_propagation_test,subtract_delete_compare)1266 TEST_F(cmod_propagation_test, subtract_delete_compare)
1267 {
1268    const fs_builder &bld = v->bld;
1269    fs_reg dest = v->vgrf(glsl_type::float_type);
1270    fs_reg dest1 = v->vgrf(glsl_type::float_type);
1271    fs_reg src0 = v->vgrf(glsl_type::float_type);
1272    fs_reg src1 = v->vgrf(glsl_type::float_type);
1273    fs_reg src2 = v->vgrf(glsl_type::float_type);
1274 
1275    set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)));
1276    set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2));
1277    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1278 
1279    /* = Before =
1280     * 0: add.l.f0(8)     dest0:F src0:F  -src1:F
1281     * 1: (+f0) mov(0)    dest1:F src2:F
1282     * 2: cmp.l.f0(8)     null:F  src0:F  src1:F
1283     *
1284     * = After =
1285     * 0: add.l.f0(8)     dest:F  src0:F  -src1:F
1286     * 1: (+f0) mov(0)    dest1:F src2:F
1287     */
1288    v->calculate_cfg();
1289    bblock_t *block0 = v->cfg->blocks[0];
1290 
1291    EXPECT_EQ(0, block0->start_ip);
1292    EXPECT_EQ(2, block0->end_ip);
1293 
1294    EXPECT_TRUE(cmod_propagation(v));
1295    EXPECT_EQ(0, block0->start_ip);
1296    EXPECT_EQ(1, block0->end_ip);
1297    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1298    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1299    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
1300    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1301 }
1302 
TEST_F(cmod_propagation_test,subtract_delete_compare_other_flag)1303 TEST_F(cmod_propagation_test, subtract_delete_compare_other_flag)
1304 {
1305    /* This test is the same as subtract_delete_compare but it explicitly used
1306     * flag f0.1 for the subtraction and the comparison.
1307     */
1308    const fs_builder &bld = v->bld;
1309    fs_reg dest = v->vgrf(glsl_type::float_type);
1310    fs_reg dest1 = v->vgrf(glsl_type::float_type);
1311    fs_reg src0 = v->vgrf(glsl_type::float_type);
1312    fs_reg src1 = v->vgrf(glsl_type::float_type);
1313    fs_reg src2 = v->vgrf(glsl_type::float_type);
1314 
1315    set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)))
1316       ->flag_subreg = 1;
1317    set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2));
1318    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
1319       ->flag_subreg = 1;
1320 
1321    /* = Before =
1322     * 0: add.l.f0.1(8)   dest0:F src0:F  -src1:F
1323     * 1: (+f0) mov(0)    dest1:F src2:F
1324     * 2: cmp.l.f0.1(8)   null:F  src0:F  src1:F
1325     *
1326     * = After =
1327     * 0: add.l.f0.1(8)   dest:F  src0:F  -src1:F
1328     * 1: (+f0) mov(0)    dest1:F src2:F
1329     */
1330    v->calculate_cfg();
1331    bblock_t *block0 = v->cfg->blocks[0];
1332 
1333    EXPECT_EQ(0, block0->start_ip);
1334    EXPECT_EQ(2, block0->end_ip);
1335 
1336    EXPECT_TRUE(cmod_propagation(v));
1337    EXPECT_EQ(0, block0->start_ip);
1338    EXPECT_EQ(1, block0->end_ip);
1339    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1340    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1341    EXPECT_EQ(1, instruction(block0, 0)->flag_subreg);
1342    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
1343    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1344 }
1345 
TEST_F(cmod_propagation_test,subtract_to_mismatch_flag)1346 TEST_F(cmod_propagation_test, subtract_to_mismatch_flag)
1347 {
1348    const fs_builder &bld = v->bld;
1349    fs_reg dest = v->vgrf(glsl_type::float_type);
1350    fs_reg src0 = v->vgrf(glsl_type::float_type);
1351    fs_reg src1 = v->vgrf(glsl_type::float_type);
1352 
1353    set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)));
1354    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
1355       ->flag_subreg = 1;
1356 
1357    /* = Before =
1358     * 0: add.l.f0(8)     dest0:F src0:F  -src1:F
1359     * 1: cmp.l.f0.1(8)   null:F  src0:F  src1:F
1360     *
1361     * = After =
1362     * No changes
1363     */
1364    v->calculate_cfg();
1365    bblock_t *block0 = v->cfg->blocks[0];
1366 
1367    EXPECT_EQ(0, block0->start_ip);
1368    EXPECT_EQ(1, block0->end_ip);
1369 
1370    EXPECT_FALSE(cmod_propagation(v));
1371    EXPECT_EQ(0, block0->start_ip);
1372    EXPECT_EQ(1, block0->end_ip);
1373    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1374    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1375    EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
1376    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
1377    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
1378    EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
1379 }
1380 
TEST_F(cmod_propagation_test,subtract_merge_with_compare_intervening_mismatch_flag_write)1381 TEST_F(cmod_propagation_test,
1382        subtract_merge_with_compare_intervening_mismatch_flag_write)
1383 {
1384    const fs_builder &bld = v->bld;
1385    fs_reg dest0 = v->vgrf(glsl_type::float_type);
1386    fs_reg src0 = v->vgrf(glsl_type::float_type);
1387    fs_reg src1 = v->vgrf(glsl_type::float_type);
1388 
1389    bld.ADD(dest0, src0, negate(src1));
1390    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
1391             ->flag_subreg = 1;
1392    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1393 
1394    /* = Before =
1395     * 0: add(8)         dest0:F src0:F  -src1:F
1396     * 1: cmp.l.f0.1(8)  null:F  src0:F  src1:F
1397     * 2: cmp.l.f0(8)    null:F  src0:F  src1:F
1398     *
1399     * = After =
1400     * 0: add.l.f0(8)    dest0:F src0:F  -src1:F
1401     * 1: cmp.l.f0.1(8)  null:F  src0:F  src1:F
1402     *
1403     * NOTE: Another perfectly valid after sequence would be:
1404     *
1405     * 0: add.f0.1(8)    dest0:F src0:F  -src1:F
1406     * 1: cmp.l.f0(8)    null:F  src0:F  src1:F
1407     *
1408     * However, the optimization pass starts at the end of the basic block.
1409     * Because of this, the cmp.l.f0 will always be chosen.  If the pass
1410     * changes its strategy, this test will also need to change.
1411     */
1412    v->calculate_cfg();
1413    bblock_t *block0 = v->cfg->blocks[0];
1414 
1415    EXPECT_EQ(0, block0->start_ip);
1416    EXPECT_EQ(2, block0->end_ip);
1417 
1418    EXPECT_TRUE(cmod_propagation(v));
1419    EXPECT_EQ(0, block0->start_ip);
1420    EXPECT_EQ(1, block0->end_ip);
1421    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1422    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1423    EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
1424    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
1425    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
1426    EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
1427 }
1428 
TEST_F(cmod_propagation_test,subtract_merge_with_compare_intervening_mismatch_flag_read)1429 TEST_F(cmod_propagation_test,
1430        subtract_merge_with_compare_intervening_mismatch_flag_read)
1431 {
1432    const fs_builder &bld = v->bld;
1433    fs_reg dest0 = v->vgrf(glsl_type::float_type);
1434    fs_reg dest1 = v->vgrf(glsl_type::float_type);
1435    fs_reg src0 = v->vgrf(glsl_type::float_type);
1436    fs_reg src1 = v->vgrf(glsl_type::float_type);
1437    fs_reg src2 = v->vgrf(glsl_type::float_type);
1438    fs_reg zero(brw_imm_f(0.0f));
1439 
1440    bld.ADD(dest0, src0, negate(src1));
1441    set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
1442       ->flag_subreg = 1;
1443    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1444 
1445    /* = Before =
1446     * 0: add(8)         dest0:F src0:F  -src1:F
1447     * 1: (+f0.1) sel(8) dest1   src2    0.0f
1448     * 2: cmp.l.f0(8)    null:F  src0:F  src1:F
1449     *
1450     * = After =
1451     * 0: add.l.f0(8)    dest0:F src0:F  -src1:F
1452     * 1: (+f0.1) sel(8) dest1   src2    0.0f
1453     */
1454    v->calculate_cfg();
1455    bblock_t *block0 = v->cfg->blocks[0];
1456 
1457    EXPECT_EQ(0, block0->start_ip);
1458    EXPECT_EQ(2, block0->end_ip);
1459 
1460    EXPECT_TRUE(cmod_propagation(v));
1461    EXPECT_EQ(0, block0->start_ip);
1462    EXPECT_EQ(1, block0->end_ip);
1463    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1464    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1465    EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
1466    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
1467    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1468    EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
1469 }
1470 
TEST_F(cmod_propagation_test,subtract_delete_compare_derp)1471 TEST_F(cmod_propagation_test, subtract_delete_compare_derp)
1472 {
1473    const fs_builder &bld = v->bld;
1474    fs_reg dest0 = v->vgrf(glsl_type::float_type);
1475    fs_reg dest1 = v->vgrf(glsl_type::float_type);
1476    fs_reg src0 = v->vgrf(glsl_type::float_type);
1477    fs_reg src1 = v->vgrf(glsl_type::float_type);
1478 
1479    set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest0, src0, negate(src1)));
1480    set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, negate(src0), src1));
1481    bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1482 
1483    /* = Before =
1484     * 0: add.l.f0(8)     dest0:F src0:F  -src1:F
1485     * 1: (+f0) add(0)    dest1:F -src0:F src1:F
1486     * 2: cmp.l.f0(8)     null:F  src0:F  src1:F
1487     *
1488     * = After =
1489     * 0: add.l.f0(8)     dest0:F src0:F  -src1:F
1490     * 1: (+f0) add(0)    dest1:F -src0:F src1:F
1491     */
1492    v->calculate_cfg();
1493    bblock_t *block0 = v->cfg->blocks[0];
1494 
1495    EXPECT_EQ(0, block0->start_ip);
1496    EXPECT_EQ(2, block0->end_ip);
1497 
1498    EXPECT_TRUE(cmod_propagation(v));
1499    EXPECT_EQ(0, block0->start_ip);
1500    EXPECT_EQ(1, block0->end_ip);
1501    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1502    EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1503    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1504    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1505 }
1506 
TEST_F(cmod_propagation_test,signed_unsigned_comparison_mismatch)1507 TEST_F(cmod_propagation_test, signed_unsigned_comparison_mismatch)
1508 {
1509    const fs_builder &bld = v->bld;
1510    fs_reg dest0 = v->vgrf(glsl_type::int_type);
1511    fs_reg src0 = v->vgrf(glsl_type::int_type);
1512    src0.type = BRW_REGISTER_TYPE_W;
1513 
1514    bld.ASR(dest0, negate(src0), brw_imm_d(15));
1515    bld.CMP(bld.null_reg_ud(), retype(dest0, BRW_REGISTER_TYPE_UD),
1516            brw_imm_ud(0u), BRW_CONDITIONAL_LE);
1517 
1518    /* = Before =
1519     * 0: asr(8)          dest:D   -src0:W 15D
1520     * 1: cmp.le.f0(8)    null:UD  dest:UD 0UD
1521     *
1522     * = After =
1523     * (no changes)
1524     */
1525    v->calculate_cfg();
1526    bblock_t *block0 = v->cfg->blocks[0];
1527 
1528    EXPECT_EQ(0, block0->start_ip);
1529    EXPECT_EQ(1, block0->end_ip);
1530 
1531    EXPECT_FALSE(cmod_propagation(v));
1532    EXPECT_EQ(0, block0->start_ip);
1533    EXPECT_EQ(1, block0->end_ip);
1534    EXPECT_EQ(BRW_OPCODE_ASR, instruction(block0, 0)->opcode);
1535    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
1536    EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 1)->conditional_mod);
1537 }
1538 
TEST_F(cmod_propagation_test,ior_f2i_nz)1539 TEST_F(cmod_propagation_test, ior_f2i_nz)
1540 {
1541    const fs_builder &bld = v->bld;
1542    fs_reg dest = bld.vgrf(BRW_REGISTER_TYPE_D);
1543    fs_reg src0 = bld.vgrf(BRW_REGISTER_TYPE_D);
1544    fs_reg src1 = bld.vgrf(BRW_REGISTER_TYPE_D);
1545 
1546    bld.OR(dest, src0, src1);
1547    bld.MOV(bld.null_reg_d(), retype(dest, BRW_REGISTER_TYPE_F))
1548       ->conditional_mod = BRW_CONDITIONAL_NZ;
1549 
1550    /* = Before =
1551     * 0: or(8)           dest:D  src0:D  src1:D
1552     * 1: mov.nz(8)       null:D  dest:F
1553     *
1554     * = After =
1555     * No changes.
1556     *
1557     * If src0 = 0x30000000 and src1 = 0x0f000000, then the value stored in
1558     * dest, interpreted as floating point, is 0.5.  This bit pattern is not
1559     * zero, but after the float-to-integer conversion, the value is zero.
1560     */
1561    v->calculate_cfg();
1562    bblock_t *block0 = v->cfg->blocks[0];
1563 
1564    EXPECT_EQ(0, block0->start_ip);
1565    EXPECT_EQ(1, block0->end_ip);
1566 
1567    EXPECT_FALSE(cmod_propagation(v));
1568    EXPECT_EQ(0, block0->start_ip);
1569 
1570    EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
1571    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1572 
1573    /* This is ASSERT_EQ because if end_ip is 0, the instruction(block0, 1)
1574     * calls will not work properly, and the test will give weird results.
1575     */
1576    ASSERT_EQ(1, block0->end_ip);
1577    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
1578    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
1579 }
1580 
1581 
1582 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)1583 cmod_propagation_test::test_mov_prop(enum brw_conditional_mod cmod,
1584                                      enum brw_reg_type add_type,
1585                                      enum brw_reg_type mov_dst_type,
1586                                      bool expected_cmod_prop_progress)
1587 {
1588    const fs_builder &bld = v->bld;
1589    fs_reg dest = bld.vgrf(add_type);
1590    fs_reg src0 = bld.vgrf(add_type);
1591    fs_reg src1 = bld.vgrf(add_type);
1592 
1593    bld.ADD(dest, src0, src1);
1594    bld.MOV(retype(bld.null_reg_ud(), mov_dst_type), dest)
1595       ->conditional_mod = cmod;
1596 
1597    v->calculate_cfg();
1598    bblock_t *block0 = v->cfg->blocks[0];
1599 
1600    EXPECT_EQ(0, block0->start_ip);
1601    EXPECT_EQ(1, block0->end_ip);
1602 
1603    EXPECT_EQ(expected_cmod_prop_progress, cmod_propagation(v));
1604 
1605    const enum brw_conditional_mod add_cmod =
1606       expected_cmod_prop_progress ? cmod : BRW_CONDITIONAL_NONE;
1607 
1608    EXPECT_EQ(0, block0->start_ip);
1609 
1610    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1611    EXPECT_EQ(add_cmod, instruction(block0, 0)->conditional_mod);
1612 
1613    if (expected_cmod_prop_progress) {
1614       EXPECT_EQ(0, block0->end_ip);
1615    } else {
1616       /* This is ASSERT_EQ because if end_ip is 0, the instruction(block0, 1)
1617        * calls will not work properly, and the test will give weird results.
1618        */
1619       ASSERT_EQ(1, block0->end_ip);
1620 
1621       EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
1622       EXPECT_EQ(cmod, instruction(block0, 1)->conditional_mod);
1623    }
1624 }
1625 
TEST_F(cmod_propagation_test,fadd_fmov_nz)1626 TEST_F(cmod_propagation_test, fadd_fmov_nz)
1627 {
1628    /* = Before =
1629     * 0: add(8)          dest:F  src0:F  src1:F
1630     * 1: mov.nz(8)       null:F  dest:F
1631     *
1632     * = After =
1633     * 0: add.nz(8)       dest:F  src0:F  src1:F
1634     */
1635    test_mov_prop(BRW_CONDITIONAL_NZ,
1636                  BRW_REGISTER_TYPE_F,
1637                  BRW_REGISTER_TYPE_F,
1638                  true);
1639 }
1640 
TEST_F(cmod_propagation_test,fadd_fmov_z)1641 TEST_F(cmod_propagation_test, fadd_fmov_z)
1642 {
1643    /* = Before =
1644     * 0: add(8)          dest:F  src0:F  src1:F
1645     * 1: mov.z(8)        null:F  dest:F
1646     *
1647     * = After =
1648     * 0: add.z(8)        dest:F  src0:F  src1:F
1649     */
1650    test_mov_prop(BRW_CONDITIONAL_Z,
1651                  BRW_REGISTER_TYPE_F,
1652                  BRW_REGISTER_TYPE_F,
1653                  true);
1654 }
1655 
TEST_F(cmod_propagation_test,fadd_fmov_l)1656 TEST_F(cmod_propagation_test, fadd_fmov_l)
1657 {
1658    /* = Before =
1659     * 0: add(8)          dest:F  src0:F  src1:F
1660     * 1: mov.l(8)        null:F  dest:F
1661     *
1662     * = After =
1663     * 0: add.l(8)        dest:F  src0:F  src1:F
1664     */
1665    test_mov_prop(BRW_CONDITIONAL_L,
1666                  BRW_REGISTER_TYPE_F,
1667                  BRW_REGISTER_TYPE_F,
1668                  true);
1669 }
1670 
TEST_F(cmod_propagation_test,fadd_fmov_g)1671 TEST_F(cmod_propagation_test, fadd_fmov_g)
1672 {
1673    /* = Before =
1674     * 0: add(8)          dest:F  src0:F  src1:F
1675     * 1: mov.g(8)        null:F  dest:F
1676     *
1677     * = After =
1678     * 0: add.g(8)        dest:F  src0:F  src1:F
1679     */
1680    test_mov_prop(BRW_CONDITIONAL_G,
1681                  BRW_REGISTER_TYPE_F,
1682                  BRW_REGISTER_TYPE_F,
1683                  true);
1684 }
1685 
TEST_F(cmod_propagation_test,fadd_fmov_le)1686 TEST_F(cmod_propagation_test, fadd_fmov_le)
1687 {
1688    /* = Before =
1689     * 0: add(8)          dest:F  src0:F  src1:F
1690     * 1: mov.le(8)       null:F  dest:F
1691     *
1692     * = After =
1693     * 0: add.le(8)        dest:F  src0:F  src1:F
1694     */
1695    test_mov_prop(BRW_CONDITIONAL_LE,
1696                  BRW_REGISTER_TYPE_F,
1697                  BRW_REGISTER_TYPE_F,
1698                  true);
1699 }
1700 
TEST_F(cmod_propagation_test,fadd_fmov_ge)1701 TEST_F(cmod_propagation_test, fadd_fmov_ge)
1702 {
1703    /* = Before =
1704     * 0: add(8)          dest:F  src0:F  src1:F
1705     * 1: mov.ge(8)       null:F  dest:F
1706     *
1707     * = After =
1708     * 0: add.ge(8)       dest:F  src0:F  src1:F
1709     */
1710    test_mov_prop(BRW_CONDITIONAL_GE,
1711                  BRW_REGISTER_TYPE_F,
1712                  BRW_REGISTER_TYPE_F,
1713                  true);
1714 }
1715 
TEST_F(cmod_propagation_test,iadd_imov_nz)1716 TEST_F(cmod_propagation_test, iadd_imov_nz)
1717 {
1718    /* = Before =
1719     * 0: add(8)          dest:D  src0:D  src1:D
1720     * 1: mov.nz(8)       null:D  dest:D
1721     *
1722     * = After =
1723     * 0: add.nz(8)       dest:D  src0:D  src1:D
1724     */
1725    test_mov_prop(BRW_CONDITIONAL_NZ,
1726                  BRW_REGISTER_TYPE_D,
1727                  BRW_REGISTER_TYPE_D,
1728                  true);
1729 }
1730 
TEST_F(cmod_propagation_test,iadd_imov_z)1731 TEST_F(cmod_propagation_test, iadd_imov_z)
1732 {
1733    /* = Before =
1734     * 0: add(8)          dest:D  src0:D  src1:D
1735     * 1: mov.z(8)        null:D  dest:D
1736     *
1737     * = After =
1738     * 0: add.z(8)        dest:D  src0:D  src1:D
1739     */
1740    test_mov_prop(BRW_CONDITIONAL_Z,
1741                  BRW_REGISTER_TYPE_D,
1742                  BRW_REGISTER_TYPE_D,
1743                  true);
1744 }
1745 
TEST_F(cmod_propagation_test,iadd_imov_l)1746 TEST_F(cmod_propagation_test, iadd_imov_l)
1747 {
1748    /* = Before =
1749     * 0: add(8)          dest:D  src0:D  src1:D
1750     * 1: mov.l(8)        null:D  dest:D
1751     *
1752     * = After =
1753     * 0: add.l(8)        dest:D  src0:D  src1:D
1754     */
1755    test_mov_prop(BRW_CONDITIONAL_L,
1756                  BRW_REGISTER_TYPE_D,
1757                  BRW_REGISTER_TYPE_D,
1758                  true);
1759 }
1760 
TEST_F(cmod_propagation_test,iadd_imov_g)1761 TEST_F(cmod_propagation_test, iadd_imov_g)
1762 {
1763    /* = Before =
1764     * 0: add(8)          dest:D  src0:D  src1:D
1765     * 1: mov.g(8)        null:D  dest:D
1766     *
1767     * = After =
1768     * 0: add.g(8)        dest:D  src0:D  src1:D
1769     */
1770    test_mov_prop(BRW_CONDITIONAL_G,
1771                  BRW_REGISTER_TYPE_D,
1772                  BRW_REGISTER_TYPE_D,
1773                  true);
1774 }
1775 
TEST_F(cmod_propagation_test,iadd_imov_le)1776 TEST_F(cmod_propagation_test, iadd_imov_le)
1777 {
1778    /* = Before =
1779     * 0: add(8)          dest:D  src0:D  src1:D
1780     * 1: mov.le(8)       null:D  dest:D
1781     *
1782     * = After =
1783     * 0: add.le(8)       dest:D  src0:D  src1:D
1784     */
1785    test_mov_prop(BRW_CONDITIONAL_LE,
1786                  BRW_REGISTER_TYPE_D,
1787                  BRW_REGISTER_TYPE_D,
1788                  true);
1789 }
1790 
TEST_F(cmod_propagation_test,iadd_imov_ge)1791 TEST_F(cmod_propagation_test, iadd_imov_ge)
1792 {
1793    /* = Before =
1794     * 0: add(8)          dest:D  src0:D  src1:D
1795     * 1: mov.ge(8)       null:D  dest:D
1796     *
1797     * = After =
1798     * 0: add.ge(8)       dest:D  src0:D  src1:D
1799     */
1800    test_mov_prop(BRW_CONDITIONAL_GE,
1801                  BRW_REGISTER_TYPE_D,
1802                  BRW_REGISTER_TYPE_D,
1803                  true);
1804 }
1805 
TEST_F(cmod_propagation_test,iadd_umov_nz)1806 TEST_F(cmod_propagation_test, iadd_umov_nz)
1807 {
1808    /* = Before =
1809     * 0: add(8)          dest:D  src0:D  src1:D
1810     * 1: mov.nz(8)       null:UD dest:D
1811     *
1812     * = After =
1813     * 0: add.nz(8)       dest:D  src0:D  src1:D
1814     */
1815    test_mov_prop(BRW_CONDITIONAL_NZ,
1816                  BRW_REGISTER_TYPE_D,
1817                  BRW_REGISTER_TYPE_UD,
1818                  true);
1819 }
1820 
TEST_F(cmod_propagation_test,iadd_umov_z)1821 TEST_F(cmod_propagation_test, iadd_umov_z)
1822 {
1823    /* = Before =
1824     * 0: add(8)          dest:D  src0:D  src1:D
1825     * 1: mov.z(8)        null:UD dest:D
1826     *
1827     * = After =
1828     * 0: add.z(8)        dest:D  src0:D  src1:D
1829     */
1830    test_mov_prop(BRW_CONDITIONAL_Z,
1831                  BRW_REGISTER_TYPE_D,
1832                  BRW_REGISTER_TYPE_UD,
1833                  true);
1834 }
1835 
TEST_F(cmod_propagation_test,iadd_umov_l)1836 TEST_F(cmod_propagation_test, iadd_umov_l)
1837 {
1838    /* = Before =
1839     * 0: add(8)          dest:D  src0:D  src1:D
1840     * 1: mov.l(8)        null:UD dest:D
1841     *
1842     * = After =
1843     * No changes.
1844     *
1845     * Due to the signed-to-usigned type conversion, the conditional modifier
1846     * cannot be propagated to the ADD without changing at least the
1847     * destination type of the add.
1848     *
1849     * This particular tests is a little silly.  Unsigned less than zero is a
1850     * contradiction, and earlier optimization passes should have eliminated
1851     * it.
1852     */
1853    test_mov_prop(BRW_CONDITIONAL_L,
1854                  BRW_REGISTER_TYPE_D,
1855                  BRW_REGISTER_TYPE_UD,
1856                  false);
1857 }
1858 
TEST_F(cmod_propagation_test,iadd_umov_g)1859 TEST_F(cmod_propagation_test, iadd_umov_g)
1860 {
1861    /* = Before =
1862     * 0: add(8)          dest:D  src0:D  src1:D
1863     * 1: mov.g(8)        null:UD dest:D
1864     *
1865     * = After =
1866     * No changes.
1867     *
1868     * In spite of the type conversion, this could be made to work by
1869     * propagating NZ instead of G to the ADD.
1870     */
1871    test_mov_prop(BRW_CONDITIONAL_G,
1872                  BRW_REGISTER_TYPE_D,
1873                  BRW_REGISTER_TYPE_UD,
1874                  false);
1875 }
1876 
TEST_F(cmod_propagation_test,iadd_umov_le)1877 TEST_F(cmod_propagation_test, iadd_umov_le)
1878 {
1879    /* = Before =
1880     * 0: add(8)          dest:D  src0:D  src1:D
1881     * 1: mov.le(8)       null:UD dest:D
1882     *
1883     * = After =
1884     * No changes.
1885     *
1886     * In spite of the type conversion, this could be made to work by
1887     * propagating Z instead of LE to the ADD.
1888     */
1889    test_mov_prop(BRW_CONDITIONAL_LE,
1890                  BRW_REGISTER_TYPE_D,
1891                  BRW_REGISTER_TYPE_UD,
1892                  false);
1893 }
1894 
TEST_F(cmod_propagation_test,iadd_umov_ge)1895 TEST_F(cmod_propagation_test, iadd_umov_ge)
1896 {
1897    /* = Before =
1898     * 0: add(8)          dest:D  src0:D  src1:D
1899     * 1: mov.ge(8)       null:UD dest:D
1900     *
1901     * = After =
1902     * No changes.
1903     *
1904     * Due to the signed-to-usigned type conversion, the conditional modifier
1905     * cannot be propagated to the ADD without changing at least the
1906     * destination type of the add.
1907     *
1908     * This particular tests is a little silly.  Unsigned greater than or equal
1909     * to zero is a tautology, and earlier optimization passes should have
1910     * eliminated it.
1911     */
1912    test_mov_prop(BRW_CONDITIONAL_GE,
1913                  BRW_REGISTER_TYPE_D,
1914                  BRW_REGISTER_TYPE_UD,
1915                  false);
1916 }
1917 
TEST_F(cmod_propagation_test,fadd_f2u_nz)1918 TEST_F(cmod_propagation_test, fadd_f2u_nz)
1919 {
1920    /* = Before =
1921     * 0: add(8)          dest:F  src0:F  src1:F
1922     * 1: mov.nz(8)       null:UD dest:F
1923     *
1924     * = After =
1925     * No changes.  The MOV changes the type from float to unsigned integer.
1926     * If dest is in the range [-Inf, 1), the conversion will clamp it to zero.
1927     * If dest is NaN, the conversion will also clamp it to zero.  It is not
1928     * safe to propagate the NZ back to the ADD.
1929     *
1930     * It's tempting to try to propagate G to the ADD in place of the NZ.  This
1931     * fails for values (0, 1).  For example, if dest is 0.5, add.g would set
1932     * the flag, but mov.nz would not because the 0.5 would get rounded down to
1933     * zero.
1934     */
1935    test_mov_prop(BRW_CONDITIONAL_NZ,
1936                  BRW_REGISTER_TYPE_F,
1937                  BRW_REGISTER_TYPE_UD,
1938                  false);
1939 }
1940 
TEST_F(cmod_propagation_test,fadd_f2u_z)1941 TEST_F(cmod_propagation_test, fadd_f2u_z)
1942 {
1943    /* = Before =
1944     * 0: add(8)          dest:F  src0:F  src1:F
1945     * 1: mov.z(8)        null:UD dest:F
1946     *
1947     * = After =
1948     * No changes.
1949     *
1950     * The MOV changes the type from float to unsigned integer.  If dest is in
1951     * the range [-Inf, 1), the conversion will clamp it to zero.  If dest is
1952     * NaN, the conversion will also clamp it to zero.  It is not safe to
1953     * propagate the Z back to the ADD.
1954     */
1955    test_mov_prop(BRW_CONDITIONAL_Z,
1956                  BRW_REGISTER_TYPE_F,
1957                  BRW_REGISTER_TYPE_UD,
1958                  false);
1959 }
1960 
TEST_F(cmod_propagation_test,fadd_f2u_l)1961 TEST_F(cmod_propagation_test, fadd_f2u_l)
1962 {
1963    /* = Before =
1964     * 0: add(8)          dest:F  src0:F  src1:F
1965     * 1: mov.l(8)        null:UD dest:F
1966     *
1967     * = After =
1968     * No changes.
1969     *
1970     * The MOV changes the type from float to unsigned integer.  If dest is in
1971     * the range [-Inf, 1), the conversion will clamp it to zero.  If dest is
1972     * NaN, the conversion will also clamp it to zero.  It is not safe to
1973     * propagate the L back to the ADD.
1974     */
1975    test_mov_prop(BRW_CONDITIONAL_L,
1976                  BRW_REGISTER_TYPE_F,
1977                  BRW_REGISTER_TYPE_UD,
1978                  false);
1979 }
1980 
TEST_F(cmod_propagation_test,fadd_f2u_g)1981 TEST_F(cmod_propagation_test, fadd_f2u_g)
1982 {
1983    /* = Before =
1984     * 0: add(8)          dest:F  src0:F  src1:F
1985     * 1: mov.g(8)        null:UD dest:F
1986     *
1987     * = After =
1988     * No changes.
1989     *
1990     * The MOV changes the type from float to unsigned integer.  If dest is in
1991     * the range [-Inf, 1), the conversion will clamp it to zero.  If dest is
1992     * NaN, the conversion will also clamp it to zero.  It is not safe to
1993     * propagate the G back to the ADD.
1994     */
1995    test_mov_prop(BRW_CONDITIONAL_G,
1996                  BRW_REGISTER_TYPE_F,
1997                  BRW_REGISTER_TYPE_UD,
1998                  false);
1999 }
2000 
TEST_F(cmod_propagation_test,fadd_f2u_le)2001 TEST_F(cmod_propagation_test, fadd_f2u_le)
2002 {
2003    /* = Before =
2004     * 0: add(8)          dest:F  src0:F  src1:F
2005     * 1: mov.le(8)       null:UD dest:F
2006     *
2007     * = After =
2008     * No changes.
2009     *
2010     * The MOV changes the type from float to unsigned integer.  If dest is in
2011     * the range [-Inf, 1), the conversion will clamp it to zero.  If dest is
2012     * NaN, the conversion will also clamp it to zero.  It is not safe to
2013     * propagate the LE back to the ADD.
2014     */
2015    test_mov_prop(BRW_CONDITIONAL_LE,
2016                  BRW_REGISTER_TYPE_F,
2017                  BRW_REGISTER_TYPE_UD,
2018                  false);
2019 }
2020 
TEST_F(cmod_propagation_test,fadd_f2u_ge)2021 TEST_F(cmod_propagation_test, fadd_f2u_ge)
2022 {
2023    /* = Before =
2024     * 0: add(8)          dest:F  src0:F  src1:F
2025     * 1: mov.ge(8)       null:UD dest:F
2026     *
2027     * = After =
2028     * No changes.
2029     *
2030     * The MOV changes the type from float to unsigned integer.  If dest is in
2031     * the range [-Inf, 1), the conversion will clamp it to zero.  If dest is
2032     * NaN, the conversion will also clamp it to zero.  It is not safe to
2033     * propagate the GE back to the ADD.
2034     */
2035    test_mov_prop(BRW_CONDITIONAL_GE,
2036                  BRW_REGISTER_TYPE_F,
2037                  BRW_REGISTER_TYPE_UD,
2038                  false);
2039 }
2040 
TEST_F(cmod_propagation_test,fadd_f2i_nz)2041 TEST_F(cmod_propagation_test, fadd_f2i_nz)
2042 {
2043    /* = Before =
2044     * 0: add(8)          dest:F  src0:F  src1:F
2045     * 1: mov.nz(8)       null:D  dest:F
2046     *
2047     * = After =
2048     * No changes.  The MOV changes the type from float to signed integer.  If
2049     * dest is in the range (-1, 1), the conversion will clamp it to zero.  If
2050     * dest is NaN, the conversion will also clamp it to zero.  It is not safe
2051     * to propagate the NZ back to the ADD.
2052     */
2053    test_mov_prop(BRW_CONDITIONAL_NZ,
2054                  BRW_REGISTER_TYPE_F,
2055                  BRW_REGISTER_TYPE_D,
2056                  false);
2057 }
2058 
TEST_F(cmod_propagation_test,fadd_f2i_z)2059 TEST_F(cmod_propagation_test, fadd_f2i_z)
2060 {
2061    /* = Before =
2062     * 0: add(8)          dest:F  src0:F  src1:F
2063     * 1: mov.z(8)        null:D  dest:F
2064     *
2065     * = After =
2066     * No changes.
2067     *
2068     * The MOV changes the type from float to signed integer.  If dest is in
2069     * the range (-1, 1), the conversion will clamp it to zero.  If dest is
2070     * NaN, the conversion will also clamp it to zero.  It is not safe to
2071     * propagate the Z back to the ADD.
2072     */
2073    test_mov_prop(BRW_CONDITIONAL_Z,
2074                  BRW_REGISTER_TYPE_F,
2075                  BRW_REGISTER_TYPE_D,
2076                  false);
2077 }
2078 
TEST_F(cmod_propagation_test,fadd_f2i_l)2079 TEST_F(cmod_propagation_test, fadd_f2i_l)
2080 {
2081    /* = Before =
2082     * 0: add(8)          dest:F  src0:F  src1:F
2083     * 1: mov.l(8)        null:D  dest:F
2084     *
2085     * = After =
2086     * No changes.
2087     *
2088     * The MOV changes the type from float to signed integer.  If dest is in
2089     * the range (-1, 1), the conversion will clamp it to zero.  If dest is
2090     * NaN, the conversion will also clamp it to zero.  It is not safe to
2091     * propagate the L back to the ADD.
2092     */
2093    test_mov_prop(BRW_CONDITIONAL_L,
2094                  BRW_REGISTER_TYPE_F,
2095                  BRW_REGISTER_TYPE_D,
2096                  false);
2097 }
2098 
TEST_F(cmod_propagation_test,fadd_f2i_g)2099 TEST_F(cmod_propagation_test, fadd_f2i_g)
2100 {
2101    /* = Before =
2102     * 0: add(8)          dest:F  src0:F  src1:F
2103     * 1: mov.g(8)        null:D  dest:F
2104     *
2105     * = After =
2106     * No changes.
2107     *
2108     * The MOV changes the type from float to signed integer.  If dest is in
2109     * the range (-1, 1), the conversion will clamp it to zero.  If dest is
2110     * NaN, the conversion will also clamp it to zero.  It is not safe to
2111     * propagate the G back to the ADD.
2112     */
2113    test_mov_prop(BRW_CONDITIONAL_G,
2114                  BRW_REGISTER_TYPE_F,
2115                  BRW_REGISTER_TYPE_D,
2116                  false);
2117 }
2118 
TEST_F(cmod_propagation_test,fadd_f2i_le)2119 TEST_F(cmod_propagation_test, fadd_f2i_le)
2120 {
2121    /* = Before =
2122     * 0: add(8)          dest:F  src0:F  src1:F
2123     * 1: mov.le(8)       null:D  dest:F
2124     *
2125     * = After =
2126     * No changes.
2127     *
2128     * The MOV changes the type from float to signed integer.  If dest is in
2129     * the range (-1, 1), the conversion will clamp it to zero.  If dest is
2130     * NaN, the conversion will also clamp it to zero.  It is not safe to
2131     * propagate the LE back to the ADD.
2132     */
2133    test_mov_prop(BRW_CONDITIONAL_LE,
2134                  BRW_REGISTER_TYPE_F,
2135                  BRW_REGISTER_TYPE_D,
2136                  false);
2137 }
2138 
TEST_F(cmod_propagation_test,fadd_f2i_ge)2139 TEST_F(cmod_propagation_test, fadd_f2i_ge)
2140 {
2141    /* = Before =
2142     * 0: add(8)          dest:F  src0:F  src1:F
2143     * 1: mov.ge(8)       null:D  dest:F
2144     *
2145     * = After =
2146     * No changes.
2147     *
2148     * The MOV changes the type from float to signed integer.  If dest is in
2149     * the range (-1, 1), the conversion will clamp it to zero.  If dest is
2150     * NaN, the conversion will also clamp it to zero.  It is not safe to
2151     * propagate the GE back to the ADD.
2152     */
2153    test_mov_prop(BRW_CONDITIONAL_GE,
2154                  BRW_REGISTER_TYPE_F,
2155                  BRW_REGISTER_TYPE_D,
2156                  false);
2157 }
2158 
2159 void
test_saturate_prop(enum brw_conditional_mod before,enum opcode op,enum brw_reg_type add_type,enum brw_reg_type op_type,bool expected_cmod_prop_progress)2160 cmod_propagation_test::test_saturate_prop(enum brw_conditional_mod before,
2161                                           enum opcode op,
2162                                           enum brw_reg_type add_type,
2163                                           enum brw_reg_type op_type,
2164                                           bool expected_cmod_prop_progress)
2165 {
2166    const fs_builder &bld = v->bld;
2167    fs_reg dest = bld.vgrf(add_type);
2168    fs_reg src0 = bld.vgrf(add_type);
2169    fs_reg src1 = bld.vgrf(add_type);
2170    fs_reg zero(brw_imm_ud(0));
2171 
2172    bld.ADD(dest, src0, src1)->saturate = true;
2173 
2174    assert(op == BRW_OPCODE_CMP || op == BRW_OPCODE_MOV);
2175    if (op == BRW_OPCODE_CMP) {
2176       bld.CMP(bld.vgrf(op_type, 0),
2177               retype(dest, op_type),
2178               retype(zero, op_type),
2179               before);
2180    } else {
2181       bld.MOV(bld.vgrf(op_type, 0), retype(dest, op_type))
2182          ->conditional_mod = before;
2183    }
2184 
2185    v->calculate_cfg();
2186    bblock_t *block0 = v->cfg->blocks[0];
2187 
2188    EXPECT_EQ(0, block0->start_ip);
2189    EXPECT_EQ(1, block0->end_ip);
2190 
2191    EXPECT_EQ(expected_cmod_prop_progress, cmod_propagation(v));
2192    EXPECT_EQ(0, block0->start_ip);
2193 
2194    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2195    EXPECT_EQ(add_type, instruction(block0, 0)->dst.type);
2196    EXPECT_EQ(add_type, instruction(block0, 0)->src[0].type);
2197    EXPECT_EQ(add_type, instruction(block0, 0)->src[1].type);
2198    EXPECT_TRUE(instruction(block0, 0)->saturate);
2199 
2200    if (expected_cmod_prop_progress) {
2201       EXPECT_EQ(0, block0->end_ip);
2202       EXPECT_EQ(before, instruction(block0, 0)->conditional_mod);
2203    } else {
2204       EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2205 
2206       /* This is ASSERT_EQ because if end_ip is 0, the instruction(block0, 1)
2207        * calls will not work properly, and the test will give weird results.
2208        */
2209       ASSERT_EQ(1, block0->end_ip);
2210       EXPECT_EQ(op, instruction(block0, 1)->opcode);
2211       EXPECT_EQ(op_type, instruction(block0, 1)->dst.type);
2212       EXPECT_EQ(op_type, instruction(block0, 1)->src[0].type);
2213       EXPECT_FALSE(instruction(block0, 1)->saturate);
2214       EXPECT_EQ(before, instruction(block0, 1)->conditional_mod);
2215    }
2216 }
2217 
TEST_F(cmod_propagation_test,float_saturate_nz_cmp)2218 TEST_F(cmod_propagation_test, float_saturate_nz_cmp)
2219 {
2220    /* With the saturate modifier, the comparison happens after clamping to
2221     * [0, 1].
2222     *
2223     * = Before =
2224     *
2225     * 0: add.sat(8)    dest  src0  src1
2226     * 1: cmp.nz.f0(8)  null  dest  0.0f
2227     *
2228     * = After =
2229     * 0: add.sat.nz.f0(8)  dest  src0  src1
2230     */
2231    test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_CMP,
2232                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2233                       true);
2234 }
2235 
TEST_F(cmod_propagation_test,float_saturate_nz_mov)2236 TEST_F(cmod_propagation_test, float_saturate_nz_mov)
2237 {
2238    /* With the saturate modifier, the comparison happens after clamping to
2239     * [0, 1].
2240     *
2241     * = Before =
2242     *
2243     * 0: add.sat(8)    dest  src0  src1
2244     * 1: mov.nz.f0(8)  null  dest
2245     *
2246     * = After =
2247     * 0: add.sat.nz.f0(8)  dest  src0  src1
2248     */
2249    test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_MOV,
2250                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2251                       true);
2252 }
2253 
TEST_F(cmod_propagation_test,float_saturate_z_cmp)2254 TEST_F(cmod_propagation_test, float_saturate_z_cmp)
2255 {
2256    /* With the saturate modifier, the comparison happens after clamping to
2257     * [0, 1].
2258     *
2259     * = Before =
2260     *
2261     * 0: add.sat(8)    dest  src0  src1
2262     * 1: cmp.z.f0(8)   null  dest  0.0f
2263     *
2264     * = After =
2265     * 0: add.sat.z.f0(8)  dest  src0  src1
2266     */
2267    test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_CMP,
2268                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2269                       true);
2270 }
2271 
TEST_F(cmod_propagation_test,float_saturate_z_mov)2272 TEST_F(cmod_propagation_test, float_saturate_z_mov)
2273 {
2274    /* With the saturate modifier, the comparison happens after clamping to
2275     * [0, 1].
2276     *
2277     * = Before =
2278     *
2279     * 0: add.sat(8)    dest  src0  src1
2280     * 1: mov.z.f0(8)   null  dest
2281     *
2282     * = After =
2283     * 0: add.sat.z.f0(8) dest  src0  src1
2284     */
2285    test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_MOV,
2286                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2287                       true);
2288 }
2289 
TEST_F(cmod_propagation_test,float_saturate_g_cmp)2290 TEST_F(cmod_propagation_test, float_saturate_g_cmp)
2291 {
2292    /* With the saturate modifier, the comparison happens after clamping to
2293     * [0, 1].
2294     *
2295     * = Before =
2296     *
2297     * 0: add.sat(8)    dest  src0  src1
2298     * 1: cmp.g.f0(8)   null  dest  0.0f
2299     *
2300     * = After =
2301     * 0: add.sat.g.f0(8)  dest  src0  src1
2302     */
2303    test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_CMP,
2304                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2305                       true);
2306 }
2307 
TEST_F(cmod_propagation_test,float_saturate_g_mov)2308 TEST_F(cmod_propagation_test, float_saturate_g_mov)
2309 {
2310    /* With the saturate modifier, the comparison happens after clamping to
2311     * [0, 1].
2312     *
2313     * = Before =
2314     *
2315     * 0: add.sat(8)    dest  src0  src1
2316     * 1: mov.g.f0(8)   null  dest
2317     *
2318     * = After =
2319     * 0: add.sat.g.f0(8)  dest  src0  src1
2320     */
2321    test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_MOV,
2322                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2323                       true);
2324 }
2325 
TEST_F(cmod_propagation_test,float_saturate_le_cmp)2326 TEST_F(cmod_propagation_test, float_saturate_le_cmp)
2327 {
2328    /* With the saturate modifier, the comparison happens after clamping to
2329     * [0, 1].
2330     *
2331     * = Before =
2332     *
2333     * 0: add.sat(8)    dest  src0  src1
2334     * 1: cmp.le.f0(8)  null  dest  0.0f
2335     *
2336     * = After =
2337     * 0: add.sat.le.f0(8)  dest  src0  src1
2338     */
2339    test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_CMP,
2340                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2341                       true);
2342 }
2343 
TEST_F(cmod_propagation_test,float_saturate_le_mov)2344 TEST_F(cmod_propagation_test, float_saturate_le_mov)
2345 {
2346    /* With the saturate modifier, the comparison happens after clamping to
2347     * [0, 1].  (sat(x) <= 0) == (x <= 0).
2348     *
2349     * = Before =
2350     *
2351     * 0: add.sat(8)    dest  src0  src1
2352     * 1: mov.le.f0(8)  null  dest
2353     *
2354     * = After =
2355     * 0: add.sat.le.f0(8)  dest  src0  src1
2356     */
2357    test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_MOV,
2358                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2359                       true);
2360 }
2361 
TEST_F(cmod_propagation_test,float_saturate_l_cmp)2362 TEST_F(cmod_propagation_test, float_saturate_l_cmp)
2363 {
2364    /* With the saturate modifier, the comparison happens after clamping to
2365     * [0, 1].
2366     *
2367     * = Before =
2368     *
2369     * 0: add.sat(8)    dest  src0  src1
2370     * 1: cmp.l.f0(8)  null  dest  0.0f
2371     *
2372     * = After =
2373     * 0: add.sat.l.f0(8)  dest  src0  src1
2374     */
2375    test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_CMP,
2376                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2377                       true);
2378 }
2379 
TEST_F(cmod_propagation_test,float_saturate_l_mov)2380 TEST_F(cmod_propagation_test, float_saturate_l_mov)
2381 {
2382    /* With the saturate modifier, the comparison happens after clamping to
2383     * [0, 1].
2384     *
2385     * = Before =
2386     *
2387     * 0: add.sat(8)    dest  src0  src1
2388     * 1: mov.l.f0(8)   null  dest
2389     *
2390     * = After =
2391     * 0: add.sat.l.f0(8)    dest  src0  src1
2392     */
2393    test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_MOV,
2394                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2395                       true);
2396 }
2397 
TEST_F(cmod_propagation_test,float_saturate_ge_cmp)2398 TEST_F(cmod_propagation_test, float_saturate_ge_cmp)
2399 {
2400    /* With the saturate modifier, the comparison happens after clamping to
2401     * [0, 1].
2402     *
2403     * = Before =
2404     *
2405     * 0: add.sat(8)    dest  src0  src1
2406     * 1: cmp.ge.f0(8)  null  dest  0.0f
2407     *
2408     * = After =
2409     * 0: add.sat.ge.f0(8)  dest  src0  src1
2410     */
2411    test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_CMP,
2412                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2413                       true);
2414 }
2415 
TEST_F(cmod_propagation_test,float_saturate_ge_mov)2416 TEST_F(cmod_propagation_test, float_saturate_ge_mov)
2417 {
2418    /* With the saturate modifier, the comparison happens before clamping to
2419     * [0, 1].
2420     *
2421     * = Before =
2422     *
2423     * 0: add.sat(8)    dest  src0  src1
2424     * 1: mov.ge.f0(8)  null  dest
2425     *
2426     * = After =
2427     * 0: add.sat.ge.f0(8)    dest  src0  src1
2428     */
2429    test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_MOV,
2430                       BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2431                       true);
2432 }
2433 
TEST_F(cmod_propagation_test,int_saturate_nz_cmp)2434 TEST_F(cmod_propagation_test, int_saturate_nz_cmp)
2435 {
2436    /* = Before =
2437     *
2438     * 0: add.sat(8)    dest  src0  src1
2439     * 1: cmp.nz.f0(8)  null  dest  0
2440     *
2441     * = After =
2442     * 0: add.sat.nz.f0(8)    dest  src0  src1
2443     */
2444    test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_CMP,
2445                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2446                       true);
2447 }
2448 
TEST_F(cmod_propagation_test,uint_saturate_nz_cmp)2449 TEST_F(cmod_propagation_test, uint_saturate_nz_cmp)
2450 {
2451    /* = Before =
2452     *
2453     * 0: add.sat(8)    dest:UD  src0:UD  src1:UD
2454     * 1: cmp.nz.f0(8)  null:D   dest:D   0
2455     *
2456     * = After =
2457     * 0: add.sat.nz.f0(8)    dest:UD  src0:UD  src1:UD
2458     */
2459    test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_CMP,
2460                       BRW_REGISTER_TYPE_UD, BRW_REGISTER_TYPE_D,
2461                       true);
2462 }
2463 
TEST_F(cmod_propagation_test,int_saturate_nz_mov)2464 TEST_F(cmod_propagation_test, int_saturate_nz_mov)
2465 {
2466    /* = Before =
2467     *
2468     * 0: add.sat(8)    dest  src0  src1
2469     * 1: mov.nz.f0(8)  null  dest
2470     *
2471     * = After =
2472     * 0: add.sat.nz.f0(8)    dest  src0  src1
2473     */
2474    test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_MOV,
2475                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2476                       true);
2477 }
2478 
TEST_F(cmod_propagation_test,int_saturate_z_cmp)2479 TEST_F(cmod_propagation_test, int_saturate_z_cmp)
2480 {
2481    /* = Before =
2482     *
2483     * 0: add.sat(8)    dest  src0  src1
2484     * 1: cmp.z.f0(8)   null  dest  0
2485     *
2486     * = After =
2487     * 0: add.sat.z.f0(8)    dest  src0  src1
2488     */
2489    test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_CMP,
2490                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2491                       true);
2492 }
2493 
TEST_F(cmod_propagation_test,uint_saturate_z_cmp)2494 TEST_F(cmod_propagation_test, uint_saturate_z_cmp)
2495 {
2496    /* = Before =
2497     *
2498     * 0: add.sat(8)   dest:UD  src0:UD  src1:UD
2499     * 1: cmp.z.f0(8)  null:D   dest:D   0
2500     *
2501     * = After =
2502     * 0: add.sat.z.f0(8)    dest:UD  src0:UD  src1:UD
2503     */
2504    test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_CMP,
2505                       BRW_REGISTER_TYPE_UD, BRW_REGISTER_TYPE_D,
2506                       true);
2507 }
2508 
TEST_F(cmod_propagation_test,int_saturate_z_mov)2509 TEST_F(cmod_propagation_test, int_saturate_z_mov)
2510 {
2511    /* With the saturate modifier, the comparison happens before clamping to
2512     * [0, 1].  (sat(x) == 0) == (x <= 0).
2513     *
2514     * = Before =
2515     *
2516     * 0: add.sat(8)    dest  src0  src1
2517     * 1: mov.z.f0(8)   null  dest
2518     *
2519     * = After =
2520     * 0: add.sat.z.f0(8)    dest  src0  src1
2521     */
2522    test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_MOV,
2523                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2524                       true);
2525 }
2526 
TEST_F(cmod_propagation_test,int_saturate_g_cmp)2527 TEST_F(cmod_propagation_test, int_saturate_g_cmp)
2528 {
2529    /* = Before =
2530     *
2531     * 0: add.sat(8)    dest  src0  src1
2532     * 1: cmp.g.f0(8)   null  dest  0
2533     *
2534     * = After =
2535     * 0: add.sat.g.f0(8)    dest  src0  src1
2536     */
2537    test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_CMP,
2538                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2539                       true);
2540 }
2541 
TEST_F(cmod_propagation_test,int_saturate_g_mov)2542 TEST_F(cmod_propagation_test, int_saturate_g_mov)
2543 {
2544    /* = Before =
2545     *
2546     * 0: add.sat(8)    dest  src0  src1
2547     * 1: mov.g.f0(8)   null  dest
2548     *
2549     * = After =
2550     * 0: add.sat.g.f0(8)    dest  src0  src1
2551     */
2552    test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_MOV,
2553                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2554                       true);
2555 }
2556 
TEST_F(cmod_propagation_test,int_saturate_le_cmp)2557 TEST_F(cmod_propagation_test, int_saturate_le_cmp)
2558 {
2559    /* = Before =
2560     *
2561     * 0: add.sat(8)    dest  src0  src1
2562     * 1: cmp.le.f0(8)  null  dest  0
2563     *
2564     * = After =
2565     * 0: add.sat.le.f0(8)    dest  src0  src1
2566     */
2567    test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_CMP,
2568                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2569                       true);
2570 }
2571 
TEST_F(cmod_propagation_test,int_saturate_le_mov)2572 TEST_F(cmod_propagation_test, int_saturate_le_mov)
2573 {
2574    /* = Before =
2575     *
2576     * 0: add.sat(8)    dest  src0  src1
2577     * 1: mov.le.f0(8)  null  dest
2578     *
2579     * = After =
2580     * 0: add.sat.le.f0(8)    dest  src0  src1
2581     */
2582    test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_MOV,
2583                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2584                       true);
2585 }
2586 
TEST_F(cmod_propagation_test,int_saturate_l_cmp)2587 TEST_F(cmod_propagation_test, int_saturate_l_cmp)
2588 {
2589    /* = Before =
2590     *
2591     * 0: add.sat(8)    dest  src0  src1
2592     * 1: cmp.l.f0(8)  null  dest  0
2593     *
2594     * = After =
2595     * 0: add.sat.l.f0(8)    dest  src0  src1
2596     */
2597    test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_CMP,
2598                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2599                       true);
2600 }
2601 
TEST_F(cmod_propagation_test,int_saturate_l_mov)2602 TEST_F(cmod_propagation_test, int_saturate_l_mov)
2603 {
2604    /* = Before =
2605     *
2606     * 0: add.sat(8)    dest  src0  src1
2607     * 1: mov.l.f0(8)  null  dest  0
2608     *
2609     * = After =
2610     * 0: add.sat.l.f0(8)    dest  src0  src1
2611     */
2612    test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_MOV,
2613                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2614                       true);
2615 }
2616 
TEST_F(cmod_propagation_test,int_saturate_ge_cmp)2617 TEST_F(cmod_propagation_test, int_saturate_ge_cmp)
2618 {
2619    /* = Before =
2620     *
2621     * 0: add.sat(8)    dest  src0  src1
2622     * 1: cmp.ge.f0(8)  null  dest  0
2623     *
2624     * = After =
2625     * 0: add.sat.ge.f0(8)    dest  src0  src1
2626     */
2627    test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_CMP,
2628                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2629                       true);
2630 }
2631 
TEST_F(cmod_propagation_test,int_saturate_ge_mov)2632 TEST_F(cmod_propagation_test, int_saturate_ge_mov)
2633 {
2634    /* = Before =
2635     *
2636     * 0: add.sat(8)    dest  src0  src1
2637     * 1: mov.ge.f0(8)  null  dest
2638     *
2639     * = After =
2640     * 0: add.sat.ge.f0(8)    dest  src0  src1
2641     */
2642    test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_MOV,
2643                       BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2644                       true);
2645 }
2646 
TEST_F(cmod_propagation_test,not_to_or)2647 TEST_F(cmod_propagation_test, not_to_or)
2648 {
2649    /* Exercise propagation of conditional modifier from a NOT instruction to
2650     * another ALU instruction as performed by cmod_propagate_not.
2651     */
2652    const fs_builder &bld = v->bld;
2653    fs_reg dest = v->vgrf(glsl_type::uint_type);
2654    fs_reg src0 = v->vgrf(glsl_type::uint_type);
2655    fs_reg src1 = v->vgrf(glsl_type::uint_type);
2656    bld.OR(dest, src0, src1);
2657    set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
2658 
2659    /* = Before =
2660     *
2661     * 0: or(8)         dest  src0  src1
2662     * 1: not.nz.f0(8)  null  dest
2663     *
2664     * = After =
2665     * 0: or.z.f0(8)    dest  src0  src1
2666     */
2667 
2668    v->calculate_cfg();
2669    bblock_t *block0 = v->cfg->blocks[0];
2670 
2671    EXPECT_EQ(0, block0->start_ip);
2672    EXPECT_EQ(1, block0->end_ip);
2673 
2674    EXPECT_TRUE(cmod_propagation(v));
2675    EXPECT_EQ(0, block0->start_ip);
2676    EXPECT_EQ(0, block0->end_ip);
2677    EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2678    EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2679 }
2680 
TEST_F(cmod_propagation_test,not_to_and)2681 TEST_F(cmod_propagation_test, not_to_and)
2682 {
2683    /* Exercise propagation of conditional modifier from a NOT instruction to
2684     * another ALU instruction as performed by cmod_propagate_not.
2685     */
2686    const fs_builder &bld = v->bld;
2687    fs_reg dest = v->vgrf(glsl_type::uint_type);
2688    fs_reg src0 = v->vgrf(glsl_type::uint_type);
2689    fs_reg src1 = v->vgrf(glsl_type::uint_type);
2690    bld.AND(dest, src0, src1);
2691    set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
2692 
2693    /* = Before =
2694     *
2695     * 0: and(8)        dest  src0  src1
2696     * 1: not.nz.f0(8)  null  dest
2697     *
2698     * = After =
2699     * 0: and.z.f0(8)   dest  src0  src1
2700     */
2701 
2702    v->calculate_cfg();
2703    bblock_t *block0 = v->cfg->blocks[0];
2704 
2705    EXPECT_EQ(0, block0->start_ip);
2706    EXPECT_EQ(1, block0->end_ip);
2707 
2708    EXPECT_TRUE(cmod_propagation(v));
2709    EXPECT_EQ(0, block0->start_ip);
2710    EXPECT_EQ(0, block0->end_ip);
2711    EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 0)->opcode);
2712    EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2713 }
2714 
TEST_F(cmod_propagation_test,not_to_uadd)2715 TEST_F(cmod_propagation_test, not_to_uadd)
2716 {
2717    /* Exercise propagation of conditional modifier from a NOT instruction to
2718     * another ALU instruction as performed by cmod_propagate_not.
2719     *
2720     * The optimization pass currently restricts to just OR and AND.  It's
2721     * possible that this is too restrictive, and the actual, necessary
2722     * restriction is just the the destination type of the ALU instruction is
2723     * the same as the source type of the NOT instruction.
2724     */
2725    const fs_builder &bld = v->bld;
2726    fs_reg dest = v->vgrf(glsl_type::uint_type);
2727    fs_reg src0 = v->vgrf(glsl_type::uint_type);
2728    fs_reg src1 = v->vgrf(glsl_type::uint_type);
2729    bld.ADD(dest, src0, src1);
2730    set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
2731 
2732    /* = Before =
2733     *
2734     * 0: add(8)        dest  src0  src1
2735     * 1: not.nz.f0(8)  null  dest
2736     *
2737     * = After =
2738     * No changes
2739     */
2740 
2741    v->calculate_cfg();
2742    bblock_t *block0 = v->cfg->blocks[0];
2743 
2744    EXPECT_EQ(0, block0->start_ip);
2745    EXPECT_EQ(1, block0->end_ip);
2746 
2747    EXPECT_FALSE(cmod_propagation(v));
2748    EXPECT_EQ(0, block0->start_ip);
2749    EXPECT_EQ(1, block0->end_ip);
2750    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2751    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2752    EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 1)->opcode);
2753    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
2754 }
2755 
TEST_F(cmod_propagation_test,not_to_fadd_to_ud)2756 TEST_F(cmod_propagation_test, not_to_fadd_to_ud)
2757 {
2758    /* Exercise propagation of conditional modifier from a NOT instruction to
2759     * another ALU instruction as performed by cmod_propagate_not.
2760     *
2761     * The optimization pass currently restricts to just OR and AND.  It's
2762     * possible that this is too restrictive, and the actual, necessary
2763     * restriction is just the the destination type of the ALU instruction is
2764     * the same as the source type of the NOT instruction.
2765     */
2766    const fs_builder &bld = v->bld;
2767    fs_reg dest = v->vgrf(glsl_type::uint_type);
2768    fs_reg src0 = v->vgrf(glsl_type::float_type);
2769    fs_reg src1 = v->vgrf(glsl_type::float_type);
2770    bld.ADD(dest, src0, src1);
2771    set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
2772 
2773    /* = Before =
2774     *
2775     * 0: add(8)        dest.ud src0.f  src1.f
2776     * 1: not.nz.f0(8)  null    dest.ud
2777     *
2778     * = After =
2779     * No changes
2780     */
2781 
2782    v->calculate_cfg();
2783    bblock_t *block0 = v->cfg->blocks[0];
2784 
2785    EXPECT_EQ(0, block0->start_ip);
2786    EXPECT_EQ(1, block0->end_ip);
2787 
2788    EXPECT_FALSE(cmod_propagation(v));
2789    EXPECT_EQ(0, block0->start_ip);
2790    EXPECT_EQ(1, block0->end_ip);
2791    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2792    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2793    EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 1)->opcode);
2794    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
2795 }
2796 
TEST_F(cmod_propagation_test,not_to_fadd)2797 TEST_F(cmod_propagation_test, not_to_fadd)
2798 {
2799    /* Exercise propagation of conditional modifier from a NOT instruction to
2800     * another ALU instruction as performed by cmod_propagate_not.
2801     *
2802     * The optimization pass currently restricts to just OR and AND.  It's
2803     * possible that this is too restrictive, and the actual, necessary
2804     * restriction is just the the destination type of the ALU instruction is
2805     * the same as the source type of the NOT instruction.
2806     */
2807    const fs_builder &bld = v->bld;
2808    fs_reg dest = v->vgrf(glsl_type::float_type);
2809    fs_reg src0 = v->vgrf(glsl_type::float_type);
2810    fs_reg src1 = v->vgrf(glsl_type::float_type);
2811    bld.ADD(dest, src0, src1);
2812    set_condmod(BRW_CONDITIONAL_NZ,
2813                bld.NOT(bld.null_reg_ud(),
2814                        retype(dest, BRW_REGISTER_TYPE_UD)));
2815 
2816    /* = Before =
2817     *
2818     * 0: add(8)        dest.f  src0.f  src1.f
2819     * 1: not.nz.f0(8)  null    dest.ud
2820     *
2821     * = After =
2822     * No changes
2823     */
2824 
2825    v->calculate_cfg();
2826    bblock_t *block0 = v->cfg->blocks[0];
2827 
2828    EXPECT_EQ(0, block0->start_ip);
2829    EXPECT_EQ(1, block0->end_ip);
2830 
2831    EXPECT_FALSE(cmod_propagation(v));
2832    EXPECT_EQ(0, block0->start_ip);
2833    EXPECT_EQ(1, block0->end_ip);
2834    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2835    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2836    EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 1)->opcode);
2837    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
2838 }
2839 
TEST_F(cmod_propagation_test,not_to_or_intervening_flag_read_compatible_value)2840 TEST_F(cmod_propagation_test, not_to_or_intervening_flag_read_compatible_value)
2841 {
2842    /* Exercise propagation of conditional modifier from a NOT instruction to
2843     * another ALU instruction as performed by cmod_propagate_not.
2844     */
2845    const fs_builder &bld = v->bld;
2846    fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2847    fs_reg dest1 = v->vgrf(glsl_type::float_type);
2848    fs_reg src0 = v->vgrf(glsl_type::uint_type);
2849    fs_reg src1 = v->vgrf(glsl_type::uint_type);
2850    fs_reg src2 = v->vgrf(glsl_type::float_type);
2851    fs_reg zero(brw_imm_f(0.0f));
2852    set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest0, src0, src1));
2853    set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
2854    set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2855 
2856    /* = Before =
2857     *
2858     * 0: or.z.f0(8)    dest0 src0  src1
2859     * 1: (+f0) sel(8)  dest1 src2  0.0f
2860     * 2: not.nz.f0(8)  null  dest0
2861     *
2862     * = After =
2863     * 0: or.z.f0(8)    dest0 src0  src1
2864     * 1: (+f0) sel(8)  dest1 src2  0.0f
2865     */
2866 
2867    v->calculate_cfg();
2868    bblock_t *block0 = v->cfg->blocks[0];
2869 
2870    EXPECT_EQ(0, block0->start_ip);
2871    EXPECT_EQ(2, block0->end_ip);
2872 
2873    EXPECT_TRUE(cmod_propagation(v));
2874    EXPECT_EQ(0, block0->start_ip);
2875    EXPECT_EQ(1, block0->end_ip);
2876    EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2877    EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2878    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
2879    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
2880 }
2881 
TEST_F(cmod_propagation_test,not_to_or_intervening_flag_read_compatible_value_mismatch_flag)2882 TEST_F(cmod_propagation_test,
2883        not_to_or_intervening_flag_read_compatible_value_mismatch_flag)
2884 {
2885    /* Exercise propagation of conditional modifier from a NOT instruction to
2886     * another ALU instruction as performed by cmod_propagate_not.
2887     */
2888    const fs_builder &bld = v->bld;
2889    fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2890    fs_reg dest1 = v->vgrf(glsl_type::float_type);
2891    fs_reg src0 = v->vgrf(glsl_type::uint_type);
2892    fs_reg src1 = v->vgrf(glsl_type::uint_type);
2893    fs_reg src2 = v->vgrf(glsl_type::float_type);
2894    fs_reg zero(brw_imm_f(0.0f));
2895    set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest0, src0, src1))
2896       ->flag_subreg = 1;
2897    set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
2898    set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2899 
2900    /* = Before =
2901     *
2902     * 0: or.z.f0.1(8)  dest0 src0  src1
2903     * 1: (+f0) sel(8)  dest1 src2  0.0f
2904     * 2: not.nz.f0(8)  null  dest0
2905     *
2906     * = After =
2907     * No changes
2908     */
2909 
2910    v->calculate_cfg();
2911    bblock_t *block0 = v->cfg->blocks[0];
2912 
2913    EXPECT_EQ(0, block0->start_ip);
2914    EXPECT_EQ(2, block0->end_ip);
2915 
2916    EXPECT_FALSE(cmod_propagation(v));
2917    EXPECT_EQ(0, block0->start_ip);
2918    EXPECT_EQ(2, block0->end_ip);
2919    EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2920    EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2921    EXPECT_EQ(1, instruction(block0, 0)->flag_subreg);
2922    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
2923    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
2924    EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 2)->opcode);
2925    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 2)->conditional_mod);
2926    EXPECT_EQ(0, instruction(block0, 2)->flag_subreg);
2927 }
2928 
TEST_F(cmod_propagation_test,not_to_or_intervening_flag_read_incompatible_value)2929 TEST_F(cmod_propagation_test, not_to_or_intervening_flag_read_incompatible_value)
2930 {
2931    /* Exercise propagation of conditional modifier from a NOT instruction to
2932     * another ALU instruction as performed by cmod_propagate_not.
2933     */
2934    const fs_builder &bld = v->bld;
2935    fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2936    fs_reg dest1 = v->vgrf(glsl_type::float_type);
2937    fs_reg src0 = v->vgrf(glsl_type::uint_type);
2938    fs_reg src1 = v->vgrf(glsl_type::uint_type);
2939    fs_reg src2 = v->vgrf(glsl_type::float_type);
2940    fs_reg zero(brw_imm_f(0.0f));
2941    set_condmod(BRW_CONDITIONAL_NZ, bld.OR(dest0, src0, src1));
2942    set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
2943    set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2944 
2945    /* = Before =
2946     *
2947     * 0: or.nz.f0(8)   dest0 src0  src1
2948     * 1: (+f0) sel(8)  dest1 src2  0.0f
2949     * 2: not.nz.f0(8)  null  dest0
2950     *
2951     * = After =
2952     * No changes
2953     */
2954 
2955    v->calculate_cfg();
2956    bblock_t *block0 = v->cfg->blocks[0];
2957 
2958    EXPECT_EQ(0, block0->start_ip);
2959    EXPECT_EQ(2, block0->end_ip);
2960 
2961    EXPECT_FALSE(cmod_propagation(v));
2962    EXPECT_EQ(0, block0->start_ip);
2963    EXPECT_EQ(2, block0->end_ip);
2964    EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2965    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
2966    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
2967    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
2968    EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 2)->opcode);
2969    EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 2)->conditional_mod);
2970 }
2971 
TEST_F(cmod_propagation_test,not_to_or_intervening_mismatch_flag_write)2972 TEST_F(cmod_propagation_test, not_to_or_intervening_mismatch_flag_write)
2973 {
2974    /* Exercise propagation of conditional modifier from a NOT instruction to
2975     * another ALU instruction as performed by cmod_propagate_not.
2976     */
2977    const fs_builder &bld = v->bld;
2978    fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2979    fs_reg dest1 = v->vgrf(glsl_type::uint_type);
2980    fs_reg src0 = v->vgrf(glsl_type::uint_type);
2981    fs_reg src1 = v->vgrf(glsl_type::uint_type);
2982 
2983    bld.OR(dest0, src0, src1);
2984    set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest1, src0, src1))
2985       ->flag_subreg = 1;
2986    set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2987 
2988    /* = Before =
2989     *
2990     * 0: or(8)          dest0 src0  src1
2991     * 1: or.z.f0.1(8)   dest1 src0  src1
2992     * 2: not.nz.f0(8)   null  dest0
2993     *
2994     * = After =
2995     * 0: or.z.f0(8)     dest0 src0  src1
2996     * 1: or.z.f0.1(8)   dest1 src0  src1
2997     */
2998 
2999    v->calculate_cfg();
3000    bblock_t *block0 = v->cfg->blocks[0];
3001 
3002    EXPECT_EQ(0, block0->start_ip);
3003    EXPECT_EQ(2, block0->end_ip);
3004 
3005    EXPECT_TRUE(cmod_propagation(v));
3006    EXPECT_EQ(0, block0->start_ip);
3007    EXPECT_EQ(1, block0->end_ip);
3008    EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
3009    EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
3010    EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
3011    EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 1)->opcode);
3012    EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 1)->conditional_mod);
3013    EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
3014 }
3015 
TEST_F(cmod_propagation_test,not_to_or_intervening_mismatch_flag_read)3016 TEST_F(cmod_propagation_test, not_to_or_intervening_mismatch_flag_read)
3017 {
3018    /* Exercise propagation of conditional modifier from a NOT instruction to
3019     * another ALU instruction as performed by cmod_propagate_not.
3020     */
3021    const fs_builder &bld = v->bld;
3022    fs_reg dest0 = v->vgrf(glsl_type::uint_type);
3023    fs_reg dest1 = v->vgrf(glsl_type::float_type);
3024    fs_reg src0 = v->vgrf(glsl_type::uint_type);
3025    fs_reg src1 = v->vgrf(glsl_type::uint_type);
3026    fs_reg src2 = v->vgrf(glsl_type::float_type);
3027    fs_reg zero(brw_imm_f(0.0f));
3028 
3029    bld.OR(dest0, src0, src1);
3030    set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
3031       ->flag_subreg = 1;
3032    set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
3033 
3034    /* = Before =
3035     *
3036     * 0: or(8)          dest0 src0  src1
3037     * 1: (+f0.1) sel(8) dest1 src2  0.0f
3038     * 2: not.nz.f0(8)   null  dest0
3039     *
3040     * = After =
3041     * 0: or.z.f0(8)     dest0 src0  src1
3042     * 1: (+f0.1) sel(8) dest1 src2  0.0f
3043     */
3044 
3045    v->calculate_cfg();
3046    bblock_t *block0 = v->cfg->blocks[0];
3047 
3048    EXPECT_EQ(0, block0->start_ip);
3049    EXPECT_EQ(2, block0->end_ip);
3050 
3051    EXPECT_TRUE(cmod_propagation(v));
3052    EXPECT_EQ(0, block0->start_ip);
3053    EXPECT_EQ(1, block0->end_ip);
3054    EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
3055    EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
3056    EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
3057    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
3058    EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
3059    EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
3060 }
3061 
TEST_F(cmod_propagation_test,cmp_to_add_float_e)3062 TEST_F(cmod_propagation_test, cmp_to_add_float_e)
3063 {
3064    const fs_builder &bld = v->bld;
3065    fs_reg dest = v->vgrf(glsl_type::float_type);
3066    fs_reg src0 = v->vgrf(glsl_type::float_type);
3067    fs_reg neg10(brw_imm_f(-10.0f));
3068    fs_reg pos10(brw_imm_f(10.0f));
3069 
3070    bld.ADD(dest, src0, neg10)->saturate = true;
3071    bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_EQ);
3072 
3073    /* = Before =
3074     * 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
3075     * 1: cmp.z.f0.0(8) null:F, vgrf1:F, 10f
3076     *
3077     * = After =
3078     * (no changes)
3079     */
3080 
3081    v->calculate_cfg();
3082    bblock_t *block0 = v->cfg->blocks[0];
3083 
3084    EXPECT_FALSE(cmod_propagation(v));
3085    EXPECT_EQ(0, block0->start_ip);
3086    EXPECT_EQ(1, block0->end_ip);
3087    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
3088    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
3089    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
3090    EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
3091 }
3092 
TEST_F(cmod_propagation_test,cmp_to_add_float_g)3093 TEST_F(cmod_propagation_test, cmp_to_add_float_g)
3094 {
3095    const fs_builder &bld = v->bld;
3096    fs_reg dest = v->vgrf(glsl_type::float_type);
3097    fs_reg src0 = v->vgrf(glsl_type::float_type);
3098    fs_reg neg10(brw_imm_f(-10.0f));
3099    fs_reg pos10(brw_imm_f(10.0f));
3100 
3101    bld.ADD(dest, src0, neg10)->saturate = true;
3102    bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_G);
3103 
3104    /* = Before =
3105     * 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
3106     * 1: cmp.g.f0.0(8) null:F, vgrf1:F, 10f
3107     *
3108     * = After =
3109     * 0: add.sat.g.f0.0(8) vgrf0:F, vgrf1:F, -10f
3110     */
3111 
3112    v->calculate_cfg();
3113    bblock_t *block0 = v->cfg->blocks[0];
3114 
3115    EXPECT_TRUE(cmod_propagation(v));
3116    EXPECT_EQ(0, block0->start_ip);
3117    EXPECT_EQ(0, block0->end_ip);
3118    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
3119    EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod);
3120 }
3121 
TEST_F(cmod_propagation_test,cmp_to_add_float_le)3122 TEST_F(cmod_propagation_test, cmp_to_add_float_le)
3123 {
3124    const fs_builder &bld = v->bld;
3125    fs_reg dest = v->vgrf(glsl_type::float_type);
3126    fs_reg src0 = v->vgrf(glsl_type::float_type);
3127    fs_reg neg10(brw_imm_f(-10.0f));
3128    fs_reg pos10(brw_imm_f(10.0f));
3129 
3130    bld.ADD(dest, src0, neg10)->saturate = true;
3131    bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_LE);
3132 
3133    /* = Before =
3134     * 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
3135     * 1: cmp.le.f0.0(8) null:F, vgrf1:F, 10f
3136     *
3137     * = After =
3138     * 0: add.sat.le.f0.0(8) vgrf0:F, vgrf1:F, -10f
3139     */
3140 
3141    v->calculate_cfg();
3142    bblock_t *block0 = v->cfg->blocks[0];
3143 
3144    EXPECT_TRUE(cmod_propagation(v));
3145    EXPECT_EQ(0, block0->start_ip);
3146    EXPECT_EQ(0, block0->end_ip);
3147    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
3148    EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
3149 }
3150 
TEST_F(cmod_propagation_test,prop_across_sel_gfx7)3151 TEST_F(cmod_propagation_test, prop_across_sel_gfx7)
3152 {
3153    const fs_builder &bld = v->bld;
3154    fs_reg dest1 = v->vgrf(glsl_type::float_type);
3155    fs_reg dest2 = v->vgrf(glsl_type::float_type);
3156    fs_reg src0 = v->vgrf(glsl_type::float_type);
3157    fs_reg src1 = v->vgrf(glsl_type::float_type);
3158    fs_reg src2 = v->vgrf(glsl_type::float_type);
3159    fs_reg src3 = v->vgrf(glsl_type::float_type);
3160    fs_reg zero(brw_imm_f(0.0f));
3161    bld.ADD(dest1, src0, src1);
3162    bld.emit_minmax(dest2, src2, src3, BRW_CONDITIONAL_GE);
3163    bld.CMP(bld.null_reg_f(), dest1, zero, BRW_CONDITIONAL_GE);
3164 
3165    /* = Before =
3166     *
3167     * 0: add(8)        dest1 src0  src1
3168     * 1: sel.ge(8)     dest2 src2  src3
3169     * 2: cmp.ge.f0(8)  null  dest1 0.0f
3170     *
3171     * = After =
3172     * 0: add.ge.f0(8)  dest1 src0  src1
3173     * 1: sel.ge(8)     dest2 src2  src3
3174     */
3175 
3176    v->calculate_cfg();
3177    bblock_t *block0 = v->cfg->blocks[0];
3178 
3179    EXPECT_EQ(0, block0->start_ip);
3180    EXPECT_EQ(2, block0->end_ip);
3181 
3182    EXPECT_TRUE(cmod_propagation(v));
3183    EXPECT_EQ(0, block0->start_ip);
3184    EXPECT_EQ(1, block0->end_ip);
3185    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
3186    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
3187    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
3188    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
3189 }
3190 
TEST_F(cmod_propagation_test,prop_across_sel_gfx5)3191 TEST_F(cmod_propagation_test, prop_across_sel_gfx5)
3192 {
3193    devinfo->ver = 5;
3194    devinfo->verx10 = devinfo->ver * 10;
3195 
3196    const fs_builder &bld = v->bld;
3197    fs_reg dest1 = v->vgrf(glsl_type::float_type);
3198    fs_reg dest2 = v->vgrf(glsl_type::float_type);
3199    fs_reg src0 = v->vgrf(glsl_type::float_type);
3200    fs_reg src1 = v->vgrf(glsl_type::float_type);
3201    fs_reg src2 = v->vgrf(glsl_type::float_type);
3202    fs_reg src3 = v->vgrf(glsl_type::float_type);
3203    fs_reg zero(brw_imm_f(0.0f));
3204    bld.ADD(dest1, src0, src1);
3205    bld.emit_minmax(dest2, src2, src3, BRW_CONDITIONAL_GE);
3206    bld.CMP(bld.null_reg_f(), dest1, zero, BRW_CONDITIONAL_GE);
3207 
3208    /* = Before =
3209     *
3210     * 0: add(8)        dest1 src0  src1
3211     * 1: sel.ge(8)     dest2 src2  src3
3212     * 2: cmp.ge.f0(8)  null  dest1 0.0f
3213     *
3214     * = After =
3215     * (no changes)
3216     *
3217     * On Gfx4 and Gfx5, sel.l (for min) and sel.ge (for max) are implemented
3218     * using a separate cmpn and sel instruction.  This lowering occurs in
3219     * fs_vistor::lower_minmax which is called a long time after the first
3220     * calls to cmod_propagation.
3221     */
3222 
3223    v->calculate_cfg();
3224    bblock_t *block0 = v->cfg->blocks[0];
3225 
3226    EXPECT_EQ(0, block0->start_ip);
3227    EXPECT_EQ(2, block0->end_ip);
3228 
3229    EXPECT_FALSE(cmod_propagation(v));
3230    EXPECT_EQ(0, block0->start_ip);
3231    EXPECT_EQ(2, block0->end_ip);
3232    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
3233    EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
3234    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
3235    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
3236    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
3237    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
3238 }
3239 
TEST_F(cmod_propagation_test,prop_into_sel_gfx5)3240 TEST_F(cmod_propagation_test, prop_into_sel_gfx5)
3241 {
3242    devinfo->ver = 5;
3243    devinfo->verx10 = devinfo->ver * 10;
3244 
3245    const fs_builder &bld = v->bld;
3246    fs_reg dest = v->vgrf(glsl_type::float_type);
3247    fs_reg src0 = v->vgrf(glsl_type::float_type);
3248    fs_reg src1 = v->vgrf(glsl_type::float_type);
3249    fs_reg zero(brw_imm_f(0.0f));
3250    bld.emit_minmax(dest, src0, src1, BRW_CONDITIONAL_GE);
3251    bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
3252 
3253    /* = Before =
3254     *
3255     * 0: sel.ge(8)     dest  src0  src1
3256     * 1: cmp.ge.f0(8)  null  dest  0.0f
3257     *
3258     * = After =
3259     * (no changes)
3260     *
3261     * Do not copy propagate into a sel.cond instruction.  While it does modify
3262     * the flags, the flags are not based on the result compared with zero (as
3263     * with most other instructions).  The result is based on the sources
3264     * compared with each other (like cmp.cond).
3265     */
3266 
3267    v->calculate_cfg();
3268    bblock_t *block0 = v->cfg->blocks[0];
3269 
3270    EXPECT_EQ(0, block0->start_ip);
3271    EXPECT_EQ(1, block0->end_ip);
3272 
3273    EXPECT_FALSE(cmod_propagation(v));
3274    EXPECT_EQ(0, block0->start_ip);
3275    EXPECT_EQ(1, block0->end_ip);
3276    EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 0)->opcode);
3277    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
3278    EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
3279    EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
3280 }
3281