Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

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

  1. //===- SampleProfWriter.h - Write LLVM sample profile data ------*- 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 definitions needed for writing sample profiles.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #ifndef LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
  13. #define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
  14.  
  15. #include "llvm/ADT/MapVector.h"
  16. #include "llvm/ADT/StringRef.h"
  17. #include "llvm/IR/ProfileSummary.h"
  18. #include "llvm/ProfileData/SampleProf.h"
  19. #include "llvm/Support/ErrorOr.h"
  20. #include "llvm/Support/raw_ostream.h"
  21. #include <cstdint>
  22. #include <memory>
  23. #include <set>
  24. #include <system_error>
  25.  
  26. namespace llvm {
  27. namespace sampleprof {
  28.  
  29. enum SectionLayout {
  30.   DefaultLayout,
  31.   // The layout splits profile with context information from profile without
  32.   // context information. When Thinlto is enabled, ThinLTO postlink phase only
  33.   // has to load profile with context information and can skip the other part.
  34.   CtxSplitLayout,
  35.   NumOfLayout,
  36. };
  37.  
  38. /// Sample-based profile writer. Base class.
  39. class SampleProfileWriter {
  40. public:
  41.   virtual ~SampleProfileWriter() = default;
  42.  
  43.   /// Write sample profiles in \p S.
  44.   ///
  45.   /// \returns status code of the file update operation.
  46.   virtual std::error_code writeSample(const FunctionSamples &S) = 0;
  47.  
  48.   /// Write all the sample profiles in the given map of samples.
  49.   ///
  50.   /// \returns status code of the file update operation.
  51.   virtual std::error_code write(const SampleProfileMap &ProfileMap);
  52.  
  53.   raw_ostream &getOutputStream() { return *OutputStream; }
  54.  
  55.   /// Profile writer factory.
  56.   ///
  57.   /// Create a new file writer based on the value of \p Format.
  58.   static ErrorOr<std::unique_ptr<SampleProfileWriter>>
  59.   create(StringRef Filename, SampleProfileFormat Format);
  60.  
  61.   /// Create a new stream writer based on the value of \p Format.
  62.   /// For testing.
  63.   static ErrorOr<std::unique_ptr<SampleProfileWriter>>
  64.   create(std::unique_ptr<raw_ostream> &OS, SampleProfileFormat Format);
  65.  
  66.   virtual void setProfileSymbolList(ProfileSymbolList *PSL) {}
  67.   virtual void setToCompressAllSections() {}
  68.   virtual void setUseMD5() {}
  69.   virtual void setPartialProfile() {}
  70.   virtual void resetSecLayout(SectionLayout SL) {}
  71.  
  72. protected:
  73.   SampleProfileWriter(std::unique_ptr<raw_ostream> &OS)
  74.       : OutputStream(std::move(OS)) {}
  75.  
  76.   /// Write a file header for the profile file.
  77.   virtual std::error_code writeHeader(const SampleProfileMap &ProfileMap) = 0;
  78.  
  79.   // Write function profiles to the profile file.
  80.   virtual std::error_code writeFuncProfiles(const SampleProfileMap &ProfileMap);
  81.  
  82.   /// Output stream where to emit the profile to.
  83.   std::unique_ptr<raw_ostream> OutputStream;
  84.  
  85.   /// Profile summary.
  86.   std::unique_ptr<ProfileSummary> Summary;
  87.  
  88.   /// Compute summary for this profile.
  89.   void computeSummary(const SampleProfileMap &ProfileMap);
  90.  
  91.   /// Profile format.
  92.   SampleProfileFormat Format = SPF_None;
  93. };
  94.  
  95. /// Sample-based profile writer (text format).
  96. class SampleProfileWriterText : public SampleProfileWriter {
  97. public:
  98.   std::error_code writeSample(const FunctionSamples &S) override;
  99.  
  100. protected:
  101.   SampleProfileWriterText(std::unique_ptr<raw_ostream> &OS)
  102.       : SampleProfileWriter(OS), Indent(0) {}
  103.  
  104.   std::error_code writeHeader(const SampleProfileMap &ProfileMap) override {
  105.     return sampleprof_error::success;
  106.   }
  107.  
  108. private:
  109.   /// Indent level to use when writing.
  110.   ///
  111.   /// This is used when printing inlined callees.
  112.   unsigned Indent;
  113.  
  114.   friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
  115.   SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
  116.                               SampleProfileFormat Format);
  117. };
  118.  
  119. /// Sample-based profile writer (binary format).
  120. class SampleProfileWriterBinary : public SampleProfileWriter {
  121. public:
  122.   SampleProfileWriterBinary(std::unique_ptr<raw_ostream> &OS)
  123.       : SampleProfileWriter(OS) {}
  124.  
  125.   std::error_code writeSample(const FunctionSamples &S) override;
  126.  
  127. protected:
  128.   virtual MapVector<StringRef, uint32_t> &getNameTable() { return NameTable; }
  129.   virtual std::error_code writeMagicIdent(SampleProfileFormat Format);
  130.   virtual std::error_code writeNameTable();
  131.   std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
  132.   std::error_code writeSummary();
  133.   virtual std::error_code writeContextIdx(const SampleContext &Context);
  134.   std::error_code writeNameIdx(StringRef FName);
  135.   std::error_code writeBody(const FunctionSamples &S);
  136.   inline void stablizeNameTable(MapVector<StringRef, uint32_t> &NameTable,
  137.                                 std::set<StringRef> &V);
  138.  
  139.   MapVector<StringRef, uint32_t> NameTable;
  140.  
  141.   void addName(StringRef FName);
  142.   virtual void addContext(const SampleContext &Context);
  143.   void addNames(const FunctionSamples &S);
  144.  
  145. private:
  146.   friend ErrorOr<std::unique_ptr<SampleProfileWriter>>
  147.   SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS,
  148.                               SampleProfileFormat Format);
  149. };
  150.  
  151. class SampleProfileWriterRawBinary : public SampleProfileWriterBinary {
  152.   using SampleProfileWriterBinary::SampleProfileWriterBinary;
  153. };
  154.  
  155. const std::array<SmallVector<SecHdrTableEntry, 8>, NumOfLayout>
  156.     ExtBinaryHdrLayoutTable = {
  157.         // Note that SecFuncOffsetTable section is written after SecLBRProfile
  158.         // in the profile, but is put before SecLBRProfile in SectionHdrLayout.
  159.         // This is because sample reader follows the order in SectionHdrLayout
  160.         // to read each section. To read function profiles on demand, sample
  161.         // reader need to get the offset of each function profile first.
  162.         //
  163.         // DefaultLayout
  164.         SmallVector<SecHdrTableEntry, 8>({{SecProfSummary, 0, 0, 0, 0},
  165.                                           {SecNameTable, 0, 0, 0, 0},
  166.                                           {SecCSNameTable, 0, 0, 0, 0},
  167.                                           {SecFuncOffsetTable, 0, 0, 0, 0},
  168.                                           {SecLBRProfile, 0, 0, 0, 0},
  169.                                           {SecProfileSymbolList, 0, 0, 0, 0},
  170.                                           {SecFuncMetadata, 0, 0, 0, 0}}),
  171.         // CtxSplitLayout
  172.         SmallVector<SecHdrTableEntry, 8>({{SecProfSummary, 0, 0, 0, 0},
  173.                                           {SecNameTable, 0, 0, 0, 0},
  174.                                           // profile with context
  175.                                           // for next two sections
  176.                                           {SecFuncOffsetTable, 0, 0, 0, 0},
  177.                                           {SecLBRProfile, 0, 0, 0, 0},
  178.                                           // profile without context
  179.                                           // for next two sections
  180.                                           {SecFuncOffsetTable, 0, 0, 0, 0},
  181.                                           {SecLBRProfile, 0, 0, 0, 0},
  182.                                           {SecProfileSymbolList, 0, 0, 0, 0},
  183.                                           {SecFuncMetadata, 0, 0, 0, 0}}),
  184. };
  185.  
  186. class SampleProfileWriterExtBinaryBase : public SampleProfileWriterBinary {
  187.   using SampleProfileWriterBinary::SampleProfileWriterBinary;
  188. public:
  189.   std::error_code write(const SampleProfileMap &ProfileMap) override;
  190.  
  191.   void setToCompressAllSections() override;
  192.   void setToCompressSection(SecType Type);
  193.   std::error_code writeSample(const FunctionSamples &S) override;
  194.  
  195.   // Set to use MD5 to represent string in NameTable.
  196.   void setUseMD5() override {
  197.     UseMD5 = true;
  198.     addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagMD5Name);
  199.     // MD5 will be stored as plain uint64_t instead of variable-length
  200.     // quantity format in NameTable section.
  201.     addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagFixedLengthMD5);
  202.   }
  203.  
  204.   // Set the profile to be partial. It means the profile is for
  205.   // common/shared code. The common profile is usually merged from
  206.   // profiles collected from running other targets.
  207.   void setPartialProfile() override {
  208.     addSectionFlag(SecProfSummary, SecProfSummaryFlags::SecFlagPartial);
  209.   }
  210.  
  211.   void setProfileSymbolList(ProfileSymbolList *PSL) override {
  212.     ProfSymList = PSL;
  213.   };
  214.  
  215.   void resetSecLayout(SectionLayout SL) override {
  216.     verifySecLayout(SL);
  217. #ifndef NDEBUG
  218.     // Make sure resetSecLayout is called before any flag setting.
  219.     for (auto &Entry : SectionHdrLayout) {
  220.       assert(Entry.Flags == 0 &&
  221.              "resetSecLayout has to be called before any flag setting");
  222.     }
  223. #endif
  224.     SecLayout = SL;
  225.     SectionHdrLayout = ExtBinaryHdrLayoutTable[SL];
  226.   }
  227.  
  228. protected:
  229.   uint64_t markSectionStart(SecType Type, uint32_t LayoutIdx);
  230.   std::error_code addNewSection(SecType Sec, uint32_t LayoutIdx,
  231.                                 uint64_t SectionStart);
  232.   template <class SecFlagType>
  233.   void addSectionFlag(SecType Type, SecFlagType Flag) {
  234.     for (auto &Entry : SectionHdrLayout) {
  235.       if (Entry.Type == Type)
  236.         addSecFlag(Entry, Flag);
  237.     }
  238.   }
  239.   template <class SecFlagType>
  240.   void addSectionFlag(uint32_t SectionIdx, SecFlagType Flag) {
  241.     addSecFlag(SectionHdrLayout[SectionIdx], Flag);
  242.   }
  243.  
  244.   void addContext(const SampleContext &Context) override;
  245.  
  246.   // placeholder for subclasses to dispatch their own section writers.
  247.   virtual std::error_code writeCustomSection(SecType Type) = 0;
  248.   // Verify the SecLayout is supported by the format.
  249.   virtual void verifySecLayout(SectionLayout SL) = 0;
  250.  
  251.   // specify the order to write sections.
  252.   virtual std::error_code writeSections(const SampleProfileMap &ProfileMap) = 0;
  253.  
  254.   // Dispatch section writer for each section. \p LayoutIdx is the sequence
  255.   // number indicating where the section is located in SectionHdrLayout.
  256.   virtual std::error_code writeOneSection(SecType Type, uint32_t LayoutIdx,
  257.                                           const SampleProfileMap &ProfileMap);
  258.  
  259.   // Helper function to write name table.
  260.   std::error_code writeNameTable() override;
  261.   std::error_code writeContextIdx(const SampleContext &Context) override;
  262.   std::error_code writeCSNameIdx(const SampleContext &Context);
  263.   std::error_code writeCSNameTableSection();
  264.  
  265.   std::error_code writeFuncMetadata(const SampleProfileMap &Profiles);
  266.   std::error_code writeFuncMetadata(const FunctionSamples &Profile);
  267.  
  268.   // Functions to write various kinds of sections.
  269.   std::error_code writeNameTableSection(const SampleProfileMap &ProfileMap);
  270.   std::error_code writeFuncOffsetTable();
  271.   std::error_code writeProfileSymbolListSection();
  272.  
  273.   SectionLayout SecLayout = DefaultLayout;
  274.   // Specifiy the order of sections in section header table. Note
  275.   // the order of sections in SecHdrTable may be different that the
  276.   // order in SectionHdrLayout. sample Reader will follow the order
  277.   // in SectionHdrLayout to read each section.
  278.   SmallVector<SecHdrTableEntry, 8> SectionHdrLayout =
  279.       ExtBinaryHdrLayoutTable[DefaultLayout];
  280.  
  281.   // Save the start of SecLBRProfile so we can compute the offset to the
  282.   // start of SecLBRProfile for each Function's Profile and will keep it
  283.   // in FuncOffsetTable.
  284.   uint64_t SecLBRProfileStart = 0;
  285.  
  286. private:
  287.   void allocSecHdrTable();
  288.   std::error_code writeSecHdrTable();
  289.   std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
  290.   std::error_code compressAndOutput();
  291.  
  292.   // We will swap the raw_ostream held by LocalBufStream and that
  293.   // held by OutputStream if we try to add a section which needs
  294.   // compression. After the swap, all the data written to output
  295.   // will be temporarily buffered into the underlying raw_string_ostream
  296.   // originally held by LocalBufStream. After the data writing for the
  297.   // section is completed, compress the data in the local buffer,
  298.   // swap the raw_ostream back and write the compressed data to the
  299.   // real output.
  300.   std::unique_ptr<raw_ostream> LocalBufStream;
  301.   // The location where the output stream starts.
  302.   uint64_t FileStart;
  303.   // The location in the output stream where the SecHdrTable should be
  304.   // written to.
  305.   uint64_t SecHdrTableOffset;
  306.   // The table contains SecHdrTableEntry entries in order of how they are
  307.   // populated in the writer. It may be different from the order in
  308.   // SectionHdrLayout which specifies the sequence in which sections will
  309.   // be read.
  310.   std::vector<SecHdrTableEntry> SecHdrTable;
  311.  
  312.   // FuncOffsetTable maps function context to its profile offset in
  313.   // SecLBRProfile section. It is used to load function profile on demand.
  314.   MapVector<SampleContext, uint64_t> FuncOffsetTable;
  315.   // Whether to use MD5 to represent string.
  316.   bool UseMD5 = false;
  317.  
  318.   /// CSNameTable maps function context to its offset in SecCSNameTable section.
  319.   /// The offset will be used everywhere where the context is referenced.
  320.   MapVector<SampleContext, uint32_t> CSNameTable;
  321.  
  322.   ProfileSymbolList *ProfSymList = nullptr;
  323. };
  324.  
  325. class SampleProfileWriterExtBinary : public SampleProfileWriterExtBinaryBase {
  326. public:
  327.   SampleProfileWriterExtBinary(std::unique_ptr<raw_ostream> &OS)
  328.       : SampleProfileWriterExtBinaryBase(OS) {}
  329.  
  330. private:
  331.   std::error_code writeDefaultLayout(const SampleProfileMap &ProfileMap);
  332.   std::error_code writeCtxSplitLayout(const SampleProfileMap &ProfileMap);
  333.  
  334.   std::error_code writeSections(const SampleProfileMap &ProfileMap) override;
  335.  
  336.   std::error_code writeCustomSection(SecType Type) override {
  337.     return sampleprof_error::success;
  338.   };
  339.  
  340.   void verifySecLayout(SectionLayout SL) override {
  341.     assert((SL == DefaultLayout || SL == CtxSplitLayout) &&
  342.            "Unsupported layout");
  343.   }
  344. };
  345.  
  346. // CompactBinary is a compact format of binary profile which both reduces
  347. // the profile size and the load time needed when compiling. It has two
  348. // major difference with Binary format.
  349. // 1. It represents all the strings in name table using md5 hash.
  350. // 2. It saves a function offset table which maps function name index to
  351. // the offset of its function profile to the start of the binary profile,
  352. // so by using the function offset table, for those function profiles which
  353. // will not be needed when compiling a module, the profile reader does't
  354. // have to read them and it saves compile time if the profile size is huge.
  355. // The layout of the compact format is shown as follows:
  356. //
  357. //    Part1: Profile header, the same as binary format, containing magic
  358. //           number, version, summary, name table...
  359. //    Part2: Function Offset Table Offset, which saves the position of
  360. //           Part4.
  361. //    Part3: Function profile collection
  362. //             function1 profile start
  363. //                 ....
  364. //             function2 profile start
  365. //                 ....
  366. //             function3 profile start
  367. //                 ....
  368. //                ......
  369. //    Part4: Function Offset Table
  370. //             function1 name index --> function1 profile start
  371. //             function2 name index --> function2 profile start
  372. //             function3 name index --> function3 profile start
  373. //
  374. // We need Part2 because profile reader can use it to find out and read
  375. // function offset table without reading Part3 first.
  376. class SampleProfileWriterCompactBinary : public SampleProfileWriterBinary {
  377.   using SampleProfileWriterBinary::SampleProfileWriterBinary;
  378.  
  379. public:
  380.   std::error_code writeSample(const FunctionSamples &S) override;
  381.   std::error_code write(const SampleProfileMap &ProfileMap) override;
  382.  
  383. protected:
  384.   /// The table mapping from function name to the offset of its FunctionSample
  385.   /// towards profile start.
  386.   MapVector<StringRef, uint64_t> FuncOffsetTable;
  387.   /// The offset of the slot to be filled with the offset of FuncOffsetTable
  388.   /// towards profile start.
  389.   uint64_t TableOffset;
  390.   std::error_code writeNameTable() override;
  391.   std::error_code writeHeader(const SampleProfileMap &ProfileMap) override;
  392.   std::error_code writeFuncOffsetTable();
  393. };
  394.  
  395. } // end namespace sampleprof
  396. } // end namespace llvm
  397.  
  398. #endif // LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
  399.