blob: 088938ef84d0dc29acae17dbbf402c3cd3b37e82 [file] [log] [blame]
// Copyright (c) 2020 Vasyl Teliman
//
// 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_move_instruction_down.h"
#include "source/fuzz/instruction_descriptor.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
TEST(TransformationMoveInstructionDownTest, BasicTest) {
std::string shader = R"(
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %4 "main"
OpExecutionMode %4 OriginUpperLeft
OpSource ESSL 310
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%9 = OpConstant %6 0
%16 = OpTypeBool
%17 = OpConstantFalse %16
%20 = OpUndef %6
%13 = OpTypePointer Function %6
%4 = OpFunction %2 None %3
%5 = OpLabel
%12 = OpVariable %13 Function
%10 = OpIAdd %6 %9 %9
%11 = OpISub %6 %9 %10
OpStore %12 %10
%14 = OpLoad %6 %12
%15 = OpIMul %6 %9 %14
OpSelectionMerge %19 None
OpBranchConditional %17 %18 %19
%18 = OpLabel
OpBranch %19
%19 = OpLabel
%22 = OpIAdd %6 %15 %15
%21 = OpIAdd %6 %15 %15
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_3;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager fact_manager;
spvtools::ValidatorOptions validator_options;
TransformationContext transformation_context(&fact_manager,
validator_options);
// Instruction descriptor is invalid.
ASSERT_FALSE(TransformationMoveInstructionDown(
MakeInstructionDescriptor(30, SpvOpNop, 0))
.IsApplicable(context.get(), transformation_context));
// Opcode is not supported.
ASSERT_FALSE(TransformationMoveInstructionDown(
MakeInstructionDescriptor(5, SpvOpLabel, 0))
.IsApplicable(context.get(), transformation_context));
ASSERT_FALSE(TransformationMoveInstructionDown(
MakeInstructionDescriptor(12, SpvOpVariable, 0))
.IsApplicable(context.get(), transformation_context));
ASSERT_FALSE(TransformationMoveInstructionDown(
MakeInstructionDescriptor(11, SpvOpStore, 0))
.IsApplicable(context.get(), transformation_context));
ASSERT_FALSE(TransformationMoveInstructionDown(
MakeInstructionDescriptor(14, SpvOpLoad, 0))
.IsApplicable(context.get(), transformation_context));
// Can't move the last instruction in the block.
ASSERT_FALSE(TransformationMoveInstructionDown(
MakeInstructionDescriptor(15, SpvOpBranchConditional, 0))
.IsApplicable(context.get(), transformation_context));
// Can't move the instruction if the next instruction is the last one in the
// block.
ASSERT_FALSE(TransformationMoveInstructionDown(
MakeInstructionDescriptor(21, SpvOpIAdd, 0))
.IsApplicable(context.get(), transformation_context));
// Can't insert instruction's opcode after its successor.
ASSERT_FALSE(TransformationMoveInstructionDown(
MakeInstructionDescriptor(15, SpvOpIMul, 0))
.IsApplicable(context.get(), transformation_context));
// Instruction's successor depends on the instruction.
ASSERT_FALSE(TransformationMoveInstructionDown(
MakeInstructionDescriptor(10, SpvOpIAdd, 0))
.IsApplicable(context.get(), transformation_context));
{
TransformationMoveInstructionDown transformation(
MakeInstructionDescriptor(11, SpvOpISub, 0));
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
transformation.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
}
{
TransformationMoveInstructionDown transformation(
MakeInstructionDescriptor(22, SpvOpIAdd, 0));
ASSERT_TRUE(
transformation.IsApplicable(context.get(), transformation_context));
transformation.Apply(context.get(), &transformation_context);
ASSERT_TRUE(IsValid(env, context.get()));
}
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
%2 = OpTypeVoid
%3 = OpTypeFunction %2
%6 = OpTypeInt 32 1
%9 = OpConstant %6 0
%16 = OpTypeBool
%17 = OpConstantFalse %16
%20 = OpUndef %6
%13 = OpTypePointer Function %6
%4 = OpFunction %2 None %3
%5 = OpLabel
%12 = OpVariable %13 Function
%10 = OpIAdd %6 %9 %9
OpStore %12 %10
%11 = OpISub %6 %9 %10
%14 = OpLoad %6 %12
%15 = OpIMul %6 %9 %14
OpSelectionMerge %19 None
OpBranchConditional %17 %18 %19
%18 = OpLabel
OpBranch %19
%19 = OpLabel
%21 = OpIAdd %6 %15 %15
%22 = OpIAdd %6 %15 %15
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
}
} // namespace
} // namespace fuzz
} // namespace spvtools