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