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