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