mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-26 21:32:10 +00:00
Refactor some code in SampleProfile.cpp
I'm adding new functionality in the sample profiler. This will require more data to be kept around for each function, so I moved the structure SampleProfile that we keep for each function into a separate class. There are no functional changes in this patch. It simply provides a new home where to place all the new data that I need to propagate weights through edges. There are some other name and minor edits throughout. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195780 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
fd115c47a2
commit
d0d8d6462a
@ -54,6 +54,55 @@ static cl::opt<std::string> SampleProfileFile(
|
||||
cl::desc("Profile file loaded by -sample-profile"), cl::Hidden);
|
||||
|
||||
namespace {
|
||||
|
||||
typedef DenseMap<uint32_t, uint32_t> BodySampleMap;
|
||||
typedef DenseMap<BasicBlock *, uint32_t> BlockWeightMap;
|
||||
|
||||
/// \brief Representation of the runtime profile for a function.
|
||||
///
|
||||
/// This data structure contains the runtime profile for a given
|
||||
/// function. It contains the total number of samples collected
|
||||
/// in the function and a map of samples collected in every statement.
|
||||
class SampleFunctionProfile {
|
||||
public:
|
||||
SampleFunctionProfile() : TotalSamples(0), TotalHeadSamples(0) {}
|
||||
|
||||
bool emitAnnotations(Function &F);
|
||||
uint32_t getInstWeight(Instruction &I, unsigned FirstLineno,
|
||||
BodySampleMap &BodySamples);
|
||||
uint32_t computeBlockWeight(BasicBlock *B, unsigned FirstLineno,
|
||||
BodySampleMap &BodySamples);
|
||||
void addTotalSamples(unsigned Num) { TotalSamples += Num; }
|
||||
void addHeadSamples(unsigned Num) { TotalHeadSamples += Num; }
|
||||
void addBodySamples(unsigned LineOffset, unsigned Num) {
|
||||
BodySamples[LineOffset] += Num;
|
||||
}
|
||||
void print(raw_ostream &OS);
|
||||
|
||||
protected:
|
||||
/// \brief Total number of samples collected inside this function.
|
||||
///
|
||||
/// Samples are cumulative, they include all the samples collected
|
||||
/// inside this function and all its inlined callees.
|
||||
unsigned TotalSamples;
|
||||
|
||||
// \brief Total number of samples collected at the head of the function.
|
||||
unsigned TotalHeadSamples;
|
||||
|
||||
/// \brief Map line offsets to collected samples.
|
||||
///
|
||||
/// Each entry in this map contains the number of samples
|
||||
/// collected at the corresponding line offset. All line locations
|
||||
/// are an offset from the start of the function.
|
||||
BodySampleMap BodySamples;
|
||||
|
||||
/// \brief Map basic blocks to their computed weights.
|
||||
///
|
||||
/// The weight of a basic block is defined to be the maximum
|
||||
/// of all the instruction weights in that block.
|
||||
BlockWeightMap BlockWeights;
|
||||
};
|
||||
|
||||
/// \brief Sample-based profile reader.
|
||||
///
|
||||
/// Each profile contains sample counts for all the functions
|
||||
@ -77,61 +126,26 @@ namespace {
|
||||
/// 2. The samples collected at each line in F. To provide some
|
||||
/// protection against source code shuffling, line numbers should
|
||||
/// be relative to the start of the function.
|
||||
class SampleProfile {
|
||||
class SampleModuleProfile {
|
||||
public:
|
||||
SampleProfile(StringRef F) : Profiles(0), Filename(F) {}
|
||||
SampleModuleProfile(StringRef F) : Profiles(0), Filename(F) {}
|
||||
|
||||
void dump();
|
||||
void loadText();
|
||||
void loadNative() { llvm_unreachable("not implemented"); }
|
||||
bool emitAnnotations(Function &F);
|
||||
void printFunctionProfile(raw_ostream &OS, StringRef FName);
|
||||
void dumpFunctionProfile(StringRef FName);
|
||||
SampleFunctionProfile &getProfile(const Function &F) {
|
||||
return Profiles[F.getName()];
|
||||
}
|
||||
|
||||
protected:
|
||||
typedef DenseMap<uint32_t, uint32_t> BodySampleMap;
|
||||
typedef DenseMap<BasicBlock *, uint32_t> BlockWeightMap;
|
||||
|
||||
/// \brief Representation of the runtime profile for a function.
|
||||
///
|
||||
/// This data structure contains the runtime profile for a given
|
||||
/// function. It contains the total number of samples collected
|
||||
/// in the function and a map of samples collected in every statement.
|
||||
struct FunctionProfile {
|
||||
/// \brief Total number of samples collected inside this function.
|
||||
///
|
||||
/// Samples are cumulative, they include all the samples collected
|
||||
/// inside this function and all its inlined callees.
|
||||
unsigned TotalSamples;
|
||||
|
||||
// \brief Total number of samples collected at the head of the function.
|
||||
unsigned TotalHeadSamples;
|
||||
|
||||
/// \brief Map line offsets to collected samples.
|
||||
///
|
||||
/// Each entry in this map contains the number of samples
|
||||
/// collected at the corresponding line offset. All line locations
|
||||
/// are an offset from the start of the function.
|
||||
BodySampleMap BodySamples;
|
||||
|
||||
/// \brief Map basic blocks to their computed weights.
|
||||
///
|
||||
/// The weight of a basic block is defined to be the maximum
|
||||
/// of all the instruction weights in that block.
|
||||
BlockWeightMap BlockWeights;
|
||||
};
|
||||
|
||||
uint32_t getInstWeight(Instruction &I, unsigned FirstLineno,
|
||||
BodySampleMap &BodySamples);
|
||||
uint32_t computeBlockWeight(BasicBlock *B, unsigned FirstLineno,
|
||||
BodySampleMap &BodySamples);
|
||||
|
||||
/// \brief Map every function to its associated profile.
|
||||
///
|
||||
/// The profile of every function executed at runtime is collected
|
||||
/// in the structure FunctionProfile. This maps function objects
|
||||
/// in the structure SampleFunctionProfile. This maps function objects
|
||||
/// to their corresponding profiles.
|
||||
StringMap<FunctionProfile> Profiles;
|
||||
StringMap<SampleFunctionProfile> Profiles;
|
||||
|
||||
/// \brief Path name to the file holding the profile data.
|
||||
///
|
||||
@ -228,41 +242,48 @@ public:
|
||||
|
||||
protected:
|
||||
/// \brief Profile reader object.
|
||||
OwningPtr<SampleProfile> Profiler;
|
||||
OwningPtr<SampleModuleProfile> Profiler;
|
||||
|
||||
/// \brief Name of the profile file to load.
|
||||
StringRef Filename;
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Print the function profile for \p FName on stream \p OS.
|
||||
/// \brief Print this function profile on stream \p OS.
|
||||
///
|
||||
/// \param OS Stream to emit the output to.
|
||||
/// \param FName Name of the function to print.
|
||||
void SampleProfile::printFunctionProfile(raw_ostream &OS, StringRef FName) {
|
||||
FunctionProfile FProfile = Profiles[FName];
|
||||
OS << "Function: " << FName << ", " << FProfile.TotalSamples << ", "
|
||||
<< FProfile.TotalHeadSamples << ", " << FProfile.BodySamples.size()
|
||||
void SampleFunctionProfile::print(raw_ostream &OS) {
|
||||
OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size()
|
||||
<< " sampled lines\n";
|
||||
for (BodySampleMap::const_iterator SI = FProfile.BodySamples.begin(),
|
||||
SE = FProfile.BodySamples.end();
|
||||
for (BodySampleMap::const_iterator SI = BodySamples.begin(),
|
||||
SE = BodySamples.end();
|
||||
SI != SE; ++SI)
|
||||
OS << "\tline offset: " << SI->first
|
||||
<< ", number of samples: " << SI->second << "\n";
|
||||
OS << "\n";
|
||||
}
|
||||
|
||||
/// \brief Print the function profile for \p FName on stream \p OS.
|
||||
///
|
||||
/// \param OS Stream to emit the output to.
|
||||
/// \param FName Name of the function to print.
|
||||
void SampleModuleProfile::printFunctionProfile(raw_ostream &OS,
|
||||
StringRef FName) {
|
||||
OS << "Function: " << FName << ":\n";
|
||||
Profiles[FName].print(OS);
|
||||
}
|
||||
|
||||
/// \brief Dump the function profile for \p FName.
|
||||
///
|
||||
/// \param FName Name of the function to print.
|
||||
void SampleProfile::dumpFunctionProfile(StringRef FName) {
|
||||
void SampleModuleProfile::dumpFunctionProfile(StringRef FName) {
|
||||
printFunctionProfile(dbgs(), FName);
|
||||
}
|
||||
|
||||
/// \brief Dump all the function profiles found.
|
||||
void SampleProfile::dump() {
|
||||
for (StringMap<FunctionProfile>::const_iterator I = Profiles.begin(),
|
||||
E = Profiles.end();
|
||||
void SampleModuleProfile::dump() {
|
||||
for (StringMap<SampleFunctionProfile>::const_iterator I = Profiles.begin(),
|
||||
E = Profiles.end();
|
||||
I != E; ++I)
|
||||
dumpFunctionProfile(I->getKey());
|
||||
}
|
||||
@ -297,7 +318,7 @@ void SampleProfile::dump() {
|
||||
/// for debugging purposes, but it should not be used to generate
|
||||
/// profiles for large programs, as the representation is extremely
|
||||
/// inefficient.
|
||||
void SampleProfile::loadText() {
|
||||
void SampleModuleProfile::loadText() {
|
||||
ExternalProfileTextLoader Loader(Filename);
|
||||
|
||||
// Read the symbol table.
|
||||
@ -308,13 +329,8 @@ void SampleProfile::loadText() {
|
||||
Line = Loader.readLine();
|
||||
if (Line.getAsInteger(10, NumSymbols))
|
||||
Loader.reportParseError("Expected a number, found " + Line);
|
||||
for (int I = 0; I < NumSymbols; I++) {
|
||||
StringRef FName = Loader.readLine();
|
||||
FunctionProfile &FProfile = Profiles[FName];
|
||||
FProfile.BodySamples.clear();
|
||||
FProfile.TotalSamples = 0;
|
||||
FProfile.TotalHeadSamples = 0;
|
||||
}
|
||||
for (int I = 0; I < NumSymbols; I++)
|
||||
Profiles[Loader.readLine()] = SampleFunctionProfile();
|
||||
|
||||
// Read the profile of each function. Since each function may be
|
||||
// mentioned more than once, and we are collecting flat profiles,
|
||||
@ -333,10 +349,9 @@ void SampleProfile::loadText() {
|
||||
Matches[2].getAsInteger(10, NumSamples);
|
||||
Matches[3].getAsInteger(10, NumHeadSamples);
|
||||
Matches[4].getAsInteger(10, NumSampledLines);
|
||||
FunctionProfile &FProfile = Profiles[FName];
|
||||
FProfile.TotalSamples += NumSamples;
|
||||
FProfile.TotalHeadSamples += NumHeadSamples;
|
||||
BodySampleMap &SampleMap = FProfile.BodySamples;
|
||||
SampleFunctionProfile &FProfile = Profiles[FName];
|
||||
FProfile.addTotalSamples(NumSamples);
|
||||
FProfile.addHeadSamples(NumHeadSamples);
|
||||
unsigned I;
|
||||
for (I = 0; I < NumSampledLines && !Loader.atEOF(); I++) {
|
||||
Line = Loader.readLine();
|
||||
@ -346,7 +361,7 @@ void SampleProfile::loadText() {
|
||||
unsigned LineOffset, NumSamples;
|
||||
Matches[1].getAsInteger(10, LineOffset);
|
||||
Matches[2].getAsInteger(10, NumSamples);
|
||||
SampleMap[LineOffset] += NumSamples;
|
||||
FProfile.addBodySamples(LineOffset, NumSamples);
|
||||
}
|
||||
|
||||
if (I < NumSampledLines)
|
||||
@ -354,6 +369,24 @@ void SampleProfile::loadText() {
|
||||
}
|
||||
}
|
||||
|
||||
char SampleProfileLoader::ID = 0;
|
||||
INITIALIZE_PASS(SampleProfileLoader, "sample-profile", "Sample Profile loader",
|
||||
false, false)
|
||||
|
||||
bool SampleProfileLoader::doInitialization(Module &M) {
|
||||
Profiler.reset(new SampleModuleProfile(Filename));
|
||||
Profiler->loadText();
|
||||
return true;
|
||||
}
|
||||
|
||||
FunctionPass *llvm::createSampleProfileLoaderPass() {
|
||||
return new SampleProfileLoader(SampleProfileFile);
|
||||
}
|
||||
|
||||
FunctionPass *llvm::createSampleProfileLoaderPass(StringRef Name) {
|
||||
return new SampleProfileLoader(Name);
|
||||
}
|
||||
|
||||
/// \brief Get the weight for an instruction.
|
||||
///
|
||||
/// The "weight" of an instruction \p Inst is the number of samples
|
||||
@ -367,8 +400,9 @@ void SampleProfile::loadText() {
|
||||
/// \param BodySamples Map of relative source line locations to samples.
|
||||
///
|
||||
/// \returns The profiled weight of I.
|
||||
uint32_t SampleProfile::getInstWeight(Instruction &Inst, unsigned FirstLineno,
|
||||
BodySampleMap &BodySamples) {
|
||||
uint32_t SampleFunctionProfile::getInstWeight(Instruction &Inst,
|
||||
unsigned FirstLineno,
|
||||
BodySampleMap &BodySamples) {
|
||||
unsigned LOffset = Inst.getDebugLoc().getLine() - FirstLineno + 1;
|
||||
return BodySamples.lookup(LOffset);
|
||||
}
|
||||
@ -385,13 +419,12 @@ uint32_t SampleProfile::getInstWeight(Instruction &Inst, unsigned FirstLineno,
|
||||
/// function.
|
||||
///
|
||||
/// \returns The computed weight of B.
|
||||
uint32_t SampleProfile::computeBlockWeight(BasicBlock *B, unsigned FirstLineno,
|
||||
BodySampleMap &BodySamples) {
|
||||
uint32_t SampleFunctionProfile::computeBlockWeight(BasicBlock *B,
|
||||
unsigned FirstLineno,
|
||||
BodySampleMap &BodySamples) {
|
||||
// If we've computed B's weight before, return it.
|
||||
Function *F = B->getParent();
|
||||
FunctionProfile &FProfile = Profiles[F->getName()];
|
||||
std::pair<BlockWeightMap::iterator, bool> Entry =
|
||||
FProfile.BlockWeights.insert(std::make_pair(B, 0));
|
||||
BlockWeights.insert(std::make_pair(B, 0));
|
||||
if (!Entry.second)
|
||||
return Entry.first->second;
|
||||
|
||||
@ -420,14 +453,13 @@ uint32_t SampleProfile::computeBlockWeight(BasicBlock *B, unsigned FirstLineno,
|
||||
/// metadata on B using the computed values.
|
||||
///
|
||||
/// \param F The function to query.
|
||||
bool SampleProfile::emitAnnotations(Function &F) {
|
||||
bool SampleFunctionProfile::emitAnnotations(Function &F) {
|
||||
bool Changed = false;
|
||||
FunctionProfile &FProfile = Profiles[F.getName()];
|
||||
unsigned FirstLineno = inst_begin(F)->getDebugLoc().getLine();
|
||||
MDBuilder MDB(F.getContext());
|
||||
|
||||
// Clear the block weights cache.
|
||||
FProfile.BlockWeights.clear();
|
||||
BlockWeights.clear();
|
||||
|
||||
// When we find a branch instruction: For each edge E out of the branch,
|
||||
// the weight of E is the weight of the target block.
|
||||
@ -443,8 +475,7 @@ bool SampleProfile::emitAnnotations(Function &F) {
|
||||
unsigned NSuccs = TI->getNumSuccessors();
|
||||
for (unsigned I = 0; I < NSuccs; ++I) {
|
||||
BasicBlock *Succ = TI->getSuccessor(I);
|
||||
uint32_t Weight =
|
||||
computeBlockWeight(Succ, FirstLineno, FProfile.BodySamples);
|
||||
uint32_t Weight = computeBlockWeight(Succ, FirstLineno, BodySamples);
|
||||
Weights.push_back(Weight);
|
||||
}
|
||||
|
||||
@ -456,24 +487,6 @@ bool SampleProfile::emitAnnotations(Function &F) {
|
||||
return Changed;
|
||||
}
|
||||
|
||||
char SampleProfileLoader::ID = 0;
|
||||
INITIALIZE_PASS(SampleProfileLoader, "sample-profile", "Sample Profile loader",
|
||||
false, false)
|
||||
|
||||
bool SampleProfileLoader::runOnFunction(Function &F) {
|
||||
return Profiler->emitAnnotations(F);
|
||||
}
|
||||
|
||||
bool SampleProfileLoader::doInitialization(Module &M) {
|
||||
Profiler.reset(new SampleProfile(Filename));
|
||||
Profiler->loadText();
|
||||
return true;
|
||||
}
|
||||
|
||||
FunctionPass *llvm::createSampleProfileLoaderPass() {
|
||||
return new SampleProfileLoader(SampleProfileFile);
|
||||
}
|
||||
|
||||
FunctionPass *llvm::createSampleProfileLoaderPass(StringRef Name) {
|
||||
return new SampleProfileLoader(Name);
|
||||
return Profiler->getProfile(F).emitAnnotations(F);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user