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    virtual void TearDown();
34 
35 public:
36    struct brw_compiler *compiler;
37    struct intel_device_info *devinfo;
38    void *ctx;
39    struct brw_wm_prog_data *prog_data;
40    struct gl_shader_program *shader_prog;
41    fs_visitor *v;
42 };
43 
44 class saturate_propagation_fs_visitor : public fs_visitor
45 {
46 public:
saturate_propagation_fs_visitor(struct brw_compiler * compiler,void * mem_ctx,struct brw_wm_prog_data * prog_data,nir_shader * shader)47    saturate_propagation_fs_visitor(struct brw_compiler *compiler,
48                                    void *mem_ctx,
49                                    struct brw_wm_prog_data *prog_data,
50                                    nir_shader *shader)
51       : fs_visitor(compiler, NULL, mem_ctx, NULL,
52                    &prog_data->base, shader, 16, -1, false) {}
53 };
54 
55 
SetUp()56 void saturate_propagation_test::SetUp()
57 {
58    ctx = ralloc_context(NULL);
59    compiler = rzalloc(ctx, struct brw_compiler);
60    devinfo = rzalloc(ctx, struct intel_device_info);
61    compiler->devinfo = devinfo;
62 
63    prog_data = ralloc(ctx, struct brw_wm_prog_data);
64    nir_shader *shader =
65       nir_shader_create(ctx, MESA_SHADER_FRAGMENT, NULL, NULL);
66 
67    v = new saturate_propagation_fs_visitor(compiler, ctx, prog_data, shader);
68 
69    devinfo->ver = 6;
70    devinfo->verx10 = devinfo->ver * 10;
71 }
72 
TearDown()73 void saturate_propagation_test::TearDown()
74 {
75    delete v;
76    v = NULL;
77 
78    ralloc_free(ctx);
79    ctx = NULL;
80 }
81 
82 
83 static fs_inst *
instruction(bblock_t * block,int num)84 instruction(bblock_t *block, int num)
85 {
86    fs_inst *inst = (fs_inst *)block->start();
87    for (int i = 0; i < num; i++) {
88       inst = (fs_inst *)inst->next;
89    }
90    return inst;
91 }
92 
93 static bool
saturate_propagation(fs_visitor * v)94 saturate_propagation(fs_visitor *v)
95 {
96    const bool print = false;
97 
98    if (print) {
99       fprintf(stderr, "= Before =\n");
100       v->cfg->dump();
101    }
102 
103    bool ret = v->opt_saturate_propagation();
104 
105    if (print) {
106       fprintf(stderr, "\n= After =\n");
107       v->cfg->dump();
108    }
109 
110    return ret;
111 }
112 
TEST_F(saturate_propagation_test,basic)113 TEST_F(saturate_propagation_test, basic)
114 {
115    const fs_builder &bld = v->bld;
116    fs_reg dst0 = v->vgrf(glsl_type::float_type);
117    fs_reg dst1 = v->vgrf(glsl_type::float_type);
118    fs_reg src0 = v->vgrf(glsl_type::float_type);
119    fs_reg src1 = v->vgrf(glsl_type::float_type);
120    bld.ADD(dst0, src0, src1);
121    set_saturate(true, bld.MOV(dst1, dst0));
122 
123    /* = Before =
124     *
125     * 0: add(16)       dst0  src0  src1
126     * 1: mov.sat(16)   dst1  dst0
127     *
128     * = After =
129     * 0: add.sat(16)   dst0  src0  src1
130     * 1: mov(16)       dst1  dst0
131     */
132 
133    v->calculate_cfg();
134    bblock_t *block0 = v->cfg->blocks[0];
135 
136    EXPECT_EQ(0, block0->start_ip);
137    EXPECT_EQ(1, block0->end_ip);
138 
139    EXPECT_TRUE(saturate_propagation(v));
140    EXPECT_EQ(0, block0->start_ip);
141    EXPECT_EQ(1, block0->end_ip);
142    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
143    EXPECT_TRUE(instruction(block0, 0)->saturate);
144    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
145    EXPECT_FALSE(instruction(block0, 1)->saturate);
146 }
147 
TEST_F(saturate_propagation_test,other_non_saturated_use)148 TEST_F(saturate_propagation_test, other_non_saturated_use)
149 {
150    const fs_builder &bld = v->bld;
151    fs_reg dst0 = v->vgrf(glsl_type::float_type);
152    fs_reg dst1 = v->vgrf(glsl_type::float_type);
153    fs_reg dst2 = v->vgrf(glsl_type::float_type);
154    fs_reg src0 = v->vgrf(glsl_type::float_type);
155    fs_reg src1 = v->vgrf(glsl_type::float_type);
156    bld.ADD(dst0, src0, src1);
157    set_saturate(true, bld.MOV(dst1, dst0));
158    bld.ADD(dst2, dst0, src0);
159 
160    /* = Before =
161     *
162     * 0: add(16)       dst0  src0  src1
163     * 1: mov.sat(16)   dst1  dst0
164     * 2: add(16)       dst2  dst0  src0
165     *
166     * = After =
167     * (no changes)
168     */
169 
170    v->calculate_cfg();
171    bblock_t *block0 = v->cfg->blocks[0];
172 
173    EXPECT_EQ(0, block0->start_ip);
174    EXPECT_EQ(2, block0->end_ip);
175 
176    EXPECT_FALSE(saturate_propagation(v));
177    EXPECT_EQ(0, block0->start_ip);
178    EXPECT_EQ(2, block0->end_ip);
179    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
180    EXPECT_FALSE(instruction(block0, 0)->saturate);
181    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
182    EXPECT_TRUE(instruction(block0, 1)->saturate);
183    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 2)->opcode);
184 }
185 
TEST_F(saturate_propagation_test,predicated_instruction)186 TEST_F(saturate_propagation_test, predicated_instruction)
187 {
188    const fs_builder &bld = v->bld;
189    fs_reg dst0 = v->vgrf(glsl_type::float_type);
190    fs_reg dst1 = v->vgrf(glsl_type::float_type);
191    fs_reg src0 = v->vgrf(glsl_type::float_type);
192    fs_reg src1 = v->vgrf(glsl_type::float_type);
193    bld.ADD(dst0, src0, src1)
194       ->predicate = BRW_PREDICATE_NORMAL;
195    set_saturate(true, bld.MOV(dst1, dst0));
196 
197    /* = Before =
198     *
199     * 0: (+f0) add(16) dst0  src0  src1
200     * 1: mov.sat(16)   dst1  dst0
201     *
202     * = After =
203     * (no changes)
204     */
205 
206    v->calculate_cfg();
207    bblock_t *block0 = v->cfg->blocks[0];
208 
209    EXPECT_EQ(0, block0->start_ip);
210    EXPECT_EQ(1, block0->end_ip);
211 
212    EXPECT_FALSE(saturate_propagation(v));
213    EXPECT_EQ(0, block0->start_ip);
214    EXPECT_EQ(1, block0->end_ip);
215    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
216    EXPECT_FALSE(instruction(block0, 0)->saturate);
217    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
218    EXPECT_TRUE(instruction(block0, 1)->saturate);
219 }
220 
TEST_F(saturate_propagation_test,neg_mov_sat)221 TEST_F(saturate_propagation_test, neg_mov_sat)
222 {
223    const fs_builder &bld = v->bld;
224    fs_reg dst0 = v->vgrf(glsl_type::float_type);
225    fs_reg dst1 = v->vgrf(glsl_type::float_type);
226    fs_reg src0 = v->vgrf(glsl_type::float_type);
227    bld.RNDU(dst0, src0);
228    dst0.negate = true;
229    set_saturate(true, bld.MOV(dst1, dst0));
230 
231    /* = Before =
232     *
233     * 0: rndu(16)      dst0  src0
234     * 1: mov.sat(16)   dst1  -dst0
235     *
236     * = After =
237     * (no changes)
238     */
239 
240    v->calculate_cfg();
241    bblock_t *block0 = v->cfg->blocks[0];
242 
243    EXPECT_EQ(0, block0->start_ip);
244    EXPECT_EQ(1, block0->end_ip);
245 
246    EXPECT_FALSE(saturate_propagation(v));
247    EXPECT_EQ(0, block0->start_ip);
248    EXPECT_EQ(1, block0->end_ip);
249    EXPECT_EQ(BRW_OPCODE_RNDU, instruction(block0, 0)->opcode);
250    EXPECT_FALSE(instruction(block0, 0)->saturate);
251    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
252    EXPECT_TRUE(instruction(block0, 1)->saturate);
253 }
254 
TEST_F(saturate_propagation_test,add_neg_mov_sat)255 TEST_F(saturate_propagation_test, add_neg_mov_sat)
256 {
257    const fs_builder &bld = v->bld;
258    fs_reg dst0 = v->vgrf(glsl_type::float_type);
259    fs_reg dst1 = v->vgrf(glsl_type::float_type);
260    fs_reg src0 = v->vgrf(glsl_type::float_type);
261    fs_reg src1 = v->vgrf(glsl_type::float_type);
262    bld.ADD(dst0, src0, src1);
263    dst0.negate = true;
264    set_saturate(true, bld.MOV(dst1, dst0));
265 
266    /* = Before =
267     *
268     * 0: add(16)       dst0  src0  src1
269     * 1: mov.sat(16)   dst1  -dst0
270     *
271     * = After =
272     * 0: add.sat(16)   dst0  -src0 -src1
273     * 1: mov(16)       dst1  dst0
274     */
275 
276    v->calculate_cfg();
277    bblock_t *block0 = v->cfg->blocks[0];
278 
279    EXPECT_EQ(0, block0->start_ip);
280    EXPECT_EQ(1, block0->end_ip);
281 
282    EXPECT_TRUE(saturate_propagation(v));
283    EXPECT_EQ(0, block0->start_ip);
284    EXPECT_EQ(1, block0->end_ip);
285    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
286    EXPECT_TRUE(instruction(block0, 0)->saturate);
287    EXPECT_TRUE(instruction(block0, 0)->src[0].negate);
288    EXPECT_TRUE(instruction(block0, 0)->src[1].negate);
289    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
290    EXPECT_FALSE(instruction(block0, 1)->saturate);
291 }
292 
TEST_F(saturate_propagation_test,add_imm_float_neg_mov_sat)293 TEST_F(saturate_propagation_test, add_imm_float_neg_mov_sat)
294 {
295    const fs_builder &bld = v->bld;
296    fs_reg dst0 = v->vgrf(glsl_type::float_type);
297    fs_reg dst1 = v->vgrf(glsl_type::float_type);
298    fs_reg src0 = v->vgrf(glsl_type::float_type);
299    fs_reg src1 = brw_imm_f(1.0f);
300    bld.ADD(dst0, src0, src1);
301    dst0.negate = true;
302    set_saturate(true, bld.MOV(dst1, dst0));
303 
304    /* = Before =
305     *
306     * 0: add(16)       dst0  src0  1.0f
307     * 1: mov.sat(16)   dst1  -dst0
308     *
309     * = After =
310     * 0: add.sat(16)   dst0  -src0 -1.0f
311     * 1: mov(16)       dst1  dst0
312     */
313 
314    v->calculate_cfg();
315    bblock_t *block0 = v->cfg->blocks[0];
316 
317    EXPECT_EQ(0, block0->start_ip);
318    EXPECT_EQ(1, block0->end_ip);
319 
320    EXPECT_TRUE(saturate_propagation(v));
321    EXPECT_EQ(0, block0->start_ip);
322    EXPECT_EQ(1, block0->end_ip);
323    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
324    EXPECT_TRUE(instruction(block0, 0)->saturate);
325    EXPECT_TRUE(instruction(block0, 0)->src[0].negate);
326    EXPECT_EQ(instruction(block0, 0)->src[1].f, -1.0f);
327    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
328    EXPECT_FALSE(instruction(block0, 1)->saturate);
329 }
330 
TEST_F(saturate_propagation_test,mul_neg_mov_sat)331 TEST_F(saturate_propagation_test, mul_neg_mov_sat)
332 {
333    const fs_builder &bld = v->bld;
334    fs_reg dst0 = v->vgrf(glsl_type::float_type);
335    fs_reg dst1 = v->vgrf(glsl_type::float_type);
336    fs_reg src0 = v->vgrf(glsl_type::float_type);
337    fs_reg src1 = v->vgrf(glsl_type::float_type);
338    bld.MUL(dst0, src0, src1);
339    dst0.negate = true;
340    set_saturate(true, bld.MOV(dst1, dst0));
341 
342    /* = Before =
343     *
344     * 0: mul(16)       dst0  src0  src1
345     * 1: mov.sat(16)   dst1  -dst0
346     *
347     * = After =
348     * 0: mul.sat(16)   dst0  src0 -src1
349     * 1: mov(16)       dst1  dst0
350     */
351 
352    v->calculate_cfg();
353    bblock_t *block0 = v->cfg->blocks[0];
354 
355    EXPECT_EQ(0, block0->start_ip);
356    EXPECT_EQ(1, block0->end_ip);
357 
358    EXPECT_TRUE(saturate_propagation(v));
359    EXPECT_EQ(0, block0->start_ip);
360    EXPECT_EQ(1, block0->end_ip);
361    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
362    EXPECT_TRUE(instruction(block0, 0)->saturate);
363    EXPECT_TRUE(instruction(block0, 0)->src[0].negate);
364    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
365    EXPECT_FALSE(instruction(block0, 1)->saturate);
366    EXPECT_FALSE(instruction(block0, 1)->src[0].negate);
367 }
368 
TEST_F(saturate_propagation_test,mad_neg_mov_sat)369 TEST_F(saturate_propagation_test, mad_neg_mov_sat)
370 {
371    const fs_builder &bld = v->bld;
372    fs_reg dst0 = v->vgrf(glsl_type::float_type);
373    fs_reg dst1 = v->vgrf(glsl_type::float_type);
374    fs_reg src0 = v->vgrf(glsl_type::float_type);
375    fs_reg src1 = v->vgrf(glsl_type::float_type);
376    fs_reg src2 = v->vgrf(glsl_type::float_type);
377    bld.MAD(dst0, src0, src1, src2);
378    dst0.negate = true;
379    set_saturate(true, bld.MOV(dst1, dst0));
380 
381    /* = Before =
382     *
383     * 0: mad(16)       dst0  src0  src1 src2
384     * 1: mov.sat(16)   dst1  -dst0
385     *
386     * = After =
387     * 0: mad.sat(16)   dst0  -src0 -src1 src2
388     * 1: mov(16)       dst1  dst0
389     */
390 
391    v->calculate_cfg();
392    bblock_t *block0 = v->cfg->blocks[0];
393 
394    EXPECT_EQ(0, block0->start_ip);
395    EXPECT_EQ(1, block0->end_ip);
396 
397    EXPECT_TRUE(saturate_propagation(v));
398    EXPECT_EQ(0, block0->start_ip);
399    EXPECT_EQ(1, block0->end_ip);
400    EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode);
401    EXPECT_TRUE(instruction(block0, 0)->saturate);
402    EXPECT_TRUE(instruction(block0, 0)->src[0].negate);
403    EXPECT_TRUE(instruction(block0, 0)->src[1].negate);
404    EXPECT_FALSE(instruction(block0, 0)->src[2].negate);
405    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
406    EXPECT_FALSE(instruction(block0, 1)->saturate);
407    EXPECT_FALSE(instruction(block0, 1)->src[0].negate);
408 }
409 
TEST_F(saturate_propagation_test,mad_imm_float_neg_mov_sat)410 TEST_F(saturate_propagation_test, mad_imm_float_neg_mov_sat)
411 {
412    const fs_builder &bld = v->bld;
413    fs_reg dst0 = v->vgrf(glsl_type::float_type);
414    fs_reg dst1 = v->vgrf(glsl_type::float_type);
415    fs_reg src0 = brw_imm_f(1.0f);
416    fs_reg src1 = brw_imm_f(-2.0f);
417    fs_reg src2 = v->vgrf(glsl_type::float_type);
418    /* The builder for MAD tries to be helpful and not put immediates as direct
419     * sources. We want to test specifically that case.
420     */
421    fs_inst *mad = bld.MAD(dst0, src2, src2, src2);
422    mad->src[0]= src0;
423    mad->src[1] = src1;
424    dst0.negate = true;
425    set_saturate(true, bld.MOV(dst1, dst0));
426 
427    /* = Before =
428     *
429     * 0: mad(16)       dst0  1.0f -2.0f src2
430     * 1: mov.sat(16)   dst1  -dst0
431     *
432     * = After =
433     * 0: mad.sat(16)   dst0  -1.0f 2.0f src2
434     * 1: mov(16)       dst1  dst0
435     */
436 
437    v->calculate_cfg();
438    bblock_t *block0 = v->cfg->blocks[0];
439 
440    EXPECT_EQ(0, block0->start_ip);
441    EXPECT_EQ(1, block0->end_ip);
442 
443    EXPECT_TRUE(saturate_propagation(v));
444    EXPECT_EQ(0, block0->start_ip);
445    EXPECT_EQ(1, block0->end_ip);
446    EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode);
447    EXPECT_TRUE(instruction(block0, 0)->saturate);
448    EXPECT_EQ(instruction(block0, 0)->src[0].f, -1.0f);
449    EXPECT_EQ(instruction(block0, 0)->src[1].f, 2.0f);
450    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
451    EXPECT_FALSE(instruction(block0, 1)->saturate);
452    EXPECT_FALSE(instruction(block0, 1)->src[0].negate);
453 }
454 
TEST_F(saturate_propagation_test,mul_mov_sat_neg_mov_sat)455 TEST_F(saturate_propagation_test, mul_mov_sat_neg_mov_sat)
456 {
457    const fs_builder &bld = v->bld;
458    fs_reg dst0 = v->vgrf(glsl_type::float_type);
459    fs_reg dst1 = v->vgrf(glsl_type::float_type);
460    fs_reg dst2 = v->vgrf(glsl_type::float_type);
461    fs_reg src0 = v->vgrf(glsl_type::float_type);
462    fs_reg src1 = v->vgrf(glsl_type::float_type);
463    bld.MUL(dst0, src0, src1);
464    set_saturate(true, bld.MOV(dst1, dst0));
465    dst0.negate = true;
466    set_saturate(true, bld.MOV(dst2, dst0));
467 
468    /* = Before =
469     *
470     * 0: mul(16)       dst0  src0  src1
471     * 1: mov.sat(16)   dst1  dst0
472     * 2: mov.sat(16)   dst2  -dst0
473     *
474     * = After =
475     * (no changes)
476     */
477 
478    v->calculate_cfg();
479    bblock_t *block0 = v->cfg->blocks[0];
480 
481    EXPECT_EQ(0, block0->start_ip);
482    EXPECT_EQ(2, block0->end_ip);
483 
484    EXPECT_FALSE(saturate_propagation(v));
485    EXPECT_EQ(0, block0->start_ip);
486    EXPECT_EQ(2, block0->end_ip);
487    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
488    EXPECT_FALSE(instruction(block0, 0)->saturate);
489    EXPECT_FALSE(instruction(block0, 0)->src[1].negate);
490    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
491    EXPECT_TRUE(instruction(block0, 1)->saturate);
492    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
493    EXPECT_TRUE(instruction(block0, 2)->src[0].negate);
494    EXPECT_TRUE(instruction(block0, 2)->saturate);
495 }
496 
TEST_F(saturate_propagation_test,mul_neg_mov_sat_neg_mov_sat)497 TEST_F(saturate_propagation_test, mul_neg_mov_sat_neg_mov_sat)
498 {
499    const fs_builder &bld = v->bld;
500    fs_reg dst0 = v->vgrf(glsl_type::float_type);
501    fs_reg dst1 = v->vgrf(glsl_type::float_type);
502    fs_reg dst2 = v->vgrf(glsl_type::float_type);
503    fs_reg src0 = v->vgrf(glsl_type::float_type);
504    fs_reg src1 = v->vgrf(glsl_type::float_type);
505    bld.MUL(dst0, src0, src1);
506    dst0.negate = true;
507    set_saturate(true, bld.MOV(dst1, dst0));
508    set_saturate(true, bld.MOV(dst2, dst0));
509 
510    /* = Before =
511     *
512     * 0: mul(16)       dst0  src0  src1
513     * 1: mov.sat(16)   dst1  -dst0
514     * 2: mov.sat(16)   dst2  -dst0
515     *
516     * = After =
517     * (no changes)
518     */
519 
520    v->calculate_cfg();
521    bblock_t *block0 = v->cfg->blocks[0];
522 
523    EXPECT_EQ(0, block0->start_ip);
524    EXPECT_EQ(2, block0->end_ip);
525 
526    EXPECT_FALSE(saturate_propagation(v));
527    EXPECT_EQ(0, block0->start_ip);
528    EXPECT_EQ(2, block0->end_ip);
529    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
530    EXPECT_FALSE(instruction(block0, 0)->saturate);
531    EXPECT_FALSE(instruction(block0, 0)->src[1].negate);
532    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
533    EXPECT_TRUE(instruction(block0, 1)->src[0].negate);
534    EXPECT_TRUE(instruction(block0, 1)->saturate);
535    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
536    EXPECT_TRUE(instruction(block0, 2)->src[0].negate);
537    EXPECT_TRUE(instruction(block0, 2)->saturate);
538 }
539 
TEST_F(saturate_propagation_test,abs_mov_sat)540 TEST_F(saturate_propagation_test, abs_mov_sat)
541 {
542    const fs_builder &bld = v->bld;
543    fs_reg dst0 = v->vgrf(glsl_type::float_type);
544    fs_reg dst1 = v->vgrf(glsl_type::float_type);
545    fs_reg src0 = v->vgrf(glsl_type::float_type);
546    fs_reg src1 = v->vgrf(glsl_type::float_type);
547    bld.ADD(dst0, src0, src1);
548    dst0.abs = true;
549    set_saturate(true, bld.MOV(dst1, dst0));
550 
551    /* = Before =
552     *
553     * 0: add(16)       dst0  src0  src1
554     * 1: mov.sat(16)   dst1  (abs)dst0
555     *
556     * = After =
557     * (no changes)
558     */
559 
560    v->calculate_cfg();
561    bblock_t *block0 = v->cfg->blocks[0];
562 
563    EXPECT_EQ(0, block0->start_ip);
564    EXPECT_EQ(1, block0->end_ip);
565 
566    EXPECT_FALSE(saturate_propagation(v));
567    EXPECT_EQ(0, block0->start_ip);
568    EXPECT_EQ(1, block0->end_ip);
569    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
570    EXPECT_FALSE(instruction(block0, 0)->saturate);
571    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
572    EXPECT_TRUE(instruction(block0, 1)->saturate);
573 }
574 
TEST_F(saturate_propagation_test,producer_saturates)575 TEST_F(saturate_propagation_test, producer_saturates)
576 {
577    const fs_builder &bld = v->bld;
578    fs_reg dst0 = v->vgrf(glsl_type::float_type);
579    fs_reg dst1 = v->vgrf(glsl_type::float_type);
580    fs_reg dst2 = v->vgrf(glsl_type::float_type);
581    fs_reg src0 = v->vgrf(glsl_type::float_type);
582    fs_reg src1 = v->vgrf(glsl_type::float_type);
583    set_saturate(true, bld.ADD(dst0, src0, src1));
584    set_saturate(true, bld.MOV(dst1, dst0));
585    bld.MOV(dst2, dst0);
586 
587    /* = Before =
588     *
589     * 0: add.sat(16)   dst0  src0  src1
590     * 1: mov.sat(16)   dst1  dst0
591     * 2: mov(16)       dst2  dst0
592     *
593     * = After =
594     * 0: add.sat(16)   dst0  src0  src1
595     * 1: mov(16)       dst1  dst0
596     * 2: mov(16)       dst2  dst0
597     */
598 
599    v->calculate_cfg();
600    bblock_t *block0 = v->cfg->blocks[0];
601 
602    EXPECT_EQ(0, block0->start_ip);
603    EXPECT_EQ(2, block0->end_ip);
604 
605    EXPECT_TRUE(saturate_propagation(v));
606    EXPECT_EQ(0, block0->start_ip);
607    EXPECT_EQ(2, block0->end_ip);
608    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
609    EXPECT_TRUE(instruction(block0, 0)->saturate);
610    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
611    EXPECT_FALSE(instruction(block0, 1)->saturate);
612 }
613 
TEST_F(saturate_propagation_test,intervening_saturating_copy)614 TEST_F(saturate_propagation_test, intervening_saturating_copy)
615 {
616    const fs_builder &bld = v->bld;
617    fs_reg dst0 = v->vgrf(glsl_type::float_type);
618    fs_reg dst1 = v->vgrf(glsl_type::float_type);
619    fs_reg dst2 = v->vgrf(glsl_type::float_type);
620    fs_reg src0 = v->vgrf(glsl_type::float_type);
621    fs_reg src1 = v->vgrf(glsl_type::float_type);
622    bld.ADD(dst0, src0, src1);
623    set_saturate(true, bld.MOV(dst1, dst0));
624    set_saturate(true, bld.MOV(dst2, dst0));
625 
626    /* = Before =
627     *
628     * 0: add(16)       dst0  src0  src1
629     * 1: mov.sat(16)   dst1  dst0
630     * 2: mov.sat(16)   dst2  dst0
631     *
632     * = After =
633     * 0: add.sat(16)   dst0  src0  src1
634     * 1: mov(16)       dst1  dst0
635     * 2: mov(16)       dst2  dst0
636     */
637 
638    v->calculate_cfg();
639    bblock_t *block0 = v->cfg->blocks[0];
640 
641    EXPECT_EQ(0, block0->start_ip);
642    EXPECT_EQ(2, block0->end_ip);
643 
644    EXPECT_TRUE(saturate_propagation(v));
645    EXPECT_EQ(0, block0->start_ip);
646    EXPECT_EQ(2, block0->end_ip);
647    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
648    EXPECT_TRUE(instruction(block0, 0)->saturate);
649    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
650    EXPECT_FALSE(instruction(block0, 1)->saturate);
651    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
652    EXPECT_FALSE(instruction(block0, 2)->saturate);
653 }
654 
TEST_F(saturate_propagation_test,intervening_dest_write)655 TEST_F(saturate_propagation_test, intervening_dest_write)
656 {
657    const fs_builder &bld = v->bld;
658    fs_reg dst0 = v->vgrf(glsl_type::vec4_type);
659    fs_reg dst1 = v->vgrf(glsl_type::float_type);
660    fs_reg src0 = v->vgrf(glsl_type::float_type);
661    fs_reg src1 = v->vgrf(glsl_type::float_type);
662    fs_reg src2 = v->vgrf(glsl_type::vec2_type);
663    bld.ADD(offset(dst0, bld, 2), src0, src1);
664    bld.emit(SHADER_OPCODE_TEX, dst0, src2)
665       ->size_written = 8 * REG_SIZE;
666    set_saturate(true, bld.MOV(dst1, offset(dst0, bld, 2)));
667 
668    /* = Before =
669     *
670     * 0: add(16)        dst0+2  src0    src1
671     * 1: tex(16) rlen 4 dst0+0  src2
672     * 2: mov.sat(16)    dst1    dst0+2
673     *
674     * = After =
675     * (no changes)
676     */
677 
678    v->calculate_cfg();
679    bblock_t *block0 = v->cfg->blocks[0];
680 
681    EXPECT_EQ(0, block0->start_ip);
682    EXPECT_EQ(2, block0->end_ip);
683 
684    EXPECT_FALSE(saturate_propagation(v));
685    EXPECT_EQ(0, block0->start_ip);
686    EXPECT_EQ(2, block0->end_ip);
687    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
688    EXPECT_FALSE(instruction(block0, 0)->saturate);
689    EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
690    EXPECT_FALSE(instruction(block0, 0)->saturate);
691    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
692    EXPECT_TRUE(instruction(block0, 2)->saturate);
693 }
694 
TEST_F(saturate_propagation_test,mul_neg_mov_sat_mov_sat)695 TEST_F(saturate_propagation_test, mul_neg_mov_sat_mov_sat)
696 {
697    const fs_builder &bld = v->bld;
698    fs_reg dst0 = v->vgrf(glsl_type::float_type);
699    fs_reg dst1 = v->vgrf(glsl_type::float_type);
700    fs_reg dst2 = v->vgrf(glsl_type::float_type);
701    fs_reg src0 = v->vgrf(glsl_type::float_type);
702    fs_reg src1 = v->vgrf(glsl_type::float_type);
703    bld.MUL(dst0, src0, src1);
704    dst0.negate = true;
705    set_saturate(true, bld.MOV(dst1, dst0));
706    dst0.negate = false;
707    set_saturate(true, bld.MOV(dst2, dst0));
708 
709    /* = Before =
710     *
711     * 0: mul(16)       dst0  src0  src1
712     * 1: mov.sat(16)   dst1  -dst0
713     * 2: mov.sat(16)   dst2  dst0
714     *
715     * = After =
716     * (no changes)
717     */
718 
719    v->calculate_cfg();
720    bblock_t *block0 = v->cfg->blocks[0];
721 
722    EXPECT_EQ(0, block0->start_ip);
723    EXPECT_EQ(2, block0->end_ip);
724 
725    EXPECT_FALSE(saturate_propagation(v));
726    EXPECT_EQ(0, block0->start_ip);
727    EXPECT_EQ(2, block0->end_ip);
728    EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
729    EXPECT_FALSE(instruction(block0, 0)->saturate);
730    EXPECT_FALSE(instruction(block0, 0)->src[1].negate);
731    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
732    EXPECT_TRUE(instruction(block0, 1)->saturate);
733    EXPECT_TRUE(instruction(block0, 1)->src[0].negate);
734    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode);
735    EXPECT_TRUE(instruction(block0, 2)->saturate);
736 }
737 
TEST_F(saturate_propagation_test,smaller_exec_size_consumer)738 TEST_F(saturate_propagation_test, smaller_exec_size_consumer)
739 {
740    const fs_builder &bld = v->bld;
741    fs_reg dst0 = v->vgrf(glsl_type::float_type);
742    fs_reg dst1 = v->vgrf(glsl_type::float_type);
743    fs_reg src0 = v->vgrf(glsl_type::float_type);
744    fs_reg src1 = v->vgrf(glsl_type::float_type);
745    bld.ADD(dst0, src0, src1);
746    set_saturate(true, bld.group(8, 0).MOV(dst1, dst0));
747 
748    /* = Before =
749     *
750     * 0: add(16)       dst0  src0  src1
751     * 1: mov.sat(8)    dst1  dst0
752     *
753     * = After =
754     * (no changes)
755     */
756 
757    v->calculate_cfg();
758    bblock_t *block0 = v->cfg->blocks[0];
759 
760    EXPECT_EQ(0, block0->start_ip);
761    EXPECT_EQ(1, block0->end_ip);
762 
763    EXPECT_FALSE(saturate_propagation(v));
764    EXPECT_EQ(0, block0->start_ip);
765    EXPECT_EQ(1, block0->end_ip);
766    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
767    EXPECT_FALSE(instruction(block0, 0)->saturate);
768    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
769    EXPECT_TRUE(instruction(block0, 1)->saturate);
770 }
771 
TEST_F(saturate_propagation_test,larger_exec_size_consumer)772 TEST_F(saturate_propagation_test, larger_exec_size_consumer)
773 {
774    const fs_builder &bld = v->bld;
775    fs_reg dst0 = v->vgrf(glsl_type::float_type);
776    fs_reg dst1 = v->vgrf(glsl_type::float_type);
777    fs_reg src0 = v->vgrf(glsl_type::float_type);
778    fs_reg src1 = v->vgrf(glsl_type::float_type);
779    bld.group(8, 0).ADD(dst0, src0, src1);
780    set_saturate(true, bld.MOV(dst1, dst0));
781 
782    /* = Before =
783     *
784     * 0: add(8)        dst0  src0  src1
785     * 1: mov.sat(16)   dst1  dst0
786     *
787     * = After =
788     * (no changes)
789     */
790 
791    v->calculate_cfg();
792    bblock_t *block0 = v->cfg->blocks[0];
793 
794    EXPECT_EQ(0, block0->start_ip);
795    EXPECT_EQ(1, block0->end_ip);
796 
797    EXPECT_FALSE(saturate_propagation(v));
798    EXPECT_EQ(0, block0->start_ip);
799    EXPECT_EQ(1, block0->end_ip);
800    EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
801    EXPECT_FALSE(instruction(block0, 0)->saturate);
802    EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
803    EXPECT_TRUE(instruction(block0, 1)->saturate);
804 }
805