Importing rustc-1.78.0

Bug: 333887339
Test: ./build.py --lto=thin
Change-Id: I70466db5e03cbd71cc5874ebae0a6d6c9fece91c
diff --git a/src/llvm-project/llvm/tools/bugpoint-passes/CMakeLists.txt b/src/llvm-project/llvm/tools/bugpoint-passes/CMakeLists.txt
index 6df49d7..60fc1bd 100644
--- a/src/llvm-project/llvm/tools/bugpoint-passes/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/bugpoint-passes/CMakeLists.txt
@@ -10,7 +10,7 @@
   endif()
 endif()
 
-if(WIN32 OR CYGWIN)
+if(WIN32 OR CYGWIN OR ZOS)
   set(LLVM_LINK_COMPONENTS Core Support)
 endif()
 
diff --git a/src/llvm-project/llvm/tools/bugpoint/BugDriver.h b/src/llvm-project/llvm/tools/bugpoint/BugDriver.h
index 9fb0880..e3117ec 100644
--- a/src/llvm-project/llvm/tools/bugpoint/BugDriver.h
+++ b/src/llvm-project/llvm/tools/bugpoint/BugDriver.h
@@ -25,7 +25,6 @@
 
 namespace llvm {
 
-class PassInfo;
 class Module;
 class GlobalVariable;
 class Function;
diff --git a/src/llvm-project/llvm/tools/bugpoint/ExecutionDriver.cpp b/src/llvm-project/llvm/tools/bugpoint/ExecutionDriver.cpp
index 2b06e8f..18187ad 100644
--- a/src/llvm-project/llvm/tools/bugpoint/ExecutionDriver.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/ExecutionDriver.cpp
@@ -299,7 +299,7 @@
              << "!\n";
       exit(1);
     }
-    BitcodeFile = std::string(UniqueFilename.str());
+    BitcodeFile = std::string(UniqueFilename);
 
     if (writeProgramToFile(BitcodeFile, UniqueFD, Program)) {
       errs() << ToolName << ": Error emitting bitcode to file '" << BitcodeFile
@@ -324,7 +324,7 @@
            << "\n";
     exit(1);
   }
-  OutputFile = std::string(UniqueFile.str());
+  OutputFile = std::string(UniqueFile);
 
   // Figure out which shared objects to run, if any.
   std::vector<std::string> SharedObjs(AdditionalSOs);
diff --git a/src/llvm-project/llvm/tools/bugpoint/Miscompilation.cpp b/src/llvm-project/llvm/tools/bugpoint/Miscompilation.cpp
index 3882194..22806ba 100644
--- a/src/llvm-project/llvm/tools/bugpoint/Miscompilation.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/Miscompilation.cpp
@@ -830,8 +830,8 @@
   // Add the resolver to the Safe module.
   // Prototype: void *getPointerToNamedFunction(const char* Name)
   FunctionCallee resolverFunc = Safe->getOrInsertFunction(
-      "getPointerToNamedFunction", Type::getInt8PtrTy(Safe->getContext()),
-      Type::getInt8PtrTy(Safe->getContext()));
+      "getPointerToNamedFunction", PointerType::getUnqual(Safe->getContext()),
+      PointerType::getUnqual(Safe->getContext()));
 
   // Use the function we just added to get addresses of functions we need.
   for (Module::iterator F = Safe->begin(), E = Safe->end(); F != E; ++F) {
@@ -956,8 +956,7 @@
            << "Error making unique filename: " << EC.message() << "\n";
     exit(1);
   }
-  if (BD.writeProgramToFile(std::string(TestModuleBC.str()), TestModuleFD,
-                            *Test)) {
+  if (BD.writeProgramToFile(std::string(TestModuleBC), TestModuleFD, *Test)) {
     errs() << "Error writing bitcode to `" << TestModuleBC.str()
            << "'\nExiting.";
     exit(1);
@@ -976,8 +975,7 @@
     exit(1);
   }
 
-  if (BD.writeProgramToFile(std::string(SafeModuleBC.str()), SafeModuleFD,
-                            *Safe)) {
+  if (BD.writeProgramToFile(std::string(SafeModuleBC), SafeModuleFD, *Safe)) {
     errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
     exit(1);
   }
@@ -985,7 +983,7 @@
   FileRemover SafeModuleBCRemover(SafeModuleBC.str(), !SaveTemps);
 
   Expected<std::string> SharedObject =
-      BD.compileSharedObject(std::string(SafeModuleBC.str()));
+      BD.compileSharedObject(std::string(SafeModuleBC));
   if (Error E = SharedObject.takeError())
     return std::move(E);
 
@@ -994,7 +992,7 @@
   // Run the code generator on the `Test' code, loading the shared library.
   // The function returns whether or not the new output differs from reference.
   Expected<bool> Result = BD.diffProgram(
-      BD.getProgram(), std::string(TestModuleBC.str()), *SharedObject, false);
+      BD.getProgram(), std::string(TestModuleBC), *SharedObject, false);
   if (Error E = Result.takeError())
     return std::move(E);
 
@@ -1051,8 +1049,7 @@
     exit(1);
   }
 
-  if (writeProgramToFile(std::string(TestModuleBC.str()), TestModuleFD,
-                         *ToCodeGen)) {
+  if (writeProgramToFile(std::string(TestModuleBC), TestModuleFD, *ToCodeGen)) {
     errs() << "Error writing bitcode to `" << TestModuleBC << "'\nExiting.";
     exit(1);
   }
@@ -1068,13 +1065,13 @@
     exit(1);
   }
 
-  if (writeProgramToFile(std::string(SafeModuleBC.str()), SafeModuleFD,
+  if (writeProgramToFile(std::string(SafeModuleBC), SafeModuleFD,
                          *ToNotCodeGen)) {
     errs() << "Error writing bitcode to `" << SafeModuleBC << "'\nExiting.";
     exit(1);
   }
   Expected<std::string> SharedObject =
-      compileSharedObject(std::string(SafeModuleBC.str()));
+      compileSharedObject(std::string(SafeModuleBC));
   if (Error E = SharedObject.takeError())
     return E;
 
diff --git a/src/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp b/src/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp
index f7239f5..ce32459 100644
--- a/src/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp
@@ -141,7 +141,7 @@
            << ": Error making unique filename: " << EC.message() << "\n";
     return true;
   }
-  OutputFilename = std::string(UniqueFilename.str());
+  OutputFilename = std::string(UniqueFilename);
 
   // set up the input file name
   Expected<sys::fs::TempFile> Temp =
diff --git a/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp b/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
index c6733ae..e45c89b 100644
--- a/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
@@ -442,7 +442,7 @@
     errs() << "Error making unique filename: " << EC.message() << "\n";
     exit(1);
   }
-  OutputAsmFile = std::string(UniqueFile.str());
+  OutputAsmFile = std::string(UniqueFile);
   std::vector<StringRef> LLCArgs;
   LLCArgs.push_back(LLCPath);
 
@@ -772,7 +772,7 @@
     errs() << "Error making unique filename: " << EC.message() << "\n";
     exit(1);
   }
-  OutputFile = std::string(UniqueFilename.str());
+  OutputFile = std::string(UniqueFilename);
 
   std::vector<StringRef> CCArgs;
 
diff --git a/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.cpp b/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.cpp
index d8293f7..646fe4f 100644
--- a/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.cpp
@@ -26,7 +26,7 @@
   return {Archive, Object};
 }
 
-static bool isArchive(StringRef Filename) { return Filename.endswith(")"); }
+static bool isArchive(StringRef Filename) { return Filename.ends_with(")"); }
 
 static std::vector<MemoryBufferRef>
 getMachOFatMemoryBuffers(StringRef Filename, MemoryBuffer &Mem,
@@ -182,7 +182,7 @@
 
   for (const auto &Archive : Archives) {
     Error Err = Error::success();
-    for (auto Child : Archive->children(Err)) {
+    for (const auto &Child : Archive->children(Err)) {
       if (auto NameOrErr = Child.getName()) {
         if (*NameOrErr == ObjectFilename) {
           auto ModTimeOrErr = Child.getLastModified();
@@ -238,6 +238,7 @@
   if (isArchive(Filename)) {
     StringRef ArchiveFilename = getArchiveAndObjectName(Filename).first;
     std::lock_guard<std::mutex> Lock(ArchiveCacheMutex);
+    ArchiveRefCounter[ArchiveFilename]++;
     if (ArchiveCache.count(ArchiveFilename)) {
       return ArchiveCache[ArchiveFilename]->getObjectEntry(Filename, Timestamp,
                                                            Verbose);
@@ -258,6 +259,7 @@
   // If this is an object, we might have it cached. If not we'll have to load
   // it from the file system and cache it now.
   std::lock_guard<std::mutex> Lock(ObjectCacheMutex);
+  ObjectRefCounter[Filename]++;
   if (!ObjectCache.count(Filename)) {
     auto OE = std::make_unique<ObjectEntry>();
     auto Err = OE->load(VFS, Filename, Timestamp, Verbose);
@@ -276,5 +278,24 @@
   ObjectCache.clear();
 }
 
+void BinaryHolder::eraseObjectEntry(StringRef Filename) {
+  if (Verbose)
+    WithColor::note() << "erasing '" << Filename << "' from cache\n";
+
+  if (isArchive(Filename)) {
+    StringRef ArchiveFilename = getArchiveAndObjectName(Filename).first;
+    std::lock_guard<std::mutex> Lock(ArchiveCacheMutex);
+    ArchiveRefCounter[ArchiveFilename]--;
+    if (ArchiveRefCounter[ArchiveFilename] == 0)
+      ArchiveCache.erase(ArchiveFilename);
+    return;
+  }
+
+  std::lock_guard<std::mutex> Lock(ObjectCacheMutex);
+  ObjectRefCounter[Filename]--;
+  if (ObjectRefCounter[Filename] == 0)
+    ObjectCache.erase(Filename);
+}
+
 } // namespace dsymutil
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.h b/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.h
index 84084c5..c4fc5a6 100644
--- a/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.h
+++ b/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.h
@@ -126,15 +126,18 @@
   getObjectEntry(StringRef Filename, TimestampTy Timestamp = TimestampTy());
 
   void clear();
+  void eraseObjectEntry(StringRef Filename);
 
 private:
   /// Cache of static archives. Objects that are part of a static archive are
   /// stored under this object, rather than in the map below.
   StringMap<std::unique_ptr<ArchiveEntry>> ArchiveCache;
+  StringMap<uint32_t> ArchiveRefCounter;
   std::mutex ArchiveCacheMutex;
 
   /// Object entries for objects that are not in a static archive.
   StringMap<std::unique_ptr<ObjectEntry>> ObjectCache;
+  StringMap<uint32_t> ObjectRefCounter;
   std::mutex ObjectCacheMutex;
 
   /// Virtual File System instance.
diff --git a/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt b/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt
index 3cb88a5..53f882e 100644
--- a/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt
@@ -10,6 +10,7 @@
   CodeGen
   CodeGenTypes
   DWARFLinker
+  DWARFLinkerClassic
   DWARFLinkerParallel
   DebugInfoDWARF
   MC
@@ -30,16 +31,18 @@
   MachODebugMapParser.cpp
   MachOUtils.cpp
   Reproducer.cpp
+  RelocationMap.cpp
   SymbolMap.cpp
 
   DEPENDS
   intrinsics_gen
   ${tablegen_deps}
   DsymutilTableGen
+  GENERATE_DRIVER
   )
 
-if(APPLE)
+if(APPLE AND NOT LLVM_TOOL_LLVM_DRIVER_BUILD)
   target_link_libraries(dsymutil PRIVATE "-framework CoreFoundation")
-endif(APPLE)
+endif(APPLE AND NOT LLVM_TOOL_LLVM_DRIVER_BUILD)
 
 # target_link_libraries(dsymutil PRIVATE ${LLVM_ATOMIC_LIB})
diff --git a/src/llvm-project/llvm/tools/dsymutil/DebugMap.cpp b/src/llvm-project/llvm/tools/dsymutil/DebugMap.cpp
index 5ae7217..8724b70 100644
--- a/src/llvm-project/llvm/tools/dsymutil/DebugMap.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/DebugMap.cpp
@@ -11,7 +11,6 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/iterator_range.h"
 #include "llvm/BinaryFormat/MachO.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/Chrono.h"
@@ -46,6 +45,11 @@
 bool DebugMapObject::addSymbol(StringRef Name,
                                std::optional<uint64_t> ObjectAddress,
                                uint64_t LinkedAddress, uint32_t Size) {
+  if (Symbols.count(Name)) {
+    // Symbol was previously added.
+    return true;
+  }
+
   auto InsertResult = Symbols.insert(
       std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));
 
@@ -54,6 +58,12 @@
   return InsertResult.second;
 }
 
+void DebugMapObject::setRelocationMap(dsymutil::RelocationMap &RM) {
+  RelocMap.emplace(RM);
+}
+
+void DebugMapObject::setInstallName(StringRef IN) { InstallName.emplace(IN); }
+
 void DebugMapObject::print(raw_ostream &OS) const {
   OS << getObjectFilename() << ":\n";
   // Sort the symbols in alphabetical order, like llvm-nm (and to get
@@ -159,8 +169,8 @@
   std::vector<dsymutil::DebugMapObject::YAMLSymbolMapping> Entries;
 };
 
-void MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>>::
-    mapping(IO &io, std::pair<std::string, DebugMapObject::SymbolMapping> &s) {
+void MappingTraits<std::pair<std::string, SymbolMapping>>::mapping(
+    IO &io, std::pair<std::string, SymbolMapping> &s) {
   io.mapRequired("sym", s.first);
   io.mapOptional("objAddr", s.second.ObjectAddress);
   io.mapRequired("binAddr", s.second.BinaryAddress);
@@ -276,7 +286,13 @@
     }
   }
 
-  dsymutil::DebugMapObject Res(Path, sys::toTimePoint(Timestamp), MachO::N_OSO);
+  uint8_t Type = MachO::N_OSO;
+  if (Path.ends_with(".dylib")) {
+    // FIXME: find a more resilient way
+    Type = MachO::N_LIB;
+  }
+  dsymutil::DebugMapObject Res(Path, sys::toTimePoint(Timestamp), Type);
+
   for (auto &Entry : Entries) {
     auto &Mapping = Entry.second;
     std::optional<uint64_t> ObjAddress;
diff --git a/src/llvm-project/llvm/tools/dsymutil/DebugMap.h b/src/llvm-project/llvm/tools/dsymutil/DebugMap.h
index 86cb88d..9c3a698 100644
--- a/src/llvm-project/llvm/tools/dsymutil/DebugMap.h
+++ b/src/llvm-project/llvm/tools/dsymutil/DebugMap.h
@@ -21,6 +21,7 @@
 #ifndef LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
 #define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
 
+#include "RelocationMap.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
@@ -134,22 +135,6 @@
 /// linked binary for all the linked atoms in this object file.
 class DebugMapObject {
 public:
-  struct SymbolMapping {
-    std::optional<yaml::Hex64> ObjectAddress;
-    yaml::Hex64 BinaryAddress;
-    yaml::Hex32 Size;
-
-    SymbolMapping(std::optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
-                  uint32_t Size)
-        : BinaryAddress(BinaryAddress), Size(Size) {
-      if (ObjectAddr)
-        ObjectAddress = *ObjectAddr;
-    }
-
-    /// For YAML IO support
-    SymbolMapping() = default;
-  };
-
   using YAMLSymbolMapping = std::pair<std::string, SymbolMapping>;
   using DebugMapEntry = StringMapEntry<SymbolMapping>;
 
@@ -182,6 +167,16 @@
   }
   const std::vector<std::string> &getWarnings() const { return Warnings; }
 
+  const std::optional<RelocationMap> &getRelocationMap() const {
+    return RelocMap;
+  }
+  void setRelocationMap(dsymutil::RelocationMap &RM);
+
+  const std::optional<std::string> &getInstallName() const {
+    return InstallName;
+  }
+  void setInstallName(StringRef IN);
+
   void print(raw_ostream &OS) const;
 #ifndef NDEBUG
   void dump() const;
@@ -196,10 +191,13 @@
 
   std::string Filename;
   sys::TimePoint<std::chrono::seconds> Timestamp;
-  StringMap<SymbolMapping> Symbols;
+  StringMap<struct SymbolMapping> Symbols;
   DenseMap<uint64_t, DebugMapEntry *> AddressToMapping;
   uint8_t Type;
 
+  std::optional<RelocationMap> RelocMap;
+  std::optional<std::string> InstallName;
+
   std::vector<std::string> Warnings;
 
   /// For YAMLIO support.
@@ -225,10 +223,8 @@
 
 using namespace llvm::dsymutil;
 
-template <>
-struct MappingTraits<std::pair<std::string, DebugMapObject::SymbolMapping>> {
-  static void mapping(IO &io,
-                      std::pair<std::string, DebugMapObject::SymbolMapping> &s);
+template <> struct MappingTraits<std::pair<std::string, SymbolMapping>> {
+  static void mapping(IO &io, std::pair<std::string, SymbolMapping> &s);
   static const bool flow = true;
 };
 
@@ -237,12 +233,6 @@
   static void mapping(IO &io, dsymutil::DebugMapObject &DMO);
 };
 
-template <> struct ScalarTraits<Triple> {
-  static void output(const Triple &val, void *, raw_ostream &out);
-  static StringRef input(StringRef scalar, void *, Triple &value);
-  static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
-};
-
 template <>
 struct SequenceTraits<std::vector<std::unique_ptr<dsymutil::DebugMapObject>>> {
   static size_t
diff --git a/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index 4b281d5..5ae5ecd 100644
--- a/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -12,16 +12,11 @@
 #include "MachOUtils.h"
 #include "dsymutil.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/BinaryFormat/Dwarf.h"
@@ -32,8 +27,9 @@
 #include "llvm/CodeGen/DIE.h"
 #include "llvm/CodeGen/NonRelocatableStringpool.h"
 #include "llvm/Config/config.h"
-#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
-#include "llvm/DWARFLinkerParallel/DWARFLinker.h"
+#include "llvm/DWARFLinker/Classic/DWARFLinker.h"
+#include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
+#include "llvm/DWARFLinker/Parallel/DWARFLinker.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
@@ -105,6 +101,8 @@
 
 static mc::RegisterMCTargetOptionsFlags MOF;
 
+using namespace dwarf_linker;
+
 namespace dsymutil {
 
 static void dumpDIE(const DWARFDie *DIE, bool Verbose) {
@@ -123,16 +121,22 @@
 /// specific \p DIE related to the warning.
 void DwarfLinkerForBinary::reportWarning(Twine Warning, Twine Context,
                                          const DWARFDie *DIE) const {
-  std::lock_guard<std::mutex> Guard(ErrorHandlerMutex);
-  warn(Warning, Context);
-  dumpDIE(DIE, Options.Verbose);
+  // FIXME: implement warning logging which does not block other threads.
+  if (ErrorHandlerMutex.try_lock()) {
+    warn(Warning, Context);
+    dumpDIE(DIE, Options.Verbose);
+    ErrorHandlerMutex.unlock();
+  }
 }
 
 void DwarfLinkerForBinary::reportError(Twine Error, Twine Context,
                                        const DWARFDie *DIE) const {
-  std::lock_guard<std::mutex> Guard(ErrorHandlerMutex);
-  error(Error, Context);
-  dumpDIE(DIE, Options.Verbose);
+  // FIXME: implement error logging which does not block other threads.
+  if (ErrorHandlerMutex.try_lock()) {
+    error(Error, Context);
+    dumpDIE(DIE, Options.Verbose);
+    ErrorHandlerMutex.unlock();
+  }
 }
 
 ErrorOr<const object::ObjectFile &>
@@ -163,7 +167,7 @@
 static Error remarksErrorHandler(const DebugMapObject &DMO,
                                  DwarfLinkerForBinary &Linker,
                                  std::unique_ptr<FileError> FE) {
-  bool IsArchive = DMO.getObjectFilename().endswith(")");
+  bool IsArchive = DMO.getObjectFilename().ends_with(")");
   // Don't report errors for missing remark files from static
   // archives.
   if (!IsArchive)
@@ -184,6 +188,42 @@
 
   return createFileError(FE->getFileName(), std::move(NewE));
 }
+Error DwarfLinkerForBinary::emitRelocations(
+    const DebugMap &DM, std::vector<ObjectWithRelocMap> &ObjectsForLinking) {
+  // Return early if the "Resources" directory is not being written to.
+  if (!Options.ResourceDir)
+    return Error::success();
+
+  RelocationMap RM(DM.getTriple(), DM.getBinaryPath());
+  for (auto &Obj : ObjectsForLinking) {
+    if (!Obj.OutRelocs->isInitialized())
+      continue;
+    Obj.OutRelocs->addValidRelocs(RM);
+  }
+
+  SmallString<128> InputPath;
+  SmallString<128> Path;
+  // Create the "Relocations" directory in the "Resources" directory, and
+  // create an architecture-specific directory in the "Relocations" directory.
+  StringRef ArchName = Triple::getArchName(RM.getTriple().getArch(),
+                                           RM.getTriple().getSubArch());
+  sys::path::append(Path, *Options.ResourceDir, "Relocations", ArchName);
+  if (std::error_code EC = sys::fs::create_directories(Path.str(), true,
+                                                       sys::fs::perms::all_all))
+    return errorCodeToError(EC);
+
+  // Append the file name.
+  sys::path::append(Path, sys::path::filename(DM.getBinaryPath()));
+  Path.append(".yml");
+
+  std::error_code EC;
+  raw_fd_ostream OS(Path.str(), EC, sys::fs::OF_Text);
+  if (EC)
+    return errorCodeToError(EC);
+
+  RM.print(OS);
+  return Error::success();
+}
 
 static Error emitRemarks(const LinkOptions &Options, StringRef BinaryPath,
                          StringRef ArchName, const remarks::RemarkLinker &RL) {
@@ -223,19 +263,32 @@
   return Error::success();
 }
 
-template <typename OutDWARFFile, typename AddressesMap>
-ErrorOr<std::unique_ptr<OutDWARFFile>>
-DwarfLinkerForBinary::loadObject(const DebugMapObject &Obj,
-                                 const DebugMap &DebugMap,
-                                 remarks::RemarkLinker &RL) {
+ErrorOr<std::unique_ptr<DWARFFile>> DwarfLinkerForBinary::loadObject(
+    const DebugMapObject &Obj, const DebugMap &DebugMap,
+    remarks::RemarkLinker &RL,
+    std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM) {
   auto ErrorOrObj = loadObject(Obj, DebugMap.getTriple());
-  std::unique_ptr<OutDWARFFile> Res;
+  std::unique_ptr<DWARFFile> Res;
 
   if (ErrorOrObj) {
-    Res = std::make_unique<OutDWARFFile>(
-        Obj.getObjectFilename(), DWARFContext::create(*ErrorOrObj),
-        std::make_unique<AddressesMap>(*this, *ErrorOrObj, Obj),
-        Obj.empty() ? Obj.getWarnings() : EmptyWarnings);
+    auto Context = DWARFContext::create(
+        *ErrorOrObj, DWARFContext::ProcessDebugRelocations::Process, nullptr,
+        "",
+        [&](Error Err) {
+          handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
+            reportError(Info.message());
+          });
+        },
+        [&](Error Warning) {
+          handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
+            reportWarning(Info.message());
+          });
+        });
+    DLBRM->init(*Context);
+    Res = std::make_unique<DWARFFile>(
+        Obj.getObjectFilename(), std::move(Context),
+        std::make_unique<AddressManager>(*this, *ErrorOrObj, Obj, DLBRM),
+        [&](StringRef FileName) { BinHolder.eraseObjectEntry(FileName); });
 
     Error E = RL.link(*ErrorOrObj);
     if (Error NewE = handleErrors(
@@ -256,7 +309,7 @@
   // need to copy them to the .dSYM. Only copy them for binaries where the
   // linker omitted the reflection metadata.
   if (!Map.getBinaryPath().empty() &&
-      Options.FileType == DWARFLinker::OutputFileType::Object) {
+      Options.FileType == DWARFLinkerBase::OutputFileType::Object) {
 
     auto ObjectEntry = BinHolder.getObjectEntry(Map.getBinaryPath());
     // If ObjectEntry or Object has an error, no binary exists, therefore no
@@ -480,9 +533,8 @@
   return Error::success();
 }
 
-template <typename OutStreamer>
 void DwarfLinkerForBinary::copySwiftReflectionMetadata(
-    const llvm::dsymutil::DebugMapObject *Obj, OutStreamer *Streamer,
+    const llvm::dsymutil::DebugMapObject *Obj, classic::DwarfStreamer *Streamer,
     std::vector<uint64_t> &SectionToOffsetInDwarf,
     std::vector<MachOUtils::DwarfRelocationApplicationInfo>
         &RelocationsToApply) {
@@ -540,28 +592,10 @@
 }
 
 bool DwarfLinkerForBinary::link(const DebugMap &Map) {
-  if (Options.DWARFLinkerType == DsymutilDWARFLinkerType::LLVM) {
-    dwarflinker_parallel::DWARFLinker::OutputFileType DWARFLinkerOutputType;
-    switch (Options.FileType) {
-    case DWARFLinker::OutputFileType::Object:
-      DWARFLinkerOutputType =
-          dwarflinker_parallel::DWARFLinker::OutputFileType::Object;
-      break;
+  if (Options.DWARFLinkerType == DsymutilDWARFLinkerType::Parallel)
+    return linkImpl<parallel::DWARFLinker>(Map, Options.FileType);
 
-    case DWARFLinker::OutputFileType::Assembly:
-      DWARFLinkerOutputType =
-          dwarflinker_parallel::DWARFLinker::OutputFileType::Assembly;
-      break;
-    }
-
-    return linkImpl<dwarflinker_parallel::DWARFLinker,
-                    dwarflinker_parallel::DWARFFile,
-                    AddressManager<dwarflinker_parallel::AddressesMap>>(
-        Map, DWARFLinkerOutputType);
-  }
-
-  return linkImpl<DWARFLinker, DWARFFile, AddressManager<AddressesMap>>(
-      Map, Options.FileType);
+  return linkImpl<classic::DWARFLinker>(Map, Options.FileType);
 }
 
 template <typename Linker>
@@ -592,11 +626,11 @@
   llvm_unreachable("All cases handled above!");
 }
 
-template <typename Linker, typename OutDwarfFile, typename AddressMap>
+template <typename Linker>
 bool DwarfLinkerForBinary::linkImpl(
     const DebugMap &Map, typename Linker::OutputFileType ObjectType) {
 
-  std::vector<std::unique_ptr<OutDwarfFile>> ObjectsForLinking;
+  std::vector<ObjectWithRelocMap> ObjectsForLinking;
 
   DebugMap DebugMap(Map.getTriple(), Map.getBinaryPath());
 
@@ -614,14 +648,32 @@
       },
       Options.Translator ? TranslationLambda : nullptr);
 
+  std::unique_ptr<classic::DwarfStreamer> Streamer;
   if (!Options.NoOutput) {
-    if (Error Err = GeneralLinker->createEmitter(Map.getTriple(), ObjectType,
-                                                 OutFile)) {
-      handleAllErrors(std::move(Err), [&](const ErrorInfoBase &EI) {
+    if (Expected<std::unique_ptr<classic::DwarfStreamer>> StreamerOrErr =
+            classic::DwarfStreamer::createStreamer(
+                Map.getTriple(), ObjectType, OutFile, Options.Translator,
+                [&](const Twine &Warning, StringRef Context,
+                    const DWARFDie *DIE) {
+                  reportWarning(Warning, Context, DIE);
+                }))
+      Streamer = std::move(*StreamerOrErr);
+    else {
+      handleAllErrors(StreamerOrErr.takeError(), [&](const ErrorInfoBase &EI) {
         reportError(EI.message(), "dwarf streamer init");
       });
       return false;
     }
+
+    if constexpr (std::is_same<Linker, parallel::DWARFLinker>::value) {
+      GeneralLinker->setOutputDWARFHandler(
+          Map.getTriple(),
+          [&](std::shared_ptr<parallel::SectionDescriptorBase> Section) {
+            Streamer->emitSectionContents(Section->getContents(),
+                                          Section->getKind());
+          });
+    } else
+      GeneralLinker->setOutputDWARFEmitter(Streamer.get());
   }
 
   remarks::RemarkLinker RL;
@@ -638,24 +690,29 @@
   GeneralLinker->setNumThreads(Options.Threads);
   GeneralLinker->setPrependPath(Options.PrependPath);
   GeneralLinker->setKeepFunctionForStatic(Options.KeepFunctionForStatic);
-  GeneralLinker->setInputVerificationHandler([&](const OutDwarfFile &File) {
-    reportWarning("input verification failed", File.FileName);
-    HasVerificationErrors = true;
-  });
+  GeneralLinker->setInputVerificationHandler(
+      [&](const DWARFFile &File, llvm::StringRef Output) {
+        std::lock_guard<std::mutex> Guard(ErrorHandlerMutex);
+        if (Options.Verbose)
+          errs() << Output;
+        warn("input verification failed", File.FileName);
+        HasVerificationErrors = true;
+      });
   auto Loader = [&](StringRef ContainerName,
-                    StringRef Path) -> ErrorOr<OutDwarfFile &> {
+                    StringRef Path) -> ErrorOr<DWARFFile &> {
     auto &Obj = DebugMap.addDebugMapObject(
         Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
 
-    if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
-            loadObject<OutDwarfFile, AddressMap>(Obj, DebugMap, RL)) {
-      ObjectsForLinking.emplace_back(std::move(*ErrorOrObj));
-      return *ObjectsForLinking.back();
+    auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();
+    if (ErrorOr<std::unique_ptr<DWARFFile>> ErrorOrObj =
+            loadObject(Obj, DebugMap, RL, DLBRelocMap)) {
+      ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);
+      return *ObjectsForLinking.back().Object;
     } else {
       // Try and emit more helpful warnings by applying some heuristics.
       StringRef ObjFile = ContainerName;
       bool IsClangModule = sys::path::extension(Path).equals(".pcm");
-      bool IsArchive = ObjFile.endswith(")");
+      bool IsArchive = ObjFile.ends_with(")");
 
       if (IsClangModule) {
         StringRef ModuleCacheDir = sys::path::parent_path(Path);
@@ -709,7 +766,7 @@
     auto SectionToOffsetInDwarf =
         calculateStartOfStrippableReflectionSections(Map);
     for (const auto &Obj : Map.objects())
-      copySwiftReflectionMetadata(Obj.get(), GeneralLinker->getEmitter(),
+      copySwiftReflectionMetadata(Obj.get(), Streamer.get(),
                                   SectionToOffsetInDwarf, RelocationsToApply);
   }
 
@@ -756,21 +813,23 @@
 
       // Copy the module into the .swift_ast section.
       if (!Options.NoOutput)
-        GeneralLinker->getEmitter()->emitSwiftAST((*ErrorOrMem)->getBuffer());
+        Streamer->emitSwiftAST((*ErrorOrMem)->getBuffer());
 
       continue;
     }
 
-    if (ErrorOr<std::unique_ptr<OutDwarfFile>> ErrorOrObj =
-            loadObject<OutDwarfFile, AddressMap>(*Obj, Map, RL)) {
-      ObjectsForLinking.emplace_back(std::move(*ErrorOrObj));
-      GeneralLinker->addObjectFile(*ObjectsForLinking.back(), Loader,
+    auto DLBRelocMap = std::make_shared<DwarfLinkerForBinaryRelocationMap>();
+    if (ErrorOr<std::unique_ptr<DWARFFile>> ErrorOrObj =
+            loadObject(*Obj, Map, RL, DLBRelocMap)) {
+      ObjectsForLinking.emplace_back(std::move(*ErrorOrObj), DLBRelocMap);
+      GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object, Loader,
                                    OnCUDieLoaded);
     } else {
-      ObjectsForLinking.push_back(std::make_unique<OutDwarfFile>(
-          Obj->getObjectFilename(), nullptr, nullptr,
-          Obj->empty() ? Obj->getWarnings() : EmptyWarnings));
-      GeneralLinker->addObjectFile(*ObjectsForLinking.back());
+      ObjectsForLinking.push_back(
+          {std::make_unique<DWARFFile>(Obj->getObjectFilename(), nullptr,
+                                       nullptr),
+           DLBRelocMap});
+      GeneralLinker->addObjectFile(*ObjectsForLinking.back().Object);
     }
   }
 
@@ -795,6 +854,9 @@
   if (Options.NoOutput)
     return true;
 
+  if (Error E = emitRelocations(Map, ObjectsForLinking))
+    return error(toString(std::move(E)));
+
   if (Options.ResourceDir && !ParseableSwiftInterfaces.empty()) {
     StringRef ArchName = Triple::getArchTypeName(Map.getTriple().getArch());
     if (auto E = copySwiftInterfaces(ArchName))
@@ -805,22 +867,18 @@
       ObjectType == Linker::OutputFileType::Object)
     return MachOUtils::generateDsymCompanion(
         Options.VFS, Map, Options.Translator,
-        *GeneralLinker->getEmitter()->getAsmPrinter().OutStreamer, OutFile,
-        RelocationsToApply);
+        *Streamer->getAsmPrinter().OutStreamer, OutFile, RelocationsToApply);
 
-  GeneralLinker->getEmitter()->finish();
+  Streamer->finish();
   return true;
 }
 
 /// Iterate over the relocations of the given \p Section and
 /// store the ones that correspond to debug map entries into the
 /// ValidRelocs array.
-template <typename AddressesMapBase>
-void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
-    findValidRelocsMachO(const object::SectionRef &Section,
-                         const object::MachOObjectFile &Obj,
-                         const DebugMapObject &DMO,
-                         std::vector<ValidReloc> &ValidRelocs) {
+void DwarfLinkerForBinary::AddressManager::findValidRelocsMachO(
+    const object::SectionRef &Section, const object::MachOObjectFile &Obj,
+    const DebugMapObject &DMO, std::vector<ValidReloc> &ValidRelocs) {
   Expected<StringRef> ContentsOrErr = Section.getContents();
   if (!ContentsOrErr) {
     consumeError(ContentsOrErr.takeError());
@@ -883,20 +941,21 @@
         continue;
       }
       if (const auto *Mapping = DMO.lookupSymbol(*SymbolName))
-        ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping);
+        ValidRelocs.emplace_back(Offset64, RelocSize, Addend, Mapping->getKey(),
+                                 Mapping->getValue());
     } else if (const auto *Mapping = DMO.lookupObjectAddress(SymAddress)) {
       // Do not store the addend. The addend was the address of the symbol in
       // the object file, the address in the binary that is stored in the debug
       // map doesn't need to be offset.
-      ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset, Mapping);
+      ValidRelocs.emplace_back(Offset64, RelocSize, SymOffset,
+                               Mapping->getKey(), Mapping->getValue());
     }
   }
 }
 
 /// Dispatch the valid relocation finding logic to the
 /// appropriate handler depending on the object file format.
-template <typename AddressesMapBase>
-bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::findValidRelocs(
+bool DwarfLinkerForBinary::AddressManager::findValidRelocs(
     const object::SectionRef &Section, const object::ObjectFile &Obj,
     const DebugMapObject &DMO, std::vector<ValidReloc> &Relocs) {
   // Dispatch to the right handler depending on the file type.
@@ -921,10 +980,8 @@
 /// entries in the debug map. These relocations will drive the Dwarf link by
 /// indicating which DIEs refer to symbols present in the linked binary.
 /// \returns whether there are any valid relocations in the debug info.
-template <typename AddressesMapBase>
-bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
-    findValidRelocsInDebugSections(const object::ObjectFile &Obj,
-                                   const DebugMapObject &DMO) {
+bool DwarfLinkerForBinary::AddressManager::findValidRelocsInDebugSections(
+    const object::ObjectFile &Obj, const DebugMapObject &DMO) {
   // Find the debug_info section.
   bool FoundValidRelocs = false;
   for (const object::SectionRef &Section : Obj.sections()) {
@@ -945,21 +1002,16 @@
   return FoundValidRelocs;
 }
 
-template <typename AddressesMapBase>
-std::vector<
-    typename DwarfLinkerForBinary::AddressManager<AddressesMapBase>::ValidReloc>
-DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocations(
+std::vector<ValidReloc> DwarfLinkerForBinary::AddressManager::getRelocations(
     const std::vector<ValidReloc> &Relocs, uint64_t StartPos, uint64_t EndPos) {
-  std::vector<
-      DwarfLinkerForBinary::AddressManager<AddressesMapBase>::ValidReloc>
-      Res;
+  std::vector<ValidReloc> Res;
 
   auto CurReloc = partition_point(Relocs, [StartPos](const ValidReloc &Reloc) {
-    return Reloc.Offset < StartPos;
+    return (uint64_t)Reloc.Offset < StartPos;
   });
 
   while (CurReloc != Relocs.end() && CurReloc->Offset >= StartPos &&
-         CurReloc->Offset < EndPos) {
+         (uint64_t)CurReloc->Offset < EndPos) {
     Res.push_back(*CurReloc);
     CurReloc++;
   }
@@ -967,40 +1019,35 @@
   return Res;
 }
 
-template <typename AddressesMapBase>
-void DwarfLinkerForBinary::AddressManager<AddressesMapBase>::printReloc(
-    const ValidReloc &Reloc) {
-  const auto &Mapping = Reloc.Mapping->getValue();
+void DwarfLinkerForBinary::AddressManager::printReloc(const ValidReloc &Reloc) {
+  const auto &Mapping = Reloc.SymbolMapping;
   const uint64_t ObjectAddress = Mapping.ObjectAddress
                                      ? uint64_t(*Mapping.ObjectAddress)
                                      : std::numeric_limits<uint64_t>::max();
 
-  outs() << "Found valid debug map entry: " << Reloc.Mapping->getKey() << "\t"
+  outs() << "Found valid debug map entry: " << Reloc.SymbolName << "\t"
          << format("0x%016" PRIx64 " => 0x%016" PRIx64 "\n", ObjectAddress,
                    uint64_t(Mapping.BinaryAddress));
 }
 
-template <typename AddressesMapBase>
-int64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::getRelocValue(
-    const ValidReloc &Reloc) {
+int64_t
+DwarfLinkerForBinary::AddressManager::getRelocValue(const ValidReloc &Reloc) {
   int64_t AddrAdjust = relocate(Reloc);
-  if (Reloc.Mapping->getValue().ObjectAddress)
-    AddrAdjust -= uint64_t(*Reloc.Mapping->getValue().ObjectAddress);
+  if (Reloc.SymbolMapping.ObjectAddress)
+    AddrAdjust -= uint64_t(*Reloc.SymbolMapping.ObjectAddress);
   return AddrAdjust;
 }
 
-template <typename AddressesMapBase>
 std::optional<int64_t>
-DwarfLinkerForBinary::AddressManager<AddressesMapBase>::hasValidRelocationAt(
+DwarfLinkerForBinary::AddressManager::hasValidRelocationAt(
     const std::vector<ValidReloc> &AllRelocs, uint64_t StartOffset,
-    uint64_t EndOffset) {
+    uint64_t EndOffset, bool Verbose) {
   std::vector<ValidReloc> Relocs =
       getRelocations(AllRelocs, StartOffset, EndOffset);
-
   if (Relocs.size() == 0)
     return std::nullopt;
 
-  if (Linker.Options.Verbose)
+  if (Verbose)
     printReloc(Relocs[0]);
 
   return getRelocValue(Relocs[0]);
@@ -1027,34 +1074,37 @@
   return std::make_pair(Offset, End);
 }
 
-template <typename AddressesMapBase>
-std::optional<int64_t> DwarfLinkerForBinary::AddressManager<AddressesMapBase>::
-    getExprOpAddressRelocAdjustment(DWARFUnit &U,
-                                    const DWARFExpression::Operation &Op,
-                                    uint64_t StartOffset, uint64_t EndOffset) {
+std::optional<int64_t>
+DwarfLinkerForBinary::AddressManager::getExprOpAddressRelocAdjustment(
+    DWARFUnit &U, const DWARFExpression::Operation &Op, uint64_t StartOffset,
+    uint64_t EndOffset, bool Verbose) {
   switch (Op.getCode()) {
   default: {
     assert(false && "Specified operation does not have address operand");
   } break;
+  case dwarf::DW_OP_const2u:
   case dwarf::DW_OP_const4u:
   case dwarf::DW_OP_const8u:
+  case dwarf::DW_OP_const2s:
   case dwarf::DW_OP_const4s:
   case dwarf::DW_OP_const8s:
   case dwarf::DW_OP_addr: {
-    return hasValidRelocationAt(ValidDebugInfoRelocs, StartOffset, EndOffset);
+    return hasValidRelocationAt(ValidDebugInfoRelocs, StartOffset, EndOffset,
+                                Verbose);
   } break;
   case dwarf::DW_OP_constx:
   case dwarf::DW_OP_addrx: {
-    return hasValidRelocationAt(ValidDebugAddrRelocs, StartOffset, EndOffset);
+    return hasValidRelocationAt(ValidDebugAddrRelocs, StartOffset, EndOffset,
+                                Verbose);
   } break;
   }
 
   return std::nullopt;
 }
 
-template <typename AddressesMapBase>
-std::optional<int64_t> DwarfLinkerForBinary::AddressManager<
-    AddressesMapBase>::getSubprogramRelocAdjustment(const DWARFDie &DIE) {
+std::optional<int64_t>
+DwarfLinkerForBinary::AddressManager::getSubprogramRelocAdjustment(
+    const DWARFDie &DIE, bool Verbose) {
   const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
 
   std::optional<uint32_t> LowPcIdx =
@@ -1071,7 +1121,7 @@
     std::tie(LowPcOffset, LowPcEndOffset) =
         getAttributeOffsets(Abbrev, *LowPcIdx, Offset, *DIE.getDwarfUnit());
     return hasValidRelocationAt(ValidDebugInfoRelocs, LowPcOffset,
-                                LowPcEndOffset);
+                                LowPcEndOffset, Verbose);
   }
   case dwarf::DW_FORM_addrx:
   case dwarf::DW_FORM_addrx1:
@@ -1082,9 +1132,9 @@
     if (std::optional<uint64_t> AddressOffset =
             DIE.getDwarfUnit()->getIndexedAddressOffset(
                 AddrValue->getRawUValue()))
-      return hasValidRelocationAt(ValidDebugAddrRelocs, *AddressOffset,
-                                  *AddressOffset +
-                                      DIE.getDwarfUnit()->getAddressByteSize());
+      return hasValidRelocationAt(
+          ValidDebugAddrRelocs, *AddressOffset,
+          *AddressOffset + DIE.getDwarfUnit()->getAddressByteSize(), Verbose);
 
     Linker.reportWarning("no base offset for address table", SrcFileName);
     return std::nullopt;
@@ -1094,12 +1144,32 @@
   }
 }
 
-template <typename AddressesMapBase>
-uint64_t DwarfLinkerForBinary::AddressManager<AddressesMapBase>::relocate(
-    const ValidReloc &Reloc) const {
-  return Reloc.Mapping->getValue().BinaryAddress + Reloc.Addend;
+std::optional<StringRef>
+DwarfLinkerForBinary::AddressManager::getLibraryInstallName() {
+  return LibInstallName;
 }
 
+uint64_t
+DwarfLinkerForBinary::AddressManager::relocate(const ValidReloc &Reloc) const {
+  return Reloc.SymbolMapping.BinaryAddress + Reloc.Addend;
+}
+
+void DwarfLinkerForBinary::AddressManager::updateAndSaveValidRelocs(
+    bool IsDWARF5, uint64_t OriginalUnitOffset, int64_t LinkedOffset,
+    uint64_t StartOffset, uint64_t EndOffset) {
+  std::vector<ValidReloc> InRelocs =
+      getRelocations(ValidDebugInfoRelocs, StartOffset, EndOffset);
+  if (IsDWARF5)
+    InRelocs = getRelocations(ValidDebugAddrRelocs, StartOffset, EndOffset);
+  DwarfLinkerRelocMap->updateAndSaveValidRelocs(
+      IsDWARF5, InRelocs, OriginalUnitOffset, LinkedOffset);
+}
+
+void DwarfLinkerForBinary::AddressManager::updateRelocationsWithUnitOffset(
+    uint64_t OriginalUnitOffset, uint64_t OutputUnitOffset) {
+  DwarfLinkerRelocMap->updateRelocationsWithUnitOffset(OriginalUnitOffset,
+                                                       OutputUnitOffset);
+}
 /// Apply the valid relocations found by findValidRelocs() to
 /// the buffer \p Data, taking into account that Data is at \p BaseOffset
 /// in the debug_info section.
@@ -1108,9 +1178,9 @@
 /// monotonic \p BaseOffset values.
 ///
 /// \returns whether any reloc has been applied.
-template <typename AddressesMapBase>
-bool DwarfLinkerForBinary::AddressManager<AddressesMapBase>::applyValidRelocs(
+bool DwarfLinkerForBinary::AddressManager::applyValidRelocs(
     MutableArrayRef<char> Data, uint64_t BaseOffset, bool IsLittleEndian) {
+
   std::vector<ValidReloc> Relocs = getRelocations(
       ValidDebugInfoRelocs, BaseOffset, BaseOffset + Data.size());
 
@@ -1126,9 +1196,47 @@
     assert(CurReloc.Size <= sizeof(Buf));
     memcpy(&Data[CurReloc.Offset - BaseOffset], Buf, CurReloc.Size);
   }
-
   return Relocs.size() > 0;
 }
 
+void DwarfLinkerForBinaryRelocationMap::init(DWARFContext &Context) {
+  for (const std::unique_ptr<DWARFUnit> &CU : Context.compile_units())
+    StoredValidDebugInfoRelocsMap.insert(
+        std::make_pair(CU->getOffset(), std::vector<ValidReloc>()));
+  // FIXME: Support relocations debug_addr (DWARF5).
+}
+
+void DwarfLinkerForBinaryRelocationMap::addValidRelocs(RelocationMap &RM) {
+  for (const auto &DebugInfoRelocs : StoredValidDebugInfoRelocsMap) {
+    for (const auto &InfoReloc : DebugInfoRelocs.second)
+      RM.addRelocationMapEntry(InfoReloc);
+  }
+  // FIXME: Support relocations debug_addr (DWARF5).
+}
+
+void DwarfLinkerForBinaryRelocationMap::updateRelocationsWithUnitOffset(
+    uint64_t OriginalUnitOffset, uint64_t OutputUnitOffset) {
+  std::vector<ValidReloc> &StoredValidDebugInfoRelocs =
+      StoredValidDebugInfoRelocsMap[OriginalUnitOffset];
+  for (ValidReloc &R : StoredValidDebugInfoRelocs) {
+    R.Offset = (uint64_t)R.Offset + OutputUnitOffset;
+  }
+  // FIXME: Support relocations debug_addr (DWARF5).
+}
+
+void DwarfLinkerForBinaryRelocationMap::updateAndSaveValidRelocs(
+    bool IsDWARF5, std::vector<ValidReloc> &InRelocs, uint64_t UnitOffset,
+    int64_t LinkedOffset) {
+  std::vector<ValidReloc> &OutRelocs =
+      StoredValidDebugInfoRelocsMap[UnitOffset];
+  if (IsDWARF5)
+    OutRelocs = StoredValidDebugAddrRelocsMap[UnitOffset];
+
+  for (ValidReloc &R : InRelocs) {
+    OutRelocs.emplace_back(R.Offset + LinkedOffset, R.Size, R.Addend,
+                           R.SymbolName, R.SymbolMapping);
+  }
+}
+
 } // namespace dsymutil
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.h b/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.h
index 230f569..53f9e18 100644
--- a/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.h
+++ b/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.h
@@ -13,18 +13,55 @@
 #include "DebugMap.h"
 #include "LinkUtils.h"
 #include "MachOUtils.h"
-#include "llvm/DWARFLinker/DWARFLinker.h"
-#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
-#include "llvm/DWARFLinker/DWARFLinkerDeclContext.h"
-#include "llvm/DWARFLinker/DWARFStreamer.h"
+#include "RelocationMap.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/Remarks/RemarkFormat.h"
 #include "llvm/Remarks/RemarkLinker.h"
 #include <mutex>
+#include <optional>
 
 namespace llvm {
+using namespace dwarf_linker;
+
 namespace dsymutil {
 
+/// DwarfLinkerForBinaryRelocationMap contains the logic to handle the
+/// relocations and to store them inside an associated RelocationMap.
+class DwarfLinkerForBinaryRelocationMap {
+public:
+  void init(DWARFContext &Context);
+
+  bool isInitialized() {
+    return StoredValidDebugInfoRelocsMap.getMemorySize() != 0;
+  }
+
+  void addValidRelocs(RelocationMap &RM);
+
+  void updateAndSaveValidRelocs(bool IsDWARF5,
+                                std::vector<ValidReloc> &InRelocs,
+                                uint64_t UnitOffset, int64_t LinkedOffset);
+
+  void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+                                       uint64_t OutputUnitOffset);
+
+  /// Map compilation unit offset to the valid relocations to store
+  /// @{
+  DenseMap<uint64_t, std::vector<ValidReloc>> StoredValidDebugInfoRelocsMap;
+  DenseMap<uint64_t, std::vector<ValidReloc>> StoredValidDebugAddrRelocsMap;
+  /// @}
+
+  DwarfLinkerForBinaryRelocationMap() = default;
+};
+
+struct ObjectWithRelocMap {
+  ObjectWithRelocMap(
+      std::unique_ptr<DWARFFile> Object,
+      std::shared_ptr<DwarfLinkerForBinaryRelocationMap> OutRelocs)
+      : Object(std::move(Object)), OutRelocs(OutRelocs) {}
+  std::unique_ptr<DWARFFile> Object;
+  std::shared_ptr<DwarfLinkerForBinaryRelocationMap> OutRelocs;
+};
+
 /// The core of the Dsymutil Dwarf linking logic.
 ///
 /// The link of the dwarf information from the object files will be
@@ -65,28 +102,12 @@
 private:
 
   /// Keeps track of relocations.
-  template <typename AddressesMapBase>
-  class AddressManager : public AddressesMapBase {
-    struct ValidReloc {
-      uint64_t Offset;
-      uint32_t Size;
-      uint64_t Addend;
-      const DebugMapObject::DebugMapEntry *Mapping;
-
-      ValidReloc(uint64_t Offset, uint32_t Size, uint64_t Addend,
-                 const DebugMapObject::DebugMapEntry *Mapping)
-          : Offset(Offset), Size(Size), Addend(Addend), Mapping(Mapping) {}
-
-      bool operator<(const ValidReloc &RHS) const {
-        return Offset < RHS.Offset;
-      }
-      bool operator<(uint64_t RHS) const { return Offset < RHS; }
-    };
+  class AddressManager : public dwarf_linker::AddressesMap {
 
     const DwarfLinkerForBinary &Linker;
 
     /// The valid relocations for the current DebugMapObject.
-    /// This vector is sorted by relocation offset.
+    /// These vectors are sorted by relocation offset.
     /// {
     std::vector<ValidReloc> ValidDebugInfoRelocs;
     std::vector<ValidReloc> ValidDebugAddrRelocs;
@@ -94,6 +115,12 @@
 
     StringRef SrcFileName;
 
+    uint8_t DebugMapObjectType;
+
+    std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DwarfLinkerRelocMap;
+
+    std::optional<std::string> LibInstallName;
+
     /// Returns list of valid relocations from \p Relocs,
     /// between \p StartOffset and \p NextOffset.
     ///
@@ -115,9 +142,29 @@
 
   public:
     AddressManager(DwarfLinkerForBinary &Linker, const object::ObjectFile &Obj,
-                   const DebugMapObject &DMO)
-        : Linker(Linker), SrcFileName(DMO.getObjectFilename()) {
-      findValidRelocsInDebugSections(Obj, DMO);
+                   const DebugMapObject &DMO,
+                   std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM)
+        : Linker(Linker), SrcFileName(DMO.getObjectFilename()),
+          DebugMapObjectType(MachO::N_OSO), DwarfLinkerRelocMap(DLBRM) {
+      if (DMO.getRelocationMap().has_value()) {
+        DebugMapObjectType = MachO::N_LIB;
+        LibInstallName.emplace(DMO.getInstallName().value());
+        const RelocationMap &RM = DMO.getRelocationMap().value();
+        for (const auto &Reloc : RM.relocations()) {
+          const auto *DebugMapEntry = DMO.lookupSymbol(Reloc.SymbolName);
+          if (!DebugMapEntry)
+            continue;
+          std::optional<uint64_t> ObjAddress;
+          ObjAddress.emplace(DebugMapEntry->getValue().ObjectAddress.value());
+          ValidDebugInfoRelocs.emplace_back(
+              Reloc.Offset, Reloc.Size, Reloc.Addend, Reloc.SymbolName,
+              SymbolMapping(ObjAddress, DebugMapEntry->getValue().BinaryAddress,
+                            DebugMapEntry->getValue().Size));
+          // FIXME: Support relocations debug_addr.
+        }
+      } else {
+        findValidRelocsInDebugSections(Obj, DMO);
+      }
     }
     ~AddressManager() override { clear(); }
 
@@ -145,22 +192,35 @@
 
     /// Checks that there is a relocation in the \p Relocs array against a
     /// debug map entry between \p StartOffset and \p NextOffset.
+    /// Print debug output if \p Verbose is set.
     ///
     /// \returns relocation value if relocation exist, otherwise std::nullopt.
     std::optional<int64_t>
     hasValidRelocationAt(const std::vector<ValidReloc> &Relocs,
-                         uint64_t StartOffset, uint64_t EndOffset);
+                         uint64_t StartOffset, uint64_t EndOffset,
+                         bool Verbose);
 
     std::optional<int64_t> getExprOpAddressRelocAdjustment(
         DWARFUnit &U, const DWARFExpression::Operation &Op,
-        uint64_t StartOffset, uint64_t EndOffset) override;
+        uint64_t StartOffset, uint64_t EndOffset, bool Verbose) override;
 
-    std::optional<int64_t>
-    getSubprogramRelocAdjustment(const DWARFDie &DIE) override;
+    std::optional<int64_t> getSubprogramRelocAdjustment(const DWARFDie &DIE,
+                                                        bool Verbose) override;
+
+    std::optional<StringRef> getLibraryInstallName() override;
 
     bool applyValidRelocs(MutableArrayRef<char> Data, uint64_t BaseOffset,
                           bool IsLittleEndian) override;
 
+    bool needToSaveValidRelocs() override { return true; }
+
+    void updateAndSaveValidRelocs(bool IsDWARF5, uint64_t OriginalUnitOffset,
+                                  int64_t LinkedOffset, uint64_t StartOffset,
+                                  uint64_t EndOffset) override;
+
+    void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+                                         uint64_t OutputUnitOffset) override;
+
     void clear() override {
       ValidDebugInfoRelocs.clear();
       ValidDebugAddrRelocs.clear();
@@ -180,11 +240,10 @@
   /// Attempt to load a debug object from disk.
   ErrorOr<const object::ObjectFile &> loadObject(const DebugMapObject &Obj,
                                                  const Triple &triple);
-
-  template <typename OutDWARFFile, typename AddressesMap>
-  ErrorOr<std::unique_ptr<OutDWARFFile>> loadObject(const DebugMapObject &Obj,
-                                                    const DebugMap &DebugMap,
-                                                    remarks::RemarkLinker &RL);
+  ErrorOr<std::unique_ptr<dwarf_linker::DWARFFile>>
+  loadObject(const DebugMapObject &Obj, const DebugMap &DebugMap,
+             remarks::RemarkLinker &RL,
+             std::shared_ptr<DwarfLinkerForBinaryRelocationMap> DLBRM);
 
   void collectRelocationsToApplyToSwiftReflectionSections(
       const object::SectionRef &Section, StringRef &Contents,
@@ -196,17 +255,20 @@
 
   Error copySwiftInterfaces(StringRef Architecture) const;
 
-  template <typename OutStreamer>
   void copySwiftReflectionMetadata(
-      const llvm::dsymutil::DebugMapObject *Obj, OutStreamer *Streamer,
+      const llvm::dsymutil::DebugMapObject *Obj,
+      classic::DwarfStreamer *Streamer,
       std::vector<uint64_t> &SectionToOffsetInDwarf,
       std::vector<MachOUtils::DwarfRelocationApplicationInfo>
           &RelocationsToApply);
 
-  template <typename Linker, typename OutDwarfFile, typename AddressMapBase>
+  template <typename Linker>
   bool linkImpl(const DebugMap &Map,
                 typename Linker::OutputFileType ObjectType);
 
+  Error emitRelocations(const DebugMap &DM,
+                        std::vector<ObjectWithRelocMap> &ObjectsForLinking);
+
   raw_fd_ostream &OutFile;
   BinaryHolder &BinHolder;
   LinkOptions Options;
diff --git a/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h b/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h
index 88c17d5..fd9d985 100644
--- a/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h
+++ b/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h
@@ -16,8 +16,8 @@
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Support/WithColor.h"
 
-#include "llvm/DWARFLinker/DWARFLinker.h"
-#include "llvm/DWARFLinker/DWARFStreamer.h"
+#include "llvm/DWARFLinker/Classic/DWARFLinker.h"
+#include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
 #include <string>
 
 namespace llvm {
@@ -32,8 +32,8 @@
 };
 
 enum class DsymutilDWARFLinkerType : uint8_t {
-  Apple, /// Apple`s implementation of DWARFLinker.
-  LLVM   /// LLVM implementation of DWARFLinker.
+  Classic, /// Classic implementation of DWARFLinker.
+  Parallel /// Implementation of DWARFLinker heavily using parallel execution.
 };
 
 struct LinkOptions {
@@ -63,7 +63,7 @@
   bool KeepFunctionForStatic = false;
 
   /// Type of DWARFLinker to use.
-  DsymutilDWARFLinkerType DWARFLinkerType = DsymutilDWARFLinkerType::Apple;
+  DsymutilDWARFLinkerType DWARFLinkerType = DsymutilDWARFLinkerType::Classic;
 
   /// Use a 64-bit header when emitting universal binaries.
   bool Fat64 = false;
@@ -72,7 +72,8 @@
   unsigned Threads = 1;
 
   // Output file type.
-  DWARFLinker::OutputFileType FileType = DWARFLinker::OutputFileType::Object;
+  dwarf_linker::DWARFLinkerBase::OutputFileType FileType =
+      dwarf_linker::DWARFLinkerBase::OutputFileType::Object;
 
   /// The accelerator table kind
   DsymutilAccelTableKind TheAccelTableKind;
@@ -93,6 +94,12 @@
   llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS =
       vfs::getRealFileSystem();
 
+  /// -build-variant-suffix.
+  std::string BuildVariantSuffix;
+
+  /// Paths where to search for the .dSYM files of merged libraries.
+  std::vector<std::string> DSYMSearchPaths;
+
   /// Fields used for linking and placing remarks into the .dSYM bundle.
   /// @{
 
diff --git a/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp b/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp
index d3bda33..6a9f256 100644
--- a/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -9,6 +9,7 @@
 #include "BinaryHolder.h"
 #include "DebugMap.h"
 #include "MachOUtils.h"
+#include "RelocationMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/Object/MachO.h"
@@ -28,11 +29,13 @@
 public:
   MachODebugMapParser(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
                       StringRef BinaryPath, ArrayRef<std::string> Archs,
-                      StringRef PathPrefix = "",
-                      bool PaperTrailWarnings = false, bool Verbose = false)
+                      ArrayRef<std::string> DSYMSearchPaths,
+                      StringRef PathPrefix = "", StringRef VariantSuffix = "",
+                      bool Verbose = false)
       : BinaryPath(std::string(BinaryPath)), Archs(Archs.begin(), Archs.end()),
+        DSYMSearchPaths(DSYMSearchPaths.begin(), DSYMSearchPaths.end()),
         PathPrefix(std::string(PathPrefix)),
-        PaperTrailWarnings(PaperTrailWarnings), BinHolder(VFS, Verbose),
+        VariantSuffix(std::string(VariantSuffix)), BinHolder(VFS, Verbose),
         CurrentDebugMapObject(nullptr), SkipDebugMapObject(false) {}
 
   /// Parses and returns the DebugMaps of the input binary. The binary contains
@@ -49,8 +52,9 @@
 private:
   std::string BinaryPath;
   SmallVector<StringRef, 1> Archs;
+  SmallVector<StringRef, 1> DSYMSearchPaths;
   std::string PathPrefix;
-  bool PaperTrailWarnings;
+  std::string VariantSuffix;
 
   /// Owns the MemoryBuffer for the main binary.
   BinaryHolder BinHolder;
@@ -90,6 +94,9 @@
   void
   switchToNewDebugMapObject(StringRef Filename,
                             sys::TimePoint<std::chrono::seconds> Timestamp);
+  void
+  switchToNewLibDebugMapObject(StringRef Filename,
+                               sys::TimePoint<std::chrono::seconds> Timestamp);
   void resetParserState();
   uint64_t getMainBinarySymbolAddress(StringRef Name);
   std::vector<StringRef> getMainBinarySymbolNames(uint64_t Value);
@@ -137,13 +144,6 @@
                          << MachOUtils::getArchName(
                                 Result->getTriple().getArchName())
                          << ") " << File << " " << Msg << "\n";
-
-    if (PaperTrailWarnings) {
-      if (!File.empty())
-        Result->addDebugMapObject(File, sys::TimePoint<std::chrono::seconds>());
-      if (Result->end() != Result->begin())
-        (*--Result->end())->addWarning(Msg.str());
-    }
   }
 };
 
@@ -210,9 +210,133 @@
 
   CurrentDebugMapObject =
       &Result->addDebugMapObject(Path, Timestamp, MachO::N_OSO);
+
   loadCurrentObjectFileSymbols(*Object);
 }
 
+/// Create a new DebugMapObject of type MachO::N_LIB.
+/// This function resets the state of the parser that was
+/// referring to the last object file and sets everything
+/// up to add symbols to the new one.
+void MachODebugMapParser::switchToNewLibDebugMapObject(
+    StringRef Filename, sys::TimePoint<std::chrono::seconds> Timestamp) {
+
+  if (DSYMSearchPaths.empty()) {
+    Warning("no dSYM search path was specified");
+    return;
+  }
+
+  StringRef LeafName = sys::path::filename(Filename);
+  SmallString<128> VariantLeafName;
+  SmallString<128> ProductName(LeafName);
+
+  // For Framework.framework/Framework and -build-variant-suffix=_debug,
+  // look in the following order:
+  // 1) Framework.framework.dSYM/Contents/Resources/DWARF/Framework_debug
+  // 2) Framework.framework.dSYM/Contents/Resources/DWARF/Framework
+  //
+  // For libName.dylib and -build-variant-suffix=_debug,
+  // look in the following order:
+  // 1) libName.dylib.dSYM/Contents/Resources/DWARF/libName_debug.dylib
+  // 2) libName.dylib.dSYM/Contents/Resources/DWARF/libName.dylib
+
+  size_t libExt = LeafName.rfind(".dylib");
+  if (libExt != StringRef::npos) {
+    if (!VariantSuffix.empty()) {
+      VariantLeafName.append(LeafName.substr(0, libExt));
+      VariantLeafName.append(VariantSuffix);
+      VariantLeafName.append(".dylib");
+    }
+  } else {
+    // Expected to be a framework
+    ProductName.append(".framework");
+    if (!VariantSuffix.empty()) {
+      VariantLeafName.append(LeafName);
+      VariantLeafName.append(VariantSuffix);
+    }
+  }
+
+  for (auto DSYMSearchPath : DSYMSearchPaths) {
+    SmallString<256> Path(DSYMSearchPath);
+    SmallString<256> FallbackPath(Path);
+
+    SmallString<256> DSYMPath(ProductName);
+    DSYMPath.append(".dSYM");
+    sys::path::append(DSYMPath, "Contents", "Resources", "DWARF");
+
+    if (!VariantSuffix.empty()) {
+      sys::path::append(Path, DSYMPath, VariantLeafName);
+      sys::path::append(FallbackPath, DSYMPath, LeafName);
+    } else {
+      sys::path::append(Path, DSYMPath, LeafName);
+    }
+
+    auto ObjectEntry = BinHolder.getObjectEntry(Path, Timestamp);
+    if (!ObjectEntry) {
+      auto Err = ObjectEntry.takeError();
+      Warning("unable to open object file: " + toString(std::move(Err)),
+              Path.str());
+      if (!VariantSuffix.empty()) {
+        ObjectEntry = BinHolder.getObjectEntry(FallbackPath, Timestamp);
+        if (!ObjectEntry) {
+          auto Err = ObjectEntry.takeError();
+          Warning("unable to open object file: " + toString(std::move(Err)),
+                  FallbackPath.str());
+          continue;
+        }
+        Path.assign(FallbackPath);
+      } else {
+        continue;
+      }
+    }
+
+    auto Object =
+        ObjectEntry->getObjectAs<MachOObjectFile>(Result->getTriple());
+    if (!Object) {
+      auto Err = Object.takeError();
+      Warning("unable to open object file: " + toString(std::move(Err)),
+              Path.str());
+      continue;
+    }
+
+    if (CurrentDebugMapObject &&
+        CurrentDebugMapObject->getType() == MachO::N_LIB &&
+        CurrentDebugMapObject->getObjectFilename().compare(Path.str()) == 0) {
+      return;
+    }
+
+    addCommonSymbols();
+    resetParserState();
+
+    CurrentDebugMapObject =
+        &Result->addDebugMapObject(Path, Timestamp, MachO::N_LIB);
+
+    CurrentDebugMapObject->setInstallName(Filename);
+
+    SmallString<256> RMPath(DSYMSearchPath);
+    sys::path::append(RMPath, ProductName);
+    RMPath.append(".dSYM");
+    StringRef ArchName = Triple::getArchName(Result->getTriple().getArch(),
+                                             Result->getTriple().getSubArch());
+    sys::path::append(RMPath, "Contents", "Resources", "Relocations", ArchName);
+    sys::path::append(RMPath, LeafName);
+    RMPath.append(".yml");
+    const auto &RelocMapPtrOrErr =
+        RelocationMap::parseYAMLRelocationMap(RMPath, PathPrefix);
+    if (auto EC = RelocMapPtrOrErr.getError()) {
+      Warning("cannot parse relocation map file: " + EC.message(),
+              RMPath.str());
+      return;
+    }
+    CurrentDebugMapObject->setRelocationMap(*RelocMapPtrOrErr->get());
+
+    loadCurrentObjectFileSymbols(*Object);
+
+    // Found and loaded new dSYM file
+    return;
+  }
+}
+
 static std::string getArchName(const object::MachOObjectFile &Obj) {
   Triple T = Obj.getArchTriple();
   return std::string(T.getArchName());
@@ -285,23 +409,39 @@
   const char *Name;
 };
 
-const struct DarwinStabName DarwinStabNames[] = {
-    {MachO::N_GSYM, "N_GSYM"},    {MachO::N_FNAME, "N_FNAME"},
-    {MachO::N_FUN, "N_FUN"},      {MachO::N_STSYM, "N_STSYM"},
-    {MachO::N_LCSYM, "N_LCSYM"},  {MachO::N_BNSYM, "N_BNSYM"},
-    {MachO::N_PC, "N_PC"},        {MachO::N_AST, "N_AST"},
-    {MachO::N_OPT, "N_OPT"},      {MachO::N_RSYM, "N_RSYM"},
-    {MachO::N_SLINE, "N_SLINE"},  {MachO::N_ENSYM, "N_ENSYM"},
-    {MachO::N_SSYM, "N_SSYM"},    {MachO::N_SO, "N_SO"},
-    {MachO::N_OSO, "N_OSO"},      {MachO::N_LSYM, "N_LSYM"},
-    {MachO::N_BINCL, "N_BINCL"},  {MachO::N_SOL, "N_SOL"},
-    {MachO::N_PARAMS, "N_PARAM"}, {MachO::N_VERSION, "N_VERS"},
-    {MachO::N_OLEVEL, "N_OLEV"},  {MachO::N_PSYM, "N_PSYM"},
-    {MachO::N_EINCL, "N_EINCL"},  {MachO::N_ENTRY, "N_ENTRY"},
-    {MachO::N_LBRAC, "N_LBRAC"},  {MachO::N_EXCL, "N_EXCL"},
-    {MachO::N_RBRAC, "N_RBRAC"},  {MachO::N_BCOMM, "N_BCOMM"},
-    {MachO::N_ECOMM, "N_ECOMM"},  {MachO::N_ECOML, "N_ECOML"},
-    {MachO::N_LENG, "N_LENG"},    {0, nullptr}};
+const struct DarwinStabName DarwinStabNames[] = {{MachO::N_GSYM, "N_GSYM"},
+                                                 {MachO::N_FNAME, "N_FNAME"},
+                                                 {MachO::N_FUN, "N_FUN"},
+                                                 {MachO::N_STSYM, "N_STSYM"},
+                                                 {MachO::N_LCSYM, "N_LCSYM"},
+                                                 {MachO::N_BNSYM, "N_BNSYM"},
+                                                 {MachO::N_PC, "N_PC"},
+                                                 {MachO::N_AST, "N_AST"},
+                                                 {MachO::N_OPT, "N_OPT"},
+                                                 {MachO::N_RSYM, "N_RSYM"},
+                                                 {MachO::N_SLINE, "N_SLINE"},
+                                                 {MachO::N_ENSYM, "N_ENSYM"},
+                                                 {MachO::N_SSYM, "N_SSYM"},
+                                                 {MachO::N_SO, "N_SO"},
+                                                 {MachO::N_OSO, "N_OSO"},
+                                                 {MachO::N_LIB, "N_LIB"},
+                                                 {MachO::N_LSYM, "N_LSYM"},
+                                                 {MachO::N_BINCL, "N_BINCL"},
+                                                 {MachO::N_SOL, "N_SOL"},
+                                                 {MachO::N_PARAMS, "N_PARAM"},
+                                                 {MachO::N_VERSION, "N_VERS"},
+                                                 {MachO::N_OLEVEL, "N_OLEV"},
+                                                 {MachO::N_PSYM, "N_PSYM"},
+                                                 {MachO::N_EINCL, "N_EINCL"},
+                                                 {MachO::N_ENTRY, "N_ENTRY"},
+                                                 {MachO::N_LBRAC, "N_LBRAC"},
+                                                 {MachO::N_EXCL, "N_EXCL"},
+                                                 {MachO::N_RBRAC, "N_RBRAC"},
+                                                 {MachO::N_BCOMM, "N_BCOMM"},
+                                                 {MachO::N_ECOMM, "N_ECOMM"},
+                                                 {MachO::N_ECOML, "N_ECOML"},
+                                                 {MachO::N_LENG, "N_LENG"},
+                                                 {0, nullptr}};
 
 static const char *getDarwinStabString(uint8_t NType) {
   for (unsigned i = 0; DarwinStabNames[i].Name; i++) {
@@ -409,11 +549,11 @@
   if (Archs.empty() || is_contained(Archs, "all") || is_contained(Archs, "*"))
     return true;
 
-  if (Arch.startswith("arm") && Arch != "arm64" && is_contained(Archs, "arm"))
+  if (Arch.starts_with("arm") && Arch != "arm64" && is_contained(Archs, "arm"))
     return true;
 
   SmallString<16> ArchName = Arch;
-  if (Arch.startswith("thumb"))
+  if (Arch.starts_with("thumb"))
     ArchName = ("arm" + Arch.substr(5)).str();
 
   return is_contained(Archs, ArchName);
@@ -487,13 +627,25 @@
 
   const char *Name = &MainBinaryStrings.data()[StringIndex];
 
+  // An N_LIB entry represents the start of a new library file description.
+  if (Type == MachO::N_LIB) {
+    switchToNewLibDebugMapObject(Name, sys::toTimePoint(Value));
+    return;
+  }
+
   // An N_OSO entry represents the start of a new object file description.
+  // If an N_LIB entry was present, this is parsed only if the library
+  // dSYM file could not be found.
   if (Type == MachO::N_OSO) {
-    if (Duplicates.count(OSO(Name, Value))) {
-      SkipDebugMapObject = true;
-      return;
+    if (!CurrentDebugMapObject ||
+        CurrentDebugMapObject->getType() != MachO::N_LIB) {
+      if (Duplicates.count(OSO(Name, Value))) {
+        SkipDebugMapObject = true;
+        return;
+      }
+      switchToNewDebugMapObject(Name, sys::toTimePoint(Value));
     }
-    return switchToNewDebugMapObject(Name, sys::toTimePoint(Value));
+    return;
   }
 
   if (SkipDebugMapObject)
@@ -576,7 +728,8 @@
   }
 
   if (ObjectSymIt == CurrentObjectAddresses.end()) {
-    Warning("could not find object file symbol for symbol " + Twine(Name));
+    Warning("could not find symbol '" + Twine(Name) + "' in object file '" +
+            CurrentDebugMapObject->getObjectFilename() + "'");
     return;
   }
 
@@ -704,20 +857,23 @@
 llvm::ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
 parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
               StringRef InputFile, ArrayRef<std::string> Archs,
-              StringRef PrependPath, bool PaperTrailWarnings, bool Verbose,
-              bool InputIsYAML) {
+              ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
+              StringRef VariantSuffix, bool Verbose, bool InputIsYAML) {
   if (InputIsYAML)
     return DebugMap::parseYAMLDebugMap(InputFile, PrependPath, Verbose);
 
-  MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath,
-                             PaperTrailWarnings, Verbose);
+  MachODebugMapParser Parser(VFS, InputFile, Archs, DSYMSearchPaths,
+                             PrependPath, VariantSuffix, Verbose);
+
   return Parser.parse();
 }
 
 bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
               StringRef InputFile, ArrayRef<std::string> Archs,
-              StringRef PrependPath) {
-  MachODebugMapParser Parser(VFS, InputFile, Archs, PrependPath, false);
+              ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
+              StringRef VariantSuffix) {
+  MachODebugMapParser Parser(VFS, InputFile, Archs, DSYMSearchPaths,
+                             PrependPath, VariantSuffix, false);
   return Parser.dumpStab();
 }
 } // namespace dsymutil
diff --git a/src/llvm-project/llvm/tools/dsymutil/MachOUtils.cpp b/src/llvm-project/llvm/tools/dsymutil/MachOUtils.cpp
index 9d440e8..3efc1af 100644
--- a/src/llvm-project/llvm/tools/dsymutil/MachOUtils.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/MachOUtils.cpp
@@ -10,6 +10,7 @@
 #include "BinaryHolder.h"
 #include "DebugMap.h"
 #include "LinkUtils.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/CodeGen/NonRelocatableStringpool.h"
 #include "llvm/MC/MCAsmLayout.h"
 #include "llvm/MC/MCAssembler.h"
@@ -29,28 +30,34 @@
 namespace MachOUtils {
 
 llvm::Error ArchAndFile::createTempFile() {
-  llvm::SmallString<128> TmpModel;
-  llvm::sys::path::system_temp_directory(true, TmpModel);
-  llvm::sys::path::append(TmpModel, "dsym.tmp%%%%%.dwarf");
-  Expected<sys::fs::TempFile> T = sys::fs::TempFile::create(TmpModel);
+  SmallString<256> SS;
+  std::error_code EC = sys::fs::createTemporaryFile("dsym", "dwarf", FD, SS);
 
-  if (!T)
-    return T.takeError();
+  if (EC)
+    return errorCodeToError(EC);
 
-  File = std::make_unique<sys::fs::TempFile>(std::move(*T));
+  Path = SS.str();
+
   return Error::success();
 }
 
-llvm::StringRef ArchAndFile::path() const { return File->TmpName; }
+llvm::StringRef ArchAndFile::getPath() const {
+  assert(!Path.empty() && "path called before createTempFile");
+  return Path;
+}
+
+int ArchAndFile::getFD() const {
+  assert((FD != -1) && "path called before createTempFile");
+  return FD;
+}
 
 ArchAndFile::~ArchAndFile() {
-  if (File)
-    if (auto E = File->discard())
-      llvm::consumeError(std::move(E));
+  if (!Path.empty())
+    sys::fs::remove(Path);
 }
 
 std::string getArchName(StringRef Arch) {
-  if (Arch.startswith("thumb"))
+  if (Arch.starts_with("thumb"))
     return (llvm::Twine("arm") + Arch.drop_front(5)).str();
   return std::string(Arch);
 }
@@ -82,11 +89,17 @@
                              bool Fat64) {
   // No need to merge one file into a universal fat binary.
   if (ArchFiles.size() == 1) {
-    if (auto E = ArchFiles.front().File->keep(OutputFileName)) {
-      WithColor::error() << "while keeping " << ArchFiles.front().path()
-                         << " as " << OutputFileName << ": "
-                         << toString(std::move(E)) << "\n";
-      return false;
+    llvm::StringRef TmpPath = ArchFiles.front().getPath();
+    if (auto EC = sys::fs::rename(TmpPath, OutputFileName)) {
+      // If we can't rename, try to copy to work around cross-device link
+      // issues.
+      EC = sys::fs::copy_file(TmpPath, OutputFileName);
+      if (EC) {
+        WithColor::error() << "while keeping " << TmpPath << " as "
+                           << OutputFileName << ": " << EC.message() << "\n";
+        return false;
+      }
+      sys::fs::remove(TmpPath);
     }
     return true;
   }
@@ -96,7 +109,7 @@
   Args.push_back("-create");
 
   for (auto &Thin : ArchFiles)
-    Args.push_back(Thin.path());
+    Args.push_back(Thin.getPath());
 
   // Align segments to match dsymutil-classic alignment.
   for (auto &Thin : ArchFiles) {
@@ -328,8 +341,9 @@
       VMAddr = alignTo(VMAddr, Alignment);
       FileOffset = alignTo(FileOffset, Alignment);
       if (FileOffset > UINT32_MAX)
-        return error("section " + Sec->getName() + "'s file offset exceeds 4GB."
-            " Refusing to produce an invalid Mach-O file.");
+        return error("section " + Sec->getName() +
+                     "'s file offset exceeds 4GB."
+                     " Refusing to produce an invalid Mach-O file.");
     }
     Writer.writeSection(Layout, *Sec, VMAddr, FileOffset, 0, 0, 0);
 
@@ -414,7 +428,7 @@
       ++NumLoadCommands;
       LoadCommandSize += sizeof(UUIDCmd);
       break;
-   case MachO::LC_BUILD_VERSION: {
+    case MachO::LC_BUILD_VERSION: {
       MachO::build_version_command Cmd;
       memset(&Cmd, 0, sizeof(Cmd));
       Cmd = InputBinary.getBuildVersionLoadCommand(LCI);
diff --git a/src/llvm-project/llvm/tools/dsymutil/MachOUtils.h b/src/llvm-project/llvm/tools/dsymutil/MachOUtils.h
index 9d35813..059d9fd 100644
--- a/src/llvm-project/llvm/tools/dsymutil/MachOUtils.h
+++ b/src/llvm-project/llvm/tools/dsymutil/MachOUtils.h
@@ -26,10 +26,12 @@
 
 struct ArchAndFile {
   std::string Arch;
-  std::unique_ptr<llvm::sys::fs::TempFile> File;
+  std::string Path;
+  int FD = -1;
 
   llvm::Error createTempFile();
-  llvm::StringRef path() const;
+  llvm::StringRef getPath() const;
+  int getFD() const;
 
   ArchAndFile(StringRef Arch) : Arch(std::string(Arch)) {}
   ArchAndFile(ArchAndFile &&A) = default;
diff --git a/src/llvm-project/llvm/tools/dsymutil/Options.td b/src/llvm-project/llvm/tools/dsymutil/Options.td
index 9b0b31b..a4e4c6c 100644
--- a/src/llvm-project/llvm/tools/dsymutil/Options.td
+++ b/src/llvm-project/llvm/tools/dsymutil/Options.td
@@ -69,10 +69,6 @@
   HelpText<"Treat the input file is a YAML debug map rather than a binary.">,
   Group<grp_general>;
 
-def papertrail: F<"papertrail">,
-  HelpText<"Embed warnings in the linked DWARF debug info.">,
-  Group<grp_general>;
-
 def assembly: Flag<["-", "--"], "S">,
   HelpText<"Output textual assembly instead of a binary dSYM companion file.">,
   Group<grp_general>;
@@ -202,6 +198,17 @@
 
 def linker: Separate<["--", "-"], "linker">,
   MetaVarName<"<DWARF linker type>">,
-  HelpText<"Specify the desired type of DWARF linker. Defaults to 'apple'">,
+  HelpText<"Specify the desired type of DWARF linker. Defaults to 'classic'">,
   Group<grp_general>;
 def: Joined<["--", "-"], "linker=">, Alias<linker>;
+
+def build_variant_suffix: Separate<["--", "-"], "build-variant-suffix">,
+  MetaVarName<"<suffix=buildvariant>">,
+  HelpText<"Specify the build variant suffix used to build the executabe file.">,
+  Group<grp_general>;
+def: Joined<["--", "-"], "build-variant-suffix=">, Alias<build_variant_suffix>;
+
+def dsym_search_path: Separate<["-", "--"], "D">,
+  MetaVarName<"<path>">,
+  HelpText<"Specify a directory that contain dSYM files to search for.">,
+  Group<grp_general>;
diff --git a/src/llvm-project/llvm/tools/dsymutil/RelocationMap.cpp b/src/llvm-project/llvm/tools/dsymutil/RelocationMap.cpp
new file mode 100644
index 0000000..5921e7c
--- /dev/null
+++ b/src/llvm-project/llvm/tools/dsymutil/RelocationMap.cpp
@@ -0,0 +1,92 @@
+//===- tools/dsymutil/RelocationMap.cpp - Relocation map representation---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RelocationMap.h"
+
+namespace llvm {
+
+namespace dsymutil {
+
+void RelocationMap::print(raw_ostream &OS) const {
+  yaml::Output yout(OS, /* Ctxt = */ nullptr, /* WrapColumn = */ 0);
+  yout << const_cast<RelocationMap &>(*this);
+}
+
+#ifndef NDEBUG
+void RelocationMap::dump() const { print(errs()); }
+#endif
+
+void RelocationMap::addRelocationMapEntry(const ValidReloc &Relocation) {
+  Relocations.push_back(Relocation);
+}
+
+namespace {
+
+struct YAMLContext {
+  StringRef PrependPath;
+  Triple BinaryTriple;
+};
+
+} // end anonymous namespace
+
+ErrorOr<std::unique_ptr<RelocationMap>>
+RelocationMap::parseYAMLRelocationMap(StringRef InputFile,
+                                      StringRef PrependPath) {
+  auto ErrOrFile = MemoryBuffer::getFileOrSTDIN(InputFile);
+  if (auto Err = ErrOrFile.getError())
+    return Err;
+
+  YAMLContext Ctxt;
+
+  Ctxt.PrependPath = PrependPath;
+
+  std::unique_ptr<RelocationMap> Result;
+  yaml::Input yin((*ErrOrFile)->getBuffer(), &Ctxt);
+  yin >> Result;
+
+  if (auto EC = yin.error())
+    return EC;
+  return std::move(Result);
+}
+
+} // end namespace dsymutil
+
+namespace yaml {
+
+void MappingTraits<dsymutil::ValidReloc>::mapping(IO &io,
+                                                  dsymutil::ValidReloc &VR) {
+  io.mapRequired("offset", VR.Offset);
+  io.mapRequired("size", VR.Size);
+  io.mapRequired("addend", VR.Addend);
+  io.mapRequired("symName", VR.SymbolName);
+  io.mapOptional("symObjAddr", VR.SymbolMapping.ObjectAddress);
+  io.mapRequired("symBinAddr", VR.SymbolMapping.BinaryAddress);
+  io.mapRequired("symSize", VR.SymbolMapping.Size);
+}
+
+void MappingTraits<dsymutil::RelocationMap>::mapping(
+    IO &io, dsymutil::RelocationMap &RM) {
+  io.mapRequired("triple", RM.BinaryTriple);
+  io.mapRequired("binary-path", RM.BinaryPath);
+  if (void *Ctxt = io.getContext())
+    reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = RM.BinaryTriple;
+  io.mapRequired("relocations", RM.Relocations);
+}
+
+void MappingTraits<std::unique_ptr<dsymutil::RelocationMap>>::mapping(
+    IO &io, std::unique_ptr<dsymutil::RelocationMap> &RM) {
+  if (!RM)
+    RM.reset(new RelocationMap());
+  io.mapRequired("triple", RM->BinaryTriple);
+  io.mapRequired("binary-path", RM->BinaryPath);
+  if (void *Ctxt = io.getContext())
+    reinterpret_cast<YAMLContext *>(Ctxt)->BinaryTriple = RM->BinaryTriple;
+  io.mapRequired("relocations", RM->Relocations);
+}
+} // end namespace yaml
+} // end namespace llvm
diff --git a/src/llvm-project/llvm/tools/dsymutil/RelocationMap.h b/src/llvm-project/llvm/tools/dsymutil/RelocationMap.h
new file mode 100644
index 0000000..3d851ac
--- /dev/null
+++ b/src/llvm-project/llvm/tools/dsymutil/RelocationMap.h
@@ -0,0 +1,160 @@
+//===- tools/dsymutil/RelocationMap.h -------------------------- *- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+///
+/// This file contains the class declaration of the RelocationMap
+/// entity. RelocationMap lists all the relocations of all the
+/// atoms used in the object files linked together to
+/// produce an executable.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_DSYMUTIL_RELOCATIONMAP_H
+#define LLVM_TOOLS_DSYMUTIL_RELOCATIONMAP_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/TargetParser/Triple.h"
+
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace dsymutil {
+
+struct SymbolMapping {
+  std::optional<yaml::Hex64> ObjectAddress;
+  yaml::Hex64 BinaryAddress;
+  yaml::Hex32 Size;
+
+  SymbolMapping(std::optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
+                uint32_t Size)
+      : BinaryAddress(BinaryAddress), Size(Size) {
+    if (ObjectAddr)
+      ObjectAddress = *ObjectAddr;
+  }
+
+  /// For YAML IO support
+  SymbolMapping() = default;
+};
+
+/// ValidReloc represents one relocation entry described by the RelocationMap.
+/// It contains a list of DWARF relocations to apply to a linked binary.
+class ValidReloc {
+public:
+  yaml::Hex64 Offset;
+  yaml::Hex32 Size;
+  yaml::Hex64 Addend;
+  std::string SymbolName;
+  struct SymbolMapping SymbolMapping;
+
+  struct SymbolMapping getSymbolMapping() const { return SymbolMapping; }
+
+  ValidReloc(uint64_t Offset, uint32_t Size, uint64_t Addend,
+             StringRef SymbolName, struct SymbolMapping SymbolMapping)
+      : Offset(Offset), Size(Size), Addend(Addend), SymbolName(SymbolName),
+        SymbolMapping(SymbolMapping) {}
+
+  bool operator<(const ValidReloc &RHS) const { return Offset < RHS.Offset; }
+
+  /// For YAMLIO support.
+  ValidReloc() = default;
+};
+
+/// The RelocationMap object stores the list of relocation entries for a binary
+class RelocationMap {
+  Triple BinaryTriple;
+  std::string BinaryPath;
+  using RelocContainer = std::vector<ValidReloc>;
+
+  RelocContainer Relocations;
+
+  /// For YAML IO support.
+  ///@{
+  friend yaml::MappingTraits<std::unique_ptr<RelocationMap>>;
+  friend yaml::MappingTraits<RelocationMap>;
+
+  RelocationMap() = default;
+  ///@}
+
+public:
+  RelocationMap(const Triple &BinaryTriple, StringRef BinaryPath)
+      : BinaryTriple(BinaryTriple), BinaryPath(std::string(BinaryPath)) {}
+
+  using const_iterator = RelocContainer::const_iterator;
+
+  iterator_range<const_iterator> relocations() const {
+    return make_range(begin(), end());
+  }
+
+  const_iterator begin() const { return Relocations.begin(); }
+
+  const_iterator end() const { return Relocations.end(); }
+
+  size_t getNumberOfEntries() const { return Relocations.size(); }
+
+  /// This function adds a ValidReloc to the list owned by this
+  /// relocation map.
+  void addRelocationMapEntry(const ValidReloc &Relocation);
+
+  const Triple &getTriple() const { return BinaryTriple; }
+
+  StringRef getBinaryPath() const { return BinaryPath; }
+
+  void print(raw_ostream &OS) const;
+
+#ifndef NDEBUG
+  void dump() const;
+#endif
+
+  /// Read a relocation map from \a InputFile.
+  static ErrorOr<std::unique_ptr<RelocationMap>>
+  parseYAMLRelocationMap(StringRef InputFile, StringRef PrependPath);
+};
+
+} // end namespace dsymutil
+} // end namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(dsymutil::ValidReloc)
+
+namespace llvm {
+namespace yaml {
+
+using namespace llvm::dsymutil;
+
+template <> struct MappingTraits<dsymutil::ValidReloc> {
+  static void mapping(IO &io, dsymutil::ValidReloc &VR);
+  static const bool flow = true;
+};
+
+template <> struct MappingTraits<dsymutil::RelocationMap> {
+  struct YamlRM;
+  static void mapping(IO &io, dsymutil::RelocationMap &RM);
+};
+
+template <> struct MappingTraits<std::unique_ptr<dsymutil::RelocationMap>> {
+  struct YamlRM;
+  static void mapping(IO &io, std::unique_ptr<dsymutil::RelocationMap> &RM);
+};
+
+template <> struct ScalarTraits<Triple> {
+  static void output(const Triple &val, void *, raw_ostream &out);
+  static StringRef input(StringRef scalar, void *, Triple &value);
+  static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+#endif // LLVM_TOOLS_DSYMUTIL_RELOCATIONMAP_H
diff --git a/src/llvm-project/llvm/tools/dsymutil/Reproducer.cpp b/src/llvm-project/llvm/tools/dsymutil/Reproducer.cpp
index 2522e2c..a6cc104 100644
--- a/src/llvm-project/llvm/tools/dsymutil/Reproducer.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/Reproducer.cpp
@@ -8,6 +8,7 @@
 
 #include "Reproducer.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
 
 using namespace llvm;
 using namespace llvm::dsymutil;
@@ -16,7 +17,12 @@
   SmallString<128> Root;
   if (const char *Path = getenv("DSYMUTIL_REPRODUCER_PATH")) {
     Root.assign(Path);
-    EC = sys::fs::create_directory(Root);
+    EC = sys::fs::create_directories(Root);
+  } else if (const char *Path = getenv("LLVM_DIAGNOSTIC_DIR")) {
+    Root.assign(Path);
+    llvm::sys::path::append(
+        Root, "dsymutil-" + llvm::Twine(llvm::sys::Process::getProcessId()));
+    EC = sys::fs::create_directories(Root);
   } else {
     EC = sys::fs::createUniqueDirectory("dsymutil", Root);
   }
diff --git a/src/llvm-project/llvm/tools/dsymutil/SymbolMap.cpp b/src/llvm-project/llvm/tools/dsymutil/SymbolMap.cpp
index 07a5479..c55362e 100644
--- a/src/llvm-project/llvm/tools/dsymutil/SymbolMap.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/SymbolMap.cpp
@@ -23,15 +23,11 @@
 namespace dsymutil {
 
 StringRef SymbolMapTranslator::operator()(StringRef Input) {
-  if (!Input.startswith("__hidden#") && !Input.startswith("___hidden#"))
+  if (!Input.starts_with("__hidden#") && !Input.starts_with("___hidden#"))
     return Input;
 
-  bool MightNeedUnderscore = false;
   StringRef Line = Input.drop_front(sizeof("__hidden#") - 1);
-  if (Line[0] == '#') {
-    Line = Line.drop_front();
-    MightNeedUnderscore = true;
-  }
+  bool MightNeedUnderscore = Line.consume_front("#");
 
   std::size_t LineNumber = std::numeric_limits<std::size_t>::max();
   Line.split('_').first.getAsInteger(10, LineNumber);
@@ -131,7 +127,7 @@
   bool MangleNames = false;
 
   // Check version string first.
-  if (!LHS.startswith("BCSymbolMap Version:")) {
+  if (!LHS.starts_with("BCSymbolMap Version:")) {
     // Version string not present, warns but try to parse it.
     WithColor::warning() << SymbolMapPath
                          << " is missing version string: assuming 1.0.\n";
diff --git a/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp b/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp
index 5a8d219..b0e988c 100644
--- a/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp
@@ -37,7 +37,6 @@
 #include "llvm/Support/FileCollector.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/TargetSelect.h"
@@ -55,13 +54,12 @@
 using namespace llvm;
 using namespace llvm::dsymutil;
 using namespace object;
+using namespace llvm::dwarf_linker;
 
 namespace {
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Options.inc"
 #undef OPTION
 };
@@ -73,14 +71,9 @@
 #include "Options.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Options.inc"
 #undef OPTION
 };
@@ -99,7 +92,7 @@
   All = Input | Output,
   Auto = Input | OutputOnValidInput,
 #if !defined(NDEBUG) || defined(EXPENSIVE_CHECKS)
-  Default = None // FIXME: Auto
+  Default = Auto
 #else
   Default = None
 #endif
@@ -114,7 +107,6 @@
   bool DumpStab = false;
   bool Flat = false;
   bool InputIsYAMLDebugMap = false;
-  bool PaperTrailWarnings = false;
   bool ForceKeepFunctionForStatic = false;
   std::string SymbolMap;
   std::string OutputFile;
@@ -205,11 +197,6 @@
         "cannot use -o with multiple inputs in flat mode.",
         errc::invalid_argument);
 
-  if (Options.PaperTrailWarnings && Options.InputIsYAMLDebugMap)
-    return make_error<StringError>(
-        "paper trail warnings are not supported for YAML input.",
-        errc::invalid_argument);
-
   if (!Options.ReproducerPath.empty() &&
       Options.ReproMode != ReproducerMode::Use)
     return make_error<StringError>(
@@ -245,18 +232,18 @@
 getDWARFLinkerType(opt::InputArgList &Args) {
   if (opt::Arg *LinkerType = Args.getLastArg(OPT_linker)) {
     StringRef S = LinkerType->getValue();
-    if (S == "apple")
-      return DsymutilDWARFLinkerType::Apple;
-    if (S == "llvm")
-      return DsymutilDWARFLinkerType::LLVM;
+    if (S == "classic")
+      return DsymutilDWARFLinkerType::Classic;
+    if (S == "parallel")
+      return DsymutilDWARFLinkerType::Parallel;
     return make_error<StringError>("invalid DWARF linker type specified: '" +
                                        S +
-                                       "'. Supported values are 'apple', "
-                                       "'llvm'.",
+                                       "'. Supported values are 'classic', "
+                                       "'parallel'.",
                                    inconvertibleErrorCode());
   }
 
-  return DsymutilDWARFLinkerType::Apple;
+  return DsymutilDWARFLinkerType::Classic;
 }
 
 static Expected<ReproducerMode> getReproducerMode(opt::InputArgList &Args) {
@@ -311,7 +298,6 @@
   Options.DumpStab = Args.hasArg(OPT_symtab);
   Options.Flat = Args.hasArg(OPT_flat);
   Options.InputIsYAMLDebugMap = Args.hasArg(OPT_yaml_input);
-  Options.PaperTrailWarnings = Args.hasArg(OPT_papertrail);
 
   if (Expected<DWARFVerify> Verify = getVerifyKind(Args)) {
     Options.Verify = *Verify;
@@ -387,7 +373,7 @@
     Options.Toolchain = Toolchain->getValue();
 
   if (Args.hasArg(OPT_assembly))
-    Options.LinkOpts.FileType = DWARFLinker::OutputFileType::Assembly;
+    Options.LinkOpts.FileType = DWARFLinkerBase::OutputFileType::Assembly;
 
   if (opt::Arg *NumThreads = Args.getLastArg(OPT_threads))
     Options.LinkOpts.Threads = atoi(NumThreads->getValue());
@@ -397,9 +383,6 @@
   if (Options.DumpDebugMap || Options.LinkOpts.Verbose)
     Options.LinkOpts.Threads = 1;
 
-  if (getenv("RC_DEBUG_OPTIONS"))
-    Options.PaperTrailWarnings = true;
-
   if (opt::Arg *RemarksPrependPath = Args.getLastArg(OPT_remarks_prepend_path))
     Options.LinkOpts.RemarksPrependPath = RemarksPrependPath->getValue();
 
@@ -415,6 +398,12 @@
   Options.LinkOpts.RemarksKeepAll =
       !Args.hasArg(OPT_remarks_drop_without_debug);
 
+  if (opt::Arg *BuildVariantSuffix = Args.getLastArg(OPT_build_variant_suffix))
+    Options.LinkOpts.BuildVariantSuffix = BuildVariantSuffix->getValue();
+
+  for (auto *SearchPath : Args.filtered(OPT_dsym_search_path))
+    Options.LinkOpts.DSYMSearchPaths.push_back(SearchPath->getValue());
+
   if (Error E = verifyOptions(Options))
     return std::move(E);
   return Options;
@@ -498,15 +487,17 @@
 }
 
 static bool verifyOutput(StringRef OutputFile, StringRef Arch,
-                         DsymutilOptions Options) {
+                         DsymutilOptions Options, std::mutex &Mutex) {
 
   if (OutputFile == "-") {
+    std::lock_guard<std::mutex> Guard(Mutex);
     WithColor::warning() << "verification skipped for " << Arch
                          << " because writing to stdout.\n";
     return true;
   }
 
   if (Options.LinkOpts.NoOutput) {
+    std::lock_guard<std::mutex> Guard(Mutex);
     WithColor::warning() << "verification skipped for " << Arch
                          << " because --no-output was passed.\n";
     return true;
@@ -514,6 +505,7 @@
 
   Expected<OwningBinary<Binary>> BinOrErr = createBinary(OutputFile);
   if (!BinOrErr) {
+    std::lock_guard<std::mutex> Guard(Mutex);
     WithColor::error() << OutputFile << ": " << toString(BinOrErr.takeError());
     return false;
   }
@@ -521,17 +513,29 @@
   Binary &Binary = *BinOrErr.get().getBinary();
   if (auto *Obj = dyn_cast<MachOObjectFile>(&Binary)) {
     std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(*Obj);
-    if (DICtx->getMaxVersion() >= 5) {
-      WithColor::warning() << "verification skipped for " << Arch
-                           << " because DWARFv5 is not fully supported yet.\n";
+    if (DICtx->getMaxVersion() > 5) {
+      std::lock_guard<std::mutex> Guard(Mutex);
+      WithColor::warning()
+          << "verification skipped for " << Arch
+          << " because DWARF standard greater than v5 is not supported yet.\n";
       return true;
     }
-    raw_ostream &os = Options.LinkOpts.Verbose ? errs() : nulls();
-    os << "Verifying DWARF for architecture: " << Arch << "\n";
+
+    if (Options.LinkOpts.Verbose) {
+      std::lock_guard<std::mutex> Guard(Mutex);
+      errs() << "Verifying DWARF for architecture: " << Arch << "\n";
+    }
+
+    std::string Buffer;
+    raw_string_ostream OS(Buffer);
+
     DIDumpOptions DumpOpts;
-    bool success = DICtx->verify(os, DumpOpts.noImplicitRecursion());
-    if (!success)
+    bool success = DICtx->verify(OS, DumpOpts.noImplicitRecursion());
+    if (!success) {
+      std::lock_guard<std::mutex> Guard(Mutex);
+      errs() << OS.str();
       WithColor::error() << "output verification failed for " << Arch << '\n';
+    }
     return success;
   }
 
@@ -597,14 +601,12 @@
   }
 
   sys::path::append(Path, "Contents", "Resources");
-  std::string ResourceDir = std::string(Path.str());
+  std::string ResourceDir = std::string(Path);
   sys::path::append(Path, "DWARF", sys::path::filename(DwarfFile));
-  return OutputLocation(std::string(Path.str()), ResourceDir);
+  return OutputLocation(std::string(Path), ResourceDir);
 }
 
-int main(int argc, char **argv) {
-  InitLLVM X(argc, argv);
-
+int dsymutil_main(int argc, char **argv, const llvm::ToolContext &) {
   // Parse arguments.
   DsymutilOptTable T;
   unsigned MAI;
@@ -672,15 +674,18 @@
     // Dump the symbol table for each input file and requested arch
     if (Options.DumpStab) {
       if (!dumpStab(Options.LinkOpts.VFS, InputFile, Options.Archs,
-                    Options.LinkOpts.PrependPath))
+                    Options.LinkOpts.DSYMSearchPaths,
+                    Options.LinkOpts.PrependPath,
+                    Options.LinkOpts.BuildVariantSuffix))
         return EXIT_FAILURE;
       continue;
     }
 
-    auto DebugMapPtrsOrErr =
-        parseDebugMap(Options.LinkOpts.VFS, InputFile, Options.Archs,
-                      Options.LinkOpts.PrependPath, Options.PaperTrailWarnings,
-                      Options.LinkOpts.Verbose, Options.InputIsYAMLDebugMap);
+    auto DebugMapPtrsOrErr = parseDebugMap(
+        Options.LinkOpts.VFS, InputFile, Options.Archs,
+        Options.LinkOpts.DSYMSearchPaths, Options.LinkOpts.PrependPath,
+        Options.LinkOpts.BuildVariantSuffix, Options.LinkOpts.Verbose,
+        Options.InputIsYAMLDebugMap);
 
     if (auto EC = DebugMapPtrsOrErr.getError()) {
       WithColor::error() << "cannot parse the debug map for '" << InputFile
@@ -737,16 +742,16 @@
         !Options.DumpDebugMap && (Options.OutputFile != "-") &&
         (DebugMapPtrsOrErr->size() != 1 || Options.LinkOpts.Update);
 
-    // Set up a crash recovery context.
-    CrashRecoveryContext::Enable();
-    CrashRecoveryContext CRC;
-    CRC.DumpStackAndCleanupOnFailure = true;
-
     std::atomic_char AllOK(1);
     SmallVector<MachOUtils::ArchAndFile, 4> TempFiles;
 
     std::mutex ErrorHandlerMutex;
 
+    // Set up a crash recovery context.
+    CrashRecoveryContext::Enable();
+    CrashRecoveryContext CRC;
+    CRC.DumpStackAndCleanupOnFailure = true;
+
     const bool Crashed = !CRC.RunSafely([&]() {
       for (auto &Map : *DebugMapPtrsOrErr) {
         if (Options.LinkOpts.Verbose || Options.DumpDebugMap)
@@ -758,11 +763,13 @@
         if (!Options.SymbolMap.empty())
           Options.LinkOpts.Translator = SymMapLoader.Load(InputFile, *Map);
 
-        if (Map->begin() == Map->end())
+        if (Map->begin() == Map->end()) {
+          std::lock_guard<std::mutex> Guard(ErrorHandlerMutex);
           WithColor::warning()
               << "no debug symbols in executable (-arch "
               << MachOUtils::getArchName(Map->getTriple().getArchName())
               << ")\n";
+        }
 
         // Using a std::shared_ptr rather than std::unique_ptr because move-only
         // types don't work with std::bind in the ThreadPool implementation.
@@ -774,15 +781,16 @@
 
           auto E = TempFiles.back().createTempFile();
           if (E) {
+            std::lock_guard<std::mutex> Guard(ErrorHandlerMutex);
             WithColor::error() << toString(std::move(E));
             AllOK.fetch_and(false);
             return;
           }
 
-          auto &TempFile = *(TempFiles.back().File);
-          OS = std::make_shared<raw_fd_ostream>(TempFile.FD,
+          MachOUtils::ArchAndFile &AF = TempFiles.back();
+          OS = std::make_shared<raw_fd_ostream>(AF.getFD(),
                                                 /*shouldClose*/ false);
-          OutputFile = TempFile.TmpName;
+          OutputFile = AF.getPath();
         } else {
           std::error_code EC;
           OS = std::make_shared<raw_fd_ostream>(
@@ -804,8 +812,9 @@
           if (flagIsSet(Options.Verify, DWARFVerify::Output) ||
               (flagIsSet(Options.Verify, DWARFVerify::OutputOnValidInput) &&
                !Linker.InputVerificationFailed())) {
-            AllOK.fetch_and(verifyOutput(
-                OutputFile, Map->getTriple().getArchName(), Options));
+            AllOK.fetch_and(verifyOutput(OutputFile,
+                                         Map->getTriple().getArchName(),
+                                         Options, ErrorHandlerMutex));
           }
         };
 
@@ -850,7 +859,8 @@
         uint64_t FileOffset =
             MagicAndCountSize + UniversalArchInfoSize * TempFiles.size();
         for (const auto &File : TempFiles) {
-          ErrorOr<vfs::Status> stat = Options.LinkOpts.VFS->status(File.path());
+          ErrorOr<vfs::Status> stat =
+              Options.LinkOpts.VFS->status(File.getPath());
           if (!stat)
             break;
           if (FileOffset > UINT32_MAX) {
diff --git a/src/llvm-project/llvm/tools/dsymutil/dsymutil.h b/src/llvm-project/llvm/tools/dsymutil/dsymutil.h
index e679928..5504dd5 100644
--- a/src/llvm-project/llvm/tools/dsymutil/dsymutil.h
+++ b/src/llvm-project/llvm/tools/dsymutil/dsymutil.h
@@ -29,21 +29,20 @@
 namespace llvm {
 namespace dsymutil {
 
-class BinaryHolder;
-
 /// Extract the DebugMaps from the given file.
 /// The file has to be a MachO object file. Multiple debug maps can be
 /// returned when the file is universal (aka fat) binary.
 ErrorOr<std::vector<std::unique_ptr<DebugMap>>>
 parseDebugMap(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
               StringRef InputFile, ArrayRef<std::string> Archs,
-              StringRef PrependPath, bool PaperTrailWarnings, bool Verbose,
-              bool InputIsYAML);
+              ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath,
+              StringRef VariantSuffix, bool Verbose, bool InputIsYAML);
 
 /// Dump the symbol table.
 bool dumpStab(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS,
               StringRef InputFile, ArrayRef<std::string> Archs,
-              StringRef PrependPath = "");
+              ArrayRef<std::string> DSYMSearchPaths, StringRef PrependPath = "",
+              StringRef VariantSuffix = "");
 
 } // end namespace dsymutil
 } // end namespace llvm
diff --git a/src/llvm-project/llvm/tools/gold/gold-plugin.cpp b/src/llvm-project/llvm/tools/gold/gold-plugin.cpp
index a47dba3..257832a 100644
--- a/src/llvm-project/llvm/tools/gold/gold-plugin.cpp
+++ b/src/llvm-project/llvm/tools/gold/gold-plugin.cpp
@@ -308,8 +308,6 @@
       RemarksFormat = std::string(opt);
     } else if (opt.consume_front("stats-file=")) {
       stats_file = std::string(opt);
-    } else if (opt == "opaque-pointers") {
-      // We always use opaque pointers.
     } else {
       // Save this option to pass to the code generator.
       // ParseCommandLineOptions() expects argv[0] to be program name. Lazily
@@ -538,14 +536,6 @@
     BufferRef = Buffer->getMemBufferRef();
   }
 
-  // Only use bitcode files for LTO.  InputFile::create() will load bitcode
-  // from the .llvmbc section within a binary object, this bitcode is typically
-  // generated by -fembed-bitcode and is not to be used by LLVMgold.so for LTO.
-  if (identify_magic(BufferRef.getBuffer()) != file_magic::bitcode) {
-    *claimed = 0;
-    return LDPS_OK;
-  }
-
   *claimed = 1;
 
   Expected<std::unique_ptr<InputFile>> ObjOrErr = InputFile::create(BufferRef);
@@ -878,7 +868,7 @@
   Conf.MAttrs = codegen::getMAttrs();
   Conf.RelocModel = RelocationModel;
   Conf.CodeModel = codegen::getExplicitCodeModel();
-  std::optional<CodeGenOpt::Level> CGOptLevelOrNone =
+  std::optional<CodeGenOptLevel> CGOptLevelOrNone =
       CodeGenOpt::getLevel(options::OptLevel);
   assert(CGOptLevelOrNone && "Invalid optimization level");
   Conf.CGOptLevel = *CGOptLevelOrNone;
@@ -934,7 +924,8 @@
                             /* UseInputModulePath */ true));
     break;
   case options::OT_ASM_ONLY:
-    Conf.CGFileType = CGFT_AssemblyFile;
+    Conf.CGFileType = CodeGenFileType::AssemblyFile;
+    Conf.Options.MCOptions.AsmVerbose = true;
     break;
   }
 
diff --git a/src/llvm-project/llvm/tools/llc/CMakeLists.txt b/src/llvm-project/llvm/tools/llc/CMakeLists.txt
index 257d5b5..01825c6 100644
--- a/src/llvm-project/llvm/tools/llc/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llc/CMakeLists.txt
@@ -8,9 +8,11 @@
   CodeGen
   CodeGenTypes
   Core
+  IRPrinter
   IRReader
   MC
   MIRParser
+  Passes
   Remarks
   ScalarOpts
   SelectionDAG
@@ -23,6 +25,7 @@
 
 add_llvm_tool(llc
   llc.cpp
+  NewPMDriver.cpp
 
   DEPENDS
   intrinsics_gen
diff --git a/src/llvm-project/llvm/tools/llc/NewPMDriver.cpp b/src/llvm-project/llvm/tools/llc/NewPMDriver.cpp
new file mode 100644
index 0000000..13020f3
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llc/NewPMDriver.cpp
@@ -0,0 +1,236 @@
+//===- NewPMDriver.cpp - Driver for llc using new PM ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// This file is just a split of the code that logically belongs in llc.cpp but
+/// that includes the new pass manager headers.
+///
+//===----------------------------------------------------------------------===//
+
+#include "NewPMDriver.h"
+#include "llvm/Analysis/CGSCCPassManager.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
+#include "llvm/CodeGen/CodeGenPassBuilder.h"
+#include "llvm/CodeGen/CommandFlags.h"
+#include "llvm/CodeGen/MIRParser/MIRParser.h"
+#include "llvm/CodeGen/MIRPrinter.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/MachinePassManager.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/IR/Verifier.h"
+#include "llvm/IRReader/IRReader.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Passes/StandardInstrumentations.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FormattedStream.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Target/CGPassBuilderOption.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Transforms/Scalar/LoopPassManager.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+
+namespace llvm {
+extern cl::opt<bool> PrintPipelinePasses;
+} // namespace llvm
+
+using namespace llvm;
+
+static cl::opt<std::string>
+    RegAlloc("regalloc-npm",
+             cl::desc("Register allocator to use for new pass manager"),
+             cl::Hidden, cl::init("default"));
+
+static cl::opt<bool>
+    DebugPM("debug-pass-manager", cl::Hidden,
+            cl::desc("Print pass management debugging information"));
+
+bool LLCDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) {
+  DiagnosticHandler::handleDiagnostics(DI);
+  if (DI.getKind() == llvm::DK_SrcMgr) {
+    const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI);
+    const SMDiagnostic &SMD = DISM.getSMDiag();
+
+    SMD.print(nullptr, errs());
+
+    // For testing purposes, we print the LocCookie here.
+    if (DISM.isInlineAsmDiag() && DISM.getLocCookie())
+      WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n";
+
+    return true;
+  }
+
+  if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
+    if (!Remark->isEnabled())
+      return true;
+
+  DiagnosticPrinterRawOStream DP(errs());
+  errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
+  DI.print(DP);
+  errs() << "\n";
+  return true;
+}
+
+static llvm::ExitOnError ExitOnErr;
+
+static void RunPasses(bool BOS, ToolOutputFile *Out, Module *M,
+                      LLVMContext &Context, SmallString<0> &Buffer,
+                      ModulePassManager *MPM, ModuleAnalysisManager *MAM,
+                      MachineFunctionPassManager &MFPM,
+                      MachineFunctionAnalysisManager &MFAM) {
+  assert(M && "invalid input module!");
+
+  // Before executing passes, print the final values of the LLVM options.
+  cl::PrintOptionValues();
+
+  if (MPM) {
+    assert(MAM && "expect a ModuleAnalysisManager!");
+    MPM->run(*M, *MAM);
+  }
+
+  ExitOnErr(MFPM.run(*M, MFAM));
+
+  if (Context.getDiagHandlerPtr()->HasErrors)
+    exit(1);
+
+  if (BOS)
+    Out->os() << Buffer;
+}
+
+int llvm::compileModuleWithNewPM(
+    StringRef Arg0, std::unique_ptr<Module> M, std::unique_ptr<MIRParser> MIR,
+    std::unique_ptr<TargetMachine> Target, std::unique_ptr<ToolOutputFile> Out,
+    std::unique_ptr<ToolOutputFile> DwoOut, LLVMContext &Context,
+    const TargetLibraryInfoImpl &TLII, bool NoVerify, StringRef PassPipeline,
+    CodeGenFileType FileType) {
+
+  if (!PassPipeline.empty() && TargetPassConfig::hasLimitedCodeGenPipeline()) {
+    WithColor::warning(errs(), Arg0)
+        << "--passes cannot be used with "
+        << TargetPassConfig::getLimitedCodeGenPipelineReason() << ".\n";
+    return 1;
+  }
+
+  LLVMTargetMachine &LLVMTM = static_cast<LLVMTargetMachine &>(*Target);
+
+  raw_pwrite_stream *OS = &Out->os();
+
+  // Manually do the buffering rather than using buffer_ostream,
+  // so we can memcmp the contents in CompileTwice mode in future.
+  SmallString<0> Buffer;
+  std::unique_ptr<raw_svector_ostream> BOS;
+  if ((codegen::getFileType() != CodeGenFileType::AssemblyFile &&
+       !Out->os().supportsSeeking())) {
+    BOS = std::make_unique<raw_svector_ostream>(Buffer);
+    OS = BOS.get();
+  }
+
+  // Fetch options from TargetPassConfig
+  CGPassBuilderOption Opt = getCGPassBuilderOption();
+  Opt.DisableVerify = NoVerify;
+  Opt.DebugPM = DebugPM;
+  Opt.RegAlloc = RegAlloc;
+
+  PassInstrumentationCallbacks PIC;
+  StandardInstrumentations SI(Context, Opt.DebugPM);
+  SI.registerCallbacks(PIC);
+  registerCodeGenCallback(PIC, LLVMTM);
+
+  LoopAnalysisManager LAM;
+  FunctionAnalysisManager FAM;
+  CGSCCAnalysisManager CGAM;
+  ModuleAnalysisManager MAM;
+  PassBuilder PB(Target.get(), PipelineTuningOptions(), std::nullopt, &PIC);
+  PB.registerModuleAnalyses(MAM);
+  PB.registerCGSCCAnalyses(CGAM);
+  PB.registerFunctionAnalyses(FAM);
+  PB.registerLoopAnalyses(LAM);
+  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+  FAM.registerPass([&] { return TargetLibraryAnalysis(TLII); });
+  MAM.registerPass([&] { return MachineModuleAnalysis(&LLVMTM); });
+
+  MachineFunctionAnalysisManager MFAM(FAM, MAM);
+
+  if (!PassPipeline.empty()) {
+    // Construct a custom pass pipeline that starts after instruction
+    // selection.
+
+    if (!MIR) {
+      WithColor::warning(errs(), Arg0) << "-passes is for .mir file only.\n";
+      return 1;
+    }
+
+    MachineFunctionPassManager MFPM;
+    ExitOnErr(PB.parsePassPipeline(MFPM, PassPipeline));
+    MFPM.addPass(PrintMIRPass(*OS));
+    MFPM.addPass(FreeMachineFunctionPass());
+
+    auto &MMI = MFAM.getResult<MachineModuleAnalysis>(*M);
+    if (MIR->parseMachineFunctions(*M, MMI))
+      return 1;
+
+    RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, nullptr, nullptr,
+              MFPM, MFAM);
+  } else {
+    ModulePassManager MPM;
+    MachineFunctionPassManager MFPM;
+
+    ExitOnErr(LLVMTM.buildCodeGenPipeline(MPM, MFPM, MFAM, *OS,
+                                          DwoOut ? &DwoOut->os() : nullptr,
+                                          FileType, Opt, &PIC));
+
+    auto StartStopInfo = TargetPassConfig::getStartStopInfo(PIC);
+    assert(StartStopInfo && "Expect StartStopInfo!");
+    // Add IR or MIR printing pass according the pass type.
+
+    if (auto StopPassName = StartStopInfo->StopPass; !StopPassName.empty()) {
+      MFPM.addPass(PrintMIRPass(*OS));
+      MFPM.addPass(FreeMachineFunctionPass());
+    }
+
+    if (PrintPipelinePasses) {
+      std::string IRPipeline;
+      raw_string_ostream IRSOS(IRPipeline);
+      MPM.printPipeline(IRSOS, [&PIC](StringRef ClassName) {
+        auto PassName = PIC.getPassNameForClassName(ClassName);
+        return PassName.empty() ? ClassName : PassName;
+      });
+      outs() << "IR pipeline: " << IRPipeline << '\n';
+
+      std::string MIRPipeline;
+      raw_string_ostream MIRSOS(MIRPipeline);
+      MFPM.printPipeline(MIRSOS, [&PIC](StringRef ClassName) {
+        auto PassName = PIC.getPassNameForClassName(ClassName);
+        return PassName.empty() ? ClassName : PassName;
+      });
+      outs() << "MIR pipeline: " << MIRPipeline << '\n';
+      return 0;
+    }
+
+    RunPasses(BOS.get(), Out.get(), M.get(), Context, Buffer, &MPM, &MAM, MFPM,
+              MFAM);
+  }
+
+  // Declare success.
+  Out->keep();
+  if (DwoOut)
+    DwoOut->keep();
+
+  return 0;
+}
diff --git a/src/llvm-project/llvm/tools/llc/NewPMDriver.h b/src/llvm-project/llvm/tools/llc/NewPMDriver.h
new file mode 100644
index 0000000..b0beeaf
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llc/NewPMDriver.h
@@ -0,0 +1,49 @@
+//===- NewPMDriver.h - Function to drive llc with the new PM ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// \file
+///
+/// A single function which is called to drive the llc behavior for the new
+/// PassManager.
+///
+/// This is only in a separate TU with a header to avoid including all of the
+/// old pass manager headers and the new pass manager headers into the same
+/// file. Eventually all of the routines here will get folded back into
+/// llc.cpp.
+///
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_TOOLS_LLC_NEWPMDRIVER_H
+#define LLVM_TOOLS_LLC_NEWPMDRIVER_H
+
+#include "llvm/IR/DiagnosticHandler.h"
+#include "llvm/Support/CodeGen.h"
+#include <memory>
+#include <vector>
+
+namespace llvm {
+class Module;
+class TargetLibraryInfoImpl;
+class TargetMachine;
+class ToolOutputFile;
+class LLVMContext;
+class MIRParser;
+
+struct LLCDiagnosticHandler : public DiagnosticHandler {
+  bool handleDiagnostics(const DiagnosticInfo &DI) override;
+};
+
+int compileModuleWithNewPM(StringRef Arg0, std::unique_ptr<Module> M,
+                           std::unique_ptr<MIRParser> MIR,
+                           std::unique_ptr<TargetMachine> Target,
+                           std::unique_ptr<ToolOutputFile> Out,
+                           std::unique_ptr<ToolOutputFile> DwoOut,
+                           LLVMContext &Context,
+                           const TargetLibraryInfoImpl &TLII, bool NoVerify,
+                           StringRef PassPipeline, CodeGenFileType FileType);
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llc/llc.cpp b/src/llvm-project/llvm/tools/llc/llc.cpp
index 8934130..3e2567c 100644
--- a/src/llvm-project/llvm/tools/llc/llc.cpp
+++ b/src/llvm-project/llvm/tools/llc/llc.cpp
@@ -7,11 +7,12 @@
 //===----------------------------------------------------------------------===//
 //
 // This is the llc code generator driver. It provides a convenient
-// command-line interface for generating native assembly-language code
-// or C code, given LLVM bitcode.
+// command-line interface for generating an assembly file or a relocatable file,
+// given LLVM bitcode.
 //
 //===----------------------------------------------------------------------===//
 
+#include "NewPMDriver.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
@@ -186,6 +187,28 @@
     cl::desc("The format used for serializing remarks (default: YAML)"),
     cl::value_desc("format"), cl::init("yaml"));
 
+static cl::opt<bool> EnableNewPassManager(
+    "enable-new-pm", cl::desc("Enable the new pass manager"), cl::init(false));
+
+// This flag specifies a textual description of the optimization pass pipeline
+// to run over the module. This flag switches opt to use the new pass manager
+// infrastructure, completely disabling all of the flags specific to the old
+// pass management.
+static cl::opt<std::string> PassPipeline(
+    "passes",
+    cl::desc(
+        "A textual description of the pass pipeline. To have analysis passes "
+        "available before a certain pass, add 'require<foo-analysis>'."));
+static cl::alias PassPipeline2("p", cl::aliasopt(PassPipeline),
+                               cl::desc("Alias for -passes"));
+
+static cl::opt<bool> TryUseNewDbgInfoFormat(
+    "try-experimental-debuginfo-iterators",
+    cl::desc("Enable debuginfo iterator positions, if they're built in"),
+    cl::init(false), cl::Hidden);
+
+extern cl::opt<bool> UseNewDbgInfoFormat;
+
 namespace {
 
 std::vector<std::string> &getRunPassNames() {
@@ -203,7 +226,7 @@
       getRunPassNames().push_back(std::string(PassName));
   }
 };
-}
+} // namespace
 
 static RunPassOption RunPassOpt;
 
@@ -242,32 +265,24 @@
     else {
       // If InputFilename ends in .bc or .ll, remove it.
       StringRef IFN = InputFilename;
-      if (IFN.endswith(".bc") || IFN.endswith(".ll"))
+      if (IFN.ends_with(".bc") || IFN.ends_with(".ll"))
         OutputFilename = std::string(IFN.drop_back(3));
-      else if (IFN.endswith(".mir"))
+      else if (IFN.ends_with(".mir"))
         OutputFilename = std::string(IFN.drop_back(4));
       else
         OutputFilename = std::string(IFN);
 
       switch (codegen::getFileType()) {
-      case CGFT_AssemblyFile:
-        if (TargetName[0] == 'c') {
-          if (TargetName[1] == 0)
-            OutputFilename += ".cbe.c";
-          else if (TargetName[1] == 'p' && TargetName[2] == 'p')
-            OutputFilename += ".cpp";
-          else
-            OutputFilename += ".s";
-        } else
-          OutputFilename += ".s";
+      case CodeGenFileType::AssemblyFile:
+        OutputFilename += ".s";
         break;
-      case CGFT_ObjectFile:
+      case CodeGenFileType::ObjectFile:
         if (OS == Triple::Win32)
           OutputFilename += ".obj";
         else
           OutputFilename += ".o";
         break;
-      case CGFT_Null:
+      case CodeGenFileType::Null:
         OutputFilename = "-";
         break;
       }
@@ -277,10 +292,10 @@
   // Decide if we need "binary" output.
   bool Binary = false;
   switch (codegen::getFileType()) {
-  case CGFT_AssemblyFile:
+  case CodeGenFileType::AssemblyFile:
     break;
-  case CGFT_ObjectFile:
-  case CGFT_Null:
+  case CodeGenFileType::ObjectFile:
+  case CodeGenFileType::Null:
     Binary = true;
     break;
   }
@@ -299,41 +314,6 @@
   return FDOut;
 }
 
-struct LLCDiagnosticHandler : public DiagnosticHandler {
-  bool *HasError;
-  LLCDiagnosticHandler(bool *HasErrorPtr) : HasError(HasErrorPtr) {}
-  bool handleDiagnostics(const DiagnosticInfo &DI) override {
-    if (DI.getKind() == llvm::DK_SrcMgr) {
-      const auto &DISM = cast<DiagnosticInfoSrcMgr>(DI);
-      const SMDiagnostic &SMD = DISM.getSMDiag();
-
-      if (SMD.getKind() == SourceMgr::DK_Error)
-        *HasError = true;
-
-      SMD.print(nullptr, errs());
-
-      // For testing purposes, we print the LocCookie here.
-      if (DISM.isInlineAsmDiag() && DISM.getLocCookie())
-        WithColor::note() << "!srcloc = " << DISM.getLocCookie() << "\n";
-
-      return true;
-    }
-
-    if (DI.getSeverity() == DS_Error)
-      *HasError = true;
-
-    if (auto *Remark = dyn_cast<DiagnosticInfoOptimizationBase>(&DI))
-      if (!Remark->isEnabled())
-        return true;
-
-    DiagnosticPrinterRawOStream DP(errs());
-    errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": ";
-    DI.print(DP);
-    errs() << "\n";
-    return true;
-  }
-};
-
 // main - Entry point for the llc compiler.
 //
 int main(int argc, char **argv) {
@@ -377,6 +357,24 @@
 
   cl::ParseCommandLineOptions(argc, argv, "llvm system compiler\n");
 
+  if (!PassPipeline.empty() && !getRunPassNames().empty()) {
+    errs() << "The `llc -run-pass=...` syntax for the new pass manager is "
+              "not supported, please use `llc -passes=<pipeline>` (or the `-p` "
+              "alias for a more concise version).\n";
+    return 1;
+  }
+
+  // RemoveDIs debug-info transition: tests may request that we /try/ to use the
+  // new debug-info format, if it's built in.
+#ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
+  if (TryUseNewDbgInfoFormat) {
+    // If LLVM was built with support for this, turn the new debug-info format
+    // on.
+    UseNewDbgInfoFormat = true;
+  }
+#endif
+  (void)TryUseNewDbgInfoFormat;
+
   if (TimeTrace)
     timeTraceProfilerInitialize(TimeTraceGranularity, argv[0]);
   auto TimeTraceScopeExit = make_scope_exit([]() {
@@ -395,9 +393,7 @@
   Context.setDiscardValueNames(DiscardValueNames);
 
   // Set a diagnostic handler that doesn't exit on the first error
-  bool HasError = false;
-  Context.setDiagnosticHandler(
-      std::make_unique<LLCDiagnosticHandler>(&HasError));
+  Context.setDiagnosticHandler(std::make_unique<LLCDiagnosticHandler>());
 
   Expected<std::unique_ptr<ToolOutputFile>> RemarksFileOrErr =
       setupLLVMOptimizationRemarks(Context, RemarksFilename, RemarksPasses,
@@ -468,7 +464,7 @@
   bool SkipModule =
       CPUStr == "help" || (!MAttrs.empty() && MAttrs.front() == "help");
 
-  CodeGenOpt::Level OLvl;
+  CodeGenOptLevel OLvl;
   if (auto Level = CodeGenOpt::parseLevel(OptLevel)) {
     OLvl = *Level;
   } else {
@@ -558,12 +554,6 @@
         exit(1);
       }
 
-      // On AIX, setting the relocation model to anything other than PIC is
-      // considered a user error.
-      if (TheTriple.isOSAIX() && RM && *RM != Reloc::PIC_)
-        reportError("invalid relocation model, AIX only supports PIC",
-                    InputFilename);
-
       InitializeOptions(TheTriple);
       Target = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
           TheTriple.getTriple(), CPUStr, FeaturesStr, Options, RM, CM, OLvl));
@@ -572,7 +562,7 @@
       return Target->createDataLayout().getStringRepresentation();
     };
     if (InputLanguage == "mir" ||
-        (InputLanguage == "" && StringRef(InputFilename).endswith(".mir"))) {
+        (InputLanguage == "" && StringRef(InputFilename).ends_with(".mir"))) {
       MIR = createMIRParserFromFile(InputFilename, Err, Context,
                                     setMIRFunctionAttributes);
       if (MIR)
@@ -591,6 +581,8 @@
     std::optional<CodeModel::Model> CM_IR = M->getCodeModel();
     if (!CM && CM_IR)
       Target->setCodeModel(*CM_IR);
+    if (std::optional<uint64_t> LDT = codegen::getExplicitLargeDataThreshold())
+      Target->setLargeDataThreshold(*LDT);
   } else {
     TheTriple = Triple(Triple::normalize(TargetTriple));
     if (TheTriple.getTriple().empty())
@@ -605,14 +597,6 @@
       return 1;
     }
 
-    // On AIX, setting the relocation model to anything other than PIC is
-    // considered a user error.
-    if (TheTriple.isOSAIX() && RM && *RM != Reloc::PIC_) {
-      WithColor::error(errs(), argv[0])
-          << "invalid relocation model, AIX only supports PIC.\n";
-      return 1;
-    }
-
     InitializeOptions(TheTriple);
     Target = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
         TheTriple.getTriple(), CPUStr, FeaturesStr, Options, RM, CM, OLvl));
@@ -626,7 +610,7 @@
 
   assert(M && "Should have exited if we didn't have a module!");
   if (codegen::getFloatABIForCalls() != FloatABI::Default)
-    Options.FloatABIType = codegen::getFloatABIForCalls();
+    Target->Options.FloatABIType = codegen::getFloatABIForCalls();
 
   // Figure out where we are going to send the output.
   std::unique_ptr<ToolOutputFile> Out =
@@ -645,16 +629,12 @@
       reportError(EC.message(), SplitDwarfOutputFile);
   }
 
-  // Build up all of the passes that we want to do to the module.
-  legacy::PassManager PM;
-
   // Add an appropriate TargetLibraryInfo pass for the module's triple.
   TargetLibraryInfoImpl TLII(Triple(M->getTargetTriple()));
 
   // The -disable-simplify-libcalls flag actually disables all builtin optzns.
   if (DisableSimplifyLibCalls)
     TLII.disableAllFunctions();
-  PM.add(new TargetLibraryInfoWrapperPass(TLII));
 
   // Verify module immediately to catch problems before doInitialization() is
   // called on any passes.
@@ -665,10 +645,22 @@
   // flags.
   codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M);
 
-  if (mc::getExplicitRelaxAll() && codegen::getFileType() != CGFT_ObjectFile)
+  if (mc::getExplicitRelaxAll() &&
+      codegen::getFileType() != CodeGenFileType::ObjectFile)
     WithColor::warning(errs(), argv[0])
         << ": warning: ignoring -mc-relax-all because filetype != obj";
 
+  if (EnableNewPassManager || !PassPipeline.empty()) {
+    return compileModuleWithNewPM(argv[0], std::move(M), std::move(MIR),
+                                  std::move(Target), std::move(Out),
+                                  std::move(DwoOut), Context, TLII, NoVerify,
+                                  PassPipeline, codegen::getFileType());
+  }
+
+  // Build up all of the passes that we want to do to the module.
+  legacy::PassManager PM;
+  PM.add(new TargetLibraryInfoWrapperPass(TLII));
+
   {
     raw_pwrite_stream *OS = &Out->os();
 
@@ -676,7 +668,7 @@
     // so we can memcmp the contents in CompileTwice mode
     SmallVector<char, 0> Buffer;
     std::unique_ptr<raw_svector_ostream> BOS;
-    if ((codegen::getFileType() != CGFT_AssemblyFile &&
+    if ((codegen::getFileType() != CodeGenFileType::AssemblyFile &&
          !Out->os().supportsSeeking()) ||
         CompileTwice) {
       BOS = std::make_unique<raw_svector_ostream>(Buffer);
@@ -702,7 +694,7 @@
       if (TPC.hasLimitedCodeGenPipeline()) {
         WithColor::warning(errs(), argv[0])
             << "run-pass cannot be used with "
-            << TPC.getLimitedCodeGenPipelineReason(" and ") << ".\n";
+            << TPC.getLimitedCodeGenPipelineReason() << ".\n";
         delete PTPC;
         delete MMIWP;
         return 1;
@@ -750,9 +742,7 @@
 
     PM.run(*M);
 
-    auto HasError =
-        ((const LLCDiagnosticHandler *)(Context.getDiagHandlerPtr()))->HasError;
-    if (*HasError)
+    if (Context.getDiagHandlerPtr()->HasErrors)
       return 1;
 
     // Compare the two outputs and make sure they're the same
diff --git a/src/llvm-project/llvm/tools/lli/CMakeLists.txt b/src/llvm-project/llvm/tools/lli/CMakeLists.txt
index 3b3cf91..e3fca22 100644
--- a/src/llvm-project/llvm/tools/lli/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/lli/CMakeLists.txt
@@ -12,8 +12,9 @@
   MC
   MCJIT
   Object
-  OrcShared
   OrcJIT
+  OrcDebugging
+  OrcShared
   OrcTargetProcess
   Passes
   RuntimeDyld
@@ -52,7 +53,6 @@
 
 add_llvm_tool(lli
   lli.cpp
-  ExecutionUtils.cpp
 
   DEPENDS
   intrinsics_gen
diff --git a/src/llvm-project/llvm/tools/lli/ChildTarget/ChildTarget.cpp b/src/llvm-project/llvm/tools/lli/ChildTarget/ChildTarget.cpp
index cf1b03a..cb81ac5 100644
--- a/src/llvm-project/llvm/tools/lli/ChildTarget/ChildTarget.cpp
+++ b/src/llvm-project/llvm/tools/lli/ChildTarget/ChildTarget.cpp
@@ -10,7 +10,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ADT/StringRef.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.h"
diff --git a/src/llvm-project/llvm/tools/lli/ExecutionUtils.cpp b/src/llvm-project/llvm/tools/lli/ExecutionUtils.cpp
deleted file mode 100644
index 55370ed..0000000
--- a/src/llvm-project/llvm/tools/lli/ExecutionUtils.cpp
+++ /dev/null
@@ -1,146 +0,0 @@
-//===---- ExecutionUtils.cpp - Utilities for executing functions in lli ---===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "ExecutionUtils.h"
-
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <cstdint>
-#include <vector>
-
-// Declarations follow the GDB JIT interface (version 1, 2009) and must match
-// those of the DYLD used for testing. See:
-//
-//   llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
-//   llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp
-//
-typedef enum {
-  JIT_NOACTION = 0,
-  JIT_REGISTER_FN,
-  JIT_UNREGISTER_FN
-} jit_actions_t;
-
-struct jit_code_entry {
-  struct jit_code_entry *next_entry;
-  struct jit_code_entry *prev_entry;
-  const char *symfile_addr;
-  uint64_t symfile_size;
-};
-
-struct jit_descriptor {
-  uint32_t version;
-  // This should be jit_actions_t, but we want to be specific about the
-  // bit-width.
-  uint32_t action_flag;
-  struct jit_code_entry *relevant_entry;
-  struct jit_code_entry *first_entry;
-};
-
-namespace llvm {
-
-template <typename... Ts> static void outsv(const char *Fmt, Ts &&...Vals) {
-  outs() << formatv(Fmt, Vals...);
-}
-
-static const char *actionFlagToStr(uint32_t ActionFlag) {
-  switch (ActionFlag) {
-  case JIT_NOACTION:
-    return "JIT_NOACTION";
-  case JIT_REGISTER_FN:
-    return "JIT_REGISTER_FN";
-  case JIT_UNREGISTER_FN:
-    return "JIT_UNREGISTER_FN";
-  }
-  return "<invalid action_flag>";
-}
-
-// Sample output:
-//
-//   Reading __jit_debug_descriptor at 0x0000000000404048
-//
-//   Version: 0
-//   Action: JIT_REGISTER_FN
-//
-//         Entry               Symbol File         Size  Previous Entry
-//   [ 0]  0x0000000000451290  0x0000000000002000   200  0x0000000000000000
-//   [ 1]  0x0000000000451260  0x0000000000001000   100  0x0000000000451290
-//   ...
-//
-static void dumpDebugDescriptor(void *Addr) {
-  outsv("Reading __jit_debug_descriptor at {0}\n\n", Addr);
-
-  jit_descriptor *Descriptor = reinterpret_cast<jit_descriptor *>(Addr);
-  outsv("Version: {0}\n", Descriptor->version);
-  outsv("Action: {0}\n\n", actionFlagToStr(Descriptor->action_flag));
-  outsv("{0,11}  {1,24}  {2,15}  {3,14}\n", "Entry", "Symbol File", "Size",
-        "Previous Entry");
-
-  unsigned Idx = 0;
-  for (auto *Entry = Descriptor->first_entry; Entry; Entry = Entry->next_entry)
-    outsv("[{0,2}]  {1:X16}  {2:X16}  {3,8:D}  {4}\n", Idx++, Entry,
-          reinterpret_cast<const void *>(Entry->symfile_addr),
-          Entry->symfile_size, Entry->prev_entry);
-}
-
-static LLIBuiltinFunctionGenerator *Generator = nullptr;
-
-static void dumpDebugObjects(void *Addr) {
-  jit_descriptor *Descriptor = reinterpret_cast<jit_descriptor *>(Addr);
-  for (auto *Entry = Descriptor->first_entry; Entry; Entry = Entry->next_entry)
-    Generator->appendDebugObject(Entry->symfile_addr, Entry->symfile_size);
-}
-
-LLIBuiltinFunctionGenerator::LLIBuiltinFunctionGenerator(
-    std::vector<BuiltinFunctionKind> Enabled, orc::MangleAndInterner &Mangle)
-    : TestOut(nullptr) {
-  Generator = this;
-  for (BuiltinFunctionKind F : Enabled) {
-    switch (F) {
-    case BuiltinFunctionKind::DumpDebugDescriptor:
-      expose(Mangle("__dump_jit_debug_descriptor"), &dumpDebugDescriptor);
-      break;
-    case BuiltinFunctionKind::DumpDebugObjects:
-      expose(Mangle("__dump_jit_debug_objects"), &dumpDebugObjects);
-      TestOut = createToolOutput();
-      break;
-    }
-  }
-}
-
-Error LLIBuiltinFunctionGenerator::tryToGenerate(
-    orc::LookupState &LS, orc::LookupKind K, orc::JITDylib &JD,
-    orc::JITDylibLookupFlags JDLookupFlags,
-    const orc::SymbolLookupSet &Symbols) {
-  orc::SymbolMap NewSymbols;
-  for (const auto &NameFlags : Symbols) {
-    auto It = BuiltinFunctions.find(NameFlags.first);
-    if (It != BuiltinFunctions.end())
-      NewSymbols.insert(*It);
-  }
-
-  if (NewSymbols.empty())
-    return Error::success();
-
-  return JD.define(absoluteSymbols(std::move(NewSymbols)));
-}
-
-// static
-std::unique_ptr<ToolOutputFile>
-LLIBuiltinFunctionGenerator::createToolOutput() {
-  std::error_code EC;
-  auto TestOut = std::make_unique<ToolOutputFile>("-", EC, sys::fs::OF_None);
-  if (EC) {
-    errs() << "Error creating tool output file: " << EC.message() << '\n';
-    exit(1);
-  }
-  return TestOut;
-}
-
-} // namespace llvm
diff --git a/src/llvm-project/llvm/tools/lli/ExecutionUtils.h b/src/llvm-project/llvm/tools/lli/ExecutionUtils.h
deleted file mode 100644
index 6bf9cd5..0000000
--- a/src/llvm-project/llvm/tools/lli/ExecutionUtils.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//===- ExecutionUtils.h - Utilities for executing code in lli ---*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Contains utilities for executing code in lli.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_TOOLS_LLI_EXECUTIONUTILS_H
-#define LLVM_TOOLS_LLI_EXECUTIONUTILS_H
-
-#include "llvm/ExecutionEngine/JITSymbol.h"
-#include "llvm/ExecutionEngine/Orc/Core.h"
-#include "llvm/ExecutionEngine/Orc/Mangling.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ToolOutputFile.h"
-
-#include <memory>
-#include <utility>
-
-namespace llvm {
-
-enum class BuiltinFunctionKind {
-  DumpDebugDescriptor,
-  DumpDebugObjects,
-};
-
-// Utility class to expose symbols for special-purpose functions to the JIT.
-class LLIBuiltinFunctionGenerator : public orc::DefinitionGenerator {
-public:
-  LLIBuiltinFunctionGenerator(std::vector<BuiltinFunctionKind> Enabled,
-                              orc::MangleAndInterner &Mangle);
-
-  Error tryToGenerate(orc::LookupState &LS, orc::LookupKind K,
-                      orc::JITDylib &JD, orc::JITDylibLookupFlags JDLookupFlags,
-                      const orc::SymbolLookupSet &Symbols) override;
-
-  void appendDebugObject(const char *Addr, size_t Size) {
-    TestOut->os().write(Addr, Size);
-  }
-
-private:
-  orc::SymbolMap BuiltinFunctions;
-  std::unique_ptr<ToolOutputFile> TestOut;
-
-  template <typename T> void expose(orc::SymbolStringPtr Name, T *Handler) {
-    BuiltinFunctions[Name] = {orc::ExecutorAddr::fromPtr(Handler),
-                              JITSymbolFlags::Exported};
-  }
-
-  static std::unique_ptr<ToolOutputFile> createToolOutput();
-};
-
-} // end namespace llvm
-
-#endif // LLVM_TOOLS_LLI_EXECUTIONUTILS_H
diff --git a/src/llvm-project/llvm/tools/lli/ForwardingMemoryManager.h b/src/llvm-project/llvm/tools/lli/ForwardingMemoryManager.h
index f1de7a1..2cc6699 100644
--- a/src/llvm-project/llvm/tools/lli/ForwardingMemoryManager.h
+++ b/src/llvm-project/llvm/tools/lli/ForwardingMemoryManager.h
@@ -105,13 +105,14 @@
   JITSymbol findSymbol(const std::string &Name) override {
     orc::RemoteSymbolLookupSet R;
     R.push_back({std::move(Name), false});
-    if (auto Addrs = DylibMgr.lookup(H, R)) {
-      if (Addrs->size() != 1)
+    if (auto Syms = DylibMgr.lookup(H, R)) {
+      if (Syms->size() != 1)
         return make_error<StringError>("Unexpected remote lookup result",
                                        inconvertibleErrorCode());
-      return JITSymbol(Addrs->front().getValue(), JITSymbolFlags::Exported);
+      return JITSymbol(Syms->front().getAddress().getValue(),
+                       Syms->front().getFlags());
     } else
-      return Addrs.takeError();
+      return Syms.takeError();
   }
 
   JITSymbol findSymbolInLogicalDylib(const std::string &Name) override {
diff --git a/src/llvm-project/llvm/tools/lli/lli.cpp b/src/llvm-project/llvm/tools/lli/lli.cpp
index e2fff69..905ec23 100644
--- a/src/llvm-project/llvm/tools/lli/lli.cpp
+++ b/src/llvm-project/llvm/tools/lli/lli.cpp
@@ -12,7 +12,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "ExecutionUtils.h"
 #include "ForwardingMemoryManager.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Bitcode/BitcodeReader.h"
@@ -26,12 +25,14 @@
 #include "llvm/ExecutionEngine/MCJIT.h"
 #include "llvm/ExecutionEngine/ObjectCache.h"
 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
+#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupport.h"
 #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
 #include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
 #include "llvm/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.h"
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
+#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
 #include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
@@ -61,6 +62,7 @@
 #include "llvm/Support/Program.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TargetParser/Triple.h"
@@ -253,35 +255,29 @@
     NoDump,
     DumpFuncsToStdOut,
     DumpModsToStdOut,
-    DumpModsToDisk
+    DumpModsToDisk,
+    DumpDebugDescriptor,
+    DumpDebugObjects,
   };
 
   cl::opt<DumpKind> OrcDumpKind(
       "orc-lazy-debug", cl::desc("Debug dumping for the orc-lazy JIT."),
       cl::init(DumpKind::NoDump),
-      cl::values(clEnumValN(DumpKind::NoDump, "no-dump",
-                            "Don't dump anything."),
-                 clEnumValN(DumpKind::DumpFuncsToStdOut, "funcs-to-stdout",
-                            "Dump function names to stdout."),
-                 clEnumValN(DumpKind::DumpModsToStdOut, "mods-to-stdout",
-                            "Dump modules to stdout."),
-                 clEnumValN(DumpKind::DumpModsToDisk, "mods-to-disk",
-                            "Dump modules to the current "
-                            "working directory. (WARNING: "
-                            "will overwrite existing files).")),
-      cl::Hidden);
-
-  cl::list<BuiltinFunctionKind> GenerateBuiltinFunctions(
-      "generate",
-      cl::desc("Provide built-in functions for access by JITed code "
-               "(jit-kind=orc-lazy only)"),
-      cl::values(clEnumValN(BuiltinFunctionKind::DumpDebugDescriptor,
-                            "__dump_jit_debug_descriptor",
-                            "Dump __jit_debug_descriptor contents to stdout"),
-                 clEnumValN(BuiltinFunctionKind::DumpDebugObjects,
-                            "__dump_jit_debug_objects",
-                            "Dump __jit_debug_descriptor in-memory debug "
-                            "objects as tool output")),
+      cl::values(
+          clEnumValN(DumpKind::NoDump, "no-dump", "Don't dump anything."),
+          clEnumValN(DumpKind::DumpFuncsToStdOut, "funcs-to-stdout",
+                     "Dump function names to stdout."),
+          clEnumValN(DumpKind::DumpModsToStdOut, "mods-to-stdout",
+                     "Dump modules to stdout."),
+          clEnumValN(DumpKind::DumpModsToDisk, "mods-to-disk",
+                     "Dump modules to the current "
+                     "working directory. (WARNING: "
+                     "will overwrite existing files)."),
+          clEnumValN(DumpKind::DumpDebugDescriptor, "jit-debug-descriptor",
+                     "Dump __jit_debug_descriptor contents to stdout"),
+          clEnumValN(DumpKind::DumpDebugObjects, "jit-debug-objects",
+                     "Dump __jit_debug_descriptor in-memory debug "
+                     "objects as tool output")),
       cl::Hidden);
 
   ExitOnError ExitOnErr;
@@ -405,7 +401,7 @@
   EE.addModule(std::move(M));
 }
 
-CodeGenOpt::Level getOptLevel() {
+CodeGenOptLevel getOptLevel() {
   if (auto Level = CodeGenOpt::parseLevel(OptLevel))
     return *Level;
   WithColor::error(errs(), "lli") << "invalid optimization level.\n";
@@ -446,7 +442,13 @@
 
   ExitOnErr(loadDylibs());
 
-  if (UseJITKind == JITKind::MCJIT)
+  if (EntryFunc.empty()) {
+    WithColor::error(errs(), argv[0])
+        << "--entry-function name cannot be empty\n";
+    exit(1);
+  }
+
+  if (UseJITKind == JITKind::MCJIT || ForceInterpreter)
     disallowOrcOptions();
   else
     return runOrcJIT(argv[0]);
@@ -615,7 +617,7 @@
   } else {
     // Otherwise, if there is a .bc suffix on the executable strip it off, it
     // might confuse the program.
-    if (StringRef(InputFile).endswith(".bc"))
+    if (StringRef(InputFile).ends_with(".bc"))
       InputFile.erase(InputFile.length() - 3);
   }
 
@@ -749,9 +751,41 @@
   return Result;
 }
 
-static std::function<void(Module &)> createDebugDumper() {
+// JITLink debug support plugins put information about JITed code in this GDB
+// JIT Interface global from OrcTargetProcess.
+extern "C" struct jit_descriptor __jit_debug_descriptor;
+
+static struct jit_code_entry *
+findNextDebugDescriptorEntry(struct jit_code_entry *Latest) {
+  if (Latest == nullptr)
+    return __jit_debug_descriptor.first_entry;
+  if (Latest->next_entry)
+    return Latest->next_entry;
+  return nullptr;
+}
+
+static ToolOutputFile &claimToolOutput() {
+  static std::unique_ptr<ToolOutputFile> ToolOutput = nullptr;
+  if (ToolOutput) {
+    WithColor::error(errs(), "lli")
+        << "Can not claim stdout for tool output twice\n";
+    exit(1);
+  }
+  std::error_code EC;
+  ToolOutput = std::make_unique<ToolOutputFile>("-", EC, sys::fs::OF_None);
+  if (EC) {
+    WithColor::error(errs(), "lli")
+        << "Failed to create tool output file: " << EC.message() << "\n";
+    exit(1);
+  }
+  return *ToolOutput;
+}
+
+static std::function<void(Module &)> createIRDebugDumper() {
   switch (OrcDumpKind) {
   case DumpKind::NoDump:
+  case DumpKind::DumpDebugDescriptor:
+  case DumpKind::DumpDebugObjects:
     return [](Module &M) {};
 
   case DumpKind::DumpFuncsToStdOut:
@@ -793,6 +827,43 @@
   llvm_unreachable("Unknown DumpKind");
 }
 
+static std::function<void(MemoryBuffer &)> createObjDebugDumper() {
+  switch (OrcDumpKind) {
+  case DumpKind::NoDump:
+  case DumpKind::DumpFuncsToStdOut:
+  case DumpKind::DumpModsToStdOut:
+  case DumpKind::DumpModsToDisk:
+    return [](MemoryBuffer &) {};
+
+  case DumpKind::DumpDebugDescriptor: {
+    // Dump the empty descriptor at startup once
+    fprintf(stderr, "jit_debug_descriptor 0x%016" PRIx64 "\n",
+            pointerToJITTargetAddress(__jit_debug_descriptor.first_entry));
+    return [](MemoryBuffer &) {
+      // Dump new entries as they appear
+      static struct jit_code_entry *Latest = nullptr;
+      while (auto *NewEntry = findNextDebugDescriptorEntry(Latest)) {
+        fprintf(stderr, "jit_debug_descriptor 0x%016" PRIx64 "\n",
+                pointerToJITTargetAddress(NewEntry));
+        Latest = NewEntry;
+      }
+    };
+  }
+
+  case DumpKind::DumpDebugObjects: {
+    return [](MemoryBuffer &Obj) {
+      static struct jit_code_entry *Latest = nullptr;
+      static ToolOutputFile &ToolOutput = claimToolOutput();
+      while (auto *NewEntry = findNextDebugDescriptorEntry(Latest)) {
+        ToolOutput.os().write(NewEntry->symfile_addr, NewEntry->symfile_size);
+        Latest = NewEntry;
+      }
+    };
+  }
+  }
+  llvm_unreachable("Unknown DumpKind");
+}
+
 Error loadDylibs() {
   for (const auto &Dylib : Dylibs) {
     std::string ErrMsg;
@@ -838,6 +909,17 @@
   return 0;
 }
 
+// Try to enable debugger support for the given instance.
+// This alway returns success, but prints a warning if it's not able to enable
+// debugger support.
+Error tryEnableDebugSupport(orc::LLJIT &J) {
+  if (auto Err = enableDebuggerSupport(J)) {
+    [[maybe_unused]] std::string ErrMsg = toString(std::move(Err));
+    LLVM_DEBUG(dbgs() << "lli: " << ErrMsg << "\n");
+  }
+  return Error::success();
+}
+
 int runOrcJIT(const char *ProgName) {
   // Start setting up the JIT environment.
 
@@ -918,6 +1000,9 @@
       });
   }
 
+  // Enable debugging of JIT'd code (only works on JITLink for ELF and MachO).
+  Builder.setPrePlatformSetup(tryEnableDebugSupport);
+
   // Set up LLJIT platform.
   LLJITPlatform P = Platform;
   if (P == LLJITPlatform::Auto)
@@ -944,9 +1029,12 @@
     EPC = ExitOnErr(orc::SelfExecutorProcessControl::Create(
         std::make_shared<orc::SymbolStringPool>()));
 
-    Builder.setObjectLinkingLayerCreator([&EPC, &P](orc::ExecutionSession &ES,
-                                                    const Triple &TT) {
-      auto L = std::make_unique<orc::ObjectLinkingLayer>(ES, EPC->getMemMgr());
+    Builder.getJITTargetMachineBuilder()
+        ->setRelocationModel(Reloc::PIC_)
+        .setCodeModel(CodeModel::Small);
+    Builder.setObjectLinkingLayerCreator([&P](orc::ExecutionSession &ES,
+                                              const Triple &TT) {
+      auto L = std::make_unique<orc::ObjectLinkingLayer>(ES);
       if (P != LLJITPlatform::ExecutorNative)
         L->addPlugin(std::make_unique<orc::EHFrameRegistrationPlugin>(
             ES, ExitOnErr(orc::EPCEHFrameRegistrar::Create(ES))));
@@ -954,9 +1042,6 @@
     });
   }
 
-  // Enable debugging of JIT'd code (only works on JITLink for ELF and MachO).
-  Builder.setEnableDebuggerSupport(true);
-
   auto J = ExitOnErr(Builder.create());
 
   auto *ObjLayer = &J->getObjLinkingLayer();
@@ -980,8 +1065,7 @@
   if (PerModuleLazy)
     J->setPartitionFunction(orc::CompileOnDemandLayer::compileWholeModule);
 
-  auto Dump = createDebugDumper();
-
+  auto IRDump = createIRDebugDumper();
   J->getIRTransformLayer().setTransform(
       [&](orc::ThreadSafeModule TSM,
           const orc::MaterializationResponsibility &R) {
@@ -990,18 +1074,18 @@
             dbgs() << "Bad module: " << &M << "\n";
             exit(1);
           }
-          Dump(M);
+          IRDump(M);
         });
         return TSM;
       });
 
-  if (GenerateBuiltinFunctions.size() > 0) {
-    // Add LLI builtins.
-    orc::MangleAndInterner Mangle(J->getExecutionSession(), J->getDataLayout());
-    J->getMainJITDylib().addGenerator(
-        std::make_unique<LLIBuiltinFunctionGenerator>(GenerateBuiltinFunctions,
-                                                      Mangle));
-  }
+  auto ObjDump = createObjDebugDumper();
+  J->getObjTransformLayer().setTransform(
+      [&](std::unique_ptr<MemoryBuffer> Obj)
+          -> Expected<std::unique_ptr<MemoryBuffer>> {
+        ObjDump(*Obj);
+        return std::move(Obj);
+      });
 
   // If this is a Mingw or Cygwin executor then we need to alias __main to
   // orc_rt_int_void_return_0.
diff --git a/src/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp b/src/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp
index d21650d..c880030 100644
--- a/src/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -25,7 +25,6 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/LineIterator.h"
 #include "llvm/Support/MemoryBuffer.h"
@@ -69,7 +68,9 @@
          << "  -v --version          - Display the version of this program\n"
          << "  -D                    - Use zero for timestamps and uids/gids "
             "(default)\n"
-         << "  -U                    - Use actual timestamps and uids/gids\n";
+         << "  -U                    - Use actual timestamps and uids/gids\n"
+         << "  -X{32|64|32_64|any}   - Specify which archive symbol tables "
+            "should be generated if they do not already exist (AIX OS only)\n";
 }
 
 static void printArHelp(StringRef ToolName) {
@@ -225,7 +226,8 @@
 static bool CompareFullPath = false;      ///< 'P' modifier
 static bool OnlyUpdate = false;           ///< 'u' modifier
 static bool Verbose = false;              ///< 'v' modifier
-static bool Symtab = true;                ///< 's' modifier
+static SymtabWritingMode Symtab =
+    SymtabWritingMode::NormalSymtab;      ///< 's' modifier
 static bool Deterministic = true;         ///< 'D' and 'U' modifiers
 static bool Thin = false;                 ///< 'T' modifier
 static bool AddLibrary = false;           ///< 'L' modifier
@@ -371,11 +373,11 @@
       CompareFullPath = true;
       break;
     case 's':
-      Symtab = true;
+      Symtab = SymtabWritingMode::NormalSymtab;
       MaybeJustCreateSymTab = true;
       break;
     case 'S':
-      Symtab = false;
+      Symtab = SymtabWritingMode::NoSymtab;
       break;
     case 'u':
       OnlyUpdate = true;
@@ -1074,9 +1076,31 @@
   // In summary, we only need to update the symbol table if we have none.
   // This is actually very common because of broken build systems that think
   // they have to run ranlib.
-  if (OldArchive->hasSymbolTable())
-    return;
+  if (OldArchive->hasSymbolTable()) {
+    if (OldArchive->kind() != object::Archive::K_AIXBIG)
+      return;
 
+    // For archives in the Big Archive format, the bit mode option specifies
+    // which symbol table to generate. The presence of a symbol table that does
+    // not match the specified bit mode does not prevent creation of the symbol
+    // table that has been requested.
+    if (OldArchive->kind() == object::Archive::K_AIXBIG) {
+      BigArchive *BigArc = dyn_cast<BigArchive>(OldArchive);
+      if (BigArc->has32BitGlobalSymtab() &&
+          Symtab == SymtabWritingMode::BigArchive32)
+        return;
+
+      if (BigArc->has64BitGlobalSymtab() &&
+          Symtab == SymtabWritingMode::BigArchive64)
+        return;
+
+      if (BigArc->has32BitGlobalSymtab() && BigArc->has64BitGlobalSymtab() &&
+          Symtab == SymtabWritingMode::NormalSymtab)
+        return;
+
+      Symtab = SymtabWritingMode::NormalSymtab;
+    }
+  }
   if (OldArchive->isThin())
     Thin = true;
   performWriteOperation(CreateSymTab, OldArchive, nullptr, nullptr);
@@ -1262,8 +1286,7 @@
                                     ArrayRef<const char *> Args) {
   StringRef Arg = *ArgIt;
 
-  if (Arg.startswith("--"))
-    Arg = Arg.substr(2);
+  Arg.consume_front("--");
 
   size_t len = Expected.size();
   if (Arg == Expected) {
@@ -1272,7 +1295,7 @@
 
     return *ArgIt;
   }
-  if (Arg.startswith(Expected) && Arg.size() > len && Arg[len] == '=')
+  if (Arg.starts_with(Expected) && Arg.size() > len && Arg[len] == '=')
     return Arg.data() + len + 1;
 
   return nullptr;
@@ -1389,6 +1412,8 @@
 
 static int ranlib_main(int argc, char **argv) {
   std::vector<StringRef> Archives;
+  bool HasAIXXOption = false;
+
   for (int i = 1; i < argc; ++i) {
     StringRef arg(argv[i]);
     if (handleGenericOption(arg)) {
@@ -1406,6 +1431,28 @@
         } else if (arg.front() == 'v') {
           cl::PrintVersionMessage();
           return 0;
+        } else if (arg.front() == 'X') {
+          if (object::Archive::getDefaultKindForHost() ==
+              object::Archive::K_AIXBIG) {
+            HasAIXXOption = true;
+            arg.consume_front("X");
+            const char *Xarg = arg.data();
+            if (Xarg[0] == '\0') {
+              if (argv[i + 1][0] != '-')
+                BitMode = getBitMode(argv[++i]);
+              else
+                BitMode = BitModeTy::Unknown;
+            } else
+              BitMode = getBitMode(arg.data());
+
+            if (BitMode == BitModeTy::Unknown)
+              fail("the specified object mode is not valid. Specify -X32, "
+                   "-X64, -X32_64, or -Xany");
+          } else {
+            fail(Twine("-") + Twine(arg) +
+                 " option not supported on non AIX OS");
+          }
+          break;
         } else {
           // TODO: GNU ranlib also supports a -t flag
           fail("Invalid option: '-" + arg + "'");
@@ -1417,6 +1464,31 @@
     }
   }
 
+  if (object::Archive::getDefaultKindForHost() == object::Archive::K_AIXBIG) {
+    // If not specify -X option, get BitMode from enviorment variable
+    // "OBJECT_MODE" for AIX OS if specify.
+    if (!HasAIXXOption) {
+      if (char *EnvObjectMode = getenv("OBJECT_MODE")) {
+        BitMode = getBitMode(EnvObjectMode);
+        if (BitMode == BitModeTy::Unknown)
+          fail("the OBJECT_MODE environment variable has an invalid value. "
+               "OBJECT_MODE must be 32, 64, 32_64, or any");
+      }
+    }
+
+    switch (BitMode) {
+    case BitModeTy::Bit32:
+      Symtab = SymtabWritingMode::BigArchive32;
+      break;
+    case BitModeTy::Bit64:
+      Symtab = SymtabWritingMode::BigArchive64;
+      break;
+    default:
+      Symtab = SymtabWritingMode::NormalSymtab;
+      break;
+    }
+  }
+
   for (StringRef Archive : Archives) {
     ArchiveName = Archive.str();
     performOperation(CreateSymTab);
@@ -1427,7 +1499,6 @@
 }
 
 int llvm_ar_main(int argc, char **argv, const llvm::ToolContext &) {
-  InitLLVM X(argc, argv);
   ToolName = argv[0];
 
   llvm::InitializeAllTargetInfos();
diff --git a/src/llvm-project/llvm/tools/llvm-as/llvm-as.cpp b/src/llvm-project/llvm/tools/llvm-as/llvm-as.cpp
index ef1c50f..1c869e1 100644
--- a/src/llvm-project/llvm/tools/llvm-as/llvm-as.cpp
+++ b/src/llvm-project/llvm/tools/llvm-as/llvm-as.cpp
@@ -75,7 +75,7 @@
       OutputFilename = "-";
     } else {
       StringRef IFN = InputFilename;
-      OutputFilename = (IFN.endswith(".ll") ? IFN.drop_back(3) : IFN).str();
+      OutputFilename = (IFN.ends_with(".ll") ? IFN.drop_back(3) : IFN).str();
       OutputFilename += ".bc";
     }
   }
diff --git a/src/llvm-project/llvm/tools/llvm-c-test/echo.cpp b/src/llvm-project/llvm/tools/llvm-c-test/echo.cpp
index b0535c7..bc708e2 100644
--- a/src/llvm-project/llvm/tools/llvm-c-test/echo.cpp
+++ b/src/llvm-project/llvm/tools/llvm-c-test/echo.cpp
@@ -406,6 +406,32 @@
   }
 }
 
+static LLVMValueRef clone_inline_asm(LLVMValueRef Asm, LLVMModuleRef M) {
+
+  if (!LLVMIsAInlineAsm(Asm))
+      report_fatal_error("Expected inline assembly");
+
+  size_t AsmStringSize = 0;
+  const char *AsmString = LLVMGetInlineAsmAsmString(Asm, &AsmStringSize);
+
+  size_t ConstraintStringSize = 0;
+  const char *ConstraintString =
+      LLVMGetInlineAsmConstraintString(Asm, &ConstraintStringSize);
+
+  LLVMInlineAsmDialect AsmDialect = LLVMGetInlineAsmDialect(Asm);
+
+  LLVMTypeRef AsmFunctionType = LLVMGetInlineAsmFunctionType(Asm);
+
+  LLVMBool HasSideEffects = LLVMGetInlineAsmHasSideEffects(Asm);
+  LLVMBool NeedsAlignStack = LLVMGetInlineAsmNeedsAlignedStack(Asm);
+  LLVMBool CanUnwind = LLVMGetInlineAsmCanUnwind(Asm);
+
+  return LLVMGetInlineAsm(AsmFunctionType, AsmString, AsmStringSize,
+                          ConstraintString, ConstraintStringSize,
+                          HasSideEffects, NeedsAlignStack, AsmDialect,
+                          CanUnwind);
+}
+
 struct FunCloner {
   LLVMValueRef Fun;
   LLVMModuleRef M;
@@ -435,6 +461,10 @@
     if (i != VMap.end())
       return i->second;
 
+    // Inline assembly is a Value, but not an Instruction
+    if (LLVMIsAInlineAsm(Src))
+      return clone_inline_asm(Src, M);
+
     if (!LLVMIsAInstruction(Src))
       report_fatal_error("Expected an instruction");
 
@@ -518,16 +548,26 @@
         break;
       case LLVMInvoke: {
         SmallVector<LLVMValueRef, 8> Args;
-        int ArgCount = LLVMGetNumArgOperands(Src);
-        for (int i = 0; i < ArgCount; i++)
+        SmallVector<LLVMOperandBundleRef, 8> Bundles;
+        unsigned ArgCount = LLVMGetNumArgOperands(Src);
+        for (unsigned i = 0; i < ArgCount; ++i)
           Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
+        unsigned BundleCount = LLVMGetNumOperandBundles(Src);
+        for (unsigned i = 0; i < BundleCount; ++i) {
+          auto Bundle = LLVMGetOperandBundleAtIndex(Src, i);
+          Bundles.push_back(CloneOB(Bundle));
+          LLVMDisposeOperandBundle(Bundle);
+        }
         LLVMTypeRef FnTy = CloneType(LLVMGetCalledFunctionType(Src));
         LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src));
         LLVMBasicBlockRef Then = DeclareBB(LLVMGetNormalDest(Src));
         LLVMBasicBlockRef Unwind = DeclareBB(LLVMGetUnwindDest(Src));
-        Dst = LLVMBuildInvoke2(Builder, FnTy, Fn, Args.data(), ArgCount,
-                               Then, Unwind, Name);
+        Dst = LLVMBuildInvokeWithOperandBundles(
+            Builder, FnTy, Fn, Args.data(), ArgCount, Then, Unwind,
+            Bundles.data(), Bundles.size(), Name);
         CloneAttrs(Src, Dst);
+        for (auto Bundle : Bundles)
+          LLVMDisposeOperandBundle(Bundle);
         break;
       }
       case LLVMUnreachable:
@@ -626,7 +666,9 @@
       case LLVMOr: {
         LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
         LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        LLVMBool IsDisjoint = LLVMGetIsDisjoint(Src);
         Dst = LLVMBuildOr(Builder, LHS, RHS, Name);
+        LLVMSetIsDisjoint(Dst, IsDisjoint);
         break;
       }
       case LLVMXor: {
@@ -647,6 +689,7 @@
         LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
         LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
         LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
+        LLVMSetAtomicSingleThread(Dst, LLVMIsAtomicSingleThread(Src));
         break;
       }
       case LLVMStore: {
@@ -656,6 +699,7 @@
         LLVMSetAlignment(Dst, LLVMGetAlignment(Src));
         LLVMSetOrdering(Dst, LLVMGetOrdering(Src));
         LLVMSetVolatile(Dst, LLVMGetVolatile(Src));
+        LLVMSetAtomicSingleThread(Dst, LLVMIsAtomicSingleThread(Src));
         break;
       }
       case LLVMGetElementPtr: {
@@ -726,18 +770,39 @@
         }
 
         LLVMAddIncoming(Dst, Values.data(), Blocks.data(), IncomingCount);
+        // Copy fast math flags here since we return early
+        if (LLVMCanValueUseFastMathFlags(Src))
+          LLVMSetFastMathFlags(Dst, LLVMGetFastMathFlags(Src));
         return Dst;
       }
+      case LLVMSelect: {
+        LLVMValueRef If = CloneValue(LLVMGetOperand(Src, 0));
+        LLVMValueRef Then = CloneValue(LLVMGetOperand(Src, 1));
+        LLVMValueRef Else = CloneValue(LLVMGetOperand(Src, 2));
+        Dst = LLVMBuildSelect(Builder, If, Then, Else, Name);
+        break;
+      }
       case LLVMCall: {
         SmallVector<LLVMValueRef, 8> Args;
-        int ArgCount = LLVMGetNumArgOperands(Src);
-        for (int i = 0; i < ArgCount; i++)
+        SmallVector<LLVMOperandBundleRef, 8> Bundles;
+        unsigned ArgCount = LLVMGetNumArgOperands(Src);
+        for (unsigned i = 0; i < ArgCount; ++i)
           Args.push_back(CloneValue(LLVMGetOperand(Src, i)));
+        unsigned BundleCount = LLVMGetNumOperandBundles(Src);
+        for (unsigned i = 0; i < BundleCount; ++i) {
+          auto Bundle = LLVMGetOperandBundleAtIndex(Src, i);
+          Bundles.push_back(CloneOB(Bundle));
+          LLVMDisposeOperandBundle(Bundle);
+        }
         LLVMTypeRef FnTy = CloneType(LLVMGetCalledFunctionType(Src));
         LLVMValueRef Fn = CloneValue(LLVMGetCalledValue(Src));
-        Dst = LLVMBuildCall2(Builder, FnTy, Fn, Args.data(), ArgCount, Name);
-        LLVMSetTailCall(Dst, LLVMIsTailCall(Src));
+        Dst = LLVMBuildCallWithOperandBundles(Builder, FnTy, Fn, Args.data(),
+                                              ArgCount, Bundles.data(),
+                                              Bundles.size(), Name);
+        LLVMSetTailCallKind(Dst, LLVMGetTailCallKind(Src));
         CloneAttrs(Src, Dst);
+        for (auto Bundle : Bundles)
+          LLVMDisposeOperandBundle(Bundle);
         break;
       }
       case LLVMResume: {
@@ -861,6 +926,62 @@
         Dst = LLVMBuildFreeze(Builder, Arg, Name);
         break;
       }
+      case LLVMFence: {
+        LLVMAtomicOrdering Ordering = LLVMGetOrdering(Src);
+        LLVMBool IsSingleThreaded = LLVMIsAtomicSingleThread(Src);
+        Dst = LLVMBuildFence(Builder, Ordering, IsSingleThreaded, Name);
+        break;
+      }
+      case LLVMZExt: {
+        LLVMValueRef Val = CloneValue(LLVMGetOperand(Src, 0));
+        LLVMTypeRef DestTy = CloneType(LLVMTypeOf(Src));
+        LLVMBool NNeg = LLVMGetNNeg(Src);
+        Dst = LLVMBuildZExt(Builder, Val, DestTy, Name);
+        LLVMSetNNeg(Dst, NNeg);
+        break;
+      }
+      case LLVMFAdd: {
+        LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
+        LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        Dst = LLVMBuildFAdd(Builder, LHS, RHS, Name);
+        break;
+      }
+      case LLVMFSub: {
+        LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
+        LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        Dst = LLVMBuildFSub(Builder, LHS, RHS, Name);
+        break;
+      }
+      case LLVMFMul: {
+        LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
+        LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        Dst = LLVMBuildFMul(Builder, LHS, RHS, Name);
+        break;
+      }
+      case LLVMFDiv: {
+        LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
+        LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        Dst = LLVMBuildFDiv(Builder, LHS, RHS, Name);
+        break;
+      }
+      case LLVMFRem: {
+        LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
+        LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        Dst = LLVMBuildFRem(Builder, LHS, RHS, Name);
+        break;
+      }
+      case LLVMFNeg: {
+        LLVMValueRef Val = CloneValue(LLVMGetOperand(Src, 0));
+        Dst = LLVMBuildFNeg(Builder, Val, Name);
+        break;
+      }
+      case LLVMFCmp: {
+        LLVMRealPredicate Pred = LLVMGetFCmpPredicate(Src);
+        LLVMValueRef LHS = CloneValue(LLVMGetOperand(Src, 0));
+        LLVMValueRef RHS = CloneValue(LLVMGetOperand(Src, 1));
+        Dst = LLVMBuildFCmp(Builder, Pred, LHS, RHS, Name);
+        break;
+      }
       default:
         break;
     }
@@ -870,6 +991,10 @@
       exit(-1);
     }
 
+    // Copy fast-math flags on instructions that support them
+    if (LLVMCanValueUseFastMathFlags(Src))
+      LLVMSetFastMathFlags(Dst, LLVMGetFastMathFlags(Src));
+
     auto Ctx = LLVMGetModuleContext(M);
     size_t NumMetadataEntries;
     auto *AllMetadata =
@@ -887,6 +1012,17 @@
     return VMap[Src] = Dst;
   }
 
+  LLVMOperandBundleRef CloneOB(LLVMOperandBundleRef Src) {
+    size_t TagLen;
+    const char *Tag = LLVMGetOperandBundleTag(Src, &TagLen);
+
+    SmallVector<LLVMValueRef, 8> Args;
+    for (unsigned i = 0, n = LLVMGetNumOperandBundleArgs(Src); i != n; ++i)
+      Args.push_back(CloneValue(LLVMGetOperandBundleArgAtIndex(Src, i)));
+
+    return LLVMCreateOperandBundle(Tag, TagLen, Args.data(), Args.size());
+  }
+
   LLVMBasicBlockRef DeclareBB(LLVMBasicBlockRef Src) {
     // Check if this is something we already computed.
     {
diff --git a/src/llvm-project/llvm/tools/llvm-c-test/main.c b/src/llvm-project/llvm/tools/llvm-c-test/main.c
index 85bbc71..badbe4b 100644
--- a/src/llvm-project/llvm/tools/llvm-c-test/main.c
+++ b/src/llvm-project/llvm/tools/llvm-c-test/main.c
@@ -58,9 +58,6 @@
           "    Run test for checking if LLVMValueRef is a ValueAsMetadata\n");
   fprintf(stderr, "  * --echo\n");
   fprintf(stderr, "    Read bitcode file from stdin - print it back out\n\n");
-  fprintf(stderr, "  * --echo --opaque-pointers\n");
-  fprintf(stderr, "    Read bitcode file from stdin - print it back out in "
-                  "opaque pointer mode\n\n");
   fprintf(stderr, "  * --test-diagnostic-handler\n");
   fprintf(stderr,
           "    Read bitcode file from stdin with a diagnostic handler set\n\n");
diff --git a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.h b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.h
index 8fd687d..6b04bc3 100644
--- a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.h
+++ b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.h
@@ -39,7 +39,6 @@
 #include <functional>
 #include <set>
 #include <string>
-#include <unordered_map>
 
 namespace llvm {
 namespace cfi_verify {
diff --git a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/GraphBuilder.h b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/GraphBuilder.h
index 89724c0..55e628a 100644
--- a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/GraphBuilder.h
+++ b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/GraphBuilder.h
@@ -38,8 +38,6 @@
 
 #include <functional>
 #include <set>
-#include <string>
-#include <unordered_map>
 
 using Instr = llvm::cfi_verify::FileAnalysis::Instr;
 
diff --git a/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt
index 35b8b21..e02bda1 100644
--- a/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt
@@ -80,7 +80,7 @@
 configure_file(${BUILDVARIABLES_SRCPATH} ${BUILDVARIABLES_OBJPATH} @ONLY)
 
 # Set build-time environment(s).
-add_compile_definitions(CMAKE_CFG_INTDIR="${CMAKE_CFG_INTDIR}")
+add_compile_definitions(CMAKE_CFG_INTDIR="$<CONFIG>")
 
 if(LLVM_ENABLE_MODULES)
   target_compile_options(llvm-config PUBLIC
diff --git a/src/llvm-project/llvm/tools/llvm-config/llvm-config.cpp b/src/llvm-project/llvm/tools/llvm-config/llvm-config.cpp
index e86eb2b..d5b76b1 100644
--- a/src/llvm-project/llvm/tools/llvm-config/llvm-config.cpp
+++ b/src/llvm-project/llvm/tools/llvm-config/llvm-config.cpp
@@ -359,18 +359,18 @@
     {
       SmallString<256> Path(LLVM_INSTALL_INCLUDEDIR);
       sys::fs::make_absolute(ActivePrefix, Path);
-      ActiveIncludeDir = std::string(Path.str());
+      ActiveIncludeDir = std::string(Path);
     }
     {
       SmallString<256> Path(LLVM_TOOLS_INSTALL_DIR);
       sys::fs::make_absolute(ActivePrefix, Path);
-      ActiveBinDir = std::string(Path.str());
+      ActiveBinDir = std::string(Path);
     }
     ActiveLibDir = ActivePrefix + "/lib" + LLVM_LIBDIR_SUFFIX;
     {
       SmallString<256> Path(LLVM_INSTALL_PACKAGE_DIR);
       sys::fs::make_absolute(ActivePrefix, Path);
-      ActiveCMakeDir = std::string(Path.str());
+      ActiveCMakeDir = std::string(Path);
     }
     ActiveIncludeOption = "-I" + ActiveIncludeDir;
   }
@@ -454,11 +454,11 @@
   /// extension. Returns true if Lib is in a recognized format.
   auto GetComponentLibraryNameSlice = [&](const StringRef &Lib,
                                           StringRef &Out) {
-    if (Lib.startswith("lib")) {
+    if (Lib.starts_with("lib")) {
       unsigned FromEnd;
-      if (Lib.endswith(StaticExt)) {
+      if (Lib.ends_with(StaticExt)) {
         FromEnd = StaticExt.size() + 1;
-      } else if (Lib.endswith(SharedExt)) {
+      } else if (Lib.ends_with(SharedExt)) {
         FromEnd = SharedExt.size() + 1;
       } else {
         FromEnd = 0;
@@ -481,7 +481,7 @@
         // Treat the DyLibName specially. It is not a component library and
         // already has the necessary prefix and suffix (e.g. `.so`) added so
         // just return it unmodified.
-        assert(Lib.endswith(SharedExt) && "DyLib is missing suffix");
+        assert(Lib.ends_with(SharedExt) && "DyLib is missing suffix");
         LibFileName = std::string(Lib);
       } else {
         LibFileName = (SharedPrefix + Lib + "." + SharedExt).str();
@@ -507,7 +507,7 @@
   for (int i = 1; i != argc; ++i) {
     StringRef Arg = argv[i];
 
-    if (Arg.startswith("-")) {
+    if (Arg.starts_with("-")) {
       HasAnyOption = true;
       if (Arg == "--version") {
         OS << PACKAGE_VERSION << '\n';
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp b/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
index 02448dc..6405bb1 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -105,6 +105,11 @@
                             const MemoryBuffer &File,
                             CoverageData &CoverageInfo);
 
+  /// Create source views for the MCDC records.
+  void attachMCDCSubViews(SourceCoverageView &View, StringRef SourceName,
+                          ArrayRef<MCDCRecord> MCDCRecords,
+                          const MemoryBuffer &File, CoverageData &CoverageInfo);
+
   /// Create the source view of a particular function.
   std::unique_ptr<SourceCoverageView>
   createFunctionView(const FunctionRecord &Function,
@@ -162,7 +167,8 @@
 
   /// The coverage data path to be remapped from, and the source path to be
   /// remapped to, when using -path-equivalence.
-  std::optional<std::pair<std::string, std::string>> PathRemapping;
+  std::optional<std::vector<std::pair<std::string, std::string>>>
+      PathRemappings;
 
   /// File status cache used when finding the same file.
   StringMap<std::optional<sys::fs::file_status>> FileStatusCache;
@@ -228,7 +234,7 @@
   llvm::sys::fs::file_status Status;
   llvm::sys::fs::status(Path, Status);
   if (!llvm::sys::fs::exists(Status)) {
-    if (PathRemapping)
+    if (PathRemappings)
       addCollectedPath(Path);
     else
       warning("Source file doesn't exist, proceeded by ignoring it.", Path);
@@ -351,6 +357,37 @@
   }
 }
 
+void CodeCoverageTool::attachMCDCSubViews(SourceCoverageView &View,
+                                          StringRef SourceName,
+                                          ArrayRef<MCDCRecord> MCDCRecords,
+                                          const MemoryBuffer &File,
+                                          CoverageData &CoverageInfo) {
+  if (!ViewOpts.ShowMCDC)
+    return;
+
+  const auto *NextRecord = MCDCRecords.begin();
+  const auto *EndRecord = MCDCRecords.end();
+
+  // Group and process MCDC records that have the same line number into the
+  // same subview.
+  while (NextRecord != EndRecord) {
+    std::vector<MCDCRecord> ViewMCDCRecords;
+    unsigned CurrentLine = NextRecord->getDecisionRegion().LineEnd;
+
+    while (NextRecord != EndRecord &&
+           CurrentLine == NextRecord->getDecisionRegion().LineEnd) {
+      ViewMCDCRecords.push_back(*NextRecord++);
+    }
+
+    if (ViewMCDCRecords.empty())
+      continue;
+
+    auto SubView = SourceCoverageView::create(SourceName, File, ViewOpts,
+                                              std::move(CoverageInfo));
+    View.addMCDCRecord(CurrentLine, ViewMCDCRecords, std::move(SubView));
+  }
+}
+
 std::unique_ptr<SourceCoverageView>
 CodeCoverageTool::createFunctionView(const FunctionRecord &Function,
                                      const CoverageMapping &Coverage) {
@@ -363,12 +400,15 @@
 
   auto Branches = FunctionCoverage.getBranches();
   auto Expansions = FunctionCoverage.getExpansions();
+  auto MCDCRecords = FunctionCoverage.getMCDCRecords();
   auto View = SourceCoverageView::create(DC.demangle(Function.Name),
                                          SourceBuffer.get(), ViewOpts,
                                          std::move(FunctionCoverage));
   attachExpansionSubViews(*View, Expansions, Coverage);
   attachBranchSubViews(*View, DC.demangle(Function.Name), Branches,
                        SourceBuffer.get(), FunctionCoverage);
+  attachMCDCSubViews(*View, DC.demangle(Function.Name), MCDCRecords,
+                     SourceBuffer.get(), FunctionCoverage);
 
   return View;
 }
@@ -385,11 +425,14 @@
 
   auto Branches = FileCoverage.getBranches();
   auto Expansions = FileCoverage.getExpansions();
+  auto MCDCRecords = FileCoverage.getMCDCRecords();
   auto View = SourceCoverageView::create(SourceFile, SourceBuffer.get(),
                                          ViewOpts, std::move(FileCoverage));
   attachExpansionSubViews(*View, Expansions, Coverage);
   attachBranchSubViews(*View, SourceFile, Branches, SourceBuffer.get(),
                        FileCoverage);
+  attachMCDCSubViews(*View, SourceFile, MCDCRecords, SourceBuffer.get(),
+                     FileCoverage);
   if (!ViewOpts.ShowFunctionInstantiations)
     return View;
 
@@ -407,11 +450,14 @@
         auto SubViewCoverage = Coverage.getCoverageForFunction(*Function);
         auto SubViewExpansions = SubViewCoverage.getExpansions();
         auto SubViewBranches = SubViewCoverage.getBranches();
+        auto SubViewMCDCRecords = SubViewCoverage.getMCDCRecords();
         SubView = SourceCoverageView::create(
             Funcname, SourceBuffer.get(), ViewOpts, std::move(SubViewCoverage));
         attachExpansionSubViews(*SubView, SubViewExpansions, Coverage);
         attachBranchSubViews(*SubView, SourceFile, SubViewBranches,
                              SourceBuffer.get(), SubViewCoverage);
+        attachMCDCSubViews(*SubView, SourceFile, SubViewMCDCRecords,
+                           SourceBuffer.get(), SubViewCoverage);
       }
 
       unsigned FileID = Function->CountedRegions.front().FileID;
@@ -446,7 +492,7 @@
       ObjectFilenames, PGOFilename, *FS, CoverageArches,
       ViewOpts.CompilationDirectory, BIDFetcher.get(), CheckBinaryIDs);
   if (Error E = CoverageOrErr.takeError()) {
-    error("Failed to load coverage: " + toString(std::move(E)));
+    error("failed to load coverage: " + toString(std::move(E)));
     return nullptr;
   }
   auto Coverage = std::move(CoverageOrErr.get());
@@ -474,7 +520,7 @@
 }
 
 void CodeCoverageTool::remapPathNames(const CoverageMapping &Coverage) {
-  if (!PathRemapping)
+  if (!PathRemappings)
     return;
 
   // Convert remapping paths to native paths with trailing seperators.
@@ -488,17 +534,23 @@
       NativePath += sys::path::get_separator();
     return NativePath.c_str();
   };
-  std::string RemapFrom = nativeWithTrailing(PathRemapping->first);
-  std::string RemapTo = nativeWithTrailing(PathRemapping->second);
 
-  // Create a mapping from coverage data file paths to local paths.
-  for (StringRef Filename : Coverage.getUniqueSourceFiles()) {
-    SmallString<128> NativeFilename;
-    sys::path::native(Filename, NativeFilename);
-    sys::path::remove_dots(NativeFilename, true);
-    if (NativeFilename.startswith(RemapFrom)) {
-      RemappedFilenames[Filename] =
-          RemapTo + NativeFilename.substr(RemapFrom.size()).str();
+  for (std::pair<std::string, std::string> &PathRemapping : *PathRemappings) {
+    std::string RemapFrom = nativeWithTrailing(PathRemapping.first);
+    std::string RemapTo = nativeWithTrailing(PathRemapping.second);
+
+    // Create a mapping from coverage data file paths to local paths.
+    for (StringRef Filename : Coverage.getUniqueSourceFiles()) {
+      if (RemappedFilenames.count(Filename) == 1)
+        continue;
+
+      SmallString<128> NativeFilename;
+      sys::path::native(Filename, NativeFilename);
+      sys::path::remove_dots(NativeFilename, true);
+      if (NativeFilename.starts_with(RemapFrom)) {
+        RemappedFilenames[Filename] =
+            RemapTo + NativeFilename.substr(RemapFrom.size()).str();
+      }
     }
   }
 
@@ -592,7 +644,7 @@
   DemanglerData.split(Symbols, '\n', /*MaxSplit=*/NumSymbols,
                       /*KeepEmpty=*/false);
   if (Symbols.size() != NumSymbols) {
-    error("Demangler did not provide expected number of symbols");
+    error("demangler did not provide expected number of symbols");
     return;
   }
 
@@ -616,7 +668,7 @@
 
   auto OSOrErr = Printer->createViewFile(SourceFile, /*InToplevel=*/false);
   if (Error E = OSOrErr.takeError()) {
-    error("Could not create view file!", toString(std::move(E)));
+    error("could not create view file!", toString(std::move(E)));
     return;
   }
   auto OS = std::move(OSOrErr.get());
@@ -674,7 +726,7 @@
                             "lcov tracefile output")),
       cl::init(CoverageViewOptions::OutputFormat::Text));
 
-  cl::opt<std::string> PathRemap(
+  cl::list<std::string> PathRemaps(
       "path-equivalence", cl::Optional,
       cl::desc("<from>,<to> Map coverage data paths to local source file "
                "paths"));
@@ -745,6 +797,10 @@
       cl::desc("Show branch condition statistics in summary table"),
       cl::init(true));
 
+  cl::opt<bool> MCDCSummary("show-mcdc-summary", cl::Optional,
+                            cl::desc("Show MCDC statistics in summary table"),
+                            cl::init(false));
+
   cl::opt<bool> InstantiationSummary(
       "show-instantiation-summary", cl::Optional,
       cl::desc("Show instantiation statistics in summary table"));
@@ -812,26 +868,30 @@
       break;
     }
 
-    // If path-equivalence was given and is a comma seperated pair then set
-    // PathRemapping.
-    if (!PathRemap.empty()) {
-      auto EquivPair = StringRef(PathRemap).split(',');
-      if (EquivPair.first.empty() || EquivPair.second.empty()) {
-        error("invalid argument '" + PathRemap +
-                  "', must be in format 'from,to'",
-              "-path-equivalence");
-        return 1;
+    if (!PathRemaps.empty()) {
+      std::vector<std::pair<std::string, std::string>> Remappings;
+
+      for (const std::string &PathRemap : PathRemaps) {
+        auto EquivPair = StringRef(PathRemap).split(',');
+        if (EquivPair.first.empty() || EquivPair.second.empty()) {
+          error("invalid argument '" + PathRemap +
+                    "', must be in format 'from,to'",
+                "-path-equivalence");
+          return 1;
+        }
+
+        Remappings.push_back(
+            {std::string(EquivPair.first), std::string(EquivPair.second)});
       }
 
-      PathRemapping = {std::string(EquivPair.first),
-                       std::string(EquivPair.second)};
+      PathRemappings = Remappings;
     }
 
     // If a demangler is supplied, check if it exists and register it.
     if (!DemanglerOpts.empty()) {
       auto DemanglerPathOrErr = sys::findProgramByName(DemanglerOpts[0]);
       if (!DemanglerPathOrErr) {
-        error("Could not find the demangler!",
+        error("could not find the demangler!",
               DemanglerPathOrErr.getError().message());
         return 1;
       }
@@ -890,14 +950,14 @@
     if (!Arches.empty()) {
       for (const std::string &Arch : Arches) {
         if (Triple(Arch).getArch() == llvm::Triple::ArchType::UnknownArch) {
-          error("Unknown architecture: " + Arch);
+          error("unknown architecture: " + Arch);
           return 1;
         }
         CoverageArches.emplace_back(Arch);
       }
       if (CoverageArches.size() != 1 &&
           CoverageArches.size() != ObjectFilenames.size()) {
-        error("Number of architectures doesn't match the number of objects");
+        error("number of architectures doesn't match the number of objects");
         return 1;
       }
     }
@@ -912,6 +972,7 @@
       ::exit(0);
     }
 
+    ViewOpts.ShowMCDCSummary = MCDCSummary;
     ViewOpts.ShowBranchSummary = BranchSummary;
     ViewOpts.ShowRegionSummary = RegionSummary;
     ViewOpts.ShowInstantiationSummary = InstantiationSummary;
@@ -957,6 +1018,11 @@
                             "percent", "Show True/False percent")),
       cl::init(CoverageViewOptions::BranchOutputType::Off));
 
+  cl::opt<bool> ShowMCDC(
+      "show-mcdc", cl::Optional,
+      cl::desc("Show the MCDC Coverage for each applicable boolean expression"),
+      cl::cat(ViewCategory));
+
   cl::opt<bool> ShowBestLineRegionsCounts(
       "show-line-counts-or-regions", cl::Optional,
       cl::desc("Show the execution counts for each line, or the execution "
@@ -971,6 +1037,10 @@
                                    cl::desc("Show function instantiations"),
                                    cl::init(true), cl::cat(ViewCategory));
 
+  cl::opt<bool> ShowDirectoryCoverage("show-directory-coverage", cl::Optional,
+                                      cl::desc("Show directory coverage"),
+                                      cl::cat(ViewCategory));
+
   cl::opt<std::string> ShowOutputDirectory(
       "output-dir", cl::init(""),
       cl::desc("Directory in which coverage information is written out"));
@@ -996,7 +1066,7 @@
     return Err;
 
   if (ViewOpts.Format == CoverageViewOptions::OutputFormat::Lcov) {
-    error("Lcov format should be used with 'llvm-cov export'.");
+    error("lcov format should be used with 'llvm-cov export'.");
     return 1;
   }
 
@@ -1048,23 +1118,25 @@
   ViewOpts.ShowExpandedRegions = ShowExpansions;
   ViewOpts.ShowBranchCounts =
       ShowBranches == CoverageViewOptions::BranchOutputType::Count;
+  ViewOpts.ShowMCDC = ShowMCDC;
   ViewOpts.ShowBranchPercents =
       ShowBranches == CoverageViewOptions::BranchOutputType::Percent;
   ViewOpts.ShowFunctionInstantiations = ShowInstantiations;
+  ViewOpts.ShowDirectoryCoverage = ShowDirectoryCoverage;
   ViewOpts.ShowOutputDirectory = ShowOutputDirectory;
   ViewOpts.TabSize = TabSize;
   ViewOpts.ProjectTitle = ProjectTitle;
 
   if (ViewOpts.hasOutputDirectory()) {
     if (auto E = sys::fs::create_directories(ViewOpts.ShowOutputDirectory)) {
-      error("Could not create output directory!", E.message());
+      error("could not create output directory!", E.message());
       return 1;
     }
   }
 
   sys::fs::file_status Status;
   if (std::error_code EC = sys::fs::status(PGOFilename, Status)) {
-    error("Could not read profile data!" + EC.message(), PGOFilename);
+    error("could not read profile data!" + EC.message(), PGOFilename);
     return 1;
   }
 
@@ -1091,7 +1163,7 @@
   // Create an index out of the source files.
   if (ViewOpts.hasOutputDirectory()) {
     if (Error E = Printer->createIndexFile(SourceFiles, *Coverage, Filters)) {
-      error("Could not create index file!", toString(std::move(E)));
+      error("could not create index file!", toString(std::move(E)));
       return 1;
     }
   }
@@ -1112,7 +1184,7 @@
 
       auto OSOrErr = Printer->createViewFile(File, /*InToplevel=*/false);
       if (Error E = OSOrErr.takeError()) {
-        error("Could not create view file!", toString(std::move(E)));
+        error("could not create view file!", toString(std::move(E)));
         return 1;
       }
       auto OS = std::move(OSOrErr.get());
@@ -1177,13 +1249,13 @@
     error("HTML output for summary reports is not yet supported.");
     return 1;
   } else if (ViewOpts.Format == CoverageViewOptions::OutputFormat::Lcov) {
-    error("Lcov format should be used with 'llvm-cov export'.");
+    error("lcov format should be used with 'llvm-cov export'.");
     return 1;
   }
 
   sys::fs::file_status Status;
   if (std::error_code EC = sys::fs::status(PGOFilename, Status)) {
-    error("Could not read profile data!" + EC.message(), PGOFilename);
+    error("could not read profile data!" + EC.message(), PGOFilename);
     return 1;
   }
 
@@ -1199,7 +1271,7 @@
       Report.renderFileReports(llvm::outs(), SourceFiles);
   } else {
     if (SourceFiles.empty()) {
-      error("Source files must be specified when -show-functions=true is "
+      error("source files must be specified when -show-functions=true is "
             "specified");
       return 1;
     }
@@ -1236,20 +1308,20 @@
 
   if (ViewOpts.Format != CoverageViewOptions::OutputFormat::Text &&
       ViewOpts.Format != CoverageViewOptions::OutputFormat::Lcov) {
-    error("Coverage data can only be exported as textual JSON or an "
+    error("coverage data can only be exported as textual JSON or an "
           "lcov tracefile.");
     return 1;
   }
 
   sys::fs::file_status Status;
   if (std::error_code EC = sys::fs::status(PGOFilename, Status)) {
-    error("Could not read profile data!" + EC.message(), PGOFilename);
+    error("could not read profile data!" + EC.message(), PGOFilename);
     return 1;
   }
 
   auto Coverage = load();
   if (!Coverage) {
-    error("Could not load coverage information");
+    error("could not load coverage information");
     return 1;
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp b/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp
index 9e43377..a424bbe 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp
@@ -20,6 +20,8 @@
 //       -- File: dict => Coverage for a single file
 //         -- Branches: array => List of Branches in the file
 //           -- Branch: dict => Describes a branch of the file with counters
+//         -- MCDC Records: array => List of MCDC records in the file
+//           -- MCDC Values: array => List of T/F covered condition values
 //         -- Segments: array => List of Segments contained in the file
 //           -- Segment: dict => Describes a segment of the file with a counter
 //         -- Expansions: array => List of expansion records
@@ -34,6 +36,7 @@
 //           -- FunctionCoverage: dict => Object summarizing function coverage
 //           -- RegionCoverage: dict => Object summarizing region coverage
 //           -- BranchCoverage: dict => Object summarizing branch coverage
+//           -- MCDCCoverage: dict => Object summarizing MC/DC coverage
 //     -- Functions: array => List of objects describing coverage for functions
 //       -- Function: dict => Coverage info for a single function
 //         -- Filenames: array => List of filenames that the function relates to
@@ -43,6 +46,7 @@
 //     -- InstantiationCoverage: dict => Object summarizing inst. coverage
 //     -- RegionCoverage: dict => Object summarizing region coverage
 //     -- BranchCoverage: dict => Object summarizing branch coverage
+//     -- MCDCCoverage: dict => Object summarizing MC/DC coverage
 //
 //===----------------------------------------------------------------------===//
 
@@ -97,6 +101,20 @@
        Region.ExpandedFileID, int64_t(Region.Kind)});
 }
 
+json::Array gatherConditions(const coverage::MCDCRecord &Record) {
+  json::Array Conditions;
+  for (unsigned c = 0; c < Record.getNumConditions(); c++)
+    Conditions.push_back(Record.isConditionIndependencePairCovered(c));
+  return Conditions;
+}
+
+json::Array renderMCDCRecord(const coverage::MCDCRecord &Record) {
+  const llvm::coverage::CounterMappingRegion &CMR = Record.getDecisionRegion();
+  return json::Array({CMR.LineStart, CMR.ColumnStart, CMR.LineEnd,
+                      CMR.ColumnEnd, CMR.ExpandedFileID, int64_t(CMR.Kind),
+                      gatherConditions(Record)});
+}
+
 json::Array renderRegions(ArrayRef<coverage::CountedRegion> Regions) {
   json::Array RegionArray;
   for (const auto &Region : Regions)
@@ -112,6 +130,13 @@
   return RegionArray;
 }
 
+json::Array renderMCDCRecords(ArrayRef<coverage::MCDCRecord> Records) {
+  json::Array RecordArray;
+  for (auto &Record : Records)
+    RecordArray.push_back(renderMCDCRecord(Record));
+  return RecordArray;
+}
+
 std::vector<llvm::coverage::CountedRegion>
 collectNestedBranches(const coverage::CoverageMapping &Coverage,
                       ArrayRef<llvm::coverage::ExpansionRecord> Expansions) {
@@ -178,7 +203,14 @@
              {"covered", int64_t(Summary.BranchCoverage.getCovered())},
              {"notcovered", int64_t(Summary.BranchCoverage.getNumBranches() -
                                     Summary.BranchCoverage.getCovered())},
-             {"percent", Summary.BranchCoverage.getPercentCovered()}})}});
+             {"percent", Summary.BranchCoverage.getPercentCovered()}})},
+       {"mcdc",
+        json::Object(
+            {{"count", int64_t(Summary.MCDCCoverage.getNumPairs())},
+             {"covered", int64_t(Summary.MCDCCoverage.getCoveredPairs())},
+             {"notcovered", int64_t(Summary.MCDCCoverage.getNumPairs() -
+                                    Summary.MCDCCoverage.getCoveredPairs())},
+             {"percent", Summary.MCDCCoverage.getPercentCovered()}})}});
 }
 
 json::Array renderFileExpansions(const coverage::CoverageMapping &Coverage,
@@ -206,6 +238,14 @@
   return BranchArray;
 }
 
+json::Array renderFileMCDC(const coverage::CoverageData &FileCoverage,
+                           const FileCoverageSummary &FileReport) {
+  json::Array MCDCRecordArray;
+  for (const auto &Record : FileCoverage.getMCDCRecords())
+    MCDCRecordArray.push_back(renderMCDCRecord(Record));
+  return MCDCRecordArray;
+}
+
 json::Object renderFile(const coverage::CoverageMapping &Coverage,
                         const std::string &Filename,
                         const FileCoverageSummary &FileReport,
@@ -216,6 +256,7 @@
     auto FileCoverage = Coverage.getCoverageForFile(Filename);
     File["segments"] = renderFileSegments(FileCoverage, FileReport);
     File["branches"] = renderFileBranches(FileCoverage, FileReport);
+    File["mcdc_records"] = renderFileMCDC(FileCoverage, FileReport);
     if (!Options.SkipExpansions) {
       File["expansions"] =
           renderFileExpansions(Coverage, FileCoverage, FileReport);
@@ -264,6 +305,7 @@
                       {"count", clamp_uint64_to_int64(F.ExecutionCount)},
                       {"regions", renderRegions(F.CountedRegions)},
                       {"branches", renderBranchRegions(F.CountedBranchRegions)},
+                      {"mcdc_records", renderMCDCRecords(F.MCDCRecords)},
                       {"filenames", json::Array(F.Filenames)}}));
   return FunctionArray;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp b/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp
index cb0b184..8cc073e 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -12,7 +12,6 @@
 
 #include "CoverageReport.h"
 #include "RenderingSupport.h"
-#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/Path.h"
@@ -87,9 +86,9 @@
 }
 
 // Specify the default column widths.
-size_t FileReportColumns[] = {25, 12, 18, 10, 12, 18, 10, 16,
-                              16, 10, 12, 18, 10, 12, 18, 10};
-size_t FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8, 10, 8, 8};
+size_t FileReportColumns[] = {25, 12, 18, 10, 12, 18, 10, 16, 16, 10,
+                              12, 18, 10, 12, 18, 10, 20, 21, 10};
+size_t FunctionReportColumns[] = {25, 10, 8, 8, 10, 8, 8, 10, 8, 8, 20, 8, 8};
 
 /// Adjust column widths to fit long file paths and function names.
 void adjustColumnWidths(ArrayRef<StringRef> Files,
@@ -166,6 +165,35 @@
   return PrefixLen;
 }
 
+/// Determine the length of the longest redundant prefix of the substrs starts
+/// from \p LCP in \p Paths. \p Paths can't be empty. If there's only one
+/// element in \p Paths, the length of the substr is returned. Note this is
+/// differnet from the behavior of the function above.
+unsigned getRedundantPrefixLen(ArrayRef<StringRef> Paths, unsigned LCP) {
+  assert(!Paths.empty() && "Paths must have at least one element");
+
+  auto Iter = Paths.begin();
+  auto IterE = Paths.end();
+  auto Prefix = Iter->substr(LCP);
+  while (++Iter != IterE) {
+    auto Other = Iter->substr(LCP);
+    auto Len = std::min(Prefix.size(), Other.size());
+    for (std::size_t I = 0; I < Len; ++I) {
+      if (Prefix[I] != Other[I]) {
+        Prefix = Prefix.substr(0, I);
+        break;
+      }
+    }
+  }
+
+  for (auto I = Prefix.size(); --I != SIZE_MAX;) {
+    if (Prefix[I] == '/' || Prefix[I] == '\\')
+      return I + 1;
+  }
+
+  return Prefix.size();
+}
+
 } // end anonymous namespace
 
 namespace llvm {
@@ -180,8 +208,14 @@
       determineCoveragePercentageColor(File.InstantiationCoverage);
   auto LineCoverageColor = determineCoveragePercentageColor(File.LineCoverage);
   SmallString<256> FileName = File.Name;
-  sys::path::remove_dots(FileName, /*remove_dot_dot=*/true);
   sys::path::native(FileName);
+
+  // remove_dots will remove trailing slash, so we need to check before it.
+  auto IsDir = FileName.ends_with(sys::path::get_separator());
+  sys::path::remove_dots(FileName, /*remove_dot_dot=*/true);
+  if (IsDir)
+    FileName += sys::path::get_separator();
+
   OS << column(FileName, FileReportColumns[0], Column::NoTrim);
 
   if (Options.ShowRegionSummary) {
@@ -257,6 +291,22 @@
       OS << column("-", FileReportColumns[15], Column::RightAlignment);
   }
 
+  if (Options.ShowMCDCSummary) {
+    OS << format("%*u", FileReportColumns[16],
+                 (unsigned)File.MCDCCoverage.getNumPairs());
+    Options.colored_ostream(OS, LineCoverageColor)
+        << format("%*u", FileReportColumns[17],
+                  (unsigned)(File.MCDCCoverage.getNumPairs() -
+                             File.MCDCCoverage.getCoveredPairs()));
+    if (File.MCDCCoverage.getNumPairs())
+      Options.colored_ostream(OS, LineCoverageColor)
+          << format("%*.2f", FileReportColumns[18] - 1,
+                    File.MCDCCoverage.getPercentCovered())
+          << '%';
+    else
+      OS << column("-", FileReportColumns[18], Column::RightAlignment);
+  }
+
   OS << "\n";
 }
 
@@ -304,6 +354,19 @@
                   Function.BranchCoverage.getPercentCovered())
         << '%';
   }
+  if (Options.ShowMCDCSummary) {
+    OS << format("%*u", FunctionReportColumns[10],
+                 (unsigned)Function.MCDCCoverage.getNumPairs());
+    Options.colored_ostream(OS, LineCoverageColor)
+        << format("%*u", FunctionReportColumns[11],
+                  (unsigned)(Function.MCDCCoverage.getNumPairs() -
+                             Function.MCDCCoverage.getCoveredPairs()));
+    Options.colored_ostream(
+        OS, determineCoveragePercentageColor(Function.MCDCCoverage))
+        << format("%*.2f", FunctionReportColumns[12] - 1,
+                  Function.MCDCCoverage.getPercentCovered())
+        << '%';
+  }
   OS << "\n";
 }
 
@@ -336,6 +399,11 @@
       OS << column("Branches", FunctionReportColumns[7], Column::RightAlignment)
          << column("Miss", FunctionReportColumns[8], Column::RightAlignment)
          << column("Cover", FunctionReportColumns[9], Column::RightAlignment);
+    if (Options.ShowMCDCSummary)
+      OS << column("MC/DC Conditions", FunctionReportColumns[10],
+                   Column::RightAlignment)
+         << column("Miss", FunctionReportColumns[11], Column::RightAlignment)
+         << column("Cover", FunctionReportColumns[12], Column::RightAlignment);
     OS << "\n";
     renderDivider(FunctionReportColumns, OS);
     OS << "\n";
@@ -346,6 +414,7 @@
       Totals.RegionCoverage += Function.RegionCoverage;
       Totals.LineCoverage += Function.LineCoverage;
       Totals.BranchCoverage += Function.BranchCoverage;
+      Totals.MCDCCoverage += Function.MCDCCoverage;
       render(Function, DC, OS);
     }
     if (Totals.ExecutionCount) {
@@ -436,7 +505,12 @@
   FileCoverageSummary Totals("TOTAL");
   auto FileReports =
       prepareFileReports(Coverage, Totals, Files, Options, Filters);
+  renderFileReports(OS, FileReports, Totals, Filters.empty());
+}
 
+void CoverageReport::renderFileReports(
+    raw_ostream &OS, const std::vector<FileCoverageSummary> &FileReports,
+    const FileCoverageSummary &Totals, bool ShowEmptyFiles) const {
   std::vector<StringRef> Filenames;
   Filenames.reserve(FileReports.size());
   for (const FileCoverageSummary &FCS : FileReports)
@@ -463,25 +537,30 @@
        << column("Missed Branches", FileReportColumns[14],
                  Column::RightAlignment)
        << column("Cover", FileReportColumns[15], Column::RightAlignment);
+  if (Options.ShowMCDCSummary)
+    OS << column("MC/DC Conditions", FileReportColumns[16],
+                 Column::RightAlignment)
+       << column("Missed Conditions", FileReportColumns[17],
+                 Column::RightAlignment)
+       << column("Cover", FileReportColumns[18], Column::RightAlignment);
   OS << "\n";
   renderDivider(FileReportColumns, OS);
   OS << "\n";
 
-  bool EmptyFiles = false;
+  std::vector<const FileCoverageSummary *> EmptyFiles;
   for (const FileCoverageSummary &FCS : FileReports) {
     if (FCS.FunctionCoverage.getNumFunctions())
       render(FCS, OS);
     else
-      EmptyFiles = true;
+      EmptyFiles.push_back(&FCS);
   }
 
-  if (EmptyFiles && Filters.empty()) {
+  if (!EmptyFiles.empty() && ShowEmptyFiles) {
     OS << "\n"
        << "Files which contain no functions:\n";
 
-    for (const FileCoverageSummary &FCS : FileReports)
-      if (!FCS.FunctionCoverage.getNumFunctions())
-        render(FCS, OS);
+    for (auto FCS : EmptyFiles)
+      render(*FCS, OS);
   }
 
   renderDivider(FileReportColumns, OS);
@@ -489,4 +568,96 @@
   render(Totals, OS);
 }
 
+Expected<FileCoverageSummary> DirectoryCoverageReport::prepareDirectoryReports(
+    ArrayRef<std::string> SourceFiles) {
+  std::vector<StringRef> Files(SourceFiles.begin(), SourceFiles.end());
+
+  unsigned RootLCP = getRedundantPrefixLen(Files, 0);
+  auto LCPath = Files.front().substr(0, RootLCP);
+
+  ThreadPoolStrategy PoolS = hardware_concurrency(Options.NumThreads);
+  if (Options.NumThreads == 0) {
+    PoolS = heavyweight_hardware_concurrency(Files.size());
+    PoolS.Limit = true;
+  }
+  ThreadPool Pool(PoolS);
+
+  TPool = &Pool;
+  LCPStack = {RootLCP};
+  FileCoverageSummary RootTotals(LCPath);
+  if (auto E = prepareSubDirectoryReports(Files, &RootTotals))
+    return {std::move(E)};
+  return {std::move(RootTotals)};
+}
+
+/// Filter out files in LCPStack.back(), group others by subdirectory name
+/// and recurse on them. After returning from all subdirectories, call
+/// generateSubDirectoryReport(). \p Files must be non-empty. The
+/// FileCoverageSummary of this directory will be added to \p Totals.
+Error DirectoryCoverageReport::prepareSubDirectoryReports(
+    const ArrayRef<StringRef> &Files, FileCoverageSummary *Totals) {
+  assert(!Files.empty() && "Files must have at least one element");
+
+  auto LCP = LCPStack.back();
+  auto LCPath = Files.front().substr(0, LCP).str();
+
+  // Use ordered map to keep entries in order.
+  SubFileReports SubFiles;
+  SubDirReports SubDirs;
+  for (auto &&File : Files) {
+    auto SubPath = File.substr(LCPath.size());
+    SmallVector<char, 128> NativeSubPath;
+    sys::path::native(SubPath, NativeSubPath);
+    StringRef NativeSubPathRef(NativeSubPath.data(), NativeSubPath.size());
+
+    auto I = sys::path::begin(NativeSubPathRef);
+    auto E = sys::path::end(NativeSubPathRef);
+    assert(I != E && "Such case should have been filtered out in the caller");
+
+    auto Name = SubPath.substr(0, I->size());
+    if (++I == E) {
+      auto Iter = SubFiles.insert_or_assign(Name, SubPath).first;
+      // Makes files reporting overlap with subdir reporting.
+      TPool->async(&CoverageReport::prepareSingleFileReport, File, &Coverage,
+                   Options, LCP, &Iter->second, &Filters);
+    } else {
+      SubDirs[Name].second.push_back(File);
+    }
+  }
+
+  // Call recursively on subdirectories.
+  for (auto &&KV : SubDirs) {
+    auto &V = KV.second;
+    if (V.second.size() == 1) {
+      // If there's only one file in that subdirectory, we don't bother to
+      // recurse on it further.
+      V.first.Name = V.second.front().substr(LCP);
+      TPool->async(&CoverageReport::prepareSingleFileReport, V.second.front(),
+                   &Coverage, Options, LCP, &V.first, &Filters);
+    } else {
+      auto SubDirLCP = getRedundantPrefixLen(V.second, LCP);
+      V.first.Name = V.second.front().substr(LCP, SubDirLCP);
+      LCPStack.push_back(LCP + SubDirLCP);
+      if (auto E = prepareSubDirectoryReports(V.second, &V.first))
+        return E;
+    }
+  }
+
+  TPool->wait();
+
+  FileCoverageSummary CurrentTotals(LCPath);
+  for (auto &&KV : SubFiles)
+    CurrentTotals += KV.second;
+  for (auto &&KV : SubDirs)
+    CurrentTotals += KV.second.first;
+  *Totals += CurrentTotals;
+
+  if (auto E = generateSubDirectoryReport(
+          std::move(SubFiles), std::move(SubDirs), std::move(CurrentTotals)))
+    return E;
+
+  LCPStack.pop_back();
+  return Error::success();
+}
+
 } // end namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.h b/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.h
index f9a092f..60f751c 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.h
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.h
@@ -16,9 +16,12 @@
 #include "CoverageFilters.h"
 #include "CoverageSummaryInfo.h"
 #include "CoverageViewOptions.h"
+#include <map>
 
 namespace llvm {
 
+class ThreadPool;
+
 /// Displays the code coverage report.
 class CoverageReport {
   const CoverageViewOptions &Options;
@@ -62,6 +65,73 @@
   /// in \p Filters.
   void renderFileReports(raw_ostream &OS, ArrayRef<std::string> Files,
                          const CoverageFiltersMatchAll &Filters) const;
+
+  /// Render file reports with given data.
+  void renderFileReports(raw_ostream &OS,
+                         const std::vector<FileCoverageSummary> &FileReports,
+                         const FileCoverageSummary &Totals,
+                         bool ShowEmptyFiles) const;
+};
+
+/// Prepare reports for every non-trivial directories (which have more than 1
+/// source files) of the source files. This class uses template method pattern.
+class DirectoryCoverageReport {
+public:
+  DirectoryCoverageReport(
+      const CoverageViewOptions &Options,
+      const coverage::CoverageMapping &Coverage,
+      const CoverageFiltersMatchAll &Filters = CoverageFiltersMatchAll())
+      : Options(Options), Coverage(Coverage), Filters(Filters) {}
+
+  virtual ~DirectoryCoverageReport() = default;
+
+  /// Prepare file reports for each directory in \p SourceFiles. The total
+  /// report for all files is returned and its Name is set to the LCP of all
+  /// files. The size of \p SourceFiles must be greater than 1 or else the
+  /// behavior is undefined, in which case you should use
+  /// CoverageReport::prepareSingleFileReport instead. If an error occurs,
+  /// the recursion will stop immediately.
+  Expected<FileCoverageSummary>
+  prepareDirectoryReports(ArrayRef<std::string> SourceFiles);
+
+protected:
+  // These member variables below are used for avoiding being passed
+  // repeatedly in recursion.
+  const CoverageViewOptions &Options;
+  const coverage::CoverageMapping &Coverage;
+  const CoverageFiltersMatchAll &Filters;
+
+  /// For calling CoverageReport::prepareSingleFileReport asynchronously
+  /// in prepareSubDirectoryReports(). It's not intended to be modified by
+  /// generateSubDirectoryReport().
+  ThreadPool *TPool;
+
+  /// One report level may correspond to multiple directory levels as we omit
+  /// directories which have only one subentry. So we use this Stack to track
+  /// each report level's corresponding drectory level.
+  /// Each value in the stack is the LCP prefix length length of that report
+  /// level. LCPStack.front() is the root LCP. Current LCP is LCPStack.back().
+  SmallVector<unsigned, 32> LCPStack;
+
+  // Use std::map to sort table rows in order.
+  using SubFileReports = std::map<StringRef, FileCoverageSummary>;
+  using SubDirReports =
+      std::map<StringRef,
+               std::pair<FileCoverageSummary, SmallVector<StringRef, 0>>>;
+
+  /// This method is called when a report level is prepared during the
+  /// recursion. \p SubFiles are the reports for those files directly in the
+  /// current directory. \p SubDirs are the reports for subdirectories in
+  /// current directory. \p SubTotals is the sum of all, and its name is the
+  /// current LCP. Note that this method won't be called for trivial
+  /// directories.
+  virtual Error generateSubDirectoryReport(SubFileReports &&SubFiles,
+                                           SubDirReports &&SubDirs,
+                                           FileCoverageSummary &&SubTotals) = 0;
+
+private:
+  Error prepareSubDirectoryReports(const ArrayRef<StringRef> &Files,
+                                   FileCoverageSummary *Totals);
 };
 
 } // end namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp b/src/llvm-project/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
index 10e059a..4f15002 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageSummaryInfo.cpp
@@ -44,6 +44,21 @@
   }
 }
 
+static std::pair<size_t, size_t>
+sumMCDCPairs(const ArrayRef<MCDCRecord> &Records) {
+  size_t NumPairs = 0, CoveredPairs = 0;
+  for (const auto &Record : Records) {
+    const auto NumConditions = Record.getNumConditions();
+    for (unsigned C = 0; C < NumConditions; C++) {
+      if (!Record.isCondFolded(C))
+        ++NumPairs;
+      if (Record.isConditionIndependencePairCovered(C))
+        ++CoveredPairs;
+    }
+  }
+  return {NumPairs, CoveredPairs};
+}
+
 FunctionCoverageSummary
 FunctionCoverageSummary::get(const CoverageMapping &CM,
                              const coverage::FunctionRecord &Function) {
@@ -73,11 +88,15 @@
   sumBranches(NumBranches, CoveredBranches, CD.getBranches());
   sumBranchExpansions(NumBranches, CoveredBranches, CM, CD.getExpansions());
 
+  size_t NumPairs = 0, CoveredPairs = 0;
+  std::tie(NumPairs, CoveredPairs) = sumMCDCPairs(CD.getMCDCRecords());
+
   return FunctionCoverageSummary(
       Function.Name, Function.ExecutionCount,
       RegionCoverageInfo(CoveredRegions, NumCodeRegions),
       LineCoverageInfo(CoveredLines, NumLines),
-      BranchCoverageInfo(CoveredBranches, NumBranches));
+      BranchCoverageInfo(CoveredBranches, NumBranches),
+      MCDCCoverageInfo(CoveredPairs, NumPairs));
 }
 
 FunctionCoverageSummary
@@ -97,10 +116,12 @@
   Summary.RegionCoverage = Summaries[0].RegionCoverage;
   Summary.LineCoverage = Summaries[0].LineCoverage;
   Summary.BranchCoverage = Summaries[0].BranchCoverage;
+  Summary.MCDCCoverage = Summaries[0].MCDCCoverage;
   for (const auto &FCS : Summaries.drop_front()) {
     Summary.RegionCoverage.merge(FCS.RegionCoverage);
     Summary.LineCoverage.merge(FCS.LineCoverage);
     Summary.BranchCoverage.merge(FCS.BranchCoverage);
+    Summary.MCDCCoverage.merge(FCS.MCDCCoverage);
   }
   return Summary;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageSummaryInfo.h b/src/llvm-project/llvm/tools/llvm-cov/CoverageSummaryInfo.h
index 84a3228..64c2c84 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageSummaryInfo.h
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageSummaryInfo.h
@@ -142,6 +142,47 @@
   }
 };
 
+/// Provides information about MC/DC coverage for a function/file.
+class MCDCCoverageInfo {
+  /// The number of Independence Pairs that were covered.
+  size_t CoveredPairs;
+
+  /// The total number of Independence Pairs in a function/file.
+  size_t NumPairs;
+
+public:
+  MCDCCoverageInfo() : CoveredPairs(0), NumPairs(0) {}
+
+  MCDCCoverageInfo(size_t CoveredPairs, size_t NumPairs)
+      : CoveredPairs(CoveredPairs), NumPairs(NumPairs) {
+    assert(CoveredPairs <= NumPairs && "Covered pairs over-counted");
+  }
+
+  MCDCCoverageInfo &operator+=(const MCDCCoverageInfo &RHS) {
+    CoveredPairs += RHS.CoveredPairs;
+    NumPairs += RHS.NumPairs;
+    return *this;
+  }
+
+  void merge(const MCDCCoverageInfo &RHS) {
+    CoveredPairs = std::max(CoveredPairs, RHS.CoveredPairs);
+    NumPairs = std::max(NumPairs, RHS.NumPairs);
+  }
+
+  size_t getCoveredPairs() const { return CoveredPairs; }
+
+  size_t getNumPairs() const { return NumPairs; }
+
+  bool isFullyCovered() const { return CoveredPairs == NumPairs; }
+
+  double getPercentCovered() const {
+    assert(CoveredPairs <= NumPairs && "Covered pairs over-counted");
+    if (NumPairs == 0)
+      return 0.0;
+    return double(CoveredPairs) / double(NumPairs) * 100.0;
+  }
+};
+
 /// Provides information about function coverage for a file.
 class FunctionCoverageInfo {
   /// The number of functions that were executed.
@@ -189,6 +230,7 @@
   RegionCoverageInfo RegionCoverage;
   LineCoverageInfo LineCoverage;
   BranchCoverageInfo BranchCoverage;
+  MCDCCoverageInfo MCDCCoverage;
 
   FunctionCoverageSummary(const std::string &Name)
       : Name(Name), ExecutionCount(0) {}
@@ -196,10 +238,11 @@
   FunctionCoverageSummary(const std::string &Name, uint64_t ExecutionCount,
                           const RegionCoverageInfo &RegionCoverage,
                           const LineCoverageInfo &LineCoverage,
-                          const BranchCoverageInfo &BranchCoverage)
+                          const BranchCoverageInfo &BranchCoverage,
+                          const MCDCCoverageInfo &MCDCCoverage)
       : Name(Name), ExecutionCount(ExecutionCount),
         RegionCoverage(RegionCoverage), LineCoverage(LineCoverage),
-        BranchCoverage(BranchCoverage) {}
+        BranchCoverage(BranchCoverage), MCDCCoverage(MCDCCoverage) {}
 
   /// Compute the code coverage summary for the given function coverage
   /// mapping record.
@@ -219,9 +262,11 @@
   RegionCoverageInfo RegionCoverage;
   LineCoverageInfo LineCoverage;
   BranchCoverageInfo BranchCoverage;
+  MCDCCoverageInfo MCDCCoverage;
   FunctionCoverageInfo FunctionCoverage;
   FunctionCoverageInfo InstantiationCoverage;
 
+  FileCoverageSummary() = default;
   FileCoverageSummary(StringRef Name) : Name(Name) {}
 
   FileCoverageSummary &operator+=(const FileCoverageSummary &RHS) {
@@ -229,6 +274,7 @@
     LineCoverage += RHS.LineCoverage;
     FunctionCoverage += RHS.FunctionCoverage;
     BranchCoverage += RHS.BranchCoverage;
+    MCDCCoverage += RHS.MCDCCoverage;
     InstantiationCoverage += RHS.InstantiationCoverage;
     return *this;
   }
@@ -237,6 +283,7 @@
     RegionCoverage += Function.RegionCoverage;
     LineCoverage += Function.LineCoverage;
     BranchCoverage += Function.BranchCoverage;
+    MCDCCoverage += Function.MCDCCoverage;
     FunctionCoverage.addFunction(/*Covered=*/Function.ExecutionCount > 0);
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h b/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h
index fedf2df..6925cff 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -30,14 +30,17 @@
   bool ShowLineNumbers;
   bool ShowLineStats;
   bool ShowRegionMarkers;
+  bool ShowMCDC;
   bool ShowBranchCounts;
   bool ShowBranchPercents;
   bool ShowExpandedRegions;
   bool ShowFunctionInstantiations;
   bool ShowFullFilenames;
   bool ShowBranchSummary;
+  bool ShowMCDCSummary;
   bool ShowRegionSummary;
   bool ShowInstantiationSummary;
+  bool ShowDirectoryCoverage;
   bool ExportSummaryOnly;
   bool SkipExpansions;
   bool SkipFunctions;
diff --git a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageView.cpp b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageView.cpp
index ea86aca..5b85d7d 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageView.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageView.cpp
@@ -48,7 +48,7 @@
   sys::path::append(FullPath, PathFilename);
   sys::path::native(FullPath);
 
-  return std::string(FullPath.str());
+  return std::string(FullPath);
 }
 
 Expected<CoveragePrinter::OwnedStream>
@@ -76,8 +76,12 @@
 CoveragePrinter::create(const CoverageViewOptions &Opts) {
   switch (Opts.Format) {
   case CoverageViewOptions::OutputFormat::Text:
+    if (Opts.ShowDirectoryCoverage)
+      return std::make_unique<CoveragePrinterTextDirectory>(Opts);
     return std::make_unique<CoveragePrinterText>(Opts);
   case CoverageViewOptions::OutputFormat::HTML:
+    if (Opts.ShowDirectoryCoverage)
+      return std::make_unique<CoveragePrinterHTMLDirectory>(Opts);
     return std::make_unique<CoveragePrinterHTML>(Opts);
   case CoverageViewOptions::OutputFormat::Lcov:
     // Unreachable because CodeCoverage.cpp should terminate with an error
@@ -126,6 +130,8 @@
     const auto *CurSeg = Segments[I];
     if (!CurSeg->IsRegionEntry || CurSeg->Count == LCS.getExecutionCount())
       continue;
+    if (!CurSeg->HasCount) // don't show tooltips for SkippedRegions
+      continue;
     return true;
   }
   return false;
@@ -133,7 +139,7 @@
 
 bool SourceCoverageView::hasSubViews() const {
   return !ExpansionSubViews.empty() || !InstantiationSubViews.empty() ||
-         !BranchSubViews.empty();
+         !BranchSubViews.empty() || !MCDCSubViews.empty();
 }
 
 std::unique_ptr<SourceCoverageView>
@@ -159,7 +165,7 @@
   SmallString<128> SourceText(SourceName);
   sys::path::remove_dots(SourceText, /*remove_dot_dot=*/true);
   sys::path::native(SourceText);
-  return std::string(SourceText.str());
+  return std::string(SourceText);
 }
 
 void SourceCoverageView::addExpansion(
@@ -174,6 +180,12 @@
   BranchSubViews.emplace_back(Line, Regions, std::move(View));
 }
 
+void SourceCoverageView::addMCDCRecord(
+    unsigned Line, ArrayRef<MCDCRecord> Records,
+    std::unique_ptr<SourceCoverageView> View) {
+  MCDCSubViews.emplace_back(Line, Records, std::move(View));
+}
+
 void SourceCoverageView::addInstantiation(
     StringRef FunctionName, unsigned Line,
     std::unique_ptr<SourceCoverageView> View) {
@@ -199,12 +211,15 @@
   llvm::stable_sort(ExpansionSubViews);
   llvm::stable_sort(InstantiationSubViews);
   llvm::stable_sort(BranchSubViews);
+  llvm::stable_sort(MCDCSubViews);
   auto NextESV = ExpansionSubViews.begin();
   auto EndESV = ExpansionSubViews.end();
   auto NextISV = InstantiationSubViews.begin();
   auto EndISV = InstantiationSubViews.end();
   auto NextBRV = BranchSubViews.begin();
   auto EndBRV = BranchSubViews.end();
+  auto NextMSV = MCDCSubViews.begin();
+  auto EndMSV = MCDCSubViews.end();
 
   // Get the coverage information for the file.
   auto StartSegment = CoverageInfo.begin();
@@ -272,6 +287,11 @@
       renderBranchView(OS, *NextBRV, ViewDepth + 1);
       RenderedSubView = true;
     }
+    for (; NextMSV != EndMSV && NextMSV->Line == LI.line_number(); ++NextMSV) {
+      renderViewDivider(OS, ViewDepth + 1);
+      renderMCDCView(OS, *NextMSV, ViewDepth + 1);
+      RenderedSubView = true;
+    }
     if (RenderedSubView)
       renderViewDivider(OS, ViewDepth + 1);
     renderLineSuffix(OS, ViewDepth);
diff --git a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageView.h b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageView.h
index 5a9fcdd..2e3fa8e 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageView.h
+++ b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageView.h
@@ -84,6 +84,23 @@
   }
 };
 
+/// A view that represents one or more MCDC regions on a given source line.
+struct MCDCView {
+  std::vector<MCDCRecord> Records;
+  std::unique_ptr<SourceCoverageView> View;
+  unsigned Line;
+
+  MCDCView(unsigned Line, ArrayRef<MCDCRecord> Records,
+           std::unique_ptr<SourceCoverageView> View)
+      : Records(Records), View(std::move(View)), Line(Line) {}
+
+  unsigned getLine() const { return Line; }
+
+  friend bool operator<(const MCDCView &LHS, const MCDCView &RHS) {
+    return LHS.Line < RHS.Line;
+  }
+};
+
 /// A file manager that handles format-aware file creation.
 class CoveragePrinter {
 public:
@@ -99,7 +116,7 @@
   CoveragePrinter(const CoverageViewOptions &Opts) : Opts(Opts) {}
 
   /// Return `OutputDir/ToplevelDir/Path.Extension`. If \p InToplevel is
-  /// false, skip the ToplevelDir component. If \p Relative is false, skip the
+  /// true, skip the ToplevelDir component. If \p Relative is true, skip the
   /// OutputDir component.
   std::string getOutputPath(StringRef Path, StringRef Extension,
                             bool InToplevel, bool Relative = true) const;
@@ -160,6 +177,9 @@
   /// A container for all branches in the source on display.
   std::vector<BranchView> BranchSubViews;
 
+  /// A container for all MCDC records in the source on display.
+  std::vector<MCDCView> MCDCSubViews;
+
   /// A container for all instantiations (e.g template functions) in the source
   /// on display.
   std::vector<InstantiationView> InstantiationSubViews;
@@ -233,6 +253,10 @@
   virtual void renderBranchView(raw_ostream &OS, BranchView &BRV,
                                 unsigned ViewDepth) = 0;
 
+  /// Render an MCDC view.
+  virtual void renderMCDCView(raw_ostream &OS, MCDCView &BRV,
+                              unsigned ViewDepth) = 0;
+
   /// Render \p Title, a project title if one is available, and the
   /// created time.
   virtual void renderTitle(raw_ostream &OS, StringRef CellText) = 0;
@@ -283,6 +307,10 @@
   void addBranch(unsigned Line, ArrayRef<CountedRegion> Regions,
                  std::unique_ptr<SourceCoverageView> View);
 
+  /// Add an MCDC subview to this view.
+  void addMCDCRecord(unsigned Line, ArrayRef<MCDCRecord> Records,
+                     std::unique_ptr<SourceCoverageView> View);
+
   /// 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,
diff --git a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index 50e3dcc..b93d8cb 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -10,12 +10,13 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#include "CoverageReport.h"
 #include "SourceCoverageViewHTML.h"
+#include "CoverageReport.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/ThreadPool.h"
 #include <optional>
 
 using namespace llvm;
@@ -49,23 +50,41 @@
 }
 
 // Create a \p Name tag around \p Str, and optionally set its \p ClassName.
-std::string tag(const std::string &Name, const std::string &Str,
-                const std::string &ClassName = "") {
-  std::string Tag = "<" + Name;
-  if (!ClassName.empty())
-    Tag += " class='" + ClassName + "'";
-  return Tag + ">" + Str + "</" + Name + ">";
+std::string tag(StringRef Name, StringRef Str, StringRef ClassName = "") {
+  std::string Tag = "<";
+  Tag += Name;
+  if (!ClassName.empty()) {
+    Tag += " class='";
+    Tag += ClassName;
+    Tag += "'";
+  }
+  Tag += ">";
+  Tag += Str;
+  Tag += "</";
+  Tag += Name;
+  Tag += ">";
+  return Tag;
 }
 
 // Create an anchor to \p Link with the label \p Str.
-std::string a(const std::string &Link, const std::string &Str,
-              const std::string &TargetName = "") {
-  std::string Name = TargetName.empty() ? "" : ("name='" + TargetName + "' ");
-  return "<a " + Name + "href='" + Link + "'>" + Str + "</a>";
+std::string a(StringRef Link, StringRef Str, StringRef TargetName = "") {
+  std::string Tag;
+  Tag += "<a ";
+  if (!TargetName.empty()) {
+    Tag += "name='";
+    Tag += TargetName;
+    Tag += "' ";
+  }
+  Tag += "href='";
+  Tag += Link;
+  Tag += "'>";
+  Tag += Str;
+  Tag += "</a>";
+  return Tag;
 }
 
 const char *BeginHeader =
-  "<head>"
+    "<head>"
     "<meta name='viewport' content='width=device-width,initial-scale=1'>"
     "<meta charset='UTF-8'>";
 
@@ -111,10 +130,14 @@
 .light-row {
   background: #ffffff;
   border: 1px solid #dbdbdb;
+  border-left: none;
+  border-right: none;
 }
 .light-row-bold {
   background: #ffffff;
   border: 1px solid #dbdbdb;
+  border-left: none;
+  border-right: none;
   font-weight: bold;
 }
 .column-entry {
@@ -128,21 +151,28 @@
   text-align: left;
   background-color: #ffffd0;
 }
-.column-entry-yellow:hover {
+.column-entry-yellow:hover, tr:hover .column-entry-yellow {
   background-color: #fffff0;
 }
 .column-entry-red {
   text-align: left;
   background-color: #ffd0d0;
 }
-.column-entry-red:hover {
+.column-entry-red:hover, tr:hover .column-entry-red {
   background-color: #fff0f0;
 }
+.column-entry-gray {
+  text-align: left;
+  background-color: #fbfbfb;
+}
+.column-entry-gray:hover, tr:hover .column-entry-gray {
+  background-color: #f0f0f0;
+}
 .column-entry-green {
   text-align: left;
   background-color: #d0ffd0;
 }
-.column-entry-green:hover {
+.column-entry-green:hover, tr:hover .column-entry-green {
   background-color: #f0fff0;
 }
 .line-number {
@@ -213,6 +243,12 @@
 tr:hover {
   background-color: #f0f0f0;
 }
+tr:last-child {
+  border-bottom: none;
+}
+tr:has(> td >a:target) > td.code > pre {
+  background-color: #ffa;
+}
 )";
 
 const char *EndHeader = "</head>";
@@ -272,6 +308,63 @@
   OS << EndHeader << "<body>";
 }
 
+void emitTableRow(raw_ostream &OS, const CoverageViewOptions &Opts,
+                  const std::string &FirstCol, const FileCoverageSummary &FCS,
+                  bool IsTotals) {
+  SmallVector<std::string, 8> Columns;
+
+  // Format a coverage triple and add the result to the list of columns.
+  auto AddCoverageTripleToColumn =
+      [&Columns, &Opts](unsigned Hit, unsigned Total, float Pctg) {
+        std::string S;
+        {
+          raw_string_ostream RSO{S};
+          if (Total)
+            RSO << format("%*.2f", 7, Pctg) << "% ";
+          else
+            RSO << "- ";
+          RSO << '(' << Hit << '/' << Total << ')';
+        }
+        const char *CellClass = "column-entry-yellow";
+        if (!Total)
+          CellClass = "column-entry-gray";
+        else if (Pctg >= Opts.HighCovWatermark)
+          CellClass = "column-entry-green";
+        else if (Pctg < Opts.LowCovWatermark)
+          CellClass = "column-entry-red";
+        Columns.emplace_back(tag("td", tag("pre", S), CellClass));
+      };
+
+  Columns.emplace_back(tag("td", tag("pre", FirstCol)));
+  AddCoverageTripleToColumn(FCS.FunctionCoverage.getExecuted(),
+                            FCS.FunctionCoverage.getNumFunctions(),
+                            FCS.FunctionCoverage.getPercentCovered());
+  if (Opts.ShowInstantiationSummary)
+    AddCoverageTripleToColumn(FCS.InstantiationCoverage.getExecuted(),
+                              FCS.InstantiationCoverage.getNumFunctions(),
+                              FCS.InstantiationCoverage.getPercentCovered());
+  AddCoverageTripleToColumn(FCS.LineCoverage.getCovered(),
+                            FCS.LineCoverage.getNumLines(),
+                            FCS.LineCoverage.getPercentCovered());
+  if (Opts.ShowRegionSummary)
+    AddCoverageTripleToColumn(FCS.RegionCoverage.getCovered(),
+                              FCS.RegionCoverage.getNumRegions(),
+                              FCS.RegionCoverage.getPercentCovered());
+  if (Opts.ShowBranchSummary)
+    AddCoverageTripleToColumn(FCS.BranchCoverage.getCovered(),
+                              FCS.BranchCoverage.getNumBranches(),
+                              FCS.BranchCoverage.getPercentCovered());
+  if (Opts.ShowMCDCSummary)
+    AddCoverageTripleToColumn(FCS.MCDCCoverage.getCoveredPairs(),
+                              FCS.MCDCCoverage.getNumPairs(),
+                              FCS.MCDCCoverage.getPercentCovered());
+
+  if (IsTotals)
+    OS << tag("tr", join(Columns.begin(), Columns.end(), ""), "light-row-bold");
+  else
+    OS << tag("tr", join(Columns.begin(), Columns.end(), ""), "light-row");
+}
+
 void emitEpilog(raw_ostream &OS) {
   OS << "</body>"
      << "</html>";
@@ -315,6 +408,8 @@
     Columns.emplace_back(tag("td", "Region Coverage", "column-entry-bold"));
   if (Opts.ShowBranchSummary)
     Columns.emplace_back(tag("td", "Branch Coverage", "column-entry-bold"));
+  if (Opts.ShowMCDCSummary)
+    Columns.emplace_back(tag("td", "MC/DC", "column-entry-bold"));
   OS << tag("tr", join(Columns.begin(), Columns.end(), ""));
 }
 
@@ -330,71 +425,7 @@
   return a(LinkTarget, LinkText);
 }
 
-/// Render a file coverage summary (\p FCS) in a table row. If \p IsTotals is
-/// false, link the summary to \p SF.
-void CoveragePrinterHTML::emitFileSummary(raw_ostream &OS, StringRef SF,
-                                          const FileCoverageSummary &FCS,
-                                          bool IsTotals) const {
-  SmallVector<std::string, 8> Columns;
-
-  // Format a coverage triple and add the result to the list of columns.
-  auto AddCoverageTripleToColumn =
-      [&Columns, this](unsigned Hit, unsigned Total, float Pctg) {
-        std::string S;
-        {
-          raw_string_ostream RSO{S};
-          if (Total)
-            RSO << format("%*.2f", 7, Pctg) << "% ";
-          else
-            RSO << "- ";
-          RSO << '(' << Hit << '/' << Total << ')';
-        }
-        const char *CellClass = "column-entry-yellow";
-        if (Pctg >= Opts.HighCovWatermark)
-          CellClass = "column-entry-green";
-        else if (Pctg < Opts.LowCovWatermark)
-          CellClass = "column-entry-red";
-        Columns.emplace_back(tag("td", tag("pre", S), CellClass));
-      };
-
-  // Simplify the display file path, and wrap it in a link if requested.
-  std::string Filename;
-  if (IsTotals) {
-    Filename = std::string(SF);
-  } else {
-    Filename = buildLinkToFile(SF, FCS);
-  }
-
-  Columns.emplace_back(tag("td", tag("pre", Filename)));
-  AddCoverageTripleToColumn(FCS.FunctionCoverage.getExecuted(),
-                            FCS.FunctionCoverage.getNumFunctions(),
-                            FCS.FunctionCoverage.getPercentCovered());
-  if (Opts.ShowInstantiationSummary)
-    AddCoverageTripleToColumn(FCS.InstantiationCoverage.getExecuted(),
-                              FCS.InstantiationCoverage.getNumFunctions(),
-                              FCS.InstantiationCoverage.getPercentCovered());
-  AddCoverageTripleToColumn(FCS.LineCoverage.getCovered(),
-                            FCS.LineCoverage.getNumLines(),
-                            FCS.LineCoverage.getPercentCovered());
-  if (Opts.ShowRegionSummary)
-    AddCoverageTripleToColumn(FCS.RegionCoverage.getCovered(),
-                              FCS.RegionCoverage.getNumRegions(),
-                              FCS.RegionCoverage.getPercentCovered());
-  if (Opts.ShowBranchSummary)
-    AddCoverageTripleToColumn(FCS.BranchCoverage.getCovered(),
-                              FCS.BranchCoverage.getNumBranches(),
-                              FCS.BranchCoverage.getPercentCovered());
-
-  if (IsTotals)
-    OS << tag("tr", join(Columns.begin(), Columns.end(), ""), "light-row-bold");
-  else
-    OS << tag("tr", join(Columns.begin(), Columns.end(), ""), "light-row");
-}
-
-Error CoveragePrinterHTML::createIndexFile(
-    ArrayRef<std::string> SourceFiles, const CoverageMapping &Coverage,
-    const CoverageFiltersMatchAll &Filters) {
-  // Emit the default stylesheet.
+Error CoveragePrinterHTML::emitStyleSheet() {
   auto CSSOrErr = createOutputStream("style", "css", /*InToplevel=*/true);
   if (Error E = CSSOrErr.takeError())
     return E;
@@ -402,20 +433,15 @@
   OwnedStream CSS = std::move(CSSOrErr.get());
   CSS->operator<<(CSSForCoverage);
 
-  // Emit a file index along with some coverage statistics.
-  auto OSOrErr = createOutputStream("index", "html", /*InToplevel=*/true);
-  if (Error E = OSOrErr.takeError())
-    return E;
-  auto OS = std::move(OSOrErr.get());
-  raw_ostream &OSRef = *OS.get();
+  return Error::success();
+}
 
-  assert(Opts.hasOutputDirectory() && "No output directory for index file");
-  emitPrelude(OSRef, Opts, getPathToStyle(""));
-
+void CoveragePrinterHTML::emitReportHeader(raw_ostream &OSRef,
+                                           const std::string &Title) {
   // Emit some basic information about the coverage report.
   if (Opts.hasProjectTitle())
     OSRef << tag(ProjectTitleTag, escape(Opts.ProjectTitle, Opts));
-  OSRef << tag(ReportTitleTag, "Coverage Report");
+  OSRef << tag(ReportTitleTag, Title);
   if (Opts.hasCreatedTime())
     OSRef << tag(CreatedTimeTag, escape(Opts.CreatedTimeStr, Opts));
 
@@ -430,6 +456,43 @@
   // Exclude files which don't contain any regions.
   OSRef << BeginCenteredDiv << BeginTable;
   emitColumnLabelsForIndex(OSRef, Opts);
+}
+
+/// Render a file coverage summary (\p FCS) in a table row. If \p IsTotals is
+/// false, link the summary to \p SF.
+void CoveragePrinterHTML::emitFileSummary(raw_ostream &OS, StringRef SF,
+                                          const FileCoverageSummary &FCS,
+                                          bool IsTotals) const {
+  // Simplify the display file path, and wrap it in a link if requested.
+  std::string Filename;
+  if (IsTotals) {
+    Filename = std::string(SF);
+  } else {
+    Filename = buildLinkToFile(SF, FCS);
+  }
+
+  emitTableRow(OS, Opts, Filename, FCS, IsTotals);
+}
+
+Error CoveragePrinterHTML::createIndexFile(
+    ArrayRef<std::string> SourceFiles, const CoverageMapping &Coverage,
+    const CoverageFiltersMatchAll &Filters) {
+  // Emit the default stylesheet.
+  if (Error E = emitStyleSheet())
+    return E;
+
+  // Emit a file index along with some coverage statistics.
+  auto OSOrErr = createOutputStream("index", "html", /*InToplevel=*/true);
+  if (Error E = OSOrErr.takeError())
+    return E;
+  auto OS = std::move(OSOrErr.get());
+  raw_ostream &OSRef = *OS.get();
+
+  assert(Opts.hasOutputDirectory() && "No output directory for index file");
+  emitPrelude(OSRef, Opts, getPathToStyle(""));
+
+  emitReportHeader(OSRef, "Coverage Report");
+
   FileCoverageSummary Totals("TOTALS");
   auto FileReports = CoverageReport::prepareFileReports(
       Coverage, Totals, SourceFiles, Opts, Filters);
@@ -465,6 +528,199 @@
   return Error::success();
 }
 
+struct CoveragePrinterHTMLDirectory::Reporter : public DirectoryCoverageReport {
+  CoveragePrinterHTMLDirectory &Printer;
+
+  Reporter(CoveragePrinterHTMLDirectory &Printer,
+           const coverage::CoverageMapping &Coverage,
+           const CoverageFiltersMatchAll &Filters)
+      : DirectoryCoverageReport(Printer.Opts, Coverage, Filters),
+        Printer(Printer) {}
+
+  Error generateSubDirectoryReport(SubFileReports &&SubFiles,
+                                   SubDirReports &&SubDirs,
+                                   FileCoverageSummary &&SubTotals) override {
+    auto &LCPath = SubTotals.Name;
+    assert(Options.hasOutputDirectory() &&
+           "No output directory for index file");
+
+    SmallString<128> OSPath = LCPath;
+    sys::path::append(OSPath, "index");
+    auto OSOrErr = Printer.createOutputStream(OSPath, "html",
+                                              /*InToplevel=*/false);
+    if (auto E = OSOrErr.takeError())
+      return E;
+    auto OS = std::move(OSOrErr.get());
+    raw_ostream &OSRef = *OS.get();
+
+    auto IndexHtmlPath = Printer.getOutputPath((LCPath + "index").str(), "html",
+                                               /*InToplevel=*/false);
+    emitPrelude(OSRef, Options, getPathToStyle(IndexHtmlPath));
+
+    auto NavLink = buildTitleLinks(LCPath);
+    Printer.emitReportHeader(OSRef, "Coverage Report (" + NavLink + ")");
+
+    std::vector<const FileCoverageSummary *> EmptyFiles;
+
+    // Make directories at the top of the table.
+    for (auto &&SubDir : SubDirs) {
+      auto &Report = SubDir.second.first;
+      if (!Report.FunctionCoverage.getNumFunctions())
+        EmptyFiles.push_back(&Report);
+      else
+        emitTableRow(OSRef, Options, buildRelLinkToFile(Report.Name), Report,
+                     /*IsTotals=*/false);
+    }
+
+    for (auto &&SubFile : SubFiles) {
+      auto &Report = SubFile.second;
+      if (!Report.FunctionCoverage.getNumFunctions())
+        EmptyFiles.push_back(&Report);
+      else
+        emitTableRow(OSRef, Options, buildRelLinkToFile(Report.Name), Report,
+                     /*IsTotals=*/false);
+    }
+
+    // Emit the totals row.
+    emitTableRow(OSRef, Options, "Totals", SubTotals, /*IsTotals=*/false);
+    OSRef << EndTable << EndCenteredDiv;
+
+    // Emit links to files which don't contain any functions. These are normally
+    // not very useful, but could be relevant for code which abuses the
+    // preprocessor.
+    if (!EmptyFiles.empty()) {
+      OSRef << tag("p", "Files which contain no functions. (These "
+                        "files contain code pulled into other files "
+                        "by the preprocessor.)\n");
+      OSRef << BeginCenteredDiv << BeginTable;
+      for (auto FCS : EmptyFiles) {
+        auto Link = buildRelLinkToFile(FCS->Name);
+        OSRef << tag("tr", tag("td", tag("pre", Link)), "light-row") << '\n';
+      }
+      OSRef << EndTable << EndCenteredDiv;
+    }
+
+    // Emit epilog.
+    OSRef << tag("h5", escape(Options.getLLVMVersionString(), Options));
+    emitEpilog(OSRef);
+
+    return Error::success();
+  }
+
+  /// Make a title with hyperlinks to the index.html files of each hierarchy
+  /// of the report.
+  std::string buildTitleLinks(StringRef LCPath) const {
+    // For each report level in LCPStack, extract the path component and
+    // calculate the number of "../" relative to current LCPath.
+    SmallVector<std::pair<SmallString<128>, unsigned>, 16> Components;
+
+    auto Iter = LCPStack.begin(), IterE = LCPStack.end();
+    SmallString<128> RootPath;
+    if (*Iter == 0) {
+      // If llvm-cov works on relative coverage mapping data, the LCP of
+      // all source file paths can be 0, which makes the title path empty.
+      // As we like adding a slash at the back of the path to indicate a
+      // directory, in this case, we use "." as the root path to make it
+      // not be confused with the root path "/".
+      RootPath = ".";
+    } else {
+      RootPath = LCPath.substr(0, *Iter);
+      sys::path::native(RootPath);
+      sys::path::remove_dots(RootPath, /*remove_dot_dot=*/true);
+    }
+    Components.emplace_back(std::move(RootPath), 0);
+
+    for (auto Last = *Iter; ++Iter != IterE; Last = *Iter) {
+      SmallString<128> SubPath = LCPath.substr(Last, *Iter - Last);
+      sys::path::native(SubPath);
+      sys::path::remove_dots(SubPath, /*remove_dot_dot=*/true);
+      auto Level = unsigned(SubPath.count(sys::path::get_separator())) + 1;
+      Components.back().second += Level;
+      Components.emplace_back(std::move(SubPath), Level);
+    }
+
+    // Then we make the title accroding to Components.
+    std::string S;
+    for (auto I = Components.begin(), E = Components.end();;) {
+      auto &Name = I->first;
+      if (++I == E) {
+        S += a("./index.html", Name);
+        S += sys::path::get_separator();
+        break;
+      }
+
+      SmallString<128> Link;
+      for (unsigned J = I->second; J > 0; --J)
+        Link += "../";
+      Link += "index.html";
+      S += a(Link, Name);
+      S += sys::path::get_separator();
+    }
+    return S;
+  }
+
+  std::string buildRelLinkToFile(StringRef RelPath) const {
+    SmallString<128> LinkTextStr(RelPath);
+    sys::path::native(LinkTextStr);
+
+    // remove_dots will remove trailing slash, so we need to check before it.
+    auto IsDir = LinkTextStr.ends_with(sys::path::get_separator());
+    sys::path::remove_dots(LinkTextStr, /*remove_dot_dot=*/true);
+
+    SmallString<128> LinkTargetStr(LinkTextStr);
+    if (IsDir) {
+      LinkTextStr += sys::path::get_separator();
+      sys::path::append(LinkTargetStr, "index.html");
+    } else {
+      LinkTargetStr += ".html";
+    }
+
+    auto LinkText = escape(LinkTextStr, Options);
+    auto LinkTarget = escape(LinkTargetStr, Options);
+    return a(LinkTarget, LinkText);
+  }
+};
+
+Error CoveragePrinterHTMLDirectory::createIndexFile(
+    ArrayRef<std::string> SourceFiles, const CoverageMapping &Coverage,
+    const CoverageFiltersMatchAll &Filters) {
+  // The createSubIndexFile function only works when SourceFiles is
+  // more than one. So we fallback to CoveragePrinterHTML when it is.
+  if (SourceFiles.size() <= 1)
+    return CoveragePrinterHTML::createIndexFile(SourceFiles, Coverage, Filters);
+
+  // Emit the default stylesheet.
+  if (Error E = emitStyleSheet())
+    return E;
+
+  // Emit index files in every subdirectory.
+  Reporter Report(*this, Coverage, Filters);
+  auto TotalsOrErr = Report.prepareDirectoryReports(SourceFiles);
+  if (auto E = TotalsOrErr.takeError())
+    return E;
+  auto &LCPath = TotalsOrErr->Name;
+
+  // Emit the top level index file. Top level index file is just a redirection
+  // to the index file in the LCP directory.
+  auto OSOrErr = createOutputStream("index", "html", /*InToplevel=*/true);
+  if (auto E = OSOrErr.takeError())
+    return E;
+  auto OS = std::move(OSOrErr.get());
+  auto LCPIndexFilePath =
+      getOutputPath((LCPath + "index").str(), "html", /*InToplevel=*/false);
+  *OS.get() << R"(<!DOCTYPE html>
+  <html>
+    <head>
+      <meta http-equiv="Refresh" content="0; url=')"
+            << LCPIndexFilePath << R"('" />
+    </head>
+    <body></body>
+  </html>
+  )";
+
+  return Error::success();
+}
+
 void SourceCoverageViewHTML::renderViewHeader(raw_ostream &OS) {
   OS << BeginCenteredDiv << BeginTable;
 }
@@ -668,7 +924,9 @@
     // Calculate TruePercent and False Percent.
     double TruePercent = 0.0;
     double FalsePercent = 0.0;
-    unsigned Total = R.ExecutionCount + R.FalseExecutionCount;
+    // FIXME: It may overflow when the data is too large, but I have not
+    // encountered it in actual use, and not sure whether to use __uint128_t.
+    uint64_t Total = R.ExecutionCount + R.FalseExecutionCount;
 
     if (!getOptions().ShowBranchCounts && Total != 0) {
       TruePercent = ((double)(R.ExecutionCount) / (double)Total) * 100.0;
@@ -722,6 +980,50 @@
   OS << EndExpansionDiv;
 }
 
+void SourceCoverageViewHTML::renderMCDCView(raw_ostream &OS, MCDCView &MRV,
+                                            unsigned ViewDepth) {
+  for (auto &Record : MRV.Records) {
+    OS << BeginExpansionDiv;
+    OS << BeginPre;
+    OS << "  MC/DC Decision Region (";
+
+    // Display Line + Column information.
+    const CounterMappingRegion &DecisionRegion = Record.getDecisionRegion();
+    std::string LineNoStr = Twine(DecisionRegion.LineStart).str();
+    std::string ColNoStr = Twine(DecisionRegion.ColumnStart).str();
+    std::string TargetName = "L" + LineNoStr;
+    OS << tag("span",
+              a("#" + TargetName, tag("span", LineNoStr + ":" + ColNoStr)),
+              "line-number") +
+              ") to (";
+    LineNoStr = utostr(uint64_t(DecisionRegion.LineEnd));
+    ColNoStr = utostr(uint64_t(DecisionRegion.ColumnEnd));
+    OS << tag("span",
+              a("#" + TargetName, tag("span", LineNoStr + ":" + ColNoStr)),
+              "line-number") +
+              ")\n\n";
+
+    // Display MC/DC Information.
+    OS << "  Number of Conditions: " << Record.getNumConditions() << "\n";
+    for (unsigned i = 0; i < Record.getNumConditions(); i++) {
+      OS << "     " << Record.getConditionHeaderString(i);
+    }
+    OS << "\n";
+    OS << "  Executed MC/DC Test Vectors:\n\n     ";
+    OS << Record.getTestVectorHeaderString();
+    for (unsigned i = 0; i < Record.getNumTestVectors(); i++)
+      OS << Record.getTestVectorString(i);
+    OS << "\n";
+    for (unsigned i = 0; i < Record.getNumConditions(); i++)
+      OS << Record.getConditionCoverageString(i);
+    OS << "  MC/DC Coverage for Expression: ";
+    OS << format("%0.2f", Record.getPercentCovered()) << "%\n";
+    OS << EndPre;
+    OS << EndExpansionDiv;
+  }
+  return;
+}
+
 void SourceCoverageViewHTML::renderInstantiationView(raw_ostream &OS,
                                                      InstantiationView &ISV,
                                                      unsigned ViewDepth) {
diff --git a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.h b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
index 7d94675..7b97f05 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
+++ b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.h
@@ -19,6 +19,8 @@
 
 using namespace coverage;
 
+class ThreadPool;
+
 struct FileCoverageSummary;
 
 /// A coverage printer for html output.
@@ -36,6 +38,10 @@
   CoveragePrinterHTML(const CoverageViewOptions &Opts)
       : CoveragePrinter(Opts) {}
 
+protected:
+  Error emitStyleSheet();
+  void emitReportHeader(raw_ostream &OSRef, const std::string &Title);
+
 private:
   void emitFileSummary(raw_ostream &OS, StringRef SF,
                        const FileCoverageSummary &FCS,
@@ -44,6 +50,20 @@
                               const FileCoverageSummary &FCS) const;
 };
 
+/// A coverage printer for html output, but generates index files in every
+/// subdirectory to show a hierarchical view.
+class CoveragePrinterHTMLDirectory : public CoveragePrinterHTML {
+public:
+  using CoveragePrinterHTML::CoveragePrinterHTML;
+
+  Error createIndexFile(ArrayRef<std::string> SourceFiles,
+                        const coverage::CoverageMapping &Coverage,
+                        const CoverageFiltersMatchAll &Filters) override;
+
+private:
+  struct Reporter;
+};
+
 /// A code coverage view which supports html-based rendering.
 class SourceCoverageViewHTML : public SourceCoverageView {
   void renderViewHeader(raw_ostream &OS) override;
@@ -71,6 +91,9 @@
   void renderBranchView(raw_ostream &OS, BranchView &BRV,
                         unsigned ViewDepth) override;
 
+  void renderMCDCView(raw_ostream &OS, MCDCView &BRV,
+                      unsigned ViewDepth) override;
+
   void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
                                unsigned ViewDepth) override;
 
diff --git a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index 40d4359..580da45 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -14,7 +14,9 @@
 #include "CoverageReport.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
 #include <optional>
 
 using namespace llvm;
@@ -46,6 +48,69 @@
   return Error::success();
 }
 
+struct CoveragePrinterTextDirectory::Reporter : public DirectoryCoverageReport {
+  CoveragePrinterTextDirectory &Printer;
+
+  Reporter(CoveragePrinterTextDirectory &Printer,
+           const coverage::CoverageMapping &Coverage,
+           const CoverageFiltersMatchAll &Filters)
+      : DirectoryCoverageReport(Printer.Opts, Coverage, Filters),
+        Printer(Printer) {}
+
+  Error generateSubDirectoryReport(SubFileReports &&SubFiles,
+                                   SubDirReports &&SubDirs,
+                                   FileCoverageSummary &&SubTotals) override {
+    auto &LCPath = SubTotals.Name;
+    assert(Options.hasOutputDirectory() &&
+           "No output directory for index file");
+
+    SmallString<128> OSPath = LCPath;
+    sys::path::append(OSPath, "index");
+    auto OSOrErr = Printer.createOutputStream(OSPath, "txt",
+                                              /*InToplevel=*/false);
+    if (auto E = OSOrErr.takeError())
+      return E;
+    auto OS = std::move(OSOrErr.get());
+    raw_ostream &OSRef = *OS.get();
+
+    std::vector<FileCoverageSummary> Reports;
+    for (auto &&SubDir : SubDirs)
+      Reports.push_back(std::move(SubDir.second.first));
+    for (auto &&SubFile : SubFiles)
+      Reports.push_back(std::move(SubFile.second));
+
+    CoverageReport Report(Options, Coverage);
+    Report.renderFileReports(OSRef, Reports, SubTotals, Filters.empty());
+
+    Options.colored_ostream(OSRef, raw_ostream::CYAN)
+        << "\n"
+        << Options.getLLVMVersionString();
+
+    return Error::success();
+  }
+};
+
+Error CoveragePrinterTextDirectory::createIndexFile(
+    ArrayRef<std::string> SourceFiles, const CoverageMapping &Coverage,
+    const CoverageFiltersMatchAll &Filters) {
+  if (SourceFiles.size() <= 1)
+    return CoveragePrinterText::createIndexFile(SourceFiles, Coverage, Filters);
+
+  Reporter Report(*this, Coverage, Filters);
+  auto TotalsOrErr = Report.prepareDirectoryReports(SourceFiles);
+  if (auto E = TotalsOrErr.takeError())
+    return E;
+  auto &LCPath = TotalsOrErr->Name;
+
+  auto TopIndexFilePath =
+      getOutputPath("index", "txt", /*InToplevel=*/true, /*Relative=*/false);
+  auto LCPIndexFilePath =
+      getOutputPath((LCPath + "index").str(), "txt", /*InToplevel=*/false,
+                    /*Relative=*/false);
+  return errorCodeToError(
+      sys::fs::copy_file(LCPIndexFilePath, TopIndexFilePath));
+}
+
 namespace {
 
 static const unsigned LineCoverageColumnWidth = 7;
@@ -232,7 +297,9 @@
   for (const auto &R : BRV.Regions) {
     double TruePercent = 0.0;
     double FalsePercent = 0.0;
-    unsigned Total = R.ExecutionCount + R.FalseExecutionCount;
+    // FIXME: It may overflow when the data is too large, but I have not
+    // encountered it in actual use, and not sure whether to use __uint128_t.
+    uint64_t Total = R.ExecutionCount + R.FalseExecutionCount;
 
     if (!getOptions().ShowBranchCounts && Total != 0) {
       TruePercent = ((double)(R.ExecutionCount) / (double)Total) * 100.0;
@@ -270,6 +337,58 @@
   }
 }
 
+void SourceCoverageViewText::renderMCDCView(raw_ostream &OS, MCDCView &MRV,
+                                            unsigned ViewDepth) {
+  for (auto &Record : MRV.Records) {
+    renderLinePrefix(OS, ViewDepth);
+    OS << "---> MC/DC Decision Region (";
+    // Display Line + Column information.
+    const CounterMappingRegion &DecisionRegion = Record.getDecisionRegion();
+    OS << DecisionRegion.LineStart << ":";
+    OS << DecisionRegion.ColumnStart << ") to (";
+    OS << DecisionRegion.LineEnd << ":";
+    OS << DecisionRegion.ColumnEnd << ")\n";
+    renderLinePrefix(OS, ViewDepth);
+    OS << "\n";
+
+    // Display MC/DC Information.
+    renderLinePrefix(OS, ViewDepth);
+    OS << "  Number of Conditions: " << Record.getNumConditions() << "\n";
+    for (unsigned i = 0; i < Record.getNumConditions(); i++) {
+      renderLinePrefix(OS, ViewDepth);
+      OS << "     " << Record.getConditionHeaderString(i);
+    }
+    renderLinePrefix(OS, ViewDepth);
+    OS << "\n";
+    renderLinePrefix(OS, ViewDepth);
+    OS << "  Executed MC/DC Test Vectors:\n";
+    renderLinePrefix(OS, ViewDepth);
+    OS << "\n";
+    renderLinePrefix(OS, ViewDepth);
+    OS << "     ";
+    OS << Record.getTestVectorHeaderString();
+    for (unsigned i = 0; i < Record.getNumTestVectors(); i++) {
+      renderLinePrefix(OS, ViewDepth);
+      OS << Record.getTestVectorString(i);
+    }
+    renderLinePrefix(OS, ViewDepth);
+    OS << "\n";
+    for (unsigned i = 0; i < Record.getNumConditions(); i++) {
+      renderLinePrefix(OS, ViewDepth);
+      OS << Record.getConditionCoverageString(i);
+    }
+    renderLinePrefix(OS, ViewDepth);
+    OS << "  MC/DC Coverage for Decision: ";
+    colored_ostream(OS, raw_ostream::RED,
+                    getOptions().Colors && Record.getPercentCovered() < 100.0,
+                    /*Bold=*/false, /*BG=*/true)
+        << format("%0.2f", Record.getPercentCovered()) << "%";
+    OS << "\n";
+    renderLinePrefix(OS, ViewDepth);
+    OS << "\n";
+  }
+}
+
 void SourceCoverageViewText::renderInstantiationView(raw_ostream &OS,
                                                      InstantiationView &ISV,
                                                      unsigned ViewDepth) {
diff --git a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.h b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.h
index b2be060..7cb47fc 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.h
+++ b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.h
@@ -35,6 +35,21 @@
       : CoveragePrinter(Opts) {}
 };
 
+/// A coverage printer for text output, but generates index files in every
+/// subdirectory to show a hierarchical view. The implementation is similar
+/// to CoveragePrinterHTMLDirectory. So please refer to that for more comments.
+class CoveragePrinterTextDirectory : public CoveragePrinterText {
+public:
+  using CoveragePrinterText::CoveragePrinterText;
+
+  Error createIndexFile(ArrayRef<std::string> SourceFiles,
+                        const CoverageMapping &Coverage,
+                        const CoverageFiltersMatchAll &Filters) override;
+
+private:
+  struct Reporter;
+};
+
 /// A code coverage view which supports text-based rendering.
 class SourceCoverageViewText : public SourceCoverageView {
   void renderViewHeader(raw_ostream &OS) override;
@@ -62,6 +77,9 @@
   void renderBranchView(raw_ostream &OS, BranchView &BRV,
                         unsigned ViewDepth) override;
 
+  void renderMCDCView(raw_ostream &OS, MCDCView &BRV,
+                      unsigned ViewDepth) override;
+
   void renderInstantiationView(raw_ostream &OS, InstantiationView &ISV,
                                unsigned ViewDepth) override;
 
diff --git a/src/llvm-project/llvm/tools/llvm-cov/TestingSupport.cpp b/src/llvm-project/llvm/tools/llvm-cov/TestingSupport.cpp
index 289a162..6ad8c35 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/TestingSupport.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/TestingSupport.cpp
@@ -6,7 +6,9 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/Object/COFF.h"
 #include "llvm/Object/ObjectFile.h"
+#include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/Support/Alignment.h"
 #include "llvm/Support/CommandLine.h"
@@ -51,6 +53,28 @@
   int FoundSectionCount = 0;
   SectionRef ProfileNames, CoverageMapping, CoverageRecords;
   auto ObjFormat = OF->getTripleObjectFormat();
+
+  auto ProfileNamesSection = getInstrProfSectionName(IPSK_name, ObjFormat,
+                                                     /*AddSegmentInfo=*/false);
+  auto CoverageMappingSection =
+      getInstrProfSectionName(IPSK_covmap, ObjFormat, /*AddSegmentInfo=*/false);
+  auto CoverageRecordsSection =
+      getInstrProfSectionName(IPSK_covfun, ObjFormat, /*AddSegmentInfo=*/false);
+  if (isa<object::COFFObjectFile>(OF)) {
+    // On COFF, the object file section name may end in "$M". This tells the
+    // linker to sort these sections between "$A" and "$Z". The linker removes
+    // the dollar and everything after it in the final binary. Do the same to
+    // match.
+    auto Strip = [](std::string &Str) {
+      auto Pos = Str.find('$');
+      if (Pos != std::string::npos)
+        Str.resize(Pos);
+    };
+    Strip(ProfileNamesSection);
+    Strip(CoverageMappingSection);
+    Strip(CoverageRecordsSection);
+  }
+
   for (const auto &Section : OF->sections()) {
     StringRef Name;
     if (Expected<StringRef> NameOrErr = Section.getName()) {
@@ -60,16 +84,13 @@
       return 1;
     }
 
-    if (Name == llvm::getInstrProfSectionName(IPSK_name, ObjFormat,
-                                              /*AddSegmentInfo=*/false)) {
+    if (Name == ProfileNamesSection)
       ProfileNames = Section;
-    } else if (Name == llvm::getInstrProfSectionName(
-                           IPSK_covmap, ObjFormat, /*AddSegmentInfo=*/false)) {
+    else if (Name == CoverageMappingSection)
       CoverageMapping = Section;
-    } else if (Name == llvm::getInstrProfSectionName(
-                           IPSK_covfun, ObjFormat, /*AddSegmentInfo=*/false)) {
+    else if (Name == CoverageRecordsSection)
       CoverageRecords = Section;
-    } else
+    else
       continue;
     ++FoundSectionCount;
   }
@@ -100,25 +121,22 @@
     return 1;
   }
 
+  // If this is a linked PE/COFF file, then we have to skip over the null byte
+  // that is allocated in the .lprfn$A section in the LLVM profiling runtime.
+  if (isa<COFFObjectFile>(OF) && !OF->isRelocatableObject())
+    ProfileNamesData = ProfileNamesData.drop_front(1);
+
   int FD;
   if (auto Err = sys::fs::openFileForWrite(OutputFilename, FD)) {
     errs() << "error: " << Err.message() << "\n";
     return 1;
   }
 
+  coverage::TestingFormatWriter Writer(ProfileNamesAddress, ProfileNamesData,
+                                       CoverageMappingData,
+                                       CoverageRecordsData);
   raw_fd_ostream OS(FD, true);
-  OS << "llvmcovmtestdata";
-  encodeULEB128(ProfileNamesData.size(), OS);
-  encodeULEB128(ProfileNamesAddress, OS);
-  OS << ProfileNamesData;
-  // Coverage mapping data is expected to have an alignment of 8.
-  for (unsigned Pad = offsetToAlignment(OS.tell(), Align(8)); Pad; --Pad)
-    OS.write(uint8_t(0));
-  OS << CoverageMappingData;
-  // Coverage records data is expected to have an alignment of 8.
-  for (unsigned Pad = offsetToAlignment(OS.tell(), Align(8)); Pad; --Pad)
-    OS.write(uint8_t(0));
-  OS << CoverageRecordsData;
+  Writer.write(OS);
 
   return 0;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-cov/gcov.cpp b/src/llvm-project/llvm/tools/llvm-cov/gcov.cpp
index 9a1ebeb..00ea124 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/gcov.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/gcov.cpp
@@ -35,12 +35,10 @@
     // A file was given. Ignore the source file and look next to this file.
     sys::path::replace_extension(CoverageFileStem, "");
 
-  std::string GCNO = InputGCNO.empty()
-                         ? std::string(CoverageFileStem.str()) + ".gcno"
-                         : InputGCNO;
-  std::string GCDA = InputGCDA.empty()
-                         ? std::string(CoverageFileStem.str()) + ".gcda"
-                         : InputGCDA;
+  std::string GCNO =
+      InputGCNO.empty() ? std::string(CoverageFileStem) + ".gcno" : InputGCNO;
+  std::string GCDA =
+      InputGCDA.empty() ? std::string(CoverageFileStem) + ".gcda" : InputGCDA;
   GCOVFile GF;
 
   // Open .gcda and .gcda without requiring a NUL terminator. The concurrent
diff --git a/src/llvm-project/llvm/tools/llvm-cvtres/llvm-cvtres.cpp b/src/llvm-project/llvm/tools/llvm-cvtres/llvm-cvtres.cpp
index 9040237..0c10769 100644
--- a/src/llvm-project/llvm/tools/llvm-cvtres/llvm-cvtres.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cvtres/llvm-cvtres.cpp
@@ -37,9 +37,7 @@
 
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -51,14 +49,9 @@
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
diff --git a/src/llvm-project/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp b/src/llvm-project/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
index f35f626..c04aec1 100644
--- a/src/llvm-project/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
@@ -217,7 +217,7 @@
     // VFTables in the MS-ABI start with '??_7' and are contained within their
     // own COMDAT section.  We then determine the contents of the VFTable by
     // looking at each relocation in the section.
-    if (SymName.startswith("??_7")) {
+    if (SymName.starts_with("??_7")) {
       // Each relocation either names a virtual method or a thunk.  We note the
       // offset into the section and the symbol used for the relocation.
       collectRelocationOffsets(Obj, Sec, SecAddress, SecAddress, SecSize,
@@ -225,14 +225,14 @@
     }
     // VBTables in the MS-ABI start with '??_8' and are filled with 32-bit
     // offsets of virtual bases.
-    else if (SymName.startswith("??_8")) {
+    else if (SymName.starts_with("??_8")) {
       ArrayRef<little32_t> VBTableData(
           reinterpret_cast<const little32_t *>(SymContents.data()),
           SymContents.size() / sizeof(little32_t));
       VBTables[SymName] = VBTableData;
     }
     // Complete object locators in the MS-ABI start with '??_R4'
-    else if (SymName.startswith("??_R4")) {
+    else if (SymName.starts_with("??_R4")) {
       CompleteObjectLocator COL;
       COL.Data =
           ArrayRef(reinterpret_cast<const little32_t *>(SymContents.data()), 3);
@@ -241,7 +241,7 @@
       COLs[SymName] = COL;
     }
     // Class hierarchy descriptors in the MS-ABI start with '??_R3'
-    else if (SymName.startswith("??_R3")) {
+    else if (SymName.starts_with("??_R3")) {
       ClassHierarchyDescriptor CHD;
       CHD.Data =
           ArrayRef(reinterpret_cast<const little32_t *>(SymContents.data()), 3);
@@ -250,14 +250,14 @@
       CHDs[SymName] = CHD;
     }
     // Class hierarchy descriptors in the MS-ABI start with '??_R2'
-    else if (SymName.startswith("??_R2")) {
+    else if (SymName.starts_with("??_R2")) {
       // Each relocation names a base class descriptor.  We note the offset into
       // the section and the symbol used for the relocation.
       collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize,
                                SymName, BCAEntries);
     }
     // Base class descriptors in the MS-ABI start with '??_R1'
-    else if (SymName.startswith("??_R1")) {
+    else if (SymName.starts_with("??_R1")) {
       BaseClassDescriptor BCD;
       BCD.Data = ArrayRef(
           reinterpret_cast<const little32_t *>(SymContents.data()) + 1, 5);
@@ -266,7 +266,7 @@
       BCDs[SymName] = BCD;
     }
     // Type descriptors in the MS-ABI start with '??_R0'
-    else if (SymName.startswith("??_R0")) {
+    else if (SymName.starts_with("??_R0")) {
       const char *DataPtr = SymContents.drop_front(BytesInAddress).data();
       TypeDescriptor TD;
       if (BytesInAddress == 8)
@@ -279,7 +279,7 @@
       TDs[SymName] = TD;
     }
     // Throw descriptors in the MS-ABI start with '_TI'
-    else if (SymName.startswith("_TI") || SymName.startswith("__TI")) {
+    else if (SymName.starts_with("_TI") || SymName.starts_with("__TI")) {
       ThrowInfo TI;
       TI.Flags = *reinterpret_cast<const little32_t *>(SymContents.data());
       collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize,
@@ -287,7 +287,7 @@
       TIs[SymName] = TI;
     }
     // Catchable type arrays in the MS-ABI start with _CTA or __CTA.
-    else if (SymName.startswith("_CTA") || SymName.startswith("__CTA")) {
+    else if (SymName.starts_with("_CTA") || SymName.starts_with("__CTA")) {
       CatchableTypeArray CTA;
       CTA.NumEntries =
           *reinterpret_cast<const little32_t *>(SymContents.data());
@@ -296,7 +296,7 @@
       CTAs[SymName] = CTA;
     }
     // Catchable types in the MS-ABI start with _CT or __CT.
-    else if (SymName.startswith("_CT") || SymName.startswith("__CT")) {
+    else if (SymName.starts_with("_CT") || SymName.starts_with("__CT")) {
       const little32_t *DataPtr =
           reinterpret_cast<const little32_t *>(SymContents.data());
       CatchableType CT;
@@ -310,16 +310,16 @@
       CTs[SymName] = CT;
     }
     // Construction vtables in the Itanium ABI start with '_ZTT' or '__ZTT'.
-    else if (SymName.startswith("_ZTT") || SymName.startswith("__ZTT")) {
+    else if (SymName.starts_with("_ZTT") || SymName.starts_with("__ZTT")) {
       collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize,
                                SymName, VTTEntries);
     }
     // Typeinfo names in the Itanium ABI start with '_ZTS' or '__ZTS'.
-    else if (SymName.startswith("_ZTS") || SymName.startswith("__ZTS")) {
+    else if (SymName.starts_with("_ZTS") || SymName.starts_with("__ZTS")) {
       TINames[SymName] = SymContents.slice(0, SymContents.find('\0'));
     }
     // Vtables in the Itanium ABI start with '_ZTV' or '__ZTV'.
-    else if (SymName.startswith("_ZTV") || SymName.startswith("__ZTV")) {
+    else if (SymName.starts_with("_ZTV") || SymName.starts_with("__ZTV")) {
       collectRelocationOffsets(Obj, Sec, SecAddress, SymAddress, SymSize,
                                SymName, VTableSymEntries);
       for (uint64_t SymOffI = 0; SymOffI < SymSize; SymOffI += BytesInAddress) {
@@ -337,7 +337,7 @@
       }
     }
     // Typeinfo structures in the Itanium ABI start with '_ZTI' or '__ZTI'.
-    else if (SymName.startswith("_ZTI") || SymName.startswith("__ZTI")) {
+    else if (SymName.starts_with("_ZTI") || SymName.starts_with("__ZTI")) {
       // FIXME: Do something with these!
     }
   }
diff --git a/src/llvm-project/llvm/tools/llvm-cxxfilt/Opts.td b/src/llvm-project/llvm/tools/llvm-cxxfilt/Opts.td
index f652a1a..034cb26 100644
--- a/src/llvm-project/llvm/tools/llvm-cxxfilt/Opts.td
+++ b/src/llvm-project/llvm/tools/llvm-cxxfilt/Opts.td
@@ -17,6 +17,7 @@
 def help : FF<"help", "Display this help">;
 defm strip_underscore : BB<"strip-underscore", "Strip the leading underscore", "Don't strip the leading underscore">;
 def types : FF<"types", "Attempt to demangle types as well as function names">;
+def no_params : FF<"no-params", "Skip function parameters and return types">;
 def version : FF<"version", "Display the version">;
 
 defm : Eq<"format", "Specify mangling format. Currently ignored because only 'gnu' is supported">;
@@ -25,4 +26,5 @@
 def : F<"_", "Alias for --strip-underscore">, Alias<strip_underscore>;
 def : F<"h", "Alias for --help">, Alias<help>;
 def : F<"n", "Alias for --no-strip-underscore">, Alias<no_strip_underscore>;
+def : F<"p", "Alias for --no-params">, Alias<no_params>;
 def : F<"t", "Alias for --types">, Alias<types>;
diff --git a/src/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp b/src/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
index 2bbd57f..d63f507 100644
--- a/src/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -13,7 +13,6 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
@@ -27,9 +26,7 @@
 namespace {
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -41,14 +38,9 @@
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -61,6 +53,7 @@
 };
 } // namespace
 
+static bool ParseParams;
 static bool StripUnderscore;
 static bool Types;
 
@@ -74,23 +67,26 @@
 static std::string demangle(const std::string &Mangled) {
   using llvm::itanium_demangle::starts_with;
   std::string_view DecoratedStr = Mangled;
-  if (StripUnderscore)
-    if (DecoratedStr[0] == '_')
-      DecoratedStr.remove_prefix(1);
+  bool CanHaveLeadingDot = true;
+  if (StripUnderscore && DecoratedStr[0] == '_') {
+    DecoratedStr.remove_prefix(1);
+    CanHaveLeadingDot = false;
+  }
 
   std::string Result;
-  if (nonMicrosoftDemangle(DecoratedStr, Result))
+  if (nonMicrosoftDemangle(DecoratedStr, Result, CanHaveLeadingDot,
+                           ParseParams))
     return Result;
 
   std::string Prefix;
   char *Undecorated = nullptr;
 
   if (Types)
-    Undecorated = itaniumDemangle(DecoratedStr);
+    Undecorated = itaniumDemangle(DecoratedStr, ParseParams);
 
   if (!Undecorated && starts_with(DecoratedStr, "__imp_")) {
     Prefix = "import thunk for ";
-    Undecorated = itaniumDemangle(DecoratedStr.substr(6));
+    Undecorated = itaniumDemangle(DecoratedStr.substr(6), ParseParams);
   }
 
   Result = Undecorated ? Prefix + Undecorated : Mangled;
@@ -149,7 +145,6 @@
 }
 
 int llvm_cxxfilt_main(int argc, char **argv, const llvm::ToolContext &) {
-  InitLLVM X(argc, argv);
   BumpPtrAllocator A;
   StringSaver Saver(A);
   CxxfiltOptTable Tbl;
@@ -178,6 +173,8 @@
   else
     StripUnderscore = Triple(sys::getProcessTriple()).isOSBinFormatMachO();
 
+  ParseParams = !Args.hasArg(OPT_no_params);
+
   Types = Args.hasArg(OPT_types);
 
   std::vector<std::string> Decorated = Args.getAllArgValues(OPT_INPUT);
diff --git a/src/llvm-project/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp b/src/llvm-project/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp
index a9b3452..425ee8d 100644
--- a/src/llvm-project/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp
+++ b/src/llvm-project/llvm/tools/llvm-debuginfod-find/llvm-debuginfod-find.cpp
@@ -123,6 +123,6 @@
           DebuginfodFetcher(DebugFileDirectory).fetch(BuildID))
     return *Path;
   errs() << "Build ID " << llvm::toHex(BuildID, /*Lowercase=*/true)
-         << " could not be found.";
+         << " could not be found.\n";
   exit(1);
 }
diff --git a/src/llvm-project/llvm/tools/llvm-debuginfod/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-debuginfod/CMakeLists.txt
index d32c682..6b0a119 100644
--- a/src/llvm-project/llvm/tools/llvm-debuginfod/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-debuginfod/CMakeLists.txt
@@ -11,8 +11,13 @@
 
   DEPENDS
   DebugInfodOptsTableGen
+  GENERATE_DRIVER
   )
-target_link_libraries(llvm-debuginfod PRIVATE LLVMDebuginfod)
+
+if(NOT LLVM_TOOL_LLVM_DRIVER_BUILD)
+  target_link_libraries(llvm-debuginfod PRIVATE LLVMDebuginfod)
+endif()
+
 if(LLVM_INSTALL_BINUTILS_SYMLINKS)
   add_llvm_tool_symlink(debuginfod llvm-debuginfod)
 endif()
diff --git a/src/llvm-project/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp b/src/llvm-project/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp
index 725b810..9d347db 100644
--- a/src/llvm-project/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp
+++ b/src/llvm-project/llvm/tools/llvm-debuginfod/llvm-debuginfod.cpp
@@ -22,7 +22,7 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/ThreadPool.h"
 
 using namespace llvm;
@@ -31,9 +31,7 @@
 namespace {
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -45,14 +43,9 @@
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -126,8 +119,7 @@
   HostInterface = Args.getLastArgValue(OPT_host_interface, "0.0.0.0");
 }
 
-int main(int argc, char **argv) {
-  InitLLVM X(argc, argv);
+int llvm_debuginfod_main(int argc, char **argv, const llvm::ToolContext &) {
   HTTPClient::initialize();
   parseArgs(argc, argv);
 
diff --git a/src/llvm-project/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp b/src/llvm-project/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp
index 6573bf0..64b5051 100644
--- a/src/llvm-project/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp
+++ b/src/llvm-project/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp
@@ -214,11 +214,9 @@
   };
 
   unsigned getUnprocPredCount(const BasicBlock *Block) const {
-    unsigned Count = 0;
-    for (const_pred_iterator I = pred_begin(Block), E = pred_end(Block); I != E;
-         ++I)
-      if (!Blocks.count(*I)) Count++;
-    return Count;
+    return llvm::count_if(predecessors(Block), [&](const BasicBlock *Pred) {
+      return !Blocks.contains(Pred);
+    });
   }
 
   typedef std::pair<const BasicBlock *, const BasicBlock *> BlockPair;
@@ -791,9 +789,9 @@
 };
 
 struct DiffEntry {
-  DiffEntry() : Cost(0) {}
+  DiffEntry() = default;
 
-  unsigned Cost;
+  unsigned Cost = 0;
   llvm::SmallVector<char, 8> Path; // actually of DifferenceEngine::DiffChange
 };
 
diff --git a/src/llvm-project/llvm/tools/llvm-diff/llvm-diff.cpp b/src/llvm-project/llvm/tools/llvm-diff/llvm-diff.cpp
index 7349469..3e77b1e 100644
--- a/src/llvm-project/llvm/tools/llvm-diff/llvm-diff.cpp
+++ b/src/llvm-project/llvm/tools/llvm-diff/llvm-diff.cpp
@@ -42,7 +42,7 @@
 static void diffGlobal(DifferenceEngine &Engine, Module &L, Module &R,
                        StringRef Name) {
   // Drop leading sigils from the global name.
-  if (Name.startswith("@")) Name = Name.substr(1);
+  Name.consume_front("@");
 
   Function *LFn = L.getFunction(Name);
   Function *RFn = R.getFunction(Name);
diff --git a/src/llvm-project/llvm/tools/llvm-dis/llvm-dis.cpp b/src/llvm-project/llvm/tools/llvm-dis/llvm-dis.cpp
index 4996fc1..06fc669 100644
--- a/src/llvm-project/llvm/tools/llvm-dis/llvm-dis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dis/llvm-dis.cpp
@@ -225,7 +225,7 @@
           FinalFilename = "-";
         } else {
           StringRef IFN = InputFilename;
-          FinalFilename = (IFN.endswith(".bc") ? IFN.drop_back(3) : IFN).str();
+          FinalFilename = (IFN.ends_with(".bc") ? IFN.drop_back(3) : IFN).str();
           if (N > 1)
             FinalFilename += std::string(".") + std::to_string(I);
           FinalFilename += ".ll";
diff --git a/src/llvm-project/llvm/tools/llvm-driver/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-driver/CMakeLists.txt
index 23cc373..83e0840 100644
--- a/src/llvm-project/llvm/tools/llvm-driver/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-driver/CMakeLists.txt
@@ -25,6 +25,7 @@
 set_target_properties(llvm-driver PROPERTIES OUTPUT_NAME llvm)
 
 target_link_libraries(llvm-driver PUBLIC ${LLVM_DRIVER_OBJLIBS})
+target_link_libraries(llvm-driver PUBLIC LLVMDebuginfod)
 
 if(APPLE)
   # dsymutil uses some CoreFoundation stuff on Darwin...
diff --git a/src/llvm-project/llvm/tools/llvm-driver/llvm-driver.cpp b/src/llvm-project/llvm/tools/llvm-driver/llvm-driver.cpp
index a0f1ca8..53a8b935 100644
--- a/src/llvm-project/llvm/tools/llvm-driver/llvm-driver.cpp
+++ b/src/llvm-project/llvm/tools/llvm-driver/llvm-driver.cpp
@@ -10,6 +10,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/WithColor.h"
@@ -79,4 +80,7 @@
   return 1;
 }
 
-int main(int Argc, char **Argv) { return findTool(Argc, Argv, Argv[0]); }
+int main(int Argc, char **Argv) {
+  llvm::InitLLVM X(Argc, Argv);
+  return findTool(Argc, Argv, Argv[0]);
+}
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp b/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
index a967abf..96841c3 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -319,7 +319,7 @@
         auto Offset = Die.find(dwarf::DW_AT_abstract_origin);
         // Do not track this variable any more, since it has location
         // coverage.
-        llvm::erase_value(*AbstractOriginVariables, (*Offset).getRawUValue());
+        llvm::erase(*AbstractOriginVariables, (*Offset).getRawUValue());
       }
     } else {
       // The locstats will be handled at the end of
@@ -743,7 +743,7 @@
          Child.find(dwarf::DW_AT_const_value))) {
       auto OffsetVar = Child.find(dwarf::DW_AT_abstract_origin);
       if (OffsetVar)
-        llvm::erase_value(AbstractOriginVars, (*OffsetVar).getRawUValue());
+        llvm::erase(AbstractOriginVars, (*OffsetVar).getRawUValue());
     } else if (ChildTag == dwarf::DW_TAG_lexical_block)
       updateVarsWithAbstractOriginLocCovInfo(Child, AbstractOriginVars);
     Child = Child.getSibling();
@@ -792,7 +792,7 @@
     ProcessedFns.push_back(FnOffset);
   }
   for (auto ProcessedFn : ProcessedFns)
-    llvm::erase_value(FnsWithAbstractOriginToBeProcessed, ProcessedFn);
+    llvm::erase(FnsWithAbstractOriginToBeProcessed, ProcessedFn);
 }
 
 /// Collect zero location coverage for inlined variables which refer to
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfdump/fuzzer/llvm-dwarfdump-fuzzer.cpp b/src/llvm-project/llvm/tools/llvm-dwarfdump/fuzzer/llvm-dwarfdump-fuzzer.cpp
index 1d74856..0e74d0b 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfdump/fuzzer/llvm-dwarfdump-fuzzer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfdump/fuzzer/llvm-dwarfdump-fuzzer.cpp
@@ -20,8 +20,8 @@
 using namespace object;
 
 extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) {
-  std::unique_ptr<MemoryBuffer> Buff = MemoryBuffer::getMemBuffer(
-      StringRef((const char *)data, size), "", false);
+  std::string Payload(reinterpret_cast<const char *>(data), size);
+  std::unique_ptr<MemoryBuffer> Buff = MemoryBuffer::getMemBuffer(Payload);
 
   Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
       ObjectFile::createObjectFile(Buff->getMemBufferRef());
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp b/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
index 156e10c..941df4e 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -181,6 +181,13 @@
 static opt<bool> IgnoreCase("ignore-case",
                             desc("Ignore case distinctions when using --name."),
                             value_desc("i"), cat(DwarfDumpCategory));
+static opt<bool> DumpNonSkeleton(
+    "dwo",
+    desc("Dump the non skeleton DIE in the .dwo or .dwp file after dumping the "
+         "skeleton DIE from the main executable. This allows dumping the .dwo "
+         "files with resolved addresses."),
+    value_desc("d"), cat(DwarfDumpCategory));
+
 static alias IgnoreCaseAlias("i", desc("Alias for --ignore-case."),
                              aliasopt(IgnoreCase), cl::NotHidden);
 static list<std::string> Name(
@@ -315,6 +322,7 @@
   DumpOpts.ShowForm = ShowForm;
   DumpOpts.SummarizeTypes = SummarizeTypes;
   DumpOpts.Verbose = Verbose;
+  DumpOpts.DumpNonSkeleton = DumpNonSkeleton;
   DumpOpts.RecoverableErrorHandler = C.getRecoverableErrorHandler();
   // In -verify mode, print DIEs without children in error messages.
   if (Verify) {
@@ -337,10 +345,10 @@
     return true;
 
   if (auto *MachO = dyn_cast<MachOObjectFile>(&Obj)) {
-    for (auto Arch : ArchFilters) {
+    for (const StringRef Arch : ArchFilters) {
       // Match architecture number.
       unsigned Value;
-      if (!StringRef(Arch).getAsInteger(0, Value))
+      if (!Arch.getAsInteger(0, Value))
         if (Value == getCPUType(*MachO))
           return true;
 
@@ -390,15 +398,27 @@
     const StringSet<> &Names, DWARFContext::unit_iterator_range CUs,
     raw_ostream &OS,
     std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
-  for (const auto &CU : CUs)
-    for (const auto &Entry : CU->dies()) {
-      DWARFDie Die = {CU.get(), &Entry};
+  auto filterDieNames = [&](DWARFUnit *Unit) {
+    for (const auto &Entry : Unit->dies()) {
+      DWARFDie Die = {Unit, &Entry};
       if (const char *Name = Die.getName(DINameKind::ShortName))
         if (filterByName(Names, Die, Name, OS, GetNameForDWARFReg))
           continue;
       if (const char *Name = Die.getName(DINameKind::LinkageName))
         filterByName(Names, Die, Name, OS, GetNameForDWARFReg);
     }
+  };
+  for (const auto &CU : CUs) {
+    filterDieNames(CU.get());
+    if (DumpNonSkeleton) {
+      // If we have split DWARF, then recurse down into the .dwo files as well.
+      DWARFDie CUDie = CU->getUnitDIE(false);
+      DWARFDie CUNonSkeletonDie = CU->getNonSkeletonUnitDIE(false);
+      // If we have a DWO file, we need to search it as well
+      if (CUNonSkeletonDie && CUDie != CUNonSkeletonDie)
+        filterDieNames(CUNonSkeletonDie.getDwarfUnit());
+    }
+  }
 }
 
 static void getDies(DWARFContext &DICtx, const AppleAcceleratorTable &Accel,
@@ -499,7 +519,7 @@
 /// information or probably display all matched entries, or something else...
 static bool lookup(ObjectFile &Obj, DWARFContext &DICtx, uint64_t Address,
                    raw_ostream &OS) {
-  auto DIEsForAddr = DICtx.getDIEsForAddress(Lookup);
+  auto DIEsForAddr = DICtx.getDIEsForAddress(Lookup, DumpNonSkeleton);
 
   if (!DIEsForAddr)
     return false;
@@ -649,7 +669,7 @@
   // Handle the --name option.
   if (!Name.empty()) {
     StringSet<> Names;
-    for (auto name : Name)
+    for (const auto &name : Name)
       Names.insert((IgnoreCase && !UseRegex) ? StringRef(name).lower() : name);
 
     filterByName(Names, DICtx.normal_units(), OS, GetRegName);
@@ -698,7 +718,7 @@
                           HandlerFn HandleObj, raw_ostream &OS) {
   bool Result = true;
   Error Err = Error::success();
-  for (auto Child : Arch.children(Err)) {
+  for (const auto &Child : Arch.children(Err)) {
     auto BuffOrErr = Child.getMemoryBufferRef();
     error(Filename, BuffOrErr.takeError());
     auto NameOrErr = Child.getName();
@@ -848,19 +868,19 @@
 
   bool Success = true;
   if (Verify) {
-    for (auto Object : Objects)
+    for (StringRef Object : Objects)
       Success &= handleFile(Object, verifyObjectFile, OutputFile.os());
   } else if (Statistics) {
-    for (auto Object : Objects)
+    for (StringRef Object : Objects)
       Success &= handleFile(Object, collectStatsForObjectFile, OutputFile.os());
   } else if (ShowSectionSizes) {
-    for (auto Object : Objects)
+    for (StringRef Object : Objects)
       Success &= handleFile(Object, collectObjectSectionSizes, OutputFile.os());
   } else if (ShowSources) {
-    for (auto Object : Objects)
+    for (StringRef Object : Objects)
       Success &= handleFile(Object, collectObjectSources, OutputFile.os());
   } else {
-    for (auto Object : Objects)
+    for (StringRef Object : Objects)
       Success &= handleFile(Object, dumpObjectFile, OutputFile.os());
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfutil/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-dwarfutil/CMakeLists.txt
index b258579..23a5267 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/CMakeLists.txt
@@ -8,6 +8,7 @@
   AllTargetsInfos
   CodeGenTypes
   DWARFLinker
+  DWARFLinkerClassic
   DWARFLinkerParallel
   DebugInfoDWARF
   MC
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
index 47a23e8..bd17f3c 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
@@ -9,17 +9,18 @@
 #include "DebugInfoLinker.h"
 #include "Error.h"
 #include "llvm/ADT/StringSwitch.h"
-#include "llvm/DWARFLinker/DWARFLinker.h"
-#include "llvm/DWARFLinker/DWARFStreamer.h"
-#include "llvm/DWARFLinkerParallel/DWARFLinker.h"
+#include "llvm/DWARFLinker/Classic/DWARFLinker.h"
+#include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
+#include "llvm/DWARFLinker/Parallel/DWARFLinker.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
 #include "llvm/Object/ObjectFile.h"
-#include "llvm/Support/Endian.h"
 #include <memory>
 #include <vector>
 
 namespace llvm {
+using namespace dwarf_linker;
+
 namespace dwarfutil {
 
 // ObjFileAddressMap allows to check whether specified DIE referencing
@@ -38,8 +39,7 @@
 // exec: [LowPC, HighPC] is not inside address ranges of .text sections
 //
 // universal: maxpc and bfd
-template <typename AddressMapBase>
-class ObjFileAddressMap : public AddressMapBase {
+class ObjFileAddressMap : public AddressesMap {
 public:
   ObjFileAddressMap(DWARFContext &Context, const Options &Options,
                     object::ObjectFile &ObjFile)
@@ -80,8 +80,8 @@
   // should be renamed into has valid address ranges
   bool hasValidRelocs() override { return HasValidAddressRanges; }
 
-  std::optional<int64_t>
-  getSubprogramRelocAdjustment(const DWARFDie &DIE) override {
+  std::optional<int64_t> getSubprogramRelocAdjustment(const DWARFDie &DIE,
+                                                      bool Verbose) override {
     assert((DIE.getTag() == dwarf::DW_TAG_subprogram ||
             DIE.getTag() == dwarf::DW_TAG_label) &&
            "Wrong type of input die");
@@ -98,15 +98,18 @@
     return std::nullopt;
   }
 
-  std::optional<int64_t> getExprOpAddressRelocAdjustment(
-      DWARFUnit &U, const DWARFExpression::Operation &Op, uint64_t StartOffset,
-      uint64_t EndOffset) override {
+  std::optional<int64_t>
+  getExprOpAddressRelocAdjustment(DWARFUnit &U,
+                                  const DWARFExpression::Operation &Op,
+                                  uint64_t, uint64_t, bool Verbose) override {
     switch (Op.getCode()) {
     default: {
       assert(false && "Specified operation does not have address operand");
     } break;
+    case dwarf::DW_OP_const2u:
     case dwarf::DW_OP_const4u:
     case dwarf::DW_OP_const8u:
+    case dwarf::DW_OP_const2s:
     case dwarf::DW_OP_const4s:
     case dwarf::DW_OP_const8s:
     case dwarf::DW_OP_addr: {
@@ -130,11 +133,23 @@
     return std::nullopt;
   }
 
+  std::optional<StringRef> getLibraryInstallName() override {
+    return std::nullopt;
+  }
+
   bool applyValidRelocs(MutableArrayRef<char>, uint64_t, bool) override {
     // no need to apply relocations to the linked binary.
     return false;
   }
 
+  bool needToSaveValidRelocs() override { return false; }
+
+  void updateAndSaveValidRelocs(bool, uint64_t, int64_t, uint64_t,
+                                uint64_t) override {}
+
+  void updateRelocationsWithUnitOffset(uint64_t OriginalUnitOffset,
+                                       uint64_t OutputUnitOffset) override {}
+
   void clear() override {}
 
 protected:
@@ -284,26 +299,36 @@
   return Message;
 }
 
-template <typename Linker, typename OutDwarfFile, typename AddressMapBase>
+template <typename Linker>
 Error linkDebugInfoImpl(object::ObjectFile &File, const Options &Options,
                         raw_pwrite_stream &OutStream) {
+  std::mutex ErrorHandlerMutex;
+
   auto ReportWarn = [&](const Twine &Message, StringRef Context,
                         const DWARFDie *Die) {
-    warning(Message, Context);
-
-    if (!Options.Verbose || !Die)
+    // FIXME: implement warning logging which does not block other threads.
+    if (!ErrorHandlerMutex.try_lock())
       return;
 
-    DIDumpOptions DumpOpts;
-    DumpOpts.ChildRecurseDepth = 0;
-    DumpOpts.Verbose = Options.Verbose;
+    warning(Message, Context);
+    if (Options.Verbose && Die) {
+      DIDumpOptions DumpOpts;
+      DumpOpts.ChildRecurseDepth = 0;
+      DumpOpts.Verbose = Options.Verbose;
 
-    WithColor::note() << "    in DIE:\n";
-    Die->dump(errs(), /*Indent=*/6, DumpOpts);
+      WithColor::note() << "    in DIE:\n";
+      Die->dump(errs(), /*Indent=*/6, DumpOpts);
+    }
+    ErrorHandlerMutex.unlock();
   };
   auto ReportErr = [&](const Twine &Message, StringRef Context,
                        const DWARFDie *) {
+    // FIXME: implement error logging which does not block other threads.
+    if (!ErrorHandlerMutex.try_lock())
+      return;
+
     WithColor::error(errs(), Context) << Message << '\n';
+    ErrorHandlerMutex.unlock();
   };
 
   // Create DWARF linker.
@@ -311,9 +336,26 @@
       Linker::createLinker(ReportErr, ReportWarn);
 
   Triple TargetTriple = File.makeTriple();
-  if (Error Err = DebugInfoLinker->createEmitter(
-          TargetTriple, Linker::OutputFileType::Object, OutStream))
-    return Err;
+  std::unique_ptr<classic::DwarfStreamer> Streamer;
+  if (Expected<std::unique_ptr<classic::DwarfStreamer>> StreamerOrErr =
+          classic::DwarfStreamer::createStreamer(
+              TargetTriple, Linker::OutputFileType::Object, OutStream, nullptr,
+              ReportWarn))
+    Streamer = std::move(*StreamerOrErr);
+  else
+    return StreamerOrErr.takeError();
+
+  if constexpr (std::is_same<Linker,
+                             dwarf_linker::parallel::DWARFLinker>::value) {
+    DebugInfoLinker->setOutputDWARFHandler(
+        TargetTriple,
+        [&](std::shared_ptr<dwarf_linker::parallel::SectionDescriptorBase>
+                Section) {
+          Streamer->emitSectionContents(Section->getContents(),
+                                        Section->getKind());
+        });
+  } else
+    DebugInfoLinker->setOutputDWARFEmitter(Streamer.get());
 
   DebugInfoLinker->setEstimatedObjfilesAmount(1);
   DebugInfoLinker->setNumThreads(Options.NumThreads);
@@ -321,18 +363,26 @@
   DebugInfoLinker->setVerbosity(Options.Verbose);
   DebugInfoLinker->setUpdateIndexTablesOnly(!Options.DoGarbageCollection);
 
-  std::vector<std::unique_ptr<OutDwarfFile>> ObjectsForLinking(1);
-  std::vector<std::string> EmptyWarnings;
+  std::vector<std::unique_ptr<DWARFFile>> ObjectsForLinking(1);
 
   // Add object files to the DWARFLinker.
-  std::unique_ptr<DWARFContext> Context = DWARFContext::create(File);
-  std::unique_ptr<ObjFileAddressMap<AddressMapBase>> AddressesMap(
-      std::make_unique<ObjFileAddressMap<AddressMapBase>>(*Context, Options,
-                                                          File));
+  std::unique_ptr<DWARFContext> Context = DWARFContext::create(
+      File, DWARFContext::ProcessDebugRelocations::Process, nullptr, "",
+      [&](Error Err) {
+        handleAllErrors(std::move(Err), [&](ErrorInfoBase &Info) {
+          ReportErr(Info.message(), "", nullptr);
+        });
+      },
+      [&](Error Warning) {
+        handleAllErrors(std::move(Warning), [&](ErrorInfoBase &Info) {
+          ReportWarn(Info.message(), "", nullptr);
+        });
+      });
+  std::unique_ptr<ObjFileAddressMap> AddressesMap(
+      std::make_unique<ObjFileAddressMap>(*Context, Options, File));
 
-  ObjectsForLinking[0] =
-      std::make_unique<OutDwarfFile>(File.getFileName(), std::move(Context),
-                                     std::move(AddressesMap), EmptyWarnings);
+  ObjectsForLinking[0] = std::make_unique<DWARFFile>(
+      File.getFileName(), std::move(Context), std::move(AddressesMap));
 
   uint16_t MaxDWARFVersion = 0;
   std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =
@@ -367,7 +417,7 @@
   for (typename Linker::AccelTableKind Table : AccelTables)
     DebugInfoLinker->addAccelTableKind(Table);
 
-  for (std::unique_ptr<OutDwarfFile> &CurFile : ObjectsForLinking) {
+  for (std::unique_ptr<DWARFFile> &CurFile : ObjectsForLinking) {
     SmallVector<StringRef> AccelTableNamesToReplace;
     SmallVector<StringRef> AccelTableNamesToDelete;
 
@@ -412,20 +462,16 @@
   if (Error Err = DebugInfoLinker->link())
     return Err;
 
-  DebugInfoLinker->getEmitter()->finish();
+  Streamer->finish();
   return Error::success();
 }
 
 Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
                     raw_pwrite_stream &OutStream) {
-  if (Options.UseLLVMDWARFLinker)
-    return linkDebugInfoImpl<dwarflinker_parallel::DWARFLinker,
-                             dwarflinker_parallel::DWARFFile,
-                             dwarflinker_parallel::AddressesMap>(File, Options,
-                                                                 OutStream);
+  if (Options.UseDWARFLinkerParallel)
+    return linkDebugInfoImpl<parallel::DWARFLinker>(File, Options, OutStream);
   else
-    return linkDebugInfoImpl<DWARFLinker, DWARFFile, AddressesMap>(
-        File, Options, OutStream);
+    return linkDebugInfoImpl<classic::DWARFLinker>(File, Options, OutStream);
 }
 
 } // end of namespace dwarfutil
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.h b/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.h
index d9d99ff..77cb8bb 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.h
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.h
@@ -18,7 +18,7 @@
 namespace dwarfutil {
 
 inline bool isDebugSection(StringRef SecName) {
-  return SecName.startswith(".debug") || SecName.startswith(".zdebug") ||
+  return SecName.starts_with(".debug") || SecName.starts_with(".zdebug") ||
          SecName == ".gdb_index";
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfutil/Error.h b/src/llvm-project/llvm/tools/llvm-dwarfutil/Error.h
index b92c50c..fff5978 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/Error.h
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/Error.h
@@ -11,7 +11,6 @@
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/Format.h"
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.h b/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.h
index e97833b..e3cfa42 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.h
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.h
@@ -9,8 +9,8 @@
 #ifndef LLVM_TOOLS_LLVM_DWARFUTIL_OPTIONS_H
 #define LLVM_TOOLS_LLVM_DWARFUTIL_OPTIONS_H
 
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
+#include <cstdint>
+#include <string>
 
 namespace llvm {
 namespace dwarfutil {
@@ -40,7 +40,7 @@
   bool Verbose = false;
   int NumThreads = 0;
   bool Verify = false;
-  bool UseLLVMDWARFLinker = false;
+  bool UseDWARFLinkerParallel = false;
   DwarfUtilAccelKind AccelTableKind = DwarfUtilAccelKind::None;
 
   std::string getSeparateDebugFileName() const {
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.td b/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.td
index 26b9ac6..85606bd 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.td
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.td
@@ -22,7 +22,7 @@
 
 def linker: Separate<["--", "-"], "linker">,
   MetaVarName<"<DWARF linker type>">,
-  HelpText<"Specify the desired type of DWARF linker. Defaults to 'apple'">;
+  HelpText<"Specify the desired type of DWARF linker. Defaults to 'classic'">;
 def: Joined<["--", "-"], "linker=">, Alias<linker>;
 
 defm odr_deduplication : BB<"odr-deduplication",
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp b/src/llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
index 1c76271..7b777b1 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
@@ -33,9 +33,7 @@
 namespace {
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Options.inc"
 #undef OPTION
 };
@@ -47,14 +45,9 @@
 #include "Options.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Options.inc"
 #undef OPTION
 };
@@ -125,10 +118,10 @@
 
   if (opt::Arg *LinkerKind = Args.getLastArg(OPT_linker)) {
     StringRef S = LinkerKind->getValue();
-    if (S == "apple")
-      Options.UseLLVMDWARFLinker = false;
-    else if (S == "llvm")
-      Options.UseLLVMDWARFLinker = true;
+    if (S == "classic")
+      Options.UseDWARFLinkerParallel = false;
+    else if (S == "parallel")
+      Options.UseDWARFLinkerParallel = true;
     else
       return createStringError(
           std::errc::invalid_argument,
diff --git a/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt
index e27c0c3..d38385c 100644
--- a/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt
@@ -21,6 +21,7 @@
   DEPENDS
   intrinsics_gen
   DwpOptsTableGen
+  GENERATE_DRIVER
   )
 
 if(LLVM_INSTALL_BINUTILS_SYMLINKS)
diff --git a/src/llvm-project/llvm/tools/llvm-dwp/Opts.td b/src/llvm-project/llvm/tools/llvm-dwp/Opts.td
index c01fa4a..46593bc 100644
--- a/src/llvm-project/llvm/tools/llvm-dwp/Opts.td
+++ b/src/llvm-project/llvm/tools/llvm-dwp/Opts.td
@@ -9,5 +9,10 @@
 
 def execFileNames : S<"e", "Specify the executable/library files to get the list of *.dwo from.">, MetaVarName<"<filename>">;
 def outputFileName : S<"o", "Specify the output file.">, MetaVarName<"<filename>">;
-def continueOnCuIndexOverflow: F<"continue-on-cu-index-overflow", "This turns an error when offset for .debug_*.dwo sections "
-                                         "overfolws into a warning.">, MetaVarName<"<filename>">;
+def continueOnCuIndexOverflow : Flag<["-", "--"], "continue-on-cu-index-overflow">;
+def continueOnCuIndexOverflow_EQ : Joined<["-", "--"], "continue-on-cu-index-overflow=">,
+  HelpText<"default = continue, This turns an error when offset \n"
+    "\t\tfor .debug_*.dwo sections overfolws into a warning. = soft-stop, This produces a \n"
+    "\t\ttruncated but valid DWP file, discarding any DWO files that would not fit within \n"
+    "\t\tthe 32 bit/4GB limits of the format.">,
+  Values<"continue,soft-stop">;
diff --git a/src/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp b/src/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
index 350a373..81556b3 100644
--- a/src/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
@@ -27,7 +27,7 @@
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
-#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/ToolOutputFile.h"
@@ -42,9 +42,7 @@
 namespace {
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -56,14 +54,9 @@
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -77,7 +70,7 @@
 // Options
 static std::vector<std::string> ExecFilenames;
 static std::string OutputFilename;
-static bool ContinueOnCuIndexOverflow;
+static std::string ContinueOption;
 
 static Expected<SmallVector<std::string, 16>>
 getDWOFilenames(StringRef ExecFilename) {
@@ -125,12 +118,11 @@
   return ErrOrObj->getBinary()->makeTriple();
 }
 
-int main(int argc, char **argv) {
-  InitLLVM X(argc, argv);
-
+int llvm_dwp_main(int argc, char **argv, const llvm::ToolContext &) {
   DwpOptTable Tbl;
   llvm::BumpPtrAllocator A;
   llvm::StringSaver Saver{A};
+  OnCuIndexOverflow OverflowOptValue = OnCuIndexOverflow::HardStop;
   opt::InputArgList Args =
       Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
         llvm::errs() << Msg << '\n';
@@ -149,7 +141,23 @@
   }
 
   OutputFilename = Args.getLastArgValue(OPT_outputFileName, "");
-  ContinueOnCuIndexOverflow = Args.hasArg(OPT_continueOnCuIndexOverflow);
+  if (Arg *Arg = Args.getLastArg(OPT_continueOnCuIndexOverflow,
+                                 OPT_continueOnCuIndexOverflow_EQ)) {
+    if (Arg->getOption().matches(OPT_continueOnCuIndexOverflow)) {
+      OverflowOptValue = OnCuIndexOverflow::Continue;
+    } else {
+      ContinueOption = Arg->getValue();
+      if (ContinueOption == "soft-stop") {
+        OverflowOptValue = OnCuIndexOverflow::SoftStop;
+      } else if (ContinueOption == "continue") {
+        OverflowOptValue = OnCuIndexOverflow::Continue;
+      } else {
+        llvm::errs() << "invalid value for --continue-on-cu-index-overflow"
+                     << ContinueOption << '\n';
+        exit(1);
+      }
+    }
+  }
 
   for (const llvm::opt::Arg *A : Args.filtered(OPT_execFileNames))
     ExecFilenames.emplace_back(A->getValue());
@@ -261,7 +269,7 @@
   if (!MS)
     return error("no object streamer for target " + TripleName, Context);
 
-  if (auto Err = write(*MS, DWOFilenames, ContinueOnCuIndexOverflow)) {
+  if (auto Err = write(*MS, DWOFilenames, OverflowOptValue)) {
     logAllUnhandledErrors(std::move(Err), WithColor::error());
     return 1;
   }
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
index c778b89..5184686 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/Target.cpp
@@ -9,6 +9,9 @@
 #include "AArch64.h"
 #include "AArch64RegisterInfo.h"
 
+#define GET_AVAILABLE_OPCODE_CHECKER
+#include "AArch64GenInstrInfo.inc"
+
 namespace llvm {
 namespace exegesis {
 
@@ -38,7 +41,8 @@
 
 class ExegesisAArch64Target : public ExegesisTarget {
 public:
-  ExegesisAArch64Target() : ExegesisTarget(AArch64CpuPfmCounters) {}
+  ExegesisAArch64Target()
+      : ExegesisTarget(AArch64CpuPfmCounters, AArch64_MC::isOpcodeAvailable) {}
 
 private:
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.cpp
index 7c44373..2b924b9 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.cpp
@@ -13,7 +13,6 @@
 #include "llvm/MC/MCTargetOptions.h"
 #include "llvm/Support/FormatVariadic.h"
 #include <limits>
-#include <unordered_set>
 #include <vector>
 
 namespace llvm {
@@ -390,7 +389,7 @@
       OS << "<li><span class=\"mono\">";
       writeEscaped<kEscapeHtml>(OS,
                                 SM.getProcResource(WPR.ProcResourceIdx)->Name);
-      OS << "</span>: " << WPR.Cycles << "</li>";
+      OS << "</span>: " << WPR.ReleaseAtCycle << "</li>";
     }
     OS << "</ul></td>";
     // Idealized port pressure.
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.h
index 9970cfe..4a85d45 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.h
@@ -23,9 +23,6 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/raw_ostream.h"
 #include <memory>
-#include <set>
-#include <string>
-#include <unordered_map>
 
 namespace llvm {
 namespace exegesis {
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Assembler.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Assembler.cpp
index 97b461e..9f03a4e 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Assembler.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Assembler.cpp
@@ -19,13 +19,15 @@
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/CodeGen/TargetPassConfig.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
-#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/MC/MCInstrInfo.h"
+#include "llvm/Object/SymbolSize.h"
 #include "llvm/Support/Alignment.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
@@ -34,6 +36,10 @@
 #include "perfmon/perf_event.h"
 #endif // HAVE_LIBPFM
 
+#ifdef __linux__
+#include <unistd.h>
+#endif
+
 namespace llvm {
 namespace exegesis {
 
@@ -43,14 +49,22 @@
 
 // Fills the given basic block with register setup code, and returns true if
 // all registers could be setup correctly.
-static bool generateSnippetSetupCode(
-    const ExegesisTarget &ET, const MCSubtargetInfo *const MSI,
-    ArrayRef<RegisterValue> RegisterInitialValues, BasicBlockFiller &BBF,
-    const BenchmarkKey &Key, bool GenerateMemoryInstructions) {
+static bool generateSnippetSetupCode(const ExegesisTarget &ET,
+                                     const MCSubtargetInfo *const MSI,
+                                     BasicBlockFiller &BBF,
+                                     const BenchmarkKey &Key,
+                                     bool GenerateMemoryInstructions) {
   bool IsSnippetSetupComplete = true;
   if (GenerateMemoryInstructions) {
     BBF.addInstructions(ET.generateMemoryInitialSetup());
     for (const MemoryMapping &MM : Key.MemoryMappings) {
+#ifdef __linux__
+      // The frontend that generates that parses the memory mapping information
+      // from the user should validate that the requested address is a multiple
+      // of the page size. Assert that this is true here.
+      assert(MM.Address % getpagesize() == 0 &&
+             "Memory mappings need to be aligned to page boundaries.");
+#endif
       BBF.addInstructions(ET.generateMmap(
           MM.Address, Key.MemoryValues.at(MM.MemoryValueName).SizeBytes,
           ET.getAuxiliaryMemoryStartAddress() +
@@ -59,7 +73,17 @@
     }
     BBF.addInstructions(ET.setStackRegisterToAuxMem());
   }
-  for (const RegisterValue &RV : RegisterInitialValues) {
+  Register StackPointerRegister = BBF.MF.getSubtarget()
+                                      .getTargetLowering()
+                                      ->getStackPointerRegisterToSaveRestore();
+  for (const RegisterValue &RV : Key.RegisterInitialValues) {
+    if (GenerateMemoryInstructions) {
+      // If we're generating memory instructions, don't load in the value for
+      // the register with the stack pointer as it will be used later to finish
+      // the setup.
+      if (RV.Register == StackPointerRegister)
+        continue;
+    }
     // Load a constant in the register.
     const auto SetRegisterCode = ET.setRegTo(*MSI, RV.Register, RV.Value);
     if (SetRegisterCode.empty())
@@ -70,6 +94,18 @@
 #ifdef HAVE_LIBPFM
     BBF.addInstructions(ET.configurePerfCounter(PERF_EVENT_IOC_RESET, true));
 #endif // HAVE_LIBPFM
+    for (const RegisterValue &RV : Key.RegisterInitialValues) {
+      // Load in the stack register now as we're done using it elsewhere
+      // and need to set the value in preparation for executing the
+      // snippet.
+      if (RV.Register != StackPointerRegister)
+        continue;
+      const auto SetRegisterCode = ET.setRegTo(*MSI, RV.Register, RV.Value);
+      if (SetRegisterCode.empty())
+        IsSnippetSetupComplete = false;
+      BBF.addInstructions(SetRegisterCode);
+      break;
+    }
   }
   return IsSnippetSetupComplete;
 }
@@ -105,7 +141,7 @@
   FunctionType *FunctionType =
       FunctionType::get(ReturnType, {MemParamType}, false);
   Function *const F = Function::Create(
-      FunctionType, GlobalValue::InternalLinkage, FunctionName, Module);
+      FunctionType, GlobalValue::ExternalLinkage, FunctionName, Module);
   BasicBlock *BB = BasicBlock::Create(Module->getContext(), "", F);
   new UnreachableInst(Module->getContext(), BB);
   return MMI->getOrCreateMachineFunction(*F);
@@ -207,10 +243,8 @@
 
 Error assembleToStream(const ExegesisTarget &ET,
                        std::unique_ptr<LLVMTargetMachine> TM,
-                       ArrayRef<unsigned> LiveIns,
-                       ArrayRef<RegisterValue> RegisterInitialValues,
-                       const FillFunction &Fill, raw_pwrite_stream &AsmStream,
-                       const BenchmarkKey &Key,
+                       ArrayRef<unsigned> LiveIns, const FillFunction &Fill,
+                       raw_pwrite_stream &AsmStream, const BenchmarkKey &Key,
                        bool GenerateMemoryInstructions) {
   auto Context = std::make_unique<LLVMContext>();
   std::unique_ptr<Module> Module =
@@ -240,7 +274,7 @@
   }
 
   std::vector<unsigned> RegistersSetUp;
-  for (const auto &InitValue : RegisterInitialValues) {
+  for (const auto &InitValue : Key.RegisterInitialValues) {
     RegistersSetUp.push_back(InitValue.Register);
   }
   FunctionFiller Sink(MF, std::move(RegistersSetUp));
@@ -259,8 +293,7 @@
   }
 
   const bool IsSnippetSetupComplete = generateSnippetSetupCode(
-      ET, TM->getMCSubtargetInfo(), RegisterInitialValues, Entry, Key,
-      GenerateMemoryInstructions);
+      ET, TM->getMCSubtargetInfo(), Entry, Key, GenerateMemoryInstructions);
 
   // If the snippet setup is not complete, we disable liveliness tracking. This
   // means that we won't know what values are in the registers.
@@ -299,7 +332,8 @@
   TPC->setInitialized();
 
   // AsmPrinter is responsible for generating the assembly into AsmBuffer.
-  if (TM->addAsmPrinter(PM, AsmStream, nullptr, CGFT_ObjectFile, MCContext))
+  if (TM->addAsmPrinter(PM, AsmStream, nullptr, CodeGenFileType::ObjectFile,
+                        MCContext))
     return make_error<Failure>("Cannot add AsmPrinter passes");
 
   PM.run(*Module); // Run all the passes
@@ -323,61 +357,49 @@
   return cantFail(object::ObjectFile::createObjectFile(Filename));
 }
 
-namespace {
-
-// Implementation of this class relies on the fact that a single object with a
-// single function will be loaded into memory.
-class TrackingSectionMemoryManager : public SectionMemoryManager {
-public:
-  explicit TrackingSectionMemoryManager(uintptr_t *CodeSize)
-      : CodeSize(CodeSize) {}
-
-  uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
-                               unsigned SectionID,
-                               StringRef SectionName) override {
-    *CodeSize = Size;
-    return SectionMemoryManager::allocateCodeSection(Size, Alignment, SectionID,
-                                                     SectionName);
-  }
-
-private:
-  uintptr_t *const CodeSize = nullptr;
-};
-
-} // namespace
-
-ExecutableFunction::ExecutableFunction(
+Expected<ExecutableFunction> ExecutableFunction::create(
     std::unique_ptr<LLVMTargetMachine> TM,
-    object::OwningBinary<object::ObjectFile> &&ObjectFileHolder)
-    : Context(std::make_unique<LLVMContext>()) {
+    object::OwningBinary<object::ObjectFile> &&ObjectFileHolder) {
   assert(ObjectFileHolder.getBinary() && "cannot create object file");
-  // Initializing the execution engine.
-  // We need to use the JIT EngineKind to be able to add an object file.
-  LLVMLinkInMCJIT();
-  uintptr_t CodeSize = 0;
-  std::string Error;
-  ExecEngine.reset(
-      EngineBuilder(createModule(Context, TM->createDataLayout()))
-          .setErrorStr(&Error)
-          .setMCPU(TM->getTargetCPU())
-          .setEngineKind(EngineKind::JIT)
-          .setMCJITMemoryManager(
-              std::make_unique<TrackingSectionMemoryManager>(&CodeSize))
-          .create(TM.release()));
-  if (!ExecEngine)
-    report_fatal_error(Twine(Error));
-  // Adding the generated object file containing the assembled function.
-  // The ExecutionEngine makes sure the object file is copied into an
-  // executable page.
-  ExecEngine->addObjectFile(std::move(ObjectFileHolder));
-  // Fetching function bytes.
-  const uint64_t FunctionAddress = ExecEngine->getFunctionAddress(FunctionID);
+  std::unique_ptr<LLVMContext> Ctx = std::make_unique<LLVMContext>();
+
+  auto SymbolSizes = object::computeSymbolSizes(*ObjectFileHolder.getBinary());
+  // Get the size of the function that we want to call into (with the name of
+  // FunctionID). This should always be the third symbol returned by
+  // calculateSymbolSizes.
+  assert(SymbolSizes.size() == 3);
+  assert(cantFail(std::get<0>(SymbolSizes[2]).getName()) == FunctionID);
+  uintptr_t CodeSize = std::get<1>(SymbolSizes[2]);
+
+  auto EJITOrErr = orc::LLJITBuilder().create();
+  if (!EJITOrErr)
+    return EJITOrErr.takeError();
+
+  auto EJIT = std::move(*EJITOrErr);
+
+  if (auto ObjErr =
+          EJIT->addObjectFile(std::get<1>(ObjectFileHolder.takeBinary())))
+    return std::move(ObjErr);
+
+  auto FunctionAddressOrErr = EJIT->lookup(FunctionID);
+  if (!FunctionAddressOrErr)
+    return FunctionAddressOrErr.takeError();
+
+  const uint64_t FunctionAddress = FunctionAddressOrErr->getValue();
+
   assert(isAligned(kFunctionAlignment, FunctionAddress) &&
          "function is not properly aligned");
-  FunctionBytes =
+
+  StringRef FBytes =
       StringRef(reinterpret_cast<const char *>(FunctionAddress), CodeSize);
+  return ExecutableFunction(std::move(Ctx), std::move(EJIT), FBytes);
 }
 
+ExecutableFunction::ExecutableFunction(std::unique_ptr<LLVMContext> Ctx,
+                                       std::unique_ptr<orc::LLJIT> EJIT,
+                                       StringRef FB)
+    : FunctionBytes(FB), Context(std::move(Ctx)), ExecJIT(std::move(EJIT)) {}
+
 Error getBenchmarkFunctionBytes(const StringRef InputData,
                                 std::vector<uint8_t> &Bytes) {
   const auto Holder = getObjectFromBuffer(InputData);
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Assembler.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Assembler.h
index 7c2a002..d85d7fd 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Assembler.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Assembler.h
@@ -23,7 +23,7 @@
 #include "llvm/ADT/BitVector.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Module.h"
 #include "llvm/MC/MCInst.h"
@@ -90,10 +90,8 @@
 // AsmStream, the temporary function is eventually discarded.
 Error assembleToStream(const ExegesisTarget &ET,
                        std::unique_ptr<LLVMTargetMachine> TM,
-                       ArrayRef<unsigned> LiveIns,
-                       ArrayRef<RegisterValue> RegisterInitialValues,
-                       const FillFunction &Fill, raw_pwrite_stream &AsmStreamm,
-                       const BenchmarkKey &Key,
+                       ArrayRef<unsigned> LiveIns, const FillFunction &Fill,
+                       raw_pwrite_stream &AsmStreamm, const BenchmarkKey &Key,
                        bool GenerateMemoryInstructions);
 
 // Creates an ObjectFile in the format understood by the host.
@@ -106,10 +104,11 @@
 
 // Consumes an ObjectFile containing a `void foo(char*)` function and make it
 // executable.
-struct ExecutableFunction {
-  explicit ExecutableFunction(
-      std::unique_ptr<LLVMTargetMachine> TM,
-      object::OwningBinary<object::ObjectFile> &&ObjectFileHolder);
+class ExecutableFunction {
+public:
+  static Expected<ExecutableFunction>
+  create(std::unique_ptr<LLVMTargetMachine> TM,
+         object::OwningBinary<object::ObjectFile> &&ObjectFileHolder);
 
   // Retrieves the function as an array of bytes.
   StringRef getFunctionBytes() const { return FunctionBytes; }
@@ -119,9 +118,14 @@
     ((void (*)(char *))(intptr_t)FunctionBytes.data())(Memory);
   }
 
-  std::unique_ptr<LLVMContext> Context;
-  std::unique_ptr<ExecutionEngine> ExecEngine;
   StringRef FunctionBytes;
+
+private:
+  ExecutableFunction(std::unique_ptr<LLVMContext> Ctx,
+                     std::unique_ptr<orc::LLJIT> EJIT, StringRef FunctionBytes);
+
+  std::unique_ptr<LLVMContext> Context;
+  std::unique_ptr<orc::LLJIT> ExecJIT;
 };
 
 // Copies benchmark function's bytes from benchmark object.
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
index b8e53de..e985c32 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
@@ -11,10 +11,10 @@
 #include "Error.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
-#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/bit.h"
 #include "llvm/ObjectYAML/YAML.h"
+#include "llvm/Support/Errc.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
@@ -193,6 +193,66 @@
   static const bool flow = false;
 };
 
+const char *validationEventToString(exegesis::ValidationEvent VE) {
+  switch (VE) {
+  case exegesis::ValidationEvent::InstructionRetired:
+    return "instructions-retired";
+  case exegesis::ValidationEvent::L1DCacheLoadMiss:
+    return "l1d-cache-load-misses";
+  case exegesis::ValidationEvent::L1DCacheStoreMiss:
+    return "l1d-cache-store-misses";
+  case exegesis::ValidationEvent::L1ICacheLoadMiss:
+    return "l1i-cache-load-misses";
+  case exegesis::ValidationEvent::DataTLBLoadMiss:
+    return "data-tlb-load-misses";
+  case exegesis::ValidationEvent::DataTLBStoreMiss:
+    return "data-tlb-store-misses";
+  case exegesis::ValidationEvent::InstructionTLBLoadMiss:
+    return "instruction-tlb-load-misses";
+  }
+  llvm_unreachable("Unhandled exegesis::ValidationEvent enum");
+}
+
+Expected<exegesis::ValidationEvent> stringToValidationEvent(StringRef Input) {
+  if (Input == "instructions-retired")
+    return exegesis::ValidationEvent::InstructionRetired;
+  else if (Input == "l1d-cache-load-misses")
+    return exegesis::ValidationEvent::L1DCacheLoadMiss;
+  else if (Input == "l1d-cache-store-misses")
+    return exegesis::ValidationEvent::L1DCacheStoreMiss;
+  else if (Input == "l1i-cache-load-misses")
+    return exegesis::ValidationEvent::L1ICacheLoadMiss;
+  else if (Input == "data-tlb-load-misses")
+    return exegesis::ValidationEvent::DataTLBLoadMiss;
+  else if (Input == "data-tlb-store-misses")
+    return exegesis::ValidationEvent::DataTLBStoreMiss;
+  else if (Input == "instruction-tlb-load-misses")
+    return exegesis::ValidationEvent::InstructionTLBLoadMiss;
+  else
+    return make_error<StringError>("Invalid validation event string",
+                                   errc::invalid_argument);
+}
+
+template <>
+struct CustomMappingTraits<std::map<exegesis::ValidationEvent, int64_t>> {
+  static void inputOne(IO &Io, StringRef KeyStr,
+                       std::map<exegesis::ValidationEvent, int64_t> &VI) {
+    Expected<exegesis::ValidationEvent> Key = stringToValidationEvent(KeyStr);
+    if (!Key) {
+      Io.setError("Key is not a valid validation event");
+      return;
+    }
+    Io.mapRequired(KeyStr.str().c_str(), VI[*Key]);
+  }
+
+  static void output(IO &Io, std::map<exegesis::ValidationEvent, int64_t> &VI) {
+    for (auto &IndividualVI : VI) {
+      Io.mapRequired(validationEventToString(IndividualVI.first),
+                     IndividualVI.second);
+    }
+  }
+};
+
 // exegesis::Measure is rendererd as a flow instead of a list.
 // e.g. { "key": "the key", "value": 0123 }
 template <> struct MappingTraits<exegesis::BenchmarkMeasure> {
@@ -204,6 +264,7 @@
     }
     Io.mapRequired("value", Obj.PerInstructionValue);
     Io.mapOptional("per_snippet_value", Obj.PerSnippetValue);
+    Io.mapOptional("validation_counters", Obj.ValidationCounters);
   }
   static const bool flow = true;
 };
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
index 77e0994..7769c9d 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
@@ -17,9 +17,7 @@
 
 #include "LlvmState.h"
 #include "RegisterValue.h"
-#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstBuilder.h"
 #include "llvm/Support/YAMLTraits.h"
@@ -34,6 +32,16 @@
 
 namespace exegesis {
 
+enum ValidationEvent {
+  InstructionRetired,
+  L1DCacheLoadMiss,
+  L1DCacheStoreMiss,
+  L1ICacheLoadMiss,
+  DataTLBLoadMiss,
+  DataTLBStoreMiss,
+  InstructionTLBLoadMiss
+};
+
 enum class BenchmarkPhaseSelectorE {
   PrepareSnippet,
   PrepareAndAssembleSnippet,
@@ -72,12 +80,17 @@
   // An opaque configuration, that can be used to separate several benchmarks of
   // the same instruction under different configurations.
   std::string Config;
+  // The address that the snippet should be loaded in at if the execution mode
+  // being used supports it.
+  intptr_t SnippetAddress = 0;
 };
 
 struct BenchmarkMeasure {
   // A helper to create an unscaled BenchmarkMeasure.
-  static BenchmarkMeasure Create(std::string Key, double Value) {
-    return {Key, Value, Value};
+  static BenchmarkMeasure
+  Create(std::string Key, double Value,
+         std::map<ValidationEvent, int64_t> ValCounters) {
+    return {Key, Value, Value, ValCounters};
   }
   std::string Key;
   // This is the per-instruction value, i.e. measured quantity scaled per
@@ -86,6 +99,8 @@
   // This is the per-snippet value, i.e. measured quantity for one repetition of
   // the whole snippet.
   double PerSnippetValue;
+  // These are the validation counter values.
+  std::map<ValidationEvent, int64_t> ValidationCounters;
 };
 
 // The result of an instruction benchmark.
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
index 96ac1ae..2b51228 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <array>
+#include <cmath>
 #include <memory>
 #include <string>
 
@@ -14,10 +14,10 @@
 #include "BenchmarkRunner.h"
 #include "Error.h"
 #include "MCInstrDescView.h"
+#include "MmapUtils.h"
 #include "PerfHelper.h"
 #include "SubprocessMemory.h"
 #include "Target.h"
-#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
@@ -27,6 +27,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Program.h"
 #include "llvm/Support/Signals.h"
+#include "llvm/Support/SystemZ/zOSSupport.h"
 
 #ifdef __linux__
 #ifdef HAVE_LIBPFM
@@ -34,6 +35,7 @@
 #endif
 #include <sys/mman.h>
 #include <sys/ptrace.h>
+#include <sys/resource.h>
 #include <sys/socket.h>
 #include <sys/syscall.h>
 #include <sys/wait.h>
@@ -45,16 +47,18 @@
 #define GLIBC_INITS_RSEQ
 #endif
 #endif
-#endif
+#endif // __linux__
 
 namespace llvm {
 namespace exegesis {
 
 BenchmarkRunner::BenchmarkRunner(const LLVMState &State, Benchmark::ModeE Mode,
                                  BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
-                                 ExecutionModeE ExecutionMode)
+                                 ExecutionModeE ExecutionMode,
+                                 ArrayRef<ValidationEvent> ValCounters)
     : State(State), Mode(Mode), BenchmarkPhaseSelector(BenchmarkPhaseSelector),
-      ExecutionMode(ExecutionMode), Scratch(std::make_unique<ScratchSpace>()) {}
+      ExecutionMode(ExecutionMode), ValidationCounters(ValCounters),
+      Scratch(std::make_unique<ScratchSpace>()) {}
 
 BenchmarkRunner::~BenchmarkRunner() = default;
 
@@ -69,7 +73,9 @@
 }
 
 Expected<llvm::SmallVector<int64_t, 4>>
-BenchmarkRunner::FunctionExecutor::runAndSample(const char *Counters) const {
+BenchmarkRunner::FunctionExecutor::runAndSample(
+    const char *Counters, ArrayRef<const char *> ValidationCounters,
+    SmallVectorImpl<int64_t> &ValidationCounterValues) const {
   // We sum counts when there are several counters for a single ProcRes
   // (e.g. P23 on SandyBridge).
   llvm::SmallVector<int64_t, 4> CounterValues;
@@ -77,8 +83,8 @@
   StringRef(Counters).split(CounterNames, '+');
   for (auto &CounterName : CounterNames) {
     CounterName = CounterName.trim();
-    Expected<SmallVector<int64_t, 4>> ValueOrError =
-        runWithCounter(CounterName);
+    Expected<SmallVector<int64_t, 4>> ValueOrError = runWithCounter(
+        CounterName, ValidationCounters, ValidationCounterValues);
     if (!ValueOrError)
       return ValueOrError.takeError();
     accumulateCounterValues(ValueOrError.get(), &CounterValues);
@@ -89,13 +95,25 @@
 namespace {
 class InProcessFunctionExecutorImpl : public BenchmarkRunner::FunctionExecutor {
 public:
-  InProcessFunctionExecutorImpl(const LLVMState &State,
-                                object::OwningBinary<object::ObjectFile> Obj,
-                                BenchmarkRunner::ScratchSpace *Scratch)
-      : State(State), Function(State.createTargetMachine(), std::move(Obj)),
-        Scratch(Scratch) {}
+  static Expected<std::unique_ptr<InProcessFunctionExecutorImpl>>
+  create(const LLVMState &State, object::OwningBinary<object::ObjectFile> Obj,
+         BenchmarkRunner::ScratchSpace *Scratch) {
+    Expected<ExecutableFunction> EF =
+        ExecutableFunction::create(State.createTargetMachine(), std::move(Obj));
+
+    if (!EF)
+      return EF.takeError();
+
+    return std::unique_ptr<InProcessFunctionExecutorImpl>(
+        new InProcessFunctionExecutorImpl(State, std::move(*EF), Scratch));
+  }
 
 private:
+  InProcessFunctionExecutorImpl(const LLVMState &State,
+                                ExecutableFunction Function,
+                                BenchmarkRunner::ScratchSpace *Scratch)
+      : State(State), Function(std::move(Function)), Scratch(Scratch) {}
+
   static void
   accumulateCounterValues(const llvm::SmallVector<int64_t, 4> &NewValues,
                           llvm::SmallVector<int64_t, 4> *Result) {
@@ -106,16 +124,18 @@
       (*Result)[I] += NewValues[I];
   }
 
-  Expected<llvm::SmallVector<int64_t, 4>>
-  runWithCounter(StringRef CounterName) const override {
+  Expected<llvm::SmallVector<int64_t, 4>> runWithCounter(
+      StringRef CounterName, ArrayRef<const char *> ValidationCounters,
+      SmallVectorImpl<int64_t> &ValidationCounterValues) const override {
     const ExegesisTarget &ET = State.getExegesisTarget();
     char *const ScratchPtr = Scratch->ptr();
-    auto CounterOrError = ET.createCounter(CounterName, State);
+    auto CounterOrError =
+        ET.createCounter(CounterName, State, ValidationCounters);
 
     if (!CounterOrError)
       return CounterOrError.takeError();
 
-    pfm::Counter *Counter = CounterOrError.get().get();
+    pfm::CounterGroup *Counter = CounterOrError.get().get();
     Scratch->clear();
     {
       auto PS = ET.withSavedState();
@@ -129,20 +149,27 @@
       CrashRecoveryContext::Disable();
       PS.reset();
       if (Crashed) {
-        std::string Msg = "snippet crashed while running";
 #ifdef LLVM_ON_UNIX
         // See "Exit Status for Commands":
         // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html
         constexpr const int kSigOffset = 128;
-        if (const char *const SigName = strsignal(CRC.RetCode - kSigOffset)) {
-          Msg += ": ";
-          Msg += SigName;
-        }
-#endif
-        return make_error<SnippetCrash>(std::move(Msg));
+        return make_error<SnippetSignal>(CRC.RetCode - kSigOffset);
+#else
+        // The exit code of the process on windows is not meaningful as a
+        // signal, so simply pass in -1 as the signal into the error.
+        return make_error<SnippetSignal>(-1);
+#endif // LLVM_ON_UNIX
       }
     }
 
+    auto ValidationValuesOrErr = Counter->readValidationCountersOrError();
+    if (!ValidationValuesOrErr)
+      return ValidationValuesOrErr.takeError();
+
+    ArrayRef RealValidationValues = *ValidationValuesOrErr;
+    for (size_t I = 0; I < RealValidationValues.size(); ++I)
+      ValidationCounterValues[I] = RealValidationValues[I];
+
     return Counter->readOrError(Function.getFunctionBytes());
   }
 
@@ -161,13 +188,24 @@
 class SubProcessFunctionExecutorImpl
     : public BenchmarkRunner::FunctionExecutor {
 public:
-  SubProcessFunctionExecutorImpl(const LLVMState &State,
-                                 object::OwningBinary<object::ObjectFile> Obj,
-                                 const BenchmarkKey &Key)
-      : State(State), Function(State.createTargetMachine(), std::move(Obj)),
-        Key(Key) {}
+  static Expected<std::unique_ptr<SubProcessFunctionExecutorImpl>>
+  create(const LLVMState &State, object::OwningBinary<object::ObjectFile> Obj,
+         const BenchmarkKey &Key) {
+    Expected<ExecutableFunction> EF =
+        ExecutableFunction::create(State.createTargetMachine(), std::move(Obj));
+    if (!EF)
+      return EF.takeError();
+
+    return std::unique_ptr<SubProcessFunctionExecutorImpl>(
+        new SubProcessFunctionExecutorImpl(State, std::move(*EF), Key));
+  }
 
 private:
+  SubProcessFunctionExecutorImpl(const LLVMState &State,
+                                 ExecutableFunction Function,
+                                 const BenchmarkKey &Key)
+      : State(State), Function(std::move(Function)), Key(Key) {}
+
   enum ChildProcessExitCodeE {
     CounterFDReadFailed = 1,
     RSeqDisableFailed,
@@ -209,7 +247,8 @@
     ssize_t BytesWritten = sendmsg(SocketFD, &Message, 0);
 
     if (BytesWritten < 0)
-      return make_error<Failure>("Failed to write FD to socket");
+      return make_error<Failure>("Failed to write FD to socket: " +
+                                 Twine(strerror(errno)));
 
     return Error::success();
   }
@@ -221,10 +260,11 @@
     Message.msg_control = ControlBuffer;
     Message.msg_controllen = sizeof(ControlBuffer);
 
-    size_t BytesRead = recvmsg(SocketFD, &Message, 0);
+    ssize_t BytesRead = recvmsg(SocketFD, &Message, 0);
 
     if (BytesRead < 0)
-      return make_error<Failure>("Failed to read FD from socket");
+      return make_error<Failure>("Failed to read FD from socket: " +
+                                 Twine(strerror(errno)));
 
     struct cmsghdr *ControlMessage = CMSG_FIRSTHDR(&Message);
 
@@ -240,13 +280,16 @@
   }
 
   Error createSubProcessAndRunBenchmark(
-      StringRef CounterName, SmallVectorImpl<int64_t> &CounterValues) const {
+      StringRef CounterName, SmallVectorImpl<int64_t> &CounterValues,
+      ArrayRef<const char *> ValidationCounters,
+      SmallVectorImpl<int64_t> &ValidationCounterValues) const {
     int PipeFiles[2];
     int PipeSuccessOrErr = socketpair(AF_UNIX, SOCK_DGRAM, 0, PipeFiles);
     if (PipeSuccessOrErr != 0) {
       return make_error<Failure>(
           "Failed to create a pipe for interprocess communication between "
-          "llvm-exegesis and the benchmarking subprocess");
+          "llvm-exegesis and the benchmarking subprocess: " +
+          Twine(strerror(errno)));
     }
 
     SubprocessMemory SPMemory;
@@ -260,6 +303,12 @@
       return AddMemDefError;
 
     pid_t ParentOrChildPID = fork();
+
+    if (ParentOrChildPID == -1) {
+      return make_error<Failure>("Failed to create child process: " +
+                                 Twine(strerror(errno)));
+    }
+
     if (ParentOrChildPID == 0) {
       // We are in the child process, close the write end of the pipe
       close(PipeFiles[1]);
@@ -273,23 +322,23 @@
     }
 
     const ExegesisTarget &ET = State.getExegesisTarget();
-    auto CounterOrError =
-        ET.createCounter(CounterName, State, ParentOrChildPID);
+    auto CounterOrError = ET.createCounter(
+        CounterName, State, ValidationCounters, ParentOrChildPID);
 
     if (!CounterOrError)
       return CounterOrError.takeError();
 
-    pfm::Counter *Counter = CounterOrError.get().get();
+    pfm::CounterGroup *Counter = CounterOrError.get().get();
 
     close(PipeFiles[0]);
 
-    int CounterFileDescriptor = Counter->getFileDescriptor();
-    Error SendError =
-        sendFileDescriptorThroughSocket(PipeFiles[1], CounterFileDescriptor);
-
-    if (SendError)
-      return SendError;
-
+    // Make sure to attach to the process (and wait for the sigstop to be
+    // delivered and for the process to continue) before we write to the counter
+    // file descriptor. Attaching to the process before writing to the socket
+    // ensures that the subprocess at most has blocked on the read call. If we
+    // attach afterwards, the subprocess might exit before we get to the attach
+    // call due to effects like scheduler contention, introducing transient
+    // failures.
     if (ptrace(PTRACE_ATTACH, ParentOrChildPID, NULL, NULL) != 0)
       return make_error<Failure>("Failed to attach to the child process: " +
                                  Twine(strerror(errno)));
@@ -305,6 +354,13 @@
           "Failed to continue execution of the child process: " +
           Twine(strerror(errno)));
 
+    int CounterFileDescriptor = Counter->getFileDescriptor();
+    Error SendError =
+        sendFileDescriptorThroughSocket(PipeFiles[1], CounterFileDescriptor);
+
+    if (SendError)
+      return SendError;
+
     int ChildStatus;
     if (wait(&ChildStatus) == -1) {
       return make_error<Failure>(
@@ -317,11 +373,23 @@
       if (ChildExitCode == 0) {
         // The child exited succesfully, read counter values and return
         // success
-        CounterValues[0] = Counter->read();
+        auto CounterValueOrErr = Counter->readOrError();
+        if (!CounterValueOrErr)
+          return CounterValueOrErr.takeError();
+        CounterValues = std::move(*CounterValueOrErr);
+
+        auto ValidationValuesOrErr = Counter->readValidationCountersOrError();
+        if (!ValidationValuesOrErr)
+          return ValidationValuesOrErr.takeError();
+
+        ArrayRef RealValidationValues = *ValidationValuesOrErr;
+        for (size_t I = 0; I < RealValidationValues.size(); ++I)
+          ValidationCounterValues[I] = RealValidationValues[I];
+
         return Error::success();
       }
       // The child exited, but not successfully
-      return make_error<SnippetCrash>(
+      return make_error<Failure>(
           "Child benchmarking process exited with non-zero exit code: " +
           childProcessExitCodeToString(ChildExitCode));
     }
@@ -334,13 +402,28 @@
                                  Twine(strerror(errno)));
     }
 
-    return make_error<SnippetCrash>(
-        "The benchmarking subprocess sent unexpected signal: " +
-        Twine(strsignal(ChildSignalInfo.si_signo)));
+    if (ChildSignalInfo.si_signo == SIGSEGV)
+      return make_error<SnippetSegmentationFault>(
+          reinterpret_cast<intptr_t>(ChildSignalInfo.si_addr));
+
+    return make_error<SnippetSignal>(ChildSignalInfo.si_signo);
+  }
+
+  void disableCoreDumps() const {
+    struct rlimit rlim;
+
+    rlim.rlim_cur = 0;
+    setrlimit(RLIMIT_CORE, &rlim);
   }
 
   [[noreturn]] void prepareAndRunBenchmark(int Pipe,
                                            const BenchmarkKey &Key) const {
+    // Disable core dumps in the child process as otherwise everytime we
+    // encounter an execution failure like a segmentation fault, we will create
+    // a core dump. We report the information directly rather than require the
+    // user inspect a core dump.
+    disableCoreDumps();
+
     // The following occurs within the benchmarking subprocess
     pid_t ParentPID = getppid();
 
@@ -364,10 +447,24 @@
       exit(ChildProcessExitCodeE::RSeqDisableFailed);
 #endif // GLIBC_INITS_RSEQ
 
+    // The frontend that generates the memory annotation structures should
+    // validate that the address to map the snippet in at is a multiple of
+    // the page size. Assert that this is true here.
+    assert(Key.SnippetAddress % getpagesize() == 0 &&
+           "The snippet address needs to be aligned to a page boundary.");
+
     size_t FunctionDataCopySize = this->Function.FunctionBytes.size();
+    void *MapAddress = NULL;
+    int MapFlags = MAP_PRIVATE | MAP_ANONYMOUS;
+
+    if (Key.SnippetAddress != 0) {
+      MapAddress = reinterpret_cast<void *>(Key.SnippetAddress);
+      MapFlags |= MAP_FIXED_NOREPLACE;
+    }
+
     char *FunctionDataCopy =
-        (char *)mmap(NULL, FunctionDataCopySize, PROT_READ | PROT_WRITE,
-                     MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+        (char *)mmap(MapAddress, FunctionDataCopySize, PROT_READ | PROT_WRITE,
+                     MapFlags, 0, 0);
     if ((intptr_t)FunctionDataCopy == -1)
       exit(ChildProcessExitCodeE::FunctionDataMappingFailed);
 
@@ -387,15 +484,15 @@
     exit(0);
   }
 
-  Expected<llvm::SmallVector<int64_t, 4>>
-  runWithCounter(StringRef CounterName) const override {
+  Expected<llvm::SmallVector<int64_t, 4>> runWithCounter(
+      StringRef CounterName, ArrayRef<const char *> ValidationCounters,
+      SmallVectorImpl<int64_t> &ValidationCounterValues) const override {
     SmallVector<int64_t, 4> Value(1, 0);
-    Error PossibleBenchmarkError =
-        createSubProcessAndRunBenchmark(CounterName, Value);
+    Error PossibleBenchmarkError = createSubProcessAndRunBenchmark(
+        CounterName, Value, ValidationCounters, ValidationCounterValues);
 
-    if (PossibleBenchmarkError) {
+    if (PossibleBenchmarkError)
       return std::move(PossibleBenchmarkError);
-    }
 
     return Value;
   }
@@ -416,7 +513,6 @@
   raw_svector_ostream OS(Buffer);
   if (Error E = assembleToStream(
           State.getExegesisTarget(), State.createTargetMachine(), BC.LiveIns,
-          BC.Key.RegisterInitialValues,
           Repetitor.Repeat(Instructions, MinInstructions, LoopBodySize,
                            GenerateMemoryInstructions),
           OS, BC.Key, GenerateMemoryInstructions)) {
@@ -431,19 +527,20 @@
     const SnippetRepetitor &Repetitor) const {
   RunnableConfiguration RC;
 
-  Benchmark &InstrBenchmark = RC.InstrBenchmark;
-  InstrBenchmark.Mode = Mode;
-  InstrBenchmark.CpuName = std::string(State.getTargetMachine().getTargetCPU());
-  InstrBenchmark.LLVMTriple =
+  Benchmark &BenchmarkResult = RC.BenchmarkResult;
+  BenchmarkResult.Mode = Mode;
+  BenchmarkResult.CpuName =
+      std::string(State.getTargetMachine().getTargetCPU());
+  BenchmarkResult.LLVMTriple =
       State.getTargetMachine().getTargetTriple().normalize();
-  InstrBenchmark.NumRepetitions = NumRepetitions;
-  InstrBenchmark.Info = BC.Info;
+  BenchmarkResult.NumRepetitions = NumRepetitions;
+  BenchmarkResult.Info = BC.Info;
 
   const std::vector<MCInst> &Instructions = BC.Key.Instructions;
 
   bool GenerateMemoryInstructions = ExecutionMode == ExecutionModeE::SubProcess;
 
-  InstrBenchmark.Key = BC.Key;
+  BenchmarkResult.Key = BC.Key;
 
   // Assemble at least kMinInstructionsForSnippet instructions by repeating
   // the snippet for debug/analysis. This is so that the user clearly
@@ -458,7 +555,7 @@
       return std::move(E);
 
     if (auto Err = getBenchmarkFunctionBytes(*Snippet,
-                                             InstrBenchmark.AssembledSnippet))
+                                             BenchmarkResult.AssembledSnippet))
       return std::move(Err);
   }
 
@@ -466,8 +563,9 @@
   // measurements.
   if (BenchmarkPhaseSelector >
       BenchmarkPhaseSelectorE::PrepareAndAssembleSnippet) {
-    auto Snippet = assembleSnippet(BC, Repetitor, InstrBenchmark.NumRepetitions,
-                                   LoopBodySize, GenerateMemoryInstructions);
+    auto Snippet =
+        assembleSnippet(BC, Repetitor, BenchmarkResult.NumRepetitions,
+                        LoopBodySize, GenerateMemoryInstructions);
     if (Error E = Snippet.takeError())
       return std::move(E);
     RC.ObjectFile = getObjectFromBuffer(*Snippet);
@@ -481,25 +579,35 @@
     object::OwningBinary<object::ObjectFile> ObjectFile,
     const BenchmarkKey &Key) const {
   switch (ExecutionMode) {
-  case ExecutionModeE::InProcess:
-    return std::make_unique<InProcessFunctionExecutorImpl>(
+  case ExecutionModeE::InProcess: {
+    auto InProcessExecutorOrErr = InProcessFunctionExecutorImpl::create(
         State, std::move(ObjectFile), Scratch.get());
-  case ExecutionModeE::SubProcess:
+    if (!InProcessExecutorOrErr)
+      return InProcessExecutorOrErr.takeError();
+
+    return std::move(*InProcessExecutorOrErr);
+  }
+  case ExecutionModeE::SubProcess: {
 #ifdef __linux__
-    return std::make_unique<SubProcessFunctionExecutorImpl>(
+    auto SubProcessExecutorOrErr = SubProcessFunctionExecutorImpl::create(
         State, std::move(ObjectFile), Key);
+    if (!SubProcessExecutorOrErr)
+      return SubProcessExecutorOrErr.takeError();
+
+    return std::move(*SubProcessExecutorOrErr);
 #else
     return make_error<Failure>(
         "The subprocess execution mode is only supported on Linux");
 #endif
   }
+  }
   llvm_unreachable("ExecutionMode is outside expected range");
 }
 
-Expected<Benchmark> BenchmarkRunner::runConfiguration(
+std::pair<Error, Benchmark> BenchmarkRunner::runConfiguration(
     RunnableConfiguration &&RC,
     const std::optional<StringRef> &DumpFile) const {
-  Benchmark &InstrBenchmark = RC.InstrBenchmark;
+  Benchmark &BenchmarkResult = RC.BenchmarkResult;
   object::OwningBinary<object::ObjectFile> &ObjectFile = RC.ObjectFile;
 
   if (DumpFile && BenchmarkPhaseSelector >
@@ -507,42 +615,38 @@
     auto ObjectFilePath =
         writeObjectFile(ObjectFile.getBinary()->getData(), *DumpFile);
     if (Error E = ObjectFilePath.takeError()) {
-      InstrBenchmark.Error = toString(std::move(E));
-      return std::move(InstrBenchmark);
+      return {std::move(E), std::move(BenchmarkResult)};
     }
     outs() << "Check generated assembly with: /usr/bin/objdump -d "
            << *ObjectFilePath << "\n";
   }
 
   if (BenchmarkPhaseSelector < BenchmarkPhaseSelectorE::Measure) {
-    InstrBenchmark.Error = "actual measurements skipped.";
-    return std::move(InstrBenchmark);
+    BenchmarkResult.Error = "actual measurements skipped.";
+    return {Error::success(), std::move(BenchmarkResult)};
   }
 
   Expected<std::unique_ptr<BenchmarkRunner::FunctionExecutor>> Executor =
-      createFunctionExecutor(std::move(ObjectFile), RC.InstrBenchmark.Key);
+      createFunctionExecutor(std::move(ObjectFile), RC.BenchmarkResult.Key);
   if (!Executor)
-    return Executor.takeError();
+    return {Executor.takeError(), std::move(BenchmarkResult)};
   auto NewMeasurements = runMeasurements(**Executor);
 
   if (Error E = NewMeasurements.takeError()) {
-    if (!E.isA<SnippetCrash>())
-      return std::move(E);
-    InstrBenchmark.Error = toString(std::move(E));
-    return std::move(InstrBenchmark);
+    return {std::move(E), std::move(BenchmarkResult)};
   }
-  assert(InstrBenchmark.NumRepetitions > 0 && "invalid NumRepetitions");
+  assert(BenchmarkResult.NumRepetitions > 0 && "invalid NumRepetitions");
   for (BenchmarkMeasure &BM : *NewMeasurements) {
     // Scale the measurements by instruction.
-    BM.PerInstructionValue /= InstrBenchmark.NumRepetitions;
+    BM.PerInstructionValue /= BenchmarkResult.NumRepetitions;
     // Scale the measurements by snippet.
-    BM.PerSnippetValue *=
-        static_cast<double>(InstrBenchmark.Key.Instructions.size()) /
-        InstrBenchmark.NumRepetitions;
+    BM.PerSnippetValue /=
+        std::ceil(BenchmarkResult.NumRepetitions /
+                  static_cast<double>(BenchmarkResult.Key.Instructions.size()));
   }
-  InstrBenchmark.Measurements = std::move(*NewMeasurements);
+  BenchmarkResult.Measurements = std::move(*NewMeasurements);
 
-  return std::move(InstrBenchmark);
+  return {Error::success(), std::move(BenchmarkResult)};
 }
 
 Expected<std::string>
@@ -559,7 +663,35 @@
   raw_fd_ostream OFS(ResultFD, true /*ShouldClose*/);
   OFS.write(Buffer.data(), Buffer.size());
   OFS.flush();
-  return std::string(ResultPath.str());
+  return std::string(ResultPath);
+}
+
+static bool EventLessThan(const std::pair<ValidationEvent, const char *> LHS,
+                          const ValidationEvent RHS) {
+  return static_cast<int>(LHS.first) < static_cast<int>(RHS);
+}
+
+Error BenchmarkRunner::getValidationCountersToRun(
+    SmallVector<const char *> &ValCountersToRun) const {
+  const PfmCountersInfo &PCI = State.getPfmCounters();
+  ValCountersToRun.reserve(ValidationCounters.size());
+
+  ValCountersToRun.reserve(ValidationCounters.size());
+  ArrayRef TargetValidationEvents(PCI.ValidationEvents,
+                                  PCI.NumValidationEvents);
+  for (const ValidationEvent RequestedValEvent : ValidationCounters) {
+    auto ValCounterIt =
+        lower_bound(TargetValidationEvents, RequestedValEvent, EventLessThan);
+    if (ValCounterIt == TargetValidationEvents.end() ||
+        ValCounterIt->first != RequestedValEvent)
+      return make_error<Failure>("Cannot create validation counter");
+
+    assert(ValCounterIt->first == RequestedValEvent &&
+           "The array of validation events from the target should be sorted");
+    ValCountersToRun.push_back(ValCounterIt->second);
+  }
+
+  return Error::success();
 }
 
 BenchmarkRunner::FunctionExecutor::~FunctionExecutor() {}
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
index 24f2086..aab4b54 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
@@ -38,7 +38,8 @@
 
   explicit BenchmarkRunner(const LLVMState &State, Benchmark::ModeE Mode,
                            BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
-                           ExecutionModeE ExecutionMode);
+                           ExecutionModeE ExecutionMode,
+                           ArrayRef<ValidationEvent> ValCounters);
 
   virtual ~BenchmarkRunner();
 
@@ -56,7 +57,7 @@
   private:
     RunnableConfiguration() = default;
 
-    Benchmark InstrBenchmark;
+    Benchmark BenchmarkResult;
     object::OwningBinary<object::ObjectFile> ObjectFile;
   };
 
@@ -65,7 +66,7 @@
                            unsigned NumRepetitions, unsigned LoopUnrollFactor,
                            const SnippetRepetitor &Repetitor) const;
 
-  Expected<Benchmark>
+  std::pair<Error, Benchmark>
   runConfiguration(RunnableConfiguration &&RC,
                    const std::optional<StringRef> &DumpFile) const;
 
@@ -93,14 +94,18 @@
     virtual ~FunctionExecutor();
 
     Expected<llvm::SmallVector<int64_t, 4>>
-    runAndSample(const char *Counters) const;
+    runAndSample(const char *Counters,
+                 ArrayRef<const char *> ValidationCounters,
+                 SmallVectorImpl<int64_t> &ValidationCounterValues) const;
 
   protected:
     static void
     accumulateCounterValues(const llvm::SmallVectorImpl<int64_t> &NewValues,
                             llvm::SmallVectorImpl<int64_t> *Result);
     virtual Expected<llvm::SmallVector<int64_t, 4>>
-    runWithCounter(StringRef CounterName) const = 0;
+    runWithCounter(StringRef CounterName,
+                   ArrayRef<const char *> ValidationCounters,
+                   SmallVectorImpl<int64_t> &ValidationCounterValues) const = 0;
   };
 
 protected:
@@ -109,6 +114,11 @@
   const BenchmarkPhaseSelectorE BenchmarkPhaseSelector;
   const ExecutionModeE ExecutionMode;
 
+  SmallVector<ValidationEvent> ValidationCounters;
+
+  Error
+  getValidationCountersToRun(SmallVector<const char *> &ValCountersToRun) const;
+
 private:
   virtual Expected<std::vector<BenchmarkMeasure>>
   runMeasurements(const FunctionExecutor &Executor) const = 0;
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
index 92135e6..7312811 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
@@ -29,10 +29,10 @@
   MC
   MCA
   MCDisassembler
-  MCJIT
   MCParser
   Object
   ObjectYAML
+  OrcJIT
   RuntimeDyld
   Support
   TargetParser
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Clustering.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Clustering.cpp
index c702462..1f1fca4 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Clustering.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Clustering.cpp
@@ -307,10 +307,8 @@
       assert(std::distance(it, OldCluster.PointIndices.end()) > 0 &&
              "Should have found at least one bad point");
       // Mark to-be-moved points as belonging to the new cluster.
-      std::for_each(it, OldCluster.PointIndices.end(),
-                    [this, &UnstableCluster](size_t P) {
-                      ClusterIdForPoint_[P] = UnstableCluster.Id;
-                    });
+      for (size_t P : llvm::make_range(it, OldCluster.PointIndices.end()))
+        ClusterIdForPoint_[P] = UnstableCluster.Id;
       // Actually append to-be-moved points to the new cluster.
       UnstableCluster.PointIndices.insert(UnstableCluster.PointIndices.end(),
                                           it, OldCluster.PointIndices.end());
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Error.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Error.cpp
index 51ce41b..82ef92d 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Error.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Error.cpp
@@ -8,6 +8,11 @@
 
 #include "Error.h"
 
+#ifdef LLVM_ON_UNIX
+#include "llvm/Support/SystemZ/zOSSupport.h"
+#include <string.h>
+#endif // LLVM_ON_UNIX
+
 namespace llvm {
 namespace exegesis {
 
@@ -19,13 +24,29 @@
   return inconvertibleErrorCode();
 }
 
-char SnippetCrash::ID;
+char SnippetExecutionFailure::ID;
 
-void SnippetCrash::log(raw_ostream &OS) const { OS << Msg; }
-
-std::error_code SnippetCrash::convertToErrorCode() const {
+std::error_code SnippetExecutionFailure::convertToErrorCode() const {
   return inconvertibleErrorCode();
 }
 
+char SnippetSegmentationFault::ID;
+
+void SnippetSegmentationFault::log(raw_ostream &OS) const {
+  OS << "The snippet encountered a segmentation fault at address "
+     << Twine::utohexstr(Address);
+}
+
+char SnippetSignal::ID;
+
+void SnippetSignal::log(raw_ostream &OS) const {
+  OS << "snippet crashed while running";
+#ifdef LLVM_ON_UNIX
+  OS << ": " << strsignal(SignalNumber);
+#else
+  (void)SignalNumber;
+#endif // LLVM_ON_UNIX
+}
+
 } // namespace exegesis
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Error.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Error.h
index e5fa093e..2587c45 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Error.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Error.h
@@ -36,19 +36,44 @@
   std::string Msg;
 };
 
-// A class representing failures that happened during snippet execution.
-// Instead of terminating the program crashes are logged into the output.
-class SnippetCrash : public ErrorInfo<SnippetCrash> {
+// A class representing a non-descript snippet execution failure. This class
+// is designed to sub-classed into more specific failures that contain
+// additional data about the specific error that they represent. Instead of
+// halting the program, the errors are reported in the output.
+class SnippetExecutionFailure : public ErrorInfo<SnippetExecutionFailure> {
 public:
   static char ID;
-  SnippetCrash(const Twine &S) : Msg(S.str()) {}
+
+  std::error_code convertToErrorCode() const override;
+};
+
+// A class representing specifically segmentation faults that happen during
+// snippet execution.
+class SnippetSegmentationFault : public SnippetExecutionFailure {
+public:
+  static char ID;
+  SnippetSegmentationFault(intptr_t SegFaultAddress)
+      : Address(SegFaultAddress){};
+
+  intptr_t getAddress() { return Address; }
 
   void log(raw_ostream &OS) const override;
 
-  std::error_code convertToErrorCode() const override;
+private:
+  intptr_t Address;
+};
+
+// A class representing all other non-specific failures that happen during
+// snippet execution.
+class SnippetSignal : public SnippetExecutionFailure {
+public:
+  static char ID;
+  SnippetSignal(int Signal) : SignalNumber(Signal){};
+
+  void log(raw_ostream &OS) const override;
 
 private:
-  std::string Msg;
+  int SignalNumber;
 };
 
 } // namespace exegesis
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp
index 753efed..eb7f70f 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp
@@ -21,11 +21,14 @@
 LatencyBenchmarkRunner::LatencyBenchmarkRunner(
     const LLVMState &State, Benchmark::ModeE Mode,
     BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
-    Benchmark::ResultAggregationModeE ResultAgg, ExecutionModeE ExecutionMode)
-    : BenchmarkRunner(State, Mode, BenchmarkPhaseSelector, ExecutionMode) {
+    Benchmark::ResultAggregationModeE ResultAgg, ExecutionModeE ExecutionMode,
+    ArrayRef<ValidationEvent> ValCounters, unsigned BenchmarkRepeatCount)
+    : BenchmarkRunner(State, Mode, BenchmarkPhaseSelector, ExecutionMode,
+                      ValCounters) {
   assert((Mode == Benchmark::Latency || Mode == Benchmark::InverseThroughput) &&
          "invalid mode");
   ResultAggMode = ResultAgg;
+  NumMeasurements = BenchmarkRepeatCount;
 }
 
 LatencyBenchmarkRunner::~LatencyBenchmarkRunner() = default;
@@ -68,14 +71,23 @@
   // Cycle measurements include some overhead from the kernel. Repeat the
   // measure several times and return the aggregated value, as specified by
   // ResultAggMode.
-  constexpr const int NumMeasurements = 30;
   llvm::SmallVector<int64_t, 4> AccumulatedValues;
   double MinVariance = std::numeric_limits<double>::infinity();
-  const char *CounterName = State.getPfmCounters().CycleCounter;
+  const PfmCountersInfo &PCI = State.getPfmCounters();
+  const char *CounterName = PCI.CycleCounter;
+
+  SmallVector<const char *> ValCountersToRun;
+  Error ValCounterErr = getValidationCountersToRun(ValCountersToRun);
+  if (ValCounterErr)
+    return std::move(ValCounterErr);
+
+  SmallVector<int64_t> ValCounterValues(ValCountersToRun.size(), 0);
   // Values count for each run.
   int ValuesCount = 0;
   for (size_t I = 0; I < NumMeasurements; ++I) {
-    auto ExpectedCounterValues = Executor.runAndSample(CounterName);
+    SmallVector<int64_t> IterationValCounterValues(ValCountersToRun.size(), -1);
+    auto ExpectedCounterValues = Executor.runAndSample(
+        CounterName, ValCountersToRun, IterationValCounterValues);
     if (!ExpectedCounterValues)
       return ExpectedCounterValues.takeError();
     ValuesCount = ExpectedCounterValues.get().size();
@@ -89,8 +101,15 @@
         MinVariance = Variance;
       }
     }
+
+    for (size_t I = 0; I < ValCounterValues.size(); ++I)
+      ValCounterValues[I] += IterationValCounterValues[I];
   }
 
+  std::map<ValidationEvent, int64_t> ValidationInfo;
+  for (size_t I = 0; I < ValidationCounters.size(); ++I)
+    ValidationInfo[ValidationCounters[I]] = ValCounterValues[I];
+
   std::string ModeName;
   switch (Mode) {
   case Benchmark::Latency:
@@ -111,25 +130,26 @@
     std::vector<BenchmarkMeasure> Result;
     Result.reserve(AccumulatedValues.size());
     for (const int64_t Value : AccumulatedValues)
-      Result.push_back(BenchmarkMeasure::Create(ModeName, Value));
+      Result.push_back(
+          BenchmarkMeasure::Create(ModeName, Value, ValidationInfo));
     return std::move(Result);
   }
   case Benchmark::Min: {
     std::vector<BenchmarkMeasure> Result;
-    Result.push_back(
-        BenchmarkMeasure::Create(ModeName, findMin(AccumulatedValues)));
+    Result.push_back(BenchmarkMeasure::Create(
+        ModeName, findMin(AccumulatedValues), ValidationInfo));
     return std::move(Result);
   }
   case Benchmark::Max: {
     std::vector<BenchmarkMeasure> Result;
-    Result.push_back(
-        BenchmarkMeasure::Create(ModeName, findMax(AccumulatedValues)));
+    Result.push_back(BenchmarkMeasure::Create(
+        ModeName, findMax(AccumulatedValues), ValidationInfo));
     return std::move(Result);
   }
   case Benchmark::Mean: {
     std::vector<BenchmarkMeasure> Result;
-    Result.push_back(
-        BenchmarkMeasure::Create(ModeName, findMean(AccumulatedValues)));
+    Result.push_back(BenchmarkMeasure::Create(
+        ModeName, findMean(AccumulatedValues), ValidationInfo));
     return std::move(Result);
   }
   }
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h
index 34b912f..6e21197 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h
@@ -15,6 +15,7 @@
 #define LLVM_TOOLS_LLVM_EXEGESIS_LATENCY_H
 
 #include "BenchmarkRunner.h"
+#include "Target.h"
 
 namespace llvm {
 namespace exegesis {
@@ -24,7 +25,9 @@
   LatencyBenchmarkRunner(const LLVMState &State, Benchmark::ModeE Mode,
                          BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
                          Benchmark::ResultAggregationModeE ResultAggMode,
-                         ExecutionModeE ExecutionMode);
+                         ExecutionModeE ExecutionMode,
+                         ArrayRef<ValidationEvent> ValCounters,
+                         unsigned BenchmarkRepeatCount);
   ~LatencyBenchmarkRunner() override;
 
 private:
@@ -32,6 +35,7 @@
   runMeasurements(const FunctionExecutor &Executor) const override;
 
   Benchmark::ResultAggregationModeE ResultAggMode;
+  unsigned NumMeasurements;
 };
 } // namespace exegesis
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.h
index 137ba1b..16f0def 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.h
@@ -16,7 +16,6 @@
 
 #include "MCInstrDescView.h"
 #include "RegisterAliasing.h"
-#include "llvm/ADT/StringMap.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstrInfo.h"
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
index f453731..d781605 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
@@ -9,7 +9,6 @@
 #include "MCInstrDescView.h"
 
 #include <iterator>
-#include <map>
 #include <tuple>
 
 #include "llvm/ADT/STLExtras.h"
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
index ec698e6..cc8cd5d 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/Target.cpp
@@ -11,6 +11,9 @@
 #include "Mips.h"
 #include "MipsRegisterInfo.h"
 
+#define GET_AVAILABLE_OPCODE_CHECKER
+#include "MipsGenInstrInfo.inc"
+
 namespace llvm {
 namespace exegesis {
 
@@ -51,7 +54,8 @@
 namespace {
 class ExegesisMipsTarget : public ExegesisTarget {
 public:
-  ExegesisMipsTarget() : ExegesisTarget(MipsCpuPfmCounters) {}
+  ExegesisMipsTarget()
+      : ExegesisTarget(MipsCpuPfmCounters, Mips_MC::isOpcodeAvailable) {}
 
 private:
   unsigned getScratchMemoryRegister(const llvm::Triple &TT) const override;
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/MmapUtils.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/MmapUtils.h
new file mode 100644
index 0000000..31e8778
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/MmapUtils.h
@@ -0,0 +1,32 @@
+//===-- MmapUtils.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains compatibility-related preprocessor directives related
+// to mmap.
+//
+//===----------------------------------------------------------------------===//
+
+#ifdef __linux__
+#include <sys/mman.h>
+#include <sys/syscall.h>
+
+// Before kernel 4.17, Linux did not support MAP_FIXED_NOREPLACE, so if it is
+// not available, simplfy define it as MAP_FIXED which performs the same
+// function but does not guarantee existing mappings won't get clobbered.
+#ifndef MAP_FIXED_NOREPLACE
+#define MAP_FIXED_NOREPLACE MAP_FIXED
+#endif
+
+// Some 32-bit architectures don't have mmap and define mmap2 instead. The only
+// difference between the two syscalls is that mmap2's offset parameter is in
+// terms 4096 byte offsets rather than individual bytes, so for our purposes
+// they are effectively the same as all ofsets here are set to 0.
+#if defined(SYS_mmap2) && !defined(SYS_mmap)
+#define SYS_mmap SYS_mmap2
+#endif
+#endif // __linux__
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
index 3ff1745..6b8df01 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.cpp
@@ -107,20 +107,17 @@
   return FullQualifiedEventString;
 }
 
-Counter::Counter(PerfEvent &&E, pid_t ProcessID) : Event(std::move(E)) {
+ConfiguredEvent::ConfiguredEvent(PerfEvent &&EventToConfigure)
+    : Event(std::move(EventToConfigure)) {
   assert(Event.valid());
-  IsDummyEvent = Event.name() == PerfEvent::DummyEventString;
-  if (!IsDummyEvent)
-    initRealEvent(E, ProcessID);
 }
 
 #ifdef HAVE_LIBPFM
-void Counter::initRealEvent(const PerfEvent &E, pid_t ProcessID) {
-  const int Cpu = -1;     // measure any processor.
-  const int GroupFd = -1; // no grouping of counters.
+void ConfiguredEvent::initRealEvent(const pid_t ProcessID, const int GroupFD) {
+  const int CPU = -1;
   const uint32_t Flags = 0;
   perf_event_attr AttrCopy = *Event.attribute();
-  FileDescriptor = perf_event_open(&AttrCopy, ProcessID, Cpu, GroupFd, Flags);
+  FileDescriptor = perf_event_open(&AttrCopy, ProcessID, CPU, GroupFD, Flags);
   if (FileDescriptor == -1) {
     errs() << "Unable to open event. ERRNO: " << strerror(errno)
            << ". Make sure your kernel allows user "
@@ -133,64 +130,101 @@
   assert(FileDescriptor != -1 && "Unable to open event");
 }
 
-Counter::~Counter() {
-  if (!IsDummyEvent)
-    close(FileDescriptor);
-}
-
-void Counter::start() {
-  if (!IsDummyEvent)
-    ioctl(FileDescriptor, PERF_EVENT_IOC_RESET, 0);
-}
-
-void Counter::stop() {
-  if (!IsDummyEvent)
-    ioctl(FileDescriptor, PERF_EVENT_IOC_DISABLE, 0);
-}
-
-int64_t Counter::read() const {
-  auto ValueOrError = readOrError();
-  if (ValueOrError) {
-    if (!ValueOrError.get().empty())
-      return ValueOrError.get()[0];
-    errs() << "Counter has no reading\n";
-  } else
-    errs() << ValueOrError.takeError() << "\n";
-  return -1;
-}
-
-llvm::Expected<llvm::SmallVector<int64_t, 4>>
-Counter::readOrError(StringRef /*unused*/) const {
+Expected<SmallVector<int64_t>>
+ConfiguredEvent::readOrError(StringRef /*unused*/) const {
   int64_t Count = 0;
-  if (!IsDummyEvent) {
-    ssize_t ReadSize = ::read(FileDescriptor, &Count, sizeof(Count));
-    if (ReadSize != sizeof(Count))
-      return llvm::make_error<llvm::StringError>("Failed to read event counter",
-                                                 llvm::errc::io_error);
-  } else {
-    Count = 42;
-  }
+  ssize_t ReadSize = ::read(FileDescriptor, &Count, sizeof(Count));
 
-  llvm::SmallVector<int64_t, 4> Result;
+  if (ReadSize != sizeof(Count))
+    return llvm::make_error<llvm::StringError>("Failed to read event counter",
+                                               llvm::errc::io_error);
+
+  SmallVector<int64_t, 1> Result;
   Result.push_back(Count);
   return Result;
 }
 
-int Counter::numValues() const { return 1; }
+ConfiguredEvent::~ConfiguredEvent() { close(FileDescriptor); }
 #else
+void ConfiguredEvent::initRealEvent(pid_t ProcessID, const int GroupFD) {}
 
-void Counter::initRealEvent(const PerfEvent &, pid_t ProcessID) {}
+Expected<SmallVector<int64_t>>
+ConfiguredEvent::readOrError(StringRef /*unused*/) const {
+  return make_error<StringError>("Not implemented",
+                                 errc::function_not_supported);
+}
 
-Counter::~Counter() = default;
+ConfiguredEvent::~ConfiguredEvent() = default;
+#endif // HAVE_LIBPFM
 
-void Counter::start() {}
+CounterGroup::CounterGroup(PerfEvent &&E, std::vector<PerfEvent> &&ValEvents,
+                           pid_t ProcessID)
+    : EventCounter(std::move(E)) {
+  IsDummyEvent = EventCounter.isDummyEvent();
 
-void Counter::stop() {}
+  for (auto &&ValEvent : ValEvents)
+    ValidationEventCounters.emplace_back(std::move(ValEvent));
 
-int64_t Counter::read() const { return 42; }
+  if (!IsDummyEvent)
+    initRealEvent(ProcessID);
+}
+
+#ifdef HAVE_LIBPFM
+void CounterGroup::initRealEvent(pid_t ProcessID) {
+  EventCounter.initRealEvent(ProcessID);
+
+  for (auto &ValCounter : ValidationEventCounters)
+    ValCounter.initRealEvent(ProcessID, getFileDescriptor());
+}
+
+void CounterGroup::start() {
+  if (!IsDummyEvent)
+    ioctl(getFileDescriptor(), PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP);
+}
+
+void CounterGroup::stop() {
+  if (!IsDummyEvent)
+    ioctl(getFileDescriptor(), PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP);
+}
 
 llvm::Expected<llvm::SmallVector<int64_t, 4>>
-Counter::readOrError(StringRef /*unused*/) const {
+CounterGroup::readOrError(StringRef FunctionBytes) const {
+  if (!IsDummyEvent)
+    return EventCounter.readOrError(FunctionBytes);
+  else
+    return SmallVector<int64_t, 1>(1, 42);
+}
+
+llvm::Expected<llvm::SmallVector<int64_t>>
+CounterGroup::readValidationCountersOrError() const {
+  llvm::SmallVector<int64_t, 4> Result;
+  for (const auto &ValCounter : ValidationEventCounters) {
+    Expected<SmallVector<int64_t>> ValueOrError =
+        ValCounter.readOrError(StringRef());
+
+    if (!ValueOrError)
+      return ValueOrError.takeError();
+
+    // Reading a validation counter will only return a single value, so it is
+    // safe to only append the first value here. Also assert that this is true.
+    assert(ValueOrError->size() == 1 &&
+           "Validation counters should only return a single value");
+    Result.push_back((*ValueOrError)[0]);
+  }
+  return Result;
+}
+
+int CounterGroup::numValues() const { return 1; }
+#else
+
+void CounterGroup::initRealEvent(pid_t ProcessID) {}
+
+void CounterGroup::start() {}
+
+void CounterGroup::stop() {}
+
+llvm::Expected<llvm::SmallVector<int64_t, 4>>
+CounterGroup::readOrError(StringRef /*unused*/) const {
   if (IsDummyEvent) {
     llvm::SmallVector<int64_t, 4> Result;
     Result.push_back(42);
@@ -200,7 +234,12 @@
                                              llvm::errc::io_error);
 }
 
-int Counter::numValues() const { return 1; }
+llvm::Expected<llvm::SmallVector<int64_t>>
+CounterGroup::readValidationCountersOrError() const {
+  return SmallVector<int64_t>(0);
+}
+
+int CounterGroup::numValues() const { return 1; }
 
 #endif
 
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.h
index a50974f..7d050b8 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PerfHelper.h
@@ -77,17 +77,43 @@
   void initRealEvent(StringRef PfmEventString);
 };
 
-// Uses a valid PerfEvent to configure the Kernel so we can measure the
-// underlying event.
-class Counter {
+// Represents a single event that has been configured in the Linux perf
+// subsystem.
+class ConfiguredEvent {
+public:
+  ConfiguredEvent(PerfEvent &&EventToConfigure);
+
+  void initRealEvent(const pid_t ProcessID, const int GroupFD = -1);
+  Expected<SmallVector<int64_t>> readOrError(StringRef FunctionBytes) const;
+  int getFileDescriptor() const { return FileDescriptor; }
+  bool isDummyEvent() const {
+    return Event.name() == PerfEvent::DummyEventString;
+  }
+
+  ConfiguredEvent(const ConfiguredEvent &) = delete;
+  ConfiguredEvent(ConfiguredEvent &&other) = default;
+
+  ~ConfiguredEvent();
+
+private:
+  PerfEvent Event;
+  int FileDescriptor = -1;
+};
+
+// Consists of a counter measuring a specific event and associated validation
+// counters measuring execution conditions. All counters in a group are part
+// of a single event group and are thus scheduled on and off the CPU as a single
+// unit.
+class CounterGroup {
 public:
   // event: the PerfEvent to measure.
-  explicit Counter(PerfEvent &&event, pid_t ProcessID = 0);
+  explicit CounterGroup(PerfEvent &&event, std::vector<PerfEvent> &&ValEvents,
+                        pid_t ProcessID = 0);
 
-  Counter(const Counter &) = delete;
-  Counter(Counter &&other) = default;
+  CounterGroup(const CounterGroup &) = delete;
+  CounterGroup(CounterGroup &&other) = default;
 
-  virtual ~Counter();
+  virtual ~CounterGroup() = default;
 
   /// Starts the measurement of the event.
   virtual void start();
@@ -95,9 +121,6 @@
   /// Stops the measurement of the event.
   void stop();
 
-  /// Returns the current value of the counter or -1 if it cannot be read.
-  int64_t read() const;
-
   /// Returns the current value of the counter or error if it cannot be read.
   /// FunctionBytes: The benchmark function being executed.
   /// This is used to filter out the measurements to ensure they are only
@@ -107,17 +130,20 @@
   virtual llvm::Expected<llvm::SmallVector<int64_t, 4>>
   readOrError(StringRef FunctionBytes = StringRef()) const;
 
+  virtual llvm::Expected<llvm::SmallVector<int64_t>>
+  readValidationCountersOrError() const;
+
   virtual int numValues() const;
 
-  int getFileDescriptor() const { return FileDescriptor; }
+  int getFileDescriptor() const { return EventCounter.getFileDescriptor(); }
 
 protected:
-  PerfEvent Event;
-  int FileDescriptor = -1;
+  ConfiguredEvent EventCounter;
   bool IsDummyEvent;
+  std::vector<ConfiguredEvent> ValidationEventCounters;
 
 private:
-  void initRealEvent(const PerfEvent &E, pid_t ProcessID);
+  void initRealEvent(pid_t ProcessID);
 };
 
 } // namespace pfm
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
index 54d42df..5c944c9 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/Target.cpp
@@ -10,6 +10,9 @@
 #include "PPC.h"
 #include "PPCRegisterInfo.h"
 
+#define GET_AVAILABLE_OPCODE_CHECKER
+#include "PPCGenInstrInfo.inc"
+
 namespace llvm {
 namespace exegesis {
 
@@ -26,7 +29,8 @@
 namespace {
 class ExegesisPowerPCTarget : public ExegesisTarget {
 public:
-  ExegesisPowerPCTarget() : ExegesisTarget(PPCCpuPfmCounters) {}
+  ExegesisPowerPCTarget()
+      : ExegesisTarget(PPCCpuPfmCounters, PPC_MC::isOpcodeAvailable) {}
 
 private:
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SchedClassResolution.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SchedClassResolution.cpp
index 6b768c8..5910757 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SchedClassResolution.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SchedClassResolution.cpp
@@ -12,8 +12,6 @@
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MCA/Support.h"
 #include "llvm/Support/FormatVariadic.h"
-#include <limits>
-#include <unordered_set>
 #include <vector>
 
 namespace llvm {
@@ -83,19 +81,20 @@
     const MCWriteProcResEntry *WPR = Entry.second;
     const MCProcResourceDesc *const ProcResDesc =
         SM.getProcResource(WPR->ProcResourceIdx);
-    // TODO: Handle StartAtCycle in llvm-exegesis and llvm-mca. See
+    // TODO: Handle AcquireAtAtCycle in llvm-exegesis and llvm-mca. See
     // https://github.com/llvm/llvm-project/issues/62680 and
     // https://github.com/llvm/llvm-project/issues/62681
-    assert(WPR->StartAtCycle == 0 &&
-           "`llvm-exegesis` does not handle StartAtCycle > 0");
+    assert(WPR->AcquireAtCycle == 0 &&
+           "`llvm-exegesis` does not handle AcquireAtCycle > 0");
     if (ProcResDesc->SubUnitsIdxBegin == nullptr) {
       // This is a ProcResUnit.
-      Result.push_back({WPR->ProcResourceIdx, WPR->Cycles, WPR->StartAtCycle});
-      ProcResUnitUsage[WPR->ProcResourceIdx] += WPR->Cycles;
+      Result.push_back(
+          {WPR->ProcResourceIdx, WPR->ReleaseAtCycle, WPR->AcquireAtCycle});
+      ProcResUnitUsage[WPR->ProcResourceIdx] += WPR->ReleaseAtCycle;
     } else {
       // This is a ProcResGroup. First see if it contributes any cycles or if
       // it has cycles just from subunits.
-      float RemainingCycles = WPR->Cycles;
+      float RemainingCycles = WPR->ReleaseAtCycle;
       for (const auto *SubResIdx = ProcResDesc->SubUnitsIdxBegin;
            SubResIdx != ProcResDesc->SubUnitsIdxBegin + ProcResDesc->NumUnits;
            ++SubResIdx) {
@@ -108,7 +107,7 @@
       // The ProcResGroup contributes `RemainingCycles` cycles of its own.
       Result.push_back({WPR->ProcResourceIdx,
                         static_cast<uint16_t>(std::round(RemainingCycles)),
-                        WPR->StartAtCycle});
+                        WPR->AcquireAtCycle});
       // Spread the remaining cycles over all subunits.
       for (const auto *SubResIdx = ProcResDesc->SubUnitsIdxBegin;
            SubResIdx != ProcResDesc->SubUnitsIdxBegin + ProcResDesc->NumUnits;
@@ -213,13 +212,13 @@
         SM.getProcResource(WPR.ProcResourceIdx);
     if (ProcResDesc->SubUnitsIdxBegin == nullptr) {
       // This is a ProcResUnit.
-      DensePressure[WPR.ProcResourceIdx] += WPR.Cycles;
+      DensePressure[WPR.ProcResourceIdx] += WPR.ReleaseAtCycle;
     } else {
       // This is a ProcResGroup.
       SmallVector<uint16_t, 32> Subunits(ProcResDesc->SubUnitsIdxBegin,
                                          ProcResDesc->SubUnitsIdxBegin +
                                              ProcResDesc->NumUnits);
-      distributePressure(WPR.Cycles, Subunits, DensePressure);
+      distributePressure(WPR.ReleaseAtCycle, Subunits, DensePressure);
     }
   }
   // Turn dense pressure into sparse pressure by removing zero entries.
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
index 07a009c..7100b51 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -38,6 +38,8 @@
 computeAliasingInstructions(const LLVMState &State, const Instruction *Instr,
                             size_t MaxAliasingInstructions,
                             const BitVector &ForbiddenRegisters) {
+  const auto &ET = State.getExegesisTarget();
+  const auto AvailableFeatures = State.getSubtargetInfo().getFeatureBits();
   // Randomly iterate the set of instructions.
   std::vector<unsigned> Opcodes;
   Opcodes.resize(State.getInstrInfo().getNumOpcodes());
@@ -46,6 +48,8 @@
 
   std::vector<const Instruction *> AliasingInstructions;
   for (const unsigned OtherOpcode : Opcodes) {
+    if (!ET.isOpcodeAvailable(OtherOpcode, AvailableFeatures))
+      continue;
     if (OtherOpcode == Instr->Description.getOpcode())
       continue;
     const Instruction &OtherInstr = State.getIC().getInstr(OtherOpcode);
@@ -58,7 +62,7 @@
     }
     if (OtherInstr.hasMemoryOperands())
       continue;
-    if (!State.getExegesisTarget().allowAsBackToBack(OtherInstr))
+    if (!ET.allowAsBackToBack(OtherInstr))
       continue;
     if (Instr->hasAliasingRegistersThrough(OtherInstr, ForbiddenRegisters))
       AliasingInstructions.push_back(&OtherInstr);
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
index d85a9f1..7258fcb 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
@@ -23,6 +23,10 @@
 #include "llvm/Support/SourceMgr.h"
 #include <string>
 
+#ifdef __linux__
+#include <unistd.h>
+#endif // __linux__
+
 namespace llvm {
 namespace exegesis {
 namespace {
@@ -118,6 +122,19 @@
       MemoryMapping MemMap;
       MemMap.MemoryValueName = Parts[0].trim().str();
       MemMap.Address = std::stol(Parts[1].trim().str());
+
+#ifdef __linux__
+      // Validate that the annotation is a multiple of the platform's page
+      // size.
+      if (MemMap.Address % getpagesize() != 0) {
+        errs() << "invalid comment 'LLVM-EXEGESIS-MEM-MAP " << CommentText
+               << "', expected <ADDRESS> to be a multiple of the platform page "
+                  "size.";
+        ++InvalidComments;
+        return;
+      }
+#endif // __linux__
+
       // validate that the annotation refers to an already existing memory
       // definition
       auto MemValIT = Result->Key.MemoryValues.find(Parts[0].trim().str());
@@ -131,6 +148,33 @@
       Result->Key.MemoryMappings.push_back(std::move(MemMap));
       return;
     }
+    if (CommentText.consume_front("SNIPPET-ADDRESS")) {
+      // LLVM-EXEGESIS-SNIPPET-ADDRESS <address>
+      if (!to_integer<intptr_t>(CommentText.trim(), Result->Key.SnippetAddress,
+                                16)) {
+        errs() << "invalid comment 'LLVM-EXEGESIS-SNIPPET-ADDRESS "
+               << CommentText
+               << "', expected <ADDRESS> to contain a valid integer in "
+                  "hexadecimal format";
+        ++InvalidComments;
+        return;
+      }
+
+#ifdef __linux__
+      // Validate that the address in the annotation is a multiple of the
+      // platform's page size.
+      if (Result->Key.SnippetAddress % getpagesize() != 0) {
+        errs() << "invalid comment 'LLVM-EXEGESIS-SNIPPET-ADDRESS "
+               << CommentText
+               << ", expected <ADDRESS> to be a multiple of the platform page "
+                  "size.";
+        ++InvalidComments;
+        return;
+      }
+#endif // __linux__
+
+      return;
+    }
   }
 
   unsigned numInvalidComments() const { return InvalidComments; }
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
index 4b47be0..7dcff60 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
@@ -6,7 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <array>
 #include <string>
 
 #include "Assembler.h"
@@ -17,6 +16,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/Program.h"
@@ -77,9 +77,12 @@
         BC.Info = CT.Info;
         BC.Key.Instructions.reserve(CT.Instructions.size());
         for (InstructionTemplate &IT : CT.Instructions) {
-          if (auto error = randomizeUnsetVariables(State, ForbiddenRegs, IT))
-            return error;
-          BC.Key.Instructions.push_back(IT.build());
+          if (auto Error = randomizeUnsetVariables(State, ForbiddenRegs, IT))
+            return Error;
+          MCInst Inst = IT.build();
+          if (auto Error = validateGeneratedInstruction(State, Inst))
+            return Error;
+          BC.Key.Instructions.push_back(Inst);
         }
         if (CT.ScratchSpacePointerInReg)
           BC.LiveIns.push_back(CT.ScratchSpacePointerInReg);
@@ -282,5 +285,21 @@
   return Error::success();
 }
 
+Error validateGeneratedInstruction(const LLVMState &State, const MCInst &Inst) {
+  for (const auto &Operand : Inst) {
+    if (!Operand.isValid()) {
+      // Mention the particular opcode - it is not necessarily the "main"
+      // opcode being benchmarked by this snippet. For example, serial snippet
+      // generator uses one more opcode when in SERIAL_VIA_NON_MEMORY_INSTR
+      // execution mode.
+      const auto OpcodeName = State.getInstrInfo().getName(Inst.getOpcode());
+      return make_error<Failure>("Not all operands were initialized by the "
+                                 "snippet generator for " +
+                                 OpcodeName + " opcode.");
+    }
+  }
+  return Error::success();
+}
+
 } // namespace exegesis
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
index 9c64d46..770e4e8 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
@@ -107,6 +107,9 @@
                               const BitVector &ForbiddenRegs,
                               InstructionTemplate &IT);
 
+// Sanity check generated instruction.
+Error validateGeneratedInstruction(const LLVMState &State, const MCInst &Inst);
+
 } // namespace exegesis
 } // namespace llvm
 
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp
index 8b0c452..c1660c2 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp
@@ -6,13 +6,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include <array>
-#include <string>
-
 #include "SnippetRepetitor.h"
 #include "Target.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/CodeGen/TargetSubtargetInfo.h"
 
 namespace llvm {
@@ -32,10 +30,10 @@
             CleanupMemory](FunctionFiller &Filler) {
       auto Entry = Filler.getEntry();
       if (!Instructions.empty()) {
-        // Add the whole snippet at least once.
-        Entry.addInstructions(Instructions);
-        for (unsigned I = Instructions.size(); I < MinInstructions; ++I) {
-          Entry.addInstruction(Instructions[I % Instructions.size()]);
+        const unsigned NumRepetitions =
+            divideCeil(MinInstructions, Instructions.size());
+        for (unsigned I = 0; I < NumRepetitions; ++I) {
+          Entry.addInstructions(Instructions);
         }
       }
       Entry.addReturn(State.getExegesisTarget(), CleanupMemory);
@@ -77,6 +75,11 @@
       auto Loop = Filler.addBasicBlock();
       auto Exit = Filler.addBasicBlock();
 
+      // Align the loop machine basic block to a target-specific boundary
+      // to promote optimal instruction fetch/predecoding conditions.
+      Loop.MBB->setAlignment(
+          Filler.MF.getSubtarget().getTargetLowering()->getPrefLoopAlignment());
+
       const unsigned LoopUnrollFactor =
           LoopBodySize <= Instructions.size()
               ? 1
@@ -106,7 +109,7 @@
         for (const auto &LiveIn : Entry.MBB->liveins())
           Loop.MBB->addLiveIn(LiveIn);
       }
-      for (auto _ : seq(0U, LoopUnrollFactor)) {
+      for (auto _ : seq(LoopUnrollFactor)) {
         (void)_;
         Loop.addInstructions(Instructions);
       }
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.cpp
index 1e5f688..58cf1b9 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -14,6 +14,7 @@
 #include "UopsBenchmarkRunner.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/Support/Error.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
 
 namespace llvm {
 namespace exegesis {
@@ -34,8 +35,9 @@
   return nullptr;
 }
 
-Expected<std::unique_ptr<pfm::Counter>>
+Expected<std::unique_ptr<pfm::CounterGroup>>
 ExegesisTarget::createCounter(StringRef CounterName, const LLVMState &,
+                              ArrayRef<const char *> ValidationCounters,
                               const pid_t ProcessID) const {
   pfm::PerfEvent Event(CounterName);
   if (!Event.valid())
@@ -44,7 +46,18 @@
             .concat(CounterName)
             .concat("'"));
 
-  return std::make_unique<pfm::Counter>(std::move(Event), ProcessID);
+  std::vector<pfm::PerfEvent> ValidationEvents;
+  for (const char *ValCounterName : ValidationCounters) {
+    ValidationEvents.emplace_back(ValCounterName);
+    if (!ValidationEvents.back().valid())
+      return llvm::make_error<Failure>(
+          llvm::Twine("Unable to create validation counter with name '")
+              .concat(ValCounterName)
+              .concat("'"));
+  }
+
+  return std::make_unique<pfm::CounterGroup>(
+      std::move(Event), std::move(ValidationEvents), ProcessID);
 }
 
 void ExegesisTarget::registerTarget(ExegesisTarget *Target) {
@@ -78,6 +91,7 @@
     Benchmark::ModeE Mode, const LLVMState &State,
     BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
     BenchmarkRunner::ExecutionModeE ExecutionMode,
+    unsigned BenchmarkRepeatCount, ArrayRef<ValidationEvent> ValidationCounters,
     Benchmark::ResultAggregationModeE ResultAggMode) const {
   PfmCountersInfo PfmCounters = State.getPfmCounters();
   switch (Mode) {
@@ -99,8 +113,9 @@
                   "benchmarking or --use-dummy-perf-counters to not query "
                   "the kernel for real event counts."));
     }
-    return createLatencyBenchmarkRunner(State, Mode, BenchmarkPhaseSelector,
-                                        ResultAggMode, ExecutionMode);
+    return createLatencyBenchmarkRunner(
+        State, Mode, BenchmarkPhaseSelector, ResultAggMode, ExecutionMode,
+        ValidationCounters, BenchmarkRepeatCount);
   case Benchmark::Uops:
     if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure &&
         !PfmCounters.UopsCounter && !PfmCounters.IssueCounters)
@@ -110,7 +125,8 @@
           "benchmarking or --use-dummy-perf-counters to not query the kernel "
           "for real event counts.");
     return createUopsBenchmarkRunner(State, BenchmarkPhaseSelector,
-                                     ResultAggMode, ExecutionMode);
+                                     ResultAggMode, ExecutionMode,
+                                     ValidationCounters);
   }
   return nullptr;
 }
@@ -129,25 +145,34 @@
     const LLVMState &State, Benchmark::ModeE Mode,
     BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
     Benchmark::ResultAggregationModeE ResultAggMode,
-    BenchmarkRunner::ExecutionModeE ExecutionMode) const {
+    BenchmarkRunner::ExecutionModeE ExecutionMode,
+    ArrayRef<ValidationEvent> ValidationCounters,
+    unsigned BenchmarkRepeatCount) const {
   return std::make_unique<LatencyBenchmarkRunner>(
-      State, Mode, BenchmarkPhaseSelector, ResultAggMode, ExecutionMode);
+      State, Mode, BenchmarkPhaseSelector, ResultAggMode, ExecutionMode,
+      ValidationCounters, BenchmarkRepeatCount);
 }
 
 std::unique_ptr<BenchmarkRunner> ExegesisTarget::createUopsBenchmarkRunner(
     const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
     Benchmark::ResultAggregationModeE /*unused*/,
-    BenchmarkRunner::ExecutionModeE ExecutionMode) const {
-  return std::make_unique<UopsBenchmarkRunner>(State, BenchmarkPhaseSelector,
-                                               ExecutionMode);
+    BenchmarkRunner::ExecutionModeE ExecutionMode,
+    ArrayRef<ValidationEvent> ValidationCounters) const {
+  return std::make_unique<UopsBenchmarkRunner>(
+      State, BenchmarkPhaseSelector, ExecutionMode, ValidationCounters);
 }
 
 static_assert(std::is_trivial_v<PfmCountersInfo>,
               "We shouldn't have dynamic initialization here");
+
 const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,
-                                                  0u};
+                                                  0u,      nullptr, 0u};
 const PfmCountersInfo PfmCountersInfo::Dummy = {
-    pfm::PerfEvent::DummyEventString, pfm::PerfEvent::DummyEventString, nullptr,
+    pfm::PerfEvent::DummyEventString,
+    pfm::PerfEvent::DummyEventString,
+    nullptr,
+    0u,
+    nullptr,
     0u};
 
 const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const {
@@ -180,10 +205,12 @@
 
 namespace {
 
+bool opcodeIsNotAvailable(unsigned, const FeatureBitset &) { return false; }
+
 // Default implementation.
 class ExegesisDefaultTarget : public ExegesisTarget {
 public:
-  ExegesisDefaultTarget() : ExegesisTarget({}) {}
+  ExegesisDefaultTarget() : ExegesisTarget({}, opcodeIsNotAvailable) {}
 
 private:
   std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.h
index 986ad98..3d6169c 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.h
@@ -29,6 +29,7 @@
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
 #include "llvm/TargetParser/Triple.h"
 
 namespace llvm {
@@ -58,6 +59,9 @@
   const IssueCounter *IssueCounters;
   unsigned NumIssueCounters;
 
+  const std::pair<ValidationEvent, const char *> *ValidationEvents;
+  unsigned NumValidationEvents;
+
   static const PfmCountersInfo Default;
   static const PfmCountersInfo Dummy;
 };
@@ -70,12 +74,15 @@
 
 class ExegesisTarget {
 public:
-  explicit ExegesisTarget(ArrayRef<CpuAndPfmCounters> CpuPfmCounters)
-      : CpuPfmCounters(CpuPfmCounters) {}
+  typedef bool (*OpcodeAvailabilityChecker)(unsigned, const FeatureBitset &);
+  ExegesisTarget(ArrayRef<CpuAndPfmCounters> CpuPfmCounters,
+                 OpcodeAvailabilityChecker IsOpcodeAvailable)
+      : CpuPfmCounters(CpuPfmCounters), IsOpcodeAvailable(IsOpcodeAvailable) {}
 
   // Targets can use this to create target-specific perf counters.
-  virtual Expected<std::unique_ptr<pfm::Counter>>
+  virtual Expected<std::unique_ptr<pfm::CounterGroup>>
   createCounter(StringRef CounterName, const LLVMState &State,
+                ArrayRef<const char *> ValidationCounters,
                 const pid_t ProcessID = 0) const;
 
   // Targets can use this to add target-specific passes in assembleToStream();
@@ -139,6 +146,12 @@
                        "current architecture\n");
   }
 
+  // Returns true if all features are available that are required by Opcode.
+  virtual bool isOpcodeAvailable(unsigned Opcode,
+                                 const FeatureBitset &Features) const {
+    return IsOpcodeAvailable(Opcode, Features);
+  }
+
   // Sets the stack register to the auxiliary memory so that operations
   // requiring the stack can be formed (e.g., setting large registers). The code
   // generated by this function may clobber registers.
@@ -253,6 +266,8 @@
       Benchmark::ModeE Mode, const LLVMState &State,
       BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
       BenchmarkRunner::ExecutionModeE ExecutionMode,
+      unsigned BenchmarkRepeatCount,
+      ArrayRef<ValidationEvent> ValidationCounters,
       Benchmark::ResultAggregationModeE ResultAggMode = Benchmark::Min) const;
 
   // Returns the ExegesisTarget for the given triple or nullptr if the target
@@ -296,14 +311,18 @@
       const LLVMState &State, Benchmark::ModeE Mode,
       BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
       Benchmark::ResultAggregationModeE ResultAggMode,
-      BenchmarkRunner::ExecutionModeE ExecutionMode) const;
+      BenchmarkRunner::ExecutionModeE ExecutionMode,
+      ArrayRef<ValidationEvent> ValidationCounters,
+      unsigned BenchmarkRepeatCount) const;
   std::unique_ptr<BenchmarkRunner> virtual createUopsBenchmarkRunner(
       const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
       Benchmark::ResultAggregationModeE ResultAggMode,
-      BenchmarkRunner::ExecutionModeE ExecutionMode) const;
+      BenchmarkRunner::ExecutionModeE ExecutionMode,
+      ArrayRef<ValidationEvent> ValidationCounters) const;
 
   const ExegesisTarget *Next = nullptr;
   const ArrayRef<CpuAndPfmCounters> CpuPfmCounters;
+  const OpcodeAvailabilityChecker IsOpcodeAvailable;
 };
 
 } // namespace exegesis
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.cpp
index 6351fdd..d6fb599 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.cpp
@@ -19,25 +19,45 @@
 UopsBenchmarkRunner::runMeasurements(const FunctionExecutor &Executor) const {
   std::vector<BenchmarkMeasure> Result;
   const PfmCountersInfo &PCI = State.getPfmCounters();
+
+  SmallVector<const char *> ValCountersToRun;
+  Error ValCounterErr = getValidationCountersToRun(ValCountersToRun);
+  if (ValCounterErr)
+    return std::move(ValCounterErr);
+
   // Uops per port.
   for (const auto *IssueCounter = PCI.IssueCounters,
                   *IssueCounterEnd = PCI.IssueCounters + PCI.NumIssueCounters;
        IssueCounter != IssueCounterEnd; ++IssueCounter) {
+    SmallVector<int64_t> ValCounterPortValues(ValCountersToRun.size(), -1);
     if (!IssueCounter->Counter)
       continue;
-    auto ExpectedCounterValue = Executor.runAndSample(IssueCounter->Counter);
+    auto ExpectedCounterValue = Executor.runAndSample(
+        IssueCounter->Counter, ValCountersToRun, ValCounterPortValues);
     if (!ExpectedCounterValue)
       return ExpectedCounterValue.takeError();
-    Result.push_back(BenchmarkMeasure::Create(IssueCounter->ProcResName,
-                                              (*ExpectedCounterValue)[0]));
+
+    std::map<ValidationEvent, int64_t> ValidationInfo;
+    for (size_t I = 0; I < ValidationCounters.size(); ++I)
+      ValidationInfo[ValidationCounters[I]] = ValCounterPortValues[I];
+
+    Result.push_back(BenchmarkMeasure::Create(
+        IssueCounter->ProcResName, (*ExpectedCounterValue)[0], ValidationInfo));
   }
   // NumMicroOps.
   if (const char *const UopsCounter = PCI.UopsCounter) {
-    auto ExpectedCounterValue = Executor.runAndSample(UopsCounter);
+    SmallVector<int64_t> ValCounterUopsValues(ValCountersToRun.size(), -1);
+    auto ExpectedCounterValue = Executor.runAndSample(
+        UopsCounter, ValCountersToRun, ValCounterUopsValues);
     if (!ExpectedCounterValue)
       return ExpectedCounterValue.takeError();
-    Result.push_back(
-        BenchmarkMeasure::Create("NumMicroOps", (*ExpectedCounterValue)[0]));
+
+    std::map<ValidationEvent, int64_t> ValidationInfo;
+    for (size_t I = 0; I < ValidationCounters.size(); ++I)
+      ValidationInfo[ValidationCounters[I]] = ValCounterUopsValues[I];
+
+    Result.push_back(BenchmarkMeasure::Create(
+        "NumMicroOps", (*ExpectedCounterValue)[0], ValidationInfo));
   }
   return std::move(Result);
 }
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h
index 337f093..ef47b7f 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h
@@ -15,6 +15,7 @@
 #define LLVM_TOOLS_LLVM_EXEGESIS_UOPSBENCHMARKRUNNER_H
 
 #include "BenchmarkRunner.h"
+#include "Target.h"
 
 namespace llvm {
 namespace exegesis {
@@ -23,9 +24,10 @@
 public:
   UopsBenchmarkRunner(const LLVMState &State,
                       BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
-                      ExecutionModeE ExecutionMode)
+                      ExecutionModeE ExecutionMode,
+                      ArrayRef<ValidationEvent> ValCounters)
       : BenchmarkRunner(State, Benchmark::Uops, BenchmarkPhaseSelector,
-                        ExecutionMode) {}
+                        ExecutionMode, ValCounters) {}
   ~UopsBenchmarkRunner() override;
 
   static constexpr const size_t kMinNumDifferentAddresses = 6;
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/Target.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
index b3d4080..adb345f 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/Target.cpp
@@ -8,6 +8,7 @@
 #include "../Target.h"
 
 #include "../Error.h"
+#include "../MmapUtils.h"
 #include "../ParallelSnippetGenerator.h"
 #include "../SerialSnippetGenerator.h"
 #include "../SnippetGenerator.h"
@@ -38,11 +39,20 @@
 #endif
 
 #ifdef __linux__
+#ifdef __x86_64__
+#include <asm/prctl.h>
+#endif // __x86_64__
 #include <sys/mman.h>
 #include <sys/syscall.h>
 #include <unistd.h>
+#ifdef HAVE_LIBPFM
+#include <perfmon/perf_event.h>
+#endif // HAVE_LIBPFM
 #endif
 
+#define GET_AVAILABLE_OPCODE_CHECKER
+#include "X86GenInstrInfo.inc"
+
 namespace llvm {
 namespace exegesis {
 
@@ -207,9 +217,9 @@
   const auto OpcodeName = Instr.Name;
   if ((Instr.Description.TSFlags & X86II::FormMask) == X86II::Pseudo)
     return "unsupported opcode: pseudo instruction";
-  if ((OpcodeName.startswith("POP") && !OpcodeName.startswith("POPCNT")) ||
-      OpcodeName.startswith("PUSH") || OpcodeName.startswith("ADJCALLSTACK") ||
-      OpcodeName.startswith("LEAVE"))
+  if ((OpcodeName.starts_with("POP") && !OpcodeName.starts_with("POPCNT")) ||
+      OpcodeName.starts_with("PUSH") ||
+      OpcodeName.starts_with("ADJCALLSTACK") || OpcodeName.starts_with("LEAVE"))
     return "unsupported opcode: Push/Pop/AdjCallStack/Leave";
   switch (Instr.Description.Opcode) {
   case X86::LFS16rm:
@@ -669,10 +679,12 @@
 
 class ExegesisX86Target : public ExegesisTarget {
 public:
-  ExegesisX86Target() : ExegesisTarget(X86CpuPfmCounters) {}
+  ExegesisX86Target()
+      : ExegesisTarget(X86CpuPfmCounters, X86_MC::isOpcodeAvailable) {}
 
-  Expected<std::unique_ptr<pfm::Counter>>
+  Expected<std::unique_ptr<pfm::CounterGroup>>
   createCounter(StringRef CounterName, const LLVMState &State,
+                ArrayRef<const char *> ValidationCounters,
                 const pid_t ProcessID) const override {
     // If LbrSamplingPeriod was provided, then ignore the
     // CounterName because we only have one for LBR.
@@ -681,6 +693,13 @@
       // __linux__ (for now)
 #if defined(HAVE_LIBPFM) && defined(LIBPFM_HAS_FIELD_CYCLES) &&                \
     defined(__linux__)
+      // TODO(boomanaiden154): Add in support for using validation counters when
+      // using LBR counters.
+      if (ValidationCounters.size() > 0)
+        return llvm::make_error<llvm::StringError>(
+            "Using LBR is not currently supported with validation counters",
+            llvm::errc::invalid_argument);
+
       return std::make_unique<X86LbrCounter>(
           X86LbrPerfEvent(LbrSamplingPeriod));
 #else
@@ -690,7 +709,8 @@
           llvm::errc::invalid_argument);
 #endif
     }
-    return ExegesisTarget::createCounter(CounterName, State, ProcessID);
+    return ExegesisTarget::createCounter(CounterName, State, ValidationCounters,
+                                         ProcessID);
   }
 
   enum ArgumentRegisters { CodeSize = X86::R12, AuxiliaryMemoryFD = X86::R13 };
@@ -902,9 +922,94 @@
       .addImm(X86::COND_NE);
 }
 
+void generateRegisterStackPush(unsigned int Register,
+                               std::vector<MCInst> &GeneratedCode) {
+  GeneratedCode.push_back(MCInstBuilder(X86::PUSH64r).addReg(Register));
+}
+
+void generateRegisterStackPop(unsigned int Register,
+                              std::vector<MCInst> &GeneratedCode) {
+  GeneratedCode.push_back(MCInstBuilder(X86::POP64r).addReg(Register));
+}
+
+void generateSyscall(long SyscallNumber, std::vector<MCInst> &GeneratedCode) {
+  GeneratedCode.push_back(
+      loadImmediate(X86::RAX, 64, APInt(64, SyscallNumber)));
+  GeneratedCode.push_back(MCInstBuilder(X86::SYSCALL));
+}
+
+// The functions below for saving and restoring system call registers are only
+// used when llvm-exegesis is built on Linux.
+#ifdef __linux__
+constexpr std::array<unsigned, 6> SyscallArgumentRegisters{
+    X86::RDI, X86::RSI, X86::RDX, X86::R10, X86::R8, X86::R9};
+
+static void saveSyscallRegisters(std::vector<MCInst> &GeneratedCode,
+                                 unsigned ArgumentCount) {
+  assert(ArgumentCount <= 6 &&
+         "System calls only X86-64 Linux can only take six arguments");
+  // Preserve RCX and R11 (Clobbered by the system call).
+  generateRegisterStackPush(X86::RCX, GeneratedCode);
+  generateRegisterStackPush(X86::R11, GeneratedCode);
+  // Preserve RAX (used for the syscall number/return value).
+  generateRegisterStackPush(X86::RAX, GeneratedCode);
+  // Preserve the registers used to pass arguments to the system call.
+  for (unsigned I = 0; I < ArgumentCount; ++I)
+    generateRegisterStackPush(SyscallArgumentRegisters[I], GeneratedCode);
+}
+
+static void restoreSyscallRegisters(std::vector<MCInst> &GeneratedCode,
+                                    unsigned ArgumentCount) {
+  assert(ArgumentCount <= 6 &&
+         "System calls only X86-64 Linux can only take six arguments");
+  // Restore the argument registers, in the opposite order of the way they are
+  // saved.
+  for (unsigned I = ArgumentCount; I > 0; --I) {
+    generateRegisterStackPop(SyscallArgumentRegisters[I - 1], GeneratedCode);
+  }
+  generateRegisterStackPop(X86::RAX, GeneratedCode);
+  generateRegisterStackPop(X86::R11, GeneratedCode);
+  generateRegisterStackPop(X86::RCX, GeneratedCode);
+}
+#endif // __linux__
+
+static std::vector<MCInst> loadImmediateSegmentRegister(unsigned Reg,
+                                                        const APInt &Value) {
+#if defined(__x86_64__) && defined(__linux__)
+  assert(Value.getBitWidth() <= 64 && "Value must fit in the register.");
+  std::vector<MCInst> loadSegmentRegisterCode;
+  // Preserve the syscall registers here as we don't
+  // want to make any assumptions about the ordering of what registers are
+  // loaded in first, and we might have already loaded in registers that we are
+  // going to be clobbering here.
+  saveSyscallRegisters(loadSegmentRegisterCode, 2);
+  // Generate the instructions to make the arch_prctl system call to set
+  // the registers.
+  int SyscallCode = 0;
+  if (Reg == X86::FS)
+    SyscallCode = ARCH_SET_FS;
+  else if (Reg == X86::GS)
+    SyscallCode = ARCH_SET_GS;
+  else
+    llvm_unreachable("Only the segment registers GS and FS are supported");
+  loadSegmentRegisterCode.push_back(
+      loadImmediate(X86::RDI, 64, APInt(64, SyscallCode)));
+  loadSegmentRegisterCode.push_back(loadImmediate(X86::RSI, 64, Value));
+  generateSyscall(SYS_arch_prctl, loadSegmentRegisterCode);
+  // Restore the registers in reverse order
+  restoreSyscallRegisters(loadSegmentRegisterCode, 2);
+  return loadSegmentRegisterCode;
+#else
+  llvm_unreachable("Loading immediate segment registers is only supported with "
+                   "x86-64 llvm-exegesis");
+#endif // defined(__x86_64__) && defined(__linux__)
+}
+
 std::vector<MCInst> ExegesisX86Target::setRegTo(const MCSubtargetInfo &STI,
                                                 unsigned Reg,
                                                 const APInt &Value) const {
+  if (X86::SEGMENT_REGRegClass.contains(Reg))
+    return loadImmediateSegmentRegister(Reg, Value);
   if (X86::GR8RegClass.contains(Reg))
     return {loadImmediate(Reg, 8, Value)};
   if (X86::GR16RegClass.contains(Reg))
@@ -987,12 +1092,6 @@
 static constexpr const intptr_t VAddressSpaceCeiling = 0x0000800000000000;
 #endif
 
-void generateSyscall(long SyscallNumber, std::vector<MCInst> &GeneratedCode) {
-  GeneratedCode.push_back(
-      loadImmediate(X86::RAX, 64, APInt(64, SyscallNumber)));
-  GeneratedCode.push_back(MCInstBuilder(X86::SYSCALL));
-}
-
 void generateRoundToNearestPage(unsigned int Register,
                                 std::vector<MCInst> &GeneratedCode) {
   int PageSizeShift = static_cast<int>(round(log2(getpagesize())));
@@ -1076,21 +1175,6 @@
   return ExitCallCode;
 }
 
-// Before kernel 4.17, Linux did not support MAP_FIXED_NOREPLACE, so if it is
-// not available, simplfy define it as MAP_FIXED which performs the same
-// function but does not guarantee existing mappings won't get clobbered.
-#ifndef MAP_FIXED_NOREPLACE
-#define MAP_FIXED_NOREPLACE MAP_FIXED
-#endif
-
-// Some 32-bit architectures don't have mmap and define mmap2 instead. The only
-// difference between the two syscalls is that mmap2's offset parameter is in
-// terms 4096 byte offsets rather than individual bytes, so for our purposes
-// they are effectively the same as all ofsets here are set to 0.
-#if defined(SYS_mmap2) && !defined(SYS_mmap)
-#define SYS_mmap SYS_mmap2
-#endif
-
 std::vector<MCInst>
 ExegesisX86Target::generateMmap(intptr_t Address, size_t Length,
                                 intptr_t FileDescriptorAddress) const {
@@ -1167,25 +1251,11 @@
   return VAddressSpaceCeiling - 2 * getpagesize();
 }
 
-void generateRegisterStackPush(unsigned int Register,
-                               std::vector<MCInst> &GeneratedCode) {
-  GeneratedCode.push_back(MCInstBuilder(X86::PUSH64r).addReg(Register));
-}
-
-void generateRegisterStackPop(unsigned int Register,
-                              std::vector<MCInst> &GeneratedCode) {
-  GeneratedCode.push_back(MCInstBuilder(X86::POP64r).addReg(Register));
-}
-
 std::vector<MCInst>
 ExegesisX86Target::configurePerfCounter(long Request, bool SaveRegisters) const {
   std::vector<MCInst> ConfigurePerfCounterCode;
-  if(SaveRegisters) {
-    // Preservie RAX, RDI, and RSI by pushing them to the stack.
-    generateRegisterStackPush(X86::RAX, ConfigurePerfCounterCode);
-    generateRegisterStackPush(X86::RDI, ConfigurePerfCounterCode);
-    generateRegisterStackPush(X86::RSI, ConfigurePerfCounterCode);
-  }
+  if (SaveRegisters)
+    saveSyscallRegisters(ConfigurePerfCounterCode, 3);
   ConfigurePerfCounterCode.push_back(
       loadImmediate(X86::RDI, 64, APInt(64, getAuxiliaryMemoryStartAddress())));
   ConfigurePerfCounterCode.push_back(MCInstBuilder(X86::MOV32rm)
@@ -1197,13 +1267,13 @@
                                          .addReg(0));
   ConfigurePerfCounterCode.push_back(
       loadImmediate(X86::RSI, 64, APInt(64, Request)));
+#ifdef HAVE_LIBPFM
+  ConfigurePerfCounterCode.push_back(
+      loadImmediate(X86::RDX, 64, APInt(64, PERF_IOC_FLAG_GROUP)));
+#endif // HAVE_LIBPFM
   generateSyscall(SYS_ioctl, ConfigurePerfCounterCode);
-  if(SaveRegisters) {
-    // Restore RAX, RDI, and RSI, in reverse order.
-    generateRegisterStackPop(X86::RSI, ConfigurePerfCounterCode);
-    generateRegisterStackPop(X86::RIP, ConfigurePerfCounterCode);
-    generateRegisterStackPop(X86::RAX, ConfigurePerfCounterCode);
-  }
+  if (SaveRegisters)
+    restoreSyscallRegisters(ConfigurePerfCounterCode, 3);
   return ConfigurePerfCounterCode;
 }
 
@@ -1212,7 +1282,7 @@
 }
 
 std::vector<unsigned> ExegesisX86Target::getRegistersNeedSaving() const {
-  return {X86::RAX, X86::RDI, X86::RSI};
+  return {X86::RAX, X86::RDI, X86::RSI, X86::RCX, X86::R11};
 }
 
 #endif // __linux__
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp
index 3fee0e5..26be9f8 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.cpp
@@ -87,7 +87,8 @@
       continue;
     }
     DataPtr += sizeof(Header);
-    uint64_t Count = llvm::support::endian::read64(DataPtr, support::native);
+    uint64_t Count =
+        llvm::support::endian::read64(DataPtr, llvm::endianness::native);
     DataPtr += sizeof(Count);
 
     struct perf_branch_entry Entry;
@@ -140,9 +141,9 @@
 }
 
 X86LbrCounter::X86LbrCounter(pfm::PerfEvent &&NewEvent)
-    : Counter(std::move(NewEvent)) {
+    : CounterGroup(std::move(NewEvent), {}) {
   MMappedBuffer = mmap(nullptr, kMappedBufferSize, PROT_READ | PROT_WRITE,
-                       MAP_SHARED, FileDescriptor, 0);
+                       MAP_SHARED, getFileDescriptor(), 0);
   if (MMappedBuffer == MAP_FAILED)
     llvm::errs() << "Failed to mmap buffer.";
 }
@@ -153,7 +154,7 @@
 }
 
 void X86LbrCounter::start() {
-  ioctl(FileDescriptor, PERF_EVENT_IOC_REFRESH, 1024 /* kMaxPollsPerFd */);
+  ioctl(getFileDescriptor(), PERF_EVENT_IOC_REFRESH, 1024 /* kMaxPollsPerFd */);
 }
 
 llvm::Error X86LbrCounter::checkLbrSupport() {
@@ -196,7 +197,7 @@
 llvm::Expected<llvm::SmallVector<int64_t, 4>>
 X86LbrCounter::readOrError(StringRef FunctionBytes) const {
   // Disable the event before reading
-  ioctl(FileDescriptor, PERF_EVENT_IOC_DISABLE, 0);
+  ioctl(getFileDescriptor(), PERF_EVENT_IOC_DISABLE, 0);
 
   // Find the boundary of the function so that we could filter the LBRs
   // to keep only the relevant records.
@@ -222,7 +223,7 @@
   int PollResult = 0;
 
   while (PollResult <= 0) {
-    PollResult = pollLbrPerfEvent(FileDescriptor);
+    PollResult = pollLbrPerfEvent(getFileDescriptor());
     if (PollResult > 0)
       break;
     if (PollResult == -1)
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.h
index 73e4dc5..bc2fced 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/X86Counter.h
@@ -31,7 +31,7 @@
   X86LbrPerfEvent(unsigned SamplingPeriod);
 };
 
-class X86LbrCounter : public pfm::Counter {
+class X86LbrCounter : public pfm::CounterGroup {
 public:
   static llvm::Error checkLbrSupport();
 
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/llvm-exegesis.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
index ff868e7..9b3fe76 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -262,6 +262,34 @@
                           "allows for the use of memory annotations")),
     cl::init(BenchmarkRunner::ExecutionModeE::InProcess));
 
+static cl::opt<unsigned> BenchmarkRepeatCount(
+    "benchmark-repeat-count",
+    cl::desc("The number of times to repeat measurements on the benchmark k "
+             "before aggregating the results"),
+    cl::cat(BenchmarkOptions), cl::init(30));
+
+static cl::list<ValidationEvent> ValidationCounters(
+    "validation-counter",
+    cl::desc(
+        "The name of a validation counter to run concurrently with the main "
+        "counter to validate benchmarking assumptions"),
+    cl::CommaSeparated, cl::cat(BenchmarkOptions),
+    cl::values(
+        clEnumValN(ValidationEvent::InstructionRetired, "instructions-retired",
+                   "Count retired instructions"),
+        clEnumValN(ValidationEvent::L1DCacheLoadMiss, "l1d-cache-load-misses",
+                   "Count L1D load cache misses"),
+        clEnumValN(ValidationEvent::L1DCacheStoreMiss, "l1d-cache-store-misses",
+                   "Count L1D store cache misses"),
+        clEnumValN(ValidationEvent::L1ICacheLoadMiss, "l1i-cache-load-misses",
+                   "Count L1I load cache misses"),
+        clEnumValN(ValidationEvent::DataTLBLoadMiss, "data-tlb-load-misses",
+                   "Count DTLB load misses"),
+        clEnumValN(ValidationEvent::DataTLBStoreMiss, "data-tlb-store-misses",
+                   "Count DTLB store misses"),
+        clEnumValN(ValidationEvent::InstructionTLBLoadMiss,
+                   "instruction-tlb-load-misses", "Count ITLB load misses")));
+
 static ExitOnError ExitOnErr("llvm-exegesis error: ");
 
 // Helper function that logs the error(s) and exits.
@@ -291,6 +319,9 @@
   const size_t NumSetFlags = (OpcodeNames.empty() ? 0 : 1) +
                              (OpcodeIndex == 0 ? 0 : 1) +
                              (SnippetsFile.empty() ? 0 : 1);
+  const auto &ET = State.getExegesisTarget();
+  const auto AvailableFeatures = State.getSubtargetInfo().getFeatureBits();
+
   if (NumSetFlags != 1) {
     ExitOnErr.setBanner("llvm-exegesis: ");
     ExitWithError("please provide one and only one of 'opcode-index', "
@@ -304,8 +335,11 @@
     std::vector<unsigned> Result;
     unsigned NumOpcodes = State.getInstrInfo().getNumOpcodes();
     Result.reserve(NumOpcodes);
-    for (unsigned I = 0, E = NumOpcodes; I < E; ++I)
+    for (unsigned I = 0, E = NumOpcodes; I < E; ++I) {
+      if (!ET.isOpcodeAvailable(I, AvailableFeatures))
+        continue;
       Result.push_back(I);
+    }
     return Result;
   }
   // Resolve opcode name -> opcode.
@@ -398,8 +432,18 @@
       std::optional<StringRef> DumpFile;
       if (DumpObjectToDisk.getNumOccurrences())
         DumpFile = DumpObjectToDisk;
-      AllResults.emplace_back(
-          ExitOnErr(Runner.runConfiguration(std::move(RC), DumpFile)));
+      auto [Err, BenchmarkResult] =
+          Runner.runConfiguration(std::move(RC), DumpFile);
+      if (Err) {
+        // Errors from executing the snippets are fine.
+        // All other errors are a framework issue and should fail.
+        if (!Err.isA<SnippetExecutionFailure>()) {
+          llvm::errs() << "llvm-exegesis error: " << toString(std::move(Err));
+          exit(1);
+        }
+        BenchmarkResult.Error = toString(std::move(Err));
+      }
+      AllResults.push_back(std::move(BenchmarkResult));
     }
     Benchmark &Result = AllResults.front();
 
@@ -415,7 +459,7 @@
            ArrayRef<Benchmark>(AllResults).drop_front()) {
         llvm::append_range(Result.AssembledSnippet,
                            OtherResult.AssembledSnippet);
-        // Aggregate measurements, but only iff all measurements succeeded.
+        // Aggregate measurements, but only if all measurements succeeded.
         if (Result.Measurements.empty())
           continue;
         assert(OtherResult.Measurements.size() == Result.Measurements.size() &&
@@ -471,10 +515,15 @@
   if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure)
     ExitOnErr(State.getExegesisTarget().checkFeatureSupport());
 
+  if (ExecutionMode == BenchmarkRunner::ExecutionModeE::SubProcess &&
+      UseDummyPerfCounters)
+    ExitWithError("Dummy perf counters are not supported in the subprocess "
+                  "execution mode.");
+
   const std::unique_ptr<BenchmarkRunner> Runner =
       ExitOnErr(State.getExegesisTarget().createBenchmarkRunner(
           BenchmarkMode, State, BenchmarkPhaseSelector, ExecutionMode,
-          ResultAggMode));
+          BenchmarkRepeatCount, ValidationCounters, ResultAggMode));
   if (!Runner) {
     ExitWithError("cannot create benchmark runner");
   }
@@ -492,11 +541,8 @@
   }
 
   BitVector AllReservedRegs;
-  llvm::for_each(Repetitors,
-                 [&AllReservedRegs](
-                     const std::unique_ptr<const SnippetRepetitor> &Repetitor) {
-                   AllReservedRegs |= Repetitor->getReservedRegs();
-                 });
+  for (const std::unique_ptr<const SnippetRepetitor> &Repetitor : Repetitors)
+    AllReservedRegs |= Repetitor->getReservedRegs();
 
   std::vector<BenchmarkCode> Configurations;
   if (!Opcodes.empty()) {
@@ -525,8 +571,10 @@
     for (const auto &Configuration : Configurations) {
       if (ExecutionMode != BenchmarkRunner::ExecutionModeE::SubProcess &&
           (Configuration.Key.MemoryMappings.size() != 0 ||
-           Configuration.Key.MemoryValues.size() != 0))
-        ExitWithError("Memory annotations are only supported in subprocess "
+           Configuration.Key.MemoryValues.size() != 0 ||
+           Configuration.Key.SnippetAddress != 0))
+        ExitWithError("Memory and snippet address annotations are only "
+                      "supported in subprocess "
                       "execution mode");
     }
   }
diff --git a/src/llvm-project/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp b/src/llvm-project/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
index 307248c..e5ae726 100644
--- a/src/llvm-project/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
+++ b/src/llvm-project/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/Object/Archive.h"
@@ -32,7 +31,6 @@
 #include <cstring>
 #include <inttypes.h>
 #include <iostream>
-#include <map>
 #include <optional>
 #include <string>
 #include <system_error>
@@ -58,9 +56,7 @@
 using namespace llvm::opt;
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -73,13 +69,7 @@
 #undef PREFIX
 
 const opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -221,14 +211,14 @@
   Triple ObjTriple(Obj.getArchTriple());
   StringRef ObjArch = ObjTriple.getArchName();
 
-  for (auto Arch : ArchFilters) {
+  for (StringRef Arch : ArchFilters) {
     // Match name.
     if (Arch == ObjArch)
       return true;
 
     // Match architecture number.
     unsigned Value;
-    if (!StringRef(Arch).getAsInteger(0, Value))
+    if (!Arch.getAsInteger(0, Value))
       if (Value == getCPUType(Obj))
         return true;
   }
@@ -238,7 +228,7 @@
 /// Determine the virtual address that is considered the base address of an ELF
 /// object file.
 ///
-/// The base address of an ELF file is the the "p_vaddr" of the first program
+/// The base address of an ELF file is the "p_vaddr" of the first program
 /// header whose "p_type" is PT_LOAD.
 ///
 /// \param ELFFile An ELF object file we will search.
@@ -315,6 +305,11 @@
   auto ThreadCount =
       NumThreads > 0 ? NumThreads : std::thread::hardware_concurrency();
   auto &OS = outs();
+  // Make a stream refernce that will become a /dev/null log stream if
+  // Quiet is true, or normal output if Quiet is false. This can stop the
+  // errors and warnings from being displayed and producing too much output
+  // when they aren't desired.
+  raw_ostream *LogOS = Quiet ? nullptr : &outs();
 
   GsymCreator Gsym(Quiet);
 
@@ -340,23 +335,30 @@
   }
 
   // Make sure there is DWARF to convert first.
-  std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(Obj);
+  std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(
+      Obj,
+      /*RelocAction=*/DWARFContext::ProcessDebugRelocations::Process,
+      nullptr,
+      /*DWPName=*/"",
+      /*RecoverableErrorHandler=*/WithColor::defaultErrorHandler,
+      /*WarningHandler=*/WithColor::defaultWarningHandler,
+      /*ThreadSafe*/true);
   if (!DICtx)
     return createStringError(std::errc::invalid_argument,
                              "unable to create DWARF context");
 
   // Make a DWARF transformer object and populate the ranges of the code
   // so we don't end up adding invalid functions to GSYM data.
-  DwarfTransformer DT(*DICtx, OS, Gsym);
+  DwarfTransformer DT(*DICtx, Gsym);
   if (!TextRanges.empty())
     Gsym.SetValidTextRanges(TextRanges);
 
   // Convert all DWARF to GSYM.
-  if (auto Err = DT.convert(ThreadCount))
+  if (auto Err = DT.convert(ThreadCount, LogOS))
     return Err;
 
   // Get the UUID and convert symbol table to GSYM.
-  if (auto Err = ObjectFileTransformer::convert(Obj, OS, Gsym))
+  if (auto Err = ObjectFileTransformer::convert(Obj, LogOS, Gsym))
     return Err;
 
   // Finalize the GSYM to make it ready to save to disk. This will remove
@@ -366,8 +368,9 @@
     return Err;
 
   // Save the GSYM file to disk.
-  support::endianness Endian =
-      Obj.makeTriple().isLittleEndian() ? support::little : support::big;
+  llvm::endianness Endian = Obj.makeTriple().isLittleEndian()
+                                ? llvm::endianness::little
+                                : llvm::endianness::big;
 
   std::optional<uint64_t> OptSegmentSize;
   if (SegmentSize > 0)
@@ -378,7 +381,7 @@
   // Verify the DWARF if requested. This will ensure all the info in the DWARF
   // can be looked up in the GSYM and that all lookups get matching data.
   if (Verify) {
-    if (auto Err = DT.verify(OutFile))
+    if (auto Err = DT.verify(OutFile, OS))
       return Err;
   }
 
@@ -465,10 +468,9 @@
     error(DsymObjectsOrErr.takeError());
   }
 
-  for (auto Object : Objects) {
-    if (auto Err = handleFileConversionToGSYM(Object, OutFile))
+  for (StringRef Object : Objects)
+    if (Error Err = handleFileConversionToGSYM(Object, OutFile))
       return Err;
-  }
   return Error::success();
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-ifs/llvm-ifs.cpp b/src/llvm-project/llvm/tools/llvm-ifs/llvm-ifs.cpp
index 0d2744f..ed660bc 100644
--- a/src/llvm-project/llvm/tools/llvm-ifs/llvm-ifs.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ifs/llvm-ifs.cpp
@@ -54,9 +54,7 @@
 using namespace llvm::opt;
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -69,13 +67,7 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
diff --git a/src/llvm-project/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp b/src/llvm-project/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
index eda165d..742f7b9 100644
--- a/src/llvm-project/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-isel-fuzzer/llvm-isel-fuzzer.cpp
@@ -99,7 +99,7 @@
   TargetLibraryInfoImpl TLII(TM->getTargetTriple());
   PM.add(new TargetLibraryInfoWrapperPass(TLII));
   raw_null_ostream OS;
-  TM->addPassesToEmitFile(PM, OS, nullptr, CGFT_Null);
+  TM->addPassesToEmitFile(PM, OS, nullptr, CodeGenFileType::Null);
   PM.run(*M);
 
   return 0;
@@ -129,33 +129,18 @@
     exit(1);
   }
 
-  Triple TheTriple = Triple(Triple::normalize(TargetTriple));
-
-  // Get the target specific parser.
-  std::string Error;
-  const Target *TheTarget =
-      TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error);
-  if (!TheTarget) {
-    errs() << argv[0] << ": " << Error;
-    return 1;
-  }
-
   // Set up the pipeline like llc does.
-  std::string CPUStr = codegen::getCPUStr(),
-              FeaturesStr = codegen::getFeaturesStr();
 
-  CodeGenOpt::Level OLvl;
+  CodeGenOptLevel OLvl;
   if (auto Level = CodeGenOpt::parseLevel(OptLevel)) {
     OLvl = *Level;
   } else {
     errs() << argv[0] << ": invalid optimization level.\n";
     return 1;
   }
-
-  TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(TheTriple);
-  TM.reset(TheTarget->createTargetMachine(
-      TheTriple.getTriple(), CPUStr, FeaturesStr, Options,
-      codegen::getExplicitRelocModel(), codegen::getExplicitCodeModel(), OLvl));
+  ExitOnError ExitOnErr(std::string(*argv[0]) + ": error:");
+  TM = ExitOnErr(codegen::createTargetMachineForTriple(
+      Triple::normalize(TargetTriple), OLvl));
   assert(TM && "Could not allocate target machine!");
 
   // Make sure we print the summary and the current unit when LLVM errors out.
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt
index a9f8bd1..c9d1d23 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt
@@ -11,6 +11,7 @@
   JITLink
   MC
   Object
+  OrcDebugging
   OrcJIT
   OrcShared
   OrcTargetProcess
@@ -27,12 +28,8 @@
   llvm-jitlink-statistics.cpp
   )
 
-if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
-  target_link_libraries(llvm-jitlink PRIVATE network)
-endif()
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
-  target_link_libraries(llvm-jitlink PRIVATE socket nsl)
-endif()
+ if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
+  target_link_libraries(llvm-jitlink PRIVATE socket)
+ endif()
 
 export_executable_symbols(llvm-jitlink)
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp
index 415aee7..5271fdb 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-coff.cpp
@@ -108,32 +108,17 @@
       if (Sym->getAddress() > LastSym->getAddress())
         LastSym = Sym;
 
-      if (isGOTSection) {
-        if (Sym->isSymbolZeroFill())
-          return make_error<StringError>("zero-fill atom in GOT section",
-                                         inconvertibleErrorCode());
-
-        // If this is a GOT symbol with size (i.e. not the GOT start symbol)
-        // then add it to the GOT entry info table.
-        if (Sym->getSize() != 0) {
-          if (auto TS = getCOFFGOTTarget(G, Sym->getBlock()))
-            FileInfo.GOTEntryInfos[TS->getName()] = {
-                Sym->getSymbolContent(), Sym->getAddress().getValue()};
-          else
-            return TS.takeError();
+      if (isGOTSection || isStubsSection) {
+        if (isGOTSection) {
+          // Skip the GOT start symbol
+          if (Sym->getSize() != 0)
+            if (Error E = FileInfo.registerGOTEntry(G, *Sym, getCOFFGOTTarget))
+              return E;
+        } else {
+          if (Error E = FileInfo.registerStubEntry(G, *Sym, getCOFFStubTarget))
+            return E;
         }
         SectionContainsContent = true;
-      } else if (isStubsSection) {
-        if (Sym->isSymbolZeroFill())
-          return make_error<StringError>("zero-fill atom in Stub section",
-                                         inconvertibleErrorCode());
-
-        if (auto TS = getCOFFStubTarget(G, Sym->getBlock()))
-          FileInfo.StubInfos[TS->getName()] = {Sym->getSymbolContent(),
-                                               Sym->getAddress().getValue()};
-        else
-          return TS.takeError();
-        SectionContainsContent = true;
       }
 
       if (Sym->hasName()) {
@@ -143,7 +128,8 @@
           SectionContainsZeroFill = true;
         } else {
           S.SymbolInfos[Sym->getName()] = {Sym->getSymbolContent(),
-                                           Sym->getAddress().getValue()};
+                                           Sym->getAddress().getValue(),
+                                           Sym->getTargetFlags()};
           SectionContainsContent = true;
         }
       }
@@ -164,7 +150,7 @@
     else
       FileInfo.SectionInfos[Sec.getName()] = {
           ArrayRef<char>(FirstSym->getBlock().getContent().data(), SecSize),
-          SecAddr.getValue()};
+          SecAddr.getValue(), FirstSym->getTargetFlags()};
   }
 
   return Error::success();
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
index 5200dbc..a8c804a 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-elf.cpp
@@ -24,6 +24,10 @@
 
 static bool isELFStubsSection(Section &S) { return S.getName() == "$__STUBS"; }
 
+static bool isELFAArch32StubsSection(Section &S) {
+  return S.getName().starts_with("__llvm_jitlink_aarch32_STUBS_");
+}
+
 static Expected<Edge &> getFirstRelocationEdge(LinkGraph &G, Block &B) {
   auto EItr =
       llvm::find_if(B.edges(), [](Edge &E) { return E.isRelocation(); });
@@ -55,7 +59,11 @@
   if (!E)
     return E.takeError();
   auto &GOTSym = E->getTarget();
-  if (!GOTSym.isDefined() || !isELFGOTSection(GOTSym.getBlock().getSection()))
+  if (!GOTSym.isDefined())
+    return make_error<StringError>("Stubs entry in " + G.getName() +
+                                       " does not point to GOT entry",
+                                   inconvertibleErrorCode());
+  if (!isELFGOTSection(GOTSym.getBlock().getSection()))
     return make_error<StringError>(
         "Stubs entry in " + G.getName() + ", \"" +
             GOTSym.getBlock().getSection().getName() +
@@ -64,6 +72,32 @@
   return getELFGOTTarget(G, GOTSym.getBlock());
 }
 
+static Expected<Symbol &> getELFAArch32StubTarget(LinkGraph &G, Block &B) {
+  auto E = getFirstRelocationEdge(G, B);
+  if (!E)
+    return E.takeError();
+  return E->getTarget();
+}
+
+enum SectionType { GOT, Stubs, AArch32Stubs, Other };
+
+static Error registerSymbol(LinkGraph &G, Symbol &Sym, Session::FileInfo &FI,
+                            SectionType SecType) {
+  switch (SecType) {
+  case GOT:
+    if (Sym.getSize() == 0)
+      return Error::success(); // Skip the GOT start symbol
+    return FI.registerGOTEntry(G, Sym, getELFGOTTarget);
+  case Stubs:
+    return FI.registerStubEntry(G, Sym, getELFStubTarget);
+  case AArch32Stubs:
+    return FI.registerMultiStubEntry(G, Sym, getELFAArch32StubTarget);
+  case Other:
+    return Error::success();
+  }
+  llvm_unreachable("Unhandled SectionType enum");
+}
+
 namespace llvm {
 
 Error registerELFGraphInfo(Session &S, LinkGraph &G) {
@@ -96,8 +130,16 @@
                                          "\"",
                                      inconvertibleErrorCode());
 
-    bool isGOTSection = isELFGOTSection(Sec);
-    bool isStubsSection = isELFStubsSection(Sec);
+    SectionType SecType;
+    if (isELFGOTSection(Sec)) {
+      SecType = GOT;
+    } else if (isELFStubsSection(Sec)) {
+      SecType = Stubs;
+    } else if (isELFAArch32StubsSection(Sec)) {
+      SecType = AArch32Stubs;
+    } else {
+      SecType = Other;
+    }
 
     bool SectionContainsContent = false;
     bool SectionContainsZeroFill = false;
@@ -110,31 +152,9 @@
       if (Sym->getAddress() > LastSym->getAddress())
         LastSym = Sym;
 
-      if (isGOTSection) {
-        if (Sym->isSymbolZeroFill())
-          return make_error<StringError>("zero-fill atom in GOT section",
-                                         inconvertibleErrorCode());
-
-        // If this is a GOT symbol with size (i.e. not the GOT start symbol)
-        // then add it to the GOT entry info table.
-        if (Sym->getSize() != 0) {
-          if (auto TS = getELFGOTTarget(G, Sym->getBlock()))
-            FileInfo.GOTEntryInfos[TS->getName()] = {
-                Sym->getSymbolContent(), Sym->getAddress().getValue()};
-          else
-            return TS.takeError();
-        }
-        SectionContainsContent = true;
-      } else if (isStubsSection) {
-        if (Sym->isSymbolZeroFill())
-          return make_error<StringError>("zero-fill atom in Stub section",
-                                         inconvertibleErrorCode());
-
-        if (auto TS = getELFStubTarget(G, Sym->getBlock()))
-          FileInfo.StubInfos[TS->getName()] = {Sym->getSymbolContent(),
-                                               Sym->getAddress().getValue()};
-        else
-          return TS.takeError();
+      if (SecType != Other) {
+        if (Error Err = registerSymbol(G, *Sym, FileInfo, SecType))
+          return Err;
         SectionContainsContent = true;
       }
 
@@ -145,7 +165,8 @@
           SectionContainsZeroFill = true;
         } else {
           S.SymbolInfos[Sym->getName()] = {Sym->getSymbolContent(),
-                                           Sym->getAddress().getValue()};
+                                           Sym->getAddress().getValue(),
+                                           Sym->getTargetFlags()};
           SectionContainsContent = true;
         }
       }
@@ -170,7 +191,7 @@
     else
       FileInfo.SectionInfos[Sec.getName()] = {
           ArrayRef<char>(FirstSym->getBlock().getContent().data(), SecSize),
-          SecAddr.getValue()};
+          SecAddr.getValue(), FirstSym->getTargetFlags()};
   }
 
   return Error::success();
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt
index 7e4570c..f6d882d 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/CMakeLists.txt
@@ -11,12 +11,4 @@
   intrinsics_gen
 )
 
-if(${CMAKE_SYSTEM_NAME} MATCHES "Haiku")
-  target_link_libraries(llvm-jitlink-executor PRIVATE network)
-endif()
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "SunOS")
-  target_link_libraries(llvm-jitlink-executor PRIVATE socket)
-endif()
-
 export_executable_symbols(llvm-jitlink-executor)
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp
index 71c83f2..c98bb26 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-executor/llvm-jitlink-executor.cpp
@@ -54,9 +54,9 @@
   errs() << "error: " << ErrMsg.str() << "\n\n"
          << "Usage:\n"
          << "  llvm-jitlink-executor " << DebugOption
-         << "filedescs=<infd>,<outfd> [args...]\n"
+         << "[test-jitloadergdb] filedescs=<infd>,<outfd> [args...]\n"
          << "  llvm-jitlink-executor " << DebugOption
-         << "listen=<host>:<port> [args...]\n";
+         << "[test-jitloadergdb] listen=<host>:<port> [args...]\n";
   exit(1);
 }
 
@@ -112,6 +112,21 @@
 #endif // LLVM_ON_UNIX
 }
 
+#if LLVM_ENABLE_THREADS
+
+// JITLink debug support plugins put information about JITed code in this GDB
+// JIT Interface global from OrcTargetProcess.
+extern "C" struct jit_descriptor __jit_debug_descriptor;
+
+static void *findLastDebugDescriptorEntryPtr() {
+  struct jit_code_entry *Last = __jit_debug_descriptor.first_entry;
+  while (Last && Last->next_entry)
+    Last = Last->next_entry;
+  return Last;
+}
+
+#endif
+
 int main(int argc, char *argv[]) {
 #if LLVM_ENABLE_THREADS
 
@@ -123,39 +138,46 @@
 
   if (argc < 2)
     printErrorAndExit("insufficient arguments");
-  else {
 
-    StringRef ConnectArg = argv[FirstProgramArg++];
+  StringRef NextArg = argv[FirstProgramArg++];
 #ifndef NDEBUG
-    if (ConnectArg == "debug") {
-      DebugFlag = true;
-      ConnectArg = argv[FirstProgramArg++];
-    }
+  if (NextArg == "debug") {
+    DebugFlag = true;
+    NextArg = argv[FirstProgramArg++];
+  }
 #endif
 
-    StringRef SpecifierType, Specifier;
-    std::tie(SpecifierType, Specifier) = ConnectArg.split('=');
-    if (SpecifierType == "filedescs") {
-      StringRef FD1Str, FD2Str;
-      std::tie(FD1Str, FD2Str) = Specifier.split(',');
-      if (FD1Str.getAsInteger(10, InFD))
-        printErrorAndExit(FD1Str + " is not a valid file descriptor");
-      if (FD2Str.getAsInteger(10, OutFD))
-        printErrorAndExit(FD2Str + " is not a valid file descriptor");
-    } else if (SpecifierType == "listen") {
-      StringRef Host, PortStr;
-      std::tie(Host, PortStr) = Specifier.split(':');
-
-      int Port = 0;
-      if (PortStr.getAsInteger(10, Port))
-        printErrorAndExit("port number '" + PortStr +
-                          "' is not a valid integer");
-
-      InFD = OutFD = openListener(Host.str(), PortStr.str());
-    } else
-      printErrorAndExit("invalid specifier type \"" + SpecifierType + "\"");
+  std::vector<StringRef> TestOutputFlags;
+  while (NextArg.starts_with("test-")) {
+    TestOutputFlags.push_back(NextArg);
+    NextArg = argv[FirstProgramArg++];
   }
 
+  if (llvm::is_contained(TestOutputFlags, "test-jitloadergdb"))
+    fprintf(stderr, "__jit_debug_descriptor.last_entry = 0x%016" PRIx64 "\n",
+            pointerToJITTargetAddress(findLastDebugDescriptorEntryPtr()));
+
+  StringRef SpecifierType, Specifier;
+  std::tie(SpecifierType, Specifier) = NextArg.split('=');
+  if (SpecifierType == "filedescs") {
+    StringRef FD1Str, FD2Str;
+    std::tie(FD1Str, FD2Str) = Specifier.split(',');
+    if (FD1Str.getAsInteger(10, InFD))
+      printErrorAndExit(FD1Str + " is not a valid file descriptor");
+    if (FD2Str.getAsInteger(10, OutFD))
+      printErrorAndExit(FD2Str + " is not a valid file descriptor");
+  } else if (SpecifierType == "listen") {
+    StringRef Host, PortStr;
+    std::tie(Host, PortStr) = Specifier.split(':');
+
+    int Port = 0;
+    if (PortStr.getAsInteger(10, Port))
+      printErrorAndExit("port number '" + PortStr + "' is not a valid integer");
+
+    InFD = OutFD = openListener(Host.str(), PortStr.str());
+  } else
+    printErrorAndExit("invalid specifier type \"" + SpecifierType + "\"");
+
   auto Server =
       ExitOnErr(SimpleRemoteEPCServer::Create<FDSimpleRemoteEPCTransport>(
           [](SimpleRemoteEPCServer::Setup &S) -> Error {
@@ -173,6 +195,11 @@
           InFD, OutFD));
 
   ExitOnErr(Server->waitForDisconnect());
+
+  if (llvm::is_contained(TestOutputFlags, "test-jitloadergdb"))
+    fprintf(stderr, "__jit_debug_descriptor.last_entry = 0x%016" PRIx64 "\n",
+            pointerToJITTargetAddress(findLastDebugDescriptorEntryPtr()));
+
   return 0;
 
 #else
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
index bcb2f25..2c60c80 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink-macho.cpp
@@ -111,27 +111,13 @@
         FirstSym = Sym;
       if (Sym->getAddress() > LastSym->getAddress())
         LastSym = Sym;
-      if (isGOTSection) {
-        if (Sym->isSymbolZeroFill())
-          return make_error<StringError>("zero-fill atom in GOT section",
-                                         inconvertibleErrorCode());
-
-        if (auto TS = getMachOGOTTarget(G, Sym->getBlock()))
-          FileInfo.GOTEntryInfos[TS->getName()] = {
-              Sym->getSymbolContent(), Sym->getAddress().getValue()};
-        else
-          return TS.takeError();
-        SectionContainsContent = true;
-      } else if (isStubsSection) {
-        if (Sym->isSymbolZeroFill())
-          return make_error<StringError>("zero-fill atom in Stub section",
-                                         inconvertibleErrorCode());
-
-        if (auto TS = getMachOStubTarget(G, Sym->getBlock()))
-          FileInfo.StubInfos[TS->getName()] = {Sym->getSymbolContent(),
-                                               Sym->getAddress().getValue()};
-        else
-          return TS.takeError();
+      if (isGOTSection || isStubsSection) {
+        Error Err =
+            isGOTSection
+                ? FileInfo.registerGOTEntry(G, *Sym, getMachOGOTTarget)
+                : FileInfo.registerStubEntry(G, *Sym, getMachOStubTarget);
+        if (Err)
+          return Err;
         SectionContainsContent = true;
       } else if (Sym->hasName()) {
         if (Sym->isSymbolZeroFill()) {
@@ -140,7 +126,8 @@
           SectionContainsZeroFill = true;
         } else {
           S.SymbolInfos[Sym->getName()] = {Sym->getSymbolContent(),
-                                           Sym->getAddress().getValue()};
+                                           Sym->getAddress().getValue(),
+                                           Sym->getTargetFlags()};
           SectionContainsContent = true;
         }
       }
@@ -160,7 +147,7 @@
     else
       FileInfo.SectionInfos[Sec.getName()] = {
           ArrayRef<char>(FirstSym->getBlock().getContent().data(), SecSize),
-          SecAddr.getValue()};
+          SecAddr.getValue(), FirstSym->getTargetFlags()};
   }
 
   return Error::success();
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.cpp b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
index 00dd520..769ed17 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -18,7 +18,9 @@
 #include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
 #include "llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h"
 #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
-#include "llvm/ExecutionEngine/Orc/DebuggerSupportPlugin.h"
+#include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h"
+#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupportPlugin.h"
+#include "llvm/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.h"
 #include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
 #include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
 #include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
@@ -30,6 +32,7 @@
 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
 #include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
@@ -55,7 +58,6 @@
 
 #include <cstring>
 #include <deque>
-#include <list>
 #include <string>
 
 #ifdef LLVM_ON_UNIX
@@ -140,6 +142,11 @@
                     cl::desc("Enable debugger suppport (default = !-noexec)"),
                     cl::init(true), cl::Hidden, cl::cat(JITLinkCategory));
 
+static cl::opt<bool> PerfSupport("perf-support",
+                                 cl::desc("Enable perf profiling support"),
+                                 cl::init(false), cl::Hidden,
+                                 cl::cat(JITLinkCategory));
+
 static cl::opt<bool>
     NoProcessSymbols("no-process-syms",
                      cl::desc("Do not resolve to llvm-jitlink process symbols"),
@@ -243,10 +250,14 @@
 static ExitOnError ExitOnErr;
 
 static LLVM_ATTRIBUTE_USED void linkComponents() {
-  errs() << (void *)&llvm_orc_registerEHFrameSectionWrapper
-         << (void *)&llvm_orc_deregisterEHFrameSectionWrapper
-         << (void *)&llvm_orc_registerJITLoaderGDBWrapper
-         << (void *)&llvm_orc_registerJITLoaderGDBAllocAction;
+  errs() << "Linking in runtime functions\n"
+         << (void *)&llvm_orc_registerEHFrameSectionWrapper << '\n'
+         << (void *)&llvm_orc_deregisterEHFrameSectionWrapper << '\n'
+         << (void *)&llvm_orc_registerJITLoaderGDBWrapper << '\n'
+         << (void *)&llvm_orc_registerJITLoaderGDBAllocAction << '\n'
+         << (void *)&llvm_orc_registerJITLoaderPerfStart << '\n'
+         << (void *)&llvm_orc_registerJITLoaderPerfEnd << '\n'
+         << (void *)&llvm_orc_registerJITLoaderPerfImpl << '\n';
 }
 
 static bool UseTestResultOverride = false;
@@ -320,8 +331,12 @@
     OS << "  Section \"" << SIKV.first() << "\": " << SIKV.second << "\n";
   for (auto &GOTKV : FI.GOTEntryInfos)
     OS << "  GOT \"" << GOTKV.first() << "\": " << GOTKV.second << "\n";
-  for (auto &StubKV : FI.StubInfos)
-    OS << "  Stub \"" << StubKV.first() << "\": " << StubKV.second << "\n";
+  for (auto &StubKVs : FI.StubInfos) {
+    OS << "  Stubs \"" << StubKVs.first() << "\":";
+    for (auto MemRegion : StubKVs.second)
+      OS << " " << MemRegion;
+    OS << "\n";
+  }
   return OS;
 }
 
@@ -501,7 +516,7 @@
     auto FixedAI = std::move(AI);
     FixedAI.MappingBase -= DeltaAddr;
     for (auto &Seg : FixedAI.Segments)
-      Seg.AG = {MemProt::Read | MemProt::Write, Seg.AG.getMemLifetimePolicy()};
+      Seg.AG = {MemProt::Read | MemProt::Write, Seg.AG.getMemLifetime()};
     FixedAI.Actions.clear();
     InProcessMemoryMapper::initialize(
         FixedAI, [this, OnInitialized = std::move(OnInitialized)](
@@ -681,11 +696,12 @@
 }
 
 static Error loadProcessSymbols(Session &S) {
+  S.ProcessSymsJD = &S.ES.createBareJITDylib("Process");
   auto FilterMainEntryPoint =
       [EPName = S.ES.intern(EntryPointName)](SymbolStringPtr Name) {
         return Name != EPName;
       };
-  S.MainJD->addGenerator(
+  S.ProcessSymsJD->addGenerator(
       ExitOnErr(orc::EPCDynamicLibrarySearchGenerator::GetForTargetProcess(
           S.ES, std::move(FilterMainEntryPoint))));
 
@@ -696,8 +712,9 @@
   LLVM_DEBUG(dbgs() << "Loading dylibs...\n");
   for (const auto &Dylib : Dylibs) {
     LLVM_DEBUG(dbgs() << "  " << Dylib << "\n");
-    if (auto Err = S.loadAndLinkDynamicLibrary(*S.MainJD, Dylib))
-      return Err;
+    auto DL = S.getOrLoadDynamicLibrary(Dylib);
+    if (!DL)
+      return DL.takeError();
   }
 
   return Error::success();
@@ -952,63 +969,79 @@
 
   ES.setErrorReporter(reportLLVMJITLinkError);
 
-  if (auto MainJDOrErr = ES.createJITDylib("main"))
-    MainJD = &*MainJDOrErr;
-  else {
-    Err = MainJDOrErr.takeError();
-    return;
-  }
-
   if (!NoProcessSymbols)
     ExitOnErr(loadProcessSymbols(*this));
-  else {
-    // This symbol is used in testcases.
-    auto &TestResultJD = ES.createBareJITDylib("<TestResultJD>");
-    ExitOnErr(TestResultJD.define(absoluteSymbols(
-        {{ES.intern("llvm_jitlink_setTestResultOverride"),
-          {ExecutorAddr::fromPtr(llvm_jitlink_setTestResultOverride),
-           JITSymbolFlags::Exported}}})));
-    MainJD->addToLinkOrder(TestResultJD);
-  }
 
   ExitOnErr(loadDylibs(*this));
 
   auto &TT = ES.getTargetTriple();
 
-  if (DebuggerSupport && TT.isOSBinFormatMachO())
-    ObjLayer.addPlugin(ExitOnErr(
-        GDBJITDebugInfoRegistrationPlugin::Create(this->ES, *MainJD, TT)));
+  if (DebuggerSupport && TT.isOSBinFormatMachO()) {
+    if (!ProcessSymsJD) {
+      Err = make_error<StringError>("MachO debugging requires process symbols",
+                                    inconvertibleErrorCode());
+      return;
+    }
+    ObjLayer.addPlugin(ExitOnErr(GDBJITDebugInfoRegistrationPlugin::Create(
+        this->ES, *ProcessSymsJD, TT)));
+  }
+
+  if (PerfSupport && TT.isOSBinFormatELF()) {
+    if (!ProcessSymsJD) {
+      Err = make_error<StringError>("MachO debugging requires process symbols",
+                                    inconvertibleErrorCode());
+      return;
+    }
+    ObjLayer.addPlugin(ExitOnErr(DebugInfoPreservationPlugin::Create()));
+    ObjLayer.addPlugin(ExitOnErr(PerfSupportPlugin::Create(
+        this->ES.getExecutorProcessControl(), *ProcessSymsJD, true, true)));
+  }
 
   // Set up the platform.
-  if (TT.isOSBinFormatMachO() && !OrcRuntime.empty()) {
-    if (auto P =
-            MachOPlatform::Create(ES, ObjLayer, *MainJD, OrcRuntime.c_str()))
-      ES.setPlatform(std::move(*P));
-    else {
-      Err = P.takeError();
-      return;
-    }
-  } else if (TT.isOSBinFormatELF() && !OrcRuntime.empty()) {
-    if (auto P =
-            ELFNixPlatform::Create(ES, ObjLayer, *MainJD, OrcRuntime.c_str()))
-      ES.setPlatform(std::move(*P));
-    else {
-      Err = P.takeError();
-      return;
-    }
-  } else if (TT.isOSBinFormatCOFF() && !OrcRuntime.empty()) {
-    auto LoadDynLibrary = [&, this](JITDylib &JD, StringRef DLLName) -> Error {
-      if (!DLLName.ends_with_insensitive(".dll"))
-        return make_error<StringError>("DLLName not ending with .dll",
-                                       inconvertibleErrorCode());
-      return loadAndLinkDynamicLibrary(JD, DLLName);
-    };
+  if (!OrcRuntime.empty()) {
+    assert(ProcessSymsJD && "ProcessSymsJD should have been set");
+    PlatformJD = &ES.createBareJITDylib("Platform");
+    PlatformJD->addToLinkOrder(*ProcessSymsJD);
 
-    if (auto P = COFFPlatform::Create(ES, ObjLayer, *MainJD, OrcRuntime.c_str(),
-                                      std::move(LoadDynLibrary))) 
-      ES.setPlatform(std::move(*P));
-     else {
-      Err = P.takeError();
+    if (TT.isOSBinFormatMachO()) {
+      if (auto P = MachOPlatform::Create(ES, ObjLayer, *PlatformJD,
+                                         OrcRuntime.c_str()))
+        ES.setPlatform(std::move(*P));
+      else {
+        Err = P.takeError();
+        return;
+      }
+    } else if (TT.isOSBinFormatELF()) {
+      if (auto P = ELFNixPlatform::Create(ES, ObjLayer, *PlatformJD,
+                                          OrcRuntime.c_str()))
+        ES.setPlatform(std::move(*P));
+      else {
+        Err = P.takeError();
+        return;
+      }
+    } else if (TT.isOSBinFormatCOFF()) {
+      auto LoadDynLibrary = [&, this](JITDylib &JD,
+                                      StringRef DLLName) -> Error {
+        if (!DLLName.ends_with_insensitive(".dll"))
+          return make_error<StringError>("DLLName not ending with .dll",
+                                         inconvertibleErrorCode());
+        return loadAndLinkDynamicLibrary(JD, DLLName);
+      };
+
+      if (auto P = COFFPlatform::Create(ES, ObjLayer, *PlatformJD,
+                                        OrcRuntime.c_str(),
+                                        std::move(LoadDynLibrary)))
+        ES.setPlatform(std::move(*P));
+      else {
+        Err = P.takeError();
+        return;
+      }
+    } else {
+      Err = make_error<StringError>(
+          "-" + OrcRuntime.ArgStr + " specified, but format " +
+              Triple::getObjectFormatTypeName(TT.getObjectFormat()) +
+              " not supported",
+          inconvertibleErrorCode());
       return;
     }
   } else if (TT.isOSBinFormatELF()) {
@@ -1020,6 +1053,24 @@
           ES, ExitOnErr(createJITLoaderGDBRegistrar(this->ES)), true, true));
   }
 
+  if (auto MainJDOrErr = ES.createJITDylib("main"))
+    MainJD = &*MainJDOrErr;
+  else {
+    Err = MainJDOrErr.takeError();
+    return;
+  }
+
+  if (NoProcessSymbols) {
+    // This symbol is used in testcases, but we're not reflecting process
+    // symbols so we'll need to make it available some other way.
+    auto &TestResultJD = ES.createBareJITDylib("<TestResultJD>");
+    ExitOnErr(TestResultJD.define(absoluteSymbols(
+        {{ES.intern("llvm_jitlink_setTestResultOverride"),
+          {ExecutorAddr::fromPtr(llvm_jitlink_setTestResultOverride),
+           JITSymbolFlags::Exported}}})));
+    MainJD->addToLinkOrder(TestResultJD);
+  }
+
   ObjLayer.addPlugin(std::make_unique<JITLinkSessionPlugin>(*this));
 
   // Process any harness files.
@@ -1136,6 +1187,62 @@
   return Error::success();
 }
 
+Error Session::FileInfo::registerGOTEntry(
+    LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {
+  if (Sym.isSymbolZeroFill())
+    return make_error<StringError>("Unexpected zero-fill symbol in section " +
+                                       Sym.getBlock().getSection().getName(),
+                                   inconvertibleErrorCode());
+  auto TS = GetSymbolTarget(G, Sym.getBlock());
+  if (!TS)
+    return TS.takeError();
+  GOTEntryInfos[TS->getName()] = {Sym.getSymbolContent(),
+                                  Sym.getAddress().getValue(),
+                                  Sym.getTargetFlags()};
+  return Error::success();
+}
+
+Error Session::FileInfo::registerStubEntry(
+    LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {
+  if (Sym.isSymbolZeroFill())
+    return make_error<StringError>("Unexpected zero-fill symbol in section " +
+                                       Sym.getBlock().getSection().getName(),
+                                   inconvertibleErrorCode());
+  auto TS = GetSymbolTarget(G, Sym.getBlock());
+  if (!TS)
+    return TS.takeError();
+
+  SmallVectorImpl<MemoryRegionInfo> &Entry = StubInfos[TS->getName()];
+  Entry.insert(Entry.begin(),
+               {Sym.getSymbolContent(), Sym.getAddress().getValue(),
+                Sym.getTargetFlags()});
+  return Error::success();
+}
+
+Error Session::FileInfo::registerMultiStubEntry(
+    LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {
+  if (Sym.isSymbolZeroFill())
+    return make_error<StringError>("Unexpected zero-fill symbol in section " +
+                                       Sym.getBlock().getSection().getName(),
+                                   inconvertibleErrorCode());
+
+  auto Target = GetSymbolTarget(G, Sym.getBlock());
+  if (!Target)
+    return Target.takeError();
+
+  SmallVectorImpl<MemoryRegionInfo> &Entry = StubInfos[Target->getName()];
+  Entry.emplace_back(Sym.getSymbolContent(), Sym.getAddress().getValue(),
+                     Sym.getTargetFlags());
+
+  // Let's keep stubs ordered by ascending address.
+  std::sort(Entry.begin(), Entry.end(),
+            [](const MemoryRegionInfo &L, const MemoryRegionInfo &R) {
+              return L.getTargetAddress() < R.getTargetAddress();
+            });
+
+  return Error::success();
+}
+
 Expected<Session::FileInfo &> Session::findFileInfo(StringRef FileName) {
   auto FileInfoItr = FileInfos.find(FileName);
   if (FileInfoItr == FileInfos.end())
@@ -1158,8 +1265,59 @@
   return SecInfoItr->second;
 }
 
+class MemoryMatcher {
+public:
+  MemoryMatcher(ArrayRef<char> Content)
+      : Pos(Content.data()), End(Pos + Content.size()) {}
+
+  template <typename MaskType> bool matchMask(MaskType Mask) {
+    if (Mask == (Mask & *reinterpret_cast<const MaskType *>(Pos))) {
+      Pos += sizeof(MaskType);
+      return true;
+    }
+    return false;
+  }
+
+  template <typename ValueType> bool matchEqual(ValueType Value) {
+    if (Value == *reinterpret_cast<const ValueType *>(Pos)) {
+      Pos += sizeof(ValueType);
+      return true;
+    }
+    return false;
+  }
+
+  bool done() const { return Pos == End; }
+
+private:
+  const char *Pos;
+  const char *End;
+};
+
+static StringRef detectStubKind(const Session::MemoryRegionInfo &Stub) {
+  using namespace support::endian;
+  auto Armv7MovWTle = byte_swap<uint32_t, endianness::little>(0xe300c000);
+  auto Armv7BxR12le = byte_swap<uint32_t, endianness::little>(0xe12fff1c);
+  auto Thumbv7MovWTle = byte_swap<uint32_t, endianness::little>(0x0c00f240);
+  auto Thumbv7BxR12le = byte_swap<uint16_t, endianness::little>(0x4760);
+
+  MemoryMatcher M(Stub.getContent());
+  if (M.matchMask(Thumbv7MovWTle)) {
+    if (M.matchMask(Thumbv7MovWTle))
+      if (M.matchEqual(Thumbv7BxR12le))
+        if (M.done())
+          return "thumbv7_abs_le";
+  } else if (M.matchMask(Armv7MovWTle)) {
+    if (M.matchMask(Armv7MovWTle))
+      if (M.matchEqual(Armv7BxR12le))
+        if (M.done())
+          return "armv7_abs_le";
+  }
+  return "";
+}
+
 Expected<Session::MemoryRegionInfo &>
-Session::findStubInfo(StringRef FileName, StringRef TargetName) {
+Session::findStubInfo(StringRef FileName, StringRef TargetName,
+                      StringRef KindNameFilter) {
   auto FI = findFileInfo(FileName);
   if (!FI)
     return FI.takeError();
@@ -1169,7 +1327,38 @@
                                        "\" registered for file \"" + FileName +
                                        "\"",
                                    inconvertibleErrorCode());
-  return StubInfoItr->second;
+  auto &StubsForTarget = StubInfoItr->second;
+  assert(!StubsForTarget.empty() && "At least 1 stub in each entry");
+  if (KindNameFilter.empty() && StubsForTarget.size() == 1)
+    return StubsForTarget[0]; // Regular single-stub match
+
+  std::string KindsStr;
+  SmallVector<MemoryRegionInfo *, 1> Matches;
+  Regex KindNameMatcher(KindNameFilter.empty() ? ".*" : KindNameFilter);
+  for (MemoryRegionInfo &Stub : StubsForTarget) {
+    StringRef Kind = detectStubKind(Stub);
+    if (KindNameMatcher.match(Kind))
+      Matches.push_back(&Stub);
+    KindsStr += "\"" + (Kind.empty() ? "<unknown>" : Kind.str()) + "\", ";
+  }
+  if (Matches.empty())
+    return make_error<StringError>(
+        "\"" + TargetName + "\" has " + Twine(StubsForTarget.size()) +
+            " stubs in file \"" + FileName +
+            "\", but none of them matches the stub-kind filter \"" +
+            KindNameFilter + "\" (all encountered kinds are " +
+            StringRef(KindsStr.data(), KindsStr.size() - 2) + ").",
+        inconvertibleErrorCode());
+  if (Matches.size() > 1)
+    return make_error<StringError>(
+        "\"" + TargetName + "\" has " + Twine(Matches.size()) +
+            " candidate stubs in file \"" + FileName +
+            "\". Please refine stub-kind filter \"" + KindNameFilter +
+            "\" for disambiguation (encountered kinds are " +
+            StringRef(KindsStr.data(), KindsStr.size() - 2) + ").",
+        inconvertibleErrorCode());
+
+  return *Matches[0];
 }
 
 Expected<Session::MemoryRegionInfo &>
@@ -1249,6 +1438,10 @@
   if (DebuggerSupport.getNumOccurrences() == 0 && NoExec)
     DebuggerSupport = false;
 
+  if (!OrcRuntime.empty() && NoProcessSymbols)
+    return make_error<StringError>("-orc-runtime requires process symbols",
+                                   inconvertibleErrorCode());
+
   // If -slab-allocate is passed, check that we're not trying to use it in
   // -oop-executor or -oop-executor-connect mode.
   //
@@ -1348,6 +1541,13 @@
     }
   }
 
+  if (S.PlatformJD)
+    S.JDSearchOrder.push_back(
+        {S.PlatformJD, JITDylibLookupFlags::MatchExportedSymbolsOnly});
+  if (S.ProcessSymsJD)
+    S.JDSearchOrder.push_back(
+        {S.ProcessSymsJD, JITDylibLookupFlags::MatchExportedSymbolsOnly});
+
   LLVM_DEBUG({
     dbgs() << "Dylib search order is [ ";
     for (auto &KV : S.JDSearchOrder)
@@ -1388,7 +1588,8 @@
       return Err;
 
     // Register the absolute symbol with the session symbol infos.
-    S.SymbolInfos[Name] = {ArrayRef<char>(), Addr};
+    S.SymbolInfos[Name] = {ArrayRef<char>(), Addr,
+                           AbsDef.getFlags().getTargetFlags()};
   }
 
   return Error::success();
@@ -1398,23 +1599,67 @@
                         const std::map<unsigned, JITDylib *> &IdxToJD) {
   // Define absolute symbols.
   LLVM_DEBUG(dbgs() << "Defining aliases...\n");
+
+  DenseMap<std::pair<JITDylib *, JITDylib *>, SymbolAliasMap> Reexports;
   for (auto AliasItr = Aliases.begin(), AliasEnd = Aliases.end();
        AliasItr != AliasEnd; ++AliasItr) {
-    unsigned AliasArgIdx = Aliases.getPosition(AliasItr - Aliases.begin());
-    auto &JD = *std::prev(IdxToJD.lower_bound(AliasArgIdx))->second;
 
-    StringRef AliasStmt = *AliasItr;
-    size_t EqIdx = AliasStmt.find_first_of('=');
-    if (EqIdx == StringRef::npos)
-      return make_error<StringError>("Invalid alias definition \"" + AliasStmt +
-                                         "\". Syntax: <name>=<addr>",
-                                     inconvertibleErrorCode());
-    StringRef Alias = AliasStmt.substr(0, EqIdx).trim();
-    StringRef Aliasee = AliasStmt.substr(EqIdx + 1).trim();
+    auto BadExpr = [&]() {
+      return make_error<StringError>(
+          "Invalid alias definition \"" + *AliasItr +
+              "\". Syntax: [<dst-jd>:]<alias>=[<src-jd>:]<aliasee>",
+          inconvertibleErrorCode());
+    };
 
-    SymbolAliasMap SAM;
-    SAM[S.ES.intern(Alias)] = {S.ES.intern(Aliasee), JITSymbolFlags::Exported};
-    if (auto Err = JD.define(symbolAliases(std::move(SAM))))
+    auto GetJD = [&](StringRef JDName) -> Expected<JITDylib *> {
+      if (JDName.empty()) {
+        unsigned AliasArgIdx = Aliases.getPosition(AliasItr - Aliases.begin());
+        return std::prev(IdxToJD.lower_bound(AliasArgIdx))->second;
+      }
+
+      auto *JD = S.ES.getJITDylibByName(JDName);
+      if (!JD)
+        return make_error<StringError>(StringRef("In alias definition \"") +
+                                           *AliasItr + "\" no dylib named " +
+                                           JDName,
+                                       inconvertibleErrorCode());
+
+      return JD;
+    };
+
+    {
+      // First split on '=' to get alias and aliasee.
+      StringRef AliasStmt = *AliasItr;
+      auto [AliasExpr, AliaseeExpr] = AliasStmt.split('=');
+      if (AliaseeExpr.empty())
+        return BadExpr();
+
+      auto [AliasJDName, Alias] = AliasExpr.split(':');
+      if (Alias.empty())
+        std::swap(AliasJDName, Alias);
+
+      auto AliasJD = GetJD(AliasJDName);
+      if (!AliasJD)
+        return AliasJD.takeError();
+
+      auto [AliaseeJDName, Aliasee] = AliaseeExpr.split(':');
+      if (Aliasee.empty())
+        std::swap(AliaseeJDName, Aliasee);
+
+      if (AliaseeJDName.empty() && !AliasJDName.empty())
+        AliaseeJDName = AliasJDName;
+      auto AliaseeJD = GetJD(AliaseeJDName);
+      if (!AliaseeJD)
+        return AliaseeJD.takeError();
+
+      Reexports[{*AliasJD, *AliaseeJD}][S.ES.intern(Alias)] = {
+          S.ES.intern(Aliasee), JITSymbolFlags::Exported};
+    }
+  }
+
+  for (auto &[JDs, AliasMap] : Reexports) {
+    auto [DstJD, SrcJD] = JDs;
+    if (auto Err = DstJD->define(reexports(*SrcJD, std::move(AliasMap))))
       return Err;
   }
 
@@ -1444,8 +1689,8 @@
     unsigned InputFileArgIdx =
         InputFiles.getPosition(InputFileItr - InputFiles.begin());
     const std::string &InputFile = *InputFileItr;
-    if (StringRef(InputFile).endswith(".a") ||
-        StringRef(InputFile).endswith(".lib"))
+    if (StringRef(InputFile).ends_with(".a") ||
+        StringRef(InputFile).ends_with(".lib"))
       continue;
     auto &JD = *std::prev(IdxToJD.lower_bound(InputFileArgIdx))->second;
     LLVM_DEBUG(dbgs() << "  " << InputFileArgIdx << ": \"" << InputFile
@@ -1545,7 +1790,7 @@
   for (auto InputFileItr = InputFiles.begin(), InputFileEnd = InputFiles.end();
        InputFileItr != InputFileEnd; ++InputFileItr) {
     StringRef InputFile = *InputFileItr;
-    if (!InputFile.endswith(".a") && !InputFile.endswith(".lib"))
+    if (!InputFile.ends_with(".a") && !InputFile.ends_with(".lib"))
       continue;
     LibraryLoad LL;
     LL.LibName = InputFile.str();
@@ -1748,6 +1993,14 @@
                                      inconvertibleErrorCode());
   }
 
+  // Add platform and process symbols if available.
+  for (auto &[Idx, JD] : IdxToJD) {
+    if (S.PlatformJD)
+      JD->addToLinkOrder(*S.PlatformJD);
+    if (S.ProcessSymsJD)
+      JD->addToLinkOrder(*S.ProcessSymsJD);
+  }
+
   return Error::success();
 }
 
@@ -1856,15 +2109,12 @@
           std::move(MAI), std::move(Ctx), std::move(Disassembler),
           std::move(MII), std::move(MIA), std::move(InstPrinter)};
 }
-
-static Error runChecks(Session &S) {
+static Error runChecks(Session &S, Triple TT, SubtargetFeatures Features) {
   if (CheckFiles.empty())
     return Error::success();
 
   LLVM_DEBUG(dbgs() << "Running checks...\n");
 
-  auto TI = getTargetInfo(S.ES.getTargetTriple(), S.Features);
-
   auto IsSymbolValid = [&S](StringRef Symbol) {
     return S.isSymbolRegistered(Symbol);
   };
@@ -1877,8 +2127,9 @@
     return S.findSectionInfo(FileName, SectionName);
   };
 
-  auto GetStubInfo = [&S](StringRef FileName, StringRef SectionName) {
-    return S.findStubInfo(FileName, SectionName);
+  auto GetStubInfo = [&S](StringRef FileName, StringRef SectionName,
+                          StringRef KindNameFilter) {
+    return S.findStubInfo(FileName, SectionName, KindNameFilter);
   };
 
   auto GetGOTInfo = [&S](StringRef FileName, StringRef SectionName) {
@@ -1887,8 +2138,9 @@
 
   RuntimeDyldChecker Checker(
       IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,
-      S.ES.getTargetTriple().isLittleEndian() ? support::little : support::big,
-      TI.Disassembler.get(), TI.InstPrinter.get(), dbgs());
+      S.ES.getTargetTriple().isLittleEndian() ? llvm::endianness::little
+                                              : llvm::endianness::big,
+      TT, StringRef(), Features, dbgs());
 
   std::string CheckLineStart = "# " + CheckName + ":";
   for (auto &CheckFile : CheckFiles) {
@@ -2000,7 +2252,7 @@
   auto [TT, Features] = getFirstFileTripleAndFeatures();
   ExitOnErr(sanitizeArguments(TT, argv[0]));
 
-  auto S = ExitOnErr(Session::Create(std::move(TT), std::move(Features)));
+  auto S = ExitOnErr(Session::Create(TT, Features));
 
   enableStatistics(*S, !OrcRuntime.empty());
 
@@ -2036,7 +2288,7 @@
     exit(1);
   }
 
-  ExitOnErr(runChecks(*S));
+  ExitOnErr(runChecks(*S, std::move(TT), std::move(Features)));
 
   int Result = 0;
   if (!NoExec) {
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.h b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.h
index 9389be4..e09c15a 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.h
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.h
@@ -25,14 +25,14 @@
 #include "llvm/TargetParser/SubtargetFeature.h"
 #include "llvm/TargetParser/Triple.h"
 
-#include <vector>
-
 namespace llvm {
 
 struct Session {
 
   orc::ExecutionSession ES;
   orc::JITDylib *MainJD = nullptr;
+  orc::JITDylib *ProcessSymsJD = nullptr;
+  orc::JITDylib *PlatformJD = nullptr;
   orc::ObjectLinkingLayer ObjLayer;
   orc::JITDylibSearchOrder JDSearchOrder;
   SubtargetFeatures Features;
@@ -49,8 +49,20 @@
 
   struct FileInfo {
     StringMap<MemoryRegionInfo> SectionInfos;
-    StringMap<MemoryRegionInfo> StubInfos;
+    StringMap<SmallVector<MemoryRegionInfo, 1>> StubInfos;
     StringMap<MemoryRegionInfo> GOTEntryInfos;
+
+    using Symbol = jitlink::Symbol;
+    using LinkGraph = jitlink::LinkGraph;
+    using GetSymbolTargetFunction =
+        unique_function<Expected<Symbol &>(LinkGraph &G, jitlink::Block &)>;
+
+    Error registerGOTEntry(LinkGraph &G, Symbol &Sym,
+                           GetSymbolTargetFunction GetSymbolTarget);
+    Error registerStubEntry(LinkGraph &G, Symbol &Sym,
+                            GetSymbolTargetFunction GetSymbolTarget);
+    Error registerMultiStubEntry(LinkGraph &G, Symbol &Sym,
+                                 GetSymbolTargetFunction GetSymbolTarget);
   };
 
   using DynLibJDMap = std::map<std::string, orc::JITDylib *>;
@@ -64,7 +76,8 @@
   Expected<MemoryRegionInfo &> findSectionInfo(StringRef FileName,
                                                StringRef SectionName);
   Expected<MemoryRegionInfo &> findStubInfo(StringRef FileName,
-                                            StringRef TargetName);
+                                            StringRef TargetName,
+                                            StringRef KindNameFilter);
   Expected<MemoryRegionInfo &> findGOTEntryInfo(StringRef FileName,
                                                 StringRef TargetName);
 
diff --git a/src/llvm-project/llvm/tools/llvm-libtool-darwin/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-libtool-darwin/CMakeLists.txt
index bc4b31f..eb95a5f 100644
--- a/src/llvm-project/llvm/tools/llvm-libtool-darwin/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-libtool-darwin/CMakeLists.txt
@@ -18,6 +18,7 @@
 
   DEPENDS
   LibtoolDarwinOptsTableGen
+  GENERATE_DRIVER
 )
 
 if(LLVM_INSTALL_CCTOOLS_SYMLINKS)
diff --git a/src/llvm-project/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp b/src/llvm-project/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
index 9188cad..77ae9b4 100644
--- a/src/llvm-project/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
+++ b/src/llvm-project/llvm/tools/llvm-libtool-darwin/llvm-libtool-darwin.cpp
@@ -23,7 +23,7 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/Option.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/LineIterator.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/VirtualFileSystem.h"
@@ -31,6 +31,7 @@
 #include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TextAPI/Architecture.h"
+#include <cstdlib>
 #include <map>
 #include <type_traits>
 
@@ -42,9 +43,7 @@
 namespace {
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -57,13 +56,7 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -138,7 +131,7 @@
 static Error processCommandLineLibraries() {
   for (StringRef BaseName : Libraries) {
     Expected<std::string> FullPath = searchForFile(
-        BaseName.endswith(".o") ? BaseName.str() : "lib" + BaseName + ".a");
+        BaseName.ends_with(".o") ? BaseName.str() : "lib" + BaseName + ".a");
     if (!FullPath)
       return FullPath.takeError();
     InputFiles.push_back(FullPath.get());
@@ -600,18 +593,17 @@
 
   if (NewMembers.size() == 1)
     return writeArchive(OutputFile, NewMembers.begin()->second.getMembers(),
-                        /*WriteSymtab=*/true,
+                        SymtabWritingMode::NormalSymtab,
                         /*Kind=*/object::Archive::K_DARWIN, C.Deterministic,
                         /*Thin=*/false);
 
   SmallVector<OwningBinary<Archive>, 2> OutputBinaries;
   for (const std::pair<const uint64_t, NewArchiveMemberList> &M : NewMembers) {
     Expected<std::unique_ptr<MemoryBuffer>> OutputBufferOrErr =
-        writeArchiveToBuffer(M.second.getMembers(),
-                             /*WriteSymtab=*/true,
-                             /*Kind=*/object::Archive::K_DARWIN,
-                             C.Deterministic,
-                             /*Thin=*/false);
+        writeArchiveToBuffer(
+            M.second.getMembers(), SymtabWritingMode::NormalSymtab,
+            /*Kind=*/object::Archive::K_DARWIN, C.Deterministic,
+            /*Thin=*/false);
     if (!OutputBufferOrErr)
       return OutputBufferOrErr.takeError();
     std::unique_ptr<MemoryBuffer> &OutputBuffer = OutputBufferOrErr.get();
@@ -733,8 +725,7 @@
   return C;
 }
 
-int main(int Argc, char **Argv) {
-  InitLLVM X(Argc, Argv);
+int llvm_libtool_darwin_main(int Argc, char **Argv, const llvm::ToolContext &) {
   Expected<Config> ConfigOrErr = parseCommandLine(Argc, Argv);
   if (!ConfigOrErr) {
     WithColor::defaultErrorHandler(ConfigOrErr.takeError());
@@ -760,4 +751,5 @@
     }
     break;
   }
+  return EXIT_SUCCESS;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-link/llvm-link.cpp b/src/llvm-project/llvm/tools/llvm-link/llvm-link.cpp
index 32ab9fa..a476b50 100644
--- a/src/llvm-project/llvm/tools/llvm-link/llvm-link.cpp
+++ b/src/llvm-project/llvm/tools/llvm-link/llvm-link.cpp
@@ -323,6 +323,11 @@
   };
 
   ModuleLazyLoaderCache ModuleLoaderCache(ModuleLoader);
+  // Owns the filename strings used to key into the ImportList. Normally this is
+  // constructed from the index and the strings are owned by the index, however,
+  // since we are synthesizing this data structure from options we need a cache
+  // to own those strings.
+  StringSet<> FileNameStringCache;
   for (const auto &Import : Imports) {
     // Identify the requested function and its bitcode source file.
     size_t Idx = Import.find(':');
@@ -360,7 +365,8 @@
     if (Verbose)
       errs() << "Importing " << FunctionName << " from " << FileName << "\n";
 
-    auto &Entry = ImportList[FileName];
+    auto &Entry =
+        ImportList[FileNameStringCache.insert(FileName).first->getKey()];
     Entry.insert(F->getGUID());
   }
   auto CachedModuleLoader = [&](StringRef Identifier) {
diff --git a/src/llvm-project/llvm/tools/llvm-lipo/LipoOpts.td b/src/llvm-project/llvm/tools/llvm-lipo/LipoOpts.td
index 8663535..32bdca4 100644
--- a/src/llvm-project/llvm/tools/llvm-lipo/LipoOpts.td
+++ b/src/llvm-project/llvm/tools/llvm-lipo/LipoOpts.td
@@ -58,3 +58,6 @@
 def output : Option<["-", "--"], "output", KIND_SEPARATE>,
              HelpText<"Create output file with specified name">;
 def o : JoinedOrSeparate<["-"], "o">, Alias<output>;
+
+def fat64 : Option<["-", "--"], "fat64", KIND_FLAG>,
+            HelpText<"Use 64 bits Universal Mach-O format">;
diff --git a/src/llvm-project/llvm/tools/llvm-lipo/llvm-lipo.cpp b/src/llvm-project/llvm/tools/llvm-lipo/llvm-lipo.cpp
index d37df62..083a922 100644
--- a/src/llvm-project/llvm/tools/llvm-lipo/llvm-lipo.cpp
+++ b/src/llvm-project/llvm/tools/llvm-lipo/llvm-lipo.cpp
@@ -26,7 +26,6 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/WithColor.h"
@@ -67,9 +66,7 @@
 namespace {
 enum LipoID {
   LIPO_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  LIPO_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(LIPO_, __VA_ARGS__),
 #include "LipoOpts.inc"
 #undef OPTION
 };
@@ -82,13 +79,9 @@
 #include "LipoOpts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info LipoInfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {PREFIX,       NAME,      HELPTEXT,                                          \
-   METAVAR,      LIPO_##ID, opt::Option::KIND##Class,                          \
-   PARAM,        FLAGS,     LIPO_##GROUP,                                      \
-   LIPO_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(LIPO_, __VA_ARGS__),
 #include "LipoOpts.inc"
 #undef OPTION
 };
@@ -122,6 +115,7 @@
   std::string ArchType;
   std::string OutputFile;
   LipoAction ActionToPerform;
+  bool UseFat64;
 };
 
 static Slice createSliceFromArchive(LLVMContext &LLVMCtx, const Archive &A) {
@@ -229,6 +223,8 @@
                   Twine(AlignmentValue));
   }
 
+  C.UseFat64 = InputArgs.hasArg(LIPO_fat64);
+
   SmallVector<opt::Arg *, 1> ActionArgs(InputArgs.filtered(LIPO_action_group));
   if (ActionArgs.empty())
     reportError("at least one action should be specified");
@@ -602,9 +598,11 @@
   return Slices;
 }
 
-[[noreturn]] static void createUniversalBinary(
-    LLVMContext &LLVMCtx, ArrayRef<OwningBinary<Binary>> InputBinaries,
-    const StringMap<const uint32_t> &Alignments, StringRef OutputFileName) {
+[[noreturn]] static void
+createUniversalBinary(LLVMContext &LLVMCtx,
+                      ArrayRef<OwningBinary<Binary>> InputBinaries,
+                      const StringMap<const uint32_t> &Alignments,
+                      StringRef OutputFileName, FatHeaderType HeaderType) {
   assert(InputBinaries.size() >= 1 && "Incorrect number of input binaries");
   assert(!OutputFileName.empty() && "Create expects a single output file");
 
@@ -615,7 +613,7 @@
   checkUnusedAlignments(Slices, Alignments);
 
   llvm::stable_sort(Slices);
-  if (Error E = writeUniversalBinary(Slices, OutputFileName))
+  if (Error E = writeUniversalBinary(Slices, OutputFileName, HeaderType))
     reportError(std::move(E));
 
   exit(EXIT_SUCCESS);
@@ -725,7 +723,6 @@
 }
 
 int llvm_lipo_main(int argc, char **argv, const llvm::ToolContext &) {
-  InitLLVM X(argc, argv);
   llvm::InitializeAllTargetInfos();
   llvm::InitializeAllTargetMCs();
   llvm::InitializeAllAsmParsers();
@@ -753,8 +750,9 @@
                  C.OutputFile);
     break;
   case LipoAction::CreateUniversal:
-    createUniversalBinary(LLVMCtx, InputBinaries, C.SegmentAlignments,
-                          C.OutputFile);
+    createUniversalBinary(
+        LLVMCtx, InputBinaries, C.SegmentAlignments, C.OutputFile,
+        C.UseFat64 ? FatHeaderType::Fat64Header : FatHeaderType::FatHeader);
     break;
   case LipoAction::ReplaceArch:
     replaceSlices(LLVMCtx, InputBinaries, C.SegmentAlignments, C.OutputFile,
diff --git a/src/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp b/src/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
index 51921d4..735b376 100644
--- a/src/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
+++ b/src/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
@@ -52,7 +52,6 @@
 #include <cassert>
 #include <cstdint>
 #include <cstdlib>
-#include <list>
 #include <map>
 #include <memory>
 #include <string>
@@ -481,12 +480,11 @@
 /// currently available via the gold plugin via -thinlto.
 static void createCombinedModuleSummaryIndex() {
   ModuleSummaryIndex CombinedIndex(/*HaveGVs=*/false);
-  uint64_t NextModuleId = 0;
   for (auto &Filename : InputFilenames) {
     ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
     std::unique_ptr<MemoryBuffer> MB =
         ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
-    ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex, NextModuleId++));
+    ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex));
   }
   // In order to use this index for testing, specifically import testing, we
   // need to update any indirect call edges created from SamplePGO, so that they
@@ -528,7 +526,7 @@
     if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
       error(EC, "error creating the directory '" + ParentPath + "'");
   }
-  return std::string(NewPath.str());
+  return std::string(NewPath);
 }
 
 namespace thinlto {
diff --git a/src/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp b/src/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp
index 7456a2f..a588058 100644
--- a/src/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp
@@ -31,10 +31,8 @@
 typedef std::pair<std::vector<unsigned char>, std::vector<const char *>>
     ByteArrayTy;
 
-static bool PrintInsts(const MCDisassembler &DisAsm,
-                       const ByteArrayTy &Bytes,
-                       SourceMgr &SM, raw_ostream &Out,
-                       MCStreamer &Streamer, bool InAtomicBlock,
+static bool PrintInsts(const MCDisassembler &DisAsm, const ByteArrayTy &Bytes,
+                       SourceMgr &SM, MCStreamer &Streamer, bool InAtomicBlock,
                        const MCSubtargetInfo &STI) {
   ArrayRef<uint8_t> Data(Bytes.first.data(), Bytes.first.size());
 
@@ -132,7 +130,7 @@
 int Disassembler::disassemble(const Target &T, const std::string &Triple,
                               MCSubtargetInfo &STI, MCStreamer &Streamer,
                               MemoryBuffer &Buffer, SourceMgr &SM,
-                              MCContext &Ctx, raw_ostream &Out,
+                              MCContext &Ctx,
                               const MCTargetOptions &MCOptions) {
 
   std::unique_ptr<const MCRegisterInfo> MRI(T.createMCRegInfo(Triple));
@@ -193,8 +191,8 @@
     ErrorOccurred |= ByteArrayFromString(ByteArray, Str, SM);
 
     if (!ByteArray.first.empty())
-      ErrorOccurred |= PrintInsts(*DisAsm, ByteArray, SM, Out, Streamer,
-                                  InAtomicBlock, STI);
+      ErrorOccurred |=
+          PrintInsts(*DisAsm, ByteArray, SM, Streamer, InAtomicBlock, STI);
   }
 
   if (InAtomicBlock) {
diff --git a/src/llvm-project/llvm/tools/llvm-mc/Disassembler.h b/src/llvm-project/llvm/tools/llvm-mc/Disassembler.h
index a1603e5..d0226ab 100644
--- a/src/llvm-project/llvm/tools/llvm-mc/Disassembler.h
+++ b/src/llvm-project/llvm/tools/llvm-mc/Disassembler.h
@@ -32,7 +32,7 @@
   static int disassemble(const Target &T, const std::string &Triple,
                          MCSubtargetInfo &STI, MCStreamer &Streamer,
                          MemoryBuffer &Buffer, SourceMgr &SM, MCContext &Ctx,
-                         raw_ostream &Out, const MCTargetOptions &MCOptions);
+                         const MCTargetOptions &MCOptions);
 };
 
 } // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp b/src/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp
index 572723a..cf6aaa1 100644
--- a/src/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -216,6 +216,7 @@
   AC_Assemble,
   AC_Disassemble,
   AC_MDisassemble,
+  AC_CDisassemble,
 };
 
 static cl::opt<ActionType> Action(
@@ -226,7 +227,9 @@
                clEnumValN(AC_Disassemble, "disassemble",
                           "Disassemble strings of hex bytes"),
                clEnumValN(AC_MDisassemble, "mdis",
-                          "Marked up disassembly of strings of hex bytes")),
+                          "Marked up disassembly of strings of hex bytes"),
+               clEnumValN(AC_CDisassemble, "cdis",
+                          "Colored disassembly of strings of hex bytes")),
     cl::cat(MCCategory));
 
 static const Target *GetTarget(const char *ProgName) {
@@ -544,6 +547,11 @@
     std::unique_ptr<MCAsmBackend> MAB(
         TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions));
     auto FOut = std::make_unique<formatted_raw_ostream>(*OS);
+    // FIXME: Workaround for bug in formatted_raw_ostream. Color escape codes
+    // are (incorrectly) written directly to the unbuffered raw_ostream wrapped
+    // by the formatted_raw_ostream.
+    if (Action == AC_CDisassemble)
+      FOut->SetUnbuffered();
     Str.reset(
         TheTarget->createAsmStreamer(Ctx, std::move(FOut), /*asmverbose*/ true,
                                      /*useDwarfDirectory*/ true, IP,
@@ -586,17 +594,20 @@
                         *MCII, MCOptions);
     break;
   case AC_MDisassemble:
-    assert(IP && "Expected assembly output");
     IP->setUseMarkup(true);
     disassemble = true;
     break;
+  case AC_CDisassemble:
+    IP->setUseColor(true);
+    disassemble = true;
+    break;
   case AC_Disassemble:
     disassemble = true;
     break;
   }
   if (disassemble)
     Res = Disassembler::disassemble(*TheTarget, TripleName, *STI, *Str, *Buffer,
-                                    SrcMgr, Ctx, Out->os(), MCOptions);
+                                    SrcMgr, Ctx, MCOptions);
 
   // Keep output if no errors.
   if (Res == 0) {
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp b/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
index b254ccd..b702113 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/BottleneckAnalysis.cpp
@@ -611,9 +611,9 @@
     ArrayRef<unsigned> Distribution = Tracker.getResourcePressureDistribution();
     const MCSchedModel &SM = getSubTargetInfo().getSchedModel();
     for (unsigned I = 0, E = Distribution.size(); I < E; ++I) {
-      unsigned ResourceCycles = Distribution[I];
-      if (ResourceCycles) {
-        double Frequency = (double)ResourceCycles * 100 / TotalCycles;
+      unsigned ReleaseAtCycles = Distribution[I];
+      if (ReleaseAtCycles) {
+        double Frequency = (double)ReleaseAtCycles * 100 / TotalCycles;
         const MCProcResourceDesc &PRDesc = *SM.getProcResource(I);
         OS << "\n  - " << PRDesc.Name << "  [ "
            << format("%.2f", floor((Frequency * 100) + 0.5) / 100) << "% ]";
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp b/src/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp
index 0f059bcc..f39350f 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.cpp
@@ -54,7 +54,7 @@
   const auto &IssueEvent = static_cast<const HWInstructionIssuedEvent &>(Event);
   ArrayRef<llvm::MCInst> Source = getSource();
   const unsigned SourceIdx = Event.IR.getSourceIndex() % Source.size();
-  for (const std::pair<ResourceRef, ResourceCycles> &Use :
+  for (const std::pair<ResourceRef, ReleaseAtCycles> &Use :
        IssueEvent.UsedResources) {
     const ResourceRef &RR = Use.first;
     assert(Resource2VecIndex.contains(RR.first));
@@ -181,7 +181,7 @@
   ArrayRef<llvm::MCInst> Source = getSource();
   const unsigned Executions = LastInstructionIdx / Source.size() + 1;
   for (const auto &R : enumerate(ResourceUsage)) {
-    const ResourceCycles &RU = R.value();
+    const ReleaseAtCycles &RU = R.value();
     if (RU.getNumerator() == 0)
       continue;
     unsigned InstructionIndex = R.index() / NumResourceUnits;
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.h b/src/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.h
index c3993a0..be8ad04 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/ResourcePressureView.h
@@ -78,7 +78,7 @@
   llvm::DenseMap<unsigned, unsigned> Resource2VecIndex;
 
   // Table of resources used by instructions.
-  std::vector<ResourceCycles> ResourceUsage;
+  std::vector<ReleaseAtCycles> ResourceUsage;
   unsigned NumResourceUnits;
 
   void printResourcePressurePerIter(llvm::raw_ostream &OS) const;
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.h b/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.h
index 21f3fad..c99905d 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/SummaryView.h
@@ -28,7 +28,6 @@
 #ifndef LLVM_TOOLS_LLVM_MCA_SUMMARYVIEW_H
 #define LLVM_TOOLS_LLVM_MCA_SUMMARYVIEW_H
 
-#include "llvm/ADT/DenseMap.h"
 #include "llvm/MC/MCSchedule.h"
 #include "llvm/MCA/View.h"
 #include "llvm/Support/raw_ostream.h"
diff --git a/src/llvm-project/llvm/tools/llvm-ml/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-ml/CMakeLists.txt
index 2b2a116a..3009717 100644
--- a/src/llvm-project/llvm/tools/llvm-ml/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-ml/CMakeLists.txt
@@ -18,4 +18,7 @@
 add_llvm_tool(llvm-ml
   llvm-ml.cpp
   Disassembler.cpp
+  DEPENDS
+  MLTableGen
+  GENERATE_DRIVER
   )
diff --git a/src/llvm-project/llvm/tools/llvm-ml/llvm-ml.cpp b/src/llvm-project/llvm/tools/llvm-ml/llvm-ml.cpp
index 34691c4..1cac576 100644
--- a/src/llvm-project/llvm/tools/llvm-ml/llvm-ml.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ml/llvm-ml.cpp
@@ -34,7 +34,7 @@
 #include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Process.h"
@@ -53,9 +53,7 @@
 
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -68,13 +66,7 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -90,7 +82,7 @@
   StringRef DefaultBitness = "32";
   SmallString<255> Program = ProgName;
   sys::path::replace_extension(Program, "");
-  if (Program.endswith("ml64"))
+  if (Program.ends_with("ml64"))
     DefaultBitness = "64";
 
   StringRef TripleName =
@@ -193,8 +185,7 @@
   return Res;
 }
 
-int main(int Argc, char **Argv) {
-  InitLLVM X(Argc, Argv);
+int llvm_ml_main(int Argc, char **Argv, const llvm::ToolContext &) {
   StringRef ProgName = sys::path::filename(Argv[0]);
 
   // Initialize targets and assembly printers/parsers.
diff --git a/src/llvm-project/llvm/tools/llvm-mt/llvm-mt.cpp b/src/llvm-project/llvm/tools/llvm-mt/llvm-mt.cpp
index 887cc90..158088d 100644
--- a/src/llvm-project/llvm/tools/llvm-mt/llvm-mt.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mt/llvm-mt.cpp
@@ -16,7 +16,6 @@
 #include "llvm/Option/Option.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
@@ -35,9 +34,7 @@
 
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -49,14 +46,9 @@
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-{                                                                              \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -84,8 +76,6 @@
 }
 
 int llvm_mt_main(int Argc, char **Argv, const llvm::ToolContext &) {
-  InitLLVM X(Argc, Argv);
-
   CvtResOptTable T;
   unsigned MAI, MAC;
   ArrayRef<const char *> ArgsArr = ArrayRef(Argv + 1, Argc - 1);
diff --git a/src/llvm-project/llvm/tools/llvm-nm/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-nm/CMakeLists.txt
index ec04f1e..5191e13 100644
--- a/src/llvm-project/llvm/tools/llvm-nm/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-nm/CMakeLists.txt
@@ -8,6 +8,7 @@
   Object
   Option
   Support
+  Symbolize
   TargetParser
   TextAPI
   )
diff --git a/src/llvm-project/llvm/tools/llvm-nm/Opts.td b/src/llvm-project/llvm/tools/llvm-nm/Opts.td
index 60ac134..04d9f5d 100644
--- a/src/llvm-project/llvm/tools/llvm-nm/Opts.td
+++ b/src/llvm-project/llvm/tools/llvm-nm/Opts.td
@@ -22,6 +22,7 @@
 def extern_only : FF<"extern-only", "Show only external symbols">;
 defm format : Eq<"format", "Specify output format: bsd (default), posix, sysv, darwin, just-symbols">, MetaVarName<"<format>">;
 def help : FF<"help", "Display this help">;
+def line_numbers : FF<"line-numbers", "Use debugging information to print symbols' filenames and line numbers">;
 def no_llvm_bc : FF<"no-llvm-bc", "Disable LLVM bitcode reader">;
 def no_sort : FF<"no-sort", "Show symbols in order encountered">;
 def no_weak : FF<"no-weak", "Show only non-weak symbols">;
@@ -67,6 +68,7 @@
 def : F<"h", "Alias for --help">, Alias<help>;
 def : F<"g", "Alias for --extern-only">, Alias<extern_only>;
 def : F<"j", "Alias for --format=just-symbols">, Alias<format_EQ>, AliasArgs<["just-symbols"]>;
+def : F<"l", "Alias for --line-numbers">, Alias<line_numbers>;
 def : F<"m", "Alias for --format=darwin">, Alias<format_EQ>, AliasArgs<["darwin"]>;
 def : F<"M", "Deprecated alias for --print-armap">, Alias<print_armap>, Flags<[HelpHidden]>;
 def : F<"n", "Alias for --numeric-sort">, Alias<numeric_sort>;
diff --git a/src/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp b/src/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
index 1f6a5d1..da5998b 100644
--- a/src/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/src/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -17,7 +17,9 @@
 
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/BinaryFormat/COFF.h"
+#include "llvm/BinaryFormat/MachO.h"
 #include "llvm/BinaryFormat/XCOFF.h"
+#include "llvm/DebugInfo/Symbolize/Symbolize.h"
 #include "llvm/Demangle/Demangle.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/LLVMContext.h"
@@ -29,6 +31,7 @@
 #include "llvm/Object/MachO.h"
 #include "llvm/Object/MachOUniversal.h"
 #include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/SymbolicFile.h"
 #include "llvm/Object/TapiFile.h"
 #include "llvm/Object/TapiUniversal.h"
 #include "llvm/Object/Wasm.h"
@@ -39,7 +42,6 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Program.h"
@@ -58,9 +60,7 @@
 using namespace llvm::opt; // for HelpHidden in Opts.inc
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -73,13 +73,7 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -103,6 +97,7 @@
 static bool DynamicSyms;
 static bool ExportSymbols;
 static bool ExternalOnly;
+static bool LineNumbers;
 static OutputFormatTy OutputFormat;
 static bool NoLLVMBitcode;
 static bool NoSort;
@@ -243,10 +238,8 @@
   std::string IndirectName;
 
   bool isDefined() const {
-    if (Sym.getRawDataRefImpl().p) {
-      uint32_t Flags = cantFail(Sym.getFlags());
-      return !(Flags & SymbolRef::SF_Undefined);
-    }
+    if (Sym.getRawDataRefImpl().p)
+      return !(SymFlags & SymbolRef::SF_Undefined);
     return TypeChar != 'U';
   }
 
@@ -559,8 +552,6 @@
       }
     }
   }
-
-  outs() << "\n";
 }
 
 // Table that maps Darwin's Mach-O stab constants to strings to allow printing.
@@ -569,37 +560,22 @@
   const char *Name;
 };
 const struct DarwinStabName DarwinStabNames[] = {
-    {MachO::N_GSYM, "GSYM"},
-    {MachO::N_FNAME, "FNAME"},
-    {MachO::N_FUN, "FUN"},
-    {MachO::N_STSYM, "STSYM"},
-    {MachO::N_LCSYM, "LCSYM"},
-    {MachO::N_BNSYM, "BNSYM"},
-    {MachO::N_PC, "PC"},
-    {MachO::N_AST, "AST"},
-    {MachO::N_OPT, "OPT"},
-    {MachO::N_RSYM, "RSYM"},
-    {MachO::N_SLINE, "SLINE"},
-    {MachO::N_ENSYM, "ENSYM"},
-    {MachO::N_SSYM, "SSYM"},
-    {MachO::N_SO, "SO"},
-    {MachO::N_OSO, "OSO"},
-    {MachO::N_LSYM, "LSYM"},
-    {MachO::N_BINCL, "BINCL"},
-    {MachO::N_SOL, "SOL"},
-    {MachO::N_PARAMS, "PARAM"},
-    {MachO::N_VERSION, "VERS"},
-    {MachO::N_OLEVEL, "OLEV"},
-    {MachO::N_PSYM, "PSYM"},
-    {MachO::N_EINCL, "EINCL"},
-    {MachO::N_ENTRY, "ENTRY"},
-    {MachO::N_LBRAC, "LBRAC"},
-    {MachO::N_EXCL, "EXCL"},
-    {MachO::N_RBRAC, "RBRAC"},
-    {MachO::N_BCOMM, "BCOMM"},
-    {MachO::N_ECOMM, "ECOMM"},
-    {MachO::N_ECOML, "ECOML"},
-    {MachO::N_LENG, "LENG"},
+    {MachO::N_GSYM, "GSYM"},    {MachO::N_FNAME, "FNAME"},
+    {MachO::N_FUN, "FUN"},      {MachO::N_STSYM, "STSYM"},
+    {MachO::N_LCSYM, "LCSYM"},  {MachO::N_BNSYM, "BNSYM"},
+    {MachO::N_PC, "PC"},        {MachO::N_AST, "AST"},
+    {MachO::N_OPT, "OPT"},      {MachO::N_RSYM, "RSYM"},
+    {MachO::N_SLINE, "SLINE"},  {MachO::N_ENSYM, "ENSYM"},
+    {MachO::N_SSYM, "SSYM"},    {MachO::N_SO, "SO"},
+    {MachO::N_OSO, "OSO"},      {MachO::N_LIB, "LIB"},
+    {MachO::N_LSYM, "LSYM"},    {MachO::N_BINCL, "BINCL"},
+    {MachO::N_SOL, "SOL"},      {MachO::N_PARAMS, "PARAM"},
+    {MachO::N_VERSION, "VERS"}, {MachO::N_OLEVEL, "OLEV"},
+    {MachO::N_PSYM, "PSYM"},    {MachO::N_EINCL, "EINCL"},
+    {MachO::N_ENTRY, "ENTRY"},  {MachO::N_LBRAC, "LBRAC"},
+    {MachO::N_EXCL, "EXCL"},    {MachO::N_RBRAC, "RBRAC"},
+    {MachO::N_BCOMM, "BCOMM"},  {MachO::N_ECOMM, "ECOMM"},
+    {MachO::N_ECOML, "ECOML"},  {MachO::N_LENG, "LENG"},
 };
 
 static const char *getDarwinStabString(uint8_t NType) {
@@ -637,30 +613,6 @@
     outs() << format("   %02x", NType);
 }
 
-static std::optional<std::string> demangle(StringRef Name) {
-  std::string Demangled;
-  if (nonMicrosoftDemangle(Name, Demangled))
-    return Demangled;
-  return std::nullopt;
-}
-
-static std::optional<std::string> demangleXCOFF(StringRef Name) {
-  if (Name.empty() || Name[0] != '.')
-    return demangle(Name);
-
-  Name = Name.drop_front();
-  std::optional<std::string> DemangledName = demangle(Name);
-  if (DemangledName)
-    return "." + *DemangledName;
-  return std::nullopt;
-}
-
-static std::optional<std::string> demangleMachO(StringRef Name) {
-  if (!Name.empty() && Name[0] == '_')
-    Name = Name.drop_front();
-  return demangle(Name);
-}
-
 static bool symbolIsDefined(const NMSymbol &Sym) {
   return Sym.TypeChar != 'U' && Sym.TypeChar != 'w' && Sym.TypeChar != 'v';
 }
@@ -697,9 +649,88 @@
   }
 }
 
+static void printLineNumbers(symbolize::LLVMSymbolizer &Symbolizer,
+                             const NMSymbol &S) {
+  const auto *Obj = dyn_cast<ObjectFile>(S.Sym.getObject());
+  if (!Obj)
+    return;
+  const SymbolRef Sym(S.Sym);
+  uint64_t SectionIndex = object::SectionedAddress::UndefSection;
+  section_iterator Sec = cantFail(Sym.getSection());
+  if (Sec != Obj->section_end())
+    SectionIndex = Sec->getIndex();
+  object::SectionedAddress Address = {cantFail(Sym.getAddress()), SectionIndex};
+
+  std::string FileName;
+  uint32_t Line;
+  switch (S.TypeChar) {
+  // For undefined symbols, find the first relocation for that symbol with a
+  // line number.
+  case 'U': {
+    for (const SectionRef RelocsSec : Obj->sections()) {
+      if (RelocsSec.relocations().empty())
+        continue;
+      SectionRef TextSec = *cantFail(RelocsSec.getRelocatedSection());
+      if (!TextSec.isText())
+        continue;
+      for (const RelocationRef R : RelocsSec.relocations()) {
+        if (R.getSymbol() != Sym)
+          continue;
+        Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(
+            *Obj, {TextSec.getAddress() + R.getOffset(), SectionIndex});
+        if (!ResOrErr) {
+          error(ResOrErr.takeError(), Obj->getFileName());
+          return;
+        }
+        if (ResOrErr->FileName == DILineInfo::BadString)
+          return;
+        FileName = std::move(ResOrErr->FileName);
+        Line = ResOrErr->Line;
+        break;
+      }
+      if (!FileName.empty())
+        break;
+    }
+    if (FileName.empty())
+      return;
+    break;
+  }
+  case 't':
+  case 'T': {
+    Expected<DILineInfo> ResOrErr = Symbolizer.symbolizeCode(*Obj, Address);
+    if (!ResOrErr) {
+      error(ResOrErr.takeError(), Obj->getFileName());
+      return;
+    }
+    if (ResOrErr->FileName == DILineInfo::BadString)
+      return;
+    FileName = std::move(ResOrErr->FileName);
+    Line = ResOrErr->Line;
+    break;
+  }
+  default: {
+    Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(*Obj, Address);
+    if (!ResOrErr) {
+      error(ResOrErr.takeError(), Obj->getFileName());
+      return;
+    }
+    if (ResOrErr->DeclFile.empty())
+      return;
+    FileName = std::move(ResOrErr->DeclFile);
+    Line = ResOrErr->DeclLine;
+    break;
+  }
+  }
+  outs() << '\t' << FileName << ':' << Line;
+}
+
 static void printSymbolList(SymbolicFile &Obj,
                             std::vector<NMSymbol> &SymbolList, bool printName,
                             StringRef ArchiveName, StringRef ArchitectureName) {
+  std::optional<symbolize::LLVMSymbolizer> Symbolizer;
+  if (LineNumbers)
+    Symbolizer.emplace();
+
   if (!PrintFileName) {
     if ((OutputFormat == bsd || OutputFormat == posix ||
          OutputFormat == just_symbols) &&
@@ -751,15 +782,8 @@
 
     std::string Name = S.Name;
     MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
-    if (Demangle) {
-      function_ref<std::optional<std::string>(StringRef)> Fn = ::demangle;
-      if (Obj.isXCOFF())
-        Fn = demangleXCOFF;
-      if (Obj.isMachO())
-        Fn = demangleMachO;
-      if (std::optional<std::string> Opt = Fn(S.Name))
-        Name = *Opt;
-    }
+    if (Demangle)
+      Name = demangle(Name);
 
     if (PrintFileName)
       writeFileName(outs(), ArchiveName, ArchitectureName);
@@ -806,7 +830,7 @@
                         printFormat);
     } else if (OutputFormat == posix) {
       outs() << Name << " " << S.TypeChar << " " << SymbolAddrStr << " "
-             << (MachO ? "0" : SymbolSizeStr) << "\n";
+             << (MachO ? "0" : SymbolSizeStr);
     } else if (OutputFormat == bsd || (OutputFormat == darwin && !MachO)) {
       if (PrintAddress)
         outs() << SymbolAddrStr << ' ';
@@ -827,12 +851,14 @@
         } else
           outs() << S.IndirectName << ")";
       }
-      outs() << "\n";
     } else if (OutputFormat == sysv) {
       outs() << left_justify(Name, 20) << "|" << SymbolAddrStr << "|   "
              << S.TypeChar << "  |" << right_justify(S.TypeName, 18) << "|"
-             << SymbolSizeStr << "|     |" << S.SectionName << "\n";
+             << SymbolSizeStr << "|     |" << S.SectionName;
     }
+    if (LineNumbers)
+      printLineNumbers(*Symbolizer, S);
+    outs() << '\n';
   }
 
   SymbolList.clear();
@@ -873,7 +899,7 @@
       consumeError(NameOrErr.takeError());
       return '?';
     }
-    if ((*NameOrErr).startswith(".debug"))
+    if ((*NameOrErr).starts_with(".debug"))
       return 'N';
     if (!(Flags & ELF::SHF_WRITE))
       return 'n';
@@ -912,7 +938,7 @@
     const coff_section *Section = Obj.getCOFFSection(*SecI);
     Characteristics = Section->Characteristics;
     if (Expected<StringRef> NameOrErr = Obj.getSectionName(Section))
-      if (NameOrErr->startswith(".idata"))
+      if (NameOrErr->starts_with(".idata"))
         return 'i';
   }
 
@@ -1031,10 +1057,12 @@
 static char getSymbolNMTypeChar(TapiFile &Obj, basic_symbol_iterator I) {
   auto Type = cantFail(Obj.getSymbolType(I->getRawDataRefImpl()));
   switch (Type) {
-  case SymbolRef::ST_Data:
-    return 'd';
   case SymbolRef::ST_Function:
     return 't';
+  case SymbolRef::ST_Data:
+    if (Obj.hasSegmentInfo())
+      return 'd';
+    [[fallthrough]];
   default:
     return 's';
   }
@@ -1709,13 +1737,13 @@
     StringRef SymName = cantFail(Sym.getName());
     if (SymName.empty())
       continue;
-    if (SymName.startswith("__sinit") || SymName.startswith("__sterm") ||
+    if (SymName.starts_with("__sinit") || SymName.starts_with("__sterm") ||
         SymName.front() == '.' || SymName.front() == '(')
       continue;
 
     // Check the SymName regex matching with "^__[0-9]+__".
-    if (SymName.size() > 4 && SymName.startswith("__") &&
-        SymName.endswith("__")) {
+    if (SymName.size() > 4 && SymName.starts_with("__") &&
+        SymName.ends_with("__")) {
       if (std::all_of(SymName.begin() + 2, SymName.end() - 2, isDigit))
         continue;
     }
@@ -1723,9 +1751,9 @@
     if (SymName == "__rsrc" && NoRsrc)
       continue;
 
-    if (SymName.startswith("__tf1"))
+    if (SymName.starts_with("__tf1"))
       SymName = SymName.substr(6);
-    else if (SymName.startswith("__tf9"))
+    else if (SymName.starts_with("__tf9"))
       SymName = SymName.substr(14);
 
     NMSymbol S = {};
@@ -1802,9 +1830,12 @@
       // are used to repesent mapping symbols and needed to honor the
       // --special-syms option.
       auto *ELFObj = dyn_cast<ELFObjectFileBase>(&Obj);
-      if ((!ELFObj || (ELFObj->getEMachine() != ELF::EM_ARM &&
-                       ELFObj->getEMachine() != ELF::EM_AARCH64)) &&
-          !DebugSyms && (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific))
+      bool HasMappingSymbol =
+          ELFObj && llvm::is_contained({ELF::EM_ARM, ELF::EM_AARCH64,
+                                        ELF::EM_CSKY, ELF::EM_RISCV},
+                                       ELFObj->getEMachine());
+      if (!HasMappingSymbol && !DebugSyms &&
+          (*SymFlagsOrErr & SymbolRef::SF_FormatSpecific))
         continue;
       if (WithoutAliases && (*SymFlagsOrErr & SymbolRef::SF_Indirect))
         continue;
@@ -1823,6 +1854,12 @@
               dyn_cast<const XCOFFObjectFile>(&Obj))
         S.Size = XCOFFObj->getSymbolSize(Sym.getRawDataRefImpl());
 
+      if (const WasmObjectFile *WasmObj = dyn_cast<WasmObjectFile>(&Obj)) {
+        const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym);
+        if (WasmSym.isTypeData() && !WasmSym.isUndefined())
+          S.Size = WasmSym.Info.DataRef.Size;
+      }
+
       if (PrintAddress && isa<ObjectFile>(Obj)) {
         SymbolRef SymRef(Sym);
         Expected<uint64_t> AddressOrErr = SymRef.getAddress();
@@ -1889,6 +1926,62 @@
   return !Obj.symbols().empty();
 }
 
+static void printSymbolNamesFromObject(
+    SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,
+    bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},
+    StringRef ArchitectureName = {}, StringRef ObjectName = {},
+    bool PrintArchiveName = true) {
+
+  if (PrintObjectLabel && !ExportSymbols)
+    printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName,
+                     ObjectName.empty() ? Obj.getFileName() : ObjectName);
+
+  if (!getSymbolNamesFromObject(Obj, SymbolList) || ExportSymbols)
+    return;
+
+  // If there is an error in hasSymbols(), the error should be encountered in
+  // function getSymbolNamesFromObject first.
+  if (!cantFail(hasSymbols(Obj)) && SymbolList.empty() && !Quiet) {
+    writeFileName(errs(), ArchiveName, ArchitectureName);
+    errs() << "no symbols\n";
+  }
+
+  sortSymbolList(SymbolList);
+  printSymbolList(Obj, SymbolList, PrintSymbolObject, ArchiveName,
+                  ArchitectureName);
+}
+
+static void dumpSymbolsNameFromMachOFilesetEntry(
+    MachOObjectFile *Obj, std::vector<NMSymbol> &SymbolList,
+    bool PrintSymbolObject, bool PrintObjectLabel) {
+  auto Buf = Obj->getMemoryBufferRef();
+  const auto *End = Obj->load_commands().end();
+  for (const auto *It = Obj->load_commands().begin(); It != End; ++It) {
+    const auto &Command = *It;
+    if (Command.C.cmd != MachO::LC_FILESET_ENTRY)
+      continue;
+
+    MachO::fileset_entry_command Entry =
+        Obj->getFilesetEntryLoadCommand(Command);
+    auto MaybeMachO =
+        MachOObjectFile::createMachOObjectFile(Buf, 0, 0, Entry.fileoff);
+
+    if (Error Err = MaybeMachO.takeError())
+      report_fatal_error(std::move(Err));
+
+    const char *EntryName = Command.Ptr + Entry.entry_id.offset;
+    if (EntryName)
+      outs() << "Symbols for " << EntryName << ": \n";
+
+    std::unique_ptr<MachOObjectFile> EntryMachO = std::move(MaybeMachO.get());
+    printSymbolNamesFromObject(*EntryMachO, SymbolList, PrintSymbolObject,
+                               PrintObjectLabel);
+
+    if (std::next(It) != End)
+      outs() << "\n";
+  }
+}
+
 static void dumpSymbolNamesFromObject(
     SymbolicFile &Obj, std::vector<NMSymbol> &SymbolList,
     bool PrintSymbolObject, bool PrintObjectLabel, StringRef ArchiveName = {},
@@ -1903,23 +1996,21 @@
     return;
   }
 
-  if (PrintObjectLabel && !ExportSymbols)
-    printObjectLabel(PrintArchiveName, ArchiveName, ArchitectureName,
-                     ObjectName.empty() ? Obj.getFileName() : ObjectName);
-  if (!getSymbolNamesFromObject(Obj, SymbolList) || ExportSymbols)
-    return;
   CurrentFilename = Obj.getFileName();
 
-  // If there is an error in hasSymbols(), the error should be encountered in
-  // function getSymbolNamesFromObject first.
-  if (!cantFail(hasSymbols(Obj)) && SymbolList.empty() && !Quiet) {
-    writeFileName(errs(), ArchiveName, ArchitectureName);
-    errs() << "no symbols\n";
+  // Are we handling a MachO of type MH_FILESET?
+  if (Obj.isMachO() && Obj.is64Bit() &&
+      cast<MachOObjectFile>(&Obj)->getHeader64().filetype ==
+          MachO::MH_FILESET) {
+    dumpSymbolsNameFromMachOFilesetEntry(cast<MachOObjectFile>(&Obj),
+                                         SymbolList, PrintSymbolObject,
+                                         PrintObjectLabel);
+    return;
   }
 
-  sortSymbolList(SymbolList);
-  printSymbolList(Obj, SymbolList, PrintSymbolObject, ArchiveName,
-                  ArchitectureName);
+  printSymbolNamesFromObject(Obj, SymbolList, PrintSymbolObject,
+                             PrintObjectLabel, ArchiveName, ArchitectureName,
+                             ObjectName, PrintArchiveName);
 }
 
 // checkMachOAndArchFlags() checks to see if the SymbolicFile is a Mach-O file
@@ -2267,6 +2358,14 @@
   if (error(BufferOrErr.getError(), Filename))
     return SymbolList;
 
+  // Ignore AIX linker import files (these files start with "#!"), when
+  // exporting symbols.
+  const char *BuffStart = (*BufferOrErr)->getBufferStart();
+  size_t BufferSize = (*BufferOrErr)->getBufferSize();
+  if (ExportSymbols && BufferSize >= 2 && BuffStart[0] == '#' &&
+      BuffStart[1] == '!')
+    return SymbolList;
+
   LLVMContext Context;
   LLVMContext *ContextPtr = NoLLVMBitcode ? nullptr : &Context;
   Expected<std::unique_ptr<Binary>> BinaryOrErr =
@@ -2305,7 +2404,6 @@
 }
 
 int llvm_nm_main(int argc, char **argv, const llvm::ToolContext &) {
-  InitLLVM X(argc, argv);
   BumpPtrAllocator A;
   StringSaver Saver(A);
   NmOptTable Tbl;
@@ -2350,6 +2448,7 @@
   else
     error("--format value should be one of: bsd, posix, sysv, darwin, "
           "just-symbols");
+  LineNumbers = Args.hasArg(OPT_line_numbers);
   NoLLVMBitcode = Args.hasArg(OPT_no_llvm_bc);
   NoSort = Args.hasArg(OPT_no_sort);
   NoWeakSymbols = Args.hasArg(OPT_no_weak);
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index 265e4fc..f63e5c6 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -10,7 +10,6 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSet.h"
 #include "llvm/BinaryFormat/COFF.h"
 #include "llvm/ObjCopy/CommonConfig.h"
 #include "llvm/ObjCopy/ConfigManager.h"
@@ -26,13 +25,12 @@
 
 using namespace llvm;
 using namespace llvm::objcopy;
+using namespace llvm::opt;
 
 namespace {
 enum ObjcopyID {
   OBJCOPY_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OBJCOPY_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
 #include "ObjcopyOpts.inc"
 #undef OPTION
 };
@@ -46,12 +44,8 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info ObjcopyInfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {PREFIX,          NAME,         HELPTEXT,                                    \
-   METAVAR,         OBJCOPY_##ID, opt::Option::KIND##Class,                    \
-   PARAM,           FLAGS,        OBJCOPY_##GROUP,                             \
-   OBJCOPY_##ALIAS, ALIASARGS,    VALUES},
+#define OPTION(...)                                                            \
+  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJCOPY_, __VA_ARGS__),
 #include "ObjcopyOpts.inc"
 #undef OPTION
 };
@@ -66,9 +60,8 @@
 
 enum InstallNameToolID {
   INSTALL_NAME_TOOL_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  INSTALL_NAME_TOOL_##ID,
+#define OPTION(...)                                                            \
+  LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
 #include "InstallNameToolOpts.inc"
 #undef OPTION
 };
@@ -83,20 +76,8 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {PREFIX,                                                                     \
-   NAME,                                                                       \
-   HELPTEXT,                                                                   \
-   METAVAR,                                                                    \
-   INSTALL_NAME_TOOL_##ID,                                                     \
-   opt::Option::KIND##Class,                                                   \
-   PARAM,                                                                      \
-   FLAGS,                                                                      \
-   INSTALL_NAME_TOOL_##GROUP,                                                  \
-   INSTALL_NAME_TOOL_##ALIAS,                                                  \
-   ALIASARGS,                                                                  \
-   VALUES},
+#define OPTION(...)                                                            \
+  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(INSTALL_NAME_TOOL_, __VA_ARGS__),
 #include "InstallNameToolOpts.inc"
 #undef OPTION
 };
@@ -110,9 +91,8 @@
 
 enum BitcodeStripID {
   BITCODE_STRIP_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  BITCODE_STRIP_##ID,
+#define OPTION(...)                                                            \
+  LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
 #include "BitcodeStripOpts.inc"
 #undef OPTION
 };
@@ -127,20 +107,8 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {PREFIX,                                                                     \
-   NAME,                                                                       \
-   HELPTEXT,                                                                   \
-   METAVAR,                                                                    \
-   BITCODE_STRIP_##ID,                                                         \
-   opt::Option::KIND##Class,                                                   \
-   PARAM,                                                                      \
-   FLAGS,                                                                      \
-   BITCODE_STRIP_##GROUP,                                                      \
-   BITCODE_STRIP_##ALIAS,                                                      \
-   ALIASARGS,                                                                  \
-   VALUES},
+#define OPTION(...)                                                            \
+  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(BITCODE_STRIP_, __VA_ARGS__),
 #include "BitcodeStripOpts.inc"
 #undef OPTION
 };
@@ -154,9 +122,7 @@
 
 enum StripID {
   STRIP_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  STRIP_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
 #include "StripOpts.inc"
 #undef OPTION
 };
@@ -170,12 +136,7 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info StripInfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {PREFIX,        NAME,       HELPTEXT,                                        \
-   METAVAR,       STRIP_##ID, opt::Option::KIND##Class,                        \
-   PARAM,         FLAGS,      STRIP_##GROUP,                                   \
-   STRIP_##ALIAS, ALIASARGS,  VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(STRIP_, __VA_ARGS__),
 #include "StripOpts.inc"
 #undef OPTION
 };
@@ -205,6 +166,7 @@
       .CaseLower("contents", SectionFlag::SecContents)
       .CaseLower("share", SectionFlag::SecShare)
       .CaseLower("exclude", SectionFlag::SecExclude)
+      .CaseLower("large", SectionFlag::SecLarge)
       .Default(SectionFlag::SecNone);
 }
 
@@ -218,7 +180,7 @@
           errc::invalid_argument,
           "unrecognized section flag '%s'. Flags supported for GNU "
           "compatibility: alloc, load, noload, readonly, exclude, debug, "
-          "code, data, rom, share, contents, merge, strings",
+          "code, data, rom, share, contents, merge, strings, large",
           Flag.str().c_str());
     ParsedFlags |= ParsedFlag;
   }
@@ -337,6 +299,8 @@
     // LoongArch
     {"elf32-loongarch", {ELF::EM_LOONGARCH, false, true}},
     {"elf64-loongarch", {ELF::EM_LOONGARCH, true, true}},
+    // SystemZ
+    {"elf64-s390", {ELF::EM_S390, true, false}},
 };
 
 static Expected<TargetInfo>
@@ -353,7 +317,7 @@
     MI.OSABI = ELF::ELFOSABI_FREEBSD;
 
   FileFormat Format;
-  if (TargetName.startswith("elf"))
+  if (TargetName.starts_with("elf"))
     Format = FileFormat::ELF;
   else
     // This should never happen because `TargetName` is valid (it certainly
@@ -775,6 +739,35 @@
   if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
     Config.ExtractPartition = Arg->getValue();
 
+  if (const auto *A = InputArgs.getLastArg(OBJCOPY_gap_fill)) {
+    if (Config.OutputFormat != FileFormat::Binary)
+      return createStringError(
+          errc::invalid_argument,
+          "'--gap-fill' is only supported for binary output");
+    ErrorOr<uint64_t> Val = getAsInteger<uint64_t>(A->getValue());
+    if (!Val)
+      return createStringError(Val.getError(), "--gap-fill: bad number: %s",
+                               A->getValue());
+    uint8_t ByteVal = Val.get();
+    if (ByteVal != Val.get())
+      return createStringError(std::errc::value_too_large,
+                               "gap-fill value %s is out of range (0 to 0xff)",
+                               A->getValue());
+    Config.GapFill = ByteVal;
+  }
+
+  if (const auto *A = InputArgs.getLastArg(OBJCOPY_pad_to)) {
+    if (Config.OutputFormat != FileFormat::Binary)
+      return createStringError(
+          errc::invalid_argument,
+          "'--pad-to' is only supported for binary output");
+    ErrorOr<uint64_t> Addr = getAsInteger<uint64_t>(A->getValue());
+    if (!Addr)
+      return createStringError(Addr.getError(), "--pad-to: bad number: %s",
+                               A->getValue());
+    Config.PadTo = *Addr;
+  }
+
   for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
     if (!StringRef(Arg->getValue()).contains('='))
       return createStringError(errc::invalid_argument,
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.h b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.h
index f7fa2af..3b88789 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.h
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.h
@@ -11,7 +11,6 @@
 
 #include "llvm/ObjCopy/ConfigManager.h"
 #include "llvm/Support/Allocator.h"
-#include <vector>
 
 namespace llvm {
 namespace objcopy {
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index a7e4263..ead8cd2 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -52,7 +52,7 @@
          "Renames a section from old to new, optionally with specified flags. "
          "Flags supported for GNU compatibility: alloc, load, noload, "
          "readonly, exclude, debug, code, data, rom, share, contents, merge, "
-         "strings">,
+         "strings, large">,
       MetaVarName<"old=new[,flag1,...]">;
 defm redefine_symbol
     : Eq<"redefine-sym", "Change the name of a symbol old to new">,
@@ -85,7 +85,7 @@
     : Eq<"set-section-flags",
          "Set section flags for a given section. Flags supported for GNU "
          "compatibility: alloc, load, noload, readonly, exclude, debug, code, "
-         "data, rom, share, contents, merge, strings">,
+         "data, rom, share, contents, merge, strings, large">,
       MetaVarName<"section=flag1[,flag2,...]">;
 
 defm set_section_type
@@ -230,3 +230,15 @@
 defm update_section
     : Eq<"update-section", "Replace the contents of section <name> with contents from a file <file>">,
       MetaVarName<"name=file">;
+
+defm gap_fill
+    : Eq<"gap-fill", "Fill the gaps between sections with <value> instead of zero. "
+                     "<value> must be an unsigned 8-bit integer. "
+                     "This option is only supported for ELF input and binary output">,
+      MetaVarName<"value">;
+
+defm pad_to
+    : Eq<"pad-to", "Pad the output up to the load address <address>, using a value "
+                   "of zero or the value specified by the --gap-fill option. "
+                   "This option is only supported for ELF input and binary output">,
+      MetaVarName<"address">;
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index 2afa976..730f423 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -42,7 +42,6 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ErrorOr.h"
 #include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/Memory.h"
 #include "llvm/Support/Path.h"
@@ -56,7 +55,6 @@
 #include <cassert>
 #include <cstdlib>
 #include <memory>
-#include <string>
 #include <system_error>
 #include <utility>
 
@@ -225,7 +223,6 @@
 }
 
 int llvm_objcopy_main(int argc, char **argv, const llvm::ToolContext &) {
-  InitLLVM X(argc, argv);
   ToolName = argv[0];
 
   // Expand response files.
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt
index 65d2f92..0306736 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt
@@ -3,6 +3,7 @@
   AllTargetsDisassemblers
   AllTargetsInfos
   BinaryFormat
+  DebugInfoBTF
   DebugInfoDWARF
   Demangle
   MC
@@ -34,12 +35,11 @@
   DEPENDS
   ObjdumpOptsTableGen
   OtoolOptsTableGen
+  GENERATE_DRIVER
   )
 
-target_link_libraries(llvm-objdump PRIVATE LLVMDebuginfod)
-
-if(LLVM_HAVE_LIBXAR)
-  target_link_libraries(llvm-objdump PRIVATE ${XAR_LIB})
+if(NOT LLVM_TOOL_LLVM_DRIVER_BUILD)
+  target_link_libraries(llvm-objdump PRIVATE LLVMDebuginfod)
 endif()
 
 add_llvm_tool_symlink(llvm-otool llvm-objdump)
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
index e1b3847..71697fa 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
@@ -45,7 +45,7 @@
   }
 
   template <class PEHeader> void printPEHeader(const PEHeader &Hdr) const;
-  void printPrivateHeaders(bool MachOOnlyFirst) override;
+  void printPrivateHeaders() override;
 
 private:
   template <typename T> FormattedNumber formatAddr(T V) const {
@@ -771,7 +771,7 @@
   }
 }
 
-void COFFDumper::printPrivateHeaders(bool MachOOnlyFirst) {
+void COFFDumper::printPrivateHeaders() {
   COFFDumper CD(Obj);
   const uint16_t Cha = Obj.getCharacteristics();
   outs() << "Characteristics 0x" << Twine::utohexstr(Cha) << '\n';
@@ -857,7 +857,7 @@
            << "(nx " << unsigned(Symbol->getNumberOfAuxSymbols()) << ") "
            << "0x" << format("%08x", unsigned(Symbol->getValue())) << " "
            << Name;
-    if (Demangle && Name.startswith("?")) {
+    if (Demangle && Name.starts_with("?")) {
       int Status = -1;
       char *DemangledSymbol = microsoftDemangle(Name, nullptr, &Status);
 
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
index 5b08a4b..fda99bd 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -28,7 +28,7 @@
 template <typename ELFT> class ELFDumper : public Dumper {
 public:
   ELFDumper(const ELFObjectFile<ELFT> &O) : Dumper(O), Obj(O) {}
-  void printPrivateHeaders(bool MachOOnlyFirst) override;
+  void printPrivateHeaders() override;
   void printDynamicRelocations() override;
 
 private:
@@ -38,6 +38,7 @@
   void printDynamicSection();
   void printProgramHeaders();
   void printSymbolVersion();
+  void printSymbolVersionDependency(const typename ELFT::Shdr &Sec);
 };
 } // namespace
 
@@ -180,8 +181,10 @@
   // Search for a PT_LOAD segment containing the requested section. Use this
   // segment's p_addr to calculate the section's LMA.
   for (const typename ELFT::Phdr &Phdr : *PhdrRangeOrErr)
-    if ((Phdr.p_type == ELF::PT_LOAD) && (Phdr.p_vaddr <= Sec.getAddress()) &&
-        (Phdr.p_vaddr + Phdr.p_memsz > Sec.getAddress()))
+    if ((Phdr.p_type == ELF::PT_LOAD) &&
+        (isSectionInSegment<ELFT>(
+            Phdr, *cast<const ELFObjectFile<ELFT>>(Sec.getObject())
+                       ->getSection(Sec.getRawDataRefImpl()))))
       return Sec.getAddress() - Phdr.p_vaddr + Phdr.p_paddr;
 
   // Return section's VMA if it isn't in a PT_LOAD segment.
@@ -282,9 +285,15 @@
     case ELF::PT_OPENBSD_MUTABLE:
       outs() << "OPENBSD_MUTABLE ";
       break;
+    case ELF::PT_OPENBSD_NOBTCFI:
+      outs() << "OPENBSD_NOBTCFI ";
+      break;
     case ELF::PT_OPENBSD_RANDOMIZE:
       outs() << "OPENBSD_RANDOMIZE ";
       break;
+    case ELF::PT_OPENBSD_SYSCALLS:
+      outs() << "OPENBSD_SYSCALLS ";
+      break;
     case ELF::PT_OPENBSD_WXNEEDED:
       outs() << "OPENBSD_WXNEEDED ";
       break;
@@ -346,19 +355,13 @@
 }
 
 template <class ELFT>
-static void printSymbolVersionDependency(StringRef FileName,
-                                         const ELFFile<ELFT> &Obj,
-                                         const typename ELFT::Shdr &Sec) {
+void ELFDumper<ELFT>::printSymbolVersionDependency(
+    const typename ELFT::Shdr &Sec) {
   outs() << "\nVersion References:\n";
-
-  auto WarningHandler = [&](const Twine &Msg) {
-    reportWarning(Msg, FileName);
-    return Error::success();
-  };
   Expected<std::vector<VerNeed>> V =
-      Obj.getVersionDependencies(Sec, WarningHandler);
+      getELFFile().getVersionDependencies(Sec, this->WarningHandler);
   if (!V) {
-    reportWarning(toString(V.takeError()), FileName);
+    reportWarning(toString(V.takeError()), Obj.getFileName());
     return;
   }
 
@@ -420,13 +423,13 @@
     StringRef StrTab = unwrapOrError(Elf.getStringTable(*StrTabSec), FileName);
 
     if (Shdr.sh_type == ELF::SHT_GNU_verneed)
-      printSymbolVersionDependency<ELFT>(FileName, Elf, Shdr);
+      printSymbolVersionDependency(Shdr);
     else
       printSymbolVersionDefinition<ELFT>(Shdr, Contents, StrTab);
   }
 }
 
-template <class ELFT> void ELFDumper<ELFT>::printPrivateHeaders(bool) {
+template <class ELFT> void ELFDumper<ELFT>::printPrivateHeaders() {
   printProgramHeaders();
   printDynamicSection();
   printSymbolVersion();
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
index 11fb1cb..0e6935c 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
@@ -53,12 +53,6 @@
 #include <cstring>
 #include <system_error>
 
-#ifdef LLVM_HAVE_LIBXAR
-extern "C" {
-#include <xar/xar.h>
-}
-#endif
-
 using namespace llvm;
 using namespace llvm::object;
 using namespace llvm::objdump;
@@ -197,7 +191,7 @@
 
 public:
   MachODumper(const object::MachOObjectFile &O) : Dumper(O), Obj(O) {}
-  void printPrivateHeaders(bool OnlyFirst) override;
+  void printPrivateHeaders() override;
 };
 } // namespace
 
@@ -212,39 +206,6 @@
 typedef std::vector<DiceTableEntry> DiceTable;
 typedef DiceTable::iterator dice_table_iterator;
 
-#ifdef LLVM_HAVE_LIBXAR
-namespace {
-struct ScopedXarFile {
-  xar_t xar;
-  ScopedXarFile(const char *filename, int32_t flags) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
-    xar = xar_open(filename, flags);
-#pragma clang diagnostic pop
-  }
-  ~ScopedXarFile() {
-    if (xar)
-      xar_close(xar);
-  }
-  ScopedXarFile(const ScopedXarFile &) = delete;
-  ScopedXarFile &operator=(const ScopedXarFile &) = delete;
-  operator xar_t() { return xar; }
-};
-
-struct ScopedXarIter {
-  xar_iter_t iter;
-  ScopedXarIter() : iter(xar_iter_new()) {}
-  ~ScopedXarIter() {
-    if (iter)
-      xar_iter_free(iter);
-  }
-  ScopedXarIter(const ScopedXarIter &) = delete;
-  ScopedXarIter &operator=(const ScopedXarIter &) = delete;
-  operator xar_iter_t() { return iter; }
-};
-} // namespace
-#endif // defined(LLVM_HAVE_LIBXAR)
-
 // This is used to search for a data in code table entry for the PC being
 // disassembled.  The j parameter has the PC in j.first.  A single data in code
 // table entry can cover many bytes for each of its Kind's.  So if the offset,
@@ -329,7 +290,7 @@
   const StringRef FileName = MachOObj->getFileName();
   for (const SymbolRef &Symbol : MachOObj->symbols()) {
     StringRef SymName = unwrapOrError(Symbol.getName(), FileName);
-    if (!SymName.startswith("ltmp"))
+    if (!SymName.starts_with("ltmp"))
       Symbols.push_back(Symbol);
   }
 
@@ -1521,7 +1482,7 @@
         ST == SymbolRef::ST_Other) {
       uint64_t Address = cantFail(Symbol.getValue());
       StringRef SymName = unwrapOrError(Symbol.getName(), FileName);
-      if (!SymName.startswith(".objc"))
+      if (!SymName.starts_with(".objc"))
         (*AddrMap)[Address] = SymName;
     }
   }
@@ -1961,13 +1922,6 @@
                              StringRef DisSegName, StringRef DisSectName);
 static void DumpProtocolSection(MachOObjectFile *O, const char *sect,
                                 uint32_t size, uint32_t addr);
-#ifdef LLVM_HAVE_LIBXAR
-static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
-                                uint32_t size, bool verbose,
-                                bool PrintXarHeader, bool PrintXarFileHeaders,
-                                std::string XarMemberName);
-#endif // defined(LLVM_HAVE_LIBXAR)
-
 static void DumpSectionContents(StringRef Filename, MachOObjectFile *O,
                                 bool verbose) {
   SymbolAddressMap AddrMap;
@@ -2037,13 +1991,6 @@
             DumpProtocolSection(O, sect, sect_size, sect_addr);
             continue;
           }
-#ifdef LLVM_HAVE_LIBXAR
-          if (SegName == "__LLVM" && SectName == "__bundle") {
-            DumpBitcodeSection(O, sect, sect_size, verbose, SymbolicOperands,
-                               ArchiveHeaders, "");
-            continue;
-          }
-#endif // defined(LLVM_HAVE_LIBXAR)
           switch (section_type) {
           case MachO::S_REGULAR:
             DumpRawSectionContents(O, sect, sect_size, sect_addr);
@@ -6732,371 +6679,6 @@
   }
 }
 
-#ifdef LLVM_HAVE_LIBXAR
-static inline void swapStruct(struct xar_header &xar) {
-  sys::swapByteOrder(xar.magic);
-  sys::swapByteOrder(xar.size);
-  sys::swapByteOrder(xar.version);
-  sys::swapByteOrder(xar.toc_length_compressed);
-  sys::swapByteOrder(xar.toc_length_uncompressed);
-  sys::swapByteOrder(xar.cksum_alg);
-}
-
-static void PrintModeVerbose(uint32_t mode) {
-  switch(mode & S_IFMT){
-  case S_IFDIR:
-    outs() << "d";
-    break;
-  case S_IFCHR:
-    outs() << "c";
-    break;
-  case S_IFBLK:
-    outs() << "b";
-    break;
-  case S_IFREG:
-    outs() << "-";
-    break;
-  case S_IFLNK:
-    outs() << "l";
-    break;
-  case S_IFSOCK:
-    outs() << "s";
-    break;
-  default:
-    outs() << "?";
-    break;
-  }
-
-  /* owner permissions */
-  if(mode & S_IREAD)
-    outs() << "r";
-  else
-    outs() << "-";
-  if(mode & S_IWRITE)
-    outs() << "w";
-  else
-    outs() << "-";
-  if(mode & S_ISUID)
-    outs() << "s";
-  else if(mode & S_IEXEC)
-    outs() << "x";
-  else
-    outs() << "-";
-
-  /* group permissions */
-  if(mode & (S_IREAD >> 3))
-    outs() << "r";
-  else
-    outs() << "-";
-  if(mode & (S_IWRITE >> 3))
-    outs() << "w";
-  else
-    outs() << "-";
-  if(mode & S_ISGID)
-    outs() << "s";
-  else if(mode & (S_IEXEC >> 3))
-    outs() << "x";
-  else
-    outs() << "-";
-
-  /* other permissions */
-  if(mode & (S_IREAD >> 6))
-    outs() << "r";
-  else
-    outs() << "-";
-  if(mode & (S_IWRITE >> 6))
-    outs() << "w";
-  else
-    outs() << "-";
-  if(mode & S_ISVTX)
-    outs() << "t";
-  else if(mode & (S_IEXEC >> 6))
-    outs() << "x";
-  else
-    outs() << "-";
-}
-
-static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) {
-  xar_file_t xf;
-  const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m;
-  char *endp;
-  uint32_t mode_value;
-
-  ScopedXarIter xi;
-  if (!xi) {
-    WithColor::error(errs(), "llvm-objdump")
-        << "can't obtain an xar iterator for xar archive " << XarFilename
-        << "\n";
-    return;
-  }
-
-  // Go through the xar's files.
-  for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
-    ScopedXarIter xp;
-    if(!xp){
-      WithColor::error(errs(), "llvm-objdump")
-          << "can't obtain an xar iterator for xar archive " << XarFilename
-          << "\n";
-      return;
-    }
-    type = nullptr;
-    mode = nullptr;
-    user = nullptr;
-    group = nullptr;
-    size = nullptr;
-    mtime = nullptr;
-    name = nullptr;
-    for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
-      const char *val = nullptr;
-      xar_prop_get(xf, key, &val);
-#if 0 // Useful for debugging.
-      outs() << "key: " << key << " value: " << val << "\n";
-#endif
-      if(strcmp(key, "type") == 0)
-        type = val;
-      if(strcmp(key, "mode") == 0)
-        mode = val;
-      if(strcmp(key, "user") == 0)
-        user = val;
-      if(strcmp(key, "group") == 0)
-        group = val;
-      if(strcmp(key, "data/size") == 0)
-        size = val;
-      if(strcmp(key, "mtime") == 0)
-        mtime = val;
-      if(strcmp(key, "name") == 0)
-        name = val;
-    }
-    if(mode != nullptr){
-      mode_value = strtoul(mode, &endp, 8);
-      if(*endp != '\0')
-        outs() << "(mode: \"" << mode << "\" contains non-octal chars) ";
-      if(strcmp(type, "file") == 0)
-        mode_value |= S_IFREG;
-      PrintModeVerbose(mode_value);
-      outs() << " ";
-    }
-    if(user != nullptr)
-      outs() << format("%10s/", user);
-    if(group != nullptr)
-      outs() << format("%-10s ", group);
-    if(size != nullptr)
-      outs() << format("%7s ", size);
-    if(mtime != nullptr){
-      for(m = mtime; *m != 'T' && *m != '\0'; m++)
-        outs() << *m;
-      if(*m == 'T')
-        m++;
-      outs() << " ";
-      for( ; *m != 'Z' && *m != '\0'; m++)
-        outs() << *m;
-      outs() << " ";
-    }
-    if(name != nullptr)
-      outs() << name;
-    outs() << "\n";
-  }
-}
-
-static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
-                                uint32_t size, bool verbose,
-                                bool PrintXarHeader, bool PrintXarFileHeaders,
-                                std::string XarMemberName) {
-  if(size < sizeof(struct xar_header)) {
-    outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
-              "of struct xar_header)\n";
-    return;
-  }
-  struct xar_header XarHeader;
-  memcpy(&XarHeader, sect, sizeof(struct xar_header));
-  if (sys::IsLittleEndianHost)
-    swapStruct(XarHeader);
-  if (PrintXarHeader) {
-    if (!XarMemberName.empty())
-      outs() << "In xar member " << XarMemberName << ": ";
-    else
-      outs() << "For (__LLVM,__bundle) section: ";
-    outs() << "xar header\n";
-    if (XarHeader.magic == XAR_HEADER_MAGIC)
-      outs() << "                  magic XAR_HEADER_MAGIC\n";
-    else
-      outs() << "                  magic "
-             << format_hex(XarHeader.magic, 10, true)
-             << " (not XAR_HEADER_MAGIC)\n";
-    outs() << "                   size " << XarHeader.size << "\n";
-    outs() << "                version " << XarHeader.version << "\n";
-    outs() << "  toc_length_compressed " << XarHeader.toc_length_compressed
-           << "\n";
-    outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
-           << "\n";
-    outs() << "              cksum_alg ";
-    switch (XarHeader.cksum_alg) {
-      case XAR_CKSUM_NONE:
-        outs() << "XAR_CKSUM_NONE\n";
-        break;
-      case XAR_CKSUM_SHA1:
-        outs() << "XAR_CKSUM_SHA1\n";
-        break;
-      case XAR_CKSUM_MD5:
-        outs() << "XAR_CKSUM_MD5\n";
-        break;
-#ifdef XAR_CKSUM_SHA256
-      case XAR_CKSUM_SHA256:
-        outs() << "XAR_CKSUM_SHA256\n";
-        break;
-#endif
-#ifdef XAR_CKSUM_SHA512
-      case XAR_CKSUM_SHA512:
-        outs() << "XAR_CKSUM_SHA512\n";
-        break;
-#endif
-      default:
-        outs() << XarHeader.cksum_alg << "\n";
-    }
-  }
-
-  SmallString<128> XarFilename;
-  int FD;
-  std::error_code XarEC =
-      sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename);
-  if (XarEC) {
-    WithColor::error(errs(), "llvm-objdump") << XarEC.message() << "\n";
-    return;
-  }
-  ToolOutputFile XarFile(XarFilename, FD);
-  raw_fd_ostream &XarOut = XarFile.os();
-  StringRef XarContents(sect, size);
-  XarOut << XarContents;
-  XarOut.close();
-  if (XarOut.has_error())
-    return;
-
-  ScopedXarFile xar(XarFilename.c_str(), READ);
-  if (!xar) {
-    WithColor::error(errs(), "llvm-objdump")
-        << "can't create temporary xar archive " << XarFilename << "\n";
-    return;
-  }
-
-  SmallString<128> TocFilename;
-  std::error_code TocEC =
-      sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename);
-  if (TocEC) {
-    WithColor::error(errs(), "llvm-objdump") << TocEC.message() << "\n";
-    return;
-  }
-  xar_serialize(xar, TocFilename.c_str());
-
-  if (PrintXarFileHeaders) {
-    if (!XarMemberName.empty())
-      outs() << "In xar member " << XarMemberName << ": ";
-    else
-      outs() << "For (__LLVM,__bundle) section: ";
-    outs() << "xar archive files:\n";
-    PrintXarFilesSummary(XarFilename.c_str(), xar);
-  }
-
-  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
-    MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
-  if (std::error_code EC = FileOrErr.getError()) {
-    WithColor::error(errs(), "llvm-objdump") << EC.message() << "\n";
-    return;
-  }
-  std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
-
-  if (!XarMemberName.empty())
-    outs() << "In xar member " << XarMemberName << ": ";
-  else
-    outs() << "For (__LLVM,__bundle) section: ";
-  outs() << "xar table of contents:\n";
-  outs() << Buffer->getBuffer() << "\n";
-
-  // TODO: Go through the xar's files.
-  ScopedXarIter xi;
-  if(!xi){
-    WithColor::error(errs(), "llvm-objdump")
-        << "can't obtain an xar iterator for xar archive "
-        << XarFilename.c_str() << "\n";
-    return;
-  }
-  for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){
-    const char *key;
-    const char *member_name, *member_type, *member_size_string;
-    size_t member_size;
-
-    ScopedXarIter xp;
-    if(!xp){
-      WithColor::error(errs(), "llvm-objdump")
-          << "can't obtain an xar iterator for xar archive "
-          << XarFilename.c_str() << "\n";
-      return;
-    }
-    member_name = NULL;
-    member_type = NULL;
-    member_size_string = NULL;
-    for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){
-      const char *val = nullptr;
-      xar_prop_get(xf, key, &val);
-#if 0 // Useful for debugging.
-      outs() << "key: " << key << " value: " << val << "\n";
-#endif
-      if (strcmp(key, "name") == 0)
-        member_name = val;
-      if (strcmp(key, "type") == 0)
-        member_type = val;
-      if (strcmp(key, "data/size") == 0)
-        member_size_string = val;
-    }
-    /*
-     * If we find a file with a name, date/size and type properties
-     * and with the type being "file" see if that is a xar file.
-     */
-    if (member_name != NULL && member_type != NULL &&
-        strcmp(member_type, "file") == 0 &&
-        member_size_string != NULL){
-      // Extract the file into a buffer.
-      char *endptr;
-      member_size = strtoul(member_size_string, &endptr, 10);
-      if (*endptr == '\0' && member_size != 0) {
-        char *buffer;
-        if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
-#if 0 // Useful for debugging.
-          outs() << "xar member: " << member_name << " extracted\n";
-#endif
-          // Set the XarMemberName we want to see printed in the header.
-          std::string OldXarMemberName;
-          // If XarMemberName is already set this is nested. So
-          // save the old name and create the nested name.
-          if (!XarMemberName.empty()) {
-            OldXarMemberName = XarMemberName;
-            XarMemberName =
-                (Twine("[") + XarMemberName + "]" + member_name).str();
-          } else {
-            OldXarMemberName = "";
-            XarMemberName = member_name;
-          }
-          // See if this is could be a xar file (nested).
-          if (member_size >= sizeof(struct xar_header)) {
-#if 0 // Useful for debugging.
-            outs() << "could be a xar file: " << member_name << "\n";
-#endif
-            memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
-            if (sys::IsLittleEndianHost)
-              swapStruct(XarHeader);
-            if (XarHeader.magic == XAR_HEADER_MAGIC)
-              DumpBitcodeSection(O, buffer, member_size, verbose,
-                                 PrintXarHeader, PrintXarFileHeaders,
-                                 XarMemberName);
-          }
-          XarMemberName = OldXarMemberName;
-          delete buffer;
-        }
-      }
-    }
-  }
-}
-#endif // defined(LLVM_HAVE_LIBXAR)
-
 static void printObjcMetaData(MachOObjectFile *O, bool verbose) {
   if (O->is64Bit())
     printObjc2_64bit_MetaData(O, verbose);
@@ -8047,16 +7629,13 @@
 
 template <typename T>
 static uint64_t read(StringRef Contents, ptrdiff_t Offset) {
-  using llvm::support::little;
-  using llvm::support::unaligned;
-
   if (Offset + sizeof(T) > Contents.size()) {
     outs() << "warning: attempt to read past end of buffer\n";
     return T();
   }
 
-  uint64_t Val =
-      support::endian::read<T, little, unaligned>(Contents.data() + Offset);
+  uint64_t Val = support::endian::read<T, llvm::endianness::little>(
+      Contents.data() + Offset);
   return Val;
 }
 
@@ -10554,9 +10133,9 @@
   PrintMachHeader(file, Verbose);
 }
 
-void MachODumper::printPrivateHeaders(bool OnlyFirst) {
+void MachODumper::printPrivateHeaders() {
   printMachOFileHeader(&Obj);
-  if (!OnlyFirst)
+  if (!FirstPrivateHeader)
     printMachOLoadCommands(&Obj);
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOptID.h b/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOptID.h
index 65f6c60..fc90cb5 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOptID.h
+++ b/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOptID.h
@@ -1,11 +1,11 @@
 #ifndef LLVM_TOOLS_LLVM_OBJDUMP_OBJDUMP_OPT_ID_H
 #define LLVM_TOOLS_LLVM_OBJDUMP_OBJDUMP_OPT_ID_H
 
+#include "llvm/Option/OptTable.h"
+
 enum ObjdumpOptID {
   OBJDUMP_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OBJDUMP_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OBJDUMP_, __VA_ARGS__),
 #include "ObjdumpOpts.inc"
 #undef OPTION
 };
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td b/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td
index e3e7476..c1dec5c 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td
+++ b/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td
@@ -87,6 +87,11 @@
 def : JoinedOrSeparate<["-"], "M">, Alias<disassembler_options_EQ>,
   HelpText<"Alias for --disassembler-options=">;
 
+def disassembler_color_EQ : Joined<["--"], "disassembler-color=">,
+  MetaVarName<"mode">,
+  HelpText<"Enable or disable disassembler color output. "
+           "Valid options are \"on\", \"off\" and \"terminal\" (default)">;
+
 def dynamic_reloc : Flag<["--"], "dynamic-reloc">,
   HelpText<"Display the dynamic relocation entries in the file">;
 def : Flag<["-"], "R">, Alias<dynamic_reloc>,
@@ -132,6 +137,9 @@
   MetaVarName<"a1,+a2,-a3,...">,
   HelpText<"Target specific attributes (--mattr=help for details)">;
 
+def mllvm : Separate<["-"], "mllvm">, HelpText<"Specify an argument to forward to LLVM's CommandLine library">, MetaVarName<"<arg>">;
+def : Joined<["-"], "mllvm=">, Alias<mllvm>;
+
 def no_show_raw_insn : Flag<["--"], "no-show-raw-insn">,
   HelpText<"When disassembling instructions, "
            "do not print the instruction bytes.">;
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp b/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp
index b2fe56c..76da865 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp
@@ -436,7 +436,7 @@
     OS << Delimiter << LineInfo.FunctionName;
     // If demangling is successful, FunctionName will end with "()". Print it
     // only if demangling did not run or was unsuccessful.
-    if (!StringRef(LineInfo.FunctionName).endswith("()"))
+    if (!StringRef(LineInfo.FunctionName).ends_with("()"))
       OS << "()";
     OS << ":\n";
   }
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/WasmDump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/WasmDump.cpp
index a1d767d..56c0847 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/WasmDump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/WasmDump.cpp
@@ -25,7 +25,7 @@
 
 public:
   WasmDumper(const WasmObjectFile &O) : Dumper(O), Obj(O) {}
-  void printPrivateHeaders(bool MachOOnlyFirst) override;
+  void printPrivateHeaders() override;
 };
 } // namespace
 
@@ -34,7 +34,7 @@
   return std::make_unique<WasmDumper>(Obj);
 }
 
-void WasmDumper::printPrivateHeaders(bool) {
+void WasmDumper::printPrivateHeaders() {
   outs() << "Program Header:\n";
   outs() << "Version: 0x";
   outs().write_hex(Obj.getHeader().Version);
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
index 87b1679..d9c00c0 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
@@ -32,7 +32,7 @@
 class XCOFFDumper : public objdump::Dumper {
 public:
   XCOFFDumper(const object::XCOFFObjectFile &O) : Dumper(O) {}
-  void printPrivateHeaders(bool MachOOnlyFirst) override;
+  void printPrivateHeaders() override {}
 };
 } // namespace
 
@@ -41,10 +41,9 @@
   return std::make_unique<XCOFFDumper>(Obj);
 }
 
-void XCOFFDumper::printPrivateHeaders(bool) {}
-
 Error objdump::getXCOFFRelocationValueString(const XCOFFObjectFile &Obj,
                                              const RelocationRef &Rel,
+                                             bool SymbolDescription,
                                              SmallVectorImpl<char> &Result) {
   symbol_iterator SymI = Rel.getSymbol();
   if (SymI == Obj.symbol_end())
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h b/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h
index cf5b19f..0ba6ba4 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h
+++ b/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h
@@ -33,6 +33,7 @@
 
 Error getXCOFFRelocationValueString(const object::XCOFFObjectFile &Obj,
                                     const object::RelocationRef &RelRef,
+                                    bool SymbolDescription,
                                     llvm::SmallVectorImpl<char> &Result);
 
 void dumpTracebackTable(ArrayRef<uint8_t> Bytes, uint64_t Address,
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp
index bd45ed1..22b427f 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -24,13 +24,12 @@
 #include "SourcePrinter.h"
 #include "WasmDump.h"
 #include "XCOFFDump.h"
-#include "llvm/ADT/IndexedMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetOperations.h"
-#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Twine.h"
+#include "llvm/DebugInfo/BTF/BTFParser.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
@@ -72,7 +71,7 @@
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/GraphWriter.h"
-#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/StringSaver.h"
@@ -85,6 +84,7 @@
 #include <cctype>
 #include <cstring>
 #include <optional>
+#include <set>
 #include <system_error>
 #include <unordered_map>
 #include <utility>
@@ -128,12 +128,8 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info ObjdumpInfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {PREFIX,          NAME,         HELPTEXT,                                    \
-   METAVAR,         OBJDUMP_##ID, opt::Option::KIND##Class,                    \
-   PARAM,           FLAGS,        OBJDUMP_##GROUP,                             \
-   OBJDUMP_##ALIAS, ALIASARGS,    VALUES},
+#define OPTION(...)                                                            \
+  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OBJDUMP_, __VA_ARGS__),
 #include "ObjdumpOpts.inc"
 #undef OPTION
 };
@@ -149,9 +145,7 @@
 
 enum OtoolOptID {
   OTOOL_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OTOOL_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(OTOOL_, __VA_ARGS__),
 #include "OtoolOpts.inc"
 #undef OPTION
 };
@@ -165,12 +159,7 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info OtoolInfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {PREFIX,        NAME,       HELPTEXT,                                        \
-   METAVAR,       OTOOL_##ID, opt::Option::KIND##Class,                        \
-   PARAM,         FLAGS,      OTOOL_##GROUP,                                   \
-   OTOOL_##ALIAS, ALIASARGS,  VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(OTOOL_, __VA_ARGS__),
 #include "OtoolOpts.inc"
 #undef OPTION
 };
@@ -187,6 +176,13 @@
 
 #define DEBUG_TYPE "objdump"
 
+enum class ColorOutput {
+  Auto,
+  Enable,
+  Disable,
+  Invalid,
+};
+
 static uint64_t AdjustVMA;
 static bool AllHeaders;
 static std::string ArchName;
@@ -199,6 +195,7 @@
 static std::vector<std::string> DisassembleSymbols;
 static bool DisassembleZeroes;
 static std::vector<std::string> DisassemblerOptions;
+static ColorOutput DisassemblyColor;
 DIDumpType objdump::DwarfDumpType;
 static bool DynamicRelocations;
 static bool FaultMapSection;
@@ -245,15 +242,21 @@
 static StringRef ToolName;
 
 std::unique_ptr<BuildIDFetcher> BIDFetcher;
-ExitOnError ExitOnErr;
+
+Dumper::Dumper(const object::ObjectFile &O) : O(O) {
+  WarningHandler = [this](const Twine &Msg) {
+    if (Warnings.insert(Msg.str()).second)
+      reportWarning(Msg, this->O.getFileName());
+    return Error::success();
+  };
+}
 
 void Dumper::reportUniqueWarning(Error Err) {
   reportUniqueWarning(toString(std::move(Err)));
 }
 
 void Dumper::reportUniqueWarning(const Twine &Msg) {
-  if (Warnings.insert(StringRef(Msg.str())).second)
-    reportWarning(Msg, O.getFileName());
+  cantFail(WarningHandler(Msg));
 }
 
 static Expected<std::unique_ptr<Dumper>> createDumper(const ObjectFile &Obj) {
@@ -420,6 +423,7 @@
 }
 
 static Error getRelocationValueString(const RelocationRef &Rel,
+                                      bool SymbolDescription,
                                       SmallVectorImpl<char> &Result) {
   const ObjectFile *Obj = Rel.getObject();
   if (auto *ELF = dyn_cast<ELFObjectFileBase>(Obj))
@@ -431,7 +435,8 @@
   if (auto *MachO = dyn_cast<MachOObjectFile>(Obj))
     return getMachORelocationValueString(MachO, Rel, Result);
   if (auto *XCOFF = dyn_cast<XCOFFObjectFile>(Obj))
-    return getXCOFFRelocationValueString(*XCOFF, Rel, Result);
+    return getXCOFFRelocationValueString(*XCOFF, Rel, SymbolDescription,
+                                         Result);
   llvm_unreachable("unknown object file format");
 }
 
@@ -516,11 +521,6 @@
   return isArmElf(Obj) || isAArch64Elf(Obj) || isCSKYElf(Obj) ;
 }
 
-static bool isMappingSymbol(const SymbolInfoTy &Sym) {
-  return Sym.Name.startswith("$d") || Sym.Name.startswith("$x") ||
-         Sym.Name.startswith("$a") || Sym.Name.startswith("$t");
-}
-
 static void printRelocation(formatted_raw_ostream &OS, StringRef FileName,
                             const RelocationRef &Rel, uint64_t Address,
                             bool Is64Bits) {
@@ -528,7 +528,7 @@
   SmallString<16> Name;
   SmallString<32> Val;
   Rel.getTypeName(Name);
-  if (Error E = getRelocationValueString(Rel, Val))
+  if (Error E = getRelocationValueString(Rel, SymbolDescription, Val))
     reportError(std::move(E), FileName);
   OS << (Is64Bits || !LeadingAddr ? "\t\t" : "\t\t\t");
   if (LeadingAddr)
@@ -536,6 +536,22 @@
   OS << Name << "\t" << Val;
 }
 
+static void printBTFRelocation(formatted_raw_ostream &FOS, llvm::BTFParser &BTF,
+                               object::SectionedAddress Address,
+                               LiveVariablePrinter &LVP) {
+  const llvm::BTF::BPFFieldReloc *Reloc = BTF.findFieldReloc(Address);
+  if (!Reloc)
+    return;
+
+  SmallString<64> Val;
+  BTF.symbolize(Reloc, Val);
+  FOS << "\t\t";
+  if (LeadingAddr)
+    FOS << format("%016" PRIx64 ":  ", Address.Address + AdjustVMA);
+  FOS << "CO-RE " << Val;
+  LVP.printAfterOtherLine(FOS, true);
+}
+
 class PrettyPrinter {
 public:
   virtual ~PrettyPrinter() = default;
@@ -669,8 +685,9 @@
       // using the .long directive, or .byte directive if fewer than 4 bytes
       // remaining
       if (Bytes.size() >= 4) {
-        OS << format("\t.long 0x%08" PRIx32 " ",
-                     support::endian::read32<support::little>(Bytes.data()));
+        OS << format(
+            "\t.long 0x%08" PRIx32 " ",
+            support::endian::read32<llvm::endianness::little>(Bytes.data()));
         OS.indent(42);
       } else {
           OS << format("\t.byte 0x%02" PRIx8, Bytes[0]);
@@ -767,12 +784,12 @@
       OS << "\t<unknown>";
   }
 
-  void setInstructionEndianness(llvm::support::endianness Endianness) {
+  void setInstructionEndianness(llvm::endianness Endianness) {
     InstructionEndianness = Endianness;
   }
 
 private:
-  llvm::support::endianness InstructionEndianness = llvm::support::little;
+  llvm::endianness InstructionEndianness = llvm::endianness::little;
 };
 ARMPrettyPrinter ARMPrettyPrinterInst;
 
@@ -795,8 +812,8 @@
       for (; Pos + 4 <= End; Pos += 4)
         OS << ' '
            << format_hex_no_prefix(
-                  llvm::support::endian::read<uint32_t>(Bytes.data() + Pos,
-                                                        llvm::support::little),
+                  llvm::support::endian::read<uint32_t>(
+                      Bytes.data() + Pos, llvm::endianness::little),
                   8);
       if (Pos < End) {
         OS << ' ';
@@ -836,6 +853,105 @@
     return AArch64PrettyPrinterInst;
   }
 }
+
+class DisassemblerTarget {
+public:
+  const Target *TheTarget;
+  std::unique_ptr<const MCSubtargetInfo> SubtargetInfo;
+  std::shared_ptr<MCContext> Context;
+  std::unique_ptr<MCDisassembler> DisAsm;
+  std::shared_ptr<MCInstrAnalysis> InstrAnalysis;
+  std::shared_ptr<MCInstPrinter> InstPrinter;
+  PrettyPrinter *Printer;
+
+  DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,
+                     StringRef TripleName, StringRef MCPU,
+                     SubtargetFeatures &Features);
+  DisassemblerTarget(DisassemblerTarget &Other, SubtargetFeatures &Features);
+
+private:
+  MCTargetOptions Options;
+  std::shared_ptr<const MCRegisterInfo> RegisterInfo;
+  std::shared_ptr<const MCAsmInfo> AsmInfo;
+  std::shared_ptr<const MCInstrInfo> InstrInfo;
+  std::shared_ptr<MCObjectFileInfo> ObjectFileInfo;
+};
+
+DisassemblerTarget::DisassemblerTarget(const Target *TheTarget, ObjectFile &Obj,
+                                       StringRef TripleName, StringRef MCPU,
+                                       SubtargetFeatures &Features)
+    : TheTarget(TheTarget),
+      Printer(&selectPrettyPrinter(Triple(TripleName))),
+      RegisterInfo(TheTarget->createMCRegInfo(TripleName)) {
+  if (!RegisterInfo)
+    reportError(Obj.getFileName(), "no register info for target " + TripleName);
+
+  // Set up disassembler.
+  AsmInfo.reset(TheTarget->createMCAsmInfo(*RegisterInfo, TripleName, Options));
+  if (!AsmInfo)
+    reportError(Obj.getFileName(), "no assembly info for target " + TripleName);
+
+  SubtargetInfo.reset(
+      TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString()));
+  if (!SubtargetInfo)
+    reportError(Obj.getFileName(),
+                "no subtarget info for target " + TripleName);
+  InstrInfo.reset(TheTarget->createMCInstrInfo());
+  if (!InstrInfo)
+    reportError(Obj.getFileName(),
+                "no instruction info for target " + TripleName);
+  Context =
+      std::make_shared<MCContext>(Triple(TripleName), AsmInfo.get(),
+                                  RegisterInfo.get(), SubtargetInfo.get());
+
+  // FIXME: for now initialize MCObjectFileInfo with default values
+  ObjectFileInfo.reset(
+      TheTarget->createMCObjectFileInfo(*Context, /*PIC=*/false));
+  Context->setObjectFileInfo(ObjectFileInfo.get());
+
+  DisAsm.reset(TheTarget->createMCDisassembler(*SubtargetInfo, *Context));
+  if (!DisAsm)
+    reportError(Obj.getFileName(), "no disassembler for target " + TripleName);
+
+  InstrAnalysis.reset(TheTarget->createMCInstrAnalysis(InstrInfo.get()));
+
+  int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
+  InstPrinter.reset(TheTarget->createMCInstPrinter(Triple(TripleName),
+                                                   AsmPrinterVariant, *AsmInfo,
+                                                   *InstrInfo, *RegisterInfo));
+  if (!InstPrinter)
+    reportError(Obj.getFileName(),
+                "no instruction printer for target " + TripleName);
+  InstPrinter->setPrintImmHex(PrintImmHex);
+  InstPrinter->setPrintBranchImmAsAddress(true);
+  InstPrinter->setSymbolizeOperands(SymbolizeOperands);
+  InstPrinter->setMCInstrAnalysis(InstrAnalysis.get());
+
+  switch (DisassemblyColor) {
+  case ColorOutput::Enable:
+    InstPrinter->setUseColor(true);
+    break;
+  case ColorOutput::Auto:
+    InstPrinter->setUseColor(outs().has_colors());
+    break;
+  case ColorOutput::Disable:
+  case ColorOutput::Invalid:
+    InstPrinter->setUseColor(false);
+    break;
+  };
+}
+
+DisassemblerTarget::DisassemblerTarget(DisassemblerTarget &Other,
+                                       SubtargetFeatures &Features)
+    : TheTarget(Other.TheTarget),
+      SubtargetInfo(TheTarget->createMCSubtargetInfo(TripleName, MCPU,
+                                                     Features.getString())),
+      Context(Other.Context),
+      DisAsm(TheTarget->createMCDisassembler(*SubtargetInfo, *Context)),
+      InstrAnalysis(Other.InstrAnalysis), InstPrinter(Other.InstPrinter),
+      Printer(Other.Printer), RegisterInfo(Other.RegisterInfo),
+      AsmInfo(Other.AsmInfo), InstrInfo(Other.InstrInfo),
+      ObjectFileInfo(Other.ObjectFileInfo) {}
 } // namespace
 
 static uint8_t getElfSymbolType(const ObjectFile &Obj, const SymbolRef &Sym) {
@@ -1052,8 +1168,8 @@
                                ArrayRef<uint8_t> Bytes,
                                ArrayRef<MappingSymbolPair> MappingSymbols,
                                const MCSubtargetInfo &STI, raw_ostream &OS) {
-  support::endianness Endian =
-      Obj.isLittleEndian() ? support::little : support::big;
+  llvm::endianness Endian =
+      Obj.isLittleEndian() ? llvm::endianness::little : llvm::endianness::big;
   size_t Start = OS.tell();
   OS << format("%8" PRIx64 ": ", SectionAddr + Index);
   if (Index + 4 <= End) {
@@ -1112,7 +1228,8 @@
 }
 
 SymbolInfoTy objdump::createSymbolInfo(const ObjectFile &Obj,
-                                       const SymbolRef &Symbol) {
+                                       const SymbolRef &Symbol,
+                                       bool IsMappingSymbol) {
   const StringRef FileName = Obj.getFileName();
   const uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);
   const StringRef Name = unwrapOrError(Symbol.getName(), FileName);
@@ -1124,30 +1241,79 @@
     const uint32_t SymbolIndex = XCOFFObj.getSymbolIndex(SymbolDRI.p);
     std::optional<XCOFF::StorageMappingClass> Smc =
         getXCOFFSymbolCsectSMC(XCOFFObj, Symbol);
-    return SymbolInfoTy(Addr, Name, Smc, SymbolIndex,
+    return SymbolInfoTy(Smc, Addr, Name, SymbolIndex,
                         isLabel(XCOFFObj, Symbol));
   } else if (Obj.isXCOFF()) {
     const SymbolRef::Type SymType = unwrapOrError(Symbol.getType(), FileName);
-    return SymbolInfoTy(Addr, Name, SymType, true);
-  } else
-    return SymbolInfoTy(Addr, Name,
-                        Obj.isELF() ? getElfSymbolType(Obj, Symbol)
-                                    : (uint8_t)ELF::STT_NOTYPE);
+    return SymbolInfoTy(Addr, Name, SymType, /*IsMappingSymbol=*/false,
+                        /*IsXCOFF=*/true);
+  } else {
+    uint8_t Type =
+        Obj.isELF() ? getElfSymbolType(Obj, Symbol) : (uint8_t)ELF::STT_NOTYPE;
+    return SymbolInfoTy(Addr, Name, Type, IsMappingSymbol);
+  }
 }
 
 static SymbolInfoTy createDummySymbolInfo(const ObjectFile &Obj,
                                           const uint64_t Addr, StringRef &Name,
                                           uint8_t Type) {
   if (Obj.isXCOFF() && (SymbolDescription || TracebackTable))
-    return SymbolInfoTy(Addr, Name, std::nullopt, std::nullopt, false);
+    return SymbolInfoTy(std::nullopt, Addr, Name, std::nullopt, false);
   else
     return SymbolInfoTy(Addr, Name, Type);
 }
 
-static void
-collectBBAddrMapLabels(const std::unordered_map<uint64_t, BBAddrMap> &AddrToBBAddrMap,
-                       uint64_t SectionAddr, uint64_t Start, uint64_t End,
-                       std::unordered_map<uint64_t, std::vector<std::string>> &Labels) {
+struct BBAddrMapLabel {
+  std::string BlockLabel;
+  std::string PGOAnalysis;
+};
+
+static std::string constructPGOLabelString(const PGOAnalysisMap &PGOMap,
+                                           size_t BBEntryIndex) {
+  std::string PGOString;
+  raw_string_ostream PGOSS(PGOString);
+
+  PGOSS << " (";
+  if (PGOMap.FeatEnable.FuncEntryCount && BBEntryIndex == 0) {
+    PGOSS << "Entry count: " << Twine(PGOMap.FuncEntryCount);
+    if (PGOMap.FeatEnable.BBFreq || PGOMap.FeatEnable.BrProb) {
+      PGOSS << ", ";
+    }
+  }
+
+  if (PGOMap.FeatEnable.BBFreq || PGOMap.FeatEnable.BrProb) {
+    assert(BBEntryIndex < PGOMap.BBEntries.size() &&
+           "Expected PGOAnalysisMap and BBAddrMap to have the same entires");
+    const PGOAnalysisMap::PGOBBEntry &PGOBBEntry =
+        PGOMap.BBEntries[BBEntryIndex];
+
+    if (PGOMap.FeatEnable.BBFreq) {
+      PGOSS << "Frequency: " << Twine(PGOBBEntry.BlockFreq.getFrequency());
+      if (PGOMap.FeatEnable.BrProb && PGOBBEntry.Successors.size() > 0) {
+        PGOSS << ", ";
+      }
+    }
+    if (PGOMap.FeatEnable.BrProb && PGOBBEntry.Successors.size() > 0) {
+      PGOSS << "Successors: ";
+      interleaveComma(
+          PGOBBEntry.Successors, PGOSS,
+          [&PGOSS](const PGOAnalysisMap::PGOBBEntry::SuccessorEntry &SE) {
+            PGOSS << "BB" << SE.ID << ":";
+            PGOSS.write_hex(SE.Prob.getNumerator());
+          });
+    }
+  }
+  PGOSS << ")";
+
+  return PGOString;
+}
+
+static void collectBBAddrMapLabels(
+    const std::unordered_map<uint64_t, BBAddrMap> &AddrToBBAddrMap,
+    const std::unordered_map<uint64_t, PGOAnalysisMap> &AddrToPGOAnalysisMap,
+    uint64_t SectionAddr, uint64_t Start, uint64_t End,
+    std::unordered_map<uint64_t, std::vector<BBAddrMapLabel>> &Labels,
+    const StringRef FileName) {
   if (AddrToBBAddrMap.empty())
     return;
   Labels.clear();
@@ -1156,28 +1322,44 @@
   auto Iter = AddrToBBAddrMap.find(StartAddress);
   if (Iter == AddrToBBAddrMap.end())
     return;
-  for (const BBAddrMap::BBEntry &BBEntry : Iter->second.BBEntries) {
-    uint64_t BBAddress = BBEntry.Offset + Iter->second.Addr;
+  auto PGOIter = AddrToPGOAnalysisMap.find(StartAddress);
+
+  for (size_t I = 0; I < Iter->second.getBBEntries().size(); ++I) {
+    const BBAddrMap::BBEntry &BBEntry = Iter->second.getBBEntries()[I];
+    uint64_t BBAddress = BBEntry.Offset + Iter->second.getFunctionAddress();
     if (BBAddress >= EndAddress)
       continue;
-    Labels[BBAddress].push_back(("BB" + Twine(BBEntry.ID)).str());
+
+    std::string LabelString = ("BB" + Twine(BBEntry.ID)).str();
+    std::string PGOString;
+
+    if (PGOIter != AddrToPGOAnalysisMap.end())
+      PGOString = constructPGOLabelString(PGOIter->second, I);
+
+    Labels[BBAddress].push_back({LabelString, PGOString});
   }
 }
 
-static void collectLocalBranchTargets(
-    ArrayRef<uint8_t> Bytes, const MCInstrAnalysis *MIA, MCDisassembler *DisAsm,
-    MCInstPrinter *IP, const MCSubtargetInfo *STI, uint64_t SectionAddr,
-    uint64_t Start, uint64_t End, std::unordered_map<uint64_t, std::string> &Labels) {
+static void
+collectLocalBranchTargets(ArrayRef<uint8_t> Bytes, MCInstrAnalysis *MIA,
+                          MCDisassembler *DisAsm, MCInstPrinter *IP,
+                          const MCSubtargetInfo *STI, uint64_t SectionAddr,
+                          uint64_t Start, uint64_t End,
+                          std::unordered_map<uint64_t, std::string> &Labels) {
   // So far only supports PowerPC and X86.
-  if (!STI->getTargetTriple().isPPC() && !STI->getTargetTriple().isX86())
+  const bool isPPC = STI->getTargetTriple().isPPC();
+  if (!isPPC && !STI->getTargetTriple().isX86())
     return;
 
+  if (MIA)
+    MIA->resetState();
+
   Labels.clear();
   unsigned LabelCount = 0;
   Start += SectionAddr;
   End += SectionAddr;
-  uint64_t Index = Start;
-  while (Index < End) {
+  const bool isXCOFF = STI->getTargetTriple().isOSBinFormatXCOFF();
+  for (uint64_t Index = Start; Index < End;) {
     // Disassemble a real instruction and record function-local branch labels.
     MCInst Inst;
     uint64_t Size;
@@ -1188,15 +1370,22 @@
       Size = std::min<uint64_t>(ThisBytes.size(),
                                 DisAsm->suggestBytesToSkip(ThisBytes, Index));
 
-    if (Disassembled && MIA) {
-      uint64_t Target;
-      bool TargetKnown = MIA->evaluateBranch(Inst, Index, Size, Target);
-      // On PowerPC, if the address of a branch is the same as the target, it
-      // means that it's a function call. Do not mark the label for this case.
-      if (TargetKnown && (Target >= Start && Target < End) &&
-          !Labels.count(Target) &&
-          !(STI->getTargetTriple().isPPC() && Target == Index))
-        Labels[Target] = ("L" + Twine(LabelCount++)).str();
+    if (MIA) {
+      if (Disassembled) {
+        uint64_t Target;
+        bool TargetKnown = MIA->evaluateBranch(Inst, Index, Size, Target);
+        if (TargetKnown && (Target >= Start && Target < End) &&
+            !Labels.count(Target)) {
+          // On PowerPC and AIX, a function call is encoded as a branch to 0.
+          // On other PowerPC platforms (ELF), a function call is encoded as
+          // a branch to self. Do not add a label for these cases.
+          if (!(isPPC &&
+                ((Target == 0 && isXCOFF) || (Target == Index && !isXCOFF))))
+            Labels[Target] = ("L" + Twine(LabelCount++)).str();
+        }
+        MIA->updateState(Inst, Index);
+      } else
+        MIA->resetState();
     }
     Index += Size;
   }
@@ -1326,29 +1515,48 @@
   return std::move(*DebugBinary);
 }
 
-static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
-                              const ObjectFile &DbgObj, MCContext &Ctx,
-                              MCDisassembler *PrimaryDisAsm,
-                              MCDisassembler *SecondaryDisAsm,
-                              const MCInstrAnalysis *MIA, MCInstPrinter *IP,
-                              const MCSubtargetInfo *PrimarySTI,
-                              const MCSubtargetInfo *SecondarySTI,
-                              PrettyPrinter &PIP, SourcePrinter &SP,
-                              bool InlineRelocs) {
-  const MCSubtargetInfo *STI = PrimarySTI;
-  MCDisassembler *DisAsm = PrimaryDisAsm;
+static void
+disassembleObject(ObjectFile &Obj, const ObjectFile &DbgObj,
+                  DisassemblerTarget &PrimaryTarget,
+                  std::optional<DisassemblerTarget> &SecondaryTarget,
+                  SourcePrinter &SP, bool InlineRelocs) {
+  DisassemblerTarget *DT = &PrimaryTarget;
   bool PrimaryIsThumb = false;
-  if (isArmElf(Obj))
-    PrimaryIsThumb = STI->checkFeatures("+thumb-mode");
+  SmallVector<std::pair<uint64_t, uint64_t>, 0> CHPECodeMap;
+
+  if (SecondaryTarget) {
+    if (isArmElf(Obj)) {
+      PrimaryIsThumb =
+          PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode");
+    } else if (const auto *COFFObj = dyn_cast<COFFObjectFile>(&Obj)) {
+      const chpe_metadata *CHPEMetadata = COFFObj->getCHPEMetadata();
+      if (CHPEMetadata && CHPEMetadata->CodeMapCount) {
+        uintptr_t CodeMapInt;
+        cantFail(COFFObj->getRvaPtr(CHPEMetadata->CodeMap, CodeMapInt));
+        auto CodeMap = reinterpret_cast<const chpe_range_entry *>(CodeMapInt);
+
+        for (uint32_t i = 0; i < CHPEMetadata->CodeMapCount; ++i) {
+          if (CodeMap[i].getType() == chpe_range_type::Amd64 &&
+              CodeMap[i].Length) {
+            // Store x86_64 CHPE code ranges.
+            uint64_t Start = CodeMap[i].getStart() + COFFObj->getImageBase();
+            CHPECodeMap.emplace_back(Start, Start + CodeMap[i].Length);
+          }
+        }
+        llvm::sort(CHPECodeMap);
+      }
+    }
+  }
 
   std::map<SectionRef, std::vector<RelocationRef>> RelocMap;
-  if (InlineRelocs)
+  if (InlineRelocs || Obj.isXCOFF())
     RelocMap = getRelocsMap(Obj);
   bool Is64Bits = Obj.getBytesInAddress() > 4;
 
   // Create a mapping from virtual address to symbol name.  This is used to
   // pretty print the symbols while disassembling.
   std::map<SectionRef, SectionSymbolsTy> AllSymbols;
+  std::map<SectionRef, SmallVector<MappingSymbolPair, 0>> AllMappingSymbols;
   SectionSymbolsTy AbsoluteSymbols;
   const StringRef FileName = Obj.getFileName();
   const MachOObjectFile *MachO = dyn_cast<const MachOObjectFile>(&Obj);
@@ -1361,14 +1569,39 @@
     if (NameOrErr->empty() && !(Obj.isXCOFF() && SymbolDescription))
       continue;
 
-    if (Obj.isELF() && getElfSymbolType(Obj, Symbol) == ELF::STT_SECTION)
+    if (Obj.isELF() &&
+        (cantFail(Symbol.getFlags()) & SymbolRef::SF_FormatSpecific)) {
+      // Symbol is intended not to be displayed by default (STT_FILE,
+      // STT_SECTION, or a mapping symbol). Ignore STT_SECTION symbols. We will
+      // synthesize a section symbol if no symbol is defined at offset 0.
+      //
+      // For a mapping symbol, store it within both AllSymbols and
+      // AllMappingSymbols. If --show-all-symbols is unspecified, its label will
+      // not be printed in disassembly listing.
+      if (getElfSymbolType(Obj, Symbol) != ELF::STT_SECTION &&
+          hasMappingSymbols(Obj)) {
+        section_iterator SecI = unwrapOrError(Symbol.getSection(), FileName);
+        if (SecI != Obj.section_end()) {
+          uint64_t SectionAddr = SecI->getAddress();
+          uint64_t Address = cantFail(Symbol.getAddress());
+          StringRef Name = *NameOrErr;
+          if (Name.consume_front("$") && Name.size() &&
+              strchr("adtx", Name[0])) {
+            AllMappingSymbols[*SecI].emplace_back(Address - SectionAddr,
+                                                  Name[0]);
+            AllSymbols[*SecI].push_back(
+                createSymbolInfo(Obj, Symbol, /*MappingSymbol=*/true));
+          }
+        }
+      }
       continue;
+    }
 
     if (MachO) {
       // __mh_(execute|dylib|dylinker|bundle|preload|object)_header are special
       // symbols that support MachO header introspection. They do not bind to
       // code locations and are irrelevant for disassembly.
-      if (NameOrErr->startswith("__mh_") && NameOrErr->endswith("_header"))
+      if (NameOrErr->starts_with("__mh_") && NameOrErr->ends_with("_header"))
         continue;
       // Don't ask a Mach-O STAB symbol for its section unless you know that
       // STAB symbol's section field refers to a valid section index. Otherwise
@@ -1450,7 +1683,7 @@
   llvm::stable_sort(AbsoluteSymbols);
 
   std::unique_ptr<DWARFContext> DICtx;
-  LiveVariablePrinter LVP(*Ctx.getRegisterInfo(), *STI);
+  LiveVariablePrinter LVP(*DT->Context->getRegisterInfo(), *DT->SubtargetInfo);
 
   if (DbgVariables != DVDisabled) {
     DICtx = DWARFContext::create(DbgObj);
@@ -1461,18 +1694,24 @@
   LLVM_DEBUG(LVP.dump());
 
   std::unordered_map<uint64_t, BBAddrMap> AddrToBBAddrMap;
+  std::unordered_map<uint64_t, PGOAnalysisMap> AddrToPGOAnalysisMap;
   auto ReadBBAddrMap = [&](std::optional<unsigned> SectionIndex =
                                std::nullopt) {
     AddrToBBAddrMap.clear();
     if (const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj)) {
-      auto BBAddrMapsOrErr = Elf->readBBAddrMap(SectionIndex);
+      std::vector<PGOAnalysisMap> PGOAnalyses;
+      auto BBAddrMapsOrErr = Elf->readBBAddrMap(SectionIndex, &PGOAnalyses);
       if (!BBAddrMapsOrErr) {
         reportWarning(toString(BBAddrMapsOrErr.takeError()), Obj.getFileName());
         return;
       }
-      for (auto &FunctionBBAddrMap : *BBAddrMapsOrErr)
-        AddrToBBAddrMap.emplace(FunctionBBAddrMap.Addr,
-                                std::move(FunctionBBAddrMap));
+      for (const auto &[FunctionBBAddrMap, FunctionPGOAnalysis] :
+           zip_equal(*std::move(BBAddrMapsOrErr), std::move(PGOAnalyses))) {
+        uint64_t Addr = FunctionBBAddrMap.Addr;
+        AddrToBBAddrMap.emplace(Addr, std::move(FunctionBBAddrMap));
+        if (FunctionPGOAnalysis.FeatEnable.anyEnabled())
+          AddrToPGOAnalysisMap.emplace(Addr, std::move(FunctionPGOAnalysis));
+      }
     }
   };
 
@@ -1481,6 +1720,16 @@
   if (SymbolizeOperands && !Obj.isRelocatableObject())
     ReadBBAddrMap();
 
+  std::optional<llvm::BTFParser> BTF;
+  if (InlineRelocs && BTFParser::hasBTFSections(Obj)) {
+    BTF.emplace();
+    BTFParser::ParseOptions Opts = {};
+    Opts.LoadTypes = true;
+    Opts.LoadRelocs = true;
+    if (Error E = BTF->parse(Obj, Opts))
+      WithColor::defaultErrorHandler(std::move(E));
+  }
+
   for (const SectionRef &Section : ToolSectionFilter(Obj)) {
     if (FilterSections.empty() && !DisassembleAll &&
         (!Section.isText() || Section.isVirtual()))
@@ -1498,22 +1747,7 @@
 
     // Get the list of all the symbols in this section.
     SectionSymbolsTy &Symbols = AllSymbols[Section];
-    std::vector<MappingSymbolPair> MappingSymbols;
-    if (hasMappingSymbols(Obj)) {
-      for (const auto &Symb : Symbols) {
-        uint64_t Address = Symb.Addr;
-        StringRef Name = Symb.Name;
-        if (Name.startswith("$d"))
-          MappingSymbols.emplace_back(Address - SectionAddr, 'd');
-        if (Name.startswith("$x"))
-          MappingSymbols.emplace_back(Address - SectionAddr, 'x');
-        if (Name.startswith("$a"))
-          MappingSymbols.emplace_back(Address - SectionAddr, 'a');
-        if (Name.startswith("$t"))
-          MappingSymbols.emplace_back(Address - SectionAddr, 't');
-      }
-    }
-
+    auto &MappingSymbols = AllMappingSymbols[Section];
     llvm::sort(MappingSymbols);
 
     ArrayRef<uint8_t> Bytes = arrayRefFromStringRef(
@@ -1522,18 +1756,33 @@
     std::vector<std::unique_ptr<std::string>> SynthesizedLabelNames;
     if (Obj.isELF() && Obj.getArch() == Triple::amdgcn) {
       // AMDGPU disassembler uses symbolizer for printing labels
-      addSymbolizer(Ctx, TheTarget, TripleName, DisAsm, SectionAddr, Bytes,
-                    Symbols, SynthesizedLabelNames);
+      addSymbolizer(*DT->Context, DT->TheTarget, TripleName, DT->DisAsm.get(),
+                    SectionAddr, Bytes, Symbols, SynthesizedLabelNames);
     }
 
     StringRef SegmentName = getSegmentName(MachO, Section);
     StringRef SectionName = unwrapOrError(Section.getName(), Obj.getFileName());
     // If the section has no symbol at the start, just insert a dummy one.
-    if (Symbols.empty() || Symbols[0].Addr != 0) {
-      Symbols.insert(Symbols.begin(),
-                     createDummySymbolInfo(Obj, SectionAddr, SectionName,
-                                           Section.isText() ? ELF::STT_FUNC
-                                                            : ELF::STT_OBJECT));
+    // Without --show-all-symbols, also insert one if all symbols at the start
+    // are mapping symbols.
+    bool CreateDummy = Symbols.empty();
+    if (!CreateDummy) {
+      CreateDummy = true;
+      for (auto &Sym : Symbols) {
+        if (Sym.Addr != SectionAddr)
+          break;
+        if (!Sym.IsMappingSymbol || ShowAllSymbols)
+          CreateDummy = false;
+      }
+    }
+    if (CreateDummy) {
+      SymbolInfoTy Sym = createDummySymbolInfo(
+          Obj, SectionAddr, SectionName,
+          Section.isText() ? ELF::STT_FUNC : ELF::STT_OBJECT);
+      if (Obj.isXCOFF())
+        Symbols.insert(Symbols.begin(), Sym);
+      else
+        Symbols.insert(llvm::lower_bound(Symbols, Sym), Sym);
     }
 
     SmallString<40> Comments;
@@ -1599,19 +1848,19 @@
       // inside functions, for which STT_FUNC would be inaccurate.
       //
       // So here, we spot whether there's any non-data symbol present at all,
-      // and only set the DisassembleAsData flag if there isn't. Also, we use
+      // and only set the DisassembleAsELFData flag if there isn't. Also, we use
       // this distinction to inform the decision of which symbol to print at
       // the head of the section, so that if we're printing code, we print a
       // code-related symbol name to go with it.
-      bool DisassembleAsData = false;
+      bool DisassembleAsELFData = false;
       size_t DisplaySymIndex = SymbolsHere.size() - 1;
       if (Obj.isELF() && !DisassembleAll && Section.isText()) {
-        DisassembleAsData = true; // unless we find a code symbol below
+        DisassembleAsELFData = true; // unless we find a code symbol below
 
         for (size_t i = 0; i < SymbolsHere.size(); ++i) {
           uint8_t SymTy = SymbolsHere[i].Type;
           if (SymTy != ELF::STT_OBJECT && SymTy != ELF::STT_COMMON) {
-            DisassembleAsData = false;
+            DisassembleAsELFData = false;
             DisplaySymIndex = i;
           }
         }
@@ -1634,7 +1883,7 @@
         // disassembling this entire chunk of code.
         if (!FoundAny)
           continue;
-      } else {
+      } else if (!SymbolsHere[DisplaySymIndex].IsMappingSymbol) {
         // Otherwise, print whichever symbol at this location is last in the
         // Symbols array, because that array is pre-sorted in a way intended to
         // correlate with priority of which symbol to display.
@@ -1678,8 +1927,7 @@
         outs() << SectionName << ":\n";
       }
 
-      outs() << '\n';
-
+      bool PrintedLabel = false;
       for (size_t i = 0; i < SymbolsHere.size(); ++i) {
         if (!SymsToPrint[i])
           continue;
@@ -1687,6 +1935,10 @@
         const SymbolInfoTy &Symbol = SymbolsHere[i];
         const StringRef SymbolName = SymNamesHere[i];
 
+        if (!PrintedLabel) {
+          outs() << '\n';
+          PrintedLabel = true;
+        }
         if (LeadingAddr)
           outs() << format(Is64Bits ? "%016" PRIx64 " " : "%08" PRIx64 " ",
                            SectionAddr + Start + VMAAdjustment);
@@ -1716,9 +1968,9 @@
       for (size_t SHI = 0; SHI < SymbolsHere.size(); ++SHI) {
         SymbolInfoTy Symbol = SymbolsHere[SHI];
 
-        auto Status =
-            DisAsm->onSymbolStart(Symbol, Size, Bytes.slice(Start, End - Start),
-                                  SectionAddr + Start, CommentStream);
+        auto Status = DT->DisAsm->onSymbolStart(
+            Symbol, Size, Bytes.slice(Start, End - Start), SectionAddr + Start,
+            CommentStream);
 
         if (!Status) {
           // If onSymbolStart returns std::nullopt, that means it didn't trigger
@@ -1743,7 +1995,7 @@
           // distance to the next symbol, and sometimes it will be just a
           // prologue and we should start disassembling instructions from where
           // it left off.
-          outs() << Ctx.getAsmInfo()->getCommentString()
+          outs() << DT->Context->getAsmInfo()->getCommentString()
                  << " error in decoding " << SymNamesHere[SHI]
                  << " : decoding failed region as bytes.\n";
           for (uint64_t I = 0; I < Size; ++I) {
@@ -1759,12 +2011,19 @@
       if (SectionAddr < StartAddress)
         Index = std::max<uint64_t>(Index, StartAddress - SectionAddr);
 
-      if (DisassembleAsData) {
+      if (DisassembleAsELFData) {
         dumpELFData(SectionAddr, Index, End, Bytes);
         Index = End;
         continue;
       }
 
+      // Skip relocations from symbols that are not dumped.
+      for (; RelCur != RelEnd; ++RelCur) {
+        uint64_t Offset = RelCur->getOffset() - RelAdjustment;
+        if (Index <= Offset)
+          break;
+      }
+
       bool DumpARMELFData = false;
       bool DumpTracebackTableForXCOFFFunction =
           Obj.isXCOFF() && Section.isText() && TracebackTable &&
@@ -1773,16 +2032,31 @@
 
       formatted_raw_ostream FOS(outs());
 
+      // FIXME: Workaround for bug in formatted_raw_ostream. Color escape codes
+      // are (incorrectly) written directly to the unbuffered raw_ostream
+      // wrapped by the formatted_raw_ostream.
+      if (DisassemblyColor == ColorOutput::Enable ||
+          DisassemblyColor == ColorOutput::Auto)
+        FOS.SetUnbuffered();
+
       std::unordered_map<uint64_t, std::string> AllLabels;
-      std::unordered_map<uint64_t, std::vector<std::string>> BBAddrMapLabels;
+      std::unordered_map<uint64_t, std::vector<BBAddrMapLabel>> BBAddrMapLabels;
       if (SymbolizeOperands) {
-        collectLocalBranchTargets(Bytes, MIA, DisAsm, IP, PrimarySTI,
+        collectLocalBranchTargets(Bytes, DT->InstrAnalysis.get(),
+                                  DT->DisAsm.get(), DT->InstPrinter.get(),
+                                  PrimaryTarget.SubtargetInfo.get(),
                                   SectionAddr, Index, End, AllLabels);
-        collectBBAddrMapLabels(AddrToBBAddrMap, SectionAddr, Index, End,
-                               BBAddrMapLabels);
+        collectBBAddrMapLabels(AddrToBBAddrMap, AddrToPGOAnalysisMap,
+                               SectionAddr, Index, End, BBAddrMapLabels,
+                               FileName);
       }
 
+      if (DT->InstrAnalysis)
+        DT->InstrAnalysis->resetState();
+
       while (Index < End) {
+        uint64_t RelOffset;
+
         // ARM and AArch64 ELF binaries can interleave data and text in the
         // same section. We rely on the markers introduced to understand what
         // we need to dump. If the data marker is within a function, it is
@@ -1790,20 +2064,56 @@
         if (!MappingSymbols.empty()) {
           char Kind = getMappingSymbolKind(MappingSymbols, Index);
           DumpARMELFData = Kind == 'd';
-          if (SecondarySTI) {
+          if (SecondaryTarget) {
             if (Kind == 'a') {
-              STI = PrimaryIsThumb ? SecondarySTI : PrimarySTI;
-              DisAsm = PrimaryIsThumb ? SecondaryDisAsm : PrimaryDisAsm;
+              DT = PrimaryIsThumb ? &*SecondaryTarget : &PrimaryTarget;
             } else if (Kind == 't') {
-              STI = PrimaryIsThumb ? PrimarySTI : SecondarySTI;
-              DisAsm = PrimaryIsThumb ? PrimaryDisAsm : SecondaryDisAsm;
+              DT = PrimaryIsThumb ? &PrimaryTarget : &*SecondaryTarget;
             }
           }
+        } else if (!CHPECodeMap.empty()) {
+          uint64_t Address = SectionAddr + Index;
+          auto It = partition_point(
+              CHPECodeMap,
+              [Address](const std::pair<uint64_t, uint64_t> &Entry) {
+                return Entry.first <= Address;
+              });
+          if (It != CHPECodeMap.begin() && Address < (It - 1)->second) {
+            DT = &*SecondaryTarget;
+          } else {
+            DT = &PrimaryTarget;
+            // X64 disassembler range may have left Index unaligned, so
+            // make sure that it's aligned when we switch back to ARM64
+            // code.
+            Index = llvm::alignTo(Index, 4);
+            if (Index >= End)
+              break;
+          }
         }
 
+        auto findRel = [&]() {
+          while (RelCur != RelEnd) {
+            RelOffset = RelCur->getOffset() - RelAdjustment;
+            // If this relocation is hidden, skip it.
+            if (getHidden(*RelCur) || SectionAddr + RelOffset < StartAddress) {
+              ++RelCur;
+              continue;
+            }
+
+            // Stop when RelCur's offset is past the disassembled
+            // instruction/data.
+            if (RelOffset >= Index + Size)
+              return false;
+            if (RelOffset >= Index)
+              return true;
+            ++RelCur;
+          }
+          return false;
+        };
+
         if (DumpARMELFData) {
           Size = dumpARMELFData(SectionAddr, Index, End, Obj, Bytes,
-                                MappingSymbols, *STI, FOS);
+                                MappingSymbols, *DT->SubtargetInfo, FOS);
         } else {
           // When -z or --disassemble-zeroes are given we always dissasemble
           // them. Otherwise we might want to skip zero bytes we see.
@@ -1811,7 +2121,7 @@
             uint64_t MaxOffset = End - Index;
             // For --reloc: print zero blocks patched by relocations, so that
             // relocations can be shown in the dump.
-            if (RelCur != RelEnd)
+            if (InlineRelocs && RelCur != RelEnd)
               MaxOffset = std::min(RelCur->getOffset() - RelAdjustment - Index,
                                    MaxOffset);
 
@@ -1827,8 +2137,8 @@
               doesXCOFFTracebackTableBegin(Bytes.slice(Index, 4))) {
             dumpTracebackTable(Bytes.slice(Index),
                                SectionAddr + Index + VMAAdjustment, FOS,
-                               SectionAddr + End + VMAAdjustment, *STI,
-                               cast<XCOFFObjectFile>(&Obj));
+                               SectionAddr + End + VMAAdjustment,
+                               *DT->SubtargetInfo, cast<XCOFFObjectFile>(&Obj));
             Index = End;
             continue;
           }
@@ -1836,8 +2146,9 @@
           // Print local label if there's any.
           auto Iter1 = BBAddrMapLabels.find(SectionAddr + Index);
           if (Iter1 != BBAddrMapLabels.end()) {
-            for (StringRef Label : Iter1->second)
-              FOS << "<" << Label << ">:\n";
+            for (const auto &BBLabel : Iter1->second)
+              FOS << "<" << BBLabel.BlockLabel << ">" << BBLabel.PGOAnalysis
+                  << ":\n";
           } else {
             auto Iter2 = AllLabels.find(SectionAddr + Index);
             if (Iter2 != AllLabels.end())
@@ -1849,39 +2160,43 @@
           MCInst Inst;
           ArrayRef<uint8_t> ThisBytes = Bytes.slice(Index);
           uint64_t ThisAddr = SectionAddr + Index;
-          bool Disassembled = DisAsm->getInstruction(Inst, Size, ThisBytes,
-                                                     ThisAddr, CommentStream);
+          bool Disassembled = DT->DisAsm->getInstruction(
+              Inst, Size, ThisBytes, ThisAddr, CommentStream);
           if (Size == 0)
             Size = std::min<uint64_t>(
                 ThisBytes.size(),
-                DisAsm->suggestBytesToSkip(ThisBytes, ThisAddr));
+                DT->DisAsm->suggestBytesToSkip(ThisBytes, ThisAddr));
 
           LVP.update({Index, Section.getIndex()},
                      {Index + Size, Section.getIndex()}, Index + Size != End);
 
-          IP->setCommentStream(CommentStream);
+          DT->InstPrinter->setCommentStream(CommentStream);
 
-          PIP.printInst(
-              *IP, Disassembled ? &Inst : nullptr, Bytes.slice(Index, Size),
+          DT->Printer->printInst(
+              *DT->InstPrinter, Disassembled ? &Inst : nullptr,
+              Bytes.slice(Index, Size),
               {SectionAddr + Index + VMAAdjustment, Section.getIndex()}, FOS,
-              "", *STI, &SP, Obj.getFileName(), &Rels, LVP);
+              "", *DT->SubtargetInfo, &SP, Obj.getFileName(), &Rels, LVP);
 
-          IP->setCommentStream(llvm::nulls());
+          DT->InstPrinter->setCommentStream(llvm::nulls());
 
-          // If disassembly has failed, avoid analysing invalid/incomplete
-          // instruction information. Otherwise, try to resolve the target
-          // address (jump target or memory operand address) and print it on the
+          // If disassembly succeeds, we try to resolve the target address
+          // (jump target or memory operand address) and print it to the
           // right of the instruction.
-          if (Disassembled && MIA) {
-            // Branch targets are printed just after the instructions.
+          //
+          // Otherwise, we don't print anything else so that we avoid
+          // analyzing invalid or incomplete instruction information.
+          if (Disassembled && DT->InstrAnalysis) {
             llvm::raw_ostream *TargetOS = &FOS;
             uint64_t Target;
-            bool PrintTarget =
-                MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target);
-            if (!PrintTarget)
+            bool PrintTarget = DT->InstrAnalysis->evaluateBranch(
+                Inst, SectionAddr + Index, Size, Target);
+
+            if (!PrintTarget) {
               if (std::optional<uint64_t> MaybeTarget =
-                      MIA->evaluateMemoryOperandAddress(
-                          Inst, STI, SectionAddr + Index, Size)) {
+                      DT->InstrAnalysis->evaluateMemoryOperandAddress(
+                          Inst, DT->SubtargetInfo.get(), SectionAddr + Index,
+                          Size)) {
                 Target = *MaybeTarget;
                 PrintTarget = true;
                 // Do not print real address when symbolizing.
@@ -1891,6 +2206,8 @@
                   *TargetOS << "0x" << Twine::utohexstr(Target);
                 }
               }
+            }
+
             if (PrintTarget) {
               // In a relocatable object, the target's section must reside in
               // the same section as the call instruction or it is accessed
@@ -1900,7 +2217,8 @@
               // In that case, locate the section(s) containing the target
               // address and find the symbol in one of those, if possible.
               //
-              // N.B. We don't walk the relocations in the relocatable case yet.
+              // N.B. Except for XCOFF, we don't walk the relocations in the
+              // relocatable case yet.
               std::vector<const SectionSymbolsTy *> TargetSectionSymbols;
               if (!Obj.isRelocatableObject()) {
                 auto It = llvm::partition_point(
@@ -1937,7 +2255,7 @@
                   --It;
                   // Skip mapping symbols to avoid possible ambiguity as they
                   // do not allow uniquely identifying the target address.
-                  if (!hasMappingSymbols(Obj) || !isMappingSymbol(*It)) {
+                  if (!It->IsMappingSymbol) {
                     TargetSym = &*It;
                     break;
                   }
@@ -1946,22 +2264,68 @@
                   break;
               }
 
+              // Branch targets are printed just after the instructions.
               // Print the labels corresponding to the target if there's any.
               bool BBAddrMapLabelAvailable = BBAddrMapLabels.count(Target);
               bool LabelAvailable = AllLabels.count(Target);
+
               if (TargetSym != nullptr) {
                 uint64_t TargetAddress = TargetSym->Addr;
                 uint64_t Disp = Target - TargetAddress;
                 std::string TargetName = Demangle ? demangle(TargetSym->Name)
                                                   : TargetSym->Name.str();
+                bool RelFixedUp = false;
+                SmallString<32> Val;
 
                 *TargetOS << " <";
-                if (!Disp) {
-                  // Always Print the binary symbol precisely corresponding to
-                  // the target address.
+                // On XCOFF, we use relocations, even without -r, so we
+                // can print the correct name for an extern function call.
+                if (Obj.isXCOFF() && findRel()) {
+                  // Check for possible branch relocations and
+                  // branches to fixup code.
+                  bool BranchRelocationType = true;
+                  XCOFF::RelocationType RelocType;
+                  if (Obj.is64Bit()) {
+                    const XCOFFRelocation64 *Reloc =
+                        reinterpret_cast<XCOFFRelocation64 *>(
+                            RelCur->getRawDataRefImpl().p);
+                    RelFixedUp = Reloc->isFixupIndicated();
+                    RelocType = Reloc->Type;
+                  } else {
+                    const XCOFFRelocation32 *Reloc =
+                        reinterpret_cast<XCOFFRelocation32 *>(
+                            RelCur->getRawDataRefImpl().p);
+                    RelFixedUp = Reloc->isFixupIndicated();
+                    RelocType = Reloc->Type;
+                  }
+                  BranchRelocationType =
+                      RelocType == XCOFF::R_BA || RelocType == XCOFF::R_BR ||
+                      RelocType == XCOFF::R_RBA || RelocType == XCOFF::R_RBR;
+
+                  // If we have a valid relocation, try to print its
+                  // corresponding symbol name. Multiple relocations on the
+                  // same instruction are not handled.
+                  // Branches to fixup code will have the RelFixedUp flag set in
+                  // the RLD. For these instructions, we print the correct
+                  // branch target, but print the referenced symbol as a
+                  // comment.
+                  if (Error E = getRelocationValueString(*RelCur, false, Val)) {
+                    // If -r was used, this error will be printed later.
+                    // Otherwise, we ignore the error and print what
+                    // would have been printed without using relocations.
+                    consumeError(std::move(E));
+                    *TargetOS << TargetName;
+                    RelFixedUp = false; // Suppress comment for RLD sym name
+                  } else if (BranchRelocationType && !RelFixedUp)
+                    *TargetOS << Val;
+                  else
+                    *TargetOS << TargetName;
+                  if (Disp)
+                    *TargetOS << "+0x" << Twine::utohexstr(Disp);
+                } else if (!Disp) {
                   *TargetOS << TargetName;
                 } else if (BBAddrMapLabelAvailable) {
-                  *TargetOS << BBAddrMapLabels[Target].front();
+                  *TargetOS << BBAddrMapLabels[Target].front().BlockLabel;
                 } else if (LabelAvailable) {
                   *TargetOS << AllLabels[Target];
                 } else {
@@ -1970,8 +2334,15 @@
                   *TargetOS << TargetName << "+0x" << Twine::utohexstr(Disp);
                 }
                 *TargetOS << ">";
+                if (RelFixedUp && !InlineRelocs) {
+                  // We have fixup code for a relocation. We print the
+                  // referenced symbol as a comment.
+                  *TargetOS << "\t# " << Val;
+                }
+
               } else if (BBAddrMapLabelAvailable) {
-                *TargetOS << " <" << BBAddrMapLabels[Target].front() << ">";
+                *TargetOS << " <" << BBAddrMapLabels[Target].front().BlockLabel
+                          << ">";
               } else if (LabelAvailable) {
                 *TargetOS << " <" << AllLabels[Target] << ">";
               }
@@ -1980,44 +2351,35 @@
               if (TargetOS == &CommentStream)
                 *TargetOS << "\n";
             }
+
+            DT->InstrAnalysis->updateState(Inst, SectionAddr + Index);
+          } else if (!Disassembled && DT->InstrAnalysis) {
+            DT->InstrAnalysis->resetState();
           }
         }
 
-        assert(Ctx.getAsmInfo());
-        emitPostInstructionInfo(FOS, *Ctx.getAsmInfo(), *STI,
-                                CommentStream.str(), LVP);
+        assert(DT->Context->getAsmInfo());
+        emitPostInstructionInfo(FOS, *DT->Context->getAsmInfo(),
+                                *DT->SubtargetInfo, CommentStream.str(), LVP);
         Comments.clear();
 
-        // Hexagon does this in pretty printer
-        if (Obj.getArch() != Triple::hexagon) {
-          // Print relocation for instruction and data.
-          while (RelCur != RelEnd) {
-            uint64_t Offset = RelCur->getOffset() - RelAdjustment;
-            // If this relocation is hidden, skip it.
-            if (getHidden(*RelCur) || SectionAddr + Offset < StartAddress) {
-              ++RelCur;
-              continue;
-            }
+        if (BTF)
+          printBTFRelocation(FOS, *BTF, {Index, Section.getIndex()}, LVP);
 
-            // Stop when RelCur's offset is past the disassembled
-            // instruction/data. Note that it's possible the disassembled data
-            // is not the complete data: we might see the relocation printed in
-            // the middle of the data, but this matches the binutils objdump
-            // output.
-            if (Offset >= Index + Size)
-              break;
-
+        // Hexagon handles relocs in pretty printer
+        if (InlineRelocs && Obj.getArch() != Triple::hexagon) {
+          while (findRel()) {
             // When --adjust-vma is used, update the address printed.
             if (RelCur->getSymbol() != Obj.symbol_end()) {
               Expected<section_iterator> SymSI =
                   RelCur->getSymbol()->getSection();
               if (SymSI && *SymSI != Obj.section_end() &&
                   shouldAdjustVA(**SymSI))
-                Offset += AdjustVMA;
+                RelOffset += AdjustVMA;
             }
 
             printRelocation(FOS, Obj.getFileName(), *RelCur,
-                            SectionAddr + Offset, Is64Bits);
+                            SectionAddr + RelOffset, Is64Bits);
             LVP.printAfterOtherLine(FOS, true);
             ++RelCur;
           }
@@ -2064,20 +2426,6 @@
     Features.AddFeature("+all");
   }
 
-  std::unique_ptr<const MCRegisterInfo> MRI(
-      TheTarget->createMCRegInfo(TripleName));
-  if (!MRI)
-    reportError(Obj->getFileName(),
-                "no register info for target " + TripleName);
-
-  // Set up disassembler.
-  MCTargetOptions MCOptions;
-  std::unique_ptr<const MCAsmInfo> AsmInfo(
-      TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
-  if (!AsmInfo)
-    reportError(Obj->getFileName(),
-                "no assembly info for target " + TripleName);
-
   if (MCPU.empty())
     MCPU = Obj->tryGetCPUName().value_or("").str();
 
@@ -2098,64 +2446,48 @@
     if (Elf32BE && (Elf32BE->isRelocatableObject() ||
                     !(Elf32BE->getPlatformFlags() & ELF::EF_ARM_BE8))) {
       Features.AddFeature("+big-endian-instructions");
-      ARMPrettyPrinterInst.setInstructionEndianness(llvm::support::big);
+      ARMPrettyPrinterInst.setInstructionEndianness(llvm::endianness::big);
     } else {
-      ARMPrettyPrinterInst.setInstructionEndianness(llvm::support::little);
+      ARMPrettyPrinterInst.setInstructionEndianness(llvm::endianness::little);
     }
   }
 
-  std::unique_ptr<const MCSubtargetInfo> STI(
-      TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString()));
-  if (!STI)
-    reportError(Obj->getFileName(),
-                "no subtarget info for target " + TripleName);
-  std::unique_ptr<const MCInstrInfo> MII(TheTarget->createMCInstrInfo());
-  if (!MII)
-    reportError(Obj->getFileName(),
-                "no instruction info for target " + TripleName);
-  MCContext Ctx(Triple(TripleName), AsmInfo.get(), MRI.get(), STI.get());
-  // FIXME: for now initialize MCObjectFileInfo with default values
-  std::unique_ptr<MCObjectFileInfo> MOFI(
-      TheTarget->createMCObjectFileInfo(Ctx, /*PIC=*/false));
-  Ctx.setObjectFileInfo(MOFI.get());
-
-  std::unique_ptr<MCDisassembler> DisAsm(
-      TheTarget->createMCDisassembler(*STI, Ctx));
-  if (!DisAsm)
-    reportError(Obj->getFileName(), "no disassembler for target " + TripleName);
+  DisassemblerTarget PrimaryTarget(TheTarget, *Obj, TripleName, MCPU, Features);
 
   // If we have an ARM object file, we need a second disassembler, because
   // ARM CPUs have two different instruction sets: ARM mode, and Thumb mode.
   // We use mapping symbols to switch between the two assemblers, where
   // appropriate.
-  std::unique_ptr<MCDisassembler> SecondaryDisAsm;
-  std::unique_ptr<const MCSubtargetInfo> SecondarySTI;
-  if (isArmElf(*Obj) && !STI->checkFeatures("+mclass")) {
-    if (STI->checkFeatures("+thumb-mode"))
-      Features.AddFeature("-thumb-mode");
-    else
-      Features.AddFeature("+thumb-mode");
-    SecondarySTI.reset(TheTarget->createMCSubtargetInfo(TripleName, MCPU,
-                                                        Features.getString()));
-    SecondaryDisAsm.reset(TheTarget->createMCDisassembler(*SecondarySTI, Ctx));
+  std::optional<DisassemblerTarget> SecondaryTarget;
+
+  if (isArmElf(*Obj)) {
+    if (!PrimaryTarget.SubtargetInfo->checkFeatures("+mclass")) {
+      if (PrimaryTarget.SubtargetInfo->checkFeatures("+thumb-mode"))
+        Features.AddFeature("-thumb-mode");
+      else
+        Features.AddFeature("+thumb-mode");
+      SecondaryTarget.emplace(PrimaryTarget, Features);
+    }
+  } else if (const auto *COFFObj = dyn_cast<COFFObjectFile>(Obj)) {
+    const chpe_metadata *CHPEMetadata = COFFObj->getCHPEMetadata();
+    if (CHPEMetadata && CHPEMetadata->CodeMapCount) {
+      // Set up x86_64 disassembler for ARM64EC binaries.
+      Triple X64Triple(TripleName);
+      X64Triple.setArch(Triple::ArchType::x86_64);
+
+      std::string Error;
+      const Target *X64Target =
+          TargetRegistry::lookupTarget("", X64Triple, Error);
+      if (X64Target) {
+        SubtargetFeatures X64Features;
+        SecondaryTarget.emplace(X64Target, *Obj, X64Triple.getTriple(), "",
+                                X64Features);
+      } else {
+        reportWarning(Error, Obj->getFileName());
+      }
+    }
   }
 
-  std::unique_ptr<const MCInstrAnalysis> MIA(
-      TheTarget->createMCInstrAnalysis(MII.get()));
-
-  int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
-  std::unique_ptr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
-      Triple(TripleName), AsmPrinterVariant, *AsmInfo, *MII, *MRI));
-  if (!IP)
-    reportError(Obj->getFileName(),
-                "no instruction printer for target " + TripleName);
-  IP->setPrintImmHex(PrintImmHex);
-  IP->setPrintBranchImmAsAddress(true);
-  IP->setSymbolizeOperands(SymbolizeOperands);
-  IP->setMCInstrAnalysis(MIA.get());
-
-  PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName));
-
   const ObjectFile *DbgObj = Obj;
   if (!FetchedBinary.getBinary() && !Obj->hasDebugInfo()) {
     if (std::optional<OwningBinary<Binary>> DebugBinaryOpt =
@@ -2184,13 +2516,12 @@
   SourcePrinter SP(DbgObj, TheTarget->getName());
 
   for (StringRef Opt : DisassemblerOptions)
-    if (!IP->applyTargetSpecificCLOption(Opt))
+    if (!PrimaryTarget.InstPrinter->applyTargetSpecificCLOption(Opt))
       reportError(Obj->getFileName(),
                   "Unrecognized disassembler option: " + Opt);
 
-  disassembleObject(TheTarget, *Obj, *DbgObj, Ctx, DisAsm.get(),
-                    SecondaryDisAsm.get(), MIA.get(), IP.get(), STI.get(),
-                    SecondarySTI.get(), PIP, SP, InlineRelocs);
+  disassembleObject(*Obj, *DbgObj, PrimaryTarget, SecondaryTarget, SP,
+                    InlineRelocs);
 }
 
 void Dumper::printRelocations() {
@@ -2232,7 +2563,8 @@
         if (Address < StartAddress || Address > StopAddress || getHidden(Reloc))
           continue;
         Reloc.getTypeName(RelocName);
-        if (Error E = getRelocationValueString(Reloc, ValueStr))
+        if (Error E =
+                getRelocationValueString(Reloc, SymbolDescription, ValueStr))
           reportUniqueWarning(std::move(E));
 
         outs() << format(Fmt.data(), Address) << " "
@@ -2411,6 +2743,9 @@
     return;
   }
   uint64_t Address = *AddrOrErr;
+  section_iterator SecI = unwrapOrError(Symbol.getSection(), FileName);
+  if (SecI != O.section_end() && shouldAdjustVA(*SecI))
+    Address += AdjustVMA;
   if ((Address < StartAddress) || (Address > StopAddress))
     return;
   SymbolRef::Type Type =
@@ -2676,7 +3011,7 @@
   outs() << FMP;
 }
 
-void Dumper::printPrivateHeaders(bool) {
+void Dumper::printPrivateHeaders() {
   reportError(O.getFileName(), "Invalid/Unsupported object file format");
 }
 
@@ -2811,7 +3146,7 @@
   if (FileHeaders)
     printFileHeaders(O);
   if (PrivateHeaders || FirstPrivateHeader)
-    D.printPrivateHeaders(FirstPrivateHeader);
+    D.printPrivateHeaders();
   if (SectionHeaders)
     printSectionHeaders(*O);
   if (SymbolTable)
@@ -3077,6 +3412,16 @@
     if (DbgVariables == DVInvalid)
       invalidArgValue(A);
   }
+  if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_disassembler_color_EQ)) {
+    DisassemblyColor = StringSwitch<ColorOutput>(A->getValue())
+                           .Case("on", ColorOutput::Enable)
+                           .Case("off", ColorOutput::Disable)
+                           .Case("terminal", ColorOutput::Auto)
+                           .Default(ColorOutput::Invalid);
+    if (DisassemblyColor == ColorOutput::Invalid)
+      invalidArgValue(A);
+  }
+
   parseIntArg(InputArgs, OBJDUMP_debug_vars_indent_EQ, DbgIndent);
 
   parseMachOOptions(InputArgs);
@@ -3111,10 +3456,13 @@
         DisassemblerOptions.push_back(V.str());
     }
   }
-  if (AsmSyntax) {
-    const char *Argv[] = {"llvm-objdump", AsmSyntax};
-    llvm::cl::ParseCommandLineOptions(2, Argv);
-  }
+  SmallVector<const char *> Args = {"llvm-objdump"};
+  for (const opt::Arg *A : InputArgs.filtered(OBJDUMP_mllvm))
+    Args.push_back(A->getValue());
+  if (AsmSyntax)
+    Args.push_back(AsmSyntax);
+  if (Args.size() > 1)
+    llvm::cl::ParseCommandLineOptions(Args.size(), Args.data());
 
   // Look up any provided build IDs, then append them to the input filenames.
   for (const opt::Arg *A : InputArgs.filtered(OBJDUMP_build_id)) {
@@ -3132,9 +3480,8 @@
     InputFilenames.push_back("a.out");
 }
 
-int main(int argc, char **argv) {
+int llvm_objdump_main(int argc, char **argv, const llvm::ToolContext &) {
   using namespace llvm;
-  InitLLVM X(argc, argv);
 
   ToolName = argv[0];
   std::unique_ptr<CommonOptTable> T;
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h b/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h
index b3136f0..7778cf6 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -18,6 +18,7 @@
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/DataTypes.h"
 #include "llvm/Support/FormattedStream.h"
+#include <functional>
 #include <memory>
 
 namespace llvm {
@@ -76,14 +77,17 @@
   const object::ObjectFile &O;
   StringSet<> Warnings;
 
+protected:
+  std::function<Error(const Twine &Msg)> WarningHandler;
+
 public:
-  Dumper(const object::ObjectFile &O) : O(O) {}
+  Dumper(const object::ObjectFile &O);
   virtual ~Dumper() {}
 
   void reportUniqueWarning(Error Err);
   void reportUniqueWarning(const Twine &Msg);
 
-  virtual void printPrivateHeaders(bool MachOOnlyFirst);
+  virtual void printPrivateHeaders();
   virtual void printDynamicRelocations() {}
   void printSymbolTable(StringRef ArchiveName,
                         StringRef ArchitectureName = StringRef(),
@@ -133,7 +137,8 @@
 std::string getFileNameForError(const object::Archive::Child &C,
                                 unsigned Index);
 SymbolInfoTy createSymbolInfo(const object::ObjectFile &Obj,
-                              const object::SymbolRef &Symbol);
+                              const object::SymbolRef &Symbol,
+                              bool IsMappingSymbol = false);
 unsigned getInstStartColumn(const MCSubtargetInfo &STI);
 void printRawData(llvm::ArrayRef<uint8_t> Bytes, uint64_t Address,
                   llvm::formatted_raw_ostream &OS,
diff --git a/src/llvm-project/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp b/src/llvm-project/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
index d952ea1..fcccf0e 100644
--- a/src/llvm-project/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-opt-fuzzer/llvm-opt-fuzzer.cpp
@@ -198,23 +198,9 @@
     errs() << *argv[0] << ": -mtriple must be specified\n";
     exit(1);
   }
-  Triple TargetTriple = Triple(Triple::normalize(TargetTripleStr));
-
-  std::string Error;
-  const Target *TheTarget =
-      TargetRegistry::lookupTarget(codegen::getMArch(), TargetTriple, Error);
-  if (!TheTarget) {
-    errs() << *argv[0] << ": " << Error;
-    exit(1);
-  }
-
-  TargetOptions Options =
-      codegen::InitTargetOptionsFromCodeGenFlags(TargetTriple);
-  TM.reset(TheTarget->createTargetMachine(
-      TargetTriple.getTriple(), codegen::getCPUStr(), codegen::getFeaturesStr(),
-      Options, codegen::getExplicitRelocModel(),
-      codegen::getExplicitCodeModel(), CodeGenOpt::Default));
-  assert(TM && "Could not allocate target machine!");
+  ExitOnError ExitOnErr(std::string(*argv[0]) + ": error:");
+  TM = ExitOnErr(codegen::createTargetMachineForTriple(
+      Triple::normalize(TargetTripleStr)));
 
   // Check that pass pipeline is specified and correct
   //
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
index 447a9cb..5ce663e 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -1286,7 +1286,7 @@
       return ContentsOrErr.takeError();
 
     uint32_t Magic;
-    BinaryStreamReader Reader(*ContentsOrErr, llvm::support::little);
+    BinaryStreamReader Reader(*ContentsOrErr, llvm::endianness::little);
     if (auto EC = Reader.readInteger(Magic))
       return EC;
     if (Magic != COFF::DEBUG_SECTION_MAGIC)
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.h b/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
index a0c9530..6714a6a 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
@@ -17,8 +17,6 @@
 #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
 
-#include <string>
-
 namespace llvm {
 namespace object {
 class COFFObjectFile;
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp
index 3e57e31..ce9d659 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp
@@ -66,9 +66,8 @@
 }
 
 Error ExplainOutputStyle::explainBinaryFile() {
-  std::unique_ptr<BinaryByteStream> Stream =
-      std::make_unique<BinaryByteStream>(File.unknown().getBuffer(),
-                                          llvm::support::little);
+  std::unique_ptr<BinaryByteStream> Stream = std::make_unique<BinaryByteStream>(
+      File.unknown().getBuffer(), llvm::endianness::little);
   switch (opts::explain::InputType) {
   case opts::explain::InputFileType::DBIStream: {
     DbiStream Dbi(std::move(Stream));
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h b/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h
index 499f2a8..84b4a7e 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h
@@ -13,8 +13,6 @@
 
 #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
 
-#include <string>
-
 namespace llvm {
 
 namespace pdb {
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
index 96c3d49..1beb2d2 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/MinimalSymbolDumper.cpp
@@ -358,6 +358,23 @@
   return typesetItemList(GapStrs, 7, IndentLevel, ", ");
 }
 
+static std::string formatJumpTableEntrySize(JumpTableEntrySize EntrySize) {
+  switch (EntrySize) {
+    RETURN_CASE(JumpTableEntrySize, Int8, "int8");
+    RETURN_CASE(JumpTableEntrySize, UInt8, "uin8");
+    RETURN_CASE(JumpTableEntrySize, Int16, "int16");
+    RETURN_CASE(JumpTableEntrySize, UInt16, "uint16");
+    RETURN_CASE(JumpTableEntrySize, Int32, "int32");
+    RETURN_CASE(JumpTableEntrySize, UInt32, "uint32");
+    RETURN_CASE(JumpTableEntrySize, Pointer, "pointer");
+    RETURN_CASE(JumpTableEntrySize, UInt8ShiftLeft, "uint8shl");
+    RETURN_CASE(JumpTableEntrySize, UInt16ShiftLeft, "uint16shl");
+    RETURN_CASE(JumpTableEntrySize, Int8ShiftLeft, "int8shl");
+    RETURN_CASE(JumpTableEntrySize, Int16ShiftLeft, "int16shl");
+  }
+  return formatUnknownEnum(EntrySize);
+}
+
 Error MinimalSymbolDumper::visitSymbolBegin(codeview::CVSymbol &Record) {
   return visitSymbolBegin(Record, 0);
 }
@@ -858,9 +875,24 @@
 }
 
 Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
+  const char *Format;
+  switch (CVR.kind()) {
+  case S_CALLEES:
+    Format = "callee: {0}";
+    break;
+  case S_CALLERS:
+    Format = "caller: {0}";
+    break;
+  case S_INLINEES:
+    Format = "inlinee: {0}";
+    break;
+  default:
+    return llvm::make_error<CodeViewError>(
+        "Unknown CV Record type for a CallerSym object!");
+  }
   AutoIndent Indent(P, 7);
   for (const auto &I : Caller.Indices) {
-    P.formatLine("callee: {0}", idIndex(I));
+    P.formatLine(Format, idIndex(I));
   }
   return Error::success();
 }
@@ -905,3 +937,17 @@
                                                    Annot.Strings));
   return Error::success();
 }
+
+Error MinimalSymbolDumper::visitKnownRecord(CVSymbol &CVR,
+                                            JumpTableSym &JumpTable) {
+  AutoIndent Indent(P, 7);
+  P.formatLine(
+      "base = {0}, switchtype = {1}, branch = {2}, table = {3}, entriescount = "
+      "{4}",
+      formatSegmentOffset(JumpTable.BaseSegment, JumpTable.BaseOffset),
+      formatJumpTableEntrySize(JumpTable.SwitchType),
+      formatSegmentOffset(JumpTable.BranchSegment, JumpTable.BranchOffset),
+      formatSegmentOffset(JumpTable.TableSegment, JumpTable.TableOffset),
+      JumpTable.EntriesCount);
+  return Error::success();
+}
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h b/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h
index f43c5c1..50c8f5d 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.h
@@ -15,9 +15,7 @@
 #include "llvm/DebugInfo/PDB/PDBSymbolData.h"
 #include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
 
-#include <list>
 #include <memory>
-#include <unordered_map>
 
 namespace llvm {
 class BitVector;
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h b/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h
index 8f78b3b..f7ef3c6 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.h
@@ -9,8 +9,6 @@
 #ifndef LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H
 #define LLVM_TOOLS_LLVMPDBDUMP_PRETTYCLASSLAYOUTGRAPHICALDUMPER_H
 
-#include "llvm/ADT/BitVector.h"
-
 #include "llvm/DebugInfo/PDB/PDBSymDumper.h"
 
 namespace llvm {
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/StreamUtil.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/StreamUtil.cpp
index 878fb77..b392582 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/StreamUtil.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/StreamUtil.cpp
@@ -9,7 +9,6 @@
 #include "StreamUtil.h"
 
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h"
 #include "llvm/DebugInfo/PDB/Native/DbiModuleList.h"
 #include "llvm/DebugInfo/PDB/Native/DbiStream.h"
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.cpp
index 5ae720a..c7653b7 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.cpp
@@ -55,7 +55,7 @@
   // - globals
   // - modi symbols
   // - LF_UDT_MOD_SRC_LINE? VC always links these in.
-  for (SymbolGroup SG : File.symbol_groups()) {
+  for (const SymbolGroup &SG : File.symbol_groups()) {
     if (File.isObj()) {
       for (const auto &SS : SG.getDebugSubsections()) {
         // FIXME: Are there other type-referencing subsections? Inlinees?
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
index 61cad15..9da14cc 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -27,8 +27,6 @@
 #include "YAMLOutputStyle.h"
 
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/BinaryFormat/Magic.h"
@@ -842,7 +840,7 @@
       ExitOnErr(DbiBuilder.addModuleSourceFile(ModiBuilder, S));
     if (MI.Modi) {
       const auto &ModiStream = *MI.Modi;
-      for (auto Symbol : ModiStream.Symbols) {
+      for (const auto &Symbol : ModiStream.Symbols) {
         ModiBuilder.addSymbol(
             Symbol.toCodeViewSymbol(Allocator, CodeViewContainer::Pdb));
       }
@@ -1415,7 +1413,7 @@
   SourceStream = File.createIndexedStream(Index);
   auto OutFile = ExitOnErr(
       FileOutputBuffer::create(OutFileName, SourceStream->getLength()));
-  FileBufferByteStream DestStream(std::move(OutFile), llvm::support::little);
+  FileBufferByteStream DestStream(std::move(OutFile), llvm::endianness::little);
   BinaryStreamWriter Writer(DestStream);
   ExitOnErr(Writer.writeStreamRef(*SourceStream));
   ExitOnErr(DestStream.commit());
@@ -1576,7 +1574,7 @@
     if (opts::yaml2pdb::YamlPdbOutputFile.empty()) {
       SmallString<16> OutputFilename(opts::yaml2pdb::InputFilename.getValue());
       sys::path::replace_extension(OutputFilename, ".pdb");
-      opts::yaml2pdb::YamlPdbOutputFile = std::string(OutputFilename.str());
+      opts::yaml2pdb::YamlPdbOutputFile = std::string(OutputFilename);
     }
     yamlToPdb(opts::yaml2pdb::InputFilename);
   } else if (opts::DiaDumpSubcommand) {
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.h b/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
index 8766d70..b8c8033 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
@@ -9,7 +9,6 @@
 #ifndef LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
 #define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
 
-#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
 #include "llvm/Support/CommandLine.h"
diff --git a/src/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp b/src/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp
index da10ddc..239aa1c 100644
--- a/src/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -30,11 +30,11 @@
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormattedStream.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/MD5.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/Regex.h"
 #include "llvm/Support/ThreadPool.h"
 #include "llvm/Support/Threading.h"
 #include "llvm/Support/VirtualFileSystem.h"
@@ -46,10 +46,36 @@
 #include <queue>
 
 using namespace llvm;
+using ProfCorrelatorKind = InstrProfCorrelator::ProfCorrelatorKind;
 
-// We use this string to indicate that there are
-// multiple static functions map to the same name.
-const std::string DuplicateNameStr = "----";
+// https://llvm.org/docs/CommandGuide/llvm-profdata.html has documentations
+// on each subcommand.
+cl::SubCommand ShowSubcommand(
+    "show",
+    "Takes a profile data file and displays the profiles. See detailed "
+    "documentation in "
+    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-show");
+cl::SubCommand OrderSubcommand(
+    "order",
+    "Reads temporal profiling traces from a profile and outputs a function "
+    "order that reduces the number of page faults for those traces. See "
+    "detailed documentation in "
+    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-order");
+cl::SubCommand OverlapSubcommand(
+    "overlap",
+    "Computes and displays the overlap between two profiles. See detailed "
+    "documentation in "
+    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-overlap");
+cl::SubCommand MergeSubcommand(
+    "merge",
+    "Takes several profiles and merge them together. See detailed "
+    "documentation in "
+    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-merge");
+
+namespace {
+enum ProfileKinds { instr, sample, memory };
+enum FailureMode { warnOnly, failIfAnyAreInvalid, failIfAllAreInvalid };
+} // namespace
 
 enum ProfileFormat {
   PF_None = 0,
@@ -62,6 +88,337 @@
 
 enum class ShowFormat { Text, Json, Yaml };
 
+// Common options.
+cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
+                                    cl::init("-"), cl::desc("Output file"),
+                                    cl::sub(ShowSubcommand),
+                                    cl::sub(OrderSubcommand),
+                                    cl::sub(OverlapSubcommand),
+                                    cl::sub(MergeSubcommand));
+// NOTE: cl::alias must not have cl::sub(), since aliased option's cl::sub()
+// will be used. llvm::cl::alias::done() method asserts this condition.
+cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
+                          cl::aliasopt(OutputFilename));
+
+// Options common to at least two commands.
+cl::opt<ProfileKinds> ProfileKind(
+    cl::desc("Profile kind:"), cl::sub(MergeSubcommand),
+    cl::sub(OverlapSubcommand), cl::init(instr),
+    cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
+               clEnumVal(sample, "Sample profile")));
+cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"),
+                              cl::sub(ShowSubcommand),
+                              cl::sub(OrderSubcommand));
+cl::opt<unsigned> MaxDbgCorrelationWarnings(
+    "max-debug-info-correlation-warnings",
+    cl::desc("The maximum number of warnings to emit when correlating "
+             "profile from debug info (0 = no limit)"),
+    cl::sub(MergeSubcommand), cl::sub(ShowSubcommand), cl::init(5));
+cl::opt<std::string> ProfiledBinary(
+    "profiled-binary", cl::init(""),
+    cl::desc("Path to binary from which the profile was collected."),
+    cl::sub(ShowSubcommand), cl::sub(MergeSubcommand));
+cl::opt<std::string> DebugInfoFilename(
+    "debug-info", cl::init(""),
+    cl::desc(
+        "For show, read and extract profile metadata from debug info and show "
+        "the functions it found. For merge, use the provided debug info to "
+        "correlate the raw profile."),
+    cl::sub(ShowSubcommand), cl::sub(MergeSubcommand));
+cl::opt<std::string>
+    BinaryFilename("binary-file", cl::init(""),
+                   cl::desc("For merge, use the provided unstripped bianry to "
+                            "correlate the raw profile."),
+                   cl::sub(MergeSubcommand));
+cl::opt<std::string> FuncNameFilter(
+    "function",
+    cl::desc("Only functions matching the filter are shown in the output. For "
+             "overlapping CSSPGO, this takes a function name with calling "
+             "context."),
+    cl::sub(ShowSubcommand), cl::sub(OverlapSubcommand),
+    cl::sub(MergeSubcommand));
+
+// TODO: Consider creating a template class (e.g., MergeOption, ShowOption) to
+// factor out the common cl::sub in cl::opt constructor for subcommand-specific
+// options.
+
+// Options specific to merge subcommand.
+cl::list<std::string> InputFilenames(cl::Positional, cl::sub(MergeSubcommand),
+                                     cl::desc("<filename...>"));
+cl::list<std::string> WeightedInputFilenames("weighted-input",
+                                             cl::sub(MergeSubcommand),
+                                             cl::desc("<weight>,<filename>"));
+cl::opt<ProfileFormat> OutputFormat(
+    cl::desc("Format of output profile"), cl::sub(MergeSubcommand),
+    cl::init(PF_Ext_Binary),
+    cl::values(clEnumValN(PF_Binary, "binary", "Binary encoding"),
+               clEnumValN(PF_Ext_Binary, "extbinary",
+                          "Extensible binary encoding "
+                          "(default)"),
+               clEnumValN(PF_Text, "text", "Text encoding"),
+               clEnumValN(PF_GCC, "gcc",
+                          "GCC encoding (only meaningful for -sample)")));
+cl::opt<std::string>
+    InputFilenamesFile("input-files", cl::init(""), cl::sub(MergeSubcommand),
+                       cl::desc("Path to file containing newline-separated "
+                                "[<weight>,]<filename> entries"));
+cl::alias InputFilenamesFileA("f", cl::desc("Alias for --input-files"),
+                              cl::aliasopt(InputFilenamesFile));
+cl::opt<bool> DumpInputFileList(
+    "dump-input-file-list", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Dump the list of input files and their weights, then exit"));
+cl::opt<std::string> RemappingFile("remapping-file", cl::value_desc("file"),
+                                   cl::sub(MergeSubcommand),
+                                   cl::desc("Symbol remapping file"));
+cl::alias RemappingFileA("r", cl::desc("Alias for --remapping-file"),
+                         cl::aliasopt(RemappingFile));
+cl::opt<bool>
+    UseMD5("use-md5", cl::init(false), cl::Hidden,
+           cl::desc("Choose to use MD5 to represent string in name table (only "
+                    "meaningful for -extbinary)"),
+           cl::sub(MergeSubcommand));
+cl::opt<bool> CompressAllSections(
+    "compress-all-sections", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Compress all sections when writing the profile (only "
+             "meaningful for -extbinary)"));
+cl::opt<bool> SampleMergeColdContext(
+    "sample-merge-cold-context", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc(
+        "Merge context sample profiles whose count is below cold threshold"));
+cl::opt<bool> SampleTrimColdContext(
+    "sample-trim-cold-context", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc(
+        "Trim context sample profiles whose count is below cold threshold"));
+cl::opt<uint32_t> SampleColdContextFrameDepth(
+    "sample-frame-depth-for-cold-context", cl::init(1),
+    cl::sub(MergeSubcommand),
+    cl::desc("Keep the last K frames while merging cold profile. 1 means the "
+             "context-less base profile"));
+cl::opt<size_t> OutputSizeLimit(
+    "output-size-limit", cl::init(0), cl::Hidden, cl::sub(MergeSubcommand),
+    cl::desc("Trim cold functions until profile size is below specified "
+             "limit in bytes. This uses a heursitic and functions may be "
+             "excessively trimmed"));
+cl::opt<bool> GenPartialProfile(
+    "gen-partial-profile", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Generate a partial profile (only meaningful for -extbinary)"));
+cl::opt<std::string> SupplInstrWithSample(
+    "supplement-instr-with-sample", cl::init(""), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Supplement an instr profile with sample profile, to correct "
+             "the profile unrepresentativeness issue. The sample "
+             "profile is the input of the flag. Output will be in instr "
+             "format (The flag only works with -instr)"));
+cl::opt<float> ZeroCounterThreshold(
+    "zero-counter-threshold", cl::init(0.7), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("For the function which is cold in instr profile but hot in "
+             "sample profile, if the ratio of the number of zero counters "
+             "divided by the total number of counters is above the "
+             "threshold, the profile of the function will be regarded as "
+             "being harmful for performance and will be dropped."));
+cl::opt<unsigned> SupplMinSizeThreshold(
+    "suppl-min-size-threshold", cl::init(10), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("If the size of a function is smaller than the threshold, "
+             "assume it can be inlined by PGO early inliner and it won't "
+             "be adjusted based on sample profile."));
+cl::opt<unsigned> InstrProfColdThreshold(
+    "instr-prof-cold-threshold", cl::init(0), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("User specified cold threshold for instr profile which will "
+             "override the cold threshold got from profile summary. "));
+// WARNING: This reservoir size value is propagated to any input indexed
+// profiles for simplicity. Changing this value between invocations could
+// result in sample bias.
+cl::opt<uint64_t> TemporalProfTraceReservoirSize(
+    "temporal-profile-trace-reservoir-size", cl::init(100),
+    cl::sub(MergeSubcommand),
+    cl::desc("The maximum number of stored temporal profile traces (default: "
+             "100)"));
+cl::opt<uint64_t> TemporalProfMaxTraceLength(
+    "temporal-profile-max-trace-length", cl::init(10000),
+    cl::sub(MergeSubcommand),
+    cl::desc("The maximum length of a single temporal profile trace "
+             "(default: 10000)"));
+cl::opt<std::string> FuncNameNegativeFilter(
+    "no-function", cl::init(""),
+    cl::sub(MergeSubcommand),
+    cl::desc("Exclude functions matching the filter from the output."));
+
+cl::opt<FailureMode>
+    FailMode("failure-mode", cl::init(failIfAnyAreInvalid),
+             cl::desc("Failure mode:"), cl::sub(MergeSubcommand),
+             cl::values(clEnumValN(warnOnly, "warn",
+                                   "Do not fail and just print warnings."),
+                        clEnumValN(failIfAnyAreInvalid, "any",
+                                   "Fail if any profile is invalid."),
+                        clEnumValN(failIfAllAreInvalid, "all",
+                                   "Fail only if all profiles are invalid.")));
+
+cl::opt<bool> OutputSparse(
+    "sparse", cl::init(false), cl::sub(MergeSubcommand),
+    cl::desc("Generate a sparse profile (only meaningful for -instr)"));
+cl::opt<unsigned> NumThreads(
+    "num-threads", cl::init(0), cl::sub(MergeSubcommand),
+    cl::desc("Number of merge threads to use (default: autodetect)"));
+cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
+                      cl::aliasopt(NumThreads));
+
+cl::opt<std::string> ProfileSymbolListFile(
+    "prof-sym-list", cl::init(""), cl::sub(MergeSubcommand),
+    cl::desc("Path to file containing the list of function symbols "
+             "used to populate profile symbol list"));
+
+cl::opt<SampleProfileLayout> ProfileLayout(
+    "convert-sample-profile-layout",
+    cl::desc("Convert the generated profile to a profile with a new layout"),
+    cl::sub(MergeSubcommand), cl::init(SPL_None),
+    cl::values(
+        clEnumValN(SPL_Nest, "nest",
+                   "Nested profile, the input should be CS flat profile"),
+        clEnumValN(SPL_Flat, "flat",
+                   "Profile with nested inlinee flatten out")));
+
+cl::opt<bool> DropProfileSymbolList(
+    "drop-profile-symbol-list", cl::init(false), cl::Hidden,
+    cl::sub(MergeSubcommand),
+    cl::desc("Drop the profile symbol list when merging AutoFDO profiles "
+             "(only meaningful for -sample)"));
+
+// Options specific to overlap subcommand.
+cl::opt<std::string> BaseFilename(cl::Positional, cl::Required,
+                                  cl::desc("<base profile file>"),
+                                  cl::sub(OverlapSubcommand));
+cl::opt<std::string> TestFilename(cl::Positional, cl::Required,
+                                  cl::desc("<test profile file>"),
+                                  cl::sub(OverlapSubcommand));
+
+cl::opt<unsigned long long> SimilarityCutoff(
+    "similarity-cutoff", cl::init(0),
+    cl::desc("For sample profiles, list function names (with calling context "
+             "for csspgo) for overlapped functions "
+             "with similarities below the cutoff (percentage times 10000)."),
+    cl::sub(OverlapSubcommand));
+
+cl::opt<bool> IsCS(
+    "cs", cl::init(false),
+    cl::desc("For context sensitive PGO counts. Does not work with CSSPGO."),
+    cl::sub(OverlapSubcommand));
+
+cl::opt<unsigned long long> OverlapValueCutoff(
+    "value-cutoff", cl::init(-1),
+    cl::desc(
+        "Function level overlap information for every function (with calling "
+        "context for csspgo) in test "
+        "profile with max count value greater then the parameter value"),
+    cl::sub(OverlapSubcommand));
+
+// Options unique to show subcommand.
+cl::opt<bool> ShowCounts("counts", cl::init(false),
+                         cl::desc("Show counter values for shown functions"),
+                         cl::sub(ShowSubcommand));
+cl::opt<ShowFormat>
+    SFormat("show-format", cl::init(ShowFormat::Text),
+            cl::desc("Emit output in the selected format if supported"),
+            cl::sub(ShowSubcommand),
+            cl::values(clEnumValN(ShowFormat::Text, "text",
+                                  "emit normal text output (default)"),
+                       clEnumValN(ShowFormat::Json, "json", "emit JSON"),
+                       clEnumValN(ShowFormat::Yaml, "yaml", "emit YAML")));
+// TODO: Consider replacing this with `--show-format=text-encoding`.
+cl::opt<bool>
+    TextFormat("text", cl::init(false),
+               cl::desc("Show instr profile data in text dump format"),
+               cl::sub(ShowSubcommand));
+cl::opt<bool>
+    JsonFormat("json",
+               cl::desc("Show sample profile data in the JSON format "
+                        "(deprecated, please use --show-format=json)"),
+               cl::sub(ShowSubcommand));
+cl::opt<bool> ShowIndirectCallTargets(
+    "ic-targets", cl::init(false),
+    cl::desc("Show indirect call site target values for shown functions"),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowMemOPSizes(
+    "memop-sizes", cl::init(false),
+    cl::desc("Show the profiled sizes of the memory intrinsic calls "
+             "for shown functions"),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowDetailedSummary("detailed-summary", cl::init(false),
+                                  cl::desc("Show detailed profile summary"),
+                                  cl::sub(ShowSubcommand));
+cl::list<uint32_t> DetailedSummaryCutoffs(
+    cl::CommaSeparated, "detailed-summary-cutoffs",
+    cl::desc(
+        "Cutoff percentages (times 10000) for generating detailed summary"),
+    cl::value_desc("800000,901000,999999"), cl::sub(ShowSubcommand));
+cl::opt<bool>
+    ShowHotFuncList("hot-func-list", cl::init(false),
+                    cl::desc("Show profile summary of a list of hot functions"),
+                    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
+                               cl::desc("Details for each and every function"),
+                               cl::sub(ShowSubcommand));
+cl::opt<bool> ShowCS("showcs", cl::init(false),
+                     cl::desc("Show context sensitive counts"),
+                     cl::sub(ShowSubcommand));
+cl::opt<ProfileKinds> ShowProfileKind(
+    cl::desc("Profile kind supported by show:"), cl::sub(ShowSubcommand),
+    cl::init(instr),
+    cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
+               clEnumVal(sample, "Sample profile"),
+               clEnumVal(memory, "MemProf memory access profile")));
+cl::opt<uint32_t> TopNFunctions(
+    "topn", cl::init(0),
+    cl::desc("Show the list of functions with the largest internal counts"),
+    cl::sub(ShowSubcommand));
+cl::opt<uint32_t> ShowValueCutoff(
+    "value-cutoff", cl::init(0),
+    cl::desc("Set the count value cutoff. Functions with the maximum count "
+             "less than this value will not be printed out. (Default is 0)"),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> OnlyListBelow(
+    "list-below-cutoff", cl::init(false),
+    cl::desc("Only output names of functions whose max count values are "
+             "below the cutoff value"),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowProfileSymbolList(
+    "show-prof-sym-list", cl::init(false),
+    cl::desc("Show profile symbol list if it exists in the profile. "),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowSectionInfoOnly(
+    "show-sec-info-only", cl::init(false),
+    cl::desc("Show the information of each section in the sample profile. "
+             "The flag is only usable when the sample profile is in "
+             "extbinary format"),
+    cl::sub(ShowSubcommand));
+cl::opt<bool> ShowBinaryIds("binary-ids", cl::init(false),
+                            cl::desc("Show binary ids in the profile. "),
+                            cl::sub(ShowSubcommand));
+cl::opt<bool> ShowTemporalProfTraces(
+    "temporal-profile-traces",
+    cl::desc("Show temporal profile traces in the profile."),
+    cl::sub(ShowSubcommand));
+
+cl::opt<bool>
+    ShowCovered("covered", cl::init(false),
+                cl::desc("Show only the functions that have been executed."),
+                cl::sub(ShowSubcommand));
+
+cl::opt<bool> ShowProfileVersion("profile-version", cl::init(false),
+                                 cl::desc("Show profile version. "),
+                                 cl::sub(ShowSubcommand));
+
+// We use this string to indicate that there are
+// multiple static functions map to the same name.
+const std::string DuplicateNameStr = "----";
+
 static void warn(Twine Message, std::string Whence = "",
                  std::string Hint = "") {
   WithColor::warning();
@@ -112,11 +469,6 @@
   exitWithError(EC.message(), std::string(Whence));
 }
 
-namespace {
-enum ProfileKinds { instr, sample, memory };
-enum FailureMode { failIfAnyAreInvalid, failIfAllAreInvalid };
-}
-
 static void warnOrExitGivenError(FailureMode FailMode, std::error_code EC,
                                  StringRef Whence = "") {
   if (FailMode == failIfAnyAreInvalid)
@@ -199,6 +551,14 @@
     StringRef New = RemappingTable.lookup(Name);
     return New.empty() ? Name : New;
   }
+
+  FunctionId operator()(FunctionId Name) {
+    // MD5 name cannot be remapped.
+    if (!Name.isStringRef())
+      return Name;
+    StringRef New = RemappingTable.lookup(Name.stringRef());
+    return New.empty() ? Name : FunctionId(New);
+  }
 };
 }
 
@@ -306,7 +666,22 @@
   }
 
   auto FS = vfs::getRealFileSystem();
-  auto ReaderOrErr = InstrProfReader::create(Input.Filename, *FS, Correlator);
+  // TODO: This only saves the first non-fatal error from InstrProfReader, and
+  // then added to WriterContext::Errors. However, this is not extensible, if
+  // we have more non-fatal errors from InstrProfReader in the future. How
+  // should this interact with different -failure-mode?
+  std::optional<std::pair<Error, std::string>> ReaderWarning;
+  auto Warn = [&](Error E) {
+    if (ReaderWarning) {
+      consumeError(std::move(E));
+      return;
+    }
+    // Only show the first time an error occurs in this file.
+    auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
+    ReaderWarning = {make_error<InstrProfError>(ErrCode, Msg), Filename};
+  };
+  auto ReaderOrErr =
+      InstrProfReader::create(Input.Filename, *FS, Correlator, Warn);
   if (Error E = ReaderOrErr.takeError()) {
     // Skip the empty profiles by returning silently.
     auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
@@ -354,14 +729,23 @@
           Traces, Reader->getTemporalProfTraceStreamSize());
   }
   if (Reader->hasError()) {
-    if (Error E = Reader->getError())
+    if (Error E = Reader->getError()) {
       WC->Errors.emplace_back(std::move(E), Filename);
+      return;
+    }
   }
 
   std::vector<llvm::object::BuildID> BinaryIds;
-  if (Error E = Reader->readBinaryIds(BinaryIds))
+  if (Error E = Reader->readBinaryIds(BinaryIds)) {
     WC->Errors.emplace_back(std::move(E), Filename);
+    return;
+  }
   WC->Writer.addBinaryIds(BinaryIds);
+
+  if (ReaderWarning) {
+    WC->Errors.emplace_back(std::move(ReaderWarning->first),
+                            ReaderWarning->second);
+  }
 }
 
 /// Merge the \p Src writer context into \p Dst.
@@ -382,6 +766,62 @@
   });
 }
 
+static StringRef
+getFuncName(const StringMap<InstrProfWriter::ProfilingData>::value_type &Val) {
+  return Val.first();
+}
+
+static std::string
+getFuncName(const SampleProfileMap::value_type &Val) {
+  return Val.second.getContext().toString();
+}
+
+template <typename T>
+static void filterFunctions(T &ProfileMap) {
+  bool hasFilter = !FuncNameFilter.empty();
+  bool hasNegativeFilter = !FuncNameNegativeFilter.empty();
+  if (!hasFilter && !hasNegativeFilter)
+    return;
+
+  // If filter starts with '?' it is MSVC mangled name, not a regex.
+  llvm::Regex ProbablyMSVCMangledName("[?@$_0-9A-Za-z]+");
+  if (hasFilter && FuncNameFilter[0] == '?' &&
+      ProbablyMSVCMangledName.match(FuncNameFilter))
+    FuncNameFilter = llvm::Regex::escape(FuncNameFilter);
+  if (hasNegativeFilter && FuncNameNegativeFilter[0] == '?' &&
+      ProbablyMSVCMangledName.match(FuncNameNegativeFilter))
+    FuncNameNegativeFilter = llvm::Regex::escape(FuncNameNegativeFilter);
+
+  size_t Count = ProfileMap.size();
+  llvm::Regex Pattern(FuncNameFilter);
+  llvm::Regex NegativePattern(FuncNameNegativeFilter);
+  std::string Error;
+  if (hasFilter && !Pattern.isValid(Error))
+    exitWithError(Error);
+  if (hasNegativeFilter && !NegativePattern.isValid(Error))
+    exitWithError(Error);
+
+  // Handle MD5 profile, so it is still able to match using the original name.
+  std::string MD5Name = std::to_string(llvm::MD5Hash(FuncNameFilter));
+  std::string NegativeMD5Name =
+      std::to_string(llvm::MD5Hash(FuncNameNegativeFilter));
+
+  for (auto I = ProfileMap.begin(); I != ProfileMap.end();) {
+    auto Tmp = I++;
+    const auto &FuncName = getFuncName(*Tmp);
+    // Negative filter has higher precedence than positive filter.
+    if ((hasNegativeFilter &&
+         (NegativePattern.match(FuncName) ||
+          (FunctionSamples::UseMD5 && NegativeMD5Name == FuncName))) ||
+        (hasFilter && !(Pattern.match(FuncName) ||
+                        (FunctionSamples::UseMD5 && MD5Name == FuncName))))
+      ProfileMap.erase(Tmp);
+  }
+
+  llvm::dbgs() << Count - ProfileMap.size() << " of " << Count << " functions "
+               << "in the original profile are filtered.\n";
+}
+
 static void writeInstrProfile(StringRef OutputFilename,
                               ProfileFormat OutputFormat,
                               InstrProfWriter &Writer) {
@@ -403,26 +843,39 @@
   }
 }
 
-static void
-mergeInstrProfile(const WeightedFileVector &Inputs, StringRef DebugInfoFilename,
-                  SymbolRemapper *Remapper, StringRef OutputFilename,
-                  ProfileFormat OutputFormat, uint64_t TraceReservoirSize,
-                  uint64_t MaxTraceLength, bool OutputSparse,
-                  unsigned NumThreads, FailureMode FailMode,
-                  const StringRef ProfiledBinary) {
+static void mergeInstrProfile(const WeightedFileVector &Inputs,
+                              SymbolRemapper *Remapper,
+                              int MaxDbgCorrelationWarnings,
+                              const StringRef ProfiledBinary) {
+  const uint64_t TraceReservoirSize = TemporalProfTraceReservoirSize.getValue();
+  const uint64_t MaxTraceLength = TemporalProfMaxTraceLength.getValue();
   if (OutputFormat == PF_Compact_Binary)
     exitWithError("Compact Binary is deprecated");
   if (OutputFormat != PF_Binary && OutputFormat != PF_Ext_Binary &&
       OutputFormat != PF_Text)
     exitWithError("unknown format is specified");
 
-  std::unique_ptr<InstrProfCorrelator> Correlator;
+  // TODO: Maybe we should support correlation with mixture of different
+  // correlation modes(w/wo debug-info/object correlation).
+  if (!DebugInfoFilename.empty() && !BinaryFilename.empty())
+    exitWithError("Expected only one of -debug-info, -binary-file");
+  std::string CorrelateFilename;
+  ProfCorrelatorKind CorrelateKind = ProfCorrelatorKind::NONE;
   if (!DebugInfoFilename.empty()) {
-    if (auto Err =
-            InstrProfCorrelator::get(DebugInfoFilename).moveInto(Correlator))
-      exitWithError(std::move(Err), DebugInfoFilename);
-    if (auto Err = Correlator->correlateProfileData())
-      exitWithError(std::move(Err), DebugInfoFilename);
+    CorrelateFilename = DebugInfoFilename;
+    CorrelateKind = ProfCorrelatorKind::DEBUG_INFO;
+  } else if (!BinaryFilename.empty()) {
+    CorrelateFilename = BinaryFilename;
+    CorrelateKind = ProfCorrelatorKind::BINARY;
+  }
+
+  std::unique_ptr<InstrProfCorrelator> Correlator;
+  if (CorrelateKind != InstrProfCorrelator::NONE) {
+    if (auto Err = InstrProfCorrelator::get(CorrelateFilename, CorrelateKind)
+                       .moveInto(Correlator))
+      exitWithError(std::move(Err), CorrelateFilename);
+    if (auto Err = Correlator->correlateProfileData(MaxDbgCorrelationWarnings))
+      exitWithError(std::move(Err), CorrelateFilename);
   }
 
   std::mutex ErrorLock;
@@ -484,10 +937,12 @@
       warn(toString(std::move(ErrorPair.first)), ErrorPair.second);
     }
   }
-  if (NumErrors == Inputs.size() ||
+  if ((NumErrors == Inputs.size() && FailMode == failIfAllAreInvalid) ||
       (NumErrors > 0 && FailMode == failIfAnyAreInvalid))
     exitWithError("no profile can be merged");
 
+  filterFunctions(Contexts[0]->Writer.getProfileData());
+
   writeInstrProfile(OutputFilename, OutputFormat, Contexts[0]->Writer);
 }
 
@@ -594,7 +1049,7 @@
 
   auto checkSampleProfileHasFUnique = [&Reader]() {
     for (const auto &PD : Reader->getProfiles()) {
-      auto &FContext = PD.first;
+      auto &FContext = PD.second.getContext();
       if (FContext.toString().find(FunctionSamples::UniqSuffix) !=
           std::string::npos) {
         return true;
@@ -607,13 +1062,14 @@
 
   auto buildStaticFuncMap = [&StaticFuncMap,
                              SampleProfileHasFUnique](const StringRef Name) {
-    std::string Prefixes[] = {".cpp:", "cc:", ".c:", ".hpp:", ".h:"};
+    std::string FilePrefixes[] = {".cpp", "cc", ".c", ".hpp", ".h"};
     size_t PrefixPos = StringRef::npos;
-    for (auto &Prefix : Prefixes) {
-      PrefixPos = Name.find_insensitive(Prefix);
+    for (auto &FilePrefix : FilePrefixes) {
+      std::string NamePrefix = FilePrefix + kGlobalIdentifierDelimiter;
+      PrefixPos = Name.find_insensitive(NamePrefix);
       if (PrefixPos == StringRef::npos)
         continue;
-      PrefixPos += Prefix.size();
+      PrefixPos += NamePrefix.size();
       break;
     }
 
@@ -634,12 +1090,12 @@
     // If sample profile and instrumented profile do not agree on symbol
     // uniqification.
     if (SampleProfileHasFUnique != ProfileHasFUnique) {
-      // If instrumented profile uses -funique-internal-linakge-symbols,
+      // If instrumented profile uses -funique-internal-linkage-symbols,
       // we need to trim the name.
       if (ProfileHasFUnique) {
         NewName = NewName.substr(0, PostfixPos);
       } else {
-        // If sample profile uses -funique-internal-linakge-symbols,
+        // If sample profile uses -funique-internal-linkage-symbols,
         // we build the map.
         std::string NStr =
             NewName.str() + getUniqueInternalLinkagePostfix(FName);
@@ -697,26 +1153,27 @@
   //
   // InstrProfile has two entries:
   //  foo
-  //  bar.cc:bar
+  //  bar.cc;bar
   //
   // After BuildMaxSampleMap, we should have the following in FlattenSampleMap:
   // {"foo", {1000, 5000}}
-  // {"bar.cc:bar", {11000, 30000}}
+  // {"bar.cc;bar", {11000, 30000}}
   //
   // foo's has an entry count of 1000, and max body count of 5000.
-  // bar.cc:bar has an entry count of 11000 (sum two callsites of 1000 and
+  // bar.cc;bar has an entry count of 11000 (sum two callsites of 1000 and
   // 10000), and max count of 30000 (from the callsite in line 8).
   //
-  // Note that goo's count will remain in bar.cc:bar() as it does not have an
+  // Note that goo's count will remain in bar.cc;bar() as it does not have an
   // entry in InstrProfile.
-  DenseMap<StringRef, std::pair<uint64_t, uint64_t>> FlattenSampleMap;
+  llvm::StringMap<std::pair<uint64_t, uint64_t>> FlattenSampleMap;
   auto BuildMaxSampleMap = [&FlattenSampleMap, &StaticFuncMap,
                             &InstrProfileMap](const FunctionSamples &FS,
                                               const StringRef &RootName) {
     auto BuildMaxSampleMapImpl = [&](const FunctionSamples &FS,
                                      const StringRef &RootName,
                                      auto &BuildImpl) -> void {
-      const StringRef &Name = FS.getName();
+      std::string NameStr = FS.getFunction().str();
+      const StringRef Name = NameStr;
       const StringRef *NewRootName = &RootName;
       uint64_t EntrySample = FS.getHeadSamplesEstimate();
       uint64_t MaxBodySample = FS.getMaxCountInside(/* SkipCallSite*/ true);
@@ -770,7 +1227,8 @@
 
   for (auto &PD : Reader->getProfiles()) {
     sampleprof::FunctionSamples &FS = PD.second;
-    BuildMaxSampleMap(FS, FS.getName());
+    std::string Name = FS.getFunction().str();
+    BuildMaxSampleMap(FS, Name);
   }
 
   ProfileSummary InstrPS = *IPBuilder.getSummary();
@@ -806,7 +1264,7 @@
     uint64_t SampleMaxCount = std::max(E.second.first, E.second.second);
     if (SampleMaxCount < ColdSampleThreshold)
       continue;
-    const StringRef &Name = E.first;
+    StringRef Name = E.first();
     auto It = InstrProfileMap.find(Name);
     if (It == InstrProfileMap.end()) {
       auto NewName = StaticFuncMap.find(Name);
@@ -840,11 +1298,11 @@
 /// should be dropped. \p InstrProfColdThreshold is the user specified
 /// cold threshold which will override the cold threshold got from the
 /// instr profile summary.
-static void supplementInstrProfile(
-    const WeightedFileVector &Inputs, StringRef SampleFilename,
-    StringRef OutputFilename, ProfileFormat OutputFormat, bool OutputSparse,
-    unsigned SupplMinSizeThreshold, float ZeroCounterThreshold,
-    unsigned InstrProfColdThreshold) {
+static void supplementInstrProfile(const WeightedFileVector &Inputs,
+                                   StringRef SampleFilename, bool OutputSparse,
+                                   unsigned SupplMinSizeThreshold,
+                                   float ZeroCounterThreshold,
+                                   unsigned InstrProfColdThreshold) {
   if (OutputFilename.compare("-") == 0)
     exitWithError("cannot write indexed profdata format to stdout");
   if (Inputs.size() != 1)
@@ -885,7 +1343,7 @@
 remapSamples(const sampleprof::FunctionSamples &Samples,
              SymbolRemapper &Remapper, sampleprof_error &Error) {
   sampleprof::FunctionSamples Result;
-  Result.setName(Remapper(Samples.getName()));
+  Result.setFunction(Remapper(Samples.getFunction()));
   Result.addTotalSamples(Samples.getTotalSamples());
   Result.addHeadSamples(Samples.getHeadSamples());
   for (const auto &BodySample : Samples.getBodySamples()) {
@@ -896,7 +1354,7 @@
     for (const auto &Target : BodySample.second.getCallTargets()) {
       Result.addCalledTargetSamples(BodySample.first.LineOffset,
                                     MaskedDiscriminator,
-                                    Remapper(Target.first()), Target.second);
+                                    Remapper(Target.first), Target.second);
     }
   }
   for (const auto &CallsiteSamples : Samples.getCallsiteSamples()) {
@@ -905,8 +1363,7 @@
     for (const auto &Callsite : CallsiteSamples.second) {
       sampleprof::FunctionSamples Remapped =
           remapSamples(Callsite.second, Remapper, Error);
-      MergeResult(Error,
-                  Target[std::string(Remapped.getName())].merge(Remapped));
+      MergeResult(Error, Target[Remapped.getFunction()].merge(Remapped));
     }
   }
   return Result;
@@ -978,15 +1435,10 @@
   }
 }
 
-static void
-mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper,
-                   StringRef OutputFilename, ProfileFormat OutputFormat,
-                   StringRef ProfileSymbolListFile, bool CompressAllSections,
-                   bool UseMD5, bool GenPartialProfile,
-                   SampleProfileLayout ProfileLayout,
-                   bool SampleMergeColdContext, bool SampleTrimColdContext,
-                   bool SampleColdContextFrameDepth, FailureMode FailMode,
-                   bool DropProfileSymbolList, size_t OutputSizeLimit) {
+static void mergeSampleProfile(const WeightedFileVector &Inputs,
+                               SymbolRemapper *Remapper,
+                               StringRef ProfileSymbolListFile,
+                               size_t OutputSizeLimit) {
   using namespace sampleprof;
   SampleProfileMap ProfileMap;
   SmallVector<std::unique_ptr<sampleprof::SampleProfileReader>, 5> Readers;
@@ -1072,6 +1524,8 @@
     ProfileIsCS = FunctionSamples::ProfileIsCS = false;
   }
 
+  filterFunctions(ProfileMap);
+
   auto WriterOrErr =
       SampleProfileWriter::create(OutputFilename, FormatMap[OutputFormat]);
   if (std::error_code EC = WriterOrErr.getError())
@@ -1146,7 +1600,7 @@
   for (const StringRef &FileWeightEntry : Entries) {
     StringRef SanitizedEntry = FileWeightEntry.trim(" \t\v\f\r");
     // Skip comments.
-    if (SanitizedEntry.startswith("#"))
+    if (SanitizedEntry.starts_with("#"))
       continue;
     // If there's no comma, it's an unweighted profile.
     else if (!SanitizedEntry.contains(','))
@@ -1157,140 +1611,6 @@
 }
 
 static int merge_main(int argc, const char *argv[]) {
-  cl::list<std::string> InputFilenames(cl::Positional,
-                                       cl::desc("<filename...>"));
-  cl::list<std::string> WeightedInputFilenames("weighted-input",
-                                               cl::desc("<weight>,<filename>"));
-  cl::opt<std::string> InputFilenamesFile(
-      "input-files", cl::init(""),
-      cl::desc("Path to file containing newline-separated "
-               "[<weight>,]<filename> entries"));
-  cl::alias InputFilenamesFileA("f", cl::desc("Alias for --input-files"),
-                                cl::aliasopt(InputFilenamesFile));
-  cl::opt<bool> DumpInputFileList(
-      "dump-input-file-list", cl::init(false), cl::Hidden,
-      cl::desc("Dump the list of input files and their weights, then exit"));
-  cl::opt<std::string> RemappingFile("remapping-file", cl::value_desc("file"),
-                                     cl::desc("Symbol remapping file"));
-  cl::alias RemappingFileA("r", cl::desc("Alias for --remapping-file"),
-                           cl::aliasopt(RemappingFile));
-  cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
-                                      cl::init("-"), cl::desc("Output file"));
-  cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
-                            cl::aliasopt(OutputFilename));
-  cl::opt<ProfileKinds> ProfileKind(
-      cl::desc("Profile kind:"), cl::init(instr),
-      cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
-                 clEnumVal(sample, "Sample profile")));
-  cl::opt<ProfileFormat> OutputFormat(
-      cl::desc("Format of output profile"), cl::init(PF_Ext_Binary),
-      cl::values(
-          clEnumValN(PF_Binary, "binary", "Binary encoding"),
-          clEnumValN(PF_Ext_Binary, "extbinary", "Extensible binary encoding "
-                     "(default)"),
-          clEnumValN(PF_Text, "text", "Text encoding"),
-          clEnumValN(PF_GCC, "gcc",
-                     "GCC encoding (only meaningful for -sample)")));
-  cl::opt<FailureMode> FailureMode(
-      "failure-mode", cl::init(failIfAnyAreInvalid), cl::desc("Failure mode:"),
-      cl::values(clEnumValN(failIfAnyAreInvalid, "any",
-                            "Fail if any profile is invalid."),
-                 clEnumValN(failIfAllAreInvalid, "all",
-                            "Fail only if all profiles are invalid.")));
-  cl::opt<bool> OutputSparse("sparse", cl::init(false),
-      cl::desc("Generate a sparse profile (only meaningful for -instr)"));
-  cl::opt<unsigned> NumThreads(
-      "num-threads", cl::init(0),
-      cl::desc("Number of merge threads to use (default: autodetect)"));
-  cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
-                        cl::aliasopt(NumThreads));
-  cl::opt<std::string> ProfileSymbolListFile(
-      "prof-sym-list", cl::init(""),
-      cl::desc("Path to file containing the list of function symbols "
-               "used to populate profile symbol list"));
-  cl::opt<bool> CompressAllSections(
-      "compress-all-sections", cl::init(false), cl::Hidden,
-      cl::desc("Compress all sections when writing the profile (only "
-               "meaningful for -extbinary)"));
-  cl::opt<bool> UseMD5(
-      "use-md5", cl::init(false), cl::Hidden,
-      cl::desc("Choose to use MD5 to represent string in name table (only "
-               "meaningful for -extbinary)"));
-  cl::opt<bool> SampleMergeColdContext(
-      "sample-merge-cold-context", cl::init(false), cl::Hidden,
-      cl::desc(
-          "Merge context sample profiles whose count is below cold threshold"));
-  cl::opt<bool> SampleTrimColdContext(
-      "sample-trim-cold-context", cl::init(false), cl::Hidden,
-      cl::desc(
-          "Trim context sample profiles whose count is below cold threshold"));
-  cl::opt<uint32_t> SampleColdContextFrameDepth(
-      "sample-frame-depth-for-cold-context", cl::init(1),
-      cl::desc("Keep the last K frames while merging cold profile. 1 means the "
-               "context-less base profile"));
-  cl::opt<size_t> OutputSizeLimit(
-      "output-size-limit", cl::init(0), cl::Hidden,
-      cl::desc("Trim cold functions until profile size is below specified "
-               "limit in bytes. This uses a heursitic and functions may be "
-               "excessively trimmed"));
-  cl::opt<bool> GenPartialProfile(
-      "gen-partial-profile", cl::init(false), cl::Hidden,
-      cl::desc("Generate a partial profile (only meaningful for -extbinary)"));
-  cl::opt<std::string> SupplInstrWithSample(
-      "supplement-instr-with-sample", cl::init(""), cl::Hidden,
-      cl::desc("Supplement an instr profile with sample profile, to correct "
-               "the profile unrepresentativeness issue. The sample "
-               "profile is the input of the flag. Output will be in instr "
-               "format (The flag only works with -instr)"));
-  cl::opt<float> ZeroCounterThreshold(
-      "zero-counter-threshold", cl::init(0.7), cl::Hidden,
-      cl::desc("For the function which is cold in instr profile but hot in "
-               "sample profile, if the ratio of the number of zero counters "
-               "divided by the total number of counters is above the "
-               "threshold, the profile of the function will be regarded as "
-               "being harmful for performance and will be dropped."));
-  cl::opt<unsigned> SupplMinSizeThreshold(
-      "suppl-min-size-threshold", cl::init(10), cl::Hidden,
-      cl::desc("If the size of a function is smaller than the threshold, "
-               "assume it can be inlined by PGO early inliner and it won't "
-               "be adjusted based on sample profile."));
-  cl::opt<unsigned> InstrProfColdThreshold(
-      "instr-prof-cold-threshold", cl::init(0), cl::Hidden,
-      cl::desc("User specified cold threshold for instr profile which will "
-               "override the cold threshold got from profile summary. "));
-  cl::opt<SampleProfileLayout> ProfileLayout(
-      "convert-sample-profile-layout",
-      cl::desc("Convert the generated profile to a profile with a new layout"),
-      cl::init(SPL_None),
-      cl::values(
-          clEnumValN(SPL_Nest, "nest",
-                     "Nested profile, the input should be CS flat profile"),
-          clEnumValN(SPL_Flat, "flat",
-                     "Profile with nested inlinee flatten out")));
-  cl::opt<std::string> DebugInfoFilename(
-      "debug-info", cl::init(""),
-      cl::desc("Use the provided debug info to correlate the raw profile."));
-  cl::opt<std::string> ProfiledBinary(
-      "profiled-binary", cl::init(""),
-      cl::desc("Path to binary from which the profile was collected."));
-  cl::opt<bool> DropProfileSymbolList(
-      "drop-profile-symbol-list", cl::init(false), cl::Hidden,
-      cl::desc("Drop the profile symbol list when merging AutoFDO profiles "
-               "(only meaningful for -sample)"));
-  // WARNING: This reservoir size value is propagated to any input indexed
-  // profiles for simplicity. Changing this value between invocations could
-  // result in sample bias.
-  cl::opt<uint64_t> TemporalProfTraceReservoirSize(
-      "temporal-profile-trace-reservoir-size", cl::init(100),
-      cl::desc("The maximum number of stored temporal profile traces (default: "
-               "100)"));
-  cl::opt<uint64_t> TemporalProfMaxTraceLength(
-      "temporal-profile-max-trace-length", cl::init(10000),
-      cl::desc("The maximum length of a single temporal profile trace "
-               "(default: 10000)"));
-
-  cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
-
   WeightedFileVector WeightedInputs;
   for (StringRef Filename : InputFilenames)
     addWeightedInput(WeightedInputs, {std::string(Filename), 1});
@@ -1304,7 +1624,7 @@
 
   if (WeightedInputs.empty())
     exitWithError("no input files specified. See " +
-                  sys::path::filename(argv[0]) + " -help");
+                  sys::path::filename(argv[0]) + " " + argv[1] + " -help");
 
   if (DumpInputFileList) {
     for (auto &WF : WeightedInputs)
@@ -1321,25 +1641,18 @@
       exitWithError(
           "-supplement-instr-with-sample can only work with -instr. ");
 
-    supplementInstrProfile(WeightedInputs, SupplInstrWithSample, OutputFilename,
-                           OutputFormat, OutputSparse, SupplMinSizeThreshold,
-                           ZeroCounterThreshold, InstrProfColdThreshold);
+    supplementInstrProfile(WeightedInputs, SupplInstrWithSample, OutputSparse,
+                           SupplMinSizeThreshold, ZeroCounterThreshold,
+                           InstrProfColdThreshold);
     return 0;
   }
 
   if (ProfileKind == instr)
-    mergeInstrProfile(WeightedInputs, DebugInfoFilename, Remapper.get(),
-                      OutputFilename, OutputFormat,
-                      TemporalProfTraceReservoirSize,
-                      TemporalProfMaxTraceLength, OutputSparse, NumThreads,
-                      FailureMode, ProfiledBinary);
+    mergeInstrProfile(WeightedInputs, Remapper.get(), MaxDbgCorrelationWarnings,
+                      ProfiledBinary);
   else
-    mergeSampleProfile(WeightedInputs, Remapper.get(), OutputFilename,
-                       OutputFormat, ProfileSymbolListFile, CompressAllSections,
-                       UseMD5, GenPartialProfile, ProfileLayout,
-                       SampleMergeColdContext, SampleTrimColdContext,
-                       SampleColdContextFrameDepth, FailureMode,
-                       DropProfileSymbolList, OutputSizeLimit);
+    mergeSampleProfile(WeightedInputs, Remapper.get(), ProfileSymbolListFile,
+                       OutputSizeLimit);
   return 0;
 }
 
@@ -1375,44 +1688,40 @@
   SampleContext BaseName;
   SampleContext TestName;
   // Number of overlap units
-  uint64_t OverlapCount;
+  uint64_t OverlapCount = 0;
   // Total samples of overlap units
-  uint64_t OverlapSample;
+  uint64_t OverlapSample = 0;
   // Number of and total samples of units that only present in base or test
   // profile
-  uint64_t BaseUniqueCount;
-  uint64_t BaseUniqueSample;
-  uint64_t TestUniqueCount;
-  uint64_t TestUniqueSample;
+  uint64_t BaseUniqueCount = 0;
+  uint64_t BaseUniqueSample = 0;
+  uint64_t TestUniqueCount = 0;
+  uint64_t TestUniqueSample = 0;
   // Number of units and total samples in base or test profile
-  uint64_t BaseCount;
-  uint64_t BaseSample;
-  uint64_t TestCount;
-  uint64_t TestSample;
+  uint64_t BaseCount = 0;
+  uint64_t BaseSample = 0;
+  uint64_t TestCount = 0;
+  uint64_t TestSample = 0;
   // Number of and total samples of units that present in at least one profile
-  uint64_t UnionCount;
-  uint64_t UnionSample;
+  uint64_t UnionCount = 0;
+  uint64_t UnionSample = 0;
   // Weighted similarity
-  double Similarity;
+  double Similarity = 0.0;
   // For SampleOverlapStats instances representing functions, weights of the
   // function in base and test profiles
-  double BaseWeight;
-  double TestWeight;
+  double BaseWeight = 0.0;
+  double TestWeight = 0.0;
 
-  SampleOverlapStats()
-      : OverlapCount(0), OverlapSample(0), BaseUniqueCount(0),
-        BaseUniqueSample(0), TestUniqueCount(0), TestUniqueSample(0),
-        BaseCount(0), BaseSample(0), TestCount(0), TestSample(0), UnionCount(0),
-        UnionSample(0), Similarity(0.0), BaseWeight(0.0), TestWeight(0.0) {}
+  SampleOverlapStats() = default;
 };
 } // end anonymous namespace
 
 namespace {
 struct FuncSampleStats {
-  uint64_t SampleSum;
-  uint64_t MaxSample;
-  uint64_t HotBlockCount;
-  FuncSampleStats() : SampleSum(0), MaxSample(0), HotBlockCount(0) {}
+  uint64_t SampleSum = 0;
+  uint64_t MaxSample = 0;
+  uint64_t HotBlockCount = 0;
+  FuncSampleStats() = default;
   FuncSampleStats(uint64_t SampleSum, uint64_t MaxSample,
                   uint64_t HotBlockCount)
       : SampleSum(SampleSum), MaxSample(MaxSample),
@@ -2302,49 +2611,18 @@
 }
 
 static int overlap_main(int argc, const char *argv[]) {
-  cl::opt<std::string> BaseFilename(cl::Positional, cl::Required,
-                                    cl::desc("<base profile file>"));
-  cl::opt<std::string> TestFilename(cl::Positional, cl::Required,
-                                    cl::desc("<test profile file>"));
-  cl::opt<std::string> Output("output", cl::value_desc("output"), cl::init("-"),
-                              cl::desc("Output file"));
-  cl::alias OutputA("o", cl::desc("Alias for --output"), cl::aliasopt(Output));
-  cl::opt<bool> IsCS(
-      "cs", cl::init(false),
-      cl::desc("For context sensitive PGO counts. Does not work with CSSPGO."));
-  cl::opt<unsigned long long> ValueCutoff(
-      "value-cutoff", cl::init(-1),
-      cl::desc(
-          "Function level overlap information for every function (with calling "
-          "context for csspgo) in test "
-          "profile with max count value greater then the parameter value"));
-  cl::opt<std::string> FuncNameFilter(
-      "function",
-      cl::desc("Function level overlap information for matching functions. For "
-               "CSSPGO this takes a a function name with calling context"));
-  cl::opt<unsigned long long> SimilarityCutoff(
-      "similarity-cutoff", cl::init(0),
-      cl::desc("For sample profiles, list function names (with calling context "
-               "for csspgo) for overlapped functions "
-               "with similarities below the cutoff (percentage times 10000)."));
-  cl::opt<ProfileKinds> ProfileKind(
-      cl::desc("Profile kind:"), cl::init(instr),
-      cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
-                 clEnumVal(sample, "Sample profile")));
-  cl::ParseCommandLineOptions(argc, argv, "LLVM profile data overlap tool\n");
-
   std::error_code EC;
-  raw_fd_ostream OS(Output.data(), EC, sys::fs::OF_TextWithCRLF);
+  raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);
   if (EC)
-    exitWithErrorCode(EC, Output);
+    exitWithErrorCode(EC, OutputFilename);
 
   if (ProfileKind == instr)
     overlapInstrProfile(BaseFilename, TestFilename,
-                        OverlapFuncFilters{ValueCutoff, FuncNameFilter}, OS,
-                        IsCS);
+                        OverlapFuncFilters{OverlapValueCutoff, FuncNameFilter},
+                        OS, IsCS);
   else
     overlapSampleProfile(BaseFilename, TestFilename,
-                         OverlapFuncFilters{ValueCutoff, FuncNameFilter},
+                         OverlapFuncFilters{OverlapValueCutoff, FuncNameFilter},
                          SimilarityCutoff, OS);
 
   return 0;
@@ -2352,12 +2630,10 @@
 
 namespace {
 struct ValueSitesStats {
-  ValueSitesStats()
-      : TotalNumValueSites(0), TotalNumValueSitesWithValueProfile(0),
-        TotalNumValues(0) {}
-  uint64_t TotalNumValueSites;
-  uint64_t TotalNumValueSitesWithValueProfile;
-  uint64_t TotalNumValues;
+  ValueSitesStats() = default;
+  uint64_t TotalNumValueSites = 0;
+  uint64_t TotalNumValueSitesWithValueProfile = 0;
+  uint64_t TotalNumValues = 0;
   std::vector<unsigned> ValueSitesHistogram;
 };
 } // namespace
@@ -2389,7 +2665,7 @@
       if (Symtab == nullptr)
         OS << format("%4" PRIu64, VD[V].Value);
       else
-        OS << Symtab->getFuncName(VD[V].Value);
+        OS << Symtab->getFuncOrVarName(VD[V].Value);
       OS << ", " << format("%10" PRId64, VD[V].Count) << " ] ("
          << format("%.2f%%", (VD[V].Count * 100.0 / SiteSum)) << ")\n";
     }
@@ -2410,14 +2686,7 @@
   }
 }
 
-static int showInstrProfile(
-    const std::string &Filename, bool ShowCounts, uint32_t TopN,
-    bool ShowIndirectCallTargets, bool ShowMemOPSizes, bool ShowDetailedSummary,
-    std::vector<uint32_t> DetailedSummaryCutoffs, bool ShowAllFunctions,
-    bool ShowCS, uint64_t ValueCutoff, bool OnlyListBelow,
-    const std::string &ShowFunction, bool TextFormat, bool ShowBinaryIds,
-    bool ShowCovered, bool ShowProfileVersion, bool ShowTemporalProfTraces,
-    ShowFormat SFormat, raw_fd_ostream &OS) {
+static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Json)
     exitWithError("JSON output is not supported for instr profiles");
   if (SFormat == ShowFormat::Yaml)
@@ -2451,7 +2720,7 @@
 
   if (!TextFormat && OnlyListBelow) {
     OS << "The list of functions with the maximum counter less than "
-       << ValueCutoff << ":\n";
+       << ShowValueCutoff << ":\n";
   }
 
   // Add marker so that IR-level instrumentation round-trips properly.
@@ -2465,7 +2734,7 @@
         continue;
     }
     bool Show = ShowAllFunctions ||
-                (!ShowFunction.empty() && Func.Name.contains(ShowFunction));
+                (!FuncNameFilter.empty() && Func.Name.contains(FuncNameFilter));
 
     bool doTextFormatDump = (Show && TextFormat);
 
@@ -2512,7 +2781,7 @@
       FuncSum += Func.Counts[I];
     }
 
-    if (FuncMax < ValueCutoff) {
+    if (FuncMax < ShowValueCutoff) {
       ++BelowCutoffFunctions;
       if (OnlyListBelow) {
         OS << "  " << Func.Name << ": (Max = " << FuncMax
@@ -2522,8 +2791,8 @@
     } else if (OnlyListBelow)
       continue;
 
-    if (TopN) {
-      if (HottestFuncs.size() == TopN) {
+    if (TopNFunctions) {
+      if (HottestFuncs.size() == TopNFunctions) {
         if (HottestFuncs.top().second < FuncMax) {
           HottestFuncs.pop();
           HottestFuncs.emplace(std::make_pair(std::string(Func.Name), FuncMax));
@@ -2587,25 +2856,25 @@
   if (IsIR)
     OS << "  entry_first = " << Reader->instrEntryBBEnabled();
   OS << "\n";
-  if (ShowAllFunctions || !ShowFunction.empty())
+  if (ShowAllFunctions || !FuncNameFilter.empty())
     OS << "Functions shown: " << ShownFunctions << "\n";
   OS << "Total functions: " << PS->getNumFunctions() << "\n";
-  if (ValueCutoff > 0) {
-    OS << "Number of functions with maximum count (< " << ValueCutoff
+  if (ShowValueCutoff > 0) {
+    OS << "Number of functions with maximum count (< " << ShowValueCutoff
        << "): " << BelowCutoffFunctions << "\n";
-    OS << "Number of functions with maximum count (>= " << ValueCutoff
+    OS << "Number of functions with maximum count (>= " << ShowValueCutoff
        << "): " << PS->getNumFunctions() - BelowCutoffFunctions << "\n";
   }
   OS << "Maximum function count: " << PS->getMaxFunctionCount() << "\n";
   OS << "Maximum internal block count: " << PS->getMaxInternalCount() << "\n";
 
-  if (TopN) {
+  if (TopNFunctions) {
     std::vector<std::pair<std::string, uint64_t>> SortedHottestFuncs;
     while (!HottestFuncs.empty()) {
       SortedHottestFuncs.emplace_back(HottestFuncs.top());
       HottestFuncs.pop();
     }
-    OS << "Top " << TopN
+    OS << "Top " << TopNFunctions
        << " functions with the largest internal block counts: \n";
     for (auto &hotfunc : llvm::reverse(SortedHottestFuncs))
       OS << "  " << hotfunc.first << ", max count = " << hotfunc.second << "\n";
@@ -2643,7 +2912,7 @@
       OS << "  Temporal Profile Trace " << i << " (weight=" << Traces[i].Weight
          << " count=" << Traces[i].FunctionNameRefs.size() << "):\n";
       for (auto &NameRef : Traces[i].FunctionNameRefs)
-        OS << "    " << Reader->getSymtab().getFuncName(NameRef) << "\n";
+        OS << "    " << Reader->getSymtab().getFuncOrVarName(NameRef) << "\n";
     }
   }
 
@@ -2663,13 +2932,12 @@
 namespace {
 struct HotFuncInfo {
   std::string FuncName;
-  uint64_t TotalCount;
-  double TotalCountPercent;
-  uint64_t MaxCount;
-  uint64_t EntryCount;
+  uint64_t TotalCount = 0;
+  double TotalCountPercent = 0.0f;
+  uint64_t MaxCount = 0;
+  uint64_t EntryCount = 0;
 
-  HotFuncInfo()
-      : TotalCount(0), TotalCountPercent(0.0f), MaxCount(0), EntryCount(0) {}
+  HotFuncInfo() = default;
 
   HotFuncInfo(StringRef FN, uint64_t TS, double TSP, uint64_t MS, uint64_t ES)
       : FuncName(FN.begin(), FN.end()), TotalCount(TS), TotalCountPercent(TSP),
@@ -2795,13 +3063,7 @@
   return 0;
 }
 
-static int showSampleProfile(const std::string &Filename, bool ShowCounts,
-                             uint32_t TopN, bool ShowAllFunctions,
-                             bool ShowDetailedSummary,
-                             const std::string &ShowFunction,
-                             bool ShowProfileSymbolList,
-                             bool ShowSectionInfoOnly, bool ShowHotFuncList,
-                             ShowFormat SFormat, raw_fd_ostream &OS) {
+static int showSampleProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Yaml)
     exitWithError("YAML output is not supported for sample profiles");
   using namespace sampleprof;
@@ -2821,7 +3083,7 @@
   if (std::error_code EC = Reader->read())
     exitWithErrorCode(EC, Filename);
 
-  if (ShowAllFunctions || ShowFunction.empty()) {
+  if (ShowAllFunctions || FuncNameFilter.empty()) {
     if (SFormat == ShowFormat::Json)
       Reader->dumpJson(OS);
     else
@@ -2833,7 +3095,8 @@
           "be printed");
 
     // TODO: parse context string to support filtering by contexts.
-    Reader->dumpFunctionProfile(StringRef(ShowFunction), OS);
+    FunctionSamples *FS = Reader->getSamplesFor(StringRef(FuncNameFilter));
+    Reader->dumpFunctionProfile(FS ? *FS : FunctionSamples(), OS);
   }
 
   if (ShowProfileSymbolList) {
@@ -2848,15 +3111,14 @@
     PS.printDetailedSummary(OS);
   }
 
-  if (ShowHotFuncList || TopN)
-    showHotFunctionList(Reader->getProfiles(), Reader->getSummary(), TopN, OS);
+  if (ShowHotFuncList || TopNFunctions)
+    showHotFunctionList(Reader->getProfiles(), Reader->getSummary(),
+                        TopNFunctions, OS);
 
   return 0;
 }
 
-static int showMemProfProfile(const std::string &Filename,
-                              const std::string &ProfiledBinary,
-                              ShowFormat SFormat, raw_fd_ostream &OS) {
+static int showMemProfProfile(ShowFormat SFormat, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Json)
     exitWithError("JSON output is not supported for MemProf");
   auto ReaderOr = llvm::memprof::RawMemProfReader::create(
@@ -2875,21 +3137,21 @@
 }
 
 static int showDebugInfoCorrelation(const std::string &Filename,
-                                    bool ShowDetailedSummary,
-                                    bool ShowProfileSymbolList,
                                     ShowFormat SFormat, raw_fd_ostream &OS) {
   if (SFormat == ShowFormat::Json)
     exitWithError("JSON output is not supported for debug info correlation");
   std::unique_ptr<InstrProfCorrelator> Correlator;
-  if (auto Err = InstrProfCorrelator::get(Filename).moveInto(Correlator))
+  if (auto Err =
+          InstrProfCorrelator::get(Filename, InstrProfCorrelator::DEBUG_INFO)
+              .moveInto(Correlator))
     exitWithError(std::move(Err), Filename);
   if (SFormat == ShowFormat::Yaml) {
-    if (auto Err = Correlator->dumpYaml(OS))
+    if (auto Err = Correlator->dumpYaml(MaxDbgCorrelationWarnings, OS))
       exitWithError(std::move(Err), Filename);
     return 0;
   }
 
-  if (auto Err = Correlator->correlateProfileData())
+  if (auto Err = Correlator->correlateProfileData(MaxDbgCorrelationWarnings))
     exitWithError(std::move(Err), Filename);
 
   InstrProfSymtab Symtab;
@@ -2910,102 +3172,13 @@
 }
 
 static int show_main(int argc, const char *argv[]) {
-  cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"));
-
-  cl::opt<bool> ShowCounts("counts", cl::init(false),
-                           cl::desc("Show counter values for shown functions"));
-  cl::opt<ShowFormat> SFormat(
-      "show-format", cl::init(ShowFormat::Text),
-      cl::desc("Emit output in the selected format if supported"),
-      cl::values(clEnumValN(ShowFormat::Text, "text",
-                            "emit normal text output (default)"),
-                 clEnumValN(ShowFormat::Json, "json", "emit JSON"),
-                 clEnumValN(ShowFormat::Yaml, "yaml", "emit YAML")));
-  // TODO: Consider replacing this with `--show-format=text-encoding`.
-  cl::opt<bool> TextFormat(
-      "text", cl::init(false),
-      cl::desc("Show instr profile data in text dump format"));
-  cl::opt<bool> JsonFormat(
-      "json", cl::desc("Show sample profile data in the JSON format "
-                       "(deprecated, please use --show-format=json)"));
-  cl::opt<bool> ShowIndirectCallTargets(
-      "ic-targets", cl::init(false),
-      cl::desc("Show indirect call site target values for shown functions"));
-  cl::opt<bool> ShowMemOPSizes(
-      "memop-sizes", cl::init(false),
-      cl::desc("Show the profiled sizes of the memory intrinsic calls "
-               "for shown functions"));
-  cl::opt<bool> ShowDetailedSummary("detailed-summary", cl::init(false),
-                                    cl::desc("Show detailed profile summary"));
-  cl::list<uint32_t> DetailedSummaryCutoffs(
-      cl::CommaSeparated, "detailed-summary-cutoffs",
-      cl::desc(
-          "Cutoff percentages (times 10000) for generating detailed summary"),
-      cl::value_desc("800000,901000,999999"));
-  cl::opt<bool> ShowHotFuncList(
-      "hot-func-list", cl::init(false),
-      cl::desc("Show profile summary of a list of hot functions"));
-  cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
-                                 cl::desc("Details for every function"));
-  cl::opt<bool> ShowCS("showcs", cl::init(false),
-                       cl::desc("Show context sensitive counts"));
-  cl::opt<std::string> ShowFunction("function",
-                                    cl::desc("Details for matching functions"));
-
-  cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
-                                      cl::init("-"), cl::desc("Output file"));
-  cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
-                            cl::aliasopt(OutputFilename));
-  cl::opt<ProfileKinds> ProfileKind(
-      cl::desc("Profile kind:"), cl::init(instr),
-      cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
-                 clEnumVal(sample, "Sample profile"),
-                 clEnumVal(memory, "MemProf memory access profile")));
-  cl::opt<uint32_t> TopNFunctions(
-      "topn", cl::init(0),
-      cl::desc("Show the list of functions with the largest internal counts"));
-  cl::opt<uint32_t> ValueCutoff(
-      "value-cutoff", cl::init(0),
-      cl::desc("Set the count value cutoff. Functions with the maximum count "
-               "less than this value will not be printed out. (Default is 0)"));
-  cl::opt<bool> OnlyListBelow(
-      "list-below-cutoff", cl::init(false),
-      cl::desc("Only output names of functions whose max count values are "
-               "below the cutoff value"));
-  cl::opt<bool> ShowProfileSymbolList(
-      "show-prof-sym-list", cl::init(false),
-      cl::desc("Show profile symbol list if it exists in the profile. "));
-  cl::opt<bool> ShowSectionInfoOnly(
-      "show-sec-info-only", cl::init(false),
-      cl::desc("Show the information of each section in the sample profile. "
-               "The flag is only usable when the sample profile is in "
-               "extbinary format"));
-  cl::opt<bool> ShowBinaryIds("binary-ids", cl::init(false),
-                              cl::desc("Show binary ids in the profile. "));
-  cl::opt<bool> ShowTemporalProfTraces(
-      "temporal-profile-traces",
-      cl::desc("Show temporal profile traces in the profile."));
-  cl::opt<std::string> DebugInfoFilename(
-      "debug-info", cl::init(""),
-      cl::desc("Read and extract profile metadata from debug info and show "
-               "the functions it found."));
-  cl::opt<bool> ShowCovered(
-      "covered", cl::init(false),
-      cl::desc("Show only the functions that have been executed."));
-  cl::opt<std::string> ProfiledBinary(
-      "profiled-binary", cl::init(""),
-      cl::desc("Path to binary from which the profile was collected."));
-  cl::opt<bool> ShowProfileVersion("profile-version", cl::init(false),
-                                   cl::desc("Show profile version. "));
-  cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n");
-
   if (Filename.empty() && DebugInfoFilename.empty())
     exitWithError(
         "the positional argument '<profdata-file>' is required unless '--" +
         DebugInfoFilename.ArgStr + "' is provided");
 
   if (Filename == OutputFilename) {
-    errs() << sys::path::filename(argv[0])
+    errs() << sys::path::filename(argv[0]) << " " << argv[1]
            << ": Input file name cannot be the same as the output file name!\n";
     return 1;
   }
@@ -3017,36 +3190,20 @@
   if (EC)
     exitWithErrorCode(EC, OutputFilename);
 
-  if (ShowAllFunctions && !ShowFunction.empty())
+  if (ShowAllFunctions && !FuncNameFilter.empty())
     WithColor::warning() << "-function argument ignored: showing all functions\n";
 
   if (!DebugInfoFilename.empty())
-    return showDebugInfoCorrelation(DebugInfoFilename, ShowDetailedSummary,
-                                    ShowProfileSymbolList, SFormat, OS);
+    return showDebugInfoCorrelation(DebugInfoFilename, SFormat, OS);
 
-  if (ProfileKind == instr)
-    return showInstrProfile(
-        Filename, ShowCounts, TopNFunctions, ShowIndirectCallTargets,
-        ShowMemOPSizes, ShowDetailedSummary, DetailedSummaryCutoffs,
-        ShowAllFunctions, ShowCS, ValueCutoff, OnlyListBelow, ShowFunction,
-        TextFormat, ShowBinaryIds, ShowCovered, ShowProfileVersion,
-        ShowTemporalProfTraces, SFormat, OS);
-  if (ProfileKind == sample)
-    return showSampleProfile(Filename, ShowCounts, TopNFunctions,
-                             ShowAllFunctions, ShowDetailedSummary,
-                             ShowFunction, ShowProfileSymbolList,
-                             ShowSectionInfoOnly, ShowHotFuncList, SFormat, OS);
-  return showMemProfProfile(Filename, ProfiledBinary, SFormat, OS);
+  if (ShowProfileKind == instr)
+    return showInstrProfile(SFormat, OS);
+  if (ShowProfileKind == sample)
+    return showSampleProfile(SFormat, OS);
+  return showMemProfProfile(SFormat, OS);
 }
 
 static int order_main(int argc, const char *argv[]) {
-  cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"));
-  cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
-                                      cl::init("-"), cl::desc("Output file"));
-  cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
-                            cl::aliasopt(OutputFilename));
-  cl::ParseCommandLineOptions(argc, argv, "LLVM profile data order\n");
-
   std::error_code EC;
   raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);
   if (EC)
@@ -3067,83 +3224,48 @@
   BalancedPartitioning BP(Config);
   BP.run(Nodes);
 
-  WithColor::note() << "# Ordered " << Nodes.size() << " functions\n";
+  OS << "# Ordered " << Nodes.size() << " functions\n";
+  OS << "# Warning: Mach-O may prefix symbols with \"_\" depending on the "
+        "linkage and this output does not take that into account. Some "
+        "post-processing may be required before passing to the linker via "
+        "-order_file.\n";
   for (auto &N : Nodes) {
-    auto FuncName = Reader->getSymtab().getFuncName(N.Id);
-    if (FuncName.contains(':')) {
-      // GlobalValue::getGlobalIdentifier() prefixes the filename if the symbol
-      // is local. This logic will break if there is a colon in the filename,
-      // but we cannot use rsplit() because ObjC symbols can have colons.
-      auto [Filename, ParsedFuncName] = FuncName.split(':');
-      // Emit a comment describing where this symbol came from
+    auto [Filename, ParsedFuncName] =
+        getParsedIRPGOFuncName(Reader->getSymtab().getFuncOrVarName(N.Id));
+    if (!Filename.empty())
       OS << "# " << Filename << "\n";
-      FuncName = ParsedFuncName;
-    }
-    OS << FuncName << "\n";
+    OS << ParsedFuncName << "\n";
   }
   return 0;
 }
 
-typedef int (*llvm_profdata_subcommand)(int, const char *[]);
-
-static std::tuple<StringRef, llvm_profdata_subcommand>
-    llvm_profdata_subcommands[] = {
-        {"merge", merge_main},
-        {"show", show_main},
-        {"order", order_main},
-        {"overlap", overlap_main},
-};
-
 int llvm_profdata_main(int argc, char **argvNonConst,
                        const llvm::ToolContext &) {
   const char **argv = const_cast<const char **>(argvNonConst);
-  InitLLVM X(argc, argv);
 
   StringRef ProgName(sys::path::filename(argv[0]));
-  if (argc > 1) {
 
-    llvm_profdata_subcommand func = nullptr;
-    for (auto [subcmd_name, subcmd_action] : llvm_profdata_subcommands)
-      if (subcmd_name == argv[1])
-        func = subcmd_action;
-
-    if (func) {
-      std::string Invocation(ProgName.str() + " " + argv[1]);
-      argv[1] = Invocation.c_str();
-      return func(argc - 1, argv + 1);
-    }
-
-    if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "-help") == 0 ||
-        strcmp(argv[1], "--help") == 0) {
-
-      errs() << "OVERVIEW: LLVM profile data tools\n\n"
-             << "USAGE: " << ProgName << " <command> [args...]\n"
-             << "USAGE: " << ProgName << " <command> -help\n\n"
-             << "See each individual command --help for more details.\n"
-             << "Available commands: "
-             << join(map_range(llvm_profdata_subcommands,
-                               [](auto const &KV) { return std::get<0>(KV); }),
-                     ", ")
-             << "\n";
-      return 0;
-    }
-
-    if (strcmp(argv[1], "--version") == 0) {
-      outs() << ProgName << '\n';
-      cl::PrintVersionMessage();
-      return 0;
-    }
+  if (argc < 2) {
+    errs() << ProgName
+           << ": No subcommand specified! Run llvm-profata --help for usage.\n";
+    return 1;
   }
 
-  if (argc < 2)
-    errs() << ProgName << ": No command specified!\n";
-  else
-    errs() << ProgName << ": Unknown command!\n";
+  cl::ParseCommandLineOptions(argc, argv, "LLVM profile data\n");
 
-  errs() << "USAGE: " << ProgName << " <"
-         << join(map_range(llvm_profdata_subcommands,
-                           [](auto const &KV) { return std::get<0>(KV); }),
-                 "|")
-         << "> [args...]\n";
+  if (ShowSubcommand)
+    return show_main(argc, argv);
+
+  if (OrderSubcommand)
+    return order_main(argc, argv);
+
+  if (OverlapSubcommand)
+    return overlap_main(argc, argv);
+
+  if (MergeSubcommand)
+    return merge_main(argc, argv);
+
+  errs() << ProgName
+         << ": Unknown command. Run llvm-profdata --help for usage.\n";
   return 1;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.cpp b/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.cpp
index ae0fd6d..87df699 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.cpp
@@ -11,6 +11,7 @@
 #include "llvm/ADT/SCCIterator.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
+#include "llvm/Transforms/IPO/SampleProfile.h"
 #include <cstdint>
 #include <queue>
 
@@ -35,13 +36,6 @@
 // TODO: the actual threshold to be tuned here because the size here is based
 // on machine code not LLVM IR.
 namespace llvm {
-extern cl::opt<int> SampleHotCallSiteThreshold;
-extern cl::opt<int> SampleColdCallSiteThreshold;
-extern cl::opt<int> ProfileInlineGrowthLimit;
-extern cl::opt<int> ProfileInlineLimitMin;
-extern cl::opt<int> ProfileInlineLimitMax;
-extern cl::opt<bool> SortProfiledSCC;
-
 cl::opt<bool> EnableCSPreInliner(
     "csspgo-preinliner", cl::Hidden, cl::init(true),
     cl::desc("Run a global pre-inliner to merge context profile based on "
@@ -80,8 +74,8 @@
     ProfileInlineLimitMax = 50000;
 }
 
-std::vector<StringRef> CSPreInliner::buildTopDownOrder() {
-  std::vector<StringRef> Order;
+std::vector<FunctionId> CSPreInliner::buildTopDownOrder() {
+  std::vector<FunctionId> Order;
   // Trim cold edges to get a more stable call graph. This allows for a more
   // stable top-down order which in turns helps the stablity of the generated
   // profile from run to run.
@@ -134,9 +128,8 @@
     uint64_t CallsiteCount = 0;
     LineLocation Callsite = CalleeNode->getCallSiteLoc();
     if (auto CallTargets = CallerSamples->findCallTargetMapAt(Callsite)) {
-      SampleRecord::CallTargetMap &TargetCounts = CallTargets.get();
-      auto It = TargetCounts.find(CalleeSamples->getName());
-      if (It != TargetCounts.end())
+      auto It = CallTargets->find(CalleeSamples->getFunction());
+      if (It != CallTargets->end())
         CallsiteCount = It->second;
     }
 
@@ -186,7 +179,7 @@
         (NormalizationUpperBound - NormalizationLowerBound);
     if (NormalizedHotness > 1.0)
       NormalizedHotness = 1.0;
-    // Add 1 to to ensure hot callsites get a non-zero threshold, which could
+    // Add 1 to ensure hot callsites get a non-zero threshold, which could
     // happen when SampleColdCallSiteThreshold is 0. This is when we do not
     // want any inlining for cold callsites.
     SampleThreshold = SampleHotCallSiteThreshold * NormalizedHotness * 100 +
@@ -202,7 +195,7 @@
   return (Candidate.SizeCost < SampleThreshold);
 }
 
-void CSPreInliner::processFunction(const StringRef Name) {
+void CSPreInliner::processFunction(const FunctionId Name) {
   FunctionSamples *FSamples = ContextTracker.getBaseSamplesFor(Name);
   if (!FSamples)
     return;
@@ -303,7 +296,7 @@
   // It also helps better compress context profile to control profile
   // size, as we now only need context profile for functions going to
   // be inlined.
-  for (StringRef FuncName : buildTopDownOrder()) {
+  for (FunctionId FuncName : buildTopDownOrder()) {
     processFunction(FuncName);
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.h b/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.h
index 4d848aa..8a3f16a 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/CSPreInliner.h
@@ -57,8 +57,7 @@
     // Tie breaker using GUID so we have stable/deterministic inlining order
     assert(LHS.CalleeSamples && RHS.CalleeSamples &&
            "Expect non-null FunctionSamples");
-    return LHS.CalleeSamples->getGUID(LHS.CalleeSamples->getName()) <
-           RHS.CalleeSamples->getGUID(RHS.CalleeSamples->getName());
+    return LHS.CalleeSamples->getGUID() < RHS.CalleeSamples->getGUID();
   }
 };
 
@@ -81,8 +80,8 @@
 private:
   bool getInlineCandidates(ProfiledCandidateQueue &CQueue,
                            const FunctionSamples *FCallerContextSamples);
-  std::vector<StringRef> buildTopDownOrder();
-  void processFunction(StringRef Name);
+  std::vector<FunctionId> buildTopDownOrder();
+  void processFunction(FunctionId Name);
   bool shouldInline(ProfiledInlineCandidate &Candidate);
   uint32_t getFuncSize(const ContextTrieNode *ContextNode);
   bool UseContextCost;
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/CallContext.h b/src/llvm-project/llvm/tools/llvm-profgen/CallContext.h
index 5e55213..574833b 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/CallContext.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/CallContext.h
@@ -12,13 +12,12 @@
 #include "llvm/ProfileData/SampleProf.h"
 #include <sstream>
 #include <string>
-#include <vector>
 
 namespace llvm {
 namespace sampleprof {
 
 inline std::string getCallSite(const SampleContextFrame &Callsite) {
-  std::string CallsiteStr = Callsite.FuncName.str();
+  std::string CallsiteStr = Callsite.Func.str();
   CallsiteStr += ":";
   CallsiteStr += Twine(Callsite.Location.LineOffset).str();
   if (Callsite.Location.Discriminator > 0) {
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp
index 9f45167..313d404 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp
@@ -597,7 +597,7 @@
   // It's in bottom-up order with each frame in one line.
 
   // Extract stack frames from sample
-  while (!TraceIt.isAtEoF() && !TraceIt.getCurrentLine().startswith(" 0x")) {
+  while (!TraceIt.isAtEoF() && !TraceIt.getCurrentLine().starts_with(" 0x")) {
     StringRef FrameStr = TraceIt.getCurrentLine().ltrim();
     uint64_t FrameAddr = 0;
     if (FrameStr.getAsInteger(16, FrameAddr)) {
@@ -645,7 +645,7 @@
   // Skip other unrelated line, find the next valid LBR line
   // Note that even for empty call stack, we should skip the address at the
   // bottom, otherwise the following pass may generate a truncated callstack
-  while (!TraceIt.isAtEoF() && !TraceIt.getCurrentLine().startswith(" 0x")) {
+  while (!TraceIt.isAtEoF() && !TraceIt.getCurrentLine().starts_with(" 0x")) {
     TraceIt.advance();
   }
   // Filter out broken stack sample. We may not have complete frame info
@@ -690,14 +690,14 @@
   // Parsing call stack and populate into PerfSample.CallStack
   if (!extractCallstack(TraceIt, Sample->CallStack)) {
     // Skip the next LBR line matched current call stack
-    if (!TraceIt.isAtEoF() && TraceIt.getCurrentLine().startswith(" 0x"))
+    if (!TraceIt.isAtEoF() && TraceIt.getCurrentLine().starts_with(" 0x"))
       TraceIt.advance();
     return;
   }
 
   warnIfMissingMMap();
 
-  if (!TraceIt.isAtEoF() && TraceIt.getCurrentLine().startswith(" 0x")) {
+  if (!TraceIt.isAtEoF() && TraceIt.getCurrentLine().starts_with(" 0x")) {
     // Parsing LBR stack and populate into PerfSample.LBRStack
     if (extractLBRStack(TraceIt, Sample->LBRStack)) {
       if (IgnoreStackSamples) {
@@ -846,7 +846,7 @@
         std::make_shared<StringBasedCtxKey>();
     StringRef Line = TraceIt.getCurrentLine();
     // Read context stack for CS profile.
-    if (Line.startswith("[")) {
+    if (Line.starts_with("[")) {
       ProfileIsCS = true;
       auto I = ContextStrSet.insert(Line.str());
       SampleContext::createCtxVectorFromStr(*I.first, Key->Context);
@@ -1005,7 +1005,7 @@
   Line.trim().split(Records, " ", 2, false);
   if (Records.size() < 2)
     return false;
-  if (Records[1].startswith("0x") && Records[1].contains('/'))
+  if (Records[1].starts_with("0x") && Records[1].contains('/'))
     return true;
   return false;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h
index 14137e8..e9f6193 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h
@@ -15,9 +15,7 @@
 #include "llvm/Support/Regex.h"
 #include <cstdint>
 #include <fstream>
-#include <list>
 #include <map>
-#include <vector>
 
 using namespace llvm;
 using namespace sampleprof;
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp
index 97bc8d5..c4028e6 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp
@@ -208,7 +208,7 @@
   }
 
   for (auto *FuncSamples : HotFuncs) {
-    auto *Func = Binary->getBinaryFunction(FuncSamples->getName());
+    auto *Func = Binary->getBinaryFunction(FuncSamples->getFunction());
     if (!Func)
       continue;
     uint64_t FuncSize = Func->getFuncSize();
@@ -449,7 +449,7 @@
 bool ProfileGenerator::collectFunctionsFromLLVMProfile(
     std::unordered_set<const BinaryFunction *> &ProfiledFunctions) {
   for (const auto &FS : ProfileMap) {
-    if (auto *Func = Binary->getBinaryFunction(FS.first.getName()))
+    if (auto *Func = Binary->getBinaryFunction(FS.second.getFunction()))
       ProfiledFunctions.insert(Func);
   }
   return true;
@@ -466,14 +466,9 @@
 }
 
 FunctionSamples &
-ProfileGenerator::getTopLevelFunctionProfile(StringRef FuncName) {
+ProfileGenerator::getTopLevelFunctionProfile(FunctionId FuncName) {
   SampleContext Context(FuncName);
-  auto Ret = ProfileMap.emplace(Context, FunctionSamples());
-  if (Ret.second) {
-    FunctionSamples &FProfile = Ret.first->second;
-    FProfile.setContext(Context);
-  }
-  return Ret.first->second;
+  return ProfileMap.Create(Context);
 }
 
 void ProfileGenerator::generateProfile() {
@@ -505,14 +500,14 @@
     return;
 
   // Move cold profiles into a tmp container.
-  std::vector<SampleContext> ColdProfiles;
+  std::vector<hash_code> ColdProfileHashes;
   for (const auto &I : ProfileMap) {
     if (I.second.getTotalSamples() < ColdCntThreshold)
-      ColdProfiles.emplace_back(I.first);
+      ColdProfileHashes.emplace_back(I.first);
   }
 
   // Remove the cold profile from ProfileMap.
-  for (const auto &I : ColdProfiles)
+  for (const auto &I : ColdProfileHashes)
     ProfileMap.erase(I);
 }
 
@@ -591,7 +586,7 @@
       FunctionProfile.addCalledTargetSamples(
           FrameVec.back().Location.LineOffset,
           FrameVec.back().Location.Discriminator,
-          CalleeName, Count);
+          FunctionId(CalleeName), Count);
     }
   }
 }
@@ -600,11 +595,11 @@
     const SampleContextFrameVector &FrameVec, uint64_t Count) {
   // Get top level profile
   FunctionSamples *FunctionProfile =
-      &getTopLevelFunctionProfile(FrameVec[0].FuncName);
+      &getTopLevelFunctionProfile(FrameVec[0].Func);
   FunctionProfile->addTotalSamples(Count);
   if (Binary->usePseudoProbes()) {
     const auto *FuncDesc = Binary->getFuncDescForGUID(
-        Function::getGUID(FunctionProfile->getName()));
+        FunctionProfile->getFunction().getHashCode());
     FunctionProfile->setFunctionHash(FuncDesc->FuncHash);
   }
 
@@ -615,16 +610,16 @@
     FunctionSamplesMap &SamplesMap =
         FunctionProfile->functionSamplesAt(Callsite);
     auto Ret =
-        SamplesMap.emplace(FrameVec[I].FuncName.str(), FunctionSamples());
+        SamplesMap.emplace(FrameVec[I].Func, FunctionSamples());
     if (Ret.second) {
-      SampleContext Context(FrameVec[I].FuncName);
+      SampleContext Context(FrameVec[I].Func);
       Ret.first->second.setContext(Context);
     }
     FunctionProfile = &Ret.first->second;
     FunctionProfile->addTotalSamples(Count);
     if (Binary->usePseudoProbes()) {
       const auto *FuncDesc = Binary->getFuncDescForGUID(
-          Function::getGUID(FunctionProfile->getName()));
+          FunctionProfile->getFunction().getHashCode());
       FunctionProfile->setFunctionHash(FuncDesc->FuncHash);
     }
   }
@@ -721,10 +716,11 @@
       FunctionProfile.addCalledTargetSamples(
           FrameVec.back().Location.LineOffset,
           getBaseDiscriminator(FrameVec.back().Location.Discriminator),
-          CalleeName, Count);
+          FunctionId(CalleeName), Count);
     }
     // Add head samples for callee.
-    FunctionSamples &CalleeProfile = getTopLevelFunctionProfile(CalleeName);
+    FunctionSamples &CalleeProfile =
+        getTopLevelFunctionProfile(FunctionId(CalleeName));
     CalleeProfile.addHeadSamples(Count);
   }
 }
@@ -742,7 +738,7 @@
   if (!FProfile) {
     FSamplesList.emplace_back();
     FProfile = &FSamplesList.back();
-    FProfile->setName(ContextNode->getFuncName());
+    FProfile->setFunction(ContextNode->getFuncName());
     ContextNode->setFunctionSamples(FProfile);
   }
   // Update ContextWasInlined attribute for existing contexts.
@@ -904,7 +900,8 @@
       if (LeafLoc) {
         CallerNode->getFunctionSamples()->addCalledTargetSamples(
             LeafLoc->Location.LineOffset,
-            getBaseDiscriminator(LeafLoc->Location.Discriminator), CalleeName,
+            getBaseDiscriminator(LeafLoc->Location.Discriminator),
+            FunctionId(CalleeName),
             Count);
         // Record head sample for called target(callee)
         CalleeCallSite = LeafLoc->Location;
@@ -912,7 +909,8 @@
     }
 
     ContextTrieNode *CalleeNode =
-        CallerNode->getOrCreateChildContext(CalleeCallSite, CalleeName);
+        CallerNode->getOrCreateChildContext(CalleeCallSite,
+                                            FunctionId(CalleeName));
     FunctionSamples *CalleeProfile = getOrCreateFunctionSamples(CalleeNode);
     CalleeProfile->addHeadSamples(Count);
   }
@@ -1018,9 +1016,7 @@
 
   // Merge function samples of CS profile to calculate profile density.
   sampleprof::SampleProfileMap ContextLessProfiles;
-  for (const auto &I : ProfileMap) {
-    ContextLessProfiles[I.second.getName()].merge(I.second);
-  }
+  ProfileConverter::flattenProfile(ProfileMap, ContextLessProfiles, true);
 
   calculateAndShowDensity(ContextLessProfiles);
   if (GenCSNestedProfile) {
@@ -1219,7 +1215,7 @@
       continue;
     FunctionProfile.addCalledTargetSamples(CallProbe->getIndex(),
                                            CallProbe->getDiscriminator(),
-                                           CalleeName, Count);
+                                           FunctionId(CalleeName), Count);
   }
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h
index 471792e..88cf2dc 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h
@@ -157,7 +157,7 @@
   void generateLineNumBasedProfile();
   void generateProbeBasedProfile();
   RangeSample preprocessRangeCounter(const RangeSample &RangeCounter);
-  FunctionSamples &getTopLevelFunctionProfile(StringRef FuncName);
+  FunctionSamples &getTopLevelFunctionProfile(FunctionId FuncName);
   // Helper function to get the leaf frame's FunctionProfile by traversing the
   // inline stack and meanwhile it adds the total samples for each frame's
   // function profile.
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index 4755f75..b40c5f8 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -77,7 +77,7 @@
   ContextTrieNode *CurNode = &RootContext;
   bool IsLeaf = true;
   for (const auto &Callsite : reverse(Context)) {
-    StringRef CallerName = Callsite.FuncName;
+    FunctionId CallerName = Callsite.Func;
     LineLocation CallsiteLoc = IsLeaf ? LineLocation(0, 0) : Callsite.Location;
     CurNode = CurNode->getOrCreateChildContext(CallsiteLoc, CallerName);
     IsLeaf = false;
@@ -145,7 +145,8 @@
       StringRef CallerName = ProbeFrame.first;
       LineLocation CallsiteLoc(ProbeFrame.second, 0);
       SizeContext =
-          SizeContext->getOrCreateChildContext(CallsiteLoc, CallerName);
+          SizeContext->getOrCreateChildContext(CallsiteLoc,
+                                               FunctionId(CallerName));
     }
     // Add 0 size to make known.
     SizeContext->addFunctionSize(0);
@@ -479,12 +480,6 @@
   if (ShowDisassembly)
     outs() << '<' << SymbolName << ">:\n";
 
-  auto WarnInvalidInsts = [](uint64_t Start, uint64_t End) {
-    WithColor::warning() << "Invalid instructions at "
-                         << format("%8" PRIx64, Start) << " - "
-                         << format("%8" PRIx64, End) << "\n";
-  };
-
   uint64_t Address = StartAddress;
   // Size of a consecutive invalid instruction range starting from Address -1
   // backwards.
@@ -577,7 +572,8 @@
       }
 
       if (InvalidInstLength) {
-        WarnInvalidInsts(Address - InvalidInstLength, Address - 1);
+        AddrsWithInvalidInstruction.insert(
+            {Address - InvalidInstLength, Address - 1});
         InvalidInstLength = 0;
       }
     } else {
@@ -588,7 +584,8 @@
   }
 
   if (InvalidInstLength)
-    WarnInvalidInsts(Address - InvalidInstLength, Address - 1);
+    AddrsWithInvalidInstruction.insert(
+        {Address - InvalidInstLength, Address - 1});
 
   if (ShowDisassembly)
     outs() << "\n";
@@ -707,6 +704,19 @@
     }
   }
 
+  if (!AddrsWithInvalidInstruction.empty()) {
+    if (ShowDetailedWarning) {
+      for (auto &Addr : AddrsWithInvalidInstruction) {
+        WithColor::warning()
+            << "Invalid instructions at " << format("%8" PRIx64, Addr.first)
+            << " - " << format("%8" PRIx64, Addr.second) << "\n";
+      }
+    }
+    WithColor::warning() << "Found " << AddrsWithInvalidInstruction.size()
+                         << " invalid instructions\n";
+    AddrsWithInvalidInstruction.clear();
+  }
+
   // Dissassemble rodata section to check if FS discriminator symbol exists.
   checkUseFSDiscriminator(Obj, AllSymbols);
 }
@@ -791,10 +801,12 @@
         FRange.StartAddress = StartAddress;
         FRange.EndAddress = EndAddress;
       } else {
-        WithColor::warning()
-            << "Duplicated symbol start address at "
-            << format("%8" PRIx64, StartAddress) << " "
-            << R.first->second.getFuncName() << " and " << Name << "\n";
+        AddrsWithMultipleSymbols.insert(StartAddress);
+        if (ShowDetailedWarning)
+          WithColor::warning()
+              << "Duplicated symbol start address at "
+              << format("%8" PRIx64, StartAddress) << " "
+              << R.first->second.getFuncName() << " and " << Name << "\n";
       }
     }
   }
@@ -810,27 +822,46 @@
     loadSymbolsFromDWARFUnit(*CompilationUnit.get());
 
   // Handles DWO sections that can either be in .o, .dwo or .dwp files.
+  uint32_t NumOfDWOMissing = 0;
   for (const auto &CompilationUnit : DebugContext->compile_units()) {
     DWARFUnit *const DwarfUnit = CompilationUnit.get();
-    if (std::optional<uint64_t> DWOId = DwarfUnit->getDWOId()) {
+    if (DwarfUnit->getDWOId()) {
       DWARFUnit *DWOCU = DwarfUnit->getNonSkeletonUnitDIE(false).getDwarfUnit();
       if (!DWOCU->isDWOUnit()) {
-        std::string DWOName = dwarf::toString(
-            DwarfUnit->getUnitDIE().find(
-                {dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
-            "");
-        WithColor::warning()
-            << "DWO debug information for " << DWOName
-            << " was not loaded. Please check the .o, .dwo or .dwp path.\n";
+        NumOfDWOMissing++;
+        if (ShowDetailedWarning) {
+          std::string DWOName = dwarf::toString(
+              DwarfUnit->getUnitDIE().find(
+                  {dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}),
+              "");
+          WithColor::warning() << "DWO debug information for " << DWOName
+                               << " was not loaded.\n";
+        }
         continue;
       }
       loadSymbolsFromDWARFUnit(*DWOCU);
     }
   }
 
+  if (NumOfDWOMissing)
+    WithColor::warning()
+        << " DWO debug information was not loaded for " << NumOfDWOMissing
+        << " modules. Please check the .o, .dwo or .dwp path.\n";
   if (BinaryFunctions.empty())
     WithColor::warning() << "Loading of DWARF info completed, but no binary "
                             "functions have been retrieved.\n";
+  // Populate the hash binary function map for MD5 function name lookup. This
+  // is done after BinaryFunctions are finalized.
+  for (auto &BinaryFunction : BinaryFunctions) {
+    HashBinaryFunctions[MD5Hash(StringRef(BinaryFunction.first))] =
+        &BinaryFunction.second;
+  }
+
+  if (!AddrsWithMultipleSymbols.empty()) {
+    WithColor::warning() << "Found " << AddrsWithMultipleSymbols.size()
+                         << " start addresses with multiple symbols\n";
+    AddrsWithMultipleSymbols.clear();
+  }
 }
 
 void ProfiledBinary::populateSymbolListFromDWARF(
@@ -865,7 +896,8 @@
   SampleContextFrameVector CallStack;
   for (int32_t I = InlineStack.getNumberOfFrames() - 1; I >= 0; I--) {
     const auto &CallerFrame = InlineStack.getFrame(I);
-    if (CallerFrame.FunctionName == "<invalid>")
+    if (CallerFrame.FunctionName.empty() ||
+        (CallerFrame.FunctionName == "<invalid>"))
       break;
 
     StringRef FunctionName(CallerFrame.FunctionName);
@@ -882,7 +914,7 @@
 
     LineLocation Line(LineOffset, Discriminator);
     auto It = NameStrings.insert(FunctionName.str());
-    CallStack.emplace_back(*It.first, Line);
+    CallStack.emplace_back(FunctionId(StringRef(*It.first)), Line);
   }
 
   return CallStack;
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h
index a6d78c6..0fd12f5 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h
@@ -33,7 +33,6 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Transforms/IPO/SampleContextTracker.h"
-#include <list>
 #include <map>
 #include <set>
 #include <sstream>
@@ -220,12 +219,20 @@
   // A map of mapping function name to BinaryFunction info.
   std::unordered_map<std::string, BinaryFunction> BinaryFunctions;
 
+  // Lookup BinaryFunctions using the function name's MD5 hash. Needed if the
+  // profile is using MD5.
+  std::unordered_map<uint64_t, BinaryFunction *> HashBinaryFunctions;
+
   // A list of binary functions that have samples.
   std::unordered_set<const BinaryFunction *> ProfiledFunctions;
 
   // GUID to Elf symbol start address map
   DenseMap<uint64_t, uint64_t> SymbolStartAddrs;
 
+  // These maps are for temporary use of warning diagnosis.
+  DenseSet<int64_t> AddrsWithMultipleSymbols;
+  DenseSet<std::pair<uint64_t, uint64_t>> AddrsWithInvalidInstruction;
+
   // Start address to Elf symbol GUID map
   std::unordered_multimap<uint64_t, uint64_t> StartAddrToSymMap;
 
@@ -476,12 +483,18 @@
   void setProfiledFunctions(std::unordered_set<const BinaryFunction *> &Funcs) {
     ProfiledFunctions = Funcs;
   }
-
-  BinaryFunction *getBinaryFunction(StringRef FName) {
-    auto I = BinaryFunctions.find(FName.str());
-    if (I == BinaryFunctions.end())
+  
+  BinaryFunction *getBinaryFunction(FunctionId FName) {
+    if (FName.isStringRef()) {
+      auto I = BinaryFunctions.find(FName.str());
+      if (I == BinaryFunctions.end())
+        return nullptr;
+      return &I->second;
+    }
+    auto I = HashBinaryFunctions.find(FName.getHashCode());
+    if (I == HashBinaryFunctions.end())
       return nullptr;
-    return &I->second;
+    return I->second;
   }
 
   uint32_t getFuncSizeForContext(const ContextTrieNode *ContextNode) {
@@ -519,7 +532,7 @@
 
   void flushSymbolizer() { Symbolizer.reset(); }
 
-  MissingFrameInferrer* getMissingContextInferrer() {
+  MissingFrameInferrer *getMissingContextInferrer() {
     return MissingContextInferrer.get();
   }
 
@@ -556,7 +569,7 @@
         InlineContextStack.clear();
         continue;
       }
-      InlineContextStack.emplace_back(Callsite.first,
+      InlineContextStack.emplace_back(FunctionId(Callsite.first),
                                       LineLocation(Callsite.second, 0));
     }
   }
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.cpp b/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.cpp
index 62eed50..9738fd4 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.cpp
@@ -471,6 +471,10 @@
   return writeResource(Res, &ResourceFileWriter::writeMenuBody);
 }
 
+Error ResourceFileWriter::visitMenuExResource(const RCResource *Res) {
+  return writeResource(Res, &ResourceFileWriter::writeMenuExBody);
+}
+
 Error ResourceFileWriter::visitStringTableResource(const RCResource *Base) {
   const auto *Res = cast<StringTableResource>(Base);
 
@@ -887,7 +891,7 @@
   if (!File)
     return File.takeError();
 
-  BinaryStreamReader Reader((*File)->getBuffer(), support::little);
+  BinaryStreamReader Reader((*File)->getBuffer(), llvm::endianness::little);
 
   // Read the file headers.
   //   - At the beginning, ICONDIR/NEWHEADER header.
@@ -1176,6 +1180,7 @@
 
 Error ResourceFileWriter::writeMenuDefinition(
     const std::unique_ptr<MenuDefinition> &Def, uint16_t Flags) {
+  // https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-menuitemtemplate
   assert(Def);
   const MenuDefinition *DefPtr = Def.get();
 
@@ -1202,6 +1207,34 @@
   return writeMenuDefinitionList(PopupPtr->SubItems);
 }
 
+Error ResourceFileWriter::writeMenuExDefinition(
+    const std::unique_ptr<MenuDefinition> &Def, uint16_t Flags) {
+  // https://learn.microsoft.com/en-us/windows/win32/menurc/menuex-template-item
+  assert(Def);
+  const MenuDefinition *DefPtr = Def.get();
+
+  padStream(sizeof(uint32_t));
+  if (auto *MenuItemPtr = dyn_cast<MenuExItem>(DefPtr)) {
+    writeInt<uint32_t>(MenuItemPtr->Type);
+    writeInt<uint32_t>(MenuItemPtr->State);
+    writeInt<uint32_t>(MenuItemPtr->Id);
+    writeInt<uint16_t>(Flags);
+    padStream(sizeof(uint16_t));
+    RETURN_IF_ERROR(writeCString(MenuItemPtr->Name));
+    return Error::success();
+  }
+
+  auto *PopupPtr = cast<PopupExItem>(DefPtr);
+  writeInt<uint32_t>(PopupPtr->Type);
+  writeInt<uint32_t>(PopupPtr->State);
+  writeInt<uint32_t>(PopupPtr->Id);
+  writeInt<uint16_t>(Flags);
+  padStream(sizeof(uint16_t));
+  RETURN_IF_ERROR(writeCString(PopupPtr->Name));
+  writeInt<uint32_t>(PopupPtr->HelpId);
+  return writeMenuExDefinitionList(PopupPtr->SubItems);
+}
+
 Error ResourceFileWriter::writeMenuDefinitionList(
     const MenuDefinitionList &List) {
   for (auto &Def : List.Definitions) {
@@ -1216,6 +1249,20 @@
   return Error::success();
 }
 
+Error ResourceFileWriter::writeMenuExDefinitionList(
+    const MenuDefinitionList &List) {
+  for (auto &Def : List.Definitions) {
+    uint16_t Flags = Def->getResFlags();
+    // Last element receives an additional 0x80 flag.
+    const uint16_t LastElementFlag = 0x0080;
+    if (&Def == &List.Definitions.back())
+      Flags |= LastElementFlag;
+
+    RETURN_IF_ERROR(writeMenuExDefinition(Def, Flags));
+  }
+  return Error::success();
+}
+
 Error ResourceFileWriter::writeMenuBody(const RCResource *Base) {
   // At first, MENUHEADER structure. In fact, these are two WORDs equal to 0.
   // Ref: msdn.microsoft.com/en-us/library/windows/desktop/ms648018.aspx
@@ -1224,6 +1271,17 @@
   return writeMenuDefinitionList(cast<MenuResource>(Base)->Elements);
 }
 
+Error ResourceFileWriter::writeMenuExBody(const RCResource *Base) {
+  // At first, MENUEX_TEMPLATE_HEADER structure.
+  // Ref:
+  // https://learn.microsoft.com/en-us/windows/win32/menurc/menuex-template-header
+  writeInt<uint16_t>(1);
+  writeInt<uint16_t>(4);
+  writeInt<uint32_t>(0);
+
+  return writeMenuExDefinitionList(cast<MenuExResource>(Base)->Elements);
+}
+
 // --- StringTableResource helpers. --- //
 
 class BundleResource : public RCResource {
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h b/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h
index 7a92f84..9413a0e 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h
@@ -55,6 +55,7 @@
   Error visitHTMLResource(const RCResource *) override;
   Error visitIconResource(const RCResource *) override;
   Error visitMenuResource(const RCResource *) override;
+  Error visitMenuExResource(const RCResource *) override;
   Error visitVersionInfoResource(const RCResource *) override;
   Error visitStringTableResource(const RCResource *) override;
   Error visitUserDefinedResource(const RCResource *) override;
@@ -150,8 +151,12 @@
   // MenuResource
   Error writeMenuDefinition(const std::unique_ptr<MenuDefinition> &,
                             uint16_t Flags);
+  Error writeMenuExDefinition(const std::unique_ptr<MenuDefinition> &,
+                              uint16_t Flags);
   Error writeMenuDefinitionList(const MenuDefinitionList &List);
+  Error writeMenuExDefinitionList(const MenuDefinitionList &List);
   Error writeMenuBody(const RCResource *);
+  Error writeMenuExBody(const RCResource *);
 
   // StringTableResource
   Error visitStringTableBundle(const RCResource *);
@@ -178,8 +183,8 @@
   uint64_t writeObject(const ArrayRef<uint8_t> Data);
 
   template <typename T> uint64_t writeInt(const T &Value) {
-    support::detail::packed_endian_specific_integral<T, support::little,
-                                                     support::unaligned>
+    support::detail::packed_endian_specific_integral<
+        T, llvm::endianness::little, support::unaligned>
         Object(Value);
     return writeObject(Object);
   }
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptCppFilter.cpp b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptCppFilter.cpp
index 6657aa5..3081dbb 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptCppFilter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptCppFilter.cpp
@@ -67,7 +67,7 @@
   // false since the preprocessing directives should be filtered out.
 
   Line.consume_front("line");
-  if (!Line.startswith(" "))
+  if (!Line.starts_with(" "))
     return false; // Not a line directive (pragma etc).
 
   // #line 123 "path/file.h"
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp
index 0037fec..4f02fa5 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp
@@ -80,6 +80,8 @@
     Result = parseIconResource();
   else if (TypeToken->equalsLower("MENU"))
     Result = parseMenuResource();
+  else if (TypeToken->equalsLower("MENUEX"))
+    Result = parseMenuExResource();
   else if (TypeToken->equalsLower("RCDATA"))
     Result = parseUserDefinedResource(RkRcData);
   else if (TypeToken->equalsLower("VERSIONINFO"))
@@ -236,7 +238,24 @@
 Expected<StringRef> RCParser::readFilename() {
   if (!isNextTokenKind(Kind::String) && !isNextTokenKind(Kind::Identifier))
     return getExpectedError("string");
-  return read().value();
+  const RCToken &Token = read();
+  StringRef Str = Token.value();
+  if (Token.kind() != Kind::String)
+    return Str;
+  while (isNextTokenKind(Kind::String)) {
+    const RCToken &NextToken = read();
+    StringRef Next = NextToken.value();
+    bool IsWide = Str.consume_front_insensitive("L");
+    Next.consume_front_insensitive("L");
+    bool StrUnquoted = Str.consume_front("\"") && Str.consume_back("\"");
+    bool NextUnquoted = Next.consume_front("\"") && Next.consume_back("\"");
+    assert(StrUnquoted && NextUnquoted);
+    (void)StrUnquoted;
+    (void)NextUnquoted;
+
+    Str = Saver.save(Twine(IsWide ? "L" : "") + "\"" + Str + Next + "\"");
+  }
+  return Str;
 }
 
 Expected<StringRef> RCParser::readIdentifier() {
@@ -497,9 +516,10 @@
   // Check if this is a file resource.
   switch (look().kind()) {
   case Kind::String:
-  case Kind::Identifier:
-    return std::make_unique<UserDefinedResource>(Type, read().value(),
-                                                  MemoryFlags);
+  case Kind::Identifier: {
+    ASSIGN_OR_RETURN(Filename, readFilename());
+    return std::make_unique<UserDefinedResource>(Type, *Filename, MemoryFlags);
+  }
   default:
     break;
   }
@@ -518,7 +538,7 @@
   }
 
   return std::make_unique<UserDefinedResource>(Type, std::move(Data),
-                                                MemoryFlags);
+                                               MemoryFlags);
 }
 
 RCParser::ParseType RCParser::parseVersionInfoResource() {
@@ -557,7 +577,8 @@
   IntOrString Class;
   std::optional<IntWithNotMask> Style;
   if (ClassUpper == "CONTROL") {
-    // CONTROL text, id, class, style, x, y, width, height [, exstyle] [, helpID]
+    // CONTROL text, id, class, style, x, y, width, height [, exstyle] [,
+    // helpID]
     ASSIGN_OR_RETURN(ClassStr, readString());
     RETURN_IF_ERROR(consumeType(Kind::Comma));
     Class = *ClassStr;
@@ -589,8 +610,8 @@
     HelpID = *Val;
   }
 
-  return Control(*ClassResult, Caption, *ID, (*Args)[0], (*Args)[1],
-                 (*Args)[2], (*Args)[3], Style, ExStyle, HelpID, Class);
+  return Control(*ClassResult, Caption, *ID, (*Args)[0], (*Args)[1], (*Args)[2],
+                 (*Args)[3], Style, ExStyle, HelpID, Class);
 }
 
 RCParser::ParseType RCParser::parseBitmapResource() {
@@ -620,7 +641,14 @@
   ASSIGN_OR_RETURN(OptStatements, parseOptionalStatements());
   ASSIGN_OR_RETURN(Items, parseMenuItemsList());
   return std::make_unique<MenuResource>(std::move(*OptStatements),
-                                         std::move(*Items), MemoryFlags);
+                                        std::move(*Items), MemoryFlags);
+}
+
+RCParser::ParseType RCParser::parseMenuExResource() {
+  uint16_t MemoryFlags =
+      parseMemoryFlags(MenuExResource::getDefaultMemoryFlags());
+  ASSIGN_OR_RETURN(Items, parseMenuExItemsList());
+  return std::make_unique<MenuExResource>(std::move(*Items), MemoryFlags);
 }
 
 Expected<MenuDefinitionList> RCParser::parseMenuItemsList() {
@@ -682,6 +710,95 @@
   return std::move(List);
 }
 
+Expected<MenuDefinitionList> RCParser::parseMenuExItemsList() {
+  RETURN_IF_ERROR(consumeType(Kind::BlockBegin));
+
+  MenuDefinitionList List;
+
+  // Read a set of items. Each item is of one of two kinds:
+  //   MENUITEM caption:String [,[id][, [type][, state]]]]
+  //   POPUP caption:String [,[id][, [type][, [state][, helpID]]]] { popupBody }
+  while (!consumeOptionalType(Kind::BlockEnd)) {
+    ASSIGN_OR_RETURN(ItemTypeResult, readIdentifier());
+
+    bool IsMenuItem = ItemTypeResult->equals_insensitive("MENUITEM");
+    bool IsPopup = ItemTypeResult->equals_insensitive("POPUP");
+    if (!IsMenuItem && !IsPopup)
+      return getExpectedError("MENUITEM, POPUP, END or '}'", true);
+
+    // Not a separator. Read the caption.
+    ASSIGN_OR_RETURN(CaptionResult, readString());
+
+    // If MENUITEM, expect [,[id][, [type][, state]]]]
+    if (IsMenuItem) {
+      uint32_t MenuId = 0;
+      uint32_t MenuType = 0;
+      uint32_t MenuState = 0;
+
+      if (consumeOptionalType(Kind::Comma)) {
+        auto IntId = readInt();
+        if (IntId) {
+          MenuId = *IntId;
+        }
+        if (consumeOptionalType(Kind::Comma)) {
+          auto IntType = readInt();
+          if (IntType) {
+            MenuType = *IntType;
+          }
+          if (consumeOptionalType(Kind::Comma)) {
+            auto IntState = readInt();
+            if (IntState) {
+              MenuState = *IntState;
+            }
+          }
+        }
+      }
+      List.addDefinition(std::make_unique<MenuExItem>(*CaptionResult, MenuId,
+                                                      MenuType, MenuState));
+      continue;
+    }
+
+    assert(IsPopup);
+
+    uint32_t PopupId = 0;
+    uint32_t PopupType = 0;
+    uint32_t PopupState = 0;
+    uint32_t PopupHelpID = 0;
+
+    if (consumeOptionalType(Kind::Comma)) {
+      auto IntId = readInt();
+      if (IntId) {
+        PopupId = *IntId;
+      }
+      if (consumeOptionalType(Kind::Comma)) {
+        auto IntType = readInt();
+        if (IntType) {
+          PopupType = *IntType;
+        }
+        if (consumeOptionalType(Kind::Comma)) {
+          auto IntState = readInt();
+          if (IntState) {
+            PopupState = *IntState;
+          }
+          if (consumeOptionalType(Kind::Comma)) {
+            auto IntHelpID = readInt();
+            if (IntHelpID) {
+              PopupHelpID = *IntHelpID;
+            }
+          }
+        }
+      }
+    }
+    // If POPUP, read submenu items recursively.
+    ASSIGN_OR_RETURN(SubMenuResult, parseMenuExItemsList());
+    List.addDefinition(std::make_unique<PopupExItem>(
+        *CaptionResult, PopupId, PopupType, PopupState, PopupHelpID,
+        std::move(*SubMenuResult)));
+  }
+
+  return std::move(List);
+}
+
 RCParser::ParseType RCParser::parseStringTableResource() {
   uint16_t MemoryFlags =
       parseMemoryFlags(StringTableResource::getDefaultMemoryFlags());
@@ -689,7 +806,7 @@
   RETURN_IF_ERROR(consumeType(Kind::BlockBegin));
 
   auto Table = std::make_unique<StringTableResource>(std::move(*OptStatements),
-                                                      MemoryFlags);
+                                                     MemoryFlags);
 
   // Read strings until we reach the end of the block.
   while (!consumeOptionalType(Kind::BlockEnd)) {
@@ -753,7 +870,7 @@
       PrecedingCommas.push_back(HadComma);
     }
     return std::make_unique<VersionInfoValue>(*KeyResult, std::move(Values),
-                                               std::move(PrecedingCommas));
+                                              std::move(PrecedingCommas));
   }
 
   return getExpectedError("BLOCK or VALUE", true);
@@ -835,7 +952,7 @@
     }
   }
   return std::make_unique<FontStmt>(*SizeResult, *NameResult, FontWeight,
-                                     FontItalic, FontCharset);
+                                    FontItalic, FontCharset);
 }
 
 RCParser::ParseOptionType RCParser::parseStyleStmt() {
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.h b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.h
index a7d3b59..603afd8 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.h
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.h
@@ -18,6 +18,7 @@
 #include "ResourceScriptToken.h"
 
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/StringSaver.h"
 #include "llvm/Support/raw_ostream.h"
 
 #include <system_error>
@@ -143,6 +144,7 @@
   ParseType parseIconResource();
   ParseType parseHTMLResource();
   ParseType parseMenuResource();
+  ParseType parseMenuExResource();
   ParseType parseStringTableResource();
   ParseType parseUserDefinedResource(IntOrString Type);
   ParseType parseVersionInfoResource();
@@ -153,6 +155,9 @@
   // Helper MENU parser.
   Expected<MenuDefinitionList> parseMenuItemsList();
 
+  // Helper MENUEX parser.
+  Expected<MenuDefinitionList> parseMenuExItemsList();
+
   // Helper VERSIONINFO parser - read the contents of a single BLOCK statement,
   // from BEGIN to END.
   Expected<std::unique_ptr<VersionInfoBlock>>
@@ -181,6 +186,9 @@
   std::vector<RCToken> Tokens;
   LocIter CurLoc;
   const LocIter End;
+
+  BumpPtrAllocator Alloc;
+  StringSaver Saver{Alloc};
 };
 
 } // namespace rc
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.cpp b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
index ef8c345..62df799 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.cpp
@@ -102,6 +102,12 @@
   return OS << "  Menu separator\n";
 }
 
+raw_ostream &MenuExItem::log(raw_ostream &OS) const {
+  OS << "  MenuExItem (" << Name << "), ID = " << Id;
+  OS << ", type: " << Type << ", state: " << State;
+  return OS << "\n";
+}
+
 raw_ostream &PopupItem::log(raw_ostream &OS) const {
   OS << "  Popup (" << Name << ")";
   logFlags(OS, Flags);
@@ -109,12 +115,25 @@
   return SubItems.log(OS);
 }
 
+raw_ostream &PopupExItem::log(raw_ostream &OS) const {
+  OS << "  Popup (" << Name << ")";
+  OS << ", type: " << Type << ", state: " << State << ", help ID: " << HelpId;
+  OS << ":\n";
+  return SubItems.log(OS);
+}
+
 raw_ostream &MenuResource::log(raw_ostream &OS) const {
   OS << "Menu (" << ResName << "):\n";
   OptStatements->log(OS);
   return Elements.log(OS);
 }
 
+raw_ostream &MenuExResource::log(raw_ostream &OS) const {
+  OS << "MenuEx (" << ResName << "):\n";
+  OptStatements->log(OS);
+  return Elements.log(OS);
+}
+
 raw_ostream &StringTableResource::log(raw_ostream &OS) const {
   OS << "StringTable:\n";
   OptStatements->log(OS);
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h
index 71f6a9d..70e7cec 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h
@@ -17,7 +17,7 @@
 #include "ResourceVisitor.h"
 
 #include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/StringSet.h"
+#include "llvm/ADT/StringMap.h"
 
 namespace llvm {
 namespace rc {
@@ -536,6 +536,23 @@
   }
 };
 
+class MenuExItem : public MenuDefinition {
+public:
+  StringRef Name;
+  uint32_t Id;
+  uint32_t Type;
+  uint32_t State;
+
+  MenuExItem(StringRef Caption, uint32_t ItemId, uint32_t Type, uint32_t State)
+      : Name(Caption), Id(ItemId), Type(Type), State(State) {}
+  raw_ostream &log(raw_ostream &) const override;
+
+  MenuDefKind getKind() const override { return MkMenuItem; }
+  static bool classof(const MenuDefinition *D) {
+    return D->getKind() == MkMenuItem;
+  }
+};
+
 // POPUP statement definition.
 //
 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381030(v=vs.85).aspx
@@ -550,8 +567,7 @@
       : Name(Caption), Flags(ItemFlags), SubItems(std::move(SubItemsList)) {}
   raw_ostream &log(raw_ostream &) const override;
 
-  // This has an additional (0x10) flag. It doesn't match with documented
-  // 0x01 flag, though.
+  // This has an additional MF_POPUP (0x10) flag.
   uint16_t getResFlags() const override { return Flags | 0x10; }
   MenuDefKind getKind() const override { return MkPopup; }
   static bool classof(const MenuDefinition *D) {
@@ -559,6 +575,28 @@
   }
 };
 
+class PopupExItem : public MenuDefinition {
+public:
+  StringRef Name;
+  uint32_t Id;
+  uint32_t Type;
+  uint32_t State;
+  uint32_t HelpId;
+  MenuDefinitionList SubItems;
+
+  PopupExItem(StringRef Caption, uint32_t Id, uint32_t Type, uint32_t State,
+              uint32_t HelpId, MenuDefinitionList &&SubItemsList)
+      : Name(Caption), Id(Id), Type(Type), State(State), HelpId(HelpId),
+        SubItems(std::move(SubItemsList)) {}
+  raw_ostream &log(raw_ostream &) const override;
+
+  uint16_t getResFlags() const override { return 0x01; }
+  MenuDefKind getKind() const override { return MkPopup; }
+  static bool classof(const MenuDefinition *D) {
+    return D->getKind() == MkPopup;
+  }
+};
+
 // Menu resource definition.
 class MenuResource : public OptStatementsRCResource {
 public:
@@ -579,6 +617,25 @@
   }
 };
 
+class MenuExResource : public OptStatementsRCResource {
+public:
+  MenuDefinitionList Elements;
+
+  MenuExResource(MenuDefinitionList &&Items, uint16_t Flags)
+      : OptStatementsRCResource({}, Flags), Elements(std::move(Items)) {}
+  raw_ostream &log(raw_ostream &) const override;
+
+  IntOrString getResourceType() const override { return RkMenu; }
+  Twine getResourceTypeName() const override { return "MENUEX"; }
+  Error visit(Visitor *V) const override {
+    return V->visitMenuExResource(this);
+  }
+  ResourceKind getKind() const override { return RkMenu; }
+  static bool classof(const RCResource *Res) {
+    return Res->getKind() == RkMenu;
+  }
+};
+
 // STRINGTABLE resource. Contains a list of strings, each having its unique ID.
 //
 // Ref: msdn.microsoft.com/en-us/library/windows/desktop/aa381050(v=vs.85).aspx
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.cpp b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.cpp
index a8f40ab..aad1060 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.cpp
@@ -274,7 +274,7 @@
 }
 
 bool Tokenizer::willNowRead(StringRef FollowingChars) const {
-  return Data.drop_front(Pos).startswith(FollowingChars);
+  return Data.drop_front(Pos).starts_with(FollowingChars);
 }
 
 bool Tokenizer::canStartIdentifier() const {
@@ -298,12 +298,12 @@
 
 bool Tokenizer::canStartBlockComment() const {
   assert(!streamEof());
-  return Data.drop_front(Pos).startswith("/*");
+  return Data.drop_front(Pos).starts_with("/*");
 }
 
 bool Tokenizer::canStartLineComment() const {
   assert(!streamEof());
-  return Data.drop_front(Pos).startswith("//");
+  return Data.drop_front(Pos).starts_with("//");
 }
 
 bool Tokenizer::canContinueInt() const {
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.h b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.h
index cc8ca48..29f7502 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.h
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptToken.h
@@ -29,7 +29,6 @@
 
 #include <cstdint>
 #include <map>
-#include <string>
 #include <vector>
 
 namespace llvm {
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceVisitor.h b/src/llvm-project/llvm/tools/llvm-rc/ResourceVisitor.h
index 843c8d8..a950cd7 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceVisitor.h
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceVisitor.h
@@ -39,6 +39,7 @@
   virtual Error visitHTMLResource(const RCResource *) = 0;
   virtual Error visitIconResource(const RCResource *) = 0;
   virtual Error visitMenuResource(const RCResource *) = 0;
+  virtual Error visitMenuExResource(const RCResource *) = 0;
   virtual Error visitStringTableResource(const RCResource *) = 0;
   virtual Error visitUserDefinedResource(const RCResource *) = 0;
   virtual Error visitVersionInfoResource(const RCResource *) = 0;
diff --git a/src/llvm-project/llvm/tools/llvm-rc/llvm-rc.cpp b/src/llvm-project/llvm/tools/llvm-rc/llvm-rc.cpp
index 0caa811..1c3379a 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/llvm-rc.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/llvm-rc.cpp
@@ -21,11 +21,11 @@
 #include "llvm/Object/WindowsResource.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
@@ -43,6 +43,7 @@
 
 using namespace llvm;
 using namespace llvm::rc;
+using namespace llvm::opt;
 
 namespace {
 
@@ -50,9 +51,7 @@
 
 enum ID {
   OPT_INVALID = 0, // This is not a correct option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -66,13 +65,7 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -85,9 +78,7 @@
 
 enum Windres_ID {
   WINDRES_INVALID = 0, // This is not a correct option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  WINDRES_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID_WITH_ID_PREFIX(WINDRES_, __VA_ARGS__),
 #include "WindresOpts.inc"
 #undef OPTION
 };
@@ -101,12 +92,8 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {PREFIX,          NAME,         HELPTEXT,                                    \
-   METAVAR,         WINDRES_##ID, opt::Option::KIND##Class,                    \
-   PARAM,           FLAGS,        WINDRES_##GROUP,                             \
-   WINDRES_##ALIAS, ALIASARGS,    VALUES},
+#define OPTION(...)                                                            \
+  LLVM_CONSTRUCT_OPT_INFO_WITH_ID_PREFIX(WINDRES_, __VA_ARGS__),
 #include "WindresOpts.inc"
 #undef OPTION
 };
@@ -221,7 +208,7 @@
   bool Preprocess = true;
   bool PrintCmdAndExit = false;
   std::string Triple;
-  std::vector<std::string> PreprocessCmd;
+  std::optional<std::string> Preprocessor;
   std::vector<std::string> PreprocessArgs;
 
   std::string InputFile;
@@ -241,7 +228,7 @@
 void preprocess(StringRef Src, StringRef Dst, const RcOptions &Opts,
                 const char *Argv0) {
   std::string Clang;
-  if (Opts.PrintCmdAndExit || !Opts.PreprocessCmd.empty()) {
+  if (Opts.PrintCmdAndExit || Opts.Preprocessor) {
     Clang = "clang";
   } else {
     ErrorOr<std::string> ClangOrErr = findClang(Argv0, Opts.Triple);
@@ -260,16 +247,22 @@
   SmallVector<StringRef, 8> Args = {
       Clang, "--driver-mode=gcc", "-target", Opts.Triple, "-E",
       "-xc", "-DRC_INVOKED"};
-  if (!Opts.PreprocessCmd.empty()) {
+  std::string PreprocessorExecutable;
+  if (Opts.Preprocessor) {
     Args.clear();
-    for (const auto &S : Opts.PreprocessCmd)
-      Args.push_back(S);
+    Args.push_back(*Opts.Preprocessor);
+    if (!sys::fs::can_execute(Args[0])) {
+      if (auto P = sys::findProgramByName(Args[0])) {
+        PreprocessorExecutable = *P;
+        Args[0] = PreprocessorExecutable;
+      }
+    }
   }
+  for (const auto &S : Opts.PreprocessArgs)
+    Args.push_back(S);
   Args.push_back(Src);
   Args.push_back("-o");
   Args.push_back(Dst);
-  for (const auto &S : Opts.PreprocessArgs)
-    Args.push_back(S);
   if (Opts.PrintCmdAndExit || Opts.BeVerbose) {
     for (const auto &A : Args) {
       outs() << " ";
@@ -281,9 +274,15 @@
   }
   // The llvm Support classes don't handle reading from stdout of a child
   // process; otherwise we could avoid using a temp file.
-  int Res = sys::ExecuteAndWait(Args[0], Args);
+  std::string ErrMsg;
+  int Res =
+      sys::ExecuteAndWait(Args[0], Args, /*Env=*/std::nullopt, /*Redirects=*/{},
+                          /*SecondsToWait=*/0, /*MemoryLimit=*/0, &ErrMsg);
   if (Res) {
-    fatalError("llvm-rc: Preprocessing failed.");
+    if (!ErrMsg.empty())
+      fatalError("llvm-rc: Preprocessing failed: " + ErrMsg);
+    else
+      fatalError("llvm-rc: Preprocessing failed.");
   }
 }
 
@@ -341,36 +340,6 @@
   return Out;
 }
 
-std::vector<std::string> unescapeSplit(StringRef S) {
-  std::vector<std::string> OutArgs;
-  std::string Out;
-  bool InQuote = false;
-  for (int I = 0, E = S.size(); I < E; I++) {
-    if (S[I] == '\\') {
-      if (I + 1 < E)
-        Out.push_back(S[++I]);
-      else
-        fatalError("Unterminated escape");
-      continue;
-    }
-    if (S[I] == '"') {
-      InQuote = !InQuote;
-      continue;
-    }
-    if (S[I] == ' ' && !InQuote) {
-      OutArgs.push_back(Out);
-      Out.clear();
-      continue;
-    }
-    Out.push_back(S[I]);
-  }
-  if (InQuote)
-    fatalError("Unterminated quote");
-  if (!Out.empty())
-    OutArgs.push_back(Out);
-  return OutArgs;
-}
-
 RcOptions parseWindresOptions(ArrayRef<const char *> ArgsArr,
                               ArrayRef<const char *> InputArgsArray,
                               std::string Prefix) {
@@ -505,11 +474,8 @@
       break;
     }
   }
-  // TODO: If --use-temp-file is set, we shouldn't be unescaping
-  // the --preprocessor argument either, only splitting it.
   if (InputArgs.hasArg(WINDRES_preprocessor))
-    Opts.PreprocessCmd =
-        unescapeSplit(InputArgs.getLastArgValue(WINDRES_preprocessor));
+    Opts.Preprocessor = InputArgs.getLastArgValue(WINDRES_preprocessor);
 
   Opts.Params.CodePage = CpWin1252; // Different default
   if (InputArgs.hasArg(WINDRES_codepage)) {
@@ -595,7 +561,7 @@
     SmallString<128> OutputFile(Opts.InputFile);
     llvm::sys::fs::make_absolute(OutputFile);
     llvm::sys::path::replace_extension(OutputFile, "res");
-    OutArgsInfo.push_back(std::string(OutputFile.str()));
+    OutArgsInfo.push_back(std::string(OutputFile));
   }
   if (!Opts.IsDryRun) {
     if (OutArgsInfo.size() != 1)
@@ -764,7 +730,6 @@
 } // anonymous namespace
 
 int llvm_rc_main(int Argc, char **Argv, const llvm::ToolContext &) {
-  InitLLVM X(Argc, Argv);
   ExitOnErr.setBanner("llvm-rc: ");
 
   char **DashDash = std::find_if(Argv + 1, Argv + Argc,
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
index ef77d4b..b77839c 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -171,6 +171,7 @@
     {0xff, 0xe8, 1, &Decoder::opcode_trap_frame},
     {0xff, 0xe9, 1, &Decoder::opcode_machine_frame},
     {0xff, 0xea, 1, &Decoder::opcode_context},
+    {0xff, 0xeb, 1, &Decoder::opcode_ec_context},
     {0xff, 0xec, 1, &Decoder::opcode_clear_unwound_to_call},
     {0xff, 0xfc, 1, &Decoder::opcode_pac_sign_lr},
 };
@@ -969,6 +970,13 @@
   return false;
 }
 
+bool Decoder::opcode_ec_context(const uint8_t *OC, unsigned &Offset,
+                                unsigned Length, bool Prologue) {
+  SW.startLine() << format("0x%02x                ; EC context\n", OC[Offset]);
+  ++Offset;
+  return false;
+}
+
 bool Decoder::opcode_clear_unwound_to_call(const uint8_t *OC, unsigned &Offset,
                                            unsigned Length, bool Prologue) {
   SW.startLine() << format("0x%02x                ; clear unwound to call\n",
@@ -1468,7 +1476,7 @@
     if (!NameOrErr)
       return NameOrErr.takeError();
 
-    if (NameOrErr->startswith(".pdata"))
+    if (NameOrErr->starts_with(".pdata"))
       dumpProcedureData(COFF, Section);
   }
   return Error::success();
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
index 0ffebe5..fa5b31d 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
@@ -129,6 +129,8 @@
                             unsigned Length, bool Prologue);
   bool opcode_context(const uint8_t *Opcodes, unsigned &Offset, unsigned Length,
                       bool Prologue);
+  bool opcode_ec_context(const uint8_t *Opcodes, unsigned &Offset,
+                         unsigned Length, bool Prologue);
   bool opcode_clear_unwound_to_call(const uint8_t *Opcodes, unsigned &Offset,
                                     unsigned Length, bool Prologue);
   bool opcode_pac_sign_lr(const uint8_t *Opcodes, unsigned &Offset,
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
index 79fef8b..32b1d6a2 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -110,7 +110,7 @@
 
 private:
   StringRef getSymbolName(uint32_t Index);
-  void printSymbols() override;
+  void printSymbols(bool ExtraSymInfo) override;
   void printDynamicSymbols() override;
   void printSymbol(const SymbolRef &Sym);
   void printRelocation(const SectionRef &Section, const RelocationRef &Reloc,
@@ -854,17 +854,17 @@
         reportError(std::move(E), Obj->getFileName());
       auto CodeMap = reinterpret_cast<const chpe_range_entry *>(CodeMapInt);
       for (uint32_t i = 0; i < CHPE->CodeMapCount; i++) {
-        uint32_t Start = CodeMap[i].StartOffset & ~3;
+        uint32_t Start = CodeMap[i].getStart();
         W.startLine() << W.hex(Start) << " - "
                       << W.hex(Start + CodeMap[i].Length) << "  ";
-        switch (CodeMap[i].StartOffset & 3) {
-        case CHPE_RANGE_ARM64:
+        switch (CodeMap[i].getType()) {
+        case chpe_range_type::Arm64:
           W.getOStream() << "ARM64\n";
           break;
-        case CHPE_RANGE_ARM64EC:
+        case chpe_range_type::Arm64EC:
           W.getOStream() << "ARM64EC\n";
           break;
-        case CHPE_RANGE_AMD64:
+        case chpe_range_type::Amd64:
           W.getOStream() << "X64\n";
           break;
         default:
@@ -1106,7 +1106,7 @@
     if (Error E = Reader.readFixedString(Contents, SubSectionSize))
       reportError(std::move(E), Obj->getFileName());
 
-    BinaryStreamRef ST(Contents, support::little);
+    BinaryStreamRef ST(Contents, llvm::endianness::little);
     switch (DebugSubsectionKind(SubType)) {
     case DebugSubsectionKind::FileChecksums:
       if (Error E = CVFileChecksumTable.initialize(ST))
@@ -1148,7 +1148,7 @@
     reportError(errorCodeToError(object_error::parse_failed),
                 Obj->getFileName());
 
-  BinaryStreamReader FSReader(Data, support::little);
+  BinaryStreamReader FSReader(Data, llvm::endianness::little);
   initializeFileAndStringTables(FSReader);
 
   // TODO: Convert this over to using ModuleSubstreamVisitor.
@@ -1237,7 +1237,7 @@
     }
     case DebugSubsectionKind::FrameData: {
       // First four bytes is a relocation against the function.
-      BinaryStreamReader SR(Contents, llvm::support::little);
+      BinaryStreamReader SR(Contents, llvm::endianness::little);
 
       DebugFrameDataSubsectionRef FrameData;
       if (Error E = FrameData.initialize(SR))
@@ -1302,7 +1302,8 @@
     ListScope S(W, "FunctionLineTable");
     W.printString("LinkageName", Name);
 
-    BinaryStreamReader Reader(FunctionLineTables[Name], support::little);
+    BinaryStreamReader Reader(FunctionLineTables[Name],
+                              llvm::endianness::little);
 
     DebugLinesSubsectionRef LineInfo;
     if (Error E = LineInfo.initialize(Reader))
@@ -1354,7 +1355,7 @@
   CVSymbolDumper CVSD(W, Types, CodeViewContainer::ObjectFile, std::move(CODD),
                       CompilationCPUType, opts::CodeViewSubsectionBytes);
   CVSymbolArray Symbols;
-  BinaryStreamReader Reader(BinaryData, llvm::support::little);
+  BinaryStreamReader Reader(BinaryData, llvm::endianness::little);
   if (Error E = Reader.readArray(Symbols, Reader.getLength())) {
     W.flush();
     reportError(std::move(E), Obj->getFileName());
@@ -1369,7 +1370,7 @@
 }
 
 void COFFDumper::printCodeViewFileChecksums(StringRef Subsection) {
-  BinaryStreamRef Stream(Subsection, llvm::support::little);
+  BinaryStreamRef Stream(Subsection, llvm::endianness::little);
   DebugChecksumsSubsectionRef Checksums;
   if (Error E = Checksums.initialize(Stream))
     reportError(std::move(E), Obj->getFileName());
@@ -1389,7 +1390,7 @@
 }
 
 void COFFDumper::printCodeViewInlineeLines(StringRef Subsection) {
-  BinaryStreamReader SR(Subsection, llvm::support::little);
+  BinaryStreamReader SR(Subsection, llvm::endianness::little);
   DebugInlineeLinesSubsectionRef Lines;
   if (Error E = Lines.initialize(SR))
     reportError(std::move(E), Obj->getFileName());
@@ -1449,7 +1450,7 @@
                     Obj->getFileName());
 
       CVTypeArray Types;
-      BinaryStreamReader Reader(Data, llvm::support::little);
+      BinaryStreamReader Reader(Data, llvm::endianness::little);
       if (auto EC = Reader.readArray(Types, Reader.getLength())) {
         consumeError(std::move(EC));
         W.flush();
@@ -1609,7 +1610,7 @@
   }
 }
 
-void COFFDumper::printSymbols() {
+void COFFDumper::printSymbols(bool /*ExtraSymInfo*/) {
   ListScope Group(W, "Symbols");
 
   for (const SymbolRef &Symbol : Obj->symbols())
@@ -1945,7 +1946,7 @@
   ListScope ResourcesD(W, "Resources");
   for (const SectionRef &S : Obj->sections()) {
     StringRef Name = unwrapOrError(Obj->getFileName(), S.getName());
-    if (!Name.startswith(".rsrc"))
+    if (!Name.starts_with(".rsrc"))
       continue;
 
     StringRef Ref = unwrapOrError(Obj->getFileName(), S.getContents());
@@ -2091,10 +2092,10 @@
 
   if (Obj->isLittleEndian())
     prettyPrintStackMap(
-        W, StackMapParser<support::little>(StackMapContentsArray));
+        W, StackMapParser<llvm::endianness::little>(StackMapContentsArray));
   else
     prettyPrintStackMap(
-        W, StackMapParser<support::big>(StackMapContentsArray));
+        W, StackMapParser<llvm::endianness::big>(StackMapContentsArray));
 }
 
 void COFFDumper::printAddrsig() {
@@ -2125,7 +2126,7 @@
   const uint8_t *End = AddrsigContents.bytes_end();
   while (Cur != End) {
     unsigned Size;
-    const char *Err;
+    const char *Err = nullptr;
     uint64_t SymIndex = decodeULEB128(Cur, &Size, End, &Err);
     if (Err)
       reportError(createError(Err), Obj->getFileName());
@@ -2150,7 +2151,7 @@
 
   StringRef CGProfileContents =
       unwrapOrError(Obj->getFileName(), CGProfileSection.getContents());
-  BinaryStreamReader Reader(CGProfileContents, llvm::support::little);
+  BinaryStreamReader Reader(CGProfileContents, llvm::endianness::little);
 
   ListScope L(W, "CGProfile");
   while (!Reader.empty()) {
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/COFFImportDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/COFFImportDumper.cpp
index c9d5e82..0ab2a17 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/COFFImportDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/COFFImportDumper.cpp
@@ -23,7 +23,7 @@
 void dumpCOFFImportFile(const COFFImportFile *File, ScopedPrinter &Writer) {
   Writer.startLine() << '\n';
   Writer.printString("File", File->getFileName());
-  Writer.printString("Format", "COFF-import-file");
+  Writer.printString("Format", File->getFileFormatName());
 
   const coff_import_header *H = File->getCOFFImportHeader();
   switch (H->getType()) {
@@ -45,8 +45,14 @@
   case COFF::IMPORT_NAME_UNDECORATE:
     Writer.printString("Name type", "undecorate");
     break;
+  case COFF::IMPORT_NAME_EXPORTAS:
+    Writer.printString("Name type", "export as");
+    break;
   }
 
+  if (H->getNameType() != COFF::IMPORT_ORDINAL)
+    Writer.printString("Export name", File->getExportName());
+
   for (const object::BasicSymbolRef &Sym : File->symbols()) {
     raw_ostream &OS = Writer.startLine();
     OS << "Symbol: ";
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/src/llvm-project/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
index 365a598..687d97a 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
@@ -113,8 +113,7 @@
   if (!Content)
     reportError(Content.takeError(), ObjF.getFileName());
 
-  DataExtractor DE(*Content,
-                   ELFT::TargetEndianness == support::endianness::little,
+  DataExtractor DE(*Content, ELFT::TargetEndianness == llvm::endianness::little,
                    ELFT::Is64Bits ? 8 : 4);
 
   DictScope D(W, "Header");
@@ -189,7 +188,7 @@
       ObjF, DWARFContext::ProcessDebugRelocations::Process, nullptr);
   DWARFDataExtractor DE(DICtx->getDWARFObj(),
                         DICtx->getDWARFObj().getEHFrameSection(),
-                        ELFT::TargetEndianness == support::endianness::little,
+                        ELFT::TargetEndianness == llvm::endianness::little,
                         ELFT::Is64Bits ? 8 : 4);
   DWARFDebugFrame EHFrame(Triple::ArchType(ObjF.getArch()), /*IsEH=*/true,
                           /*EHFrameAddress=*/Address);
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
index bc8e041..387124a 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -21,7 +21,6 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/MapVector.h"
-#include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
@@ -58,6 +57,7 @@
 #include "llvm/Support/RISCVAttributeParser.h"
 #include "llvm/Support/RISCVAttributes.h"
 #include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/SystemZ/zOSSupport.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
 #include <cinttypes>
@@ -298,11 +298,13 @@
       llvm::function_ref<void(const Elf_Relr &)> RelrFn);
 
   virtual void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset,
-                                  bool NonVisibilityBitsUsed) const {};
+                                  bool NonVisibilityBitsUsed,
+                                  bool ExtraSymInfo) const {};
   virtual void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
                            DataRegion<Elf_Word> ShndxTable,
                            std::optional<StringRef> StrTable, bool IsDynamic,
-                           bool NonVisibilityBitsUsed) const = 0;
+                           bool NonVisibilityBitsUsed,
+                           bool ExtraSymInfo) const = 0;
 
   virtual void printMipsABIFlags() = 0;
   virtual void printMipsGOT(const MipsGOTParser<ELFT> &Parser) = 0;
@@ -361,7 +363,7 @@
   }
 
   void printAttributes(unsigned, std::unique_ptr<ELFAttributeParser>,
-                       support::endianness);
+                       llvm::endianness);
   void printMipsReginfo();
   void printMipsOptions();
 
@@ -406,7 +408,7 @@
   std::string getStaticSymbolName(uint32_t Index) const;
   StringRef getDynamicString(uint64_t Value) const;
 
-  void printSymbolsHelper(bool IsDynamic) const;
+  void printSymbolsHelper(bool IsDynamic, bool ExtraSymInfo) const;
   std::string getDynamicEntry(uint64_t Type, uint64_t Value) const;
 
   Expected<RelSymbol<ELFT>> getRelocationTarget(const Relocation<ELFT> &R,
@@ -508,7 +510,8 @@
 }
 
 template <class ELFT>
-void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
+void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic,
+                                         bool ExtraSymInfo) const {
   std::optional<StringRef> StrTable;
   size_t Entries = 0;
   Elf_Sym_Range Syms(nullptr, nullptr);
@@ -549,10 +552,10 @@
                       this->getElfObject().getELFFile().end())
                 : DataRegion<Elf_Word>(this->getShndxTable(SymtabSec));
 
-  printSymtabMessage(SymtabSec, Entries, NonVisibilityBitsUsed);
+  printSymtabMessage(SymtabSec, Entries, NonVisibilityBitsUsed, ExtraSymInfo);
   for (const Elf_Sym &Sym : Syms)
     printSymbol(Sym, &Sym - Syms.begin(), ShndxTable, StrTable, IsDynamic,
-                NonVisibilityBitsUsed);
+                NonVisibilityBitsUsed, ExtraSymInfo);
 }
 
 template <typename ELFT> class GNUELFDumper : public ELFDumper<ELFT> {
@@ -574,14 +577,16 @@
   void printGroupSections() override;
   void printRelocations() override;
   void printSectionHeaders() override;
-  void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override;
+  void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,
+                    bool ExtraSymInfo) override;
   void printHashSymbols() override;
   void printSectionDetails() override;
   void printDependentLibs() override;
   void printDynamicTable() override;
   void printDynamicRelocations() override;
   void printSymtabMessage(const Elf_Shdr *Symtab, size_t Offset,
-                          bool NonVisibilityBitsUsed) const override;
+                          bool NonVisibilityBitsUsed,
+                          bool ExtraSymInfo) const override;
   void printProgramHeaders(bool PrintProgramHeaders,
                            cl::boolOrDefault PrintSectionMapping) override;
   void printVersionSymbolSection(const Elf_Shdr *Sec) override;
@@ -656,12 +661,14 @@
   void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
                    DataRegion<Elf_Word> ShndxTable,
                    std::optional<StringRef> StrTable, bool IsDynamic,
-                   bool NonVisibilityBitsUsed) const override;
+                   bool NonVisibilityBitsUsed,
+                   bool ExtraSymInfo) const override;
   void printDynamicRelocHeader(unsigned Type, StringRef Name,
                                const DynRegionInfo &Reg) override;
 
   std::string getSymbolSectionNdx(const Elf_Sym &Symbol, unsigned SymIndex,
-                                  DataRegion<Elf_Word> ShndxTable) const;
+                                  DataRegion<Elf_Word> ShndxTable,
+                                  bool ExtraSymInfo = false) const;
   void printProgramHeaders() override;
   void printSectionMapping() override;
   void printGNUVersionSectionProlog(const typename ELFT::Shdr &Sec,
@@ -686,7 +693,8 @@
   void printGroupSections() override;
   void printRelocations() override;
   void printSectionHeaders() override;
-  void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override;
+  void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,
+                    bool ExtraSymInfo) override;
   void printDependentLibs() override;
   void printDynamicTable() override;
   void printDynamicRelocations() override;
@@ -719,7 +727,8 @@
   void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
                    DataRegion<Elf_Word> ShndxTable,
                    std::optional<StringRef> StrTable, bool IsDynamic,
-                   bool /*NonVisibilityBitsUsed*/) const override;
+                   bool /*NonVisibilityBitsUsed*/,
+                   bool /*ExtraSymInfo*/) const override;
   void printProgramHeaders() override;
   void printSectionMapping() override {}
   void printStackSizeEntry(uint64_t Size,
@@ -1075,6 +1084,7 @@
   {"AROS",         "AROS",                 ELF::ELFOSABI_AROS},
   {"FenixOS",      "FenixOS",              ELF::ELFOSABI_FENIXOS},
   {"CloudABI",     "CloudABI",             ELF::ELFOSABI_CLOUDABI},
+  {"CUDA",         "NVIDIA - CUDA",        ELF::ELFOSABI_CUDA},
   {"Standalone",   "Standalone App",       ELF::ELFOSABI_STANDALONE}
 };
 
@@ -1467,6 +1477,8 @@
     LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_MUTABLE);
     LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_RANDOMIZE);
     LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_WXNEEDED);
+    LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_NOBTCFI);
+    LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_SYSCALLS);
     LLVM_READOBJ_ENUM_CASE(ELF, PT_OPENBSD_BOOTDATA);
   default:
     return "";
@@ -1491,7 +1503,7 @@
     return Seg.str();
 
   // E.g. "PT_LOAD" -> "LOAD".
-  assert(Seg.startswith("PT_"));
+  assert(Seg.starts_with("PT_"));
   return Seg.drop_front(3).str();
 }
 
@@ -1548,135 +1560,152 @@
 };
 
 const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion3[] = {
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RS880),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV670),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV710),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV730),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV770),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CEDAR),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CYPRESS),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_JUNIPER),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_REDWOOD),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_SUMO),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_BARTS),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAICOS),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAYMAN),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_TURKS),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX600),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX601),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX602),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX700),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX701),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX702),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX703),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX704),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX705),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX801),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX802),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX803),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX805),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX810),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX900),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX902),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX904),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX908),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX909),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90A),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90C),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX940),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX941),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX942),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1010),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1011),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1012),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1013),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1030),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1031),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1032),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1033),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1034),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1035),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1036),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1100),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1101),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1102),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1103),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1150),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1151),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_V3),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_V3)
+    ENUM_ENT(EF_AMDGPU_MACH_NONE, "none"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_R600, "r600"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_R630, "r630"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_RS880, "rs880"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_RV670, "rv670"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_RV710, "rv710"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_RV730, "rv730"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_RV770, "rv770"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_CEDAR, "cedar"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_CYPRESS, "cypress"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_JUNIPER, "juniper"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_REDWOOD, "redwood"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_SUMO, "sumo"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_BARTS, "barts"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_CAICOS, "caicos"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_CAYMAN, "cayman"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_TURKS, "turks"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX600, "gfx600"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX601, "gfx601"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX602, "gfx602"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX700, "gfx700"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX701, "gfx701"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX702, "gfx702"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX703, "gfx703"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX704, "gfx704"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX705, "gfx705"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX801, "gfx801"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX802, "gfx802"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX803, "gfx803"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX805, "gfx805"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX810, "gfx810"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX900, "gfx900"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX902, "gfx902"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX904, "gfx904"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX906, "gfx906"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX908, "gfx908"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX909, "gfx909"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90A, "gfx90a"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90C, "gfx90c"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX940, "gfx940"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX941, "gfx941"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX942, "gfx942"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1010, "gfx1010"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1011, "gfx1011"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1012, "gfx1012"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1013, "gfx1013"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1030, "gfx1030"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1031, "gfx1031"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1032, "gfx1032"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1033, "gfx1033"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1034, "gfx1034"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1035, "gfx1035"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1036, "gfx1036"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1100, "gfx1100"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1101, "gfx1101"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1102, "gfx1102"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1103, "gfx1103"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1150, "gfx1150"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1151, "gfx1151"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1200, "gfx1200"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1201, "gfx1201"),
+    ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_V3, "xnack"),
+    ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_V3, "sramecc"),
 };
 
 const EnumEntry<unsigned> ElfHeaderAMDGPUFlagsABIVersion4[] = {
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_NONE),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R600),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_R630),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RS880),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV670),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV710),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV730),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_RV770),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CEDAR),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CYPRESS),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_JUNIPER),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_REDWOOD),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_SUMO),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_BARTS),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAICOS),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_CAYMAN),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_R600_TURKS),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX600),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX601),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX602),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX700),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX701),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX702),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX703),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX704),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX705),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX801),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX802),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX803),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX805),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX810),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX900),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX902),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX904),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX906),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX908),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX909),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90A),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX90C),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX940),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX941),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX942),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1010),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1011),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1012),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1013),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1030),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1031),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1032),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1033),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1034),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1035),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1036),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1100),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1101),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1102),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1103),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1150),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_MACH_AMDGCN_GFX1151),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_ANY_V4),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_OFF_V4),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_XNACK_ON_V4),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_ANY_V4),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_OFF_V4),
-  LLVM_READOBJ_ENUM_ENT(ELF, EF_AMDGPU_FEATURE_SRAMECC_ON_V4)
+    ENUM_ENT(EF_AMDGPU_MACH_NONE, "none"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_R600, "r600"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_R630, "r630"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_RS880, "rs880"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_RV670, "rv670"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_RV710, "rv710"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_RV730, "rv730"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_RV770, "rv770"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_CEDAR, "cedar"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_CYPRESS, "cypress"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_JUNIPER, "juniper"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_REDWOOD, "redwood"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_SUMO, "sumo"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_BARTS, "barts"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_CAICOS, "caicos"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_CAYMAN, "cayman"),
+    ENUM_ENT(EF_AMDGPU_MACH_R600_TURKS, "turks"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX600, "gfx600"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX601, "gfx601"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX602, "gfx602"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX700, "gfx700"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX701, "gfx701"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX702, "gfx702"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX703, "gfx703"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX704, "gfx704"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX705, "gfx705"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX801, "gfx801"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX802, "gfx802"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX803, "gfx803"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX805, "gfx805"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX810, "gfx810"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX900, "gfx900"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX902, "gfx902"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX904, "gfx904"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX906, "gfx906"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX908, "gfx908"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX909, "gfx909"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90A, "gfx90a"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX90C, "gfx90c"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX940, "gfx940"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX941, "gfx941"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX942, "gfx942"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1010, "gfx1010"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1011, "gfx1011"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1012, "gfx1012"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1013, "gfx1013"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1030, "gfx1030"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1031, "gfx1031"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1032, "gfx1032"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1033, "gfx1033"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1034, "gfx1034"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1035, "gfx1035"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1036, "gfx1036"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1100, "gfx1100"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1101, "gfx1101"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1102, "gfx1102"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1103, "gfx1103"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1150, "gfx1150"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1151, "gfx1151"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1200, "gfx1200"),
+    ENUM_ENT(EF_AMDGPU_MACH_AMDGCN_GFX1201, "gfx1201"),
+    ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_ANY_V4, "xnack"),
+    ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_OFF_V4, "xnack-"),
+    ENUM_ENT(EF_AMDGPU_FEATURE_XNACK_ON_V4, "xnack+"),
+    ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_ANY_V4, "sramecc"),
+    ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_OFF_V4, "sramecc-"),
+    ENUM_ENT(EF_AMDGPU_FEATURE_SRAMECC_ON_V4, "sramecc+"),
+};
+
+const EnumEntry<unsigned> ElfHeaderNVPTXFlags[] = {
+    ENUM_ENT(EF_CUDA_SM20, "sm_20"), ENUM_ENT(EF_CUDA_SM21, "sm_21"),
+    ENUM_ENT(EF_CUDA_SM30, "sm_30"), ENUM_ENT(EF_CUDA_SM32, "sm_32"),
+    ENUM_ENT(EF_CUDA_SM35, "sm_35"), ENUM_ENT(EF_CUDA_SM37, "sm_37"),
+    ENUM_ENT(EF_CUDA_SM50, "sm_50"), ENUM_ENT(EF_CUDA_SM52, "sm_52"),
+    ENUM_ENT(EF_CUDA_SM53, "sm_53"), ENUM_ENT(EF_CUDA_SM60, "sm_60"),
+    ENUM_ENT(EF_CUDA_SM61, "sm_61"), ENUM_ENT(EF_CUDA_SM62, "sm_62"),
+    ENUM_ENT(EF_CUDA_SM70, "sm_70"), ENUM_ENT(EF_CUDA_SM72, "sm_72"),
+    ENUM_ENT(EF_CUDA_SM75, "sm_75"), ENUM_ENT(EF_CUDA_SM80, "sm_80"),
+    ENUM_ENT(EF_CUDA_SM86, "sm_86"), ENUM_ENT(EF_CUDA_SM87, "sm_87"),
+    ENUM_ENT(EF_CUDA_SM89, "sm_89"), ENUM_ENT(EF_CUDA_SM90, "sm_90"),
 };
 
 const EnumEntry<unsigned> ElfHeaderRISCVFlags[] = {
@@ -2014,6 +2043,18 @@
   uint64_t StringTableSize = 0;
   std::optional<DynRegionInfo> DynSymFromTable;
   for (const Elf_Dyn &Dyn : dynamic_table()) {
+    if (Obj.getHeader().e_machine == EM_AARCH64) {
+      switch (Dyn.d_tag) {
+      case ELF::DT_AARCH64_AUTH_RELRSZ:
+        DynRelrRegion.Size = Dyn.getVal();
+        DynRelrRegion.SizePrintName = "DT_AARCH64_AUTH_RELRSZ value";
+        continue;
+      case ELF::DT_AARCH64_AUTH_RELRENT:
+        DynRelrRegion.EntSize = Dyn.getVal();
+        DynRelrRegion.EntSizePrintName = "DT_AARCH64_AUTH_RELRENT value";
+        continue;
+      }
+    }
     switch (Dyn.d_tag) {
     case ELF::DT_HASH:
       HashTable = reinterpret_cast<const Elf_Hash *>(
@@ -2077,10 +2118,12 @@
       break;
     case ELF::DT_RELR:
     case ELF::DT_ANDROID_RELR:
+    case ELF::DT_AARCH64_AUTH_RELR:
       DynRelrRegion.Addr = toMappedAddr(Dyn.getTag(), Dyn.getPtr());
       break;
     case ELF::DT_RELRSZ:
     case ELF::DT_ANDROID_RELRSZ:
+    case ELF::DT_AARCH64_AUTH_RELRSZ:
       DynRelrRegion.Size = Dyn.getVal();
       DynRelrRegion.SizePrintName = Dyn.d_tag == ELF::DT_RELRSZ
                                         ? "DT_RELRSZ value"
@@ -2088,6 +2131,7 @@
       break;
     case ELF::DT_RELRENT:
     case ELF::DT_ANDROID_RELRENT:
+    case ELF::DT_AARCH64_AUTH_RELRENT:
       DynRelrRegion.EntSize = Dyn.getVal();
       DynRelrRegion.EntSizePrintName = Dyn.d_tag == ELF::DT_RELRENT
                                            ? "DT_RELRENT value"
@@ -2454,6 +2498,8 @@
   case DT_PREINIT_ARRAYSZ:
   case DT_RELRSZ:
   case DT_RELRENT:
+  case DT_AARCH64_AUTH_RELRSZ:
+  case DT_AARCH64_AUTH_RELRENT:
   case DT_ANDROID_RELSZ:
   case DT_ANDROID_RELASZ:
     return std::to_string(Value) + " (bytes)";
@@ -2551,7 +2597,7 @@
   llvm::sort(Libs);
 
   for (StringRef L : Libs)
-    W.startLine() << L << "\n";
+    W.printString(L);
 }
 
 template <class ELFT>
@@ -2741,7 +2787,7 @@
     return;
 
   std::vector<size_t> ChainLen(NBucket, 0);
-  // Go over all buckets and and note chain lengths of each bucket (total
+  // Go over all buckets and note chain lengths of each bucket (total
   // unique chain lengths).
   for (size_t B = 0; B < NBucket; ++B) {
     BitVector Visited(NChain);
@@ -2832,7 +2878,7 @@
     if (Obj.isLE())
       printAttributes(ELF::SHT_ARM_ATTRIBUTES,
                       std::make_unique<ARMAttributeParser>(&W),
-                      support::little);
+                      llvm::endianness::little);
     else
       reportUniqueWarning("attribute printing not implemented for big-endian "
                           "ARM objects");
@@ -2841,7 +2887,7 @@
     if (Obj.isLE())
       printAttributes(ELF::SHT_RISCV_ATTRIBUTES,
                       std::make_unique<RISCVAttributeParser>(&W),
-                      support::little);
+                      llvm::endianness::little);
     else
       reportUniqueWarning("attribute printing not implemented for big-endian "
                           "RISC-V objects");
@@ -2849,7 +2895,7 @@
   case EM_MSP430:
     printAttributes(ELF::SHT_MSP430_ATTRIBUTES,
                     std::make_unique<MSP430AttributeParser>(&W),
-                    support::little);
+                    llvm::endianness::little);
     break;
   case EM_MIPS: {
     printMipsABIFlags();
@@ -2875,7 +2921,7 @@
 template <class ELFT>
 void ELFDumper<ELFT>::printAttributes(
     unsigned AttrShType, std::unique_ptr<ELFAttributeParser> AttrParser,
-    support::endianness Endianness) {
+    llvm::endianness Endianness) {
   assert((AttrShType != ELF::SHT_NULL) && AttrParser &&
          "Incomplete ELF attribute implementation");
   DictScope BA(W, "BuildAttributes");
@@ -3555,7 +3601,18 @@
   if (e.e_version == ELF::EV_CURRENT)
     OS << " (current)";
   OS << "\n";
-  Str = enumToString(e.e_ident[ELF::EI_OSABI], ArrayRef(ElfOSABI));
+  auto OSABI = ArrayRef(ElfOSABI);
+  if (e.e_ident[ELF::EI_OSABI] >= ELF::ELFOSABI_FIRST_ARCH &&
+      e.e_ident[ELF::EI_OSABI] <= ELF::ELFOSABI_LAST_ARCH) {
+    switch (e.e_machine) {
+    case ELF::EM_AMDGPU:
+      OSABI = ArrayRef(AMDGPUElfOSABI);
+      break;
+    default:
+      break;
+    }
+  }
+  Str = enumToString(e.e_ident[ELF::EI_OSABI], OSABI);
   printFields(OS, "OS/ABI:", Str);
   printFields(OS,
               "ABI Version:", std::to_string(e.e_ident[ELF::EI_ABIVERSION]));
@@ -3599,6 +3656,31 @@
   else if (e.e_machine == EM_XTENSA)
     ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderXtensaFlags),
                           unsigned(ELF::EF_XTENSA_MACH));
+  else if (e.e_machine == EM_CUDA)
+    ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderNVPTXFlags),
+                          unsigned(ELF::EF_CUDA_SM));
+  else if (e.e_machine == EM_AMDGPU) {
+    switch (e.e_ident[ELF::EI_ABIVERSION]) {
+    default:
+      break;
+    case 0:
+      // ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags.
+      [[fallthrough]];
+    case ELF::ELFABIVERSION_AMDGPU_HSA_V3:
+      ElfFlags =
+          printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion3),
+                     unsigned(ELF::EF_AMDGPU_MACH));
+      break;
+    case ELF::ELFABIVERSION_AMDGPU_HSA_V4:
+    case ELF::ELFABIVERSION_AMDGPU_HSA_V5:
+      ElfFlags =
+          printFlags(e.e_flags, ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),
+                     unsigned(ELF::EF_AMDGPU_MACH),
+                     unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),
+                     unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));
+      break;
+    }
+  }
   Str = "0x" + utohexstr(e.e_flags);
   if (!ElfFlags.empty())
     Str = Str + ", " + ElfFlags;
@@ -3786,9 +3868,12 @@
 }
 
 template <class ELFT>
-static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType) {
+static void printRelocHeaderFields(formatted_raw_ostream &OS, unsigned SType,
+                                   const typename ELFT::Ehdr &EHeader) {
   bool IsRela = SType == ELF::SHT_RELA || SType == ELF::SHT_ANDROID_RELA;
-  bool IsRelr = SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR;
+  bool IsRelr =
+      SType == ELF::SHT_RELR || SType == ELF::SHT_ANDROID_RELR ||
+      (EHeader.e_machine == EM_AARCH64 && SType == ELF::SHT_AARCH64_AUTH_RELR);
   if (ELFT::Is64Bits)
     OS << "    ";
   else
@@ -3813,15 +3898,18 @@
   uint64_t Offset = Reg.Addr - this->Obj.base();
   OS << "\n'" << Name.str().c_str() << "' relocation section at offset 0x"
      << utohexstr(Offset, /*LowerCase=*/true) << " contains " << Reg.Size << " bytes:\n";
-  printRelocHeaderFields<ELFT>(OS, Type);
+  printRelocHeaderFields<ELFT>(OS, Type, this->Obj.getHeader());
 }
 
 template <class ELFT>
-static bool isRelocationSec(const typename ELFT::Shdr &Sec) {
+static bool isRelocationSec(const typename ELFT::Shdr &Sec,
+                            const typename ELFT::Ehdr &EHeader) {
   return Sec.sh_type == ELF::SHT_REL || Sec.sh_type == ELF::SHT_RELA ||
          Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_REL ||
          Sec.sh_type == ELF::SHT_ANDROID_RELA ||
-         Sec.sh_type == ELF::SHT_ANDROID_RELR;
+         Sec.sh_type == ELF::SHT_ANDROID_RELR ||
+         (EHeader.e_machine == EM_AARCH64 &&
+          Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR);
 }
 
 template <class ELFT> void GNUELFDumper<ELFT>::printRelocations() {
@@ -3837,8 +3925,10 @@
       return RelasOrErr->size();
     }
 
-    if (!opts::RawRelr && (Sec.sh_type == ELF::SHT_RELR ||
-                           Sec.sh_type == ELF::SHT_ANDROID_RELR)) {
+    if (!opts::RawRelr &&
+        (Sec.sh_type == ELF::SHT_RELR || Sec.sh_type == ELF::SHT_ANDROID_RELR ||
+         (this->Obj.getHeader().e_machine == EM_AARCH64 &&
+          Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR))) {
       Expected<Elf_Relr_Range> RelrsOrErr = this->Obj.relrs(Sec);
       if (!RelrsOrErr)
         return RelrsOrErr.takeError();
@@ -3850,7 +3940,7 @@
 
   bool HasRelocSections = false;
   for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {
-    if (!isRelocationSec<ELFT>(Sec))
+    if (!isRelocationSec<ELFT>(Sec, this->Obj.getHeader()))
       continue;
     HasRelocSections = true;
 
@@ -3867,7 +3957,7 @@
     OS << "\nRelocation section '" << Name << "' at offset 0x"
        << utohexstr(Offset, /*LowerCase=*/true) << " contains " << EntriesNum
        << " entries:\n";
-    printRelocHeaderFields<ELFT>(OS, Sec.sh_type);
+    printRelocHeaderFields<ELFT>(OS, Sec.sh_type, this->Obj.getHeader());
     this->printRelocationsHelper(Sec);
   }
   if (!HasRelocSections)
@@ -3998,7 +4088,8 @@
 template <class ELFT>
 void GNUELFDumper<ELFT>::printSymtabMessage(const Elf_Shdr *Symtab,
                                             size_t Entries,
-                                            bool NonVisibilityBitsUsed) const {
+                                            bool NonVisibilityBitsUsed,
+                                            bool ExtraSymInfo) const {
   StringRef Name;
   if (Symtab)
     Name = this->getPrintableSectionName(*Symtab);
@@ -4008,21 +4099,27 @@
     OS << "\nSymbol table for image";
   OS << " contains " << Entries << " entries:\n";
 
-  if (ELFT::Is64Bits)
+  if (ELFT::Is64Bits) {
     OS << "   Num:    Value          Size Type    Bind   Vis";
-  else
+    if (ExtraSymInfo)
+      OS << "+Other";
+  } else {
     OS << "   Num:    Value  Size Type    Bind   Vis";
+    if (ExtraSymInfo)
+      OS << "+Other";
+  }
 
-  if (NonVisibilityBitsUsed)
-    OS << "             ";
-  OS << "       Ndx Name\n";
+  OS.PadToColumn((ELFT::Is64Bits ? 56 : 48) + (NonVisibilityBitsUsed ? 13 : 0));
+  if (ExtraSymInfo)
+    OS << "Ndx(SecName) Name [+ Version Info]\n";
+  else
+    OS << "Ndx Name\n";
 }
 
 template <class ELFT>
-std::string
-GNUELFDumper<ELFT>::getSymbolSectionNdx(const Elf_Sym &Symbol,
-                                        unsigned SymIndex,
-                                        DataRegion<Elf_Word> ShndxTable) const {
+std::string GNUELFDumper<ELFT>::getSymbolSectionNdx(
+    const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable,
+    bool ExtraSymInfo) const {
   unsigned SectionIndex = Symbol.st_shndx;
   switch (SectionIndex) {
   case ELF::SHN_UNDEF:
@@ -4041,7 +4138,8 @@
       this->reportUniqueWarning(IndexOrErr.takeError());
       return "RSV[0xffff]";
     }
-    return to_string(format_decimal(*IndexOrErr, 3));
+    SectionIndex = *IndexOrErr;
+    break;
   }
   default:
     // Find if:
@@ -4058,17 +4156,31 @@
         SectionIndex <= ELF::SHN_HIRESERVE)
       return std::string("RSV[0x") +
              to_string(format_hex_no_prefix(SectionIndex, 4)) + "]";
-    // A normal section with an index
-    return to_string(format_decimal(SectionIndex, 3));
+    break;
   }
+
+  std::string Extra;
+  if (ExtraSymInfo) {
+    auto Sec = this->Obj.getSection(SectionIndex);
+    if (!Sec) {
+      this->reportUniqueWarning(Sec.takeError());
+    } else {
+      auto SecName = this->Obj.getSectionName(**Sec);
+      if (!SecName)
+        this->reportUniqueWarning(SecName.takeError());
+      else
+        Extra = Twine(" (" + *SecName + ")").str();
+    }
+  }
+  return to_string(format_decimal(SectionIndex, 3)) + Extra;
 }
 
 template <class ELFT>
 void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
                                      DataRegion<Elf_Word> ShndxTable,
                                      std::optional<StringRef> StrTable,
-                                     bool IsDynamic,
-                                     bool NonVisibilityBitsUsed) const {
+                                     bool IsDynamic, bool NonVisibilityBitsUsed,
+                                     bool ExtraSymInfo) const {
   unsigned Bias = ELFT::Is64Bits ? 8 : 0;
   Field Fields[8] = {0,         8,         17 + Bias, 23 + Bias,
                      31 + Bias, 38 + Bias, 48 + Bias, 51 + Bias};
@@ -4115,8 +4227,10 @@
   }
 
   Fields[6].Column += NonVisibilityBitsUsed ? 13 : 0;
-  Fields[6].Str = getSymbolSectionNdx(Symbol, SymIndex, ShndxTable);
+  Fields[6].Str =
+      getSymbolSectionNdx(Symbol, SymIndex, ShndxTable, ExtraSymInfo);
 
+  Fields[7].Column += ExtraSymInfo ? 10 : 0;
   Fields[7].Str = this->getFullSymbolName(Symbol, SymIndex, ShndxTable,
                                           StrTable, IsDynamic);
   for (const Field &Entry : Fields)
@@ -4162,13 +4276,14 @@
 
 template <class ELFT>
 void GNUELFDumper<ELFT>::printSymbols(bool PrintSymbols,
-                                      bool PrintDynamicSymbols) {
+                                      bool PrintDynamicSymbols,
+                                      bool ExtraSymInfo) {
   if (!PrintSymbols && !PrintDynamicSymbols)
     return;
   // GNU readelf prints both the .dynsym and .symtab with --symbols.
-  this->printSymbolsHelper(true);
+  this->printSymbolsHelper(true, ExtraSymInfo);
   if (PrintSymbols)
-    this->printSymbolsHelper(false);
+    this->printSymbolsHelper(false, ExtraSymInfo);
 }
 
 template <class ELFT>
@@ -4474,43 +4589,6 @@
 }
 
 template <class ELFT>
-static bool checkOffsets(const typename ELFT::Phdr &Phdr,
-                         const typename ELFT::Shdr &Sec) {
-  // SHT_NOBITS sections don't need to have an offset inside the segment.
-  if (Sec.sh_type == ELF::SHT_NOBITS)
-    return true;
-
-  if (Sec.sh_offset < Phdr.p_offset)
-    return false;
-
-  // Only non-empty sections can be at the end of a segment.
-  if (Sec.sh_size == 0)
-    return (Sec.sh_offset + 1 <= Phdr.p_offset + Phdr.p_filesz);
-  return Sec.sh_offset + Sec.sh_size <= Phdr.p_offset + Phdr.p_filesz;
-}
-
-// Check that an allocatable section belongs to a virtual address
-// space of a segment.
-template <class ELFT>
-static bool checkVMA(const typename ELFT::Phdr &Phdr,
-                     const typename ELFT::Shdr &Sec) {
-  if (!(Sec.sh_flags & ELF::SHF_ALLOC))
-    return true;
-
-  if (Sec.sh_addr < Phdr.p_vaddr)
-    return false;
-
-  bool IsTbss =
-      (Sec.sh_type == ELF::SHT_NOBITS) && ((Sec.sh_flags & ELF::SHF_TLS) != 0);
-  // .tbss is special, it only has memory in PT_TLS and has NOBITS properties.
-  bool IsTbssInNonTLS = IsTbss && Phdr.p_type != ELF::PT_TLS;
-  // Only non-empty sections can be at the end of a segment.
-  if (Sec.sh_size == 0 || IsTbssInNonTLS)
-    return Sec.sh_addr + 1 <= Phdr.p_vaddr + Phdr.p_memsz;
-  return Sec.sh_addr + Sec.sh_size <= Phdr.p_vaddr + Phdr.p_memsz;
-}
-
-template <class ELFT>
 static bool checkPTDynamic(const typename ELFT::Phdr &Phdr,
                            const typename ELFT::Shdr &Sec) {
   if (Phdr.p_type != ELF::PT_DYNAMIC || Phdr.p_memsz == 0 || Sec.sh_size != 0)
@@ -4641,8 +4719,9 @@
       // readelf additionally makes sure it does not print zero sized sections
       // at end of segments and for PT_DYNAMIC both start and end of section
       // .tbss must only be shown in PT_TLS section.
-      if (checkTLSSections<ELFT>(Phdr, Sec) && checkOffsets<ELFT>(Phdr, Sec) &&
-          checkVMA<ELFT>(Phdr, Sec) && checkPTDynamic<ELFT>(Phdr, Sec)) {
+      if (isSectionInSegment<ELFT>(Phdr, Sec) &&
+          checkTLSSections<ELFT>(Phdr, Sec) &&
+          checkPTDynamic<ELFT>(Phdr, Sec)) {
         Sections +=
             unwrapOrError(this->FileName, this->Obj.getSectionName(Sec)).str() +
             " ";
@@ -5002,7 +5081,7 @@
   const uint8_t *End = Data.end();
   while (Cur != End) {
     unsigned Size;
-    const char *Err;
+    const char *Err = nullptr;
     Ret.push_back(decodeULEB128(Cur, &Size, End, &Err));
     if (Err)
       return createError(Err);
@@ -5102,6 +5181,7 @@
     if (Type == GNU_PROPERTY_AARCH64_FEATURE_1_AND) {
       DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_BTI, "BTI");
       DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_PAC, "PAC");
+      DumpBit(GNU_PROPERTY_AARCH64_FEATURE_1_GCS, "GCS");
     } else {
       DumpBit(GNU_PROPERTY_X86_FEATURE_1_IBT, "IBT");
       DumpBit(GNU_PROPERTY_X86_FEATURE_1_SHSTK, "SHSTK");
@@ -5311,6 +5391,31 @@
 }
 
 template <class ELFT>
+static bool printAArch64Note(raw_ostream &OS, uint32_t NoteType,
+                             ArrayRef<uint8_t> Desc) {
+  if (NoteType != NT_ARM_TYPE_PAUTH_ABI_TAG)
+    return false;
+
+  OS << "    AArch64 PAuth ABI tag: ";
+  if (Desc.size() < 16) {
+    OS << format("<corrupted size: expected at least 16, got %d>", Desc.size());
+    return false;
+  }
+
+  uint64_t Platform =
+      support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 0);
+  uint64_t Version =
+      support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 8);
+  OS << format("platform 0x%" PRIx64 ", version 0x%" PRIx64, Platform, Version);
+
+  if (Desc.size() > 16)
+    OS << ", additional info 0x"
+       << toHex(ArrayRef<uint8_t>(Desc.data() + 16, Desc.size() - 16));
+
+  return true;
+}
+
+template <class ELFT>
 void GNUELFDumper<ELFT>::printMemtag(
     const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
     const ArrayRef<uint8_t> AndroidNoteDesc,
@@ -5416,8 +5521,8 @@
     return {"", ""};
   case ELF::NT_AMD_HSA_CODE_OBJECT_VERSION: {
     struct CodeObjectVersion {
-      uint32_t MajorVersion;
-      uint32_t MinorVersion;
+      support::aligned_ulittle32_t MajorVersion;
+      support::aligned_ulittle32_t MinorVersion;
     };
     if (Desc.size() != sizeof(CodeObjectVersion))
       return {"AMD HSA Code Object Version",
@@ -5431,8 +5536,8 @@
   }
   case ELF::NT_AMD_HSA_HSAIL: {
     struct HSAILProperties {
-      uint32_t HSAILMajorVersion;
-      uint32_t HSAILMinorVersion;
+      support::aligned_ulittle32_t HSAILMajorVersion;
+      support::aligned_ulittle32_t HSAILMinorVersion;
       uint8_t Profile;
       uint8_t MachineModel;
       uint8_t DefaultFloatRound;
@@ -5452,11 +5557,11 @@
   }
   case ELF::NT_AMD_HSA_ISA_VERSION: {
     struct IsaVersion {
-      uint16_t VendorNameSize;
-      uint16_t ArchitectureNameSize;
-      uint32_t Major;
-      uint32_t Minor;
-      uint32_t Stepping;
+      support::aligned_ulittle16_t VendorNameSize;
+      support::aligned_ulittle16_t ArchitectureNameSize;
+      support::aligned_ulittle32_t Major;
+      support::aligned_ulittle32_t Minor;
+      support::aligned_ulittle32_t Stepping;
     };
     if (Desc.size() < sizeof(IsaVersion))
       return {"AMD HSA ISA Version", "Invalid AMD HSA ISA Version"};
@@ -5492,8 +5597,8 @@
   }
   case ELF::NT_AMD_PAL_METADATA: {
     struct PALMetadata {
-      uint32_t Key;
-      uint32_t Value;
+      support::aligned_ulittle32_t Key;
+      support::aligned_ulittle32_t Value;
     };
     if (Desc.size() % sizeof(PALMetadata) != 0)
       return {"AMD PAL Metadata", "Invalid AMD PAL Metadata"};
@@ -5530,7 +5635,7 @@
     // FIXME: Metadata Verifier only works with AMDHSA.
     //  This is an ugly workaround to avoid the verifier for other MD
     //  formats (e.g. amdpal)
-    if (MsgPackString.find("amdhsa.") != StringRef::npos) {
+    if (MsgPackString.contains("amdhsa.")) {
       AMDGPU::HSAMD::V3::MetadataVerifier Verifier(true);
       if (!Verifier.verify(MsgPackDoc.getRoot()))
         MetadataString = "Invalid AMDGPU Metadata\n";
@@ -5709,6 +5814,10 @@
      "NT_ANDROID_TYPE_MEMTAG (Android memory tagging information)"},
 };
 
+const NoteType ARMNoteTypes[] = {
+    {ELF::NT_ARM_TYPE_PAUTH_ABI_TAG, "NT_ARM_TYPE_PAUTH_ABI_TAG"},
+};
+
 const NoteType CoreNoteTypes[] = {
     {ELF::NT_PRSTATUS, "NT_PRSTATUS (prstatus structure)"},
     {ELF::NT_FPREGSET, "NT_FPREGSET (floating point registers)"},
@@ -5771,6 +5880,8 @@
     {ELF::NT_ARM_SVE, "NT_ARM_SVE (AArch64 SVE registers)"},
     {ELF::NT_ARM_PAC_MASK,
      "NT_ARM_PAC_MASK (AArch64 Pointer Authentication code masks)"},
+    {ELF::NT_ARM_TAGGED_ADDR_CTRL,
+     "NT_ARM_TAGGED_ADDR_CTRL (AArch64 Tagged Address Control)"},
     {ELF::NT_ARM_SSVE, "NT_ARM_SSVE (AArch64 Streaming SVE registers)"},
     {ELF::NT_ARM_ZA, "NT_ARM_ZA (AArch64 SME ZA registers)"},
     {ELF::NT_ARM_ZT, "NT_ARM_ZT (AArch64 SME ZT registers)"},
@@ -5804,13 +5915,13 @@
       return FindNote(FreeBSDNoteTypes);
     }
   }
-  if (ELFType == ELF::ET_CORE && Name.startswith("NetBSD-CORE")) {
+  if (ELFType == ELF::ET_CORE && Name.starts_with("NetBSD-CORE")) {
     StringRef Result = FindNote(NetBSDCoreNoteTypes);
     if (!Result.empty())
       return Result;
     return FindNote(CoreNoteTypes);
   }
-  if (ELFType == ELF::ET_CORE && Name.startswith("OpenBSD")) {
+  if (ELFType == ELF::ET_CORE && Name.starts_with("OpenBSD")) {
     // OpenBSD also places the generic core notes in the OpenBSD namespace.
     StringRef Result = FindNote(OpenBSDCoreNoteTypes);
     if (!Result.empty())
@@ -5825,6 +5936,8 @@
     return FindNote(LLVMOMPOFFLOADNoteTypes);
   if (Name == "Android")
     return FindNote(AndroidNoteTypes);
+  if (Name == "ARM")
+    return FindNote(ARMNoteTypes);
 
   if (ELFType == ELF::ET_CORE)
     return FindNote(CoreNoteTypes);
@@ -5967,9 +6080,9 @@
         return Error::success();
     } else if (Name == "CORE") {
       if (Type == ELF::NT_FILE) {
-        DataExtractor DescExtractor(Descriptor,
-                                    ELFT::TargetEndianness == support::little,
-                                    sizeof(Elf_Addr));
+        DataExtractor DescExtractor(
+            Descriptor, ELFT::TargetEndianness == llvm::endianness::little,
+            sizeof(Elf_Addr));
         if (Expected<CoreNote> NoteOrErr = readCoreNote(DescExtractor)) {
           printCoreNote<ELFT>(OS, *NoteOrErr);
           return Error::success();
@@ -5980,6 +6093,9 @@
     } else if (Name == "Android") {
       if (printAndroidNote(OS, Type, Descriptor))
         return Error::success();
+    } else if (Name == "ARM") {
+      if (printAArch64Note<ELFT>(OS, Type, Descriptor))
+        return Error::success();
     }
     if (!Descriptor.empty()) {
       OS << "   description data:";
@@ -6172,11 +6288,13 @@
                               toString(std::move(E)));
   };
 
-  // SHT_RELR/SHT_ANDROID_RELR sections do not have an associated symbol table.
-  // For them we should not treat the value of the sh_link field as an index of
-  // a symbol table.
+  // SHT_RELR/SHT_ANDROID_RELR/SHT_AARCH64_AUTH_RELR sections do not have an
+  // associated symbol table. For them we should not treat the value of the
+  // sh_link field as an index of a symbol table.
   const Elf_Shdr *SymTab;
-  if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR) {
+  if (Sec.sh_type != ELF::SHT_RELR && Sec.sh_type != ELF::SHT_ANDROID_RELR &&
+      !(Obj.getHeader().e_machine == EM_AARCH64 &&
+        Sec.sh_type == ELF::SHT_AARCH64_AUTH_RELR)) {
     Expected<const Elf_Shdr *> SymTabOrErr = Obj.getSection(Sec.sh_link);
     if (!SymTabOrErr) {
       Warn(SymTabOrErr.takeError(), "unable to locate a symbol table for");
@@ -6204,6 +6322,10 @@
       Warn(RangeOrErr.takeError());
     }
     break;
+  case ELF::SHT_AARCH64_AUTH_RELR:
+    if (Obj.getHeader().e_machine != EM_AARCH64)
+      break;
+    [[fallthrough]];
   case ELF::SHT_RELR:
   case ELF::SHT_ANDROID_RELR: {
     Expected<Elf_Relr_Range> RangeOrErr = Obj.relrs(Sec);
@@ -6841,6 +6963,9 @@
     else if (E.e_machine == EM_XTENSA)
       W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderXtensaFlags),
                    unsigned(ELF::EF_XTENSA_MACH));
+    else if (E.e_machine == EM_CUDA)
+      W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderNVPTXFlags),
+                   unsigned(ELF::EF_CUDA_SM));
     else
       W.printFlags("Flags", E.e_flags);
     W.printNumber("HeaderSize", E.e_ehsize);
@@ -6900,7 +7025,7 @@
   ListScope D(W, "Relocations");
 
   for (const Elf_Shdr &Sec : cantFail(this->Obj.sections())) {
-    if (!isRelocationSec<ELFT>(Sec))
+    if (!isRelocationSec<ELFT>(Sec, this->Obj.getHeader()))
       continue;
 
     StringRef Name = this->getPrintableSectionName(Sec);
@@ -7011,7 +7136,8 @@
               this->Obj.getSection(Sym, this->DotSymtabSec, ShndxTable));
           if (SymSec == &Sec)
             printSymbol(Sym, &Sym - &Symbols[0], ShndxTable, StrTable, false,
-                        false);
+                        /*NonVisibilityBitsUsed=*/false,
+                        /*ExtraSymInfo=*/false);
         }
       }
     }
@@ -7098,7 +7224,8 @@
                                       DataRegion<Elf_Word> ShndxTable,
                                       std::optional<StringRef> StrTable,
                                       bool IsDynamic,
-                                      bool /*NonVisibilityBitsUsed*/) const {
+                                      bool /*NonVisibilityBitsUsed*/,
+                                      bool /*ExtraSymInfo*/) const {
   std::string FullSymbolName = this->getFullSymbolName(
       Symbol, SymIndex, ShndxTable, StrTable, IsDynamic);
   unsigned char SymbolType = Symbol.getType();
@@ -7122,14 +7249,15 @@
 
 template <class ELFT>
 void LLVMELFDumper<ELFT>::printSymbols(bool PrintSymbols,
-                                       bool PrintDynamicSymbols) {
+                                       bool PrintDynamicSymbols,
+                                       bool ExtraSymInfo) {
   if (PrintSymbols) {
     ListScope Group(W, "Symbols");
-    this->printSymbolsHelper(false);
+    this->printSymbolsHelper(false, ExtraSymInfo);
   }
   if (PrintDynamicSymbols) {
     ListScope Group(W, "DynamicSymbols");
-    this->printSymbolsHelper(true);
+    this->printSymbolsHelper(true, ExtraSymInfo);
   }
 }
 
@@ -7471,7 +7599,7 @@
         W.printBoolean("HasTailCall", BBE.hasTailCall());
         W.printBoolean("IsEHPad", BBE.isEHPad());
         W.printBoolean("CanFallThrough", BBE.canFallThrough());
-        W.printBoolean("HasIndirectBranch", BBE.MD.HasIndirectBranch);
+        W.printBoolean("HasIndirectBranch", BBE.hasIndirectBranch());
       }
     }
   }
@@ -7539,6 +7667,29 @@
 }
 
 template <class ELFT>
+static bool printAarch64NoteLLVMStyle(uint32_t NoteType, ArrayRef<uint8_t> Desc,
+                                      ScopedPrinter &W) {
+  if (NoteType != NT_ARM_TYPE_PAUTH_ABI_TAG)
+    return false;
+
+  if (Desc.size() < 16)
+    return false;
+
+  uint64_t platform =
+      support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 0);
+  uint64_t version =
+      support::endian::read64<ELFT::TargetEndianness>(Desc.data() + 8);
+  W.printNumber("Platform", platform);
+  W.printNumber("Version", version);
+
+  if (Desc.size() > 16)
+    W.printString("Additional info",
+                  toHex(ArrayRef<uint8_t>(Desc.data() + 16, Desc.size() - 16)));
+
+  return true;
+}
+
+template <class ELFT>
 void LLVMELFDumper<ELFT>::printMemtag(
     const ArrayRef<std::pair<std::string, std::string>> DynamicEntries,
     const ArrayRef<uint8_t> AndroidNoteDesc,
@@ -7661,9 +7812,9 @@
         return Error::success();
     } else if (Name == "CORE") {
       if (Type == ELF::NT_FILE) {
-        DataExtractor DescExtractor(Descriptor,
-                                    ELFT::TargetEndianness == support::little,
-                                    sizeof(Elf_Addr));
+        DataExtractor DescExtractor(
+            Descriptor, ELFT::TargetEndianness == llvm::endianness::little,
+            sizeof(Elf_Addr));
         if (Expected<CoreNote> N = readCoreNote(DescExtractor)) {
           printCoreNoteLLVMStyle(*N, W);
           return Error::success();
@@ -7674,6 +7825,9 @@
     } else if (Name == "Android") {
       if (printAndroidNoteLLVMStyle(Type, Descriptor, W))
         return Error::success();
+    } else if (Name == "ARM") {
+      if (printAarch64NoteLLVMStyle<ELFT>(Type, Descriptor, W))
+        return Error::success();
     }
     if (!Descriptor.empty()) {
       W.printBinaryBlock("Description data", Descriptor);
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp
index 5b38501..0a23ad7 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp
@@ -59,7 +59,7 @@
   StringRef getSymbolName(const SymbolRef &Symbol) const;
   uint8_t getSymbolType(const SymbolRef &Symbol) const;
 
-  void printSymbols() override;
+  void printSymbols(bool ExtraSymInfo) override;
   void printSymbols(std::optional<SymbolComparator> SymComp) override;
   void printDynamicSymbols() override;
   void printDynamicSymbols(std::optional<SymbolComparator> SymComp) override;
@@ -632,7 +632,9 @@
   return getSymbolType(LHS) < getSymbolType(RHS);
 }
 
-void MachODumper::printSymbols() { printSymbols(std::nullopt); }
+void MachODumper::printSymbols(bool /*ExtraSymInfo*/) {
+  printSymbols(std::nullopt);
+}
 
 void MachODumper::printSymbols(std::optional<SymbolComparator> SymComp) {
   ListScope Group(W, "Symbols");
@@ -732,10 +734,10 @@
 
   if (Obj->isLittleEndian())
     prettyPrintStackMap(
-        W, StackMapParser<support::little>(StackMapContentsArray));
+        W, StackMapParser<llvm::endianness::little>(StackMapContentsArray));
   else
     prettyPrintStackMap(
-        W, StackMapParser<support::big>(StackMapContentsArray));
+        W, StackMapParser<llvm::endianness::big>(StackMapContentsArray));
 }
 
 void MachODumper::printCGProfile() {
@@ -758,8 +760,8 @@
   StringRef CGProfileContents =
       unwrapOrError(Obj->getFileName(), CGProfileSection.getContents());
   BinaryStreamReader Reader(CGProfileContents, Obj->isLittleEndian()
-                                                   ? llvm::support::little
-                                                   : llvm::support::big);
+                                                   ? llvm::endianness::little
+                                                   : llvm::endianness::big);
 
   ListScope L(W, "CGProfile");
   while (!Reader.empty()) {
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.cpp
index 6dde372..0d3fea7 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.cpp
@@ -14,10 +14,12 @@
 #include "ObjDumper.h"
 #include "llvm-readobj.h"
 #include "llvm/Object/Archive.h"
+#include "llvm/Object/Decompressor.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/ScopedPrinter.h"
+#include "llvm/Support/SystemZ/zOSSupport.h"
 #include "llvm/Support/raw_ostream.h"
 #include <map>
 
@@ -141,8 +143,23 @@
   return Ret;
 }
 
+static void maybeDecompress(const object::ObjectFile &Obj,
+                            StringRef SectionName, StringRef &SectionContent,
+                            SmallString<0> &Out) {
+  Expected<object::Decompressor> Decompressor = object::Decompressor::create(
+      SectionName, SectionContent, Obj.isLittleEndian(), Obj.is64Bit());
+  if (!Decompressor)
+    reportWarning(Decompressor.takeError(), Obj.getFileName());
+  else if (auto Err = Decompressor->resizeAndDecompress(Out))
+    reportWarning(std::move(Err), Obj.getFileName());
+  else
+    SectionContent = Out;
+}
+
 void ObjDumper::printSectionsAsString(const object::ObjectFile &Obj,
-                                      ArrayRef<std::string> Sections) {
+                                      ArrayRef<std::string> Sections,
+                                      bool Decompress) {
+  SmallString<0> Out;
   bool First = true;
   for (object::SectionRef Section :
        getSectionRefsByNameOrIndex(Obj, Sections)) {
@@ -155,12 +172,16 @@
 
     StringRef SectionContent =
         unwrapOrError(Obj.getFileName(), Section.getContents());
+    if (Decompress && Section.isCompressed())
+      maybeDecompress(Obj, SectionName, SectionContent, Out);
     printAsStringList(SectionContent);
   }
 }
 
 void ObjDumper::printSectionsAsHex(const object::ObjectFile &Obj,
-                                   ArrayRef<std::string> Sections) {
+                                   ArrayRef<std::string> Sections,
+                                   bool Decompress) {
+  SmallString<0> Out;
   bool First = true;
   for (object::SectionRef Section :
        getSectionRefsByNameOrIndex(Obj, Sections)) {
@@ -173,6 +194,8 @@
 
     StringRef SectionContent =
         unwrapOrError(Obj.getFileName(), Section.getContents());
+    if (Decompress && Section.isCompressed())
+      maybeDecompress(Obj, SectionName, SectionContent, Out);
     const uint8_t *SecContent = SectionContent.bytes_begin();
     const uint8_t *SecEnd = SecContent + SectionContent.size();
 
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h b/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
index 921792f..3958dd3 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
@@ -13,9 +13,7 @@
 #include <memory>
 #include <system_error>
 
-#include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/CommandLine.h"
@@ -77,13 +75,15 @@
   virtual void printFileHeaders() = 0;
   virtual void printSectionHeaders() = 0;
   virtual void printRelocations() = 0;
-  virtual void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) {
+  virtual void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,
+                            bool ExtraSymInfo) {
     if (PrintSymbols)
-      printSymbols();
+      printSymbols(ExtraSymInfo);
     if (PrintDynamicSymbols)
       printDynamicSymbols();
   }
   virtual void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,
+                            bool ExtraSymInfo,
                             std::optional<SymbolComparator> SymComp) {
     if (SymComp) {
       if (PrintSymbols)
@@ -91,7 +91,7 @@
       if (PrintDynamicSymbols)
         printDynamicSymbols(SymComp);
     } else {
-      printSymbols(PrintSymbols, PrintDynamicSymbols);
+      printSymbols(PrintSymbols, PrintDynamicSymbols, ExtraSymInfo);
     }
   }
   virtual void printProgramHeaders(bool PrintProgramHeaders,
@@ -175,9 +175,9 @@
   void printAsStringList(StringRef StringContent, size_t StringDataOffset = 0);
 
   void printSectionsAsString(const object::ObjectFile &Obj,
-                             ArrayRef<std::string> Sections);
+                             ArrayRef<std::string> Sections, bool Decompress);
   void printSectionsAsHex(const object::ObjectFile &Obj,
-                          ArrayRef<std::string> Sections);
+                          ArrayRef<std::string> Sections, bool Decompress);
 
   std::function<Error(const Twine &Msg)> WarningHandler;
   void reportUniqueWarning(Error Err) const;
@@ -187,7 +187,7 @@
   ScopedPrinter &W;
 
 private:
-  virtual void printSymbols() {}
+  virtual void printSymbols(bool ExtraSymInfo) {}
   virtual void printSymbols(std::optional<SymbolComparator> Comp) {}
   virtual void printDynamicSymbols() {}
   virtual void printDynamicSymbols(std::optional<SymbolComparator> Comp) {}
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/Opts.td b/src/llvm-project/llvm/tools/llvm-readobj/Opts.td
index fec0adb..018facc 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/Opts.td
+++ b/src/llvm-project/llvm/tools/llvm-readobj/Opts.td
@@ -20,11 +20,13 @@
 def arch_specific : FF<"arch-specific", "Display architecture-specific information">;
 def bb_addr_map : FF<"bb-addr-map", "Display the BB address map section">;
 def cg_profile : FF<"cg-profile", "Display call graph profile section">;
+def decompress : FF<"decompress", "Dump decompressed section content when used with -x or -p">;
 defm demangle : BB<"demangle", "Demangle symbol names", "Do not demangle symbol names (default)">;
 def dependent_libraries : FF<"dependent-libraries", "Display the dependent libraries section">;
 def dyn_relocations : FF<"dyn-relocations", "Display the dynamic relocation entries in the file">;
 def dyn_syms : FF<"dyn-syms", "Display the dynamic symbol table">;
 def expand_relocs : FF<"expand-relocs", "Expand each shown relocation to multiple lines">;
+def extra_sym_info : FF<"extra-sym-info", "Display extra information when showing symbols">;
 def file_header : FF<"file-header", "Display file header">;
 def headers : FF<"headers", "Equivalent to setting: --file-header, --program-headers, --section-headers">;
 defm hex_dump : Eq<"hex-dump", "Display the specified section(s) as hexadecimal bytes">, MetaVarName<"<name or index>">;
@@ -135,5 +137,7 @@
 def : F<"s", "Alias for --symbols">, Alias<symbols>;
 def : F<"t", "Alias for --section-details">, Alias<section_details>;
 def : F<"u", "Alias for --unwind">, Alias<unwind>;
+def : F<"X", "Alias for --extra-sym-info">, Alias<extra_sym_info>, Group<grp_elf>;
 def : F<"V", "Alias for --version-info">, Alias<version_info>, Group<grp_elf>;
 def : JoinedOrSeparate<["-"], "x">, Alias<hex_dump_EQ>, HelpText<"Alias for --hex-dump">, MetaVarName<"<name or index>">;
+def : F<"z", "Alias for --decompress">, Alias<decompress>;
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp
index e6f0ac7..5d7639b 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp
@@ -70,7 +70,7 @@
   void printRelocation(const SectionRef &Section, const RelocationRef &Reloc);
 
 private:
-  void printSymbols() override;
+  void printSymbols(bool ExtraSymInfo) override;
   void printDynamicSymbols() override { llvm_unreachable("unimplemented"); }
 
   const WasmObjectFile *Obj;
@@ -144,7 +144,7 @@
   }
 }
 
-void WasmDumper::printSymbols() {
+void WasmDumper::printSymbols(bool /*ExtraSymInfo*/) {
   ListScope Group(W, "Symbols");
 
   for (const SymbolRef &Symbol : Obj->symbols())
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/Win64EHDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/Win64EHDumper.cpp
index 2896f20..e4bd772 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/Win64EHDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/Win64EHDumper.cpp
@@ -397,7 +397,7 @@
     else
       consumeError(NameOrErr.takeError());
 
-    if (Name != ".pdata" && !Name.startswith(".pdata$"))
+    if (Name != ".pdata" && !Name.starts_with(".pdata$"))
       continue;
 
     const coff_section *PData = Ctx.COFF.getCOFFSection(Section);
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/WindowsResourceDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/WindowsResourceDumper.cpp
index fb085ec..5337005 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/WindowsResourceDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/WindowsResourceDumper.cpp
@@ -26,7 +26,7 @@
   for (UTF16 Ch : UTF16Str) {
     // UTF16Str will have swapped byte order in case of big-endian machines.
     // Swap it back in such a case.
-    uint16_t ChValue = support::endian::byte_swap(Ch, support::little);
+    uint16_t ChValue = support::endian::byte_swap(Ch, llvm::endianness::little);
     if (ChValue <= 0xFF)
       Result += ChValue;
     else
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
index 74ebcc4..8ebd670 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
@@ -33,7 +33,7 @@
   void printAuxiliaryHeader() override;
   void printSectionHeaders() override;
   void printRelocations() override;
-  void printSymbols() override;
+  void printSymbols(bool ExtraSymInfo) override;
   void printDynamicSymbols() override;
   void printUnwindInfo() override;
   void printStackMap() const override;
@@ -903,7 +903,7 @@
   }
 }
 
-void XCOFFDumper::printSymbols() {
+void XCOFFDumper::printSymbols(bool /*ExtraSymInfo*/) {
   ListScope Group(W, "Symbols");
   for (const SymbolRef &S : Obj.symbols())
     printSymbol(S);
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp b/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
index d72eec0..979433d 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -42,7 +42,6 @@
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/ScopedPrinter.h"
@@ -55,9 +54,7 @@
 using namespace llvm::opt; // for HelpHidden in Opts.inc
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -70,13 +67,7 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -106,10 +97,12 @@
 static bool BBAddrMap;
 bool ExpandRelocs;
 static bool CGProfile;
+static bool Decompress;
 bool Demangle;
 static bool DependentLibraries;
 static bool DynRelocs;
 static bool DynamicSymbols;
+static bool ExtraSymInfo;
 static bool FileHeaders;
 static bool Headers;
 static std::vector<std::string> HexDump;
@@ -220,11 +213,13 @@
   opts::ArchSpecificInfo = Args.hasArg(OPT_arch_specific);
   opts::BBAddrMap = Args.hasArg(OPT_bb_addr_map);
   opts::CGProfile = Args.hasArg(OPT_cg_profile);
+  opts::Decompress = Args.hasArg(OPT_decompress);
   opts::Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false);
   opts::DependentLibraries = Args.hasArg(OPT_dependent_libraries);
   opts::DynRelocs = Args.hasArg(OPT_dyn_relocations);
   opts::DynamicSymbols = Args.hasArg(OPT_dyn_syms);
   opts::ExpandRelocs = Args.hasArg(OPT_expand_relocs);
+  opts::ExtraSymInfo = Args.hasArg(OPT_extra_sym_info);
   opts::FileHeaders = Args.hasArg(OPT_file_header);
   opts::Headers = Args.hasArg(OPT_headers);
   opts::HexDump = Args.getAllArgValues(OPT_hex_dump_EQ);
@@ -443,11 +438,12 @@
   if (opts::UnwindInfo)
     Dumper->printUnwindInfo();
   if (opts::Symbols || opts::DynamicSymbols)
-    Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols, SymComp);
+    Dumper->printSymbols(opts::Symbols, opts::DynamicSymbols,
+                         opts::ExtraSymInfo, SymComp);
   if (!opts::StringDump.empty())
-    Dumper->printSectionsAsString(Obj, opts::StringDump);
+    Dumper->printSectionsAsString(Obj, opts::StringDump, opts::Decompress);
   if (!opts::HexDump.empty())
-    Dumper->printSectionsAsHex(Obj, opts::HexDump);
+    Dumper->printSectionsAsHex(Obj, opts::HexDump, opts::Decompress);
   if (opts::HashTable)
     Dumper->printHashTable();
   if (opts::GnuHashTable)
@@ -638,7 +634,6 @@
 }
 
 int llvm_readobj_main(int argc, char **argv, const llvm::ToolContext &) {
-  InitLLVM X(argc, argv);
   BumpPtrAllocator A;
   StringSaver Saver(A);
   ReadobjOptTable Tbl;
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.h b/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.h
index 5a9fe28..532e43d 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.h
@@ -16,7 +16,6 @@
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorOr.h"
-#include <string>
 
 namespace llvm {
   namespace object {
diff --git a/src/llvm-project/llvm/tools/llvm-readtapi/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-readtapi/CMakeLists.txt
new file mode 100644
index 0000000..855a147
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-readtapi/CMakeLists.txt
@@ -0,0 +1,24 @@
+set(LLVM_LINK_COMPONENTS
+  BinaryFormat
+  Object
+  Support
+  Option
+  TextAPI
+  TextAPIBinaryReader
+  )
+
+set(LLVM_TARGET_DEFINITIONS TapiOpts.td)
+tablegen(LLVM TapiOpts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(ReadTAPIOptsTableGen)
+
+add_llvm_tool(llvm-readtapi
+  llvm-readtapi.cpp
+  DiffEngine.cpp
+
+  DEPENDS
+  ReadTAPIOptsTableGen
+  )
+
+if(LLVM_INSTALL_BINUTILS_SYMLINKS)
+  add_llvm_tool_symlink(readtapi llvm-readtapi)
+endif()
diff --git a/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp b/src/llvm-project/llvm/tools/llvm-readtapi/DiffEngine.cpp
similarity index 93%
rename from src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp
rename to src/llvm-project/llvm/tools/llvm-readtapi/DiffEngine.cpp
index 3e07bb9..40722d2 100644
--- a/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readtapi/DiffEngine.cpp
@@ -224,7 +224,7 @@
                 Order);
   diffAttribute("Parent Umbrellas", Output, Interface->umbrellas(), Order);
   diffAttribute("Symbols", Output, Interface->symbols(), Order);
-  for (auto Doc : Interface->documents()) {
+  for (const auto &Doc : Interface->documents()) {
     DiffOutput Documents("Inlined Reexported Frameworks/Libraries");
     Documents.Kind = AD_Inline_Doc;
     Documents.Values.push_back(std::make_unique<InlineDoc>(
@@ -363,11 +363,30 @@
                               rhs, IFRHS->isApplicationExtensionSafe()),
                           "Application Extension Safe"));
 
+  if (IFLHS->hasSimulatorSupport() != IFRHS->hasSimulatorSupport())
+    Output.push_back(recordDifferences(DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+                                           lhs, IFLHS->hasSimulatorSupport()),
+                                       DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+                                           rhs, IFRHS->hasSimulatorSupport()),
+                                       "Simulator Support"));
+
+  if (IFLHS->isOSLibNotForSharedCache() != IFRHS->isOSLibNotForSharedCache())
+    Output.push_back(
+        recordDifferences(DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+                              lhs, IFLHS->isOSLibNotForSharedCache()),
+                          DiffScalarVal<bool, AD_Diff_Scalar_Bool>(
+                              rhs, IFRHS->isOSLibNotForSharedCache()),
+                          "Shared Cache Ineligible"));
+
   if (IFLHS->reexportedLibraries() != IFRHS->reexportedLibraries())
     Output.push_back(recordDifferences(IFLHS->reexportedLibraries(),
                                        IFRHS->reexportedLibraries(),
                                        "Reexported Libraries"));
 
+  if (IFLHS->rpaths() != IFRHS->rpaths())
+    Output.push_back(recordDifferences(IFLHS->rpaths(), IFRHS->rpaths(),
+                                       "Run Path Search Paths"));
+
   if (IFLHS->allowableClients() != IFRHS->allowableClients())
     Output.push_back(recordDifferences(IFLHS->allowableClients(),
                                        IFRHS->allowableClients(),
@@ -440,11 +459,11 @@
 
 template <typename T> void sortTargetValues(std::vector<T> &TargValues) {
   llvm::stable_sort(TargValues, [](const auto &ValA, const auto &ValB) {
+    if (ValA.getOrder() == ValB.getOrder()) {
+      return ValA.getVal() < ValB.getVal();
+    }
     return ValA.getOrder() < ValB.getOrder();
   });
-  llvm::stable_sort(TargValues, [](const auto &ValA, const auto &ValB) {
-    return ValA.getOrder() == ValB.getOrder() && ValA.getVal() < ValB.getVal();
-  });
 }
 
 template <typename T>
@@ -541,13 +560,11 @@
 }
 
 bool DiffEngine::compareFiles(raw_ostream &OS) {
-  const auto *IFLHS = &(FileLHS->getInterfaceFile());
-  const auto *IFRHS = &(FileRHS->getInterfaceFile());
-  if (*IFLHS == *IFRHS)
+  if (*FileLHS == *FileRHS)
     return false;
-  OS << "< " << std::string(IFLHS->getPath().data()) << "\n> "
-     << std::string(IFRHS->getPath().data()) << "\n\n";
-  std::vector<DiffOutput> Diffs = findDifferences(IFLHS, IFRHS);
+  OS << "< " << std::string(FileLHS->getPath().data()) << "\n> "
+     << std::string(FileRHS->getPath().data()) << "\n\n";
+  std::vector<DiffOutput> Diffs = findDifferences(FileLHS, FileRHS);
   printDifferences(OS, Diffs, 0);
   return true;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h b/src/llvm-project/llvm/tools/llvm-readtapi/DiffEngine.h
similarity index 96%
rename from src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h
rename to src/llvm-project/llvm/tools/llvm-readtapi/DiffEngine.h
index 27b7257..5f7c29c 100644
--- a/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h
+++ b/src/llvm-project/llvm/tools/llvm-readtapi/DiffEngine.h
@@ -141,14 +141,14 @@
 /// output of the differences found in the files.
 class DiffEngine {
 public:
-  DiffEngine(object::TapiUniversal *InputFileNameLHS,
-             object::TapiUniversal *InputFileNameRHS)
+  DiffEngine(MachO::InterfaceFile *InputFileNameLHS,
+             MachO::InterfaceFile *InputFileNameRHS)
       : FileLHS(InputFileNameLHS), FileRHS(InputFileNameRHS){};
   bool compareFiles(raw_ostream &);
 
 private:
-  object::TapiUniversal *FileLHS;
-  object::TapiUniversal *FileRHS;
+  MachO::InterfaceFile *FileLHS;
+  MachO::InterfaceFile *FileRHS;
 
   /// Function that prints the differences found in the files.
   void printDifferences(raw_ostream &, const std::vector<DiffOutput> &, int);
diff --git a/src/llvm-project/llvm/tools/llvm-readtapi/TapiOpts.td b/src/llvm-project/llvm/tools/llvm-readtapi/TapiOpts.td
new file mode 100644
index 0000000..34ec561
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-readtapi/TapiOpts.td
@@ -0,0 +1,34 @@
+// Include the common option parsing interfaces.
+include "llvm/Option/OptParser.td"
+
+class FF<string name, string help>: Flag<["-", "--"], name>, HelpText<help>;
+multiclass JS<string name, string help, string var = ""> {
+  def NAME #_EQ : Joined<["--"], name #"=">, HelpText<help>, MetaVarName<var>;
+  def : Separate<["-", "--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+}
+
+//
+// Top level operations 
+//
+def action_group : OptionGroup<"action group">, HelpText<"COMMANDS">;
+def compare : FF<"compare", "compare tapi files for library differences">, Group<action_group>;
+def merge : FF<"merge", "merge the input files that represent the same library">, Group<action_group>;
+def extract: FF<"extract", "extract <architecture> from input file">, Group<action_group>;
+def remove: FF<"remove", "remove <architecture> from input file">, Group<action_group>;
+def stubify: FF<"stubify", "create a tapi file from a dynamic library or framework">, Group<action_group>;
+
+//
+// General Driver options 
+//
+def help : FF<"help", "display this help">;
+def version: FF<"version", "print the llvm-readtapi version">;
+def v: FF<"v", "alias for --version">, Alias<version>;
+defm output: JS<"o", "write output to <file>","<file>">;
+def compact: FF<"compact", "write compact tapi output file">;
+defm filetype: JS<"filetype", "specify the output file type (tbd-v3, tbd-v4 or tbd-v5)","<value>">;
+defm arch: JS<"arch", "specify the <architecture>", "<architecture>">;
+
+//
+// Stub options
+//
+def delete_input : FF<"delete-input", "delete and replace input file on success">;
diff --git a/src/llvm-project/llvm/tools/llvm-readtapi/llvm-readtapi.cpp b/src/llvm-project/llvm/tools/llvm-readtapi/llvm-readtapi.cpp
new file mode 100644
index 0000000..4bd4722
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-readtapi/llvm-readtapi.cpp
@@ -0,0 +1,300 @@
+//===-- llvm-readtapi.cpp - tapi file reader and transformer -----*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the command-line driver for llvm-readtapi.
+//
+//===----------------------------------------------------------------------===//
+#include "DiffEngine.h"
+#include "llvm/BinaryFormat/Magic.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/TextAPI/DylibReader.h"
+#include "llvm/TextAPI/TextAPIError.h"
+#include "llvm/TextAPI/TextAPIReader.h"
+#include "llvm/TextAPI/TextAPIWriter.h"
+#include "llvm/TextAPI/Utils.h"
+#include <cstdlib>
+
+using namespace llvm;
+using namespace MachO;
+using namespace object;
+
+#if !defined(PATH_MAX)
+#define PATH_MAX 1024
+#endif
+
+namespace {
+using namespace llvm::opt;
+enum ID {
+  OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
+#include "TapiOpts.inc"
+#undef OPTION
+};
+
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
+#include "TapiOpts.inc"
+#undef PREFIX
+
+static constexpr opt::OptTable::Info InfoTable[] = {
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
+#include "TapiOpts.inc"
+#undef OPTION
+};
+
+class TAPIOptTable : public opt::GenericOptTable {
+public:
+  TAPIOptTable() : opt::GenericOptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
+};
+
+struct StubOptions {
+  bool DeleteInput = false;
+};
+
+struct Context {
+  std::vector<std::string> Inputs;
+  std::unique_ptr<llvm::raw_fd_stream> OutStream;
+  FileType WriteFT = FileType::TBD_V5;
+  StubOptions StubOpt;
+  bool Compact = false;
+  Architecture Arch = AK_unknown;
+};
+
+// Use unique exit code to differentiate failures not directly caused from
+// TextAPI operations. This is used for wrapping `compare` operations in
+// automation and scripting.
+const int NON_TAPI_EXIT_CODE = 2;
+const std::string TOOLNAME = "llvm-readtapi";
+ExitOnError ExitOnErr;
+} // anonymous namespace
+
+// Handle error reporting in cases where `ExitOnError` is not used.
+static void reportError(Twine Message, int ExitCode = EXIT_FAILURE) {
+  errs() << TOOLNAME << ": error: " << Message << "\n";
+  errs().flush();
+  exit(ExitCode);
+}
+
+static std::unique_ptr<InterfaceFile>
+getInterfaceFile(const StringRef Filename, bool ResetBanner = true) {
+  ExitOnErr.setBanner(TOOLNAME + ": error: '" + Filename.str() + "' ");
+  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
+      MemoryBuffer::getFile(Filename);
+  if (BufferOrErr.getError())
+    ExitOnErr(errorCodeToError(BufferOrErr.getError()));
+  auto Buffer = std::move(*BufferOrErr);
+
+  std::unique_ptr<InterfaceFile> IF;
+  switch (identify_magic(Buffer->getBuffer())) {
+  case file_magic::macho_dynamically_linked_shared_lib:
+    LLVM_FALLTHROUGH;
+  case file_magic::macho_dynamically_linked_shared_lib_stub:
+    LLVM_FALLTHROUGH;
+  case file_magic::macho_universal_binary:
+    IF = ExitOnErr(DylibReader::get(Buffer->getMemBufferRef()));
+    break;
+  case file_magic::tapi_file:
+    IF = ExitOnErr(TextAPIReader::get(Buffer->getMemBufferRef()));
+    break;
+  default:
+    reportError(Filename + ": unsupported file type");
+  }
+
+  if (ResetBanner)
+    ExitOnErr.setBanner(TOOLNAME + ": error: ");
+  return IF;
+}
+
+static bool handleCompareAction(const Context &Ctx) {
+  if (Ctx.Inputs.size() != 2)
+    reportError("compare only supports two input files",
+                /*ExitCode=*/NON_TAPI_EXIT_CODE);
+
+  // Override default exit code.
+  ExitOnErr = ExitOnError(TOOLNAME + ": error: ",
+                          /*DefaultErrorExitCode=*/NON_TAPI_EXIT_CODE);
+  auto LeftIF = getInterfaceFile(Ctx.Inputs.front());
+  auto RightIF = getInterfaceFile(Ctx.Inputs.at(1));
+
+  raw_ostream &OS = Ctx.OutStream ? *Ctx.OutStream : outs();
+  return DiffEngine(LeftIF.get(), RightIF.get()).compareFiles(OS);
+}
+
+static bool handleWriteAction(const Context &Ctx,
+                              std::unique_ptr<InterfaceFile> Out = nullptr) {
+  if (!Out) {
+    if (Ctx.Inputs.size() != 1)
+      reportError("write only supports one input file");
+    Out = getInterfaceFile(Ctx.Inputs.front());
+  }
+  raw_ostream &OS = Ctx.OutStream ? *Ctx.OutStream : outs();
+  ExitOnErr(TextAPIWriter::writeToStream(OS, *Out, Ctx.WriteFT, Ctx.Compact));
+  return EXIT_SUCCESS;
+}
+
+static bool handleMergeAction(const Context &Ctx) {
+  if (Ctx.Inputs.size() < 2)
+    reportError("merge requires at least two input files");
+
+  std::unique_ptr<InterfaceFile> Out;
+  for (StringRef FileName : Ctx.Inputs) {
+    auto IF = getInterfaceFile(FileName);
+    // On the first iteration copy the input file and skip merge.
+    if (!Out) {
+      Out = std::move(IF);
+      continue;
+    }
+    Out = ExitOnErr(Out->merge(IF.get()));
+  }
+  return handleWriteAction(Ctx, std::move(Out));
+}
+
+static bool handleStubifyAction(Context &Ctx) {
+  if (Ctx.Inputs.empty())
+    reportError("stubify requires at least one input file");
+
+  if ((Ctx.Inputs.size() > 1) && (Ctx.OutStream != nullptr))
+    reportError("cannot write multiple inputs into single output file");
+
+  for (StringRef FileName : Ctx.Inputs) {
+    auto IF = getInterfaceFile(FileName);
+    if (Ctx.StubOpt.DeleteInput) {
+      std::error_code EC;
+      SmallString<PATH_MAX> OutputLoc = FileName;
+      MachO::replace_extension(OutputLoc, ".tbd");
+      Ctx.OutStream = std::make_unique<llvm::raw_fd_stream>(OutputLoc, EC);
+      if (EC)
+        reportError("opening file '" + OutputLoc + ": " + EC.message());
+      if (auto Err = sys::fs::remove(FileName))
+        reportError("deleting file '" + FileName + ": " + EC.message());
+    }
+    handleWriteAction(Ctx, std::move(IF));
+  }
+  return EXIT_SUCCESS;
+}
+
+using IFOperation =
+    std::function<llvm::Expected<std::unique_ptr<InterfaceFile>>(
+        const llvm::MachO::InterfaceFile &, Architecture)>;
+static bool handleSingleFileAction(const Context &Ctx, const StringRef Action,
+                                   IFOperation act) {
+  if (Ctx.Inputs.size() != 1)
+    reportError(Action + " only supports one input file");
+  if (Ctx.Arch == AK_unknown)
+    reportError(Action + " requires -arch <arch>");
+
+  auto IF = getInterfaceFile(Ctx.Inputs.front(), /*ResetBanner=*/false);
+  auto OutIF = act(*IF, Ctx.Arch);
+  if (!OutIF)
+    ExitOnErr(OutIF.takeError());
+
+  return handleWriteAction(Ctx, std::move(*OutIF));
+}
+
+static void setStubOptions(opt::InputArgList &Args, StubOptions &Opt) {
+  Opt.DeleteInput = Args.hasArg(OPT_delete_input);
+}
+
+int main(int Argc, char **Argv) {
+  InitLLVM X(Argc, Argv);
+  BumpPtrAllocator A;
+  StringSaver Saver(A);
+  TAPIOptTable Tbl;
+  Context Ctx;
+  ExitOnErr.setBanner(TOOLNAME + ": error:");
+  opt::InputArgList Args = Tbl.parseArgs(
+      Argc, Argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) { reportError(Msg); });
+  if (Args.hasArg(OPT_help)) {
+    Tbl.printHelp(outs(),
+                  "USAGE: llvm-readtapi <command> [-arch <architecture> "
+                  "<options>]* <inputs> [-o "
+                  "<output>]*",
+                  "LLVM TAPI file reader and transformer");
+    return EXIT_SUCCESS;
+  }
+
+  if (Args.hasArg(OPT_version)) {
+    cl::PrintVersionMessage();
+    return EXIT_SUCCESS;
+  }
+
+  // TODO: Add support for picking up libraries from directory input.
+  for (opt::Arg *A : Args.filtered(OPT_INPUT))
+    Ctx.Inputs.push_back(A->getValue());
+
+  if (opt::Arg *A = Args.getLastArg(OPT_output_EQ)) {
+    std::string OutputLoc = std::move(A->getValue());
+    std::error_code EC;
+    Ctx.OutStream = std::make_unique<llvm::raw_fd_stream>(OutputLoc, EC);
+    if (EC)
+      reportError("error opening the file '" + OutputLoc + EC.message(),
+                  NON_TAPI_EXIT_CODE);
+  }
+
+  Ctx.Compact = Args.hasArg(OPT_compact);
+
+  if (opt::Arg *A = Args.getLastArg(OPT_filetype_EQ)) {
+    StringRef FT = A->getValue();
+    Ctx.WriteFT = TextAPIWriter::parseFileType(FT);
+    if (Ctx.WriteFT < FileType::TBD_V3)
+      reportError("deprecated filetype '" + FT + "' is not supported to write");
+    if (Ctx.WriteFT == FileType::Invalid)
+      reportError("unsupported filetype '" + FT + "'");
+  }
+
+  if (opt::Arg *A = Args.getLastArg(OPT_arch_EQ)) {
+    StringRef Arch = A->getValue();
+    Ctx.Arch = getArchitectureFromName(Arch);
+    if (Ctx.Arch == AK_unknown)
+      reportError("unsupported architecture '" + Arch);
+  }
+  // Handle top level and exclusive operation.
+  SmallVector<opt::Arg *, 1> ActionArgs(Args.filtered(OPT_action_group));
+
+  if (ActionArgs.empty())
+    // If no action specified, write out tapi file in requested format.
+    return handleWriteAction(Ctx);
+
+  if (ActionArgs.size() > 1) {
+    std::string Buf;
+    raw_string_ostream OS(Buf);
+    OS << "only one of the following actions can be specified:";
+    for (auto *Arg : ActionArgs)
+      OS << " " << Arg->getSpelling();
+    reportError(OS.str());
+  }
+
+  switch (ActionArgs.front()->getOption().getID()) {
+  case OPT_compare:
+    return handleCompareAction(Ctx);
+  case OPT_merge:
+    return handleMergeAction(Ctx);
+  case OPT_extract:
+    return handleSingleFileAction(Ctx, "extract", &InterfaceFile::extract);
+  case OPT_remove:
+    return handleSingleFileAction(Ctx, "remove", &InterfaceFile::remove);
+  case OPT_stubify:
+    setStubOptions(Args, Ctx.StubOpt);
+    return handleStubifyAction(Ctx);
+  }
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt
index 4375376..2f1164b 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt
@@ -31,6 +31,7 @@
   deltas/ReduceAttributes.cpp
   deltas/ReduceBasicBlocks.cpp
   deltas/ReduceDIMetadata.cpp
+  deltas/ReduceDPValues.cpp
   deltas/ReduceFunctionBodies.cpp
   deltas/ReduceFunctions.cpp
   deltas/ReduceGlobalObjects.cpp
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.cpp b/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.cpp
index bfe299c..56e39b8 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.cpp
@@ -20,6 +20,7 @@
 #include "deltas/ReduceAttributes.h"
 #include "deltas/ReduceBasicBlocks.h"
 #include "deltas/ReduceDIMetadata.h"
+#include "deltas/ReduceDPValues.h"
 #include "deltas/ReduceFunctionBodies.h"
 #include "deltas/ReduceFunctions.h"
 #include "deltas/ReduceGlobalObjects.h"
@@ -78,9 +79,11 @@
     DELTA_PASS("aliases", reduceAliasesDeltaPass)                              \
     DELTA_PASS("ifuncs", reduceIFuncsDeltaPass)                                \
     DELTA_PASS("simplify-conditionals-true", reduceConditionalsTrueDeltaPass)  \
-    DELTA_PASS("simplify-conditionals-false", reduceConditionalsFalseDeltaPass)\
+    DELTA_PASS("simplify-conditionals-false",                                  \
+               reduceConditionalsFalseDeltaPass)                               \
     DELTA_PASS("invokes", reduceInvokesDeltaPass)                              \
-    DELTA_PASS("unreachable-basic-blocks", reduceUnreachableBasicBlocksDeltaPass) \
+    DELTA_PASS("unreachable-basic-blocks",                                     \
+               reduceUnreachableBasicBlocksDeltaPass)                          \
     DELTA_PASS("basic-blocks", reduceBasicBlocksDeltaPass)                     \
     DELTA_PASS("simplify-cfg", reduceUsingSimplifyCFGDeltaPass)                \
     DELTA_PASS("function-data", reduceFunctionDataDeltaPass)                   \
@@ -89,6 +92,7 @@
     DELTA_PASS("global-initializers", reduceGlobalsInitializersDeltaPass)      \
     DELTA_PASS("global-variables", reduceGlobalsDeltaPass)                     \
     DELTA_PASS("di-metadata", reduceDIMetadataDeltaPass)                       \
+    DELTA_PASS("dpvalues", reduceDPValuesDeltaPass)                            \
     DELTA_PASS("metadata", reduceMetadataDeltaPass)                            \
     DELTA_PASS("named-metadata", reduceNamedMetadataDeltaPass)                 \
     DELTA_PASS("arguments", reduceArgumentsDeltaPass)                          \
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.cpp b/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
index 3085208..3532167 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
@@ -19,8 +19,10 @@
 #include "llvm/CodeGen/MachineFrameInfo.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/PseudoSourceValueManager.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Instructions.h"
@@ -153,6 +155,23 @@
   }
 }
 
+static void cloneJumpTableInfo(
+    MachineFunction &DstMF, const MachineJumpTableInfo &SrcJTI,
+    const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) {
+
+  auto *DstJTI = DstMF.getOrCreateJumpTableInfo(SrcJTI.getEntryKind());
+
+  std::vector<MachineBasicBlock *> DstBBs;
+
+  for (const MachineJumpTableEntry &Entry : SrcJTI.getJumpTables()) {
+    for (MachineBasicBlock *X : Entry.MBBs)
+      DstBBs.push_back(Src2DstMBB.find(X)->second);
+
+    DstJTI->createJumpTableIndex(DstBBs);
+    DstBBs.clear();
+  }
+}
+
 static void cloneMemOperands(MachineInstr &DstMI, MachineInstr &SrcMI,
                              MachineFunction &SrcMF, MachineFunction &DstMF) {
   // The new MachineMemOperands should be owned by the new function's
@@ -225,6 +244,8 @@
         DstMF->CreateMachineBasicBlock(SrcMBB.getBasicBlock());
     Src2DstMBB[&SrcMBB] = DstMBB;
 
+    DstMBB->setCallFrameSize(SrcMBB.getCallFrameSize());
+
     if (SrcMBB.isIRBlockAddressTaken())
       DstMBB->setAddressTakenIRBlock(SrcMBB.getAddressTakenIRBlock());
     if (SrcMBB.isMachineBlockAddressTaken())
@@ -264,6 +285,10 @@
   // Copy stack objects and other info
   cloneFrameInfo(DstMFI, SrcMFI, Src2DstMBB);
 
+  if (MachineJumpTableInfo *SrcJTI = SrcMF->getJumpTableInfo()) {
+    cloneJumpTableInfo(*DstMF, *SrcJTI, Src2DstMBB);
+  }
+
   // Remap the debug info frame index references.
   DstMF->VariableDbgInfos = SrcMF->VariableDbgInfos;
 
@@ -762,31 +787,17 @@
 
     auto SetDataLayout = [&](StringRef DataLayoutTargetTriple,
                              StringRef OldDLStr) -> std::optional<std::string> {
-      // If we are supposed to override the target triple, do so now.
+      // NB: We always call createTargetMachineForTriple() even if an explicit
+      // DataLayout is already set in the module since we want to use this
+      // callback to setup the TargetMachine rather than doing it later.
       std::string IRTargetTriple = DataLayoutTargetTriple.str();
       if (!TargetTriple.empty())
         IRTargetTriple = Triple::normalize(TargetTriple);
       TheTriple = Triple(IRTargetTriple);
       if (TheTriple.getTriple().empty())
         TheTriple.setTriple(sys::getDefaultTargetTriple());
-
-      std::string Error;
-      const Target *TheTarget =
-          TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error);
-      if (!TheTarget) {
-        WithColor::error(errs(), ToolName) << Error;
-        exit(1);
-      }
-
-      // Hopefully the MIR parsing doesn't depend on any options.
-      TargetOptions Options;
-      std::optional<Reloc::Model> RM = codegen::getExplicitRelocModel();
-      std::string CPUStr = codegen::getCPUStr();
-      std::string FeaturesStr = codegen::getFeaturesStr();
-      TM = std::unique_ptr<TargetMachine>(TheTarget->createTargetMachine(
-          TheTriple.getTriple(), CPUStr, FeaturesStr, Options, RM,
-          codegen::getExplicitCodeModel(), CodeGenOpt::Default));
-      assert(TM && "Could not allocate target machine!");
+      ExitOnError ExitOnErr(std::string(ToolName) + ": error: ");
+      TM = ExitOnErr(codegen::createTargetMachineForTriple(TheTriple.str()));
 
       return TM->createDataLayout().getStringRepresentation();
     };
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h b/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h
index 136cd80..16d3dcd 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h
@@ -10,7 +10,6 @@
 #define LLVM_TOOLS_LLVM_REDUCE_TESTRUNNER_H
 
 #include "ReducerWorkItem.h"
-#include "llvm/ADT/SmallString.h"
 #include "llvm/IR/Module.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.cpp
index 46bc93c..62dfd62 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.cpp
@@ -29,7 +29,6 @@
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/Support/ThreadPool.h"
 #include <fstream>
-#include <set>
 
 using namespace llvm;
 
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.h
index 5b60ea6..96fcea8 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.h
@@ -17,11 +17,9 @@
 
 #include "ReducerWorkItem.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/ScopeExit.h"
 #include "llvm/Support/raw_ostream.h"
 #include <functional>
 #include <utility>
-#include <vector>
 
 namespace llvm {
 
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp
index d3572e2..5b1363d 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp
@@ -113,7 +113,7 @@
     replaceFunctionCalls(*F, *ClonedFunc, ArgIndexesToKeep);
     // Rename Cloned Function to Old's name
     std::string FName = std::string(F->getName());
-    F->replaceAllUsesWith(ConstantExpr::getBitCast(ClonedFunc, F->getType()));
+    F->replaceAllUsesWith(ClonedFunc);
     F->eraseFromParent();
     ClonedFunc->setName(FName);
   }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp
index df87ce7..e643fe2 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp
@@ -15,11 +15,9 @@
 #include "Delta.h"
 #include "TestRunner.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/iterator_range.h"
 #include "llvm/IR/Attributes.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/GlobalVariable.h"
@@ -32,7 +30,6 @@
 #include <cassert>
 #include <iterator>
 #include <utility>
-#include <vector>
 
 namespace llvm {
 class LLVMContext;
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDIMetadata.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDIMetadata.cpp
index bbd928a..f4d8496 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDIMetadata.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDIMetadata.cpp
@@ -15,12 +15,9 @@
 #include "Delta.h"
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/SetVector.h"
-#include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/IR/InstIterator.h"
-#include <set>
-#include <stack>
 #include <tuple>
 #include <vector>
 
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDPValues.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDPValues.cpp
new file mode 100644
index 0000000..8f5bafd
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDPValues.cpp
@@ -0,0 +1,39 @@
+//===- ReduceDPValues.cpp - Specialized Delta Pass ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a function which calls the Generic Delta pass in order
+// to reduce uninteresting DPValues from defined functions.
+//
+// DPValues store variable-location debug-info and are attached to instructions.
+// This information used to be represented by intrinsics such as dbg.value, and
+// would naturally get reduced by llvm-reduce like any other instruction. As
+// DPValues get stored elsewhere, they need to be enumerated and eliminated like
+// any other data structure in LLVM.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceDPValues.h"
+#include "Utils.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace llvm;
+
+static void extractDPValuesFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &M = WorkItem.getModule();
+
+  for (auto &F : M)
+    for (auto &BB : F)
+      for (auto &I : BB)
+        for (DPValue &DPV : llvm::make_early_inc_range(I.getDbgValueRange()))
+          if (!O.shouldKeep())
+            DPV.eraseFromParent();
+}
+
+void llvm::reduceDPValuesDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, extractDPValuesFromModule, "Reducing DPValues");
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDPValues.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDPValues.h
new file mode 100644
index 0000000..34ebd27
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDPValues.h
@@ -0,0 +1,25 @@
+//===- ReduceDPValues.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a function which calls the Generic Delta pass in order
+// to reduce uninteresting DPValues from defined functions.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEDPVALUES_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEDPVALUES_H
+
+#include "Delta.h"
+#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/DebugProgramInstruction.h"
+
+namespace llvm {
+void reduceDPValuesDeltaPass(TestRunner &Test);
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp
index 05127ec..619811c 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp
@@ -16,10 +16,8 @@
 #include "Delta.h"
 #include "Utils.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SetVector.h"
 #include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <iterator>
-#include <vector>
 
 using namespace llvm;
 
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp
index c73e74e..7b6fe7e 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp
@@ -30,6 +30,12 @@
       } else if (auto *PE = dyn_cast<PossiblyExactOperator>(&I)) {
         if (PE->isExact() && !O.shouldKeep())
           I.setIsExact(false);
+      } else if (auto *NNI = dyn_cast<PossiblyNonNegInst>(&I)) {
+        if (NNI->hasNonNeg() && !O.shouldKeep())
+          NNI->setNonNeg(false);
+      } else if (auto *PDI = dyn_cast<PossiblyDisjointInst>(&I)) {
+        if (PDI->isDisjoint() && !O.shouldKeep())
+          PDI->setIsDisjoint(false);
       } else if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
         if (GEP->isInBounds() && !O.shouldKeep())
           GEP->setIsInBounds(false);
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp
index d491858..30bf612 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp
@@ -17,7 +17,6 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/IntrinsicInst.h"
-#include <vector>
 
 using namespace llvm;
 
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOpcodes.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOpcodes.cpp
index 93992303..f8fa83e 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOpcodes.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOpcodes.cpp
@@ -114,12 +114,6 @@
     PtrArg = ConstantPointerNull::get(PtrTy);
   }
 
-  // Make sure we don't emit an invalid store with typed pointers.
-  if (IsStore && DataArg->getType()->getPointerTo(
-        cast<PointerType>(PtrArg->getType())->getAddressSpace()) !=
-      PtrArg->getType())
-    return false;
-
   return true;
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp
index 6f9cafb..a211b6a 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp
@@ -18,7 +18,6 @@
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Sequence.h"
-#include "llvm/ADT/iterator_range.h"
 #include "llvm/IR/InstVisitor.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/Support/raw_ostream.h"
@@ -55,7 +54,7 @@
     OperandBundlesToKeepIndexes.reserve(Call.getNumOperandBundles());
 
     // Enumerate every operand bundle on this call.
-    for (unsigned BundleIndex : seq(0U, Call.getNumOperandBundles()))
+    for (unsigned BundleIndex : seq(Call.getNumOperandBundles()))
       if (O.shouldKeep()) // Should we keep this one?
         OperandBundlesToKeepIndexes.emplace_back(BundleIndex);
   }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsSkip.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsSkip.cpp
index 52679f8..1763fee 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsSkip.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsSkip.cpp
@@ -14,6 +14,7 @@
 #include "llvm/IR/InstIterator.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Operator.h"
+#include <queue>
 
 using namespace llvm;
 
@@ -149,13 +150,13 @@
 
       // Regardless whether referenced, add the function arguments as
       // replacement possibility with the goal of reducing the number of (used)
-      // function arguments, possibly created by the the operands-to-args.
+      // function arguments, possibly created by the operands-to-args.
       for (Argument &Arg : F.args())
         ReferencedVals.insert(&Arg);
 
       // After all candidates have been added, it doesn't need to be a set
       // anymore.
-      std::vector<Value *> Candidates = ReferencedVals.takeVector();
+      auto Candidates = ReferencedVals.takeVector();
 
       // Remove ineligible candidates.
       llvm::erase_if(Candidates, [&, OpVal](Value *V) {
@@ -185,7 +186,7 @@
       std::reverse(Candidates.begin(), Candidates.end());
 
       // Independency of collectReferencedValues's idea of reductive power,
-      // ensure the the partial order of IsMoreReduced is enforced.
+      // ensure the partial order of IsMoreReduced is enforced.
       llvm::stable_sort(Candidates, IsMoreReduced);
 
       Callback(Op, Candidates);
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp
index 0f949ab..a04f354 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp
@@ -160,7 +160,14 @@
   for (Use *Op : OpsToReplace) {
     Value *NewArg = OldValMap.lookup(Op->get());
     auto *NewUser = cast<Instruction>(VMap.lookup(Op->getUser()));
-    NewUser->setOperand(Op->getOperandNo(), NewArg);
+
+    if (PHINode *NewPhi = dyn_cast<PHINode>(NewUser)) {
+      PHINode *OldPhi = cast<PHINode>(Op->getUser());
+      BasicBlock *OldBB = OldPhi->getIncomingBlock(*Op);
+      NewPhi->setIncomingValueForBlock(cast<BasicBlock>(VMap.lookup(OldBB)),
+                                       NewArg);
+    } else
+      NewUser->setOperand(Op->getOperandNo(), NewArg);
   }
 
   // Replace all OldF uses with NewF.
@@ -168,7 +175,7 @@
 
   // Rename NewF to OldF's name.
   std::string FName = OldF->getName().str();
-  OldF->replaceAllUsesWith(ConstantExpr::getBitCast(NewF, OldF->getType()));
+  OldF->replaceAllUsesWith(NewF);
   OldF->eraseFromParent();
   NewF->setName(FName);
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/StripDebugInfo.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/StripDebugInfo.cpp
index a65e55d..c9e1261 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/StripDebugInfo.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/StripDebugInfo.cpp
@@ -18,7 +18,7 @@
 static void stripDebugInfoImpl(Oracle &O, ReducerWorkItem &WorkItem) {
   Module &Program = WorkItem.getModule();
   bool HasDebugInfo = any_of(Program.named_metadata(), [](NamedMDNode &NMD) {
-    return NMD.getName().startswith("llvm.dbg.");
+    return NMD.getName().starts_with("llvm.dbg.");
   });
   if (HasDebugInfo && !O.shouldKeep())
     StripDebugInfo(Program);
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/llvm-reduce.cpp b/src/llvm-project/llvm/tools/llvm-reduce/llvm-reduce.cpp
index ace5c95..71ce0ca 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/llvm-reduce.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/llvm-reduce.cpp
@@ -26,7 +26,6 @@
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 #include <system_error>
-#include <vector>
 
 #ifdef _WIN32
 #include <windows.h>
@@ -101,6 +100,13 @@
                                "of delta passes (default=5)"),
                       cl::init(5), cl::cat(LLVMReduceOptions));
 
+static cl::opt<bool> TryUseNewDbgInfoFormat(
+    "try-experimental-debuginfo-iterators",
+    cl::desc("Enable debuginfo iterator positions, if they're built in"),
+    cl::init(false));
+
+extern cl::opt<bool> UseNewDbgInfoFormat;
+
 static codegen::RegisterCodeGenFlags CGF;
 
 /// Turn off crash debugging features
@@ -144,6 +150,17 @@
   cl::HideUnrelatedOptions({&LLVMReduceOptions, &getColorCategory()});
   cl::ParseCommandLineOptions(Argc, Argv, "LLVM automatic testcase reducer.\n");
 
+  // RemoveDIs debug-info transition: tests may request that we /try/ to use the
+  // new debug-info format, if it's built in.
+#ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
+  if (TryUseNewDbgInfoFormat) {
+    // If LLVM was built with support for this, turn the new debug-info format
+    // on.
+    UseNewDbgInfoFormat = true;
+  }
+#endif
+  (void)TryUseNewDbgInfoFormat;
+
   if (Argc == 1) {
     cl::PrintHelpMessage();
     return 0;
@@ -158,7 +175,7 @@
   if (InputLanguage != InputLanguages::None) {
     if (InputLanguage == InputLanguages::MIR)
       ReduceModeMIR = true;
-  } else if (StringRef(InputFilename).endswith(".mir")) {
+  } else if (StringRef(InputFilename).ends_with(".mir")) {
     ReduceModeMIR = true;
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-remark-size-diff/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-remark-size-diff/CMakeLists.txt
deleted file mode 100644
index 7e6f007..0000000
--- a/src/llvm-project/llvm/tools/llvm-remark-size-diff/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-set(LLVM_LINK_COMPONENTS
-  Demangle
-  Remarks
-  Support
-  )
-
-add_llvm_tool(llvm-remark-size-diff
-  RemarkSizeDiff.cpp
-  )
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-remarkutil/CMakeLists.txt
index bf044d2..48aeb93 100644
--- a/src/llvm-project/llvm/tools/llvm-remarkutil/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/CMakeLists.txt
@@ -5,5 +5,11 @@
   )
 
 add_llvm_tool(llvm-remarkutil
+  RemarkConvert.cpp
+  RemarkCount.cpp
+  RemarkCounter.cpp
+  RemarkSizeDiff.cpp
   RemarkUtil.cpp
+  RemarkUtilHelpers.cpp
+  RemarkUtilRegistry.cpp
   )
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkConvert.cpp b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkConvert.cpp
new file mode 100644
index 0000000..35d8dcd
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkConvert.cpp
@@ -0,0 +1,143 @@
+//===- RemarkConvert.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Convert remarks from bitstream to yaml and the other way around.
+//
+//===----------------------------------------------------------------------===//
+
+#include "RemarkUtilHelpers.h"
+#include "RemarkUtilRegistry.h"
+
+using namespace llvm;
+using namespace remarks;
+using namespace llvm::remarkutil;
+
+extern ExitOnError ExitOnErr;
+static cl::SubCommand
+    YAML2Bitstream("yaml2bitstream",
+                   "Convert YAML remarks to bitstream remarks");
+static cl::SubCommand
+    Bitstream2YAML("bitstream2yaml",
+                   "Convert bitstream remarks to YAML remarks");
+
+namespace yaml2bitstream {
+/// Remark format to parse.
+static constexpr Format InputFormat = Format::YAML;
+/// Remark format to output.
+static constexpr Format OutputFormat = Format::Bitstream;
+INPUT_OUTPUT_COMMAND_LINE_OPTIONS(YAML2Bitstream)
+} // namespace yaml2bitstream
+
+namespace bitstream2yaml {
+/// Remark format to parse.
+static constexpr Format InputFormat = Format::Bitstream;
+/// Remark format to output.
+static constexpr Format OutputFormat = Format::YAML;
+INPUT_OUTPUT_COMMAND_LINE_OPTIONS(Bitstream2YAML)
+} // namespace bitstream2yaml
+
+namespace yaml2bitstream {
+/// Parses all remarks in the input YAML file.
+/// \p [out] ParsedRemarks - Filled with remarks parsed from the input file.
+/// \p [out] StrTab - A string table populated for later remark serialization.
+/// \returns Error::success() if all remarks were successfully parsed, and an
+/// Error otherwise.
+static Error
+tryParseRemarksFromYAMLFile(std::vector<std::unique_ptr<Remark>> &ParsedRemarks,
+                            StringTable &StrTab) {
+  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
+  if (!MaybeBuf)
+    return MaybeBuf.takeError();
+  auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
+  if (!MaybeParser)
+    return MaybeParser.takeError();
+  auto &Parser = **MaybeParser;
+  auto MaybeRemark = Parser.next();
+  for (; MaybeRemark; MaybeRemark = Parser.next()) {
+    StrTab.internalize(**MaybeRemark);
+    ParsedRemarks.push_back(std::move(*MaybeRemark));
+  }
+  auto E = MaybeRemark.takeError();
+  if (!E.isA<EndOfFileError>())
+    return E;
+  consumeError(std::move(E));
+  return Error::success();
+}
+
+/// Reserialize a list of parsed YAML remarks into bitstream remarks.
+/// \p ParsedRemarks - A list of remarks.
+/// \p StrTab - The string table for the remarks.
+/// \returns Error::success() on success.
+static Error tryReserializeYAML2Bitstream(
+    const std::vector<std::unique_ptr<Remark>> &ParsedRemarks,
+    StringTable &StrTab) {
+  auto MaybeOF = getOutputFileForRemarks(OutputFileName, OutputFormat);
+  if (!MaybeOF)
+    return MaybeOF.takeError();
+  auto OF = std::move(*MaybeOF);
+  auto MaybeSerializer = createRemarkSerializer(
+      OutputFormat, SerializerMode::Standalone, OF->os(), std::move(StrTab));
+  if (!MaybeSerializer)
+    return MaybeSerializer.takeError();
+  auto Serializer = std::move(*MaybeSerializer);
+  for (const auto &Remark : ParsedRemarks)
+    Serializer->emit(*Remark);
+  OF->keep();
+  return Error::success();
+}
+
+/// Parse YAML remarks and reserialize as bitstream remarks.
+/// \returns Error::success() on success, and an Error otherwise.
+static Error tryYAML2Bitstream() {
+  StringTable StrTab;
+  std::vector<std::unique_ptr<Remark>> ParsedRemarks;
+  ExitOnErr(tryParseRemarksFromYAMLFile(ParsedRemarks, StrTab));
+  return tryReserializeYAML2Bitstream(ParsedRemarks, StrTab);
+}
+} // namespace yaml2bitstream
+
+namespace bitstream2yaml {
+/// Parse bitstream remarks and reserialize as YAML remarks.
+/// \returns An Error if reserialization fails, or Error::success() on success.
+static Error tryBitstream2YAML() {
+  // Create the serializer.
+  auto MaybeOF = getOutputFileForRemarks(OutputFileName, OutputFormat);
+  if (!MaybeOF)
+    return MaybeOF.takeError();
+  auto OF = std::move(*MaybeOF);
+  auto MaybeSerializer = createRemarkSerializer(
+      OutputFormat, SerializerMode::Standalone, OF->os());
+  if (!MaybeSerializer)
+    return MaybeSerializer.takeError();
+
+  // Create the parser.
+  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
+  if (!MaybeBuf)
+    return MaybeBuf.takeError();
+  auto Serializer = std::move(*MaybeSerializer);
+  auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
+  if (!MaybeParser)
+    return MaybeParser.takeError();
+  auto &Parser = **MaybeParser;
+
+  // Parse + reserialize all remarks.
+  auto MaybeRemark = Parser.next();
+  for (; MaybeRemark; MaybeRemark = Parser.next())
+    Serializer->emit(**MaybeRemark);
+  auto E = MaybeRemark.takeError();
+  if (!E.isA<EndOfFileError>())
+    return E;
+  consumeError(std::move(E));
+  return Error::success();
+}
+} // namespace bitstream2yaml
+
+static CommandRegistration Bitstream2YamlReg(&Bitstream2YAML,
+                                             bitstream2yaml::tryBitstream2YAML);
+static CommandRegistration Yaml2Bitstream(&YAML2Bitstream,
+                                          yaml2bitstream::tryYAML2Bitstream);
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkCount.cpp b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkCount.cpp
new file mode 100644
index 0000000..d08f47f
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkCount.cpp
@@ -0,0 +1,159 @@
+//===- RemarkCount.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Count remarks using `instruction-count` for asm-printer remarks and
+// `annotation-count` for annotation-remarks
+//
+//===----------------------------------------------------------------------===//
+#include "RemarkUtilHelpers.h"
+#include "RemarkUtilRegistry.h"
+
+using namespace llvm;
+using namespace remarks;
+using namespace llvm::remarkutil;
+
+static cl::SubCommand InstructionCount(
+    "instruction-count",
+    "Function instruction count information (requires asm-printer remarks)");
+static cl::SubCommand
+    AnnotationCount("annotation-count",
+                    "Collect count information from annotation remarks (uses "
+                    "AnnotationRemarksPass)");
+
+namespace instructioncount {
+INPUT_FORMAT_COMMAND_LINE_OPTIONS(InstructionCount)
+INPUT_OUTPUT_COMMAND_LINE_OPTIONS(InstructionCount)
+DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(InstructionCount)
+} // namespace instructioncount
+
+namespace annotationcount {
+INPUT_FORMAT_COMMAND_LINE_OPTIONS(AnnotationCount)
+static cl::opt<std::string> AnnotationTypeToCollect(
+    "annotation-type", cl::desc("annotation-type remark to collect count for"),
+    cl::sub(AnnotationCount));
+INPUT_OUTPUT_COMMAND_LINE_OPTIONS(AnnotationCount)
+DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(AnnotationCount)
+} // namespace annotationcount
+
+static bool shouldSkipRemark(bool UseDebugLoc, Remark &Remark) {
+  return UseDebugLoc && !Remark.Loc.has_value();
+}
+
+namespace instructioncount {
+/// Outputs all instruction count remarks in the file as a CSV.
+/// \returns Error::success() on success, and an Error otherwise.
+static Error tryInstructionCount() {
+  // Create the output buffer.
+  auto MaybeOF = getOutputFileWithFlags(OutputFileName,
+                                        /*Flags = */ sys::fs::OF_TextWithCRLF);
+  if (!MaybeOF)
+    return MaybeOF.takeError();
+  auto OF = std::move(*MaybeOF);
+  // Create a parser for the user-specified input format.
+  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
+  if (!MaybeBuf)
+    return MaybeBuf.takeError();
+  auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
+  if (!MaybeParser)
+    return MaybeParser.takeError();
+  // Emit CSV header.
+  if (UseDebugLoc)
+    OF->os() << "Source,";
+  OF->os() << "Function,InstructionCount\n";
+  // Parse all remarks. Whenever we see an instruction count remark, output
+  // the file name and the number of instructions.
+  auto &Parser = **MaybeParser;
+  auto MaybeRemark = Parser.next();
+  for (; MaybeRemark; MaybeRemark = Parser.next()) {
+    auto &Remark = **MaybeRemark;
+    if (Remark.RemarkName != "InstructionCount")
+      continue;
+    if (shouldSkipRemark(UseDebugLoc, Remark))
+      continue;
+    auto *InstrCountArg = find_if(Remark.Args, [](const Argument &Arg) {
+      return Arg.Key == "NumInstructions";
+    });
+    assert(InstrCountArg != Remark.Args.end() &&
+           "Expected instruction count remarks to have a NumInstructions key?");
+    if (UseDebugLoc) {
+      std::string Loc = Remark.Loc->SourceFilePath.str() + ":" +
+                        std::to_string(Remark.Loc->SourceLine) + +":" +
+                        std::to_string(Remark.Loc->SourceColumn);
+      OF->os() << Loc << ",";
+    }
+    OF->os() << Remark.FunctionName << "," << InstrCountArg->Val << "\n";
+  }
+  auto E = MaybeRemark.takeError();
+  if (!E.isA<EndOfFileError>())
+    return E;
+  consumeError(std::move(E));
+  OF->keep();
+  return Error::success();
+}
+} // namespace instructioncount
+
+namespace annotationcount {
+static Error tryAnnotationCount() {
+  // Create the output buffer.
+  auto MaybeOF = getOutputFileWithFlags(OutputFileName,
+                                        /*Flags = */ sys::fs::OF_TextWithCRLF);
+  if (!MaybeOF)
+    return MaybeOF.takeError();
+  auto OF = std::move(*MaybeOF);
+  // Create a parser for the user-specified input format.
+  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
+  if (!MaybeBuf)
+    return MaybeBuf.takeError();
+  auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
+  if (!MaybeParser)
+    return MaybeParser.takeError();
+  // Emit CSV header.
+  if (UseDebugLoc)
+    OF->os() << "Source,";
+  OF->os() << "Function,Count\n";
+  // Parse all remarks. When we see the specified remark collect the count
+  // information.
+  auto &Parser = **MaybeParser;
+  auto MaybeRemark = Parser.next();
+  for (; MaybeRemark; MaybeRemark = Parser.next()) {
+    auto &Remark = **MaybeRemark;
+    if (Remark.RemarkName != "AnnotationSummary")
+      continue;
+    if (shouldSkipRemark(UseDebugLoc, Remark))
+      continue;
+    auto *RemarkNameArg = find_if(Remark.Args, [](const Argument &Arg) {
+      return Arg.Key == "type" && Arg.Val == AnnotationTypeToCollect;
+    });
+    if (RemarkNameArg == Remark.Args.end())
+      continue;
+    auto *CountArg = find_if(
+        Remark.Args, [](const Argument &Arg) { return Arg.Key == "count"; });
+    assert(CountArg != Remark.Args.end() &&
+           "Expected annotation-type remark to have a count key?");
+    if (UseDebugLoc) {
+      std::string Loc = Remark.Loc->SourceFilePath.str() + ":" +
+                        std::to_string(Remark.Loc->SourceLine) + +":" +
+                        std::to_string(Remark.Loc->SourceColumn);
+      OF->os() << Loc << ",";
+    }
+    OF->os() << Remark.FunctionName << "," << CountArg->Val << "\n";
+  }
+  auto E = MaybeRemark.takeError();
+  if (!E.isA<EndOfFileError>())
+    return E;
+  consumeError(std::move(E));
+  OF->keep();
+  return Error::success();
+}
+} // namespace annotationcount
+
+static CommandRegistration
+    InstructionCountReg(&InstructionCount,
+                        instructioncount::tryInstructionCount);
+static CommandRegistration Yaml2Bitstream(&AnnotationCount,
+                                          annotationcount::tryAnnotationCount);
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkCounter.cpp b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
new file mode 100644
index 0000000..dc0685f
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkCounter.cpp
@@ -0,0 +1,337 @@
+//===- RemarkCounter.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic tool to count remarks based on properties
+//
+//===----------------------------------------------------------------------===//
+
+#include "RemarkCounter.h"
+#include "RemarkUtilRegistry.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Regex.h"
+
+using namespace llvm;
+using namespace remarks;
+using namespace llvm::remarkutil;
+
+static cl::SubCommand CountSub("count",
+                               "Collect remarks based on specified criteria.");
+
+INPUT_FORMAT_COMMAND_LINE_OPTIONS(CountSub)
+INPUT_OUTPUT_COMMAND_LINE_OPTIONS(CountSub)
+
+static cl::list<std::string>
+    Keys("args", cl::desc("Specify remark argument/s to count by."),
+         cl::value_desc("arguments"), cl::sub(CountSub), cl::ValueOptional);
+static cl::list<std::string> RKeys(
+    "rargs",
+    cl::desc(
+        "Specify remark argument/s to count (accepts regular expressions)."),
+    cl::value_desc("arguments"), cl::sub(CountSub), cl::ValueOptional);
+static cl::opt<std::string>
+    RemarkNameOpt("remark-name",
+                  cl::desc("Optional remark name to filter collection by."),
+                  cl::ValueOptional, cl::sub(CountSub));
+static cl::opt<std::string>
+    PassNameOpt("pass-name", cl::ValueOptional,
+                cl::desc("Optional remark pass name to filter collection by."),
+                cl::sub(CountSub));
+
+static cl::opt<std::string> RemarkFilterArgByOpt(
+    "filter-arg-by", cl::desc("Optional remark arg to filter collection by."),
+    cl::ValueOptional, cl::sub(CountSub));
+static cl::opt<std::string>
+    RemarkNameOptRE("rremark-name",
+                    cl::desc("Optional remark name to filter collection by "
+                             "(accepts regular expressions)."),
+                    cl::ValueOptional, cl::sub(CountSub));
+static cl::opt<std::string>
+    RemarkArgFilterOptRE("rfilter-arg-by",
+                         cl::desc("Optional remark arg to filter collection by "
+                                  "(accepts regular expressions)."),
+                         cl::sub(CountSub), cl::ValueOptional);
+static cl::opt<std::string>
+    PassNameOptRE("rpass-name", cl::ValueOptional,
+                  cl::desc("Optional remark pass name to filter collection "
+                           "by (accepts regular expressions)."),
+                  cl::sub(CountSub));
+static cl::opt<Type> RemarkTypeOpt(
+    "remark-type", cl::desc("Optional remark type to filter collection by."),
+    cl::values(clEnumValN(Type::Unknown, "unknown", "UNKOWN"),
+               clEnumValN(Type::Passed, "passed", "PASSED"),
+               clEnumValN(Type::Missed, "missed", "MISSED"),
+               clEnumValN(Type::Analysis, "analysis", "ANALYSIS"),
+               clEnumValN(Type::AnalysisFPCommute, "analysis-fp-commute",
+                          "ANALYSIS_FP_COMMUTE"),
+               clEnumValN(Type::AnalysisAliasing, "analysis-aliasing",
+                          "ANALYSIS_ALIASING"),
+               clEnumValN(Type::Failure, "failure", "FAILURE")),
+    cl::init(Type::Failure), cl::sub(CountSub));
+static cl::opt<CountBy> CountByOpt(
+    "count-by", cl::desc("Specify the property to collect remarks by."),
+    cl::values(
+        clEnumValN(CountBy::REMARK, "remark-name",
+                   "Counts individual remarks based on how many of the remark "
+                   "exists."),
+        clEnumValN(CountBy::ARGUMENT, "arg",
+                   "Counts based on the value each specified argument has. The "
+                   "argument has to have a number value to be considered.")),
+    cl::init(CountBy::REMARK), cl::sub(CountSub));
+static cl::opt<GroupBy> GroupByOpt(
+    "group-by", cl::desc("Specify the property to group remarks by."),
+    cl::values(
+        clEnumValN(
+            GroupBy::PER_SOURCE, "source",
+            "Display the count broken down by the filepath of each remark "
+            "emitted. Requires remarks to have DebugLoc information."),
+        clEnumValN(GroupBy::PER_FUNCTION, "function",
+                   "Breakdown the count by function name."),
+        clEnumValN(
+            GroupBy::PER_FUNCTION_WITH_DEBUG_LOC, "function-with-loc",
+            "Breakdown the count by function name taking into consideration "
+            "the filepath info from the DebugLoc of the remark."),
+        clEnumValN(GroupBy::TOTAL, "total",
+                   "Output the total number corresponding to the count for the "
+                   "provided input file.")),
+    cl::init(GroupBy::PER_SOURCE), cl::sub(CountSub));
+
+/// Look for matching argument with \p Key in \p Remark and return the parsed
+/// integer value or 0 if it is has no integer value.
+static unsigned getValForKey(StringRef Key, const Remark &Remark) {
+  auto *RemarkArg = find_if(Remark.Args, [&Key](const Argument &Arg) {
+    return Arg.Key == Key && Arg.isValInt();
+  });
+  if (RemarkArg == Remark.Args.end())
+    return 0;
+  return *RemarkArg->getValAsInt();
+}
+
+Error Filters::regexArgumentsValid() {
+  if (RemarkNameFilter && RemarkNameFilter->IsRegex)
+    if (auto E = checkRegex(RemarkNameFilter->FilterRE))
+      return E;
+  if (PassNameFilter && PassNameFilter->IsRegex)
+    if (auto E = checkRegex(PassNameFilter->FilterRE))
+      return E;
+  if (ArgFilter && ArgFilter->IsRegex)
+    if (auto E = checkRegex(ArgFilter->FilterRE))
+      return E;
+  return Error::success();
+}
+
+bool Filters::filterRemark(const Remark &Remark) {
+  if (RemarkNameFilter && !RemarkNameFilter->match(Remark.RemarkName))
+    return false;
+  if (PassNameFilter && !PassNameFilter->match(Remark.PassName))
+    return false;
+  if (RemarkTypeFilter)
+    return *RemarkTypeFilter == Remark.RemarkType;
+  if (ArgFilter) {
+    if (!any_of(Remark.Args,
+                [this](Argument Arg) { return ArgFilter->match(Arg.Val); }))
+      return false;
+  }
+  return true;
+}
+
+Error ArgumentCounter::getAllMatchingArgumentsInRemark(
+    StringRef Buffer, ArrayRef<FilterMatcher> Arguments, Filters &Filter) {
+  auto MaybeParser = createRemarkParser(InputFormat, Buffer);
+  if (!MaybeParser)
+    return MaybeParser.takeError();
+  auto &Parser = **MaybeParser;
+  auto MaybeRemark = Parser.next();
+  for (; MaybeRemark; MaybeRemark = Parser.next()) {
+    auto &Remark = **MaybeRemark;
+    // Only collect keys from remarks included in the filter.
+    if (!Filter.filterRemark(Remark))
+      continue;
+    for (auto &Key : Arguments) {
+      for (Argument Arg : Remark.Args)
+        if (Key.match(Arg.Key) && Arg.isValInt())
+          ArgumentSetIdxMap.insert({Arg.Key, ArgumentSetIdxMap.size()});
+    }
+  }
+
+  auto E = MaybeRemark.takeError();
+  if (!E.isA<EndOfFileError>())
+    return E;
+  consumeError(std::move(E));
+  return Error::success();
+}
+
+std::optional<std::string> Counter::getGroupByKey(const Remark &Remark) {
+  switch (Group) {
+  case GroupBy::PER_FUNCTION:
+    return Remark.FunctionName.str();
+  case GroupBy::TOTAL:
+    return "Total";
+  case GroupBy::PER_SOURCE:
+  case GroupBy::PER_FUNCTION_WITH_DEBUG_LOC:
+    if (!Remark.Loc.has_value())
+      return std::nullopt;
+
+    if (Group == GroupBy::PER_FUNCTION_WITH_DEBUG_LOC)
+      return Remark.Loc->SourceFilePath.str() + ":" + Remark.FunctionName.str();
+    return Remark.Loc->SourceFilePath.str();
+  }
+  llvm_unreachable("Fully covered switch above!");
+}
+
+void ArgumentCounter::collect(const Remark &Remark) {
+  SmallVector<unsigned, 4> Row(ArgumentSetIdxMap.size());
+  std::optional<std::string> GroupByKey = getGroupByKey(Remark);
+  // Early return if we don't have a value
+  if (!GroupByKey)
+    return;
+  auto GroupVal = *GroupByKey;
+  CountByKeysMap.insert({GroupVal, Row});
+  for (auto [Key, Idx] : ArgumentSetIdxMap) {
+    auto Count = getValForKey(Key, Remark);
+    CountByKeysMap[GroupVal][Idx] += Count;
+  }
+}
+
+void RemarkCounter::collect(const Remark &Remark) {
+  std::optional<std::string> Key = getGroupByKey(Remark);
+  if (!Key.has_value())
+    return;
+  auto Iter = CountedByRemarksMap.insert({*Key, 1});
+  if (!Iter.second)
+    Iter.first->second += 1;
+}
+
+Error ArgumentCounter::print(StringRef OutputFileName) {
+  auto MaybeOF =
+      getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF);
+  if (!MaybeOF)
+    return MaybeOF.takeError();
+
+  auto OF = std::move(*MaybeOF);
+  OF->os() << groupByToStr(Group) << ",";
+  unsigned Idx = 0;
+  for (auto [Key, _] : ArgumentSetIdxMap) {
+    OF->os() << Key;
+    if (Idx != ArgumentSetIdxMap.size() - 1)
+      OF->os() << ",";
+    Idx++;
+  }
+  OF->os() << "\n";
+  for (auto [Header, CountVector] : CountByKeysMap) {
+    OF->os() << Header << ",";
+    unsigned Idx = 0;
+    for (auto Count : CountVector) {
+      OF->os() << Count;
+      if (Idx != ArgumentSetIdxMap.size() - 1)
+        OF->os() << ",";
+      Idx++;
+    }
+    OF->os() << "\n";
+  }
+  return Error::success();
+}
+
+Error RemarkCounter::print(StringRef OutputFileName) {
+  auto MaybeOF =
+      getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF);
+  if (!MaybeOF)
+    return MaybeOF.takeError();
+
+  auto OF = std::move(*MaybeOF);
+  OF->os() << groupByToStr(Group) << ","
+           << "Count\n";
+  for (auto [Key, Count] : CountedByRemarksMap)
+    OF->os() << Key << "," << Count << "\n";
+  OF->keep();
+  return Error::success();
+}
+
+Expected<Filters> getRemarkFilter() {
+  // Create Filter properties.
+  std::optional<FilterMatcher> RemarkNameFilter;
+  std::optional<FilterMatcher> PassNameFilter;
+  std::optional<FilterMatcher> RemarkArgFilter;
+  std::optional<Type> RemarkType;
+  if (!RemarkNameOpt.empty())
+    RemarkNameFilter = {RemarkNameOpt, false};
+  else if (!RemarkNameOptRE.empty())
+    RemarkNameFilter = {RemarkNameOptRE, true};
+  if (!PassNameOpt.empty())
+    PassNameFilter = {PassNameOpt, false};
+  else if (!PassNameOptRE.empty())
+    PassNameFilter = {PassNameOptRE, true};
+  if (RemarkTypeOpt != Type::Failure)
+    RemarkType = RemarkTypeOpt;
+  if (!RemarkFilterArgByOpt.empty())
+    RemarkArgFilter = {RemarkFilterArgByOpt, false};
+  else if (!RemarkArgFilterOptRE.empty())
+    RemarkArgFilter = {RemarkArgFilterOptRE, true};
+  // Create RemarkFilter.
+  return Filters::createRemarkFilter(std::move(RemarkNameFilter),
+                                     std::move(PassNameFilter),
+                                     std::move(RemarkArgFilter), RemarkType);
+}
+
+Error useCollectRemark(StringRef Buffer, Counter &Counter, Filters &Filter) {
+  // Create Parser.
+  auto MaybeParser = createRemarkParser(InputFormat, Buffer);
+  if (!MaybeParser)
+    return MaybeParser.takeError();
+  auto &Parser = **MaybeParser;
+  auto MaybeRemark = Parser.next();
+  for (; MaybeRemark; MaybeRemark = Parser.next()) {
+    const Remark &Remark = **MaybeRemark;
+    if (Filter.filterRemark(Remark))
+      Counter.collect(Remark);
+  }
+
+  if (auto E = Counter.print(OutputFileName))
+    return E;
+  auto E = MaybeRemark.takeError();
+  if (!E.isA<EndOfFileError>())
+    return E;
+  consumeError(std::move(E));
+  return Error::success();
+}
+
+static Error collectRemarks() {
+  // Create a parser for the user-specified input format.
+  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
+  if (!MaybeBuf)
+    return MaybeBuf.takeError();
+  StringRef Buffer = (*MaybeBuf)->getBuffer();
+  auto MaybeFilter = getRemarkFilter();
+  if (!MaybeFilter)
+    return MaybeFilter.takeError();
+  auto &Filter = *MaybeFilter;
+  if (CountByOpt == CountBy::REMARK) {
+    RemarkCounter RC(GroupByOpt);
+    if (auto E = useCollectRemark(Buffer, RC, Filter))
+      return E;
+  } else if (CountByOpt == CountBy::ARGUMENT) {
+    SmallVector<FilterMatcher, 4> ArgumentsVector;
+    if (!Keys.empty()) {
+      for (auto &Key : Keys)
+        ArgumentsVector.push_back({Key, false});
+    } else if (!RKeys.empty())
+      for (auto Key : RKeys)
+        ArgumentsVector.push_back({Key, true});
+    else
+      ArgumentsVector.push_back({".*", true});
+
+    Expected<ArgumentCounter> AC = ArgumentCounter::createArgumentCounter(
+        GroupByOpt, ArgumentsVector, Buffer, Filter);
+    if (!AC)
+      return AC.takeError();
+    if (auto E = useCollectRemark(Buffer, *AC, Filter))
+      return E;
+  }
+  return Error::success();
+}
+
+static CommandRegistration CountReg(&CountSub, collectRemarks);
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkCounter.h b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkCounter.h
new file mode 100644
index 0000000..34d5bff
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkCounter.h
@@ -0,0 +1,215 @@
+//===- RemarkCounter.h ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic tool to count remarks based on properties
+//
+//===----------------------------------------------------------------------===//
+#ifndef TOOLS_LLVM_REMARKCOUNTER_H
+#define TOOLS_LLVM_REMARKCOUNTER_H
+#include "RemarkUtilHelpers.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/Support/Regex.h"
+
+namespace llvm {
+namespace remarks {
+
+/// Collect remarks by counting the existance of a remark or by looking through
+/// the keys and summing through the total count.
+enum class CountBy { REMARK, ARGUMENT };
+
+/// Summarize the count by either emitting one count for the remark file, or
+/// grouping the count by source file or by function name.
+enum class GroupBy {
+  TOTAL,
+  PER_SOURCE,
+  PER_FUNCTION,
+  PER_FUNCTION_WITH_DEBUG_LOC
+};
+
+/// Convert \p GroupBy to a std::string.
+inline std::string groupByToStr(GroupBy GroupBy) {
+  switch (GroupBy) {
+  default:
+    return "Total";
+  case GroupBy::PER_FUNCTION:
+    return "Function";
+  case GroupBy::PER_FUNCTION_WITH_DEBUG_LOC:
+    return "FuctionWithDebugLoc";
+  case GroupBy::PER_SOURCE:
+    return "Source";
+  }
+}
+
+/// Filter object which can be either a string or a regex to match with the
+/// remark properties.
+struct FilterMatcher {
+  Regex FilterRE;
+  std::string FilterStr;
+  bool IsRegex;
+  FilterMatcher(std::string Filter, bool IsRegex) : IsRegex(IsRegex) {
+    if (IsRegex)
+      FilterRE = Regex(Filter);
+    else
+      FilterStr = Filter;
+  }
+
+  bool match(StringRef StringToMatch) const {
+    if (IsRegex)
+      return FilterRE.match(StringToMatch);
+    return FilterStr == StringToMatch.trim().str();
+  }
+};
+
+/// Filter out remarks based on remark properties based on name, pass name,
+/// argument and type.
+struct Filters {
+  std::optional<FilterMatcher> RemarkNameFilter;
+  std::optional<FilterMatcher> PassNameFilter;
+  std::optional<FilterMatcher> ArgFilter;
+  std::optional<Type> RemarkTypeFilter;
+  /// Returns a filter object if all the arguments provided are valid regex
+  /// types otherwise return an error.
+  static Expected<Filters>
+  createRemarkFilter(std::optional<FilterMatcher> RemarkNameFilter,
+                     std::optional<FilterMatcher> PassNameFilter,
+                     std::optional<FilterMatcher> ArgFilter,
+                     std::optional<Type> RemarkTypeFilter) {
+    Filters Filter;
+    Filter.RemarkNameFilter = std::move(RemarkNameFilter);
+    Filter.PassNameFilter = std::move(PassNameFilter);
+    Filter.ArgFilter = std::move(ArgFilter);
+    Filter.RemarkTypeFilter = std::move(RemarkTypeFilter);
+    if (auto E = Filter.regexArgumentsValid())
+      return std::move(E);
+    return std::move(Filter);
+  }
+  /// Returns true if \p Remark satisfies all the provided filters.
+  bool filterRemark(const Remark &Remark);
+
+private:
+  /// Check if arguments can be parsed as valid regex types.
+  Error regexArgumentsValid();
+};
+
+/// Convert Regex string error to an error object.
+inline Error checkRegex(const Regex &Regex) {
+  std::string Error;
+  if (!Regex.isValid(Error))
+    return createStringError(make_error_code(std::errc::invalid_argument),
+                             Twine("Regex: ", Error));
+  return Error::success();
+}
+
+/// Abstract counter class used to define the general required methods for
+/// counting a remark.
+struct Counter {
+  GroupBy Group = GroupBy::TOTAL;
+  Counter() = default;
+  Counter(enum GroupBy GroupBy) : Group(GroupBy) {}
+  /// Obtain the field for collecting remark info based on how we are
+  /// collecting. Remarks are grouped by FunctionName, Source, Source and
+  /// Function or collect by file.
+  std::optional<std::string> getGroupByKey(const Remark &Remark);
+
+  /// Collect count information from \p Remark organized based on \p Group
+  /// property.
+  virtual void collect(const Remark &) = 0;
+  /// Output the final count to the file \p OutputFileName
+  virtual Error print(StringRef OutputFileName) = 0;
+  virtual ~Counter() = default;
+};
+
+/// Count remarks based on the provided \p Keys argument and summing up the
+/// value for each matching key organized by source, function or reporting a
+/// total for the specified remark file.
+/// Reporting count grouped by source:
+///
+///  | source        | key1 | key2 | key3 |
+///  |---------------|------|------|------|
+///  | path/to/file1 | 0    | 1    | 3    |
+///  | path/to/file2 | 1    | 0    | 2    |
+///  | path/to/file3 | 2    | 3    | 1    |
+///
+/// Reporting count grouped by function:
+///
+///  | Function      | key1 | key2 | key3 |
+///  |---------------|------|------|------|
+///  | function1     | 0    | 1    | 3    |
+///  | function2     | 1    | 0    | 2    |
+///  | function3     | 2    | 3    | 1    |
+struct ArgumentCounter : Counter {
+  /// The internal object to keep the count for the remarks. The first argument
+  /// corresponds to the property we are collecting for this can be either a
+  /// source or function. The second argument is a row of integers where each
+  /// item in the row is the count for a specified key.
+  std::map<std::string, SmallVector<unsigned, 4>> CountByKeysMap;
+  /// A set of all the remark argument found in the remark file. The second
+  /// argument is the index of each of those arguments which can be used in
+  /// `CountByKeysMap` to fill count information for that argument.
+  MapVector<StringRef, unsigned> ArgumentSetIdxMap;
+  /// Create an argument counter. If the provided \p Arguments represent a regex
+  /// vector then we need to check that the provided regular expressions are
+  /// valid if not we return an Error.
+  static Expected<ArgumentCounter>
+  createArgumentCounter(GroupBy Group, ArrayRef<FilterMatcher> Arguments,
+                        StringRef Buffer, Filters &Filter) {
+    ArgumentCounter AC;
+    AC.Group = Group;
+    for (auto &Arg : Arguments) {
+      if (Arg.IsRegex) {
+        if (auto E = checkRegex(Arg.FilterRE))
+          return std::move(E);
+      }
+    }
+    if (auto E = AC.getAllMatchingArgumentsInRemark(Buffer, Arguments, Filter))
+      return std::move(E);
+    return AC;
+  }
+
+  /// Update the internal count map based on the remark integer arguments that
+  /// correspond the the user specified argument keys to collect for.
+  void collect(const Remark &) override;
+
+  /// Print a CSV table consisting of an index which is specified by \p
+  /// `Group` and can be a function name, source file name or function name
+  /// with the full source path and columns of user specified remark arguments
+  /// to collect the count for.
+  Error print(StringRef OutputFileName) override;
+
+private:
+  /// collect all the arguments that match the list of \p Arguments provided by
+  /// parsing through \p Buffer of remarks and filling \p ArgumentSetIdxMap
+  /// acting as a row for for all the keys that we are interested in collecting
+  /// information for.
+  Error getAllMatchingArgumentsInRemark(StringRef Buffer,
+                                        ArrayRef<FilterMatcher> Arguments,
+                                        Filters &Filter);
+};
+
+/// Collect remarks based by counting the existance of individual remarks. The
+/// reported table will be structured based on the provided \p Group argument
+/// by reporting count for functions, source or total count for the provided
+/// remark file.
+struct RemarkCounter : Counter {
+  std::map<std::string, unsigned> CountedByRemarksMap;
+  RemarkCounter(GroupBy Group) : Counter(Group) {}
+
+  /// Advance the internal map count broken by \p Group when
+  /// seeing \p Remark.
+  void collect(const Remark &) override;
+
+  /// Print a CSV table consisting of an index which is specified by \p
+  /// `Group` and can be a function name, source file name or function name
+  /// with the full source path and a counts column corresponding to the count
+  /// of each individual remark at th index.
+  Error print(StringRef OutputFileName) override;
+};
+} // namespace remarks
+
+} // namespace llvm
+#endif // TOOLS_LLVM_REMARKCOUNTER_H
diff --git a/src/llvm-project/llvm/tools/llvm-remark-size-diff/RemarkSizeDiff.cpp b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkSizeDiff.cpp
similarity index 86%
rename from src/llvm-project/llvm/tools/llvm-remark-size-diff/RemarkSizeDiff.cpp
rename to src/llvm-project/llvm/tools/llvm-remarkutil/RemarkSizeDiff.cpp
index d97589e..35ea432 100644
--- a/src/llvm-project/llvm/tools/llvm-remark-size-diff/RemarkSizeDiff.cpp
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkSizeDiff.cpp
@@ -1,4 +1,4 @@
-//===-------------- llvm-remark-size-diff/RemarkSizeDiff.cpp --------------===//
+//===-------------- RemarkSizeDiff.cpp ------------------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -14,51 +14,38 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#include "llvm-c/Remarks.h"
-#include "llvm/ADT/STLExtras.h"
+#include "RemarkUtilHelpers.h"
+#include "RemarkUtilRegistry.h"
 #include "llvm/ADT/SmallSet.h"
-#include "llvm/Remarks/Remark.h"
-#include "llvm/Remarks/RemarkParser.h"
-#include "llvm/Remarks/RemarkSerializer.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/JSON.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/ToolOutputFile.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
 
 using namespace llvm;
-
-enum ParserFormatOptions { yaml, bitstream };
+using namespace remarks;
+using namespace remarkutil;
+static cl::SubCommand
+    RemarkSizeDiffUtil("size-diff",
+                       "Diff instruction count and stack size remarks "
+                       "between two remark files");
 enum ReportStyleOptions { human_output, json_output };
-static cl::OptionCategory SizeDiffCategory("llvm-remark-size-diff options");
 static cl::opt<std::string> InputFileNameA(cl::Positional, cl::Required,
-                                           cl::cat(SizeDiffCategory),
+                                           cl::sub(RemarkSizeDiffUtil),
                                            cl::desc("remarks_a"));
 static cl::opt<std::string> InputFileNameB(cl::Positional, cl::Required,
-                                           cl::cat(SizeDiffCategory),
+                                           cl::sub(RemarkSizeDiffUtil),
                                            cl::desc("remarks_b"));
 static cl::opt<std::string> OutputFilename("o", cl::init("-"),
-                                           cl::cat(SizeDiffCategory),
+                                           cl::sub(RemarkSizeDiffUtil),
                                            cl::desc("Output"),
                                            cl::value_desc("file"));
-static cl::opt<ParserFormatOptions>
-    ParserFormat("parser", cl::cat(SizeDiffCategory), cl::init(bitstream),
-                 cl::desc("Set the remark parser format:"),
-                 cl::values(clEnumVal(yaml, "YAML format"),
-                            clEnumVal(bitstream, "Bitstream format")));
+INPUT_FORMAT_COMMAND_LINE_OPTIONS(RemarkSizeDiffUtil)
 static cl::opt<ReportStyleOptions> ReportStyle(
-    "report_style", cl::cat(SizeDiffCategory),
+    "report_style", cl::sub(RemarkSizeDiffUtil),
     cl::init(ReportStyleOptions::human_output),
     cl::desc("Choose the report output format:"),
     cl::values(clEnumValN(human_output, "human", "Human-readable format"),
                clEnumValN(json_output, "json", "JSON format")));
-static cl::opt<bool> PrettyPrint("pretty", cl::cat(SizeDiffCategory),
+static cl::opt<bool> PrettyPrint("pretty", cl::sub(RemarkSizeDiffUtil),
                                  cl::init(false),
                                  cl::desc("Pretty-print JSON"));
 
@@ -300,14 +287,12 @@
 static Error readFileAndProcessRemarks(
     StringRef InputFileName,
     StringMap<InstCountAndStackSize> &FuncNameToSizeInfo) {
-  auto Buf = MemoryBuffer::getFile(InputFileName);
-  if (auto EC = Buf.getError())
-    return createStringError(
-        EC, Twine("Cannot open file '" + InputFileName + "': " + EC.message()));
-  auto MaybeParser = remarks::createRemarkParserFromMeta(
-      ParserFormat == bitstream ? remarks::Format::Bitstream
-                                : remarks::Format::YAML,
-      (*Buf)->getBuffer());
+
+  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
+  if (!MaybeBuf)
+    return MaybeBuf.takeError();
+  auto MaybeParser =
+      createRemarkParserFromMeta(InputFormat, (*MaybeBuf)->getBuffer());
   if (!MaybeParser)
     return MaybeParser.takeError();
   auto &Parser = **MaybeParser;
@@ -340,17 +325,13 @@
 ///
 /// \returns true if readFileAndProcessRemarks returned no errors. False
 /// otherwise.
-static bool tryReadFileAndProcessRemarks(
+static Error tryReadFileAndProcessRemarks(
     StringRef InputFileName,
     StringMap<InstCountAndStackSize> &FuncNameToSizeInfo) {
   if (Error E = readFileAndProcessRemarks(InputFileName, FuncNameToSizeInfo)) {
-    handleAllErrors(std::move(E), [&](const ErrorInfoBase &PE) {
-      PE.log(WithColor::error());
-      errs() << '\n';
-    });
-    return false;
+    return E;
   }
-  return true;
+  return Error::success();
 }
 
 /// Populates \p FuncDiffs with the difference between \p
@@ -489,33 +470,32 @@
 }
 
 /// Boolean wrapper for outputDiff which handles errors.
-static bool
+static Error
 tryOutputAllDiffs(StringRef InputFileNameA, StringRef InputFileNameB,
                   DiffsCategorizedByFilesPresent &DiffsByFilesPresent) {
   if (Error E =
           outputAllDiffs(InputFileNameA, InputFileNameB, DiffsByFilesPresent)) {
-    handleAllErrors(std::move(E), [&](const ErrorInfoBase &PE) {
-      PE.log(WithColor::error());
-      errs() << '\n';
-    });
-    return false;
+    return E;
   }
-  return true;
+  return Error::success();
 }
 
-int main(int argc, const char **argv) {
-  InitLLVM X(argc, argv);
-  cl::HideUnrelatedOptions(SizeDiffCategory);
-  cl::ParseCommandLineOptions(argc, argv,
-                              "Diff instruction count and stack size remarks "
-                              "between two remark files.\n");
+static Error trySizeSiff() {
   StringMap<InstCountAndStackSize> FuncNameToSizeInfoA;
   StringMap<InstCountAndStackSize> FuncNameToSizeInfoB;
-  if (!tryReadFileAndProcessRemarks(InputFileNameA, FuncNameToSizeInfoA) ||
-      !tryReadFileAndProcessRemarks(InputFileNameB, FuncNameToSizeInfoB))
-    return 1;
+  if (auto E =
+          tryReadFileAndProcessRemarks(InputFileNameA, FuncNameToSizeInfoA))
+    return E;
+  if (auto E =
+          tryReadFileAndProcessRemarks(InputFileNameB, FuncNameToSizeInfoB))
+    return E;
   DiffsCategorizedByFilesPresent DiffsByFilesPresent;
   computeDiff(FuncNameToSizeInfoA, FuncNameToSizeInfoB, DiffsByFilesPresent);
-  if (!tryOutputAllDiffs(InputFileNameA, InputFileNameB, DiffsByFilesPresent))
-    return 1;
+  if (auto E = tryOutputAllDiffs(InputFileNameA, InputFileNameB,
+                                 DiffsByFilesPresent))
+    return E;
+  return Error::success();
 }
+
+static CommandRegistration RemarkSizeSiffRegister(&RemarkSizeDiffUtil,
+                                                  trySizeSiff);
\ No newline at end of file
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp
index 14af5d2..8ab3fbb 100644
--- a/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp
@@ -1,4 +1,4 @@
-//===--------- llvm-remarkutil/RemarkUtil.cpp -----------===//
+//===--------- llvm-remarkutil/RemarkUtil.cpp -----------------------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -8,370 +8,34 @@
 /// Utility for remark files.
 //===----------------------------------------------------------------------===//
 
-#include "llvm-c/Remarks.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Remarks/Remark.h"
-#include "llvm/Remarks/RemarkFormat.h"
-#include "llvm/Remarks/RemarkParser.h"
-#include "llvm/Remarks/YAMLRemarkSerializer.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Compiler.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
+#include "RemarkUtilRegistry.h"
 #include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/ToolOutputFile.h"
-#include "llvm/Support/WithColor.h"
 
 using namespace llvm;
-using namespace remarks;
+using namespace llvm::remarkutil;
+ExitOnError ExitOnErr;
 
-static ExitOnError ExitOnErr;
-static cl::OptionCategory RemarkUtilCategory("llvm-remarkutil options");
-namespace subopts {
-static cl::SubCommand
-    YAML2Bitstream("yaml2bitstream",
-                   "Convert YAML remarks to bitstream remarks");
-static cl::SubCommand
-    Bitstream2YAML("bitstream2yaml",
-                   "Convert bitstream remarks to YAML remarks");
-static cl::SubCommand InstructionCount(
-    "instruction-count",
-    "Function instruction count information (requires asm-printer remarks)");
-static cl::SubCommand
-    AnnotationCount("annotation-count",
-                    "Collect count information from annotation remarks (uses "
-                    "AnnotationRemarksPass)");
-} // namespace subopts
-
-// Keep input + output help + names consistent across the various modes via a
-// hideous macro.
-#define INPUT_OUTPUT_COMMAND_LINE_OPTIONS(SUBOPT)                              \
-  static cl::opt<std::string> InputFileName(                                   \
-      cl::Positional, cl::cat(RemarkUtilCategory), cl::init("-"),              \
-      cl::desc("<input file>"), cl::sub(SUBOPT));                              \
-  static cl::opt<std::string> OutputFileName(                                  \
-      "o", cl::init("-"), cl::cat(RemarkUtilCategory), cl::desc("Output"),     \
-      cl::value_desc("filename"), cl::sub(SUBOPT));
-
-// Keep Input format and names consistent accross the modes via a macro.
-#define INPUT_FORMAT_COMMAND_LINE_OPTIONS(SUBOPT)                              \
-  static cl::opt<Format> InputFormat(                                          \
-      "parser", cl::desc("Input remark format to parse"),                      \
-      cl::values(clEnumValN(Format::YAML, "yaml", "YAML"),                     \
-                 clEnumValN(Format::Bitstream, "bitstream", "Bitstream")),     \
-      cl::sub(SUBOPT));
-
-#define DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(SUBOPT)                            \
-  static cl::opt<bool> UseDebugLoc(                                            \
-      "use-debug-loc",                                                         \
-      cl::desc(                                                                \
-          "Add debug loc information when generating tables for "              \
-          "functions. The loc is represented as (path:line number:column "     \
-          "number)"),                                                          \
-      cl::init(false), cl::sub(SUBOPT));
-namespace yaml2bitstream {
-/// Remark format to parse.
-static constexpr Format InputFormat = Format::YAML;
-/// Remark format to output.
-static constexpr Format OutputFormat = Format::Bitstream;
-INPUT_OUTPUT_COMMAND_LINE_OPTIONS(subopts::YAML2Bitstream)
-} // namespace yaml2bitstream
-
-namespace bitstream2yaml {
-/// Remark format to parse.
-static constexpr Format InputFormat = Format::Bitstream;
-/// Remark format to output.
-static constexpr Format OutputFormat = Format::YAML;
-INPUT_OUTPUT_COMMAND_LINE_OPTIONS(subopts::Bitstream2YAML)
-} // namespace bitstream2yaml
-
-namespace instructioncount {
-INPUT_FORMAT_COMMAND_LINE_OPTIONS(subopts::InstructionCount)
-INPUT_OUTPUT_COMMAND_LINE_OPTIONS(subopts::InstructionCount)
-DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(subopts::InstructionCount)
-} // namespace instructioncount
-
-namespace annotationcount {
-INPUT_FORMAT_COMMAND_LINE_OPTIONS(subopts::AnnotationCount)
-static cl::opt<std::string> AnnotationTypeToCollect(
-    "annotation-type", cl::desc("annotation-type remark to collect count for"),
-    cl::sub(subopts::AnnotationCount));
-INPUT_OUTPUT_COMMAND_LINE_OPTIONS(subopts::AnnotationCount)
-DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(subopts::AnnotationCount)
-} // namespace annotationcount
-
-/// \returns A MemoryBuffer for the input file on success, and an Error
-/// otherwise.
-static Expected<std::unique_ptr<MemoryBuffer>>
-getInputMemoryBuffer(StringRef InputFileName) {
-  auto MaybeBuf = MemoryBuffer::getFileOrSTDIN(InputFileName);
-  if (auto ErrorCode = MaybeBuf.getError())
-    return createStringError(ErrorCode,
-                             Twine("Cannot open file '" + InputFileName +
-                                   "': " + ErrorCode.message()));
-  return std::move(*MaybeBuf);
-}
-
-/// \returns A ToolOutputFile which can be used for outputting the results of
-/// some tool mode.
-/// \p OutputFileName is the desired destination.
-/// \p Flags controls whether or not the file is opened for writing in text
-/// mode, as a binary, etc. See sys::fs::OpenFlags for more detail.
-static Expected<std::unique_ptr<ToolOutputFile>>
-getOutputFileWithFlags(StringRef OutputFileName, sys::fs::OpenFlags Flags) {
-  if (OutputFileName == "")
-    OutputFileName = "-";
-  std::error_code ErrorCode;
-  auto OF = std::make_unique<ToolOutputFile>(OutputFileName, ErrorCode, Flags);
-  if (ErrorCode)
-    return errorCodeToError(ErrorCode);
-  return std::move(OF);
-}
-
-/// \returns A ToolOutputFile which can be used for writing remarks on success,
-/// and an Error otherwise.
-/// \p OutputFileName is the desired destination.
-/// \p OutputFormat
-static Expected<std::unique_ptr<ToolOutputFile>>
-getOutputFileForRemarks(StringRef OutputFileName, Format OutputFormat) {
-  assert((OutputFormat == Format::YAML || OutputFormat == Format::Bitstream) &&
-         "Expected one of YAML or Bitstream!");
-  return getOutputFileWithFlags(OutputFileName, OutputFormat == Format::YAML
-                                                    ? sys::fs::OF_TextWithCRLF
-                                                    : sys::fs::OF_None);
-}
-
-static bool shouldSkipRemark(bool UseDebugLoc, Remark &Remark) {
-  return UseDebugLoc && !Remark.Loc.has_value();
-}
-
-namespace yaml2bitstream {
-/// Parses all remarks in the input YAML file.
-/// \p [out] ParsedRemarks - Filled with remarks parsed from the input file.
-/// \p [out] StrTab - A string table populated for later remark serialization.
-/// \returns Error::success() if all remarks were successfully parsed, and an
-/// Error otherwise.
-static Error
-tryParseRemarksFromYAMLFile(std::vector<std::unique_ptr<Remark>> &ParsedRemarks,
-                            StringTable &StrTab) {
-  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
-  if (!MaybeBuf)
-    return MaybeBuf.takeError();
-  auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
-  if (!MaybeParser)
-    return MaybeParser.takeError();
-  auto &Parser = **MaybeParser;
-  auto MaybeRemark = Parser.next();
-  for (; MaybeRemark; MaybeRemark = Parser.next()) {
-    StrTab.internalize(**MaybeRemark);
-    ParsedRemarks.push_back(std::move(*MaybeRemark));
-  }
-  auto E = MaybeRemark.takeError();
-  if (!E.isA<EndOfFileError>())
-    return E;
-  consumeError(std::move(E));
-  return Error::success();
-}
-
-/// Reserialize a list of parsed YAML remarks into bitstream remarks.
-/// \p ParsedRemarks - A list of remarks.
-/// \p StrTab - The string table for the remarks.
-/// \returns Error::success() on success.
-static Error tryReserializeYAML2Bitstream(
-    const std::vector<std::unique_ptr<Remark>> &ParsedRemarks,
-    StringTable &StrTab) {
-  auto MaybeOF = getOutputFileForRemarks(OutputFileName, OutputFormat);
-  if (!MaybeOF)
-    return MaybeOF.takeError();
-  auto OF = std::move(*MaybeOF);
-  auto MaybeSerializer = createRemarkSerializer(
-      OutputFormat, SerializerMode::Standalone, OF->os(), std::move(StrTab));
-  if (!MaybeSerializer)
-    return MaybeSerializer.takeError();
-  auto Serializer = std::move(*MaybeSerializer);
-  for (const auto &Remark : ParsedRemarks)
-    Serializer->emit(*Remark);
-  OF->keep();
-  return Error::success();
-}
-
-/// Parse YAML remarks and reserialize as bitstream remarks.
-/// \returns Error::success() on success, and an Error otherwise.
-static Error tryYAML2Bitstream() {
-  StringTable StrTab;
-  std::vector<std::unique_ptr<Remark>> ParsedRemarks;
-  ExitOnErr(tryParseRemarksFromYAMLFile(ParsedRemarks, StrTab));
-  return tryReserializeYAML2Bitstream(ParsedRemarks, StrTab);
-}
-} // namespace yaml2bitstream
-
-namespace bitstream2yaml {
-/// Parse bitstream remarks and reserialize as YAML remarks.
-/// \returns An Error if reserialization fails, or Error::success() on success.
-static Error tryBitstream2YAML() {
-  // Create the serializer.
-  auto MaybeOF = getOutputFileForRemarks(OutputFileName, OutputFormat);
-  if (!MaybeOF)
-    return MaybeOF.takeError();
-  auto OF = std::move(*MaybeOF);
-  auto MaybeSerializer = createRemarkSerializer(
-      OutputFormat, SerializerMode::Standalone, OF->os());
-  if (!MaybeSerializer)
-    return MaybeSerializer.takeError();
-
-  // Create the parser.
-  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
-  if (!MaybeBuf)
-    return MaybeBuf.takeError();
-  auto Serializer = std::move(*MaybeSerializer);
-  auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
-  if (!MaybeParser)
-    return MaybeParser.takeError();
-  auto &Parser = **MaybeParser;
-
-  // Parse + reserialize all remarks.
-  auto MaybeRemark = Parser.next();
-  for (; MaybeRemark; MaybeRemark = Parser.next())
-    Serializer->emit(**MaybeRemark);
-  auto E = MaybeRemark.takeError();
-  if (!E.isA<EndOfFileError>())
-    return E;
-  consumeError(std::move(E));
-  return Error::success();
-}
-} // namespace bitstream2yaml
-
-namespace instructioncount {
-/// Outputs all instruction count remarks in the file as a CSV.
-/// \returns Error::success() on success, and an Error otherwise.
-static Error tryInstructionCount() {
-  // Create the output buffer.
-  auto MaybeOF = getOutputFileWithFlags(OutputFileName,
-                                        /*Flags = */ sys::fs::OF_TextWithCRLF);
-  if (!MaybeOF)
-    return MaybeOF.takeError();
-  auto OF = std::move(*MaybeOF);
-  // Create a parser for the user-specified input format.
-  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
-  if (!MaybeBuf)
-    return MaybeBuf.takeError();
-  auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
-  if (!MaybeParser)
-    return MaybeParser.takeError();
-  // Emit CSV header.
-  if (UseDebugLoc)
-    OF->os() << "Source,";
-  OF->os() << "Function,InstructionCount\n";
-  // Parse all remarks. Whenever we see an instruction count remark, output
-  // the file name and the number of instructions.
-  auto &Parser = **MaybeParser;
-  auto MaybeRemark = Parser.next();
-  for (; MaybeRemark; MaybeRemark = Parser.next()) {
-    auto &Remark = **MaybeRemark;
-    if (Remark.RemarkName != "InstructionCount")
-      continue;
-    if (shouldSkipRemark(UseDebugLoc, Remark))
-      continue;
-    auto *InstrCountArg = find_if(Remark.Args, [](const Argument &Arg) {
-      return Arg.Key == "NumInstructions";
-    });
-    assert(InstrCountArg != Remark.Args.end() &&
-           "Expected instruction count remarks to have a NumInstructions key?");
-    if (UseDebugLoc) {
-      std::string Loc = Remark.Loc->SourceFilePath.str() + ":" +
-                        std::to_string(Remark.Loc->SourceLine) + +":" +
-                        std::to_string(Remark.Loc->SourceColumn);
-      OF->os() << Loc << ",";
+static Error handleSubOptions() {
+  for (auto *SC : cl::getRegisteredSubcommands()) {
+    if (*SC) {
+      // If no subcommand was provided, we need to explicitly check if this is
+      // the top-level subcommand.
+      if (SC == &cl::SubCommand::getTopLevel())
+        break;
+      if (auto C = dispatch(SC)) {
+        return C();
+      }
     }
-    OF->os() << Remark.FunctionName << "," << InstrCountArg->Val << "\n";
   }
-  auto E = MaybeRemark.takeError();
-  if (!E.isA<EndOfFileError>())
-    return E;
-  consumeError(std::move(E));
-  OF->keep();
-  return Error::success();
-}
-} // namespace instructioncount
-
-namespace annotationcount {
-static Error tryAnnotationCount() {
-  // Create the output buffer.
-  auto MaybeOF = getOutputFileWithFlags(OutputFileName,
-                                        /*Flags = */ sys::fs::OF_TextWithCRLF);
-  if (!MaybeOF)
-    return MaybeOF.takeError();
-  auto OF = std::move(*MaybeOF);
-  // Create a parser for the user-specified input format.
-  auto MaybeBuf = getInputMemoryBuffer(InputFileName);
-  if (!MaybeBuf)
-    return MaybeBuf.takeError();
-  auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
-  if (!MaybeParser)
-    return MaybeParser.takeError();
-  // Emit CSV header.
-  if (UseDebugLoc)
-    OF->os() << "Source,";
-  OF->os() << "Function,Count\n";
-  // Parse all remarks. When we see the specified remark collect the count
-  // information.
-  auto &Parser = **MaybeParser;
-  auto MaybeRemark = Parser.next();
-  for (; MaybeRemark; MaybeRemark = Parser.next()) {
-    auto &Remark = **MaybeRemark;
-    if (Remark.RemarkName != "AnnotationSummary")
-      continue;
-    if (shouldSkipRemark(UseDebugLoc, Remark))
-      continue;
-    auto *RemarkNameArg = find_if(Remark.Args, [](const Argument &Arg) {
-      return Arg.Key == "type" && Arg.Val == AnnotationTypeToCollect;
-    });
-    if (RemarkNameArg == Remark.Args.end())
-      continue;
-    auto *CountArg = find_if(
-        Remark.Args, [](const Argument &Arg) { return Arg.Key == "count"; });
-    assert(CountArg != Remark.Args.end() &&
-           "Expected annotation-type remark to have a count key?");
-    if (UseDebugLoc) {
-      std::string Loc = Remark.Loc->SourceFilePath.str() + ":" +
-                        std::to_string(Remark.Loc->SourceLine) + +":" +
-                        std::to_string(Remark.Loc->SourceColumn);
-      OF->os() << Loc << ",";
-    }
-    OF->os() << Remark.FunctionName << "," << CountArg->Val << "\n";
-  }
-  auto E = MaybeRemark.takeError();
-  if (!E.isA<EndOfFileError>())
-    return E;
-  consumeError(std::move(E));
-  OF->keep();
-  return Error::success();
-}
-
-} // namespace annotationcount
-/// Handle user-specified suboptions (e.g. yaml2bitstream, bitstream2yaml).
-/// \returns An Error if the specified suboption fails or if no suboption was
-/// specified. Otherwise, Error::success().
-static Error handleSuboptions() {
-  if (subopts::Bitstream2YAML)
-    return bitstream2yaml::tryBitstream2YAML();
-  if (subopts::YAML2Bitstream)
-    return yaml2bitstream::tryYAML2Bitstream();
-  if (subopts::InstructionCount)
-    return instructioncount::tryInstructionCount();
-  if (subopts::AnnotationCount)
-    return annotationcount::tryAnnotationCount();
 
   return make_error<StringError>(
       "Please specify a subcommand. (See -help for options)",
       inconvertibleErrorCode());
 }
 
-int main(int argc, const char **argv) {
+int main(int argc, char *argv[]) {
   InitLLVM X(argc, argv);
-  cl::HideUnrelatedOptions(RemarkUtilCategory);
   cl::ParseCommandLineOptions(argc, argv, "Remark file utilities\n");
   ExitOnErr.setBanner(std::string(argv[0]) + ": error: ");
-  ExitOnErr(handleSuboptions());
+  ExitOnErr(handleSubOptions());
 }
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
new file mode 100644
index 0000000..c035716
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.cpp
@@ -0,0 +1,57 @@
+//===- RemarkUtilHelpers.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Helpers for remark utilites
+//
+//===----------------------------------------------------------------------===//
+#include "RemarkUtilHelpers.h"
+
+namespace llvm {
+namespace remarks {
+/// \returns A MemoryBuffer for the input file on success, and an Error
+/// otherwise.
+Expected<std::unique_ptr<MemoryBuffer>>
+getInputMemoryBuffer(StringRef InputFileName) {
+  auto MaybeBuf = MemoryBuffer::getFileOrSTDIN(InputFileName);
+  if (auto ErrorCode = MaybeBuf.getError())
+    return createStringError(ErrorCode,
+                             Twine("Cannot open file '" + InputFileName +
+                                   "': " + ErrorCode.message()));
+  return std::move(*MaybeBuf);
+}
+
+/// \returns A ToolOutputFile which can be used for outputting the results of
+/// some tool mode.
+/// \p OutputFileName is the desired destination.
+/// \p Flags controls whether or not the file is opened for writing in text
+/// mode, as a binary, etc. See sys::fs::OpenFlags for more detail.
+Expected<std::unique_ptr<ToolOutputFile>>
+getOutputFileWithFlags(StringRef OutputFileName, sys::fs::OpenFlags Flags) {
+  if (OutputFileName == "")
+    OutputFileName = "-";
+  std::error_code ErrorCode;
+  auto OF = std::make_unique<ToolOutputFile>(OutputFileName, ErrorCode, Flags);
+  if (ErrorCode)
+    return errorCodeToError(ErrorCode);
+  return std::move(OF);
+}
+
+/// \returns A ToolOutputFile which can be used for writing remarks on success,
+/// and an Error otherwise.
+/// \p OutputFileName is the desired destination.
+/// \p OutputFormat
+Expected<std::unique_ptr<ToolOutputFile>>
+getOutputFileForRemarks(StringRef OutputFileName, Format OutputFormat) {
+  assert((OutputFormat == Format::YAML || OutputFormat == Format::Bitstream) &&
+         "Expected one of YAML or Bitstream!");
+  return getOutputFileWithFlags(OutputFileName, OutputFormat == Format::YAML
+                                                    ? sys::fs::OF_TextWithCRLF
+                                                    : sys::fs::OF_None);
+}
+} // namespace remarks
+} // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
new file mode 100644
index 0000000..5d23352
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilHelpers.h
@@ -0,0 +1,59 @@
+//===- RemarkUtilHelpers.h ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Helpers for remark utilites
+//
+//===----------------------------------------------------------------------===//
+#include "llvm-c/Remarks.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Remarks/Remark.h"
+#include "llvm/Remarks/RemarkFormat.h"
+#include "llvm/Remarks/RemarkParser.h"
+#include "llvm/Remarks/YAMLRemarkSerializer.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/ToolOutputFile.h"
+
+// Keep input + output help + names consistent across the various modes via a
+// hideous macro.
+#define INPUT_OUTPUT_COMMAND_LINE_OPTIONS(SUBOPT)                              \
+  static cl::opt<std::string> InputFileName(cl::Positional, cl::init("-"),     \
+                                            cl::desc("<input file>"),          \
+                                            cl::sub(SUBOPT));                  \
+  static cl::opt<std::string> OutputFileName(                                  \
+      "o", cl::init("-"), cl::desc("Output"), cl::value_desc("filename"),      \
+      cl::sub(SUBOPT));
+
+// Keep Input format and names consistent accross the modes via a macro.
+#define INPUT_FORMAT_COMMAND_LINE_OPTIONS(SUBOPT)                              \
+  static cl::opt<Format> InputFormat(                                          \
+      "parser", cl::desc("Input remark format to parse"),                      \
+      cl::values(clEnumValN(Format::YAML, "yaml", "YAML"),                     \
+                 clEnumValN(Format::Bitstream, "bitstream", "Bitstream")),     \
+      cl::sub(SUBOPT));
+
+#define DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(SUBOPT)                            \
+  static cl::opt<bool> UseDebugLoc(                                            \
+      "use-debug-loc",                                                         \
+      cl::desc(                                                                \
+          "Add debug loc information when generating tables for "              \
+          "functions. The loc is represented as (path:line number:column "     \
+          "number)"),                                                          \
+      cl::init(false), cl::sub(SUBOPT));
+
+namespace llvm {
+namespace remarks {
+Expected<std::unique_ptr<MemoryBuffer>>
+getInputMemoryBuffer(StringRef InputFileName);
+Expected<std::unique_ptr<ToolOutputFile>>
+getOutputFileWithFlags(StringRef OutputFileName, sys::fs::OpenFlags Flags);
+Expected<std::unique_ptr<ToolOutputFile>>
+getOutputFileForRemarks(StringRef OutputFileName, Format OutputFormat);
+} // namespace remarks
+} // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilRegistry.cpp b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilRegistry.cpp
new file mode 100644
index 0000000..244a16d
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilRegistry.cpp
@@ -0,0 +1,41 @@
+//===- RemarkUtilRegistry.cpp: Implement a command registry. --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implement a simple subcommand registry.
+//
+//===----------------------------------------------------------------------===//
+#include "RemarkUtilRegistry.h"
+#include <unordered_map>
+
+namespace llvm {
+namespace remarkutil {
+
+using HandlerType = std::function<Error()>;
+
+static std::unordered_map<cl::SubCommand *, HandlerType> &getCommands() {
+  static std::unordered_map<cl::SubCommand *, HandlerType> Commands;
+  return Commands;
+}
+
+CommandRegistration::CommandRegistration(cl::SubCommand *SC,
+                                         HandlerType Command) {
+  assert(getCommands().count(SC) == 0 &&
+         "Attempting to overwrite a command handler");
+  assert(Command && "Attempting to register an empty std::function<Error()>");
+  getCommands()[SC] = Command;
+}
+
+HandlerType dispatch(cl::SubCommand *SC) {
+  auto It = getCommands().find(SC);
+  assert(It != getCommands().end() &&
+         "Attempting to dispatch on un-registered SubCommand.");
+  return It->second;
+}
+
+} // namespace remarkutil
+} // namespace llvm
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilRegistry.h b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilRegistry.h
new file mode 100644
index 0000000..2dd3a53
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtilRegistry.h
@@ -0,0 +1,40 @@
+//===- RemarkUtilRegistry.h: Implement a command registry. ----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Implement a simple subcommand registry.
+//
+//===----------------------------------------------------------------------===//
+#ifndef TOOLS_LLVM_REMARKUTIL_REGISTRY_H
+#define TOOLS_LLVM_REMARKUTIL_REGISTRY_H
+
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace remarkutil {
+
+// Use |CommandRegistration| as a global initialiser that registers a function
+// and associates it with |SC|. This requires that a command has not been
+// registered to a given |SC|.
+//
+// Usage:
+//
+//   // At namespace scope.
+//   static CommandRegistration Unused(&MySubCommand, [] { ... });
+//
+struct CommandRegistration {
+  CommandRegistration(cl::SubCommand *SC, std::function<Error()> Command);
+};
+
+// Requires that |SC| is not null and has an associated function to it.
+std::function<Error()> dispatch(cl::SubCommand *SC);
+
+} // namespace remarkutil
+} // namespace llvm
+
+#endif // TOOLS_LLVM_REMARKUTIL_REGISTRY_H
diff --git a/src/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/src/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
index df82fb0..4cb76f4 100644
--- a/src/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp
@@ -892,6 +892,8 @@
         StringRef SecContent = Dyld.getSectionContent(SectionID);
         uint64_t SymSize = SecContent.size() - (CSymAddr - SecContent.data());
         SymInfo.setContent(ArrayRef<char>(CSymAddr, SymSize));
+        SymInfo.setTargetFlags(
+            Dyld.getSymbol(Symbol).getFlags().getTargetFlags());
       }
     }
     return SymInfo;
@@ -924,7 +926,8 @@
   };
 
   auto GetStubInfo = [&Dyld, &StubMap](StringRef StubContainer,
-                                       StringRef SymbolName)
+                                       StringRef SymbolName,
+                                       StringRef KindNameFilter)
       -> Expected<RuntimeDyldChecker::MemoryRegionInfo> {
     if (!StubMap.count(StubContainer))
       return make_error<StringError>("Stub container not found: " +
@@ -945,6 +948,11 @@
     return StubMemInfo;
   };
 
+  auto GetGOTInfo = [&GetStubInfo](StringRef StubContainer,
+                                   StringRef SymbolName) {
+    return GetStubInfo(StubContainer, SymbolName, "");
+  };
+
   // We will initialize this below once we have the first object file and can
   // know the endianness.
   std::unique_ptr<RuntimeDyldChecker> Checker;
@@ -975,9 +983,10 @@
 
     if (!Checker)
       Checker = std::make_unique<RuntimeDyldChecker>(
-          IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo,
-          GetStubInfo, Obj.isLittleEndian() ? support::little : support::big,
-          Disassembler.get(), InstPrinter.get(), dbgs());
+          IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,
+          Obj.isLittleEndian() ? llvm::endianness::little
+                               : llvm::endianness::big,
+          TheTriple, MCPU, SubtargetFeatures(), dbgs());
 
     auto FileName = sys::path::filename(InputFile);
     MemMgr.setSectionIDsMap(&FileToSecIDMap[FileName]);
diff --git a/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt
index 8ace190..b20ac31 100644
--- a/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt
@@ -14,6 +14,9 @@
   if(MSVC)
     message(FATAL_ERROR "Generating libLLVM is not supported on MSVC")
   endif()
+  if(ZOS)
+    message(FATAL_ERROR "Generating libLLVM is not supported on z/OS")
+  endif()
 
   llvm_map_components_to_libnames(LIB_NAMES ${LLVM_DYLIB_COMPONENTS})
 
@@ -30,19 +33,18 @@
   if (LLVM_LINK_LLVM_DYLIB)
     set(INSTALL_WITH_TOOLCHAIN INSTALL_WITH_TOOLCHAIN)
   endif()
-  add_llvm_library(LLVM SHARED DISABLE_LLVM_LINK_LLVM_DYLIB SONAME ${INSTALL_WITH_TOOLCHAIN} ${SOURCES})
+  if (WIN32)
+    add_llvm_library(LLVM SHARED DISABLE_LLVM_LINK_LLVM_DYLIB SONAME ${INSTALL_WITH_TOOLCHAIN} ${SOURCES})
+  else()
+    add_llvm_library(LLVM SHARED DISABLE_LLVM_LINK_LLVM_DYLIB OUTPUT_NAME LLVM ${INSTALL_WITH_TOOLCHAIN} ${SOURCES})
+    # Add symlink for backwards compatibility with old library name
+    llvm_install_library_symlink(LLVM-${LLVM_VERSION_MAJOR}${LLVM_VERSION_SUFFIX} $<TARGET_FILE_NAME:LLVM> SHARED FULL_DEST COMPONENT LLVM)
+  endif()
 
   list(REMOVE_DUPLICATES LIB_NAMES)
-  if((MINGW) OR (HAIKU)
-     OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
-     OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "GNU")
-     OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "FreeBSD")
-     OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "NetBSD")
-     OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD")
-     OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "DragonFly")
-     OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia")
-     OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
-     OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")) # FIXME: It should be "GNU ld for elf"
+  if("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
+    set(LIB_NAMES -Wl,-all_load ${LIB_NAMES})
+  else()
     configure_file(
     ${CMAKE_CURRENT_SOURCE_DIR}/simple_version_script.map.in
     ${LLVM_LIBRARY_DIR}/tools/llvm-shlib/simple_version_script.map)
@@ -53,15 +55,13 @@
       # Solaris ld does not accept global: *; so there is no way to version *all* global symbols
       set(LIB_NAMES -Wl,--version-script,${LLVM_LIBRARY_DIR}/tools/llvm-shlib/simple_version_script.map ${LIB_NAMES})
     endif()
-    if (NOT MINGW)
+    if (NOT MINGW AND NOT LLVM_LINKER_IS_SOLARISLD_ILLUMOS)
       # Optimize function calls for default visibility definitions to avoid PLT and
       # reduce dynamic relocations.
       # Note: for -fno-pic default, the address of a function may be different from
       # inside and outside libLLVM.so.
       target_link_options(LLVM PRIVATE LINKER:-Bsymbolic-functions)
     endif()
-  elseif("${CMAKE_SYSTEM_NAME}" STREQUAL "Darwin")
-    set(LIB_NAMES -Wl,-all_load ${LIB_NAMES})
   endif()
 
   target_link_libraries(LLVM PRIVATE ${LIB_NAMES})
diff --git a/src/llvm-project/llvm/tools/llvm-size/llvm-size.cpp b/src/llvm-project/llvm/tools/llvm-size/llvm-size.cpp
index 048a98b..78b207e 100644
--- a/src/llvm-project/llvm/tools/llvm-size/llvm-size.cpp
+++ b/src/llvm-project/llvm/tools/llvm-size/llvm-size.cpp
@@ -25,7 +25,6 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/WithColor.h"
@@ -41,9 +40,7 @@
 using namespace llvm::opt; // for HelpHidden in Opts.inc
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -56,13 +53,7 @@
 #undef PREFIX
 
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -871,7 +862,6 @@
 }
 
 int llvm_size_main(int argc, char **argv, const llvm::ToolContext &) {
-  InitLLVM X(argc, argv);
   BumpPtrAllocator A;
   StringSaver Saver(A);
   SizeOptTable Tbl;
diff --git a/src/llvm-project/llvm/tools/llvm-special-case-list-fuzzer/special-case-list-fuzzer.cpp b/src/llvm-project/llvm/tools/llvm-special-case-list-fuzzer/special-case-list-fuzzer.cpp
index aaab5f8..0691f29 100644
--- a/src/llvm-project/llvm/tools/llvm-special-case-list-fuzzer/special-case-list-fuzzer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-special-case-list-fuzzer/special-case-list-fuzzer.cpp
@@ -12,8 +12,9 @@
 #include <cstdlib>
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
-  std::unique_ptr<llvm::MemoryBuffer> Buf = llvm::MemoryBuffer::getMemBuffer(
-      llvm::StringRef(reinterpret_cast<const char *>(Data), Size), "", false);
+  std::string Payload(reinterpret_cast<const char *>(Data), Size);
+  std::unique_ptr<llvm::MemoryBuffer> Buf =
+      llvm::MemoryBuffer::getMemBuffer(Payload);
 
   if (!Buf)
     return 0;
diff --git a/src/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp b/src/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
index d1cf160..8cb7fce 100644
--- a/src/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
+++ b/src/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
@@ -132,9 +132,9 @@
   // Define a few arguments
   LLVMContext &Context = M->getContext();
   Type* ArgsTy[] = {
-    Type::getInt8PtrTy(Context),
-    Type::getInt32PtrTy(Context),
-    Type::getInt64PtrTy(Context),
+    PointerType::get(Context, 0),
+    PointerType::get(Context, 0),
+    PointerType::get(Context, 0),
     Type::getInt32Ty(Context),
     Type::getInt64Ty(Context),
     Type::getInt8Ty(Context)
@@ -175,7 +175,7 @@
         Ty = Type::getPPC_FP128Ty(Context);
       else if (Arg == "x86_mmx")
         Ty = Type::getX86_MMXTy(Context);
-      else if (Arg.startswith("i")) {
+      else if (Arg.starts_with("i")) {
         unsigned N = 0;
         Arg.drop_front().getAsInteger(10, N);
         if (N > 0)
diff --git a/src/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp b/src/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp
index d9bc34e..8642be3 100644
--- a/src/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp
+++ b/src/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp
@@ -33,9 +33,7 @@
 namespace {
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -47,14 +45,9 @@
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
diff --git a/src/llvm-project/llvm/tools/llvm-symbolizer/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-symbolizer/CMakeLists.txt
index a6bc047..6f8de1f 100644
--- a/src/llvm-project/llvm/tools/llvm-symbolizer/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-symbolizer/CMakeLists.txt
@@ -20,9 +20,12 @@
 
   DEPENDS
   SymbolizerOptsTableGen
+  GENERATE_DRIVER
   )
 
-target_link_libraries(llvm-symbolizer PRIVATE LLVMDebuginfod)
+if(NOT LLVM_TOOL_LLVM_DRIVER_BUILD)
+  target_link_libraries(llvm-symbolizer PRIVATE LLVMDebuginfod)
+endif()
 
 add_llvm_tool_symlink(llvm-addr2line llvm-symbolizer)
 
diff --git a/src/llvm-project/llvm/tools/llvm-symbolizer/Opts.td b/src/llvm-project/llvm/tools/llvm-symbolizer/Opts.td
index 6742e08..edc80bf 100644
--- a/src/llvm-project/llvm/tools/llvm-symbolizer/Opts.td
+++ b/src/llvm-project/llvm/tools/llvm-symbolizer/Opts.td
@@ -82,5 +82,3 @@
 // Compatibility aliases for pprof's symbolizer.
 def : Flag<["-"], "demangle=true">, Alias<demangle>, HelpText<"Alias for --demangle">;
 def : Flag<["-"], "demangle=false">, Alias<no_demangle>, HelpText<"Alias for --no-demangle">;
-// Compatibility no-op options.
-def : Flag<["--"], "use-symbol-table=true">;
diff --git a/src/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp b/src/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
index 3e342a4..b98bdbc 100644
--- a/src/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -32,8 +32,9 @@
 #include "llvm/Support/COM.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/Errc.h"
 #include "llvm/Support/FileSystem.h"
-#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/StringSaver.h"
 #include "llvm/Support/WithColor.h"
@@ -50,9 +51,7 @@
 namespace {
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -64,14 +63,9 @@
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -86,10 +80,10 @@
 
 static std::string ToolName;
 
-static void printError(const ErrorInfoBase &EI, StringRef Path) {
+static void printError(const ErrorInfoBase &EI, StringRef AuxInfo) {
   WithColor::error(errs(), ToolName);
-  if (!EI.isA<FileError>())
-    errs() << "'" << Path << "': ";
+  if (!AuxInfo.empty())
+    errs() << "'" << AuxInfo << "': ";
   EI.log(errs());
   errs() << '\n';
 }
@@ -135,12 +129,37 @@
   HTTPClient::initialize();
 }
 
-static bool parseCommand(StringRef BinaryName, bool IsAddr2Line,
-                         StringRef InputString, Command &Cmd,
-                         std::string &ModuleName, object::BuildID &BuildID,
-                         uint64_t &ModuleOffset) {
+static StringRef getSpaceDelimitedWord(StringRef &Source) {
   const char kDelimiters[] = " \n\r";
-  ModuleName = "";
+  const char *Pos = Source.data();
+  StringRef Result;
+  Pos += strspn(Pos, kDelimiters);
+  if (*Pos == '"' || *Pos == '\'') {
+    char Quote = *Pos;
+    Pos++;
+    const char *End = strchr(Pos, Quote);
+    if (!End)
+      return StringRef();
+    Result = StringRef(Pos, End - Pos);
+    Pos = End + 1;
+  } else {
+    int NameLength = strcspn(Pos, kDelimiters);
+    Result = StringRef(Pos, NameLength);
+    Pos += NameLength;
+  }
+  Source = StringRef(Pos, Source.end() - Pos);
+  return Result;
+}
+
+static Error makeStringError(StringRef Msg) {
+  return make_error<StringError>(Msg, inconvertibleErrorCode());
+}
+
+static Error parseCommand(StringRef BinaryName, bool IsAddr2Line,
+                          StringRef InputString, Command &Cmd,
+                          std::string &ModuleName, object::BuildID &BuildID,
+                          StringRef &Symbol, uint64_t &Offset) {
+  ModuleName = BinaryName;
   if (InputString.consume_front("CODE ")) {
     Cmd = Command::Code;
   } else if (InputString.consume_front("DATA ")) {
@@ -152,74 +171,119 @@
     Cmd = Command::Code;
   }
 
-  const char *Pos;
-  // Skip delimiters and parse input filename (if needed).
-  if (BinaryName.empty() && BuildID.empty()) {
-    bool HasFilePrefix = false;
-    bool HasBuildIDPrefix = false;
-    while (true) {
-      if (InputString.consume_front("FILE:")) {
-        if (HasFilePrefix)
-          return false;
-        HasFilePrefix = true;
-        continue;
-      }
-      if (InputString.consume_front("BUILDID:")) {
-        if (HasBuildIDPrefix)
-          return false;
-        HasBuildIDPrefix = true;
-        continue;
-      }
-      break;
+  // Parse optional input file specification.
+  bool HasFilePrefix = false;
+  bool HasBuildIDPrefix = false;
+  while (!InputString.empty()) {
+    InputString = InputString.ltrim();
+    if (InputString.consume_front("FILE:")) {
+      if (HasFilePrefix || HasBuildIDPrefix)
+        return makeStringError("duplicate input file specification prefix");
+      HasFilePrefix = true;
+      continue;
     }
-    if (HasFilePrefix && HasBuildIDPrefix)
-      return false;
-
-    Pos = InputString.data();
-    Pos += strspn(Pos, kDelimiters);
-    if (*Pos == '"' || *Pos == '\'') {
-      char Quote = *Pos;
-      Pos++;
-      const char *End = strchr(Pos, Quote);
-      if (!End)
-        return false;
-      ModuleName = std::string(Pos, End - Pos);
-      Pos = End + 1;
-    } else {
-      int NameLength = strcspn(Pos, kDelimiters);
-      ModuleName = std::string(Pos, NameLength);
-      Pos += NameLength;
+    if (InputString.consume_front("BUILDID:")) {
+      if (HasBuildIDPrefix || HasFilePrefix)
+        return makeStringError("duplicate input file specification prefix");
+      HasBuildIDPrefix = true;
+      continue;
     }
-    if (HasBuildIDPrefix) {
-      BuildID = parseBuildID(ModuleName);
-      if (BuildID.empty())
-        return false;
-      ModuleName.clear();
-    }
-  } else {
-    Pos = InputString.data();
-    ModuleName = BinaryName.str();
+    break;
   }
-  // Skip delimiters and parse module offset.
-  Pos += strspn(Pos, kDelimiters);
-  int OffsetLength = strcspn(Pos, kDelimiters);
-  StringRef Offset(Pos, OffsetLength);
-  // GNU addr2line assumes the offset is hexadecimal and allows a redundant
+
+  // If an input file is not specified on the command line, try to extract it
+  // from the command.
+  if (HasBuildIDPrefix || HasFilePrefix) {
+    InputString = InputString.ltrim();
+    if (InputString.empty()) {
+      if (HasFilePrefix)
+        return makeStringError("must be followed by an input file");
+      else
+        return makeStringError("must be followed by a hash");
+    }
+
+    if (!BinaryName.empty() || !BuildID.empty())
+      return makeStringError("input file has already been specified");
+
+    StringRef Name = getSpaceDelimitedWord(InputString);
+    if (Name.empty())
+      return makeStringError("unbalanced quotes in input file name");
+    if (HasBuildIDPrefix) {
+      BuildID = parseBuildID(Name);
+      if (BuildID.empty())
+        return makeStringError("wrong format of build-id");
+    } else {
+      ModuleName = Name;
+    }
+  } else if (BinaryName.empty() && BuildID.empty()) {
+    // No input file has been specified. If the input string contains at least
+    // two items, assume that the first item is a file name.
+    ModuleName = getSpaceDelimitedWord(InputString);
+    if (ModuleName.empty())
+      return makeStringError("no input filename has been specified");
+  }
+
+  // Parse address specification, which can be an offset in module or a
+  // symbol with optional offset.
+  InputString = InputString.trim();
+  if (InputString.empty())
+    return makeStringError("no module offset has been specified");
+
+  // If input string contains a space, ignore everything after it. This behavior
+  // is consistent with GNU addr2line.
+  int AddrSpecLength = InputString.find_first_of(" \n\r");
+  StringRef AddrSpec = InputString.substr(0, AddrSpecLength);
+  bool StartsWithDigit = std::isdigit(AddrSpec.front());
+
+  // GNU addr2line assumes the address is hexadecimal and allows a redundant
   // "0x" or "0X" prefix; do the same for compatibility.
   if (IsAddr2Line)
-    Offset.consume_front("0x") || Offset.consume_front("0X");
-  return !Offset.getAsInteger(IsAddr2Line ? 16 : 0, ModuleOffset);
+    AddrSpec.consume_front("0x") || AddrSpec.consume_front("0X");
+
+  // If address specification is a number, treat it as a module offset.
+  if (!AddrSpec.getAsInteger(IsAddr2Line ? 16 : 0, Offset)) {
+    // Module offset is an address.
+    Symbol = StringRef();
+    return Error::success();
+  }
+
+  // If address specification starts with a digit, but is not a number, consider
+  // it as invalid.
+  if (StartsWithDigit || AddrSpec.empty())
+    return makeStringError("expected a number as module offset");
+
+  // Otherwise it is a symbol name, potentially with an offset.
+  Symbol = AddrSpec;
+  Offset = 0;
+
+  // If the address specification contains '+', try treating it as
+  // "symbol + offset".
+  size_t Plus = AddrSpec.rfind('+');
+  if (Plus != StringRef::npos) {
+    StringRef SymbolStr = AddrSpec.take_front(Plus);
+    StringRef OffsetStr = AddrSpec.substr(Plus + 1);
+    if (!SymbolStr.empty() && !OffsetStr.empty() &&
+        !OffsetStr.getAsInteger(0, Offset)) {
+      Symbol = SymbolStr;
+      return Error::success();
+    }
+    // The found '+' is not an offset delimiter.
+  }
+
+  return Error::success();
 }
 
 template <typename T>
 void executeCommand(StringRef ModuleName, const T &ModuleSpec, Command Cmd,
-                    uint64_t Offset, uint64_t AdjustVMA, bool ShouldInline,
-                    OutputStyle Style, LLVMSymbolizer &Symbolizer,
-                    DIPrinter &Printer) {
+                    StringRef Symbol, uint64_t Offset, uint64_t AdjustVMA,
+                    bool ShouldInline, OutputStyle Style,
+                    LLVMSymbolizer &Symbolizer, DIPrinter &Printer) {
   uint64_t AdjustedOffset = Offset - AdjustVMA;
   object::SectionedAddress Address = {AdjustedOffset,
                                       object::SectionedAddress::UndefSection};
-  Request SymRequest = {ModuleName, Offset};
+  Request SymRequest = {
+      ModuleName, Symbol.empty() ? std::make_optional(Offset) : std::nullopt,
+      Symbol};
   if (Cmd == Command::Data) {
     Expected<DIGlobal> ResOrErr = Symbolizer.symbolizeData(ModuleSpec, Address);
     print(SymRequest, ResOrErr, Printer);
@@ -227,6 +291,10 @@
     Expected<std::vector<DILocal>> ResOrErr =
         Symbolizer.symbolizeFrame(ModuleSpec, Address);
     print(SymRequest, ResOrErr, Printer);
+  } else if (!Symbol.empty()) {
+    Expected<std::vector<DILineInfo>> ResOrErr =
+        Symbolizer.findSymbol(ModuleSpec, Symbol, Offset);
+    print(SymRequest, ResOrErr, Printer);
   } else if (ShouldInline) {
     Expected<DIInliningInfo> ResOrErr =
         Symbolizer.symbolizeInlinedCode(ModuleSpec, Address);
@@ -254,6 +322,11 @@
   Symbolizer.pruneCache();
 }
 
+static void printUnknownLineInfo(std::string ModuleName, DIPrinter &Printer) {
+  Request SymRequest = {ModuleName, std::nullopt, StringRef()};
+  Printer.print(SymRequest, DILineInfo());
+}
+
 static void symbolizeInput(const opt::InputArgList &Args,
                            object::BuildIDRef IncomingBuildID,
                            uint64_t AdjustVMA, bool IsAddr2Line,
@@ -263,9 +336,14 @@
   std::string ModuleName;
   object::BuildID BuildID(IncomingBuildID.begin(), IncomingBuildID.end());
   uint64_t Offset = 0;
-  if (!parseCommand(Args.getLastArgValue(OPT_obj_EQ), IsAddr2Line,
-                    StringRef(InputString), Cmd, ModuleName, BuildID, Offset)) {
-    Printer.printInvalidCommand({ModuleName, std::nullopt}, InputString);
+  StringRef Symbol;
+  if (Error E = parseCommand(Args.getLastArgValue(OPT_obj_EQ), IsAddr2Line,
+                             StringRef(InputString), Cmd, ModuleName, BuildID,
+                             Symbol, Offset)) {
+    handleAllErrors(std::move(E), [&](const StringError &EI) {
+      printError(EI, InputString);
+      printUnknownLineInfo(ModuleName, Printer);
+    });
     return;
   }
   bool ShouldInline = Args.hasFlag(OPT_inlines, OPT_no_inlines, !IsAddr2Line);
@@ -274,11 +352,11 @@
     if (!Args.hasArg(OPT_no_debuginfod))
       enableDebuginfod(Symbolizer, Args);
     std::string BuildIDStr = toHex(BuildID);
-    executeCommand(BuildIDStr, BuildID, Cmd, Offset, AdjustVMA, ShouldInline,
-                   Style, Symbolizer, Printer);
+    executeCommand(BuildIDStr, BuildID, Cmd, Symbol, Offset, AdjustVMA,
+                   ShouldInline, Style, Symbolizer, Printer);
   } else {
-    executeCommand(ModuleName, ModuleName, Cmd, Offset, AdjustVMA, ShouldInline,
-                   Style, Symbolizer, Printer);
+    executeCommand(ModuleName, ModuleName, Cmd, Symbol, Offset, AdjustVMA,
+                   ShouldInline, Style, Symbolizer, Printer);
   }
 }
 
@@ -377,15 +455,12 @@
   std::string InputString;
   while (std::getline(std::cin, InputString)) {
     InputString += '\n';
-    Filter.filter(InputString);
+    Filter.filter(std::move(InputString));
   }
   Filter.finish();
 }
 
-ExitOnError ExitOnErr;
-
-int main(int argc, char **argv) {
-  InitLLVM X(argc, argv);
+int llvm_symbolizer_main(int argc, char **argv, const llvm::ToolContext &) {
   sys::InitializeCOMRAII COM(sys::COMThreadingMode::MultiThreaded);
 
   ToolName = argv[0];
@@ -484,7 +559,7 @@
   if (auto *Arg = Args.getLastArg(OPT_obj_EQ); Arg) {
     auto Status = Symbolizer.getOrCreateModuleInfo(Arg->getValue());
     if (!Status) {
-      Request SymRequest = {Arg->getValue(), 0};
+      Request SymRequest = {Arg->getValue(), 0, StringRef()};
       handleAllErrors(Status.takeError(), [&](const ErrorInfoBase &EI) {
         Printer->printError(SymRequest, EI);
       });
diff --git a/src/llvm-project/llvm/tools/llvm-tapi-diff/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-tapi-diff/CMakeLists.txt
deleted file mode 100644
index 2870221..0000000
--- a/src/llvm-project/llvm/tools/llvm-tapi-diff/CMakeLists.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-set(LLVM_LINK_COMPONENTS
-  Object
-  Support
-  TextAPI
-  )
-
-add_llvm_tool(llvm-tapi-diff
-  llvm-tapi-diff.cpp
-  DiffEngine.cpp
-  )
diff --git a/src/llvm-project/llvm/tools/llvm-tapi-diff/llvm-tapi-diff.cpp b/src/llvm-project/llvm/tools/llvm-tapi-diff/llvm-tapi-diff.cpp
deleted file mode 100644
index 09dd6f7..0000000
--- a/src/llvm-project/llvm/tools/llvm-tapi-diff/llvm-tapi-diff.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-//===-- llvm-tapi-diff.cpp - tbd comparator command-line driver --*- C++-*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the command-line driver for the llvm-tapi difference
-// engine.
-//
-//===----------------------------------------------------------------------===//
-#include "DiffEngine.h"
-#include "llvm/Object/TapiUniversal.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstdlib>
-
-using namespace llvm;
-using namespace MachO;
-using namespace object;
-
-namespace {
-cl::OptionCategory NMCat("llvm-tapi-diff Options");
-cl::opt<std::string> InputFileNameLHS(cl::Positional, cl::desc("<first file>"),
-                                      cl::cat(NMCat));
-cl::opt<std::string> InputFileNameRHS(cl::Positional, cl::desc("<second file>"),
-                                      cl::cat(NMCat));
-} // anonymous namespace
-
-Expected<std::unique_ptr<Binary>> convertFileToBinary(std::string &Filename) {
-  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
-      MemoryBuffer::getFileOrSTDIN(Filename);
-  if (BufferOrErr.getError())
-    return errorCodeToError(BufferOrErr.getError());
-  return createBinary(BufferOrErr.get()->getMemBufferRef());
-}
-
-int main(int Argc, char **Argv) {
-  InitLLVM X(Argc, Argv);
-  cl::HideUnrelatedOptions(NMCat);
-  cl::ParseCommandLineOptions(Argc, Argv, "Text-based Stubs Comparison Tool");
-  if (InputFileNameLHS.empty() || InputFileNameRHS.empty()) {
-    cl::PrintHelpMessage();
-    return EXIT_FAILURE;
-  }
-
-  ExitOnError ExitOnErr("error: '" + InputFileNameLHS + "' ",
-                        /*DefaultErrorExitCode=*/2);
-  auto BinLHS = ExitOnErr(convertFileToBinary(InputFileNameLHS));
-
-  TapiUniversal *FileLHS = dyn_cast<TapiUniversal>(BinLHS.get());
-  if (!FileLHS) {
-    ExitOnErr(createStringError(std::errc::executable_format_error,
-                                "unsupported file format"));
-  }
-
-  ExitOnErr.setBanner("error: '" + InputFileNameRHS + "' ");
-  auto BinRHS = ExitOnErr(convertFileToBinary(InputFileNameRHS));
-
-  TapiUniversal *FileRHS = dyn_cast<TapiUniversal>(BinRHS.get());
-  if (!FileRHS) {
-    ExitOnErr(createStringError(std::errc::executable_format_error,
-                                "unsupported file format"));
-  }
-
-  raw_ostream &OS = outs();
-
-  return DiffEngine(FileLHS, FileRHS).compareFiles(OS);
-}
diff --git a/src/llvm-project/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp b/src/llvm-project/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
index 9cc18f8..a091e37 100644
--- a/src/llvm-project/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
+++ b/src/llvm-project/llvm/tools/llvm-tli-checker/llvm-tli-checker.cpp
@@ -28,9 +28,7 @@
 namespace {
 enum ID {
   OPT_INVALID = 0, // This is not an option ID.
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  OPT_##ID,
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
@@ -42,14 +40,9 @@
 #include "Opts.inc"
 #undef PREFIX
 
+using namespace llvm::opt;
 static constexpr opt::OptTable::Info InfoTable[] = {
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
-               HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      PREFIX,      NAME,      HELPTEXT,                                        \
-      METAVAR,     OPT_##ID,  opt::Option::KIND##Class,                        \
-      PARAM,       FLAGS,     OPT_##GROUP,                                     \
-      OPT_##ALIAS, ALIASARGS, VALUES},
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
 #include "Opts.inc"
 #undef OPTION
 };
diff --git a/src/llvm-project/llvm/tools/llvm-undname/llvm-undname.cpp b/src/llvm-project/llvm/tools/llvm-undname/llvm-undname.cpp
index 96f031a..d2d76de 100644
--- a/src/llvm-project/llvm/tools/llvm-undname/llvm-undname.cpp
+++ b/src/llvm-project/llvm/tools/llvm-undname/llvm-undname.cpp
@@ -116,7 +116,7 @@
 
       StringRef Line(LineStr);
       Line = Line.trim();
-      if (Line.empty() || Line.startswith("#") || Line.startswith(";"))
+      if (Line.empty() || Line.starts_with("#") || Line.starts_with(";"))
         continue;
 
       // If the user is manually typing in these decorated names, don't echo
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-account.h b/src/llvm-project/llvm/tools/llvm-xray/xray-account.h
index 38d3ec9..0f24f93 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-account.h
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-account.h
@@ -13,9 +13,7 @@
 #ifndef LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H
 #define LLVM_TOOLS_LLVM_XRAY_XRAY_ACCOUNT_H
 
-#include <map>
 #include <utility>
-#include <vector>
 
 #include "func-id-helper.h"
 #include "llvm/ADT/Bitfields.h"
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-converter.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-converter.cpp
index 82d0261..34832eb 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-converter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-converter.cpp
@@ -104,7 +104,7 @@
 void TraceConverter::exportAsRAWv1(const Trace &Records, raw_ostream &OS) {
   // First write out the file header, in the correct endian-appropriate format
   // (XRay assumes currently little endian).
-  support::endian::Writer Writer(OS, support::endianness::little);
+  support::endian::Writer Writer(OS, llvm::endianness::little);
   const auto &FH = Records.getFileHeader();
   Writer.write(FH.Version);
   Writer.write(FH.Type);
@@ -190,7 +190,7 @@
   SmallVector<StackTrieNode *, 4> Siblings{};
 
   if (parent == nullptr) {
-    for (auto map_iter : StackRootsByThreadId) {
+    for (const auto &map_iter : StackRootsByThreadId) {
       // Only look for siblings in other threads.
       if (map_iter.first != TId)
         for (auto node_iter : map_iter.second) {
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-fdr-dump.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-fdr-dump.cpp
index 295f7a7..017ff03 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-fdr-dump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-fdr-dump.cpp
@@ -101,7 +101,7 @@
 
   // Then we validate while printing each block.
   BlockVerifier BV;
-  for (auto ProcessThreadBlocks : Index) {
+  for (const auto &ProcessThreadBlocks : Index) {
     auto &Blocks = ProcessThreadBlocks.second;
     for (auto &B : Blocks) {
       for (auto *R : B.Records) {
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.cpp
index 8ccfd30..899a672 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.cpp
@@ -20,7 +20,6 @@
 #include "xray-registry.h"
 
 #include "xray-color-helper.h"
-#include "llvm/ADT/iterator_range.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/XRay/Trace.h"
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.h b/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.h
index 5d12c56..c2b2a93 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.h
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-graph-diff.h
@@ -15,7 +15,6 @@
 #define XRAY_GRAPH_DIFF_H
 
 #include "xray-graph.h"
-#include "llvm/ADT/StringMap.h"
 #include "llvm/XRay/Graph.h"
 
 namespace llvm {
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-stacks.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-stacks.cpp
index d04b998..aebca90 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-stacks.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-stacks.cpp
@@ -478,7 +478,7 @@
 
   /// Prints top stacks for each thread.
   void printPerThread(raw_ostream &OS, FuncIdConversionHelper &FN) {
-    for (auto iter : Roots) {
+    for (const auto &iter : Roots) {
       OS << "Thread " << iter.first << ":\n";
       print(OS, FN, iter.second);
       OS << "\n";
@@ -489,12 +489,8 @@
   template <AggregationType AggType>
   void printAllPerThread(raw_ostream &OS, FuncIdConversionHelper &FN,
                          StackOutputFormat format) {
-    for (auto iter : Roots) {
-      uint32_t threadId = iter.first;
-      RootVector &perThreadRoots = iter.second;
-      bool reportThreadId = true;
-      printAll<AggType>(OS, FN, perThreadRoots, threadId, reportThreadId);
-    }
+    for (const auto &iter : Roots)
+      printAll<AggType>(OS, FN, iter.second, iter.first, true);
   }
 
   /// Prints top stacks from looking at all the leaves and ignoring thread IDs.
@@ -521,7 +517,7 @@
   /// thread IDs.
   RootVector mergeAcrossThreads(std::forward_list<StackTrieNode> &NodeStore) {
     RootVector MergedByThreadRoots;
-    for (auto MapIter : Roots) {
+    for (const auto &MapIter : Roots) {
       const auto &RootNodeVector = MapIter.second;
       for (auto *Node : RootNodeVector) {
         auto MaybeFoundIter =
diff --git a/src/llvm-project/llvm/tools/llvm-yaml-numeric-parser-fuzzer/yaml-numeric-parser-fuzzer.cpp b/src/llvm-project/llvm/tools/llvm-yaml-numeric-parser-fuzzer/yaml-numeric-parser-fuzzer.cpp
index c61b509..c837028 100644
--- a/src/llvm-project/llvm/tools/llvm-yaml-numeric-parser-fuzzer/yaml-numeric-parser-fuzzer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-yaml-numeric-parser-fuzzer/yaml-numeric-parser-fuzzer.cpp
@@ -38,7 +38,7 @@
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
   std::string Input(reinterpret_cast<const char *>(Data), Size);
-  llvm::erase_value(Input, 0);
+  llvm::erase(Input, 0);
   if (!Input.empty() && llvm::yaml::isNumeric(Input) != isNumericRegex(Input))
     LLVM_BUILTIN_TRAP;
   return 0;
diff --git a/src/llvm-project/llvm/tools/llvm-yaml-parser-fuzzer/yaml-parser-fuzzer.cpp b/src/llvm-project/llvm/tools/llvm-yaml-parser-fuzzer/yaml-parser-fuzzer.cpp
index 007769f..b29920d 100644
--- a/src/llvm-project/llvm/tools/llvm-yaml-parser-fuzzer/yaml-parser-fuzzer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-yaml-parser-fuzzer/yaml-parser-fuzzer.cpp
@@ -25,7 +25,7 @@
   isValidYaml(Input.data(), Input.size());
 
   // Ensure we don't crash on byte strings with no null characters.
-  llvm::erase_value(Input, 0);
+  llvm::erase(Input, 0);
   Input.shrink_to_fit();
   bool IsValidWithout0s = isValidYaml(Input.data(), Input.size());
 
diff --git a/src/llvm-project/llvm/tools/lto/lto.cpp b/src/llvm-project/llvm/tools/lto/lto.cpp
index 22ebf54..ece6dd0 100644
--- a/src/llvm-project/llvm/tools/lto/lto.cpp
+++ b/src/llvm-project/llvm/tools/lto/lto.cpp
@@ -528,7 +528,7 @@
     if (OptLevel < '0' || OptLevel > '3')
       report_fatal_error("Optimization level must be between 0 and 3");
     CodeGen->setOptLevel(OptLevel - '0');
-    std::optional<CodeGenOpt::Level> CGOptLevelOrNone =
+    std::optional<CodeGenOptLevel> CGOptLevelOrNone =
         CodeGenOpt::getLevel(OptLevel - '0');
     assert(CGOptLevelOrNone);
     CodeGen->setCodeGenOptLevel(*CGOptLevelOrNone);
diff --git a/src/llvm-project/llvm/tools/obj2yaml/archive2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/archive2yaml.cpp
index c7b0ee4..35bcd43 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/archive2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/archive2yaml.cpp
@@ -24,7 +24,7 @@
         std::make_unique<ArchYAML::Archive>();
 
     StringRef Magic = "!<arch>\n";
-    if (!Buffer.startswith(Magic))
+    if (!Buffer.starts_with(Magic))
       return createStringError(std::errc::not_supported,
                                "only regular archives are supported");
     Obj->Magic = Magic;
diff --git a/src/llvm-project/llvm/tools/obj2yaml/coff2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/coff2yaml.cpp
index 604799f..2f80e62 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/coff2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/coff2yaml.cpp
@@ -123,7 +123,7 @@
 
     cantFail(Obj.getSectionContents(COFFSection, sectionData));
 
-    BinaryStreamReader Reader(sectionData, support::little);
+    BinaryStreamReader Reader(sectionData, llvm::endianness::little);
     uint32_t Magic;
 
     Err(Reader.readInteger(Magic));
diff --git a/src/llvm-project/llvm/tools/obj2yaml/dwarf2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/dwarf2yaml.cpp
index 3d3798d..b3062c4 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/dwarf2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/dwarf2yaml.cpp
@@ -22,15 +22,17 @@
 
 using namespace llvm;
 
-void dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) {
+Error dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) {
   auto AbbrevSetPtr = DCtx.getDebugAbbrev();
   if (AbbrevSetPtr) {
     uint64_t AbbrevTableID = 0;
-    AbbrevSetPtr->parse();
-    for (auto AbbrvDeclSet : *AbbrevSetPtr) {
+    if (Error Err = AbbrevSetPtr->parse())
+      return Err;
+    for (const auto &AbbrvDeclSet : *AbbrevSetPtr) {
       Y.DebugAbbrev.emplace_back();
       Y.DebugAbbrev.back().ID = AbbrevTableID++;
-      for (auto AbbrvDecl : AbbrvDeclSet.second) {
+      for (const DWARFAbbreviationDeclaration &AbbrvDecl :
+           AbbrvDeclSet.second) {
         DWARFYAML::Abbrev Abbrv;
         Abbrv.Code = AbbrvDecl.getCode();
         Abbrv.Tag = AbbrvDecl.getTag();
@@ -48,6 +50,7 @@
       }
     }
   }
+  return Error::success();
 }
 
 Error dumpDebugAddr(DWARFContext &DCtx, DWARFYAML::Data &Y) {
@@ -220,7 +223,12 @@
     if (NewUnit.Version >= 5)
       NewUnit.Type = (dwarf::UnitType)CU->getUnitType();
     const DWARFDebugAbbrev *DebugAbbrev = DCtx.getDebugAbbrev();
-    DebugAbbrev->parse();
+    // FIXME: Ideally we would propagate this error upwards, but that would
+    // prevent us from displaying any debug info at all. For now we just consume
+    // the error and display everything that was parsed successfully.
+    if (Error Err = DebugAbbrev->parse())
+      llvm::consumeError(std::move(Err));
+
     NewUnit.AbbrevTableID = std::distance(
         DebugAbbrev->begin(),
         llvm::find_if(
diff --git a/src/llvm-project/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
index dd3bea6..b58d7cd 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
@@ -16,6 +16,16 @@
 using namespace llvm;
 using namespace llvm::object;
 
+static DXContainerYAML::Signature dumpSignature(const DirectX::Signature &Sig) {
+  DXContainerYAML::Signature YAML;
+  for (auto Param : Sig)
+    YAML.Parameters.push_back(DXContainerYAML::SignatureParameter{
+        Param.Stream, Sig.getName(Param.NameOffset).str(), Param.Index,
+        Param.SystemValue, Param.CompType, Param.Register, Param.Mask,
+        Param.ExclusiveMask, Param.MinPrecision});
+  return YAML;
+}
+
 static Expected<DXContainerYAML::Object *>
 dumpDXContainer(MemoryBufferRef Source) {
   assert(file_magic::dxcontainer_object == identify_magic(Source.getBuffer()));
@@ -92,8 +102,52 @@
       NewPart.Info->ResourceStride = PSVInfo->getResourceStride();
       for (auto Res : PSVInfo->getResources())
         NewPart.Info->Resources.push_back(Res);
+
+      for (auto El : PSVInfo->getSigInputElements())
+        NewPart.Info->SigInputElements.push_back(
+            DXContainerYAML::SignatureElement(
+                El, PSVInfo->getStringTable(),
+                PSVInfo->getSemanticIndexTable()));
+      for (auto El : PSVInfo->getSigOutputElements())
+        NewPart.Info->SigOutputElements.push_back(
+            DXContainerYAML::SignatureElement(
+                El, PSVInfo->getStringTable(),
+                PSVInfo->getSemanticIndexTable()));
+      for (auto El : PSVInfo->getSigPatchOrPrimElements())
+        NewPart.Info->SigPatchOrPrimElements.push_back(
+            DXContainerYAML::SignatureElement(
+                El, PSVInfo->getStringTable(),
+                PSVInfo->getSemanticIndexTable()));
+
+      if (PSVInfo->usesViewID()) {
+        for (int I = 0; I < 4; ++I)
+          for (auto Mask : PSVInfo->getOutputVectorMasks(I))
+            NewPart.Info->OutputVectorMasks[I].push_back(Mask);
+        for (auto Mask : PSVInfo->getPatchOrPrimMasks())
+          NewPart.Info->PatchOrPrimMasks.push_back(Mask);
+      }
+
+      for (int I = 0; I < 4; ++I)
+        for (auto Mask : PSVInfo->getInputOutputMap(I))
+          NewPart.Info->InputOutputMap[I].push_back(Mask);
+
+      for (auto Mask : PSVInfo->getInputPatchMap())
+        NewPart.Info->InputPatchMap.push_back(Mask);
+
+      for (auto Mask : PSVInfo->getPatchOutputMap())
+        NewPart.Info->PatchOutputMap.push_back(Mask);
+
       break;
     }
+    case dxbc::PartType::ISG1:
+      NewPart.Signature = dumpSignature(Container.getInputSignature());
+      break;
+    case dxbc::PartType::OSG1:
+      NewPart.Signature = dumpSignature(Container.getOutputSignature());
+      break;
+    case dxbc::PartType::PSG1:
+      NewPart.Signature = dumpSignature(Container.getPatchConstantSignature());
+      break;
     case dxbc::PartType::Unknown:
       break;
     }
diff --git a/src/llvm-project/llvm/tools/obj2yaml/elf2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/elf2yaml.cpp
index b261b9d..86bd138 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "obj2yaml.h"
-#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Twine.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
@@ -300,7 +299,7 @@
   }
 
   // Normally an object that does not have sections has e_shnum == 0.
-  // Also, e_shnum might be 0, when the the number of entries in the section
+  // Also, e_shnum might be 0, when the number of entries in the section
   // header table is larger than or equal to SHN_LORESERVE (0xff00). In this
   // case the real number of entries is held in the sh_size member of the
   // initial entry. We have a section header table when `e_shoff` is not 0.
@@ -484,6 +483,7 @@
     PH.Flags = Phdr.p_flags;
     PH.VAddr = Phdr.p_vaddr;
     PH.PAddr = Phdr.p_paddr;
+    PH.Offset = Phdr.p_offset;
 
     // yaml2obj sets the alignment of a segment to 1 by default.
     // We do not print the default alignment to reduce noise in the output.
@@ -514,7 +514,7 @@
     std::vector<std::unique_ptr<ELFYAML::Chunk>> &Sections) {
   DWARFYAML::Data DWARF;
   for (std::unique_ptr<ELFYAML::Chunk> &C : Sections) {
-    if (!C->Name.startswith(".debug_"))
+    if (!C->Name.starts_with(".debug_"))
       continue;
 
     if (ELFYAML::RawContentSection *RawSec =
diff --git a/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp
index c96b6cc..cdd871e 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp
@@ -15,6 +15,7 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/LEB128.h"
+#include "llvm/Support/SystemZ/zOSSupport.h"
 
 #include <string.h> // for memcpy
 
@@ -139,10 +140,8 @@
 
 static Error dumpDebugSection(StringRef SecName, DWARFContext &DCtx,
                               DWARFYAML::Data &DWARF) {
-  if (SecName == "__debug_abbrev") {
-    dumpDebugAbbrev(DCtx, DWARF);
-    return Error::success();
-  }
+  if (SecName == "__debug_abbrev")
+    return dumpDebugAbbrev(DCtx, DWARF);
   if (SecName == "__debug_aranges")
     return dumpDebugARanges(DCtx, DWARF);
   if (SecName == "__debug_info") {
@@ -153,7 +152,7 @@
     dumpDebugLines(DCtx, DWARF);
     return Error::success();
   }
-  if (SecName.startswith("__debug_pub")) {
+  if (SecName.starts_with("__debug_pub")) {
     // FIXME: We should extract pub-section dumpers from this function.
     dumpDebugPubSections(DCtx, DWARF);
     return Error::success();
@@ -185,11 +184,11 @@
 
       // Copy data sections if requested.
       if ((RawSegment & ::RawSegments::data) &&
-          StringRef(S->segname).startswith("__DATA"))
+          StringRef(S->segname).starts_with("__DATA"))
         S->content =
             yaml::BinaryRef(Obj.getSectionContents(Sec.offset, Sec.size));
 
-      if (SecName.startswith("__debug_")) {
+      if (SecName.starts_with("__debug_")) {
         // If the DWARF section cannot be successfully parsed, emit raw content
         // instead of an entry in the DWARF section of the YAML.
         if (Error Err = dumpDebugSection(SecName, *DWARFCtx, Y.DWARF))
@@ -533,7 +532,7 @@
  * terminal.
 */
 
-const uint8_t *processExportNode(const uint8_t *CurrPtr,
+const uint8_t *processExportNode(const uint8_t *Start, const uint8_t *CurrPtr,
                                  const uint8_t *const End,
                                  MachOYAML::ExportEntry &Entry) {
   if (CurrPtr >= End)
@@ -572,7 +571,7 @@
     CurrPtr += Count;
   }
   for (auto &Child : Entry.Children) {
-    CurrPtr = processExportNode(CurrPtr, End, Child);
+    CurrPtr = processExportNode(Start, Start + Child.NodeOffset, End, Child);
   }
   return CurrPtr;
 }
@@ -583,7 +582,8 @@
   auto ExportsTrie = Obj.getDyldInfoExportsTrie();
   if (ExportsTrie.empty())
     ExportsTrie = Obj.getDyldExportsTrie();
-  processExportNode(ExportsTrie.begin(), ExportsTrie.end(), LEData.ExportTrie);
+  processExportNode(ExportsTrie.begin(), ExportsTrie.begin(), ExportsTrie.end(),
+                    LEData.ExportTrie);
 }
 
 template <typename nlist_t>
diff --git a/src/llvm-project/llvm/tools/obj2yaml/obj2yaml.h b/src/llvm-project/llvm/tools/obj2yaml/obj2yaml.h
index e0204c6..03d7db5 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/obj2yaml.h
+++ b/src/llvm-project/llvm/tools/obj2yaml/obj2yaml.h
@@ -46,7 +46,7 @@
 }
 } // namespace llvm
 
-void dumpDebugAbbrev(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y);
+llvm::Error dumpDebugAbbrev(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y);
 llvm::Error dumpDebugAddr(llvm::DWARFContext &DCtx, llvm::DWARFYAML::Data &Y);
 llvm::Error dumpDebugARanges(llvm::DWARFContext &DCtx,
                              llvm::DWARFYAML::Data &Y);
diff --git a/src/llvm-project/llvm/tools/obj2yaml/wasm2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/wasm2yaml.cpp
index c450c02..c15d64c 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/wasm2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/wasm2yaml.cpp
@@ -44,7 +44,7 @@
                                  const wasm::WasmTableType &Type) {
   WasmYAML::Table T;
   T.Index = Index;
-  T.ElemType = Type.ElemType;
+  T.ElemType = (uint32_t)Type.ElemType;
   T.TableLimits = makeLimits(Type.Limits);
   return T;
 }
@@ -205,7 +205,7 @@
     std::unique_ptr<WasmYAML::Section> S;
     switch (WasmSec.Type) {
     case wasm::WASM_SEC_CUSTOM: {
-      if (WasmSec.Name.startswith("reloc.")) {
+      if (WasmSec.Name.starts_with("reloc.")) {
         // Relocations are attached the sections they apply to rather than
         // being represented as a custom section in the YAML output.
         continue;
@@ -334,7 +334,7 @@
         WasmYAML::ElemSegment Seg;
         Seg.Flags = Segment.Flags;
         Seg.TableNumber = Segment.TableNumber;
-        Seg.ElemKind = Segment.ElemKind;
+        Seg.ElemKind = (uint32_t)Segment.ElemKind;
         Seg.Offset.Extended = Segment.Offset.Extended;
         if (Seg.Offset.Extended) {
           Seg.Offset.Body = yaml::BinaryRef(Segment.Offset.Body);
diff --git a/src/llvm-project/llvm/tools/obj2yaml/xcoff2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/xcoff2yaml.cpp
index 882c410..0acbf48 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/xcoff2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/xcoff2yaml.cpp
@@ -25,10 +25,30 @@
   template <typename Shdr, typename Reloc>
   Error dumpSections(ArrayRef<Shdr> Sections);
 
+  // Dump auxiliary symbols.
+  Error dumpFileAuxSym(XCOFFYAML::Symbol &Sym,
+                       const XCOFFSymbolRef &SymbolEntRef);
+  Error dumpStatAuxSym(XCOFFYAML::Symbol &Sym,
+                       const XCOFFSymbolRef &SymbolEntRef);
+  Error dumpBlockAuxSym(XCOFFYAML::Symbol &Sym,
+                        const XCOFFSymbolRef &SymbolEntRef);
+  Error dumpDwarfAuxSym(XCOFFYAML::Symbol &Sym,
+                        const XCOFFSymbolRef &SymbolEntRef);
+  Error dumpAuxSyms(XCOFFYAML::Symbol &Sym, const XCOFFSymbolRef &SymbolEntRef);
+  void dumpFuncAuxSym(XCOFFYAML::Symbol &Sym, const uintptr_t AuxAddress);
+  void dumpExpAuxSym(XCOFFYAML::Symbol &Sym, const uintptr_t AuxAddress);
+  void dumpCsectAuxSym(XCOFFYAML::Symbol &Sym,
+                       const object::XCOFFCsectAuxRef &AuxEntPtr);
+
 public:
   XCOFFDumper(const object::XCOFFObjectFile &obj) : Obj(obj) {}
   Error dump();
   XCOFFYAML::Object &getYAMLObj() { return YAMLObj; }
+
+  template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress) {
+    Obj.checkSymbolEntryPointer(AuxAddress);
+    return reinterpret_cast<const T *>(AuxAddress);
+  }
 };
 } // namespace
 
@@ -106,6 +126,210 @@
   return Error::success();
 }
 
+Error XCOFFDumper::dumpFileAuxSym(XCOFFYAML::Symbol &Sym,
+                                  const XCOFFSymbolRef &SymbolEntRef) {
+  for (uint8_t I = 1; I <= Sym.NumberOfAuxEntries; ++I) {
+    uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
+        SymbolEntRef.getEntryAddress(), I);
+    const XCOFFFileAuxEnt *FileAuxEntPtr =
+        getAuxEntPtr<XCOFFFileAuxEnt>(AuxAddress);
+    auto FileNameOrError = Obj.getCFileName(FileAuxEntPtr);
+    if (!FileNameOrError)
+      return FileNameOrError.takeError();
+
+    XCOFFYAML::FileAuxEnt FileAuxSym;
+    FileAuxSym.FileNameOrString = FileNameOrError.get();
+    FileAuxSym.FileStringType = FileAuxEntPtr->Type;
+    Sym.AuxEntries.push_back(
+        std::make_unique<XCOFFYAML::FileAuxEnt>(FileAuxSym));
+  }
+  return Error::success();
+}
+
+Error XCOFFDumper::dumpStatAuxSym(XCOFFYAML::Symbol &Sym,
+                                  const XCOFFSymbolRef &SymbolEntRef) {
+  if (Sym.NumberOfAuxEntries != 1) {
+    uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
+    return createError("failed to parse symbol \"" + Sym.SymbolName +
+                       "\" with index of " + Twine(SymbolIndex) +
+                       ": expected 1 aux symbol for C_STAT, while got " +
+                       Twine(static_cast<uint32_t>(*Sym.NumberOfAuxEntries)));
+  }
+
+  const XCOFFSectAuxEntForStat *AuxEntPtr =
+      getAuxEntPtr<XCOFFSectAuxEntForStat>(
+          XCOFFObjectFile::getAdvancedSymbolEntryAddress(
+              SymbolEntRef.getEntryAddress(), 1));
+  XCOFFYAML::SectAuxEntForStat StatAuxSym;
+  StatAuxSym.SectionLength = AuxEntPtr->SectionLength;
+  StatAuxSym.NumberOfLineNum = AuxEntPtr->NumberOfLineNum;
+  StatAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt;
+  Sym.AuxEntries.push_back(
+      std::make_unique<XCOFFYAML::SectAuxEntForStat>(StatAuxSym));
+  return Error::success();
+}
+
+void XCOFFDumper::dumpFuncAuxSym(XCOFFYAML::Symbol &Sym,
+                                 const uintptr_t AuxAddress) {
+  XCOFFYAML::FunctionAuxEnt FunAuxSym;
+
+  if (Obj.is64Bit()) {
+    const XCOFFFunctionAuxEnt64 *AuxEntPtr =
+        getAuxEntPtr<XCOFFFunctionAuxEnt64>(AuxAddress);
+    FunAuxSym.PtrToLineNum = AuxEntPtr->PtrToLineNum;
+    FunAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction;
+    FunAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond;
+  } else {
+    const XCOFFFunctionAuxEnt32 *AuxEntPtr =
+        getAuxEntPtr<XCOFFFunctionAuxEnt32>(AuxAddress);
+    FunAuxSym.OffsetToExceptionTbl = AuxEntPtr->OffsetToExceptionTbl;
+    FunAuxSym.PtrToLineNum = AuxEntPtr->PtrToLineNum;
+    FunAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction;
+    FunAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond;
+  }
+
+  Sym.AuxEntries.push_back(
+      std::make_unique<XCOFFYAML::FunctionAuxEnt>(FunAuxSym));
+}
+
+void XCOFFDumper::dumpExpAuxSym(XCOFFYAML::Symbol &Sym,
+                                const uintptr_t AuxAddress) {
+  const XCOFFExceptionAuxEnt *AuxEntPtr =
+      getAuxEntPtr<XCOFFExceptionAuxEnt>(AuxAddress);
+  XCOFFYAML::ExcpetionAuxEnt ExceptAuxSym;
+  ExceptAuxSym.OffsetToExceptionTbl = AuxEntPtr->OffsetToExceptionTbl;
+  ExceptAuxSym.SizeOfFunction = AuxEntPtr->SizeOfFunction;
+  ExceptAuxSym.SymIdxOfNextBeyond = AuxEntPtr->SymIdxOfNextBeyond;
+  Sym.AuxEntries.push_back(
+      std::make_unique<XCOFFYAML::ExcpetionAuxEnt>(ExceptAuxSym));
+}
+
+void XCOFFDumper::dumpCsectAuxSym(XCOFFYAML::Symbol &Sym,
+                                  const object::XCOFFCsectAuxRef &AuxEntPtr) {
+  XCOFFYAML::CsectAuxEnt CsectAuxSym;
+  CsectAuxSym.ParameterHashIndex = AuxEntPtr.getParameterHashIndex();
+  CsectAuxSym.TypeChkSectNum = AuxEntPtr.getTypeChkSectNum();
+  CsectAuxSym.SymbolAlignmentAndType = AuxEntPtr.getSymbolAlignmentAndType();
+  CsectAuxSym.StorageMappingClass = AuxEntPtr.getStorageMappingClass();
+
+  if (Obj.is64Bit()) {
+    CsectAuxSym.SectionOrLengthLo =
+        static_cast<uint32_t>(AuxEntPtr.getSectionOrLength64());
+    CsectAuxSym.SectionOrLengthHi =
+        static_cast<uint32_t>(AuxEntPtr.getSectionOrLength64() >> 32);
+  } else {
+    CsectAuxSym.SectionOrLength = AuxEntPtr.getSectionOrLength32();
+    CsectAuxSym.StabInfoIndex = AuxEntPtr.getStabInfoIndex32();
+    CsectAuxSym.StabSectNum = AuxEntPtr.getStabSectNum32();
+  }
+
+  Sym.AuxEntries.push_back(
+      std::make_unique<XCOFFYAML::CsectAuxEnt>(CsectAuxSym));
+}
+
+Error XCOFFDumper::dumpAuxSyms(XCOFFYAML::Symbol &Sym,
+                               const XCOFFSymbolRef &SymbolEntRef) {
+  auto ErrOrCsectAuxRef = SymbolEntRef.getXCOFFCsectAuxRef();
+  if (!ErrOrCsectAuxRef)
+    return ErrOrCsectAuxRef.takeError();
+  XCOFFCsectAuxRef CsectAuxRef = ErrOrCsectAuxRef.get();
+
+  for (uint8_t I = 1; I <= Sym.NumberOfAuxEntries; ++I) {
+
+    if (I == Sym.NumberOfAuxEntries && !Obj.is64Bit()) {
+      dumpCsectAuxSym(Sym, CsectAuxRef);
+      return Error::success();
+    }
+
+    uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
+        SymbolEntRef.getEntryAddress(), I);
+
+    if (Obj.is64Bit()) {
+      XCOFF::SymbolAuxType Type = *Obj.getSymbolAuxType(AuxAddress);
+      if (Type == XCOFF::SymbolAuxType::AUX_CSECT)
+        dumpCsectAuxSym(Sym, CsectAuxRef);
+      else if (Type == XCOFF::SymbolAuxType::AUX_FCN)
+        dumpFuncAuxSym(Sym, AuxAddress);
+      else if (Type == XCOFF::SymbolAuxType::AUX_EXCEPT)
+        dumpExpAuxSym(Sym, AuxAddress);
+      else {
+        uint32_t SymbolIndex =
+            Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
+        return createError("failed to parse symbol \"" + Sym.SymbolName +
+                           "\" with index of " + Twine(SymbolIndex) +
+                           ": invalid auxiliary symbol type: " +
+                           Twine(static_cast<uint32_t>(Type)));
+      }
+
+    } else
+      dumpFuncAuxSym(Sym, AuxAddress);
+  }
+
+  return Error::success();
+}
+
+Error XCOFFDumper::dumpBlockAuxSym(XCOFFYAML::Symbol &Sym,
+                                   const XCOFFSymbolRef &SymbolEntRef) {
+  if (Sym.NumberOfAuxEntries != 1) {
+    uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
+    return createError(
+        "failed to parse symbol \"" + Sym.SymbolName + "\" with index of " +
+        Twine(SymbolIndex) +
+        ": expected 1 aux symbol for C_BLOCK or C_FCN, while got " +
+        Twine(static_cast<uint32_t>(*Sym.NumberOfAuxEntries)));
+  }
+
+  uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
+      SymbolEntRef.getEntryAddress(), 1);
+  XCOFFYAML::BlockAuxEnt BlockAuxSym;
+
+  if (Obj.is64Bit()) {
+    const XCOFFBlockAuxEnt64 *AuxEntPtr =
+        getAuxEntPtr<XCOFFBlockAuxEnt64>(AuxAddress);
+    BlockAuxSym.LineNum = AuxEntPtr->LineNum;
+  } else {
+    const XCOFFBlockAuxEnt32 *AuxEntPtr =
+        getAuxEntPtr<XCOFFBlockAuxEnt32>(AuxAddress);
+    BlockAuxSym.LineNumLo = AuxEntPtr->LineNumLo;
+    BlockAuxSym.LineNumHi = AuxEntPtr->LineNumHi;
+  }
+
+  Sym.AuxEntries.push_back(
+      std::make_unique<XCOFFYAML::BlockAuxEnt>(BlockAuxSym));
+  return Error::success();
+}
+
+Error XCOFFDumper::dumpDwarfAuxSym(XCOFFYAML::Symbol &Sym,
+                                   const XCOFFSymbolRef &SymbolEntRef) {
+  if (Sym.NumberOfAuxEntries != 1) {
+    uint32_t SymbolIndex = Obj.getSymbolIndex(SymbolEntRef.getEntryAddress());
+    return createError("failed to parse symbol \"" + Sym.SymbolName +
+                       "\" with index of " + Twine(SymbolIndex) +
+                       ": expected 1 aux symbol for C_DWARF, while got " +
+                       Twine(static_cast<uint32_t>(*Sym.NumberOfAuxEntries)));
+  }
+
+  uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
+      SymbolEntRef.getEntryAddress(), 1);
+  XCOFFYAML::SectAuxEntForDWARF DwarfAuxSym;
+
+  if (Obj.is64Bit()) {
+    const XCOFFSectAuxEntForDWARF64 *AuxEntPtr =
+        getAuxEntPtr<XCOFFSectAuxEntForDWARF64>(AuxAddress);
+    DwarfAuxSym.LengthOfSectionPortion = AuxEntPtr->LengthOfSectionPortion;
+    DwarfAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt;
+  } else {
+    const XCOFFSectAuxEntForDWARF32 *AuxEntPtr =
+        getAuxEntPtr<XCOFFSectAuxEntForDWARF32>(AuxAddress);
+    DwarfAuxSym.LengthOfSectionPortion = AuxEntPtr->LengthOfSectionPortion;
+    DwarfAuxSym.NumberOfRelocEnt = AuxEntPtr->NumberOfRelocEnt;
+  }
+
+  Sym.AuxEntries.push_back(
+      std::make_unique<XCOFFYAML::SectAuxEntForDWARF>(DwarfAuxSym));
+  return Error::success();
+}
+
 Error XCOFFDumper::dumpSymbols() {
   std::vector<XCOFFYAML::Symbol> &Symbols = YAMLObj.Symbols;
 
@@ -133,6 +357,36 @@
     Sym.StorageClass = SymbolEntRef.getStorageClass();
     Sym.NumberOfAuxEntries = SymbolEntRef.getNumberOfAuxEntries();
 
+    if (Sym.NumberOfAuxEntries) {
+      switch (Sym.StorageClass) {
+      case XCOFF::C_FILE:
+        if (Error E = dumpFileAuxSym(Sym, SymbolEntRef))
+          return E;
+        break;
+      case XCOFF::C_STAT:
+        if (Error E = dumpStatAuxSym(Sym, SymbolEntRef))
+          return E;
+        break;
+      case XCOFF::C_EXT:
+      case XCOFF::C_WEAKEXT:
+      case XCOFF::C_HIDEXT:
+        if (Error E = dumpAuxSyms(Sym, SymbolEntRef))
+          return E;
+        break;
+      case XCOFF::C_BLOCK:
+      case XCOFF::C_FCN:
+        if (Error E = dumpBlockAuxSym(Sym, SymbolEntRef))
+          return E;
+        break;
+      case XCOFF::C_DWARF:
+        if (Error E = dumpDwarfAuxSym(Sym, SymbolEntRef))
+          return E;
+        break;
+      default:
+        break;
+      }
+    }
+
     Symbols.push_back(std::move(Sym));
   }
 
diff --git a/src/llvm-project/llvm/tools/opt/opt.cpp b/src/llvm-project/llvm/tools/opt/opt.cpp
index 9c20e77..8c0e989 100644
--- a/src/llvm-project/llvm/tools/opt/opt.cpp
+++ b/src/llvm-project/llvm/tools/opt/opt.cpp
@@ -39,6 +39,7 @@
 #include "llvm/Passes/PassPlugin.h"
 #include "llvm/Remarks/HotnessThresholdParser.h"
 #include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/PluginLoader.h"
@@ -149,34 +150,32 @@
     StripNamedMetadata("strip-named-metadata",
                        cl::desc("Strip module-level named metadata"));
 
-
-
 static cl::opt<bool>
     OptLevelO0("O0", cl::desc("Optimization level 0. Similar to clang -O0. "
-                              "Use -passes='default<O0>' for the new PM"));
+                              "Same as -passes='default<O0>'"));
 
 static cl::opt<bool>
     OptLevelO1("O1", cl::desc("Optimization level 1. Similar to clang -O1. "
-                              "Use -passes='default<O1>' for the new PM"));
+                              "Same as -passes='default<O1>'"));
 
 static cl::opt<bool>
     OptLevelO2("O2", cl::desc("Optimization level 2. Similar to clang -O2. "
-                              "Use -passes='default<O2>' for the new PM"));
+                              "Same as -passes='default<O2>'"));
 
 static cl::opt<bool>
     OptLevelOs("Os", cl::desc("Like -O2 but size-conscious. Similar to clang "
-                              "-Os. Use -passes='default<Os>' for the new PM"));
+                              "-Os. Same as -passes='default<Os>'"));
 
 static cl::opt<bool> OptLevelOz(
     "Oz",
     cl::desc("Like -O2 but optimize for code size above all else. Similar to "
-             "clang -Oz. Use -passes='default<Oz>' for the new PM"));
+             "clang -Oz. Same as -passes='default<Oz>'"));
 
 static cl::opt<bool>
     OptLevelO3("O3", cl::desc("Optimization level 3. Similar to clang -O3. "
-                              "Use -passes='default<O3>' for the new PM"));
+                              "Same as -passes='default<O3>'"));
 
-static cl::opt<unsigned> CodeGenOptLevel(
+static cl::opt<unsigned> CodeGenOptLevelCL(
     "codegen-opt-level",
     cl::desc("Override optimization level for codegen hooks, legacy PM only"));
 
@@ -280,30 +279,19 @@
     PassPlugins("load-pass-plugin",
                 cl::desc("Load passes from plugin library"));
 
+static cl::opt<bool> TryUseNewDbgInfoFormat(
+    "try-experimental-debuginfo-iterators",
+    cl::desc("Enable debuginfo iterator positions, if they're built in"),
+    cl::init(false), cl::Hidden);
+
+extern cl::opt<bool> UseNewDbgInfoFormat;
+
 //===----------------------------------------------------------------------===//
 // CodeGen-related helper functions.
 //
 
-static CodeGenOpt::Level GetCodeGenOptLevel() {
-  return static_cast<CodeGenOpt::Level>(unsigned(CodeGenOptLevel));
-}
-
-// Returns the TargetMachine instance or zero if no triple is provided.
-static TargetMachine* GetTargetMachine(Triple TheTriple, StringRef CPUStr,
-                                       StringRef FeaturesStr,
-                                       const TargetOptions &Options) {
-  std::string Error;
-  const Target *TheTarget =
-      TargetRegistry::lookupTarget(codegen::getMArch(), TheTriple, Error);
-  // Some modules don't specify a triple, and this is okay.
-  if (!TheTarget) {
-    return nullptr;
-  }
-
-  return TheTarget->createTargetMachine(
-      TheTriple.getTriple(), codegen::getCPUStr(), codegen::getFeaturesStr(),
-      Options, codegen::getExplicitRelocModel(),
-      codegen::getExplicitCodeModel(), GetCodeGenOptLevel());
+static CodeGenOptLevel GetCodeGenOptLevel() {
+  return static_cast<CodeGenOptLevel>(unsigned(CodeGenOptLevelCL));
 }
 
 struct TimeTracerRAII {
@@ -333,6 +321,7 @@
       "nvvm-reflect",
       "nvvm-intr-range",
       "amdgpu-simplifylib",
+      "amdgpu-image-intrinsic-opt",
       "amdgpu-usenative",
       "amdgpu-promote-alloca",
       "amdgpu-promote-alloca-to-vector",
@@ -350,7 +339,7 @@
       "nvptx-",  "mips-",  "lanai-", "hexagon-", "bpf-",    "avr-",
       "thumb2-", "arm-",   "si-",    "gcn-",     "amdgpu-", "aarch64-",
       "amdgcn-", "polly-", "riscv-", "dxil-"};
-  std::vector<StringRef> PassNameContain = {"ehprepare"};
+  std::vector<StringRef> PassNameContain = {"-eh-prepare"};
   std::vector<StringRef> PassNameExact = {
       "safe-stack",
       "cost-model",
@@ -367,15 +356,14 @@
       "expand-reductions",
       "indirectbr-expand",
       "generic-to-nvvm",
-      "expandmemcmp",
+      "expand-memcmp",
       "loop-reduce",
       "lower-amx-type",
-      "pre-amx-config",
       "lower-amx-intrinsics",
       "polyhedral-info",
       "print-polyhedral-info",
       "replace-with-veclib",
-      "jmc-instrument",
+      "jmc-instrumenter",
       "dot-regions",
       "dot-regions-only",
       "view-regions",
@@ -388,7 +376,7 @@
       "callbrprepare",
   };
   for (const auto &P : PassNamePrefix)
-    if (Pass.startswith(P))
+    if (Pass.starts_with(P))
       return true;
   for (const auto &P : PassNameContain)
     if (Pass.contains(P))
@@ -434,11 +422,11 @@
   // supported.
   initializeExpandLargeDivRemLegacyPassPass(Registry);
   initializeExpandLargeFpConvertLegacyPassPass(Registry);
-  initializeExpandMemCmpPassPass(Registry);
+  initializeExpandMemCmpLegacyPassPass(Registry);
   initializeScalarizeMaskedMemIntrinLegacyPassPass(Registry);
   initializeSelectOptimizePass(Registry);
   initializeCallBrPreparePass(Registry);
-  initializeCodeGenPreparePass(Registry);
+  initializeCodeGenPrepareLegacyPassPass(Registry);
   initializeAtomicExpandPass(Registry);
   initializeWinEHPreparePass(Registry);
   initializeDwarfEHPrepareLegacyPassPass(Registry);
@@ -446,7 +434,7 @@
   initializeSjLjEHPreparePass(Registry);
   initializePreISelIntrinsicLoweringLegacyPassPass(Registry);
   initializeGlobalMergePass(Registry);
-  initializeIndirectBrExpandPassPass(Registry);
+  initializeIndirectBrExpandLegacyPassPass(Registry);
   initializeInterleavedLoadCombinePass(Registry);
   initializeInterleavedAccessPass(Registry);
   initializeUnreachableBlockElimLegacyPassPass(Registry);
@@ -460,11 +448,8 @@
   SmallVector<PassPlugin, 1> PluginList;
   PassPlugins.setCallback([&](const std::string &PluginPath) {
     auto Plugin = PassPlugin::Load(PluginPath);
-    if (!Plugin) {
-      errs() << "Failed to load passes from '" << PluginPath
-             << "'. Request ignored.\n";
-      return;
-    }
+    if (!Plugin)
+      report_fatal_error(Plugin.takeError(), /*gen_crash_diag=*/false);
     PluginList.emplace_back(Plugin.get());
   });
 
@@ -474,6 +459,17 @@
   cl::ParseCommandLineOptions(argc, argv,
     "llvm .bc -> .bc modular optimizer and analysis printer\n");
 
+  // RemoveDIs debug-info transition: tests may request that we /try/ to use the
+  // new debug-info format, if it's built in.
+#ifdef EXPERIMENTAL_DEBUGINFO_ITERATORS
+  if (TryUseNewDbgInfoFormat) {
+    // If LLVM was built with support for this, turn the new debug-info format
+    // on.
+    UseNewDbgInfoFormat = true;
+  }
+#endif
+  (void)TryUseNewDbgInfoFormat;
+
   LLVMContext Context;
 
   // TODO: remove shouldForceLegacyPM().
@@ -522,10 +518,36 @@
   std::unique_ptr<ToolOutputFile> RemarksFile = std::move(*RemarksFileOrErr);
 
   // Load the input module...
-  auto SetDataLayout = [](StringRef, StringRef) -> std::optional<std::string> {
-    if (ClDataLayout.empty())
+  auto SetDataLayout = [&](StringRef IRTriple,
+                           StringRef IRLayout) -> std::optional<std::string> {
+    // Data layout specified on the command line has the highest priority.
+    if (!ClDataLayout.empty())
+      return ClDataLayout;
+    // If an explicit data layout is already defined in the IR, don't infer.
+    if (!IRLayout.empty())
       return std::nullopt;
-    return ClDataLayout;
+
+    // If an explicit triple was specified (either in the IR or on the
+    // command line), use that to infer the default data layout. However, the
+    // command line target triple should override the IR file target triple.
+    std::string TripleStr =
+        TargetTriple.empty() ? IRTriple.str() : Triple::normalize(TargetTriple);
+    // If the triple string is still empty, we don't fall back to
+    // sys::getDefaultTargetTriple() since we do not want to have differing
+    // behaviour dependent on the configured default triple. Therefore, if the
+    // user did not pass -mtriple or define an explicit triple/datalayout in
+    // the IR, we should default to an empty (default) DataLayout.
+    if (TripleStr.empty())
+      return std::nullopt;
+    // Otherwise we infer the DataLayout from the target machine.
+    Expected<std::unique_ptr<TargetMachine>> ExpectedTM =
+        codegen::createTargetMachineForTriple(TripleStr, GetCodeGenOptLevel());
+    if (!ExpectedTM) {
+      errs() << argv[0] << ": warning: failed to infer data layout: "
+             << toString(ExpectedTM.takeError()) << "\n";
+      return std::nullopt;
+    }
+    return (*ExpectedTM)->createDataLayout().getStringRepresentation();
   };
   std::unique_ptr<Module> M;
   if (NoUpgradeDebugInfo)
@@ -553,7 +575,7 @@
     }
   }
 
-  // If we are supposed to override the target triple or data layout, do so now.
+  // If we are supposed to override the target triple, do so now.
   if (!TargetTriple.empty())
     M->setTargetTriple(Triple::normalize(TargetTriple));
 
@@ -570,9 +592,14 @@
   // the facility for updating public visibility to linkage unit visibility when
   // specified by an internal option. This is normally done during LTO which is
   // not performed via opt.
-  updateVCallVisibilityInModule(*M,
-                                /* WholeProgramVisibilityEnabledInLTO */ false,
-                                /* DynamicExportSymbols */ {});
+  updateVCallVisibilityInModule(
+      *M,
+      /*WholeProgramVisibilityEnabledInLTO=*/false,
+      // FIXME: These need linker information via a
+      // TBD new interface.
+      /*DynamicExportSymbols=*/{},
+      /*ValidateAllVtablesHaveTypeInfos=*/false,
+      /*IsVisibleToRegularObj=*/[](StringRef) { return true; });
 
   // Figure out what stream we are supposed to write to...
   std::unique_ptr<ToolOutputFile> Out;
@@ -607,14 +634,19 @@
 
   Triple ModuleTriple(M->getTargetTriple());
   std::string CPUStr, FeaturesStr;
-  TargetMachine *Machine = nullptr;
-  const TargetOptions Options =
-      codegen::InitTargetOptionsFromCodeGenFlags(ModuleTriple);
-
+  std::unique_ptr<TargetMachine> TM;
   if (ModuleTriple.getArch()) {
     CPUStr = codegen::getCPUStr();
     FeaturesStr = codegen::getFeaturesStr();
-    Machine = GetTargetMachine(ModuleTriple, CPUStr, FeaturesStr, Options);
+    Expected<std::unique_ptr<TargetMachine>> ExpectedTM =
+        codegen::createTargetMachineForTriple(ModuleTriple.str(),
+                                              GetCodeGenOptLevel());
+    if (auto E = ExpectedTM.takeError()) {
+      errs() << argv[0] << ": WARNING: failed to create target machine for '"
+             << ModuleTriple.str() << "': " << toString(std::move(E)) << "\n";
+    } else {
+      TM = std::move(*ExpectedTM);
+    }
   } else if (ModuleTriple.getArchName() != "unknown" &&
              ModuleTriple.getArchName() != "") {
     errs() << argv[0] << ": unrecognized architecture '"
@@ -622,8 +654,6 @@
     return 1;
   }
 
-  std::unique_ptr<TargetMachine> TM(Machine);
-
   // Override function attributes based on CPUStr, FeaturesStr, and command line
   // flags.
   codegen::setFunctionAttributes(CPUStr, FeaturesStr, *M);
diff --git a/src/llvm-project/llvm/tools/sancov/CMakeLists.txt b/src/llvm-project/llvm/tools/sancov/CMakeLists.txt
index 3fc1cac..a174ddf 100644
--- a/src/llvm-project/llvm/tools/sancov/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/sancov/CMakeLists.txt
@@ -5,11 +5,20 @@
   MC
   MCDisassembler
   Object
+  Option
   Support
   Symbolize
   TargetParser
   )
 
+set(LLVM_TARGET_DEFINITIONS Opts.td)
+tablegen(LLVM Opts.inc -gen-opt-parser-defs)
+add_public_tablegen_target(SancovOptsTableGen)
+
 add_llvm_tool(sancov
   sancov.cpp
+
+  DEPENDS
+  SancovOptsTableGen
+  GENERATE_DRIVER
   )
diff --git a/src/llvm-project/llvm/tools/sancov/Opts.td b/src/llvm-project/llvm/tools/sancov/Opts.td
new file mode 100644
index 0000000..2e8af81
--- /dev/null
+++ b/src/llvm-project/llvm/tools/sancov/Opts.td
@@ -0,0 +1,58 @@
+include "llvm/Option/OptParser.td"
+
+class F<string name, string help> : Flag<["-", "--"], name>, HelpText<help>;
+
+multiclass B<string name, string help1, string help2> {
+  def NAME: Flag<["-", "--"], name>, HelpText<help1>;
+  def no_ # NAME: Flag<["-", "--"], "no-" # name>, HelpText<help2>;
+}
+
+multiclass Eq<string name, string help> {
+  def NAME #_EQ : Joined<["-", "--"], name #"=">,
+                  HelpText<help>;
+  def : Separate<["-", "--"], name>, Alias<!cast<Joined>(NAME #_EQ)>;
+}
+
+def generic_grp : OptionGroup<"Genric Options">, HelpText<"Generic Options">;
+def help : F<"help", "Display this help">, Group<generic_grp>;
+def : Flag<["-"], "h">, Alias<help>, HelpText<"Alias for --help">, Group<generic_grp>;
+def version : F<"version", "Display the version">, Group<generic_grp>;
+def : Flag<["-"], "v">, Alias<version>, HelpText<"Alias for --version">, Group<generic_grp>;
+
+def action_grp : OptionGroup<"Action">, HelpText<"Action (required)">;
+def print : F<"print", "Print coverage addresses">,
+  Group<action_grp>;
+def printCoveragePcs : F<"print-coverage-pcs", "Print coverage instrumentation points addresses.">,
+  Group<action_grp>;
+def coveredFunctions : F<"covered-functions", "Print all covered funcions.">,
+  Group<action_grp>;
+def notCoveredFunctions : F<"not-covered-functions", "Print all not covered funcions.">,
+  Group<action_grp>;
+def printCoverageStats : F<"print-coverage-stats", "Print coverage statistics.">,
+  Group<action_grp>;
+def htmlReport : F<"html-report", "REMOVED. Use -symbolize & coverage-report-server.py.">,
+  Group<action_grp>;
+def symbolize : F<"symbolize", "Produces a symbolized JSON report from binary report.">,
+  Group<action_grp>;
+def merge : F<"merge", "Merges reports.">,
+  Group<action_grp>;
+
+defm demangle : B<"demangle", "Demangle function names", "Do not demangle function names">;
+defm skipDeadFiles : B<"skip-dead-files", "Do not list dead source files in reports",
+                                          "List dead source files in reports">;
+defm useDefaultIgnoreList :
+  B<"use_default_ignorelist", "Use the default ignore list", "Don't use the default ignore list">,
+  Flags<[HelpHidden]>;
+
+// Compatibility aliases
+def : Flag<["-"], "demangle=0">, Alias<no_demangle>, HelpText<"Alias for --no-demangle">;
+def : Flag<["-"], "skip-dead-files=0">, Alias<no_skipDeadFiles>, HelpText<"Alias for --no-skip-dead-files">;
+def : Flag<["-"], "use_default_ignorelist=0">, Alias<no_useDefaultIgnoreList>, HelpText<"Alias for --no-use_default_ignore_list">;
+
+defm stripPathPrefix
+    : Eq<"strip_path_prefix", "Strip this prefix from files paths in reports">,
+      MetaVarName<"<string>">;
+
+defm ignorelist
+    : Eq<"ignorelist", "Ignorelist file (sanitizer ignorelist format)">,
+      MetaVarName<"<string>">;
diff --git a/src/llvm-project/llvm/tools/sancov/sancov.cpp b/src/llvm-project/llvm/tools/sancov/sancov.cpp
index 9d29e9a..e5b0875 100644
--- a/src/llvm-project/llvm/tools/sancov/sancov.cpp
+++ b/src/llvm-project/llvm/tools/sancov/sancov.cpp
@@ -29,13 +29,15 @@
 #include "llvm/Object/COFF.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/Object/ObjectFile.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/ErrorOr.h"
 #include "llvm/Support/FileSystem.h"
-#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/JSON.h"
+#include "llvm/Support/LLVMDriver.h"
 #include "llvm/Support/MD5.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
@@ -55,9 +57,36 @@
 
 namespace {
 
-// --------- COMMAND LINE FLAGS ---------
+// Command-line option boilerplate.
+namespace {
+using namespace llvm::opt;
+enum ID {
+  OPT_INVALID = 0, // This is not an option ID.
+#define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
+#include "Opts.inc"
+#undef OPTION
+};
 
-cl::OptionCategory Cat("sancov Options");
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
+#include "Opts.inc"
+#undef PREFIX
+
+static constexpr opt::OptTable::Info InfoTable[] = {
+#define OPTION(...) LLVM_CONSTRUCT_OPT_INFO(__VA_ARGS__),
+#include "Opts.inc"
+#undef OPTION
+};
+
+class SancovOptTable : public opt::GenericOptTable {
+public:
+  SancovOptTable() : GenericOptTable(InfoTable) {}
+};
+} // namespace
+
+// --------- COMMAND LINE FLAGS ---------
 
 enum ActionType {
   CoveredFunctionsAction,
@@ -70,53 +99,13 @@
   SymbolizeAction
 };
 
-cl::opt<ActionType> Action(
-    cl::desc("Action (required)"), cl::Required,
-    cl::values(
-        clEnumValN(PrintAction, "print", "Print coverage addresses"),
-        clEnumValN(PrintCovPointsAction, "print-coverage-pcs",
-                   "Print coverage instrumentation points addresses."),
-        clEnumValN(CoveredFunctionsAction, "covered-functions",
-                   "Print all covered funcions."),
-        clEnumValN(NotCoveredFunctionsAction, "not-covered-functions",
-                   "Print all not covered funcions."),
-        clEnumValN(StatsAction, "print-coverage-stats",
-                   "Print coverage statistics."),
-        clEnumValN(HtmlReportAction, "html-report",
-                   "REMOVED. Use -symbolize & coverage-report-server.py."),
-        clEnumValN(SymbolizeAction, "symbolize",
-                   "Produces a symbolized JSON report from binary report."),
-        clEnumValN(MergeAction, "merge", "Merges reports.")),
-    cl::cat(Cat));
-
-static cl::list<std::string>
-    ClInputFiles(cl::Positional, cl::OneOrMore,
-                 cl::desc("<action> <binary files...> <.sancov files...> "
-                          "<.symcov files...>"),
-                 cl::cat(Cat));
-
-static cl::opt<bool> ClDemangle("demangle", cl::init(true),
-                                cl::desc("Print demangled function name"),
-                                cl::cat(Cat));
-
-static cl::opt<bool>
-    ClSkipDeadFiles("skip-dead-files", cl::init(true),
-                    cl::desc("Do not list dead source files in reports"),
-                    cl::cat(Cat));
-
-static cl::opt<std::string>
-    ClStripPathPrefix("strip_path_prefix", cl::init(""),
-                      cl::desc("Strip this prefix from file paths in reports"),
-                      cl::cat(Cat));
-
-static cl::opt<std::string>
-    ClIgnorelist("ignorelist", cl::init(""),
-                 cl::desc("Ignorelist file (sanitizer ignorelist format)"),
-                 cl::cat(Cat));
-
-static cl::opt<bool> ClUseDefaultIgnorelist(
-    "use_default_ignorelist", cl::init(true), cl::Hidden,
-    cl::desc("Controls if default ignorelist should be used"), cl::cat(Cat));
+static ActionType Action;
+static std::vector<std::string> ClInputFiles;
+static bool ClDemangle;
+static bool ClSkipDeadFiles;
+static bool ClUseDefaultIgnorelist;
+static std::string ClStripPathPrefix;
+static std::string ClIgnorelist;
 
 static const char *const DefaultIgnorelistStr = "fun:__sanitizer_.*\n"
                                                 "src:/usr/include/.*\n"
@@ -699,8 +688,7 @@
 // Ported from
 // compiler-rt/lib/sanitizer_common/sanitizer_stacktrace.h:GetPreviousInstructionPc
 // GetPreviousInstructionPc.
-static uint64_t getPreviousInstructionPc(uint64_t PC,
-                                         Triple TheTriple) {
+static uint64_t getPreviousInstructionPc(uint64_t PC, Triple TheTriple) {
   if (TheTriple.isARM())
     return (PC - 3) & (~1);
   if (TheTriple.isMIPS() || TheTriple.isSPARC())
@@ -1145,31 +1133,99 @@
 
 } // namespace
 
-int main(int Argc, char **Argv) {
-  llvm::InitLLVM X(Argc, Argv);
-  cl::HideUnrelatedOptions(Cat);
+static void parseArgs(int Argc, char **Argv) {
+  SancovOptTable Tbl;
+  llvm::BumpPtrAllocator A;
+  llvm::StringSaver Saver{A};
+  opt::InputArgList Args =
+      Tbl.parseArgs(Argc, Argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
+        llvm::errs() << Msg << '\n';
+        std::exit(1);
+      });
 
+  if (Args.hasArg(OPT_help)) {
+    Tbl.printHelp(
+        llvm::outs(),
+        "sancov [options] <action> <binary files...> <.sancov files...> "
+        "<.symcov files...>",
+        "Sanitizer Coverage Processing Tool (sancov)\n\n"
+        "  This tool can extract various coverage-related information from: \n"
+        "  coverage-instrumented binary files, raw .sancov files and their "
+        "symbolized .symcov version.\n"
+        "  Depending on chosen action the tool expects different input files:\n"
+        "    -print-coverage-pcs     - coverage-instrumented binary files\n"
+        "    -print-coverage         - .sancov files\n"
+        "    <other actions>         - .sancov files & corresponding binary "
+        "files, .symcov files\n");
+    std::exit(0);
+  }
+
+  if (Args.hasArg(OPT_version)) {
+    cl::PrintVersionMessage();
+    std::exit(0);
+  }
+
+  if (Args.hasMultipleArgs(OPT_action_grp)) {
+    fail("Only one action option is allowed");
+  }
+
+  for (const opt::Arg *A : Args.filtered(OPT_INPUT)) {
+    ClInputFiles.emplace_back(A->getValue());
+  }
+
+  if (const llvm::opt::Arg *A = Args.getLastArg(OPT_action_grp)) {
+    switch (A->getOption().getID()) {
+    case OPT_print:
+      Action = ActionType::PrintAction;
+      break;
+    case OPT_printCoveragePcs:
+      Action = ActionType::PrintCovPointsAction;
+      break;
+    case OPT_coveredFunctions:
+      Action = ActionType::CoveredFunctionsAction;
+      break;
+    case OPT_notCoveredFunctions:
+      Action = ActionType::NotCoveredFunctionsAction;
+      break;
+    case OPT_printCoverageStats:
+      Action = ActionType::StatsAction;
+      break;
+    case OPT_htmlReport:
+      Action = ActionType::HtmlReportAction;
+      break;
+    case OPT_symbolize:
+      Action = ActionType::SymbolizeAction;
+      break;
+    case OPT_merge:
+      Action = ActionType::MergeAction;
+      break;
+    default:
+      fail("Invalid Action");
+    }
+  }
+
+  ClDemangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true);
+  ClSkipDeadFiles = Args.hasFlag(OPT_skipDeadFiles, OPT_no_skipDeadFiles, true);
+  ClUseDefaultIgnorelist =
+      Args.hasFlag(OPT_useDefaultIgnoreList, OPT_no_useDefaultIgnoreList, true);
+
+  ClStripPathPrefix = Args.getLastArgValue(OPT_stripPathPrefix_EQ);
+  ClIgnorelist = Args.getLastArgValue(OPT_ignorelist_EQ);
+}
+
+int sancov_main(int Argc, char **Argv, const llvm::ToolContext &) {
   llvm::InitializeAllTargetInfos();
   llvm::InitializeAllTargetMCs();
   llvm::InitializeAllDisassemblers();
 
-  cl::ParseCommandLineOptions(Argc, Argv,
-      "Sanitizer Coverage Processing Tool (sancov)\n\n"
-      "  This tool can extract various coverage-related information from: \n"
-      "  coverage-instrumented binary files, raw .sancov files and their "
-      "symbolized .symcov version.\n"
-      "  Depending on chosen action the tool expects different input files:\n"
-      "    -print-coverage-pcs     - coverage-instrumented binary files\n"
-      "    -print-coverage         - .sancov files\n"
-      "    <other actions>         - .sancov files & corresponding binary "
-      "files, .symcov files\n"
-      );
+  parseArgs(Argc, Argv);
 
   // -print doesn't need object files.
   if (Action == PrintAction) {
     readAndPrintRawCoverage(ClInputFiles, outs());
     return 0;
-  } else if (Action == PrintCovPointsAction) {
+  }
+  if (Action == PrintCovPointsAction) {
     // -print-coverage-points doesn't need coverage files.
     for (const std::string &ObjFile : ClInputFiles) {
       printCovPoints(ObjFile, outs());
@@ -1207,4 +1263,6 @@
   case PrintCovPointsAction:
     llvm_unreachable("unsupported action");
   }
+
+  return 0;
 }
diff --git a/src/llvm-project/llvm/tools/spirv-tools/CMakeLists.txt b/src/llvm-project/llvm/tools/spirv-tools/CMakeLists.txt
new file mode 100644
index 0000000..f73dcad
--- /dev/null
+++ b/src/llvm-project/llvm/tools/spirv-tools/CMakeLists.txt
@@ -0,0 +1,65 @@
+option(LLVM_INCLUDE_SPIRV_TOOLS_TESTS "Include tests that use SPIRV-Tools" Off)
+mark_as_advanced(LLVM_INCLUDE_SPIRV_TOOLS_TESTS)
+
+if (NOT LLVM_INCLUDE_SPIRV_TOOLS_TESTS)
+  return()
+endif ()
+
+if (NOT "SPIRV" IN_LIST LLVM_TARGETS_TO_BUILD)
+  message(FATAL_ERROR "Building SPIRV-Tools tests is unsupported without the SPIR-V target")
+endif ()
+
+# SPIRV_DIS and SPIRV_VAL variables can be used to provide paths to existing
+# spirv-dis and spirv-val binaries, respectively. Otherwise, build them from
+# SPIRV-Tools source.
+if (NOT SPIRV_DIS OR NOT SPIRV_VAL)
+  include(ExternalProject)
+
+  set(BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/SPIRVTools-bin)
+
+  ExternalProject_Add(SPIRVTools
+    GIT_REPOSITORY https://github.com/KhronosGroup/SPIRV-Tools.git
+    GIT_TAG main
+    BINARY_DIR ${BINARY_DIR}
+    BUILD_COMMAND ${CMAKE_COMMAND} --build ${BINARY_DIR} --target spirv-dis spirv-val
+    BUILD_BYPRODUCTS ${BINARY_DIR}/tools/spirv-dis ${BINARY_DIR}/tools/spirv-val
+    DOWNLOAD_COMMAND git clone https://github.com/KhronosGroup/SPIRV-Tools.git SPIRVTools &&
+      cd SPIRVTools &&
+      ${Python3_EXECUTABLE} utils/git-sync-deps
+    UPDATE_COMMAND git pull origin main &&
+      ${Python3_EXECUTABLE} utils/git-sync-deps
+    # Don't auto-update on every build.
+    UPDATE_DISCONNECTED 1
+    # Allow manual updating with an explicit SPIRVTools-update target.
+    STEP_TARGETS update
+    # Install handled below.
+    INSTALL_COMMAND ""
+    )
+endif ()
+
+if (CMAKE_HOST_UNIX)
+  set(LLVM_LINK_OR_COPY create_symlink)
+else ()
+  set(LLVM_LINK_OR_COPY copy)
+endif ()
+
+# Link the provided or just built spirv-dis and spirv-val binaries.
+if (SPIRV_DIS)
+  add_custom_target(spirv-dis
+    COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${SPIRV_DIS}" "${LLVM_RUNTIME_OUTPUT_INTDIR}/spirv-dis")
+else ()
+  add_custom_target(spirv-dis
+    COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${BINARY_DIR}/tools/spirv-dis" "${LLVM_RUNTIME_OUTPUT_INTDIR}/spirv-dis"
+    DEPENDS SPIRVTools
+    )
+endif ()
+
+if (SPIRV_VAL)
+  add_custom_target(spirv-val
+    COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${SPIRV_VAL}" "${LLVM_RUNTIME_OUTPUT_INTDIR}/spirv-val")
+else ()
+  add_custom_target(spirv-val
+    COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${BINARY_DIR}/tools/spirv-val" "${LLVM_RUNTIME_OUTPUT_INTDIR}/spirv-val"
+    DEPENDS SPIRVTools
+    )
+endif ()
diff --git a/src/llvm-project/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp b/src/llvm-project/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
index b0b8013..e1041bd 100644
--- a/src/llvm-project/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
+++ b/src/llvm-project/llvm/tools/vfabi-demangle-fuzzer/vfabi-demangler-fuzzer.cpp
@@ -10,8 +10,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/Analysis/VectorUtils.h"
 #include "llvm/AsmParser/Parser.h"
+#include "llvm/IR/VFABIDemangler.h"
 
 using namespace llvm;
 
@@ -27,15 +27,16 @@
   // present. We need to make sure we can even invoke
   // `getOrInsertFunction` because such method asserts on strings with
   // zeroes.
-  if (!MangledName.empty() && MangledName.find_first_of(0) == StringRef::npos)
-    M->getOrInsertFunction(
-        MangledName,
-        FunctionType::get(Type::getVoidTy(M->getContext()), false));
-  const auto Info = VFABI::tryDemangleForVFABI(MangledName, *M);
+  // TODO: What is this actually testing? That we don't crash?
+  if (!MangledName.empty() && MangledName.find_first_of(0) == StringRef::npos) {
+    FunctionType *FTy =
+        FunctionType::get(Type::getVoidTy(M->getContext()), false);
+    const auto Info = VFABI::tryDemangleForVFABI(MangledName, FTy);
 
-  // Do not optimize away the return value. Inspired by
-  // https://github.com/google/benchmark/blob/main/include/benchmark/benchmark.h#L307-L345
-  asm volatile("" : : "r,m"(Info) : "memory");
+    // Do not optimize away the return value. Inspired by
+    // https://github.com/google/benchmark/blob/main/include/benchmark/benchmark.h#L307-L345
+    asm volatile("" : : "r,m"(Info) : "memory");
+  }
 
   return 0;
 }
diff --git a/src/llvm-project/llvm/tools/yaml2obj/yaml2obj.cpp b/src/llvm-project/llvm/tools/yaml2obj/yaml2obj.cpp
index ba1f54d..b7f5356 100644
--- a/src/llvm-project/llvm/tools/yaml2obj/yaml2obj.cpp
+++ b/src/llvm-project/llvm/tools/yaml2obj/yaml2obj.cpp
@@ -78,9 +78,9 @@
 
   std::string Preprocessed;
   while (!Buf.empty()) {
-    if (Buf.startswith("[[")) {
+    if (Buf.starts_with("[[")) {
       size_t I = Buf.find_first_of("[]", 2);
-      if (Buf.substr(I).startswith("]]")) {
+      if (Buf.substr(I).starts_with("]]")) {
         StringRef MacroExpr = Buf.substr(2, I - 2);
         StringRef Macro;
         StringRef Default;
@@ -92,7 +92,7 @@
         std::optional<StringRef> Value;
         if (It != Defines.end())
           Value = It->second;
-        else if (!Default.empty() || MacroExpr.endswith("="))
+        else if (!Default.empty() || MacroExpr.ends_with("="))
           Value = Default;
 
         if (Value) {