Home | History | Annotate | Download | only in opt
      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 DeadBranchElimTest = PassTest<::testing::Test>;
     26 
     27 TEST_F(DeadBranchElimTest, IfThenElseTrue) {
     28   // #version 140
     29   //
     30   // in vec4 BaseColor;
     31   //
     32   // void main()
     33   // {
     34   //     vec4 v;
     35   //     if (true)
     36   //       v = vec4(0.0,0.0,0.0,0.0);
     37   //     else
     38   //       v = vec4(1.0,1.0,1.0,1.0);
     39   //     gl_FragColor = v;
     40   // }
     41 
     42   const std::string predefs =
     43       R"(OpCapability Shader
     44 %1 = OpExtInstImport "GLSL.std.450"
     45 OpMemoryModel Logical GLSL450
     46 OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
     47 OpExecutionMode %main OriginUpperLeft
     48 OpSource GLSL 140
     49 OpName %main "main"
     50 OpName %v "v"
     51 OpName %gl_FragColor "gl_FragColor"
     52 OpName %BaseColor "BaseColor"
     53 %void = OpTypeVoid
     54 %7 = OpTypeFunction %void
     55 %bool = OpTypeBool
     56 %true = OpConstantTrue %bool
     57 %float = OpTypeFloat 32
     58 %v4float = OpTypeVector %float 4
     59 %_ptr_Function_v4float = OpTypePointer Function %v4float
     60 %float_0 = OpConstant %float 0
     61 %14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
     62 %float_1 = OpConstant %float 1
     63 %16 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
     64 %_ptr_Output_v4float = OpTypePointer Output %v4float
     65 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
     66 %_ptr_Input_v4float = OpTypePointer Input %v4float
     67 %BaseColor = OpVariable %_ptr_Input_v4float Input
     68 )";
     69 
     70   const std::string before =
     71       R"(%main = OpFunction %void None %7
     72 %19 = OpLabel
     73 %v = OpVariable %_ptr_Function_v4float Function
     74 OpSelectionMerge %20 None
     75 OpBranchConditional %true %21 %22
     76 %21 = OpLabel
     77 OpStore %v %14
     78 OpBranch %20
     79 %22 = OpLabel
     80 OpStore %v %16
     81 OpBranch %20
     82 %20 = OpLabel
     83 %23 = OpLoad %v4float %v
     84 OpStore %gl_FragColor %23
     85 OpReturn
     86 OpFunctionEnd
     87 )";
     88 
     89   const std::string after =
     90       R"(%main = OpFunction %void None %7
     91 %19 = OpLabel
     92 %v = OpVariable %_ptr_Function_v4float Function
     93 OpBranch %21
     94 %21 = OpLabel
     95 OpStore %v %14
     96 OpBranch %20
     97 %20 = OpLabel
     98 %23 = OpLoad %v4float %v
     99 OpStore %gl_FragColor %23
    100 OpReturn
    101 OpFunctionEnd
    102 )";
    103 
    104   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
    105                                             true, true);
    106 }
    107 
    108 TEST_F(DeadBranchElimTest, IfThenElseFalse) {
    109   // #version 140
    110   //
    111   // in vec4 BaseColor;
    112   //
    113   // void main()
    114   // {
    115   //     vec4 v;
    116   //     if (false)
    117   //       v = vec4(0.0,0.0,0.0,0.0);
    118   //     else
    119   //       v = vec4(1.0,1.0,1.0,1.0);
    120   //     gl_FragColor = v;
    121   // }
    122 
    123   const std::string predefs =
    124       R"(OpCapability Shader
    125 %1 = OpExtInstImport "GLSL.std.450"
    126 OpMemoryModel Logical GLSL450
    127 OpEntryPoint Fragment %main "main" %gl_FragColor %BaseColor
    128 OpExecutionMode %main OriginUpperLeft
    129 OpSource GLSL 140
    130 OpName %main "main"
    131 OpName %v "v"
    132 OpName %gl_FragColor "gl_FragColor"
    133 OpName %BaseColor "BaseColor"
    134 %void = OpTypeVoid
    135 %7 = OpTypeFunction %void
    136 %bool = OpTypeBool
    137 %false = OpConstantFalse %bool
    138 %float = OpTypeFloat 32
    139 %v4float = OpTypeVector %float 4
    140 %_ptr_Function_v4float = OpTypePointer Function %v4float
    141 %float_0 = OpConstant %float 0
    142 %14 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
    143 %float_1 = OpConstant %float 1
    144 %16 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
    145 %_ptr_Output_v4float = OpTypePointer Output %v4float
    146 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    147 %_ptr_Input_v4float = OpTypePointer Input %v4float
    148 %BaseColor = OpVariable %_ptr_Input_v4float Input
    149 )";
    150 
    151   const std::string before =
    152       R"(%main = OpFunction %void None %7
    153 %19 = OpLabel
    154 %v = OpVariable %_ptr_Function_v4float Function
    155 OpSelectionMerge %20 None
    156 OpBranchConditional %false %21 %22
    157 %21 = OpLabel
    158 OpStore %v %14
    159 OpBranch %20
    160 %22 = OpLabel
    161 OpStore %v %16
    162 OpBranch %20
    163 %20 = OpLabel
    164 %23 = OpLoad %v4float %v
    165 OpStore %gl_FragColor %23
    166 OpReturn
    167 OpFunctionEnd
    168 )";
    169 
    170   const std::string after =
    171       R"(%main = OpFunction %void None %7
    172 %19 = OpLabel
    173 %v = OpVariable %_ptr_Function_v4float Function
    174 OpBranch %22
    175 %22 = OpLabel
    176 OpStore %v %16
    177 OpBranch %20
    178 %20 = OpLabel
    179 %23 = OpLoad %v4float %v
    180 OpStore %gl_FragColor %23
    181 OpReturn
    182 OpFunctionEnd
    183 )";
    184 
    185   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
    186                                             true, true);
    187 }
    188 
    189 TEST_F(DeadBranchElimTest, IfThenTrue) {
    190   // #version 140
    191   //
    192   // in vec4 BaseColor;
    193   //
    194   // void main()
    195   // {
    196   //     vec4 v = BaseColor;
    197   //     if (true)
    198   //       v = v * vec4(0.5,0.5,0.5,0.5);
    199   //     gl_FragColor = v;
    200   // }
    201 
    202   const std::string predefs =
    203       R"(OpCapability Shader
    204 %1 = OpExtInstImport "GLSL.std.450"
    205 OpMemoryModel Logical GLSL450
    206 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
    207 OpExecutionMode %main OriginUpperLeft
    208 OpSource GLSL 140
    209 OpName %main "main"
    210 OpName %v "v"
    211 OpName %BaseColor "BaseColor"
    212 OpName %gl_FragColor "gl_FragColor"
    213 %void = OpTypeVoid
    214 %7 = OpTypeFunction %void
    215 %float = OpTypeFloat 32
    216 %v4float = OpTypeVector %float 4
    217 %_ptr_Function_v4float = OpTypePointer Function %v4float
    218 %_ptr_Input_v4float = OpTypePointer Input %v4float
    219 %BaseColor = OpVariable %_ptr_Input_v4float Input
    220 %bool = OpTypeBool
    221 %true = OpConstantTrue %bool
    222 %float_0_5 = OpConstant %float 0.5
    223 %15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
    224 %_ptr_Output_v4float = OpTypePointer Output %v4float
    225 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    226 )";
    227 
    228   const std::string before =
    229       R"(%main = OpFunction %void None %7
    230 %17 = OpLabel
    231 %v = OpVariable %_ptr_Function_v4float Function
    232 %18 = OpLoad %v4float %BaseColor
    233 OpStore %v %18
    234 OpSelectionMerge %19 None
    235 OpBranchConditional %true %20 %19
    236 %20 = OpLabel
    237 %21 = OpLoad %v4float %v
    238 %22 = OpFMul %v4float %21 %15
    239 OpStore %v %22
    240 OpBranch %19
    241 %19 = OpLabel
    242 %23 = OpLoad %v4float %v
    243 OpStore %gl_FragColor %23
    244 OpReturn
    245 OpFunctionEnd
    246 )";
    247 
    248   const std::string after =
    249       R"(%main = OpFunction %void None %7
    250 %17 = OpLabel
    251 %v = OpVariable %_ptr_Function_v4float Function
    252 %18 = OpLoad %v4float %BaseColor
    253 OpStore %v %18
    254 OpBranch %20
    255 %20 = OpLabel
    256 %21 = OpLoad %v4float %v
    257 %22 = OpFMul %v4float %21 %15
    258 OpStore %v %22
    259 OpBranch %19
    260 %19 = OpLabel
    261 %23 = OpLoad %v4float %v
    262 OpStore %gl_FragColor %23
    263 OpReturn
    264 OpFunctionEnd
    265 )";
    266 
    267   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
    268                                             true, true);
    269 }
    270 
    271 TEST_F(DeadBranchElimTest, IfThenFalse) {
    272   // #version 140
    273   //
    274   // in vec4 BaseColor;
    275   //
    276   // void main()
    277   // {
    278   //     vec4 v = BaseColor;
    279   //     if (false)
    280   //       v = v * vec4(0.5,0.5,0.5,0.5);
    281   //     gl_FragColor = v;
    282   // }
    283 
    284   const std::string predefs =
    285       R"(OpCapability Shader
    286 %1 = OpExtInstImport "GLSL.std.450"
    287 OpMemoryModel Logical GLSL450
    288 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
    289 OpExecutionMode %main OriginUpperLeft
    290 OpSource GLSL 140
    291 OpName %main "main"
    292 OpName %v "v"
    293 OpName %BaseColor "BaseColor"
    294 OpName %gl_FragColor "gl_FragColor"
    295 %void = OpTypeVoid
    296 %7 = OpTypeFunction %void
    297 %float = OpTypeFloat 32
    298 %v4float = OpTypeVector %float 4
    299 %_ptr_Function_v4float = OpTypePointer Function %v4float
    300 %_ptr_Input_v4float = OpTypePointer Input %v4float
    301 %BaseColor = OpVariable %_ptr_Input_v4float Input
    302 %bool = OpTypeBool
    303 %false = OpConstantFalse %bool
    304 %float_0_5 = OpConstant %float 0.5
    305 %15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
    306 %_ptr_Output_v4float = OpTypePointer Output %v4float
    307 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    308 )";
    309 
    310   const std::string before =
    311       R"(%main = OpFunction %void None %7
    312 %17 = OpLabel
    313 %v = OpVariable %_ptr_Function_v4float Function
    314 %18 = OpLoad %v4float %BaseColor
    315 OpStore %v %18
    316 OpSelectionMerge %19 None
    317 OpBranchConditional %false %20 %19
    318 %20 = OpLabel
    319 %21 = OpLoad %v4float %v
    320 %22 = OpFMul %v4float %21 %15
    321 OpStore %v %22
    322 OpBranch %19
    323 %19 = OpLabel
    324 %23 = OpLoad %v4float %v
    325 OpStore %gl_FragColor %23
    326 OpReturn
    327 OpFunctionEnd
    328 )";
    329 
    330   const std::string after =
    331       R"(%main = OpFunction %void None %7
    332 %17 = OpLabel
    333 %v = OpVariable %_ptr_Function_v4float Function
    334 %18 = OpLoad %v4float %BaseColor
    335 OpStore %v %18
    336 OpBranch %19
    337 %19 = OpLabel
    338 %23 = OpLoad %v4float %v
    339 OpStore %gl_FragColor %23
    340 OpReturn
    341 OpFunctionEnd
    342 )";
    343 
    344   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
    345                                             true, true);
    346 }
    347 
    348 TEST_F(DeadBranchElimTest, IfThenElsePhiTrue) {
    349   // Test handling of phi in merge block after dead branch elimination.
    350   // Note: The SPIR-V has had store/load elimination and phi insertion
    351   //
    352   // #version 140
    353   //
    354   // void main()
    355   // {
    356   //     vec4 v;
    357   //     if (true)
    358   //       v = vec4(0.0,0.0,0.0,0.0);
    359   //     else
    360   //       v = vec4(1.0,1.0,1.0,1.0);
    361   //     gl_FragColor = v;
    362   // }
    363 
    364   const std::string predefs =
    365       R"(OpCapability Shader
    366 %1 = OpExtInstImport "GLSL.std.450"
    367 OpMemoryModel Logical GLSL450
    368 OpEntryPoint Fragment %main "main" %gl_FragColor
    369 OpExecutionMode %main OriginUpperLeft
    370 OpSource GLSL 140
    371 OpName %main "main"
    372 OpName %gl_FragColor "gl_FragColor"
    373 %void = OpTypeVoid
    374 %5 = OpTypeFunction %void
    375 %bool = OpTypeBool
    376 %true = OpConstantTrue %bool
    377 %float = OpTypeFloat 32
    378 %v4float = OpTypeVector %float 4
    379 %_ptr_Function_v4float = OpTypePointer Function %v4float
    380 %float_0 = OpConstant %float 0
    381 %12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
    382 %float_1 = OpConstant %float 1
    383 %14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
    384 %_ptr_Output_v4float = OpTypePointer Output %v4float
    385 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    386 %_ptr_Input_v4float = OpTypePointer Input %v4float
    387 )";
    388 
    389   const std::string before =
    390       R"(%main = OpFunction %void None %5
    391 %17 = OpLabel
    392 OpSelectionMerge %18 None
    393 OpBranchConditional %true %19 %20
    394 %19 = OpLabel
    395 OpBranch %18
    396 %20 = OpLabel
    397 OpBranch %18
    398 %18 = OpLabel
    399 %21 = OpPhi %v4float %12 %19 %14 %20
    400 OpStore %gl_FragColor %21
    401 OpReturn
    402 OpFunctionEnd
    403 )";
    404 
    405   const std::string after =
    406       R"(%main = OpFunction %void None %5
    407 %17 = OpLabel
    408 OpBranch %19
    409 %19 = OpLabel
    410 OpBranch %18
    411 %18 = OpLabel
    412 OpStore %gl_FragColor %12
    413 OpReturn
    414 OpFunctionEnd
    415 )";
    416 
    417   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
    418                                             true, true);
    419 }
    420 
    421 TEST_F(DeadBranchElimTest, IfThenElsePhiFalse) {
    422   // Test handling of phi in merge block after dead branch elimination.
    423   // Note: The SPIR-V has had store/load elimination and phi insertion
    424   //
    425   // #version 140
    426   //
    427   // void main()
    428   // {
    429   //     vec4 v;
    430   //     if (true)
    431   //       v = vec4(0.0,0.0,0.0,0.0);
    432   //     else
    433   //       v = vec4(1.0,1.0,1.0,1.0);
    434   //     gl_FragColor = v;
    435   // }
    436 
    437   const std::string predefs =
    438       R"(OpCapability Shader
    439 %1 = OpExtInstImport "GLSL.std.450"
    440 OpMemoryModel Logical GLSL450
    441 OpEntryPoint Fragment %main "main" %gl_FragColor
    442 OpExecutionMode %main OriginUpperLeft
    443 OpSource GLSL 140
    444 OpName %main "main"
    445 OpName %gl_FragColor "gl_FragColor"
    446 %void = OpTypeVoid
    447 %5 = OpTypeFunction %void
    448 %bool = OpTypeBool
    449 %false = OpConstantFalse %bool
    450 %float = OpTypeFloat 32
    451 %v4float = OpTypeVector %float 4
    452 %_ptr_Function_v4float = OpTypePointer Function %v4float
    453 %float_0 = OpConstant %float 0
    454 %12 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
    455 %float_1 = OpConstant %float 1
    456 %14 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
    457 %_ptr_Output_v4float = OpTypePointer Output %v4float
    458 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    459 %_ptr_Input_v4float = OpTypePointer Input %v4float
    460 )";
    461 
    462   const std::string before =
    463       R"(%main = OpFunction %void None %5
    464 %17 = OpLabel
    465 OpSelectionMerge %18 None
    466 OpBranchConditional %false %19 %20
    467 %19 = OpLabel
    468 OpBranch %18
    469 %20 = OpLabel
    470 OpBranch %18
    471 %18 = OpLabel
    472 %21 = OpPhi %v4float %12 %19 %14 %20
    473 OpStore %gl_FragColor %21
    474 OpReturn
    475 OpFunctionEnd
    476 )";
    477 
    478   const std::string after =
    479       R"(%main = OpFunction %void None %5
    480 %17 = OpLabel
    481 OpBranch %20
    482 %20 = OpLabel
    483 OpBranch %18
    484 %18 = OpLabel
    485 OpStore %gl_FragColor %14
    486 OpReturn
    487 OpFunctionEnd
    488 )";
    489 
    490   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
    491                                             true, true);
    492 }
    493 
    494 TEST_F(DeadBranchElimTest, CompoundIfThenElseFalse) {
    495   // #version 140
    496   //
    497   // layout(std140) uniform U_t
    498   // {
    499   //     bool g_B ;
    500   // } ;
    501   //
    502   // void main()
    503   // {
    504   //     vec4 v;
    505   //     if (false) {
    506   //       if (g_B)
    507   //         v = vec4(0.0,0.0,0.0,0.0);
    508   //       else
    509   //         v = vec4(1.0,1.0,1.0,1.0);
    510   //     } else {
    511   //       if (g_B)
    512   //         v = vec4(1.0,1.0,1.0,1.0);
    513   //       else
    514   //         v = vec4(0.0,0.0,0.0,0.0);
    515   //     }
    516   //     gl_FragColor = v;
    517   // }
    518 
    519   const std::string predefs =
    520       R"(OpCapability Shader
    521 %1 = OpExtInstImport "GLSL.std.450"
    522 OpMemoryModel Logical GLSL450
    523 OpEntryPoint Fragment %main "main" %gl_FragColor
    524 OpExecutionMode %main OriginUpperLeft
    525 OpSource GLSL 140
    526 OpName %main "main"
    527 OpName %U_t "U_t"
    528 OpMemberName %U_t 0 "g_B"
    529 OpName %_ ""
    530 OpName %v "v"
    531 OpName %gl_FragColor "gl_FragColor"
    532 OpMemberDecorate %U_t 0 Offset 0
    533 OpDecorate %U_t Block
    534 OpDecorate %_ DescriptorSet 0
    535 %void = OpTypeVoid
    536 %8 = OpTypeFunction %void
    537 %bool = OpTypeBool
    538 %false = OpConstantFalse %bool
    539 %uint = OpTypeInt 32 0
    540 %U_t = OpTypeStruct %uint
    541 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
    542 %_ = OpVariable %_ptr_Uniform_U_t Uniform
    543 %int = OpTypeInt 32 1
    544 %int_0 = OpConstant %int 0
    545 %_ptr_Uniform_uint = OpTypePointer Uniform %uint
    546 %uint_0 = OpConstant %uint 0
    547 %float = OpTypeFloat 32
    548 %v4float = OpTypeVector %float 4
    549 %_ptr_Function_v4float = OpTypePointer Function %v4float
    550 %float_0 = OpConstant %float 0
    551 %21 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
    552 %float_1 = OpConstant %float 1
    553 %23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
    554 %_ptr_Output_v4float = OpTypePointer Output %v4float
    555 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    556 )";
    557 
    558   const std::string before =
    559       R"(%main = OpFunction %void None %8
    560 %25 = OpLabel
    561 %v = OpVariable %_ptr_Function_v4float Function
    562 OpSelectionMerge %26 None
    563 OpBranchConditional %false %27 %28
    564 %27 = OpLabel
    565 %29 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
    566 %30 = OpLoad %uint %29
    567 %31 = OpINotEqual %bool %30 %uint_0
    568 OpSelectionMerge %32 None
    569 OpBranchConditional %31 %33 %34
    570 %33 = OpLabel
    571 OpStore %v %21
    572 OpBranch %32
    573 %34 = OpLabel
    574 OpStore %v %23
    575 OpBranch %32
    576 %32 = OpLabel
    577 OpBranch %26
    578 %28 = OpLabel
    579 %35 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
    580 %36 = OpLoad %uint %35
    581 %37 = OpINotEqual %bool %36 %uint_0
    582 OpSelectionMerge %38 None
    583 OpBranchConditional %37 %39 %40
    584 %39 = OpLabel
    585 OpStore %v %23
    586 OpBranch %38
    587 %40 = OpLabel
    588 OpStore %v %21
    589 OpBranch %38
    590 %38 = OpLabel
    591 OpBranch %26
    592 %26 = OpLabel
    593 %41 = OpLoad %v4float %v
    594 OpStore %gl_FragColor %41
    595 OpReturn
    596 OpFunctionEnd
    597 )";
    598 
    599   const std::string after =
    600       R"(%main = OpFunction %void None %8
    601 %25 = OpLabel
    602 %v = OpVariable %_ptr_Function_v4float Function
    603 OpBranch %28
    604 %28 = OpLabel
    605 %35 = OpAccessChain %_ptr_Uniform_uint %_ %int_0
    606 %36 = OpLoad %uint %35
    607 %37 = OpINotEqual %bool %36 %uint_0
    608 OpSelectionMerge %38 None
    609 OpBranchConditional %37 %39 %40
    610 %40 = OpLabel
    611 OpStore %v %21
    612 OpBranch %38
    613 %39 = OpLabel
    614 OpStore %v %23
    615 OpBranch %38
    616 %38 = OpLabel
    617 OpBranch %26
    618 %26 = OpLabel
    619 %41 = OpLoad %v4float %v
    620 OpStore %gl_FragColor %41
    621 OpReturn
    622 OpFunctionEnd
    623 )";
    624 
    625   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
    626                                             true, true);
    627 }
    628 
    629 TEST_F(DeadBranchElimTest, PreventOrphanMerge) {
    630   const std::string predefs =
    631       R"(OpCapability Shader
    632 %1 = OpExtInstImport "GLSL.std.450"
    633 OpMemoryModel Logical GLSL450
    634 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
    635 OpExecutionMode %main OriginUpperLeft
    636 OpSource GLSL 140
    637 OpName %main "main"
    638 OpName %v "v"
    639 OpName %BaseColor "BaseColor"
    640 OpName %gl_FragColor "gl_FragColor"
    641 %void = OpTypeVoid
    642 %7 = OpTypeFunction %void
    643 %float = OpTypeFloat 32
    644 %v4float = OpTypeVector %float 4
    645 %_ptr_Function_v4float = OpTypePointer Function %v4float
    646 %_ptr_Input_v4float = OpTypePointer Input %v4float
    647 %BaseColor = OpVariable %_ptr_Input_v4float Input
    648 %bool = OpTypeBool
    649 %true = OpConstantTrue %bool
    650 %float_0_5 = OpConstant %float 0.5
    651 %_ptr_Output_v4float = OpTypePointer Output %v4float
    652 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    653 )";
    654 
    655   const std::string before =
    656       R"(%main = OpFunction %void None %7
    657 %16 = OpLabel
    658 %v = OpVariable %_ptr_Function_v4float Function
    659 %17 = OpLoad %v4float %BaseColor
    660 OpStore %v %17
    661 OpSelectionMerge %18 None
    662 OpBranchConditional %true %19 %20
    663 %19 = OpLabel
    664 OpKill
    665 %20 = OpLabel
    666 %21 = OpLoad %v4float %v
    667 %22 = OpVectorTimesScalar %v4float %21 %float_0_5
    668 OpStore %v %22
    669 OpBranch %18
    670 %18 = OpLabel
    671 %23 = OpLoad %v4float %v
    672 OpStore %gl_FragColor %23
    673 OpReturn
    674 OpFunctionEnd
    675 )";
    676 
    677   const std::string after =
    678       R"(%main = OpFunction %void None %7
    679 %16 = OpLabel
    680 %v = OpVariable %_ptr_Function_v4float Function
    681 %17 = OpLoad %v4float %BaseColor
    682 OpStore %v %17
    683 OpBranch %19
    684 %19 = OpLabel
    685 OpKill
    686 OpFunctionEnd
    687 )";
    688 
    689   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
    690                                             true, true);
    691 }
    692 
    693 TEST_F(DeadBranchElimTest, HandleOrphanMerge) {
    694   const std::string predefs =
    695       R"(OpCapability Shader
    696 %1 = OpExtInstImport "GLSL.std.450"
    697 OpMemoryModel Logical GLSL450
    698 OpEntryPoint Fragment %main "main" %gl_FragColor
    699 OpExecutionMode %main OriginUpperLeft
    700 OpSource GLSL 140
    701 OpName %main "main"
    702 OpName %foo_ "foo("
    703 OpName %gl_FragColor "gl_FragColor"
    704 OpDecorate %gl_FragColor Location 0
    705 %void = OpTypeVoid
    706 %6 = OpTypeFunction %void
    707 %float = OpTypeFloat 32
    708 %v4float = OpTypeVector %float 4
    709 %9 = OpTypeFunction %v4float
    710 %bool = OpTypeBool
    711 %true = OpConstantTrue %bool
    712 %float_0 = OpConstant %float 0
    713 %13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
    714 %float_1 = OpConstant %float 1
    715 %15 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
    716 %_ptr_Output_v4float = OpTypePointer Output %v4float
    717 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    718 %main = OpFunction %void None %6
    719 %17 = OpLabel
    720 %18 = OpFunctionCall %v4float %foo_
    721 OpStore %gl_FragColor %18
    722 OpReturn
    723 OpFunctionEnd
    724 )";
    725 
    726   const std::string before =
    727       R"(%foo_ = OpFunction %v4float None %9
    728 %19 = OpLabel
    729 OpSelectionMerge %20 None
    730 OpBranchConditional %true %21 %22
    731 %21 = OpLabel
    732 OpReturnValue %13
    733 %22 = OpLabel
    734 OpReturnValue %15
    735 %20 = OpLabel
    736 %23 = OpUndef %v4float
    737 OpReturnValue %23
    738 OpFunctionEnd
    739 )";
    740 
    741   const std::string after =
    742       R"(%foo_ = OpFunction %v4float None %9
    743 %19 = OpLabel
    744 OpBranch %21
    745 %21 = OpLabel
    746 OpReturnValue %13
    747 OpFunctionEnd
    748 )";
    749 
    750   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
    751                                             true, true);
    752 }
    753 
    754 TEST_F(DeadBranchElimTest, KeepContinueTargetWhenKillAfterMerge) {
    755   // #version 450
    756   // void main() {
    757   //   bool c;
    758   //   bool d;
    759   //   while(c) {
    760   //     if(d) {
    761   //      continue;
    762   //     }
    763   //     if(false) {
    764   //      continue;
    765   //     }
    766   //     discard;
    767   //   }
    768   // }
    769 
    770   const std::string predefs =
    771       R"(OpCapability Shader
    772 %1 = OpExtInstImport "GLSL.std.450"
    773 OpMemoryModel Logical GLSL450
    774 OpEntryPoint Fragment %main "main"
    775 OpExecutionMode %main OriginUpperLeft
    776 OpSource GLSL 450
    777 OpName %main "main"
    778 OpName %c "c"
    779 OpName %d "d"
    780 %void = OpTypeVoid
    781 %6 = OpTypeFunction %void
    782 %bool = OpTypeBool
    783 %_ptr_Function_bool = OpTypePointer Function %bool
    784 %false = OpConstantFalse %bool
    785 )";
    786 
    787   const std::string before =
    788       R"(%main = OpFunction %void None %6
    789 %10 = OpLabel
    790 %c = OpVariable %_ptr_Function_bool Function
    791 %d = OpVariable %_ptr_Function_bool Function
    792 OpBranch %11
    793 %11 = OpLabel
    794 OpLoopMerge %12 %13 None
    795 OpBranch %14
    796 %14 = OpLabel
    797 %15 = OpLoad %bool %c
    798 OpBranchConditional %15 %16 %12
    799 %16 = OpLabel
    800 %17 = OpLoad %bool %d
    801 OpSelectionMerge %18 None
    802 OpBranchConditional %17 %19 %18
    803 %19 = OpLabel
    804 OpBranch %13
    805 %18 = OpLabel
    806 OpSelectionMerge %20 None
    807 OpBranchConditional %false %21 %20
    808 %21 = OpLabel
    809 OpBranch %13
    810 %20 = OpLabel
    811 OpKill
    812 %13 = OpLabel
    813 OpBranch %11
    814 %12 = OpLabel
    815 OpReturn
    816 OpFunctionEnd
    817 )";
    818 
    819   const std::string after =
    820       R"(%main = OpFunction %void None %6
    821 %10 = OpLabel
    822 %c = OpVariable %_ptr_Function_bool Function
    823 %d = OpVariable %_ptr_Function_bool Function
    824 OpBranch %11
    825 %11 = OpLabel
    826 OpLoopMerge %12 %13 None
    827 OpBranch %14
    828 %14 = OpLabel
    829 %15 = OpLoad %bool %c
    830 OpBranchConditional %15 %16 %12
    831 %16 = OpLabel
    832 %17 = OpLoad %bool %d
    833 OpSelectionMerge %18 None
    834 OpBranchConditional %17 %19 %18
    835 %19 = OpLabel
    836 OpBranch %13
    837 %18 = OpLabel
    838 OpBranch %20
    839 %20 = OpLabel
    840 OpKill
    841 %13 = OpLabel
    842 OpBranch %11
    843 %12 = OpLabel
    844 OpReturn
    845 OpFunctionEnd
    846 )";
    847 
    848   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
    849                                             true, true);
    850 }
    851 
    852 TEST_F(DeadBranchElimTest, DecorateDeleted) {
    853   // Note: SPIR-V hand-edited to add decoration
    854   // #version 140
    855   //
    856   // in vec4 BaseColor;
    857   //
    858   // void main()
    859   // {
    860   //     vec4 v = BaseColor;
    861   //     if (false)
    862   //       v = v * vec4(0.5,0.5,0.5,0.5);
    863   //     gl_FragColor = v;
    864   // }
    865 
    866   const std::string predefs_before =
    867       R"(OpCapability Shader
    868 %1 = OpExtInstImport "GLSL.std.450"
    869 OpMemoryModel Logical GLSL450
    870 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
    871 OpExecutionMode %main OriginUpperLeft
    872 OpSource GLSL 140
    873 OpName %main "main"
    874 OpName %v "v"
    875 OpName %BaseColor "BaseColor"
    876 OpName %gl_FragColor "gl_FragColor"
    877 OpDecorate %22 RelaxedPrecision
    878 %void = OpTypeVoid
    879 %7 = OpTypeFunction %void
    880 %float = OpTypeFloat 32
    881 %v4float = OpTypeVector %float 4
    882 %_ptr_Function_v4float = OpTypePointer Function %v4float
    883 %_ptr_Input_v4float = OpTypePointer Input %v4float
    884 %BaseColor = OpVariable %_ptr_Input_v4float Input
    885 %bool = OpTypeBool
    886 %false = OpConstantFalse %bool
    887 %float_0_5 = OpConstant %float 0.5
    888 %15 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
    889 %_ptr_Output_v4float = OpTypePointer Output %v4float
    890 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    891 )";
    892 
    893   const std::string predefs_after =
    894       R"(OpCapability Shader
    895 %1 = OpExtInstImport "GLSL.std.450"
    896 OpMemoryModel Logical GLSL450
    897 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
    898 OpExecutionMode %main OriginUpperLeft
    899 OpSource GLSL 140
    900 OpName %main "main"
    901 OpName %v "v"
    902 OpName %BaseColor "BaseColor"
    903 OpName %gl_FragColor "gl_FragColor"
    904 %void = OpTypeVoid
    905 %8 = OpTypeFunction %void
    906 %float = OpTypeFloat 32
    907 %v4float = OpTypeVector %float 4
    908 %_ptr_Function_v4float = OpTypePointer Function %v4float
    909 %_ptr_Input_v4float = OpTypePointer Input %v4float
    910 %BaseColor = OpVariable %_ptr_Input_v4float Input
    911 %bool = OpTypeBool
    912 %false = OpConstantFalse %bool
    913 %float_0_5 = OpConstant %float 0.5
    914 %16 = OpConstantComposite %v4float %float_0_5 %float_0_5 %float_0_5 %float_0_5
    915 %_ptr_Output_v4float = OpTypePointer Output %v4float
    916 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    917 )";
    918 
    919   const std::string before =
    920       R"(%main = OpFunction %void None %7
    921 %17 = OpLabel
    922 %v = OpVariable %_ptr_Function_v4float Function
    923 %18 = OpLoad %v4float %BaseColor
    924 OpStore %v %18
    925 OpSelectionMerge %19 None
    926 OpBranchConditional %false %20 %19
    927 %20 = OpLabel
    928 %21 = OpLoad %v4float %v
    929 %22 = OpFMul %v4float %21 %15
    930 OpStore %v %22
    931 OpBranch %19
    932 %19 = OpLabel
    933 %23 = OpLoad %v4float %v
    934 OpStore %gl_FragColor %23
    935 OpReturn
    936 OpFunctionEnd
    937 )";
    938 
    939   const std::string after =
    940       R"(%main = OpFunction %void None %8
    941 %18 = OpLabel
    942 %v = OpVariable %_ptr_Function_v4float Function
    943 %19 = OpLoad %v4float %BaseColor
    944 OpStore %v %19
    945 OpBranch %20
    946 %20 = OpLabel
    947 %23 = OpLoad %v4float %v
    948 OpStore %gl_FragColor %23
    949 OpReturn
    950 OpFunctionEnd
    951 )";
    952 
    953   SinglePassRunAndCheck<DeadBranchElimPass>(predefs_before + before,
    954                                             predefs_after + after, true, true);
    955 }
    956 
    957 TEST_F(DeadBranchElimTest, LoopInDeadBranch) {
    958   // #version 450
    959   //
    960   // layout(location = 0) in vec4 BaseColor;
    961   // layout(location = 0) out vec4 OutColor;
    962   //
    963   // void main()
    964   // {
    965   //     vec4 v = BaseColor;
    966   //     if (false)
    967   //       for (int i=0; i<3; i++)
    968   //         v = v * 0.5;
    969   //     OutColor = v;
    970   // }
    971 
    972   const std::string predefs =
    973       R"(OpCapability Shader
    974 %1 = OpExtInstImport "GLSL.std.450"
    975 OpMemoryModel Logical GLSL450
    976 OpEntryPoint Fragment %main "main" %BaseColor %OutColor
    977 OpExecutionMode %main OriginUpperLeft
    978 OpSource GLSL 450
    979 OpName %main "main"
    980 OpName %v "v"
    981 OpName %BaseColor "BaseColor"
    982 OpName %i "i"
    983 OpName %OutColor "OutColor"
    984 OpDecorate %BaseColor Location 0
    985 OpDecorate %OutColor Location 0
    986 %void = OpTypeVoid
    987 %8 = OpTypeFunction %void
    988 %float = OpTypeFloat 32
    989 %v4float = OpTypeVector %float 4
    990 %_ptr_Function_v4float = OpTypePointer Function %v4float
    991 %_ptr_Input_v4float = OpTypePointer Input %v4float
    992 %BaseColor = OpVariable %_ptr_Input_v4float Input
    993 %bool = OpTypeBool
    994 %false = OpConstantFalse %bool
    995 %int = OpTypeInt 32 1
    996 %_ptr_Function_int = OpTypePointer Function %int
    997 %int_0 = OpConstant %int 0
    998 %int_3 = OpConstant %int 3
    999 %float_0_5 = OpConstant %float 0.5
   1000 %int_1 = OpConstant %int 1
   1001 %_ptr_Output_v4float = OpTypePointer Output %v4float
   1002 %OutColor = OpVariable %_ptr_Output_v4float Output
   1003 )";
   1004 
   1005   const std::string before =
   1006       R"(%main = OpFunction %void None %8
   1007 %22 = OpLabel
   1008 %v = OpVariable %_ptr_Function_v4float Function
   1009 %i = OpVariable %_ptr_Function_int Function
   1010 %23 = OpLoad %v4float %BaseColor
   1011 OpStore %v %23
   1012 OpSelectionMerge %24 None
   1013 OpBranchConditional %false %25 %24
   1014 %25 = OpLabel
   1015 OpStore %i %int_0
   1016 OpBranch %26
   1017 %26 = OpLabel
   1018 OpLoopMerge %27 %28 None
   1019 OpBranch %29
   1020 %29 = OpLabel
   1021 %30 = OpLoad %int %i
   1022 %31 = OpSLessThan %bool %30 %int_3
   1023 OpBranchConditional %31 %32 %27
   1024 %32 = OpLabel
   1025 %33 = OpLoad %v4float %v
   1026 %34 = OpVectorTimesScalar %v4float %33 %float_0_5
   1027 OpStore %v %34
   1028 OpBranch %28
   1029 %28 = OpLabel
   1030 %35 = OpLoad %int %i
   1031 %36 = OpIAdd %int %35 %int_1
   1032 OpStore %i %36
   1033 OpBranch %26
   1034 %27 = OpLabel
   1035 OpBranch %24
   1036 %24 = OpLabel
   1037 %37 = OpLoad %v4float %v
   1038 OpStore %OutColor %37
   1039 OpReturn
   1040 OpFunctionEnd
   1041 )";
   1042 
   1043   const std::string after =
   1044       R"(%main = OpFunction %void None %8
   1045 %22 = OpLabel
   1046 %v = OpVariable %_ptr_Function_v4float Function
   1047 %i = OpVariable %_ptr_Function_int Function
   1048 %23 = OpLoad %v4float %BaseColor
   1049 OpStore %v %23
   1050 OpBranch %24
   1051 %24 = OpLabel
   1052 %37 = OpLoad %v4float %v
   1053 OpStore %OutColor %37
   1054 OpReturn
   1055 OpFunctionEnd
   1056 )";
   1057 
   1058   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
   1059                                             true, true);
   1060 }
   1061 
   1062 TEST_F(DeadBranchElimTest, SwitchLiveCase) {
   1063   // #version 450
   1064   //
   1065   // layout (location=0) in vec4 BaseColor;
   1066   // layout (location=0) out vec4 OutColor;
   1067   //
   1068   // void main()
   1069   // {
   1070   //     switch (1) {
   1071   //       case 0:
   1072   //         OutColor = vec4(0.0,0.0,0.0,0.0);
   1073   //         break;
   1074   //       case 1:
   1075   //         OutColor = vec4(0.125,0.125,0.125,0.125);
   1076   //         break;
   1077   //       case 2:
   1078   //         OutColor = vec4(0.25,0.25,0.25,0.25);
   1079   //         break;
   1080   //       default:
   1081   //         OutColor = vec4(1.0,1.0,1.0,1.0);
   1082   //     }
   1083   // }
   1084 
   1085   const std::string predefs =
   1086       R"(OpCapability Shader
   1087 %1 = OpExtInstImport "GLSL.std.450"
   1088 OpMemoryModel Logical GLSL450
   1089 OpEntryPoint Fragment %main "main" %OutColor %BaseColor
   1090 OpExecutionMode %main OriginUpperLeft
   1091 OpSource GLSL 450
   1092 OpName %main "main"
   1093 OpName %OutColor "OutColor"
   1094 OpName %BaseColor "BaseColor"
   1095 OpDecorate %OutColor Location 0
   1096 OpDecorate %BaseColor Location 0
   1097 %void = OpTypeVoid
   1098 %6 = OpTypeFunction %void
   1099 %int = OpTypeInt 32 1
   1100 %int_1 = OpConstant %int 1
   1101 %float = OpTypeFloat 32
   1102 %v4float = OpTypeVector %float 4
   1103 %_ptr_Output_v4float = OpTypePointer Output %v4float
   1104 %OutColor = OpVariable %_ptr_Output_v4float Output
   1105 %float_0 = OpConstant %float 0
   1106 %13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
   1107 %float_0_125 = OpConstant %float 0.125
   1108 %15 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125
   1109 %float_0_25 = OpConstant %float 0.25
   1110 %17 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
   1111 %float_1 = OpConstant %float 1
   1112 %19 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
   1113 %_ptr_Input_v4float = OpTypePointer Input %v4float
   1114 %BaseColor = OpVariable %_ptr_Input_v4float Input
   1115 )";
   1116 
   1117   const std::string before =
   1118       R"(%main = OpFunction %void None %6
   1119 %21 = OpLabel
   1120 OpSelectionMerge %22 None
   1121 OpSwitch %int_1 %23 0 %24 1 %25 2 %26
   1122 %23 = OpLabel
   1123 OpStore %OutColor %19
   1124 OpBranch %22
   1125 %24 = OpLabel
   1126 OpStore %OutColor %13
   1127 OpBranch %22
   1128 %25 = OpLabel
   1129 OpStore %OutColor %15
   1130 OpBranch %22
   1131 %26 = OpLabel
   1132 OpStore %OutColor %17
   1133 OpBranch %22
   1134 %22 = OpLabel
   1135 OpReturn
   1136 OpFunctionEnd
   1137 )";
   1138 
   1139   const std::string after =
   1140       R"(%main = OpFunction %void None %6
   1141 %21 = OpLabel
   1142 OpBranch %25
   1143 %25 = OpLabel
   1144 OpStore %OutColor %15
   1145 OpBranch %22
   1146 %22 = OpLabel
   1147 OpReturn
   1148 OpFunctionEnd
   1149 )";
   1150 
   1151   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
   1152                                             true, true);
   1153 }
   1154 
   1155 TEST_F(DeadBranchElimTest, SwitchLiveDefault) {
   1156   // #version 450
   1157   //
   1158   // layout (location=0) in vec4 BaseColor;
   1159   // layout (location=0) out vec4 OutColor;
   1160   //
   1161   // void main()
   1162   // {
   1163   //     switch (7) {
   1164   //       case 0:
   1165   //         OutColor = vec4(0.0,0.0,0.0,0.0);
   1166   //         break;
   1167   //       case 1:
   1168   //         OutColor = vec4(0.125,0.125,0.125,0.125);
   1169   //         break;
   1170   //       case 2:
   1171   //         OutColor = vec4(0.25,0.25,0.25,0.25);
   1172   //         break;
   1173   //       default:
   1174   //         OutColor = vec4(1.0,1.0,1.0,1.0);
   1175   //     }
   1176   // }
   1177 
   1178   const std::string predefs =
   1179       R"(OpCapability Shader
   1180 %1 = OpExtInstImport "GLSL.std.450"
   1181 OpMemoryModel Logical GLSL450
   1182 OpEntryPoint Fragment %main "main" %OutColor %BaseColor
   1183 OpExecutionMode %main OriginUpperLeft
   1184 OpSource GLSL 450
   1185 OpName %main "main"
   1186 OpName %OutColor "OutColor"
   1187 OpName %BaseColor "BaseColor"
   1188 OpDecorate %OutColor Location 0
   1189 OpDecorate %BaseColor Location 0
   1190 %void = OpTypeVoid
   1191 %6 = OpTypeFunction %void
   1192 %int = OpTypeInt 32 1
   1193 %int_7 = OpConstant %int 7
   1194 %float = OpTypeFloat 32
   1195 %v4float = OpTypeVector %float 4
   1196 %_ptr_Output_v4float = OpTypePointer Output %v4float
   1197 %OutColor = OpVariable %_ptr_Output_v4float Output
   1198 %float_0 = OpConstant %float 0
   1199 %13 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
   1200 %float_0_125 = OpConstant %float 0.125
   1201 %15 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125
   1202 %float_0_25 = OpConstant %float 0.25
   1203 %17 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
   1204 %float_1 = OpConstant %float 1
   1205 %19 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
   1206 %_ptr_Input_v4float = OpTypePointer Input %v4float
   1207 %BaseColor = OpVariable %_ptr_Input_v4float Input
   1208 )";
   1209 
   1210   const std::string before =
   1211       R"(%main = OpFunction %void None %6
   1212 %21 = OpLabel
   1213 OpSelectionMerge %22 None
   1214 OpSwitch %int_7 %23 0 %24 1 %25 2 %26
   1215 %23 = OpLabel
   1216 OpStore %OutColor %19
   1217 OpBranch %22
   1218 %24 = OpLabel
   1219 OpStore %OutColor %13
   1220 OpBranch %22
   1221 %25 = OpLabel
   1222 OpStore %OutColor %15
   1223 OpBranch %22
   1224 %26 = OpLabel
   1225 OpStore %OutColor %17
   1226 OpBranch %22
   1227 %22 = OpLabel
   1228 OpReturn
   1229 OpFunctionEnd
   1230 )";
   1231 
   1232   const std::string after =
   1233       R"(%main = OpFunction %void None %6
   1234 %21 = OpLabel
   1235 OpBranch %23
   1236 %23 = OpLabel
   1237 OpStore %OutColor %19
   1238 OpBranch %22
   1239 %22 = OpLabel
   1240 OpReturn
   1241 OpFunctionEnd
   1242 )";
   1243 
   1244   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
   1245                                             true, true);
   1246 }
   1247 
   1248 TEST_F(DeadBranchElimTest, SwitchLiveCaseBreakFromLoop) {
   1249   // This sample does not directly translate to GLSL/HLSL as
   1250   // direct breaks from a loop cannot be made from a switch.
   1251   // This construct is currently formed by inlining a function
   1252   // containing early returns from the cases of a switch. The
   1253   // function is wrapped in a one-trip loop and returns are
   1254   // translated to branches to the loop's merge block.
   1255 
   1256   const std::string predefs =
   1257       R"(OpCapability Shader
   1258 %1 = OpExtInstImport "GLSL.std.450"
   1259 OpMemoryModel Logical GLSL450
   1260 OpEntryPoint Fragment %main "main" %OutColor %BaseColor
   1261 OpExecutionMode %main OriginUpperLeft
   1262 OpSource GLSL 450
   1263 OpName %main "main"
   1264 OpName %oc "oc"
   1265 OpName %OutColor "OutColor"
   1266 OpName %BaseColor "BaseColor"
   1267 OpDecorate %OutColor Location 0
   1268 OpDecorate %BaseColor Location 0
   1269 %void = OpTypeVoid
   1270 %7 = OpTypeFunction %void
   1271 %bool = OpTypeBool
   1272 %true = OpConstantTrue %bool
   1273 %false = OpConstantFalse %bool
   1274 %int = OpTypeInt 32 1
   1275 %int_1 = OpConstant %int 1
   1276 %float = OpTypeFloat 32
   1277 %v4float = OpTypeVector %float 4
   1278 %_ptr_Function_v4float = OpTypePointer Function %v4float
   1279 %float_0 = OpConstant %float 0
   1280 %17 = OpConstantComposite %v4float %float_0 %float_0 %float_0 %float_0
   1281 %float_0_125 = OpConstant %float 0.125
   1282 %19 = OpConstantComposite %v4float %float_0_125 %float_0_125 %float_0_125 %float_0_125
   1283 %float_0_25 = OpConstant %float 0.25
   1284 %21 = OpConstantComposite %v4float %float_0_25 %float_0_25 %float_0_25 %float_0_25
   1285 %float_1 = OpConstant %float 1
   1286 %23 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
   1287 %_ptr_Output_v4float = OpTypePointer Output %v4float
   1288 %OutColor = OpVariable %_ptr_Output_v4float Output
   1289 %_ptr_Input_v4float = OpTypePointer Input %v4float
   1290 %BaseColor = OpVariable %_ptr_Input_v4float Input
   1291 )";
   1292 
   1293   const std::string before =
   1294       R"(%main = OpFunction %void None %7
   1295 %26 = OpLabel
   1296 %oc = OpVariable %_ptr_Function_v4float Function
   1297 OpBranch %27
   1298 %27 = OpLabel
   1299 OpLoopMerge %28 %29 None
   1300 OpBranch %30
   1301 %30 = OpLabel
   1302 OpSelectionMerge %31 None
   1303 OpSwitch %int_1 %31 0 %32 1 %33 2 %34
   1304 %32 = OpLabel
   1305 OpStore %oc %17
   1306 OpBranch %28
   1307 %33 = OpLabel
   1308 OpStore %oc %19
   1309 OpBranch %28
   1310 %34 = OpLabel
   1311 OpStore %oc %21
   1312 OpBranch %28
   1313 %31 = OpLabel
   1314 OpStore %oc %23
   1315 OpBranch %28
   1316 %29 = OpLabel
   1317 OpBranchConditional %false %27 %28
   1318 %28 = OpLabel
   1319 %35 = OpLoad %v4float %oc
   1320 OpStore %OutColor %35
   1321 OpReturn
   1322 OpFunctionEnd
   1323 )";
   1324 
   1325   const std::string after =
   1326       R"(%main = OpFunction %void None %7
   1327 %26 = OpLabel
   1328 %oc = OpVariable %_ptr_Function_v4float Function
   1329 OpBranch %27
   1330 %27 = OpLabel
   1331 OpLoopMerge %28 %29 None
   1332 OpBranch %30
   1333 %30 = OpLabel
   1334 OpBranch %33
   1335 %33 = OpLabel
   1336 OpStore %oc %19
   1337 OpBranch %28
   1338 %29 = OpLabel
   1339 OpBranch %27
   1340 %28 = OpLabel
   1341 %35 = OpLoad %v4float %oc
   1342 OpStore %OutColor %35
   1343 OpReturn
   1344 OpFunctionEnd
   1345 )";
   1346 
   1347   SinglePassRunAndCheck<DeadBranchElimPass>(predefs + before, predefs + after,
   1348                                             true, true);
   1349 }
   1350 
   1351 TEST_F(DeadBranchElimTest, LeaveContinueBackedge) {
   1352   const std::string text = R"(
   1353 ; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
   1354 ; CHECK: [[continue]] = OpLabel
   1355 ; CHECK-NEXT: OpBranchConditional {{%\w+}} {{%\w+}} [[merge]]
   1356 ; CHECK-NEXT: [[merge]] = OpLabel
   1357 ; CHECK-NEXT: OpReturn
   1358 OpCapability Kernel
   1359 OpCapability Linkage
   1360 OpMemoryModel Logical OpenCL
   1361 %bool = OpTypeBool
   1362 %false = OpConstantFalse %bool
   1363 %void = OpTypeVoid
   1364 %funcTy = OpTypeFunction %void
   1365 %func = OpFunction %void None %funcTy
   1366 %1 = OpLabel
   1367 OpBranch %2
   1368 %2 = OpLabel
   1369 OpLoopMerge %3 %4 None
   1370 OpBranch %4
   1371 %4 = OpLabel
   1372 ; Be careful we don't remove the backedge to %2 despite never taking it.
   1373 OpBranchConditional %false %2 %3
   1374 %3 = OpLabel
   1375 OpReturn
   1376 OpFunctionEnd
   1377 )";
   1378 
   1379   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1380 }
   1381 TEST_F(DeadBranchElimTest, LeaveContinueBackedgeExtraBlock) {
   1382   const std::string text = R"(
   1383 ; CHECK: OpBranch [[header:%\w+]]
   1384 ; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
   1385 ; CHECK-NEXT: OpBranch [[continue]]
   1386 ; CHECK-NEXT: [[continue]] = OpLabel
   1387 ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[extra:%\w+]] [[merge]]
   1388 ; CHECK-NEXT: [[extra]] = OpLabel
   1389 ; CHECK-NEXT: OpBranch [[header]]
   1390 ; CHECK-NEXT: [[merge]] = OpLabel
   1391 ; CHECK-NEXT: OpReturn
   1392 OpCapability Kernel
   1393 OpCapability Linkage
   1394 OpMemoryModel Logical OpenCL
   1395 %bool = OpTypeBool
   1396 %false = OpConstantFalse %bool
   1397 %void = OpTypeVoid
   1398 %funcTy = OpTypeFunction %void
   1399 %func = OpFunction %void None %funcTy
   1400 %1 = OpLabel
   1401 OpBranch %2
   1402 %2 = OpLabel
   1403 OpLoopMerge %3 %4 None
   1404 OpBranch %4
   1405 %4 = OpLabel
   1406 ; Be careful we don't remove the backedge to %2 despite never taking it.
   1407 OpBranchConditional %false %5 %3
   1408 ; This block remains live despite being unreachable.
   1409 %5 = OpLabel
   1410 OpBranch %2
   1411 %3 = OpLabel
   1412 OpReturn
   1413 OpFunctionEnd
   1414 )";
   1415 
   1416   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1417 }
   1418 
   1419 TEST_F(DeadBranchElimTest, RemovePhiWithUnreachableContinue) {
   1420   const std::string text = R"(
   1421 ; CHECK: [[entry:%\w+]] = OpLabel
   1422 ; CHECK-NEXT: OpBranch [[header:%\w+]]
   1423 ; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
   1424 ; CHECK-NEXT: OpBranch [[ret:%\w+]]
   1425 ; CHECK-NEXT: [[ret]] = OpLabel
   1426 ; CHECK-NEXT: OpReturn
   1427 ; CHECK: [[continue]] = OpLabel
   1428 ; CHECK-NEXT: OpBranch [[header]]
   1429 ; CHECK: [[merge]] = OpLabel
   1430 ; CHECK-NEXT: OpUnreachable
   1431 OpCapability Kernel
   1432 OpCapability Linkage
   1433 OpMemoryModel Logical OpenCL
   1434 OpName %func "func"
   1435 OpDecorate %func LinkageAttributes "func" Export
   1436 %bool = OpTypeBool
   1437 %false = OpConstantFalse %bool
   1438 %true = OpConstantTrue %bool
   1439 %void = OpTypeVoid
   1440 %funcTy = OpTypeFunction %void
   1441 %func = OpFunction %void None %funcTy
   1442 %1 = OpLabel
   1443 OpBranch %2
   1444 %2 = OpLabel
   1445 %phi = OpPhi %bool %false %1 %true %continue
   1446 OpLoopMerge %merge %continue None
   1447 OpBranch %3
   1448 %3 = OpLabel
   1449 OpReturn
   1450 %continue = OpLabel
   1451 OpBranch %2
   1452 %merge = OpLabel
   1453 OpReturn
   1454 OpFunctionEnd
   1455 )";
   1456 
   1457   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1458 }
   1459 
   1460 TEST_F(DeadBranchElimTest, UnreachableLoopMergeAndContinueTargets) {
   1461   const std::string text = R"(
   1462 ; CHECK: [[undef:%\w+]] = OpUndef %bool
   1463 ; CHECK: OpSelectionMerge [[header:%\w+]]
   1464 ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[if_lab:%\w+]] [[else_lab:%\w+]]
   1465 ; CHECK: OpPhi %bool %false [[if_lab]] %false [[else_lab]] [[undef]] [[continue:%\w+]]
   1466 ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue]] None
   1467 ; CHECK-NEXT: OpBranch [[ret:%\w+]]
   1468 ; CHECK-NEXT: [[ret]] = OpLabel
   1469 ; CHECK-NEXT: OpReturn
   1470 ; CHECK: [[continue]] = OpLabel
   1471 ; CHECK-NEXT: OpBranch [[header]]
   1472 ; CHECK: [[merge]] = OpLabel
   1473 ; CHECK-NEXT: OpUnreachable
   1474 OpCapability Kernel
   1475 OpCapability Linkage
   1476 OpMemoryModel Logical OpenCL
   1477 OpName %func "func"
   1478 OpDecorate %func LinkageAttributes "func" Export
   1479 %bool = OpTypeBool
   1480 %false = OpConstantFalse %bool
   1481 %true = OpConstantTrue %bool
   1482 %void = OpTypeVoid
   1483 %funcTy = OpTypeFunction %void
   1484 %func = OpFunction %void None %funcTy
   1485 %1 = OpLabel
   1486 %c = OpUndef %bool
   1487 OpSelectionMerge %2 None
   1488 OpBranchConditional %c %if %else
   1489 %if = OpLabel
   1490 OpBranch %2
   1491 %else = OpLabel
   1492 OpBranch %2
   1493 %2 = OpLabel
   1494 %phi = OpPhi %bool %false %if %false %else %true %continue
   1495 OpLoopMerge %merge %continue None
   1496 OpBranch %3
   1497 %3 = OpLabel
   1498 OpReturn
   1499 %continue = OpLabel
   1500 OpBranch %2
   1501 %merge = OpLabel
   1502 OpReturn
   1503 OpFunctionEnd
   1504 )";
   1505 
   1506   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1507 }
   1508 TEST_F(DeadBranchElimTest, EarlyReconvergence) {
   1509   const std::string text = R"(
   1510 ; CHECK-NOT: OpBranchConditional
   1511 ; CHECK: [[logical:%\w+]] = OpLogicalOr
   1512 ; CHECK-NOT: OpPhi
   1513 ; CHECK: OpLogicalAnd {{%\w+}} {{%\w+}} [[logical]]
   1514 OpCapability Shader
   1515 OpMemoryModel Logical GLSL450
   1516 OpEntryPoint Fragment %func "func"
   1517 OpExecutionMode %func OriginUpperLeft
   1518 %void = OpTypeVoid
   1519 %bool = OpTypeBool
   1520 %false = OpConstantFalse %bool
   1521 %true = OpConstantTrue %bool
   1522 %func_ty = OpTypeFunction %void
   1523 %func = OpFunction %void None %func_ty
   1524 %1 = OpLabel
   1525 OpSelectionMerge %2 None
   1526 OpBranchConditional %false %3 %4
   1527 %3 = OpLabel
   1528 %12 = OpLogicalNot %bool %true
   1529 OpBranch %2
   1530 %4 = OpLabel
   1531 OpSelectionMerge %14 None
   1532 OpBranchConditional %false %5 %6
   1533 %5 = OpLabel
   1534 %10 = OpLogicalAnd %bool %true %false
   1535 OpBranch %7
   1536 %6 = OpLabel
   1537 %11 = OpLogicalOr %bool %true %false
   1538 OpBranch %7
   1539 %7 = OpLabel
   1540 ; This phi is in a block preceeding the merge %14!
   1541 %8 = OpPhi %bool %10 %5 %11 %6
   1542 OpBranch %14
   1543 %14 = OpLabel
   1544 OpBranch %2
   1545 %2 = OpLabel
   1546 %9 = OpPhi %bool %12 %3 %8 %14
   1547 %13 = OpLogicalAnd %bool %true %9
   1548 OpReturn
   1549 OpFunctionEnd
   1550 )";
   1551 
   1552   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1553 }
   1554 
   1555 TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksFloating) {
   1556   const std::string text = R"(
   1557 ; CHECK: OpFunction
   1558 ; CHECK-NEXT: OpLabel
   1559 ; CHECK-NEXT: OpReturn
   1560 ; CHECK-NEXT: OpFunctionEnd
   1561 OpCapability Kernel
   1562 OpCapability Linkage
   1563 OpMemoryModel Logical OpenCL
   1564 OpName %func "func"
   1565 OpDecorate %func LinkageAttributes "func" Export
   1566 %void = OpTypeVoid
   1567 %1 = OpTypeFunction %void
   1568 %func = OpFunction %void None %1
   1569 %2 = OpLabel
   1570 OpReturn
   1571 %3 = OpLabel
   1572 OpReturn
   1573 OpFunctionEnd
   1574 )";
   1575 
   1576   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1577 }
   1578 
   1579 TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksFloatingJoin) {
   1580   const std::string text = R"(
   1581 ; CHECK: OpFunction
   1582 ; CHECK-NEXT: OpFunctionParameter
   1583 ; CHECK-NEXT: OpLabel
   1584 ; CHECK-NEXT: OpReturn
   1585 ; CHECK-NEXT: OpFunctionEnd
   1586 OpCapability Kernel
   1587 OpCapability Linkage
   1588 OpMemoryModel Logical OpenCL
   1589 OpName %func "func"
   1590 OpDecorate %func LinkageAttributes "func" Export
   1591 %void = OpTypeVoid
   1592 %bool = OpTypeBool
   1593 %false = OpConstantFalse %bool
   1594 %true = OpConstantTrue %bool
   1595 %1 = OpTypeFunction %void %bool
   1596 %func = OpFunction %void None %1
   1597 %bool_param = OpFunctionParameter %bool
   1598 %2 = OpLabel
   1599 OpReturn
   1600 %3 = OpLabel
   1601 OpSelectionMerge %6 None
   1602 OpBranchConditional %bool_param %4 %5
   1603 %4 = OpLabel
   1604 OpBranch %6
   1605 %5 = OpLabel
   1606 OpBranch %6
   1607 %6 = OpLabel
   1608 %7 = OpPhi %bool %true %4 %false %6
   1609 OpReturn
   1610 OpFunctionEnd
   1611 )";
   1612 
   1613   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1614 }
   1615 
   1616 TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksDeadPhi) {
   1617   const std::string text = R"(
   1618 ; CHECK: OpFunction
   1619 ; CHECK-NEXT: OpFunctionParameter
   1620 ; CHECK-NEXT: OpLabel
   1621 ; CHECK-NEXT: OpBranch [[label:%\w+]]
   1622 ; CHECK-NEXT: [[label]] = OpLabel
   1623 ; CHECK-NEXT: OpLogicalNot %bool %true
   1624 ; CHECK-NEXT: OpReturn
   1625 ; CHECK-NEXT: OpFunctionEnd
   1626 OpCapability Kernel
   1627 OpCapability Linkage
   1628 OpMemoryModel Logical OpenCL
   1629 OpName %func "func"
   1630 OpDecorate %func LinkageAttributes "func" Export
   1631 %void = OpTypeVoid
   1632 %bool = OpTypeBool
   1633 %false = OpConstantFalse %bool
   1634 %true = OpConstantTrue %bool
   1635 %1 = OpTypeFunction %void %bool
   1636 %func = OpFunction %void None %1
   1637 %bool_param = OpFunctionParameter %bool
   1638 %2 = OpLabel
   1639 OpBranch %3
   1640 %4 = OpLabel
   1641 OpBranch %3
   1642 %3 = OpLabel
   1643 %5 = OpPhi %bool %true %2 %false %4
   1644 %6 = OpLogicalNot %bool %5
   1645 OpReturn
   1646 OpFunctionEnd
   1647 )";
   1648 
   1649   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1650 }
   1651 
   1652 TEST_F(DeadBranchElimTest, RemoveUnreachableBlocksPartiallyDeadPhi) {
   1653   const std::string text = R"(
   1654 ; CHECK: OpFunction
   1655 ; CHECK-NEXT: [[param:%\w+]] = OpFunctionParameter
   1656 ; CHECK-NEXT: OpLabel
   1657 ; CHECK-NEXT: OpBranchConditional [[param]] [[merge:%\w+]] [[br:%\w+]]
   1658 ; CHECK-NEXT: [[merge]] = OpLabel
   1659 ; CHECK-NEXT: [[phi:%\w+]] = OpPhi %bool %true %2 %false [[br]]
   1660 ; CHECK-NEXT: OpLogicalNot %bool [[phi]]
   1661 ; CHECK-NEXT: OpReturn
   1662 ; CHECK-NEXT: [[br]] = OpLabel
   1663 ; CHECK-NEXT: OpBranch [[merge]]
   1664 ; CHECK-NEXT: OpFunctionEnd
   1665 OpCapability Kernel
   1666 OpCapability Linkage
   1667 OpMemoryModel Logical OpenCL
   1668 OpName %func "func"
   1669 OpDecorate %func LinkageAttributes "func" Export
   1670 %void = OpTypeVoid
   1671 %bool = OpTypeBool
   1672 %false = OpConstantFalse %bool
   1673 %true = OpConstantTrue %bool
   1674 %1 = OpTypeFunction %void %bool
   1675 %func = OpFunction %void None %1
   1676 %bool_param = OpFunctionParameter %bool
   1677 %2 = OpLabel
   1678 OpBranchConditional %bool_param %3 %7
   1679 %7 = OpLabel
   1680 OpBranch %3
   1681 %4 = OpLabel
   1682 OpBranch %3
   1683 %3 = OpLabel
   1684 %5 = OpPhi %bool %true %2 %false %7 %false %4
   1685 %6 = OpLogicalNot %bool %5
   1686 OpReturn
   1687 OpFunctionEnd
   1688 )";
   1689 
   1690   SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
   1691   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1692 }
   1693 
   1694 TEST_F(DeadBranchElimTest, LiveHeaderDeadPhi) {
   1695   const std::string text = R"(
   1696 ; CHECK: OpLabel
   1697 ; CHECK-NOT: OpBranchConditional
   1698 ; CHECK-NOT: OpPhi
   1699 ; CHECK: OpLogicalNot %bool %false
   1700 OpCapability Kernel
   1701 OpCapability Linkage
   1702 OpMemoryModel Logical OpenCL
   1703 OpName %func "func"
   1704 OpDecorate %func LinkageAttributes "func" Export
   1705 %void = OpTypeVoid
   1706 %bool = OpTypeBool
   1707 %true = OpConstantTrue %bool
   1708 %false = OpConstantFalse %bool
   1709 %func_ty = OpTypeFunction %void
   1710 %func = OpFunction %void None %func_ty
   1711 %1 = OpLabel
   1712 OpSelectionMerge %3 None
   1713 OpBranchConditional %true %2 %3
   1714 %2 = OpLabel
   1715 OpBranch %3
   1716 %3 = OpLabel
   1717 %5 = OpPhi %bool %true %3 %false %2
   1718 %6 = OpLogicalNot %bool %5
   1719 OpReturn
   1720 OpFunctionEnd
   1721 )";
   1722 
   1723   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1724 }
   1725 
   1726 TEST_F(DeadBranchElimTest, ExtraBackedgeBlocksLive) {
   1727   const std::string text = R"(
   1728 ; CHECK: [[entry:%\w+]] = OpLabel
   1729 ; CHECK-NOT: OpSelectionMerge
   1730 ; CHECK: OpBranch [[header:%\w+]]
   1731 ; CHECK-NEXT: [[header]] = OpLabel
   1732 ; CHECK-NEXT: OpPhi %bool %true [[entry]] %false [[backedge:%\w+]]
   1733 ; CHECK-NEXT: OpLoopMerge
   1734 OpCapability Kernel
   1735 OpCapability Linkage
   1736 OpMemoryModel Logical OpenCL
   1737 OpName %func "func"
   1738 OpDecorate %func LinkageAttributes "func" Export
   1739 %void = OpTypeVoid
   1740 %bool = OpTypeBool
   1741 %true = OpConstantTrue %bool
   1742 %false = OpConstantFalse %bool
   1743 %func_ty = OpTypeFunction %void %bool
   1744 %func = OpFunction %void None %func_ty
   1745 %param = OpFunctionParameter %bool
   1746 %entry = OpLabel
   1747 OpSelectionMerge %if_merge None
   1748 ; This dead branch is included to ensure the pass does work.
   1749 OpBranchConditional %false %if_merge %loop_header
   1750 %loop_header = OpLabel
   1751 ; Both incoming edges are live, so the phi should be untouched.
   1752 %phi = OpPhi %bool %true %entry %false %backedge
   1753 OpLoopMerge %loop_merge %continue None
   1754 OpBranchConditional %param %loop_merge %continue
   1755 %continue = OpLabel
   1756 OpBranch %backedge
   1757 %backedge = OpLabel
   1758 OpBranch %loop_header
   1759 %loop_merge = OpLabel
   1760 OpBranch %if_merge
   1761 %if_merge = OpLabel
   1762 OpReturn
   1763 OpFunctionEnd
   1764 )";
   1765 
   1766   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1767 }
   1768 
   1769 TEST_F(DeadBranchElimTest, ExtraBackedgeBlocksUnreachable) {
   1770   const std::string text = R"(
   1771 ; CHECK: [[entry:%\w+]] = OpLabel
   1772 ; CHECK-NEXT: OpBranch [[header:%\w+]]
   1773 ; CHECK-NEXT: [[header]] = OpLabel
   1774 ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
   1775 ; CHECK-NEXT: OpBranch [[merge]]
   1776 ; CHECK-NEXT: [[merge]] = OpLabel
   1777 ; CHECK-NEXT: OpReturn
   1778 ; CHECK-NEXT: [[continue]] = OpLabel
   1779 ; CHECK-NEXT: OpBranch [[header]]
   1780 OpCapability Kernel
   1781 OpCapability Linkage
   1782 OpMemoryModel Logical OpenCL
   1783 OpName %func "func"
   1784 OpDecorate %func LinkageAttributes "func" Export
   1785 %void = OpTypeVoid
   1786 %bool = OpTypeBool
   1787 %true = OpConstantTrue %bool
   1788 %false = OpConstantFalse %bool
   1789 %func_ty = OpTypeFunction %void %bool
   1790 %func = OpFunction %void None %func_ty
   1791 %param = OpFunctionParameter %bool
   1792 %entry = OpLabel
   1793 OpBranch %loop_header
   1794 %loop_header = OpLabel
   1795 ; Since the continue is unreachable, %backedge will be removed. The phi will
   1796 ; instead require an edge from %continue.
   1797 %phi = OpPhi %bool %true %entry %false %backedge
   1798 OpLoopMerge %merge %continue None
   1799 OpBranch %merge
   1800 %continue = OpLabel
   1801 OpBranch %backedge
   1802 %backedge = OpLabel
   1803 OpBranch %loop_header
   1804 %merge = OpLabel
   1805 OpReturn
   1806 OpFunctionEnd
   1807 )";
   1808 
   1809   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1810 }
   1811 
   1812 TEST_F(DeadBranchElimTest, NoUnnecessaryChanges) {
   1813   const std::string text = R"(
   1814 OpCapability Shader
   1815 OpMemoryModel Logical GLSL450
   1816 OpEntryPoint Fragment %func "func"
   1817 %void = OpTypeVoid
   1818 %bool = OpTypeBool
   1819 %true = OpConstantTrue %bool
   1820 %undef = OpUndef %bool
   1821 %functy = OpTypeFunction %void
   1822 %func = OpFunction %void None %functy
   1823 %1 = OpLabel
   1824 OpBranch %2
   1825 %2 = OpLabel
   1826 OpLoopMerge %4 %5 None
   1827 OpBranch %6
   1828 %6 = OpLabel
   1829 OpReturn
   1830 %5 = OpLabel
   1831 OpBranch %2
   1832 %4 = OpLabel
   1833 OpUnreachable
   1834 OpFunctionEnd
   1835 )";
   1836 
   1837   auto result = SinglePassRunToBinary<DeadBranchElimPass>(text, true);
   1838   EXPECT_EQ(std::get<1>(result), Pass::Status::SuccessWithoutChange);
   1839 }
   1840 
   1841 TEST_F(DeadBranchElimTest, ExtraBackedgePartiallyDead) {
   1842   const std::string text = R"(
   1843 ; CHECK: OpLabel
   1844 ; CHECK: [[header:%\w+]] = OpLabel
   1845 ; CHECK: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
   1846 ; CHECK: [[merge]] = OpLabel
   1847 ; CHECK: [[continue]] = OpLabel
   1848 ; CHECK: OpBranch [[extra:%\w+]]
   1849 ; CHECK: [[extra]] = OpLabel
   1850 ; CHECK-NOT: OpSelectionMerge
   1851 ; CHECK-NEXT: OpBranch [[else:%\w+]]
   1852 ; CHECK-NEXT: [[else]] = OpLabel
   1853 ; CHECK-NEXT: OpLogicalOr
   1854 ; CHECK-NEXT: OpBranch [[backedge:%\w+]]
   1855 ; CHECK-NEXT: [[backedge:%\w+]] = OpLabel
   1856 ; CHECK-NEXT: OpBranch [[header]]
   1857 OpCapability Kernel
   1858 OpCapability Linkage
   1859 OpMemoryModel Logical OpenCL
   1860 OpName %func "func"
   1861 OpDecorate %func LinkageAttributes "func" Export
   1862 %void = OpTypeVoid
   1863 %bool = OpTypeBool
   1864 %true = OpConstantTrue %bool
   1865 %false = OpConstantFalse %bool
   1866 %func_ty = OpTypeFunction %void %bool
   1867 %func = OpFunction %void None %func_ty
   1868 %param = OpFunctionParameter %bool
   1869 %entry = OpLabel
   1870 OpBranch %loop_header
   1871 %loop_header = OpLabel
   1872 OpLoopMerge %loop_merge %continue None
   1873 OpBranchConditional %param %loop_merge %continue
   1874 %continue = OpLabel
   1875 OpBranch %extra
   1876 %extra = OpLabel
   1877 OpSelectionMerge %backedge None
   1878 OpBranchConditional %false %then %else
   1879 %then = OpLabel
   1880 %and = OpLogicalAnd %bool %true %false
   1881 OpBranch %backedge
   1882 %else = OpLabel
   1883 %or = OpLogicalOr %bool %true %false
   1884 OpBranch %backedge
   1885 %backedge = OpLabel
   1886 OpBranch %loop_header
   1887 %loop_merge = OpLabel
   1888 OpReturn
   1889 OpFunctionEnd
   1890 )";
   1891 
   1892   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1893 }
   1894 
   1895 TEST_F(DeadBranchElimTest, UnreachableContinuePhiInMerge) {
   1896   const std::string text = R"(
   1897 ; CHECK: [[entry:%\w+]] = OpLabel
   1898 ; CHECK-NEXT: OpBranch [[header:%\w+]]
   1899 ; CHECK-NEXT: [[header]] = OpLabel
   1900 ; CHECK-NEXT: OpLoopMerge [[merge:%\w+]] [[continue:%\w+]] None
   1901 ; CHECK-NEXT: OpBranch [[label:%\w+]]
   1902 ; CHECK-NEXT: [[label]] = OpLabel
   1903 ; CHECK-NEXT: [[fadd:%\w+]] = OpFAdd
   1904 ; CHECK-NEXT: OpBranch [[label:%\w+]]
   1905 ; CHECK-NEXT: [[label]] = OpLabel
   1906 ; CHECK-NEXT: OpBranch [[merge]]
   1907 ; CHECK-NEXT: [[continue]] = OpLabel
   1908 ; CHECK-NEXT: OpBranch [[header]]
   1909 ; CHECK-NEXT: [[merge]] = OpLabel
   1910 ; CHECK-NEXT: OpStore {{%\w+}} [[fadd]]
   1911                OpCapability Shader
   1912           %1 = OpExtInstImport "GLSL.std.450"
   1913                OpMemoryModel Logical GLSL450
   1914                OpEntryPoint Fragment %main "main" %o
   1915                OpExecutionMode %main OriginUpperLeft
   1916                OpSource GLSL 430
   1917                OpSourceExtension "GL_GOOGLE_cpp_style_line_directive"
   1918                OpSourceExtension "GL_GOOGLE_include_directive"
   1919                OpName %main "main"
   1920                OpName %o "o"
   1921                OpName %S "S"
   1922                OpMemberName %S 0 "a"
   1923                OpName %U_t "U_t"
   1924                OpMemberName %U_t 0 "g_F"
   1925                OpMemberName %U_t 1 "g_F2"
   1926                OpDecorate %o Location 0
   1927                OpMemberDecorate %S 0 Offset 0
   1928                OpMemberDecorate %U_t 0 Volatile
   1929                OpMemberDecorate %U_t 0 Offset 0
   1930                OpMemberDecorate %U_t 1 Offset 4
   1931                OpDecorate %U_t BufferBlock
   1932        %void = OpTypeVoid
   1933           %7 = OpTypeFunction %void
   1934       %float = OpTypeFloat 32
   1935 %_ptr_Function_float = OpTypePointer Function %float
   1936     %float_0 = OpConstant %float 0
   1937         %int = OpTypeInt 32 1
   1938 %_ptr_Function_int = OpTypePointer Function %int
   1939       %int_0 = OpConstant %int 0
   1940      %int_10 = OpConstant %int 10
   1941        %bool = OpTypeBool
   1942        %true = OpConstantTrue %bool
   1943     %float_1 = OpConstant %float 1
   1944     %float_5 = OpConstant %float 5
   1945       %int_1 = OpConstant %int 1
   1946 %_ptr_Output_float = OpTypePointer Output %float
   1947           %o = OpVariable %_ptr_Output_float Output
   1948           %S = OpTypeStruct %float
   1949         %U_t = OpTypeStruct %S %S
   1950 %_ptr_Uniform_U_t = OpTypePointer Uniform %U_t
   1951        %main = OpFunction %void None %7
   1952          %22 = OpLabel
   1953                OpBranch %23
   1954          %23 = OpLabel
   1955          %24 = OpPhi %float %float_0 %22 %25 %26
   1956          %27 = OpPhi %int %int_0 %22 %28 %26
   1957                OpLoopMerge %29 %26 None
   1958                OpBranch %40
   1959          %40 = OpLabel
   1960          %25 = OpFAdd %float %24 %float_1
   1961                OpSelectionMerge %30 None
   1962                OpBranchConditional %true %31 %30
   1963          %31 = OpLabel
   1964                OpBranch %29
   1965          %30 = OpLabel
   1966                OpBranch %26
   1967          %26 = OpLabel
   1968          %28 = OpIAdd %int %27 %int_1
   1969          %32 = OpSLessThan %bool %27 %int_10
   1970 ; continue block branches to the header or another none dead block.
   1971                OpBranchConditional %32 %23 %29
   1972          %29 = OpLabel
   1973          %33 = OpPhi %float %24 %26 %25 %31
   1974                OpStore %o %33
   1975                OpReturn
   1976                OpFunctionEnd
   1977 )";
   1978 
   1979   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   1980 }
   1981 
   1982 TEST_F(DeadBranchElimTest, NonStructuredIf) {
   1983   const std::string text = R"(
   1984 ; CHECK-NOT: OpBranchConditional
   1985 OpCapability Kernel
   1986 OpCapability Linkage
   1987 OpMemoryModel Logical OpenCL
   1988 OpDecorate %func LinkageAttributes "func" Export
   1989 %void = OpTypeVoid
   1990 %bool = OpTypeBool
   1991 %true = OpConstantTrue %bool
   1992 %functy = OpTypeFunction %void
   1993 %func = OpFunction %void None %functy
   1994 %entry = OpLabel
   1995 OpBranchConditional %true %then %else
   1996 %then = OpLabel
   1997 OpBranch %final
   1998 %else = OpLabel
   1999 OpBranch %final
   2000 %final = OpLabel
   2001 OpReturn
   2002 OpFunctionEnd
   2003 )";
   2004 
   2005   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   2006 }
   2007 
   2008 TEST_F(DeadBranchElimTest, ReorderBlocks) {
   2009   const std::string text = R"(
   2010 ; CHECK: OpLabel
   2011 ; CHECK: OpBranch [[label:%\w+]]
   2012 ; CHECK: [[label:%\w+]] = OpLabel
   2013 ; CHECK-NEXT: OpLogicalNot
   2014 ; CHECK-NEXT: OpBranch [[label:%\w+]]
   2015 ; CHECK: [[label]] = OpLabel
   2016 ; CHECK-NEXT: OpReturn
   2017 OpCapability Shader
   2018 OpMemoryModel Logical GLSL450
   2019 OpEntryPoint Fragment %func "func"
   2020 OpExecutionMode %func OriginUpperLeft
   2021 %void = OpTypeVoid
   2022 %bool = OpTypeBool
   2023 %true = OpConstantTrue %bool
   2024 %func_ty = OpTypeFunction %void
   2025 %func = OpFunction %void None %func_ty
   2026 %1 = OpLabel
   2027 OpSelectionMerge %3 None
   2028 OpBranchConditional %true %2 %3
   2029 %3 = OpLabel
   2030 OpReturn
   2031 %2 = OpLabel
   2032 %not = OpLogicalNot %bool %true
   2033 OpBranch %3
   2034 OpFunctionEnd
   2035 )";
   2036 
   2037   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   2038 }
   2039 
   2040 TEST_F(DeadBranchElimTest, ReorderBlocksMultiple) {
   2041   // Checks are not important. The validation post optimization is the
   2042   // important part.
   2043   const std::string text = R"(
   2044 ; CHECK: OpLabel
   2045 OpCapability Shader
   2046 OpMemoryModel Logical GLSL450
   2047 OpEntryPoint Fragment %func "func"
   2048 OpExecutionMode %func OriginUpperLeft
   2049 %void = OpTypeVoid
   2050 %bool = OpTypeBool
   2051 %true = OpConstantTrue %bool
   2052 %func_ty = OpTypeFunction %void
   2053 %func = OpFunction %void None %func_ty
   2054 %1 = OpLabel
   2055 OpSelectionMerge %3 None
   2056 OpBranchConditional %true %2 %3
   2057 %3 = OpLabel
   2058 OpReturn
   2059 %2 = OpLabel
   2060 OpBranch %4
   2061 %4 = OpLabel
   2062 OpBranch %3
   2063 OpFunctionEnd
   2064 )";
   2065 
   2066   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   2067 }
   2068 
   2069 TEST_F(DeadBranchElimTest, ReorderBlocksMultiple2) {
   2070   // Checks are not important. The validation post optimization is the
   2071   // important part.
   2072   const std::string text = R"(
   2073 ; CHECK: OpLabel
   2074 OpCapability Shader
   2075 OpMemoryModel Logical GLSL450
   2076 OpEntryPoint Fragment %func "func"
   2077 OpExecutionMode %func OriginUpperLeft
   2078 %void = OpTypeVoid
   2079 %bool = OpTypeBool
   2080 %true = OpConstantTrue %bool
   2081 %func_ty = OpTypeFunction %void
   2082 %func = OpFunction %void None %func_ty
   2083 %1 = OpLabel
   2084 OpSelectionMerge %3 None
   2085 OpBranchConditional %true %2 %3
   2086 %3 = OpLabel
   2087 OpBranch %5
   2088 %5 = OpLabel
   2089 OpReturn
   2090 %2 = OpLabel
   2091 OpBranch %4
   2092 %4 = OpLabel
   2093 OpBranch %3
   2094 OpFunctionEnd
   2095 )";
   2096 
   2097   SinglePassRunAndMatch<DeadBranchElimPass>(text, true);
   2098 }
   2099 
   2100 TEST_F(DeadBranchElimTest, SelectionMergeWithEarlyExit1) {
   2101   // Checks  that if a selection merge construct contains a conditional branch
   2102   // to the merge node, then the OpSelectionMerge instruction is positioned
   2103   // correctly.
   2104   const std::string predefs = R"(
   2105 OpCapability Shader
   2106 %1 = OpExtInstImport "GLSL.std.450"
   2107 OpMemoryModel Logical GLSL450
   2108 OpEntryPoint Fragment %main "main"
   2109 OpExecutionMode %main OriginUpperLeft
   2110 OpSource GLSL 140
   2111 %void = OpTypeVoid
   2112 %func_type = OpTypeFunction %void
   2113 %bool = OpTypeBool
   2114 %true = OpConstantTrue %bool
   2115 %undef_bool = OpUndef %bool
   2116 )";
   2117 
   2118   const std::string body =
   2119       R"(
   2120 ; CHECK: OpFunction
   2121 ; CHECK-NEXT: OpLabel
   2122 ; CHECK-NEXT: OpBranch [[taken_branch:%\w+]]
   2123 ; CHECK-NEXT: [[taken_branch]] = OpLabel
   2124 ; CHECK-NEXT: OpSelectionMerge [[merge:%\w+]]
   2125 ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[merge]] {{%\w+}}
   2126 %main = OpFunction %void None %func_type
   2127 %entry_bb = OpLabel
   2128 OpSelectionMerge %outer_merge None
   2129 OpBranchConditional %true %bb1 %bb3
   2130 %bb1 = OpLabel
   2131 OpBranchConditional %undef_bool %outer_merge %bb2
   2132 %bb2 = OpLabel
   2133 OpBranch %outer_merge
   2134 %bb3 = OpLabel
   2135 OpBranch %outer_merge
   2136 %outer_merge = OpLabel
   2137 OpReturn
   2138 OpFunctionEnd
   2139 )";
   2140 
   2141   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2142 }
   2143 
   2144 TEST_F(DeadBranchElimTest, SelectionMergeWithEarlyExit2) {
   2145   // Checks  that if a selection merge construct contains a conditional branch
   2146   // to the merge node, then the OpSelectionMerge instruction is positioned
   2147   // correctly.
   2148   const std::string predefs = R"(
   2149 OpCapability Shader
   2150 %1 = OpExtInstImport "GLSL.std.450"
   2151 OpMemoryModel Logical GLSL450
   2152 OpEntryPoint Fragment %main "main"
   2153 OpExecutionMode %main OriginUpperLeft
   2154 OpSource GLSL 140
   2155 %void = OpTypeVoid
   2156 %func_type = OpTypeFunction %void
   2157 %bool = OpTypeBool
   2158 %true = OpConstantTrue %bool
   2159 %undef_bool = OpUndef %bool
   2160 )";
   2161 
   2162   const std::string body =
   2163       R"(
   2164 ; CHECK: OpFunction
   2165 ; CHECK-NEXT: OpLabel
   2166 ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
   2167 ; CHECK-NEXT: [[bb1]] = OpLabel
   2168 ; CHECK-NEXT: OpSelectionMerge [[inner_merge:%\w+]]
   2169 ; CHECK: [[inner_merge]] = OpLabel
   2170 ; CHECK-NEXT: OpSelectionMerge [[outer_merge:%\w+]]
   2171 ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[outer_merge]:%\w+]] {{%\w+}}
   2172 ; CHECK: [[outer_merge]] = OpLabel
   2173 ; CHECK-NEXT: OpReturn
   2174 %main = OpFunction %void None %func_type
   2175 %entry_bb = OpLabel
   2176 OpSelectionMerge %outer_merge None
   2177 OpBranchConditional %true %bb1 %bb5
   2178 %bb1 = OpLabel
   2179 OpSelectionMerge %inner_merge None
   2180 OpBranchConditional %undef_bool %bb2 %bb3
   2181 %bb2 = OpLabel
   2182 OpBranch %inner_merge
   2183 %bb3 = OpLabel
   2184 OpBranch %inner_merge
   2185 %inner_merge = OpLabel
   2186 OpBranchConditional %undef_bool %outer_merge %bb4
   2187 %bb4 = OpLabel
   2188 OpBranch %outer_merge
   2189 %bb5 = OpLabel
   2190 OpBranch %outer_merge
   2191 %outer_merge = OpLabel
   2192 OpReturn
   2193 OpFunctionEnd
   2194 )";
   2195 
   2196   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2197 }
   2198 
   2199 TEST_F(DeadBranchElimTest, SelectionMergeWithConditionalExit) {
   2200   // Checks that if a selection merge construct contains a conditional branch
   2201   // to the merge node, then we keep the OpSelectionMerge on that branch.
   2202   const std::string predefs = R"(
   2203 OpCapability Shader
   2204 %1 = OpExtInstImport "GLSL.std.450"
   2205 OpMemoryModel Logical GLSL450
   2206 OpEntryPoint Fragment %main "main"
   2207 OpExecutionMode %main OriginUpperLeft
   2208 OpSource GLSL 140
   2209 %void = OpTypeVoid
   2210 %func_type = OpTypeFunction %void
   2211 %bool = OpTypeBool
   2212 %true = OpConstantTrue %bool
   2213 %uint = OpTypeInt 32 0
   2214 %undef_int = OpUndef %uint
   2215 )";
   2216 
   2217   const std::string body =
   2218       R"(
   2219 ; CHECK: OpLoopMerge [[loop_merge:%\w+]]
   2220 ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
   2221 ; CHECK: [[bb1]] = OpLabel
   2222 ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
   2223 ; CHECK: [[bb2]] = OpLabel
   2224 ; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None
   2225 ; CHECK-NEXT: OpSwitch {{%\w+}} [[sel_merge]] 1 [[bb3:%\w+]]
   2226 ; CHECK: [[bb3]] = OpLabel
   2227 ; CHECK-NEXT: OpBranch [[sel_merge]]
   2228 ; CHECK: [[sel_merge]] = OpLabel
   2229 ; CHECK-NEXT: OpBranch [[loop_merge]]
   2230 ; CHECK: [[loop_merge]] = OpLabel
   2231 ; CHECK-NEXT: OpReturn
   2232 %main = OpFunction %void None %func_type
   2233 %entry_bb = OpLabel
   2234 OpBranch %loop_header
   2235 %loop_header = OpLabel
   2236 OpLoopMerge %loop_merge %cont None
   2237 OpBranch %bb1
   2238 %bb1 = OpLabel
   2239 OpSelectionMerge %sel_merge None
   2240 OpBranchConditional %true %bb2 %bb4
   2241 %bb2 = OpLabel
   2242 OpSwitch %undef_int %sel_merge 1 %bb3
   2243 %bb3 = OpLabel
   2244 OpBranch %sel_merge
   2245 %bb4 = OpLabel
   2246 OpBranch %sel_merge
   2247 %sel_merge = OpLabel
   2248 OpBranch %loop_merge
   2249 %cont = OpLabel
   2250 OpBranch %loop_header
   2251 %loop_merge = OpLabel
   2252 OpReturn
   2253 OpFunctionEnd
   2254 )";
   2255 
   2256   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2257 }
   2258 
   2259 TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop) {
   2260   // Checks  that if a selection merge construct contains a conditional branch
   2261   // to a loop surrounding the selection merge, then we do not keep the
   2262   // OpSelectionMerge instruction.
   2263   const std::string predefs = R"(
   2264 OpCapability Shader
   2265 %1 = OpExtInstImport "GLSL.std.450"
   2266 OpMemoryModel Logical GLSL450
   2267 OpEntryPoint Fragment %main "main"
   2268 OpExecutionMode %main OriginUpperLeft
   2269 OpSource GLSL 140
   2270 %void = OpTypeVoid
   2271 %func_type = OpTypeFunction %void
   2272 %bool = OpTypeBool
   2273 %true = OpConstantTrue %bool
   2274 %undef_bool = OpUndef %bool
   2275 )";
   2276 
   2277   const std::string body =
   2278       R"(
   2279 ; CHECK: OpLoopMerge [[loop_merge:%\w+]]
   2280 ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
   2281 ; CHECK: [[bb1]] = OpLabel
   2282 ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
   2283 ; CHECK: [[bb2]] = OpLabel
   2284 ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_merge]]
   2285 ; CHECK: [[bb3]] = OpLabel
   2286 ; CHECK-NEXT: OpBranch [[sel_merge:%\w+]]
   2287 ; CHECK: [[sel_merge]] = OpLabel
   2288 ; CHECK-NEXT: OpBranch [[loop_merge]]
   2289 ; CHECK: [[loop_merge]] = OpLabel
   2290 ; CHECK-NEXT: OpReturn
   2291 %main = OpFunction %void None %func_type
   2292 %entry_bb = OpLabel
   2293 OpBranch %loop_header
   2294 %loop_header = OpLabel
   2295 OpLoopMerge %loop_merge %cont None
   2296 OpBranch %bb1
   2297 %bb1 = OpLabel
   2298 OpSelectionMerge %sel_merge None
   2299 OpBranchConditional %true %bb2 %bb4
   2300 %bb2 = OpLabel
   2301 OpBranchConditional %undef_bool %bb3 %loop_merge
   2302 %bb3 = OpLabel
   2303 OpBranch %sel_merge
   2304 %bb4 = OpLabel
   2305 OpBranch %sel_merge
   2306 %sel_merge = OpLabel
   2307 OpBranch %loop_merge
   2308 %cont = OpLabel
   2309 OpBranch %loop_header
   2310 %loop_merge = OpLabel
   2311 OpReturn
   2312 OpFunctionEnd
   2313 )";
   2314 
   2315   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2316 }
   2317 
   2318 TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue) {
   2319   // Checks  that if a selection merge construct contains a conditional branch
   2320   // to continue of a loop surrounding the selection merge, then we do not keep
   2321   // the OpSelectionMerge instruction.
   2322   const std::string predefs = R"(
   2323 OpCapability Shader
   2324 %1 = OpExtInstImport "GLSL.std.450"
   2325 OpMemoryModel Logical GLSL450
   2326 OpEntryPoint Fragment %main "main"
   2327 OpExecutionMode %main OriginUpperLeft
   2328 OpSource GLSL 140
   2329 %void = OpTypeVoid
   2330 %func_type = OpTypeFunction %void
   2331 %bool = OpTypeBool
   2332 %true = OpConstantTrue %bool
   2333 %undef_bool = OpUndef %bool
   2334 )";
   2335 
   2336   const std::string body =
   2337       R"(;
   2338 ; CHECK: OpLabel
   2339 ; CHECK: [[loop_header:%\w+]] = OpLabel
   2340 ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]]
   2341 ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
   2342 ; CHECK: [[bb1]] = OpLabel
   2343 ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
   2344 ; CHECK: [[bb2]] = OpLabel
   2345 ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_cont]]
   2346 ; CHECK: [[bb3]] = OpLabel
   2347 ; CHECK-NEXT: OpBranch [[sel_merge:%\w+]]
   2348 ; CHECK: [[sel_merge]] = OpLabel
   2349 ; CHECK-NEXT: OpBranch [[loop_merge]]
   2350 ; CHECK: [[loop_cont]] = OpLabel
   2351 ; CHECK-NEXT: OpBranch [[loop_header]]
   2352 ; CHECK: [[loop_merge]] = OpLabel
   2353 ; CHECK-NEXT: OpReturn
   2354 %main = OpFunction %void None %func_type
   2355 %entry_bb = OpLabel
   2356 OpBranch %loop_header
   2357 %loop_header = OpLabel
   2358 OpLoopMerge %loop_merge %cont None
   2359 OpBranch %bb1
   2360 %bb1 = OpLabel
   2361 OpSelectionMerge %sel_merge None
   2362 OpBranchConditional %true %bb2 %bb4
   2363 %bb2 = OpLabel
   2364 OpBranchConditional %undef_bool %bb3 %cont
   2365 %bb3 = OpLabel
   2366 OpBranch %sel_merge
   2367 %bb4 = OpLabel
   2368 OpBranch %sel_merge
   2369 %sel_merge = OpLabel
   2370 OpBranch %loop_merge
   2371 %cont = OpLabel
   2372 OpBranch %loop_header
   2373 %loop_merge = OpLabel
   2374 OpReturn
   2375 OpFunctionEnd
   2376 )";
   2377 
   2378   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2379 }
   2380 
   2381 TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop2) {
   2382   // Same as |SelectionMergeWithExitToLoop|, except the switch goes to the loop
   2383   // merge or the selection merge.  In this case, we do not need an
   2384   // OpSelectionMerge either.
   2385   const std::string predefs = R"(
   2386 OpCapability Shader
   2387 %1 = OpExtInstImport "GLSL.std.450"
   2388 OpMemoryModel Logical GLSL450
   2389 OpEntryPoint Fragment %main "main"
   2390 OpExecutionMode %main OriginUpperLeft
   2391 OpSource GLSL 140
   2392 %void = OpTypeVoid
   2393 %func_type = OpTypeFunction %void
   2394 %bool = OpTypeBool
   2395 %true = OpConstantTrue %bool
   2396 %undef_bool = OpUndef %bool
   2397 )";
   2398 
   2399   const std::string body =
   2400       R"(
   2401 ; CHECK: OpLoopMerge [[loop_merge:%\w+]]
   2402 ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
   2403 ; CHECK: [[bb1]] = OpLabel
   2404 ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
   2405 ; CHECK: [[bb2]] = OpLabel
   2406 ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge:%\w+]] [[loop_merge]]
   2407 ; CHECK: [[sel_merge]] = OpLabel
   2408 ; CHECK-NEXT: OpBranch [[loop_merge]]
   2409 ; CHECK: [[loop_merge]] = OpLabel
   2410 ; CHECK-NEXT: OpReturn
   2411 %main = OpFunction %void None %func_type
   2412 %entry_bb = OpLabel
   2413 OpBranch %loop_header
   2414 %loop_header = OpLabel
   2415 OpLoopMerge %loop_merge %cont None
   2416 OpBranch %bb1
   2417 %bb1 = OpLabel
   2418 OpSelectionMerge %sel_merge None
   2419 OpBranchConditional %true %bb2 %bb4
   2420 %bb2 = OpLabel
   2421 OpBranchConditional %undef_bool %sel_merge %loop_merge
   2422 %bb4 = OpLabel
   2423 OpBranch %sel_merge
   2424 %sel_merge = OpLabel
   2425 OpBranch %loop_merge
   2426 %cont = OpLabel
   2427 OpBranch %loop_header
   2428 %loop_merge = OpLabel
   2429 OpReturn
   2430 OpFunctionEnd
   2431 )";
   2432 
   2433   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2434 }
   2435 
   2436 TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue2) {
   2437   // Same as |SelectionMergeWithExitToLoopContinue|, except the branch goes to
   2438   // the loop continue or the selection merge.  In this case, we do not need an
   2439   // OpSelectionMerge either.
   2440   const std::string predefs = R"(
   2441 OpCapability Shader
   2442 %1 = OpExtInstImport "GLSL.std.450"
   2443 OpMemoryModel Logical GLSL450
   2444 OpEntryPoint Fragment %main "main"
   2445 OpExecutionMode %main OriginUpperLeft
   2446 OpSource GLSL 140
   2447 %void = OpTypeVoid
   2448 %func_type = OpTypeFunction %void
   2449 %bool = OpTypeBool
   2450 %true = OpConstantTrue %bool
   2451 %undef_bool = OpUndef %bool
   2452 )";
   2453 
   2454   const std::string body =
   2455       R"(
   2456 ; CHECK: OpLabel
   2457 ; CHECK: [[loop_header:%\w+]] = OpLabel
   2458 ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]]
   2459 ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
   2460 ; CHECK: [[bb1]] = OpLabel
   2461 ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
   2462 ; CHECK: [[bb2]] = OpLabel
   2463 ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[sel_merge:%\w+]] [[loop_cont]]
   2464 ; CHECK: [[sel_merge]] = OpLabel
   2465 ; CHECK-NEXT: OpBranch [[loop_merge]]
   2466 ; CHECK: [[loop_cont]] = OpLabel
   2467 ; CHECK: OpBranch [[loop_header]]
   2468 ; CHECK: [[loop_merge]] = OpLabel
   2469 ; CHECK-NEXT: OpReturn
   2470 %main = OpFunction %void None %func_type
   2471 %entry_bb = OpLabel
   2472 OpBranch %loop_header
   2473 %loop_header = OpLabel
   2474 OpLoopMerge %loop_merge %cont None
   2475 OpBranch %bb1
   2476 %bb1 = OpLabel
   2477 OpSelectionMerge %sel_merge None
   2478 OpBranchConditional %true %bb2 %bb4
   2479 %bb2 = OpLabel
   2480 OpBranchConditional %undef_bool %sel_merge %cont
   2481 %bb4 = OpLabel
   2482 OpBranch %sel_merge
   2483 %sel_merge = OpLabel
   2484 OpBranch %loop_merge
   2485 %cont = OpLabel
   2486 OpBranch %loop_header
   2487 %loop_merge = OpLabel
   2488 OpReturn
   2489 OpFunctionEnd
   2490 )";
   2491 
   2492   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2493 }
   2494 
   2495 TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop3) {
   2496   // Checks that if a selection merge construct contains a conditional branch
   2497   // to the merge of a surrounding loop, the selection merge, and another block
   2498   // inside the selection merge, then we must keep the OpSelectionMerge
   2499   // instruction on that branch.
   2500   const std::string predefs = R"(
   2501 OpCapability Shader
   2502 %1 = OpExtInstImport "GLSL.std.450"
   2503 OpMemoryModel Logical GLSL450
   2504 OpEntryPoint Fragment %main "main"
   2505 OpExecutionMode %main OriginUpperLeft
   2506 OpSource GLSL 140
   2507 %void = OpTypeVoid
   2508 %func_type = OpTypeFunction %void
   2509 %bool = OpTypeBool
   2510 %true = OpConstantTrue %bool
   2511 %uint = OpTypeInt 32 0
   2512 %undef_int = OpUndef %uint
   2513 )";
   2514 
   2515   const std::string body =
   2516       R"(
   2517 ; CHECK: OpLoopMerge [[loop_merge:%\w+]]
   2518 ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
   2519 ; CHECK: [[bb1]] = OpLabel
   2520 ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
   2521 ; CHECK: [[bb2]] = OpLabel
   2522 ; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None
   2523 ; CHECK-NEXT: OpSwitch {{%\w+}} [[sel_merge]] 0 [[loop_merge]] 1 [[bb3:%\w+]]
   2524 ; CHECK: [[bb3]] = OpLabel
   2525 ; CHECK-NEXT: OpBranch [[sel_merge]]
   2526 ; CHECK: [[sel_merge]] = OpLabel
   2527 ; CHECK-NEXT: OpBranch [[loop_merge]]
   2528 ; CHECK: [[loop_merge]] = OpLabel
   2529 ; CHECK-NEXT: OpReturn
   2530 %main = OpFunction %void None %func_type
   2531 %entry_bb = OpLabel
   2532 OpBranch %loop_header
   2533 %loop_header = OpLabel
   2534 OpLoopMerge %loop_merge %cont None
   2535 OpBranch %bb1
   2536 %bb1 = OpLabel
   2537 OpSelectionMerge %sel_merge None
   2538 OpBranchConditional %true %bb2 %bb4
   2539 %bb2 = OpLabel
   2540 OpSwitch %undef_int %sel_merge 0 %loop_merge 1 %bb3
   2541 %bb3 = OpLabel
   2542 OpBranch %sel_merge
   2543 %bb4 = OpLabel
   2544 OpBranch %sel_merge
   2545 %sel_merge = OpLabel
   2546 OpBranch %loop_merge
   2547 %cont = OpLabel
   2548 OpBranch %loop_header
   2549 %loop_merge = OpLabel
   2550 OpReturn
   2551 OpFunctionEnd
   2552 )";
   2553 
   2554   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2555 }
   2556 
   2557 TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue3) {
   2558   // Checks that if a selection merge construct contains a conditional branch
   2559   // to the merge of a surrounding loop, the selection merge, and another block
   2560   // inside the selection merge, then we must keep the OpSelectionMerge
   2561   // instruction on that branch.
   2562   const std::string predefs = R"(
   2563 OpCapability Shader
   2564 %1 = OpExtInstImport "GLSL.std.450"
   2565 OpMemoryModel Logical GLSL450
   2566 OpEntryPoint Fragment %main "main"
   2567 OpExecutionMode %main OriginUpperLeft
   2568 OpSource GLSL 140
   2569 %void = OpTypeVoid
   2570 %func_type = OpTypeFunction %void
   2571 %bool = OpTypeBool
   2572 %true = OpConstantTrue %bool
   2573 %uint = OpTypeInt 32 0
   2574 %undef_int = OpUndef %uint
   2575 )";
   2576 
   2577   const std::string body =
   2578       R"(
   2579 ; CHECK: OpLabel
   2580 ; CHECK: [[loop_header:%\w+]] = OpLabel
   2581 ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_continue:%\w+]]
   2582 ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
   2583 ; CHECK: [[bb1]] = OpLabel
   2584 ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
   2585 ; CHECK: [[bb2]] = OpLabel
   2586 ; CHECK-NEXT: OpSelectionMerge [[sel_merge:%\w+]] None
   2587 ; CHECK-NEXT: OpSwitch {{%\w+}} [[sel_merge]] 0 [[loop_continue]] 1 [[bb3:%\w+]]
   2588 ; CHECK: [[bb3]] = OpLabel
   2589 ; CHECK-NEXT: OpBranch [[sel_merge]]
   2590 ; CHECK: [[sel_merge]] = OpLabel
   2591 ; CHECK-NEXT: OpBranch [[loop_merge]]
   2592 ; CHECK: [[loop_continue]] = OpLabel
   2593 ; CHECK-NEXT: OpBranch [[loop_header]]
   2594 ; CHECK: [[loop_merge]] = OpLabel
   2595 ; CHECK-NEXT: OpReturn
   2596 %main = OpFunction %void None %func_type
   2597 %entry_bb = OpLabel
   2598 OpBranch %loop_header
   2599 %loop_header = OpLabel
   2600 OpLoopMerge %loop_merge %cont None
   2601 OpBranch %bb1
   2602 %bb1 = OpLabel
   2603 OpSelectionMerge %sel_merge None
   2604 OpBranchConditional %true %bb2 %bb4
   2605 %bb2 = OpLabel
   2606 OpSwitch %undef_int %sel_merge 0 %cont 1 %bb3
   2607 %bb3 = OpLabel
   2608 OpBranch %sel_merge
   2609 %bb4 = OpLabel
   2610 OpBranch %sel_merge
   2611 %sel_merge = OpLabel
   2612 OpBranch %loop_merge
   2613 %cont = OpLabel
   2614 OpBranch %loop_header
   2615 %loop_merge = OpLabel
   2616 OpReturn
   2617 OpFunctionEnd
   2618 )";
   2619 
   2620   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2621 }
   2622 
   2623 TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoop4) {
   2624   // Same as |SelectionMergeWithExitToLoop|, except the branch in the selection
   2625   // construct is an |OpSwitch| instead of an |OpConditionalBranch|.  The
   2626   // OpSelectionMerge instruction is not needed in this case either.
   2627   const std::string predefs = R"(
   2628 OpCapability Shader
   2629 %1 = OpExtInstImport "GLSL.std.450"
   2630 OpMemoryModel Logical GLSL450
   2631 OpEntryPoint Fragment %main "main"
   2632 OpExecutionMode %main OriginUpperLeft
   2633 OpSource GLSL 140
   2634 %void = OpTypeVoid
   2635 %func_type = OpTypeFunction %void
   2636 %bool = OpTypeBool
   2637 %true = OpConstantTrue %bool
   2638 %uint = OpTypeInt 32 0
   2639 %undef_int = OpUndef %uint
   2640 )";
   2641 
   2642   const std::string body =
   2643       R"(
   2644 ; CHECK: OpLoopMerge [[loop_merge:%\w+]]
   2645 ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
   2646 ; CHECK: [[bb1]] = OpLabel
   2647 ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
   2648 ; CHECK: [[bb2]] = OpLabel
   2649 ; CHECK-NEXT: OpSwitch {{%\w+}} [[bb3:%\w+]] 0 [[loop_merge]] 1 [[bb3:%\w+]]
   2650 ; CHECK: [[bb3]] = OpLabel
   2651 ; CHECK-NEXT: OpBranch [[sel_merge:%\w+]]
   2652 ; CHECK: [[sel_merge]] = OpLabel
   2653 ; CHECK-NEXT: OpBranch [[loop_merge]]
   2654 ; CHECK: [[loop_merge]] = OpLabel
   2655 ; CHECK-NEXT: OpReturn
   2656 %main = OpFunction %void None %func_type
   2657 %entry_bb = OpLabel
   2658 OpBranch %loop_header
   2659 %loop_header = OpLabel
   2660 OpLoopMerge %loop_merge %cont None
   2661 OpBranch %bb1
   2662 %bb1 = OpLabel
   2663 OpSelectionMerge %sel_merge None
   2664 OpBranchConditional %true %bb2 %bb4
   2665 %bb2 = OpLabel
   2666 OpSwitch %undef_int %bb3 0 %loop_merge 1 %bb3
   2667 %bb3 = OpLabel
   2668 OpBranch %sel_merge
   2669 %bb4 = OpLabel
   2670 OpBranch %sel_merge
   2671 %sel_merge = OpLabel
   2672 OpBranch %loop_merge
   2673 %cont = OpLabel
   2674 OpBranch %loop_header
   2675 %loop_merge = OpLabel
   2676 OpReturn
   2677 OpFunctionEnd
   2678 )";
   2679 
   2680   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2681 }
   2682 
   2683 TEST_F(DeadBranchElimTest, SelectionMergeWithExitToLoopContinue4) {
   2684   // Same as |SelectionMergeWithExitToLoopContinue|, except the branch in the
   2685   // selection construct is an |OpSwitch| instead of an |OpConditionalBranch|.
   2686   // The OpSelectionMerge instruction is not needed in this case either.
   2687   const std::string predefs = R"(
   2688 OpCapability Shader
   2689 %1 = OpExtInstImport "GLSL.std.450"
   2690 OpMemoryModel Logical GLSL450
   2691 OpEntryPoint Fragment %main "main"
   2692 OpExecutionMode %main OriginUpperLeft
   2693 OpSource GLSL 140
   2694 %void = OpTypeVoid
   2695 %func_type = OpTypeFunction %void
   2696 %bool = OpTypeBool
   2697 %true = OpConstantTrue %bool
   2698 %uint = OpTypeInt 32 0
   2699 %undef_int = OpUndef %uint
   2700 )";
   2701 
   2702   const std::string body =
   2703       R"(
   2704 ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]]
   2705 ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
   2706 ; CHECK: [[bb1]] = OpLabel
   2707 ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
   2708 ; CHECK: [[bb2]] = OpLabel
   2709 ; CHECK-NEXT: OpSwitch {{%\w+}} [[bb3:%\w+]] 0 [[loop_cont]] 1 [[bb3:%\w+]]
   2710 ; CHECK: [[bb3]] = OpLabel
   2711 ; CHECK-NEXT: OpBranch [[sel_merge:%\w+]]
   2712 ; CHECK: [[sel_merge]] = OpLabel
   2713 ; CHECK-NEXT: OpBranch [[loop_merge]]
   2714 ; CHECK: [[loop_merge]] = OpLabel
   2715 ; CHECK-NEXT: OpReturn
   2716 %main = OpFunction %void None %func_type
   2717 %entry_bb = OpLabel
   2718 OpBranch %loop_header
   2719 %loop_header = OpLabel
   2720 OpLoopMerge %loop_merge %cont None
   2721 OpBranch %bb1
   2722 %bb1 = OpLabel
   2723 OpSelectionMerge %sel_merge None
   2724 OpBranchConditional %true %bb2 %bb4
   2725 %bb2 = OpLabel
   2726 OpSwitch %undef_int %bb3 0 %cont 1 %bb3
   2727 %bb3 = OpLabel
   2728 OpBranch %sel_merge
   2729 %bb4 = OpLabel
   2730 OpBranch %sel_merge
   2731 %sel_merge = OpLabel
   2732 OpBranch %loop_merge
   2733 %cont = OpLabel
   2734 OpBranch %loop_header
   2735 %loop_merge = OpLabel
   2736 OpReturn
   2737 OpFunctionEnd
   2738 )";
   2739 
   2740   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2741 }
   2742 
   2743 TEST_F(DeadBranchElimTest, SelectionMergeSameAsLoopContinue) {
   2744   // Same as |SelectionMergeWithExitToLoopContinue|, except the branch in the
   2745   // selection construct is an |OpSwitch| instead of an |OpConditionalBranch|.
   2746   // The OpSelectionMerge instruction is not needed in this case either.
   2747   const std::string predefs = R"(
   2748 OpCapability Shader
   2749 %1 = OpExtInstImport "GLSL.std.450"
   2750 OpMemoryModel Logical GLSL450
   2751 OpEntryPoint Fragment %main "main"
   2752 OpExecutionMode %main OriginUpperLeft
   2753 OpSource GLSL 140
   2754 %void = OpTypeVoid
   2755 %func_type = OpTypeFunction %void
   2756 %bool = OpTypeBool
   2757 %true = OpConstantTrue %bool
   2758 %uint = OpTypeInt 32 0
   2759 %undef_bool = OpUndef %bool
   2760 )";
   2761 
   2762   const std::string body =
   2763       R"(
   2764 ; CHECK: OpLabel
   2765 ; CHECK: [[loop_header:%\w+]] = OpLabel
   2766 ; CHECK: OpLoopMerge [[loop_merge:%\w+]] [[loop_cont:%\w+]]
   2767 ; CHECK-NEXT: OpBranch [[bb1:%\w+]]
   2768 ; CHECK: [[bb1]] = OpLabel
   2769 ; CHECK-NEXT: OpBranch [[bb2:%\w+]]
   2770 ; CHECK: [[bb2]] = OpLabel
   2771 ; CHECK-NEXT: OpSelectionMerge [[loop_cont]]
   2772 ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[bb3:%\w+]] [[loop_cont]]
   2773 ; CHECK: [[bb3]] = OpLabel
   2774 ; CHECK-NEXT: OpBranch [[loop_cont]]
   2775 ; CHECK: [[loop_cont]] = OpLabel
   2776 ; CHECK-NEXT: OpBranchConditional {{%\w+}} [[loop_header]] [[loop_merge]]
   2777 ; CHECK: [[loop_merge]] = OpLabel
   2778 ; CHECK-NEXT: OpReturn
   2779 %main = OpFunction %void None %func_type
   2780 %entry_bb = OpLabel
   2781 OpBranch %loop_header
   2782 %loop_header = OpLabel
   2783 OpLoopMerge %loop_merge %cont None
   2784 OpBranch %bb1
   2785 %bb1 = OpLabel
   2786 OpSelectionMerge %cont None
   2787 OpBranchConditional %true %bb2 %bb4
   2788 %bb2 = OpLabel
   2789 OpBranchConditional %undef_bool %bb3 %cont
   2790 %bb3 = OpLabel
   2791 OpBranch %cont
   2792 %bb4 = OpLabel
   2793 OpBranch %cont
   2794 %cont = OpLabel
   2795 OpBranchConditional %undef_bool %loop_header %loop_merge
   2796 %loop_merge = OpLabel
   2797 OpReturn
   2798 OpFunctionEnd
   2799 )";
   2800 
   2801   SinglePassRunAndMatch<DeadBranchElimPass>(predefs + body, true);
   2802 }
   2803 
   2804 TEST_F(DeadBranchElimTest, SelectionMergeWithNestedLoop) {
   2805   const std::string body =
   2806       R"(
   2807 ; CHECK: OpSelectionMerge [[merge1:%\w+]]
   2808 ; CHECK: [[merge1]] = OpLabel
   2809 ; CHECK-NEXT: OpBranch [[preheader:%\w+]]
   2810 ; CHECK: [[preheader]] = OpLabel
   2811 ; CHECK-NOT: OpLabel
   2812 ; CHECK: OpBranch [[header:%\w+]]
   2813 ; CHECK: [[header]] = OpLabel
   2814 ; CHECK-NOT: OpLabel
   2815 ; CHECK: OpLoopMerge [[merge2:%\w+]]
   2816 ; CHECK: [[merge2]] = OpLabel
   2817 ; CHECK-NEXT: OpUnreachable
   2818                  OpCapability Shader
   2819             %1 = OpExtInstImport "GLSL.std.450"
   2820                  OpMemoryModel Logical GLSL450
   2821                  OpEntryPoint Fragment %main "main"
   2822                  OpExecutionMode %main OriginUpperLeft
   2823                  OpSource ESSL 310
   2824                  OpName %main "main"
   2825                  OpName %h "h"
   2826                  OpName %i "i"
   2827          %void = OpTypeVoid
   2828             %3 = OpTypeFunction %void
   2829          %bool = OpTypeBool
   2830   %_ptr_Function_bool = OpTypePointer Function %bool
   2831          %true = OpConstantTrue %bool
   2832           %int = OpTypeInt 32 1
   2833   %_ptr_Function_int = OpTypePointer Function %int
   2834         %int_1 = OpConstant %int 1
   2835         %int_0 = OpConstant %int 0
   2836            %27 = OpUndef %bool
   2837          %main = OpFunction %void None %3
   2838             %5 = OpLabel
   2839             %h = OpVariable %_ptr_Function_bool Function
   2840             %i = OpVariable %_ptr_Function_int Function
   2841                  OpSelectionMerge %11 None
   2842                  OpBranchConditional %27 %10 %11
   2843            %10 = OpLabel
   2844                  OpBranch %11
   2845            %11 = OpLabel
   2846                  OpSelectionMerge %14 None
   2847                  OpBranchConditional %true %13 %14
   2848            %13 = OpLabel
   2849                  OpStore %i %int_1
   2850                  OpBranch %19
   2851            %19 = OpLabel
   2852                  OpLoopMerge %21 %22 None
   2853                  OpBranch %23
   2854            %23 = OpLabel
   2855            %26 = OpSGreaterThan %bool %int_1 %int_0
   2856                  OpBranchConditional %true %20 %21
   2857            %20 = OpLabel
   2858                  OpBranch %22
   2859            %22 = OpLabel
   2860                  OpBranch %19
   2861            %21 = OpLabel
   2862                  OpBranch %14
   2863            %14 = OpLabel
   2864                  OpReturn
   2865                  OpFunctionEnd
   2866 )";
   2867 
   2868   SinglePassRunAndMatch<DeadBranchElimPass>(body, true);
   2869 }
   2870 
   2871 // TODO(greg-lunarg): Add tests to verify handling of these cases:
   2872 //
   2873 //    More complex control flow
   2874 //    Others?
   2875 
   2876 }  // namespace
   2877 }  // namespace opt
   2878 }  // namespace spvtools
   2879