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