[llvm] [llvm-profdata] Use simple enum for error checking in Sample Profile Reader (PR #67453)

William Junda Huang via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 26 09:25:30 PDT 2023


https://github.com/huangjd created https://github.com/llvm/llvm-project/pull/67453


Benchmarking data show that around 7% of the time is spent on handling llvm::ErrorOr<T> and std::error_code, which are not efficiently processed. This has a significant impact on profile load time, so it should be changed into a simple enum and check if it is 0 instead.

>From 228eabe8a2c102b6ddaaa804b4264e54c98cb93d Mon Sep 17 00:00:00 2001
From: William Huang <williamjhuang at google.com>
Date: Mon, 25 Sep 2023 23:34:16 +0000
Subject: [PATCH] [llvm-profdata] Use simple enum for error checking in Sample
 Profile Reader.

Benchmarking data show that around 7% of the time is spent on handling
llvm::ErrorOr<T> and std::error_code, which are not efficiently
processed. This has a significant impact on profile load time, so it
should be changed into a simple enum and check if it is 0 instead.
---
 llvm/include/llvm/ProfileData/SampleProf.h    |   2 +-
 .../llvm/ProfileData/SampleProfReader.h       | 108 +--
 llvm/lib/ProfileData/SampleProfReader.cpp     | 818 +++++++++---------
 3 files changed, 471 insertions(+), 457 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h
index 78a16499accd64a..22c6a0080ad6847 100644
--- a/llvm/include/llvm/ProfileData/SampleProf.h
+++ b/llvm/include/llvm/ProfileData/SampleProf.h
@@ -43,7 +43,7 @@ class raw_ostream;
 
 const std::error_category &sampleprof_category();
 
-enum class sampleprof_error {
+enum sampleprof_error {
   success = 0,
   bad_magic,
   unsupported_version,
diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h
index a5b1df3ef550b2b..f37d7ef798e549e 100644
--- a/llvm/include/llvm/ProfileData/SampleProfReader.h
+++ b/llvm/include/llvm/ProfileData/SampleProfReader.h
@@ -352,7 +352,7 @@ class SampleProfileReader {
   virtual ~SampleProfileReader() = default;
 
   /// Read and validate the file header.
-  virtual std::error_code readHeader() = 0;
+  virtual sampleprof_error readHeader() = 0;
 
   /// Set the bits for FS discriminators. Parameter Pass specify the sequence
   /// number, Pass == i is for the i-th round of adding FS discriminators.
@@ -381,7 +381,7 @@ class SampleProfileReader {
   }
 
   /// The implementaion to read sample profiles from the associated file.
-  virtual std::error_code readImpl() = 0;
+  virtual sampleprof_error readImpl() = 0;
 
   /// Print the profile for \p FunctionSamples on stream \p OS.
   void dumpFunctionProfile(const FunctionSamples &FS, raw_ostream &OS = dbgs());
@@ -564,10 +564,10 @@ class SampleProfileReaderText : public SampleProfileReader {
       : SampleProfileReader(std::move(B), C, SPF_Text) {}
 
   /// Read and validate the file header.
-  std::error_code readHeader() override { return sampleprof_error::success; }
+  sampleprof_error readHeader() override { return sampleprof_error::success; }
 
   /// Read sample profiles from the associated file.
-  std::error_code readImpl() override;
+  sampleprof_error readImpl() override;
 
   /// Return true if \p Buffer is in the format supported by this class.
   static bool hasFormat(const MemoryBuffer &Buffer);
@@ -588,10 +588,10 @@ class SampleProfileReaderBinary : public SampleProfileReader {
       : SampleProfileReader(std::move(B), C, Format) {}
 
   /// Read and validate the file header.
-  std::error_code readHeader() override;
+  sampleprof_error readHeader() override;
 
   /// Read sample profiles from the associated file.
-  std::error_code readImpl() override;
+  sampleprof_error readImpl() override;
 
   /// It includes all the names that have samples either in outline instance
   /// or inline instance.
@@ -604,11 +604,11 @@ class SampleProfileReaderBinary : public SampleProfileReader {
   /// EC is set.
   ///
   /// \returns the read value.
-  template <typename T> ErrorOr<T> readNumber();
+  template <typename T> sampleprof_error readNumber(T &Result);
 
   /// Read a numeric value of type T from the profile. The value is saved
   /// without encoded.
-  template <typename T> ErrorOr<T> readUnencodedNumber();
+  template <typename T> sampleprof_error readUnencodedNumber(T &Result);
 
   /// Read a string from the profile.
   ///
@@ -616,36 +616,40 @@ class SampleProfileReaderBinary : public SampleProfileReader {
   /// EC is set.
   ///
   /// \returns the read value.
-  ErrorOr<StringRef> readString();
+  sampleprof_error readString(StringRef &Result);
 
   /// Read the string index and check whether it overflows the table.
-  template <typename T> inline ErrorOr<size_t> readStringIndex(T &Table);
+  template <typename T> sampleprof_error readStringIndex(T &Table,
+                                   size_t &Result);
 
   /// Read the next function profile instance.
-  std::error_code readFuncProfile(const uint8_t *Start);
+  sampleprof_error readFuncProfile(const uint8_t *Start);
 
   /// Read the contents of the given profile instance.
-  std::error_code readProfile(FunctionSamples &FProfile);
+  sampleprof_error readProfile(FunctionSamples &FProfile);
 
   /// Read the contents of Magic number and Version number.
-  std::error_code readMagicIdent();
+  sampleprof_error readMagicIdent();
 
   /// Read profile summary.
-  std::error_code readSummary();
+  sampleprof_error readSummary();
 
   /// Read the whole name table.
-  std::error_code readNameTable();
+  sampleprof_error readNameTable();
 
   /// Read a string indirectly via the name table. Optionally return the index.
-  ErrorOr<StringRef> readStringFromTable(size_t *RetIdx = nullptr);
+  sampleprof_error readStringFromTable(StringRef &Result,
+                                       size_t *RetIdx = nullptr);
 
   /// Read a context indirectly via the CSNameTable. Optionally return the
   /// index.
-  ErrorOr<SampleContextFrames> readContextFromTable(size_t *RetIdx = nullptr);
+  sampleprof_error readContextFromTable(SampleContextFrames &Result,
+                                        size_t *RetIdx = nullptr);
 
   /// Read a context indirectly via the CSNameTable if the profile has context,
   /// otherwise same as readStringFromTable, also return its hash value.
-  ErrorOr<std::pair<SampleContext, uint64_t>> readSampleContextFromTable();
+  sampleprof_error readSampleContextFromTable(SampleContext &Result,
+                                              uint64_t &Hash);
 
   /// Points to the current location in the buffer.
   const uint8_t *Data = nullptr;
@@ -684,13 +688,13 @@ class SampleProfileReaderBinary : public SampleProfileReader {
   const uint64_t *MD5SampleContextStart = nullptr;
 
 private:
-  std::error_code readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries);
-  virtual std::error_code verifySPMagic(uint64_t Magic) = 0;
+  sampleprof_error readSummaryEntry(std::vector<ProfileSummaryEntry> &Entries);
+  virtual sampleprof_error verifySPMagic(uint64_t Magic) = 0;
 };
 
 class SampleProfileReaderRawBinary : public SampleProfileReaderBinary {
 private:
-  std::error_code verifySPMagic(uint64_t Magic) override;
+  sampleprof_error verifySPMagic(uint64_t Magic) override;
 
 public:
   SampleProfileReaderRawBinary(std::unique_ptr<MemoryBuffer> B, LLVMContext &C,
@@ -722,7 +726,7 @@ class SampleProfileReaderRawBinary : public SampleProfileReaderBinary {
 /// SampleProfileReaderExtBinaryBase/SampleProfileWriterExtBinaryBase.
 class SampleProfileReaderExtBinaryBase : public SampleProfileReaderBinary {
 private:
-  std::error_code decompressSection(const uint8_t *SecStart,
+  sampleprof_error decompressSection(const uint8_t *SecStart,
                                     const uint64_t SecSize,
                                     const uint8_t *&DecompressBuf,
                                     uint64_t &DecompressBufSize);
@@ -731,24 +735,24 @@ class SampleProfileReaderExtBinaryBase : public SampleProfileReaderBinary {
 
 protected:
   std::vector<SecHdrTableEntry> SecHdrTable;
-  std::error_code readSecHdrTableEntry(uint64_t Idx);
-  std::error_code readSecHdrTable();
-
-  std::error_code readFuncMetadata(bool ProfileHasAttribute);
-  std::error_code readFuncMetadata(bool ProfileHasAttribute,
-                                   FunctionSamples *FProfile);
-  std::error_code readFuncOffsetTable();
-  std::error_code readFuncProfiles();
-  std::error_code readNameTableSec(bool IsMD5, bool FixedLengthMD5);
-  std::error_code readCSNameTableSec();
-  std::error_code readProfileSymbolList();
-
-  std::error_code readHeader() override;
-  std::error_code verifySPMagic(uint64_t Magic) override = 0;
-  virtual std::error_code readOneSection(const uint8_t *Start, uint64_t Size,
-                                         const SecHdrTableEntry &Entry);
+  sampleprof_error readSecHdrTableEntry(uint64_t Idx);
+  sampleprof_error readSecHdrTable();
+
+  sampleprof_error readFuncMetadata(bool ProfileHasAttribute);
+  sampleprof_error readFuncMetadata(bool ProfileHasAttribute,
+                                    FunctionSamples *FProfile);
+  sampleprof_error readFuncOffsetTable();
+  sampleprof_error readFuncProfiles();
+  sampleprof_error readNameTableSec(bool IsMD5, bool FixedLengthMD5);
+  sampleprof_error readCSNameTableSec();
+  sampleprof_error readProfileSymbolList();
+
+  sampleprof_error readHeader() override;
+  sampleprof_error verifySPMagic(uint64_t Magic) override = 0;
+  virtual sampleprof_error readOneSection(const uint8_t *Start, uint64_t Size,
+                                          const SecHdrTableEntry &Entry);
   // placeholder for subclasses to dispatch their own section readers.
-  virtual std::error_code readCustomSection(const SecHdrTableEntry &Entry) = 0;
+  virtual sampleprof_error readCustomSection(const SecHdrTableEntry &Entry) = 0;
 
   /// Determine which container readFuncOffsetTable() should populate, the list
   /// FuncOffsetList or the map FuncOffsetTable.
@@ -778,7 +782,7 @@ class SampleProfileReaderExtBinaryBase : public SampleProfileReaderBinary {
       : SampleProfileReaderBinary(std::move(B), C, Format) {}
 
   /// Read sample profiles in extensible format from the associated file.
-  std::error_code readImpl() override;
+  sampleprof_error readImpl() override;
 
   /// Get the total size of all \p Type sections.
   uint64_t getSectionSize(SecType Type);
@@ -799,8 +803,8 @@ class SampleProfileReaderExtBinaryBase : public SampleProfileReaderBinary {
 
 class SampleProfileReaderExtBinary : public SampleProfileReaderExtBinaryBase {
 private:
-  std::error_code verifySPMagic(uint64_t Magic) override;
-  std::error_code readCustomSection(const SecHdrTableEntry &Entry) override {
+  sampleprof_error verifySPMagic(uint64_t Magic) override;
+  sampleprof_error readCustomSection(const SecHdrTableEntry &Entry) override {
     // Update the data reader pointer to the end of the section.
     Data = End;
     return sampleprof_error::success;
@@ -837,25 +841,25 @@ class SampleProfileReaderGCC : public SampleProfileReader {
         GcovBuffer(Buffer.get()) {}
 
   /// Read and validate the file header.
-  std::error_code readHeader() override;
+  sampleprof_error readHeader() override;
 
   /// Read sample profiles from the associated file.
-  std::error_code readImpl() override;
+  sampleprof_error readImpl() override;
 
   /// Return true if \p Buffer is in the format supported by this class.
   static bool hasFormat(const MemoryBuffer &Buffer);
 
 protected:
-  std::error_code readNameTable();
-  std::error_code readOneFunctionProfile(const InlineCallStack &InlineStack,
-                                         bool Update, uint32_t Offset);
-  std::error_code readFunctionProfiles();
-  std::error_code skipNextWord();
-  template <typename T> ErrorOr<T> readNumber();
-  ErrorOr<StringRef> readString();
+  sampleprof_error readNameTable();
+  sampleprof_error readOneFunctionProfile(const InlineCallStack &InlineStack,
+                                          bool Update, uint32_t Offset);
+  sampleprof_error readFunctionProfiles();
+  sampleprof_error skipNextWord();
+  template <typename T> sampleprof_error readNumber(T &Result);
+  sampleprof_error readString(StringRef &Result);
 
   /// Read the section tag and check that it's the same as \p Expected.
-  std::error_code readSectionTag(uint32_t Expected);
+  sampleprof_error readSectionTag(uint32_t Expected);
 
   /// GCOV buffer containing the profile.
   GCOVBuffer GcovBuffer;
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index d632a812b86e004..af2ca10cbb06b12 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -314,7 +314,7 @@ static bool ParseLine(const StringRef &Input, LineType &LineTy, uint32_t &Depth,
 /// the expected format.
 ///
 /// \returns true if the file was loaded successfully, false otherwise.
-std::error_code SampleProfileReaderText::readImpl() {
+sampleprof_error SampleProfileReaderText::readImpl() {
   line_iterator LineIt(*Buffer, /*SkipBlanks=*/true, '#');
   sampleprof_error Result = sampleprof_error::success;
 
@@ -463,252 +463,261 @@ bool SampleProfileReaderText::hasFormat(const MemoryBuffer &Buffer) {
   return result;
 }
 
-template <typename T> ErrorOr<T> SampleProfileReaderBinary::readNumber() {
+template <typename T>
+sampleprof_error SampleProfileReaderBinary::readNumber(T &Result) {
   unsigned NumBytesRead = 0;
   uint64_t Val = decodeULEB128(Data, &NumBytesRead);
 
   if (Val > std::numeric_limits<T>::max()) {
-    std::error_code EC = sampleprof_error::malformed;
-    reportError(0, EC.message());
-    return EC;
+    sampleprof_error E = sampleprof_error::malformed;
+    reportError(0, std::error_code(E).message());
+    return E;
   } else if (Data + NumBytesRead > End) {
-    std::error_code EC = sampleprof_error::truncated;
-    reportError(0, EC.message());
-    return EC;
+    sampleprof_error E = sampleprof_error::truncated;
+    reportError(0, std::error_code(E).message());
+    return E;
   }
 
   Data += NumBytesRead;
-  return static_cast<T>(Val);
+  Result = static_cast<T>(Val);
+  return sampleprof_error::success;
 }
 
-ErrorOr<StringRef> SampleProfileReaderBinary::readString() {
+sampleprof_error SampleProfileReaderBinary::readString(StringRef &Result) {
   StringRef Str(reinterpret_cast<const char *>(Data));
   if (Data + Str.size() + 1 > End) {
-    std::error_code EC = sampleprof_error::truncated;
-    reportError(0, EC.message());
-    return EC;
+    sampleprof_error E = sampleprof_error::truncated;
+    reportError(0, std::error_code(E).message());
+    return E;
   }
 
   Data += Str.size() + 1;
-  return Str;
+  Result = Str;
+  return sampleprof_error::success;
 }
 
 template <typename T>
-ErrorOr<T> SampleProfileReaderBinary::readUnencodedNumber() {
+sampleprof_error SampleProfileReaderBinary::readUnencodedNumber(T &Result) {
   if (Data + sizeof(T) > End) {
-    std::error_code EC = sampleprof_error::truncated;
-    reportError(0, EC.message());
-    return EC;
+    sampleprof_error E = sampleprof_error::truncated;
+    reportError(0, std::error_code(E).message());
+    return E;
   }
 
   using namespace support;
-  T Val = endian::readNext<T, little, unaligned>(Data);
-  return Val;
+  Result = endian::readNext<T, little, unaligned>(Data);
+  return sampleprof_error::success;
 }
 
 template <typename T>
-inline ErrorOr<size_t> SampleProfileReaderBinary::readStringIndex(T &Table) {
-  auto Idx = readNumber<size_t>();
-  if (std::error_code EC = Idx.getError())
-    return EC;
-  if (*Idx >= Table.size())
+sampleprof_error SampleProfileReaderBinary::readStringIndex(T &Table,
+                                                            size_t &Result) {
+  size_t Idx;
+  if (sampleprof_error E = readNumber(Idx))
+    return E;
+  if (Idx >= Table.size())
     return sampleprof_error::truncated_name_table;
-  return *Idx;
+  Result = Idx;
+  return sampleprof_error::success;
 }
 
-ErrorOr<StringRef>
-SampleProfileReaderBinary::readStringFromTable(size_t *RetIdx) {
-  auto Idx = readStringIndex(NameTable);
-  if (std::error_code EC = Idx.getError())
-    return EC;
+sampleprof_error
+SampleProfileReaderBinary::readStringFromTable(StringRef &Result,
+                                               size_t *RetIdx) {
+  size_t Idx;
+  if (sampleprof_error E = readStringIndex(NameTable, Idx))
+    return E;
 
   // Lazy loading, if the string has not been materialized from memory storing
   // MD5 values, then it is default initialized with the null pointer. This can
   // only happen when using fixed length MD5, that bounds check is performed
   // while parsing the name table to ensure MD5NameMemStart points to an array
   // with enough MD5 entries.
-  StringRef &SR = NameTable[*Idx];
+  StringRef &SR = NameTable[Idx];
   if (!SR.data()) {
     assert(MD5NameMemStart);
     using namespace support;
     uint64_t FID = endian::read<uint64_t, little, unaligned>(
-       MD5NameMemStart + (*Idx) * sizeof(uint64_t));
+       MD5NameMemStart + (Idx) * sizeof(uint64_t));
     SR = MD5StringBuf.emplace_back(std::to_string(FID));
   }
   if (RetIdx)
-    *RetIdx = *Idx;
-  return SR;
+    *RetIdx = Idx;
+  Result = SR;
+  return sampleprof_error::success;
 }
 
-ErrorOr<SampleContextFrames>
-SampleProfileReaderBinary::readContextFromTable(size_t *RetIdx) {
-  auto ContextIdx = readNumber<size_t>();
-  if (std::error_code EC = ContextIdx.getError())
-    return EC;
-  if (*ContextIdx >= CSNameTable.size())
+sampleprof_error
+SampleProfileReaderBinary::readContextFromTable(SampleContextFrames &Result,
+                                                size_t *RetIdx) {
+  size_t ContextIdx;
+  if (sampleprof_error E = readNumber(ContextIdx))
+    return E;
+  if (ContextIdx >= CSNameTable.size())
     return sampleprof_error::truncated_name_table;
   if (RetIdx)
-    *RetIdx = *ContextIdx;
-  return CSNameTable[*ContextIdx];
+    *RetIdx = ContextIdx;
+  Result = CSNameTable[ContextIdx];
+  return sampleprof_error::success;
 }
 
-ErrorOr<std::pair<SampleContext, uint64_t>>
-SampleProfileReaderBinary::readSampleContextFromTable() {
-  SampleContext Context;
+sampleprof_error
+SampleProfileReaderBinary::readSampleContextFromTable(SampleContext &Result,
+                                                      uint64_t &Hash) {
   size_t Idx;
   if (ProfileIsCS) {
-    auto FContext(readContextFromTable(&Idx));
-    if (std::error_code EC = FContext.getError())
-      return EC;
-    Context = SampleContext(*FContext);
+    SampleContextFrames FContext;
+    if (sampleprof_error E = readContextFromTable(FContext, &Idx))
+      return E;
+    Result = SampleContext(FContext);
   } else {
-    auto FName(readStringFromTable(&Idx));
-    if (std::error_code EC = FName.getError())
-      return EC;
-    Context = SampleContext(*FName);
+    StringRef FName;
+    if (sampleprof_error E = readStringFromTable(FName, &Idx))
+      return E;
+    Result = SampleContext(FName);
   }
+
   // Since MD5SampleContextStart may point to the profile's file data, need to
   // make sure it is reading the same value on big endian CPU.
-  uint64_t Hash = support::endian::read64le(MD5SampleContextStart + Idx);
+  Hash = support::endian::read64le(MD5SampleContextStart + Idx);
   // Lazy computing of hash value, write back to the table to cache it. Only
   // compute the context's hash value if it is being referenced for the first
   // time.
   if (Hash == 0) {
     assert(MD5SampleContextStart == MD5SampleContextTable.data());
-    Hash = Context.getHashCode();
+    Hash = Result.getHashCode();
     support::endian::write64le(&MD5SampleContextTable[Idx], Hash);
   }
-  return std::make_pair(Context, Hash);
+  return sampleprof_error::success;
 }
 
-std::error_code
+sampleprof_error
 SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
-  auto NumSamples = readNumber<uint64_t>();
-  if (std::error_code EC = NumSamples.getError())
-    return EC;
-  FProfile.addTotalSamples(*NumSamples);
+  uint64_t NumSamples;
+  if (sampleprof_error E = readNumber(NumSamples))
+    return E;
+  FProfile.addTotalSamples(NumSamples);
 
   // Read the samples in the body.
-  auto NumRecords = readNumber<uint32_t>();
-  if (std::error_code EC = NumRecords.getError())
-    return EC;
+  uint32_t NumRecords;
+  if (sampleprof_error E = readNumber(NumRecords))
+    return E;
 
-  for (uint32_t I = 0; I < *NumRecords; ++I) {
-    auto LineOffset = readNumber<uint64_t>();
-    if (std::error_code EC = LineOffset.getError())
-      return EC;
+  for (uint32_t I = 0; I < NumRecords; ++I) {
+    uint64_t LineOffset;
+    if (sampleprof_error E = readNumber(LineOffset))
+      return E;
 
-    if (!isOffsetLegal(*LineOffset)) {
-      return std::error_code();
+    if (!isOffsetLegal(LineOffset)) {
+      return sampleprof_error::malformed;
     }
 
-    auto Discriminator = readNumber<uint64_t>();
-    if (std::error_code EC = Discriminator.getError())
-      return EC;
+    uint64_t Discriminator;
+    if (sampleprof_error E = readNumber(Discriminator))
+      return E;
 
-    auto NumSamples = readNumber<uint64_t>();
-    if (std::error_code EC = NumSamples.getError())
-      return EC;
+    uint64_t NumSamples;
+    if (sampleprof_error E = readNumber(NumSamples))
+      return E;
 
-    auto NumCalls = readNumber<uint32_t>();
-    if (std::error_code EC = NumCalls.getError())
-      return EC;
+    uint32_t NumCalls;
+    if (sampleprof_error E = readNumber(NumCalls))
+      return E;
 
     // Here we handle FS discriminators:
-    uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
+    uint32_t DiscriminatorVal = Discriminator & getDiscriminatorMask();
 
-    for (uint32_t J = 0; J < *NumCalls; ++J) {
-      auto CalledFunction(readStringFromTable());
-      if (std::error_code EC = CalledFunction.getError())
-        return EC;
+    for (uint32_t J = 0; J < NumCalls; ++J) {
+      StringRef CalledFunction;
+      if (sampleprof_error E = readStringFromTable(CalledFunction))
+        return E;
 
-      auto CalledFunctionSamples = readNumber<uint64_t>();
-      if (std::error_code EC = CalledFunctionSamples.getError())
-        return EC;
+      uint64_t CalledFunctionSamples;
+      if (sampleprof_error E = readNumber(CalledFunctionSamples))
+        return E;
 
-      FProfile.addCalledTargetSamples(*LineOffset, DiscriminatorVal,
-                                      *CalledFunction, *CalledFunctionSamples);
+      FProfile.addCalledTargetSamples(LineOffset, DiscriminatorVal,
+                                      CalledFunction, CalledFunctionSamples);
     }
 
-    FProfile.addBodySamples(*LineOffset, DiscriminatorVal, *NumSamples);
+    FProfile.addBodySamples(LineOffset, DiscriminatorVal, NumSamples);
   }
 
   // Read all the samples for inlined function calls.
-  auto NumCallsites = readNumber<uint32_t>();
-  if (std::error_code EC = NumCallsites.getError())
-    return EC;
+  uint32_t NumCallsites;
+  if (sampleprof_error E = readNumber(NumCallsites))
+    return E;
 
-  for (uint32_t J = 0; J < *NumCallsites; ++J) {
-    auto LineOffset = readNumber<uint64_t>();
-    if (std::error_code EC = LineOffset.getError())
-      return EC;
+  for (uint32_t J = 0; J < NumCallsites; ++J) {
+    uint64_t LineOffset;
+    if (sampleprof_error E = readNumber(LineOffset))
+      return E;
 
-    auto Discriminator = readNumber<uint64_t>();
-    if (std::error_code EC = Discriminator.getError())
-      return EC;
+    uint64_t Discriminator;
+    if (sampleprof_error E = readNumber(Discriminator))
+      return E;
 
-    auto FName(readStringFromTable());
-    if (std::error_code EC = FName.getError())
-      return EC;
+    StringRef FName;
+    if (sampleprof_error E = readStringFromTable(FName))
+      return E;
 
     // Here we handle FS discriminators:
-    uint32_t DiscriminatorVal = (*Discriminator) & getDiscriminatorMask();
+    uint32_t DiscriminatorVal = Discriminator & getDiscriminatorMask();
 
     FunctionSamples &CalleeProfile = FProfile.functionSamplesAt(
-        LineLocation(*LineOffset, DiscriminatorVal))[std::string(*FName)];
-    CalleeProfile.setName(*FName);
-    if (std::error_code EC = readProfile(CalleeProfile))
-      return EC;
+        LineLocation(LineOffset, DiscriminatorVal))[std::string(FName)];
+    CalleeProfile.setName(FName);
+    if (sampleprof_error E = readProfile(CalleeProfile))
+      return E;
   }
 
   return sampleprof_error::success;
 }
 
-std::error_code
-SampleProfileReaderBinary::readFuncProfile(const uint8_t *Start) {
+sampleprof_error SampleProfileReaderBinary::readFuncProfile(const uint8_t *Start) {
   Data = Start;
-  auto NumHeadSamples = readNumber<uint64_t>();
-  if (std::error_code EC = NumHeadSamples.getError())
-    return EC;
+  uint64_t NumHeadSamples;
+  if (sampleprof_error E = readNumber(NumHeadSamples))
+    return E;
 
-  auto FContextHash(readSampleContextFromTable());
-  if (std::error_code EC = FContextHash.getError())
-    return EC;
+  SampleContext FContext;
+  uint64_t Hash;
+  if (sampleprof_error E = readSampleContextFromTable(FContext, Hash))
+    return E;
 
-  auto &[FContext, Hash] = *FContextHash;
   // Use the cached hash value for insertion instead of recalculating it.
   auto Res = Profiles.try_emplace(Hash, FContext, FunctionSamples());
   FunctionSamples &FProfile = Res.first->second;
   FProfile.setContext(FContext);
-  FProfile.addHeadSamples(*NumHeadSamples);
+  FProfile.addHeadSamples(NumHeadSamples);
 
   if (FContext.hasContext())
     CSProfileCount++;
 
-  if (std::error_code EC = readProfile(FProfile))
-    return EC;
+  if (sampleprof_error E = readProfile(FProfile))
+    return E;
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderBinary::readImpl() {
+sampleprof_error SampleProfileReaderBinary::readImpl() {
   ProfileIsFS = ProfileIsFSDisciminator;
   FunctionSamples::ProfileIsFS = ProfileIsFS;
   while (Data < End) {
-    if (std::error_code EC = readFuncProfile(Data))
-      return EC;
+    if (sampleprof_error E = readFuncProfile(Data))
+      return E;
   }
 
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
+sampleprof_error SampleProfileReaderExtBinaryBase::readOneSection(
     const uint8_t *Start, uint64_t Size, const SecHdrTableEntry &Entry) {
   Data = Start;
   End = Start + Size;
   switch (Entry.Type) {
   case SecProfSummary:
-    if (std::error_code EC = readSummary())
-      return EC;
+    if (sampleprof_error E = readSummary())
+      return E;
     if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagPartial))
       Summary->setPartialProfile(true);
     if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagFullContext))
@@ -727,18 +736,18 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
     ProfileIsMD5 = ProfileIsMD5 || UseMD5;
     FunctionSamples::HasUniqSuffix =
         hasSecFlag(Entry, SecNameTableFlags::SecFlagUniqSuffix);
-    if (std::error_code EC = readNameTableSec(UseMD5, FixedLengthMD5))
-      return EC;
+    if (sampleprof_error E = readNameTableSec(UseMD5, FixedLengthMD5))
+      return E;
     break;
   }
   case SecCSNameTable: {
-    if (std::error_code EC = readCSNameTableSec())
-      return EC;
+    if (sampleprof_error E = readCSNameTableSec())
+      return E;
     break;
   }
   case SecLBRProfile:
-    if (std::error_code EC = readFuncProfiles())
-      return EC;
+    if (sampleprof_error E = readFuncProfiles())
+      return E;
     break;
   case SecFuncOffsetTable:
     // If module is absent, we are using LLVM tools, and need to read all
@@ -749,8 +758,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
       assert((!ProfileIsCS ||
               hasSecFlag(Entry, SecFuncOffsetFlags::SecFlagOrdered)) &&
              "func offset table should always be sorted in CS profile");
-      if (std::error_code EC = readFuncOffsetTable())
-        return EC;
+      if (sampleprof_error E = readFuncOffsetTable())
+        return E;
     }
     break;
   case SecFuncMetadata: {
@@ -759,17 +768,17 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection(
     FunctionSamples::ProfileIsProbeBased = ProfileIsProbeBased;
     bool HasAttribute =
         hasSecFlag(Entry, SecFuncMetadataFlags::SecFlagHasAttribute);
-    if (std::error_code EC = readFuncMetadata(HasAttribute))
-      return EC;
+    if (sampleprof_error E = readFuncMetadata(HasAttribute))
+      return E;
     break;
   }
   case SecProfileSymbolList:
-    if (std::error_code EC = readProfileSymbolList())
-      return EC;
+    if (sampleprof_error E = readProfileSymbolList())
+      return E;
     break;
   default:
-    if (std::error_code EC = readCustomSection(Entry))
-      return EC;
+    if (sampleprof_error E = readCustomSection(Entry))
+      return E;
     break;
   }
   return sampleprof_error::success;
@@ -813,44 +822,44 @@ bool SampleProfileReaderExtBinaryBase::collectFuncsFromModule() {
   return true;
 }
 
-std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() {
+sampleprof_error SampleProfileReaderExtBinaryBase::readFuncOffsetTable() {
   // If there are more than one function offset section, the profile associated
   // with the previous section has to be done reading before next one is read.
   FuncOffsetTable.clear();
   FuncOffsetList.clear();
 
-  auto Size = readNumber<uint64_t>();
-  if (std::error_code EC = Size.getError())
-    return EC;
+  uint64_t Size;
+  if (sampleprof_error E = readNumber(Size))
+    return E;
 
   bool UseFuncOffsetList = useFuncOffsetList();
   if (UseFuncOffsetList)
-    FuncOffsetList.reserve(*Size);
+    FuncOffsetList.reserve(Size);
   else
-    FuncOffsetTable.reserve(*Size);
+    FuncOffsetTable.reserve(Size);
 
-  for (uint64_t I = 0; I < *Size; ++I) {
-    auto FContextHash(readSampleContextFromTable());
-    if (std::error_code EC = FContextHash.getError())
-      return EC;
+  for (uint64_t I = 0; I < Size; ++I) {
+    SampleContext FContext;
+    uint64_t Hash;
+    if (sampleprof_error E = readSampleContextFromTable(FContext, Hash))
+      return E;
 
-    auto &[FContext, Hash] = *FContextHash;
-    auto Offset = readNumber<uint64_t>();
-    if (std::error_code EC = Offset.getError())
-      return EC;
+    uint64_t Offset;
+    if (sampleprof_error E = readNumber(Offset))
+      return E;
 
     if (UseFuncOffsetList)
-      FuncOffsetList.emplace_back(FContext, *Offset);
+      FuncOffsetList.emplace_back(FContext, Offset);
     else
       // Because Porfiles replace existing value with new value if collision
       // happens, we also use the latest offset so that they are consistent.
-      FuncOffsetTable[Hash] = *Offset;
+      FuncOffsetTable[Hash] = Offset;
  }
 
  return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
+sampleprof_error SampleProfileReaderExtBinaryBase::readFuncProfiles() {
   // Collect functions used by current module if the Reader has been
   // given a module.
   // collectFuncsFromModule uses FunctionSamples::getCanonicalFnName
@@ -864,8 +873,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
   const uint8_t *Start = Data;
   if (!LoadFuncsToBeUsed) {
     while (Data < End) {
-      if (std::error_code EC = readFuncProfile(Data))
-        return EC;
+      if (sampleprof_error E = readFuncProfile(Data))
+        return E;
     }
     assert(Data == End && "More data is read than expected");
   } else {
@@ -910,8 +919,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
           // Load profile for the current context which originated from
           // the common ancestor.
           const uint8_t *FuncProfileAddr = Start + NameOffset.second;
-          if (std::error_code EC = readFuncProfile(FuncProfileAddr))
-            return EC;
+          if (sampleprof_error E = readFuncProfile(FuncProfileAddr))
+            return E;
         }
       }
     } else if (useMD5()) {
@@ -922,8 +931,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
         if (iter == FuncOffsetTable.end())
           continue;
         const uint8_t *FuncProfileAddr = Start + iter->second;
-        if (std::error_code EC = readFuncProfile(FuncProfileAddr))
-          return EC;
+        if (sampleprof_error E = readFuncProfile(FuncProfileAddr))
+          return E;
       }
     } else if (Remapper) {
       assert(useFuncOffsetList());
@@ -933,8 +942,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
         if (!FuncsToUse.count(FuncName) && !Remapper->exist(FuncName))
           continue;
         const uint8_t *FuncProfileAddr = Start + NameOffset.second;
-        if (std::error_code EC = readFuncProfile(FuncProfileAddr))
-          return EC;
+        if (sampleprof_error E = readFuncProfile(FuncProfileAddr))
+          return E;
       }
     } else {
       assert(!useFuncOffsetList());
@@ -943,8 +952,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
         if (iter == FuncOffsetTable.end())
           continue;
         const uint8_t *FuncProfileAddr = Start + iter->second;
-        if (std::error_code EC = readFuncProfile(FuncProfileAddr))
-          return EC;
+        if (sampleprof_error E = readFuncProfile(FuncProfileAddr))
+          return E;
       }
     }
     Data = End;
@@ -956,37 +965,37 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() {
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderExtBinaryBase::readProfileSymbolList() {
+sampleprof_error SampleProfileReaderExtBinaryBase::readProfileSymbolList() {
   if (!ProfSymList)
     ProfSymList = std::make_unique<ProfileSymbolList>();
 
   if (std::error_code EC = ProfSymList->read(Data, End - Data))
-    return EC;
+    return (sampleprof_error) EC.value();
 
   Data = End;
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderExtBinaryBase::decompressSection(
+sampleprof_error SampleProfileReaderExtBinaryBase::decompressSection(
     const uint8_t *SecStart, const uint64_t SecSize,
     const uint8_t *&DecompressBuf, uint64_t &DecompressBufSize) {
   Data = SecStart;
   End = SecStart + SecSize;
-  auto DecompressSize = readNumber<uint64_t>();
-  if (std::error_code EC = DecompressSize.getError())
-    return EC;
-  DecompressBufSize = *DecompressSize;
+  uint64_t DecompressSize;
+  if (sampleprof_error E = readNumber(DecompressSize))
+    return E;
+  DecompressBufSize = DecompressSize;
 
-  auto CompressSize = readNumber<uint64_t>();
-  if (std::error_code EC = CompressSize.getError())
-    return EC;
+  uint64_t CompressSize;
+  if (sampleprof_error E = readNumber(CompressSize))
+    return E;
 
   if (!llvm::compression::zlib::isAvailable())
     return sampleprof_error::zlib_unavailable;
 
   uint8_t *Buffer = Allocator.Allocate<uint8_t>(DecompressBufSize);
   size_t UCSize = DecompressBufSize;
-  llvm::Error E = compression::zlib::decompress(ArrayRef(Data, *CompressSize),
+  llvm::Error E = compression::zlib::decompress(ArrayRef(Data, CompressSize),
                                                 Buffer, UCSize);
   if (E)
     return sampleprof_error::uncompress_failed;
@@ -994,7 +1003,7 @@ std::error_code SampleProfileReaderExtBinaryBase::decompressSection(
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderExtBinaryBase::readImpl() {
+sampleprof_error SampleProfileReaderExtBinaryBase::readImpl() {
   const uint8_t *BufStart =
       reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
 
@@ -1018,15 +1027,15 @@ std::error_code SampleProfileReaderExtBinaryBase::readImpl() {
     if (isCompressed) {
       const uint8_t *DecompressBuf;
       uint64_t DecompressBufSize;
-      if (std::error_code EC = decompressSection(
+      if (sampleprof_error E = decompressSection(
               SecStart, SecSize, DecompressBuf, DecompressBufSize))
-        return EC;
+        return E;
       SecStart = DecompressBuf;
       SecSize = DecompressBufSize;
     }
 
-    if (std::error_code EC = readOneSection(SecStart, SecSize, Entry))
-      return EC;
+    if (sampleprof_error E = readOneSection(SecStart, SecSize, Entry))
+      return E;
     if (Data != SecStart + SecSize)
       return sampleprof_error::malformed;
 
@@ -1040,22 +1049,22 @@ std::error_code SampleProfileReaderExtBinaryBase::readImpl() {
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderRawBinary::verifySPMagic(uint64_t Magic) {
+sampleprof_error SampleProfileReaderRawBinary::verifySPMagic(uint64_t Magic) {
   if (Magic == SPMagic())
     return sampleprof_error::success;
   return sampleprof_error::bad_magic;
 }
 
-std::error_code SampleProfileReaderExtBinary::verifySPMagic(uint64_t Magic) {
+sampleprof_error SampleProfileReaderExtBinary::verifySPMagic(uint64_t Magic) {
   if (Magic == SPMagic(SPF_Ext_Binary))
     return sampleprof_error::success;
   return sampleprof_error::bad_magic;
 }
 
-std::error_code SampleProfileReaderBinary::readNameTable() {
-  auto Size = readNumber<size_t>();
-  if (std::error_code EC = Size.getError())
-    return EC;
+sampleprof_error SampleProfileReaderBinary::readNameTable() {
+  size_t Size;
+  if (sampleprof_error E = readNumber(Size))
+    return E;
 
   // Normally if useMD5 is true, the name table should have MD5 values, not
   // strings, however in the case that ExtBinary profile has multiple name
@@ -1063,85 +1072,84 @@ std::error_code SampleProfileReaderBinary::readNameTable() {
   // because optimization passes can only handle either type.
   bool UseMD5 = useMD5();
   if (UseMD5)
-    MD5StringBuf.reserve(MD5StringBuf.size() + *Size);
+    MD5StringBuf.reserve(MD5StringBuf.size() + Size);
 
   NameTable.clear();
-  NameTable.reserve(*Size);
+  NameTable.reserve(Size);
   if (!ProfileIsCS) {
     MD5SampleContextTable.clear();
     if (UseMD5)
-      MD5SampleContextTable.reserve(*Size);
+      MD5SampleContextTable.reserve(Size);
     else
       // If we are using strings, delay MD5 computation since only a portion of
       // names are used by top level functions. Use 0 to indicate MD5 value is
       // to be calculated as no known string has a MD5 value of 0.
-      MD5SampleContextTable.resize(*Size);
+      MD5SampleContextTable.resize(Size);
   }
-  for (size_t I = 0; I < *Size; ++I) {
-    auto Name(readString());
-    if (std::error_code EC = Name.getError())
-      return EC;
+  for (size_t I = 0; I < Size; ++I) {
+    StringRef Name;
+    if (sampleprof_error E = readString(Name))
+      return E;
     if (UseMD5) {
-      uint64_t FID = hashFuncName(*Name);
+      uint64_t FID = hashFuncName(Name);
       if (!ProfileIsCS)
         MD5SampleContextTable.emplace_back(FID);
       NameTable.emplace_back(MD5StringBuf.emplace_back(std::to_string(FID)));
     } else
-      NameTable.push_back(*Name);
+      NameTable.push_back(Name);
   }
   if (!ProfileIsCS)
     MD5SampleContextStart = MD5SampleContextTable.data();
   return sampleprof_error::success;
 }
 
-std::error_code
-SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5,
+sampleprof_error SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5,
                                                    bool FixedLengthMD5) {
   if (FixedLengthMD5) {
     if (!IsMD5)
       errs() << "If FixedLengthMD5 is true, UseMD5 has to be true";
-    auto Size = readNumber<size_t>();
-    if (std::error_code EC = Size.getError())
-      return EC;
+    size_t Size;
+    if (sampleprof_error E = readNumber(Size))
+      return E;
 
-    assert(Data + (*Size) * sizeof(uint64_t) == End &&
+    assert(Data + Size * sizeof(uint64_t) == End &&
            "Fixed length MD5 name table does not contain specified number of "
            "entries");
-    if (Data + (*Size) * sizeof(uint64_t) > End)
+    if (Data + Size * sizeof(uint64_t) > End)
       return sampleprof_error::truncated;
 
     // Preallocate and initialize NameTable so we can check whether a name
     // index has been read before by checking whether the element in the
     // NameTable is empty, meanwhile readStringIndex can do the boundary
     // check using the size of NameTable.
-    MD5StringBuf.reserve(MD5StringBuf.size() + *Size);
+    MD5StringBuf.reserve(MD5StringBuf.size() + Size);
     NameTable.clear();
-    NameTable.resize(*Size);
+    NameTable.resize(Size);
     MD5NameMemStart = Data;
     if (!ProfileIsCS)
       MD5SampleContextStart = reinterpret_cast<const uint64_t *>(Data);
-    Data = Data + (*Size) * sizeof(uint64_t);
+    Data = Data + Size * sizeof(uint64_t);
     return sampleprof_error::success;
   }
 
   if (IsMD5) {
     assert(!FixedLengthMD5 && "FixedLengthMD5 should be unreachable here");
-    auto Size = readNumber<size_t>();
-    if (std::error_code EC = Size.getError())
-      return EC;
+    size_t Size;
+    if (sampleprof_error E = readNumber(Size))
+      return E;
 
-    MD5StringBuf.reserve(MD5StringBuf.size() + *Size);
+    MD5StringBuf.reserve(MD5StringBuf.size() + Size);
     NameTable.clear();
-    NameTable.reserve(*Size);
+    NameTable.reserve(Size);
     if (!ProfileIsCS)
-      MD5SampleContextTable.resize(*Size);
-    for (size_t I = 0; I < *Size; ++I) {
-      auto FID = readNumber<uint64_t>();
-      if (std::error_code EC = FID.getError())
-        return EC;
+      MD5SampleContextTable.resize(Size);
+    for (size_t I = 0; I < Size; ++I) {
+      uint64_t FID;
+      if (sampleprof_error E = readNumber(FID))
+        return E;
       if (!ProfileIsCS)
-        support::endian::write64le(&MD5SampleContextTable[I], *FID);
-      NameTable.emplace_back(MD5StringBuf.emplace_back(std::to_string(*FID)));
+        support::endian::write64le(&MD5SampleContextTable[I], FID);
+      NameTable.emplace_back(MD5StringBuf.emplace_back(std::to_string(FID)));
     }
     if (!ProfileIsCS)
       MD5SampleContextStart = MD5SampleContextTable.data();
@@ -1155,99 +1163,98 @@ SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5,
 // vectors. Each element of a context vector, aka a frame, refers to the
 // underlying raw function names that are stored in the name table, as well as
 // a callsite identifier that only makes sense for non-leaf frames.
-std::error_code SampleProfileReaderExtBinaryBase::readCSNameTableSec() {
-  auto Size = readNumber<size_t>();
-  if (std::error_code EC = Size.getError())
-    return EC;
+sampleprof_error SampleProfileReaderExtBinaryBase::readCSNameTableSec() {
+  size_t Size;
+  if (sampleprof_error E = readNumber(Size))
+    return E;
 
   CSNameTable.clear();
-  CSNameTable.reserve(*Size);
+  CSNameTable.reserve(Size);
   if (ProfileIsCS) {
     // Delay MD5 computation of CS context until they are needed. Use 0 to
     // indicate MD5 value is to be calculated as no known string has a MD5
     // value of 0.
     MD5SampleContextTable.clear();
-    MD5SampleContextTable.resize(*Size);
+    MD5SampleContextTable.resize(Size);
     MD5SampleContextStart = MD5SampleContextTable.data();
   }
-  for (size_t I = 0; I < *Size; ++I) {
+  for (size_t I = 0; I < Size; ++I) {
     CSNameTable.emplace_back(SampleContextFrameVector());
-    auto ContextSize = readNumber<uint32_t>();
-    if (std::error_code EC = ContextSize.getError())
-      return EC;
-    for (uint32_t J = 0; J < *ContextSize; ++J) {
-      auto FName(readStringFromTable());
-      if (std::error_code EC = FName.getError())
-        return EC;
-      auto LineOffset = readNumber<uint64_t>();
-      if (std::error_code EC = LineOffset.getError())
-        return EC;
-
-      if (!isOffsetLegal(*LineOffset))
-        return std::error_code();
-
-      auto Discriminator = readNumber<uint64_t>();
-      if (std::error_code EC = Discriminator.getError())
-        return EC;
-
-      CSNameTable.back().emplace_back(
-          FName.get(), LineLocation(LineOffset.get(), Discriminator.get()));
+    uint32_t ContextSize;
+    if (sampleprof_error E = readNumber(ContextSize))
+      return E;
+    for (uint32_t J = 0; J < ContextSize; ++J) {
+      StringRef FName;
+      if (sampleprof_error E = readStringFromTable(FName))
+        return E;
+      uint64_t LineOffset;
+      if (sampleprof_error E = readNumber(LineOffset))
+        return E;
+
+      if (!isOffsetLegal(LineOffset))
+        return sampleprof_error::malformed;
+
+      uint64_t Discriminator;
+      if (sampleprof_error E = readNumber(Discriminator))
+        return E;
+
+      CSNameTable.back().emplace_back(FName,
+                                      LineLocation(LineOffset, Discriminator));
     }
   }
 
   return sampleprof_error::success;
 }
 
-std::error_code
-SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute,
+sampleprof_error SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute,
                                                    FunctionSamples *FProfile) {
   if (Data < End) {
     if (ProfileIsProbeBased) {
-      auto Checksum = readNumber<uint64_t>();
-      if (std::error_code EC = Checksum.getError())
-        return EC;
+      uint64_t Checksum;
+      if (sampleprof_error E = readNumber(Checksum))
+        return E;
       if (FProfile)
-        FProfile->setFunctionHash(*Checksum);
+        FProfile->setFunctionHash(Checksum);
     }
 
     if (ProfileHasAttribute) {
-      auto Attributes = readNumber<uint32_t>();
-      if (std::error_code EC = Attributes.getError())
-        return EC;
+      uint32_t Attributes;
+      if (sampleprof_error E = readNumber(Attributes))
+        return E;
       if (FProfile)
-        FProfile->getContext().setAllAttributes(*Attributes);
+        FProfile->getContext().setAllAttributes(Attributes);
     }
 
     if (!ProfileIsCS) {
       // Read all the attributes for inlined function calls.
-      auto NumCallsites = readNumber<uint32_t>();
-      if (std::error_code EC = NumCallsites.getError())
-        return EC;
+      uint32_t NumCallsites;
+      if (sampleprof_error E = readNumber(NumCallsites))
+        return E;
 
-      for (uint32_t J = 0; J < *NumCallsites; ++J) {
-        auto LineOffset = readNumber<uint64_t>();
-        if (std::error_code EC = LineOffset.getError())
-          return EC;
+      for (uint32_t J = 0; J < NumCallsites; ++J) {
+        uint64_t LineOffset;
+        if (sampleprof_error E = readNumber(LineOffset))
+          return E;
 
-        auto Discriminator = readNumber<uint64_t>();
-        if (std::error_code EC = Discriminator.getError())
-          return EC;
+        uint64_t Discriminator;
+        if (sampleprof_error E = readNumber(Discriminator))
+          return E;
 
-        auto FContextHash(readSampleContextFromTable());
-        if (std::error_code EC = FContextHash.getError())
-          return EC;
+        SampleContext FContext;
+        uint64_t Hash;
+        if (sampleprof_error E = readSampleContextFromTable(FContext, Hash))
+          return E;
 
-        auto &[FContext, Hash] = *FContextHash;
         FunctionSamples *CalleeProfile = nullptr;
         if (FProfile) {
           CalleeProfile = const_cast<FunctionSamples *>(
               &FProfile->functionSamplesAt(LineLocation(
-                  *LineOffset,
-                  *Discriminator))[std::string(FContext.getName())]);
+                  LineOffset,
+                  Discriminator))[std::string(FContext.getName())]);
         }
-        if (std::error_code EC =
+        if (sampleprof_error E =
                 readFuncMetadata(ProfileHasAttribute, CalleeProfile))
-          return EC;
+          return E;
       }
     }
   }
@@ -1255,77 +1262,77 @@ SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute,
   return sampleprof_error::success;
 }
 
-std::error_code
+sampleprof_error
 SampleProfileReaderExtBinaryBase::readFuncMetadata(bool ProfileHasAttribute) {
   while (Data < End) {
-    auto FContextHash(readSampleContextFromTable());
-    if (std::error_code EC = FContextHash.getError())
-      return EC;
-    auto &[FContext, Hash] = *FContextHash;
+    SampleContext FContext;
+    uint64_t Hash;
+    if (sampleprof_error E = readSampleContextFromTable(FContext, Hash))
+      return E;
     FunctionSamples *FProfile = nullptr;
     auto It = Profiles.find(FContext);
     if (It != Profiles.end())
       FProfile = &It->second;
 
-    if (std::error_code EC = readFuncMetadata(ProfileHasAttribute, FProfile))
-      return EC;
+    if (sampleprof_error E = readFuncMetadata(ProfileHasAttribute, FProfile))
+      return E;
   }
 
   assert(Data == End && "More data is read than expected");
   return sampleprof_error::success;
 }
 
-std::error_code
+sampleprof_error
 SampleProfileReaderExtBinaryBase::readSecHdrTableEntry(uint64_t Idx) {
   SecHdrTableEntry Entry;
-  auto Type = readUnencodedNumber<uint64_t>();
-  if (std::error_code EC = Type.getError())
-    return EC;
-  Entry.Type = static_cast<SecType>(*Type);
-
-  auto Flags = readUnencodedNumber<uint64_t>();
-  if (std::error_code EC = Flags.getError())
-    return EC;
-  Entry.Flags = *Flags;
-
-  auto Offset = readUnencodedNumber<uint64_t>();
-  if (std::error_code EC = Offset.getError())
-    return EC;
-  Entry.Offset = *Offset;
-
-  auto Size = readUnencodedNumber<uint64_t>();
-  if (std::error_code EC = Size.getError())
-    return EC;
-  Entry.Size = *Size;
+  uint64_t Type;;
+  if (sampleprof_error E = readUnencodedNumber(Type))
+    return E;
+  Entry.Type = static_cast<SecType>(Type);
+
+  uint64_t Flags;
+  if (sampleprof_error E = readUnencodedNumber(Flags))
+    return E;
+  Entry.Flags = Flags;
+
+  uint64_t Offset;
+  if (sampleprof_error E = readUnencodedNumber(Offset))
+    return E;
+  Entry.Offset = Offset;
+
+  uint64_t Size;;
+  if (sampleprof_error E = readUnencodedNumber(Size))
+    return E;
+  Entry.Size = Size;
 
   Entry.LayoutIndex = Idx;
   SecHdrTable.push_back(std::move(Entry));
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderExtBinaryBase::readSecHdrTable() {
-  auto EntryNum = readUnencodedNumber<uint64_t>();
-  if (std::error_code EC = EntryNum.getError())
-    return EC;
+sampleprof_error SampleProfileReaderExtBinaryBase::readSecHdrTable() {
+  uint64_t EntryNum;
+  if (sampleprof_error E = readUnencodedNumber(EntryNum))
+    return E;
 
-  for (uint64_t i = 0; i < (*EntryNum); i++)
-    if (std::error_code EC = readSecHdrTableEntry(i))
-      return EC;
+  for (uint64_t i = 0; i < EntryNum; i++)
+    if (sampleprof_error E = readSecHdrTableEntry(i))
+      return E;
 
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderExtBinaryBase::readHeader() {
+sampleprof_error SampleProfileReaderExtBinaryBase::readHeader() {
   const uint8_t *BufStart =
       reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
   Data = BufStart;
   End = BufStart + Buffer->getBufferSize();
 
-  if (std::error_code EC = readMagicIdent())
-    return EC;
+  if (sampleprof_error E = readMagicIdent())
+    return E;
 
-  if (std::error_code EC = readSecHdrTable())
-    return EC;
+  if (sampleprof_error E = readSecHdrTable())
+    return E;
 
   return sampleprof_error::success;
 }
@@ -1421,91 +1428,90 @@ bool SampleProfileReaderExtBinaryBase::dumpSectionInfo(raw_ostream &OS) {
   return true;
 }
 
-std::error_code SampleProfileReaderBinary::readMagicIdent() {
+sampleprof_error SampleProfileReaderBinary::readMagicIdent() {
   // Read and check the magic identifier.
-  auto Magic = readNumber<uint64_t>();
-  if (std::error_code EC = Magic.getError())
-    return EC;
-  else if (std::error_code EC = verifySPMagic(*Magic))
-    return EC;
+  uint64_t Magic;
+  if (sampleprof_error E = readNumber(Magic))
+    return E;
+  else if (sampleprof_error E = verifySPMagic(Magic))
+    return E;
 
   // Read the version number.
-  auto Version = readNumber<uint64_t>();
-  if (std::error_code EC = Version.getError())
-    return EC;
-  else if (*Version != SPVersion())
+  uint64_t Version;
+  if (sampleprof_error E = readNumber(Version))
+    return E;
+  else if (Version != SPVersion())
     return sampleprof_error::unsupported_version;
 
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderBinary::readHeader() {
+sampleprof_error SampleProfileReaderBinary::readHeader() {
   Data = reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
   End = Data + Buffer->getBufferSize();
 
-  if (std::error_code EC = readMagicIdent())
-    return EC;
+  if (sampleprof_error E = readMagicIdent())
+    return E;
 
-  if (std::error_code EC = readSummary())
-    return EC;
+  if (sampleprof_error E = readSummary())
+    return E;
 
-  if (std::error_code EC = readNameTable())
-    return EC;
+  if (sampleprof_error E = readNameTable())
+    return E;
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderBinary::readSummaryEntry(
+sampleprof_error SampleProfileReaderBinary::readSummaryEntry(
     std::vector<ProfileSummaryEntry> &Entries) {
-  auto Cutoff = readNumber<uint64_t>();
-  if (std::error_code EC = Cutoff.getError())
-    return EC;
+  uint64_t Cutoff;
+  if (sampleprof_error E = readNumber(Cutoff))
+    return E;
 
-  auto MinBlockCount = readNumber<uint64_t>();
-  if (std::error_code EC = MinBlockCount.getError())
-    return EC;
+  uint64_t MinBlockCount;
+  if (sampleprof_error E = readNumber(MinBlockCount))
+    return E;
 
-  auto NumBlocks = readNumber<uint64_t>();
-  if (std::error_code EC = NumBlocks.getError())
-    return EC;
+  uint64_t NumBlocks;
+  if (sampleprof_error E = readNumber(NumBlocks))
+    return E;
 
-  Entries.emplace_back(*Cutoff, *MinBlockCount, *NumBlocks);
+  Entries.emplace_back(Cutoff, MinBlockCount, NumBlocks);
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderBinary::readSummary() {
-  auto TotalCount = readNumber<uint64_t>();
-  if (std::error_code EC = TotalCount.getError())
-    return EC;
+sampleprof_error SampleProfileReaderBinary::readSummary() {
+  uint64_t TotalCount;
+  if (sampleprof_error E = readNumber(TotalCount))
+    return E;
 
-  auto MaxBlockCount = readNumber<uint64_t>();
-  if (std::error_code EC = MaxBlockCount.getError())
-    return EC;
+  uint64_t MaxBlockCount;
+  if (sampleprof_error E = readNumber(MaxBlockCount))
+    return E;
 
-  auto MaxFunctionCount = readNumber<uint64_t>();
-  if (std::error_code EC = MaxFunctionCount.getError())
-    return EC;
+  uint64_t MaxFunctionCount;
+  if (sampleprof_error E = readNumber(MaxFunctionCount))
+    return E;
 
-  auto NumBlocks = readNumber<uint64_t>();
-  if (std::error_code EC = NumBlocks.getError())
-    return EC;
+  uint64_t NumBlocks;
+  if (sampleprof_error E = readNumber(NumBlocks))
+    return E;
 
-  auto NumFunctions = readNumber<uint64_t>();
-  if (std::error_code EC = NumFunctions.getError())
-    return EC;
+  uint64_t NumFunctions;
+  if (sampleprof_error E = readNumber(NumFunctions))
+    return E;
 
-  auto NumSummaryEntries = readNumber<uint64_t>();
-  if (std::error_code EC = NumSummaryEntries.getError())
-    return EC;
+  uint64_t NumSummaryEntries;
+  if (sampleprof_error E = readNumber(NumSummaryEntries))
+    return E;
 
   std::vector<ProfileSummaryEntry> Entries;
-  for (unsigned i = 0; i < *NumSummaryEntries; i++) {
-    std::error_code EC = readSummaryEntry(Entries);
-    if (EC != sampleprof_error::success)
-      return EC;
+  for (unsigned i = 0; i < NumSummaryEntries; i++) {
+    if (sampleprof_error E = readSummaryEntry(Entries))
+      return E;
   }
   Summary = std::make_unique<ProfileSummary>(
-      ProfileSummary::PSK_Sample, Entries, *TotalCount, *MaxBlockCount, 0,
-      *MaxFunctionCount, *NumBlocks, *NumFunctions);
+      ProfileSummary::PSK_Sample, Entries, TotalCount, MaxBlockCount, 0,
+      MaxFunctionCount, NumBlocks, NumFunctions);
 
   return sampleprof_error::success;
 }
@@ -1524,37 +1530,41 @@ bool SampleProfileReaderExtBinary::hasFormat(const MemoryBuffer &Buffer) {
   return Magic == SPMagic(SPF_Ext_Binary);
 }
 
-std::error_code SampleProfileReaderGCC::skipNextWord() {
+sampleprof_error SampleProfileReaderGCC::skipNextWord() {
   uint32_t dummy;
   if (!GcovBuffer.readInt(dummy))
     return sampleprof_error::truncated;
   return sampleprof_error::success;
 }
 
-template <typename T> ErrorOr<T> SampleProfileReaderGCC::readNumber() {
+template <typename T>
+sampleprof_error SampleProfileReaderGCC::readNumber(T &Result) {
   if (sizeof(T) <= sizeof(uint32_t)) {
     uint32_t Val;
-    if (GcovBuffer.readInt(Val) && Val <= std::numeric_limits<T>::max())
-      return static_cast<T>(Val);
+    if (GcovBuffer.readInt(Val) && Val <= std::numeric_limits<T>::max()) {
+      Result = static_cast<T>(Val);
+      return sampleprof_error::success;
+    }
   } else if (sizeof(T) <= sizeof(uint64_t)) {
     uint64_t Val;
-    if (GcovBuffer.readInt64(Val) && Val <= std::numeric_limits<T>::max())
-      return static_cast<T>(Val);
+    if (GcovBuffer.readInt64(Val) && Val <= std::numeric_limits<T>::max()) {
+      Result = static_cast<T>(Val);
+      return sampleprof_error::success;
+    }
   }
 
-  std::error_code EC = sampleprof_error::malformed;
-  reportError(0, EC.message());
-  return EC;
+  sampleprof_error E = sampleprof_error::malformed;
+  reportError(0, std::error_code(E).message());
+  return E;
 }
 
-ErrorOr<StringRef> SampleProfileReaderGCC::readString() {
-  StringRef Str;
-  if (!GcovBuffer.readString(Str))
+sampleprof_error SampleProfileReaderGCC::readString(StringRef &Result) {
+  if (!GcovBuffer.readString(Result))
     return sampleprof_error::truncated;
-  return Str;
+  return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderGCC::readHeader() {
+sampleprof_error SampleProfileReaderGCC::readHeader() {
   // Read the magic identifier.
   if (!GcovBuffer.readGCDAFormat())
     return sampleprof_error::unrecognized_format;
@@ -1569,13 +1579,13 @@ std::error_code SampleProfileReaderGCC::readHeader() {
     return sampleprof_error::unsupported_version;
 
   // Skip the empty integer.
-  if (std::error_code EC = skipNextWord())
-    return EC;
+  if (sampleprof_error E = skipNextWord())
+    return E;
 
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderGCC::readSectionTag(uint32_t Expected) {
+sampleprof_error SampleProfileReaderGCC::readSectionTag(uint32_t Expected) {
   uint32_t Tag;
   if (!GcovBuffer.readInt(Tag))
     return sampleprof_error::truncated;
@@ -1583,15 +1593,15 @@ std::error_code SampleProfileReaderGCC::readSectionTag(uint32_t Expected) {
   if (Tag != Expected)
     return sampleprof_error::malformed;
 
-  if (std::error_code EC = skipNextWord())
-    return EC;
+  if (sampleprof_error E = skipNextWord())
+    return E;
 
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderGCC::readNameTable() {
-  if (std::error_code EC = readSectionTag(GCOVTagAFDOFileNames))
-    return EC;
+sampleprof_error SampleProfileReaderGCC::readNameTable() {
+  if (sampleprof_error E = readSectionTag(GCOVTagAFDOFileNames))
+    return E;
 
   uint32_t Size;
   if (!GcovBuffer.readInt(Size))
@@ -1607,9 +1617,9 @@ std::error_code SampleProfileReaderGCC::readNameTable() {
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderGCC::readFunctionProfiles() {
-  if (std::error_code EC = readSectionTag(GCOVTagAFDOFunction))
-    return EC;
+sampleprof_error SampleProfileReaderGCC::readFunctionProfiles() {
+  if (sampleprof_error E = readSectionTag(GCOVTagAFDOFunction))
+    return E;
 
   uint32_t NumFunctions;
   if (!GcovBuffer.readInt(NumFunctions))
@@ -1617,14 +1627,14 @@ std::error_code SampleProfileReaderGCC::readFunctionProfiles() {
 
   InlineCallStack Stack;
   for (uint32_t I = 0; I < NumFunctions; ++I)
-    if (std::error_code EC = readOneFunctionProfile(Stack, true, 0))
-      return EC;
+    if (sampleprof_error E = readOneFunctionProfile(Stack, true, 0))
+      return E;
 
   computeSummary();
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
+sampleprof_error SampleProfileReaderGCC::readOneFunctionProfile(
     const InlineCallStack &InlineStack, bool Update, uint32_t Offset) {
   uint64_t HeadCount = 0;
   if (InlineStack.size() == 0)
@@ -1739,8 +1749,8 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
     InlineCallStack NewStack;
     NewStack.push_back(FProfile);
     llvm::append_range(NewStack, InlineStack);
-    if (std::error_code EC = readOneFunctionProfile(NewStack, Update, Offset))
-      return EC;
+    if (sampleprof_error E = readOneFunctionProfile(NewStack, Update, Offset))
+      return E;
   }
 
   return sampleprof_error::success;
@@ -1750,15 +1760,15 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
 ///
 /// This format is generated by the Linux Perf conversion tool at
 /// https://github.com/google/autofdo.
-std::error_code SampleProfileReaderGCC::readImpl() {
+sampleprof_error SampleProfileReaderGCC::readImpl() {
   assert(!ProfileIsFSDisciminator && "Gcc profiles not support FSDisciminator");
   // Read the string table.
-  if (std::error_code EC = readNameTable())
-    return EC;
+  if (sampleprof_error E = readNameTable())
+    return E;
 
   // Read the source profile.
-  if (std::error_code EC = readFunctionProfiles())
-    return EC;
+  if (sampleprof_error E = readFunctionProfiles())
+    return E;
 
   return sampleprof_error::success;
 }



More information about the llvm-commits mailing list