blob: f3ba1806682a7a52c74d6259d4628880c96ca4c7 [file] [log] [blame]
// Copyright (c) 2018 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
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// See the License for the specific language governing permissions and
// limitations under the License.
#include <functional>
#include <string>
#include "source/reduce/reduction_pass.h"
#include "spirv-tools/libspirv.hpp"
namespace spvtools {
namespace reduce {
// This class manages the process of applying a reduction -- parameterized by a
// number of reduction passes and an interestingness test, to a SPIR-V binary.
class Reducer {
// Possible statuses that can result from running a reduction.
enum ReductionResultStatus {
// Returned when the fail-on-validation-error option is set and a
// reduction step yields a state that fails validation.
// The type for a function that will take a binary and return true if and
// only if the binary is deemed interesting. (The function also takes an
// integer argument that will be incremented each time the function is
// called; this is for debugging purposes).
// The notion of "interesting" depends on what properties of the binary or
// tools that process the binary we are trying to maintain during reduction.
using InterestingnessFunction =
std::function<bool(const std::vector<uint32_t>&, uint32_t)>;
// Constructs an instance with the given target |target_env|, which is used to
// decode the binary to be reduced later.
// The constructed instance will have an empty message consumer, which just
// ignores all messages from the library. Use SetMessageConsumer() to supply
// one if messages are of concern.
// The constructed instance also needs to have an interestingness function
// set and some reduction passes added to it in order to be useful.
explicit Reducer(spv_target_env target_env);
// Disables copy/move constructor/assignment operations.
Reducer(const Reducer&) = delete;
Reducer(Reducer&&) = delete;
Reducer& operator=(const Reducer&) = delete;
Reducer& operator=(Reducer&&) = delete;
// Destructs this instance.
// Sets the message consumer to the given |consumer|. The |consumer| will be
// invoked once for each message communicated from the library.
void SetMessageConsumer(MessageConsumer consumer);
// Sets the function that will be used to decide whether a reduced binary
// turned out to be interesting.
void SetInterestingnessFunction(
InterestingnessFunction interestingness_function);
// Adds all default reduction passes.
void AddDefaultReductionPasses();
// Adds a reduction pass based on the given finder to the sequence of passes
// that will be iterated over.
void AddReductionPass(std::unique_ptr<ReductionOpportunityFinder> finder);
// Adds a cleanup reduction pass based on the given finder to the sequence of
// passes that will run after other passes.
void AddCleanupReductionPass(
std::unique_ptr<ReductionOpportunityFinder> finder);
// Reduces the given SPIR-V module |binary_out|.
// The reduced binary ends up in |binary_out|.
// A status is returned.
ReductionResultStatus Run(const std::vector<uint32_t>& binary_in,
std::vector<uint32_t>* binary_out,
spv_const_reducer_options options,
spv_validator_options validator_options);
static bool ReachedStepLimit(uint32_t current_step,
spv_const_reducer_options options);
ReductionResultStatus RunPasses(
std::vector<std::unique_ptr<ReductionPass>>* passes,
spv_const_reducer_options options,
spv_validator_options validator_options, const SpirvTools& tools,
std::vector<uint32_t>* current_binary, uint32_t* reductions_applied);
const spv_target_env target_env_;
MessageConsumer consumer_;
InterestingnessFunction interestingness_function_;
std::vector<std::unique_ptr<ReductionPass>> passes_;
std::vector<std::unique_ptr<ReductionPass>> cleanup_passes_;
} // namespace reduce
} // namespace spvtools