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