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