mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-22 10:29:35 +00:00
must be called in the pass's constructor. This function uses static dependency declarations to recursively initialize the pass's dependencies. Clients that only create passes through the createFooPass() APIs will require no changes. Clients that want to use the CommandLine options for passes will need to manually call the appropriate initialization functions in PassInitialization.h before parsing commandline arguments. I have tested this with all standard configurations of clang and llvm-gcc on Darwin. It is possible that there are problems with the static dependencies that will only be visible with non-standard options. If you encounter any crash in pass registration/creation, please send the testcase to me directly. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116820 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 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.
|
|
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 recieving 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;
|
|
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(); }
|