Home | History | Annotate | Download | only in ProfileData
      1 //=-- SampleProf.cpp - Sample profiling format support --------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains common definitions used in the reading and writing of
     11 // sample profile data.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "llvm/ProfileData/SampleProf.h"
     16 #include "llvm/Config/llvm-config.h"
     17 #include "llvm/IR/DebugInfoMetadata.h"
     18 #include "llvm/Support/Compiler.h"
     19 #include "llvm/Support/Debug.h"
     20 #include "llvm/Support/ErrorHandling.h"
     21 #include "llvm/Support/ManagedStatic.h"
     22 #include "llvm/Support/raw_ostream.h"
     23 #include <string>
     24 #include <system_error>
     25 
     26 using namespace llvm;
     27 using namespace sampleprof;
     28 
     29 namespace {
     30 
     31 // FIXME: This class is only here to support the transition to llvm::Error. It
     32 // will be removed once this transition is complete. Clients should prefer to
     33 // deal with the Error value directly, rather than converting to error_code.
     34 class SampleProfErrorCategoryType : public std::error_category {
     35   const char *name() const noexcept override { return "llvm.sampleprof"; }
     36 
     37   std::string message(int IE) const override {
     38     sampleprof_error E = static_cast<sampleprof_error>(IE);
     39     switch (E) {
     40     case sampleprof_error::success:
     41       return "Success";
     42     case sampleprof_error::bad_magic:
     43       return "Invalid sample profile data (bad magic)";
     44     case sampleprof_error::unsupported_version:
     45       return "Unsupported sample profile format version";
     46     case sampleprof_error::too_large:
     47       return "Too much profile data";
     48     case sampleprof_error::truncated:
     49       return "Truncated profile data";
     50     case sampleprof_error::malformed:
     51       return "Malformed sample profile data";
     52     case sampleprof_error::unrecognized_format:
     53       return "Unrecognized sample profile encoding format";
     54     case sampleprof_error::unsupported_writing_format:
     55       return "Profile encoding format unsupported for writing operations";
     56     case sampleprof_error::truncated_name_table:
     57       return "Truncated function name table";
     58     case sampleprof_error::not_implemented:
     59       return "Unimplemented feature";
     60     case sampleprof_error::counter_overflow:
     61       return "Counter overflow";
     62     }
     63     llvm_unreachable("A value of sampleprof_error has no message.");
     64   }
     65 };
     66 
     67 } // end anonymous namespace
     68 
     69 static ManagedStatic<SampleProfErrorCategoryType> ErrorCategory;
     70 
     71 const std::error_category &llvm::sampleprof_category() {
     72   return *ErrorCategory;
     73 }
     74 
     75 void LineLocation::print(raw_ostream &OS) const {
     76   OS << LineOffset;
     77   if (Discriminator > 0)
     78     OS << "." << Discriminator;
     79 }
     80 
     81 raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
     82                                           const LineLocation &Loc) {
     83   Loc.print(OS);
     84   return OS;
     85 }
     86 
     87 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
     88 LLVM_DUMP_METHOD void LineLocation::dump() const { print(dbgs()); }
     89 #endif
     90 
     91 /// Print the sample record to the stream \p OS indented by \p Indent.
     92 void SampleRecord::print(raw_ostream &OS, unsigned Indent) const {
     93   OS << NumSamples;
     94   if (hasCalls()) {
     95     OS << ", calls:";
     96     for (const auto &I : getCallTargets())
     97       OS << " " << I.first() << ":" << I.second;
     98   }
     99   OS << "\n";
    100 }
    101 
    102 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    103 LLVM_DUMP_METHOD void SampleRecord::dump() const { print(dbgs(), 0); }
    104 #endif
    105 
    106 raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
    107                                           const SampleRecord &Sample) {
    108   Sample.print(OS, 0);
    109   return OS;
    110 }
    111 
    112 /// Print the samples collected for a function on stream \p OS.
    113 void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const {
    114   OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size()
    115      << " sampled lines\n";
    116 
    117   OS.indent(Indent);
    118   if (!BodySamples.empty()) {
    119     OS << "Samples collected in the function's body {\n";
    120     SampleSorter<LineLocation, SampleRecord> SortedBodySamples(BodySamples);
    121     for (const auto &SI : SortedBodySamples.get()) {
    122       OS.indent(Indent + 2);
    123       OS << SI->first << ": " << SI->second;
    124     }
    125     OS.indent(Indent);
    126     OS << "}\n";
    127   } else {
    128     OS << "No samples collected in the function's body\n";
    129   }
    130 
    131   OS.indent(Indent);
    132   if (!CallsiteSamples.empty()) {
    133     OS << "Samples collected in inlined callsites {\n";
    134     SampleSorter<LineLocation, FunctionSamplesMap> SortedCallsiteSamples(
    135         CallsiteSamples);
    136     for (const auto &CS : SortedCallsiteSamples.get()) {
    137       for (const auto &FS : CS->second) {
    138         OS.indent(Indent + 2);
    139         OS << CS->first << ": inlined callee: " << FS.second.getName() << ": ";
    140         FS.second.print(OS, Indent + 4);
    141       }
    142     }
    143     OS << "}\n";
    144   } else {
    145     OS << "No inlined callsites in this function\n";
    146   }
    147 }
    148 
    149 raw_ostream &llvm::sampleprof::operator<<(raw_ostream &OS,
    150                                           const FunctionSamples &FS) {
    151   FS.print(OS);
    152   return OS;
    153 }
    154 
    155 unsigned FunctionSamples::getOffset(const DILocation *DIL) {
    156   return (DIL->getLine() - DIL->getScope()->getSubprogram()->getLine()) &
    157       0xffff;
    158 }
    159 
    160 const FunctionSamples *
    161 FunctionSamples::findFunctionSamples(const DILocation *DIL) const {
    162   assert(DIL);
    163   SmallVector<std::pair<LineLocation, StringRef>, 10> S;
    164 
    165   const DILocation *PrevDIL = DIL;
    166   for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
    167     S.push_back(std::make_pair(
    168         LineLocation(getOffset(DIL), DIL->getBaseDiscriminator()),
    169         PrevDIL->getScope()->getSubprogram()->getLinkageName()));
    170     PrevDIL = DIL;
    171   }
    172   if (S.size() == 0)
    173     return this;
    174   const FunctionSamples *FS = this;
    175   for (int i = S.size() - 1; i >= 0 && FS != nullptr; i--) {
    176     FS = FS->findFunctionSamplesAt(S[i].first, S[i].second);
    177   }
    178   return FS;
    179 }
    180 
    181 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
    182 LLVM_DUMP_METHOD void FunctionSamples::dump() const { print(dbgs(), 0); }
    183 #endif
    184