mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-26 21:30:07 +00:00
spirv-fuzz: Fuzzer pass to randomly apply loop preheaders (#3668)
This PR introduces FuzzerPassAddLoopPreheaders, which: - Finds existing loop headers - If they have no simple preheader (where simple means that the preheader itself is not a loop header), randomly decides whether to add one. Fixes #3621.
This commit is contained in:
parent
72ea7bec4a
commit
eade36db22
@ -50,6 +50,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
fuzzer_pass_add_synonyms.h
|
||||
fuzzer_pass_add_loads.h
|
||||
fuzzer_pass_add_local_variables.h
|
||||
fuzzer_pass_add_loop_preheaders.h
|
||||
fuzzer_pass_add_no_contraction_decorations.h
|
||||
fuzzer_pass_add_parameters.h
|
||||
fuzzer_pass_add_relaxed_decorations.h
|
||||
@ -189,6 +190,7 @@ if(SPIRV_BUILD_FUZZER)
|
||||
fuzzer_pass_add_synonyms.cpp
|
||||
fuzzer_pass_add_loads.cpp
|
||||
fuzzer_pass_add_local_variables.cpp
|
||||
fuzzer_pass_add_loop_preheaders.cpp
|
||||
fuzzer_pass_add_no_contraction_decorations.cpp
|
||||
fuzzer_pass_add_parameters.cpp
|
||||
fuzzer_pass_add_relaxed_decorations.cpp
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "source/fuzz/fuzzer_pass_add_image_sample_unused_components.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_loads.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_local_variables.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_loop_preheaders.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_no_contraction_decorations.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_parameters.h"
|
||||
#include "source/fuzz/fuzzer_pass_add_stores.h"
|
||||
@ -242,6 +243,9 @@ Fuzzer::FuzzerResultStatus Fuzzer::Run(
|
||||
MaybeAddPass<FuzzerPassAddLocalVariables>(
|
||||
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
MaybeAddPass<FuzzerPassAddLoopPreheaders>(
|
||||
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
MaybeAddPass<FuzzerPassAddParameters>(
|
||||
&passes, ir_context.get(), &transformation_context, &fuzzer_context,
|
||||
transformation_sequence_out);
|
||||
|
@ -38,6 +38,7 @@ const std::pair<uint32_t, uint32_t> kChanceOfAddingImageSampleUnusedComponents =
|
||||
{20, 90};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingLoad = {5, 50};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingLocalVariable = {20, 90};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingLoopPreheader = {20, 90};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingMatrixType = {20, 70};
|
||||
const std::pair<uint32_t, uint32_t> kChanceOfAddingNoContractionDecoration = {
|
||||
5, 70};
|
||||
@ -165,6 +166,8 @@ FuzzerContext::FuzzerContext(RandomGenerator* random_generator,
|
||||
chance_of_adding_global_variable_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfAddingGlobalVariable);
|
||||
chance_of_adding_load_ = ChooseBetweenMinAndMax(kChanceOfAddingLoad);
|
||||
chance_of_adding_loop_preheader_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfAddingLoopPreheader);
|
||||
chance_of_adding_image_sample_unused_components_ =
|
||||
ChooseBetweenMinAndMax(kChanceOfAddingImageSampleUnusedComponents);
|
||||
chance_of_adding_local_variable_ =
|
||||
|
@ -136,6 +136,9 @@ class FuzzerContext {
|
||||
uint32_t GetChanceOfAddingLocalVariable() {
|
||||
return chance_of_adding_local_variable_;
|
||||
}
|
||||
uint32_t GetChanceOfAddingLoopPreheader() {
|
||||
return chance_of_adding_loop_preheader_;
|
||||
}
|
||||
uint32_t GetChanceOfAddingMatrixType() {
|
||||
return chance_of_adding_matrix_type_;
|
||||
}
|
||||
@ -348,6 +351,7 @@ class FuzzerContext {
|
||||
uint32_t chance_of_adding_image_sample_unused_components_;
|
||||
uint32_t chance_of_adding_load_;
|
||||
uint32_t chance_of_adding_local_variable_;
|
||||
uint32_t chance_of_adding_loop_preheader_;
|
||||
uint32_t chance_of_adding_matrix_type_;
|
||||
uint32_t chance_of_adding_no_contraction_decoration_;
|
||||
uint32_t chance_of_adding_parameters;
|
||||
|
66
source/fuzz/fuzzer_pass_add_loop_preheaders.cpp
Normal file
66
source/fuzz/fuzzer_pass_add_loop_preheaders.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "source/fuzz/fuzzer_pass_add_loop_preheaders.h"
|
||||
|
||||
#include "source/fuzz/fuzzer_util.h"
|
||||
#include "source/fuzz/transformation_add_loop_preheader.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
FuzzerPassAddLoopPreheaders::FuzzerPassAddLoopPreheaders(
|
||||
opt::IRContext* ir_context, TransformationContext* transformation_context,
|
||||
FuzzerContext* fuzzer_context,
|
||||
protobufs::TransformationSequence* transformations)
|
||||
: FuzzerPass(ir_context, transformation_context, fuzzer_context,
|
||||
transformations) {}
|
||||
|
||||
FuzzerPassAddLoopPreheaders::~FuzzerPassAddLoopPreheaders() = default;
|
||||
|
||||
void FuzzerPassAddLoopPreheaders::Apply() {
|
||||
for (auto& function : *GetIRContext()->module()) {
|
||||
// Keep track of all the loop headers we want to add a preheader to.
|
||||
std::vector<uint32_t> loop_header_ids_to_consider;
|
||||
for (auto& block : function) {
|
||||
// We only care about loop headers.
|
||||
if (!block.IsLoopHeader()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Randomly decide whether to consider this header.
|
||||
if (!GetFuzzerContext()->ChoosePercentage(
|
||||
GetFuzzerContext()->GetChanceOfAddingLoopPreheader())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We exclude loop headers with just one predecessor (the back-edge block)
|
||||
// because they are unreachable.
|
||||
if (GetIRContext()->cfg()->preds(block.id()).size() < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
loop_header_ids_to_consider.push_back(block.id());
|
||||
}
|
||||
|
||||
for (uint32_t header_id : loop_header_ids_to_consider) {
|
||||
// If not already present, add a preheader which is not also a loop
|
||||
// header.
|
||||
GetOrCreateSimpleLoopPreheader(header_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
43
source/fuzz/fuzzer_pass_add_loop_preheaders.h
Normal file
43
source/fuzz/fuzzer_pass_add_loop_preheaders.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2020 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef SOURCE_FUZZ_FUZZER_PASS_ADD_LOOP_PREHEADERS_H
|
||||
#define SOURCE_FUZZ_FUZZER_PASS_ADD_LOOP_PREHEADERS_H
|
||||
|
||||
#include "source/fuzz/fuzzer_pass.h"
|
||||
|
||||
namespace spvtools {
|
||||
namespace fuzz {
|
||||
|
||||
// A fuzzer pass that randomly adds simple loop preheaders to loops that do not
|
||||
// have one. A simple loop preheader is a block that:
|
||||
// - is the only out-of-loop predecessor of the header
|
||||
// - branches unconditionally to the header
|
||||
// - is not a loop header itself
|
||||
class FuzzerPassAddLoopPreheaders : public FuzzerPass {
|
||||
public:
|
||||
FuzzerPassAddLoopPreheaders(
|
||||
opt::IRContext* ir_context, TransformationContext* transformation_context,
|
||||
FuzzerContext* fuzzer_context,
|
||||
protobufs::TransformationSequence* transformations);
|
||||
|
||||
~FuzzerPassAddLoopPreheaders();
|
||||
|
||||
void Apply() override;
|
||||
};
|
||||
|
||||
} // namespace fuzz
|
||||
} // namespace spvtools
|
||||
|
||||
#endif // SOURCE_FUZZ_FUZZER_PASS_ADD_LOOP_PREHEADERS_H
|
Loading…
Reference in New Issue
Block a user