// 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 #include #include #include "../assembly_builder.h" #include "../function_utils.h" #include "../pass_fixture.h" #include "../pass_utils.h" #include "opt/dominator_analysis.h" #include "opt/pass.h" namespace { using namespace spvtools; using ::testing::UnorderedElementsAre; using PassClassTest = PassTest<::testing::Test>; /* Generated from the following GLSL #version 440 core layout(location = 0) out vec4 v; layout(location = 1) in vec4 in_val; void main() { int i; switch (int(in_val.x)) { case 0: i = 0; case 1: i = 1; break; case 2: i = 2; case 3: i = 3; case 4: i = 4; break; default: i = 0; } v = vec4(i, i, i, i); } */ TEST_F(PassClassTest, UnreachableNestedIfs) { const std::string text = R"( OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %4 "main" %9 %35 OpExecutionMode %4 OriginUpperLeft OpSource GLSL 440 OpName %4 "main" OpName %9 "in_val" OpName %25 "i" OpName %35 "v" OpDecorate %9 Location 1 OpDecorate %35 Location 0 %2 = OpTypeVoid %3 = OpTypeFunction %2 %6 = OpTypeFloat 32 %7 = OpTypeVector %6 4 %8 = OpTypePointer Input %7 %9 = OpVariable %8 Input %10 = OpTypeInt 32 0 %11 = OpConstant %10 0 %12 = OpTypePointer Input %6 %15 = OpTypeInt 32 1 %24 = OpTypePointer Function %15 %26 = OpConstant %15 0 %27 = OpConstant %15 1 %29 = OpConstant %15 2 %30 = OpConstant %15 3 %31 = OpConstant %15 4 %34 = OpTypePointer Output %7 %35 = OpVariable %34 Output %4 = OpFunction %2 None %3 %5 = OpLabel %25 = OpVariable %24 Function %13 = OpAccessChain %12 %9 %11 %14 = OpLoad %6 %13 %16 = OpConvertFToS %15 %14 OpSelectionMerge %23 None OpSwitch %16 %22 0 %17 1 %18 2 %19 3 %20 4 %21 %22 = OpLabel OpStore %25 %26 OpBranch %23 %17 = OpLabel OpStore %25 %26 OpBranch %18 %18 = OpLabel OpStore %25 %27 OpBranch %23 %19 = OpLabel OpStore %25 %29 OpBranch %20 %20 = OpLabel OpStore %25 %30 OpBranch %21 %21 = OpLabel OpStore %25 %31 OpBranch %23 %23 = OpLabel %36 = OpLoad %15 %25 %37 = OpConvertSToF %6 %36 %38 = OpLoad %15 %25 %39 = OpConvertSToF %6 %38 %40 = OpLoad %15 %25 %41 = OpConvertSToF %6 %40 %42 = OpLoad %15 %25 %43 = OpConvertSToF %6 %42 %44 = OpCompositeConstruct %7 %37 %39 %41 %43 OpStore %35 %44 OpReturn OpFunctionEnd )"; // clang-format on std::unique_ptr context = BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); ir::Module* module = context->module(); EXPECT_NE(nullptr, module) << "Assembling failed for shader:\n" << text << std::endl; const ir::Function* f = spvtest::GetFunction(module, 4); ir::CFG cfg(module); opt::DominatorAnalysis* analysis = context->GetDominatorAnalysis(f, cfg); EXPECT_TRUE(analysis->Dominates(5, 5)); EXPECT_TRUE(analysis->Dominates(5, 17)); EXPECT_TRUE(analysis->Dominates(5, 18)); EXPECT_TRUE(analysis->Dominates(5, 19)); EXPECT_TRUE(analysis->Dominates(5, 20)); EXPECT_TRUE(analysis->Dominates(5, 21)); EXPECT_TRUE(analysis->Dominates(5, 22)); EXPECT_TRUE(analysis->Dominates(5, 23)); EXPECT_TRUE(analysis->StrictlyDominates(5, 17)); EXPECT_TRUE(analysis->StrictlyDominates(5, 18)); EXPECT_TRUE(analysis->StrictlyDominates(5, 19)); EXPECT_TRUE(analysis->StrictlyDominates(5, 20)); EXPECT_TRUE(analysis->StrictlyDominates(5, 21)); EXPECT_TRUE(analysis->StrictlyDominates(5, 22)); EXPECT_TRUE(analysis->StrictlyDominates(5, 23)); } } // namespace