blob: 14de1f1f4754571e5c121d4469b29b04becf545f [file] [log] [blame]
Chris Lattner5add0512004-02-11 04:53:20 +00001//===-- BasicBlockPlacement.cpp - Basic Block Code Layout optimization ----===//
Misha Brukmanb1c93172005-04-21 23:48:37 +00002//
Chris Lattner5add0512004-02-11 04:53:20 +00003// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
Misha Brukmanb1c93172005-04-21 23:48:37 +00007//
Chris Lattner5add0512004-02-11 04:53:20 +00008//===----------------------------------------------------------------------===//
9//
10// This file implements a very simple profile guided basic block placement
11// algorithm. The idea is to put frequently executed blocks together at the
12// start of the function, and hopefully increase the number of fall-through
13// conditional branches. If there is no profile information for a particular
14// function, this pass basically orders blocks in depth-first order
15//
16// The algorithm implemented here is basically "Algo1" from "Profile Guided Code
17// Positioning" by Pettis and Hansen, except that it uses basic block counts
18// instead of edge counts. This should be improved in many ways, but is very
19// simple for now.
20//
21// Basically we "place" the entry block, then loop over all successors in a DFO,
22// placing the most frequently executed successor until we run out of blocks. I
23// told you this was _extremely_ simplistic. :) This is also much slower than it
24// could be. When it becomes important, this pass will be rewritten to use a
25// better algorithm, and then we can worry about efficiency.
26//
27//===----------------------------------------------------------------------===//
28
Chris Lattner79a42ac2006-12-19 21:40:18 +000029#define DEBUG_TYPE "block-placement"
Chris Lattner5add0512004-02-11 04:53:20 +000030#include "llvm/Analysis/ProfileInfo.h"
31#include "llvm/Function.h"
32#include "llvm/Pass.h"
33#include "llvm/Support/CFG.h"
Reid Spencer557ab152007-02-05 23:32:05 +000034#include "llvm/Support/Compiler.h"
Reid Spencer7c16caa2004-09-01 22:55:40 +000035#include "llvm/ADT/Statistic.h"
Jeff Cohen677babc2005-01-08 17:21:40 +000036#include "llvm/Transforms/Scalar.h"
Chris Lattner5add0512004-02-11 04:53:20 +000037#include <set>
38using namespace llvm;
39
Chris Lattner79a42ac2006-12-19 21:40:18 +000040STATISTIC(NumMoved, "Number of basic blocks moved");
Misha Brukmanb1c93172005-04-21 23:48:37 +000041
Chris Lattner79a42ac2006-12-19 21:40:18 +000042namespace {
Reid Spencer557ab152007-02-05 23:32:05 +000043 struct VISIBILITY_HIDDEN BlockPlacement : public FunctionPass {
Chris Lattner5add0512004-02-11 04:53:20 +000044 virtual bool runOnFunction(Function &F);
45
46 virtual void getAnalysisUsage(AnalysisUsage &AU) const {
47 AU.setPreservesCFG();
48 AU.addRequired<ProfileInfo>();
49 //AU.addPreserved<ProfileInfo>(); // Does this work?
50 }
51 private:
52 /// PI - The profile information that is guiding us.
53 ///
54 ProfileInfo *PI;
55
56 /// NumMovedBlocks - Every time we move a block, increment this counter.
57 ///
58 unsigned NumMovedBlocks;
59
60 /// PlacedBlocks - Every time we place a block, remember it so we don't get
61 /// into infinite loops.
62 std::set<BasicBlock*> PlacedBlocks;
63
64 /// InsertPos - This an iterator to the next place we want to insert a
65 /// block.
66 Function::iterator InsertPos;
67
68 /// PlaceBlocks - Recursively place the specified blocks and any unplaced
69 /// successors.
70 void PlaceBlocks(BasicBlock *BB);
71 };
72
Chris Lattnerc2d3d312006-08-27 22:42:52 +000073 RegisterPass<BlockPlacement> X("block-placement",
74 "Profile Guided Basic Block Placement");
Chris Lattner5add0512004-02-11 04:53:20 +000075}
76
Jeff Cohen677babc2005-01-08 17:21:40 +000077FunctionPass *llvm::createBlockPlacementPass() { return new BlockPlacement(); }
78
Chris Lattner5add0512004-02-11 04:53:20 +000079bool BlockPlacement::runOnFunction(Function &F) {
80 PI = &getAnalysis<ProfileInfo>();
81
82 NumMovedBlocks = 0;
Misha Brukmanb1c93172005-04-21 23:48:37 +000083 InsertPos = F.begin();
Chris Lattner5add0512004-02-11 04:53:20 +000084
85 // Recursively place all blocks.
86 PlaceBlocks(F.begin());
Misha Brukmanb1c93172005-04-21 23:48:37 +000087
Chris Lattner5add0512004-02-11 04:53:20 +000088 PlacedBlocks.clear();
89 NumMoved += NumMovedBlocks;
90 return NumMovedBlocks != 0;
91}
92
93
94/// PlaceBlocks - Recursively place the specified blocks and any unplaced
95/// successors.
96void BlockPlacement::PlaceBlocks(BasicBlock *BB) {
97 assert(!PlacedBlocks.count(BB) && "Already placed this block!");
98 PlacedBlocks.insert(BB);
99
100 // Place the specified block.
101 if (&*InsertPos != BB) {
102 // Use splice to move the block into the right place. This avoids having to
103 // remove the block from the function then readd it, which causes a bunch of
104 // symbol table traffic that is entirely pointless.
105 Function::BasicBlockListType &Blocks = BB->getParent()->getBasicBlockList();
106 Blocks.splice(InsertPos, Blocks, BB);
107
108 ++NumMovedBlocks;
109 } else {
110 // This block is already in the right place, we don't have to do anything.
111 ++InsertPos;
112 }
113
114 // Keep placing successors until we run out of ones to place. Note that this
115 // loop is very inefficient (N^2) for blocks with many successors, like switch
116 // statements. FIXME!
117 while (1) {
118 // Okay, now place any unplaced successors.
119 succ_iterator SI = succ_begin(BB), E = succ_end(BB);
Misha Brukmanb1c93172005-04-21 23:48:37 +0000120
Chris Lattner5add0512004-02-11 04:53:20 +0000121 // Scan for the first unplaced successor.
122 for (; SI != E && PlacedBlocks.count(*SI); ++SI)
123 /*empty*/;
124 if (SI == E) return; // No more successors to place.
Misha Brukmanb1c93172005-04-21 23:48:37 +0000125
Chris Lattner5add0512004-02-11 04:53:20 +0000126 unsigned MaxExecutionCount = PI->getExecutionCount(*SI);
127 BasicBlock *MaxSuccessor = *SI;
128
129 // Scan for more frequently executed successors
130 for (; SI != E; ++SI)
131 if (!PlacedBlocks.count(*SI)) {
132 unsigned Count = PI->getExecutionCount(*SI);
133 if (Count > MaxExecutionCount ||
134 // Prefer to not disturb the code.
135 (Count == MaxExecutionCount && *SI == &*InsertPos)) {
136 MaxExecutionCount = Count;
137 MaxSuccessor = *SI;
138 }
139 }
140
141 // Now that we picked the maximally executed successor, place it.
142 PlaceBlocks(MaxSuccessor);
143 }
144}