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 cmod_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 cmod_propagation_fs_visitor
: public fs_visitor
44 cmod_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 cmod_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 cmod_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 cmod_propagation(fs_visitor
*v
)
80 const bool print
= false;
83 fprintf(stderr
, "= Before =\n");
87 bool ret
= v
->opt_cmod_propagation();
90 fprintf(stderr
, "\n= After =\n");
97 TEST_F(cmod_propagation_test
, basic
)
99 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
100 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
101 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
103 v
->emit(BRW_OPCODE_ADD
, dest
, src0
, src1
);
104 v
->emit(BRW_OPCODE_CMP
, v
->reg_null_f
, dest
, zero
)
105 ->conditional_mod
= BRW_CONDITIONAL_GE
;
109 * 0: add(8) dest src0 src1
110 * 1: cmp.ge.f0(8) null dest 0.0f
113 * 0: add.ge.f0(8) dest src0 src1
117 bblock_t
*block0
= v
->cfg
->blocks
[0];
119 EXPECT_EQ(0, block0
->start_ip
);
120 EXPECT_EQ(1, block0
->end_ip
);
122 EXPECT_TRUE(cmod_propagation(v
));
123 EXPECT_EQ(0, block0
->start_ip
);
124 EXPECT_EQ(0, block0
->end_ip
);
125 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
126 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 0)->conditional_mod
);
129 TEST_F(cmod_propagation_test
, cmp_nonzero
)
131 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
132 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
133 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
134 fs_reg
nonzero(1.0f
);
135 v
->emit(BRW_OPCODE_ADD
, dest
, src0
, src1
);
136 v
->emit(BRW_OPCODE_CMP
, v
->reg_null_f
, dest
, nonzero
)
137 ->conditional_mod
= BRW_CONDITIONAL_GE
;
141 * 0: add(8) dest src0 src1
142 * 1: cmp.ge.f0(8) null dest 1.0f
149 bblock_t
*block0
= v
->cfg
->blocks
[0];
151 EXPECT_EQ(0, block0
->start_ip
);
152 EXPECT_EQ(1, block0
->end_ip
);
154 EXPECT_FALSE(cmod_propagation(v
));
155 EXPECT_EQ(0, block0
->start_ip
);
156 EXPECT_EQ(1, block0
->end_ip
);
157 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
158 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
159 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
162 TEST_F(cmod_propagation_test
, non_cmod_instruction
)
164 fs_reg dest
= v
->vgrf(glsl_type::uint_type
);
165 fs_reg src0
= v
->vgrf(glsl_type::uint_type
);
167 v
->emit(BRW_OPCODE_FBL
, dest
, src0
);
168 v
->emit(BRW_OPCODE_CMP
, v
->reg_null_ud
, dest
, zero
)
169 ->conditional_mod
= BRW_CONDITIONAL_GE
;
173 * 0: fbl(8) dest src0
174 * 1: cmp.ge.f0(8) null dest 0u
181 bblock_t
*block0
= v
->cfg
->blocks
[0];
183 EXPECT_EQ(0, block0
->start_ip
);
184 EXPECT_EQ(1, block0
->end_ip
);
186 EXPECT_FALSE(cmod_propagation(v
));
187 EXPECT_EQ(0, block0
->start_ip
);
188 EXPECT_EQ(1, block0
->end_ip
);
189 EXPECT_EQ(BRW_OPCODE_FBL
, instruction(block0
, 0)->opcode
);
190 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
191 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
194 TEST_F(cmod_propagation_test
, intervening_flag_write
)
196 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
197 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
198 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
199 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
201 v
->emit(BRW_OPCODE_ADD
, dest
, src0
, src1
);
202 v
->emit(BRW_OPCODE_CMP
, v
->reg_null_f
, src2
, zero
)
203 ->conditional_mod
= BRW_CONDITIONAL_GE
;
204 v
->emit(BRW_OPCODE_CMP
, v
->reg_null_f
, dest
, zero
)
205 ->conditional_mod
= BRW_CONDITIONAL_GE
;
209 * 0: add(8) dest src0 src1
210 * 1: cmp.ge.f0(8) null src2 0.0f
211 * 2: cmp.ge.f0(8) null dest 0.0f
218 bblock_t
*block0
= v
->cfg
->blocks
[0];
220 EXPECT_EQ(0, block0
->start_ip
);
221 EXPECT_EQ(2, block0
->end_ip
);
223 EXPECT_FALSE(cmod_propagation(v
));
224 EXPECT_EQ(0, block0
->start_ip
);
225 EXPECT_EQ(2, block0
->end_ip
);
226 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
227 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
228 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
229 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
230 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
233 TEST_F(cmod_propagation_test
, intervening_flag_read
)
235 fs_reg dest0
= v
->vgrf(glsl_type::float_type
);
236 fs_reg dest1
= v
->vgrf(glsl_type::float_type
);
237 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
238 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
239 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
241 v
->emit(BRW_OPCODE_ADD
, dest0
, src0
, src1
);
242 v
->emit(BRW_OPCODE_SEL
, dest1
, src2
, zero
)
243 ->predicate
= BRW_PREDICATE_NORMAL
;
244 v
->emit(BRW_OPCODE_CMP
, v
->reg_null_f
, dest0
, zero
)
245 ->conditional_mod
= BRW_CONDITIONAL_GE
;
249 * 0: add(8) dest0 src0 src1
250 * 1: (+f0) sel(8) dest1 src2 0.0f
251 * 2: cmp.ge.f0(8) null dest0 0.0f
258 bblock_t
*block0
= v
->cfg
->blocks
[0];
260 EXPECT_EQ(0, block0
->start_ip
);
261 EXPECT_EQ(2, block0
->end_ip
);
263 EXPECT_FALSE(cmod_propagation(v
));
264 EXPECT_EQ(0, block0
->start_ip
);
265 EXPECT_EQ(2, block0
->end_ip
);
266 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
267 EXPECT_EQ(BRW_OPCODE_SEL
, instruction(block0
, 1)->opcode
);
268 EXPECT_EQ(BRW_PREDICATE_NORMAL
, instruction(block0
, 1)->predicate
);
269 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
270 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
273 TEST_F(cmod_propagation_test
, intervening_dest_write
)
275 fs_reg dest
= v
->vgrf(glsl_type::vec4_type
);
276 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
277 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
278 fs_reg src2
= v
->vgrf(glsl_type::vec2_type
);
280 v
->emit(BRW_OPCODE_ADD
, offset(dest
, 2), src0
, src1
);
281 v
->emit(SHADER_OPCODE_TEX
, dest
, src2
)
283 v
->emit(BRW_OPCODE_CMP
, v
->reg_null_f
, offset(dest
, 2), zero
)
284 ->conditional_mod
= BRW_CONDITIONAL_GE
;
288 * 0: add(8) dest+2 src0 src1
289 * 1: tex(8) rlen 4 dest+0 src2
290 * 2: cmp.ge.f0(8) null dest+2 0.0f
297 bblock_t
*block0
= v
->cfg
->blocks
[0];
299 EXPECT_EQ(0, block0
->start_ip
);
300 EXPECT_EQ(2, block0
->end_ip
);
302 EXPECT_FALSE(cmod_propagation(v
));
303 EXPECT_EQ(0, block0
->start_ip
);
304 EXPECT_EQ(2, block0
->end_ip
);
305 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
306 EXPECT_EQ(BRW_CONDITIONAL_NONE
, instruction(block0
, 0)->conditional_mod
);
307 EXPECT_EQ(SHADER_OPCODE_TEX
, instruction(block0
, 1)->opcode
);
308 EXPECT_EQ(BRW_CONDITIONAL_NONE
, instruction(block0
, 0)->conditional_mod
);
309 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
310 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
313 TEST_F(cmod_propagation_test
, intervening_flag_read_same_value
)
315 fs_reg dest0
= v
->vgrf(glsl_type::float_type
);
316 fs_reg dest1
= v
->vgrf(glsl_type::float_type
);
317 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
318 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
319 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
321 v
->emit(BRW_OPCODE_ADD
, dest0
, src0
, src1
)
322 ->conditional_mod
= BRW_CONDITIONAL_GE
;
323 v
->emit(BRW_OPCODE_SEL
, dest1
, src2
, zero
)
324 ->predicate
= BRW_PREDICATE_NORMAL
;
325 v
->emit(BRW_OPCODE_CMP
, v
->reg_null_f
, dest0
, zero
)
326 ->conditional_mod
= BRW_CONDITIONAL_GE
;
330 * 0: add.ge.f0(8) dest0 src0 src1
331 * 1: (+f0) sel(8) dest1 src2 0.0f
332 * 2: cmp.ge.f0(8) null dest0 0.0f
335 * 0: add.ge.f0(8) dest0 src0 src1
336 * 1: (+f0) sel(8) dest1 src2 0.0f
340 bblock_t
*block0
= v
->cfg
->blocks
[0];
342 EXPECT_EQ(0, block0
->start_ip
);
343 EXPECT_EQ(2, block0
->end_ip
);
345 EXPECT_TRUE(cmod_propagation(v
));
346 EXPECT_EQ(0, block0
->start_ip
);
347 EXPECT_EQ(1, block0
->end_ip
);
348 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
349 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 0)->conditional_mod
);
350 EXPECT_EQ(BRW_OPCODE_SEL
, instruction(block0
, 1)->opcode
);
351 EXPECT_EQ(BRW_PREDICATE_NORMAL
, instruction(block0
, 1)->predicate
);
354 TEST_F(cmod_propagation_test
, negate
)
356 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
357 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
358 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
360 v
->emit(BRW_OPCODE_ADD
, dest
, src0
, src1
);
362 v
->emit(BRW_OPCODE_CMP
, v
->reg_null_f
, dest
, zero
)
363 ->conditional_mod
= BRW_CONDITIONAL_GE
;
367 * 0: add(8) dest src0 src1
368 * 1: cmp.ge.f0(8) null -dest 0.0f
371 * 0: add.le.f0(8) dest src0 src1
375 bblock_t
*block0
= v
->cfg
->blocks
[0];
377 EXPECT_EQ(0, block0
->start_ip
);
378 EXPECT_EQ(1, block0
->end_ip
);
380 EXPECT_TRUE(cmod_propagation(v
));
381 EXPECT_EQ(0, block0
->start_ip
);
382 EXPECT_EQ(0, block0
->end_ip
);
383 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
384 EXPECT_EQ(BRW_CONDITIONAL_LE
, instruction(block0
, 0)->conditional_mod
);
387 TEST_F(cmod_propagation_test
, movnz
)
389 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
390 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
391 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
392 v
->emit(BRW_OPCODE_CMP
, dest
, src0
, src1
)
393 ->conditional_mod
= BRW_CONDITIONAL_GE
;
394 v
->emit(BRW_OPCODE_MOV
, v
->reg_null_f
, dest
)
395 ->conditional_mod
= BRW_CONDITIONAL_NZ
;
399 * 0: cmp.ge.f0(8) dest src0 src1
400 * 1: mov.nz.f0(8) null dest
403 * 0: cmp.ge.f0(8) dest src0 src1
407 bblock_t
*block0
= v
->cfg
->blocks
[0];
409 EXPECT_EQ(0, block0
->start_ip
);
410 EXPECT_EQ(1, block0
->end_ip
);
412 EXPECT_TRUE(cmod_propagation(v
));
413 EXPECT_EQ(0, block0
->start_ip
);
414 EXPECT_EQ(0, block0
->end_ip
);
415 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
416 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 0)->conditional_mod
);
419 TEST_F(cmod_propagation_test
, different_types_cmod_with_zero
)
421 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
422 fs_reg src0
= v
->vgrf(glsl_type::int_type
);
423 fs_reg src1
= v
->vgrf(glsl_type::int_type
);
425 v
->emit(BRW_OPCODE_ADD
, dest
, src0
, src1
);
426 v
->emit(BRW_OPCODE_CMP
, v
->reg_null_f
, retype(dest
, BRW_REGISTER_TYPE_F
),
428 ->conditional_mod
= BRW_CONDITIONAL_GE
;
432 * 0: add(8) dest:D src0:D src1:D
433 * 1: cmp.ge.f0(8) null:F dest:F 0.0f
440 bblock_t
*block0
= v
->cfg
->blocks
[0];
442 EXPECT_EQ(0, block0
->start_ip
);
443 EXPECT_EQ(1, block0
->end_ip
);
445 EXPECT_FALSE(cmod_propagation(v
));
446 EXPECT_EQ(0, block0
->start_ip
);
447 EXPECT_EQ(1, block0
->end_ip
);
448 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
449 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
450 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
453 TEST_F(cmod_propagation_test
, andnz_one
)
455 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
456 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
460 v
->emit(BRW_OPCODE_CMP
, retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
)
461 ->conditional_mod
= BRW_CONDITIONAL_L
;
462 v
->emit(BRW_OPCODE_AND
, v
->reg_null_d
, dest
, one
)
463 ->conditional_mod
= BRW_CONDITIONAL_NZ
;
466 * 0: cmp.l.f0(8) dest:F src0:F 0F
467 * 1: and.nz.f0(8) null:D dest:D 1D
470 * 0: cmp.l.f0(8) dest:F src0:F 0F
474 bblock_t
*block0
= v
->cfg
->blocks
[0];
476 EXPECT_EQ(0, block0
->start_ip
);
477 EXPECT_EQ(1, block0
->end_ip
);
479 EXPECT_TRUE(cmod_propagation(v
));
480 EXPECT_EQ(0, block0
->start_ip
);
481 EXPECT_EQ(0, block0
->end_ip
);
482 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
483 EXPECT_EQ(BRW_CONDITIONAL_L
, instruction(block0
, 0)->conditional_mod
);
484 EXPECT_TRUE(retype(dest
, BRW_REGISTER_TYPE_F
)
485 .equals(instruction(block0
, 0)->dst
));
488 TEST_F(cmod_propagation_test
, andnz_non_one
)
490 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
491 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
495 v
->emit(BRW_OPCODE_CMP
, retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
)
496 ->conditional_mod
= BRW_CONDITIONAL_L
;
497 v
->emit(BRW_OPCODE_AND
, v
->reg_null_d
, dest
, nonone
)
498 ->conditional_mod
= BRW_CONDITIONAL_NZ
;
501 * 0: cmp.l.f0(8) dest:F src0:F 0F
502 * 1: and.nz.f0(8) null:D dest:D 38D
509 bblock_t
*block0
= v
->cfg
->blocks
[0];
511 EXPECT_EQ(0, block0
->start_ip
);
512 EXPECT_EQ(1, block0
->end_ip
);
514 EXPECT_FALSE(cmod_propagation(v
));
515 EXPECT_EQ(0, block0
->start_ip
);
516 EXPECT_EQ(1, block0
->end_ip
);
517 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
518 EXPECT_EQ(BRW_CONDITIONAL_L
, instruction(block0
, 0)->conditional_mod
);
519 EXPECT_EQ(BRW_OPCODE_AND
, instruction(block0
, 1)->opcode
);
520 EXPECT_EQ(BRW_CONDITIONAL_NZ
, instruction(block0
, 1)->conditional_mod
);
523 TEST_F(cmod_propagation_test
, andz_one
)
525 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
526 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
530 v
->emit(BRW_OPCODE_CMP
, retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
)
531 ->conditional_mod
= BRW_CONDITIONAL_L
;
532 v
->emit(BRW_OPCODE_AND
, v
->reg_null_d
, dest
, one
)
533 ->conditional_mod
= BRW_CONDITIONAL_Z
;
536 * 0: cmp.l.f0(8) dest:F src0:F 0F
537 * 1: and.z.f0(8) null:D dest:D 1D
544 bblock_t
*block0
= v
->cfg
->blocks
[0];
546 EXPECT_EQ(0, block0
->start_ip
);
547 EXPECT_EQ(1, block0
->end_ip
);
549 EXPECT_FALSE(cmod_propagation(v
));
550 EXPECT_EQ(0, block0
->start_ip
);
551 EXPECT_EQ(1, block0
->end_ip
);
552 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
553 EXPECT_EQ(BRW_CONDITIONAL_L
, instruction(block0
, 0)->conditional_mod
);
554 EXPECT_EQ(BRW_OPCODE_AND
, instruction(block0
, 1)->opcode
);
555 EXPECT_EQ(BRW_CONDITIONAL_EQ
, instruction(block0
, 1)->conditional_mod
);