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