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 virtual void TearDown();
34
35 public:
36 struct brw_compiler *compiler;
37 struct intel_device_info *devinfo;
38 void *ctx;
39 struct brw_wm_prog_data *prog_data;
40 struct gl_shader_program *shader_prog;
41 fs_visitor *v;
42
43 void test_mov_prop(enum brw_conditional_mod cmod,
44 enum brw_reg_type add_type,
45 enum brw_reg_type mov_dst_type,
46 bool expected_cmod_prop_progress);
47
48 void test_saturate_prop(enum brw_conditional_mod before,
49 enum opcode op,
50 enum brw_reg_type add_type,
51 enum brw_reg_type op_type,
52 bool expected_cmod_prop_progress);
53 };
54
55 class cmod_propagation_fs_visitor : public fs_visitor
56 {
57 public:
cmod_propagation_fs_visitor(struct brw_compiler * compiler,void * mem_ctx,struct brw_wm_prog_data * prog_data,nir_shader * shader)58 cmod_propagation_fs_visitor(struct brw_compiler *compiler,
59 void *mem_ctx,
60 struct brw_wm_prog_data *prog_data,
61 nir_shader *shader)
62 : fs_visitor(compiler, NULL, mem_ctx, NULL,
63 &prog_data->base, shader, 8, false) {}
64 };
65
66
SetUp()67 void cmod_propagation_test::SetUp()
68 {
69 ctx = ralloc_context(NULL);
70 compiler = rzalloc(ctx, struct brw_compiler);
71 devinfo = rzalloc(ctx, struct intel_device_info);
72 compiler->devinfo = devinfo;
73
74 prog_data = ralloc(ctx, struct brw_wm_prog_data);
75 nir_shader *shader =
76 nir_shader_create(ctx, MESA_SHADER_FRAGMENT, NULL, NULL);
77
78 v = new cmod_propagation_fs_visitor(compiler, ctx, prog_data, shader);
79
80 devinfo->ver = 7;
81 devinfo->verx10 = devinfo->ver * 10;
82 }
83
TearDown()84 void cmod_propagation_test::TearDown()
85 {
86 delete v;
87 v = NULL;
88
89 ralloc_free(ctx);
90 ctx = NULL;
91 }
92
93 static fs_inst *
instruction(bblock_t * block,int num)94 instruction(bblock_t *block, int num)
95 {
96 fs_inst *inst = (fs_inst *)block->start();
97 for (int i = 0; i < num; i++) {
98 inst = (fs_inst *)inst->next;
99 }
100 return inst;
101 }
102
103 static bool
cmod_propagation(fs_visitor * v)104 cmod_propagation(fs_visitor *v)
105 {
106 const bool print = getenv("TEST_DEBUG");
107
108 if (print) {
109 fprintf(stderr, "= Before =\n");
110 v->cfg->dump();
111 }
112
113 bool ret = v->opt_cmod_propagation();
114
115 if (print) {
116 fprintf(stderr, "\n= After =\n");
117 v->cfg->dump();
118 }
119
120 return ret;
121 }
122
TEST_F(cmod_propagation_test,basic)123 TEST_F(cmod_propagation_test, basic)
124 {
125 const fs_builder &bld = v->bld;
126 fs_reg dest = v->vgrf(glsl_type::float_type);
127 fs_reg src0 = v->vgrf(glsl_type::float_type);
128 fs_reg src1 = v->vgrf(glsl_type::float_type);
129 fs_reg zero(brw_imm_f(0.0f));
130 bld.ADD(dest, src0, src1);
131 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
132
133 /* = Before =
134 *
135 * 0: add(8) dest src0 src1
136 * 1: cmp.ge.f0(8) null dest 0.0f
137 *
138 * = After =
139 * 0: add.ge.f0(8) dest src0 src1
140 */
141
142 v->calculate_cfg();
143 bblock_t *block0 = v->cfg->blocks[0];
144
145 EXPECT_EQ(0, block0->start_ip);
146 EXPECT_EQ(1, block0->end_ip);
147
148 EXPECT_TRUE(cmod_propagation(v));
149 EXPECT_EQ(0, block0->start_ip);
150 EXPECT_EQ(0, block0->end_ip);
151 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
152 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
153 }
154
TEST_F(cmod_propagation_test,basic_other_flag)155 TEST_F(cmod_propagation_test, basic_other_flag)
156 {
157 const fs_builder &bld = v->bld;
158 fs_reg dest = v->vgrf(glsl_type::float_type);
159 fs_reg src0 = v->vgrf(glsl_type::float_type);
160 fs_reg src1 = v->vgrf(glsl_type::float_type);
161 fs_reg zero(brw_imm_f(0.0f));
162 bld.ADD(dest, src0, src1);
163 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE)
164 ->flag_subreg = 1;
165
166 /* = Before =
167 *
168 * 0: add(8) dest src0 src1
169 * 1: cmp.ge.f0.1(8) null dest 0.0f
170 *
171 * = After =
172 * 0: add.ge.f0.1(8) dest src0 src1
173 */
174
175 v->calculate_cfg();
176 bblock_t *block0 = v->cfg->blocks[0];
177
178 EXPECT_EQ(0, block0->start_ip);
179 EXPECT_EQ(1, block0->end_ip);
180
181 EXPECT_TRUE(cmod_propagation(v));
182 EXPECT_EQ(0, block0->start_ip);
183 EXPECT_EQ(0, block0->end_ip);
184 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
185 EXPECT_EQ(1, instruction(block0, 0)->flag_subreg);
186 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
187 }
188
TEST_F(cmod_propagation_test,cmp_nonzero)189 TEST_F(cmod_propagation_test, cmp_nonzero)
190 {
191 const fs_builder &bld = v->bld;
192 fs_reg dest = v->vgrf(glsl_type::float_type);
193 fs_reg src0 = v->vgrf(glsl_type::float_type);
194 fs_reg src1 = v->vgrf(glsl_type::float_type);
195 fs_reg nonzero(brw_imm_f(1.0f));
196 bld.ADD(dest, src0, src1);
197 bld.CMP(bld.null_reg_f(), dest, nonzero, BRW_CONDITIONAL_GE);
198
199 /* = Before =
200 *
201 * 0: add(8) dest src0 src1
202 * 1: cmp.ge.f0(8) null dest 1.0f
203 *
204 * = After =
205 * (no changes)
206 */
207
208 v->calculate_cfg();
209 bblock_t *block0 = v->cfg->blocks[0];
210
211 EXPECT_EQ(0, block0->start_ip);
212 EXPECT_EQ(1, block0->end_ip);
213
214 EXPECT_FALSE(cmod_propagation(v));
215 EXPECT_EQ(0, block0->start_ip);
216 EXPECT_EQ(1, block0->end_ip);
217 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
218 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
219 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
220 }
221
TEST_F(cmod_propagation_test,non_cmod_instruction)222 TEST_F(cmod_propagation_test, non_cmod_instruction)
223 {
224 const fs_builder &bld = v->bld;
225 fs_reg dest = v->vgrf(glsl_type::uint_type);
226 fs_reg src0 = v->vgrf(glsl_type::uint_type);
227 fs_reg zero(brw_imm_ud(0u));
228 bld.FBL(dest, src0);
229 bld.CMP(bld.null_reg_ud(), dest, zero, BRW_CONDITIONAL_GE);
230
231 /* = Before =
232 *
233 * 0: fbl(8) dest src0
234 * 1: cmp.ge.f0(8) null dest 0u
235 *
236 * = After =
237 * (no changes)
238 */
239
240 v->calculate_cfg();
241 bblock_t *block0 = v->cfg->blocks[0];
242
243 EXPECT_EQ(0, block0->start_ip);
244 EXPECT_EQ(1, block0->end_ip);
245
246 EXPECT_FALSE(cmod_propagation(v));
247 EXPECT_EQ(0, block0->start_ip);
248 EXPECT_EQ(1, block0->end_ip);
249 EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode);
250 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
251 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
252 }
253
TEST_F(cmod_propagation_test,non_cmod_livechannel)254 TEST_F(cmod_propagation_test, non_cmod_livechannel)
255 {
256 const fs_builder &bld = v->bld;
257 fs_reg dest = v->vgrf(glsl_type::uint_type);
258 fs_reg zero(brw_imm_d(0));
259 bld.emit(SHADER_OPCODE_FIND_LIVE_CHANNEL, dest)->exec_size = 32;
260 bld.CMP(bld.null_reg_d(), dest, zero, BRW_CONDITIONAL_Z)->exec_size = 32;
261
262 /* = Before =
263 *
264 * 0: find_live_channel(32) dest
265 * 1: cmp.z.f0.0(32) null dest 0d
266 *
267 *
268 * = After =
269 * (no changes)
270 */
271
272 v->calculate_cfg();
273 bblock_t *block0 = v->cfg->blocks[0];
274
275 EXPECT_EQ(0, block0->start_ip);
276 EXPECT_EQ(1, block0->end_ip);
277
278 EXPECT_FALSE(cmod_propagation(v));
279 EXPECT_EQ(0, block0->start_ip);
280 EXPECT_EQ(1, block0->end_ip);
281 EXPECT_EQ(SHADER_OPCODE_FIND_LIVE_CHANNEL, instruction(block0, 0)->opcode);
282 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
283 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 1)->conditional_mod);
284 }
285
TEST_F(cmod_propagation_test,intervening_flag_write)286 TEST_F(cmod_propagation_test, intervening_flag_write)
287 {
288 const fs_builder &bld = v->bld;
289 fs_reg dest = v->vgrf(glsl_type::float_type);
290 fs_reg src0 = v->vgrf(glsl_type::float_type);
291 fs_reg src1 = v->vgrf(glsl_type::float_type);
292 fs_reg src2 = v->vgrf(glsl_type::float_type);
293 fs_reg zero(brw_imm_f(0.0f));
294 bld.ADD(dest, src0, src1);
295 bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE);
296 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
297
298 /* = Before =
299 *
300 * 0: add(8) dest src0 src1
301 * 1: cmp.ge.f0(8) null src2 0.0f
302 * 2: cmp.ge.f0(8) null dest 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_OPCODE_CMP, instruction(block0, 1)->opcode);
319 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
320 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
321 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
322 }
323
TEST_F(cmod_propagation_test,intervening_mismatch_flag_write)324 TEST_F(cmod_propagation_test, intervening_mismatch_flag_write)
325 {
326 const fs_builder &bld = v->bld;
327 fs_reg dest = v->vgrf(glsl_type::float_type);
328 fs_reg src0 = v->vgrf(glsl_type::float_type);
329 fs_reg src1 = v->vgrf(glsl_type::float_type);
330 fs_reg src2 = v->vgrf(glsl_type::float_type);
331 fs_reg zero(brw_imm_f(0.0f));
332 bld.ADD(dest, src0, src1);
333 bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE)
334 ->flag_subreg = 1;
335 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
336
337 /* = Before =
338 *
339 * 0: add(8) dest src0 src1
340 * 1: cmp.ge.f0.1(8) null src2 0.0f
341 * 2: cmp.ge.f0(8) null dest 0.0f
342 *
343 * = After =
344 * 0: add.ge.f0(8) dest src0 src1
345 * 1: cmp.ge.f0.1(8) null src2 0.0f
346 */
347
348 v->calculate_cfg();
349 bblock_t *block0 = v->cfg->blocks[0];
350
351 EXPECT_EQ(0, block0->start_ip);
352 EXPECT_EQ(2, block0->end_ip);
353
354 EXPECT_TRUE(cmod_propagation(v));
355 EXPECT_EQ(0, block0->start_ip);
356 EXPECT_EQ(1, block0->end_ip);
357 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
358 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
359 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
360 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
361 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
362 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
363 }
364
TEST_F(cmod_propagation_test,intervening_flag_read)365 TEST_F(cmod_propagation_test, intervening_flag_read)
366 {
367 const fs_builder &bld = v->bld;
368 fs_reg dest0 = v->vgrf(glsl_type::float_type);
369 fs_reg dest1 = v->vgrf(glsl_type::float_type);
370 fs_reg src0 = v->vgrf(glsl_type::float_type);
371 fs_reg src1 = v->vgrf(glsl_type::float_type);
372 fs_reg src2 = v->vgrf(glsl_type::float_type);
373 fs_reg zero(brw_imm_f(0.0f));
374 bld.ADD(dest0, src0, src1);
375 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
376 bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
377
378 /* = Before =
379 *
380 * 0: add(8) dest0 src0 src1
381 * 1: (+f0) sel(8) dest1 src2 0.0f
382 * 2: cmp.ge.f0(8) null dest0 0.0f
383 *
384 * = After =
385 * (no changes)
386 */
387
388 v->calculate_cfg();
389 bblock_t *block0 = v->cfg->blocks[0];
390
391 EXPECT_EQ(0, block0->start_ip);
392 EXPECT_EQ(2, block0->end_ip);
393
394 EXPECT_FALSE(cmod_propagation(v));
395 EXPECT_EQ(0, block0->start_ip);
396 EXPECT_EQ(2, block0->end_ip);
397 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
398 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
399 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
400 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
401 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
402 }
403
TEST_F(cmod_propagation_test,intervening_mismatch_flag_read)404 TEST_F(cmod_propagation_test, intervening_mismatch_flag_read)
405 {
406 const fs_builder &bld = v->bld;
407 fs_reg dest0 = v->vgrf(glsl_type::float_type);
408 fs_reg dest1 = v->vgrf(glsl_type::float_type);
409 fs_reg src0 = v->vgrf(glsl_type::float_type);
410 fs_reg src1 = v->vgrf(glsl_type::float_type);
411 fs_reg src2 = v->vgrf(glsl_type::float_type);
412 fs_reg zero(brw_imm_f(0.0f));
413 bld.ADD(dest0, src0, src1);
414 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
415 ->flag_subreg = 1;
416 bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
417
418 /* = Before =
419 *
420 * 0: add(8) dest0 src0 src1
421 * 1: (+f0.1) sel(8) dest1 src2 0.0f
422 * 2: cmp.ge.f0(8) null dest0 0.0f
423 *
424 * = After =
425 * 0: add.ge.f0(8) dest0 src0 src1
426 * 1: (+f0.1) sel(8) dest1 src2 0.0f
427 */
428
429 v->calculate_cfg();
430 bblock_t *block0 = v->cfg->blocks[0];
431
432 EXPECT_EQ(0, block0->start_ip);
433 EXPECT_EQ(2, block0->end_ip);
434
435 EXPECT_TRUE(cmod_propagation(v));
436 EXPECT_EQ(0, block0->start_ip);
437 EXPECT_EQ(1, block0->end_ip);
438 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
439 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
440 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
441 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
442 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
443 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
444 }
445
TEST_F(cmod_propagation_test,intervening_dest_write)446 TEST_F(cmod_propagation_test, intervening_dest_write)
447 {
448 const fs_builder &bld = v->bld;
449 fs_reg dest = v->vgrf(glsl_type::vec4_type);
450 fs_reg src0 = v->vgrf(glsl_type::float_type);
451 fs_reg src1 = v->vgrf(glsl_type::float_type);
452 fs_reg src2 = v->vgrf(glsl_type::vec2_type);
453 fs_reg zero(brw_imm_f(0.0f));
454 bld.ADD(offset(dest, bld, 2), src0, src1);
455 bld.emit(SHADER_OPCODE_TEX, dest, src2)
456 ->size_written = 4 * REG_SIZE;
457 bld.CMP(bld.null_reg_f(), offset(dest, bld, 2), zero, BRW_CONDITIONAL_GE);
458
459 /* = Before =
460 *
461 * 0: add(8) dest+2 src0 src1
462 * 1: tex(8) rlen 4 dest+0 src2
463 * 2: cmp.ge.f0(8) null dest+2 0.0f
464 *
465 * = After =
466 * (no changes)
467 */
468
469 v->calculate_cfg();
470 bblock_t *block0 = v->cfg->blocks[0];
471
472 EXPECT_EQ(0, block0->start_ip);
473 EXPECT_EQ(2, block0->end_ip);
474
475 EXPECT_FALSE(cmod_propagation(v));
476 EXPECT_EQ(0, block0->start_ip);
477 EXPECT_EQ(2, block0->end_ip);
478 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
479 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
480 EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode);
481 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
482 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
483 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
484 }
485
TEST_F(cmod_propagation_test,intervening_flag_read_same_value)486 TEST_F(cmod_propagation_test, intervening_flag_read_same_value)
487 {
488 const fs_builder &bld = v->bld;
489 fs_reg dest0 = v->vgrf(glsl_type::float_type);
490 fs_reg dest1 = v->vgrf(glsl_type::float_type);
491 fs_reg src0 = v->vgrf(glsl_type::float_type);
492 fs_reg src1 = v->vgrf(glsl_type::float_type);
493 fs_reg src2 = v->vgrf(glsl_type::float_type);
494 fs_reg zero(brw_imm_f(0.0f));
495 set_condmod(BRW_CONDITIONAL_GE, bld.ADD(dest0, src0, src1));
496 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
497 bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE);
498
499 /* = Before =
500 *
501 * 0: add.ge.f0(8) dest0 src0 src1
502 * 1: (+f0) sel(8) dest1 src2 0.0f
503 * 2: cmp.ge.f0(8) null dest0 0.0f
504 *
505 * = After =
506 * 0: add.ge.f0(8) dest0 src0 src1
507 * 1: (+f0) sel(8) dest1 src2 0.0f
508 */
509
510 v->calculate_cfg();
511 bblock_t *block0 = v->cfg->blocks[0];
512
513 EXPECT_EQ(0, block0->start_ip);
514 EXPECT_EQ(2, block0->end_ip);
515
516 EXPECT_TRUE(cmod_propagation(v));
517 EXPECT_EQ(0, block0->start_ip);
518 EXPECT_EQ(1, block0->end_ip);
519 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
520 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
521 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
522 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
523 }
524
TEST_F(cmod_propagation_test,negate)525 TEST_F(cmod_propagation_test, negate)
526 {
527 const fs_builder &bld = v->bld;
528 fs_reg dest = v->vgrf(glsl_type::float_type);
529 fs_reg src0 = v->vgrf(glsl_type::float_type);
530 fs_reg src1 = v->vgrf(glsl_type::float_type);
531 fs_reg zero(brw_imm_f(0.0f));
532 bld.ADD(dest, src0, src1);
533 dest.negate = true;
534 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
535
536 /* = Before =
537 *
538 * 0: add(8) dest src0 src1
539 * 1: cmp.ge.f0(8) null -dest 0.0f
540 *
541 * = After =
542 * 0: add.le.f0(8) dest src0 src1
543 */
544
545 v->calculate_cfg();
546 bblock_t *block0 = v->cfg->blocks[0];
547
548 EXPECT_EQ(0, block0->start_ip);
549 EXPECT_EQ(1, block0->end_ip);
550
551 EXPECT_TRUE(cmod_propagation(v));
552 EXPECT_EQ(0, block0->start_ip);
553 EXPECT_EQ(0, block0->end_ip);
554 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
555 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
556 }
557
TEST_F(cmod_propagation_test,movnz)558 TEST_F(cmod_propagation_test, movnz)
559 {
560 const fs_builder &bld = v->bld;
561 fs_reg dest = v->vgrf(glsl_type::float_type);
562 fs_reg src0 = v->vgrf(glsl_type::float_type);
563 fs_reg src1 = v->vgrf(glsl_type::float_type);
564 bld.CMP(dest, src0, src1, BRW_CONDITIONAL_GE);
565 set_condmod(BRW_CONDITIONAL_NZ,
566 bld.MOV(bld.null_reg_f(), dest));
567
568 /* = Before =
569 *
570 * 0: cmp.ge.f0(8) dest src0 src1
571 * 1: mov.nz.f0(8) null dest
572 *
573 * = After =
574 * 0: cmp.ge.f0(8) dest src0 src1
575 */
576
577 v->calculate_cfg();
578 bblock_t *block0 = v->cfg->blocks[0];
579
580 EXPECT_EQ(0, block0->start_ip);
581 EXPECT_EQ(1, block0->end_ip);
582
583 EXPECT_TRUE(cmod_propagation(v));
584 EXPECT_EQ(0, block0->start_ip);
585 EXPECT_EQ(0, block0->end_ip);
586 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
587 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
588 }
589
TEST_F(cmod_propagation_test,different_types_cmod_with_zero)590 TEST_F(cmod_propagation_test, different_types_cmod_with_zero)
591 {
592 const fs_builder &bld = v->bld;
593 fs_reg dest = v->vgrf(glsl_type::int_type);
594 fs_reg src0 = v->vgrf(glsl_type::int_type);
595 fs_reg src1 = v->vgrf(glsl_type::int_type);
596 fs_reg zero(brw_imm_f(0.0f));
597 bld.ADD(dest, src0, src1);
598 bld.CMP(bld.null_reg_f(), retype(dest, BRW_REGISTER_TYPE_F), zero,
599 BRW_CONDITIONAL_GE);
600
601 /* = Before =
602 *
603 * 0: add(8) dest:D src0:D src1:D
604 * 1: cmp.ge.f0(8) null:F dest:F 0.0f
605 *
606 * = After =
607 * (no changes)
608 */
609
610 v->calculate_cfg();
611 bblock_t *block0 = v->cfg->blocks[0];
612
613 EXPECT_EQ(0, block0->start_ip);
614 EXPECT_EQ(1, block0->end_ip);
615
616 EXPECT_FALSE(cmod_propagation(v));
617 EXPECT_EQ(0, block0->start_ip);
618 EXPECT_EQ(1, block0->end_ip);
619 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
620 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
621 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
622 }
623
TEST_F(cmod_propagation_test,andnz_one)624 TEST_F(cmod_propagation_test, andnz_one)
625 {
626 const fs_builder &bld = v->bld;
627 fs_reg dest = v->vgrf(glsl_type::int_type);
628 fs_reg src0 = v->vgrf(glsl_type::float_type);
629 fs_reg zero(brw_imm_f(0.0f));
630 fs_reg one(brw_imm_d(1));
631
632 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
633 set_condmod(BRW_CONDITIONAL_NZ,
634 bld.AND(bld.null_reg_d(), dest, one));
635
636 /* = Before =
637 * 0: cmp.l.f0(8) dest:F src0:F 0F
638 * 1: and.nz.f0(8) null:D dest:D 1D
639 *
640 * = After =
641 * 0: cmp.l.f0(8) dest:F src0:F 0F
642 */
643
644 v->calculate_cfg();
645 bblock_t *block0 = v->cfg->blocks[0];
646
647 EXPECT_EQ(0, block0->start_ip);
648 EXPECT_EQ(1, block0->end_ip);
649
650 EXPECT_TRUE(cmod_propagation(v));
651 EXPECT_EQ(0, block0->start_ip);
652 EXPECT_EQ(0, block0->end_ip);
653 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
654 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
655 EXPECT_TRUE(retype(dest, BRW_REGISTER_TYPE_F)
656 .equals(instruction(block0, 0)->dst));
657 }
658
TEST_F(cmod_propagation_test,andnz_non_one)659 TEST_F(cmod_propagation_test, andnz_non_one)
660 {
661 const fs_builder &bld = v->bld;
662 fs_reg dest = v->vgrf(glsl_type::int_type);
663 fs_reg src0 = v->vgrf(glsl_type::float_type);
664 fs_reg zero(brw_imm_f(0.0f));
665 fs_reg nonone(brw_imm_d(38));
666
667 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
668 set_condmod(BRW_CONDITIONAL_NZ,
669 bld.AND(bld.null_reg_d(), dest, nonone));
670
671 /* = Before =
672 * 0: cmp.l.f0(8) dest:F src0:F 0F
673 * 1: and.nz.f0(8) null:D dest:D 38D
674 *
675 * = After =
676 * (no changes)
677 */
678
679 v->calculate_cfg();
680 bblock_t *block0 = v->cfg->blocks[0];
681
682 EXPECT_EQ(0, block0->start_ip);
683 EXPECT_EQ(1, block0->end_ip);
684
685 EXPECT_FALSE(cmod_propagation(v));
686 EXPECT_EQ(0, block0->start_ip);
687 EXPECT_EQ(1, block0->end_ip);
688 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
689 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
690 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
691 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
692 }
693
TEST_F(cmod_propagation_test,cmp_cmpnz)694 TEST_F(cmod_propagation_test, cmp_cmpnz)
695 {
696 const fs_builder &bld = v->bld;
697
698 fs_reg dst0 = v->vgrf(glsl_type::float_type);
699 fs_reg src0 = v->vgrf(glsl_type::float_type);
700 fs_reg zero(brw_imm_f(0));
701
702 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
703 bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_NZ);
704
705 /* = Before =
706 * 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
707 * 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f
708 *
709 * = After =
710 * 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
711 */
712
713 v->calculate_cfg();
714 bblock_t *block0 = v->cfg->blocks[0];
715
716 EXPECT_TRUE(cmod_propagation(v));
717 EXPECT_EQ(0, block0->start_ip);
718 EXPECT_EQ(0, block0->end_ip);
719 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
720 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
721 }
722
TEST_F(cmod_propagation_test,cmp_cmpg)723 TEST_F(cmod_propagation_test, cmp_cmpg)
724 {
725 const fs_builder &bld = v->bld;
726
727 fs_reg dst0 = v->vgrf(glsl_type::float_type);
728 fs_reg src0 = v->vgrf(glsl_type::float_type);
729 fs_reg zero(brw_imm_f(0));
730
731 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
732 bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_G);
733
734 /* = Before =
735 * 0: cmp.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
736 * 1: cmp.g.f0.0(8) null:F, vgrf0:F, 0f
737 *
738 * = After =
739 * (no changes)
740 */
741
742 v->calculate_cfg();
743 bblock_t *block0 = v->cfg->blocks[0];
744
745 EXPECT_FALSE(cmod_propagation(v));
746 EXPECT_EQ(0, block0->start_ip);
747 EXPECT_EQ(1, block0->end_ip);
748 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
749 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
750 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
751 EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 1)->conditional_mod);
752 }
753
TEST_F(cmod_propagation_test,plnnz_cmpnz)754 TEST_F(cmod_propagation_test, plnnz_cmpnz)
755 {
756 const fs_builder &bld = v->bld;
757
758 fs_reg dst0 = v->vgrf(glsl_type::float_type);
759 fs_reg src0 = v->vgrf(glsl_type::float_type);
760 fs_reg zero(brw_imm_f(0));
761
762 set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
763 bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_NZ);
764
765 /* = Before =
766 * 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
767 * 1: cmp.nz.f0.0(8) null:F, vgrf0:F, 0f
768 *
769 * = After =
770 * 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
771 */
772
773 v->calculate_cfg();
774 bblock_t *block0 = v->cfg->blocks[0];
775
776 EXPECT_TRUE(cmod_propagation(v));
777 EXPECT_EQ(0, block0->start_ip);
778 EXPECT_EQ(0, block0->end_ip);
779 EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
780 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
781 }
782
TEST_F(cmod_propagation_test,plnnz_cmpz)783 TEST_F(cmod_propagation_test, plnnz_cmpz)
784 {
785 const fs_builder &bld = v->bld;
786
787 fs_reg dst0 = v->vgrf(glsl_type::float_type);
788 fs_reg src0 = v->vgrf(glsl_type::float_type);
789 fs_reg zero(brw_imm_f(0));
790
791 set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
792 bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_Z);
793
794 /* = Before =
795 * 0: pln.nz.f0.0(8) vgrf0:F, vgrf1:F, 0f
796 * 1: cmp.z.f0.0(8) null:F, vgrf0:F, 0f
797 *
798 * = After =
799 * 0: pln.z.f0.0(8) vgrf0:F, vgrf1:F, 0f
800 */
801
802 v->calculate_cfg();
803 bblock_t *block0 = v->cfg->blocks[0];
804
805 EXPECT_TRUE(cmod_propagation(v));
806 EXPECT_EQ(0, block0->start_ip);
807 EXPECT_EQ(0, block0->end_ip);
808 EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
809 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
810 }
811
TEST_F(cmod_propagation_test,plnnz_sel_cmpz)812 TEST_F(cmod_propagation_test, plnnz_sel_cmpz)
813 {
814 const fs_builder &bld = v->bld;
815
816 fs_reg dst0 = v->vgrf(glsl_type::float_type);
817 fs_reg dst1 = v->vgrf(glsl_type::float_type);
818 fs_reg src0 = v->vgrf(glsl_type::float_type);
819 fs_reg zero(brw_imm_f(0));
820
821 set_condmod(BRW_CONDITIONAL_NZ, bld.PLN(dst0, src0, zero));
822 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dst1, src0, zero));
823 bld.CMP(bld.null_reg_f(), dst0, zero, BRW_CONDITIONAL_Z);
824
825 /* = Before =
826 * 0: pln.nz.f0.0(8) vgrf0:F, vgrf2:F, 0f
827 * 1: (+f0.0) sel(8) vgrf1:F, vgrf2:F, 0f
828 * 2: cmp.z.f0.0(8) null:F, vgrf0:F, 0f
829 *
830 * = After =
831 * (no changes)
832 */
833
834 v->calculate_cfg();
835 bblock_t *block0 = v->cfg->blocks[0];
836
837 EXPECT_FALSE(cmod_propagation(v));
838 EXPECT_EQ(0, block0->start_ip);
839 EXPECT_EQ(2, block0->end_ip);
840 EXPECT_EQ(BRW_OPCODE_PLN, instruction(block0, 0)->opcode);
841 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
842 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
843 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
844 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
845 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 2)->conditional_mod);
846 }
847
TEST_F(cmod_propagation_test,cmp_cmpg_D)848 TEST_F(cmod_propagation_test, cmp_cmpg_D)
849 {
850 const fs_builder &bld = v->bld;
851
852 fs_reg dst0 = v->vgrf(glsl_type::int_type);
853 fs_reg src0 = v->vgrf(glsl_type::int_type);
854 fs_reg zero(brw_imm_d(0));
855 fs_reg one(brw_imm_d(1));
856
857 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
858 bld.CMP(bld.null_reg_d(), dst0, zero, BRW_CONDITIONAL_G);
859
860 /* = Before =
861 * 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
862 * 1: cmp.g.f0.0(8) null:D, vgrf0:D, 0d
863 *
864 * = After =
865 * (no changes)
866 */
867
868 v->calculate_cfg();
869 bblock_t *block0 = v->cfg->blocks[0];
870
871 EXPECT_FALSE(cmod_propagation(v));
872 EXPECT_EQ(0, block0->start_ip);
873 EXPECT_EQ(1, block0->end_ip);
874 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
875 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
876 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
877 EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 1)->conditional_mod);
878 }
879
TEST_F(cmod_propagation_test,cmp_cmpg_UD)880 TEST_F(cmod_propagation_test, cmp_cmpg_UD)
881 {
882 const fs_builder &bld = v->bld;
883
884 fs_reg dst0 = v->vgrf(glsl_type::uint_type);
885 fs_reg src0 = v->vgrf(glsl_type::uint_type);
886 fs_reg zero(brw_imm_ud(0));
887
888 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
889 bld.CMP(bld.null_reg_ud(), dst0, zero, BRW_CONDITIONAL_G);
890
891 /* = Before =
892 * 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
893 * 1: cmp.g.f0.0(8) null:UD, vgrf0:UD, 0u
894 *
895 * = After =
896 * 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
897 */
898
899 v->calculate_cfg();
900 bblock_t *block0 = v->cfg->blocks[0];
901
902 EXPECT_TRUE(cmod_propagation(v));
903 EXPECT_EQ(0, block0->start_ip);
904 EXPECT_EQ(0, block0->end_ip);
905 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
906 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
907 }
908
TEST_F(cmod_propagation_test,cmp_cmpl_D)909 TEST_F(cmod_propagation_test, cmp_cmpl_D)
910 {
911 const fs_builder &bld = v->bld;
912
913 fs_reg dst0 = v->vgrf(glsl_type::int_type);
914 fs_reg src0 = v->vgrf(glsl_type::int_type);
915 fs_reg zero(brw_imm_d(0));
916
917 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
918 bld.CMP(bld.null_reg_d(), dst0, zero, BRW_CONDITIONAL_L);
919
920 /* = Before =
921 * 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
922 * 1: cmp.l.f0.0(8) null:D, vgrf0:D, 0d
923 *
924 * = After =
925 * 0: cmp.nz.f0.0(8) vgrf0:D, vgrf1:D, 0d
926 */
927
928 v->calculate_cfg();
929 bblock_t *block0 = v->cfg->blocks[0];
930
931 EXPECT_TRUE(cmod_propagation(v));
932 EXPECT_EQ(0, block0->start_ip);
933 EXPECT_EQ(0, block0->end_ip);
934 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
935 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
936 }
937
TEST_F(cmod_propagation_test,cmp_cmpl_UD)938 TEST_F(cmod_propagation_test, cmp_cmpl_UD)
939 {
940 const fs_builder &bld = v->bld;
941
942 fs_reg dst0 = v->vgrf(glsl_type::uint_type);
943 fs_reg src0 = v->vgrf(glsl_type::uint_type);
944 fs_reg zero(brw_imm_ud(0));
945
946 bld.CMP(dst0, src0, zero, BRW_CONDITIONAL_NZ);
947 bld.CMP(bld.null_reg_ud(), dst0, zero, BRW_CONDITIONAL_L);
948
949 /* = Before =
950 * 0: cmp.nz.f0.0(8) vgrf0:UD, vgrf1:UD, 0u
951 * 1: cmp.l.f0.0(8) null:UD, vgrf0:UD, 0u
952 *
953 * = After =
954 * (no changes)
955 */
956
957 v->calculate_cfg();
958 bblock_t *block0 = v->cfg->blocks[0];
959
960 EXPECT_FALSE(cmod_propagation(v));
961 EXPECT_EQ(0, block0->start_ip);
962 EXPECT_EQ(1, block0->end_ip);
963 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
964 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
965 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
966 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
967 }
968
TEST_F(cmod_propagation_test,andz_one)969 TEST_F(cmod_propagation_test, andz_one)
970 {
971 const fs_builder &bld = v->bld;
972 fs_reg dest = v->vgrf(glsl_type::int_type);
973 fs_reg src0 = v->vgrf(glsl_type::float_type);
974 fs_reg zero(brw_imm_f(0.0f));
975 fs_reg one(brw_imm_d(1));
976
977 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L);
978 set_condmod(BRW_CONDITIONAL_Z,
979 bld.AND(bld.null_reg_d(), dest, one));
980
981 /* = Before =
982 * 0: cmp.l.f0(8) dest:F src0:F 0F
983 * 1: and.z.f0(8) null:D dest:D 1D
984 *
985 * = After =
986 * (no changes)
987 */
988
989 v->calculate_cfg();
990 bblock_t *block0 = v->cfg->blocks[0];
991
992 EXPECT_EQ(0, block0->start_ip);
993 EXPECT_EQ(1, block0->end_ip);
994
995 EXPECT_FALSE(cmod_propagation(v));
996 EXPECT_EQ(0, block0->start_ip);
997 EXPECT_EQ(1, block0->end_ip);
998 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode);
999 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1000 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode);
1001 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
1002 }
1003
TEST_F(cmod_propagation_test,add_not_merge_with_compare)1004 TEST_F(cmod_propagation_test, add_not_merge_with_compare)
1005 {
1006 const fs_builder &bld = v->bld;
1007 fs_reg dest = v->vgrf(glsl_type::float_type);
1008 fs_reg src0 = v->vgrf(glsl_type::float_type);
1009 fs_reg src1 = v->vgrf(glsl_type::float_type);
1010 bld.ADD(dest, src0, src1);
1011 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1012
1013 /* The addition and the implicit subtraction in the compare do not compute
1014 * related values.
1015 *
1016 * = Before =
1017 * 0: add(8) dest:F src0:F src1:F
1018 * 1: cmp.l.f0(8) null:F src0:F src1:F
1019 *
1020 * = After =
1021 * (no changes)
1022 */
1023 v->calculate_cfg();
1024 bblock_t *block0 = v->cfg->blocks[0];
1025
1026 EXPECT_EQ(0, block0->start_ip);
1027 EXPECT_EQ(1, block0->end_ip);
1028
1029 EXPECT_FALSE(cmod_propagation(v));
1030 EXPECT_EQ(0, block0->start_ip);
1031 EXPECT_EQ(1, block0->end_ip);
1032 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1033 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1034 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
1035 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
1036 }
1037
TEST_F(cmod_propagation_test,subtract_merge_with_compare)1038 TEST_F(cmod_propagation_test, subtract_merge_with_compare)
1039 {
1040 const fs_builder &bld = v->bld;
1041 fs_reg dest = v->vgrf(glsl_type::float_type);
1042 fs_reg src0 = v->vgrf(glsl_type::float_type);
1043 fs_reg src1 = v->vgrf(glsl_type::float_type);
1044 bld.ADD(dest, src0, negate(src1));
1045 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1046
1047 /* = Before =
1048 * 0: add(8) dest:F src0:F -src1:F
1049 * 1: cmp.l.f0(8) null:F src0:F src1:F
1050 *
1051 * = After =
1052 * 0: add.l.f0(8) dest:F src0:F -src1:F
1053 */
1054 v->calculate_cfg();
1055 bblock_t *block0 = v->cfg->blocks[0];
1056
1057 EXPECT_EQ(0, block0->start_ip);
1058 EXPECT_EQ(1, block0->end_ip);
1059
1060 EXPECT_TRUE(cmod_propagation(v));
1061 EXPECT_EQ(0, block0->start_ip);
1062 EXPECT_EQ(0, block0->end_ip);
1063 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1064 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1065 }
1066
TEST_F(cmod_propagation_test,subtract_immediate_merge_with_compare)1067 TEST_F(cmod_propagation_test, subtract_immediate_merge_with_compare)
1068 {
1069 const fs_builder &bld = v->bld;
1070 fs_reg dest = v->vgrf(glsl_type::float_type);
1071 fs_reg src0 = v->vgrf(glsl_type::float_type);
1072 fs_reg one(brw_imm_f(1.0f));
1073 fs_reg negative_one(brw_imm_f(-1.0f));
1074
1075 bld.ADD(dest, src0, negative_one);
1076 bld.CMP(bld.null_reg_f(), src0, one, BRW_CONDITIONAL_NZ);
1077
1078 /* = Before =
1079 * 0: add(8) dest:F src0:F -1.0f
1080 * 1: cmp.nz.f0(8) null:F src0:F 1.0f
1081 *
1082 * = After =
1083 * 0: add.nz.f0(8) dest:F src0:F -1.0f
1084 */
1085 v->calculate_cfg();
1086 bblock_t *block0 = v->cfg->blocks[0];
1087
1088 EXPECT_EQ(0, block0->start_ip);
1089 EXPECT_EQ(1, block0->end_ip);
1090
1091 EXPECT_TRUE(cmod_propagation(v));
1092 EXPECT_EQ(0, block0->start_ip);
1093 EXPECT_EQ(0, block0->end_ip);
1094 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1095 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
1096 }
1097
TEST_F(cmod_propagation_test,subtract_merge_with_compare_intervening_add)1098 TEST_F(cmod_propagation_test, subtract_merge_with_compare_intervening_add)
1099 {
1100 const fs_builder &bld = v->bld;
1101 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1102 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1103 fs_reg src0 = v->vgrf(glsl_type::float_type);
1104 fs_reg src1 = v->vgrf(glsl_type::float_type);
1105 bld.ADD(dest0, src0, negate(src1));
1106 bld.ADD(dest1, src0, src1);
1107 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1108
1109 /* = Before =
1110 * 0: add(8) dest0:F src0:F -src1:F
1111 * 1: add(8) dest1:F src0:F src1:F
1112 * 2: cmp.l.f0(8) null:F src0:F src1:F
1113 *
1114 * = After =
1115 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1116 * 1: add(8) dest1:F src0:F src1:F
1117 */
1118 v->calculate_cfg();
1119 bblock_t *block0 = v->cfg->blocks[0];
1120
1121 EXPECT_EQ(0, block0->start_ip);
1122 EXPECT_EQ(2, block0->end_ip);
1123
1124 EXPECT_TRUE(cmod_propagation(v));
1125 EXPECT_EQ(0, block0->start_ip);
1126 EXPECT_EQ(1, block0->end_ip);
1127 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1128 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1129 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1130 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
1131 }
1132
TEST_F(cmod_propagation_test,subtract_not_merge_with_compare_intervening_partial_write)1133 TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_partial_write)
1134 {
1135 const fs_builder &bld = v->bld;
1136 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1137 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1138 fs_reg src0 = v->vgrf(glsl_type::float_type);
1139 fs_reg src1 = v->vgrf(glsl_type::float_type);
1140 bld.ADD(dest0, src0, negate(src1));
1141 set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, src0, negate(src1)));
1142 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1143
1144 /* = Before =
1145 * 0: add(8) dest0:F src0:F -src1:F
1146 * 1: (+f0) add(8) dest1:F src0:F -src1:F
1147 * 2: cmp.l.f0(8) null:F src0:F src1:F
1148 *
1149 * = After =
1150 * (no changes)
1151 */
1152 v->calculate_cfg();
1153 bblock_t *block0 = v->cfg->blocks[0];
1154
1155 EXPECT_EQ(0, block0->start_ip);
1156 EXPECT_EQ(2, block0->end_ip);
1157
1158 EXPECT_FALSE(cmod_propagation(v));
1159 EXPECT_EQ(0, block0->start_ip);
1160 EXPECT_EQ(2, block0->end_ip);
1161 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1162 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1163 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1164 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod);
1165 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
1166 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
1167 }
1168
TEST_F(cmod_propagation_test,subtract_not_merge_with_compare_intervening_add)1169 TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_add)
1170 {
1171 const fs_builder &bld = v->bld;
1172 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1173 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1174 fs_reg src0 = v->vgrf(glsl_type::float_type);
1175 fs_reg src1 = v->vgrf(glsl_type::float_type);
1176 bld.ADD(dest0, src0, negate(src1));
1177 set_condmod(BRW_CONDITIONAL_EQ, bld.ADD(dest1, src0, src1));
1178 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1179
1180 /* = Before =
1181 * 0: add(8) dest0:F src0:F -src1:F
1182 * 1: add.z.f0(8) dest1:F src0:F src1:F
1183 * 2: cmp.l.f0(8) null:F src0:F src1:F
1184 *
1185 * = After =
1186 * (no changes)
1187 */
1188 v->calculate_cfg();
1189 bblock_t *block0 = v->cfg->blocks[0];
1190
1191 EXPECT_EQ(0, block0->start_ip);
1192 EXPECT_EQ(2, block0->end_ip);
1193
1194 EXPECT_FALSE(cmod_propagation(v));
1195 EXPECT_EQ(0, block0->start_ip);
1196 EXPECT_EQ(2, block0->end_ip);
1197 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1198 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1199 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1200 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
1201 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
1202 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod);
1203 }
1204
TEST_F(cmod_propagation_test,add_merge_with_compare)1205 TEST_F(cmod_propagation_test, add_merge_with_compare)
1206 {
1207 const fs_builder &bld = v->bld;
1208 fs_reg dest = v->vgrf(glsl_type::float_type);
1209 fs_reg src0 = v->vgrf(glsl_type::float_type);
1210 fs_reg src1 = v->vgrf(glsl_type::float_type);
1211 bld.ADD(dest, src0, src1);
1212 bld.CMP(bld.null_reg_f(), src0, negate(src1), BRW_CONDITIONAL_L);
1213
1214 /* = Before =
1215 * 0: add(8) dest:F src0:F src1:F
1216 * 1: cmp.l.f0(8) null:F src0:F -src1:F
1217 *
1218 * = After =
1219 * 0: add.l.f0(8) dest:F src0:F src1:F
1220 */
1221 v->calculate_cfg();
1222 bblock_t *block0 = v->cfg->blocks[0];
1223
1224 EXPECT_EQ(0, block0->start_ip);
1225 EXPECT_EQ(1, block0->end_ip);
1226
1227 EXPECT_TRUE(cmod_propagation(v));
1228 EXPECT_EQ(0, block0->start_ip);
1229 EXPECT_EQ(0, block0->end_ip);
1230 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1231 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1232 }
1233
TEST_F(cmod_propagation_test,negative_subtract_merge_with_compare)1234 TEST_F(cmod_propagation_test, negative_subtract_merge_with_compare)
1235 {
1236 const fs_builder &bld = v->bld;
1237 fs_reg dest = v->vgrf(glsl_type::float_type);
1238 fs_reg src0 = v->vgrf(glsl_type::float_type);
1239 fs_reg src1 = v->vgrf(glsl_type::float_type);
1240 bld.ADD(dest, src1, negate(src0));
1241 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1242
1243 /* The result of the subtract is the negatiion of the result of the
1244 * implicit subtract in the compare, so the condition must change.
1245 *
1246 * = Before =
1247 * 0: add(8) dest:F src1:F -src0:F
1248 * 1: cmp.l.f0(8) null:F src0:F src1:F
1249 *
1250 * = After =
1251 * 0: add.g.f0(8) dest:F src0:F -src1:F
1252 */
1253 v->calculate_cfg();
1254 bblock_t *block0 = v->cfg->blocks[0];
1255
1256 EXPECT_EQ(0, block0->start_ip);
1257 EXPECT_EQ(1, block0->end_ip);
1258
1259 EXPECT_TRUE(cmod_propagation(v));
1260 EXPECT_EQ(0, block0->start_ip);
1261 EXPECT_EQ(0, block0->end_ip);
1262 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1263 EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod);
1264 }
1265
TEST_F(cmod_propagation_test,subtract_delete_compare)1266 TEST_F(cmod_propagation_test, subtract_delete_compare)
1267 {
1268 const fs_builder &bld = v->bld;
1269 fs_reg dest = v->vgrf(glsl_type::float_type);
1270 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1271 fs_reg src0 = v->vgrf(glsl_type::float_type);
1272 fs_reg src1 = v->vgrf(glsl_type::float_type);
1273 fs_reg src2 = v->vgrf(glsl_type::float_type);
1274
1275 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)));
1276 set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2));
1277 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1278
1279 /* = Before =
1280 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1281 * 1: (+f0) mov(0) dest1:F src2:F
1282 * 2: cmp.l.f0(8) null:F src0:F src1:F
1283 *
1284 * = After =
1285 * 0: add.l.f0(8) dest:F src0:F -src1:F
1286 * 1: (+f0) mov(0) dest1:F src2:F
1287 */
1288 v->calculate_cfg();
1289 bblock_t *block0 = v->cfg->blocks[0];
1290
1291 EXPECT_EQ(0, block0->start_ip);
1292 EXPECT_EQ(2, block0->end_ip);
1293
1294 EXPECT_TRUE(cmod_propagation(v));
1295 EXPECT_EQ(0, block0->start_ip);
1296 EXPECT_EQ(1, block0->end_ip);
1297 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1298 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1299 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
1300 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1301 }
1302
TEST_F(cmod_propagation_test,subtract_delete_compare_other_flag)1303 TEST_F(cmod_propagation_test, subtract_delete_compare_other_flag)
1304 {
1305 /* This test is the same as subtract_delete_compare but it explicitly used
1306 * flag f0.1 for the subtraction and the comparison.
1307 */
1308 const fs_builder &bld = v->bld;
1309 fs_reg dest = v->vgrf(glsl_type::float_type);
1310 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1311 fs_reg src0 = v->vgrf(glsl_type::float_type);
1312 fs_reg src1 = v->vgrf(glsl_type::float_type);
1313 fs_reg src2 = v->vgrf(glsl_type::float_type);
1314
1315 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)))
1316 ->flag_subreg = 1;
1317 set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2));
1318 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
1319 ->flag_subreg = 1;
1320
1321 /* = Before =
1322 * 0: add.l.f0.1(8) dest0:F src0:F -src1:F
1323 * 1: (+f0) mov(0) dest1:F src2:F
1324 * 2: cmp.l.f0.1(8) null:F src0:F src1:F
1325 *
1326 * = After =
1327 * 0: add.l.f0.1(8) dest:F src0:F -src1:F
1328 * 1: (+f0) mov(0) dest1:F src2:F
1329 */
1330 v->calculate_cfg();
1331 bblock_t *block0 = v->cfg->blocks[0];
1332
1333 EXPECT_EQ(0, block0->start_ip);
1334 EXPECT_EQ(2, block0->end_ip);
1335
1336 EXPECT_TRUE(cmod_propagation(v));
1337 EXPECT_EQ(0, block0->start_ip);
1338 EXPECT_EQ(1, block0->end_ip);
1339 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1340 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1341 EXPECT_EQ(1, instruction(block0, 0)->flag_subreg);
1342 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
1343 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1344 }
1345
TEST_F(cmod_propagation_test,subtract_to_mismatch_flag)1346 TEST_F(cmod_propagation_test, subtract_to_mismatch_flag)
1347 {
1348 const fs_builder &bld = v->bld;
1349 fs_reg dest = v->vgrf(glsl_type::float_type);
1350 fs_reg src0 = v->vgrf(glsl_type::float_type);
1351 fs_reg src1 = v->vgrf(glsl_type::float_type);
1352
1353 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1)));
1354 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
1355 ->flag_subreg = 1;
1356
1357 /* = Before =
1358 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1359 * 1: cmp.l.f0.1(8) null:F src0:F src1:F
1360 *
1361 * = After =
1362 * No changes
1363 */
1364 v->calculate_cfg();
1365 bblock_t *block0 = v->cfg->blocks[0];
1366
1367 EXPECT_EQ(0, block0->start_ip);
1368 EXPECT_EQ(1, block0->end_ip);
1369
1370 EXPECT_FALSE(cmod_propagation(v));
1371 EXPECT_EQ(0, block0->start_ip);
1372 EXPECT_EQ(1, block0->end_ip);
1373 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1374 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1375 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
1376 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
1377 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
1378 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
1379 }
1380
TEST_F(cmod_propagation_test,subtract_merge_with_compare_intervening_mismatch_flag_write)1381 TEST_F(cmod_propagation_test,
1382 subtract_merge_with_compare_intervening_mismatch_flag_write)
1383 {
1384 const fs_builder &bld = v->bld;
1385 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1386 fs_reg src0 = v->vgrf(glsl_type::float_type);
1387 fs_reg src1 = v->vgrf(glsl_type::float_type);
1388
1389 bld.ADD(dest0, src0, negate(src1));
1390 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L)
1391 ->flag_subreg = 1;
1392 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1393
1394 /* = Before =
1395 * 0: add(8) dest0:F src0:F -src1:F
1396 * 1: cmp.l.f0.1(8) null:F src0:F src1:F
1397 * 2: cmp.l.f0(8) null:F src0:F src1:F
1398 *
1399 * = After =
1400 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1401 * 1: cmp.l.f0.1(8) null:F src0:F src1:F
1402 *
1403 * NOTE: Another perfectly valid after sequence would be:
1404 *
1405 * 0: add.f0.1(8) dest0:F src0:F -src1:F
1406 * 1: cmp.l.f0(8) null:F src0:F src1:F
1407 *
1408 * However, the optimization pass starts at the end of the basic block.
1409 * Because of this, the cmp.l.f0 will always be chosen. If the pass
1410 * changes its strategy, this test will also need to change.
1411 */
1412 v->calculate_cfg();
1413 bblock_t *block0 = v->cfg->blocks[0];
1414
1415 EXPECT_EQ(0, block0->start_ip);
1416 EXPECT_EQ(2, block0->end_ip);
1417
1418 EXPECT_TRUE(cmod_propagation(v));
1419 EXPECT_EQ(0, block0->start_ip);
1420 EXPECT_EQ(1, block0->end_ip);
1421 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1422 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1423 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
1424 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
1425 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod);
1426 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
1427 }
1428
TEST_F(cmod_propagation_test,subtract_merge_with_compare_intervening_mismatch_flag_read)1429 TEST_F(cmod_propagation_test,
1430 subtract_merge_with_compare_intervening_mismatch_flag_read)
1431 {
1432 const fs_builder &bld = v->bld;
1433 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1434 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1435 fs_reg src0 = v->vgrf(glsl_type::float_type);
1436 fs_reg src1 = v->vgrf(glsl_type::float_type);
1437 fs_reg src2 = v->vgrf(glsl_type::float_type);
1438 fs_reg zero(brw_imm_f(0.0f));
1439
1440 bld.ADD(dest0, src0, negate(src1));
1441 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
1442 ->flag_subreg = 1;
1443 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1444
1445 /* = Before =
1446 * 0: add(8) dest0:F src0:F -src1:F
1447 * 1: (+f0.1) sel(8) dest1 src2 0.0f
1448 * 2: cmp.l.f0(8) null:F src0:F src1:F
1449 *
1450 * = After =
1451 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1452 * 1: (+f0.1) sel(8) dest1 src2 0.0f
1453 */
1454 v->calculate_cfg();
1455 bblock_t *block0 = v->cfg->blocks[0];
1456
1457 EXPECT_EQ(0, block0->start_ip);
1458 EXPECT_EQ(2, block0->end_ip);
1459
1460 EXPECT_TRUE(cmod_propagation(v));
1461 EXPECT_EQ(0, block0->start_ip);
1462 EXPECT_EQ(1, block0->end_ip);
1463 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1464 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1465 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
1466 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
1467 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1468 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
1469 }
1470
TEST_F(cmod_propagation_test,subtract_delete_compare_derp)1471 TEST_F(cmod_propagation_test, subtract_delete_compare_derp)
1472 {
1473 const fs_builder &bld = v->bld;
1474 fs_reg dest0 = v->vgrf(glsl_type::float_type);
1475 fs_reg dest1 = v->vgrf(glsl_type::float_type);
1476 fs_reg src0 = v->vgrf(glsl_type::float_type);
1477 fs_reg src1 = v->vgrf(glsl_type::float_type);
1478
1479 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest0, src0, negate(src1)));
1480 set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, negate(src0), src1));
1481 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L);
1482
1483 /* = Before =
1484 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1485 * 1: (+f0) add(0) dest1:F -src0:F src1:F
1486 * 2: cmp.l.f0(8) null:F src0:F src1:F
1487 *
1488 * = After =
1489 * 0: add.l.f0(8) dest0:F src0:F -src1:F
1490 * 1: (+f0) add(0) dest1:F -src0:F src1:F
1491 */
1492 v->calculate_cfg();
1493 bblock_t *block0 = v->cfg->blocks[0];
1494
1495 EXPECT_EQ(0, block0->start_ip);
1496 EXPECT_EQ(2, block0->end_ip);
1497
1498 EXPECT_TRUE(cmod_propagation(v));
1499 EXPECT_EQ(0, block0->start_ip);
1500 EXPECT_EQ(1, block0->end_ip);
1501 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1502 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod);
1503 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode);
1504 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
1505 }
1506
TEST_F(cmod_propagation_test,signed_unsigned_comparison_mismatch)1507 TEST_F(cmod_propagation_test, signed_unsigned_comparison_mismatch)
1508 {
1509 const fs_builder &bld = v->bld;
1510 fs_reg dest0 = v->vgrf(glsl_type::int_type);
1511 fs_reg src0 = v->vgrf(glsl_type::int_type);
1512 src0.type = BRW_REGISTER_TYPE_W;
1513
1514 bld.ASR(dest0, negate(src0), brw_imm_d(15));
1515 bld.CMP(bld.null_reg_ud(), retype(dest0, BRW_REGISTER_TYPE_UD),
1516 brw_imm_ud(0u), BRW_CONDITIONAL_LE);
1517
1518 /* = Before =
1519 * 0: asr(8) dest:D -src0:W 15D
1520 * 1: cmp.le.f0(8) null:UD dest:UD 0UD
1521 *
1522 * = After =
1523 * (no changes)
1524 */
1525 v->calculate_cfg();
1526 bblock_t *block0 = v->cfg->blocks[0];
1527
1528 EXPECT_EQ(0, block0->start_ip);
1529 EXPECT_EQ(1, block0->end_ip);
1530
1531 EXPECT_FALSE(cmod_propagation(v));
1532 EXPECT_EQ(0, block0->start_ip);
1533 EXPECT_EQ(1, block0->end_ip);
1534 EXPECT_EQ(BRW_OPCODE_ASR, instruction(block0, 0)->opcode);
1535 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
1536 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 1)->conditional_mod);
1537 }
1538
TEST_F(cmod_propagation_test,ior_f2i_nz)1539 TEST_F(cmod_propagation_test, ior_f2i_nz)
1540 {
1541 const fs_builder &bld = v->bld;
1542 fs_reg dest = bld.vgrf(BRW_REGISTER_TYPE_D);
1543 fs_reg src0 = bld.vgrf(BRW_REGISTER_TYPE_D);
1544 fs_reg src1 = bld.vgrf(BRW_REGISTER_TYPE_D);
1545
1546 bld.OR(dest, src0, src1);
1547 bld.MOV(bld.null_reg_d(), retype(dest, BRW_REGISTER_TYPE_F))
1548 ->conditional_mod = BRW_CONDITIONAL_NZ;
1549
1550 /* = Before =
1551 * 0: or(8) dest:D src0:D src1:D
1552 * 1: mov.nz(8) null:D dest:F
1553 *
1554 * = After =
1555 * No changes.
1556 *
1557 * If src0 = 0x30000000 and src1 = 0x0f000000, then the value stored in
1558 * dest, interpreted as floating point, is 0.5. This bit pattern is not
1559 * zero, but after the float-to-integer conversion, the value is zero.
1560 */
1561 v->calculate_cfg();
1562 bblock_t *block0 = v->cfg->blocks[0];
1563
1564 EXPECT_EQ(0, block0->start_ip);
1565 EXPECT_EQ(1, block0->end_ip);
1566
1567 EXPECT_FALSE(cmod_propagation(v));
1568 EXPECT_EQ(0, block0->start_ip);
1569
1570 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
1571 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
1572
1573 /* This is ASSERT_EQ because if end_ip is 0, the instruction(block0, 1)
1574 * calls will not work properly, and the test will give weird results.
1575 */
1576 ASSERT_EQ(1, block0->end_ip);
1577 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
1578 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
1579 }
1580
1581
1582 void
test_mov_prop(enum brw_conditional_mod cmod,enum brw_reg_type add_type,enum brw_reg_type mov_dst_type,bool expected_cmod_prop_progress)1583 cmod_propagation_test::test_mov_prop(enum brw_conditional_mod cmod,
1584 enum brw_reg_type add_type,
1585 enum brw_reg_type mov_dst_type,
1586 bool expected_cmod_prop_progress)
1587 {
1588 const fs_builder &bld = v->bld;
1589 fs_reg dest = bld.vgrf(add_type);
1590 fs_reg src0 = bld.vgrf(add_type);
1591 fs_reg src1 = bld.vgrf(add_type);
1592
1593 bld.ADD(dest, src0, src1);
1594 bld.MOV(retype(bld.null_reg_ud(), mov_dst_type), dest)
1595 ->conditional_mod = cmod;
1596
1597 v->calculate_cfg();
1598 bblock_t *block0 = v->cfg->blocks[0];
1599
1600 EXPECT_EQ(0, block0->start_ip);
1601 EXPECT_EQ(1, block0->end_ip);
1602
1603 EXPECT_EQ(expected_cmod_prop_progress, cmod_propagation(v));
1604
1605 const enum brw_conditional_mod add_cmod =
1606 expected_cmod_prop_progress ? cmod : BRW_CONDITIONAL_NONE;
1607
1608 EXPECT_EQ(0, block0->start_ip);
1609
1610 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
1611 EXPECT_EQ(add_cmod, instruction(block0, 0)->conditional_mod);
1612
1613 if (expected_cmod_prop_progress) {
1614 EXPECT_EQ(0, block0->end_ip);
1615 } else {
1616 /* This is ASSERT_EQ because if end_ip is 0, the instruction(block0, 1)
1617 * calls will not work properly, and the test will give weird results.
1618 */
1619 ASSERT_EQ(1, block0->end_ip);
1620
1621 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode);
1622 EXPECT_EQ(cmod, instruction(block0, 1)->conditional_mod);
1623 }
1624 }
1625
TEST_F(cmod_propagation_test,fadd_fmov_nz)1626 TEST_F(cmod_propagation_test, fadd_fmov_nz)
1627 {
1628 /* = Before =
1629 * 0: add(8) dest:F src0:F src1:F
1630 * 1: mov.nz(8) null:F dest:F
1631 *
1632 * = After =
1633 * 0: add.nz(8) dest:F src0:F src1:F
1634 */
1635 test_mov_prop(BRW_CONDITIONAL_NZ,
1636 BRW_REGISTER_TYPE_F,
1637 BRW_REGISTER_TYPE_F,
1638 true);
1639 }
1640
TEST_F(cmod_propagation_test,fadd_fmov_z)1641 TEST_F(cmod_propagation_test, fadd_fmov_z)
1642 {
1643 /* = Before =
1644 * 0: add(8) dest:F src0:F src1:F
1645 * 1: mov.z(8) null:F dest:F
1646 *
1647 * = After =
1648 * 0: add.z(8) dest:F src0:F src1:F
1649 */
1650 test_mov_prop(BRW_CONDITIONAL_Z,
1651 BRW_REGISTER_TYPE_F,
1652 BRW_REGISTER_TYPE_F,
1653 true);
1654 }
1655
TEST_F(cmod_propagation_test,fadd_fmov_l)1656 TEST_F(cmod_propagation_test, fadd_fmov_l)
1657 {
1658 /* = Before =
1659 * 0: add(8) dest:F src0:F src1:F
1660 * 1: mov.l(8) null:F dest:F
1661 *
1662 * = After =
1663 * 0: add.l(8) dest:F src0:F src1:F
1664 */
1665 test_mov_prop(BRW_CONDITIONAL_L,
1666 BRW_REGISTER_TYPE_F,
1667 BRW_REGISTER_TYPE_F,
1668 true);
1669 }
1670
TEST_F(cmod_propagation_test,fadd_fmov_g)1671 TEST_F(cmod_propagation_test, fadd_fmov_g)
1672 {
1673 /* = Before =
1674 * 0: add(8) dest:F src0:F src1:F
1675 * 1: mov.g(8) null:F dest:F
1676 *
1677 * = After =
1678 * 0: add.g(8) dest:F src0:F src1:F
1679 */
1680 test_mov_prop(BRW_CONDITIONAL_G,
1681 BRW_REGISTER_TYPE_F,
1682 BRW_REGISTER_TYPE_F,
1683 true);
1684 }
1685
TEST_F(cmod_propagation_test,fadd_fmov_le)1686 TEST_F(cmod_propagation_test, fadd_fmov_le)
1687 {
1688 /* = Before =
1689 * 0: add(8) dest:F src0:F src1:F
1690 * 1: mov.le(8) null:F dest:F
1691 *
1692 * = After =
1693 * 0: add.le(8) dest:F src0:F src1:F
1694 */
1695 test_mov_prop(BRW_CONDITIONAL_LE,
1696 BRW_REGISTER_TYPE_F,
1697 BRW_REGISTER_TYPE_F,
1698 true);
1699 }
1700
TEST_F(cmod_propagation_test,fadd_fmov_ge)1701 TEST_F(cmod_propagation_test, fadd_fmov_ge)
1702 {
1703 /* = Before =
1704 * 0: add(8) dest:F src0:F src1:F
1705 * 1: mov.ge(8) null:F dest:F
1706 *
1707 * = After =
1708 * 0: add.ge(8) dest:F src0:F src1:F
1709 */
1710 test_mov_prop(BRW_CONDITIONAL_GE,
1711 BRW_REGISTER_TYPE_F,
1712 BRW_REGISTER_TYPE_F,
1713 true);
1714 }
1715
TEST_F(cmod_propagation_test,iadd_imov_nz)1716 TEST_F(cmod_propagation_test, iadd_imov_nz)
1717 {
1718 /* = Before =
1719 * 0: add(8) dest:D src0:D src1:D
1720 * 1: mov.nz(8) null:D dest:D
1721 *
1722 * = After =
1723 * 0: add.nz(8) dest:D src0:D src1:D
1724 */
1725 test_mov_prop(BRW_CONDITIONAL_NZ,
1726 BRW_REGISTER_TYPE_D,
1727 BRW_REGISTER_TYPE_D,
1728 true);
1729 }
1730
TEST_F(cmod_propagation_test,iadd_imov_z)1731 TEST_F(cmod_propagation_test, iadd_imov_z)
1732 {
1733 /* = Before =
1734 * 0: add(8) dest:D src0:D src1:D
1735 * 1: mov.z(8) null:D dest:D
1736 *
1737 * = After =
1738 * 0: add.z(8) dest:D src0:D src1:D
1739 */
1740 test_mov_prop(BRW_CONDITIONAL_Z,
1741 BRW_REGISTER_TYPE_D,
1742 BRW_REGISTER_TYPE_D,
1743 true);
1744 }
1745
TEST_F(cmod_propagation_test,iadd_imov_l)1746 TEST_F(cmod_propagation_test, iadd_imov_l)
1747 {
1748 /* = Before =
1749 * 0: add(8) dest:D src0:D src1:D
1750 * 1: mov.l(8) null:D dest:D
1751 *
1752 * = After =
1753 * 0: add.l(8) dest:D src0:D src1:D
1754 */
1755 test_mov_prop(BRW_CONDITIONAL_L,
1756 BRW_REGISTER_TYPE_D,
1757 BRW_REGISTER_TYPE_D,
1758 true);
1759 }
1760
TEST_F(cmod_propagation_test,iadd_imov_g)1761 TEST_F(cmod_propagation_test, iadd_imov_g)
1762 {
1763 /* = Before =
1764 * 0: add(8) dest:D src0:D src1:D
1765 * 1: mov.g(8) null:D dest:D
1766 *
1767 * = After =
1768 * 0: add.g(8) dest:D src0:D src1:D
1769 */
1770 test_mov_prop(BRW_CONDITIONAL_G,
1771 BRW_REGISTER_TYPE_D,
1772 BRW_REGISTER_TYPE_D,
1773 true);
1774 }
1775
TEST_F(cmod_propagation_test,iadd_imov_le)1776 TEST_F(cmod_propagation_test, iadd_imov_le)
1777 {
1778 /* = Before =
1779 * 0: add(8) dest:D src0:D src1:D
1780 * 1: mov.le(8) null:D dest:D
1781 *
1782 * = After =
1783 * 0: add.le(8) dest:D src0:D src1:D
1784 */
1785 test_mov_prop(BRW_CONDITIONAL_LE,
1786 BRW_REGISTER_TYPE_D,
1787 BRW_REGISTER_TYPE_D,
1788 true);
1789 }
1790
TEST_F(cmod_propagation_test,iadd_imov_ge)1791 TEST_F(cmod_propagation_test, iadd_imov_ge)
1792 {
1793 /* = Before =
1794 * 0: add(8) dest:D src0:D src1:D
1795 * 1: mov.ge(8) null:D dest:D
1796 *
1797 * = After =
1798 * 0: add.ge(8) dest:D src0:D src1:D
1799 */
1800 test_mov_prop(BRW_CONDITIONAL_GE,
1801 BRW_REGISTER_TYPE_D,
1802 BRW_REGISTER_TYPE_D,
1803 true);
1804 }
1805
TEST_F(cmod_propagation_test,iadd_umov_nz)1806 TEST_F(cmod_propagation_test, iadd_umov_nz)
1807 {
1808 /* = Before =
1809 * 0: add(8) dest:D src0:D src1:D
1810 * 1: mov.nz(8) null:UD dest:D
1811 *
1812 * = After =
1813 * 0: add.nz(8) dest:D src0:D src1:D
1814 */
1815 test_mov_prop(BRW_CONDITIONAL_NZ,
1816 BRW_REGISTER_TYPE_D,
1817 BRW_REGISTER_TYPE_UD,
1818 true);
1819 }
1820
TEST_F(cmod_propagation_test,iadd_umov_z)1821 TEST_F(cmod_propagation_test, iadd_umov_z)
1822 {
1823 /* = Before =
1824 * 0: add(8) dest:D src0:D src1:D
1825 * 1: mov.z(8) null:UD dest:D
1826 *
1827 * = After =
1828 * 0: add.z(8) dest:D src0:D src1:D
1829 */
1830 test_mov_prop(BRW_CONDITIONAL_Z,
1831 BRW_REGISTER_TYPE_D,
1832 BRW_REGISTER_TYPE_UD,
1833 true);
1834 }
1835
TEST_F(cmod_propagation_test,iadd_umov_l)1836 TEST_F(cmod_propagation_test, iadd_umov_l)
1837 {
1838 /* = Before =
1839 * 0: add(8) dest:D src0:D src1:D
1840 * 1: mov.l(8) null:UD dest:D
1841 *
1842 * = After =
1843 * No changes.
1844 *
1845 * Due to the signed-to-usigned type conversion, the conditional modifier
1846 * cannot be propagated to the ADD without changing at least the
1847 * destination type of the add.
1848 *
1849 * This particular tests is a little silly. Unsigned less than zero is a
1850 * contradiction, and earlier optimization passes should have eliminated
1851 * it.
1852 */
1853 test_mov_prop(BRW_CONDITIONAL_L,
1854 BRW_REGISTER_TYPE_D,
1855 BRW_REGISTER_TYPE_UD,
1856 false);
1857 }
1858
TEST_F(cmod_propagation_test,iadd_umov_g)1859 TEST_F(cmod_propagation_test, iadd_umov_g)
1860 {
1861 /* = Before =
1862 * 0: add(8) dest:D src0:D src1:D
1863 * 1: mov.g(8) null:UD dest:D
1864 *
1865 * = After =
1866 * No changes.
1867 *
1868 * In spite of the type conversion, this could be made to work by
1869 * propagating NZ instead of G to the ADD.
1870 */
1871 test_mov_prop(BRW_CONDITIONAL_G,
1872 BRW_REGISTER_TYPE_D,
1873 BRW_REGISTER_TYPE_UD,
1874 false);
1875 }
1876
TEST_F(cmod_propagation_test,iadd_umov_le)1877 TEST_F(cmod_propagation_test, iadd_umov_le)
1878 {
1879 /* = Before =
1880 * 0: add(8) dest:D src0:D src1:D
1881 * 1: mov.le(8) null:UD dest:D
1882 *
1883 * = After =
1884 * No changes.
1885 *
1886 * In spite of the type conversion, this could be made to work by
1887 * propagating Z instead of LE to the ADD.
1888 */
1889 test_mov_prop(BRW_CONDITIONAL_LE,
1890 BRW_REGISTER_TYPE_D,
1891 BRW_REGISTER_TYPE_UD,
1892 false);
1893 }
1894
TEST_F(cmod_propagation_test,iadd_umov_ge)1895 TEST_F(cmod_propagation_test, iadd_umov_ge)
1896 {
1897 /* = Before =
1898 * 0: add(8) dest:D src0:D src1:D
1899 * 1: mov.ge(8) null:UD dest:D
1900 *
1901 * = After =
1902 * No changes.
1903 *
1904 * Due to the signed-to-usigned type conversion, the conditional modifier
1905 * cannot be propagated to the ADD without changing at least the
1906 * destination type of the add.
1907 *
1908 * This particular tests is a little silly. Unsigned greater than or equal
1909 * to zero is a tautology, and earlier optimization passes should have
1910 * eliminated it.
1911 */
1912 test_mov_prop(BRW_CONDITIONAL_GE,
1913 BRW_REGISTER_TYPE_D,
1914 BRW_REGISTER_TYPE_UD,
1915 false);
1916 }
1917
TEST_F(cmod_propagation_test,fadd_f2u_nz)1918 TEST_F(cmod_propagation_test, fadd_f2u_nz)
1919 {
1920 /* = Before =
1921 * 0: add(8) dest:F src0:F src1:F
1922 * 1: mov.nz(8) null:UD dest:F
1923 *
1924 * = After =
1925 * No changes. The MOV changes the type from float to unsigned integer.
1926 * If dest is in the range [-Inf, 1), the conversion will clamp it to zero.
1927 * If dest is NaN, the conversion will also clamp it to zero. It is not
1928 * safe to propagate the NZ back to the ADD.
1929 *
1930 * It's tempting to try to propagate G to the ADD in place of the NZ. This
1931 * fails for values (0, 1). For example, if dest is 0.5, add.g would set
1932 * the flag, but mov.nz would not because the 0.5 would get rounded down to
1933 * zero.
1934 */
1935 test_mov_prop(BRW_CONDITIONAL_NZ,
1936 BRW_REGISTER_TYPE_F,
1937 BRW_REGISTER_TYPE_UD,
1938 false);
1939 }
1940
TEST_F(cmod_propagation_test,fadd_f2u_z)1941 TEST_F(cmod_propagation_test, fadd_f2u_z)
1942 {
1943 /* = Before =
1944 * 0: add(8) dest:F src0:F src1:F
1945 * 1: mov.z(8) null:UD dest:F
1946 *
1947 * = After =
1948 * No changes.
1949 *
1950 * The MOV changes the type from float to unsigned integer. If dest is in
1951 * the range [-Inf, 1), the conversion will clamp it to zero. If dest is
1952 * NaN, the conversion will also clamp it to zero. It is not safe to
1953 * propagate the Z back to the ADD.
1954 */
1955 test_mov_prop(BRW_CONDITIONAL_Z,
1956 BRW_REGISTER_TYPE_F,
1957 BRW_REGISTER_TYPE_UD,
1958 false);
1959 }
1960
TEST_F(cmod_propagation_test,fadd_f2u_l)1961 TEST_F(cmod_propagation_test, fadd_f2u_l)
1962 {
1963 /* = Before =
1964 * 0: add(8) dest:F src0:F src1:F
1965 * 1: mov.l(8) null:UD dest:F
1966 *
1967 * = After =
1968 * No changes.
1969 *
1970 * The MOV changes the type from float to unsigned integer. If dest is in
1971 * the range [-Inf, 1), the conversion will clamp it to zero. If dest is
1972 * NaN, the conversion will also clamp it to zero. It is not safe to
1973 * propagate the L back to the ADD.
1974 */
1975 test_mov_prop(BRW_CONDITIONAL_L,
1976 BRW_REGISTER_TYPE_F,
1977 BRW_REGISTER_TYPE_UD,
1978 false);
1979 }
1980
TEST_F(cmod_propagation_test,fadd_f2u_g)1981 TEST_F(cmod_propagation_test, fadd_f2u_g)
1982 {
1983 /* = Before =
1984 * 0: add(8) dest:F src0:F src1:F
1985 * 1: mov.g(8) null:UD dest:F
1986 *
1987 * = After =
1988 * No changes.
1989 *
1990 * The MOV changes the type from float to unsigned integer. If dest is in
1991 * the range [-Inf, 1), the conversion will clamp it to zero. If dest is
1992 * NaN, the conversion will also clamp it to zero. It is not safe to
1993 * propagate the G back to the ADD.
1994 */
1995 test_mov_prop(BRW_CONDITIONAL_G,
1996 BRW_REGISTER_TYPE_F,
1997 BRW_REGISTER_TYPE_UD,
1998 false);
1999 }
2000
TEST_F(cmod_propagation_test,fadd_f2u_le)2001 TEST_F(cmod_propagation_test, fadd_f2u_le)
2002 {
2003 /* = Before =
2004 * 0: add(8) dest:F src0:F src1:F
2005 * 1: mov.le(8) null:UD dest:F
2006 *
2007 * = After =
2008 * No changes.
2009 *
2010 * The MOV changes the type from float to unsigned integer. If dest is in
2011 * the range [-Inf, 1), the conversion will clamp it to zero. If dest is
2012 * NaN, the conversion will also clamp it to zero. It is not safe to
2013 * propagate the LE back to the ADD.
2014 */
2015 test_mov_prop(BRW_CONDITIONAL_LE,
2016 BRW_REGISTER_TYPE_F,
2017 BRW_REGISTER_TYPE_UD,
2018 false);
2019 }
2020
TEST_F(cmod_propagation_test,fadd_f2u_ge)2021 TEST_F(cmod_propagation_test, fadd_f2u_ge)
2022 {
2023 /* = Before =
2024 * 0: add(8) dest:F src0:F src1:F
2025 * 1: mov.ge(8) null:UD dest:F
2026 *
2027 * = After =
2028 * No changes.
2029 *
2030 * The MOV changes the type from float to unsigned integer. If dest is in
2031 * the range [-Inf, 1), the conversion will clamp it to zero. If dest is
2032 * NaN, the conversion will also clamp it to zero. It is not safe to
2033 * propagate the GE back to the ADD.
2034 */
2035 test_mov_prop(BRW_CONDITIONAL_GE,
2036 BRW_REGISTER_TYPE_F,
2037 BRW_REGISTER_TYPE_UD,
2038 false);
2039 }
2040
TEST_F(cmod_propagation_test,fadd_f2i_nz)2041 TEST_F(cmod_propagation_test, fadd_f2i_nz)
2042 {
2043 /* = Before =
2044 * 0: add(8) dest:F src0:F src1:F
2045 * 1: mov.nz(8) null:D dest:F
2046 *
2047 * = After =
2048 * No changes. The MOV changes the type from float to signed integer. If
2049 * dest is in the range (-1, 1), the conversion will clamp it to zero. If
2050 * dest is NaN, the conversion will also clamp it to zero. It is not safe
2051 * to propagate the NZ back to the ADD.
2052 */
2053 test_mov_prop(BRW_CONDITIONAL_NZ,
2054 BRW_REGISTER_TYPE_F,
2055 BRW_REGISTER_TYPE_D,
2056 false);
2057 }
2058
TEST_F(cmod_propagation_test,fadd_f2i_z)2059 TEST_F(cmod_propagation_test, fadd_f2i_z)
2060 {
2061 /* = Before =
2062 * 0: add(8) dest:F src0:F src1:F
2063 * 1: mov.z(8) null:D dest:F
2064 *
2065 * = After =
2066 * No changes.
2067 *
2068 * The MOV changes the type from float to signed integer. If dest is in
2069 * the range (-1, 1), the conversion will clamp it to zero. If dest is
2070 * NaN, the conversion will also clamp it to zero. It is not safe to
2071 * propagate the Z back to the ADD.
2072 */
2073 test_mov_prop(BRW_CONDITIONAL_Z,
2074 BRW_REGISTER_TYPE_F,
2075 BRW_REGISTER_TYPE_D,
2076 false);
2077 }
2078
TEST_F(cmod_propagation_test,fadd_f2i_l)2079 TEST_F(cmod_propagation_test, fadd_f2i_l)
2080 {
2081 /* = Before =
2082 * 0: add(8) dest:F src0:F src1:F
2083 * 1: mov.l(8) null:D dest:F
2084 *
2085 * = After =
2086 * No changes.
2087 *
2088 * The MOV changes the type from float to signed integer. If dest is in
2089 * the range (-1, 1), the conversion will clamp it to zero. If dest is
2090 * NaN, the conversion will also clamp it to zero. It is not safe to
2091 * propagate the L back to the ADD.
2092 */
2093 test_mov_prop(BRW_CONDITIONAL_L,
2094 BRW_REGISTER_TYPE_F,
2095 BRW_REGISTER_TYPE_D,
2096 false);
2097 }
2098
TEST_F(cmod_propagation_test,fadd_f2i_g)2099 TEST_F(cmod_propagation_test, fadd_f2i_g)
2100 {
2101 /* = Before =
2102 * 0: add(8) dest:F src0:F src1:F
2103 * 1: mov.g(8) null:D dest:F
2104 *
2105 * = After =
2106 * No changes.
2107 *
2108 * The MOV changes the type from float to signed integer. If dest is in
2109 * the range (-1, 1), the conversion will clamp it to zero. If dest is
2110 * NaN, the conversion will also clamp it to zero. It is not safe to
2111 * propagate the G back to the ADD.
2112 */
2113 test_mov_prop(BRW_CONDITIONAL_G,
2114 BRW_REGISTER_TYPE_F,
2115 BRW_REGISTER_TYPE_D,
2116 false);
2117 }
2118
TEST_F(cmod_propagation_test,fadd_f2i_le)2119 TEST_F(cmod_propagation_test, fadd_f2i_le)
2120 {
2121 /* = Before =
2122 * 0: add(8) dest:F src0:F src1:F
2123 * 1: mov.le(8) null:D dest:F
2124 *
2125 * = After =
2126 * No changes.
2127 *
2128 * The MOV changes the type from float to signed integer. If dest is in
2129 * the range (-1, 1), the conversion will clamp it to zero. If dest is
2130 * NaN, the conversion will also clamp it to zero. It is not safe to
2131 * propagate the LE back to the ADD.
2132 */
2133 test_mov_prop(BRW_CONDITIONAL_LE,
2134 BRW_REGISTER_TYPE_F,
2135 BRW_REGISTER_TYPE_D,
2136 false);
2137 }
2138
TEST_F(cmod_propagation_test,fadd_f2i_ge)2139 TEST_F(cmod_propagation_test, fadd_f2i_ge)
2140 {
2141 /* = Before =
2142 * 0: add(8) dest:F src0:F src1:F
2143 * 1: mov.ge(8) null:D dest:F
2144 *
2145 * = After =
2146 * No changes.
2147 *
2148 * The MOV changes the type from float to signed integer. If dest is in
2149 * the range (-1, 1), the conversion will clamp it to zero. If dest is
2150 * NaN, the conversion will also clamp it to zero. It is not safe to
2151 * propagate the GE back to the ADD.
2152 */
2153 test_mov_prop(BRW_CONDITIONAL_GE,
2154 BRW_REGISTER_TYPE_F,
2155 BRW_REGISTER_TYPE_D,
2156 false);
2157 }
2158
2159 void
test_saturate_prop(enum brw_conditional_mod before,enum opcode op,enum brw_reg_type add_type,enum brw_reg_type op_type,bool expected_cmod_prop_progress)2160 cmod_propagation_test::test_saturate_prop(enum brw_conditional_mod before,
2161 enum opcode op,
2162 enum brw_reg_type add_type,
2163 enum brw_reg_type op_type,
2164 bool expected_cmod_prop_progress)
2165 {
2166 const fs_builder &bld = v->bld;
2167 fs_reg dest = bld.vgrf(add_type);
2168 fs_reg src0 = bld.vgrf(add_type);
2169 fs_reg src1 = bld.vgrf(add_type);
2170 fs_reg zero(brw_imm_ud(0));
2171
2172 bld.ADD(dest, src0, src1)->saturate = true;
2173
2174 assert(op == BRW_OPCODE_CMP || op == BRW_OPCODE_MOV);
2175 if (op == BRW_OPCODE_CMP) {
2176 bld.CMP(bld.vgrf(op_type, 0),
2177 retype(dest, op_type),
2178 retype(zero, op_type),
2179 before);
2180 } else {
2181 bld.MOV(bld.vgrf(op_type, 0), retype(dest, op_type))
2182 ->conditional_mod = before;
2183 }
2184
2185 v->calculate_cfg();
2186 bblock_t *block0 = v->cfg->blocks[0];
2187
2188 EXPECT_EQ(0, block0->start_ip);
2189 EXPECT_EQ(1, block0->end_ip);
2190
2191 EXPECT_EQ(expected_cmod_prop_progress, cmod_propagation(v));
2192 EXPECT_EQ(0, block0->start_ip);
2193
2194 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2195 EXPECT_EQ(add_type, instruction(block0, 0)->dst.type);
2196 EXPECT_EQ(add_type, instruction(block0, 0)->src[0].type);
2197 EXPECT_EQ(add_type, instruction(block0, 0)->src[1].type);
2198 EXPECT_TRUE(instruction(block0, 0)->saturate);
2199
2200 if (expected_cmod_prop_progress) {
2201 EXPECT_EQ(0, block0->end_ip);
2202 EXPECT_EQ(before, instruction(block0, 0)->conditional_mod);
2203 } else {
2204 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2205
2206 /* This is ASSERT_EQ because if end_ip is 0, the instruction(block0, 1)
2207 * calls will not work properly, and the test will give weird results.
2208 */
2209 ASSERT_EQ(1, block0->end_ip);
2210 EXPECT_EQ(op, instruction(block0, 1)->opcode);
2211 EXPECT_EQ(op_type, instruction(block0, 1)->dst.type);
2212 EXPECT_EQ(op_type, instruction(block0, 1)->src[0].type);
2213 EXPECT_FALSE(instruction(block0, 1)->saturate);
2214 EXPECT_EQ(before, instruction(block0, 1)->conditional_mod);
2215 }
2216 }
2217
TEST_F(cmod_propagation_test,float_saturate_nz_cmp)2218 TEST_F(cmod_propagation_test, float_saturate_nz_cmp)
2219 {
2220 /* With the saturate modifier, the comparison happens after clamping to
2221 * [0, 1].
2222 *
2223 * = Before =
2224 *
2225 * 0: add.sat(8) dest src0 src1
2226 * 1: cmp.nz.f0(8) null dest 0.0f
2227 *
2228 * = After =
2229 * 0: add.sat.nz.f0(8) dest src0 src1
2230 */
2231 test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_CMP,
2232 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2233 true);
2234 }
2235
TEST_F(cmod_propagation_test,float_saturate_nz_mov)2236 TEST_F(cmod_propagation_test, float_saturate_nz_mov)
2237 {
2238 /* With the saturate modifier, the comparison happens after clamping to
2239 * [0, 1].
2240 *
2241 * = Before =
2242 *
2243 * 0: add.sat(8) dest src0 src1
2244 * 1: mov.nz.f0(8) null dest
2245 *
2246 * = After =
2247 * 0: add.sat.nz.f0(8) dest src0 src1
2248 */
2249 test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_MOV,
2250 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2251 true);
2252 }
2253
TEST_F(cmod_propagation_test,float_saturate_z_cmp)2254 TEST_F(cmod_propagation_test, float_saturate_z_cmp)
2255 {
2256 /* With the saturate modifier, the comparison happens after clamping to
2257 * [0, 1].
2258 *
2259 * = Before =
2260 *
2261 * 0: add.sat(8) dest src0 src1
2262 * 1: cmp.z.f0(8) null dest 0.0f
2263 *
2264 * = After =
2265 * 0: add.sat.z.f0(8) dest src0 src1
2266 */
2267 test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_CMP,
2268 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2269 true);
2270 }
2271
TEST_F(cmod_propagation_test,float_saturate_z_mov)2272 TEST_F(cmod_propagation_test, float_saturate_z_mov)
2273 {
2274 /* With the saturate modifier, the comparison happens after clamping to
2275 * [0, 1].
2276 *
2277 * = Before =
2278 *
2279 * 0: add.sat(8) dest src0 src1
2280 * 1: mov.z.f0(8) null dest
2281 *
2282 * = After =
2283 * 0: add.sat.z.f0(8) dest src0 src1
2284 */
2285 test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_MOV,
2286 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2287 true);
2288 }
2289
TEST_F(cmod_propagation_test,float_saturate_g_cmp)2290 TEST_F(cmod_propagation_test, float_saturate_g_cmp)
2291 {
2292 /* With the saturate modifier, the comparison happens after clamping to
2293 * [0, 1].
2294 *
2295 * = Before =
2296 *
2297 * 0: add.sat(8) dest src0 src1
2298 * 1: cmp.g.f0(8) null dest 0.0f
2299 *
2300 * = After =
2301 * 0: add.sat.g.f0(8) dest src0 src1
2302 */
2303 test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_CMP,
2304 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2305 true);
2306 }
2307
TEST_F(cmod_propagation_test,float_saturate_g_mov)2308 TEST_F(cmod_propagation_test, float_saturate_g_mov)
2309 {
2310 /* With the saturate modifier, the comparison happens after clamping to
2311 * [0, 1].
2312 *
2313 * = Before =
2314 *
2315 * 0: add.sat(8) dest src0 src1
2316 * 1: mov.g.f0(8) null dest
2317 *
2318 * = After =
2319 * 0: add.sat.g.f0(8) dest src0 src1
2320 */
2321 test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_MOV,
2322 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2323 true);
2324 }
2325
TEST_F(cmod_propagation_test,float_saturate_le_cmp)2326 TEST_F(cmod_propagation_test, float_saturate_le_cmp)
2327 {
2328 /* With the saturate modifier, the comparison happens after clamping to
2329 * [0, 1].
2330 *
2331 * = Before =
2332 *
2333 * 0: add.sat(8) dest src0 src1
2334 * 1: cmp.le.f0(8) null dest 0.0f
2335 *
2336 * = After =
2337 * 0: add.sat.le.f0(8) dest src0 src1
2338 */
2339 test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_CMP,
2340 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2341 true);
2342 }
2343
TEST_F(cmod_propagation_test,float_saturate_le_mov)2344 TEST_F(cmod_propagation_test, float_saturate_le_mov)
2345 {
2346 /* With the saturate modifier, the comparison happens after clamping to
2347 * [0, 1]. (sat(x) <= 0) == (x <= 0).
2348 *
2349 * = Before =
2350 *
2351 * 0: add.sat(8) dest src0 src1
2352 * 1: mov.le.f0(8) null dest
2353 *
2354 * = After =
2355 * 0: add.sat.le.f0(8) dest src0 src1
2356 */
2357 test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_MOV,
2358 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2359 true);
2360 }
2361
TEST_F(cmod_propagation_test,float_saturate_l_cmp)2362 TEST_F(cmod_propagation_test, float_saturate_l_cmp)
2363 {
2364 /* With the saturate modifier, the comparison happens after clamping to
2365 * [0, 1].
2366 *
2367 * = Before =
2368 *
2369 * 0: add.sat(8) dest src0 src1
2370 * 1: cmp.l.f0(8) null dest 0.0f
2371 *
2372 * = After =
2373 * 0: add.sat.l.f0(8) dest src0 src1
2374 */
2375 test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_CMP,
2376 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2377 true);
2378 }
2379
TEST_F(cmod_propagation_test,float_saturate_l_mov)2380 TEST_F(cmod_propagation_test, float_saturate_l_mov)
2381 {
2382 /* With the saturate modifier, the comparison happens after clamping to
2383 * [0, 1].
2384 *
2385 * = Before =
2386 *
2387 * 0: add.sat(8) dest src0 src1
2388 * 1: mov.l.f0(8) null dest
2389 *
2390 * = After =
2391 * 0: add.sat.l.f0(8) dest src0 src1
2392 */
2393 test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_MOV,
2394 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2395 true);
2396 }
2397
TEST_F(cmod_propagation_test,float_saturate_ge_cmp)2398 TEST_F(cmod_propagation_test, float_saturate_ge_cmp)
2399 {
2400 /* With the saturate modifier, the comparison happens after clamping to
2401 * [0, 1].
2402 *
2403 * = Before =
2404 *
2405 * 0: add.sat(8) dest src0 src1
2406 * 1: cmp.ge.f0(8) null dest 0.0f
2407 *
2408 * = After =
2409 * 0: add.sat.ge.f0(8) dest src0 src1
2410 */
2411 test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_CMP,
2412 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2413 true);
2414 }
2415
TEST_F(cmod_propagation_test,float_saturate_ge_mov)2416 TEST_F(cmod_propagation_test, float_saturate_ge_mov)
2417 {
2418 /* With the saturate modifier, the comparison happens before clamping to
2419 * [0, 1].
2420 *
2421 * = Before =
2422 *
2423 * 0: add.sat(8) dest src0 src1
2424 * 1: mov.ge.f0(8) null dest
2425 *
2426 * = After =
2427 * 0: add.sat.ge.f0(8) dest src0 src1
2428 */
2429 test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_MOV,
2430 BRW_REGISTER_TYPE_F, BRW_REGISTER_TYPE_F,
2431 true);
2432 }
2433
TEST_F(cmod_propagation_test,int_saturate_nz_cmp)2434 TEST_F(cmod_propagation_test, int_saturate_nz_cmp)
2435 {
2436 /* = Before =
2437 *
2438 * 0: add.sat(8) dest src0 src1
2439 * 1: cmp.nz.f0(8) null dest 0
2440 *
2441 * = After =
2442 * 0: add.sat.nz.f0(8) dest src0 src1
2443 */
2444 test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_CMP,
2445 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2446 true);
2447 }
2448
TEST_F(cmod_propagation_test,uint_saturate_nz_cmp)2449 TEST_F(cmod_propagation_test, uint_saturate_nz_cmp)
2450 {
2451 /* = Before =
2452 *
2453 * 0: add.sat(8) dest:UD src0:UD src1:UD
2454 * 1: cmp.nz.f0(8) null:D dest:D 0
2455 *
2456 * = After =
2457 * 0: add.sat.nz.f0(8) dest:UD src0:UD src1:UD
2458 */
2459 test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_CMP,
2460 BRW_REGISTER_TYPE_UD, BRW_REGISTER_TYPE_D,
2461 true);
2462 }
2463
TEST_F(cmod_propagation_test,int_saturate_nz_mov)2464 TEST_F(cmod_propagation_test, int_saturate_nz_mov)
2465 {
2466 /* = Before =
2467 *
2468 * 0: add.sat(8) dest src0 src1
2469 * 1: mov.nz.f0(8) null dest
2470 *
2471 * = After =
2472 * 0: add.sat.nz.f0(8) dest src0 src1
2473 */
2474 test_saturate_prop(BRW_CONDITIONAL_NZ, BRW_OPCODE_MOV,
2475 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2476 true);
2477 }
2478
TEST_F(cmod_propagation_test,int_saturate_z_cmp)2479 TEST_F(cmod_propagation_test, int_saturate_z_cmp)
2480 {
2481 /* = Before =
2482 *
2483 * 0: add.sat(8) dest src0 src1
2484 * 1: cmp.z.f0(8) null dest 0
2485 *
2486 * = After =
2487 * 0: add.sat.z.f0(8) dest src0 src1
2488 */
2489 test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_CMP,
2490 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2491 true);
2492 }
2493
TEST_F(cmod_propagation_test,uint_saturate_z_cmp)2494 TEST_F(cmod_propagation_test, uint_saturate_z_cmp)
2495 {
2496 /* = Before =
2497 *
2498 * 0: add.sat(8) dest:UD src0:UD src1:UD
2499 * 1: cmp.z.f0(8) null:D dest:D 0
2500 *
2501 * = After =
2502 * 0: add.sat.z.f0(8) dest:UD src0:UD src1:UD
2503 */
2504 test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_CMP,
2505 BRW_REGISTER_TYPE_UD, BRW_REGISTER_TYPE_D,
2506 true);
2507 }
2508
TEST_F(cmod_propagation_test,int_saturate_z_mov)2509 TEST_F(cmod_propagation_test, int_saturate_z_mov)
2510 {
2511 /* With the saturate modifier, the comparison happens before clamping to
2512 * [0, 1]. (sat(x) == 0) == (x <= 0).
2513 *
2514 * = Before =
2515 *
2516 * 0: add.sat(8) dest src0 src1
2517 * 1: mov.z.f0(8) null dest
2518 *
2519 * = After =
2520 * 0: add.sat.z.f0(8) dest src0 src1
2521 */
2522 test_saturate_prop(BRW_CONDITIONAL_Z, BRW_OPCODE_MOV,
2523 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2524 true);
2525 }
2526
TEST_F(cmod_propagation_test,int_saturate_g_cmp)2527 TEST_F(cmod_propagation_test, int_saturate_g_cmp)
2528 {
2529 /* = Before =
2530 *
2531 * 0: add.sat(8) dest src0 src1
2532 * 1: cmp.g.f0(8) null dest 0
2533 *
2534 * = After =
2535 * 0: add.sat.g.f0(8) dest src0 src1
2536 */
2537 test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_CMP,
2538 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2539 true);
2540 }
2541
TEST_F(cmod_propagation_test,int_saturate_g_mov)2542 TEST_F(cmod_propagation_test, int_saturate_g_mov)
2543 {
2544 /* = Before =
2545 *
2546 * 0: add.sat(8) dest src0 src1
2547 * 1: mov.g.f0(8) null dest
2548 *
2549 * = After =
2550 * 0: add.sat.g.f0(8) dest src0 src1
2551 */
2552 test_saturate_prop(BRW_CONDITIONAL_G, BRW_OPCODE_MOV,
2553 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2554 true);
2555 }
2556
TEST_F(cmod_propagation_test,int_saturate_le_cmp)2557 TEST_F(cmod_propagation_test, int_saturate_le_cmp)
2558 {
2559 /* = Before =
2560 *
2561 * 0: add.sat(8) dest src0 src1
2562 * 1: cmp.le.f0(8) null dest 0
2563 *
2564 * = After =
2565 * 0: add.sat.le.f0(8) dest src0 src1
2566 */
2567 test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_CMP,
2568 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2569 true);
2570 }
2571
TEST_F(cmod_propagation_test,int_saturate_le_mov)2572 TEST_F(cmod_propagation_test, int_saturate_le_mov)
2573 {
2574 /* = Before =
2575 *
2576 * 0: add.sat(8) dest src0 src1
2577 * 1: mov.le.f0(8) null dest
2578 *
2579 * = After =
2580 * 0: add.sat.le.f0(8) dest src0 src1
2581 */
2582 test_saturate_prop(BRW_CONDITIONAL_LE, BRW_OPCODE_MOV,
2583 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2584 true);
2585 }
2586
TEST_F(cmod_propagation_test,int_saturate_l_cmp)2587 TEST_F(cmod_propagation_test, int_saturate_l_cmp)
2588 {
2589 /* = Before =
2590 *
2591 * 0: add.sat(8) dest src0 src1
2592 * 1: cmp.l.f0(8) null dest 0
2593 *
2594 * = After =
2595 * 0: add.sat.l.f0(8) dest src0 src1
2596 */
2597 test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_CMP,
2598 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2599 true);
2600 }
2601
TEST_F(cmod_propagation_test,int_saturate_l_mov)2602 TEST_F(cmod_propagation_test, int_saturate_l_mov)
2603 {
2604 /* = Before =
2605 *
2606 * 0: add.sat(8) dest src0 src1
2607 * 1: mov.l.f0(8) null dest 0
2608 *
2609 * = After =
2610 * 0: add.sat.l.f0(8) dest src0 src1
2611 */
2612 test_saturate_prop(BRW_CONDITIONAL_L, BRW_OPCODE_MOV,
2613 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2614 true);
2615 }
2616
TEST_F(cmod_propagation_test,int_saturate_ge_cmp)2617 TEST_F(cmod_propagation_test, int_saturate_ge_cmp)
2618 {
2619 /* = Before =
2620 *
2621 * 0: add.sat(8) dest src0 src1
2622 * 1: cmp.ge.f0(8) null dest 0
2623 *
2624 * = After =
2625 * 0: add.sat.ge.f0(8) dest src0 src1
2626 */
2627 test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_CMP,
2628 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2629 true);
2630 }
2631
TEST_F(cmod_propagation_test,int_saturate_ge_mov)2632 TEST_F(cmod_propagation_test, int_saturate_ge_mov)
2633 {
2634 /* = Before =
2635 *
2636 * 0: add.sat(8) dest src0 src1
2637 * 1: mov.ge.f0(8) null dest
2638 *
2639 * = After =
2640 * 0: add.sat.ge.f0(8) dest src0 src1
2641 */
2642 test_saturate_prop(BRW_CONDITIONAL_GE, BRW_OPCODE_MOV,
2643 BRW_REGISTER_TYPE_D, BRW_REGISTER_TYPE_D,
2644 true);
2645 }
2646
TEST_F(cmod_propagation_test,not_to_or)2647 TEST_F(cmod_propagation_test, not_to_or)
2648 {
2649 /* Exercise propagation of conditional modifier from a NOT instruction to
2650 * another ALU instruction as performed by cmod_propagate_not.
2651 */
2652 const fs_builder &bld = v->bld;
2653 fs_reg dest = v->vgrf(glsl_type::uint_type);
2654 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2655 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2656 bld.OR(dest, src0, src1);
2657 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
2658
2659 /* = Before =
2660 *
2661 * 0: or(8) dest src0 src1
2662 * 1: not.nz.f0(8) null dest
2663 *
2664 * = After =
2665 * 0: or.z.f0(8) dest src0 src1
2666 */
2667
2668 v->calculate_cfg();
2669 bblock_t *block0 = v->cfg->blocks[0];
2670
2671 EXPECT_EQ(0, block0->start_ip);
2672 EXPECT_EQ(1, block0->end_ip);
2673
2674 EXPECT_TRUE(cmod_propagation(v));
2675 EXPECT_EQ(0, block0->start_ip);
2676 EXPECT_EQ(0, block0->end_ip);
2677 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2678 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2679 }
2680
TEST_F(cmod_propagation_test,not_to_and)2681 TEST_F(cmod_propagation_test, not_to_and)
2682 {
2683 /* Exercise propagation of conditional modifier from a NOT instruction to
2684 * another ALU instruction as performed by cmod_propagate_not.
2685 */
2686 const fs_builder &bld = v->bld;
2687 fs_reg dest = v->vgrf(glsl_type::uint_type);
2688 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2689 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2690 bld.AND(dest, src0, src1);
2691 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
2692
2693 /* = Before =
2694 *
2695 * 0: and(8) dest src0 src1
2696 * 1: not.nz.f0(8) null dest
2697 *
2698 * = After =
2699 * 0: and.z.f0(8) dest src0 src1
2700 */
2701
2702 v->calculate_cfg();
2703 bblock_t *block0 = v->cfg->blocks[0];
2704
2705 EXPECT_EQ(0, block0->start_ip);
2706 EXPECT_EQ(1, block0->end_ip);
2707
2708 EXPECT_TRUE(cmod_propagation(v));
2709 EXPECT_EQ(0, block0->start_ip);
2710 EXPECT_EQ(0, block0->end_ip);
2711 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 0)->opcode);
2712 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2713 }
2714
TEST_F(cmod_propagation_test,not_to_uadd)2715 TEST_F(cmod_propagation_test, not_to_uadd)
2716 {
2717 /* Exercise propagation of conditional modifier from a NOT instruction to
2718 * another ALU instruction as performed by cmod_propagate_not.
2719 *
2720 * The optimization pass currently restricts to just OR and AND. It's
2721 * possible that this is too restrictive, and the actual, necessary
2722 * restriction is just the the destination type of the ALU instruction is
2723 * the same as the source type of the NOT instruction.
2724 */
2725 const fs_builder &bld = v->bld;
2726 fs_reg dest = v->vgrf(glsl_type::uint_type);
2727 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2728 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2729 bld.ADD(dest, src0, src1);
2730 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
2731
2732 /* = Before =
2733 *
2734 * 0: add(8) dest src0 src1
2735 * 1: not.nz.f0(8) null dest
2736 *
2737 * = After =
2738 * No changes
2739 */
2740
2741 v->calculate_cfg();
2742 bblock_t *block0 = v->cfg->blocks[0];
2743
2744 EXPECT_EQ(0, block0->start_ip);
2745 EXPECT_EQ(1, block0->end_ip);
2746
2747 EXPECT_FALSE(cmod_propagation(v));
2748 EXPECT_EQ(0, block0->start_ip);
2749 EXPECT_EQ(1, block0->end_ip);
2750 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2751 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2752 EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 1)->opcode);
2753 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
2754 }
2755
TEST_F(cmod_propagation_test,not_to_fadd_to_ud)2756 TEST_F(cmod_propagation_test, not_to_fadd_to_ud)
2757 {
2758 /* Exercise propagation of conditional modifier from a NOT instruction to
2759 * another ALU instruction as performed by cmod_propagate_not.
2760 *
2761 * The optimization pass currently restricts to just OR and AND. It's
2762 * possible that this is too restrictive, and the actual, necessary
2763 * restriction is just the the destination type of the ALU instruction is
2764 * the same as the source type of the NOT instruction.
2765 */
2766 const fs_builder &bld = v->bld;
2767 fs_reg dest = v->vgrf(glsl_type::uint_type);
2768 fs_reg src0 = v->vgrf(glsl_type::float_type);
2769 fs_reg src1 = v->vgrf(glsl_type::float_type);
2770 bld.ADD(dest, src0, src1);
2771 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest));
2772
2773 /* = Before =
2774 *
2775 * 0: add(8) dest.ud src0.f src1.f
2776 * 1: not.nz.f0(8) null dest.ud
2777 *
2778 * = After =
2779 * No changes
2780 */
2781
2782 v->calculate_cfg();
2783 bblock_t *block0 = v->cfg->blocks[0];
2784
2785 EXPECT_EQ(0, block0->start_ip);
2786 EXPECT_EQ(1, block0->end_ip);
2787
2788 EXPECT_FALSE(cmod_propagation(v));
2789 EXPECT_EQ(0, block0->start_ip);
2790 EXPECT_EQ(1, block0->end_ip);
2791 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2792 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2793 EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 1)->opcode);
2794 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
2795 }
2796
TEST_F(cmod_propagation_test,not_to_fadd)2797 TEST_F(cmod_propagation_test, not_to_fadd)
2798 {
2799 /* Exercise propagation of conditional modifier from a NOT instruction to
2800 * another ALU instruction as performed by cmod_propagate_not.
2801 *
2802 * The optimization pass currently restricts to just OR and AND. It's
2803 * possible that this is too restrictive, and the actual, necessary
2804 * restriction is just the the destination type of the ALU instruction is
2805 * the same as the source type of the NOT instruction.
2806 */
2807 const fs_builder &bld = v->bld;
2808 fs_reg dest = v->vgrf(glsl_type::float_type);
2809 fs_reg src0 = v->vgrf(glsl_type::float_type);
2810 fs_reg src1 = v->vgrf(glsl_type::float_type);
2811 bld.ADD(dest, src0, src1);
2812 set_condmod(BRW_CONDITIONAL_NZ,
2813 bld.NOT(bld.null_reg_ud(),
2814 retype(dest, BRW_REGISTER_TYPE_UD)));
2815
2816 /* = Before =
2817 *
2818 * 0: add(8) dest.f src0.f src1.f
2819 * 1: not.nz.f0(8) null dest.ud
2820 *
2821 * = After =
2822 * No changes
2823 */
2824
2825 v->calculate_cfg();
2826 bblock_t *block0 = v->cfg->blocks[0];
2827
2828 EXPECT_EQ(0, block0->start_ip);
2829 EXPECT_EQ(1, block0->end_ip);
2830
2831 EXPECT_FALSE(cmod_propagation(v));
2832 EXPECT_EQ(0, block0->start_ip);
2833 EXPECT_EQ(1, block0->end_ip);
2834 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
2835 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
2836 EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 1)->opcode);
2837 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod);
2838 }
2839
TEST_F(cmod_propagation_test,not_to_or_intervening_flag_read_compatible_value)2840 TEST_F(cmod_propagation_test, not_to_or_intervening_flag_read_compatible_value)
2841 {
2842 /* Exercise propagation of conditional modifier from a NOT instruction to
2843 * another ALU instruction as performed by cmod_propagate_not.
2844 */
2845 const fs_builder &bld = v->bld;
2846 fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2847 fs_reg dest1 = v->vgrf(glsl_type::float_type);
2848 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2849 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2850 fs_reg src2 = v->vgrf(glsl_type::float_type);
2851 fs_reg zero(brw_imm_f(0.0f));
2852 set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest0, src0, src1));
2853 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
2854 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2855
2856 /* = Before =
2857 *
2858 * 0: or.z.f0(8) dest0 src0 src1
2859 * 1: (+f0) sel(8) dest1 src2 0.0f
2860 * 2: not.nz.f0(8) null dest0
2861 *
2862 * = After =
2863 * 0: or.z.f0(8) dest0 src0 src1
2864 * 1: (+f0) sel(8) dest1 src2 0.0f
2865 */
2866
2867 v->calculate_cfg();
2868 bblock_t *block0 = v->cfg->blocks[0];
2869
2870 EXPECT_EQ(0, block0->start_ip);
2871 EXPECT_EQ(2, block0->end_ip);
2872
2873 EXPECT_TRUE(cmod_propagation(v));
2874 EXPECT_EQ(0, block0->start_ip);
2875 EXPECT_EQ(1, block0->end_ip);
2876 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2877 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2878 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
2879 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
2880 }
2881
TEST_F(cmod_propagation_test,not_to_or_intervening_flag_read_compatible_value_mismatch_flag)2882 TEST_F(cmod_propagation_test,
2883 not_to_or_intervening_flag_read_compatible_value_mismatch_flag)
2884 {
2885 /* Exercise propagation of conditional modifier from a NOT instruction to
2886 * another ALU instruction as performed by cmod_propagate_not.
2887 */
2888 const fs_builder &bld = v->bld;
2889 fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2890 fs_reg dest1 = v->vgrf(glsl_type::float_type);
2891 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2892 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2893 fs_reg src2 = v->vgrf(glsl_type::float_type);
2894 fs_reg zero(brw_imm_f(0.0f));
2895 set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest0, src0, src1))
2896 ->flag_subreg = 1;
2897 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
2898 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2899
2900 /* = Before =
2901 *
2902 * 0: or.z.f0.1(8) dest0 src0 src1
2903 * 1: (+f0) sel(8) dest1 src2 0.0f
2904 * 2: not.nz.f0(8) null dest0
2905 *
2906 * = After =
2907 * No changes
2908 */
2909
2910 v->calculate_cfg();
2911 bblock_t *block0 = v->cfg->blocks[0];
2912
2913 EXPECT_EQ(0, block0->start_ip);
2914 EXPECT_EQ(2, block0->end_ip);
2915
2916 EXPECT_FALSE(cmod_propagation(v));
2917 EXPECT_EQ(0, block0->start_ip);
2918 EXPECT_EQ(2, block0->end_ip);
2919 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2920 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
2921 EXPECT_EQ(1, instruction(block0, 0)->flag_subreg);
2922 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
2923 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
2924 EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 2)->opcode);
2925 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 2)->conditional_mod);
2926 EXPECT_EQ(0, instruction(block0, 2)->flag_subreg);
2927 }
2928
TEST_F(cmod_propagation_test,not_to_or_intervening_flag_read_incompatible_value)2929 TEST_F(cmod_propagation_test, not_to_or_intervening_flag_read_incompatible_value)
2930 {
2931 /* Exercise propagation of conditional modifier from a NOT instruction to
2932 * another ALU instruction as performed by cmod_propagate_not.
2933 */
2934 const fs_builder &bld = v->bld;
2935 fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2936 fs_reg dest1 = v->vgrf(glsl_type::float_type);
2937 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2938 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2939 fs_reg src2 = v->vgrf(glsl_type::float_type);
2940 fs_reg zero(brw_imm_f(0.0f));
2941 set_condmod(BRW_CONDITIONAL_NZ, bld.OR(dest0, src0, src1));
2942 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero));
2943 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2944
2945 /* = Before =
2946 *
2947 * 0: or.nz.f0(8) dest0 src0 src1
2948 * 1: (+f0) sel(8) dest1 src2 0.0f
2949 * 2: not.nz.f0(8) null dest0
2950 *
2951 * = After =
2952 * No changes
2953 */
2954
2955 v->calculate_cfg();
2956 bblock_t *block0 = v->cfg->blocks[0];
2957
2958 EXPECT_EQ(0, block0->start_ip);
2959 EXPECT_EQ(2, block0->end_ip);
2960
2961 EXPECT_FALSE(cmod_propagation(v));
2962 EXPECT_EQ(0, block0->start_ip);
2963 EXPECT_EQ(2, block0->end_ip);
2964 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
2965 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod);
2966 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
2967 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
2968 EXPECT_EQ(BRW_OPCODE_NOT, instruction(block0, 2)->opcode);
2969 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 2)->conditional_mod);
2970 }
2971
TEST_F(cmod_propagation_test,not_to_or_intervening_mismatch_flag_write)2972 TEST_F(cmod_propagation_test, not_to_or_intervening_mismatch_flag_write)
2973 {
2974 /* Exercise propagation of conditional modifier from a NOT instruction to
2975 * another ALU instruction as performed by cmod_propagate_not.
2976 */
2977 const fs_builder &bld = v->bld;
2978 fs_reg dest0 = v->vgrf(glsl_type::uint_type);
2979 fs_reg dest1 = v->vgrf(glsl_type::uint_type);
2980 fs_reg src0 = v->vgrf(glsl_type::uint_type);
2981 fs_reg src1 = v->vgrf(glsl_type::uint_type);
2982
2983 bld.OR(dest0, src0, src1);
2984 set_condmod(BRW_CONDITIONAL_Z, bld.OR(dest1, src0, src1))
2985 ->flag_subreg = 1;
2986 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
2987
2988 /* = Before =
2989 *
2990 * 0: or(8) dest0 src0 src1
2991 * 1: or.z.f0.1(8) dest1 src0 src1
2992 * 2: not.nz.f0(8) null dest0
2993 *
2994 * = After =
2995 * 0: or.z.f0(8) dest0 src0 src1
2996 * 1: or.z.f0.1(8) dest1 src0 src1
2997 */
2998
2999 v->calculate_cfg();
3000 bblock_t *block0 = v->cfg->blocks[0];
3001
3002 EXPECT_EQ(0, block0->start_ip);
3003 EXPECT_EQ(2, block0->end_ip);
3004
3005 EXPECT_TRUE(cmod_propagation(v));
3006 EXPECT_EQ(0, block0->start_ip);
3007 EXPECT_EQ(1, block0->end_ip);
3008 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
3009 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
3010 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
3011 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 1)->opcode);
3012 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 1)->conditional_mod);
3013 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
3014 }
3015
TEST_F(cmod_propagation_test,not_to_or_intervening_mismatch_flag_read)3016 TEST_F(cmod_propagation_test, not_to_or_intervening_mismatch_flag_read)
3017 {
3018 /* Exercise propagation of conditional modifier from a NOT instruction to
3019 * another ALU instruction as performed by cmod_propagate_not.
3020 */
3021 const fs_builder &bld = v->bld;
3022 fs_reg dest0 = v->vgrf(glsl_type::uint_type);
3023 fs_reg dest1 = v->vgrf(glsl_type::float_type);
3024 fs_reg src0 = v->vgrf(glsl_type::uint_type);
3025 fs_reg src1 = v->vgrf(glsl_type::uint_type);
3026 fs_reg src2 = v->vgrf(glsl_type::float_type);
3027 fs_reg zero(brw_imm_f(0.0f));
3028
3029 bld.OR(dest0, src0, src1);
3030 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero))
3031 ->flag_subreg = 1;
3032 set_condmod(BRW_CONDITIONAL_NZ, bld.NOT(bld.null_reg_ud(), dest0));
3033
3034 /* = Before =
3035 *
3036 * 0: or(8) dest0 src0 src1
3037 * 1: (+f0.1) sel(8) dest1 src2 0.0f
3038 * 2: not.nz.f0(8) null dest0
3039 *
3040 * = After =
3041 * 0: or.z.f0(8) dest0 src0 src1
3042 * 1: (+f0.1) sel(8) dest1 src2 0.0f
3043 */
3044
3045 v->calculate_cfg();
3046 bblock_t *block0 = v->cfg->blocks[0];
3047
3048 EXPECT_EQ(0, block0->start_ip);
3049 EXPECT_EQ(2, block0->end_ip);
3050
3051 EXPECT_TRUE(cmod_propagation(v));
3052 EXPECT_EQ(0, block0->start_ip);
3053 EXPECT_EQ(1, block0->end_ip);
3054 EXPECT_EQ(BRW_OPCODE_OR, instruction(block0, 0)->opcode);
3055 EXPECT_EQ(BRW_CONDITIONAL_Z, instruction(block0, 0)->conditional_mod);
3056 EXPECT_EQ(0, instruction(block0, 0)->flag_subreg);
3057 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
3058 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate);
3059 EXPECT_EQ(1, instruction(block0, 1)->flag_subreg);
3060 }
3061
TEST_F(cmod_propagation_test,cmp_to_add_float_e)3062 TEST_F(cmod_propagation_test, cmp_to_add_float_e)
3063 {
3064 const fs_builder &bld = v->bld;
3065 fs_reg dest = v->vgrf(glsl_type::float_type);
3066 fs_reg src0 = v->vgrf(glsl_type::float_type);
3067 fs_reg neg10(brw_imm_f(-10.0f));
3068 fs_reg pos10(brw_imm_f(10.0f));
3069
3070 bld.ADD(dest, src0, neg10)->saturate = true;
3071 bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_EQ);
3072
3073 /* = Before =
3074 * 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
3075 * 1: cmp.z.f0.0(8) null:F, vgrf1:F, 10f
3076 *
3077 * = After =
3078 * (no changes)
3079 */
3080
3081 v->calculate_cfg();
3082 bblock_t *block0 = v->cfg->blocks[0];
3083
3084 EXPECT_FALSE(cmod_propagation(v));
3085 EXPECT_EQ(0, block0->start_ip);
3086 EXPECT_EQ(1, block0->end_ip);
3087 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
3088 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
3089 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
3090 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod);
3091 }
3092
TEST_F(cmod_propagation_test,cmp_to_add_float_g)3093 TEST_F(cmod_propagation_test, cmp_to_add_float_g)
3094 {
3095 const fs_builder &bld = v->bld;
3096 fs_reg dest = v->vgrf(glsl_type::float_type);
3097 fs_reg src0 = v->vgrf(glsl_type::float_type);
3098 fs_reg neg10(brw_imm_f(-10.0f));
3099 fs_reg pos10(brw_imm_f(10.0f));
3100
3101 bld.ADD(dest, src0, neg10)->saturate = true;
3102 bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_G);
3103
3104 /* = Before =
3105 * 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
3106 * 1: cmp.g.f0.0(8) null:F, vgrf1:F, 10f
3107 *
3108 * = After =
3109 * 0: add.sat.g.f0.0(8) vgrf0:F, vgrf1:F, -10f
3110 */
3111
3112 v->calculate_cfg();
3113 bblock_t *block0 = v->cfg->blocks[0];
3114
3115 EXPECT_TRUE(cmod_propagation(v));
3116 EXPECT_EQ(0, block0->start_ip);
3117 EXPECT_EQ(0, block0->end_ip);
3118 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
3119 EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod);
3120 }
3121
TEST_F(cmod_propagation_test,cmp_to_add_float_le)3122 TEST_F(cmod_propagation_test, cmp_to_add_float_le)
3123 {
3124 const fs_builder &bld = v->bld;
3125 fs_reg dest = v->vgrf(glsl_type::float_type);
3126 fs_reg src0 = v->vgrf(glsl_type::float_type);
3127 fs_reg neg10(brw_imm_f(-10.0f));
3128 fs_reg pos10(brw_imm_f(10.0f));
3129
3130 bld.ADD(dest, src0, neg10)->saturate = true;
3131 bld.CMP(bld.null_reg_f(), src0, pos10, BRW_CONDITIONAL_LE);
3132
3133 /* = Before =
3134 * 0: add.sat(8) vgrf0:F, vgrf1:F, -10f
3135 * 1: cmp.le.f0.0(8) null:F, vgrf1:F, 10f
3136 *
3137 * = After =
3138 * 0: add.sat.le.f0.0(8) vgrf0:F, vgrf1:F, -10f
3139 */
3140
3141 v->calculate_cfg();
3142 bblock_t *block0 = v->cfg->blocks[0];
3143
3144 EXPECT_TRUE(cmod_propagation(v));
3145 EXPECT_EQ(0, block0->start_ip);
3146 EXPECT_EQ(0, block0->end_ip);
3147 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
3148 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod);
3149 }
3150
TEST_F(cmod_propagation_test,prop_across_sel_gfx7)3151 TEST_F(cmod_propagation_test, prop_across_sel_gfx7)
3152 {
3153 const fs_builder &bld = v->bld;
3154 fs_reg dest1 = v->vgrf(glsl_type::float_type);
3155 fs_reg dest2 = v->vgrf(glsl_type::float_type);
3156 fs_reg src0 = v->vgrf(glsl_type::float_type);
3157 fs_reg src1 = v->vgrf(glsl_type::float_type);
3158 fs_reg src2 = v->vgrf(glsl_type::float_type);
3159 fs_reg src3 = v->vgrf(glsl_type::float_type);
3160 fs_reg zero(brw_imm_f(0.0f));
3161 bld.ADD(dest1, src0, src1);
3162 bld.emit_minmax(dest2, src2, src3, BRW_CONDITIONAL_GE);
3163 bld.CMP(bld.null_reg_f(), dest1, zero, BRW_CONDITIONAL_GE);
3164
3165 /* = Before =
3166 *
3167 * 0: add(8) dest1 src0 src1
3168 * 1: sel.ge(8) dest2 src2 src3
3169 * 2: cmp.ge.f0(8) null dest1 0.0f
3170 *
3171 * = After =
3172 * 0: add.ge.f0(8) dest1 src0 src1
3173 * 1: sel.ge(8) dest2 src2 src3
3174 */
3175
3176 v->calculate_cfg();
3177 bblock_t *block0 = v->cfg->blocks[0];
3178
3179 EXPECT_EQ(0, block0->start_ip);
3180 EXPECT_EQ(2, block0->end_ip);
3181
3182 EXPECT_TRUE(cmod_propagation(v));
3183 EXPECT_EQ(0, block0->start_ip);
3184 EXPECT_EQ(1, block0->end_ip);
3185 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
3186 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
3187 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
3188 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
3189 }
3190
TEST_F(cmod_propagation_test,prop_across_sel_gfx5)3191 TEST_F(cmod_propagation_test, prop_across_sel_gfx5)
3192 {
3193 devinfo->ver = 5;
3194 devinfo->verx10 = devinfo->ver * 10;
3195
3196 const fs_builder &bld = v->bld;
3197 fs_reg dest1 = v->vgrf(glsl_type::float_type);
3198 fs_reg dest2 = v->vgrf(glsl_type::float_type);
3199 fs_reg src0 = v->vgrf(glsl_type::float_type);
3200 fs_reg src1 = v->vgrf(glsl_type::float_type);
3201 fs_reg src2 = v->vgrf(glsl_type::float_type);
3202 fs_reg src3 = v->vgrf(glsl_type::float_type);
3203 fs_reg zero(brw_imm_f(0.0f));
3204 bld.ADD(dest1, src0, src1);
3205 bld.emit_minmax(dest2, src2, src3, BRW_CONDITIONAL_GE);
3206 bld.CMP(bld.null_reg_f(), dest1, zero, BRW_CONDITIONAL_GE);
3207
3208 /* = Before =
3209 *
3210 * 0: add(8) dest1 src0 src1
3211 * 1: sel.ge(8) dest2 src2 src3
3212 * 2: cmp.ge.f0(8) null dest1 0.0f
3213 *
3214 * = After =
3215 * (no changes)
3216 *
3217 * On Gfx4 and Gfx5, sel.l (for min) and sel.ge (for max) are implemented
3218 * using a separate cmpn and sel instruction. This lowering occurs in
3219 * fs_vistor::lower_minmax which is called a long time after the first
3220 * calls to cmod_propagation.
3221 */
3222
3223 v->calculate_cfg();
3224 bblock_t *block0 = v->cfg->blocks[0];
3225
3226 EXPECT_EQ(0, block0->start_ip);
3227 EXPECT_EQ(2, block0->end_ip);
3228
3229 EXPECT_FALSE(cmod_propagation(v));
3230 EXPECT_EQ(0, block0->start_ip);
3231 EXPECT_EQ(2, block0->end_ip);
3232 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode);
3233 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod);
3234 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode);
3235 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
3236 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode);
3237 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod);
3238 }
3239
TEST_F(cmod_propagation_test,prop_into_sel_gfx5)3240 TEST_F(cmod_propagation_test, prop_into_sel_gfx5)
3241 {
3242 devinfo->ver = 5;
3243 devinfo->verx10 = devinfo->ver * 10;
3244
3245 const fs_builder &bld = v->bld;
3246 fs_reg dest = v->vgrf(glsl_type::float_type);
3247 fs_reg src0 = v->vgrf(glsl_type::float_type);
3248 fs_reg src1 = v->vgrf(glsl_type::float_type);
3249 fs_reg zero(brw_imm_f(0.0f));
3250 bld.emit_minmax(dest, src0, src1, BRW_CONDITIONAL_GE);
3251 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE);
3252
3253 /* = Before =
3254 *
3255 * 0: sel.ge(8) dest src0 src1
3256 * 1: cmp.ge.f0(8) null dest 0.0f
3257 *
3258 * = After =
3259 * (no changes)
3260 *
3261 * Do not copy propagate into a sel.cond instruction. While it does modify
3262 * the flags, the flags are not based on the result compared with zero (as
3263 * with most other instructions). The result is based on the sources
3264 * compared with each other (like cmp.cond).
3265 */
3266
3267 v->calculate_cfg();
3268 bblock_t *block0 = v->cfg->blocks[0];
3269
3270 EXPECT_EQ(0, block0->start_ip);
3271 EXPECT_EQ(1, block0->end_ip);
3272
3273 EXPECT_FALSE(cmod_propagation(v));
3274 EXPECT_EQ(0, block0->start_ip);
3275 EXPECT_EQ(1, block0->end_ip);
3276 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 0)->opcode);
3277 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod);
3278 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode);
3279 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod);
3280 }
3281