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 cmod_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 cmod_propagation_fs_visitor
: public fs_visitor
47 cmod_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 cmod_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 cmod_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 cmod_propagation(fs_visitor
*v
)
87 const bool print
= false;
90 fprintf(stderr
, "= Before =\n");
94 bool ret
= v
->opt_cmod_propagation();
97 fprintf(stderr
, "\n= After =\n");
104 TEST_F(cmod_propagation_test
, basic
)
106 const fs_builder
&bld
= v
->bld
;
107 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
108 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
109 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
111 bld
.ADD(dest
, src0
, src1
);
112 bld
.CMP(bld
.null_reg_f(), dest
, zero
, BRW_CONDITIONAL_GE
);
116 * 0: add(8) dest src0 src1
117 * 1: cmp.ge.f0(8) null dest 0.0f
120 * 0: add.ge.f0(8) dest src0 src1
124 bblock_t
*block0
= v
->cfg
->blocks
[0];
126 EXPECT_EQ(0, block0
->start_ip
);
127 EXPECT_EQ(1, block0
->end_ip
);
129 EXPECT_TRUE(cmod_propagation(v
));
130 EXPECT_EQ(0, block0
->start_ip
);
131 EXPECT_EQ(0, block0
->end_ip
);
132 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
133 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 0)->conditional_mod
);
136 TEST_F(cmod_propagation_test
, cmp_nonzero
)
138 const fs_builder
&bld
= v
->bld
;
139 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
140 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
141 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
142 fs_reg
nonzero(1.0f
);
143 bld
.ADD(dest
, src0
, src1
);
144 bld
.CMP(bld
.null_reg_f(), dest
, nonzero
, BRW_CONDITIONAL_GE
);
148 * 0: add(8) dest src0 src1
149 * 1: cmp.ge.f0(8) null dest 1.0f
156 bblock_t
*block0
= v
->cfg
->blocks
[0];
158 EXPECT_EQ(0, block0
->start_ip
);
159 EXPECT_EQ(1, block0
->end_ip
);
161 EXPECT_FALSE(cmod_propagation(v
));
162 EXPECT_EQ(0, block0
->start_ip
);
163 EXPECT_EQ(1, block0
->end_ip
);
164 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
165 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
166 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
169 TEST_F(cmod_propagation_test
, non_cmod_instruction
)
171 const fs_builder
&bld
= v
->bld
;
172 fs_reg dest
= v
->vgrf(glsl_type::uint_type
);
173 fs_reg src0
= v
->vgrf(glsl_type::uint_type
);
176 bld
.CMP(bld
.null_reg_ud(), dest
, zero
, BRW_CONDITIONAL_GE
);
180 * 0: fbl(8) dest src0
181 * 1: cmp.ge.f0(8) null dest 0u
188 bblock_t
*block0
= v
->cfg
->blocks
[0];
190 EXPECT_EQ(0, block0
->start_ip
);
191 EXPECT_EQ(1, block0
->end_ip
);
193 EXPECT_FALSE(cmod_propagation(v
));
194 EXPECT_EQ(0, block0
->start_ip
);
195 EXPECT_EQ(1, block0
->end_ip
);
196 EXPECT_EQ(BRW_OPCODE_FBL
, instruction(block0
, 0)->opcode
);
197 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
198 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
201 TEST_F(cmod_propagation_test
, intervening_flag_write
)
203 const fs_builder
&bld
= v
->bld
;
204 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
205 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
206 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
207 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
209 bld
.ADD(dest
, src0
, src1
);
210 bld
.CMP(bld
.null_reg_f(), src2
, zero
, BRW_CONDITIONAL_GE
);
211 bld
.CMP(bld
.null_reg_f(), dest
, zero
, BRW_CONDITIONAL_GE
);
215 * 0: add(8) dest src0 src1
216 * 1: cmp.ge.f0(8) null src2 0.0f
217 * 2: cmp.ge.f0(8) null dest 0.0f
224 bblock_t
*block0
= v
->cfg
->blocks
[0];
226 EXPECT_EQ(0, block0
->start_ip
);
227 EXPECT_EQ(2, block0
->end_ip
);
229 EXPECT_FALSE(cmod_propagation(v
));
230 EXPECT_EQ(0, block0
->start_ip
);
231 EXPECT_EQ(2, block0
->end_ip
);
232 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
233 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
234 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
235 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
236 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
239 TEST_F(cmod_propagation_test
, intervening_flag_read
)
241 const fs_builder
&bld
= v
->bld
;
242 fs_reg dest0
= v
->vgrf(glsl_type::float_type
);
243 fs_reg dest1
= 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 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
248 bld
.ADD(dest0
, src0
, src1
);
249 set_predicate(BRW_PREDICATE_NORMAL
, bld
.SEL(dest1
, src2
, zero
));
250 bld
.CMP(bld
.null_reg_f(), dest0
, zero
, BRW_CONDITIONAL_GE
);
254 * 0: add(8) dest0 src0 src1
255 * 1: (+f0) sel(8) dest1 src2 0.0f
256 * 2: cmp.ge.f0(8) null dest0 0.0f
263 bblock_t
*block0
= v
->cfg
->blocks
[0];
265 EXPECT_EQ(0, block0
->start_ip
);
266 EXPECT_EQ(2, block0
->end_ip
);
268 EXPECT_FALSE(cmod_propagation(v
));
269 EXPECT_EQ(0, block0
->start_ip
);
270 EXPECT_EQ(2, block0
->end_ip
);
271 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
272 EXPECT_EQ(BRW_OPCODE_SEL
, instruction(block0
, 1)->opcode
);
273 EXPECT_EQ(BRW_PREDICATE_NORMAL
, instruction(block0
, 1)->predicate
);
274 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
275 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
278 TEST_F(cmod_propagation_test
, intervening_dest_write
)
280 const fs_builder
&bld
= v
->bld
;
281 fs_reg dest
= v
->vgrf(glsl_type::vec4_type
);
282 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
283 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
284 fs_reg src2
= v
->vgrf(glsl_type::vec2_type
);
286 bld
.ADD(offset(dest
, bld
, 2), src0
, src1
);
287 bld
.emit(SHADER_OPCODE_TEX
, dest
, src2
)
289 bld
.CMP(bld
.null_reg_f(), offset(dest
, bld
, 2), zero
, BRW_CONDITIONAL_GE
);
293 * 0: add(8) dest+2 src0 src1
294 * 1: tex(8) rlen 4 dest+0 src2
295 * 2: cmp.ge.f0(8) null dest+2 0.0f
302 bblock_t
*block0
= v
->cfg
->blocks
[0];
304 EXPECT_EQ(0, block0
->start_ip
);
305 EXPECT_EQ(2, block0
->end_ip
);
307 EXPECT_FALSE(cmod_propagation(v
));
308 EXPECT_EQ(0, block0
->start_ip
);
309 EXPECT_EQ(2, block0
->end_ip
);
310 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
311 EXPECT_EQ(BRW_CONDITIONAL_NONE
, instruction(block0
, 0)->conditional_mod
);
312 EXPECT_EQ(SHADER_OPCODE_TEX
, instruction(block0
, 1)->opcode
);
313 EXPECT_EQ(BRW_CONDITIONAL_NONE
, instruction(block0
, 0)->conditional_mod
);
314 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
315 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
318 TEST_F(cmod_propagation_test
, intervening_flag_read_same_value
)
320 const fs_builder
&bld
= v
->bld
;
321 fs_reg dest0
= v
->vgrf(glsl_type::float_type
);
322 fs_reg dest1
= v
->vgrf(glsl_type::float_type
);
323 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
324 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
325 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
327 set_condmod(BRW_CONDITIONAL_GE
, bld
.ADD(dest0
, src0
, src1
));
328 set_predicate(BRW_PREDICATE_NORMAL
, bld
.SEL(dest1
, src2
, zero
));
329 bld
.CMP(bld
.null_reg_f(), dest0
, zero
, BRW_CONDITIONAL_GE
);
333 * 0: add.ge.f0(8) dest0 src0 src1
334 * 1: (+f0) sel(8) dest1 src2 0.0f
335 * 2: cmp.ge.f0(8) null dest0 0.0f
338 * 0: add.ge.f0(8) dest0 src0 src1
339 * 1: (+f0) sel(8) dest1 src2 0.0f
343 bblock_t
*block0
= v
->cfg
->blocks
[0];
345 EXPECT_EQ(0, block0
->start_ip
);
346 EXPECT_EQ(2, block0
->end_ip
);
348 EXPECT_TRUE(cmod_propagation(v
));
349 EXPECT_EQ(0, block0
->start_ip
);
350 EXPECT_EQ(1, block0
->end_ip
);
351 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
352 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 0)->conditional_mod
);
353 EXPECT_EQ(BRW_OPCODE_SEL
, instruction(block0
, 1)->opcode
);
354 EXPECT_EQ(BRW_PREDICATE_NORMAL
, instruction(block0
, 1)->predicate
);
357 TEST_F(cmod_propagation_test
, negate
)
359 const fs_builder
&bld
= v
->bld
;
360 fs_reg dest
= 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
);
364 bld
.ADD(dest
, src0
, src1
);
366 bld
.CMP(bld
.null_reg_f(), dest
, zero
, BRW_CONDITIONAL_GE
);
370 * 0: add(8) dest src0 src1
371 * 1: cmp.ge.f0(8) null -dest 0.0f
374 * 0: add.le.f0(8) dest src0 src1
378 bblock_t
*block0
= v
->cfg
->blocks
[0];
380 EXPECT_EQ(0, block0
->start_ip
);
381 EXPECT_EQ(1, block0
->end_ip
);
383 EXPECT_TRUE(cmod_propagation(v
));
384 EXPECT_EQ(0, block0
->start_ip
);
385 EXPECT_EQ(0, block0
->end_ip
);
386 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
387 EXPECT_EQ(BRW_CONDITIONAL_LE
, instruction(block0
, 0)->conditional_mod
);
390 TEST_F(cmod_propagation_test
, movnz
)
392 const fs_builder
&bld
= v
->bld
;
393 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
394 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
395 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
396 bld
.CMP(dest
, src0
, src1
, BRW_CONDITIONAL_GE
);
397 set_condmod(BRW_CONDITIONAL_NZ
,
398 bld
.MOV(bld
.null_reg_f(), dest
));
402 * 0: cmp.ge.f0(8) dest src0 src1
403 * 1: mov.nz.f0(8) null dest
406 * 0: cmp.ge.f0(8) dest src0 src1
410 bblock_t
*block0
= v
->cfg
->blocks
[0];
412 EXPECT_EQ(0, block0
->start_ip
);
413 EXPECT_EQ(1, block0
->end_ip
);
415 EXPECT_TRUE(cmod_propagation(v
));
416 EXPECT_EQ(0, block0
->start_ip
);
417 EXPECT_EQ(0, block0
->end_ip
);
418 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
419 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 0)->conditional_mod
);
422 TEST_F(cmod_propagation_test
, different_types_cmod_with_zero
)
424 const fs_builder
&bld
= v
->bld
;
425 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
426 fs_reg src0
= v
->vgrf(glsl_type::int_type
);
427 fs_reg src1
= v
->vgrf(glsl_type::int_type
);
429 bld
.ADD(dest
, src0
, src1
);
430 bld
.CMP(bld
.null_reg_f(), retype(dest
, BRW_REGISTER_TYPE_F
), zero
,
435 * 0: add(8) dest:D src0:D src1:D
436 * 1: cmp.ge.f0(8) null:F dest:F 0.0f
443 bblock_t
*block0
= v
->cfg
->blocks
[0];
445 EXPECT_EQ(0, block0
->start_ip
);
446 EXPECT_EQ(1, block0
->end_ip
);
448 EXPECT_FALSE(cmod_propagation(v
));
449 EXPECT_EQ(0, block0
->start_ip
);
450 EXPECT_EQ(1, block0
->end_ip
);
451 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
452 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
453 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
456 TEST_F(cmod_propagation_test
, andnz_one
)
458 const fs_builder
&bld
= v
->bld
;
459 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
460 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
464 bld
.CMP(retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
, BRW_CONDITIONAL_L
);
465 set_condmod(BRW_CONDITIONAL_NZ
,
466 bld
.AND(bld
.null_reg_d(), dest
, one
));
469 * 0: cmp.l.f0(8) dest:F src0:F 0F
470 * 1: and.nz.f0(8) null:D dest:D 1D
473 * 0: cmp.l.f0(8) dest:F src0:F 0F
477 bblock_t
*block0
= v
->cfg
->blocks
[0];
479 EXPECT_EQ(0, block0
->start_ip
);
480 EXPECT_EQ(1, block0
->end_ip
);
482 EXPECT_TRUE(cmod_propagation(v
));
483 EXPECT_EQ(0, block0
->start_ip
);
484 EXPECT_EQ(0, block0
->end_ip
);
485 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
486 EXPECT_EQ(BRW_CONDITIONAL_L
, instruction(block0
, 0)->conditional_mod
);
487 EXPECT_TRUE(retype(dest
, BRW_REGISTER_TYPE_F
)
488 .equals(instruction(block0
, 0)->dst
));
491 TEST_F(cmod_propagation_test
, andnz_non_one
)
493 const fs_builder
&bld
= v
->bld
;
494 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
495 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
499 bld
.CMP(retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
, BRW_CONDITIONAL_L
);
500 set_condmod(BRW_CONDITIONAL_NZ
,
501 bld
.AND(bld
.null_reg_d(), dest
, nonone
));
504 * 0: cmp.l.f0(8) dest:F src0:F 0F
505 * 1: and.nz.f0(8) null:D dest:D 38D
512 bblock_t
*block0
= v
->cfg
->blocks
[0];
514 EXPECT_EQ(0, block0
->start_ip
);
515 EXPECT_EQ(1, block0
->end_ip
);
517 EXPECT_FALSE(cmod_propagation(v
));
518 EXPECT_EQ(0, block0
->start_ip
);
519 EXPECT_EQ(1, block0
->end_ip
);
520 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
521 EXPECT_EQ(BRW_CONDITIONAL_L
, instruction(block0
, 0)->conditional_mod
);
522 EXPECT_EQ(BRW_OPCODE_AND
, instruction(block0
, 1)->opcode
);
523 EXPECT_EQ(BRW_CONDITIONAL_NZ
, instruction(block0
, 1)->conditional_mod
);
526 TEST_F(cmod_propagation_test
, andz_one
)
528 const fs_builder
&bld
= v
->bld
;
529 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
530 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
534 bld
.CMP(retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
, BRW_CONDITIONAL_L
);
535 set_condmod(BRW_CONDITIONAL_Z
,
536 bld
.AND(bld
.null_reg_d(), dest
, one
));
539 * 0: cmp.l.f0(8) dest:F src0:F 0F
540 * 1: and.z.f0(8) null:D dest:D 1D
547 bblock_t
*block0
= v
->cfg
->blocks
[0];
549 EXPECT_EQ(0, block0
->start_ip
);
550 EXPECT_EQ(1, block0
->end_ip
);
552 EXPECT_FALSE(cmod_propagation(v
));
553 EXPECT_EQ(0, block0
->start_ip
);
554 EXPECT_EQ(1, block0
->end_ip
);
555 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
556 EXPECT_EQ(BRW_CONDITIONAL_L
, instruction(block0
, 0)->conditional_mod
);
557 EXPECT_EQ(BRW_OPCODE_AND
, instruction(block0
, 1)->opcode
);
558 EXPECT_EQ(BRW_CONDITIONAL_EQ
, instruction(block0
, 1)->conditional_mod
);