spirv-fuzz: Add swap commutable operands transformation (#3205)

In this PR, the classes that represent the swap commutable operands
transformation and the fuzzer pass were implemented.

Fixes #3205.
This commit is contained in:
Alastair Donaldson 2020-03-05 08:18:39 +00:00 коммит произвёл GitHub
Родитель 044ecc0b2c
Коммит 66a682b6a8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
13 изменённых файлов: 699 добавлений и 2 удалений

Просмотреть файл

@ -63,6 +63,7 @@ if(SPIRV_BUILD_FUZZER)
fuzzer_pass_outline_functions.h
fuzzer_pass_permute_blocks.h
fuzzer_pass_split_blocks.h
fuzzer_pass_swap_commutable_operands.h
fuzzer_util.h
id_use_descriptor.h
instruction_descriptor.h
@ -112,6 +113,7 @@ if(SPIRV_BUILD_FUZZER)
transformation_set_selection_control.h
transformation_split_block.h
transformation_store.h
transformation_swap_commutable_operands.h
transformation_vector_shuffle.h
uniform_buffer_element_descriptor.h
${CMAKE_CURRENT_BINARY_DIR}/protobufs/spvtoolsfuzz.pb.h
@ -149,6 +151,7 @@ if(SPIRV_BUILD_FUZZER)
fuzzer_pass_outline_functions.cpp
fuzzer_pass_permute_blocks.cpp
fuzzer_pass_split_blocks.cpp
fuzzer_pass_swap_commutable_operands.cpp
fuzzer_util.cpp
id_use_descriptor.cpp
instruction_descriptor.cpp
@ -197,6 +200,7 @@ if(SPIRV_BUILD_FUZZER)
transformation_set_selection_control.cpp
transformation_split_block.cpp
transformation_store.cpp
transformation_swap_commutable_operands.cpp
transformation_vector_shuffle.cpp
uniform_buffer_element_descriptor.cpp
${CMAKE_CURRENT_BINARY_DIR}/protobufs/spvtoolsfuzz.pb.cc

Просмотреть файл

@ -46,6 +46,7 @@
#include "source/fuzz/fuzzer_pass_outline_functions.h"
#include "source/fuzz/fuzzer_pass_permute_blocks.h"
#include "source/fuzz/fuzzer_pass_split_blocks.h"
#include "source/fuzz/fuzzer_pass_swap_commutable_operands.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/pseudo_random_generator.h"
#include "source/opt/build_module.h"
@ -280,6 +281,9 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
MaybeAddPass<FuzzerPassAddNoContractionDecorations>(
&final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
transformation_sequence_out);
MaybeAddPass<FuzzerPassSwapCommutableOperands>(
&final_passes, ir_context.get(), &fact_manager, &fuzzer_context,
transformation_sequence_out);
for (auto& pass : final_passes) {
if (!impl_->ApplyPassAndCheckValidity(pass.get(), *ir_context, tools)) {
return Fuzzer::FuzzerResultStatus::kFuzzerPassLedToInvalidModule;

Просмотреть файл

@ -0,0 +1,50 @@
// Copyright (c) 2020 André Perez Maselco
//
// 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/fuzzer_pass_swap_commutable_operands.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/instruction_descriptor.h"
#include "source/fuzz/transformation_swap_commutable_operands.h"
namespace spvtools {
namespace fuzz {
FuzzerPassSwapCommutableOperands::FuzzerPassSwapCommutableOperands(
opt::IRContext* ir_context, FactManager* fact_manager,
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations)
: FuzzerPass(ir_context, fact_manager, fuzzer_context, transformations) {}
FuzzerPassSwapCommutableOperands::~FuzzerPassSwapCommutableOperands() = default;
void FuzzerPassSwapCommutableOperands::Apply() {
auto context = GetIRContext();
// Iterates over the module's instructions and checks whether it is
// commutative. In this case, the transformation is probabilistically applied.
context->module()->ForEachInst(
[this, context](opt::Instruction* instruction) {
if (spvOpcodeIsCommutativeBinaryOperator(instruction->opcode()) &&
GetFuzzerContext()->ChooseEven()) {
auto instructionDescriptor =
MakeInstructionDescriptor(context, instruction);
auto transformation =
TransformationSwapCommutableOperands(instructionDescriptor);
ApplyTransformation(transformation);
}
});
}
} // namespace fuzz
} // namespace spvtools

Просмотреть файл

@ -0,0 +1,41 @@
// Copyright (c) 2020 André Perez Maselco
//
// 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.
#ifndef SOURCE_FUZZ_FUZZER_PASS_SWAP_COMMUTABLE_OPERANDS_H_
#define SOURCE_FUZZ_FUZZER_PASS_SWAP_COMMUTABLE_OPERANDS_H_
#include "source/fuzz/fuzzer_pass.h"
namespace spvtools {
namespace fuzz {
// This fuzzer pass searches for all commutative instructions in the module,
// probabilistically choosing which of these instructions will have its input
// operands swapped.
class FuzzerPassSwapCommutableOperands : public FuzzerPass {
public:
FuzzerPassSwapCommutableOperands(
opt::IRContext* ir_context, FactManager* fact_manager,
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
~FuzzerPassSwapCommutableOperands();
void Apply() override;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_FUZZER_PASS_SWAP_COMMUTABLE_OPERANDS_H_

Просмотреть файл

@ -369,6 +369,7 @@ message Transformation {
TransformationFunctionCall function_call = 38;
TransformationAccessChain access_chain = 39;
TransformationEquationInstruction equation_instruction = 40;
TransformationSwapCommutableOperands swap_commutable_operands = 41;
// Add additional option using the next available number.
}
}
@ -1068,6 +1069,15 @@ message TransformationStore {
}
message TransformationSwapCommutableOperands {
// A transformation that swaps the operands of a commutative instruction.
// A descriptor for a commutative instruction
InstructionDescriptor instruction_descriptor = 1;
}
message TransformationVectorShuffle {
// A transformation that adds a vector shuffle instruction.

Просмотреть файл

@ -56,6 +56,7 @@
#include "source/fuzz/transformation_set_selection_control.h"
#include "source/fuzz/transformation_split_block.h"
#include "source/fuzz/transformation_store.h"
#include "source/fuzz/transformation_swap_commutable_operands.h"
#include "source/fuzz/transformation_vector_shuffle.h"
#include "source/util/make_unique.h"
@ -170,6 +171,9 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
return MakeUnique<TransformationSplitBlock>(message.split_block());
case protobufs::Transformation::TransformationCase::kStore:
return MakeUnique<TransformationStore>(message.store());
case protobufs::Transformation::TransformationCase::kSwapCommutableOperands:
return MakeUnique<TransformationSwapCommutableOperands>(
message.swap_commutable_operands());
case protobufs::Transformation::TransformationCase::kVectorShuffle:
return MakeUnique<TransformationVectorShuffle>(message.vector_shuffle());
case protobufs::Transformation::TRANSFORMATION_NOT_SET:

Просмотреть файл

@ -0,0 +1,66 @@
// Copyright (c) 2020 André Perez Maselco
//
// 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_swap_commutable_operands.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/instruction_descriptor.h"
namespace spvtools {
namespace fuzz {
TransformationSwapCommutableOperands::TransformationSwapCommutableOperands(
const spvtools::fuzz::protobufs::TransformationSwapCommutableOperands&
message)
: message_(message) {}
TransformationSwapCommutableOperands::TransformationSwapCommutableOperands(
const protobufs::InstructionDescriptor& instruction_descriptor) {
*message_.mutable_instruction_descriptor() = instruction_descriptor;
}
bool TransformationSwapCommutableOperands::IsApplicable(
opt::IRContext* context, const spvtools::fuzz::FactManager& /*unused*/
) const {
auto instruction =
FindInstruction(message_.instruction_descriptor(), context);
if (instruction == nullptr) return false;
SpvOp opcode = static_cast<SpvOp>(
message_.instruction_descriptor().target_instruction_opcode());
assert(instruction->opcode() == opcode &&
"The located instruction must have the same opcode as in the "
"descriptor.");
return spvOpcodeIsCommutativeBinaryOperator(opcode);
}
void TransformationSwapCommutableOperands::Apply(
opt::IRContext* context, spvtools::fuzz::FactManager* /*unused*/
) const {
auto instruction =
FindInstruction(message_.instruction_descriptor(), context);
// By design, the instructions defined to be commutative have exactly two
// input parameters.
std::swap(instruction->GetInOperand(0), instruction->GetInOperand(1));
}
protobufs::Transformation TransformationSwapCommutableOperands::ToMessage()
const {
protobufs::Transformation result;
*result.mutable_swap_commutable_operands() = message_;
return result;
}
} // namespace fuzz
} // namespace spvtools

Просмотреть файл

@ -0,0 +1,51 @@
// Copyright (c) 2020 André Perez Maselco
//
// 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.
#ifndef SOURCE_FUZZ_TRANSFORMATION_SWAP_COMMUTABLE_OPERANDS_H_
#define SOURCE_FUZZ_TRANSFORMATION_SWAP_COMMUTABLE_OPERANDS_H_
#include "source/fuzz/fact_manager.h"
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
class TransformationSwapCommutableOperands : public Transformation {
public:
explicit TransformationSwapCommutableOperands(
const protobufs::TransformationSwapCommutableOperands& message);
TransformationSwapCommutableOperands(
const protobufs::InstructionDescriptor& instruction_descriptor);
// - |message_.instruction_descriptor| must identify an existing
// commutative instruction
bool IsApplicable(opt::IRContext* context,
const FactManager& fact_manager) const override;
// Swaps the commutable operands.
void Apply(opt::IRContext* context, FactManager* fact_manager) const override;
protobufs::Transformation ToMessage() const override;
private:
protobufs::TransformationSwapCommutableOperands message_;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_TRANSFORMATION_SWAP_COMMUTABLE_OPERANDS_H_

Просмотреть файл

@ -612,6 +612,39 @@ bool spvOpcodeIsDebug(SpvOp opcode) {
}
}
bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode) {
switch (opcode) {
case SpvOpPtrEqual:
case SpvOpPtrNotEqual:
case SpvOpIAdd:
case SpvOpFAdd:
case SpvOpIMul:
case SpvOpFMul:
case SpvOpDot:
case SpvOpIAddCarry:
case SpvOpUMulExtended:
case SpvOpSMulExtended:
case SpvOpBitwiseOr:
case SpvOpBitwiseXor:
case SpvOpBitwiseAnd:
case SpvOpOrdered:
case SpvOpUnordered:
case SpvOpLogicalEqual:
case SpvOpLogicalNotEqual:
case SpvOpLogicalOr:
case SpvOpLogicalAnd:
case SpvOpIEqual:
case SpvOpINotEqual:
case SpvOpFOrdEqual:
case SpvOpFUnordEqual:
case SpvOpFOrdNotEqual:
case SpvOpFUnordNotEqual:
return true;
default:
return false;
}
}
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode) {
switch (opcode) {
case SpvOpMemoryBarrier:

Просмотреть файл

@ -130,6 +130,10 @@ bool spvOpcodeIsScalarizable(SpvOp opcode);
// Returns true if the given opcode is a debug instruction.
bool spvOpcodeIsDebug(SpvOp opcode);
// Returns true for opcodes that are binary operators,
// where the order of the operands is irrelevant.
bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode);
// Returns a vector containing the indices of the memory semantics <id>
// operands for |opcode|.
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode);

Просмотреть файл

@ -63,6 +63,7 @@ if (${SPIRV_BUILD_FUZZER})
transformation_set_selection_control_test.cpp
transformation_split_block_test.cpp
transformation_store_test.cpp
transformation_swap_commutable_operands_test.cpp
transformation_vector_shuffle_test.cpp
uniform_buffer_element_descriptor_test.cpp)

Просмотреть файл

@ -0,0 +1,427 @@
// Copyright (c) 2020 André Perez Maselco
//
// 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_swap_commutable_operands.h"
#include "source/fuzz/instruction_descriptor.h"
#include "test/fuzz/fuzz_test_util.h"
namespace spvtools {
namespace fuzz {
namespace {
TEST(TransformationSwapCommutableOperandsTest, IsApplicableTest) {
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 = OpTypeInt 32 0
%8 = OpConstant %7 2
%9 = OpTypeArray %6 %8
%10 = OpTypePointer Function %9
%12 = OpConstant %6 1
%13 = OpConstant %6 2
%14 = OpConstantComposite %9 %12 %13
%15 = OpTypePointer Function %6
%17 = OpConstant %6 0
%29 = OpTypeFloat 32
%30 = OpTypeArray %29 %8
%31 = OpTypePointer Function %30
%33 = OpConstant %29 1
%34 = OpConstant %29 2
%35 = OpConstantComposite %30 %33 %34
%36 = OpTypePointer Function %29
%49 = OpTypeVector %29 3
%50 = OpTypeArray %49 %8
%51 = OpTypePointer Function %50
%53 = OpConstant %29 3
%54 = OpConstantComposite %49 %33 %34 %53
%55 = OpConstant %29 4
%56 = OpConstant %29 5
%57 = OpConstant %29 6
%58 = OpConstantComposite %49 %55 %56 %57
%59 = OpConstantComposite %50 %54 %58
%61 = OpTypePointer Function %49
%4 = OpFunction %2 None %3
%5 = OpLabel
%11 = OpVariable %10 Function
%16 = OpVariable %15 Function
%23 = OpVariable %15 Function
%32 = OpVariable %31 Function
%37 = OpVariable %36 Function
%43 = OpVariable %36 Function
%52 = OpVariable %51 Function
%60 = OpVariable %36 Function
OpStore %11 %14
%18 = OpAccessChain %15 %11 %17
%19 = OpLoad %6 %18
%20 = OpAccessChain %15 %11 %12
%21 = OpLoad %6 %20
%22 = OpIAdd %6 %19 %21
OpStore %16 %22
%24 = OpAccessChain %15 %11 %17
%25 = OpLoad %6 %24
%26 = OpAccessChain %15 %11 %12
%27 = OpLoad %6 %26
%28 = OpIMul %6 %25 %27
OpStore %23 %28
OpStore %32 %35
%38 = OpAccessChain %36 %32 %17
%39 = OpLoad %29 %38
%40 = OpAccessChain %36 %32 %12
%41 = OpLoad %29 %40
%42 = OpFAdd %29 %39 %41
OpStore %37 %42
%44 = OpAccessChain %36 %32 %17
%45 = OpLoad %29 %44
%46 = OpAccessChain %36 %32 %12
%47 = OpLoad %29 %46
%48 = OpFMul %29 %45 %47
OpStore %43 %48
OpStore %52 %59
%62 = OpAccessChain %61 %52 %17
%63 = OpLoad %49 %62
%64 = OpAccessChain %61 %52 %12
%65 = OpLoad %49 %64
%66 = OpDot %29 %63 %65
OpStore %60 %66
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_5;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager factManager;
// Tests existing commutative instructions
auto instructionDescriptor = MakeInstructionDescriptor(22, SpvOpIAdd, 0);
auto transformation =
TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(28, SpvOpIMul, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(42, SpvOpFAdd, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(48, SpvOpFMul, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(66, SpvOpDot, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_TRUE(transformation.IsApplicable(context.get(), factManager));
// Tests existing non-commutative instructions
instructionDescriptor = MakeInstructionDescriptor(1, SpvOpExtInstImport, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(5, SpvOpLabel, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(8, SpvOpConstant, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(11, SpvOpVariable, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor =
MakeInstructionDescriptor(14, SpvOpConstantComposite, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
// Tests the base instruction id not existing
instructionDescriptor = MakeInstructionDescriptor(67, SpvOpIAddCarry, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(68, SpvOpIEqual, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(69, SpvOpINotEqual, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(70, SpvOpFOrdEqual, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(71, SpvOpPtrEqual, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
// Tests there being no instruction with the desired opcode after the base
// instruction id
instructionDescriptor = MakeInstructionDescriptor(24, SpvOpIAdd, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(38, SpvOpIMul, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(45, SpvOpFAdd, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(66, SpvOpFMul, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
// Tests there being an instruction with the desired opcode after the base
// instruction id, but the skip count associated with the instruction
// descriptor being so high.
instructionDescriptor = MakeInstructionDescriptor(11, SpvOpIAdd, 100);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(16, SpvOpIMul, 100);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(23, SpvOpFAdd, 100);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(32, SpvOpFMul, 100);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
instructionDescriptor = MakeInstructionDescriptor(37, SpvOpDot, 100);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
ASSERT_FALSE(transformation.IsApplicable(context.get(), factManager));
}
TEST(TransformationSwapCommutableOperandsTest, ApplyTest) {
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 = OpTypeInt 32 0
%8 = OpConstant %7 2
%9 = OpTypeArray %6 %8
%10 = OpTypePointer Function %9
%12 = OpConstant %6 1
%13 = OpConstant %6 2
%14 = OpConstantComposite %9 %12 %13
%15 = OpTypePointer Function %6
%17 = OpConstant %6 0
%29 = OpTypeFloat 32
%30 = OpTypeArray %29 %8
%31 = OpTypePointer Function %30
%33 = OpConstant %29 1
%34 = OpConstant %29 2
%35 = OpConstantComposite %30 %33 %34
%36 = OpTypePointer Function %29
%49 = OpTypeVector %29 3
%50 = OpTypeArray %49 %8
%51 = OpTypePointer Function %50
%53 = OpConstant %29 3
%54 = OpConstantComposite %49 %33 %34 %53
%55 = OpConstant %29 4
%56 = OpConstant %29 5
%57 = OpConstant %29 6
%58 = OpConstantComposite %49 %55 %56 %57
%59 = OpConstantComposite %50 %54 %58
%61 = OpTypePointer Function %49
%4 = OpFunction %2 None %3
%5 = OpLabel
%11 = OpVariable %10 Function
%16 = OpVariable %15 Function
%23 = OpVariable %15 Function
%32 = OpVariable %31 Function
%37 = OpVariable %36 Function
%43 = OpVariable %36 Function
%52 = OpVariable %51 Function
%60 = OpVariable %36 Function
OpStore %11 %14
%18 = OpAccessChain %15 %11 %17
%19 = OpLoad %6 %18
%20 = OpAccessChain %15 %11 %12
%21 = OpLoad %6 %20
%22 = OpIAdd %6 %19 %21
OpStore %16 %22
%24 = OpAccessChain %15 %11 %17
%25 = OpLoad %6 %24
%26 = OpAccessChain %15 %11 %12
%27 = OpLoad %6 %26
%28 = OpIMul %6 %25 %27
OpStore %23 %28
OpStore %32 %35
%38 = OpAccessChain %36 %32 %17
%39 = OpLoad %29 %38
%40 = OpAccessChain %36 %32 %12
%41 = OpLoad %29 %40
%42 = OpFAdd %29 %39 %41
OpStore %37 %42
%44 = OpAccessChain %36 %32 %17
%45 = OpLoad %29 %44
%46 = OpAccessChain %36 %32 %12
%47 = OpLoad %29 %46
%48 = OpFMul %29 %45 %47
OpStore %43 %48
OpStore %52 %59
%62 = OpAccessChain %61 %52 %17
%63 = OpLoad %49 %62
%64 = OpAccessChain %61 %52 %12
%65 = OpLoad %49 %64
%66 = OpDot %29 %63 %65
OpStore %60 %66
OpReturn
OpFunctionEnd
)";
const auto env = SPV_ENV_UNIVERSAL_1_5;
const auto consumer = nullptr;
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
ASSERT_TRUE(IsValid(env, context.get()));
FactManager factManager;
auto instructionDescriptor = MakeInstructionDescriptor(22, SpvOpIAdd, 0);
auto transformation =
TransformationSwapCommutableOperands(instructionDescriptor);
transformation.Apply(context.get(), &factManager);
instructionDescriptor = MakeInstructionDescriptor(28, SpvOpIMul, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
transformation.Apply(context.get(), &factManager);
instructionDescriptor = MakeInstructionDescriptor(42, SpvOpFAdd, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
transformation.Apply(context.get(), &factManager);
instructionDescriptor = MakeInstructionDescriptor(48, SpvOpFMul, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
transformation.Apply(context.get(), &factManager);
instructionDescriptor = MakeInstructionDescriptor(66, SpvOpDot, 0);
transformation = TransformationSwapCommutableOperands(instructionDescriptor);
transformation.Apply(context.get(), &factManager);
std::string variantShader = 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 = OpTypeInt 32 0
%8 = OpConstant %7 2
%9 = OpTypeArray %6 %8
%10 = OpTypePointer Function %9
%12 = OpConstant %6 1
%13 = OpConstant %6 2
%14 = OpConstantComposite %9 %12 %13
%15 = OpTypePointer Function %6
%17 = OpConstant %6 0
%29 = OpTypeFloat 32
%30 = OpTypeArray %29 %8
%31 = OpTypePointer Function %30
%33 = OpConstant %29 1
%34 = OpConstant %29 2
%35 = OpConstantComposite %30 %33 %34
%36 = OpTypePointer Function %29
%49 = OpTypeVector %29 3
%50 = OpTypeArray %49 %8
%51 = OpTypePointer Function %50
%53 = OpConstant %29 3
%54 = OpConstantComposite %49 %33 %34 %53
%55 = OpConstant %29 4
%56 = OpConstant %29 5
%57 = OpConstant %29 6
%58 = OpConstantComposite %49 %55 %56 %57
%59 = OpConstantComposite %50 %54 %58
%61 = OpTypePointer Function %49
%4 = OpFunction %2 None %3
%5 = OpLabel
%11 = OpVariable %10 Function
%16 = OpVariable %15 Function
%23 = OpVariable %15 Function
%32 = OpVariable %31 Function
%37 = OpVariable %36 Function
%43 = OpVariable %36 Function
%52 = OpVariable %51 Function
%60 = OpVariable %36 Function
OpStore %11 %14
%18 = OpAccessChain %15 %11 %17
%19 = OpLoad %6 %18
%20 = OpAccessChain %15 %11 %12
%21 = OpLoad %6 %20
%22 = OpIAdd %6 %21 %19
OpStore %16 %22
%24 = OpAccessChain %15 %11 %17
%25 = OpLoad %6 %24
%26 = OpAccessChain %15 %11 %12
%27 = OpLoad %6 %26
%28 = OpIMul %6 %27 %25
OpStore %23 %28
OpStore %32 %35
%38 = OpAccessChain %36 %32 %17
%39 = OpLoad %29 %38
%40 = OpAccessChain %36 %32 %12
%41 = OpLoad %29 %40
%42 = OpFAdd %29 %41 %39
OpStore %37 %42
%44 = OpAccessChain %36 %32 %17
%45 = OpLoad %29 %44
%46 = OpAccessChain %36 %32 %12
%47 = OpLoad %29 %46
%48 = OpFMul %29 %47 %45
OpStore %43 %48
OpStore %52 %59
%62 = OpAccessChain %61 %52 %17
%63 = OpLoad %49 %62
%64 = OpAccessChain %61 %52 %12
%65 = OpLoad %49 %64
%66 = OpDot %29 %65 %63
OpStore %60 %66
OpReturn
OpFunctionEnd
)";
ASSERT_TRUE(IsEqual(env, variantShader, context.get()));
}
} // namespace
} // namespace fuzz
} // namespace spvtools

Просмотреть файл

@ -1,4 +1,5 @@
#!/usr/bin/env python
# coding=utf-8
# Copyright (c) 2016 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
@ -31,7 +32,8 @@ AUTHORS = ['The Khronos Group Inc.',
'Google Inc.',
'Google LLC',
'Pierre Moreau',
'Samsung Inc']
'Samsung Inc',
'André Perez Maselco']
CURRENT_YEAR='2020'
YEARS = '(2014-2016|2015-2016|2016|2016-2017|2017|2017-2019|2018|2019|2020)'
@ -167,7 +169,7 @@ def alert_if_no_copyright(glob, comment_prefix):
has_apache2 = False
line_num = 0
apache_expected_end = 0
with open(file) as contents:
with open(file, encoding='utf-8') as contents:
for line in contents:
line_num += 1
if COPYRIGHT_RE.search(line):