| // 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 |
| // |
| // 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_OPT_LOOP_FISSION_H_ |
| #define SOURCE_OPT_LOOP_FISSION_H_ |
| |
| #include <algorithm> |
| #include <cstdint> |
| #include <map> |
| #include <utility> |
| #include <vector> |
| |
| #include "source/opt/cfg.h" |
| #include "source/opt/loop_dependence.h" |
| #include "source/opt/loop_utils.h" |
| #include "source/opt/module.h" |
| #include "source/opt/pass.h" |
| #include "source/opt/tree_iterator.h" |
| |
| namespace spvtools { |
| namespace opt { |
| |
| class LoopFissionPass : public Pass { |
| public: |
| // Fuction used to determine if a given loop should be split. Takes register |
| // pressure region for that loop as a parameter and returns true if the loop |
| // should be split. |
| using FissionCriteriaFunction = |
| std::function<bool(const RegisterLiveness::RegionRegisterLiveness&)>; |
| |
| // Pass built with this constructor will split all loops regardless of |
| // register pressure. Will not split loops more than once. |
| LoopFissionPass(); |
| |
| // Split the loop if the number of registers used in the loop exceeds |
| // |register_threshold_to_split|. |split_multiple_times| flag determines |
| // whether or not the pass should split loops after already splitting them |
| // once. |
| LoopFissionPass(size_t register_threshold_to_split, |
| bool split_multiple_times = true); |
| |
| // Split loops whose register pressure meets the criteria of |functor|. |
| LoopFissionPass(FissionCriteriaFunction functor, |
| bool split_multiple_times = true) |
| : split_criteria_(functor), split_multiple_times_(split_multiple_times) {} |
| |
| const char* name() const override { return "loop-fission"; } |
| |
| Pass::Status Process() override; |
| |
| // Checks if |loop| meets the register pressure criteria to be split. |
| bool ShouldSplitLoop(const Loop& loop, IRContext* context); |
| |
| private: |
| // Functor to run in ShouldSplitLoop to determine if the register pressure |
| // criteria is met for splitting the loop. |
| FissionCriteriaFunction split_criteria_; |
| |
| // Flag designating whether or not we should also split the result of |
| // previously split loops if they meet the register presure criteria. |
| bool split_multiple_times_; |
| }; |
| |
| } // namespace opt |
| } // namespace spvtools |
| |
| #endif // SOURCE_OPT_LOOP_FISSION_H_ |