i965/fs: Check ADD/MAD with immediates in satprop unit test
[mesa.git] / src / intel / compiler / test_fs_saturate_propagation.cpp
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:
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
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 }