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