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