2 * Copyright © 2015 Intel Corporation
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:
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
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
24 #include <gtest/gtest.h>
27 #include "program/program.h"
31 class saturate_propagation_test
: public ::testing::Test
{
35 struct brw_compiler
*compiler
;
36 struct brw_device_info
*devinfo
;
37 struct gl_context
*ctx
;
38 struct brw_wm_prog_data
*prog_data
;
39 struct gl_shader_program
*shader_prog
;
40 struct brw_fragment_program
*fp
;
44 class saturate_propagation_fs_visitor
: public fs_visitor
47 saturate_propagation_fs_visitor(struct brw_compiler
*compiler
,
48 struct brw_wm_prog_data
*prog_data
,
49 struct gl_shader_program
*shader_prog
)
50 : fs_visitor(compiler
, NULL
, NULL
, MESA_SHADER_FRAGMENT
, NULL
,
51 &prog_data
->base
, shader_prog
,
52 (struct gl_program
*) NULL
, 8, -1) {}
56 void saturate_propagation_test::SetUp()
58 ctx
= (struct gl_context
*)calloc(1, sizeof(*ctx
));
59 compiler
= (struct brw_compiler
*)calloc(1, sizeof(*compiler
));
60 devinfo
= (struct brw_device_info
*)calloc(1, sizeof(*devinfo
));
61 compiler
->devinfo
= devinfo
;
63 fp
= ralloc(NULL
, struct brw_fragment_program
);
64 prog_data
= ralloc(NULL
, struct brw_wm_prog_data
);
65 shader_prog
= ralloc(NULL
, struct gl_shader_program
);
67 v
= new saturate_propagation_fs_visitor(compiler
, prog_data
, shader_prog
);
69 _mesa_init_fragment_program(ctx
, &fp
->program
, GL_FRAGMENT_SHADER
, 0);
75 instruction(bblock_t
*block
, int num
)
77 fs_inst
*inst
= (fs_inst
*)block
->start();
78 for (int i
= 0; i
< num
; i
++) {
79 inst
= (fs_inst
*)inst
->next
;
85 saturate_propagation(fs_visitor
*v
)
87 const bool print
= false;
90 fprintf(stderr
, "= Before =\n");
94 bool ret
= v
->opt_saturate_propagation();
97 fprintf(stderr
, "\n= After =\n");
104 TEST_F(saturate_propagation_test
, basic
)
106 const fs_builder
&bld
= v
->bld
;
107 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
108 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
109 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
110 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
111 bld
.ADD(dst0
, src0
, src1
);
112 set_saturate(true, bld
.MOV(dst1
, dst0
));
116 * 0: add(8) dst0 src0 src1
117 * 1: mov.sat(8) dst1 dst0
120 * 0: add.sat(8) dst0 src0 src1
121 * 1: mov(8) dst1 dst0
125 bblock_t
*block0
= v
->cfg
->blocks
[0];
127 EXPECT_EQ(0, block0
->start_ip
);
128 EXPECT_EQ(1, block0
->end_ip
);
130 EXPECT_TRUE(saturate_propagation(v
));
131 EXPECT_EQ(0, block0
->start_ip
);
132 EXPECT_EQ(1, block0
->end_ip
);
133 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
134 EXPECT_TRUE(instruction(block0
, 0)->saturate
);
135 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
136 EXPECT_FALSE(instruction(block0
, 1)->saturate
);
139 TEST_F(saturate_propagation_test
, other_non_saturated_use
)
141 const fs_builder
&bld
= v
->bld
;
142 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
143 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
144 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
145 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
146 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
147 bld
.ADD(dst0
, src0
, src1
);
148 set_saturate(true, bld
.MOV(dst1
, dst0
));
149 bld
.ADD(dst2
, dst0
, src0
);
153 * 0: add(8) dst0 src0 src1
154 * 1: mov.sat(8) dst1 dst0
155 * 2: add(8) dst2 dst0 src0
162 bblock_t
*block0
= v
->cfg
->blocks
[0];
164 EXPECT_EQ(0, block0
->start_ip
);
165 EXPECT_EQ(2, block0
->end_ip
);
167 EXPECT_FALSE(saturate_propagation(v
));
168 EXPECT_EQ(0, block0
->start_ip
);
169 EXPECT_EQ(2, block0
->end_ip
);
170 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
171 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
172 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
173 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
174 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 2)->opcode
);
177 TEST_F(saturate_propagation_test
, predicated_instruction
)
179 const fs_builder
&bld
= v
->bld
;
180 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
181 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
182 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
183 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
184 bld
.ADD(dst0
, src0
, src1
)
185 ->predicate
= BRW_PREDICATE_NORMAL
;
186 set_saturate(true, bld
.MOV(dst1
, dst0
));
190 * 0: (+f0) add(8) dst0 src0 src1
191 * 1: mov.sat(8) dst1 dst0
198 bblock_t
*block0
= v
->cfg
->blocks
[0];
200 EXPECT_EQ(0, block0
->start_ip
);
201 EXPECT_EQ(1, block0
->end_ip
);
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
);
212 TEST_F(saturate_propagation_test
, neg_mov_sat
)
214 const fs_builder
&bld
= v
->bld
;
215 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
216 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
217 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
218 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
219 bld
.ADD(dst0
, src0
, src1
);
221 set_saturate(true, bld
.MOV(dst1
, dst0
));
225 * 0: add(8) dst0 src0 src1
226 * 1: mov.sat(8) dst1 -dst0
233 bblock_t
*block0
= v
->cfg
->blocks
[0];
235 EXPECT_EQ(0, block0
->start_ip
);
236 EXPECT_EQ(1, block0
->end_ip
);
238 EXPECT_FALSE(saturate_propagation(v
));
239 EXPECT_EQ(0, block0
->start_ip
);
240 EXPECT_EQ(1, block0
->end_ip
);
241 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
242 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
243 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
244 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
247 TEST_F(saturate_propagation_test
, abs_mov_sat
)
249 const fs_builder
&bld
= v
->bld
;
250 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
251 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
252 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
253 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
254 bld
.ADD(dst0
, src0
, src1
);
256 set_saturate(true, bld
.MOV(dst1
, dst0
));
260 * 0: add(8) dst0 src0 src1
261 * 1: mov.sat(8) dst1 (abs)dst0
268 bblock_t
*block0
= v
->cfg
->blocks
[0];
270 EXPECT_EQ(0, block0
->start_ip
);
271 EXPECT_EQ(1, block0
->end_ip
);
273 EXPECT_FALSE(saturate_propagation(v
));
274 EXPECT_EQ(0, block0
->start_ip
);
275 EXPECT_EQ(1, block0
->end_ip
);
276 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
277 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
278 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
279 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
282 TEST_F(saturate_propagation_test
, producer_saturates
)
284 const fs_builder
&bld
= v
->bld
;
285 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
286 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
287 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
288 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
289 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
290 set_saturate(true, bld
.ADD(dst0
, src0
, src1
));
291 set_saturate(true, bld
.MOV(dst1
, dst0
));
296 * 0: add.sat(8) dst0 src0 src1
297 * 1: mov.sat(8) dst1 dst0
298 * 2: mov(8) dst2 dst0
301 * 0: add.sat(8) dst0 src0 src1
302 * 1: mov(8) dst1 dst0
303 * 2: mov(8) dst2 dst0
307 bblock_t
*block0
= v
->cfg
->blocks
[0];
309 EXPECT_EQ(0, block0
->start_ip
);
310 EXPECT_EQ(2, block0
->end_ip
);
312 EXPECT_TRUE(saturate_propagation(v
));
313 EXPECT_EQ(0, block0
->start_ip
);
314 EXPECT_EQ(2, block0
->end_ip
);
315 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
316 EXPECT_TRUE(instruction(block0
, 0)->saturate
);
317 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
318 EXPECT_FALSE(instruction(block0
, 1)->saturate
);
321 TEST_F(saturate_propagation_test
, intervening_saturating_copy
)
323 const fs_builder
&bld
= v
->bld
;
324 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
325 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
326 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
327 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
328 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
329 bld
.ADD(dst0
, src0
, src1
);
330 set_saturate(true, bld
.MOV(dst1
, dst0
));
331 set_saturate(true, bld
.MOV(dst2
, dst0
));
335 * 0: add(8) dst0 src0 src1
336 * 1: mov.sat(8) dst1 dst0
337 * 2: mov.sat(8) dst2 dst0
340 * 0: add.sat(8) dst0 src0 src1
341 * 1: mov(8) dst1 dst0
342 * 2: mov(8) dst2 dst0
346 bblock_t
*block0
= v
->cfg
->blocks
[0];
348 EXPECT_EQ(0, block0
->start_ip
);
349 EXPECT_EQ(2, block0
->end_ip
);
351 EXPECT_TRUE(saturate_propagation(v
));
352 EXPECT_EQ(0, block0
->start_ip
);
353 EXPECT_EQ(2, block0
->end_ip
);
354 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
355 EXPECT_TRUE(instruction(block0
, 0)->saturate
);
356 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
357 EXPECT_FALSE(instruction(block0
, 1)->saturate
);
358 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 2)->opcode
);
359 EXPECT_FALSE(instruction(block0
, 2)->saturate
);
362 TEST_F(saturate_propagation_test
, intervening_dest_write
)
364 const fs_builder
&bld
= v
->bld
;
365 fs_reg dst0
= v
->vgrf(glsl_type::vec4_type
);
366 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
367 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
368 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
369 fs_reg src2
= v
->vgrf(glsl_type::vec2_type
);
370 bld
.ADD(offset(dst0
, bld
, 2), src0
, src1
);
371 bld
.emit(SHADER_OPCODE_TEX
, dst0
, src2
)
373 set_saturate(true, bld
.MOV(dst1
, offset(dst0
, bld
, 2)));
377 * 0: add(8) dst0+2 src0 src1
378 * 1: tex(8) rlen 4 dst0+0 src2
379 * 2: mov.sat(8) dst1 dst0+2
386 bblock_t
*block0
= v
->cfg
->blocks
[0];
388 EXPECT_EQ(0, block0
->start_ip
);
389 EXPECT_EQ(2, block0
->end_ip
);
391 EXPECT_FALSE(saturate_propagation(v
));
392 EXPECT_EQ(0, block0
->start_ip
);
393 EXPECT_EQ(2, block0
->end_ip
);
394 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
395 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
396 EXPECT_EQ(SHADER_OPCODE_TEX
, instruction(block0
, 1)->opcode
);
397 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
398 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 2)->opcode
);
399 EXPECT_TRUE(instruction(block0
, 2)->saturate
);
402 TEST_F(saturate_propagation_test
, mul_neg_mov_sat_mov_sat
)
404 const fs_builder
&bld
= v
->bld
;
405 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
406 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
407 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
408 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
409 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
410 bld
.MUL(dst0
, src0
, src1
);
412 set_saturate(true, bld
.MOV(dst1
, dst0
));
414 set_saturate(true, bld
.MOV(dst2
, dst0
));
418 * 0: mul(8) dst0 src0 src1
419 * 1: mov.sat(8) dst1 -dst0
420 * 2: mov.sat(8) dst2 dst0
427 bblock_t
*block0
= v
->cfg
->blocks
[0];
429 EXPECT_EQ(0, block0
->start_ip
);
430 EXPECT_EQ(2, block0
->end_ip
);
432 EXPECT_FALSE(saturate_propagation(v
));
433 EXPECT_EQ(0, block0
->start_ip
);
434 EXPECT_EQ(2, block0
->end_ip
);
435 EXPECT_EQ(BRW_OPCODE_MUL
, instruction(block0
, 0)->opcode
);
436 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
437 EXPECT_FALSE(instruction(block0
, 0)->src
[1].negate
);
438 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
439 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
440 EXPECT_TRUE(instruction(block0
, 1)->src
[0].negate
);
441 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 2)->opcode
);
442 EXPECT_TRUE(instruction(block0
, 2)->saturate
);