mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 04:33:05 +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);
|
cl::desc("Profile file loaded by -sample-profile"), cl::Hidden);
|
||||||
|
|
||||||
namespace {
|
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.
|
/// \brief Sample-based profile reader.
|
||||||
///
|
///
|
||||||
/// Each profile contains sample counts for all the functions
|
/// 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
|
/// 2. The samples collected at each line in F. To provide some
|
||||||
/// protection against source code shuffling, line numbers should
|
/// protection against source code shuffling, line numbers should
|
||||||
/// be relative to the start of the function.
|
/// be relative to the start of the function.
|
||||||
class SampleProfile {
|
class SampleModuleProfile {
|
||||||
public:
|
public:
|
||||||
SampleProfile(StringRef F) : Profiles(0), Filename(F) {}
|
SampleModuleProfile(StringRef F) : Profiles(0), Filename(F) {}
|
||||||
|
|
||||||
void dump();
|
void dump();
|
||||||
void loadText();
|
void loadText();
|
||||||
void loadNative() { llvm_unreachable("not implemented"); }
|
void loadNative() { llvm_unreachable("not implemented"); }
|
||||||
bool emitAnnotations(Function &F);
|
|
||||||
void printFunctionProfile(raw_ostream &OS, StringRef FName);
|
void printFunctionProfile(raw_ostream &OS, StringRef FName);
|
||||||
void dumpFunctionProfile(StringRef FName);
|
void dumpFunctionProfile(StringRef FName);
|
||||||
|
SampleFunctionProfile &getProfile(const Function &F) {
|
||||||
|
return Profiles[F.getName()];
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
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.
|
/// \brief Map every function to its associated profile.
|
||||||
///
|
///
|
||||||
/// The profile of every function executed at runtime is collected
|
/// 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.
|
/// to their corresponding profiles.
|
||||||
StringMap<FunctionProfile> Profiles;
|
StringMap<SampleFunctionProfile> Profiles;
|
||||||
|
|
||||||
/// \brief Path name to the file holding the profile data.
|
/// \brief Path name to the file holding the profile data.
|
||||||
///
|
///
|
||||||
@ -228,41 +242,48 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// \brief Profile reader object.
|
/// \brief Profile reader object.
|
||||||
OwningPtr<SampleProfile> Profiler;
|
OwningPtr<SampleModuleProfile> Profiler;
|
||||||
|
|
||||||
/// \brief Name of the profile file to load.
|
/// \brief Name of the profile file to load.
|
||||||
StringRef Filename;
|
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 OS Stream to emit the output to.
|
||||||
/// \param FName Name of the function to print.
|
void SampleFunctionProfile::print(raw_ostream &OS) {
|
||||||
void SampleProfile::printFunctionProfile(raw_ostream &OS, StringRef FName) {
|
OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size()
|
||||||
FunctionProfile FProfile = Profiles[FName];
|
|
||||||
OS << "Function: " << FName << ", " << FProfile.TotalSamples << ", "
|
|
||||||
<< FProfile.TotalHeadSamples << ", " << FProfile.BodySamples.size()
|
|
||||||
<< " sampled lines\n";
|
<< " sampled lines\n";
|
||||||
for (BodySampleMap::const_iterator SI = FProfile.BodySamples.begin(),
|
for (BodySampleMap::const_iterator SI = BodySamples.begin(),
|
||||||
SE = FProfile.BodySamples.end();
|
SE = BodySamples.end();
|
||||||
SI != SE; ++SI)
|
SI != SE; ++SI)
|
||||||
OS << "\tline offset: " << SI->first
|
OS << "\tline offset: " << SI->first
|
||||||
<< ", number of samples: " << SI->second << "\n";
|
<< ", number of samples: " << SI->second << "\n";
|
||||||
OS << "\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.
|
/// \brief Dump the function profile for \p FName.
|
||||||
///
|
///
|
||||||
/// \param FName Name of the function to print.
|
/// \param FName Name of the function to print.
|
||||||
void SampleProfile::dumpFunctionProfile(StringRef FName) {
|
void SampleModuleProfile::dumpFunctionProfile(StringRef FName) {
|
||||||
printFunctionProfile(dbgs(), FName);
|
printFunctionProfile(dbgs(), FName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Dump all the function profiles found.
|
/// \brief Dump all the function profiles found.
|
||||||
void SampleProfile::dump() {
|
void SampleModuleProfile::dump() {
|
||||||
for (StringMap<FunctionProfile>::const_iterator I = Profiles.begin(),
|
for (StringMap<SampleFunctionProfile>::const_iterator I = Profiles.begin(),
|
||||||
E = Profiles.end();
|
E = Profiles.end();
|
||||||
I != E; ++I)
|
I != E; ++I)
|
||||||
dumpFunctionProfile(I->getKey());
|
dumpFunctionProfile(I->getKey());
|
||||||
}
|
}
|
||||||
@ -297,7 +318,7 @@ void SampleProfile::dump() {
|
|||||||
/// for debugging purposes, but it should not be used to generate
|
/// for debugging purposes, but it should not be used to generate
|
||||||
/// profiles for large programs, as the representation is extremely
|
/// profiles for large programs, as the representation is extremely
|
||||||
/// inefficient.
|
/// inefficient.
|
||||||
void SampleProfile::loadText() {
|
void SampleModuleProfile::loadText() {
|
||||||
ExternalProfileTextLoader Loader(Filename);
|
ExternalProfileTextLoader Loader(Filename);
|
||||||
|
|
||||||
// Read the symbol table.
|
// Read the symbol table.
|
||||||
@ -308,13 +329,8 @@ void SampleProfile::loadText() {
|
|||||||
Line = Loader.readLine();
|
Line = Loader.readLine();
|
||||||
if (Line.getAsInteger(10, NumSymbols))
|
if (Line.getAsInteger(10, NumSymbols))
|
||||||
Loader.reportParseError("Expected a number, found " + Line);
|
Loader.reportParseError("Expected a number, found " + Line);
|
||||||
for (int I = 0; I < NumSymbols; I++) {
|
for (int I = 0; I < NumSymbols; I++)
|
||||||
StringRef FName = Loader.readLine();
|
Profiles[Loader.readLine()] = SampleFunctionProfile();
|
||||||
FunctionProfile &FProfile = Profiles[FName];
|
|
||||||
FProfile.BodySamples.clear();
|
|
||||||
FProfile.TotalSamples = 0;
|
|
||||||
FProfile.TotalHeadSamples = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the profile of each function. Since each function may be
|
// Read the profile of each function. Since each function may be
|
||||||
// mentioned more than once, and we are collecting flat profiles,
|
// mentioned more than once, and we are collecting flat profiles,
|
||||||
@ -333,10 +349,9 @@ void SampleProfile::loadText() {
|
|||||||
Matches[2].getAsInteger(10, NumSamples);
|
Matches[2].getAsInteger(10, NumSamples);
|
||||||
Matches[3].getAsInteger(10, NumHeadSamples);
|
Matches[3].getAsInteger(10, NumHeadSamples);
|
||||||
Matches[4].getAsInteger(10, NumSampledLines);
|
Matches[4].getAsInteger(10, NumSampledLines);
|
||||||
FunctionProfile &FProfile = Profiles[FName];
|
SampleFunctionProfile &FProfile = Profiles[FName];
|
||||||
FProfile.TotalSamples += NumSamples;
|
FProfile.addTotalSamples(NumSamples);
|
||||||
FProfile.TotalHeadSamples += NumHeadSamples;
|
FProfile.addHeadSamples(NumHeadSamples);
|
||||||
BodySampleMap &SampleMap = FProfile.BodySamples;
|
|
||||||
unsigned I;
|
unsigned I;
|
||||||
for (I = 0; I < NumSampledLines && !Loader.atEOF(); I++) {
|
for (I = 0; I < NumSampledLines && !Loader.atEOF(); I++) {
|
||||||
Line = Loader.readLine();
|
Line = Loader.readLine();
|
||||||
@ -346,7 +361,7 @@ void SampleProfile::loadText() {
|
|||||||
unsigned LineOffset, NumSamples;
|
unsigned LineOffset, NumSamples;
|
||||||
Matches[1].getAsInteger(10, LineOffset);
|
Matches[1].getAsInteger(10, LineOffset);
|
||||||
Matches[2].getAsInteger(10, NumSamples);
|
Matches[2].getAsInteger(10, NumSamples);
|
||||||
SampleMap[LineOffset] += NumSamples;
|
FProfile.addBodySamples(LineOffset, NumSamples);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (I < NumSampledLines)
|
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.
|
/// \brief Get the weight for an instruction.
|
||||||
///
|
///
|
||||||
/// The "weight" of an instruction \p Inst is the number of samples
|
/// 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.
|
/// \param BodySamples Map of relative source line locations to samples.
|
||||||
///
|
///
|
||||||
/// \returns The profiled weight of I.
|
/// \returns The profiled weight of I.
|
||||||
uint32_t SampleProfile::getInstWeight(Instruction &Inst, unsigned FirstLineno,
|
uint32_t SampleFunctionProfile::getInstWeight(Instruction &Inst,
|
||||||
BodySampleMap &BodySamples) {
|
unsigned FirstLineno,
|
||||||
|
BodySampleMap &BodySamples) {
|
||||||
unsigned LOffset = Inst.getDebugLoc().getLine() - FirstLineno + 1;
|
unsigned LOffset = Inst.getDebugLoc().getLine() - FirstLineno + 1;
|
||||||
return BodySamples.lookup(LOffset);
|
return BodySamples.lookup(LOffset);
|
||||||
}
|
}
|
||||||
@ -385,13 +419,12 @@ uint32_t SampleProfile::getInstWeight(Instruction &Inst, unsigned FirstLineno,
|
|||||||
/// function.
|
/// function.
|
||||||
///
|
///
|
||||||
/// \returns The computed weight of B.
|
/// \returns The computed weight of B.
|
||||||
uint32_t SampleProfile::computeBlockWeight(BasicBlock *B, unsigned FirstLineno,
|
uint32_t SampleFunctionProfile::computeBlockWeight(BasicBlock *B,
|
||||||
BodySampleMap &BodySamples) {
|
unsigned FirstLineno,
|
||||||
|
BodySampleMap &BodySamples) {
|
||||||
// If we've computed B's weight before, return it.
|
// 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 =
|
std::pair<BlockWeightMap::iterator, bool> Entry =
|
||||||
FProfile.BlockWeights.insert(std::make_pair(B, 0));
|
BlockWeights.insert(std::make_pair(B, 0));
|
||||||
if (!Entry.second)
|
if (!Entry.second)
|
||||||
return Entry.first->second;
|
return Entry.first->second;
|
||||||
|
|
||||||
@ -420,14 +453,13 @@ uint32_t SampleProfile::computeBlockWeight(BasicBlock *B, unsigned FirstLineno,
|
|||||||
/// metadata on B using the computed values.
|
/// metadata on B using the computed values.
|
||||||
///
|
///
|
||||||
/// \param F The function to query.
|
/// \param F The function to query.
|
||||||
bool SampleProfile::emitAnnotations(Function &F) {
|
bool SampleFunctionProfile::emitAnnotations(Function &F) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
FunctionProfile &FProfile = Profiles[F.getName()];
|
|
||||||
unsigned FirstLineno = inst_begin(F)->getDebugLoc().getLine();
|
unsigned FirstLineno = inst_begin(F)->getDebugLoc().getLine();
|
||||||
MDBuilder MDB(F.getContext());
|
MDBuilder MDB(F.getContext());
|
||||||
|
|
||||||
// Clear the block weights cache.
|
// Clear the block weights cache.
|
||||||
FProfile.BlockWeights.clear();
|
BlockWeights.clear();
|
||||||
|
|
||||||
// When we find a branch instruction: For each edge E out of the branch,
|
// 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.
|
// the weight of E is the weight of the target block.
|
||||||
@ -443,8 +475,7 @@ bool SampleProfile::emitAnnotations(Function &F) {
|
|||||||
unsigned NSuccs = TI->getNumSuccessors();
|
unsigned NSuccs = TI->getNumSuccessors();
|
||||||
for (unsigned I = 0; I < NSuccs; ++I) {
|
for (unsigned I = 0; I < NSuccs; ++I) {
|
||||||
BasicBlock *Succ = TI->getSuccessor(I);
|
BasicBlock *Succ = TI->getSuccessor(I);
|
||||||
uint32_t Weight =
|
uint32_t Weight = computeBlockWeight(Succ, FirstLineno, BodySamples);
|
||||||
computeBlockWeight(Succ, FirstLineno, FProfile.BodySamples);
|
|
||||||
Weights.push_back(Weight);
|
Weights.push_back(Weight);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -456,24 +487,6 @@ bool SampleProfile::emitAnnotations(Function &F) {
|
|||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
char SampleProfileLoader::ID = 0;
|
|
||||||
INITIALIZE_PASS(SampleProfileLoader, "sample-profile", "Sample Profile loader",
|
|
||||||
false, false)
|
|
||||||
|
|
||||||
bool SampleProfileLoader::runOnFunction(Function &F) {
|
bool SampleProfileLoader::runOnFunction(Function &F) {
|
||||||
return Profiler->emitAnnotations(F);
|
return Profiler->getProfile(F).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);
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user