intel/compiler: Allow MESA_SHADER_KERNEL
[mesa.git] / src / intel / compiler / test_fs_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
24 #include <gtest/gtest.h>
25 #include "brw_fs.h"
26 #include "brw_cfg.h"
27 #include "program/program.h"
28
29 using namespace brw;
30
31 class cmod_propagation_test : public ::testing::Test {
32 virtual void SetUp();
33
34 public:
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;
40 fs_visitor *v;
41
42 void test_positive_float_saturate_prop(enum brw_conditional_mod before,
43 enum brw_conditional_mod after,
44 enum opcode op);
45
46 void test_negative_float_saturate_prop(enum brw_conditional_mod before,
47 enum opcode op);
48
49 void test_negative_int_saturate_prop(enum brw_conditional_mod before,
50 enum opcode op);
51 };
52
53 class cmod_propagation_fs_visitor : public fs_visitor
54 {
55 public:
56 cmod_propagation_fs_visitor(struct brw_compiler *compiler,
57 struct brw_wm_prog_data *prog_data,
58 nir_shader *shader)
59 : fs_visitor(compiler, NULL, NULL, NULL,
60 &prog_data->base, shader, 8, -1) {}
61 };
62
63
64 void cmod_propagation_test::SetUp()
65 {
66 ctx = (struct gl_context *)calloc(1, sizeof(*ctx));
67 compiler = (struct brw_compiler *)calloc(1, sizeof(*compiler));
68 devinfo = (struct gen_device_info *)calloc(1, sizeof(*devinfo));
69 compiler->devinfo = devinfo;
70
71 prog_data = ralloc(NULL, struct brw_wm_prog_data);
72 nir_shader *shader =
73 nir_shader_create(NULL, MESA_SHADER_FRAGMENT, NULL, NULL);
74
75 v = new cmod_propagation_fs_visitor(compiler, prog_data, shader);
76
77 devinfo->gen = 7;
78 }
79
80 static fs_inst *
81 instruction(bblock_t *block, int num)
82 {
83 fs_inst *inst = (fs_inst *)block->start();
84 for (int i = 0; i < num; i++) {
85 inst = (fs_inst *)inst->next;
86 }
87 return inst;
88 }
89
90 static bool
91 cmod_propagation(fs_visitor *v)
92 {
93 const bool print = getenv("TEST_DEBUG");
94
95 if (print) {
96 fprintf(stderr, "= Before =\n");
97 v->cfg->dump();
98 }
99
100 bool ret = v->opt_cmod_propagation();
101
102 if (print) {
103 fprintf(stderr, "\n= After =\n");
104 v->cfg->dump();
105 }
106
107 return ret;
108 }
109
110 TEST_F(cmod_propagation_test, basic)
111 {
112 const fs_builder &bld = v->bld;
113 fs_reg dest = v->vgrf(glsl_type::float_type);
114 fs_reg src0 = v->vgrf(glsl_type::float_type);
115 fs_reg src1 = v->vgrf(glsl_type::float_type);
116 fs_reg zero(brw_imm_f(0.0f));
117 bld.ADD(dest, src0, src1);
118 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
119
120 /* = Before =
121 *
122 * 0: add(8) dest src0 src1
123 * 1: cmp.ge.f0(8) null dest 0.0f
124 *
125 * = After =
126 * 0: add.ge.f0(8) dest src0 src1
127 */
128
129 v->calculate_cfg();
130 bblock_t *block0 = v->cfg->blocks[0];
131
132 EXPECT_EQ(0, block0->start_ip);
133 EXPECT_EQ(1, block0->end_ip);
134
135 EXPECT_TRUE(cmod_propagation(v));
136 EXPECT_EQ(0, block0->start_ip);
137 EXPECT_EQ(0, block0->end_ip);
138 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
139 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
140 }
141
142 TEST_F(cmod_propagation_test, basic_other_flag)
143 {
144 const fs_builder &bld = v->bld;
145 fs_reg dest = v->vgrf(glsl_type::float_type);
146 fs_reg src0 = v->vgrf(glsl_type::float_type);
147 fs_reg src1 = v->vgrf(glsl_type::float_type);
148 fs_reg zero(brw_imm_f(0.0f));
149 bld.ADD(dest, src0, src1);
150 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE)
151 ->flag_subreg = 1;
152
153 /* = Before =
154 *
155 * 0: add(8) dest src0 src1
156 * 1: cmp.ge.f0.1(8) null dest 0.0f
157 *
158 * = After =
159 * 0: add.ge.f0.1(8) dest src0 src1
160 */
161
162 v->calculate_cfg();
163 bblock_t *block0 = v->cfg->blocks[0];
164
165 EXPECT_EQ(0, block0->start_ip);
166 EXPECT_EQ(1, block0->end_ip);
167
168 EXPECT_TRUE(cmod_propagation(v));
169 EXPECT_EQ(0, block0->start_ip);
170 EXPECT_EQ(0, block0->end_ip);
171 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
172 EXPECT_EQ(1, instruction(block0, 0)->flag_subreg);
173 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
174 }
175
176 TEST_F(cmod_propagation_test, cmp_nonzero)
177 {
178 const fs_builder &bld = v->bld;
179 fs_reg dest = v->vgrf(glsl_type::float_type);
180 fs_reg src0 = v->vgrf(glsl_type::float_type);
181 fs_reg src1 = v->vgrf(glsl_type::float_type);
182 fs_reg nonzero(brw_imm_f(1.0f));
183 bld.ADD(dest, src0, src1);
184 bld.CMP(bld.null_reg_f(), dest, nonzero, BRW_CONDITIONAL_GE);
185
186 /* = Before =
187 *
188 * 0: add(8) dest src0 src1
189 * 1: cmp.ge.f0(8) null dest 1.0f
190 *
191 * = After =
192 * (no changes)
193 */
194
195 v->calculate_cfg();
196 bblock_t *block0 = v->cfg->blocks[0];
197
198 EXPECT_EQ(0, block0->start_ip);
199 EXPECT_EQ(1, block0->end_ip);
200
201 EXPECT_FALSE(cmod_propagation(v));
202 EXPECT_EQ(0, block0->start_ip);
203 EXPECT_EQ(1, block0->end_ip);
204 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
205 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
206 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
207 }
208
209 TEST_F(cmod_propagation_test, non_cmod_instruction)
210 {
211 const fs_builder &bld = v->bld;
212 fs_reg dest = v->vgrf(glsl_type::uint_type);
213 fs_reg src0 = v->vgrf(glsl_type::uint_type);
214 fs_reg zero(brw_imm_ud(0u));
215 bld.FBL(dest, src0);
216 bld.CMP(bld.null_reg_ud(), dest, zero, BRW_CONDITIONAL_GE);
217
218 /* = Before =
219 *
220 * 0: fbl(8) dest src0
221 * 1: cmp.ge.f0(8) null dest 0u
222 *
223 * = After =
224 * (no changes)
225 */
226
227 v->calculate_cfg();
228 bblock_t *block0 = v->cfg->blocks[0];
229
230 EXPECT_EQ(0, block0->start_ip);
231 EXPECT_EQ(1, block0->end_ip);
232
233 EXPECT_FALSE(cmod_propagation(v));
234 EXPECT_EQ(0, block0->start_ip);
235 EXPECT_EQ(1, block0->end_ip);
236 EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode);
237 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
238 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
239 }
240
241 TEST_F(cmod_propagation_test, intervening_flag_write)
242 {
243 const fs_builder &bld = v->bld;
244 fs_reg dest = v->vgrf(glsl_type::float_type);
245 fs_reg src0 = v->vgrf(glsl_type::float_type);
246 fs_reg src1 = v->vgrf(glsl_type::float_type);
247 fs_reg src2 = v->vgrf(glsl_type::float_type);
248 fs_reg zero(brw_imm_f(0.0f));
249 bld.ADD(dest, src0, src1);
250 bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE);
251 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
252
253 /* = Before =
254 *
255 * 0: add(8) dest src0 src1
256 * 1: cmp.ge.f0(8) null src2 0.0f
257 * 2: cmp.ge.f0(8) null dest 0.0f
258 *
259 * = After =
260 * (no changes)
261 */
262
263 v->calculate_cfg();
264 bblock_t *block0 = v->cfg->blocks[0];
265
266 EXPECT_EQ(0, block0->start_ip);
267 EXPECT_EQ(2, block0->end_ip);
268
269 EXPECT_FALSE(cmod_propagation(v));
270 EXPECT_EQ(0, block0->start_ip);
271 EXPECT_EQ(2, block0->end_ip);
272 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
273 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
274 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
275 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
276 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
277 }
278
279 TEST_F(cmod_propagation_test, intervening_mismatch_flag_write)
280 {
281 const fs_builder &bld = v->bld;
282 fs_reg dest = v->vgrf(glsl_type::float_type);
283 fs_reg src0 = v->vgrf(glsl_type::float_type);
284 fs_reg src1 = v->vgrf(glsl_type::float_type);
285 fs_reg src2 = v->vgrf(glsl_type::float_type);
286 fs_reg zero(brw_imm_f(0.0f));
287 bld.ADD(dest, src0, src1);
288 bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE)
289 ->flag_subreg = 1;
290 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
291
292 /* = Before =
293 *
294 * 0: add(8) dest src0 src1
295 * 1: cmp.ge.f0.1(8) null src2 0.0f
296 * 2: cmp.ge.f0(8) null dest 0.0f
297 *
298 * = After =
299 * 0: add.ge.f0(8) dest src0 src1
300 * 1: cmp.ge.f0.1(8) null src2 0.0f
301 */
302
303 v->calculate_cfg();
304 bblock_t *block0 = v->cfg->blocks[0];
305
306 EXPECT_EQ(0, block0->start_ip);
307 EXPECT_EQ(2, block0->end_ip);
308
309 EXPECT_TRUE(cmod_propagation(v));
310 EXPECT_EQ(0, block0->start_ip);
311 EXPECT_EQ(1, block0->end_ip);
312 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
313 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
314 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
315 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
316 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
317 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
318 }
319
320 TEST_F(cmod_propagation_test, intervening_flag_read)
321 {
322 const fs_builder &bld = v->bld;
323 fs_reg dest0 = v->vgrf(glsl_type::float_type);
324 fs_reg dest1 = v->vgrf(glsl_type::float_type);
325 fs_reg src0 = v->vgrf(glsl_type::float_type);
326 fs_reg src1 = v->vgrf(glsl_type::float_type);
327 fs_reg src2 = v->vgrf(glsl_type::float_type);
328 fs_reg zero(brw_imm_f(0.0f));
329 bld.ADD(dest0, src0, src1);
330 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
331 bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
332
333 /* = Before =
334 *
335 * 0: add(8) dest0 src0 src1
336 * 1: (+f0) sel(8) dest1 src2 0.0f
337 * 2: cmp.ge.f0(8) null dest0 0.0f
338 *
339 * = After =
340 * (no changes)
341 */
342
343 v->calculate_cfg();
344 bblock_t *block0 = v->cfg->blocks[0];
345
346 EXPECT_EQ(0, block0->start_ip);
347 EXPECT_EQ(2, block0->end_ip);
348
349 EXPECT_FALSE(cmod_propagation(v));
350 EXPECT_EQ(0, block0->start_ip);
351 EXPECT_EQ(2, block0->end_ip);
352 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
353 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
354 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
355 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
356 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
357 }
358
359 TEST_F(cmod_propagation_test, intervening_mismatch_flag_read)
360 {
361 const fs_builder &bld = v->bld;
362 fs_reg dest0 = v->vgrf(glsl_type::float_type);
363 fs_reg dest1 = v->vgrf(glsl_type::float_type);
364 fs_reg src0 = v->vgrf(glsl_type::float_type);
365 fs_reg src1 = v->vgrf(glsl_type::float_type);
366 fs_reg src2 = v->vgrf(glsl_type::float_type);
367 fs_reg zero(brw_imm_f(0.0f));
368 bld.ADD(dest0, src0, src1);
369 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
370 ->flag_subreg = 1;
371 bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
372
373 /* = Before =
374 *
375 * 0: add(8) dest0 src0 src1
376 * 1: (+f0.1) sel(8) dest1 src2 0.0f
377 * 2: cmp.ge.f0(8) null dest0 0.0f
378 *
379 * = After =
380 * 0: add.ge.f0(8) dest0 src0 src1
381 * 1: (+f0.1) sel(8) dest1 src2 0.0f
382 */
383
384 v->calculate_cfg();
385 bblock_t *block0 = v->cfg->blocks[0];
386
387 EXPECT_EQ(0, block0->start_ip);
388 EXPECT_EQ(2, block0->end_ip);
389
390 EXPECT_TRUE(cmod_propagation(v));
391 EXPECT_EQ(0, block0->start_ip);
392 EXPECT_EQ(1, block0->end_ip);
393 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
394 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
395 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
396 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
397 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
398 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
399 }
400
401 TEST_F(cmod_propagation_test, intervening_dest_write)
402 {
403 const fs_builder &bld = v->bld;
404 fs_reg dest = v->vgrf(glsl_type::vec4_type);
405 fs_reg src0 = v->vgrf(glsl_type::float_type);
406 fs_reg src1 = v->vgrf(glsl_type::float_type);
407 fs_reg src2 = v->vgrf(glsl_type::vec2_type);
408 fs_reg zero(brw_imm_f(0.0f));
409 bld.ADD(offset(dest, bld, 2), src0, src1);
410 bld.emit(SHADER_OPCODE_TEX, dest, src2)
411 ->size_written = 4 * REG_SIZE;
412 bld.CMP(bld.null_reg_f(), offset(dest, bld, 2), zero, BRW_CONDITIONAL_GE);
413
414 /* = Before =
415 *
416 * 0: add(8) dest+2 src0 src1
417 * 1: tex(8) rlen 4 dest+0 src2
418 * 2: cmp.ge.f0(8) null dest+2 0.0f
419 *
420 * = After =
421 * (no changes)
422 */
423
424 v->calculate_cfg();
425 bblock_t *block0 = v->cfg->blocks[0];
426
427 EXPECT_EQ(0, block0->start_ip);
428 EXPECT_EQ(2, block0->end_ip);
429
430 EXPECT_FALSE(cmod_propagation(v));
431 EXPECT_EQ(0, block0->start_ip);
432 EXPECT_EQ(2, block0->end_ip);
433 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
434 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
435 EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
436 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
437 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
438 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
439 }
440
441 TEST_F(cmod_propagation_test, intervening_flag_read_same_value)
442 {
443 const fs_builder &bld = v->bld;
444 fs_reg dest0 = v->vgrf(glsl_type::float_type);
445 fs_reg dest1 = v->vgrf(glsl_type::float_type);
446 fs_reg src0 = v->vgrf(glsl_type::float_type);
447 fs_reg src1 = v->vgrf(glsl_type::float_type);
448 fs_reg src2 = v->vgrf(glsl_type::float_type);
449 fs_reg zero(brw_imm_f(0.0f));
450 set_condmod(BRW_CONDITIONAL_GE, bld.ADD(dest0, src0, src1));
451 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
452 bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
453
454 /* = Before =
455 *
456 * 0: add.ge.f0(8) dest0 src0 src1
457 * 1: (+f0) sel(8) dest1 src2 0.0f
458 * 2: cmp.ge.f0(8) null dest0 0.0f
459 *
460 * = After =
461 * 0: add.ge.f0(8) dest0 src0 src1
462 * 1: (+f0) sel(8) dest1 src2 0.0f
463 */
464
465 v->calculate_cfg();
466 bblock_t *block0 = v->cfg->blocks[0];
467
468 EXPECT_EQ(0, block0->start_ip);
469 EXPECT_EQ(2, block0->end_ip);
470
471 EXPECT_TRUE(cmod_propagation(v));
472 EXPECT_EQ(0, block0->start_ip);
473 EXPECT_EQ(1, block0->end_ip);
474 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
475 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
476 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
477 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
478 }
479
480 TEST_F(cmod_propagation_test, negate)
481 {
482 const fs_builder &bld = v->bld;
483 fs_reg dest = v->vgrf(glsl_type::float_type);
484 fs_reg src0 = v->vgrf(glsl_type::float_type);
485 fs_reg src1 = v->vgrf(glsl_type::float_type);
486 fs_reg zero(brw_imm_f(0.0f));
487 bld.ADD(dest, src0, src1);
488 dest.negate = true;
489 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
490
491 /* = Before =
492 *
493 * 0: add(8) dest src0 src1
494 * 1: cmp.ge.f0(8) null -dest 0.0f
495 *
496 * = After =
497 * 0: add.le.f0(8) dest src0 src1
498 */
499
500 v->calculate_cfg();
501 bblock_t *block0 = v->cfg->blocks[0];
502
503 EXPECT_EQ(0, block0->start_ip);
504 EXPECT_EQ(1, block0->end_ip);
505
506 EXPECT_TRUE(cmod_propagation(v));
507 EXPECT_EQ(0, block0->start_ip);
508 EXPECT_EQ(0, block0->end_ip);
509 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
510 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
511 }
512
513 TEST_F(cmod_propagation_test, movnz)
514 {
515 const fs_builder &bld = v->bld;
516 fs_reg dest = v->vgrf(glsl_type::float_type);
517 fs_reg src0 = v->vgrf(glsl_type::float_type);
518 fs_reg src1 = v->vgrf(glsl_type::float_type);
519 bld.CMP(dest, src0, src1, BRW_CONDITIONAL_GE);
520 set_condmod(BRW_CONDITIONAL_NZ,
521 bld.MOV(bld.null_reg_f(), dest));
522
523 /* = Before =
524 *
525 * 0: cmp.ge.f0(8) dest src0 src1
526 * 1: mov.nz.f0(8) null dest
527 *
528 * = After =
529 * 0: cmp.ge.f0(8) dest src0 src1
530 */
531
532 v->calculate_cfg();
533 bblock_t *block0 = v->cfg->blocks[0];
534
535 EXPECT_EQ(0, block0->start_ip);
536 EXPECT_EQ(1, block0->end_ip);
537
538 EXPECT_TRUE(cmod_propagation(v));
539 EXPECT_EQ(0, block0->start_ip);
540 EXPECT_EQ(0, block0->end_ip);
541 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
542 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
543 }
544
545 TEST_F(cmod_propagation_test, different_types_cmod_with_zero)
546 {
547 const fs_builder &bld = v->bld;
548 fs_reg dest = v->vgrf(glsl_type::int_type);
549 fs_reg src0 = v->vgrf(glsl_type::int_type);
550 fs_reg src1 = v->vgrf(glsl_type::int_type);
551 fs_reg zero(brw_imm_f(0.0f));
552 bld.ADD(dest, src0, src1);
553 bld.CMP(bld.null_reg_f(), retype(dest, BRW_REGISTER_TYPE_F), zero,
554 BRW_CONDITIONAL_GE);
555
556 /* = Before =
557 *
558 * 0: add(8) dest:D src0:D src1:D
559 * 1: cmp.ge.f0(8) null:F dest:F 0.0f
560 *
561 * = After =
562 * (no changes)
563 */
564
565 v->calculate_cfg();
566 bblock_t *block0 = v->cfg->blocks[0];
567
568 EXPECT_EQ(0, block0->start_ip);
569 EXPECT_EQ(1, block0->end_ip);
570
571 EXPECT_FALSE(cmod_propagation(v));
572 EXPECT_EQ(0, block0->start_ip);
573 EXPECT_EQ(1, block0->end_ip);
574 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
575 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
576 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
577 }
578
579 TEST_F(cmod_propagation_test, andnz_one)
580 {
581 const fs_builder &bld = v->bld;
582 fs_reg dest = v->vgrf(glsl_type::int_type);
583 fs_reg src0 = v->vgrf(glsl_type::float_type);
584 fs_reg zero(brw_imm_f(0.0f));
585 fs_reg one(brw_imm_d(1));
586
587 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
588 set_condmod(BRW_CONDITIONAL_NZ,
589 bld.AND(bld.null_reg_d(), dest, one));
590
591 /* = Before =
592 * 0: cmp.l.f0(8) dest:F src0:F 0F
593 * 1: and.nz.f0(8) null:D dest:D 1D
594 *
595 * = After =
596 * 0: cmp.l.f0(8) dest:F src0:F 0F
597 */
598
599 v->calculate_cfg();
600 bblock_t *block0 = v->cfg->blocks[0];
601
602 EXPECT_EQ(0, block0->start_ip);
603 EXPECT_EQ(1, block0->end_ip);
604
605 EXPECT_TRUE(cmod_propagation(v));
606 EXPECT_EQ(0, block0->start_ip);
607 EXPECT_EQ(0, block0->end_ip);
608 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
609 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
610 EXPECT_TRUE(retype(dest, BRW_REGISTER_TYPE_F)
611 .equals(instruction(block0, 0)->dst));
612 }
613
614 TEST_F(cmod_propagation_test, andnz_non_one)
615 {
616 const fs_builder &bld = v->bld;
617 fs_reg dest = v->vgrf(glsl_type::int_type);
618 fs_reg src0 = v->vgrf(glsl_type::float_type);
619 fs_reg zero(brw_imm_f(0.0f));
620 fs_reg nonone(brw_imm_d(38));
621
622 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
623 set_condmod(BRW_CONDITIONAL_NZ,
624 bld.AND(bld.null_reg_d(), dest, nonone));
625
626 /* = Before =
627 * 0: cmp.l.f0(8) dest:F src0:F 0F
628 * 1: and.nz.f0(8) null:D dest:D 38D
629 *
630 * = After =
631 * (no changes)
632 */
633
634 v->calculate_cfg();
635 bblock_t *block0 = v->cfg->blocks[0];
636
637 EXPECT_EQ(0, block0->start_ip);
638 EXPECT_EQ(1, block0->end_ip);
639
640 EXPECT_FALSE(cmod_propagation(v));
641 EXPECT_EQ(0, block0->start_ip);
642 EXPECT_EQ(1, block0->end_ip);
643 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
644 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
645 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
646 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
647 }
648
649 TEST_F(cmod_propagation_test, cmp_cmpnz)
650 {
651 const fs_builder &bld = v->bld;
652
653 fs_reg dst0 = v->vgrf(glsl_type::float_type);
654 fs_reg src0 = v->vgrf(glsl_type::float_type);
655 fs_reg zero(brw_imm_f(0));
656
657 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
658 bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_NZ);
659
660 /* = Before =
661 * 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
662 * 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f
663 *
664 * = After =
665 * 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
666 */
667
668 v->calculate_cfg();
669 bblock_t *block0 = v->cfg->blocks[0];
670
671 EXPECT_TRUE(cmod_propagation(v));
672 EXPECT_EQ(0, block0->start_ip);
673 EXPECT_EQ(0, block0->end_ip);
674 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
675 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
676 }
677
678 TEST_F(cmod_propagation_test, cmp_cmpg)
679 {
680 const fs_builder &bld = v->bld;
681
682 fs_reg dst0 = v->vgrf(glsl_type::float_type);
683 fs_reg src0 = v->vgrf(glsl_type::float_type);
684 fs_reg zero(brw_imm_f(0));
685
686 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
687 bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_G);
688
689 /* = Before =
690 * 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
691 * 1: cmp.g.f0.0(8) null:F, vgrf0:F, 0f
692 *
693 * = After =
694 * (no changes)
695 */
696
697 v->calculate_cfg();
698 bblock_t *block0 = v->cfg->blocks[0];
699
700 EXPECT_FALSE(cmod_propagation(v));
701 EXPECT_EQ(0, block0->start_ip);
702 EXPECT_EQ(1, block0->end_ip);
703 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
704 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
705 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
706 EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 1)->conditional_mod);
707 }
708
709 TEST_F(cmod_propagation_test, plnnz_cmpnz)
710 {
711 const fs_builder &bld = v->bld;
712
713 fs_reg dst0 = v->vgrf(glsl_type::float_type);
714 fs_reg src0 = v->vgrf(glsl_type::float_type);
715 fs_reg zero(brw_imm_f(0));
716
717 set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
718 bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_NZ);
719
720 /* = Before =
721 * 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
722 * 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f
723 *
724 * = After =
725 * 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
726 */
727
728 v->calculate_cfg();
729 bblock_t *block0 = v->cfg->blocks[0];
730
731 EXPECT_TRUE(cmod_propagation(v));
732 EXPECT_EQ(0, block0->start_ip);
733 EXPECT_EQ(0, block0->end_ip);
734 EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
735 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
736 }
737
738 TEST_F(cmod_propagation_test, plnnz_cmpz)
739 {
740 const fs_builder &bld = v->bld;
741
742 fs_reg dst0 = v->vgrf(glsl_type::float_type);
743 fs_reg src0 = v->vgrf(glsl_type::float_type);
744 fs_reg zero(brw_imm_f(0));
745
746 set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
747 bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_Z);
748
749 /* = Before =
750 * 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
751 * 1: cmp.z.f0.0(8) null:F, vgrf0:F, 0f
752 *
753 * = After =
754 * 0: pln.z.f0.0(8) vgrf0:F, vgrf1:F, 0f
755 */
756
757 v->calculate_cfg();
758 bblock_t *block0 = v->cfg->blocks[0];
759
760 EXPECT_TRUE(cmod_propagation(v));
761 EXPECT_EQ(0, block0->start_ip);
762 EXPECT_EQ(0, block0->end_ip);
763 EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
764 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
765 }
766
767 TEST_F(cmod_propagation_test, plnnz_sel_cmpz)
768 {
769 const fs_builder &bld = v->bld;
770
771 fs_reg dst0 = v->vgrf(glsl_type::float_type);
772 fs_reg dst1 = v->vgrf(glsl_type::float_type);
773 fs_reg src0 = v->vgrf(glsl_type::float_type);
774 fs_reg zero(brw_imm_f(0));
775
776 set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
777 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dst1, src0, zero));
778 bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_Z);
779
780 /* = Before =
781 * 0: pln.nz.f0.0(8) vgrf0:F, vgrf2:F, 0f
782 * 1: (+f0.0) sel(8) vgrf1:F, vgrf2:F, 0f
783 * 2: cmp.z.f0.0(8) null:F, vgrf0:F, 0f
784 *
785 * = After =
786 * (no changes)
787 */
788
789 v->calculate_cfg();
790 bblock_t *block0 = v->cfg->blocks[0];
791
792 EXPECT_FALSE(cmod_propagation(v));
793 EXPECT_EQ(0, block0->start_ip);
794 EXPECT_EQ(2, block0->end_ip);
795 EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
796 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
797 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
798 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
799 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
800 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 2)->conditional_mod);
801 }
802
803 TEST_F(cmod_propagation_test, cmp_cmpg_D)
804 {
805 const fs_builder &bld = v->bld;
806
807 fs_reg dst0 = v->vgrf(glsl_type::int_type);
808 fs_reg src0 = v->vgrf(glsl_type::int_type);
809 fs_reg zero(brw_imm_d(0));
810 fs_reg one(brw_imm_d(1));
811
812 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
813 bld.CMP(bld.null_reg_d(), dst0, zero, BRW_CONDITIONAL_G);
814
815 /* = Before =
816 * 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
817 * 1: cmp.g.f0.0(8) null:D, vgrf0:D, 0d
818 *
819 * = After =
820 * (no changes)
821 */
822
823 v->calculate_cfg();
824 bblock_t *block0 = v->cfg->blocks[0];
825
826 EXPECT_FALSE(cmod_propagation(v));
827 EXPECT_EQ(0, block0->start_ip);
828 EXPECT_EQ(1, block0->end_ip);
829 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
830 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
831 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
832 EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 1)->conditional_mod);
833 }
834
835 TEST_F(cmod_propagation_test, cmp_cmpg_UD)
836 {
837 const fs_builder &bld = v->bld;
838
839 fs_reg dst0 = v->vgrf(glsl_type::uint_type);
840 fs_reg src0 = v->vgrf(glsl_type::uint_type);
841 fs_reg zero(brw_imm_ud(0));
842
843 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
844 bld.CMP(bld.null_reg_ud(), dst0, zero, BRW_CONDITIONAL_G);
845
846 /* = Before =
847 * 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
848 * 1: cmp.g.f0.0(8) null:UD, vgrf0:UD, 0u
849 *
850 * = After =
851 * 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
852 */
853
854 v->calculate_cfg();
855 bblock_t *block0 = v->cfg->blocks[0];
856
857 EXPECT_TRUE(cmod_propagation(v));
858 EXPECT_EQ(0, block0->start_ip);
859 EXPECT_EQ(0, block0->end_ip);
860 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
861 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
862 }
863
864 TEST_F(cmod_propagation_test, cmp_cmpl_D)
865 {
866 const fs_builder &bld = v->bld;
867
868 fs_reg dst0 = v->vgrf(glsl_type::int_type);
869 fs_reg src0 = v->vgrf(glsl_type::int_type);
870 fs_reg zero(brw_imm_d(0));
871
872 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
873 bld.CMP(bld.null_reg_d(), dst0, zero, BRW_CONDITIONAL_L);
874
875 /* = Before =
876 * 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
877 * 1: cmp.l.f0.0(8) null:D, vgrf0:D, 0d
878 *
879 * = After =
880 * 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
881 */
882
883 v->calculate_cfg();
884 bblock_t *block0 = v->cfg->blocks[0];
885
886 EXPECT_TRUE(cmod_propagation(v));
887 EXPECT_EQ(0, block0->start_ip);
888 EXPECT_EQ(0, block0->end_ip);
889 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
890 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
891 }
892
893 TEST_F(cmod_propagation_test, cmp_cmpl_UD)
894 {
895 const fs_builder &bld = v->bld;
896
897 fs_reg dst0 = v->vgrf(glsl_type::uint_type);
898 fs_reg src0 = v->vgrf(glsl_type::uint_type);
899 fs_reg zero(brw_imm_ud(0));
900
901 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
902 bld.CMP(bld.null_reg_ud(), dst0, zero, BRW_CONDITIONAL_L);
903
904 /* = Before =
905 * 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
906 * 1: cmp.l.f0.0(8) null:UD, vgrf0:UD, 0u
907 *
908 * = After =
909 * (no changes)
910 */
911
912 v->calculate_cfg();
913 bblock_t *block0 = v->cfg->blocks[0];
914
915 EXPECT_FALSE(cmod_propagation(v));
916 EXPECT_EQ(0, block0->start_ip);
917 EXPECT_EQ(1, block0->end_ip);
918 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
919 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
920 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
921 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
922 }
923
924 TEST_F(cmod_propagation_test, andz_one)
925 {
926 const fs_builder &bld = v->bld;
927 fs_reg dest = v->vgrf(glsl_type::int_type);
928 fs_reg src0 = v->vgrf(glsl_type::float_type);
929 fs_reg zero(brw_imm_f(0.0f));
930 fs_reg one(brw_imm_d(1));
931
932 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
933 set_condmod(BRW_CONDITIONAL_Z,
934 bld.AND(bld.null_reg_d(), dest, one));
935
936 /* = Before =
937 * 0: cmp.l.f0(8) dest:F src0:F 0F
938 * 1: and.z.f0(8) null:D dest:D 1D
939 *
940 * = After =
941 * (no changes)
942 */
943
944 v->calculate_cfg();
945 bblock_t *block0 = v->cfg->blocks[0];
946
947 EXPECT_EQ(0, block0->start_ip);
948 EXPECT_EQ(1, block0->end_ip);
949
950 EXPECT_FALSE(cmod_propagation(v));
951 EXPECT_EQ(0, block0->start_ip);
952 EXPECT_EQ(1, block0->end_ip);
953 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
954 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
955 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
956 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
957 }
958
959 TEST_F(cmod_propagation_test, add_not_merge_with_compare)
960 {
961 const fs_builder &bld = v->bld;
962 fs_reg dest = v->vgrf(glsl_type::float_type);
963 fs_reg src0 = v->vgrf(glsl_type::float_type);
964 fs_reg src1 = v->vgrf(glsl_type::float_type);
965 bld.ADD(dest, src0, src1);
966 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
967
968 /* The addition and the implicit subtraction in the compare do not compute
969 * related values.
970 *
971 * = Before =
972 * 0: add(8) dest:F src0:F src1:F
973 * 1: cmp.l.f0(8) null:F src0:F src1:F
974 *
975 * = After =
976 * (no changes)
977 */
978 v->calculate_cfg();
979 bblock_t *block0 = v->cfg->blocks[0];
980
981 EXPECT_EQ(0, block0->start_ip);
982 EXPECT_EQ(1, block0->end_ip);
983
984 EXPECT_FALSE(cmod_propagation(v));
985 EXPECT_EQ(0, block0->start_ip);
986 EXPECT_EQ(1, block0->end_ip);
987 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
988 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
989 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
990 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
991 }
992
993 TEST_F(cmod_propagation_test, subtract_merge_with_compare)
994 {
995 const fs_builder &bld = v->bld;
996 fs_reg dest = v->vgrf(glsl_type::float_type);
997 fs_reg src0 = v->vgrf(glsl_type::float_type);
998 fs_reg src1 = v->vgrf(glsl_type::float_type);
999 bld.ADD(dest, src0, negate(src1));
1000 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1001
1002 /* = Before =
1003 * 0: add(8) dest:F src0:F -src1:F
1004 * 1: cmp.l.f0(8) null:F src0:F src1:F
1005 *
1006 * = After =
1007 * 0: add.l.f0(8) dest:F src0:F -src1:F
1008 */
1009 v->calculate_cfg();
1010 bblock_t *block0 = v->cfg->blocks[0];
1011
1012 EXPECT_EQ(0, block0->start_ip);
1013 EXPECT_EQ(1, block0->end_ip);
1014
1015 EXPECT_TRUE(cmod_propagation(v));
1016 EXPECT_EQ(0, block0->start_ip);
1017 EXPECT_EQ(0, block0->end_ip);
1018 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1019 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1020 }
1021
1022 TEST_F(cmod_propagation_test, subtract_immediate_merge_with_compare)
1023 {
1024 const fs_builder &bld = v->bld;
1025 fs_reg dest = v->vgrf(glsl_type::float_type);
1026 fs_reg src0 = v->vgrf(glsl_type::float_type);
1027 fs_reg one(brw_imm_f(1.0f));
1028 fs_reg negative_one(brw_imm_f(-1.0f));
1029
1030 bld.ADD(dest, src0, negative_one);
1031 bld.CMP(bld.null_reg_f(), src0, one, BRW_CONDITIONAL_NZ);
1032
1033 /* = Before =
1034 * 0: add(8) dest:F src0:F -1.0f
1035 * 1: cmp.nz.f0(8) null:F src0:F 1.0f
1036 *
1037 * = After =
1038 * 0: add.nz.f0(8) dest:F src0:F -1.0f
1039 */
1040 v->calculate_cfg();
1041 bblock_t *block0 = v->cfg->blocks[0];
1042
1043 EXPECT_EQ(0, block0->start_ip);
1044 EXPECT_EQ(1, block0->end_ip);
1045
1046 EXPECT_TRUE(cmod_propagation(v));
1047 EXPECT_EQ(0, block0->start_ip);
1048 EXPECT_EQ(0, block0->end_ip);
1049 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1050 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
1051 }
1052
1053 TEST_F(cmod_propagation_test, subtract_merge_with_compare_intervening_add)
1054 {
1055 const fs_builder &bld = v->bld;
1056 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1057 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1058 fs_reg src0 = v->vgrf(glsl_type::float_type);
1059 fs_reg src1 = v->vgrf(glsl_type::float_type);
1060 bld.ADD(dest0, src0, negate(src1));
1061 bld.ADD(dest1, src0, src1);
1062 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1063
1064 /* = Before =
1065 * 0: add(8) dest0:F src0:F -src1:F
1066 * 1: add(8) dest1:F src0:F src1:F
1067 * 2: cmp.l.f0(8) null:F src0:F src1:F
1068 *
1069 * = After =
1070 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1071 * 1: add(8) dest1:F src0:F src1:F
1072 */
1073 v->calculate_cfg();
1074 bblock_t *block0 = v->cfg->blocks[0];
1075
1076 EXPECT_EQ(0, block0->start_ip);
1077 EXPECT_EQ(2, block0->end_ip);
1078
1079 EXPECT_TRUE(cmod_propagation(v));
1080 EXPECT_EQ(0, block0->start_ip);
1081 EXPECT_EQ(1, block0->end_ip);
1082 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1083 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1084 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1085 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
1086 }
1087
1088 TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_partial_write)
1089 {
1090 const fs_builder &bld = v->bld;
1091 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1092 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1093 fs_reg src0 = v->vgrf(glsl_type::float_type);
1094 fs_reg src1 = v->vgrf(glsl_type::float_type);
1095 bld.ADD(dest0, src0, negate(src1));
1096 set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, src0, negate(src1)));
1097 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1098
1099 /* = Before =
1100 * 0: add(8) dest0:F src0:F -src1:F
1101 * 1: (+f0) add(8) dest1:F src0:F -src1:F
1102 * 2: cmp.l.f0(8) null:F src0:F src1:F
1103 *
1104 * = After =
1105 * (no changes)
1106 */
1107 v->calculate_cfg();
1108 bblock_t *block0 = v->cfg->blocks[0];
1109
1110 EXPECT_EQ(0, block0->start_ip);
1111 EXPECT_EQ(2, block0->end_ip);
1112
1113 EXPECT_FALSE(cmod_propagation(v));
1114 EXPECT_EQ(0, block0->start_ip);
1115 EXPECT_EQ(2, block0->end_ip);
1116 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1117 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1118 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1119 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
1120 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
1121 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
1122 }
1123
1124 TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_add)
1125 {
1126 const fs_builder &bld = v->bld;
1127 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1128 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1129 fs_reg src0 = v->vgrf(glsl_type::float_type);
1130 fs_reg src1 = v->vgrf(glsl_type::float_type);
1131 bld.ADD(dest0, src0, negate(src1));
1132 set_condmod(BRW_CONDITIONAL_EQ, bld.ADD(dest1, src0, src1));
1133 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1134
1135 /* = Before =
1136 * 0: add(8) dest0:F src0:F -src1:F
1137 * 1: add.z.f0(8) dest1:F src0:F src1:F
1138 * 2: cmp.l.f0(8) null:F src0:F src1:F
1139 *
1140 * = After =
1141 * (no changes)
1142 */
1143 v->calculate_cfg();
1144 bblock_t *block0 = v->cfg->blocks[0];
1145
1146 EXPECT_EQ(0, block0->start_ip);
1147 EXPECT_EQ(2, block0->end_ip);
1148
1149 EXPECT_FALSE(cmod_propagation(v));
1150 EXPECT_EQ(0, block0->start_ip);
1151 EXPECT_EQ(2, block0->end_ip);
1152 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1153 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1154 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1155 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
1156 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
1157 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
1158 }
1159
1160 TEST_F(cmod_propagation_test, add_merge_with_compare)
1161 {
1162 const fs_builder &bld = v->bld;
1163 fs_reg dest = v->vgrf(glsl_type::float_type);
1164 fs_reg src0 = v->vgrf(glsl_type::float_type);
1165 fs_reg src1 = v->vgrf(glsl_type::float_type);
1166 bld.ADD(dest, src0, src1);
1167 bld.CMP(bld.null_reg_f(), src0, negate(src1), BRW_CONDITIONAL_L);
1168
1169 /* = Before =
1170 * 0: add(8) dest:F src0:F src1:F
1171 * 1: cmp.l.f0(8) null:F src0:F -src1:F
1172 *
1173 * = After =
1174 * 0: add.l.f0(8) dest:F src0:F src1:F
1175 */
1176 v->calculate_cfg();
1177 bblock_t *block0 = v->cfg->blocks[0];
1178
1179 EXPECT_EQ(0, block0->start_ip);
1180 EXPECT_EQ(1, block0->end_ip);
1181
1182 EXPECT_TRUE(cmod_propagation(v));
1183 EXPECT_EQ(0, block0->start_ip);
1184 EXPECT_EQ(0, block0->end_ip);
1185 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1186 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1187 }
1188
1189 TEST_F(cmod_propagation_test, negative_subtract_merge_with_compare)
1190 {
1191 const fs_builder &bld = v->bld;
1192 fs_reg dest = v->vgrf(glsl_type::float_type);
1193 fs_reg src0 = v->vgrf(glsl_type::float_type);
1194 fs_reg src1 = v->vgrf(glsl_type::float_type);
1195 bld.ADD(dest, src1, negate(src0));
1196 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1197
1198 /* The result of the subtract is the negatiion of the result of the
1199 * implicit subtract in the compare, so the condition must change.
1200 *
1201 * = Before =
1202 * 0: add(8) dest:F src1:F -src0:F
1203 * 1: cmp.l.f0(8) null:F src0:F src1:F
1204 *
1205 * = After =
1206 * 0: add.g.f0(8) dest:F src0:F -src1:F
1207 */
1208 v->calculate_cfg();
1209 bblock_t *block0 = v->cfg->blocks[0];
1210
1211 EXPECT_EQ(0, block0->start_ip);
1212 EXPECT_EQ(1, block0->end_ip);
1213
1214 EXPECT_TRUE(cmod_propagation(v));
1215 EXPECT_EQ(0, block0->start_ip);
1216 EXPECT_EQ(0, block0->end_ip);
1217 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1218 EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod);
1219 }
1220
1221 TEST_F(cmod_propagation_test, subtract_delete_compare)
1222 {
1223 const fs_builder &bld = v->bld;
1224 fs_reg dest = v->vgrf(glsl_type::float_type);
1225 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1226 fs_reg src0 = v->vgrf(glsl_type::float_type);
1227 fs_reg src1 = v->vgrf(glsl_type::float_type);
1228 fs_reg src2 = v->vgrf(glsl_type::float_type);
1229
1230 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)));
1231 set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2));
1232 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1233
1234 /* = Before =
1235 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1236 * 1: (+f0) mov(0) dest1:F src2:F
1237 * 2: cmp.l.f0(8) null:F src0:F src1:F
1238 *
1239 * = After =
1240 * 0: add.l.f0(8) dest:F src0:F -src1:F
1241 * 1: (+f0) mov(0) dest1:F src2:F
1242 */
1243 v->calculate_cfg();
1244 bblock_t *block0 = v->cfg->blocks[0];
1245
1246 EXPECT_EQ(0, block0->start_ip);
1247 EXPECT_EQ(2, block0->end_ip);
1248
1249 EXPECT_TRUE(cmod_propagation(v));
1250 EXPECT_EQ(0, block0->start_ip);
1251 EXPECT_EQ(1, block0->end_ip);
1252 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1253 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1254 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
1255 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1256 }
1257
1258 TEST_F(cmod_propagation_test, subtract_delete_compare_other_flag)
1259 {
1260 /* This test is the same as subtract_delete_compare but it explicitly used
1261 * flag f0.1 for the subtraction and the comparison.
1262 */
1263 const fs_builder &bld = v->bld;
1264 fs_reg dest = v->vgrf(glsl_type::float_type);
1265 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1266 fs_reg src0 = v->vgrf(glsl_type::float_type);
1267 fs_reg src1 = v->vgrf(glsl_type::float_type);
1268 fs_reg src2 = v->vgrf(glsl_type::float_type);
1269
1270 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)))
1271 ->flag_subreg = 1;
1272 set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2));
1273 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
1274 ->flag_subreg = 1;
1275
1276 /* = Before =
1277 * 0: add.l.f0.1(8) dest0:F src0:F -src1:F
1278 * 1: (+f0) mov(0) dest1:F src2:F
1279 * 2: cmp.l.f0.1(8) null:F src0:F src1:F
1280 *
1281 * = After =
1282 * 0: add.l.f0.1(8) dest:F src0:F -src1:F
1283 * 1: (+f0) mov(0) dest1:F src2:F
1284 */
1285 v->calculate_cfg();
1286 bblock_t *block0 = v->cfg->blocks[0];
1287
1288 EXPECT_EQ(0, block0->start_ip);
1289 EXPECT_EQ(2, block0->end_ip);
1290
1291 EXPECT_TRUE(cmod_propagation(v));
1292 EXPECT_EQ(0, block0->start_ip);
1293 EXPECT_EQ(1, block0->end_ip);
1294 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1295 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1296 EXPECT_EQ(1, instruction(block0, 0)->flag_subreg);
1297 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
1298 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1299 }
1300
1301 TEST_F(cmod_propagation_test, subtract_to_mismatch_flag)
1302 {
1303 const fs_builder &bld = v->bld;
1304 fs_reg dest = v->vgrf(glsl_type::float_type);
1305 fs_reg src0 = v->vgrf(glsl_type::float_type);
1306 fs_reg src1 = v->vgrf(glsl_type::float_type);
1307
1308 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)));
1309 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
1310 ->flag_subreg = 1;
1311
1312 /* = Before =
1313 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1314 * 1: cmp.l.f0.1(8) null:F src0:F src1:F
1315 *
1316 * = After =
1317 * No changes
1318 */
1319 v->calculate_cfg();
1320 bblock_t *block0 = v->cfg->blocks[0];
1321
1322 EXPECT_EQ(0, block0->start_ip);
1323 EXPECT_EQ(1, block0->end_ip);
1324
1325 EXPECT_FALSE(cmod_propagation(v));
1326 EXPECT_EQ(0, block0->start_ip);
1327 EXPECT_EQ(1, block0->end_ip);
1328 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1329 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1330 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
1331 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
1332 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
1333 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
1334 }
1335
1336 TEST_F(cmod_propagation_test,
1337 subtract_merge_with_compare_intervening_mismatch_flag_write)
1338 {
1339 const fs_builder &bld = v->bld;
1340 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1341 fs_reg src0 = v->vgrf(glsl_type::float_type);
1342 fs_reg src1 = v->vgrf(glsl_type::float_type);
1343
1344 bld.ADD(dest0, src0, negate(src1));
1345 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
1346 ->flag_subreg = 1;
1347 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1348
1349 /* = Before =
1350 * 0: add(8) dest0:F src0:F -src1:F
1351 * 1: cmp.l.f0.1(8) null:F src0:F src1:F
1352 * 2: cmp.l.f0(8) null:F src0:F src1:F
1353 *
1354 * = After =
1355 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1356 * 1: cmp.l.f0.1(8) null:F src0:F src1:F
1357 *
1358 * NOTE: Another perfectly valid after sequence would be:
1359 *
1360 * 0: add.f0.1(8) dest0:F src0:F -src1:F
1361 * 1: cmp.l.f0(8) null:F src0:F src1:F
1362 *
1363 * However, the optimization pass starts at the end of the basic block.
1364 * Because of this, the cmp.l.f0 will always be chosen. If the pass
1365 * changes its strategy, this test will also need to change.
1366 */
1367 v->calculate_cfg();
1368 bblock_t *block0 = v->cfg->blocks[0];
1369
1370 EXPECT_EQ(0, block0->start_ip);
1371 EXPECT_EQ(2, block0->end_ip);
1372
1373 EXPECT_TRUE(cmod_propagation(v));
1374 EXPECT_EQ(0, block0->start_ip);
1375 EXPECT_EQ(1, block0->end_ip);
1376 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1377 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1378 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
1379 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
1380 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
1381 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
1382 }
1383
1384 TEST_F(cmod_propagation_test,
1385 subtract_merge_with_compare_intervening_mismatch_flag_read)
1386 {
1387 const fs_builder &bld = v->bld;
1388 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1389 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1390 fs_reg src0 = v->vgrf(glsl_type::float_type);
1391 fs_reg src1 = v->vgrf(glsl_type::float_type);
1392 fs_reg src2 = v->vgrf(glsl_type::float_type);
1393 fs_reg zero(brw_imm_f(0.0f));
1394
1395 bld.ADD(dest0, src0, negate(src1));
1396 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
1397 ->flag_subreg = 1;
1398 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1399
1400 /* = Before =
1401 * 0: add(8) dest0:F src0:F -src1:F
1402 * 1: (+f0.1) sel(8) dest1 src2 0.0f
1403 * 2: cmp.l.f0(8) null:F src0:F src1:F
1404 *
1405 * = After =
1406 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1407 * 1: (+f0.1) sel(8) dest1 src2 0.0f
1408 */
1409 v->calculate_cfg();
1410 bblock_t *block0 = v->cfg->blocks[0];
1411
1412 EXPECT_EQ(0, block0->start_ip);
1413 EXPECT_EQ(2, block0->end_ip);
1414
1415 EXPECT_TRUE(cmod_propagation(v));
1416 EXPECT_EQ(0, block0->start_ip);
1417 EXPECT_EQ(1, block0->end_ip);
1418 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1419 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1420 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
1421 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
1422 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1423 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
1424 }
1425
1426 TEST_F(cmod_propagation_test, subtract_delete_compare_derp)
1427 {
1428 const fs_builder &bld = v->bld;
1429 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1430 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1431 fs_reg src0 = v->vgrf(glsl_type::float_type);
1432 fs_reg src1 = v->vgrf(glsl_type::float_type);
1433
1434 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest0, src0, negate(src1)));
1435 set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, negate(src0), src1));
1436 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1437
1438 /* = Before =
1439 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1440 * 1: (+f0) add(0) dest1:F -src0:F src1:F
1441 * 2: cmp.l.f0(8) null:F src0:F src1:F
1442 *
1443 * = After =
1444 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1445 * 1: (+f0) add(0) dest1:F -src0:F src1:F
1446 */
1447 v->calculate_cfg();
1448 bblock_t *block0 = v->cfg->blocks[0];
1449
1450 EXPECT_EQ(0, block0->start_ip);
1451 EXPECT_EQ(2, block0->end_ip);
1452
1453 EXPECT_TRUE(cmod_propagation(v));
1454 EXPECT_EQ(0, block0->start_ip);
1455 EXPECT_EQ(1, block0->end_ip);
1456 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1457 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1458 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1459 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1460 }
1461
1462 TEST_F(cmod_propagation_test, signed_unsigned_comparison_mismatch)
1463 {
1464 const fs_builder &bld = v->bld;
1465 fs_reg dest0 = v->vgrf(glsl_type::int_type);
1466 fs_reg src0 = v->vgrf(glsl_type::int_type);
1467 src0.type = BRW_REGISTER_TYPE_W;
1468
1469 bld.ASR(dest0, negate(src0), brw_imm_d(15));
1470 bld.CMP(bld.null_reg_ud(), retype(dest0, BRW_REGISTER_TYPE_UD),
1471 brw_imm_ud(0u), BRW_CONDITIONAL_LE);
1472
1473 /* = Before =
1474 * 0: asr(8) dest:D -src0:W 15D
1475 * 1: cmp.le.f0(8) null:UD dest:UD 0UD
1476 *
1477 * = After =
1478 * (no changes)
1479 */
1480 v->calculate_cfg();
1481 bblock_t *block0 = v->cfg->blocks[0];
1482
1483 EXPECT_EQ(0, block0->start_ip);
1484 EXPECT_EQ(1, block0->end_ip);
1485
1486 EXPECT_FALSE(cmod_propagation(v));
1487 EXPECT_EQ(0, block0->start_ip);
1488 EXPECT_EQ(1, block0->end_ip);
1489 EXPECT_EQ(BRW_OPCODE_ASR, instruction(block0, 0)->opcode);
1490 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
1491 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 1)->conditional_mod);
1492 }
1493
1494 void
1495 cmod_propagation_test::test_positive_float_saturate_prop(enum brw_conditional_mod before,
1496 enum brw_conditional_mod after,
1497 enum opcode op)
1498 {
1499 const fs_builder &bld = v->bld;
1500 fs_reg dest = v->vgrf(glsl_type::float_type);
1501 fs_reg src0 = v->vgrf(glsl_type::float_type);
1502 fs_reg src1 = v->vgrf(glsl_type::float_type);
1503 fs_reg zero(brw_imm_f(0.0f));
1504 bld.ADD(dest, src0, src1)->saturate = true;
1505
1506 assert(op == BRW_OPCODE_CMP || op == BRW_OPCODE_MOV);
1507 if (op == BRW_OPCODE_CMP)
1508 bld.CMP(bld.null_reg_f(), dest, zero, before);
1509 else
1510 bld.MOV(bld.null_reg_f(), dest)->conditional_mod = before;
1511
1512 v->calculate_cfg();
1513 bblock_t *block0 = v->cfg->blocks[0];
1514
1515 EXPECT_EQ(0, block0->start_ip);
1516 EXPECT_EQ(1, block0->end_ip);
1517
1518 EXPECT_TRUE(cmod_propagation(v));
1519 EXPECT_EQ(0, block0->start_ip);
1520 EXPECT_EQ(0, block0->end_ip);
1521 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1522 EXPECT_TRUE(instruction(block0, 0)->saturate);
1523 EXPECT_EQ(after, instruction(block0, 0)->conditional_mod);
1524 }
1525
1526 void
1527 cmod_propagation_test::test_negative_float_saturate_prop(enum brw_conditional_mod before,
1528 enum opcode op)
1529 {
1530 const fs_builder &bld = v->bld;
1531 fs_reg dest = v->vgrf(glsl_type::float_type);
1532 fs_reg src0 = v->vgrf(glsl_type::float_type);
1533 fs_reg src1 = v->vgrf(glsl_type::float_type);
1534 fs_reg zero(brw_imm_f(0.0f));
1535 bld.ADD(dest, src0, src1)->saturate = true;
1536
1537 assert(op == BRW_OPCODE_CMP || op == BRW_OPCODE_MOV);
1538 if (op == BRW_OPCODE_CMP)
1539 bld.CMP(bld.null_reg_f(), dest, zero, before);
1540 else
1541 bld.MOV(bld.null_reg_f(), dest)->conditional_mod = before;
1542
1543 v->calculate_cfg();
1544 bblock_t *block0 = v->cfg->blocks[0];
1545
1546 EXPECT_EQ(0, block0->start_ip);
1547 EXPECT_EQ(1, block0->end_ip);
1548
1549 EXPECT_FALSE(cmod_propagation(v));
1550 EXPECT_EQ(0, block0->start_ip);
1551 EXPECT_EQ(1, block0->end_ip);
1552 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1553 EXPECT_TRUE(instruction(block0, 0)->saturate);
1554 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1555 EXPECT_EQ(op, instruction(block0, 1)->opcode);
1556 EXPECT_FALSE(instruction(block0, 1)->saturate);
1557 EXPECT_EQ(before, instruction(block0, 1)->conditional_mod);
1558 }
1559
1560 void
1561 cmod_propagation_test::test_negative_int_saturate_prop(enum brw_conditional_mod before,
1562 enum opcode op)
1563 {
1564 const fs_builder &bld = v->bld;
1565 fs_reg dest = v->vgrf(glsl_type::int_type);
1566 fs_reg src0 = v->vgrf(glsl_type::int_type);
1567 fs_reg src1 = v->vgrf(glsl_type::int_type);
1568 fs_reg zero(brw_imm_d(0));
1569 bld.ADD(dest, src0, src1)->saturate = true;
1570
1571 assert(op == BRW_OPCODE_CMP || op == BRW_OPCODE_MOV);
1572 if (op == BRW_OPCODE_CMP)
1573 bld.CMP(bld.null_reg_d(), dest, zero, before);
1574 else
1575 bld.MOV(bld.null_reg_d(), dest)->conditional_mod = before;
1576
1577 v->calculate_cfg();
1578 bblock_t *block0 = v->cfg->blocks[0];
1579
1580 EXPECT_EQ(0, block0->start_ip);
1581 EXPECT_EQ(1, block0->end_ip);
1582
1583 EXPECT_FALSE(cmod_propagation(v));
1584 EXPECT_EQ(0, block0->start_ip);
1585 EXPECT_EQ(1, block0->end_ip);
1586 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1587 EXPECT_TRUE(instruction(block0, 0)->saturate);
1588 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1589 EXPECT_EQ(op, instruction(block0, 1)->opcode);
1590 EXPECT_FALSE(instruction(block0, 1)->saturate);
1591 EXPECT_EQ(before, instruction(block0, 1)->conditional_mod);
1592 }
1593
1594 TEST_F(cmod_propagation_test, float_saturate_nz_cmp)
1595 {
1596 /* With the saturate modifier, the comparison happens before clamping to
1597 * [0, 1]. (sat(x) != 0) == (x > 0).
1598 *
1599 * = Before =
1600 *
1601 * 0: add.sat(8) dest src0 src1
1602 * 1: cmp.nz.f0(8) null dest 0.0f
1603 *
1604 * = After =
1605 * 0: add.sat.g.f0(8) dest src0 src1
1606 */
1607 test_positive_float_saturate_prop(BRW_CONDITIONAL_NZ, BRW_CONDITIONAL_G,
1608 BRW_OPCODE_CMP);
1609 }
1610
1611 TEST_F(cmod_propagation_test, float_saturate_nz_mov)
1612 {
1613 /* With the saturate modifier, the comparison happens before clamping to
1614 * [0, 1]. (sat(x) != 0) == (x > 0).
1615 *
1616 * = Before =
1617 *
1618 * 0: add.sat(8) dest src0 src1
1619 * 1: mov.nz.f0(8) null dest
1620 *
1621 * = After =
1622 * 0: add.sat.g.f0(8) dest src0 src1
1623 */
1624 test_positive_float_saturate_prop(BRW_CONDITIONAL_NZ, BRW_CONDITIONAL_G,
1625 BRW_OPCODE_MOV);
1626 }
1627
1628 TEST_F(cmod_propagation_test, float_saturate_z_cmp)
1629 {
1630 /* With the saturate modifier, the comparison happens before clamping to
1631 * [0, 1]. (sat(x) == 0) == (x <= 0).
1632 *
1633 * = Before =
1634 *
1635 * 0: add.sat(8) dest src0 src1
1636 * 1: cmp.z.f0(8) null dest 0.0f
1637 *
1638 * = After =
1639 * 0: add.sat.le.f0(8) dest src0 src1
1640 */
1641 test_positive_float_saturate_prop(BRW_CONDITIONAL_Z, BRW_CONDITIONAL_LE,
1642 BRW_OPCODE_CMP);
1643 }
1644
1645 TEST_F(cmod_propagation_test, float_saturate_z_mov)
1646 {
1647 /* With the saturate modifier, the comparison happens before clamping to
1648 * [0, 1]. (sat(x) == 0) == (x <= 0).
1649 *
1650 * = Before =
1651 *
1652 * 0: add.sat(8) dest src0 src1
1653 * 1: mov.z.f0(8) null dest
1654 *
1655 * = After =
1656 * 0: add.sat.le.f0(8) dest src0 src1
1657 */
1658 #if 1
1659 /* cmod propagation bails on every MOV except MOV.NZ. */
1660 test_negative_float_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_MOV);
1661 #else
1662 test_positive_float_saturate_prop(BRW_CONDITIONAL_Z, BRW_CONDITIONAL_LE,
1663 BRW_OPCODE_MOV);
1664 #endif
1665 }
1666
1667 TEST_F(cmod_propagation_test, float_saturate_g_cmp)
1668 {
1669 /* With the saturate modifier, the comparison happens before clamping to
1670 * [0, 1]. (sat(x) > 0) == (x > 0).
1671 *
1672 * = Before =
1673 *
1674 * 0: add.sat(8) dest src0 src1
1675 * 1: cmp.g.f0(8) null dest 0.0f
1676 *
1677 * = After =
1678 * 0: add.sat.g.f0(8) dest src0 src1
1679 */
1680 test_positive_float_saturate_prop(BRW_CONDITIONAL_G, BRW_CONDITIONAL_G,
1681 BRW_OPCODE_CMP);
1682 }
1683
1684 TEST_F(cmod_propagation_test, float_saturate_g_mov)
1685 {
1686 /* With the saturate modifier, the comparison happens before clamping to
1687 * [0, 1]. (sat(x) > 0) == (x > 0).
1688 *
1689 * = Before =
1690 *
1691 * 0: add.sat(8) dest src0 src1
1692 * 1: mov.g.f0(8) null dest
1693 *
1694 * = After =
1695 * 0: add.sat.g.f0(8) dest src0 src1
1696 */
1697 #if 1
1698 /* cmod propagation bails on every MOV except MOV.NZ. */
1699 test_negative_float_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_MOV);
1700 #else
1701 test_positive_float_saturate_prop(BRW_CONDITIONAL_G, BRW_CONDITIONAL_G,
1702 BRW_OPCODE_MOV);
1703 #endif
1704 }
1705
1706 TEST_F(cmod_propagation_test, float_saturate_le_cmp)
1707 {
1708 /* With the saturate modifier, the comparison happens before clamping to
1709 * [0, 1]. (sat(x) <= 0) == (x <= 0).
1710 *
1711 * = Before =
1712 *
1713 * 0: add.sat(8) dest src0 src1
1714 * 1: cmp.le.f0(8) null dest 0.0f
1715 *
1716 * = After =
1717 * 0: add.sat.le.f0(8) dest src0 src1
1718 */
1719 test_positive_float_saturate_prop(BRW_CONDITIONAL_LE, BRW_CONDITIONAL_LE,
1720 BRW_OPCODE_CMP);
1721 }
1722
1723 TEST_F(cmod_propagation_test, float_saturate_le_mov)
1724 {
1725 /* With the saturate modifier, the comparison happens before clamping to
1726 * [0, 1]. (sat(x) <= 0) == (x <= 0).
1727 *
1728 * = Before =
1729 *
1730 * 0: add.sat(8) dest src0 src1
1731 * 1: mov.le.f0(8) null dest
1732 *
1733 * = After =
1734 * 0: add.sat.le.f0(8) dest src0 src1
1735 */
1736 #if 1
1737 /* cmod propagation bails on every MOV except MOV.NZ. */
1738 test_negative_float_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_MOV);
1739 #else
1740 test_positive_float_saturate_prop(BRW_CONDITIONAL_LE, BRW_CONDITIONAL_LE,
1741 BRW_OPCODE_MOV);
1742 #endif
1743 }
1744
1745 TEST_F(cmod_propagation_test, float_saturate_l_cmp)
1746 {
1747 /* With the saturate modifier, the comparison happens before clamping to
1748 * [0, 1]. There is no before / after equivalence for (sat(x) < 0).
1749 *
1750 * = Before =
1751 *
1752 * 0: add.sat(8) dest src0 src1
1753 * 1: cmp.l.f0(8) null dest 0.0f
1754 *
1755 * = After =
1756 * No change
1757 */
1758 test_negative_float_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_CMP);
1759 }
1760
1761 #if 0
1762 TEST_F(cmod_propagation_test, float_saturate_l_mov)
1763 {
1764 /* With the saturate modifier, the comparison happens before clamping to
1765 * [0, 1]. There is no before / after equivalence for (sat(x) < 0).
1766 *
1767 * = Before =
1768 *
1769 * 0: add.sat(8) dest src0 src1
1770 * 1: mov.l.f0(8) null dest 0.0f
1771 *
1772 * = After =
1773 * No change
1774 */
1775 test_negative_float_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_MOV);
1776 }
1777 #endif
1778
1779 TEST_F(cmod_propagation_test, float_saturate_ge_cmp)
1780 {
1781 /* With the saturate modifier, the comparison happens before clamping to
1782 * [0, 1]. There is no before / after equivalence for (sat(x) >= 0).
1783 *
1784 * = Before =
1785 *
1786 * 0: add.sat(8) dest src0 src1
1787 * 1: cmp.ge.f0(8) null dest 0.0f
1788 *
1789 * = After =
1790 * No change
1791 */
1792 test_negative_float_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_CMP);
1793 }
1794
1795 TEST_F(cmod_propagation_test, float_saturate_ge_mov)
1796 {
1797 /* With the saturate modifier, the comparison happens before clamping to
1798 * [0, 1]. There is no before / after equivalence for (sat(x) >= 0).
1799 *
1800 * = Before =
1801 *
1802 * 0: add.sat(8) dest src0 src1
1803 * 1: mov.ge.f0(8) null dest 0.0f
1804 *
1805 * = After =
1806 * No change
1807 */
1808 test_negative_float_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_MOV);
1809 }
1810
1811 TEST_F(cmod_propagation_test, int_saturate_nz_cmp)
1812 {
1813 /* = Before =
1814 *
1815 * 0: add.sat(8) dest src0 src1
1816 * 1: cmp.nz.f0(8) null dest 0
1817 *
1818 * = After =
1819 * No change.
1820 */
1821 test_negative_int_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_CMP);
1822 }
1823
1824 TEST_F(cmod_propagation_test, int_saturate_nz_mov)
1825 {
1826 /* = Before =
1827 *
1828 * 0: add.sat(8) dest src0 src1
1829 * 1: mov.nz.f0(8) null dest
1830 *
1831 * = After =
1832 * No change.
1833 */
1834 test_negative_int_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_MOV);
1835 }
1836
1837 TEST_F(cmod_propagation_test, int_saturate_z_cmp)
1838 {
1839 /* = Before =
1840 *
1841 * 0: add.sat(8) dest src0 src1
1842 * 1: cmp.z.f0(8) null dest 0
1843 *
1844 * = After =
1845 * No change.
1846 */
1847 test_negative_int_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_CMP);
1848 }
1849
1850 TEST_F(cmod_propagation_test, int_saturate_z_mov)
1851 {
1852 /* With the saturate modifier, the comparison happens before clamping to
1853 * [0, 1]. (sat(x) == 0) == (x <= 0).
1854 *
1855 * = Before =
1856 *
1857 * 0: add.sat(8) dest src0 src1
1858 * 1: mov.z.f0(8) null dest
1859 *
1860 * = After =
1861 * No change.
1862 */
1863 test_negative_int_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_MOV);
1864 }
1865
1866 TEST_F(cmod_propagation_test, int_saturate_g_cmp)
1867 {
1868 /* = Before =
1869 *
1870 * 0: add.sat(8) dest src0 src1
1871 * 1: cmp.g.f0(8) null dest 0
1872 *
1873 * = After =
1874 * No change.
1875 */
1876 test_negative_int_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_CMP);
1877 }
1878
1879 TEST_F(cmod_propagation_test, int_saturate_g_mov)
1880 {
1881 /* = Before =
1882 *
1883 * 0: add.sat(8) dest src0 src1
1884 * 1: mov.g.f0(8) null dest
1885 *
1886 * = After =
1887 * No change.
1888 */
1889 test_negative_int_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_MOV);
1890 }
1891
1892 TEST_F(cmod_propagation_test, int_saturate_le_cmp)
1893 {
1894 /* = Before =
1895 *
1896 * 0: add.sat(8) dest src0 src1
1897 * 1: cmp.le.f0(8) null dest 0
1898 *
1899 * = After =
1900 * No change.
1901 */
1902 test_negative_int_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_CMP);
1903 }
1904
1905 TEST_F(cmod_propagation_test, int_saturate_le_mov)
1906 {
1907 /* = Before =
1908 *
1909 * 0: add.sat(8) dest src0 src1
1910 * 1: mov.le.f0(8) null dest
1911 *
1912 * = After =
1913 * No change.
1914 */
1915 test_negative_int_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_MOV);
1916 }
1917
1918 TEST_F(cmod_propagation_test, int_saturate_l_cmp)
1919 {
1920 /* = Before =
1921 *
1922 * 0: add.sat(8) dest src0 src1
1923 * 1: cmp.l.f0(8) null dest 0
1924 *
1925 * = After =
1926 * No change
1927 */
1928 test_negative_int_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_CMP);
1929 }
1930
1931 TEST_F(cmod_propagation_test, int_saturate_l_mov)
1932 {
1933 /* = Before =
1934 *
1935 * 0: add.sat(8) dest src0 src1
1936 * 1: mov.l.f0(8) null dest 0
1937 *
1938 * = After =
1939 * No change
1940 */
1941 test_negative_int_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_MOV);
1942 }
1943
1944 TEST_F(cmod_propagation_test, int_saturate_ge_cmp)
1945 {
1946 /* = Before =
1947 *
1948 * 0: add.sat(8) dest src0 src1
1949 * 1: cmp.ge.f0(8) null dest 0
1950 *
1951 * = After =
1952 * No change
1953 */
1954 test_negative_int_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_CMP);
1955 }
1956
1957 TEST_F(cmod_propagation_test, int_saturate_ge_mov)
1958 {
1959 /* = Before =
1960 *
1961 * 0: add.sat(8) dest src0 src1
1962 * 1: mov.ge.f0(8) null dest
1963 *
1964 * = After =
1965 * No change
1966 */
1967 test_negative_int_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_MOV);
1968 }
1969
1970 TEST_F(cmod_propagation_test, not_to_or)
1971 {
1972 /* Exercise propagation of conditional modifier from a NOT instruction to
1973 * another ALU instruction as performed by cmod_propagate_not.
1974 */
1975 const fs_builder &bld = v->bld;
1976 fs_reg dest = v->vgrf(glsl_type::uint_type);
1977 fs_reg src0 = v->vgrf(glsl_type::uint_type);
1978 fs_reg src1 = v->vgrf(glsl_type::uint_type);
1979 bld.OR(dest, src0, src1);
1980 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
1981
1982 /* = Before =
1983 *
1984 * 0: or(8) dest src0 src1
1985 * 1: not.nz.f0(8) null dest
1986 *
1987 * = After =
1988 * 0: or.z.f0(8) dest src0 src1
1989 */
1990
1991 v->calculate_cfg();
1992 bblock_t *block0 = v->cfg->blocks[0];
1993
1994 EXPECT_EQ(0, block0->start_ip);
1995 EXPECT_EQ(1, block0->end_ip);
1996
1997 EXPECT_TRUE(cmod_propagation(v));
1998 EXPECT_EQ(0, block0->start_ip);
1999 EXPECT_EQ(0, block0->end_ip);
2000 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2001 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2002 }
2003
2004 TEST_F(cmod_propagation_test, not_to_and)
2005 {
2006 /* Exercise propagation of conditional modifier from a NOT instruction to
2007 * another ALU instruction as performed by cmod_propagate_not.
2008 */
2009 const fs_builder &bld = v->bld;
2010 fs_reg dest = v->vgrf(glsl_type::uint_type);
2011 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2012 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2013 bld.AND(dest, src0, src1);
2014 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
2015
2016 /* = Before =
2017 *
2018 * 0: and(8) dest src0 src1
2019 * 1: not.nz.f0(8) null dest
2020 *
2021 * = After =
2022 * 0: and.z.f0(8) dest src0 src1
2023 */
2024
2025 v->calculate_cfg();
2026 bblock_t *block0 = v->cfg->blocks[0];
2027
2028 EXPECT_EQ(0, block0->start_ip);
2029 EXPECT_EQ(1, block0->end_ip);
2030
2031 EXPECT_TRUE(cmod_propagation(v));
2032 EXPECT_EQ(0, block0->start_ip);
2033 EXPECT_EQ(0, block0->end_ip);
2034 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 0)->opcode);
2035 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2036 }
2037
2038 TEST_F(cmod_propagation_test, not_to_uadd)
2039 {
2040 /* Exercise propagation of conditional modifier from a NOT instruction to
2041 * another ALU instruction as performed by cmod_propagate_not.
2042 *
2043 * The optimization pass currently restricts to just OR and AND. It's
2044 * possible that this is too restrictive, and the actual, necessary
2045 * restriction is just the the destination type of the ALU instruction is
2046 * the same as the source type of the NOT instruction.
2047 */
2048 const fs_builder &bld = v->bld;
2049 fs_reg dest = v->vgrf(glsl_type::uint_type);
2050 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2051 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2052 bld.ADD(dest, src0, src1);
2053 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
2054
2055 /* = Before =
2056 *
2057 * 0: add(8) dest src0 src1
2058 * 1: not.nz.f0(8) null dest
2059 *
2060 * = After =
2061 * No changes
2062 */
2063
2064 v->calculate_cfg();
2065 bblock_t *block0 = v->cfg->blocks[0];
2066
2067 EXPECT_EQ(0, block0->start_ip);
2068 EXPECT_EQ(1, block0->end_ip);
2069
2070 EXPECT_FALSE(cmod_propagation(v));
2071 EXPECT_EQ(0, block0->start_ip);
2072 EXPECT_EQ(1, block0->end_ip);
2073 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2074 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2075 EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 1)->opcode);
2076 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
2077 }
2078
2079 TEST_F(cmod_propagation_test, not_to_fadd_to_ud)
2080 {
2081 /* Exercise propagation of conditional modifier from a NOT instruction to
2082 * another ALU instruction as performed by cmod_propagate_not.
2083 *
2084 * The optimization pass currently restricts to just OR and AND. It's
2085 * possible that this is too restrictive, and the actual, necessary
2086 * restriction is just the the destination type of the ALU instruction is
2087 * the same as the source type of the NOT instruction.
2088 */
2089 const fs_builder &bld = v->bld;
2090 fs_reg dest = v->vgrf(glsl_type::uint_type);
2091 fs_reg src0 = v->vgrf(glsl_type::float_type);
2092 fs_reg src1 = v->vgrf(glsl_type::float_type);
2093 bld.ADD(dest, src0, src1);
2094 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
2095
2096 /* = Before =
2097 *
2098 * 0: add(8) dest.ud src0.f src1.f
2099 * 1: not.nz.f0(8) null dest.ud
2100 *
2101 * = After =
2102 * No changes
2103 */
2104
2105 v->calculate_cfg();
2106 bblock_t *block0 = v->cfg->blocks[0];
2107
2108 EXPECT_EQ(0, block0->start_ip);
2109 EXPECT_EQ(1, block0->end_ip);
2110
2111 EXPECT_FALSE(cmod_propagation(v));
2112 EXPECT_EQ(0, block0->start_ip);
2113 EXPECT_EQ(1, block0->end_ip);
2114 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2115 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2116 EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 1)->opcode);
2117 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
2118 }
2119
2120 TEST_F(cmod_propagation_test, not_to_fadd)
2121 {
2122 /* Exercise propagation of conditional modifier from a NOT instruction to
2123 * another ALU instruction as performed by cmod_propagate_not.
2124 *
2125 * The optimization pass currently restricts to just OR and AND. It's
2126 * possible that this is too restrictive, and the actual, necessary
2127 * restriction is just the the destination type of the ALU instruction is
2128 * the same as the source type of the NOT instruction.
2129 */
2130 const fs_builder &bld = v->bld;
2131 fs_reg dest = v->vgrf(glsl_type::float_type);
2132 fs_reg src0 = v->vgrf(glsl_type::float_type);
2133 fs_reg src1 = v->vgrf(glsl_type::float_type);
2134 bld.ADD(dest, src0, src1);
2135 set_condmod(BRW_CONDITIONAL_NZ,
2136 bld.NOT(bld.null_reg_ud(),
2137 retype(dest, BRW_REGISTER_TYPE_UD)));
2138
2139 /* = Before =
2140 *
2141 * 0: add(8) dest.f src0.f src1.f
2142 * 1: not.nz.f0(8) null dest.ud
2143 *
2144 * = After =
2145 * No changes
2146 */
2147
2148 v->calculate_cfg();
2149 bblock_t *block0 = v->cfg->blocks[0];
2150
2151 EXPECT_EQ(0, block0->start_ip);
2152 EXPECT_EQ(1, block0->end_ip);
2153
2154 EXPECT_FALSE(cmod_propagation(v));
2155 EXPECT_EQ(0, block0->start_ip);
2156 EXPECT_EQ(1, block0->end_ip);
2157 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2158 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2159 EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 1)->opcode);
2160 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
2161 }
2162
2163 TEST_F(cmod_propagation_test, not_to_or_intervening_flag_read_compatible_value)
2164 {
2165 /* Exercise propagation of conditional modifier from a NOT instruction to
2166 * another ALU instruction as performed by cmod_propagate_not.
2167 */
2168 const fs_builder &bld = v->bld;
2169 fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2170 fs_reg dest1 = v->vgrf(glsl_type::float_type);
2171 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2172 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2173 fs_reg src2 = v->vgrf(glsl_type::float_type);
2174 fs_reg zero(brw_imm_f(0.0f));
2175 set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest0, src0, src1));
2176 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
2177 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2178
2179 /* = Before =
2180 *
2181 * 0: or.z.f0(8) dest0 src0 src1
2182 * 1: (+f0) sel(8) dest1 src2 0.0f
2183 * 2: not.nz.f0(8) null dest0
2184 *
2185 * = After =
2186 * 0: or.z.f0(8) dest0 src0 src1
2187 * 1: (+f0) sel(8) dest1 src2 0.0f
2188 */
2189
2190 v->calculate_cfg();
2191 bblock_t *block0 = v->cfg->blocks[0];
2192
2193 EXPECT_EQ(0, block0->start_ip);
2194 EXPECT_EQ(2, block0->end_ip);
2195
2196 EXPECT_TRUE(cmod_propagation(v));
2197 EXPECT_EQ(0, block0->start_ip);
2198 EXPECT_EQ(1, block0->end_ip);
2199 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2200 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2201 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
2202 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
2203 }
2204
2205 TEST_F(cmod_propagation_test,
2206 not_to_or_intervening_flag_read_compatible_value_mismatch_flag)
2207 {
2208 /* Exercise propagation of conditional modifier from a NOT instruction to
2209 * another ALU instruction as performed by cmod_propagate_not.
2210 */
2211 const fs_builder &bld = v->bld;
2212 fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2213 fs_reg dest1 = v->vgrf(glsl_type::float_type);
2214 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2215 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2216 fs_reg src2 = v->vgrf(glsl_type::float_type);
2217 fs_reg zero(brw_imm_f(0.0f));
2218 set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest0, src0, src1))
2219 ->flag_subreg = 1;
2220 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
2221 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2222
2223 /* = Before =
2224 *
2225 * 0: or.z.f0.1(8) dest0 src0 src1
2226 * 1: (+f0) sel(8) dest1 src2 0.0f
2227 * 2: not.nz.f0(8) null dest0
2228 *
2229 * = After =
2230 * No changes
2231 */
2232
2233 v->calculate_cfg();
2234 bblock_t *block0 = v->cfg->blocks[0];
2235
2236 EXPECT_EQ(0, block0->start_ip);
2237 EXPECT_EQ(2, block0->end_ip);
2238
2239 EXPECT_FALSE(cmod_propagation(v));
2240 EXPECT_EQ(0, block0->start_ip);
2241 EXPECT_EQ(2, block0->end_ip);
2242 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2243 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2244 EXPECT_EQ(1, instruction(block0, 0)->flag_subreg);
2245 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
2246 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
2247 EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 2)->opcode);
2248 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 2)->conditional_mod);
2249 EXPECT_EQ(0, instruction(block0, 2)->flag_subreg);
2250 }
2251
2252 TEST_F(cmod_propagation_test, not_to_or_intervening_flag_read_incompatible_value)
2253 {
2254 /* Exercise propagation of conditional modifier from a NOT instruction to
2255 * another ALU instruction as performed by cmod_propagate_not.
2256 */
2257 const fs_builder &bld = v->bld;
2258 fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2259 fs_reg dest1 = v->vgrf(glsl_type::float_type);
2260 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2261 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2262 fs_reg src2 = v->vgrf(glsl_type::float_type);
2263 fs_reg zero(brw_imm_f(0.0f));
2264 set_condmod(BRW_CONDITIONAL_NZ, bld.OR(dest0, src0, src1));
2265 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
2266 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2267
2268 /* = Before =
2269 *
2270 * 0: or.nz.f0(8) dest0 src0 src1
2271 * 1: (+f0) sel(8) dest1 src2 0.0f
2272 * 2: not.nz.f0(8) null dest0
2273 *
2274 * = After =
2275 * No changes
2276 */
2277
2278 v->calculate_cfg();
2279 bblock_t *block0 = v->cfg->blocks[0];
2280
2281 EXPECT_EQ(0, block0->start_ip);
2282 EXPECT_EQ(2, block0->end_ip);
2283
2284 EXPECT_FALSE(cmod_propagation(v));
2285 EXPECT_EQ(0, block0->start_ip);
2286 EXPECT_EQ(2, block0->end_ip);
2287 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2288 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
2289 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
2290 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
2291 EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 2)->opcode);
2292 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 2)->conditional_mod);
2293 }
2294
2295 TEST_F(cmod_propagation_test, not_to_or_intervening_mismatch_flag_write)
2296 {
2297 /* Exercise propagation of conditional modifier from a NOT instruction to
2298 * another ALU instruction as performed by cmod_propagate_not.
2299 */
2300 const fs_builder &bld = v->bld;
2301 fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2302 fs_reg dest1 = v->vgrf(glsl_type::uint_type);
2303 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2304 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2305
2306 bld.OR(dest0, src0, src1);
2307 set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest1, src0, src1))
2308 ->flag_subreg = 1;
2309 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2310
2311 /* = Before =
2312 *
2313 * 0: or(8) dest0 src0 src1
2314 * 1: or.z.f0.1(8) dest1 src0 src1
2315 * 2: not.nz.f0(8) null dest0
2316 *
2317 * = After =
2318 * 0: or.z.f0(8) dest0 src0 src1
2319 * 1: or.z.f0.1(8) dest1 src0 src1
2320 */
2321
2322 v->calculate_cfg();
2323 bblock_t *block0 = v->cfg->blocks[0];
2324
2325 EXPECT_EQ(0, block0->start_ip);
2326 EXPECT_EQ(2, block0->end_ip);
2327
2328 EXPECT_TRUE(cmod_propagation(v));
2329 EXPECT_EQ(0, block0->start_ip);
2330 EXPECT_EQ(1, block0->end_ip);
2331 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2332 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2333 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
2334 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 1)->opcode);
2335 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 1)->conditional_mod);
2336 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
2337 }
2338
2339 TEST_F(cmod_propagation_test, not_to_or_intervening_mismatch_flag_read)
2340 {
2341 /* Exercise propagation of conditional modifier from a NOT instruction to
2342 * another ALU instruction as performed by cmod_propagate_not.
2343 */
2344 const fs_builder &bld = v->bld;
2345 fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2346 fs_reg dest1 = v->vgrf(glsl_type::float_type);
2347 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2348 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2349 fs_reg src2 = v->vgrf(glsl_type::float_type);
2350 fs_reg zero(brw_imm_f(0.0f));
2351
2352 bld.OR(dest0, src0, src1);
2353 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
2354 ->flag_subreg = 1;
2355 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2356
2357 /* = Before =
2358 *
2359 * 0: or(8) dest0 src0 src1
2360 * 1: (+f0.1) sel(8) dest1 src2 0.0f
2361 * 2: not.nz.f0(8) null dest0
2362 *
2363 * = After =
2364 * 0: or.z.f0(8) dest0 src0 src1
2365 * 1: (+f0.1) sel(8) dest1 src2 0.0f
2366 */
2367
2368 v->calculate_cfg();
2369 bblock_t *block0 = v->cfg->blocks[0];
2370
2371 EXPECT_EQ(0, block0->start_ip);
2372 EXPECT_EQ(2, block0->end_ip);
2373
2374 EXPECT_TRUE(cmod_propagation(v));
2375 EXPECT_EQ(0, block0->start_ip);
2376 EXPECT_EQ(1, block0->end_ip);
2377 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2378 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2379 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
2380 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
2381 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
2382 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
2383 }
2384
2385 TEST_F(cmod_propagation_test, cmp_to_add_float_e)
2386 {
2387 const fs_builder &bld = v->bld;
2388 fs_reg dest = v->vgrf(glsl_type::float_type);
2389 fs_reg src0 = v->vgrf(glsl_type::float_type);
2390 fs_reg neg10(brw_imm_f(-10.0f));
2391 fs_reg pos10(brw_imm_f(10.0f));
2392
2393 bld.ADD(dest, src0, neg10)->saturate = true;
2394 bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_EQ);
2395
2396 /* = Before =
2397 * 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
2398 * 1: cmp.z.f0.0(8) null:F, vgrf1:F, 10f
2399 *
2400 * = After =
2401 * (no changes)
2402 */
2403
2404 v->calculate_cfg();
2405 bblock_t *block0 = v->cfg->blocks[0];
2406
2407 EXPECT_FALSE(cmod_propagation(v));
2408 EXPECT_EQ(0, block0->start_ip);
2409 EXPECT_EQ(1, block0->end_ip);
2410 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2411 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2412 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
2413 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
2414 }
2415
2416 TEST_F(cmod_propagation_test, cmp_to_add_float_g)
2417 {
2418 const fs_builder &bld = v->bld;
2419 fs_reg dest = v->vgrf(glsl_type::float_type);
2420 fs_reg src0 = v->vgrf(glsl_type::float_type);
2421 fs_reg neg10(brw_imm_f(-10.0f));
2422 fs_reg pos10(brw_imm_f(10.0f));
2423
2424 bld.ADD(dest, src0, neg10)->saturate = true;
2425 bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_G);
2426
2427 /* = Before =
2428 * 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
2429 * 1: cmp.g.f0.0(8) null:F, vgrf1:F, 10f
2430 *
2431 * = After =
2432 * 0: add.sat.g.f0.0(8) vgrf0:F, vgrf1:F, -10f
2433 */
2434
2435 v->calculate_cfg();
2436 bblock_t *block0 = v->cfg->blocks[0];
2437
2438 EXPECT_TRUE(cmod_propagation(v));
2439 EXPECT_EQ(0, block0->start_ip);
2440 EXPECT_EQ(0, block0->end_ip);
2441 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2442 EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod);
2443 }
2444
2445 TEST_F(cmod_propagation_test, cmp_to_add_float_le)
2446 {
2447 const fs_builder &bld = v->bld;
2448 fs_reg dest = v->vgrf(glsl_type::float_type);
2449 fs_reg src0 = v->vgrf(glsl_type::float_type);
2450 fs_reg neg10(brw_imm_f(-10.0f));
2451 fs_reg pos10(brw_imm_f(10.0f));
2452
2453 bld.ADD(dest, src0, neg10)->saturate = true;
2454 bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_LE);
2455
2456 /* = Before =
2457 * 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
2458 * 1: cmp.le.f0.0(8) null:F, vgrf1:F, 10f
2459 *
2460 * = After =
2461 * 0: add.sat.le.f0.0(8) vgrf0:F, vgrf1:F, -10f
2462 */
2463
2464 v->calculate_cfg();
2465 bblock_t *block0 = v->cfg->blocks[0];
2466
2467 EXPECT_TRUE(cmod_propagation(v));
2468 EXPECT_EQ(0, block0->start_ip);
2469 EXPECT_EQ(0, block0->end_ip);
2470 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2471 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
2472 }