LLVM API Documentation

BasicBlockPlacement.cpp

Go to the documentation of this file.
00001 //===-- BasicBlockPlacement.cpp - Basic Block Code Layout optimization ----===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements a very simple profile guided basic block placement
00011 // algorithm.  The idea is to put frequently executed blocks together at the
00012 // start of the function, and hopefully increase the number of fall-through
00013 // conditional branches.  If there is no profile information for a particular
00014 // function, this pass basically orders blocks in depth-first order
00015 //
00016 // The algorithm implemented here is basically "Algo1" from "Profile Guided Code
00017 // Positioning" by Pettis and Hansen, except that it uses basic block counts
00018 // instead of edge counts.  This should be improved in many ways, but is very
00019 // simple for now.
00020 //
00021 // Basically we "place" the entry block, then loop over all successors in a DFO,
00022 // placing the most frequently executed successor until we run out of blocks.  I
00023 // told you this was _extremely_ simplistic. :) This is also much slower than it
00024 // could be.  When it becomes important, this pass will be rewritten to use a
00025 // better algorithm, and then we can worry about efficiency.
00026 //
00027 //===----------------------------------------------------------------------===//
00028 
00029 #define DEBUG_TYPE "block-placement"
00030 #include "llvm/Analysis/ProfileInfo.h"
00031 #include "llvm/Function.h"
00032 #include "llvm/Pass.h"
00033 #include "llvm/Support/CFG.h"
00034 #include "llvm/Support/Compiler.h"
00035 #include "llvm/ADT/Statistic.h"
00036 #include "llvm/Transforms/Scalar.h"
00037 #include <set>
00038 using namespace llvm;
00039 
00040 STATISTIC(NumMoved, "Number of basic blocks moved");
00041 
00042 namespace {
00043   struct VISIBILITY_HIDDEN BlockPlacement : public FunctionPass {
00044     static char ID; // Pass identification, replacement for typeid
00045     BlockPlacement() : FunctionPass(&ID) {}
00046 
00047     virtual bool runOnFunction(Function &F);
00048 
00049     virtual void getAnalysisUsage(AnalysisUsage &AU) const {
00050       AU.setPreservesCFG();
00051       AU.addRequired<ProfileInfo>();
00052       //AU.addPreserved<ProfileInfo>();  // Does this work?
00053     }
00054   private:
00055     /// PI - The profile information that is guiding us.
00056     ///
00057     ProfileInfo *PI;
00058 
00059     /// NumMovedBlocks - Every time we move a block, increment this counter.
00060     ///
00061     unsigned NumMovedBlocks;
00062 
00063     /// PlacedBlocks - Every time we place a block, remember it so we don't get
00064     /// into infinite loops.
00065     std::set<BasicBlock*> PlacedBlocks;
00066 
00067     /// InsertPos - This an iterator to the next place we want to insert a
00068     /// block.
00069     Function::iterator InsertPos;
00070 
00071     /// PlaceBlocks - Recursively place the specified blocks and any unplaced
00072     /// successors.
00073     void PlaceBlocks(BasicBlock *BB);
00074   };
00075 }
00076 
00077 char BlockPlacement::ID = 0;
00078 static RegisterPass<BlockPlacement>
00079 X("block-placement", "Profile Guided Basic Block Placement");
00080 
00081 FunctionPass *llvm::createBlockPlacementPass() { return new BlockPlacement(); }
00082 
00083 bool BlockPlacement::runOnFunction(Function &F) {
00084   PI = &getAnalysis<ProfileInfo>();
00085 
00086   NumMovedBlocks = 0;
00087   InsertPos = F.begin();
00088 
00089   // Recursively place all blocks.
00090   PlaceBlocks(F.begin());
00091 
00092   PlacedBlocks.clear();
00093   NumMoved += NumMovedBlocks;
00094   return NumMovedBlocks != 0;
00095 }
00096 
00097 
00098 /// PlaceBlocks - Recursively place the specified blocks and any unplaced
00099 /// successors.
00100 void BlockPlacement::PlaceBlocks(BasicBlock *BB) {
00101   assert(!PlacedBlocks.count(BB) && "Already placed this block!");
00102   PlacedBlocks.insert(BB);
00103 
00104   // Place the specified block.
00105   if (&*InsertPos != BB) {
00106     // Use splice to move the block into the right place.  This avoids having to
00107     // remove the block from the function then readd it, which causes a bunch of
00108     // symbol table traffic that is entirely pointless.
00109     Function::BasicBlockListType &Blocks = BB->getParent()->getBasicBlockList();
00110     Blocks.splice(InsertPos, Blocks, BB);
00111 
00112     ++NumMovedBlocks;
00113   } else {
00114     // This block is already in the right place, we don't have to do anything.
00115     ++InsertPos;
00116   }
00117 
00118   // Keep placing successors until we run out of ones to place.  Note that this
00119   // loop is very inefficient (N^2) for blocks with many successors, like switch
00120   // statements.  FIXME!
00121   while (1) {
00122     // Okay, now place any unplaced successors.
00123     succ_iterator SI = succ_begin(BB), E = succ_end(BB);
00124 
00125     // Scan for the first unplaced successor.
00126     for (; SI != E && PlacedBlocks.count(*SI); ++SI)
00127       /*empty*/;
00128     if (SI == E) return;  // No more successors to place.
00129 
00130     unsigned MaxExecutionCount = PI->getExecutionCount(*SI);
00131     BasicBlock *MaxSuccessor = *SI;
00132 
00133     // Scan for more frequently executed successors
00134     for (; SI != E; ++SI)
00135       if (!PlacedBlocks.count(*SI)) {
00136         unsigned Count = PI->getExecutionCount(*SI);
00137         if (Count > MaxExecutionCount ||
00138             // Prefer to not disturb the code.
00139             (Count == MaxExecutionCount && *SI == &*InsertPos)) {
00140           MaxExecutionCount = Count;
00141           MaxSuccessor = *SI;
00142         }
00143       }
00144 
00145     // Now that we picked the maximally executed successor, place it.
00146     PlaceBlocks(MaxSuccessor);
00147   }
00148 }