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"
29 class saturate_propagation_test
: public ::testing::Test
{
33 struct brw_context
*brw
;
34 struct gl_context
*ctx
;
35 struct brw_wm_prog_data
*prog_data
;
36 struct gl_shader_program
*shader_prog
;
37 struct brw_fragment_program
*fp
;
41 class saturate_propagation_fs_visitor
: public fs_visitor
44 saturate_propagation_fs_visitor(struct brw_context
*brw
,
45 struct brw_wm_prog_data
*prog_data
,
46 struct gl_shader_program
*shader_prog
)
47 : fs_visitor(brw
, NULL
, NULL
, prog_data
, shader_prog
, NULL
, 8) {}
51 void saturate_propagation_test::SetUp()
53 brw
= (struct brw_context
*)calloc(1, sizeof(*brw
));
56 fp
= ralloc(NULL
, struct brw_fragment_program
);
57 prog_data
= ralloc(NULL
, struct brw_wm_prog_data
);
58 shader_prog
= ralloc(NULL
, struct gl_shader_program
);
60 v
= new saturate_propagation_fs_visitor(brw
, prog_data
, shader_prog
);
62 _mesa_init_fragment_program(ctx
, &fp
->program
, GL_FRAGMENT_SHADER
, 0);
68 instruction(bblock_t
*block
, int num
)
70 fs_inst
*inst
= (fs_inst
*)block
->start();
71 for (int i
= 0; i
< num
; i
++) {
72 inst
= (fs_inst
*)inst
->next
;
78 saturate_propagation(fs_visitor
*v
)
80 const bool print
= false;
83 fprintf(stderr
, "= Before =\n");
87 bool ret
= v
->opt_saturate_propagation();
90 fprintf(stderr
, "\n= After =\n");
97 TEST_F(saturate_propagation_test
, basic
)
99 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
100 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
101 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
102 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
103 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
104 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
109 * 0: add(8) dst0 src0 src1
110 * 1: mov.sat(8) dst1 dst0
113 * 0: add.sat(8) dst0 src0 src1
114 * 1: mov(8) dst1 dst0
118 bblock_t
*block0
= v
->cfg
->blocks
[0];
120 EXPECT_EQ(0, block0
->start_ip
);
121 EXPECT_EQ(1, block0
->end_ip
);
123 EXPECT_TRUE(saturate_propagation(v
));
124 EXPECT_EQ(0, block0
->start_ip
);
125 EXPECT_EQ(1, block0
->end_ip
);
126 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
127 EXPECT_TRUE(instruction(block0
, 0)->saturate
);
128 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
129 EXPECT_FALSE(instruction(block0
, 1)->saturate
);
132 TEST_F(saturate_propagation_test
, other_non_saturated_use
)
134 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
135 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
136 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
137 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
138 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
139 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
140 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
142 v
->emit(BRW_OPCODE_ADD
, dst2
, dst0
, src0
);
146 * 0: add(8) dst0 src0 src1
147 * 1: mov.sat(8) dst1 dst0
148 * 2: add(8) dst2 dst0 src0
155 bblock_t
*block0
= v
->cfg
->blocks
[0];
157 EXPECT_EQ(0, block0
->start_ip
);
158 EXPECT_EQ(2, block0
->end_ip
);
160 EXPECT_FALSE(saturate_propagation(v
));
161 EXPECT_EQ(0, block0
->start_ip
);
162 EXPECT_EQ(2, block0
->end_ip
);
163 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
164 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
165 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
166 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
167 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 2)->opcode
);
170 TEST_F(saturate_propagation_test
, predicated_instruction
)
172 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
173 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
174 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
175 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
176 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
)
177 ->predicate
= BRW_PREDICATE_NORMAL
;
178 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
183 * 0: (+f0) add(8) dst0 src0 src1
184 * 1: mov.sat(8) dst1 dst0
191 bblock_t
*block0
= v
->cfg
->blocks
[0];
193 EXPECT_EQ(0, block0
->start_ip
);
194 EXPECT_EQ(1, block0
->end_ip
);
196 EXPECT_FALSE(saturate_propagation(v
));
197 EXPECT_EQ(0, block0
->start_ip
);
198 EXPECT_EQ(1, block0
->end_ip
);
199 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
200 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
201 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
202 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
205 TEST_F(saturate_propagation_test
, neg_mov_sat
)
207 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
208 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
209 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
210 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
211 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
213 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
218 * 0: add(8) dst0 src0 src1
219 * 1: mov.sat(8) dst1 -dst0
226 bblock_t
*block0
= v
->cfg
->blocks
[0];
228 EXPECT_EQ(0, block0
->start_ip
);
229 EXPECT_EQ(1, block0
->end_ip
);
231 EXPECT_FALSE(saturate_propagation(v
));
232 EXPECT_EQ(0, block0
->start_ip
);
233 EXPECT_EQ(1, block0
->end_ip
);
234 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
235 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
236 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
237 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
240 TEST_F(saturate_propagation_test
, abs_mov_sat
)
242 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
243 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
244 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
245 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
246 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
248 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
253 * 0: add(8) dst0 src0 src1
254 * 1: mov.sat(8) dst1 (abs)dst0
261 bblock_t
*block0
= v
->cfg
->blocks
[0];
263 EXPECT_EQ(0, block0
->start_ip
);
264 EXPECT_EQ(1, block0
->end_ip
);
266 EXPECT_FALSE(saturate_propagation(v
));
267 EXPECT_EQ(0, block0
->start_ip
);
268 EXPECT_EQ(1, block0
->end_ip
);
269 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
270 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
271 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
272 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
275 TEST_F(saturate_propagation_test
, producer_saturates
)
277 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
278 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
279 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
280 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
281 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
282 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
)
284 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
286 v
->emit(BRW_OPCODE_MOV
, dst2
, dst0
);
290 * 0: add.sat(8) dst0 src0 src1
291 * 1: mov.sat(8) dst1 dst0
292 * 2: mov(8) dst2 dst0
295 * 0: add.sat(8) dst0 src0 src1
296 * 1: mov(8) dst1 dst0
297 * 2: mov(8) dst2 dst0
301 bblock_t
*block0
= v
->cfg
->blocks
[0];
303 EXPECT_EQ(0, block0
->start_ip
);
304 EXPECT_EQ(2, block0
->end_ip
);
306 EXPECT_TRUE(saturate_propagation(v
));
307 EXPECT_EQ(0, block0
->start_ip
);
308 EXPECT_EQ(2, block0
->end_ip
);
309 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
310 EXPECT_TRUE(instruction(block0
, 0)->saturate
);
311 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
312 EXPECT_FALSE(instruction(block0
, 1)->saturate
);
315 TEST_F(saturate_propagation_test
, intervening_saturating_copy
)
317 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
318 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
319 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
320 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
321 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
322 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
323 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
325 v
->emit(BRW_OPCODE_MOV
, dst2
, dst0
)
330 * 0: add(8) dst0 src0 src1
331 * 1: mov.sat(8) dst1 dst0
332 * 2: mov.sat(8) dst2 dst0
335 * 0: add.sat(8) dst0 src0 src1
336 * 1: mov(8) dst1 dst0
337 * 2: mov(8) dst2 dst0
341 bblock_t
*block0
= v
->cfg
->blocks
[0];
343 EXPECT_EQ(0, block0
->start_ip
);
344 EXPECT_EQ(2, block0
->end_ip
);
346 EXPECT_TRUE(saturate_propagation(v
));
347 EXPECT_EQ(0, block0
->start_ip
);
348 EXPECT_EQ(2, block0
->end_ip
);
349 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
350 EXPECT_TRUE(instruction(block0
, 0)->saturate
);
351 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
352 EXPECT_FALSE(instruction(block0
, 1)->saturate
);
353 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 2)->opcode
);
354 EXPECT_FALSE(instruction(block0
, 2)->saturate
);
357 TEST_F(saturate_propagation_test
, intervening_dest_write
)
359 fs_reg dst0
= v
->vgrf(glsl_type::vec4_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::vec2_type
);
364 v
->emit(BRW_OPCODE_ADD
, offset(dst0
, 2), src0
, src1
);
365 v
->emit(SHADER_OPCODE_TEX
, dst0
, src2
)
367 v
->emit(BRW_OPCODE_MOV
, dst1
, offset(dst0
, 2))
372 * 0: add(8) dst0+2 src0 src1
373 * 1: tex(8) rlen 4 dst0+0 src2
374 * 2: mov.sat(8) dst1 dst0+2
381 bblock_t
*block0
= v
->cfg
->blocks
[0];
383 EXPECT_EQ(0, block0
->start_ip
);
384 EXPECT_EQ(2, block0
->end_ip
);
386 EXPECT_FALSE(saturate_propagation(v
));
387 EXPECT_EQ(0, block0
->start_ip
);
388 EXPECT_EQ(2, block0
->end_ip
);
389 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
390 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
391 EXPECT_EQ(SHADER_OPCODE_TEX
, instruction(block0
, 1)->opcode
);
392 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
393 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 2)->opcode
);
394 EXPECT_TRUE(instruction(block0
, 2)->saturate
);
397 TEST_F(saturate_propagation_test
, mul_neg_mov_sat_mov_sat
)
399 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
400 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
401 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
402 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
403 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
404 v
->emit(BRW_OPCODE_MUL
, dst0
, src0
, src1
);
406 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
409 v
->emit(BRW_OPCODE_MOV
, dst2
, dst0
)
414 * 0: mul(8) dst0 src0 src1
415 * 1: mov.sat(8) dst1 -dst0
416 * 2: mov.sat(8) dst2 dst0
423 bblock_t
*block0
= v
->cfg
->blocks
[0];
425 EXPECT_EQ(0, block0
->start_ip
);
426 EXPECT_EQ(2, block0
->end_ip
);
428 EXPECT_FALSE(saturate_propagation(v
));
429 EXPECT_EQ(0, block0
->start_ip
);
430 EXPECT_EQ(2, block0
->end_ip
);
431 EXPECT_EQ(BRW_OPCODE_MUL
, instruction(block0
, 0)->opcode
);
432 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
433 EXPECT_FALSE(instruction(block0
, 0)->src
[1].negate
);
434 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
435 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
436 EXPECT_TRUE(instruction(block0
, 1)->src
[0].negate
);
437 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 2)->opcode
);
438 EXPECT_TRUE(instruction(block0
, 2)->saturate
);