Merge remote-tracking branch 'origin/master' into vulkan
[mesa.git] / src / mesa / drivers / dri / i965 / test_vec4_cmod_propagation.cpp
1 /*
2 * Copyright © 2015 Intel Corporation
3 *
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:
10 *
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
13 * Software.
14 *
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
21 * IN THE SOFTWARE.
22 *
23 * Based on test_fs_cmod_propagation.cpp
24 */
25
26 #include <gtest/gtest.h>
27 #include "brw_vec4.h"
28 #include "brw_vec4_builder.h"
29 #include "brw_cfg.h"
30 #include "program/program.h"
31
32 using namespace brw;
33
34 class cmod_propagation_test : public ::testing::Test {
35 virtual void SetUp();
36
37 public:
38 struct brw_compiler *compiler;
39 struct brw_device_info *devinfo;
40 struct gl_context *ctx;
41 struct gl_shader_program *shader_prog;
42 struct brw_vertex_program *vp;
43 struct brw_vue_prog_data *prog_data;
44 vec4_visitor *v;
45 };
46
47 class cmod_propagation_vec4_visitor : public vec4_visitor
48 {
49 public:
50 cmod_propagation_vec4_visitor(struct brw_compiler *compiler,
51 nir_shader *shader,
52 struct brw_vue_prog_data *prog_data)
53 : vec4_visitor(compiler, NULL, NULL, prog_data, shader, NULL,
54 false, -1)
55 {
56 prog_data->dispatch_mode = DISPATCH_MODE_4X2_DUAL_OBJECT;
57 }
58
59 protected:
60 /* Dummy implementation for pure virtual methods */
61 virtual dst_reg *make_reg_for_system_value(int location,
62 const glsl_type *type)
63 {
64 unreachable("Not reached");
65 }
66
67 virtual void setup_payload()
68 {
69 unreachable("Not reached");
70 }
71
72 virtual void emit_prolog()
73 {
74 unreachable("Not reached");
75 }
76
77 virtual void emit_program_code()
78 {
79 unreachable("Not reached");
80 }
81
82 virtual void emit_thread_end()
83 {
84 unreachable("Not reached");
85 }
86
87 virtual void emit_urb_write_header(int mrf)
88 {
89 unreachable("Not reached");
90 }
91
92 virtual vec4_instruction *emit_urb_write_opcode(bool complete)
93 {
94 unreachable("Not reached");
95 }
96 };
97
98
99 void cmod_propagation_test::SetUp()
100 {
101 ctx = (struct gl_context *)calloc(1, sizeof(*ctx));
102 compiler = (struct brw_compiler *)calloc(1, sizeof(*compiler));
103 devinfo = (struct brw_device_info *)calloc(1, sizeof(*devinfo));
104 prog_data = (struct brw_vue_prog_data *)calloc(1, sizeof(*prog_data));
105 compiler->devinfo = devinfo;
106
107 vp = ralloc(NULL, struct brw_vertex_program);
108
109 nir_shader *shader = nir_shader_create(NULL, MESA_SHADER_VERTEX, NULL);
110
111 v = new cmod_propagation_vec4_visitor(compiler, shader, prog_data);
112
113 _mesa_init_gl_program(&vp->program.Base, GL_VERTEX_SHADER, 0);
114
115 devinfo->gen = 4;
116 }
117
118 static vec4_instruction *
119 instruction(bblock_t *block, int num)
120 {
121 vec4_instruction *inst = (vec4_instruction *)block->start();
122 for (int i = 0; i < num; i++) {
123 inst = (vec4_instruction *)inst->next;
124 }
125 return inst;
126 }
127
128 static bool
129 cmod_propagation(vec4_visitor *v)
130 {
131 const bool print = getenv("TEST_DEBUG");
132
133 if (print) {
134 fprintf(stderr, "= Before =\n");
135 v->dump_instructions();
136 }
137
138 bool ret = v->opt_cmod_propagation();
139
140 if (print) {
141 fprintf(stderr, "\n= After =\n");
142 v->dump_instructions();
143 }
144
145 return ret;
146 }
147
148 TEST_F(cmod_propagation_test, basic)
149 {
150 const vec4_builder bld = vec4_builder(v).at_end();
151 dst_reg dest = dst_reg(v, glsl_type::float_type);
152 src_reg src0 = src_reg(v, glsl_type::float_type);
153 src_reg src1 = src_reg(v, glsl_type::float_type);
154 src_reg zero(brw_imm_f(0.0f));
155 dst_reg dest_null = bld.null_reg_f();
156 dest_null.writemask = WRITEMASK_X;
157
158 bld.ADD(dest, src0, src1);
159 bld.CMP(dest_null, src_reg(dest), zero, BRW_CONDITIONAL_GE);
160
161 /* = Before =
162 *
163 * 0: add dest.x src0.xxxx src1.xxxx
164 * 1: cmp.ge.f0 null.x dest.xxxx 0.0f
165 *
166 * = After =
167 * 0: add.ge.f0 dest.x src0.xxxx src1.xxxx
168 */
169
170 v->calculate_cfg();
171 bblock_t *block0 = v->cfg->blocks[0];
172
173 EXPECT_EQ(0, block0->start_ip);
174 EXPECT_EQ(1, block0->end_ip);
175
176 EXPECT_TRUE(cmod_propagation(v));
177
178 ASSERT_EQ(0, block0->start_ip);
179 ASSERT_EQ(0, block0->end_ip);
180 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
181 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
182 }
183
184 TEST_F(cmod_propagation_test, basic_different_dst_writemask)
185 {
186 const vec4_builder bld = vec4_builder(v).at_end();
187 dst_reg dest = dst_reg(v, glsl_type::float_type);
188 src_reg src0 = src_reg(v, glsl_type::float_type);
189 src_reg src1 = src_reg(v, glsl_type::float_type);
190 src_reg zero(brw_imm_f(0.0f));
191 dst_reg dest_null = bld.null_reg_f();
192
193 bld.ADD(dest, src0, src1);
194 bld.CMP(dest_null, src_reg(dest), zero, BRW_CONDITIONAL_GE);
195
196 /* = Before =
197 *
198 * 0: add dest.x src0 src1
199 * 1: cmp.ge.f0 null.xyzw dest 0.0f
200 *
201 * = After =
202 * (no changes)
203 */
204
205 v->calculate_cfg();
206 bblock_t *block0 = v->cfg->blocks[0];
207
208 EXPECT_EQ(0, block0->start_ip);
209 EXPECT_EQ(1, block0->end_ip);
210
211 EXPECT_FALSE(cmod_propagation(v));
212
213 ASSERT_EQ(0, block0->start_ip);
214 ASSERT_EQ(1, block0->end_ip);
215 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
216 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
217 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
218 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
219 }
220
221 TEST_F(cmod_propagation_test, andz_one)
222 {
223 const vec4_builder bld = vec4_builder(v).at_end();
224 dst_reg dest = dst_reg(v, glsl_type::int_type);
225 src_reg src0 = src_reg(v, glsl_type::float_type);
226 src_reg zero(brw_imm_f(0.0f));
227 src_reg one(brw_imm_d(1));
228
229 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
230 set_condmod(BRW_CONDITIONAL_Z,
231 bld.AND(bld.null_reg_d(), src_reg(dest), one));
232
233 /* = Before =
234 * 0: cmp.l.f0 dest:F src0:F 0F
235 * 1: and.z.f0 null:D dest:D 1D
236 *
237 * = After =
238 * (no changes)
239 */
240
241 v->calculate_cfg();
242 bblock_t *block0 = v->cfg->blocks[0];
243
244 EXPECT_EQ(0, block0->start_ip);
245 EXPECT_EQ(1, block0->end_ip);
246
247 EXPECT_FALSE(cmod_propagation(v));
248
249 ASSERT_EQ(0, block0->start_ip);
250 ASSERT_EQ(1, block0->end_ip);
251 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
252 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
253 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
254 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
255 }
256
257 TEST_F(cmod_propagation_test, non_cmod_instruction)
258 {
259 const vec4_builder bld = vec4_builder(v).at_end();
260 dst_reg dest = dst_reg(v, glsl_type::uint_type);
261 src_reg src0 = src_reg(v, glsl_type::uint_type);
262 src_reg zero(brw_imm_ud(0u));
263 bld.FBL(dest, src0);
264 bld.CMP(bld.null_reg_ud(), src_reg(dest), zero, BRW_CONDITIONAL_GE);
265
266 /* = Before =
267 *
268 * 0: fbl dest src0
269 * 1: cmp.ge.f0 null dest 0u
270 *
271 * = After =
272 * (no changes)
273 */
274
275 v->calculate_cfg();
276 bblock_t *block0 = v->cfg->blocks[0];
277
278 EXPECT_EQ(0, block0->start_ip);
279 EXPECT_EQ(1, block0->end_ip);
280
281 EXPECT_FALSE(cmod_propagation(v));
282
283 ASSERT_EQ(0, block0->start_ip);
284 ASSERT_EQ(1, block0->end_ip);
285 EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode);
286 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
287 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
288 }
289
290 TEST_F(cmod_propagation_test, intervening_flag_write)
291 {
292 const vec4_builder bld = vec4_builder(v).at_end();
293 dst_reg dest = dst_reg(v, glsl_type::float_type);
294 src_reg src0 = src_reg(v, glsl_type::float_type);
295 src_reg src1 = src_reg(v, glsl_type::float_type);
296 src_reg src2 = src_reg(v, glsl_type::float_type);
297 src_reg zero(brw_imm_f(0.0f));
298 bld.ADD(dest, src0, src1);
299 bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE);
300 bld.CMP(bld.null_reg_f(), src_reg(dest), zero, BRW_CONDITIONAL_GE);
301
302 /* = Before =
303 *
304 * 0: add dest src0 src1
305 * 1: cmp.ge.f0 null src2 0.0f
306 * 2: cmp.ge.f0 null dest 0.0f
307 *
308 * = After =
309 * (no changes)
310 */
311
312 v->calculate_cfg();
313 bblock_t *block0 = v->cfg->blocks[0];
314
315 EXPECT_EQ(0, block0->start_ip);
316 EXPECT_EQ(2, block0->end_ip);
317
318 EXPECT_FALSE(cmod_propagation(v));
319
320 ASSERT_EQ(0, block0->start_ip);
321 ASSERT_EQ(2, block0->end_ip);
322 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
323 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
324 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
325 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
326 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
327 }
328
329 TEST_F(cmod_propagation_test, intervening_flag_read)
330 {
331 const vec4_builder bld = vec4_builder(v).at_end();
332 dst_reg dest0 = dst_reg(v, glsl_type::float_type);
333 dst_reg dest1 = dst_reg(v, glsl_type::float_type);
334 src_reg src0 = src_reg(v, glsl_type::float_type);
335 src_reg src1 = src_reg(v, glsl_type::float_type);
336 src_reg src2 = src_reg(v, glsl_type::float_type);
337 src_reg zero(brw_imm_f(0.0f));
338 bld.ADD(dest0, src0, src1);
339 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
340 bld.CMP(bld.null_reg_f(), src_reg(dest0), zero, BRW_CONDITIONAL_GE);
341
342 /* = Before =
343 *
344 * 0: add dest0 src0 src1
345 * 1: (+f0) sel dest1 src2 0.0f
346 * 2: cmp.ge.f0 null dest0 0.0f
347 *
348 * = After =
349 * (no changes)
350 */
351
352 v->calculate_cfg();
353 bblock_t *block0 = v->cfg->blocks[0];
354
355 EXPECT_EQ(0, block0->start_ip);
356 EXPECT_EQ(2, block0->end_ip);
357
358 EXPECT_FALSE(cmod_propagation(v));
359
360 ASSERT_EQ(0, block0->start_ip);
361 ASSERT_EQ(2, block0->end_ip);
362 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
363 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
364 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
365 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
366 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
367 }
368
369 TEST_F(cmod_propagation_test, intervening_dest_write)
370 {
371 const vec4_builder bld = vec4_builder(v).at_end();
372 dst_reg dest = dst_reg(v, glsl_type::vec4_type);
373 src_reg src0 = src_reg(v, glsl_type::float_type);
374 src_reg src1 = src_reg(v, glsl_type::float_type);
375 src_reg src2 = src_reg(v, glsl_type::vec2_type);
376 src_reg zero(brw_imm_f(0.0f));
377 bld.ADD(offset(dest, 2), src0, src1);
378 bld.emit(SHADER_OPCODE_TEX, dest, src2)
379 ->regs_written = 4;
380 bld.CMP(bld.null_reg_f(), offset(src_reg(dest), 2), zero, BRW_CONDITIONAL_GE);
381
382 /* = Before =
383 *
384 * 0: add dest+2 src0 src1
385 * 1: tex rlen 4 dest+0 src2
386 * 2: cmp.ge.f0 null dest+2 0.0f
387 *
388 * = After =
389 * (no changes)
390 */
391
392 v->calculate_cfg();
393 bblock_t *block0 = v->cfg->blocks[0];
394
395 EXPECT_EQ(0, block0->start_ip);
396 EXPECT_EQ(2, block0->end_ip);
397
398 EXPECT_FALSE(cmod_propagation(v));
399
400 ASSERT_EQ(0, block0->start_ip);
401 ASSERT_EQ(2, block0->end_ip);
402 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
403 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
404 EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
405 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
406 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
407 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
408 }
409
410 TEST_F(cmod_propagation_test, intervening_flag_read_same_value)
411 {
412 const vec4_builder bld = vec4_builder(v).at_end();
413 dst_reg dest0 = dst_reg(v, glsl_type::float_type);
414 dst_reg dest1 = dst_reg(v, glsl_type::float_type);
415 src_reg src0 = src_reg(v, glsl_type::float_type);
416 src_reg src1 = src_reg(v, glsl_type::float_type);
417 src_reg src2 = src_reg(v, glsl_type::float_type);
418 src_reg zero(brw_imm_f(0.0f));
419 dst_reg dest_null = bld.null_reg_f();
420 dest_null.writemask = WRITEMASK_X;
421
422 set_condmod(BRW_CONDITIONAL_GE, bld.ADD(dest0, src0, src1));
423 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
424 bld.CMP(dest_null, src_reg(dest0), zero, BRW_CONDITIONAL_GE);
425
426 /* = Before =
427 *
428 * 0: add.ge.f0 dest0 src0 src1
429 * 1: (+f0) sel dest1 src2 0.0f
430 * 2: cmp.ge.f0 null.x dest0 0.0f
431 *
432 * = After =
433 * 0: add.ge.f0 dest0 src0 src1
434 * 1: (+f0) sel dest1 src2 0.0f
435 */
436
437 v->calculate_cfg();
438 bblock_t *block0 = v->cfg->blocks[0];
439
440 EXPECT_EQ(0, block0->start_ip);
441 EXPECT_EQ(2, block0->end_ip);
442
443 EXPECT_TRUE(cmod_propagation(v));
444 ASSERT_EQ(0, block0->start_ip);
445 ASSERT_EQ(1, block0->end_ip);
446 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
447 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
448 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
449 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
450 }
451
452 TEST_F(cmod_propagation_test, negate)
453 {
454 const vec4_builder bld = vec4_builder(v).at_end();
455 dst_reg dest = dst_reg(v, glsl_type::float_type);
456 src_reg src0 = src_reg(v, glsl_type::float_type);
457 src_reg src1 = src_reg(v, glsl_type::float_type);
458 src_reg zero(brw_imm_f(0.0f));
459 bld.ADD(dest, src0, src1);
460 src_reg tmp_src = src_reg(dest);
461 tmp_src.negate = true;
462 dst_reg dest_null = bld.null_reg_f();
463 dest_null.writemask = WRITEMASK_X;
464 bld.CMP(dest_null, tmp_src, zero, BRW_CONDITIONAL_GE);
465
466 /* = Before =
467 *
468 * 0: add dest src0 src1
469 * 1: cmp.ge.f0 null.x -dest 0.0f
470 *
471 * = After =
472 * 0: add.le.f0 dest src0 src1
473 */
474
475 v->calculate_cfg();
476 bblock_t *block0 = v->cfg->blocks[0];
477
478 EXPECT_EQ(0, block0->start_ip);
479 EXPECT_EQ(1, block0->end_ip);
480
481 EXPECT_TRUE(cmod_propagation(v));
482 EXPECT_EQ(0, block0->start_ip);
483 EXPECT_EQ(0, block0->end_ip);
484 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
485 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
486 }
487
488 TEST_F(cmod_propagation_test, movnz)
489 {
490 const vec4_builder bld = vec4_builder(v).at_end();
491 dst_reg dest = dst_reg(v, glsl_type::float_type);
492 src_reg src0 = src_reg(v, glsl_type::float_type);
493 src_reg src1 = src_reg(v, glsl_type::float_type);
494 dst_reg dest_null = bld.null_reg_f();
495 dest_null.writemask = WRITEMASK_X;
496
497 bld.CMP(dest, src0, src1, BRW_CONDITIONAL_L);
498 set_condmod(BRW_CONDITIONAL_NZ,
499 bld.MOV(dest_null, src_reg(dest)));
500
501 /* = Before =
502 *
503 * 0: cmp.l.f0 dest:F src0:F src1:F
504 * 1: mov.nz.f0 null.x dest:F
505 *
506 * = After =
507 * 0: cmp.l.f0 dest src0:F src1:F
508 */
509
510 v->calculate_cfg();
511 bblock_t *block0 = v->cfg->blocks[0];
512
513 EXPECT_EQ(0, block0->start_ip);
514 EXPECT_EQ(1, block0->end_ip);
515
516 EXPECT_TRUE(cmod_propagation(v));
517
518 ASSERT_EQ(0, block0->start_ip);
519 ASSERT_EQ(0, 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 }
523
524 TEST_F(cmod_propagation_test, different_types_cmod_with_zero)
525 {
526 const vec4_builder bld = vec4_builder(v).at_end();
527 dst_reg dest = dst_reg(v, glsl_type::int_type);
528 src_reg src0 = src_reg(v, glsl_type::int_type);
529 src_reg src1 = src_reg(v, glsl_type::int_type);
530 src_reg zero(brw_imm_f(0.0f));
531 bld.ADD(dest, src0, src1);
532 bld.CMP(bld.null_reg_f(), retype(src_reg(dest), BRW_REGISTER_TYPE_F), zero,
533 BRW_CONDITIONAL_GE);
534
535 /* = Before =
536 *
537 * 0: add dest:D src0:D src1:D
538 * 1: cmp.ge.f0 null:F dest:F 0.0f
539 *
540 * = After =
541 * (no changes)
542 */
543
544 v->calculate_cfg();
545 bblock_t *block0 = v->cfg->blocks[0];
546
547 EXPECT_EQ(0, block0->start_ip);
548 EXPECT_EQ(1, block0->end_ip);
549
550 EXPECT_FALSE(cmod_propagation(v));
551
552 ASSERT_EQ(0, block0->start_ip);
553 ASSERT_EQ(1, block0->end_ip);
554 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
555 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
556 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
557 }
558
559 TEST_F(cmod_propagation_test, andnz_non_one)
560 {
561 const vec4_builder bld = vec4_builder(v).at_end();
562 dst_reg dest = dst_reg(v, glsl_type::int_type);
563 src_reg src0 = src_reg(v, glsl_type::float_type);
564 src_reg zero(brw_imm_f(0.0f));
565 src_reg nonone(brw_imm_d(38));
566
567 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
568 set_condmod(BRW_CONDITIONAL_NZ,
569 bld.AND(bld.null_reg_d(), src_reg(dest), nonone));
570
571 /* = Before =
572 * 0: cmp.l.f0 dest:F src0:F 0F
573 * 1: and.nz.f0 null:D dest:D 38D
574 *
575 * = After =
576 * (no changes)
577 */
578
579 v->calculate_cfg();
580 bblock_t *block0 = v->cfg->blocks[0];
581
582 EXPECT_EQ(0, block0->start_ip);
583 EXPECT_EQ(1, block0->end_ip);
584
585 EXPECT_FALSE(cmod_propagation(v));
586
587 ASSERT_EQ(0, block0->start_ip);
588 ASSERT_EQ(1, block0->end_ip);
589 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
590 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
591 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
592 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
593 }
594
595 /* Note that basic is using glsl_type:float types, while this one is using
596 * glsl_type::vec4 */
597 TEST_F(cmod_propagation_test, basic_vec4)
598 {
599 const vec4_builder bld = vec4_builder(v).at_end();
600 dst_reg dest = dst_reg(v, glsl_type::vec4_type);
601 src_reg src0 = src_reg(v, glsl_type::vec4_type);
602 src_reg src1 = src_reg(v, glsl_type::vec4_type);
603 src_reg zero(brw_imm_f(0.0f));
604
605 bld.MUL(dest, src0, src1);
606 bld.CMP(bld.null_reg_f(), src_reg(dest), zero, BRW_CONDITIONAL_NZ);
607
608 /* = Before =
609 * 0: mul dest.xyzw src0.xyzw src1.xyzw
610 * 1: cmp.nz.f0.0 null.xyzw dest.xyzw 0.0f
611 *
612 * = After =
613 * 0: mul.nz.f0.0 dest.xyzw src0.xyzw src1.xyzw
614 */
615
616 v->calculate_cfg();
617 bblock_t *block0 = v->cfg->blocks[0];
618
619 EXPECT_EQ(0, block0->start_ip);
620 EXPECT_EQ(1, block0->end_ip);
621
622 EXPECT_TRUE(cmod_propagation(v));
623
624 ASSERT_EQ(0, block0->start_ip);
625 ASSERT_EQ(0, block0->end_ip);
626 EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
627 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
628 }
629
630 TEST_F(cmod_propagation_test, basic_vec4_different_dst_writemask)
631 {
632 const vec4_builder bld = vec4_builder(v).at_end();
633 dst_reg dest = dst_reg(v, glsl_type::vec4_type);
634 dest.writemask = WRITEMASK_X;
635 src_reg src0 = src_reg(v, glsl_type::vec4_type);
636 src_reg src1 = src_reg(v, glsl_type::vec4_type);
637 src_reg zero(brw_imm_f(0.0f));
638 dst_reg dest_null = bld.null_reg_f();
639
640 bld.MUL(dest, src0, src1);
641 bld.CMP(dest_null, src_reg(dest), zero, BRW_CONDITIONAL_NZ);
642
643 /* = Before =
644 * 0: mul dest.x src0 src1
645 * 1: cmp.nz.f0.0 null dest 0.0f
646 *
647 * = After =
648 * (no changes)
649 */
650
651 v->calculate_cfg();
652 bblock_t *block0 = v->cfg->blocks[0];
653
654 EXPECT_EQ(0, block0->start_ip);
655 EXPECT_EQ(1, block0->end_ip);
656
657 EXPECT_FALSE(cmod_propagation(v));
658
659 ASSERT_EQ(0, block0->start_ip);
660 ASSERT_EQ(1, block0->end_ip);
661 EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
662 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
663 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
664 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
665 }
666
667 TEST_F(cmod_propagation_test, mad_one_component_vec4)
668 {
669 const vec4_builder bld = vec4_builder(v).at_end();
670 dst_reg dest = dst_reg(v, glsl_type::vec4_type);
671 dest.writemask = WRITEMASK_X;
672 src_reg src0 = src_reg(v, glsl_type::vec4_type);
673 src_reg src1 = src_reg(v, glsl_type::vec4_type);
674 src_reg src2 = src_reg(v, glsl_type::vec4_type);
675 src0.swizzle = src1.swizzle = src2.swizzle = BRW_SWIZZLE_XXXX;
676 src2.negate = true;
677 src_reg zero(brw_imm_f(0.0f));
678 src_reg tmp(dest);
679 tmp.swizzle = BRW_SWIZZLE_XXXX;
680 dst_reg dest_null = bld.null_reg_f();
681 dest_null.writemask = WRITEMASK_X;
682
683 bld.MAD(dest, src0, src1, src2);
684 bld.CMP(dest_null, tmp, zero, BRW_CONDITIONAL_L);
685
686 /* = Before =
687 *
688 * 0: mad dest.x:F src0.xxxx:F src10.xxxx:F -src2.xxxx:F
689 * 1: cmp.l.f0.0 null.x:F dest.xxxx:F 0.0f
690 *
691 * = After =
692 * 0: mad.l.f0 dest.x:F src0.xxxx:F src10.xxxx:F -src2.xxxx:F
693 */
694
695 v->calculate_cfg();
696 bblock_t *block0 = v->cfg->blocks[0];
697
698 EXPECT_EQ(0, block0->start_ip);
699 EXPECT_EQ(1, block0->end_ip);
700
701 EXPECT_TRUE(cmod_propagation(v));
702
703 ASSERT_EQ(0, block0->start_ip);
704 ASSERT_EQ(0, block0->end_ip);
705 EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode);
706 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
707 }
708
709 TEST_F(cmod_propagation_test, mad_more_one_component_vec4)
710 {
711 const vec4_builder bld = vec4_builder(v).at_end();
712 dst_reg dest = dst_reg(v, glsl_type::vec4_type);
713 dest.writemask = WRITEMASK_XW;
714 src_reg src0 = src_reg(v, glsl_type::vec4_type);
715 src_reg src1 = src_reg(v, glsl_type::vec4_type);
716 src_reg src2 = src_reg(v, glsl_type::vec4_type);
717 src0.swizzle = src1.swizzle = src2.swizzle = BRW_SWIZZLE_XXXX;
718 src2.negate = true;
719 src_reg zero(brw_imm_f(0.0f));
720 src_reg tmp(dest);
721 tmp.swizzle = BRW_SWIZZLE_XXXX;
722 dst_reg dest_null = bld.null_reg_f();
723
724 bld.MAD(dest, src0, src1, src2);
725 bld.CMP(dest_null, tmp, zero, BRW_CONDITIONAL_L);
726
727 /* = Before =
728 *
729 * 0: mad dest.xw:F src0.xxxx:F src10.xxxx:F -src2.xxxx:F
730 * 1: cmp.l.f0.0 null:F dest.xxxx:F zeroF
731 *
732 * = After =
733 * (No changes)
734 */
735
736 v->calculate_cfg();
737 bblock_t *block0 = v->cfg->blocks[0];
738
739 EXPECT_EQ(0, block0->start_ip);
740 EXPECT_EQ(1, block0->end_ip);
741
742 EXPECT_FALSE(cmod_propagation(v));
743
744 ASSERT_EQ(0, block0->start_ip);
745 ASSERT_EQ(1, block0->end_ip);
746 EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode);
747 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
748 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
749 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
750 }
751
752 TEST_F(cmod_propagation_test, cmp_mov_vec4)
753 {
754 const vec4_builder bld = vec4_builder(v).at_end();
755 dst_reg dest = dst_reg(v, glsl_type::ivec4_type);
756 dest.writemask = WRITEMASK_X;
757 src_reg src0 = src_reg(v, glsl_type::ivec4_type);
758 src0.swizzle = BRW_SWIZZLE_XXXX;
759 src0.file = UNIFORM;
760 src_reg nonone = retype(brw_imm_d(16), BRW_REGISTER_TYPE_D);
761 src_reg mov_src = src_reg(dest);
762 mov_src.swizzle = BRW_SWIZZLE_XXXX;
763 dst_reg dest_null = bld.null_reg_d();
764 dest_null.writemask = WRITEMASK_X;
765
766 bld.CMP(dest, src0, nonone, BRW_CONDITIONAL_GE);
767 set_condmod(BRW_CONDITIONAL_NZ,
768 bld.MOV(dest_null, mov_src));
769
770 /* = Before =
771 *
772 * 0: cmp.ge.f0 dest.x:D u.xxxx:D 16D
773 * 1: mov.nz.f0 null.x:D dest.xxxx:D
774 *
775 * = After =
776 * 0: cmp.ge.f0 dest.x:D u.xxxx:D 16D
777 */
778
779 v->calculate_cfg();
780 bblock_t *block0 = v->cfg->blocks[0];
781
782 EXPECT_EQ(0, block0->start_ip);
783 EXPECT_EQ(1, block0->end_ip);
784
785 EXPECT_TRUE(cmod_propagation(v));
786
787 ASSERT_EQ(0, block0->start_ip);
788 ASSERT_EQ(0, block0->end_ip);
789 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
790 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
791 }
792
793 TEST_F(cmod_propagation_test, mul_cmp_different_channels_vec4)
794 {
795 const vec4_builder bld = vec4_builder(v).at_end();
796 dst_reg dest = dst_reg(v, glsl_type::vec4_type);
797 src_reg src0 = src_reg(v, glsl_type::vec4_type);
798 src_reg src1 = src_reg(v, glsl_type::vec4_type);
799 src_reg zero(brw_imm_f(0.0f));
800 src_reg cmp_src = src_reg(dest);
801 cmp_src.swizzle = BRW_SWIZZLE4(0,1,3,2);
802
803 bld.MUL(dest, src0, src1);
804 bld.CMP(bld.null_reg_f(), cmp_src, zero, BRW_CONDITIONAL_NZ);
805
806 /* = Before =
807 * 0: mul dest src0 src1
808 * 1: cmp.nz.f0.0 null dest.xywz 0.0f
809 *
810 * = After =
811 * (No changes)
812 */
813
814 v->calculate_cfg();
815 bblock_t *block0 = v->cfg->blocks[0];
816
817 EXPECT_EQ(0, block0->start_ip);
818 EXPECT_EQ(1, block0->end_ip);
819
820 EXPECT_FALSE(cmod_propagation(v));
821
822 ASSERT_EQ(0, block0->start_ip);
823 ASSERT_EQ(1, block0->end_ip);
824 EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode);
825 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
826 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
827 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
828 }