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