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