diff options
Diffstat (limited to '3rdparty/bgfx/3rdparty/spirv-tools/test/fuzz/transformation_set_loop_control_test.cpp')
-rw-r--r-- | 3rdparty/bgfx/3rdparty/spirv-tools/test/fuzz/transformation_set_loop_control_test.cpp | 968 |
1 files changed, 968 insertions, 0 deletions
diff --git a/3rdparty/bgfx/3rdparty/spirv-tools/test/fuzz/transformation_set_loop_control_test.cpp b/3rdparty/bgfx/3rdparty/spirv-tools/test/fuzz/transformation_set_loop_control_test.cpp new file mode 100644 index 00000000000..83953ec0e6a --- /dev/null +++ b/3rdparty/bgfx/3rdparty/spirv-tools/test/fuzz/transformation_set_loop_control_test.cpp @@ -0,0 +1,968 @@ +// Copyright (c) 2019 Google LLC +// +// 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 "source/fuzz/transformation_set_loop_control.h" +#include "test/fuzz/fuzz_test_util.h" + +namespace spvtools { +namespace fuzz { +namespace { + +TEST(TransformationSetLoopControlTest, VariousScenarios) { + // This test features loops with various different controls, and goes through + // a number of acceptable and unacceptable transformations to those controls. + + std::string shader = R"( + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %4 "main" + OpExecutionMode %4 OriginUpperLeft + OpSource ESSL 310 + OpName %4 "main" + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeInt 32 1 + %7 = OpTypePointer Function %6 + %9 = OpConstant %6 0 + %16 = OpConstant %6 100 + %17 = OpTypeBool + %20 = OpConstant %6 1 + %4 = OpFunction %2 None %3 + %5 = OpLabel + %8 = OpVariable %7 Function + %22 = OpVariable %7 Function + %32 = OpVariable %7 Function + %42 = OpVariable %7 Function + %52 = OpVariable %7 Function + %62 = OpVariable %7 Function + %72 = OpVariable %7 Function + %82 = OpVariable %7 Function + %92 = OpVariable %7 Function + %102 = OpVariable %7 Function + %112 = OpVariable %7 Function + %122 = OpVariable %7 Function + OpStore %8 %9 + OpBranch %10 + %10 = OpLabel + %132 = OpPhi %6 %9 %5 %21 %13 + OpLoopMerge %12 %13 None + OpBranch %14 + %14 = OpLabel + %18 = OpSLessThan %17 %132 %16 + OpBranchConditional %18 %11 %12 + %11 = OpLabel + OpBranch %13 + %13 = OpLabel + %21 = OpIAdd %6 %132 %20 + OpStore %8 %21 + OpBranch %10 + %12 = OpLabel + OpStore %22 %9 + OpBranch %23 + %23 = OpLabel + %133 = OpPhi %6 %9 %12 %31 %26 + OpLoopMerge %25 %26 Unroll + OpBranch %27 + %27 = OpLabel + %29 = OpSLessThan %17 %133 %16 + OpBranchConditional %29 %24 %25 + %24 = OpLabel + OpBranch %26 + %26 = OpLabel + %31 = OpIAdd %6 %133 %20 + OpStore %22 %31 + OpBranch %23 + %25 = OpLabel + OpStore %32 %9 + OpBranch %33 + %33 = OpLabel + %134 = OpPhi %6 %9 %25 %41 %36 + OpLoopMerge %35 %36 DontUnroll + OpBranch %37 + %37 = OpLabel + %39 = OpSLessThan %17 %134 %16 + OpBranchConditional %39 %34 %35 + %34 = OpLabel + OpBranch %36 + %36 = OpLabel + %41 = OpIAdd %6 %134 %20 + OpStore %32 %41 + OpBranch %33 + %35 = OpLabel + OpStore %42 %9 + OpBranch %43 + %43 = OpLabel + %135 = OpPhi %6 %9 %35 %51 %46 + OpLoopMerge %45 %46 DependencyInfinite + OpBranch %47 + %47 = OpLabel + %49 = OpSLessThan %17 %135 %16 + OpBranchConditional %49 %44 %45 + %44 = OpLabel + OpBranch %46 + %46 = OpLabel + %51 = OpIAdd %6 %135 %20 + OpStore %42 %51 + OpBranch %43 + %45 = OpLabel + OpStore %52 %9 + OpBranch %53 + %53 = OpLabel + %136 = OpPhi %6 %9 %45 %61 %56 + OpLoopMerge %55 %56 DependencyLength 3 + OpBranch %57 + %57 = OpLabel + %59 = OpSLessThan %17 %136 %16 + OpBranchConditional %59 %54 %55 + %54 = OpLabel + OpBranch %56 + %56 = OpLabel + %61 = OpIAdd %6 %136 %20 + OpStore %52 %61 + OpBranch %53 + %55 = OpLabel + OpStore %62 %9 + OpBranch %63 + %63 = OpLabel + %137 = OpPhi %6 %9 %55 %71 %66 + OpLoopMerge %65 %66 MinIterations 10 + OpBranch %67 + %67 = OpLabel + %69 = OpSLessThan %17 %137 %16 + OpBranchConditional %69 %64 %65 + %64 = OpLabel + OpBranch %66 + %66 = OpLabel + %71 = OpIAdd %6 %137 %20 + OpStore %62 %71 + OpBranch %63 + %65 = OpLabel + OpStore %72 %9 + OpBranch %73 + %73 = OpLabel + %138 = OpPhi %6 %9 %65 %81 %76 + OpLoopMerge %75 %76 MaxIterations 50 + OpBranch %77 + %77 = OpLabel + %79 = OpSLessThan %17 %138 %16 + OpBranchConditional %79 %74 %75 + %74 = OpLabel + OpBranch %76 + %76 = OpLabel + %81 = OpIAdd %6 %138 %20 + OpStore %72 %81 + OpBranch %73 + %75 = OpLabel + OpStore %82 %9 + OpBranch %83 + %83 = OpLabel + %139 = OpPhi %6 %9 %75 %91 %86 + OpLoopMerge %85 %86 IterationMultiple 4 + OpBranch %87 + %87 = OpLabel + %89 = OpSLessThan %17 %139 %16 + OpBranchConditional %89 %84 %85 + %84 = OpLabel + OpBranch %86 + %86 = OpLabel + %91 = OpIAdd %6 %139 %20 + OpStore %82 %91 + OpBranch %83 + %85 = OpLabel + OpStore %92 %9 + OpBranch %93 + %93 = OpLabel + %140 = OpPhi %6 %9 %85 %101 %96 + OpLoopMerge %95 %96 PeelCount 2 + OpBranch %97 + %97 = OpLabel + %99 = OpSLessThan %17 %140 %16 + OpBranchConditional %99 %94 %95 + %94 = OpLabel + OpBranch %96 + %96 = OpLabel + %101 = OpIAdd %6 %140 %20 + OpStore %92 %101 + OpBranch %93 + %95 = OpLabel + OpStore %102 %9 + OpBranch %103 + %103 = OpLabel + %141 = OpPhi %6 %9 %95 %111 %106 + OpLoopMerge %105 %106 PartialCount 3 + OpBranch %107 + %107 = OpLabel + %109 = OpSLessThan %17 %141 %16 + OpBranchConditional %109 %104 %105 + %104 = OpLabel + OpBranch %106 + %106 = OpLabel + %111 = OpIAdd %6 %141 %20 + OpStore %102 %111 + OpBranch %103 + %105 = OpLabel + OpStore %112 %9 + OpBranch %113 + %113 = OpLabel + %142 = OpPhi %6 %9 %105 %121 %116 + OpLoopMerge %115 %116 Unroll|PeelCount|PartialCount 3 4 + OpBranch %117 + %117 = OpLabel + %119 = OpSLessThan %17 %142 %16 + OpBranchConditional %119 %114 %115 + %114 = OpLabel + OpBranch %116 + %116 = OpLabel + %121 = OpIAdd %6 %142 %20 + OpStore %112 %121 + OpBranch %113 + %115 = OpLabel + OpStore %122 %9 + OpBranch %123 + %123 = OpLabel + %143 = OpPhi %6 %9 %115 %131 %126 + OpLoopMerge %125 %126 DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount 2 5 90 4 7 14 + OpBranch %127 + %127 = OpLabel + %129 = OpSLessThan %17 %143 %16 + OpBranchConditional %129 %124 %125 + %124 = OpLabel + OpBranch %126 + %126 = OpLabel + %131 = OpIAdd %6 %143 %20 + OpStore %122 %131 + OpBranch %123 + %125 = OpLabel + OpReturn + OpFunctionEnd + )"; + + const auto env = SPV_ENV_UNIVERSAL_1_4; + const auto consumer = nullptr; + const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); + + ASSERT_TRUE(IsValid(env, context.get())); + + FactManager fact_manager; + + // These are the loop headers together with the selection controls of their + // merge instructions: + // %10 None + // %23 Unroll + // %33 DontUnroll + // %43 DependencyInfinite + // %53 DependencyLength 3 + // %63 MinIterations 10 + // %73 MaxIterations 50 + // %83 IterationMultiple 4 + // %93 PeelCount 2 + // %103 PartialCount 3 + // %113 Unroll|PeelCount|PartialCount 3 4 + // %123 + // DependencyLength|MinIterations|MaxIterations|IterationMultiple|PeelCount|PartialCount + // 2 5 90 4 7 14 + + ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(10, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(10, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE(TransformationSetLoopControl( + 10, SpvLoopControlDependencyInfiniteMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(10, SpvLoopControlDependencyLengthMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(10, SpvLoopControlMinIterationsMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(10, SpvLoopControlMaxIterationsMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE(TransformationSetLoopControl( + 10, SpvLoopControlIterationMultipleMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(10, SpvLoopControlPeelCountMask, 3, 3) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 0, 3) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(10, SpvLoopControlPartialCountMask, 3, 3) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl( + 10, + SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, + 3, 3) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(10, + SpvLoopControlUnrollMask | + SpvLoopControlPeelCountMask | + SpvLoopControlPartialCountMask, + 3, 3) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE(TransformationSetLoopControl(10, + SpvLoopControlDontUnrollMask | + SpvLoopControlPeelCountMask | + SpvLoopControlPartialCountMask, + 3, 3) + .IsApplicable(context.get(), fact_manager)); + + ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(23, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl( + 23, + SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, + 3, 3) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(23, SpvLoopControlMaxIterationsMask, 2, 3) + .IsApplicable(context.get(), fact_manager)); + + ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(33, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(33, SpvLoopControlMinIterationsMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl( + 33, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE(TransformationSetLoopControl(33, + SpvLoopControlDontUnrollMask | + SpvLoopControlPartialCountMask, + 0, 10) + .IsApplicable(context.get(), fact_manager)); + + ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(43, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(43, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl( + 43, + SpvLoopControlMaskNone | SpvLoopControlDependencyInfiniteMask, + 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl( + 43, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask, + 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl( + 43, + SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask, + 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(43, + SpvLoopControlDependencyInfiniteMask | + SpvLoopControlDependencyLengthMask, + 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl( + 43, SpvLoopControlUnrollMask | SpvLoopControlPeelCountMask, 5, 0) + .IsApplicable(context.get(), fact_manager)); + + ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(53, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(53, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(53, SpvLoopControlMaxIterationsMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl( + 53, SpvLoopControlMaskNone | SpvLoopControlDependencyLengthMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl( + 53, SpvLoopControlUnrollMask | SpvLoopControlDependencyInfiniteMask, + 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl( + 53, SpvLoopControlDontUnrollMask | SpvLoopControlDependencyLengthMask, + 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(53, + SpvLoopControlDependencyInfiniteMask | + SpvLoopControlDependencyLengthMask, + 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl( + 53, + SpvLoopControlUnrollMask | SpvLoopControlDependencyLengthMask | + SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, + 5, 3) + .IsApplicable(context.get(), fact_manager)); + + ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(63, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(63, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(63, + SpvLoopControlUnrollMask | + SpvLoopControlMinIterationsMask | + SpvLoopControlPeelCountMask | + SpvLoopControlPartialCountMask, + 5, 3) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(63, + SpvLoopControlUnrollMask | + SpvLoopControlMinIterationsMask | + SpvLoopControlPeelCountMask, + 23, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE(TransformationSetLoopControl( + 63, + SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask | + SpvLoopControlPeelCountMask, + 2, 23) + .IsApplicable(context.get(), fact_manager)); + + ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(73, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(73, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE(TransformationSetLoopControl( + 73, + SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask | + SpvLoopControlPeelCountMask | + SpvLoopControlPartialCountMask, + 5, 3) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(73, + SpvLoopControlUnrollMask | + SpvLoopControlMaxIterationsMask | + SpvLoopControlPeelCountMask, + 23, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE(TransformationSetLoopControl( + 73, + SpvLoopControlUnrollMask | SpvLoopControlMaxIterationsMask | + SpvLoopControlPeelCountMask, + 2, 23) + .IsApplicable(context.get(), fact_manager)); + + ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(83, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE(TransformationSetLoopControl( + 83, + SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask | + SpvLoopControlPeelCountMask | + SpvLoopControlPartialCountMask, + 5, 3) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(83, + SpvLoopControlUnrollMask | + SpvLoopControlIterationMultipleMask | + SpvLoopControlPeelCountMask, + 23, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(83, + SpvLoopControlUnrollMask | + SpvLoopControlIterationMultipleMask | + SpvLoopControlPeelCountMask, + 2, 23) + .IsApplicable(context.get(), fact_manager)); + + ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(93, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(93, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl(93, SpvLoopControlPeelCountMask, 8, 8) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(93, SpvLoopControlPartialCountMask, 0, 8) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl( + 93, + SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, + 16, 8) + .IsApplicable(context.get(), fact_manager)); + + ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(103, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(103, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE(TransformationSetLoopControl(103, + SpvLoopControlDontUnrollMask | + SpvLoopControlPartialCountMask, + 0, 60) + .IsApplicable(context.get(), fact_manager)); + + ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(113, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(113, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl( + 113, + SpvLoopControlIterationMultipleMask | SpvLoopControlPeelCountMask, 12, + 0) + .IsApplicable(context.get(), fact_manager)); + + ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlMaskNone, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(123, SpvLoopControlUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl(123, SpvLoopControlDontUnrollMask, 0, 0) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE( + TransformationSetLoopControl( + 123, + SpvLoopControlMinIterationsMask | SpvLoopControlMaxIterationsMask | + SpvLoopControlIterationMultipleMask | + SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, + 7, 8) + .IsApplicable(context.get(), fact_manager)); + ASSERT_TRUE(TransformationSetLoopControl(123, + SpvLoopControlUnrollMask | + SpvLoopControlMinIterationsMask | + SpvLoopControlMaxIterationsMask | + SpvLoopControlPartialCountMask, + 0, 9) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE(TransformationSetLoopControl( + 123, + SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask | + SpvLoopControlMaxIterationsMask | + SpvLoopControlPartialCountMask, + 7, 9) + .IsApplicable(context.get(), fact_manager)); + ASSERT_FALSE( + TransformationSetLoopControl( + 123, + SpvLoopControlDontUnrollMask | SpvLoopControlMinIterationsMask | + SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask, + 7, 9) + .IsApplicable(context.get(), fact_manager)); + + TransformationSetLoopControl(10, + SpvLoopControlUnrollMask | + SpvLoopControlPeelCountMask | + SpvLoopControlPartialCountMask, + 3, 3) + .Apply(context.get(), &fact_manager); + TransformationSetLoopControl(23, SpvLoopControlDontUnrollMask, 0, 0) + .Apply(context.get(), &fact_manager); + TransformationSetLoopControl(33, SpvLoopControlUnrollMask, 0, 0) + .Apply(context.get(), &fact_manager); + TransformationSetLoopControl( + 43, SpvLoopControlDontUnrollMask | SpvLoopControlDependencyInfiniteMask, + 0, 0) + .Apply(context.get(), &fact_manager); + TransformationSetLoopControl(53, SpvLoopControlMaskNone, 0, 0) + .Apply(context.get(), &fact_manager); + TransformationSetLoopControl(63, + SpvLoopControlUnrollMask | + SpvLoopControlMinIterationsMask | + SpvLoopControlPeelCountMask, + 23, 0) + .Apply(context.get(), &fact_manager); + TransformationSetLoopControl(73, + SpvLoopControlUnrollMask | + SpvLoopControlMaxIterationsMask | + SpvLoopControlPeelCountMask, + 23, 0) + .Apply(context.get(), &fact_manager); + TransformationSetLoopControl(83, SpvLoopControlDontUnrollMask, 0, 0) + .Apply(context.get(), &fact_manager); + TransformationSetLoopControl( + 93, SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, 16, 8) + .Apply(context.get(), &fact_manager); + TransformationSetLoopControl(103, SpvLoopControlPartialCountMask, 0, 60) + .Apply(context.get(), &fact_manager); + TransformationSetLoopControl(113, SpvLoopControlPeelCountMask, 12, 0) + .Apply(context.get(), &fact_manager); + TransformationSetLoopControl( + 123, + SpvLoopControlUnrollMask | SpvLoopControlMinIterationsMask | + SpvLoopControlMaxIterationsMask | SpvLoopControlPartialCountMask, + 0, 9) + .Apply(context.get(), &fact_manager); + + std::string after_transformation = R"( + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %4 "main" + OpExecutionMode %4 OriginUpperLeft + OpSource ESSL 310 + OpName %4 "main" + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeInt 32 1 + %7 = OpTypePointer Function %6 + %9 = OpConstant %6 0 + %16 = OpConstant %6 100 + %17 = OpTypeBool + %20 = OpConstant %6 1 + %4 = OpFunction %2 None %3 + %5 = OpLabel + %8 = OpVariable %7 Function + %22 = OpVariable %7 Function + %32 = OpVariable %7 Function + %42 = OpVariable %7 Function + %52 = OpVariable %7 Function + %62 = OpVariable %7 Function + %72 = OpVariable %7 Function + %82 = OpVariable %7 Function + %92 = OpVariable %7 Function + %102 = OpVariable %7 Function + %112 = OpVariable %7 Function + %122 = OpVariable %7 Function + OpStore %8 %9 + OpBranch %10 + %10 = OpLabel + %132 = OpPhi %6 %9 %5 %21 %13 + OpLoopMerge %12 %13 Unroll|PeelCount|PartialCount 3 3 + OpBranch %14 + %14 = OpLabel + %18 = OpSLessThan %17 %132 %16 + OpBranchConditional %18 %11 %12 + %11 = OpLabel + OpBranch %13 + %13 = OpLabel + %21 = OpIAdd %6 %132 %20 + OpStore %8 %21 + OpBranch %10 + %12 = OpLabel + OpStore %22 %9 + OpBranch %23 + %23 = OpLabel + %133 = OpPhi %6 %9 %12 %31 %26 + OpLoopMerge %25 %26 DontUnroll + OpBranch %27 + %27 = OpLabel + %29 = OpSLessThan %17 %133 %16 + OpBranchConditional %29 %24 %25 + %24 = OpLabel + OpBranch %26 + %26 = OpLabel + %31 = OpIAdd %6 %133 %20 + OpStore %22 %31 + OpBranch %23 + %25 = OpLabel + OpStore %32 %9 + OpBranch %33 + %33 = OpLabel + %134 = OpPhi %6 %9 %25 %41 %36 + OpLoopMerge %35 %36 Unroll + OpBranch %37 + %37 = OpLabel + %39 = OpSLessThan %17 %134 %16 + OpBranchConditional %39 %34 %35 + %34 = OpLabel + OpBranch %36 + %36 = OpLabel + %41 = OpIAdd %6 %134 %20 + OpStore %32 %41 + OpBranch %33 + %35 = OpLabel + OpStore %42 %9 + OpBranch %43 + %43 = OpLabel + %135 = OpPhi %6 %9 %35 %51 %46 + OpLoopMerge %45 %46 DontUnroll|DependencyInfinite + OpBranch %47 + %47 = OpLabel + %49 = OpSLessThan %17 %135 %16 + OpBranchConditional %49 %44 %45 + %44 = OpLabel + OpBranch %46 + %46 = OpLabel + %51 = OpIAdd %6 %135 %20 + OpStore %42 %51 + OpBranch %43 + %45 = OpLabel + OpStore %52 %9 + OpBranch %53 + %53 = OpLabel + %136 = OpPhi %6 %9 %45 %61 %56 + OpLoopMerge %55 %56 None + OpBranch %57 + %57 = OpLabel + %59 = OpSLessThan %17 %136 %16 + OpBranchConditional %59 %54 %55 + %54 = OpLabel + OpBranch %56 + %56 = OpLabel + %61 = OpIAdd %6 %136 %20 + OpStore %52 %61 + OpBranch %53 + %55 = OpLabel + OpStore %62 %9 + OpBranch %63 + %63 = OpLabel + %137 = OpPhi %6 %9 %55 %71 %66 + OpLoopMerge %65 %66 Unroll|MinIterations|PeelCount 10 23 + OpBranch %67 + %67 = OpLabel + %69 = OpSLessThan %17 %137 %16 + OpBranchConditional %69 %64 %65 + %64 = OpLabel + OpBranch %66 + %66 = OpLabel + %71 = OpIAdd %6 %137 %20 + OpStore %62 %71 + OpBranch %63 + %65 = OpLabel + OpStore %72 %9 + OpBranch %73 + %73 = OpLabel + %138 = OpPhi %6 %9 %65 %81 %76 + OpLoopMerge %75 %76 Unroll|MaxIterations|PeelCount 50 23 + OpBranch %77 + %77 = OpLabel + %79 = OpSLessThan %17 %138 %16 + OpBranchConditional %79 %74 %75 + %74 = OpLabel + OpBranch %76 + %76 = OpLabel + %81 = OpIAdd %6 %138 %20 + OpStore %72 %81 + OpBranch %73 + %75 = OpLabel + OpStore %82 %9 + OpBranch %83 + %83 = OpLabel + %139 = OpPhi %6 %9 %75 %91 %86 + OpLoopMerge %85 %86 DontUnroll + OpBranch %87 + %87 = OpLabel + %89 = OpSLessThan %17 %139 %16 + OpBranchConditional %89 %84 %85 + %84 = OpLabel + OpBranch %86 + %86 = OpLabel + %91 = OpIAdd %6 %139 %20 + OpStore %82 %91 + OpBranch %83 + %85 = OpLabel + OpStore %92 %9 + OpBranch %93 + %93 = OpLabel + %140 = OpPhi %6 %9 %85 %101 %96 + OpLoopMerge %95 %96 PeelCount|PartialCount 16 8 + OpBranch %97 + %97 = OpLabel + %99 = OpSLessThan %17 %140 %16 + OpBranchConditional %99 %94 %95 + %94 = OpLabel + OpBranch %96 + %96 = OpLabel + %101 = OpIAdd %6 %140 %20 + OpStore %92 %101 + OpBranch %93 + %95 = OpLabel + OpStore %102 %9 + OpBranch %103 + %103 = OpLabel + %141 = OpPhi %6 %9 %95 %111 %106 + OpLoopMerge %105 %106 PartialCount 60 + OpBranch %107 + %107 = OpLabel + %109 = OpSLessThan %17 %141 %16 + OpBranchConditional %109 %104 %105 + %104 = OpLabel + OpBranch %106 + %106 = OpLabel + %111 = OpIAdd %6 %141 %20 + OpStore %102 %111 + OpBranch %103 + %105 = OpLabel + OpStore %112 %9 + OpBranch %113 + %113 = OpLabel + %142 = OpPhi %6 %9 %105 %121 %116 + OpLoopMerge %115 %116 PeelCount 12 + OpBranch %117 + %117 = OpLabel + %119 = OpSLessThan %17 %142 %16 + OpBranchConditional %119 %114 %115 + %114 = OpLabel + OpBranch %116 + %116 = OpLabel + %121 = OpIAdd %6 %142 %20 + OpStore %112 %121 + OpBranch %113 + %115 = OpLabel + OpStore %122 %9 + OpBranch %123 + %123 = OpLabel + %143 = OpPhi %6 %9 %115 %131 %126 + OpLoopMerge %125 %126 Unroll|MinIterations|MaxIterations|PartialCount 5 90 9 + OpBranch %127 + %127 = OpLabel + %129 = OpSLessThan %17 %143 %16 + OpBranchConditional %129 %124 %125 + %124 = OpLabel + OpBranch %126 + %126 = OpLabel + %131 = OpIAdd %6 %143 %20 + OpStore %122 %131 + OpBranch %123 + %125 = OpLabel + OpReturn + OpFunctionEnd + )"; + ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); +} + +TEST(TransformationSetLoopControlTest, CheckSPIRVVersionsRespected) { + // This test checks that we do not allow introducing PeelCount and + // PartialCount loop controls if the SPIR-V version being used does not + // support them. + + std::string shader = R"( + OpCapability Shader + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %4 "main" + OpExecutionMode %4 OriginUpperLeft + OpSource ESSL 310 + OpName %4 "main" + OpName %8 "i" + %2 = OpTypeVoid + %3 = OpTypeFunction %2 + %6 = OpTypeInt 32 1 + %7 = OpTypePointer Function %6 + %9 = OpConstant %6 0 + %16 = OpConstant %6 10 + %17 = OpTypeBool + %20 = OpConstant %6 1 + %4 = OpFunction %2 None %3 + %5 = OpLabel + %8 = OpVariable %7 Function + OpStore %8 %9 + OpBranch %10 + %10 = OpLabel + OpLoopMerge %12 %13 None + OpBranch %14 + %14 = OpLabel + %15 = OpLoad %6 %8 + %18 = OpSLessThan %17 %15 %16 + OpBranchConditional %18 %11 %12 + %11 = OpLabel + OpBranch %13 + %13 = OpLabel + %19 = OpLoad %6 %8 + %21 = OpIAdd %6 %19 %20 + OpStore %8 %21 + OpBranch %10 + %12 = OpLabel + OpReturn + OpFunctionEnd + )"; + + const auto consumer = nullptr; + const auto context_1_0 = + BuildModule(SPV_ENV_UNIVERSAL_1_0, consumer, shader, kFuzzAssembleOption); + const auto context_1_1 = + BuildModule(SPV_ENV_UNIVERSAL_1_1, consumer, shader, kFuzzAssembleOption); + const auto context_1_2 = + BuildModule(SPV_ENV_UNIVERSAL_1_2, consumer, shader, kFuzzAssembleOption); + const auto context_1_3 = + BuildModule(SPV_ENV_UNIVERSAL_1_3, consumer, shader, kFuzzAssembleOption); + const auto context_1_4 = + BuildModule(SPV_ENV_UNIVERSAL_1_4, consumer, shader, kFuzzAssembleOption); + const auto context_1_5 = + BuildModule(SPV_ENV_UNIVERSAL_1_5, consumer, shader, kFuzzAssembleOption); + + FactManager fact_manager; + + TransformationSetLoopControl set_peel_and_partial( + 10, SpvLoopControlPeelCountMask | SpvLoopControlPartialCountMask, 4, 4); + + // PeelCount and PartialCount were introduced in SPIRV 1.4, so are not valid + // in the context of older versions. + ASSERT_FALSE( + set_peel_and_partial.IsApplicable(context_1_0.get(), fact_manager)); + ASSERT_FALSE( + set_peel_and_partial.IsApplicable(context_1_1.get(), fact_manager)); + ASSERT_FALSE( + set_peel_and_partial.IsApplicable(context_1_2.get(), fact_manager)); + ASSERT_FALSE( + set_peel_and_partial.IsApplicable(context_1_3.get(), fact_manager)); + + ASSERT_TRUE( + set_peel_and_partial.IsApplicable(context_1_4.get(), fact_manager)); + ASSERT_TRUE( + set_peel_and_partial.IsApplicable(context_1_5.get(), fact_manager)); +} + +} // namespace +} // namespace fuzz +} // namespace spvtools |