Updated spirv-tools.

This commit is contained in:
Бранимир Караџић
2020-06-18 21:48:39 -07:00
parent 685eeed252
commit 4979ee49ab
29 changed files with 813 additions and 50 deletions

View File

@@ -1 +1 @@
"v2020.4-dev", "SPIRV-Tools v2020.4-dev 2cdcab3215d654e18c3b6d5f12bd94e7e64fb8b1"
"v2020.4-dev", "SPIRV-Tools v2020.4-dev 685eeed2529a1671c875d204406decacdff43cb3"

View File

@@ -49,6 +49,7 @@ if(SPIRV_BUILD_FUZZER)
fuzzer_pass_add_local_variables.h
fuzzer_pass_add_no_contraction_decorations.h
fuzzer_pass_add_stores.h
fuzzer_pass_add_vector_shuffle_instructions.h
fuzzer_pass_adjust_branch_weights.h
fuzzer_pass_adjust_function_controls.h
fuzzer_pass_adjust_loop_controls.h
@@ -64,6 +65,7 @@ if(SPIRV_BUILD_FUZZER)
fuzzer_pass_permute_blocks.h
fuzzer_pass_permute_function_parameters.h
fuzzer_pass_push_ids_through_variables.h
fuzzer_pass_replace_linear_algebra_instructions.h
fuzzer_pass_split_blocks.h
fuzzer_pass_swap_commutable_operands.h
fuzzer_pass_toggle_access_chain_instruction.h
@@ -117,6 +119,7 @@ if(SPIRV_BUILD_FUZZER)
transformation_replace_boolean_constant_with_constant_binary.h
transformation_replace_constant_with_uniform.h
transformation_replace_id_with_synonym.h
transformation_replace_linear_algebra_instruction.h
transformation_set_function_control.h
transformation_set_loop_control.h
transformation_set_memory_operands_mask.h
@@ -148,6 +151,7 @@ if(SPIRV_BUILD_FUZZER)
fuzzer_pass_add_local_variables.cpp
fuzzer_pass_add_no_contraction_decorations.cpp
fuzzer_pass_add_stores.cpp
fuzzer_pass_add_vector_shuffle_instructions.cpp
fuzzer_pass_adjust_branch_weights.cpp
fuzzer_pass_adjust_function_controls.cpp
fuzzer_pass_adjust_loop_controls.cpp
@@ -163,6 +167,7 @@ if(SPIRV_BUILD_FUZZER)
fuzzer_pass_permute_blocks.cpp
fuzzer_pass_permute_function_parameters.cpp
fuzzer_pass_push_ids_through_variables.cpp
fuzzer_pass_replace_linear_algebra_instructions.cpp
fuzzer_pass_split_blocks.cpp
fuzzer_pass_swap_commutable_operands.cpp
fuzzer_pass_toggle_access_chain_instruction.cpp
@@ -215,6 +220,7 @@ if(SPIRV_BUILD_FUZZER)
transformation_replace_boolean_constant_with_constant_binary.cpp
transformation_replace_constant_with_uniform.cpp
transformation_replace_id_with_synonym.cpp
transformation_replace_linear_algebra_instruction.cpp
transformation_set_function_control.cpp
transformation_set_loop_control.cpp
transformation_set_memory_operands_mask.cpp

View File

@@ -33,6 +33,7 @@
#include "source/fuzz/fuzzer_pass_add_local_variables.h"
#include "source/fuzz/fuzzer_pass_add_no_contraction_decorations.h"
#include "source/fuzz/fuzzer_pass_add_stores.h"
#include "source/fuzz/fuzzer_pass_add_vector_shuffle_instructions.h"
#include "source/fuzz/fuzzer_pass_adjust_branch_weights.h"
#include "source/fuzz/fuzzer_pass_adjust_function_controls.h"
#include "source/fuzz/fuzzer_pass_adjust_loop_controls.h"
@@ -47,6 +48,7 @@
#include "source/fuzz/fuzzer_pass_permute_blocks.h"
#include "source/fuzz/fuzzer_pass_permute_function_parameters.h"
#include "source/fuzz/fuzzer_pass_push_ids_through_variables.h"
#include "source/fuzz/fuzzer_pass_replace_linear_algebra_instructions.h"
#include "source/fuzz/fuzzer_pass_split_blocks.h"
#include "source/fuzz/fuzzer_pass_swap_commutable_operands.h"
#include "source/fuzz/fuzzer_pass_toggle_access_chain_instruction.h"
@@ -223,6 +225,9 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
MaybeAddPass<FuzzerPassAddStores>(&passes, ir_context.get(),
&transformation_context, &fuzzer_context,
transformation_sequence_out);
MaybeAddPass<FuzzerPassAddVectorShuffleInstructions>(
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
transformation_sequence_out);
MaybeAddPass<FuzzerPassApplyIdSynonyms>(
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
transformation_sequence_out);
@@ -253,6 +258,9 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
MaybeAddPass<FuzzerPassPushIdsThroughVariables>(
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
transformation_sequence_out);
MaybeAddPass<FuzzerPassReplaceLinearAlgebraInstructions>(
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
transformation_sequence_out);
MaybeAddPass<FuzzerPassSplitBlocks>(
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
transformation_sequence_out);

View File

@@ -40,6 +40,7 @@ const std::pair<uint32_t, uint32_t> kChanceOfAddingNoContractionDecoration = {
5, 70};
const std::pair<uint32_t, uint32_t> kChanceOfAddingStore = {5, 50};
const std::pair<uint32_t, uint32_t> kChanceOfAddingVectorType = {20, 70};
const std::pair<uint32_t, uint32_t> kChanceOfAddingVectorShuffle = {20, 70};
const std::pair<uint32_t, uint32_t> kChanceOfAdjustingBranchWeights = {20, 90};
const std::pair<uint32_t, uint32_t> kChanceOfAdjustingFunctionControl = {20,
70};
@@ -64,6 +65,8 @@ const std::pair<uint32_t, uint32_t> kChanceOfOutliningFunction = {10, 90};
const std::pair<uint32_t, uint32_t> kChanceOfPermutingParameters = {30, 90};
const std::pair<uint32_t, uint32_t> kChanceOfPushingIdThroughVariable = {5, 50};
const std::pair<uint32_t, uint32_t> kChanceOfReplacingIdWithSynonym = {10, 90};
const std::pair<uint32_t, uint32_t>
kChanceOfReplacingLinearAlgebraInstructions = {10, 90};
const std::pair<uint32_t, uint32_t> kChanceOfSplittingBlock = {40, 95};
const std::pair<uint32_t, uint32_t> kChanceOfTogglingAccessChainInstruction = {
20, 90};
@@ -124,6 +127,8 @@ FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
chance_of_adding_no_contraction_decoration_ =
ChooseBetweenMinAndMax(kChanceOfAddingNoContractionDecoration);
chance_of_adding_store_ = ChooseBetweenMinAndMax(kChanceOfAddingStore);
chance_of_adding_vector_shuffle_ =
ChooseBetweenMinAndMax(kChanceOfAddingVectorShuffle);
chance_of_adding_vector_type_ =
ChooseBetweenMinAndMax(kChanceOfAddingVectorType);
chance_of_adjusting_branch_weights_ =
@@ -162,6 +167,8 @@ FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
ChooseBetweenMinAndMax(kChanceOfPushingIdThroughVariable);
chance_of_replacing_id_with_synonym_ =
ChooseBetweenMinAndMax(kChanceOfReplacingIdWithSynonym);
chance_of_replacing_linear_algebra_instructions_ =
ChooseBetweenMinAndMax(kChanceOfReplacingLinearAlgebraInstructions);
chance_of_splitting_block_ = ChooseBetweenMinAndMax(kChanceOfSplittingBlock);
chance_of_toggling_access_chain_instruction_ =
ChooseBetweenMinAndMax(kChanceOfTogglingAccessChainInstruction);
@@ -171,6 +178,16 @@ FuzzerContext::~FuzzerContext() = default;
uint32_t FuzzerContext::GetFreshId() { return next_fresh_id_++; }
std::vector<uint32_t> FuzzerContext::GetFreshIds(const uint32_t count) {
std::vector<uint32_t> fresh_ids(count);
for (uint32_t& fresh_id : fresh_ids) {
fresh_id = next_fresh_id_++;
}
return fresh_ids;
}
bool FuzzerContext::ChooseEven() { return random_generator_->RandomBool(); }
bool FuzzerContext::ChoosePercentage(uint32_t percentage_chance) {

View File

@@ -100,6 +100,9 @@ class FuzzerContext {
// or to have been issued before.
uint32_t GetFreshId();
// Returns a vector of |count| fresh ids.
std::vector<uint32_t> GetFreshIds(const uint32_t count);
// Probabilities associated with applying various transformations.
// Keep them in alphabetical order.
uint32_t GetChanceOfAddingAccessChain() {
@@ -133,6 +136,9 @@ class FuzzerContext {
return chance_of_adding_no_contraction_decoration_;
}
uint32_t GetChanceOfAddingStore() { return chance_of_adding_store_; }
uint32_t GetChanceOfAddingVectorShuffle() {
return chance_of_adding_vector_shuffle_;
}
uint32_t GetChanceOfAddingVectorType() {
return chance_of_adding_vector_type_;
}
@@ -185,6 +191,9 @@ class FuzzerContext {
uint32_t GetChanceOfReplacingIdWithSynonym() {
return chance_of_replacing_id_with_synonym_;
}
uint32_t GetChanceOfReplacingLinearAlgebraInstructions() {
return chance_of_replacing_linear_algebra_instructions_;
}
uint32_t GetChanceOfSplittingBlock() { return chance_of_splitting_block_; }
uint32_t GetChanceOfTogglingAccessChainInstruction() {
return chance_of_toggling_access_chain_instruction_;
@@ -195,18 +204,6 @@ class FuzzerContext {
uint32_t GetMaximumEquivalenceClassSizeForDataSynonymFactClosure() {
return max_equivalence_class_size_for_data_synonym_fact_closure_;
}
uint32_t GetRandomIndexForAccessChain(uint32_t composite_size_bound) {
return random_generator_->RandomUint32(composite_size_bound);
}
uint32_t GetRandomLoopControlPartialCount() {
return random_generator_->RandomUint32(max_loop_control_partial_count_);
}
uint32_t GetRandomLoopControlPeelCount() {
return random_generator_->RandomUint32(max_loop_control_peel_count_);
}
uint32_t GetRandomLoopLimit() {
return random_generator_->RandomUint32(max_loop_limit_);
}
std::pair<uint32_t, uint32_t> GetRandomBranchWeights() {
std::pair<uint32_t, uint32_t> branch_weights = {0, 0};
@@ -219,6 +216,29 @@ class FuzzerContext {
return branch_weights;
}
std::vector<uint32_t> GetRandomComponentsForVectorShuffle(
uint32_t max_component_index) {
// Component count must be in range [2, 4].
std::vector<uint32_t> components(random_generator_->RandomUint32(2) + 2);
for (uint32_t& component : components) {
component = random_generator_->RandomUint32(max_component_index);
}
return components;
}
uint32_t GetRandomIndexForAccessChain(uint32_t composite_size_bound) {
return random_generator_->RandomUint32(composite_size_bound);
}
uint32_t GetRandomLoopControlPartialCount() {
return random_generator_->RandomUint32(max_loop_control_partial_count_);
}
uint32_t GetRandomLoopControlPeelCount() {
return random_generator_->RandomUint32(max_loop_control_peel_count_);
}
uint32_t GetRandomLoopLimit() {
return random_generator_->RandomUint32(max_loop_limit_);
}
uint32_t GetRandomSizeForNewArray() {
// Ensure that the array size is non-zero.
return random_generator_->RandomUint32(max_new_array_size_limit_ - 1) + 1;
@@ -248,6 +268,7 @@ class FuzzerContext {
uint32_t chance_of_adding_matrix_type_;
uint32_t chance_of_adding_no_contraction_decoration_;
uint32_t chance_of_adding_store_;
uint32_t chance_of_adding_vector_shuffle_;
uint32_t chance_of_adding_vector_type_;
uint32_t chance_of_adjusting_branch_weights_;
uint32_t chance_of_adjusting_function_control_;
@@ -268,6 +289,7 @@ class FuzzerContext {
uint32_t chance_of_permuting_parameters_;
uint32_t chance_of_pushing_id_through_variable_;
uint32_t chance_of_replacing_id_with_synonym_;
uint32_t chance_of_replacing_linear_algebra_instructions_;
uint32_t chance_of_splitting_block_;
uint32_t chance_of_toggling_access_chain_instruction_;

View File

@@ -0,0 +1,133 @@
// 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_add_vector_shuffle_instructions.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/instruction_descriptor.h"
#include "source/fuzz/transformation_vector_shuffle.h"
namespace spvtools {
namespace fuzz {
FuzzerPassAddVectorShuffleInstructions::FuzzerPassAddVectorShuffleInstructions(
opt::IRContext* ir_context, TransformationContext* transformation_context,
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations)
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
FuzzerPassAddVectorShuffleInstructions::
~FuzzerPassAddVectorShuffleInstructions() = default;
void FuzzerPassAddVectorShuffleInstructions::Apply() {
ForEachInstructionWithInstructionDescriptor(
[this](opt::Function* function, opt::BasicBlock* block,
opt::BasicBlock::iterator instruction_iterator,
const protobufs::InstructionDescriptor& instruction_descriptor)
-> void {
assert(instruction_iterator->opcode() ==
instruction_descriptor.target_instruction_opcode() &&
"The opcode of the instruction we might insert before must be "
"the same as the opcode in the descriptor for the instruction");
// Randomly decide whether to try adding an OpVectorShuffle instruction.
if (!GetFuzzerContext()->ChoosePercentage(
GetFuzzerContext()->GetChanceOfAddingVectorShuffle())) {
return;
}
// It must be valid to insert an OpVectorShuffle instruction
// before |instruction_iterator|.
if (!fuzzerutil::CanInsertOpcodeBeforeInstruction(
SpvOpVectorShuffle, instruction_iterator)) {
return;
}
// Looks for vectors that we might consider to use as OpVectorShuffle
// operands.
std::vector<opt::Instruction*> vector_instructions =
FindAvailableInstructions(
function, block, instruction_iterator,
[instruction_descriptor](
opt::IRContext* ir_context,
opt::Instruction* instruction) -> bool {
if (!instruction->type_id()) {
return false;
}
if (!ir_context->get_type_mgr()
->GetType(instruction->type_id())
->AsVector()) {
return false;
}
return fuzzerutil::IdIsAvailableBeforeInstruction(
ir_context,
FindInstruction(instruction_descriptor, ir_context),
instruction->result_id());
});
// If there are no vector instructions, then return.
if (vector_instructions.empty()) {
return;
}
auto vector_1_instruction =
vector_instructions[GetFuzzerContext()->RandomIndex(
vector_instructions)];
auto vector_1_type = GetIRContext()
->get_type_mgr()
->GetType(vector_1_instruction->type_id())
->AsVector();
auto vector_2_instruction =
GetFuzzerContext()->RemoveAtRandomIndex(&vector_instructions);
auto vector_2_type = GetIRContext()
->get_type_mgr()
->GetType(vector_2_instruction->type_id())
->AsVector();
// |vector_1| and |vector_2| must have the same element type as each
// other. The loop is guaranteed to terminate because each iteration
// removes on possible choice for |vector_2|, and there is at least one
// choice that will cause the loop to exit - namely |vector_1|.
while (vector_1_type->element_type() != vector_2_type->element_type()) {
vector_2_instruction =
GetFuzzerContext()->RemoveAtRandomIndex(&vector_instructions);
vector_2_type = GetIRContext()
->get_type_mgr()
->GetType(vector_2_instruction->type_id())
->AsVector();
}
// Gets components and creates the appropriate result vector type.
std::vector<uint32_t> components =
GetFuzzerContext()->GetRandomComponentsForVectorShuffle(
vector_1_type->element_count() +
vector_2_type->element_count());
FindOrCreateVectorType(GetIRContext()->get_type_mgr()->GetId(
vector_1_type->element_type()),
static_cast<uint32_t>(components.size()));
// Applies the vector shuffle transformation.
ApplyTransformation(TransformationVectorShuffle(
instruction_descriptor, GetFuzzerContext()->GetFreshId(),
vector_1_instruction->result_id(),
vector_2_instruction->result_id(), components));
});
}
} // namespace fuzz
} // namespace spvtools

View File

@@ -0,0 +1,39 @@
// 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_ADD_VECTOR_SHUFFLE_INSTRUCTIONS_H_
#define SOURCE_FUZZ_FUZZER_PASS_ADD_VECTOR_SHUFFLE_INSTRUCTIONS_H_
#include "source/fuzz/fuzzer_pass.h"
namespace spvtools {
namespace fuzz {
// Adds OpVectorShuffle instructions to the module.
class FuzzerPassAddVectorShuffleInstructions : public FuzzerPass {
public:
FuzzerPassAddVectorShuffleInstructions(
opt::IRContext* ir_context, TransformationContext* transformation_context,
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
~FuzzerPassAddVectorShuffleInstructions();
void Apply() override;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_VECTOR_SHUFFLE_INSTRUCTIONS_H_

View File

@@ -0,0 +1,64 @@
// 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_replace_linear_algebra_instructions.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/instruction_descriptor.h"
#include "source/fuzz/transformation_replace_linear_algebra_instruction.h"
namespace spvtools {
namespace fuzz {
FuzzerPassReplaceLinearAlgebraInstructions::
FuzzerPassReplaceLinearAlgebraInstructions(
opt::IRContext* ir_context,
TransformationContext* transformation_context,
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations)
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
transformations) {}
FuzzerPassReplaceLinearAlgebraInstructions::
~FuzzerPassReplaceLinearAlgebraInstructions() = default;
void FuzzerPassReplaceLinearAlgebraInstructions::Apply() {
// For each instruction, checks whether it is a supported linear algebra
// instruction. In this case, the transformation is randomly applied.
GetIRContext()->module()->ForEachInst([this](opt::Instruction* instruction) {
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3354):
// Right now we only support certain operations. When this issue is
// addressed the following conditional can use the function
// |spvOpcodeIsLinearAlgebra|.
if (instruction->opcode() != SpvOpVectorTimesScalar &&
instruction->opcode() != SpvOpDot) {
return;
}
if (!GetFuzzerContext()->ChoosePercentage(
GetFuzzerContext()
->GetChanceOfReplacingLinearAlgebraInstructions())) {
return;
}
ApplyTransformation(TransformationReplaceLinearAlgebraInstruction(
GetFuzzerContext()->GetFreshIds(
TransformationReplaceLinearAlgebraInstruction::
GetRequiredFreshIdCount(GetIRContext(), instruction)),
MakeInstructionDescriptor(GetIRContext(), instruction)));
});
}
} // namespace fuzz
} // namespace spvtools

View File

@@ -0,0 +1,40 @@
// 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_REPLACE_LINEAR_ALGEBRA_INSTRUCTIONS_H_
#define SOURCE_FUZZ_FUZZER_PASS_REPLACE_LINEAR_ALGEBRA_INSTRUCTIONS_H_
#include "source/fuzz/fuzzer_pass.h"
namespace spvtools {
namespace fuzz {
// This fuzzer pass replaces linear algebra instructions with its mathematical
// definition.
class FuzzerPassReplaceLinearAlgebraInstructions : public FuzzerPass {
public:
FuzzerPassReplaceLinearAlgebraInstructions(
opt::IRContext* ir_context, TransformationContext* transformation_context,
FuzzerContext* fuzzer_context,
protobufs::TransformationSequence* transformations);
~FuzzerPassReplaceLinearAlgebraInstructions();
void Apply() override;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_FUZZER_PASS_REPLACE_LINEAR_ALGEBRA_INSTRUCTIONS_H_

View File

@@ -377,6 +377,7 @@ message Transformation {
TransformationAdjustBranchWeights adjust_branch_weights = 46;
TransformationPushIdThroughVariable push_id_through_variable = 47;
TransformationAddSpecConstantOp add_spec_constant_op = 48;
TransformationReplaceLinearAlgebraInstruction replace_linear_algebra_instruction = 49;
// Add additional option using the next available number.
}
}
@@ -1081,6 +1082,33 @@ message TransformationReplaceIdWithSynonym {
}
message TransformationReplaceLinearAlgebraInstruction {
// Replaces a linear algebra instruction with its
// mathematical definition.
// The fresh ids needed to apply the transformation.
repeated uint32 fresh_ids = 1;
// A descriptor for a linear algebra instruction.
// This transformation is only applicable if the described instruction has one of the following opcodes.
// Supported:
// OpVectorTimesScalar
// OpDot
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3354):
// Right now we only support certain operations. When this issue is addressed
// the supporting comments can be removed.
// To be supported in the future:
// OpTranspose
// OpMatrixTimesScalar
// OpVectorTimesMatrix
// OpMatrixTimesVector
// OpMatrixTimesMatrix
// OpOuterProduct
InstructionDescriptor instruction_descriptor = 2;
}
message TransformationSetFunctionControl {
// A transformation that sets the function control operand of an OpFunction

View File

@@ -56,6 +56,7 @@
#include "source/fuzz/transformation_replace_boolean_constant_with_constant_binary.h"
#include "source/fuzz/transformation_replace_constant_with_uniform.h"
#include "source/fuzz/transformation_replace_id_with_synonym.h"
#include "source/fuzz/transformation_replace_linear_algebra_instruction.h"
#include "source/fuzz/transformation_set_function_control.h"
#include "source/fuzz/transformation_set_loop_control.h"
#include "source/fuzz/transformation_set_memory_operands_mask.h"
@@ -182,6 +183,10 @@ std::unique_ptr<Transformation> Transformation::FromMessage(
case protobufs::Transformation::TransformationCase::kReplaceIdWithSynonym:
return MakeUnique<TransformationReplaceIdWithSynonym>(
message.replace_id_with_synonym());
case protobufs::Transformation::TransformationCase::
kReplaceLinearAlgebraInstruction:
return MakeUnique<TransformationReplaceLinearAlgebraInstruction>(
message.replace_linear_algebra_instruction());
case protobufs::Transformation::TransformationCase::kSetFunctionControl:
return MakeUnique<TransformationSetFunctionControl>(
message.set_function_control());

View File

@@ -0,0 +1,275 @@
// 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_replace_linear_algebra_instruction.h"
#include "source/fuzz/fuzzer_util.h"
#include "source/fuzz/instruction_descriptor.h"
namespace spvtools {
namespace fuzz {
TransformationReplaceLinearAlgebraInstruction::
TransformationReplaceLinearAlgebraInstruction(
const spvtools::fuzz::protobufs::
TransformationReplaceLinearAlgebraInstruction& message)
: message_(message) {}
TransformationReplaceLinearAlgebraInstruction::
TransformationReplaceLinearAlgebraInstruction(
const std::vector<uint32_t>& fresh_ids,
const protobufs::InstructionDescriptor& instruction_descriptor) {
for (auto fresh_id : fresh_ids) {
message_.add_fresh_ids(fresh_id);
}
*message_.mutable_instruction_descriptor() = instruction_descriptor;
}
bool TransformationReplaceLinearAlgebraInstruction::IsApplicable(
opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
auto instruction =
FindInstruction(message_.instruction_descriptor(), ir_context);
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3354):
// Right now we only support certain operations. When this issue is addressed
// the following conditional can use the function |spvOpcodeIsLinearAlgebra|.
// It must be a supported linear algebra instruction.
if (instruction->opcode() != SpvOpVectorTimesScalar &&
instruction->opcode() != SpvOpDot) {
return false;
}
// |message_.fresh_ids.size| must be the exact number of fresh ids needed to
// apply the transformation.
if (static_cast<uint32_t>(message_.fresh_ids().size()) !=
GetRequiredFreshIdCount(ir_context, instruction)) {
return false;
}
// All ids in |message_.fresh_ids| must be fresh.
for (uint32_t i = 0; i < static_cast<uint32_t>(message_.fresh_ids().size());
i++) {
if (!fuzzerutil::IsFreshId(ir_context, message_.fresh_ids(i))) {
return false;
}
}
return true;
}
void TransformationReplaceLinearAlgebraInstruction::Apply(
opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
auto linear_algebra_instruction =
FindInstruction(message_.instruction_descriptor(), ir_context);
switch (linear_algebra_instruction->opcode()) {
case SpvOpVectorTimesScalar:
ReplaceOpVectorTimesScalar(ir_context, linear_algebra_instruction);
break;
case SpvOpDot:
ReplaceOpDot(ir_context, linear_algebra_instruction);
break;
default:
assert(false && "Should be unreachable.");
break;
}
ir_context->InvalidateAnalysesExceptFor(opt::IRContext::kAnalysisNone);
}
protobufs::Transformation
TransformationReplaceLinearAlgebraInstruction::ToMessage() const {
protobufs::Transformation result;
*result.mutable_replace_linear_algebra_instruction() = message_;
return result;
}
uint32_t TransformationReplaceLinearAlgebraInstruction::GetRequiredFreshIdCount(
opt::IRContext* ir_context, opt::Instruction* instruction) {
// TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3354):
// Right now we only support certain operations.
switch (instruction->opcode()) {
case SpvOpVectorTimesScalar:
// For each vector component, 1 OpCompositeExtract and 1 OpFMul will be
// inserted.
return 2 *
ir_context->get_type_mgr()
->GetType(ir_context->get_def_use_mgr()
->GetDef(instruction->GetSingleWordInOperand(0))
->type_id())
->AsVector()
->element_count();
case SpvOpDot: {
// For each pair of vector components, 2 OpCompositeExtract and 1 OpFMul
// will be inserted. The first two OpFMul instructions will result the
// first OpFAdd instruction to be inserted. For each remaining OpFMul, 1
// OpFAdd will be inserted. The last OpFAdd instruction is got by changing
// the OpDot instruction.
return 4 * ir_context->get_type_mgr()
->GetType(
ir_context->get_def_use_mgr()
->GetDef(instruction->GetSingleWordInOperand(0))
->type_id())
->AsVector()
->element_count() -
2;
}
default:
assert(false && "Unsupported linear algebra instruction.");
return 0;
}
}
void TransformationReplaceLinearAlgebraInstruction::ReplaceOpVectorTimesScalar(
opt::IRContext* ir_context,
opt::Instruction* linear_algebra_instruction) const {
// Gets OpVectorTimesScalar in operands.
auto vector = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(0));
auto scalar = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(1));
uint32_t vector_component_count = ir_context->get_type_mgr()
->GetType(vector->type_id())
->AsVector()
->element_count();
std::vector<uint32_t> float_multiplication_ids(vector_component_count);
uint32_t fresh_id_index = 0;
for (uint32_t i = 0; i < vector_component_count; i++) {
// Extracts |vector| component.
uint32_t vector_extract_id = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, vector_extract_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpCompositeExtract, scalar->type_id(), vector_extract_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
// Multiplies the |vector| component with the |scalar|.
uint32_t float_multiplication_id = message_.fresh_ids(fresh_id_index++);
float_multiplication_ids[i] = float_multiplication_id;
fuzzerutil::UpdateModuleIdBound(ir_context, float_multiplication_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpFMul, scalar->type_id(), float_multiplication_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_extract_id}},
{SPV_OPERAND_TYPE_ID, {scalar->result_id()}}})));
}
// The OpVectorTimesScalar instruction is changed to an OpCompositeConstruct
// instruction.
linear_algebra_instruction->SetOpcode(SpvOpCompositeConstruct);
linear_algebra_instruction->SetInOperand(0, {float_multiplication_ids[0]});
linear_algebra_instruction->SetInOperand(1, {float_multiplication_ids[1]});
for (uint32_t i = 2; i < float_multiplication_ids.size(); i++) {
linear_algebra_instruction->AddOperand(
{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[i]}});
}
}
void TransformationReplaceLinearAlgebraInstruction::ReplaceOpDot(
opt::IRContext* ir_context,
opt::Instruction* linear_algebra_instruction) const {
// Gets OpDot in operands.
auto vector_1 = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(0));
auto vector_2 = ir_context->get_def_use_mgr()->GetDef(
linear_algebra_instruction->GetSingleWordInOperand(1));
uint32_t vectors_component_count = ir_context->get_type_mgr()
->GetType(vector_1->type_id())
->AsVector()
->element_count();
std::vector<uint32_t> float_multiplication_ids(vectors_component_count);
uint32_t fresh_id_index = 0;
for (uint32_t i = 0; i < vectors_component_count; i++) {
// Extracts |vector_1| component.
uint32_t vector_1_extract_id = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, vector_1_extract_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpCompositeExtract,
linear_algebra_instruction->type_id(), vector_1_extract_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_1->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
// Extracts |vector_2| component.
uint32_t vector_2_extract_id = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, vector_2_extract_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpCompositeExtract,
linear_algebra_instruction->type_id(), vector_2_extract_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_2->result_id()}},
{SPV_OPERAND_TYPE_LITERAL_INTEGER, {i}}})));
// Multiplies the pair of components.
float_multiplication_ids[i] = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, float_multiplication_ids[i]);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpFMul, linear_algebra_instruction->type_id(),
float_multiplication_ids[i],
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {vector_1_extract_id}},
{SPV_OPERAND_TYPE_ID, {vector_2_extract_id}}})));
}
// If the vector has 2 components, then there will be 2 float multiplication
// instructions.
if (vectors_component_count == 2) {
linear_algebra_instruction->SetOpcode(SpvOpFAdd);
linear_algebra_instruction->SetInOperand(0, {float_multiplication_ids[0]});
linear_algebra_instruction->SetInOperand(1, {float_multiplication_ids[1]});
} else {
// The first OpFAdd instruction has as operands the first two OpFMul
// instructions.
std::vector<uint32_t> float_add_ids;
uint32_t float_add_id = message_.fresh_ids(fresh_id_index++);
float_add_ids.push_back(float_add_id);
fuzzerutil::UpdateModuleIdBound(ir_context, float_add_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpFAdd, linear_algebra_instruction->type_id(),
float_add_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[0]}},
{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[1]}}})));
// The remaining OpFAdd instructions has as operands an OpFMul and an OpFAdd
// instruction.
for (uint32_t i = 2; i < float_multiplication_ids.size() - 1; i++) {
float_add_id = message_.fresh_ids(fresh_id_index++);
fuzzerutil::UpdateModuleIdBound(ir_context, float_add_id);
float_add_ids.push_back(float_add_id);
linear_algebra_instruction->InsertBefore(MakeUnique<opt::Instruction>(
ir_context, SpvOpFAdd, linear_algebra_instruction->type_id(),
float_add_id,
opt::Instruction::OperandList(
{{SPV_OPERAND_TYPE_ID, {float_multiplication_ids[i]}},
{SPV_OPERAND_TYPE_ID, {float_add_ids[i - 2]}}})));
}
// The last OpFAdd instruction is got by changing some of the OpDot
// instruction attributes.
linear_algebra_instruction->SetOpcode(SpvOpFAdd);
linear_algebra_instruction->SetInOperand(
0, {float_multiplication_ids[float_multiplication_ids.size() - 1]});
linear_algebra_instruction->SetInOperand(
1, {float_add_ids[float_add_ids.size() - 1]});
}
}
} // namespace fuzz
} // namespace spvtools

View File

@@ -0,0 +1,67 @@
// 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_REPLACE_LINEAR_ALGEBRA_INSTRUCTION_H_
#define SOURCE_FUZZ_TRANSFORMATION_REPLACE_LINEAR_ALGEBRA_INSTRUCTION_H_
#include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
#include "source/fuzz/transformation.h"
#include "source/fuzz/transformation_context.h"
#include "source/opt/ir_context.h"
namespace spvtools {
namespace fuzz {
class TransformationReplaceLinearAlgebraInstruction : public Transformation {
public:
explicit TransformationReplaceLinearAlgebraInstruction(
const protobufs::TransformationReplaceLinearAlgebraInstruction& message);
TransformationReplaceLinearAlgebraInstruction(
const std::vector<uint32_t>& fresh_ids,
const protobufs::InstructionDescriptor& instruction_descriptor);
// - |message_.fresh_ids| must be fresh ids needed to apply the
// transformation.
// - |message_.instruction_descriptor| must be a linear algebra instruction
bool IsApplicable(
opt::IRContext* ir_context,
const TransformationContext& transformation_context) const override;
// Replaces a linear algebra instruction.
void Apply(opt::IRContext* ir_context,
TransformationContext* transformation_context) const override;
protobufs::Transformation ToMessage() const override;
// Returns the number of ids needed to apply the transformation.
static uint32_t GetRequiredFreshIdCount(opt::IRContext* ir_context,
opt::Instruction* instruction);
private:
protobufs::TransformationReplaceLinearAlgebraInstruction message_;
// Replaces an OpVectorTimesScalar instruction.
void ReplaceOpVectorTimesScalar(opt::IRContext* ir_context,
opt::Instruction* instruction) const;
// Replaces an OpDot instruction.
void ReplaceOpDot(opt::IRContext* ir_context,
opt::Instruction* instruction) const;
};
} // namespace fuzz
} // namespace spvtools
#endif // SOURCE_FUZZ_TRANSFORMATION_REPLACE_LINEAR_ALGEBRA_INSTRUCTION_H_

View File

@@ -650,6 +650,22 @@ bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode) {
}
}
bool spvOpcodeIsLinearAlgebra(SpvOp opcode) {
switch (opcode) {
case SpvOpTranspose:
case SpvOpVectorTimesScalar:
case SpvOpMatrixTimesScalar:
case SpvOpVectorTimesMatrix:
case SpvOpMatrixTimesVector:
case SpvOpMatrixTimesMatrix:
case SpvOpOuterProduct:
case SpvOpDot:
return true;
default:
return false;
}
}
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode) {
switch (opcode) {
case SpvOpMemoryBarrier:

View File

@@ -134,6 +134,9 @@ bool spvOpcodeIsDebug(SpvOp opcode);
// where the order of the operands is irrelevant.
bool spvOpcodeIsCommutativeBinaryOperator(SpvOp opcode);
// Returns true for opcodes that represents linear algebra instructions.
bool spvOpcodeIsLinearAlgebra(SpvOp opcode);
// Returns a vector containing the indices of the memory semantics <id>
// operands for |opcode|.
std::vector<uint32_t> spvOpcodeMemorySemanticsOperandIndices(SpvOp opcode);

View File

@@ -455,7 +455,7 @@ bool spvIsInIdType(spv_operand_type_t type) {
return false;
}
switch (type) {
// Blacklist non-input IDs.
// Deny non-input IDs.
case SPV_OPERAND_TYPE_TYPE_ID:
case SPV_OPERAND_TYPE_RESULT_ID:
return false;

View File

@@ -131,11 +131,11 @@ void AggressiveDCEPass::AddStores(uint32_t ptrId) {
}
bool AggressiveDCEPass::AllExtensionsSupported() const {
// If any extension not in whitelist, return false
// If any extension not in allowlist, return false
for (auto& ei : get_module()->extensions()) {
const char* extName =
reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
if (extensions_whitelist_.find(extName) == extensions_whitelist_.end())
if (extensions_allowlist_.find(extName) == extensions_allowlist_.end())
return false;
}
return true;
@@ -882,14 +882,14 @@ bool AggressiveDCEPass::ProcessGlobalValues() {
AggressiveDCEPass::AggressiveDCEPass() = default;
Pass::Status AggressiveDCEPass::Process() {
// Initialize extensions whitelist
// Initialize extensions allowlist
InitExtensions();
return ProcessImpl();
}
void AggressiveDCEPass::InitExtensions() {
extensions_whitelist_.clear();
extensions_whitelist_.insert({
extensions_allowlist_.clear();
extensions_allowlist_.insert({
"SPV_AMD_shader_explicit_vertex_parameter",
"SPV_AMD_shader_trinary_minmax",
"SPV_AMD_gcn_shader",

View File

@@ -87,7 +87,7 @@ class AggressiveDCEPass : public MemPass {
// to the live instruction worklist.
void AddStores(uint32_t ptrId);
// Initialize extensions whitelist
// Initialize extensions allowlist
void InitExtensions();
// Return true if all extensions in this module are supported by this pass.
@@ -191,7 +191,7 @@ class AggressiveDCEPass : public MemPass {
std::vector<Instruction*> to_kill_;
// Extensions supported by this pass.
std::unordered_set<std::string> extensions_whitelist_;
std::unordered_set<std::string> extensions_allowlist_;
};
} // namespace opt

View File

@@ -41,6 +41,7 @@ bool DeadBranchElimPass::GetConstCondition(uint32_t condId, bool* condVal) {
bool condIsConst;
Instruction* cInst = get_def_use_mgr()->GetDef(condId);
switch (cInst->opcode()) {
case SpvOpConstantNull:
case SpvOpConstantFalse: {
*condVal = false;
condIsConst = true;

View File

@@ -72,6 +72,10 @@ class Function {
// Delete all basic blocks that contain no instructions.
inline void RemoveEmptyBlocks();
// Removes a parameter from the function with result id equal to |id|.
// Does nothing if the function doesn't have such a parameter.
inline void RemoveParameter(uint32_t id);
// Saves the given function end instruction.
inline void SetFunctionEnd(std::unique_ptr<Instruction> end_inst);
@@ -219,6 +223,14 @@ inline void Function::RemoveEmptyBlocks() {
blocks_.erase(first_empty, std::end(blocks_));
}
inline void Function::RemoveParameter(uint32_t id) {
params_.erase(std::remove_if(params_.begin(), params_.end(),
[id](const std::unique_ptr<Instruction>& param) {
return param->result_id() == id;
}),
params_.end());
}
inline void Function::SetFunctionEnd(std::unique_ptr<Instruction> end_inst) {
end_inst_ = std::move(end_inst);
}

View File

@@ -61,6 +61,16 @@ class InstructionList : public utils::IntrusiveList<Instruction> {
: utils::IntrusiveList<Instruction>::iterator(i) {}
iterator(Instruction* i) : utils::IntrusiveList<Instruction>::iterator(i) {}
iterator& operator++() {
utils::IntrusiveList<Instruction>::iterator::operator++();
return *this;
}
iterator& operator--() {
utils::IntrusiveList<Instruction>::iterator::operator--();
return *this;
}
// DEPRECATED: Please use MoveBefore with an InstructionList instead.
//
// Moves the nodes in |list| to the list that |this| points to. The

View File

@@ -281,7 +281,7 @@ void LocalAccessChainConvertPass::Initialize() {
// Initialize collections
supported_ref_ptrs_.clear();
// Initialize extension whitelist
// Initialize extension allowlist
InitExtensions();
}
@@ -292,11 +292,11 @@ bool LocalAccessChainConvertPass::AllExtensionsSupported() const {
if (context()->get_feature_mgr()->HasCapability(
SpvCapabilityVariablePointers))
return false;
// If any extension not in whitelist, return false
// If any extension not in allowlist, return false
for (auto& ei : get_module()->extensions()) {
const char* extName =
reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
if (extensions_whitelist_.find(extName) == extensions_whitelist_.end())
if (extensions_allowlist_.find(extName) == extensions_allowlist_.end())
return false;
}
return true;
@@ -336,8 +336,8 @@ Pass::Status LocalAccessChainConvertPass::Process() {
}
void LocalAccessChainConvertPass::InitExtensions() {
extensions_whitelist_.clear();
extensions_whitelist_.insert({
extensions_allowlist_.clear();
extensions_allowlist_.insert({
"SPV_AMD_shader_explicit_vertex_parameter",
"SPV_AMD_shader_trinary_minmax",
"SPV_AMD_gcn_shader",

View File

@@ -110,7 +110,7 @@ class LocalAccessChainConvertPass : public MemPass {
// Returns a status to indicate success or failure, and change or no change.
Status ConvertLocalAccessChains(Function* func);
// Initialize extensions whitelist
// Initialize extensions allowlist
void InitExtensions();
// Return true if all extensions in this module are allowed by this pass.
@@ -124,7 +124,7 @@ class LocalAccessChainConvertPass : public MemPass {
std::unordered_set<uint32_t> supported_ref_ptrs_;
// Extensions supported by this pass.
std::unordered_set<std::string> extensions_whitelist_;
std::unordered_set<std::string> extensions_allowlist_;
};
} // namespace opt

View File

@@ -168,16 +168,16 @@ void LocalSingleBlockLoadStoreElimPass::Initialize() {
// Clear collections
supported_ref_ptrs_.clear();
// Initialize extensions whitelist
// Initialize extensions allowlist
InitExtensions();
}
bool LocalSingleBlockLoadStoreElimPass::AllExtensionsSupported() const {
// If any extension not in whitelist, return false
// If any extension not in allowlist, return false
for (auto& ei : get_module()->extensions()) {
const char* extName =
reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
if (extensions_whitelist_.find(extName) == extensions_whitelist_.end())
if (extensions_allowlist_.find(extName) == extensions_allowlist_.end())
return false;
}
return true;
@@ -214,8 +214,8 @@ Pass::Status LocalSingleBlockLoadStoreElimPass::Process() {
}
void LocalSingleBlockLoadStoreElimPass::InitExtensions() {
extensions_whitelist_.clear();
extensions_whitelist_.insert({
extensions_allowlist_.clear();
extensions_allowlist_.insert({
"SPV_AMD_shader_explicit_vertex_parameter",
"SPV_AMD_shader_trinary_minmax",
"SPV_AMD_gcn_shader",

View File

@@ -63,7 +63,7 @@ class LocalSingleBlockLoadStoreElimPass : public MemPass {
// where possible. Assumes logical addressing.
bool LocalSingleBlockLoadStoreElim(Function* func);
// Initialize extensions whitelist
// Initialize extensions allowlist
void InitExtensions();
// Return true if all extensions in this module are supported by this pass.
@@ -94,7 +94,7 @@ class LocalSingleBlockLoadStoreElimPass : public MemPass {
std::unordered_set<uint32_t> pinned_vars_;
// Extensions supported by this pass.
std::unordered_set<std::string> extensions_whitelist_;
std::unordered_set<std::string> extensions_allowlist_;
// Variables that are only referenced by supported operations for this
// pass ie. loads and stores.

View File

@@ -46,11 +46,11 @@ bool LocalSingleStoreElimPass::LocalSingleStoreElim(Function* func) {
}
bool LocalSingleStoreElimPass::AllExtensionsSupported() const {
// If any extension not in whitelist, return false
// If any extension not in allowlist, return false
for (auto& ei : get_module()->extensions()) {
const char* extName =
reinterpret_cast<const char*>(&ei.GetInOperand(0).words[0]);
if (extensions_whitelist_.find(extName) == extensions_whitelist_.end())
if (extensions_allowlist_.find(extName) == extensions_allowlist_.end())
return false;
}
return true;
@@ -74,12 +74,12 @@ Pass::Status LocalSingleStoreElimPass::ProcessImpl() {
LocalSingleStoreElimPass::LocalSingleStoreElimPass() = default;
Pass::Status LocalSingleStoreElimPass::Process() {
InitExtensionWhiteList();
InitExtensionAllowList();
return ProcessImpl();
}
void LocalSingleStoreElimPass::InitExtensionWhiteList() {
extensions_whitelist_.insert({
void LocalSingleStoreElimPass::InitExtensionAllowList() {
extensions_allowlist_.insert({
"SPV_AMD_shader_explicit_vertex_parameter",
"SPV_AMD_shader_trinary_minmax",
"SPV_AMD_gcn_shader",

View File

@@ -57,8 +57,8 @@ class LocalSingleStoreElimPass : public Pass {
// any resulting dead code.
bool LocalSingleStoreElim(Function* func);
// Initialize extensions whitelist
void InitExtensionWhiteList();
// Initialize extensions allowlist
void InitExtensionAllowList();
// Return true if all extensions in this module are allowed by this pass.
bool AllExtensionsSupported() const;
@@ -94,7 +94,7 @@ class LocalSingleStoreElimPass : public Pass {
const std::vector<Instruction*>& uses);
// Extensions supported by this pass.
std::unordered_set<std::string> extensions_whitelist_;
std::unordered_set<std::string> extensions_allowlist_;
};
} // namespace opt

View File

@@ -485,10 +485,27 @@ void Loop::ComputeLoopStructuredOrder(
if (include_pre_header && GetPreHeaderBlock())
ordered_loop_blocks->push_back(loop_preheader_);
cfg.ForEachBlockInReversePostOrder(
loop_header_, [ordered_loop_blocks, this](BasicBlock* bb) {
if (IsInsideLoop(bb)) ordered_loop_blocks->push_back(bb);
});
bool is_shader =
context_->get_feature_mgr()->HasCapability(SpvCapabilityShader);
if (!is_shader) {
cfg.ForEachBlockInReversePostOrder(
loop_header_, [ordered_loop_blocks, this](BasicBlock* bb) {
if (IsInsideLoop(bb)) ordered_loop_blocks->push_back(bb);
});
} else {
// If this is a shader, it is possible that there are unreachable merge and
// continue blocks that must be copied to retain the structured order.
// The structured order will include these.
std::list<BasicBlock*> order;
cfg.ComputeStructuredOrder(loop_header_->GetParent(), loop_header_, &order);
for (BasicBlock* bb : order) {
if (bb == GetMergeBlock()) {
break;
}
ordered_loop_blocks->push_back(bb);
}
}
if (include_merge && GetMergeBlock())
ordered_loop_blocks->push_back(loop_merge_);
}

View File

@@ -55,11 +55,11 @@ def check_library(library):
# _Z[0-9]+spv[A-Z_] : C++ symbol starting with spv[A-Z_]
symbol_ok_pattern = re.compile(r'^(spv[A-Z]|_ZN|_Z[0-9]+spv[A-Z_])')
# In addition, the following pattern whitelists global functions that are added
# In addition, the following pattern allowlists global functions that are added
# by the protobuf compiler:
# - AddDescriptors_spvtoolsfuzz_2eproto()
# - InitDefaults_spvtoolsfuzz_2eproto()
symbol_whitelist_pattern = re.compile(r'_Z[0-9]+(InitDefaults|AddDescriptors)_spvtoolsfuzz_2eprotov')
symbol_allowlist_pattern = re.compile(r'_Z[0-9]+(InitDefaults|AddDescriptors)_spvtoolsfuzz_2eprotov')
seen = set()
result = 0
@@ -70,7 +70,7 @@ def check_library(library):
if symbol not in seen:
seen.add(symbol)
#print("look at '{}'".format(symbol))
if not (symbol_whitelist_pattern.match(symbol) or symbol_ok_pattern.match(symbol)):
if not (symbol_allowlist_pattern.match(symbol) or symbol_ok_pattern.match(symbol)):
print('{}: error: Unescaped exported symbol: {}'.format(PROG, symbol))
result = 1
return result