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