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:
Родитель
044ecc0b2c
Коммит
66a682b6a8
|
@ -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):
|
||||
|
|
Загрузка…
Ссылка в новой задаче