Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. //===- InstrProfWriter.h - Instrumented profiling writer --------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file contains support for writing profiling data for instrumentation
  10. // based PGO and coverage.
  11. //
  12. //===----------------------------------------------------------------------===//
  13.  
  14. #ifndef LLVM_PROFILEDATA_INSTRPROFWRITER_H
  15. #define LLVM_PROFILEDATA_INSTRPROFWRITER_H
  16.  
  17. #include "llvm/ADT/DenseMap.h"
  18. #include "llvm/ADT/MapVector.h"
  19. #include "llvm/ADT/StringMap.h"
  20. #include "llvm/IR/GlobalValue.h"
  21. #include "llvm/Object/BuildID.h"
  22. #include "llvm/ProfileData/InstrProf.h"
  23. #include "llvm/ProfileData/MemProf.h"
  24. #include "llvm/Support/Endian.h"
  25. #include "llvm/Support/Error.h"
  26. #include <cstdint>
  27. #include <memory>
  28.  
  29. namespace llvm {
  30.  
  31. /// Writer for instrumentation based profile data.
  32. class InstrProfRecordWriterTrait;
  33. class ProfOStream;
  34. class MemoryBuffer;
  35. class raw_fd_ostream;
  36.  
  37. class InstrProfWriter {
  38. public:
  39.   using ProfilingData = SmallDenseMap<uint64_t, InstrProfRecord>;
  40.  
  41. private:
  42.   bool Sparse;
  43.   StringMap<ProfilingData> FunctionData;
  44.  
  45.   // A map to hold memprof data per function. The lower 64 bits obtained from
  46.   // the md5 hash of the function name is used to index into the map.
  47.   llvm::MapVector<GlobalValue::GUID, memprof::IndexedMemProfRecord>
  48.       MemProfRecordData;
  49.   // A map to hold frame id to frame mappings. The mappings are used to
  50.   // convert IndexedMemProfRecord to MemProfRecords with frame information
  51.   // inline.
  52.   llvm::MapVector<memprof::FrameId, memprof::Frame> MemProfFrameData;
  53.  
  54.   // List of binary ids.
  55.   std::vector<llvm::object::BuildID> BinaryIds;
  56.  
  57.   // An enum describing the attributes of the profile.
  58.   InstrProfKind ProfileKind = InstrProfKind::Unknown;
  59.   // Use raw pointer here for the incomplete type object.
  60.   InstrProfRecordWriterTrait *InfoObj;
  61.  
  62. public:
  63.   InstrProfWriter(bool Sparse = false);
  64.   ~InstrProfWriter();
  65.  
  66.   StringMap<ProfilingData> &getProfileData() { return FunctionData; }
  67.  
  68.   /// Add function counts for the given function. If there are already counts
  69.   /// for this function and the hash and number of counts match, each counter is
  70.   /// summed. Optionally scale counts by \p Weight.
  71.   void addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
  72.                  function_ref<void(Error)> Warn);
  73.   void addRecord(NamedInstrProfRecord &&I, function_ref<void(Error)> Warn) {
  74.     addRecord(std::move(I), 1, Warn);
  75.   }
  76.  
  77.   /// Add a memprof record for a function identified by its \p Id.
  78.   void addMemProfRecord(const GlobalValue::GUID Id,
  79.                         const memprof::IndexedMemProfRecord &Record);
  80.  
  81.   /// Add a memprof frame identified by the hash of the contents of the frame in
  82.   /// \p FrameId.
  83.   bool addMemProfFrame(const memprof::FrameId, const memprof::Frame &F,
  84.                        function_ref<void(Error)> Warn);
  85.  
  86.   // Add a binary id to the binary ids list.
  87.   void addBinaryIds(ArrayRef<llvm::object::BuildID> BIs);
  88.  
  89.   /// Merge existing function counts from the given writer.
  90.   void mergeRecordsFromWriter(InstrProfWriter &&IPW,
  91.                               function_ref<void(Error)> Warn);
  92.  
  93.   /// Write the profile to \c OS
  94.   Error write(raw_fd_ostream &OS);
  95.  
  96.   /// Write the profile in text format to \c OS
  97.   Error writeText(raw_fd_ostream &OS);
  98.  
  99.   Error validateRecord(const InstrProfRecord &Func);
  100.  
  101.   /// Write \c Record in text format to \c OS
  102.   static void writeRecordInText(StringRef Name, uint64_t Hash,
  103.                                 const InstrProfRecord &Counters,
  104.                                 InstrProfSymtab &Symtab, raw_fd_ostream &OS);
  105.  
  106.   /// Write the profile, returning the raw data. For testing.
  107.   std::unique_ptr<MemoryBuffer> writeBuffer();
  108.  
  109.   /// Update the attributes of the current profile from the attributes
  110.   /// specified. An error is returned if IR and FE profiles are mixed.
  111.   Error mergeProfileKind(const InstrProfKind Other) {
  112.     // If the kind is unset, this is the first profile we are merging so just
  113.     // set it to the given type.
  114.     if (ProfileKind == InstrProfKind::Unknown) {
  115.       ProfileKind = Other;
  116.       return Error::success();
  117.     }
  118.  
  119.     // Returns true if merging is should fail assuming A and B are incompatible.
  120.     auto testIncompatible = [&](InstrProfKind A, InstrProfKind B) {
  121.       return (static_cast<bool>(ProfileKind & A) &&
  122.               static_cast<bool>(Other & B)) ||
  123.              (static_cast<bool>(ProfileKind & B) &&
  124.               static_cast<bool>(Other & A));
  125.     };
  126.  
  127.     // Check if the profiles are in-compatible. Clang frontend profiles can't be
  128.     // merged with other profile types.
  129.     if (static_cast<bool>(
  130.             (ProfileKind & InstrProfKind::FrontendInstrumentation) ^
  131.             (Other & InstrProfKind::FrontendInstrumentation))) {
  132.       return make_error<InstrProfError>(instrprof_error::unsupported_version);
  133.     }
  134.     if (testIncompatible(InstrProfKind::FunctionEntryOnly,
  135.                          InstrProfKind::FunctionEntryInstrumentation)) {
  136.       return make_error<InstrProfError>(
  137.           instrprof_error::unsupported_version,
  138.           "cannot merge FunctionEntryOnly profiles and BB profiles together");
  139.     }
  140.  
  141.     // Now we update the profile type with the bits that are set.
  142.     ProfileKind |= Other;
  143.     return Error::success();
  144.   }
  145.  
  146.   InstrProfKind getProfileKind() const { return ProfileKind; }
  147.  
  148.   // Internal interface for testing purpose only.
  149.   void setValueProfDataEndianness(support::endianness Endianness);
  150.   void setOutputSparse(bool Sparse);
  151.   // Compute the overlap b/w this object and Other. Program level result is
  152.   // stored in Overlap and function level result is stored in FuncLevelOverlap.
  153.   void overlapRecord(NamedInstrProfRecord &&Other, OverlapStats &Overlap,
  154.                      OverlapStats &FuncLevelOverlap,
  155.                      const OverlapFuncFilters &FuncFilter);
  156.  
  157. private:
  158.   void addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I,
  159.                  uint64_t Weight, function_ref<void(Error)> Warn);
  160.   bool shouldEncodeData(const ProfilingData &PD);
  161.  
  162.   Error writeImpl(ProfOStream &OS);
  163. };
  164.  
  165. } // end namespace llvm
  166.  
  167. #endif // LLVM_PROFILEDATA_INSTRPROFWRITER_H
  168.