// 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_PEELING_H_ #define SOURCE_OPT_LOOP_PEELING_H_ #include <algorithm> #include <limits> #include <memory> #include <tuple> #include <unordered_map> #include <unordered_set> #include <utility> #include <vector> #include "source/opt/ir_context.h" #include "source/opt/loop_descriptor.h" #include "source/opt/loop_utils.h" #include "source/opt/pass.h" #include "source/opt/scalar_analysis.h" namespace spvtools { namespace opt { // Utility class to perform the peeling of a given loop. // The loop peeling transformation make a certain amount of a loop iterations to // be executed either before (peel before) or after (peel after) the transformed // loop. // // For peeling cases the transformation does the following steps: // - It clones the loop and inserts the cloned loop before the original loop; // - It connects all iterating values of the cloned loop with the // corresponding original loop values so that the second loop starts with // the appropriate values. // - It inserts a new induction variable "i" is inserted into the cloned that // starts with the value 0 and increment by step of one. // // The last step is specific to each case: // - Peel before: the transformation is to peel the "N" first iterations. // The exit condition of the cloned loop is changed so that the loop // exits when "i < N" becomes false. The original loop is then protected to // only execute if there is any iteration left to do. // - Peel after: the transformation is to peel the "N" last iterations, // then the exit condition of the cloned loop is changed so that the loop // exits when "i + N < max_iteration" becomes false, where "max_iteration" // is the upper bound of the loop. The cloned loop is then protected to // only execute if there is any iteration left to do no covered by the // second. // // To be peelable: // - The loop must be in LCSSA form; // - The loop must not contain any breaks; // - The loop must not have any ambiguous iterators updates (see // "CanPeelLoop"). // The method "CanPeelLoop" checks that those constrained are met. class LoopPeeling { … }; // Implements a loop peeling optimization. // For each loop, the pass will try to peel it if there is conditions that // are true for the "N" first or last iterations of the loop. // To avoid code size explosion, too large loops will not be peeled. class LoopPeelingPass : public Pass { … }; } // namespace opt } // namespace spvtools #endif // SOURCE_OPT_LOOP_PEELING_H_