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