Home | History | Annotate | Download | only in ProfileData
      1 //=-- InstrProf.cpp - Instrumented 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 support for clang's instrumentation based PGO and
     11 // coverage.
     12 //
     13 //===----------------------------------------------------------------------===//
     14 
     15 #include "llvm/IR/Constants.h"
     16 #include "llvm/IR/Function.h"
     17 #include "llvm/IR/Module.h"
     18 #include "llvm/IR/GlobalVariable.h"
     19 #include "llvm/ProfileData/InstrProf.h"
     20 #include "llvm/Support/ErrorHandling.h"
     21 #include "llvm/Support/ManagedStatic.h"
     22 
     23 using namespace llvm;
     24 
     25 namespace {
     26 class InstrProfErrorCategoryType : public std::error_category {
     27   const char *name() const LLVM_NOEXCEPT override { return "llvm.instrprof"; }
     28   std::string message(int IE) const override {
     29     instrprof_error E = static_cast<instrprof_error>(IE);
     30     switch (E) {
     31     case instrprof_error::success:
     32       return "Success";
     33     case instrprof_error::eof:
     34       return "End of File";
     35     case instrprof_error::unrecognized_format:
     36       return "Unrecognized instrumentation profile encoding format";
     37     case instrprof_error::bad_magic:
     38       return "Invalid instrumentation profile data (bad magic)";
     39     case instrprof_error::bad_header:
     40       return "Invalid instrumentation profile data (file header is corrupt)";
     41     case instrprof_error::unsupported_version:
     42       return "Unsupported instrumentation profile format version";
     43     case instrprof_error::unsupported_hash_type:
     44       return "Unsupported instrumentation profile hash type";
     45     case instrprof_error::too_large:
     46       return "Too much profile data";
     47     case instrprof_error::truncated:
     48       return "Truncated profile data";
     49     case instrprof_error::malformed:
     50       return "Malformed instrumentation profile data";
     51     case instrprof_error::unknown_function:
     52       return "No profile data available for function";
     53     case instrprof_error::hash_mismatch:
     54       return "Function control flow change detected (hash mismatch)";
     55     case instrprof_error::count_mismatch:
     56       return "Function basic block count change detected (counter mismatch)";
     57     case instrprof_error::counter_overflow:
     58       return "Counter overflow";
     59     case instrprof_error::value_site_count_mismatch:
     60       return "Function value site count change detected (counter mismatch)";
     61     }
     62     llvm_unreachable("A value of instrprof_error has no message.");
     63   }
     64 };
     65 }
     66 
     67 static ManagedStatic<InstrProfErrorCategoryType> ErrorCategory;
     68 
     69 const std::error_category &llvm::instrprof_category() {
     70   return *ErrorCategory;
     71 }
     72 
     73 namespace llvm {
     74 
     75 std::string getPGOFuncName(StringRef RawFuncName,
     76                            GlobalValue::LinkageTypes Linkage,
     77                            StringRef FileName,
     78                            uint64_t Version LLVM_ATTRIBUTE_UNUSED) {
     79 
     80   // Function names may be prefixed with a binary '1' to indicate
     81   // that the backend should not modify the symbols due to any platform
     82   // naming convention. Do not include that '1' in the PGO profile name.
     83   if (RawFuncName[0] == '\1')
     84     RawFuncName = RawFuncName.substr(1);
     85 
     86   std::string FuncName = RawFuncName;
     87   if (llvm::GlobalValue::isLocalLinkage(Linkage)) {
     88     // For local symbols, prepend the main file name to distinguish them.
     89     // Do not include the full path in the file name since there's no guarantee
     90     // that it will stay the same, e.g., if the files are checked out from
     91     // version control in different locations.
     92     if (FileName.empty())
     93       FuncName = FuncName.insert(0, "<unknown>:");
     94     else
     95       FuncName = FuncName.insert(0, FileName.str() + ":");
     96   }
     97   return FuncName;
     98 }
     99 
    100 std::string getPGOFuncName(const Function &F, uint64_t Version) {
    101   return getPGOFuncName(F.getName(), F.getLinkage(), F.getParent()->getName(),
    102                         Version);
    103 }
    104 
    105 StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName, StringRef FileName) {
    106   if (FileName.empty())
    107     return PGOFuncName;
    108   // Drop the file name including ':'. See also getPGOFuncName.
    109   if (PGOFuncName.startswith(FileName))
    110     PGOFuncName = PGOFuncName.drop_front(FileName.size() + 1);
    111   return PGOFuncName;
    112 }
    113 
    114 // \p FuncName is the string used as profile lookup key for the function. A
    115 // symbol is created to hold the name. Return the legalized symbol name.
    116 static std::string getPGOFuncNameVarName(StringRef FuncName,
    117                                          GlobalValue::LinkageTypes Linkage) {
    118   std::string VarName = getInstrProfNameVarPrefix();
    119   VarName += FuncName;
    120 
    121   if (!GlobalValue::isLocalLinkage(Linkage))
    122     return VarName;
    123 
    124   // Now fix up illegal chars in local VarName that may upset the assembler.
    125   const char *InvalidChars = "-:<>\"'";
    126   size_t found = VarName.find_first_of(InvalidChars);
    127   while (found != std::string::npos) {
    128     VarName[found] = '_';
    129     found = VarName.find_first_of(InvalidChars, found + 1);
    130   }
    131   return VarName;
    132 }
    133 
    134 GlobalVariable *createPGOFuncNameVar(Module &M,
    135                                      GlobalValue::LinkageTypes Linkage,
    136                                      StringRef FuncName) {
    137 
    138   // We generally want to match the function's linkage, but available_externally
    139   // and extern_weak both have the wrong semantics, and anything that doesn't
    140   // need to link across compilation units doesn't need to be visible at all.
    141   if (Linkage == GlobalValue::ExternalWeakLinkage)
    142     Linkage = GlobalValue::LinkOnceAnyLinkage;
    143   else if (Linkage == GlobalValue::AvailableExternallyLinkage)
    144     Linkage = GlobalValue::LinkOnceODRLinkage;
    145   else if (Linkage == GlobalValue::InternalLinkage ||
    146            Linkage == GlobalValue::ExternalLinkage)
    147     Linkage = GlobalValue::PrivateLinkage;
    148 
    149   auto *Value = ConstantDataArray::getString(M.getContext(), FuncName, false);
    150   auto FuncNameVar =
    151       new GlobalVariable(M, Value->getType(), true, Linkage, Value,
    152                          getPGOFuncNameVarName(FuncName, Linkage));
    153 
    154   // Hide the symbol so that we correctly get a copy for each executable.
    155   if (!GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
    156     FuncNameVar->setVisibility(GlobalValue::HiddenVisibility);
    157 
    158   return FuncNameVar;
    159 }
    160 
    161 GlobalVariable *createPGOFuncNameVar(Function &F, StringRef FuncName) {
    162   return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), FuncName);
    163 }
    164 
    165 instrprof_error
    166 InstrProfValueSiteRecord::mergeValueData(InstrProfValueSiteRecord &Input,
    167                                          uint64_t Weight) {
    168   this->sortByTargetValues();
    169   Input.sortByTargetValues();
    170   auto I = ValueData.begin();
    171   auto IE = ValueData.end();
    172   instrprof_error Result = instrprof_error::success;
    173   for (auto J = Input.ValueData.begin(), JE = Input.ValueData.end(); J != JE;
    174        ++J) {
    175     while (I != IE && I->Value < J->Value)
    176       ++I;
    177     if (I != IE && I->Value == J->Value) {
    178       uint64_t JCount = J->Count;
    179       bool Overflowed;
    180       if (Weight > 1) {
    181         JCount = SaturatingMultiply(JCount, Weight, &Overflowed);
    182         if (Overflowed)
    183           Result = instrprof_error::counter_overflow;
    184       }
    185       I->Count = SaturatingAdd(I->Count, JCount, &Overflowed);
    186       if (Overflowed)
    187         Result = instrprof_error::counter_overflow;
    188       ++I;
    189       continue;
    190     }
    191     ValueData.insert(I, *J);
    192   }
    193   return Result;
    194 }
    195 
    196 // Merge Value Profile data from Src record to this record for ValueKind.
    197 // Scale merged value counts by \p Weight.
    198 instrprof_error InstrProfRecord::mergeValueProfData(uint32_t ValueKind,
    199                                                     InstrProfRecord &Src,
    200                                                     uint64_t Weight) {
    201   uint32_t ThisNumValueSites = getNumValueSites(ValueKind);
    202   uint32_t OtherNumValueSites = Src.getNumValueSites(ValueKind);
    203   if (ThisNumValueSites != OtherNumValueSites)
    204     return instrprof_error::value_site_count_mismatch;
    205   std::vector<InstrProfValueSiteRecord> &ThisSiteRecords =
    206       getValueSitesForKind(ValueKind);
    207   std::vector<InstrProfValueSiteRecord> &OtherSiteRecords =
    208       Src.getValueSitesForKind(ValueKind);
    209   instrprof_error Result = instrprof_error::success;
    210   for (uint32_t I = 0; I < ThisNumValueSites; I++)
    211     MergeResult(Result,
    212                 ThisSiteRecords[I].mergeValueData(OtherSiteRecords[I], Weight));
    213   return Result;
    214 }
    215 
    216 instrprof_error InstrProfRecord::merge(InstrProfRecord &Other,
    217                                        uint64_t Weight) {
    218   // If the number of counters doesn't match we either have bad data
    219   // or a hash collision.
    220   if (Counts.size() != Other.Counts.size())
    221     return instrprof_error::count_mismatch;
    222 
    223   instrprof_error Result = instrprof_error::success;
    224 
    225   for (size_t I = 0, E = Other.Counts.size(); I < E; ++I) {
    226     bool Overflowed;
    227     uint64_t OtherCount = Other.Counts[I];
    228     if (Weight > 1) {
    229       OtherCount = SaturatingMultiply(OtherCount, Weight, &Overflowed);
    230       if (Overflowed)
    231         Result = instrprof_error::counter_overflow;
    232     }
    233     Counts[I] = SaturatingAdd(Counts[I], OtherCount, &Overflowed);
    234     if (Overflowed)
    235       Result = instrprof_error::counter_overflow;
    236   }
    237 
    238   for (uint32_t Kind = IPVK_First; Kind <= IPVK_Last; ++Kind)
    239     MergeResult(Result, mergeValueProfData(Kind, Other, Weight));
    240 
    241   return Result;
    242 }
    243 
    244 // Map indirect call target name hash to name string.
    245 uint64_t InstrProfRecord::remapValue(uint64_t Value, uint32_t ValueKind,
    246                                      ValueMapType *ValueMap) {
    247   if (!ValueMap)
    248     return Value;
    249   switch (ValueKind) {
    250   case IPVK_IndirectCallTarget: {
    251     auto Result =
    252         std::lower_bound(ValueMap->begin(), ValueMap->end(), Value,
    253                          [](const std::pair<uint64_t, uint64_t> &LHS,
    254                             uint64_t RHS) { return LHS.first < RHS; });
    255     if (Result != ValueMap->end())
    256       Value = (uint64_t)Result->second;
    257     break;
    258   }
    259   }
    260   return Value;
    261 }
    262 
    263 void InstrProfRecord::addValueData(uint32_t ValueKind, uint32_t Site,
    264                                    InstrProfValueData *VData, uint32_t N,
    265                                    ValueMapType *ValueMap) {
    266   for (uint32_t I = 0; I < N; I++) {
    267     VData[I].Value = remapValue(VData[I].Value, ValueKind, ValueMap);
    268   }
    269   std::vector<InstrProfValueSiteRecord> &ValueSites =
    270       getValueSitesForKind(ValueKind);
    271   if (N == 0)
    272     ValueSites.push_back(InstrProfValueSiteRecord());
    273   else
    274     ValueSites.emplace_back(VData, VData + N);
    275 }
    276 
    277 #define INSTR_PROF_COMMON_API_IMPL
    278 #include "llvm/ProfileData/InstrProfData.inc"
    279 
    280 /*!
    281  * \brief ValueProfRecordClosure Interface implementation for  InstrProfRecord
    282  *  class. These C wrappers are used as adaptors so that C++ code can be
    283  *  invoked as callbacks.
    284  */
    285 uint32_t getNumValueKindsInstrProf(const void *Record) {
    286   return reinterpret_cast<const InstrProfRecord *>(Record)->getNumValueKinds();
    287 }
    288 
    289 uint32_t getNumValueSitesInstrProf(const void *Record, uint32_t VKind) {
    290   return reinterpret_cast<const InstrProfRecord *>(Record)
    291       ->getNumValueSites(VKind);
    292 }
    293 
    294 uint32_t getNumValueDataInstrProf(const void *Record, uint32_t VKind) {
    295   return reinterpret_cast<const InstrProfRecord *>(Record)
    296       ->getNumValueData(VKind);
    297 }
    298 
    299 uint32_t getNumValueDataForSiteInstrProf(const void *R, uint32_t VK,
    300                                          uint32_t S) {
    301   return reinterpret_cast<const InstrProfRecord *>(R)
    302       ->getNumValueDataForSite(VK, S);
    303 }
    304 
    305 void getValueForSiteInstrProf(const void *R, InstrProfValueData *Dst,
    306                               uint32_t K, uint32_t S,
    307                               uint64_t (*Mapper)(uint32_t, uint64_t)) {
    308   return reinterpret_cast<const InstrProfRecord *>(R)->getValueForSite(
    309       Dst, K, S, Mapper);
    310 }
    311 
    312 ValueProfData *allocValueProfDataInstrProf(size_t TotalSizeInBytes) {
    313   ValueProfData *VD =
    314       (ValueProfData *)(new (::operator new(TotalSizeInBytes)) ValueProfData());
    315   memset(VD, 0, TotalSizeInBytes);
    316   return VD;
    317 }
    318 
    319 static ValueProfRecordClosure InstrProfRecordClosure = {
    320     0,
    321     getNumValueKindsInstrProf,
    322     getNumValueSitesInstrProf,
    323     getNumValueDataInstrProf,
    324     getNumValueDataForSiteInstrProf,
    325     0,
    326     getValueForSiteInstrProf,
    327     allocValueProfDataInstrProf};
    328 
    329 // Wrapper implementation using the closure mechanism.
    330 uint32_t ValueProfData::getSize(const InstrProfRecord &Record) {
    331   InstrProfRecordClosure.Record = &Record;
    332   return getValueProfDataSize(&InstrProfRecordClosure);
    333 }
    334 
    335 // Wrapper implementation using the closure mechanism.
    336 std::unique_ptr<ValueProfData>
    337 ValueProfData::serializeFrom(const InstrProfRecord &Record) {
    338   InstrProfRecordClosure.Record = &Record;
    339 
    340   std::unique_ptr<ValueProfData> VPD(
    341       serializeValueProfDataFrom(&InstrProfRecordClosure, nullptr));
    342   return VPD;
    343 }
    344 
    345 void ValueProfRecord::deserializeTo(InstrProfRecord &Record,
    346                                     InstrProfRecord::ValueMapType *VMap) {
    347   Record.reserveSites(Kind, NumValueSites);
    348 
    349   InstrProfValueData *ValueData = getValueProfRecordValueData(this);
    350   for (uint64_t VSite = 0; VSite < NumValueSites; ++VSite) {
    351     uint8_t ValueDataCount = this->SiteCountArray[VSite];
    352     Record.addValueData(Kind, VSite, ValueData, ValueDataCount, VMap);
    353     ValueData += ValueDataCount;
    354   }
    355 }
    356 
    357 // For writing/serializing,  Old is the host endianness, and  New is
    358 // byte order intended on disk. For Reading/deserialization, Old
    359 // is the on-disk source endianness, and New is the host endianness.
    360 void ValueProfRecord::swapBytes(support::endianness Old,
    361                                 support::endianness New) {
    362   using namespace support;
    363   if (Old == New)
    364     return;
    365 
    366   if (getHostEndianness() != Old) {
    367     sys::swapByteOrder<uint32_t>(NumValueSites);
    368     sys::swapByteOrder<uint32_t>(Kind);
    369   }
    370   uint32_t ND = getValueProfRecordNumValueData(this);
    371   InstrProfValueData *VD = getValueProfRecordValueData(this);
    372 
    373   // No need to swap byte array: SiteCountArrray.
    374   for (uint32_t I = 0; I < ND; I++) {
    375     sys::swapByteOrder<uint64_t>(VD[I].Value);
    376     sys::swapByteOrder<uint64_t>(VD[I].Count);
    377   }
    378   if (getHostEndianness() == Old) {
    379     sys::swapByteOrder<uint32_t>(NumValueSites);
    380     sys::swapByteOrder<uint32_t>(Kind);
    381   }
    382 }
    383 
    384 void ValueProfData::deserializeTo(InstrProfRecord &Record,
    385                                   InstrProfRecord::ValueMapType *VMap) {
    386   if (NumValueKinds == 0)
    387     return;
    388 
    389   ValueProfRecord *VR = getFirstValueProfRecord(this);
    390   for (uint32_t K = 0; K < NumValueKinds; K++) {
    391     VR->deserializeTo(Record, VMap);
    392     VR = getValueProfRecordNext(VR);
    393   }
    394 }
    395 
    396 template <class T>
    397 static T swapToHostOrder(const unsigned char *&D, support::endianness Orig) {
    398   using namespace support;
    399   if (Orig == little)
    400     return endian::readNext<T, little, unaligned>(D);
    401   else
    402     return endian::readNext<T, big, unaligned>(D);
    403 }
    404 
    405 static std::unique_ptr<ValueProfData> allocValueProfData(uint32_t TotalSize) {
    406   return std::unique_ptr<ValueProfData>(new (::operator new(TotalSize))
    407                                             ValueProfData());
    408 }
    409 
    410 instrprof_error ValueProfData::checkIntegrity() {
    411   if (NumValueKinds > IPVK_Last + 1)
    412     return instrprof_error::malformed;
    413   // Total size needs to be mulltiple of quadword size.
    414   if (TotalSize % sizeof(uint64_t))
    415     return instrprof_error::malformed;
    416 
    417   ValueProfRecord *VR = getFirstValueProfRecord(this);
    418   for (uint32_t K = 0; K < this->NumValueKinds; K++) {
    419     if (VR->Kind > IPVK_Last)
    420       return instrprof_error::malformed;
    421     VR = getValueProfRecordNext(VR);
    422     if ((char *)VR - (char *)this > (ptrdiff_t)TotalSize)
    423       return instrprof_error::malformed;
    424   }
    425   return instrprof_error::success;
    426 }
    427 
    428 ErrorOr<std::unique_ptr<ValueProfData>>
    429 ValueProfData::getValueProfData(const unsigned char *D,
    430                                 const unsigned char *const BufferEnd,
    431                                 support::endianness Endianness) {
    432   using namespace support;
    433   if (D + sizeof(ValueProfData) > BufferEnd)
    434     return instrprof_error::truncated;
    435 
    436   const unsigned char *Header = D;
    437   uint32_t TotalSize = swapToHostOrder<uint32_t>(Header, Endianness);
    438   if (D + TotalSize > BufferEnd)
    439     return instrprof_error::too_large;
    440 
    441   std::unique_ptr<ValueProfData> VPD = allocValueProfData(TotalSize);
    442   memcpy(VPD.get(), D, TotalSize);
    443   // Byte swap.
    444   VPD->swapBytesToHost(Endianness);
    445 
    446   instrprof_error EC = VPD->checkIntegrity();
    447   if (EC != instrprof_error::success)
    448     return EC;
    449 
    450   return std::move(VPD);
    451 }
    452 
    453 void ValueProfData::swapBytesToHost(support::endianness Endianness) {
    454   using namespace support;
    455   if (Endianness == getHostEndianness())
    456     return;
    457 
    458   sys::swapByteOrder<uint32_t>(TotalSize);
    459   sys::swapByteOrder<uint32_t>(NumValueKinds);
    460 
    461   ValueProfRecord *VR = getFirstValueProfRecord(this);
    462   for (uint32_t K = 0; K < NumValueKinds; K++) {
    463     VR->swapBytes(Endianness, getHostEndianness());
    464     VR = getValueProfRecordNext(VR);
    465   }
    466 }
    467 
    468 void ValueProfData::swapBytesFromHost(support::endianness Endianness) {
    469   using namespace support;
    470   if (Endianness == getHostEndianness())
    471     return;
    472 
    473   ValueProfRecord *VR = getFirstValueProfRecord(this);
    474   for (uint32_t K = 0; K < NumValueKinds; K++) {
    475     ValueProfRecord *NVR = getValueProfRecordNext(VR);
    476     VR->swapBytes(getHostEndianness(), Endianness);
    477     VR = NVR;
    478   }
    479   sys::swapByteOrder<uint32_t>(TotalSize);
    480   sys::swapByteOrder<uint32_t>(NumValueKinds);
    481 }
    482 
    483 }
    484