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 34public: 35 struct brw_compiler *compiler; 36 struct gen_device_info *devinfo; 37 struct gl_context *ctx; 38 struct brw_wm_prog_data *prog_data; 39 struct gl_shader_program *shader_prog; 40 fs_visitor *v; 41}; 42 43class cmod_propagation_fs_visitor : public fs_visitor 44{ 45public: 46 cmod_propagation_fs_visitor(struct brw_compiler *compiler, 47 struct brw_wm_prog_data *prog_data, 48 nir_shader *shader) 49 : fs_visitor(compiler, NULL, NULL, NULL, 50 &prog_data->base, (struct gl_program *) NULL, 51 shader, 8, -1) {} 52}; 53 54 55void cmod_propagation_test::SetUp() 56{ 57 ctx = (struct gl_context *)calloc(1, sizeof(*ctx)); 58 compiler = (struct brw_compiler *)calloc(1, sizeof(*compiler)); 59 devinfo = (struct gen_device_info *)calloc(1, sizeof(*devinfo)); 60 compiler->devinfo = devinfo; 61 62 prog_data = ralloc(NULL, struct brw_wm_prog_data); 63 nir_shader *shader = 64 nir_shader_create(NULL, MESA_SHADER_FRAGMENT, NULL, NULL); 65 66 v = new cmod_propagation_fs_visitor(compiler, prog_data, shader); 67 68 devinfo->gen = 7; 69} 70 71static fs_inst * 72instruction(bblock_t *block, int num) 73{ 74 fs_inst *inst = (fs_inst *)block->start(); 75 for (int i = 0; i < num; i++) { 76 inst = (fs_inst *)inst->next; 77 } 78 return inst; 79} 80 81static bool 82cmod_propagation(fs_visitor *v) 83{ 84 const bool print = getenv("TEST_DEBUG"); 85 86 if (print) { 87 fprintf(stderr, "= Before =\n"); 88 v->cfg->dump(v); 89 } 90 91 bool ret = v->opt_cmod_propagation(); 92 93 if (print) { 94 fprintf(stderr, "\n= After =\n"); 95 v->cfg->dump(v); 96 } 97 98 return ret; 99} 100 101TEST_F(cmod_propagation_test, basic) 102{ 103 const fs_builder &bld = v->bld; 104 fs_reg dest = v->vgrf(glsl_type::float_type); 105 fs_reg src0 = v->vgrf(glsl_type::float_type); 106 fs_reg src1 = v->vgrf(glsl_type::float_type); 107 fs_reg zero(brw_imm_f(0.0f)); 108 bld.ADD(dest, src0, src1); 109 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE); 110 111 /* = Before = 112 * 113 * 0: add(8) dest src0 src1 114 * 1: cmp.ge.f0(8) null dest 0.0f 115 * 116 * = After = 117 * 0: add.ge.f0(8) dest src0 src1 118 */ 119 120 v->calculate_cfg(); 121 bblock_t *block0 = v->cfg->blocks[0]; 122 123 EXPECT_EQ(0, block0->start_ip); 124 EXPECT_EQ(1, block0->end_ip); 125 126 EXPECT_TRUE(cmod_propagation(v)); 127 EXPECT_EQ(0, block0->start_ip); 128 EXPECT_EQ(0, block0->end_ip); 129 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 130 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod); 131} 132 133TEST_F(cmod_propagation_test, cmp_nonzero) 134{ 135 const fs_builder &bld = v->bld; 136 fs_reg dest = v->vgrf(glsl_type::float_type); 137 fs_reg src0 = v->vgrf(glsl_type::float_type); 138 fs_reg src1 = v->vgrf(glsl_type::float_type); 139 fs_reg nonzero(brw_imm_f(1.0f)); 140 bld.ADD(dest, src0, src1); 141 bld.CMP(bld.null_reg_f(), dest, nonzero, BRW_CONDITIONAL_GE); 142 143 /* = Before = 144 * 145 * 0: add(8) dest src0 src1 146 * 1: cmp.ge.f0(8) null dest 1.0f 147 * 148 * = After = 149 * (no changes) 150 */ 151 152 v->calculate_cfg(); 153 bblock_t *block0 = v->cfg->blocks[0]; 154 155 EXPECT_EQ(0, block0->start_ip); 156 EXPECT_EQ(1, block0->end_ip); 157 158 EXPECT_FALSE(cmod_propagation(v)); 159 EXPECT_EQ(0, block0->start_ip); 160 EXPECT_EQ(1, block0->end_ip); 161 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 162 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 163 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 164} 165 166TEST_F(cmod_propagation_test, non_cmod_instruction) 167{ 168 const fs_builder &bld = v->bld; 169 fs_reg dest = v->vgrf(glsl_type::uint_type); 170 fs_reg src0 = v->vgrf(glsl_type::uint_type); 171 fs_reg zero(brw_imm_ud(0u)); 172 bld.FBL(dest, src0); 173 bld.CMP(bld.null_reg_ud(), dest, zero, BRW_CONDITIONAL_GE); 174 175 /* = Before = 176 * 177 * 0: fbl(8) dest src0 178 * 1: cmp.ge.f0(8) null dest 0u 179 * 180 * = After = 181 * (no changes) 182 */ 183 184 v->calculate_cfg(); 185 bblock_t *block0 = v->cfg->blocks[0]; 186 187 EXPECT_EQ(0, block0->start_ip); 188 EXPECT_EQ(1, block0->end_ip); 189 190 EXPECT_FALSE(cmod_propagation(v)); 191 EXPECT_EQ(0, block0->start_ip); 192 EXPECT_EQ(1, block0->end_ip); 193 EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode); 194 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 195 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 196} 197 198TEST_F(cmod_propagation_test, intervening_flag_write) 199{ 200 const fs_builder &bld = v->bld; 201 fs_reg dest = v->vgrf(glsl_type::float_type); 202 fs_reg src0 = v->vgrf(glsl_type::float_type); 203 fs_reg src1 = v->vgrf(glsl_type::float_type); 204 fs_reg src2 = v->vgrf(glsl_type::float_type); 205 fs_reg zero(brw_imm_f(0.0f)); 206 bld.ADD(dest, src0, src1); 207 bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE); 208 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE); 209 210 /* = Before = 211 * 212 * 0: add(8) dest src0 src1 213 * 1: cmp.ge.f0(8) null src2 0.0f 214 * 2: cmp.ge.f0(8) null dest 0.0f 215 * 216 * = After = 217 * (no changes) 218 */ 219 220 v->calculate_cfg(); 221 bblock_t *block0 = v->cfg->blocks[0]; 222 223 EXPECT_EQ(0, block0->start_ip); 224 EXPECT_EQ(2, block0->end_ip); 225 226 EXPECT_FALSE(cmod_propagation(v)); 227 EXPECT_EQ(0, block0->start_ip); 228 EXPECT_EQ(2, block0->end_ip); 229 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 230 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 231 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 232 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode); 233 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod); 234} 235 236TEST_F(cmod_propagation_test, intervening_flag_read) 237{ 238 const fs_builder &bld = v->bld; 239 fs_reg dest0 = v->vgrf(glsl_type::float_type); 240 fs_reg dest1 = v->vgrf(glsl_type::float_type); 241 fs_reg src0 = v->vgrf(glsl_type::float_type); 242 fs_reg src1 = v->vgrf(glsl_type::float_type); 243 fs_reg src2 = v->vgrf(glsl_type::float_type); 244 fs_reg zero(brw_imm_f(0.0f)); 245 bld.ADD(dest0, src0, src1); 246 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero)); 247 bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE); 248 249 /* = Before = 250 * 251 * 0: add(8) dest0 src0 src1 252 * 1: (+f0) sel(8) dest1 src2 0.0f 253 * 2: cmp.ge.f0(8) null dest0 0.0f 254 * 255 * = After = 256 * (no changes) 257 */ 258 259 v->calculate_cfg(); 260 bblock_t *block0 = v->cfg->blocks[0]; 261 262 EXPECT_EQ(0, block0->start_ip); 263 EXPECT_EQ(2, block0->end_ip); 264 265 EXPECT_FALSE(cmod_propagation(v)); 266 EXPECT_EQ(0, block0->start_ip); 267 EXPECT_EQ(2, block0->end_ip); 268 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 269 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode); 270 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate); 271 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode); 272 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod); 273} 274 275TEST_F(cmod_propagation_test, intervening_dest_write) 276{ 277 const fs_builder &bld = v->bld; 278 fs_reg dest = v->vgrf(glsl_type::vec4_type); 279 fs_reg src0 = v->vgrf(glsl_type::float_type); 280 fs_reg src1 = v->vgrf(glsl_type::float_type); 281 fs_reg src2 = v->vgrf(glsl_type::vec2_type); 282 fs_reg zero(brw_imm_f(0.0f)); 283 bld.ADD(offset(dest, bld, 2), src0, src1); 284 bld.emit(SHADER_OPCODE_TEX, dest, src2) 285 ->size_written = 4 * REG_SIZE; 286 bld.CMP(bld.null_reg_f(), offset(dest, bld, 2), zero, BRW_CONDITIONAL_GE); 287 288 /* = Before = 289 * 290 * 0: add(8) dest+2 src0 src1 291 * 1: tex(8) rlen 4 dest+0 src2 292 * 2: cmp.ge.f0(8) null dest+2 0.0f 293 * 294 * = After = 295 * (no changes) 296 */ 297 298 v->calculate_cfg(); 299 bblock_t *block0 = v->cfg->blocks[0]; 300 301 EXPECT_EQ(0, block0->start_ip); 302 EXPECT_EQ(2, block0->end_ip); 303 304 EXPECT_FALSE(cmod_propagation(v)); 305 EXPECT_EQ(0, block0->start_ip); 306 EXPECT_EQ(2, block0->end_ip); 307 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 308 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 309 EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode); 310 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 311 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode); 312 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod); 313} 314 315TEST_F(cmod_propagation_test, intervening_flag_read_same_value) 316{ 317 const fs_builder &bld = v->bld; 318 fs_reg dest0 = v->vgrf(glsl_type::float_type); 319 fs_reg dest1 = v->vgrf(glsl_type::float_type); 320 fs_reg src0 = v->vgrf(glsl_type::float_type); 321 fs_reg src1 = v->vgrf(glsl_type::float_type); 322 fs_reg src2 = v->vgrf(glsl_type::float_type); 323 fs_reg zero(brw_imm_f(0.0f)); 324 set_condmod(BRW_CONDITIONAL_GE, bld.ADD(dest0, src0, src1)); 325 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero)); 326 bld.CMP(bld.null_reg_f(), dest0, zero, BRW_CONDITIONAL_GE); 327 328 /* = Before = 329 * 330 * 0: add.ge.f0(8) dest0 src0 src1 331 * 1: (+f0) sel(8) dest1 src2 0.0f 332 * 2: cmp.ge.f0(8) null dest0 0.0f 333 * 334 * = After = 335 * 0: add.ge.f0(8) dest0 src0 src1 336 * 1: (+f0) sel(8) dest1 src2 0.0f 337 */ 338 339 v->calculate_cfg(); 340 bblock_t *block0 = v->cfg->blocks[0]; 341 342 EXPECT_EQ(0, block0->start_ip); 343 EXPECT_EQ(2, block0->end_ip); 344 345 EXPECT_TRUE(cmod_propagation(v)); 346 EXPECT_EQ(0, block0->start_ip); 347 EXPECT_EQ(1, block0->end_ip); 348 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 349 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod); 350 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode); 351 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate); 352} 353 354TEST_F(cmod_propagation_test, negate) 355{ 356 const fs_builder &bld = v->bld; 357 fs_reg dest = v->vgrf(glsl_type::float_type); 358 fs_reg src0 = v->vgrf(glsl_type::float_type); 359 fs_reg src1 = v->vgrf(glsl_type::float_type); 360 fs_reg zero(brw_imm_f(0.0f)); 361 bld.ADD(dest, src0, src1); 362 dest.negate = true; 363 bld.CMP(bld.null_reg_f(), dest, zero, BRW_CONDITIONAL_GE); 364 365 /* = Before = 366 * 367 * 0: add(8) dest src0 src1 368 * 1: cmp.ge.f0(8) null -dest 0.0f 369 * 370 * = After = 371 * 0: add.le.f0(8) dest src0 src1 372 */ 373 374 v->calculate_cfg(); 375 bblock_t *block0 = v->cfg->blocks[0]; 376 377 EXPECT_EQ(0, block0->start_ip); 378 EXPECT_EQ(1, block0->end_ip); 379 380 EXPECT_TRUE(cmod_propagation(v)); 381 EXPECT_EQ(0, block0->start_ip); 382 EXPECT_EQ(0, block0->end_ip); 383 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 384 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod); 385} 386 387TEST_F(cmod_propagation_test, movnz) 388{ 389 const fs_builder &bld = v->bld; 390 fs_reg dest = v->vgrf(glsl_type::float_type); 391 fs_reg src0 = v->vgrf(glsl_type::float_type); 392 fs_reg src1 = v->vgrf(glsl_type::float_type); 393 bld.CMP(dest, src0, src1, BRW_CONDITIONAL_GE); 394 set_condmod(BRW_CONDITIONAL_NZ, 395 bld.MOV(bld.null_reg_f(), dest)); 396 397 /* = Before = 398 * 399 * 0: cmp.ge.f0(8) dest src0 src1 400 * 1: mov.nz.f0(8) null dest 401 * 402 * = After = 403 * 0: cmp.ge.f0(8) dest src0 src1 404 */ 405 406 v->calculate_cfg(); 407 bblock_t *block0 = v->cfg->blocks[0]; 408 409 EXPECT_EQ(0, block0->start_ip); 410 EXPECT_EQ(1, block0->end_ip); 411 412 EXPECT_TRUE(cmod_propagation(v)); 413 EXPECT_EQ(0, block0->start_ip); 414 EXPECT_EQ(0, block0->end_ip); 415 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode); 416 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod); 417} 418 419TEST_F(cmod_propagation_test, different_types_cmod_with_zero) 420{ 421 const fs_builder &bld = v->bld; 422 fs_reg dest = v->vgrf(glsl_type::int_type); 423 fs_reg src0 = v->vgrf(glsl_type::int_type); 424 fs_reg src1 = v->vgrf(glsl_type::int_type); 425 fs_reg zero(brw_imm_f(0.0f)); 426 bld.ADD(dest, src0, src1); 427 bld.CMP(bld.null_reg_f(), retype(dest, BRW_REGISTER_TYPE_F), zero, 428 BRW_CONDITIONAL_GE); 429 430 /* = Before = 431 * 432 * 0: add(8) dest:D src0:D src1:D 433 * 1: cmp.ge.f0(8) null:F dest:F 0.0f 434 * 435 * = After = 436 * (no changes) 437 */ 438 439 v->calculate_cfg(); 440 bblock_t *block0 = v->cfg->blocks[0]; 441 442 EXPECT_EQ(0, block0->start_ip); 443 EXPECT_EQ(1, block0->end_ip); 444 445 EXPECT_FALSE(cmod_propagation(v)); 446 EXPECT_EQ(0, block0->start_ip); 447 EXPECT_EQ(1, block0->end_ip); 448 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 449 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 450 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 451} 452 453TEST_F(cmod_propagation_test, andnz_one) 454{ 455 const fs_builder &bld = v->bld; 456 fs_reg dest = v->vgrf(glsl_type::int_type); 457 fs_reg src0 = v->vgrf(glsl_type::float_type); 458 fs_reg zero(brw_imm_f(0.0f)); 459 fs_reg one(brw_imm_d(1)); 460 461 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L); 462 set_condmod(BRW_CONDITIONAL_NZ, 463 bld.AND(bld.null_reg_d(), dest, one)); 464 465 /* = Before = 466 * 0: cmp.l.f0(8) dest:F src0:F 0F 467 * 1: and.nz.f0(8) null:D dest:D 1D 468 * 469 * = After = 470 * 0: cmp.l.f0(8) dest:F src0:F 0F 471 */ 472 473 v->calculate_cfg(); 474 bblock_t *block0 = v->cfg->blocks[0]; 475 476 EXPECT_EQ(0, block0->start_ip); 477 EXPECT_EQ(1, block0->end_ip); 478 479 EXPECT_TRUE(cmod_propagation(v)); 480 EXPECT_EQ(0, block0->start_ip); 481 EXPECT_EQ(0, block0->end_ip); 482 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode); 483 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 484 EXPECT_TRUE(retype(dest, BRW_REGISTER_TYPE_F) 485 .equals(instruction(block0, 0)->dst)); 486} 487 488TEST_F(cmod_propagation_test, andnz_non_one) 489{ 490 const fs_builder &bld = v->bld; 491 fs_reg dest = v->vgrf(glsl_type::int_type); 492 fs_reg src0 = v->vgrf(glsl_type::float_type); 493 fs_reg zero(brw_imm_f(0.0f)); 494 fs_reg nonone(brw_imm_d(38)); 495 496 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L); 497 set_condmod(BRW_CONDITIONAL_NZ, 498 bld.AND(bld.null_reg_d(), dest, nonone)); 499 500 /* = Before = 501 * 0: cmp.l.f0(8) dest:F src0:F 0F 502 * 1: and.nz.f0(8) null:D dest:D 38D 503 * 504 * = After = 505 * (no changes) 506 */ 507 508 v->calculate_cfg(); 509 bblock_t *block0 = v->cfg->blocks[0]; 510 511 EXPECT_EQ(0, block0->start_ip); 512 EXPECT_EQ(1, block0->end_ip); 513 514 EXPECT_FALSE(cmod_propagation(v)); 515 EXPECT_EQ(0, block0->start_ip); 516 EXPECT_EQ(1, block0->end_ip); 517 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode); 518 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 519 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode); 520 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod); 521} 522 523TEST_F(cmod_propagation_test, andz_one) 524{ 525 const fs_builder &bld = v->bld; 526 fs_reg dest = v->vgrf(glsl_type::int_type); 527 fs_reg src0 = v->vgrf(glsl_type::float_type); 528 fs_reg zero(brw_imm_f(0.0f)); 529 fs_reg one(brw_imm_d(1)); 530 531 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L); 532 set_condmod(BRW_CONDITIONAL_Z, 533 bld.AND(bld.null_reg_d(), dest, one)); 534 535 /* = Before = 536 * 0: cmp.l.f0(8) dest:F src0:F 0F 537 * 1: and.z.f0(8) null:D dest:D 1D 538 * 539 * = After = 540 * (no changes) 541 */ 542 543 v->calculate_cfg(); 544 bblock_t *block0 = v->cfg->blocks[0]; 545 546 EXPECT_EQ(0, block0->start_ip); 547 EXPECT_EQ(1, block0->end_ip); 548 549 EXPECT_FALSE(cmod_propagation(v)); 550 EXPECT_EQ(0, block0->start_ip); 551 EXPECT_EQ(1, block0->end_ip); 552 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode); 553 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 554 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode); 555 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod); 556} 557 558TEST_F(cmod_propagation_test, add_not_merge_with_compare) 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.ADD(dest, src0, src1); 565 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L); 566 567 /* The addition and the implicit subtraction in the compare do not compute 568 * related values. 569 * 570 * = Before = 571 * 0: add(8) dest:F src0:F src1:F 572 * 1: cmp.l.f0(8) null:F src0:F src1:F 573 * 574 * = After = 575 * (no changes) 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_FALSE(cmod_propagation(v)); 584 EXPECT_EQ(0, block0->start_ip); 585 EXPECT_EQ(1, block0->end_ip); 586 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 587 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 588 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 589 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod); 590} 591 592TEST_F(cmod_propagation_test, subtract_merge_with_compare) 593{ 594 const fs_builder &bld = v->bld; 595 fs_reg dest = v->vgrf(glsl_type::float_type); 596 fs_reg src0 = v->vgrf(glsl_type::float_type); 597 fs_reg src1 = v->vgrf(glsl_type::float_type); 598 bld.ADD(dest, src0, negate(src1)); 599 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L); 600 601 /* = Before = 602 * 0: add(8) dest:F src0:F -src1:F 603 * 1: cmp.l.f0(8) null:F src0:F src1:F 604 * 605 * = After = 606 * 0: add.l.f0(8) dest:F src0:F -src1:F 607 */ 608 v->calculate_cfg(); 609 bblock_t *block0 = v->cfg->blocks[0]; 610 611 EXPECT_EQ(0, block0->start_ip); 612 EXPECT_EQ(1, block0->end_ip); 613 614 EXPECT_TRUE(cmod_propagation(v)); 615 EXPECT_EQ(0, block0->start_ip); 616 EXPECT_EQ(0, block0->end_ip); 617 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 618 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 619} 620 621TEST_F(cmod_propagation_test, subtract_immediate_merge_with_compare) 622{ 623 const fs_builder &bld = v->bld; 624 fs_reg dest = v->vgrf(glsl_type::float_type); 625 fs_reg src0 = v->vgrf(glsl_type::float_type); 626 fs_reg one(brw_imm_f(1.0f)); 627 fs_reg negative_one(brw_imm_f(-1.0f)); 628 629 bld.ADD(dest, src0, negative_one); 630 bld.CMP(bld.null_reg_f(), src0, one, BRW_CONDITIONAL_NZ); 631 632 /* = Before = 633 * 0: add(8) dest:F src0:F -1.0f 634 * 1: cmp.nz.f0(8) null:F src0:F 1.0f 635 * 636 * = After = 637 * 0: add.nz.f0(8) dest:F src0:F -1.0f 638 */ 639 v->calculate_cfg(); 640 bblock_t *block0 = v->cfg->blocks[0]; 641 642 EXPECT_EQ(0, block0->start_ip); 643 EXPECT_EQ(1, block0->end_ip); 644 645 EXPECT_TRUE(cmod_propagation(v)); 646 EXPECT_EQ(0, block0->start_ip); 647 EXPECT_EQ(0, block0->end_ip); 648 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 649 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod); 650} 651 652TEST_F(cmod_propagation_test, subtract_merge_with_compare_intervening_add) 653{ 654 const fs_builder &bld = v->bld; 655 fs_reg dest0 = v->vgrf(glsl_type::float_type); 656 fs_reg dest1 = v->vgrf(glsl_type::float_type); 657 fs_reg src0 = v->vgrf(glsl_type::float_type); 658 fs_reg src1 = v->vgrf(glsl_type::float_type); 659 bld.ADD(dest0, src0, negate(src1)); 660 bld.ADD(dest1, src0, src1); 661 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L); 662 663 /* = Before = 664 * 0: add(8) dest0:F src0:F -src1:F 665 * 1: add(8) dest1:F src0:F src1:F 666 * 2: cmp.l.f0(8) null:F src0:F src1:F 667 * 668 * = After = 669 * 0: add.l.f0(8) dest0:F src0:F -src1:F 670 * 1: add(8) dest1:F src0:F src1:F 671 */ 672 v->calculate_cfg(); 673 bblock_t *block0 = v->cfg->blocks[0]; 674 675 EXPECT_EQ(0, block0->start_ip); 676 EXPECT_EQ(2, block0->end_ip); 677 678 EXPECT_TRUE(cmod_propagation(v)); 679 EXPECT_EQ(0, block0->start_ip); 680 EXPECT_EQ(1, block0->end_ip); 681 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 682 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 683 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode); 684 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod); 685} 686 687TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_partial_write) 688{ 689 const fs_builder &bld = v->bld; 690 fs_reg dest0 = v->vgrf(glsl_type::float_type); 691 fs_reg dest1 = v->vgrf(glsl_type::float_type); 692 fs_reg src0 = v->vgrf(glsl_type::float_type); 693 fs_reg src1 = v->vgrf(glsl_type::float_type); 694 bld.ADD(dest0, src0, negate(src1)); 695 set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, src0, negate(src1))); 696 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L); 697 698 /* = Before = 699 * 0: add(8) dest0:F src0:F -src1:F 700 * 1: (+f0) add(8) dest1:F src0:F -src1:F 701 * 2: cmp.l.f0(8) null:F src0:F src1:F 702 * 703 * = After = 704 * (no changes) 705 */ 706 v->calculate_cfg(); 707 bblock_t *block0 = v->cfg->blocks[0]; 708 709 EXPECT_EQ(0, block0->start_ip); 710 EXPECT_EQ(2, block0->end_ip); 711 712 EXPECT_FALSE(cmod_propagation(v)); 713 EXPECT_EQ(0, block0->start_ip); 714 EXPECT_EQ(2, block0->end_ip); 715 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 716 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 717 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode); 718 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 1)->conditional_mod); 719 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode); 720 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod); 721} 722 723TEST_F(cmod_propagation_test, subtract_not_merge_with_compare_intervening_add) 724{ 725 const fs_builder &bld = v->bld; 726 fs_reg dest0 = v->vgrf(glsl_type::float_type); 727 fs_reg dest1 = v->vgrf(glsl_type::float_type); 728 fs_reg src0 = v->vgrf(glsl_type::float_type); 729 fs_reg src1 = v->vgrf(glsl_type::float_type); 730 bld.ADD(dest0, src0, negate(src1)); 731 set_condmod(BRW_CONDITIONAL_EQ, bld.ADD(dest1, src0, src1)); 732 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L); 733 734 /* = Before = 735 * 0: add(8) dest0:F src0:F -src1:F 736 * 1: add.z.f0(8) dest1:F src0:F src1:F 737 * 2: cmp.l.f0(8) null:F src0:F src1:F 738 * 739 * = After = 740 * (no changes) 741 */ 742 v->calculate_cfg(); 743 bblock_t *block0 = v->cfg->blocks[0]; 744 745 EXPECT_EQ(0, block0->start_ip); 746 EXPECT_EQ(2, block0->end_ip); 747 748 EXPECT_FALSE(cmod_propagation(v)); 749 EXPECT_EQ(0, block0->start_ip); 750 EXPECT_EQ(2, block0->end_ip); 751 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 752 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 753 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode); 754 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod); 755 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode); 756 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 2)->conditional_mod); 757} 758 759TEST_F(cmod_propagation_test, add_merge_with_compare) 760{ 761 const fs_builder &bld = v->bld; 762 fs_reg dest = v->vgrf(glsl_type::float_type); 763 fs_reg src0 = v->vgrf(glsl_type::float_type); 764 fs_reg src1 = v->vgrf(glsl_type::float_type); 765 bld.ADD(dest, src0, src1); 766 bld.CMP(bld.null_reg_f(), src0, negate(src1), BRW_CONDITIONAL_L); 767 768 /* = Before = 769 * 0: add(8) dest:F src0:F src1:F 770 * 1: cmp.l.f0(8) null:F src0:F -src1:F 771 * 772 * = After = 773 * 0: add.l.f0(8) dest:F src0:F src1:F 774 */ 775 v->calculate_cfg(); 776 bblock_t *block0 = v->cfg->blocks[0]; 777 778 EXPECT_EQ(0, block0->start_ip); 779 EXPECT_EQ(1, block0->end_ip); 780 781 EXPECT_TRUE(cmod_propagation(v)); 782 EXPECT_EQ(0, block0->start_ip); 783 EXPECT_EQ(0, block0->end_ip); 784 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 785 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 786} 787 788TEST_F(cmod_propagation_test, negative_subtract_merge_with_compare) 789{ 790 const fs_builder &bld = v->bld; 791 fs_reg dest = v->vgrf(glsl_type::float_type); 792 fs_reg src0 = v->vgrf(glsl_type::float_type); 793 fs_reg src1 = v->vgrf(glsl_type::float_type); 794 bld.ADD(dest, src1, negate(src0)); 795 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L); 796 797 /* The result of the subtract is the negatiion of the result of the 798 * implicit subtract in the compare, so the condition must change. 799 * 800 * = Before = 801 * 0: add(8) dest:F src1:F -src0:F 802 * 1: cmp.l.f0(8) null:F src0:F src1:F 803 * 804 * = After = 805 * 0: add.g.f0(8) dest:F src0:F -src1:F 806 */ 807 v->calculate_cfg(); 808 bblock_t *block0 = v->cfg->blocks[0]; 809 810 EXPECT_EQ(0, block0->start_ip); 811 EXPECT_EQ(1, block0->end_ip); 812 813 EXPECT_TRUE(cmod_propagation(v)); 814 EXPECT_EQ(0, block0->start_ip); 815 EXPECT_EQ(0, block0->end_ip); 816 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 817 EXPECT_EQ(BRW_CONDITIONAL_G, instruction(block0, 0)->conditional_mod); 818} 819 820TEST_F(cmod_propagation_test, subtract_delete_compare) 821{ 822 const fs_builder &bld = v->bld; 823 fs_reg dest = v->vgrf(glsl_type::float_type); 824 fs_reg dest1 = v->vgrf(glsl_type::float_type); 825 fs_reg src0 = v->vgrf(glsl_type::float_type); 826 fs_reg src1 = v->vgrf(glsl_type::float_type); 827 fs_reg src2 = v->vgrf(glsl_type::float_type); 828 829 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest, src0, negate(src1))); 830 set_predicate(BRW_PREDICATE_NORMAL, bld.MOV(dest1, src2)); 831 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L); 832 833 /* = Before = 834 * 0: add.l.f0(8) dest0:F src0:F -src1:F 835 * 1: (+f0) mov(0) dest1:F src2:F 836 * 2: cmp.l.f0(8) null:F src0:F src1:F 837 * 838 * = After = 839 * 0: add.l.f0(8) dest:F src0:F -src1:F 840 * 1: (+f0) mov(0) dest1:F src2:F 841 */ 842 v->calculate_cfg(); 843 bblock_t *block0 = v->cfg->blocks[0]; 844 845 EXPECT_EQ(0, block0->start_ip); 846 EXPECT_EQ(2, block0->end_ip); 847 848 EXPECT_TRUE(cmod_propagation(v)); 849 EXPECT_EQ(0, block0->start_ip); 850 EXPECT_EQ(1, block0->end_ip); 851 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 852 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 853 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 854 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate); 855} 856 857TEST_F(cmod_propagation_test, subtract_delete_compare_derp) 858{ 859 const fs_builder &bld = v->bld; 860 fs_reg dest0 = v->vgrf(glsl_type::float_type); 861 fs_reg dest1 = v->vgrf(glsl_type::float_type); 862 fs_reg src0 = v->vgrf(glsl_type::float_type); 863 fs_reg src1 = v->vgrf(glsl_type::float_type); 864 865 set_condmod(BRW_CONDITIONAL_L, bld.ADD(dest0, src0, negate(src1))); 866 set_predicate(BRW_PREDICATE_NORMAL, bld.ADD(dest1, negate(src0), src1)); 867 bld.CMP(bld.null_reg_f(), src0, src1, BRW_CONDITIONAL_L); 868 869 /* = Before = 870 * 0: add.l.f0(8) dest0:F src0:F -src1:F 871 * 1: (+f0) add(0) dest1:F -src0:F src1:F 872 * 2: cmp.l.f0(8) null:F src0:F src1:F 873 * 874 * = After = 875 * 0: add.l.f0(8) dest0:F src0:F -src1:F 876 * 1: (+f0) add(0) dest1:F -src0:F src1:F 877 */ 878 v->calculate_cfg(); 879 bblock_t *block0 = v->cfg->blocks[0]; 880 881 EXPECT_EQ(0, block0->start_ip); 882 EXPECT_EQ(2, block0->end_ip); 883 884 EXPECT_TRUE(cmod_propagation(v)); 885 EXPECT_EQ(0, block0->start_ip); 886 EXPECT_EQ(1, block0->end_ip); 887 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 888 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 889 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 1)->opcode); 890 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate); 891} 892 893TEST_F(cmod_propagation_test, signed_unsigned_comparison_mismatch) 894{ 895 const fs_builder &bld = v->bld; 896 fs_reg dest0 = v->vgrf(glsl_type::int_type); 897 fs_reg src0 = v->vgrf(glsl_type::int_type); 898 src0.type = BRW_REGISTER_TYPE_W; 899 900 bld.ASR(dest0, negate(src0), brw_imm_d(15)); 901 bld.CMP(bld.null_reg_ud(), retype(dest0, BRW_REGISTER_TYPE_UD), 902 brw_imm_ud(0u), BRW_CONDITIONAL_LE); 903 904 /* = Before = 905 * 0: asr(8) dest:D -src0:W 15D 906 * 1: cmp.le.f0(8) null:UD dest:UD 0UD 907 * 908 * = After = 909 * (no changes) 910 */ 911 v->calculate_cfg(); 912 bblock_t *block0 = v->cfg->blocks[0]; 913 914 EXPECT_EQ(0, block0->start_ip); 915 EXPECT_EQ(1, block0->end_ip); 916 917 EXPECT_FALSE(cmod_propagation(v)); 918 EXPECT_EQ(0, block0->start_ip); 919 EXPECT_EQ(1, block0->end_ip); 920 EXPECT_EQ(BRW_OPCODE_ASR, instruction(block0, 0)->opcode); 921 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 922 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 1)->conditional_mod); 923} 924