1 // Copyright (c) 2018 Google LLC. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef SOURCE_OPT_LOOP_FISSION_H_ 16 #define SOURCE_OPT_LOOP_FISSION_H_ 17 18 #include <algorithm> 19 #include <cstdint> 20 #include <map> 21 #include <utility> 22 #include <vector> 23 24 #include "source/opt/cfg.h" 25 #include "source/opt/loop_dependence.h" 26 #include "source/opt/loop_utils.h" 27 #include "source/opt/module.h" 28 #include "source/opt/pass.h" 29 #include "source/opt/tree_iterator.h" 30 31 namespace spvtools { 32 namespace opt { 33 34 class LoopFissionPass : public Pass { 35 public: 36 // Fuction used to determine if a given loop should be split. Takes register 37 // pressure region for that loop as a parameter and returns true if the loop 38 // should be split. 39 using FissionCriteriaFunction = 40 std::function<bool(const RegisterLiveness::RegionRegisterLiveness&)>; 41 42 // Pass built with this constructor will split all loops regardless of 43 // register pressure. Will not split loops more than once. 44 LoopFissionPass(); 45 46 // Split the loop if the number of registers used in the loop exceeds 47 // |register_threshold_to_split|. |split_multiple_times| flag determines 48 // whether or not the pass should split loops after already splitting them 49 // once. 50 LoopFissionPass(size_t register_threshold_to_split, 51 bool split_multiple_times = true); 52 53 // Split loops whose register pressure meets the criteria of |functor|. 54 LoopFissionPass(FissionCriteriaFunction functor, 55 bool split_multiple_times = true) split_criteria_(functor)56 : split_criteria_(functor), split_multiple_times_(split_multiple_times) {} 57 name()58 const char* name() const override { return "loop-fission"; } 59 60 Pass::Status Process() override; 61 62 // Checks if |loop| meets the register pressure criteria to be split. 63 bool ShouldSplitLoop(const Loop& loop, IRContext* context); 64 65 private: 66 // Functor to run in ShouldSplitLoop to determine if the register pressure 67 // criteria is met for splitting the loop. 68 FissionCriteriaFunction split_criteria_; 69 70 // Flag designating whether or not we should also split the result of 71 // previously split loops if they meet the register presure criteria. 72 bool split_multiple_times_; 73 }; 74 75 } // namespace opt 76 } // namespace spvtools 77 78 #endif // SOURCE_OPT_LOOP_FISSION_H_ 79