forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			194 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			194 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| //=-- SampleProf.cpp - Sample profiling format support --------------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file contains common definitions used in the reading and writing of
 | |
| // sample profile data.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "llvm/ProfileData/SampleProf.h"
 | |
| #include "llvm/Config/llvm-config.h"
 | |
| #include "llvm/IR/DebugInfoMetadata.h"
 | |
| #include "llvm/Support/Compiler.h"
 | |
| #include "llvm/Support/Debug.h"
 | |
| #include "llvm/Support/ErrorHandling.h"
 | |
| #include "llvm/Support/ManagedStatic.h"
 | |
| #include "llvm/Support/raw_ostream.h"
 | |
| #include <string>
 | |
| #include <system_error>
 | |
| 
 | |
| using namespace llvm;
 | |
| using namespace sampleprof;
 | |
| 
 | |
| namespace llvm {
 | |
| namespace sampleprof {
 | |
| SampleProfileFormat FunctionSamples::Format;
 | |
| DenseMap<uint64_t, StringRef> FunctionSamples::GUIDToFuncNameMap;
 | |
| Module *FunctionSamples::CurrentModule;
 | |
| } // namespace sampleprof
 | |
| } // namespace llvm
 | |
| 
 | |
| namespace {
 | |
| 
 | |
| // FIXME: This class is only here to support the transition to llvm::Error. It
 | |
| // will be removed once this transition is complete. Clients should prefer to
 | |
| // deal with the Error value directly, rather than converting to error_code.
 | |
| class SampleProfErrorCategoryType : public std::error_category {
 | |
|   const char *name() const noexcept override { return "llvm.sampleprof"; }
 | |
| 
 | |
|   std::string message(int IE) const override {
 | |
|     sampleprof_error E = static_cast<sampleprof_error>(IE);
 | |
|     switch (E) {
 | |
|     case sampleprof_error::success:
 | |
|       return "Success";
 | |
|     case sampleprof_error::bad_magic:
 | |
|       return "Invalid sample profile data (bad magic)";
 | |
|     case sampleprof_error::unsupported_version:
 | |
|       return "Unsupported sample profile format version";
 | |
|     case sampleprof_error::too_large:
 | |
|       return "Too much profile data";
 | |
|     case sampleprof_error::truncated:
 | |
|       return "Truncated profile data";
 | |
|     case sampleprof_error::malformed:
 | |
|       return "Malformed sample profile data";
 | |
|     case sampleprof_error::unrecognized_format:
 | |
|       return "Unrecognized sample profile encoding format";
 | |
|     case sampleprof_error::unsupported_writing_format:
 | |
|       return "Profile encoding format unsupported for writing operations";
 | |
|     case sampleprof_error::truncated_name_table:
 | |
|       return "Truncated function name table";
 | |
|     case sampleprof_error::not_implemented:
 | |
|       return "Unimplemented feature";
 | |
|     case sampleprof_error::counter_overflow:
 | |
|       return "Counter overflow";
 | |
|     case sampleprof_error::ostream_seek_unsupported:
 | |
|       return "Ostream does not support seek";
 | |
|     }
 | |
|     llvm_unreachable("A value of sampleprof_error has no message.");
 | |
|   }
 | |
| };
 | |
| 
 | |
| } // end anonymous namespace
 | |
| 
 | |
| static ManagedStatic<SampleProfErrorCategoryType> ErrorCategory;
 | |
| 
 | |
| const std::error_category &llvm::sampleprof_category() {
 | |
|   return *ErrorCategory;
 | |
| }
 | |
| 
 | |
| void LineLocation::print(raw_ostream &OS) const {
 | |
|   OS << LineOffset;
 | |
|   if (Discriminator > 0)
 | |
|     OS << "." << Discriminator;
 | |
| }
 | |
| 
 | |
| raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
 | |
|                                           const LineLocation &Loc) {
 | |
|   Loc.print(OS);
 | |
|   return OS;
 | |
| }
 | |
| 
 | |
| #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 | |
| LLVM_DUMP_METHOD void LineLocation::dump() const { print(dbgs()); }
 | |
| #endif
 | |
| 
 | |
| /// Print the sample record to the stream \p OS indented by \p Indent.
 | |
| void SampleRecord::print(raw_ostream &OS, unsigned Indent) const {
 | |
|   OS << NumSamples;
 | |
|   if (hasCalls()) {
 | |
|     OS << ", calls:";
 | |
|     for (const auto &I : getCallTargets())
 | |
|       OS << " " << I.first() << ":" << I.second;
 | |
|   }
 | |
|   OS << "\n";
 | |
| }
 | |
| 
 | |
| #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 | |
| LLVM_DUMP_METHOD void SampleRecord::dump() const { print(dbgs(), 0); }
 | |
| #endif
 | |
| 
 | |
| raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
 | |
|                                           const SampleRecord &Sample) {
 | |
|   Sample.print(OS, 0);
 | |
|   return OS;
 | |
| }
 | |
| 
 | |
| /// Print the samples collected for a function on stream \p OS.
 | |
| void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const {
 | |
|   OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size()
 | |
|      << " sampled lines\n";
 | |
| 
 | |
|   OS.indent(Indent);
 | |
|   if (!BodySamples.empty()) {
 | |
|     OS << "Samples collected in the function's body {\n";
 | |
|     SampleSorter<LineLocation, SampleRecord> SortedBodySamples(BodySamples);
 | |
|     for (const auto &SI : SortedBodySamples.get()) {
 | |
|       OS.indent(Indent + 2);
 | |
|       OS << SI->first << ": " << SI->second;
 | |
|     }
 | |
|     OS.indent(Indent);
 | |
|     OS << "}\n";
 | |
|   } else {
 | |
|     OS << "No samples collected in the function's body\n";
 | |
|   }
 | |
| 
 | |
|   OS.indent(Indent);
 | |
|   if (!CallsiteSamples.empty()) {
 | |
|     OS << "Samples collected in inlined callsites {\n";
 | |
|     SampleSorter<LineLocation, FunctionSamplesMap> SortedCallsiteSamples(
 | |
|         CallsiteSamples);
 | |
|     for (const auto &CS : SortedCallsiteSamples.get()) {
 | |
|       for (const auto &FS : CS->second) {
 | |
|         OS.indent(Indent + 2);
 | |
|         OS << CS->first << ": inlined callee: " << FS.second.getName() << ": ";
 | |
|         FS.second.print(OS, Indent + 4);
 | |
|       }
 | |
|     }
 | |
|     OS << "}\n";
 | |
|   } else {
 | |
|     OS << "No inlined callsites in this function\n";
 | |
|   }
 | |
| }
 | |
| 
 | |
| raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
 | |
|                                           const FunctionSamples &FS) {
 | |
|   FS.print(OS);
 | |
|   return OS;
 | |
| }
 | |
| 
 | |
| unsigned FunctionSamples::getOffset(const DILocation *DIL) {
 | |
|   return (DIL->getLine() - DIL->getScope()->getSubprogram()->getLine()) &
 | |
|       0xffff;
 | |
| }
 | |
| 
 | |
| const FunctionSamples *
 | |
| FunctionSamples::findFunctionSamples(const DILocation *DIL) const {
 | |
|   assert(DIL);
 | |
|   SmallVector<std::pair<LineLocation, StringRef>, 10> S;
 | |
| 
 | |
|   const DILocation *PrevDIL = DIL;
 | |
|   for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
 | |
|     S.push_back(std::make_pair(
 | |
|         LineLocation(getOffset(DIL), DIL->getBaseDiscriminator()),
 | |
|         PrevDIL->getScope()->getSubprogram()->getLinkageName()));
 | |
|     PrevDIL = DIL;
 | |
|   }
 | |
|   if (S.size() == 0)
 | |
|     return this;
 | |
|   const FunctionSamples *FS = this;
 | |
|   for (int i = S.size() - 1; i >= 0 && FS != nullptr; i--) {
 | |
|     FS = FS->findFunctionSamplesAt(S[i].first, S[i].second);
 | |
|   }
 | |
|   return FS;
 | |
| }
 | |
| 
 | |
| #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
 | |
| LLVM_DUMP_METHOD void FunctionSamples::dump() const { print(dbgs(), 0); }
 | |
| #endif
 |