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
, NULL
, prog_data
, shader_prog
, NULL
, 8) {}
52 void saturate_propagation_test::SetUp()
54 brw
= (struct brw_context
*)calloc(1, sizeof(*brw
));
55 devinfo
= (struct brw_device_info
*)calloc(1, sizeof(*brw
));
56 brw
->intelScreen
= (struct intel_screen
*)calloc(1, sizeof(*brw
->intelScreen
));
57 brw
->intelScreen
->devinfo
= devinfo
;
60 fp
= ralloc(NULL
, struct brw_fragment_program
);
61 prog_data
= ralloc(NULL
, struct brw_wm_prog_data
);
62 shader_prog
= ralloc(NULL
, struct gl_shader_program
);
64 v
= new saturate_propagation_fs_visitor(brw
, prog_data
, shader_prog
);
66 _mesa_init_fragment_program(ctx
, &fp
->program
, GL_FRAGMENT_SHADER
, 0);
68 brw
->gen
= devinfo
->gen
= 4;
72 instruction(bblock_t
*block
, int num
)
74 fs_inst
*inst
= (fs_inst
*)block
->start();
75 for (int i
= 0; i
< num
; i
++) {
76 inst
= (fs_inst
*)inst
->next
;
82 saturate_propagation(fs_visitor
*v
)
84 const bool print
= false;
87 fprintf(stderr
, "= Before =\n");
91 bool ret
= v
->opt_saturate_propagation();
94 fprintf(stderr
, "\n= After =\n");
101 TEST_F(saturate_propagation_test
, basic
)
103 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
104 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
105 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
106 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
107 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
108 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
113 * 0: add(8) dst0 src0 src1
114 * 1: mov.sat(8) dst1 dst0
117 * 0: add.sat(8) dst0 src0 src1
118 * 1: mov(8) dst1 dst0
122 bblock_t
*block0
= v
->cfg
->blocks
[0];
124 EXPECT_EQ(0, block0
->start_ip
);
125 EXPECT_EQ(1, block0
->end_ip
);
127 EXPECT_TRUE(saturate_propagation(v
));
128 EXPECT_EQ(0, block0
->start_ip
);
129 EXPECT_EQ(1, block0
->end_ip
);
130 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
131 EXPECT_TRUE(instruction(block0
, 0)->saturate
);
132 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
133 EXPECT_FALSE(instruction(block0
, 1)->saturate
);
136 TEST_F(saturate_propagation_test
, other_non_saturated_use
)
138 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
139 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
140 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
141 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
142 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
143 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
144 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
146 v
->emit(BRW_OPCODE_ADD
, dst2
, dst0
, src0
);
150 * 0: add(8) dst0 src0 src1
151 * 1: mov.sat(8) dst1 dst0
152 * 2: add(8) dst2 dst0 src0
159 bblock_t
*block0
= v
->cfg
->blocks
[0];
161 EXPECT_EQ(0, block0
->start_ip
);
162 EXPECT_EQ(2, block0
->end_ip
);
164 EXPECT_FALSE(saturate_propagation(v
));
165 EXPECT_EQ(0, block0
->start_ip
);
166 EXPECT_EQ(2, block0
->end_ip
);
167 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
168 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
169 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
170 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
171 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 2)->opcode
);
174 TEST_F(saturate_propagation_test
, predicated_instruction
)
176 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
177 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
178 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
179 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
180 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
)
181 ->predicate
= BRW_PREDICATE_NORMAL
;
182 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
187 * 0: (+f0) add(8) dst0 src0 src1
188 * 1: mov.sat(8) dst1 dst0
195 bblock_t
*block0
= v
->cfg
->blocks
[0];
197 EXPECT_EQ(0, block0
->start_ip
);
198 EXPECT_EQ(1, block0
->end_ip
);
200 EXPECT_FALSE(saturate_propagation(v
));
201 EXPECT_EQ(0, block0
->start_ip
);
202 EXPECT_EQ(1, block0
->end_ip
);
203 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
204 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
205 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
206 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
209 TEST_F(saturate_propagation_test
, neg_mov_sat
)
211 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
212 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
213 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
214 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
215 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
217 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
222 * 0: add(8) dst0 src0 src1
223 * 1: mov.sat(8) dst1 -dst0
230 bblock_t
*block0
= v
->cfg
->blocks
[0];
232 EXPECT_EQ(0, block0
->start_ip
);
233 EXPECT_EQ(1, block0
->end_ip
);
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_ADD
, 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
);
244 TEST_F(saturate_propagation_test
, abs_mov_sat
)
246 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
247 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
248 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
249 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
250 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
252 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
257 * 0: add(8) dst0 src0 src1
258 * 1: mov.sat(8) dst1 (abs)dst0
265 bblock_t
*block0
= v
->cfg
->blocks
[0];
267 EXPECT_EQ(0, block0
->start_ip
);
268 EXPECT_EQ(1, block0
->end_ip
);
270 EXPECT_FALSE(saturate_propagation(v
));
271 EXPECT_EQ(0, block0
->start_ip
);
272 EXPECT_EQ(1, block0
->end_ip
);
273 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
274 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
275 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
276 EXPECT_TRUE(instruction(block0
, 1)->saturate
);
279 TEST_F(saturate_propagation_test
, producer_saturates
)
281 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
282 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
283 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
284 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
285 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
286 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
)
288 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
290 v
->emit(BRW_OPCODE_MOV
, dst2
, dst0
);
294 * 0: add.sat(8) dst0 src0 src1
295 * 1: mov.sat(8) dst1 dst0
296 * 2: mov(8) dst2 dst0
299 * 0: add.sat(8) dst0 src0 src1
300 * 1: mov(8) dst1 dst0
301 * 2: mov(8) dst2 dst0
305 bblock_t
*block0
= v
->cfg
->blocks
[0];
307 EXPECT_EQ(0, block0
->start_ip
);
308 EXPECT_EQ(2, block0
->end_ip
);
310 EXPECT_TRUE(saturate_propagation(v
));
311 EXPECT_EQ(0, block0
->start_ip
);
312 EXPECT_EQ(2, block0
->end_ip
);
313 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
314 EXPECT_TRUE(instruction(block0
, 0)->saturate
);
315 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
316 EXPECT_FALSE(instruction(block0
, 1)->saturate
);
319 TEST_F(saturate_propagation_test
, intervening_saturating_copy
)
321 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
322 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
323 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
324 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
325 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
326 v
->emit(BRW_OPCODE_ADD
, dst0
, src0
, src1
);
327 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
329 v
->emit(BRW_OPCODE_MOV
, dst2
, dst0
)
334 * 0: add(8) dst0 src0 src1
335 * 1: mov.sat(8) dst1 dst0
336 * 2: mov.sat(8) dst2 dst0
339 * 0: add.sat(8) dst0 src0 src1
340 * 1: mov(8) dst1 dst0
341 * 2: mov(8) dst2 dst0
345 bblock_t
*block0
= v
->cfg
->blocks
[0];
347 EXPECT_EQ(0, block0
->start_ip
);
348 EXPECT_EQ(2, block0
->end_ip
);
350 EXPECT_TRUE(saturate_propagation(v
));
351 EXPECT_EQ(0, block0
->start_ip
);
352 EXPECT_EQ(2, block0
->end_ip
);
353 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
354 EXPECT_TRUE(instruction(block0
, 0)->saturate
);
355 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 1)->opcode
);
356 EXPECT_FALSE(instruction(block0
, 1)->saturate
);
357 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 2)->opcode
);
358 EXPECT_FALSE(instruction(block0
, 2)->saturate
);
361 TEST_F(saturate_propagation_test
, intervening_dest_write
)
363 fs_reg dst0
= v
->vgrf(glsl_type::vec4_type
);
364 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
365 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
366 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
367 fs_reg src2
= v
->vgrf(glsl_type::vec2_type
);
368 v
->emit(BRW_OPCODE_ADD
, offset(dst0
, 2), src0
, src1
);
369 v
->emit(SHADER_OPCODE_TEX
, dst0
, src2
)
371 v
->emit(BRW_OPCODE_MOV
, dst1
, offset(dst0
, 2))
376 * 0: add(8) dst0+2 src0 src1
377 * 1: tex(8) rlen 4 dst0+0 src2
378 * 2: mov.sat(8) dst1 dst0+2
385 bblock_t
*block0
= v
->cfg
->blocks
[0];
387 EXPECT_EQ(0, block0
->start_ip
);
388 EXPECT_EQ(2, block0
->end_ip
);
390 EXPECT_FALSE(saturate_propagation(v
));
391 EXPECT_EQ(0, block0
->start_ip
);
392 EXPECT_EQ(2, block0
->end_ip
);
393 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
394 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
395 EXPECT_EQ(SHADER_OPCODE_TEX
, instruction(block0
, 1)->opcode
);
396 EXPECT_FALSE(instruction(block0
, 0)->saturate
);
397 EXPECT_EQ(BRW_OPCODE_MOV
, instruction(block0
, 2)->opcode
);
398 EXPECT_TRUE(instruction(block0
, 2)->saturate
);
401 TEST_F(saturate_propagation_test
, mul_neg_mov_sat_mov_sat
)
403 fs_reg dst0
= v
->vgrf(glsl_type::float_type
);
404 fs_reg dst1
= v
->vgrf(glsl_type::float_type
);
405 fs_reg dst2
= v
->vgrf(glsl_type::float_type
);
406 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
407 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
408 v
->emit(BRW_OPCODE_MUL
, dst0
, src0
, src1
);
410 v
->emit(BRW_OPCODE_MOV
, dst1
, dst0
)
413 v
->emit(BRW_OPCODE_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
);