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
34public:
35   struct brw_compiler *compiler;
36   struct gen_device_info *devinfo;
37   struct gl_context *ctx;
38   struct brw_wm_prog_data *prog_data;
39   struct gl_shader_program *shader_prog;
40   fs_visitor *v;
41};
42
43class cmod_propagation_fs_visitor : public fs_visitor
44{
45public:
46   cmod_propagation_fs_visitor(struct brw_compiler *compiler,
47                               struct brw_wm_prog_data *prog_data,
48                               nir_shader *shader)
49      : fs_visitor(compiler, NULL, NULL, NULL,
50                   &prog_data->base, (struct gl_program *) NULL,
51                   shader, 8, -1) {}
52};
53
54
55void cmod_propagation_test::SetUp()
56{
57   ctx = (struct gl_context *)calloc(1, sizeof(*ctx));
58   compiler = (struct brw_compiler *)calloc(1, sizeof(*compiler));
59   devinfo = (struct gen_device_info *)calloc(1, sizeof(*devinfo));
60   compiler->devinfo = devinfo;
61
62   prog_data = ralloc(NULL, struct brw_wm_prog_data);
63   nir_shader *shader =
64      nir_shader_create(NULL, MESA_SHADER_FRAGMENT, NULL, NULL);
65
66   v = new cmod_propagation_fs_visitor(compiler, prog_data, shader);
67
68   devinfo->gen = 7;
69}
70
71static fs_inst *
72instruction(bblock_t *block, int num)
73{
74   fs_inst *inst = (fs_inst *)block->start();
75   for (int i = 0; i < num; i++) {
76      inst = (fs_inst *)inst->next;
77   }
78   return inst;
79}
80
81static bool
82cmod_propagation(fs_visitor *v)
83{
84   const bool print = getenv("TEST_DEBUG");
85
86   if (print) {
87      fprintf(stderr, "= Before =\n");
88      v->cfg->dump(v);
89   }
90
91   bool ret = v->opt_cmod_propagation();
92
93   if (print) {
94      fprintf(stderr, "\n= After =\n");
95      v->cfg->dump(v);
96   }
97
98   return ret;
99}
100
101TEST_F(cmod_propagation_test, basic)
102{
103   const fs_builder &bld = v->bld;
104   fs_reg dest = v->vgrf(glsl_type::float_type);
105   fs_reg src0 = v->vgrf(glsl_type::float_type);
106   fs_reg src1 = v->vgrf(glsl_type::float_type);
107   fs_reg zero(brw_imm_f(0.0f));
108   bld.ADD(dest, src0, src1);
109   bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
110
111   /* = Before =
112    *
113    * 0: add(8)        dest  src0  src1
114    * 1: cmp.ge.f0(8)  null  dest  0.0f
115    *
116    * = After =
117    * 0: add.ge.f0(8)  dest  src0  src1
118    */
119
120   v->calculate_cfg();
121   bblock_t *block0 = v->cfg->blocks[0];
122
123   EXPECT_EQ(0, block0->start_ip);
124   EXPECT_EQ(1, block0->end_ip);
125
126   EXPECT_TRUE(cmod_propagation(v));
127   EXPECT_EQ(0, block0->start_ip);
128   EXPECT_EQ(0, block0->end_ip);
129   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
130   EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
131}
132
133TEST_F(cmod_propagation_test, cmp_nonzero)
134{
135   const fs_builder &bld = v->bld;
136   fs_reg dest = v->vgrf(glsl_type::float_type);
137   fs_reg src0 = v->vgrf(glsl_type::float_type);
138   fs_reg src1 = v->vgrf(glsl_type::float_type);
139   fs_reg nonzero(brw_imm_f(1.0f));
140   bld.ADD(dest, src0, src1);
141   bld.CMP(bld.null_reg_f(), dest, nonzero, BRW_CONDITIONAL_GE);
142
143   /* = Before =
144    *
145    * 0: add(8)        dest  src0  src1
146    * 1: cmp.ge.f0(8)  null  dest  1.0f
147    *
148    * = After =
149    * (no changes)
150    */
151
152   v->calculate_cfg();
153   bblock_t *block0 = v->cfg->blocks[0];
154
155   EXPECT_EQ(0, block0->start_ip);
156   EXPECT_EQ(1, block0->end_ip);
157
158   EXPECT_FALSE(cmod_propagation(v));
159   EXPECT_EQ(0, block0->start_ip);
160   EXPECT_EQ(1, block0->end_ip);
161   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
162   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
163   EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
164}
165
166TEST_F(cmod_propagation_test, non_cmod_instruction)
167{
168   const fs_builder &bld = v->bld;
169   fs_reg dest = v->vgrf(glsl_type::uint_type);
170   fs_reg src0 = v->vgrf(glsl_type::uint_type);
171   fs_reg zero(brw_imm_ud(0u));
172   bld.FBL(dest, src0);
173   bld.CMP(bld.null_reg_ud(), dest, zero, BRW_CONDITIONAL_GE);
174
175   /* = Before =
176    *
177    * 0: fbl(8)        dest  src0
178    * 1: cmp.ge.f0(8)  null  dest  0u
179    *
180    * = After =
181    * (no changes)
182    */
183
184   v->calculate_cfg();
185   bblock_t *block0 = v->cfg->blocks[0];
186
187   EXPECT_EQ(0, block0->start_ip);
188   EXPECT_EQ(1, block0->end_ip);
189
190   EXPECT_FALSE(cmod_propagation(v));
191   EXPECT_EQ(0, block0->start_ip);
192   EXPECT_EQ(1, block0->end_ip);
193   EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode);
194   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
195   EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
196}
197
198TEST_F(cmod_propagation_test, intervening_flag_write)
199{
200   const fs_builder &bld = v->bld;
201   fs_reg dest = v->vgrf(glsl_type::float_type);
202   fs_reg src0 = v->vgrf(glsl_type::float_type);
203   fs_reg src1 = v->vgrf(glsl_type::float_type);
204   fs_reg src2 = v->vgrf(glsl_type::float_type);
205   fs_reg zero(brw_imm_f(0.0f));
206   bld.ADD(dest, src0, src1);
207   bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE);
208   bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
209
210   /* = Before =
211    *
212    * 0: add(8)        dest  src0  src1
213    * 1: cmp.ge.f0(8)  null  src2  0.0f
214    * 2: cmp.ge.f0(8)  null  dest  0.0f
215    *
216    * = After =
217    * (no changes)
218    */
219
220   v->calculate_cfg();
221   bblock_t *block0 = v->cfg->blocks[0];
222
223   EXPECT_EQ(0, block0->start_ip);
224   EXPECT_EQ(2, block0->end_ip);
225
226   EXPECT_FALSE(cmod_propagation(v));
227   EXPECT_EQ(0, block0->start_ip);
228   EXPECT_EQ(2, block0->end_ip);
229   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
230   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
231   EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
232   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
233   EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
234}
235
236TEST_F(cmod_propagation_test, intervening_flag_read)
237{
238   const fs_builder &bld = v->bld;
239   fs_reg dest0 = v->vgrf(glsl_type::float_type);
240   fs_reg dest1 = v->vgrf(glsl_type::float_type);
241   fs_reg src0 = v->vgrf(glsl_type::float_type);
242   fs_reg src1 = v->vgrf(glsl_type::float_type);
243   fs_reg src2 = v->vgrf(glsl_type::float_type);
244   fs_reg zero(brw_imm_f(0.0f));
245   bld.ADD(dest0, src0, src1);
246   set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
247   bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
248
249   /* = Before =
250    *
251    * 0: add(8)        dest0 src0  src1
252    * 1: (+f0) sel(8)  dest1 src2  0.0f
253    * 2: cmp.ge.f0(8)  null  dest0 0.0f
254    *
255    * = After =
256    * (no changes)
257    */
258
259   v->calculate_cfg();
260   bblock_t *block0 = v->cfg->blocks[0];
261
262   EXPECT_EQ(0, block0->start_ip);
263   EXPECT_EQ(2, block0->end_ip);
264
265   EXPECT_FALSE(cmod_propagation(v));
266   EXPECT_EQ(0, block0->start_ip);
267   EXPECT_EQ(2, block0->end_ip);
268   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
269   EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
270   EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
271   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
272   EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
273}
274
275TEST_F(cmod_propagation_test, intervening_dest_write)
276{
277   const fs_builder &bld = v->bld;
278   fs_reg dest = v->vgrf(glsl_type::vec4_type);
279   fs_reg src0 = v->vgrf(glsl_type::float_type);
280   fs_reg src1 = v->vgrf(glsl_type::float_type);
281   fs_reg src2 = v->vgrf(glsl_type::vec2_type);
282   fs_reg zero(brw_imm_f(0.0f));
283   bld.ADD(offset(dest, bld, 2), src0, src1);
284   bld.emit(SHADER_OPCODE_TEX, dest, src2)
285      ->size_written = 4 * REG_SIZE;
286   bld.CMP(bld.null_reg_f(), offset(dest, bld, 2), zero, BRW_CONDITIONAL_GE);
287
288   /* = Before =
289    *
290    * 0: add(8)        dest+2  src0    src1
291    * 1: tex(8) rlen 4 dest+0  src2
292    * 2: cmp.ge.f0(8)  null    dest+2  0.0f
293    *
294    * = After =
295    * (no changes)
296    */
297
298   v->calculate_cfg();
299   bblock_t *block0 = v->cfg->blocks[0];
300
301   EXPECT_EQ(0, block0->start_ip);
302   EXPECT_EQ(2, block0->end_ip);
303
304   EXPECT_FALSE(cmod_propagation(v));
305   EXPECT_EQ(0, block0->start_ip);
306   EXPECT_EQ(2, block0->end_ip);
307   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
308   EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
309   EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
310   EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
311   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
312   EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
313}
314
315TEST_F(cmod_propagation_test, intervening_flag_read_same_value)
316{
317   const fs_builder &bld = v->bld;
318   fs_reg dest0 = v->vgrf(glsl_type::float_type);
319   fs_reg dest1 = v->vgrf(glsl_type::float_type);
320   fs_reg src0 = v->vgrf(glsl_type::float_type);
321   fs_reg src1 = v->vgrf(glsl_type::float_type);
322   fs_reg src2 = v->vgrf(glsl_type::float_type);
323   fs_reg zero(brw_imm_f(0.0f));
324   set_condmod(BRW_CONDITIONAL_GE, bld.ADD(dest0, src0, src1));
325   set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
326   bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
327
328   /* = Before =
329    *
330    * 0: add.ge.f0(8)  dest0 src0  src1
331    * 1: (+f0) sel(8)  dest1 src2  0.0f
332    * 2: cmp.ge.f0(8)  null  dest0 0.0f
333    *
334    * = After =
335    * 0: add.ge.f0(8)  dest0 src0  src1
336    * 1: (+f0) sel(8)  dest1 src2  0.0f
337    */
338
339   v->calculate_cfg();
340   bblock_t *block0 = v->cfg->blocks[0];
341
342   EXPECT_EQ(0, block0->start_ip);
343   EXPECT_EQ(2, block0->end_ip);
344
345   EXPECT_TRUE(cmod_propagation(v));
346   EXPECT_EQ(0, block0->start_ip);
347   EXPECT_EQ(1, block0->end_ip);
348   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
349   EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
350   EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
351   EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
352}
353
354TEST_F(cmod_propagation_test, negate)
355{
356   const fs_builder &bld = v->bld;
357   fs_reg dest = v->vgrf(glsl_type::float_type);
358   fs_reg src0 = v->vgrf(glsl_type::float_type);
359   fs_reg src1 = v->vgrf(glsl_type::float_type);
360   fs_reg zero(brw_imm_f(0.0f));
361   bld.ADD(dest, src0, src1);
362   dest.negate = true;
363   bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
364
365   /* = Before =
366    *
367    * 0: add(8)        dest  src0  src1
368    * 1: cmp.ge.f0(8)  null  -dest 0.0f
369    *
370    * = After =
371    * 0: add.le.f0(8)  dest  src0  src1
372    */
373
374   v->calculate_cfg();
375   bblock_t *block0 = v->cfg->blocks[0];
376
377   EXPECT_EQ(0, block0->start_ip);
378   EXPECT_EQ(1, block0->end_ip);
379
380   EXPECT_TRUE(cmod_propagation(v));
381   EXPECT_EQ(0, block0->start_ip);
382   EXPECT_EQ(0, block0->end_ip);
383   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
384   EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
385}
386
387TEST_F(cmod_propagation_test, movnz)
388{
389   const fs_builder &bld = v->bld;
390   fs_reg dest = v->vgrf(glsl_type::float_type);
391   fs_reg src0 = v->vgrf(glsl_type::float_type);
392   fs_reg src1 = v->vgrf(glsl_type::float_type);
393   bld.CMP(dest, src0, src1, BRW_CONDITIONAL_GE);
394   set_condmod(BRW_CONDITIONAL_NZ,
395               bld.MOV(bld.null_reg_f(), dest));
396
397   /* = Before =
398    *
399    * 0: cmp.ge.f0(8)  dest  src0  src1
400    * 1: mov.nz.f0(8)  null  dest
401    *
402    * = After =
403    * 0: cmp.ge.f0(8)  dest  src0  src1
404    */
405
406   v->calculate_cfg();
407   bblock_t *block0 = v->cfg->blocks[0];
408
409   EXPECT_EQ(0, block0->start_ip);
410   EXPECT_EQ(1, block0->end_ip);
411
412   EXPECT_TRUE(cmod_propagation(v));
413   EXPECT_EQ(0, block0->start_ip);
414   EXPECT_EQ(0, block0->end_ip);
415   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
416   EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
417}
418
419TEST_F(cmod_propagation_test, different_types_cmod_with_zero)
420{
421   const fs_builder &bld = v->bld;
422   fs_reg dest = v->vgrf(glsl_type::int_type);
423   fs_reg src0 = v->vgrf(glsl_type::int_type);
424   fs_reg src1 = v->vgrf(glsl_type::int_type);
425   fs_reg zero(brw_imm_f(0.0f));
426   bld.ADD(dest, src0, src1);
427   bld.CMP(bld.null_reg_f(), retype(dest, BRW_REGISTER_TYPE_F), zero,
428           BRW_CONDITIONAL_GE);
429
430   /* = Before =
431    *
432    * 0: add(8)        dest:D  src0:D  src1:D
433    * 1: cmp.ge.f0(8)  null:F  dest:F  0.0f
434    *
435    * = After =
436    * (no changes)
437    */
438
439   v->calculate_cfg();
440   bblock_t *block0 = v->cfg->blocks[0];
441
442   EXPECT_EQ(0, block0->start_ip);
443   EXPECT_EQ(1, block0->end_ip);
444
445   EXPECT_FALSE(cmod_propagation(v));
446   EXPECT_EQ(0, block0->start_ip);
447   EXPECT_EQ(1, block0->end_ip);
448   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
449   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
450   EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
451}
452
453TEST_F(cmod_propagation_test, andnz_one)
454{
455   const fs_builder &bld = v->bld;
456   fs_reg dest = v->vgrf(glsl_type::int_type);
457   fs_reg src0 = v->vgrf(glsl_type::float_type);
458   fs_reg zero(brw_imm_f(0.0f));
459   fs_reg one(brw_imm_d(1));
460
461   bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
462   set_condmod(BRW_CONDITIONAL_NZ,
463               bld.AND(bld.null_reg_d(), dest, one));
464
465   /* = Before =
466    * 0: cmp.l.f0(8)     dest:F  src0:F  0F
467    * 1: and.nz.f0(8)    null:D  dest:D  1D
468    *
469    * = After =
470    * 0: cmp.l.f0(8)     dest:F  src0:F  0F
471    */
472
473   v->calculate_cfg();
474   bblock_t *block0 = v->cfg->blocks[0];
475
476   EXPECT_EQ(0, block0->start_ip);
477   EXPECT_EQ(1, block0->end_ip);
478
479   EXPECT_TRUE(cmod_propagation(v));
480   EXPECT_EQ(0, block0->start_ip);
481   EXPECT_EQ(0, block0->end_ip);
482   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
483   EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
484   EXPECT_TRUE(retype(dest, BRW_REGISTER_TYPE_F)
485               .equals(instruction(block0, 0)->dst));
486}
487
488TEST_F(cmod_propagation_test, andnz_non_one)
489{
490   const fs_builder &bld = v->bld;
491   fs_reg dest = v->vgrf(glsl_type::int_type);
492   fs_reg src0 = v->vgrf(glsl_type::float_type);
493   fs_reg zero(brw_imm_f(0.0f));
494   fs_reg nonone(brw_imm_d(38));
495
496   bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
497   set_condmod(BRW_CONDITIONAL_NZ,
498               bld.AND(bld.null_reg_d(), dest, nonone));
499
500   /* = Before =
501    * 0: cmp.l.f0(8)     dest:F  src0:F  0F
502    * 1: and.nz.f0(8)    null:D  dest:D  38D
503    *
504    * = After =
505    * (no changes)
506    */
507
508   v->calculate_cfg();
509   bblock_t *block0 = v->cfg->blocks[0];
510
511   EXPECT_EQ(0, block0->start_ip);
512   EXPECT_EQ(1, block0->end_ip);
513
514   EXPECT_FALSE(cmod_propagation(v));
515   EXPECT_EQ(0, block0->start_ip);
516   EXPECT_EQ(1, block0->end_ip);
517   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
518   EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
519   EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
520   EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
521}
522
523TEST_F(cmod_propagation_test, andz_one)
524{
525   const fs_builder &bld = v->bld;
526   fs_reg dest = v->vgrf(glsl_type::int_type);
527   fs_reg src0 = v->vgrf(glsl_type::float_type);
528   fs_reg zero(brw_imm_f(0.0f));
529   fs_reg one(brw_imm_d(1));
530
531   bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
532   set_condmod(BRW_CONDITIONAL_Z,
533               bld.AND(bld.null_reg_d(), dest, one));
534
535   /* = Before =
536    * 0: cmp.l.f0(8)     dest:F  src0:F  0F
537    * 1: and.z.f0(8)     null:D  dest:D  1D
538    *
539    * = After =
540    * (no changes)
541    */
542
543   v->calculate_cfg();
544   bblock_t *block0 = v->cfg->blocks[0];
545
546   EXPECT_EQ(0, block0->start_ip);
547   EXPECT_EQ(1, block0->end_ip);
548
549   EXPECT_FALSE(cmod_propagation(v));
550   EXPECT_EQ(0, block0->start_ip);
551   EXPECT_EQ(1, block0->end_ip);
552   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
553   EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
554   EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
555   EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
556}
557
558TEST_F(cmod_propagation_test, add_not_merge_with_compare)
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.ADD(dest, src0, src1);
565   bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
566
567   /* The addition and the implicit subtraction in the compare do not compute
568    * related values.
569    *
570    * = Before =
571    * 0: add(8)          dest:F  src0:F  src1:F
572    * 1: cmp.l.f0(8)     null:F  src0:F  src1:F
573    *
574    * = After =
575    * (no changes)
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_FALSE(cmod_propagation(v));
584   EXPECT_EQ(0, block0->start_ip);
585   EXPECT_EQ(1, block0->end_ip);
586   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
587   EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
588   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
589   EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
590}
591
592TEST_F(cmod_propagation_test, subtract_merge_with_compare)
593{
594   const fs_builder &bld = v->bld;
595   fs_reg dest = v->vgrf(glsl_type::float_type);
596   fs_reg src0 = v->vgrf(glsl_type::float_type);
597   fs_reg src1 = v->vgrf(glsl_type::float_type);
598   bld.ADD(dest, src0, negate(src1));
599   bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
600
601   /* = Before =
602    * 0: add(8)          dest:F  src0:F  -src1:F
603    * 1: cmp.l.f0(8)     null:F  src0:F  src1:F
604    *
605    * = After =
606    * 0: add.l.f0(8)     dest:F  src0:F  -src1:F
607    */
608   v->calculate_cfg();
609   bblock_t *block0 = v->cfg->blocks[0];
610
611   EXPECT_EQ(0, block0->start_ip);
612   EXPECT_EQ(1, block0->end_ip);
613
614   EXPECT_TRUE(cmod_propagation(v));
615   EXPECT_EQ(0, block0->start_ip);
616   EXPECT_EQ(0, block0->end_ip);
617   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
618   EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
619}
620
621TEST_F(cmod_propagation_test, subtract_immediate_merge_with_compare)
622{
623   const fs_builder &bld = v->bld;
624   fs_reg dest = v->vgrf(glsl_type::float_type);
625   fs_reg src0 = v->vgrf(glsl_type::float_type);
626   fs_reg one(brw_imm_f(1.0f));
627   fs_reg negative_one(brw_imm_f(-1.0f));
628
629   bld.ADD(dest, src0, negative_one);
630   bld.CMP(bld.null_reg_f(), src0, one, BRW_CONDITIONAL_NZ);
631
632   /* = Before =
633    * 0: add(8)          dest:F  src0:F  -1.0f
634    * 1: cmp.nz.f0(8)    null:F  src0:F  1.0f
635    *
636    * = After =
637    * 0: add.nz.f0(8)    dest:F  src0:F  -1.0f
638    */
639   v->calculate_cfg();
640   bblock_t *block0 = v->cfg->blocks[0];
641
642   EXPECT_EQ(0, block0->start_ip);
643   EXPECT_EQ(1, block0->end_ip);
644
645   EXPECT_TRUE(cmod_propagation(v));
646   EXPECT_EQ(0, block0->start_ip);
647   EXPECT_EQ(0, block0->end_ip);
648   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
649   EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
650}
651
652TEST_F(cmod_propagation_test, subtract_merge_with_compare_intervening_add)
653{
654   const fs_builder &bld = v->bld;
655   fs_reg dest0 = v->vgrf(glsl_type::float_type);
656   fs_reg dest1 = v->vgrf(glsl_type::float_type);
657   fs_reg src0 = v->vgrf(glsl_type::float_type);
658   fs_reg src1 = v->vgrf(glsl_type::float_type);
659   bld.ADD(dest0, src0, negate(src1));
660   bld.ADD(dest1, src0, src1);
661   bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
662
663   /* = Before =
664    * 0: add(8)          dest0:F src0:F  -src1:F
665    * 1: add(8)          dest1:F src0:F  src1:F
666    * 2: cmp.l.f0(8)     null:F  src0:F  src1:F
667    *
668    * = After =
669    * 0: add.l.f0(8)     dest0:F src0:F  -src1:F
670    * 1: add(8)          dest1:F src0:F  src1:F
671    */
672   v->calculate_cfg();
673   bblock_t *block0 = v->cfg->blocks[0];
674
675   EXPECT_EQ(0, block0->start_ip);
676   EXPECT_EQ(2, block0->end_ip);
677
678   EXPECT_TRUE(cmod_propagation(v));
679   EXPECT_EQ(0, block0->start_ip);
680   EXPECT_EQ(1, block0->end_ip);
681   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
682   EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
683   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
684   EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
685}
686
687TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_partial_write)
688{
689   const fs_builder &bld = v->bld;
690   fs_reg dest0 = v->vgrf(glsl_type::float_type);
691   fs_reg dest1 = v->vgrf(glsl_type::float_type);
692   fs_reg src0 = v->vgrf(glsl_type::float_type);
693   fs_reg src1 = v->vgrf(glsl_type::float_type);
694   bld.ADD(dest0, src0, negate(src1));
695   set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, src0, negate(src1)));
696   bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
697
698   /* = Before =
699    * 0: add(8)          dest0:F src0:F  -src1:F
700    * 1: (+f0) add(8)    dest1:F src0:F  -src1:F
701    * 2: cmp.l.f0(8)     null:F  src0:F  src1:F
702    *
703    * = After =
704    * (no changes)
705    */
706   v->calculate_cfg();
707   bblock_t *block0 = v->cfg->blocks[0];
708
709   EXPECT_EQ(0, block0->start_ip);
710   EXPECT_EQ(2, block0->end_ip);
711
712   EXPECT_FALSE(cmod_propagation(v));
713   EXPECT_EQ(0, block0->start_ip);
714   EXPECT_EQ(2, block0->end_ip);
715   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
716   EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
717   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
718   EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
719   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
720   EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
721}
722
723TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_add)
724{
725   const fs_builder &bld = v->bld;
726   fs_reg dest0 = v->vgrf(glsl_type::float_type);
727   fs_reg dest1 = v->vgrf(glsl_type::float_type);
728   fs_reg src0 = v->vgrf(glsl_type::float_type);
729   fs_reg src1 = v->vgrf(glsl_type::float_type);
730   bld.ADD(dest0, src0, negate(src1));
731   set_condmod(BRW_CONDITIONAL_EQ, bld.ADD(dest1, src0, src1));
732   bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
733
734   /* = Before =
735    * 0: add(8)          dest0:F src0:F  -src1:F
736    * 1: add.z.f0(8)     dest1:F src0:F  src1:F
737    * 2: cmp.l.f0(8)     null:F  src0:F  src1:F
738    *
739    * = After =
740    * (no changes)
741    */
742   v->calculate_cfg();
743   bblock_t *block0 = v->cfg->blocks[0];
744
745   EXPECT_EQ(0, block0->start_ip);
746   EXPECT_EQ(2, block0->end_ip);
747
748   EXPECT_FALSE(cmod_propagation(v));
749   EXPECT_EQ(0, block0->start_ip);
750   EXPECT_EQ(2, block0->end_ip);
751   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
752   EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
753   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
754   EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
755   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
756   EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
757}
758
759TEST_F(cmod_propagation_test, add_merge_with_compare)
760{
761   const fs_builder &bld = v->bld;
762   fs_reg dest = v->vgrf(glsl_type::float_type);
763   fs_reg src0 = v->vgrf(glsl_type::float_type);
764   fs_reg src1 = v->vgrf(glsl_type::float_type);
765   bld.ADD(dest, src0, src1);
766   bld.CMP(bld.null_reg_f(), src0, negate(src1), BRW_CONDITIONAL_L);
767
768   /* = Before =
769    * 0: add(8)          dest:F  src0:F  src1:F
770    * 1: cmp.l.f0(8)     null:F  src0:F  -src1:F
771    *
772    * = After =
773    * 0: add.l.f0(8)     dest:F  src0:F  src1:F
774    */
775   v->calculate_cfg();
776   bblock_t *block0 = v->cfg->blocks[0];
777
778   EXPECT_EQ(0, block0->start_ip);
779   EXPECT_EQ(1, block0->end_ip);
780
781   EXPECT_TRUE(cmod_propagation(v));
782   EXPECT_EQ(0, block0->start_ip);
783   EXPECT_EQ(0, block0->end_ip);
784   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
785   EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
786}
787
788TEST_F(cmod_propagation_test, negative_subtract_merge_with_compare)
789{
790   const fs_builder &bld = v->bld;
791   fs_reg dest = v->vgrf(glsl_type::float_type);
792   fs_reg src0 = v->vgrf(glsl_type::float_type);
793   fs_reg src1 = v->vgrf(glsl_type::float_type);
794   bld.ADD(dest, src1, negate(src0));
795   bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
796
797   /* The result of the subtract is the negatiion of the result of the
798    * implicit subtract in the compare, so the condition must change.
799    *
800    * = Before =
801    * 0: add(8)          dest:F  src1:F  -src0:F
802    * 1: cmp.l.f0(8)     null:F  src0:F  src1:F
803    *
804    * = After =
805    * 0: add.g.f0(8)     dest:F  src0:F  -src1:F
806    */
807   v->calculate_cfg();
808   bblock_t *block0 = v->cfg->blocks[0];
809
810   EXPECT_EQ(0, block0->start_ip);
811   EXPECT_EQ(1, block0->end_ip);
812
813   EXPECT_TRUE(cmod_propagation(v));
814   EXPECT_EQ(0, block0->start_ip);
815   EXPECT_EQ(0, block0->end_ip);
816   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
817   EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod);
818}
819
820TEST_F(cmod_propagation_test, subtract_delete_compare)
821{
822   const fs_builder &bld = v->bld;
823   fs_reg dest = v->vgrf(glsl_type::float_type);
824   fs_reg dest1 = v->vgrf(glsl_type::float_type);
825   fs_reg src0 = v->vgrf(glsl_type::float_type);
826   fs_reg src1 = v->vgrf(glsl_type::float_type);
827   fs_reg src2 = v->vgrf(glsl_type::float_type);
828
829   set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)));
830   set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2));
831   bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
832
833   /* = Before =
834    * 0: add.l.f0(8)     dest0:F src0:F  -src1:F
835    * 1: (+f0) mov(0)    dest1:F src2:F
836    * 2: cmp.l.f0(8)     null:F  src0:F  src1:F
837    *
838    * = After =
839    * 0: add.l.f0(8)     dest:F  src0:F  -src1:F
840    * 1: (+f0) mov(0)    dest1:F src2:F
841    */
842   v->calculate_cfg();
843   bblock_t *block0 = v->cfg->blocks[0];
844
845   EXPECT_EQ(0, block0->start_ip);
846   EXPECT_EQ(2, block0->end_ip);
847
848   EXPECT_TRUE(cmod_propagation(v));
849   EXPECT_EQ(0, block0->start_ip);
850   EXPECT_EQ(1, block0->end_ip);
851   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
852   EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
853   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
854   EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
855}
856
857TEST_F(cmod_propagation_test, subtract_delete_compare_derp)
858{
859   const fs_builder &bld = v->bld;
860   fs_reg dest0 = v->vgrf(glsl_type::float_type);
861   fs_reg dest1 = v->vgrf(glsl_type::float_type);
862   fs_reg src0 = v->vgrf(glsl_type::float_type);
863   fs_reg src1 = v->vgrf(glsl_type::float_type);
864
865   set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest0, src0, negate(src1)));
866   set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, negate(src0), src1));
867   bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
868
869   /* = Before =
870    * 0: add.l.f0(8)     dest0:F src0:F  -src1:F
871    * 1: (+f0) add(0)    dest1:F -src0:F src1:F
872    * 2: cmp.l.f0(8)     null:F  src0:F  src1:F
873    *
874    * = After =
875    * 0: add.l.f0(8)     dest0:F src0:F  -src1:F
876    * 1: (+f0) add(0)    dest1:F -src0:F src1:F
877    */
878   v->calculate_cfg();
879   bblock_t *block0 = v->cfg->blocks[0];
880
881   EXPECT_EQ(0, block0->start_ip);
882   EXPECT_EQ(2, block0->end_ip);
883
884   EXPECT_TRUE(cmod_propagation(v));
885   EXPECT_EQ(0, block0->start_ip);
886   EXPECT_EQ(1, block0->end_ip);
887   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
888   EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
889   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
890   EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
891}
892
893TEST_F(cmod_propagation_test, signed_unsigned_comparison_mismatch)
894{
895   const fs_builder &bld = v->bld;
896   fs_reg dest0 = v->vgrf(glsl_type::int_type);
897   fs_reg src0 = v->vgrf(glsl_type::int_type);
898   src0.type = BRW_REGISTER_TYPE_W;
899
900   bld.ASR(dest0, negate(src0), brw_imm_d(15));
901   bld.CMP(bld.null_reg_ud(), retype(dest0, BRW_REGISTER_TYPE_UD),
902           brw_imm_ud(0u), BRW_CONDITIONAL_LE);
903
904   /* = Before =
905    * 0: asr(8)          dest:D   -src0:W 15D
906    * 1: cmp.le.f0(8)    null:UD  dest:UD 0UD
907    *
908    * = After =
909    * (no changes)
910    */
911   v->calculate_cfg();
912   bblock_t *block0 = v->cfg->blocks[0];
913
914   EXPECT_EQ(0, block0->start_ip);
915   EXPECT_EQ(1, block0->end_ip);
916
917   EXPECT_FALSE(cmod_propagation(v));
918   EXPECT_EQ(0, block0->start_ip);
919   EXPECT_EQ(1, block0->end_ip);
920   EXPECT_EQ(BRW_OPCODE_ASR, instruction(block0, 0)->opcode);
921   EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
922   EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 1)->conditional_mod);
923}
924