| // 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 |