1fd4e5da5Sopenharmony_ci// Copyright (c) 2018 Google LLC
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#ifndef SOURCE_REDUCE_REDUCER_H_
16fd4e5da5Sopenharmony_ci#define SOURCE_REDUCE_REDUCER_H_
17fd4e5da5Sopenharmony_ci
18fd4e5da5Sopenharmony_ci#include <functional>
19fd4e5da5Sopenharmony_ci#include <string>
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_ci#include "source/reduce/reduction_pass.h"
22fd4e5da5Sopenharmony_ci#include "spirv-tools/libspirv.hpp"
23fd4e5da5Sopenharmony_ci
24fd4e5da5Sopenharmony_cinamespace spvtools {
25fd4e5da5Sopenharmony_cinamespace reduce {
26fd4e5da5Sopenharmony_ci
27fd4e5da5Sopenharmony_ci// This class manages the process of applying a reduction -- parameterized by a
28fd4e5da5Sopenharmony_ci// number of reduction passes and an interestingness test, to a SPIR-V binary.
29fd4e5da5Sopenharmony_ciclass Reducer {
30fd4e5da5Sopenharmony_ci public:
31fd4e5da5Sopenharmony_ci  // Possible statuses that can result from running a reduction.
32fd4e5da5Sopenharmony_ci  enum ReductionResultStatus {
33fd4e5da5Sopenharmony_ci    kInitialStateNotInteresting,
34fd4e5da5Sopenharmony_ci    kReachedStepLimit,
35fd4e5da5Sopenharmony_ci    kComplete,
36fd4e5da5Sopenharmony_ci    kInitialStateInvalid,
37fd4e5da5Sopenharmony_ci
38fd4e5da5Sopenharmony_ci    // Returned when the fail-on-validation-error option is set and a
39fd4e5da5Sopenharmony_ci    // reduction step yields a state that fails validation.
40fd4e5da5Sopenharmony_ci    kStateInvalid,
41fd4e5da5Sopenharmony_ci  };
42fd4e5da5Sopenharmony_ci
43fd4e5da5Sopenharmony_ci  // The type for a function that will take a binary and return true if and
44fd4e5da5Sopenharmony_ci  // only if the binary is deemed interesting. (The function also takes an
45fd4e5da5Sopenharmony_ci  // integer argument that will be incremented each time the function is
46fd4e5da5Sopenharmony_ci  // called; this is for debugging purposes).
47fd4e5da5Sopenharmony_ci  //
48fd4e5da5Sopenharmony_ci  // The notion of "interesting" depends on what properties of the binary or
49fd4e5da5Sopenharmony_ci  // tools that process the binary we are trying to maintain during reduction.
50fd4e5da5Sopenharmony_ci  using InterestingnessFunction =
51fd4e5da5Sopenharmony_ci      std::function<bool(const std::vector<uint32_t>&, uint32_t)>;
52fd4e5da5Sopenharmony_ci
53fd4e5da5Sopenharmony_ci  // Constructs an instance with the given target |target_env|, which is used to
54fd4e5da5Sopenharmony_ci  // decode the binary to be reduced later.
55fd4e5da5Sopenharmony_ci  //
56fd4e5da5Sopenharmony_ci  // The constructed instance will have an empty message consumer, which just
57fd4e5da5Sopenharmony_ci  // ignores all messages from the library. Use SetMessageConsumer() to supply
58fd4e5da5Sopenharmony_ci  // one if messages are of concern.
59fd4e5da5Sopenharmony_ci  //
60fd4e5da5Sopenharmony_ci  // The constructed instance also needs to have an interestingness function
61fd4e5da5Sopenharmony_ci  // set and some reduction passes added to it in order to be useful.
62fd4e5da5Sopenharmony_ci  explicit Reducer(spv_target_env target_env);
63fd4e5da5Sopenharmony_ci
64fd4e5da5Sopenharmony_ci  // Disables copy/move constructor/assignment operations.
65fd4e5da5Sopenharmony_ci  Reducer(const Reducer&) = delete;
66fd4e5da5Sopenharmony_ci  Reducer(Reducer&&) = delete;
67fd4e5da5Sopenharmony_ci  Reducer& operator=(const Reducer&) = delete;
68fd4e5da5Sopenharmony_ci  Reducer& operator=(Reducer&&) = delete;
69fd4e5da5Sopenharmony_ci
70fd4e5da5Sopenharmony_ci  // Destructs this instance.
71fd4e5da5Sopenharmony_ci  ~Reducer();
72fd4e5da5Sopenharmony_ci
73fd4e5da5Sopenharmony_ci  // Sets the message consumer to the given |consumer|. The |consumer| will be
74fd4e5da5Sopenharmony_ci  // invoked once for each message communicated from the library.
75fd4e5da5Sopenharmony_ci  void SetMessageConsumer(MessageConsumer consumer);
76fd4e5da5Sopenharmony_ci
77fd4e5da5Sopenharmony_ci  // Sets the function that will be used to decide whether a reduced binary
78fd4e5da5Sopenharmony_ci  // turned out to be interesting.
79fd4e5da5Sopenharmony_ci  void SetInterestingnessFunction(
80fd4e5da5Sopenharmony_ci      InterestingnessFunction interestingness_function);
81fd4e5da5Sopenharmony_ci
82fd4e5da5Sopenharmony_ci  // Adds all default reduction passes.
83fd4e5da5Sopenharmony_ci  void AddDefaultReductionPasses();
84fd4e5da5Sopenharmony_ci
85fd4e5da5Sopenharmony_ci  // Adds a reduction pass based on the given finder to the sequence of passes
86fd4e5da5Sopenharmony_ci  // that will be iterated over.
87fd4e5da5Sopenharmony_ci  void AddReductionPass(std::unique_ptr<ReductionOpportunityFinder> finder);
88fd4e5da5Sopenharmony_ci
89fd4e5da5Sopenharmony_ci  // Adds a cleanup reduction pass based on the given finder to the sequence of
90fd4e5da5Sopenharmony_ci  // passes that will run after other passes.
91fd4e5da5Sopenharmony_ci  void AddCleanupReductionPass(
92fd4e5da5Sopenharmony_ci      std::unique_ptr<ReductionOpportunityFinder> finder);
93fd4e5da5Sopenharmony_ci
94fd4e5da5Sopenharmony_ci  // Reduces the given SPIR-V module |binary_out|.
95fd4e5da5Sopenharmony_ci  // The reduced binary ends up in |binary_out|.
96fd4e5da5Sopenharmony_ci  // A status is returned.
97fd4e5da5Sopenharmony_ci  ReductionResultStatus Run(const std::vector<uint32_t>& binary_in,
98fd4e5da5Sopenharmony_ci                            std::vector<uint32_t>* binary_out,
99fd4e5da5Sopenharmony_ci                            spv_const_reducer_options options,
100fd4e5da5Sopenharmony_ci                            spv_validator_options validator_options);
101fd4e5da5Sopenharmony_ci
102fd4e5da5Sopenharmony_ci private:
103fd4e5da5Sopenharmony_ci  static bool ReachedStepLimit(uint32_t current_step,
104fd4e5da5Sopenharmony_ci                               spv_const_reducer_options options);
105fd4e5da5Sopenharmony_ci
106fd4e5da5Sopenharmony_ci  ReductionResultStatus RunPasses(
107fd4e5da5Sopenharmony_ci      std::vector<std::unique_ptr<ReductionPass>>* passes,
108fd4e5da5Sopenharmony_ci      spv_const_reducer_options options,
109fd4e5da5Sopenharmony_ci      spv_validator_options validator_options, const SpirvTools& tools,
110fd4e5da5Sopenharmony_ci      std::vector<uint32_t>* current_binary, uint32_t* reductions_applied);
111fd4e5da5Sopenharmony_ci
112fd4e5da5Sopenharmony_ci  const spv_target_env target_env_;
113fd4e5da5Sopenharmony_ci  MessageConsumer consumer_;
114fd4e5da5Sopenharmony_ci  InterestingnessFunction interestingness_function_;
115fd4e5da5Sopenharmony_ci  std::vector<std::unique_ptr<ReductionPass>> passes_;
116fd4e5da5Sopenharmony_ci  std::vector<std::unique_ptr<ReductionPass>> cleanup_passes_;
117fd4e5da5Sopenharmony_ci};
118fd4e5da5Sopenharmony_ci
119fd4e5da5Sopenharmony_ci}  // namespace reduce
120fd4e5da5Sopenharmony_ci}  // namespace spvtools
121fd4e5da5Sopenharmony_ci
122fd4e5da5Sopenharmony_ci#endif  // SOURCE_REDUCE_REDUCER_H_
123