OSDN Git Service

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