summaryrefslogtreecommitdiffstats
path: root/lib/Analysis/ProfileInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/ProfileInfo.cpp')
-rw-r--r--lib/Analysis/ProfileInfo.cpp166
1 files changed, 131 insertions, 35 deletions
diff --git a/lib/Analysis/ProfileInfo.cpp b/lib/Analysis/ProfileInfo.cpp
index a0965b6..9efdd23 100644
--- a/lib/Analysis/ProfileInfo.cpp
+++ b/lib/Analysis/ProfileInfo.cpp
@@ -17,6 +17,9 @@
#include "llvm/Pass.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Format.h"
#include <set>
using namespace llvm;
@@ -26,56 +29,149 @@ char ProfileInfo::ID = 0;
ProfileInfo::~ProfileInfo() {}
-unsigned ProfileInfo::getExecutionCount(BasicBlock *BB) const {
- pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
+const double ProfileInfo::MissingValue = -1;
+
+double ProfileInfo::getExecutionCount(const BasicBlock *BB) {
+ std::map<const Function*, BlockCounts>::iterator J =
+ BlockInformation.find(BB->getParent());
+ if (J != BlockInformation.end()) {
+ BlockCounts::iterator I = J->second.find(BB);
+ if (I != J->second.end())
+ return I->second;
+ }
+
+ pred_const_iterator PI = pred_begin(BB), PE = pred_end(BB);
// Are there zero predecessors of this block?
if (PI == PE) {
// If this is the entry block, look for the Null -> Entry edge.
if (BB == &BB->getParent()->getEntryBlock())
- return getEdgeWeight(0, BB);
+ return getEdgeWeight(getEdge(0, BB));
else
return 0; // Otherwise, this is a dead block.
}
// Otherwise, if there are predecessors, the execution count of this block is
- // the sum of the edge frequencies from the incoming edges. Note that if
- // there are multiple edges from a predecessor to this block that we don't
- // want to count its weight multiple times. For this reason, we keep track of
- // the predecessors we've seen and only count them if we haven't run into them
- // yet.
- //
- // We don't want to create an std::set unless we are dealing with a block that
- // has a LARGE number of in-edges. Handle the common case of having only a
- // few in-edges with special code.
- //
- BasicBlock *FirstPred = *PI;
- unsigned Count = getEdgeWeight(FirstPred, BB);
- ++PI;
- if (PI == PE) return Count; // Quick exit for single predecessor blocks
-
- BasicBlock *SecondPred = *PI;
- if (SecondPred != FirstPred) Count += getEdgeWeight(SecondPred, BB);
- ++PI;
- if (PI == PE) return Count; // Quick exit for two predecessor blocks
-
- BasicBlock *ThirdPred = *PI;
- if (ThirdPred != FirstPred && ThirdPred != SecondPred)
- Count += getEdgeWeight(ThirdPred, BB);
- ++PI;
- if (PI == PE) return Count; // Quick exit for three predecessor blocks
-
- std::set<BasicBlock*> ProcessedPreds;
- ProcessedPreds.insert(FirstPred);
- ProcessedPreds.insert(SecondPred);
- ProcessedPreds.insert(ThirdPred);
+ // the sum of the edge frequencies from the incoming edges.
+ std::set<const BasicBlock*> ProcessedPreds;
+ double Count = 0;
for (; PI != PE; ++PI)
- if (ProcessedPreds.insert(*PI).second)
- Count += getEdgeWeight(*PI, BB);
+ if (ProcessedPreds.insert(*PI).second) {
+ double w = getEdgeWeight(getEdge(*PI, BB));
+ if (w == MissingValue) {
+ Count = MissingValue;
+ break;
+ }
+ Count += w;
+ }
+
+ if (Count != MissingValue) BlockInformation[BB->getParent()][BB] = Count;
+ return Count;
+}
+
+double ProfileInfo::getExecutionCount(const Function *F) {
+ std::map<const Function*, double>::iterator J =
+ FunctionInformation.find(F);
+ if (J != FunctionInformation.end())
+ return J->second;
+
+ // isDeclaration() is checked here and not at start of function to allow
+ // functions without a body still to have a execution count.
+ if (F->isDeclaration()) return MissingValue;
+
+ double Count = getExecutionCount(&F->getEntryBlock());
+ if (Count != MissingValue) FunctionInformation[F] = Count;
return Count;
}
+/// Replaces all occurences of RmBB in the ProfilingInfo with DestBB.
+/// This checks all edges of the function the blocks reside in and replaces the
+/// occurences of RmBB with DestBB.
+void ProfileInfo::replaceAllUses(const BasicBlock *RmBB,
+ const BasicBlock *DestBB) {
+ DEBUG(errs() << "Replacing " << RmBB->getNameStr()
+ << " with " << DestBB->getNameStr() << "\n");
+ const Function *F = DestBB->getParent();
+ std::map<const Function*, EdgeWeights>::iterator J =
+ EdgeInformation.find(F);
+ if (J == EdgeInformation.end()) return;
+
+ for (EdgeWeights::iterator I = J->second.begin(), E = J->second.end();
+ I != E; ++I) {
+ Edge e = I->first;
+ Edge newedge; bool foundedge = false;
+ if (e.first == RmBB) {
+ newedge = getEdge(DestBB, e.second);
+ foundedge = true;
+ }
+ if (e.second == RmBB) {
+ newedge = getEdge(e.first, DestBB);
+ foundedge = true;
+ }
+ if (foundedge) {
+ double w = getEdgeWeight(e);
+ EdgeInformation[F][newedge] = w;
+ DEBUG(errs() << "Replacing " << e << " with " << newedge << "\n");
+ J->second.erase(e);
+ }
+ }
+}
+
+/// Splits an edge in the ProfileInfo and redirects flow over NewBB.
+/// Since its possible that there is more than one edge in the CFG from FristBB
+/// to SecondBB its necessary to redirect the flow proporionally.
+void ProfileInfo::splitEdge(const BasicBlock *FirstBB,
+ const BasicBlock *SecondBB,
+ const BasicBlock *NewBB,
+ bool MergeIdenticalEdges) {
+ const Function *F = FirstBB->getParent();
+ std::map<const Function*, EdgeWeights>::iterator J =
+ EdgeInformation.find(F);
+ if (J == EdgeInformation.end()) return;
+
+ // Generate edges and read current weight.
+ Edge e = getEdge(FirstBB, SecondBB);
+ Edge n1 = getEdge(FirstBB, NewBB);
+ Edge n2 = getEdge(NewBB, SecondBB);
+ EdgeWeights &ECs = J->second;
+ double w = ECs[e];
+
+ int succ_count = 0;
+ if (!MergeIdenticalEdges) {
+ // First count the edges from FristBB to SecondBB, if there is more than
+ // one, only slice out a proporional part for NewBB.
+ for(succ_const_iterator BBI = succ_begin(FirstBB), BBE = succ_end(FirstBB);
+ BBI != BBE; ++BBI) {
+ if (*BBI == SecondBB) succ_count++;
+ }
+ // When the NewBB is completely new, increment the count by one so that
+ // the counts are properly distributed.
+ if (getExecutionCount(NewBB) == ProfileInfo::MissingValue) succ_count++;
+ } else {
+ // When the edges are merged anyway, then redirect all flow.
+ succ_count = 1;
+ }
+ // We know now how many edges there are from FirstBB to SecondBB, reroute a
+ // proportional part of the edge weight over NewBB.
+ double neww = w / succ_count;
+ ECs[n1] += neww;
+ ECs[n2] += neww;
+ BlockInformation[F][NewBB] += neww;
+ if (succ_count == 1) {
+ ECs.erase(e);
+ } else {
+ ECs[e] -= neww;
+ }
+}
+
+raw_ostream& llvm::operator<<(raw_ostream &O, ProfileInfo::Edge E) {
+ O << "(";
+ O << (E.first ? E.first->getNameStr() : "0");
+ O << ",";
+ O << (E.second ? E.second->getNameStr() : "0");
+ return O << ")";
+}
//===----------------------------------------------------------------------===//
// NoProfile ProfileInfo implementation
OpenPOWER on IntegriCloud