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 gen_device_info
*devinfo
;
37 struct gl_context
*ctx
;
38 struct brw_wm_prog_data
*prog_data
;
39 struct gl_shader_program
*shader_prog
;
43 class cmod_propagation_fs_visitor
: public fs_visitor
46 cmod_propagation_fs_visitor(struct brw_compiler
*compiler
,
47 struct brw_wm_prog_data
*prog_data
,
49 : fs_visitor(compiler
, NULL
, NULL
, NULL
,
50 &prog_data
->base
, (struct gl_program
*) NULL
,
55 void cmod_propagation_test::SetUp()
57 ctx
= (struct gl_context
*)calloc(1, sizeof(*ctx
));
58 compiler
= (struct brw_compiler
*)calloc(1, sizeof(*compiler
));
59 devinfo
= (struct gen_device_info
*)calloc(1, sizeof(*devinfo
));
60 compiler
->devinfo
= devinfo
;
62 prog_data
= ralloc(NULL
, struct brw_wm_prog_data
);
63 nir_shader
*shader
= nir_shader_create(NULL
, MESA_SHADER_FRAGMENT
, NULL
);
65 v
= new cmod_propagation_fs_visitor(compiler
, prog_data
, shader
);
71 instruction(bblock_t
*block
, int num
)
73 fs_inst
*inst
= (fs_inst
*)block
->start();
74 for (int i
= 0; i
< num
; i
++) {
75 inst
= (fs_inst
*)inst
->next
;
81 cmod_propagation(fs_visitor
*v
)
83 const bool print
= getenv("TEST_DEBUG");
86 fprintf(stderr
, "= Before =\n");
90 bool ret
= v
->opt_cmod_propagation();
93 fprintf(stderr
, "\n= After =\n");
100 TEST_F(cmod_propagation_test
, basic
)
102 const fs_builder
&bld
= v
->bld
;
103 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
104 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
105 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
106 fs_reg
zero(brw_imm_f(0.0f
));
107 bld
.ADD(dest
, src0
, src1
);
108 bld
.CMP(bld
.null_reg_f(), dest
, zero
, BRW_CONDITIONAL_GE
);
112 * 0: add(8) dest src0 src1
113 * 1: cmp.ge.f0(8) null dest 0.0f
116 * 0: add.ge.f0(8) dest src0 src1
120 bblock_t
*block0
= v
->cfg
->blocks
[0];
122 EXPECT_EQ(0, block0
->start_ip
);
123 EXPECT_EQ(1, block0
->end_ip
);
125 EXPECT_TRUE(cmod_propagation(v
));
126 EXPECT_EQ(0, block0
->start_ip
);
127 EXPECT_EQ(0, block0
->end_ip
);
128 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
129 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 0)->conditional_mod
);
132 TEST_F(cmod_propagation_test
, cmp_nonzero
)
134 const fs_builder
&bld
= v
->bld
;
135 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
136 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
137 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
138 fs_reg
nonzero(brw_imm_f(1.0f
));
139 bld
.ADD(dest
, src0
, src1
);
140 bld
.CMP(bld
.null_reg_f(), dest
, nonzero
, BRW_CONDITIONAL_GE
);
144 * 0: add(8) dest src0 src1
145 * 1: cmp.ge.f0(8) null dest 1.0f
152 bblock_t
*block0
= v
->cfg
->blocks
[0];
154 EXPECT_EQ(0, block0
->start_ip
);
155 EXPECT_EQ(1, block0
->end_ip
);
157 EXPECT_FALSE(cmod_propagation(v
));
158 EXPECT_EQ(0, block0
->start_ip
);
159 EXPECT_EQ(1, block0
->end_ip
);
160 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
161 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
162 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
165 TEST_F(cmod_propagation_test
, non_cmod_instruction
)
167 const fs_builder
&bld
= v
->bld
;
168 fs_reg dest
= v
->vgrf(glsl_type::uint_type
);
169 fs_reg src0
= v
->vgrf(glsl_type::uint_type
);
170 fs_reg
zero(brw_imm_ud(0u));
172 bld
.CMP(bld
.null_reg_ud(), dest
, zero
, BRW_CONDITIONAL_GE
);
176 * 0: fbl(8) dest src0
177 * 1: cmp.ge.f0(8) null dest 0u
184 bblock_t
*block0
= v
->cfg
->blocks
[0];
186 EXPECT_EQ(0, block0
->start_ip
);
187 EXPECT_EQ(1, block0
->end_ip
);
189 EXPECT_FALSE(cmod_propagation(v
));
190 EXPECT_EQ(0, block0
->start_ip
);
191 EXPECT_EQ(1, block0
->end_ip
);
192 EXPECT_EQ(BRW_OPCODE_FBL
, instruction(block0
, 0)->opcode
);
193 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
194 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
197 TEST_F(cmod_propagation_test
, intervening_flag_write
)
199 const fs_builder
&bld
= v
->bld
;
200 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
201 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
202 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
203 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
204 fs_reg
zero(brw_imm_f(0.0f
));
205 bld
.ADD(dest
, src0
, src1
);
206 bld
.CMP(bld
.null_reg_f(), src2
, zero
, BRW_CONDITIONAL_GE
);
207 bld
.CMP(bld
.null_reg_f(), dest
, zero
, BRW_CONDITIONAL_GE
);
211 * 0: add(8) dest src0 src1
212 * 1: cmp.ge.f0(8) null src2 0.0f
213 * 2: cmp.ge.f0(8) null dest 0.0f
220 bblock_t
*block0
= v
->cfg
->blocks
[0];
222 EXPECT_EQ(0, block0
->start_ip
);
223 EXPECT_EQ(2, block0
->end_ip
);
225 EXPECT_FALSE(cmod_propagation(v
));
226 EXPECT_EQ(0, block0
->start_ip
);
227 EXPECT_EQ(2, block0
->end_ip
);
228 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
229 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
230 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
231 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
232 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
235 TEST_F(cmod_propagation_test
, intervening_flag_read
)
237 const fs_builder
&bld
= v
->bld
;
238 fs_reg dest0
= v
->vgrf(glsl_type::float_type
);
239 fs_reg dest1
= v
->vgrf(glsl_type::float_type
);
240 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
241 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
242 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
243 fs_reg
zero(brw_imm_f(0.0f
));
244 bld
.ADD(dest0
, src0
, src1
);
245 set_predicate(BRW_PREDICATE_NORMAL
, bld
.SEL(dest1
, src2
, zero
));
246 bld
.CMP(bld
.null_reg_f(), dest0
, zero
, BRW_CONDITIONAL_GE
);
250 * 0: add(8) dest0 src0 src1
251 * 1: (+f0) sel(8) dest1 src2 0.0f
252 * 2: cmp.ge.f0(8) null dest0 0.0f
259 bblock_t
*block0
= v
->cfg
->blocks
[0];
261 EXPECT_EQ(0, block0
->start_ip
);
262 EXPECT_EQ(2, block0
->end_ip
);
264 EXPECT_FALSE(cmod_propagation(v
));
265 EXPECT_EQ(0, block0
->start_ip
);
266 EXPECT_EQ(2, block0
->end_ip
);
267 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
268 EXPECT_EQ(BRW_OPCODE_SEL
, instruction(block0
, 1)->opcode
);
269 EXPECT_EQ(BRW_PREDICATE_NORMAL
, instruction(block0
, 1)->predicate
);
270 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
271 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
274 TEST_F(cmod_propagation_test
, intervening_dest_write
)
276 const fs_builder
&bld
= v
->bld
;
277 fs_reg dest
= v
->vgrf(glsl_type::vec4_type
);
278 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
279 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
280 fs_reg src2
= v
->vgrf(glsl_type::vec2_type
);
281 fs_reg
zero(brw_imm_f(0.0f
));
282 bld
.ADD(offset(dest
, bld
, 2), src0
, src1
);
283 bld
.emit(SHADER_OPCODE_TEX
, dest
, src2
)
285 bld
.CMP(bld
.null_reg_f(), offset(dest
, bld
, 2), zero
, BRW_CONDITIONAL_GE
);
289 * 0: add(8) dest+2 src0 src1
290 * 1: tex(8) rlen 4 dest+0 src2
291 * 2: cmp.ge.f0(8) null dest+2 0.0f
298 bblock_t
*block0
= v
->cfg
->blocks
[0];
300 EXPECT_EQ(0, block0
->start_ip
);
301 EXPECT_EQ(2, block0
->end_ip
);
303 EXPECT_FALSE(cmod_propagation(v
));
304 EXPECT_EQ(0, block0
->start_ip
);
305 EXPECT_EQ(2, block0
->end_ip
);
306 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
307 EXPECT_EQ(BRW_CONDITIONAL_NONE
, instruction(block0
, 0)->conditional_mod
);
308 EXPECT_EQ(SHADER_OPCODE_TEX
, instruction(block0
, 1)->opcode
);
309 EXPECT_EQ(BRW_CONDITIONAL_NONE
, instruction(block0
, 0)->conditional_mod
);
310 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
311 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
314 TEST_F(cmod_propagation_test
, intervening_flag_read_same_value
)
316 const fs_builder
&bld
= v
->bld
;
317 fs_reg dest0
= v
->vgrf(glsl_type::float_type
);
318 fs_reg dest1
= v
->vgrf(glsl_type::float_type
);
319 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
320 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
321 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
322 fs_reg
zero(brw_imm_f(0.0f
));
323 set_condmod(BRW_CONDITIONAL_GE
, bld
.ADD(dest0
, src0
, src1
));
324 set_predicate(BRW_PREDICATE_NORMAL
, bld
.SEL(dest1
, src2
, zero
));
325 bld
.CMP(bld
.null_reg_f(), dest0
, zero
, BRW_CONDITIONAL_GE
);
329 * 0: add.ge.f0(8) dest0 src0 src1
330 * 1: (+f0) sel(8) dest1 src2 0.0f
331 * 2: cmp.ge.f0(8) null dest0 0.0f
334 * 0: add.ge.f0(8) dest0 src0 src1
335 * 1: (+f0) sel(8) dest1 src2 0.0f
339 bblock_t
*block0
= v
->cfg
->blocks
[0];
341 EXPECT_EQ(0, block0
->start_ip
);
342 EXPECT_EQ(2, block0
->end_ip
);
344 EXPECT_TRUE(cmod_propagation(v
));
345 EXPECT_EQ(0, block0
->start_ip
);
346 EXPECT_EQ(1, block0
->end_ip
);
347 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
348 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 0)->conditional_mod
);
349 EXPECT_EQ(BRW_OPCODE_SEL
, instruction(block0
, 1)->opcode
);
350 EXPECT_EQ(BRW_PREDICATE_NORMAL
, instruction(block0
, 1)->predicate
);
353 TEST_F(cmod_propagation_test
, negate
)
355 const fs_builder
&bld
= v
->bld
;
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
);
359 fs_reg
zero(brw_imm_f(0.0f
));
360 bld
.ADD(dest
, src0
, src1
);
362 bld
.CMP(bld
.null_reg_f(), dest
, zero
, BRW_CONDITIONAL_GE
);
366 * 0: add(8) dest src0 src1
367 * 1: cmp.ge.f0(8) null -dest 0.0f
370 * 0: add.le.f0(8) dest src0 src1
374 bblock_t
*block0
= v
->cfg
->blocks
[0];
376 EXPECT_EQ(0, block0
->start_ip
);
377 EXPECT_EQ(1, block0
->end_ip
);
379 EXPECT_TRUE(cmod_propagation(v
));
380 EXPECT_EQ(0, block0
->start_ip
);
381 EXPECT_EQ(0, block0
->end_ip
);
382 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
383 EXPECT_EQ(BRW_CONDITIONAL_LE
, instruction(block0
, 0)->conditional_mod
);
386 TEST_F(cmod_propagation_test
, movnz
)
388 const fs_builder
&bld
= v
->bld
;
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 bld
.CMP(dest
, src0
, src1
, BRW_CONDITIONAL_GE
);
393 set_condmod(BRW_CONDITIONAL_NZ
,
394 bld
.MOV(bld
.null_reg_f(), dest
));
398 * 0: cmp.ge.f0(8) dest src0 src1
399 * 1: mov.nz.f0(8) null dest
402 * 0: cmp.ge.f0(8) dest src0 src1
406 bblock_t
*block0
= v
->cfg
->blocks
[0];
408 EXPECT_EQ(0, block0
->start_ip
);
409 EXPECT_EQ(1, block0
->end_ip
);
411 EXPECT_TRUE(cmod_propagation(v
));
412 EXPECT_EQ(0, block0
->start_ip
);
413 EXPECT_EQ(0, block0
->end_ip
);
414 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
415 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 0)->conditional_mod
);
418 TEST_F(cmod_propagation_test
, different_types_cmod_with_zero
)
420 const fs_builder
&bld
= v
->bld
;
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
);
424 fs_reg
zero(brw_imm_f(0.0f
));
425 bld
.ADD(dest
, src0
, src1
);
426 bld
.CMP(bld
.null_reg_f(), retype(dest
, BRW_REGISTER_TYPE_F
), zero
,
431 * 0: add(8) dest:D src0:D src1:D
432 * 1: cmp.ge.f0(8) null:F dest:F 0.0f
439 bblock_t
*block0
= v
->cfg
->blocks
[0];
441 EXPECT_EQ(0, block0
->start_ip
);
442 EXPECT_EQ(1, block0
->end_ip
);
444 EXPECT_FALSE(cmod_propagation(v
));
445 EXPECT_EQ(0, block0
->start_ip
);
446 EXPECT_EQ(1, block0
->end_ip
);
447 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
448 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
449 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
452 TEST_F(cmod_propagation_test
, andnz_one
)
454 const fs_builder
&bld
= v
->bld
;
455 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
456 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
457 fs_reg
zero(brw_imm_f(0.0f
));
458 fs_reg
one(brw_imm_d(1));
460 bld
.CMP(retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
, BRW_CONDITIONAL_L
);
461 set_condmod(BRW_CONDITIONAL_NZ
,
462 bld
.AND(bld
.null_reg_d(), dest
, one
));
465 * 0: cmp.l.f0(8) dest:F src0:F 0F
466 * 1: and.nz.f0(8) null:D dest:D 1D
469 * 0: cmp.l.f0(8) dest:F src0:F 0F
473 bblock_t
*block0
= v
->cfg
->blocks
[0];
475 EXPECT_EQ(0, block0
->start_ip
);
476 EXPECT_EQ(1, block0
->end_ip
);
478 EXPECT_TRUE(cmod_propagation(v
));
479 EXPECT_EQ(0, block0
->start_ip
);
480 EXPECT_EQ(0, block0
->end_ip
);
481 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
482 EXPECT_EQ(BRW_CONDITIONAL_L
, instruction(block0
, 0)->conditional_mod
);
483 EXPECT_TRUE(retype(dest
, BRW_REGISTER_TYPE_F
)
484 .equals(instruction(block0
, 0)->dst
));
487 TEST_F(cmod_propagation_test
, andnz_non_one
)
489 const fs_builder
&bld
= v
->bld
;
490 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
491 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
492 fs_reg
zero(brw_imm_f(0.0f
));
493 fs_reg
nonone(brw_imm_d(38));
495 bld
.CMP(retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
, BRW_CONDITIONAL_L
);
496 set_condmod(BRW_CONDITIONAL_NZ
,
497 bld
.AND(bld
.null_reg_d(), dest
, nonone
));
500 * 0: cmp.l.f0(8) dest:F src0:F 0F
501 * 1: and.nz.f0(8) null:D dest:D 38D
508 bblock_t
*block0
= v
->cfg
->blocks
[0];
510 EXPECT_EQ(0, block0
->start_ip
);
511 EXPECT_EQ(1, block0
->end_ip
);
513 EXPECT_FALSE(cmod_propagation(v
));
514 EXPECT_EQ(0, block0
->start_ip
);
515 EXPECT_EQ(1, block0
->end_ip
);
516 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
517 EXPECT_EQ(BRW_CONDITIONAL_L
, instruction(block0
, 0)->conditional_mod
);
518 EXPECT_EQ(BRW_OPCODE_AND
, instruction(block0
, 1)->opcode
);
519 EXPECT_EQ(BRW_CONDITIONAL_NZ
, instruction(block0
, 1)->conditional_mod
);
522 TEST_F(cmod_propagation_test
, andz_one
)
524 const fs_builder
&bld
= v
->bld
;
525 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
526 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
527 fs_reg
zero(brw_imm_f(0.0f
));
528 fs_reg
one(brw_imm_d(1));
530 bld
.CMP(retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
, BRW_CONDITIONAL_L
);
531 set_condmod(BRW_CONDITIONAL_Z
,
532 bld
.AND(bld
.null_reg_d(), dest
, one
));
535 * 0: cmp.l.f0(8) dest:F src0:F 0F
536 * 1: and.z.f0(8) null:D dest:D 1D
543 bblock_t
*block0
= v
->cfg
->blocks
[0];
545 EXPECT_EQ(0, block0
->start_ip
);
546 EXPECT_EQ(1, block0
->end_ip
);
548 EXPECT_FALSE(cmod_propagation(v
));
549 EXPECT_EQ(0, block0
->start_ip
);
550 EXPECT_EQ(1, block0
->end_ip
);
551 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 0)->opcode
);
552 EXPECT_EQ(BRW_CONDITIONAL_L
, instruction(block0
, 0)->conditional_mod
);
553 EXPECT_EQ(BRW_OPCODE_AND
, instruction(block0
, 1)->opcode
);
554 EXPECT_EQ(BRW_CONDITIONAL_EQ
, instruction(block0
, 1)->conditional_mod
);