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 
29 using namespace brw;
30 
31 class saturate_propagation_test : public ::testing::Test {
32    virtual void SetUp();
33 
34 public:
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 
43 class saturate_propagation_fs_visitor : public fs_visitor
44 {
45 public:
saturate_propagation_fs_visitor(struct brw_compiler * compiler,struct brw_wm_prog_data * prog_data,nir_shader * shader)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 
SetUp()55 void 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 = 6;
69 }
70 
71 static fs_inst *
instruction(bblock_t * block,int num)72 instruction(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 
81 static bool
saturate_propagation(fs_visitor * v)82 saturate_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 
TEST_F(saturate_propagation_test,basic)101 TEST_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 
TEST_F(saturate_propagation_test,other_non_saturated_use)136 TEST_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 
TEST_F(saturate_propagation_test,predicated_instruction)174 TEST_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 
TEST_F(saturate_propagation_test,neg_mov_sat)209 TEST_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 
TEST_F(saturate_propagation_test,add_neg_mov_sat)243 TEST_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 
TEST_F(saturate_propagation_test,add_imm_float_neg_mov_sat)281 TEST_F(saturate_propagation_test, add_imm_float_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 = brw_imm_f(1.0f);
288    bld.ADD(dst0, src0, src1);
289    dst0.negate = true;
290    set_saturate(true, bld.MOV(dst1, dst0));
291 
292    /* = Before =
293     *
294     * 0: add(8)        dst0  src0  1.0f
295     * 1: mov.sat(8)    dst1  -dst0
296     *
297     * = After =
298     * 0: add.sat(8)    dst0  -src0 -1.0f
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_ADD, instruction(block0, 0)->opcode);
312    EXPECT_TRUE(instruction(block0, 0)->saturate);
313    EXPECT_TRUE(instruction(block0, 0)->src[0].negate);
314    EXPECT_EQ(instruction(block0, 0)->src[1].f, -1.0f);
315    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
316    EXPECT_FALSE(instruction(block0, 1)->saturate);
317 }
318 
TEST_F(saturate_propagation_test,mul_neg_mov_sat)319 TEST_F(saturate_propagation_test, mul_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 src0 = v->vgrf(glsl_type::float_type);
325    fs_reg src1 = v->vgrf(glsl_type::float_type);
326    bld.MUL(dst0, src0, src1);
327    dst0.negate = true;
328    set_saturate(true, bld.MOV(dst1, dst0));
329 
330    /* = Before =
331     *
332     * 0: mul(8)        dst0  src0  src1
333     * 1: mov.sat(8)    dst1  -dst0
334     *
335     * = After =
336     * 0: mul.sat(8)    dst0  src0 -src1
337     * 1: mov(8)        dst1  dst0
338     */
339 
340    v->calculate_cfg();
341    bblock_t *block0 = v->cfg->blocks[0];
342 
343    EXPECT_EQ(0, block0->start_ip);
344    EXPECT_EQ(1, block0->end_ip);
345 
346    EXPECT_TRUE(saturate_propagation(v));
347    EXPECT_EQ(0, block0->start_ip);
348    EXPECT_EQ(1, block0->end_ip);
349    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
350    EXPECT_TRUE(instruction(block0, 0)->saturate);
351    EXPECT_TRUE(instruction(block0, 0)->src[0].negate);
352    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
353    EXPECT_FALSE(instruction(block0, 1)->saturate);
354    EXPECT_FALSE(instruction(block0, 1)->src[0].negate);
355 }
356 
TEST_F(saturate_propagation_test,mad_neg_mov_sat)357 TEST_F(saturate_propagation_test, mad_neg_mov_sat)
358 {
359    const fs_builder &bld = v->bld;
360    fs_reg dst0 = v->vgrf(glsl_type::float_type);
361    fs_reg dst1 = v->vgrf(glsl_type::float_type);
362    fs_reg src0 = v->vgrf(glsl_type::float_type);
363    fs_reg src1 = v->vgrf(glsl_type::float_type);
364    fs_reg src2 = v->vgrf(glsl_type::float_type);
365    bld.MAD(dst0, src0, src1, src2);
366    dst0.negate = true;
367    set_saturate(true, bld.MOV(dst1, dst0));
368 
369    /* = Before =
370     *
371     * 0: mad(8)        dst0  src0  src1 src2
372     * 1: mov.sat(8)    dst1  -dst0
373     *
374     * = After =
375     * 0: mad.sat(8)    dst0  -src0 -src1 src2
376     * 1: mov(8)        dst1  dst0
377     */
378 
379    v->calculate_cfg();
380    bblock_t *block0 = v->cfg->blocks[0];
381 
382    EXPECT_EQ(0, block0->start_ip);
383    EXPECT_EQ(1, block0->end_ip);
384 
385    EXPECT_TRUE(saturate_propagation(v));
386    EXPECT_EQ(0, block0->start_ip);
387    EXPECT_EQ(1, block0->end_ip);
388    EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode);
389    EXPECT_TRUE(instruction(block0, 0)->saturate);
390    EXPECT_TRUE(instruction(block0, 0)->src[0].negate);
391    EXPECT_TRUE(instruction(block0, 0)->src[1].negate);
392    EXPECT_FALSE(instruction(block0, 0)->src[2].negate);
393    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
394    EXPECT_FALSE(instruction(block0, 1)->saturate);
395    EXPECT_FALSE(instruction(block0, 1)->src[0].negate);
396 }
397 
TEST_F(saturate_propagation_test,mad_imm_float_neg_mov_sat)398 TEST_F(saturate_propagation_test, mad_imm_float_neg_mov_sat)
399 {
400    const fs_builder &bld = v->bld;
401    fs_reg dst0 = v->vgrf(glsl_type::float_type);
402    fs_reg dst1 = v->vgrf(glsl_type::float_type);
403    fs_reg src0 = brw_imm_f(1.0f);
404    fs_reg src1 = brw_imm_f(-2.0f);
405    fs_reg src2 = v->vgrf(glsl_type::float_type);
406    /* The builder for MAD tries to be helpful and not put immediates as direct
407     * sources. We want to test specifically that case.
408     */
409    fs_inst *mad = bld.MAD(dst0, src2, src2, src2);
410    mad->src[0]= src0;
411    mad->src[1] = src1;
412    dst0.negate = true;
413    set_saturate(true, bld.MOV(dst1, dst0));
414 
415    /* = Before =
416     *
417     * 0: mad(8)        dst0  1.0f -2.0f src2
418     * 1: mov.sat(8)    dst1  -dst0
419     *
420     * = After =
421     * 0: mad.sat(8)    dst0  -1.0f 2.0f src2
422     * 1: mov(8)        dst1  dst0
423     */
424 
425    v->calculate_cfg();
426    bblock_t *block0 = v->cfg->blocks[0];
427 
428    EXPECT_EQ(0, block0->start_ip);
429    EXPECT_EQ(1, block0->end_ip);
430 
431    EXPECT_TRUE(saturate_propagation(v));
432    EXPECT_EQ(0, block0->start_ip);
433    EXPECT_EQ(1, block0->end_ip);
434    EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode);
435    EXPECT_TRUE(instruction(block0, 0)->saturate);
436    EXPECT_EQ(instruction(block0, 0)->src[0].f, -1.0f);
437    EXPECT_EQ(instruction(block0, 0)->src[1].f, 2.0f);
438    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
439    EXPECT_FALSE(instruction(block0, 1)->saturate);
440    EXPECT_FALSE(instruction(block0, 1)->src[0].negate);
441 }
442 
TEST_F(saturate_propagation_test,mul_mov_sat_neg_mov_sat)443 TEST_F(saturate_propagation_test, mul_mov_sat_neg_mov_sat)
444 {
445    const fs_builder &bld = v->bld;
446    fs_reg dst0 = v->vgrf(glsl_type::float_type);
447    fs_reg dst1 = v->vgrf(glsl_type::float_type);
448    fs_reg dst2 = v->vgrf(glsl_type::float_type);
449    fs_reg src0 = v->vgrf(glsl_type::float_type);
450    fs_reg src1 = v->vgrf(glsl_type::float_type);
451    bld.MUL(dst0, src0, src1);
452    set_saturate(true, bld.MOV(dst1, dst0));
453    dst0.negate = true;
454    set_saturate(true, bld.MOV(dst2, dst0));
455 
456    /* = Before =
457     *
458     * 0: mul(8)        dst0  src0  src1
459     * 1: mov.sat(8)    dst1  dst0
460     * 2: mov.sat(8)    dst2  -dst0
461     *
462     * = After =
463     * (no changes)
464     */
465 
466    v->calculate_cfg();
467    bblock_t *block0 = v->cfg->blocks[0];
468 
469    EXPECT_EQ(0, block0->start_ip);
470    EXPECT_EQ(2, block0->end_ip);
471 
472    EXPECT_FALSE(saturate_propagation(v));
473    EXPECT_EQ(0, block0->start_ip);
474    EXPECT_EQ(2, block0->end_ip);
475    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
476    EXPECT_FALSE(instruction(block0, 0)->saturate);
477    EXPECT_FALSE(instruction(block0, 0)->src[1].negate);
478    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
479    EXPECT_TRUE(instruction(block0, 1)->saturate);
480    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
481    EXPECT_TRUE(instruction(block0, 2)->src[0].negate);
482    EXPECT_TRUE(instruction(block0, 2)->saturate);
483 }
484 
TEST_F(saturate_propagation_test,mul_neg_mov_sat_neg_mov_sat)485 TEST_F(saturate_propagation_test, mul_neg_mov_sat_neg_mov_sat)
486 {
487    const fs_builder &bld = v->bld;
488    fs_reg dst0 = v->vgrf(glsl_type::float_type);
489    fs_reg dst1 = v->vgrf(glsl_type::float_type);
490    fs_reg dst2 = 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    bld.MUL(dst0, src0, src1);
494    dst0.negate = true;
495    set_saturate(true, bld.MOV(dst1, dst0));
496    set_saturate(true, bld.MOV(dst2, dst0));
497 
498    /* = Before =
499     *
500     * 0: mul(8)        dst0  src0  src1
501     * 1: mov.sat(8)    dst1  -dst0
502     * 2: mov.sat(8)    dst2  -dst0
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(2, block0->end_ip);
513 
514    EXPECT_FALSE(saturate_propagation(v));
515    EXPECT_EQ(0, block0->start_ip);
516    EXPECT_EQ(2, block0->end_ip);
517    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
518    EXPECT_FALSE(instruction(block0, 0)->saturate);
519    EXPECT_FALSE(instruction(block0, 0)->src[1].negate);
520    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
521    EXPECT_TRUE(instruction(block0, 1)->src[0].negate);
522    EXPECT_TRUE(instruction(block0, 1)->saturate);
523    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
524    EXPECT_TRUE(instruction(block0, 2)->src[0].negate);
525    EXPECT_TRUE(instruction(block0, 2)->saturate);
526 }
527 
TEST_F(saturate_propagation_test,abs_mov_sat)528 TEST_F(saturate_propagation_test, abs_mov_sat)
529 {
530    const fs_builder &bld = v->bld;
531    fs_reg dst0 = v->vgrf(glsl_type::float_type);
532    fs_reg dst1 = v->vgrf(glsl_type::float_type);
533    fs_reg src0 = v->vgrf(glsl_type::float_type);
534    fs_reg src1 = v->vgrf(glsl_type::float_type);
535    bld.ADD(dst0, src0, src1);
536    dst0.abs = true;
537    set_saturate(true, bld.MOV(dst1, dst0));
538 
539    /* = Before =
540     *
541     * 0: add(8)        dst0  src0  src1
542     * 1: mov.sat(8)    dst1  (abs)dst0
543     *
544     * = After =
545     * (no changes)
546     */
547 
548    v->calculate_cfg();
549    bblock_t *block0 = v->cfg->blocks[0];
550 
551    EXPECT_EQ(0, block0->start_ip);
552    EXPECT_EQ(1, block0->end_ip);
553 
554    EXPECT_FALSE(saturate_propagation(v));
555    EXPECT_EQ(0, block0->start_ip);
556    EXPECT_EQ(1, block0->end_ip);
557    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
558    EXPECT_FALSE(instruction(block0, 0)->saturate);
559    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
560    EXPECT_TRUE(instruction(block0, 1)->saturate);
561 }
562 
TEST_F(saturate_propagation_test,producer_saturates)563 TEST_F(saturate_propagation_test, producer_saturates)
564 {
565    const fs_builder &bld = v->bld;
566    fs_reg dst0 = v->vgrf(glsl_type::float_type);
567    fs_reg dst1 = v->vgrf(glsl_type::float_type);
568    fs_reg dst2 = v->vgrf(glsl_type::float_type);
569    fs_reg src0 = v->vgrf(glsl_type::float_type);
570    fs_reg src1 = v->vgrf(glsl_type::float_type);
571    set_saturate(true, bld.ADD(dst0, src0, src1));
572    set_saturate(true, bld.MOV(dst1, dst0));
573    bld.MOV(dst2, dst0);
574 
575    /* = Before =
576     *
577     * 0: add.sat(8)    dst0  src0  src1
578     * 1: mov.sat(8)    dst1  dst0
579     * 2: mov(8)        dst2  dst0
580     *
581     * = After =
582     * 0: add.sat(8)    dst0  src0  src1
583     * 1: mov(8)        dst1  dst0
584     * 2: mov(8)        dst2  dst0
585     */
586 
587    v->calculate_cfg();
588    bblock_t *block0 = v->cfg->blocks[0];
589 
590    EXPECT_EQ(0, block0->start_ip);
591    EXPECT_EQ(2, block0->end_ip);
592 
593    EXPECT_TRUE(saturate_propagation(v));
594    EXPECT_EQ(0, block0->start_ip);
595    EXPECT_EQ(2, block0->end_ip);
596    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
597    EXPECT_TRUE(instruction(block0, 0)->saturate);
598    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
599    EXPECT_FALSE(instruction(block0, 1)->saturate);
600 }
601 
TEST_F(saturate_propagation_test,intervening_saturating_copy)602 TEST_F(saturate_propagation_test, intervening_saturating_copy)
603 {
604    const fs_builder &bld = v->bld;
605    fs_reg dst0 = v->vgrf(glsl_type::float_type);
606    fs_reg dst1 = v->vgrf(glsl_type::float_type);
607    fs_reg dst2 = v->vgrf(glsl_type::float_type);
608    fs_reg src0 = v->vgrf(glsl_type::float_type);
609    fs_reg src1 = v->vgrf(glsl_type::float_type);
610    bld.ADD(dst0, src0, src1);
611    set_saturate(true, bld.MOV(dst1, dst0));
612    set_saturate(true, bld.MOV(dst2, dst0));
613 
614    /* = Before =
615     *
616     * 0: add(8)    dst0  src0  src1
617     * 1: mov.sat(8)    dst1  dst0
618     * 2: mov.sat(8)    dst2  dst0
619     *
620     * = After =
621     * 0: add.sat(8)    dst0  src0  src1
622     * 1: mov(8)        dst1  dst0
623     * 2: mov(8)        dst2  dst0
624     */
625 
626    v->calculate_cfg();
627    bblock_t *block0 = v->cfg->blocks[0];
628 
629    EXPECT_EQ(0, block0->start_ip);
630    EXPECT_EQ(2, block0->end_ip);
631 
632    EXPECT_TRUE(saturate_propagation(v));
633    EXPECT_EQ(0, block0->start_ip);
634    EXPECT_EQ(2, block0->end_ip);
635    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
636    EXPECT_TRUE(instruction(block0, 0)->saturate);
637    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
638    EXPECT_FALSE(instruction(block0, 1)->saturate);
639    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
640    EXPECT_FALSE(instruction(block0, 2)->saturate);
641 }
642 
TEST_F(saturate_propagation_test,intervening_dest_write)643 TEST_F(saturate_propagation_test, intervening_dest_write)
644 {
645    const fs_builder &bld = v->bld;
646    fs_reg dst0 = v->vgrf(glsl_type::vec4_type);
647    fs_reg dst1 = v->vgrf(glsl_type::float_type);
648    fs_reg src0 = v->vgrf(glsl_type::float_type);
649    fs_reg src1 = v->vgrf(glsl_type::float_type);
650    fs_reg src2 = v->vgrf(glsl_type::vec2_type);
651    bld.ADD(offset(dst0, bld, 2), src0, src1);
652    bld.emit(SHADER_OPCODE_TEX, dst0, src2)
653       ->size_written = 4 * REG_SIZE;
654    set_saturate(true, bld.MOV(dst1, offset(dst0, bld, 2)));
655 
656    /* = Before =
657     *
658     * 0: add(8)        dst0+2  src0    src1
659     * 1: tex(8) rlen 4 dst0+0  src2
660     * 2: mov.sat(8)    dst1    dst0+2
661     *
662     * = After =
663     * (no changes)
664     */
665 
666    v->calculate_cfg();
667    bblock_t *block0 = v->cfg->blocks[0];
668 
669    EXPECT_EQ(0, block0->start_ip);
670    EXPECT_EQ(2, block0->end_ip);
671 
672    EXPECT_FALSE(saturate_propagation(v));
673    EXPECT_EQ(0, block0->start_ip);
674    EXPECT_EQ(2, block0->end_ip);
675    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
676    EXPECT_FALSE(instruction(block0, 0)->saturate);
677    EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
678    EXPECT_FALSE(instruction(block0, 0)->saturate);
679    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
680    EXPECT_TRUE(instruction(block0, 2)->saturate);
681 }
682 
TEST_F(saturate_propagation_test,mul_neg_mov_sat_mov_sat)683 TEST_F(saturate_propagation_test, mul_neg_mov_sat_mov_sat)
684 {
685    const fs_builder &bld = v->bld;
686    fs_reg dst0 = v->vgrf(glsl_type::float_type);
687    fs_reg dst1 = v->vgrf(glsl_type::float_type);
688    fs_reg dst2 = v->vgrf(glsl_type::float_type);
689    fs_reg src0 = v->vgrf(glsl_type::float_type);
690    fs_reg src1 = v->vgrf(glsl_type::float_type);
691    bld.MUL(dst0, src0, src1);
692    dst0.negate = true;
693    set_saturate(true, bld.MOV(dst1, dst0));
694    dst0.negate = false;
695    set_saturate(true, bld.MOV(dst2, dst0));
696 
697    /* = Before =
698     *
699     * 0: mul(8)        dst0  src0  src1
700     * 1: mov.sat(8)    dst1  -dst0
701     * 2: mov.sat(8)    dst2  dst0
702     *
703     * = After =
704     * (no changes)
705     */
706 
707    v->calculate_cfg();
708    bblock_t *block0 = v->cfg->blocks[0];
709 
710    EXPECT_EQ(0, block0->start_ip);
711    EXPECT_EQ(2, block0->end_ip);
712 
713    EXPECT_FALSE(saturate_propagation(v));
714    EXPECT_EQ(0, block0->start_ip);
715    EXPECT_EQ(2, block0->end_ip);
716    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
717    EXPECT_FALSE(instruction(block0, 0)->saturate);
718    EXPECT_FALSE(instruction(block0, 0)->src[1].negate);
719    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
720    EXPECT_TRUE(instruction(block0, 1)->saturate);
721    EXPECT_TRUE(instruction(block0, 1)->src[0].negate);
722    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
723    EXPECT_TRUE(instruction(block0, 2)->saturate);
724 }
725