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 brw_device_info
*devinfo
;
35 struct gl_context
*ctx
;
36 struct brw_wm_prog_data
*prog_data
;
37 struct gl_shader_program
*shader_prog
;
38 struct brw_fragment_program
*fp
;
42 class saturate_propagation_fs_visitor
: public fs_visitor
45 saturate_propagation_fs_visitor(struct brw_context
*brw
,
46 struct brw_wm_prog_data
*prog_data
,
47 struct gl_shader_program
*shader_prog
)
48 : fs_visitor(brw
, NULL
, MESA_SHADER_FRAGMENT
, NULL
, &prog_data
->base
,
49 shader_prog
, (struct gl_program
*) NULL
, 8) {}
53 void saturate_propagation_test::SetUp()
55 brw
= (struct brw_context
*)calloc(1, sizeof(*brw
));
56 devinfo
= (struct brw_device_info
*)calloc(1, sizeof(*brw
));
57 brw
->intelScreen
= (struct intel_screen
*)calloc(1, sizeof(*brw
->intelScreen
));
58 brw
->intelScreen
->devinfo
= devinfo
;
61 fp
= ralloc(NULL
, struct brw_fragment_program
);
62 prog_data
= ralloc(NULL
, struct brw_wm_prog_data
);
63 shader_prog
= ralloc(NULL
, struct gl_shader_program
);
65 v
= new saturate_propagation_fs_visitor(brw
, prog_data
, shader_prog
);
67 _mesa_init_fragment_program(ctx
, &fp
->program
, GL_FRAGMENT_SHADER
, 0);
69 brw
->gen
= devinfo
->gen
= 4;
73 instruction(bblock_t
*block
, int num
)
75 fs_inst
*inst
= (fs_inst
*)block
->start();
76 for (int i
= 0; i
< num
; i
++) {
77 inst
= (fs_inst
*)inst
->next
;
83 saturate_propagation(fs_visitor
*v
)
85 const bool print
= false;
88 fprintf(stderr
, "= Before =\n");
92 bool ret
= v
->opt_saturate_propagation();
95 fprintf(stderr
, "\n= After =\n");
102 TEST_F(saturate_propagation_test
, basic
)
104 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
105 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
106 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
107 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
108 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
109 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
114 * 0: add(8) dst0 src0 src1
115 * 1: mov.sat(8) dst1 dst0
118 * 0: add.sat(8) dst0 src0 src1
119 * 1: mov(8) dst1 dst0
123 bblock_t
*block0
= v
->cfg
->blocks
[0];
125 EXPECT_EQ(0, block0
->start_ip
);
126 EXPECT_EQ(1, block0
->end_ip
);
128 EXPECT_TRUE(saturate_propagation(v
));
129 EXPECT_EQ(0, block0
->start_ip
);
130 EXPECT_EQ(1, block0
->end_ip
);
131 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
132 EXPECT_TRUE(instruction(block0
, 0)->saturate
);
133 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
134 EXPECT_FALSE(instruction(block0
, 1)->saturate
);
137 TEST_F(saturate_propagation_test
, other_non_saturated_use
)
139 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
140 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
141 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
142 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
143 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
144 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
145 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
147 v
->emit(BRW_OPCODE_ADD
, dst2
, dst0
, src0
);
151 * 0: add(8) dst0 src0 src1
152 * 1: mov.sat(8) dst1 dst0
153 * 2: add(8) dst2 dst0 src0
160 bblock_t
*block0
= v
->cfg
->blocks
[0];
162 EXPECT_EQ(0, block0
->start_ip
);
163 EXPECT_EQ(2, block0
->end_ip
);
165 EXPECT_FALSE(saturate_propagation(v
));
166 EXPECT_EQ(0, block0
->start_ip
);
167 EXPECT_EQ(2, block0
->end_ip
);
168 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
169 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
170 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
171 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
172 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 2)->opcode
);
175 TEST_F(saturate_propagation_test
, predicated_instruction
)
177 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
178 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
179 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
180 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
181 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
)
182 ->predicate
= BRW_PREDICATE_NORMAL
;
183 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
188 * 0: (+f0) add(8) dst0 src0 src1
189 * 1: mov.sat(8) dst1 dst0
196 bblock_t
*block0
= v
->cfg
->blocks
[0];
198 EXPECT_EQ(0, block0
->start_ip
);
199 EXPECT_EQ(1, block0
->end_ip
);
201 EXPECT_FALSE(saturate_propagation(v
));
202 EXPECT_EQ(0, block0
->start_ip
);
203 EXPECT_EQ(1, block0
->end_ip
);
204 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
205 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
206 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
207 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
210 TEST_F(saturate_propagation_test
, neg_mov_sat
)
212 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
213 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
214 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
215 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
216 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
218 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
223 * 0: add(8) dst0 src0 src1
224 * 1: mov.sat(8) dst1 -dst0
231 bblock_t
*block0
= v
->cfg
->blocks
[0];
233 EXPECT_EQ(0, block0
->start_ip
);
234 EXPECT_EQ(1, block0
->end_ip
);
236 EXPECT_FALSE(saturate_propagation(v
));
237 EXPECT_EQ(0, block0
->start_ip
);
238 EXPECT_EQ(1, block0
->end_ip
);
239 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
240 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
241 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
242 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
245 TEST_F(saturate_propagation_test
, abs_mov_sat
)
247 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
248 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
249 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
250 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
251 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
253 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
258 * 0: add(8) dst0 src0 src1
259 * 1: mov.sat(8) dst1 (abs)dst0
266 bblock_t
*block0
= v
->cfg
->blocks
[0];
268 EXPECT_EQ(0, block0
->start_ip
);
269 EXPECT_EQ(1, block0
->end_ip
);
271 EXPECT_FALSE(saturate_propagation(v
));
272 EXPECT_EQ(0, block0
->start_ip
);
273 EXPECT_EQ(1, block0
->end_ip
);
274 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
275 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
276 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
277 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
280 TEST_F(saturate_propagation_test
, producer_saturates
)
282 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
283 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
284 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
285 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
286 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
287 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
)
289 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
291 v
->emit(BRW_OPCODE_MOV
, dst2
, dst0
);
295 * 0: add.sat(8) dst0 src0 src1
296 * 1: mov.sat(8) dst1 dst0
297 * 2: mov(8) dst2 dst0
300 * 0: add.sat(8) dst0 src0 src1
301 * 1: mov(8) dst1 dst0
302 * 2: mov(8) dst2 dst0
306 bblock_t
*block0
= v
->cfg
->blocks
[0];
308 EXPECT_EQ(0, block0
->start_ip
);
309 EXPECT_EQ(2, block0
->end_ip
);
311 EXPECT_TRUE(saturate_propagation(v
));
312 EXPECT_EQ(0, block0
->start_ip
);
313 EXPECT_EQ(2, block0
->end_ip
);
314 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
315 EXPECT_TRUE(instruction(block0
, 0)->saturate
);
316 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
317 EXPECT_FALSE(instruction(block0
, 1)->saturate
);
320 TEST_F(saturate_propagation_test
, intervening_saturating_copy
)
322 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
323 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
324 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
325 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
326 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
327 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
328 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
330 v
->emit(BRW_OPCODE_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 fs_reg dst0
= v
->vgrf(glsl_type::vec4_type
);
365 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
366 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
367 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
368 fs_reg src2
= v
->vgrf(glsl_type::vec2_type
);
369 v
->emit(BRW_OPCODE_ADD
, offset(dst0
, 2), src0
, src1
);
370 v
->emit(SHADER_OPCODE_TEX
, dst0
, src2
)
372 v
->emit(BRW_OPCODE_MOV
, dst1
, offset(dst0
, 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 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
405 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
406 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
407 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
408 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
409 v
->emit(BRW_OPCODE_MUL
, dst0
, src0
, src1
);
411 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
414 v
->emit(BRW_OPCODE_MOV
, dst2
, dst0
)
419 * 0: mul(8) dst0 src0 src1
420 * 1: mov.sat(8) dst1 -dst0
421 * 2: mov.sat(8) dst2 dst0
428 bblock_t
*block0
= v
->cfg
->blocks
[0];
430 EXPECT_EQ(0, block0
->start_ip
);
431 EXPECT_EQ(2, block0
->end_ip
);
433 EXPECT_FALSE(saturate_propagation(v
));
434 EXPECT_EQ(0, block0
->start_ip
);
435 EXPECT_EQ(2, block0
->end_ip
);
436 EXPECT_EQ(BRW_OPCODE_MUL
, instruction(block0
, 0)->opcode
);
437 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
438 EXPECT_FALSE(instruction(block0
, 0)->src
[1].negate
);
439 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
440 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
441 EXPECT_TRUE(instruction(block0
, 1)->src
[0].negate
);
442 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 2)->opcode
);
443 EXPECT_TRUE(instruction(block0
, 2)->saturate
);