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