[llvm] Update for Code Coverage, Fixing Double Counts on Functions Compiled in Different Binaries and Merging of Conditional Compilation (PR #151771)

via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 1 14:04:27 PDT 2025


https://github.com/awearden updated https://github.com/llvm/llvm-project/pull/151771

>From 52d0d66504f992debfefecbde5dd1e852328f870 Mon Sep 17 00:00:00 2001
From: Andres Wearden <awearden at hu-awearden-lv.qualcomm.com>
Date: Tue, 1 Jul 2025 09:37:43 -0700
Subject: [PATCH 01/17] saving changes for llvm-cross arch feature

---
 llvm/include/llvm/ProfileData/InstrProf.h     | 207 ++++++++++--------
 .../llvm/ProfileData/InstrProfReader.h        |  55 +++--
 .../llvm/ProfileData/InstrProfWriter.h        |  85 ++++---
 llvm/lib/ProfileData/InstrProf.cpp            |  55 ++++-
 llvm/lib/ProfileData/InstrProfReader.cpp      |  42 +++-
 .../llvm-profdata-cross-arch/CMakeLists.txt   |  35 +++
 .../ELFSymbolReader.cpp                       |  90 ++++++++
 .../ELFSymbolReader.h                         |  31 +++
 .../llvm-profdata-cross-arch.cpp              | 112 ++++++++++
 llvm/tools/llvm-profdata/llvm-profdata.cpp    | 102 ++++++++-
 10 files changed, 643 insertions(+), 171 deletions(-)
 create mode 100644 llvm/tools/llvm-profdata-cross-arch/CMakeLists.txt
 create mode 100644 llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.cpp
 create mode 100644 llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.h
 create mode 100644 llvm/tools/llvm-profdata-cross-arch/llvm-profdata-cross-arch.cpp

diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index 544a59df43ed3..a786aadce6de1 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -69,18 +69,18 @@ struct PatchItem {
 // back patching.
 class ProfOStream {
 public:
-  ProfOStream(raw_fd_ostream &FD);
-  ProfOStream(raw_string_ostream &STR);
+  LLVM_ABI ProfOStream(raw_fd_ostream &FD);
+  LLVM_ABI ProfOStream(raw_string_ostream &STR);
 
-  [[nodiscard]] uint64_t tell() const;
-  void write(uint64_t V);
-  void write32(uint32_t V);
-  void writeByte(uint8_t V);
+  [[nodiscard]] LLVM_ABI uint64_t tell() const;
+  LLVM_ABI void write(uint64_t V);
+  LLVM_ABI void write32(uint32_t V);
+  LLVM_ABI void writeByte(uint8_t V);
 
   // \c patch can only be called when all data is written and flushed.
   // For raw_string_ostream, the patch is done on the target string
   // directly and it won't be reflected in the stream's internal buffer.
-  void patch(ArrayRef<PatchItem> P);
+  LLVM_ABI void patch(ArrayRef<PatchItem> P);
 
   // If \c OS is an instance of \c raw_fd_ostream, this field will be
   // true. Otherwise, \c OS will be an raw_string_ostream.
@@ -104,9 +104,9 @@ inline uint64_t getInstrMaxCountValue() {
 /// The name of the section depends on the object format type \p OF. If
 /// \p AddSegmentInfo is true, a segment prefix and additional linker hints may
 /// be added to the section name (this is the default).
-std::string getInstrProfSectionName(InstrProfSectKind IPSK,
-                                    Triple::ObjectFormatType OF,
-                                    bool AddSegmentInfo = true);
+LLVM_ABI std::string getInstrProfSectionName(InstrProfSectKind IPSK,
+                                             Triple::ObjectFormatType OF,
+                                             bool AddSegmentInfo = true);
 
 /// Return the name profile runtime entry point to do value profiling
 /// for a given site.
@@ -215,62 +215,64 @@ inline StringRef getInstrProfNameSeparator() { return "\01"; }
 
 /// Determines whether module targets a GPU eligable for PGO
 /// instrumentation
-bool isGPUProfTarget(const Module &M);
+LLVM_ABI bool isGPUProfTarget(const Module &M);
 
 /// Please use getIRPGOFuncName for LLVM IR instrumentation. This function is
 /// for front-end (Clang, etc) instrumentation.
 /// Return the modified name for function \c F suitable to be
 /// used the key for profile lookup. Variable \c InLTO indicates if this
 /// is called in LTO optimization passes.
-std::string getPGOFuncName(const Function &F, bool InLTO = false,
-                           uint64_t Version = INSTR_PROF_INDEX_VERSION);
+LLVM_ABI std::string
+getPGOFuncName(const Function &F, bool InLTO = false,
+               uint64_t Version = INSTR_PROF_INDEX_VERSION);
 
 /// Return the modified name for a function suitable to be
 /// used the key for profile lookup. The function's original
 /// name is \c RawFuncName and has linkage of type \c Linkage.
 /// The function is defined in module \c FileName.
-std::string getPGOFuncName(StringRef RawFuncName,
-                           GlobalValue::LinkageTypes Linkage,
-                           StringRef FileName,
-                           uint64_t Version = INSTR_PROF_INDEX_VERSION);
+LLVM_ABI std::string
+getPGOFuncName(StringRef RawFuncName, GlobalValue::LinkageTypes Linkage,
+               StringRef FileName, uint64_t Version = INSTR_PROF_INDEX_VERSION);
 
 /// \return the modified name for function \c F suitable to be
 /// used as the key for IRPGO profile lookup. \c InLTO indicates if this is
 /// called from LTO optimization passes.
-std::string getIRPGOFuncName(const Function &F, bool InLTO = false);
+LLVM_ABI std::string getIRPGOFuncName(const Function &F, bool InLTO = false);
 
 /// \return the filename and the function name parsed from the output of
 /// \c getIRPGOFuncName()
-std::pair<StringRef, StringRef> getParsedIRPGOName(StringRef IRPGOName);
+LLVM_ABI std::pair<StringRef, StringRef>
+getParsedIRPGOName(StringRef IRPGOName);
 
 /// Return the name of the global variable used to store a function
 /// name in PGO instrumentation. \c FuncName is the IRPGO function name
 /// (returned by \c getIRPGOFuncName) for LLVM IR instrumentation and PGO
 /// function name (returned by \c getPGOFuncName) for front-end instrumentation.
-std::string getPGOFuncNameVarName(StringRef FuncName,
-                                  GlobalValue::LinkageTypes Linkage);
+LLVM_ABI std::string getPGOFuncNameVarName(StringRef FuncName,
+                                           GlobalValue::LinkageTypes Linkage);
 
 /// Create and return the global variable for function name used in PGO
 /// instrumentation. \c FuncName is the IRPGO function name (returned by
 /// \c getIRPGOFuncName) for LLVM IR instrumentation and PGO function name
 /// (returned by \c getPGOFuncName) for front-end instrumentation.
-GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName);
+LLVM_ABI GlobalVariable *createPGOFuncNameVar(Function &F,
+                                              StringRef PGOFuncName);
 
 /// Create and return the global variable for function name used in PGO
 /// instrumentation. \c FuncName is the IRPGO function name (returned by
 /// \c getIRPGOFuncName) for LLVM IR instrumentation and PGO function name
 /// (returned by \c getPGOFuncName) for front-end instrumentation.
-GlobalVariable *createPGOFuncNameVar(Module &M,
-                                     GlobalValue::LinkageTypes Linkage,
-                                     StringRef PGOFuncName);
+LLVM_ABI GlobalVariable *createPGOFuncNameVar(Module &M,
+                                              GlobalValue::LinkageTypes Linkage,
+                                              StringRef PGOFuncName);
 
 /// Return the initializer in string of the PGO name var \c NameVar.
-StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar);
+LLVM_ABI StringRef getPGOFuncNameVarInitializer(GlobalVariable *NameVar);
 
 /// Given a PGO function name, remove the filename prefix and return
 /// the original (static) function name.
-StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName,
-                                   StringRef FileName = "<unknown>");
+LLVM_ABI StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName,
+                                            StringRef FileName = "<unknown>");
 
 /// Given a vector of strings (names of global objects like functions or,
 /// virtual tables) \c NameStrs, the method generates a combined string \c
@@ -281,28 +283,31 @@ StringRef getFuncNameWithoutPrefix(StringRef PGOFuncName,
 ///  third field is the uncompressed strings; otherwise it is the
 /// compressed string. When the string compression is off, the
 /// second field will have value zero.
-Error collectGlobalObjectNameStrings(ArrayRef<std::string> NameStrs,
-                                     bool doCompression, std::string &Result);
+LLVM_ABI Error collectGlobalObjectNameStrings(ArrayRef<std::string> NameStrs,
+                                              bool doCompression,
+                                              std::string &Result);
 
 /// Produce \c Result string with the same format described above. The input
 /// is vector of PGO function name variables that are referenced.
 /// The global variable element in 'NameVars' is a string containing the pgo
 /// name of a function. See `createPGOFuncNameVar` that creates these global
 /// variables.
-Error collectPGOFuncNameStrings(ArrayRef<GlobalVariable *> NameVars,
-                                std::string &Result, bool doCompression = true);
+LLVM_ABI Error collectPGOFuncNameStrings(ArrayRef<GlobalVariable *> NameVars,
+                                         std::string &Result,
+                                         bool doCompression = true);
 
-Error collectVTableStrings(ArrayRef<GlobalVariable *> VTables,
-                           std::string &Result, bool doCompression);
+LLVM_ABI Error collectVTableStrings(ArrayRef<GlobalVariable *> VTables,
+                                    std::string &Result, bool doCompression);
 
 /// Check if INSTR_PROF_RAW_VERSION_VAR is defined. This global is only being
 /// set in IR PGO compilation.
-bool isIRPGOFlagSet(const Module *M);
+LLVM_ABI bool isIRPGOFlagSet(const Module *M);
 
 /// Check if we can safely rename this Comdat function. Instances of the same
 /// comdat function may have different control flows thus can not share the
 /// same counter variable.
-bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken = false);
+LLVM_ABI bool canRenameComdatFunc(const Function &F,
+                                  bool CheckAddressTaken = false);
 
 enum InstrProfValueKind : uint32_t {
 #define VALUE_PROF_KIND(Enumerator, Value, Descr) Enumerator = Value,
@@ -312,23 +317,24 @@ enum InstrProfValueKind : uint32_t {
 /// Get the value profile data for value site \p SiteIdx from \p InstrProfR
 /// and annotate the instruction \p Inst with the value profile meta data.
 /// Annotate up to \p MaxMDCount (default 3) number of records per value site.
-void annotateValueSite(Module &M, Instruction &Inst,
-                       const InstrProfRecord &InstrProfR,
-                       InstrProfValueKind ValueKind, uint32_t SiteIndx,
-                       uint32_t MaxMDCount = 3);
+LLVM_ABI void annotateValueSite(Module &M, Instruction &Inst,
+                                const InstrProfRecord &InstrProfR,
+                                InstrProfValueKind ValueKind, uint32_t SiteIndx,
+                                uint32_t MaxMDCount = 3);
 
 /// Same as the above interface but using an ArrayRef, as well as \p Sum.
 /// This function will not annotate !prof metadata on the instruction if the
 /// referenced array is empty.
-void annotateValueSite(Module &M, Instruction &Inst,
-                       ArrayRef<InstrProfValueData> VDs, uint64_t Sum,
-                       InstrProfValueKind ValueKind, uint32_t MaxMDCount);
+LLVM_ABI void annotateValueSite(Module &M, Instruction &Inst,
+                                ArrayRef<InstrProfValueData> VDs, uint64_t Sum,
+                                InstrProfValueKind ValueKind,
+                                uint32_t MaxMDCount);
 
 // TODO: Unify metadata name 'PGOFuncName' and 'PGOName', by supporting read
 // of this metadata for backward compatibility and generating 'PGOName' only.
 /// Extract the value profile data from \p Inst and returns them if \p Inst is
 /// annotated with value profile data. Returns an empty vector otherwise.
-SmallVector<InstrProfValueData, 4>
+LLVM_ABI SmallVector<InstrProfValueData, 4>
 getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind,
                          uint32_t MaxNumValueData, uint64_t &TotalC,
                          bool GetNoICPValue = false);
@@ -338,32 +344,33 @@ inline StringRef getPGOFuncNameMetadataName() { return "PGOFuncName"; }
 inline StringRef getPGONameMetadataName() { return "PGOName"; }
 
 /// Return the PGOFuncName meta data associated with a function.
-MDNode *getPGOFuncNameMetadata(const Function &F);
+LLVM_ABI MDNode *getPGOFuncNameMetadata(const Function &F);
 
-std::string getPGOName(const GlobalVariable &V, bool InLTO = false);
+LLVM_ABI std::string getPGOName(const GlobalVariable &V, bool InLTO = false);
 
 /// Create the PGOFuncName meta data if PGOFuncName is different from
 /// function's raw name. This should only apply to internal linkage functions
 /// declared by users only.
 /// TODO: Update all callers to 'createPGONameMetadata' and deprecate this
 /// function.
-void createPGOFuncNameMetadata(Function &F, StringRef PGOFuncName);
+LLVM_ABI void createPGOFuncNameMetadata(Function &F, StringRef PGOFuncName);
 
 /// Create the PGOName metadata if a global object's PGO name is different from
 /// its mangled name. This should apply to local-linkage global objects only.
-void createPGONameMetadata(GlobalObject &GO, StringRef PGOName);
+LLVM_ABI void createPGONameMetadata(GlobalObject &GO, StringRef PGOName);
 
 /// Check if we can use Comdat for profile variables. This will eliminate
 /// the duplicated profile variables for Comdat functions.
-bool needsComdatForCounter(const GlobalObject &GV, const Module &M);
+LLVM_ABI bool needsComdatForCounter(const GlobalObject &GV, const Module &M);
 
 /// \c NameStrings is a string composed of one or more possibly encoded
 /// sub-strings. The substrings are separated by `\01` (returned by
 /// InstrProf.h:getInstrProfNameSeparator). This method decodes the string and
 /// calls `NameCallback` for each substring.
-Error readAndDecodeStrings(StringRef NameStrings,
-                           std::function<Error(StringRef)> NameCallback);
+LLVM_ABI Error readAndDecodeStrings(
+    StringRef NameStrings, std::function<Error(StringRef)> NameCallback);
 
+LLVM_ABI Error readAndDecodeStrings(StringRef NameStrings, std::function<Error(StringRef)> NameCallback, const std::string &Architecture);
 /// An enum describing the attributes of an instrumented profile.
 enum class InstrProfKind {
   Unknown = 0x0,
@@ -388,7 +395,7 @@ enum class InstrProfKind {
   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/LoopEntriesInstrumentation)
 };
 
-const std::error_category &instrprof_category();
+LLVM_ABI const std::error_category &instrprof_category();
 
 enum class instrprof_error {
   success = 0,
@@ -431,16 +438,17 @@ struct TemporalProfTraceTy {
   /// Use a set of temporal profile traces to create a list of balanced
   /// partitioning function nodes used by BalancedPartitioning to generate a
   /// function order that reduces page faults during startup
-  static void createBPFunctionNodes(ArrayRef<TemporalProfTraceTy> Traces,
-                                    std::vector<BPFunctionNode> &Nodes,
-                                    bool RemoveOutlierUNs = true);
+  LLVM_ABI static void
+  createBPFunctionNodes(ArrayRef<TemporalProfTraceTy> Traces,
+                        std::vector<BPFunctionNode> &Nodes,
+                        bool RemoveOutlierUNs = true);
 };
 
 inline std::error_code make_error_code(instrprof_error E) {
   return std::error_code(static_cast<int>(E), instrprof_category());
 }
 
-class InstrProfError : public ErrorInfo<InstrProfError> {
+class LLVM_ABI InstrProfError : public ErrorInfo<InstrProfError> {
 public:
   InstrProfError(instrprof_error Err, const Twine &ErrStr = Twine())
       : Err(Err), Msg(ErrStr.str()) {
@@ -503,9 +511,14 @@ class InstrProfSymtab {
   // Returns the canonical name of the given PGOName. In a canonical name, all
   // suffixes that begins with "." except ".__uniq." are stripped.
   // FIXME: Unify this with `FunctionSamples::getCanonicalFnName`.
-  static StringRef getCanonicalName(StringRef PGOName);
+  LLVM_ABI static StringRef getCanonicalName(StringRef PGOName);
 
+  //ANDRES Function
+  const std::string &getArchitecture() {return Architecture;}
+  void setArchitecture(const std::string &Arch) {Architecture = Arch;}
+  //ANDRES Function
 private:
+  std::string Architecture;
   using AddrIntervalMap =
       IntervalMap<uint64_t, uint64_t, 4, IntervalMapHalfOpenInfo<uint64_t>>;
   StringRef Data;
@@ -537,7 +550,6 @@ class InstrProfSymtab {
   // This map is only populated and used by raw instr profile reader.
   AddrIntervalMap VTableAddrMap;
   bool Sorted = false;
-
   static StringRef getExternalSymbol() { return "** External Symbol **"; }
 
   // Add the function into the symbol table, by creating the following
@@ -577,22 +589,23 @@ class InstrProfSymtab {
   /// only initialize the symtab with reference to the data and
   /// the section base address. The decompression will be delayed
   /// until before it is used. See also \c create(StringRef) method.
-  Error create(object::SectionRef &Section);
+  LLVM_ABI Error create(object::SectionRef &Section);
 
   /// \c NameStrings is a string composed of one of more sub-strings
   ///  encoded in the format described in \c collectPGOFuncNameStrings.
   /// This method is a wrapper to \c readAndDecodeStrings method.
-  Error create(StringRef NameStrings);
+  LLVM_ABI Error create(StringRef NameStrings);
 
   /// Initialize symtab states with function names and vtable names. \c
   /// FuncNameStrings is a string composed of one or more encoded function name
   /// strings, and \c VTableNameStrings composes of one or more encoded vtable
   /// names. This interface is solely used by raw profile reader.
-  Error create(StringRef FuncNameStrings, StringRef VTableNameStrings);
+  LLVM_ABI Error create(StringRef FuncNameStrings, StringRef VTableNameStrings);
 
   /// Initialize 'this' with the set of vtable names encoded in
   /// \c CompressedVTableNames.
-  Error initVTableNamesFromCompressedStrings(StringRef CompressedVTableNames);
+  LLVM_ABI Error
+  initVTableNamesFromCompressedStrings(StringRef CompressedVTableNames);
 
   /// This interface is used by reader of CoverageMapping test
   /// format.
@@ -604,7 +617,8 @@ class InstrProfSymtab {
   /// indicates if this is called from LTO optimization passes.
   /// A canonical name, removing non-__uniq suffixes, is added if
   /// \c AddCanonical is true.
-  Error create(Module &M, bool InLTO = false, bool AddCanonical = true);
+  LLVM_ABI Error create(Module &M, bool InLTO = false,
+                        bool AddCanonical = true);
 
   /// Create InstrProfSymtab from a set of names iteratable from
   /// \p IterRange. This interface is used by IndexedProfReader.
@@ -620,6 +634,9 @@ class InstrProfSymtab {
 
   // Map the MD5 of the symbol name to the name.
   Error addSymbolName(StringRef SymbolName) {
+    StringRef FuncName;
+    StringRef ArchName;
+    std::tie(FuncName, ArchName) = SymbolName.split(":");
     if (SymbolName.empty())
       return make_error<InstrProfError>(instrprof_error::malformed,
                                         "symbol name is empty");
@@ -667,15 +684,15 @@ class InstrProfSymtab {
   }
 
   /// Return a function's hash, or 0, if the function isn't in this SymTab.
-  uint64_t getFunctionHashFromAddress(uint64_t Address);
+  LLVM_ABI uint64_t getFunctionHashFromAddress(uint64_t Address);
 
   /// Return a vtable's hash, or 0 if the vtable doesn't exist in this SymTab.
-  uint64_t getVTableHashFromAddress(uint64_t Address);
+  LLVM_ABI uint64_t getVTableHashFromAddress(uint64_t Address);
 
   /// Return function's PGO name from the function name's symbol
   /// address in the object file. If an error occurs, return
   /// an empty string.
-  StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize);
+  LLVM_ABI StringRef getFuncName(uint64_t FuncNameAddress, size_t NameSize);
 
   /// Return name of functions or global variables from the name's md5 hash
   /// value. If not found, return an empty string.
@@ -702,7 +719,7 @@ class InstrProfSymtab {
   inline StringRef getNameData() const { return Data; }
 
   /// Dump the symbols in this table.
-  void dumpNames(raw_ostream &OS) const;
+  LLVM_ABI void dumpNames(raw_ostream &OS) const;
 };
 
 Error InstrProfSymtab::create(StringRef D, uint64_t BaseAddr) {
@@ -814,17 +831,17 @@ struct OverlapStats {
 
   OverlapStats(OverlapStatsLevel L = ProgramLevel) : Level(L) {}
 
-  void dump(raw_fd_ostream &OS) const;
+  LLVM_ABI void dump(raw_fd_ostream &OS) const;
 
   void setFuncInfo(StringRef Name, uint64_t Hash) {
     FuncName = Name;
     FuncHash = Hash;
   }
 
-  Error accumulateCounts(const std::string &BaseFilename,
-                         const std::string &TestFilename, bool IsCS);
-  void addOneMismatch(const CountSumOrPercent &MismatchFunc);
-  void addOneUnique(const CountSumOrPercent &UniqueFunc);
+  LLVM_ABI Error accumulateCounts(const std::string &BaseFilename,
+                                  const std::string &TestFilename, bool IsCS);
+  LLVM_ABI void addOneMismatch(const CountSumOrPercent &MismatchFunc);
+  LLVM_ABI void addOneUnique(const CountSumOrPercent &UniqueFunc);
 
   static inline double score(uint64_t Val1, uint64_t Val2, double Sum1,
                              double Sum2) {
@@ -861,14 +878,15 @@ struct InstrProfValueSiteRecord {
 
   /// Merge data from another InstrProfValueSiteRecord
   /// Optionally scale merged counts by \p Weight.
-  void merge(InstrProfValueSiteRecord &Input, uint64_t Weight,
-             function_ref<void(instrprof_error)> Warn);
+  LLVM_ABI void merge(InstrProfValueSiteRecord &Input, uint64_t Weight,
+                      function_ref<void(instrprof_error)> Warn);
   /// Scale up value profile data counts by N (Numerator) / D (Denominator).
-  void scale(uint64_t N, uint64_t D, function_ref<void(instrprof_error)> Warn);
+  LLVM_ABI void scale(uint64_t N, uint64_t D,
+                      function_ref<void(instrprof_error)> Warn);
 
   /// Compute the overlap b/w this record and Input record.
-  void overlap(InstrProfValueSiteRecord &Input, uint32_t ValueKind,
-               OverlapStats &Overlap, OverlapStats &FuncLevelOverlap);
+  LLVM_ABI void overlap(InstrProfValueSiteRecord &Input, uint32_t ValueKind,
+                        OverlapStats &Overlap, OverlapStats &FuncLevelOverlap);
 };
 
 /// Profiling information for a single function.
@@ -920,18 +938,19 @@ struct InstrProfRecord {
 
   /// Add ValueData for ValueKind at value Site.  We do not support adding sites
   /// out of order.  Site must go up from 0 one by one.
-  void addValueData(uint32_t ValueKind, uint32_t Site,
-                    ArrayRef<InstrProfValueData> VData,
-                    InstrProfSymtab *SymTab);
+  LLVM_ABI void addValueData(uint32_t ValueKind, uint32_t Site,
+                             ArrayRef<InstrProfValueData> VData,
+                             InstrProfSymtab *SymTab);
 
   /// Merge the counts in \p Other into this one.
   /// Optionally scale merged counts by \p Weight.
-  void merge(InstrProfRecord &Other, uint64_t Weight,
-             function_ref<void(instrprof_error)> Warn);
+  LLVM_ABI void merge(InstrProfRecord &Other, uint64_t Weight,
+                      function_ref<void(instrprof_error)> Warn);
 
   /// Scale up profile counts (including value profile data) by
   /// a factor of (N / D).
-  void scale(uint64_t N, uint64_t D, function_ref<void(instrprof_error)> Warn);
+  LLVM_ABI void scale(uint64_t N, uint64_t D,
+                      function_ref<void(instrprof_error)> Warn);
 
   /// Sort value profile data (per site) by count.
   void sortValueData() {
@@ -950,16 +969,16 @@ struct InstrProfRecord {
   void clearValueData() { ValueData = nullptr; }
 
   /// Compute the sums of all counts and store in Sum.
-  void accumulateCounts(CountSumOrPercent &Sum) const;
+  LLVM_ABI void accumulateCounts(CountSumOrPercent &Sum) const;
 
   /// Compute the overlap b/w this IntrprofRecord and Other.
-  void overlap(InstrProfRecord &Other, OverlapStats &Overlap,
-               OverlapStats &FuncLevelOverlap, uint64_t ValueCutoff);
+  LLVM_ABI void overlap(InstrProfRecord &Other, OverlapStats &Overlap,
+                        OverlapStats &FuncLevelOverlap, uint64_t ValueCutoff);
 
   /// Compute the overlap of value profile counts.
-  void overlapValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
-                            OverlapStats &Overlap,
-                            OverlapStats &FuncLevelOverlap);
+  LLVM_ABI void overlapValueProfData(uint32_t ValueKind, InstrProfRecord &Src,
+                                     OverlapStats &Overlap,
+                                     OverlapStats &FuncLevelOverlap);
 
   enum CountPseudoKind {
     NotPseudo = 0,
@@ -1187,15 +1206,15 @@ struct Header {
 
   // Reads a header struct from the buffer. Header fields are in machine native
   // endianness.
-  static Expected<Header> readFromBuffer(const unsigned char *Buffer);
+  LLVM_ABI static Expected<Header> readFromBuffer(const unsigned char *Buffer);
 
   // Returns the size of the header in bytes for all valid fields based on the
   // version. I.e a older version header will return a smaller size.
-  size_t size() const;
+  LLVM_ABI size_t size() const;
 
   // Return the indexed profile version, i.e., the least significant 32 bits
   // in Header.Version.
-  uint64_t getIndexedProfileVersion() const;
+  LLVM_ABI uint64_t getIndexedProfileVersion() const;
 };
 
 // Profile summary data recorded in the profile data file in indexed
@@ -1340,11 +1359,11 @@ struct Header {
 } // end namespace RawInstrProf
 
 // Create the variable for the profile file name.
-void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput);
+LLVM_ABI void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput);
 
 // Whether to compress function names in profile records, and filenames in
 // code coverage mappings. Used by the Instrumentation library and unit tests.
-extern cl::opt<bool> DoInstrProfNameCompression;
+LLVM_ABI extern cl::opt<bool> DoInstrProfNameCompression;
 
 } // end namespace llvm
 #endif // LLVM_PROFILEDATA_INSTRPROF_H
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index c250a9ede39bc..af3b305192aa3 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -18,10 +18,13 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/ProfileSummary.h"
 #include "llvm/Object/BuildID.h"
+#include "llvm/ProfileData/DataAccessProf.h"
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/ProfileData/InstrProfCorrelator.h"
 #include "llvm/ProfileData/MemProf.h"
+#include "llvm/ProfileData/MemProfSummary.h"
 #include "llvm/ProfileData/MemProfYAML.h"
+#include "llvm/Support/Compiler.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/LineIterator.h"
@@ -156,9 +159,12 @@ class InstrProfReader {
   virtual InstrProfSymtab &getSymtab() = 0;
 
   /// Compute the sum of counts and return in Sum.
-  void accumulateCounts(CountSumOrPercent &Sum, bool IsCS);
+  LLVM_ABI void accumulateCounts(CountSumOrPercent &Sum, bool IsCS);
 
 protected:
+  //ANDRES Storing Architecture Information as a string
+  std::string Architecture;
+
   std::unique_ptr<InstrProfSymtab> Symtab;
   /// A list of temporal profile traces.
   SmallVector<TemporalProfTraceTy> TemporalProfTraces;
@@ -201,22 +207,25 @@ class InstrProfReader {
 
   /// Factory method to create an appropriately typed reader for the given
   /// instrprof file.
-  static Expected<std::unique_ptr<InstrProfReader>> create(
+  LLVM_ABI static Expected<std::unique_ptr<InstrProfReader>> create(
       const Twine &Path, vfs::FileSystem &FS,
       const InstrProfCorrelator *Correlator = nullptr,
       const object::BuildIDFetcher *BIDFetcher = nullptr,
       const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind =
           InstrProfCorrelator::ProfCorrelatorKind::NONE,
-      std::function<void(Error)> Warn = nullptr);
+      std::function<void(Error)> Warn = nullptr, const std::string &Architecture = "");
 
-  static Expected<std::unique_ptr<InstrProfReader>> create(
+  LLVM_ABI static Expected<std::unique_ptr<InstrProfReader>> create(
       std::unique_ptr<MemoryBuffer> Buffer,
       const InstrProfCorrelator *Correlator = nullptr,
       const object::BuildIDFetcher *BIDFetcher = nullptr,
       const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind =
           InstrProfCorrelator::ProfCorrelatorKind::NONE,
-      std::function<void(Error)> Warn = nullptr);
+      std::function<void(Error)> Warn = nullptr, const std::string &Architecture = "");
+  
+  const std::string &getArchitecture() {return Architecture;}
 
+  void setArchitecture(const std::string &Arch) {Architecture = Arch;}
   /// \param Weight for raw profiles use this as the temporal profile trace
   ///               weight
   /// \returns a list of temporal profile traces.
@@ -240,7 +249,7 @@ class InstrProfReader {
 ///
 /// Each record consists of a function name, a function hash, a number of
 /// counters, and then each counter value, in that order.
-class TextInstrProfReader : public InstrProfReader {
+class LLVM_ABI TextInstrProfReader : public InstrProfReader {
 private:
   /// The profile data file contents.
   std::unique_ptr<MemoryBuffer> DataBuffer;
@@ -533,7 +542,7 @@ class InstrProfLookupTrait {
   static StringRef GetInternalKey(StringRef K) { return K; }
   static StringRef GetExternalKey(StringRef K) { return K; }
 
-  hash_value_type ComputeHash(StringRef K);
+  LLVM_ABI hash_value_type ComputeHash(StringRef K);
 
   static std::pair<offset_type, offset_type>
   ReadKeyDataLength(const unsigned char *&D) {
@@ -550,9 +559,10 @@ class InstrProfLookupTrait {
     return StringRef((const char *)D, N);
   }
 
-  bool readValueProfilingData(const unsigned char *&D,
-                              const unsigned char *const End);
-  data_type ReadData(StringRef K, const unsigned char *D, offset_type N);
+  LLVM_ABI bool readValueProfilingData(const unsigned char *&D,
+                                       const unsigned char *const End);
+  LLVM_ABI data_type ReadData(StringRef K, const unsigned char *D,
+                              offset_type N);
 
   // Used for testing purpose only.
   void setValueProfDataEndianness(llvm::endianness Endianness) {
@@ -689,6 +699,8 @@ class IndexedMemProfReader {
   /// The MemProf version.
   memprof::IndexedVersion Version =
       static_cast<memprof::IndexedVersion>(memprof::MinimumSupportedVersion);
+  /// MemProf summary (if available, version >= 4).
+  std::unique_ptr<memprof::MemProfSummary> MemProfSum;
   /// MemProf profile schema (if available).
   memprof::MemProfSchema Schema;
   /// MemProf record profile data on-disk indexed via llvm::md5(FunctionName).
@@ -703,28 +715,34 @@ class IndexedMemProfReader {
   const unsigned char *CallStackBase = nullptr;
   // The number of elements in the radix tree array.
   unsigned RadixTreeSize = 0;
+  /// The data access profiles, deserialized from binary data.
+  std::unique_ptr<memprof::DataAccessProfData> DataAccessProfileData;
 
   Error deserializeV2(const unsigned char *Start, const unsigned char *Ptr);
   Error deserializeRadixTreeBased(const unsigned char *Start,
-                                  const unsigned char *Ptr);
+                                  const unsigned char *Ptr,
+                                  memprof::IndexedVersion Version);
 
 public:
   IndexedMemProfReader() = default;
 
-  Error deserialize(const unsigned char *Start, uint64_t MemProfOffset);
+  LLVM_ABI Error deserialize(const unsigned char *Start,
+                             uint64_t MemProfOffset);
 
-  Expected<memprof::MemProfRecord>
+  LLVM_ABI Expected<memprof::MemProfRecord>
   getMemProfRecord(const uint64_t FuncNameHash) const;
 
-  DenseMap<uint64_t, SmallVector<memprof::CallEdgeTy, 0>>
+  LLVM_ABI DenseMap<uint64_t, SmallVector<memprof::CallEdgeTy, 0>>
   getMemProfCallerCalleePairs() const;
 
   // Return the entire MemProf profile.
-  memprof::AllMemProfData getAllMemProfData() const;
+  LLVM_ABI memprof::AllMemProfData getAllMemProfData() const;
+
+  memprof::MemProfSummary *getSummary() const { return MemProfSum.get(); }
 };
 
 /// Reader for the indexed binary instrprof format.
-class IndexedInstrProfReader : public InstrProfReader {
+class LLVM_ABI IndexedInstrProfReader : public InstrProfReader {
 private:
   /// The profile data file contents.
   std::unique_ptr<MemoryBuffer> DataBuffer;
@@ -883,6 +901,11 @@ class IndexedInstrProfReader : public InstrProfReader {
     }
   }
 
+  /// Return the MemProf summary. Will be null if unavailable (version < 4).
+  memprof::MemProfSummary *getMemProfSummary() const {
+    return MemProfReader.getSummary();
+  }
+
   Error readBinaryIds(std::vector<llvm::object::BuildID> &BinaryIds) override;
   Error printBinaryIds(raw_ostream &OS) override;
 };
diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h
index b72c901dbb5b2..f339fe2c2a9eb 100644
--- a/llvm/include/llvm/ProfileData/InstrProfWriter.h
+++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h
@@ -19,8 +19,11 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/IR/GlobalValue.h"
 #include "llvm/Object/BuildID.h"
+#include "llvm/ProfileData/DataAccessProf.h"
 #include "llvm/ProfileData/IndexedMemProfData.h"
 #include "llvm/ProfileData/InstrProf.h"
+#include "llvm/ProfileData/MemProfSummaryBuilder.h"
+#include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
 #include <cstdint>
 #include <memory>
@@ -81,30 +84,36 @@ class InstrProfWriter {
   // Whether to generated random memprof hotness for testing.
   bool MemprofGenerateRandomHotness;
 
+  std::unique_ptr<memprof::DataAccessProfData> DataAccessProfileData;
+
+  // MemProf summary builder to which records are added as MemProf data is added
+  // to the writer.
+  memprof::MemProfSummaryBuilder MemProfSumBuilder;
+
 public:
   // For memprof testing, random hotness can be assigned to the contexts if
   // MemprofGenerateRandomHotness is enabled. The random seed can be either
   // provided by MemprofGenerateRandomHotnessSeed, or if that is 0, one will be
   // generated in the writer using the current time.
-  InstrProfWriter(bool Sparse = false,
-                  uint64_t TemporalProfTraceReservoirSize = 0,
-                  uint64_t MaxTemporalProfTraceLength = 0,
-                  bool WritePrevVersion = false,
-                  memprof::IndexedVersion MemProfVersionRequested =
-                      static_cast<memprof::IndexedVersion>(
-                          memprof::MinimumSupportedVersion),
-                  bool MemProfFullSchema = false,
-                  bool MemprofGenerateRandomHotness = false,
-                  unsigned MemprofGenerateRandomHotnessSeed = 0);
-  ~InstrProfWriter();
+  LLVM_ABI InstrProfWriter(bool Sparse = false,
+                           uint64_t TemporalProfTraceReservoirSize = 0,
+                           uint64_t MaxTemporalProfTraceLength = 0,
+                           bool WritePrevVersion = false,
+                           memprof::IndexedVersion MemProfVersionRequested =
+                               static_cast<memprof::IndexedVersion>(
+                                   memprof::MinimumSupportedVersion),
+                           bool MemProfFullSchema = false,
+                           bool MemprofGenerateRandomHotness = false,
+                           unsigned MemprofGenerateRandomHotnessSeed = 0);
+  LLVM_ABI ~InstrProfWriter();
 
   StringMap<ProfilingData> &getProfileData() { return FunctionData; }
 
   /// Add function counts for the given function. If there are already counts
   /// for this function and the hash and number of counts match, each counter is
   /// summed. Optionally scale counts by \p Weight.
-  void addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
-                 function_ref<void(Error)> Warn);
+  LLVM_ABI void addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
+                          function_ref<void(Error)> Warn);
   void addRecord(NamedInstrProfRecord &&I, function_ref<void(Error)> Warn) {
     addRecord(std::move(I), 1, Warn);
   }
@@ -112,42 +121,47 @@ class InstrProfWriter {
 
   /// Add \p SrcTraces using reservoir sampling where \p SrcStreamSize is the
   /// total number of temporal profiling traces the source has seen.
-  void addTemporalProfileTraces(SmallVectorImpl<TemporalProfTraceTy> &SrcTraces,
-                                uint64_t SrcStreamSize);
+  LLVM_ABI void
+  addTemporalProfileTraces(SmallVectorImpl<TemporalProfTraceTy> &SrcTraces,
+                           uint64_t SrcStreamSize);
 
   /// Add the entire MemProfData \p Incoming to the writer context.
-  bool addMemProfData(memprof::IndexedMemProfData Incoming,
-                      function_ref<void(Error)> Warn);
+  LLVM_ABI bool addMemProfData(memprof::IndexedMemProfData Incoming,
+                               function_ref<void(Error)> Warn);
 
   // Add a binary id to the binary ids list.
-  void addBinaryIds(ArrayRef<llvm::object::BuildID> BIs);
+  LLVM_ABI void addBinaryIds(ArrayRef<llvm::object::BuildID> BIs);
+
+  LLVM_ABI void addDataAccessProfData(
+      std::unique_ptr<memprof::DataAccessProfData> DataAccessProfile);
 
   /// Merge existing function counts from the given writer.
-  void mergeRecordsFromWriter(InstrProfWriter &&IPW,
-                              function_ref<void(Error)> Warn);
+  LLVM_ABI void mergeRecordsFromWriter(InstrProfWriter &&IPW,
+                                       function_ref<void(Error)> Warn);
 
   /// Write the profile to \c OS
-  Error write(raw_fd_ostream &OS);
+  LLVM_ABI Error write(raw_fd_ostream &OS);
 
   /// Write the profile to a string output stream \c OS
-  Error write(raw_string_ostream &OS);
+  LLVM_ABI Error write(raw_string_ostream &OS);
 
   /// Write the profile in text format to \c OS
-  Error writeText(raw_fd_ostream &OS);
+  LLVM_ABI Error writeText(raw_fd_ostream &OS);
 
   /// Write temporal profile trace data to the header in text format to \c OS
-  void writeTextTemporalProfTraceData(raw_fd_ostream &OS,
-                                      InstrProfSymtab &Symtab);
+  LLVM_ABI void writeTextTemporalProfTraceData(raw_fd_ostream &OS,
+                                               InstrProfSymtab &Symtab);
 
-  Error validateRecord(const InstrProfRecord &Func);
+  LLVM_ABI Error validateRecord(const InstrProfRecord &Func);
 
   /// Write \c Record in text format to \c OS
-  static void writeRecordInText(StringRef Name, uint64_t Hash,
-                                const InstrProfRecord &Counters,
-                                InstrProfSymtab &Symtab, raw_fd_ostream &OS);
+  LLVM_ABI static void writeRecordInText(StringRef Name, uint64_t Hash,
+                                         const InstrProfRecord &Counters,
+                                         InstrProfSymtab &Symtab,
+                                         raw_fd_ostream &OS);
 
   /// Write the profile, returning the raw data. For testing.
-  std::unique_ptr<MemoryBuffer> writeBuffer();
+  LLVM_ABI std::unique_ptr<MemoryBuffer> writeBuffer();
 
   /// Update the attributes of the current profile from the attributes
   /// specified. An error is returned if IR and FE profiles are mixed.
@@ -195,17 +209,18 @@ class InstrProfWriter {
   }
 
   // Internal interfaces for testing purpose only.
-  void setValueProfDataEndianness(llvm::endianness Endianness);
-  void setOutputSparse(bool Sparse);
+  LLVM_ABI void setValueProfDataEndianness(llvm::endianness Endianness);
+  LLVM_ABI void setOutputSparse(bool Sparse);
   void setMemProfVersionRequested(memprof::IndexedVersion Version) {
     MemProfVersionRequested = Version;
   }
   void setMemProfFullSchema(bool Full) { MemProfFullSchema = Full; }
   // Compute the overlap b/w this object and Other. Program level result is
   // stored in Overlap and function level result is stored in FuncLevelOverlap.
-  void overlapRecord(NamedInstrProfRecord &&Other, OverlapStats &Overlap,
-                     OverlapStats &FuncLevelOverlap,
-                     const OverlapFuncFilters &FuncFilter);
+  LLVM_ABI void overlapRecord(NamedInstrProfRecord &&Other,
+                              OverlapStats &Overlap,
+                              OverlapStats &FuncLevelOverlap,
+                              const OverlapFuncFilters &FuncFilter);
 
 private:
   void addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I,
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index 368e3535fe905..ba852ac1405d8 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -572,6 +572,50 @@ Error InstrProfSymtab::addVTableWithName(GlobalVariable &VTable,
   return Error::success();
 }
 
+Error readAndDecodeStrings(StringRef NameStrings,
+                           std::function<Error(StringRef)> NameCallback, const std::string &Architecture) {
+  const uint8_t *P = NameStrings.bytes_begin();
+  const uint8_t *EndP = NameStrings.bytes_end();
+  while (P < EndP) {
+    uint32_t N;
+    uint64_t UncompressedSize = decodeULEB128(P, &N);
+    P += N;
+    uint64_t CompressedSize = decodeULEB128(P, &N);
+    P += N;
+    const bool IsCompressed = (CompressedSize != 0);
+    SmallVector<uint8_t, 128> UncompressedNameStrings;
+    StringRef NameStrings;
+    if (IsCompressed) {
+      if (!llvm::compression::zlib::isAvailable())
+        return make_error<InstrProfError>(instrprof_error::zlib_unavailable);
+
+      if (Error E = compression::zlib::decompress(ArrayRef(P, CompressedSize),
+                                                  UncompressedNameStrings,
+                                                  UncompressedSize)) {
+        consumeError(std::move(E));
+        return make_error<InstrProfError>(instrprof_error::uncompress_failed);
+      }
+      P += CompressedSize;
+      NameStrings = toStringRef(UncompressedNameStrings);
+    } else {
+      NameStrings =
+          StringRef(reinterpret_cast<const char *>(P), UncompressedSize);
+      P += UncompressedSize;
+    }
+    // Now parse the name strings.
+    SmallVector<StringRef, 0> Names;
+    StringRef ArchRef(Architecture); 
+    NameStrings.split(Names, getInstrProfNameSeparator());
+    for (StringRef &Name : Names)
+      if (Error E = NameCallback(Name.str()+ ":" + ArchRef.str()*/))
+        return E;
+
+    while (P < EndP && *P == 0)
+      P++;
+  }
+  return Error::success();
+}
+
 Error readAndDecodeStrings(StringRef NameStrings,
                            std::function<Error(StringRef)> NameCallback) {
   const uint8_t *P = NameStrings.bytes_begin();
@@ -616,21 +660,18 @@ Error readAndDecodeStrings(StringRef NameStrings,
 }
 
 Error InstrProfSymtab::create(StringRef NameStrings) {
-  return readAndDecodeStrings(
-      NameStrings,
-      std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1));
+  return readAndDecodeStrings(NameStrings, std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1));
 }
 
 Error InstrProfSymtab::create(StringRef FuncNameStrings,
                               StringRef VTableNameStrings) {
-  if (Error E = readAndDecodeStrings(FuncNameStrings,
-                                     std::bind(&InstrProfSymtab::addFuncName,
-                                               this, std::placeholders::_1)))
+  const std::string &Architecture = getArchitecture();                                
+  if (Error E = readAndDecodeStrings(FuncNameStrings, std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1), Architecture))
     return E;
 
   return readAndDecodeStrings(
       VTableNameStrings,
-      std::bind(&InstrProfSymtab::addVTableName, this, std::placeholders::_1));
+      std::bind(&InstrProfSymtab::addVTableName, this, std::placeholders::_1), Architecture);
 }
 
 Error InstrProfSymtab::initVTableNamesFromCompressedStrings(
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index a1eb08362087f..d78bf4e468ab8 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -18,7 +18,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/ProfileSummary.h"
 #include "llvm/ProfileData/InstrProf.h"
-// #include "llvm/ProfileData/MemProf.h"
+#include "llvm/ProfileData/MemProf.h"
 #include "llvm/ProfileData/MemProfRadixTree.h"
 #include "llvm/ProfileData/ProfileCommon.h"
 #include "llvm/ProfileData/SymbolRemappingReader.h"
@@ -28,6 +28,7 @@
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/ProfileData/InstrProfReader.h"
 #include <algorithm>
 #include <cstddef>
 #include <cstdint>
@@ -153,25 +154,26 @@ static void printBinaryIdsInternal(raw_ostream &OS,
   }
 }
 
-Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
+Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create( //STEP 1
     const Twine &Path, vfs::FileSystem &FS,
     const InstrProfCorrelator *Correlator,
     const object::BuildIDFetcher *BIDFetcher,
     const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
-    std::function<void(Error)> Warn) {
+    std::function<void(Error)> Warn, 
+    const std::string &Architecture) {
   // Set up the buffer to read.
   auto BufferOrError = setupMemoryBuffer(Path, FS);
   if (Error E = BufferOrError.takeError())
     return std::move(E);
   return InstrProfReader::create(std::move(BufferOrError.get()), Correlator,
-                                 BIDFetcher, BIDFetcherCorrelatorKind, Warn);
+                                 BIDFetcher, BIDFetcherCorrelatorKind, Warn, Architecture);
 }
 
 Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
     std::unique_ptr<MemoryBuffer> Buffer, const InstrProfCorrelator *Correlator,
     const object::BuildIDFetcher *BIDFetcher,
     const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
-    std::function<void(Error)> Warn) {
+    std::function<void(Error)> Warn, const std::string &Architecture) {
   if (Buffer->getBufferSize() == 0)
     return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
 
@@ -193,9 +195,12 @@ Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
     return make_error<InstrProfError>(instrprof_error::unrecognized_format);
 
   // Initialize the reader and return the result.
+
+  if(Result){
+    Result->setArchitecture(Architecture);
+  }
   if (Error E = initializeReader(*Result))
     return std::move(E);
-
   return std::move(Result);
 }
 
@@ -509,7 +514,7 @@ bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
 }
 
 template <class IntPtrT>
-Error RawInstrProfReader<IntPtrT>::readHeader() {
+Error RawInstrProfReader<IntPtrT>::readHeader() { //STEP 2
   if (!hasFormat(*DataBuffer))
     return error(instrprof_error::bad_magic);
   if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
@@ -549,7 +554,10 @@ Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
 }
 
 template <class IntPtrT>
-Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
+Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { //STEP 5
+  
+  Symtab.setArchitecture(Architecture)
+  
   if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart),
                               StringRef(VNamesStart, VNamesEnd - VNamesStart)))
     return error(std::move(E));
@@ -580,7 +588,7 @@ Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
 template <class IntPtrT>
 Error RawInstrProfReader<IntPtrT>::readHeader(
     const RawInstrProf::Header &Header) {
-  Version = swap(Header.Version);
+  Version = swap(Header.Version); //STEP 4
   if (GET_VERSION(Version) != RawInstrProf::Version)
     return error(instrprof_error::raw_profile_version_mismatch,
                  ("Profile uses raw profile format version = " +
@@ -697,7 +705,7 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
   ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
 
   std::unique_ptr<InstrProfSymtab> NewSymtab = std::make_unique<InstrProfSymtab>();
-  if (Error E = createSymtab(*NewSymtab))
+  if (Error E = createSymtab(*NewSymtab)) //IMPORTANT FUNCTION CALL
     return E;
 
   Symtab = std::move(NewSymtab);
@@ -1552,6 +1560,20 @@ memprof::AllMemProfData IndexedMemProfReader::getAllMemProfData() const {
     Pair.Record = std::move(*Record);
     AllMemProfData.HeapProfileRecords.push_back(std::move(Pair));
   }
+  // Populate the data access profiles for yaml output.
+  if (DataAccessProfileData != nullptr) {
+    for (const auto &[SymHandleRef, RecordRef] :
+         DataAccessProfileData->getRecords())
+      AllMemProfData.YamlifiedDataAccessProfiles.Records.push_back(
+          memprof::DataAccessProfRecord(SymHandleRef, RecordRef.AccessCount,
+                                        RecordRef.Locations));
+    for (StringRef ColdSymbol : DataAccessProfileData->getKnownColdSymbols())
+      AllMemProfData.YamlifiedDataAccessProfiles.KnownColdSymbols.push_back(
+          ColdSymbol.str());
+    for (uint64_t Hash : DataAccessProfileData->getKnownColdHashes())
+      AllMemProfData.YamlifiedDataAccessProfiles.KnownColdStrHashes.push_back(
+          Hash);
+  }
   return AllMemProfData;
 }
 
diff --git a/llvm/tools/llvm-profdata-cross-arch/CMakeLists.txt b/llvm/tools/llvm-profdata-cross-arch/CMakeLists.txt
new file mode 100644
index 0000000000000..b37f76db883b5
--- /dev/null
+++ b/llvm/tools/llvm-profdata-cross-arch/CMakeLists.txt
@@ -0,0 +1,35 @@
+cmake_minimum_required(VERSION 3.13)
+project(llvm-profdata-cross-arch)
+
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+# Find LLVM package
+find_package(LLVM REQUIRED CONFIG)
+
+message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
+message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
+
+# Set LLVM include and library directories
+include_directories(${LLVM_INCLUDE_DIRS})
+link_directories(${LLVM_LIBRARY_DIRS})
+add_definitions(${LLVM_DEFINITIONS})
+
+# Define the source files
+set(SOURCES
+    ELFSymbolReader.cpp
+    llvm-profdata-cross-arch.cpp
+)
+
+# Add the executable
+add_executable(llvm-profdata-cross-arch ${SOURCES})
+
+# Link against LLVM libraries
+llvm_map_components_to_libnames(llvm_libs
+    Core
+    Support
+    Object
+    Demangle
+)
+
+target_link_libraries(llvm-profdata-cross-arch ${llvm_libs})
diff --git a/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.cpp b/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.cpp
new file mode 100644
index 0000000000000..61076f4e72073
--- /dev/null
+++ b/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.cpp
@@ -0,0 +1,90 @@
+#include "ELFSymbolReader.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Demangle/Demangle.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/TargetSelect.h"
+
+
+using namespace llvm;
+using namespace llvm::object;
+
+Expected<std::vector<FunctionSymbol>> ELFSymbolReader::readSymbols(StringRef File){
+    Expected<OwningBinary<Binary>> BinOrErr = createBinary(File);
+    if(!BinOrErr){
+        return BinOrErr.takeError();
+    }
+
+    const ELFObjectFileBase *Obj = dyn_cast<ELFObjectFileBase>(BinOrErr->getBinary());
+    if(!Obj){
+        return createStringError(inconvertibleErrorCode(), "Not an ELF");
+    }
+
+    std::vector<FunctionSymbol> Syms;
+
+    for(const SymbolRef &Sym : Obj->symbols()){
+        if(!(cantFail(Sym.getType()) & SymbolRef::ST_Function)){
+            continue;
+        }
+        if(cantFail(Sym.getFlags()) & SymbolRef::SF_Undefined){
+            continue;
+        }
+        Expected<StringRef> NameOrErr = Sym.getName();
+        if(!NameOrErr){
+            consumeError(NameOrErr.takeError());
+            continue;
+        }
+        StringRef FuncNameRef = *NameOrErr;
+        if(FuncNameRef.starts_with("__")){
+            continue;
+        }
+        
+        // Skip symbols not in executable sections (e.g., not in .text)
+        Expected<section_iterator> SecOrErr = Sym.getSection();
+        if (!SecOrErr || *SecOrErr == Obj->section_end()){
+            continue;
+        }
+        StringRef SectionName;
+        if (Expected<StringRef> NameOrErr = (*SecOrErr)->getName()) {
+            SectionName = *NameOrErr;
+            if (!SectionName.equals_insensitive(".text")){
+                continue;
+            }
+        } else {
+            consumeError(NameOrErr.takeError());
+            continue;
+        }
+
+
+        uint64_t Addr = cantFail(Sym.getAddress());
+        StringRef NameRef = cantFail(Sym.getName());
+
+        FunctionSymbol FS;
+        FS.Address = Addr;
+        FS.Name = NameRef.str();
+        FS.DemangledName = llvm::demangle(FS.Name);
+        Syms.push_back(std::move(FS));
+    }
+    return Syms;
+}
+
+Expected<std::string> ELFSymbolReader::detectArchitecture(StringRef File){
+    Expected<OwningBinary<Binary>> BinOrErr = createBinary(File);
+    if(!BinOrErr){
+        return BinOrErr.takeError();
+    }
+    
+    const ELFObjectFileBase *Obj = dyn_cast<ELFObjectFileBase>(BinOrErr->getBinary());
+    if(!Obj){
+        return createStringError(inconvertibleErrorCode(), "Not an ELF");
+    }
+    return std::string(Triple::getArchTypeName(Obj->getArch()));
+}
+
+std::string ELFSymbolReader::demangleName(StringRef N){
+    return llvm::demangle(N.str());
+}
\ No newline at end of file
diff --git a/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.h b/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.h
new file mode 100644
index 0000000000000..99f88498d3d41
--- /dev/null
+++ b/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.h
@@ -0,0 +1,31 @@
+#pragma once
+
+#include "llvm/Object/ELF.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Error.h"
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+    struct FunctionSymbol {
+        uint64_t Address;
+        std::string Name;
+        std::string DemangledName;
+    };
+
+    class ELFSymbolReader {
+        public:
+            //Expected datatype is an llvm data type that will either have the type specified in the <> or contain an error message explaining why the error occurred.
+            static Expected<std::vector<FunctionSymbol>> readSymbols(StringRef Filename);
+
+            static Expected<std::string> detectArchitecture(StringRef Filename);
+
+            static std::string demangleName(StringRef MangledName);
+    };
+
+} // namespace llvm
+
+
+
+
diff --git a/llvm/tools/llvm-profdata-cross-arch/llvm-profdata-cross-arch.cpp b/llvm/tools/llvm-profdata-cross-arch/llvm-profdata-cross-arch.cpp
new file mode 100644
index 0000000000000..cbb904cc90161
--- /dev/null
+++ b/llvm/tools/llvm-profdata-cross-arch/llvm-profdata-cross-arch.cpp
@@ -0,0 +1,112 @@
+#include "ELFSymbolReader.h"
+#include "llvm/IR/Function.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+static cl::SubCommand AnalyzeSymbolsSubcommand("analyze-symbols", "Analyze symbols in ELF files for cross-arch profiling");
+static cl::SubCommand AnalyzeProfrawSubcommand("analyze-profraw", "Used to analyze mappings between source code and coverage data");
+
+static cl::list<std::string> ELFFiles(cl::Positional, cl::sub(AnalyzeSymbolsSubcommand), cl::desc("<elf-files>"), cl::OneOrMore);
+static cl::list<std::string> ProfrawFiles(cl::Positional, cl::sub(AnalyzeProfrawSubcommand), cl::desc("<profraw-files>"), cl::OneOrMore);
+
+static void findAndPrintMatches(const std::vector<std::vector<FunctionSymbol>> &AllSymbols, const std::vector<std::string> &Architectures) {
+    const std::vector<FunctionSymbol> &Symbols1 = AllSymbols[0];
+    const std::vector<FunctionSymbol> &Symbols2 = AllSymbols[1];
+
+    std::vector<std::pair<FunctionSymbol, FunctionSymbol>> Matches;
+
+    for (const FunctionSymbol &Sym1 : Symbols1) {
+        for (const FunctionSymbol &Sym2 : Symbols2) {
+            if (Sym1.Name == Sym2.Name) {
+                Matches.push_back({Sym1, Sym2});
+                continue;
+            }
+
+            if (!Sym1.DemangledName.empty() && !Sym2.DemangledName.empty() && Sym1.DemangledName == Sym2.DemangledName) {
+                Matches.push_back({Sym1, Sym2});
+                continue;
+            }
+        }
+    }
+
+    outs() << "Potential matches found: " << Matches.size() << "\n";
+    for (const auto &Match : Matches) {
+        if (Match.first.DemangledName == Match.second.DemangledName) {
+            outs() << " " << Match.first.DemangledName << " <-> " << Match.second.DemangledName << " (demangled match)\n";
+        } else {
+            outs() << " " << Match.first.Name << " <-> " << Match.second.Name << " (exact match)\n";
+        }
+    }
+
+    outs() << "\n" << Architectures[0] << "-only functions: " << (Symbols1.size() - Matches.size()) << "\n";
+    outs() << Architectures[1] << "-only functions: " << (Symbols2.size() - Matches.size()) << "\n";
+
+    if (!Matches.empty()) {
+        outs() << "\nSUCCESS: Found " << Matches.size() << " functions that exist in both architectures!\n";
+    } else {
+        outs() << "\nWARNING: No matching functions found between architectures.\n";
+    }
+}
+
+static int analyzeSymbols_main(StringRef ProgName) {
+    outs() << "=== Symbol Analysis ==\n\n";
+    std::vector<std::vector<FunctionSymbol>> AllSymbols;
+    std::vector<std::string> Architectures;
+
+    for (const std::string &Filename : ELFFiles) {
+        Expected<std::string> ArchOrErr = ELFSymbolReader::detectArchitecture(Filename);
+        if (!ArchOrErr) {
+            errs() << "Error detecting architecture for " << Filename << ": " << toString(ArchOrErr.takeError()) << "\n";
+            continue;
+        }
+
+        Expected<std::vector<FunctionSymbol>> SymbolsOrErr = ELFSymbolReader::readSymbols(Filename);
+        if (!SymbolsOrErr) {
+            errs() << "Error reading symbols from " << Filename << ": " << toString(SymbolsOrErr.takeError()) << "\n";
+            continue;
+        }
+
+        std::string Arch = ArchOrErr.get();
+        std::vector<FunctionSymbol> Symbols = SymbolsOrErr.get();
+
+        outs() << "File: " << Filename << "\n";
+        outs() << "Architecture: " << Arch << "\n";
+        outs() << "Functions found: " << Symbols.size() << "\n";
+
+        for (const FunctionSymbol &Symbol : Symbols) {
+            outs() << " 0x" << format("%08x", Symbol.Address) << ": " << Symbol.Name;
+            if (Symbol.DemangledName != Symbol.Name) {
+                outs() << " (" << Symbol.DemangledName << ")";
+            }
+            outs() << "\n";
+        }
+        outs() << "\n";
+
+        AllSymbols.push_back(std::move(Symbols));
+        Architectures.push_back(std::move(Arch));
+    }
+
+    if (AllSymbols.size() >= 2) {
+        outs() << "=== Cross-Architecture Analysis ==\n";
+        findAndPrintMatches(AllSymbols, Architectures);
+    }
+
+    return 0;
+}
+
+int main(int argc, const char *argv[]) {
+    cl::ParseCommandLineOptions(argc, argv, "LLVM cross-architecture profile analysis\n");
+    if (AnalyzeSymbolsSubcommand) {
+        return analyzeSymbols_main(argv[0]);
+    }
+
+    cl::PrintHelpMessage();
+    return 1;
+}
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 885e06df6c390..d5a9a33f47a9a 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -16,11 +16,13 @@
 #include "llvm/Debuginfod/HTTPClient.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/Object/Binary.h"
+#include "llvm/ProfileData/DataAccessProf.h"
 #include "llvm/ProfileData/InstrProfCorrelator.h"
 #include "llvm/ProfileData/InstrProfReader.h"
 #include "llvm/ProfileData/InstrProfWriter.h"
 #include "llvm/ProfileData/MemProf.h"
 #include "llvm/ProfileData/MemProfReader.h"
+#include "llvm/ProfileData/MemProfSummaryBuilder.h"
 #include "llvm/ProfileData/MemProfYAML.h"
 #include "llvm/ProfileData/ProfileCommon.h"
 #include "llvm/ProfileData/SampleProfReader.h"
@@ -29,6 +31,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Discriminator.h"
 #include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormattedStream.h"
@@ -42,6 +45,7 @@
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Object/ObjectFile.h"
 #include <algorithm>
 #include <cmath>
 #include <optional>
@@ -651,9 +655,7 @@ struct WriterContext {
   std::mutex &ErrLock;
   SmallSet<instrprof_error, 4> &WriterErrorCodes;
 
-  WriterContext(bool IsSparse, std::mutex &ErrLock,
-                SmallSet<instrprof_error, 4> &WriterErrorCodes,
-                uint64_t ReservoirSize = 0, uint64_t MaxTraceLength = 0)
+  WriterContext(bool IsSparse, std::mutex &ErrLock, SmallSet<instrprof_error, 4> &WriterErrorCodes, uint64_t ReservoirSize = 0, uint64_t MaxTraceLength = 0)
       : Writer(IsSparse, ReservoirSize, MaxTraceLength, DoWritePrevVersion,
                MemProfVersionRequested, MemProfFullSchema,
                MemprofGenerateRandomHotness, MemprofGenerateRandomHotnessSeed),
@@ -688,6 +690,26 @@ static void overlapInput(const std::string &BaseFilename,
   }
 }
 
+//ANDRES FUNCTION
+Expected<std::string> getArchitectureFromExecutable(StringRef ExecutablePath){
+  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError = MemoryBuffer::getFile(ExecutablePath);
+  if(!BufferOrError){
+    return createStringError(BufferOrError.getError(), "Failed to load input file");
+  }
+
+  Expected<std::unique_ptr<object::ObjectFile>> ObjectOrError = object::ObjectFile::createObjectFile(BufferOrError.get()->getMemBufferRef());
+  if(!ObjectOrError){
+    return ObjectOrError.takeError();
+  }
+
+  std::unique_ptr<llvm::object::ObjectFile> &Object = ObjectOrError.get();
+
+  StringRef ArchStr = Object->getArch() != Triple::UnknownArch ? Triple::getArchTypeName(Object->getArch()) : "unknown";
+
+  return ArchStr.str();
+}
+//ANDRES FUNCTION
+
 /// Load an input into a writer context.
 static void
 loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
@@ -701,11 +723,35 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
   // invalid outside of this packaged task.
   std::string Filename = Input.Filename;
 
+  //ANDRES CODE
+  std::string ExecutableName;
+  std::string ProfileFile = Input.Filename;
+  std::string Architecture = "";
+
+  StringRef FilenameRef = Filename;
+  if(FilenameRef.contains(':')){
+    StringRef ExeRef, ProfRef;
+    std::tie(ExeRef, ProfRef) = FilenameRef.split(':');
+    if(!ExeRef.empty() && !ProfRef.empty()){
+      ExecutableName = ExeRef.str();
+      ProfileFile = ProfRef.str();
+    }
+    Expected<std::string> ArchOrError = getArchitectureFromExecutable(ExeRef);
+    if(ArchOrError){
+      Architecture = std::move(ArchOrError.get());
+    }else{
+      consumeError(ArchOrError.takeError());
+      Architecture = "unknown";
+    }
+  }
+  //ANDRES CODE
+
+
   using ::llvm::memprof::RawMemProfReader;
-  if (RawMemProfReader::hasFormat(Input.Filename)) {
-    auto ReaderOrErr = RawMemProfReader::create(Input.Filename, ProfiledBinary);
+  if (RawMemProfReader::hasFormat(ProfileFile)) {
+    auto ReaderOrErr = RawMemProfReader::create(ProfileFile, ProfiledBinary);
     if (!ReaderOrErr) {
-      exitWithError(ReaderOrErr.takeError(), Input.Filename);
+      exitWithError(ReaderOrErr.takeError(), ProfileFile);
     }
     std::unique_ptr<RawMemProfReader> Reader = std::move(ReaderOrErr.get());
     // Check if the profile types can be merged, e.g. clang frontend profiles
@@ -756,6 +802,8 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
 
     auto MemProfData = Reader->takeMemProfData();
 
+    auto DataAccessProfData = Reader->takeDataAccessProfData();
+
     // Check for the empty input in case the YAML file is invalid.
     if (MemProfData.Records.empty()) {
       WC->Errors.emplace_back(
@@ -764,6 +812,7 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
     }
 
     WC->Writer.addMemProfData(std::move(MemProfData), MemProfError);
+    WC->Writer.addDataAccessProfData(std::move(DataAccessProfData));
     return;
   }
 
@@ -786,8 +835,8 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
   const ProfCorrelatorKind CorrelatorKind = BIDFetcherCorrelatorKind
                                                 ? *BIDFetcherCorrelatorKind
                                                 : ProfCorrelatorKind::NONE;
-  auto ReaderOrErr = InstrProfReader::create(Input.Filename, *FS, Correlator,
-                                             BIDFetcher, CorrelatorKind, Warn);
+  auto ReaderOrErr = InstrProfReader::create(ProfileFile /*ANDRES changed from Input.Filename to ProfileFile*/, *FS, Correlator, //THIS IS THE IMPORTANT LINE!!!!
+                                             BIDFetcher, CorrelatorKind, Warn, Architecture /*ANDRES added this parameter*/);
   if (Error E = ReaderOrErr.takeError()) {
     // Skip the empty profiles by returning silently.
     auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
@@ -1713,6 +1762,28 @@ static void addWeightedInput(WeightedFileVector &WNI, const WeightedFile &WF) {
     return;
   }
 
+  //ANDRES ADDED CODE UPDATED CODE TO HANDLE ARCH SPECIFIC EXECUTABLE
+  StringRef ExecutableName, ProfileFile;
+  if(Filename.contains(':')){
+    std::tie(ExecutableName, ProfileFile) = Filename.split(':');
+
+
+    if(!ExecutableName.empty() && !ProfileFile.empty()){
+      llvm::sys::fs::file_status Status;
+      llvm::sys::fs::status(ProfileFile, Status);
+      if(!llvm::sys::fs::exists(Status)){
+        exitWithErrorCode(make_error_code(errc::no_such_file_or_directory),ProfileFile);
+      }
+      if(llvm::sys::fs::is_regular_file(Status)){
+        WNI.push_back({std::string(Filename), Weight});
+        return;
+      }
+
+      Filename = ProfileFile;
+    }
+  }
+  //ANDRES ADDED CODE
+
   llvm::sys::fs::file_status Status;
   llvm::sys::fs::status(Filename, Status);
   if (!llvm::sys::fs::exists(Status))
@@ -1760,8 +1831,9 @@ static void parseInputFilenamesFile(MemoryBuffer *Buffer,
 
 static int merge_main(StringRef ProgName) {
   WeightedFileVector WeightedInputs;
-  for (StringRef Filename : InputFilenames)
+  for (StringRef Filename : InputFilenames){
     addWeightedInput(WeightedInputs, {std::string(Filename), 1});
+  }
   for (StringRef WeightedFilename : WeightedInputFilenames)
     addWeightedInput(WeightedInputs, parseWeightedFile(WeightedFilename));
 
@@ -3308,6 +3380,18 @@ static int showMemProfProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
 
   auto Reader = std::move(ReaderOrErr.get());
   memprof::AllMemProfData Data = Reader->getAllMemProfData();
+
+  // For v4 and above the summary is serialized in the indexed profile, and can
+  // be accessed from the reader. Earlier versions build the summary below.
+  // The summary is emitted as YAML comments at the start of the output.
+  if (auto *MemProfSum = Reader->getMemProfSummary()) {
+    MemProfSum->printSummaryYaml(OS);
+  } else {
+    memprof::MemProfSummaryBuilder MemProfSumBuilder;
+    for (auto &Pair : Data.HeapProfileRecords)
+      MemProfSumBuilder.addRecord(Pair.Record);
+    MemProfSumBuilder.getSummary()->printSummaryYaml(OS);
+  }
   // Construct yaml::Output with the maximum column width of 80 so that each
   // Frame fits in one line.
   yaml::Output Yout(OS, nullptr, 80);

>From b88e0bc94119daba5e0c8b729eacdc6e72003526 Mon Sep 17 00:00:00 2001
From: Andres Wearden <awearden at hu-awearden-lv.qualcomm.com>
Date: Tue, 1 Jul 2025 09:58:52 -0700
Subject: [PATCH 02/17] saving changes

---
 llvm/include/llvm/ProfileData/InstrProfReader.h | 2 +-
 llvm/lib/ProfileData/InstrProf.cpp              | 2 +-
 llvm/lib/ProfileData/InstrProfReader.cpp        | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index d5988ed793fb3..b92253a81502d 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -106,7 +106,7 @@ class InstrProfReader {
   /// Read a single record.
   virtual Error readNextRecord(NamedInstrProfRecord &Record) = 0;
 
-  /// Read a list of binary ids.
+  /// Read a list of biny ids.
   virtual Error readBinaryIds(std::vector<llvm::object::BuildID> &BinaryIds) {
     return success();
   }
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index f2ba250845f67..16d4877f3ccc8 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -608,7 +608,7 @@ Error readAndDecodeStrings(StringRef NameStrings,
     StringRef ArchRef(Architecture); 
     NameStrings.split(Names, getInstrProfNameSeparator());
     for (StringRef &Name : Names)
-      if (Error E = NameCallback(Name.str()+ ":" + ArchRef.str()*/))
+      if (Error E = NameCallback(Name.str()+ ":" + ArchRef.str()))
         return E;
 
     while (P < EndP && *P == 0)
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 916758dde4fa9..33b62cf5cca5c 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -556,7 +556,7 @@ Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
 template <class IntPtrT>
 Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { //STEP 5
   
-  Symtab.setArchitecture(Architecture)
+  Symtab.setArchitecture(Architecture);
   
   if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart),
                               StringRef(VNamesStart, VNamesEnd - VNamesStart)))

>From 7e74608c9beb84778ebdb12e3a145bdfd9273be8 Mon Sep 17 00:00:00 2001
From: Andres Wearden <awearden at hu-awearden-lv.qualcomm.com>
Date: Sat, 5 Jul 2025 12:12:44 -0700
Subject: [PATCH 03/17] saving updates

---
 code_changes.txt                          | 81 +++++++++++++++++++++++
 llvm/include/llvm/ProfileData/InstrProf.h |  6 +-
 llvm/lib/ProfileData/InstrProf.cpp        | 18 +++--
 3 files changed, 98 insertions(+), 7 deletions(-)
 create mode 100644 code_changes.txt

diff --git a/code_changes.txt b/code_changes.txt
new file mode 100644
index 0000000000000..62aa011714912
--- /dev/null
+++ b/code_changes.txt
@@ -0,0 +1,81 @@
+diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
+index a786aadce6de..eeea25e25fe8 100644
+--- a/llvm/include/llvm/ProfileData/InstrProf.h
++++ b/llvm/include/llvm/ProfileData/InstrProf.h
+@@ -40,6 +40,7 @@
+ #include <cassert>
+ #include <cstddef>
+ #include <cstdint>
++#include <cstdio>
+ #include <cstring>
+ #include <list>
+ #include <memory>
+@@ -643,7 +644,10 @@ public:
+ 
+     // Insert into NameTab so that MD5NameMap (a vector that will be sorted)
+     // won't have duplicated entries in the first place.
+-    auto Ins = NameTab.insert(SymbolName);
++    uint64_t HashValue = IndexedInstrProf::ComputeHash(SymbolName);
++    printf("Hash Value for %.*s: %" PRIu64 "\n", static_cast<int>(SymbolName.size()), SymbolName.data(), HashValue);
++    auto Ins = NameTab.insert(FuncName);
++    printf("mapped value for %" PRIu64 " hash: %.*s\n", HashValue, static_cast<int>(Ins.first->getKey().size()), Ins.first->getKey().data());
+     if (Ins.second) {
+       MD5NameMap.push_back(std::make_pair(
+           IndexedInstrProf::ComputeHash(SymbolName), Ins.first->getKey()));
+diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
+index b92253a81502..7bd1bed6b74f 100644
+--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
++++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
+@@ -356,7 +356,8 @@ private:
+   uint64_t CountersDelta;
+   uint64_t BitmapDelta;
+   uint64_t NamesDelta;
+-  const RawInstrProf::ProfileData<IntPtrT> *Data;
++  const RawInstrProf::ProfileData<IntPtrT> *cccccbveifehbfkeciugkvlcugkcgbdhkkkvdtrfbgkn
++  Data;
+   const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
+   const RawInstrProf::VTableProfileData<IntPtrT> *VTableBegin = nullptr;
+   const RawInstrProf::VTableProfileData<IntPtrT> *VTableEnd = nullptr;
+diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
+index 16d4877f3ccc..ea9e0ea2e129 100644
+--- a/llvm/lib/ProfileData/InstrProf.cpp
++++ b/llvm/lib/ProfileData/InstrProf.cpp
+@@ -555,7 +555,6 @@ Error InstrProfSymtab::addVTableWithName(GlobalVariable &VTable,
+   auto NameToGUIDMap = [&](StringRef Name) -> Error {
+     if (Error E = addSymbolName(Name))
+       return E;
+-
+     bool Inserted = true;
+     std::tie(std::ignore, Inserted) = MD5VTableMap.try_emplace(
+         GlobalValue::getGUIDAssumingExternalLinkage(Name), &VTable);
+@@ -607,10 +606,18 @@ Error readAndDecodeStrings(StringRef NameStrings,
+     SmallVector<StringRef, 0> Names;
+     StringRef ArchRef(Architecture); 
+     NameStrings.split(Names, getInstrProfNameSeparator());
+-    for (StringRef &Name : Names)
+-      if (Error E = NameCallback(Name.str()+ ":" + ArchRef.str()))
+-        return E;
+-
++    printf("=====================READER DATA====================");
++    for (StringRef &Name : Names){
++      std::string ConcHashString = Name.str() + ":" + ArchRef.str();
++      printf("The string %s will get hashed and mapped to %s\n", ConcHashString.c_str(), Name.str().c_str());
++      if(ArchRef.empty()){
++        if (Error E = NameCallback(Name))
++          return E;
++      }else{
++        if (Error E = NameCallback(Name.str() + ":" + ArchRef.str()))
++          return E;
++      }
++    }
+     while (P < EndP && *P == 0)
+       P++;
+   }
+@@ -653,7 +660,6 @@ Error readAndDecodeStrings(StringRef NameStrings,
+     for (StringRef &Name : Names)
+       if (Error E = NameCallback(Name))
+         return E;
+-
+     while (P < EndP && *P == 0)
+       P++;
+   }
diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index a786aadce6de1..eeea25e25fe86 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -40,6 +40,7 @@
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
+#include <cstdio>
 #include <cstring>
 #include <list>
 #include <memory>
@@ -643,7 +644,10 @@ class InstrProfSymtab {
 
     // Insert into NameTab so that MD5NameMap (a vector that will be sorted)
     // won't have duplicated entries in the first place.
-    auto Ins = NameTab.insert(SymbolName);
+    uint64_t HashValue = IndexedInstrProf::ComputeHash(SymbolName);
+    printf("Hash Value for %.*s: %" PRIu64 "\n", static_cast<int>(SymbolName.size()), SymbolName.data(), HashValue);
+    auto Ins = NameTab.insert(FuncName);
+    printf("mapped value for %" PRIu64 " hash: %.*s\n", HashValue, static_cast<int>(Ins.first->getKey().size()), Ins.first->getKey().data());
     if (Ins.second) {
       MD5NameMap.push_back(std::make_pair(
           IndexedInstrProf::ComputeHash(SymbolName), Ins.first->getKey()));
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index 16d4877f3ccc8..ea9e0ea2e1292 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -555,7 +555,6 @@ Error InstrProfSymtab::addVTableWithName(GlobalVariable &VTable,
   auto NameToGUIDMap = [&](StringRef Name) -> Error {
     if (Error E = addSymbolName(Name))
       return E;
-
     bool Inserted = true;
     std::tie(std::ignore, Inserted) = MD5VTableMap.try_emplace(
         GlobalValue::getGUIDAssumingExternalLinkage(Name), &VTable);
@@ -607,10 +606,18 @@ Error readAndDecodeStrings(StringRef NameStrings,
     SmallVector<StringRef, 0> Names;
     StringRef ArchRef(Architecture); 
     NameStrings.split(Names, getInstrProfNameSeparator());
-    for (StringRef &Name : Names)
-      if (Error E = NameCallback(Name.str()+ ":" + ArchRef.str()))
-        return E;
-
+    printf("=====================READER DATA====================");
+    for (StringRef &Name : Names){
+      std::string ConcHashString = Name.str() + ":" + ArchRef.str();
+      printf("The string %s will get hashed and mapped to %s\n", ConcHashString.c_str(), Name.str().c_str());
+      if(ArchRef.empty()){
+        if (Error E = NameCallback(Name))
+          return E;
+      }else{
+        if (Error E = NameCallback(Name.str() + ":" + ArchRef.str()))
+          return E;
+      }
+    }
     while (P < EndP && *P == 0)
       P++;
   }
@@ -653,7 +660,6 @@ Error readAndDecodeStrings(StringRef NameStrings,
     for (StringRef &Name : Names)
       if (Error E = NameCallback(Name))
         return E;
-
     while (P < EndP && *P == 0)
       P++;
   }

>From 3a398c11a57236a83e0a364718f1b0eaaf7043ef Mon Sep 17 00:00:00 2001
From: Andres Wearden <awearden at hu-awearden-lv.qualcomm.com>
Date: Sat, 5 Jul 2025 23:08:53 -0700
Subject: [PATCH 04/17] added new way of hashing the functions so they are more
 consistent with hashes from .profraw file

---
 llvm/include/llvm/ProfileData/InstrProf.h     | 18 ++++++++---
 .../llvm/ProfileData/InstrProfWriter.h        |  5 +++
 llvm/lib/ProfileData/InstrProf.cpp            |  3 +-
 llvm/lib/ProfileData/InstrProfWriter.cpp      | 32 +++++++++++++++++--
 llvm/tools/llvm-profdata/llvm-profdata.cpp    |  2 +-
 5 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index eeea25e25fe86..e9c21c5fc284b 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -644,13 +644,19 @@ class InstrProfSymtab {
 
     // Insert into NameTab so that MD5NameMap (a vector that will be sorted)
     // won't have duplicated entries in the first place.
-    uint64_t HashValue = IndexedInstrProf::ComputeHash(SymbolName);
+    
+    uint64_t HashValue = IndexedInstrProf::ComputeHash(FuncName);
+    std::string HashStr = std::to_string(HashValue);
+    std::string CombinedStr = HashStr + ":" + ArchName.str();
+    llvm::StringRef HashRef(CombinedStr);
+    HashValue = IndexedInstrProf::ComputeHash(HashRef);
+
     printf("Hash Value for %.*s: %" PRIu64 "\n", static_cast<int>(SymbolName.size()), SymbolName.data(), HashValue);
     auto Ins = NameTab.insert(FuncName);
     printf("mapped value for %" PRIu64 " hash: %.*s\n", HashValue, static_cast<int>(Ins.first->getKey().size()), Ins.first->getKey().data());
     if (Ins.second) {
       MD5NameMap.push_back(std::make_pair(
-          IndexedInstrProf::ComputeHash(SymbolName), Ins.first->getKey()));
+          IndexedInstrProf::ComputeHash(HashRef), Ins.first->getKey()));
       Sorted = false;
     }
     return Error::success();
@@ -779,10 +785,14 @@ StringRef InstrProfSymtab::getFuncOrVarNameIfDefined(uint64_t MD5Hash) {
 
 StringRef InstrProfSymtab::getFuncOrVarName(uint64_t MD5Hash) {
   finalizeSymtab();
-  auto Result = llvm::lower_bound(MD5NameMap, MD5Hash,
+  std::string TempMD5HashStr = std::to_string(MD5Hash);
+  std::string CombinedHashStr = TempMD5HashStr + ":" + Architecture;
+  llvm::StringRef CombinedHashRef(CombinedHashStr);
+  uint64_t NewMD5Hash = IndexedInstrProf::ComputeHash(CombinedHashRef);
+  auto Result = llvm::lower_bound(MD5NameMap, NewMD5Hash,
                                   [](const std::pair<uint64_t, StringRef> &LHS,
                                      uint64_t RHS) { return LHS.first < RHS; });
-  if (Result != MD5NameMap.end() && Result->first == MD5Hash)
+  if (Result != MD5NameMap.end() && Result->first == NewMD5Hash)
     return Result->second;
   return StringRef();
 }
diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h
index f339fe2c2a9eb..e281e100bf808 100644
--- a/llvm/include/llvm/ProfileData/InstrProfWriter.h
+++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h
@@ -114,6 +114,11 @@ class InstrProfWriter {
   /// summed. Optionally scale counts by \p Weight.
   LLVM_ABI void addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
                           function_ref<void(Error)> Warn);
+  LLVM_ABI void addRecord(StringRef Name, uint64_t Hash,
+                                InstrProfRecord &&I, uint64_t Weight,
+                                function_ref<void(Error)> Warn, const std::string &Architecture);
+  void addRecord(NamedInstrProfRecord &&I, uint64_t Weight, const std::string &Architecture,
+                                function_ref<void(Error)> Warn);
   void addRecord(NamedInstrProfRecord &&I, function_ref<void(Error)> Warn) {
     addRecord(std::move(I), 1, Warn);
   }
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index ea9e0ea2e1292..c175723bb41c7 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -320,6 +320,8 @@ std::string getPGOFuncName(StringRef Name, GlobalValue::LinkageTypes Linkage,
     else
       NewName = NewName.insert(0, FileName.str() + ":");
   }
+
+  
   return NewName;
 }
 
@@ -606,7 +608,6 @@ Error readAndDecodeStrings(StringRef NameStrings,
     SmallVector<StringRef, 0> Names;
     StringRef ArchRef(Architecture); 
     NameStrings.split(Names, getInstrProfNameSeparator());
-    printf("=====================READER DATA====================");
     for (StringRef &Name : Names){
       std::string ConcHashString = Name.str() + ":" + ArchRef.str();
       printf("The string %s will get hashed and mapped to %s\n", ConcHashString.c_str(), Name.str().c_str());
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 7ca26aa138012..4dfeeca00d988 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -153,11 +153,11 @@ void InstrProfWriter::setValueProfDataEndianness(llvm::endianness Endianness) {
 
 void InstrProfWriter::setOutputSparse(bool Sparse) { this->Sparse = Sparse; }
 
-void InstrProfWriter::addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
+void InstrProfWriter::addRecord(NamedInstrProfRecord &&I, uint64_t Weight, const std::string &Architecture,
                                 function_ref<void(Error)> Warn) {
   auto Name = I.Name;
   auto Hash = I.Hash;
-  addRecord(Name, Hash, std::move(I), Weight, Warn);
+  addRecord(Name, Hash, std::move(I), Weight, Warn, Architecture);
 }
 
 void InstrProfWriter::overlapRecord(NamedInstrProfRecord &&Other,
@@ -216,6 +216,34 @@ void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
   Dest.sortValueData();
 }
 
+void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
+                                InstrProfRecord &&I, uint64_t Weight,
+                                function_ref<void(Error)> Warn, const std::string &Architecture) {
+  auto &ProfileDataMap = FunctionData[Name];
+  std::string HashStr = std::to_string(Hash) + ":" + Architecture;
+  llvm::StringRef HashRef(HashStr);
+  uint64_t NewHash = IndexedInstrProf::ComputeHash(HashRef);
+
+  auto [Where, NewFunc] = ProfileDataMap.try_emplace(NewHash);
+  InstrProfRecord &Dest = Where->second;
+
+  auto MapWarn = [&](instrprof_error E) {
+    Warn(make_error<InstrProfError>(E));
+  };
+
+  if (NewFunc) {
+    // We've never seen a function with this name and hash, add it.
+    Dest = std::move(I);
+    if (Weight > 1)
+      Dest.scale(Weight, 1, MapWarn);
+  } else {
+    // We're updating a function we've seen before.
+    Dest.merge(I, Weight, MapWarn);
+  }
+
+  Dest.sortValueData();
+}
+
 void InstrProfWriter::addMemProfRecord(
     const Function::GUID Id, const memprof::IndexedMemProfRecord &Record) {
   auto NewRecord = Record;
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 2b53b7e77f0a7..3d3fd34a493ab 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -862,7 +862,7 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
       I.Name = (*Remapper)(I.Name);
     const StringRef FuncName = I.Name;
     bool Reported = false;
-    WC->Writer.addRecord(std::move(I), Input.Weight, [&](Error E) {
+    WC->Writer.addRecord(std::move(I), Input.Weight, Architecture, [&](Error E) {
       if (Reported) {
         consumeError(std::move(E));
         return;

>From 1d6ae59767ab3bae2cd4a3b77781658cf06c6eca Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Tue, 8 Jul 2025 08:26:10 -0700
Subject: [PATCH 05/17] saving changes to compare with main branch

---
 .../ProfileData/Coverage/CoverageMapping.h    |  35 +++-
 .../Coverage/CoverageMappingReader.h          |   9 +-
 llvm/include/llvm/ProfileData/InstrProf.h     |  32 +--
 .../llvm/ProfileData/InstrProfReader.h        |   4 +
 .../ProfileData/Coverage/CoverageMapping.cpp  | 189 +++++++++++++++++-
 .../Coverage/CoverageMappingReader.cpp        |  33 +--
 llvm/lib/ProfileData/InstrProf.cpp            |   3 +-
 llvm/lib/ProfileData/InstrProfReader.cpp      |  22 ++
 8 files changed, 280 insertions(+), 47 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 7d1a85ba528fc..555c7e5f37f2b 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -993,6 +993,7 @@ class CoverageMapping {
   std::vector<FunctionRecord> Functions;
   DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices;
   std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
+  StringRef Arch;
 
   std::optional<bool> SingleByteCoverage;
 
@@ -1000,10 +1001,16 @@ class CoverageMapping {
 
   // Load coverage records from readers.
   static Error loadFromReaders(
-      ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
-      std::optional<std::reference_wrapper<IndexedInstrProfReader>>
-          &ProfileReader,
-      CoverageMapping &Coverage);
+    ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
+    std::optional<std::reference_wrapper<IndexedInstrProfReader>>
+        &ProfileReader,
+    CoverageMapping &Coverage, StringRef Arch);
+  
+  static Error loadFromReaders(
+    ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
+    std::optional<std::reference_wrapper<IndexedInstrProfReader>>
+        &ProfileReader,
+    CoverageMapping &Coverage);
 
   // Load coverage records from file.
   static Error
@@ -1018,6 +1025,8 @@ class CoverageMapping {
       const CoverageMappingRecord &Record,
       const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
           &ProfileReader);
+  
+  Error loadFunctionRecord(const CoverageMappingRecord &Record, const std::optional<std::reference_wrapper<IndexedInstrProfReader>> &ProfileReader, const std::string &Arch);
 
   /// Look up the indices for function records which are at least partially
   /// defined in the specified file. This is guaranteed to return a superset of
@@ -1027,6 +1036,13 @@ class CoverageMapping {
   getImpreciseRecordIndicesForFilename(StringRef Filename) const;
 
 public:
+
+  const StringRef &getArchitecture() const { return Arch; }
+
+  void setArchitecture(StringRef NewArch){
+    Arch = StringRef(NewArch);
+  }
+
   CoverageMapping(const CoverageMapping &) = delete;
   CoverageMapping &operator=(const CoverageMapping &) = delete;
 
@@ -1234,8 +1250,9 @@ uint64_t getFuncNameRef(const FuncRecordTy *Record) {
 /// a hash.
 template <class FuncRecordTy, llvm::endianness Endian>
 Error getFuncNameViaRef(const FuncRecordTy *Record,
-                        InstrProfSymtab &ProfileNames, StringRef &FuncName) {
+                        InstrProfSymtab &ProfileNames, StringRef &FuncName, StringRef Arch = "") {
   uint64_t NameRef = getFuncNameRef<FuncRecordTy, Endian>(Record);
+  ProfileNames.setArchitecture(Arch.str());
   FuncName = ProfileNames.getFuncOrVarName(NameRef);
   return Error::success();
 }
@@ -1285,7 +1302,7 @@ struct CovMapFunctionRecordV1 {
 
   /// Return the PGO name of the function.
   template <llvm::endianness Endian>
-  Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
+  Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName, StringRef Arch = "") const {
     IntPtrT NameRef = getFuncNameRef<Endian>();
     uint32_t NameS = support::endian::byte_swap<uint32_t, Endian>(NameSize);
     FuncName = ProfileNames.getFuncName(NameRef, NameS);
@@ -1334,7 +1351,7 @@ struct CovMapFunctionRecordV2 {
   }
 
   template <llvm::endianness Endian>
-  Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
+  Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName, StringRef Arch = "") const {
     return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
                                                        FuncName);
   }
@@ -1378,9 +1395,9 @@ struct CovMapFunctionRecordV3 {
   }
 
   template <llvm::endianness Endian>
-  Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName) const {
+  Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName, StringRef Arch = "") const {
     return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
-                                                       FuncName);
+                                                       FuncName, Arch);
   }
 
   /// Get the filename set reference.
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
index e91ba9147a745..7cf09e29f2145 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -39,6 +39,12 @@ struct CoverageMappingRecord {
   ArrayRef<StringRef> Filenames;
   ArrayRef<CounterExpression> Expressions;
   ArrayRef<CounterMappingRegion> MappingRegions;
+  StringRef Arch;
+
+  const StringRef &getArchitecture() const { return Arch; }
+  void setArchitecture(StringRef NewArch){
+    Arch = StringRef(NewArch);
+  }
 };
 
 /// A file format agnostic iterator over coverage mapping data.
@@ -191,6 +197,7 @@ class LLVM_ABI BinaryCoverageReader : public CoverageMappingReader {
   std::vector<StringRef> FunctionsFilenames;
   std::vector<CounterExpression> Expressions;
   std::vector<CounterMappingRegion> MappingRegions;
+  StringRef Arch;
 
   // Used to tie the lifetimes of coverage function records to the lifetime of
   // this BinaryCoverageReader instance. Needed to support the format change in
@@ -223,7 +230,7 @@ class LLVM_ABI BinaryCoverageReader : public CoverageMappingReader {
       StringRef Coverage, FuncRecordsStorage &&FuncRecords,
       CoverageMapCopyStorage &&CoverageMap,
       std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress,
-      llvm::endianness Endian, StringRef CompilationDir = "");
+      llvm::endianness Endian, StringRef CompilationDir = "", StringRef Arch = "");
 
   Error readNextRecord(CoverageMappingRecord &Record) override;
 };
diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index e9c21c5fc284b..747853f3af8e9 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -636,7 +636,7 @@ class InstrProfSymtab {
   // Map the MD5 of the symbol name to the name.
   Error addSymbolName(StringRef SymbolName) {
     StringRef FuncName;
-    StringRef ArchName;
+    StringRef ArchName = "";
     std::tie(FuncName, ArchName) = SymbolName.split(":");
     if (SymbolName.empty())
       return make_error<InstrProfError>(instrprof_error::malformed,
@@ -644,14 +644,15 @@ class InstrProfSymtab {
 
     // Insert into NameTab so that MD5NameMap (a vector that will be sorted)
     // won't have duplicated entries in the first place.
-    
     uint64_t HashValue = IndexedInstrProf::ComputeHash(FuncName);
-    std::string HashStr = std::to_string(HashValue);
-    std::string CombinedStr = HashStr + ":" + ArchName.str();
-    llvm::StringRef HashRef(CombinedStr);
-    HashValue = IndexedInstrProf::ComputeHash(HashRef);
-
-    printf("Hash Value for %.*s: %" PRIu64 "\n", static_cast<int>(SymbolName.size()), SymbolName.data(), HashValue);
+    llvm::StringRef HashRef(FuncName);
+    if(!ArchName.empty()){
+      std::string HashStr = std::to_string(HashValue);
+      std::string CombinedStr = HashStr + ":" + ArchName.str();
+      HashRef = CombinedStr;
+      HashValue = IndexedInstrProf::ComputeHash(HashRef);
+    }
+    printf("Hash Value for %.*s %" PRIu64 "\n", static_cast<int>(SymbolName.size()), SymbolName.data(), HashValue);
     auto Ins = NameTab.insert(FuncName);
     printf("mapped value for %" PRIu64 " hash: %.*s\n", HashValue, static_cast<int>(Ins.first->getKey().size()), Ins.first->getKey().data());
     if (Ins.second) {
@@ -786,13 +787,14 @@ StringRef InstrProfSymtab::getFuncOrVarNameIfDefined(uint64_t MD5Hash) {
 StringRef InstrProfSymtab::getFuncOrVarName(uint64_t MD5Hash) {
   finalizeSymtab();
   std::string TempMD5HashStr = std::to_string(MD5Hash);
-  std::string CombinedHashStr = TempMD5HashStr + ":" + Architecture;
-  llvm::StringRef CombinedHashRef(CombinedHashStr);
-  uint64_t NewMD5Hash = IndexedInstrProf::ComputeHash(CombinedHashRef);
-  auto Result = llvm::lower_bound(MD5NameMap, NewMD5Hash,
-                                  [](const std::pair<uint64_t, StringRef> &LHS,
-                                     uint64_t RHS) { return LHS.first < RHS; });
-  if (Result != MD5NameMap.end() && Result->first == NewMD5Hash)
+  if(!Architecture.empty()){
+    std::string CombinedHashStr = TempMD5HashStr + ":" + Architecture;
+    llvm::StringRef CombinedHashRef(CombinedHashStr);
+    MD5Hash = IndexedInstrProf::ComputeHash(CombinedHashRef);
+  }
+  auto Result = llvm::lower_bound(MD5NameMap, MD5Hash, [](const std::pair<uint64_t, StringRef> &LHS, uint64_t RHS) { return LHS.first < RHS; });
+  llvm::errs() << "Architecture: " << (!Architecture.empty() ? Architecture : "No Specified Architecture") << ": " << Result->second<< ": " << "Result->first: " << Result->first << " vs. MD5hash: " << MD5Hash << "\n";
+  if (Result != MD5NameMap.end() && Result->first == MD5Hash)
     return Result->second;
   return StringRef();
 }
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index b92253a81502d..70b54d1fa0fba 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -875,6 +875,10 @@ class LLVM_ABI IndexedInstrProfReader : public InstrProfReader {
   create(const Twine &Path, vfs::FileSystem &FS,
          const Twine &RemappingPath = "");
 
+  static Expected<std::unique_ptr<IndexedInstrProfReader>>
+  create(const Twine &Path, vfs::FileSystem &FS,
+        const std::string &Arch, const Twine &RemappingPath = "");
+
   static Expected<std::unique_ptr<IndexedInstrProfReader>>
   create(std::unique_ptr<MemoryBuffer> Buffer,
          std::unique_ptr<MemoryBuffer> RemappingBuffer = nullptr);
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 429ec5c19f1f8..a034ac7dd2e69 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -821,6 +821,154 @@ class MCDCDecisionRecorder {
 
 } // namespace
 
+Error CoverageMapping::loadFunctionRecord(
+    const CoverageMappingRecord &Record,
+    const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
+        &ProfileReader, const std::string &Arch) {
+  StringRef OrigFuncName = Record.FunctionName;
+  if (OrigFuncName.empty())
+    return make_error<CoverageMapError>(coveragemap_error::malformed,
+                                        "record function name is empty");
+
+  if (Record.Filenames.empty())
+    OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
+  else
+    OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
+
+  CounterMappingContext Ctx(Record.Expressions);
+
+  std::string HashStr = std::to_string(Record.FunctionHash) + ":" + Arch;
+  llvm::StringRef HashRef(HashStr);
+  uint64_t NewHash = IndexedInstrProf::ComputeHash(HashRef);
+
+  std::vector<uint64_t> Counts;
+  if (ProfileReader) {
+    if (Error E = ProfileReader.value().get().getFunctionCounts(
+            Record.FunctionName, NewHash, Counts)) {
+      instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
+      if (IPE == instrprof_error::hash_mismatch) {
+        FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
+                                        NewHash);
+        return Error::success();
+      }
+      if (IPE != instrprof_error::unknown_function)
+        return make_error<InstrProfError>(IPE);
+      Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0);
+    }
+  } else {
+    Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0);
+  }
+  Ctx.setCounts(Counts);
+
+  bool IsVersion11 =
+      ProfileReader && ProfileReader.value().get().getVersion() <
+                           IndexedInstrProf::ProfVersion::Version12;
+
+  BitVector Bitmap;
+  if (ProfileReader) {
+    if (Error E = ProfileReader.value().get().getFunctionBitmap(
+            Record.FunctionName, NewHash, Bitmap)) {
+      instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
+      if (IPE == instrprof_error::hash_mismatch) {
+        FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
+                                        NewHash);
+        return Error::success();
+      }
+      if (IPE != instrprof_error::unknown_function)
+        return make_error<InstrProfError>(IPE);
+      Bitmap = BitVector(getMaxBitmapSize(Record, IsVersion11));
+    }
+  } else {
+    Bitmap = BitVector(getMaxBitmapSize(Record, false));
+  }
+  Ctx.setBitmap(std::move(Bitmap));
+
+  assert(!Record.MappingRegions.empty() && "Function has no regions");
+
+  // This coverage record is a zero region for a function that's unused in
+  // some TU, but used in a different TU. Ignore it. The coverage maps from the
+  // the other TU will either be loaded (providing full region counts) or they
+  // won't (in which case we don't unintuitively report functions as uncovered
+  // when they have non-zero counts in the profile).
+  if (Record.MappingRegions.size() == 1 &&
+      Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
+    return Error::success();
+
+  MCDCDecisionRecorder MCDCDecisions;
+  FunctionRecord Function(OrigFuncName, Record.Filenames);
+  for (const auto &Region : Record.MappingRegions) {
+    // MCDCDecisionRegion should be handled first since it overlaps with
+    // others inside.
+    if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) {
+      MCDCDecisions.registerDecision(Region);
+      continue;
+    }
+    Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
+    if (auto E = ExecutionCount.takeError()) {
+      consumeError(std::move(E));
+      return Error::success();
+    }
+    Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);
+    if (auto E = AltExecutionCount.takeError()) {
+      consumeError(std::move(E));
+      return Error::success();
+    }
+    Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
+
+    // Record ExpansionRegion.
+    if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
+      MCDCDecisions.recordExpansion(Region);
+      continue;
+    }
+
+    // Do nothing unless MCDCBranchRegion.
+    if (Region.Kind != CounterMappingRegion::MCDCBranchRegion)
+      continue;
+
+    auto Result = MCDCDecisions.processBranch(Region);
+    if (!Result) // Any Decision doesn't complete.
+      continue;
+
+    auto MCDCDecision = Result->first;
+    auto &MCDCBranches = Result->second;
+
+    // Since the bitmap identifies the executed test vectors for an MC/DC
+    // DecisionRegion, all of the information is now available to process.
+    // This is where the bulk of the MC/DC progressing takes place.
+    Expected<MCDCRecord> Record =
+        Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches, IsVersion11);
+    if (auto E = Record.takeError()) {
+      consumeError(std::move(E));
+      return Error::success();
+    }
+
+    // Save the MC/DC Record so that it can be visualized later.
+    Function.pushMCDCRecord(std::move(*Record));
+  }
+
+  // Don't create records for (filenames, function) pairs we've already seen.
+  auto FilenamesHash = hash_combine_range(Record.Filenames);
+  if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
+    return Error::success();
+
+  Functions.push_back(std::move(Function));
+
+  // Performance optimization: keep track of the indices of the function records
+  // which correspond to each filename. This can be used to substantially speed
+  // up queries for coverage info in a file.
+  unsigned RecordIndex = Functions.size() - 1;
+  for (StringRef Filename : Record.Filenames) {
+    auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)];
+    // Note that there may be duplicates in the filename set for a function
+    // record, because of e.g. macro expansions in the function in which both
+    // the macro and the function are defined in the same file.
+    if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
+      RecordIndices.push_back(RecordIndex);
+  }
+
+  return Error::success();
+}
+
 Error CoverageMapping::loadFunctionRecord(
     const CoverageMappingRecord &Record,
     const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
@@ -837,14 +985,18 @@ Error CoverageMapping::loadFunctionRecord(
 
   CounterMappingContext Ctx(Record.Expressions);
 
+  std::string HashStr = std::to_string(Record.FunctionHash) + ":" + Arch.str();
+  llvm::StringRef HashRef(HashStr);
+  uint64_t NewHash = IndexedInstrProf::ComputeHash(HashRef);
+
   std::vector<uint64_t> Counts;
   if (ProfileReader) {
     if (Error E = ProfileReader.value().get().getFunctionCounts(
-            Record.FunctionName, Record.FunctionHash, Counts)) {
+            Record.FunctionName, NewHash, Counts)) {
       instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
       if (IPE == instrprof_error::hash_mismatch) {
         FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
-                                        Record.FunctionHash);
+                                        NewHash);
         return Error::success();
       }
       if (IPE != instrprof_error::unknown_function)
@@ -863,11 +1015,11 @@ Error CoverageMapping::loadFunctionRecord(
   BitVector Bitmap;
   if (ProfileReader) {
     if (Error E = ProfileReader.value().get().getFunctionBitmap(
-            Record.FunctionName, Record.FunctionHash, Bitmap)) {
+            Record.FunctionName, NewHash, Bitmap)) {
       instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
       if (IPE == instrprof_error::hash_mismatch) {
         FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
-                                        Record.FunctionHash);
+                                        NewHash);
         return Error::success();
       }
       if (IPE != instrprof_error::unknown_function)
@@ -989,6 +1141,31 @@ Error CoverageMapping::loadFromReaders(
   return Error::success();
 }
 
+
+Error CoverageMapping::loadFromReaders(
+    ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
+    std::optional<std::reference_wrapper<IndexedInstrProfReader>>
+        &ProfileReader,
+    CoverageMapping &Coverage, StringRef Arch) {
+  
+  Coverage.setArchitecture(Arch);
+  assert(!Coverage.SingleByteCoverage || !ProfileReader ||
+         *Coverage.SingleByteCoverage ==
+             ProfileReader.value().get().hasSingleByteCoverage());
+  Coverage.SingleByteCoverage =
+      !ProfileReader || ProfileReader.value().get().hasSingleByteCoverage();
+  for (const auto &CoverageReader : CoverageReaders) {
+    for (auto RecordOrErr : *CoverageReader) {
+      if (Error E = RecordOrErr.takeError())
+        return E;
+      const auto &Record = *RecordOrErr;
+      if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader))
+        return E;
+    }
+  }
+  return Error::success();
+}
+
 Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
     std::optional<std::reference_wrapper<IndexedInstrProfReader>>
@@ -1022,6 +1199,8 @@ Error CoverageMapping::loadFromFile(
       CovMappingBufOrErr.get()->getMemBufferRef();
   SmallVector<std::unique_ptr<MemoryBuffer>, 4> Buffers;
 
+
+
   SmallVector<object::BuildIDRef> BinaryIDs;
   auto CoverageReadersOrErr = BinaryCoverageReader::create(
       CovMappingBufRef, Arch, Buffers, CompilationDir,
@@ -1043,7 +1222,7 @@ Error CoverageMapping::loadFromFile(
                        }));
   }
   DataFound |= !Readers.empty();
-  if (Error E = loadFromReaders(Readers, ProfileReader, Coverage))
+  if (Error E = loadFromReaders(Readers, ProfileReader, Coverage, Arch))
     return createFileError(Filename, std::move(E));
   return Error::success();
 }
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
index cdf4412c6477a..aa5b714bbdec8 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -579,13 +579,13 @@ struct CovMapFuncRecordReader {
   readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
                       std::optional<FilenameRange> OutOfLineFileRange,
                       const char *OutOfLineMappingBuf,
-                      const char *OutOfLineMappingBufEnd) = 0;
+                      const char *OutOfLineMappingBufEnd, StringRef Arch = "") = 0;
 
   template <class IntPtrT, llvm::endianness Endian>
   static Expected<std::unique_ptr<CovMapFuncRecordReader>>
   get(CovMapVersion Version, InstrProfSymtab &P,
       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
-      std::vector<std::string> &F);
+      std::vector<std::string> &F, StringRef Arch = "");
 };
 
 // A class for reading coverage mapping function records for a module.
@@ -615,7 +615,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
   // not used in the corresponding translation unit.
   Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
                                      StringRef Mapping,
-                                     FilenameRange FileRange) {
+                                     FilenameRange FileRange, StringRef Arch = "") {
     ++CovMapNumRecords;
     uint64_t FuncHash = CFR->template getFuncHash<Endian>();
     NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
@@ -623,7 +623,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
         FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
     if (InsertResult.second) {
       StringRef FuncName;
-      if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName))
+      if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName, Arch))
         return Err;
       if (FuncName.empty())
         return make_error<InstrProfError>(instrprof_error::malformed,
@@ -762,7 +762,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
   Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
                             std::optional<FilenameRange> OutOfLineFileRange,
                             const char *OutOfLineMappingBuf,
-                            const char *OutOfLineMappingBufEnd) override {
+                            const char *OutOfLineMappingBufEnd, StringRef Arch = "") override {
     auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);
     while ((const char *)CFR < FuncRecBufEnd) {
       // Validate the length of the coverage mapping for this function.
@@ -801,7 +801,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
           return make_error<CoverageMapError>(
               coveragemap_error::malformed,
               "coverage mapping data is larger than buffer size");
-        if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange))
+        if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange, Arch))
           return Err;
       }
 
@@ -817,7 +817,7 @@ template <class IntPtrT, llvm::endianness Endian>
 Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
     CovMapVersion Version, InstrProfSymtab &P,
     std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
-    std::vector<std::string> &F) {
+    std::vector<std::string> &F, StringRef Arch) {
   using namespace coverage;
 
   switch (Version) {
@@ -831,6 +831,7 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
   case CovMapVersion::Version6:
   case CovMapVersion::Version7:
     // Decompress the name data.
+    P.setArchitecture(Arch.str());
     if (Error E = P.create(P.getNameData()))
       return std::move(E);
     if (Version == CovMapVersion::Version2)
@@ -859,7 +860,7 @@ template <typename T, llvm::endianness Endian>
 static Error readCoverageMappingData(
     InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
-    StringRef CompilationDir, std::vector<std::string> &Filenames) {
+    StringRef CompilationDir, std::vector<std::string> &Filenames, StringRef Arch = "") {
   using namespace coverage;
 
   // Read the records in the coverage data section.
@@ -870,7 +871,7 @@ static Error readCoverageMappingData(
     return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
   Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
       CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
-                                             CompilationDir, Filenames);
+                                             CompilationDir, Filenames, Arch);
   if (Error E = ReaderExpected.takeError())
     return E;
   auto Reader = std::move(ReaderExpected.get());
@@ -894,7 +895,7 @@ static Error readCoverageMappingData(
   // the records from their dedicated section.
   if (Version >= CovMapVersion::Version4)
     return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, std::nullopt,
-                                       nullptr, nullptr);
+                                       nullptr, nullptr, Arch);
   return Error::success();
 }
 
@@ -903,7 +904,7 @@ BinaryCoverageReader::createCoverageReaderFromBuffer(
     StringRef Coverage, FuncRecordsStorage &&FuncRecords,
     CoverageMapCopyStorage &&CoverageMap,
     std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress,
-    llvm::endianness Endian, StringRef CompilationDir) {
+    llvm::endianness Endian, StringRef CompilationDir, StringRef Arch) {
   if (ProfileNamesPtr == nullptr)
     return make_error<CoverageMapError>(coveragemap_error::malformed,
                                         "Caller must provide ProfileNames");
@@ -915,22 +916,22 @@ BinaryCoverageReader::createCoverageReaderFromBuffer(
   if (BytesInAddress == 4 && Endian == llvm::endianness::little) {
     if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::little>(
             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
-            CompilationDir, Reader->Filenames))
+            CompilationDir, Reader->Filenames, Arch))
       return std::move(E);
   } else if (BytesInAddress == 4 && Endian == llvm::endianness::big) {
     if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::big>(
             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
-            CompilationDir, Reader->Filenames))
+            CompilationDir, Reader->Filenames, Arch))
       return std::move(E);
   } else if (BytesInAddress == 8 && Endian == llvm::endianness::little) {
     if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::little>(
             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
-            CompilationDir, Reader->Filenames))
+            CompilationDir, Reader->Filenames, Arch))
       return std::move(E);
   } else if (BytesInAddress == 8 && Endian == llvm::endianness::big) {
     if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::big>(
             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
-            CompilationDir, Reader->Filenames))
+            CompilationDir, Reader->Filenames, Arch))
       return std::move(E);
   } else
     return make_error<CoverageMapError>(
@@ -1250,7 +1251,7 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
 
   return BinaryCoverageReader::createCoverageReaderFromBuffer(
       CoverageMapping, std::move(FuncRecords), std::move(CoverageMapCopy),
-      std::move(ProfileNames), BytesInAddress, Endian, CompilationDir);
+      std::move(ProfileNames), BytesInAddress, Endian, CompilationDir, Arch);
 }
 
 /// Determine whether \p Arch is invalid or empty, given \p Bin.
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index c175723bb41c7..9998adc5b2343 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -668,7 +668,8 @@ Error readAndDecodeStrings(StringRef NameStrings,
 }
 
 Error InstrProfSymtab::create(StringRef NameStrings) {
-  return readAndDecodeStrings(NameStrings, std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1));
+  const std::string &Architecture = getArchitecture();
+  return readAndDecodeStrings(NameStrings, std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1), Architecture);
 }
 
 Error InstrProfSymtab::create(StringRef FuncNameStrings,
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 33b62cf5cca5c..33ebcfd3200b2 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -226,6 +226,28 @@ IndexedInstrProfReader::create(const Twine &Path, vfs::FileSystem &FS,
                                         std::move(RemappingBuffer));
 }
 
+Expected<std::unique_ptr<IndexedInstrProfReader>>
+IndexedInstrProfReader::create(const Twine &Path, vfs::FileSystem &FS,
+                               const std::string &Arch, const Twine &RemappingPath) {
+  // Set up the buffer to read.
+  auto BufferOrError = setupMemoryBuffer(Path, FS);
+  if (Error E = BufferOrError.takeError())
+    return std::move(E);
+
+  // Set up the remapping buffer if requested.
+  std::unique_ptr<MemoryBuffer> RemappingBuffer;
+  std::string RemappingPathStr = RemappingPath.str();
+  if (!RemappingPathStr.empty()) {
+    auto RemappingBufferOrError = setupMemoryBuffer(RemappingPathStr, FS);
+    if (Error E = RemappingBufferOrError.takeError())
+      return std::move(E);
+    RemappingBuffer = std::move(RemappingBufferOrError.get());
+  }
+
+  return IndexedInstrProfReader::create(std::move(BufferOrError.get()),
+                                        std::move(RemappingBuffer));
+}
+
 Expected<std::unique_ptr<IndexedInstrProfReader>>
 IndexedInstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
                                std::unique_ptr<MemoryBuffer> RemappingBuffer) {

>From 451e0fd2bbef42ce263e28a0c0d2c84123011c0e Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Tue, 8 Jul 2025 13:41:49 -0700
Subject: [PATCH 06/17] fixed bug messing up coremark build, it was getting
 rehashed when hash was inserted into MD5NameMap

---
 llvm/include/llvm/ProfileData/InstrProf.h | 21 ++++++++++++++++-----
 llvm/lib/ProfileData/InstrProf.cpp        |  2 +-
 2 files changed, 17 insertions(+), 6 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index 747853f3af8e9..19850c418db9d 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -636,14 +636,15 @@ class InstrProfSymtab {
   // Map the MD5 of the symbol name to the name.
   Error addSymbolName(StringRef SymbolName) {
     StringRef FuncName;
-    StringRef ArchName = "";
-    std::tie(FuncName, ArchName) = SymbolName.split(":");
+    StringRef ArchName = Architecture;
+    std::tie(FuncName, ArchName) = SymbolName.split("#");
     if (SymbolName.empty())
       return make_error<InstrProfError>(instrprof_error::malformed,
                                         "symbol name is empty");
 
     // Insert into NameTab so that MD5NameMap (a vector that will be sorted)
     // won't have duplicated entries in the first place.
+
     uint64_t HashValue = IndexedInstrProf::ComputeHash(FuncName);
     llvm::StringRef HashRef(FuncName);
     if(!ArchName.empty()){
@@ -652,14 +653,18 @@ class InstrProfSymtab {
       HashRef = CombinedStr;
       HashValue = IndexedInstrProf::ComputeHash(HashRef);
     }
+    llvm::errs() << "FuncName is " << FuncName << " is written in " << ArchName << "\n";
     printf("Hash Value for %.*s %" PRIu64 "\n", static_cast<int>(SymbolName.size()), SymbolName.data(), HashValue);
     auto Ins = NameTab.insert(FuncName);
     printf("mapped value for %" PRIu64 " hash: %.*s\n", HashValue, static_cast<int>(Ins.first->getKey().size()), Ins.first->getKey().data());
     if (Ins.second) {
-      MD5NameMap.push_back(std::make_pair(
-          IndexedInstrProf::ComputeHash(HashRef), Ins.first->getKey()));
+      MD5NameMap.push_back(std::make_pair(HashValue /*IndexedInstrProf::ComputeHash(HashRef)*/, Ins.first->getKey()));
       Sorted = false;
     }
+    llvm::errs() << "Hash values when inside of addSymbolName" << "\n";
+    for(int I = 0; I < int(MD5NameMap.size()); ++I){
+      llvm::errs() << "Hash: " << MD5NameMap[I].first << " Function Name: " << MD5NameMap[I].second << "\n";
+    }
     return Error::success();
   }
 
@@ -787,13 +792,19 @@ StringRef InstrProfSymtab::getFuncOrVarNameIfDefined(uint64_t MD5Hash) {
 StringRef InstrProfSymtab::getFuncOrVarName(uint64_t MD5Hash) {
   finalizeSymtab();
   std::string TempMD5HashStr = std::to_string(MD5Hash);
+  llvm::errs() << "Before: " << MD5Hash << "\n";
   if(!Architecture.empty()){
     std::string CombinedHashStr = TempMD5HashStr + ":" + Architecture;
     llvm::StringRef CombinedHashRef(CombinedHashStr);
     MD5Hash = IndexedInstrProf::ComputeHash(CombinedHashRef);
   }
+  llvm::errs() << "After: " << MD5Hash << "\n";
+  llvm::errs() << "Hash values when inside of getFuncOrVarName" << "\n";
+  for(int I = 0; I < int(MD5NameMap.size()); ++I){
+    llvm::errs() << "Hash: " << MD5NameMap[I].first << " Function Name: " << MD5NameMap[I].second << "\n";
+  }
   auto Result = llvm::lower_bound(MD5NameMap, MD5Hash, [](const std::pair<uint64_t, StringRef> &LHS, uint64_t RHS) { return LHS.first < RHS; });
-  llvm::errs() << "Architecture: " << (!Architecture.empty() ? Architecture : "No Specified Architecture") << ": " << Result->second<< ": " << "Result->first: " << Result->first << " vs. MD5hash: " << MD5Hash << "\n";
+  llvm::errs() << "Architecture: " << (!Architecture.empty() ? Architecture : "No Specified Architecture") << ": " << Result->second << ": " << "Result->first: " << Result->first << " vs. MD5hash: " << MD5Hash << "\n";
   if (Result != MD5NameMap.end() && Result->first == MD5Hash)
     return Result->second;
   return StringRef();
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index 9998adc5b2343..9a75164ebe698 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -615,7 +615,7 @@ Error readAndDecodeStrings(StringRef NameStrings,
         if (Error E = NameCallback(Name))
           return E;
       }else{
-        if (Error E = NameCallback(Name.str() + ":" + ArchRef.str()))
+        if (Error E = NameCallback(Name.str() + "#" + ArchRef.str()))
           return E;
       }
     }

>From 4b25f41035b11ca0230690d1978044f2dc743cca Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Fri, 11 Jul 2025 10:25:20 -0700
Subject: [PATCH 07/17] saving changes

---
 llvm/include/llvm/ProfileData/InstrProf.h     |  45 ++-
 .../llvm/ProfileData/InstrProfReader.h        |   8 +-
 .../llvm/ProfileData/InstrProfWriter.h        |  10 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  | 314 +++++++++---------
 llvm/lib/ProfileData/InstrProf.cpp            | 102 +++---
 llvm/lib/ProfileData/InstrProfReader.cpp      |   4 +-
 llvm/lib/ProfileData/InstrProfWriter.cpp      |  56 ++--
 llvm/tools/llvm-cov/CodeCoverage.cpp          |   8 +-
 llvm/tools/llvm-cov/SourceCoverageView.cpp    |  23 +-
 llvm/tools/llvm-cov/SourceCoverageView.h      |   5 +-
 .../tools/llvm-cov/SourceCoverageViewHTML.cpp |  25 ++
 llvm/tools/llvm-cov/SourceCoverageViewHTML.h  |   2 +
 .../tools/llvm-cov/SourceCoverageViewText.cpp |  21 +-
 llvm/tools/llvm-cov/SourceCoverageViewText.h  |   2 +
 llvm/tools/llvm-profdata/llvm-profdata.cpp    |   4 +-
 15 files changed, 342 insertions(+), 287 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index 19850c418db9d..98890b5541a8f 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -369,9 +369,9 @@ LLVM_ABI bool needsComdatForCounter(const GlobalObject &GV, const Module &M);
 /// InstrProf.h:getInstrProfNameSeparator). This method decodes the string and
 /// calls `NameCallback` for each substring.
 LLVM_ABI Error readAndDecodeStrings(
-    StringRef NameStrings, std::function<Error(StringRef)> NameCallback);
+    StringRef NameStrings, std::function<Error(StringRef)> NameCallback, StringRef Architecture = "");
+
 
-LLVM_ABI Error readAndDecodeStrings(StringRef NameStrings, std::function<Error(StringRef)> NameCallback, const std::string &Architecture);
 /// An enum describing the attributes of an instrumented profile.
 enum class InstrProfKind {
   Unknown = 0x0,
@@ -515,11 +515,11 @@ class InstrProfSymtab {
   LLVM_ABI static StringRef getCanonicalName(StringRef PGOName);
 
   //ANDRES Function
-  const std::string &getArchitecture() {return Architecture;}
-  void setArchitecture(const std::string &Arch) {Architecture = Arch;}
+  StringRef getArchitecture() {return Architecture;}
+  void setArchitecture(StringRef Arch) {Architecture = Arch;}
   //ANDRES Function
 private:
-  std::string Architecture;
+  StringRef Architecture;
   using AddrIntervalMap =
       IntervalMap<uint64_t, uint64_t, 4, IntervalMapHalfOpenInfo<uint64_t>>;
   StringRef Data;
@@ -635,9 +635,9 @@ class InstrProfSymtab {
 
   // Map the MD5 of the symbol name to the name.
   Error addSymbolName(StringRef SymbolName) {
-    StringRef FuncName;
-    StringRef ArchName = Architecture;
-    std::tie(FuncName, ArchName) = SymbolName.split("#");
+    // StringRef FuncName;
+    // StringRef ArchName = Architecture;
+    // std::tie(FuncName, ArchName) = SymbolName.split("#");
     if (SymbolName.empty())
       return make_error<InstrProfError>(instrprof_error::malformed,
                                         "symbol name is empty");
@@ -645,25 +645,20 @@ class InstrProfSymtab {
     // Insert into NameTab so that MD5NameMap (a vector that will be sorted)
     // won't have duplicated entries in the first place.
 
-    uint64_t HashValue = IndexedInstrProf::ComputeHash(FuncName);
-    llvm::StringRef HashRef(FuncName);
-    if(!ArchName.empty()){
+    uint64_t HashValue = IndexedInstrProf::ComputeHash(SymbolName);
+    llvm::StringRef HashRef(SymbolName);
+    if(!Architecture.empty()){
       std::string HashStr = std::to_string(HashValue);
-      std::string CombinedStr = HashStr + ":" + ArchName.str();
+      std::string CombinedStr = HashStr + ":" + Architecture.str();
       HashRef = CombinedStr;
       HashValue = IndexedInstrProf::ComputeHash(HashRef);
     }
-    llvm::errs() << "FuncName is " << FuncName << " is written in " << ArchName << "\n";
-    printf("Hash Value for %.*s %" PRIu64 "\n", static_cast<int>(SymbolName.size()), SymbolName.data(), HashValue);
-    auto Ins = NameTab.insert(FuncName);
-    printf("mapped value for %" PRIu64 " hash: %.*s\n", HashValue, static_cast<int>(Ins.first->getKey().size()), Ins.first->getKey().data());
+    auto Ins = NameTab.insert(SymbolName);
     if (Ins.second) {
       MD5NameMap.push_back(std::make_pair(HashValue /*IndexedInstrProf::ComputeHash(HashRef)*/, Ins.first->getKey()));
       Sorted = false;
     }
-    llvm::errs() << "Hash values when inside of addSymbolName" << "\n";
     for(int I = 0; I < int(MD5NameMap.size()); ++I){
-      llvm::errs() << "Hash: " << MD5NameMap[I].first << " Function Name: " << MD5NameMap[I].second << "\n";
     }
     return Error::success();
   }
@@ -792,19 +787,17 @@ StringRef InstrProfSymtab::getFuncOrVarNameIfDefined(uint64_t MD5Hash) {
 StringRef InstrProfSymtab::getFuncOrVarName(uint64_t MD5Hash) {
   finalizeSymtab();
   std::string TempMD5HashStr = std::to_string(MD5Hash);
-  llvm::errs() << "Before: " << MD5Hash << "\n";
   if(!Architecture.empty()){
-    std::string CombinedHashStr = TempMD5HashStr + ":" + Architecture;
+    std::string CombinedHashStr = TempMD5HashStr + ":" + Architecture.str();
     llvm::StringRef CombinedHashRef(CombinedHashStr);
     MD5Hash = IndexedInstrProf::ComputeHash(CombinedHashRef);
   }
-  llvm::errs() << "After: " << MD5Hash << "\n";
-  llvm::errs() << "Hash values when inside of getFuncOrVarName" << "\n";
-  for(int I = 0; I < int(MD5NameMap.size()); ++I){
-    llvm::errs() << "Hash: " << MD5NameMap[I].first << " Function Name: " << MD5NameMap[I].second << "\n";
-  }
   auto Result = llvm::lower_bound(MD5NameMap, MD5Hash, [](const std::pair<uint64_t, StringRef> &LHS, uint64_t RHS) { return LHS.first < RHS; });
-  llvm::errs() << "Architecture: " << (!Architecture.empty() ? Architecture : "No Specified Architecture") << ": " << Result->second << ": " << "Result->first: " << Result->first << " vs. MD5hash: " << MD5Hash << "\n";
+
+  // for(auto name : MD5NameMap){
+  //   llvm::errs() << "Function Name " << name.second  << " Result->first: " << name.first << "\n";
+  // }
+  // llvm::errs() << "Function Name " << Result->second  << " Result->first: " << Result->first << " vs. " << MD5Hash << "\n";
   if (Result != MD5NameMap.end() && Result->first == MD5Hash)
     return Result->second;
   return StringRef();
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index 70b54d1fa0fba..e2ed1cb8cf399 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -213,7 +213,7 @@ class InstrProfReader {
       const object::BuildIDFetcher *BIDFetcher = nullptr,
       const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind =
           InstrProfCorrelator::ProfCorrelatorKind::NONE,
-      std::function<void(Error)> Warn = nullptr, const std::string &Architecture = "");
+      std::function<void(Error)> Warn = nullptr, StringRef Architecture = "");
 
   LLVM_ABI static Expected<std::unique_ptr<InstrProfReader>> create(
       std::unique_ptr<MemoryBuffer> Buffer,
@@ -221,11 +221,11 @@ class InstrProfReader {
       const object::BuildIDFetcher *BIDFetcher = nullptr,
       const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind =
           InstrProfCorrelator::ProfCorrelatorKind::NONE,
-      std::function<void(Error)> Warn = nullptr, const std::string &Architecture = "");
+      std::function<void(Error)> Warn = nullptr, StringRef Architecture = "");
   
-  const std::string &getArchitecture() {return Architecture;}
+  StringRef getArchitecture() {return Architecture;}
 
-  void setArchitecture(const std::string &Arch) {Architecture = Arch;}
+  void setArchitecture(StringRef Arch) {Architecture = Arch;}
   /// \param Weight for raw profiles use this as the temporal profile trace
   ///               weight
   /// \returns a list of temporal profile traces.
diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h
index e281e100bf808..77c93c537f468 100644
--- a/llvm/include/llvm/ProfileData/InstrProfWriter.h
+++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h
@@ -113,12 +113,8 @@ class InstrProfWriter {
   /// for this function and the hash and number of counts match, each counter is
   /// summed. Optionally scale counts by \p Weight.
   LLVM_ABI void addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
-                          function_ref<void(Error)> Warn);
-  LLVM_ABI void addRecord(StringRef Name, uint64_t Hash,
-                                InstrProfRecord &&I, uint64_t Weight,
-                                function_ref<void(Error)> Warn, const std::string &Architecture);
-  void addRecord(NamedInstrProfRecord &&I, uint64_t Weight, const std::string &Architecture,
-                                function_ref<void(Error)> Warn);
+                          function_ref<void(Error)> Warn, StringRef Architecture = "");
+  // void addRecord(NamedInstrProfRecord &&I, uint64_t Weight, function_ref<void(Error)> Warn);
   void addRecord(NamedInstrProfRecord &&I, function_ref<void(Error)> Warn) {
     addRecord(std::move(I), 1, Warn);
   }
@@ -229,7 +225,7 @@ class InstrProfWriter {
 
 private:
   void addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I,
-                 uint64_t Weight, function_ref<void(Error)> Warn);
+                 uint64_t Weight, function_ref<void(Error)> Warn, StringRef Architecture = "");
   bool shouldEncodeData(const ProfilingData &PD);
   /// Add \p Trace using reservoir sampling.
   void addTemporalProfileTrace(TemporalProfTraceTy Trace);
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index a034ac7dd2e69..0a391b3d56773 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -821,153 +821,156 @@ class MCDCDecisionRecorder {
 
 } // namespace
 
-Error CoverageMapping::loadFunctionRecord(
-    const CoverageMappingRecord &Record,
-    const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
-        &ProfileReader, const std::string &Arch) {
-  StringRef OrigFuncName = Record.FunctionName;
-  if (OrigFuncName.empty())
-    return make_error<CoverageMapError>(coveragemap_error::malformed,
-                                        "record function name is empty");
-
-  if (Record.Filenames.empty())
-    OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
-  else
-    OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
-
-  CounterMappingContext Ctx(Record.Expressions);
-
-  std::string HashStr = std::to_string(Record.FunctionHash) + ":" + Arch;
-  llvm::StringRef HashRef(HashStr);
-  uint64_t NewHash = IndexedInstrProf::ComputeHash(HashRef);
-
-  std::vector<uint64_t> Counts;
-  if (ProfileReader) {
-    if (Error E = ProfileReader.value().get().getFunctionCounts(
-            Record.FunctionName, NewHash, Counts)) {
-      instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
-      if (IPE == instrprof_error::hash_mismatch) {
-        FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
-                                        NewHash);
-        return Error::success();
-      }
-      if (IPE != instrprof_error::unknown_function)
-        return make_error<InstrProfError>(IPE);
-      Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0);
-    }
-  } else {
-    Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0);
-  }
-  Ctx.setCounts(Counts);
-
-  bool IsVersion11 =
-      ProfileReader && ProfileReader.value().get().getVersion() <
-                           IndexedInstrProf::ProfVersion::Version12;
-
-  BitVector Bitmap;
-  if (ProfileReader) {
-    if (Error E = ProfileReader.value().get().getFunctionBitmap(
-            Record.FunctionName, NewHash, Bitmap)) {
-      instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
-      if (IPE == instrprof_error::hash_mismatch) {
-        FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
-                                        NewHash);
-        return Error::success();
-      }
-      if (IPE != instrprof_error::unknown_function)
-        return make_error<InstrProfError>(IPE);
-      Bitmap = BitVector(getMaxBitmapSize(Record, IsVersion11));
-    }
-  } else {
-    Bitmap = BitVector(getMaxBitmapSize(Record, false));
-  }
-  Ctx.setBitmap(std::move(Bitmap));
-
-  assert(!Record.MappingRegions.empty() && "Function has no regions");
-
-  // This coverage record is a zero region for a function that's unused in
-  // some TU, but used in a different TU. Ignore it. The coverage maps from the
-  // the other TU will either be loaded (providing full region counts) or they
-  // won't (in which case we don't unintuitively report functions as uncovered
-  // when they have non-zero counts in the profile).
-  if (Record.MappingRegions.size() == 1 &&
-      Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
-    return Error::success();
-
-  MCDCDecisionRecorder MCDCDecisions;
-  FunctionRecord Function(OrigFuncName, Record.Filenames);
-  for (const auto &Region : Record.MappingRegions) {
-    // MCDCDecisionRegion should be handled first since it overlaps with
-    // others inside.
-    if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) {
-      MCDCDecisions.registerDecision(Region);
-      continue;
-    }
-    Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
-    if (auto E = ExecutionCount.takeError()) {
-      consumeError(std::move(E));
-      return Error::success();
-    }
-    Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);
-    if (auto E = AltExecutionCount.takeError()) {
-      consumeError(std::move(E));
-      return Error::success();
-    }
-    Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
-
-    // Record ExpansionRegion.
-    if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
-      MCDCDecisions.recordExpansion(Region);
-      continue;
-    }
-
-    // Do nothing unless MCDCBranchRegion.
-    if (Region.Kind != CounterMappingRegion::MCDCBranchRegion)
-      continue;
-
-    auto Result = MCDCDecisions.processBranch(Region);
-    if (!Result) // Any Decision doesn't complete.
-      continue;
-
-    auto MCDCDecision = Result->first;
-    auto &MCDCBranches = Result->second;
-
-    // Since the bitmap identifies the executed test vectors for an MC/DC
-    // DecisionRegion, all of the information is now available to process.
-    // This is where the bulk of the MC/DC progressing takes place.
-    Expected<MCDCRecord> Record =
-        Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches, IsVersion11);
-    if (auto E = Record.takeError()) {
-      consumeError(std::move(E));
-      return Error::success();
-    }
-
-    // Save the MC/DC Record so that it can be visualized later.
-    Function.pushMCDCRecord(std::move(*Record));
-  }
-
-  // Don't create records for (filenames, function) pairs we've already seen.
-  auto FilenamesHash = hash_combine_range(Record.Filenames);
-  if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
-    return Error::success();
-
-  Functions.push_back(std::move(Function));
-
-  // Performance optimization: keep track of the indices of the function records
-  // which correspond to each filename. This can be used to substantially speed
-  // up queries for coverage info in a file.
-  unsigned RecordIndex = Functions.size() - 1;
-  for (StringRef Filename : Record.Filenames) {
-    auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)];
-    // Note that there may be duplicates in the filename set for a function
-    // record, because of e.g. macro expansions in the function in which both
-    // the macro and the function are defined in the same file.
-    if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
-      RecordIndices.push_back(RecordIndex);
-  }
-
-  return Error::success();
-}
+// Error CoverageMapping::loadFunctionRecord(
+//     const CoverageMappingRecord &Record,
+//     const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
+//         &ProfileReader, StringRef Arch) {
+//   StringRef OrigFuncName = Record.FunctionName;
+//   if (OrigFuncName.empty())
+//     return make_error<CoverageMapError>(coveragemap_error::malformed,
+//                                         "record function name is empty");
+
+//   if (Record.Filenames.empty())
+//     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
+//   else
+//     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
+
+//   CounterMappingContext Ctx(Record.Expressions);
+
+//   uint64_t FuncArchHash = Record.FunctionHash;
+//   if(!Arch.empty()){
+//     std::string HashStr = std::to_string(Record.FunctionHash) + ":" + Arch.str();
+//     llvm::StringRef HashRef(HashStr);
+//     FuncArchHash = IndexedInstrProf::ComputeHash(HashRef);
+//   }
+
+//   std::vector<uint64_t> Counts;
+//   if (ProfileReader) {
+//     if (Error E = ProfileReader.value().get().getFunctionCounts(
+//             Record.FunctionName, FuncArchHash, Counts)) {
+//       instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
+//       if (IPE == instrprof_error::hash_mismatch) {
+//         FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
+//                                         FuncArchHash);
+//         return Error::success();
+//       }
+//       if (IPE != instrprof_error::unknown_function)
+//         return make_error<InstrProfError>(IPE);
+//       Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0);
+//     }
+//   } else {
+//     Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0);
+//   }
+//   Ctx.setCounts(Counts);
+
+//   bool IsVersion11 =
+//       ProfileReader && ProfileReader.value().get().getVersion() <
+//                            IndexedInstrProf::ProfVersion::Version12;
+
+//   BitVector Bitmap;
+//   if (ProfileReader) {
+//     if (Error E = ProfileReader.value().get().getFunctionBitmap(
+//             Record.FunctionName, FuncArchHash, Bitmap)) {
+//       instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
+//       if (IPE == instrprof_error::hash_mismatch) {
+//         FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
+//                                         FuncArchHash);
+//         return Error::success();
+//       }
+//       if (IPE != instrprof_error::unknown_function)
+//         return make_error<InstrProfError>(IPE);
+//       Bitmap = BitVector(getMaxBitmapSize(Record, IsVersion11));
+//     }
+//   } else {
+//     Bitmap = BitVector(getMaxBitmapSize(Record, false));
+//   }
+//   Ctx.setBitmap(std::move(Bitmap));
+
+//   assert(!Record.MappingRegions.empty() && "Function has no regions");
+
+//   // This coverage record is a zero region for a function that's unused in
+//   // some TU, but used in a different TU. Ignore it. The coverage maps from the
+//   // the other TU will either be loaded (providing full region counts) or they
+//   // won't (in which case we don't unintuitively report functions as uncovered
+//   // when they have non-zero counts in the profile).
+//   if (Record.MappingRegions.size() == 1 &&
+//       Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
+//     return Error::success();
+
+//   MCDCDecisionRecorder MCDCDecisions;
+//   FunctionRecord Function(OrigFuncName, Record.Filenames);
+//   for (const auto &Region : Record.MappingRegions) {
+//     // MCDCDecisionRegion should be handled first since it overlaps with
+//     // others inside.
+//     if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) {
+//       MCDCDecisions.registerDecision(Region);
+//       continue;
+//     }
+//     Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
+//     if (auto E = ExecutionCount.takeError()) {
+//       consumeError(std::move(E));
+//       return Error::success();
+//     }
+//     Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);
+//     if (auto E = AltExecutionCount.takeError()) {
+//       consumeError(std::move(E));
+//       return Error::success();
+//     }
+//     Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
+
+//     // Record ExpansionRegion.
+//     if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
+//       MCDCDecisions.recordExpansion(Region);
+//       continue;
+//     }
+
+//     // Do nothing unless MCDCBranchRegion.
+//     if (Region.Kind != CounterMappingRegion::MCDCBranchRegion)
+//       continue;
+
+//     auto Result = MCDCDecisions.processBranch(Region);
+//     if (!Result) // Any Decision doesn't complete.
+//       continue;
+
+//     auto MCDCDecision = Result->first;
+//     auto &MCDCBranches = Result->second;
+
+//     // Since the bitmap identifies the executed test vectors for an MC/DC
+//     // DecisionRegion, all of the information is now available to process.
+//     // This is where the bulk of the MC/DC progressing takes place.
+//     Expected<MCDCRecord> Record =
+//         Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches, IsVersion11);
+//     if (auto E = Record.takeError()) {
+//       consumeError(std::move(E));
+//       return Error::success();
+//     }
+
+//     // Save the MC/DC Record so that it can be visualized later.
+//     Function.pushMCDCRecord(std::move(*Record));
+//   }
+
+//   // Don't create records for (filenames, function) pairs we've already seen.
+//   auto FilenamesHash = hash_combine_range(Record.Filenames);
+//   if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
+//     return Error::success();
+
+//   Functions.push_back(std::move(Function));
+
+//   // Performance optimization: keep track of the indices of the function records
+//   // which correspond to each filename. This can be used to substantially speed
+//   // up queries for coverage info in a file.
+//   unsigned RecordIndex = Functions.size() - 1;
+//   for (StringRef Filename : Record.Filenames) {
+//     auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)];
+//     // Note that there may be duplicates in the filename set for a function
+//     // record, because of e.g. macro expansions in the function in which both
+//     // the macro and the function are defined in the same file.
+//     if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
+//       RecordIndices.push_back(RecordIndex);
+//   }
+
+//   return Error::success();
+// }
 
 Error CoverageMapping::loadFunctionRecord(
     const CoverageMappingRecord &Record,
@@ -985,18 +988,21 @@ Error CoverageMapping::loadFunctionRecord(
 
   CounterMappingContext Ctx(Record.Expressions);
 
-  std::string HashStr = std::to_string(Record.FunctionHash) + ":" + Arch.str();
-  llvm::StringRef HashRef(HashStr);
-  uint64_t NewHash = IndexedInstrProf::ComputeHash(HashRef);
+  uint64_t FuncArchHash = Record.FunctionHash;
+  if(!Arch.empty()){
+    std::string HashStr = std::to_string(Record.FunctionHash) + ":" + Arch.str();
+    llvm::StringRef HashRef(HashStr);
+    FuncArchHash = IndexedInstrProf::ComputeHash(HashRef);
+  }
 
   std::vector<uint64_t> Counts;
   if (ProfileReader) {
     if (Error E = ProfileReader.value().get().getFunctionCounts(
-            Record.FunctionName, NewHash, Counts)) {
+            Record.FunctionName, FuncArchHash, Counts)) {
       instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
       if (IPE == instrprof_error::hash_mismatch) {
         FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
-                                        NewHash);
+                                        FuncArchHash);
         return Error::success();
       }
       if (IPE != instrprof_error::unknown_function)
@@ -1015,11 +1021,11 @@ Error CoverageMapping::loadFunctionRecord(
   BitVector Bitmap;
   if (ProfileReader) {
     if (Error E = ProfileReader.value().get().getFunctionBitmap(
-            Record.FunctionName, NewHash, Bitmap)) {
+            Record.FunctionName, FuncArchHash, Bitmap)) {
       instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
       if (IPE == instrprof_error::hash_mismatch) {
         FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
-                                        NewHash);
+                                        FuncArchHash);
         return Error::success();
       }
       if (IPE != instrprof_error::unknown_function)
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index 9a75164ebe698..8fda78bd26802 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -574,59 +574,51 @@ Error InstrProfSymtab::addVTableWithName(GlobalVariable &VTable,
   return Error::success();
 }
 
-Error readAndDecodeStrings(StringRef NameStrings,
-                           std::function<Error(StringRef)> NameCallback, const std::string &Architecture) {
-  const uint8_t *P = NameStrings.bytes_begin();
-  const uint8_t *EndP = NameStrings.bytes_end();
-  while (P < EndP) {
-    uint32_t N;
-    uint64_t UncompressedSize = decodeULEB128(P, &N);
-    P += N;
-    uint64_t CompressedSize = decodeULEB128(P, &N);
-    P += N;
-    const bool IsCompressed = (CompressedSize != 0);
-    SmallVector<uint8_t, 128> UncompressedNameStrings;
-    StringRef NameStrings;
-    if (IsCompressed) {
-      if (!llvm::compression::zlib::isAvailable())
-        return make_error<InstrProfError>(instrprof_error::zlib_unavailable);
-
-      if (Error E = compression::zlib::decompress(ArrayRef(P, CompressedSize),
-                                                  UncompressedNameStrings,
-                                                  UncompressedSize)) {
-        consumeError(std::move(E));
-        return make_error<InstrProfError>(instrprof_error::uncompress_failed);
-      }
-      P += CompressedSize;
-      NameStrings = toStringRef(UncompressedNameStrings);
-    } else {
-      NameStrings =
-          StringRef(reinterpret_cast<const char *>(P), UncompressedSize);
-      P += UncompressedSize;
-    }
-    // Now parse the name strings.
-    SmallVector<StringRef, 0> Names;
-    StringRef ArchRef(Architecture); 
-    NameStrings.split(Names, getInstrProfNameSeparator());
-    for (StringRef &Name : Names){
-      std::string ConcHashString = Name.str() + ":" + ArchRef.str();
-      printf("The string %s will get hashed and mapped to %s\n", ConcHashString.c_str(), Name.str().c_str());
-      if(ArchRef.empty()){
-        if (Error E = NameCallback(Name))
-          return E;
-      }else{
-        if (Error E = NameCallback(Name.str() + "#" + ArchRef.str()))
-          return E;
-      }
-    }
-    while (P < EndP && *P == 0)
-      P++;
-  }
-  return Error::success();
-}
+// Error readAndDecodeStrings(StringRef NameStrings,
+//                            std::function<Error(StringRef)> NameCallback, const std::string &Architecture) {
+//   const uint8_t *P = NameStrings.bytes_begin();
+//   const uint8_t *EndP = NameStrings.bytes_end();
+//   while (P < EndP) {
+//     uint32_t N;
+//     uint64_t UncompressedSize = decodeULEB128(P, &N);
+//     P += N;
+//     uint64_t CompressedSize = decodeULEB128(P, &N);
+//     P += N;
+//     const bool IsCompressed = (CompressedSize != 0);
+//     SmallVector<uint8_t, 128> UncompressedNameStrings;
+//     StringRef NameStrings;
+//     if (IsCompressed) {
+//       if (!llvm::compression::zlib::isAvailable())
+//         return make_error<InstrProfError>(instrprof_error::zlib_unavailable);
+
+//       if (Error E = compression::zlib::decompress(ArrayRef(P, CompressedSize),
+//                                                   UncompressedNameStrings,
+//                                                   UncompressedSize)) {
+//         consumeError(std::move(E));
+//         return make_error<InstrProfError>(instrprof_error::uncompress_failed);
+//       }
+//       P += CompressedSize;
+//       NameStrings = toStringRef(UncompressedNameStrings);
+//     } else {
+//       NameStrings =
+//           StringRef(reinterpret_cast<const char *>(P), UncompressedSize);
+//       P += UncompressedSize;
+//     }
+//     // Now parse the name strings.
+//     SmallVector<StringRef, 0> Names;
+//     NameStrings.split(Names, getInstrProfNameSeparator());
+//     for (StringRef &Name : Names){
+//       if (Error E = NameCallback(Name))
+//         return E;
+//     }
+//     while (P < EndP && *P == 0)
+//       P++;
+//   }
+//   return Error::success();
+// }
 
 Error readAndDecodeStrings(StringRef NameStrings,
-                           std::function<Error(StringRef)> NameCallback) {
+                           std::function<Error(StringRef)> NameCallback, StringRef Architecture) {
   const uint8_t *P = NameStrings.bytes_begin();
   const uint8_t *EndP = NameStrings.bytes_end();
   while (P < EndP) {
@@ -668,19 +660,19 @@ Error readAndDecodeStrings(StringRef NameStrings,
 }
 
 Error InstrProfSymtab::create(StringRef NameStrings) {
-  const std::string &Architecture = getArchitecture();
+  StringRef Architecture = getArchitecture();
   return readAndDecodeStrings(NameStrings, std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1), Architecture);
 }
 
 Error InstrProfSymtab::create(StringRef FuncNameStrings,
                               StringRef VTableNameStrings) {
-  const std::string &Architecture = getArchitecture();                                
-  if (Error E = readAndDecodeStrings(FuncNameStrings, std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1), Architecture))
+  // const std::string &Architecture = getArchitecture();                                
+  if (Error E = readAndDecodeStrings(FuncNameStrings, std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1)))
     return E;
 
   return readAndDecodeStrings(
       VTableNameStrings,
-      std::bind(&InstrProfSymtab::addVTableName, this, std::placeholders::_1), Architecture);
+      std::bind(&InstrProfSymtab::addVTableName, this, std::placeholders::_1));
 }
 
 Error InstrProfSymtab::initVTableNamesFromCompressedStrings(
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 33ebcfd3200b2..b8a1397f323b2 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -160,7 +160,7 @@ Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create( //STEP 1
     const object::BuildIDFetcher *BIDFetcher,
     const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
     std::function<void(Error)> Warn, 
-    const std::string &Architecture) {
+    StringRef Architecture) {
   // Set up the buffer to read.
   auto BufferOrError = setupMemoryBuffer(Path, FS);
   if (Error E = BufferOrError.takeError())
@@ -173,7 +173,7 @@ Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
     std::unique_ptr<MemoryBuffer> Buffer, const InstrProfCorrelator *Correlator,
     const object::BuildIDFetcher *BIDFetcher,
     const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
-    std::function<void(Error)> Warn, const std::string &Architecture) {
+    std::function<void(Error)> Warn, StringRef Architecture) {
   if (Buffer->getBufferSize() == 0)
     return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
 
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 4dfeeca00d988..1c5c82b3c5193 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -153,8 +153,8 @@ void InstrProfWriter::setValueProfDataEndianness(llvm::endianness Endianness) {
 
 void InstrProfWriter::setOutputSparse(bool Sparse) { this->Sparse = Sparse; }
 
-void InstrProfWriter::addRecord(NamedInstrProfRecord &&I, uint64_t Weight, const std::string &Architecture,
-                                function_ref<void(Error)> Warn) {
+void InstrProfWriter::addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
+                                function_ref<void(Error)> Warn, StringRef Architecture) {
   auto Name = I.Name;
   auto Hash = I.Hash;
   addRecord(Name, Hash, std::move(I), Weight, Warn, Architecture);
@@ -191,40 +191,42 @@ void InstrProfWriter::overlapRecord(NamedInstrProfRecord &&Other,
   Dest.overlap(Other, Overlap, FuncLevelOverlap, ValueCutoff);
 }
 
-void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
-                                InstrProfRecord &&I, uint64_t Weight,
-                                function_ref<void(Error)> Warn) {
-  auto &ProfileDataMap = FunctionData[Name];
+// void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
+//                                 InstrProfRecord &&I, uint64_t Weight,
+//                                 function_ref<void(Error)> Warn) {
+//   auto &ProfileDataMap = FunctionData[Name];
 
-  auto [Where, NewFunc] = ProfileDataMap.try_emplace(Hash);
-  InstrProfRecord &Dest = Where->second;
+//   auto [Where, NewFunc] = ProfileDataMap.try_emplace(Hash);
+//   InstrProfRecord &Dest = Where->second;
 
-  auto MapWarn = [&](instrprof_error E) {
-    Warn(make_error<InstrProfError>(E));
-  };
+//   auto MapWarn = [&](instrprof_error E) {
+//     Warn(make_error<InstrProfError>(E));
+//   };
 
-  if (NewFunc) {
-    // We've never seen a function with this name and hash, add it.
-    Dest = std::move(I);
-    if (Weight > 1)
-      Dest.scale(Weight, 1, MapWarn);
-  } else {
-    // We're updating a function we've seen before.
-    Dest.merge(I, Weight, MapWarn);
-  }
+//   if (NewFunc) {
+//     // We've never seen a function with this name and hash, add it.
+//     Dest = std::move(I);
+//     if (Weight > 1)
+//       Dest.scale(Weight, 1, MapWarn);
+//   } else {
+//     // We're updating a function we've seen before.
+//     Dest.merge(I, Weight, MapWarn);
+//   }
 
-  Dest.sortValueData();
-}
+//   Dest.sortValueData();
+// }
 
 void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
                                 InstrProfRecord &&I, uint64_t Weight,
-                                function_ref<void(Error)> Warn, const std::string &Architecture) {
+                                function_ref<void(Error)> Warn, StringRef Architecture) {
   auto &ProfileDataMap = FunctionData[Name];
-  std::string HashStr = std::to_string(Hash) + ":" + Architecture;
-  llvm::StringRef HashRef(HashStr);
-  uint64_t NewHash = IndexedInstrProf::ComputeHash(HashRef);
+  if(!Architecture.empty()){
+    std::string HashStr = std::to_string(Hash) + ":" + Architecture.str();
+    llvm::StringRef HashRef(HashStr);
+    Hash = IndexedInstrProf::ComputeHash(HashRef);
+  }
 
-  auto [Where, NewFunc] = ProfileDataMap.try_emplace(NewHash);
+  auto [Where, NewFunc] = ProfileDataMap.try_emplace(Hash);
   InstrProfRecord &Dest = Where->second;
 
   auto MapWarn = [&](instrprof_error E) {
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index 6c66858c4de8c..a90bcef7eaf7d 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -114,7 +114,7 @@ class CodeCoverageTool {
 
   /// Create the main source view of a particular source file.
   std::unique_ptr<SourceCoverageView>
-  createSourceFileView(StringRef SourceFile, const CoverageMapping &Coverage);
+  createSourceFileView(StringRef SourceFile, const CoverageMapping &Coverage, std::vector<StringRef> Arches);
 
   /// Load the coverage mapping data. Return nullptr if an error occurred.
   std::unique_ptr<CoverageMapping> load();
@@ -391,7 +391,7 @@ CodeCoverageTool::createFunctionView(const FunctionRecord &Function,
 
 std::unique_ptr<SourceCoverageView>
 CodeCoverageTool::createSourceFileView(StringRef SourceFile,
-                                       const CoverageMapping &Coverage) {
+                                       const CoverageMapping &Coverage, std::vector<StringRef> Arches) {
   auto SourceBuffer = getSourceFile(SourceFile);
   if (!SourceBuffer)
     return nullptr;
@@ -633,7 +633,7 @@ void CodeCoverageTool::writeSourceFileView(StringRef SourceFile,
                                            CoverageMapping *Coverage,
                                            CoveragePrinter *Printer,
                                            bool ShowFilenames) {
-  auto View = createSourceFileView(SourceFile, *Coverage);
+  auto View = createSourceFileView(SourceFile, *Coverage, CoverageArches);
   if (!View) {
     warning("The file '" + SourceFile + "' isn't covered.");
     return;
@@ -648,7 +648,7 @@ void CodeCoverageTool::writeSourceFileView(StringRef SourceFile,
 
   View->print(*OS.get(), /*Wholefile=*/true,
               /*ShowSourceName=*/ShowFilenames,
-              /*ShowTitle=*/ViewOpts.hasOutputDirectory());
+              /*ShowTitle=*/ViewOpts.hasOutputDirectory(), SourceFile);
   Printer->closeViewFile(std::move(OS));
 }
 
diff --git a/llvm/tools/llvm-cov/SourceCoverageView.cpp b/llvm/tools/llvm-cov/SourceCoverageView.cpp
index dfecddfaf4143..810e2c6024584 100644
--- a/llvm/tools/llvm-cov/SourceCoverageView.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageView.cpp
@@ -15,9 +15,11 @@
 #include "SourceCoverageViewText.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ProfileData/Coverage/CoverageMapping.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/LineIterator.h"
 #include "llvm/Support/Path.h"
+#include <vector>
 
 using namespace llvm;
 
@@ -192,7 +194,7 @@ void SourceCoverageView::addInstantiation(
 
 void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
                                bool ShowSourceName, bool ShowTitle,
-                               unsigned ViewDepth) {
+                               unsigned ViewDepth, StringRef SourceFile) {
   if (ShowTitle)
     renderTitle(OS, "Coverage Report");
 
@@ -222,9 +224,25 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
   auto StartSegment = CoverageInfo.begin();
   auto EndSegment = CoverageInfo.end();
   LineCoverageIterator LCI{CoverageInfo, 1};
+  // LineCoverageIterator LCIInit{CoverageInfo, 1};
   LineCoverageIterator LCIEnd = LCI.getEnd();
-
   unsigned FirstLine = StartSegment != EndSegment ? StartSegment->Line : 0;
+  
+  // // Determine the number of lines in the file
+  // unsigned NumLines = 0;
+  // for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof(); ++LI)
+  //   ++NumLines;
+  // // Resize the outer vector to hold one entry per line
+  // std::vector<std::vector<LineCoverageStats>> LineArchStats;
+  // LineArchStats.resize(CoverageArches.size()); // +1 in case line numbers are 1-based
+  // for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof(); ++LI, ++LCIInit) {
+  //   unsigned LineNo = LCIInit->getLine();
+  //   if (LineNo >= LineArchStats.size()){
+  //     LineArchStats.resize(LineNo + 1); // Ensure enough space
+  //   }
+  //   LineArchStats[LineNo].push_back(*LCIInit); // Store the LineCoverageStats
+  // }
+
   for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof();
        ++LI, ++LCI) {
     // If we aren't rendering the whole file, we need to filter out the prologue
@@ -242,6 +260,7 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
 
     if (getOptions().ShowLineStats)
       renderLineCoverageColumn(OS, *LCI);
+      // renderArchLineCoverageColumn(OS, *LCI, LineArchStats);
 
     // If there are expansion subviews, we want to highlight the first one.
     unsigned ExpansionColumn = 0;
diff --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h
index cff32b756ee32..df83e8ca37279 100644
--- a/llvm/tools/llvm-cov/SourceCoverageView.h
+++ b/llvm/tools/llvm-cov/SourceCoverageView.h
@@ -224,6 +224,9 @@ class SourceCoverageView {
   /// Render the line's execution count column.
   virtual void renderLineCoverageColumn(raw_ostream &OS,
                                         const LineCoverageStats &Line) = 0;
+                                
+  virtual void renderArchLineCoverageColumn(raw_ostream &OS, const LineCoverageStats &Line, std::vector<std::vector<LineCoverageStats>> LineArchStats) = 0;
+
 
   /// Render the line number column.
   virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0;
@@ -319,7 +322,7 @@ class SourceCoverageView {
   /// Print the code coverage information for a specific portion of a
   /// source file to the output stream.
   void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
-             bool ShowTitle, unsigned ViewDepth = 0);
+             bool ShowTitle, unsigned ViewDepth = 0, StringRef CoverageArches = "");
 };
 
 } // namespace llvm
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index c94d3853fc014..d4dec5e699a58 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -1062,6 +1062,31 @@ void SourceCoverageViewHTML::renderLineCoverageColumn(
   OS << tag("td", Count, CoverageClass);
 }
 
+void SourceCoverageViewHTML::renderArchLineCoverageColumn(
+    raw_ostream &OS,
+    const LineCoverageStats &Line,
+    std::vector<std::vector<LineCoverageStats>> LineArchStats) {
+  
+  std::string CellContent;
+
+  if (Line.isMapped()) {
+    unsigned LineNo = Line.getLine();
+    for (const auto &ArchStats : LineArchStats[LineNo]) {
+      CellContent += formatBinaryCount(ArchStats.getExecutionCount()) + "/";
+    }
+    if (!CellContent.empty())
+      CellContent.pop_back(); // Remove trailing '/'
+  }
+
+  std::string CoverageClass =
+      (Line.getExecutionCount() > 0)
+          ? "covered-line"
+          : (Line.isMapped() ? "uncovered-line" : "skipped-line");
+
+  OS << tag("td", tag("pre", CellContent), CoverageClass);
+}
+
+
 void SourceCoverageViewHTML::renderLineNumberColumn(raw_ostream &OS,
                                                     unsigned LineNo) {
   std::string LineNoStr = utostr(uint64_t(LineNo));
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.h b/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
index 9b7391d0043ec..37098273510e0 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
@@ -99,6 +99,8 @@ class SourceCoverageViewHTML : public SourceCoverageView {
   void renderLineCoverageColumn(raw_ostream &OS,
                                 const LineCoverageStats &Line) override;
 
+  void renderArchLineCoverageColumn(raw_ostream &OS, const LineCoverageStats &Line, std::vector<std::vector<LineCoverageStats>> LineArchStats) override;
+
   void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override;
 
   void renderRegionMarkers(raw_ostream &OS, const LineCoverageStats &Line,
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index df8eb1d871878..45a8dcf76010f 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -14,6 +14,7 @@
 #include "CoverageReport.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/ProfileData/Coverage/CoverageMapping.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/Path.h"
@@ -218,9 +219,23 @@ void SourceCoverageViewText::renderLineCoverageColumn(
   }
   std::string C = formatBinaryCount(Line.getExecutionCount());
   OS.indent(LineCoverageColumnWidth - C.size());
-  colored_ostream(OS, raw_ostream::MAGENTA,
-                  Line.hasMultipleRegions() && getOptions().Colors)
-      << C;
+  colored_ostream(OS, raw_ostream::MAGENTA, Line.hasMultipleRegions() && getOptions().Colors) << C;
+  OS << '|';
+}
+
+void SourceCoverageViewText::renderArchLineCoverageColumn(
+    raw_ostream &OS, const LineCoverageStats &Line, std::vector<std::vector<LineCoverageStats>> LineArchStats) {
+  if (!Line.isMapped()) {
+    OS.indent(LineCoverageColumnWidth) << '|';
+    return;
+  }
+  std::string C = "";
+  for(LineCoverageStats Counts : LineArchStats[Line.getLine()]){
+    C += formatBinaryCount(Counts.getExecutionCount()) + "/";
+  }
+  // std::string C = formatBinaryCount(Line.getExecutionCount());
+  OS.indent(LineCoverageColumnWidth - C.size());
+  colored_ostream(OS, raw_ostream::MAGENTA, Line.hasMultipleRegions() && getOptions().Colors) << C;
   OS << '|';
 }
 
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.h b/llvm/tools/llvm-cov/SourceCoverageViewText.h
index 25a161b096200..3841aad607324 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.h
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.h
@@ -85,6 +85,8 @@ class SourceCoverageViewText : public SourceCoverageView {
 
   void renderLineCoverageColumn(raw_ostream &OS,
                                 const LineCoverageStats &Line) override;
+  
+  void renderArchLineCoverageColumn(raw_ostream &OS, const LineCoverageStats &Line, std::vector<std::vector<LineCoverageStats>> LineArchStats) override;
 
   void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override;
 
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 3d3fd34a493ab..8aa7f23a3398d 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -862,7 +862,7 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
       I.Name = (*Remapper)(I.Name);
     const StringRef FuncName = I.Name;
     bool Reported = false;
-    WC->Writer.addRecord(std::move(I), Input.Weight, Architecture, [&](Error E) {
+    WC->Writer.addRecord(std::move(I), Input.Weight, [&](Error E) {
       if (Reported) {
         consumeError(std::move(E));
         return;
@@ -874,7 +874,7 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
       bool firstTime = WC->WriterErrorCodes.insert(ErrCode).second;
       handleMergeWriterError(make_error<InstrProfError>(ErrCode, Msg),
                              Input.Filename, FuncName, firstTime);
-    });
+    }, Architecture);
   }
 
   if (KeepVTableSymbols) {

>From e88c4ea0698e8918f9be7bed150ef647a694f42f Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Sun, 20 Jul 2025 20:38:16 -0700
Subject: [PATCH 08/17] committing to save updates

---
 .../ProfileData/Coverage/CoverageMapping.h    | 30 ++++++---
 llvm/include/llvm/ProfileData/InstrProf.h     |  4 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  | 66 ++++++++++++++-----
 .../Coverage/CoverageMappingReader.cpp        |  3 +-
 llvm/lib/ProfileData/InstrProfWriter.cpp      | 37 ++++++++++-
 llvm/tools/llvm-cov/CodeCoverage.cpp          | 30 ++++++++-
 .../tools/llvm-cov/SourceCoverageViewText.cpp |  3 +
 llvm/tools/llvm-profdata/llvm-profdata.cpp    |  1 +
 8 files changed, 141 insertions(+), 33 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 555c7e5f37f2b..0487a96ce4ae8 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -19,6 +19,7 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/iterator.h"
 #include "llvm/ADT/iterator_range.h"
@@ -375,6 +376,7 @@ struct CountedRegion : public CounterMappingRegion {
   uint64_t FalseExecutionCount;
   bool TrueFolded;
   bool FalseFolded;
+  StringRef ObjectFilename;
 
   CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount)
       : CounterMappingRegion(R), ExecutionCount(ExecutionCount),
@@ -385,6 +387,12 @@ struct CountedRegion : public CounterMappingRegion {
       : CounterMappingRegion(R), ExecutionCount(ExecutionCount),
         FalseExecutionCount(FalseExecutionCount), TrueFolded(false),
         FalseFolded(false) {}
+  
+  CountedRegion(const CounterMappingRegion &R, uint64_t ExecutionCount,
+          uint64_t FalseExecutionCount, StringRef ObjectFilename)
+: CounterMappingRegion(R), ExecutionCount(ExecutionCount),
+  FalseExecutionCount(FalseExecutionCount), TrueFolded(false),
+  FalseFolded(false), ObjectFilename(ObjectFilename) {}
 };
 
 /// MCDC Record grouping all information together.
@@ -731,9 +739,11 @@ struct FunctionRecord {
   std::vector<MCDCRecord> MCDCRecords;
   /// The number of times this function was executed.
   uint64_t ExecutionCount = 0;
+  /// The executable this function was compiled in
+  StringRef ObjectFilename;
 
-  FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames)
-      : Name(Name), Filenames(Filenames.begin(), Filenames.end()) {}
+  FunctionRecord(StringRef Name, ArrayRef<StringRef> Filenames, StringRef ObjectFilename = "")
+      : Name(Name), Filenames(Filenames.begin(), Filenames.end()), ObjectFilename(ObjectFilename) {}
 
   FunctionRecord(FunctionRecord &&FR) = default;
   FunctionRecord &operator=(FunctionRecord &&) = default;
@@ -752,9 +762,10 @@ struct FunctionRecord {
       CountedBranchRegions.back().FalseFolded = Region.FalseCount.isZero();
       return;
     }
-    if (CountedRegions.empty())
+    if (CountedRegions.empty()){
       ExecutionCount = Count;
-    CountedRegions.emplace_back(Region, Count, FalseCount);
+    }
+    CountedRegions.emplace_back(Region, Count, FalseCount, ObjectFilename);
   }
 };
 
@@ -994,6 +1005,9 @@ class CoverageMapping {
   DenseMap<size_t, SmallVector<unsigned, 0>> FilenameHash2RecordIndices;
   std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
   StringRef Arch;
+  DenseMap<std::pair<size_t, hash_code>, unsigned> RecordIndices;
+
+  std::map<std::pair<std::string, std::string>, std::vector<uint64_t>> AggregatedCounts;
 
   std::optional<bool> SingleByteCoverage;
 
@@ -1004,7 +1018,7 @@ class CoverageMapping {
     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
     std::optional<std::reference_wrapper<IndexedInstrProfReader>>
         &ProfileReader,
-    CoverageMapping &Coverage, StringRef Arch);
+    CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename = "");
   
   static Error loadFromReaders(
     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
@@ -1018,15 +1032,15 @@ class CoverageMapping {
                std::optional<std::reference_wrapper<IndexedInstrProfReader>>
                    &ProfileReader,
                CoverageMapping &Coverage, bool &DataFound,
-               SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr);
+               SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr, StringRef ObjectFilename = "");
 
   /// Add a function record corresponding to \p Record.
   Error loadFunctionRecord(
       const CoverageMappingRecord &Record,
       const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
-          &ProfileReader);
+          &ProfileReader, StringRef ObjectFilename = "");
   
-  Error loadFunctionRecord(const CoverageMappingRecord &Record, const std::optional<std::reference_wrapper<IndexedInstrProfReader>> &ProfileReader, const std::string &Arch);
+  Error loadFunctionRecord(const CoverageMappingRecord &Record, const std::optional<std::reference_wrapper<IndexedInstrProfReader>> &ProfileReader, const std::string &Arch, StringRef ObjectFilename = "");
 
   /// Look up the indices for function records which are at least partially
   /// defined in the specified file. This is guaranteed to return a superset of
diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index 98890b5541a8f..21a58ce1f14ce 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -635,9 +635,6 @@ class InstrProfSymtab {
 
   // Map the MD5 of the symbol name to the name.
   Error addSymbolName(StringRef SymbolName) {
-    // StringRef FuncName;
-    // StringRef ArchName = Architecture;
-    // std::tie(FuncName, ArchName) = SymbolName.split("#");
     if (SymbolName.empty())
       return make_error<InstrProfError>(instrprof_error::malformed,
                                         "symbol name is empty");
@@ -1075,6 +1072,7 @@ struct InstrProfRecord {
 struct NamedInstrProfRecord : InstrProfRecord {
   StringRef Name;
   uint64_t Hash;
+  StringRef Filename;
 
   // We reserve this bit as the flag for context sensitive profile record.
   static const int CS_FLAG_IN_FUNC_HASH = 60;
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 0a391b3d56773..3dcbbbb1aaa5b 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -40,6 +40,7 @@
 #include <stack>
 #include <string>
 #include <system_error>
+#include <unordered_map>
 #include <utility>
 #include <vector>
 
@@ -975,7 +976,7 @@ class MCDCDecisionRecorder {
 Error CoverageMapping::loadFunctionRecord(
     const CoverageMappingRecord &Record,
     const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
-        &ProfileReader) {
+        &ProfileReader, StringRef ObjectFilename) {
   StringRef OrigFuncName = Record.FunctionName;
   if (OrigFuncName.empty())
     return make_error<CoverageMapError>(coveragemap_error::malformed,
@@ -997,12 +998,10 @@ Error CoverageMapping::loadFunctionRecord(
 
   std::vector<uint64_t> Counts;
   if (ProfileReader) {
-    if (Error E = ProfileReader.value().get().getFunctionCounts(
-            Record.FunctionName, FuncArchHash, Counts)) {
+    if (Error E = ProfileReader.value().get().getFunctionCounts(Record.FunctionName, FuncArchHash, Counts)) {
       instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
       if (IPE == instrprof_error::hash_mismatch) {
-        FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
-                                        FuncArchHash);
+        FuncHashMismatches.emplace_back(std::string(Record.FunctionName), FuncArchHash);
         return Error::success();
       }
       if (IPE != instrprof_error::unknown_function)
@@ -1035,6 +1034,7 @@ Error CoverageMapping::loadFunctionRecord(
   } else {
     Bitmap = BitVector(getMaxBitmapSize(Record, false));
   }
+
   Ctx.setBitmap(std::move(Bitmap));
 
   assert(!Record.MappingRegions.empty() && "Function has no regions");
@@ -1049,7 +1049,7 @@ Error CoverageMapping::loadFunctionRecord(
     return Error::success();
 
   MCDCDecisionRecorder MCDCDecisions;
-  FunctionRecord Function(OrigFuncName, Record.Filenames);
+  FunctionRecord Function(OrigFuncName, Record.Filenames, ObjectFilename);
   for (const auto &Region : Record.MappingRegions) {
     // MCDCDecisionRegion should be handled first since it overlaps with
     // others inside.
@@ -1102,9 +1102,9 @@ Error CoverageMapping::loadFunctionRecord(
 
   // Don't create records for (filenames, function) pairs we've already seen.
   auto FilenamesHash = hash_combine_range(Record.Filenames);
-  if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
+  if (!RecordProvenance[FilenamesHash].insert(FuncArchHash).second){
     return Error::success();
-
+  }
   Functions.push_back(std::move(Function));
 
   // Performance optimization: keep track of the indices of the function records
@@ -1152,7 +1152,7 @@ Error CoverageMapping::loadFromReaders(
     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
     std::optional<std::reference_wrapper<IndexedInstrProfReader>>
         &ProfileReader,
-    CoverageMapping &Coverage, StringRef Arch) {
+    CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename) {
   
   Coverage.setArchitecture(Arch);
   assert(!Coverage.SingleByteCoverage || !ProfileReader ||
@@ -1165,7 +1165,7 @@ Error CoverageMapping::loadFromReaders(
       if (Error E = RecordOrErr.takeError())
         return E;
       const auto &Record = *RecordOrErr;
-      if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader))
+      if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader, ObjectFilename))
         return E;
     }
   }
@@ -1196,7 +1196,7 @@ Error CoverageMapping::loadFromFile(
     std::optional<std::reference_wrapper<IndexedInstrProfReader>>
         &ProfileReader,
     CoverageMapping &Coverage, bool &DataFound,
-    SmallVectorImpl<object::BuildID> *FoundBinaryIDs) {
+    SmallVectorImpl<object::BuildID> *FoundBinaryIDs, StringRef ObjectFilename) {
   auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(
       Filename, /*IsText=*/false, /*RequiresNullTerminator=*/false);
   if (std::error_code EC = CovMappingBufOrErr.getError())
@@ -1228,7 +1228,7 @@ Error CoverageMapping::loadFromFile(
                        }));
   }
   DataFound |= !Readers.empty();
-  if (Error E = loadFromReaders(Readers, ProfileReader, Coverage, Arch))
+  if (Error E = loadFromReaders(Readers, ProfileReader, Coverage, Arch, ObjectFilename))
     return createFileError(Filename, std::move(E));
   return Error::success();
 }
@@ -1262,14 +1262,20 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
     return Arches[Idx];
   };
 
+  //I beleive there is an error in this area of code, it's iterating through all arch's of the object files
+  // but its only filling *Coverage with last architecture it gets to
+
   SmallVector<object::BuildID> FoundBinaryIDs;
   for (const auto &File : llvm::enumerate(ObjectFilenames)) {
     if (Error E = loadFromFile(File.value(), GetArch(File.index()),
                                CompilationDir, ProfileReaderRef, *Coverage,
-                               DataFound, &FoundBinaryIDs))
+                               DataFound, &FoundBinaryIDs, ObjectFilenames[File.index()]))
       return std::move(E);
   }
 
+  //I beleive there is an error in this area of code, it's iterating through all arch's of the object files
+  // but its only filling *Coverage with last architecture it gets to
+
   if (BIDFetcher) {
     std::vector<object::BuildID> ProfileBinaryIDs;
     if (ProfileReader)
@@ -1508,19 +1514,24 @@ class SegmentBuilder {
   }
 
   /// Combine counts of regions which cover the same area.
+  //[(3:12, 10:1), (4:1, 6:7), (6:7, 8:1)]
   static ArrayRef<CountedRegion>
   combineRegions(MutableArrayRef<CountedRegion> Regions) {
     if (Regions.empty())
       return Regions;
+
+    
     auto Active = Regions.begin();
     auto End = Regions.end();
     for (auto I = Regions.begin() + 1; I != End; ++I) {
-      if (Active->startLoc() != I->startLoc() ||
-          Active->endLoc() != I->endLoc()) {
+      if (Active->startLoc() != I->startLoc() || Active->endLoc() != I->endLoc()) {
         // Shift to the next region.
         ++Active;
-        if (Active != I)
+        if (Active != I){
           *Active = *I;
+          // Active->ExecutionCount = 1;
+          // Active->Kind = CounterMappingRegion::CodeRegion;
+        }
         continue;
       }
       // Merge duplicate region.
@@ -1549,6 +1560,29 @@ class SegmentBuilder {
     SegmentBuilder Builder(Segments);
 
     sortNestedRegions(Regions);
+
+    for(auto *I = Regions.begin(); I != Regions.end(); ++I){
+      bool FoundMatchInOtherBinary = false;
+      for(auto *J = I + 1; J != Regions.end(); ++J){
+        if(I->ObjectFilename != J->ObjectFilename &&
+            J->Kind == CounterMappingRegion::SkippedRegion 
+            && I->Kind != CounterMappingRegion::SkippedRegion &&
+            J->startLoc() >= I->startLoc() && J->endLoc() <= I->endLoc()){
+          for(auto *K = J + 1; K != Regions.end(); ++K){
+            if(K->ObjectFilename == I->ObjectFilename &&
+              J->startLoc() == K->startLoc() && J->endLoc() == K->endLoc()){
+              FoundMatchInOtherBinary = true;
+            }
+          }
+          if(!FoundMatchInOtherBinary){
+            J->Kind = I->Kind;
+            J->ExecutionCount = I->ExecutionCount;
+          }
+        }
+      }
+    }
+    
+
     ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
 
     LLVM_DEBUG({
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
index aa5b714bbdec8..1c79ffab66b05 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -288,7 +288,7 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray(
           // Don't do anything when we have a code region with a zero counter.
           break;
         case CounterMappingRegion::SkippedRegion:
-          Kind = CounterMappingRegion::SkippedRegion;
+          Kind = CounterMappingRegion::SkippedRegion; //if you change this to "CodeRegion, then all skipped regions have counter of 0"
           break;
         case CounterMappingRegion::BranchRegion:
           // For a Branch Region, read two successive counters.
@@ -381,7 +381,6 @@ Error RawCoverageMappingReader::readMappingRegionsSubArray(
         CounterMappingContext(Expressions).dump(C, dbgs());
       dbgs() << "\n";
     });
-
     auto CMR = CounterMappingRegion(
         C, C2, InferredFileID, ExpandedFileID, LineStart, ColumnStart,
         LineStart + NumLines, ColumnEnd, Kind, Params);
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 1c5c82b3c5193..d911ce6a6ee68 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -15,7 +15,11 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/bit.h"
+#include "llvm/DebugInfo/DIContext.h"
 #include "llvm/IR/ProfileSummary.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/ProfileData/Coverage/CoverageMapping.h"
 #include "llvm/ProfileData/DataAccessProf.h"
 #include "llvm/ProfileData/IndexedMemProfData.h"
 #include "llvm/ProfileData/InstrProf.h"
@@ -216,16 +220,47 @@ void InstrProfWriter::overlapRecord(NamedInstrProfRecord &&Other,
 //   Dest.sortValueData();
 // }
 
+
+
+// #include "llvm/DebugInfo/DWARF/DWARFContext.h"
+
+
+#include <llvm/Support/raw_ostream.h>
+#include <llvm/Support/MemoryBuffer.h>
+#include <llvm/Support/SHA1.h>
+#include <array>
+
+StringRef hashSourceFile(llvm::StringRef FilePath) {
+    auto FileOrErr = llvm::MemoryBuffer::getFile(FilePath);
+    if (!FileOrErr) {
+        llvm::errs() << "Error reading file: " << FilePath << "\n";
+        return "";
+    }
+
+    const auto &Buffer = *FileOrErr.get();
+    llvm::SHA1 Hasher;
+    Hasher.update(Buffer.getBuffer());
+
+    std::array<uint8_t, 20> Hash = Hasher.final();
+    
+    std::string HexStr = llvm::toHex(llvm::ArrayRef<uint8_t>(Hash));
+    llvm::StringRef HashRef(HexStr);
+    return HashRef;
+}
+
+
+
 void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
                                 InstrProfRecord &&I, uint64_t Weight,
                                 function_ref<void(Error)> Warn, StringRef Architecture) {
   auto &ProfileDataMap = FunctionData[Name];
+  StringRef SHAHash = hashSourceFile(Architecture);
+  llvm::errs() << "SHA Hashing: " << SHAHash << "\n";
   if(!Architecture.empty()){
     std::string HashStr = std::to_string(Hash) + ":" + Architecture.str();
     llvm::StringRef HashRef(HashStr);
     Hash = IndexedInstrProf::ComputeHash(HashRef);
   }
-
   auto [Where, NewFunc] = ProfileDataMap.try_emplace(Hash);
   InstrProfRecord &Dest = Where->second;
 
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index a90bcef7eaf7d..9885c2ac36df2 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -46,6 +46,7 @@
 #include <functional>
 #include <map>
 #include <optional>
+#include <string>
 #include <system_error>
 
 using namespace llvm;
@@ -297,8 +298,7 @@ CodeCoverageTool::getSourceFile(StringRef SourceFile) {
     error(EC.message(), SourceFile);
     return EC;
   }
-  LoadedSourceFiles.emplace_back(std::string(SourceFile),
-                                 std::move(Buffer.get()));
+  LoadedSourceFiles.emplace_back(std::string(SourceFile), std::move(Buffer.get()));
   return *LoadedSourceFiles.back().second;
 }
 
@@ -310,6 +310,7 @@ void CodeCoverageTool::attachExpansionSubViews(
   for (const auto &Expansion : Expansions) {
     auto ExpansionCoverage = Coverage.getCoverageForExpansion(Expansion);
     if (ExpansionCoverage.empty())
+    
       continue;
     auto SourceBuffer = getSourceFile(ExpansionCoverage.getFilename());
     if (!SourceBuffer)
@@ -454,6 +455,27 @@ static bool modifiedTimeGT(StringRef LHS, StringRef RHS) {
   return LHSTime > RHSTime;
 }
 
+// void mergeExecutionCounts(CoverageMapping &Coverage){
+//   std::map<std::string, std::vector<const FunctionRecord*>> functionGroups;
+
+//   for(const auto &Function : Coverage.getCoveredFunctions()){
+//     if(Function.CountedRegions.empty()) continue;
+//     const auto &MainRegion = Function.CountedRegions.front();
+//     const std::string Key = Function.Name + ":" + std::to_string(MainRegion.LineStart) + ":" + std::to_string(MainRegion.ColumnStart) + ":" + (Function.Filenames.empty() ? "" : std::string(Function.Filenames[0]));
+//     functionGroups[Key].push_back(&Function);
+//     llvm::errs() << Key << "\n";
+//   }
+
+//   for(auto &Group : functionGroups){
+//     if(Group.second.size() > 1){
+//       uint64_t TotalCount = 0;
+//       for(auto *Func : Group.second){
+//         TotalCount += Func->ExecutionCount;
+//       }
+//     }
+//   }
+// }
+
 std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
   if (PGOFilename) {
     for (StringRef ObjectFilename : ObjectFilenames)
@@ -483,6 +505,8 @@ std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
     }
   }
 
+  // mergeExecutionCounts(*Coverage);
+
   remapPathNames(*Coverage);
 
   if (!SourceFiles.empty())
@@ -648,7 +672,7 @@ void CodeCoverageTool::writeSourceFileView(StringRef SourceFile,
 
   View->print(*OS.get(), /*Wholefile=*/true,
               /*ShowSourceName=*/ShowFilenames,
-              /*ShowTitle=*/ViewOpts.hasOutputDirectory(), SourceFile);
+              /*ShowTitle=*/ViewOpts.hasOutputDirectory());
   Printer->closeViewFile(std::move(OS));
 }
 
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index 45a8dcf76010f..f8b366ac3b3b6 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -218,6 +218,9 @@ void SourceCoverageViewText::renderLineCoverageColumn(
     return;
   }
   std::string C = formatBinaryCount(Line.getExecutionCount());
+  if(C == "2"){
+    llvm::errs() << C << "\n";
+  }
   OS.indent(LineCoverageColumnWidth - C.size());
   colored_ostream(OS, raw_ostream::MAGENTA, Line.hasMultipleRegions() && getOptions().Colors) << C;
   OS << '|';
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 8aa7f23a3398d..900d105c66e55 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -743,6 +743,7 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
       consumeError(ArchOrError.takeError());
       Architecture = "unknown";
     }
+    // Architecture = ExeRef;
   }
   //ANDRES CODE
 

>From 76967333cb824f0dc9be1ff6a3505f6c112b751f Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Mon, 21 Jul 2025 12:45:24 -0700
Subject: [PATCH 09/17] merging works, just need to fix llvm-lit tests and
 merging errors on same arch

---
 .../ProfileData/Coverage/CoverageMapping.h    |  1 +
 .../ProfileData/Coverage/CoverageMapping.cpp  | 32 +++++++++++++++++--
 llvm/lib/ProfileData/InstrProfWriter.cpp      |  3 +-
 .../tools/llvm-cov/SourceCoverageViewText.cpp |  3 --
 4 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 0487a96ce4ae8..118f4e1fd662a 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -1006,6 +1006,7 @@ class CoverageMapping {
   std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
   StringRef Arch;
   DenseMap<std::pair<size_t, hash_code>, unsigned> RecordIndices;
+  uint64_t Counter = 0;
 
   std::map<std::pair<std::string, std::string>, std::vector<uint64_t>> AggregatedCounts;
 
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 3dcbbbb1aaa5b..c38df7c41f940 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -1100,11 +1100,39 @@ Error CoverageMapping::loadFunctionRecord(
     Function.pushMCDCRecord(std::move(*Record));
   }
 
-  // Don't create records for (filenames, function) pairs we've already seen.
+  //CHANGES MADE HERE
   auto FilenamesHash = hash_combine_range(Record.Filenames);
-  if (!RecordProvenance[FilenamesHash].insert(FuncArchHash).second){
+  std::string HashStr = OrigFuncName.str(); /*+ ":" + Arch.str();*/
+  if(!Arch.empty()){
+    HashStr += ":" + Arch.str();
+    // auto LogicalFuncKey = std::make_pair(FilenamesHash, hash_value(OrigFuncName));
+    // auto It = RecordIndices.find(LogicalFuncKey);
+    // std::vector<llvm::coverage::CountedRegion> RegionsToAdd;
+
+    // if (It != RecordIndices.end()) {
+    //   auto &ExistingFunction = Functions[It->second];
+
+    //   for (const auto &NewRegion : Function.CountedRegions) {
+    //     for (auto &ExistingRegion : ExistingFunction.CountedRegions) {
+    //       if((NewRegion.ObjectFilename != ExistingRegion.ObjectFilename) &&
+    //         (NewRegion.startLoc() >= ExistingRegion.startLoc()) &&
+    //           (NewRegion.endLoc() <= ExistingRegion.endLoc())){
+    //           RegionsToAdd.push_back(NewRegion);
+    //       }
+    //     }
+    //   }
+    //   ExistingFunction.CountedRegions.insert(ExistingFunction.CountedRegions.end(), RegionsToAdd.begin(), RegionsToAdd.end());
+    // }
+    // RecordIndices[LogicalFuncKey] = Functions.size();
+  }
+  //CHANGES MADE HERE
+
+  // Don't create records for (filenames, function) pairs we've already seen.
+  StringRef HashStrRef(HashStr);
+  if (!RecordProvenance[FilenamesHash].insert(hash_value(HashStrRef)).second){
     return Error::success();
   }
+
   Functions.push_back(std::move(Function));
 
   // Performance optimization: keep track of the indices of the function records
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index d911ce6a6ee68..4e7cb302afc01 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -254,8 +254,7 @@ void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
                                 InstrProfRecord &&I, uint64_t Weight,
                                 function_ref<void(Error)> Warn, StringRef Architecture) {
   auto &ProfileDataMap = FunctionData[Name];
-  StringRef SHAHash = hashSourceFile(Architecture);
-  llvm::errs() << "SHA Hashing: " << SHAHash << "\n";
+  // StringRef SHAHash = hashSourceFile(Architecture);
   if(!Architecture.empty()){
     std::string HashStr = std::to_string(Hash) + ":" + Architecture.str();
     llvm::StringRef HashRef(HashStr);
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index f8b366ac3b3b6..45a8dcf76010f 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -218,9 +218,6 @@ void SourceCoverageViewText::renderLineCoverageColumn(
     return;
   }
   std::string C = formatBinaryCount(Line.getExecutionCount());
-  if(C == "2"){
-    llvm::errs() << C << "\n";
-  }
   OS.indent(LineCoverageColumnWidth - C.size());
   colored_ostream(OS, raw_ostream::MAGENTA, Line.hasMultipleRegions() && getOptions().Colors) << C;
   OS << '|';

>From 41d03b02a2fe8cabde2a6237219eb3d171a97e7c Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Tue, 22 Jul 2025 13:43:40 -0700
Subject: [PATCH 10/17] changed from hashing arches to hashing executables in
 llvm-profdata and llvm-cov

---
 .../ProfileData/Coverage/CoverageMapping.h    | 13 ++--
 .../ProfileData/Coverage/CoverageMapping.cpp  | 60 ++++++++++---------
 llvm/tools/llvm-cov/CodeCoverage.cpp          |  8 ++-
 llvm/tools/llvm-cov/CoverageViewOptions.h     |  1 +
 .../tools/llvm-cov/SourceCoverageViewText.cpp |  6 +-
 llvm/tools/llvm-profdata/llvm-profdata.cpp    |  2 +-
 6 files changed, 49 insertions(+), 41 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 118f4e1fd662a..8ed62cfcdfc25 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -1019,7 +1019,7 @@ class CoverageMapping {
     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
     std::optional<std::reference_wrapper<IndexedInstrProfReader>>
         &ProfileReader,
-    CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename = "");
+    CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename = "", bool ShowArchExecutables = false);
   
   static Error loadFromReaders(
     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
@@ -1033,15 +1033,18 @@ class CoverageMapping {
                std::optional<std::reference_wrapper<IndexedInstrProfReader>>
                    &ProfileReader,
                CoverageMapping &Coverage, bool &DataFound,
-               SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr, StringRef ObjectFilename = "");
+               SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr, StringRef ObjectFilename = "", 
+                bool ShowArchExecutables = false);
 
   /// Add a function record corresponding to \p Record.
   Error loadFunctionRecord(
       const CoverageMappingRecord &Record,
       const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
-          &ProfileReader, StringRef ObjectFilename = "");
+          &ProfileReader, StringRef ObjectFilename = "", bool ShowArchExecutables = false);
   
-  Error loadFunctionRecord(const CoverageMappingRecord &Record, const std::optional<std::reference_wrapper<IndexedInstrProfReader>> &ProfileReader, const std::string &Arch, StringRef ObjectFilename = "");
+  Error loadFunctionRecord(const CoverageMappingRecord &Record, 
+    const std::optional<std::reference_wrapper<IndexedInstrProfReader>> &ProfileReader, 
+    const std::string &Arch, StringRef ObjectFilename = "");
 
   /// Look up the indices for function records which are at least partially
   /// defined in the specified file. This is guaranteed to return a superset of
@@ -1075,7 +1078,7 @@ class CoverageMapping {
        std::optional<StringRef> ProfileFilename, vfs::FileSystem &FS,
        ArrayRef<StringRef> Arches = {}, StringRef CompilationDir = "",
        const object::BuildIDFetcher *BIDFetcher = nullptr,
-       bool CheckBinaryIDs = false);
+       bool CheckBinaryIDs = false, bool ShowArchExecutables = false);
 
   /// The number of functions that couldn't have their profiles mapped.
   ///
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index c38df7c41f940..1f7e057d58b1e 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -976,7 +976,7 @@ class MCDCDecisionRecorder {
 Error CoverageMapping::loadFunctionRecord(
     const CoverageMappingRecord &Record,
     const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
-        &ProfileReader, StringRef ObjectFilename) {
+        &ProfileReader, StringRef ObjectFilename, bool ShowArchExecutables) {
   StringRef OrigFuncName = Record.FunctionName;
   if (OrigFuncName.empty())
     return make_error<CoverageMapError>(coveragemap_error::malformed,
@@ -991,7 +991,7 @@ Error CoverageMapping::loadFunctionRecord(
 
   uint64_t FuncArchHash = Record.FunctionHash;
   if(!Arch.empty()){
-    std::string HashStr = std::to_string(Record.FunctionHash) + ":" + Arch.str();
+    std::string HashStr = std::to_string(Record.FunctionHash) + ":" + ObjectFilename.str();
     llvm::StringRef HashRef(HashStr);
     FuncArchHash = IndexedInstrProf::ComputeHash(HashRef);
   }
@@ -1102,28 +1102,29 @@ Error CoverageMapping::loadFunctionRecord(
 
   //CHANGES MADE HERE
   auto FilenamesHash = hash_combine_range(Record.Filenames);
-  std::string HashStr = OrigFuncName.str(); /*+ ":" + Arch.str();*/
-  if(!Arch.empty()){
+  std::string HashStr = OrigFuncName.str();
+  if(ShowArchExecutables){
     HashStr += ":" + Arch.str();
-    // auto LogicalFuncKey = std::make_pair(FilenamesHash, hash_value(OrigFuncName));
-    // auto It = RecordIndices.find(LogicalFuncKey);
-    // std::vector<llvm::coverage::CountedRegion> RegionsToAdd;
-
-    // if (It != RecordIndices.end()) {
-    //   auto &ExistingFunction = Functions[It->second];
-
-    //   for (const auto &NewRegion : Function.CountedRegions) {
-    //     for (auto &ExistingRegion : ExistingFunction.CountedRegions) {
-    //       if((NewRegion.ObjectFilename != ExistingRegion.ObjectFilename) &&
-    //         (NewRegion.startLoc() >= ExistingRegion.startLoc()) &&
-    //           (NewRegion.endLoc() <= ExistingRegion.endLoc())){
-    //           RegionsToAdd.push_back(NewRegion);
-    //       }
-    //     }
-    //   }
-    //   ExistingFunction.CountedRegions.insert(ExistingFunction.CountedRegions.end(), RegionsToAdd.begin(), RegionsToAdd.end());
-    // }
-    // RecordIndices[LogicalFuncKey] = Functions.size();
+  }else{
+    auto LogicalFuncKey = std::make_pair(FilenamesHash, hash_value(OrigFuncName));
+    auto It = RecordIndices.find(LogicalFuncKey);
+    std::vector<llvm::coverage::CountedRegion> RegionsToAdd;
+
+    if (It != RecordIndices.end()) {
+      auto &ExistingFunction = Functions[It->second];
+
+      for (const auto &NewRegion : Function.CountedRegions) {
+        for (auto &ExistingRegion : ExistingFunction.CountedRegions) {
+          if((NewRegion.ObjectFilename != ExistingRegion.ObjectFilename) &&
+            (NewRegion.startLoc() >= ExistingRegion.startLoc()) &&
+              (NewRegion.endLoc() <= ExistingRegion.endLoc())){
+              RegionsToAdd.push_back(NewRegion);
+          }
+        }
+      }
+      ExistingFunction.CountedRegions.insert(ExistingFunction.CountedRegions.end(), RegionsToAdd.begin(), RegionsToAdd.end());
+    }
+    RecordIndices[LogicalFuncKey] = Functions.size();
   }
   //CHANGES MADE HERE
 
@@ -1180,7 +1181,7 @@ Error CoverageMapping::loadFromReaders(
     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
     std::optional<std::reference_wrapper<IndexedInstrProfReader>>
         &ProfileReader,
-    CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename) {
+    CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename, bool ShowArchExecutables) {
   
   Coverage.setArchitecture(Arch);
   assert(!Coverage.SingleByteCoverage || !ProfileReader ||
@@ -1193,7 +1194,7 @@ Error CoverageMapping::loadFromReaders(
       if (Error E = RecordOrErr.takeError())
         return E;
       const auto &Record = *RecordOrErr;
-      if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader, ObjectFilename))
+      if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader, ObjectFilename, ShowArchExecutables))
         return E;
     }
   }
@@ -1224,7 +1225,7 @@ Error CoverageMapping::loadFromFile(
     std::optional<std::reference_wrapper<IndexedInstrProfReader>>
         &ProfileReader,
     CoverageMapping &Coverage, bool &DataFound,
-    SmallVectorImpl<object::BuildID> *FoundBinaryIDs, StringRef ObjectFilename) {
+    SmallVectorImpl<object::BuildID> *FoundBinaryIDs, StringRef ObjectFilename, bool ShowArchExecutables) {
   auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(
       Filename, /*IsText=*/false, /*RequiresNullTerminator=*/false);
   if (std::error_code EC = CovMappingBufOrErr.getError())
@@ -1256,7 +1257,7 @@ Error CoverageMapping::loadFromFile(
                        }));
   }
   DataFound |= !Readers.empty();
-  if (Error E = loadFromReaders(Readers, ProfileReader, Coverage, Arch, ObjectFilename))
+  if (Error E = loadFromReaders(Readers, ProfileReader, Coverage, Arch, ObjectFilename, ShowArchExecutables))
     return createFileError(Filename, std::move(E));
   return Error::success();
 }
@@ -1265,7 +1266,7 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
     ArrayRef<StringRef> ObjectFilenames,
     std::optional<StringRef> ProfileFilename, vfs::FileSystem &FS,
     ArrayRef<StringRef> Arches, StringRef CompilationDir,
-    const object::BuildIDFetcher *BIDFetcher, bool CheckBinaryIDs) {
+    const object::BuildIDFetcher *BIDFetcher, bool CheckBinaryIDs, bool ShowArchExecutables) {
   std::unique_ptr<IndexedInstrProfReader> ProfileReader;
   if (ProfileFilename) {
     auto ProfileReaderOrErr =
@@ -1297,7 +1298,8 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
   for (const auto &File : llvm::enumerate(ObjectFilenames)) {
     if (Error E = loadFromFile(File.value(), GetArch(File.index()),
                                CompilationDir, ProfileReaderRef, *Coverage,
-                               DataFound, &FoundBinaryIDs, ObjectFilenames[File.index()]))
+                               DataFound, &FoundBinaryIDs, ObjectFilenames[File.index()], 
+                               ShowArchExecutables))
       return std::move(E);
   }
 
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index 9885c2ac36df2..93d4f03032ac8 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -486,7 +486,8 @@ std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
   auto FS = vfs::getRealFileSystem();
   auto CoverageOrErr = CoverageMapping::load(
       ObjectFilenames, PGOFilename, *FS, CoverageArches,
-      ViewOpts.CompilationDirectory, BIDFetcher.get(), CheckBinaryIDs);
+      ViewOpts.CompilationDirectory, BIDFetcher.get(), CheckBinaryIDs, 
+      ViewOpts.ShowArchExecutables);
   if (Error E = CoverageOrErr.takeError()) {
     error("failed to load coverage: " + toString(std::move(E)));
     return nullptr;
@@ -824,6 +825,10 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
   cl::opt<bool> CheckBinaryIDs(
       "check-binary-ids", cl::desc("Fail if an object couldn't be found for a "
                                    "binary ID in the profile"));
+  cl::opt<bool> ShowArchExecutables(
+    "show-arch-executables",
+    cl::desc("Show coverage per architecture and the associated executable slice"),
+    cl::init(false));
 
   auto commandLineParser = [&, this](int argc, const char **argv) -> int {
     cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
@@ -990,6 +995,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
     ViewOpts.ExportSummaryOnly = SummaryOnly;
     ViewOpts.NumThreads = NumThreads;
     ViewOpts.CompilationDirectory = CompilationDirectory;
+    ViewOpts.ShowArchExecutables = ShowArchExecutables;
 
     return 0;
   };
diff --git a/llvm/tools/llvm-cov/CoverageViewOptions.h b/llvm/tools/llvm-cov/CoverageViewOptions.h
index 1f6ad570f86f2..6129bcfb59757 100644
--- a/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -47,6 +47,7 @@ struct CoverageViewOptions {
   bool SkipFunctions;
   bool SkipBranches;
   bool BinaryCounters;
+  bool ShowArchExecutables;
   OutputFormat Format;
   BranchOutputType ShowBranches;
   std::string ShowOutputDirectory;
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index 45a8dcf76010f..9471f7529e104 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -229,11 +229,7 @@ void SourceCoverageViewText::renderArchLineCoverageColumn(
     OS.indent(LineCoverageColumnWidth) << '|';
     return;
   }
-  std::string C = "";
-  for(LineCoverageStats Counts : LineArchStats[Line.getLine()]){
-    C += formatBinaryCount(Counts.getExecutionCount()) + "/";
-  }
-  // std::string C = formatBinaryCount(Line.getExecutionCount());
+  std::string C = formatBinaryCount(Line.getExecutionCount());
   OS.indent(LineCoverageColumnWidth - C.size());
   colored_ostream(OS, raw_ostream::MAGENTA, Line.hasMultipleRegions() && getOptions().Colors) << C;
   OS << '|';
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 900d105c66e55..1f74d80cf58d9 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -743,7 +743,7 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
       consumeError(ArchOrError.takeError());
       Architecture = "unknown";
     }
-    // Architecture = ExeRef;
+    Architecture = ExeRef;
   }
   //ANDRES CODE
 

>From 6cdb2e1e3e61db5f523b43a56c25673cf7431614 Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Wed, 23 Jul 2025 14:17:43 -0700
Subject: [PATCH 11/17] updating repository

---
 .../ProfileData/Coverage/CoverageMapping.cpp  | 23 ++---
 llvm/tools/llvm-profdata/llvm-profdata.cpp    | 85 ++++++++++---------
 2 files changed, 58 insertions(+), 50 deletions(-)

diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 1f7e057d58b1e..cf24a85771878 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -40,7 +40,7 @@
 #include <stack>
 #include <string>
 #include <system_error>
-#include <unordered_map>
+#include <unordered_set>
 #include <utility>
 #include <vector>
 
@@ -1113,24 +1113,27 @@ Error CoverageMapping::loadFunctionRecord(
     if (It != RecordIndices.end()) {
       auto &ExistingFunction = Functions[It->second];
 
+      // Step 1: Build a set of existing ObjectFilenames
+      std::unordered_set<std::string> ExistingFilenames;
+      for (const auto &ExistingRegion : ExistingFunction.CountedRegions) {
+        ExistingFilenames.insert(ExistingRegion.ObjectFilename.str());
+      }
+
+      // Step 2: Only add NewRegions with unique ObjectFilenames
       for (const auto &NewRegion : Function.CountedRegions) {
-        for (auto &ExistingRegion : ExistingFunction.CountedRegions) {
-          if((NewRegion.ObjectFilename != ExistingRegion.ObjectFilename) &&
-            (NewRegion.startLoc() >= ExistingRegion.startLoc()) &&
-              (NewRegion.endLoc() <= ExistingRegion.endLoc())){
-              RegionsToAdd.push_back(NewRegion);
-          }
+        if (ExistingFilenames.find(NewRegion.ObjectFilename.str()) == ExistingFilenames.end()) {
+          ExistingFunction.CountedRegions.push_back(NewRegion);
         }
+        
       }
-      ExistingFunction.CountedRegions.insert(ExistingFunction.CountedRegions.end(), RegionsToAdd.begin(), RegionsToAdd.end());
     }
     RecordIndices[LogicalFuncKey] = Functions.size();
   }
   //CHANGES MADE HERE
 
   // Don't create records for (filenames, function) pairs we've already seen.
-  StringRef HashStrRef(HashStr);
-  if (!RecordProvenance[FilenamesHash].insert(hash_value(HashStrRef)).second){
+  StringRef Hash(HashStr);
+  if (!RecordProvenance[FilenamesHash].insert(hash_value(Hash)).second){
     return Error::success();
   }
 
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 1f74d80cf58d9..4dbdce3a1ab5b 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -199,6 +199,11 @@ static cl::opt<std::string> RemappingFile("remapping-file",
                                           cl::desc("Symbol remapping file"));
 static cl::alias RemappingFileA("r", cl::desc("Alias for --remapping-file"),
                                 cl::aliasopt(RemappingFile));
+static cl::list<std::string> ObjectAwareHashing("object-aware-hashing", 
+                                cl::desc("Includes the object file name when hashing function names "
+                                              "and control flow hashes, allowing functions from different "
+                                              "binaries to be distinguished"), 
+                                cl::sub(MergeSubcommand));
 static cl::opt<bool>
     UseMD5("use-md5", cl::init(false), cl::Hidden,
            cl::desc("Choose to use MD5 to represent string in name table (only "
@@ -690,32 +695,32 @@ static void overlapInput(const std::string &BaseFilename,
   }
 }
 
-//ANDRES FUNCTION
-Expected<std::string> getArchitectureFromExecutable(StringRef ExecutablePath){
-  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError = MemoryBuffer::getFile(ExecutablePath);
-  if(!BufferOrError){
-    return createStringError(BufferOrError.getError(), "Failed to load input file");
-  }
+// //ANDRES FUNCTION
+// Expected<std::string> getArchitectureFromExecutable(StringRef ExecutablePath){
+//   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError = MemoryBuffer::getFile(ExecutablePath);
+//   if(!BufferOrError){
+//     return createStringError(BufferOrError.getError(), "Failed to load input file");
+//   }
 
-  Expected<std::unique_ptr<object::ObjectFile>> ObjectOrError = object::ObjectFile::createObjectFile(BufferOrError.get()->getMemBufferRef());
-  if(!ObjectOrError){
-    return ObjectOrError.takeError();
-  }
+//   Expected<std::unique_ptr<object::ObjectFile>> ObjectOrError = object::ObjectFile::createObjectFile(BufferOrError.get()->getMemBufferRef());
+//   if(!ObjectOrError){
+//     return ObjectOrError.takeError();
+//   }
 
-  std::unique_ptr<llvm::object::ObjectFile> &Object = ObjectOrError.get();
+//   std::unique_ptr<llvm::object::ObjectFile> &Object = ObjectOrError.get();
 
-  StringRef ArchStr = Object->getArch() != Triple::UnknownArch ? Triple::getArchTypeName(Object->getArch()) : "unknown";
+//   StringRef ArchStr = Object->getArch() != Triple::UnknownArch ? Triple::getArchTypeName(Object->getArch()) : "unknown";
 
-  return ArchStr.str();
-}
-//ANDRES FUNCTION
+//   return ArchStr.str();
+// }
+// //ANDRES FUNCTION
 
 /// Load an input into a writer context.
 static void
 loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
           const InstrProfCorrelator *Correlator, const StringRef ProfiledBinary,
           WriterContext *WC, const object::BuildIDFetcher *BIDFetcher = nullptr,
-          const ProfCorrelatorKind *BIDFetcherCorrelatorKind = nullptr) {
+          const ProfCorrelatorKind *BIDFetcherCorrelatorKind = nullptr, StringRef ObjectFilename = "") {
   std::unique_lock<std::mutex> CtxGuard{WC->Lock};
 
   // Copy the filename, because llvm::ThreadPool copied the input "const
@@ -726,24 +731,24 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
   //ANDRES CODE
   std::string ExecutableName;
   std::string ProfileFile = Input.Filename;
-  std::string Architecture = "";
+  std::string ObjectFilename = "";
 
   StringRef FilenameRef = Filename;
-  if(FilenameRef.contains(':')){
-    StringRef ExeRef, ProfRef;
-    std::tie(ExeRef, ProfRef) = FilenameRef.split(':');
-    if(!ExeRef.empty() && !ProfRef.empty()){
-      ExecutableName = ExeRef.str();
-      ProfileFile = ProfRef.str();
-    }
-    Expected<std::string> ArchOrError = getArchitectureFromExecutable(ExeRef);
-    if(ArchOrError){
-      Architecture = std::move(ArchOrError.get());
-    }else{
-      consumeError(ArchOrError.takeError());
-      Architecture = "unknown";
-    }
-    Architecture = ExeRef;
+  if(!ObjectFilename.empty()){
+    // StringRef ExeRef, ProfRef;
+    // std::tie(ExeRef, ProfRef) = FilenameRef.split(':');
+    // if(!ExeRef.empty() && !ProfRef.empty()){
+    ObjectFilename = ObjectFilename.data();
+      // ProfileFile = ProfRef.str();
+    // }
+    // Expected<std::string> ArchOrError = getArchitectureFromExecutable(ExeRef);
+    // if(ArchOrError){
+    //   Architecture = std::move(ArchOrError.get());
+    // }else{
+    //   consumeError(ArchOrError.takeError());
+    //   Architecture = "unknown";
+    // }
+    // ObjectFilename = ExeRef;
   }
   //ANDRES CODE
 
@@ -837,7 +842,7 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
                                                 ? *BIDFetcherCorrelatorKind
                                                 : ProfCorrelatorKind::NONE;
   auto ReaderOrErr = InstrProfReader::create(ProfileFile /*ANDRES changed from Input.Filename to ProfileFile*/, *FS, Correlator, //THIS IS THE IMPORTANT LINE!!!!
-                                             BIDFetcher, CorrelatorKind, Warn, Architecture /*ANDRES added this parameter*/);
+                                             BIDFetcher, CorrelatorKind, Warn, ObjectFilename /*ANDRES added this parameter*/);
   if (Error E = ReaderOrErr.takeError()) {
     // Skip the empty profiles by returning silently.
     auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
@@ -875,7 +880,7 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
       bool firstTime = WC->WriterErrorCodes.insert(ErrCode).second;
       handleMergeWriterError(make_error<InstrProfError>(ErrCode, Msg),
                              Input.Filename, FuncName, firstTime);
-    }, Architecture);
+    }, ObjectFilename);
   }
 
   if (KeepVTableSymbols) {
@@ -1084,18 +1089,18 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
         MaxTraceLength));
 
   if (NumThreads == 1) {
-    for (const auto &Input : Inputs)
-      loadInput(Input, Remapper, Correlator.get(), ProfiledBinary,
-                Contexts[0].get(), BIDFetcher.get(), &BIDFetcherCorrelateKind);
+    for (int I = 0; I < int(Inputs.size()); ++I)
+      loadInput(Inputs[I], Remapper, Correlator.get(), ProfiledBinary,
+                Contexts[0].get(), BIDFetcher.get(), &BIDFetcherCorrelateKind, !ObjectAwareHashing.empty() ? ObjectAwareHashing[I] : "");
   } else {
     DefaultThreadPool Pool(hardware_concurrency(NumThreads));
 
     // Load the inputs in parallel (N/NumThreads serial steps).
     unsigned Ctx = 0;
-    for (const auto &Input : Inputs) {
-      Pool.async(loadInput, Input, Remapper, Correlator.get(), ProfiledBinary,
+    for (int I = 0; I < int(Inputs.size()); ++I) {
+      Pool.async(loadInput, Inputs[I], Remapper, Correlator.get(), ProfiledBinary,
                  Contexts[Ctx].get(), BIDFetcher.get(),
-                 &BIDFetcherCorrelateKind);
+                 &BIDFetcherCorrelateKind, !ObjectAwareHashing[I].empty() ? ObjectAwareHashing[I] : "");
       Ctx = (Ctx + 1) % NumThreads;
     }
     Pool.wait();

>From bea56b993df209fb593b4dfc0504fcb3e168352c Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Wed, 23 Jul 2025 20:23:16 -0700
Subject: [PATCH 12/17] updated compiler error

---
 llvm/tools/llvm-profdata/llvm-profdata.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 4dbdce3a1ab5b..194c59fb7e8c4 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -720,7 +720,7 @@ static void
 loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
           const InstrProfCorrelator *Correlator, const StringRef ProfiledBinary,
           WriterContext *WC, const object::BuildIDFetcher *BIDFetcher = nullptr,
-          const ProfCorrelatorKind *BIDFetcherCorrelatorKind = nullptr, StringRef ObjectFilename = "") {
+          const ProfCorrelatorKind *BIDFetcherCorrelatorKind = nullptr, StringRef ObjectAwareHashing = "") {
   std::unique_lock<std::mutex> CtxGuard{WC->Lock};
 
   // Copy the filename, because llvm::ThreadPool copied the input "const
@@ -738,7 +738,7 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
     // StringRef ExeRef, ProfRef;
     // std::tie(ExeRef, ProfRef) = FilenameRef.split(':');
     // if(!ExeRef.empty() && !ProfRef.empty()){
-    ObjectFilename = ObjectFilename.data();
+    ObjectFilename = ObjectAwareHashing.data();
       // ProfileFile = ProfRef.str();
     // }
     // Expected<std::string> ArchOrError = getArchitectureFromExecutable(ExeRef);

>From ebcd68ebbc4f5d7cfa440b652e5a60cd8948c725 Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Mon, 28 Jul 2025 01:32:19 -0700
Subject: [PATCH 13/17] fixed issues with time complexity and region counts

---
 .../ProfileData/Coverage/CoverageMapping.h    |  16 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  | 142 ++++++++++++++++--
 llvm/tools/llvm-cov/CodeCoverage.cpp          |   3 +-
 .../llvm-profdata-cross-arch/CMakeLists.txt   |  35 -----
 .../ELFSymbolReader.cpp                       |  90 -----------
 .../ELFSymbolReader.h                         |  31 ----
 .../llvm-profdata-cross-arch.cpp              | 112 --------------
 llvm/tools/llvm-profdata/llvm-profdata.cpp    |   4 +-
 8 files changed, 147 insertions(+), 286 deletions(-)
 delete mode 100644 llvm/tools/llvm-profdata-cross-arch/CMakeLists.txt
 delete mode 100644 llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.cpp
 delete mode 100644 llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.h
 delete mode 100644 llvm/tools/llvm-profdata-cross-arch/llvm-profdata-cross-arch.cpp

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index 8ed62cfcdfc25..a91bbde99066d 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -748,6 +748,16 @@ struct FunctionRecord {
   FunctionRecord(FunctionRecord &&FR) = default;
   FunctionRecord &operator=(FunctionRecord &&) = default;
 
+  FunctionRecord(const FunctionRecord &FR)
+    : Name(FR.Name),
+      Filenames(FR.Filenames),
+      CountedRegions(FR.CountedRegions),
+      CountedBranchRegions(FR.CountedBranchRegions),
+      MCDCRecords(FR.MCDCRecords),
+      ExecutionCount(FR.ExecutionCount),
+      ObjectFilename(FR.ObjectFilename) {}
+
+
   void pushMCDCRecord(MCDCRecord &&Record) {
     MCDCRecords.push_back(std::move(Record));
   }
@@ -1006,7 +1016,9 @@ class CoverageMapping {
   std::vector<std::pair<std::string, uint64_t>> FuncHashMismatches;
   StringRef Arch;
   DenseMap<std::pair<size_t, hash_code>, unsigned> RecordIndices;
-  uint64_t Counter = 0;
+  uint64_t DebugCount = 0;
+  std::vector<FunctionRecord> AllFunctionRegions;
+
 
   std::map<std::pair<std::string, std::string>, std::vector<uint64_t>> AggregatedCounts;
 
@@ -1103,7 +1115,7 @@ class CoverageMapping {
   /// The given filename must be the name as recorded in the coverage
   /// information. That is, only names returned from getUniqueSourceFiles will
   /// yield a result.
-  LLVM_ABI CoverageData getCoverageForFile(StringRef Filename) const;
+  LLVM_ABI CoverageData getCoverageForFile(StringRef Filename, bool ShowArchExecutables = false) const;
 
   /// Get the coverage for a particular function.
   LLVM_ABI CoverageData
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index cf24a85771878..6248c202ec6ff 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ProfileData/Coverage/CoverageMapping.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/ADT/SmallVector.h"
@@ -23,10 +24,12 @@
 #include "llvm/ProfileData/Coverage/CoverageMappingReader.h"
 #include "llvm/ProfileData/InstrProfReader.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/DebugCounter.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/ScopedPrinter.h"
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
@@ -1106,39 +1109,74 @@ Error CoverageMapping::loadFunctionRecord(
   if(ShowArchExecutables){
     HashStr += ":" + Arch.str();
   }else{
+    //THIS ALGORITHM NEEDS TO BE FIXED!!!
     auto LogicalFuncKey = std::make_pair(FilenamesHash, hash_value(OrigFuncName));
     auto It = RecordIndices.find(LogicalFuncKey);
-    std::vector<llvm::coverage::CountedRegion> RegionsToAdd;
 
     if (It != RecordIndices.end()) {
       auto &ExistingFunction = Functions[It->second];
 
-      // Step 1: Build a set of existing ObjectFilenames
-      std::unordered_set<std::string> ExistingFilenames;
-      for (const auto &ExistingRegion : ExistingFunction.CountedRegions) {
-        ExistingFilenames.insert(ExistingRegion.ObjectFilename.str());
+
+      // Create a map of existing regions for efficient lookup.
+      // The key uniquely identifies the source region.
+      using RegionKey = std::tuple<unsigned, unsigned, unsigned, unsigned, unsigned>;
+      std::map<RegionKey, CountedRegion *> ExistingRegionsMap;
+      for (auto &ExistingRegion : ExistingFunction.CountedRegions) {
+        RegionKey Key = {ExistingRegion.FileID, ExistingRegion.LineStart,
+                         ExistingRegion.ColumnStart, ExistingRegion.LineEnd,
+                         ExistingRegion.ColumnEnd};
+        ExistingRegionsMap[Key] = &ExistingRegion;
+      }
+
+      for (auto NewRegion : Function.CountedRegions) {
+        AllFunctionRegions[It->second].CountedRegions.push_back(NewRegion);
       }
 
-      // Step 2: Only add NewRegions with unique ObjectFilenames
+      // Merge the new regions into the existing function's regions.
       for (const auto &NewRegion : Function.CountedRegions) {
-        if (ExistingFilenames.find(NewRegion.ObjectFilename.str()) == ExistingFilenames.end()) {
+        RegionKey Key = {NewRegion.FileID, NewRegion.LineStart,
+                         NewRegion.ColumnStart, NewRegion.LineEnd,
+                         NewRegion.ColumnEnd};
+        auto MapIt = ExistingRegionsMap.find(Key);
+        if (MapIt != ExistingRegionsMap.end()) {
+          // Region already exists, merge counts by taking the max.
+          CountedRegion *ExistingRegion = MapIt->second;
+          // llvm::errs() << "EXECUTION COUNTS BEFORE: " +  to_string(ExistingRegion->ExecutionCount) << "\n";
+          // llvm::errs() << "(" << ExistingRegion->LineStart << ", " << ExistingRegion->LineEnd << ")" << "\n";
+          ExistingRegion->ExecutionCount += NewRegion.ExecutionCount;
+          // llvm::errs() << "EXECUTION COUNTS AFTER: " +  to_string(ExistingRegion->ExecutionCount) << "\n";
+          // DebugCount++;
+        } else {
+          // llvm::errs() << "ENTERS ELSE STATEMENT HERE" << "\n";
+          // llvm::errs() << "(" << NewRegion.LineStart << ", " << NewRegion.LineEnd << ")" << "\n";
           ExistingFunction.CountedRegions.push_back(NewRegion);
         }
-        
       }
+      // Since we modified an existing function, we don't add a new one.
+      // We just need to make sure we don't add the new 'Function' object later.
+      // The logic below this block needs to be adjusted to handle this.
+      return Error::success();
     }
-    RecordIndices[LogicalFuncKey] = Functions.size();
+    // llvm::errs() << "ENTERS ELSE STATEMENT HERE" << "\n";
+    RecordIndices.insert({LogicalFuncKey, Functions.size()});
+    //THIS ALGORITHM NEEDS TO BE FIXED!!!
   }
   //CHANGES MADE HERE
 
+  // if(DebugCount == 29){
+  //   llvm::errs() << "ENTERS ELSE STATEMENT HERE" << "\n";
+  // }
+
+
+
   // Don't create records for (filenames, function) pairs we've already seen.
   StringRef Hash(HashStr);
   if (!RecordProvenance[FilenamesHash].insert(hash_value(Hash)).second){
     return Error::success();
   }
 
+  AllFunctionRegions.push_back(Function);
   Functions.push_back(std::move(Function));
-
   // Performance optimization: keep track of the indices of the function records
   // which correspond to each filename. This can be used to substantially speed
   // up queries for coverage info in a file.
@@ -1594,6 +1632,59 @@ class SegmentBuilder {
 
     sortNestedRegions(Regions);
 
+    // // This map is used to efficiently check for the existence of a specific region
+    // // from a specific binary, which is the purpose of the innermost loop in the
+    // // original code.
+    // // Key: A tuple uniquely identifying a region's location and its binary of origin.
+    // // Value: A boolean indicating if the region is NOT a SkippedRegion.
+    // using RegionKey = std::tuple<LineColPair, LineColPair, StringRef>;
+    // std::map<RegionKey, bool> RegionExistenceMap;
+    // for (const auto &R : Regions) {
+    //   RegionKey Key = {R.startLoc(), R.endLoc(), R.ObjectFilename};
+    //   // Only insert if it's a more "valid" region than what might already be there.
+    //   if (R.Kind != CounterMappingRegion::SkippedRegion)
+    //     RegionExistenceMap[Key] = true;
+    //   else
+    //     RegionExistenceMap.try_emplace(Key, false);
+    // }
+
+    // for (auto &I : Regions) {
+    //   // We are only interested in patching SkippedRegions.
+    //   if (I.Kind != CounterMappingRegion::SkippedRegion)
+    //     continue;
+
+    //   for (auto &J : Regions) {
+    //     // Find a non-skipped region 'J' from a different binary that contains 'I'.
+    //     if (I.ObjectFilename == J.ObjectFilename ||
+    //         J.Kind == CounterMappingRegion::SkippedRegion ||
+    //         !(I.startLoc() >= J.startLoc() && I.endLoc() <= J.endLoc())) {
+    //       continue;
+    //     }
+
+    //     // Check if a non-skipped region already exists at I's exact location
+    //     // coming from J's binary. This replaces the O(N) inner loop.
+    //     RegionKey KeyToFind = {I.startLoc(), I.endLoc(), J.ObjectFilename};
+    //     auto It = RegionExistenceMap.find(KeyToFind);
+
+    //     // If no region from J's binary exists at I's location, or if it does
+    //     // but it's a SkippedRegion, we can patch I with J's data.
+    //     if (It == RegionExistenceMap.end() || It->second == false) {
+    //       I.Kind = J.Kind;
+    //       I.ExecutionCount = J.ExecutionCount;
+    //       // We found a patch, no need to check other containing regions.
+    //       break;
+    //     }
+    //   }
+    // }
+
+    // llvm::errs() << "START HERE" << "\n";
+    // for(auto *I = Regions.begin(); I != Regions.end(); ++I){
+    //   llvm::errs() << "(" << to_string(I->startLoc().first) << ", " << to_string(I->endLoc().first) << ")" << "\n";
+    //   llvm::errs() << "Execution Count: " << I->ExecutionCount << "\n";
+    // }
+    // llvm::errs() << "END HERE" << "\n";
+
+
     for(auto *I = Regions.begin(); I != Regions.end(); ++I){
       bool FoundMatchInOtherBinary = false;
       for(auto *J = I + 1; J != Regions.end(); ++J){
@@ -1601,6 +1692,7 @@ class SegmentBuilder {
             J->Kind == CounterMappingRegion::SkippedRegion 
             && I->Kind != CounterMappingRegion::SkippedRegion &&
             J->startLoc() >= I->startLoc() && J->endLoc() <= I->endLoc()){
+          // llvm::errs() << "(" << to_string(J->startLoc().first) << ", " << to_string(J->endLoc().first) << ")" << "\n";
           for(auto *K = J + 1; K != Regions.end(); ++K){
             if(K->ObjectFilename == I->ObjectFilename &&
               J->startLoc() == K->startLoc() && J->endLoc() == K->endLoc()){
@@ -1614,6 +1706,13 @@ class SegmentBuilder {
         }
       }
     }
+
+    // llvm::errs() << "START HERE" << "\n";
+    // for(auto *I = Regions.begin(); I != Regions.end(); ++I){
+    //   llvm::errs() << "(" << to_string(I->startLoc().first) << ", " << to_string(I->endLoc().first) << ")" << "\n";
+    //   llvm::errs() << "Execution Count: " << I->ExecutionCount << "\n";
+    // }
+    // llvm::errs() << "END HERE" << "\n";
     
 
     ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
@@ -1671,9 +1770,15 @@ static SmallBitVector gatherFileIDs(StringRef SourceFile,
 static std::optional<unsigned>
 findMainViewFileID(const FunctionRecord &Function) {
   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
-  for (const auto &CR : Function.CountedRegions)
+  uint64_t counter = 0;
+  for (const auto &CR : Function.CountedRegions){
+    // counter++;
+    // if(counter == 245){
+    //   llvm::errs() << counter << "\n";
+    // }
     if (CR.Kind == CounterMappingRegion::ExpansionRegion)
       IsNotExpandedFile[CR.ExpandedFileID] = false;
+  }
   int I = IsNotExpandedFile.find_first();
   if (I == -1)
     return std::nullopt;
@@ -1695,17 +1800,26 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) {
   return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
 }
 
-CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
+CoverageData CoverageMapping::getCoverageForFile(StringRef Filename, bool ShowArchExecutables) const {
   assert(SingleByteCoverage);
   CoverageData FileCoverage(*SingleByteCoverage, Filename);
   std::vector<CountedRegion> Regions;
 
   // Look up the function records in the given file. Due to hash collisions on
   // the filename, we may get back some records that are not in the file.
+  // DenseSet<CountedRegion> DeDuplicationSet;
   ArrayRef<unsigned> RecordIndices =
       getImpreciseRecordIndicesForFilename(Filename);
+  // for (unsigned RecordIndex : RecordIndices) {
+  //   const FunctionRecord &Function = AllFunctionRegions[RecordIndex];
+  //   for(const auto &I : Function.CountedRegions){
+  //     llvm::errs() << "(" << to_string(I.startLoc().first) << ", " << to_string(I.endLoc().first) << ")" << "\n";
+  //   }
+  // }
+  // ArrayRef<unsigned> RecordIndices =
+  //     getImpreciseRecordIndicesForFilename(Filename);
   for (unsigned RecordIndex : RecordIndices) {
-    const FunctionRecord &Function = Functions[RecordIndex];
+    const FunctionRecord &Function = ShowArchExecutables ? Functions[RecordIndex] : AllFunctionRegions[RecordIndex];
     auto MainFileID = findMainViewFileID(Filename, Function);
     auto FileIDs = gatherFileIDs(Filename, Function);
     for (const auto &CR : Function.CountedRegions)
@@ -1724,6 +1838,8 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename) const {
         FileCoverage.MCDCRecords.push_back(MR);
   }
 
+
+
   LLVM_DEBUG(dbgs() << "Emitting segments for file: " << Filename << "\n");
   FileCoverage.Segments = SegmentBuilder::buildSegments(Regions);
 
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index 93d4f03032ac8..1feb1f8402d38 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -29,6 +29,7 @@
 #include "llvm/ProfileData/Coverage/CoverageMapping.h"
 #include "llvm/ProfileData/InstrProfReader.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DebugCounter.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -396,7 +397,7 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile,
   auto SourceBuffer = getSourceFile(SourceFile);
   if (!SourceBuffer)
     return nullptr;
-  auto FileCoverage = Coverage.getCoverageForFile(SourceFile);
+  auto FileCoverage = Coverage.getCoverageForFile(SourceFile, ViewOpts.ShowArchExecutables);
   if (FileCoverage.empty())
     return nullptr;
 
diff --git a/llvm/tools/llvm-profdata-cross-arch/CMakeLists.txt b/llvm/tools/llvm-profdata-cross-arch/CMakeLists.txt
deleted file mode 100644
index b37f76db883b5..0000000000000
--- a/llvm/tools/llvm-profdata-cross-arch/CMakeLists.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-cmake_minimum_required(VERSION 3.13)
-project(llvm-profdata-cross-arch)
-
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
-
-# Find LLVM package
-find_package(LLVM REQUIRED CONFIG)
-
-message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
-message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
-
-# Set LLVM include and library directories
-include_directories(${LLVM_INCLUDE_DIRS})
-link_directories(${LLVM_LIBRARY_DIRS})
-add_definitions(${LLVM_DEFINITIONS})
-
-# Define the source files
-set(SOURCES
-    ELFSymbolReader.cpp
-    llvm-profdata-cross-arch.cpp
-)
-
-# Add the executable
-add_executable(llvm-profdata-cross-arch ${SOURCES})
-
-# Link against LLVM libraries
-llvm_map_components_to_libnames(llvm_libs
-    Core
-    Support
-    Object
-    Demangle
-)
-
-target_link_libraries(llvm-profdata-cross-arch ${llvm_libs})
diff --git a/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.cpp b/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.cpp
deleted file mode 100644
index 61076f4e72073..0000000000000
--- a/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "ELFSymbolReader.h"
-#include "llvm/Object/Binary.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Object/ELFObjectFile.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Demangle/Demangle.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/TargetSelect.h"
-
-
-using namespace llvm;
-using namespace llvm::object;
-
-Expected<std::vector<FunctionSymbol>> ELFSymbolReader::readSymbols(StringRef File){
-    Expected<OwningBinary<Binary>> BinOrErr = createBinary(File);
-    if(!BinOrErr){
-        return BinOrErr.takeError();
-    }
-
-    const ELFObjectFileBase *Obj = dyn_cast<ELFObjectFileBase>(BinOrErr->getBinary());
-    if(!Obj){
-        return createStringError(inconvertibleErrorCode(), "Not an ELF");
-    }
-
-    std::vector<FunctionSymbol> Syms;
-
-    for(const SymbolRef &Sym : Obj->symbols()){
-        if(!(cantFail(Sym.getType()) & SymbolRef::ST_Function)){
-            continue;
-        }
-        if(cantFail(Sym.getFlags()) & SymbolRef::SF_Undefined){
-            continue;
-        }
-        Expected<StringRef> NameOrErr = Sym.getName();
-        if(!NameOrErr){
-            consumeError(NameOrErr.takeError());
-            continue;
-        }
-        StringRef FuncNameRef = *NameOrErr;
-        if(FuncNameRef.starts_with("__")){
-            continue;
-        }
-        
-        // Skip symbols not in executable sections (e.g., not in .text)
-        Expected<section_iterator> SecOrErr = Sym.getSection();
-        if (!SecOrErr || *SecOrErr == Obj->section_end()){
-            continue;
-        }
-        StringRef SectionName;
-        if (Expected<StringRef> NameOrErr = (*SecOrErr)->getName()) {
-            SectionName = *NameOrErr;
-            if (!SectionName.equals_insensitive(".text")){
-                continue;
-            }
-        } else {
-            consumeError(NameOrErr.takeError());
-            continue;
-        }
-
-
-        uint64_t Addr = cantFail(Sym.getAddress());
-        StringRef NameRef = cantFail(Sym.getName());
-
-        FunctionSymbol FS;
-        FS.Address = Addr;
-        FS.Name = NameRef.str();
-        FS.DemangledName = llvm::demangle(FS.Name);
-        Syms.push_back(std::move(FS));
-    }
-    return Syms;
-}
-
-Expected<std::string> ELFSymbolReader::detectArchitecture(StringRef File){
-    Expected<OwningBinary<Binary>> BinOrErr = createBinary(File);
-    if(!BinOrErr){
-        return BinOrErr.takeError();
-    }
-    
-    const ELFObjectFileBase *Obj = dyn_cast<ELFObjectFileBase>(BinOrErr->getBinary());
-    if(!Obj){
-        return createStringError(inconvertibleErrorCode(), "Not an ELF");
-    }
-    return std::string(Triple::getArchTypeName(Obj->getArch()));
-}
-
-std::string ELFSymbolReader::demangleName(StringRef N){
-    return llvm::demangle(N.str());
-}
\ No newline at end of file
diff --git a/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.h b/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.h
deleted file mode 100644
index 99f88498d3d41..0000000000000
--- a/llvm/tools/llvm-profdata-cross-arch/ELFSymbolReader.h
+++ /dev/null
@@ -1,31 +0,0 @@
-#pragma once
-
-#include "llvm/Object/ELF.h"
-#include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/Error.h"
-#include <string>
-#include <vector>
-
-namespace llvm {
-
-    struct FunctionSymbol {
-        uint64_t Address;
-        std::string Name;
-        std::string DemangledName;
-    };
-
-    class ELFSymbolReader {
-        public:
-            //Expected datatype is an llvm data type that will either have the type specified in the <> or contain an error message explaining why the error occurred.
-            static Expected<std::vector<FunctionSymbol>> readSymbols(StringRef Filename);
-
-            static Expected<std::string> detectArchitecture(StringRef Filename);
-
-            static std::string demangleName(StringRef MangledName);
-    };
-
-} // namespace llvm
-
-
-
-
diff --git a/llvm/tools/llvm-profdata-cross-arch/llvm-profdata-cross-arch.cpp b/llvm/tools/llvm-profdata-cross-arch/llvm-profdata-cross-arch.cpp
deleted file mode 100644
index cbb904cc90161..0000000000000
--- a/llvm/tools/llvm-profdata-cross-arch/llvm-profdata-cross-arch.cpp
+++ /dev/null
@@ -1,112 +0,0 @@
-#include "ELFSymbolReader.h"
-#include "llvm/IR/Function.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <string>
-#include <utility>
-#include <vector>
-
-using namespace llvm;
-
-static cl::SubCommand AnalyzeSymbolsSubcommand("analyze-symbols", "Analyze symbols in ELF files for cross-arch profiling");
-static cl::SubCommand AnalyzeProfrawSubcommand("analyze-profraw", "Used to analyze mappings between source code and coverage data");
-
-static cl::list<std::string> ELFFiles(cl::Positional, cl::sub(AnalyzeSymbolsSubcommand), cl::desc("<elf-files>"), cl::OneOrMore);
-static cl::list<std::string> ProfrawFiles(cl::Positional, cl::sub(AnalyzeProfrawSubcommand), cl::desc("<profraw-files>"), cl::OneOrMore);
-
-static void findAndPrintMatches(const std::vector<std::vector<FunctionSymbol>> &AllSymbols, const std::vector<std::string> &Architectures) {
-    const std::vector<FunctionSymbol> &Symbols1 = AllSymbols[0];
-    const std::vector<FunctionSymbol> &Symbols2 = AllSymbols[1];
-
-    std::vector<std::pair<FunctionSymbol, FunctionSymbol>> Matches;
-
-    for (const FunctionSymbol &Sym1 : Symbols1) {
-        for (const FunctionSymbol &Sym2 : Symbols2) {
-            if (Sym1.Name == Sym2.Name) {
-                Matches.push_back({Sym1, Sym2});
-                continue;
-            }
-
-            if (!Sym1.DemangledName.empty() && !Sym2.DemangledName.empty() && Sym1.DemangledName == Sym2.DemangledName) {
-                Matches.push_back({Sym1, Sym2});
-                continue;
-            }
-        }
-    }
-
-    outs() << "Potential matches found: " << Matches.size() << "\n";
-    for (const auto &Match : Matches) {
-        if (Match.first.DemangledName == Match.second.DemangledName) {
-            outs() << " " << Match.first.DemangledName << " <-> " << Match.second.DemangledName << " (demangled match)\n";
-        } else {
-            outs() << " " << Match.first.Name << " <-> " << Match.second.Name << " (exact match)\n";
-        }
-    }
-
-    outs() << "\n" << Architectures[0] << "-only functions: " << (Symbols1.size() - Matches.size()) << "\n";
-    outs() << Architectures[1] << "-only functions: " << (Symbols2.size() - Matches.size()) << "\n";
-
-    if (!Matches.empty()) {
-        outs() << "\nSUCCESS: Found " << Matches.size() << " functions that exist in both architectures!\n";
-    } else {
-        outs() << "\nWARNING: No matching functions found between architectures.\n";
-    }
-}
-
-static int analyzeSymbols_main(StringRef ProgName) {
-    outs() << "=== Symbol Analysis ==\n\n";
-    std::vector<std::vector<FunctionSymbol>> AllSymbols;
-    std::vector<std::string> Architectures;
-
-    for (const std::string &Filename : ELFFiles) {
-        Expected<std::string> ArchOrErr = ELFSymbolReader::detectArchitecture(Filename);
-        if (!ArchOrErr) {
-            errs() << "Error detecting architecture for " << Filename << ": " << toString(ArchOrErr.takeError()) << "\n";
-            continue;
-        }
-
-        Expected<std::vector<FunctionSymbol>> SymbolsOrErr = ELFSymbolReader::readSymbols(Filename);
-        if (!SymbolsOrErr) {
-            errs() << "Error reading symbols from " << Filename << ": " << toString(SymbolsOrErr.takeError()) << "\n";
-            continue;
-        }
-
-        std::string Arch = ArchOrErr.get();
-        std::vector<FunctionSymbol> Symbols = SymbolsOrErr.get();
-
-        outs() << "File: " << Filename << "\n";
-        outs() << "Architecture: " << Arch << "\n";
-        outs() << "Functions found: " << Symbols.size() << "\n";
-
-        for (const FunctionSymbol &Symbol : Symbols) {
-            outs() << " 0x" << format("%08x", Symbol.Address) << ": " << Symbol.Name;
-            if (Symbol.DemangledName != Symbol.Name) {
-                outs() << " (" << Symbol.DemangledName << ")";
-            }
-            outs() << "\n";
-        }
-        outs() << "\n";
-
-        AllSymbols.push_back(std::move(Symbols));
-        Architectures.push_back(std::move(Arch));
-    }
-
-    if (AllSymbols.size() >= 2) {
-        outs() << "=== Cross-Architecture Analysis ==\n";
-        findAndPrintMatches(AllSymbols, Architectures);
-    }
-
-    return 0;
-}
-
-int main(int argc, const char *argv[]) {
-    cl::ParseCommandLineOptions(argc, argv, "LLVM cross-architecture profile analysis\n");
-    if (AnalyzeSymbolsSubcommand) {
-        return analyzeSymbols_main(argv[0]);
-    }
-
-    cl::PrintHelpMessage();
-    return 1;
-}
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 194c59fb7e8c4..7f4a0df458201 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -731,10 +731,10 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
   //ANDRES CODE
   std::string ExecutableName;
   std::string ProfileFile = Input.Filename;
-  std::string ObjectFilename = "";
+  StringRef ObjectFilename = "";
 
   StringRef FilenameRef = Filename;
-  if(!ObjectFilename.empty()){
+  if(!ObjectAwareHashing.empty()){
     // StringRef ExeRef, ProfRef;
     // std::tie(ExeRef, ProfRef) = FilenameRef.split(':');
     // if(!ExeRef.empty() && !ProfRef.empty()){

>From 035dd724ba23af8044b1a2d9ce37f78d540a58c4 Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Tue, 29 Jul 2025 18:44:18 -0700
Subject: [PATCH 14/17] llvm-lit test cases pass

---
 .../ProfileData/Coverage/CoverageMapping.h    |  18 +--
 .../Coverage/CoverageMappingReader.h          |   9 +-
 llvm/include/llvm/ProfileData/InstrProf.h     |  34 +++---
 .../llvm/ProfileData/InstrProfReader.h        |  14 +--
 .../llvm/ProfileData/InstrProfWriter.h        |   4 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  | 110 +++---------------
 .../Coverage/CoverageMappingReader.cpp        |  40 +++----
 llvm/lib/ProfileData/InstrProf.cpp            |   6 +-
 llvm/lib/ProfileData/InstrProfReader.cpp      |  12 +-
 llvm/lib/ProfileData/InstrProfWriter.cpp      |  10 +-
 .../universal_bin_wrapping_archives.test      |   2 +-
 llvm/tools/llvm-cov/CodeCoverage.cpp          |  10 +-
 llvm/tools/llvm-cov/CoverageViewOptions.h     |   1 +
 13 files changed, 100 insertions(+), 170 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index a91bbde99066d..cb3b7c60ba981 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -1031,7 +1031,7 @@ class CoverageMapping {
     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
     std::optional<std::reference_wrapper<IndexedInstrProfReader>>
         &ProfileReader,
-    CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename = "", bool ShowArchExecutables = false);
+    CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename = "", bool ShowArchExecutables = false, bool MergeBinaryCoverage = false);
   
   static Error loadFromReaders(
     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
@@ -1046,13 +1046,13 @@ class CoverageMapping {
                    &ProfileReader,
                CoverageMapping &Coverage, bool &DataFound,
                SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr, StringRef ObjectFilename = "", 
-                bool ShowArchExecutables = false);
+                bool ShowArchExecutables = false, bool MergeBinaryCoverage = false);
 
   /// Add a function record corresponding to \p Record.
   Error loadFunctionRecord(
       const CoverageMappingRecord &Record,
       const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
-          &ProfileReader, StringRef ObjectFilename = "", bool ShowArchExecutables = false);
+          &ProfileReader, StringRef ObjectFilename = "", bool ShowArchExecutables = false, bool MergeBinaryCoverage = false);
   
   Error loadFunctionRecord(const CoverageMappingRecord &Record, 
     const std::optional<std::reference_wrapper<IndexedInstrProfReader>> &ProfileReader, 
@@ -1090,7 +1090,7 @@ class CoverageMapping {
        std::optional<StringRef> ProfileFilename, vfs::FileSystem &FS,
        ArrayRef<StringRef> Arches = {}, StringRef CompilationDir = "",
        const object::BuildIDFetcher *BIDFetcher = nullptr,
-       bool CheckBinaryIDs = false, bool ShowArchExecutables = false);
+       bool CheckBinaryIDs = false, bool ShowArchExecutables = false, bool MergeBinaryCoverage = false);
 
   /// The number of functions that couldn't have their profiles mapped.
   ///
@@ -1115,7 +1115,7 @@ class CoverageMapping {
   /// The given filename must be the name as recorded in the coverage
   /// information. That is, only names returned from getUniqueSourceFiles will
   /// yield a result.
-  LLVM_ABI CoverageData getCoverageForFile(StringRef Filename, bool ShowArchExecutables = false) const;
+  LLVM_ABI CoverageData getCoverageForFile(StringRef Filename, bool ShowArchExecutables = false, bool MergeBinaryCoverage = false) const;
 
   /// Get the coverage for a particular function.
   LLVM_ABI CoverageData
@@ -1280,9 +1280,9 @@ uint64_t getFuncNameRef(const FuncRecordTy *Record) {
 /// a hash.
 template <class FuncRecordTy, llvm::endianness Endian>
 Error getFuncNameViaRef(const FuncRecordTy *Record,
-                        InstrProfSymtab &ProfileNames, StringRef &FuncName, StringRef Arch = "") {
+                        InstrProfSymtab &ProfileNames, StringRef &FuncName, StringRef ObjectFilename = "") {
   uint64_t NameRef = getFuncNameRef<FuncRecordTy, Endian>(Record);
-  ProfileNames.setArchitecture(Arch.str());
+  ProfileNames.setObjectFilename(ObjectFilename);
   FuncName = ProfileNames.getFuncOrVarName(NameRef);
   return Error::success();
 }
@@ -1425,9 +1425,9 @@ struct CovMapFunctionRecordV3 {
   }
 
   template <llvm::endianness Endian>
-  Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName, StringRef Arch = "") const {
+  Error getFuncName(InstrProfSymtab &ProfileNames, StringRef &FuncName, StringRef ObjectFilename = "") const {
     return accessors::getFuncNameViaRef<ThisT, Endian>(this, ProfileNames,
-                                                       FuncName, Arch);
+                                                       FuncName, ObjectFilename);
   }
 
   /// Get the filename set reference.
diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
index 7cf09e29f2145..45f2f86dc75a3 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h
@@ -40,11 +40,16 @@ struct CoverageMappingRecord {
   ArrayRef<CounterExpression> Expressions;
   ArrayRef<CounterMappingRegion> MappingRegions;
   StringRef Arch;
+  StringRef ObjectFilename;
 
   const StringRef &getArchitecture() const { return Arch; }
   void setArchitecture(StringRef NewArch){
     Arch = StringRef(NewArch);
   }
+  const StringRef &getObjectFilename() const { return ObjectFilename; }
+  void setObjectFilename(StringRef ObjectFilename){
+    this->ObjectFilename = StringRef(ObjectFilename);
+  }
 };
 
 /// A file format agnostic iterator over coverage mapping data.
@@ -223,14 +228,14 @@ class LLVM_ABI BinaryCoverageReader : public CoverageMappingReader {
   create(MemoryBufferRef ObjectBuffer, StringRef Arch,
          SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
          StringRef CompilationDir = "",
-         SmallVectorImpl<object::BuildIDRef> *BinaryIDs = nullptr);
+         SmallVectorImpl<object::BuildIDRef> *BinaryIDs = nullptr, StringRef ObjectFilename = "");
 
   static Expected<std::unique_ptr<BinaryCoverageReader>>
   createCoverageReaderFromBuffer(
       StringRef Coverage, FuncRecordsStorage &&FuncRecords,
       CoverageMapCopyStorage &&CoverageMap,
       std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress,
-      llvm::endianness Endian, StringRef CompilationDir = "", StringRef Arch = "");
+      llvm::endianness Endian, StringRef CompilationDir = "", StringRef Arch = "", StringRef ObjectFilename = "");
 
   Error readNextRecord(CoverageMappingRecord &Record) override;
 };
diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index 21a58ce1f14ce..c41c8323bf5fb 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -369,7 +369,7 @@ LLVM_ABI bool needsComdatForCounter(const GlobalObject &GV, const Module &M);
 /// InstrProf.h:getInstrProfNameSeparator). This method decodes the string and
 /// calls `NameCallback` for each substring.
 LLVM_ABI Error readAndDecodeStrings(
-    StringRef NameStrings, std::function<Error(StringRef)> NameCallback, StringRef Architecture = "");
+    StringRef NameStrings, std::function<Error(StringRef)> NameCallback, StringRef ObjectFilename = "");
 
 
 /// An enum describing the attributes of an instrumented profile.
@@ -513,12 +513,14 @@ class InstrProfSymtab {
   // suffixes that begins with "." except ".__uniq." are stripped.
   // FIXME: Unify this with `FunctionSamples::getCanonicalFnName`.
   LLVM_ABI static StringRef getCanonicalName(StringRef PGOName);
-
   //ANDRES Function
+  StringRef getObjectFilename() {return ObjectFilename;}
+  void setObjectFilename(StringRef ObjectFilename) {this->ObjectFilename = ObjectFilename;}
   StringRef getArchitecture() {return Architecture;}
-  void setArchitecture(StringRef Arch) {Architecture = Arch;}
+  void setArchitecture(StringRef Architecture) {this->Architecture = Architecture;}
   //ANDRES Function
 private:
+  StringRef ObjectFilename;
   StringRef Architecture;
   using AddrIntervalMap =
       IntervalMap<uint64_t, uint64_t, 4, IntervalMapHalfOpenInfo<uint64_t>>;
@@ -643,11 +645,12 @@ class InstrProfSymtab {
     // won't have duplicated entries in the first place.
 
     uint64_t HashValue = IndexedInstrProf::ComputeHash(SymbolName);
-    llvm::StringRef HashRef(SymbolName);
-    if(!Architecture.empty()){
-      std::string HashStr = std::to_string(HashValue);
-      std::string CombinedStr = HashStr + ":" + Architecture.str();
-      HashRef = CombinedStr;
+    std::string HashStr(std::to_string(HashValue));
+    // llvm::errs() << "HELLLOOOOOOOOO" << "\n";
+    if(!ObjectFilename.empty()){
+      std::string CombinedStr = HashStr + ":" + ObjectFilename.str();
+      llvm::errs() << CombinedStr << "\n";
+      StringRef HashRef = CombinedStr;
       HashValue = IndexedInstrProf::ComputeHash(HashRef);
     }
     auto Ins = NameTab.insert(SymbolName);
@@ -655,8 +658,6 @@ class InstrProfSymtab {
       MD5NameMap.push_back(std::make_pair(HashValue /*IndexedInstrProf::ComputeHash(HashRef)*/, Ins.first->getKey()));
       Sorted = false;
     }
-    for(int I = 0; I < int(MD5NameMap.size()); ++I){
-    }
     return Error::success();
   }
 
@@ -784,19 +785,20 @@ StringRef InstrProfSymtab::getFuncOrVarNameIfDefined(uint64_t MD5Hash) {
 StringRef InstrProfSymtab::getFuncOrVarName(uint64_t MD5Hash) {
   finalizeSymtab();
   std::string TempMD5HashStr = std::to_string(MD5Hash);
-  if(!Architecture.empty()){
-    std::string CombinedHashStr = TempMD5HashStr + ":" + Architecture.str();
+  if(!ObjectFilename.empty()){
+    std::string CombinedHashStr = TempMD5HashStr + ":" + ObjectFilename.str();
     llvm::StringRef CombinedHashRef(CombinedHashStr);
     MD5Hash = IndexedInstrProf::ComputeHash(CombinedHashRef);
   }
   auto Result = llvm::lower_bound(MD5NameMap, MD5Hash, [](const std::pair<uint64_t, StringRef> &LHS, uint64_t RHS) { return LHS.first < RHS; });
 
-  // for(auto name : MD5NameMap){
-  //   llvm::errs() << "Function Name " << name.second  << " Result->first: " << name.first << "\n";
-  // }
-  // llvm::errs() << "Function Name " << Result->second  << " Result->first: " << Result->first << " vs. " << MD5Hash << "\n";
+  for(auto name : MD5NameMap){
+    llvm::errs() << "Function Name " << name.second  << " Result->first: " << name.first << "\n";
+  }
+  llvm::errs() << "Function Name " << Result->second  << " Result->first: " << Result->first << " vs. " << MD5Hash << "\n";
   if (Result != MD5NameMap.end() && Result->first == MD5Hash)
     return Result->second;
+  llvm::errs() << "MISMATCH HERE" << "\n";
   return StringRef();
 }
 
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index e2ed1cb8cf399..db80731037887 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -162,8 +162,8 @@ class InstrProfReader {
   LLVM_ABI void accumulateCounts(CountSumOrPercent &Sum, bool IsCS);
 
 protected:
-  //ANDRES Storing Architecture Information as a string
-  std::string Architecture;
+  //ANDRES Storing ObjectFilename Information as a string
+  std::string ObjectFilename;
 
   std::unique_ptr<InstrProfSymtab> Symtab;
   /// A list of temporal profile traces.
@@ -213,7 +213,7 @@ class InstrProfReader {
       const object::BuildIDFetcher *BIDFetcher = nullptr,
       const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind =
           InstrProfCorrelator::ProfCorrelatorKind::NONE,
-      std::function<void(Error)> Warn = nullptr, StringRef Architecture = "");
+      std::function<void(Error)> Warn = nullptr, StringRef ObjectFilename = "");
 
   LLVM_ABI static Expected<std::unique_ptr<InstrProfReader>> create(
       std::unique_ptr<MemoryBuffer> Buffer,
@@ -221,11 +221,11 @@ class InstrProfReader {
       const object::BuildIDFetcher *BIDFetcher = nullptr,
       const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind =
           InstrProfCorrelator::ProfCorrelatorKind::NONE,
-      std::function<void(Error)> Warn = nullptr, StringRef Architecture = "");
+      std::function<void(Error)> Warn = nullptr, StringRef ObjectFilename = "");
   
-  StringRef getArchitecture() {return Architecture;}
+  StringRef getObjectFilename() {return ObjectFilename;}
 
-  void setArchitecture(StringRef Arch) {Architecture = Arch;}
+  void setObjectFilename(StringRef ObjectFilename) {this->ObjectFilename = ObjectFilename;}
   /// \param Weight for raw profiles use this as the temporal profile trace
   ///               weight
   /// \returns a list of temporal profile traces.
@@ -877,7 +877,7 @@ class LLVM_ABI IndexedInstrProfReader : public InstrProfReader {
 
   static Expected<std::unique_ptr<IndexedInstrProfReader>>
   create(const Twine &Path, vfs::FileSystem &FS,
-        const std::string &Arch, const Twine &RemappingPath = "");
+        const std::string &ObjectFilename, const Twine &RemappingPath = "");
 
   static Expected<std::unique_ptr<IndexedInstrProfReader>>
   create(std::unique_ptr<MemoryBuffer> Buffer,
diff --git a/llvm/include/llvm/ProfileData/InstrProfWriter.h b/llvm/include/llvm/ProfileData/InstrProfWriter.h
index 77c93c537f468..5ba07991f0f48 100644
--- a/llvm/include/llvm/ProfileData/InstrProfWriter.h
+++ b/llvm/include/llvm/ProfileData/InstrProfWriter.h
@@ -113,7 +113,7 @@ class InstrProfWriter {
   /// for this function and the hash and number of counts match, each counter is
   /// summed. Optionally scale counts by \p Weight.
   LLVM_ABI void addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
-                          function_ref<void(Error)> Warn, StringRef Architecture = "");
+                          function_ref<void(Error)> Warn, StringRef ObjectFilename = "");
   // void addRecord(NamedInstrProfRecord &&I, uint64_t Weight, function_ref<void(Error)> Warn);
   void addRecord(NamedInstrProfRecord &&I, function_ref<void(Error)> Warn) {
     addRecord(std::move(I), 1, Warn);
@@ -225,7 +225,7 @@ class InstrProfWriter {
 
 private:
   void addRecord(StringRef Name, uint64_t Hash, InstrProfRecord &&I,
-                 uint64_t Weight, function_ref<void(Error)> Warn, StringRef Architecture = "");
+                 uint64_t Weight, function_ref<void(Error)> Warn, StringRef ObjectFilename = "");
   bool shouldEncodeData(const ProfilingData &PD);
   /// Add \p Trace using reservoir sampling.
   void addTemporalProfileTrace(TemporalProfTraceTy Trace);
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index 6248c202ec6ff..cac35b29e8aec 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -979,7 +979,7 @@ class MCDCDecisionRecorder {
 Error CoverageMapping::loadFunctionRecord(
     const CoverageMappingRecord &Record,
     const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
-        &ProfileReader, StringRef ObjectFilename, bool ShowArchExecutables) {
+        &ProfileReader, StringRef ObjectFilename, bool ShowArchExecutables, bool MergeBinaryCoverage) {
   StringRef OrigFuncName = Record.FunctionName;
   if (OrigFuncName.empty())
     return make_error<CoverageMapError>(coveragemap_error::malformed,
@@ -993,12 +993,11 @@ Error CoverageMapping::loadFunctionRecord(
   CounterMappingContext Ctx(Record.Expressions);
 
   uint64_t FuncArchHash = Record.FunctionHash;
-  if(!Arch.empty()){
+  if(!ObjectFilename.empty() && MergeBinaryCoverage){
     std::string HashStr = std::to_string(Record.FunctionHash) + ":" + ObjectFilename.str();
     llvm::StringRef HashRef(HashStr);
     FuncArchHash = IndexedInstrProf::ComputeHash(HashRef);
   }
-
   std::vector<uint64_t> Counts;
   if (ProfileReader) {
     if (Error E = ProfileReader.value().get().getFunctionCounts(Record.FunctionName, FuncArchHash, Counts)) {
@@ -1103,20 +1102,15 @@ Error CoverageMapping::loadFunctionRecord(
     Function.pushMCDCRecord(std::move(*Record));
   }
 
-  //CHANGES MADE HERE
   auto FilenamesHash = hash_combine_range(Record.Filenames);
   std::string HashStr = OrigFuncName.str();
   if(ShowArchExecutables){
     HashStr += ":" + Arch.str();
   }else{
-    //THIS ALGORITHM NEEDS TO BE FIXED!!!
     auto LogicalFuncKey = std::make_pair(FilenamesHash, hash_value(OrigFuncName));
     auto It = RecordIndices.find(LogicalFuncKey);
-
     if (It != RecordIndices.end()) {
       auto &ExistingFunction = Functions[It->second];
-
-
       // Create a map of existing regions for efficient lookup.
       // The key uniquely identifies the source region.
       using RegionKey = std::tuple<unsigned, unsigned, unsigned, unsigned, unsigned>;
@@ -1127,11 +1121,9 @@ Error CoverageMapping::loadFunctionRecord(
                          ExistingRegion.ColumnEnd};
         ExistingRegionsMap[Key] = &ExistingRegion;
       }
-
       for (auto NewRegion : Function.CountedRegions) {
         AllFunctionRegions[It->second].CountedRegions.push_back(NewRegion);
       }
-
       // Merge the new regions into the existing function's regions.
       for (const auto &NewRegion : Function.CountedRegions) {
         RegionKey Key = {NewRegion.FileID, NewRegion.LineStart,
@@ -1141,14 +1133,8 @@ Error CoverageMapping::loadFunctionRecord(
         if (MapIt != ExistingRegionsMap.end()) {
           // Region already exists, merge counts by taking the max.
           CountedRegion *ExistingRegion = MapIt->second;
-          // llvm::errs() << "EXECUTION COUNTS BEFORE: " +  to_string(ExistingRegion->ExecutionCount) << "\n";
-          // llvm::errs() << "(" << ExistingRegion->LineStart << ", " << ExistingRegion->LineEnd << ")" << "\n";
           ExistingRegion->ExecutionCount += NewRegion.ExecutionCount;
-          // llvm::errs() << "EXECUTION COUNTS AFTER: " +  to_string(ExistingRegion->ExecutionCount) << "\n";
-          // DebugCount++;
         } else {
-          // llvm::errs() << "ENTERS ELSE STATEMENT HERE" << "\n";
-          // llvm::errs() << "(" << NewRegion.LineStart << ", " << NewRegion.LineEnd << ")" << "\n";
           ExistingFunction.CountedRegions.push_back(NewRegion);
         }
       }
@@ -1157,18 +1143,8 @@ Error CoverageMapping::loadFunctionRecord(
       // The logic below this block needs to be adjusted to handle this.
       return Error::success();
     }
-    // llvm::errs() << "ENTERS ELSE STATEMENT HERE" << "\n";
     RecordIndices.insert({LogicalFuncKey, Functions.size()});
-    //THIS ALGORITHM NEEDS TO BE FIXED!!!
   }
-  //CHANGES MADE HERE
-
-  // if(DebugCount == 29){
-  //   llvm::errs() << "ENTERS ELSE STATEMENT HERE" << "\n";
-  // }
-
-
-
   // Don't create records for (filenames, function) pairs we've already seen.
   StringRef Hash(HashStr);
   if (!RecordProvenance[FilenamesHash].insert(hash_value(Hash)).second){
@@ -1222,9 +1198,9 @@ Error CoverageMapping::loadFromReaders(
     ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
     std::optional<std::reference_wrapper<IndexedInstrProfReader>>
         &ProfileReader,
-    CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename, bool ShowArchExecutables) {
+    CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename, bool ShowArchExecutables, bool MergeBinaryCoverage) {
   
-  Coverage.setArchitecture(Arch);
+  // Coverage.setArchitecture(Arch);
   assert(!Coverage.SingleByteCoverage || !ProfileReader ||
          *Coverage.SingleByteCoverage ==
              ProfileReader.value().get().hasSingleByteCoverage());
@@ -1235,7 +1211,7 @@ Error CoverageMapping::loadFromReaders(
       if (Error E = RecordOrErr.takeError())
         return E;
       const auto &Record = *RecordOrErr;
-      if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader, ObjectFilename, ShowArchExecutables))
+      if (Error E = Coverage.loadFunctionRecord(Record, ProfileReader, ObjectFilename, ShowArchExecutables, MergeBinaryCoverage))
         return E;
     }
   }
@@ -1266,7 +1242,7 @@ Error CoverageMapping::loadFromFile(
     std::optional<std::reference_wrapper<IndexedInstrProfReader>>
         &ProfileReader,
     CoverageMapping &Coverage, bool &DataFound,
-    SmallVectorImpl<object::BuildID> *FoundBinaryIDs, StringRef ObjectFilename, bool ShowArchExecutables) {
+    SmallVectorImpl<object::BuildID> *FoundBinaryIDs, StringRef ObjectFilename, bool ShowArchExecutables, bool MergeBinaryCoverage) {
   auto CovMappingBufOrErr = MemoryBuffer::getFileOrSTDIN(
       Filename, /*IsText=*/false, /*RequiresNullTerminator=*/false);
   if (std::error_code EC = CovMappingBufOrErr.getError())
@@ -1280,7 +1256,7 @@ Error CoverageMapping::loadFromFile(
   SmallVector<object::BuildIDRef> BinaryIDs;
   auto CoverageReadersOrErr = BinaryCoverageReader::create(
       CovMappingBufRef, Arch, Buffers, CompilationDir,
-      FoundBinaryIDs ? &BinaryIDs : nullptr);
+      FoundBinaryIDs ? &BinaryIDs : nullptr, ObjectFilename);
   if (Error E = CoverageReadersOrErr.takeError()) {
     E = handleMaybeNoDataFoundError(std::move(E));
     if (E)
@@ -1298,7 +1274,7 @@ Error CoverageMapping::loadFromFile(
                        }));
   }
   DataFound |= !Readers.empty();
-  if (Error E = loadFromReaders(Readers, ProfileReader, Coverage, Arch, ObjectFilename, ShowArchExecutables))
+  if (Error E = loadFromReaders(Readers, ProfileReader, Coverage, Arch, ObjectFilename, ShowArchExecutables, MergeBinaryCoverage))
     return createFileError(Filename, std::move(E));
   return Error::success();
 }
@@ -1307,7 +1283,7 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
     ArrayRef<StringRef> ObjectFilenames,
     std::optional<StringRef> ProfileFilename, vfs::FileSystem &FS,
     ArrayRef<StringRef> Arches, StringRef CompilationDir,
-    const object::BuildIDFetcher *BIDFetcher, bool CheckBinaryIDs, bool ShowArchExecutables) {
+    const object::BuildIDFetcher *BIDFetcher, bool CheckBinaryIDs, bool ShowArchExecutables, bool MergeBinaryCoverage) {
   std::unique_ptr<IndexedInstrProfReader> ProfileReader;
   if (ProfileFilename) {
     auto ProfileReaderOrErr =
@@ -1339,8 +1315,8 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
   for (const auto &File : llvm::enumerate(ObjectFilenames)) {
     if (Error E = loadFromFile(File.value(), GetArch(File.index()),
                                CompilationDir, ProfileReaderRef, *Coverage,
-                               DataFound, &FoundBinaryIDs, ObjectFilenames[File.index()], 
-                               ShowArchExecutables))
+                               DataFound, &FoundBinaryIDs, MergeBinaryCoverage ? ObjectFilenames[File.index()] : "", 
+                               ShowArchExecutables, MergeBinaryCoverage))
       return std::move(E);
   }
 
@@ -1632,59 +1608,6 @@ class SegmentBuilder {
 
     sortNestedRegions(Regions);
 
-    // // This map is used to efficiently check for the existence of a specific region
-    // // from a specific binary, which is the purpose of the innermost loop in the
-    // // original code.
-    // // Key: A tuple uniquely identifying a region's location and its binary of origin.
-    // // Value: A boolean indicating if the region is NOT a SkippedRegion.
-    // using RegionKey = std::tuple<LineColPair, LineColPair, StringRef>;
-    // std::map<RegionKey, bool> RegionExistenceMap;
-    // for (const auto &R : Regions) {
-    //   RegionKey Key = {R.startLoc(), R.endLoc(), R.ObjectFilename};
-    //   // Only insert if it's a more "valid" region than what might already be there.
-    //   if (R.Kind != CounterMappingRegion::SkippedRegion)
-    //     RegionExistenceMap[Key] = true;
-    //   else
-    //     RegionExistenceMap.try_emplace(Key, false);
-    // }
-
-    // for (auto &I : Regions) {
-    //   // We are only interested in patching SkippedRegions.
-    //   if (I.Kind != CounterMappingRegion::SkippedRegion)
-    //     continue;
-
-    //   for (auto &J : Regions) {
-    //     // Find a non-skipped region 'J' from a different binary that contains 'I'.
-    //     if (I.ObjectFilename == J.ObjectFilename ||
-    //         J.Kind == CounterMappingRegion::SkippedRegion ||
-    //         !(I.startLoc() >= J.startLoc() && I.endLoc() <= J.endLoc())) {
-    //       continue;
-    //     }
-
-    //     // Check if a non-skipped region already exists at I's exact location
-    //     // coming from J's binary. This replaces the O(N) inner loop.
-    //     RegionKey KeyToFind = {I.startLoc(), I.endLoc(), J.ObjectFilename};
-    //     auto It = RegionExistenceMap.find(KeyToFind);
-
-    //     // If no region from J's binary exists at I's location, or if it does
-    //     // but it's a SkippedRegion, we can patch I with J's data.
-    //     if (It == RegionExistenceMap.end() || It->second == false) {
-    //       I.Kind = J.Kind;
-    //       I.ExecutionCount = J.ExecutionCount;
-    //       // We found a patch, no need to check other containing regions.
-    //       break;
-    //     }
-    //   }
-    // }
-
-    // llvm::errs() << "START HERE" << "\n";
-    // for(auto *I = Regions.begin(); I != Regions.end(); ++I){
-    //   llvm::errs() << "(" << to_string(I->startLoc().first) << ", " << to_string(I->endLoc().first) << ")" << "\n";
-    //   llvm::errs() << "Execution Count: " << I->ExecutionCount << "\n";
-    // }
-    // llvm::errs() << "END HERE" << "\n";
-
-
     for(auto *I = Regions.begin(); I != Regions.end(); ++I){
       bool FoundMatchInOtherBinary = false;
       for(auto *J = I + 1; J != Regions.end(); ++J){
@@ -1706,13 +1629,6 @@ class SegmentBuilder {
         }
       }
     }
-
-    // llvm::errs() << "START HERE" << "\n";
-    // for(auto *I = Regions.begin(); I != Regions.end(); ++I){
-    //   llvm::errs() << "(" << to_string(I->startLoc().first) << ", " << to_string(I->endLoc().first) << ")" << "\n";
-    //   llvm::errs() << "Execution Count: " << I->ExecutionCount << "\n";
-    // }
-    // llvm::errs() << "END HERE" << "\n";
     
 
     ArrayRef<CountedRegion> CombinedRegions = combineRegions(Regions);
@@ -1800,7 +1716,7 @@ static bool isExpansion(const CountedRegion &R, unsigned FileID) {
   return R.Kind == CounterMappingRegion::ExpansionRegion && R.FileID == FileID;
 }
 
-CoverageData CoverageMapping::getCoverageForFile(StringRef Filename, bool ShowArchExecutables) const {
+CoverageData CoverageMapping::getCoverageForFile(StringRef Filename, bool ShowArchExecutables, bool MergeBinaryCoverage) const {
   assert(SingleByteCoverage);
   CoverageData FileCoverage(*SingleByteCoverage, Filename);
   std::vector<CountedRegion> Regions;
@@ -1819,7 +1735,7 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename, bool ShowAr
   // ArrayRef<unsigned> RecordIndices =
   //     getImpreciseRecordIndicesForFilename(Filename);
   for (unsigned RecordIndex : RecordIndices) {
-    const FunctionRecord &Function = ShowArchExecutables ? Functions[RecordIndex] : AllFunctionRegions[RecordIndex];
+    const FunctionRecord &Function = !MergeBinaryCoverage ? Functions[RecordIndex] : AllFunctionRegions[RecordIndex];
     auto MainFileID = findMainViewFileID(Filename, Function);
     auto FileIDs = gatherFileIDs(Filename, Function);
     for (const auto &CR : Function.CountedRegions)
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
index 1c79ffab66b05..aaf11e451cc26 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -578,13 +578,13 @@ struct CovMapFuncRecordReader {
   readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
                       std::optional<FilenameRange> OutOfLineFileRange,
                       const char *OutOfLineMappingBuf,
-                      const char *OutOfLineMappingBufEnd, StringRef Arch = "") = 0;
+                      const char *OutOfLineMappingBufEnd, StringRef Arch = "", StringRef ObjectFilename = "") = 0;
 
   template <class IntPtrT, llvm::endianness Endian>
   static Expected<std::unique_ptr<CovMapFuncRecordReader>>
   get(CovMapVersion Version, InstrProfSymtab &P,
       std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
-      std::vector<std::string> &F, StringRef Arch = "");
+      std::vector<std::string> &F, StringRef Arch = "", StringRef ObjectFilename = "");
 };
 
 // A class for reading coverage mapping function records for a module.
@@ -614,7 +614,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
   // not used in the corresponding translation unit.
   Error insertFunctionRecordIfNeeded(const FuncRecordType *CFR,
                                      StringRef Mapping,
-                                     FilenameRange FileRange, StringRef Arch = "") {
+                                     FilenameRange FileRange, StringRef Arch = "", StringRef ObjectFilename = "") {
     ++CovMapNumRecords;
     uint64_t FuncHash = CFR->template getFuncHash<Endian>();
     NameRefType NameRef = CFR->template getFuncNameRef<Endian>();
@@ -622,7 +622,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
         FunctionRecords.insert(std::make_pair(NameRef, Records.size()));
     if (InsertResult.second) {
       StringRef FuncName;
-      if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName, Arch))
+      if (Error Err = CFR->template getFuncName<Endian>(ProfileNames, FuncName, ObjectFilename))
         return Err;
       if (FuncName.empty())
         return make_error<InstrProfError>(instrprof_error::malformed,
@@ -761,7 +761,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
   Error readFunctionRecords(const char *FuncRecBuf, const char *FuncRecBufEnd,
                             std::optional<FilenameRange> OutOfLineFileRange,
                             const char *OutOfLineMappingBuf,
-                            const char *OutOfLineMappingBufEnd, StringRef Arch = "") override {
+                            const char *OutOfLineMappingBufEnd, StringRef Arch = "", StringRef ObjectFilename = "") override {
     auto CFR = reinterpret_cast<const FuncRecordType *>(FuncRecBuf);
     while ((const char *)CFR < FuncRecBufEnd) {
       // Validate the length of the coverage mapping for this function.
@@ -800,7 +800,7 @@ class VersionedCovMapFuncRecordReader : public CovMapFuncRecordReader {
           return make_error<CoverageMapError>(
               coveragemap_error::malformed,
               "coverage mapping data is larger than buffer size");
-        if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange, Arch))
+        if (Error Err = insertFunctionRecordIfNeeded(CFR, Mapping, *FileRange, Arch, ObjectFilename))
           return Err;
       }
 
@@ -816,7 +816,7 @@ template <class IntPtrT, llvm::endianness Endian>
 Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
     CovMapVersion Version, InstrProfSymtab &P,
     std::vector<BinaryCoverageReader::ProfileMappingRecord> &R, StringRef D,
-    std::vector<std::string> &F, StringRef Arch) {
+    std::vector<std::string> &F, StringRef Arch, StringRef ObjectFilename) {
   using namespace coverage;
 
   switch (Version) {
@@ -829,8 +829,8 @@ Expected<std::unique_ptr<CovMapFuncRecordReader>> CovMapFuncRecordReader::get(
   case CovMapVersion::Version5:
   case CovMapVersion::Version6:
   case CovMapVersion::Version7:
+    P.setObjectFilename(ObjectFilename);
     // Decompress the name data.
-    P.setArchitecture(Arch.str());
     if (Error E = P.create(P.getNameData()))
       return std::move(E);
     if (Version == CovMapVersion::Version2)
@@ -859,7 +859,7 @@ template <typename T, llvm::endianness Endian>
 static Error readCoverageMappingData(
     InstrProfSymtab &ProfileNames, StringRef CovMap, StringRef FuncRecords,
     std::vector<BinaryCoverageReader::ProfileMappingRecord> &Records,
-    StringRef CompilationDir, std::vector<std::string> &Filenames, StringRef Arch = "") {
+    StringRef CompilationDir, std::vector<std::string> &Filenames, StringRef Arch = "", StringRef ObjectFilename = "") {
   using namespace coverage;
 
   // Read the records in the coverage data section.
@@ -870,7 +870,7 @@ static Error readCoverageMappingData(
     return make_error<CoverageMapError>(coveragemap_error::unsupported_version);
   Expected<std::unique_ptr<CovMapFuncRecordReader>> ReaderExpected =
       CovMapFuncRecordReader::get<T, Endian>(Version, ProfileNames, Records,
-                                             CompilationDir, Filenames, Arch);
+                                             CompilationDir, Filenames, Arch, ObjectFilename);
   if (Error E = ReaderExpected.takeError())
     return E;
   auto Reader = std::move(ReaderExpected.get());
@@ -894,7 +894,7 @@ static Error readCoverageMappingData(
   // the records from their dedicated section.
   if (Version >= CovMapVersion::Version4)
     return Reader->readFunctionRecords(FuncRecBuf, FuncRecBufEnd, std::nullopt,
-                                       nullptr, nullptr, Arch);
+                                       nullptr, nullptr, Arch, ObjectFilename);
   return Error::success();
 }
 
@@ -903,7 +903,7 @@ BinaryCoverageReader::createCoverageReaderFromBuffer(
     StringRef Coverage, FuncRecordsStorage &&FuncRecords,
     CoverageMapCopyStorage &&CoverageMap,
     std::unique_ptr<InstrProfSymtab> ProfileNamesPtr, uint8_t BytesInAddress,
-    llvm::endianness Endian, StringRef CompilationDir, StringRef Arch) {
+    llvm::endianness Endian, StringRef CompilationDir, StringRef Arch, StringRef ObjectFilename) {
   if (ProfileNamesPtr == nullptr)
     return make_error<CoverageMapError>(coveragemap_error::malformed,
                                         "Caller must provide ProfileNames");
@@ -915,22 +915,22 @@ BinaryCoverageReader::createCoverageReaderFromBuffer(
   if (BytesInAddress == 4 && Endian == llvm::endianness::little) {
     if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::little>(
             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
-            CompilationDir, Reader->Filenames, Arch))
+            CompilationDir, Reader->Filenames, Arch, ObjectFilename))
       return std::move(E);
   } else if (BytesInAddress == 4 && Endian == llvm::endianness::big) {
     if (Error E = readCoverageMappingData<uint32_t, llvm::endianness::big>(
             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
-            CompilationDir, Reader->Filenames, Arch))
+            CompilationDir, Reader->Filenames, Arch, ObjectFilename))
       return std::move(E);
   } else if (BytesInAddress == 8 && Endian == llvm::endianness::little) {
     if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::little>(
             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
-            CompilationDir, Reader->Filenames, Arch))
+            CompilationDir, Reader->Filenames, Arch, ObjectFilename))
       return std::move(E);
   } else if (BytesInAddress == 8 && Endian == llvm::endianness::big) {
     if (Error E = readCoverageMappingData<uint64_t, llvm::endianness::big>(
             ProfileNames, Coverage, FuncRecordsRef, Reader->MappingRecords,
-            CompilationDir, Reader->Filenames, Arch))
+            CompilationDir, Reader->Filenames, Arch,ObjectFilename))
       return std::move(E);
   } else
     return make_error<CoverageMapError>(
@@ -1137,7 +1137,7 @@ lookupAllocatableSection(ObjectFile &OF, InstrProfSectKind IPSK) {
 static Expected<std::unique_ptr<BinaryCoverageReader>>
 loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
                  StringRef CompilationDir = "",
-                 object::BuildIDRef *BinaryID = nullptr) {
+                 object::BuildIDRef *BinaryID = nullptr, StringRef ObjectFilename = "") {
   std::unique_ptr<ObjectFile> OF;
   if (auto *Universal = dyn_cast<MachOUniversalBinary>(Bin.get())) {
     // If we have a universal binary, try to look up the object for the
@@ -1250,7 +1250,7 @@ loadBinaryFormat(std::unique_ptr<Binary> Bin, StringRef Arch,
 
   return BinaryCoverageReader::createCoverageReaderFromBuffer(
       CoverageMapping, std::move(FuncRecords), std::move(CoverageMapCopy),
-      std::move(ProfileNames), BytesInAddress, Endian, CompilationDir, Arch);
+      std::move(ProfileNames), BytesInAddress, Endian, CompilationDir, Arch, ObjectFilename);
 }
 
 /// Determine whether \p Arch is invalid or empty, given \p Bin.
@@ -1270,7 +1270,7 @@ Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
 BinaryCoverageReader::create(
     MemoryBufferRef ObjectBuffer, StringRef Arch,
     SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
-    StringRef CompilationDir, SmallVectorImpl<object::BuildIDRef> *BinaryIDs) {
+    StringRef CompilationDir, SmallVectorImpl<object::BuildIDRef> *BinaryIDs, StringRef ObjectFilename) {
   std::vector<std::unique_ptr<BinaryCoverageReader>> Readers;
 
   if (ObjectBuffer.getBuffer().size() > sizeof(TestingFormatMagic)) {
@@ -1350,7 +1350,7 @@ BinaryCoverageReader::create(
 
   object::BuildIDRef BinaryID;
   auto ReaderOrErr = loadBinaryFormat(std::move(Bin), Arch, CompilationDir,
-                                      BinaryIDs ? &BinaryID : nullptr);
+                                      BinaryIDs ? &BinaryID : nullptr, ObjectFilename);
   if (!ReaderOrErr)
     return ReaderOrErr.takeError();
   Readers.push_back(std::move(ReaderOrErr.get()));
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index 8fda78bd26802..404e5177980d6 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -618,7 +618,7 @@ Error InstrProfSymtab::addVTableWithName(GlobalVariable &VTable,
 // }
 
 Error readAndDecodeStrings(StringRef NameStrings,
-                           std::function<Error(StringRef)> NameCallback, StringRef Architecture) {
+                           std::function<Error(StringRef)> NameCallback, StringRef ObjectFilename) {
   const uint8_t *P = NameStrings.bytes_begin();
   const uint8_t *EndP = NameStrings.bytes_end();
   while (P < EndP) {
@@ -660,8 +660,8 @@ Error readAndDecodeStrings(StringRef NameStrings,
 }
 
 Error InstrProfSymtab::create(StringRef NameStrings) {
-  StringRef Architecture = getArchitecture();
-  return readAndDecodeStrings(NameStrings, std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1), Architecture);
+  StringRef ObjectFilename = getObjectFilename();
+  return readAndDecodeStrings(NameStrings, std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1), ObjectFilename);
 }
 
 Error InstrProfSymtab::create(StringRef FuncNameStrings,
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index b8a1397f323b2..d4f70ecb247a0 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -160,20 +160,20 @@ Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create( //STEP 1
     const object::BuildIDFetcher *BIDFetcher,
     const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
     std::function<void(Error)> Warn, 
-    StringRef Architecture) {
+    StringRef ObjectFilename) {
   // Set up the buffer to read.
   auto BufferOrError = setupMemoryBuffer(Path, FS);
   if (Error E = BufferOrError.takeError())
     return std::move(E);
   return InstrProfReader::create(std::move(BufferOrError.get()), Correlator,
-                                 BIDFetcher, BIDFetcherCorrelatorKind, Warn, Architecture);
+                                 BIDFetcher, BIDFetcherCorrelatorKind, Warn, ObjectFilename);
 }
 
 Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
     std::unique_ptr<MemoryBuffer> Buffer, const InstrProfCorrelator *Correlator,
     const object::BuildIDFetcher *BIDFetcher,
     const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
-    std::function<void(Error)> Warn, StringRef Architecture) {
+    std::function<void(Error)> Warn, StringRef ObjectFilename) {
   if (Buffer->getBufferSize() == 0)
     return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
 
@@ -197,7 +197,7 @@ Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
   // Initialize the reader and return the result.
 
   if(Result){
-    Result->setArchitecture(Architecture);
+    Result->setObjectFilename(ObjectFilename);
   }
   if (Error E = initializeReader(*Result))
     return std::move(E);
@@ -228,7 +228,7 @@ IndexedInstrProfReader::create(const Twine &Path, vfs::FileSystem &FS,
 
 Expected<std::unique_ptr<IndexedInstrProfReader>>
 IndexedInstrProfReader::create(const Twine &Path, vfs::FileSystem &FS,
-                               const std::string &Arch, const Twine &RemappingPath) {
+                               const std::string &ObjectFilename, const Twine &RemappingPath) {
   // Set up the buffer to read.
   auto BufferOrError = setupMemoryBuffer(Path, FS);
   if (Error E = BufferOrError.takeError())
@@ -578,7 +578,7 @@ Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
 template <class IntPtrT>
 Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { //STEP 5
   
-  Symtab.setArchitecture(Architecture);
+  Symtab.setObjectFilename(ObjectFilename);
   
   if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart),
                               StringRef(VNamesStart, VNamesEnd - VNamesStart)))
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 4e7cb302afc01..2c18a5c7825ad 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -158,10 +158,10 @@ void InstrProfWriter::setValueProfDataEndianness(llvm::endianness Endianness) {
 void InstrProfWriter::setOutputSparse(bool Sparse) { this->Sparse = Sparse; }
 
 void InstrProfWriter::addRecord(NamedInstrProfRecord &&I, uint64_t Weight,
-                                function_ref<void(Error)> Warn, StringRef Architecture) {
+                                function_ref<void(Error)> Warn, StringRef ObjectFilename) {
   auto Name = I.Name;
   auto Hash = I.Hash;
-  addRecord(Name, Hash, std::move(I), Weight, Warn, Architecture);
+  addRecord(Name, Hash, std::move(I), Weight, Warn, ObjectFilename);
 }
 
 void InstrProfWriter::overlapRecord(NamedInstrProfRecord &&Other,
@@ -252,11 +252,11 @@ StringRef hashSourceFile(llvm::StringRef FilePath) {
 
 void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
                                 InstrProfRecord &&I, uint64_t Weight,
-                                function_ref<void(Error)> Warn, StringRef Architecture) {
+                                function_ref<void(Error)> Warn, StringRef ObjectFilename) {
   auto &ProfileDataMap = FunctionData[Name];
   // StringRef SHAHash = hashSourceFile(Architecture);
-  if(!Architecture.empty()){
-    std::string HashStr = std::to_string(Hash) + ":" + Architecture.str();
+  if(!ObjectFilename.empty()){
+    std::string HashStr = std::to_string(Hash) + ":" + ObjectFilename.str();
     llvm::StringRef HashRef(HashStr);
     Hash = IndexedInstrProf::ComputeHash(HashRef);
   }
diff --git a/llvm/test/tools/llvm-cov/universal_bin_wrapping_archives.test b/llvm/test/tools/llvm-cov/universal_bin_wrapping_archives.test
index 903dae45002ec..342edce47368b 100644
--- a/llvm/test/tools/llvm-cov/universal_bin_wrapping_archives.test
+++ b/llvm/test/tools/llvm-cov/universal_bin_wrapping_archives.test
@@ -4,7 +4,7 @@ MachO universal binaries.
 ---
 Steps to re-generate these files on macOS:
 
-clang -fprofile-instr-generate -fcoverage-mapping -c obj1.c -o obj1_32.o -arch i386
+clang -fprofile-instr-generate -fcoverage-mapping -c obj1.c -o obj1_32.o -arch=i386
 clang -fprofile-instr-generate -fcoverage-mapping -c obj2.c -o obj2_32.o -arch i386
 clang -fprofile-instr-generate -fcoverage-mapping -c obj1.c -o obj1_64.o -arch x86_64
 clang -fprofile-instr-generate -fcoverage-mapping -c obj2.c -o obj2_64.o -arch x86_64
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index 1feb1f8402d38..bc273f554043e 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -397,7 +397,7 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile,
   auto SourceBuffer = getSourceFile(SourceFile);
   if (!SourceBuffer)
     return nullptr;
-  auto FileCoverage = Coverage.getCoverageForFile(SourceFile, ViewOpts.ShowArchExecutables);
+  auto FileCoverage = Coverage.getCoverageForFile(SourceFile, ViewOpts.ShowArchExecutables, ViewOpts.MergeBinaryCoverage);
   if (FileCoverage.empty())
     return nullptr;
 
@@ -488,7 +488,7 @@ std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
   auto CoverageOrErr = CoverageMapping::load(
       ObjectFilenames, PGOFilename, *FS, CoverageArches,
       ViewOpts.CompilationDirectory, BIDFetcher.get(), CheckBinaryIDs, 
-      ViewOpts.ShowArchExecutables);
+      ViewOpts.ShowArchExecutables, ViewOpts.MergeBinaryCoverage);
   if (Error E = CoverageOrErr.takeError()) {
     error("failed to load coverage: " + toString(std::move(E)));
     return nullptr;
@@ -830,6 +830,11 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
     "show-arch-executables",
     cl::desc("Show coverage per architecture and the associated executable slice"),
     cl::init(false));
+  
+  cl::opt<bool> MergeBinaryCoverage(
+    "merge-binary-coverage",
+    cl::desc("Enable merging of coverage profiles from binaries compiled for different architectures"),
+    cl::init(false));
 
   auto commandLineParser = [&, this](int argc, const char **argv) -> int {
     cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
@@ -997,6 +1002,7 @@ int CodeCoverageTool::run(Command Cmd, int argc, const char **argv) {
     ViewOpts.NumThreads = NumThreads;
     ViewOpts.CompilationDirectory = CompilationDirectory;
     ViewOpts.ShowArchExecutables = ShowArchExecutables;
+    ViewOpts.MergeBinaryCoverage = MergeBinaryCoverage;
 
     return 0;
   };
diff --git a/llvm/tools/llvm-cov/CoverageViewOptions.h b/llvm/tools/llvm-cov/CoverageViewOptions.h
index 6129bcfb59757..ec99220558ca2 100644
--- a/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -48,6 +48,7 @@ struct CoverageViewOptions {
   bool SkipBranches;
   bool BinaryCounters;
   bool ShowArchExecutables;
+  bool MergeBinaryCoverage;
   OutputFormat Format;
   BranchOutputType ShowBranches;
   std::string ShowOutputDirectory;

>From d9006f25a1b2dc7a481f0fc62db1dd1dfe5ff70b Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Wed, 30 Jul 2025 09:45:49 -0700
Subject: [PATCH 15/17] commit to push final changes

---
 llvm/include/llvm/ProfileData/InstrProf.h     |  14 +-
 .../llvm/ProfileData/InstrProfReader.h        |   2 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  | 178 +-----------------
 llvm/lib/ProfileData/InstrProf.cpp            |  46 +----
 llvm/lib/ProfileData/InstrProfReader.cpp      |  10 +-
 llvm/lib/ProfileData/InstrProfWriter.cpp      |  55 +-----
 llvm/tools/llvm-profdata/llvm-profdata.cpp    |  62 +-----
 7 files changed, 17 insertions(+), 350 deletions(-)

diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index c41c8323bf5fb..99c3df6a2e834 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -513,12 +513,12 @@ class InstrProfSymtab {
   // suffixes that begins with "." except ".__uniq." are stripped.
   // FIXME: Unify this with `FunctionSamples::getCanonicalFnName`.
   LLVM_ABI static StringRef getCanonicalName(StringRef PGOName);
-  //ANDRES Function
+
   StringRef getObjectFilename() {return ObjectFilename;}
   void setObjectFilename(StringRef ObjectFilename) {this->ObjectFilename = ObjectFilename;}
   StringRef getArchitecture() {return Architecture;}
   void setArchitecture(StringRef Architecture) {this->Architecture = Architecture;}
-  //ANDRES Function
+
 private:
   StringRef ObjectFilename;
   StringRef Architecture;
@@ -646,16 +646,15 @@ class InstrProfSymtab {
 
     uint64_t HashValue = IndexedInstrProf::ComputeHash(SymbolName);
     std::string HashStr(std::to_string(HashValue));
-    // llvm::errs() << "HELLLOOOOOOOOO" << "\n";
+    //if ObjectFilename is not empty from the --object-aware-hashing flag, add ObjectFilename to hash context
     if(!ObjectFilename.empty()){
       std::string CombinedStr = HashStr + ":" + ObjectFilename.str();
-      llvm::errs() << CombinedStr << "\n";
       StringRef HashRef = CombinedStr;
       HashValue = IndexedInstrProf::ComputeHash(HashRef);
     }
     auto Ins = NameTab.insert(SymbolName);
     if (Ins.second) {
-      MD5NameMap.push_back(std::make_pair(HashValue /*IndexedInstrProf::ComputeHash(HashRef)*/, Ins.first->getKey()));
+      MD5NameMap.push_back(std::make_pair(HashValue, Ins.first->getKey()));
       Sorted = false;
     }
     return Error::success();
@@ -792,13 +791,8 @@ StringRef InstrProfSymtab::getFuncOrVarName(uint64_t MD5Hash) {
   }
   auto Result = llvm::lower_bound(MD5NameMap, MD5Hash, [](const std::pair<uint64_t, StringRef> &LHS, uint64_t RHS) { return LHS.first < RHS; });
 
-  for(auto name : MD5NameMap){
-    llvm::errs() << "Function Name " << name.second  << " Result->first: " << name.first << "\n";
-  }
-  llvm::errs() << "Function Name " << Result->second  << " Result->first: " << Result->first << " vs. " << MD5Hash << "\n";
   if (Result != MD5NameMap.end() && Result->first == MD5Hash)
     return Result->second;
-  llvm::errs() << "MISMATCH HERE" << "\n";
   return StringRef();
 }
 
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index db80731037887..230c7e3233e58 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -162,7 +162,7 @@ class InstrProfReader {
   LLVM_ABI void accumulateCounts(CountSumOrPercent &Sum, bool IsCS);
 
 protected:
-  //ANDRES Storing ObjectFilename Information as a string
+  //Storing ObjectFilename Information as a string
   std::string ObjectFilename;
 
   std::unique_ptr<InstrProfSymtab> Symtab;
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index cac35b29e8aec..aaab6081e8bc4 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -825,157 +825,6 @@ class MCDCDecisionRecorder {
 
 } // namespace
 
-// Error CoverageMapping::loadFunctionRecord(
-//     const CoverageMappingRecord &Record,
-//     const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
-//         &ProfileReader, StringRef Arch) {
-//   StringRef OrigFuncName = Record.FunctionName;
-//   if (OrigFuncName.empty())
-//     return make_error<CoverageMapError>(coveragemap_error::malformed,
-//                                         "record function name is empty");
-
-//   if (Record.Filenames.empty())
-//     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName);
-//   else
-//     OrigFuncName = getFuncNameWithoutPrefix(OrigFuncName, Record.Filenames[0]);
-
-//   CounterMappingContext Ctx(Record.Expressions);
-
-//   uint64_t FuncArchHash = Record.FunctionHash;
-//   if(!Arch.empty()){
-//     std::string HashStr = std::to_string(Record.FunctionHash) + ":" + Arch.str();
-//     llvm::StringRef HashRef(HashStr);
-//     FuncArchHash = IndexedInstrProf::ComputeHash(HashRef);
-//   }
-
-//   std::vector<uint64_t> Counts;
-//   if (ProfileReader) {
-//     if (Error E = ProfileReader.value().get().getFunctionCounts(
-//             Record.FunctionName, FuncArchHash, Counts)) {
-//       instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
-//       if (IPE == instrprof_error::hash_mismatch) {
-//         FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
-//                                         FuncArchHash);
-//         return Error::success();
-//       }
-//       if (IPE != instrprof_error::unknown_function)
-//         return make_error<InstrProfError>(IPE);
-//       Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0);
-//     }
-//   } else {
-//     Counts.assign(getMaxCounterID(Ctx, Record) + 1, 0);
-//   }
-//   Ctx.setCounts(Counts);
-
-//   bool IsVersion11 =
-//       ProfileReader && ProfileReader.value().get().getVersion() <
-//                            IndexedInstrProf::ProfVersion::Version12;
-
-//   BitVector Bitmap;
-//   if (ProfileReader) {
-//     if (Error E = ProfileReader.value().get().getFunctionBitmap(
-//             Record.FunctionName, FuncArchHash, Bitmap)) {
-//       instrprof_error IPE = std::get<0>(InstrProfError::take(std::move(E)));
-//       if (IPE == instrprof_error::hash_mismatch) {
-//         FuncHashMismatches.emplace_back(std::string(Record.FunctionName),
-//                                         FuncArchHash);
-//         return Error::success();
-//       }
-//       if (IPE != instrprof_error::unknown_function)
-//         return make_error<InstrProfError>(IPE);
-//       Bitmap = BitVector(getMaxBitmapSize(Record, IsVersion11));
-//     }
-//   } else {
-//     Bitmap = BitVector(getMaxBitmapSize(Record, false));
-//   }
-//   Ctx.setBitmap(std::move(Bitmap));
-
-//   assert(!Record.MappingRegions.empty() && "Function has no regions");
-
-//   // This coverage record is a zero region for a function that's unused in
-//   // some TU, but used in a different TU. Ignore it. The coverage maps from the
-//   // the other TU will either be loaded (providing full region counts) or they
-//   // won't (in which case we don't unintuitively report functions as uncovered
-//   // when they have non-zero counts in the profile).
-//   if (Record.MappingRegions.size() == 1 &&
-//       Record.MappingRegions[0].Count.isZero() && Counts[0] > 0)
-//     return Error::success();
-
-//   MCDCDecisionRecorder MCDCDecisions;
-//   FunctionRecord Function(OrigFuncName, Record.Filenames);
-//   for (const auto &Region : Record.MappingRegions) {
-//     // MCDCDecisionRegion should be handled first since it overlaps with
-//     // others inside.
-//     if (Region.Kind == CounterMappingRegion::MCDCDecisionRegion) {
-//       MCDCDecisions.registerDecision(Region);
-//       continue;
-//     }
-//     Expected<int64_t> ExecutionCount = Ctx.evaluate(Region.Count);
-//     if (auto E = ExecutionCount.takeError()) {
-//       consumeError(std::move(E));
-//       return Error::success();
-//     }
-//     Expected<int64_t> AltExecutionCount = Ctx.evaluate(Region.FalseCount);
-//     if (auto E = AltExecutionCount.takeError()) {
-//       consumeError(std::move(E));
-//       return Error::success();
-//     }
-//     Function.pushRegion(Region, *ExecutionCount, *AltExecutionCount);
-
-//     // Record ExpansionRegion.
-//     if (Region.Kind == CounterMappingRegion::ExpansionRegion) {
-//       MCDCDecisions.recordExpansion(Region);
-//       continue;
-//     }
-
-//     // Do nothing unless MCDCBranchRegion.
-//     if (Region.Kind != CounterMappingRegion::MCDCBranchRegion)
-//       continue;
-
-//     auto Result = MCDCDecisions.processBranch(Region);
-//     if (!Result) // Any Decision doesn't complete.
-//       continue;
-
-//     auto MCDCDecision = Result->first;
-//     auto &MCDCBranches = Result->second;
-
-//     // Since the bitmap identifies the executed test vectors for an MC/DC
-//     // DecisionRegion, all of the information is now available to process.
-//     // This is where the bulk of the MC/DC progressing takes place.
-//     Expected<MCDCRecord> Record =
-//         Ctx.evaluateMCDCRegion(*MCDCDecision, MCDCBranches, IsVersion11);
-//     if (auto E = Record.takeError()) {
-//       consumeError(std::move(E));
-//       return Error::success();
-//     }
-
-//     // Save the MC/DC Record so that it can be visualized later.
-//     Function.pushMCDCRecord(std::move(*Record));
-//   }
-
-//   // Don't create records for (filenames, function) pairs we've already seen.
-//   auto FilenamesHash = hash_combine_range(Record.Filenames);
-//   if (!RecordProvenance[FilenamesHash].insert(hash_value(OrigFuncName)).second)
-//     return Error::success();
-
-//   Functions.push_back(std::move(Function));
-
-//   // Performance optimization: keep track of the indices of the function records
-//   // which correspond to each filename. This can be used to substantially speed
-//   // up queries for coverage info in a file.
-//   unsigned RecordIndex = Functions.size() - 1;
-//   for (StringRef Filename : Record.Filenames) {
-//     auto &RecordIndices = FilenameHash2RecordIndices[hash_value(Filename)];
-//     // Note that there may be duplicates in the filename set for a function
-//     // record, because of e.g. macro expansions in the function in which both
-//     // the macro and the function are defined in the same file.
-//     if (RecordIndices.empty() || RecordIndices.back() != RecordIndex)
-//       RecordIndices.push_back(RecordIndex);
-//   }
-
-//   return Error::success();
-// }
-
 Error CoverageMapping::loadFunctionRecord(
     const CoverageMappingRecord &Record,
     const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
@@ -1200,7 +1049,6 @@ Error CoverageMapping::loadFromReaders(
         &ProfileReader,
     CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename, bool ShowArchExecutables, bool MergeBinaryCoverage) {
   
-  // Coverage.setArchitecture(Arch);
   assert(!Coverage.SingleByteCoverage || !ProfileReader ||
          *Coverage.SingleByteCoverage ==
              ProfileReader.value().get().hasSingleByteCoverage());
@@ -1308,9 +1156,6 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
     return Arches[Idx];
   };
 
-  //I beleive there is an error in this area of code, it's iterating through all arch's of the object files
-  // but its only filling *Coverage with last architecture it gets to
-
   SmallVector<object::BuildID> FoundBinaryIDs;
   for (const auto &File : llvm::enumerate(ObjectFilenames)) {
     if (Error E = loadFromFile(File.value(), GetArch(File.index()),
@@ -1320,9 +1165,6 @@ Expected<std::unique_ptr<CoverageMapping>> CoverageMapping::load(
       return std::move(E);
   }
 
-  //I beleive there is an error in this area of code, it's iterating through all arch's of the object files
-  // but its only filling *Coverage with last architecture it gets to
-
   if (BIDFetcher) {
     std::vector<object::BuildID> ProfileBinaryIDs;
     if (ProfileReader)
@@ -1561,7 +1403,6 @@ class SegmentBuilder {
   }
 
   /// Combine counts of regions which cover the same area.
-  //[(3:12, 10:1), (4:1, 6:7), (6:7, 8:1)]
   static ArrayRef<CountedRegion>
   combineRegions(MutableArrayRef<CountedRegion> Regions) {
     if (Regions.empty())
@@ -1576,8 +1417,6 @@ class SegmentBuilder {
         ++Active;
         if (Active != I){
           *Active = *I;
-          // Active->ExecutionCount = 1;
-          // Active->Kind = CounterMappingRegion::CodeRegion;
         }
         continue;
       }
@@ -1608,6 +1447,9 @@ class SegmentBuilder {
 
     sortNestedRegions(Regions);
 
+    
+    //check to see if a skipped region from executable A is within a CodeRegion from executable B,
+    //promote to CodeRegion if skipped region does not show up on any other executable.
     for(auto *I = Regions.begin(); I != Regions.end(); ++I){
       bool FoundMatchInOtherBinary = false;
       for(auto *J = I + 1; J != Regions.end(); ++J){
@@ -1615,7 +1457,6 @@ class SegmentBuilder {
             J->Kind == CounterMappingRegion::SkippedRegion 
             && I->Kind != CounterMappingRegion::SkippedRegion &&
             J->startLoc() >= I->startLoc() && J->endLoc() <= I->endLoc()){
-          // llvm::errs() << "(" << to_string(J->startLoc().first) << ", " << to_string(J->endLoc().first) << ")" << "\n";
           for(auto *K = J + 1; K != Regions.end(); ++K){
             if(K->ObjectFilename == I->ObjectFilename &&
               J->startLoc() == K->startLoc() && J->endLoc() == K->endLoc()){
@@ -1686,12 +1527,7 @@ static SmallBitVector gatherFileIDs(StringRef SourceFile,
 static std::optional<unsigned>
 findMainViewFileID(const FunctionRecord &Function) {
   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
-  uint64_t counter = 0;
   for (const auto &CR : Function.CountedRegions){
-    // counter++;
-    // if(counter == 245){
-    //   llvm::errs() << counter << "\n";
-    // }
     if (CR.Kind == CounterMappingRegion::ExpansionRegion)
       IsNotExpandedFile[CR.ExpandedFileID] = false;
   }
@@ -1726,14 +1562,6 @@ CoverageData CoverageMapping::getCoverageForFile(StringRef Filename, bool ShowAr
   // DenseSet<CountedRegion> DeDuplicationSet;
   ArrayRef<unsigned> RecordIndices =
       getImpreciseRecordIndicesForFilename(Filename);
-  // for (unsigned RecordIndex : RecordIndices) {
-  //   const FunctionRecord &Function = AllFunctionRegions[RecordIndex];
-  //   for(const auto &I : Function.CountedRegions){
-  //     llvm::errs() << "(" << to_string(I.startLoc().first) << ", " << to_string(I.endLoc().first) << ")" << "\n";
-  //   }
-  // }
-  // ArrayRef<unsigned> RecordIndices =
-  //     getImpreciseRecordIndicesForFilename(Filename);
   for (unsigned RecordIndex : RecordIndices) {
     const FunctionRecord &Function = !MergeBinaryCoverage ? Functions[RecordIndex] : AllFunctionRegions[RecordIndex];
     auto MainFileID = findMainViewFileID(Filename, Function);
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index 404e5177980d6..2910ca8486b63 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -574,49 +574,6 @@ Error InstrProfSymtab::addVTableWithName(GlobalVariable &VTable,
   return Error::success();
 }
 
-// Error readAndDecodeStrings(StringRef NameStrings,
-//                            std::function<Error(StringRef)> NameCallback, const std::string &Architecture) {
-//   const uint8_t *P = NameStrings.bytes_begin();
-//   const uint8_t *EndP = NameStrings.bytes_end();
-//   while (P < EndP) {
-//     uint32_t N;
-//     uint64_t UncompressedSize = decodeULEB128(P, &N);
-//     P += N;
-//     uint64_t CompressedSize = decodeULEB128(P, &N);
-//     P += N;
-//     const bool IsCompressed = (CompressedSize != 0);
-//     SmallVector<uint8_t, 128> UncompressedNameStrings;
-//     StringRef NameStrings;
-//     if (IsCompressed) {
-//       if (!llvm::compression::zlib::isAvailable())
-//         return make_error<InstrProfError>(instrprof_error::zlib_unavailable);
-
-//       if (Error E = compression::zlib::decompress(ArrayRef(P, CompressedSize),
-//                                                   UncompressedNameStrings,
-//                                                   UncompressedSize)) {
-//         consumeError(std::move(E));
-//         return make_error<InstrProfError>(instrprof_error::uncompress_failed);
-//       }
-//       P += CompressedSize;
-//       NameStrings = toStringRef(UncompressedNameStrings);
-//     } else {
-//       NameStrings =
-//           StringRef(reinterpret_cast<const char *>(P), UncompressedSize);
-//       P += UncompressedSize;
-//     }
-//     // Now parse the name strings.
-//     SmallVector<StringRef, 0> Names;
-//     NameStrings.split(Names, getInstrProfNameSeparator());
-//     for (StringRef &Name : Names){
-//       if (Error E = NameCallback(Name))
-//         return E;
-//     }
-//     while (P < EndP && *P == 0)
-//       P++;
-//   }
-//   return Error::success();
-// }
-
 Error readAndDecodeStrings(StringRef NameStrings,
                            std::function<Error(StringRef)> NameCallback, StringRef ObjectFilename) {
   const uint8_t *P = NameStrings.bytes_begin();
@@ -665,8 +622,7 @@ Error InstrProfSymtab::create(StringRef NameStrings) {
 }
 
 Error InstrProfSymtab::create(StringRef FuncNameStrings,
-                              StringRef VTableNameStrings) {
-  // const std::string &Architecture = getArchitecture();                                
+                              StringRef VTableNameStrings) {                          
   if (Error E = readAndDecodeStrings(FuncNameStrings, std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1)))
     return E;
 
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index d4f70ecb247a0..a13c557d8f923 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -154,7 +154,7 @@ static void printBinaryIdsInternal(raw_ostream &OS,
   }
 }
 
-Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create( //STEP 1
+Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
     const Twine &Path, vfs::FileSystem &FS,
     const InstrProfCorrelator *Correlator,
     const object::BuildIDFetcher *BIDFetcher,
@@ -196,6 +196,7 @@ Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
 
   // Initialize the reader and return the result.
 
+  //Pass the ObjectFilename to Result
   if(Result){
     Result->setObjectFilename(ObjectFilename);
   }
@@ -536,7 +537,7 @@ bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
 }
 
 template <class IntPtrT>
-Error RawInstrProfReader<IntPtrT>::readHeader() { //STEP 2
+Error RawInstrProfReader<IntPtrT>::readHeader() {
   if (!hasFormat(*DataBuffer))
     return error(instrprof_error::bad_magic);
   if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
@@ -576,8 +577,7 @@ Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
 }
 
 template <class IntPtrT>
-Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { //STEP 5
-  
+Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
   Symtab.setObjectFilename(ObjectFilename);
   
   if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart),
@@ -610,7 +610,7 @@ Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) { //STE
 template <class IntPtrT>
 Error RawInstrProfReader<IntPtrT>::readHeader(
     const RawInstrProf::Header &Header) {
-  Version = swap(Header.Version); //STEP 4
+  Version = swap(Header.Version);
   if (GET_VERSION(Version) != RawInstrProf::Version)
     return error(instrprof_error::raw_profile_version_mismatch,
                  ("Profile uses raw profile format version = " +
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 2c18a5c7825ad..5d42d5c24346f 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -195,66 +195,13 @@ void InstrProfWriter::overlapRecord(NamedInstrProfRecord &&Other,
   Dest.overlap(Other, Overlap, FuncLevelOverlap, ValueCutoff);
 }
 
-// void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
-//                                 InstrProfRecord &&I, uint64_t Weight,
-//                                 function_ref<void(Error)> Warn) {
-//   auto &ProfileDataMap = FunctionData[Name];
-
-//   auto [Where, NewFunc] = ProfileDataMap.try_emplace(Hash);
-//   InstrProfRecord &Dest = Where->second;
-
-//   auto MapWarn = [&](instrprof_error E) {
-//     Warn(make_error<InstrProfError>(E));
-//   };
-
-//   if (NewFunc) {
-//     // We've never seen a function with this name and hash, add it.
-//     Dest = std::move(I);
-//     if (Weight > 1)
-//       Dest.scale(Weight, 1, MapWarn);
-//   } else {
-//     // We're updating a function we've seen before.
-//     Dest.merge(I, Weight, MapWarn);
-//   }
-
-//   Dest.sortValueData();
-// }
-
-
-
-// #include "llvm/DebugInfo/DWARF/DWARFContext.h"
-
-
-#include <llvm/Support/raw_ostream.h>
-#include <llvm/Support/MemoryBuffer.h>
-#include <llvm/Support/SHA1.h>
-#include <array>
-
-StringRef hashSourceFile(llvm::StringRef FilePath) {
-    auto FileOrErr = llvm::MemoryBuffer::getFile(FilePath);
-    if (!FileOrErr) {
-        llvm::errs() << "Error reading file: " << FilePath << "\n";
-        return "";
-    }
-
-    const auto &Buffer = *FileOrErr.get();
-    llvm::SHA1 Hasher;
-    Hasher.update(Buffer.getBuffer());
-
-    std::array<uint8_t, 20> Hash = Hasher.final();
-    
-    std::string HexStr = llvm::toHex(llvm::ArrayRef<uint8_t>(Hash));
-    llvm::StringRef HashRef(HexStr);
-    return HashRef;
-}
-
 
 
 void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
                                 InstrProfRecord &&I, uint64_t Weight,
                                 function_ref<void(Error)> Warn, StringRef ObjectFilename) {
   auto &ProfileDataMap = FunctionData[Name];
-  // StringRef SHAHash = hashSourceFile(Architecture);
+  //add objectFilename to hash value if --object-aware-hashing is used
   if(!ObjectFilename.empty()){
     std::string HashStr = std::to_string(Hash) + ":" + ObjectFilename.str();
     llvm::StringRef HashRef(HashStr);
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 7f4a0df458201..e24cba8f532bd 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -695,26 +695,6 @@ static void overlapInput(const std::string &BaseFilename,
   }
 }
 
-// //ANDRES FUNCTION
-// Expected<std::string> getArchitectureFromExecutable(StringRef ExecutablePath){
-//   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError = MemoryBuffer::getFile(ExecutablePath);
-//   if(!BufferOrError){
-//     return createStringError(BufferOrError.getError(), "Failed to load input file");
-//   }
-
-//   Expected<std::unique_ptr<object::ObjectFile>> ObjectOrError = object::ObjectFile::createObjectFile(BufferOrError.get()->getMemBufferRef());
-//   if(!ObjectOrError){
-//     return ObjectOrError.takeError();
-//   }
-
-//   std::unique_ptr<llvm::object::ObjectFile> &Object = ObjectOrError.get();
-
-//   StringRef ArchStr = Object->getArch() != Triple::UnknownArch ? Triple::getArchTypeName(Object->getArch()) : "unknown";
-
-//   return ArchStr.str();
-// }
-// //ANDRES FUNCTION
-
 /// Load an input into a writer context.
 static void
 loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
@@ -727,30 +707,14 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
   // WeightedFile &" by value, making a reference to the filename within it
   // invalid outside of this packaged task.
   std::string Filename = Input.Filename;
-
-  //ANDRES CODE
   std::string ExecutableName;
   std::string ProfileFile = Input.Filename;
   StringRef ObjectFilename = "";
 
   StringRef FilenameRef = Filename;
   if(!ObjectAwareHashing.empty()){
-    // StringRef ExeRef, ProfRef;
-    // std::tie(ExeRef, ProfRef) = FilenameRef.split(':');
-    // if(!ExeRef.empty() && !ProfRef.empty()){
     ObjectFilename = ObjectAwareHashing.data();
-      // ProfileFile = ProfRef.str();
-    // }
-    // Expected<std::string> ArchOrError = getArchitectureFromExecutable(ExeRef);
-    // if(ArchOrError){
-    //   Architecture = std::move(ArchOrError.get());
-    // }else{
-    //   consumeError(ArchOrError.takeError());
-    //   Architecture = "unknown";
-    // }
-    // ObjectFilename = ExeRef;
   }
-  //ANDRES CODE
 
 
   using ::llvm::memprof::RawMemProfReader;
@@ -841,8 +805,8 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
   const ProfCorrelatorKind CorrelatorKind = BIDFetcherCorrelatorKind
                                                 ? *BIDFetcherCorrelatorKind
                                                 : ProfCorrelatorKind::NONE;
-  auto ReaderOrErr = InstrProfReader::create(ProfileFile /*ANDRES changed from Input.Filename to ProfileFile*/, *FS, Correlator, //THIS IS THE IMPORTANT LINE!!!!
-                                             BIDFetcher, CorrelatorKind, Warn, ObjectFilename /*ANDRES added this parameter*/);
+  auto ReaderOrErr = InstrProfReader::create(ProfileFile, *FS, Correlator,
+                                             BIDFetcher, CorrelatorKind, Warn, ObjectFilename);
   if (Error E = ReaderOrErr.takeError()) {
     // Skip the empty profiles by returning silently.
     auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
@@ -1771,28 +1735,6 @@ static void addWeightedInput(WeightedFileVector &WNI, const WeightedFile &WF) {
     return;
   }
 
-  //ANDRES ADDED CODE UPDATED CODE TO HANDLE ARCH SPECIFIC EXECUTABLE
-  StringRef ExecutableName, ProfileFile;
-  if(Filename.contains(':')){
-    std::tie(ExecutableName, ProfileFile) = Filename.split(':');
-
-
-    if(!ExecutableName.empty() && !ProfileFile.empty()){
-      llvm::sys::fs::file_status Status;
-      llvm::sys::fs::status(ProfileFile, Status);
-      if(!llvm::sys::fs::exists(Status)){
-        exitWithErrorCode(make_error_code(errc::no_such_file_or_directory),ProfileFile);
-      }
-      if(llvm::sys::fs::is_regular_file(Status)){
-        WNI.push_back({std::string(Filename), Weight});
-        return;
-      }
-
-      Filename = ProfileFile;
-    }
-  }
-  //ANDRES ADDED CODE
-
   llvm::sys::fs::file_status Status;
   llvm::sys::fs::status(Filename, Status);
   if (!llvm::sys::fs::exists(Status))

>From e8a2c1a967faf89b2a69e8aa409ea64dfc3d80a6 Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Fri, 1 Aug 2025 10:21:18 -0700
Subject: [PATCH 16/17] added three llvm-lit tests, testing the
 --merge-binary-coverage flag and the --show-arch-executables flag

---
 .../ProfileData/Coverage/CoverageMapping.h    |  7 ++
 llvm/include/llvm/ProfileData/InstrProf.h     |  3 +-
 .../llvm/ProfileData/InstrProfReader.h        |  2 +-
 .../ProfileData/Coverage/CoverageMapping.cpp  | 28 +++----
 llvm/lib/ProfileData/InstrProf.cpp            |  2 +-
 llvm/lib/ProfileData/InstrProfReader.cpp      |  8 +-
 llvm/lib/ProfileData/InstrProfWriter.cpp      |  4 +-
 llvm/test/tools/llvm-cov/Inputs/fb.c          |  5 ++
 llvm/test/tools/llvm-cov/Inputs/mypg.c        |  2 +
 llvm/test/tools/llvm-cov/Inputs/myprogram.c   |  8 ++
 .../merge-binary-coverage-multi-file.c        | 39 ++++++++++
 .../tools/llvm-cov/merge-binary-coverage.c    | 61 ++++++++++++++++
 .../tools/llvm-cov/merge-show-arch-exec.c     | 73 +++++++++++++++++++
 llvm/tools/llvm-cov/CodeCoverage.cpp          | 48 ++++--------
 llvm/tools/llvm-cov/SourceCoverageView.cpp    | 42 +++++------
 llvm/tools/llvm-cov/SourceCoverageView.h      | 26 +++++--
 .../tools/llvm-cov/SourceCoverageViewHTML.cpp | 59 ++++++++-------
 llvm/tools/llvm-cov/SourceCoverageViewHTML.h  | 10 +--
 .../tools/llvm-cov/SourceCoverageViewText.cpp | 48 ++++++++----
 llvm/tools/llvm-cov/SourceCoverageViewText.h  | 10 +--
 llvm/tools/llvm-profdata/llvm-profdata.cpp    | 10 +--
 21 files changed, 349 insertions(+), 146 deletions(-)
 create mode 100644 llvm/test/tools/llvm-cov/Inputs/fb.c
 create mode 100644 llvm/test/tools/llvm-cov/Inputs/mypg.c
 create mode 100644 llvm/test/tools/llvm-cov/Inputs/myprogram.c
 create mode 100644 llvm/test/tools/llvm-cov/merge-binary-coverage-multi-file.c
 create mode 100644 llvm/test/tools/llvm-cov/merge-binary-coverage.c
 create mode 100644 llvm/test/tools/llvm-cov/merge-show-arch-exec.c

diff --git a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
index cb3b7c60ba981..5c4eece59e2e2 100644
--- a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
+++ b/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h
@@ -1018,6 +1018,7 @@ class CoverageMapping {
   DenseMap<std::pair<size_t, hash_code>, unsigned> RecordIndices;
   uint64_t DebugCount = 0;
   std::vector<FunctionRecord> AllFunctionRegions;
+  StringRef ObjectFilename;
 
 
   std::map<std::pair<std::string, std::string>, std::vector<uint64_t>> AggregatedCounts;
@@ -1073,6 +1074,12 @@ class CoverageMapping {
     Arch = StringRef(NewArch);
   }
 
+  void setObjectFilename(StringRef ObjectFilename){
+    this->ObjectFilename = StringRef(ObjectFilename);
+  }
+
+  const StringRef &getObjectFilename() const { return this->ObjectFilename; }
+
   CoverageMapping(const CoverageMapping &) = delete;
   CoverageMapping &operator=(const CoverageMapping &) = delete;
 
diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h
index 99c3df6a2e834..2cbe412fed75c 100644
--- a/llvm/include/llvm/ProfileData/InstrProf.h
+++ b/llvm/include/llvm/ProfileData/InstrProf.h
@@ -646,7 +646,8 @@ class InstrProfSymtab {
 
     uint64_t HashValue = IndexedInstrProf::ComputeHash(SymbolName);
     std::string HashStr(std::to_string(HashValue));
-    //if ObjectFilename is not empty from the --object-aware-hashing flag, add ObjectFilename to hash context
+    // if ObjectFilename is not empty from the --object-aware-hashing flag, add
+    // ObjectFilename to hash context
     if(!ObjectFilename.empty()){
       std::string CombinedStr = HashStr + ":" + ObjectFilename.str();
       StringRef HashRef = CombinedStr;
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index 230c7e3233e58..24bb3f384a394 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -162,7 +162,7 @@ class InstrProfReader {
   LLVM_ABI void accumulateCounts(CountSumOrPercent &Sum, bool IsCS);
 
 protected:
-  //Storing ObjectFilename Information as a string
+  // Storing ObjectFilename Information as a string
   std::string ObjectFilename;
 
   std::unique_ptr<InstrProfSymtab> Symtab;
diff --git a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
index aaab6081e8bc4..4880582f79f8d 100644
--- a/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
+++ b/llvm/lib/ProfileData/Coverage/CoverageMapping.cpp
@@ -32,6 +32,7 @@
 #include "llvm/Support/ScopedPrinter.h"
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Object/ObjectFile.h"
 #include <algorithm>
 #include <cassert>
 #include <cmath>
@@ -825,6 +826,7 @@ class MCDCDecisionRecorder {
 
 } // namespace
 
+
 Error CoverageMapping::loadFunctionRecord(
     const CoverageMappingRecord &Record,
     const std::optional<std::reference_wrapper<IndexedInstrProfReader>>
@@ -954,13 +956,13 @@ Error CoverageMapping::loadFunctionRecord(
   auto FilenamesHash = hash_combine_range(Record.Filenames);
   std::string HashStr = OrigFuncName.str();
   if(ShowArchExecutables){
-    HashStr += ":" + Arch.str();
+    HashStr += ":" + ObjectFilename.str();
   }else{
     auto LogicalFuncKey = std::make_pair(FilenamesHash, hash_value(OrigFuncName));
     auto It = RecordIndices.find(LogicalFuncKey);
     if (It != RecordIndices.end()) {
       auto &ExistingFunction = Functions[It->second];
-      // Create a map of existing regions for efficient lookup.
+      // Create a map of existing regions for lookup.
       // The key uniquely identifies the source region.
       using RegionKey = std::tuple<unsigned, unsigned, unsigned, unsigned, unsigned>;
       std::map<RegionKey, CountedRegion *> ExistingRegionsMap;
@@ -987,9 +989,7 @@ Error CoverageMapping::loadFunctionRecord(
           ExistingFunction.CountedRegions.push_back(NewRegion);
         }
       }
-      // Since we modified an existing function, we don't add a new one.
-      // We just need to make sure we don't add the new 'Function' object later.
-      // The logic below this block needs to be adjusted to handle this.
+
       return Error::success();
     }
     RecordIndices.insert({LogicalFuncKey, Functions.size()});
@@ -1048,7 +1048,7 @@ Error CoverageMapping::loadFromReaders(
     std::optional<std::reference_wrapper<IndexedInstrProfReader>>
         &ProfileReader,
     CoverageMapping &Coverage, StringRef Arch, StringRef ObjectFilename, bool ShowArchExecutables, bool MergeBinaryCoverage) {
-  
+
   assert(!Coverage.SingleByteCoverage || !ProfileReader ||
          *Coverage.SingleByteCoverage ==
              ProfileReader.value().get().hasSingleByteCoverage());
@@ -1447,16 +1447,16 @@ class SegmentBuilder {
 
     sortNestedRegions(Regions);
 
-    
-    //check to see if a skipped region from executable A is within a CodeRegion from executable B,
-    //promote to CodeRegion if skipped region does not show up on any other executable.
+    // check to see if a skipped region from executable A is within a CodeRegion
+    // from executable B, promote to CodeRegion if skipped region does not show
+    // up on any other executable.
     for(auto *I = Regions.begin(); I != Regions.end(); ++I){
       bool FoundMatchInOtherBinary = false;
       for(auto *J = I + 1; J != Regions.end(); ++J){
-        if(I->ObjectFilename != J->ObjectFilename &&
-            J->Kind == CounterMappingRegion::SkippedRegion 
-            && I->Kind != CounterMappingRegion::SkippedRegion &&
-            J->startLoc() >= I->startLoc() && J->endLoc() <= I->endLoc()){
+        if (I->ObjectFilename != J->ObjectFilename &&
+            J->Kind == CounterMappingRegion::SkippedRegion &&
+            I->Kind != CounterMappingRegion::SkippedRegion &&
+            J->startLoc() >= I->startLoc() && J->endLoc() <= I->endLoc()) {
           for(auto *K = J + 1; K != Regions.end(); ++K){
             if(K->ObjectFilename == I->ObjectFilename &&
               J->startLoc() == K->startLoc() && J->endLoc() == K->endLoc()){
@@ -1527,7 +1527,7 @@ static SmallBitVector gatherFileIDs(StringRef SourceFile,
 static std::optional<unsigned>
 findMainViewFileID(const FunctionRecord &Function) {
   SmallBitVector IsNotExpandedFile(Function.Filenames.size(), true);
-  for (const auto &CR : Function.CountedRegions){
+  for (const auto &CR : Function.CountedRegions) {
     if (CR.Kind == CounterMappingRegion::ExpansionRegion)
       IsNotExpandedFile[CR.ExpandedFileID] = false;
   }
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index 2910ca8486b63..07122e4736486 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -622,7 +622,7 @@ Error InstrProfSymtab::create(StringRef NameStrings) {
 }
 
 Error InstrProfSymtab::create(StringRef FuncNameStrings,
-                              StringRef VTableNameStrings) {                          
+                              StringRef VTableNameStrings) {
   if (Error E = readAndDecodeStrings(FuncNameStrings, std::bind(&InstrProfSymtab::addFuncName, this, std::placeholders::_1)))
     return E;
 
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index a13c557d8f923..875fe57765088 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -159,8 +159,7 @@ Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
     const InstrProfCorrelator *Correlator,
     const object::BuildIDFetcher *BIDFetcher,
     const InstrProfCorrelator::ProfCorrelatorKind BIDFetcherCorrelatorKind,
-    std::function<void(Error)> Warn, 
-    StringRef ObjectFilename) {
+    std::function<void(Error)> Warn, StringRef ObjectFilename) {
   // Set up the buffer to read.
   auto BufferOrError = setupMemoryBuffer(Path, FS);
   if (Error E = BufferOrError.takeError())
@@ -196,7 +195,7 @@ Expected<std::unique_ptr<InstrProfReader>> InstrProfReader::create(
 
   // Initialize the reader and return the result.
 
-  //Pass the ObjectFilename to Result
+  // Pass the ObjectFilename to Result
   if(Result){
     Result->setObjectFilename(ObjectFilename);
   }
@@ -536,8 +535,7 @@ bool RawInstrProfReader<IntPtrT>::hasFormat(const MemoryBuffer &DataBuffer) {
          llvm::byteswap(RawInstrProf::getMagic<IntPtrT>()) == Magic;
 }
 
-template <class IntPtrT>
-Error RawInstrProfReader<IntPtrT>::readHeader() {
+template <class IntPtrT> Error RawInstrProfReader<IntPtrT>::readHeader() {
   if (!hasFormat(*DataBuffer))
     return error(instrprof_error::bad_magic);
   if (DataBuffer->getBufferSize() < sizeof(RawInstrProf::Header))
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 5d42d5c24346f..c5644d1cb56e3 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -195,13 +195,11 @@ void InstrProfWriter::overlapRecord(NamedInstrProfRecord &&Other,
   Dest.overlap(Other, Overlap, FuncLevelOverlap, ValueCutoff);
 }
 
-
-
 void InstrProfWriter::addRecord(StringRef Name, uint64_t Hash,
                                 InstrProfRecord &&I, uint64_t Weight,
                                 function_ref<void(Error)> Warn, StringRef ObjectFilename) {
   auto &ProfileDataMap = FunctionData[Name];
-  //add objectFilename to hash value if --object-aware-hashing is used
+  // add objectFilename to hash value if --object-aware-hashing is used
   if(!ObjectFilename.empty()){
     std::string HashStr = std::to_string(Hash) + ":" + ObjectFilename.str();
     llvm::StringRef HashRef(HashStr);
diff --git a/llvm/test/tools/llvm-cov/Inputs/fb.c b/llvm/test/tools/llvm-cov/Inputs/fb.c
new file mode 100644
index 0000000000000..428cbfd163a72
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/fb.c
@@ -0,0 +1,5 @@
+int foo() { return 0; }
+
+int bar() { return 0; }
+
+int bun() { return 0; }
diff --git a/llvm/test/tools/llvm-cov/Inputs/mypg.c b/llvm/test/tools/llvm-cov/Inputs/mypg.c
new file mode 100644
index 0000000000000..2fcea0fce9546
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/mypg.c
@@ -0,0 +1,2 @@
+int baz() { return 0; }
+int main() { return 1; }
diff --git a/llvm/test/tools/llvm-cov/Inputs/myprogram.c b/llvm/test/tools/llvm-cov/Inputs/myprogram.c
new file mode 100644
index 0000000000000..863b2baa017f6
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/Inputs/myprogram.c
@@ -0,0 +1,8 @@
+extern int foo();
+extern int bar();
+extern int bun();
+
+
+int main() {
+  return foo() + bar() + bun();
+}
diff --git a/llvm/test/tools/llvm-cov/merge-binary-coverage-multi-file.c b/llvm/test/tools/llvm-cov/merge-binary-coverage-multi-file.c
new file mode 100644
index 0000000000000..74945ab84bb36
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/merge-binary-coverage-multi-file.c
@@ -0,0 +1,39 @@
+// RUN: clang -O0 -fprofile-instr-generate -fcoverage-mapping \
+// RUN:        %S/Inputs/myprogram.c %S/Inputs/fb.c -o %t.hex
+// RUN: env LLVM_PROFILE_FILE=%t.hex.profraw 
+// RUN: %t.hex
+//
+//---------------- build & run the “x86” variant ------------------------------//
+// RUN: clang -O0 -fprofile-instr-generate -fcoverage-mapping \
+// RUN:        %S/Inputs/mypg.c %S/Inputs/fb.c -o %t.x86
+// RUN: env LLVM_PROFILE_FILE=%t.x86.profraw 
+// RUN: %t.x86 || true
+//
+//---------------- merge the raw profiles ------------------------------------//
+// RUN: llvm-profdata merge --object-aware-hashing=%t.x86 %t.x86.profraw \
+// RUN:                     --object-aware-hashing=%t.hex %t.hex.profraw \
+// RUN:                     -o %t.profdata
+//
+//---------------- show unified coverage & check -----------------------------//
+// RUN: llvm-cov show -instr-profile=%t.profdata --object=%t.x86 --object=%t.hex --merge-binary-coverage | FileCheck %s
+//
+// CHECK-LABEL: {{.*fb\.c}}:
+// CHECK:     1|      1|int foo() { return 0; }
+// CHECK:     2|       |
+// CHECK:     3|      1|int bar() { return 0; }
+// CHECK:     4|       |
+// CHECK:     5|      1|int bun() { return 0; }
+//
+// CHECK-LABEL: {{.*mypg\.c}}:
+// CHECK:     1|      0|int baz() { return 0; }
+// CHECK:     2|      1|int main() { return 1; }
+//
+// CHECK-LABEL: {{.*myprogram\.c}}:
+// CHECK:     1|       |extern int foo();
+// CHECK:     2|       |extern int bar();
+// CHECK:     3|       |extern int bun();
+// CHECK:     4|       |
+// CHECK:     5|       |
+// CHECK:     6|      1|int main()
+// CHECK:     7|      1|  return foo() + bar() + bun();
+// CHECK:     8|      1|}
diff --git a/llvm/test/tools/llvm-cov/merge-binary-coverage.c b/llvm/test/tools/llvm-cov/merge-binary-coverage.c
new file mode 100644
index 0000000000000..23dce6c30f2dc
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/merge-binary-coverage.c
@@ -0,0 +1,61 @@
+// RUN: clang -O0 -fprofile-instr-generate -fcoverage-mapping -DTOGGLE %s \
+// RUN:       -o %t.toggle
+// RUN: env LLVM_PROFILE_FILE=%t.toggle.profraw 
+// RUN: %t.toggle
+// RUN: cp default.profraw %t.toggle.profraw
+
+//------------------ build & run variant WITHOUT TOGGLE ----------------------//
+// RUN: clang -O0 -fprofile-instr-generate -fcoverage-mapping %s \
+// RUN:       -o %t.notoggle
+// RUN: env LLVM_PROFILE_FILE=%t.notoggle.profraw 
+// RUN: %t.notoggle
+
+//------------------ merge profiles & show coverage --------------------------//
+// RUN: llvm-profdata merge --object-aware-hashing=%t.notoggle %t.notoggle.profraw\
+// RUN:     --object-aware-hashing=%t.toggle   %t.toggle.profraw \
+// RUN:     -o %t.profdata
+//
+// RUN: llvm-cov show -instr-profile=%t.profdata                     \
+// RUN:       --object=%t.toggle --object=%t.notoggle                \
+// RUN:       --merge-binary-coverage                                \
+// RUN:   | FileCheck %s
+
+/* Expected unified coverage table:
+
+ 1|      2|int main() {
+ 2|      2|  int a = 1;
+ 3|      2|  int b = 2;
+ 4|      2|  int res = 0;
+ 5|      2|#if defined(TOGGLE)
+ 6|      1|    res = a + b;
+ 7|      1|#else
+ 8|      1|    res = b - a;
+ 9|      1|#endif
+10|      2|  return 0;
+11|      2|}
+*/
+
+// CHECK-LABEL: {{^ *1\|}}
+// CHECK: 1|      2|int main()
+// CHECK: 2|      2|int a = 1;
+// CHECK: 3|      2|int b = 2;
+// CHECK: 4|      2|int res = 0;
+// CHECK: 5|      2|#if defined(TOGGLE)
+// CHECK: 6|      1|    res = a + b;
+// CHECK: 7|      1|#else
+// CHECK: 8|      1|    res = b - a;
+// CHECK: 9|      1|#endif
+// CHECK: 10|      2|    return 0;
+// CHECK: 11|      2|}
+
+int main() {
+  int a = 1;
+  int b = 2;
+  int res = 0;
+#if defined(TOGGLE)
+  res = a + b;
+#else
+  res = b - a;
+#endif
+  return 0;
+}
\ No newline at end of file
diff --git a/llvm/test/tools/llvm-cov/merge-show-arch-exec.c b/llvm/test/tools/llvm-cov/merge-show-arch-exec.c
new file mode 100644
index 0000000000000..aae3570042d10
--- /dev/null
+++ b/llvm/test/tools/llvm-cov/merge-show-arch-exec.c
@@ -0,0 +1,73 @@
+// RUN: clang -O0 -fprofile-instr-generate -fcoverage-mapping -DTOGGLE %s \
+// RUN:       -o %t.toggle
+// RUN: %t.toggle
+// RUN: cp default.profraw %t.toggle.profraw
+
+//------------------ build & run variant WITHOUT TOGGLE ----------------------//
+// RUN: clang -O0 -fprofile-instr-generate -fcoverage-mapping %s \
+// RUN:       -o %t.notoggle
+// RUN: %t.notoggle
+// RUN: cp default.profraw %t.notoggle.profraw 
+
+//------------------ merge profiles & show coverage --------------------------//
+// RUN: llvm-profdata merge --object-aware-hashing=%t.notoggle %t.notoggle.profraw\
+// RUN:     --object-aware-hashing=%t.toggle   %t.toggle.profraw \
+// RUN:     -o %t.profdata
+//
+// RUN: llvm-cov show -instr-profile=%t.profdata --object=%t.toggle --object=%t.notoggle --merge-binary-coverage --show-arch-executables | FileCheck %s
+
+// CHECK:       |    2|      2|int a = 1;
+// CHECK:       |    3|      2|int b = 2;
+// CHECK:       |    4|      2|int res = 0;
+// CHECK:       |    5|      2|#if defined\(TOGGLE\)
+// CHECK:       |    6|      1|    res = a \+ b;
+// CHECK:       |    7|      1|#else
+// CHECK:       |    8|      1|    res = b - a;
+// CHECK:       |    9|      1|#endif
+// CHECK:       |   10|      2|    return 0;
+// CHECK:       |   11|      2|}
+// CHECK:       |  ------------------
+// CHECK:       |  | main:
+// CHECK:       |  |    -x86_64
+// CHECK:       |  |    -merge-ifdef.toggle:
+// CHECK:       |  |    1|      1|int main\(\) {
+// CHECK:       |  |    2|      1|int a = 1;
+// CHECK:       |  |    3|      1|int b = 2;
+// CHECK:       |  |    4|      1|int res = 0;
+// CHECK:       |  |    5|      1|#if defined\(TOGGLE\)
+// CHECK:       |  |    6|      1|    res = a \+ b;
+// CHECK:       |  |    7|       |#else
+// CHECK:       |  |    8|       |    res = b - a;
+// CHECK:       |  |    9|       |#endif
+// CHECK:       |  |   10|      1|    return 0;
+// CHECK:       |  |   11|      1|}
+// CHECK:       |  ------------------
+// CHECK:       |  | main:
+// CHECK:       |  |    -x86_64
+// CHECK:       |  |    -merge-ifdef.notoggle:
+// CHECK:       |  |    1|      1|int main\(\) {
+// CHECK:       |  |    2|      1|int a = 1;
+// CHECK:       |  |    3|      1|int b = 2;
+// CHECK:       |  |    4|      1|int res = 0;
+// CHECK:       |  |    5|       |#if defined\(TOGGLE\)
+// CHECK:       |  |    6|       |    res = a \+ b;
+// CHECK:       |  |    7|       |#else
+// CHECK:       |  |    8|      1|    res = b - a;
+// CHECK:       |  |    9|      1|#endif
+// CHECK:       |  |   10|      1|    return 0;
+// CHECK:       |  |   11|      1|}
+// CHECK:       |  ------------------
+
+
+
+int main() {
+  int a = 1;
+  int b = 2;
+  int res = 0;
+#if defined(TOGGLE)
+  res = a + b;
+#else
+  res = b - a;
+#endif
+  return 0;
+}
\ No newline at end of file
diff --git a/llvm/tools/llvm-cov/CodeCoverage.cpp b/llvm/tools/llvm-cov/CodeCoverage.cpp
index bc273f554043e..a157a3069e349 100644
--- a/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -116,7 +116,7 @@ class CodeCoverageTool {
 
   /// Create the main source view of a particular source file.
   std::unique_ptr<SourceCoverageView>
-  createSourceFileView(StringRef SourceFile, const CoverageMapping &Coverage, std::vector<StringRef> Arches);
+  createSourceFileView(StringRef SourceFile, const CoverageMapping &Coverage, std::vector<StringRef> Arches, std::vector<StringRef> ObjectFilenames = {});
 
   /// Load the coverage mapping data. Return nullptr if an error occurred.
   std::unique_ptr<CoverageMapping> load();
@@ -131,9 +131,10 @@ class CodeCoverageTool {
   /// If a demangler is available, demangle all symbol names.
   void demangleSymbols(const CoverageMapping &Coverage);
 
-  /// Write out a source file view to the filesystem.
   void writeSourceFileView(StringRef SourceFile, CoverageMapping *Coverage,
-                           CoveragePrinter *Printer, bool ShowFilenames);
+                            CoveragePrinter *Printer, bool ShowFilenames, 
+                            std::vector<StringRef> ObjectFilenames);
+
 
   typedef llvm::function_ref<int(int, const char **)> CommandLineParserType;
 
@@ -393,7 +394,7 @@ CodeCoverageTool::createFunctionView(const FunctionRecord &Function,
 
 std::unique_ptr<SourceCoverageView>
 CodeCoverageTool::createSourceFileView(StringRef SourceFile,
-                                       const CoverageMapping &Coverage, std::vector<StringRef> Arches) {
+                                       const CoverageMapping &Coverage, std::vector<StringRef> Arches, std::vector<StringRef>ObjectFilenames) {
   auto SourceBuffer = getSourceFile(SourceFile);
   if (!SourceBuffer)
     return nullptr;
@@ -405,7 +406,7 @@ CodeCoverageTool::createSourceFileView(StringRef SourceFile,
   auto Expansions = FileCoverage.getExpansions();
   auto MCDCRecords = FileCoverage.getMCDCRecords();
   auto View = SourceCoverageView::create(SourceFile, SourceBuffer.get(),
-                                         ViewOpts, std::move(FileCoverage));
+                                         ViewOpts, std::move(FileCoverage), ObjectFilenames);
   attachExpansionSubViews(*View, Expansions, Coverage);
   attachBranchSubViews(*View, Branches);
   attachMCDCSubViews(*View, MCDCRecords);
@@ -456,27 +457,6 @@ static bool modifiedTimeGT(StringRef LHS, StringRef RHS) {
   return LHSTime > RHSTime;
 }
 
-// void mergeExecutionCounts(CoverageMapping &Coverage){
-//   std::map<std::string, std::vector<const FunctionRecord*>> functionGroups;
-
-//   for(const auto &Function : Coverage.getCoveredFunctions()){
-//     if(Function.CountedRegions.empty()) continue;
-//     const auto &MainRegion = Function.CountedRegions.front();
-//     const std::string Key = Function.Name + ":" + std::to_string(MainRegion.LineStart) + ":" + std::to_string(MainRegion.ColumnStart) + ":" + (Function.Filenames.empty() ? "" : std::string(Function.Filenames[0]));
-//     functionGroups[Key].push_back(&Function);
-//     llvm::errs() << Key << "\n";
-//   }
-
-//   for(auto &Group : functionGroups){
-//     if(Group.second.size() > 1){
-//       uint64_t TotalCount = 0;
-//       for(auto *Func : Group.second){
-//         TotalCount += Func->ExecutionCount;
-//       }
-//     }
-//   }
-// }
-
 std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
   if (PGOFilename) {
     for (StringRef ObjectFilename : ObjectFilenames)
@@ -506,9 +486,6 @@ std::unique_ptr<CoverageMapping> CodeCoverageTool::load() {
                << '\n';
     }
   }
-
-  // mergeExecutionCounts(*Coverage);
-
   remapPathNames(*Coverage);
 
   if (!SourceFiles.empty())
@@ -658,8 +635,9 @@ void CodeCoverageTool::demangleSymbols(const CoverageMapping &Coverage) {
 void CodeCoverageTool::writeSourceFileView(StringRef SourceFile,
                                            CoverageMapping *Coverage,
                                            CoveragePrinter *Printer,
-                                           bool ShowFilenames) {
-  auto View = createSourceFileView(SourceFile, *Coverage, CoverageArches);
+                                           bool ShowFilenames, 
+                                           std::vector<StringRef> ObjectFilenames) {
+  auto View = createSourceFileView(SourceFile, *Coverage, CoverageArches, ObjectFilenames);
   if (!View) {
     warning("The file '" + SourceFile + "' isn't covered.");
     return;
@@ -674,7 +652,7 @@ void CodeCoverageTool::writeSourceFileView(StringRef SourceFile,
 
   View->print(*OS.get(), /*Wholefile=*/true,
               /*ShowSourceName=*/ShowFilenames,
-              /*ShowTitle=*/ViewOpts.hasOutputDirectory());
+              /*ShowTitle=*/ViewOpts.hasOutputDirectory(), ViewOpts.ShowArchExecutables);
   Printer->closeViewFile(std::move(OS));
 }
 
@@ -1262,13 +1240,13 @@ int CodeCoverageTool::doShow(int argc, const char **argv,
   if (!ViewOpts.hasOutputDirectory() || S.ThreadsRequested == 1) {
     for (const std::string &SourceFile : SourceFiles)
       writeSourceFileView(SourceFile, Coverage.get(), Printer.get(),
-                          ShowFilenames);
+                          ShowFilenames, ObjectFilenames);
   } else {
     // In -output-dir mode, it's safe to use multiple threads to print files.
     DefaultThreadPool Pool(S);
     for (const std::string &SourceFile : SourceFiles)
-      Pool.async(&CodeCoverageTool::writeSourceFileView, this, SourceFile,
-                 Coverage.get(), Printer.get(), ShowFilenames);
+      Pool.async(static_cast<void (CodeCoverageTool::*)(StringRef, CoverageMapping *, CoveragePrinter *, bool, std::vector<StringRef>)>(&CodeCoverageTool::writeSourceFileView), this, SourceFile,
+                 Coverage.get(), Printer.get(), ShowFilenames, ObjectFilenames);
     Pool.wait();
   }
 
diff --git a/llvm/tools/llvm-cov/SourceCoverageView.cpp b/llvm/tools/llvm-cov/SourceCoverageView.cpp
index 810e2c6024584..084c601601c73 100644
--- a/llvm/tools/llvm-cov/SourceCoverageView.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageView.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "SourceCoverageView.h"
+#include "CoverageViewOptions.h"
 #include "SourceCoverageViewHTML.h"
 #include "SourceCoverageViewText.h"
 #include "llvm/ADT/SmallString.h"
@@ -147,14 +148,14 @@ bool SourceCoverageView::hasSubViews() const {
 std::unique_ptr<SourceCoverageView>
 SourceCoverageView::create(StringRef SourceName, const MemoryBuffer &File,
                            const CoverageViewOptions &Options,
-                           CoverageData &&CoverageInfo) {
+                           CoverageData &&CoverageInfo, std::vector<StringRef> ObjectFilenames) {
   switch (Options.Format) {
   case CoverageViewOptions::OutputFormat::Text:
     return std::make_unique<SourceCoverageViewText>(
-        SourceName, File, Options, std::move(CoverageInfo));
+        SourceName, File, Options, std::move(CoverageInfo), ObjectFilenames);
   case CoverageViewOptions::OutputFormat::HTML:
     return std::make_unique<SourceCoverageViewHTML>(
-        SourceName, File, Options, std::move(CoverageInfo));
+        SourceName, File, Options, std::move(CoverageInfo), ObjectFilenames);
   case CoverageViewOptions::OutputFormat::Lcov:
     // Unreachable because CodeCoverage.cpp should terminate with an error
     // before we get here.
@@ -194,14 +195,19 @@ void SourceCoverageView::addInstantiation(
 
 void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
                                bool ShowSourceName, bool ShowTitle,
-                               unsigned ViewDepth, StringRef SourceFile) {
+                               unsigned ViewDepth, StringRef ObjectFilename) {
   if (ShowTitle)
     renderTitle(OS, "Coverage Report");
 
   renderViewHeader(OS);
 
-  if (ShowSourceName)
+  if (ShowSourceName){
     renderSourceName(OS, WholeFile);
+    if(!ObjectFilename.empty()){
+      renderArchandObj(OS, ObjectFilename);
+    }
+  }
+
 
   renderTableHeader(OS, ViewDepth);
 
@@ -224,25 +230,8 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
   auto StartSegment = CoverageInfo.begin();
   auto EndSegment = CoverageInfo.end();
   LineCoverageIterator LCI{CoverageInfo, 1};
-  // LineCoverageIterator LCIInit{CoverageInfo, 1};
   LineCoverageIterator LCIEnd = LCI.getEnd();
   unsigned FirstLine = StartSegment != EndSegment ? StartSegment->Line : 0;
-  
-  // // Determine the number of lines in the file
-  // unsigned NumLines = 0;
-  // for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof(); ++LI)
-  //   ++NumLines;
-  // // Resize the outer vector to hold one entry per line
-  // std::vector<std::vector<LineCoverageStats>> LineArchStats;
-  // LineArchStats.resize(CoverageArches.size()); // +1 in case line numbers are 1-based
-  // for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof(); ++LI, ++LCIInit) {
-  //   unsigned LineNo = LCIInit->getLine();
-  //   if (LineNo >= LineArchStats.size()){
-  //     LineArchStats.resize(LineNo + 1); // Ensure enough space
-  //   }
-  //   LineArchStats[LineNo].push_back(*LCIInit); // Store the LineCoverageStats
-  // }
-
   for (line_iterator LI(File, /*SkipBlanks=*/false); !LI.is_at_eof();
        ++LI, ++LCI) {
     // If we aren't rendering the whole file, we need to filter out the prologue
@@ -260,7 +249,6 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
 
     if (getOptions().ShowLineStats)
       renderLineCoverageColumn(OS, *LCI);
-      // renderArchLineCoverageColumn(OS, *LCI, LineArchStats);
 
     // If there are expansion subviews, we want to highlight the first one.
     unsigned ExpansionColumn = 0;
@@ -294,8 +282,14 @@ void SourceCoverageView::print(raw_ostream &OS, bool WholeFile,
       RenderedSubView = true;
     }
     for (; NextISV != EndISV && NextISV->Line == LI.line_number(); ++NextISV) {
+      //ANDRES FIX HERE, ADD MAP FROM STRINGREF TO OBJECT FILE INDEX NEED TO PASS IN ObjectFilenames ARRAY INSTEAD OF ObjectFilename
       renderViewDivider(OS, ViewDepth + 1);
-      renderInstantiationView(OS, *NextISV, ViewDepth + 1);
+      renderInstantiationView(OS, *NextISV, ViewDepth + 1, ObjectFilenames[FunctionNameToObjectFile[NextISV->FunctionName]]);
+      if(FunctionNameToObjectFile.find(NextISV->FunctionName) == FunctionNameToObjectFile.end()){
+        FunctionNameToObjectFile[NextISV->FunctionName] = 0;
+      }else{
+        FunctionNameToObjectFile[NextISV->FunctionName] += (FunctionNameToObjectFile[NextISV->FunctionName] + 1) % ObjectFilenames.size();
+      }
       RenderedSubView = true;
     }
     for (; NextBRV != EndBRV && NextBRV->Line == LI.line_number(); ++NextBRV) {
diff --git a/llvm/tools/llvm-cov/SourceCoverageView.h b/llvm/tools/llvm-cov/SourceCoverageView.h
index df83e8ca37279..11794b708ef00 100644
--- a/llvm/tools/llvm-cov/SourceCoverageView.h
+++ b/llvm/tools/llvm-cov/SourceCoverageView.h
@@ -15,6 +15,7 @@
 
 #include "CoverageViewOptions.h"
 #include "CoverageSummaryInfo.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ProfileData/Coverage/CoverageMapping.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include <vector>
@@ -182,6 +183,11 @@ class SourceCoverageView {
 
   bool BinaryCounters;
 
+  //Contains the object file path
+  std::vector<StringRef> ObjectFilenames;
+
+  DenseMap<StringRef, uint64_t> FunctionNameToObjectFile;
+
   /// Get the first uncovered line number for the source file.
   unsigned getFirstUncoveredLineNo();
 
@@ -207,6 +213,11 @@ class SourceCoverageView {
   /// Render the source name for the view.
   virtual void renderSourceName(raw_ostream &OS, bool WholeFile) = 0;
 
+  /// Render the Architecture for the view.
+  virtual void renderArchandObj(raw_ostream &OS, StringRef ObjectFilename) = 0;
+
+  /// Render the Object name for the view.
+
   /// Render the line prefix at the given \p ViewDepth.
   virtual void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) = 0;
 
@@ -224,9 +235,6 @@ class SourceCoverageView {
   /// Render the line's execution count column.
   virtual void renderLineCoverageColumn(raw_ostream &OS,
                                         const LineCoverageStats &Line) = 0;
-                                
-  virtual void renderArchLineCoverageColumn(raw_ostream &OS, const LineCoverageStats &Line, std::vector<std::vector<LineCoverageStats>> LineArchStats) = 0;
-
 
   /// Render the line number column.
   virtual void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) = 0;
@@ -248,7 +256,7 @@ class SourceCoverageView {
 
   /// Render an instantiation view and any nested views.
   virtual void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
-                                       unsigned ViewDepth) = 0;
+                                       unsigned ViewDepth, StringRef ObjectFilename) = 0;
 
   /// Render a branch view and any nested views.
   virtual void renderBranchView(raw_ostream &OS, BranchView &BRV,
@@ -287,16 +295,18 @@ class SourceCoverageView {
 
   SourceCoverageView(StringRef SourceName, const MemoryBuffer &File,
                      const CoverageViewOptions &Options,
-                     CoverageData &&CoverageInfo)
+                     CoverageData &&CoverageInfo, std::vector<StringRef> ObjectFilenames)
       : SourceName(SourceName), File(File), Options(Options),
         CoverageInfo(std::move(CoverageInfo)),
         BinaryCounters(Options.BinaryCounters ||
-                       CoverageInfo.getSingleByteCoverage()) {}
+        CoverageInfo.getSingleByteCoverage()),
+        ObjectFilenames(ObjectFilenames) {}
+
 
 public:
   static std::unique_ptr<SourceCoverageView>
   create(StringRef SourceName, const MemoryBuffer &File,
-         const CoverageViewOptions &Options, CoverageData &&CoverageInfo);
+         const CoverageViewOptions &Options, CoverageData &&CoverageInfo, std::vector<StringRef> ObjectFilenames = {});
 
   virtual ~SourceCoverageView() {}
 
@@ -322,7 +332,7 @@ class SourceCoverageView {
   /// Print the code coverage information for a specific portion of a
   /// source file to the output stream.
   void print(raw_ostream &OS, bool WholeFile, bool ShowSourceName,
-             bool ShowTitle, unsigned ViewDepth = 0, StringRef CoverageArches = "");
+             bool ShowTitle, unsigned ViewDepth = 0, StringRef ObjectFilename = "");
 };
 
 } // namespace llvm
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index d4dec5e699a58..c4aecd3dbac71 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -17,6 +17,7 @@
 #include "llvm/Support/Format.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/ThreadPool.h"
+#include "llvm/Object/ObjectFile.h"
 #include <optional>
 
 using namespace llvm;
@@ -907,6 +908,36 @@ void SourceCoverageViewHTML::renderSourceName(raw_ostream &OS, bool WholeFile) {
      << EndSourceNameDiv;
 }
 
+static Expected<std::string> getArchitectureFromExecutable(StringRef ExecutablePath){
+  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError = MemoryBuffer::getFile(ExecutablePath);
+  if(!BufferOrError){
+    return createStringError(BufferOrError.getError(), "Failed to load input file");
+  }
+
+  Expected<std::unique_ptr<object::ObjectFile>> ObjectOrError = object::ObjectFile::createObjectFile(BufferOrError.get()->getMemBufferRef());
+  if(!ObjectOrError){
+    return ObjectOrError.takeError();
+  }
+
+  std::unique_ptr<llvm::object::ObjectFile> &Object = ObjectOrError.get();
+
+  StringRef ArchStr = Object->getArch() != Triple::UnknownArch ? Triple::getArchTypeName(Object->getArch()) : "unknown";
+
+  return ArchStr.str();
+}
+
+void SourceCoverageViewHTML::renderArchandObj(raw_ostream &OS, StringRef ObjectFilename) {
+  Expected<std::string> ArchOrErr = getArchitectureFromExecutable(ObjectFilename);
+    if (!ArchOrErr) {
+      // Handle the error
+      logAllUnhandledErrors(ArchOrErr.takeError(), llvm::errs(), "Error extracting architecture: ");
+      return;
+    }
+    // Use the value
+  StringRef Arch = *ArchOrErr;
+  OS << tag("pre", escape("\t-" + Arch.str() + "\n" + "\t-" + ObjectFilename.str(), getOptions()));
+}
+
 void SourceCoverageViewHTML::renderLinePrefix(raw_ostream &OS, unsigned) {
   OS << "<tr>";
 }
@@ -1062,30 +1093,6 @@ void SourceCoverageViewHTML::renderLineCoverageColumn(
   OS << tag("td", Count, CoverageClass);
 }
 
-void SourceCoverageViewHTML::renderArchLineCoverageColumn(
-    raw_ostream &OS,
-    const LineCoverageStats &Line,
-    std::vector<std::vector<LineCoverageStats>> LineArchStats) {
-  
-  std::string CellContent;
-
-  if (Line.isMapped()) {
-    unsigned LineNo = Line.getLine();
-    for (const auto &ArchStats : LineArchStats[LineNo]) {
-      CellContent += formatBinaryCount(ArchStats.getExecutionCount()) + "/";
-    }
-    if (!CellContent.empty())
-      CellContent.pop_back(); // Remove trailing '/'
-  }
-
-  std::string CoverageClass =
-      (Line.getExecutionCount() > 0)
-          ? "covered-line"
-          : (Line.isMapped() ? "uncovered-line" : "skipped-line");
-
-  OS << tag("td", tag("pre", CellContent), CoverageClass);
-}
-
 
 void SourceCoverageViewHTML::renderLineNumberColumn(raw_ostream &OS,
                                                     unsigned LineNo) {
@@ -1220,7 +1227,7 @@ void SourceCoverageViewHTML::renderMCDCView(raw_ostream &OS, MCDCView &MRV,
 
 void SourceCoverageViewHTML::renderInstantiationView(raw_ostream &OS,
                                                      InstantiationView &ISV,
-                                                     unsigned ViewDepth) {
+                                                     unsigned ViewDepth, StringRef ObjectFilename) {
   OS << BeginExpansionDiv;
   if (!ISV.View)
     OS << BeginSourceNameDiv
@@ -1230,7 +1237,7 @@ void SourceCoverageViewHTML::renderInstantiationView(raw_ostream &OS,
        << EndSourceNameDiv;
   else
     ISV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/true,
-                    /*ShowTitle=*/false, ViewDepth);
+                    /*ShowTitle=*/false, ViewDepth, ObjectFilename);
   OS << EndExpansionDiv;
 }
 
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewHTML.h b/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
index 37098273510e0..92cbe6c16d23d 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
+++ b/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
@@ -71,6 +71,8 @@ class SourceCoverageViewHTML : public SourceCoverageView {
 
   void renderSourceName(raw_ostream &OS, bool WholeFile) override;
 
+  void renderArchandObj(raw_ostream &OS, StringRef ObjectFilename) override;
+
   void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;
 
   void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) override;
@@ -94,13 +96,11 @@ class SourceCoverageViewHTML : public SourceCoverageView {
                       unsigned ViewDepth) override;
 
   void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
-                               unsigned ViewDepth) override;
+                               unsigned ViewDepth, StringRef ObjectFilenames) override;
 
   void renderLineCoverageColumn(raw_ostream &OS,
                                 const LineCoverageStats &Line) override;
 
-  void renderArchLineCoverageColumn(raw_ostream &OS, const LineCoverageStats &Line, std::vector<std::vector<LineCoverageStats>> LineArchStats) override;
-
   void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override;
 
   void renderRegionMarkers(raw_ostream &OS, const LineCoverageStats &Line,
@@ -113,8 +113,8 @@ class SourceCoverageViewHTML : public SourceCoverageView {
 public:
   SourceCoverageViewHTML(StringRef SourceName, const MemoryBuffer &File,
                          const CoverageViewOptions &Options,
-                         coverage::CoverageData &&CoverageInfo)
-      : SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo)) {
+                         coverage::CoverageData &&CoverageInfo, std::vector<StringRef> ObjectFilenames)
+      : SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo), ObjectFilenames) {
   }
 };
 
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index 9471f7529e104..e70fb6cf4e292 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -18,6 +18,7 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Object/ObjectFile.h"
 #include <optional>
 
 using namespace llvm;
@@ -140,6 +141,38 @@ void SourceCoverageViewText::renderSourceName(raw_ostream &OS, bool WholeFile) {
                                                       << ":\n";
 }
 
+static Expected<std::string> getArchitectureFromExecutable(StringRef ExecutablePath){
+  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrError = MemoryBuffer::getFile(ExecutablePath);
+  if(!BufferOrError){
+    return createStringError(BufferOrError.getError(), "Failed to load input file");
+  }
+
+  Expected<std::unique_ptr<object::ObjectFile>> ObjectOrError = object::ObjectFile::createObjectFile(BufferOrError.get()->getMemBufferRef());
+  if(!ObjectOrError){
+    return ObjectOrError.takeError();
+  }
+
+  std::unique_ptr<llvm::object::ObjectFile> &Object = ObjectOrError.get();
+
+  StringRef ArchStr = Object->getArch() != Triple::UnknownArch ? Triple::getArchTypeName(Object->getArch()) : "unknown";
+
+  return ArchStr.str();
+}
+
+void SourceCoverageViewText::renderArchandObj(raw_ostream &OS, StringRef ObjectFilename) {
+  Expected<std::string> ArchOrErr = getArchitectureFromExecutable(ObjectFilename);
+    if (!ArchOrErr) {
+      // Handle the error
+      logAllUnhandledErrors(ArchOrErr.takeError(), llvm::errs(), "Error extracting architecture: ");
+      return;
+    }
+    // Use the value
+  StringRef Arch = *ArchOrErr;
+  getOptions().colored_ostream(OS, raw_ostream::CYAN) << "\t-" + Arch + "\n" + "\t-" + ObjectFilename
+                                                      << ":\n";
+}
+
+
 void SourceCoverageViewText::renderLinePrefix(raw_ostream &OS,
                                               unsigned ViewDepth) {
   for (unsigned I = 0; I < ViewDepth; ++I)
@@ -223,17 +256,6 @@ void SourceCoverageViewText::renderLineCoverageColumn(
   OS << '|';
 }
 
-void SourceCoverageViewText::renderArchLineCoverageColumn(
-    raw_ostream &OS, const LineCoverageStats &Line, std::vector<std::vector<LineCoverageStats>> LineArchStats) {
-  if (!Line.isMapped()) {
-    OS.indent(LineCoverageColumnWidth) << '|';
-    return;
-  }
-  std::string C = formatBinaryCount(Line.getExecutionCount());
-  OS.indent(LineCoverageColumnWidth - C.size());
-  colored_ostream(OS, raw_ostream::MAGENTA, Line.hasMultipleRegions() && getOptions().Colors) << C;
-  OS << '|';
-}
 
 void SourceCoverageViewText::renderLineNumberColumn(raw_ostream &OS,
                                                     unsigned LineNo) {
@@ -400,7 +422,7 @@ void SourceCoverageViewText::renderMCDCView(raw_ostream &OS, MCDCView &MRV,
 
 void SourceCoverageViewText::renderInstantiationView(raw_ostream &OS,
                                                      InstantiationView &ISV,
-                                                     unsigned ViewDepth) {
+                                                     unsigned ViewDepth, StringRef ObjectFilename) {
   renderLinePrefix(OS, ViewDepth);
   OS << ' ';
   if (!ISV.View)
@@ -408,7 +430,7 @@ void SourceCoverageViewText::renderInstantiationView(raw_ostream &OS,
         << "Unexecuted instantiation: " << ISV.FunctionName << "\n";
   else
     ISV.View->print(OS, /*WholeFile=*/false, /*ShowSourceName=*/true,
-                    /*ShowTitle=*/false, ViewDepth);
+                    /*ShowTitle=*/false, ViewDepth, ObjectFilename);
 }
 
 void SourceCoverageViewText::renderTitle(raw_ostream &OS, StringRef Title) {
diff --git a/llvm/tools/llvm-cov/SourceCoverageViewText.h b/llvm/tools/llvm-cov/SourceCoverageViewText.h
index 3841aad607324..7f7131e1eb324 100644
--- a/llvm/tools/llvm-cov/SourceCoverageViewText.h
+++ b/llvm/tools/llvm-cov/SourceCoverageViewText.h
@@ -58,6 +58,8 @@ class SourceCoverageViewText : public SourceCoverageView {
 
   void renderSourceName(raw_ostream &OS, bool WholeFile) override;
 
+  void renderArchandObj(raw_ostream &OS, StringRef ObjectFilename) override;
+
   void renderLinePrefix(raw_ostream &OS, unsigned ViewDepth) override;
 
   void renderLineSuffix(raw_ostream &OS, unsigned ViewDepth) override;
@@ -81,13 +83,11 @@ class SourceCoverageViewText : public SourceCoverageView {
                       unsigned ViewDepth) override;
 
   void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
-                               unsigned ViewDepth) override;
+                               unsigned ViewDepth, StringRef ObjectFilenames) override;
 
   void renderLineCoverageColumn(raw_ostream &OS,
                                 const LineCoverageStats &Line) override;
   
-  void renderArchLineCoverageColumn(raw_ostream &OS, const LineCoverageStats &Line, std::vector<std::vector<LineCoverageStats>> LineArchStats) override;
-
   void renderLineNumberColumn(raw_ostream &OS, unsigned LineNo) override;
 
   void renderRegionMarkers(raw_ostream &OS, const LineCoverageStats &Line,
@@ -100,8 +100,8 @@ class SourceCoverageViewText : public SourceCoverageView {
 public:
   SourceCoverageViewText(StringRef SourceName, const MemoryBuffer &File,
                          const CoverageViewOptions &Options,
-                         CoverageData &&CoverageInfo)
-      : SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo)) {
+                         CoverageData &&CoverageInfo, std::vector<StringRef> ObjectFilenames)
+      : SourceCoverageView(SourceName, File, Options, std::move(CoverageInfo), ObjectFilenames) {
   }
 };
 
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index e24cba8f532bd..aa0a90aaa7afd 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -712,11 +712,10 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
   StringRef ObjectFilename = "";
 
   StringRef FilenameRef = Filename;
-  if(!ObjectAwareHashing.empty()){
+  if (!ObjectAwareHashing.empty()) {
     ObjectFilename = ObjectAwareHashing.data();
   }
 
-
   using ::llvm::memprof::RawMemProfReader;
   if (RawMemProfReader::hasFormat(ProfileFile)) {
     auto ReaderOrErr = RawMemProfReader::create(ProfileFile, ProfiledBinary);
@@ -805,8 +804,9 @@ loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
   const ProfCorrelatorKind CorrelatorKind = BIDFetcherCorrelatorKind
                                                 ? *BIDFetcherCorrelatorKind
                                                 : ProfCorrelatorKind::NONE;
-  auto ReaderOrErr = InstrProfReader::create(ProfileFile, *FS, Correlator,
-                                             BIDFetcher, CorrelatorKind, Warn, ObjectFilename);
+  auto ReaderOrErr =
+      InstrProfReader::create(ProfileFile, *FS, Correlator, BIDFetcher,
+                              CorrelatorKind, Warn, ObjectFilename);
   if (Error E = ReaderOrErr.takeError()) {
     // Skip the empty profiles by returning silently.
     auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
@@ -1064,7 +1064,7 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
     for (int I = 0; I < int(Inputs.size()); ++I) {
       Pool.async(loadInput, Inputs[I], Remapper, Correlator.get(), ProfiledBinary,
                  Contexts[Ctx].get(), BIDFetcher.get(),
-                 &BIDFetcherCorrelateKind, !ObjectAwareHashing[I].empty() ? ObjectAwareHashing[I] : "");
+                 &BIDFetcherCorrelateKind, !ObjectAwareHashing.empty() ? ObjectAwareHashing[I] : "");
       Ctx = (Ctx + 1) % NumThreads;
     }
     Pool.wait();

>From 33ed3662da65f1141f0bd57aa03b77f189a15f60 Mon Sep 17 00:00:00 2001
From: Andres Wearden <andreswearden5 at gmail.com>
Date: Fri, 1 Aug 2025 10:41:13 -0700
Subject: [PATCH 17/17] changed some of the llvm-lit file names to make more
 sense

---
 .../Inputs/{fb.c => merge-same-func-bin1-2.c} |  0
 .../{myprogram.c => merge-same-func-bin1.c}   |  0
 .../Inputs/{mypg.c => merge-same-func-bin2.c} |  0
 ...ulti-file.c => merge-same-func-diff-bin.c} | 21 +++++++++----------
 .../tools/llvm-cov/merge-show-arch-exec.c     |  1 +
 5 files changed, 11 insertions(+), 11 deletions(-)
 rename llvm/test/tools/llvm-cov/Inputs/{fb.c => merge-same-func-bin1-2.c} (100%)
 rename llvm/test/tools/llvm-cov/Inputs/{myprogram.c => merge-same-func-bin1.c} (100%)
 rename llvm/test/tools/llvm-cov/Inputs/{mypg.c => merge-same-func-bin2.c} (100%)
 rename llvm/test/tools/llvm-cov/{merge-binary-coverage-multi-file.c => merge-same-func-diff-bin.c} (76%)

diff --git a/llvm/test/tools/llvm-cov/Inputs/fb.c b/llvm/test/tools/llvm-cov/Inputs/merge-same-func-bin1-2.c
similarity index 100%
rename from llvm/test/tools/llvm-cov/Inputs/fb.c
rename to llvm/test/tools/llvm-cov/Inputs/merge-same-func-bin1-2.c
diff --git a/llvm/test/tools/llvm-cov/Inputs/myprogram.c b/llvm/test/tools/llvm-cov/Inputs/merge-same-func-bin1.c
similarity index 100%
rename from llvm/test/tools/llvm-cov/Inputs/myprogram.c
rename to llvm/test/tools/llvm-cov/Inputs/merge-same-func-bin1.c
diff --git a/llvm/test/tools/llvm-cov/Inputs/mypg.c b/llvm/test/tools/llvm-cov/Inputs/merge-same-func-bin2.c
similarity index 100%
rename from llvm/test/tools/llvm-cov/Inputs/mypg.c
rename to llvm/test/tools/llvm-cov/Inputs/merge-same-func-bin2.c
diff --git a/llvm/test/tools/llvm-cov/merge-binary-coverage-multi-file.c b/llvm/test/tools/llvm-cov/merge-same-func-diff-bin.c
similarity index 76%
rename from llvm/test/tools/llvm-cov/merge-binary-coverage-multi-file.c
rename to llvm/test/tools/llvm-cov/merge-same-func-diff-bin.c
index 74945ab84bb36..6132254b0ac17 100644
--- a/llvm/test/tools/llvm-cov/merge-binary-coverage-multi-file.c
+++ b/llvm/test/tools/llvm-cov/merge-same-func-diff-bin.c
@@ -1,14 +1,13 @@
 // RUN: clang -O0 -fprofile-instr-generate -fcoverage-mapping \
-// RUN:        %S/Inputs/myprogram.c %S/Inputs/fb.c -o %t.hex
-// RUN: env LLVM_PROFILE_FILE=%t.hex.profraw 
+// RUN:        %S/Inputs/merge-same-func-bin1.c %S/Inputs/merge-same-func-bin1-2.c -o %t.hex
 // RUN: %t.hex
+// RUN: cp default.profraw %t.hex.profraw 
 //
 //---------------- build & run the “x86” variant ------------------------------//
 // RUN: clang -O0 -fprofile-instr-generate -fcoverage-mapping \
-// RUN:        %S/Inputs/mypg.c %S/Inputs/fb.c -o %t.x86
-// RUN: env LLVM_PROFILE_FILE=%t.x86.profraw 
+// RUN:        %S/Inputs/merge-same-func-bin2.c %S/Inputs/merge-same-func-bin1-2.c -o %t.x86
 // RUN: %t.x86 || true
-//
+// RUN: cp default.profraw %t.x86.profraw  
 //---------------- merge the raw profiles ------------------------------------//
 // RUN: llvm-profdata merge --object-aware-hashing=%t.x86 %t.x86.profraw \
 // RUN:                     --object-aware-hashing=%t.hex %t.hex.profraw \
@@ -17,18 +16,14 @@
 //---------------- show unified coverage & check -----------------------------//
 // RUN: llvm-cov show -instr-profile=%t.profdata --object=%t.x86 --object=%t.hex --merge-binary-coverage | FileCheck %s
 //
-// CHECK-LABEL: {{.*fb\.c}}:
+// CHECK-LABEL: {{.*merge-same-func-bin1-2\.c}}:
 // CHECK:     1|      1|int foo() { return 0; }
 // CHECK:     2|       |
 // CHECK:     3|      1|int bar() { return 0; }
 // CHECK:     4|       |
 // CHECK:     5|      1|int bun() { return 0; }
 //
-// CHECK-LABEL: {{.*mypg\.c}}:
-// CHECK:     1|      0|int baz() { return 0; }
-// CHECK:     2|      1|int main() { return 1; }
-//
-// CHECK-LABEL: {{.*myprogram\.c}}:
+// CHECK-LABEL: {{.*merge-same-func-bin1\.c}}:
 // CHECK:     1|       |extern int foo();
 // CHECK:     2|       |extern int bar();
 // CHECK:     3|       |extern int bun();
@@ -37,3 +32,7 @@
 // CHECK:     6|      1|int main()
 // CHECK:     7|      1|  return foo() + bar() + bun();
 // CHECK:     8|      1|}
+//
+// CHECK-LABEL: {{.*merge-same-func-bin2\.c}}:
+// CHECK:     1|      0|int baz() { return 0; }
+// CHECK:     2|      1|int main() { return 1; }
diff --git a/llvm/test/tools/llvm-cov/merge-show-arch-exec.c b/llvm/test/tools/llvm-cov/merge-show-arch-exec.c
index aae3570042d10..967d5f2604311 100644
--- a/llvm/test/tools/llvm-cov/merge-show-arch-exec.c
+++ b/llvm/test/tools/llvm-cov/merge-show-arch-exec.c
@@ -16,6 +16,7 @@
 //
 // RUN: llvm-cov show -instr-profile=%t.profdata --object=%t.toggle --object=%t.notoggle --merge-binary-coverage --show-arch-executables | FileCheck %s
 
+// CHECK:       |    1|      2|int main() {
 // CHECK:       |    2|      2|int a = 1;
 // CHECK:       |    3|      2|int b = 2;
 // CHECK:       |    4|      2|int res = 0;



More information about the llvm-commits mailing list