6801f94de0c01042cf7fbd71a132d47f74ddc9ea
[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, (struct gl_program *) NULL,
61 shader, 8, -1) {}
62 };
63
64
65 void cmod_propagation_test::SetUp()
66 {
67 ctx = (struct gl_context *)calloc(1, sizeof(*ctx));
68 compiler = (struct brw_compiler *)calloc(1, sizeof(*compiler));
69 devinfo = (struct gen_device_info *)calloc(1, sizeof(*devinfo));
70 compiler->devinfo = devinfo;
71
72 prog_data = ralloc(NULL, struct brw_wm_prog_data);
73 nir_shader *shader =
74 nir_shader_create(NULL, MESA_SHADER_FRAGMENT, NULL, NULL);
75
76 v = new cmod_propagation_fs_visitor(compiler, prog_data, shader);
77
78 devinfo->gen = 7;
79 }
80
81 static fs_inst *
82 instruction(bblock_t *block, int num)
83 {
84 fs_inst *inst = (fs_inst *)block->start();
85 for (int i = 0; i < num; i++) {
86 inst = (fs_inst *)inst->next;
87 }
88 return inst;
89 }
90
91 static bool
92 cmod_propagation(fs_visitor *v)
93 {
94 const bool print = getenv("TEST_DEBUG");
95
96 if (print) {
97 fprintf(stderr, "= Before =\n");
98 v->cfg->dump(v);
99 }
100
101 bool ret = v->opt_cmod_propagation();
102
103 if (print) {
104 fprintf(stderr, "\n= After =\n");
105 v->cfg->dump(v);
106 }
107
108 return ret;
109 }
110
111 TEST_F(cmod_propagation_test, basic)
112 {
113 const fs_builder &bld = v->bld;
114 fs_reg dest = v->vgrf(glsl_type::float_type);
115 fs_reg src0 = v->vgrf(glsl_type::float_type);
116 fs_reg src1 = v->vgrf(glsl_type::float_type);
117 fs_reg zero(brw_imm_f(0.0f));
118 bld.ADD(dest, src0, src1);
119 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
120
121 /* = Before =
122 *
123 * 0: add(8) dest src0 src1
124 * 1: cmp.ge.f0(8) null dest 0.0f
125 *
126 * = After =
127 * 0: add.ge.f0(8) dest src0 src1
128 */
129
130 v->calculate_cfg();
131 bblock_t *block0 = v->cfg->blocks[0];
132
133 EXPECT_EQ(0, block0->start_ip);
134 EXPECT_EQ(1, block0->end_ip);
135
136 EXPECT_TRUE(cmod_propagation(v));
137 EXPECT_EQ(0, block0->start_ip);
138 EXPECT_EQ(0, block0->end_ip);
139 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
140 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
141 }
142
143 TEST_F(cmod_propagation_test, cmp_nonzero)
144 {
145 const fs_builder &bld = v->bld;
146 fs_reg dest = v->vgrf(glsl_type::float_type);
147 fs_reg src0 = v->vgrf(glsl_type::float_type);
148 fs_reg src1 = v->vgrf(glsl_type::float_type);
149 fs_reg nonzero(brw_imm_f(1.0f));
150 bld.ADD(dest, src0, src1);
151 bld.CMP(bld.null_reg_f(), dest, nonzero, BRW_CONDITIONAL_GE);
152
153 /* = Before =
154 *
155 * 0: add(8) dest src0 src1
156 * 1: cmp.ge.f0(8) null dest 1.0f
157 *
158 * = After =
159 * (no changes)
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_FALSE(cmod_propagation(v));
169 EXPECT_EQ(0, block0->start_ip);
170 EXPECT_EQ(1, block0->end_ip);
171 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
172 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
173 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
174 }
175
176 TEST_F(cmod_propagation_test, non_cmod_instruction)
177 {
178 const fs_builder &bld = v->bld;
179 fs_reg dest = v->vgrf(glsl_type::uint_type);
180 fs_reg src0 = v->vgrf(glsl_type::uint_type);
181 fs_reg zero(brw_imm_ud(0u));
182 bld.FBL(dest, src0);
183 bld.CMP(bld.null_reg_ud(), dest, zero, BRW_CONDITIONAL_GE);
184
185 /* = Before =
186 *
187 * 0: fbl(8) dest src0
188 * 1: cmp.ge.f0(8) null dest 0u
189 *
190 * = After =
191 * (no changes)
192 */
193
194 v->calculate_cfg();
195 bblock_t *block0 = v->cfg->blocks[0];
196
197 EXPECT_EQ(0, block0->start_ip);
198 EXPECT_EQ(1, block0->end_ip);
199
200 EXPECT_FALSE(cmod_propagation(v));
201 EXPECT_EQ(0, block0->start_ip);
202 EXPECT_EQ(1, block0->end_ip);
203 EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode);
204 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
205 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
206 }
207
208 TEST_F(cmod_propagation_test, intervening_flag_write)
209 {
210 const fs_builder &bld = v->bld;
211 fs_reg dest = v->vgrf(glsl_type::float_type);
212 fs_reg src0 = v->vgrf(glsl_type::float_type);
213 fs_reg src1 = v->vgrf(glsl_type::float_type);
214 fs_reg src2 = v->vgrf(glsl_type::float_type);
215 fs_reg zero(brw_imm_f(0.0f));
216 bld.ADD(dest, src0, src1);
217 bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE);
218 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
219
220 /* = Before =
221 *
222 * 0: add(8) dest src0 src1
223 * 1: cmp.ge.f0(8) null src2 0.0f
224 * 2: cmp.ge.f0(8) null dest 0.0f
225 *
226 * = After =
227 * (no changes)
228 */
229
230 v->calculate_cfg();
231 bblock_t *block0 = v->cfg->blocks[0];
232
233 EXPECT_EQ(0, block0->start_ip);
234 EXPECT_EQ(2, block0->end_ip);
235
236 EXPECT_FALSE(cmod_propagation(v));
237 EXPECT_EQ(0, block0->start_ip);
238 EXPECT_EQ(2, block0->end_ip);
239 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
240 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
241 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
242 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
243 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
244 }
245
246 TEST_F(cmod_propagation_test, intervening_flag_read)
247 {
248 const fs_builder &bld = v->bld;
249 fs_reg dest0 = v->vgrf(glsl_type::float_type);
250 fs_reg dest1 = v->vgrf(glsl_type::float_type);
251 fs_reg src0 = v->vgrf(glsl_type::float_type);
252 fs_reg src1 = v->vgrf(glsl_type::float_type);
253 fs_reg src2 = v->vgrf(glsl_type::float_type);
254 fs_reg zero(brw_imm_f(0.0f));
255 bld.ADD(dest0, src0, src1);
256 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
257 bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
258
259 /* = Before =
260 *
261 * 0: add(8) dest0 src0 src1
262 * 1: (+f0) sel(8) dest1 src2 0.0f
263 * 2: cmp.ge.f0(8) null dest0 0.0f
264 *
265 * = After =
266 * (no changes)
267 */
268
269 v->calculate_cfg();
270 bblock_t *block0 = v->cfg->blocks[0];
271
272 EXPECT_EQ(0, block0->start_ip);
273 EXPECT_EQ(2, block0->end_ip);
274
275 EXPECT_FALSE(cmod_propagation(v));
276 EXPECT_EQ(0, block0->start_ip);
277 EXPECT_EQ(2, block0->end_ip);
278 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
279 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
280 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
281 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
282 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
283 }
284
285 TEST_F(cmod_propagation_test, intervening_dest_write)
286 {
287 const fs_builder &bld = v->bld;
288 fs_reg dest = v->vgrf(glsl_type::vec4_type);
289 fs_reg src0 = v->vgrf(glsl_type::float_type);
290 fs_reg src1 = v->vgrf(glsl_type::float_type);
291 fs_reg src2 = v->vgrf(glsl_type::vec2_type);
292 fs_reg zero(brw_imm_f(0.0f));
293 bld.ADD(offset(dest, bld, 2), src0, src1);
294 bld.emit(SHADER_OPCODE_TEX, dest, src2)
295 ->size_written = 4 * REG_SIZE;
296 bld.CMP(bld.null_reg_f(), offset(dest, bld, 2), zero, BRW_CONDITIONAL_GE);
297
298 /* = Before =
299 *
300 * 0: add(8) dest+2 src0 src1
301 * 1: tex(8) rlen 4 dest+0 src2
302 * 2: cmp.ge.f0(8) null dest+2 0.0f
303 *
304 * = After =
305 * (no changes)
306 */
307
308 v->calculate_cfg();
309 bblock_t *block0 = v->cfg->blocks[0];
310
311 EXPECT_EQ(0, block0->start_ip);
312 EXPECT_EQ(2, block0->end_ip);
313
314 EXPECT_FALSE(cmod_propagation(v));
315 EXPECT_EQ(0, block0->start_ip);
316 EXPECT_EQ(2, block0->end_ip);
317 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
318 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
319 EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
320 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
321 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
322 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
323 }
324
325 TEST_F(cmod_propagation_test, intervening_flag_read_same_value)
326 {
327 const fs_builder &bld = v->bld;
328 fs_reg dest0 = v->vgrf(glsl_type::float_type);
329 fs_reg dest1 = v->vgrf(glsl_type::float_type);
330 fs_reg src0 = v->vgrf(glsl_type::float_type);
331 fs_reg src1 = v->vgrf(glsl_type::float_type);
332 fs_reg src2 = v->vgrf(glsl_type::float_type);
333 fs_reg zero(brw_imm_f(0.0f));
334 set_condmod(BRW_CONDITIONAL_GE, bld.ADD(dest0, src0, src1));
335 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
336 bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
337
338 /* = Before =
339 *
340 * 0: add.ge.f0(8) dest0 src0 src1
341 * 1: (+f0) sel(8) dest1 src2 0.0f
342 * 2: cmp.ge.f0(8) null dest0 0.0f
343 *
344 * = After =
345 * 0: add.ge.f0(8) dest0 src0 src1
346 * 1: (+f0) sel(8) dest1 src2 0.0f
347 */
348
349 v->calculate_cfg();
350 bblock_t *block0 = v->cfg->blocks[0];
351
352 EXPECT_EQ(0, block0->start_ip);
353 EXPECT_EQ(2, block0->end_ip);
354
355 EXPECT_TRUE(cmod_propagation(v));
356 EXPECT_EQ(0, block0->start_ip);
357 EXPECT_EQ(1, block0->end_ip);
358 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
359 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
360 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
361 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
362 }
363
364 TEST_F(cmod_propagation_test, negate)
365 {
366 const fs_builder &bld = v->bld;
367 fs_reg dest = v->vgrf(glsl_type::float_type);
368 fs_reg src0 = v->vgrf(glsl_type::float_type);
369 fs_reg src1 = v->vgrf(glsl_type::float_type);
370 fs_reg zero(brw_imm_f(0.0f));
371 bld.ADD(dest, src0, src1);
372 dest.negate = true;
373 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
374
375 /* = Before =
376 *
377 * 0: add(8) dest src0 src1
378 * 1: cmp.ge.f0(8) null -dest 0.0f
379 *
380 * = After =
381 * 0: add.le.f0(8) dest src0 src1
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(1, block0->end_ip);
389
390 EXPECT_TRUE(cmod_propagation(v));
391 EXPECT_EQ(0, block0->start_ip);
392 EXPECT_EQ(0, block0->end_ip);
393 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
394 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
395 }
396
397 TEST_F(cmod_propagation_test, movnz)
398 {
399 const fs_builder &bld = v->bld;
400 fs_reg dest = v->vgrf(glsl_type::float_type);
401 fs_reg src0 = v->vgrf(glsl_type::float_type);
402 fs_reg src1 = v->vgrf(glsl_type::float_type);
403 bld.CMP(dest, src0, src1, BRW_CONDITIONAL_GE);
404 set_condmod(BRW_CONDITIONAL_NZ,
405 bld.MOV(bld.null_reg_f(), dest));
406
407 /* = Before =
408 *
409 * 0: cmp.ge.f0(8) dest src0 src1
410 * 1: mov.nz.f0(8) null dest
411 *
412 * = After =
413 * 0: cmp.ge.f0(8) dest src0 src1
414 */
415
416 v->calculate_cfg();
417 bblock_t *block0 = v->cfg->blocks[0];
418
419 EXPECT_EQ(0, block0->start_ip);
420 EXPECT_EQ(1, block0->end_ip);
421
422 EXPECT_TRUE(cmod_propagation(v));
423 EXPECT_EQ(0, block0->start_ip);
424 EXPECT_EQ(0, block0->end_ip);
425 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
426 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
427 }
428
429 TEST_F(cmod_propagation_test, different_types_cmod_with_zero)
430 {
431 const fs_builder &bld = v->bld;
432 fs_reg dest = v->vgrf(glsl_type::int_type);
433 fs_reg src0 = v->vgrf(glsl_type::int_type);
434 fs_reg src1 = v->vgrf(glsl_type::int_type);
435 fs_reg zero(brw_imm_f(0.0f));
436 bld.ADD(dest, src0, src1);
437 bld.CMP(bld.null_reg_f(), retype(dest, BRW_REGISTER_TYPE_F), zero,
438 BRW_CONDITIONAL_GE);
439
440 /* = Before =
441 *
442 * 0: add(8) dest:D src0:D src1:D
443 * 1: cmp.ge.f0(8) null:F dest:F 0.0f
444 *
445 * = After =
446 * (no changes)
447 */
448
449 v->calculate_cfg();
450 bblock_t *block0 = v->cfg->blocks[0];
451
452 EXPECT_EQ(0, block0->start_ip);
453 EXPECT_EQ(1, block0->end_ip);
454
455 EXPECT_FALSE(cmod_propagation(v));
456 EXPECT_EQ(0, block0->start_ip);
457 EXPECT_EQ(1, block0->end_ip);
458 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
459 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
460 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
461 }
462
463 TEST_F(cmod_propagation_test, andnz_one)
464 {
465 const fs_builder &bld = v->bld;
466 fs_reg dest = v->vgrf(glsl_type::int_type);
467 fs_reg src0 = v->vgrf(glsl_type::float_type);
468 fs_reg zero(brw_imm_f(0.0f));
469 fs_reg one(brw_imm_d(1));
470
471 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
472 set_condmod(BRW_CONDITIONAL_NZ,
473 bld.AND(bld.null_reg_d(), dest, one));
474
475 /* = Before =
476 * 0: cmp.l.f0(8) dest:F src0:F 0F
477 * 1: and.nz.f0(8) null:D dest:D 1D
478 *
479 * = After =
480 * 0: cmp.l.f0(8) dest:F src0:F 0F
481 */
482
483 v->calculate_cfg();
484 bblock_t *block0 = v->cfg->blocks[0];
485
486 EXPECT_EQ(0, block0->start_ip);
487 EXPECT_EQ(1, block0->end_ip);
488
489 EXPECT_TRUE(cmod_propagation(v));
490 EXPECT_EQ(0, block0->start_ip);
491 EXPECT_EQ(0, block0->end_ip);
492 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
493 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
494 EXPECT_TRUE(retype(dest, BRW_REGISTER_TYPE_F)
495 .equals(instruction(block0, 0)->dst));
496 }
497
498 TEST_F(cmod_propagation_test, andnz_non_one)
499 {
500 const fs_builder &bld = v->bld;
501 fs_reg dest = v->vgrf(glsl_type::int_type);
502 fs_reg src0 = v->vgrf(glsl_type::float_type);
503 fs_reg zero(brw_imm_f(0.0f));
504 fs_reg nonone(brw_imm_d(38));
505
506 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
507 set_condmod(BRW_CONDITIONAL_NZ,
508 bld.AND(bld.null_reg_d(), dest, nonone));
509
510 /* = Before =
511 * 0: cmp.l.f0(8) dest:F src0:F 0F
512 * 1: and.nz.f0(8) null:D dest:D 38D
513 *
514 * = After =
515 * (no changes)
516 */
517
518 v->calculate_cfg();
519 bblock_t *block0 = v->cfg->blocks[0];
520
521 EXPECT_EQ(0, block0->start_ip);
522 EXPECT_EQ(1, block0->end_ip);
523
524 EXPECT_FALSE(cmod_propagation(v));
525 EXPECT_EQ(0, block0->start_ip);
526 EXPECT_EQ(1, block0->end_ip);
527 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
528 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
529 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
530 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
531 }
532
533 TEST_F(cmod_propagation_test, andz_one)
534 {
535 const fs_builder &bld = v->bld;
536 fs_reg dest = v->vgrf(glsl_type::int_type);
537 fs_reg src0 = v->vgrf(glsl_type::float_type);
538 fs_reg zero(brw_imm_f(0.0f));
539 fs_reg one(brw_imm_d(1));
540
541 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
542 set_condmod(BRW_CONDITIONAL_Z,
543 bld.AND(bld.null_reg_d(), dest, one));
544
545 /* = Before =
546 * 0: cmp.l.f0(8) dest:F src0:F 0F
547 * 1: and.z.f0(8) null:D dest:D 1D
548 *
549 * = After =
550 * (no changes)
551 */
552
553 v->calculate_cfg();
554 bblock_t *block0 = v->cfg->blocks[0];
555
556 EXPECT_EQ(0, block0->start_ip);
557 EXPECT_EQ(1, block0->end_ip);
558
559 EXPECT_FALSE(cmod_propagation(v));
560 EXPECT_EQ(0, block0->start_ip);
561 EXPECT_EQ(1, block0->end_ip);
562 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
563 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
564 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
565 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
566 }
567
568 TEST_F(cmod_propagation_test, add_not_merge_with_compare)
569 {
570 const fs_builder &bld = v->bld;
571 fs_reg dest = v->vgrf(glsl_type::float_type);
572 fs_reg src0 = v->vgrf(glsl_type::float_type);
573 fs_reg src1 = v->vgrf(glsl_type::float_type);
574 bld.ADD(dest, src0, src1);
575 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
576
577 /* The addition and the implicit subtraction in the compare do not compute
578 * related values.
579 *
580 * = Before =
581 * 0: add(8) dest:F src0:F src1:F
582 * 1: cmp.l.f0(8) null:F src0:F src1:F
583 *
584 * = After =
585 * (no changes)
586 */
587 v->calculate_cfg();
588 bblock_t *block0 = v->cfg->blocks[0];
589
590 EXPECT_EQ(0, block0->start_ip);
591 EXPECT_EQ(1, block0->end_ip);
592
593 EXPECT_FALSE(cmod_propagation(v));
594 EXPECT_EQ(0, block0->start_ip);
595 EXPECT_EQ(1, block0->end_ip);
596 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
597 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
598 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
599 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
600 }
601
602 TEST_F(cmod_propagation_test, subtract_merge_with_compare)
603 {
604 const fs_builder &bld = v->bld;
605 fs_reg dest = v->vgrf(glsl_type::float_type);
606 fs_reg src0 = v->vgrf(glsl_type::float_type);
607 fs_reg src1 = v->vgrf(glsl_type::float_type);
608 bld.ADD(dest, src0, negate(src1));
609 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
610
611 /* = Before =
612 * 0: add(8) dest:F src0:F -src1:F
613 * 1: cmp.l.f0(8) null:F src0:F src1:F
614 *
615 * = After =
616 * 0: add.l.f0(8) dest:F src0:F -src1:F
617 */
618 v->calculate_cfg();
619 bblock_t *block0 = v->cfg->blocks[0];
620
621 EXPECT_EQ(0, block0->start_ip);
622 EXPECT_EQ(1, block0->end_ip);
623
624 EXPECT_TRUE(cmod_propagation(v));
625 EXPECT_EQ(0, block0->start_ip);
626 EXPECT_EQ(0, block0->end_ip);
627 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
628 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
629 }
630
631 TEST_F(cmod_propagation_test, subtract_immediate_merge_with_compare)
632 {
633 const fs_builder &bld = v->bld;
634 fs_reg dest = v->vgrf(glsl_type::float_type);
635 fs_reg src0 = v->vgrf(glsl_type::float_type);
636 fs_reg one(brw_imm_f(1.0f));
637 fs_reg negative_one(brw_imm_f(-1.0f));
638
639 bld.ADD(dest, src0, negative_one);
640 bld.CMP(bld.null_reg_f(), src0, one, BRW_CONDITIONAL_NZ);
641
642 /* = Before =
643 * 0: add(8) dest:F src0:F -1.0f
644 * 1: cmp.nz.f0(8) null:F src0:F 1.0f
645 *
646 * = After =
647 * 0: add.nz.f0(8) dest:F src0:F -1.0f
648 */
649 v->calculate_cfg();
650 bblock_t *block0 = v->cfg->blocks[0];
651
652 EXPECT_EQ(0, block0->start_ip);
653 EXPECT_EQ(1, block0->end_ip);
654
655 EXPECT_TRUE(cmod_propagation(v));
656 EXPECT_EQ(0, block0->start_ip);
657 EXPECT_EQ(0, block0->end_ip);
658 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
659 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
660 }
661
662 TEST_F(cmod_propagation_test, subtract_merge_with_compare_intervening_add)
663 {
664 const fs_builder &bld = v->bld;
665 fs_reg dest0 = v->vgrf(glsl_type::float_type);
666 fs_reg dest1 = v->vgrf(glsl_type::float_type);
667 fs_reg src0 = v->vgrf(glsl_type::float_type);
668 fs_reg src1 = v->vgrf(glsl_type::float_type);
669 bld.ADD(dest0, src0, negate(src1));
670 bld.ADD(dest1, src0, src1);
671 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
672
673 /* = Before =
674 * 0: add(8) dest0:F src0:F -src1:F
675 * 1: add(8) dest1:F src0:F src1:F
676 * 2: cmp.l.f0(8) null:F src0:F src1:F
677 *
678 * = After =
679 * 0: add.l.f0(8) dest0:F src0:F -src1:F
680 * 1: add(8) dest1:F src0:F src1:F
681 */
682 v->calculate_cfg();
683 bblock_t *block0 = v->cfg->blocks[0];
684
685 EXPECT_EQ(0, block0->start_ip);
686 EXPECT_EQ(2, block0->end_ip);
687
688 EXPECT_TRUE(cmod_propagation(v));
689 EXPECT_EQ(0, block0->start_ip);
690 EXPECT_EQ(1, block0->end_ip);
691 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
692 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
693 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
694 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
695 }
696
697 TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_partial_write)
698 {
699 const fs_builder &bld = v->bld;
700 fs_reg dest0 = v->vgrf(glsl_type::float_type);
701 fs_reg dest1 = v->vgrf(glsl_type::float_type);
702 fs_reg src0 = v->vgrf(glsl_type::float_type);
703 fs_reg src1 = v->vgrf(glsl_type::float_type);
704 bld.ADD(dest0, src0, negate(src1));
705 set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, src0, negate(src1)));
706 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
707
708 /* = Before =
709 * 0: add(8) dest0:F src0:F -src1:F
710 * 1: (+f0) add(8) dest1:F src0:F -src1:F
711 * 2: cmp.l.f0(8) null:F src0:F src1:F
712 *
713 * = After =
714 * (no changes)
715 */
716 v->calculate_cfg();
717 bblock_t *block0 = v->cfg->blocks[0];
718
719 EXPECT_EQ(0, block0->start_ip);
720 EXPECT_EQ(2, block0->end_ip);
721
722 EXPECT_FALSE(cmod_propagation(v));
723 EXPECT_EQ(0, block0->start_ip);
724 EXPECT_EQ(2, block0->end_ip);
725 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
726 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
727 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
728 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
729 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
730 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
731 }
732
733 TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_add)
734 {
735 const fs_builder &bld = v->bld;
736 fs_reg dest0 = v->vgrf(glsl_type::float_type);
737 fs_reg dest1 = v->vgrf(glsl_type::float_type);
738 fs_reg src0 = v->vgrf(glsl_type::float_type);
739 fs_reg src1 = v->vgrf(glsl_type::float_type);
740 bld.ADD(dest0, src0, negate(src1));
741 set_condmod(BRW_CONDITIONAL_EQ, bld.ADD(dest1, src0, src1));
742 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
743
744 /* = Before =
745 * 0: add(8) dest0:F src0:F -src1:F
746 * 1: add.z.f0(8) dest1:F src0:F src1:F
747 * 2: cmp.l.f0(8) null:F src0:F src1:F
748 *
749 * = After =
750 * (no changes)
751 */
752 v->calculate_cfg();
753 bblock_t *block0 = v->cfg->blocks[0];
754
755 EXPECT_EQ(0, block0->start_ip);
756 EXPECT_EQ(2, block0->end_ip);
757
758 EXPECT_FALSE(cmod_propagation(v));
759 EXPECT_EQ(0, block0->start_ip);
760 EXPECT_EQ(2, block0->end_ip);
761 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
762 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
763 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
764 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
765 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
766 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
767 }
768
769 TEST_F(cmod_propagation_test, add_merge_with_compare)
770 {
771 const fs_builder &bld = v->bld;
772 fs_reg dest = v->vgrf(glsl_type::float_type);
773 fs_reg src0 = v->vgrf(glsl_type::float_type);
774 fs_reg src1 = v->vgrf(glsl_type::float_type);
775 bld.ADD(dest, src0, src1);
776 bld.CMP(bld.null_reg_f(), src0, negate(src1), BRW_CONDITIONAL_L);
777
778 /* = Before =
779 * 0: add(8) dest:F src0:F src1:F
780 * 1: cmp.l.f0(8) null:F src0:F -src1:F
781 *
782 * = After =
783 * 0: add.l.f0(8) dest:F src0:F src1:F
784 */
785 v->calculate_cfg();
786 bblock_t *block0 = v->cfg->blocks[0];
787
788 EXPECT_EQ(0, block0->start_ip);
789 EXPECT_EQ(1, block0->end_ip);
790
791 EXPECT_TRUE(cmod_propagation(v));
792 EXPECT_EQ(0, block0->start_ip);
793 EXPECT_EQ(0, block0->end_ip);
794 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
795 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
796 }
797
798 TEST_F(cmod_propagation_test, negative_subtract_merge_with_compare)
799 {
800 const fs_builder &bld = v->bld;
801 fs_reg dest = v->vgrf(glsl_type::float_type);
802 fs_reg src0 = v->vgrf(glsl_type::float_type);
803 fs_reg src1 = v->vgrf(glsl_type::float_type);
804 bld.ADD(dest, src1, negate(src0));
805 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
806
807 /* The result of the subtract is the negatiion of the result of the
808 * implicit subtract in the compare, so the condition must change.
809 *
810 * = Before =
811 * 0: add(8) dest:F src1:F -src0:F
812 * 1: cmp.l.f0(8) null:F src0:F src1:F
813 *
814 * = After =
815 * 0: add.g.f0(8) dest:F src0:F -src1:F
816 */
817 v->calculate_cfg();
818 bblock_t *block0 = v->cfg->blocks[0];
819
820 EXPECT_EQ(0, block0->start_ip);
821 EXPECT_EQ(1, block0->end_ip);
822
823 EXPECT_TRUE(cmod_propagation(v));
824 EXPECT_EQ(0, block0->start_ip);
825 EXPECT_EQ(0, block0->end_ip);
826 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
827 EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod);
828 }
829
830 TEST_F(cmod_propagation_test, subtract_delete_compare)
831 {
832 const fs_builder &bld = v->bld;
833 fs_reg dest = v->vgrf(glsl_type::float_type);
834 fs_reg dest1 = v->vgrf(glsl_type::float_type);
835 fs_reg src0 = v->vgrf(glsl_type::float_type);
836 fs_reg src1 = v->vgrf(glsl_type::float_type);
837 fs_reg src2 = v->vgrf(glsl_type::float_type);
838
839 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)));
840 set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2));
841 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
842
843 /* = Before =
844 * 0: add.l.f0(8) dest0:F src0:F -src1:F
845 * 1: (+f0) mov(0) dest1:F src2:F
846 * 2: cmp.l.f0(8) null:F src0:F src1:F
847 *
848 * = After =
849 * 0: add.l.f0(8) dest:F src0:F -src1:F
850 * 1: (+f0) mov(0) dest1:F src2:F
851 */
852 v->calculate_cfg();
853 bblock_t *block0 = v->cfg->blocks[0];
854
855 EXPECT_EQ(0, block0->start_ip);
856 EXPECT_EQ(2, block0->end_ip);
857
858 EXPECT_TRUE(cmod_propagation(v));
859 EXPECT_EQ(0, block0->start_ip);
860 EXPECT_EQ(1, block0->end_ip);
861 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
862 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
863 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
864 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
865 }
866
867 TEST_F(cmod_propagation_test, subtract_delete_compare_derp)
868 {
869 const fs_builder &bld = v->bld;
870 fs_reg dest0 = v->vgrf(glsl_type::float_type);
871 fs_reg dest1 = v->vgrf(glsl_type::float_type);
872 fs_reg src0 = v->vgrf(glsl_type::float_type);
873 fs_reg src1 = v->vgrf(glsl_type::float_type);
874
875 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest0, src0, negate(src1)));
876 set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, negate(src0), src1));
877 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
878
879 /* = Before =
880 * 0: add.l.f0(8) dest0:F src0:F -src1:F
881 * 1: (+f0) add(0) dest1:F -src0:F src1:F
882 * 2: cmp.l.f0(8) null:F src0:F src1:F
883 *
884 * = After =
885 * 0: add.l.f0(8) dest0:F src0:F -src1:F
886 * 1: (+f0) add(0) dest1:F -src0:F src1:F
887 */
888 v->calculate_cfg();
889 bblock_t *block0 = v->cfg->blocks[0];
890
891 EXPECT_EQ(0, block0->start_ip);
892 EXPECT_EQ(2, block0->end_ip);
893
894 EXPECT_TRUE(cmod_propagation(v));
895 EXPECT_EQ(0, block0->start_ip);
896 EXPECT_EQ(1, block0->end_ip);
897 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
898 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
899 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
900 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
901 }
902
903 TEST_F(cmod_propagation_test, signed_unsigned_comparison_mismatch)
904 {
905 const fs_builder &bld = v->bld;
906 fs_reg dest0 = v->vgrf(glsl_type::int_type);
907 fs_reg src0 = v->vgrf(glsl_type::int_type);
908 src0.type = BRW_REGISTER_TYPE_W;
909
910 bld.ASR(dest0, negate(src0), brw_imm_d(15));
911 bld.CMP(bld.null_reg_ud(), retype(dest0, BRW_REGISTER_TYPE_UD),
912 brw_imm_ud(0u), BRW_CONDITIONAL_LE);
913
914 /* = Before =
915 * 0: asr(8) dest:D -src0:W 15D
916 * 1: cmp.le.f0(8) null:UD dest:UD 0UD
917 *
918 * = After =
919 * (no changes)
920 */
921 v->calculate_cfg();
922 bblock_t *block0 = v->cfg->blocks[0];
923
924 EXPECT_EQ(0, block0->start_ip);
925 EXPECT_EQ(1, block0->end_ip);
926
927 EXPECT_FALSE(cmod_propagation(v));
928 EXPECT_EQ(0, block0->start_ip);
929 EXPECT_EQ(1, block0->end_ip);
930 EXPECT_EQ(BRW_OPCODE_ASR, instruction(block0, 0)->opcode);
931 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
932 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 1)->conditional_mod);
933 }
934
935 void
936 cmod_propagation_test::test_positive_float_saturate_prop(enum brw_conditional_mod before,
937 enum brw_conditional_mod after,
938 enum opcode op)
939 {
940 const fs_builder &bld = v->bld;
941 fs_reg dest = v->vgrf(glsl_type::float_type);
942 fs_reg src0 = v->vgrf(glsl_type::float_type);
943 fs_reg src1 = v->vgrf(glsl_type::float_type);
944 fs_reg zero(brw_imm_f(0.0f));
945 bld.ADD(dest, src0, src1)->saturate = true;
946
947 assert(op == BRW_OPCODE_CMP || op == BRW_OPCODE_MOV);
948 if (op == BRW_OPCODE_CMP)
949 bld.CMP(bld.null_reg_f(), dest, zero, before);
950 else
951 bld.MOV(bld.null_reg_f(), dest)->conditional_mod = before;
952
953 v->calculate_cfg();
954 bblock_t *block0 = v->cfg->blocks[0];
955
956 EXPECT_EQ(0, block0->start_ip);
957 EXPECT_EQ(1, block0->end_ip);
958
959 EXPECT_TRUE(cmod_propagation(v));
960 EXPECT_EQ(0, block0->start_ip);
961 EXPECT_EQ(0, block0->end_ip);
962 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
963 EXPECT_TRUE(instruction(block0, 0)->saturate);
964 EXPECT_EQ(after, instruction(block0, 0)->conditional_mod);
965 }
966
967 void
968 cmod_propagation_test::test_negative_float_saturate_prop(enum brw_conditional_mod before,
969 enum opcode op)
970 {
971 const fs_builder &bld = v->bld;
972 fs_reg dest = v->vgrf(glsl_type::float_type);
973 fs_reg src0 = v->vgrf(glsl_type::float_type);
974 fs_reg src1 = v->vgrf(glsl_type::float_type);
975 fs_reg zero(brw_imm_f(0.0f));
976 bld.ADD(dest, src0, src1)->saturate = true;
977
978 assert(op == BRW_OPCODE_CMP || op == BRW_OPCODE_MOV);
979 if (op == BRW_OPCODE_CMP)
980 bld.CMP(bld.null_reg_f(), dest, zero, before);
981 else
982 bld.MOV(bld.null_reg_f(), dest)->conditional_mod = before;
983
984 v->calculate_cfg();
985 bblock_t *block0 = v->cfg->blocks[0];
986
987 EXPECT_EQ(0, block0->start_ip);
988 EXPECT_EQ(1, block0->end_ip);
989
990 EXPECT_FALSE(cmod_propagation(v));
991 EXPECT_EQ(0, block0->start_ip);
992 EXPECT_EQ(1, block0->end_ip);
993 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
994 EXPECT_TRUE(instruction(block0, 0)->saturate);
995 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
996 EXPECT_EQ(op, instruction(block0, 1)->opcode);
997 EXPECT_FALSE(instruction(block0, 1)->saturate);
998 EXPECT_EQ(before, instruction(block0, 1)->conditional_mod);
999 }
1000
1001 void
1002 cmod_propagation_test::test_negative_int_saturate_prop(enum brw_conditional_mod before,
1003 enum opcode op)
1004 {
1005 const fs_builder &bld = v->bld;
1006 fs_reg dest = v->vgrf(glsl_type::int_type);
1007 fs_reg src0 = v->vgrf(glsl_type::int_type);
1008 fs_reg src1 = v->vgrf(glsl_type::int_type);
1009 fs_reg zero(brw_imm_d(0));
1010 bld.ADD(dest, src0, src1)->saturate = true;
1011
1012 assert(op == BRW_OPCODE_CMP || op == BRW_OPCODE_MOV);
1013 if (op == BRW_OPCODE_CMP)
1014 bld.CMP(bld.null_reg_d(), dest, zero, before);
1015 else
1016 bld.MOV(bld.null_reg_d(), dest)->conditional_mod = before;
1017
1018 v->calculate_cfg();
1019 bblock_t *block0 = v->cfg->blocks[0];
1020
1021 EXPECT_EQ(0, block0->start_ip);
1022 EXPECT_EQ(1, block0->end_ip);
1023
1024 EXPECT_FALSE(cmod_propagation(v));
1025 EXPECT_EQ(0, block0->start_ip);
1026 EXPECT_EQ(1, block0->end_ip);
1027 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1028 EXPECT_TRUE(instruction(block0, 0)->saturate);
1029 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1030 EXPECT_EQ(op, instruction(block0, 1)->opcode);
1031 EXPECT_FALSE(instruction(block0, 1)->saturate);
1032 EXPECT_EQ(before, instruction(block0, 1)->conditional_mod);
1033 }
1034
1035 TEST_F(cmod_propagation_test, float_saturate_nz_cmp)
1036 {
1037 /* With the saturate modifier, the comparison happens before clamping to
1038 * [0, 1]. (sat(x) != 0) == (x > 0).
1039 *
1040 * = Before =
1041 *
1042 * 0: add.sat(8) dest src0 src1
1043 * 1: cmp.nz.f0(8) null dest 0.0f
1044 *
1045 * = After =
1046 * 0: add.sat.g.f0(8) dest src0 src1
1047 */
1048 test_positive_float_saturate_prop(BRW_CONDITIONAL_NZ, BRW_CONDITIONAL_G,
1049 BRW_OPCODE_CMP);
1050 }
1051
1052 TEST_F(cmod_propagation_test, float_saturate_nz_mov)
1053 {
1054 /* With the saturate modifier, the comparison happens before clamping to
1055 * [0, 1]. (sat(x) != 0) == (x > 0).
1056 *
1057 * = Before =
1058 *
1059 * 0: add.sat(8) dest src0 src1
1060 * 1: mov.nz.f0(8) null dest
1061 *
1062 * = After =
1063 * 0: add.sat.g.f0(8) dest src0 src1
1064 */
1065 test_positive_float_saturate_prop(BRW_CONDITIONAL_NZ, BRW_CONDITIONAL_G,
1066 BRW_OPCODE_MOV);
1067 }
1068
1069 TEST_F(cmod_propagation_test, float_saturate_z_cmp)
1070 {
1071 /* With the saturate modifier, the comparison happens before clamping to
1072 * [0, 1]. (sat(x) == 0) == (x <= 0).
1073 *
1074 * = Before =
1075 *
1076 * 0: add.sat(8) dest src0 src1
1077 * 1: cmp.z.f0(8) null dest 0.0f
1078 *
1079 * = After =
1080 * 0: add.sat.le.f0(8) dest src0 src1
1081 */
1082 test_positive_float_saturate_prop(BRW_CONDITIONAL_Z, BRW_CONDITIONAL_LE,
1083 BRW_OPCODE_CMP);
1084 }
1085
1086 TEST_F(cmod_propagation_test, float_saturate_z_mov)
1087 {
1088 /* With the saturate modifier, the comparison happens before clamping to
1089 * [0, 1]. (sat(x) == 0) == (x <= 0).
1090 *
1091 * = Before =
1092 *
1093 * 0: add.sat(8) dest src0 src1
1094 * 1: mov.z.f0(8) null dest
1095 *
1096 * = After =
1097 * 0: add.sat.le.f0(8) dest src0 src1
1098 */
1099 #if 1
1100 /* cmod propagation bails on every MOV except MOV.NZ. */
1101 test_negative_float_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_MOV);
1102 #else
1103 test_positive_float_saturate_prop(BRW_CONDITIONAL_Z, BRW_CONDITIONAL_LE,
1104 BRW_OPCODE_MOV);
1105 #endif
1106 }
1107
1108 TEST_F(cmod_propagation_test, float_saturate_g_cmp)
1109 {
1110 /* With the saturate modifier, the comparison happens before clamping to
1111 * [0, 1]. (sat(x) > 0) == (x > 0).
1112 *
1113 * = Before =
1114 *
1115 * 0: add.sat(8) dest src0 src1
1116 * 1: cmp.g.f0(8) null dest 0.0f
1117 *
1118 * = After =
1119 * 0: add.sat.g.f0(8) dest src0 src1
1120 */
1121 test_positive_float_saturate_prop(BRW_CONDITIONAL_G, BRW_CONDITIONAL_G,
1122 BRW_OPCODE_CMP);
1123 }
1124
1125 TEST_F(cmod_propagation_test, float_saturate_g_mov)
1126 {
1127 /* With the saturate modifier, the comparison happens before clamping to
1128 * [0, 1]. (sat(x) > 0) == (x > 0).
1129 *
1130 * = Before =
1131 *
1132 * 0: add.sat(8) dest src0 src1
1133 * 1: mov.g.f0(8) null dest
1134 *
1135 * = After =
1136 * 0: add.sat.g.f0(8) dest src0 src1
1137 */
1138 #if 1
1139 /* cmod propagation bails on every MOV except MOV.NZ. */
1140 test_negative_float_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_MOV);
1141 #else
1142 test_positive_float_saturate_prop(BRW_CONDITIONAL_G, BRW_CONDITIONAL_G,
1143 BRW_OPCODE_MOV);
1144 #endif
1145 }
1146
1147 TEST_F(cmod_propagation_test, float_saturate_le_cmp)
1148 {
1149 /* With the saturate modifier, the comparison happens before clamping to
1150 * [0, 1]. (sat(x) <= 0) == (x <= 0).
1151 *
1152 * = Before =
1153 *
1154 * 0: add.sat(8) dest src0 src1
1155 * 1: cmp.le.f0(8) null dest 0.0f
1156 *
1157 * = After =
1158 * 0: add.sat.le.f0(8) dest src0 src1
1159 */
1160 test_positive_float_saturate_prop(BRW_CONDITIONAL_LE, BRW_CONDITIONAL_LE,
1161 BRW_OPCODE_CMP);
1162 }
1163
1164 TEST_F(cmod_propagation_test, float_saturate_le_mov)
1165 {
1166 /* With the saturate modifier, the comparison happens before clamping to
1167 * [0, 1]. (sat(x) <= 0) == (x <= 0).
1168 *
1169 * = Before =
1170 *
1171 * 0: add.sat(8) dest src0 src1
1172 * 1: mov.le.f0(8) null dest
1173 *
1174 * = After =
1175 * 0: add.sat.le.f0(8) dest src0 src1
1176 */
1177 #if 1
1178 /* cmod propagation bails on every MOV except MOV.NZ. */
1179 test_negative_float_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_MOV);
1180 #else
1181 test_positive_float_saturate_prop(BRW_CONDITIONAL_LE, BRW_CONDITIONAL_LE,
1182 BRW_OPCODE_MOV);
1183 #endif
1184 }
1185
1186 TEST_F(cmod_propagation_test, float_saturate_l_cmp)
1187 {
1188 /* With the saturate modifier, the comparison happens before clamping to
1189 * [0, 1]. There is no before / after equivalence for (sat(x) < 0).
1190 *
1191 * = Before =
1192 *
1193 * 0: add.sat(8) dest src0 src1
1194 * 1: cmp.l.f0(8) null dest 0.0f
1195 *
1196 * = After =
1197 * No change
1198 */
1199 test_negative_float_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_CMP);
1200 }
1201
1202 #if 0
1203 TEST_F(cmod_propagation_test, float_saturate_l_mov)
1204 {
1205 /* With the saturate modifier, the comparison happens before clamping to
1206 * [0, 1]. There is no before / after equivalence for (sat(x) < 0).
1207 *
1208 * = Before =
1209 *
1210 * 0: add.sat(8) dest src0 src1
1211 * 1: mov.l.f0(8) null dest 0.0f
1212 *
1213 * = After =
1214 * No change
1215 */
1216 test_negative_float_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_MOV);
1217 }
1218 #endif
1219
1220 TEST_F(cmod_propagation_test, float_saturate_ge_cmp)
1221 {
1222 /* With the saturate modifier, the comparison happens before clamping to
1223 * [0, 1]. There is no before / after equivalence for (sat(x) >= 0).
1224 *
1225 * = Before =
1226 *
1227 * 0: add.sat(8) dest src0 src1
1228 * 1: cmp.ge.f0(8) null dest 0.0f
1229 *
1230 * = After =
1231 * No change
1232 */
1233 test_negative_float_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_CMP);
1234 }
1235
1236 TEST_F(cmod_propagation_test, float_saturate_ge_mov)
1237 {
1238 /* With the saturate modifier, the comparison happens before clamping to
1239 * [0, 1]. There is no before / after equivalence for (sat(x) >= 0).
1240 *
1241 * = Before =
1242 *
1243 * 0: add.sat(8) dest src0 src1
1244 * 1: mov.ge.f0(8) null dest 0.0f
1245 *
1246 * = After =
1247 * No change
1248 */
1249 test_negative_float_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_MOV);
1250 }
1251
1252 TEST_F(cmod_propagation_test, int_saturate_nz_cmp)
1253 {
1254 /* = Before =
1255 *
1256 * 0: add.sat(8) dest src0 src1
1257 * 1: cmp.nz.f0(8) null dest 0
1258 *
1259 * = After =
1260 * No change.
1261 */
1262 test_negative_int_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_CMP);
1263 }
1264
1265 TEST_F(cmod_propagation_test, int_saturate_nz_mov)
1266 {
1267 /* = Before =
1268 *
1269 * 0: add.sat(8) dest src0 src1
1270 * 1: mov.nz.f0(8) null dest
1271 *
1272 * = After =
1273 * No change.
1274 */
1275 test_negative_int_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_MOV);
1276 }
1277
1278 TEST_F(cmod_propagation_test, int_saturate_z_cmp)
1279 {
1280 /* = Before =
1281 *
1282 * 0: add.sat(8) dest src0 src1
1283 * 1: cmp.z.f0(8) null dest 0
1284 *
1285 * = After =
1286 * No change.
1287 */
1288 test_negative_int_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_CMP);
1289 }
1290
1291 TEST_F(cmod_propagation_test, int_saturate_z_mov)
1292 {
1293 /* With the saturate modifier, the comparison happens before clamping to
1294 * [0, 1]. (sat(x) == 0) == (x <= 0).
1295 *
1296 * = Before =
1297 *
1298 * 0: add.sat(8) dest src0 src1
1299 * 1: mov.z.f0(8) null dest
1300 *
1301 * = After =
1302 * No change.
1303 */
1304 test_negative_int_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_MOV);
1305 }
1306
1307 TEST_F(cmod_propagation_test, int_saturate_g_cmp)
1308 {
1309 /* = Before =
1310 *
1311 * 0: add.sat(8) dest src0 src1
1312 * 1: cmp.g.f0(8) null dest 0
1313 *
1314 * = After =
1315 * No change.
1316 */
1317 test_negative_int_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_CMP);
1318 }
1319
1320 TEST_F(cmod_propagation_test, int_saturate_g_mov)
1321 {
1322 /* = Before =
1323 *
1324 * 0: add.sat(8) dest src0 src1
1325 * 1: mov.g.f0(8) null dest
1326 *
1327 * = After =
1328 * No change.
1329 */
1330 test_negative_int_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_MOV);
1331 }
1332
1333 TEST_F(cmod_propagation_test, int_saturate_le_cmp)
1334 {
1335 /* = Before =
1336 *
1337 * 0: add.sat(8) dest src0 src1
1338 * 1: cmp.le.f0(8) null dest 0
1339 *
1340 * = After =
1341 * No change.
1342 */
1343 test_negative_int_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_CMP);
1344 }
1345
1346 TEST_F(cmod_propagation_test, int_saturate_le_mov)
1347 {
1348 /* = Before =
1349 *
1350 * 0: add.sat(8) dest src0 src1
1351 * 1: mov.le.f0(8) null dest
1352 *
1353 * = After =
1354 * No change.
1355 */
1356 test_negative_int_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_MOV);
1357 }
1358
1359 TEST_F(cmod_propagation_test, int_saturate_l_cmp)
1360 {
1361 /* = Before =
1362 *
1363 * 0: add.sat(8) dest src0 src1
1364 * 1: cmp.l.f0(8) null dest 0
1365 *
1366 * = After =
1367 * No change
1368 */
1369 test_negative_int_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_CMP);
1370 }
1371
1372 TEST_F(cmod_propagation_test, int_saturate_l_mov)
1373 {
1374 /* = Before =
1375 *
1376 * 0: add.sat(8) dest src0 src1
1377 * 1: mov.l.f0(8) null dest 0
1378 *
1379 * = After =
1380 * No change
1381 */
1382 test_negative_int_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_MOV);
1383 }
1384
1385 TEST_F(cmod_propagation_test, int_saturate_ge_cmp)
1386 {
1387 /* = Before =
1388 *
1389 * 0: add.sat(8) dest src0 src1
1390 * 1: cmp.ge.f0(8) null dest 0
1391 *
1392 * = After =
1393 * No change
1394 */
1395 test_negative_int_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_CMP);
1396 }
1397
1398 TEST_F(cmod_propagation_test, int_saturate_ge_mov)
1399 {
1400 /* = Before =
1401 *
1402 * 0: add.sat(8) dest src0 src1
1403 * 1: mov.ge.f0(8) null dest
1404 *
1405 * = After =
1406 * No change
1407 */
1408 test_negative_int_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_MOV);
1409 }