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 saturate_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 saturate_propagation_fs_visitor : public fs_visitor 44{ 45public: 46 saturate_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, 16, -1) {} 52}; 53 54 55void saturate_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 saturate_propagation_fs_visitor(compiler, prog_data, shader); 67 68 devinfo->gen = 6; 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 82saturate_propagation(fs_visitor *v) 83{ 84 const bool print = false; 85 86 if (print) { 87 fprintf(stderr, "= Before =\n"); 88 v->cfg->dump(v); 89 } 90 91 bool ret = v->opt_saturate_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(saturate_propagation_test, basic) 102{ 103 const fs_builder &bld = v->bld; 104 fs_reg dst0 = v->vgrf(glsl_type::float_type); 105 fs_reg dst1 = v->vgrf(glsl_type::float_type); 106 fs_reg src0 = v->vgrf(glsl_type::float_type); 107 fs_reg src1 = v->vgrf(glsl_type::float_type); 108 bld.ADD(dst0, src0, src1); 109 set_saturate(true, bld.MOV(dst1, dst0)); 110 111 /* = Before = 112 * 113 * 0: add(16) dst0 src0 src1 114 * 1: mov.sat(16) dst1 dst0 115 * 116 * = After = 117 * 0: add.sat(16) dst0 src0 src1 118 * 1: mov(16) dst1 dst0 119 */ 120 121 v->calculate_cfg(); 122 bblock_t *block0 = v->cfg->blocks[0]; 123 124 EXPECT_EQ(0, block0->start_ip); 125 EXPECT_EQ(1, block0->end_ip); 126 127 EXPECT_TRUE(saturate_propagation(v)); 128 EXPECT_EQ(0, block0->start_ip); 129 EXPECT_EQ(1, block0->end_ip); 130 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 131 EXPECT_TRUE(instruction(block0, 0)->saturate); 132 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 133 EXPECT_FALSE(instruction(block0, 1)->saturate); 134} 135 136TEST_F(saturate_propagation_test, other_non_saturated_use) 137{ 138 const fs_builder &bld = v->bld; 139 fs_reg dst0 = v->vgrf(glsl_type::float_type); 140 fs_reg dst1 = v->vgrf(glsl_type::float_type); 141 fs_reg dst2 = v->vgrf(glsl_type::float_type); 142 fs_reg src0 = v->vgrf(glsl_type::float_type); 143 fs_reg src1 = v->vgrf(glsl_type::float_type); 144 bld.ADD(dst0, src0, src1); 145 set_saturate(true, bld.MOV(dst1, dst0)); 146 bld.ADD(dst2, dst0, src0); 147 148 /* = Before = 149 * 150 * 0: add(16) dst0 src0 src1 151 * 1: mov.sat(16) dst1 dst0 152 * 2: add(16) dst2 dst0 src0 153 * 154 * = After = 155 * (no changes) 156 */ 157 158 v->calculate_cfg(); 159 bblock_t *block0 = v->cfg->blocks[0]; 160 161 EXPECT_EQ(0, block0->start_ip); 162 EXPECT_EQ(2, block0->end_ip); 163 164 EXPECT_FALSE(saturate_propagation(v)); 165 EXPECT_EQ(0, block0->start_ip); 166 EXPECT_EQ(2, block0->end_ip); 167 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 168 EXPECT_FALSE(instruction(block0, 0)->saturate); 169 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 170 EXPECT_TRUE(instruction(block0, 1)->saturate); 171 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 2)->opcode); 172} 173 174TEST_F(saturate_propagation_test, predicated_instruction) 175{ 176 const fs_builder &bld = v->bld; 177 fs_reg dst0 = v->vgrf(glsl_type::float_type); 178 fs_reg dst1 = v->vgrf(glsl_type::float_type); 179 fs_reg src0 = v->vgrf(glsl_type::float_type); 180 fs_reg src1 = v->vgrf(glsl_type::float_type); 181 bld.ADD(dst0, src0, src1) 182 ->predicate = BRW_PREDICATE_NORMAL; 183 set_saturate(true, bld.MOV(dst1, dst0)); 184 185 /* = Before = 186 * 187 * 0: (+f0) add(16) dst0 src0 src1 188 * 1: mov.sat(16) dst1 dst0 189 * 190 * = After = 191 * (no changes) 192 */ 193 194 v->calculate_cfg(); 195 bblock_t *block0 = v->cfg->blocks[0]; 196 197 EXPECT_EQ(0, block0->start_ip); 198 EXPECT_EQ(1, block0->end_ip); 199 200 EXPECT_FALSE(saturate_propagation(v)); 201 EXPECT_EQ(0, block0->start_ip); 202 EXPECT_EQ(1, block0->end_ip); 203 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 204 EXPECT_FALSE(instruction(block0, 0)->saturate); 205 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 206 EXPECT_TRUE(instruction(block0, 1)->saturate); 207} 208 209TEST_F(saturate_propagation_test, neg_mov_sat) 210{ 211 const fs_builder &bld = v->bld; 212 fs_reg dst0 = v->vgrf(glsl_type::float_type); 213 fs_reg dst1 = v->vgrf(glsl_type::float_type); 214 fs_reg src0 = v->vgrf(glsl_type::float_type); 215 bld.RNDU(dst0, src0); 216 dst0.negate = true; 217 set_saturate(true, bld.MOV(dst1, dst0)); 218 219 /* = Before = 220 * 221 * 0: rndu(16) dst0 src0 222 * 1: mov.sat(16) dst1 -dst0 223 * 224 * = After = 225 * (no changes) 226 */ 227 228 v->calculate_cfg(); 229 bblock_t *block0 = v->cfg->blocks[0]; 230 231 EXPECT_EQ(0, block0->start_ip); 232 EXPECT_EQ(1, block0->end_ip); 233 234 EXPECT_FALSE(saturate_propagation(v)); 235 EXPECT_EQ(0, block0->start_ip); 236 EXPECT_EQ(1, block0->end_ip); 237 EXPECT_EQ(BRW_OPCODE_RNDU, instruction(block0, 0)->opcode); 238 EXPECT_FALSE(instruction(block0, 0)->saturate); 239 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 240 EXPECT_TRUE(instruction(block0, 1)->saturate); 241} 242 243TEST_F(saturate_propagation_test, add_neg_mov_sat) 244{ 245 const fs_builder &bld = v->bld; 246 fs_reg dst0 = v->vgrf(glsl_type::float_type); 247 fs_reg dst1 = v->vgrf(glsl_type::float_type); 248 fs_reg src0 = v->vgrf(glsl_type::float_type); 249 fs_reg src1 = v->vgrf(glsl_type::float_type); 250 bld.ADD(dst0, src0, src1); 251 dst0.negate = true; 252 set_saturate(true, bld.MOV(dst1, dst0)); 253 254 /* = Before = 255 * 256 * 0: add(16) dst0 src0 src1 257 * 1: mov.sat(16) dst1 -dst0 258 * 259 * = After = 260 * 0: add.sat(16) dst0 -src0 -src1 261 * 1: mov(16) dst1 dst0 262 */ 263 264 v->calculate_cfg(); 265 bblock_t *block0 = v->cfg->blocks[0]; 266 267 EXPECT_EQ(0, block0->start_ip); 268 EXPECT_EQ(1, block0->end_ip); 269 270 EXPECT_TRUE(saturate_propagation(v)); 271 EXPECT_EQ(0, block0->start_ip); 272 EXPECT_EQ(1, block0->end_ip); 273 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 274 EXPECT_TRUE(instruction(block0, 0)->saturate); 275 EXPECT_TRUE(instruction(block0, 0)->src[0].negate); 276 EXPECT_TRUE(instruction(block0, 0)->src[1].negate); 277 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 278 EXPECT_FALSE(instruction(block0, 1)->saturate); 279} 280 281TEST_F(saturate_propagation_test, add_imm_float_neg_mov_sat) 282{ 283 const fs_builder &bld = v->bld; 284 fs_reg dst0 = v->vgrf(glsl_type::float_type); 285 fs_reg dst1 = v->vgrf(glsl_type::float_type); 286 fs_reg src0 = v->vgrf(glsl_type::float_type); 287 fs_reg src1 = brw_imm_f(1.0f); 288 bld.ADD(dst0, src0, src1); 289 dst0.negate = true; 290 set_saturate(true, bld.MOV(dst1, dst0)); 291 292 /* = Before = 293 * 294 * 0: add(16) dst0 src0 1.0f 295 * 1: mov.sat(16) dst1 -dst0 296 * 297 * = After = 298 * 0: add.sat(16) dst0 -src0 -1.0f 299 * 1: mov(16) dst1 dst0 300 */ 301 302 v->calculate_cfg(); 303 bblock_t *block0 = v->cfg->blocks[0]; 304 305 EXPECT_EQ(0, block0->start_ip); 306 EXPECT_EQ(1, block0->end_ip); 307 308 EXPECT_TRUE(saturate_propagation(v)); 309 EXPECT_EQ(0, block0->start_ip); 310 EXPECT_EQ(1, block0->end_ip); 311 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 312 EXPECT_TRUE(instruction(block0, 0)->saturate); 313 EXPECT_TRUE(instruction(block0, 0)->src[0].negate); 314 EXPECT_EQ(instruction(block0, 0)->src[1].f, -1.0f); 315 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 316 EXPECT_FALSE(instruction(block0, 1)->saturate); 317} 318 319TEST_F(saturate_propagation_test, mul_neg_mov_sat) 320{ 321 const fs_builder &bld = v->bld; 322 fs_reg dst0 = v->vgrf(glsl_type::float_type); 323 fs_reg dst1 = v->vgrf(glsl_type::float_type); 324 fs_reg src0 = v->vgrf(glsl_type::float_type); 325 fs_reg src1 = v->vgrf(glsl_type::float_type); 326 bld.MUL(dst0, src0, src1); 327 dst0.negate = true; 328 set_saturate(true, bld.MOV(dst1, dst0)); 329 330 /* = Before = 331 * 332 * 0: mul(16) dst0 src0 src1 333 * 1: mov.sat(16) dst1 -dst0 334 * 335 * = After = 336 * 0: mul.sat(16) dst0 src0 -src1 337 * 1: mov(16) dst1 dst0 338 */ 339 340 v->calculate_cfg(); 341 bblock_t *block0 = v->cfg->blocks[0]; 342 343 EXPECT_EQ(0, block0->start_ip); 344 EXPECT_EQ(1, block0->end_ip); 345 346 EXPECT_TRUE(saturate_propagation(v)); 347 EXPECT_EQ(0, block0->start_ip); 348 EXPECT_EQ(1, block0->end_ip); 349 EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode); 350 EXPECT_TRUE(instruction(block0, 0)->saturate); 351 EXPECT_TRUE(instruction(block0, 0)->src[0].negate); 352 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 353 EXPECT_FALSE(instruction(block0, 1)->saturate); 354 EXPECT_FALSE(instruction(block0, 1)->src[0].negate); 355} 356 357TEST_F(saturate_propagation_test, mad_neg_mov_sat) 358{ 359 const fs_builder &bld = v->bld; 360 fs_reg dst0 = v->vgrf(glsl_type::float_type); 361 fs_reg dst1 = v->vgrf(glsl_type::float_type); 362 fs_reg src0 = v->vgrf(glsl_type::float_type); 363 fs_reg src1 = v->vgrf(glsl_type::float_type); 364 fs_reg src2 = v->vgrf(glsl_type::float_type); 365 bld.MAD(dst0, src0, src1, src2); 366 dst0.negate = true; 367 set_saturate(true, bld.MOV(dst1, dst0)); 368 369 /* = Before = 370 * 371 * 0: mad(16) dst0 src0 src1 src2 372 * 1: mov.sat(16) dst1 -dst0 373 * 374 * = After = 375 * 0: mad.sat(16) dst0 -src0 -src1 src2 376 * 1: mov(16) dst1 dst0 377 */ 378 379 v->calculate_cfg(); 380 bblock_t *block0 = v->cfg->blocks[0]; 381 382 EXPECT_EQ(0, block0->start_ip); 383 EXPECT_EQ(1, block0->end_ip); 384 385 EXPECT_TRUE(saturate_propagation(v)); 386 EXPECT_EQ(0, block0->start_ip); 387 EXPECT_EQ(1, block0->end_ip); 388 EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode); 389 EXPECT_TRUE(instruction(block0, 0)->saturate); 390 EXPECT_TRUE(instruction(block0, 0)->src[0].negate); 391 EXPECT_TRUE(instruction(block0, 0)->src[1].negate); 392 EXPECT_FALSE(instruction(block0, 0)->src[2].negate); 393 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 394 EXPECT_FALSE(instruction(block0, 1)->saturate); 395 EXPECT_FALSE(instruction(block0, 1)->src[0].negate); 396} 397 398TEST_F(saturate_propagation_test, mad_imm_float_neg_mov_sat) 399{ 400 const fs_builder &bld = v->bld; 401 fs_reg dst0 = v->vgrf(glsl_type::float_type); 402 fs_reg dst1 = v->vgrf(glsl_type::float_type); 403 fs_reg src0 = brw_imm_f(1.0f); 404 fs_reg src1 = brw_imm_f(-2.0f); 405 fs_reg src2 = v->vgrf(glsl_type::float_type); 406 /* The builder for MAD tries to be helpful and not put immediates as direct 407 * sources. We want to test specifically that case. 408 */ 409 fs_inst *mad = bld.MAD(dst0, src2, src2, src2); 410 mad->src[0]= src0; 411 mad->src[1] = src1; 412 dst0.negate = true; 413 set_saturate(true, bld.MOV(dst1, dst0)); 414 415 /* = Before = 416 * 417 * 0: mad(16) dst0 1.0f -2.0f src2 418 * 1: mov.sat(16) dst1 -dst0 419 * 420 * = After = 421 * 0: mad.sat(16) dst0 -1.0f 2.0f src2 422 * 1: mov(16) dst1 dst0 423 */ 424 425 v->calculate_cfg(); 426 bblock_t *block0 = v->cfg->blocks[0]; 427 428 EXPECT_EQ(0, block0->start_ip); 429 EXPECT_EQ(1, block0->end_ip); 430 431 EXPECT_TRUE(saturate_propagation(v)); 432 EXPECT_EQ(0, block0->start_ip); 433 EXPECT_EQ(1, block0->end_ip); 434 EXPECT_EQ(BRW_OPCODE_MAD, instruction(block0, 0)->opcode); 435 EXPECT_TRUE(instruction(block0, 0)->saturate); 436 EXPECT_EQ(instruction(block0, 0)->src[0].f, -1.0f); 437 EXPECT_EQ(instruction(block0, 0)->src[1].f, 2.0f); 438 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 439 EXPECT_FALSE(instruction(block0, 1)->saturate); 440 EXPECT_FALSE(instruction(block0, 1)->src[0].negate); 441} 442 443TEST_F(saturate_propagation_test, mul_mov_sat_neg_mov_sat) 444{ 445 const fs_builder &bld = v->bld; 446 fs_reg dst0 = v->vgrf(glsl_type::float_type); 447 fs_reg dst1 = v->vgrf(glsl_type::float_type); 448 fs_reg dst2 = v->vgrf(glsl_type::float_type); 449 fs_reg src0 = v->vgrf(glsl_type::float_type); 450 fs_reg src1 = v->vgrf(glsl_type::float_type); 451 bld.MUL(dst0, src0, src1); 452 set_saturate(true, bld.MOV(dst1, dst0)); 453 dst0.negate = true; 454 set_saturate(true, bld.MOV(dst2, dst0)); 455 456 /* = Before = 457 * 458 * 0: mul(16) dst0 src0 src1 459 * 1: mov.sat(16) dst1 dst0 460 * 2: mov.sat(16) dst2 -dst0 461 * 462 * = After = 463 * (no changes) 464 */ 465 466 v->calculate_cfg(); 467 bblock_t *block0 = v->cfg->blocks[0]; 468 469 EXPECT_EQ(0, block0->start_ip); 470 EXPECT_EQ(2, block0->end_ip); 471 472 EXPECT_FALSE(saturate_propagation(v)); 473 EXPECT_EQ(0, block0->start_ip); 474 EXPECT_EQ(2, block0->end_ip); 475 EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode); 476 EXPECT_FALSE(instruction(block0, 0)->saturate); 477 EXPECT_FALSE(instruction(block0, 0)->src[1].negate); 478 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 479 EXPECT_TRUE(instruction(block0, 1)->saturate); 480 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode); 481 EXPECT_TRUE(instruction(block0, 2)->src[0].negate); 482 EXPECT_TRUE(instruction(block0, 2)->saturate); 483} 484 485TEST_F(saturate_propagation_test, mul_neg_mov_sat_neg_mov_sat) 486{ 487 const fs_builder &bld = v->bld; 488 fs_reg dst0 = v->vgrf(glsl_type::float_type); 489 fs_reg dst1 = v->vgrf(glsl_type::float_type); 490 fs_reg dst2 = 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 bld.MUL(dst0, src0, src1); 494 dst0.negate = true; 495 set_saturate(true, bld.MOV(dst1, dst0)); 496 set_saturate(true, bld.MOV(dst2, dst0)); 497 498 /* = Before = 499 * 500 * 0: mul(16) dst0 src0 src1 501 * 1: mov.sat(16) dst1 -dst0 502 * 2: mov.sat(16) dst2 -dst0 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(2, block0->end_ip); 513 514 EXPECT_FALSE(saturate_propagation(v)); 515 EXPECT_EQ(0, block0->start_ip); 516 EXPECT_EQ(2, block0->end_ip); 517 EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode); 518 EXPECT_FALSE(instruction(block0, 0)->saturate); 519 EXPECT_FALSE(instruction(block0, 0)->src[1].negate); 520 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 521 EXPECT_TRUE(instruction(block0, 1)->src[0].negate); 522 EXPECT_TRUE(instruction(block0, 1)->saturate); 523 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode); 524 EXPECT_TRUE(instruction(block0, 2)->src[0].negate); 525 EXPECT_TRUE(instruction(block0, 2)->saturate); 526} 527 528TEST_F(saturate_propagation_test, abs_mov_sat) 529{ 530 const fs_builder &bld = v->bld; 531 fs_reg dst0 = v->vgrf(glsl_type::float_type); 532 fs_reg dst1 = v->vgrf(glsl_type::float_type); 533 fs_reg src0 = v->vgrf(glsl_type::float_type); 534 fs_reg src1 = v->vgrf(glsl_type::float_type); 535 bld.ADD(dst0, src0, src1); 536 dst0.abs = true; 537 set_saturate(true, bld.MOV(dst1, dst0)); 538 539 /* = Before = 540 * 541 * 0: add(16) dst0 src0 src1 542 * 1: mov.sat(16) dst1 (abs)dst0 543 * 544 * = After = 545 * (no changes) 546 */ 547 548 v->calculate_cfg(); 549 bblock_t *block0 = v->cfg->blocks[0]; 550 551 EXPECT_EQ(0, block0->start_ip); 552 EXPECT_EQ(1, block0->end_ip); 553 554 EXPECT_FALSE(saturate_propagation(v)); 555 EXPECT_EQ(0, block0->start_ip); 556 EXPECT_EQ(1, block0->end_ip); 557 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 558 EXPECT_FALSE(instruction(block0, 0)->saturate); 559 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 560 EXPECT_TRUE(instruction(block0, 1)->saturate); 561} 562 563TEST_F(saturate_propagation_test, producer_saturates) 564{ 565 const fs_builder &bld = v->bld; 566 fs_reg dst0 = v->vgrf(glsl_type::float_type); 567 fs_reg dst1 = v->vgrf(glsl_type::float_type); 568 fs_reg dst2 = v->vgrf(glsl_type::float_type); 569 fs_reg src0 = v->vgrf(glsl_type::float_type); 570 fs_reg src1 = v->vgrf(glsl_type::float_type); 571 set_saturate(true, bld.ADD(dst0, src0, src1)); 572 set_saturate(true, bld.MOV(dst1, dst0)); 573 bld.MOV(dst2, dst0); 574 575 /* = Before = 576 * 577 * 0: add.sat(16) dst0 src0 src1 578 * 1: mov.sat(16) dst1 dst0 579 * 2: mov(16) dst2 dst0 580 * 581 * = After = 582 * 0: add.sat(16) dst0 src0 src1 583 * 1: mov(16) dst1 dst0 584 * 2: mov(16) dst2 dst0 585 */ 586 587 v->calculate_cfg(); 588 bblock_t *block0 = v->cfg->blocks[0]; 589 590 EXPECT_EQ(0, block0->start_ip); 591 EXPECT_EQ(2, block0->end_ip); 592 593 EXPECT_TRUE(saturate_propagation(v)); 594 EXPECT_EQ(0, block0->start_ip); 595 EXPECT_EQ(2, block0->end_ip); 596 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 597 EXPECT_TRUE(instruction(block0, 0)->saturate); 598 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 599 EXPECT_FALSE(instruction(block0, 1)->saturate); 600} 601 602TEST_F(saturate_propagation_test, intervening_saturating_copy) 603{ 604 const fs_builder &bld = v->bld; 605 fs_reg dst0 = v->vgrf(glsl_type::float_type); 606 fs_reg dst1 = v->vgrf(glsl_type::float_type); 607 fs_reg dst2 = v->vgrf(glsl_type::float_type); 608 fs_reg src0 = v->vgrf(glsl_type::float_type); 609 fs_reg src1 = v->vgrf(glsl_type::float_type); 610 bld.ADD(dst0, src0, src1); 611 set_saturate(true, bld.MOV(dst1, dst0)); 612 set_saturate(true, bld.MOV(dst2, dst0)); 613 614 /* = Before = 615 * 616 * 0: add(16) dst0 src0 src1 617 * 1: mov.sat(16) dst1 dst0 618 * 2: mov.sat(16) dst2 dst0 619 * 620 * = After = 621 * 0: add.sat(16) dst0 src0 src1 622 * 1: mov(16) dst1 dst0 623 * 2: mov(16) dst2 dst0 624 */ 625 626 v->calculate_cfg(); 627 bblock_t *block0 = v->cfg->blocks[0]; 628 629 EXPECT_EQ(0, block0->start_ip); 630 EXPECT_EQ(2, block0->end_ip); 631 632 EXPECT_TRUE(saturate_propagation(v)); 633 EXPECT_EQ(0, block0->start_ip); 634 EXPECT_EQ(2, block0->end_ip); 635 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 636 EXPECT_TRUE(instruction(block0, 0)->saturate); 637 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 638 EXPECT_FALSE(instruction(block0, 1)->saturate); 639 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode); 640 EXPECT_FALSE(instruction(block0, 2)->saturate); 641} 642 643TEST_F(saturate_propagation_test, intervening_dest_write) 644{ 645 const fs_builder &bld = v->bld; 646 fs_reg dst0 = v->vgrf(glsl_type::vec4_type); 647 fs_reg dst1 = v->vgrf(glsl_type::float_type); 648 fs_reg src0 = v->vgrf(glsl_type::float_type); 649 fs_reg src1 = v->vgrf(glsl_type::float_type); 650 fs_reg src2 = v->vgrf(glsl_type::vec2_type); 651 bld.ADD(offset(dst0, bld, 2), src0, src1); 652 bld.emit(SHADER_OPCODE_TEX, dst0, src2) 653 ->size_written = 8 * REG_SIZE; 654 set_saturate(true, bld.MOV(dst1, offset(dst0, bld, 2))); 655 656 /* = Before = 657 * 658 * 0: add(16) dst0+2 src0 src1 659 * 1: tex(16) rlen 4 dst0+0 src2 660 * 2: mov.sat(16) dst1 dst0+2 661 * 662 * = After = 663 * (no changes) 664 */ 665 666 v->calculate_cfg(); 667 bblock_t *block0 = v->cfg->blocks[0]; 668 669 EXPECT_EQ(0, block0->start_ip); 670 EXPECT_EQ(2, block0->end_ip); 671 672 EXPECT_FALSE(saturate_propagation(v)); 673 EXPECT_EQ(0, block0->start_ip); 674 EXPECT_EQ(2, block0->end_ip); 675 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 676 EXPECT_FALSE(instruction(block0, 0)->saturate); 677 EXPECT_EQ(SHADER_OPCODE_TEX, instruction(block0, 1)->opcode); 678 EXPECT_FALSE(instruction(block0, 0)->saturate); 679 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode); 680 EXPECT_TRUE(instruction(block0, 2)->saturate); 681} 682 683TEST_F(saturate_propagation_test, mul_neg_mov_sat_mov_sat) 684{ 685 const fs_builder &bld = v->bld; 686 fs_reg dst0 = v->vgrf(glsl_type::float_type); 687 fs_reg dst1 = v->vgrf(glsl_type::float_type); 688 fs_reg dst2 = v->vgrf(glsl_type::float_type); 689 fs_reg src0 = v->vgrf(glsl_type::float_type); 690 fs_reg src1 = v->vgrf(glsl_type::float_type); 691 bld.MUL(dst0, src0, src1); 692 dst0.negate = true; 693 set_saturate(true, bld.MOV(dst1, dst0)); 694 dst0.negate = false; 695 set_saturate(true, bld.MOV(dst2, dst0)); 696 697 /* = Before = 698 * 699 * 0: mul(16) dst0 src0 src1 700 * 1: mov.sat(16) dst1 -dst0 701 * 2: mov.sat(16) dst2 dst0 702 * 703 * = After = 704 * (no changes) 705 */ 706 707 v->calculate_cfg(); 708 bblock_t *block0 = v->cfg->blocks[0]; 709 710 EXPECT_EQ(0, block0->start_ip); 711 EXPECT_EQ(2, block0->end_ip); 712 713 EXPECT_FALSE(saturate_propagation(v)); 714 EXPECT_EQ(0, block0->start_ip); 715 EXPECT_EQ(2, block0->end_ip); 716 EXPECT_EQ(BRW_OPCODE_MUL, instruction(block0, 0)->opcode); 717 EXPECT_FALSE(instruction(block0, 0)->saturate); 718 EXPECT_FALSE(instruction(block0, 0)->src[1].negate); 719 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 720 EXPECT_TRUE(instruction(block0, 1)->saturate); 721 EXPECT_TRUE(instruction(block0, 1)->src[0].negate); 722 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 2)->opcode); 723 EXPECT_TRUE(instruction(block0, 2)->saturate); 724} 725 726TEST_F(saturate_propagation_test, smaller_exec_size_consumer) 727{ 728 const fs_builder &bld = v->bld; 729 fs_reg dst0 = v->vgrf(glsl_type::float_type); 730 fs_reg dst1 = v->vgrf(glsl_type::float_type); 731 fs_reg src0 = v->vgrf(glsl_type::float_type); 732 fs_reg src1 = v->vgrf(glsl_type::float_type); 733 bld.ADD(dst0, src0, src1); 734 set_saturate(true, bld.group(8, 0).MOV(dst1, dst0)); 735 736 /* = Before = 737 * 738 * 0: add(16) dst0 src0 src1 739 * 1: mov.sat(8) dst1 dst0 740 * 741 * = After = 742 * (no changes) 743 */ 744 745 v->calculate_cfg(); 746 bblock_t *block0 = v->cfg->blocks[0]; 747 748 EXPECT_EQ(0, block0->start_ip); 749 EXPECT_EQ(1, block0->end_ip); 750 751 EXPECT_FALSE(saturate_propagation(v)); 752 EXPECT_EQ(0, block0->start_ip); 753 EXPECT_EQ(1, block0->end_ip); 754 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 755 EXPECT_FALSE(instruction(block0, 0)->saturate); 756 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 757 EXPECT_TRUE(instruction(block0, 1)->saturate); 758} 759 760TEST_F(saturate_propagation_test, larger_exec_size_consumer) 761{ 762 const fs_builder &bld = v->bld; 763 fs_reg dst0 = v->vgrf(glsl_type::float_type); 764 fs_reg dst1 = v->vgrf(glsl_type::float_type); 765 fs_reg src0 = v->vgrf(glsl_type::float_type); 766 fs_reg src1 = v->vgrf(glsl_type::float_type); 767 bld.group(8, 0).ADD(dst0, src0, src1); 768 set_saturate(true, bld.MOV(dst1, dst0)); 769 770 /* = Before = 771 * 772 * 0: add(8) dst0 src0 src1 773 * 1: mov.sat(16) dst1 dst0 774 * 775 * = After = 776 * (no changes) 777 */ 778 779 v->calculate_cfg(); 780 bblock_t *block0 = v->cfg->blocks[0]; 781 782 EXPECT_EQ(0, block0->start_ip); 783 EXPECT_EQ(1, block0->end_ip); 784 785 EXPECT_FALSE(saturate_propagation(v)); 786 EXPECT_EQ(0, block0->start_ip); 787 EXPECT_EQ(1, block0->end_ip); 788 EXPECT_EQ(BRW_OPCODE_ADD, instruction(block0, 0)->opcode); 789 EXPECT_FALSE(instruction(block0, 0)->saturate); 790 EXPECT_EQ(BRW_OPCODE_MOV, instruction(block0, 1)->opcode); 791 EXPECT_TRUE(instruction(block0, 1)->saturate); 792} 793