//===- bolt/Passes/MCF.cpp ------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements functions for solving minimum-cost flow problem. // //===----------------------------------------------------------------------===// #include "bolt/Passes/MCF.h" #include "bolt/Core/BinaryFunction.h" #include "bolt/Core/ParallelUtilities.h" #include "bolt/Passes/DataflowInfoManager.h" #include "bolt/Utils/CommandLineOpts.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/CommandLine.h" #include <algorithm> #include <vector> #undef DEBUG_TYPE #define DEBUG_TYPE … usingnamespacellvm; usingnamespacebolt; namespace opts { extern cl::OptionCategory BoltOptCategory; static cl::opt<bool> IterativeGuess( "iterative-guess", cl::desc("in non-LBR mode, guess edge counts using iterative technique"), cl::Hidden, cl::cat(BoltOptCategory)); } // namespace opts namespace llvm { namespace bolt { namespace { // Edge Weight Inference Heuristic // // We start by maintaining the invariant used in LBR mode where the sum of // pred edges count is equal to the block execution count. This loop will set // pred edges count by balancing its own execution count in different pred // edges. The weight of each edge is guessed by looking at how hot each pred // block is (in terms of samples). // There are two caveats in this approach. One is for critical edges and the // other is for self-referencing blocks (loops of 1 BB). For critical edges, // we can't infer the hotness of them based solely on pred BBs execution // count. For each critical edge we look at the pred BB, then look at its // succs to adjust its weight. // // [ 60 ] [ 25 ] // | \ | // [ 10 ] [ 75 ] // // The illustration above shows a critical edge \. We wish to adjust bb count // 60 to 50 to properly determine the weight of the critical edge to be // 50 / 75. // For self-referencing edges, we attribute its weight by subtracting the // current BB execution count by the sum of predecessors count if this result // is non-negative. EdgeWeightMap; template <class NodeT> void updateEdgeWeight(EdgeWeightMap &EdgeWeights, const BinaryBasicBlock *A, const BinaryBasicBlock *B, double Weight); template <> void updateEdgeWeight<BinaryBasicBlock *>(EdgeWeightMap &EdgeWeights, const BinaryBasicBlock *A, const BinaryBasicBlock *B, double Weight) { … } template <> void updateEdgeWeight<Inverse<BinaryBasicBlock *>>(EdgeWeightMap &EdgeWeights, const BinaryBasicBlock *A, const BinaryBasicBlock *B, double Weight) { … } template <class NodeT> void computeEdgeWeights(BinaryBasicBlock *BB, EdgeWeightMap &EdgeWeights) { … } template <class NodeT> void computeEdgeWeights(BinaryFunction &BF, EdgeWeightMap &EdgeWeights) { … } /// Make BB count match the sum of all incoming edges. If AllEdges is true, /// make it match max(SumPredEdges, SumSuccEdges). void recalculateBBCounts(BinaryFunction &BF, bool AllEdges) { … } // This is our main edge count guessing heuristic. Look at predecessors and // assign a proportionally higher count to pred edges coming from blocks with // a higher execution count in comparison with the other predecessor blocks, // making SumPredEdges match the current BB count. // If "UseSucc" is true, apply the same logic to successor edges as well. Since // some successor edges may already have assigned a count, only update it if the // new count is higher. void guessEdgeByRelHotness(BinaryFunction &BF, bool UseSucc, EdgeWeightMap &PredEdgeWeights, EdgeWeightMap &SuccEdgeWeights) { … } ArcSet; /// Predecessor edges version of guessEdgeByIterativeApproach. GuessedArcs has /// all edges we already established their count. Try to guess the count of /// the remaining edge, if there is only one to guess, and return true if we /// were able to guess. bool guessPredEdgeCounts(BinaryBasicBlock *BB, ArcSet &GuessedArcs) { … } /// Successor edges version of guessEdgeByIterativeApproach. GuessedArcs has /// all edges we already established their count. Try to guess the count of /// the remaining edge, if there is only one to guess, and return true if we /// were able to guess. bool guessSuccEdgeCounts(BinaryBasicBlock *BB, ArcSet &GuessedArcs) { … } /// Guess edge count whenever we have only one edge (pred or succ) left /// to guess. Then make its count equal to BB count minus all other edge /// counts we already know their count. Repeat this until there is no /// change. void guessEdgeByIterativeApproach(BinaryFunction &BF) { … } /// Associate each basic block with the BinaryLoop object corresponding to the /// innermost loop containing this block. DenseMap<const BinaryBasicBlock *, const BinaryLoop *> createLoopNestLevelMap(BinaryFunction &BF) { … } } // end anonymous namespace void equalizeBBCounts(DataflowInfoManager &Info, BinaryFunction &BF) { … } void EstimateEdgeCounts::runOnFunction(BinaryFunction &BF) { … } Error EstimateEdgeCounts::runOnFunctions(BinaryContext &BC) { … } } // namespace bolt } // namespace llvm