diff --git a/lib/Analysis/ProfileInfoLoader.cpp b/lib/Analysis/ProfileInfoLoader.cpp index cef0897983e..6c3f0d7bb37 100644 --- a/lib/Analysis/ProfileInfoLoader.cpp +++ b/lib/Analysis/ProfileInfoLoader.cpp @@ -16,6 +16,7 @@ #include "llvm/Module.h" #include "llvm/InstrTypes.h" #include +#include using namespace llvm; enum ProfilingType { @@ -145,15 +146,19 @@ ProfileInfoLoader::ProfileInfoLoader(const char *ToolName, void ProfileInfoLoader::getFunctionCounts(std::vector > &Counts) { if (FunctionCounts.empty()) { - // Synthesize function frequency information from the number of times their - // entry blocks were executed. - std::vector > BlockCounts; - getBlockCounts(BlockCounts); - - for (unsigned i = 0, e = BlockCounts.size(); i != e; ++i) - if (&BlockCounts[i].first->getParent()->front() == BlockCounts[i].first) - Counts.push_back(std::make_pair(BlockCounts[i].first->getParent(), - BlockCounts[i].second)); + if (hasAccurateBlockCounts()) { + // Synthesize function frequency information from the number of times + // their entry blocks were executed. + std::vector > BlockCounts; + getBlockCounts(BlockCounts); + + for (unsigned i = 0, e = BlockCounts.size(); i != e; ++i) + if (&BlockCounts[i].first->getParent()->front() == BlockCounts[i].first) + Counts.push_back(std::make_pair(BlockCounts[i].first->getParent(), + BlockCounts[i].second)); + } else { + std::cerr << "Function counts are not available!\n"; + } return; } @@ -171,8 +176,59 @@ void ProfileInfoLoader::getFunctionCounts(std::vector > &Counts) { if (BlockCounts.empty()) { - std::cerr << "Block counts not available, and no synthesis " - << "is implemented yet!\n"; + if (hasAccurateEdgeCounts()) { + // Synthesize block count information from edge frequency information. + // The block execution frequency is equal to the sum of the execution + // frequency of all outgoing edges from a block. + // + // If a block has no successors, this will not be correct, so we have to + // special case it. :( + std::vector > EdgeCounts; + getEdgeCounts(EdgeCounts); + + std::map InEdgeFreqs; + + BasicBlock *LastBlock = 0; + TerminatorInst *TI = 0; + for (unsigned i = 0, e = EdgeCounts.size(); i != e; ++i) { + if (EdgeCounts[i].first.first != LastBlock) { + LastBlock = EdgeCounts[i].first.first; + TI = LastBlock->getTerminator(); + Counts.push_back(std::make_pair(LastBlock, 0)); + } + Counts.back().second += EdgeCounts[i].second; + unsigned SuccNum = EdgeCounts[i].first.second; + if (SuccNum >= TI->getNumSuccessors()) { + static bool Warned = false; + if (!Warned) { + std::cerr << "WARNING: profile info doesn't seem to match" + << " the program!\n"; + Warned = true; + } + } else { + // If this successor has no successors of its own, we will never + // compute an execution count for that block. Remember the incoming + // edge frequencies to add later. + BasicBlock *Succ = TI->getSuccessor(SuccNum); + if (Succ->getTerminator()->getNumSuccessors() == 0) + InEdgeFreqs[Succ] += EdgeCounts[i].second; + } + } + + // Now we have to accumulate information for those blocks without + // successors into our table. + for (std::map::iterator I = InEdgeFreqs.begin(), + E = InEdgeFreqs.end(); I != E; ++I) { + unsigned i = 0; + for (; i != Counts.size() && Counts[i].first != I->first; ++i) + /*empty*/; + if (i == Counts.size()) Counts.push_back(std::make_pair(I->first, 0)); + Counts[i].second += I->second; + } + + } else { + std::cerr << "Block counts are not available!\n"; + } return; }