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