| // Copyright (c) 2017 Google Inc. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include <string> | |
| #include "test/opt/pass_fixture.h" | |
| #include "test/opt/pass_utils.h" | |
| namespace spvtools { | |
| namespace opt { | |
| namespace { | |
| using CFGCleanupTest = PassTest<::testing::Test>; | |
| TEST_F(CFGCleanupTest, RemoveUnreachableBlocks) { | |
| const std::string declarations = R"(OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %inf %outf4 | |
| OpExecutionMode %main OriginUpperLeft | |
| OpSource GLSL 450 | |
| OpName %main "main" | |
| OpName %inf "inf" | |
| OpName %outf4 "outf4" | |
| OpDecorate %inf Location 0 | |
| OpDecorate %outf4 Location 0 | |
| %void = OpTypeVoid | |
| %6 = OpTypeFunction %void | |
| %float = OpTypeFloat 32 | |
| %_ptr_Input_float = OpTypePointer Input %float | |
| %inf = OpVariable %_ptr_Input_float Input | |
| %float_2 = OpConstant %float 2 | |
| %bool = OpTypeBool | |
| %v4float = OpTypeVector %float 4 | |
| %_ptr_Output_v4float = OpTypePointer Output %v4float | |
| %outf4 = OpVariable %_ptr_Output_v4float Output | |
| %float_n0_5 = OpConstant %float -0.5 | |
| )"; | |
| const std::string body_before = R"(%main = OpFunction %void None %6 | |
| %14 = OpLabel | |
| OpBranch %18 | |
| %19 = OpLabel | |
| %20 = OpLoad %float %inf | |
| %21 = OpCompositeConstruct %v4float %20 %20 %20 %20 | |
| OpStore %outf4 %21 | |
| OpBranch %17 | |
| %18 = OpLabel | |
| %22 = OpLoad %float %inf | |
| %23 = OpFAdd %float %22 %float_n0_5 | |
| %24 = OpCompositeConstruct %v4float %23 %23 %23 %23 | |
| OpStore %outf4 %24 | |
| OpBranch %17 | |
| %17 = OpLabel | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| const std::string body_after = R"(%main = OpFunction %void None %6 | |
| %14 = OpLabel | |
| OpBranch %15 | |
| %15 = OpLabel | |
| %20 = OpLoad %float %inf | |
| %21 = OpFAdd %float %20 %float_n0_5 | |
| %22 = OpCompositeConstruct %v4float %21 %21 %21 %21 | |
| OpStore %outf4 %22 | |
| OpBranch %19 | |
| %19 = OpLabel | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndCheck<CFGCleanupPass>(declarations + body_before, | |
| declarations + body_after, true, true); | |
| } | |
| TEST_F(CFGCleanupTest, RemoveDecorations) { | |
| const std::string before = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" | |
| OpExecutionMode %main OriginUpperLeft | |
| OpName %main "main" | |
| OpName %x "x" | |
| OpName %dead "dead" | |
| OpDecorate %x RelaxedPrecision | |
| OpDecorate %dead RelaxedPrecision | |
| %void = OpTypeVoid | |
| %6 = OpTypeFunction %void | |
| %float = OpTypeFloat 32 | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %float_2 = OpConstant %float 2 | |
| %float_4 = OpConstant %float 4 | |
| %main = OpFunction %void None %6 | |
| %14 = OpLabel | |
| %x = OpVariable %_ptr_Function_float Function | |
| OpBranch %18 | |
| %19 = OpLabel | |
| %dead = OpVariable %_ptr_Function_float Function | |
| OpStore %dead %float_2 | |
| OpBranch %17 | |
| %18 = OpLabel | |
| OpStore %x %float_4 | |
| OpBranch %17 | |
| %17 = OpLabel | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| const std::string after = R"(OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" | |
| OpExecutionMode %main OriginUpperLeft | |
| OpName %main "main" | |
| OpName %x "x" | |
| OpDecorate %x RelaxedPrecision | |
| %void = OpTypeVoid | |
| %6 = OpTypeFunction %void | |
| %float = OpTypeFloat 32 | |
| %_ptr_Function_float = OpTypePointer Function %float | |
| %float_2 = OpConstant %float 2 | |
| %float_4 = OpConstant %float 4 | |
| %main = OpFunction %void None %6 | |
| %11 = OpLabel | |
| %x = OpVariable %_ptr_Function_float Function | |
| OpBranch %12 | |
| %12 = OpLabel | |
| OpStore %x %float_4 | |
| OpBranch %14 | |
| %14 = OpLabel | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndCheck<CFGCleanupPass>(before, after, true, true); | |
| } | |
| TEST_F(CFGCleanupTest, UpdatePhis) { | |
| const std::string before = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %y %outparm | |
| OpExecutionMode %main OriginUpperLeft | |
| OpName %main "main" | |
| OpName %y "y" | |
| OpName %outparm "outparm" | |
| OpDecorate %y Flat | |
| OpDecorate %y Location 0 | |
| OpDecorate %outparm Location 0 | |
| %void = OpTypeVoid | |
| %3 = OpTypeFunction %void | |
| %int = OpTypeInt 32 1 | |
| %_ptr_Function_int = OpTypePointer Function %int | |
| %_ptr_Input_int = OpTypePointer Input %int | |
| %y = OpVariable %_ptr_Input_int Input | |
| %int_10 = OpConstant %int 10 | |
| %bool = OpTypeBool | |
| %int_42 = OpConstant %int 42 | |
| %int_23 = OpConstant %int 23 | |
| %int_5 = OpConstant %int 5 | |
| %_ptr_Output_int = OpTypePointer Output %int | |
| %outparm = OpVariable %_ptr_Output_int Output | |
| %main = OpFunction %void None %3 | |
| %5 = OpLabel | |
| %11 = OpLoad %int %y | |
| OpBranch %21 | |
| %16 = OpLabel | |
| %20 = OpIAdd %int %11 %int_42 | |
| OpBranch %17 | |
| %21 = OpLabel | |
| %24 = OpISub %int %11 %int_23 | |
| OpBranch %17 | |
| %17 = OpLabel | |
| %31 = OpPhi %int %20 %16 %24 %21 | |
| %27 = OpIAdd %int %31 %int_5 | |
| OpStore %outparm %27 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| const std::string after = R"(OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %y %outparm | |
| OpExecutionMode %main OriginUpperLeft | |
| OpName %main "main" | |
| OpName %y "y" | |
| OpName %outparm "outparm" | |
| OpDecorate %y Flat | |
| OpDecorate %y Location 0 | |
| OpDecorate %outparm Location 0 | |
| %void = OpTypeVoid | |
| %6 = OpTypeFunction %void | |
| %int = OpTypeInt 32 1 | |
| %_ptr_Function_int = OpTypePointer Function %int | |
| %_ptr_Input_int = OpTypePointer Input %int | |
| %y = OpVariable %_ptr_Input_int Input | |
| %int_10 = OpConstant %int 10 | |
| %bool = OpTypeBool | |
| %int_42 = OpConstant %int 42 | |
| %int_23 = OpConstant %int 23 | |
| %int_5 = OpConstant %int 5 | |
| %_ptr_Output_int = OpTypePointer Output %int | |
| %outparm = OpVariable %_ptr_Output_int Output | |
| %main = OpFunction %void None %6 | |
| %16 = OpLabel | |
| %17 = OpLoad %int %y | |
| OpBranch %18 | |
| %18 = OpLabel | |
| %22 = OpISub %int %17 %int_23 | |
| OpBranch %21 | |
| %21 = OpLabel | |
| %23 = OpPhi %int %22 %18 | |
| %24 = OpIAdd %int %23 %int_5 | |
| OpStore %outparm %24 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndCheck<CFGCleanupPass>(before, after, true, true); | |
| } | |
| TEST_F(CFGCleanupTest, RemoveNamedLabels) { | |
| const std::string before = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Vertex %main "main" | |
| OpSource GLSL 430 | |
| OpName %main "main" | |
| OpName %dead "dead" | |
| %void = OpTypeVoid | |
| %5 = OpTypeFunction %void | |
| %main = OpFunction %void None %5 | |
| %6 = OpLabel | |
| OpReturn | |
| %dead = OpLabel | |
| OpReturn | |
| OpFunctionEnd)"; | |
| const std::string after = R"(OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Vertex %main "main" | |
| OpSource GLSL 430 | |
| OpName %main "main" | |
| %void = OpTypeVoid | |
| %5 = OpTypeFunction %void | |
| %main = OpFunction %void None %5 | |
| %6 = OpLabel | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndCheck<CFGCleanupPass>(before, after, true, true); | |
| } | |
| TEST_F(CFGCleanupTest, RemovePhiArgsFromFarBlocks) { | |
| const std::string before = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %y %outparm | |
| OpExecutionMode %main OriginUpperLeft | |
| OpName %main "main" | |
| OpName %y "y" | |
| OpName %outparm "outparm" | |
| OpDecorate %y Flat | |
| OpDecorate %y Location 0 | |
| OpDecorate %outparm Location 0 | |
| %void = OpTypeVoid | |
| %3 = OpTypeFunction %void | |
| %int = OpTypeInt 32 1 | |
| %_ptr_Function_int = OpTypePointer Function %int | |
| %_ptr_Input_int = OpTypePointer Input %int | |
| %y = OpVariable %_ptr_Input_int Input | |
| %int_42 = OpConstant %int 42 | |
| %_ptr_Output_int = OpTypePointer Output %int | |
| %outparm = OpVariable %_ptr_Output_int Output | |
| %int_14 = OpConstant %int 14 | |
| %int_15 = OpConstant %int 15 | |
| %int_5 = OpConstant %int 5 | |
| %main = OpFunction %void None %3 | |
| %5 = OpLabel | |
| OpBranch %40 | |
| %41 = OpLabel | |
| %11 = OpLoad %int %y | |
| OpBranch %40 | |
| %40 = OpLabel | |
| %12 = OpLoad %int %y | |
| OpSelectionMerge %16 None | |
| OpSwitch %12 %16 10 %13 13 %14 18 %15 | |
| %13 = OpLabel | |
| OpBranch %16 | |
| %14 = OpLabel | |
| OpStore %outparm %int_14 | |
| OpBranch %16 | |
| %15 = OpLabel | |
| OpStore %outparm %int_15 | |
| OpBranch %16 | |
| %16 = OpLabel | |
| %30 = OpPhi %int %11 %40 %int_42 %13 %11 %14 %11 %15 | |
| %28 = OpIAdd %int %30 %int_5 | |
| OpStore %outparm %28 | |
| OpReturn | |
| OpFunctionEnd)"; | |
| const std::string after = R"(OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %y %outparm | |
| OpExecutionMode %main OriginUpperLeft | |
| OpName %main "main" | |
| OpName %y "y" | |
| OpName %outparm "outparm" | |
| OpDecorate %y Flat | |
| OpDecorate %y Location 0 | |
| OpDecorate %outparm Location 0 | |
| %void = OpTypeVoid | |
| %6 = OpTypeFunction %void | |
| %int = OpTypeInt 32 1 | |
| %_ptr_Function_int = OpTypePointer Function %int | |
| %_ptr_Input_int = OpTypePointer Input %int | |
| %y = OpVariable %_ptr_Input_int Input | |
| %int_42 = OpConstant %int 42 | |
| %_ptr_Output_int = OpTypePointer Output %int | |
| %outparm = OpVariable %_ptr_Output_int Output | |
| %int_14 = OpConstant %int 14 | |
| %int_15 = OpConstant %int 15 | |
| %int_5 = OpConstant %int 5 | |
| %26 = OpUndef %int | |
| %main = OpFunction %void None %6 | |
| %15 = OpLabel | |
| OpBranch %16 | |
| %16 = OpLabel | |
| %19 = OpLoad %int %y | |
| OpSelectionMerge %20 None | |
| OpSwitch %19 %20 10 %21 13 %22 18 %23 | |
| %21 = OpLabel | |
| OpBranch %20 | |
| %22 = OpLabel | |
| OpStore %outparm %int_14 | |
| OpBranch %20 | |
| %23 = OpLabel | |
| OpStore %outparm %int_15 | |
| OpBranch %20 | |
| %20 = OpLabel | |
| %24 = OpPhi %int %26 %16 %int_42 %21 %26 %22 %26 %23 | |
| %25 = OpIAdd %int %24 %int_5 | |
| OpStore %outparm %25 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndCheck<CFGCleanupPass>(before, after, true, true); | |
| } | |
| TEST_F(CFGCleanupTest, RemovePhiConstantArgs) { | |
| const std::string before = R"( | |
| OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %y %outparm | |
| OpExecutionMode %main OriginUpperLeft | |
| OpName %main "main" | |
| OpName %y "y" | |
| OpName %outparm "outparm" | |
| OpDecorate %y Flat | |
| OpDecorate %y Location 0 | |
| OpDecorate %outparm Location 0 | |
| %void = OpTypeVoid | |
| %3 = OpTypeFunction %void | |
| %int = OpTypeInt 32 1 | |
| %_ptr_Input_int = OpTypePointer Input %int | |
| %y = OpVariable %_ptr_Input_int Input | |
| %int_10 = OpConstant %int 10 | |
| %bool = OpTypeBool | |
| %_ptr_Function_int = OpTypePointer Function %int | |
| %int_23 = OpConstant %int 23 | |
| %int_5 = OpConstant %int 5 | |
| %_ptr_Output_int = OpTypePointer Output %int | |
| %outparm = OpVariable %_ptr_Output_int Output | |
| %24 = OpUndef %int | |
| %main = OpFunction %void None %3 | |
| %5 = OpLabel | |
| OpBranch %14 | |
| %40 = OpLabel | |
| %9 = OpLoad %int %y | |
| %12 = OpSGreaterThan %bool %9 %int_10 | |
| OpSelectionMerge %14 None | |
| OpBranchConditional %12 %13 %14 | |
| %13 = OpLabel | |
| OpBranch %14 | |
| %14 = OpLabel | |
| %25 = OpPhi %int %24 %5 %int_23 %13 | |
| %20 = OpIAdd %int %25 %int_5 | |
| OpStore %outparm %20 | |
| OpReturn | |
| OpFunctionEnd)"; | |
| const std::string after = R"(OpCapability Shader | |
| %1 = OpExtInstImport "GLSL.std.450" | |
| OpMemoryModel Logical GLSL450 | |
| OpEntryPoint Fragment %main "main" %y %outparm | |
| OpExecutionMode %main OriginUpperLeft | |
| OpName %main "main" | |
| OpName %y "y" | |
| OpName %outparm "outparm" | |
| OpDecorate %y Flat | |
| OpDecorate %y Location 0 | |
| OpDecorate %outparm Location 0 | |
| %void = OpTypeVoid | |
| %6 = OpTypeFunction %void | |
| %int = OpTypeInt 32 1 | |
| %_ptr_Input_int = OpTypePointer Input %int | |
| %y = OpVariable %_ptr_Input_int Input | |
| %int_10 = OpConstant %int 10 | |
| %bool = OpTypeBool | |
| %_ptr_Function_int = OpTypePointer Function %int | |
| %int_23 = OpConstant %int 23 | |
| %int_5 = OpConstant %int 5 | |
| %_ptr_Output_int = OpTypePointer Output %int | |
| %outparm = OpVariable %_ptr_Output_int Output | |
| %15 = OpUndef %int | |
| %main = OpFunction %void None %6 | |
| %16 = OpLabel | |
| OpBranch %17 | |
| %17 = OpLabel | |
| %22 = OpPhi %int %15 %16 | |
| %23 = OpIAdd %int %22 %int_5 | |
| OpStore %outparm %23 | |
| OpReturn | |
| OpFunctionEnd | |
| )"; | |
| SinglePassRunAndCheck<CFGCleanupPass>(before, after, true, true); | |
| } | |
| } // namespace | |
| } // namespace opt | |
| } // namespace spvtools |