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 saturate_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 saturate_propagation_fs_visitor : public fs_visitor
44{
45public:
46   saturate_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 saturate_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 saturate_propagation_fs_visitor(compiler, prog_data, shader);
67
68   devinfo->gen = 4;
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
82saturate_propagation(fs_visitor *v)
83{
84   const bool print = false;
85
86   if (print) {
87      fprintf(stderr, "= Before =\n");
88      v->cfg->dump(v);
89   }
90
91   bool ret = v->opt_saturate_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(saturate_propagation_test, basic)
102{
103   const fs_builder &bld = v->bld;
104   fs_reg dst0 = v->vgrf(glsl_type::float_type);
105   fs_reg dst1 = v->vgrf(glsl_type::float_type);
106   fs_reg src0 = v->vgrf(glsl_type::float_type);
107   fs_reg src1 = v->vgrf(glsl_type::float_type);
108   bld.ADD(dst0, src0, src1);
109   set_saturate(true, bld.MOV(dst1, dst0));
110
111   /* = Before =
112    *
113    * 0: add(8)        dst0  src0  src1
114    * 1: mov.sat(8)    dst1  dst0
115    *
116    * = After =
117    * 0: add.sat(8)    dst0  src0  src1
118    * 1: mov(8)        dst1  dst0
119    */
120
121   v->calculate_cfg();
122   bblock_t *block0 = v->cfg->blocks[0];
123
124   EXPECT_EQ(0, block0->start_ip);
125   EXPECT_EQ(1, block0->end_ip);
126
127   EXPECT_TRUE(saturate_propagation(v));
128   EXPECT_EQ(0, block0->start_ip);
129   EXPECT_EQ(1, block0->end_ip);
130   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
131   EXPECT_TRUE(instruction(block0, 0)->saturate);
132   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
133   EXPECT_FALSE(instruction(block0, 1)->saturate);
134}
135
136TEST_F(saturate_propagation_test, other_non_saturated_use)
137{
138   const fs_builder &bld = v->bld;
139   fs_reg dst0 = v->vgrf(glsl_type::float_type);
140   fs_reg dst1 = v->vgrf(glsl_type::float_type);
141   fs_reg dst2 = v->vgrf(glsl_type::float_type);
142   fs_reg src0 = v->vgrf(glsl_type::float_type);
143   fs_reg src1 = v->vgrf(glsl_type::float_type);
144   bld.ADD(dst0, src0, src1);
145   set_saturate(true, bld.MOV(dst1, dst0));
146   bld.ADD(dst2, dst0, src0);
147
148   /* = Before =
149    *
150    * 0: add(8)        dst0  src0  src1
151    * 1: mov.sat(8)    dst1  dst0
152    * 2: add(8)        dst2  dst0  src0
153    *
154    * = After =
155    * (no changes)
156    */
157
158   v->calculate_cfg();
159   bblock_t *block0 = v->cfg->blocks[0];
160
161   EXPECT_EQ(0, block0->start_ip);
162   EXPECT_EQ(2, block0->end_ip);
163
164   EXPECT_FALSE(saturate_propagation(v));
165   EXPECT_EQ(0, block0->start_ip);
166   EXPECT_EQ(2, block0->end_ip);
167   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
168   EXPECT_FALSE(instruction(block0, 0)->saturate);
169   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
170   EXPECT_TRUE(instruction(block0, 1)->saturate);
171   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 2)->opcode);
172}
173
174TEST_F(saturate_propagation_test, predicated_instruction)
175{
176   const fs_builder &bld = v->bld;
177   fs_reg dst0 = v->vgrf(glsl_type::float_type);
178   fs_reg dst1 = v->vgrf(glsl_type::float_type);
179   fs_reg src0 = v->vgrf(glsl_type::float_type);
180   fs_reg src1 = v->vgrf(glsl_type::float_type);
181   bld.ADD(dst0, src0, src1)
182      ->predicate = BRW_PREDICATE_NORMAL;
183   set_saturate(true, bld.MOV(dst1, dst0));
184
185   /* = Before =
186    *
187    * 0: (+f0) add(8)  dst0  src0  src1
188    * 1: mov.sat(8)    dst1  dst0
189    *
190    * = After =
191    * (no changes)
192    */
193
194   v->calculate_cfg();
195   bblock_t *block0 = v->cfg->blocks[0];
196
197   EXPECT_EQ(0, block0->start_ip);
198   EXPECT_EQ(1, block0->end_ip);
199
200   EXPECT_FALSE(saturate_propagation(v));
201   EXPECT_EQ(0, block0->start_ip);
202   EXPECT_EQ(1, block0->end_ip);
203   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
204   EXPECT_FALSE(instruction(block0, 0)->saturate);
205   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
206   EXPECT_TRUE(instruction(block0, 1)->saturate);
207}
208
209TEST_F(saturate_propagation_test, neg_mov_sat)
210{
211   const fs_builder &bld = v->bld;
212   fs_reg dst0 = v->vgrf(glsl_type::float_type);
213   fs_reg dst1 = v->vgrf(glsl_type::float_type);
214   fs_reg src0 = v->vgrf(glsl_type::float_type);
215   bld.RNDU(dst0, src0);
216   dst0.negate = true;
217   set_saturate(true, bld.MOV(dst1, dst0));
218
219   /* = Before =
220    *
221    * 0: rndu(8)       dst0  src0
222    * 1: mov.sat(8)    dst1  -dst0
223    *
224    * = After =
225    * (no changes)
226    */
227
228   v->calculate_cfg();
229   bblock_t *block0 = v->cfg->blocks[0];
230
231   EXPECT_EQ(0, block0->start_ip);
232   EXPECT_EQ(1, block0->end_ip);
233
234   EXPECT_FALSE(saturate_propagation(v));
235   EXPECT_EQ(0, block0->start_ip);
236   EXPECT_EQ(1, block0->end_ip);
237   EXPECT_EQ(BRW_OPCODE_RNDU, instruction(block0, 0)->opcode);
238   EXPECT_FALSE(instruction(block0, 0)->saturate);
239   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
240   EXPECT_TRUE(instruction(block0, 1)->saturate);
241}
242
243TEST_F(saturate_propagation_test, add_neg_mov_sat)
244{
245   const fs_builder &bld = v->bld;
246   fs_reg dst0 = v->vgrf(glsl_type::float_type);
247   fs_reg dst1 = v->vgrf(glsl_type::float_type);
248   fs_reg src0 = v->vgrf(glsl_type::float_type);
249   fs_reg src1 = v->vgrf(glsl_type::float_type);
250   bld.ADD(dst0, src0, src1);
251   dst0.negate = true;
252   set_saturate(true, bld.MOV(dst1, dst0));
253
254   /* = Before =
255    *
256    * 0: add(8)        dst0  src0  src1
257    * 1: mov.sat(8)    dst1  -dst0
258    *
259    * = After =
260    * 0: add.sat(8)    dst0  -src0 -src1
261    * 1: mov(8)        dst1  dst0
262    */
263
264   v->calculate_cfg();
265   bblock_t *block0 = v->cfg->blocks[0];
266
267   EXPECT_EQ(0, block0->start_ip);
268   EXPECT_EQ(1, block0->end_ip);
269
270   EXPECT_TRUE(saturate_propagation(v));
271   EXPECT_EQ(0, block0->start_ip);
272   EXPECT_EQ(1, block0->end_ip);
273   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
274   EXPECT_TRUE(instruction(block0, 0)->saturate);
275   EXPECT_TRUE(instruction(block0, 0)->src[0].negate);
276   EXPECT_TRUE(instruction(block0, 0)->src[1].negate);
277   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
278   EXPECT_FALSE(instruction(block0, 1)->saturate);
279}
280
281TEST_F(saturate_propagation_test, mul_neg_mov_sat)
282{
283   const fs_builder &bld = v->bld;
284   fs_reg dst0 = v->vgrf(glsl_type::float_type);
285   fs_reg dst1 = v->vgrf(glsl_type::float_type);
286   fs_reg src0 = v->vgrf(glsl_type::float_type);
287   fs_reg src1 = v->vgrf(glsl_type::float_type);
288   bld.MUL(dst0, src0, src1);
289   dst0.negate = true;
290   set_saturate(true, bld.MOV(dst1, dst0));
291
292   /* = Before =
293    *
294    * 0: mul(8)        dst0  src0  src1
295    * 1: mov.sat(8)    dst1  -dst0
296    *
297    * = After =
298    * 0: mul.sat(8)    dst0  src0 -src1
299    * 1: mov(8)        dst1  dst0
300    */
301
302   v->calculate_cfg();
303   bblock_t *block0 = v->cfg->blocks[0];
304
305   EXPECT_EQ(0, block0->start_ip);
306   EXPECT_EQ(1, block0->end_ip);
307
308   EXPECT_TRUE(saturate_propagation(v));
309   EXPECT_EQ(0, block0->start_ip);
310   EXPECT_EQ(1, block0->end_ip);
311   EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
312   EXPECT_TRUE(instruction(block0, 0)->saturate);
313   EXPECT_TRUE(instruction(block0, 0)->src[0].negate);
314   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
315   EXPECT_FALSE(instruction(block0, 1)->saturate);
316   EXPECT_FALSE(instruction(block0, 1)->src[0].negate);
317}
318
319TEST_F(saturate_propagation_test, mul_mov_sat_neg_mov_sat)
320{
321   const fs_builder &bld = v->bld;
322   fs_reg dst0 = v->vgrf(glsl_type::float_type);
323   fs_reg dst1 = v->vgrf(glsl_type::float_type);
324   fs_reg dst2 = v->vgrf(glsl_type::float_type);
325   fs_reg src0 = v->vgrf(glsl_type::float_type);
326   fs_reg src1 = v->vgrf(glsl_type::float_type);
327   bld.MUL(dst0, src0, src1);
328   set_saturate(true, bld.MOV(dst1, dst0));
329   dst0.negate = true;
330   set_saturate(true, bld.MOV(dst2, dst0));
331
332   /* = Before =
333    *
334    * 0: mul(8)        dst0  src0  src1
335    * 1: mov.sat(8)    dst1  dst0
336    * 2: mov.sat(8)    dst2  -dst0
337    *
338    * = After =
339    * (no changes)
340    */
341
342   v->calculate_cfg();
343   bblock_t *block0 = v->cfg->blocks[0];
344
345   EXPECT_EQ(0, block0->start_ip);
346   EXPECT_EQ(2, block0->end_ip);
347
348   EXPECT_FALSE(saturate_propagation(v));
349   EXPECT_EQ(0, block0->start_ip);
350   EXPECT_EQ(2, block0->end_ip);
351   EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
352   EXPECT_FALSE(instruction(block0, 0)->saturate);
353   EXPECT_FALSE(instruction(block0, 0)->src[1].negate);
354   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
355   EXPECT_TRUE(instruction(block0, 1)->saturate);
356   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
357   EXPECT_TRUE(instruction(block0, 2)->src[0].negate);
358   EXPECT_TRUE(instruction(block0, 2)->saturate);
359}
360
361TEST_F(saturate_propagation_test, mul_neg_mov_sat_neg_mov_sat)
362{
363   const fs_builder &bld = v->bld;
364   fs_reg dst0 = v->vgrf(glsl_type::float_type);
365   fs_reg dst1 = v->vgrf(glsl_type::float_type);
366   fs_reg dst2 = v->vgrf(glsl_type::float_type);
367   fs_reg src0 = v->vgrf(glsl_type::float_type);
368   fs_reg src1 = v->vgrf(glsl_type::float_type);
369   bld.MUL(dst0, src0, src1);
370   dst0.negate = true;
371   set_saturate(true, bld.MOV(dst1, dst0));
372   set_saturate(true, bld.MOV(dst2, dst0));
373
374   /* = Before =
375    *
376    * 0: mul(8)        dst0  src0  src1
377    * 1: mov.sat(8)    dst1  -dst0
378    * 2: mov.sat(8)    dst2  -dst0
379    *
380    * = After =
381    * (no changes)
382    */
383
384   v->calculate_cfg();
385   bblock_t *block0 = v->cfg->blocks[0];
386
387   EXPECT_EQ(0, block0->start_ip);
388   EXPECT_EQ(2, block0->end_ip);
389
390   EXPECT_FALSE(saturate_propagation(v));
391   EXPECT_EQ(0, block0->start_ip);
392   EXPECT_EQ(2, block0->end_ip);
393   EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
394   EXPECT_FALSE(instruction(block0, 0)->saturate);
395   EXPECT_FALSE(instruction(block0, 0)->src[1].negate);
396   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
397   EXPECT_TRUE(instruction(block0, 1)->src[0].negate);
398   EXPECT_TRUE(instruction(block0, 1)->saturate);
399   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
400   EXPECT_TRUE(instruction(block0, 2)->src[0].negate);
401   EXPECT_TRUE(instruction(block0, 2)->saturate);
402}
403
404TEST_F(saturate_propagation_test, abs_mov_sat)
405{
406   const fs_builder &bld = v->bld;
407   fs_reg dst0 = v->vgrf(glsl_type::float_type);
408   fs_reg dst1 = 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   bld.ADD(dst0, src0, src1);
412   dst0.abs = true;
413   set_saturate(true, bld.MOV(dst1, dst0));
414
415   /* = Before =
416    *
417    * 0: add(8)        dst0  src0  src1
418    * 1: mov.sat(8)    dst1  (abs)dst0
419    *
420    * = After =
421    * (no changes)
422    */
423
424   v->calculate_cfg();
425   bblock_t *block0 = v->cfg->blocks[0];
426
427   EXPECT_EQ(0, block0->start_ip);
428   EXPECT_EQ(1, block0->end_ip);
429
430   EXPECT_FALSE(saturate_propagation(v));
431   EXPECT_EQ(0, block0->start_ip);
432   EXPECT_EQ(1, block0->end_ip);
433   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
434   EXPECT_FALSE(instruction(block0, 0)->saturate);
435   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
436   EXPECT_TRUE(instruction(block0, 1)->saturate);
437}
438
439TEST_F(saturate_propagation_test, producer_saturates)
440{
441   const fs_builder &bld = v->bld;
442   fs_reg dst0 = v->vgrf(glsl_type::float_type);
443   fs_reg dst1 = v->vgrf(glsl_type::float_type);
444   fs_reg dst2 = v->vgrf(glsl_type::float_type);
445   fs_reg src0 = v->vgrf(glsl_type::float_type);
446   fs_reg src1 = v->vgrf(glsl_type::float_type);
447   set_saturate(true, bld.ADD(dst0, src0, src1));
448   set_saturate(true, bld.MOV(dst1, dst0));
449   bld.MOV(dst2, dst0);
450
451   /* = Before =
452    *
453    * 0: add.sat(8)    dst0  src0  src1
454    * 1: mov.sat(8)    dst1  dst0
455    * 2: mov(8)        dst2  dst0
456    *
457    * = After =
458    * 0: add.sat(8)    dst0  src0  src1
459    * 1: mov(8)        dst1  dst0
460    * 2: mov(8)        dst2  dst0
461    */
462
463   v->calculate_cfg();
464   bblock_t *block0 = v->cfg->blocks[0];
465
466   EXPECT_EQ(0, block0->start_ip);
467   EXPECT_EQ(2, block0->end_ip);
468
469   EXPECT_TRUE(saturate_propagation(v));
470   EXPECT_EQ(0, block0->start_ip);
471   EXPECT_EQ(2, block0->end_ip);
472   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
473   EXPECT_TRUE(instruction(block0, 0)->saturate);
474   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
475   EXPECT_FALSE(instruction(block0, 1)->saturate);
476}
477
478TEST_F(saturate_propagation_test, intervening_saturating_copy)
479{
480   const fs_builder &bld = v->bld;
481   fs_reg dst0 = v->vgrf(glsl_type::float_type);
482   fs_reg dst1 = v->vgrf(glsl_type::float_type);
483   fs_reg dst2 = v->vgrf(glsl_type::float_type);
484   fs_reg src0 = v->vgrf(glsl_type::float_type);
485   fs_reg src1 = v->vgrf(glsl_type::float_type);
486   bld.ADD(dst0, src0, src1);
487   set_saturate(true, bld.MOV(dst1, dst0));
488   set_saturate(true, bld.MOV(dst2, dst0));
489
490   /* = Before =
491    *
492    * 0: add(8)    dst0  src0  src1
493    * 1: mov.sat(8)    dst1  dst0
494    * 2: mov.sat(8)    dst2  dst0
495    *
496    * = After =
497    * 0: add.sat(8)    dst0  src0  src1
498    * 1: mov(8)        dst1  dst0
499    * 2: mov(8)        dst2  dst0
500    */
501
502   v->calculate_cfg();
503   bblock_t *block0 = v->cfg->blocks[0];
504
505   EXPECT_EQ(0, block0->start_ip);
506   EXPECT_EQ(2, block0->end_ip);
507
508   EXPECT_TRUE(saturate_propagation(v));
509   EXPECT_EQ(0, block0->start_ip);
510   EXPECT_EQ(2, block0->end_ip);
511   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
512   EXPECT_TRUE(instruction(block0, 0)->saturate);
513   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
514   EXPECT_FALSE(instruction(block0, 1)->saturate);
515   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
516   EXPECT_FALSE(instruction(block0, 2)->saturate);
517}
518
519TEST_F(saturate_propagation_test, intervening_dest_write)
520{
521   const fs_builder &bld = v->bld;
522   fs_reg dst0 = v->vgrf(glsl_type::vec4_type);
523   fs_reg dst1 = v->vgrf(glsl_type::float_type);
524   fs_reg src0 = v->vgrf(glsl_type::float_type);
525   fs_reg src1 = v->vgrf(glsl_type::float_type);
526   fs_reg src2 = v->vgrf(glsl_type::vec2_type);
527   bld.ADD(offset(dst0, bld, 2), src0, src1);
528   bld.emit(SHADER_OPCODE_TEX, dst0, src2)
529      ->size_written = 4 * REG_SIZE;
530   set_saturate(true, bld.MOV(dst1, offset(dst0, bld, 2)));
531
532   /* = Before =
533    *
534    * 0: add(8)        dst0+2  src0    src1
535    * 1: tex(8) rlen 4 dst0+0  src2
536    * 2: mov.sat(8)    dst1    dst0+2
537    *
538    * = After =
539    * (no changes)
540    */
541
542   v->calculate_cfg();
543   bblock_t *block0 = v->cfg->blocks[0];
544
545   EXPECT_EQ(0, block0->start_ip);
546   EXPECT_EQ(2, block0->end_ip);
547
548   EXPECT_FALSE(saturate_propagation(v));
549   EXPECT_EQ(0, block0->start_ip);
550   EXPECT_EQ(2, block0->end_ip);
551   EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
552   EXPECT_FALSE(instruction(block0, 0)->saturate);
553   EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
554   EXPECT_FALSE(instruction(block0, 0)->saturate);
555   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
556   EXPECT_TRUE(instruction(block0, 2)->saturate);
557}
558
559TEST_F(saturate_propagation_test, mul_neg_mov_sat_mov_sat)
560{
561   const fs_builder &bld = v->bld;
562   fs_reg dst0 = v->vgrf(glsl_type::float_type);
563   fs_reg dst1 = v->vgrf(glsl_type::float_type);
564   fs_reg dst2 = v->vgrf(glsl_type::float_type);
565   fs_reg src0 = v->vgrf(glsl_type::float_type);
566   fs_reg src1 = v->vgrf(glsl_type::float_type);
567   bld.MUL(dst0, src0, src1);
568   dst0.negate = true;
569   set_saturate(true, bld.MOV(dst1, dst0));
570   dst0.negate = false;
571   set_saturate(true, bld.MOV(dst2, dst0));
572
573   /* = Before =
574    *
575    * 0: mul(8)        dst0  src0  src1
576    * 1: mov.sat(8)    dst1  -dst0
577    * 2: mov.sat(8)    dst2  dst0
578    *
579    * = After =
580    * (no changes)
581    */
582
583   v->calculate_cfg();
584   bblock_t *block0 = v->cfg->blocks[0];
585
586   EXPECT_EQ(0, block0->start_ip);
587   EXPECT_EQ(2, block0->end_ip);
588
589   EXPECT_FALSE(saturate_propagation(v));
590   EXPECT_EQ(0, block0->start_ip);
591   EXPECT_EQ(2, block0->end_ip);
592   EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
593   EXPECT_FALSE(instruction(block0, 0)->saturate);
594   EXPECT_FALSE(instruction(block0, 0)->src[1].negate);
595   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
596   EXPECT_TRUE(instruction(block0, 1)->saturate);
597   EXPECT_TRUE(instruction(block0, 1)->src[0].negate);
598   EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
599   EXPECT_TRUE(instruction(block0, 2)->saturate);
600}
601