1fd4e5da5Sopenharmony_ci// Copyright (c) 2017 Google Inc. 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include <string> 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "test/opt/pass_fixture.h" 18fd4e5da5Sopenharmony_ci#include "test/opt/pass_utils.h" 19fd4e5da5Sopenharmony_ci 20fd4e5da5Sopenharmony_cinamespace spvtools { 21fd4e5da5Sopenharmony_cinamespace opt { 22fd4e5da5Sopenharmony_cinamespace { 23fd4e5da5Sopenharmony_ci 24fd4e5da5Sopenharmony_ciusing DeadVariableElimTest = PassTest<::testing::Test>; 25fd4e5da5Sopenharmony_ci 26fd4e5da5Sopenharmony_ci// %dead is unused. Make sure we remove it along with its name. 27fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, RemoveUnreferenced) { 28fd4e5da5Sopenharmony_ci const std::string before = 29fd4e5da5Sopenharmony_ci R"(OpCapability Shader 30fd4e5da5Sopenharmony_ciOpCapability Linkage 31fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450" 32fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 33fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 34fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft 35fd4e5da5Sopenharmony_ciOpSource GLSL 150 36fd4e5da5Sopenharmony_ciOpName %main "main" 37fd4e5da5Sopenharmony_ciOpName %dead "dead" 38fd4e5da5Sopenharmony_ci%void = OpTypeVoid 39fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void 40fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 41fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float 42fd4e5da5Sopenharmony_ci%dead = OpVariable %_ptr_Private_float Private 43fd4e5da5Sopenharmony_ci%main = OpFunction %void None %5 44fd4e5da5Sopenharmony_ci%8 = OpLabel 45fd4e5da5Sopenharmony_ciOpReturn 46fd4e5da5Sopenharmony_ciOpFunctionEnd 47fd4e5da5Sopenharmony_ci)"; 48fd4e5da5Sopenharmony_ci 49fd4e5da5Sopenharmony_ci const std::string after = 50fd4e5da5Sopenharmony_ci R"(OpCapability Shader 51fd4e5da5Sopenharmony_ciOpCapability Linkage 52fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450" 53fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 54fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 55fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft 56fd4e5da5Sopenharmony_ciOpSource GLSL 150 57fd4e5da5Sopenharmony_ciOpName %main "main" 58fd4e5da5Sopenharmony_ci%void = OpTypeVoid 59fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void 60fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 61fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float 62fd4e5da5Sopenharmony_ci%main = OpFunction %void None %5 63fd4e5da5Sopenharmony_ci%8 = OpLabel 64fd4e5da5Sopenharmony_ciOpReturn 65fd4e5da5Sopenharmony_ciOpFunctionEnd 66fd4e5da5Sopenharmony_ci)"; 67fd4e5da5Sopenharmony_ci 68fd4e5da5Sopenharmony_ci SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 69fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<DeadVariableElimination>(before, after, true, true); 70fd4e5da5Sopenharmony_ci} 71fd4e5da5Sopenharmony_ci 72fd4e5da5Sopenharmony_ci// Since %dead is exported, make sure we keep it. It could be referenced 73fd4e5da5Sopenharmony_ci// somewhere else. 74fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, KeepExported) { 75fd4e5da5Sopenharmony_ci const std::string before = 76fd4e5da5Sopenharmony_ci R"(OpCapability Shader 77fd4e5da5Sopenharmony_ciOpCapability Linkage 78fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450" 79fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 80fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 81fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft 82fd4e5da5Sopenharmony_ciOpSource GLSL 150 83fd4e5da5Sopenharmony_ciOpName %main "main" 84fd4e5da5Sopenharmony_ciOpName %dead "dead" 85fd4e5da5Sopenharmony_ciOpDecorate %dead LinkageAttributes "dead" Export 86fd4e5da5Sopenharmony_ci%void = OpTypeVoid 87fd4e5da5Sopenharmony_ci%5 = OpTypeFunction %void 88fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 89fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float 90fd4e5da5Sopenharmony_ci%dead = OpVariable %_ptr_Private_float Private 91fd4e5da5Sopenharmony_ci%main = OpFunction %void None %5 92fd4e5da5Sopenharmony_ci%8 = OpLabel 93fd4e5da5Sopenharmony_ciOpReturn 94fd4e5da5Sopenharmony_ciOpFunctionEnd 95fd4e5da5Sopenharmony_ci)"; 96fd4e5da5Sopenharmony_ci 97fd4e5da5Sopenharmony_ci SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 98fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<DeadVariableElimination>(before, before, true, true); 99fd4e5da5Sopenharmony_ci} 100fd4e5da5Sopenharmony_ci 101fd4e5da5Sopenharmony_ci// Delete %dead because it is unreferenced. Then %initializer becomes 102fd4e5da5Sopenharmony_ci// unreferenced, so remove it as well. 103fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, RemoveUnreferencedWithInit1) { 104fd4e5da5Sopenharmony_ci const std::string before = 105fd4e5da5Sopenharmony_ci R"(OpCapability Shader 106fd4e5da5Sopenharmony_ciOpCapability Linkage 107fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450" 108fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 109fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 110fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft 111fd4e5da5Sopenharmony_ciOpSource GLSL 150 112fd4e5da5Sopenharmony_ciOpName %main "main" 113fd4e5da5Sopenharmony_ciOpName %dead "dead" 114fd4e5da5Sopenharmony_ciOpName %initializer "initializer" 115fd4e5da5Sopenharmony_ci%void = OpTypeVoid 116fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void 117fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 118fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float 119fd4e5da5Sopenharmony_ci%initializer = OpVariable %_ptr_Private_float Private 120fd4e5da5Sopenharmony_ci%dead = OpVariable %_ptr_Private_float Private %initializer 121fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6 122fd4e5da5Sopenharmony_ci%9 = OpLabel 123fd4e5da5Sopenharmony_ciOpReturn 124fd4e5da5Sopenharmony_ciOpFunctionEnd 125fd4e5da5Sopenharmony_ci)"; 126fd4e5da5Sopenharmony_ci 127fd4e5da5Sopenharmony_ci const std::string after = 128fd4e5da5Sopenharmony_ci R"(OpCapability Shader 129fd4e5da5Sopenharmony_ciOpCapability Linkage 130fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450" 131fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 132fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 133fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft 134fd4e5da5Sopenharmony_ciOpSource GLSL 150 135fd4e5da5Sopenharmony_ciOpName %main "main" 136fd4e5da5Sopenharmony_ci%void = OpTypeVoid 137fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void 138fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 139fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float 140fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6 141fd4e5da5Sopenharmony_ci%9 = OpLabel 142fd4e5da5Sopenharmony_ciOpReturn 143fd4e5da5Sopenharmony_ciOpFunctionEnd 144fd4e5da5Sopenharmony_ci)"; 145fd4e5da5Sopenharmony_ci 146fd4e5da5Sopenharmony_ci SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 147fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<DeadVariableElimination>(before, after, true, true); 148fd4e5da5Sopenharmony_ci} 149fd4e5da5Sopenharmony_ci 150fd4e5da5Sopenharmony_ci// Delete %dead because it is unreferenced. In this case, the initialized has 151fd4e5da5Sopenharmony_ci// another reference, and should not be removed. 152fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, RemoveUnreferencedWithInit2) { 153fd4e5da5Sopenharmony_ci const std::string before = 154fd4e5da5Sopenharmony_ci R"(OpCapability Shader 155fd4e5da5Sopenharmony_ciOpCapability Linkage 156fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450" 157fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 158fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 159fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft 160fd4e5da5Sopenharmony_ciOpSource GLSL 150 161fd4e5da5Sopenharmony_ciOpName %main "main" 162fd4e5da5Sopenharmony_ciOpName %dead "dead" 163fd4e5da5Sopenharmony_ciOpName %initializer "initializer" 164fd4e5da5Sopenharmony_ci%void = OpTypeVoid 165fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void 166fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 167fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float 168fd4e5da5Sopenharmony_ci%initializer = OpVariable %_ptr_Private_float Private 169fd4e5da5Sopenharmony_ci%dead = OpVariable %_ptr_Private_float Private %initializer 170fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6 171fd4e5da5Sopenharmony_ci%9 = OpLabel 172fd4e5da5Sopenharmony_ci%10 = OpLoad %float %initializer 173fd4e5da5Sopenharmony_ciOpReturn 174fd4e5da5Sopenharmony_ciOpFunctionEnd 175fd4e5da5Sopenharmony_ci)"; 176fd4e5da5Sopenharmony_ci 177fd4e5da5Sopenharmony_ci const std::string after = 178fd4e5da5Sopenharmony_ci R"(OpCapability Shader 179fd4e5da5Sopenharmony_ciOpCapability Linkage 180fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450" 181fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 182fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 183fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft 184fd4e5da5Sopenharmony_ciOpSource GLSL 150 185fd4e5da5Sopenharmony_ciOpName %main "main" 186fd4e5da5Sopenharmony_ciOpName %initializer "initializer" 187fd4e5da5Sopenharmony_ci%void = OpTypeVoid 188fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void 189fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 190fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float 191fd4e5da5Sopenharmony_ci%initializer = OpVariable %_ptr_Private_float Private 192fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6 193fd4e5da5Sopenharmony_ci%9 = OpLabel 194fd4e5da5Sopenharmony_ci%10 = OpLoad %float %initializer 195fd4e5da5Sopenharmony_ciOpReturn 196fd4e5da5Sopenharmony_ciOpFunctionEnd 197fd4e5da5Sopenharmony_ci)"; 198fd4e5da5Sopenharmony_ci 199fd4e5da5Sopenharmony_ci SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 200fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<DeadVariableElimination>(before, after, true, true); 201fd4e5da5Sopenharmony_ci} 202fd4e5da5Sopenharmony_ci 203fd4e5da5Sopenharmony_ci// Keep %live because it is used, and its initializer. 204fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, KeepReferenced) { 205fd4e5da5Sopenharmony_ci const std::string before = 206fd4e5da5Sopenharmony_ci R"(OpCapability Shader 207fd4e5da5Sopenharmony_ciOpCapability Linkage 208fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450" 209fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 210fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %main "main" 211fd4e5da5Sopenharmony_ciOpExecutionMode %main OriginUpperLeft 212fd4e5da5Sopenharmony_ciOpSource GLSL 150 213fd4e5da5Sopenharmony_ciOpName %main "main" 214fd4e5da5Sopenharmony_ciOpName %live "live" 215fd4e5da5Sopenharmony_ciOpName %initializer "initializer" 216fd4e5da5Sopenharmony_ci%void = OpTypeVoid 217fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void 218fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32 219fd4e5da5Sopenharmony_ci%_ptr_Private_float = OpTypePointer Private %float 220fd4e5da5Sopenharmony_ci%initializer = OpConstant %float 0 221fd4e5da5Sopenharmony_ci%live = OpVariable %_ptr_Private_float Private %initializer 222fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6 223fd4e5da5Sopenharmony_ci%9 = OpLabel 224fd4e5da5Sopenharmony_ci%10 = OpLoad %float %live 225fd4e5da5Sopenharmony_ciOpReturn 226fd4e5da5Sopenharmony_ciOpFunctionEnd 227fd4e5da5Sopenharmony_ci)"; 228fd4e5da5Sopenharmony_ci 229fd4e5da5Sopenharmony_ci SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 230fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<DeadVariableElimination>(before, before, true, true); 231fd4e5da5Sopenharmony_ci} 232fd4e5da5Sopenharmony_ci 233fd4e5da5Sopenharmony_ci// This test that the decoration associated with a variable are removed when the 234fd4e5da5Sopenharmony_ci// variable is removed. 235fd4e5da5Sopenharmony_ciTEST_F(DeadVariableElimTest, RemoveVariableAndDecorations) { 236fd4e5da5Sopenharmony_ci const std::string before = 237fd4e5da5Sopenharmony_ci R"(OpCapability Shader 238fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450" 239fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 240fd4e5da5Sopenharmony_ciOpEntryPoint Vertex %main "main" 241fd4e5da5Sopenharmony_ciOpSource GLSL 450 242fd4e5da5Sopenharmony_ciOpName %main "main" 243fd4e5da5Sopenharmony_ciOpName %B "B" 244fd4e5da5Sopenharmony_ciOpMemberName %B 0 "a" 245fd4e5da5Sopenharmony_ciOpName %Bdat "Bdat" 246fd4e5da5Sopenharmony_ciOpMemberDecorate %B 0 Offset 0 247fd4e5da5Sopenharmony_ciOpDecorate %B BufferBlock 248fd4e5da5Sopenharmony_ciOpDecorate %Bdat DescriptorSet 0 249fd4e5da5Sopenharmony_ciOpDecorate %Bdat Binding 0 250fd4e5da5Sopenharmony_ci%void = OpTypeVoid 251fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void 252fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 253fd4e5da5Sopenharmony_ci%B = OpTypeStruct %uint 254fd4e5da5Sopenharmony_ci%_ptr_Uniform_B = OpTypePointer Uniform %B 255fd4e5da5Sopenharmony_ci%Bdat = OpVariable %_ptr_Uniform_B Uniform 256fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1 257fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0 258fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1 259fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint 260fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6 261fd4e5da5Sopenharmony_ci%13 = OpLabel 262fd4e5da5Sopenharmony_ciOpReturn 263fd4e5da5Sopenharmony_ciOpFunctionEnd 264fd4e5da5Sopenharmony_ci)"; 265fd4e5da5Sopenharmony_ci 266fd4e5da5Sopenharmony_ci const std::string after = 267fd4e5da5Sopenharmony_ci R"(OpCapability Shader 268fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "GLSL.std.450" 269fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450 270fd4e5da5Sopenharmony_ciOpEntryPoint Vertex %main "main" 271fd4e5da5Sopenharmony_ciOpSource GLSL 450 272fd4e5da5Sopenharmony_ciOpName %main "main" 273fd4e5da5Sopenharmony_ciOpName %B "B" 274fd4e5da5Sopenharmony_ciOpMemberName %B 0 "a" 275fd4e5da5Sopenharmony_ciOpMemberDecorate %B 0 Offset 0 276fd4e5da5Sopenharmony_ciOpDecorate %B BufferBlock 277fd4e5da5Sopenharmony_ci%void = OpTypeVoid 278fd4e5da5Sopenharmony_ci%6 = OpTypeFunction %void 279fd4e5da5Sopenharmony_ci%uint = OpTypeInt 32 0 280fd4e5da5Sopenharmony_ci%B = OpTypeStruct %uint 281fd4e5da5Sopenharmony_ci%_ptr_Uniform_B = OpTypePointer Uniform %B 282fd4e5da5Sopenharmony_ci%int = OpTypeInt 32 1 283fd4e5da5Sopenharmony_ci%int_0 = OpConstant %int 0 284fd4e5da5Sopenharmony_ci%uint_1 = OpConstant %uint 1 285fd4e5da5Sopenharmony_ci%_ptr_Uniform_uint = OpTypePointer Uniform %uint 286fd4e5da5Sopenharmony_ci%main = OpFunction %void None %6 287fd4e5da5Sopenharmony_ci%13 = OpLabel 288fd4e5da5Sopenharmony_ciOpReturn 289fd4e5da5Sopenharmony_ciOpFunctionEnd 290fd4e5da5Sopenharmony_ci)"; 291fd4e5da5Sopenharmony_ci 292fd4e5da5Sopenharmony_ci SetAssembleOptions(SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 293fd4e5da5Sopenharmony_ci SinglePassRunAndCheck<DeadVariableElimination>(before, after, true, true); 294fd4e5da5Sopenharmony_ci} 295fd4e5da5Sopenharmony_ci 296fd4e5da5Sopenharmony_ci} // namespace 297fd4e5da5Sopenharmony_ci} // namespace opt 298fd4e5da5Sopenharmony_ci} // namespace spvtools 299