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