mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-30 07:00:45 +00:00
7a2bdde0a0
Luis Felipe Strano Moraes! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@129558 91177308-0d34-0410-b5e6-96231b3b80d8
1106 lines
33 KiB
C++
1106 lines
33 KiB
C++
//===- ProfileInfo.cpp - Profile Info Interface ---------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file implements the abstract ProfileInfo interface, and the default
|
|
// "no profile" implementation.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
#define DEBUG_TYPE "profile-info"
|
|
#include "llvm/Analysis/Passes.h"
|
|
#include "llvm/Analysis/ProfileInfo.h"
|
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
|
#include "llvm/CodeGen/MachineFunction.h"
|
|
#include "llvm/Pass.h"
|
|
#include "llvm/Support/CFG.h"
|
|
#include "llvm/ADT/SmallSet.h"
|
|
#include <set>
|
|
#include <queue>
|
|
#include <limits>
|
|
using namespace llvm;
|
|
|
|
namespace llvm {
|
|
template<> char ProfileInfoT<Function,BasicBlock>::ID = 0;
|
|
}
|
|
|
|
// Register the ProfileInfo interface, providing a nice name to refer to.
|
|
INITIALIZE_ANALYSIS_GROUP(ProfileInfo, "Profile Information", NoProfileInfo)
|
|
|
|
namespace llvm {
|
|
|
|
template <>
|
|
ProfileInfoT<MachineFunction, MachineBasicBlock>::ProfileInfoT() {}
|
|
template <>
|
|
ProfileInfoT<MachineFunction, MachineBasicBlock>::~ProfileInfoT() {}
|
|
|
|
template <>
|
|
ProfileInfoT<Function, BasicBlock>::ProfileInfoT() {
|
|
MachineProfile = 0;
|
|
}
|
|
template <>
|
|
ProfileInfoT<Function, BasicBlock>::~ProfileInfoT() {
|
|
if (MachineProfile) delete MachineProfile;
|
|
}
|
|
|
|
template<>
|
|
char ProfileInfoT<MachineFunction, MachineBasicBlock>::ID = 0;
|
|
|
|
template<>
|
|
const double ProfileInfoT<Function,BasicBlock>::MissingValue = -1;
|
|
|
|
template<> const
|
|
double ProfileInfoT<MachineFunction, MachineBasicBlock>::MissingValue = -1;
|
|
|
|
template<> double
|
|
ProfileInfoT<Function,BasicBlock>::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;
|
|
}
|
|
|
|
double Count = MissingValue;
|
|
|
|
const_pred_iterator PI = pred_begin(BB), PE = pred_end(BB);
|
|
|
|
// Are there zero predecessors of this block?
|
|
if (PI == PE) {
|
|
Edge e = getEdge(0, BB);
|
|
Count = getEdgeWeight(e);
|
|
} else {
|
|
// Otherwise, if there are predecessors, the execution count of this block is
|
|
// the sum of the edge frequencies from the incoming edges.
|
|
std::set<const BasicBlock*> ProcessedPreds;
|
|
Count = 0;
|
|
for (; PI != PE; ++PI) {
|
|
const BasicBlock *P = *PI;
|
|
if (ProcessedPreds.insert(P).second) {
|
|
double w = getEdgeWeight(getEdge(P, BB));
|
|
if (w == MissingValue) {
|
|
Count = MissingValue;
|
|
break;
|
|
}
|
|
Count += w;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If the predecessors did not suffice to get block weight, try successors.
|
|
if (Count == MissingValue) {
|
|
|
|
succ_const_iterator SI = succ_begin(BB), SE = succ_end(BB);
|
|
|
|
// Are there zero successors of this block?
|
|
if (SI == SE) {
|
|
Edge e = getEdge(BB,0);
|
|
Count = getEdgeWeight(e);
|
|
} else {
|
|
std::set<const BasicBlock*> ProcessedSuccs;
|
|
Count = 0;
|
|
for (; SI != SE; ++SI)
|
|
if (ProcessedSuccs.insert(*SI).second) {
|
|
double w = getEdgeWeight(getEdge(BB, *SI));
|
|
if (w == MissingValue) {
|
|
Count = MissingValue;
|
|
break;
|
|
}
|
|
Count += w;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Count != MissingValue) BlockInformation[BB->getParent()][BB] = Count;
|
|
return Count;
|
|
}
|
|
|
|
template<>
|
|
double ProfileInfoT<MachineFunction, MachineBasicBlock>::
|
|
getExecutionCount(const MachineBasicBlock *MBB) {
|
|
std::map<const MachineFunction*, BlockCounts>::iterator J =
|
|
BlockInformation.find(MBB->getParent());
|
|
if (J != BlockInformation.end()) {
|
|
BlockCounts::iterator I = J->second.find(MBB);
|
|
if (I != J->second.end())
|
|
return I->second;
|
|
}
|
|
|
|
return MissingValue;
|
|
}
|
|
|
|
template<>
|
|
double ProfileInfoT<Function,BasicBlock>::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;
|
|
}
|
|
|
|
template<>
|
|
double ProfileInfoT<MachineFunction, MachineBasicBlock>::
|
|
getExecutionCount(const MachineFunction *MF) {
|
|
std::map<const MachineFunction*, double>::iterator J =
|
|
FunctionInformation.find(MF);
|
|
if (J != FunctionInformation.end())
|
|
return J->second;
|
|
|
|
double Count = getExecutionCount(&MF->front());
|
|
if (Count != MissingValue) FunctionInformation[MF] = Count;
|
|
return Count;
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::
|
|
setExecutionCount(const BasicBlock *BB, double w) {
|
|
DEBUG(dbgs() << "Creating Block " << BB->getName()
|
|
<< " (weight: " << format("%.20g",w) << ")\n");
|
|
BlockInformation[BB->getParent()][BB] = w;
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<MachineFunction, MachineBasicBlock>::
|
|
setExecutionCount(const MachineBasicBlock *MBB, double w) {
|
|
DEBUG(dbgs() << "Creating Block " << MBB->getBasicBlock()->getName()
|
|
<< " (weight: " << format("%.20g",w) << ")\n");
|
|
BlockInformation[MBB->getParent()][MBB] = w;
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::addEdgeWeight(Edge e, double w) {
|
|
double oldw = getEdgeWeight(e);
|
|
assert (oldw != MissingValue && "Adding weight to Edge with no previous weight");
|
|
DEBUG(dbgs() << "Adding to Edge " << e
|
|
<< " (new weight: " << format("%.20g",oldw + w) << ")\n");
|
|
EdgeInformation[getFunction(e)][e] = oldw + w;
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::
|
|
addExecutionCount(const BasicBlock *BB, double w) {
|
|
double oldw = getExecutionCount(BB);
|
|
assert (oldw != MissingValue && "Adding weight to Block with no previous weight");
|
|
DEBUG(dbgs() << "Adding to Block " << BB->getName()
|
|
<< " (new weight: " << format("%.20g",oldw + w) << ")\n");
|
|
BlockInformation[BB->getParent()][BB] = oldw + w;
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::removeBlock(const BasicBlock *BB) {
|
|
std::map<const Function*, BlockCounts>::iterator J =
|
|
BlockInformation.find(BB->getParent());
|
|
if (J == BlockInformation.end()) return;
|
|
|
|
DEBUG(dbgs() << "Deleting " << BB->getName() << "\n");
|
|
J->second.erase(BB);
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::removeEdge(Edge e) {
|
|
std::map<const Function*, EdgeWeights>::iterator J =
|
|
EdgeInformation.find(getFunction(e));
|
|
if (J == EdgeInformation.end()) return;
|
|
|
|
DEBUG(dbgs() << "Deleting" << e << "\n");
|
|
J->second.erase(e);
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::
|
|
replaceEdge(const Edge &oldedge, const Edge &newedge) {
|
|
double w;
|
|
if ((w = getEdgeWeight(newedge)) == MissingValue) {
|
|
w = getEdgeWeight(oldedge);
|
|
DEBUG(dbgs() << "Replacing " << oldedge << " with " << newedge << "\n");
|
|
} else {
|
|
w += getEdgeWeight(oldedge);
|
|
DEBUG(dbgs() << "Adding " << oldedge << " to " << newedge << "\n");
|
|
}
|
|
setEdgeWeight(newedge,w);
|
|
removeEdge(oldedge);
|
|
}
|
|
|
|
template<>
|
|
const BasicBlock *ProfileInfoT<Function,BasicBlock>::
|
|
GetPath(const BasicBlock *Src, const BasicBlock *Dest,
|
|
Path &P, unsigned Mode) {
|
|
const BasicBlock *BB = 0;
|
|
bool hasFoundPath = false;
|
|
|
|
std::queue<const BasicBlock *> BFS;
|
|
BFS.push(Src);
|
|
|
|
while(BFS.size() && !hasFoundPath) {
|
|
BB = BFS.front();
|
|
BFS.pop();
|
|
|
|
succ_const_iterator Succ = succ_begin(BB), End = succ_end(BB);
|
|
if (Succ == End) {
|
|
P[0] = BB;
|
|
if (Mode & GetPathToExit) {
|
|
hasFoundPath = true;
|
|
BB = 0;
|
|
}
|
|
}
|
|
for(;Succ != End; ++Succ) {
|
|
if (P.find(*Succ) != P.end()) continue;
|
|
Edge e = getEdge(BB,*Succ);
|
|
if ((Mode & GetPathWithNewEdges) && (getEdgeWeight(e) != MissingValue)) continue;
|
|
P[*Succ] = BB;
|
|
BFS.push(*Succ);
|
|
if ((Mode & GetPathToDest) && *Succ == Dest) {
|
|
hasFoundPath = true;
|
|
BB = *Succ;
|
|
break;
|
|
}
|
|
if ((Mode & GetPathToValue) && (getExecutionCount(*Succ) != MissingValue)) {
|
|
hasFoundPath = true;
|
|
BB = *Succ;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return BB;
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::
|
|
divertFlow(const Edge &oldedge, const Edge &newedge) {
|
|
DEBUG(dbgs() << "Diverting " << oldedge << " via " << newedge );
|
|
|
|
// First check if the old edge was taken, if not, just delete it...
|
|
if (getEdgeWeight(oldedge) == 0) {
|
|
removeEdge(oldedge);
|
|
return;
|
|
}
|
|
|
|
Path P;
|
|
P[newedge.first] = 0;
|
|
P[newedge.second] = newedge.first;
|
|
const BasicBlock *BB = GetPath(newedge.second,oldedge.second,P,GetPathToExit | GetPathToDest);
|
|
|
|
double w = getEdgeWeight (oldedge);
|
|
DEBUG(dbgs() << ", Weight: " << format("%.20g",w) << "\n");
|
|
do {
|
|
const BasicBlock *Parent = P.find(BB)->second;
|
|
Edge e = getEdge(Parent,BB);
|
|
double oldw = getEdgeWeight(e);
|
|
double oldc = getExecutionCount(e.first);
|
|
setEdgeWeight(e, w+oldw);
|
|
if (Parent != oldedge.first) {
|
|
setExecutionCount(e.first, w+oldc);
|
|
}
|
|
BB = Parent;
|
|
} while (BB != newedge.first);
|
|
removeEdge(oldedge);
|
|
}
|
|
|
|
/// Replaces all occurrences of RmBB in the ProfilingInfo with DestBB.
|
|
/// This checks all edges of the function the blocks reside in and replaces the
|
|
/// occurrences of RmBB with DestBB.
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::
|
|
replaceAllUses(const BasicBlock *RmBB, const BasicBlock *DestBB) {
|
|
DEBUG(dbgs() << "Replacing " << RmBB->getName()
|
|
<< " with " << DestBB->getName() << "\n");
|
|
const Function *F = DestBB->getParent();
|
|
std::map<const Function*, EdgeWeights>::iterator J =
|
|
EdgeInformation.find(F);
|
|
if (J == EdgeInformation.end()) return;
|
|
|
|
Edge e, newedge;
|
|
bool erasededge = false;
|
|
EdgeWeights::iterator I = J->second.begin(), E = J->second.end();
|
|
while(I != E) {
|
|
e = (I++)->first;
|
|
bool foundedge = false; bool eraseedge = false;
|
|
if (e.first == RmBB) {
|
|
if (e.second == DestBB) {
|
|
eraseedge = true;
|
|
} else {
|
|
newedge = getEdge(DestBB, e.second);
|
|
foundedge = true;
|
|
}
|
|
}
|
|
if (e.second == RmBB) {
|
|
if (e.first == DestBB) {
|
|
eraseedge = true;
|
|
} else {
|
|
newedge = getEdge(e.first, DestBB);
|
|
foundedge = true;
|
|
}
|
|
}
|
|
if (foundedge) {
|
|
replaceEdge(e, newedge);
|
|
}
|
|
if (eraseedge) {
|
|
if (erasededge) {
|
|
Edge newedge = getEdge(DestBB, DestBB);
|
|
replaceEdge(e, newedge);
|
|
} else {
|
|
removeEdge(e);
|
|
erasededge = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 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.
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::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 = floor(w / succ_count);
|
|
ECs[n1] += neww;
|
|
ECs[n2] += neww;
|
|
BlockInformation[F][NewBB] += neww;
|
|
if (succ_count == 1) {
|
|
ECs.erase(e);
|
|
} else {
|
|
ECs[e] -= neww;
|
|
}
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::splitBlock(const BasicBlock *Old,
|
|
const BasicBlock* New) {
|
|
const Function *F = Old->getParent();
|
|
std::map<const Function*, EdgeWeights>::iterator J =
|
|
EdgeInformation.find(F);
|
|
if (J == EdgeInformation.end()) return;
|
|
|
|
DEBUG(dbgs() << "Splitting " << Old->getName() << " to " << New->getName() << "\n");
|
|
|
|
std::set<Edge> Edges;
|
|
for (EdgeWeights::iterator ewi = J->second.begin(), ewe = J->second.end();
|
|
ewi != ewe; ++ewi) {
|
|
Edge old = ewi->first;
|
|
if (old.first == Old) {
|
|
Edges.insert(old);
|
|
}
|
|
}
|
|
for (std::set<Edge>::iterator EI = Edges.begin(), EE = Edges.end();
|
|
EI != EE; ++EI) {
|
|
Edge newedge = getEdge(New, EI->second);
|
|
replaceEdge(*EI, newedge);
|
|
}
|
|
|
|
double w = getExecutionCount(Old);
|
|
setEdgeWeight(getEdge(Old, New), w);
|
|
setExecutionCount(New, w);
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::splitBlock(const BasicBlock *BB,
|
|
const BasicBlock* NewBB,
|
|
BasicBlock *const *Preds,
|
|
unsigned NumPreds) {
|
|
const Function *F = BB->getParent();
|
|
std::map<const Function*, EdgeWeights>::iterator J =
|
|
EdgeInformation.find(F);
|
|
if (J == EdgeInformation.end()) return;
|
|
|
|
DEBUG(dbgs() << "Splitting " << NumPreds << " Edges from " << BB->getName()
|
|
<< " to " << NewBB->getName() << "\n");
|
|
|
|
// Collect weight that was redirected over NewBB.
|
|
double newweight = 0;
|
|
|
|
std::set<const BasicBlock *> ProcessedPreds;
|
|
// For all requestes Predecessors.
|
|
for (unsigned pred = 0; pred < NumPreds; ++pred) {
|
|
const BasicBlock * Pred = Preds[pred];
|
|
if (ProcessedPreds.insert(Pred).second) {
|
|
// Create edges and read old weight.
|
|
Edge oldedge = getEdge(Pred, BB);
|
|
Edge newedge = getEdge(Pred, NewBB);
|
|
|
|
// Remember how much weight was redirected.
|
|
newweight += getEdgeWeight(oldedge);
|
|
|
|
replaceEdge(oldedge,newedge);
|
|
}
|
|
}
|
|
|
|
Edge newedge = getEdge(NewBB,BB);
|
|
setEdgeWeight(newedge, newweight);
|
|
setExecutionCount(NewBB, newweight);
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::transfer(const Function *Old,
|
|
const Function *New) {
|
|
DEBUG(dbgs() << "Replacing Function " << Old->getName() << " with "
|
|
<< New->getName() << "\n");
|
|
std::map<const Function*, EdgeWeights>::iterator J =
|
|
EdgeInformation.find(Old);
|
|
if(J != EdgeInformation.end()) {
|
|
EdgeInformation[New] = J->second;
|
|
}
|
|
EdgeInformation.erase(Old);
|
|
BlockInformation.erase(Old);
|
|
FunctionInformation.erase(Old);
|
|
}
|
|
|
|
static double readEdgeOrRemember(ProfileInfo::Edge edge, double w,
|
|
ProfileInfo::Edge &tocalc, unsigned &uncalc) {
|
|
if (w == ProfileInfo::MissingValue) {
|
|
tocalc = edge;
|
|
uncalc++;
|
|
return 0;
|
|
} else {
|
|
return w;
|
|
}
|
|
}
|
|
|
|
template<>
|
|
bool ProfileInfoT<Function,BasicBlock>::
|
|
CalculateMissingEdge(const BasicBlock *BB, Edge &removed,
|
|
bool assumeEmptySelf) {
|
|
Edge edgetocalc;
|
|
unsigned uncalculated = 0;
|
|
|
|
// collect weights of all incoming and outgoing edges, rememer edges that
|
|
// have no value
|
|
double incount = 0;
|
|
SmallSet<const BasicBlock*,8> pred_visited;
|
|
const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
|
if (bbi==bbe) {
|
|
Edge e = getEdge(0,BB);
|
|
incount += readEdgeOrRemember(e, getEdgeWeight(e) ,edgetocalc,uncalculated);
|
|
}
|
|
for (;bbi != bbe; ++bbi) {
|
|
if (pred_visited.insert(*bbi)) {
|
|
Edge e = getEdge(*bbi,BB);
|
|
incount += readEdgeOrRemember(e, getEdgeWeight(e) ,edgetocalc,uncalculated);
|
|
}
|
|
}
|
|
|
|
double outcount = 0;
|
|
SmallSet<const BasicBlock*,8> succ_visited;
|
|
succ_const_iterator sbbi = succ_begin(BB), sbbe = succ_end(BB);
|
|
if (sbbi==sbbe) {
|
|
Edge e = getEdge(BB,0);
|
|
if (getEdgeWeight(e) == MissingValue) {
|
|
double w = getExecutionCount(BB);
|
|
if (w != MissingValue) {
|
|
setEdgeWeight(e,w);
|
|
removed = e;
|
|
}
|
|
}
|
|
outcount += readEdgeOrRemember(e, getEdgeWeight(e), edgetocalc, uncalculated);
|
|
}
|
|
for (;sbbi != sbbe; ++sbbi) {
|
|
if (succ_visited.insert(*sbbi)) {
|
|
Edge e = getEdge(BB,*sbbi);
|
|
outcount += readEdgeOrRemember(e, getEdgeWeight(e), edgetocalc, uncalculated);
|
|
}
|
|
}
|
|
|
|
// if exactly one edge weight was missing, calculate it and remove it from
|
|
// spanning tree
|
|
if (uncalculated == 0 ) {
|
|
return true;
|
|
} else
|
|
if (uncalculated == 1) {
|
|
if (incount < outcount) {
|
|
EdgeInformation[BB->getParent()][edgetocalc] = outcount-incount;
|
|
} else {
|
|
EdgeInformation[BB->getParent()][edgetocalc] = incount-outcount;
|
|
}
|
|
DEBUG(dbgs() << "--Calc Edge Counter for " << edgetocalc << ": "
|
|
<< format("%.20g", getEdgeWeight(edgetocalc)) << "\n");
|
|
removed = edgetocalc;
|
|
return true;
|
|
} else
|
|
if (uncalculated == 2 && assumeEmptySelf && edgetocalc.first == edgetocalc.second && incount == outcount) {
|
|
setEdgeWeight(edgetocalc, incount * 10);
|
|
removed = edgetocalc;
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static void readEdge(ProfileInfo *PI, ProfileInfo::Edge e, double &calcw, std::set<ProfileInfo::Edge> &misscount) {
|
|
double w = PI->getEdgeWeight(e);
|
|
if (w != ProfileInfo::MissingValue) {
|
|
calcw += w;
|
|
} else {
|
|
misscount.insert(e);
|
|
}
|
|
}
|
|
|
|
template<>
|
|
bool ProfileInfoT<Function,BasicBlock>::EstimateMissingEdges(const BasicBlock *BB) {
|
|
double inWeight = 0;
|
|
std::set<Edge> inMissing;
|
|
std::set<const BasicBlock*> ProcessedPreds;
|
|
const_pred_iterator bbi = pred_begin(BB), bbe = pred_end(BB);
|
|
if (bbi == bbe) {
|
|
readEdge(this,getEdge(0,BB),inWeight,inMissing);
|
|
}
|
|
for( ; bbi != bbe; ++bbi ) {
|
|
if (ProcessedPreds.insert(*bbi).second) {
|
|
readEdge(this,getEdge(*bbi,BB),inWeight,inMissing);
|
|
}
|
|
}
|
|
|
|
double outWeight = 0;
|
|
std::set<Edge> outMissing;
|
|
std::set<const BasicBlock*> ProcessedSuccs;
|
|
succ_const_iterator sbbi = succ_begin(BB), sbbe = succ_end(BB);
|
|
if (sbbi == sbbe)
|
|
readEdge(this,getEdge(BB,0),outWeight,outMissing);
|
|
for ( ; sbbi != sbbe; ++sbbi ) {
|
|
if (ProcessedSuccs.insert(*sbbi).second) {
|
|
readEdge(this,getEdge(BB,*sbbi),outWeight,outMissing);
|
|
}
|
|
}
|
|
|
|
double share;
|
|
std::set<Edge>::iterator ei,ee;
|
|
if (inMissing.size() == 0 && outMissing.size() > 0) {
|
|
ei = outMissing.begin();
|
|
ee = outMissing.end();
|
|
share = inWeight/outMissing.size();
|
|
setExecutionCount(BB,inWeight);
|
|
} else
|
|
if (inMissing.size() > 0 && outMissing.size() == 0 && outWeight == 0) {
|
|
ei = inMissing.begin();
|
|
ee = inMissing.end();
|
|
share = 0;
|
|
setExecutionCount(BB,0);
|
|
} else
|
|
if (inMissing.size() == 0 && outMissing.size() == 0) {
|
|
setExecutionCount(BB,outWeight);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
for ( ; ei != ee; ++ei ) {
|
|
setEdgeWeight(*ei,share);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
template<>
|
|
void ProfileInfoT<Function,BasicBlock>::repair(const Function *F) {
|
|
// if (getExecutionCount(&(F->getEntryBlock())) == 0) {
|
|
// for (Function::const_iterator FI = F->begin(), FE = F->end();
|
|
// FI != FE; ++FI) {
|
|
// const BasicBlock* BB = &(*FI);
|
|
// {
|
|
// const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
|
// if (NBB == End) {
|
|
// setEdgeWeight(getEdge(0,BB),0);
|
|
// }
|
|
// for(;NBB != End; ++NBB) {
|
|
// setEdgeWeight(getEdge(*NBB,BB),0);
|
|
// }
|
|
// }
|
|
// {
|
|
// succ_const_iterator NBB = succ_begin(BB), End = succ_end(BB);
|
|
// if (NBB == End) {
|
|
// setEdgeWeight(getEdge(0,BB),0);
|
|
// }
|
|
// for(;NBB != End; ++NBB) {
|
|
// setEdgeWeight(getEdge(*NBB,BB),0);
|
|
// }
|
|
// }
|
|
// }
|
|
// return;
|
|
// }
|
|
// The set of BasicBlocks that are still unvisited.
|
|
std::set<const BasicBlock*> Unvisited;
|
|
|
|
// The set of return edges (Edges with no successors).
|
|
std::set<Edge> ReturnEdges;
|
|
double ReturnWeight = 0;
|
|
|
|
// First iterate over the whole function and collect:
|
|
// 1) The blocks in this function in the Unvisited set.
|
|
// 2) The return edges in the ReturnEdges set.
|
|
// 3) The flow that is leaving the function already via return edges.
|
|
|
|
// Data structure for searching the function.
|
|
std::queue<const BasicBlock *> BFS;
|
|
const BasicBlock *BB = &(F->getEntryBlock());
|
|
BFS.push(BB);
|
|
Unvisited.insert(BB);
|
|
|
|
while (BFS.size()) {
|
|
BB = BFS.front(); BFS.pop();
|
|
succ_const_iterator NBB = succ_begin(BB), End = succ_end(BB);
|
|
if (NBB == End) {
|
|
Edge e = getEdge(BB,0);
|
|
double w = getEdgeWeight(e);
|
|
if (w == MissingValue) {
|
|
// If the return edge has no value, try to read value from block.
|
|
double bw = getExecutionCount(BB);
|
|
if (bw != MissingValue) {
|
|
setEdgeWeight(e,bw);
|
|
ReturnWeight += bw;
|
|
} else {
|
|
// If both return edge and block provide no value, collect edge.
|
|
ReturnEdges.insert(e);
|
|
}
|
|
} else {
|
|
// If the return edge has a proper value, collect it.
|
|
ReturnWeight += w;
|
|
}
|
|
}
|
|
for (;NBB != End; ++NBB) {
|
|
if (Unvisited.insert(*NBB).second) {
|
|
BFS.push(*NBB);
|
|
}
|
|
}
|
|
}
|
|
|
|
while (Unvisited.size() > 0) {
|
|
unsigned oldUnvisitedCount = Unvisited.size();
|
|
bool FoundPath = false;
|
|
|
|
// If there is only one edge left, calculate it.
|
|
if (ReturnEdges.size() == 1) {
|
|
ReturnWeight = getExecutionCount(&(F->getEntryBlock())) - ReturnWeight;
|
|
|
|
Edge e = *ReturnEdges.begin();
|
|
setEdgeWeight(e,ReturnWeight);
|
|
setExecutionCount(e.first,ReturnWeight);
|
|
|
|
Unvisited.erase(e.first);
|
|
ReturnEdges.erase(e);
|
|
continue;
|
|
}
|
|
|
|
// Calculate all blocks where only one edge is missing, this may also
|
|
// resolve furhter return edges.
|
|
std::set<const BasicBlock *>::iterator FI = Unvisited.begin(), FE = Unvisited.end();
|
|
while(FI != FE) {
|
|
const BasicBlock *BB = *FI; ++FI;
|
|
Edge e;
|
|
if(CalculateMissingEdge(BB,e,true)) {
|
|
if (BlockInformation[F].find(BB) == BlockInformation[F].end()) {
|
|
setExecutionCount(BB,getExecutionCount(BB));
|
|
}
|
|
Unvisited.erase(BB);
|
|
if (e.first != 0 && e.second == 0) {
|
|
ReturnEdges.erase(e);
|
|
ReturnWeight += getEdgeWeight(e);
|
|
}
|
|
}
|
|
}
|
|
if (oldUnvisitedCount > Unvisited.size()) continue;
|
|
|
|
// Estimate edge weights by dividing the flow proportionally.
|
|
FI = Unvisited.begin(), FE = Unvisited.end();
|
|
while(FI != FE) {
|
|
const BasicBlock *BB = *FI; ++FI;
|
|
const BasicBlock *Dest = 0;
|
|
bool AllEdgesHaveSameReturn = true;
|
|
// Check each Successor, these must all end up in the same or an empty
|
|
// return block otherwise its dangerous to do an estimation on them.
|
|
for (succ_const_iterator Succ = succ_begin(BB), End = succ_end(BB);
|
|
Succ != End; ++Succ) {
|
|
Path P;
|
|
GetPath(*Succ, 0, P, GetPathToExit);
|
|
if (Dest && Dest != P[0]) {
|
|
AllEdgesHaveSameReturn = false;
|
|
}
|
|
Dest = P[0];
|
|
}
|
|
if (AllEdgesHaveSameReturn) {
|
|
if(EstimateMissingEdges(BB)) {
|
|
Unvisited.erase(BB);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (oldUnvisitedCount > Unvisited.size()) continue;
|
|
|
|
// Check if there is a path to an block that has a known value and redirect
|
|
// flow accordingly.
|
|
FI = Unvisited.begin(), FE = Unvisited.end();
|
|
while(FI != FE && !FoundPath) {
|
|
// Fetch path.
|
|
const BasicBlock *BB = *FI; ++FI;
|
|
Path P;
|
|
const BasicBlock *Dest = GetPath(BB, 0, P, GetPathToValue);
|
|
|
|
// Calculate incoming flow.
|
|
double iw = 0; unsigned inmissing = 0; unsigned incount = 0; unsigned invalid = 0;
|
|
std::set<const BasicBlock *> Processed;
|
|
for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
|
NBB != End; ++NBB) {
|
|
if (Processed.insert(*NBB).second) {
|
|
Edge e = getEdge(*NBB, BB);
|
|
double ew = getEdgeWeight(e);
|
|
if (ew != MissingValue) {
|
|
iw += ew;
|
|
invalid++;
|
|
} else {
|
|
// If the path contains the successor, this means its a backedge,
|
|
// do not count as missing.
|
|
if (P.find(*NBB) == P.end())
|
|
inmissing++;
|
|
}
|
|
incount++;
|
|
}
|
|
}
|
|
if (inmissing == incount) continue;
|
|
if (invalid == 0) continue;
|
|
|
|
// Subtract (already) outgoing flow.
|
|
Processed.clear();
|
|
for (succ_const_iterator NBB = succ_begin(BB), End = succ_end(BB);
|
|
NBB != End; ++NBB) {
|
|
if (Processed.insert(*NBB).second) {
|
|
Edge e = getEdge(BB, *NBB);
|
|
double ew = getEdgeWeight(e);
|
|
if (ew != MissingValue) {
|
|
iw -= ew;
|
|
}
|
|
}
|
|
}
|
|
if (iw < 0) continue;
|
|
|
|
// Check the receiving end of the path if it can handle the flow.
|
|
double ow = getExecutionCount(Dest);
|
|
Processed.clear();
|
|
for (succ_const_iterator NBB = succ_begin(BB), End = succ_end(BB);
|
|
NBB != End; ++NBB) {
|
|
if (Processed.insert(*NBB).second) {
|
|
Edge e = getEdge(BB, *NBB);
|
|
double ew = getEdgeWeight(e);
|
|
if (ew != MissingValue) {
|
|
ow -= ew;
|
|
}
|
|
}
|
|
}
|
|
if (ow < 0) continue;
|
|
|
|
// Determine how much flow shall be used.
|
|
double ew = getEdgeWeight(getEdge(P[Dest],Dest));
|
|
if (ew != MissingValue) {
|
|
ew = ew<ow?ew:ow;
|
|
ew = ew<iw?ew:iw;
|
|
} else {
|
|
if (inmissing == 0)
|
|
ew = iw;
|
|
}
|
|
|
|
// Create flow.
|
|
if (ew != MissingValue) {
|
|
do {
|
|
Edge e = getEdge(P[Dest],Dest);
|
|
if (getEdgeWeight(e) == MissingValue) {
|
|
setEdgeWeight(e,ew);
|
|
FoundPath = true;
|
|
}
|
|
Dest = P[Dest];
|
|
} while (Dest != BB);
|
|
}
|
|
}
|
|
if (FoundPath) continue;
|
|
|
|
// Calculate a block with self loop.
|
|
FI = Unvisited.begin(), FE = Unvisited.end();
|
|
while(FI != FE && !FoundPath) {
|
|
const BasicBlock *BB = *FI; ++FI;
|
|
bool SelfEdgeFound = false;
|
|
for (succ_const_iterator NBB = succ_begin(BB), End = succ_end(BB);
|
|
NBB != End; ++NBB) {
|
|
if (*NBB == BB) {
|
|
SelfEdgeFound = true;
|
|
break;
|
|
}
|
|
}
|
|
if (SelfEdgeFound) {
|
|
Edge e = getEdge(BB,BB);
|
|
if (getEdgeWeight(e) == MissingValue) {
|
|
double iw = 0;
|
|
std::set<const BasicBlock *> Processed;
|
|
for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
|
NBB != End; ++NBB) {
|
|
if (Processed.insert(*NBB).second) {
|
|
Edge e = getEdge(*NBB, BB);
|
|
double ew = getEdgeWeight(e);
|
|
if (ew != MissingValue) {
|
|
iw += ew;
|
|
}
|
|
}
|
|
}
|
|
setEdgeWeight(e,iw * 10);
|
|
FoundPath = true;
|
|
}
|
|
}
|
|
}
|
|
if (FoundPath) continue;
|
|
|
|
// Determine backedges, set them to zero.
|
|
FI = Unvisited.begin(), FE = Unvisited.end();
|
|
while(FI != FE && !FoundPath) {
|
|
const BasicBlock *BB = *FI; ++FI;
|
|
const BasicBlock *Dest = 0;
|
|
Path P;
|
|
bool BackEdgeFound = false;
|
|
for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
|
NBB != End; ++NBB) {
|
|
Dest = GetPath(BB, *NBB, P, GetPathToDest | GetPathWithNewEdges);
|
|
if (Dest == *NBB) {
|
|
BackEdgeFound = true;
|
|
break;
|
|
}
|
|
}
|
|
if (BackEdgeFound) {
|
|
Edge e = getEdge(Dest,BB);
|
|
double w = getEdgeWeight(e);
|
|
if (w == MissingValue) {
|
|
setEdgeWeight(e,0);
|
|
FoundPath = true;
|
|
}
|
|
do {
|
|
Edge e = getEdge(P[Dest], Dest);
|
|
double w = getEdgeWeight(e);
|
|
if (w == MissingValue) {
|
|
setEdgeWeight(e,0);
|
|
FoundPath = true;
|
|
}
|
|
Dest = P[Dest];
|
|
} while (Dest != BB);
|
|
}
|
|
}
|
|
if (FoundPath) continue;
|
|
|
|
// Channel flow to return block.
|
|
FI = Unvisited.begin(), FE = Unvisited.end();
|
|
while(FI != FE && !FoundPath) {
|
|
const BasicBlock *BB = *FI; ++FI;
|
|
|
|
Path P;
|
|
const BasicBlock *Dest = GetPath(BB, 0, P, GetPathToExit | GetPathWithNewEdges);
|
|
Dest = P[0];
|
|
if (!Dest) continue;
|
|
|
|
if (getEdgeWeight(getEdge(Dest,0)) == MissingValue) {
|
|
// Calculate incoming flow.
|
|
double iw = 0;
|
|
std::set<const BasicBlock *> Processed;
|
|
for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
|
NBB != End; ++NBB) {
|
|
if (Processed.insert(*NBB).second) {
|
|
Edge e = getEdge(*NBB, BB);
|
|
double ew = getEdgeWeight(e);
|
|
if (ew != MissingValue) {
|
|
iw += ew;
|
|
}
|
|
}
|
|
}
|
|
do {
|
|
Edge e = getEdge(P[Dest], Dest);
|
|
double w = getEdgeWeight(e);
|
|
if (w == MissingValue) {
|
|
setEdgeWeight(e,iw);
|
|
FoundPath = true;
|
|
} else {
|
|
assert(0 && "Edge should not have value already!");
|
|
}
|
|
Dest = P[Dest];
|
|
} while (Dest != BB);
|
|
}
|
|
}
|
|
if (FoundPath) continue;
|
|
|
|
// Speculatively set edges to zero.
|
|
FI = Unvisited.begin(), FE = Unvisited.end();
|
|
while(FI != FE && !FoundPath) {
|
|
const BasicBlock *BB = *FI; ++FI;
|
|
|
|
for (const_pred_iterator NBB = pred_begin(BB), End = pred_end(BB);
|
|
NBB != End; ++NBB) {
|
|
Edge e = getEdge(*NBB,BB);
|
|
double w = getEdgeWeight(e);
|
|
if (w == MissingValue) {
|
|
setEdgeWeight(e,0);
|
|
FoundPath = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (FoundPath) continue;
|
|
|
|
errs() << "{";
|
|
FI = Unvisited.begin(), FE = Unvisited.end();
|
|
while(FI != FE) {
|
|
const BasicBlock *BB = *FI; ++FI;
|
|
dbgs() << BB->getName();
|
|
if (FI != FE)
|
|
dbgs() << ",";
|
|
}
|
|
errs() << "}";
|
|
|
|
errs() << "ASSERT: could not repair function";
|
|
assert(0 && "could not repair function");
|
|
}
|
|
|
|
EdgeWeights J = EdgeInformation[F];
|
|
for (EdgeWeights::iterator EI = J.begin(), EE = J.end(); EI != EE; ++EI) {
|
|
Edge e = EI->first;
|
|
|
|
bool SuccFound = false;
|
|
if (e.first != 0) {
|
|
succ_const_iterator NBB = succ_begin(e.first), End = succ_end(e.first);
|
|
if (NBB == End) {
|
|
if (0 == e.second) {
|
|
SuccFound = true;
|
|
}
|
|
}
|
|
for (;NBB != End; ++NBB) {
|
|
if (*NBB == e.second) {
|
|
SuccFound = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!SuccFound) {
|
|
removeEdge(e);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
raw_ostream& operator<<(raw_ostream &O, const Function *F) {
|
|
return O << F->getName();
|
|
}
|
|
|
|
raw_ostream& operator<<(raw_ostream &O, const MachineFunction *MF) {
|
|
return O << MF->getFunction()->getName() << "(MF)";
|
|
}
|
|
|
|
raw_ostream& operator<<(raw_ostream &O, const BasicBlock *BB) {
|
|
return O << BB->getName();
|
|
}
|
|
|
|
raw_ostream& operator<<(raw_ostream &O, const MachineBasicBlock *MBB) {
|
|
return O << MBB->getBasicBlock()->getName() << "(MB)";
|
|
}
|
|
|
|
raw_ostream& operator<<(raw_ostream &O, std::pair<const BasicBlock *, const BasicBlock *> E) {
|
|
O << "(";
|
|
|
|
if (E.first)
|
|
O << E.first;
|
|
else
|
|
O << "0";
|
|
|
|
O << ",";
|
|
|
|
if (E.second)
|
|
O << E.second;
|
|
else
|
|
O << "0";
|
|
|
|
return O << ")";
|
|
}
|
|
|
|
raw_ostream& operator<<(raw_ostream &O, std::pair<const MachineBasicBlock *, const MachineBasicBlock *> E) {
|
|
O << "(";
|
|
|
|
if (E.first)
|
|
O << E.first;
|
|
else
|
|
O << "0";
|
|
|
|
O << ",";
|
|
|
|
if (E.second)
|
|
O << E.second;
|
|
else
|
|
O << "0";
|
|
|
|
return O << ")";
|
|
}
|
|
|
|
} // namespace llvm
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// NoProfile ProfileInfo implementation
|
|
//
|
|
|
|
namespace {
|
|
struct NoProfileInfo : public ImmutablePass, public ProfileInfo {
|
|
static char ID; // Class identification, replacement for typeinfo
|
|
NoProfileInfo() : ImmutablePass(ID) {
|
|
initializeNoProfileInfoPass(*PassRegistry::getPassRegistry());
|
|
}
|
|
|
|
/// getAdjustedAnalysisPointer - This method is used when a pass implements
|
|
/// an analysis interface through multiple inheritance. If needed, it
|
|
/// should override this to adjust the this pointer as needed for the
|
|
/// specified pass info.
|
|
virtual void *getAdjustedAnalysisPointer(AnalysisID PI) {
|
|
if (PI == &ProfileInfo::ID)
|
|
return (ProfileInfo*)this;
|
|
return this;
|
|
}
|
|
|
|
virtual const char *getPassName() const {
|
|
return "NoProfileInfo";
|
|
}
|
|
};
|
|
} // End of anonymous namespace
|
|
|
|
char NoProfileInfo::ID = 0;
|
|
// Register this pass...
|
|
INITIALIZE_AG_PASS(NoProfileInfo, ProfileInfo, "no-profile",
|
|
"No Profile Information", false, true, true)
|
|
|
|
ImmutablePass *llvm::createNoProfileInfoPass() { return new NoProfileInfo(); }
|