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