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
);
64 nir_shader_create(NULL
, MESA_SHADER_FRAGMENT
, NULL
, NULL
);
66 v
= new cmod_propagation_fs_visitor(compiler
, prog_data
, shader
);
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 cmod_propagation(fs_visitor
*v
)
84 const bool print
= getenv("TEST_DEBUG");
87 fprintf(stderr
, "= Before =\n");
91 bool ret
= v
->opt_cmod_propagation();
94 fprintf(stderr
, "\n= After =\n");
101 TEST_F(cmod_propagation_test
, basic
)
103 const fs_builder
&bld
= v
->bld
;
104 fs_reg dest
= 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 fs_reg
zero(brw_imm_f(0.0f
));
108 bld
.ADD(dest
, src0
, src1
);
109 bld
.CMP(bld
.null_reg_f(), dest
, zero
, BRW_CONDITIONAL_GE
);
113 * 0: add(8) dest src0 src1
114 * 1: cmp.ge.f0(8) null dest 0.0f
117 * 0: add.ge.f0(8) dest src0 src1
121 bblock_t
*block0
= v
->cfg
->blocks
[0];
123 EXPECT_EQ(0, block0
->start_ip
);
124 EXPECT_EQ(1, block0
->end_ip
);
126 EXPECT_TRUE(cmod_propagation(v
));
127 EXPECT_EQ(0, block0
->start_ip
);
128 EXPECT_EQ(0, block0
->end_ip
);
129 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
130 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 0)->conditional_mod
);
133 TEST_F(cmod_propagation_test
, cmp_nonzero
)
135 const fs_builder
&bld
= v
->bld
;
136 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
137 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
138 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
139 fs_reg
nonzero(brw_imm_f(1.0f
));
140 bld
.ADD(dest
, src0
, src1
);
141 bld
.CMP(bld
.null_reg_f(), dest
, nonzero
, BRW_CONDITIONAL_GE
);
145 * 0: add(8) dest src0 src1
146 * 1: cmp.ge.f0(8) null dest 1.0f
153 bblock_t
*block0
= v
->cfg
->blocks
[0];
155 EXPECT_EQ(0, block0
->start_ip
);
156 EXPECT_EQ(1, block0
->end_ip
);
158 EXPECT_FALSE(cmod_propagation(v
));
159 EXPECT_EQ(0, block0
->start_ip
);
160 EXPECT_EQ(1, block0
->end_ip
);
161 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
162 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
163 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
166 TEST_F(cmod_propagation_test
, non_cmod_instruction
)
168 const fs_builder
&bld
= v
->bld
;
169 fs_reg dest
= v
->vgrf(glsl_type::uint_type
);
170 fs_reg src0
= v
->vgrf(glsl_type::uint_type
);
171 fs_reg
zero(brw_imm_ud(0u));
173 bld
.CMP(bld
.null_reg_ud(), dest
, zero
, BRW_CONDITIONAL_GE
);
177 * 0: fbl(8) dest src0
178 * 1: cmp.ge.f0(8) null dest 0u
185 bblock_t
*block0
= v
->cfg
->blocks
[0];
187 EXPECT_EQ(0, block0
->start_ip
);
188 EXPECT_EQ(1, block0
->end_ip
);
190 EXPECT_FALSE(cmod_propagation(v
));
191 EXPECT_EQ(0, block0
->start_ip
);
192 EXPECT_EQ(1, block0
->end_ip
);
193 EXPECT_EQ(BRW_OPCODE_FBL
, instruction(block0
, 0)->opcode
);
194 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
195 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
198 TEST_F(cmod_propagation_test
, intervening_flag_write
)
200 const fs_builder
&bld
= v
->bld
;
201 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
202 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
203 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
204 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
205 fs_reg
zero(brw_imm_f(0.0f
));
206 bld
.ADD(dest
, src0
, src1
);
207 bld
.CMP(bld
.null_reg_f(), src2
, zero
, BRW_CONDITIONAL_GE
);
208 bld
.CMP(bld
.null_reg_f(), dest
, zero
, BRW_CONDITIONAL_GE
);
212 * 0: add(8) dest src0 src1
213 * 1: cmp.ge.f0(8) null src2 0.0f
214 * 2: cmp.ge.f0(8) null dest 0.0f
221 bblock_t
*block0
= v
->cfg
->blocks
[0];
223 EXPECT_EQ(0, block0
->start_ip
);
224 EXPECT_EQ(2, block0
->end_ip
);
226 EXPECT_FALSE(cmod_propagation(v
));
227 EXPECT_EQ(0, block0
->start_ip
);
228 EXPECT_EQ(2, block0
->end_ip
);
229 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
230 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 1)->opcode
);
231 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 1)->conditional_mod
);
232 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
233 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
236 TEST_F(cmod_propagation_test
, intervening_flag_read
)
238 const fs_builder
&bld
= v
->bld
;
239 fs_reg dest0
= v
->vgrf(glsl_type::float_type
);
240 fs_reg dest1
= v
->vgrf(glsl_type::float_type
);
241 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
242 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
243 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
244 fs_reg
zero(brw_imm_f(0.0f
));
245 bld
.ADD(dest0
, src0
, src1
);
246 set_predicate(BRW_PREDICATE_NORMAL
, bld
.SEL(dest1
, src2
, zero
));
247 bld
.CMP(bld
.null_reg_f(), dest0
, zero
, BRW_CONDITIONAL_GE
);
251 * 0: add(8) dest0 src0 src1
252 * 1: (+f0) sel(8) dest1 src2 0.0f
253 * 2: cmp.ge.f0(8) null dest0 0.0f
260 bblock_t
*block0
= v
->cfg
->blocks
[0];
262 EXPECT_EQ(0, block0
->start_ip
);
263 EXPECT_EQ(2, block0
->end_ip
);
265 EXPECT_FALSE(cmod_propagation(v
));
266 EXPECT_EQ(0, block0
->start_ip
);
267 EXPECT_EQ(2, block0
->end_ip
);
268 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
269 EXPECT_EQ(BRW_OPCODE_SEL
, instruction(block0
, 1)->opcode
);
270 EXPECT_EQ(BRW_PREDICATE_NORMAL
, instruction(block0
, 1)->predicate
);
271 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
272 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
275 TEST_F(cmod_propagation_test
, intervening_dest_write
)
277 const fs_builder
&bld
= v
->bld
;
278 fs_reg dest
= v
->vgrf(glsl_type::vec4_type
);
279 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
280 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
281 fs_reg src2
= v
->vgrf(glsl_type::vec2_type
);
282 fs_reg
zero(brw_imm_f(0.0f
));
283 bld
.ADD(offset(dest
, bld
, 2), src0
, src1
);
284 bld
.emit(SHADER_OPCODE_TEX
, dest
, src2
)
285 ->size_written
= 4 * REG_SIZE
;
286 bld
.CMP(bld
.null_reg_f(), offset(dest
, bld
, 2), zero
, BRW_CONDITIONAL_GE
);
290 * 0: add(8) dest+2 src0 src1
291 * 1: tex(8) rlen 4 dest+0 src2
292 * 2: cmp.ge.f0(8) null dest+2 0.0f
299 bblock_t
*block0
= v
->cfg
->blocks
[0];
301 EXPECT_EQ(0, block0
->start_ip
);
302 EXPECT_EQ(2, block0
->end_ip
);
304 EXPECT_FALSE(cmod_propagation(v
));
305 EXPECT_EQ(0, block0
->start_ip
);
306 EXPECT_EQ(2, block0
->end_ip
);
307 EXPECT_EQ(BRW_OPCODE_ADD
, instruction(block0
, 0)->opcode
);
308 EXPECT_EQ(BRW_CONDITIONAL_NONE
, instruction(block0
, 0)->conditional_mod
);
309 EXPECT_EQ(SHADER_OPCODE_TEX
, instruction(block0
, 1)->opcode
);
310 EXPECT_EQ(BRW_CONDITIONAL_NONE
, instruction(block0
, 0)->conditional_mod
);
311 EXPECT_EQ(BRW_OPCODE_CMP
, instruction(block0
, 2)->opcode
);
312 EXPECT_EQ(BRW_CONDITIONAL_GE
, instruction(block0
, 2)->conditional_mod
);
315 TEST_F(cmod_propagation_test
, intervening_flag_read_same_value
)
317 const fs_builder
&bld
= v
->bld
;
318 fs_reg dest0
= v
->vgrf(glsl_type::float_type
);
319 fs_reg dest1
= v
->vgrf(glsl_type::float_type
);
320 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
321 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
322 fs_reg src2
= v
->vgrf(glsl_type::float_type
);
323 fs_reg
zero(brw_imm_f(0.0f
));
324 set_condmod(BRW_CONDITIONAL_GE
, bld
.ADD(dest0
, src0
, src1
));
325 set_predicate(BRW_PREDICATE_NORMAL
, bld
.SEL(dest1
, src2
, zero
));
326 bld
.CMP(bld
.null_reg_f(), dest0
, zero
, 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 const fs_builder
&bld
= v
->bld
;
357 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
358 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
359 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
360 fs_reg
zero(brw_imm_f(0.0f
));
361 bld
.ADD(dest
, src0
, src1
);
363 bld
.CMP(bld
.null_reg_f(), dest
, zero
, 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 const fs_builder
&bld
= v
->bld
;
390 fs_reg dest
= v
->vgrf(glsl_type::float_type
);
391 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
392 fs_reg src1
= v
->vgrf(glsl_type::float_type
);
393 bld
.CMP(dest
, src0
, src1
, BRW_CONDITIONAL_GE
);
394 set_condmod(BRW_CONDITIONAL_NZ
,
395 bld
.MOV(bld
.null_reg_f(), dest
));
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 const fs_builder
&bld
= v
->bld
;
422 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
423 fs_reg src0
= v
->vgrf(glsl_type::int_type
);
424 fs_reg src1
= v
->vgrf(glsl_type::int_type
);
425 fs_reg
zero(brw_imm_f(0.0f
));
426 bld
.ADD(dest
, src0
, src1
);
427 bld
.CMP(bld
.null_reg_f(), retype(dest
, BRW_REGISTER_TYPE_F
), zero
,
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 const fs_builder
&bld
= v
->bld
;
456 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
457 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
458 fs_reg
zero(brw_imm_f(0.0f
));
459 fs_reg
one(brw_imm_d(1));
461 bld
.CMP(retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
, BRW_CONDITIONAL_L
);
462 set_condmod(BRW_CONDITIONAL_NZ
,
463 bld
.AND(bld
.null_reg_d(), dest
, one
));
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 const fs_builder
&bld
= v
->bld
;
491 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
492 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
493 fs_reg
zero(brw_imm_f(0.0f
));
494 fs_reg
nonone(brw_imm_d(38));
496 bld
.CMP(retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
, BRW_CONDITIONAL_L
);
497 set_condmod(BRW_CONDITIONAL_NZ
,
498 bld
.AND(bld
.null_reg_d(), dest
, nonone
));
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 const fs_builder
&bld
= v
->bld
;
526 fs_reg dest
= v
->vgrf(glsl_type::int_type
);
527 fs_reg src0
= v
->vgrf(glsl_type::float_type
);
528 fs_reg
zero(brw_imm_f(0.0f
));
529 fs_reg
one(brw_imm_d(1));
531 bld
.CMP(retype(dest
, BRW_REGISTER_TYPE_F
), src0
, zero
, BRW_CONDITIONAL_L
);
532 set_condmod(BRW_CONDITIONAL_Z
,
533 bld
.AND(bld
.null_reg_d(), dest
, one
));
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
);