Home | History | Annotate | Download | only in opt
      1 // Copyright (c) 2018 Google LLC
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include <string>
     16 
     17 #include "test/opt/pass_fixture.h"
     18 #include "test/opt/pass_utils.h"
     19 
     20 namespace spvtools {
     21 namespace opt {
     22 namespace {
     23 
     24 using VectorDCETest = PassTest<::testing::Test>;
     25 
     26 TEST_F(VectorDCETest, InsertAfterInsertElim) {
     27   // With two insertions to the same offset, the first is dead.
     28   //
     29   // Note: The SPIR-V assembly has had store/load elimination
     30   // performed to allow the inserts and extracts to directly
     31   // reference each other.
     32   //
     33   // #version 450
     34   //
     35   // layout (location=0) in float In0;
     36   // layout (location=1) in float In1;
     37   // layout (location=2) in vec2 In2;
     38   // layout (location=0) out vec4 OutColor;
     39   //
     40   // void main()
     41   // {
     42   //     vec2 v = In2;
     43   //     v.x = In0 + In1; // dead
     44   //     v.x = 0.0;
     45   //     OutColor = v.xyxy;
     46   // }
     47 
     48   const std::string before_predefs =
     49       R"(OpCapability Shader
     50 %1 = OpExtInstImport "GLSL.std.450"
     51 OpMemoryModel Logical GLSL450
     52 OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
     53 OpExecutionMode %main OriginUpperLeft
     54 OpSource GLSL 450
     55 OpName %main "main"
     56 OpName %In2 "In2"
     57 OpName %In0 "In0"
     58 OpName %In1 "In1"
     59 OpName %OutColor "OutColor"
     60 OpName %_Globals_ "_Globals_"
     61 OpMemberName %_Globals_ 0 "g_b"
     62 OpMemberName %_Globals_ 1 "g_n"
     63 OpName %_ ""
     64 OpDecorate %In2 Location 2
     65 OpDecorate %In0 Location 0
     66 OpDecorate %In1 Location 1
     67 OpDecorate %OutColor Location 0
     68 OpMemberDecorate %_Globals_ 0 Offset 0
     69 OpMemberDecorate %_Globals_ 1 Offset 4
     70 OpDecorate %_Globals_ Block
     71 OpDecorate %_ DescriptorSet 0
     72 OpDecorate %_ Binding 0
     73 %void = OpTypeVoid
     74 %11 = OpTypeFunction %void
     75 %float = OpTypeFloat 32
     76 %v2float = OpTypeVector %float 2
     77 %_ptr_Function_v2float = OpTypePointer Function %v2float
     78 %_ptr_Input_v2float = OpTypePointer Input %v2float
     79 %In2 = OpVariable %_ptr_Input_v2float Input
     80 %_ptr_Input_float = OpTypePointer Input %float
     81 %In0 = OpVariable %_ptr_Input_float Input
     82 %In1 = OpVariable %_ptr_Input_float Input
     83 %uint = OpTypeInt 32 0
     84 %_ptr_Function_float = OpTypePointer Function %float
     85 %float_0 = OpConstant %float 0
     86 %v4float = OpTypeVector %float 4
     87 %_ptr_Output_v4float = OpTypePointer Output %v4float
     88 %OutColor = OpVariable %_ptr_Output_v4float Output
     89 %int = OpTypeInt 32 1
     90 %_Globals_ = OpTypeStruct %uint %int
     91 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
     92 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
     93 )";
     94 
     95   const std::string after_predefs =
     96       R"(OpCapability Shader
     97 %1 = OpExtInstImport "GLSL.std.450"
     98 OpMemoryModel Logical GLSL450
     99 OpEntryPoint Fragment %main "main" %In2 %In0 %In1 %OutColor
    100 OpExecutionMode %main OriginUpperLeft
    101 OpSource GLSL 450
    102 OpName %main "main"
    103 OpName %In2 "In2"
    104 OpName %In0 "In0"
    105 OpName %In1 "In1"
    106 OpName %OutColor "OutColor"
    107 OpName %_Globals_ "_Globals_"
    108 OpMemberName %_Globals_ 0 "g_b"
    109 OpMemberName %_Globals_ 1 "g_n"
    110 OpName %_ ""
    111 OpDecorate %In2 Location 2
    112 OpDecorate %In0 Location 0
    113 OpDecorate %In1 Location 1
    114 OpDecorate %OutColor Location 0
    115 OpMemberDecorate %_Globals_ 0 Offset 0
    116 OpMemberDecorate %_Globals_ 1 Offset 4
    117 OpDecorate %_Globals_ Block
    118 OpDecorate %_ DescriptorSet 0
    119 OpDecorate %_ Binding 0
    120 %void = OpTypeVoid
    121 %10 = OpTypeFunction %void
    122 %float = OpTypeFloat 32
    123 %v2float = OpTypeVector %float 2
    124 %_ptr_Function_v2float = OpTypePointer Function %v2float
    125 %_ptr_Input_v2float = OpTypePointer Input %v2float
    126 %In2 = OpVariable %_ptr_Input_v2float Input
    127 %_ptr_Input_float = OpTypePointer Input %float
    128 %In0 = OpVariable %_ptr_Input_float Input
    129 %In1 = OpVariable %_ptr_Input_float Input
    130 %uint = OpTypeInt 32 0
    131 %_ptr_Function_float = OpTypePointer Function %float
    132 %float_0 = OpConstant %float 0
    133 %v4float = OpTypeVector %float 4
    134 %_ptr_Output_v4float = OpTypePointer Output %v4float
    135 %OutColor = OpVariable %_ptr_Output_v4float Output
    136 %int = OpTypeInt 32 1
    137 %_Globals_ = OpTypeStruct %uint %int
    138 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
    139 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
    140 )";
    141 
    142   const std::string before =
    143       R"(%main = OpFunction %void None %11
    144 %25 = OpLabel
    145 %26 = OpLoad %v2float %In2
    146 %27 = OpLoad %float %In0
    147 %28 = OpLoad %float %In1
    148 %29 = OpFAdd %float %27 %28
    149 %35 = OpCompositeInsert %v2float %29 %26 0
    150 %37 = OpCompositeInsert %v2float %float_0 %35 0
    151 %33 = OpVectorShuffle %v4float %37 %37 0 1 0 1
    152 OpStore %OutColor %33
    153 OpReturn
    154 OpFunctionEnd
    155 )";
    156 
    157   const std::string after =
    158       R"(%main = OpFunction %void None %10
    159 %23 = OpLabel
    160 %24 = OpLoad %v2float %In2
    161 %25 = OpLoad %float %In0
    162 %26 = OpLoad %float %In1
    163 %27 = OpFAdd %float %25 %26
    164 %28 = OpCompositeInsert %v2float %27 %24 0
    165 %29 = OpCompositeInsert %v2float %float_0 %24 0
    166 %30 = OpVectorShuffle %v4float %29 %29 0 1 0 1
    167 OpStore %OutColor %30
    168 OpReturn
    169 OpFunctionEnd
    170 )";
    171 
    172   SinglePassRunAndCheck<VectorDCE>(before_predefs + before,
    173                                    after_predefs + after, true, true);
    174 }
    175 
    176 TEST_F(VectorDCETest, DeadInsertInChainWithPhi) {
    177   // Dead insert eliminated with phi in insertion chain.
    178   //
    179   // Note: The SPIR-V assembly has had store/load elimination
    180   // performed to allow the inserts and extracts to directly
    181   // reference each other.
    182   //
    183   // #version 450
    184   //
    185   // layout (location=0) in vec4 In0;
    186   // layout (location=1) in float In1;
    187   // layout (location=2) in float In2;
    188   // layout (location=0) out vec4 OutColor;
    189   //
    190   // layout(std140, binding = 0 ) uniform _Globals_
    191   // {
    192   //     bool g_b;
    193   // };
    194   //
    195   // void main()
    196   // {
    197   //     vec4 v = In0;
    198   //     v.z = In1 + In2;
    199   //     if (g_b) v.w = 1.0;
    200   //     OutColor = vec4(v.x,v.y,0.0,v.w);
    201   // }
    202 
    203   const std::string before_predefs =
    204       R"(OpCapability Shader
    205 %1 = OpExtInstImport "GLSL.std.450"
    206 OpMemoryModel Logical GLSL450
    207 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
    208 OpExecutionMode %main OriginUpperLeft
    209 OpSource GLSL 450
    210 OpName %main "main"
    211 OpName %In0 "In0"
    212 OpName %In1 "In1"
    213 OpName %In2 "In2"
    214 OpName %_Globals_ "_Globals_"
    215 OpMemberName %_Globals_ 0 "g_b"
    216 OpName %_ ""
    217 OpName %OutColor "OutColor"
    218 OpDecorate %In0 Location 0
    219 OpDecorate %In1 Location 1
    220 OpDecorate %In2 Location 2
    221 OpMemberDecorate %_Globals_ 0 Offset 0
    222 OpDecorate %_Globals_ Block
    223 OpDecorate %_ DescriptorSet 0
    224 OpDecorate %_ Binding 0
    225 OpDecorate %OutColor Location 0
    226 %void = OpTypeVoid
    227 %11 = OpTypeFunction %void
    228 %float = OpTypeFloat 32
    229 %v4float = OpTypeVector %float 4
    230 %_ptr_Function_v4float = OpTypePointer Function %v4float
    231 %_ptr_Input_v4float = OpTypePointer Input %v4float
    232 %In0 = OpVariable %_ptr_Input_v4float Input
    233 %_ptr_Input_float = OpTypePointer Input %float
    234 %In1 = OpVariable %_ptr_Input_float Input
    235 %In2 = OpVariable %_ptr_Input_float Input
    236 %uint = OpTypeInt 32 0
    237 %_ptr_Function_float = OpTypePointer Function %float
    238 %_Globals_ = OpTypeStruct %uint
    239 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
    240 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
    241 %int = OpTypeInt 32 1
    242 %int_0 = OpConstant %int 0
    243 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
    244 %bool = OpTypeBool
    245 %uint_0 = OpConstant %uint 0
    246 %float_1 = OpConstant %float 1
    247 %_ptr_Output_v4float = OpTypePointer Output %v4float
    248 %OutColor = OpVariable %_ptr_Output_v4float Output
    249 %float_0 = OpConstant %float 0
    250 )";
    251 
    252   const std::string after_predefs =
    253       R"(OpCapability Shader
    254 %1 = OpExtInstImport "GLSL.std.450"
    255 OpMemoryModel Logical GLSL450
    256 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
    257 OpExecutionMode %main OriginUpperLeft
    258 OpSource GLSL 450
    259 OpName %main "main"
    260 OpName %In0 "In0"
    261 OpName %In1 "In1"
    262 OpName %In2 "In2"
    263 OpName %_Globals_ "_Globals_"
    264 OpMemberName %_Globals_ 0 "g_b"
    265 OpName %_ ""
    266 OpName %OutColor "OutColor"
    267 OpDecorate %In0 Location 0
    268 OpDecorate %In1 Location 1
    269 OpDecorate %In2 Location 2
    270 OpMemberDecorate %_Globals_ 0 Offset 0
    271 OpDecorate %_Globals_ Block
    272 OpDecorate %_ DescriptorSet 0
    273 OpDecorate %_ Binding 0
    274 OpDecorate %OutColor Location 0
    275 %void = OpTypeVoid
    276 %10 = OpTypeFunction %void
    277 %float = OpTypeFloat 32
    278 %v4float = OpTypeVector %float 4
    279 %_ptr_Function_v4float = OpTypePointer Function %v4float
    280 %_ptr_Input_v4float = OpTypePointer Input %v4float
    281 %In0 = OpVariable %_ptr_Input_v4float Input
    282 %_ptr_Input_float = OpTypePointer Input %float
    283 %In1 = OpVariable %_ptr_Input_float Input
    284 %In2 = OpVariable %_ptr_Input_float Input
    285 %uint = OpTypeInt 32 0
    286 %_ptr_Function_float = OpTypePointer Function %float
    287 %_Globals_ = OpTypeStruct %uint
    288 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
    289 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
    290 %int = OpTypeInt 32 1
    291 %int_0 = OpConstant %int 0
    292 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
    293 %bool = OpTypeBool
    294 %uint_0 = OpConstant %uint 0
    295 %float_1 = OpConstant %float 1
    296 %_ptr_Output_v4float = OpTypePointer Output %v4float
    297 %OutColor = OpVariable %_ptr_Output_v4float Output
    298 %float_0 = OpConstant %float 0
    299 )";
    300 
    301   const std::string before =
    302       R"(%main = OpFunction %void None %11
    303 %31 = OpLabel
    304 %32 = OpLoad %v4float %In0
    305 %33 = OpLoad %float %In1
    306 %34 = OpLoad %float %In2
    307 %35 = OpFAdd %float %33 %34
    308 %51 = OpCompositeInsert %v4float %35 %32 2
    309 %37 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
    310 %38 = OpLoad %uint %37
    311 %39 = OpINotEqual %bool %38 %uint_0
    312 OpSelectionMerge %40 None
    313 OpBranchConditional %39 %41 %40
    314 %41 = OpLabel
    315 %53 = OpCompositeInsert %v4float %float_1 %51 3
    316 OpBranch %40
    317 %40 = OpLabel
    318 %60 = OpPhi %v4float %51 %31 %53 %41
    319 %55 = OpCompositeExtract %float %60 0
    320 %57 = OpCompositeExtract %float %60 1
    321 %59 = OpCompositeExtract %float %60 3
    322 %49 = OpCompositeConstruct %v4float %55 %57 %float_0 %59
    323 OpStore %OutColor %49
    324 OpReturn
    325 OpFunctionEnd
    326 )";
    327 
    328   const std::string after =
    329       R"(%main = OpFunction %void None %10
    330 %27 = OpLabel
    331 %28 = OpLoad %v4float %In0
    332 %29 = OpLoad %float %In1
    333 %30 = OpLoad %float %In2
    334 %31 = OpFAdd %float %29 %30
    335 %32 = OpCompositeInsert %v4float %31 %28 2
    336 %33 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
    337 %34 = OpLoad %uint %33
    338 %35 = OpINotEqual %bool %34 %uint_0
    339 OpSelectionMerge %36 None
    340 OpBranchConditional %35 %37 %36
    341 %37 = OpLabel
    342 %38 = OpCompositeInsert %v4float %float_1 %28 3
    343 OpBranch %36
    344 %36 = OpLabel
    345 %39 = OpPhi %v4float %28 %27 %38 %37
    346 %40 = OpCompositeExtract %float %39 0
    347 %41 = OpCompositeExtract %float %39 1
    348 %42 = OpCompositeExtract %float %39 3
    349 %43 = OpCompositeConstruct %v4float %40 %41 %float_0 %42
    350 OpStore %OutColor %43
    351 OpReturn
    352 OpFunctionEnd
    353 )";
    354 
    355   SinglePassRunAndCheck<VectorDCE>(before_predefs + before,
    356                                    after_predefs + after, true, true);
    357 }
    358 
    359 TEST_F(VectorDCETest, DeadInsertWithScalars) {
    360   // Dead insert which requires two passes to eliminate
    361   //
    362   // Note: The SPIR-V assembly has had store/load elimination
    363   // performed to allow the inserts and extracts to directly
    364   // reference each other.
    365   //
    366   // #version 450
    367   //
    368   // layout (location=0) in vec4 In0;
    369   // layout (location=1) in float In1;
    370   // layout (location=2) in float In2;
    371   // layout (location=0) out vec4 OutColor;
    372   //
    373   // layout(std140, binding = 0 ) uniform _Globals_
    374   // {
    375   //     bool g_b;
    376   //     bool g_b2;
    377   // };
    378   //
    379   // void main()
    380   // {
    381   //     vec4 v1, v2;
    382   //     v1 = In0;
    383   //     v1.y = In1 + In2; // dead, second pass
    384   //     if (g_b) v1.x = 1.0;
    385   //     v2.x = v1.x;
    386   //     v2.y = v1.y; // dead, first pass
    387   //     if (g_b2) v2.x = 0.0;
    388   //     OutColor = vec4(v2.x,v2.x,0.0,1.0);
    389   // }
    390 
    391   const std::string before_predefs =
    392       R"(OpCapability Shader
    393 %1 = OpExtInstImport "GLSL.std.450"
    394 OpMemoryModel Logical GLSL450
    395 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
    396 OpExecutionMode %main OriginUpperLeft
    397 OpSource GLSL 450
    398 OpName %main "main"
    399 OpName %In0 "In0"
    400 OpName %In1 "In1"
    401 OpName %In2 "In2"
    402 OpName %_Globals_ "_Globals_"
    403 OpMemberName %_Globals_ 0 "g_b"
    404 OpMemberName %_Globals_ 1 "g_b2"
    405 OpName %_ ""
    406 OpName %OutColor "OutColor"
    407 OpDecorate %In0 Location 0
    408 OpDecorate %In1 Location 1
    409 OpDecorate %In2 Location 2
    410 OpMemberDecorate %_Globals_ 0 Offset 0
    411 OpMemberDecorate %_Globals_ 1 Offset 4
    412 OpDecorate %_Globals_ Block
    413 OpDecorate %_ DescriptorSet 0
    414 OpDecorate %_ Binding 0
    415 OpDecorate %OutColor Location 0
    416 %void = OpTypeVoid
    417 %10 = OpTypeFunction %void
    418 %float = OpTypeFloat 32
    419 %v4float = OpTypeVector %float 4
    420 %_ptr_Function_v4float = OpTypePointer Function %v4float
    421 %_ptr_Input_v4float = OpTypePointer Input %v4float
    422 %In0 = OpVariable %_ptr_Input_v4float Input
    423 %_ptr_Input_float = OpTypePointer Input %float
    424 %In1 = OpVariable %_ptr_Input_float Input
    425 %In2 = OpVariable %_ptr_Input_float Input
    426 %uint = OpTypeInt 32 0
    427 %_Globals_ = OpTypeStruct %uint %uint
    428 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
    429 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
    430 %int = OpTypeInt 32 1
    431 %int_0 = OpConstant %int 0
    432 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
    433 %bool = OpTypeBool
    434 %uint_0 = OpConstant %uint 0
    435 %float_1 = OpConstant %float 1
    436 %int_1 = OpConstant %int 1
    437 %float_0 = OpConstant %float 0
    438 %_ptr_Output_v4float = OpTypePointer Output %v4float
    439 %OutColor = OpVariable %_ptr_Output_v4float Output
    440 %27 = OpUndef %v4float
    441 )";
    442 
    443   const std::string after_predefs =
    444       R"(OpCapability Shader
    445 %1 = OpExtInstImport "GLSL.std.450"
    446 OpMemoryModel Logical GLSL450
    447 OpEntryPoint Fragment %main "main" %In0 %In1 %In2 %OutColor
    448 OpExecutionMode %main OriginUpperLeft
    449 OpSource GLSL 450
    450 OpName %main "main"
    451 OpName %In0 "In0"
    452 OpName %In1 "In1"
    453 OpName %In2 "In2"
    454 OpName %_Globals_ "_Globals_"
    455 OpMemberName %_Globals_ 0 "g_b"
    456 OpMemberName %_Globals_ 1 "g_b2"
    457 OpName %_ ""
    458 OpName %OutColor "OutColor"
    459 OpDecorate %In0 Location 0
    460 OpDecorate %In1 Location 1
    461 OpDecorate %In2 Location 2
    462 OpMemberDecorate %_Globals_ 0 Offset 0
    463 OpMemberDecorate %_Globals_ 1 Offset 4
    464 OpDecorate %_Globals_ Block
    465 OpDecorate %_ DescriptorSet 0
    466 OpDecorate %_ Binding 0
    467 OpDecorate %OutColor Location 0
    468 %void = OpTypeVoid
    469 %10 = OpTypeFunction %void
    470 %float = OpTypeFloat 32
    471 %v4float = OpTypeVector %float 4
    472 %_ptr_Function_v4float = OpTypePointer Function %v4float
    473 %_ptr_Input_v4float = OpTypePointer Input %v4float
    474 %In0 = OpVariable %_ptr_Input_v4float Input
    475 %_ptr_Input_float = OpTypePointer Input %float
    476 %In1 = OpVariable %_ptr_Input_float Input
    477 %In2 = OpVariable %_ptr_Input_float Input
    478 %uint = OpTypeInt 32 0
    479 %_Globals_ = OpTypeStruct %uint %uint
    480 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
    481 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
    482 %int = OpTypeInt 32 1
    483 %int_0 = OpConstant %int 0
    484 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
    485 %bool = OpTypeBool
    486 %uint_0 = OpConstant %uint 0
    487 %float_1 = OpConstant %float 1
    488 %int_1 = OpConstant %int 1
    489 %float_0 = OpConstant %float 0
    490 %_ptr_Output_v4float = OpTypePointer Output %v4float
    491 %OutColor = OpVariable %_ptr_Output_v4float Output
    492 %27 = OpUndef %v4float
    493 )";
    494 
    495   const std::string before =
    496       R"(%main = OpFunction %void None %10
    497 %28 = OpLabel
    498 %29 = OpLoad %v4float %In0
    499 %30 = OpLoad %float %In1
    500 %31 = OpLoad %float %In2
    501 %32 = OpFAdd %float %30 %31
    502 %33 = OpCompositeInsert %v4float %32 %29 1
    503 %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
    504 %35 = OpLoad %uint %34
    505 %36 = OpINotEqual %bool %35 %uint_0
    506 OpSelectionMerge %37 None
    507 OpBranchConditional %36 %38 %37
    508 %38 = OpLabel
    509 %39 = OpCompositeInsert %v4float %float_1 %33 0
    510 OpBranch %37
    511 %37 = OpLabel
    512 %40 = OpPhi %v4float %33 %28 %39 %38
    513 %41 = OpCompositeExtract %float %40 0
    514 %42 = OpCompositeInsert %v4float %41 %27 0
    515 %43 = OpCompositeExtract %float %40 1
    516 %44 = OpCompositeInsert %v4float %43 %42 1
    517 %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1
    518 %46 = OpLoad %uint %45
    519 %47 = OpINotEqual %bool %46 %uint_0
    520 OpSelectionMerge %48 None
    521 OpBranchConditional %47 %49 %48
    522 %49 = OpLabel
    523 %50 = OpCompositeInsert %v4float %float_0 %44 0
    524 OpBranch %48
    525 %48 = OpLabel
    526 %51 = OpPhi %v4float %44 %37 %50 %49
    527 %52 = OpCompositeExtract %float %51 0
    528 %53 = OpCompositeExtract %float %51 0
    529 %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1
    530 OpStore %OutColor %54
    531 OpReturn
    532 OpFunctionEnd
    533 )";
    534 
    535   const std::string after =
    536       R"(%main = OpFunction %void None %10
    537 %28 = OpLabel
    538 %29 = OpLoad %v4float %In0
    539 %34 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
    540 %35 = OpLoad %uint %34
    541 %36 = OpINotEqual %bool %35 %uint_0
    542 OpSelectionMerge %37 None
    543 OpBranchConditional %36 %38 %37
    544 %38 = OpLabel
    545 %39 = OpCompositeInsert %v4float %float_1 %29 0
    546 OpBranch %37
    547 %37 = OpLabel
    548 %40 = OpPhi %v4float %29 %28 %39 %38
    549 %41 = OpCompositeExtract %float %40 0
    550 %42 = OpCompositeInsert %v4float %41 %27 0
    551 %45 = OpAccessChain %_ptr_Uniform_uint %_ %int_1
    552 %46 = OpLoad %uint %45
    553 %47 = OpINotEqual %bool %46 %uint_0
    554 OpSelectionMerge %48 None
    555 OpBranchConditional %47 %49 %48
    556 %49 = OpLabel
    557 %50 = OpCompositeInsert %v4float %float_0 %42 0
    558 OpBranch %48
    559 %48 = OpLabel
    560 %51 = OpPhi %v4float %42 %37 %50 %49
    561 %52 = OpCompositeExtract %float %51 0
    562 %53 = OpCompositeExtract %float %51 0
    563 %54 = OpCompositeConstruct %v4float %52 %53 %float_0 %float_1
    564 OpStore %OutColor %54
    565 OpReturn
    566 OpFunctionEnd
    567 )";
    568 
    569   SinglePassRunAndCheck<DeadInsertElimPass>(before_predefs + before,
    570                                             after_predefs + after, true, true);
    571 }
    572 
    573 TEST_F(VectorDCETest, InsertObjectLive) {
    574   // Make sure that the object being inserted in an OpCompositeInsert
    575   // is not removed when it is uses later on.
    576   const std::string before =
    577       R"(OpCapability Shader
    578 %1 = OpExtInstImport "GLSL.std.450"
    579 OpMemoryModel Logical GLSL450
    580 OpEntryPoint Fragment %main "main" %In0 %In1 %OutColor
    581 OpExecutionMode %main OriginUpperLeft
    582 OpSource GLSL 450
    583 OpName %main "main"
    584 OpName %In0 "In0"
    585 OpName %In1 "In1"
    586 OpName %OutColor "OutColor"
    587 OpDecorate %In0 Location 0
    588 OpDecorate %In1 Location 1
    589 OpDecorate %OutColor Location 0
    590 %void = OpTypeVoid
    591 %10 = OpTypeFunction %void
    592 %float = OpTypeFloat 32
    593 %v4float = OpTypeVector %float 4
    594 %_ptr_Input_v4float = OpTypePointer Input %v4float
    595 %In0 = OpVariable %_ptr_Input_v4float Input
    596 %_ptr_Input_float = OpTypePointer Input %float
    597 %In1 = OpVariable %_ptr_Input_float Input
    598 %_ptr_Output_v4float = OpTypePointer Output %v4float
    599 %OutColor = OpVariable %_ptr_Output_v4float Output
    600 %main = OpFunction %void None %10
    601 %28 = OpLabel
    602 %29 = OpLoad %v4float %In0
    603 %30 = OpLoad %float %In1
    604 %33 = OpCompositeInsert %v4float %30 %29 1
    605 OpStore %OutColor %33
    606 OpReturn
    607 OpFunctionEnd
    608 )";
    609 
    610   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
    611   SinglePassRunAndCheck<DeadInsertElimPass>(before, before, true, true);
    612 }
    613 
    614 TEST_F(VectorDCETest, DeadInsertInCycle) {
    615   // Dead insert in chain with cycle. Demonstrates analysis can handle
    616   // cycles in chains going through scalars intermediate values.
    617   //
    618   // Note: The SPIR-V assembly has had store/load elimination
    619   // performed to allow the inserts and extracts to directly
    620   // reference each other.
    621   //
    622   // #version 450
    623   //
    624   // layout (location=0) in vec4 In0;
    625   // layout (location=1) in float In1;
    626   // layout (location=2) in float In2;
    627   // layout (location=0) out vec4 OutColor;
    628   //
    629   // layout(std140, binding = 0 ) uniform _Globals_
    630   // {
    631   //     int g_n  ;
    632   // };
    633   //
    634   // void main()
    635   // {
    636   //     vec2 v = vec2(0.0, 1.0);
    637   //     for (int i = 0; i < g_n; i++) {
    638   //       v.x = v.x + 1;
    639   //       v.y = v.y * 0.9; // dead
    640   //     }
    641   //     OutColor = vec4(v.x);
    642   // }
    643 
    644   const std::string assembly =
    645       R"(
    646 ; CHECK: [[init_val:%\w+]] = OpConstantComposite %v2float %float_0 %float_1
    647 ; CHECK: [[undef:%\w+]] = OpUndef %v2float
    648 ; CHECK: OpFunction
    649 ; CHECK: [[entry_lab:%\w+]] = OpLabel
    650 ; CHECK: [[loop_header:%\w+]] = OpLabel
    651 ; CHECK: OpPhi %v2float [[init_val]] [[entry_lab]] [[x_insert:%\w+]] {{%\w+}}
    652 ; CHECK: [[x_insert:%\w+]] = OpCompositeInsert %v2float %43 [[undef]] 0
    653 OpCapability Shader
    654 %1 = OpExtInstImport "GLSL.std.450"
    655 OpMemoryModel Logical GLSL450
    656 OpEntryPoint Fragment %main "main" %OutColor %In0 %In1 %In2
    657 OpExecutionMode %main OriginUpperLeft
    658 OpSource GLSL 450
    659 OpName %main "main"
    660 OpName %_Globals_ "_Globals_"
    661 OpMemberName %_Globals_ 0 "g_n"
    662 OpName %_ ""
    663 OpName %OutColor "OutColor"
    664 OpName %In0 "In0"
    665 OpName %In1 "In1"
    666 OpName %In2 "In2"
    667 OpMemberDecorate %_Globals_ 0 Offset 0
    668 OpDecorate %_Globals_ Block
    669 OpDecorate %_ DescriptorSet 0
    670 OpDecorate %_ Binding 0
    671 OpDecorate %OutColor Location 0
    672 OpDecorate %In0 Location 0
    673 OpDecorate %In1 Location 1
    674 OpDecorate %In2 Location 2
    675 %void = OpTypeVoid
    676 %10 = OpTypeFunction %void
    677 %float = OpTypeFloat 32
    678 %v2float = OpTypeVector %float 2
    679 %_ptr_Function_v2float = OpTypePointer Function %v2float
    680 %float_0 = OpConstant %float 0
    681 %float_1 = OpConstant %float 1
    682 %16 = OpConstantComposite %v2float %float_0 %float_1
    683 %int = OpTypeInt 32 1
    684 %_ptr_Function_int = OpTypePointer Function %int
    685 %int_0 = OpConstant %int 0
    686 %_Globals_ = OpTypeStruct %int
    687 %_ptr_Uniform__Globals_ = OpTypePointer Uniform %_Globals_
    688 %_ = OpVariable %_ptr_Uniform__Globals_ Uniform
    689 %_ptr_Uniform_int = OpTypePointer Uniform %int
    690 %bool = OpTypeBool
    691 %float_0_75 = OpConstant %float 0.75
    692 %int_1 = OpConstant %int 1
    693 %v4float = OpTypeVector %float 4
    694 %_ptr_Output_v4float = OpTypePointer Output %v4float
    695 %OutColor = OpVariable %_ptr_Output_v4float Output
    696 %_ptr_Input_v4float = OpTypePointer Input %v4float
    697 %In0 = OpVariable %_ptr_Input_v4float Input
    698 %_ptr_Input_float = OpTypePointer Input %float
    699 %In1 = OpVariable %_ptr_Input_float Input
    700 %In2 = OpVariable %_ptr_Input_float Input
    701 %main = OpFunction %void None %10
    702 %29 = OpLabel
    703 OpBranch %30
    704 %30 = OpLabel
    705 %31 = OpPhi %v2float %16 %29 %32 %33
    706 %34 = OpPhi %int %int_0 %29 %35 %33
    707 OpLoopMerge %36 %33 None
    708 OpBranch %37
    709 %37 = OpLabel
    710 %38 = OpAccessChain %_ptr_Uniform_int %_ %int_0
    711 %39 = OpLoad %int %38
    712 %40 = OpSLessThan %bool %34 %39
    713 OpBranchConditional %40 %41 %36
    714 %41 = OpLabel
    715 %42 = OpCompositeExtract %float %31 0
    716 %43 = OpFAdd %float %42 %float_1
    717 %44 = OpCompositeInsert %v2float %43 %31 0
    718 %45 = OpCompositeExtract %float %44 1
    719 %46 = OpFMul %float %45 %float_0_75
    720 %32 = OpCompositeInsert %v2float %46 %44 1
    721 OpBranch %33
    722 %33 = OpLabel
    723 %35 = OpIAdd %int %34 %int_1
    724 OpBranch %30
    725 %36 = OpLabel
    726 %47 = OpCompositeExtract %float %31 0
    727 %48 = OpCompositeConstruct %v4float %47 %47 %47 %47
    728 OpStore %OutColor %48
    729 OpReturn
    730 OpFunctionEnd
    731 )";
    732 
    733   SinglePassRunAndMatch<VectorDCE>(assembly, true);
    734 }
    735 
    736 TEST_F(VectorDCETest, DeadLoadFeedingCompositeConstruct) {
    737   // Detach the loads feeding the CompositeConstruct for the unused elements.
    738   // TODO: Implement the rewrite for CompositeConstruct.
    739 
    740   const std::string assembly =
    741       R"(
    742 ; CHECK: [[undef:%\w+]] = OpUndef %float
    743 ; CHECK: [[ac:%\w+]] = OpAccessChain %_ptr_Input_float %In0 %uint_2
    744 ; CHECK: [[load:%\w+]] = OpLoad %float [[ac]]
    745 ; CHECK: OpCompositeConstruct %v3float [[load]] [[undef]] [[undef]]
    746 OpCapability Shader
    747 %1 = OpExtInstImport "GLSL.std.450"
    748 OpMemoryModel Logical GLSL450
    749 OpEntryPoint Fragment %main "main" %In0 %OutColor
    750 OpExecutionMode %main OriginUpperLeft
    751 OpSource GLSL 450
    752 OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
    753 OpSourceExtension "GL_GOOGLE_include_directive"
    754 OpName %main "main"
    755 OpName %In0 "In0"
    756 OpName %OutColor "OutColor"
    757 OpDecorate %In0 Location 0
    758 OpDecorate %OutColor Location 0
    759 %void = OpTypeVoid
    760 %6 = OpTypeFunction %void
    761 %float = OpTypeFloat 32
    762 %v4float = OpTypeVector %float 4
    763 %_ptr_Input_v4float = OpTypePointer Input %v4float
    764 %In0 = OpVariable %_ptr_Input_v4float Input
    765 %uint = OpTypeInt 32 0
    766 %uint_0 = OpConstant %uint 0
    767 %_ptr_Input_float = OpTypePointer Input %float
    768 %uint_1 = OpConstant %uint 1
    769 %uint_2 = OpConstant %uint 2
    770 %v3float = OpTypeVector %float 3
    771 %int = OpTypeInt 32 1
    772 %int_0 = OpConstant %int 0
    773 %int_20 = OpConstant %int 20
    774 %bool = OpTypeBool
    775 %float_1 = OpConstant %float 1
    776 %int_1 = OpConstant %int 1
    777 %_ptr_Output_v4float = OpTypePointer Output %v4float
    778 %OutColor = OpVariable %_ptr_Output_v4float Output
    779 %23 = OpUndef %v3float
    780 %main = OpFunction %void None %6
    781 %24 = OpLabel
    782 %25 = OpAccessChain %_ptr_Input_float %In0 %uint_0
    783 %26 = OpLoad %float %25
    784 %27 = OpAccessChain %_ptr_Input_float %In0 %uint_1
    785 %28 = OpLoad %float %27
    786 %29 = OpAccessChain %_ptr_Input_float %In0 %uint_2
    787 %30 = OpLoad %float %29
    788 %31 = OpCompositeConstruct %v3float %30 %28 %26
    789 OpBranch %32
    790 %32 = OpLabel
    791 %33 = OpPhi %v3float %31 %24 %34 %35
    792 %36 = OpPhi %int %int_0 %24 %37 %35
    793 OpLoopMerge %38 %35 None
    794 OpBranch %39
    795 %39 = OpLabel
    796 %40 = OpSLessThan %bool %36 %int_20
    797 OpBranchConditional %40 %41 %38
    798 %41 = OpLabel
    799 %42 = OpCompositeExtract %float %33 0
    800 %43 = OpFAdd %float %42 %float_1
    801 %34 = OpCompositeInsert %v3float %43 %33 0
    802 OpBranch %35
    803 %35 = OpLabel
    804 %37 = OpIAdd %int %36 %int_1
    805 OpBranch %32
    806 %38 = OpLabel
    807 %44 = OpCompositeExtract %float %33 0
    808 %45 = OpCompositeConstruct %v4float %44 %44 %44 %44
    809 OpStore %OutColor %45
    810 OpReturn
    811 OpFunctionEnd
    812 )";
    813 
    814   SinglePassRunAndMatch<VectorDCE>(assembly, true);
    815 }
    816 
    817 TEST_F(VectorDCETest, DeadLoadFeedingVectorShuffle) {
    818   // Detach the loads feeding the CompositeConstruct for the unused elements.
    819   // TODO: Implement the rewrite for CompositeConstruct.
    820 
    821   const std::string assembly =
    822       R"(
    823 ; MemPass Type2Undef does not reuse and already existing undef.
    824 ; CHECK: {{%\w+}} = OpUndef %v3float
    825 ; CHECK: [[undef:%\w+]] = OpUndef %v3float
    826 ; CHECK: OpFunction
    827 ; CHECK: OpVectorShuffle %v3float {{%\w+}} [[undef]] 0 4 5
    828                OpCapability Shader
    829           %1 = OpExtInstImport "GLSL.std.450"
    830                OpMemoryModel Logical GLSL450
    831                OpEntryPoint Fragment %main "main" %In0 %OutColor
    832                OpExecutionMode %main OriginUpperLeft
    833                OpSource GLSL 450
    834                OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
    835                OpSourceExtension "GL_GOOGLE_include_directive"
    836                OpName %main "main"
    837                OpName %In0 "In0"
    838                OpName %OutColor "OutColor"
    839                OpDecorate %In0 Location 0
    840                OpDecorate %OutColor Location 0
    841        %void = OpTypeVoid
    842           %6 = OpTypeFunction %void
    843       %float = OpTypeFloat 32
    844     %v4float = OpTypeVector %float 4
    845 %_ptr_Input_v4float = OpTypePointer Input %v4float
    846         %In0 = OpVariable %_ptr_Input_v4float Input
    847        %uint = OpTypeInt 32 0
    848      %uint_0 = OpConstant %uint 0
    849 %_ptr_Input_float = OpTypePointer Input %float
    850      %uint_1 = OpConstant %uint 1
    851      %uint_2 = OpConstant %uint 2
    852     %v3float = OpTypeVector %float 3
    853         %int = OpTypeInt 32 1
    854       %int_0 = OpConstant %int 0
    855      %int_20 = OpConstant %int 20
    856        %bool = OpTypeBool
    857     %float_1 = OpConstant %float 1
    858     %vec_const = OpConstantComposite %v3float %float_1 %float_1 %float_1
    859       %int_1 = OpConstant %int 1
    860 %_ptr_Output_v4float = OpTypePointer Output %v4float
    861    %OutColor = OpVariable %_ptr_Output_v4float Output
    862          %23 = OpUndef %v3float
    863        %main = OpFunction %void None %6
    864          %24 = OpLabel
    865          %25 = OpAccessChain %_ptr_Input_float %In0 %uint_0
    866          %26 = OpLoad %float %25
    867          %27 = OpAccessChain %_ptr_Input_float %In0 %uint_1
    868          %28 = OpLoad %float %27
    869          %29 = OpAccessChain %_ptr_Input_float %In0 %uint_2
    870          %30 = OpLoad %float %29
    871          %31 = OpCompositeConstruct %v3float %30 %28 %26
    872          %sh = OpVectorShuffle %v3float %vec_const %31 0 4 5
    873                OpBranch %32
    874          %32 = OpLabel
    875          %33 = OpPhi %v3float %sh %24 %34 %35
    876          %36 = OpPhi %int %int_0 %24 %37 %35
    877                OpLoopMerge %38 %35 None
    878                OpBranch %39
    879          %39 = OpLabel
    880          %40 = OpSLessThan %bool %36 %int_20
    881                OpBranchConditional %40 %41 %38
    882          %41 = OpLabel
    883          %42 = OpCompositeExtract %float %33 0
    884          %43 = OpFAdd %float %42 %float_1
    885          %34 = OpCompositeInsert %v3float %43 %33 0
    886                OpBranch %35
    887          %35 = OpLabel
    888          %37 = OpIAdd %int %36 %int_1
    889                OpBranch %32
    890          %38 = OpLabel
    891          %44 = OpCompositeExtract %float %33 0
    892          %45 = OpCompositeConstruct %v4float %44 %44 %44 %44
    893                OpStore %OutColor %45
    894                OpReturn
    895                OpFunctionEnd
    896 )";
    897 
    898   SinglePassRunAndMatch<VectorDCE>(assembly, true);
    899 }
    900 
    901 TEST_F(VectorDCETest, DeadInstThroughShuffle) {
    902   // Dead insert in chain with cycle. Demonstrates analysis can handle
    903   // cycles in chains.
    904   //
    905   // Note: The SPIR-V assembly has had store/load elimination
    906   // performed to allow the inserts and extracts to directly
    907   // reference each other.
    908   //
    909   // #version 450
    910   //
    911   // layout (location=0) out vec4 OutColor;
    912   //
    913   // void main()
    914   // {
    915   //     vec2 v;
    916   //     v.x = 0.0;
    917   //     v.y = 0.1; // dead
    918   //     for (int i = 0; i < 20; i++) {
    919   //       v.x = v.x + 1;
    920   //       v = v * 0.9;
    921   //     }
    922   //     OutColor = vec4(v.x);
    923   // }
    924 
    925   const std::string assembly =
    926       R"(
    927 ; CHECK: OpFunction
    928 ; CHECK-NOT: OpCompositeInsert %v2float {{%\w+}} 1
    929 ; CHECK: OpFunctionEnd
    930                OpCapability Shader
    931           %1 = OpExtInstImport "GLSL.std.450"
    932                OpMemoryModel Logical GLSL450
    933                OpEntryPoint Fragment %main "main" %OutColor
    934                OpExecutionMode %main OriginUpperLeft
    935                OpSource GLSL 450
    936                OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
    937                OpSourceExtension "GL_GOOGLE_include_directive"
    938                OpName %main "main"
    939                OpName %OutColor "OutColor"
    940                OpDecorate %OutColor Location 0
    941        %void = OpTypeVoid
    942           %3 = OpTypeFunction %void
    943       %float = OpTypeFloat 32
    944     %v2float = OpTypeVector %float 2
    945     %float_0 = OpConstant %float 0
    946 %float_0_100000001 = OpConstant %float 0.100000001
    947         %int = OpTypeInt 32 1
    948       %int_0 = OpConstant %int 0
    949      %int_20 = OpConstant %int 20
    950        %bool = OpTypeBool
    951     %float_1 = OpConstant %float 1
    952 %float_0_899999976 = OpConstant %float 0.899999976
    953       %int_1 = OpConstant %int 1
    954     %v4float = OpTypeVector %float 4
    955 %_ptr_Output_v4float = OpTypePointer Output %v4float
    956    %OutColor = OpVariable %_ptr_Output_v4float Output
    957          %58 = OpUndef %v2float
    958        %main = OpFunction %void None %3
    959           %5 = OpLabel
    960          %49 = OpCompositeInsert %v2float %float_0 %58 0
    961          %51 = OpCompositeInsert %v2float %float_0_100000001 %49 1
    962                OpBranch %22
    963          %22 = OpLabel
    964          %60 = OpPhi %v2float %51 %5 %38 %25
    965          %59 = OpPhi %int %int_0 %5 %41 %25
    966                OpLoopMerge %24 %25 None
    967                OpBranch %26
    968          %26 = OpLabel
    969          %30 = OpSLessThan %bool %59 %int_20
    970                OpBranchConditional %30 %23 %24
    971          %23 = OpLabel
    972          %53 = OpCompositeExtract %float %60 0
    973          %34 = OpFAdd %float %53 %float_1
    974          %55 = OpCompositeInsert %v2float %34 %60 0
    975          %38 = OpVectorTimesScalar %v2float %55 %float_0_899999976
    976                OpBranch %25
    977          %25 = OpLabel
    978          %41 = OpIAdd %int %59 %int_1
    979                OpBranch %22
    980          %24 = OpLabel
    981          %57 = OpCompositeExtract %float %60 0
    982          %47 = OpCompositeConstruct %v4float %57 %57 %57 %57
    983                OpStore %OutColor %47
    984                OpReturn
    985                OpFunctionEnd
    986 )";
    987 
    988   SinglePassRunAndMatch<VectorDCE>(assembly, true);
    989 }
    990 
    991 TEST_F(VectorDCETest, DeadInsertThroughOtherInst) {
    992   // Dead insert in chain with cycle. Demonstrates analysis can handle
    993   // cycles in chains.
    994   //
    995   // Note: The SPIR-V assembly has had store/load elimination
    996   // performed to allow the inserts and extracts to directly
    997   // reference each other.
    998   //
    999   // #version 450
   1000   //
   1001   // layout (location=0) out vec4 OutColor;
   1002   //
   1003   // void main()
   1004   // {
   1005   //     vec2 v;
   1006   //     v.x = 0.0;
   1007   //     v.y = 0.1; // dead
   1008   //     for (int i = 0; i < 20; i++) {
   1009   //       v.x = v.x + 1;
   1010   //       v = v * 0.9;
   1011   //     }
   1012   //     OutColor = vec4(v.x);
   1013   // }
   1014 
   1015   const std::string assembly =
   1016       R"(
   1017 ; CHECK: OpFunction
   1018 ; CHECK-NOT: OpCompositeInsert %v2float {{%\w+}} 1
   1019 ; CHECK: OpFunctionEnd
   1020                OpCapability Shader
   1021           %1 = OpExtInstImport "GLSL.std.450"
   1022                OpMemoryModel Logical GLSL450
   1023                OpEntryPoint Fragment %main "main" %OutColor
   1024                OpExecutionMode %main OriginUpperLeft
   1025                OpSource GLSL 450
   1026                OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
   1027                OpSourceExtension "GL_GOOGLE_include_directive"
   1028                OpName %main "main"
   1029                OpName %OutColor "OutColor"
   1030                OpDecorate %OutColor Location 0
   1031        %void = OpTypeVoid
   1032           %3 = OpTypeFunction %void
   1033       %float = OpTypeFloat 32
   1034     %v2float = OpTypeVector %float 2
   1035     %float_0 = OpConstant %float 0
   1036 %float_0_100000001 = OpConstant %float 0.100000001
   1037         %int = OpTypeInt 32 1
   1038       %int_0 = OpConstant %int 0
   1039      %int_20 = OpConstant %int 20
   1040        %bool = OpTypeBool
   1041     %float_1 = OpConstant %float 1
   1042 %float_0_899999976 = OpConstant %float 0.899999976
   1043       %int_1 = OpConstant %int 1
   1044     %v4float = OpTypeVector %float 4
   1045 %_ptr_Output_v4float = OpTypePointer Output %v4float
   1046    %OutColor = OpVariable %_ptr_Output_v4float Output
   1047          %58 = OpUndef %v2float
   1048        %main = OpFunction %void None %3
   1049           %5 = OpLabel
   1050          %49 = OpCompositeInsert %v2float %float_0 %58 0
   1051          %51 = OpCompositeInsert %v2float %float_0_100000001 %49 1
   1052                OpBranch %22
   1053          %22 = OpLabel
   1054          %60 = OpPhi %v2float %51 %5 %38 %25
   1055          %59 = OpPhi %int %int_0 %5 %41 %25
   1056                OpLoopMerge %24 %25 None
   1057                OpBranch %26
   1058          %26 = OpLabel
   1059          %30 = OpSLessThan %bool %59 %int_20
   1060                OpBranchConditional %30 %23 %24
   1061          %23 = OpLabel
   1062          %53 = OpCompositeExtract %float %60 0
   1063          %34 = OpFAdd %float %53 %float_1
   1064          %55 = OpCompositeInsert %v2float %34 %60 0
   1065          %38 = OpVectorTimesScalar %v2float %55 %float_0_899999976
   1066                OpBranch %25
   1067          %25 = OpLabel
   1068          %41 = OpIAdd %int %59 %int_1
   1069                OpBranch %22
   1070          %24 = OpLabel
   1071          %57 = OpCompositeExtract %float %60 0
   1072          %47 = OpCompositeConstruct %v4float %57 %57 %57 %57
   1073                OpStore %OutColor %47
   1074                OpReturn
   1075                OpFunctionEnd
   1076 )";
   1077 
   1078   SinglePassRunAndMatch<VectorDCE>(assembly, true);
   1079 }
   1080 
   1081 TEST_F(VectorDCETest, VectorIntoCompositeConstruct) {
   1082   const std::string text = R"(OpCapability Linkage
   1083 OpCapability Shader
   1084 OpMemoryModel Logical GLSL450
   1085 OpEntryPoint Fragment %1 "EntryPoint_Main" %2 %3
   1086 OpExecutionMode %1 OriginUpperLeft
   1087 OpDecorate %2 Location 0
   1088 OpDecorate %_struct_4 Block
   1089 OpDecorate %3 Location 0
   1090 %float = OpTypeFloat 32
   1091 %v2float = OpTypeVector %float 2
   1092 %_ptr_Function_v2float = OpTypePointer Function %v2float
   1093 %v4float = OpTypeVector %float 4
   1094 %_ptr_Function_v4float = OpTypePointer Function %v4float
   1095 %mat4v4float = OpTypeMatrix %v4float 4
   1096 %_ptr_Function_mat4v4float = OpTypePointer Function %mat4v4float
   1097 %v3float = OpTypeVector %float 3
   1098 %_ptr_Function_v3float = OpTypePointer Function %v3float
   1099 %_struct_14 = OpTypeStruct %v2float %mat4v4float %v3float %v2float %v4float
   1100 %_ptr_Function__struct_14 = OpTypePointer Function %_struct_14
   1101 %void = OpTypeVoid
   1102 %int = OpTypeInt 32 1
   1103 %int_2 = OpConstant %int 2
   1104 %int_1 = OpConstant %int 1
   1105 %int_4 = OpConstant %int 4
   1106 %int_0 = OpConstant %int 0
   1107 %int_3 = OpConstant %int 3
   1108 %float_0 = OpConstant %float 0
   1109 %float_1 = OpConstant %float 1
   1110 %_ptr_Input_v2float = OpTypePointer Input %v2float
   1111 %2 = OpVariable %_ptr_Input_v2float Input
   1112 %_ptr_Output_v2float = OpTypePointer Output %v2float
   1113 %_struct_4 = OpTypeStruct %v2float
   1114 %_ptr_Output__struct_4 = OpTypePointer Output %_struct_4
   1115 %3 = OpVariable %_ptr_Output__struct_4 Output
   1116 %28 = OpTypeFunction %void
   1117 %29 = OpConstantComposite %v2float %float_0 %float_0
   1118 %30 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
   1119 %31 = OpConstantComposite %mat4v4float %30 %30 %30 %30
   1120 %32 = OpConstantComposite %v3float %float_0 %float_0 %float_0
   1121 %1 = OpFunction %void None %28
   1122 %33 = OpLabel
   1123 %34 = OpVariable %_ptr_Function_v4float Function
   1124 %35 = OpVariable %_ptr_Function__struct_14 Function
   1125 %36 = OpAccessChain %_ptr_Function_v2float %35 %int_0
   1126 OpStore %36 %29
   1127 %37 = OpAccessChain %_ptr_Function_mat4v4float %35 %int_1
   1128 OpStore %37 %31
   1129 %38 = OpAccessChain %_ptr_Function_v3float %35 %int_2
   1130 OpStore %38 %32
   1131 %39 = OpAccessChain %_ptr_Function_v2float %35 %int_3
   1132 OpStore %39 %29
   1133 %40 = OpAccessChain %_ptr_Function_v4float %35 %int_4
   1134 OpStore %40 %30
   1135 %41 = OpLoad %v2float %2
   1136 OpStore %36 %41
   1137 %42 = OpLoad %v3float %38
   1138 %43 = OpCompositeConstruct %v4float %42 %float_1
   1139 %44 = OpLoad %mat4v4float %37
   1140 %45 = OpVectorTimesMatrix %v4float %43 %44
   1141 OpStore %34 %45
   1142 OpCopyMemory %40 %34
   1143 OpCopyMemory %36 %39
   1144 %46 = OpAccessChain %_ptr_Output_v2float %3 %int_0
   1145 %47 = OpLoad %v2float %36
   1146 OpStore %46 %47
   1147 OpReturn
   1148 OpFunctionEnd
   1149 )";
   1150 
   1151   SinglePassRunAndCheck<DeadInsertElimPass>(text, text, true, true);
   1152 }
   1153 
   1154 }  // namespace
   1155 }  // namespace opt
   1156 }  // namespace spvtools
   1157