|  | // 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_ |