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 18 #include "test/opt/pass_fixture.h" 19 #include "test/opt/pass_utils.h" 20 21 namespace spvtools { 22 namespace opt { 23 namespace { 24 25 using DeadInsertElimTest = PassTest<::testing::Test>; 26 27 TEST_F(DeadInsertElimTest, InsertAfterInsertElim) { 28 // With two insertions to the same offset, the first is dead. 29 // 30 // Note: The SPIR-V assembly has had store/load elimination 31 // performed to allow the inserts and extracts to directly 32 // reference each other. 33 // 34 // #version 450 35 // 36 // layout (location=0) in float In0; 37 // layout (location=1) in float In1; 38 // layout (location=2) in vec2 In2; 39 // layout (location=0) out vec4 OutColor; 40 // 41 // void main() 42 // { 43 // vec2 v = In2; 44 // v.x = In0 + In1; // dead 45 // v.x = 0.0; 46 // OutColor = v.xyxy; 47 // } 48 49 const std::string before_predefs = 50 R"(OpCapability Shader 51 %1 = OpExtInstImport "GLSL.std.450" 52 OpMemoryModel Logical GLSL450 53 OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor 54 OpExecutionMode %main OriginUpperLeft 55 OpSource GLSL 450 56 OpName %main "main" 57 OpName %In2 "In2" 58 OpName %In0 "In0" 59 OpName %In1 "In1" 60 OpName %OutColor "OutColor" 61 OpName %_Globals_ "_Globals_" 62 OpMemberName %_Globals_ 0 "g_b" 63 OpMemberName %_Globals_ 1 "g_n" 64 OpName %_ "" 65 OpDecorate %In2 Location 2 66 OpDecorate %In0 Location 0 67 OpDecorate %In1 Location 1 68 OpDecorate %OutColor Location 0 69 OpMemberDecorate %_Globals_ 0 Offset 0 70 OpMemberDecorate %_Globals_ 1 Offset 4 71 OpDecorate %_Globals_ Block 72 OpDecorate %_ DescriptorSet 0 73 OpDecorate %_ Binding 0 74 %void = OpTypeVoid 75 %11 = OpTypeFunction %void 76 %float = OpTypeFloat 32 77 %v2float = OpTypeVector %float 2 78 %_ptr_Function_v2float = OpTypePointer Function %v2float 79 %_ptr_Input_v2float = OpTypePointer Input %v2float 80 %In2 = OpVariable %_ptr_Input_v2float Input 81 %_ptr_Input_float = OpTypePointer Input %float 82 %In0 = OpVariable %_ptr_Input_float Input 83 %In1 = OpVariable %_ptr_Input_float Input 84 %uint = OpTypeInt 32 0 85 %_ptr_Function_float = OpTypePointer Function %float 86 %float_0 = OpConstant %float 0 87 %v4float = OpTypeVector %float 4 88 %_ptr_Output_v4float = OpTypePointer Output %v4float 89 %OutColor = OpVariable %_ptr_Output_v4float Output 90 %int = OpTypeInt 32 1 91 %_Globals_ = OpTypeStruct %uint %int 92 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ 93 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform 94 )"; 95 96 const std::string after_predefs = 97 R"(OpCapability Shader 98 %1 = OpExtInstImport "GLSL.std.450" 99 OpMemoryModel Logical GLSL450 100 OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor 101 OpExecutionMode %main OriginUpperLeft 102 OpSource GLSL 450 103 OpName %main "main" 104 OpName %In2 "In2" 105 OpName %In0 "In0" 106 OpName %In1 "In1" 107 OpName %OutColor "OutColor" 108 OpName %_Globals_ "_Globals_" 109 OpMemberName %_Globals_ 0 "g_b" 110 OpMemberName %_Globals_ 1 "g_n" 111 OpName %_ "" 112 OpDecorate %In2 Location 2 113 OpDecorate %In0 Location 0 114 OpDecorate %In1 Location 1 115 OpDecorate %OutColor Location 0 116 OpMemberDecorate %_Globals_ 0 Offset 0 117 OpMemberDecorate %_Globals_ 1 Offset 4 118 OpDecorate %_Globals_ Block 119 OpDecorate %_ DescriptorSet 0 120 OpDecorate %_ Binding 0 121 %void = OpTypeVoid 122 %10 = OpTypeFunction %void 123 %float = OpTypeFloat 32 124 %v2float = OpTypeVector %float 2 125 %_ptr_Function_v2float = OpTypePointer Function %v2float 126 %_ptr_Input_v2float = OpTypePointer Input %v2float 127 %In2 = OpVariable %_ptr_Input_v2float Input 128 %_ptr_Input_float = OpTypePointer Input %float 129 %In0 = OpVariable %_ptr_Input_float Input 130 %In1 = OpVariable %_ptr_Input_float Input 131 %uint = OpTypeInt 32 0 132 %_ptr_Function_float = OpTypePointer Function %float 133 %float_0 = OpConstant %float 0 134 %v4float = OpTypeVector %float 4 135 %_ptr_Output_v4float = OpTypePointer Output %v4float 136 %OutColor = OpVariable %_ptr_Output_v4float Output 137 %int = OpTypeInt 32 1 138 %_Globals_ = OpTypeStruct %uint %int 139 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ 140 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform 141 )"; 142 143 const std::string before = 144 R"(%main = OpFunction %void None %11 145 %25 = OpLabel 146 %26 = OpLoad %v2float %In2 147 %27 = OpLoad %float %In0 148 %28 = OpLoad %float %In1 149 %29 = OpFAdd %float %27 %28 150 %35 = OpCompositeInsert %v2float %29 %26 0 151 %37 = OpCompositeInsert %v2float %float_0 %35 0 152 %33 = OpVectorShuffle %v4float %37 %37 0 1 0 1 153 OpStore %OutColor %33 154 OpReturn 155 OpFunctionEnd 156 )"; 157 158 const std::string after = 159 R"(%main = OpFunction %void None %10 160 %23 = OpLabel 161 %24 = OpLoad %v2float %In2 162 %29 = OpCompositeInsert %v2float %float_0 %24 0 163 %30 = OpVectorShuffle %v4float %29 %29 0 1 0 1 164 OpStore %OutColor %30 165 OpReturn 166 OpFunctionEnd 167 )"; 168 169 SinglePassRunAndCheck<DeadInsertElimPass>(before_predefs + before, 170 after_predefs + after, true, true); 171 } 172 173 TEST_F(DeadInsertElimTest, DeadInsertInChainWithPhi) { 174 // Dead insert eliminated with phi in insertion chain. 175 // 176 // Note: The SPIR-V assembly has had store/load elimination 177 // performed to allow the inserts and extracts to directly 178 // reference each other. 179 // 180 // #version 450 181 // 182 // layout (location=0) in vec4 In0; 183 // layout (location=1) in float In1; 184 // layout (location=2) in float In2; 185 // layout (location=0) out vec4 OutColor; 186 // 187 // layout(std140, binding = 0 ) uniform _Globals_ 188 // { 189 // bool g_b; 190 // }; 191 // 192 // void main() 193 // { 194 // vec4 v = In0; 195 // v.z = In1 + In2; 196 // if (g_b) v.w = 1.0; 197 // OutColor = vec4(v.x,v.y,0.0,v.w); 198 // } 199 200 const std::string before_predefs = 201 R"(OpCapability Shader 202 %1 = OpExtInstImport "GLSL.std.450" 203 OpMemoryModel Logical GLSL450 204 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor 205 OpExecutionMode %main OriginUpperLeft 206 OpSource GLSL 450 207 OpName %main "main" 208 OpName %In0 "In0" 209 OpName %In1 "In1" 210 OpName %In2 "In2" 211 OpName %_Globals_ "_Globals_" 212 OpMemberName %_Globals_ 0 "g_b" 213 OpName %_ "" 214 OpName %OutColor "OutColor" 215 OpDecorate %In0 Location 0 216 OpDecorate %In1 Location 1 217 OpDecorate %In2 Location 2 218 OpMemberDecorate %_Globals_ 0 Offset 0 219 OpDecorate %_Globals_ Block 220 OpDecorate %_ DescriptorSet 0 221 OpDecorate %_ Binding 0 222 OpDecorate %OutColor Location 0 223 %void = OpTypeVoid 224 %11 = OpTypeFunction %void 225 %float = OpTypeFloat 32 226 %v4float = OpTypeVector %float 4 227 %_ptr_Function_v4float = OpTypePointer Function %v4float 228 %_ptr_Input_v4float = OpTypePointer Input %v4float 229 %In0 = OpVariable %_ptr_Input_v4float Input 230 %_ptr_Input_float = OpTypePointer Input %float 231 %In1 = OpVariable %_ptr_Input_float Input 232 %In2 = OpVariable %_ptr_Input_float Input 233 %uint = OpTypeInt 32 0 234 %_ptr_Function_float = OpTypePointer Function %float 235 %_Globals_ = OpTypeStruct %uint 236 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ 237 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform 238 %int = OpTypeInt 32 1 239 %int_0 = OpConstant %int 0 240 %_ptr_Uniform_uint = OpTypePointer Uniform %uint 241 %bool = OpTypeBool 242 %uint_0 = OpConstant %uint 0 243 %float_1 = OpConstant %float 1 244 %_ptr_Output_v4float = OpTypePointer Output %v4float 245 %OutColor = OpVariable %_ptr_Output_v4float Output 246 %float_0 = OpConstant %float 0 247 )"; 248 249 const std::string after_predefs = 250 R"(OpCapability Shader 251 %1 = OpExtInstImport "GLSL.std.450" 252 OpMemoryModel Logical GLSL450 253 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor 254 OpExecutionMode %main OriginUpperLeft 255 OpSource GLSL 450 256 OpName %main "main" 257 OpName %In0 "In0" 258 OpName %In1 "In1" 259 OpName %In2 "In2" 260 OpName %_Globals_ "_Globals_" 261 OpMemberName %_Globals_ 0 "g_b" 262 OpName %_ "" 263 OpName %OutColor "OutColor" 264 OpDecorate %In0 Location 0 265 OpDecorate %In1 Location 1 266 OpDecorate %In2 Location 2 267 OpMemberDecorate %_Globals_ 0 Offset 0 268 OpDecorate %_Globals_ Block 269 OpDecorate %_ DescriptorSet 0 270 OpDecorate %_ Binding 0 271 OpDecorate %OutColor Location 0 272 %void = OpTypeVoid 273 %10 = OpTypeFunction %void 274 %float = OpTypeFloat 32 275 %v4float = OpTypeVector %float 4 276 %_ptr_Function_v4float = OpTypePointer Function %v4float 277 %_ptr_Input_v4float = OpTypePointer Input %v4float 278 %In0 = OpVariable %_ptr_Input_v4float Input 279 %_ptr_Input_float = OpTypePointer Input %float 280 %In1 = OpVariable %_ptr_Input_float Input 281 %In2 = OpVariable %_ptr_Input_float Input 282 %uint = OpTypeInt 32 0 283 %_ptr_Function_float = OpTypePointer Function %float 284 %_Globals_ = OpTypeStruct %uint 285 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ 286 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform 287 %int = OpTypeInt 32 1 288 %int_0 = OpConstant %int 0 289 %_ptr_Uniform_uint = OpTypePointer Uniform %uint 290 %bool = OpTypeBool 291 %uint_0 = OpConstant %uint 0 292 %float_1 = OpConstant %float 1 293 %_ptr_Output_v4float = OpTypePointer Output %v4float 294 %OutColor = OpVariable %_ptr_Output_v4float Output 295 %float_0 = OpConstant %float 0 296 )"; 297 298 const std::string before = 299 R"(%main = OpFunction %void None %11 300 %31 = OpLabel 301 %32 = OpLoad %v4float %In0 302 %33 = OpLoad %float %In1 303 %34 = OpLoad %float %In2 304 %35 = OpFAdd %float %33 %34 305 %51 = OpCompositeInsert %v4float %35 %32 2 306 %37 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 307 %38 = OpLoad %uint %37 308 %39 = OpINotEqual %bool %38 %uint_0 309 OpSelectionMerge %40 None 310 OpBranchConditional %39 %41 %40 311 %41 = OpLabel 312 %53 = OpCompositeInsert %v4float %float_1 %51 3 313 OpBranch %40 314 %40 = OpLabel 315 %60 = OpPhi %v4float %51 %31 %53 %41 316 %55 = OpCompositeExtract %float %60 0 317 %57 = OpCompositeExtract %float %60 1 318 %59 = OpCompositeExtract %float %60 3 319 %49 = OpCompositeConstruct %v4float %55 %57 %float_0 %59 320 OpStore %OutColor %49 321 OpReturn 322 OpFunctionEnd 323 )"; 324 325 const std::string after = 326 R"(%main = OpFunction %void None %10 327 %27 = OpLabel 328 %28 = OpLoad %v4float %In0 329 %33 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 330 %34 = OpLoad %uint %33 331 %35 = OpINotEqual %bool %34 %uint_0 332 OpSelectionMerge %36 None 333 OpBranchConditional %35 %37 %36 334 %37 = OpLabel 335 %38 = OpCompositeInsert %v4float %float_1 %28 3 336 OpBranch %36 337 %36 = OpLabel 338 %39 = OpPhi %v4float %28 %27 %38 %37 339 %40 = OpCompositeExtract %float %39 0 340 %41 = OpCompositeExtract %float %39 1 341 %42 = OpCompositeExtract %float %39 3 342 %43 = OpCompositeConstruct %v4float %40 %41 %float_0 %42 343 OpStore %OutColor %43 344 OpReturn 345 OpFunctionEnd 346 )"; 347 348 SinglePassRunAndCheck<DeadInsertElimPass>(before_predefs + before, 349 after_predefs + after, true, true); 350 } 351 352 TEST_F(DeadInsertElimTest, DeadInsertTwoPasses) { 353 // Dead insert which requires two passes to eliminate 354 // 355 // Note: The SPIR-V assembly has had store/load elimination 356 // performed to allow the inserts and extracts to directly 357 // reference each other. 358 // 359 // #version 450 360 // 361 // layout (location=0) in vec4 In0; 362 // layout (location=1) in float In1; 363 // layout (location=2) in float In2; 364 // layout (location=0) out vec4 OutColor; 365 // 366 // layout(std140, binding = 0 ) uniform _Globals_ 367 // { 368 // bool g_b; 369 // bool g_b2; 370 // }; 371 // 372 // void main() 373 // { 374 // vec4 v1, v2; 375 // v1 = In0; 376 // v1.y = In1 + In2; // dead, second pass 377 // if (g_b) v1.x = 1.0; 378 // v2.x = v1.x; 379 // v2.y = v1.y; // dead, first pass 380 // if (g_b2) v2.x = 0.0; 381 // OutColor = vec4(v2.x,v2.x,0.0,1.0); 382 // } 383 384 const std::string before_predefs = 385 R"(OpCapability Shader 386 %1 = OpExtInstImport "GLSL.std.450" 387 OpMemoryModel Logical GLSL450 388 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor 389 OpExecutionMode %main OriginUpperLeft 390 OpSource GLSL 450 391 OpName %main "main" 392 OpName %In0 "In0" 393 OpName %In1 "In1" 394 OpName %In2 "In2" 395 OpName %_Globals_ "_Globals_" 396 OpMemberName %_Globals_ 0 "g_b" 397 OpMemberName %_Globals_ 1 "g_b2" 398 OpName %_ "" 399 OpName %OutColor "OutColor" 400 OpDecorate %In0 Location 0 401 OpDecorate %In1 Location 1 402 OpDecorate %In2 Location 2 403 OpMemberDecorate %_Globals_ 0 Offset 0 404 OpMemberDecorate %_Globals_ 1 Offset 4 405 OpDecorate %_Globals_ Block 406 OpDecorate %_ DescriptorSet 0 407 OpDecorate %_ Binding 0 408 OpDecorate %OutColor Location 0 409 %void = OpTypeVoid 410 %10 = OpTypeFunction %void 411 %float = OpTypeFloat 32 412 %v4float = OpTypeVector %float 4 413 %_ptr_Function_v4float = OpTypePointer Function %v4float 414 %_ptr_Input_v4float = OpTypePointer Input %v4float 415 %In0 = OpVariable %_ptr_Input_v4float Input 416 %_ptr_Input_float = OpTypePointer Input %float 417 %In1 = OpVariable %_ptr_Input_float Input 418 %In2 = OpVariable %_ptr_Input_float Input 419 %uint = OpTypeInt 32 0 420 %_Globals_ = OpTypeStruct %uint %uint 421 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ 422 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform 423 %int = OpTypeInt 32 1 424 %int_0 = OpConstant %int 0 425 %_ptr_Uniform_uint = OpTypePointer Uniform %uint 426 %bool = OpTypeBool 427 %uint_0 = OpConstant %uint 0 428 %float_1 = OpConstant %float 1 429 %int_1 = OpConstant %int 1 430 %float_0 = OpConstant %float 0 431 %_ptr_Output_v4float = OpTypePointer Output %v4float 432 %OutColor = OpVariable %_ptr_Output_v4float Output 433 %27 = OpUndef %v4float 434 )"; 435 436 const std::string after_predefs = 437 R"(OpCapability Shader 438 %1 = OpExtInstImport "GLSL.std.450" 439 OpMemoryModel Logical GLSL450 440 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor 441 OpExecutionMode %main OriginUpperLeft 442 OpSource GLSL 450 443 OpName %main "main" 444 OpName %In0 "In0" 445 OpName %In1 "In1" 446 OpName %In2 "In2" 447 OpName %_Globals_ "_Globals_" 448 OpMemberName %_Globals_ 0 "g_b" 449 OpMemberName %_Globals_ 1 "g_b2" 450 OpName %_ "" 451 OpName %OutColor "OutColor" 452 OpDecorate %In0 Location 0 453 OpDecorate %In1 Location 1 454 OpDecorate %In2 Location 2 455 OpMemberDecorate %_Globals_ 0 Offset 0 456 OpMemberDecorate %_Globals_ 1 Offset 4 457 OpDecorate %_Globals_ Block 458 OpDecorate %_ DescriptorSet 0 459 OpDecorate %_ Binding 0 460 OpDecorate %OutColor Location 0 461 %void = OpTypeVoid 462 %10 = OpTypeFunction %void 463 %float = OpTypeFloat 32 464 %v4float = OpTypeVector %float 4 465 %_ptr_Function_v4float = OpTypePointer Function %v4float 466 %_ptr_Input_v4float = OpTypePointer Input %v4float 467 %In0 = OpVariable %_ptr_Input_v4float Input 468 %_ptr_Input_float = OpTypePointer Input %float 469 %In1 = OpVariable %_ptr_Input_float Input 470 %In2 = OpVariable %_ptr_Input_float Input 471 %uint = OpTypeInt 32 0 472 %_Globals_ = OpTypeStruct %uint %uint 473 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_ 474 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform 475 %int = OpTypeInt 32 1 476 %int_0 = OpConstant %int 0 477 %_ptr_Uniform_uint = OpTypePointer Uniform %uint 478 %bool = OpTypeBool 479 %uint_0 = OpConstant %uint 0 480 %float_1 = OpConstant %float 1 481 %int_1 = OpConstant %int 1 482 %float_0 = OpConstant %float 0 483 %_ptr_Output_v4float = OpTypePointer Output %v4float 484 %OutColor = OpVariable %_ptr_Output_v4float Output 485 %27 = OpUndef %v4float 486 )"; 487 488 const std::string before = 489 R"(%main = OpFunction %void None %10 490 %28 = OpLabel 491 %29 = OpLoad %v4float %In0 492 %30 = OpLoad %float %In1 493 %31 = OpLoad %float %In2 494 %32 = OpFAdd %float %30 %31 495 %33 = OpCompositeInsert %v4float %32 %29 1 496 %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 497 %35 = OpLoad %uint %34 498 %36 = OpINotEqual %bool %35 %uint_0 499 OpSelectionMerge %37 None 500 OpBranchConditional %36 %38 %37 501 %38 = OpLabel 502 %39 = OpCompositeInsert %v4float %float_1 %33 0 503 OpBranch %37 504 %37 = OpLabel 505 %40 = OpPhi %v4float %33 %28 %39 %38 506 %41 = OpCompositeExtract %float %40 0 507 %42 = OpCompositeInsert %v4float %41 %27 0 508 %43 = OpCompositeExtract %float %40 1 509 %44 = OpCompositeInsert %v4float %43 %42 1 510 %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1 511 %46 = OpLoad %uint %45 512 %47 = OpINotEqual %bool %46 %uint_0 513 OpSelectionMerge %48 None 514 OpBranchConditional %47 %49 %48 515 %49 = OpLabel 516 %50 = OpCompositeInsert %v4float %float_0 %44 0 517 OpBranch %48 518 %48 = OpLabel 519 %51 = OpPhi %v4float %44 %37 %50 %49 520 %52 = OpCompositeExtract %float %51 0 521 %53 = OpCompositeExtract %float %51 0 522 %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1 523 OpStore %OutColor %54 524 OpReturn 525 OpFunctionEnd 526 )"; 527 528 const std::string after = 529 R"(%main = OpFunction %void None %10 530 %28 = OpLabel 531 %29 = OpLoad %v4float %In0 532 %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0 533 %35 = OpLoad %uint %34 534 %36 = OpINotEqual %bool %35 %uint_0 535 OpSelectionMerge %37 None 536 OpBranchConditional %36 %38 %37 537 %38 = OpLabel 538 %39 = OpCompositeInsert %v4float %float_1 %29 0 539 OpBranch %37 540 %37 = OpLabel 541 %40 = OpPhi %v4float %29 %28 %39 %38 542 %41 = OpCompositeExtract %float %40 0 543 %42 = OpCompositeInsert %v4float %41 %27 0 544 %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1 545 %46 = OpLoad %uint %45 546 %47 = OpINotEqual %bool %46 %uint_0 547 OpSelectionMerge %48 None 548 OpBranchConditional %47 %49 %48 549 %49 = OpLabel 550 %50 = OpCompositeInsert %v4float %float_0 %42 0 551 OpBranch %48 552 %48 = OpLabel 553 %51 = OpPhi %v4float %42 %37 %50 %49 554 %52 = OpCompositeExtract %float %51 0 555 %53 = OpCompositeExtract %float %51 0 556 %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1 557 OpStore %OutColor %54 558 OpReturn 559 OpFunctionEnd 560 )"; 561 562 SinglePassRunAndCheck<DeadInsertElimPass>(before_predefs + before, 563 after_predefs + after, true, true); 564 } 565 566 // TODO(greg-lunarg): Add tests to verify handling of these cases: 567 // 568 569 } // namespace 570 } // namespace opt 571 } // namespace spvtools 572