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 * Based on test_fs_cmod_propagation.cpp 24 */ 25 26#include <gtest/gtest.h> 27#include "brw_vec4.h" 28#include "brw_vec4_builder.h" 29#include "brw_cfg.h" 30#include "program/program.h" 31 32using namespace brw; 33 34class cmod_propagation_test : public ::testing::Test { 35 virtual void SetUp(); 36 virtual void TearDown(); 37 38public: 39 struct brw_compiler *compiler; 40 struct intel_device_info *devinfo; 41 void *ctx; 42 struct gl_shader_program *shader_prog; 43 struct brw_vue_prog_data *prog_data; 44 vec4_visitor *v; 45}; 46 47class cmod_propagation_vec4_visitor : public vec4_visitor 48{ 49public: 50 cmod_propagation_vec4_visitor(struct brw_compiler *compiler, 51 void *mem_ctx, 52 nir_shader *shader, 53 struct brw_vue_prog_data *prog_data) 54 : vec4_visitor(compiler, NULL, NULL, prog_data, shader, mem_ctx, 55 false, -1, false) 56 { 57 prog_data->dispatch_mode = DISPATCH_MODE_4X2_DUAL_OBJECT; 58 } 59 60protected: 61 /* Dummy implementation for pure virtual methods */ 62 virtual dst_reg *make_reg_for_system_value(int /* location */) 63 { 64 unreachable("Not reached"); 65 } 66 67 virtual void setup_payload() 68 { 69 unreachable("Not reached"); 70 } 71 72 virtual void emit_prolog() 73 { 74 unreachable("Not reached"); 75 } 76 77 virtual void emit_program_code() 78 { 79 unreachable("Not reached"); 80 } 81 82 virtual void emit_thread_end() 83 { 84 unreachable("Not reached"); 85 } 86 87 virtual void emit_urb_write_header(int /* mrf */) 88 { 89 unreachable("Not reached"); 90 } 91 92 virtual vec4_instruction *emit_urb_write_opcode(bool /* complete */) 93 { 94 unreachable("Not reached"); 95 } 96}; 97 98 99void cmod_propagation_test::SetUp() 100{ 101 ctx = ralloc_context(NULL); 102 compiler = rzalloc(ctx, struct brw_compiler); 103 devinfo = rzalloc(ctx, struct intel_device_info); 104 compiler->devinfo = devinfo; 105 106 prog_data = ralloc(ctx, struct brw_vue_prog_data); 107 nir_shader *shader = 108 nir_shader_create(ctx, MESA_SHADER_VERTEX, NULL, NULL); 109 110 v = new cmod_propagation_vec4_visitor(compiler, ctx, shader, prog_data); 111 112 devinfo->ver = 7; 113 devinfo->verx10 = devinfo->ver * 10; 114} 115 116void cmod_propagation_test::TearDown() 117{ 118 delete v; 119 v = NULL; 120 121 ralloc_free(ctx); 122 ctx = NULL; 123} 124 125static vec4_instruction * 126instruction(bblock_t *block, int num) 127{ 128 vec4_instruction *inst = (vec4_instruction *)block->start(); 129 for (int i = 0; i < num; i++) { 130 inst = (vec4_instruction *)inst->next; 131 } 132 return inst; 133} 134 135static bool 136cmod_propagation(vec4_visitor *v) 137{ 138 const bool print = getenv("TEST_DEBUG"); 139 140 if (print) { 141 fprintf(stderr, "= Before =\n"); 142 v->dump_instructions(); 143 } 144 145 bool ret = v->opt_cmod_propagation(); 146 147 if (print) { 148 fprintf(stderr, "\n= After =\n"); 149 v->dump_instructions(); 150 } 151 152 return ret; 153} 154 155TEST_F(cmod_propagation_test, basic) 156{ 157 const vec4_builder bld = vec4_builder(v).at_end(); 158 dst_reg dest = dst_reg(v, glsl_type::float_type); 159 src_reg src0 = src_reg(v, glsl_type::float_type); 160 src_reg src1 = src_reg(v, glsl_type::float_type); 161 src_reg zero(brw_imm_f(0.0f)); 162 dst_reg dest_null = bld.null_reg_f(); 163 dest_null.writemask = WRITEMASK_X; 164 165 bld.ADD(dest, src0, src1); 166 bld.CMP(dest_null, src_reg(dest), zero, BRW_CONDITIONAL_GE); 167 168 /* = Before = 169 * 170 * 0: add dest.x src0.xxxx src1.xxxx 171 * 1: cmp.ge.f0 null.x dest.xxxx 0.0f 172 * 173 * = After = 174 * 0: add.ge.f0 dest.x src0.xxxx src1.xxxx 175 */ 176 177 v->calculate_cfg(); 178 bblock_t *block0 = v->cfg->blocks[0]; 179 180 EXPECT_EQ(0, block0->start_ip); 181 EXPECT_EQ(1, block0->end_ip); 182 183 EXPECT_TRUE(cmod_propagation(v)); 184 185 ASSERT_EQ(0, block0->start_ip); 186 ASSERT_EQ(0, block0->end_ip); 187 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 188 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod); 189} 190 191TEST_F(cmod_propagation_test, basic_different_dst_writemask) 192{ 193 const vec4_builder bld = vec4_builder(v).at_end(); 194 dst_reg dest = dst_reg(v, glsl_type::float_type); 195 src_reg src0 = src_reg(v, glsl_type::float_type); 196 src_reg src1 = src_reg(v, glsl_type::float_type); 197 src_reg zero(brw_imm_f(0.0f)); 198 dst_reg dest_null = bld.null_reg_f(); 199 200 bld.ADD(dest, src0, src1); 201 bld.CMP(dest_null, src_reg(dest), zero, BRW_CONDITIONAL_GE); 202 203 /* = Before = 204 * 205 * 0: add dest.x src0 src1 206 * 1: cmp.ge.f0 null.xyzw dest 0.0f 207 * 208 * = After = 209 * (no changes) 210 */ 211 212 v->calculate_cfg(); 213 bblock_t *block0 = v->cfg->blocks[0]; 214 215 EXPECT_EQ(0, block0->start_ip); 216 EXPECT_EQ(1, block0->end_ip); 217 218 EXPECT_FALSE(cmod_propagation(v)); 219 220 ASSERT_EQ(0, block0->start_ip); 221 ASSERT_EQ(1, block0->end_ip); 222 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 223 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 224 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 225 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 226} 227 228TEST_F(cmod_propagation_test, andz_one) 229{ 230 const vec4_builder bld = vec4_builder(v).at_end(); 231 dst_reg dest = dst_reg(v, glsl_type::int_type); 232 src_reg src0 = src_reg(v, glsl_type::float_type); 233 src_reg zero(brw_imm_f(0.0f)); 234 src_reg one(brw_imm_d(1)); 235 236 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L); 237 set_condmod(BRW_CONDITIONAL_Z, 238 bld.AND(bld.null_reg_d(), src_reg(dest), one)); 239 240 /* = Before = 241 * 0: cmp.l.f0 dest:F src0:F 0F 242 * 1: and.z.f0 null:D dest:D 1D 243 * 244 * = After = 245 * (no changes) 246 */ 247 248 v->calculate_cfg(); 249 bblock_t *block0 = v->cfg->blocks[0]; 250 251 EXPECT_EQ(0, block0->start_ip); 252 EXPECT_EQ(1, block0->end_ip); 253 254 EXPECT_FALSE(cmod_propagation(v)); 255 256 ASSERT_EQ(0, block0->start_ip); 257 ASSERT_EQ(1, block0->end_ip); 258 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode); 259 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 260 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode); 261 EXPECT_EQ(BRW_CONDITIONAL_EQ, instruction(block0, 1)->conditional_mod); 262} 263 264TEST_F(cmod_propagation_test, non_cmod_instruction) 265{ 266 const vec4_builder bld = vec4_builder(v).at_end(); 267 dst_reg dest = dst_reg(v, glsl_type::uint_type); 268 src_reg src0 = src_reg(v, glsl_type::uint_type); 269 src_reg zero(brw_imm_ud(0u)); 270 bld.FBL(dest, src0); 271 bld.CMP(bld.null_reg_ud(), src_reg(dest), zero, BRW_CONDITIONAL_GE); 272 273 /* = Before = 274 * 275 * 0: fbl dest src0 276 * 1: cmp.ge.f0 null dest 0u 277 * 278 * = After = 279 * (no changes) 280 */ 281 282 v->calculate_cfg(); 283 bblock_t *block0 = v->cfg->blocks[0]; 284 285 EXPECT_EQ(0, block0->start_ip); 286 EXPECT_EQ(1, block0->end_ip); 287 288 EXPECT_FALSE(cmod_propagation(v)); 289 290 ASSERT_EQ(0, block0->start_ip); 291 ASSERT_EQ(1, block0->end_ip); 292 EXPECT_EQ(BRW_OPCODE_FBL, instruction(block0, 0)->opcode); 293 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 294 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 295} 296 297TEST_F(cmod_propagation_test, intervening_flag_write) 298{ 299 const vec4_builder bld = vec4_builder(v).at_end(); 300 dst_reg dest = dst_reg(v, glsl_type::float_type); 301 src_reg src0 = src_reg(v, glsl_type::float_type); 302 src_reg src1 = src_reg(v, glsl_type::float_type); 303 src_reg src2 = src_reg(v, glsl_type::float_type); 304 src_reg zero(brw_imm_f(0.0f)); 305 bld.ADD(dest, src0, src1); 306 bld.CMP(bld.null_reg_f(), src2, zero, BRW_CONDITIONAL_GE); 307 bld.CMP(bld.null_reg_f(), src_reg(dest), zero, BRW_CONDITIONAL_GE); 308 309 /* = Before = 310 * 311 * 0: add dest src0 src1 312 * 1: cmp.ge.f0 null src2 0.0f 313 * 2: cmp.ge.f0 null dest 0.0f 314 * 315 * = After = 316 * (no changes) 317 */ 318 319 v->calculate_cfg(); 320 bblock_t *block0 = v->cfg->blocks[0]; 321 322 EXPECT_EQ(0, block0->start_ip); 323 EXPECT_EQ(2, block0->end_ip); 324 325 EXPECT_FALSE(cmod_propagation(v)); 326 327 ASSERT_EQ(0, block0->start_ip); 328 ASSERT_EQ(2, block0->end_ip); 329 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 330 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 331 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 332 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode); 333 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod); 334} 335 336TEST_F(cmod_propagation_test, intervening_flag_read) 337{ 338 const vec4_builder bld = vec4_builder(v).at_end(); 339 dst_reg dest0 = dst_reg(v, glsl_type::float_type); 340 dst_reg dest1 = dst_reg(v, glsl_type::float_type); 341 src_reg src0 = src_reg(v, glsl_type::float_type); 342 src_reg src1 = src_reg(v, glsl_type::float_type); 343 src_reg src2 = src_reg(v, glsl_type::float_type); 344 src_reg zero(brw_imm_f(0.0f)); 345 bld.ADD(dest0, src0, src1); 346 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero)); 347 bld.CMP(bld.null_reg_f(), src_reg(dest0), zero, BRW_CONDITIONAL_GE); 348 349 /* = Before = 350 * 351 * 0: add dest0 src0 src1 352 * 1: (+f0) sel dest1 src2 0.0f 353 * 2: cmp.ge.f0 null dest0 0.0f 354 * 355 * = After = 356 * (no changes) 357 */ 358 359 v->calculate_cfg(); 360 bblock_t *block0 = v->cfg->blocks[0]; 361 362 EXPECT_EQ(0, block0->start_ip); 363 EXPECT_EQ(2, block0->end_ip); 364 365 EXPECT_FALSE(cmod_propagation(v)); 366 367 ASSERT_EQ(0, block0->start_ip); 368 ASSERT_EQ(2, block0->end_ip); 369 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 370 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode); 371 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate); 372 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode); 373 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod); 374} 375 376TEST_F(cmod_propagation_test, intervening_dest_write) 377{ 378 const vec4_builder bld = vec4_builder(v).at_end(); 379 dst_reg dest = dst_reg(v, glsl_type::vec4_type); 380 src_reg src0 = src_reg(v, glsl_type::float_type); 381 src_reg src1 = src_reg(v, glsl_type::float_type); 382 src_reg src2 = src_reg(v, glsl_type::vec2_type); 383 src_reg zero(brw_imm_f(0.0f)); 384 bld.ADD(offset(dest, 8, 2), src0, src1); 385 bld.emit(SHADER_OPCODE_TEX, dest, src2) 386 ->size_written = 4 * REG_SIZE; 387 bld.CMP(bld.null_reg_f(), offset(src_reg(dest), 8, 2), zero, BRW_CONDITIONAL_GE); 388 389 /* = Before = 390 * 391 * 0: add dest+2 src0 src1 392 * 1: tex rlen 4 dest+0 src2 393 * 2: cmp.ge.f0 null dest+2 0.0f 394 * 395 * = After = 396 * (no changes) 397 */ 398 399 v->calculate_cfg(); 400 bblock_t *block0 = v->cfg->blocks[0]; 401 402 EXPECT_EQ(0, block0->start_ip); 403 EXPECT_EQ(2, block0->end_ip); 404 405 EXPECT_FALSE(cmod_propagation(v)); 406 407 ASSERT_EQ(0, block0->start_ip); 408 ASSERT_EQ(2, block0->end_ip); 409 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 410 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 411 EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode); 412 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 413 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode); 414 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod); 415} 416 417TEST_F(cmod_propagation_test, intervening_flag_read_same_value) 418{ 419 const vec4_builder bld = vec4_builder(v).at_end(); 420 dst_reg dest0 = dst_reg(v, glsl_type::float_type); 421 dst_reg dest1 = dst_reg(v, glsl_type::float_type); 422 src_reg src0 = src_reg(v, glsl_type::float_type); 423 src_reg src1 = src_reg(v, glsl_type::float_type); 424 src_reg src2 = src_reg(v, glsl_type::float_type); 425 src_reg zero(brw_imm_f(0.0f)); 426 dst_reg dest_null = bld.null_reg_f(); 427 dest_null.writemask = WRITEMASK_X; 428 429 set_condmod(BRW_CONDITIONAL_GE, bld.ADD(dest0, src0, src1)); 430 set_predicate(BRW_PREDICATE_NORMAL, bld.SEL(dest1, src2, zero)); 431 bld.CMP(dest_null, src_reg(dest0), zero, BRW_CONDITIONAL_GE); 432 433 /* = Before = 434 * 435 * 0: add.ge.f0 dest0 src0 src1 436 * 1: (+f0) sel dest1 src2 0.0f 437 * 2: cmp.ge.f0 null.x dest0 0.0f 438 * 439 * = After = 440 * 0: add.ge.f0 dest0 src0 src1 441 * 1: (+f0) sel dest1 src2 0.0f 442 */ 443 444 v->calculate_cfg(); 445 bblock_t *block0 = v->cfg->blocks[0]; 446 447 EXPECT_EQ(0, block0->start_ip); 448 EXPECT_EQ(2, block0->end_ip); 449 450 EXPECT_TRUE(cmod_propagation(v)); 451 ASSERT_EQ(0, block0->start_ip); 452 ASSERT_EQ(1, block0->end_ip); 453 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 454 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod); 455 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode); 456 EXPECT_EQ(BRW_PREDICATE_NORMAL, instruction(block0, 1)->predicate); 457} 458 459TEST_F(cmod_propagation_test, negate) 460{ 461 const vec4_builder bld = vec4_builder(v).at_end(); 462 dst_reg dest = dst_reg(v, glsl_type::float_type); 463 src_reg src0 = src_reg(v, glsl_type::float_type); 464 src_reg src1 = src_reg(v, glsl_type::float_type); 465 src_reg zero(brw_imm_f(0.0f)); 466 bld.ADD(dest, src0, src1); 467 src_reg tmp_src = src_reg(dest); 468 tmp_src.negate = true; 469 dst_reg dest_null = bld.null_reg_f(); 470 dest_null.writemask = WRITEMASK_X; 471 bld.CMP(dest_null, tmp_src, zero, BRW_CONDITIONAL_GE); 472 473 /* = Before = 474 * 475 * 0: add dest src0 src1 476 * 1: cmp.ge.f0 null.x -dest 0.0f 477 * 478 * = After = 479 * 0: add.le.f0 dest src0 src1 480 */ 481 482 v->calculate_cfg(); 483 bblock_t *block0 = v->cfg->blocks[0]; 484 485 EXPECT_EQ(0, block0->start_ip); 486 EXPECT_EQ(1, block0->end_ip); 487 488 EXPECT_TRUE(cmod_propagation(v)); 489 EXPECT_EQ(0, block0->start_ip); 490 EXPECT_EQ(0, block0->end_ip); 491 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 492 EXPECT_EQ(BRW_CONDITIONAL_LE, instruction(block0, 0)->conditional_mod); 493} 494 495TEST_F(cmod_propagation_test, movnz) 496{ 497 const vec4_builder bld = vec4_builder(v).at_end(); 498 dst_reg dest = dst_reg(v, glsl_type::float_type); 499 src_reg src0 = src_reg(v, glsl_type::float_type); 500 src_reg src1 = src_reg(v, glsl_type::float_type); 501 dst_reg dest_null = bld.null_reg_f(); 502 dest_null.writemask = WRITEMASK_X; 503 504 bld.CMP(dest, src0, src1, BRW_CONDITIONAL_L); 505 set_condmod(BRW_CONDITIONAL_NZ, 506 bld.MOV(dest_null, src_reg(dest))); 507 508 /* = Before = 509 * 510 * 0: cmp.l.f0 dest:F src0:F src1:F 511 * 1: mov.nz.f0 null.x dest:F 512 * 513 * = After = 514 * 0: cmp.l.f0 dest src0:F src1:F 515 */ 516 517 v->calculate_cfg(); 518 bblock_t *block0 = v->cfg->blocks[0]; 519 520 EXPECT_EQ(0, block0->start_ip); 521 EXPECT_EQ(1, block0->end_ip); 522 523 EXPECT_TRUE(cmod_propagation(v)); 524 525 ASSERT_EQ(0, block0->start_ip); 526 ASSERT_EQ(0, block0->end_ip); 527 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode); 528 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 529} 530 531TEST_F(cmod_propagation_test, different_types_cmod_with_zero) 532{ 533 const vec4_builder bld = vec4_builder(v).at_end(); 534 dst_reg dest = dst_reg(v, glsl_type::int_type); 535 src_reg src0 = src_reg(v, glsl_type::int_type); 536 src_reg src1 = src_reg(v, glsl_type::int_type); 537 src_reg zero(brw_imm_f(0.0f)); 538 bld.ADD(dest, src0, src1); 539 bld.CMP(bld.null_reg_f(), retype(src_reg(dest), BRW_REGISTER_TYPE_F), zero, 540 BRW_CONDITIONAL_GE); 541 542 /* = Before = 543 * 544 * 0: add dest:D src0:D src1:D 545 * 1: cmp.ge.f0 null:F dest:F 0.0f 546 * 547 * = After = 548 * (no changes) 549 */ 550 551 v->calculate_cfg(); 552 bblock_t *block0 = v->cfg->blocks[0]; 553 554 EXPECT_EQ(0, block0->start_ip); 555 EXPECT_EQ(1, block0->end_ip); 556 557 EXPECT_FALSE(cmod_propagation(v)); 558 559 ASSERT_EQ(0, block0->start_ip); 560 ASSERT_EQ(1, block0->end_ip); 561 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 562 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 563 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 564} 565 566TEST_F(cmod_propagation_test, andnz_non_one) 567{ 568 const vec4_builder bld = vec4_builder(v).at_end(); 569 dst_reg dest = dst_reg(v, glsl_type::int_type); 570 src_reg src0 = src_reg(v, glsl_type::float_type); 571 src_reg zero(brw_imm_f(0.0f)); 572 src_reg nonone(brw_imm_d(38)); 573 574 bld.CMP(retype(dest, BRW_REGISTER_TYPE_F), src0, zero, BRW_CONDITIONAL_L); 575 set_condmod(BRW_CONDITIONAL_NZ, 576 bld.AND(bld.null_reg_d(), src_reg(dest), nonone)); 577 578 /* = Before = 579 * 0: cmp.l.f0 dest:F src0:F 0F 580 * 1: and.nz.f0 null:D dest:D 38D 581 * 582 * = After = 583 * (no changes) 584 */ 585 586 v->calculate_cfg(); 587 bblock_t *block0 = v->cfg->blocks[0]; 588 589 EXPECT_EQ(0, block0->start_ip); 590 EXPECT_EQ(1, block0->end_ip); 591 592 EXPECT_FALSE(cmod_propagation(v)); 593 594 ASSERT_EQ(0, block0->start_ip); 595 ASSERT_EQ(1, block0->end_ip); 596 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode); 597 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 598 EXPECT_EQ(BRW_OPCODE_AND, instruction(block0, 1)->opcode); 599 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod); 600} 601 602/* Note that basic is using glsl_type:float types, while this one is using 603 * glsl_type::vec4 */ 604TEST_F(cmod_propagation_test, basic_vec4) 605{ 606 const vec4_builder bld = vec4_builder(v).at_end(); 607 dst_reg dest = dst_reg(v, glsl_type::vec4_type); 608 src_reg src0 = src_reg(v, glsl_type::vec4_type); 609 src_reg src1 = src_reg(v, glsl_type::vec4_type); 610 src_reg zero(brw_imm_f(0.0f)); 611 612 bld.MUL(dest, src0, src1); 613 bld.CMP(bld.null_reg_f(), src_reg(dest), zero, BRW_CONDITIONAL_NZ); 614 615 /* = Before = 616 * 0: mul dest.xyzw src0.xyzw src1.xyzw 617 * 1: cmp.nz.f0.0 null.xyzw dest.xyzw 0.0f 618 * 619 * = After = 620 * 0: mul.nz.f0.0 dest.xyzw src0.xyzw src1.xyzw 621 */ 622 623 v->calculate_cfg(); 624 bblock_t *block0 = v->cfg->blocks[0]; 625 626 EXPECT_EQ(0, block0->start_ip); 627 EXPECT_EQ(1, block0->end_ip); 628 629 EXPECT_TRUE(cmod_propagation(v)); 630 631 ASSERT_EQ(0, block0->start_ip); 632 ASSERT_EQ(0, block0->end_ip); 633 EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode); 634 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 0)->conditional_mod); 635} 636 637TEST_F(cmod_propagation_test, basic_vec4_different_dst_writemask) 638{ 639 const vec4_builder bld = vec4_builder(v).at_end(); 640 dst_reg dest = dst_reg(v, glsl_type::vec4_type); 641 dest.writemask = WRITEMASK_X; 642 src_reg src0 = src_reg(v, glsl_type::vec4_type); 643 src_reg src1 = src_reg(v, glsl_type::vec4_type); 644 src_reg zero(brw_imm_f(0.0f)); 645 dst_reg dest_null = bld.null_reg_f(); 646 647 bld.MUL(dest, src0, src1); 648 bld.CMP(dest_null, src_reg(dest), zero, BRW_CONDITIONAL_NZ); 649 650 /* = Before = 651 * 0: mul dest.x src0 src1 652 * 1: cmp.nz.f0.0 null dest 0.0f 653 * 654 * = After = 655 * (no changes) 656 */ 657 658 v->calculate_cfg(); 659 bblock_t *block0 = v->cfg->blocks[0]; 660 661 EXPECT_EQ(0, block0->start_ip); 662 EXPECT_EQ(1, block0->end_ip); 663 664 EXPECT_FALSE(cmod_propagation(v)); 665 666 ASSERT_EQ(0, block0->start_ip); 667 ASSERT_EQ(1, block0->end_ip); 668 EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode); 669 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 670 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 671 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod); 672} 673 674TEST_F(cmod_propagation_test, mad_one_component_vec4) 675{ 676 const vec4_builder bld = vec4_builder(v).at_end(); 677 dst_reg dest = dst_reg(v, glsl_type::vec4_type); 678 dest.writemask = WRITEMASK_X; 679 src_reg src0 = src_reg(v, glsl_type::vec4_type); 680 src_reg src1 = src_reg(v, glsl_type::vec4_type); 681 src_reg src2 = src_reg(v, glsl_type::vec4_type); 682 src0.swizzle = src1.swizzle = src2.swizzle = BRW_SWIZZLE_XXXX; 683 src2.negate = true; 684 src_reg zero(brw_imm_f(0.0f)); 685 src_reg tmp(dest); 686 tmp.swizzle = BRW_SWIZZLE_XXXX; 687 dst_reg dest_null = bld.null_reg_f(); 688 dest_null.writemask = WRITEMASK_X; 689 690 bld.MAD(dest, src0, src1, src2); 691 bld.CMP(dest_null, tmp, zero, BRW_CONDITIONAL_L); 692 693 /* = Before = 694 * 695 * 0: mad dest.x:F src0.xxxx:F src10.xxxx:F -src2.xxxx:F 696 * 1: cmp.l.f0.0 null.x:F dest.xxxx:F 0.0f 697 * 698 * = After = 699 * 0: mad.l.f0 dest.x:F src0.xxxx:F src10.xxxx:F -src2.xxxx:F 700 */ 701 702 v->calculate_cfg(); 703 bblock_t *block0 = v->cfg->blocks[0]; 704 705 EXPECT_EQ(0, block0->start_ip); 706 EXPECT_EQ(1, block0->end_ip); 707 708 EXPECT_TRUE(cmod_propagation(v)); 709 710 ASSERT_EQ(0, block0->start_ip); 711 ASSERT_EQ(0, block0->end_ip); 712 EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode); 713 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 0)->conditional_mod); 714} 715 716TEST_F(cmod_propagation_test, mad_more_one_component_vec4) 717{ 718 const vec4_builder bld = vec4_builder(v).at_end(); 719 dst_reg dest = dst_reg(v, glsl_type::vec4_type); 720 dest.writemask = WRITEMASK_XW; 721 src_reg src0 = src_reg(v, glsl_type::vec4_type); 722 src_reg src1 = src_reg(v, glsl_type::vec4_type); 723 src_reg src2 = src_reg(v, glsl_type::vec4_type); 724 src0.swizzle = src1.swizzle = src2.swizzle = BRW_SWIZZLE_XXXX; 725 src2.negate = true; 726 src_reg zero(brw_imm_f(0.0f)); 727 src_reg tmp(dest); 728 tmp.swizzle = BRW_SWIZZLE_XXXX; 729 dst_reg dest_null = bld.null_reg_f(); 730 731 bld.MAD(dest, src0, src1, src2); 732 bld.CMP(dest_null, tmp, zero, BRW_CONDITIONAL_L); 733 734 /* = Before = 735 * 736 * 0: mad dest.xw:F src0.xxxx:F src10.xxxx:F -src2.xxxx:F 737 * 1: cmp.l.f0.0 null:F dest.xxxx:F zeroF 738 * 739 * = After = 740 * (No changes) 741 */ 742 743 v->calculate_cfg(); 744 bblock_t *block0 = v->cfg->blocks[0]; 745 746 EXPECT_EQ(0, block0->start_ip); 747 EXPECT_EQ(1, block0->end_ip); 748 749 EXPECT_FALSE(cmod_propagation(v)); 750 751 ASSERT_EQ(0, block0->start_ip); 752 ASSERT_EQ(1, block0->end_ip); 753 EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode); 754 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 755 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 756 EXPECT_EQ(BRW_CONDITIONAL_L, instruction(block0, 1)->conditional_mod); 757} 758 759TEST_F(cmod_propagation_test, cmp_mov_vec4) 760{ 761 const vec4_builder bld = vec4_builder(v).at_end(); 762 dst_reg dest = dst_reg(v, glsl_type::ivec4_type); 763 dest.writemask = WRITEMASK_X; 764 src_reg src0 = src_reg(v, glsl_type::ivec4_type); 765 src0.swizzle = BRW_SWIZZLE_XXXX; 766 src0.file = UNIFORM; 767 src_reg nonone = retype(brw_imm_d(16), BRW_REGISTER_TYPE_D); 768 src_reg mov_src = src_reg(dest); 769 mov_src.swizzle = BRW_SWIZZLE_XXXX; 770 dst_reg dest_null = bld.null_reg_d(); 771 dest_null.writemask = WRITEMASK_X; 772 773 bld.CMP(dest, src0, nonone, BRW_CONDITIONAL_GE); 774 set_condmod(BRW_CONDITIONAL_NZ, 775 bld.MOV(dest_null, mov_src)); 776 777 /* = Before = 778 * 779 * 0: cmp.ge.f0 dest.x:D u.xxxx:D 16D 780 * 1: mov.nz.f0 null.x:D dest.xxxx:D 781 * 782 * = After = 783 * 0: cmp.ge.f0 dest.x:D u.xxxx:D 16D 784 */ 785 786 v->calculate_cfg(); 787 bblock_t *block0 = v->cfg->blocks[0]; 788 789 EXPECT_EQ(0, block0->start_ip); 790 EXPECT_EQ(1, block0->end_ip); 791 792 EXPECT_TRUE(cmod_propagation(v)); 793 794 ASSERT_EQ(0, block0->start_ip); 795 ASSERT_EQ(0, block0->end_ip); 796 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 0)->opcode); 797 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod); 798} 799 800TEST_F(cmod_propagation_test, mul_cmp_different_channels_vec4) 801{ 802 const vec4_builder bld = vec4_builder(v).at_end(); 803 dst_reg dest = dst_reg(v, glsl_type::vec4_type); 804 src_reg src0 = src_reg(v, glsl_type::vec4_type); 805 src_reg src1 = src_reg(v, glsl_type::vec4_type); 806 src_reg zero(brw_imm_f(0.0f)); 807 src_reg cmp_src = src_reg(dest); 808 cmp_src.swizzle = BRW_SWIZZLE4(0,1,3,2); 809 810 bld.MUL(dest, src0, src1); 811 bld.CMP(bld.null_reg_f(), cmp_src, zero, BRW_CONDITIONAL_NZ); 812 813 /* = Before = 814 * 0: mul dest src0 src1 815 * 1: cmp.nz.f0.0 null dest.xywz 0.0f 816 * 817 * = After = 818 * (No changes) 819 */ 820 821 v->calculate_cfg(); 822 bblock_t *block0 = v->cfg->blocks[0]; 823 824 EXPECT_EQ(0, block0->start_ip); 825 EXPECT_EQ(1, block0->end_ip); 826 827 EXPECT_FALSE(cmod_propagation(v)); 828 829 ASSERT_EQ(0, block0->start_ip); 830 ASSERT_EQ(1, block0->end_ip); 831 EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode); 832 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 833 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 834 EXPECT_EQ(BRW_CONDITIONAL_NZ, instruction(block0, 1)->conditional_mod); 835} 836 837TEST_F(cmod_propagation_test, add_cmp_same_dst_writemask) 838{ 839 const vec4_builder bld = vec4_builder(v).at_end(); 840 dst_reg dest = dst_reg(v, glsl_type::vec4_type); 841 src_reg src0 = src_reg(v, glsl_type::vec4_type); 842 src_reg src1 = src_reg(v, glsl_type::vec4_type); 843 dst_reg dest_null = bld.null_reg_f(); 844 845 bld.ADD(dest, src0, src1); 846 vec4_instruction *inst = bld.CMP(dest_null, src0, src1, BRW_CONDITIONAL_GE); 847 inst->src[1].negate = true; 848 849 /* = Before = 850 * 851 * 0: add dest.xyzw src0 src1 852 * 1: cmp.ge.f0 null.xyzw src0 -src1 853 * 854 * = After = 855 * 0: add.ge.f0 dest.xyzw src0 src1 856 */ 857 858 v->calculate_cfg(); 859 bblock_t *block0 = v->cfg->blocks[0]; 860 861 EXPECT_EQ(0, block0->start_ip); 862 EXPECT_EQ(1, block0->end_ip); 863 864 EXPECT_TRUE(cmod_propagation(v)); 865 866 ASSERT_EQ(0, block0->start_ip); 867 ASSERT_EQ(0, block0->end_ip); 868 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 869 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod); 870} 871 872TEST_F(cmod_propagation_test, add_cmp_different_dst_writemask) 873{ 874 const vec4_builder bld = vec4_builder(v).at_end(); 875 dst_reg dest = dst_reg(v, glsl_type::float_type); 876 src_reg src0 = src_reg(v, glsl_type::vec4_type); 877 src_reg src1 = src_reg(v, glsl_type::vec4_type); 878 dst_reg dest_null = bld.null_reg_f(); 879 880 bld.ADD(dest, src0, src1); 881 vec4_instruction *inst = bld.CMP(dest_null, src0, src1, BRW_CONDITIONAL_GE); 882 inst->src[1].negate = true; 883 884 /* = Before = 885 * 886 * 0: add dest.x src0 src1 887 * 1: cmp.ge.f0 null.xyzw src0 -src1 888 * 889 * = After = 890 * (no changes) 891 */ 892 893 v->calculate_cfg(); 894 bblock_t *block0 = v->cfg->blocks[0]; 895 896 EXPECT_EQ(0, block0->start_ip); 897 EXPECT_EQ(1, block0->end_ip); 898 899 EXPECT_FALSE(cmod_propagation(v)); 900 901 ASSERT_EQ(0, block0->start_ip); 902 ASSERT_EQ(1, block0->end_ip); 903 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 904 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 905 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 906 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 907} 908 909TEST_F(cmod_propagation_test, prop_across_sel_gfx7) 910{ 911 const vec4_builder bld = vec4_builder(v).at_end(); 912 dst_reg dest1 = dst_reg(v, glsl_type::float_type); 913 dst_reg dest2 = dst_reg(v, glsl_type::float_type); 914 src_reg src0 = src_reg(v, glsl_type::float_type); 915 src_reg src1 = src_reg(v, glsl_type::float_type); 916 src_reg src2 = src_reg(v, glsl_type::float_type); 917 src_reg src3 = src_reg(v, glsl_type::float_type); 918 src_reg zero(brw_imm_f(0.0f)); 919 dst_reg dest_null = bld.null_reg_f(); 920 dest_null.writemask = WRITEMASK_X; 921 922 bld.ADD(dest1, src0, src1); 923 bld.SEL(dest2, src2, src3) 924 ->conditional_mod = BRW_CONDITIONAL_GE; 925 bld.CMP(dest_null, src_reg(dest1), zero, BRW_CONDITIONAL_GE); 926 927 /* = Before = 928 * 929 * 0: add dest1.x src0.xxxx src1.xxxx 930 * 1: sel.ge.f0 dest2.x src2.xxxx src3.xxxx 931 * 2: cmp.ge.f0 null.x dest.xxxx 0.0f 932 * 933 * = After = 934 * 0: add.ge.f0 dest.x src0.xxxx src1.xxxx 935 * 1: sel.ge.f0 dest2.x src2.xxxx src3.xxxx 936 */ 937 938 v->calculate_cfg(); 939 bblock_t *block0 = v->cfg->blocks[0]; 940 941 EXPECT_EQ(0, block0->start_ip); 942 EXPECT_EQ(2, block0->end_ip); 943 944 EXPECT_TRUE(cmod_propagation(v)); 945 946 ASSERT_EQ(0, block0->start_ip); 947 ASSERT_EQ(1, block0->end_ip); 948 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 949 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod); 950 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode); 951 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 952} 953 954TEST_F(cmod_propagation_test, prop_across_sel_gfx5) 955{ 956 devinfo->ver = 5; 957 devinfo->verx10 = devinfo->ver * 10; 958 959 const vec4_builder bld = vec4_builder(v).at_end(); 960 dst_reg dest1 = dst_reg(v, glsl_type::float_type); 961 dst_reg dest2 = dst_reg(v, glsl_type::float_type); 962 src_reg src0 = src_reg(v, glsl_type::float_type); 963 src_reg src1 = src_reg(v, glsl_type::float_type); 964 src_reg src2 = src_reg(v, glsl_type::float_type); 965 src_reg src3 = src_reg(v, glsl_type::float_type); 966 src_reg zero(brw_imm_f(0.0f)); 967 dst_reg dest_null = bld.null_reg_f(); 968 dest_null.writemask = WRITEMASK_X; 969 970 bld.ADD(dest1, src0, src1); 971 bld.SEL(dest2, src2, src3) 972 ->conditional_mod = BRW_CONDITIONAL_GE; 973 bld.CMP(dest_null, src_reg(dest1), zero, BRW_CONDITIONAL_GE); 974 975 /* = Before = 976 * 977 * 0: add dest1.x src0.xxxx src1.xxxx 978 * 1: sel.ge.f0 dest2.x src2.xxxx src3.xxxx 979 * 2: cmp.ge.f0 null.x dest.xxxx 0.0f 980 * 981 * = After = 982 * (no changes) 983 * 984 * On Gfx4 and Gfx5, sel.l (for min) and sel.ge (for max) are implemented 985 * using a separate cmpn and sel instruction. This lowering occurs in 986 * fs_vistor::lower_minmax which is called a long time after the first 987 * calls to cmod_propagation. 988 */ 989 990 v->calculate_cfg(); 991 bblock_t *block0 = v->cfg->blocks[0]; 992 993 EXPECT_EQ(0, block0->start_ip); 994 EXPECT_EQ(2, block0->end_ip); 995 996 EXPECT_FALSE(cmod_propagation(v)); 997 998 ASSERT_EQ(0, block0->start_ip); 999 ASSERT_EQ(2, block0->end_ip); 1000 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 1001 EXPECT_EQ(BRW_CONDITIONAL_NONE, instruction(block0, 0)->conditional_mod); 1002 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 1)->opcode); 1003 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 1004 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 2)->opcode); 1005 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 2)->conditional_mod); 1006} 1007 1008TEST_F(cmod_propagation_test, prop_into_sel_gfx5) 1009{ 1010 devinfo->ver = 5; 1011 devinfo->verx10 = devinfo->ver * 10; 1012 1013 const vec4_builder bld = vec4_builder(v).at_end(); 1014 dst_reg dest = dst_reg(v, glsl_type::float_type); 1015 src_reg src0 = src_reg(v, glsl_type::float_type); 1016 src_reg src1 = src_reg(v, glsl_type::float_type); 1017 src_reg zero(brw_imm_f(0.0f)); 1018 dst_reg dest_null = bld.null_reg_f(); 1019 dest_null.writemask = WRITEMASK_X; 1020 1021 bld.SEL(dest, src0, src1) 1022 ->conditional_mod = BRW_CONDITIONAL_GE; 1023 bld.CMP(dest_null, src_reg(dest), zero, BRW_CONDITIONAL_GE); 1024 1025 /* = Before = 1026 * 1027 * 0: sel.ge.f0 dest.x src2.xxxx src3.xxxx 1028 * 1: cmp.ge.f0 null.x dest.xxxx 0.0f 1029 * 1030 * = After = 1031 * (no changes) 1032 * 1033 * Do not copy propagate into a sel.cond instruction. While it does modify 1034 * the flags, the flags are not based on the result compared with zero (as 1035 * with most other instructions). The result is based on the sources 1036 * compared with each other (like cmp.cond). 1037 */ 1038 1039 v->calculate_cfg(); 1040 bblock_t *block0 = v->cfg->blocks[0]; 1041 1042 EXPECT_EQ(0, block0->start_ip); 1043 EXPECT_EQ(1, block0->end_ip); 1044 1045 EXPECT_FALSE(cmod_propagation(v)); 1046 1047 ASSERT_EQ(0, block0->start_ip); 1048 ASSERT_EQ(1, block0->end_ip); 1049 EXPECT_EQ(BRW_OPCODE_SEL, instruction(block0, 0)->opcode); 1050 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 0)->conditional_mod); 1051 EXPECT_EQ(BRW_OPCODE_CMP, instruction(block0, 1)->opcode); 1052 EXPECT_EQ(BRW_CONDITIONAL_GE, instruction(block0, 1)->conditional_mod); 1053} 1054