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 "source/opt/simplification_pass.h"
     19 #include "test/opt/pass_fixture.h"
     20 #include "test/opt/pass_utils.h"
     21 
     22 namespace spvtools {
     23 namespace opt {
     24 namespace {
     25 
     26 using InsertExtractElimTest = PassTest<::testing::Test>;
     27 
     28 TEST_F(InsertExtractElimTest, Simple) {
     29   // Note: The SPIR-V assembly has had store/load elimination
     30   // performed to allow the inserts and extracts to directly
     31   // reference each other.
     32   //
     33   // #version 140
     34   //
     35   // in vec4 BaseColor;
     36   //
     37   // struct S_t {
     38   //     vec4 v0;
     39   //     vec4 v1;
     40   // };
     41   //
     42   // void main()
     43   // {
     44   //     S_t s0;
     45   //     s0.v1 = BaseColor;
     46   //     gl_FragColor = s0.v1;
     47   // }
     48 
     49   const std::string predefs =
     50       R"(OpCapability Shader
     51 %1 = OpExtInstImport "GLSL.std.450"
     52 OpMemoryModel Logical GLSL450
     53 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
     54 OpExecutionMode %main OriginUpperLeft
     55 OpSource GLSL 140
     56 OpName %main "main"
     57 OpName %S_t "S_t"
     58 OpMemberName %S_t 0 "v0"
     59 OpMemberName %S_t 1 "v1"
     60 OpName %s0 "s0"
     61 OpName %BaseColor "BaseColor"
     62 OpName %gl_FragColor "gl_FragColor"
     63 %void = OpTypeVoid
     64 %8 = OpTypeFunction %void
     65 %float = OpTypeFloat 32
     66 %v4float = OpTypeVector %float 4
     67 %S_t = OpTypeStruct %v4float %v4float
     68 %_ptr_Function_S_t = OpTypePointer Function %S_t
     69 %int = OpTypeInt 32 1
     70 %int_1 = OpConstant %int 1
     71 %_ptr_Input_v4float = OpTypePointer Input %v4float
     72 %BaseColor = OpVariable %_ptr_Input_v4float Input
     73 %_ptr_Function_v4float = OpTypePointer Function %v4float
     74 %_ptr_Output_v4float = OpTypePointer Output %v4float
     75 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
     76 )";
     77 
     78   const std::string before =
     79       R"(%main = OpFunction %void None %8
     80 %17 = OpLabel
     81 %s0 = OpVariable %_ptr_Function_S_t Function
     82 %18 = OpLoad %v4float %BaseColor
     83 %19 = OpLoad %S_t %s0
     84 %20 = OpCompositeInsert %S_t %18 %19 1
     85 OpStore %s0 %20
     86 %21 = OpCompositeExtract %v4float %20 1
     87 OpStore %gl_FragColor %21
     88 OpReturn
     89 OpFunctionEnd
     90 )";
     91 
     92   const std::string after =
     93       R"(%main = OpFunction %void None %8
     94 %17 = OpLabel
     95 %s0 = OpVariable %_ptr_Function_S_t Function
     96 %18 = OpLoad %v4float %BaseColor
     97 %19 = OpLoad %S_t %s0
     98 %20 = OpCompositeInsert %S_t %18 %19 1
     99 OpStore %s0 %20
    100 OpStore %gl_FragColor %18
    101 OpReturn
    102 OpFunctionEnd
    103 )";
    104 
    105   SinglePassRunAndCheck<SimplificationPass>(predefs + before, predefs + after,
    106                                             true, true);
    107 }
    108 
    109 TEST_F(InsertExtractElimTest, OptimizeAcrossNonConflictingInsert) {
    110   // Note: The SPIR-V assembly has had store/load elimination
    111   // performed to allow the inserts and extracts to directly
    112   // reference each other.
    113   //
    114   // #version 140
    115   //
    116   // in vec4 BaseColor;
    117   //
    118   // struct S_t {
    119   //     vec4 v0;
    120   //     vec4 v1;
    121   // };
    122   //
    123   // void main()
    124   // {
    125   //     S_t s0;
    126   //     s0.v1 = BaseColor;
    127   //     s0.v0[2] = 0.0;
    128   //     gl_FragColor = s0.v1;
    129   // }
    130 
    131   const std::string predefs =
    132       R"(OpCapability Shader
    133 %1 = OpExtInstImport "GLSL.std.450"
    134 OpMemoryModel Logical GLSL450
    135 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
    136 OpExecutionMode %main OriginUpperLeft
    137 OpSource GLSL 140
    138 OpName %main "main"
    139 OpName %S_t "S_t"
    140 OpMemberName %S_t 0 "v0"
    141 OpMemberName %S_t 1 "v1"
    142 OpName %s0 "s0"
    143 OpName %BaseColor "BaseColor"
    144 OpName %gl_FragColor "gl_FragColor"
    145 %void = OpTypeVoid
    146 %8 = OpTypeFunction %void
    147 %float = OpTypeFloat 32
    148 %v4float = OpTypeVector %float 4
    149 %S_t = OpTypeStruct %v4float %v4float
    150 %_ptr_Function_S_t = OpTypePointer Function %S_t
    151 %int = OpTypeInt 32 1
    152 %int_1 = OpConstant %int 1
    153 %float_0 = OpConstant %float 0
    154 %_ptr_Input_v4float = OpTypePointer Input %v4float
    155 %BaseColor = OpVariable %_ptr_Input_v4float Input
    156 %_ptr_Function_v4float = OpTypePointer Function %v4float
    157 %_ptr_Output_v4float = OpTypePointer Output %v4float
    158 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    159 )";
    160 
    161   const std::string before =
    162       R"(%main = OpFunction %void None %8
    163 %18 = OpLabel
    164 %s0 = OpVariable %_ptr_Function_S_t Function
    165 %19 = OpLoad %v4float %BaseColor
    166 %20 = OpLoad %S_t %s0
    167 %21 = OpCompositeInsert %S_t %19 %20 1
    168 %22 = OpCompositeInsert %S_t %float_0 %21 0 2
    169 OpStore %s0 %22
    170 %23 = OpCompositeExtract %v4float %22 1
    171 OpStore %gl_FragColor %23
    172 OpReturn
    173 OpFunctionEnd
    174 )";
    175 
    176   const std::string after =
    177       R"(%main = OpFunction %void None %8
    178 %18 = OpLabel
    179 %s0 = OpVariable %_ptr_Function_S_t Function
    180 %19 = OpLoad %v4float %BaseColor
    181 %20 = OpLoad %S_t %s0
    182 %21 = OpCompositeInsert %S_t %19 %20 1
    183 %22 = OpCompositeInsert %S_t %float_0 %21 0 2
    184 OpStore %s0 %22
    185 OpStore %gl_FragColor %19
    186 OpReturn
    187 OpFunctionEnd
    188 )";
    189 
    190   SinglePassRunAndCheck<SimplificationPass>(predefs + before, predefs + after,
    191                                             true, true);
    192 }
    193 
    194 TEST_F(InsertExtractElimTest, OptimizeOpaque) {
    195   // SPIR-V not representable in GLSL; not generatable from HLSL
    196   // for the moment.
    197 
    198   const std::string predefs =
    199       R"(OpCapability Shader
    200 %1 = OpExtInstImport "GLSL.std.450"
    201 OpMemoryModel Logical GLSL450
    202 OpEntryPoint Fragment %main "main" %outColor %texCoords
    203 OpExecutionMode %main OriginUpperLeft
    204 OpSource GLSL 140
    205 OpName %main "main"
    206 OpName %S_t "S_t"
    207 OpMemberName %S_t 0 "v0"
    208 OpMemberName %S_t 1 "v1"
    209 OpMemberName %S_t 2 "smp"
    210 OpName %outColor "outColor"
    211 OpName %sampler15 "sampler15"
    212 OpName %s0 "s0"
    213 OpName %texCoords "texCoords"
    214 OpDecorate %sampler15 DescriptorSet 0
    215 %void = OpTypeVoid
    216 %9 = OpTypeFunction %void
    217 %float = OpTypeFloat 32
    218 %v2float = OpTypeVector %float 2
    219 %v4float = OpTypeVector %float 4
    220 %_ptr_Output_v4float = OpTypePointer Output %v4float
    221 %outColor = OpVariable %_ptr_Output_v4float Output
    222 %14 = OpTypeImage %float 2D 0 0 0 1 Unknown
    223 %15 = OpTypeSampledImage %14
    224 %S_t = OpTypeStruct %v2float %v2float %15
    225 %_ptr_Function_S_t = OpTypePointer Function %S_t
    226 %17 = OpTypeFunction %void %_ptr_Function_S_t
    227 %_ptr_UniformConstant_15 = OpTypePointer UniformConstant %15
    228 %_ptr_Function_15 = OpTypePointer Function %15
    229 %sampler15 = OpVariable %_ptr_UniformConstant_15 UniformConstant
    230 %int = OpTypeInt 32 1
    231 %int_0 = OpConstant %int 0
    232 %int_2 = OpConstant %int 2
    233 %_ptr_Function_v2float = OpTypePointer Function %v2float
    234 %_ptr_Input_v2float = OpTypePointer Input %v2float
    235 %texCoords = OpVariable %_ptr_Input_v2float Input
    236 )";
    237 
    238   const std::string before =
    239       R"(%main = OpFunction %void None %9
    240 %25 = OpLabel
    241 %s0 = OpVariable %_ptr_Function_S_t Function
    242 %26 = OpLoad %v2float %texCoords
    243 %27 = OpLoad %S_t %s0
    244 %28 = OpCompositeInsert %S_t %26 %27 0
    245 %29 = OpLoad %15 %sampler15
    246 %30 = OpCompositeInsert %S_t %29 %28 2
    247 OpStore %s0 %30
    248 %31 = OpCompositeExtract %15 %30 2
    249 %32 = OpCompositeExtract %v2float %30 0
    250 %33 = OpImageSampleImplicitLod %v4float %31 %32
    251 OpStore %outColor %33
    252 OpReturn
    253 OpFunctionEnd
    254 )";
    255 
    256   const std::string after =
    257       R"(%main = OpFunction %void None %9
    258 %25 = OpLabel
    259 %s0 = OpVariable %_ptr_Function_S_t Function
    260 %26 = OpLoad %v2float %texCoords
    261 %27 = OpLoad %S_t %s0
    262 %28 = OpCompositeInsert %S_t %26 %27 0
    263 %29 = OpLoad %15 %sampler15
    264 %30 = OpCompositeInsert %S_t %29 %28 2
    265 OpStore %s0 %30
    266 %33 = OpImageSampleImplicitLod %v4float %29 %26
    267 OpStore %outColor %33
    268 OpReturn
    269 OpFunctionEnd
    270 )";
    271 
    272   SinglePassRunAndCheck<SimplificationPass>(predefs + before, predefs + after,
    273                                             true, true);
    274 }
    275 
    276 TEST_F(InsertExtractElimTest, OptimizeNestedStruct) {
    277   // The following HLSL has been pre-optimized to get the SPIR-V:
    278   // struct S0
    279   // {
    280   //     int x;
    281   //     SamplerState ss;
    282   // };
    283   //
    284   // struct S1
    285   // {
    286   //     float b;
    287   //     S0 s0;
    288   // };
    289   //
    290   // struct S2
    291   // {
    292   //     int a1;
    293   //     S1 resources;
    294   // };
    295   //
    296   // SamplerState samp;
    297   // Texture2D tex;
    298   //
    299   // float4 main(float4 vpos : VPOS) : COLOR0
    300   // {
    301   //     S1 s1;
    302   //     S2 s2;
    303   //     s1.s0.ss = samp;
    304   //     s2.resources = s1;
    305   //     return tex.Sample(s2.resources.s0.ss, float2(0.5));
    306   // }
    307 
    308   const std::string predefs =
    309       R"(OpCapability Shader
    310 %1 = OpExtInstImport "GLSL.std.450"
    311 OpMemoryModel Logical GLSL450
    312 OpEntryPoint Fragment %main "main" %_entryPointOutput
    313 OpExecutionMode %main OriginUpperLeft
    314 OpSource HLSL 500
    315 OpName %main "main"
    316 OpName %S0 "S0"
    317 OpMemberName %S0 0 "x"
    318 OpMemberName %S0 1 "ss"
    319 OpName %S1 "S1"
    320 OpMemberName %S1 0 "b"
    321 OpMemberName %S1 1 "s0"
    322 OpName %samp "samp"
    323 OpName %S2 "S2"
    324 OpMemberName %S2 0 "a1"
    325 OpMemberName %S2 1 "resources"
    326 OpName %tex "tex"
    327 OpName %_entryPointOutput "@entryPointOutput"
    328 OpDecorate %samp DescriptorSet 0
    329 OpDecorate %tex DescriptorSet 0
    330 OpDecorate %_entryPointOutput Location 0
    331 %void = OpTypeVoid
    332 %10 = OpTypeFunction %void
    333 %float = OpTypeFloat 32
    334 %v4float = OpTypeVector %float 4
    335 %_ptr_Function_v4float = OpTypePointer Function %v4float
    336 %14 = OpTypeFunction %v4float %_ptr_Function_v4float
    337 %int = OpTypeInt 32 1
    338 %16 = OpTypeSampler
    339 %S0 = OpTypeStruct %int %16
    340 %S1 = OpTypeStruct %float %S0
    341 %_ptr_Function_S1 = OpTypePointer Function %S1
    342 %int_1 = OpConstant %int 1
    343 %_ptr_UniformConstant_16 = OpTypePointer UniformConstant %16
    344 %samp = OpVariable %_ptr_UniformConstant_16 UniformConstant
    345 %_ptr_Function_16 = OpTypePointer Function %16
    346 %S2 = OpTypeStruct %int %S1
    347 %_ptr_Function_S2 = OpTypePointer Function %S2
    348 %22 = OpTypeImage %float 2D 0 0 0 1 Unknown
    349 %_ptr_UniformConstant_22 = OpTypePointer UniformConstant %22
    350 %tex = OpVariable %_ptr_UniformConstant_22 UniformConstant
    351 %24 = OpTypeSampledImage %22
    352 %v2float = OpTypeVector %float 2
    353 %float_0_5 = OpConstant %float 0.5
    354 %27 = OpConstantComposite %v2float %float_0_5 %float_0_5
    355 %_ptr_Input_v4float = OpTypePointer Input %v4float
    356 %_ptr_Output_v4float = OpTypePointer Output %v4float
    357 %_entryPointOutput = OpVariable %_ptr_Output_v4float Output
    358 )";
    359 
    360   const std::string before =
    361       R"(%main = OpFunction %void None %10
    362 %30 = OpLabel
    363 %31 = OpVariable %_ptr_Function_S1 Function
    364 %32 = OpVariable %_ptr_Function_S2 Function
    365 %33 = OpLoad %16 %samp
    366 %34 = OpLoad %S1 %31
    367 %35 = OpCompositeInsert %S1 %33 %34 1 1
    368 OpStore %31 %35
    369 %36 = OpLoad %S2 %32
    370 %37 = OpCompositeInsert %S2 %35 %36 1
    371 OpStore %32 %37
    372 %38 = OpLoad %22 %tex
    373 %39 = OpCompositeExtract %16 %37 1 1 1
    374 %40 = OpSampledImage %24 %38 %39
    375 %41 = OpImageSampleImplicitLod %v4float %40 %27
    376 OpStore %_entryPointOutput %41
    377 OpReturn
    378 OpFunctionEnd
    379 )";
    380 
    381   const std::string after =
    382       R"(%main = OpFunction %void None %10
    383 %30 = OpLabel
    384 %31 = OpVariable %_ptr_Function_S1 Function
    385 %32 = OpVariable %_ptr_Function_S2 Function
    386 %33 = OpLoad %16 %samp
    387 %34 = OpLoad %S1 %31
    388 %35 = OpCompositeInsert %S1 %33 %34 1 1
    389 OpStore %31 %35
    390 %36 = OpLoad %S2 %32
    391 %37 = OpCompositeInsert %S2 %35 %36 1
    392 OpStore %32 %37
    393 %38 = OpLoad %22 %tex
    394 %40 = OpSampledImage %24 %38 %33
    395 %41 = OpImageSampleImplicitLod %v4float %40 %27
    396 OpStore %_entryPointOutput %41
    397 OpReturn
    398 OpFunctionEnd
    399 )";
    400 
    401   SinglePassRunAndCheck<SimplificationPass>(predefs + before, predefs + after,
    402                                             true, true);
    403 }
    404 
    405 TEST_F(InsertExtractElimTest, ConflictingInsertPreventsOptimization) {
    406   // Note: The SPIR-V assembly has had store/load elimination
    407   // performed to allow the inserts and extracts to directly
    408   // reference each other.
    409   //
    410   // #version 140
    411   //
    412   // in vec4 BaseColor;
    413   //
    414   // struct S_t {
    415   //     vec4 v0;
    416   //     vec4 v1;
    417   // };
    418   //
    419   // void main()
    420   // {
    421   //     S_t s0;
    422   //     s0.v1 = BaseColor;
    423   //     s0.v1[2] = 0.0;
    424   //     gl_FragColor = s0.v1;
    425   // }
    426 
    427   const std::string assembly =
    428       R"(OpCapability Shader
    429 %1 = OpExtInstImport "GLSL.std.450"
    430 OpMemoryModel Logical GLSL450
    431 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
    432 OpExecutionMode %main OriginUpperLeft
    433 OpSource GLSL 140
    434 OpName %main "main"
    435 OpName %S_t "S_t"
    436 OpMemberName %S_t 0 "v0"
    437 OpMemberName %S_t 1 "v1"
    438 OpName %s0 "s0"
    439 OpName %BaseColor "BaseColor"
    440 OpName %gl_FragColor "gl_FragColor"
    441 %void = OpTypeVoid
    442 %8 = OpTypeFunction %void
    443 %float = OpTypeFloat 32
    444 %v4float = OpTypeVector %float 4
    445 %S_t = OpTypeStruct %v4float %v4float
    446 %_ptr_Function_S_t = OpTypePointer Function %S_t
    447 %int = OpTypeInt 32 1
    448 %int_1 = OpConstant %int 1
    449 %float_0 = OpConstant %float 0
    450 %_ptr_Input_v4float = OpTypePointer Input %v4float
    451 %BaseColor = OpVariable %_ptr_Input_v4float Input
    452 %_ptr_Function_v4float = OpTypePointer Function %v4float
    453 %_ptr_Output_v4float = OpTypePointer Output %v4float
    454 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    455 %main = OpFunction %void None %8
    456 %18 = OpLabel
    457 %s0 = OpVariable %_ptr_Function_S_t Function
    458 %19 = OpLoad %v4float %BaseColor
    459 %20 = OpLoad %S_t %s0
    460 %21 = OpCompositeInsert %S_t %19 %20 1
    461 %22 = OpCompositeInsert %S_t %float_0 %21 1 2
    462 OpStore %s0 %22
    463 %23 = OpCompositeExtract %v4float %22 1
    464 OpStore %gl_FragColor %23
    465 OpReturn
    466 OpFunctionEnd
    467 )";
    468 
    469   SinglePassRunAndCheck<SimplificationPass>(assembly, assembly, true, true);
    470 }
    471 
    472 TEST_F(InsertExtractElimTest, ConflictingInsertPreventsOptimization2) {
    473   // Note: The SPIR-V assembly has had store/load elimination
    474   // performed to allow the inserts and extracts to directly
    475   // reference each other.
    476   //
    477   // #version 140
    478   //
    479   // in vec4 BaseColor;
    480   //
    481   // struct S_t {
    482   //     vec4 v0;
    483   //     vec4 v1;
    484   // };
    485   //
    486   // void main()
    487   // {
    488   //     S_t s0;
    489   //     s0.v1[1] = 1.0; // dead
    490   //     s0.v1 = Baseline;
    491   //     gl_FragColor = vec4(s0.v1[1], 0.0, 0.0, 0.0);
    492   // }
    493 
    494   const std::string before_predefs =
    495       R"(OpCapability Shader
    496 %1 = OpExtInstImport "GLSL.std.450"
    497 OpMemoryModel Logical GLSL450
    498 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
    499 OpExecutionMode %main OriginUpperLeft
    500 OpSource GLSL 140
    501 OpName %main "main"
    502 OpName %S_t "S_t"
    503 OpMemberName %S_t 0 "v0"
    504 OpMemberName %S_t 1 "v1"
    505 OpName %s0 "s0"
    506 OpName %BaseColor "BaseColor"
    507 OpName %gl_FragColor "gl_FragColor"
    508 %void = OpTypeVoid
    509 %8 = OpTypeFunction %void
    510 %float = OpTypeFloat 32
    511 %v4float = OpTypeVector %float 4
    512 %S_t = OpTypeStruct %v4float %v4float
    513 %_ptr_Function_S_t = OpTypePointer Function %S_t
    514 %int = OpTypeInt 32 1
    515 %int_1 = OpConstant %int 1
    516 %float_1 = OpConstant %float 1
    517 %uint = OpTypeInt 32 0
    518 %uint_1 = OpConstant %uint 1
    519 %_ptr_Function_float = OpTypePointer Function %float
    520 %_ptr_Input_v4float = OpTypePointer Input %v4float
    521 %BaseColor = OpVariable %_ptr_Input_v4float Input
    522 %_ptr_Function_v4float = OpTypePointer Function %v4float
    523 %_ptr_Output_v4float = OpTypePointer Output %v4float
    524 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    525 %float_0 = OpConstant %float 0
    526 )";
    527 
    528   const std::string after_predefs =
    529       R"(OpCapability Shader
    530 %1 = OpExtInstImport "GLSL.std.450"
    531 OpMemoryModel Logical GLSL450
    532 OpEntryPoint Fragment %main "main" %BaseColor %gl_FragColor
    533 OpExecutionMode %main OriginUpperLeft
    534 OpSource GLSL 140
    535 OpName %main "main"
    536 OpName %S_t "S_t"
    537 OpMemberName %S_t 0 "v0"
    538 OpMemberName %S_t 1 "v1"
    539 OpName %s0 "s0"
    540 OpName %BaseColor "BaseColor"
    541 OpName %gl_FragColor "gl_FragColor"
    542 %void = OpTypeVoid
    543 %8 = OpTypeFunction %void
    544 %float = OpTypeFloat 32
    545 %v4float = OpTypeVector %float 4
    546 %S_t = OpTypeStruct %v4float %v4float
    547 %_ptr_Function_S_t = OpTypePointer Function %S_t
    548 %int = OpTypeInt 32 1
    549 %int_1 = OpConstant %int 1
    550 %float_1 = OpConstant %float 1
    551 %uint = OpTypeInt 32 0
    552 %uint_1 = OpConstant %uint 1
    553 %_ptr_Function_float = OpTypePointer Function %float
    554 %_ptr_Input_v4float = OpTypePointer Input %v4float
    555 %BaseColor = OpVariable %_ptr_Input_v4float Input
    556 %_ptr_Function_v4float = OpTypePointer Function %v4float
    557 %_ptr_Output_v4float = OpTypePointer Output %v4float
    558 %gl_FragColor = OpVariable %_ptr_Output_v4float Output
    559 %float_0 = OpConstant %float 0
    560 )";
    561 
    562   const std::string before =
    563       R"(%main = OpFunction %void None %8
    564 %22 = OpLabel
    565 %s0 = OpVariable %_ptr_Function_S_t Function
    566 %23 = OpLoad %S_t %s0
    567 %24 = OpCompositeInsert %S_t %float_1 %23 1 1
    568 %25 = OpLoad %v4float %BaseColor
    569 %26 = OpCompositeInsert %S_t %25 %24 1
    570 %27 = OpCompositeExtract %float %26 1 1
    571 %28 = OpCompositeConstruct %v4float %27 %float_0 %float_0 %float_0
    572 OpStore %gl_FragColor %28
    573 OpReturn
    574 OpFunctionEnd
    575 )";
    576 
    577   const std::string after =
    578       R"(%main = OpFunction %void None %8
    579 %22 = OpLabel
    580 %s0 = OpVariable %_ptr_Function_S_t Function
    581 %23 = OpLoad %S_t %s0
    582 %24 = OpCompositeInsert %S_t %float_1 %23 1 1
    583 %25 = OpLoad %v4float %BaseColor
    584 %26 = OpCompositeInsert %S_t %25 %24 1
    585 %27 = OpCompositeExtract %float %25 1
    586 %28 = OpCompositeConstruct %v4float %27 %float_0 %float_0 %float_0
    587 OpStore %gl_FragColor %28
    588 OpReturn
    589 OpFunctionEnd
    590 )";
    591 
    592   SinglePassRunAndCheck<SimplificationPass>(before_predefs + before,
    593                                             after_predefs + after, true, true);
    594 }
    595 
    596 TEST_F(InsertExtractElimTest, MixWithConstants) {
    597   // Extract component of FMix with 0.0 or 1.0 as the a-value.
    598   //
    599   // Note: The SPIR-V assembly has had store/load elimination
    600   // performed to allow the inserts and extracts to directly
    601   // reference each other.
    602   //
    603   // #version 450
    604   //
    605   // layout (location=0) in float bc;
    606   // layout (location=1) in float bc2;
    607   // layout (location=2) in float m;
    608   // layout (location=3) in float m2;
    609   // layout (location=0) out vec4 OutColor;
    610   //
    611   // void main()
    612   // {
    613   //     vec4 bcv = vec4(bc, bc2, 0.0, 1.0);
    614   //     vec4 bcv2 = vec4(bc2, bc, 1.0, 0.0);
    615   //     vec4 v = mix(bcv, bcv2, vec4(0.0,1.0,m,m2));
    616   //     OutColor = vec4(v.y);
    617   // }
    618 
    619   const std::string predefs =
    620       R"(OpCapability Shader
    621 %1 = OpExtInstImport "GLSL.std.450"
    622 OpMemoryModel Logical GLSL450
    623 OpEntryPoint Fragment %main "main" %bc %bc2 %m %m2 %OutColor
    624 OpExecutionMode %main OriginUpperLeft
    625 OpSource GLSL 450
    626 OpName %main "main"
    627 OpName %bc "bc"
    628 OpName %bc2 "bc2"
    629 OpName %m "m"
    630 OpName %m2 "m2"
    631 OpName %OutColor "OutColor"
    632 OpDecorate %bc Location 0
    633 OpDecorate %bc2 Location 1
    634 OpDecorate %m Location 2
    635 OpDecorate %m2 Location 3
    636 OpDecorate %OutColor Location 0
    637 %void = OpTypeVoid
    638 %9 = OpTypeFunction %void
    639 %float = OpTypeFloat 32
    640 %v4float = OpTypeVector %float 4
    641 %_ptr_Function_v4float = OpTypePointer Function %v4float
    642 %_ptr_Input_float = OpTypePointer Input %float
    643 %bc = OpVariable %_ptr_Input_float Input
    644 %bc2 = OpVariable %_ptr_Input_float Input
    645 %float_0 = OpConstant %float 0
    646 %float_1 = OpConstant %float 1
    647 %m = OpVariable %_ptr_Input_float Input
    648 %m2 = OpVariable %_ptr_Input_float Input
    649 %_ptr_Output_v4float = OpTypePointer Output %v4float
    650 %OutColor = OpVariable %_ptr_Output_v4float Output
    651 %uint = OpTypeInt 32 0
    652 %_ptr_Function_float = OpTypePointer Function %float
    653 )";
    654 
    655   const std::string before =
    656       R"(%main = OpFunction %void None %9
    657 %19 = OpLabel
    658 %20 = OpLoad %float %bc
    659 %21 = OpLoad %float %bc2
    660 %22 = OpCompositeConstruct %v4float %20 %21 %float_0 %float_1
    661 %23 = OpLoad %float %bc2
    662 %24 = OpLoad %float %bc
    663 %25 = OpCompositeConstruct %v4float %23 %24 %float_1 %float_0
    664 %26 = OpLoad %float %m
    665 %27 = OpLoad %float %m2
    666 %28 = OpCompositeConstruct %v4float %float_0 %float_1 %26 %27
    667 %29 = OpExtInst %v4float %1 FMix %22 %25 %28
    668 %30 = OpCompositeExtract %float %29 1
    669 %31 = OpCompositeConstruct %v4float %30 %30 %30 %30
    670 OpStore %OutColor %31
    671 OpReturn
    672 OpFunctionEnd
    673 )";
    674 
    675   const std::string after =
    676       R"(%main = OpFunction %void None %9
    677 %19 = OpLabel
    678 %20 = OpLoad %float %bc
    679 %21 = OpLoad %float %bc2
    680 %22 = OpCompositeConstruct %v4float %20 %21 %float_0 %float_1
    681 %23 = OpLoad %float %bc2
    682 %24 = OpLoad %float %bc
    683 %25 = OpCompositeConstruct %v4float %23 %24 %float_1 %float_0
    684 %26 = OpLoad %float %m
    685 %27 = OpLoad %float %m2
    686 %28 = OpCompositeConstruct %v4float %float_0 %float_1 %26 %27
    687 %29 = OpExtInst %v4float %1 FMix %22 %25 %28
    688 %31 = OpCompositeConstruct %v4float %24 %24 %24 %24
    689 OpStore %OutColor %31
    690 OpReturn
    691 OpFunctionEnd
    692 )";
    693 
    694   SinglePassRunAndCheck<SimplificationPass>(predefs + before, predefs + after,
    695                                             true, true);
    696 }
    697 
    698 TEST_F(InsertExtractElimTest, VectorShuffle1) {
    699   // Extract component from first vector in VectorShuffle
    700   //
    701   // Note: The SPIR-V assembly has had store/load elimination
    702   // performed to allow the inserts and extracts to directly
    703   // reference each other.
    704   //
    705   // #version 450
    706   //
    707   // layout (location=0) in float bc;
    708   // layout (location=1) in float bc2;
    709   // layout (location=0) out vec4 OutColor;
    710   //
    711   // void main()
    712   // {
    713   //     vec4 bcv = vec4(bc, bc2, 0.0, 1.0);
    714   //     vec4 v = bcv.zwxy;
    715   //     OutColor = vec4(v.y);
    716   // }
    717 
    718   const std::string predefs_before =
    719       R"(OpCapability Shader
    720 %1 = OpExtInstImport "GLSL.std.450"
    721 OpMemoryModel Logical GLSL450
    722 OpEntryPoint Fragment %main "main" %bc %bc2 %OutColor
    723 OpExecutionMode %main OriginUpperLeft
    724 OpSource GLSL 450
    725 OpName %main "main"
    726 OpName %bc "bc"
    727 OpName %bc2 "bc2"
    728 OpName %OutColor "OutColor"
    729 OpDecorate %bc Location 0
    730 OpDecorate %bc2 Location 1
    731 OpDecorate %OutColor Location 0
    732 %void = OpTypeVoid
    733 %7 = OpTypeFunction %void
    734 %float = OpTypeFloat 32
    735 %v4float = OpTypeVector %float 4
    736 %_ptr_Function_v4float = OpTypePointer Function %v4float
    737 %_ptr_Input_float = OpTypePointer Input %float
    738 %bc = OpVariable %_ptr_Input_float Input
    739 %bc2 = OpVariable %_ptr_Input_float Input
    740 %float_0 = OpConstant %float 0
    741 %float_1 = OpConstant %float 1
    742 %_ptr_Output_v4float = OpTypePointer Output %v4float
    743 %OutColor = OpVariable %_ptr_Output_v4float Output
    744 %uint = OpTypeInt 32 0
    745 %_ptr_Function_float = OpTypePointer Function %float
    746 )";
    747 
    748   const std::string predefs_after = predefs_before +
    749                                     "%24 = OpConstantComposite %v4float "
    750                                     "%float_1 %float_1 %float_1 %float_1\n";
    751 
    752   const std::string before =
    753       R"(%main = OpFunction %void None %7
    754 %17 = OpLabel
    755 %18 = OpLoad %float %bc
    756 %19 = OpLoad %float %bc2
    757 %20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1
    758 %21 = OpVectorShuffle %v4float %20 %20 2 3 0 1
    759 %22 = OpCompositeExtract %float %21 1
    760 %23 = OpCompositeConstruct %v4float %22 %22 %22 %22
    761 OpStore %OutColor %23
    762 OpReturn
    763 OpFunctionEnd
    764 )";
    765 
    766   const std::string after =
    767       R"(%main = OpFunction %void None %7
    768 %17 = OpLabel
    769 %18 = OpLoad %float %bc
    770 %19 = OpLoad %float %bc2
    771 %20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1
    772 %21 = OpVectorShuffle %v4float %20 %20 2 3 0 1
    773 OpStore %OutColor %24
    774 OpReturn
    775 OpFunctionEnd
    776 )";
    777 
    778   SinglePassRunAndCheck<SimplificationPass>(predefs_before + before,
    779                                             predefs_after + after, true, true);
    780 }
    781 
    782 TEST_F(InsertExtractElimTest, VectorShuffle2) {
    783   // Extract component from second vector in VectorShuffle
    784   // Identical to test VectorShuffle1 except for the vector
    785   // shuffle index of 7.
    786   //
    787   // Note: The SPIR-V assembly has had store/load elimination
    788   // performed to allow the inserts and extracts to directly
    789   // reference each other.
    790   //
    791   // #version 450
    792   //
    793   // layout (location=0) in float bc;
    794   // layout (location=1) in float bc2;
    795   // layout (location=0) out vec4 OutColor;
    796   //
    797   // void main()
    798   // {
    799   //     vec4 bcv = vec4(bc, bc2, 0.0, 1.0);
    800   //     vec4 v = bcv.zwxy;
    801   //     OutColor = vec4(v.y);
    802   // }
    803 
    804   const std::string predefs_before =
    805       R"(OpCapability Shader
    806 %1 = OpExtInstImport "GLSL.std.450"
    807 OpMemoryModel Logical GLSL450
    808 OpEntryPoint Fragment %main "main" %bc %bc2 %OutColor
    809 OpExecutionMode %main OriginUpperLeft
    810 OpSource GLSL 450
    811 OpName %main "main"
    812 OpName %bc "bc"
    813 OpName %bc2 "bc2"
    814 OpName %OutColor "OutColor"
    815 OpDecorate %bc Location 0
    816 OpDecorate %bc2 Location 1
    817 OpDecorate %OutColor Location 0
    818 %void = OpTypeVoid
    819 %7 = OpTypeFunction %void
    820 %float = OpTypeFloat 32
    821 %v4float = OpTypeVector %float 4
    822 %_ptr_Function_v4float = OpTypePointer Function %v4float
    823 %_ptr_Input_float = OpTypePointer Input %float
    824 %bc = OpVariable %_ptr_Input_float Input
    825 %bc2 = OpVariable %_ptr_Input_float Input
    826 %float_0 = OpConstant %float 0
    827 %float_1 = OpConstant %float 1
    828 %_ptr_Output_v4float = OpTypePointer Output %v4float
    829 %OutColor = OpVariable %_ptr_Output_v4float Output
    830 %uint = OpTypeInt 32 0
    831 %_ptr_Function_float = OpTypePointer Function %float
    832 )";
    833 
    834   const std::string predefs_after =
    835       R"(OpCapability Shader
    836 %1 = OpExtInstImport "GLSL.std.450"
    837 OpMemoryModel Logical GLSL450
    838 OpEntryPoint Fragment %main "main" %bc %bc2 %OutColor
    839 OpExecutionMode %main OriginUpperLeft
    840 OpSource GLSL 450
    841 OpName %main "main"
    842 OpName %bc "bc"
    843 OpName %bc2 "bc2"
    844 OpName %OutColor "OutColor"
    845 OpDecorate %bc Location 0
    846 OpDecorate %bc2 Location 1
    847 OpDecorate %OutColor Location 0
    848 %void = OpTypeVoid
    849 %7 = OpTypeFunction %void
    850 %float = OpTypeFloat 32
    851 %v4float = OpTypeVector %float 4
    852 %_ptr_Function_v4float = OpTypePointer Function %v4float
    853 %_ptr_Input_float = OpTypePointer Input %float
    854 %bc = OpVariable %_ptr_Input_float Input
    855 %bc2 = OpVariable %_ptr_Input_float Input
    856 %float_0 = OpConstant %float 0
    857 %float_1 = OpConstant %float 1
    858 %_ptr_Output_v4float = OpTypePointer Output %v4float
    859 %OutColor = OpVariable %_ptr_Output_v4float Output
    860 %uint = OpTypeInt 32 0
    861 %_ptr_Function_float = OpTypePointer Function %float
    862 %24 = OpConstantComposite %v4float %float_1 %float_1 %float_1 %float_1
    863 )";
    864 
    865   const std::string before =
    866       R"(%main = OpFunction %void None %7
    867 %17 = OpLabel
    868 %18 = OpLoad %float %bc
    869 %19 = OpLoad %float %bc2
    870 %20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1
    871 %21 = OpVectorShuffle %v4float %20 %20 2 7 0 1
    872 %22 = OpCompositeExtract %float %21 1
    873 %23 = OpCompositeConstruct %v4float %22 %22 %22 %22
    874 OpStore %OutColor %23
    875 OpReturn
    876 OpFunctionEnd
    877 )";
    878 
    879   const std::string after =
    880       R"(%main = OpFunction %void None %7
    881 %17 = OpLabel
    882 %18 = OpLoad %float %bc
    883 %19 = OpLoad %float %bc2
    884 %20 = OpCompositeConstruct %v4float %18 %19 %float_0 %float_1
    885 %21 = OpVectorShuffle %v4float %20 %20 2 7 0 1
    886 OpStore %OutColor %24
    887 OpReturn
    888 OpFunctionEnd
    889 )";
    890 
    891   SinglePassRunAndCheck<SimplificationPass>(predefs_before + before,
    892                                             predefs_after + after, true, true);
    893 }
    894 
    895 // TODO(greg-lunarg): Add tests to verify handling of these cases:
    896 //
    897 
    898 }  // namespace
    899 }  // namespace opt
    900 }  // namespace spvtools
    901