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