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