1// Copyright (c) 2017 Valve Corporation 2// Copyright (c) 2017 LunarG Inc. 3// 4// Licensed under the Apache License, Version 2.0 (the "License"); 5// you may not use this file except in compliance with the License. 6// You may obtain a copy of the License at 7// 8// http://www.apache.org/licenses/LICENSE-2.0 9// 10// Unless required by applicable law or agreed to in writing, software 11// distributed under the License is distributed on an "AS IS" BASIS, 12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13// See the License for the specific language governing permissions and 14// limitations under the License. 15 16#include <string> 17#include <vector> 18 19#include "test/opt/assembly_builder.h" 20#include "test/opt/pass_fixture.h" 21#include "test/opt/pass_utils.h" 22 23namespace spvtools { 24namespace opt { 25namespace { 26 27using AggressiveDCETest = PassTest<::testing::Test>; 28 29TEST_F(AggressiveDCETest, EliminateExtendedInst) { 30 // #version 140 31 // 32 // in vec4 BaseColor; 33 // in vec4 Dead; 34 // 35 // void main() 36 // { 37 // vec4 v = BaseColor; 38 // vec4 dv = sqrt(Dead); 39 // gl_FragColor = v; 40 // } 41 const std::string spirv = R"( 42OpCapability Shader 43%1 = OpExtInstImport "GLSL.std.450" 44OpMemoryModel Logical GLSL450 45; CHECK: OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 46OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor 47OpExecutionMode %main OriginUpperLeft 48OpSource GLSL 140 49OpName %main "main" 50OpName %v "v" 51OpName %BaseColor "BaseColor" 52; CHECK-NOT: OpName %dv "dv" 53OpName %dv "dv" 54; CHECK-NOT: OpName %Dead "Dead" 55OpName %Dead "Dead" 56OpName %gl_FragColor "gl_FragColor" 57%void = OpTypeVoid 58%9 = OpTypeFunction %void 59%float = OpTypeFloat 32 60%v4float = OpTypeVector %float 4 61%_ptr_Function_v4float = OpTypePointer Function %v4float 62%_ptr_Input_v4float = OpTypePointer Input %v4float 63%BaseColor = OpVariable %_ptr_Input_v4float Input 64; CHECK-NOT: %Dead = OpVariable 65%Dead = OpVariable %_ptr_Input_v4float Input 66%_ptr_Output_v4float = OpTypePointer Output %v4float 67%gl_FragColor = OpVariable %_ptr_Output_v4float Output 68%main = OpFunction %void None %9 69%15 = OpLabel 70%v = OpVariable %_ptr_Function_v4float Function 71; CHECK-NOT: %dv = OpVariable 72%dv = OpVariable %_ptr_Function_v4float Function 73%16 = OpLoad %v4float %BaseColor 74OpStore %v %16 75; CHECK-NOT: OpLoad %v4float %Dead 76%17 = OpLoad %v4float %Dead 77; CHECK-NOT: OpExtInst %v4float %1 Sqrt 78%18 = OpExtInst %v4float %1 Sqrt %17 79; CHECK-NOT: OpStore %dv 80OpStore %dv %18 81%19 = OpLoad %v4float %v 82OpStore %gl_FragColor %19 83OpReturn 84OpFunctionEnd 85)"; 86 87 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 88} 89 90TEST_F(AggressiveDCETest, NoEliminateFrexp) { 91 // Note: SPIR-V hand-edited to utilize Frexp 92 // 93 // #version 450 94 // 95 // in vec4 BaseColor; 96 // in vec4 Dead; 97 // out vec4 Color; 98 // out ivec4 iv2; 99 // 100 // void main() 101 // { 102 // vec4 v = BaseColor; 103 // vec4 dv = frexp(Dead, iv2); 104 // Color = v; 105 // } 106 107 const std::string predefs1 = 108 R"(OpCapability Shader 109%1 = OpExtInstImport "GLSL.std.450" 110OpMemoryModel Logical GLSL450 111OpEntryPoint Fragment %main "main" %BaseColor %Dead %iv2 %Color 112OpExecutionMode %main OriginUpperLeft 113OpSource GLSL 450 114)"; 115 116 const std::string names_before = 117 R"(OpName %main "main" 118OpName %v "v" 119OpName %BaseColor "BaseColor" 120OpName %dv "dv" 121OpName %Dead "Dead" 122OpName %iv2 "iv2" 123OpName %ResType "ResType" 124OpName %Color "Color" 125)"; 126 127 const std::string names_after = 128 R"(OpName %main "main" 129OpName %v "v" 130OpName %BaseColor "BaseColor" 131OpName %Dead "Dead" 132OpName %iv2 "iv2" 133OpName %Color "Color" 134)"; 135 136 const std::string predefs2_before = 137 R"(%void = OpTypeVoid 138%11 = OpTypeFunction %void 139%float = OpTypeFloat 32 140%v4float = OpTypeVector %float 4 141%_ptr_Function_v4float = OpTypePointer Function %v4float 142%_ptr_Input_v4float = OpTypePointer Input %v4float 143%BaseColor = OpVariable %_ptr_Input_v4float Input 144%Dead = OpVariable %_ptr_Input_v4float Input 145%int = OpTypeInt 32 1 146%v4int = OpTypeVector %int 4 147%_ptr_Output_v4int = OpTypePointer Output %v4int 148%iv2 = OpVariable %_ptr_Output_v4int Output 149%ResType = OpTypeStruct %v4float %v4int 150%_ptr_Output_v4float = OpTypePointer Output %v4float 151%Color = OpVariable %_ptr_Output_v4float Output 152)"; 153 154 const std::string predefs2_after = 155 R"(%void = OpTypeVoid 156%11 = OpTypeFunction %void 157%float = OpTypeFloat 32 158%v4float = OpTypeVector %float 4 159%_ptr_Function_v4float = OpTypePointer Function %v4float 160%_ptr_Input_v4float = OpTypePointer Input %v4float 161%BaseColor = OpVariable %_ptr_Input_v4float Input 162%Dead = OpVariable %_ptr_Input_v4float Input 163%int = OpTypeInt 32 1 164%v4int = OpTypeVector %int 4 165%_ptr_Output_v4int = OpTypePointer Output %v4int 166%iv2 = OpVariable %_ptr_Output_v4int Output 167%_ptr_Output_v4float = OpTypePointer Output %v4float 168%Color = OpVariable %_ptr_Output_v4float Output 169)"; 170 171 const std::string func_before = 172 R"(%main = OpFunction %void None %11 173%20 = OpLabel 174%v = OpVariable %_ptr_Function_v4float Function 175%dv = OpVariable %_ptr_Function_v4float Function 176%21 = OpLoad %v4float %BaseColor 177OpStore %v %21 178%22 = OpLoad %v4float %Dead 179%23 = OpExtInst %v4float %1 Frexp %22 %iv2 180OpStore %dv %23 181%24 = OpLoad %v4float %v 182OpStore %Color %24 183OpReturn 184OpFunctionEnd 185)"; 186 187 const std::string func_after = 188 R"(%main = OpFunction %void None %11 189%20 = OpLabel 190%v = OpVariable %_ptr_Function_v4float Function 191%21 = OpLoad %v4float %BaseColor 192OpStore %v %21 193%22 = OpLoad %v4float %Dead 194%23 = OpExtInst %v4float %1 Frexp %22 %iv2 195%24 = OpLoad %v4float %v 196OpStore %Color %24 197OpReturn 198OpFunctionEnd 199)"; 200 201 SinglePassRunAndCheck<AggressiveDCEPass>( 202 predefs1 + names_before + predefs2_before + func_before, 203 predefs1 + names_after + predefs2_after + func_after, true, true); 204} 205 206TEST_F(AggressiveDCETest, EliminateDecorate) { 207 // Note: The SPIR-V was hand-edited to add the OpDecorate 208 // 209 // #version 140 210 // 211 // in vec4 BaseColor; 212 // in vec4 Dead; 213 // 214 // void main() 215 // { 216 // vec4 v = BaseColor; 217 // vec4 dv = Dead * 0.5; 218 // gl_FragColor = v; 219 // } 220 221 const std::string spirv = 222 R"( 223OpCapability Shader 224%1 = OpExtInstImport "GLSL.std.450" 225OpMemoryModel Logical GLSL450 226OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor 227OpExecutionMode %main OriginUpperLeft 228OpSource GLSL 140 229OpName %main "main" 230OpName %v "v" 231OpName %BaseColor "BaseColor" 232OpName %dv "dv" 233OpName %Dead "Dead" 234OpName %gl_FragColor "gl_FragColor" 235; CHECK-NOT: OpDecorate 236OpDecorate %8 RelaxedPrecision 237%void = OpTypeVoid 238%10 = OpTypeFunction %void 239%float = OpTypeFloat 32 240%v4float = OpTypeVector %float 4 241%_ptr_Function_v4float = OpTypePointer Function %v4float 242%_ptr_Input_v4float = OpTypePointer Input %v4float 243%BaseColor = OpVariable %_ptr_Input_v4float Input 244%Dead = OpVariable %_ptr_Input_v4float Input 245%float_0_5 = OpConstant %float 0.5 246%_ptr_Output_v4float = OpTypePointer Output %v4float 247%gl_FragColor = OpVariable %_ptr_Output_v4float Output 248%main = OpFunction %void None %10 249%17 = OpLabel 250%v = OpVariable %_ptr_Function_v4float Function 251%dv = OpVariable %_ptr_Function_v4float Function 252%18 = OpLoad %v4float %BaseColor 253OpStore %v %18 254%19 = OpLoad %v4float %Dead 255; CHECK-NOT: OpVectorTimesScalar 256%8 = OpVectorTimesScalar %v4float %19 %float_0_5 257OpStore %dv %8 258%20 = OpLoad %v4float %v 259OpStore %gl_FragColor %20 260OpReturn 261OpFunctionEnd 262)"; 263 264 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 265} 266 267TEST_F(AggressiveDCETest, Simple) { 268 // #version 140 269 // 270 // in vec4 BaseColor; 271 // in vec4 Dead; 272 // 273 // void main() 274 // { 275 // vec4 v = BaseColor; 276 // vec4 dv = Dead; 277 // gl_FragColor = v; 278 // } 279 280 const std::string spirv = 281 R"( 282OpCapability Shader 283%1 = OpExtInstImport "GLSL.std.450" 284OpMemoryModel Logical GLSL450 285; CHECK: OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 286OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor 287OpExecutionMode %main OriginUpperLeft 288OpSource GLSL 140 289OpName %main "main" 290OpName %v "v" 291OpName %BaseColor "BaseColor" 292; CHECK-NOT: OpName %dv "dv" 293OpName %dv "dv" 294; CHECK-NOT: OpName %Dead "Dead" 295OpName %Dead "Dead" 296OpName %gl_FragColor "gl_FragColor" 297%void = OpTypeVoid 298%9 = OpTypeFunction %void 299%float = OpTypeFloat 32 300%v4float = OpTypeVector %float 4 301%_ptr_Function_v4float = OpTypePointer Function %v4float 302%_ptr_Input_v4float = OpTypePointer Input %v4float 303%BaseColor = OpVariable %_ptr_Input_v4float Input 304; CHECK-NOT: %Dead = OpVariable 305%Dead = OpVariable %_ptr_Input_v4float Input 306%_ptr_Output_v4float = OpTypePointer Output %v4float 307%gl_FragColor = OpVariable %_ptr_Output_v4float Output 308%main = OpFunction %void None %9 309%15 = OpLabel 310%v = OpVariable %_ptr_Function_v4float Function 311; CHECK-NOT: %dv = OpVariable 312%dv = OpVariable %_ptr_Function_v4float Function 313%16 = OpLoad %v4float %BaseColor 314OpStore %v %16 315; CHECK-NOT: OpLoad %v4float %Dead 316%17 = OpLoad %v4float %Dead 317; CHECK-NOT: OpStore %dv 318OpStore %dv %17 319%18 = OpLoad %v4float %v 320OpStore %gl_FragColor %18 321OpReturn 322OpFunctionEnd 323)"; 324 325 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 326} 327 328TEST_F(AggressiveDCETest, OptAllowListExtension) { 329 // #version 140 330 // 331 // in vec4 BaseColor; 332 // in vec4 Dead; 333 // 334 // void main() 335 // { 336 // vec4 v = BaseColor; 337 // vec4 dv = Dead; 338 // gl_FragColor = v; 339 // } 340 341 const std::string spirv = 342 R"(OpCapability Shader 343OpExtension "SPV_AMD_gpu_shader_int16" 344%1 = OpExtInstImport "GLSL.std.450" 345OpMemoryModel Logical GLSL450 346; CHECK: OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 347OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor 348OpExecutionMode %main OriginUpperLeft 349OpSource GLSL 140 350OpName %main "main" 351OpName %v "v" 352OpName %BaseColor "BaseColor" 353OpName %dv "dv" 354OpName %Dead "Dead" 355OpName %gl_FragColor "gl_FragColor" 356%void = OpTypeVoid 357%9 = OpTypeFunction %void 358%float = OpTypeFloat 32 359%v4float = OpTypeVector %float 4 360%_ptr_Function_v4float = OpTypePointer Function %v4float 361%_ptr_Input_v4float = OpTypePointer Input %v4float 362%BaseColor = OpVariable %_ptr_Input_v4float Input 363%Dead = OpVariable %_ptr_Input_v4float Input 364%_ptr_Output_v4float = OpTypePointer Output %v4float 365%gl_FragColor = OpVariable %_ptr_Output_v4float Output 366%main = OpFunction %void None %9 367%15 = OpLabel 368%v = OpVariable %_ptr_Function_v4float Function 369%dv = OpVariable %_ptr_Function_v4float Function 370%16 = OpLoad %v4float %BaseColor 371OpStore %v %16 372%17 = OpLoad %v4float %Dead 373OpStore %dv %17 374%18 = OpLoad %v4float %v 375OpStore %gl_FragColor %18 376OpReturn 377OpFunctionEnd 378)"; 379 380 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 381} 382 383TEST_F(AggressiveDCETest, NoOptDenyListExtension) { 384 // #version 140 385 // 386 // in vec4 BaseColor; 387 // in vec4 Dead; 388 // 389 // void main() 390 // { 391 // vec4 v = BaseColor; 392 // vec4 dv = Dead; 393 // gl_FragColor = v; 394 // } 395 396 const std::string assembly = 397 R"(OpCapability Shader 398OpExtension "SPV_KHR_variable_pointers" 399%1 = OpExtInstImport "GLSL.std.450" 400OpMemoryModel Logical GLSL450 401OpEntryPoint Fragment %main "main" %BaseColor %Dead %gl_FragColor 402OpExecutionMode %main OriginUpperLeft 403OpSource GLSL 140 404OpName %main "main" 405OpName %v "v" 406OpName %BaseColor "BaseColor" 407OpName %dv "dv" 408OpName %Dead "Dead" 409OpName %gl_FragColor "gl_FragColor" 410%void = OpTypeVoid 411%9 = OpTypeFunction %void 412%float = OpTypeFloat 32 413%v4float = OpTypeVector %float 4 414%_ptr_Function_v4float = OpTypePointer Function %v4float 415%_ptr_Input_v4float = OpTypePointer Input %v4float 416%BaseColor = OpVariable %_ptr_Input_v4float Input 417%Dead = OpVariable %_ptr_Input_v4float Input 418%_ptr_Output_v4float = OpTypePointer Output %v4float 419%gl_FragColor = OpVariable %_ptr_Output_v4float Output 420%main = OpFunction %void None %9 421%15 = OpLabel 422%v = OpVariable %_ptr_Function_v4float Function 423%dv = OpVariable %_ptr_Function_v4float Function 424%16 = OpLoad %v4float %BaseColor 425OpStore %v %16 426%17 = OpLoad %v4float %Dead 427OpStore %dv %17 428%18 = OpLoad %v4float %v 429OpStore %gl_FragColor %18 430OpReturn 431OpFunctionEnd 432)"; 433 434 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 435} 436 437TEST_F(AggressiveDCETest, ElimWithCall) { 438 // This demonstrates that "dead" function calls are not eliminated. 439 // Also demonstrates that DCE will happen in presence of function call. 440 // #version 140 441 // in vec4 i1; 442 // in vec4 i2; 443 // 444 // void nothing(vec4 v) 445 // { 446 // } 447 // 448 // void main() 449 // { 450 // vec4 v1 = i1; 451 // vec4 v2 = i2; 452 // nothing(v1); 453 // gl_FragColor = vec4(0.0); 454 // } 455 456 const std::string text = 457 R"( OpCapability Shader 458%1 = OpExtInstImport "GLSL.std.450" 459OpMemoryModel Logical GLSL450 460OpEntryPoint Fragment %main "main" %i1 %i2 %gl_FragColor 461OpExecutionMode %main OriginUpperLeft 462OpSource GLSL 140 463OpName %main "main" 464OpName %nothing_vf4_ "nothing(vf4;" 465OpName %v "v" 466OpName %v1 "v1" 467OpName %i1 "i1" 468OpName %v2 "v2" 469OpName %i2 "i2" 470OpName %param "param" 471OpName %gl_FragColor "gl_FragColor" 472%void = OpTypeVoid 473%12 = OpTypeFunction %void 474%float = OpTypeFloat 32 475%v4float = OpTypeVector %float 4 476%_ptr_Function_v4float = OpTypePointer Function %v4float 477%16 = OpTypeFunction %void %_ptr_Function_v4float 478%_ptr_Input_v4float = OpTypePointer Input %v4float 479%i1 = OpVariable %_ptr_Input_v4float Input 480%i2 = OpVariable %_ptr_Input_v4float Input 481%_ptr_Output_v4float = OpTypePointer Output %v4float 482%gl_FragColor = OpVariable %_ptr_Output_v4float Output 483%float_0 = OpConstant %float 0 484%20 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 485%main = OpFunction %void None %12 486%21 = OpLabel 487%v1 = OpVariable %_ptr_Function_v4float Function 488%v2 = OpVariable %_ptr_Function_v4float Function 489%param = OpVariable %_ptr_Function_v4float Function 490%22 = OpLoad %v4float %i1 491OpStore %v1 %22 492; CHECK-NOT: OpLoad %v4float %i2 493%23 = OpLoad %v4float %i2 494; CHECK-NOT: OpStore %v2 495OpStore %v2 %23 496%24 = OpLoad %v4float %v1 497OpStore %param %24 498; CHECK: OpFunctionCall %void %nothing_vf4_ 499%25 = OpFunctionCall %void %nothing_vf4_ %param 500OpStore %gl_FragColor %20 501OpReturn 502OpFunctionEnd 503; CHECK: %nothing_vf4_ = OpFunction 504%nothing_vf4_ = OpFunction %void None %16 505%v = OpFunctionParameter %_ptr_Function_v4float 506%26 = OpLabel 507OpReturn 508OpFunctionEnd 509)"; 510 511 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 512} 513 514TEST_F(AggressiveDCETest, NoParamElim) { 515 // This demonstrates that unused parameters are not eliminated, but 516 // dead uses of them are. 517 // #version 140 518 // 519 // in vec4 BaseColor; 520 // 521 // vec4 foo(vec4 v1, vec4 v2) 522 // { 523 // vec4 t = -v1; 524 // return v2; 525 // } 526 // 527 // void main() 528 // { 529 // vec4 dead; 530 // gl_FragColor = foo(dead, BaseColor); 531 // } 532 533 const std::string defs_before = 534 R"(OpCapability Shader 535%1 = OpExtInstImport "GLSL.std.450" 536OpMemoryModel Logical GLSL450 537OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor 538OpExecutionMode %main OriginUpperLeft 539OpSource GLSL 140 540OpName %main "main" 541OpName %foo_vf4_vf4_ "foo(vf4;vf4;" 542OpName %v1 "v1" 543OpName %v2 "v2" 544OpName %t "t" 545OpName %gl_FragColor "gl_FragColor" 546OpName %dead "dead" 547OpName %BaseColor "BaseColor" 548OpName %param "param" 549OpName %param_0 "param" 550%void = OpTypeVoid 551%13 = OpTypeFunction %void 552%float = OpTypeFloat 32 553%v4float = OpTypeVector %float 4 554%_ptr_Function_v4float = OpTypePointer Function %v4float 555%17 = OpTypeFunction %v4float %_ptr_Function_v4float %_ptr_Function_v4float 556%_ptr_Output_v4float = OpTypePointer Output %v4float 557%gl_FragColor = OpVariable %_ptr_Output_v4float Output 558%_ptr_Input_v4float = OpTypePointer Input %v4float 559%BaseColor = OpVariable %_ptr_Input_v4float Input 560%main = OpFunction %void None %13 561%20 = OpLabel 562%dead = OpVariable %_ptr_Function_v4float Function 563%param = OpVariable %_ptr_Function_v4float Function 564%param_0 = OpVariable %_ptr_Function_v4float Function 565%21 = OpLoad %v4float %dead 566OpStore %param %21 567%22 = OpLoad %v4float %BaseColor 568OpStore %param_0 %22 569%23 = OpFunctionCall %v4float %foo_vf4_vf4_ %param %param_0 570OpStore %gl_FragColor %23 571OpReturn 572OpFunctionEnd 573)"; 574 575 const std::string defs_after = 576 R"(OpCapability Shader 577%1 = OpExtInstImport "GLSL.std.450" 578OpMemoryModel Logical GLSL450 579OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor 580OpExecutionMode %main OriginUpperLeft 581OpSource GLSL 140 582OpName %main "main" 583OpName %foo_vf4_vf4_ "foo(vf4;vf4;" 584OpName %v1 "v1" 585OpName %v2 "v2" 586OpName %gl_FragColor "gl_FragColor" 587OpName %dead "dead" 588OpName %BaseColor "BaseColor" 589OpName %param "param" 590OpName %param_0 "param" 591%void = OpTypeVoid 592%13 = OpTypeFunction %void 593%float = OpTypeFloat 32 594%v4float = OpTypeVector %float 4 595%_ptr_Function_v4float = OpTypePointer Function %v4float 596%17 = OpTypeFunction %v4float %_ptr_Function_v4float %_ptr_Function_v4float 597%_ptr_Output_v4float = OpTypePointer Output %v4float 598%gl_FragColor = OpVariable %_ptr_Output_v4float Output 599%_ptr_Input_v4float = OpTypePointer Input %v4float 600%BaseColor = OpVariable %_ptr_Input_v4float Input 601%main = OpFunction %void None %13 602%20 = OpLabel 603%dead = OpVariable %_ptr_Function_v4float Function 604%param = OpVariable %_ptr_Function_v4float Function 605%param_0 = OpVariable %_ptr_Function_v4float Function 606%21 = OpLoad %v4float %dead 607OpStore %param %21 608%22 = OpLoad %v4float %BaseColor 609OpStore %param_0 %22 610%23 = OpFunctionCall %v4float %foo_vf4_vf4_ %param %param_0 611OpStore %gl_FragColor %23 612OpReturn 613OpFunctionEnd 614)"; 615 616 const std::string func_before = 617 R"(%foo_vf4_vf4_ = OpFunction %v4float None %17 618%v1 = OpFunctionParameter %_ptr_Function_v4float 619%v2 = OpFunctionParameter %_ptr_Function_v4float 620%24 = OpLabel 621%t = OpVariable %_ptr_Function_v4float Function 622%25 = OpLoad %v4float %v1 623%26 = OpFNegate %v4float %25 624OpStore %t %26 625%27 = OpLoad %v4float %v2 626OpReturnValue %27 627OpFunctionEnd 628)"; 629 630 const std::string func_after = 631 R"(%foo_vf4_vf4_ = OpFunction %v4float None %17 632%v1 = OpFunctionParameter %_ptr_Function_v4float 633%v2 = OpFunctionParameter %_ptr_Function_v4float 634%24 = OpLabel 635%27 = OpLoad %v4float %v2 636OpReturnValue %27 637OpFunctionEnd 638)"; 639 640 SinglePassRunAndCheck<AggressiveDCEPass>(defs_before + func_before, 641 defs_after + func_after, true, true); 642} 643 644TEST_F(AggressiveDCETest, ElimOpaque) { 645 // SPIR-V not representable from GLSL; not generatable from HLSL 646 // for the moment. 647 648 const std::string defs_before = 649 R"(OpCapability Shader 650%1 = OpExtInstImport "GLSL.std.450" 651OpMemoryModel Logical GLSL450 652OpEntryPoint Fragment %main "main" %outColor %texCoords 653OpExecutionMode %main OriginUpperLeft 654OpSource GLSL 140 655OpName %main "main" 656OpName %S_t "S_t" 657OpMemberName %S_t 0 "v0" 658OpMemberName %S_t 1 "v1" 659OpMemberName %S_t 2 "smp" 660OpName %outColor "outColor" 661OpName %sampler15 "sampler15" 662OpName %s0 "s0" 663OpName %texCoords "texCoords" 664OpDecorate %sampler15 DescriptorSet 0 665%void = OpTypeVoid 666%9 = OpTypeFunction %void 667%float = OpTypeFloat 32 668%v2float = OpTypeVector %float 2 669%v4float = OpTypeVector %float 4 670%_ptr_Output_v4float = OpTypePointer Output %v4float 671%outColor = OpVariable %_ptr_Output_v4float Output 672%14 = OpTypeImage %float 2D 0 0 0 1 Unknown 673%15 = OpTypeSampledImage %14 674%S_t = OpTypeStruct %v2float %v2float %15 675%_ptr_Function_S_t = OpTypePointer Function %S_t 676%17 = OpTypeFunction %void %_ptr_Function_S_t 677%_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15 678%_ptr_Function_15 = OpTypePointer Function %15 679%sampler15 = OpVariable %_ptr_UniformConstant_15 UniformConstant 680%int = OpTypeInt 32 1 681%int_0 = OpConstant %int 0 682%int_2 = OpConstant %int 2 683%_ptr_Function_v2float = OpTypePointer Function %v2float 684%_ptr_Input_v2float = OpTypePointer Input %v2float 685%texCoords = OpVariable %_ptr_Input_v2float Input 686)"; 687 688 const std::string defs_after = 689 R"(OpCapability Shader 690%1 = OpExtInstImport "GLSL.std.450" 691OpMemoryModel Logical GLSL450 692OpEntryPoint Fragment %main "main" %outColor %texCoords 693OpExecutionMode %main OriginUpperLeft 694OpSource GLSL 140 695OpName %main "main" 696OpName %outColor "outColor" 697OpName %sampler15 "sampler15" 698OpName %texCoords "texCoords" 699OpDecorate %sampler15 DescriptorSet 0 700%void = OpTypeVoid 701%9 = OpTypeFunction %void 702%float = OpTypeFloat 32 703%v2float = OpTypeVector %float 2 704%v4float = OpTypeVector %float 4 705%_ptr_Output_v4float = OpTypePointer Output %v4float 706%outColor = OpVariable %_ptr_Output_v4float Output 707%14 = OpTypeImage %float 2D 0 0 0 1 Unknown 708%15 = OpTypeSampledImage %14 709%_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15 710%sampler15 = OpVariable %_ptr_UniformConstant_15 UniformConstant 711%_ptr_Input_v2float = OpTypePointer Input %v2float 712%texCoords = OpVariable %_ptr_Input_v2float Input 713)"; 714 715 const std::string func_before = 716 R"(%main = OpFunction %void None %9 717%25 = OpLabel 718%s0 = OpVariable %_ptr_Function_S_t Function 719%26 = OpLoad %v2float %texCoords 720%27 = OpLoad %S_t %s0 721%28 = OpCompositeInsert %S_t %26 %27 0 722%29 = OpLoad %15 %sampler15 723%30 = OpCompositeInsert %S_t %29 %28 2 724OpStore %s0 %30 725%31 = OpImageSampleImplicitLod %v4float %29 %26 726OpStore %outColor %31 727OpReturn 728OpFunctionEnd 729)"; 730 731 const std::string func_after = 732 R"(%main = OpFunction %void None %9 733%25 = OpLabel 734%26 = OpLoad %v2float %texCoords 735%29 = OpLoad %15 %sampler15 736%31 = OpImageSampleImplicitLod %v4float %29 %26 737OpStore %outColor %31 738OpReturn 739OpFunctionEnd 740)"; 741 742 SinglePassRunAndCheck<AggressiveDCEPass>(defs_before + func_before, 743 defs_after + func_after, true, true); 744} 745 746TEST_F(AggressiveDCETest, NoParamStoreElim) { 747 // Should not eliminate stores to params 748 // 749 // #version 450 750 // 751 // layout(location = 0) in vec4 BaseColor; 752 // layout(location = 0) out vec4 OutColor; 753 // 754 // void foo(in vec4 v1, out vec4 v2) 755 // { 756 // v2 = -v1; 757 // } 758 // 759 // void main() 760 // { 761 // foo(BaseColor, OutColor); 762 // } 763 764 const std::string assembly = 765 R"(OpCapability Shader 766%1 = OpExtInstImport "GLSL.std.450" 767OpMemoryModel Logical GLSL450 768OpEntryPoint Fragment %main "main" %BaseColor %OutColor 769OpExecutionMode %main OriginUpperLeft 770OpSource GLSL 450 771OpName %main "main" 772OpName %foo_vf4_vf4_ "foo(vf4;vf4;" 773OpName %v1 "v1" 774OpName %v2 "v2" 775OpName %BaseColor "BaseColor" 776OpName %OutColor "OutColor" 777OpName %param "param" 778OpName %param_0 "param" 779OpDecorate %BaseColor Location 0 780OpDecorate %OutColor Location 0 781%void = OpTypeVoid 782%11 = OpTypeFunction %void 783%float = OpTypeFloat 32 784%v4float = OpTypeVector %float 4 785%_ptr_Function_v4float = OpTypePointer Function %v4float 786%15 = OpTypeFunction %void %_ptr_Function_v4float %_ptr_Function_v4float 787%_ptr_Input_v4float = OpTypePointer Input %v4float 788%BaseColor = OpVariable %_ptr_Input_v4float Input 789%_ptr_Output_v4float = OpTypePointer Output %v4float 790%OutColor = OpVariable %_ptr_Output_v4float Output 791%main = OpFunction %void None %11 792%18 = OpLabel 793%param = OpVariable %_ptr_Function_v4float Function 794%param_0 = OpVariable %_ptr_Function_v4float Function 795%19 = OpLoad %v4float %BaseColor 796OpStore %param %19 797%20 = OpFunctionCall %void %foo_vf4_vf4_ %param %param_0 798%21 = OpLoad %v4float %param_0 799OpStore %OutColor %21 800OpReturn 801OpFunctionEnd 802%foo_vf4_vf4_ = OpFunction %void None %15 803%v1 = OpFunctionParameter %_ptr_Function_v4float 804%v2 = OpFunctionParameter %_ptr_Function_v4float 805%22 = OpLabel 806%23 = OpLoad %v4float %v1 807%24 = OpFNegate %v4float %23 808OpStore %v2 %24 809OpReturn 810OpFunctionEnd 811)"; 812 813 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 814} 815 816TEST_F(AggressiveDCETest, PrivateStoreElimInEntryNoCalls) { 817 // Eliminate stores to private in entry point with no calls 818 // Note: Not legal GLSL 819 // 820 // layout(location = 0) in vec4 BaseColor; 821 // layout(location = 1) in vec4 Dead; 822 // layout(location = 0) out vec4 OutColor; 823 // 824 // private vec4 dv; 825 // 826 // void main() 827 // { 828 // vec4 v = BaseColor; 829 // dv = Dead; 830 // OutColor = v; 831 // } 832 833 const std::string spirv = 834 R"(OpCapability Shader 835%1 = OpExtInstImport "GLSL.std.450" 836OpMemoryModel Logical GLSL450 837OpEntryPoint Fragment %main "main" %BaseColor %Dead %OutColor 838OpExecutionMode %main OriginUpperLeft 839OpSource GLSL 450 840OpName %main "main" 841OpName %v "v" 842OpName %BaseColor "BaseColor" 843; CHECK-NOT: OpName %dv "dv" 844OpName %dv "dv" 845OpName %Dead "Dead" 846OpName %OutColor "OutColor" 847OpDecorate %BaseColor Location 0 848OpDecorate %Dead Location 1 849OpDecorate %OutColor Location 0 850%void = OpTypeVoid 851%9 = OpTypeFunction %void 852%float = OpTypeFloat 32 853%v4float = OpTypeVector %float 4 854%_ptr_Function_v4float = OpTypePointer Function %v4float 855; CHECK-NOT: OpTypePointer Private 856%_ptr_Private_v4float = OpTypePointer Private %v4float 857%_ptr_Input_v4float = OpTypePointer Input %v4float 858%BaseColor = OpVariable %_ptr_Input_v4float Input 859%Dead = OpVariable %_ptr_Input_v4float Input 860%_ptr_Output_v4float = OpTypePointer Output %v4float 861; CHECK-NOT: %dv = OpVariable 862%dv = OpVariable %_ptr_Private_v4float Private 863%OutColor = OpVariable %_ptr_Output_v4float Output 864%main = OpFunction %void None %9 865%16 = OpLabel 866%v = OpVariable %_ptr_Function_v4float Function 867%17 = OpLoad %v4float %BaseColor 868OpStore %v %17 869%18 = OpLoad %v4float %Dead 870; CHECK-NOT: OpStore %dv 871OpStore %dv %18 872%19 = OpLoad %v4float %v 873%20 = OpFNegate %v4float %19 874OpStore %OutColor %20 875OpReturn 876OpFunctionEnd 877)"; 878 879 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 880} 881 882TEST_F(AggressiveDCETest, NoPrivateStoreElimIfLoad) { 883 // Should not eliminate stores to private when there is a load 884 // Note: Not legal GLSL 885 // 886 // #version 450 887 // 888 // layout(location = 0) in vec4 BaseColor; 889 // layout(location = 0) out vec4 OutColor; 890 // 891 // private vec4 pv; 892 // 893 // void main() 894 // { 895 // pv = BaseColor; 896 // OutColor = pv; 897 // } 898 899 const std::string assembly = 900 R"(OpCapability Shader 901%1 = OpExtInstImport "GLSL.std.450" 902OpMemoryModel Logical GLSL450 903OpEntryPoint Fragment %main "main" %BaseColor %OutColor 904OpExecutionMode %main OriginUpperLeft 905OpSource GLSL 450 906OpName %main "main" 907OpName %pv "pv" 908OpName %BaseColor "BaseColor" 909OpName %OutColor "OutColor" 910OpDecorate %BaseColor Location 0 911OpDecorate %OutColor Location 0 912%void = OpTypeVoid 913%7 = OpTypeFunction %void 914%float = OpTypeFloat 32 915%v4float = OpTypeVector %float 4 916%_ptr_Private_v4float = OpTypePointer Private %v4float 917%_ptr_Input_v4float = OpTypePointer Input %v4float 918%BaseColor = OpVariable %_ptr_Input_v4float Input 919%_ptr_Output_v4float = OpTypePointer Output %v4float 920%OutColor = OpVariable %_ptr_Output_v4float Output 921%pv = OpVariable %_ptr_Private_v4float Private 922%main = OpFunction %void None %7 923%13 = OpLabel 924%14 = OpLoad %v4float %BaseColor 925OpStore %pv %14 926%15 = OpLoad %v4float %pv 927%16 = OpFNegate %v4float %15 928OpStore %OutColor %16 929OpReturn 930OpFunctionEnd 931)"; 932 933 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 934} 935 936TEST_F(AggressiveDCETest, NoPrivateStoreElimWithCall) { 937 // Should not eliminate stores to private when function contains call 938 // Note: Not legal GLSL 939 // 940 // #version 450 941 // 942 // layout(location = 0) in vec4 BaseColor; 943 // layout(location = 0) out vec4 OutColor; 944 // 945 // private vec4 v1; 946 // 947 // void foo() 948 // { 949 // OutColor = -v1; 950 // } 951 // 952 // void main() 953 // { 954 // v1 = BaseColor; 955 // foo(); 956 // } 957 958 const std::string assembly = 959 R"(OpCapability Shader 960%1 = OpExtInstImport "GLSL.std.450" 961OpMemoryModel Logical GLSL450 962OpEntryPoint Fragment %main "main" %OutColor %BaseColor 963OpExecutionMode %main OriginUpperLeft 964OpSource GLSL 450 965OpName %main "main" 966OpName %foo_ "foo(" 967OpName %OutColor "OutColor" 968OpName %v1 "v1" 969OpName %BaseColor "BaseColor" 970OpDecorate %OutColor Location 0 971OpDecorate %BaseColor Location 0 972%void = OpTypeVoid 973%8 = OpTypeFunction %void 974%float = OpTypeFloat 32 975%v4float = OpTypeVector %float 4 976%_ptr_Output_v4float = OpTypePointer Output %v4float 977%OutColor = OpVariable %_ptr_Output_v4float Output 978%_ptr_Private_v4float = OpTypePointer Private %v4float 979%_ptr_Input_v4float = OpTypePointer Input %v4float 980%v1 = OpVariable %_ptr_Private_v4float Private 981%BaseColor = OpVariable %_ptr_Input_v4float Input 982%main = OpFunction %void None %8 983%14 = OpLabel 984%15 = OpLoad %v4float %BaseColor 985OpStore %v1 %15 986%16 = OpFunctionCall %void %foo_ 987OpReturn 988OpFunctionEnd 989%foo_ = OpFunction %void None %8 990%17 = OpLabel 991%18 = OpLoad %v4float %v1 992%19 = OpFNegate %v4float %18 993OpStore %OutColor %19 994OpReturn 995OpFunctionEnd 996)"; 997 998 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 999} 1000 1001TEST_F(AggressiveDCETest, NoPrivateStoreElimInNonEntry) { 1002 // Should not eliminate stores to private when function is not entry point 1003 // Note: Not legal GLSL 1004 // 1005 // #version 450 1006 // 1007 // layout(location = 0) in vec4 BaseColor; 1008 // layout(location = 0) out vec4 OutColor; 1009 // 1010 // private vec4 v1; 1011 // 1012 // void foo() 1013 // { 1014 // v1 = BaseColor; 1015 // } 1016 // 1017 // void main() 1018 // { 1019 // foo(); 1020 // OutColor = -v1; 1021 // } 1022 1023 const std::string assembly = 1024 R"(OpCapability Shader 1025%1 = OpExtInstImport "GLSL.std.450" 1026OpMemoryModel Logical GLSL450 1027OpEntryPoint Fragment %main "main" %BaseColor %OutColor 1028OpExecutionMode %main OriginUpperLeft 1029OpSource GLSL 450 1030OpName %main "main" 1031OpName %foo_ "foo(" 1032OpName %v1 "v1" 1033OpName %BaseColor "BaseColor" 1034OpName %OutColor "OutColor" 1035OpDecorate %BaseColor Location 0 1036OpDecorate %OutColor Location 0 1037%void = OpTypeVoid 1038%8 = OpTypeFunction %void 1039%float = OpTypeFloat 32 1040%v4float = OpTypeVector %float 4 1041%_ptr_Private_v4float = OpTypePointer Private %v4float 1042%_ptr_Input_v4float = OpTypePointer Input %v4float 1043%BaseColor = OpVariable %_ptr_Input_v4float Input 1044%_ptr_Output_v4float = OpTypePointer Output %v4float 1045%v1 = OpVariable %_ptr_Private_v4float Private 1046%OutColor = OpVariable %_ptr_Output_v4float Output 1047%main = OpFunction %void None %8 1048%14 = OpLabel 1049%15 = OpFunctionCall %void %foo_ 1050%16 = OpLoad %v4float %v1 1051%17 = OpFNegate %v4float %16 1052OpStore %OutColor %17 1053OpReturn 1054OpFunctionEnd 1055%foo_ = OpFunction %void None %8 1056%18 = OpLabel 1057%19 = OpLoad %v4float %BaseColor 1058OpStore %v1 %19 1059OpReturn 1060OpFunctionEnd 1061)"; 1062 1063 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 1064} 1065 1066TEST_F(AggressiveDCETest, WorkgroupStoreElimInEntryNoCalls) { 1067 // Eliminate stores to private in entry point with no calls 1068 // Note: Not legal GLSL 1069 // 1070 // layout(location = 0) in vec4 BaseColor; 1071 // layout(location = 1) in vec4 Dead; 1072 // layout(location = 0) out vec4 OutColor; 1073 // 1074 // workgroup vec4 dv; 1075 // 1076 // void main() 1077 // { 1078 // vec4 v = BaseColor; 1079 // dv = Dead; 1080 // OutColor = v; 1081 // } 1082 1083 const std::string spirv = 1084 R"(OpCapability Shader 1085%1 = OpExtInstImport "GLSL.std.450" 1086OpMemoryModel Logical GLSL450 1087OpEntryPoint Fragment %main "main" %BaseColor %Dead %OutColor 1088OpExecutionMode %main OriginUpperLeft 1089OpSource GLSL 450 1090OpName %main "main" 1091OpName %v "v" 1092OpName %BaseColor "BaseColor" 1093; CHECK-NOT: OpName %dv "dv" 1094OpName %dv "dv" 1095OpName %Dead "Dead" 1096OpName %OutColor "OutColor" 1097OpDecorate %BaseColor Location 0 1098OpDecorate %Dead Location 1 1099OpDecorate %OutColor Location 0 1100%void = OpTypeVoid 1101%9 = OpTypeFunction %void 1102%float = OpTypeFloat 32 1103%v4float = OpTypeVector %float 4 1104%_ptr_Function_v4float = OpTypePointer Function %v4float 1105; CHECK-NOT: OpTypePointer Workgroup 1106%_ptr_Workgroup_v4float = OpTypePointer Workgroup %v4float 1107%_ptr_Input_v4float = OpTypePointer Input %v4float 1108%BaseColor = OpVariable %_ptr_Input_v4float Input 1109%Dead = OpVariable %_ptr_Input_v4float Input 1110%_ptr_Output_v4float = OpTypePointer Output %v4float 1111; CHECK-NOT: %dv = OpVariable 1112%dv = OpVariable %_ptr_Workgroup_v4float Workgroup 1113%OutColor = OpVariable %_ptr_Output_v4float Output 1114%main = OpFunction %void None %9 1115%16 = OpLabel 1116%v = OpVariable %_ptr_Function_v4float Function 1117%17 = OpLoad %v4float %BaseColor 1118OpStore %v %17 1119%18 = OpLoad %v4float %Dead 1120; CHECK-NOT: OpStore %dv 1121OpStore %dv %18 1122%19 = OpLoad %v4float %v 1123%20 = OpFNegate %v4float %19 1124OpStore %OutColor %20 1125OpReturn 1126OpFunctionEnd 1127)"; 1128 1129 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 1130} 1131 1132TEST_F(AggressiveDCETest, EliminateDeadIfThenElse) { 1133 // #version 450 1134 // 1135 // layout(location = 0) in vec4 BaseColor; 1136 // layout(location = 0) out vec4 OutColor; 1137 // 1138 // void main() 1139 // { 1140 // float d; 1141 // if (BaseColor.x == 0) 1142 // d = BaseColor.y; 1143 // else 1144 // d = BaseColor.z; 1145 // OutColor = vec4(1.0,1.0,1.0,1.0); 1146 // } 1147 1148 const std::string spirv = 1149 R"(OpCapability Shader 1150%1 = OpExtInstImport "GLSL.std.450" 1151OpMemoryModel Logical GLSL450 1152OpEntryPoint Fragment %main "main" %BaseColor %OutColor 1153OpExecutionMode %main OriginUpperLeft 1154OpSource GLSL 450 1155OpName %main "main" 1156OpName %BaseColor "BaseColor" 1157OpName %d "d" 1158OpName %OutColor "OutColor" 1159OpDecorate %BaseColor Location 0 1160OpDecorate %OutColor Location 0 1161%void = OpTypeVoid 1162%7 = OpTypeFunction %void 1163%float = OpTypeFloat 32 1164%v4float = OpTypeVector %float 4 1165%_ptr_Input_v4float = OpTypePointer Input %v4float 1166%BaseColor = OpVariable %_ptr_Input_v4float Input 1167%uint = OpTypeInt 32 0 1168%uint_0 = OpConstant %uint 0 1169%_ptr_Input_float = OpTypePointer Input %float 1170%float_0 = OpConstant %float 0 1171%bool = OpTypeBool 1172%_ptr_Function_float = OpTypePointer Function %float 1173%uint_1 = OpConstant %uint 1 1174%uint_2 = OpConstant %uint 2 1175%_ptr_Output_v4float = OpTypePointer Output %v4float 1176%OutColor = OpVariable %_ptr_Output_v4float Output 1177%float_1 = OpConstant %float 1 1178%21 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 1179; CHECK: = OpFunction %void 1180; CHECK-NEXT: %22 = OpLabel 1181; CHECK-NEXT: OpBranch %26 1182; CHECK-NEXT: %26 = OpLabel 1183%main = OpFunction %void None %7 1184%22 = OpLabel 1185%d = OpVariable %_ptr_Function_float Function 1186%23 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 1187%24 = OpLoad %float %23 1188%25 = OpFOrdEqual %bool %24 %float_0 1189OpSelectionMerge %26 None 1190OpBranchConditional %25 %27 %28 1191%27 = OpLabel 1192%29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 1193%30 = OpLoad %float %29 1194OpStore %d %30 1195OpBranch %26 1196%28 = OpLabel 1197%31 = OpAccessChain %_ptr_Input_float %BaseColor %uint_2 1198%32 = OpLoad %float %31 1199OpStore %d %32 1200OpBranch %26 1201%26 = OpLabel 1202OpStore %OutColor %21 1203OpReturn 1204OpFunctionEnd 1205)"; 1206 1207 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 1208} 1209 1210TEST_F(AggressiveDCETest, EliminateDeadIfThen) { 1211 // #version 450 1212 // 1213 // layout(location = 0) in vec4 BaseColor; 1214 // layout(location = 0) out vec4 OutColor; 1215 // 1216 // void main() 1217 // { 1218 // float d; 1219 // if (BaseColor.x == 0) 1220 // d = BaseColor.y; 1221 // OutColor = vec4(1.0,1.0,1.0,1.0); 1222 // } 1223 1224 const std::string spirv = 1225 R"(OpCapability Shader 1226%1 = OpExtInstImport "GLSL.std.450" 1227OpMemoryModel Logical GLSL450 1228OpEntryPoint Fragment %main "main" %BaseColor %OutColor 1229OpExecutionMode %main OriginUpperLeft 1230OpSource GLSL 450 1231OpName %main "main" 1232OpName %BaseColor "BaseColor" 1233OpName %d "d" 1234OpName %OutColor "OutColor" 1235OpDecorate %BaseColor Location 0 1236OpDecorate %OutColor Location 0 1237%void = OpTypeVoid 1238%7 = OpTypeFunction %void 1239%float = OpTypeFloat 32 1240%v4float = OpTypeVector %float 4 1241%_ptr_Input_v4float = OpTypePointer Input %v4float 1242%BaseColor = OpVariable %_ptr_Input_v4float Input 1243%uint = OpTypeInt 32 0 1244%uint_0 = OpConstant %uint 0 1245%_ptr_Input_float = OpTypePointer Input %float 1246%float_0 = OpConstant %float 0 1247%bool = OpTypeBool 1248%_ptr_Function_float = OpTypePointer Function %float 1249%uint_1 = OpConstant %uint 1 1250%_ptr_Output_v4float = OpTypePointer Output %v4float 1251%OutColor = OpVariable %_ptr_Output_v4float Output 1252%float_1 = OpConstant %float 1 1253%20 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 1254; CHECK: = OpFunction 1255; CHECK-NEXT: %21 = OpLabel 1256; CHECK-NEXT: OpBranch [[target:%\w+]] 1257; CHECK-NEXT: [[target]] = OpLabel 1258%main = OpFunction %void None %7 1259%21 = OpLabel 1260%d = OpVariable %_ptr_Function_float Function 1261%22 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 1262%23 = OpLoad %float %22 1263%24 = OpFOrdEqual %bool %23 %float_0 1264OpSelectionMerge %25 None 1265OpBranchConditional %24 %26 %25 1266%26 = OpLabel 1267%27 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 1268%28 = OpLoad %float %27 1269OpStore %d %28 1270OpBranch %25 1271%25 = OpLabel 1272OpStore %OutColor %20 1273OpReturn 1274OpFunctionEnd 1275)"; 1276 1277 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 1278} 1279 1280TEST_F(AggressiveDCETest, EliminateDeadSwitch) { 1281 // #version 450 1282 // 1283 // layout(location = 0) in vec4 BaseColor; 1284 // layout(location = 1) in flat int x; 1285 // layout(location = 0) out vec4 OutColor; 1286 // 1287 // void main() 1288 // { 1289 // float d; 1290 // switch (x) { 1291 // case 0: 1292 // d = BaseColor.y; 1293 // } 1294 // OutColor = vec4(1.0,1.0,1.0,1.0); 1295 // } 1296 const std::string spirv = 1297 R"(OpCapability Shader 1298 %1 = OpExtInstImport "GLSL.std.450" 1299 OpMemoryModel Logical GLSL450 1300 OpEntryPoint Fragment %main "main" %x %BaseColor %OutColor 1301 OpExecutionMode %main OriginUpperLeft 1302 OpSource GLSL 450 1303 OpName %main "main" 1304 OpName %x "x" 1305 OpName %d "d" 1306 OpName %BaseColor "BaseColor" 1307 OpName %OutColor "OutColor" 1308 OpDecorate %x Flat 1309 OpDecorate %x Location 1 1310 OpDecorate %BaseColor Location 0 1311 OpDecorate %OutColor Location 0 1312 %void = OpTypeVoid 1313 %3 = OpTypeFunction %void 1314 %int = OpTypeInt 32 1 1315%_ptr_Input_int = OpTypePointer Input %int 1316 %x = OpVariable %_ptr_Input_int Input 1317 %float = OpTypeFloat 32 1318%_ptr_Function_float = OpTypePointer Function %float 1319 %v4float = OpTypeVector %float 4 1320%_ptr_Input_v4float = OpTypePointer Input %v4float 1321 %BaseColor = OpVariable %_ptr_Input_v4float Input 1322 %uint = OpTypeInt 32 0 1323 %uint_1 = OpConstant %uint 1 1324%_ptr_Input_float = OpTypePointer Input %float 1325%_ptr_Output_v4float = OpTypePointer Output %v4float 1326 %OutColor = OpVariable %_ptr_Output_v4float Output 1327 %float_1 = OpConstant %float 1 1328 %27 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 1329; CHECK: = OpFunction 1330; CHECK-NEXT: = OpLabel 1331; CHECK-NEXT: OpBranch [[target:%\w+]] 1332; CHECK-NEXT: [[target]] = OpLabel 1333 %main = OpFunction %void None %3 1334 %5 = OpLabel 1335 %d = OpVariable %_ptr_Function_float Function 1336 %9 = OpLoad %int %x 1337 OpSelectionMerge %11 None 1338 OpSwitch %9 %11 0 %10 1339 %10 = OpLabel 1340 %21 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 1341 %22 = OpLoad %float %21 1342 OpStore %d %22 1343 OpBranch %11 1344 %11 = OpLabel 1345 OpStore %OutColor %27 1346 OpReturn 1347 OpFunctionEnd)"; 1348 1349 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 1350} 1351 1352TEST_F(AggressiveDCETest, EliminateDeadIfThenElseNested) { 1353 // #version 450 1354 // 1355 // layout(location = 0) in vec4 BaseColor; 1356 // layout(location = 0) out vec4 OutColor; 1357 // 1358 // void main() 1359 // { 1360 // float d; 1361 // if (BaseColor.x == 0) 1362 // if (BaseColor.y == 0) 1363 // d = 0.0; 1364 // else 1365 // d = 0.25; 1366 // else 1367 // if (BaseColor.y == 0) 1368 // d = 0.5; 1369 // else 1370 // d = 0.75; 1371 // OutColor = vec4(1.0,1.0,1.0,1.0); 1372 // } 1373 1374 const std::string spirv = 1375 R"(OpCapability Shader 1376%1 = OpExtInstImport "GLSL.std.450" 1377OpMemoryModel Logical GLSL450 1378OpEntryPoint Fragment %main "main" %BaseColor %OutColor 1379OpExecutionMode %main OriginUpperLeft 1380OpSource GLSL 450 1381OpName %main "main" 1382OpName %BaseColor "BaseColor" 1383OpName %d "d" 1384OpName %OutColor "OutColor" 1385OpDecorate %BaseColor Location 0 1386OpDecorate %OutColor Location 0 1387%void = OpTypeVoid 1388%7 = OpTypeFunction %void 1389%float = OpTypeFloat 32 1390%v4float = OpTypeVector %float 4 1391%_ptr_Input_v4float = OpTypePointer Input %v4float 1392%BaseColor = OpVariable %_ptr_Input_v4float Input 1393%uint = OpTypeInt 32 0 1394%uint_0 = OpConstant %uint 0 1395%_ptr_Input_float = OpTypePointer Input %float 1396%float_0 = OpConstant %float 0 1397%bool = OpTypeBool 1398%uint_1 = OpConstant %uint 1 1399%_ptr_Function_float = OpTypePointer Function %float 1400%float_0_25 = OpConstant %float 0.25 1401%float_0_5 = OpConstant %float 0.5 1402%float_0_75 = OpConstant %float 0.75 1403%_ptr_Output_v4float = OpTypePointer Output %v4float 1404%OutColor = OpVariable %_ptr_Output_v4float Output 1405%float_1 = OpConstant %float 1 1406%23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1 1407 1408; CHECK: = OpFunction 1409; CHECK-NEXT: = OpLabel 1410; CHECK-NEXT: OpBranch [[target:%\w+]] 1411; CHECK-NEXT: [[target]] = OpLabel 1412; CHECK-NOT: OpLabel 1413 1414%main = OpFunction %void None %7 1415%24 = OpLabel 1416%d = OpVariable %_ptr_Function_float Function 1417%25 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 1418%26 = OpLoad %float %25 1419%27 = OpFOrdEqual %bool %26 %float_0 1420OpSelectionMerge %28 None 1421OpBranchConditional %27 %29 %30 1422%29 = OpLabel 1423%31 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 1424%32 = OpLoad %float %31 1425%33 = OpFOrdEqual %bool %32 %float_0 1426OpSelectionMerge %34 None 1427OpBranchConditional %33 %35 %36 1428%35 = OpLabel 1429OpStore %d %float_0 1430OpBranch %34 1431%36 = OpLabel 1432OpStore %d %float_0_25 1433OpBranch %34 1434%34 = OpLabel 1435OpBranch %28 1436%30 = OpLabel 1437%37 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 1438%38 = OpLoad %float %37 1439%39 = OpFOrdEqual %bool %38 %float_0 1440OpSelectionMerge %40 None 1441OpBranchConditional %39 %41 %42 1442%41 = OpLabel 1443OpStore %d %float_0_5 1444OpBranch %40 1445%42 = OpLabel 1446OpStore %d %float_0_75 1447OpBranch %40 1448%40 = OpLabel 1449OpBranch %28 1450%28 = OpLabel 1451OpStore %OutColor %23 1452OpReturn 1453OpFunctionEnd 1454)"; 1455 1456 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 1457} 1458 1459TEST_F(AggressiveDCETest, NoEliminateLiveIfThenElse) { 1460 // #version 450 1461 // 1462 // layout(location = 0) in vec4 BaseColor; 1463 // layout(location = 0) out vec4 OutColor; 1464 // 1465 // void main() 1466 // { 1467 // float t; 1468 // if (BaseColor.x == 0) 1469 // t = BaseColor.y; 1470 // else 1471 // t = BaseColor.z; 1472 // OutColor = vec4(t); 1473 // } 1474 1475 const std::string assembly = 1476 R"(OpCapability Shader 1477%1 = OpExtInstImport "GLSL.std.450" 1478OpMemoryModel Logical GLSL450 1479OpEntryPoint Fragment %main "main" %BaseColor %OutColor 1480OpExecutionMode %main OriginUpperLeft 1481OpSource GLSL 450 1482OpName %main "main" 1483OpName %BaseColor "BaseColor" 1484OpName %t "t" 1485OpName %OutColor "OutColor" 1486OpDecorate %BaseColor Location 0 1487OpDecorate %OutColor Location 0 1488%void = OpTypeVoid 1489%7 = OpTypeFunction %void 1490%float = OpTypeFloat 32 1491%v4float = OpTypeVector %float 4 1492%_ptr_Input_v4float = OpTypePointer Input %v4float 1493%BaseColor = OpVariable %_ptr_Input_v4float Input 1494%uint = OpTypeInt 32 0 1495%uint_0 = OpConstant %uint 0 1496%_ptr_Input_float = OpTypePointer Input %float 1497%float_0 = OpConstant %float 0 1498%bool = OpTypeBool 1499%_ptr_Function_float = OpTypePointer Function %float 1500%uint_1 = OpConstant %uint 1 1501%uint_2 = OpConstant %uint 2 1502%_ptr_Output_v4float = OpTypePointer Output %v4float 1503%OutColor = OpVariable %_ptr_Output_v4float Output 1504%main = OpFunction %void None %7 1505%20 = OpLabel 1506%t = OpVariable %_ptr_Function_float Function 1507%21 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 1508%22 = OpLoad %float %21 1509%23 = OpFOrdEqual %bool %22 %float_0 1510OpSelectionMerge %24 None 1511OpBranchConditional %23 %25 %26 1512%25 = OpLabel 1513%27 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 1514%28 = OpLoad %float %27 1515OpStore %t %28 1516OpBranch %24 1517%26 = OpLabel 1518%29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_2 1519%30 = OpLoad %float %29 1520OpStore %t %30 1521OpBranch %24 1522%24 = OpLabel 1523%31 = OpLoad %float %t 1524%32 = OpCompositeConstruct %v4float %31 %31 %31 %31 1525OpStore %OutColor %32 1526OpReturn 1527OpFunctionEnd 1528)"; 1529 1530 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 1531} 1532 1533TEST_F(AggressiveDCETest, NoEliminateLiveIfThenElseNested) { 1534 // #version 450 1535 // 1536 // layout(location = 0) in vec4 BaseColor; 1537 // layout(location = 0) out vec4 OutColor; 1538 // 1539 // void main() 1540 // { 1541 // float t; 1542 // if (BaseColor.x == 0) 1543 // if (BaseColor.y == 0) 1544 // t = 0.0; 1545 // else 1546 // t = 0.25; 1547 // else 1548 // if (BaseColor.y == 0) 1549 // t = 0.5; 1550 // else 1551 // t = 0.75; 1552 // OutColor = vec4(t); 1553 // } 1554 1555 const std::string assembly = 1556 R"(OpCapability Shader 1557%1 = OpExtInstImport "GLSL.std.450" 1558OpMemoryModel Logical GLSL450 1559OpEntryPoint Fragment %main "main" %BaseColor %OutColor 1560OpExecutionMode %main OriginUpperLeft 1561OpSource GLSL 450 1562OpName %main "main" 1563OpName %BaseColor "BaseColor" 1564OpName %t "t" 1565OpName %OutColor "OutColor" 1566OpDecorate %BaseColor Location 0 1567OpDecorate %OutColor Location 0 1568%void = OpTypeVoid 1569%7 = OpTypeFunction %void 1570%float = OpTypeFloat 32 1571%v4float = OpTypeVector %float 4 1572%_ptr_Input_v4float = OpTypePointer Input %v4float 1573%BaseColor = OpVariable %_ptr_Input_v4float Input 1574%uint = OpTypeInt 32 0 1575%uint_0 = OpConstant %uint 0 1576%_ptr_Input_float = OpTypePointer Input %float 1577%float_0 = OpConstant %float 0 1578%bool = OpTypeBool 1579%uint_1 = OpConstant %uint 1 1580%_ptr_Function_float = OpTypePointer Function %float 1581%float_0_25 = OpConstant %float 0.25 1582%float_0_5 = OpConstant %float 0.5 1583%float_0_75 = OpConstant %float 0.75 1584%_ptr_Output_v4float = OpTypePointer Output %v4float 1585%OutColor = OpVariable %_ptr_Output_v4float Output 1586%main = OpFunction %void None %7 1587%22 = OpLabel 1588%t = OpVariable %_ptr_Function_float Function 1589%23 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 1590%24 = OpLoad %float %23 1591%25 = OpFOrdEqual %bool %24 %float_0 1592OpSelectionMerge %26 None 1593OpBranchConditional %25 %27 %28 1594%27 = OpLabel 1595%29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 1596%30 = OpLoad %float %29 1597%31 = OpFOrdEqual %bool %30 %float_0 1598OpSelectionMerge %32 None 1599OpBranchConditional %31 %33 %34 1600%33 = OpLabel 1601OpStore %t %float_0 1602OpBranch %32 1603%34 = OpLabel 1604OpStore %t %float_0_25 1605OpBranch %32 1606%32 = OpLabel 1607OpBranch %26 1608%28 = OpLabel 1609%35 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 1610%36 = OpLoad %float %35 1611%37 = OpFOrdEqual %bool %36 %float_0 1612OpSelectionMerge %38 None 1613OpBranchConditional %37 %39 %40 1614%39 = OpLabel 1615OpStore %t %float_0_5 1616OpBranch %38 1617%40 = OpLabel 1618OpStore %t %float_0_75 1619OpBranch %38 1620%38 = OpLabel 1621OpBranch %26 1622%26 = OpLabel 1623%41 = OpLoad %float %t 1624%42 = OpCompositeConstruct %v4float %41 %41 %41 %41 1625OpStore %OutColor %42 1626OpReturn 1627OpFunctionEnd 1628)"; 1629 1630 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 1631} 1632 1633TEST_F(AggressiveDCETest, NoEliminateIfWithPhi) { 1634 // Note: Assembly hand-optimized from GLSL 1635 // 1636 // #version 450 1637 // 1638 // layout(location = 0) in vec4 BaseColor; 1639 // layout(location = 0) out vec4 OutColor; 1640 // 1641 // void main() 1642 // { 1643 // float t; 1644 // if (BaseColor.x == 0) 1645 // t = 0.0; 1646 // else 1647 // t = 1.0; 1648 // OutColor = vec4(t); 1649 // } 1650 1651 const std::string assembly = 1652 R"(OpCapability Shader 1653%1 = OpExtInstImport "GLSL.std.450" 1654OpMemoryModel Logical GLSL450 1655OpEntryPoint Fragment %main "main" %BaseColor %OutColor 1656OpExecutionMode %main OriginUpperLeft 1657OpSource GLSL 450 1658OpName %main "main" 1659OpName %BaseColor "BaseColor" 1660OpName %OutColor "OutColor" 1661OpDecorate %BaseColor Location 0 1662OpDecorate %OutColor Location 0 1663%void = OpTypeVoid 1664%6 = OpTypeFunction %void 1665%float = OpTypeFloat 32 1666%v4float = OpTypeVector %float 4 1667%_ptr_Input_v4float = OpTypePointer Input %v4float 1668%BaseColor = OpVariable %_ptr_Input_v4float Input 1669%uint = OpTypeInt 32 0 1670%uint_0 = OpConstant %uint 0 1671%_ptr_Input_float = OpTypePointer Input %float 1672%float_0 = OpConstant %float 0 1673%bool = OpTypeBool 1674%float_1 = OpConstant %float 1 1675%_ptr_Output_v4float = OpTypePointer Output %v4float 1676%OutColor = OpVariable %_ptr_Output_v4float Output 1677%main = OpFunction %void None %6 1678%17 = OpLabel 1679%18 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 1680%19 = OpLoad %float %18 1681%20 = OpFOrdEqual %bool %19 %float_0 1682OpSelectionMerge %21 None 1683OpBranchConditional %20 %22 %23 1684%22 = OpLabel 1685OpBranch %21 1686%23 = OpLabel 1687OpBranch %21 1688%21 = OpLabel 1689%24 = OpPhi %float %float_0 %22 %float_1 %23 1690%25 = OpCompositeConstruct %v4float %24 %24 %24 %24 1691OpStore %OutColor %25 1692OpReturn 1693OpFunctionEnd 1694)"; 1695 1696 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 1697} 1698 1699TEST_F(AggressiveDCETest, NoEliminateIfBreak) { 1700 // Note: Assembly optimized from GLSL 1701 // 1702 // #version 450 1703 // 1704 // layout(location=0) in vec4 InColor; 1705 // layout(location=0) out vec4 OutColor; 1706 // 1707 // void main() 1708 // { 1709 // float f = 0.0; 1710 // for (;;) { 1711 // f += 2.0; 1712 // if (f > 20.0) 1713 // break; 1714 // } 1715 // 1716 // OutColor = InColor / f; 1717 // } 1718 1719 const std::string assembly = 1720 R"(OpCapability Shader 1721%1 = OpExtInstImport "GLSL.std.450" 1722OpMemoryModel Logical GLSL450 1723OpEntryPoint Fragment %main "main" %OutColor %InColor 1724OpExecutionMode %main OriginUpperLeft 1725OpSource GLSL 450 1726OpName %main "main" 1727OpName %f "f" 1728OpName %OutColor "OutColor" 1729OpName %InColor "InColor" 1730OpDecorate %OutColor Location 0 1731OpDecorate %InColor Location 0 1732%void = OpTypeVoid 1733%7 = OpTypeFunction %void 1734%float = OpTypeFloat 32 1735%_ptr_Function_float = OpTypePointer Function %float 1736%float_0 = OpConstant %float 0 1737%float_2 = OpConstant %float 2 1738%float_20 = OpConstant %float 20 1739%bool = OpTypeBool 1740%v4float = OpTypeVector %float 4 1741%_ptr_Output_v4float = OpTypePointer Output %v4float 1742%OutColor = OpVariable %_ptr_Output_v4float Output 1743%_ptr_Input_v4float = OpTypePointer Input %v4float 1744%InColor = OpVariable %_ptr_Input_v4float Input 1745%main = OpFunction %void None %7 1746%17 = OpLabel 1747%f = OpVariable %_ptr_Function_float Function 1748OpStore %f %float_0 1749OpBranch %18 1750%18 = OpLabel 1751OpLoopMerge %19 %20 None 1752OpBranch %21 1753%21 = OpLabel 1754%22 = OpLoad %float %f 1755%23 = OpFAdd %float %22 %float_2 1756OpStore %f %23 1757%24 = OpLoad %float %f 1758%25 = OpFOrdGreaterThan %bool %24 %float_20 1759OpSelectionMerge %26 None 1760OpBranchConditional %25 %27 %26 1761%27 = OpLabel 1762OpBranch %19 1763%26 = OpLabel 1764OpBranch %20 1765%20 = OpLabel 1766OpBranch %18 1767%19 = OpLabel 1768%28 = OpLoad %v4float %InColor 1769%29 = OpLoad %float %f 1770%30 = OpCompositeConstruct %v4float %29 %29 %29 %29 1771%31 = OpFDiv %v4float %28 %30 1772OpStore %OutColor %31 1773OpReturn 1774OpFunctionEnd 1775)"; 1776 1777 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 1778} 1779 1780TEST_F(AggressiveDCETest, NoEliminateIfBreak2) { 1781 // Do not eliminate break as conditional branch with merge instruction 1782 // Note: SPIR-V edited to add merge instruction before break. 1783 // 1784 // #version 430 1785 // 1786 // layout(std430) buffer U_t 1787 // { 1788 // float g_F[10]; 1789 // }; 1790 // 1791 // layout(location = 0)out float o; 1792 // 1793 // void main(void) 1794 // { 1795 // float s = 0.0; 1796 // for (int i=0; i<10; i++) 1797 // s += g_F[i]; 1798 // o = s; 1799 // } 1800 1801 const std::string assembly = 1802 R"(OpCapability Shader 1803%1 = OpExtInstImport "GLSL.std.450" 1804OpMemoryModel Logical GLSL450 1805OpEntryPoint Fragment %main "main" %o 1806OpExecutionMode %main OriginUpperLeft 1807OpSource GLSL 430 1808OpName %main "main" 1809OpName %s "s" 1810OpName %i "i" 1811OpName %U_t "U_t" 1812OpMemberName %U_t 0 "g_F" 1813OpName %_ "" 1814OpName %o "o" 1815OpDecorate %_arr_float_uint_10 ArrayStride 4 1816OpMemberDecorate %U_t 0 Offset 0 1817OpDecorate %U_t BufferBlock 1818OpDecorate %_ DescriptorSet 0 1819OpDecorate %o Location 0 1820%void = OpTypeVoid 1821%10 = OpTypeFunction %void 1822%float = OpTypeFloat 32 1823%_ptr_Function_float = OpTypePointer Function %float 1824%float_0 = OpConstant %float 0 1825%int = OpTypeInt 32 1 1826%_ptr_Function_int = OpTypePointer Function %int 1827%int_0 = OpConstant %int 0 1828%int_10 = OpConstant %int 10 1829%bool = OpTypeBool 1830%uint = OpTypeInt 32 0 1831%uint_10 = OpConstant %uint 10 1832%_arr_float_uint_10 = OpTypeArray %float %uint_10 1833%U_t = OpTypeStruct %_arr_float_uint_10 1834%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 1835%_ = OpVariable %_ptr_Uniform_U_t Uniform 1836%_ptr_Uniform_float = OpTypePointer Uniform %float 1837%int_1 = OpConstant %int 1 1838%_ptr_Output_float = OpTypePointer Output %float 1839%o = OpVariable %_ptr_Output_float Output 1840%main = OpFunction %void None %10 1841%25 = OpLabel 1842%s = OpVariable %_ptr_Function_float Function 1843%i = OpVariable %_ptr_Function_int Function 1844OpStore %s %float_0 1845OpStore %i %int_0 1846OpBranch %26 1847%26 = OpLabel 1848OpLoopMerge %27 %28 None 1849OpBranch %29 1850%29 = OpLabel 1851%30 = OpLoad %int %i 1852%31 = OpSLessThan %bool %30 %int_10 1853OpSelectionMerge %32 None 1854OpBranchConditional %31 %32 %27 1855%32 = OpLabel 1856%33 = OpLoad %int %i 1857%34 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %33 1858%35 = OpLoad %float %34 1859%36 = OpLoad %float %s 1860%37 = OpFAdd %float %36 %35 1861OpStore %s %37 1862OpBranch %28 1863%28 = OpLabel 1864%38 = OpLoad %int %i 1865%39 = OpIAdd %int %38 %int_1 1866OpStore %i %39 1867OpBranch %26 1868%27 = OpLabel 1869%40 = OpLoad %float %s 1870OpStore %o %40 1871OpReturn 1872OpFunctionEnd 1873)"; 1874 1875 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 1876} 1877 1878TEST_F(AggressiveDCETest, EliminateEntireUselessLoop) { 1879 // #version 140 1880 // in vec4 BaseColor; 1881 // 1882 // layout(std140) uniform U_t 1883 // { 1884 // int g_I ; 1885 // } ; 1886 // 1887 // void main() 1888 // { 1889 // vec4 v = BaseColor; 1890 // float df = 0.0; 1891 // int i = 0; 1892 // while (i < g_I) { 1893 // df = df * 0.5; 1894 // i = i + 1; 1895 // } 1896 // gl_FragColor = v; 1897 // } 1898 1899 const std::string predefs1 = 1900 R"(OpCapability Shader 1901%1 = OpExtInstImport "GLSL.std.450" 1902OpMemoryModel Logical GLSL450 1903OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor 1904OpExecutionMode %main OriginUpperLeft 1905OpSource GLSL 140 1906)"; 1907 1908 const std::string names_before = 1909 R"(OpName %main "main" 1910OpName %v "v" 1911OpName %BaseColor "BaseColor" 1912OpName %df "df" 1913OpName %i "i" 1914OpName %U_t "U_t" 1915OpMemberName %U_t 0 "g_I" 1916OpName %_ "" 1917OpName %gl_FragColor "gl_FragColor" 1918)"; 1919 1920 const std::string names_after = 1921 R"(OpName %main "main" 1922OpName %v "v" 1923OpName %BaseColor "BaseColor" 1924OpName %gl_FragColor "gl_FragColor" 1925)"; 1926 1927 const std::string predefs2_before = 1928 R"(OpMemberDecorate %U_t 0 Offset 0 1929OpDecorate %U_t Block 1930OpDecorate %_ DescriptorSet 0 1931%void = OpTypeVoid 1932%11 = OpTypeFunction %void 1933%float = OpTypeFloat 32 1934%v4float = OpTypeVector %float 4 1935%_ptr_Function_v4float = OpTypePointer Function %v4float 1936%_ptr_Input_v4float = OpTypePointer Input %v4float 1937%BaseColor = OpVariable %_ptr_Input_v4float Input 1938%_ptr_Function_float = OpTypePointer Function %float 1939%float_0 = OpConstant %float 0 1940%int = OpTypeInt 32 1 1941%_ptr_Function_int = OpTypePointer Function %int 1942%int_0 = OpConstant %int 0 1943%U_t = OpTypeStruct %int 1944%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 1945%_ = OpVariable %_ptr_Uniform_U_t Uniform 1946%_ptr_Uniform_int = OpTypePointer Uniform %int 1947%bool = OpTypeBool 1948%float_0_5 = OpConstant %float 0.5 1949%int_1 = OpConstant %int 1 1950%_ptr_Output_v4float = OpTypePointer Output %v4float 1951%gl_FragColor = OpVariable %_ptr_Output_v4float Output 1952)"; 1953 1954 const std::string predefs2_after = 1955 R"(%void = OpTypeVoid 1956%11 = OpTypeFunction %void 1957%float = OpTypeFloat 32 1958%v4float = OpTypeVector %float 4 1959%_ptr_Function_v4float = OpTypePointer Function %v4float 1960%_ptr_Input_v4float = OpTypePointer Input %v4float 1961%BaseColor = OpVariable %_ptr_Input_v4float Input 1962%_ptr_Output_v4float = OpTypePointer Output %v4float 1963%gl_FragColor = OpVariable %_ptr_Output_v4float Output 1964)"; 1965 1966 const std::string func_before = 1967 R"(%main = OpFunction %void None %11 1968%27 = OpLabel 1969%v = OpVariable %_ptr_Function_v4float Function 1970%df = OpVariable %_ptr_Function_float Function 1971%i = OpVariable %_ptr_Function_int Function 1972%28 = OpLoad %v4float %BaseColor 1973OpStore %v %28 1974OpStore %df %float_0 1975OpStore %i %int_0 1976OpBranch %29 1977%29 = OpLabel 1978OpLoopMerge %30 %31 None 1979OpBranch %32 1980%32 = OpLabel 1981%33 = OpLoad %int %i 1982%34 = OpAccessChain %_ptr_Uniform_int %_ %int_0 1983%35 = OpLoad %int %34 1984%36 = OpSLessThan %bool %33 %35 1985OpBranchConditional %36 %37 %30 1986%37 = OpLabel 1987%38 = OpLoad %float %df 1988%39 = OpFMul %float %38 %float_0_5 1989OpStore %df %39 1990%40 = OpLoad %int %i 1991%41 = OpIAdd %int %40 %int_1 1992OpStore %i %41 1993OpBranch %31 1994%31 = OpLabel 1995OpBranch %29 1996%30 = OpLabel 1997%42 = OpLoad %v4float %v 1998OpStore %gl_FragColor %42 1999OpReturn 2000OpFunctionEnd 2001)"; 2002 2003 const std::string func_after = 2004 R"(%main = OpFunction %void None %11 2005%27 = OpLabel 2006%v = OpVariable %_ptr_Function_v4float Function 2007%28 = OpLoad %v4float %BaseColor 2008OpStore %v %28 2009OpBranch %29 2010%29 = OpLabel 2011OpBranch %30 2012%30 = OpLabel 2013%42 = OpLoad %v4float %v 2014OpStore %gl_FragColor %42 2015OpReturn 2016OpFunctionEnd 2017)"; 2018 2019 SinglePassRunAndCheck<AggressiveDCEPass>( 2020 predefs1 + names_before + predefs2_before + func_before, 2021 predefs1 + names_after + predefs2_after + func_after, true, true); 2022} 2023 2024TEST_F(AggressiveDCETest, NoEliminateBusyLoop) { 2025 // Note: SPIR-V edited to replace AtomicAdd(i,0) with AtomicLoad(i) 2026 // 2027 // #version 450 2028 // 2029 // layout(std430) buffer I_t 2030 // { 2031 // int g_I; 2032 // int g_I2; 2033 // }; 2034 // 2035 // layout(location = 0) out int o; 2036 // 2037 // void main(void) 2038 // { 2039 // while (atomicAdd(g_I, 0) == 0) {} 2040 // o = g_I2; 2041 // } 2042 2043 const std::string assembly = 2044 R"(OpCapability Shader 2045%1 = OpExtInstImport "GLSL.std.450" 2046OpMemoryModel Logical GLSL450 2047OpEntryPoint Fragment %main "main" %o 2048OpExecutionMode %main OriginUpperLeft 2049OpSource GLSL 450 2050OpName %main "main" 2051OpName %I_t "I_t" 2052OpMemberName %I_t 0 "g_I" 2053OpMemberName %I_t 1 "g_I2" 2054OpName %_ "" 2055OpName %o "o" 2056OpMemberDecorate %I_t 0 Offset 0 2057OpMemberDecorate %I_t 1 Offset 4 2058OpDecorate %I_t BufferBlock 2059OpDecorate %_ DescriptorSet 0 2060OpDecorate %o Location 0 2061%void = OpTypeVoid 2062%7 = OpTypeFunction %void 2063%int = OpTypeInt 32 1 2064%I_t = OpTypeStruct %int %int 2065%_ptr_Uniform_I_t = OpTypePointer Uniform %I_t 2066%_ = OpVariable %_ptr_Uniform_I_t Uniform 2067%int_0 = OpConstant %int 0 2068%int_1 = OpConstant %int 1 2069%_ptr_Uniform_int = OpTypePointer Uniform %int 2070%uint = OpTypeInt 32 0 2071%uint_1 = OpConstant %uint 1 2072%uint_0 = OpConstant %uint 0 2073%bool = OpTypeBool 2074%_ptr_Output_int = OpTypePointer Output %int 2075%o = OpVariable %_ptr_Output_int Output 2076%main = OpFunction %void None %7 2077%18 = OpLabel 2078OpBranch %19 2079%19 = OpLabel 2080OpLoopMerge %20 %21 None 2081OpBranch %22 2082%22 = OpLabel 2083%23 = OpAccessChain %_ptr_Uniform_int %_ %int_0 2084%24 = OpAtomicLoad %int %23 %uint_1 %uint_0 2085%25 = OpIEqual %bool %24 %int_0 2086OpBranchConditional %25 %26 %20 2087%26 = OpLabel 2088OpBranch %21 2089%21 = OpLabel 2090OpBranch %19 2091%20 = OpLabel 2092%27 = OpAccessChain %_ptr_Uniform_int %_ %int_1 2093%28 = OpLoad %int %27 2094OpStore %o %28 2095OpReturn 2096OpFunctionEnd 2097)"; 2098 2099 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 2100} 2101 2102TEST_F(AggressiveDCETest, NoEliminateLiveLoop) { 2103 // Note: SPIR-V optimized 2104 // 2105 // #version 430 2106 // 2107 // layout(std430) buffer U_t 2108 // { 2109 // float g_F[10]; 2110 // }; 2111 // 2112 // layout(location = 0)out float o; 2113 // 2114 // void main(void) 2115 // { 2116 // float s = 0.0; 2117 // for (int i=0; i<10; i++) 2118 // s += g_F[i]; 2119 // o = s; 2120 // } 2121 2122 const std::string assembly = 2123 R"(OpCapability Shader 2124%1 = OpExtInstImport "GLSL.std.450" 2125OpMemoryModel Logical GLSL450 2126OpEntryPoint Fragment %main "main" %o 2127OpExecutionMode %main OriginUpperLeft 2128OpSource GLSL 430 2129OpName %main "main" 2130OpName %U_t "U_t" 2131OpMemberName %U_t 0 "g_F" 2132OpName %_ "" 2133OpName %o "o" 2134OpDecorate %_arr_float_uint_10 ArrayStride 4 2135OpMemberDecorate %U_t 0 Offset 0 2136OpDecorate %U_t BufferBlock 2137OpDecorate %_ DescriptorSet 0 2138OpDecorate %o Location 0 2139%void = OpTypeVoid 2140%8 = OpTypeFunction %void 2141%float = OpTypeFloat 32 2142%float_0 = OpConstant %float 0 2143%int = OpTypeInt 32 1 2144%int_0 = OpConstant %int 0 2145%int_10 = OpConstant %int 10 2146%bool = OpTypeBool 2147%uint = OpTypeInt 32 0 2148%uint_10 = OpConstant %uint 10 2149%_arr_float_uint_10 = OpTypeArray %float %uint_10 2150%U_t = OpTypeStruct %_arr_float_uint_10 2151%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 2152%_ = OpVariable %_ptr_Uniform_U_t Uniform 2153%_ptr_Uniform_float = OpTypePointer Uniform %float 2154%int_1 = OpConstant %int 1 2155%_ptr_Output_float = OpTypePointer Output %float 2156%o = OpVariable %_ptr_Output_float Output 2157%main = OpFunction %void None %8 2158%21 = OpLabel 2159OpBranch %22 2160%22 = OpLabel 2161%23 = OpPhi %float %float_0 %21 %24 %25 2162%26 = OpPhi %int %int_0 %21 %27 %25 2163OpLoopMerge %28 %25 None 2164OpBranch %29 2165%29 = OpLabel 2166%30 = OpSLessThan %bool %26 %int_10 2167OpBranchConditional %30 %31 %28 2168%31 = OpLabel 2169%32 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %26 2170%33 = OpLoad %float %32 2171%24 = OpFAdd %float %23 %33 2172OpBranch %25 2173%25 = OpLabel 2174%27 = OpIAdd %int %26 %int_1 2175OpBranch %22 2176%28 = OpLabel 2177OpStore %o %23 2178OpReturn 2179OpFunctionEnd 2180)"; 2181 2182 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 2183} 2184 2185TEST_F(AggressiveDCETest, EliminateEntireFunctionBody) { 2186 // #version 450 2187 // 2188 // layout(location = 0) in vec4 BaseColor; 2189 // layout(location = 0) out vec4 OutColor; 2190 // 2191 // void main() 2192 // { 2193 // float d; 2194 // if (BaseColor.x == 0) 2195 // d = BaseColor.y; 2196 // else 2197 // d = BaseColor.z; 2198 // } 2199 2200 const std::string spirv = 2201 R"(OpCapability Shader 2202%1 = OpExtInstImport "GLSL.std.450" 2203OpMemoryModel Logical GLSL450 2204OpEntryPoint Fragment %main "main" %BaseColor %OutColor 2205OpExecutionMode %main OriginUpperLeft 2206OpSource GLSL 450 2207OpName %main "main" 2208OpName %BaseColor "BaseColor" 2209OpName %d "d" 2210OpName %OutColor "OutColor" 2211OpDecorate %BaseColor Location 0 2212OpDecorate %OutColor Location 0 2213%void = OpTypeVoid 2214%7 = OpTypeFunction %void 2215%float = OpTypeFloat 32 2216%v4float = OpTypeVector %float 4 2217%_ptr_Input_v4float = OpTypePointer Input %v4float 2218%BaseColor = OpVariable %_ptr_Input_v4float Input 2219%uint = OpTypeInt 32 0 2220%uint_0 = OpConstant %uint 0 2221%_ptr_Input_float = OpTypePointer Input %float 2222%float_0 = OpConstant %float 0 2223%bool = OpTypeBool 2224%_ptr_Function_float = OpTypePointer Function %float 2225%uint_1 = OpConstant %uint 1 2226%uint_2 = OpConstant %uint 2 2227%_ptr_Output_v4float = OpTypePointer Output %v4float 2228%OutColor = OpVariable %_ptr_Output_v4float Output 2229 2230; CHECK: = OpFunction 2231; CHECK-NEXT: = OpLabel 2232; CHECK-NEXT: OpBranch [[target:%\w+]] 2233; CHECK-NEXT: [[target]] = OpLabel 2234; CHECK-NEXT: OpReturn 2235; CHECK-NEXT: OpFunctionEnd 2236 2237%main = OpFunction %void None %7 2238%20 = OpLabel 2239%d = OpVariable %_ptr_Function_float Function 2240%21 = OpAccessChain %_ptr_Input_float %BaseColor %uint_0 2241%22 = OpLoad %float %21 2242%23 = OpFOrdEqual %bool %22 %float_0 2243OpSelectionMerge %24 None 2244OpBranchConditional %23 %25 %26 2245%25 = OpLabel 2246%27 = OpAccessChain %_ptr_Input_float %BaseColor %uint_1 2247%28 = OpLoad %float %27 2248OpStore %d %28 2249OpBranch %24 2250%26 = OpLabel 2251%29 = OpAccessChain %_ptr_Input_float %BaseColor %uint_2 2252%30 = OpLoad %float %29 2253OpStore %d %30 2254OpBranch %24 2255%24 = OpLabel 2256OpReturn 2257OpFunctionEnd 2258)"; 2259 2260 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 2261} 2262 2263TEST_F(AggressiveDCETest, EliminateUselessInnerLoop) { 2264 // #version 430 2265 // 2266 // layout(std430) buffer U_t 2267 // { 2268 // float g_F[10]; 2269 // }; 2270 // 2271 // layout(location = 0)out float o; 2272 // 2273 // void main(void) 2274 // { 2275 // float s = 0.0; 2276 // for (int i=0; i<10; i++) { 2277 // for (int j=0; j<10; j++) { 2278 // } 2279 // s += g_F[i]; 2280 // } 2281 // o = s; 2282 // } 2283 2284 const std::string predefs_before = 2285 R"(OpCapability Shader 2286%1 = OpExtInstImport "GLSL.std.450" 2287OpMemoryModel Logical GLSL450 2288OpEntryPoint Fragment %main "main" %o 2289OpExecutionMode %main OriginUpperLeft 2290OpSource GLSL 430 2291OpName %main "main" 2292OpName %s "s" 2293OpName %i "i" 2294OpName %j "j" 2295OpName %U_t "U_t" 2296OpMemberName %U_t 0 "g_F" 2297OpName %_ "" 2298OpName %o "o" 2299OpDecorate %_arr_float_uint_10 ArrayStride 4 2300OpMemberDecorate %U_t 0 Offset 0 2301OpDecorate %U_t BufferBlock 2302OpDecorate %_ DescriptorSet 0 2303OpDecorate %o Location 0 2304%void = OpTypeVoid 2305%11 = OpTypeFunction %void 2306%float = OpTypeFloat 32 2307%_ptr_Function_float = OpTypePointer Function %float 2308%float_0 = OpConstant %float 0 2309%int = OpTypeInt 32 1 2310%_ptr_Function_int = OpTypePointer Function %int 2311%int_0 = OpConstant %int 0 2312%int_10 = OpConstant %int 10 2313%bool = OpTypeBool 2314%int_1 = OpConstant %int 1 2315%uint = OpTypeInt 32 0 2316%uint_10 = OpConstant %uint 10 2317%_arr_float_uint_10 = OpTypeArray %float %uint_10 2318%U_t = OpTypeStruct %_arr_float_uint_10 2319%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 2320%_ = OpVariable %_ptr_Uniform_U_t Uniform 2321%_ptr_Uniform_float = OpTypePointer Uniform %float 2322%_ptr_Output_float = OpTypePointer Output %float 2323%o = OpVariable %_ptr_Output_float Output 2324)"; 2325 2326 const std::string predefs_after = 2327 R"(OpCapability Shader 2328%1 = OpExtInstImport "GLSL.std.450" 2329OpMemoryModel Logical GLSL450 2330OpEntryPoint Fragment %main "main" %o 2331OpExecutionMode %main OriginUpperLeft 2332OpSource GLSL 430 2333OpName %main "main" 2334OpName %s "s" 2335OpName %i "i" 2336OpName %U_t "U_t" 2337OpMemberName %U_t 0 "g_F" 2338OpName %_ "" 2339OpName %o "o" 2340OpDecorate %_arr_float_uint_10 ArrayStride 4 2341OpMemberDecorate %U_t 0 Offset 0 2342OpDecorate %U_t BufferBlock 2343OpDecorate %_ DescriptorSet 0 2344OpDecorate %o Location 0 2345%void = OpTypeVoid 2346%11 = OpTypeFunction %void 2347%float = OpTypeFloat 32 2348%_ptr_Function_float = OpTypePointer Function %float 2349%float_0 = OpConstant %float 0 2350%int = OpTypeInt 32 1 2351%_ptr_Function_int = OpTypePointer Function %int 2352%int_0 = OpConstant %int 0 2353%int_10 = OpConstant %int 10 2354%bool = OpTypeBool 2355%int_1 = OpConstant %int 1 2356%uint = OpTypeInt 32 0 2357%uint_10 = OpConstant %uint 10 2358%_arr_float_uint_10 = OpTypeArray %float %uint_10 2359%U_t = OpTypeStruct %_arr_float_uint_10 2360%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 2361%_ = OpVariable %_ptr_Uniform_U_t Uniform 2362%_ptr_Uniform_float = OpTypePointer Uniform %float 2363%_ptr_Output_float = OpTypePointer Output %float 2364%o = OpVariable %_ptr_Output_float Output 2365)"; 2366 2367 const std::string func_before = 2368 R"(%main = OpFunction %void None %11 2369%26 = OpLabel 2370%s = OpVariable %_ptr_Function_float Function 2371%i = OpVariable %_ptr_Function_int Function 2372%j = OpVariable %_ptr_Function_int Function 2373OpStore %s %float_0 2374OpStore %i %int_0 2375OpBranch %27 2376%27 = OpLabel 2377OpLoopMerge %28 %29 None 2378OpBranch %30 2379%30 = OpLabel 2380%31 = OpLoad %int %i 2381%32 = OpSLessThan %bool %31 %int_10 2382OpBranchConditional %32 %33 %28 2383%33 = OpLabel 2384OpStore %j %int_0 2385OpBranch %34 2386%34 = OpLabel 2387OpLoopMerge %35 %36 None 2388OpBranch %37 2389%37 = OpLabel 2390%38 = OpLoad %int %j 2391%39 = OpSLessThan %bool %38 %int_10 2392OpBranchConditional %39 %40 %35 2393%40 = OpLabel 2394OpBranch %36 2395%36 = OpLabel 2396%41 = OpLoad %int %j 2397%42 = OpIAdd %int %41 %int_1 2398OpStore %j %42 2399OpBranch %34 2400%35 = OpLabel 2401%43 = OpLoad %int %i 2402%44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %43 2403%45 = OpLoad %float %44 2404%46 = OpLoad %float %s 2405%47 = OpFAdd %float %46 %45 2406OpStore %s %47 2407OpBranch %29 2408%29 = OpLabel 2409%48 = OpLoad %int %i 2410%49 = OpIAdd %int %48 %int_1 2411OpStore %i %49 2412OpBranch %27 2413%28 = OpLabel 2414%50 = OpLoad %float %s 2415OpStore %o %50 2416OpReturn 2417OpFunctionEnd 2418)"; 2419 2420 const std::string func_after = 2421 R"(%main = OpFunction %void None %11 2422%26 = OpLabel 2423%s = OpVariable %_ptr_Function_float Function 2424%i = OpVariable %_ptr_Function_int Function 2425OpStore %s %float_0 2426OpStore %i %int_0 2427OpBranch %27 2428%27 = OpLabel 2429OpLoopMerge %28 %29 None 2430OpBranch %30 2431%30 = OpLabel 2432%31 = OpLoad %int %i 2433%32 = OpSLessThan %bool %31 %int_10 2434OpBranchConditional %32 %33 %28 2435%33 = OpLabel 2436OpBranch %34 2437%34 = OpLabel 2438OpBranch %35 2439%35 = OpLabel 2440%43 = OpLoad %int %i 2441%44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %43 2442%45 = OpLoad %float %44 2443%46 = OpLoad %float %s 2444%47 = OpFAdd %float %46 %45 2445OpStore %s %47 2446OpBranch %29 2447%29 = OpLabel 2448%48 = OpLoad %int %i 2449%49 = OpIAdd %int %48 %int_1 2450OpStore %i %49 2451OpBranch %27 2452%28 = OpLabel 2453%50 = OpLoad %float %s 2454OpStore %o %50 2455OpReturn 2456OpFunctionEnd 2457)"; 2458 2459 SinglePassRunAndCheck<AggressiveDCEPass>( 2460 predefs_before + func_before, predefs_after + func_after, true, true); 2461} 2462 2463TEST_F(AggressiveDCETest, EliminateUselessNestedLoopWithIf) { 2464 // #version 430 2465 // 2466 // layout(std430) buffer U_t 2467 // { 2468 // float g_F[10][10]; 2469 // }; 2470 // 2471 // layout(location = 0)out float o; 2472 // 2473 // void main(void) 2474 // { 2475 // float s = 0.0; 2476 // for (int i=0; i<10; i++) { 2477 // for (int j=0; j<10; j++) { 2478 // float t = g_F[i][j]; 2479 // if (t > 0.0) 2480 // s += t; 2481 // } 2482 // } 2483 // o = 0.0; 2484 // } 2485 2486 const std::string predefs_before = 2487 R"(OpCapability Shader 2488%1 = OpExtInstImport "GLSL.std.450" 2489OpMemoryModel Logical GLSL450 2490OpEntryPoint Fragment %main "main" %o 2491OpExecutionMode %main OriginUpperLeft 2492OpSource GLSL 430 2493OpName %main "main" 2494OpName %s "s" 2495OpName %i "i" 2496OpName %j "j" 2497OpName %U_t "U_t" 2498OpMemberName %U_t 0 "g_F" 2499OpName %_ "" 2500OpName %o "o" 2501OpDecorate %_arr_float_uint_10 ArrayStride 4 2502OpDecorate %_arr__arr_float_uint_10_uint_10 ArrayStride 40 2503OpMemberDecorate %U_t 0 Offset 0 2504OpDecorate %U_t BufferBlock 2505OpDecorate %_ DescriptorSet 0 2506OpDecorate %o Location 0 2507%void = OpTypeVoid 2508%12 = OpTypeFunction %void 2509%float = OpTypeFloat 32 2510%_ptr_Function_float = OpTypePointer Function %float 2511%float_0 = OpConstant %float 0 2512%int = OpTypeInt 32 1 2513%_ptr_Function_int = OpTypePointer Function %int 2514%int_0 = OpConstant %int 0 2515%int_10 = OpConstant %int 10 2516%bool = OpTypeBool 2517%uint = OpTypeInt 32 0 2518%uint_10 = OpConstant %uint 10 2519%_arr_float_uint_10 = OpTypeArray %float %uint_10 2520%_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10 2521%U_t = OpTypeStruct %_arr__arr_float_uint_10_uint_10 2522%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 2523%_ = OpVariable %_ptr_Uniform_U_t Uniform 2524%_ptr_Uniform_float = OpTypePointer Uniform %float 2525%int_1 = OpConstant %int 1 2526%_ptr_Output_float = OpTypePointer Output %float 2527%o = OpVariable %_ptr_Output_float Output 2528)"; 2529 2530 const std::string predefs_after = 2531 R"(OpCapability Shader 2532%1 = OpExtInstImport "GLSL.std.450" 2533OpMemoryModel Logical GLSL450 2534OpEntryPoint Fragment %main "main" %o 2535OpExecutionMode %main OriginUpperLeft 2536OpSource GLSL 430 2537OpName %main "main" 2538OpName %o "o" 2539OpDecorate %o Location 0 2540%void = OpTypeVoid 2541%12 = OpTypeFunction %void 2542%float = OpTypeFloat 32 2543%float_0 = OpConstant %float 0 2544%_ptr_Output_float = OpTypePointer Output %float 2545%o = OpVariable %_ptr_Output_float Output 2546)"; 2547 2548 const std::string func_before = 2549 R"(%main = OpFunction %void None %12 2550%27 = OpLabel 2551%s = OpVariable %_ptr_Function_float Function 2552%i = OpVariable %_ptr_Function_int Function 2553%j = OpVariable %_ptr_Function_int Function 2554OpStore %s %float_0 2555OpStore %i %int_0 2556OpBranch %28 2557%28 = OpLabel 2558OpLoopMerge %29 %30 None 2559OpBranch %31 2560%31 = OpLabel 2561%32 = OpLoad %int %i 2562%33 = OpSLessThan %bool %32 %int_10 2563OpBranchConditional %33 %34 %29 2564%34 = OpLabel 2565OpStore %j %int_0 2566OpBranch %35 2567%35 = OpLabel 2568OpLoopMerge %36 %37 None 2569OpBranch %38 2570%38 = OpLabel 2571%39 = OpLoad %int %j 2572%40 = OpSLessThan %bool %39 %int_10 2573OpBranchConditional %40 %41 %36 2574%41 = OpLabel 2575%42 = OpLoad %int %i 2576%43 = OpLoad %int %j 2577%44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %42 %43 2578%45 = OpLoad %float %44 2579%46 = OpFOrdGreaterThan %bool %45 %float_0 2580OpSelectionMerge %47 None 2581OpBranchConditional %46 %48 %47 2582%48 = OpLabel 2583%49 = OpLoad %float %s 2584%50 = OpFAdd %float %49 %45 2585OpStore %s %50 2586OpBranch %47 2587%47 = OpLabel 2588OpBranch %37 2589%37 = OpLabel 2590%51 = OpLoad %int %j 2591%52 = OpIAdd %int %51 %int_1 2592OpStore %j %52 2593OpBranch %35 2594%36 = OpLabel 2595OpBranch %30 2596%30 = OpLabel 2597%53 = OpLoad %int %i 2598%54 = OpIAdd %int %53 %int_1 2599OpStore %i %54 2600OpBranch %28 2601%29 = OpLabel 2602OpStore %o %float_0 2603OpReturn 2604OpFunctionEnd 2605)"; 2606 2607 const std::string func_after = 2608 R"(%main = OpFunction %void None %12 2609%27 = OpLabel 2610OpBranch %28 2611%28 = OpLabel 2612OpBranch %29 2613%29 = OpLabel 2614OpStore %o %float_0 2615OpReturn 2616OpFunctionEnd 2617)"; 2618 2619 SinglePassRunAndCheck<AggressiveDCEPass>( 2620 predefs_before + func_before, predefs_after + func_after, true, true); 2621} 2622 2623TEST_F(AggressiveDCETest, EliminateEmptyIfBeforeContinue) { 2624 // #version 430 2625 // 2626 // layout(location = 0)out float o; 2627 // 2628 // void main(void) 2629 // { 2630 // float s = 0.0; 2631 // for (int i=0; i<10; i++) { 2632 // s += 1.0; 2633 // if (i > s) {} 2634 // } 2635 // o = s; 2636 // } 2637 2638 const std::string predefs_before = 2639 R"(OpCapability Shader 2640%1 = OpExtInstImport "GLSL.std.450" 2641OpMemoryModel Logical GLSL450 2642OpEntryPoint Fragment %main "main" %3 2643OpExecutionMode %main OriginUpperLeft 2644OpSource GLSL 430 2645OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" 2646OpSourceExtension "GL_GOOGLE_include_directive" 2647OpName %main "main" 2648OpDecorate %3 Location 0 2649%void = OpTypeVoid 2650%5 = OpTypeFunction %void 2651%float = OpTypeFloat 32 2652%float_0 = OpConstant %float 0 2653%int = OpTypeInt 32 1 2654%_ptr_Function_int = OpTypePointer Function %int 2655%int_0 = OpConstant %int 0 2656%int_10 = OpConstant %int 10 2657%bool = OpTypeBool 2658%float_1 = OpConstant %float 1 2659%int_1 = OpConstant %int 1 2660%_ptr_Output_float = OpTypePointer Output %float 2661%3 = OpVariable %_ptr_Output_float Output 2662)"; 2663 2664 const std::string predefs_after = 2665 R"(OpCapability Shader 2666%1 = OpExtInstImport "GLSL.std.450" 2667OpMemoryModel Logical GLSL450 2668OpEntryPoint Fragment %main "main" %3 2669OpExecutionMode %main OriginUpperLeft 2670OpSource GLSL 430 2671OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" 2672OpSourceExtension "GL_GOOGLE_include_directive" 2673OpName %main "main" 2674OpDecorate %3 Location 0 2675%void = OpTypeVoid 2676%5 = OpTypeFunction %void 2677%float = OpTypeFloat 32 2678%float_0 = OpConstant %float 0 2679%int = OpTypeInt 32 1 2680%int_0 = OpConstant %int 0 2681%int_10 = OpConstant %int 10 2682%bool = OpTypeBool 2683%float_1 = OpConstant %float 1 2684%int_1 = OpConstant %int 1 2685%_ptr_Output_float = OpTypePointer Output %float 2686%3 = OpVariable %_ptr_Output_float Output 2687)"; 2688 2689 const std::string func_before = 2690 R"(%main = OpFunction %void None %5 2691%16 = OpLabel 2692OpBranch %17 2693%17 = OpLabel 2694%18 = OpPhi %float %float_0 %16 %19 %20 2695%21 = OpPhi %int %int_0 %16 %22 %20 2696OpLoopMerge %23 %20 None 2697OpBranch %24 2698%24 = OpLabel 2699%25 = OpSLessThan %bool %21 %int_10 2700OpBranchConditional %25 %26 %23 2701%26 = OpLabel 2702%19 = OpFAdd %float %18 %float_1 2703%27 = OpConvertFToS %int %19 2704%28 = OpSGreaterThan %bool %21 %27 2705OpSelectionMerge %20 None 2706OpBranchConditional %28 %29 %20 2707%29 = OpLabel 2708OpBranch %20 2709%20 = OpLabel 2710%22 = OpIAdd %int %21 %int_1 2711OpBranch %17 2712%23 = OpLabel 2713OpStore %3 %18 2714OpReturn 2715OpFunctionEnd 2716)"; 2717 2718 const std::string func_after = 2719 R"(%main = OpFunction %void None %5 2720%16 = OpLabel 2721OpBranch %17 2722%17 = OpLabel 2723%18 = OpPhi %float %float_0 %16 %19 %20 2724%21 = OpPhi %int %int_0 %16 %22 %20 2725OpLoopMerge %23 %20 None 2726OpBranch %24 2727%24 = OpLabel 2728%25 = OpSLessThan %bool %21 %int_10 2729OpBranchConditional %25 %26 %23 2730%26 = OpLabel 2731%19 = OpFAdd %float %18 %float_1 2732OpBranch %20 2733%20 = OpLabel 2734%22 = OpIAdd %int %21 %int_1 2735OpBranch %17 2736%23 = OpLabel 2737OpStore %3 %18 2738OpReturn 2739OpFunctionEnd 2740)"; 2741 2742 SinglePassRunAndCheck<AggressiveDCEPass>( 2743 predefs_before + func_before, predefs_after + func_after, true, true); 2744} 2745 2746TEST_F(AggressiveDCETest, NoEliminateLiveNestedLoopWithIf) { 2747 // Note: SPIR-V optimized 2748 // 2749 // #version 430 2750 // 2751 // layout(std430) buffer U_t 2752 // { 2753 // float g_F[10][10]; 2754 // }; 2755 // 2756 // layout(location = 0)out float o; 2757 // 2758 // void main(void) 2759 // { 2760 // float s = 0.0; 2761 // for (int i=0; i<10; i++) { 2762 // for (int j=0; j<10; j++) { 2763 // float t = g_F[i][j]; 2764 // if (t > 0.0) 2765 // s += t; 2766 // } 2767 // } 2768 // o = s; 2769 // } 2770 2771 const std::string assembly = 2772 R"(OpCapability Shader 2773%1 = OpExtInstImport "GLSL.std.450" 2774OpMemoryModel Logical GLSL450 2775OpEntryPoint Fragment %main "main" %o 2776OpExecutionMode %main OriginUpperLeft 2777OpSource GLSL 430 2778OpName %main "main" 2779OpName %s "s" 2780OpName %i "i" 2781OpName %j "j" 2782OpName %U_t "U_t" 2783OpMemberName %U_t 0 "g_F" 2784OpName %_ "" 2785OpName %o "o" 2786OpDecorate %_arr_float_uint_10 ArrayStride 4 2787OpDecorate %_arr__arr_float_uint_10_uint_10 ArrayStride 40 2788OpMemberDecorate %U_t 0 Offset 0 2789OpDecorate %U_t BufferBlock 2790OpDecorate %_ DescriptorSet 0 2791OpDecorate %o Location 0 2792%void = OpTypeVoid 2793%12 = OpTypeFunction %void 2794%float = OpTypeFloat 32 2795%_ptr_Function_float = OpTypePointer Function %float 2796%float_0 = OpConstant %float 0 2797%int = OpTypeInt 32 1 2798%_ptr_Function_int = OpTypePointer Function %int 2799%int_0 = OpConstant %int 0 2800%int_10 = OpConstant %int 10 2801%bool = OpTypeBool 2802%uint = OpTypeInt 32 0 2803%uint_10 = OpConstant %uint 10 2804%_arr_float_uint_10 = OpTypeArray %float %uint_10 2805%_arr__arr_float_uint_10_uint_10 = OpTypeArray %_arr_float_uint_10 %uint_10 2806%U_t = OpTypeStruct %_arr__arr_float_uint_10_uint_10 2807%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 2808%_ = OpVariable %_ptr_Uniform_U_t Uniform 2809%_ptr_Uniform_float = OpTypePointer Uniform %float 2810%int_1 = OpConstant %int 1 2811%_ptr_Output_float = OpTypePointer Output %float 2812%o = OpVariable %_ptr_Output_float Output 2813%main = OpFunction %void None %12 2814%27 = OpLabel 2815%s = OpVariable %_ptr_Function_float Function 2816%i = OpVariable %_ptr_Function_int Function 2817%j = OpVariable %_ptr_Function_int Function 2818OpStore %s %float_0 2819OpStore %i %int_0 2820OpBranch %28 2821%28 = OpLabel 2822OpLoopMerge %29 %30 None 2823OpBranch %31 2824%31 = OpLabel 2825%32 = OpLoad %int %i 2826%33 = OpSLessThan %bool %32 %int_10 2827OpBranchConditional %33 %34 %29 2828%34 = OpLabel 2829OpStore %j %int_0 2830OpBranch %35 2831%35 = OpLabel 2832OpLoopMerge %36 %37 None 2833OpBranch %38 2834%38 = OpLabel 2835%39 = OpLoad %int %j 2836%40 = OpSLessThan %bool %39 %int_10 2837OpBranchConditional %40 %41 %36 2838%41 = OpLabel 2839%42 = OpLoad %int %i 2840%43 = OpLoad %int %j 2841%44 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %42 %43 2842%45 = OpLoad %float %44 2843%46 = OpFOrdGreaterThan %bool %45 %float_0 2844OpSelectionMerge %47 None 2845OpBranchConditional %46 %48 %47 2846%48 = OpLabel 2847%49 = OpLoad %float %s 2848%50 = OpFAdd %float %49 %45 2849OpStore %s %50 2850OpBranch %47 2851%47 = OpLabel 2852OpBranch %37 2853%37 = OpLabel 2854%51 = OpLoad %int %j 2855%52 = OpIAdd %int %51 %int_1 2856OpStore %j %52 2857OpBranch %35 2858%36 = OpLabel 2859OpBranch %30 2860%30 = OpLabel 2861%53 = OpLoad %int %i 2862%54 = OpIAdd %int %53 %int_1 2863OpStore %i %54 2864OpBranch %28 2865%29 = OpLabel 2866%55 = OpLoad %float %s 2867OpStore %o %55 2868OpReturn 2869OpFunctionEnd 2870)"; 2871 2872 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 2873} 2874 2875TEST_F(AggressiveDCETest, NoEliminateIfContinue) { 2876 // Do not eliminate continue embedded in if construct 2877 // 2878 // #version 430 2879 // 2880 // layout(std430) buffer U_t 2881 // { 2882 // float g_F[10]; 2883 // }; 2884 // 2885 // layout(location = 0)out float o; 2886 // 2887 // void main(void) 2888 // { 2889 // float s = 0.0; 2890 // for (int i=0; i<10; i++) { 2891 // if (i % 2 == 0) continue; 2892 // s += g_F[i]; 2893 // } 2894 // o = s; 2895 // } 2896 2897 const std::string assembly = 2898 R"(OpCapability Shader 2899%1 = OpExtInstImport "GLSL.std.450" 2900OpMemoryModel Logical GLSL450 2901OpEntryPoint Fragment %main "main" %o 2902OpExecutionMode %main OriginUpperLeft 2903OpSource GLSL 430 2904OpName %main "main" 2905OpName %s "s" 2906OpName %i "i" 2907OpName %U_t "U_t" 2908OpMemberName %U_t 0 "g_F" 2909OpName %_ "" 2910OpName %o "o" 2911OpDecorate %_arr_float_uint_10 ArrayStride 4 2912OpMemberDecorate %U_t 0 Offset 0 2913OpDecorate %U_t BufferBlock 2914OpDecorate %_ DescriptorSet 0 2915OpDecorate %o Location 0 2916%void = OpTypeVoid 2917%10 = OpTypeFunction %void 2918%float = OpTypeFloat 32 2919%_ptr_Function_float = OpTypePointer Function %float 2920%float_0 = OpConstant %float 0 2921%int = OpTypeInt 32 1 2922%_ptr_Function_int = OpTypePointer Function %int 2923%int_0 = OpConstant %int 0 2924%int_10 = OpConstant %int 10 2925%bool = OpTypeBool 2926%int_2 = OpConstant %int 2 2927%uint = OpTypeInt 32 0 2928%uint_10 = OpConstant %uint 10 2929%_arr_float_uint_10 = OpTypeArray %float %uint_10 2930%U_t = OpTypeStruct %_arr_float_uint_10 2931%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 2932%_ = OpVariable %_ptr_Uniform_U_t Uniform 2933%_ptr_Uniform_float = OpTypePointer Uniform %float 2934%int_1 = OpConstant %int 1 2935%_ptr_Output_float = OpTypePointer Output %float 2936%o = OpVariable %_ptr_Output_float Output 2937%main = OpFunction %void None %10 2938%26 = OpLabel 2939%s = OpVariable %_ptr_Function_float Function 2940%i = OpVariable %_ptr_Function_int Function 2941OpStore %s %float_0 2942OpStore %i %int_0 2943OpBranch %27 2944%27 = OpLabel 2945OpLoopMerge %28 %29 None 2946OpBranch %30 2947%30 = OpLabel 2948%31 = OpLoad %int %i 2949%32 = OpSLessThan %bool %31 %int_10 2950OpBranchConditional %32 %33 %28 2951%33 = OpLabel 2952%34 = OpLoad %int %i 2953%35 = OpSMod %int %34 %int_2 2954%36 = OpIEqual %bool %35 %int_0 2955OpSelectionMerge %37 None 2956OpBranchConditional %36 %38 %37 2957%38 = OpLabel 2958OpBranch %29 2959%37 = OpLabel 2960%39 = OpLoad %int %i 2961%40 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %39 2962%41 = OpLoad %float %40 2963%42 = OpLoad %float %s 2964%43 = OpFAdd %float %42 %41 2965OpStore %s %43 2966OpBranch %29 2967%29 = OpLabel 2968%44 = OpLoad %int %i 2969%45 = OpIAdd %int %44 %int_1 2970OpStore %i %45 2971OpBranch %27 2972%28 = OpLabel 2973%46 = OpLoad %float %s 2974OpStore %o %46 2975OpReturn 2976OpFunctionEnd 2977)"; 2978 2979 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 2980} 2981 2982TEST_F(AggressiveDCETest, NoEliminateIfContinue2) { 2983 // Do not eliminate continue not embedded in if construct 2984 // 2985 // #version 430 2986 // 2987 // layout(std430) buffer U_t 2988 // { 2989 // float g_F[10]; 2990 // }; 2991 // 2992 // layout(location = 0)out float o; 2993 // 2994 // void main(void) 2995 // { 2996 // float s = 0.0; 2997 // for (int i=0; i<10; i++) { 2998 // if (i % 2 == 0) continue; 2999 // s += g_F[i]; 3000 // } 3001 // o = s; 3002 // } 3003 3004 const std::string assembly = 3005 R"(OpCapability Shader 3006%1 = OpExtInstImport "GLSL.std.450" 3007OpMemoryModel Logical GLSL450 3008OpEntryPoint Fragment %main "main" %o 3009OpExecutionMode %main OriginUpperLeft 3010OpSource GLSL 430 3011OpName %main "main" 3012OpName %s "s" 3013OpName %i "i" 3014OpName %U_t "U_t" 3015OpMemberName %U_t 0 "g_F" 3016OpName %_ "" 3017OpName %o "o" 3018OpDecorate %_arr_float_uint_10 ArrayStride 4 3019OpMemberDecorate %U_t 0 Offset 0 3020OpDecorate %U_t BufferBlock 3021OpDecorate %_ DescriptorSet 0 3022OpDecorate %o Location 0 3023%void = OpTypeVoid 3024%10 = OpTypeFunction %void 3025%float = OpTypeFloat 32 3026%_ptr_Function_float = OpTypePointer Function %float 3027%float_0 = OpConstant %float 0 3028%int = OpTypeInt 32 1 3029%_ptr_Function_int = OpTypePointer Function %int 3030%int_0 = OpConstant %int 0 3031%int_10 = OpConstant %int 10 3032%bool = OpTypeBool 3033%int_2 = OpConstant %int 2 3034%uint = OpTypeInt 32 0 3035%uint_10 = OpConstant %uint 10 3036%_arr_float_uint_10 = OpTypeArray %float %uint_10 3037%U_t = OpTypeStruct %_arr_float_uint_10 3038%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 3039%_ = OpVariable %_ptr_Uniform_U_t Uniform 3040%_ptr_Uniform_float = OpTypePointer Uniform %float 3041%int_1 = OpConstant %int 1 3042%_ptr_Output_float = OpTypePointer Output %float 3043%o = OpVariable %_ptr_Output_float Output 3044%main = OpFunction %void None %10 3045%26 = OpLabel 3046%s = OpVariable %_ptr_Function_float Function 3047%i = OpVariable %_ptr_Function_int Function 3048OpStore %s %float_0 3049OpStore %i %int_0 3050OpBranch %27 3051%27 = OpLabel 3052OpLoopMerge %28 %29 None 3053OpBranch %30 3054%30 = OpLabel 3055%31 = OpLoad %int %i 3056%32 = OpSLessThan %bool %31 %int_10 3057OpBranchConditional %32 %33 %28 3058%33 = OpLabel 3059%34 = OpLoad %int %i 3060%35 = OpSMod %int %34 %int_2 3061%36 = OpIEqual %bool %35 %int_0 3062OpBranchConditional %36 %29 %37 3063%37 = OpLabel 3064%38 = OpLoad %int %i 3065%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %38 3066%40 = OpLoad %float %39 3067%41 = OpLoad %float %s 3068%42 = OpFAdd %float %41 %40 3069OpStore %s %42 3070OpBranch %29 3071%29 = OpLabel 3072%43 = OpLoad %int %i 3073%44 = OpIAdd %int %43 %int_1 3074OpStore %i %44 3075OpBranch %27 3076%28 = OpLabel 3077%45 = OpLoad %float %s 3078OpStore %o %45 3079OpReturn 3080OpFunctionEnd 3081)"; 3082 3083 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 3084} 3085 3086TEST_F(AggressiveDCETest, NoEliminateIfContinue3) { 3087 // Do not eliminate continue as conditional branch with merge instruction 3088 // Note: SPIR-V edited to add merge instruction before continue. 3089 // 3090 // #version 430 3091 // 3092 // layout(std430) buffer U_t 3093 // { 3094 // float g_F[10]; 3095 // }; 3096 // 3097 // layout(location = 0)out float o; 3098 // 3099 // void main(void) 3100 // { 3101 // float s = 0.0; 3102 // for (int i=0; i<10; i++) { 3103 // if (i % 2 == 0) continue; 3104 // s += g_F[i]; 3105 // } 3106 // o = s; 3107 // } 3108 3109 const std::string assembly = 3110 R"(OpCapability Shader 3111%1 = OpExtInstImport "GLSL.std.450" 3112OpMemoryModel Logical GLSL450 3113OpEntryPoint Fragment %main "main" %o 3114OpExecutionMode %main OriginUpperLeft 3115OpSource GLSL 430 3116OpName %main "main" 3117OpName %s "s" 3118OpName %i "i" 3119OpName %U_t "U_t" 3120OpMemberName %U_t 0 "g_F" 3121OpName %_ "" 3122OpName %o "o" 3123OpDecorate %_arr_float_uint_10 ArrayStride 4 3124OpMemberDecorate %U_t 0 Offset 0 3125OpDecorate %U_t BufferBlock 3126OpDecorate %_ DescriptorSet 0 3127OpDecorate %o Location 0 3128%void = OpTypeVoid 3129%10 = OpTypeFunction %void 3130%float = OpTypeFloat 32 3131%_ptr_Function_float = OpTypePointer Function %float 3132%float_0 = OpConstant %float 0 3133%int = OpTypeInt 32 1 3134%_ptr_Function_int = OpTypePointer Function %int 3135%int_0 = OpConstant %int 0 3136%int_10 = OpConstant %int 10 3137%bool = OpTypeBool 3138%int_2 = OpConstant %int 2 3139%uint = OpTypeInt 32 0 3140%uint_10 = OpConstant %uint 10 3141%_arr_float_uint_10 = OpTypeArray %float %uint_10 3142%U_t = OpTypeStruct %_arr_float_uint_10 3143%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 3144%_ = OpVariable %_ptr_Uniform_U_t Uniform 3145%_ptr_Uniform_float = OpTypePointer Uniform %float 3146%int_1 = OpConstant %int 1 3147%_ptr_Output_float = OpTypePointer Output %float 3148%o = OpVariable %_ptr_Output_float Output 3149%main = OpFunction %void None %10 3150%26 = OpLabel 3151%s = OpVariable %_ptr_Function_float Function 3152%i = OpVariable %_ptr_Function_int Function 3153OpStore %s %float_0 3154OpStore %i %int_0 3155OpBranch %27 3156%27 = OpLabel 3157OpLoopMerge %28 %29 None 3158OpBranch %30 3159%30 = OpLabel 3160%31 = OpLoad %int %i 3161%32 = OpSLessThan %bool %31 %int_10 3162OpBranchConditional %32 %33 %28 3163%33 = OpLabel 3164%34 = OpLoad %int %i 3165%35 = OpSMod %int %34 %int_2 3166%36 = OpIEqual %bool %35 %int_0 3167OpSelectionMerge %37 None 3168OpBranchConditional %36 %29 %37 3169%37 = OpLabel 3170%38 = OpLoad %int %i 3171%39 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %38 3172%40 = OpLoad %float %39 3173%41 = OpLoad %float %s 3174%42 = OpFAdd %float %41 %40 3175OpStore %s %42 3176OpBranch %29 3177%29 = OpLabel 3178%43 = OpLoad %int %i 3179%44 = OpIAdd %int %43 %int_1 3180OpStore %i %44 3181OpBranch %27 3182%28 = OpLabel 3183%45 = OpLoad %float %s 3184OpStore %o %45 3185OpReturn 3186OpFunctionEnd 3187)"; 3188 3189 SinglePassRunAndCheck<AggressiveDCEPass>(assembly, assembly, true, true); 3190} 3191 3192// This is not valid input and ADCE does not support variable pointers and only 3193// supports shaders. 3194TEST_F(AggressiveDCETest, PointerVariable) { 3195 // ADCE is able to handle code that contains a load whose base address 3196 // comes from a load and not an OpVariable. I want to see an instruction 3197 // removed to be sure that ADCE is not exiting early. 3198 3199 const std::string before = 3200 R"(OpCapability Shader 3201OpMemoryModel Logical GLSL450 3202OpEntryPoint Fragment %1 "main" %2 3203OpExecutionMode %1 OriginUpperLeft 3204OpMemberDecorate %_struct_3 0 Offset 0 3205OpDecorate %_runtimearr__struct_3 ArrayStride 16 3206OpMemberDecorate %_struct_5 0 Offset 0 3207OpDecorate %_struct_5 BufferBlock 3208OpMemberDecorate %_struct_6 0 Offset 0 3209OpDecorate %_struct_6 BufferBlock 3210OpDecorate %2 Location 0 3211OpDecorate %7 DescriptorSet 0 3212OpDecorate %7 Binding 0 3213OpDecorate %8 DescriptorSet 0 3214OpDecorate %8 Binding 1 3215%void = OpTypeVoid 3216%10 = OpTypeFunction %void 3217%int = OpTypeInt 32 1 3218%uint = OpTypeInt 32 0 3219%float = OpTypeFloat 32 3220%v4float = OpTypeVector %float 4 3221%_ptr_Output_v4float = OpTypePointer Output %v4float 3222%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float 3223%_struct_3 = OpTypeStruct %v4float 3224%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 3225%_struct_5 = OpTypeStruct %_runtimearr__struct_3 3226%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 3227%_struct_6 = OpTypeStruct %int 3228%_ptr_Uniform__struct_6 = OpTypePointer Uniform %_struct_6 3229%_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5 3230%_ptr_Function__ptr_Uniform__struct_6 = OpTypePointer Function %_ptr_Uniform__struct_6 3231%int_0 = OpConstant %int 0 3232%uint_0 = OpConstant %uint 0 3233%2 = OpVariable %_ptr_Output_v4float Output 3234%7 = OpVariable %_ptr_Uniform__struct_5 Uniform 3235%8 = OpVariable %_ptr_Uniform__struct_6 Uniform 3236%1 = OpFunction %void None %10 3237%23 = OpLabel 3238%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function 3239OpStore %24 %7 3240%26 = OpLoad %_ptr_Uniform__struct_5 %24 3241%27 = OpAccessChain %_ptr_Uniform_v4float %26 %int_0 %uint_0 %int_0 3242%28 = OpLoad %v4float %27 3243%29 = OpCopyObject %v4float %28 3244OpStore %2 %28 3245OpReturn 3246OpFunctionEnd 3247)"; 3248 3249 const std::string after = 3250 R"(OpCapability Shader 3251OpMemoryModel Logical GLSL450 3252OpEntryPoint Fragment %1 "main" %2 3253OpExecutionMode %1 OriginUpperLeft 3254OpMemberDecorate %_struct_3 0 Offset 0 3255OpDecorate %_runtimearr__struct_3 ArrayStride 16 3256OpMemberDecorate %_struct_5 0 Offset 0 3257OpDecorate %_struct_5 BufferBlock 3258OpDecorate %2 Location 0 3259OpDecorate %7 DescriptorSet 0 3260OpDecorate %7 Binding 0 3261%void = OpTypeVoid 3262%10 = OpTypeFunction %void 3263%int = OpTypeInt 32 1 3264%uint = OpTypeInt 32 0 3265%float = OpTypeFloat 32 3266%v4float = OpTypeVector %float 4 3267%_ptr_Output_v4float = OpTypePointer Output %v4float 3268%_ptr_Uniform_v4float = OpTypePointer Uniform %v4float 3269%_struct_3 = OpTypeStruct %v4float 3270%_runtimearr__struct_3 = OpTypeRuntimeArray %_struct_3 3271%_struct_5 = OpTypeStruct %_runtimearr__struct_3 3272%_ptr_Uniform__struct_5 = OpTypePointer Uniform %_struct_5 3273%_ptr_Function__ptr_Uniform__struct_5 = OpTypePointer Function %_ptr_Uniform__struct_5 3274%int_0 = OpConstant %int 0 3275%uint_0 = OpConstant %uint 0 3276%2 = OpVariable %_ptr_Output_v4float Output 3277%7 = OpVariable %_ptr_Uniform__struct_5 Uniform 3278%1 = OpFunction %void None %10 3279%23 = OpLabel 3280%24 = OpVariable %_ptr_Function__ptr_Uniform__struct_5 Function 3281OpStore %24 %7 3282%25 = OpLoad %_ptr_Uniform__struct_5 %24 3283%26 = OpAccessChain %_ptr_Uniform_v4float %25 %int_0 %uint_0 %int_0 3284%27 = OpLoad %v4float %26 3285OpStore %2 %27 3286OpReturn 3287OpFunctionEnd 3288)"; 3289 3290 // The input is not valid and ADCE only supports shaders, but not variable 3291 // pointers. Workaround this by enabling relaxed logical pointers in the 3292 // validator. 3293 ValidatorOptions()->relax_logical_pointer = true; 3294 SinglePassRunAndCheck<AggressiveDCEPass>(before, after, true, true); 3295} 3296 3297// %dead is unused. Make sure we remove it along with its name. 3298TEST_F(AggressiveDCETest, RemoveUnreferenced) { 3299 const std::string before = 3300 R"(OpCapability Shader 3301OpCapability Linkage 3302%1 = OpExtInstImport "GLSL.std.450" 3303OpMemoryModel Logical GLSL450 3304OpEntryPoint Fragment %main "main" 3305OpExecutionMode %main OriginUpperLeft 3306OpSource GLSL 150 3307OpName %main "main" 3308OpName %dead "dead" 3309%void = OpTypeVoid 3310%5 = OpTypeFunction %void 3311%float = OpTypeFloat 32 3312%_ptr_Private_float = OpTypePointer Private %float 3313%dead = OpVariable %_ptr_Private_float Private 3314%main = OpFunction %void None %5 3315%8 = OpLabel 3316OpReturn 3317OpFunctionEnd 3318)"; 3319 3320 const std::string after = 3321 R"(OpCapability Shader 3322OpCapability Linkage 3323%1 = OpExtInstImport "GLSL.std.450" 3324OpMemoryModel Logical GLSL450 3325OpEntryPoint Fragment %main "main" 3326OpExecutionMode %main OriginUpperLeft 3327OpSource GLSL 150 3328OpName %main "main" 3329%void = OpTypeVoid 3330%5 = OpTypeFunction %void 3331%main = OpFunction %void None %5 3332%8 = OpLabel 3333OpReturn 3334OpFunctionEnd 3335)"; 3336 3337 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3338 SinglePassRunAndCheck<AggressiveDCEPass>(before, after, true, true); 3339} 3340 3341// Delete %dead because it is unreferenced. Then %initializer becomes 3342// unreferenced, so remove it as well. 3343TEST_F(AggressiveDCETest, RemoveUnreferencedWithInit1) { 3344 const std::string before = 3345 R"(OpCapability Shader 3346OpCapability Linkage 3347%1 = OpExtInstImport "GLSL.std.450" 3348OpMemoryModel Logical GLSL450 3349OpEntryPoint Fragment %main "main" 3350OpExecutionMode %main OriginUpperLeft 3351OpSource GLSL 150 3352OpName %main "main" 3353OpName %dead "dead" 3354OpName %initializer "initializer" 3355%void = OpTypeVoid 3356%6 = OpTypeFunction %void 3357%float = OpTypeFloat 32 3358%_ptr_Private_float = OpTypePointer Private %float 3359%initializer = OpVariable %_ptr_Private_float Private 3360%dead = OpVariable %_ptr_Private_float Private %initializer 3361%main = OpFunction %void None %6 3362%9 = OpLabel 3363OpReturn 3364OpFunctionEnd 3365)"; 3366 3367 const std::string after = 3368 R"(OpCapability Shader 3369OpCapability Linkage 3370%1 = OpExtInstImport "GLSL.std.450" 3371OpMemoryModel Logical GLSL450 3372OpEntryPoint Fragment %main "main" 3373OpExecutionMode %main OriginUpperLeft 3374OpSource GLSL 150 3375OpName %main "main" 3376%void = OpTypeVoid 3377%6 = OpTypeFunction %void 3378%main = OpFunction %void None %6 3379%9 = OpLabel 3380OpReturn 3381OpFunctionEnd 3382)"; 3383 3384 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3385 SinglePassRunAndCheck<AggressiveDCEPass>(before, after, true, true); 3386} 3387 3388// Keep %live because it is used, and its initializer. 3389TEST_F(AggressiveDCETest, KeepReferenced) { 3390 const std::string before = 3391 R"(OpCapability Shader 3392OpCapability Linkage 3393%1 = OpExtInstImport "GLSL.std.450" 3394OpMemoryModel Logical GLSL450 3395OpEntryPoint Fragment %main "main" %output 3396OpExecutionMode %main OriginUpperLeft 3397OpSource GLSL 150 3398OpName %main "main" 3399OpName %live "live" 3400OpName %initializer "initializer" 3401OpName %output "output" 3402%void = OpTypeVoid 3403%6 = OpTypeFunction %void 3404%float = OpTypeFloat 32 3405%_ptr_Private_float = OpTypePointer Private %float 3406%initializer = OpConstant %float 0 3407%live = OpVariable %_ptr_Private_float Private %initializer 3408%_ptr_Output_float = OpTypePointer Output %float 3409%output = OpVariable %_ptr_Output_float Output 3410%main = OpFunction %void None %6 3411%9 = OpLabel 3412%10 = OpLoad %float %live 3413OpStore %output %10 3414OpReturn 3415OpFunctionEnd 3416)"; 3417 3418 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3419 SinglePassRunAndCheck<AggressiveDCEPass>(before, before, true, true); 3420} 3421 3422// This test that the decoration associated with a variable are removed when the 3423// variable is removed. 3424TEST_F(AggressiveDCETest, RemoveVariableAndDecorations) { 3425 const std::string before = 3426 R"(OpCapability Shader 3427%1 = OpExtInstImport "GLSL.std.450" 3428OpMemoryModel Logical GLSL450 3429OpEntryPoint Vertex %main "main" 3430OpSource GLSL 450 3431OpName %main "main" 3432OpName %B "B" 3433OpMemberName %B 0 "a" 3434OpName %Bdat "Bdat" 3435OpMemberDecorate %B 0 Offset 0 3436OpDecorate %B BufferBlock 3437OpDecorate %Bdat DescriptorSet 0 3438OpDecorate %Bdat Binding 0 3439%void = OpTypeVoid 3440%6 = OpTypeFunction %void 3441%uint = OpTypeInt 32 0 3442%B = OpTypeStruct %uint 3443%_ptr_Uniform_B = OpTypePointer Uniform %B 3444%Bdat = OpVariable %_ptr_Uniform_B Uniform 3445%int = OpTypeInt 32 1 3446%int_0 = OpConstant %int 0 3447%uint_1 = OpConstant %uint 1 3448%_ptr_Uniform_uint = OpTypePointer Uniform %uint 3449%main = OpFunction %void None %6 3450%13 = OpLabel 3451OpReturn 3452OpFunctionEnd 3453)"; 3454 3455 const std::string after = 3456 R"(OpCapability Shader 3457%1 = OpExtInstImport "GLSL.std.450" 3458OpMemoryModel Logical GLSL450 3459OpEntryPoint Vertex %main "main" 3460OpSource GLSL 450 3461OpName %main "main" 3462%void = OpTypeVoid 3463%6 = OpTypeFunction %void 3464%main = OpFunction %void None %6 3465%13 = OpLabel 3466OpReturn 3467OpFunctionEnd 3468)"; 3469 3470 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3471 SinglePassRunAndCheck<AggressiveDCEPass>(before, after, true, true); 3472} 3473 3474TEST_F(AggressiveDCETest, DeadNestedSwitch) { 3475 const std::string text = R"( 3476; CHECK: OpLabel 3477; CHECK: OpBranch [[block:%\w+]] 3478; CHECK-NOT: OpSwitch 3479; CHECK-NEXT: [[block]] = OpLabel 3480; CHECK: OpBranch [[block:%\w+]] 3481; CHECK-NOT: OpSwitch 3482; CHECK-NEXT: [[block]] = OpLabel 3483; CHECK-NEXT: OpStore 3484OpCapability Shader 3485OpMemoryModel Logical GLSL450 3486OpEntryPoint Fragment %func "func" %x 3487OpExecutionMode %func OriginUpperLeft 3488OpName %func "func" 3489%void = OpTypeVoid 3490%1 = OpTypeFunction %void 3491%uint = OpTypeInt 32 0 3492%uint_0 = OpConstant %uint 0 3493%uint_ptr_Output = OpTypePointer Output %uint 3494%uint_ptr_Input = OpTypePointer Input %uint 3495%x = OpVariable %uint_ptr_Output Output 3496%a = OpVariable %uint_ptr_Input Input 3497%func = OpFunction %void None %1 3498%entry = OpLabel 3499OpBranch %header 3500%header = OpLabel 3501%ld = OpLoad %uint %a 3502OpLoopMerge %merge %continue None 3503OpBranch %postheader 3504%postheader = OpLabel 3505; This switch doesn't require an OpSelectionMerge and is nested in the dead loop. 3506OpSwitch %ld %merge 0 %extra 1 %continue 3507%extra = OpLabel 3508OpBranch %continue 3509%continue = OpLabel 3510OpBranch %header 3511%merge = OpLabel 3512OpStore %x %uint_0 3513OpReturn 3514OpFunctionEnd 3515)"; 3516 3517 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 3518} 3519 3520TEST_F(AggressiveDCETest, LiveNestedSwitch) { 3521 const std::string text = R"(OpCapability Shader 3522OpMemoryModel Logical GLSL450 3523OpEntryPoint Fragment %func "func" %3 %10 3524OpExecutionMode %func OriginUpperLeft 3525OpName %func "func" 3526%void = OpTypeVoid 3527%1 = OpTypeFunction %void 3528%uint = OpTypeInt 32 0 3529%uint_0 = OpConstant %uint 0 3530%uint_1 = OpConstant %uint 1 3531%_ptr_Output_uint = OpTypePointer Output %uint 3532%_ptr_Input_uint = OpTypePointer Input %uint 3533%3 = OpVariable %_ptr_Output_uint Output 3534%10 = OpVariable %_ptr_Input_uint Input 3535%func = OpFunction %void None %1 3536%11 = OpLabel 3537OpBranch %12 3538%12 = OpLabel 3539%13 = OpLoad %uint %10 3540OpLoopMerge %14 %15 None 3541OpBranch %16 3542%16 = OpLabel 3543OpSelectionMerge %18 None 3544OpSwitch %13 %18 0 %17 1 %19 3545%17 = OpLabel 3546OpStore %3 %uint_1 3547OpBranch %19 3548%19 = OpLabel 3549OpBranch %15 3550%15 = OpLabel 3551OpBranch %12 3552%18 = OpLabel 3553OpBranch %14 3554%14 = OpLabel 3555OpStore %3 %uint_0 3556OpReturn 3557OpFunctionEnd 3558)"; 3559 3560 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3561 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, false, true); 3562} 3563 3564TEST_F(AggressiveDCETest, BasicDeleteDeadFunction) { 3565 // The function Dead should be removed because it is never called. 3566 const std::vector<const char*> common_code = { 3567 // clang-format off 3568 "OpCapability Shader", 3569 "OpMemoryModel Logical GLSL450", 3570 "OpEntryPoint Fragment %main \"main\"", 3571 "OpName %main \"main\"", 3572 "OpName %Live \"Live\"", 3573 "%void = OpTypeVoid", 3574 "%7 = OpTypeFunction %void", 3575 "%main = OpFunction %void None %7", 3576 "%15 = OpLabel", 3577 "%16 = OpFunctionCall %void %Live", 3578 "%17 = OpFunctionCall %void %Live", 3579 "OpReturn", 3580 "OpFunctionEnd", 3581 "%Live = OpFunction %void None %7", 3582 "%20 = OpLabel", 3583 "OpReturn", 3584 "OpFunctionEnd" 3585 // clang-format on 3586 }; 3587 3588 const std::vector<const char*> dead_function = { 3589 // clang-format off 3590 "%Dead = OpFunction %void None %7", 3591 "%19 = OpLabel", 3592 "OpReturn", 3593 "OpFunctionEnd", 3594 // clang-format on 3595 }; 3596 3597 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3598 SinglePassRunAndCheck<AggressiveDCEPass>( 3599 JoinAllInsts(Concat(common_code, dead_function)), 3600 JoinAllInsts(common_code), /* skip_nop = */ true); 3601} 3602 3603TEST_F(AggressiveDCETest, BasicKeepLiveFunction) { 3604 // Everything is reachable from an entry point, so no functions should be 3605 // deleted. 3606 const std::vector<const char*> text = { 3607 // clang-format off 3608 "OpCapability Shader", 3609 "OpMemoryModel Logical GLSL450", 3610 "OpEntryPoint Fragment %main \"main\"", 3611 "OpName %main \"main\"", 3612 "OpName %Live1 \"Live1\"", 3613 "OpName %Live2 \"Live2\"", 3614 "%void = OpTypeVoid", 3615 "%7 = OpTypeFunction %void", 3616 "%main = OpFunction %void None %7", 3617 "%15 = OpLabel", 3618 "%16 = OpFunctionCall %void %Live2", 3619 "%17 = OpFunctionCall %void %Live1", 3620 "OpReturn", 3621 "OpFunctionEnd", 3622 "%Live1 = OpFunction %void None %7", 3623 "%19 = OpLabel", 3624 "OpReturn", 3625 "OpFunctionEnd", 3626 "%Live2 = OpFunction %void None %7", 3627 "%20 = OpLabel", 3628 "OpReturn", 3629 "OpFunctionEnd" 3630 // clang-format on 3631 }; 3632 3633 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3634 std::string assembly = JoinAllInsts(text); 3635 auto result = SinglePassRunAndDisassemble<AggressiveDCEPass>( 3636 assembly, /* skip_nop = */ true, /* do_validation = */ false); 3637 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 3638 EXPECT_EQ(assembly, std::get<0>(result)); 3639} 3640 3641TEST_F(AggressiveDCETest, BasicRemoveDecorationsAndNames) { 3642 // We want to remove the names and decorations associated with results that 3643 // are removed. This test will check for that. 3644 const std::string text = R"( 3645 OpCapability Shader 3646 OpMemoryModel Logical GLSL450 3647 OpEntryPoint Vertex %main "main" 3648 OpName %main "main" 3649 OpName %Dead "Dead" 3650 OpName %x "x" 3651 OpName %y "y" 3652 OpName %z "z" 3653 OpDecorate %x RelaxedPrecision 3654 OpDecorate %y RelaxedPrecision 3655 OpDecorate %z RelaxedPrecision 3656 OpDecorate %6 RelaxedPrecision 3657 OpDecorate %7 RelaxedPrecision 3658 OpDecorate %8 RelaxedPrecision 3659 %void = OpTypeVoid 3660 %10 = OpTypeFunction %void 3661 %float = OpTypeFloat 32 3662%_ptr_Function_float = OpTypePointer Function %float 3663 %float_1 = OpConstant %float 1 3664 %main = OpFunction %void None %10 3665 %14 = OpLabel 3666 OpReturn 3667 OpFunctionEnd 3668 %Dead = OpFunction %void None %10 3669 %15 = OpLabel 3670 %x = OpVariable %_ptr_Function_float Function 3671 %y = OpVariable %_ptr_Function_float Function 3672 %z = OpVariable %_ptr_Function_float Function 3673 OpStore %x %float_1 3674 OpStore %y %float_1 3675 %6 = OpLoad %float %x 3676 %7 = OpLoad %float %y 3677 %8 = OpFAdd %float %6 %7 3678 OpStore %z %8 3679 OpReturn 3680 OpFunctionEnd)"; 3681 3682 const std::string expected_output = R"(OpCapability Shader 3683OpMemoryModel Logical GLSL450 3684OpEntryPoint Vertex %main "main" 3685OpName %main "main" 3686%void = OpTypeVoid 3687%10 = OpTypeFunction %void 3688%main = OpFunction %void None %10 3689%14 = OpLabel 3690OpReturn 3691OpFunctionEnd 3692)"; 3693 3694 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 3695 SinglePassRunAndCheck<AggressiveDCEPass>(text, expected_output, 3696 /* skip_nop = */ true); 3697} 3698 3699TEST_F(AggressiveDCETest, BasicAllDeadConstants) { 3700 const std::string text = R"( 3701 ; CHECK-NOT: OpConstant 3702 OpCapability Shader 3703 OpCapability Float64 3704 %1 = OpExtInstImport "GLSL.std.450" 3705 OpMemoryModel Logical GLSL450 3706 OpEntryPoint Vertex %main "main" 3707 OpName %main "main" 3708 %void = OpTypeVoid 3709 %4 = OpTypeFunction %void 3710 %bool = OpTypeBool 3711 %true = OpConstantTrue %bool 3712 %false = OpConstantFalse %bool 3713 %int = OpTypeInt 32 1 3714 %9 = OpConstant %int 1 3715 %uint = OpTypeInt 32 0 3716 %11 = OpConstant %uint 2 3717 %float = OpTypeFloat 32 3718 %13 = OpConstant %float 3.1415 3719 %double = OpTypeFloat 64 3720 %15 = OpConstant %double 3.14159265358979 3721 %main = OpFunction %void None %4 3722 %16 = OpLabel 3723 OpReturn 3724 OpFunctionEnd 3725 )"; 3726 3727 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 3728} 3729 3730TEST_F(AggressiveDCETest, BasicNoneDeadConstants) { 3731 const std::vector<const char*> text = { 3732 // clang-format off 3733 "OpCapability Shader", 3734 "OpCapability Float64", 3735 "%1 = OpExtInstImport \"GLSL.std.450\"", 3736 "OpMemoryModel Logical GLSL450", 3737 "OpEntryPoint Vertex %main \"main\" %btv %bfv %iv %uv %fv %dv", 3738 "OpName %main \"main\"", 3739 "OpName %btv \"btv\"", 3740 "OpName %bfv \"bfv\"", 3741 "OpName %iv \"iv\"", 3742 "OpName %uv \"uv\"", 3743 "OpName %fv \"fv\"", 3744 "OpName %dv \"dv\"", 3745 "%void = OpTypeVoid", 3746 "%10 = OpTypeFunction %void", 3747 "%bool = OpTypeBool", 3748 "%_ptr_Output_bool = OpTypePointer Output %bool", 3749 "%true = OpConstantTrue %bool", 3750 "%false = OpConstantFalse %bool", 3751 "%int = OpTypeInt 32 1", 3752 "%_ptr_Output_int = OpTypePointer Output %int", 3753 "%int_1 = OpConstant %int 1", 3754 "%uint = OpTypeInt 32 0", 3755 "%_ptr_Output_uint = OpTypePointer Output %uint", 3756 "%uint_2 = OpConstant %uint 2", 3757 "%float = OpTypeFloat 32", 3758 "%_ptr_Output_float = OpTypePointer Output %float", 3759 "%float_3_1415 = OpConstant %float 3.1415", 3760 "%double = OpTypeFloat 64", 3761 "%_ptr_Output_double = OpTypePointer Output %double", 3762 "%double_3_14159265358979 = OpConstant %double 3.14159265358979", 3763 "%btv = OpVariable %_ptr_Output_bool Output", 3764 "%bfv = OpVariable %_ptr_Output_bool Output", 3765 "%iv = OpVariable %_ptr_Output_int Output", 3766 "%uv = OpVariable %_ptr_Output_uint Output", 3767 "%fv = OpVariable %_ptr_Output_float Output", 3768 "%dv = OpVariable %_ptr_Output_double Output", 3769 "%main = OpFunction %void None %10", 3770 "%27 = OpLabel", 3771 "OpStore %btv %true", 3772 "OpStore %bfv %false", 3773 "OpStore %iv %int_1", 3774 "OpStore %uv %uint_2", 3775 "OpStore %fv %float_3_1415", 3776 "OpStore %dv %double_3_14159265358979", 3777 "OpReturn", 3778 "OpFunctionEnd", 3779 // clang-format on 3780 }; 3781 // All constants are used, so none of them should be eliminated. 3782 SinglePassRunAndCheck<AggressiveDCEPass>( 3783 JoinAllInsts(text), JoinAllInsts(text), /* skip_nop = */ true); 3784} 3785 3786struct AggressiveEliminateDeadConstantTestCase { 3787 // Type declarations and constants that should be kept. 3788 std::vector<std::string> used_consts; 3789 // Instructions that refer to constants, this is added to create uses for 3790 // some constants so they won't be treated as dead constants. 3791 std::vector<std::string> main_insts; 3792 // Dead constants that should be removed. 3793 std::vector<std::string> dead_consts; 3794 // Expectations 3795 std::vector<std::string> checks; 3796}; 3797 3798// All types that are potentially required in 3799// AggressiveEliminateDeadConstantTest. 3800const std::vector<std::string> CommonTypes = { 3801 // clang-format off 3802 // scalar types 3803 "%bool = OpTypeBool", 3804 "%uint = OpTypeInt 32 0", 3805 "%int = OpTypeInt 32 1", 3806 "%float = OpTypeFloat 32", 3807 "%double = OpTypeFloat 64", 3808 // vector types 3809 "%v2bool = OpTypeVector %bool 2", 3810 "%v2uint = OpTypeVector %uint 2", 3811 "%v2int = OpTypeVector %int 2", 3812 "%v3int = OpTypeVector %int 3", 3813 "%v4int = OpTypeVector %int 4", 3814 "%v2float = OpTypeVector %float 2", 3815 "%v3float = OpTypeVector %float 3", 3816 "%v2double = OpTypeVector %double 2", 3817 // variable pointer types 3818 "%_pf_bool = OpTypePointer Output %bool", 3819 "%_pf_uint = OpTypePointer Output %uint", 3820 "%_pf_int = OpTypePointer Output %int", 3821 "%_pf_float = OpTypePointer Output %float", 3822 "%_pf_double = OpTypePointer Output %double", 3823 "%_pf_v2int = OpTypePointer Output %v2int", 3824 "%_pf_v3int = OpTypePointer Output %v3int", 3825 "%_pf_v2float = OpTypePointer Output %v2float", 3826 "%_pf_v3float = OpTypePointer Output %v3float", 3827 "%_pf_v2double = OpTypePointer Output %v2double", 3828 // struct types 3829 "%inner_struct = OpTypeStruct %bool %int %float %double", 3830 "%outer_struct = OpTypeStruct %inner_struct %int %double", 3831 "%flat_struct = OpTypeStruct %bool %int %float %double", 3832 // clang-format on 3833}; 3834 3835using AggressiveEliminateDeadConstantTest = 3836 PassTest<::testing::TestWithParam<AggressiveEliminateDeadConstantTestCase>>; 3837 3838TEST_P(AggressiveEliminateDeadConstantTest, Custom) { 3839 auto& tc = GetParam(); 3840 AssemblyBuilder builder; 3841 builder.AppendTypesConstantsGlobals(CommonTypes) 3842 .AppendTypesConstantsGlobals(tc.used_consts) 3843 .AppendInMain(tc.main_insts); 3844 const std::string expected = builder.GetCode(); 3845 builder.AppendTypesConstantsGlobals(tc.dead_consts); 3846 builder.PrependPreamble(tc.checks); 3847 const std::string assembly_with_dead_const = builder.GetCode(); 3848 3849 // Do not enable validation. As the input code is invalid from the base 3850 // tests (ported from other passes). 3851 SinglePassRunAndMatch<AggressiveDCEPass>(assembly_with_dead_const, false); 3852} 3853 3854INSTANTIATE_TEST_SUITE_P( 3855 ScalarTypeConstants, AggressiveEliminateDeadConstantTest, 3856 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({ 3857 // clang-format off 3858 // Scalar type constants, one dead constant and one used constant. 3859 { 3860 /* .used_consts = */ 3861 { 3862 "%used_const_int = OpConstant %int 1", 3863 }, 3864 /* .main_insts = */ 3865 { 3866 "%int_var = OpVariable %_pf_int Output", 3867 "OpStore %int_var %used_const_int", 3868 }, 3869 /* .dead_consts = */ 3870 { 3871 "%dead_const_int = OpConstant %int 1", 3872 }, 3873 /* .checks = */ 3874 { 3875 "; CHECK: [[const:%\\w+]] = OpConstant %int 1", 3876 "; CHECK-NOT: OpConstant", 3877 "; CHECK: OpStore {{%\\w+}} [[const]]", 3878 }, 3879 }, 3880 { 3881 /* .used_consts = */ 3882 { 3883 "%used_const_uint = OpConstant %uint 1", 3884 }, 3885 /* .main_insts = */ 3886 { 3887 "%uint_var = OpVariable %_pf_uint Output", 3888 "OpStore %uint_var %used_const_uint", 3889 }, 3890 /* .dead_consts = */ 3891 { 3892 "%dead_const_uint = OpConstant %uint 1", 3893 }, 3894 /* .checks = */ 3895 { 3896 "; CHECK: [[const:%\\w+]] = OpConstant %uint 1", 3897 "; CHECK-NOT: OpConstant", 3898 "; CHECK: OpStore {{%\\w+}} [[const]]", 3899 }, 3900 }, 3901 { 3902 /* .used_consts = */ 3903 { 3904 "%used_const_float = OpConstant %float 3.1415", 3905 }, 3906 /* .main_insts = */ 3907 { 3908 "%float_var = OpVariable %_pf_float Output", 3909 "OpStore %float_var %used_const_float", 3910 }, 3911 /* .dead_consts = */ 3912 { 3913 "%dead_const_float = OpConstant %float 3.1415", 3914 }, 3915 /* .checks = */ 3916 { 3917 "; CHECK: [[const:%\\w+]] = OpConstant %float 3.1415", 3918 "; CHECK-NOT: OpConstant", 3919 "; CHECK: OpStore {{%\\w+}} [[const]]", 3920 }, 3921 }, 3922 { 3923 /* .used_consts = */ 3924 { 3925 "%used_const_double = OpConstant %double 3.14", 3926 }, 3927 /* .main_insts = */ 3928 { 3929 "%double_var = OpVariable %_pf_double Output", 3930 "OpStore %double_var %used_const_double", 3931 }, 3932 /* .dead_consts = */ 3933 { 3934 "%dead_const_double = OpConstant %double 3.14", 3935 }, 3936 /* .checks = */ 3937 { 3938 "; CHECK: [[const:%\\w+]] = OpConstant %double 3.14", 3939 "; CHECK-NOT: OpConstant", 3940 "; CHECK: OpStore {{%\\w+}} [[const]]", 3941 }, 3942 }, 3943 // clang-format on 3944 }))); 3945 3946INSTANTIATE_TEST_SUITE_P( 3947 VectorTypeConstants, AggressiveEliminateDeadConstantTest, 3948 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({ 3949 // clang-format off 3950 // Tests eliminating dead constant type ivec2. One dead constant vector 3951 // and one used constant vector, each built from its own group of 3952 // scalar constants. 3953 { 3954 /* .used_consts = */ 3955 { 3956 "%used_int_x = OpConstant %int 1", 3957 "%used_int_y = OpConstant %int 2", 3958 "%used_v2int = OpConstantComposite %v2int %used_int_x %used_int_y", 3959 }, 3960 /* .main_insts = */ 3961 { 3962 "%v2int_var = OpVariable %_pf_v2int Output", 3963 "OpStore %v2int_var %used_v2int", 3964 }, 3965 /* .dead_consts = */ 3966 { 3967 "%dead_int_x = OpConstant %int 1", 3968 "%dead_int_y = OpConstant %int 2", 3969 "%dead_v2int = OpConstantComposite %v2int %dead_int_x %dead_int_y", 3970 }, 3971 /* .checks = */ 3972 { 3973 "; CHECK: [[constx:%\\w+]] = OpConstant %int 1", 3974 "; CHECK: [[consty:%\\w+]] = OpConstant %int 2", 3975 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v2int [[constx]] [[consty]]", 3976 "; CHECK-NOT: OpConstant", 3977 "; CHECK: OpStore {{%\\w+}} [[const]]", 3978 }, 3979 }, 3980 // Tests eliminating dead constant ivec3. One dead constant vector and 3981 // one used constant vector. But both built from a same group of 3982 // scalar constants. 3983 { 3984 /* .used_consts = */ 3985 { 3986 "%used_int_x = OpConstant %int 1", 3987 "%used_int_y = OpConstant %int 2", 3988 "%used_int_z = OpConstant %int 3", 3989 "%used_v3int = OpConstantComposite %v3int %used_int_x %used_int_y %used_int_z", 3990 }, 3991 /* .main_insts = */ 3992 { 3993 "%v3int_var = OpVariable %_pf_v3int Output", 3994 "OpStore %v3int_var %used_v3int", 3995 }, 3996 /* .dead_consts = */ 3997 { 3998 "%dead_v3int = OpConstantComposite %v3int %used_int_x %used_int_y %used_int_z", 3999 }, 4000 /* .checks = */ 4001 { 4002 "; CHECK: [[constx:%\\w+]] = OpConstant %int 1", 4003 "; CHECK: [[consty:%\\w+]] = OpConstant %int 2", 4004 "; CHECK: [[constz:%\\w+]] = OpConstant %int 3", 4005 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v3int [[constx]] [[consty]] [[constz]]", 4006 "; CHECK-NOT: OpConstant", 4007 "; CHECK: OpStore {{%\\w+}} [[const]]", 4008 }, 4009 }, 4010 // Tests eliminating dead constant vec2. One dead constant vector and 4011 // one used constant vector. Each built from its own group of scalar 4012 // constants. 4013 { 4014 /* .used_consts = */ 4015 { 4016 "%used_float_x = OpConstant %float 3.1415", 4017 "%used_float_y = OpConstant %float 4.13", 4018 "%used_v2float = OpConstantComposite %v2float %used_float_x %used_float_y", 4019 }, 4020 /* .main_insts = */ 4021 { 4022 "%v2float_var = OpVariable %_pf_v2float Output", 4023 "OpStore %v2float_var %used_v2float", 4024 }, 4025 /* .dead_consts = */ 4026 { 4027 "%dead_float_x = OpConstant %float 3.1415", 4028 "%dead_float_y = OpConstant %float 4.13", 4029 "%dead_v2float = OpConstantComposite %v2float %dead_float_x %dead_float_y", 4030 }, 4031 /* .checks = */ 4032 { 4033 "; CHECK: [[constx:%\\w+]] = OpConstant %float 3.1415", 4034 "; CHECK: [[consty:%\\w+]] = OpConstant %float 4.13", 4035 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v2float [[constx]] [[consty]]", 4036 "; CHECK-NOT: OpConstant", 4037 "; CHECK: OpStore {{%\\w+}} [[const]]", 4038 }, 4039 }, 4040 // Tests eliminating dead constant vec3. One dead constant vector and 4041 // one used constant vector. Both built from a same group of scalar 4042 // constants. 4043 { 4044 /* .used_consts = */ 4045 { 4046 "%used_float_x = OpConstant %float 3.1415", 4047 "%used_float_y = OpConstant %float 4.25", 4048 "%used_float_z = OpConstant %float 4.75", 4049 "%used_v3float = OpConstantComposite %v3float %used_float_x %used_float_y %used_float_z", 4050 }, 4051 /* .main_insts = */ 4052 { 4053 "%v3float_var = OpVariable %_pf_v3float Output", 4054 "OpStore %v3float_var %used_v3float", 4055 }, 4056 /* .dead_consts = */ 4057 { 4058 "%dead_v3float = OpConstantComposite %v3float %used_float_x %used_float_y %used_float_z", 4059 }, 4060 /* .checks = */ 4061 { 4062 "; CHECK: [[constx:%\\w+]] = OpConstant %float 3.1415", 4063 "; CHECK: [[consty:%\\w+]] = OpConstant %float 4.25", 4064 "; CHECK: [[constz:%\\w+]] = OpConstant %float 4.75", 4065 "; CHECK: [[const:%\\w+]] = OpConstantComposite %v3float [[constx]] [[consty]]", 4066 "; CHECK-NOT: OpConstant", 4067 "; CHECK: OpStore {{%\\w+}} [[const]]", 4068 }, 4069 }, 4070 // clang-format on 4071 }))); 4072 4073INSTANTIATE_TEST_SUITE_P( 4074 StructTypeConstants, AggressiveEliminateDeadConstantTest, 4075 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({ 4076 // clang-format off 4077 // A plain struct type dead constants. All of its components are dead 4078 // constants too. 4079 { 4080 /* .used_consts = */ {}, 4081 /* .main_insts = */ {}, 4082 /* .dead_consts = */ 4083 { 4084 "%dead_bool = OpConstantTrue %bool", 4085 "%dead_int = OpConstant %int 1", 4086 "%dead_float = OpConstant %float 2.5", 4087 "%dead_double = OpConstant %double 3.14159265358979", 4088 "%dead_struct = OpConstantComposite %flat_struct %dead_bool %dead_int %dead_float %dead_double", 4089 }, 4090 /* .checks = */ 4091 { 4092 "; CHECK-NOT: OpConstant", 4093 }, 4094 }, 4095 // A plain struct type dead constants. Some of its components are dead 4096 // constants while others are not. 4097 { 4098 /* .used_consts = */ 4099 { 4100 "%used_int = OpConstant %int 1", 4101 "%used_double = OpConstant %double 3.14159265358979", 4102 }, 4103 /* .main_insts = */ 4104 { 4105 "%int_var = OpVariable %_pf_int Output", 4106 "OpStore %int_var %used_int", 4107 "%double_var = OpVariable %_pf_double Output", 4108 "OpStore %double_var %used_double", 4109 }, 4110 /* .dead_consts = */ 4111 { 4112 "%dead_bool = OpConstantTrue %bool", 4113 "%dead_float = OpConstant %float 2.5", 4114 "%dead_struct = OpConstantComposite %flat_struct %dead_bool %used_int %dead_float %used_double", 4115 }, 4116 /* .checks = */ 4117 { 4118 "; CHECK: [[int:%\\w+]] = OpConstant %int 1", 4119 "; CHECK: [[double:%\\w+]] = OpConstant %double 3.14159265358979", 4120 "; CHECK-NOT: OpConstant", 4121 "; CHECK: OpStore {{%\\w+}} [[int]]", 4122 "; CHECK: OpStore {{%\\w+}} [[double]]", 4123 }, 4124 }, 4125 // A nesting struct type dead constants. All components of both outer 4126 // and inner structs are dead and should be removed after dead constant 4127 // elimination. 4128 { 4129 /* .used_consts = */ {}, 4130 /* .main_insts = */ {}, 4131 /* .dead_consts = */ 4132 { 4133 "%dead_bool = OpConstantTrue %bool", 4134 "%dead_int = OpConstant %int 1", 4135 "%dead_float = OpConstant %float 2.5", 4136 "%dead_double = OpConstant %double 3.1415926535", 4137 "%dead_inner_struct = OpConstantComposite %inner_struct %dead_bool %dead_int %dead_float %dead_double", 4138 "%dead_int2 = OpConstant %int 2", 4139 "%dead_double2 = OpConstant %double 1.428571428514", 4140 "%dead_outer_struct = OpConstantComposite %outer_struct %dead_inner_struct %dead_int2 %dead_double2", 4141 }, 4142 /* .checks = */ 4143 { 4144 "; CHECK-NOT: OpConstant", 4145 }, 4146 }, 4147 // A nesting struct type dead constants. Some of its components are 4148 // dead constants while others are not. 4149 { 4150 /* .used_consts = */ 4151 { 4152 "%used_int = OpConstant %int 1", 4153 "%used_double = OpConstant %double 3.14159265358979", 4154 }, 4155 /* .main_insts = */ 4156 { 4157 "%int_var = OpVariable %_pf_int Output", 4158 "OpStore %int_var %used_int", 4159 "%double_var = OpVariable %_pf_double Output", 4160 "OpStore %double_var %used_double", 4161 }, 4162 /* .dead_consts = */ 4163 { 4164 "%dead_bool = OpConstantTrue %bool", 4165 "%dead_float = OpConstant %float 2.5", 4166 "%dead_inner_struct = OpConstantComposite %inner_struct %dead_bool %used_int %dead_float %used_double", 4167 "%dead_int = OpConstant %int 2", 4168 "%dead_outer_struct = OpConstantComposite %outer_struct %dead_inner_struct %dead_int %used_double", 4169 }, 4170 /* .checks = */ 4171 { 4172 "; CHECK: [[int:%\\w+]] = OpConstant %int 1", 4173 "; CHECK: [[double:%\\w+]] = OpConstant %double 3.14159265358979", 4174 "; CHECK-NOT: OpConstant", 4175 "; CHECK: OpStore {{%\\w+}} [[int]]", 4176 "; CHECK: OpStore {{%\\w+}} [[double]]", 4177 }, 4178 }, 4179 // A nesting struct case. The inner struct is used while the outer struct is not 4180 { 4181 /* .used_const = */ 4182 { 4183 "%used_bool = OpConstantTrue %bool", 4184 "%used_int = OpConstant %int 1", 4185 "%used_float = OpConstant %float 1.23", 4186 "%used_double = OpConstant %double 1.2345678901234", 4187 "%used_inner_struct = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double", 4188 }, 4189 /* .main_insts = */ 4190 { 4191 "%bool_var = OpVariable %_pf_bool Output", 4192 "%bool_from_inner_struct = OpCompositeExtract %bool %used_inner_struct 0", 4193 "OpStore %bool_var %bool_from_inner_struct", 4194 }, 4195 /* .dead_consts = */ 4196 { 4197 "%dead_int = OpConstant %int 2", 4198 "%dead_outer_struct = OpConstantComposite %outer_struct %used_inner_struct %dead_int %used_double" 4199 }, 4200 /* .checks = */ 4201 { 4202 "; CHECK: [[bool:%\\w+]] = OpConstantTrue", 4203 "; CHECK: [[int:%\\w+]] = OpConstant %int 1", 4204 "; CHECK: [[float:%\\w+]] = OpConstant %float 1.23", 4205 "; CHECK: [[double:%\\w+]] = OpConstant %double 1.2345678901234", 4206 "; CHECK: [[struct:%\\w+]] = OpConstantComposite %inner_struct [[bool]] [[int]] [[float]] [[double]]", 4207 "; CHECK-NOT: OpConstant", 4208 "; CHECK: OpCompositeExtract %bool [[struct]]", 4209 } 4210 }, 4211 // A nesting struct case. The outer struct is used, so the inner struct should not 4212 // be removed even though it is not used anywhere. 4213 { 4214 /* .used_const = */ 4215 { 4216 "%used_bool = OpConstantTrue %bool", 4217 "%used_int = OpConstant %int 1", 4218 "%used_float = OpConstant %float 1.23", 4219 "%used_double = OpConstant %double 1.2345678901234", 4220 "%used_inner_struct = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double", 4221 "%used_outer_struct = OpConstantComposite %outer_struct %used_inner_struct %used_int %used_double" 4222 }, 4223 /* .main_insts = */ 4224 { 4225 "%int_var = OpVariable %_pf_int Output", 4226 "%int_from_outer_struct = OpCompositeExtract %int %used_outer_struct 1", 4227 "OpStore %int_var %int_from_outer_struct", 4228 }, 4229 /* .dead_consts = */ {}, 4230 /* .checks = */ 4231 { 4232 "; CHECK: [[bool:%\\w+]] = OpConstantTrue %bool", 4233 "; CHECK: [[int:%\\w+]] = OpConstant %int 1", 4234 "; CHECK: [[float:%\\w+]] = OpConstant %float 1.23", 4235 "; CHECK: [[double:%\\w+]] = OpConstant %double 1.2345678901234", 4236 "; CHECK: [[inner_struct:%\\w+]] = OpConstantComposite %inner_struct %used_bool %used_int %used_float %used_double", 4237 "; CHECK: [[outer_struct:%\\w+]] = OpConstantComposite %outer_struct %used_inner_struct %used_int %used_double", 4238 "; CHECK: OpCompositeExtract %int [[outer_struct]]", 4239 }, 4240 }, 4241 // clang-format on 4242 }))); 4243 4244INSTANTIATE_TEST_SUITE_P( 4245 ScalarTypeSpecConstants, AggressiveEliminateDeadConstantTest, 4246 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({ 4247 // clang-format off 4248 // All scalar type spec constants. 4249 { 4250 /* .used_consts = */ 4251 { 4252 "%used_bool = OpSpecConstantTrue %bool", 4253 "%used_uint = OpSpecConstant %uint 2", 4254 "%used_int = OpSpecConstant %int 2", 4255 "%used_float = OpSpecConstant %float 2.5", 4256 "%used_double = OpSpecConstant %double 1.428571428514", 4257 }, 4258 /* .main_insts = */ 4259 { 4260 "%bool_var = OpVariable %_pf_bool Output", 4261 "%uint_var = OpVariable %_pf_uint Output", 4262 "%int_var = OpVariable %_pf_int Output", 4263 "%float_var = OpVariable %_pf_float Output", 4264 "%double_var = OpVariable %_pf_double Output", 4265 "OpStore %bool_var %used_bool", 4266 "OpStore %uint_var %used_uint", 4267 "OpStore %int_var %used_int", 4268 "OpStore %float_var %used_float", 4269 "OpStore %double_var %used_double", 4270 }, 4271 /* .dead_consts = */ 4272 { 4273 "%dead_bool = OpSpecConstantTrue %bool", 4274 "%dead_uint = OpSpecConstant %uint 2", 4275 "%dead_int = OpSpecConstant %int 2", 4276 "%dead_float = OpSpecConstant %float 2.5", 4277 "%dead_double = OpSpecConstant %double 1.428571428514", 4278 }, 4279 /* .checks = */ 4280 { 4281 "; CHECK: [[bool:%\\w+]] = OpSpecConstantTrue %bool", 4282 "; CHECK: [[uint:%\\w+]] = OpSpecConstant %uint 2", 4283 "; CHECK: [[int:%\\w+]] = OpSpecConstant %int 2", 4284 "; CHECK: [[float:%\\w+]] = OpSpecConstant %float 2.5", 4285 "; CHECK: [[double:%\\w+]] = OpSpecConstant %double 1.428571428514", 4286 "; CHECK-NOT: OpSpecConstant", 4287 "; CHECK: OpStore {{%\\w+}} [[bool]]", 4288 "; CHECK: OpStore {{%\\w+}} [[uint]]", 4289 "; CHECK: OpStore {{%\\w+}} [[int]]", 4290 "; CHECK: OpStore {{%\\w+}} [[float]]", 4291 "; CHECK: OpStore {{%\\w+}} [[double]]", 4292 }, 4293 }, 4294 // clang-format on 4295 }))); 4296 4297INSTANTIATE_TEST_SUITE_P( 4298 VectorTypeSpecConstants, AggressiveEliminateDeadConstantTest, 4299 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({ 4300 // clang-format off 4301 // Bool vector type spec constants. One vector has all component dead, 4302 // another vector has one dead boolean and one used boolean. 4303 { 4304 /* .used_consts = */ 4305 { 4306 "%used_bool = OpSpecConstantTrue %bool", 4307 }, 4308 /* .main_insts = */ 4309 { 4310 "%bool_var = OpVariable %_pf_bool Output", 4311 "OpStore %bool_var %used_bool", 4312 }, 4313 /* .dead_consts = */ 4314 { 4315 "%dead_bool = OpSpecConstantFalse %bool", 4316 "%dead_bool_vec1 = OpSpecConstantComposite %v2bool %dead_bool %dead_bool", 4317 "%dead_bool_vec2 = OpSpecConstantComposite %v2bool %dead_bool %used_bool", 4318 }, 4319 /* .checks = */ 4320 { 4321 "; CHECK: [[bool:%\\w+]] = OpSpecConstantTrue %bool", 4322 "; CHECK-NOT: OpSpecConstant", 4323 "; CHECK: OpStore {{%\\w+}} [[bool]]", 4324 }, 4325 }, 4326 4327 // Uint vector type spec constants. One vector has all component dead, 4328 // another vector has one dead unsigned integer and one used unsigned 4329 // integer. 4330 { 4331 /* .used_consts = */ 4332 { 4333 "%used_uint = OpSpecConstant %uint 3", 4334 }, 4335 /* .main_insts = */ 4336 { 4337 "%uint_var = OpVariable %_pf_uint Output", 4338 "OpStore %uint_var %used_uint", 4339 }, 4340 /* .dead_consts = */ 4341 { 4342 "%dead_uint = OpSpecConstant %uint 1", 4343 "%dead_uint_vec1 = OpSpecConstantComposite %v2uint %dead_uint %dead_uint", 4344 "%dead_uint_vec2 = OpSpecConstantComposite %v2uint %dead_uint %used_uint", 4345 }, 4346 /* .checks = */ 4347 { 4348 "; CHECK: [[uint:%\\w+]] = OpSpecConstant %uint 3", 4349 "; CHECK-NOT: OpSpecConstant", 4350 "; CHECK: OpStore {{%\\w+}} [[uint]]", 4351 }, 4352 }, 4353 4354 // Int vector type spec constants. One vector has all component dead, 4355 // another vector has one dead integer and one used integer. 4356 { 4357 /* .used_consts = */ 4358 { 4359 "%used_int = OpSpecConstant %int 3", 4360 }, 4361 /* .main_insts = */ 4362 { 4363 "%int_var = OpVariable %_pf_int Output", 4364 "OpStore %int_var %used_int", 4365 }, 4366 /* .dead_consts = */ 4367 { 4368 "%dead_int = OpSpecConstant %int 1", 4369 "%dead_int_vec1 = OpSpecConstantComposite %v2int %dead_int %dead_int", 4370 "%dead_int_vec2 = OpSpecConstantComposite %v2int %dead_int %used_int", 4371 }, 4372 /* .checks = */ 4373 { 4374 "; CHECK: [[int:%\\w+]] = OpSpecConstant %int 3", 4375 "; CHECK-NOT: OpSpecConstant", 4376 "; CHECK: OpStore {{%\\w+}} [[int]]", 4377 }, 4378 }, 4379 4380 // Int vector type spec constants built with both spec constants and 4381 // front-end constants. 4382 { 4383 /* .used_consts = */ 4384 { 4385 "%used_spec_int = OpSpecConstant %int 3", 4386 "%used_front_end_int = OpConstant %int 3", 4387 }, 4388 /* .main_insts = */ 4389 { 4390 "%int_var1 = OpVariable %_pf_int Output", 4391 "OpStore %int_var1 %used_spec_int", 4392 "%int_var2 = OpVariable %_pf_int Output", 4393 "OpStore %int_var2 %used_front_end_int", 4394 }, 4395 /* .dead_consts = */ 4396 { 4397 "%dead_spec_int = OpSpecConstant %int 1", 4398 "%dead_front_end_int = OpConstant %int 1", 4399 // Dead front-end and dead spec constants 4400 "%dead_int_vec1 = OpSpecConstantComposite %v2int %dead_spec_int %dead_front_end_int", 4401 // Used front-end and dead spec constants 4402 "%dead_int_vec2 = OpSpecConstantComposite %v2int %dead_spec_int %used_front_end_int", 4403 // Dead front-end and used spec constants 4404 "%dead_int_vec3 = OpSpecConstantComposite %v2int %dead_front_end_int %used_spec_int", 4405 }, 4406 /* .checks = */ 4407 { 4408 "; CHECK: [[int1:%\\w+]] = OpSpecConstant %int 3", 4409 "; CHECK: [[int2:%\\w+]] = OpConstant %int 3", 4410 "; CHECK-NOT: OpSpecConstant", 4411 "; CHECK-NOT: OpConstant", 4412 "; CHECK: OpStore {{%\\w+}} [[int1]]", 4413 "; CHECK: OpStore {{%\\w+}} [[int2]]", 4414 }, 4415 }, 4416 // clang-format on 4417 }))); 4418 4419INSTANTIATE_TEST_SUITE_P( 4420 SpecConstantOp, AggressiveEliminateDeadConstantTest, 4421 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({ 4422 // clang-format off 4423 // Cast operations: uint <-> int <-> bool 4424 { 4425 /* .used_consts = */ {}, 4426 /* .main_insts = */ {}, 4427 /* .dead_consts = */ 4428 { 4429 // Assistant constants, only used in dead spec constant 4430 // operations. 4431 "%signed_zero = OpConstant %int 0", 4432 "%signed_zero_vec = OpConstantComposite %v2int %signed_zero %signed_zero", 4433 "%unsigned_zero = OpConstant %uint 0", 4434 "%unsigned_zero_vec = OpConstantComposite %v2uint %unsigned_zero %unsigned_zero", 4435 "%signed_one = OpConstant %int 1", 4436 "%signed_one_vec = OpConstantComposite %v2int %signed_one %signed_one", 4437 "%unsigned_one = OpConstant %uint 1", 4438 "%unsigned_one_vec = OpConstantComposite %v2uint %unsigned_one %unsigned_one", 4439 4440 // Spec constants that support casting to each other. 4441 "%dead_bool = OpSpecConstantTrue %bool", 4442 "%dead_uint = OpSpecConstant %uint 1", 4443 "%dead_int = OpSpecConstant %int 2", 4444 "%dead_bool_vec = OpSpecConstantComposite %v2bool %dead_bool %dead_bool", 4445 "%dead_uint_vec = OpSpecConstantComposite %v2uint %dead_uint %dead_uint", 4446 "%dead_int_vec = OpSpecConstantComposite %v2int %dead_int %dead_int", 4447 4448 // Scalar cast to boolean spec constant. 4449 "%int_to_bool = OpSpecConstantOp %bool INotEqual %dead_int %signed_zero", 4450 "%uint_to_bool = OpSpecConstantOp %bool INotEqual %dead_uint %unsigned_zero", 4451 4452 // Vector cast to boolean spec constant. 4453 "%int_to_bool_vec = OpSpecConstantOp %v2bool INotEqual %dead_int_vec %signed_zero_vec", 4454 "%uint_to_bool_vec = OpSpecConstantOp %v2bool INotEqual %dead_uint_vec %unsigned_zero_vec", 4455 4456 // Scalar cast to int spec constant. 4457 "%bool_to_int = OpSpecConstantOp %int Select %dead_bool %signed_one %signed_zero", 4458 "%uint_to_int = OpSpecConstantOp %uint IAdd %dead_uint %unsigned_zero", 4459 4460 // Vector cast to int spec constant. 4461 "%bool_to_int_vec = OpSpecConstantOp %v2int Select %dead_bool_vec %signed_one_vec %signed_zero_vec", 4462 "%uint_to_int_vec = OpSpecConstantOp %v2uint IAdd %dead_uint_vec %unsigned_zero_vec", 4463 4464 // Scalar cast to uint spec constant. 4465 "%bool_to_uint = OpSpecConstantOp %uint Select %dead_bool %unsigned_one %unsigned_zero", 4466 "%int_to_uint_vec = OpSpecConstantOp %uint IAdd %dead_int %signed_zero", 4467 4468 // Vector cast to uint spec constant. 4469 "%bool_to_uint_vec = OpSpecConstantOp %v2uint Select %dead_bool_vec %unsigned_one_vec %unsigned_zero_vec", 4470 "%int_to_uint = OpSpecConstantOp %v2uint IAdd %dead_int_vec %signed_zero_vec", 4471 }, 4472 /* .checks = */ 4473 { 4474 "; CHECK-NOT: OpConstant", 4475 "; CHECK-NOT: OpSpecConstant", 4476 }, 4477 }, 4478 4479 // Add, sub, mul, div, rem. 4480 { 4481 /* .used_consts = */ {}, 4482 /* .main_insts = */ {}, 4483 /* .dead_consts = */ 4484 { 4485 "%dead_spec_int_a = OpSpecConstant %int 1", 4486 "%dead_spec_int_a_vec = OpSpecConstantComposite %v2int %dead_spec_int_a %dead_spec_int_a", 4487 4488 "%dead_spec_int_b = OpSpecConstant %int 2", 4489 "%dead_spec_int_b_vec = OpSpecConstantComposite %v2int %dead_spec_int_b %dead_spec_int_b", 4490 4491 "%dead_const_int_c = OpConstant %int 3", 4492 "%dead_const_int_c_vec = OpConstantComposite %v2int %dead_const_int_c %dead_const_int_c", 4493 4494 // Add 4495 "%add_a_b = OpSpecConstantOp %int IAdd %dead_spec_int_a %dead_spec_int_b", 4496 "%add_a_b_vec = OpSpecConstantOp %v2int IAdd %dead_spec_int_a_vec %dead_spec_int_b_vec", 4497 4498 // Sub 4499 "%sub_a_b = OpSpecConstantOp %int ISub %dead_spec_int_a %dead_spec_int_b", 4500 "%sub_a_b_vec = OpSpecConstantOp %v2int ISub %dead_spec_int_a_vec %dead_spec_int_b_vec", 4501 4502 // Mul 4503 "%mul_a_b = OpSpecConstantOp %int IMul %dead_spec_int_a %dead_spec_int_b", 4504 "%mul_a_b_vec = OpSpecConstantOp %v2int IMul %dead_spec_int_a_vec %dead_spec_int_b_vec", 4505 4506 // Div 4507 "%div_a_b = OpSpecConstantOp %int SDiv %dead_spec_int_a %dead_spec_int_b", 4508 "%div_a_b_vec = OpSpecConstantOp %v2int SDiv %dead_spec_int_a_vec %dead_spec_int_b_vec", 4509 4510 // Bitwise Xor 4511 "%xor_a_b = OpSpecConstantOp %int BitwiseXor %dead_spec_int_a %dead_spec_int_b", 4512 "%xor_a_b_vec = OpSpecConstantOp %v2int BitwiseXor %dead_spec_int_a_vec %dead_spec_int_b_vec", 4513 4514 // Scalar Comparison 4515 "%less_a_b = OpSpecConstantOp %bool SLessThan %dead_spec_int_a %dead_spec_int_b", 4516 }, 4517 /* .checks = */ 4518 { 4519 "; CHECK-NOT: OpConstant", 4520 "; CHECK-NOT: OpSpecConstant", 4521 }, 4522 }, 4523 4524 // Vectors without used swizzles should be removed. 4525 { 4526 /* .used_consts = */ 4527 { 4528 "%used_int = OpConstant %int 3", 4529 }, 4530 /* .main_insts = */ 4531 { 4532 "%int_var = OpVariable %_pf_int Output", 4533 "OpStore %int_var %used_int", 4534 }, 4535 /* .dead_consts = */ 4536 { 4537 "%dead_int = OpConstant %int 3", 4538 4539 "%dead_spec_int_a = OpSpecConstant %int 1", 4540 "%vec_a = OpSpecConstantComposite %v4int %dead_spec_int_a %dead_spec_int_a %dead_int %dead_int", 4541 4542 "%dead_spec_int_b = OpSpecConstant %int 2", 4543 "%vec_b = OpSpecConstantComposite %v4int %dead_spec_int_b %dead_spec_int_b %used_int %used_int", 4544 4545 // Extract scalar 4546 "%a_x = OpSpecConstantOp %int CompositeExtract %vec_a 0", 4547 "%b_x = OpSpecConstantOp %int CompositeExtract %vec_b 0", 4548 4549 // Extract vector 4550 "%a_xy = OpSpecConstantOp %v2int VectorShuffle %vec_a %vec_a 0 1", 4551 "%b_xy = OpSpecConstantOp %v2int VectorShuffle %vec_b %vec_b 0 1", 4552 }, 4553 /* .checks = */ 4554 { 4555 "; CHECK: [[int:%\\w+]] = OpConstant %int 3", 4556 "; CHECK-NOT: OpConstant", 4557 "; CHECK-NOT: OpSpecConstant", 4558 "; CHECK: OpStore {{%\\w+}} [[int]]", 4559 }, 4560 }, 4561 // Vectors with used swizzles should not be removed. 4562 { 4563 /* .used_consts = */ 4564 { 4565 "%used_int = OpConstant %int 3", 4566 "%used_spec_int_a = OpSpecConstant %int 1", 4567 "%used_spec_int_b = OpSpecConstant %int 2", 4568 // Create vectors 4569 "%vec_a = OpSpecConstantComposite %v4int %used_spec_int_a %used_spec_int_a %used_int %used_int", 4570 "%vec_b = OpSpecConstantComposite %v4int %used_spec_int_b %used_spec_int_b %used_int %used_int", 4571 // Extract vector 4572 "%a_xy = OpSpecConstantOp %v2int VectorShuffle %vec_a %vec_a 0 1", 4573 "%b_xy = OpSpecConstantOp %v2int VectorShuffle %vec_b %vec_b 0 1", 4574 }, 4575 /* .main_insts = */ 4576 { 4577 "%v2int_var_a = OpVariable %_pf_v2int Output", 4578 "%v2int_var_b = OpVariable %_pf_v2int Output", 4579 "OpStore %v2int_var_a %a_xy", 4580 "OpStore %v2int_var_b %b_xy", 4581 }, 4582 /* .dead_consts = */ {}, 4583 /* .checks = */ 4584 { 4585 "; CHECK: [[int:%\\w+]] = OpConstant %int 3", 4586 "; CHECK: [[a:%\\w+]] = OpSpecConstant %int 1", 4587 "; CHECK: [[b:%\\w+]] = OpSpecConstant %int 2", 4588 "; CHECK: [[veca:%\\w+]] = OpSpecConstantComposite %v4int [[a]] [[a]] [[int]] [[int]]", 4589 "; CHECK: [[vecb:%\\w+]] = OpSpecConstantComposite %v4int [[b]] [[b]] [[int]] [[int]]", 4590 "; CHECK: [[exa:%\\w+]] = OpSpecConstantOp %v2int VectorShuffle [[veca]] [[veca]] 0 1", 4591 "; CHECK: [[exb:%\\w+]] = OpSpecConstantOp %v2int VectorShuffle [[vecb]] [[vecb]] 0 1", 4592 "; CHECK-NOT: OpConstant", 4593 "; CHECK-NOT: OpSpecConstant", 4594 "; CHECK: OpStore {{%\\w+}} [[exa]]", 4595 "; CHECK: OpStore {{%\\w+}} [[exb]]", 4596 }, 4597 }, 4598 // clang-format on 4599 }))); 4600 4601INSTANTIATE_TEST_SUITE_P( 4602 LongDefUseChain, AggressiveEliminateDeadConstantTest, 4603 ::testing::ValuesIn(std::vector<AggressiveEliminateDeadConstantTestCase>({ 4604 // clang-format off 4605 // Long Def-Use chain with binary operations. 4606 { 4607 /* .used_consts = */ 4608 { 4609 "%array_size = OpConstant %int 4", 4610 "%type_arr_int_4 = OpTypeArray %int %array_size", 4611 "%used_int_0 = OpConstant %int 100", 4612 "%used_int_1 = OpConstant %int 1", 4613 "%used_int_2 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_1", 4614 "%used_int_3 = OpSpecConstantOp %int ISub %used_int_0 %used_int_2", 4615 "%used_int_4 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_3", 4616 "%used_int_5 = OpSpecConstantOp %int ISub %used_int_0 %used_int_4", 4617 "%used_int_6 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_5", 4618 "%used_int_7 = OpSpecConstantOp %int ISub %used_int_0 %used_int_6", 4619 "%used_int_8 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_7", 4620 "%used_int_9 = OpSpecConstantOp %int ISub %used_int_0 %used_int_8", 4621 "%used_int_10 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_9", 4622 "%used_int_11 = OpSpecConstantOp %int ISub %used_int_0 %used_int_10", 4623 "%used_int_12 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_11", 4624 "%used_int_13 = OpSpecConstantOp %int ISub %used_int_0 %used_int_12", 4625 "%used_int_14 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_13", 4626 "%used_int_15 = OpSpecConstantOp %int ISub %used_int_0 %used_int_14", 4627 "%used_int_16 = OpSpecConstantOp %int ISub %used_int_0 %used_int_15", 4628 "%used_int_17 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_16", 4629 "%used_int_18 = OpSpecConstantOp %int ISub %used_int_0 %used_int_17", 4630 "%used_int_19 = OpSpecConstantOp %int IAdd %used_int_0 %used_int_18", 4631 "%used_int_20 = OpSpecConstantOp %int ISub %used_int_0 %used_int_19", 4632 "%used_vec_a = OpSpecConstantComposite %v2int %used_int_18 %used_int_19", 4633 "%used_vec_b = OpSpecConstantOp %v2int IMul %used_vec_a %used_vec_a", 4634 "%used_int_21 = OpSpecConstantOp %int CompositeExtract %used_vec_b 0", 4635 "%used_array = OpConstantComposite %type_arr_int_4 %used_int_20 %used_int_20 %used_int_21 %used_int_21", 4636 }, 4637 /* .main_insts = */ 4638 { 4639 "%int_var = OpVariable %_pf_int Output", 4640 "%used_array_2 = OpCompositeExtract %int %used_array 2", 4641 "OpStore %int_var %used_array_2", 4642 }, 4643 /* .dead_consts = */ 4644 { 4645 "%dead_int_1 = OpConstant %int 2", 4646 "%dead_int_2 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_1", 4647 "%dead_int_3 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_2", 4648 "%dead_int_4 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_3", 4649 "%dead_int_5 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_4", 4650 "%dead_int_6 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_5", 4651 "%dead_int_7 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_6", 4652 "%dead_int_8 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_7", 4653 "%dead_int_9 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_8", 4654 "%dead_int_10 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_9", 4655 "%dead_int_11 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_10", 4656 "%dead_int_12 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_11", 4657 "%dead_int_13 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_12", 4658 "%dead_int_14 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_13", 4659 "%dead_int_15 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_14", 4660 "%dead_int_16 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_15", 4661 "%dead_int_17 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_16", 4662 "%dead_int_18 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_17", 4663 "%dead_int_19 = OpSpecConstantOp %int IAdd %used_int_0 %dead_int_18", 4664 "%dead_int_20 = OpSpecConstantOp %int ISub %used_int_0 %dead_int_19", 4665 "%dead_vec_a = OpSpecConstantComposite %v2int %dead_int_18 %dead_int_19", 4666 "%dead_vec_b = OpSpecConstantOp %v2int IMul %dead_vec_a %dead_vec_a", 4667 "%dead_int_21 = OpSpecConstantOp %int CompositeExtract %dead_vec_b 0", 4668 "%dead_array = OpConstantComposite %type_arr_int_4 %dead_int_20 %used_int_20 %dead_int_19 %used_int_19", 4669 }, 4670 /* .checks = */ 4671 { 4672 "; CHECK: OpConstant %int 4", 4673 "; CHECK: [[array:%\\w+]] = OpConstantComposite %type_arr_int_4 %used_int_20 %used_int_20 %used_int_21 %used_int_21", 4674 "; CHECK-NOT: OpConstant", 4675 "; CHECK-NOT: OpSpecConstant", 4676 "; CHECK: OpStore {{%\\w+}} [[array]]", 4677 }, 4678 }, 4679 // Long Def-Use chain with swizzle 4680 // clang-format on 4681 }))); 4682 4683TEST_F(AggressiveDCETest, DeadDecorationGroup) { 4684 // The decoration group should be eliminated because the target of group 4685 // decorate is dead. 4686 const std::string text = R"( 4687; CHECK-NOT: OpDecorat 4688; CHECK-NOT: OpGroupDecorate 4689OpCapability Shader 4690OpMemoryModel Logical GLSL450 4691OpEntryPoint Fragment %main "main" 4692OpExecutionMode %main OriginUpperLeft 4693OpDecorate %1 Restrict 4694OpDecorate %1 Aliased 4695%1 = OpDecorationGroup 4696OpGroupDecorate %1 %var 4697%void = OpTypeVoid 4698%func = OpTypeFunction %void 4699%uint = OpTypeInt 32 0 4700%uint_ptr = OpTypePointer Function %uint 4701%main = OpFunction %void None %func 4702%2 = OpLabel 4703%var = OpVariable %uint_ptr Function 4704OpReturn 4705OpFunctionEnd 4706 )"; 4707 4708 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 4709} 4710 4711TEST_F(AggressiveDCETest, DeadDecorationGroupAndValidDecorationMgr) { 4712 // The decoration group should be eliminated because the target of group 4713 // decorate is dead. 4714 const std::string text = R"( 4715OpCapability Shader 4716OpMemoryModel Logical GLSL450 4717OpEntryPoint Fragment %main "main" 4718OpExecutionMode %main OriginUpperLeft 4719OpDecorate %1 Restrict 4720OpDecorate %1 Aliased 4721%1 = OpDecorationGroup 4722OpGroupDecorate %1 %var 4723%void = OpTypeVoid 4724%func = OpTypeFunction %void 4725%uint = OpTypeInt 32 0 4726%uint_ptr = OpTypePointer Function %uint 4727%main = OpFunction %void None %func 4728%2 = OpLabel 4729%var = OpVariable %uint_ptr Function 4730OpReturn 4731OpFunctionEnd 4732 )"; 4733 4734 auto pass = MakeUnique<AggressiveDCEPass>(); 4735 auto consumer = [](spv_message_level_t, const char*, const spv_position_t&, 4736 const char* message) { 4737 std::cerr << message << std::endl; 4738 }; 4739 auto context = BuildModule(SPV_ENV_UNIVERSAL_1_1, consumer, text); 4740 4741 // Build the decoration manager before the pass. 4742 context->get_decoration_mgr(); 4743 4744 const auto status = pass->Run(context.get()); 4745 EXPECT_EQ(status, Pass::Status::SuccessWithChange); 4746} 4747 4748TEST_F(AggressiveDCETest, ParitallyDeadDecorationGroup) { 4749 const std::string text = R"( 4750; CHECK: OpDecorate [[grp:%\w+]] Restrict 4751; CHECK: [[grp]] = OpDecorationGroup 4752; CHECK: OpGroupDecorate [[grp]] [[output:%\w+]] 4753; CHECK: [[output]] = OpVariable {{%\w+}} Output 4754; CHECK-NOT: OpVariable {{%\w+}} Function 4755OpCapability Shader 4756OpMemoryModel Logical GLSL450 4757OpEntryPoint Fragment %main "main" %output 4758OpExecutionMode %main OriginUpperLeft 4759OpDecorate %1 Restrict 4760%1 = OpDecorationGroup 4761OpGroupDecorate %1 %var %output 4762%void = OpTypeVoid 4763%func = OpTypeFunction %void 4764%uint = OpTypeInt 32 0 4765%uint_ptr_Function = OpTypePointer Function %uint 4766%uint_ptr_Output = OpTypePointer Output %uint 4767%uint_0 = OpConstant %uint 0 4768%output = OpVariable %uint_ptr_Output Output 4769%main = OpFunction %void None %func 4770%2 = OpLabel 4771%var = OpVariable %uint_ptr_Function Function 4772OpStore %output %uint_0 4773OpReturn 4774OpFunctionEnd 4775 )"; 4776 4777 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 4778} 4779 4780TEST_F(AggressiveDCETest, ParitallyDeadDecorationGroupDifferentGroupDecorate) { 4781 const std::string text = R"( 4782; CHECK: OpDecorate [[grp:%\w+]] Restrict 4783; CHECK: [[grp]] = OpDecorationGroup 4784; CHECK: OpGroupDecorate [[grp]] [[output:%\w+]] 4785; CHECK-NOT: OpGroupDecorate 4786; CHECK: [[output]] = OpVariable {{%\w+}} Output 4787; CHECK-NOT: OpVariable {{%\w+}} Function 4788OpCapability Shader 4789OpMemoryModel Logical GLSL450 4790OpEntryPoint Fragment %main "main" %output 4791OpExecutionMode %main OriginUpperLeft 4792OpDecorate %1 Restrict 4793%1 = OpDecorationGroup 4794OpGroupDecorate %1 %output 4795OpGroupDecorate %1 %var 4796%void = OpTypeVoid 4797%func = OpTypeFunction %void 4798%uint = OpTypeInt 32 0 4799%uint_ptr_Function = OpTypePointer Function %uint 4800%uint_ptr_Output = OpTypePointer Output %uint 4801%uint_0 = OpConstant %uint 0 4802%output = OpVariable %uint_ptr_Output Output 4803%main = OpFunction %void None %func 4804%2 = OpLabel 4805%var = OpVariable %uint_ptr_Function Function 4806OpStore %output %uint_0 4807OpReturn 4808OpFunctionEnd 4809 )"; 4810 4811 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 4812} 4813 4814TEST_F(AggressiveDCETest, DeadGroupMemberDecorate) { 4815 const std::string text = R"( 4816; CHECK-NOT: OpDec 4817; CHECK-NOT: OpGroup 4818OpCapability Shader 4819OpMemoryModel Logical GLSL450 4820OpEntryPoint Fragment %main "main" 4821OpExecutionMode %main OriginUpperLeft 4822OpDecorate %1 Offset 0 4823OpDecorate %1 Uniform 4824%1 = OpDecorationGroup 4825OpGroupMemberDecorate %1 %var 0 4826%void = OpTypeVoid 4827%func = OpTypeFunction %void 4828%uint = OpTypeInt 32 0 4829%struct = OpTypeStruct %uint %uint 4830%struct_ptr = OpTypePointer Function %struct 4831%main = OpFunction %void None %func 4832%2 = OpLabel 4833%var = OpVariable %struct_ptr Function 4834OpReturn 4835OpFunctionEnd 4836 )"; 4837 4838 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 4839} 4840 4841TEST_F(AggressiveDCETest, PartiallyDeadGroupMemberDecorate) { 4842 const std::string text = R"( 4843; CHECK: OpDecorate [[grp:%\w+]] Offset 0 4844; CHECK: OpDecorate [[grp]] RelaxedPrecision 4845; CHECK: [[grp]] = OpDecorationGroup 4846; CHECK: OpGroupMemberDecorate [[grp]] [[output:%\w+]] 1 4847; CHECK: [[output]] = OpTypeStruct 4848; CHECK-NOT: OpTypeStruct 4849OpCapability Shader 4850OpMemoryModel Logical GLSL450 4851OpEntryPoint Fragment %main "main" %output 4852OpExecutionMode %main OriginUpperLeft 4853OpDecorate %1 Offset 0 4854OpDecorate %1 RelaxedPrecision 4855%1 = OpDecorationGroup 4856OpGroupMemberDecorate %1 %var_struct 0 %output_struct 1 4857%void = OpTypeVoid 4858%func = OpTypeFunction %void 4859%uint = OpTypeInt 32 0 4860%var_struct = OpTypeStruct %uint %uint 4861%output_struct = OpTypeStruct %uint %uint 4862%struct_ptr_Function = OpTypePointer Function %var_struct 4863%struct_ptr_Output = OpTypePointer Output %output_struct 4864%uint_ptr_Output = OpTypePointer Output %uint 4865%output = OpVariable %struct_ptr_Output Output 4866%uint_0 = OpConstant %uint 0 4867%main = OpFunction %void None %func 4868%2 = OpLabel 4869%var = OpVariable %struct_ptr_Function Function 4870%3 = OpAccessChain %uint_ptr_Output %output %uint_0 4871OpStore %3 %uint_0 4872OpReturn 4873OpFunctionEnd 4874 )"; 4875 4876 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 4877} 4878 4879TEST_F(AggressiveDCETest, 4880 PartiallyDeadGroupMemberDecorateDifferentGroupDecorate) { 4881 const std::string text = R"( 4882; CHECK: OpDecorate [[grp:%\w+]] Offset 0 4883; CHECK: OpDecorate [[grp]] RelaxedPrecision 4884; CHECK: [[grp]] = OpDecorationGroup 4885; CHECK: OpGroupMemberDecorate [[grp]] [[output:%\w+]] 1 4886; CHECK-NOT: OpGroupMemberDecorate 4887; CHECK: [[output]] = OpTypeStruct 4888; CHECK-NOT: OpTypeStruct 4889OpCapability Shader 4890OpMemoryModel Logical GLSL450 4891OpEntryPoint Fragment %main "main" %output 4892OpExecutionMode %main OriginUpperLeft 4893OpDecorate %1 Offset 0 4894OpDecorate %1 RelaxedPrecision 4895%1 = OpDecorationGroup 4896OpGroupMemberDecorate %1 %var_struct 0 4897OpGroupMemberDecorate %1 %output_struct 1 4898%void = OpTypeVoid 4899%func = OpTypeFunction %void 4900%uint = OpTypeInt 32 0 4901%var_struct = OpTypeStruct %uint %uint 4902%output_struct = OpTypeStruct %uint %uint 4903%struct_ptr_Function = OpTypePointer Function %var_struct 4904%struct_ptr_Output = OpTypePointer Output %output_struct 4905%uint_ptr_Output = OpTypePointer Output %uint 4906%output = OpVariable %struct_ptr_Output Output 4907%uint_0 = OpConstant %uint 0 4908%main = OpFunction %void None %func 4909%2 = OpLabel 4910%var = OpVariable %struct_ptr_Function Function 4911%3 = OpAccessChain %uint_ptr_Output %output %uint_0 4912OpStore %3 %uint_0 4913OpReturn 4914OpFunctionEnd 4915 )"; 4916 4917 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 4918} 4919 4920// Test for #1404 4921TEST_F(AggressiveDCETest, DontRemoveWorkgroupSize) { 4922 const std::string text = R"( 4923; CHECK: OpDecorate [[wgs:%\w+]] BuiltIn WorkgroupSize 4924; CHECK: [[wgs]] = OpSpecConstantComposite 4925OpCapability Shader 4926OpMemoryModel Logical GLSL450 4927OpEntryPoint GLCompute %func "func" 4928OpExecutionMode %func LocalSize 1 1 1 4929OpDecorate %1 BuiltIn WorkgroupSize 4930%void = OpTypeVoid 4931%int = OpTypeInt 32 0 4932%functy = OpTypeFunction %void 4933%v3int = OpTypeVector %int 3 4934%2 = OpSpecConstant %int 1 4935%1 = OpSpecConstantComposite %v3int %2 %2 %2 4936%func = OpFunction %void None %functy 4937%3 = OpLabel 4938OpReturn 4939OpFunctionEnd 4940)"; 4941 4942 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 4943} 4944 4945// Test for #1214 4946TEST_F(AggressiveDCETest, LoopHeaderIsAlsoAnotherLoopMerge) { 4947 const std::string text = R"(OpCapability Shader 4948OpMemoryModel Logical GLSL450 4949OpEntryPoint Fragment %1 "func" %2 4950OpExecutionMode %1 OriginUpperLeft 4951%void = OpTypeVoid 4952%bool = OpTypeBool 4953%true = OpConstantTrue %bool 4954%uint = OpTypeInt 32 0 4955%_ptr_Output_uint = OpTypePointer Output %uint 4956%2 = OpVariable %_ptr_Output_uint Output 4957%uint_0 = OpConstant %uint 0 4958%9 = OpTypeFunction %void 4959%1 = OpFunction %void None %9 4960%10 = OpLabel 4961OpBranch %11 4962%11 = OpLabel 4963OpLoopMerge %12 %13 None 4964OpBranchConditional %true %14 %13 4965%14 = OpLabel 4966OpStore %2 %uint_0 4967OpLoopMerge %15 %16 None 4968OpBranchConditional %true %15 %16 4969%16 = OpLabel 4970OpBranch %14 4971%15 = OpLabel 4972OpBranchConditional %true %12 %13 4973%13 = OpLabel 4974OpBranch %11 4975%12 = OpLabel 4976%17 = OpPhi %uint %uint_0 %15 %uint_0 %18 4977OpStore %2 %17 4978OpLoopMerge %19 %18 None 4979OpBranchConditional %true %19 %18 4980%18 = OpLabel 4981OpBranch %12 4982%19 = OpLabel 4983OpReturn 4984OpFunctionEnd 4985)"; 4986 4987 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true); 4988} 4989 4990TEST_F(AggressiveDCETest, BreaksDontVisitPhis) { 4991 const std::string text = R"( 4992OpCapability Shader 4993OpMemoryModel Logical GLSL450 4994OpEntryPoint Fragment %func "func" %var 4995OpExecutionMode %func OriginUpperLeft 4996%void = OpTypeVoid 4997%bool = OpTypeBool 4998%true = OpConstantTrue %bool 4999%int = OpTypeInt 32 0 5000%int_ptr_Output = OpTypePointer Output %int 5001%var = OpVariable %int_ptr_Output Output 5002%int0 = OpConstant %int 0 5003%functy = OpTypeFunction %void 5004%func = OpFunction %void None %functy 5005%entry = OpLabel 5006OpBranch %outer_header 5007%outer_header = OpLabel 5008OpLoopMerge %outer_merge %outer_continue None 5009OpBranchConditional %true %inner_header %outer_continue 5010%inner_header = OpLabel 5011%phi = OpPhi %int %int0 %outer_header %int0 %inner_continue 5012OpStore %var %phi 5013OpLoopMerge %inner_merge %inner_continue None 5014OpBranchConditional %true %inner_merge %inner_continue 5015%inner_continue = OpLabel 5016OpBranch %inner_header 5017%inner_merge = OpLabel 5018OpBranch %outer_continue 5019%outer_continue = OpLabel 5020%p = OpPhi %int %int0 %outer_header %int0 %inner_merge 5021OpStore %var %p 5022OpBranch %outer_header 5023%outer_merge = OpLabel 5024OpReturn 5025OpFunctionEnd 5026)"; 5027 5028 EXPECT_EQ(Pass::Status::SuccessWithoutChange, 5029 std::get<1>(SinglePassRunAndDisassemble<AggressiveDCEPass>( 5030 text, false, true))); 5031} 5032 5033// Test for #1212 5034TEST_F(AggressiveDCETest, ConstStoreInnerLoop) { 5035 const std::string text = R"(OpCapability Shader 5036OpMemoryModel Logical GLSL450 5037OpEntryPoint Vertex %1 "main" %2 5038%void = OpTypeVoid 5039%4 = OpTypeFunction %void 5040%float = OpTypeFloat 32 5041%bool = OpTypeBool 5042%true = OpConstantTrue %bool 5043%_ptr_Output_float = OpTypePointer Output %float 5044%2 = OpVariable %_ptr_Output_float Output 5045%float_3 = OpConstant %float 3 5046%1 = OpFunction %void None %4 5047%13 = OpLabel 5048OpBranch %14 5049%14 = OpLabel 5050OpLoopMerge %15 %16 None 5051OpBranchConditional %true %17 %15 5052%17 = OpLabel 5053OpStore %2 %float_3 5054OpLoopMerge %18 %17 None 5055OpBranchConditional %true %18 %17 5056%18 = OpLabel 5057OpBranch %15 5058%16 = OpLabel 5059OpBranch %14 5060%15 = OpLabel 5061OpBranch %20 5062%20 = OpLabel 5063OpReturn 5064OpFunctionEnd 5065)"; 5066 5067 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5068 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true); 5069} 5070 5071// Test for #1212 5072TEST_F(AggressiveDCETest, InnerLoopCopy) { 5073 const std::string text = R"(OpCapability Shader 5074OpMemoryModel Logical GLSL450 5075OpEntryPoint Vertex %1 "main" %2 %3 5076%void = OpTypeVoid 5077%5 = OpTypeFunction %void 5078%float = OpTypeFloat 32 5079%bool = OpTypeBool 5080%true = OpConstantTrue %bool 5081%_ptr_Output_float = OpTypePointer Output %float 5082%_ptr_Input_float = OpTypePointer Input %float 5083%2 = OpVariable %_ptr_Output_float Output 5084%3 = OpVariable %_ptr_Input_float Input 5085%1 = OpFunction %void None %5 5086%14 = OpLabel 5087OpBranch %15 5088%15 = OpLabel 5089OpLoopMerge %16 %17 None 5090OpBranchConditional %true %18 %16 5091%18 = OpLabel 5092%19 = OpLoad %float %3 5093OpStore %2 %19 5094OpLoopMerge %20 %18 None 5095OpBranchConditional %true %20 %18 5096%20 = OpLabel 5097OpBranch %16 5098%17 = OpLabel 5099OpBranch %15 5100%16 = OpLabel 5101OpBranch %22 5102%22 = OpLabel 5103OpReturn 5104OpFunctionEnd 5105)"; 5106 5107 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5108 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true); 5109} 5110 5111TEST_F(AggressiveDCETest, AtomicAdd) { 5112 const std::string text = R"(OpCapability SampledBuffer 5113OpCapability StorageImageExtendedFormats 5114OpCapability ImageBuffer 5115OpCapability Shader 5116%1 = OpExtInstImport "GLSL.std.450" 5117OpMemoryModel Logical GLSL450 5118OpEntryPoint GLCompute %2 "min" 5119OpExecutionMode %2 LocalSize 64 1 1 5120OpSource HLSL 600 5121OpDecorate %4 DescriptorSet 4 5122OpDecorate %4 Binding 70 5123%uint = OpTypeInt 32 0 5124%6 = OpTypeImage %uint Buffer 0 0 0 2 R32ui 5125%_ptr_UniformConstant_6 = OpTypePointer UniformConstant %6 5126%_ptr_Private_6 = OpTypePointer Private %6 5127%void = OpTypeVoid 5128%10 = OpTypeFunction %void 5129%uint_0 = OpConstant %uint 0 5130%uint_1 = OpConstant %uint 1 5131%_ptr_Image_uint = OpTypePointer Image %uint 5132%4 = OpVariable %_ptr_UniformConstant_6 UniformConstant 5133%16 = OpVariable %_ptr_Private_6 Private 5134%2 = OpFunction %void None %10 5135%17 = OpLabel 5136%18 = OpLoad %6 %4 5137OpStore %16 %18 5138%19 = OpImageTexelPointer %_ptr_Image_uint %16 %uint_0 %uint_0 5139%20 = OpAtomicIAdd %uint %19 %uint_1 %uint_0 %uint_1 5140OpReturn 5141OpFunctionEnd 5142)"; 5143 5144 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5145 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, true, true); 5146} 5147 5148TEST_F(AggressiveDCETest, SafelyRemoveDecorateString) { 5149 const std::string preamble = R"(OpCapability Shader 5150OpExtension "SPV_GOOGLE_hlsl_functionality1" 5151OpMemoryModel Logical GLSL450 5152OpEntryPoint Fragment %1 "main" 5153OpExecutionMode %1 OriginUpperLeft 5154)"; 5155 5156 const std::string body_before = 5157 R"(OpDecorateStringGOOGLE %2 HlslSemanticGOOGLE "FOOBAR" 5158%void = OpTypeVoid 5159%4 = OpTypeFunction %void 5160%uint = OpTypeInt 32 0 5161%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint 5162%2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer 5163%1 = OpFunction %void None %4 5164%7 = OpLabel 5165OpReturn 5166OpFunctionEnd 5167)"; 5168 5169 const std::string body_after = R"(%void = OpTypeVoid 5170%4 = OpTypeFunction %void 5171%1 = OpFunction %void None %4 5172%7 = OpLabel 5173OpReturn 5174OpFunctionEnd 5175)"; 5176 5177 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5178 SinglePassRunAndCheck<AggressiveDCEPass>(preamble + body_before, 5179 preamble + body_after, true, true); 5180} 5181 5182TEST_F(AggressiveDCETest, CopyMemoryToGlobal) { 5183 // |local| is loaded in an OpCopyMemory instruction. So the store must be 5184 // kept alive. 5185 const std::string test = 5186 R"(OpCapability Geometry 5187%1 = OpExtInstImport "GLSL.std.450" 5188OpMemoryModel Logical GLSL450 5189OpEntryPoint Geometry %main "main" %global 5190OpExecutionMode %main Triangles 5191OpExecutionMode %main Invocations 1 5192OpExecutionMode %main OutputTriangleStrip 5193OpExecutionMode %main OutputVertices 5 5194OpSource GLSL 440 5195OpName %main "main" 5196OpName %local "local" 5197OpName %global "global" 5198%void = OpTypeVoid 5199%7 = OpTypeFunction %void 5200%float = OpTypeFloat 32 5201%v4float = OpTypeVector %float 4 5202%12 = OpConstantNull %v4float 5203%_ptr_Function_v4float = OpTypePointer Function %v4float 5204%_ptr_Output_v4float = OpTypePointer Output %v4float 5205%global = OpVariable %_ptr_Output_v4float Output 5206%main = OpFunction %void None %7 5207%19 = OpLabel 5208%local = OpVariable %_ptr_Function_v4float Function 5209OpStore %local %12 5210OpCopyMemory %global %local 5211OpEndPrimitive 5212OpReturn 5213OpFunctionEnd 5214)"; 5215 5216 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5217 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true); 5218} 5219 5220TEST_F(AggressiveDCETest, CopyMemoryToLocal) { 5221 // Make sure the store to |local2| using OpCopyMemory is kept and keeps 5222 // |local1| alive. 5223 const std::string test = 5224 R"(OpCapability Geometry 5225%1 = OpExtInstImport "GLSL.std.450" 5226OpMemoryModel Logical GLSL450 5227OpEntryPoint Geometry %main "main" %global 5228OpExecutionMode %main Triangles 5229OpExecutionMode %main Invocations 1 5230OpExecutionMode %main OutputTriangleStrip 5231OpExecutionMode %main OutputVertices 5 5232OpSource GLSL 440 5233OpName %main "main" 5234OpName %local1 "local1" 5235OpName %local2 "local2" 5236OpName %global "global" 5237%void = OpTypeVoid 5238%7 = OpTypeFunction %void 5239%float = OpTypeFloat 32 5240%v4float = OpTypeVector %float 4 5241%12 = OpConstantNull %v4float 5242%_ptr_Function_v4float = OpTypePointer Function %v4float 5243%_ptr_Output_v4float = OpTypePointer Output %v4float 5244%global = OpVariable %_ptr_Output_v4float Output 5245%main = OpFunction %void None %7 5246%19 = OpLabel 5247%local1 = OpVariable %_ptr_Function_v4float Function 5248%local2 = OpVariable %_ptr_Function_v4float Function 5249OpStore %local1 %12 5250OpCopyMemory %local2 %local1 5251OpCopyMemory %global %local2 5252OpEndPrimitive 5253OpReturn 5254OpFunctionEnd 5255)"; 5256 5257 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5258 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true); 5259} 5260 5261TEST_F(AggressiveDCETest, RemoveCopyMemoryToLocal) { 5262 // Test that we remove function scope variables that are stored to using 5263 // OpCopyMemory, but are never loaded. We can remove both |local1| and 5264 // |local2|. 5265 const std::string test = 5266 R"(OpCapability Geometry 5267%1 = OpExtInstImport "GLSL.std.450" 5268OpMemoryModel Logical GLSL450 5269OpEntryPoint Geometry %main "main" %global 5270OpExecutionMode %main Triangles 5271OpExecutionMode %main Invocations 1 5272OpExecutionMode %main OutputTriangleStrip 5273OpExecutionMode %main OutputVertices 5 5274OpSource GLSL 440 5275OpName %main "main" 5276OpName %local1 "local1" 5277OpName %local2 "local2" 5278OpName %global "global" 5279%void = OpTypeVoid 5280%7 = OpTypeFunction %void 5281%float = OpTypeFloat 32 5282%v4float = OpTypeVector %float 4 5283%12 = OpConstantNull %v4float 5284%_ptr_Function_v4float = OpTypePointer Function %v4float 5285%_ptr_Output_v4float = OpTypePointer Output %v4float 5286%global = OpVariable %_ptr_Output_v4float Output 5287%main = OpFunction %void None %7 5288%19 = OpLabel 5289%local1 = OpVariable %_ptr_Function_v4float Function 5290%local2 = OpVariable %_ptr_Function_v4float Function 5291OpStore %local1 %12 5292OpCopyMemory %local2 %local1 5293OpEndPrimitive 5294OpReturn 5295OpFunctionEnd 5296)"; 5297 5298 const std::string result = 5299 R"(OpCapability Geometry 5300%1 = OpExtInstImport "GLSL.std.450" 5301OpMemoryModel Logical GLSL450 5302OpEntryPoint Geometry %main "main" %global 5303OpExecutionMode %main Triangles 5304OpExecutionMode %main Invocations 1 5305OpExecutionMode %main OutputTriangleStrip 5306OpExecutionMode %main OutputVertices 5 5307OpSource GLSL 440 5308OpName %main "main" 5309OpName %global "global" 5310%void = OpTypeVoid 5311%7 = OpTypeFunction %void 5312%float = OpTypeFloat 32 5313%v4float = OpTypeVector %float 4 5314%_ptr_Output_v4float = OpTypePointer Output %v4float 5315%global = OpVariable %_ptr_Output_v4float Output 5316%main = OpFunction %void None %7 5317%19 = OpLabel 5318OpEndPrimitive 5319OpReturn 5320OpFunctionEnd 5321)"; 5322 5323 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5324 SinglePassRunAndCheck<AggressiveDCEPass>(test, result, true, true); 5325} 5326 5327TEST_F(AggressiveDCETest, RemoveCopyMemoryToLocal2) { 5328 // We are able to remove "local2" because it is not loaded, but have to keep 5329 // the stores to "local1". 5330 const std::string test = 5331 R"(OpCapability Geometry 5332%1 = OpExtInstImport "GLSL.std.450" 5333OpMemoryModel Logical GLSL450 5334OpEntryPoint Geometry %main "main" %global 5335OpExecutionMode %main Triangles 5336OpExecutionMode %main Invocations 1 5337OpExecutionMode %main OutputTriangleStrip 5338OpExecutionMode %main OutputVertices 5 5339OpSource GLSL 440 5340OpName %main "main" 5341OpName %local1 "local1" 5342OpName %local2 "local2" 5343OpName %global "global" 5344%void = OpTypeVoid 5345%7 = OpTypeFunction %void 5346%float = OpTypeFloat 32 5347%v4float = OpTypeVector %float 4 5348%12 = OpConstantNull %v4float 5349%_ptr_Function_v4float = OpTypePointer Function %v4float 5350%_ptr_Output_v4float = OpTypePointer Output %v4float 5351%global = OpVariable %_ptr_Output_v4float Output 5352%main = OpFunction %void None %7 5353%19 = OpLabel 5354%local1 = OpVariable %_ptr_Function_v4float Function 5355%local2 = OpVariable %_ptr_Function_v4float Function 5356OpStore %local1 %12 5357OpCopyMemory %local2 %local1 5358OpCopyMemory %global %local1 5359OpEndPrimitive 5360OpReturn 5361OpFunctionEnd 5362)"; 5363 5364 const std::string result = 5365 R"(OpCapability Geometry 5366%1 = OpExtInstImport "GLSL.std.450" 5367OpMemoryModel Logical GLSL450 5368OpEntryPoint Geometry %main "main" %global 5369OpExecutionMode %main Triangles 5370OpExecutionMode %main Invocations 1 5371OpExecutionMode %main OutputTriangleStrip 5372OpExecutionMode %main OutputVertices 5 5373OpSource GLSL 440 5374OpName %main "main" 5375OpName %local1 "local1" 5376OpName %global "global" 5377%void = OpTypeVoid 5378%7 = OpTypeFunction %void 5379%float = OpTypeFloat 32 5380%v4float = OpTypeVector %float 4 5381%12 = OpConstantNull %v4float 5382%_ptr_Function_v4float = OpTypePointer Function %v4float 5383%_ptr_Output_v4float = OpTypePointer Output %v4float 5384%global = OpVariable %_ptr_Output_v4float Output 5385%main = OpFunction %void None %7 5386%19 = OpLabel 5387%local1 = OpVariable %_ptr_Function_v4float Function 5388OpStore %local1 %12 5389OpCopyMemory %global %local1 5390OpEndPrimitive 5391OpReturn 5392OpFunctionEnd 5393)"; 5394 5395 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5396 SinglePassRunAndCheck<AggressiveDCEPass>(test, result, true, true); 5397} 5398 5399TEST_F(AggressiveDCETest, StructuredIfWithConditionalExit) { 5400 // We are able to remove "local2" because it is not loaded, but have to keep 5401 // the stores to "local1". 5402 const std::string test = 5403 R"(OpCapability Shader 5404%1 = OpExtInstImport "GLSL.std.450" 5405OpMemoryModel Logical GLSL450 5406OpEntryPoint Fragment %main "main" 5407OpExecutionMode %main OriginUpperLeft 5408OpSource GLSL 140 5409OpSourceExtension "GL_GOOGLE_cpp_style_line_directive" 5410OpSourceExtension "GL_GOOGLE_include_directive" 5411OpName %main "main" 5412OpName %a "a" 5413%void = OpTypeVoid 5414%5 = OpTypeFunction %void 5415%int = OpTypeInt 32 1 5416%_ptr_Uniform_int = OpTypePointer Uniform %int 5417%int_0 = OpConstant %int 0 5418%bool = OpTypeBool 5419%int_100 = OpConstant %int 100 5420%int_1 = OpConstant %int 1 5421%a = OpVariable %_ptr_Uniform_int Uniform 5422%main = OpFunction %void None %5 5423%12 = OpLabel 5424%13 = OpLoad %int %a 5425%14 = OpSGreaterThan %bool %13 %int_0 5426OpSelectionMerge %15 None 5427OpBranchConditional %14 %16 %15 5428%16 = OpLabel 5429%17 = OpLoad %int %a 5430%18 = OpSLessThan %bool %17 %int_100 5431OpBranchConditional %18 %19 %15 5432%19 = OpLabel 5433OpStore %a %int_1 5434OpBranch %15 5435%15 = OpLabel 5436OpReturn 5437OpFunctionEnd 5438)"; 5439 5440 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5441 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true); 5442} 5443 5444TEST_F(AggressiveDCETest, CountingLoopNotEliminated) { 5445 // #version 310 es 5446 // 5447 // precision highp float; 5448 // precision highp int; 5449 // 5450 // layout(location = 0) out vec4 _GLF_color; 5451 // 5452 // void main() 5453 // { 5454 // float data[1]; 5455 // for (int c = 0; c < 1; c++) { 5456 // if (true) { 5457 // do { 5458 // for (int i = 0; i < 1; i++) { 5459 // data[i] = 1.0; 5460 // } 5461 // } while (false); 5462 // } 5463 // } 5464 // _GLF_color = vec4(data[0], 0.0, 0.0, 1.0); 5465 // } 5466 const std::string test = 5467 R"(OpCapability Shader 5468%1 = OpExtInstImport "GLSL.std.450" 5469OpMemoryModel Logical GLSL450 5470OpEntryPoint Fragment %main "main" %_GLF_color 5471OpExecutionMode %main OriginUpperLeft 5472OpSource ESSL 310 5473OpName %main "main" 5474OpName %c "c" 5475OpName %i "i" 5476OpName %data "data" 5477OpName %_GLF_color "_GLF_color" 5478OpDecorate %_GLF_color Location 0 5479%void = OpTypeVoid 5480%8 = OpTypeFunction %void 5481%int = OpTypeInt 32 1 5482%_ptr_Function_int = OpTypePointer Function %int 5483%int_0 = OpConstant %int 0 5484%int_1 = OpConstant %int 1 5485%bool = OpTypeBool 5486%float = OpTypeFloat 32 5487%uint = OpTypeInt 32 0 5488%uint_1 = OpConstant %uint 1 5489%_arr_float_uint_1 = OpTypeArray %float %uint_1 5490%_ptr_Function__arr_float_uint_1 = OpTypePointer Function %_arr_float_uint_1 5491%float_1 = OpConstant %float 1 5492%_ptr_Function_float = OpTypePointer Function %float 5493%false = OpConstantFalse %bool 5494%v4float = OpTypeVector %float 4 5495%_ptr_Output_v4float = OpTypePointer Output %v4float 5496%_GLF_color = OpVariable %_ptr_Output_v4float Output 5497%float_0 = OpConstant %float 0 5498%main = OpFunction %void None %8 5499%26 = OpLabel 5500%c = OpVariable %_ptr_Function_int Function 5501%i = OpVariable %_ptr_Function_int Function 5502%data = OpVariable %_ptr_Function__arr_float_uint_1 Function 5503OpStore %c %int_0 5504OpBranch %27 5505%27 = OpLabel 5506OpLoopMerge %28 %29 None 5507OpBranch %30 5508%30 = OpLabel 5509%31 = OpLoad %int %c 5510%32 = OpSLessThan %bool %31 %int_1 5511OpBranchConditional %32 %33 %28 5512%33 = OpLabel 5513OpBranch %34 5514%34 = OpLabel 5515OpBranch %35 5516%35 = OpLabel 5517OpLoopMerge %36 %37 None 5518OpBranch %38 5519%38 = OpLabel 5520OpStore %i %int_0 5521OpBranch %39 5522%39 = OpLabel 5523OpLoopMerge %40 %41 None 5524OpBranch %42 5525%42 = OpLabel 5526%43 = OpLoad %int %i 5527%44 = OpSLessThan %bool %43 %int_1 5528OpBranchConditional %44 %46 %40 5529%46 = OpLabel 5530%47 = OpLoad %int %i 5531%48 = OpAccessChain %_ptr_Function_float %data %47 5532OpStore %48 %float_1 5533OpBranch %41 5534%41 = OpLabel 5535%49 = OpLoad %int %i 5536%50 = OpIAdd %int %49 %int_1 5537OpStore %i %50 5538OpBranch %39 5539%40 = OpLabel 5540OpBranch %37 5541%37 = OpLabel 5542OpBranchConditional %false %35 %36 5543%36 = OpLabel 5544OpBranch %45 5545%45 = OpLabel 5546OpBranch %29 5547%29 = OpLabel 5548%51 = OpLoad %int %c 5549%52 = OpIAdd %int %51 %int_1 5550OpStore %c %52 5551OpBranch %27 5552%28 = OpLabel 5553%53 = OpAccessChain %_ptr_Function_float %data %int_0 5554%54 = OpLoad %float %53 5555%55 = OpCompositeConstruct %v4float %54 %float_0 %float_0 %float_1 5556OpStore %_GLF_color %55 5557OpReturn 5558OpFunctionEnd 5559)"; 5560 5561 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5562 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true); 5563} 5564 5565TEST_F(AggressiveDCETest, EliminateLoopWithUnreachable) { 5566 // #version 430 5567 // 5568 // layout(std430) buffer U_t 5569 // { 5570 // float g_F[10]; 5571 // float g_S; 5572 // }; 5573 // 5574 // layout(location = 0)out float o; 5575 // 5576 // void main(void) 5577 // { 5578 // // Useless loop 5579 // for (int i = 0; i<10; i++) { 5580 // if (g_F[i] == 0.0) 5581 // break; 5582 // else 5583 // break; 5584 // // Unreachable merge block created here. 5585 // // Need to edit SPIR-V to change to OpUnreachable 5586 // } 5587 // o = g_S; 5588 // } 5589 5590 const std::string before = 5591 R"(OpCapability Shader 5592%1 = OpExtInstImport "GLSL.std.450" 5593OpMemoryModel Logical GLSL450 5594OpEntryPoint Fragment %main "main" %o 5595OpExecutionMode %main OriginUpperLeft 5596OpSource GLSL 430 5597OpName %main "main" 5598OpName %i "i" 5599OpName %U_t "U_t" 5600OpMemberName %U_t 0 "g_F" 5601OpMemberName %U_t 1 "g_S" 5602OpName %_ "" 5603OpName %o "o" 5604OpDecorate %_arr_float_uint_10 ArrayStride 4 5605OpMemberDecorate %U_t 0 Offset 0 5606OpMemberDecorate %U_t 1 Offset 40 5607OpDecorate %U_t BufferBlock 5608OpDecorate %_ DescriptorSet 0 5609OpDecorate %o Location 0 5610%void = OpTypeVoid 5611%9 = OpTypeFunction %void 5612%int = OpTypeInt 32 1 5613%_ptr_Function_int = OpTypePointer Function %int 5614%int_0 = OpConstant %int 0 5615%int_10 = OpConstant %int 10 5616%bool = OpTypeBool 5617%float = OpTypeFloat 32 5618%uint = OpTypeInt 32 0 5619%uint_10 = OpConstant %uint 10 5620%_arr_float_uint_10 = OpTypeArray %float %uint_10 5621%U_t = OpTypeStruct %_arr_float_uint_10 %float 5622%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 5623%_ = OpVariable %_ptr_Uniform_U_t Uniform 5624%_ptr_Uniform_float = OpTypePointer Uniform %float 5625%float_0 = OpConstant %float 0 5626%int_1 = OpConstant %int 1 5627%_ptr_Output_float = OpTypePointer Output %float 5628%o = OpVariable %_ptr_Output_float Output 5629%main = OpFunction %void None %9 5630%23 = OpLabel 5631%i = OpVariable %_ptr_Function_int Function 5632OpStore %i %int_0 5633OpBranch %24 5634%24 = OpLabel 5635OpLoopMerge %25 %26 None 5636OpBranch %27 5637%27 = OpLabel 5638%28 = OpLoad %int %i 5639%29 = OpSLessThan %bool %28 %int_10 5640OpBranchConditional %29 %30 %25 5641%30 = OpLabel 5642%31 = OpLoad %int %i 5643%32 = OpAccessChain %_ptr_Uniform_float %_ %int_0 %31 5644%33 = OpLoad %float %32 5645%34 = OpFOrdEqual %bool %33 %float_0 5646OpSelectionMerge %35 None 5647OpBranchConditional %34 %36 %37 5648%36 = OpLabel 5649OpBranch %25 5650%37 = OpLabel 5651OpBranch %25 5652%35 = OpLabel 5653OpUnreachable 5654%26 = OpLabel 5655%38 = OpLoad %int %i 5656%39 = OpIAdd %int %38 %int_1 5657OpStore %i %39 5658OpBranch %24 5659%25 = OpLabel 5660%40 = OpAccessChain %_ptr_Uniform_float %_ %int_1 5661%41 = OpLoad %float %40 5662OpStore %o %41 5663OpReturn 5664OpFunctionEnd 5665)"; 5666 5667 const std::string after = 5668 R"(OpCapability Shader 5669%1 = OpExtInstImport "GLSL.std.450" 5670OpMemoryModel Logical GLSL450 5671OpEntryPoint Fragment %main "main" %o 5672OpExecutionMode %main OriginUpperLeft 5673OpSource GLSL 430 5674OpName %main "main" 5675OpName %U_t "U_t" 5676OpMemberName %U_t 0 "g_F" 5677OpMemberName %U_t 1 "g_S" 5678OpName %_ "" 5679OpName %o "o" 5680OpDecorate %_arr_float_uint_10 ArrayStride 4 5681OpMemberDecorate %U_t 0 Offset 0 5682OpMemberDecorate %U_t 1 Offset 40 5683OpDecorate %U_t BufferBlock 5684OpDecorate %_ DescriptorSet 0 5685OpDecorate %o Location 0 5686%void = OpTypeVoid 5687%9 = OpTypeFunction %void 5688%int = OpTypeInt 32 1 5689%float = OpTypeFloat 32 5690%uint = OpTypeInt 32 0 5691%uint_10 = OpConstant %uint 10 5692%_arr_float_uint_10 = OpTypeArray %float %uint_10 5693%U_t = OpTypeStruct %_arr_float_uint_10 %float 5694%_ptr_Uniform_U_t = OpTypePointer Uniform %U_t 5695%_ = OpVariable %_ptr_Uniform_U_t Uniform 5696%_ptr_Uniform_float = OpTypePointer Uniform %float 5697%int_1 = OpConstant %int 1 5698%_ptr_Output_float = OpTypePointer Output %float 5699%o = OpVariable %_ptr_Output_float Output 5700%main = OpFunction %void None %9 5701%23 = OpLabel 5702OpBranch %24 5703%24 = OpLabel 5704OpBranch %25 5705%25 = OpLabel 5706%40 = OpAccessChain %_ptr_Uniform_float %_ %int_1 5707%41 = OpLoad %float %40 5708OpStore %o %41 5709OpReturn 5710OpFunctionEnd 5711)"; 5712 5713 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5714 SinglePassRunAndCheck<AggressiveDCEPass>(before, after, true, true); 5715} 5716 5717TEST_F(AggressiveDCETest, DeadHlslCounterBufferGOOGLE) { 5718 // We are able to remove "local2" because it is not loaded, but have to keep 5719 // the stores to "local1". 5720 const std::string test = 5721 R"( 5722; CHECK-NOT: OpDecorateId 5723; CHECK: [[var:%\w+]] = OpVariable 5724; CHECK-NOT: OpVariable 5725; CHECK: [[ac:%\w+]] = OpAccessChain {{%\w+}} [[var]] 5726; CHECK: OpStore [[ac]] 5727 OpCapability Shader 5728 OpExtension "SPV_GOOGLE_hlsl_functionality1" 5729 OpMemoryModel Logical GLSL450 5730 OpEntryPoint GLCompute %1 "main" 5731 OpExecutionMode %1 LocalSize 32 1 1 5732 OpSource HLSL 600 5733 OpDecorate %_runtimearr_v2float ArrayStride 8 5734 OpMemberDecorate %_struct_3 0 Offset 0 5735 OpDecorate %_struct_3 BufferBlock 5736 OpMemberDecorate %_struct_4 0 Offset 0 5737 OpDecorate %_struct_4 BufferBlock 5738 OpDecorateId %5 HlslCounterBufferGOOGLE %6 5739 OpDecorate %5 DescriptorSet 0 5740 OpDecorate %5 Binding 0 5741 OpDecorate %6 DescriptorSet 0 5742 OpDecorate %6 Binding 1 5743 %float = OpTypeFloat 32 5744 %v2float = OpTypeVector %float 2 5745%_runtimearr_v2float = OpTypeRuntimeArray %v2float 5746 %_struct_3 = OpTypeStruct %_runtimearr_v2float 5747%_ptr_Uniform__struct_3 = OpTypePointer Uniform %_struct_3 5748 %int = OpTypeInt 32 1 5749 %_struct_4 = OpTypeStruct %int 5750%_ptr_Uniform__struct_4 = OpTypePointer Uniform %_struct_4 5751 %void = OpTypeVoid 5752 %13 = OpTypeFunction %void 5753 %19 = OpConstantNull %v2float 5754 %int_0 = OpConstant %int 0 5755%_ptr_Uniform_v2float = OpTypePointer Uniform %v2float 5756 %5 = OpVariable %_ptr_Uniform__struct_3 Uniform 5757 %6 = OpVariable %_ptr_Uniform__struct_4 Uniform 5758 %1 = OpFunction %void None %13 5759 %22 = OpLabel 5760 %23 = OpAccessChain %_ptr_Uniform_v2float %5 %int_0 %int_0 5761 OpStore %23 %19 5762 OpReturn 5763 OpFunctionEnd 5764)"; 5765 5766 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5767 SinglePassRunAndMatch<AggressiveDCEPass>(test, true); 5768} 5769 5770TEST_F(AggressiveDCETest, Dead) { 5771 // We are able to remove "local2" because it is not loaded, but have to keep 5772 // the stores to "local1". 5773 const std::string test = 5774 R"( 5775; CHECK: OpCapability 5776; CHECK-NOT: OpMemberDecorateStringGOOGLE 5777; CHECK: OpFunctionEnd 5778 OpCapability Shader 5779 OpExtension "SPV_GOOGLE_hlsl_functionality1" 5780 %1 = OpExtInstImport "GLSL.std.450" 5781 OpMemoryModel Logical GLSL450 5782 OpEntryPoint Vertex %VSMain "VSMain" 5783 OpSource HLSL 500 5784 OpName %VSMain "VSMain" 5785 OpName %PSInput "PSInput" 5786 OpMemberName %PSInput 0 "Pos" 5787 OpMemberName %PSInput 1 "uv" 5788 OpMemberDecorateStringGOOGLE %PSInput 0 HlslSemanticGOOGLE "SV_POSITION" 5789 OpMemberDecorateStringGOOGLE %PSInput 1 HlslSemanticGOOGLE "TEX_COORD" 5790 %void = OpTypeVoid 5791 %5 = OpTypeFunction %void 5792 %float = OpTypeFloat 32 5793%v2float = OpTypeVector %float 2 5794%v4float = OpTypeVector %float 4 5795%PSInput = OpTypeStruct %v4float %v2float 5796 %VSMain = OpFunction %void None %5 5797 %9 = OpLabel 5798 OpReturn 5799 OpFunctionEnd 5800)"; 5801 5802 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5803 SinglePassRunAndMatch<AggressiveDCEPass>(test, true); 5804} 5805 5806TEST_F(AggressiveDCETest, DeadInfiniteLoop) { 5807 const std::string test = R"( 5808; CHECK: OpSwitch {{%\w+}} {{%\w+}} {{\w+}} {{%\w+}} {{\w+}} [[block:%\w+]] 5809; CHECK: [[block]] = OpLabel 5810; CHECK-NEXT: OpBranch [[block:%\w+]] 5811; CHECK: [[block]] = OpLabel 5812; CHECK-NEXT: OpBranch [[block:%\w+]] 5813; CHECK: [[block]] = OpLabel 5814; CHECK-NEXT: OpReturn 5815 OpCapability Shader 5816 OpMemoryModel Logical GLSL450 5817 OpEntryPoint Fragment %2 "main" 5818 OpExecutionMode %2 OriginUpperLeft 5819 %6 = OpTypeVoid 5820 %7 = OpTypeFunction %6 5821 %8 = OpTypeFloat 32 5822 %9 = OpTypeVector %8 3 5823 %10 = OpTypeFunction %9 5824 %11 = OpConstant %8 1 5825 %12 = OpConstantComposite %9 %11 %11 %11 5826 %13 = OpTypeInt 32 1 5827 %32 = OpUndef %13 5828 %2 = OpFunction %6 None %7 5829 %33 = OpLabel 5830 OpBranch %34 5831 %34 = OpLabel 5832 OpLoopMerge %35 %36 None 5833 OpBranch %37 5834 %37 = OpLabel 5835 %38 = OpFunctionCall %9 %39 5836 OpSelectionMerge %40 None 5837 OpSwitch %32 %40 14 %41 58 %42 5838 %42 = OpLabel 5839 OpBranch %43 5840 %43 = OpLabel 5841 OpLoopMerge %44 %45 None 5842 OpBranch %45 5843 %45 = OpLabel 5844 OpBranch %43 5845 %44 = OpLabel 5846 OpUnreachable 5847 %41 = OpLabel 5848 OpBranch %36 5849 %40 = OpLabel 5850 OpBranch %36 5851 %36 = OpLabel 5852 OpBranch %34 5853 %35 = OpLabel 5854 OpReturn 5855 OpFunctionEnd 5856 %39 = OpFunction %9 None %10 5857 %46 = OpLabel 5858 OpReturnValue %12 5859 OpFunctionEnd 5860)"; 5861 5862 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5863 SinglePassRunAndMatch<AggressiveDCEPass>(test, true); 5864} 5865 5866TEST_F(AggressiveDCETest, DeadInfiniteLoopReturnValue) { 5867 const std::string test = R"( 5868; CHECK: [[vec3:%\w+]] = OpTypeVector 5869; CHECK: [[undef:%\w+]] = OpUndef [[vec3]] 5870; CHECK: OpSwitch {{%\w+}} {{%\w+}} {{\w+}} {{%\w+}} {{\w+}} [[block:%\w+]] 5871; CHECK: [[block]] = OpLabel 5872; CHECK-NEXT: OpBranch [[block:%\w+]] 5873; CHECK: [[block]] = OpLabel 5874; CHECK-NEXT: OpBranch [[block:%\w+]] 5875; CHECK: [[block]] = OpLabel 5876; CHECK-NEXT: OpReturnValue [[undef]] 5877 OpCapability Shader 5878 OpMemoryModel Logical GLSL450 5879 OpEntryPoint Fragment %2 "main" 5880 OpExecutionMode %2 OriginUpperLeft 5881 %6 = OpTypeVoid 5882 %7 = OpTypeFunction %6 5883 %8 = OpTypeFloat 32 5884 %9 = OpTypeVector %8 3 5885 %10 = OpTypeFunction %9 5886 %11 = OpConstant %8 1 5887 %12 = OpConstantComposite %9 %11 %11 %11 5888 %13 = OpTypeInt 32 1 5889 %32 = OpUndef %13 5890 %2 = OpFunction %6 None %7 5891 %entry = OpLabel 5892 %call = OpFunctionCall %9 %func 5893 OpReturn 5894 OpFunctionEnd 5895 %func = OpFunction %9 None %10 5896 %33 = OpLabel 5897 OpBranch %34 5898 %34 = OpLabel 5899 OpLoopMerge %35 %36 None 5900 OpBranch %37 5901 %37 = OpLabel 5902 %38 = OpFunctionCall %9 %39 5903 OpSelectionMerge %40 None 5904 OpSwitch %32 %40 14 %41 58 %42 5905 %42 = OpLabel 5906 OpBranch %43 5907 %43 = OpLabel 5908 OpLoopMerge %44 %45 None 5909 OpBranch %45 5910 %45 = OpLabel 5911 OpBranch %43 5912 %44 = OpLabel 5913 OpUnreachable 5914 %41 = OpLabel 5915 OpBranch %36 5916 %40 = OpLabel 5917 OpBranch %36 5918 %36 = OpLabel 5919 OpBranch %34 5920 %35 = OpLabel 5921 OpReturnValue %12 5922 OpFunctionEnd 5923 %39 = OpFunction %9 None %10 5924 %46 = OpLabel 5925 OpReturnValue %12 5926 OpFunctionEnd 5927)"; 5928 5929 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5930 SinglePassRunAndMatch<AggressiveDCEPass>(test, true); 5931} 5932 5933TEST_F(AggressiveDCETest, TestVariablePointer) { 5934 const std::string before = 5935 R"(OpCapability Shader 5936OpCapability VariablePointers 5937%1 = OpExtInstImport "GLSL.std.450" 5938OpMemoryModel Logical GLSL450 5939OpEntryPoint GLCompute %2 "main" 5940OpExecutionMode %2 LocalSize 1 1 1 5941OpSource GLSL 450 5942OpMemberDecorate %_struct_3 0 Offset 0 5943OpDecorate %_struct_3 Block 5944OpDecorate %4 DescriptorSet 0 5945OpDecorate %4 Binding 0 5946OpDecorate %_ptr_StorageBuffer_int ArrayStride 4 5947OpDecorate %_arr_int_int_128 ArrayStride 4 5948%void = OpTypeVoid 5949%8 = OpTypeFunction %void 5950%int = OpTypeInt 32 1 5951%int_128 = OpConstant %int 128 5952%_arr_int_int_128 = OpTypeArray %int %int_128 5953%_struct_3 = OpTypeStruct %_arr_int_int_128 5954%_ptr_StorageBuffer__struct_3 = OpTypePointer StorageBuffer %_struct_3 5955%4 = OpVariable %_ptr_StorageBuffer__struct_3 StorageBuffer 5956%bool = OpTypeBool 5957%true = OpConstantTrue %bool 5958%int_0 = OpConstant %int 0 5959%int_1 = OpConstant %int 1 5960%_ptr_StorageBuffer_int = OpTypePointer StorageBuffer %int 5961%2 = OpFunction %void None %8 5962%16 = OpLabel 5963%17 = OpAccessChain %_ptr_StorageBuffer_int %4 %int_0 %int_0 5964OpBranch %18 5965%18 = OpLabel 5966%19 = OpPhi %_ptr_StorageBuffer_int %17 %16 %20 %21 5967OpLoopMerge %22 %21 None 5968OpBranchConditional %true %23 %22 5969%23 = OpLabel 5970OpStore %19 %int_0 5971OpBranch %21 5972%21 = OpLabel 5973%20 = OpPtrAccessChain %_ptr_StorageBuffer_int %19 %int_1 5974OpBranch %18 5975%22 = OpLabel 5976OpReturn 5977OpFunctionEnd 5978)"; 5979 5980 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 5981 SinglePassRunAndCheck<AggressiveDCEPass>(before, before, true, true); 5982} 5983 5984TEST_F(AggressiveDCETest, DeadInputInterfaceV13) { 5985 const std::string spirv = R"( 5986; CHECK: OpEntryPoint GLCompute %main "main" 5987; CHECK-NOT: OpVariable 5988OpCapability Shader 5989OpMemoryModel Logical GLSL450 5990OpEntryPoint GLCompute %main "main" %dead 5991OpExecutionMode %main LocalSize 1 1 1 5992OpName %main "main" 5993%void = OpTypeVoid 5994%int = OpTypeInt 32 0 5995%ptr_input_int = OpTypePointer Input %int 5996%dead = OpVariable %ptr_input_int Input 5997%void_fn = OpTypeFunction %void 5998%main = OpFunction %void None %void_fn 5999%entry = OpLabel 6000OpReturn 6001OpFunctionEnd 6002)"; 6003 6004 SetTargetEnv(SPV_ENV_UNIVERSAL_1_3); 6005 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 6006} 6007 6008TEST_F(AggressiveDCETest, DeadInputInterfaceV14) { 6009 const std::string spirv = R"( 6010; CHECK: OpEntryPoint GLCompute %main "main" 6011; CHECK-NOT: OpVariable 6012OpCapability Shader 6013OpMemoryModel Logical GLSL450 6014OpEntryPoint GLCompute %main "main" %dead 6015OpExecutionMode %main LocalSize 1 1 1 6016OpName %main "main" 6017%void = OpTypeVoid 6018%int = OpTypeInt 32 0 6019%ptr_input_int = OpTypePointer Input %int 6020%dead = OpVariable %ptr_input_int Input 6021%void_fn = OpTypeFunction %void 6022%main = OpFunction %void None %void_fn 6023%entry = OpLabel 6024OpReturn 6025OpFunctionEnd 6026)"; 6027 6028 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 6029 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 6030} 6031 6032TEST_F(AggressiveDCETest, DeadInterfaceV14) { 6033 const std::string spirv = R"( 6034; CHECK-NOT: OpEntryPoint GLCompute %main "main" % 6035; CHECK: OpEntryPoint GLCompute %main "main" 6036; CHECK-NOT: OpVariable 6037OpCapability Shader 6038OpMemoryModel Logical GLSL450 6039OpEntryPoint GLCompute %main "main" %dead 6040OpExecutionMode %main LocalSize 1 1 1 6041OpName %main "main" 6042%void = OpTypeVoid 6043%int = OpTypeInt 32 0 6044%ptr_private_int = OpTypePointer Private %int 6045%dead = OpVariable %ptr_private_int Private 6046%void_fn = OpTypeFunction %void 6047%main = OpFunction %void None %void_fn 6048%entry = OpLabel 6049OpReturn 6050OpFunctionEnd 6051)"; 6052 6053 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 6054 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 6055} 6056 6057TEST_F(AggressiveDCETest, DeadInterfacesV14) { 6058 const std::string spirv = R"( 6059; CHECK: OpEntryPoint GLCompute %main "main" %live1 %live2 6060; CHECK-NOT: %dead 6061OpCapability Shader 6062OpMemoryModel Logical GLSL450 6063OpEntryPoint GLCompute %main "main" %live1 %dead1 %dead2 %live2 6064OpExecutionMode %main LocalSize 1 1 1 6065OpName %main "main" 6066OpName %live1 "live1" 6067OpName %live2 "live2" 6068OpName %dead1 "dead1" 6069OpName %dead2 "dead2" 6070%void = OpTypeVoid 6071%int = OpTypeInt 32 0 6072%int0 = OpConstant %int 0 6073%ptr_ssbo_int = OpTypePointer StorageBuffer %int 6074%live1 = OpVariable %ptr_ssbo_int StorageBuffer 6075%live2 = OpVariable %ptr_ssbo_int StorageBuffer 6076%dead1 = OpVariable %ptr_ssbo_int StorageBuffer 6077%dead2 = OpVariable %ptr_ssbo_int StorageBuffer 6078%void_fn = OpTypeFunction %void 6079%main = OpFunction %void None %void_fn 6080%entry = OpLabel 6081OpStore %live1 %int0 6082OpStore %live2 %int0 6083OpReturn 6084OpFunctionEnd 6085)"; 6086 6087 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 6088 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 6089} 6090 6091TEST_F(AggressiveDCETest, PreserveBindings) { 6092 const std::string spirv = R"( 6093; CHECK: OpDecorate %unusedSampler DescriptorSet 0 6094; CHECK: OpDecorate %unusedSampler Binding 0 6095OpCapability Shader 6096%1 = OpExtInstImport "GLSL.std.450" 6097OpMemoryModel Logical GLSL450 6098OpEntryPoint Fragment %main "main" 6099OpExecutionMode %main OriginUpperLeft 6100OpSource GLSL 430 6101OpName %main "main" 6102OpName %unusedSampler "unusedSampler" 6103OpDecorate %unusedSampler DescriptorSet 0 6104OpDecorate %unusedSampler Binding 0 6105%void = OpTypeVoid 6106%5 = OpTypeFunction %void 6107%float = OpTypeFloat 32 6108%7 = OpTypeImage %float 2D 0 0 0 1 Unknown 6109%8 = OpTypeSampledImage %7 6110%_ptr_UniformConstant_8 = OpTypePointer UniformConstant %8 6111%unusedSampler = OpVariable %_ptr_UniformConstant_8 UniformConstant 6112%main = OpFunction %void None %5 6113%10 = OpLabel 6114OpReturn 6115OpFunctionEnd 6116)"; 6117 6118 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 6119 6120 OptimizerOptions()->preserve_bindings_ = true; 6121 6122 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 6123} 6124 6125TEST_F(AggressiveDCETest, PreserveSpecConstants) { 6126 const std::string spirv = R"( 6127; CHECK: OpName %specConstant "specConstant" 6128; CHECK: %specConstant = OpSpecConstant %int 0 6129OpCapability Shader 6130%1 = OpExtInstImport "GLSL.std.450" 6131OpMemoryModel Logical GLSL450 6132OpEntryPoint Fragment %main "main" 6133OpExecutionMode %main OriginUpperLeft 6134OpSource GLSL 430 6135OpName %main "main" 6136OpName %specConstant "specConstant" 6137OpDecorate %specConstant SpecId 0 6138%void = OpTypeVoid 6139%3 = OpTypeFunction %void 6140%int = OpTypeInt 32 1 6141%specConstant = OpSpecConstant %int 0 6142%main = OpFunction %void None %3 6143%5 = OpLabel 6144OpReturn 6145OpFunctionEnd 6146)"; 6147 6148 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 6149 6150 OptimizerOptions()->preserve_spec_constants_ = true; 6151 6152 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 6153} 6154 6155TEST_F(AggressiveDCETest, LiveDecorateId) { 6156 const std::string spirv = R"(OpCapability Shader 6157OpMemoryModel Logical GLSL450 6158OpEntryPoint GLCompute %1 "main" %2 6159OpExecutionMode %1 LocalSize 8 1 1 6160OpDecorate %2 DescriptorSet 0 6161OpDecorate %2 Binding 0 6162OpDecorateId %3 UniformId %uint_2 6163%void = OpTypeVoid 6164%uint = OpTypeInt 32 0 6165%uint_2 = OpConstant %uint 2 6166%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint 6167%2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer 6168%8 = OpTypeFunction %void 6169%1 = OpFunction %void None %8 6170%9 = OpLabel 6171%3 = OpLoad %uint %2 6172OpStore %2 %3 6173OpReturn 6174OpFunctionEnd 6175)"; 6176 6177 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 6178 OptimizerOptions()->preserve_spec_constants_ = true; 6179 SinglePassRunAndCheck<AggressiveDCEPass>(spirv, spirv, true); 6180} 6181 6182TEST_F(AggressiveDCETest, LiveDecorateIdOnGroup) { 6183 const std::string spirv = R"(OpCapability Shader 6184OpMemoryModel Logical GLSL450 6185OpEntryPoint GLCompute %1 "main" %2 6186OpExecutionMode %1 LocalSize 8 1 1 6187OpDecorate %2 DescriptorSet 0 6188OpDecorate %2 Binding 0 6189OpDecorateId %3 UniformId %uint_2 6190%3 = OpDecorationGroup 6191OpGroupDecorate %3 %5 6192%void = OpTypeVoid 6193%uint = OpTypeInt 32 0 6194%uint_2 = OpConstant %uint 2 6195%_ptr_StorageBuffer_uint = OpTypePointer StorageBuffer %uint 6196%2 = OpVariable %_ptr_StorageBuffer_uint StorageBuffer 6197%9 = OpTypeFunction %void 6198%1 = OpFunction %void None %9 6199%10 = OpLabel 6200%5 = OpLoad %uint %2 6201OpStore %2 %5 6202OpReturn 6203OpFunctionEnd 6204)"; 6205 6206 SetTargetEnv(SPV_ENV_UNIVERSAL_1_4); 6207 OptimizerOptions()->preserve_spec_constants_ = true; 6208 SinglePassRunAndCheck<AggressiveDCEPass>(spirv, spirv, true); 6209} 6210 6211TEST_F(AggressiveDCETest, NoEliminateForwardPointer) { 6212 // clang-format off 6213 // 6214 // #version 450 6215 // #extension GL_EXT_buffer_reference : enable 6216 // 6217 // // forward reference 6218 // layout(buffer_reference) buffer blockType; 6219 // 6220 // layout(buffer_reference, std430, buffer_reference_align = 16) buffer blockType { 6221 // int x; 6222 // blockType next; 6223 // }; 6224 // 6225 // layout(std430) buffer rootBlock { 6226 // blockType root; 6227 // } r; 6228 // 6229 // void main() 6230 // { 6231 // blockType b = r.root; 6232 // b = b.next; 6233 // b.x = 531; 6234 // } 6235 // 6236 // clang-format on 6237 6238 const std::string predefs1 = 6239 R"(OpCapability Shader 6240OpCapability PhysicalStorageBufferAddresses 6241OpExtension "SPV_EXT_physical_storage_buffer" 6242OpExtension "SPV_KHR_storage_buffer_storage_class" 6243%1 = OpExtInstImport "GLSL.std.450" 6244OpMemoryModel PhysicalStorageBuffer64 GLSL450 6245OpEntryPoint GLCompute %main "main" 6246OpExecutionMode %main LocalSize 1 1 1 6247OpSource GLSL 450 6248OpSourceExtension "GL_EXT_buffer_reference" 6249)"; 6250 6251 const std::string names_before = 6252 R"(OpName %main "main" 6253OpName %blockType "blockType" 6254OpMemberName %blockType 0 "x" 6255OpMemberName %blockType 1 "next" 6256OpName %b "b" 6257OpName %rootBlock "rootBlock" 6258OpMemberName %rootBlock 0 "root" 6259OpName %r "r" 6260OpMemberDecorate %blockType 0 Offset 0 6261OpMemberDecorate %blockType 1 Offset 8 6262OpDecorate %blockType Block 6263OpDecorate %b AliasedPointer 6264OpMemberDecorate %rootBlock 0 Offset 0 6265OpDecorate %rootBlock Block 6266OpDecorate %r DescriptorSet 0 6267OpDecorate %r Binding 0 6268)"; 6269 6270 const std::string names_after = 6271 R"(OpName %main "main" 6272OpName %blockType "blockType" 6273OpMemberName %blockType 0 "x" 6274OpMemberName %blockType 1 "next" 6275OpName %rootBlock "rootBlock" 6276OpMemberName %rootBlock 0 "root" 6277OpName %r "r" 6278OpMemberDecorate %blockType 0 Offset 0 6279OpMemberDecorate %blockType 1 Offset 8 6280OpDecorate %blockType Block 6281OpMemberDecorate %rootBlock 0 Offset 0 6282OpDecorate %rootBlock Block 6283OpDecorate %r DescriptorSet 0 6284OpDecorate %r Binding 0 6285)"; 6286 6287 const std::string predefs2_before = 6288 R"(%void = OpTypeVoid 6289%3 = OpTypeFunction %void 6290OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer 6291%int = OpTypeInt 32 1 6292%blockType = OpTypeStruct %int %_ptr_PhysicalStorageBuffer_blockType 6293%_ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %blockType 6294%_ptr_Function__ptr_PhysicalStorageBuffer_blockType = OpTypePointer Function %_ptr_PhysicalStorageBuffer_blockType 6295%rootBlock = OpTypeStruct %_ptr_PhysicalStorageBuffer_blockType 6296%_ptr_StorageBuffer_rootBlock = OpTypePointer StorageBuffer %rootBlock 6297%r = OpVariable %_ptr_StorageBuffer_rootBlock StorageBuffer 6298%int_0 = OpConstant %int 0 6299%_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_blockType 6300%int_1 = OpConstant %int 1 6301%_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType 6302%int_531 = OpConstant %int 531 6303%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int 6304)"; 6305 6306 const std::string predefs2_after = 6307 R"(%void = OpTypeVoid 6308%8 = OpTypeFunction %void 6309OpTypeForwardPointer %_ptr_PhysicalStorageBuffer_blockType PhysicalStorageBuffer 6310%int = OpTypeInt 32 1 6311%blockType = OpTypeStruct %int %_ptr_PhysicalStorageBuffer_blockType 6312%_ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %blockType 6313%rootBlock = OpTypeStruct %_ptr_PhysicalStorageBuffer_blockType 6314%_ptr_StorageBuffer_rootBlock = OpTypePointer StorageBuffer %rootBlock 6315%r = OpVariable %_ptr_StorageBuffer_rootBlock StorageBuffer 6316%int_0 = OpConstant %int 0 6317%_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer StorageBuffer %_ptr_PhysicalStorageBuffer_blockType 6318%int_1 = OpConstant %int 1 6319%_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType = OpTypePointer PhysicalStorageBuffer %_ptr_PhysicalStorageBuffer_blockType 6320%int_531 = OpConstant %int 531 6321%_ptr_PhysicalStorageBuffer_int = OpTypePointer PhysicalStorageBuffer %int 6322)"; 6323 6324 const std::string func_before = 6325 R"(%main = OpFunction %void None %3 6326%5 = OpLabel 6327%b = OpVariable %_ptr_Function__ptr_PhysicalStorageBuffer_blockType Function 6328%16 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0 6329%17 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %16 6330%21 = OpAccessChain %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType %17 %int_1 6331%22 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %21 Aligned 8 6332OpStore %b %22 6333%26 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %22 %int_0 6334OpStore %26 %int_531 Aligned 16 6335OpReturn 6336OpFunctionEnd 6337)"; 6338 6339 const std::string func_after = 6340 R"(%main = OpFunction %void None %8 6341%19 = OpLabel 6342%20 = OpAccessChain %_ptr_StorageBuffer__ptr_PhysicalStorageBuffer_blockType %r %int_0 6343%21 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %20 6344%22 = OpAccessChain %_ptr_PhysicalStorageBuffer__ptr_PhysicalStorageBuffer_blockType %21 %int_1 6345%23 = OpLoad %_ptr_PhysicalStorageBuffer_blockType %22 Aligned 8 6346%24 = OpAccessChain %_ptr_PhysicalStorageBuffer_int %23 %int_0 6347OpStore %24 %int_531 Aligned 16 6348OpReturn 6349OpFunctionEnd 6350)"; 6351 6352 SinglePassRunAndCheck<AggressiveDCEPass>( 6353 predefs1 + names_before + predefs2_before + func_before, 6354 predefs1 + names_after + predefs2_after + func_after, true, true); 6355} 6356 6357TEST_F(AggressiveDCETest, MultipleFunctionProcessIndependently) { 6358 const std::string spirv = R"( 6359 OpCapability Shader 6360 OpMemoryModel Logical GLSL450 6361 OpEntryPoint GLCompute %entryHistogram "entryHistogram" %gl_GlobalInvocationID %gl_LocalInvocationIndex 6362 OpEntryPoint GLCompute %entryAverage "entryAverage" %gl_GlobalInvocationID %gl_LocalInvocationIndex 6363 OpExecutionMode %entryHistogram LocalSize 16 16 1 6364 OpExecutionMode %entryAverage LocalSize 256 1 1 6365 OpSource HLSL 640 6366 OpName %type_RWStructuredBuffer_uint "type.RWStructuredBuffer.uint" 6367 OpName %uHistogram "uHistogram" 6368 OpName %type_ACSBuffer_counter "type.ACSBuffer.counter" 6369 OpMemberName %type_ACSBuffer_counter 0 "counter" 6370 OpName %counter_var_uHistogram "counter.var.uHistogram" 6371 OpName %sharedHistogram "sharedHistogram" 6372 OpName %entryHistogram "entryHistogram" 6373 OpName %param_var_id "param.var.id" 6374 OpName %param_var_idx "param.var.idx" 6375 OpName %entryAverage "entryAverage" 6376 OpName %param_var_id_0 "param.var.id" 6377 OpName %param_var_idx_0 "param.var.idx" 6378 OpDecorate %gl_GlobalInvocationID BuiltIn GlobalInvocationId 6379 OpDecorate %gl_LocalInvocationIndex BuiltIn LocalInvocationIndex 6380 OpDecorate %uHistogram DescriptorSet 0 6381 OpDecorate %uHistogram Binding 0 6382 OpDecorate %counter_var_uHistogram DescriptorSet 0 6383 OpDecorate %counter_var_uHistogram Binding 1 6384 OpDecorate %_runtimearr_uint ArrayStride 4 6385 OpMemberDecorate %type_RWStructuredBuffer_uint 0 Offset 0 6386 OpDecorate %type_RWStructuredBuffer_uint BufferBlock 6387 OpMemberDecorate %type_ACSBuffer_counter 0 Offset 0 6388 OpDecorate %type_ACSBuffer_counter BufferBlock 6389 %uint = OpTypeInt 32 0 6390 %uint_0 = OpConstant %uint 0 6391 %uint_1 = OpConstant %uint 1 6392 %uint_2 = OpConstant %uint 2 6393 %uint_4 = OpConstant %uint 4 6394 %uint_8 = OpConstant %uint 8 6395 %uint_16 = OpConstant %uint 16 6396 %uint_32 = OpConstant %uint 32 6397 %uint_64 = OpConstant %uint 64 6398 %uint_128 = OpConstant %uint 128 6399 %uint_256 = OpConstant %uint 256 6400 %uint_512 = OpConstant %uint 512 6401 %uint_254 = OpConstant %uint 254 6402 %uint_255 = OpConstant %uint 255 6403 %int = OpTypeInt 32 1 6404 %int_0 = OpConstant %int 0 6405%_runtimearr_uint = OpTypeRuntimeArray %uint 6406%type_RWStructuredBuffer_uint = OpTypeStruct %_runtimearr_uint 6407%_ptr_Uniform_type_RWStructuredBuffer_uint = OpTypePointer Uniform %type_RWStructuredBuffer_uint 6408%type_ACSBuffer_counter = OpTypeStruct %int 6409%_ptr_Uniform_type_ACSBuffer_counter = OpTypePointer Uniform %type_ACSBuffer_counter 6410%_arr_uint_uint_256 = OpTypeArray %uint %uint_256 6411%_ptr_Workgroup__arr_uint_uint_256 = OpTypePointer Workgroup %_arr_uint_uint_256 6412 %v3uint = OpTypeVector %uint 3 6413%_ptr_Input_v3uint = OpTypePointer Input %v3uint 6414%_ptr_Input_uint = OpTypePointer Input %uint 6415 %void = OpTypeVoid 6416 %49 = OpTypeFunction %void 6417%_ptr_Function_v3uint = OpTypePointer Function %v3uint 6418%_ptr_Function_uint = OpTypePointer Function %uint 6419 %52 = OpTypeFunction %void %_ptr_Function_v3uint %_ptr_Function_uint 6420%_ptr_Workgroup_uint = OpTypePointer Workgroup %uint 6421 %uint_264 = OpConstant %uint 264 6422 %bool = OpTypeBool 6423%_ptr_Uniform_uint = OpTypePointer Uniform %uint 6424 %uHistogram = OpVariable %_ptr_Uniform_type_RWStructuredBuffer_uint Uniform 6425%counter_var_uHistogram = OpVariable %_ptr_Uniform_type_ACSBuffer_counter Uniform 6426%sharedHistogram = OpVariable %_ptr_Workgroup__arr_uint_uint_256 Workgroup 6427%gl_GlobalInvocationID = OpVariable %_ptr_Input_v3uint Input 6428%gl_LocalInvocationIndex = OpVariable %_ptr_Input_uint Input 6429%entryHistogram = OpFunction %void None %49 6430 %57 = OpLabel 6431%param_var_id = OpVariable %_ptr_Function_v3uint Function 6432%param_var_idx = OpVariable %_ptr_Function_uint Function 6433 %58 = OpLoad %v3uint %gl_GlobalInvocationID 6434 %59 = OpLoad %uint %gl_LocalInvocationIndex 6435 %79 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %int_0 6436 %80 = OpAtomicIAdd %uint %79 %uint_1 %uint_0 %uint_1 6437 OpReturn 6438 OpFunctionEnd 6439%entryAverage = OpFunction %void None %49 6440 %63 = OpLabel 6441%param_var_id_0 = OpVariable %_ptr_Function_v3uint Function 6442%param_var_idx_0 = OpVariable %_ptr_Function_uint Function 6443 %64 = OpLoad %v3uint %gl_GlobalInvocationID 6444 %65 = OpLoad %uint %gl_LocalInvocationIndex 6445 OpStore %param_var_idx_0 %65 6446 %83 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %65 6447 OpStore %83 %uint_0 6448 6449; CHECK: [[ieq:%\w+]] = OpIEqual 6450; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]] 6451; CHECK-NEXT: OpBranchConditional [[ieq]] [[not_elim:%\w+]] [[merge]] 6452; CHECK-NEXT: [[not_elim]] = OpLabel 6453; CHECK: [[merge]] = OpLabel 6454 6455 OpControlBarrier %uint_2 %uint_2 %uint_264 6456 %85 = OpIEqual %bool %65 %uint_0 6457 OpSelectionMerge %89 None 6458 OpBranchConditional %85 %86 %89 6459 %86 = OpLabel 6460 %88 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %65 6461 OpStore %88 %uint_1 6462 OpBranch %89 6463 %89 = OpLabel 6464 OpControlBarrier %uint_2 %uint_2 %uint_264 6465 %91 = OpAccessChain %_ptr_Workgroup_uint %sharedHistogram %65 6466 %92 = OpLoad %uint %91 6467 %94 = OpAccessChain %_ptr_Uniform_uint %uHistogram %int_0 %65 6468 OpStore %94 %92 6469 OpReturn 6470 OpFunctionEnd 6471)"; 6472 6473 SetTargetEnv(SPV_ENV_UNIVERSAL_1_3); 6474 6475 SinglePassRunAndMatch<AggressiveDCEPass>(spirv, true); 6476} 6477 6478TEST_F(AggressiveDCETest, DebugInfoKeepInFunctionElimStoreVar) { 6479 // Verify that dead local variable tc and store eliminated but all 6480 // in-function debuginfo kept. 6481 // 6482 // The SPIR-V has been inlined and local single store eliminated 6483 // 6484 // Texture2D g_tColor; 6485 // SamplerState g_sAniso; 6486 // 6487 // struct PS_INPUT { 6488 // float2 vTextureCoords : TEXCOORD2; 6489 // }; 6490 // 6491 // struct PS_OUTPUT { 6492 // float4 vColor : SV_Target0; 6493 // }; 6494 // 6495 // PS_OUTPUT MainPs(PS_INPUT i) { 6496 // PS_OUTPUT ps_output; 6497 // float2 tc = i.vTextureCoords.xy; 6498 // ps_output.vColor = g_tColor.Sample(g_sAniso, tc); 6499 // return ps_output; 6500 // } 6501 6502 const std::string text = R"( 6503 OpCapability Shader 6504 %1 = OpExtInstImport "OpenCL.DebugInfo.100" 6505 OpMemoryModel Logical GLSL450 6506 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0 6507 OpExecutionMode %MainPs OriginUpperLeft 6508 %7 = OpString "foo.frag" 6509 %8 = OpString "PS_OUTPUT" 6510 %9 = OpString "float" 6511 %10 = OpString "vColor" 6512 %11 = OpString "PS_INPUT" 6513 %12 = OpString "vTextureCoords" 6514 %13 = OpString "@type.2d.image" 6515 %14 = OpString "type.2d.image" 6516 %15 = OpString "Texture2D.TemplateParam" 6517 %16 = OpString "src.MainPs" 6518 %17 = OpString "tc" 6519 %18 = OpString "ps_output" 6520 %19 = OpString "i" 6521 %20 = OpString "@type.sampler" 6522 %21 = OpString "type.sampler" 6523 %22 = OpString "g_sAniso" 6524 %23 = OpString "g_tColor" 6525 OpName %type_2d_image "type.2d.image" 6526 OpName %g_tColor "g_tColor" 6527 OpName %type_sampler "type.sampler" 6528 OpName %g_sAniso "g_sAniso" 6529 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2" 6530 OpName %out_var_SV_Target0 "out.var.SV_Target0" 6531 OpName %MainPs "MainPs" 6532 OpName %PS_INPUT "PS_INPUT" 6533 OpMemberName %PS_INPUT 0 "vTextureCoords" 6534 OpName %param_var_i "param.var.i" 6535 OpName %PS_OUTPUT "PS_OUTPUT" 6536 OpMemberName %PS_OUTPUT 0 "vColor" 6537 OpName %type_sampled_image "type.sampled.image" 6538 OpDecorate %in_var_TEXCOORD2 Location 0 6539 OpDecorate %out_var_SV_Target0 Location 0 6540 OpDecorate %g_tColor DescriptorSet 0 6541 OpDecorate %g_tColor Binding 0 6542 OpDecorate %g_sAniso DescriptorSet 0 6543 OpDecorate %g_sAniso Binding 1 6544 %int = OpTypeInt 32 1 6545 %int_0 = OpConstant %int 0 6546 %uint = OpTypeInt 32 0 6547 %uint_32 = OpConstant %uint 32 6548 %float = OpTypeFloat 32 6549%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown 6550%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image 6551%type_sampler = OpTypeSampler 6552%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler 6553 %v2float = OpTypeVector %float 2 6554%_ptr_Input_v2float = OpTypePointer Input %v2float 6555 %v4float = OpTypeVector %float 4 6556%_ptr_Output_v4float = OpTypePointer Output %v4float 6557 %void = OpTypeVoid 6558 %uint_128 = OpConstant %uint 128 6559 %uint_0 = OpConstant %uint 0 6560 %uint_64 = OpConstant %uint 64 6561 %45 = OpTypeFunction %void 6562 %PS_INPUT = OpTypeStruct %v2float 6563%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT 6564 %PS_OUTPUT = OpTypeStruct %v4float 6565 %47 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT 6566%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT 6567%_ptr_Function_v2float = OpTypePointer Function %v2float 6568%type_sampled_image = OpTypeSampledImage %type_2d_image 6569%_ptr_Function_v4float = OpTypePointer Function %v4float 6570 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant 6571 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant 6572%in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input 6573%out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output 6574 %51 = OpExtInst %void %1 DebugInfoNone 6575 %52 = OpExtInst %void %1 DebugExpression 6576 %53 = OpExtInst %void %1 DebugOperation Deref 6577 %54 = OpExtInst %void %1 DebugExpression %53 6578 %55 = OpExtInst %void %1 DebugSource %7 6579 %56 = OpExtInst %void %1 DebugCompilationUnit 1 4 %55 HLSL 6580 %57 = OpExtInst %void %1 DebugTypeComposite %8 Structure %55 10 1 %56 %8 %uint_128 FlagIsProtected|FlagIsPrivate %58 6581 %59 = OpExtInst %void %1 DebugTypeBasic %9 %uint_32 Float 6582 %60 = OpExtInst %void %1 DebugTypeVector %59 4 6583 %58 = OpExtInst %void %1 DebugTypeMember %10 %60 %55 12 5 %57 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate 6584 %61 = OpExtInst %void %1 DebugTypeComposite %11 Structure %55 5 1 %56 %11 %uint_64 FlagIsProtected|FlagIsPrivate %62 6585 %63 = OpExtInst %void %1 DebugTypeVector %59 2 6586 %62 = OpExtInst %void %1 DebugTypeMember %12 %63 %55 7 5 %61 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate 6587 %64 = OpExtInst %void %1 DebugTypeComposite %13 Class %55 0 0 %56 %14 %51 FlagIsProtected|FlagIsPrivate 6588 %65 = OpExtInst %void %1 DebugTypeTemplateParameter %15 %59 %51 %55 0 0 6589 %66 = OpExtInst %void %1 DebugTypeTemplate %64 %65 6590 %67 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %57 %61 6591 %68 = OpExtInst %void %1 DebugFunction %16 %67 %55 15 1 %56 %16 FlagIsProtected|FlagIsPrivate 16 %51 6592 %69 = OpExtInst %void %1 DebugLexicalBlock %55 16 1 %68 6593 %70 = OpExtInst %void %1 DebugLocalVariable %17 %63 %55 19 12 %69 FlagIsLocal 6594 %71 = OpExtInst %void %1 DebugLocalVariable %18 %57 %55 17 15 %69 FlagIsLocal 6595 %72 = OpExtInst %void %1 DebugLocalVariable %19 %61 %55 15 29 %68 FlagIsLocal 1 6596 %73 = OpExtInst %void %1 DebugTypeComposite %20 Structure %55 0 0 %56 %21 %51 FlagIsProtected|FlagIsPrivate 6597 %74 = OpExtInst %void %1 DebugGlobalVariable %22 %73 %55 3 14 %56 %22 %g_sAniso FlagIsDefinition 6598 %75 = OpExtInst %void %1 DebugGlobalVariable %23 %64 %55 1 11 %56 %23 %g_tColor FlagIsDefinition 6599 %MainPs = OpFunction %void None %45 6600 %76 = OpLabel 6601 %107 = OpExtInst %void %1 DebugScope %69 6602;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %69 6603 %78 = OpVariable %_ptr_Function_PS_OUTPUT Function 6604 %79 = OpVariable %_ptr_Function_v2float Function 6605 %108 = OpExtInst %void %1 DebugNoScope 6606;CHECK: {{%\w+}} = OpExtInst %void %1 DebugNoScope 6607 %81 = OpVariable %_ptr_Function_PS_OUTPUT Function 6608%param_var_i = OpVariable %_ptr_Function_PS_INPUT Function 6609 %82 = OpLoad %v2float %in_var_TEXCOORD2 6610 %83 = OpCompositeConstruct %PS_INPUT %82 6611 OpStore %param_var_i %83 6612 %109 = OpExtInst %void %1 DebugScope %68 6613 %85 = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52 6614 %110 = OpExtInst %void %1 DebugScope %69 6615 %87 = OpExtInst %void %1 DebugDeclare %71 %78 %52 6616;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %68 6617;CHECK: {{%\w+}} = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52 6618;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %69 6619;CHECK: {{%\w+}} = OpExtInst %void %1 DebugDeclare %71 %78 %52 6620 OpLine %7 19 17 6621 %88 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0 6622 %89 = OpLoad %v2float %88 6623 OpLine %7 19 12 6624 OpStore %79 %89 6625;CHECK-NOT: OpStore %79 %89 6626 OpLine %7 19 12 6627 %106 = OpExtInst %void %1 DebugValue %70 %89 %52 6628;CHECK: {{%\w+}} = OpExtInst %void %1 DebugValue %70 %89 %52 6629 OpLine %7 20 26 6630 %91 = OpLoad %type_2d_image %g_tColor 6631 OpLine %7 20 46 6632 %92 = OpLoad %type_sampler %g_sAniso 6633 OpLine %7 20 26 6634 %94 = OpSampledImage %type_sampled_image %91 %92 6635 %95 = OpImageSampleImplicitLod %v4float %94 %89 None 6636 OpLine %7 20 5 6637 %96 = OpAccessChain %_ptr_Function_v4float %78 %int_0 6638 OpStore %96 %95 6639 OpLine %7 21 12 6640 %97 = OpLoad %PS_OUTPUT %78 6641 OpLine %7 21 5 6642 OpStore %81 %97 6643 %111 = OpExtInst %void %1 DebugNoScope 6644;CHECK: {{%\w+}} = OpExtInst %void %1 DebugNoScope 6645 %100 = OpCompositeExtract %v4float %97 0 6646 OpStore %out_var_SV_Target0 %100 6647 OpReturn 6648 OpFunctionEnd 6649)"; 6650 6651 SetTargetEnv(SPV_ENV_VULKAN_1_2); 6652 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 6653 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 6654} 6655 6656TEST_F(AggressiveDCETest, ShaderDebugInfoKeepInFunctionElimStoreVar) { 6657 // Verify that dead local variable tc and store eliminated but all 6658 // in-function NonSemantic Shader debuginfo kept. 6659 6660 const std::string text = R"( 6661 OpCapability Shader 6662 OpExtension "SPV_KHR_non_semantic_info" 6663 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100" 6664 OpMemoryModel Logical GLSL450 6665 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0 6666 OpExecutionMode %MainPs OriginUpperLeft 6667 %7 = OpString "foo.frag" 6668 %8 = OpString "PS_OUTPUT" 6669 %9 = OpString "float" 6670 %10 = OpString "vColor" 6671 %11 = OpString "PS_INPUT" 6672 %12 = OpString "vTextureCoords" 6673 %13 = OpString "@type.2d.image" 6674 %14 = OpString "type.2d.image" 6675 %15 = OpString "Texture2D.TemplateParam" 6676 %16 = OpString "src.MainPs" 6677 %17 = OpString "tc" 6678 %18 = OpString "ps_output" 6679 %19 = OpString "i" 6680 %20 = OpString "@type.sampler" 6681 %21 = OpString "type.sampler" 6682 %22 = OpString "g_sAniso" 6683 %23 = OpString "g_tColor" 6684 OpName %type_2d_image "type.2d.image" 6685 OpName %g_tColor "g_tColor" 6686 OpName %type_sampler "type.sampler" 6687 OpName %g_sAniso "g_sAniso" 6688 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2" 6689 OpName %out_var_SV_Target0 "out.var.SV_Target0" 6690 OpName %MainPs "MainPs" 6691 OpName %PS_INPUT "PS_INPUT" 6692 OpMemberName %PS_INPUT 0 "vTextureCoords" 6693 OpName %param_var_i "param.var.i" 6694 OpName %PS_OUTPUT "PS_OUTPUT" 6695 OpMemberName %PS_OUTPUT 0 "vColor" 6696 OpName %type_sampled_image "type.sampled.image" 6697 OpDecorate %in_var_TEXCOORD2 Location 0 6698 OpDecorate %out_var_SV_Target0 Location 0 6699 OpDecorate %g_tColor DescriptorSet 0 6700 OpDecorate %g_tColor Binding 0 6701 OpDecorate %g_sAniso DescriptorSet 0 6702 OpDecorate %g_sAniso Binding 1 6703 %int = OpTypeInt 32 1 6704 %int_0 = OpConstant %int 0 6705 %uint = OpTypeInt 32 0 6706 %uint_32 = OpConstant %uint 32 6707 %float = OpTypeFloat 32 6708%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown 6709%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image 6710%type_sampler = OpTypeSampler 6711%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler 6712 %v2float = OpTypeVector %float 2 6713%_ptr_Input_v2float = OpTypePointer Input %v2float 6714 %v4float = OpTypeVector %float 4 6715%_ptr_Output_v4float = OpTypePointer Output %v4float 6716 %void = OpTypeVoid 6717 %uint_128 = OpConstant %uint 128 6718 %uint_0 = OpConstant %uint 0 6719 %uint_1 = OpConstant %uint 1 6720 %uint_2 = OpConstant %uint 2 6721 %uint_3 = OpConstant %uint 3 6722 %uint_4 = OpConstant %uint 4 6723 %uint_5 = OpConstant %uint 5 6724 %uint_7 = OpConstant %uint 7 6725 %uint_8 = OpConstant %uint 8 6726 %uint_10 = OpConstant %uint 10 6727 %uint_11 = OpConstant %uint 11 6728 %uint_12 = OpConstant %uint 12 6729 %uint_14 = OpConstant %uint 14 6730 %uint_15 = OpConstant %uint 15 6731 %uint_16 = OpConstant %uint 16 6732 %uint_17 = OpConstant %uint 17 6733 %uint_19 = OpConstant %uint 19 6734 %uint_20 = OpConstant %uint 20 6735 %uint_21 = OpConstant %uint 21 6736 %uint_25 = OpConstant %uint 25 6737 %uint_29 = OpConstant %uint 29 6738 %uint_30 = OpConstant %uint 30 6739 %uint_35 = OpConstant %uint 35 6740 %uint_41 = OpConstant %uint 41 6741 %uint_48 = OpConstant %uint 48 6742 %uint_53 = OpConstant %uint 53 6743 %uint_64 = OpConstant %uint 64 6744 %45 = OpTypeFunction %void 6745 %PS_INPUT = OpTypeStruct %v2float 6746%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT 6747 %PS_OUTPUT = OpTypeStruct %v4float 6748 %47 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT 6749%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT 6750%_ptr_Function_v2float = OpTypePointer Function %v2float 6751%type_sampled_image = OpTypeSampledImage %type_2d_image 6752%_ptr_Function_v4float = OpTypePointer Function %v4float 6753 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant 6754 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant 6755%in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input 6756%out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output 6757 %51 = OpExtInst %void %1 DebugInfoNone 6758 %52 = OpExtInst %void %1 DebugExpression 6759 %53 = OpExtInst %void %1 DebugOperation %uint_0 6760 %54 = OpExtInst %void %1 DebugExpression %53 6761 %55 = OpExtInst %void %1 DebugSource %7 6762 %56 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %55 %uint_5 6763 %59 = OpExtInst %void %1 DebugTypeBasic %9 %uint_32 %uint_3 %uint_0 6764 %60 = OpExtInst %void %1 DebugTypeVector %59 %uint_4 6765 %58 = OpExtInst %void %1 DebugTypeMember %10 %60 %55 %uint_12 %uint_5 %uint_0 %uint_128 %uint_3 6766 %57 = OpExtInst %void %1 DebugTypeComposite %8 %uint_1 %55 %uint_10 %uint_1 %56 %8 %uint_128 %uint_3 %58 6767 %63 = OpExtInst %void %1 DebugTypeVector %59 %uint_2 6768 %62 = OpExtInst %void %1 DebugTypeMember %12 %63 %55 %uint_7 %uint_5 %uint_0 %uint_64 %uint_3 6769 %61 = OpExtInst %void %1 DebugTypeComposite %11 %uint_1 %55 %uint_5 %uint_1 %56 %11 %uint_64 %uint_3 %62 6770 %64 = OpExtInst %void %1 DebugTypeComposite %13 %uint_0 %55 %uint_0 %uint_0 %56 %14 %51 %uint_3 6771 %67 = OpExtInst %void %1 DebugTypeFunction %uint_3 %57 %61 6772 %68 = OpExtInst %void %1 DebugFunction %16 %67 %55 %uint_15 %uint_1 %56 %16 %uint_3 %uint_16 6773 %69 = OpExtInst %void %1 DebugLexicalBlock %55 %uint_16 %uint_1 %68 6774 %70 = OpExtInst %void %1 DebugLocalVariable %17 %63 %55 %uint_19 %uint_12 %69 %uint_4 6775 %71 = OpExtInst %void %1 DebugLocalVariable %18 %57 %55 %uint_17 %uint_15 %69 %uint_4 6776 %72 = OpExtInst %void %1 DebugLocalVariable %19 %61 %55 %uint_15 %uint_29 %68 %uint_4 %uint_1 6777 %73 = OpExtInst %void %1 DebugTypeComposite %20 %uint_1 %55 %uint_0 %uint_0 %56 %21 %51 %uint_3 6778 %74 = OpExtInst %void %1 DebugGlobalVariable %22 %73 %55 %uint_3 %uint_14 %56 %22 %g_sAniso %uint_8 6779 %75 = OpExtInst %void %1 DebugGlobalVariable %23 %64 %55 %uint_1 %uint_11 %56 %23 %g_tColor %uint_8 6780 %MainPs = OpFunction %void None %45 6781 %76 = OpLabel 6782 %78 = OpVariable %_ptr_Function_PS_OUTPUT Function 6783 %79 = OpVariable %_ptr_Function_v2float Function 6784 %81 = OpVariable %_ptr_Function_PS_OUTPUT Function 6785%param_var_i = OpVariable %_ptr_Function_PS_INPUT Function 6786 %82 = OpLoad %v2float %in_var_TEXCOORD2 6787 %83 = OpCompositeConstruct %PS_INPUT %82 6788 OpStore %param_var_i %83 6789 %112 = OpExtInst %void %1 DebugFunctionDefinition %68 %MainPs 6790 %109 = OpExtInst %void %1 DebugScope %68 6791 %85 = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52 6792 %110 = OpExtInst %void %1 DebugScope %69 6793 %87 = OpExtInst %void %1 DebugDeclare %71 %78 %52 6794;CHECK: {{%\w+}} = OpExtInst %void %1 DebugFunctionDefinition %68 %MainPs 6795;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %68 6796;CHECK: {{%\w+}} = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52 6797;CHECK: {{%\w+}} = OpExtInst %void %1 DebugScope %69 6798;CHECK: {{%\w+}} = OpExtInst %void %1 DebugDeclare %71 %78 %52 6799 %300 = OpExtInst %void %1 DebugLine %55 %uint_19 %uint_19 %uint_17 %uint_30 6800;CHECK: {{%\w+}} = OpExtInst %void %1 DebugLine %55 %uint_19 %uint_19 %uint_17 %uint_30 6801 %88 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0 6802 %89 = OpLoad %v2float %88 6803 %301 = OpExtInst %void %1 DebugLine %55 %uint_19 %uint_19 %uint_12 %uint_35 6804 OpStore %79 %89 6805;CHECK-NOT: OpStore %79 %89 6806 %302 = OpExtInst %void %1 DebugLine %55 %uint_19 %uint_19 %uint_12 %uint_35 6807;CHECK: {{%\w+}} = OpExtInst %void %1 DebugLine %55 %uint_19 %uint_19 %uint_12 %uint_35 6808 %106 = OpExtInst %void %1 DebugValue %70 %89 %52 6809;CHECK: {{%\w+}} = OpExtInst %void %1 DebugValue %70 %89 %52 6810 %303 = OpExtInst %void %1 DebugLine %55 %uint_20 %uint_20 %uint_25 %uint_32 6811 %91 = OpLoad %type_2d_image %g_tColor 6812 %304 = OpExtInst %void %1 DebugLine %55 %uint_20 %uint_20 %uint_41 %uint_48 6813 %92 = OpLoad %type_sampler %g_sAniso 6814 %305 = OpExtInst %void %1 DebugLine %55 %uint_20 %uint_20 %uint_25 %uint_53 6815 %94 = OpSampledImage %type_sampled_image %91 %92 6816 %95 = OpImageSampleImplicitLod %v4float %94 %89 None 6817 %306 = OpExtInst %void %1 DebugLine %55 %uint_20 %uint_20 %uint_5 %uint_53 6818 %96 = OpAccessChain %_ptr_Function_v4float %78 %int_0 6819 OpStore %96 %95 6820 %307 = OpExtInst %void %1 DebugLine %55 %uint_21 %uint_21 %uint_12 %uint_20 6821 %97 = OpLoad %PS_OUTPUT %78 6822 %308 = OpExtInst %void %1 DebugLine %55 %uint_21 %uint_21 %uint_5 %uint_20 6823 OpStore %81 %97 6824 %309 = OpExtInst %void %1 DebugNoLine 6825;CHECK: {{%\w+}} = OpExtInst %void %1 DebugNoLine 6826 %111 = OpExtInst %void %1 DebugNoScope 6827;CHECK: {{%\w+}} = OpExtInst %void %1 DebugNoScope 6828 %100 = OpCompositeExtract %v4float %97 0 6829 OpStore %out_var_SV_Target0 %100 6830 OpReturn 6831 OpFunctionEnd 6832)"; 6833 6834 SetTargetEnv(SPV_ENV_VULKAN_1_2); 6835 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 6836 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 6837} 6838 6839TEST_F(AggressiveDCETest, ShaderDebugInfoGlobalDCE) { 6840 // Verify that DebugGlobalVariable for eliminated private variable has 6841 // variable operand replaced with DebugInfoNone. 6842 6843 const std::string text = R"(OpCapability Shader 6844OpExtension "SPV_KHR_non_semantic_info" 6845%1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100" 6846OpMemoryModel Logical GLSL450 6847OpEntryPoint Fragment %MainPs "MainPs" %out_var_SV_Target0 %a 6848OpExecutionMode %MainPs OriginUpperLeft 6849%5 = OpString "source2.hlsl" 6850%24 = OpString "float" 6851%29 = OpString "vColor" 6852%33 = OpString "PS_OUTPUT" 6853%37 = OpString "MainPs" 6854%38 = OpString "" 6855%42 = OpString "ps_output" 6856%46 = OpString "a" 6857OpName %a "a" 6858OpName %out_var_SV_Target0 "out.var.SV_Target0" 6859OpName %MainPs "MainPs" 6860OpName %PS_OUTPUT "PS_OUTPUT" 6861OpMemberName %PS_OUTPUT 0 "vColor" 6862OpDecorate %out_var_SV_Target0 Location 0 6863%float = OpTypeFloat 32 6864%v4float = OpTypeVector %float 4 6865%8 = OpConstantNull %v4float 6866%float_0 = OpConstant %float 0 6867%10 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 6868%int = OpTypeInt 32 1 6869%int_0 = OpConstant %int 0 6870%uint = OpTypeInt 32 0 6871%uint_32 = OpConstant %uint 32 6872%_ptr_Private_v4float = OpTypePointer Private %v4float 6873%_ptr_Output_v4float = OpTypePointer Output %v4float 6874%void = OpTypeVoid 6875%uint_1 = OpConstant %uint 1 6876%uint_4 = OpConstant %uint 4 6877%uint_5 = OpConstant %uint 5 6878%uint_3 = OpConstant %uint 3 6879%uint_0 = OpConstant %uint 0 6880%uint_128 = OpConstant %uint 128 6881%uint_12 = OpConstant %uint 12 6882%uint_8 = OpConstant %uint 8 6883%uint_9 = OpConstant %uint 9 6884%uint_10 = OpConstant %uint 10 6885%uint_15 = OpConstant %uint 15 6886%48 = OpTypeFunction %void 6887%PS_OUTPUT = OpTypeStruct %v4float 6888%54 = OpTypeFunction %PS_OUTPUT 6889%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT 6890%_ptr_Function_v4float = OpTypePointer Function %v4float 6891%a = OpVariable %_ptr_Private_v4float Private 6892;CHECK-NOT: %a = OpVariable %_ptr_Private_v4float Private 6893%out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output 6894;CHECK: [[dbg_none:%\w+]] = OpExtInst %void %1 DebugInfoNone 6895%18 = OpExtInst %void %1 DebugExpression 6896%19 = OpExtInst %void %1 DebugSource %5 6897%20 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %19 %uint_5 6898%25 = OpExtInst %void %1 DebugTypeBasic %24 %uint_32 %uint_3 %uint_0 6899%28 = OpExtInst %void %1 DebugTypeVector %25 %uint_4 6900%31 = OpExtInst %void %1 DebugTypeMember %29 %28 %19 %uint_5 %uint_12 %uint_0 %uint_128 %uint_3 6901%34 = OpExtInst %void %1 DebugTypeComposite %33 %uint_1 %19 %uint_3 %uint_8 %20 %33 %uint_128 %uint_3 %31 6902%36 = OpExtInst %void %1 DebugTypeFunction %uint_3 %34 6903%39 = OpExtInst %void %1 DebugFunction %37 %36 %19 %uint_8 %uint_1 %20 %38 %uint_3 %uint_9 6904%41 = OpExtInst %void %1 DebugLexicalBlock %19 %uint_9 %uint_1 %39 6905%43 = OpExtInst %void %1 DebugLocalVariable %42 %34 %19 %uint_10 %uint_15 %41 %uint_4 6906%47 = OpExtInst %void %1 DebugGlobalVariable %46 %28 %19 %uint_1 %uint_15 %20 %46 %a %uint_8 6907;CHECK: %47 = OpExtInst %void %1 DebugGlobalVariable %46 %28 %19 %uint_1 %uint_15 %20 %46 [[dbg_none]] %uint_8 6908%MainPs = OpFunction %void None %48 6909%49 = OpLabel 6910%65 = OpVariable %_ptr_Function_PS_OUTPUT Function 6911%66 = OpVariable %_ptr_Function_PS_OUTPUT Function 6912OpStore %a %8 6913%72 = OpExtInst %void %1 DebugScope %41 6914%69 = OpExtInst %void %1 DebugDeclare %43 %65 %18 6915OpLine %5 11 5 6916%70 = OpAccessChain %_ptr_Function_v4float %65 %int_0 6917OpStore %70 %10 6918OpLine %5 12 12 6919%71 = OpLoad %PS_OUTPUT %65 6920OpLine %5 12 5 6921OpStore %66 %71 6922%73 = OpExtInst %void %1 DebugNoLine 6923%74 = OpExtInst %void %1 DebugNoScope 6924%51 = OpLoad %PS_OUTPUT %66 6925%53 = OpCompositeExtract %v4float %51 0 6926OpStore %out_var_SV_Target0 %53 6927OpLine %5 13 1 6928OpReturn 6929OpFunctionEnd 6930)"; 6931 6932 SetTargetEnv(SPV_ENV_VULKAN_1_2); 6933 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 6934 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 6935} 6936 6937TEST_F(AggressiveDCETest, DebugInfoDeclareKeepsStore) { 6938 // Verify that local variable tc and its store are kept by DebugDeclare. 6939 // 6940 // Same shader source as DebugInfoInFunctionKeepStoreVarElim. The SPIR-V 6941 // has just been inlined. 6942 6943 const std::string text = R"( 6944 OpCapability Shader 6945 %1 = OpExtInstImport "OpenCL.DebugInfo.100" 6946 OpMemoryModel Logical GLSL450 6947 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0 6948 OpExecutionMode %MainPs OriginUpperLeft 6949 %20 = OpString "foo.frag" 6950 %24 = OpString "PS_OUTPUT" 6951 %28 = OpString "float" 6952 %31 = OpString "vColor" 6953 %33 = OpString "PS_INPUT" 6954 %38 = OpString "vTextureCoords" 6955 %40 = OpString "@type.2d.image" 6956 %41 = OpString "type.2d.image" 6957 %43 = OpString "Texture2D.TemplateParam" 6958 %47 = OpString "src.MainPs" 6959 %51 = OpString "tc" 6960 %53 = OpString "ps_output" 6961 %56 = OpString "i" 6962 %58 = OpString "@type.sampler" 6963 %59 = OpString "type.sampler" 6964 %61 = OpString "g_sAniso" 6965 %63 = OpString "g_tColor" 6966 OpName %type_2d_image "type.2d.image" 6967 OpName %g_tColor "g_tColor" 6968 OpName %type_sampler "type.sampler" 6969 OpName %g_sAniso "g_sAniso" 6970 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2" 6971 OpName %out_var_SV_Target0 "out.var.SV_Target0" 6972 OpName %MainPs "MainPs" 6973 OpName %PS_INPUT "PS_INPUT" 6974 OpMemberName %PS_INPUT 0 "vTextureCoords" 6975 OpName %param_var_i "param.var.i" 6976 OpName %PS_OUTPUT "PS_OUTPUT" 6977 OpMemberName %PS_OUTPUT 0 "vColor" 6978 OpName %type_sampled_image "type.sampled.image" 6979 OpDecorate %in_var_TEXCOORD2 Location 0 6980 OpDecorate %out_var_SV_Target0 Location 0 6981 OpDecorate %g_tColor DescriptorSet 0 6982 OpDecorate %g_tColor Binding 0 6983 OpDecorate %g_sAniso DescriptorSet 0 6984 OpDecorate %g_sAniso Binding 1 6985 %int = OpTypeInt 32 1 6986 %int_0 = OpConstant %int 0 6987 %uint = OpTypeInt 32 0 6988 %uint_32 = OpConstant %uint 32 6989 %float = OpTypeFloat 32 6990%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown 6991%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image 6992%type_sampler = OpTypeSampler 6993%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler 6994 %v2float = OpTypeVector %float 2 6995%_ptr_Input_v2float = OpTypePointer Input %v2float 6996 %v4float = OpTypeVector %float 4 6997%_ptr_Output_v4float = OpTypePointer Output %v4float 6998 %void = OpTypeVoid 6999 %uint_128 = OpConstant %uint 128 7000 %uint_0 = OpConstant %uint 0 7001 %uint_64 = OpConstant %uint 64 7002 %65 = OpTypeFunction %void 7003 %PS_INPUT = OpTypeStruct %v2float 7004%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT 7005 %PS_OUTPUT = OpTypeStruct %v4float 7006 %75 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT 7007%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT 7008%_ptr_Function_v2float = OpTypePointer Function %v2float 7009%type_sampled_image = OpTypeSampledImage %type_2d_image 7010%_ptr_Function_v4float = OpTypePointer Function %v4float 7011 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant 7012 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant 7013%in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input 7014%out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output 7015 %39 = OpExtInst %void %1 DebugInfoNone 7016 %55 = OpExtInst %void %1 DebugExpression 7017 %22 = OpExtInst %void %1 DebugSource %20 7018 %23 = OpExtInst %void %1 DebugCompilationUnit 1 4 %22 HLSL 7019 %26 = OpExtInst %void %1 DebugTypeComposite %24 Structure %22 10 1 %23 %24 %uint_128 FlagIsProtected|FlagIsPrivate %27 7020 %29 = OpExtInst %void %1 DebugTypeBasic %28 %uint_32 Float 7021 %30 = OpExtInst %void %1 DebugTypeVector %29 4 7022 %27 = OpExtInst %void %1 DebugTypeMember %31 %30 %22 12 5 %26 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate 7023 %35 = OpExtInst %void %1 DebugTypeComposite %33 Structure %22 5 1 %23 %33 %uint_64 FlagIsProtected|FlagIsPrivate %36 7024 %37 = OpExtInst %void %1 DebugTypeVector %29 2 7025 %36 = OpExtInst %void %1 DebugTypeMember %38 %37 %22 7 5 %35 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate 7026 %42 = OpExtInst %void %1 DebugTypeComposite %40 Class %22 0 0 %23 %41 %39 FlagIsProtected|FlagIsPrivate 7027 %44 = OpExtInst %void %1 DebugTypeTemplateParameter %43 %29 %39 %22 0 0 7028 %45 = OpExtInst %void %1 DebugTypeTemplate %42 %44 7029 %46 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %26 %35 7030 %48 = OpExtInst %void %1 DebugFunction %47 %46 %22 15 1 %23 %47 FlagIsProtected|FlagIsPrivate 16 %39 7031 %50 = OpExtInst %void %1 DebugLexicalBlock %22 16 1 %48 7032 %52 = OpExtInst %void %1 DebugLocalVariable %51 %37 %22 19 12 %50 FlagIsLocal 7033 %54 = OpExtInst %void %1 DebugLocalVariable %53 %26 %22 17 15 %50 FlagIsLocal 7034 %57 = OpExtInst %void %1 DebugLocalVariable %56 %35 %22 15 29 %48 FlagIsLocal 1 7035 %60 = OpExtInst %void %1 DebugTypeComposite %58 Structure %22 0 0 %23 %59 %39 FlagIsProtected|FlagIsPrivate 7036 %62 = OpExtInst %void %1 DebugGlobalVariable %61 %60 %22 3 14 %23 %61 %g_sAniso FlagIsDefinition 7037 %64 = OpExtInst %void %1 DebugGlobalVariable %63 %42 %22 1 11 %23 %63 %g_tColor FlagIsDefinition 7038 %MainPs = OpFunction %void None %65 7039 %66 = OpLabel 7040 %114 = OpExtInst %void %1 DebugScope %50 7041 %98 = OpVariable %_ptr_Function_PS_OUTPUT Function 7042 %99 = OpVariable %_ptr_Function_v2float Function 7043 %115 = OpExtInst %void %1 DebugNoScope 7044 %100 = OpVariable %_ptr_Function_PS_OUTPUT Function 7045%param_var_i = OpVariable %_ptr_Function_PS_INPUT Function 7046 %70 = OpLoad %v2float %in_var_TEXCOORD2 7047 %71 = OpCompositeConstruct %PS_INPUT %70 7048 OpStore %param_var_i %71 7049 %116 = OpExtInst %void %1 DebugScope %48 7050 %102 = OpExtInst %void %1 DebugDeclare %57 %param_var_i %55 7051 %117 = OpExtInst %void %1 DebugScope %50 7052 %103 = OpExtInst %void %1 DebugDeclare %54 %98 %55 7053 OpLine %20 19 17 7054 %104 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0 7055 %105 = OpLoad %v2float %104 7056 OpLine %20 19 12 7057 OpStore %99 %105 7058;CHECK: OpStore %99 %105 7059 %106 = OpExtInst %void %1 DebugDeclare %52 %99 %55 7060 OpLine %20 20 26 7061 %107 = OpLoad %type_2d_image %g_tColor 7062 OpLine %20 20 46 7063 %108 = OpLoad %type_sampler %g_sAniso 7064 OpLine %20 20 26 7065 %110 = OpSampledImage %type_sampled_image %107 %108 7066 %111 = OpImageSampleImplicitLod %v4float %110 %105 None 7067 OpLine %20 20 5 7068 %112 = OpAccessChain %_ptr_Function_v4float %98 %int_0 7069 OpStore %112 %111 7070 OpLine %20 21 12 7071 %113 = OpLoad %PS_OUTPUT %98 7072 OpLine %20 21 5 7073 OpStore %100 %113 7074 %118 = OpExtInst %void %1 DebugNoScope 7075 %73 = OpLoad %PS_OUTPUT %100 7076 %74 = OpCompositeExtract %v4float %73 0 7077 OpStore %out_var_SV_Target0 %74 7078 OpReturn 7079 OpFunctionEnd 7080)"; 7081 7082 SetTargetEnv(SPV_ENV_VULKAN_1_2); 7083 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7084 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 7085} 7086 7087TEST_F(AggressiveDCETest, DebugInfoValueDerefKeepsStore) { 7088 // Verify that local variable tc and its store are kept by DebugValue with 7089 // Deref. 7090 // 7091 // Same shader source as DebugInfoInFunctionKeepStoreVarElim. The SPIR-V 7092 // has just been inlined and edited to replace the DebugDeclare with the 7093 // DebugValue/Deref. 7094 7095 const std::string text = R"( 7096 OpCapability Shader 7097 %1 = OpExtInstImport "OpenCL.DebugInfo.100" 7098 OpMemoryModel Logical GLSL450 7099 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0 7100 OpExecutionMode %MainPs OriginUpperLeft 7101 %7 = OpString "foo.frag" 7102 %8 = OpString "PS_OUTPUT" 7103 %9 = OpString "float" 7104 %10 = OpString "vColor" 7105 %11 = OpString "PS_INPUT" 7106 %12 = OpString "vTextureCoords" 7107 %13 = OpString "@type.2d.image" 7108 %14 = OpString "type.2d.image" 7109 %15 = OpString "Texture2D.TemplateParam" 7110 %16 = OpString "src.MainPs" 7111 %17 = OpString "tc" 7112 %18 = OpString "ps_output" 7113 %19 = OpString "i" 7114 %20 = OpString "@type.sampler" 7115 %21 = OpString "type.sampler" 7116 %22 = OpString "g_sAniso" 7117 %23 = OpString "g_tColor" 7118 OpName %type_2d_image "type.2d.image" 7119 OpName %g_tColor "g_tColor" 7120 OpName %type_sampler "type.sampler" 7121 OpName %g_sAniso "g_sAniso" 7122 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2" 7123 OpName %out_var_SV_Target0 "out.var.SV_Target0" 7124 OpName %MainPs "MainPs" 7125 OpName %PS_INPUT "PS_INPUT" 7126 OpMemberName %PS_INPUT 0 "vTextureCoords" 7127 OpName %param_var_i "param.var.i" 7128 OpName %PS_OUTPUT "PS_OUTPUT" 7129 OpMemberName %PS_OUTPUT 0 "vColor" 7130 OpName %type_sampled_image "type.sampled.image" 7131 OpDecorate %in_var_TEXCOORD2 Location 0 7132 OpDecorate %out_var_SV_Target0 Location 0 7133 OpDecorate %g_tColor DescriptorSet 0 7134 OpDecorate %g_tColor Binding 0 7135 OpDecorate %g_sAniso DescriptorSet 0 7136 OpDecorate %g_sAniso Binding 1 7137 %int = OpTypeInt 32 1 7138 %int_0 = OpConstant %int 0 7139 %uint = OpTypeInt 32 0 7140 %uint_32 = OpConstant %uint 32 7141 %float = OpTypeFloat 32 7142%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown 7143%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image 7144%type_sampler = OpTypeSampler 7145%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler 7146 %v2float = OpTypeVector %float 2 7147%_ptr_Input_v2float = OpTypePointer Input %v2float 7148 %v4float = OpTypeVector %float 4 7149%_ptr_Output_v4float = OpTypePointer Output %v4float 7150 %void = OpTypeVoid 7151 %uint_128 = OpConstant %uint 128 7152 %uint_0 = OpConstant %uint 0 7153 %uint_64 = OpConstant %uint 64 7154 %45 = OpTypeFunction %void 7155 %PS_INPUT = OpTypeStruct %v2float 7156%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT 7157 %PS_OUTPUT = OpTypeStruct %v4float 7158 %47 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT 7159%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT 7160%_ptr_Function_v2float = OpTypePointer Function %v2float 7161%type_sampled_image = OpTypeSampledImage %type_2d_image 7162%_ptr_Function_v4float = OpTypePointer Function %v4float 7163 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant 7164 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant 7165%in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input 7166%out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output 7167 %51 = OpExtInst %void %1 DebugInfoNone 7168 %52 = OpExtInst %void %1 DebugExpression 7169 %53 = OpExtInst %void %1 DebugOperation Deref 7170 %54 = OpExtInst %void %1 DebugExpression %53 7171 %55 = OpExtInst %void %1 DebugSource %7 7172 %56 = OpExtInst %void %1 DebugCompilationUnit 1 4 %55 HLSL 7173 %57 = OpExtInst %void %1 DebugTypeComposite %8 Structure %55 10 1 %56 %8 %uint_128 FlagIsProtected|FlagIsPrivate %58 7174 %59 = OpExtInst %void %1 DebugTypeBasic %9 %uint_32 Float 7175 %60 = OpExtInst %void %1 DebugTypeVector %59 4 7176 %58 = OpExtInst %void %1 DebugTypeMember %10 %60 %55 12 5 %57 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate 7177 %61 = OpExtInst %void %1 DebugTypeComposite %11 Structure %55 5 1 %56 %11 %uint_64 FlagIsProtected|FlagIsPrivate %62 7178 %63 = OpExtInst %void %1 DebugTypeVector %59 2 7179 %62 = OpExtInst %void %1 DebugTypeMember %12 %63 %55 7 5 %61 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate 7180 %64 = OpExtInst %void %1 DebugTypeComposite %13 Class %55 0 0 %56 %14 %51 FlagIsProtected|FlagIsPrivate 7181 %65 = OpExtInst %void %1 DebugTypeTemplateParameter %15 %59 %51 %55 0 0 7182 %66 = OpExtInst %void %1 DebugTypeTemplate %64 %65 7183 %67 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %57 %61 7184 %68 = OpExtInst %void %1 DebugFunction %16 %67 %55 15 1 %56 %16 FlagIsProtected|FlagIsPrivate 16 %51 7185 %69 = OpExtInst %void %1 DebugLexicalBlock %55 16 1 %68 7186 %70 = OpExtInst %void %1 DebugLocalVariable %17 %63 %55 19 12 %69 FlagIsLocal 7187 %71 = OpExtInst %void %1 DebugLocalVariable %18 %57 %55 17 15 %69 FlagIsLocal 7188 %72 = OpExtInst %void %1 DebugLocalVariable %19 %61 %55 15 29 %68 FlagIsLocal 1 7189 %73 = OpExtInst %void %1 DebugTypeComposite %20 Structure %55 0 0 %56 %21 %51 FlagIsProtected|FlagIsPrivate 7190 %74 = OpExtInst %void %1 DebugGlobalVariable %22 %73 %55 3 14 %56 %22 %g_sAniso FlagIsDefinition 7191 %75 = OpExtInst %void %1 DebugGlobalVariable %23 %64 %55 1 11 %56 %23 %g_tColor FlagIsDefinition 7192 %MainPs = OpFunction %void None %45 7193 %76 = OpLabel 7194 %101 = OpExtInst %void %1 DebugScope %69 7195 %78 = OpVariable %_ptr_Function_PS_OUTPUT Function 7196 %79 = OpVariable %_ptr_Function_v2float Function 7197 %102 = OpExtInst %void %1 DebugNoScope 7198 %81 = OpVariable %_ptr_Function_PS_OUTPUT Function 7199%param_var_i = OpVariable %_ptr_Function_PS_INPUT Function 7200 %82 = OpLoad %v2float %in_var_TEXCOORD2 7201 %83 = OpCompositeConstruct %PS_INPUT %82 7202 OpStore %param_var_i %83 7203 %103 = OpExtInst %void %1 DebugScope %68 7204 %85 = OpExtInst %void %1 DebugDeclare %72 %param_var_i %52 7205 %104 = OpExtInst %void %1 DebugScope %69 7206 %87 = OpExtInst %void %1 DebugDeclare %71 %78 %52 7207 OpLine %7 19 17 7208 %88 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0 7209 %89 = OpLoad %v2float %88 7210 OpLine %7 19 12 7211 OpStore %79 %89 7212;CHECK: OpStore %79 %89 7213 %90 = OpExtInst %void %1 DebugValue %70 %79 %54 7214 OpLine %7 20 26 7215 %91 = OpLoad %type_2d_image %g_tColor 7216 OpLine %7 20 46 7217 %92 = OpLoad %type_sampler %g_sAniso 7218 OpLine %7 20 26 7219 %94 = OpSampledImage %type_sampled_image %91 %92 7220 %95 = OpImageSampleImplicitLod %v4float %94 %89 None 7221 OpLine %7 20 5 7222 %96 = OpAccessChain %_ptr_Function_v4float %78 %int_0 7223 OpStore %96 %95 7224 OpLine %7 21 12 7225 %97 = OpLoad %PS_OUTPUT %78 7226 OpLine %7 21 5 7227 OpStore %81 %97 7228 %105 = OpExtInst %void %1 DebugNoScope 7229 %99 = OpLoad %PS_OUTPUT %81 7230 %100 = OpCompositeExtract %v4float %99 0 7231 OpStore %out_var_SV_Target0 %100 7232 OpReturn 7233 OpFunctionEnd 7234)"; 7235 7236 SetTargetEnv(SPV_ENV_VULKAN_1_2); 7237 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7238 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 7239} 7240 7241TEST_F(AggressiveDCETest, DebugInfoElimUnusedTextureKeepGlobalVariable) { 7242 // Verify that unused texture g_tColor2 is eliminated but its 7243 // DebugGlobalVariable is retained but with DebugInfoNone for its Variable. 7244 // 7245 // Same shader source as DebugInfoInFunctionKeepStoreVarElim but with unused 7246 // g_tColor2 added. 7247 7248 const std::string text = R"( 7249 OpCapability Shader 7250 %1 = OpExtInstImport "OpenCL.DebugInfo.100" 7251 OpMemoryModel Logical GLSL450 7252 OpEntryPoint Fragment %MainPs "MainPs" %g_tColor %g_tColor2 %g_sAniso %in_var_TEXCOORD2 %out_var_SV_Target0 7253 OpExecutionMode %MainPs OriginUpperLeft 7254 %21 = OpString "foo6.frag" 7255 %25 = OpString "PS_OUTPUT" 7256 %29 = OpString "float" 7257 %32 = OpString "vColor" 7258 %34 = OpString "PS_INPUT" 7259 %39 = OpString "vTextureCoords" 7260 %41 = OpString "@type.2d.image" 7261 %42 = OpString "type.2d.image" 7262 %44 = OpString "Texture2D.TemplateParam" 7263 %48 = OpString "src.MainPs" 7264 %52 = OpString "tc" 7265 %54 = OpString "ps_output" 7266 %57 = OpString "i" 7267 %59 = OpString "@type.sampler" 7268 %60 = OpString "type.sampler" 7269 %62 = OpString "g_sAniso" 7270 %64 = OpString "g_tColor2" 7271 %66 = OpString "g_tColor" 7272 OpName %type_2d_image "type.2d.image" 7273 OpName %g_tColor "g_tColor" 7274 OpName %g_tColor2 "g_tColor2" 7275 OpName %type_sampler "type.sampler" 7276 OpName %g_sAniso "g_sAniso" 7277 OpName %in_var_TEXCOORD2 "in.var.TEXCOORD2" 7278 OpName %out_var_SV_Target0 "out.var.SV_Target0" 7279 OpName %MainPs "MainPs" 7280 OpName %PS_INPUT "PS_INPUT" 7281 OpMemberName %PS_INPUT 0 "vTextureCoords" 7282 OpName %param_var_i "param.var.i" 7283 OpName %PS_OUTPUT "PS_OUTPUT" 7284 OpMemberName %PS_OUTPUT 0 "vColor" 7285 OpName %type_sampled_image "type.sampled.image" 7286 OpDecorate %in_var_TEXCOORD2 Location 0 7287 OpDecorate %out_var_SV_Target0 Location 0 7288 OpDecorate %g_tColor DescriptorSet 0 7289 OpDecorate %g_tColor Binding 0 7290 OpDecorate %g_tColor2 DescriptorSet 0 7291 OpDecorate %g_tColor2 Binding 1 7292 OpDecorate %g_sAniso DescriptorSet 0 7293 OpDecorate %g_sAniso Binding 2 7294 %int = OpTypeInt 32 1 7295 %int_0 = OpConstant %int 0 7296 %uint = OpTypeInt 32 0 7297 %uint_32 = OpConstant %uint 32 7298 %float = OpTypeFloat 32 7299%type_2d_image = OpTypeImage %float 2D 2 0 0 1 Unknown 7300%_ptr_UniformConstant_type_2d_image = OpTypePointer UniformConstant %type_2d_image 7301%type_sampler = OpTypeSampler 7302%_ptr_UniformConstant_type_sampler = OpTypePointer UniformConstant %type_sampler 7303 %v2float = OpTypeVector %float 2 7304%_ptr_Input_v2float = OpTypePointer Input %v2float 7305 %v4float = OpTypeVector %float 4 7306%_ptr_Output_v4float = OpTypePointer Output %v4float 7307 %void = OpTypeVoid 7308 %uint_128 = OpConstant %uint 128 7309 %uint_0 = OpConstant %uint 0 7310 %uint_64 = OpConstant %uint 64 7311 %68 = OpTypeFunction %void 7312 %PS_INPUT = OpTypeStruct %v2float 7313%_ptr_Function_PS_INPUT = OpTypePointer Function %PS_INPUT 7314 %PS_OUTPUT = OpTypeStruct %v4float 7315 %78 = OpTypeFunction %PS_OUTPUT %_ptr_Function_PS_INPUT 7316%_ptr_Function_PS_OUTPUT = OpTypePointer Function %PS_OUTPUT 7317%_ptr_Function_v2float = OpTypePointer Function %v2float 7318%type_sampled_image = OpTypeSampledImage %type_2d_image 7319%_ptr_Function_v4float = OpTypePointer Function %v4float 7320 %g_tColor = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant 7321 %g_tColor2 = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant 7322;CHECK-NOT: %g_tColor2 = OpVariable %_ptr_UniformConstant_type_2d_image UniformConstant 7323 %g_sAniso = OpVariable %_ptr_UniformConstant_type_sampler UniformConstant 7324%in_var_TEXCOORD2 = OpVariable %_ptr_Input_v2float Input 7325%out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output 7326 %40 = OpExtInst %void %1 DebugInfoNone 7327 %56 = OpExtInst %void %1 DebugExpression 7328 %23 = OpExtInst %void %1 DebugSource %21 7329 %24 = OpExtInst %void %1 DebugCompilationUnit 1 4 %23 HLSL 7330 %27 = OpExtInst %void %1 DebugTypeComposite %25 Structure %23 11 1 %24 %25 %uint_128 FlagIsProtected|FlagIsPrivate %28 7331 %30 = OpExtInst %void %1 DebugTypeBasic %29 %uint_32 Float 7332 %31 = OpExtInst %void %1 DebugTypeVector %30 4 7333 %28 = OpExtInst %void %1 DebugTypeMember %32 %31 %23 13 5 %27 %uint_0 %uint_128 FlagIsProtected|FlagIsPrivate 7334 %36 = OpExtInst %void %1 DebugTypeComposite %34 Structure %23 6 1 %24 %34 %uint_64 FlagIsProtected|FlagIsPrivate %37 7335 %38 = OpExtInst %void %1 DebugTypeVector %30 2 7336 %37 = OpExtInst %void %1 DebugTypeMember %39 %38 %23 8 5 %36 %uint_0 %uint_64 FlagIsProtected|FlagIsPrivate 7337 %43 = OpExtInst %void %1 DebugTypeComposite %41 Class %23 0 0 %24 %42 %40 FlagIsProtected|FlagIsPrivate 7338 %45 = OpExtInst %void %1 DebugTypeTemplateParameter %44 %30 %40 %23 0 0 7339 %46 = OpExtInst %void %1 DebugTypeTemplate %43 %45 7340 %47 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %27 %36 7341 %49 = OpExtInst %void %1 DebugFunction %48 %47 %23 16 1 %24 %48 FlagIsProtected|FlagIsPrivate 17 %40 7342 %51 = OpExtInst %void %1 DebugLexicalBlock %23 17 1 %49 7343 %53 = OpExtInst %void %1 DebugLocalVariable %52 %38 %23 20 12 %51 FlagIsLocal 7344 %55 = OpExtInst %void %1 DebugLocalVariable %54 %27 %23 18 15 %51 FlagIsLocal 7345 %58 = OpExtInst %void %1 DebugLocalVariable %57 %36 %23 16 29 %49 FlagIsLocal 1 7346 %61 = OpExtInst %void %1 DebugTypeComposite %59 Structure %23 0 0 %24 %60 %40 FlagIsProtected|FlagIsPrivate 7347 %63 = OpExtInst %void %1 DebugGlobalVariable %62 %61 %23 4 14 %24 %62 %g_sAniso FlagIsDefinition 7348 %65 = OpExtInst %void %1 DebugGlobalVariable %64 %43 %23 2 11 %24 %64 %g_tColor2 FlagIsDefinition 7349;CHECK-NOT: %65 = OpExtInst %void %1 DebugGlobalVariable %64 %43 %23 2 11 %24 %64 %g_tColor2 FlagIsDefinition 7350;CHECK: %65 = OpExtInst %void %1 DebugGlobalVariable %64 %43 %23 2 11 %24 %64 %40 FlagIsDefinition 7351 %67 = OpExtInst %void %1 DebugGlobalVariable %66 %43 %23 1 11 %24 %66 %g_tColor FlagIsDefinition 7352 %MainPs = OpFunction %void None %68 7353 %69 = OpLabel 7354 %117 = OpExtInst %void %1 DebugScope %51 7355 %101 = OpVariable %_ptr_Function_PS_OUTPUT Function 7356 %102 = OpVariable %_ptr_Function_v2float Function 7357 %118 = OpExtInst %void %1 DebugNoScope 7358 %103 = OpVariable %_ptr_Function_PS_OUTPUT Function 7359%param_var_i = OpVariable %_ptr_Function_PS_INPUT Function 7360 %73 = OpLoad %v2float %in_var_TEXCOORD2 7361 %74 = OpCompositeConstruct %PS_INPUT %73 7362 OpStore %param_var_i %74 7363 %119 = OpExtInst %void %1 DebugScope %49 7364 %105 = OpExtInst %void %1 DebugDeclare %58 %param_var_i %56 7365 %120 = OpExtInst %void %1 DebugScope %51 7366 %106 = OpExtInst %void %1 DebugDeclare %55 %101 %56 7367 OpLine %21 20 17 7368 %107 = OpAccessChain %_ptr_Function_v2float %param_var_i %int_0 7369 %108 = OpLoad %v2float %107 7370 OpLine %21 20 12 7371 OpStore %102 %108 7372 %109 = OpExtInst %void %1 DebugDeclare %53 %102 %56 7373 OpLine %21 21 26 7374 %110 = OpLoad %type_2d_image %g_tColor 7375 OpLine %21 21 46 7376 %111 = OpLoad %type_sampler %g_sAniso 7377 OpLine %21 21 57 7378 %112 = OpLoad %v2float %102 7379 OpLine %21 21 26 7380 %113 = OpSampledImage %type_sampled_image %110 %111 7381 %114 = OpImageSampleImplicitLod %v4float %113 %112 None 7382 OpLine %21 21 5 7383 %115 = OpAccessChain %_ptr_Function_v4float %101 %int_0 7384 OpStore %115 %114 7385 OpLine %21 22 12 7386 %116 = OpLoad %PS_OUTPUT %101 7387 OpLine %21 22 5 7388 OpStore %103 %116 7389 %121 = OpExtInst %void %1 DebugNoScope 7390 %76 = OpLoad %PS_OUTPUT %103 7391 %77 = OpCompositeExtract %v4float %76 0 7392 OpStore %out_var_SV_Target0 %77 7393 OpReturn 7394 OpFunctionEnd 7395)"; 7396 7397 SetTargetEnv(SPV_ENV_VULKAN_1_2); 7398 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7399 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 7400} 7401 7402TEST_F(AggressiveDCETest, KeepDebugScopeParent) { 7403 // Verify that local variable tc and its store are kept by DebugDeclare. 7404 // 7405 // Same shader source as DebugInfoInFunctionKeepStoreVarElim. The SPIR-V 7406 // has just been inlined. 7407 7408 const std::string text = R"( 7409 OpCapability Shader 7410 %1 = OpExtInstImport "OpenCL.DebugInfo.100" 7411 OpMemoryModel Logical GLSL450 7412 OpEntryPoint Fragment %main "main" %out_var_SV_TARGET0 7413 OpExecutionMode %main OriginUpperLeft 7414 %11 = OpString "float" 7415 %16 = OpString "t.hlsl" 7416 %19 = OpString "src.main" 7417 OpName %out_var_SV_TARGET0 "out.var.SV_TARGET0" 7418 OpName %main "main" 7419 OpDecorate %out_var_SV_TARGET0 Location 0 7420 %float = OpTypeFloat 32 7421 %float_0 = OpConstant %float 0 7422 %v4float = OpTypeVector %float 4 7423 %7 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0 7424 %uint = OpTypeInt 32 0 7425 %uint_32 = OpConstant %uint 32 7426%_ptr_Output_v4float = OpTypePointer Output %v4float 7427 %void = OpTypeVoid 7428 %23 = OpTypeFunction %void 7429 %26 = OpTypeFunction %v4float 7430%out_var_SV_TARGET0 = OpVariable %_ptr_Output_v4float Output 7431%_ptr_Function_v4float = OpTypePointer Function %v4float 7432 %33 = OpExtInst %void %1 DebugInfoNone 7433 %13 = OpExtInst %void %1 DebugTypeBasic %11 %uint_32 Float 7434 %14 = OpExtInst %void %1 DebugTypeVector %13 4 7435 %15 = OpExtInst %void %1 DebugTypeFunction FlagIsProtected|FlagIsPrivate %14 7436 %17 = OpExtInst %void %1 DebugSource %16 7437 %18 = OpExtInst %void %1 DebugCompilationUnit 1 4 %17 HLSL 7438 %20 = OpExtInst %void %1 DebugFunction %19 %15 %17 1 1 %18 %19 FlagIsProtected|FlagIsPrivate 2 %33 7439 %22 = OpExtInst %void %1 DebugLexicalBlock %17 2 1 %20 7440 %main = OpFunction %void None %23 7441 %24 = OpLabel 7442 %31 = OpVariable %_ptr_Function_v4float Function 7443; CHECK: [[block:%\w+]] = OpExtInst %void %1 DebugLexicalBlock 7444; CHECK: DebugScope [[block]] 7445 %34 = OpExtInst %void %1 DebugScope %22 7446 OpLine %16 3 5 7447 OpStore %31 %7 7448 OpStore %out_var_SV_TARGET0 %7 7449 %35 = OpExtInst %void %1 DebugNoScope 7450 OpReturn 7451 OpFunctionEnd 7452)"; 7453 7454 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7455 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 7456} 7457 7458TEST_F(AggressiveDCETest, KeepExportFunctions) { 7459 // All functions are reachable. In particular, ExportedFunc and Constant are 7460 // reachable because ExportedFunc is exported. Nothing should be removed. 7461 const std::vector<const char*> text = { 7462 // clang-format off 7463 "OpCapability Shader", 7464 "OpCapability Linkage", 7465 "OpMemoryModel Logical GLSL450", 7466 "OpEntryPoint Fragment %main \"main\"", 7467 "OpName %main \"main\"", 7468 "OpName %ExportedFunc \"ExportedFunc\"", 7469 "OpName %Live \"Live\"", 7470 "OpDecorate %ExportedFunc LinkageAttributes \"ExportedFunc\" Export", 7471 "%void = OpTypeVoid", 7472 "%7 = OpTypeFunction %void", 7473 "%main = OpFunction %void None %7", 7474 "%15 = OpLabel", 7475 "OpReturn", 7476 "OpFunctionEnd", 7477"%ExportedFunc = OpFunction %void None %7", 7478 "%19 = OpLabel", 7479 "%16 = OpFunctionCall %void %Live", 7480 "OpReturn", 7481 "OpFunctionEnd", 7482 "%Live = OpFunction %void None %7", 7483 "%20 = OpLabel", 7484 "OpReturn", 7485 "OpFunctionEnd" 7486 // clang-format on 7487 }; 7488 7489 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7490 std::string assembly = JoinAllInsts(text); 7491 auto result = SinglePassRunAndDisassemble<AggressiveDCEPass>( 7492 assembly, /* skip_nop = */ true, /* do_validation = */ false); 7493 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 7494 EXPECT_EQ(assembly, std::get<0>(result)); 7495} 7496 7497TEST_F(AggressiveDCETest, KeepPrivateVarInExportFunctions) { 7498 // The loads and stores from the private variable should not be removed 7499 // because the functions are exported and could be called. 7500 const std::string text = R"(OpCapability Shader 7501OpCapability Linkage 7502OpMemoryModel Logical GLSL450 7503OpSource HLSL 630 7504OpName %privateVar "privateVar" 7505OpName %ReadPrivate "ReadPrivate" 7506OpName %WritePrivate "WritePrivate" 7507OpName %value "value" 7508OpDecorate %ReadPrivate LinkageAttributes "ReadPrivate" Export 7509OpDecorate %WritePrivate LinkageAttributes "WritePrivate" Export 7510%int = OpTypeInt 32 1 7511%_ptr_Private_int = OpTypePointer Private %int 7512%6 = OpTypeFunction %int 7513%void = OpTypeVoid 7514%_ptr_Function_int = OpTypePointer Function %int 7515%10 = OpTypeFunction %void %_ptr_Function_int 7516%privateVar = OpVariable %_ptr_Private_int Private 7517%ReadPrivate = OpFunction %int None %6 7518%12 = OpLabel 7519%8 = OpLoad %int %privateVar 7520OpReturnValue %8 7521OpFunctionEnd 7522%WritePrivate = OpFunction %void None %10 7523%value = OpFunctionParameter %_ptr_Function_int 7524%13 = OpLabel 7525%14 = OpLoad %int %value 7526OpStore %privateVar %14 7527OpReturn 7528OpFunctionEnd 7529)"; 7530 7531 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7532 auto result = SinglePassRunAndDisassemble<AggressiveDCEPass>( 7533 text, /* skip_nop = */ true, /* do_validation = */ false); 7534 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 7535 EXPECT_EQ(text, std::get<0>(result)); 7536} 7537 7538TEST_F(AggressiveDCETest, KeepLableNames) { 7539 const std::string text = R"(OpCapability Shader 7540OpCapability Linkage 7541OpMemoryModel Logical GLSL450 7542OpSource HLSL 630 7543OpName %WritePrivate "WritePrivate" 7544OpName %entry "entry" 7545OpName %target "target" 7546OpDecorate %WritePrivate LinkageAttributes "WritePrivate" Export 7547%void = OpTypeVoid 7548%3 = OpTypeFunction %void 7549%WritePrivate = OpFunction %void None %3 7550%entry = OpLabel 7551OpBranch %target 7552%target = OpLabel 7553OpReturn 7554OpFunctionEnd 7555)"; 7556 7557 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7558 auto result = SinglePassRunAndDisassemble<AggressiveDCEPass>( 7559 text, /* skip_nop = */ true, /* do_validation = */ false); 7560 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 7561 EXPECT_EQ(text, std::get<0>(result)); 7562} 7563 7564TEST_F(AggressiveDCETest, PreserveInterface) { 7565 // Set preserve_interface to true. Verify that unused uniform 7566 // constant in entry point interface is not eliminated. 7567 const std::string text = R"(OpCapability RayTracingKHR 7568OpExtension "SPV_KHR_ray_tracing" 7569%1 = OpExtInstImport "GLSL.std.450" 7570OpMemoryModel Logical GLSL450 7571OpEntryPoint RayGenerationNV %2 "main" %3 %4 7572OpDecorate %3 Location 0 7573OpDecorate %4 DescriptorSet 2 7574OpDecorate %4 Binding 0 7575%void = OpTypeVoid 7576%6 = OpTypeFunction %void 7577%uint = OpTypeInt 32 0 7578%uint_0 = OpConstant %uint 0 7579%float = OpTypeFloat 32 7580%_ptr_CallableDataNV_float = OpTypePointer CallableDataNV %float 7581%3 = OpVariable %_ptr_CallableDataNV_float CallableDataNV 7582%13 = OpTypeAccelerationStructureKHR 7583%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13 7584%4 = OpVariable %_ptr_UniformConstant_13 UniformConstant 7585%2 = OpFunction %void None %6 7586%15 = OpLabel 7587OpExecuteCallableKHR %uint_0 %3 7588OpReturn 7589OpFunctionEnd 7590)"; 7591 7592 SetTargetEnv(SPV_ENV_VULKAN_1_2); 7593 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7594 auto result = SinglePassRunAndDisassemble<AggressiveDCEPass>( 7595 text, /* skip_nop = */ true, /* do_validation = */ false, 7596 /* preserve_interface */ true); 7597 EXPECT_EQ(Pass::Status::SuccessWithoutChange, std::get<1>(result)); 7598 EXPECT_EQ(text, std::get<0>(result)); 7599} 7600 7601TEST_F(AggressiveDCETest, EmptyContinueWithConditionalBranch) { 7602 const std::string text = R"(OpCapability Shader 7603%1 = OpExtInstImport "GLSL.std.450" 7604OpMemoryModel Logical GLSL450 7605OpEntryPoint Fragment %2 "main" 7606OpExecutionMode %2 OriginUpperLeft 7607%void = OpTypeVoid 7608%4 = OpTypeFunction %void 7609%bool = OpTypeBool 7610%false = OpConstantFalse %bool 7611%2 = OpFunction %void None %4 7612%9 = OpLabel 7613OpBranch %10 7614%10 = OpLabel 7615OpLoopMerge %11 %12 None 7616OpBranch %13 7617%13 = OpLabel 7618OpKill 7619%12 = OpLabel 7620OpBranchConditional %false %10 %10 7621%11 = OpLabel 7622OpUnreachable 7623OpFunctionEnd 7624)"; 7625 7626 SetTargetEnv(SPV_ENV_VULKAN_1_2); 7627 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7628 SinglePassRunAndCheck<AggressiveDCEPass>(text, text, false); 7629} 7630 7631TEST_F(AggressiveDCETest, FunctionBecomesUnreachableAfterDCE) { 7632 const std::string text = R"( 7633 OpCapability Shader 7634 %1 = OpExtInstImport "GLSL.std.450" 7635 OpMemoryModel Logical GLSL450 7636 OpEntryPoint Fragment %2 "main" 7637 OpExecutionMode %2 OriginUpperLeft 7638 OpSource ESSL 320 7639 %void = OpTypeVoid 7640 %4 = OpTypeFunction %void 7641 %int = OpTypeInt 32 1 7642%_ptr_Function_int = OpTypePointer Function %int 7643 %7 = OpTypeFunction %int 7644 %int_n1 = OpConstant %int -1 7645 %2 = OpFunction %void None %4 7646 %9 = OpLabel 7647 OpKill 7648 %10 = OpLabel 7649 %11 = OpFunctionCall %int %12 7650 OpReturn 7651 OpFunctionEnd 7652; CHECK: {{%\w+}} = OpFunction %int DontInline|Pure 7653 %12 = OpFunction %int DontInline|Pure %7 7654; CHECK-NEXT: {{%\w+}} = OpLabel 7655 %13 = OpLabel 7656 %14 = OpVariable %_ptr_Function_int Function 7657; CHECK-NEXT: OpBranch [[header:%\w+]] 7658 OpBranch %15 7659; CHECK-NEXT: [[header]] = OpLabel 7660; CHECK-NEXT: OpBranch [[merge:%\w+]] 7661 %15 = OpLabel 7662 OpLoopMerge %16 %17 None 7663 OpBranch %18 7664 %18 = OpLabel 7665 %19 = OpLoad %int %14 7666 OpBranch %17 7667 %17 = OpLabel 7668 OpBranch %15 7669; CHECK-NEXT: [[merge]] = OpLabel 7670 %16 = OpLabel 7671; CHECK-NEXT: OpReturnValue %int_n1 7672 OpReturnValue %int_n1 7673; CHECK-NEXT: OpFunctionEnd 7674 OpFunctionEnd 7675)"; 7676 7677 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 7678} 7679 7680TEST_F(AggressiveDCETest, KeepTopLevelDebugInfo) { 7681 // Don't eliminate DebugCompilationUnit, DebugSourceContinued, and 7682 // DebugEntryPoint 7683 const std::string text = R"( 7684 OpCapability Shader 7685 OpExtension "SPV_KHR_non_semantic_info" 7686 %1 = OpExtInstImport "NonSemantic.Shader.DebugInfo.100" 7687 OpMemoryModel Logical GLSL450 7688 OpEntryPoint Fragment %MainPs "MainPs" %out_var_SV_Target0 7689 OpExecutionMode %MainPs OriginUpperLeft 7690 %4 = OpString "foo2.frag" 7691 %5 = OpString " 7692struct PS_OUTPUT 7693{ 7694 float4 vColor : SV_Target0 ; 7695} ; 7696 7697" 7698 %6 = OpString " 7699PS_OUTPUT MainPs ( ) 7700{ 7701 PS_OUTPUT ps_output ; 7702 ps_output . vColor = float4( 1.0, 0.0, 0.0, 0.0 ); 7703 return ps_output ; 7704} 7705 7706" 7707 %7 = OpString "float" 7708 %8 = OpString "vColor" 7709 %9 = OpString "PS_OUTPUT" 7710 %10 = OpString "MainPs" 7711 %11 = OpString "" 7712 %12 = OpString "ps_output" 7713 %13 = OpString "97a939fb" 7714 %14 = OpString " foo2.frag -E MainPs -T ps_6_1 -spirv -fspv-target-env=vulkan1.2 -fspv-debug=vulkan-with-source -fcgl -Fo foo2.frag.nopt.spv -Qembed_debug" 7715 OpName %out_var_SV_Target0 "out.var.SV_Target0" 7716 OpName %MainPs "MainPs" 7717 OpDecorate %out_var_SV_Target0 Location 0 7718 %float = OpTypeFloat 32 7719 %float_1 = OpConstant %float 1 7720 %float_0 = OpConstant %float 0 7721 %v4float = OpTypeVector %float 4 7722 %23 = OpConstantComposite %v4float %float_1 %float_0 %float_0 %float_0 7723 %int = OpTypeInt 32 1 7724 %int_0 = OpConstant %int 0 7725 %uint = OpTypeInt 32 0 7726 %uint_32 = OpConstant %uint 32 7727%_ptr_Output_v4float = OpTypePointer Output %v4float 7728 %void = OpTypeVoid 7729 %uint_1 = OpConstant %uint 1 7730 %uint_4 = OpConstant %uint 4 7731 %uint_5 = OpConstant %uint 5 7732 %uint_3 = OpConstant %uint 3 7733 %uint_0 = OpConstant %uint 0 7734 %uint_128 = OpConstant %uint 128 7735 %uint_12 = OpConstant %uint 12 7736 %uint_2 = OpConstant %uint 2 7737 %uint_8 = OpConstant %uint 8 7738 %uint_7 = OpConstant %uint 7 7739 %uint_9 = OpConstant %uint 9 7740 %uint_15 = OpConstant %uint 15 7741 %42 = OpTypeFunction %void 7742 %uint_10 = OpConstant %uint 10 7743 %uint_53 = OpConstant %uint 53 7744%out_var_SV_Target0 = OpVariable %_ptr_Output_v4float Output 7745 %49 = OpExtInst %void %1 DebugExpression 7746 %50 = OpExtInst %void %1 DebugSource %4 %5 7747 %51 = OpExtInst %void %1 DebugSourceContinued %6 7748; CHECK: %51 = OpExtInst %void %1 DebugSourceContinued %6 7749 %52 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %50 %uint_5 7750; CHECK: %52 = OpExtInst %void %1 DebugCompilationUnit %uint_1 %uint_4 %50 %uint_5 7751 %53 = OpExtInst %void %1 DebugTypeBasic %7 %uint_32 %uint_3 %uint_0 7752 %54 = OpExtInst %void %1 DebugTypeVector %53 %uint_4 7753 %55 = OpExtInst %void %1 DebugTypeMember %8 %54 %50 %uint_4 %uint_12 %uint_0 %uint_128 %uint_3 7754 %56 = OpExtInst %void %1 DebugTypeComposite %9 %uint_1 %50 %uint_2 %uint_8 %52 %9 %uint_128 %uint_3 %55 7755 %57 = OpExtInst %void %1 DebugTypeFunction %uint_3 %56 7756 %58 = OpExtInst %void %1 DebugFunction %10 %57 %50 %uint_7 %uint_1 %52 %11 %uint_3 %uint_8 7757 %59 = OpExtInst %void %1 DebugLexicalBlock %50 %uint_8 %uint_1 %58 7758 %60 = OpExtInst %void %1 DebugLocalVariable %12 %56 %50 %uint_9 %uint_15 %59 %uint_4 7759 %61 = OpExtInst %void %1 DebugEntryPoint %58 %52 %13 %14 7760; CHECK: %61 = OpExtInst %void %1 DebugEntryPoint %58 %52 %13 %14 7761 %MainPs = OpFunction %void None %42 7762 %62 = OpLabel 7763 %63 = OpExtInst %void %1 DebugFunctionDefinition %58 %MainPs 7764 %112 = OpExtInst %void %1 DebugScope %59 7765 %111 = OpExtInst %void %1 DebugLine %50 %uint_10 %uint_10 %uint_5 %uint_53 7766 %110 = OpExtInst %void %1 DebugValue %60 %23 %49 %int_0 7767 %113 = OpExtInst %void %1 DebugNoLine 7768 %114 = OpExtInst %void %1 DebugNoScope 7769 OpStore %out_var_SV_Target0 %23 7770 %66 = OpExtInst %void %1 DebugLine %50 %uint_12 %uint_12 %uint_1 %uint_1 7771 OpReturn 7772 OpFunctionEnd 7773)"; 7774 7775 SetTargetEnv(SPV_ENV_VULKAN_1_2); 7776 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7777 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 7778} 7779 7780TEST_F(AggressiveDCETest, RemoveOutputTrue) { 7781 // Remove dead n_out output variable from module 7782 const std::string text = R"( 7783 OpCapability Shader 7784 %1 = OpExtInstImport "GLSL.std.450" 7785 OpMemoryModel Logical GLSL450 7786 OpEntryPoint Vertex %main "main" %c_out %c_in %n_out 7787;CHECK: OpEntryPoint Vertex %main "main" %c_out %c_in 7788 OpSource GLSL 450 7789 OpName %main "main" 7790 OpName %c_out "c_out" 7791 OpName %c_in "c_in" 7792 OpName %n_out "n_out" 7793 OpDecorate %c_out Location 0 7794 OpDecorate %c_in Location 0 7795 OpDecorate %n_out Location 1 7796 %void = OpTypeVoid 7797 %3 = OpTypeFunction %void 7798 %float = OpTypeFloat 32 7799 %v4float = OpTypeVector %float 4 7800%_ptr_Output_v4float = OpTypePointer Output %v4float 7801 %c_out = OpVariable %_ptr_Output_v4float Output 7802%_ptr_Input_v4float = OpTypePointer Input %v4float 7803 %c_in = OpVariable %_ptr_Input_v4float Input 7804 %v3float = OpTypeVector %float 3 7805%_ptr_Output_v3float = OpTypePointer Output %v3float 7806 %n_out = OpVariable %_ptr_Output_v3float Output 7807 %main = OpFunction %void None %3 7808 %5 = OpLabel 7809 %12 = OpLoad %v4float %c_in 7810 OpStore %c_out %12 7811 OpReturn 7812 OpFunctionEnd 7813)"; 7814 7815 SetTargetEnv(SPV_ENV_VULKAN_1_3); 7816 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7817 SinglePassRunAndMatch<AggressiveDCEPass>(text, true, false, true); 7818} 7819 7820TEST_F(AggressiveDCETest, RemoveOutputFalse) { 7821 // Remove dead n_out output variable from module 7822 const std::string text = R"( 7823 OpCapability Shader 7824 %1 = OpExtInstImport "GLSL.std.450" 7825 OpMemoryModel Logical GLSL450 7826 OpEntryPoint Vertex %main "main" %c_out %c_in %n_out 7827;CHECK: OpEntryPoint Vertex %main "main" %c_out %c_in %n_out 7828 OpSource GLSL 450 7829 OpName %main "main" 7830 OpName %c_out "c_out" 7831 OpName %c_in "c_in" 7832 OpName %n_out "n_out" 7833 OpDecorate %c_out Location 0 7834 OpDecorate %c_in Location 0 7835 OpDecorate %n_out Location 1 7836 %void = OpTypeVoid 7837 %3 = OpTypeFunction %void 7838 %float = OpTypeFloat 32 7839 %v4float = OpTypeVector %float 4 7840%_ptr_Output_v4float = OpTypePointer Output %v4float 7841 %c_out = OpVariable %_ptr_Output_v4float Output 7842%_ptr_Input_v4float = OpTypePointer Input %v4float 7843 %c_in = OpVariable %_ptr_Input_v4float Input 7844 %v3float = OpTypeVector %float 3 7845%_ptr_Output_v3float = OpTypePointer Output %v3float 7846 %n_out = OpVariable %_ptr_Output_v3float Output 7847 %main = OpFunction %void None %3 7848 %5 = OpLabel 7849 %12 = OpLoad %v4float %c_in 7850 OpStore %c_out %12 7851 OpReturn 7852 OpFunctionEnd 7853)"; 7854 7855 SetTargetEnv(SPV_ENV_VULKAN_1_3); 7856 SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 7857 SinglePassRunAndMatch<AggressiveDCEPass>(text, true, false, false); 7858} 7859 7860TEST_F(AggressiveDCETest, RemoveWhenUsingPrintfExtension) { 7861 // Remove dead n_out output variable from module 7862 const std::string text = R"( 7863; CHECK: OpExtInstImport "NonSemantic.DebugPrintf" 7864; CHECK-NOT: OpVariable 7865 OpCapability Shader 7866 %1 = OpExtInstImport "NonSemantic.DebugPrintf" 7867 OpMemoryModel Logical GLSL450 7868 OpEntryPoint GLCompute %main "main" 7869 OpExecutionMode %main LocalSize 8 8 1 7870 OpSource HLSL 660 7871 OpName %main "main" 7872 %uint = OpTypeInt 32 0 7873 %void = OpTypeVoid 7874 %5 = OpTypeFunction %void 7875%_ptr_Function_uint = OpTypePointer Function %uint 7876 %main = OpFunction %void None %5 7877 %7 = OpLabel 7878 %8 = OpVariable %_ptr_Function_uint Function 7879 OpReturn 7880 OpFunctionEnd 7881)"; 7882 7883 SetTargetEnv(SPV_ENV_VULKAN_1_3); 7884 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 7885} 7886 7887TEST_F(AggressiveDCETest, FunctionReturnPointer) { 7888 // Run DCE when a function returning a pointer to a reference is present 7889 7890 const std::string text = R"( 7891 OpCapability Shader 7892 OpCapability PhysicalStorageBufferAddresses 7893 %1 = OpExtInstImport "GLSL.std.450" 7894 OpMemoryModel PhysicalStorageBuffer64 GLSL450 7895 OpEntryPoint Vertex %2 "main" %3 %4 7896 OpSource GLSL 450 7897 OpSourceExtension "GL_EXT_buffer_reference" 7898 OpSourceExtension "GL_EXT_scalar_block_layout" 7899 OpName %4 "color" 7900 OpMemberDecorate %5 0 Offset 0 7901 OpDecorate %5 Block 7902 OpMemberDecorate %7 0 Offset 0 7903 OpDecorate %7 Block 7904 OpDecorate %8 AliasedPointer 7905 OpDecorate %4 Location 0 7906 %9 = OpTypeVoid 7907 %10 = OpTypeFunction %9 7908 OpTypeForwardPointer %11 PhysicalStorageBuffer 7909 %12 = OpTypeInt 32 0 7910 %5 = OpTypeStruct %12 7911 %11 = OpTypePointer PhysicalStorageBuffer %5 7912;CHECK: [[pt:%\w+]] = OpTypePointer PhysicalStorageBuffer {{%\w+}} 7913 %13 = OpTypeFunction %11 7914;CHECK: [[pt_fn:%\w+]] = OpTypeFunction [[pt]] 7915 %7 = OpTypeStruct %11 7916 %14 = OpTypePointer PushConstant %7 7917 %3 = OpVariable %14 PushConstant 7918 %15 = OpTypeInt 32 1 7919 %16 = OpConstant %15 0 7920 %17 = OpTypePointer PushConstant %11 7921 %18 = OpTypePointer Function %11 7922 %19 = OpTypeFloat 32 7923 %20 = OpTypeVector %19 4 7924 %21 = OpTypePointer Output %20 7925 %4 = OpVariable %21 Output 7926 %22 = OpConstant %19 1 7927 %23 = OpConstant %19 0 7928 %24 = OpConstantComposite %20 %22 %23 %22 %22 7929 %6 = OpFunction %11 None %13 7930;CHECK: [[fn:%\w+]] = OpFunction [[pt]] None [[pt_fn]] 7931 %27 = OpLabel 7932 %28 = OpAccessChain %17 %3 %16 7933 %29 = OpLoad %11 %28 7934 OpReturnValue %29 7935 OpFunctionEnd 7936 %2 = OpFunction %9 None %10 7937 %25 = OpLabel 7938 %8 = OpVariable %18 Function 7939 %26 = OpFunctionCall %11 %6 7940;CHECK: {{%\w+}} = OpFunctionCall [[pt]] [[fn]] 7941 OpStore %8 %26 7942 OpStore %4 %24 7943 OpReturn 7944 OpFunctionEnd 7945)"; 7946 7947 // For physical storage buffer support 7948 SetTargetEnv(SPV_ENV_VULKAN_1_2); 7949 SinglePassRunAndMatch<AggressiveDCEPass>(text, true); 7950} 7951 7952TEST_F(AggressiveDCETest, KeepBeginEndInvocationInterlock) { 7953 // OpBeginInvocationInterlockEXT and OpEndInvocationInterlockEXT delimit a 7954 // critical section. As such, they should be treated as if they have side 7955 // effects and should not be removed. 7956 const std::string test = 7957 R"(OpCapability Shader 7958OpCapability FragmentShaderSampleInterlockEXT 7959OpExtension "SPV_EXT_fragment_shader_interlock" 7960OpMemoryModel Logical GLSL450 7961OpEntryPoint Fragment %1 "main" %gl_FragCoord 7962OpExecutionMode %1 OriginUpperLeft 7963OpExecutionMode %1 SampleInterlockOrderedEXT 7964OpDecorate %gl_FragCoord BuiltIn FragCoord 7965%float = OpTypeFloat 32 7966%float_0 = OpConstant %float 0 7967%v4float = OpTypeVector %float 4 7968%_ptr_Input_v4float = OpTypePointer Input %v4float 7969%void = OpTypeVoid 7970%8 = OpTypeFunction %void 7971%bool = OpTypeBool 7972%gl_FragCoord = OpVariable %_ptr_Input_v4float Input 7973%1 = OpFunction %void None %8 7974%10 = OpLabel 7975%11 = OpLoad %v4float %gl_FragCoord 7976%12 = OpCompositeExtract %float %11 0 7977%13 = OpFOrdGreaterThan %bool %12 %float_0 7978OpSelectionMerge %14 None 7979OpBranchConditional %13 %15 %16 7980%15 = OpLabel 7981OpBeginInvocationInterlockEXT 7982OpBranch %14 7983%16 = OpLabel 7984OpBeginInvocationInterlockEXT 7985OpBranch %14 7986%14 = OpLabel 7987OpEndInvocationInterlockEXT 7988OpReturn 7989OpFunctionEnd 7990)"; 7991 7992 SinglePassRunAndCheck<AggressiveDCEPass>(test, test, true, true); 7993} 7994 7995} // namespace 7996} // namespace opt 7997} // namespace spvtools 7998