Importing rustc-1.70.0

Test: ./build.py --lto=thin
Change-Id: I34045ec5a79462afe9900f38a66f9783d4055a18
diff --git a/src/llvm-project/llvm/tools/bugpoint-passes/CMakeLists.txt b/src/llvm-project/llvm/tools/bugpoint-passes/CMakeLists.txt
index eea3e23..6df49d7 100644
--- a/src/llvm-project/llvm/tools/bugpoint-passes/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/bugpoint-passes/CMakeLists.txt
@@ -11,7 +11,7 @@
 endif()
 
 if(WIN32 OR CYGWIN)
-  set(LLVM_LINK_COMPONENTS Core)
+  set(LLVM_LINK_COMPONENTS Core Support)
 endif()
 
 add_llvm_library( BugpointPasses MODULE BUILDTREE_ONLY
diff --git a/src/llvm-project/llvm/tools/bugpoint-passes/TestPasses.cpp b/src/llvm-project/llvm/tools/bugpoint-passes/TestPasses.cpp
index 1e66953..aad1377 100644
--- a/src/llvm-project/llvm/tools/bugpoint-passes/TestPasses.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint-passes/TestPasses.cpp
@@ -68,7 +68,7 @@
         if (CallInst *CI = dyn_cast<CallInst>(I)) {
           if (!CI->use_empty())
             CI->replaceAllUsesWith(Constant::getNullValue(CI->getType()));
-          CI->getParent()->getInstList().erase(CI);
+          CI->eraseFromParent();
           break;
         }
     return false;
diff --git a/src/llvm-project/llvm/tools/bugpoint/CMakeLists.txt b/src/llvm-project/llvm/tools/bugpoint/CMakeLists.txt
index d64481df..b0e7191 100644
--- a/src/llvm-project/llvm/tools/bugpoint/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/bugpoint/CMakeLists.txt
@@ -18,6 +18,7 @@
   ScalarOpts
   Support
   Target
+  TargetParser
   TransformUtils
   Vectorize
   )
diff --git a/src/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp b/src/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp
index 9912f59..c90e1af 100644
--- a/src/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/CrashDebugger.cpp
@@ -484,7 +484,7 @@
           BBTerm->replaceAllUsesWith(Constant::getNullValue(BBTerm->getType()));
 
         // Replace the old terminator instruction.
-        BB.getInstList().pop_back();
+        BB.back().eraseFromParent();
         new UnreachableInst(BB.getContext(), &BB);
       }
     }
@@ -791,7 +791,7 @@
             !Inst.isEHPad() && !Inst.getType()->isTokenTy() &&
             !Inst.isSwiftError()) {
           if (!Inst.getType()->isVoidTy())
-            Inst.replaceAllUsesWith(UndefValue::get(Inst.getType()));
+            Inst.replaceAllUsesWith(PoisonValue::get(Inst.getType()));
           Inst.eraseFromParent();
         }
       }
@@ -1338,7 +1338,7 @@
       // contribute to the crash, bisect the operands of the remaining ones
       std::vector<const MDNode *> NamedMDOps;
       for (auto &NamedMD : BD.getProgram().named_metadata())
-        for (auto op : NamedMD.operands())
+        for (auto *op : NamedMD.operands())
           NamedMDOps.push_back(op);
       Expected<bool> Result =
           ReduceCrashingNamedMDOps(BD, TestFn).reduceList(NamedMDOps);
diff --git a/src/llvm-project/llvm/tools/bugpoint/ExtractFunction.cpp b/src/llvm-project/llvm/tools/bugpoint/ExtractFunction.cpp
index 7a75cb90..5047aa3 100644
--- a/src/llvm-project/llvm/tools/bugpoint/ExtractFunction.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/ExtractFunction.cpp
@@ -105,7 +105,7 @@
     TheInst->replaceAllUsesWith(Constant::getNullValue(TheInst->getType()));
 
   // Remove the instruction from the program.
-  TheInst->getParent()->getInstList().erase(TheInst);
+  TheInst->eraseFromParent();
 
   // Spiff up the output a little bit.
   std::vector<std::string> Passes;
diff --git a/src/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp b/src/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp
index d425a8c..1197528 100644
--- a/src/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/OptimizerDriver.cpp
@@ -232,7 +232,8 @@
              << " " << Args[i];
              errs() << "\n";);
 
-  Optional<StringRef> Redirects[3] = {None, None, None};
+  std::optional<StringRef> Redirects[3] = {std::nullopt, std::nullopt,
+                                           std::nullopt};
   // Redirect stdout and stderr to nowhere if SilencePasses is given.
   if (SilencePasses) {
     Redirects[1] = "";
@@ -240,7 +241,7 @@
   }
 
   std::string ErrMsg;
-  int result = sys::ExecuteAndWait(Prog, Args, None, Redirects, Timeout,
+  int result = sys::ExecuteAndWait(Prog, Args, std::nullopt, Redirects, Timeout,
                                    MemoryLimit, &ErrMsg);
 
   // If we are supposed to delete the bitcode file or if the passes crashed,
diff --git a/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp b/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
index d3111e5..352588f 100644
--- a/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/ToolRunner.cpp
@@ -58,9 +58,9 @@
                                  unsigned NumSeconds = 0,
                                  unsigned MemoryLimit = 0,
                                  std::string *ErrMsg = nullptr) {
-  Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
-  return sys::ExecuteAndWait(ProgramPath, Args, None, Redirects, NumSeconds,
-                             MemoryLimit, ErrMsg);
+  std::optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
+  return sys::ExecuteAndWait(ProgramPath, Args, std::nullopt, Redirects,
+                             NumSeconds, MemoryLimit, ErrMsg);
 }
 
 /// RunProgramRemotelyWithTimeout - This function runs the given program
@@ -73,11 +73,11 @@
     StringRef RemoteClientPath, ArrayRef<StringRef> Args, StringRef StdInFile,
     StringRef StdOutFile, StringRef StdErrFile, unsigned NumSeconds = 0,
     unsigned MemoryLimit = 0) {
-  Optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
+  std::optional<StringRef> Redirects[3] = {StdInFile, StdOutFile, StdErrFile};
 
   // Run the program remotely with the remote client
-  int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, None, Redirects,
-                                       NumSeconds, MemoryLimit);
+  int ReturnCode = sys::ExecuteAndWait(RemoteClientPath, Args, std::nullopt,
+                                       Redirects, NumSeconds, MemoryLimit);
 
   // Has the remote client fail?
   if (255 == ReturnCode) {
diff --git a/src/llvm-project/llvm/tools/bugpoint/bugpoint.cpp b/src/llvm-project/llvm/tools/bugpoint/bugpoint.cpp
index 4dece12..0305f64 100644
--- a/src/llvm-project/llvm/tools/bugpoint/bugpoint.cpp
+++ b/src/llvm-project/llvm/tools/bugpoint/bugpoint.cpp
@@ -143,14 +143,11 @@
   PassRegistry &Registry = *PassRegistry::getPassRegistry();
   initializeCore(Registry);
   initializeScalarOpts(Registry);
-  initializeObjCARCOpts(Registry);
   initializeVectorization(Registry);
   initializeIPO(Registry);
   initializeAnalysis(Registry);
   initializeTransformUtils(Registry);
   initializeInstCombine(Registry);
-  initializeAggressiveInstCombine(Registry);
-  initializeInstrumentation(Registry);
   initializeTarget(Registry);
 
   if (std::getenv("bar") == (char*) -1) {
diff --git a/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.cpp b/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.cpp
index d16e1d5..d8293f7 100644
--- a/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/BinaryHolder.cpp
@@ -173,7 +173,7 @@
   // Try the cache first.
   std::lock_guard<std::mutex> Lock(MemberCacheMutex);
   if (MemberCache.count(Key))
-    return *MemberCache[Key].get();
+    return *MemberCache[Key];
 
   // Create a new ObjectEntry, but don't add it to the cache yet. Loading of
   // the archive members might fail and we don't want to lock the whole archive
diff --git a/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt b/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt
index 38028cd..ae92e3f 100644
--- a/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/dsymutil/CMakeLists.txt
@@ -9,6 +9,7 @@
   AsmPrinter
   DebugInfoDWARF
   DWARFLinker
+  DWARFLinkerParallel
   MC
   Object
   CodeGen
@@ -16,6 +17,7 @@
   Remarks
   Support
   Target
+  TargetParser
   )
 
 add_llvm_tool(dsymutil
@@ -33,7 +35,6 @@
   intrinsics_gen
   ${tablegen_deps}
   DsymutilTableGen
-  GENERATE_DRIVER
   )
 
 if(APPLE)
diff --git a/src/llvm-project/llvm/tools/dsymutil/DebugMap.cpp b/src/llvm-project/llvm/tools/dsymutil/DebugMap.cpp
index 79b6cb2..68c26bc 100644
--- a/src/llvm-project/llvm/tools/dsymutil/DebugMap.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/DebugMap.cpp
@@ -8,7 +8,6 @@
 
 #include "DebugMap.h"
 #include "BinaryHolder.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
@@ -28,6 +27,7 @@
 #include <cinttypes>
 #include <cstdint>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -43,7 +43,8 @@
                                uint8_t Type)
     : Filename(std::string(ObjectFilename)), Timestamp(Timestamp), Type(Type) {}
 
-bool DebugMapObject::addSymbol(StringRef Name, Optional<uint64_t> ObjectAddress,
+bool DebugMapObject::addSymbol(StringRef Name,
+                               std::optional<uint64_t> ObjectAddress,
                                uint64_t LinkedAddress, uint32_t Size) {
   auto InsertResult = Symbols.insert(
       std::make_pair(Name, SymbolMapping(ObjectAddress, LinkedAddress, Size)));
@@ -277,7 +278,7 @@
   dsymutil::DebugMapObject Res(Path, sys::toTimePoint(Timestamp), MachO::N_OSO);
   for (auto &Entry : Entries) {
     auto &Mapping = Entry.second;
-    Optional<uint64_t> ObjAddress;
+    std::optional<uint64_t> ObjAddress;
     if (Mapping.ObjectAddress)
       ObjAddress = *Mapping.ObjectAddress;
     auto AddressIt = SymbolAddresses.find(Entry.first);
diff --git a/src/llvm-project/llvm/tools/dsymutil/DebugMap.h b/src/llvm-project/llvm/tools/dsymutil/DebugMap.h
index e4fbaa8..4854f41be 100644
--- a/src/llvm-project/llvm/tools/dsymutil/DebugMap.h
+++ b/src/llvm-project/llvm/tools/dsymutil/DebugMap.h
@@ -22,7 +22,6 @@
 #define LLVM_TOOLS_DSYMUTIL_DEBUGMAP_H
 
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Triple.h"
@@ -35,6 +34,7 @@
 #include <cstddef>
 #include <cstdint>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -135,11 +135,11 @@
 class DebugMapObject {
 public:
   struct SymbolMapping {
-    Optional<yaml::Hex64> ObjectAddress;
+    std::optional<yaml::Hex64> ObjectAddress;
     yaml::Hex64 BinaryAddress;
     yaml::Hex32 Size;
 
-    SymbolMapping(Optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
+    SymbolMapping(std::optional<uint64_t> ObjectAddr, uint64_t BinaryAddress,
                   uint32_t Size)
         : BinaryAddress(BinaryAddress), Size(Size) {
       if (ObjectAddr)
@@ -156,7 +156,7 @@
   /// Adds a symbol mapping to this DebugMapObject.
   /// \returns false if the symbol was already registered. The request
   /// is discarded in this case.
-  bool addSymbol(StringRef SymName, Optional<uint64_t> ObjectAddress,
+  bool addSymbol(StringRef SymName, std::optional<uint64_t> ObjectAddress,
                  uint64_t LinkedAddress, uint32_t Size);
 
   /// Lookup a symbol mapping.
diff --git a/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index 5f43680..8df95f5 100644
--- a/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -18,8 +18,6 @@
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/None.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
@@ -94,6 +92,7 @@
 #include <limits>
 #include <map>
 #include <memory>
+#include <optional>
 #include <string>
 #include <system_error>
 #include <tuple>
@@ -410,7 +409,7 @@
     }
 
     auto CalculateAddressOfSymbolInDwarfSegment =
-        [&]() -> llvm::Optional<int64_t> {
+        [&]() -> std::optional<int64_t> {
       auto Symbol = It->getSymbol();
       auto SymbolAbsoluteAddress = Symbol->getAddress();
       if (!SymbolAbsoluteAddress)
@@ -446,7 +445,7 @@
 
     bool ShouldSubtractDwarfVM = false;
     // For the second symbol there are two possibilities.
-    llvm::Optional<int64_t> SecondSymbolAddress;
+    std::optional<int64_t> SecondSymbolAddress;
     auto Sym = It->getSymbol();
     if (Sym != MO->symbol_end()) {
       Expected<StringRef> SymbolName = Sym->getName();
@@ -506,7 +505,7 @@
   if (auto *MO = dyn_cast<llvm::object::MachOObjectFile>(OF->getBinary())) {
     // Collect the swift reflection sections before emitting them. This is
     // done so we control the order they're emitted.
-    std::array<Optional<object::SectionRef>,
+    std::array<std::optional<object::SectionRef>,
                Swift5ReflectionSectionKind::last + 1>
         SwiftSections;
     for (auto &Section : MO->sections()) {
@@ -543,7 +542,7 @@
       // place.
       SectionToOffsetInDwarf[SectionKind] += Section.getSize();
       Streamer->emitSwiftReflectionSection(SectionKind, *SectionContents,
-                                           Section.getAlignment(),
+                                           Section.getAlignment().value(),
                                            Section.getSize());
     }
   }
@@ -578,7 +577,6 @@
   GeneralLinker.setNoODR(Options.NoODR);
   GeneralLinker.setUpdate(Options.Update);
   GeneralLinker.setNumThreads(Options.Threads);
-  GeneralLinker.setAccelTableKind(Options.TheAccelTableKind);
   GeneralLinker.setPrependPath(Options.PrependPath);
   GeneralLinker.setKeepFunctionForStatic(Options.KeepFunctionForStatic);
   if (Options.Translator)
@@ -591,58 +589,58 @@
       [&](const Twine &Error, StringRef Context, const DWARFDie *) {
         error(Error, Context);
       });
-  GeneralLinker.setObjFileLoader(
-      [&DebugMap, &RL, this](StringRef ContainerName,
-                             StringRef Path) -> ErrorOr<DWARFFile &> {
-        auto &Obj = DebugMap.addDebugMapObject(
-            Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
+  objFileLoader Loader = [&DebugMap, &RL,
+                          this](StringRef ContainerName,
+                                StringRef Path) -> ErrorOr<DWARFFile &> {
+    auto &Obj = DebugMap.addDebugMapObject(
+        Path, sys::TimePoint<std::chrono::seconds>(), MachO::N_OSO);
 
-        if (auto ErrorOrObj = loadObject(Obj, DebugMap, RL)) {
-          return *ErrorOrObj;
-        } 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(")");
+    if (auto ErrorOrObj = loadObject(Obj, DebugMap, RL)) {
+      return *ErrorOrObj;
+    } 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(")");
 
-          if (IsClangModule) {
-            StringRef ModuleCacheDir = sys::path::parent_path(Path);
-            if (sys::fs::exists(ModuleCacheDir)) {
-              // If the module's parent directory exists, we assume that the
-              // module cache has expired and was pruned by clang.  A more
-              // adventurous dsymutil would invoke clang to rebuild the module
-              // now.
-              if (!ModuleCacheHintDisplayed) {
-                WithColor::note()
-                    << "The clang module cache may have expired since "
-                       "this object file was built. Rebuilding the "
-                       "object file will rebuild the module cache.\n";
-                ModuleCacheHintDisplayed = true;
-              }
-            } else if (IsArchive) {
-              // If the module cache directory doesn't exist at all and the
-              // object file is inside a static library, we assume that the
-              // static library was built on a different machine. We don't want
-              // to discourage module debugging for convenience libraries within
-              // a project though.
-              if (!ArchiveHintDisplayed) {
-                WithColor::note()
-                    << "Linking a static library that was built with "
-                       "-gmodules, but the module cache was not found.  "
-                       "Redistributable static libraries should never be "
-                       "built with module debugging enabled.  The debug "
-                       "experience will be degraded due to incomplete "
-                       "debug information.\n";
-                ArchiveHintDisplayed = true;
-              }
-            }
+      if (IsClangModule) {
+        StringRef ModuleCacheDir = sys::path::parent_path(Path);
+        if (sys::fs::exists(ModuleCacheDir)) {
+          // If the module's parent directory exists, we assume that the
+          // module cache has expired and was pruned by clang.  A more
+          // adventurous dsymutil would invoke clang to rebuild the module
+          // now.
+          if (!ModuleCacheHintDisplayed) {
+            WithColor::note()
+                << "The clang module cache may have expired since "
+                   "this object file was built. Rebuilding the "
+                   "object file will rebuild the module cache.\n";
+            ModuleCacheHintDisplayed = true;
           }
-
-          return ErrorOrObj.getError();
+        } else if (IsArchive) {
+          // If the module cache directory doesn't exist at all and the
+          // object file is inside a static library, we assume that the
+          // static library was built on a different machine. We don't want
+          // to discourage module debugging for convenience libraries within
+          // a project though.
+          if (!ArchiveHintDisplayed) {
+            WithColor::note()
+                << "Linking a static library that was built with "
+                   "-gmodules, but the module cache was not found.  "
+                   "Redistributable static libraries should never be "
+                   "built with module debugging enabled.  The debug "
+                   "experience will be degraded due to incomplete "
+                   "debug information.\n";
+            ArchiveHintDisplayed = true;
+          }
         }
+      }
 
-        llvm_unreachable("Unhandled DebugMap object");
-      });
+      return ErrorOrObj.getError();
+    }
+
+    llvm_unreachable("Unhandled DebugMap object");
+  };
   GeneralLinker.setSwiftInterfacesMap(&ParseableSwiftInterfaces);
   bool ReflectionSectionsPresentInBinary = false;
   // If there is no output specified, no point in checking the binary for swift5
@@ -661,6 +659,12 @@
                                   SectionToOffsetInDwarf, RelocationsToApply);
   }
 
+  uint16_t MaxDWARFVersion = 0;
+  std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =
+      [&MaxDWARFVersion](const DWARFUnit &Unit) {
+        MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion);
+      };
+
   for (const auto &Obj : Map.objects()) {
     // N_AST objects (swiftmodule files) should get dumped directly into the
     // appropriate DWARF section.
@@ -702,8 +706,9 @@
 
       continue;
     }
+
     if (auto ErrorOrObj = loadObject(*Obj, Map, RL))
-      GeneralLinker.addObjectFile(*ErrorOrObj);
+      GeneralLinker.addObjectFile(*ErrorOrObj, Loader, OnCUDieLoaded);
     else {
       ObjectsForLinking.push_back(std::make_unique<DWARFFile>(
           Obj->getObjectFilename(), nullptr, nullptr,
@@ -712,6 +717,34 @@
     }
   }
 
+  // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway.
+  if (MaxDWARFVersion == 0)
+    MaxDWARFVersion = 3;
+
+  if (Error E = GeneralLinker.setTargetDWARFVersion(MaxDWARFVersion))
+    return error(toString(std::move(E)));
+
+  switch (Options.TheAccelTableKind) {
+  case DsymutilAccelTableKind::Apple:
+    GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::Apple);
+    break;
+  case DsymutilAccelTableKind::Dwarf:
+    GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::DebugNames);
+    break;
+  case DsymutilAccelTableKind::Pub:
+    GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::Pub);
+    break;
+  case DsymutilAccelTableKind::Default:
+    if (MaxDWARFVersion >= 5)
+      GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::DebugNames);
+    else
+      GeneralLinker.addAccelTableKind(DwarfLinkerAccelTableKind::Apple);
+    break;
+  case DsymutilAccelTableKind::None:
+    // Nothing to do.
+    break;
+  }
+
   // link debug info for loaded object files.
   if (Error E = GeneralLinker.link())
     return error(toString(std::move(E)));
@@ -945,7 +978,7 @@
     const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo) {
   const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
 
-  Optional<uint32_t> LocationIdx =
+  std::optional<uint32_t> LocationIdx =
       Abbrev->findAttributeIndex(dwarf::DW_AT_location);
   if (!LocationIdx)
     return false;
@@ -964,7 +997,8 @@
     const DWARFDie &DIE, CompileUnit::DIEInfo &MyInfo) {
   const auto *Abbrev = DIE.getAbbreviationDeclarationPtr();
 
-  Optional<uint32_t> LowPcIdx = Abbrev->findAttributeIndex(dwarf::DW_AT_low_pc);
+  std::optional<uint32_t> LowPcIdx =
+      Abbrev->findAttributeIndex(dwarf::DW_AT_low_pc);
   if (!LowPcIdx)
     return false;
 
@@ -980,8 +1014,8 @@
   }
 
   if (Form == dwarf::DW_FORM_addrx) {
-    Optional<DWARFFormValue> AddrValue = DIE.find(dwarf::DW_AT_low_pc);
-    if (Optional<uint64_t> AddrOffsetSectionBase =
+    std::optional<DWARFFormValue> AddrValue = DIE.find(dwarf::DW_AT_low_pc);
+    if (std::optional<uint64_t> AddrOffsetSectionBase =
             DIE.getDwarfUnit()->getAddrOffsetSectionBase()) {
       uint64_t StartOffset = *AddrOffsetSectionBase + AddrValue->getRawUValue();
       uint64_t EndOffset =
diff --git a/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h b/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h
index 03b9a64..f08d923 100644
--- a/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h
+++ b/src/llvm-project/llvm/tools/dsymutil/LinkUtils.h
@@ -23,6 +23,14 @@
 namespace llvm {
 namespace dsymutil {
 
+enum class DsymutilAccelTableKind : uint8_t {
+  None,
+  Apple,   ///< .apple_names, .apple_namespaces, .apple_types, .apple_objc.
+  Dwarf,   ///< DWARF v5 .debug_names.
+  Default, ///< Dwarf for DWARF5 or later, Apple otherwise.
+  Pub,     ///< .debug_pubnames, .debug_pubtypes
+};
+
 struct LinkOptions {
   /// Verbosity
   bool Verbose = false;
@@ -56,7 +64,7 @@
   OutputFileType FileType = OutputFileType::Object;
 
   /// The accelerator table kind
-  DwarfLinkerAccelTableKind TheAccelTableKind;
+  DsymutilAccelTableKind TheAccelTableKind;
 
   /// -oso-prepend-path
   std::string PrependPath;
@@ -65,7 +73,7 @@
   std::map<std::string, std::string> ObjectPrefixMap;
 
   /// The Resources directory in the .dSYM bundle.
-  Optional<std::string> ResourceDir;
+  std::optional<std::string> ResourceDir;
 
   /// Symbol map translator.
   SymbolMapTranslator Translator;
diff --git a/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp b/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp
index 955272b..2f391c5 100644
--- a/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/MachODebugMapParser.cpp
@@ -9,12 +9,12 @@
 #include "BinaryHolder.h"
 #include "DebugMap.h"
 #include "MachOUtils.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/Object/MachO.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
+#include <optional>
 #include <vector>
 
 namespace {
@@ -59,10 +59,10 @@
   std::vector<std::string> CommonSymbols;
 
   /// Map of the currently processed object file symbol addresses.
-  StringMap<Optional<uint64_t>> CurrentObjectAddresses;
+  StringMap<std::optional<uint64_t>> CurrentObjectAddresses;
 
   /// Lazily computed map of symbols aliased to the processed object file.
-  StringMap<Optional<uint64_t>> CurrentObjectAliasMap;
+  StringMap<std::optional<uint64_t>> CurrentObjectAliasMap;
 
   /// If CurrentObjectAliasMap has been computed for a given address.
   SmallSet<uint64_t, 4> SeenAliasValues;
@@ -151,7 +151,8 @@
       // The main binary doesn't have an address for the given symbol.
       continue;
     }
-    if (!CurrentDebugMapObject->addSymbol(CommonSymbol, None /*ObjectAddress*/,
+    if (!CurrentDebugMapObject->addSymbol(CommonSymbol,
+                                          std::nullopt /*ObjectAddress*/,
                                           CommonAddr, 0 /*size*/)) {
       // The symbol is already present.
       continue;
@@ -533,9 +534,9 @@
     // in the DebugMap, leave it unassigned for these symbols.
     uint32_t Flags = cantFail(Sym.getFlags());
     if (Flags & SymbolRef::SF_Absolute) {
-      CurrentObjectAddresses[*Name] = None;
+      CurrentObjectAddresses[*Name] = std::nullopt;
     } else if (Flags & SymbolRef::SF_Common) {
-      CurrentObjectAddresses[*Name] = None;
+      CurrentObjectAddresses[*Name] = std::nullopt;
       CommonSymbols.push_back(std::string(*Name));
     } else {
       CurrentObjectAddresses[*Name] = Addr;
diff --git a/src/llvm-project/llvm/tools/dsymutil/MachOUtils.cpp b/src/llvm-project/llvm/tools/dsymutil/MachOUtils.cpp
index 3bf455e..2d3437e 100644
--- a/src/llvm-project/llvm/tools/dsymutil/MachOUtils.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/MachOUtils.cpp
@@ -56,7 +56,7 @@
 }
 
 static bool runLipo(StringRef SDKPath, SmallVectorImpl<StringRef> &Args) {
-  auto Path = sys::findProgramByName("lipo", makeArrayRef(SDKPath));
+  auto Path = sys::findProgramByName("lipo", ArrayRef(SDKPath));
   if (!Path)
     Path = sys::findProgramByName("lipo");
 
@@ -66,7 +66,8 @@
   }
 
   std::string ErrMsg;
-  int result = sys::ExecuteAndWait(*Path, Args, None, {}, 0, 0, &ErrMsg);
+  int result =
+      sys::ExecuteAndWait(*Path, Args, std::nullopt, {}, 0, 0, &ErrMsg);
   if (result) {
     WithColor::error() << "lipo: " << ErrMsg << "\n";
     return false;
@@ -317,10 +318,10 @@
     if (Sec->begin() == Sec->end() || !Layout.getSectionFileSize(Sec))
       continue;
 
-    unsigned Align = Sec->getAlignment();
-    if (Align > 1) {
-      VMAddr = alignTo(VMAddr, Align);
-      FileOffset = alignTo(FileOffset, Align);
+    Align Alignment = Sec->getAlign();
+    if (Alignment > 1) {
+      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.");
@@ -477,7 +478,7 @@
       continue;
 
     if (uint64_t Size = Layout.getSectionFileSize(Sec)) {
-      DwarfSegmentSize = alignTo(DwarfSegmentSize, Sec->getAlignment());
+      DwarfSegmentSize = alignTo(DwarfSegmentSize, Sec->getAlign());
       DwarfSegmentSize += Size;
       ++NumDwarfSections;
     }
@@ -617,7 +618,7 @@
       continue;
 
     uint64_t Pos = OutFile.tell();
-    OutFile.write_zeros(alignTo(Pos, Sec.getAlignment()) - Pos);
+    OutFile.write_zeros(alignTo(Pos, Sec.getAlign()) - Pos);
     MCAsm.writeSectionData(OutFile, &Sec, Layout);
   }
 
diff --git a/src/llvm-project/llvm/tools/dsymutil/Reproducer.cpp b/src/llvm-project/llvm/tools/dsymutil/Reproducer.cpp
index 2e28859..dda5557 100644
--- a/src/llvm-project/llvm/tools/dsymutil/Reproducer.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/Reproducer.cpp
@@ -20,6 +20,7 @@
   } else {
     EC = sys::fs::createUniqueDirectory("dsymutil", Root);
   }
+  sys::fs::make_absolute(Root);
   return EC ? "" : std::string(Root);
 }
 
diff --git a/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp b/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp
index 0ebdcc1..75876a8 100644
--- a/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp
+++ b/src/llvm-project/llvm/tools/dsymutil/dsymutil.cpp
@@ -63,11 +63,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
 #include "Options.inc"
 #undef PREFIX
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -79,9 +82,9 @@
 #undef OPTION
 };
 
-class DsymutilOptTable : public opt::OptTable {
+class DsymutilOptTable : public opt::GenericOptTable {
 public:
-  DsymutilOptTable() : OptTable(InfoTable) {}
+  DsymutilOptTable() : opt::GenericOptTable(InfoTable) {}
 };
 } // namespace
 
@@ -206,26 +209,26 @@
   return Error::success();
 }
 
-static Expected<DwarfLinkerAccelTableKind>
+static Expected<DsymutilAccelTableKind>
 getAccelTableKind(opt::InputArgList &Args) {
   if (opt::Arg *Accelerator = Args.getLastArg(OPT_accelerator)) {
     StringRef S = Accelerator->getValue();
     if (S == "Apple")
-      return DwarfLinkerAccelTableKind::Apple;
+      return DsymutilAccelTableKind::Apple;
     if (S == "Dwarf")
-      return DwarfLinkerAccelTableKind::Dwarf;
+      return DsymutilAccelTableKind::Dwarf;
     if (S == "Pub")
-      return DwarfLinkerAccelTableKind::Pub;
+      return DsymutilAccelTableKind::Pub;
     if (S == "Default")
-      return DwarfLinkerAccelTableKind::Default;
+      return DsymutilAccelTableKind::Default;
     if (S == "None")
-      return DwarfLinkerAccelTableKind::None;
+      return DsymutilAccelTableKind::None;
     return make_error<StringError>("invalid accelerator type specified: '" + S +
                                        "'. Supported values are 'Apple', "
                                        "'Dwarf', 'Pub', 'Default' and 'None'.",
                                    inconvertibleErrorCode());
   }
-  return DwarfLinkerAccelTableKind::Default;
+  return DsymutilAccelTableKind::Default;
 }
 
 static Expected<ReproducerMode> getReproducerMode(opt::InputArgList &Args) {
@@ -310,7 +313,7 @@
     }
   }
 
-  if (Expected<DwarfLinkerAccelTableKind> AccelKind = getAccelTableKind(Args)) {
+  if (Expected<DsymutilAccelTableKind> AccelKind = getAccelTableKind(Args)) {
     Options.LinkOpts.TheAccelTableKind = *AccelKind;
   } else {
     return AccelKind.takeError();
@@ -485,12 +488,13 @@
 
 namespace {
 struct OutputLocation {
-  OutputLocation(std::string DWARFFile, Optional<std::string> ResourceDir = {})
+  OutputLocation(std::string DWARFFile,
+                 std::optional<std::string> ResourceDir = {})
       : DWARFFile(DWARFFile), ResourceDir(ResourceDir) {}
   /// This method is a workaround for older compilers.
-  Optional<std::string> getResourceDir() const { return ResourceDir; }
+  std::optional<std::string> getResourceDir() const { return ResourceDir; }
   std::string DWARFFile;
-  Optional<std::string> ResourceDir;
+  std::optional<std::string> ResourceDir;
 };
 } // namespace
 
@@ -546,14 +550,14 @@
   return OutputLocation(std::string(Path.str()), ResourceDir);
 }
 
-int dsymutil_main(int argc, char **argv) {
+int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
 
   // Parse arguments.
   DsymutilOptTable T;
   unsigned MAI;
   unsigned MAC;
-  ArrayRef<const char *> ArgsArr = makeArrayRef(argv + 1, argc - 1);
+  ArrayRef<const char *> ArgsArr = ArrayRef(argv + 1, argc - 1);
   opt::InputArgList Args = T.ParseArgs(ArgsArr, MAI, MAC);
 
   void *P = (void *)(intptr_t)getOutputFileName;
@@ -798,7 +802,7 @@
           break;
         FileOffset += stat->getSize();
         if (FileOffset > UINT32_MAX) {
-          WithColor::error() << "the univesral binary has a slice with an "
+          WithColor::error() << "the universal binary has a slice with an "
               "offset exceeds 4GB and will produce an invalid Mach-O file.";
           return EXIT_FAILURE;
         }
diff --git a/src/llvm-project/llvm/tools/dxil-dis/CMakeLists.txt b/src/llvm-project/llvm/tools/dxil-dis/CMakeLists.txt
index 2859318..9addf10 100644
--- a/src/llvm-project/llvm/tools/dxil-dis/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/dxil-dis/CMakeLists.txt
@@ -17,7 +17,7 @@
 
 if (DXIL_DIS)
   add_custom_target(dxil-dis
-    COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${DXIL_DIS}" "${LLVM_RUNTIME_OUTPUT_INTDIR}/dxil-dis")
+    COMMAND ${CMAKE_COMMAND} -E ${LLVM_LINK_OR_COPY} "${DXIL_DIS}" "${LLVM_RUNTIME_OUTPUT_INTDIR}/dxil-dis${CMAKE_EXECUTABLE_SUFFIX}")
   return()
 endif ()
 
diff --git a/src/llvm-project/llvm/tools/gold/CMakeLists.txt b/src/llvm-project/llvm/tools/gold/CMakeLists.txt
index 72f7655..58b3238 100644
--- a/src/llvm-project/llvm/tools/gold/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/gold/CMakeLists.txt
@@ -9,6 +9,7 @@
      LTO
      BitWriter
      IPO
+     TargetParser
      )
 
   add_llvm_library(LLVMgold MODULE
diff --git a/src/llvm-project/llvm/tools/gold/gold-plugin.cpp b/src/llvm-project/llvm/tools/gold/gold-plugin.cpp
index f1b457b..939dbaf 100644
--- a/src/llvm-project/llvm/tools/gold/gold-plugin.cpp
+++ b/src/llvm-project/llvm/tools/gold/gold-plugin.cpp
@@ -121,7 +121,7 @@
 static ld_plugin_get_view get_view = nullptr;
 static bool IsExecutable = false;
 static bool SplitSections = true;
-static Optional<Reloc::Model> RelocationModel = None;
+static std::optional<Reloc::Model> RelocationModel;
 static std::string output_name = "";
 static std::list<claimed_file> Modules;
 static DenseMap<int, void *> FDToLeaderHandle;
@@ -215,7 +215,7 @@
   static std::string RemarksFilename;
   static std::string RemarksPasses;
   static bool RemarksWithHotness = false;
-  static Optional<uint64_t> RemarksHotnessThreshold = 0;
+  static std::optional<uint64_t> RemarksHotnessThreshold = 0;
   static std::string RemarksFormat;
 
   // Context sensitive PGO options.
@@ -722,8 +722,8 @@
 // Returns true if S is valid as a C language identifier.
 static bool isValidCIdentifier(StringRef S) {
   return !S.empty() && (isAlpha(S[0]) || S[0] == '_') &&
-         std::all_of(S.begin() + 1, S.end(),
-                     [](char C) { return C == '_' || isAlnum(C); });
+         llvm::all_of(llvm::drop_begin(S),
+                      [](char C) { return C == '_' || isAlnum(C); });
 }
 
 static bool isUndefined(ld_plugin_symbol &Sym) {
@@ -846,20 +846,6 @@
   return FD;
 }
 
-static CodeGenOpt::Level getCGOptLevel() {
-  switch (options::OptLevel) {
-  case 0:
-    return CodeGenOpt::None;
-  case 1:
-    return CodeGenOpt::Less;
-  case 2:
-    return CodeGenOpt::Default;
-  case 3:
-    return CodeGenOpt::Aggressive;
-  }
-  llvm_unreachable("Invalid optimization level");
-}
-
 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
 /// \p NewPrefix strings, if it was specified.
 static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
@@ -896,7 +882,10 @@
   Conf.MAttrs = codegen::getMAttrs();
   Conf.RelocModel = RelocationModel;
   Conf.CodeModel = codegen::getExplicitCodeModel();
-  Conf.CGOptLevel = getCGOptLevel();
+  std::optional<CodeGenOpt::Level> CGOptLevelOrNone =
+      CodeGenOpt::getLevel(options::OptLevel);
+  assert(CGOptLevelOrNone && "Invalid optimization level");
+  Conf.CGOptLevel = *CGOptLevelOrNone;
   Conf.DisableVerify = options::DisableVerify;
   Conf.OptLevel = options::OptLevel;
   Conf.PTO.LoopVectorization = options::OptLevel > 1;
@@ -1091,7 +1080,9 @@
   size_t MaxTasks = Lto->getMaxTasks();
   std::vector<std::pair<SmallString<128>, bool>> Files(MaxTasks);
 
-  auto AddStream = [&](size_t Task) -> std::unique_ptr<CachedFileStream> {
+  auto AddStream =
+      [&](size_t Task,
+          const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
     Files[Task].second = !SaveTemps;
     int FD = getOutputFileName(Filename, /* TempOutFile */ !SaveTemps,
                                Files[Task].first, Task);
@@ -1099,8 +1090,9 @@
         std::make_unique<llvm::raw_fd_ostream>(FD, true));
   };
 
-  auto AddBuffer = [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) {
-    *AddStream(Task)->OS << MB->getBuffer();
+  auto AddBuffer = [&](size_t Task, const Twine &moduleName,
+                       std::unique_ptr<MemoryBuffer> MB) {
+    *AddStream(Task, moduleName)->OS << MB->getBuffer();
   };
 
   FileCache Cache;
diff --git a/src/llvm-project/llvm/tools/llc/CMakeLists.txt b/src/llvm-project/llvm/tools/llc/CMakeLists.txt
index f0bc582..d283ebe 100644
--- a/src/llvm-project/llvm/tools/llc/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llc/CMakeLists.txt
@@ -16,6 +16,7 @@
   SelectionDAG
   Support
   Target
+  TargetParser
   TransformUtils
   Vectorize
   )
diff --git a/src/llvm-project/llvm/tools/llc/llc.cpp b/src/llvm-project/llvm/tools/llc/llc.cpp
index f084ee2..f2dae67 100644
--- a/src/llvm-project/llvm/tools/llc/llc.cpp
+++ b/src/llvm-project/llvm/tools/llc/llc.cpp
@@ -28,7 +28,6 @@
 #include "llvm/IR/DataLayout.h"
 #include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/DiagnosticPrinter.h"
-#include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/LLVMRemarkStreamer.h"
 #include "llvm/IR/LegacyPassManager.h"
@@ -57,6 +56,7 @@
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Transforms/Utils/Cloning.h"
 #include <memory>
+#include <optional>
 using namespace llvm;
 
 static codegen::RegisterCodeGenFlags CGF;
@@ -120,7 +120,7 @@
     OptLevel("O",
              cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
                       "(default = '-O2')"),
-             cl::Prefix, cl::init(' '));
+             cl::Prefix, cl::init('2'));
 
 static cl::opt<std::string>
 TargetTriple("mtriple", cl::desc("Override target triple for module"));
@@ -166,7 +166,7 @@
     cl::desc("With PGO, include profile count in optimization remarks"),
     cl::Hidden);
 
-static cl::opt<Optional<uint64_t>, false, remarks::HotnessThresholdParser>
+static cl::opt<std::optional<uint64_t>, false, remarks::HotnessThresholdParser>
     RemarksHotnessThreshold(
         "pass-remarks-hotness-threshold",
         cl::desc("Minimum profile count required for "
@@ -374,6 +374,8 @@
   // Initialize debugging passes.
   initializeScavengerTestPass(*Registry);
 
+  // Register the Target and CPU printer for --version.
+  cl::AddExtraVersionPrinter(sys::printDefaultTargetAndDetectedCPU);
   // Register the target printer for --version.
   cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
 
@@ -467,19 +469,15 @@
   };
 
   auto MAttrs = codegen::getMAttrs();
-  bool SkipModule = codegen::getMCPU() == "help" ||
-                    (!MAttrs.empty() && MAttrs.front() == "help");
+  bool SkipModule =
+      CPUStr == "help" || (!MAttrs.empty() && MAttrs.front() == "help");
 
-  CodeGenOpt::Level OLvl = CodeGenOpt::Default;
-  switch (OptLevel) {
-  default:
+  CodeGenOpt::Level OLvl;
+  if (auto Level = CodeGenOpt::parseLevel(OptLevel)) {
+    OLvl = *Level;
+  } else {
     WithColor::error(errs(), argv[0]) << "invalid optimization level.\n";
     return 1;
-  case ' ': break;
-  case '0': OLvl = CodeGenOpt::None; break;
-  case '1': OLvl = CodeGenOpt::Less; break;
-  case '2': OLvl = CodeGenOpt::Default; break;
-  case '3': OLvl = CodeGenOpt::Aggressive; break;
   }
 
   // Parse 'none' or '$major.$minor'. Disallow -binutils-version=0 because we
@@ -520,16 +518,16 @@
     }
   };
 
-  Optional<Reloc::Model> RM = codegen::getExplicitRelocModel();
-  Optional<CodeModel::Model> CM = codegen::getExplicitCodeModel();
+  std::optional<Reloc::Model> RM = codegen::getExplicitRelocModel();
+  std::optional<CodeModel::Model> CM = codegen::getExplicitCodeModel();
 
   const Target *TheTarget = nullptr;
   std::unique_ptr<TargetMachine> Target;
 
   // If user just wants to list available options, skip module loading
   if (!SkipModule) {
-    auto SetDataLayout =
-        [&](StringRef DataLayoutTargetTriple) -> Optional<std::string> {
+    auto SetDataLayout = [&](StringRef DataLayoutTargetTriple,
+                             StringRef OldDLStr) -> std::optional<std::string> {
       // If we are supposed to override the target triple, do so now.
       std::string IRTargetTriple = DataLayoutTargetTriple.str();
       if (!TargetTriple.empty())
@@ -566,7 +564,8 @@
       if (MIR)
         M = MIR->parseIRModule(SetDataLayout);
     } else {
-      M = parseIRFile(InputFilename, Err, Context, SetDataLayout);
+      M = parseIRFile(InputFilename, Err, Context,
+                      ParserCallbacks(SetDataLayout));
     }
     if (!M) {
       Err.print(argv[0], WithColor::error(errs(), argv[0]));
@@ -575,9 +574,9 @@
     if (!TargetTriple.empty())
       M->setTargetTriple(Triple::normalize(TargetTriple));
 
-    Optional<CodeModel::Model> CM_IR = M->getCodeModel();
+    std::optional<CodeModel::Model> CM_IR = M->getCodeModel();
     if (!CM && CM_IR)
-      Target->setCodeModel(CM_IR.value());
+      Target->setCodeModel(*CM_IR);
   } else {
     TheTriple = Triple(Triple::normalize(TargetTriple));
     if (TheTriple.getTriple().empty())
diff --git a/src/llvm-project/llvm/tools/lli/CMakeLists.txt b/src/llvm-project/llvm/tools/lli/CMakeLists.txt
index 90797cc..3b3cf91 100644
--- a/src/llvm-project/llvm/tools/lli/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/lli/CMakeLists.txt
@@ -20,6 +20,7 @@
   SelectionDAG
   Support
   Target
+  TargetParser
   TransformUtils
   native
   )
diff --git a/src/llvm-project/llvm/tools/lli/ForwardingMemoryManager.h b/src/llvm-project/llvm/tools/lli/ForwardingMemoryManager.h
index 99a545e..f1de7a1 100644
--- a/src/llvm-project/llvm/tools/lli/ForwardingMemoryManager.h
+++ b/src/llvm-project/llvm/tools/lli/ForwardingMemoryManager.h
@@ -43,10 +43,10 @@
                                        IsReadOnly);
   }
 
-  void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
-                              uintptr_t RODataSize, uint32_t RODataAlign,
+  void reserveAllocationSpace(uintptr_t CodeSize, Align CodeAlign,
+                              uintptr_t RODataSize, Align RODataAlign,
                               uintptr_t RWDataSize,
-                              uint32_t RWDataAlign) override {
+                              Align RWDataAlign) override {
     MemMgr->reserveAllocationSpace(CodeSize, CodeAlign, RODataSize, RODataAlign,
                                    RWDataSize, RWDataAlign);
   }
diff --git a/src/llvm-project/llvm/tools/lli/lli.cpp b/src/llvm-project/llvm/tools/lli/lli.cpp
index 3fd2a61..c9b77e2 100644
--- a/src/llvm-project/llvm/tools/lli/lli.cpp
+++ b/src/llvm-project/llvm/tools/lli/lli.cpp
@@ -70,6 +70,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Transforms/Instrumentation.h"
 #include <cerrno>
+#include <optional>
 
 #if !defined(_MSC_VER) && !defined(__MINGW32__)
 #include <unistd.h>
@@ -173,7 +174,7 @@
   cl::opt<char> OptLevel("O",
                          cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
                                   "(default = '-O2')"),
-                         cl::Prefix, cl::init(' '));
+                         cl::Prefix, cl::init('2'));
 
   cl::opt<std::string>
   TargetTriple("mtriple", cl::desc("Override target triple for module"));
@@ -373,53 +374,6 @@
   }
 };
 
-class ORCPlatformSupport : public orc::LLJIT::PlatformSupport {
-public:
-  ORCPlatformSupport(orc::LLJIT &J) : J(J) {}
-
-  Error initialize(orc::JITDylib &JD) override {
-    using llvm::orc::shared::SPSExecutorAddr;
-    using llvm::orc::shared::SPSString;
-    using SPSDLOpenSig = SPSExecutorAddr(SPSString, int32_t);
-    enum dlopen_mode : int32_t {
-      ORC_RT_RTLD_LAZY = 0x1,
-      ORC_RT_RTLD_NOW = 0x2,
-      ORC_RT_RTLD_LOCAL = 0x4,
-      ORC_RT_RTLD_GLOBAL = 0x8
-    };
-
-    if (auto WrapperAddr = J.lookup("__orc_rt_jit_dlopen_wrapper")) {
-      return J.getExecutionSession().callSPSWrapper<SPSDLOpenSig>(
-          *WrapperAddr, DSOHandles[&JD], JD.getName(),
-          int32_t(ORC_RT_RTLD_LAZY));
-    } else
-      return WrapperAddr.takeError();
-  }
-
-  Error deinitialize(orc::JITDylib &JD) override {
-    using llvm::orc::shared::SPSExecutorAddr;
-    using SPSDLCloseSig = int32_t(SPSExecutorAddr);
-
-    if (auto WrapperAddr = J.lookup("__orc_rt_jit_dlclose_wrapper")) {
-      int32_t result;
-      auto E = J.getExecutionSession().callSPSWrapper<SPSDLCloseSig>(
-          *WrapperAddr, result, DSOHandles[&JD]);
-      if (E)
-        return E;
-      else if (result)
-        return make_error<StringError>("dlclose failed",
-                                       inconvertibleErrorCode());
-      DSOHandles.erase(&JD);
-    } else
-      return WrapperAddr.takeError();
-    return Error::success();
-  }
-
-private:
-  orc::LLJIT &J;
-  DenseMap<orc::JITDylib *, orc::ExecutorAddr> DSOHandles;
-};
-
 // On Mingw and Cygwin, an external symbol named '__main' is called from the
 // generated 'main' function to allow static initialization.  To avoid linking
 // problems with remote targets (because lli's remote target support does not
@@ -454,17 +408,10 @@
 }
 
 CodeGenOpt::Level getOptLevel() {
-  switch (OptLevel) {
-  default:
-    WithColor::error(errs(), "lli") << "invalid optimization level.\n";
-    exit(1);
-  case '0': return CodeGenOpt::None;
-  case '1': return CodeGenOpt::Less;
-  case ' ':
-  case '2': return CodeGenOpt::Default;
-  case '3': return CodeGenOpt::Aggressive;
-  }
-  llvm_unreachable("Unrecognized opt level.");
+  if (auto Level = CodeGenOpt::parseLevel(OptLevel))
+    return *Level;
+  WithColor::error(errs(), "lli") << "invalid optimization level.\n";
+  exit(1);
 }
 
 [[noreturn]] static void reportError(SMDiagnostic Err, const char *ProgName) {
@@ -536,9 +483,9 @@
   builder.setMCPU(codegen::getCPUStr());
   builder.setMAttrs(codegen::getFeatureList());
   if (auto RM = codegen::getExplicitRelocModel())
-    builder.setRelocationModel(RM.value());
+    builder.setRelocationModel(*RM);
   if (auto CM = codegen::getExplicitCodeModel())
-    builder.setCodeModel(CM.value());
+    builder.setCodeModel(*CM);
   builder.setErrorStr(&ErrorMsg);
   builder.setEngineKind(ForceInterpreter
                         ? EngineKind::Interpreter
@@ -891,8 +838,8 @@
 
   // Get TargetTriple and DataLayout from the main module if they're explicitly
   // set.
-  Optional<Triple> TT;
-  Optional<DataLayout> DL;
+  std::optional<Triple> TT;
+  std::optional<DataLayout> DL;
   MainModule.withModuleDo([&](Module &M) {
       if (!M.getTargetTriple().empty())
         TT = Triple(M.getTargetTriple());
@@ -969,10 +916,7 @@
   }
   switch (P) {
   case LLJITPlatform::ORC:
-    Builder.setPlatformSetUp([](llvm::orc::LLJIT &J) -> llvm::Error {
-      J.setPlatformSupport(std::make_unique<ORCPlatformSupport>(J));
-      return Error::success();
-    });
+    Builder.setPlatformSetUp(orc::setUpOrcPlatform);
     break;
   case LLJITPlatform::GenericIR:
     // Nothing to do: LLJITBuilder will use this by default.
diff --git a/src/llvm-project/llvm/tools/llvm-ar/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-ar/CMakeLists.txt
index 166731e..19e3fad 100644
--- a/src/llvm-project/llvm/tools/llvm-ar/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-ar/CMakeLists.txt
@@ -8,6 +8,7 @@
   LibDriver
   Object
   Support
+  TargetParser
   TextAPI
   )
 
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 4ffc5cf..12f3196 100644
--- a/src/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ar/llvm-ar.cpp
@@ -875,8 +875,16 @@
 
   if (Operation == QuickAppend || Members.empty())
     return IA_AddOldMember;
-  auto MI = find_if(
-      Members, [Name](StringRef Path) { return comparePaths(Name, Path); });
+
+  auto MI = find_if(Members, [Name](StringRef Path) {
+    if (Thin && !sys::path::is_absolute(Path)) {
+      Expected<std::string> PathOrErr =
+          computeArchiveRelativePath(ArchiveName, Path);
+      return comparePaths(Name, PathOrErr ? *PathOrErr : Path);
+    } else {
+      return comparePaths(Name, Path);
+    }
+  });
 
   if (MI == Members.end())
     return IA_AddOldMember;
@@ -1218,7 +1226,7 @@
       break;
     case MRICommand::CreateThin:
       Thin = true;
-      LLVM_FALLTHROUGH;
+      [[fallthrough]];
     case MRICommand::Create:
       Create = true;
       if (!ArchiveName.empty())
@@ -1322,7 +1330,7 @@
   SmallVector<const char *, 0> Argv(argv + 1, argv + argc);
   StringSaver Saver(Alloc);
 
-  cl::ExpandResponseFiles(Saver, getRspQuoting(makeArrayRef(argv, argc)), Argv);
+  cl::ExpandResponseFiles(Saver, getRspQuoting(ArrayRef(argv, argc)), Argv);
 
   // Get BitMode from enviorment variable "OBJECT_MODE" for AIX OS, if
   // specified.
@@ -1465,11 +1473,11 @@
   };
 
   if (Is("dlltool"))
-    return dlltoolDriverMain(makeArrayRef(argv, argc));
+    return dlltoolDriverMain(ArrayRef(argv, argc));
   if (Is("ranlib"))
     return ranlib_main(argc, argv);
   if (Is("lib"))
-    return libDriverMain(makeArrayRef(argv, argc));
+    return libDriverMain(ArrayRef(argv, argc));
   if (Is("ar"))
     return ar_main(argc, argv);
 
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 b777f72..ef1c50f 100644
--- a/src/llvm-project/llvm/tools/llvm-as/llvm-as.cpp
+++ b/src/llvm-project/llvm/tools/llvm-as/llvm-as.cpp
@@ -27,6 +27,7 @@
 #include "llvm/Support/SystemUtils.h"
 #include "llvm/Support/ToolOutputFile.h"
 #include <memory>
+#include <optional>
 using namespace llvm;
 
 cl::OptionCategory AsCat("llvm-as Options");
@@ -120,9 +121,9 @@
 
   // Parse the file now...
   SMDiagnostic Err;
-  auto SetDataLayout = [](StringRef) -> Optional<std::string> {
+  auto SetDataLayout = [](StringRef, StringRef) -> std::optional<std::string> {
     if (ClDataLayout.empty())
-      return None;
+      return std::nullopt;
     return ClDataLayout;
   };
   ParsedModuleAndIndex ModuleAndIndex;
diff --git a/src/llvm-project/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp b/src/llvm-project/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
index a238b0c..610b479 100644
--- a/src/llvm-project/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp
@@ -27,7 +27,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ADT/Optional.h"
 #include "llvm/Bitcode/BitcodeAnalyzer.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
@@ -36,6 +35,7 @@
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 #include <memory>
+#include <optional>
 using namespace llvm;
 
 static cl::OptionCategory BCAnalyzerCategory("BC Analyzer Options");
@@ -113,8 +113,9 @@
     BlockInfoMB = ExitOnErr(openBitcodeFile(BlockInfoFilename));
 
   BitcodeAnalyzer BA(MB->getBuffer(),
-                     BlockInfoMB ? Optional<StringRef>(BlockInfoMB->getBuffer())
-                                 : None);
+                     BlockInfoMB
+                         ? std::optional<StringRef>(BlockInfoMB->getBuffer())
+                         : std::nullopt);
 
   BCDumpOptions O(outs());
   O.Histogram = !NoHistogram;
@@ -123,8 +124,8 @@
   O.DumpBlockinfo = DumpBlockinfo;
 
   ExitOnErr(BA.analyze(
-      Dump ? Optional<BCDumpOptions>(O) : Optional<BCDumpOptions>(None),
-      CheckHash.empty() ? None : Optional<StringRef>(CheckHash)));
+      Dump ? std::optional<BCDumpOptions>(O) : std::optional<BCDumpOptions>(),
+      CheckHash.empty() ? std::nullopt : std::optional<StringRef>(CheckHash)));
 
   if (Dump)
     outs() << "\n\n";
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 b7b7730..7a54e26 100644
--- a/src/llvm-project/llvm/tools/llvm-c-test/echo.cpp
+++ b/src/llvm-project/llvm/tools/llvm-c-test/echo.cpp
@@ -159,6 +159,8 @@
         return LLVMX86MMXTypeInContext(Ctx);
       case LLVMTokenTypeKind:
         return LLVMTokenTypeInContext(Ctx);
+      case LLVMTargetExtTypeKind:
+        assert(false && "Implement me");
     }
 
     fprintf(stderr, "%d is not a supported typekind\n", Kind);
@@ -1374,7 +1376,7 @@
   }
 }
 
-int llvm_echo(bool OpaquePointers) {
+int llvm_echo(void) {
   LLVMEnablePrettyStackTrace();
 
   LLVMModuleRef Src = llvm_load_module(false, true);
@@ -1383,8 +1385,6 @@
   size_t ModuleIdentLen;
   const char *ModuleName = LLVMGetModuleIdentifier(Src, &ModuleIdentLen);
   LLVMContextRef Ctx = LLVMContextCreate();
-  if (!OpaquePointers)
-    LLVMContextSetOpaquePointers(Ctx, false);
   LLVMModuleRef M = LLVMModuleCreateWithNameInContext(ModuleName, Ctx);
 
   LLVMSetSourceFileName(M, SourceFileName, SourceFileLen);
diff --git a/src/llvm-project/llvm/tools/llvm-c-test/include-all.c b/src/llvm-project/llvm/tools/llvm-c-test/include-all.c
index 144393a..69ed753 100644
--- a/src/llvm-project/llvm/tools/llvm-c-test/include-all.c
+++ b/src/llvm-project/llvm/tools/llvm-c-test/include-all.c
@@ -35,7 +35,6 @@
 #include "llvm-c/Support.h"
 #include "llvm-c/Target.h"
 #include "llvm-c/TargetMachine.h"
-#include "llvm-c/Transforms/AggressiveInstCombine.h"
 #include "llvm-c/Transforms/InstCombine.h"
 #include "llvm-c/Transforms/IPO.h"
 #include "llvm-c/Transforms/PassManagerBuilder.h"
diff --git a/src/llvm-project/llvm/tools/llvm-c-test/llvm-c-test.h b/src/llvm-project/llvm/tools/llvm-c-test/llvm-c-test.h
index 7c08423..b828a82 100644
--- a/src/llvm-project/llvm/tools/llvm-c-test/llvm-c-test.h
+++ b/src/llvm-project/llvm/tools/llvm-c-test/llvm-c-test.h
@@ -50,7 +50,7 @@
 int llvm_targets_list(void);
 
 // echo.c
-int llvm_echo(bool OpaquePointers);
+int llvm_echo(void);
 
 // diagnostic.c
 int llvm_test_diagnostic_handler(void);
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 2d010b8..89a43db 100644
--- a/src/llvm-project/llvm/tools/llvm-c-test/main.c
+++ b/src/llvm-project/llvm/tools/llvm-c-test/main.c
@@ -95,9 +95,8 @@
     return llvm_test_function_attributes();
   } else if (argc == 2 && !strcmp(argv[1], "--test-callsite-attributes")) {
     return llvm_test_callsite_attributes();
-  } else if ((argc == 2 || argc == 3) && !strcmp(argv[1], "--echo")) {
-    return llvm_echo(argc == 3 ? strcmp(argv[2], "--no-opaque-pointers") != 0
-                               : 1);
+  } else if (argc == 2 && !strcmp(argv[1], "--echo")) {
+    return llvm_echo();
   } else if (argc == 2 && !strcmp(argv[1], "--test-diagnostic-handler")) {
     return llvm_test_diagnostic_handler();
   } else if (argc == 2 && !strcmp(argv[1], "--test-dibuilder")) {
diff --git a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt
index 679bffe..03a7eae 100644
--- a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/CMakeLists.txt
@@ -5,6 +5,7 @@
     Object
     Support
     Symbolize
+    TargetParser
     )
 
 add_llvm_library(LLVMCFIVerify
diff --git a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
index e8990c3..3e03c82 100644
--- a/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cfi-verify/lib/FileAnalysis.cpp
@@ -96,7 +96,11 @@
   }
 
   Analysis.ObjectTriple = Analysis.Object->makeTriple();
-  Analysis.Features = Analysis.Object->getFeatures();
+  Expected<SubtargetFeatures> Features = Analysis.Object->getFeatures();
+  if (!Features)
+    return Features.takeError();
+
+  Analysis.Features = *Features;
 
   // Init the rest of the object.
   if (auto InitResponse = Analysis.initialiseDisassemblyMembers())
@@ -365,7 +369,7 @@
 
 void FileAnalysis::printInstruction(const Instr &InstrMeta,
                                     raw_ostream &OS) const {
-  Printer->printInst(&InstrMeta.Instruction, 0, "", *SubtargetInfo.get(), OS);
+  Printer->printInst(&InstrMeta.Instruction, 0, "", *SubtargetInfo, OS);
 }
 
 Error FileAnalysis::initialiseDisassemblyMembers() {
diff --git a/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt
index 6faee03..35b8b21 100644
--- a/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-config/CMakeLists.txt
@@ -1,4 +1,7 @@
-set(LLVM_LINK_COMPONENTS support)
+set(LLVM_LINK_COMPONENTS
+  Support
+  TargetParser
+  )
 
 set(BUILDVARIABLES_SRCPATH ${CMAKE_CURRENT_SOURCE_DIR}/BuildVariables.inc.in)
 set(BUILDVARIABLES_OBJPATH ${CMAKE_CURRENT_BINARY_DIR}/BuildVariables.inc)
@@ -77,7 +80,7 @@
 configure_file(${BUILDVARIABLES_SRCPATH} ${BUILDVARIABLES_OBJPATH} @ONLY)
 
 # Set build-time environment(s).
-add_definitions(-DCMAKE_CFG_INTDIR="${CMAKE_CFG_INTDIR}")
+add_compile_definitions(CMAKE_CFG_INTDIR="${CMAKE_CFG_INTDIR}")
 
 if(LLVM_ENABLE_MODULES)
   target_compile_options(llvm-config PUBLIC
@@ -88,10 +91,18 @@
 # Add the dependency on the generation step.
 add_file_dependencies(${CMAKE_CURRENT_SOURCE_DIR}/llvm-config.cpp ${BUILDVARIABLES_OBJPATH})
 
-if(CMAKE_CROSSCOMPILING AND NOT LLVM_CONFIG_PATH)
-  build_native_tool(llvm-config LLVM_CONFIG_PATH)
-  set(LLVM_CONFIG_PATH "${LLVM_CONFIG_PATH}" CACHE STRING "")
+if(CMAKE_CROSSCOMPILING)
+  if (LLVM_NATIVE_TOOL_DIR AND NOT LLVM_CONFIG_PATH)
+    if (EXISTS "${LLVM_NATIVE_TOOL_DIR}/llvm-config${LLVM_HOST_EXECUTABLE_SUFFIX}")
+      set(LLVM_CONFIG_PATH "${LLVM_NATIVE_TOOL_DIR}/llvm-config${LLVM_HOST_EXECUTABLE_SUFFIX}")
+    endif()
+  endif()
 
-  add_custom_target(NativeLLVMConfig DEPENDS ${LLVM_CONFIG_PATH})
-  add_dependencies(llvm-config NativeLLVMConfig)
+  if (NOT LLVM_CONFIG_PATH)
+    build_native_tool(llvm-config LLVM_CONFIG_PATH)
+    set(LLVM_CONFIG_PATH "${LLVM_CONFIG_PATH}" CACHE STRING "")
+
+    add_custom_target(NativeLLVMConfig DEPENDS ${LLVM_CONFIG_PATH})
+    add_dependencies(llvm-config NativeLLVMConfig)
+  endif()
 endif()
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 2c6c55f..b1d795a 100644
--- a/src/llvm-project/llvm/tools/llvm-config/llvm-config.cpp
+++ b/src/llvm-project/llvm/tools/llvm-config/llvm-config.cpp
@@ -170,10 +170,8 @@
 
   // Build a map of component names to information.
   StringMap<AvailableComponent *> ComponentMap;
-  for (unsigned i = 0; i != array_lengthof(AvailableComponents); ++i) {
-    AvailableComponent *AC = &AvailableComponents[i];
-    ComponentMap[AC->Name] = AC;
-  }
+  for (auto &AC : AvailableComponents)
+    ComponentMap[AC.Name] = &AC;
 
   // Visit the components.
   for (unsigned i = 0, e = Components.size(); i != e; ++i) {
@@ -236,7 +234,6 @@
   --obj-root        Print the object root used to build LLVM.\n\
   --prefix          Print the installation prefix.\n\
   --shared-mode     Print how the provided components can be collectively linked (`shared` or `static`).\n\
-  --src-root        Print the source root LLVM was built from.\n\
   --system-libs     System Libraries needed to link against LLVM components.\n\
   --targets-built   List of all targets currently built.\n\
   --version         Print LLVM version.\n\
@@ -546,15 +543,14 @@
         /// built, print LLVM_DYLIB_COMPONENTS instead of everything
         /// in the manifest.
         std::vector<std::string> Components;
-        for (unsigned j = 0; j != array_lengthof(AvailableComponents); ++j) {
+        for (const auto &AC : AvailableComponents) {
           // Only include non-installed components when in a development tree.
-          if (!AvailableComponents[j].IsInstalled && !IsInDevelopmentTree)
+          if (!AC.IsInstalled && !IsInDevelopmentTree)
             continue;
 
-          Components.push_back(AvailableComponents[j].Name);
-          if (AvailableComponents[j].Library && !IsInDevelopmentTree) {
-            std::string path(
-                GetComponentLibraryPath(AvailableComponents[j].Library, false));
+          Components.push_back(AC.Name);
+          if (AC.Library && !IsInDevelopmentTree) {
+            std::string path(GetComponentLibraryPath(AC.Library, false));
             if (DirSep == "\\") {
               std::replace(path.begin(), path.end(), '/', '\\');
             }
@@ -595,8 +591,6 @@
         PrintSharedMode = true;
       } else if (Arg == "--obj-root") {
         OS << ActivePrefix << '\n';
-      } else if (Arg == "--src-root") {
-        OS << LLVM_SRC_ROOT << '\n';
       } else if (Arg == "--ignore-libllvm") {
         LinkDyLib = false;
         LinkMode = BuiltSharedLibs ? LinkModeShared : LinkModeAuto;
@@ -660,7 +654,7 @@
         }
         WithColor::error(errs(), "llvm-config")
             << "component libraries and shared library\n\n";
-        LLVM_FALLTHROUGH;
+        [[fallthrough]];
       case LinkModeStatic:
         for (auto &Lib : MissingLibs)
           WithColor::error(errs(), "llvm-config") << "missing: " << Lib << "\n";
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-cov/CMakeLists.txt
index c3afec8..7acc87e 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-cov/CMakeLists.txt
@@ -1,4 +1,11 @@
-set(LLVM_LINK_COMPONENTS core support object coverage profiledata)
+set(LLVM_LINK_COMPONENTS
+  Core
+  Support
+  Object
+  Coverage
+  ProfileData
+  TargetParser
+  )
 
 add_llvm_tool(llvm-cov
   llvm-cov.cpp
@@ -14,3 +21,5 @@
   SourceCoverageViewText.cpp
   TestingSupport.cpp
   )
+
+target_link_libraries(llvm-cov PRIVATE LLVMDebuginfod)
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp b/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
index 13b6c30..7b71d5a 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CodeCoverage.cpp
@@ -23,6 +23,10 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Triple.h"
+#include "llvm/Debuginfod/BuildIDFetcher.h"
+#include "llvm/Debuginfod/Debuginfod.h"
+#include "llvm/Debuginfod/HTTPClient.h"
+#include "llvm/Object/BuildID.h"
 #include "llvm/ProfileData/Coverage/CoverageMapping.h"
 #include "llvm/ProfileData/InstrProfReader.h"
 #include "llvm/Support/CommandLine.h"
@@ -41,6 +45,7 @@
 
 #include <functional>
 #include <map>
+#include <optional>
 #include <system_error>
 
 using namespace llvm;
@@ -84,7 +89,7 @@
   bool isEquivalentFile(StringRef FilePath1, StringRef FilePath2);
 
   /// Retrieve a file status with a cache.
-  Optional<sys::fs::file_status> getFileStatus(StringRef FilePath);
+  std::optional<sys::fs::file_status> getFileStatus(StringRef FilePath);
 
   /// Return a memory buffer for the given source file.
   ErrorOr<const MemoryBuffer &> getSourceFile(StringRef SourceFile);
@@ -157,10 +162,10 @@
 
   /// The coverage data path to be remapped from, and the source path to be
   /// remapped to, when using -path-equivalence.
-  Optional<std::pair<std::string, std::string>> PathRemapping;
+  std::optional<std::pair<std::string, std::string>> PathRemapping;
 
   /// File status cache used when finding the same file.
-  StringMap<Optional<sys::fs::file_status>> FileStatusCache;
+  StringMap<std::optional<sys::fs::file_status>> FileStatusCache;
 
   /// The architecture the coverage mapping data targets.
   std::vector<StringRef> CoverageArches;
@@ -178,6 +183,8 @@
 
   /// Allowlist from -name-allowlist to be used for filtering.
   std::unique_ptr<SpecialCaseList> NameAllowlist;
+
+  std::unique_ptr<object::BuildIDFetcher> BIDFetcher;
 };
 }
 
@@ -248,7 +255,7 @@
   }
 }
 
-Optional<sys::fs::file_status>
+std::optional<sys::fs::file_status>
 CodeCoverageTool::getFileStatus(StringRef FilePath) {
   auto It = FileStatusCache.try_emplace(FilePath);
   auto &CachedStatus = It.first->getValue();
@@ -434,7 +441,7 @@
               ObjectFilename);
   auto CoverageOrErr =
       CoverageMapping::load(ObjectFilenames, PGOFilename, CoverageArches,
-                            ViewOpts.CompilationDirectory);
+                            ViewOpts.CompilationDirectory, BIDFetcher.get());
   if (Error E = CoverageOrErr.takeError()) {
     error("Failed to load coverage: " + toString(std::move(E)));
     return nullptr;
@@ -553,13 +560,16 @@
 
   // Invoke the demangler.
   std::vector<StringRef> ArgsV;
+  ArgsV.reserve(ViewOpts.DemanglerOpts.size());
   for (StringRef Arg : ViewOpts.DemanglerOpts)
     ArgsV.push_back(Arg);
-  Optional<StringRef> Redirects[] = {InputPath.str(), OutputPath.str(), {""}};
+  std::optional<StringRef> Redirects[] = {
+      InputPath.str(), OutputPath.str(), {""}};
   std::string ErrMsg;
-  int RC = sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV,
-                               /*env=*/None, Redirects, /*secondsToWait=*/0,
-                               /*memoryLimit=*/0, &ErrMsg);
+  int RC =
+      sys::ExecuteAndWait(ViewOpts.DemanglerOpts[0], ArgsV,
+                          /*env=*/std::nullopt, Redirects, /*secondsToWait=*/0,
+                          /*memoryLimit=*/0, &ErrMsg);
   if (RC) {
     error(ErrMsg, ViewOpts.DemanglerOpts[0]);
     return;
@@ -625,7 +635,7 @@
       "dump-collected-objects", cl::Optional, cl::Hidden,
       cl::desc("Show the collected coverage object files"));
 
-  cl::list<std::string> InputSourceFiles(cl::Positional,
+  cl::list<std::string> InputSourceFiles("sources", cl::Positional,
                                          cl::desc("<Source files>"));
 
   cl::opt<bool> DebugDumpCollectedPaths(
@@ -643,6 +653,14 @@
   cl::opt<bool> DebugDump("dump", cl::Optional,
                           cl::desc("Show internal debug dump"));
 
+  cl::list<std::string> DebugFileDirectory(
+      "debug-file-directory",
+      cl::desc("Directories to search for object files by build ID"));
+  cl::opt<bool> Debuginfod(
+      "debuginfod", cl::ZeroOrMore,
+      cl::desc("Use debuginfod to look up object files from profile"),
+      cl::init(canUseDebuginfod()));
+
   cl::opt<CoverageViewOptions::OutputFormat> Format(
       "format", cl::desc("Output format for line-based coverage reports"),
       cl::values(clEnumValN(CoverageViewOptions::OutputFormat::Text, "text",
@@ -671,13 +689,6 @@
                "file"),
       cl::cat(FilteringCategory));
 
-  // Allow for accepting previous option name.
-  cl::list<std::string> NameFilterFilesDeprecated(
-      "name-whitelist", cl::Optional, cl::Hidden,
-      cl::desc("Show code coverage only for functions listed in the given "
-               "file. Deprecated, use -name-allowlist instead"),
-      cl::cat(FilteringCategory));
-
   cl::list<std::string> NameRegexFilters(
       "name-regex", cl::Optional,
       cl::desc("Show code coverage only for functions that match the given "
@@ -752,12 +763,18 @@
   auto commandLineParser = [&, this](int argc, const char **argv) -> int {
     cl::ParseCommandLineOptions(argc, argv, "LLVM code coverage tool\n");
     ViewOpts.Debug = DebugDump;
+    if (Debuginfod) {
+      HTTPClient::initialize();
+      BIDFetcher = std::make_unique<DebuginfodFetcher>(DebugFileDirectory);
+    } else {
+      BIDFetcher = std::make_unique<object::BuildIDFetcher>(DebugFileDirectory);
+    }
 
     if (!CovFilename.empty())
       ObjectFilenames.emplace_back(CovFilename);
     for (const std::string &Filename : CovFilenames)
       ObjectFilenames.emplace_back(Filename);
-    if (ObjectFilenames.empty()) {
+    if (ObjectFilenames.empty() && !Debuginfod && DebugFileDirectory.empty()) {
       errs() << "No filenames specified!\n";
       ::exit(1);
     }
@@ -815,16 +832,10 @@
     }
 
     // Read in -name-allowlist files.
-    if (!NameFilterFiles.empty() || !NameFilterFilesDeprecated.empty()) {
+    if (!NameFilterFiles.empty()) {
       std::string SpecialCaseListErr;
-      if (!NameFilterFiles.empty())
-        NameAllowlist = SpecialCaseList::create(
-            NameFilterFiles, *vfs::getRealFileSystem(), SpecialCaseListErr);
-      if (!NameFilterFilesDeprecated.empty())
-        NameAllowlist = SpecialCaseList::create(NameFilterFilesDeprecated,
-                                                *vfs::getRealFileSystem(),
-                                                SpecialCaseListErr);
-
+      NameAllowlist = SpecialCaseList::create(
+          NameFilterFiles, *vfs::getRealFileSystem(), SpecialCaseListErr);
       if (!NameAllowlist)
         error(SpecialCaseListErr);
     }
@@ -834,14 +845,9 @@
       auto NameFilterer = std::make_unique<CoverageFilters>();
       for (const auto &Name : NameFilters)
         NameFilterer->push_back(std::make_unique<NameCoverageFilter>(Name));
-      if (NameAllowlist) {
-        if (!NameFilterFiles.empty())
-          NameFilterer->push_back(
-              std::make_unique<NameAllowlistCoverageFilter>(*NameAllowlist));
-        if (!NameFilterFilesDeprecated.empty())
-          NameFilterer->push_back(
-              std::make_unique<NameWhitelistCoverageFilter>(*NameAllowlist));
-      }
+      if (NameAllowlist && !NameFilterFiles.empty())
+        NameFilterer->push_back(
+            std::make_unique<NameAllowlistCoverageFilter>(*NameAllowlist));
       for (const auto &Regex : NameRegexFilters)
         NameFilterer->push_back(
             std::make_unique<NameRegexCoverageFilter>(Regex));
@@ -881,10 +887,8 @@
         }
         CoverageArches.emplace_back(Arch);
       }
-      if (CoverageArches.size() == 1)
-        CoverageArches.insert(CoverageArches.end(), ObjectFilenames.size() - 1,
-                              CoverageArches[0]);
-      if (CoverageArches.size() != ObjectFilenames.size()) {
+      if (CoverageArches.size() != 1 &&
+          CoverageArches.size() != ObjectFilenames.size()) {
         error("Number of architectures doesn't match the number of objects");
         return 1;
       }
@@ -1090,7 +1094,7 @@
         FilenameFunctionMap;
     for (const auto &SourceFile : SourceFiles)
       for (const auto &Function : Coverage->getCoveredFunctions(SourceFile))
-        if (Filters.matches(*Coverage.get(), Function))
+        if (Filters.matches(*Coverage, Function))
           FilenameFunctionMap[SourceFile].push_back(&Function);
 
     // Only print filter matching functions for each file.
@@ -1179,7 +1183,7 @@
   if (!Coverage)
     return 1;
 
-  CoverageReport Report(ViewOpts, *Coverage.get());
+  CoverageReport Report(ViewOpts, *Coverage);
   if (!ShowFunctionSummaries) {
     if (SourceFiles.empty())
       Report.renderFileReports(llvm::outs(), IgnoreFilenameFilters);
@@ -1210,12 +1214,17 @@
                               cl::desc("Don't export per-function data"),
                               cl::cat(ExportCategory));
 
+  cl::opt<bool> SkipBranches("skip-branches", cl::Optional,
+                              cl::desc("Don't export branch data (LCOV)"),
+                              cl::cat(ExportCategory));
+
   auto Err = commandLineParser(argc, argv);
   if (Err)
     return Err;
 
   ViewOpts.SkipExpansions = SkipExpansions;
   ViewOpts.SkipFunctions = SkipFunctions;
+  ViewOpts.SkipBranches = SkipBranches;
 
   if (ViewOpts.Format != CoverageViewOptions::OutputFormat::Text &&
       ViewOpts.Format != CoverageViewOptions::OutputFormat::Lcov) {
@@ -1240,16 +1249,16 @@
 
   switch (ViewOpts.Format) {
   case CoverageViewOptions::OutputFormat::Text:
-    Exporter = std::make_unique<CoverageExporterJson>(*Coverage.get(),
-                                                       ViewOpts, outs());
+    Exporter =
+        std::make_unique<CoverageExporterJson>(*Coverage, ViewOpts, outs());
     break;
   case CoverageViewOptions::OutputFormat::HTML:
     // Unreachable because we should have gracefully terminated with an error
     // above.
     llvm_unreachable("Export in HTML is not supported!");
   case CoverageViewOptions::OutputFormat::Lcov:
-    Exporter = std::make_unique<CoverageExporterLcov>(*Coverage.get(),
-                                                       ViewOpts, outs());
+    Exporter =
+        std::make_unique<CoverageExporterLcov>(*Coverage, ViewOpts, outs());
     break;
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp b/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp
index 2e161f5..9e43377 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterJson.cpp
@@ -48,7 +48,6 @@
 
 #include "CoverageExporterJson.h"
 #include "CoverageReport.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/ThreadPool.h"
@@ -291,8 +290,8 @@
     const json::Object *ObjB = B.getAsObject();
     assert(ObjA != nullptr && "Value A was not an Object");
     assert(ObjB != nullptr && "Value B was not an Object");
-    const StringRef FilenameA = ObjA->getString("filename").value();
-    const StringRef FilenameB = ObjB->getString("filename").value();
+    const StringRef FilenameA = *ObjA->getString("filename");
+    const StringRef FilenameB = *ObjB->getString("filename");
     return FilenameA.compare(FilenameB) < 0;
   });
   auto Export = json::Object(
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterLcov.cpp b/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
index 0096a3d..ae8f556 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageExporterLcov.cpp
@@ -173,7 +173,7 @@
 void renderFile(raw_ostream &OS, const coverage::CoverageMapping &Coverage,
                 const std::string &Filename,
                 const FileCoverageSummary &FileReport, bool ExportSummaryOnly,
-                bool SkipFunctions) {
+                bool SkipFunctions, bool SkipBranches) {
   OS << "SF:" << Filename << '\n';
 
   if (!ExportSummaryOnly && !SkipFunctions) {
@@ -185,9 +185,11 @@
     // Calculate and render detailed coverage information for given file.
     auto FileCoverage = Coverage.getCoverageForFile(Filename);
     renderLineExecutionCounts(OS, FileCoverage);
-    renderBranchExecutionCounts(OS, Coverage, FileCoverage);
+    if (!SkipBranches)
+      renderBranchExecutionCounts(OS, Coverage, FileCoverage);
   }
-  renderBranchSummary(OS, FileReport);
+  if (!SkipBranches)
+    renderBranchSummary(OS, FileReport);
   renderLineSummary(OS, FileReport);
 
   OS << "end_of_record\n";
@@ -196,10 +198,11 @@
 void renderFiles(raw_ostream &OS, const coverage::CoverageMapping &Coverage,
                  ArrayRef<std::string> SourceFiles,
                  ArrayRef<FileCoverageSummary> FileReports,
-                 bool ExportSummaryOnly, bool SkipFunctions) {
+                 bool ExportSummaryOnly, bool SkipFunctions,
+                 bool SkipBranches) {
   for (unsigned I = 0, E = SourceFiles.size(); I < E; ++I)
     renderFile(OS, Coverage, SourceFiles[I], FileReports[I], ExportSummaryOnly,
-               SkipFunctions);
+               SkipFunctions, SkipBranches);
 }
 
 } // end anonymous namespace
@@ -218,5 +221,5 @@
   auto FileReports = CoverageReport::prepareFileReports(Coverage, Totals,
                                                         SourceFiles, Options);
   renderFiles(OS, Coverage, SourceFiles, FileReports, Options.ExportSummaryOnly,
-              Options.SkipFunctions);
+              Options.SkipFunctions, Options.SkipBranches);
 }
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageFilters.cpp b/src/llvm-project/llvm/tools/llvm-cov/CoverageFilters.cpp
index b799864..bc1ddb4 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageFilters.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageFilters.cpp
@@ -40,13 +40,6 @@
   return Allowlist.inSection("llvmcov", "allowlist_fun", Function.Name);
 }
 
-// TODO: remove this when -name-whitelist option is removed.
-bool NameWhitelistCoverageFilter::matches(
-    const coverage::CoverageMapping &,
-    const coverage::FunctionRecord &Function) const {
-  return Whitelist.inSection("llvmcov", "whitelist_fun", Function.Name);
-}
-
 bool RegionCoverageFilter::matches(
     const coverage::CoverageMapping &CM,
     const coverage::FunctionRecord &Function) const {
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageFilters.h b/src/llvm-project/llvm/tools/llvm-cov/CoverageFilters.h
index 3040fe7..5345b0c 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageFilters.h
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageFilters.h
@@ -79,18 +79,6 @@
                const coverage::FunctionRecord &Function) const override;
 };
 
-// TODO: Remove this class when -name-whitelist option is removed.
-class NameWhitelistCoverageFilter : public CoverageFilter {
-  const SpecialCaseList &Whitelist;
-
-public:
-  NameWhitelistCoverageFilter(const SpecialCaseList &Whitelist)
-      : Whitelist(Whitelist) {}
-
-  bool matches(const coverage::CoverageMapping &CM,
-               const coverage::FunctionRecord &Function) const override;
-};
-
 /// Matches numbers that pass a certain threshold.
 template <typename T> class StatisticThresholdFilter {
 public:
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp b/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp
index c91edc2..be042aa 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageReport.cpp
@@ -437,6 +437,7 @@
       prepareFileReports(Coverage, Totals, Files, Options, Filters);
 
   std::vector<StringRef> Filenames;
+  Filenames.reserve(FileReports.size());
   for (const FileCoverageSummary &FCS : FileReports)
     Filenames.emplace_back(FCS.Name);
   adjustColumnWidths(Filenames, {});
diff --git a/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h b/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h
index c6e9981..fedf2df 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h
+++ b/src/llvm-project/llvm/tools/llvm-cov/CoverageViewOptions.h
@@ -41,6 +41,7 @@
   bool ExportSummaryOnly;
   bool SkipExpansions;
   bool SkipFunctions;
+  bool SkipBranches;
   OutputFormat Format;
   BranchOutputType ShowBranches;
   std::string ShowOutputDirectory;
diff --git a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
index 46782c9..50e3dcc 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewHTML.cpp
@@ -12,11 +12,11 @@
 
 #include "CoverageReport.h"
 #include "SourceCoverageViewHTML.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/Path.h"
+#include <optional>
 
 using namespace llvm;
 
@@ -533,7 +533,7 @@
   //    1 to set the highlight for snippet 2, segment 2 to set the highlight for
   //    snippet 3, and so on.
 
-  Optional<StringRef> Color;
+  std::optional<StringRef> Color;
   SmallVector<std::pair<unsigned, unsigned>, 2> HighlightedRanges;
   auto Highlight = [&](const std::string &Snippet, unsigned LC, unsigned RC) {
     if (getOptions().Debug)
@@ -559,7 +559,7 @@
     else if (CurSeg->Col == ExpansionCol)
       Color = "cyan";
     else
-      Color = None;
+      Color = std::nullopt;
 
     if (Color)
       Snippets[I + 1] = Highlight(Snippets[I + 1], CurSeg->Col,
diff --git a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.cpp b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
index 948414a..40d4359 100644
--- a/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cov/SourceCoverageViewText.cpp
@@ -12,10 +12,10 @@
 
 #include "SourceCoverageViewText.h"
 #include "CoverageReport.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/Format.h"
+#include <optional>
 
 using namespace llvm;
 
@@ -102,7 +102,7 @@
   auto *WrappedSegment = LCS.getWrappedSegment();
   CoverageSegmentArray Segments = LCS.getLineSegments();
 
-  Optional<raw_ostream::Colors> Highlight;
+  std::optional<raw_ostream::Colors> Highlight;
   SmallVector<std::pair<unsigned, unsigned>, 2> HighlightedRanges;
 
   // The first segment overlaps from a previous line, so we treat it specially.
@@ -127,7 +127,7 @@
     else if (Col == ExpansionCol)
       Highlight = raw_ostream::CYAN;
     else
-      Highlight = None;
+      Highlight = std::nullopt;
   }
 
   // Show the rest of the line.
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 6462017..9040237 100644
--- a/src/llvm-project/llvm/tools/llvm-cvtres/llvm-cvtres.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cvtres/llvm-cvtres.cpp
@@ -44,11 +44,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#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
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -60,9 +63,9 @@
 #undef OPTION
 };
 
-class CvtResOptTable : public opt::OptTable {
+class CvtResOptTable : public opt::GenericOptTable {
 public:
-  CvtResOptTable() : OptTable(InfoTable, true) {}
+  CvtResOptTable() : opt::GenericOptTable(InfoTable, true) {}
 };
 }
 
@@ -118,7 +121,7 @@
 
   CvtResOptTable T;
   unsigned MAI, MAC;
-  ArrayRef<const char *> ArgsArr = makeArrayRef(Argv + 1, Argc - 1);
+  ArrayRef<const char *> ArgsArr = ArrayRef(Argv + 1, Argc - 1);
   opt::InputArgList InputArgs = T.ParseArgs(ArgsArr, MAI, MAC);
 
   if (InputArgs.hasArg(OPT_HELP)) {
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 02f4c84..f35f626 100644
--- a/src/llvm-project/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cxxdump/llvm-cxxdump.cpp
@@ -234,8 +234,8 @@
     // Complete object locators in the MS-ABI start with '??_R4'
     else if (SymName.startswith("??_R4")) {
       CompleteObjectLocator COL;
-      COL.Data = makeArrayRef(
-          reinterpret_cast<const little32_t *>(SymContents.data()), 3);
+      COL.Data =
+          ArrayRef(reinterpret_cast<const little32_t *>(SymContents.data()), 3);
       StringRef *I = std::begin(COL.Symbols), *E = std::end(COL.Symbols);
       collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E);
       COLs[SymName] = COL;
@@ -243,8 +243,8 @@
     // Class hierarchy descriptors in the MS-ABI start with '??_R3'
     else if (SymName.startswith("??_R3")) {
       ClassHierarchyDescriptor CHD;
-      CHD.Data = makeArrayRef(
-          reinterpret_cast<const little32_t *>(SymContents.data()), 3);
+      CHD.Data =
+          ArrayRef(reinterpret_cast<const little32_t *>(SymContents.data()), 3);
       StringRef *I = std::begin(CHD.Symbols), *E = std::end(CHD.Symbols);
       collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E);
       CHDs[SymName] = CHD;
@@ -259,7 +259,7 @@
     // Base class descriptors in the MS-ABI start with '??_R1'
     else if (SymName.startswith("??_R1")) {
       BaseClassDescriptor BCD;
-      BCD.Data = makeArrayRef(
+      BCD.Data = ArrayRef(
           reinterpret_cast<const little32_t *>(SymContents.data()) + 1, 5);
       StringRef *I = std::begin(BCD.Symbols), *E = std::end(BCD.Symbols);
       collectRelocatedSymbols(Obj, Sec, SecAddress, SymAddress, SymSize, I, E);
@@ -499,7 +499,7 @@
 
 static void dumpArchive(const Archive *Arc) {
   Error Err = Error::success();
-  for (auto &ArcC : Arc->children(Err)) {
+  for (const auto &ArcC : Arc->children(Err)) {
     Expected<std::unique_ptr<Binary>> ChildOrErr = ArcC.getAsBinary();
     if (!ChildOrErr) {
       // Ignore non-object files.
diff --git a/src/llvm-project/llvm/tools/llvm-cxxfilt/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-cxxfilt/CMakeLists.txt
index 367744b..cbc4c2d 100644
--- a/src/llvm-project/llvm/tools/llvm-cxxfilt/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-cxxfilt/CMakeLists.txt
@@ -2,6 +2,7 @@
   Demangle
   Option
   Support
+  TargetParser
   )
 
 set(LLVM_TARGET_DEFINITIONS Opts.td)
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 1cea9e2..06f0a25 100644
--- a/src/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
+++ b/src/llvm-project/llvm/tools/llvm-cxxfilt/llvm-cxxfilt.cpp
@@ -32,11 +32,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr llvm::StringLiteral NAME##_init[] = VALUE;                  \
+  static constexpr llvm::ArrayRef<llvm::StringLiteral> NAME(                   \
+      NAME##_init, std::size(NAME##_init) - 1);
 #include "Opts.inc"
 #undef PREFIX
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -48,9 +51,11 @@
 #undef OPTION
 };
 
-class CxxfiltOptTable : public opt::OptTable {
+class CxxfiltOptTable : public opt::GenericOptTable {
 public:
-  CxxfiltOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  CxxfiltOptTable() : opt::GenericOptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 } // namespace
 
diff --git a/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt
new file mode 100644
index 0000000..b36f5d7
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/CMakeLists.txt
@@ -0,0 +1,19 @@
+set(LLVM_LINK_COMPONENTS
+  AllTargetsDescs
+  AllTargetsInfos
+  AllTargetsDisassemblers
+  BinaryFormat
+  DebugInfoLogicalView
+  DebugInfoCodeView
+  DebugInfoDWARF
+  DebugInfoPDB
+  MC
+  MCDisassembler
+  Object
+  Support
+  )
+
+add_llvm_tool(llvm-debuginfo-analyzer
+  llvm-debuginfo-analyzer.cpp
+  Options.cpp
+  )
diff --git a/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/Options.cpp b/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/Options.cpp
new file mode 100644
index 0000000..e5566b3
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/Options.cpp
@@ -0,0 +1,501 @@
+//===-- options.cpp - Command line options for llvm-debuginfo-analyzer----===//
+//
+// 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 handles the command line options for llvm-debuginfo-analyzer.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Options.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVSort.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+using namespace llvm::logicalview;
+using namespace llvm::logicalview::cmdline;
+
+/// @}
+/// Command line options.
+/// @{
+
+OffsetParser::OffsetParser(cl::Option &O) : parser<unsigned long long>(O) {}
+OffsetParser::~OffsetParser() = default;
+
+bool OffsetParser::parse(cl::Option &O, StringRef ArgName, StringRef Arg,
+                         unsigned long long &Val) {
+  char *End;
+  std::string Argument(Arg);
+  Val = strtoull(Argument.c_str(), &End, 0);
+  if (*End)
+    // Print an error message if unrecognized character.
+    return O.error("'" + Arg + "' unrecognized character.");
+  return false;
+}
+
+LVOptions cmdline::ReaderOptions;
+
+//===----------------------------------------------------------------------===//
+// Specific options
+//===----------------------------------------------------------------------===//
+cl::list<std::string>
+    cmdline::InputFilenames(cl::desc("<input object files or .dSYM bundles>"),
+                            cl::Positional, cl::ZeroOrMore);
+
+//===----------------------------------------------------------------------===//
+// '--attribute' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::AttributeCategory("Attribute Options",
+                               "These control extra attributes that are "
+                               "added when the element is printed.");
+
+// --attribute=<value>[,<value>,...]
+cl::list<LVAttributeKind> cmdline::AttributeOptions(
+    "attribute", cl::cat(AttributeCategory), cl::desc("Element attributes."),
+    cl::Hidden, cl::CommaSeparated,
+    values(clEnumValN(LVAttributeKind::All, "all", "Include all attributes."),
+           clEnumValN(LVAttributeKind::Argument, "argument",
+                      "Template parameters replaced by its arguments."),
+           clEnumValN(LVAttributeKind::Base, "base",
+                      "Base types (int, bool, etc.)."),
+           clEnumValN(LVAttributeKind::Coverage, "coverage",
+                      "Symbol location coverage."),
+           clEnumValN(LVAttributeKind::Directories, "directories",
+                      "Directories referenced in the debug information."),
+           clEnumValN(LVAttributeKind::Discarded, "discarded",
+                      "Discarded elements by the linker."),
+           clEnumValN(LVAttributeKind::Discriminator, "discriminator",
+                      "Discriminators for inlined function instances."),
+           clEnumValN(LVAttributeKind::Encoded, "encoded",
+                      "Template arguments encoded in the template name."),
+           clEnumValN(LVAttributeKind::Extended, "extended",
+                      "Advanced attributes alias."),
+           clEnumValN(LVAttributeKind::Filename, "filename",
+                      "Filename where the element is defined."),
+           clEnumValN(LVAttributeKind::Files, "files",
+                      "Files referenced in the debug information."),
+           clEnumValN(LVAttributeKind::Format, "format",
+                      "Object file format name."),
+           clEnumValN(LVAttributeKind::Gaps, "gaps",
+                      "Missing debug location (gaps)."),
+           clEnumValN(LVAttributeKind::Generated, "generated",
+                      "Compiler generated elements."),
+           clEnumValN(LVAttributeKind::Global, "global",
+                      "Element referenced across Compile Units."),
+           clEnumValN(LVAttributeKind::Inserted, "inserted",
+                      "Generated inlined abstract references."),
+           clEnumValN(LVAttributeKind::Level, "level",
+                      "Lexical scope level (File=0, Compile Unit=1)."),
+           clEnumValN(LVAttributeKind::Linkage, "linkage", "Linkage name."),
+           clEnumValN(LVAttributeKind::Local, "local",
+                      "Element referenced only in the Compile Unit."),
+           clEnumValN(LVAttributeKind::Location, "location",
+                      "Element debug location."),
+           clEnumValN(LVAttributeKind::Offset, "offset",
+                      "Debug information offset."),
+           clEnumValN(LVAttributeKind::Pathname, "pathname",
+                      "Pathname where the element is defined."),
+           clEnumValN(LVAttributeKind::Producer, "producer",
+                      "Toolchain identification name."),
+           clEnumValN(LVAttributeKind::Publics, "publics",
+                      "Function names that are public."),
+           clEnumValN(LVAttributeKind::Qualified, "qualified",
+                      "The element type include parents in its name."),
+           clEnumValN(LVAttributeKind::Qualifier, "qualifier",
+                      "Line qualifiers (Newstatement, BasicBlock, etc.)."),
+           clEnumValN(LVAttributeKind::Range, "range",
+                      "Debug location ranges."),
+           clEnumValN(LVAttributeKind::Reference, "reference",
+                      "Element declaration and definition references."),
+           clEnumValN(LVAttributeKind::Register, "register",
+                      "Processor register names."),
+           clEnumValN(LVAttributeKind::Standard, "standard",
+                      "Basic attributes alias."),
+           clEnumValN(LVAttributeKind::Subrange, "subrange",
+                      "Subrange encoding information for arrays."),
+           clEnumValN(LVAttributeKind::System, "system",
+                      "Display PDB's MS system elements."),
+           clEnumValN(LVAttributeKind::Typename, "typename",
+                      "Include Parameters in templates."),
+           clEnumValN(LVAttributeKind::Underlying, "underlying",
+                      "Underlying type for type definitions."),
+           clEnumValN(LVAttributeKind::Zero, "zero", "Zero line numbers.")));
+
+//===----------------------------------------------------------------------===//
+// '--compare' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::CompareCategory("Compare Options",
+                             "These control the view comparison.");
+
+// --compare-context
+static cl::opt<bool, true>
+    CompareContext("compare-context", cl::cat(CompareCategory),
+                   cl::desc("Add the view as compare context."), cl::Hidden,
+                   cl::ZeroOrMore, cl::location(ReaderOptions.Compare.Context),
+                   cl::init(false));
+
+// --compare=<value>[,<value>,...]
+cl::list<LVCompareKind> cmdline::CompareElements(
+    "compare", cl::cat(CompareCategory), cl::desc("Elements to compare."),
+    cl::Hidden, cl::CommaSeparated,
+    values(clEnumValN(LVCompareKind::All, "all", "Compare all elements."),
+           clEnumValN(LVCompareKind::Lines, "lines", "Lines."),
+           clEnumValN(LVCompareKind::Scopes, "scopes", "Scopes."),
+           clEnumValN(LVCompareKind::Symbols, "symbols", "Symbols."),
+           clEnumValN(LVCompareKind::Types, "types", "Types.")));
+
+//===----------------------------------------------------------------------===//
+// '--output' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::OutputCategory("Output Options",
+                            "These control the output generated.");
+
+// --output-file=<filename>
+cl::opt<std::string>
+    cmdline::OutputFilename("output-file", cl::cat(OutputCategory),
+                            cl::desc("Redirect output to the specified file."),
+                            cl::Hidden, cl::value_desc("filename"),
+                            cl::init("-"));
+
+// --output-folder=<path>
+static cl::opt<std::string, true>
+    OutputFolder("output-folder", cl::cat(OutputCategory),
+                 cl::desc("Folder name for view splitting."),
+                 cl::value_desc("pathname"), cl::Hidden, cl::ZeroOrMore,
+                 cl::location(ReaderOptions.Output.Folder));
+
+// --output-level=<level>
+static cl::opt<unsigned, true>
+    OutputLevel("output-level", cl::cat(OutputCategory),
+                cl::desc("Only print to a depth of N elements."),
+                cl::value_desc("N"), cl::Hidden, cl::ZeroOrMore,
+                cl::location(ReaderOptions.Output.Level), cl::init(-1U));
+
+// --ouput=<value>[,<value>,...]
+cl::list<LVOutputKind> cmdline::OutputOptions(
+    "output", cl::cat(OutputCategory), cl::desc("Outputs for view."),
+    cl::Hidden, cl::CommaSeparated,
+    values(clEnumValN(LVOutputKind::All, "all", "All outputs."),
+           clEnumValN(LVOutputKind::Split, "split",
+                      "Split the output by Compile Units."),
+           clEnumValN(LVOutputKind::Text, "text",
+                      "Use a free form text output."),
+           clEnumValN(LVOutputKind::Json, "json",
+                      "Use JSON as the output format.")));
+
+// --output-sort
+static cl::opt<LVSortMode, true> OutputSort(
+    "output-sort", cl::cat(OutputCategory),
+    cl::desc("Primary key when ordering logical view (default: line)."),
+    cl::Hidden, cl::ZeroOrMore,
+    values(clEnumValN(LVSortMode::Kind, "kind", "Sort by element kind."),
+           clEnumValN(LVSortMode::Line, "line", "Sort by element line number."),
+           clEnumValN(LVSortMode::Name, "name", "Sort by element name."),
+           clEnumValN(LVSortMode::Offset, "offset", "Sort by element offset.")),
+    cl::location(ReaderOptions.Output.SortMode), cl::init(LVSortMode::Line));
+
+//===----------------------------------------------------------------------===//
+// '--print' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::PrintCategory("Print Options",
+                           "These control which elements are printed.");
+
+// --print=<value>[,<value>,...]
+cl::list<LVPrintKind> cmdline::PrintOptions(
+    "print", cl::cat(PrintCategory), cl::desc("Element to print."),
+    cl::CommaSeparated,
+    values(clEnumValN(LVPrintKind::All, "all", "All elements."),
+           clEnumValN(LVPrintKind::Elements, "elements",
+                      "Instructions, lines, scopes, symbols and types."),
+           clEnumValN(LVPrintKind::Instructions, "instructions",
+                      "Assembler instructions."),
+           clEnumValN(LVPrintKind::Lines, "lines",
+                      "Lines referenced in the debug information."),
+           clEnumValN(LVPrintKind::Scopes, "scopes",
+                      "A lexical block (Function, Class, etc.)."),
+           clEnumValN(LVPrintKind::Sizes, "sizes",
+                      "Scope contributions to the debug information."),
+           clEnumValN(LVPrintKind::Summary, "summary",
+                      "Summary of elements missing/added/matched/printed."),
+           clEnumValN(LVPrintKind::Symbols, "symbols",
+                      "Symbols (Variable, Members, etc.)."),
+           clEnumValN(LVPrintKind::Types, "types",
+                      "Types (Pointer, Reference, etc.)."),
+           clEnumValN(LVPrintKind::Warnings, "warnings",
+                      "Warnings detected.")));
+
+//===----------------------------------------------------------------------===//
+// '--report' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::ReportCategory("Report Options",
+                            "These control how the elements are printed.");
+
+// --report=<value>[,<value>,...]
+cl::list<LVReportKind> cmdline::ReportOptions(
+    "report", cl::cat(ReportCategory),
+    cl::desc("Reports layout used for print, compare and select."), cl::Hidden,
+    cl::CommaSeparated,
+    values(clEnumValN(LVReportKind::All, "all", "Generate all reports."),
+           clEnumValN(LVReportKind::Children, "children",
+                      "Selected elements are displayed in a tree view "
+                      "(Include children)"),
+           clEnumValN(LVReportKind::List, "list",
+                      "Selected elements are displayed in a tabular format."),
+           clEnumValN(LVReportKind::Parents, "parents",
+                      "Selected elements are displayed in a tree view. "
+                      "(Include parents)"),
+           clEnumValN(LVReportKind::View, "view",
+                      "Selected elements are displayed in a tree view "
+                      "(Include parents and children.")));
+
+//===----------------------------------------------------------------------===//
+// '--select' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::SelectCategory("Select Options",
+                            "These control which elements are selected.");
+
+// --select-nocase
+static cl::opt<bool, true>
+    SelectIgnoreCase("select-nocase", cl::cat(SelectCategory),
+                     cl::desc("Ignore case distinctions when searching."),
+                     cl::Hidden, cl::ZeroOrMore,
+                     cl::location(ReaderOptions.Select.IgnoreCase),
+                     cl::init(false));
+
+// --select-regex
+static cl::opt<bool, true> SelectUseRegex(
+    "select-regex", cl::cat(SelectCategory),
+    cl::desc("Treat any <pattern> strings as regular expressions when "
+             "selecting instead of just as an exact string match."),
+    cl::Hidden, cl::ZeroOrMore, cl::location(ReaderOptions.Select.UseRegex),
+    cl::init(false));
+
+// --select=<pattern>
+cl::list<std::string> cmdline::SelectPatterns(
+    "select", cl::cat(SelectCategory),
+    cl::desc("Search elements matching the given pattern."), cl::Hidden,
+    cl::value_desc("pattern"), cl::CommaSeparated);
+
+// --select-offsets=<value>[,<value>,...]
+OffsetOptionList cmdline::SelectOffsets("select-offsets",
+                                        cl::cat(SelectCategory),
+                                        cl::desc("Offset element to print."),
+                                        cl::Hidden, cl::value_desc("offset"),
+                                        cl::CommaSeparated, cl::ZeroOrMore);
+
+// --select-elements=<value>[,<value>,...]
+cl::list<LVElementKind> cmdline::SelectElements(
+    "select-elements", cl::cat(SelectCategory),
+    cl::desc("Conditions to use when printing elements."), cl::Hidden,
+    cl::CommaSeparated,
+    values(clEnumValN(LVElementKind::Discarded, "Discarded",
+                      "Discarded elements by the linker."),
+           clEnumValN(LVElementKind::Global, "Global",
+                      "Element referenced across Compile Units."),
+           clEnumValN(LVElementKind::Optimized, "Optimized",
+                      "Generated inlined abstract references.")));
+
+// --select-lines=<value>[,<value>,...]
+cl::list<LVLineKind> cmdline::SelectLines(
+    "select-lines", cl::cat(SelectCategory),
+    cl::desc("Line kind to use when printing lines."), cl::Hidden,
+    cl::CommaSeparated,
+    values(
+        clEnumValN(LVLineKind::IsAlwaysStepInto, "AlwaysStepInto",
+                   "Always Step Into."),
+        clEnumValN(LVLineKind::IsBasicBlock, "BasicBlock", "Basic block."),
+        clEnumValN(LVLineKind::IsDiscriminator, "Discriminator",
+                   "Discriminator."),
+        clEnumValN(LVLineKind::IsEndSequence, "EndSequence", "End sequence."),
+        clEnumValN(LVLineKind::IsEpilogueBegin, "EpilogueBegin.",
+                   "Epilogue begin."),
+        clEnumValN(LVLineKind::IsLineDebug, "LineDebug", "Debug line."),
+        clEnumValN(LVLineKind::IsLineAssembler, "LineAssembler",
+                   "Assembler line."),
+        clEnumValN(LVLineKind::IsNeverStepInto, "NeverStepInto",
+                   "Never Step Into."),
+        clEnumValN(LVLineKind::IsNewStatement, "NewStatement",
+                   "New statement."),
+        clEnumValN(LVLineKind::IsPrologueEnd, "PrologueEnd", "Prologue end.")));
+
+// --select-scopes=<value>[,<value>,...]
+cl::list<LVScopeKind> cmdline::SelectScopes(
+    "select-scopes", cl::cat(SelectCategory),
+    cl::desc("Scope kind to use when printing scopes."), cl::Hidden,
+    cl::CommaSeparated,
+    values(
+        clEnumValN(LVScopeKind::IsAggregate, "Aggregate",
+                   "Class, Structure or Union."),
+        clEnumValN(LVScopeKind::IsArray, "Array", "Array."),
+        clEnumValN(LVScopeKind::IsBlock, "Block", "Lexical block."),
+        clEnumValN(LVScopeKind::IsCallSite, "CallSite", "Call site block."),
+        clEnumValN(LVScopeKind::IsCatchBlock, "CatchBlock",
+                   "Exception catch block."),
+        clEnumValN(LVScopeKind::IsClass, "Class", "Class."),
+        clEnumValN(LVScopeKind::IsCompileUnit, "CompileUnit", "Compile unit."),
+        clEnumValN(LVScopeKind::IsEntryPoint, "EntryPoint",
+                   "Function entry point."),
+        clEnumValN(LVScopeKind::IsEnumeration, "Enumeration", "Enumeration."),
+        clEnumValN(LVScopeKind::IsFunction, "Function", "Function."),
+        clEnumValN(LVScopeKind::IsFunctionType, "FunctionType",
+                   "Function type."),
+        clEnumValN(LVScopeKind::IsInlinedFunction, "InlinedFunction",
+                   "Inlined function."),
+        clEnumValN(LVScopeKind::IsLabel, "Label", "Label."),
+        clEnumValN(LVScopeKind::IsLexicalBlock, "LexicalBlock",
+                   "Lexical block."),
+        clEnumValN(LVScopeKind::IsNamespace, "Namespace", "Namespace."),
+        clEnumValN(LVScopeKind::IsRoot, "Root", "Root."),
+        clEnumValN(LVScopeKind::IsStructure, "Structure", "Structure."),
+        clEnumValN(LVScopeKind::IsSubprogram, "Subprogram", "Subprogram."),
+        clEnumValN(LVScopeKind::IsTemplate, "Template", "Template."),
+        clEnumValN(LVScopeKind::IsTemplateAlias, "TemplateAlias",
+                   "Template alias."),
+        clEnumValN(LVScopeKind::IsTemplatePack, "TemplatePack",
+                   "Template pack."),
+        clEnumValN(LVScopeKind::IsTryBlock, "TryBlock", "Exception try block."),
+        clEnumValN(LVScopeKind::IsUnion, "Union", "Union.")));
+
+// --select-symbols=<value>[,<value>,...]
+cl::list<LVSymbolKind> cmdline::SelectSymbols(
+    "select-symbols", cl::cat(SelectCategory),
+    cl::desc("Symbol kind to use when printing symbols."), cl::Hidden,
+    cl::CommaSeparated,
+    values(clEnumValN(LVSymbolKind::IsCallSiteParameter, "CallSiteParameter",
+                      "Call site parameter."),
+           clEnumValN(LVSymbolKind::IsConstant, "Constant", "Constant."),
+           clEnumValN(LVSymbolKind::IsInheritance, "Inheritance",
+                      "Inheritance."),
+           clEnumValN(LVSymbolKind::IsMember, "Member", "Member."),
+           clEnumValN(LVSymbolKind::IsParameter, "Parameter", "Parameter."),
+           clEnumValN(LVSymbolKind::IsUnspecified, "Unspecified",
+                      "Unspecified parameter."),
+           clEnumValN(LVSymbolKind::IsVariable, "Variable", "Variable.")));
+
+// --select-types=<value>[,<value>,...]
+cl::list<LVTypeKind> cmdline::SelectTypes(
+    "select-types", cl::cat(SelectCategory),
+    cl::desc("Type kind to use when printing types."), cl::Hidden,
+    cl::CommaSeparated,
+    values(
+        clEnumValN(LVTypeKind::IsBase, "Base", "Base Type (int, bool, etc.)."),
+        clEnumValN(LVTypeKind::IsConst, "Const", "Constant specifier."),
+        clEnumValN(LVTypeKind::IsEnumerator, "Enumerator", "Enumerator."),
+        clEnumValN(LVTypeKind::IsImport, "Import", "Import."),
+        clEnumValN(LVTypeKind::IsImportDeclaration, "ImportDeclaration",
+                   "Import declaration."),
+        clEnumValN(LVTypeKind::IsImportModule, "ImportModule",
+                   "Import module."),
+        clEnumValN(LVTypeKind::IsPointer, "Pointer", "Pointer."),
+        clEnumValN(LVTypeKind::IsPointerMember, "PointerMember",
+                   "Pointer to member."),
+        clEnumValN(LVTypeKind::IsReference, "Reference", "Reference type."),
+        clEnumValN(LVTypeKind::IsRestrict, "Restrict", "Restrict specifier."),
+        clEnumValN(LVTypeKind::IsRvalueReference, "RvalueReference",
+                   "Rvalue reference."),
+        clEnumValN(LVTypeKind::IsSubrange, "Subrange", "Array subrange."),
+        clEnumValN(LVTypeKind::IsTemplateParam, "TemplateParam",
+                   "Template Parameter."),
+        clEnumValN(LVTypeKind::IsTemplateTemplateParam, "TemplateTemplateParam",
+                   "Template template parameter."),
+        clEnumValN(LVTypeKind::IsTemplateTypeParam, "TemplateTypeParam",
+                   "Template type parameter."),
+        clEnumValN(LVTypeKind::IsTemplateValueParam, "TemplateValueParam",
+                   "Template value parameter."),
+        clEnumValN(LVTypeKind::IsTypedef, "Typedef", "Type definition."),
+        clEnumValN(LVTypeKind::IsUnspecified, "Unspecified",
+                   "Unspecified type."),
+        clEnumValN(LVTypeKind::IsVolatile, "Volatile", "Volatile specifier.")));
+
+//===----------------------------------------------------------------------===//
+// '--warning' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::WarningCategory("Warning Options",
+                             "These control the generated warnings.");
+
+// --warning=<value>[,<value>,...]
+cl::list<LVWarningKind> cmdline::WarningOptions(
+    "warning", cl::cat(WarningCategory), cl::desc("Warnings to generate."),
+    cl::Hidden, cl::CommaSeparated,
+    values(
+        clEnumValN(LVWarningKind::All, "all", "All warnings."),
+        clEnumValN(LVWarningKind::Coverages, "coverages",
+                   "Invalid symbol coverages values."),
+        clEnumValN(LVWarningKind::Lines, "lines", "Debug lines that are zero."),
+        clEnumValN(LVWarningKind::Locations, "locations",
+                   "Invalid symbol locations."),
+        clEnumValN(LVWarningKind::Ranges, "ranges", "Invalid code ranges.")));
+
+//===----------------------------------------------------------------------===//
+// '--internal' options
+//===----------------------------------------------------------------------===//
+cl::OptionCategory
+    cmdline::InternalCategory("Internal Options",
+                              "Internal traces and extra debugging code.");
+
+// --internal=<value>[,<value>,...]
+cl::list<LVInternalKind> cmdline::InternalOptions(
+    "internal", cl::cat(InternalCategory), cl::desc("Traces to enable."),
+    cl::Hidden, cl::CommaSeparated,
+    values(
+        clEnumValN(LVInternalKind::All, "all", "Enable all traces."),
+        clEnumValN(LVInternalKind::Cmdline, "cmdline", "Print command line."),
+        clEnumValN(LVInternalKind::ID, "id", "Print unique element ID"),
+        clEnumValN(LVInternalKind::Integrity, "integrity",
+                   "Check elements integrity."),
+        clEnumValN(LVInternalKind::None, "none", "Ignore element line number."),
+        clEnumValN(LVInternalKind::Tag, "tag", "Debug information tags.")));
+
+/// @}
+
+// Copy local options into a globally accessible data structure.
+void llvm::logicalview::cmdline::propagateOptions() {
+  // Traverse list of options and update the given set (Using case and Regex).
+  auto UpdatePattern = [&](auto &List, auto &Set, bool IgnoreCase,
+                           bool UseRegex) {
+    if (!List.empty())
+      for (std::string &Pattern : List)
+        Set.insert((IgnoreCase && !UseRegex) ? StringRef(Pattern).lower()
+                                             : Pattern);
+  };
+
+  // Handle --select.
+  UpdatePattern(SelectPatterns, ReaderOptions.Select.Generic,
+                ReaderOptions.Select.IgnoreCase, ReaderOptions.Select.UseRegex);
+
+  // Traverse list of options and update the given set.
+  auto UpdateSet = [&](auto &List, auto &Set) {
+    std::copy(List.begin(), List.end(), std::inserter(Set, Set.begin()));
+  };
+
+  // Handle options sets.
+  UpdateSet(AttributeOptions, ReaderOptions.Attribute.Kinds);
+  UpdateSet(PrintOptions, ReaderOptions.Print.Kinds);
+  UpdateSet(OutputOptions, ReaderOptions.Output.Kinds);
+  UpdateSet(ReportOptions, ReaderOptions.Report.Kinds);
+  UpdateSet(WarningOptions, ReaderOptions.Warning.Kinds);
+  UpdateSet(InternalOptions, ReaderOptions.Internal.Kinds);
+
+  UpdateSet(SelectElements, ReaderOptions.Select.Elements);
+  UpdateSet(SelectLines, ReaderOptions.Select.Lines);
+  UpdateSet(SelectScopes, ReaderOptions.Select.Scopes);
+  UpdateSet(SelectSymbols, ReaderOptions.Select.Symbols);
+  UpdateSet(SelectTypes, ReaderOptions.Select.Types);
+  UpdateSet(SelectOffsets, ReaderOptions.Select.Offsets);
+  UpdateSet(CompareElements, ReaderOptions.Compare.Elements);
+
+  // Resolve any options dependencies (ie. --print=all should set other
+  // print options, etc.).
+  ReaderOptions.resolveDependencies();
+}
diff --git a/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/Options.h b/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/Options.h
new file mode 100644
index 0000000..7f30141
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/Options.h
@@ -0,0 +1,81 @@
+//===-- Options.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 defines command line options used by llvm-debuginfo-analyzer.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef OPTIONS_H
+#define OPTIONS_H
+
+#include "llvm/DebugInfo/LogicalView/Core/LVLine.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVScope.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVType.h"
+#include "llvm/Support/CommandLine.h"
+
+namespace llvm {
+namespace logicalview {
+namespace cmdline {
+
+class OffsetParser final : public llvm::cl::parser<unsigned long long> {
+public:
+  OffsetParser(llvm::cl::Option &O);
+  ~OffsetParser() override;
+
+  // Parse an argument representing an offset. Return true on error.
+  // If the prefix is 0, the base is octal, if the prefix is 0x or 0X, the
+  // base is hexadecimal, otherwise the base is decimal.
+  bool parse(llvm::cl::Option &O, StringRef ArgName, StringRef ArgValue,
+             unsigned long long &Val);
+};
+
+typedef llvm::cl::list<unsigned long long, bool, OffsetParser> OffsetOptionList;
+
+extern llvm::cl::OptionCategory AttributeCategory;
+extern llvm::cl::OptionCategory CompareCategory;
+extern llvm::cl::OptionCategory OutputCategory;
+extern llvm::cl::OptionCategory PrintCategory;
+extern llvm::cl::OptionCategory ReportCategory;
+extern llvm::cl::OptionCategory SelectCategory;
+extern llvm::cl::OptionCategory WarningCategory;
+extern llvm::cl::OptionCategory InternalCategory;
+
+extern llvm::cl::list<std::string> InputFilenames;
+extern llvm::cl::opt<std::string> OutputFilename;
+
+extern llvm::cl::list<std::string> SelectPatterns;
+
+extern llvm::cl::list<LVElementKind> SelectElements;
+extern llvm::cl::list<LVLineKind> SelectLines;
+extern llvm::cl::list<LVScopeKind> SelectScopes;
+extern llvm::cl::list<LVSymbolKind> SelectSymbols;
+extern llvm::cl::list<LVTypeKind> SelectTypes;
+extern OffsetOptionList SelectOffsets;
+
+extern llvm::cl::list<LVAttributeKind> AttributeOptions;
+extern llvm::cl::list<LVOutputKind> OutputOptions;
+extern llvm::cl::list<LVPrintKind> PrintOptions;
+extern llvm::cl::list<LVWarningKind> WarningOptions;
+extern llvm::cl::list<LVInternalKind> InternalOptions;
+
+extern llvm::cl::list<LVCompareKind> CompareElements;
+extern llvm::cl::list<LVReportKind> ReportOptions;
+
+extern LVOptions ReaderOptions;
+
+// Perform any additional post parse command line actions. Propagate the
+// values captured by the command line parser, into the generic reader.
+void propagateOptions();
+
+} // namespace cmdline
+} // namespace logicalview
+} // namespace llvm
+
+#endif // OPTIONS_H
diff --git a/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp b/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp
new file mode 100644
index 0000000..fb82ec0
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-debuginfo-analyzer/llvm-debuginfo-analyzer.cpp
@@ -0,0 +1,141 @@
+//===-- llvm-debuginfo-analyzer.cpp - LLVM Debug info analysis utility ---===//
+//
+// 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 program is a utility that displays the logical view for the debug
+// information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Options.h"
+#include "llvm/DebugInfo/LogicalView/Core/LVOptions.h"
+#include "llvm/DebugInfo/LogicalView/LVReaderHandler.h"
+#include "llvm/Support/COM.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/WithColor.h"
+
+using namespace llvm;
+using namespace logicalview;
+using namespace cmdline;
+
+/// Create formatted StringError object.
+static StringRef ToolName = "llvm-debuginfo-analyzer";
+template <typename... Ts>
+static void error(std::error_code EC, char const *Fmt, const Ts &...Vals) {
+  if (!EC)
+    return;
+  std::string Buffer;
+  raw_string_ostream Stream(Buffer);
+  Stream << format(Fmt, Vals...);
+  WithColor::error(errs(), ToolName) << Stream.str() << "\n";
+  exit(1);
+}
+
+static void error(Error EC) {
+  if (!EC)
+    return;
+  handleAllErrors(std::move(EC), [&](const ErrorInfoBase &EI) {
+    errs() << "\n";
+    WithColor::error(errs(), ToolName) << EI.message() << ".\n";
+    exit(1);
+  });
+}
+
+/// If the input path is a .dSYM bundle (as created by the dsymutil tool),
+/// replace it with individual entries for each of the object files inside the
+/// bundle otherwise return the input path.
+static std::vector<std::string> expandBundle(const std::string &InputPath) {
+  std::vector<std::string> BundlePaths;
+  SmallString<256> BundlePath(InputPath);
+  // Normalize input path. This is necessary to accept `bundle.dSYM/`.
+  sys::path::remove_dots(BundlePath);
+  // Manually open up the bundle to avoid introducing additional dependencies.
+  if (sys::fs::is_directory(BundlePath) &&
+      sys::path::extension(BundlePath) == ".dSYM") {
+    std::error_code EC;
+    sys::path::append(BundlePath, "Contents", "Resources", "DWARF");
+    for (sys::fs::directory_iterator Dir(BundlePath, EC), DirEnd;
+         Dir != DirEnd && !EC; Dir.increment(EC)) {
+      const std::string &Path = Dir->path();
+      sys::fs::file_status Status;
+      EC = sys::fs::status(Path, Status);
+      error(EC, "%s", Path.c_str());
+      switch (Status.type()) {
+      case sys::fs::file_type::regular_file:
+      case sys::fs::file_type::symlink_file:
+      case sys::fs::file_type::type_unknown:
+        BundlePaths.push_back(Path);
+        break;
+      default: /*ignore*/;
+      }
+    }
+  }
+  if (BundlePaths.empty())
+    BundlePaths.push_back(InputPath);
+  return BundlePaths;
+}
+
+int main(int argc, char **argv) {
+  InitLLVM X(argc, argv);
+
+  // Initialize targets and assembly printers/parsers.
+  llvm::InitializeAllTargetInfos();
+  llvm::InitializeAllTargetMCs();
+  InitializeAllDisassemblers();
+
+  llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
+
+  cl::extrahelp HelpResponse(
+      "\nPass @FILE as argument to read options from FILE.\n");
+
+  cl::HideUnrelatedOptions(
+      {&AttributeCategory, &CompareCategory, &InternalCategory, &OutputCategory,
+       &PrintCategory, &ReportCategory, &SelectCategory, &WarningCategory});
+  cl::ParseCommandLineOptions(argc, argv,
+                              "Printing a logical representation of low-level "
+                              "debug information.\n");
+  cl::PrintOptionValues();
+
+  std::error_code EC;
+  ToolOutputFile OutputFile(OutputFilename, EC, sys::fs::OF_None);
+  error(EC, "Unable to open output file %s", OutputFilename.c_str());
+  // Don't remove output file if we exit with an error.
+  OutputFile.keep();
+
+  // Defaults to a.out if no filenames specified.
+  if (InputFilenames.empty())
+    InputFilenames.push_back("a.out");
+
+  // Expand any .dSYM bundles to the individual object files contained therein.
+  std::vector<std::string> Objects;
+  for (const std::string &Filename : InputFilenames) {
+    std::vector<std::string> Objs = expandBundle(Filename);
+    Objects.insert(Objects.end(), Objs.begin(), Objs.end());
+  }
+
+  propagateOptions();
+  ScopedPrinter W(OutputFile.os());
+  LVReaderHandler ReaderHandler(Objects, W, ReaderOptions);
+
+  // Print the command line.
+  if (options().getInternalCmdline()) {
+    raw_ostream &Stream = W.getOStream();
+    Stream << "\nCommand line:\n";
+    for (int Index = 0; Index < argc; ++Index)
+      Stream << "  " << argv[Index] << "\n";
+    Stream << "\n";
+  }
+
+  // Create readers and perform requested tasks on them.
+  if (Error Err = ReaderHandler.process())
+    error(std::move(Err));
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/llvm-project/llvm/tools/llvm-debuginfod-find/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-debuginfod-find/CMakeLists.txt
index a045560..b98c431 100644
--- a/src/llvm-project/llvm/tools/llvm-debuginfod-find/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-debuginfod-find/CMakeLists.txt
@@ -1,6 +1,6 @@
 set(LLVM_LINK_COMPONENTS
+  Object
   Support
-  Symbolize
   )
 add_llvm_tool(llvm-debuginfod-find
   llvm-debuginfod-find.cpp
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 373353c..40350a0 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
@@ -15,7 +15,7 @@
 ///
 //===----------------------------------------------------------------------===//
 
-#include "llvm/DebugInfo/Symbolize/DIFetcher.h"
+#include "llvm/Debuginfod/BuildIDFetcher.h"
 #include "llvm/Debuginfod/Debuginfod.h"
 #include "llvm/Debuginfod/HTTPClient.h"
 #include "llvm/Support/CommandLine.h"
@@ -67,7 +67,7 @@
 
 ExitOnError ExitOnErr;
 
-static std::string fetchDebugInfo(ArrayRef<uint8_t> BuildID);
+static std::string fetchDebugInfo(object::BuildIDRef BuildID);
 
 int main(int argc, char **argv) {
   InitLLVM X(argc, argv);
@@ -92,7 +92,7 @@
     errs() << "Build ID " << InputBuildID << " is not a hex string.\n";
     exit(1);
   }
-  BuildID ID(IDString.begin(), IDString.end());
+  object::BuildID ID(IDString.begin(), IDString.end());
 
   std::string Path;
   if (FetchSource != "")
@@ -116,12 +116,12 @@
     outs() << Path << "\n";
 }
 
-// Find a debug binary in local build ID directories and via debuginfod.
-std::string fetchDebugInfo(ArrayRef<uint8_t> BuildID) {
-  if (!DebugFileDirectory.empty()) {
-    symbolize::LocalDIFetcher Fetcher(DebugFileDirectory);
-    if (Optional<std::string> LocalPath = Fetcher.fetchBuildID(BuildID))
-      return *LocalPath;
-  }
-  return ExitOnErr(getCachedOrDownloadDebuginfo(BuildID));
+// Find a debug file in local build ID directories and via debuginfod.
+std::string fetchDebugInfo(object::BuildIDRef BuildID) {
+  if (std::optional<std::string> Path =
+          DebuginfodFetcher(DebugFileDirectory).fetch(BuildID))
+    return *Path;
+  errs() << "Build ID " << llvm::toHex(BuildID, /*Lowercase=*/true)
+         << " could not be found.";
+  exit(1);
 }
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 4bdefcd..6573bf0 100644
--- a/src/llvm-project/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp
+++ b/src/llvm-project/llvm/tools/llvm-diff/lib/DifferenceEngine.cpp
@@ -17,6 +17,7 @@
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringSet.h"
+#include "llvm/IR/BasicBlock.h"
 #include "llvm/IR/CFG.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/Function.h"
@@ -119,14 +120,99 @@
   const Value *SavedLHS;
   const Value *SavedRHS;
 
-  /// The current mapping from old local values to new local values.
+  // The current mapping from old local values to new local values.
   DenseMap<const Value *, const Value *> Values;
 
-  /// The current mapping from old blocks to new blocks.
+  // The current mapping from old blocks to new blocks.
   DenseMap<const BasicBlock *, const BasicBlock *> Blocks;
 
+  // The tentative mapping from old local values while comparing a pair of
+  // basic blocks. Once the pair has been processed, the tentative mapping is
+  // committed to the Values map.
   DenseSet<std::pair<const Value *, const Value *>> TentativeValues;
 
+  // Equivalence Assumptions
+  //
+  // For basic blocks in loops, some values in phi nodes may depend on
+  // values from not yet processed basic blocks in the loop. When encountering
+  // such values, we optimistically asssume their equivalence and store this
+  // assumption in a BlockDiffCandidate for the pair of compared BBs.
+  //
+  // Once we have diffed all BBs, for every BlockDiffCandidate, we check all
+  // stored assumptions using the Values map that stores proven equivalences
+  // between the old and new values, and report a diff if an assumption cannot
+  // be proven to be true.
+  //
+  // Note that after having made an assumption, all further determined
+  // equivalences implicitly depend on that assumption. These will not be
+  // reverted or reported if the assumption proves to be false, because these
+  // are considered indirect diffs caused by earlier direct diffs.
+  //
+  // We aim to avoid false negatives in llvm-diff, that is, ensure that
+  // whenever no diff is reported, the functions are indeed equal. If
+  // assumptions were made, this is not entirely clear, because in principle we
+  // could end up with a circular proof where the proof of equivalence of two
+  // nodes is depending on the assumption of their equivalence.
+  //
+  // To see that assumptions do not add false negatives, note that if we do not
+  // report a diff, this means that there is an equivalence mapping between old
+  // and new values that is consistent with all assumptions made. The circular
+  // dependency that exists on an IR value level does not exist at run time,
+  // because the values selected by the phi nodes must always already have been
+  // computed. Hence, we can prove equivalence of the old and new functions by
+  // considering step-wise parallel execution, and incrementally proving
+  // equivalence of every new computed value. Another way to think about it is
+  // to imagine cloning the loop BBs for every iteration, turning the loops
+  // into (possibly infinite) DAGs, and proving equivalence by induction on the
+  // iteration, using the computed value mapping.
+
+  // The class BlockDiffCandidate stores pairs which either have already been
+  // proven to differ, or pairs whose equivalence depends on assumptions to be
+  // verified later.
+  struct BlockDiffCandidate {
+    const BasicBlock *LBB;
+    const BasicBlock *RBB;
+    // Maps old values to assumed-to-be-equivalent new values
+    SmallDenseMap<const Value *, const Value *> EquivalenceAssumptions;
+    // If set, we already know the blocks differ.
+    bool KnownToDiffer;
+  };
+
+  // List of block diff candidates in the order found by processing.
+  // We generate reports in this order.
+  // For every LBB, there may only be one corresponding RBB.
+  SmallVector<BlockDiffCandidate> BlockDiffCandidates;
+  // Maps LBB to the index of its BlockDiffCandidate, if existing.
+  DenseMap<const BasicBlock *, uint64_t> BlockDiffCandidateIndices;
+
+  // Note: Every LBB must always be queried together with the same RBB.
+  // The returned reference is not permanently valid and should not be stored.
+  BlockDiffCandidate &getOrCreateBlockDiffCandidate(const BasicBlock *LBB,
+                                                    const BasicBlock *RBB) {
+    auto It = BlockDiffCandidateIndices.find(LBB);
+    // Check if LBB already has a diff candidate
+    if (It == BlockDiffCandidateIndices.end()) {
+      // Add new one
+      BlockDiffCandidateIndices[LBB] = BlockDiffCandidates.size();
+      BlockDiffCandidates.push_back(
+          {LBB, RBB, SmallDenseMap<const Value *, const Value *>(), false});
+      return BlockDiffCandidates.back();
+    }
+    // Use existing one
+    BlockDiffCandidate &Result = BlockDiffCandidates[It->second];
+    assert(Result.RBB == RBB && "Inconsistent basic block pairing!");
+    return Result;
+  }
+
+  // Optionally passed to equivalence checker functions, so these can add
+  // assumptions in BlockDiffCandidates. Its presence controls whether
+  // assumptions are generated.
+  struct AssumptionContext {
+    // The two basic blocks that need the two compared values to be equivalent.
+    const BasicBlock *LBB;
+    const BasicBlock *RBB;
+  };
+
   unsigned getUnprocPredCount(const BasicBlock *Block) const {
     unsigned Count = 0;
     for (const_pred_iterator I = pred_begin(Block), E = pred_end(Block); I != E;
@@ -180,7 +266,7 @@
   void unify(const Instruction *L, const Instruction *R) {
     DifferenceEngine::Context C(Engine, L, R);
 
-    bool Result = diff(L, R, true, true);
+    bool Result = diff(L, R, true, true, true);
     assert(!Result && "structural differences second time around?");
     (void) Result;
     if (!L->use_empty())
@@ -194,6 +280,26 @@
     }
   }
 
+  void checkAndReportDiffCandidates() {
+    for (BlockDiffCandidate &BDC : BlockDiffCandidates) {
+
+      // Check assumptions
+      for (const auto &[L, R] : BDC.EquivalenceAssumptions) {
+        auto It = Values.find(L);
+        if (It == Values.end() || It->second != R) {
+          BDC.KnownToDiffer = true;
+          break;
+        }
+      }
+
+      // Run block diff if the BBs differ
+      if (BDC.KnownToDiffer) {
+        DifferenceEngine::Context C(Engine, BDC.LBB, BDC.RBB);
+        runBlockDiff(BDC.LBB->begin(), BDC.RBB->begin());
+      }
+    }
+  }
+
   void diff(const BasicBlock *L, const BasicBlock *R) {
     DifferenceEngine::Context C(Engine, L, R);
 
@@ -206,9 +312,14 @@
 
       // If the instructions differ, start the more sophisticated diff
       // algorithm at the start of the block.
-      if (diff(LeftI, RightI, false, false)) {
+      if (diff(LeftI, RightI, false, false, true)) {
         TentativeValues.clear();
-        return runBlockDiff(L->begin(), R->begin());
+        // Register (L, R) as diffing pair. Note that we could directly emit a
+        // block diff here, but this way we ensure all diffs are emitted in one
+        // consistent order, independent of whether the diffs were detected
+        // immediately or via invalid assumptions.
+        getOrCreateBlockDiffCandidate(L, R).KnownToDiffer = true;
+        return;
       }
 
       // Otherwise, tentatively unify them.
@@ -232,7 +343,9 @@
 
   bool diffCallSites(const CallBase &L, const CallBase &R, bool Complain) {
     // FIXME: call attributes
-    if (!equivalentAsOperands(L.getCalledOperand(), R.getCalledOperand())) {
+    AssumptionContext AC = {L.getParent(), R.getParent()};
+    if (!equivalentAsOperands(L.getCalledOperand(), R.getCalledOperand(),
+                              &AC)) {
       if (Complain) Engine.log("called functions differ");
       return true;
     }
@@ -241,7 +354,7 @@
       return true;
     }
     for (unsigned I = 0, E = L.arg_size(); I != E; ++I)
-      if (!equivalentAsOperands(L.getArgOperand(I), R.getArgOperand(I))) {
+      if (!equivalentAsOperands(L.getArgOperand(I), R.getArgOperand(I), &AC)) {
         if (Complain)
           Engine.logf("arguments %l and %r differ")
               << L.getArgOperand(I) << R.getArgOperand(I);
@@ -250,9 +363,15 @@
     return false;
   }
 
+  // If AllowAssumptions is enabled, whenever we encounter a pair of values
+  // that we cannot prove to be equivalent, we assume equivalence and store that
+  // assumption to be checked later in BlockDiffCandidates.
   bool diff(const Instruction *L, const Instruction *R, bool Complain,
-            bool TryUnify) {
+            bool TryUnify, bool AllowAssumptions) {
     // FIXME: metadata (if Complain is set)
+    AssumptionContext ACValue = {L->getParent(), R->getParent()};
+    // nullptr AssumptionContext disables assumption generation.
+    const AssumptionContext *AC = AllowAssumptions ? &ACValue : nullptr;
 
     // Different opcodes always imply different operations.
     if (L->getOpcode() != R->getOpcode()) {
@@ -291,7 +410,7 @@
           tryUnify(LI.getIncomingBlock(I), RI.getIncomingBlock(I));
 
         if (!equivalentAsOperands(LI.getIncomingValue(I),
-                                  RI.getIncomingValue(I))) {
+                                  RI.getIncomingValue(I), AC)) {
           if (Complain)
             Engine.log("PHI node incoming values differ");
           return true;
@@ -343,7 +462,7 @@
       }
 
       if (LI->isConditional()) {
-        if (!equivalentAsOperands(LI->getCondition(), RI->getCondition())) {
+        if (!equivalentAsOperands(LI->getCondition(), RI->getCondition(), AC)) {
           if (Complain) Engine.log("branch conditions differ");
           return true;
         }
@@ -360,7 +479,7 @@
         return true;
       }
 
-      if (!equivalentAsOperands(LI->getAddress(), RI->getAddress())) {
+      if (!equivalentAsOperands(LI->getAddress(), RI->getAddress(), AC)) {
         if (Complain) Engine.log("indirectbr addresses differ");
         return true;
       }
@@ -375,7 +494,7 @@
     } else if (isa<SwitchInst>(L)) {
       const SwitchInst *LI = cast<SwitchInst>(L);
       const SwitchInst *RI = cast<SwitchInst>(R);
-      if (!equivalentAsOperands(LI->getCondition(), RI->getCondition())) {
+      if (!equivalentAsOperands(LI->getCondition(), RI->getCondition(), AC)) {
         if (Complain) Engine.log("switch conditions differ");
         return true;
       }
@@ -421,7 +540,7 @@
 
     for (unsigned I = 0, E = L->getNumOperands(); I != E; ++I) {
       Value *LO = L->getOperand(I), *RO = R->getOperand(I);
-      if (!equivalentAsOperands(LO, RO)) {
+      if (!equivalentAsOperands(LO, RO, AC)) {
         if (Complain) Engine.logf("operands %l and %r differ") << LO << RO;
         return true;
       }
@@ -431,7 +550,8 @@
   }
 
 public:
-  bool equivalentAsOperands(const Constant *L, const Constant *R) {
+  bool equivalentAsOperands(const Constant *L, const Constant *R,
+                            const AssumptionContext *AC) {
     // Use equality as a preliminary filter.
     if (L == R)
       return true;
@@ -446,8 +566,8 @@
 
     // Compare constant expressions structurally.
     if (isa<ConstantExpr>(L))
-      return equivalentAsOperands(cast<ConstantExpr>(L),
-                                  cast<ConstantExpr>(R));
+      return equivalentAsOperands(cast<ConstantExpr>(L), cast<ConstantExpr>(R),
+                                  AC);
 
     // Constants of the "same type" don't always actually have the same
     // type; I don't know why.  Just white-list them.
@@ -467,7 +587,7 @@
       if (CVL->getType()->getNumElements() != CVR->getType()->getNumElements())
         return false;
       for (unsigned i = 0; i < CVL->getType()->getNumElements(); i++) {
-        if (!equivalentAsOperands(CVL->getOperand(i), CVR->getOperand(i)))
+        if (!equivalentAsOperands(CVL->getOperand(i), CVR->getOperand(i), AC))
           return false;
       }
       return true;
@@ -484,7 +604,7 @@
 
       for (unsigned I = 0; I < CAL->getType()->getNumElements(); ++I) {
         if (!equivalentAsOperands(CAL->getAggregateElement(I),
-                                  CAR->getAggregateElement(I)))
+                                  CAR->getAggregateElement(I), AC))
           return false;
       }
 
@@ -520,7 +640,7 @@
           continue;
         }
 
-        if (!equivalentAsOperands(LAgg, RAgg)) {
+        if (!equivalentAsOperands(LAgg, RAgg, AC)) {
           return false;
         }
       }
@@ -531,7 +651,8 @@
     return false;
   }
 
-  bool equivalentAsOperands(const ConstantExpr *L, const ConstantExpr *R) {
+  bool equivalentAsOperands(const ConstantExpr *L, const ConstantExpr *R,
+                            const AssumptionContext *AC) {
     if (L == R)
       return true;
 
@@ -570,14 +691,25 @@
         continue;
       }
 
-      if (!equivalentAsOperands(LOp, ROp))
+      if (!equivalentAsOperands(LOp, ROp, AC))
         return false;
     }
 
     return true;
   }
 
-  bool equivalentAsOperands(const Value *L, const Value *R) {
+  // There are cases where we cannot determine whether two values are
+  // equivalent, because it depends on not yet processed basic blocks -- see the
+  // documentation on assumptions.
+  //
+  // AC is the context in which we are currently performing a diff.
+  // When we encounter a pair of values for which we can neither prove
+  // equivalence nor the opposite, we do the following:
+  //  * If AC is nullptr, we treat the pair as non-equivalent.
+  //  * If AC is set, we add an assumption for the basic blocks given by AC,
+  //    and treat the pair as equivalent. The assumption is checked later.
+  bool equivalentAsOperands(const Value *L, const Value *R,
+                            const AssumptionContext *AC) {
     // Fall out if the values have different kind.
     // This possibly shouldn't take priority over oracles.
     if (L->getValueID() != R->getValueID())
@@ -587,10 +719,38 @@
     //                  InlineAsm, MDNode, MDString, PseudoSourceValue
 
     if (isa<Constant>(L))
-      return equivalentAsOperands(cast<Constant>(L), cast<Constant>(R));
+      return equivalentAsOperands(cast<Constant>(L), cast<Constant>(R), AC);
 
-    if (isa<Instruction>(L))
-      return Values[L] == R || TentativeValues.count(std::make_pair(L, R));
+    if (isa<Instruction>(L)) {
+      auto It = Values.find(L);
+      if (It != Values.end())
+        return It->second == R;
+
+      if (TentativeValues.count(std::make_pair(L, R)))
+        return true;
+
+      // L and R might be equivalent, this could depend on not yet processed
+      // basic blocks, so we cannot decide here.
+      if (AC) {
+        // Add an assumption, unless there is a conflict with an existing one
+        BlockDiffCandidate &BDC =
+            getOrCreateBlockDiffCandidate(AC->LBB, AC->RBB);
+        auto InsertionResult = BDC.EquivalenceAssumptions.insert({L, R});
+        if (!InsertionResult.second && InsertionResult.first->second != R) {
+          // We already have a conflicting equivalence assumption for L, so at
+          // least one must be wrong, and we know that there is a diff.
+          BDC.KnownToDiffer = true;
+          BDC.EquivalenceAssumptions.clear();
+          return false;
+        }
+        // Optimistically assume equivalence, and check later once all BBs
+        // have been processed.
+        return true;
+      }
+
+      // Assumptions disabled, so pessimistically assume non-equivalence.
+      return false;
+    }
 
     if (isa<Argument>(L))
       return Values[L] == R;
@@ -613,6 +773,8 @@
         Queue(QueueSorter(*this_())) {}
 
   void diff(const Function *L, const Function *R) {
+    assert(Values.empty() && "Multiple diffs per engine are not supported!");
+
     if (L->arg_size() != R->arg_size())
       Engine.log("different argument counts");
 
@@ -624,6 +786,7 @@
 
     tryUnify(&*L->begin(), &*R->begin());
     processQueue();
+    checkAndReportDiffCandidates();
   }
 };
 
@@ -636,7 +799,7 @@
 
 bool FunctionDifferenceEngine::matchForBlockDiff(const Instruction *L,
                                                  const Instruction *R) {
-  return !diff(L, R, false, false);
+  return !diff(L, R, false, false, false);
 }
 
 void FunctionDifferenceEngine::runBlockDiff(BasicBlock::const_iterator LStart,
@@ -764,7 +927,7 @@
     const CallInst *LCall = cast<CallInst>(&*I);
     const InvokeInst *RInvoke = cast<InvokeInst>(RTerm);
     if (!equivalentAsOperands(LCall->getCalledOperand(),
-                              RInvoke->getCalledOperand()))
+                              RInvoke->getCalledOperand(), nullptr))
       return;
     if (!LCall->use_empty())
       Values[LCall] = RInvoke;
@@ -778,7 +941,7 @@
     const CallInst *RCall = cast<CallInst>(I);
     const InvokeInst *LInvoke = cast<InvokeInst>(LTerm);
     if (!equivalentAsOperands(LInvoke->getCalledOperand(),
-                              RCall->getCalledOperand()))
+                              RCall->getCalledOperand(), nullptr))
       return;
     if (!LInvoke->use_empty())
       Values[LInvoke] = RCall;
@@ -867,7 +1030,8 @@
     if (GVL->hasLocalLinkage() && GVL->hasUniqueInitializer() &&
         GVR->hasLocalLinkage() && GVR->hasUniqueInitializer())
       return FunctionDifferenceEngine(*this, GVL, GVR)
-          .equivalentAsOperands(GVL->getInitializer(), GVR->getInitializer());
+          .equivalentAsOperands(GVL->getInitializer(), GVR->getInitializer(),
+                                nullptr);
   }
 
   return L->getName() == R->getName();
diff --git a/src/llvm-project/llvm/tools/llvm-driver/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-driver/CMakeLists.txt
index 148e54b..e709cd7 100644
--- a/src/llvm-project/llvm/tools/llvm-driver/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-driver/CMakeLists.txt
@@ -5,15 +5,17 @@
 
 foreach(tool ${LLVM_DRIVER_TOOLS})
   string(REPLACE "-" "_" tool_entry ${tool})
-  string(REPLACE "llvm-" "" tool ${tool})
-  set(def_decl "${def_decl}LLVM_DRIVER_TOOL(\"${tool}\", ${tool_entry})\n")
+  get_property(tool_aliases GLOBAL PROPERTY LLVM_DRIVER_TOOL_ALIASES_${tool})
+  foreach(alias ${tool_aliases})
+    set_property(GLOBAL APPEND PROPERTY LLVM_DRIVER_TOOL_SYMLINKS ${alias})
+    string(REPLACE "llvm-" "" alias ${alias})
+    set(def_decl "${def_decl}LLVM_DRIVER_TOOL(\"${alias}\", ${tool_entry})\n")
+  endforeach()
 endforeach()
 
-get_property(LLVM_EXTRA_DRIVER_ENTRIES GLOBAL PROPERTY LLVM_EXTRA_DRIVER_ENTRIES)
-
 file(WRITE
           "${CMAKE_CURRENT_BINARY_DIR}/LLVMDriverTools.def"
-          "${def_decl}${LLVM_EXTRA_DRIVER_ENTRIES}#undef LLVM_DRIVER_TOOL\n")
+          "${def_decl}#undef LLVM_DRIVER_TOOL\n")
 
 target_include_directories(llvm-driver PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
 target_sources(llvm-driver PRIVATE llvm-driver.cpp)
@@ -28,9 +30,8 @@
 endif(APPLE)
 
 macro(generate_driver_tool_targets)
-  get_property(LLVM_DRIVER_TOOLS GLOBAL PROPERTY LLVM_DRIVER_TOOLS)
   get_property(LLVM_DRIVER_TOOL_SYMLINKS GLOBAL PROPERTY LLVM_DRIVER_TOOL_SYMLINKS)
-  foreach(name IN LISTS LLVM_DRIVER_TOOLS LLVM_DRIVER_TOOL_SYMLINKS)
+  foreach(name ${LLVM_DRIVER_TOOL_SYMLINKS})
     add_llvm_tool_symlink(${name} llvm-driver ALWAYS_GENERATE)
     # Always generate install targets
     llvm_install_symlink(LLVM ${name} llvm-driver ALWAYS_GENERATE)
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 3f54336..a373daf 100644
--- a/src/llvm-project/llvm/tools/llvm-driver/llvm-driver.cpp
+++ b/src/llvm-project/llvm/tools/llvm-driver/llvm-driver.cpp
@@ -49,9 +49,15 @@
 
   StringRef Stem = sys::path::stem(ToolName);
   auto Is = [=](StringRef Tool) {
-    auto I = Stem.rfind_insensitive(Tool);
-    return I != StringRef::npos && (I + Tool.size() == Stem.size() ||
-                                    !llvm::isAlnum(Stem[I + Tool.size()]));
+    auto IsImpl = [=](StringRef Stem) {
+      auto I = Stem.rfind_insensitive(Tool);
+      return I != StringRef::npos && (I + Tool.size() == Stem.size() ||
+                                      !llvm::isAlnum(Stem[I + Tool.size()]));
+    };
+    for (StringRef S : {Stem, sys::path::filename(ToolName)})
+      if (IsImpl(S))
+        return true;
+    return false;
   };
 
 #define LLVM_DRIVER_TOOL(tool, entry)                                          \
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfdump/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-dwarfdump/CMakeLists.txt
index 58d8114..7c68aaa 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfdump/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-dwarfdump/CMakeLists.txt
@@ -5,6 +5,7 @@
   MC
   Object
   Support
+  TargetParser
   )
 
 add_llvm_tool(llvm-dwarfdump
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp b/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
index ed92665..a967abf 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -500,7 +500,8 @@
     return;
 
   // Handle any kind of lexical scope.
-  const bool HasAbstractOrigin = Die.find(dwarf::DW_AT_abstract_origin) != None;
+  const bool HasAbstractOrigin =
+      Die.find(dwarf::DW_AT_abstract_origin) != std::nullopt;
   const bool IsFunction = Tag == dwarf::DW_TAG_subprogram;
   const bool IsBlock = Tag == dwarf::DW_TAG_lexical_block;
   const bool IsInlinedFunction = Tag == dwarf::DW_TAG_inlined_subroutine;
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 cc7f353..27330a5 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfdump/llvm-dwarfdump.cpp
@@ -18,6 +18,8 @@
 #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
 #include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/TargetRegistry.h"
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/MachOUniversal.h"
 #include "llvm/Object/ObjectFile.h"
@@ -137,8 +139,7 @@
 
 // Options for dumping specific sections.
 static unsigned DumpType = DIDT_Null;
-static std::array<llvm::Optional<uint64_t>, (unsigned)DIDT_ID_Count>
-    DumpOffsets;
+static std::array<std::optional<uint64_t>, (unsigned)DIDT_ID_Count> DumpOffsets;
 #define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION)        \
   static opt<OPTION> Dump##ENUM_NAME(CMDLINE_NAME,                             \
                                      desc("Dump the " ELF_NAME " section"),    \
@@ -248,6 +249,13 @@
                      cl::desc("Show the sizes of all debug sections, "
                               "expressed in bytes."),
                      cat(DwarfDumpCategory));
+static cl::opt<bool> ManuallyGenerateUnitIndex(
+    "manaully-generate-unit-index",
+    cl::desc("if the input is dwp file, parse .debug_info "
+             "section and use it to populate "
+             "DW_SECT_INFO contributions in cu-index. "
+             "For DWARF5 it also populated TU Index."),
+    cl::init(false), cl::Hidden, cl::cat(DwarfDumpCategory));
 static cl::opt<bool>
     ShowSources("show-sources",
                 cl::desc("Show the sources across all compilation units."),
@@ -341,9 +349,11 @@
                                      const Twine &, raw_ostream &)>;
 
 /// Print only DIEs that have a certain name.
-static bool filterByName(const StringSet<> &Names, DWARFDie Die,
-                         StringRef NameRef, raw_ostream &OS) {
+static bool filterByName(
+    const StringSet<> &Names, DWARFDie Die, StringRef NameRef, raw_ostream &OS,
+    std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
   DIDumpOptions DumpOpts = getDumpOpts(Die.getDwarfUnit()->getContext());
+  DumpOpts.GetNameForDWARFReg = GetNameForDWARFReg;
   std::string Name =
       (IgnoreCase && !UseRegex) ? NameRef.lower() : NameRef.str();
   if (UseRegex) {
@@ -369,24 +379,25 @@
 }
 
 /// Print only DIEs that have a certain name.
-static void filterByName(const StringSet<> &Names,
-                         DWARFContext::unit_iterator_range CUs,
-                         raw_ostream &OS) {
+static void filterByName(
+    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};
       if (const char *Name = Die.getName(DINameKind::ShortName))
-        if (filterByName(Names, Die, Name, OS))
+        if (filterByName(Names, Die, Name, OS, GetNameForDWARFReg))
           continue;
       if (const char *Name = Die.getName(DINameKind::LinkageName))
-        filterByName(Names, Die, Name, OS);
+        filterByName(Names, Die, Name, OS, GetNameForDWARFReg);
     }
 }
 
 static void getDies(DWARFContext &DICtx, const AppleAcceleratorTable &Accel,
                     StringRef Name, SmallVectorImpl<DWARFDie> &Dies) {
   for (const auto &Entry : Accel.equal_range(Name)) {
-    if (llvm::Optional<uint64_t> Off = Entry.getDIESectionOffset()) {
+    if (std::optional<uint64_t> Off = Entry.getDIESectionOffset()) {
       if (DWARFDie Die = DICtx.getDIEForOffset(*Off))
         Dies.push_back(Die);
     }
@@ -395,8 +406,8 @@
 
 static DWARFDie toDie(const DWARFDebugNames::Entry &Entry,
                       DWARFContext &DICtx) {
-  llvm::Optional<uint64_t> CUOff = Entry.getCUOffset();
-  llvm::Optional<uint64_t> Off = Entry.getDIEUnitOffset();
+  std::optional<uint64_t> CUOff = Entry.getCUOffset();
+  std::optional<uint64_t> Off = Entry.getDIEUnitOffset();
   if (!CUOff || !Off)
     return DWARFDie();
 
@@ -404,7 +415,7 @@
   if (!CU)
     return DWARFDie();
 
-  if (llvm::Optional<uint64_t> DWOId = CU->getDWOId()) {
+  if (std::optional<uint64_t> DWOId = CU->getDWOId()) {
     // This is a skeleton unit. Look up the DIE in the DWO unit.
     CU = DICtx.getDWOCompileUnitForHash(*DWOId);
     if (!CU)
@@ -423,8 +434,9 @@
 }
 
 /// Print only DIEs that have a certain name.
-static void filterByAccelName(ArrayRef<std::string> Names, DWARFContext &DICtx,
-                              raw_ostream &OS) {
+static void filterByAccelName(
+    ArrayRef<std::string> Names, DWARFContext &DICtx, raw_ostream &OS,
+    std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) {
   SmallVector<DWARFDie, 4> Dies;
   for (const auto &Name : Names) {
     getDies(DICtx, DICtx.getAppleNames(), Name, Dies);
@@ -436,6 +448,7 @@
   Dies.erase(std::unique(Dies.begin(), Dies.end()), Dies.end());
 
   DIDumpOptions DumpOpts = getDumpOpts(DICtx);
+  DumpOpts.GetNameForDWARFReg = GetNameForDWARFReg;
   for (DWARFDie Die : Dies)
     Die.dump(OS, 0, DumpOpts);
 }
@@ -477,7 +490,7 @@
                                     StringRef CompDir,
                                     std::vector<std::string> &Sources) {
   bool Result = true;
-  llvm::Optional<uint64_t> LastIndex = LT.getLastValidFileIndex();
+  std::optional<uint64_t> LastIndex = LT.getLastValidFileIndex();
   for (uint64_t I = LT.hasFileAtIndex(0) ? 0 : 1,
                 E = LastIndex ? *LastIndex + 1 : 0;
        I < E; ++I) {
@@ -552,10 +565,41 @@
   return Result;
 }
 
+static std::unique_ptr<MCRegisterInfo>
+createRegInfo(const object::ObjectFile &Obj) {
+  std::unique_ptr<MCRegisterInfo> MCRegInfo;
+  Triple TT;
+  TT.setArch(Triple::ArchType(Obj.getArch()));
+  TT.setVendor(Triple::UnknownVendor);
+  TT.setOS(Triple::UnknownOS);
+  std::string TargetLookupError;
+  const Target *TheTarget =
+      TargetRegistry::lookupTarget(TT.str(), TargetLookupError);
+  if (!TargetLookupError.empty())
+    return nullptr;
+  MCRegInfo.reset(TheTarget->createMCRegInfo(TT.str()));
+  return MCRegInfo;
+}
+
 static bool dumpObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
                            const Twine &Filename, raw_ostream &OS) {
-  logAllUnhandledErrors(DICtx.loadRegisterInfo(Obj), errs(),
-                        Filename.str() + ": ");
+
+  auto MCRegInfo = createRegInfo(Obj);
+  if (!MCRegInfo)
+    logAllUnhandledErrors(createStringError(inconvertibleErrorCode(),
+                                            "Error in creating MCRegInfo"),
+                          errs(), Filename.str() + ": ");
+
+  auto GetRegName = [&MCRegInfo](uint64_t DwarfRegNum, bool IsEH) -> StringRef {
+    if (!MCRegInfo)
+      return {};
+    if (std::optional<unsigned> LLVMRegNum =
+            MCRegInfo->getLLVMRegNum(DwarfRegNum, IsEH))
+      if (const char *RegName = MCRegInfo->getName(*LLVMRegNum))
+        return StringRef(RegName);
+    return {};
+  };
+
   // The UUID dump already contains all the same information.
   if (!(DumpType & DIDT_UUID) || DumpType == DIDT_All)
     OS << Filename << ":\tfile format " << Obj.getFileFormatName() << '\n';
@@ -570,19 +614,21 @@
     for (auto name : Name)
       Names.insert((IgnoreCase && !UseRegex) ? StringRef(name).lower() : name);
 
-    filterByName(Names, DICtx.normal_units(), OS);
-    filterByName(Names, DICtx.dwo_units(), OS);
+    filterByName(Names, DICtx.normal_units(), OS, GetRegName);
+    filterByName(Names, DICtx.dwo_units(), OS, GetRegName);
     return true;
   }
 
   // Handle the --find option and lower it to --debug-info=<offset>.
   if (!Find.empty()) {
-    filterByAccelName(Find, DICtx, OS);
+    filterByAccelName(Find, DICtx, OS, GetRegName);
     return true;
   }
 
   // Dump the complete DWARF structure.
-  DICtx.dump(OS, getDumpOpts(DICtx), DumpOffsets);
+  auto DumpOpts = getDumpOpts(DICtx);
+  DumpOpts.GetNameForDWARFReg = GetRegName;
+  DICtx.dump(OS, DumpOpts, DumpOffsets);
   return true;
 }
 
@@ -636,6 +682,7 @@
       std::unique_ptr<DWARFContext> DICtx = DWARFContext::create(
           *Obj, DWARFContext::ProcessDebugRelocations::Process, nullptr, "",
           RecoverableErrorHandler);
+      DICtx->setParseCUTUIndexManually(ManuallyGenerateUnitIndex);
       if (!HandleObj(*Obj, *DICtx, Filename, OS))
         Result = false;
     }
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfutil/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-dwarfutil/CMakeLists.txt
index d932ff1..4210250 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/CMakeLists.txt
@@ -3,15 +3,16 @@
 add_public_tablegen_target(DwarfutilTableGen)
 
 set(LLVM_LINK_COMPONENTS
-  ${LLVM_TARGETS_TO_BUILD}
   DebugInfoDWARF
   DWARFLinker
+  DWARFLinkerParallel
   MC
   ObjCopy
   Object
   Option
   Support
   Target
+  TargetParser
   AllTargetsCodeGens
   AllTargetsDescs
   AllTargetsInfos
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
index 3e70f46..ef222f8c 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp
@@ -14,6 +14,7 @@
 #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>
 
@@ -40,7 +41,7 @@
 public:
   ObjFileAddressMap(DWARFContext &Context, const Options &Options,
                     object::ObjectFile &ObjFile)
-      : Opts(Options) {
+      : Opts(Options), Context(Context) {
     // Remember addresses of existing text sections.
     for (const object::SectionRef &Sect : ObjFile.sections()) {
       if (!Sect.isText())
@@ -75,7 +76,7 @@
             DIE.getTag() == dwarf::DW_TAG_label) &&
            "Wrong type of input die");
 
-    if (Optional<uint64_t> LowPC =
+    if (std::optional<uint64_t> LowPC =
             dwarf::toAddress(DIE.find(dwarf::DW_AT_low_pc))) {
       if (!isDeadAddress(*LowPC, DIE.getDwarfUnit()->getVersion(),
                          Opts.Tombstone,
@@ -137,17 +138,36 @@
 
   void clear() override { DWARFAddressRanges.clear(); }
 
-  llvm::Expected<uint64_t> relocateIndexedAddr(uint64_t, uint64_t) override {
-    // should not be called.
-    return object::createError("no relocations in linked binary");
+  llvm::Expected<uint64_t> relocateIndexedAddr(uint64_t StartOffset,
+                                               uint64_t EndOffset) override {
+    // No relocations in linked binary. Return just address value.
+
+    const char *AddrPtr =
+        Context.getDWARFObj().getAddrSection().Data.data() + StartOffset;
+    support::endianness Endianess =
+        Context.getDWARFObj().isLittleEndian() ? support::little : support::big;
+
+    assert(EndOffset > StartOffset);
+    switch (EndOffset - StartOffset) {
+    case 1:
+      return *AddrPtr;
+    case 2:
+      return support::endian::read16(AddrPtr, Endianess);
+    case 4:
+      return support::endian::read32(AddrPtr, Endianess);
+    case 8:
+      return support::endian::read64(AddrPtr, Endianess);
+    }
+
+    llvm_unreachable("relocateIndexedAddr unhandled case!");
   }
 
 protected:
   // returns true if specified address range is inside address ranges
   // of executable sections.
   bool isInsideExecutableSectionsAddressRange(uint64_t LowPC,
-                                              Optional<uint64_t> HighPC) {
-    Optional<AddressRange> Range =
+                                              std::optional<uint64_t> HighPC) {
+    std::optional<AddressRange> Range =
         TextAddressRanges.getRangeThatContains(LowPC);
 
     if (HighPC)
@@ -156,7 +176,7 @@
     return Range.has_value();
   }
 
-  uint64_t isBFDDeadAddressRange(uint64_t LowPC, Optional<uint64_t> HighPC,
+  uint64_t isBFDDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC,
                                  uint16_t Version) {
     if (LowPC == 0)
       return true;
@@ -167,7 +187,8 @@
     return !isInsideExecutableSectionsAddressRange(LowPC, HighPC);
   }
 
-  uint64_t isMAXPCDeadAddressRange(uint64_t LowPC, Optional<uint64_t> HighPC,
+  uint64_t isMAXPCDeadAddressRange(uint64_t LowPC,
+                                   std::optional<uint64_t> HighPC,
                                    uint16_t Version, uint8_t AddressByteSize) {
     if (Version <= 4 && HighPC) {
       if (LowPC == (dwarf::computeTombstoneAddress(AddressByteSize) - 1))
@@ -182,7 +203,7 @@
     return false;
   }
 
-  bool isDeadAddressRange(uint64_t LowPC, Optional<uint64_t> HighPC,
+  bool isDeadAddressRange(uint64_t LowPC, std::optional<uint64_t> HighPC,
                           uint16_t Version, TombstoneKind Tombstone,
                           uint8_t AddressByteSize) {
     switch (Tombstone) {
@@ -202,13 +223,15 @@
 
   bool isDeadAddress(uint64_t LowPC, uint16_t Version, TombstoneKind Tombstone,
                      uint8_t AddressByteSize) {
-    return isDeadAddressRange(LowPC, None, Version, Tombstone, AddressByteSize);
+    return isDeadAddressRange(LowPC, std::nullopt, Version, Tombstone,
+                              AddressByteSize);
   }
 
 private:
   RangesTy DWARFAddressRanges;
   AddressRanges TextAddressRanges;
   const Options &Opts;
+  DWARFContext &Context;
 };
 
 static bool knownByDWARFUtil(StringRef SecName) {
@@ -229,9 +252,63 @@
       .Case(".debug_macinfo", true)
       .Case(".debug_str", true)
       .Case(".debug_str_offsets", true)
+      .Case(".debug_pubnames", true)
+      .Case(".debug_pubtypes", true)
+      .Case(".debug_names", true)
       .Default(false);
 }
 
+static std::optional<DwarfLinkerAccelTableKind>
+getAcceleratorTableKind(StringRef SecName) {
+  return llvm::StringSwitch<std::optional<DwarfLinkerAccelTableKind>>(SecName)
+      .Case(".debug_pubnames", DwarfLinkerAccelTableKind::Pub)
+      .Case(".debug_pubtypes", DwarfLinkerAccelTableKind::Pub)
+      .Case(".debug_names", DwarfLinkerAccelTableKind::DebugNames)
+      .Default(std::nullopt);
+}
+
+static std::string getMessageForReplacedAcceleratorTables(
+    SmallVector<StringRef> &AccelTableNamesToReplace,
+    DwarfUtilAccelKind TargetTable) {
+  std::string Message;
+
+  Message += "'";
+  for (StringRef Name : AccelTableNamesToReplace) {
+    if (Message.size() > 1)
+      Message += ", ";
+    Message += Name;
+  }
+
+  Message += "' will be replaced with requested ";
+
+  switch (TargetTable) {
+  case DwarfUtilAccelKind::DWARF:
+    Message += ".debug_names table";
+    break;
+
+  default:
+    assert(false);
+  }
+
+  return Message;
+}
+
+static std::string getMessageForDeletedAcceleratorTables(
+    SmallVector<StringRef> &AccelTableNamesToReplace) {
+  std::string Message;
+
+  Message += "'";
+  for (StringRef Name : AccelTableNamesToReplace) {
+    if (Message.size() > 1)
+      Message += ", ";
+    Message += Name;
+  }
+
+  Message += "' will be deleted as no accelerator tables are requested";
+
+  return Message;
+}
+
 Error linkDebugInfo(object::ObjectFile &File, const Options &Options,
                     raw_pwrite_stream &OutStream) {
 
@@ -263,11 +340,12 @@
                                           .str()))
     return createStringError(std::errc::invalid_argument, "");
 
+  std::unique_ptr<DWARFContext> Context = DWARFContext::create(File);
+
   // Create DWARF linker.
   DWARFLinker DebugInfoLinker(&OutStreamer, DwarfLinkerClient::LLD);
 
   DebugInfoLinker.setEstimatedObjfilesAmount(1);
-  DebugInfoLinker.setAccelTableKind(DwarfLinkerAccelTableKind::None);
   DebugInfoLinker.setErrorHandler(ReportErr);
   DebugInfoLinker.setWarningHandler(ReportWarn);
   DebugInfoLinker.setNumThreads(Options.NumThreads);
@@ -279,18 +357,6 @@
   std::vector<std::unique_ptr<AddressesMap>> AddresssMapForLinking(1);
   std::vector<std::string> EmptyWarnings;
 
-  std::unique_ptr<DWARFContext> Context = DWARFContext::create(File);
-
-  // Unknown debug sections would be removed. Display warning
-  // for such sections.
-  for (SectionName Sec : Context->getDWARFObj().getSectionNames()) {
-    if (isDebugSection(Sec.Name) && !knownByDWARFUtil(Sec.Name))
-      warning(
-          formatv("'{0}' is not currently supported: section will be skipped",
-                  Sec.Name),
-          Options.InputFileName);
-  }
-
   // Add object files to the DWARFLinker.
   AddresssMapForLinking[0] =
       std::make_unique<ObjFileAddressMap>(*Context, Options, File);
@@ -299,8 +365,77 @@
       File.getFileName(), &*Context, AddresssMapForLinking[0].get(),
       EmptyWarnings);
 
+  uint16_t MaxDWARFVersion = 0;
+  std::function<void(const DWARFUnit &Unit)> OnCUDieLoaded =
+      [&MaxDWARFVersion](const DWARFUnit &Unit) {
+        MaxDWARFVersion = std::max(Unit.getVersion(), MaxDWARFVersion);
+      };
+
   for (size_t I = 0; I < ObjectsForLinking.size(); I++)
-    DebugInfoLinker.addObjectFile(*ObjectsForLinking[I]);
+    DebugInfoLinker.addObjectFile(*ObjectsForLinking[I], nullptr,
+                                  OnCUDieLoaded);
+
+  // If we haven't seen any CUs, pick an arbitrary valid Dwarf version anyway.
+  if (MaxDWARFVersion == 0)
+    MaxDWARFVersion = 3;
+
+  if (Error Err = DebugInfoLinker.setTargetDWARFVersion(MaxDWARFVersion))
+    return Err;
+
+  SmallVector<DwarfLinkerAccelTableKind> AccelTables;
+
+  switch (Options.AccelTableKind) {
+  case DwarfUtilAccelKind::None:
+    // Nothing to do.
+    break;
+  case DwarfUtilAccelKind::DWARF:
+    // use .debug_names for all DWARF versions.
+    AccelTables.push_back(DwarfLinkerAccelTableKind::DebugNames);
+    break;
+  }
+
+  // Add accelerator tables to DWARFLinker.
+  for (DwarfLinkerAccelTableKind Table : AccelTables)
+    DebugInfoLinker.addAccelTableKind(Table);
+
+  SmallVector<StringRef> AccelTableNamesToReplace;
+  SmallVector<StringRef> AccelTableNamesToDelete;
+
+  // Unknown debug sections or non-requested accelerator sections would be
+  // removed. Display warning for such sections.
+  for (SectionName Sec : Context->getDWARFObj().getSectionNames()) {
+    if (isDebugSection(Sec.Name)) {
+      std::optional<DwarfLinkerAccelTableKind> SrcAccelTableKind =
+          getAcceleratorTableKind(Sec.Name);
+
+      if (SrcAccelTableKind) {
+        assert(knownByDWARFUtil(Sec.Name));
+
+        if (Options.AccelTableKind == DwarfUtilAccelKind::None)
+          AccelTableNamesToDelete.push_back(Sec.Name);
+        else if (std::find(AccelTables.begin(), AccelTables.end(),
+                           *SrcAccelTableKind) == AccelTables.end())
+          AccelTableNamesToReplace.push_back(Sec.Name);
+      } else if (!knownByDWARFUtil(Sec.Name)) {
+        assert(!SrcAccelTableKind);
+        warning(
+            formatv("'{0}' is not currently supported: section will be skipped",
+                    Sec.Name),
+            Options.InputFileName);
+      }
+    }
+  }
+
+  // Display message for the replaced accelerator tables.
+  if (!AccelTableNamesToReplace.empty())
+    warning(getMessageForReplacedAcceleratorTables(AccelTableNamesToReplace,
+                                                   Options.AccelTableKind),
+            Options.InputFileName);
+
+  // Display message for the removed accelerator tables.
+  if (!AccelTableNamesToDelete.empty())
+    warning(getMessageForDeletedAcceleratorTables(AccelTableNamesToDelete),
+            Options.InputFileName);
 
   // Link debug info.
   if (Error Err = DebugInfoLinker.link())
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.h b/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.h
index c993200..38fa2b9 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.h
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.h
@@ -24,6 +24,12 @@
   Exec,      /// match with address range of executable sections.
 };
 
+/// The kind of accelerator table.
+enum class DwarfUtilAccelKind : uint8_t {
+  None,
+  DWARF // DWARFv5: .debug_names
+};
+
 struct Options {
   std::string InputFileName;
   std::string OutputFileName;
@@ -34,6 +40,7 @@
   bool Verbose = false;
   int NumThreads = 0;
   bool Verify = false;
+  DwarfUtilAccelKind AccelTableKind = DwarfUtilAccelKind::None;
 
   std::string getSeparateDebugFileName() const {
     return OutputFileName + ".debug";
diff --git a/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.td b/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.td
index 4ab1b51..d454118 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.td
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/Options.td
@@ -5,6 +5,14 @@
   def no_ # NAME: Flag<["--"], "no-" # name>, HelpText<help2>;
 }
 
+def build_accelerator: Separate<["--", "-"], "build-accelerator">,
+  MetaVarName<"[none,DWARF]">,
+  HelpText<"Build accelerator tables(default: none)\n"
+  "    =none - Do not build accelerators\n"
+  "    =DWARF - .debug_names are generated for all DWARF versions\n"
+  >;
+def: Joined<["--", "-"], "build-accelerator=">, Alias<build_accelerator>;
+
 def help : Flag<["--"], "help">,
   HelpText<"Prints this help output">;
 
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 a6466be..74b6104 100644
--- a/src/llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwarfutil/llvm-dwarfutil.cpp
@@ -40,11 +40,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
 #include "Options.inc"
 #undef PREFIX
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -56,9 +59,9 @@
 #undef OPTION
 };
 
-class DwarfutilOptTable : public opt::OptTable {
+class DwarfutilOptTable : public opt::GenericOptTable {
 public:
-  DwarfutilOptTable() : OptTable(InfoTable) {}
+  DwarfutilOptTable() : opt::GenericOptTable(InfoTable) {}
 };
 } // namespace
 
@@ -120,6 +123,19 @@
           formatv("unknown tombstone value: '{0}'", S).str().c_str());
   }
 
+  if (opt::Arg *BuildAccelerator = Args.getLastArg(OPT_build_accelerator)) {
+    StringRef S = BuildAccelerator->getValue();
+
+    if (S == "none")
+      Options.AccelTableKind = DwarfUtilAccelKind::None;
+    else if (S == "DWARF")
+      Options.AccelTableKind = DwarfUtilAccelKind::DWARF;
+    else
+      return createStringError(
+          std::errc::invalid_argument,
+          formatv("unknown build-accelerator value: '{0}'", S).str().c_str());
+  }
+
   if (Options.Verbose) {
     if (Options.NumThreads != 1 && Args.hasArg(OPT_threads))
       warning("--num-threads set to 1 because verbose mode is specified");
@@ -420,8 +436,9 @@
 }
 
 static Error applyCLOptions(const struct Options &Opts, ObjectFile &InputFile) {
-  if (Opts.DoGarbageCollection) {
-    verbose("Do garbage collection for debug info ...", Opts.Verbose);
+  if (Opts.DoGarbageCollection ||
+      Opts.AccelTableKind != DwarfUtilAccelKind::None) {
+    verbose("Do debug info linking...", Opts.Verbose);
 
     DebugInfoBits LinkedDebugInfo;
     raw_svector_ostream OutStream(LinkedDebugInfo);
@@ -458,7 +475,7 @@
   DwarfutilOptTable T;
   unsigned MAI;
   unsigned MAC;
-  ArrayRef<const char *> ArgsArr = makeArrayRef(Argv + 1, Argc - 1);
+  ArrayRef<const char *> ArgsArr = ArrayRef(Argv + 1, Argc - 1);
   opt::InputArgList Args = T.ParseArgs(ArgsArr, MAI, MAC);
 
   if (Args.hasArg(OPT_help) || Args.size() == 0) {
@@ -481,7 +498,6 @@
   InitializeAllTargetMCs();
   InitializeAllTargetInfos();
   InitializeAllAsmPrinters();
-  InitializeAllAsmParsers();
 
   ErrorOr<std::unique_ptr<MemoryBuffer>> BuffOrErr =
       MemoryBuffer::getFileOrSTDIN(Opts.InputFileName);
diff --git a/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt
index 15210c4..3babab0 100644
--- a/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-dwp/CMakeLists.txt
@@ -7,6 +7,7 @@
   MC
   Object
   Support
+  TargetParser
   )
 
 add_llvm_tool(llvm-dwp
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 d2d162d..0a2c1c1 100644
--- a/src/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
+++ b/src/llvm-project/llvm/tools/llvm-dwp/llvm-dwp.cpp
@@ -29,6 +29,7 @@
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/ToolOutputFile.h"
+#include <optional>
 
 using namespace llvm;
 using namespace llvm::object;
@@ -71,7 +72,10 @@
     if (!DWOCompDir.empty()) {
       SmallString<16> DWOPath(std::move(DWOName));
       sys::fs::make_absolute(DWOCompDir, DWOPath);
-      DWOPaths.emplace_back(DWOPath.data(), DWOPath.size());
+      if (!sys::fs::exists(DWOPath) && sys::fs::exists(DWOName))
+        DWOPaths.push_back(std::move(DWOName));
+      else
+        DWOPaths.emplace_back(DWOPath.data(), DWOPath.size());
     } else {
       DWOPaths.push_back(std::move(DWOName));
     }
@@ -108,7 +112,13 @@
   for (const auto &ExecFilename : ExecFilenames) {
     auto DWOs = getDWOFilenames(ExecFilename);
     if (!DWOs) {
-      logAllUnhandledErrors(DWOs.takeError(), WithColor::error());
+      logAllUnhandledErrors(
+          handleErrors(DWOs.takeError(),
+                       [&](std::unique_ptr<ECError> EC) -> Error {
+                         return createFileError(ExecFilename,
+                                                Error(std::move(EC)));
+                       }),
+          WithColor::error());
       return 1;
     }
     DWOFilenames.insert(DWOFilenames.end(),
@@ -124,7 +134,13 @@
 
   auto ErrOrTriple = readTargetTriple(DWOFilenames.front());
   if (!ErrOrTriple) {
-    logAllUnhandledErrors(ErrOrTriple.takeError(), WithColor::error());
+    logAllUnhandledErrors(
+        handleErrors(ErrOrTriple.takeError(),
+                     [&](std::unique_ptr<ECError> EC) -> Error {
+                       return createFileError(DWOFilenames.front(),
+                                              Error(std::move(EC)));
+                     }),
+        WithColor::error());
     return 1;
   }
 
@@ -172,7 +188,7 @@
   // Create the output file.
   std::error_code EC;
   ToolOutputFile OutFile(OutputFilename, EC, sys::fs::OF_None);
-  Optional<buffer_ostream> BOS;
+  std::optional<buffer_ostream> BOS;
   raw_pwrite_stream *OS;
   if (EC)
     return error(Twine(OutputFilename) + ": " + EC.message(), Context);
@@ -180,7 +196,7 @@
     OS = &OutFile.os();
   } else {
     BOS.emplace(OutFile.os());
-    OS = BOS.getPointer();
+    OS = &*BOS;
   }
 
   std::unique_ptr<MCStreamer> MS(TheTarget->createMCObjectStreamer(
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/CMakeLists.txt
index f1e1784..4ff1db9 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/CMakeLists.txt
@@ -1,8 +1,13 @@
 set(LLVM_LINK_COMPONENTS
+  AllTargetsAsmParsers
+  AllTargetsCodeGens
+  AllTargetsDescs
+  AllTargetsDisassemblers
+  AllTargetsInfos
   MC
   MCParser
   Support
-  native
+  TargetParser
   )
 
 add_llvm_tool(llvm-exegesis
@@ -13,19 +18,17 @@
   intrinsics_gen
   )
 
+# Has side effect of defining LLVM_EXEGESIS_TARGETS
 add_subdirectory(lib)
 
-# Link the native exegesis target if compiled and on the right host.
-if ((LLVM_TARGETS_TO_BUILD MATCHES "${LLVM_NATIVE_ARCH}") AND (LLVM_EXEGESIS_TARGETS MATCHES "${LLVM_NATIVE_ARCH}"))
-  set(LLVM_EXEGESIS_NATIVE_ARCH "${LLVM_NATIVE_ARCH}")
-endif()
-
-if (LLVM_EXEGESIS_NATIVE_ARCH)
-  set(LLVM_EXEGESIS_NATIVE_TARGET "LLVMExegesis${LLVM_EXEGESIS_NATIVE_ARCH}")
-  set_source_files_properties(llvm-exegesis.cpp PROPERTIES COMPILE_FLAGS "-DLLVM_EXEGESIS_INITIALIZE_NATIVE_TARGET=Initialize${LLVM_EXEGESIS_NATIVE_ARCH}ExegesisTarget")
-endif()
+# Link all enabled exegesis targets
+set(libs)
+foreach(t ${LLVM_EXEGESIS_TARGETS})
+  string(STRIP ${t} t)
+  list(APPEND libs "LLVMExegesis${t}")
+endforeach()
 
 target_link_libraries(llvm-exegesis PRIVATE
   LLVMExegesis
-  ${LLVM_EXEGESIS_NATIVE_TARGET}
+  ${libs}
   )
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/CMakeLists.txt
index e416d80..554eabd 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/AArch64/CMakeLists.txt
@@ -8,6 +8,7 @@
   Exegesis
   Core
   Support
+  MC
   )
 
 add_llvm_library(LLVMExegesisAArch64
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 b12f872..d1ec125 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.cpp
@@ -102,6 +102,7 @@
 void Analysis::writeSnippet(raw_ostream &OS, ArrayRef<uint8_t> Bytes,
                             const char *Separator) const {
   SmallVector<std::string, 3> Lines;
+  const auto &SI = State_.getSubtargetInfo();
   // Parse the asm snippet and print it.
   while (!Bytes.empty()) {
     MCInst MI;
@@ -114,7 +115,7 @@
     }
     SmallString<128> InstPrinterStr; // FIXME: magic number.
     raw_svector_ostream OSS(InstPrinterStr);
-    InstPrinter_->printInst(&MI, 0, "", *SubtargetInfo_, OSS);
+    InstPrinter_->printInst(&MI, 0, "", SI, OSS);
     Bytes = Bytes.drop_front(MISize);
     Lines.emplace_back(InstPrinterStr.str().trim());
   }
@@ -136,10 +137,10 @@
   const MCInst &MCI = Point.keyInstruction();
   unsigned SchedClassId;
   std::tie(SchedClassId, std::ignore) = ResolvedSchedClass::resolveSchedClassId(
-      *SubtargetInfo_, *InstrInfo_, MCI);
+      State_.getSubtargetInfo(), State_.getInstrInfo(), MCI);
 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
   const MCSchedClassDesc *const SCDesc =
-      SubtargetInfo_->getSchedModel().getSchedClassDesc(SchedClassId);
+      State_.getSubtargetInfo().getSchedModel().getSchedClassDesc(SchedClassId);
   writeEscaped<kEscapeCsv>(OS, SCDesc->Name);
 #else
   OS << SchedClassId;
@@ -151,38 +152,30 @@
   OS << "\n";
 }
 
-Analysis::Analysis(const Target &Target,
-                   std::unique_ptr<MCSubtargetInfo> SubtargetInfo,
-                   std::unique_ptr<MCInstrInfo> InstrInfo,
+Analysis::Analysis(const LLVMState &State,
                    const InstructionBenchmarkClustering &Clustering,
                    double AnalysisInconsistencyEpsilon,
-                   bool AnalysisDisplayUnstableOpcodes,
-                   const std::string &ForceCpuName)
-    : Clustering_(Clustering), SubtargetInfo_(std::move(SubtargetInfo)),
-      InstrInfo_(std::move(InstrInfo)),
+                   bool AnalysisDisplayUnstableOpcodes)
+    : Clustering_(Clustering), State_(State),
       AnalysisInconsistencyEpsilonSquared_(AnalysisInconsistencyEpsilon *
                                            AnalysisInconsistencyEpsilon),
       AnalysisDisplayUnstableOpcodes_(AnalysisDisplayUnstableOpcodes) {
   if (Clustering.getPoints().empty())
     return;
 
-  const InstructionBenchmark &FirstPoint = Clustering.getPoints().front();
-  const std::string CpuName =
-      ForceCpuName.empty() ? FirstPoint.CpuName : ForceCpuName;
-  RegInfo_.reset(Target.createMCRegInfo(FirstPoint.LLVMTriple));
   MCTargetOptions MCOptions;
-  AsmInfo_.reset(
-      Target.createMCAsmInfo(*RegInfo_, FirstPoint.LLVMTriple, MCOptions));
-  SubtargetInfo_.reset(
-      Target.createMCSubtargetInfo(FirstPoint.LLVMTriple, CpuName, ""));
-  InstPrinter_.reset(Target.createMCInstPrinter(
-      Triple(FirstPoint.LLVMTriple), 0 /*default variant*/, *AsmInfo_,
-      *InstrInfo_, *RegInfo_));
+  const auto &TM = State.getTargetMachine();
+  const auto &Triple = TM.getTargetTriple();
+  AsmInfo_.reset(TM.getTarget().createMCAsmInfo(State_.getRegInfo(),
+                                                Triple.str(), MCOptions));
+  InstPrinter_.reset(TM.getTarget().createMCInstPrinter(
+      Triple, 0 /*default variant*/, *AsmInfo_, State_.getInstrInfo(),
+      State_.getRegInfo()));
 
-  Context_ =
-      std::make_unique<MCContext>(Triple(FirstPoint.LLVMTriple), AsmInfo_.get(),
-                                  RegInfo_.get(), SubtargetInfo_.get());
-  Disasm_.reset(Target.createMCDisassembler(*SubtargetInfo_, *Context_));
+  Context_ = std::make_unique<MCContext>(
+      Triple, AsmInfo_.get(), &State_.getRegInfo(), &State_.getSubtargetInfo());
+  Disasm_.reset(TM.getTarget().createMCDisassembler(State_.getSubtargetInfo(),
+                                                    *Context_));
   assert(Disasm_ && "cannot create MCDisassembler. missing call to "
                     "InitializeXXXTargetDisassembler ?");
 }
@@ -232,14 +225,14 @@
     unsigned SchedClassId;
     bool WasVariant;
     std::tie(SchedClassId, WasVariant) =
-        ResolvedSchedClass::resolveSchedClassId(*SubtargetInfo_, *InstrInfo_,
-                                                MCI);
+        ResolvedSchedClass::resolveSchedClassId(State_.getSubtargetInfo(),
+                                                State_.getInstrInfo(), MCI);
     const auto IndexIt = SchedClassIdToIndex.find(SchedClassId);
     if (IndexIt == SchedClassIdToIndex.end()) {
       // Create a new entry.
       SchedClassIdToIndex.emplace(SchedClassId, Entries.size());
-      ResolvedSchedClassAndPoints Entry(
-          ResolvedSchedClass(*SubtargetInfo_, SchedClassId, WasVariant));
+      ResolvedSchedClassAndPoints Entry(ResolvedSchedClass(
+          State_.getSubtargetInfo(), SchedClassId, WasVariant));
       Entry.PointIds.push_back(PointId);
       Entries.push_back(std::move(Entry));
     } else {
@@ -284,11 +277,11 @@
   OS << "\">";
   switch (Point.Mode) {
   case InstructionBenchmark::Latency:
-    writeLatencySnippetHtml(OS, Point.Key.Instructions, *InstrInfo_);
+    writeLatencySnippetHtml(OS, Point.Key.Instructions, State_.getInstrInfo());
     break;
   case InstructionBenchmark::Uops:
   case InstructionBenchmark::InverseThroughput:
-    writeParallelSnippetHtml(OS, Point.Key.Instructions, *InstrInfo_);
+    writeParallelSnippetHtml(OS, Point.Key.Instructions, State_.getInstrInfo());
     break;
   default:
     llvm_unreachable("invalid mode");
@@ -314,7 +307,8 @@
   OS << "</tr>";
   for (const SchedClassCluster &Cluster : Clusters) {
     OS << "<tr class=\""
-       << (Cluster.measurementsMatch(*SubtargetInfo_, RSC, Clustering_,
+       << (Cluster.measurementsMatch(State_.getSubtargetInfo(), RSC,
+                                     Clustering_,
                                      AnalysisInconsistencyEpsilonSquared_)
                ? "good-cluster"
                : "bad-cluster")
@@ -383,15 +377,15 @@
         "idealized unit resource (port) pressure assuming ideal "
         "distribution\">Idealized Resource Pressure</th></tr>";
   if (RSC.SCDesc->isValid()) {
-    const auto &SM = SubtargetInfo_->getSchedModel();
+    const auto &SI = State_.getSubtargetInfo();
+    const auto &SM = SI.getSchedModel();
     OS << "<tr><td>&#10004;</td>";
     OS << "<td>" << (RSC.WasVariant ? "&#10004;" : "&#10005;") << "</td>";
     OS << "<td>" << RSC.SCDesc->NumMicroOps << "</td>";
     // Latencies.
     OS << "<td><ul>";
     for (int I = 0, E = RSC.SCDesc->NumWriteLatencyEntries; I < E; ++I) {
-      const auto *const Entry =
-          SubtargetInfo_->getWriteLatencyEntry(RSC.SCDesc, I);
+      const auto *const Entry = SI.getWriteLatencyEntry(RSC.SCDesc, I);
       OS << "<li>" << Entry->Cycles;
       if (RSC.SCDesc->NumWriteLatencyEntries > 1) {
         // Dismabiguate if more than 1 latency.
@@ -403,8 +397,7 @@
     // inverse throughput.
     OS << "<td>";
     writeMeasurementValue<kEscapeHtml>(
-        OS,
-        MCSchedModel::getReciprocalThroughput(*SubtargetInfo_, *RSC.SCDesc));
+        OS, MCSchedModel::getReciprocalThroughput(SI, *RSC.SCDesc));
     OS << "</td>";
     // WriteProcRes.
     OS << "<td><ul>";
@@ -419,9 +412,8 @@
     OS << "<td><ul>";
     for (const auto &Pressure : RSC.IdealizedProcResPressure) {
       OS << "<li><span class=\"mono\">";
-      writeEscaped<kEscapeHtml>(OS, SubtargetInfo_->getSchedModel()
-                                        .getProcResource(Pressure.first)
-                                        ->Name);
+      writeEscaped<kEscapeHtml>(
+          OS, SI.getSchedModel().getProcResource(Pressure.first)->Name);
       OS << "</span>: ";
       writeMeasurementValue<kEscapeHtml>(OS, Pressure.second);
       OS << "</li>";
@@ -550,6 +542,7 @@
   writeEscaped<kEscapeHtml>(OS, FirstPoint.CpuName);
   OS << "</span></h3>";
 
+  const auto &SI = State_.getSubtargetInfo();
   for (const auto &RSCAndPoints : makePointsPerSchedClass()) {
     if (!RSCAndPoints.RSC.SCDesc)
       continue;
@@ -574,10 +567,9 @@
 
     // Print any scheduling class that has at least one cluster that does not
     // match the checked-in data.
-    if (all_of(SchedClassClusters, [this,
-                                    &RSCAndPoints](const SchedClassCluster &C) {
-          return C.measurementsMatch(*SubtargetInfo_, RSCAndPoints.RSC,
-                                     Clustering_,
+    if (all_of(SchedClassClusters, [this, &RSCAndPoints,
+                                    &SI](const SchedClassCluster &C) {
+          return C.measurementsMatch(SI, RSCAndPoints.RSC, Clustering_,
                                      AnalysisInconsistencyEpsilonSquared_);
         }))
       continue; // Nothing weird.
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 b6746be..a903fd2 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Analysis.h
@@ -36,12 +36,10 @@
 // A helper class to analyze benchmark results for a target.
 class Analysis {
 public:
-  Analysis(const Target &Target, std::unique_ptr<MCSubtargetInfo> SubtargetInfo,
-           std::unique_ptr<MCInstrInfo> InstrInfo,
+  Analysis(const LLVMState &State,
            const InstructionBenchmarkClustering &Clustering,
            double AnalysisInconsistencyEpsilon,
-           bool AnalysisDisplayUnstableOpcodes,
-           const std::string &ForceCpuName = "");
+           bool AnalysisDisplayUnstableOpcodes);
 
   // Prints a csv of instructions for each cluster.
   struct PrintClusters {};
@@ -113,10 +111,8 @@
                     const char *Separator) const;
 
   const InstructionBenchmarkClustering &Clustering_;
+  const LLVMState &State_;
   std::unique_ptr<MCContext> Context_;
-  std::unique_ptr<MCSubtargetInfo> SubtargetInfo_;
-  std::unique_ptr<MCInstrInfo> InstrInfo_;
-  std::unique_ptr<MCRegisterInfo> RegInfo_;
   std::unique_ptr<MCAsmInfo> AsmInfo_;
   std::unique_ptr<MCInstPrinter> InstPrinter_;
   std::unique_ptr<MCDisassembler> Disasm_;
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 84fd929..0f8b765 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Assembler.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Assembler.cpp
@@ -209,6 +209,7 @@
 
   // If the snippet setup is not complete, we disable liveliness tracking. This
   // means that we won't know what values are in the registers.
+  // FIXME: this should probably be an assertion.
   if (!IsSnippetSetupComplete)
     Properties.reset(MachineFunctionProperties::Property::TracksLiveness);
 
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 dbf0769..673221e 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.cpp
@@ -23,7 +23,6 @@
 static constexpr const char kIntegerPrefix[] = "i_0x";
 static constexpr const char kDoublePrefix[] = "f_";
 static constexpr const char kInvalidOperand[] = "INVALID";
-static constexpr llvm::StringLiteral kNoRegister("%noreg");
 
 namespace llvm {
 
@@ -34,29 +33,8 @@
 struct YamlContext {
   YamlContext(const exegesis::LLVMState &State)
       : State(&State), ErrorStream(LastError),
-        OpcodeNameToOpcodeIdx(
-            generateOpcodeNameToOpcodeIdxMapping(State.getInstrInfo())),
-        RegNameToRegNo(generateRegNameToRegNoMapping(State.getRegInfo())) {}
-
-  static StringMap<unsigned>
-  generateOpcodeNameToOpcodeIdxMapping(const MCInstrInfo &InstrInfo) {
-    StringMap<unsigned> Map(InstrInfo.getNumOpcodes());
-    for (unsigned I = 0, E = InstrInfo.getNumOpcodes(); I < E; ++I)
-      Map[InstrInfo.getName(I)] = I;
-    assert(Map.size() == InstrInfo.getNumOpcodes() && "Size prediction failed");
-    return Map;
-  };
-
-  StringMap<unsigned>
-  generateRegNameToRegNoMapping(const MCRegisterInfo &RegInfo) {
-    StringMap<unsigned> Map(RegInfo.getNumRegs());
-    // Special-case RegNo 0, which would otherwise be spelled as ''.
-    Map[kNoRegister] = 0;
-    for (unsigned I = 1, E = RegInfo.getNumRegs(); I < E; ++I)
-      Map[RegInfo.getName(I)] = I;
-    assert(Map.size() == RegInfo.getNumRegs() && "Size prediction failed");
-    return Map;
-  };
+        OpcodeNameToOpcodeIdx(State.getOpcodeNameToOpcodeIdxMapping()),
+        RegNameToRegNo(State.getRegNameToRegNoMapping()) {}
 
   void serializeMCInst(const MCInst &MCInst, raw_ostream &OS) {
     OS << getInstrName(MCInst.getOpcode());
@@ -97,12 +75,12 @@
     return RegName;
   }
 
-  Optional<unsigned> getRegNo(StringRef RegName) {
+  std::optional<unsigned> getRegNo(StringRef RegName) {
     auto Iter = RegNameToRegNo.find(RegName);
     if (Iter != RegNameToRegNo.end())
       return Iter->second;
     ErrorStream << "No register with name '" << RegName << "'\n";
-    return None;
+    return std::nullopt;
   }
 
 private:
@@ -174,8 +152,8 @@
   const exegesis::LLVMState *State;
   std::string LastError;
   raw_string_ostream ErrorStream;
-  const StringMap<unsigned> OpcodeNameToOpcodeIdx;
-  const StringMap<unsigned> RegNameToRegNo;
+  const DenseMap<StringRef, unsigned> &OpcodeNameToOpcodeIdx;
+  const DenseMap<StringRef, unsigned> &RegNameToRegNo;
 };
 } // namespace
 
@@ -264,7 +242,7 @@
     String.split(Pieces, "=0x", /* MaxSplit */ -1,
                  /* KeepEmpty */ false);
     YamlContext &Context = getTypedContext(Ctx);
-    Optional<unsigned> RegNo;
+    std::optional<unsigned> RegNo;
     if (Pieces.size() == 2 && (RegNo = Context.getRegNo(Pieces[0]))) {
       RV.Register = *RegNo;
       const unsigned BitsNeeded = APInt::getBitsNeeded(Pieces[1], kRadix);
@@ -327,47 +305,69 @@
   }
 };
 
+template <> struct MappingTraits<exegesis::InstructionBenchmark::TripleAndCpu> {
+  static void mapping(IO &Io,
+                      exegesis::InstructionBenchmark::TripleAndCpu &Obj) {
+    assert(!Io.outputting() && "can only read TripleAndCpu");
+    // Read triple.
+    Io.mapRequired("llvm_triple", Obj.LLVMTriple);
+    Io.mapRequired("cpu_name", Obj.CpuName);
+    // Drop everything else.
+  }
+};
+
 } // namespace yaml
 
 namespace exegesis {
 
-Expected<InstructionBenchmark>
-InstructionBenchmark::readYaml(const LLVMState &State, StringRef Filename) {
-  if (auto ExpectedMemoryBuffer =
-          errorOrToExpected(MemoryBuffer::getFile(Filename, /*IsText=*/true))) {
-    yaml::Input Yin(*ExpectedMemoryBuffer.get());
-    YamlContext Context(State);
-    InstructionBenchmark Benchmark;
-    if (Yin.setCurrentDocument())
-      yaml::yamlize(Yin, Benchmark, /*unused*/ true, Context);
-    if (!Context.getLastError().empty())
-      return make_error<Failure>(Context.getLastError());
-    return Benchmark;
-  } else {
-    return ExpectedMemoryBuffer.takeError();
+Expected<std::set<InstructionBenchmark::TripleAndCpu>>
+InstructionBenchmark::readTriplesAndCpusFromYamls(MemoryBufferRef Buffer) {
+  // We're only mapping a field, drop other fields and silence the corresponding
+  // warnings.
+  yaml::Input Yin(
+      Buffer, nullptr, +[](const SMDiagnostic &, void *Context) {});
+  Yin.setAllowUnknownKeys(true);
+  std::set<TripleAndCpu> Result;
+  yaml::EmptyContext Context;
+  while (Yin.setCurrentDocument()) {
+    TripleAndCpu TC;
+    yamlize(Yin, TC, /*unused*/ true, Context);
+    if (Yin.error())
+      return errorCodeToError(Yin.error());
+    Result.insert(TC);
+    Yin.nextDocument();
   }
+  return Result;
+}
+
+Expected<InstructionBenchmark>
+InstructionBenchmark::readYaml(const LLVMState &State, MemoryBufferRef Buffer) {
+  yaml::Input Yin(Buffer);
+  YamlContext Context(State);
+  InstructionBenchmark Benchmark;
+  if (Yin.setCurrentDocument())
+    yaml::yamlize(Yin, Benchmark, /*unused*/ true, Context);
+  if (!Context.getLastError().empty())
+    return make_error<Failure>(Context.getLastError());
+  return std::move(Benchmark);
 }
 
 Expected<std::vector<InstructionBenchmark>>
-InstructionBenchmark::readYamls(const LLVMState &State, StringRef Filename) {
-  if (auto ExpectedMemoryBuffer =
-          errorOrToExpected(MemoryBuffer::getFile(Filename, /*IsText=*/true))) {
-    yaml::Input Yin(*ExpectedMemoryBuffer.get());
-    YamlContext Context(State);
-    std::vector<InstructionBenchmark> Benchmarks;
-    while (Yin.setCurrentDocument()) {
-      Benchmarks.emplace_back();
-      yamlize(Yin, Benchmarks.back(), /*unused*/ true, Context);
-      if (Yin.error())
-        return errorCodeToError(Yin.error());
-      if (!Context.getLastError().empty())
-        return make_error<Failure>(Context.getLastError());
-      Yin.nextDocument();
-    }
-    return Benchmarks;
-  } else {
-    return ExpectedMemoryBuffer.takeError();
+InstructionBenchmark::readYamls(const LLVMState &State,
+                                MemoryBufferRef Buffer) {
+  yaml::Input Yin(Buffer);
+  YamlContext Context(State);
+  std::vector<InstructionBenchmark> Benchmarks;
+  while (Yin.setCurrentDocument()) {
+    Benchmarks.emplace_back();
+    yamlize(Yin, Benchmarks.back(), /*unused*/ true, Context);
+    if (Yin.error())
+      return errorCodeToError(Yin.error());
+    if (!Context.getLastError().empty())
+      return make_error<Failure>(Context.getLastError());
+    Yin.nextDocument();
   }
+  return std::move(Benchmarks);
 }
 
 Error InstructionBenchmark::writeYamlTo(const LLVMState &State,
@@ -394,25 +394,6 @@
   return Error::success();
 }
 
-Error InstructionBenchmark::writeYaml(const LLVMState &State,
-                                      const StringRef Filename) {
-  if (Filename == "-") {
-    if (auto Err = writeYamlTo(State, outs()))
-      return Err;
-  } else {
-    int ResultFD = 0;
-    if (auto E = errorCodeToError(openFileForWrite(Filename, ResultFD,
-                                                   sys::fs::CD_CreateAlways,
-                                                   sys::fs::OF_TextWithCRLF))) {
-      return E;
-    }
-    raw_fd_ostream Ostr(ResultFD, true /*shouldClose*/);
-    if (auto Err = writeYamlTo(State, Ostr))
-      return Err;
-  }
-  return Error::success();
-}
-
 void PerInstructionStats::push(const BenchmarkMeasure &BM) {
   if (Key.empty())
     Key = BM.Key;
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 436bd00..a2a8095 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkResult.h
@@ -19,10 +19,12 @@
 #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"
 #include <limits>
+#include <set>
 #include <string>
 #include <unordered_map>
 #include <vector>
@@ -32,6 +34,15 @@
 
 namespace exegesis {
 
+enum class BenchmarkPhaseSelectorE {
+  PrepareSnippet,
+  PrepareAndAssembleSnippet,
+  AssembleMeasuredCode,
+  Measure,
+};
+
+enum class InstructionBenchmarkFilter { All, RegOnly, WithMem };
+
 struct InstructionBenchmarkKey {
   // The LLVM opcode name.
   std::vector<MCInst> Instructions;
@@ -76,19 +87,40 @@
   std::vector<uint8_t> AssembledSnippet;
   // How to aggregate measurements.
   enum ResultAggregationModeE { Min, Max, Mean, MinVariance };
+
+  InstructionBenchmark() = default;
+  InstructionBenchmark(InstructionBenchmark &&) = default;
+
+  InstructionBenchmark(const InstructionBenchmark &) = delete;
+  InstructionBenchmark &operator=(const InstructionBenchmark &) = delete;
+  InstructionBenchmark &operator=(InstructionBenchmark &&) = delete;
+
   // Read functions.
   static Expected<InstructionBenchmark> readYaml(const LLVMState &State,
-                                                 StringRef Filename);
+                                                 MemoryBufferRef Buffer);
 
   static Expected<std::vector<InstructionBenchmark>>
-  readYamls(const LLVMState &State, StringRef Filename);
+  readYamls(const LLVMState &State, MemoryBufferRef Buffer);
+
+  // Given a set of serialized instruction benchmarks, returns the set of
+  // triples and CPUs that appear in the list of benchmarks.
+  struct TripleAndCpu {
+    std::string LLVMTriple;
+    std::string CpuName;
+    bool operator<(const TripleAndCpu &O) const {
+      return std::tie(LLVMTriple, CpuName) < std::tie(O.LLVMTriple, O.CpuName);
+    }
+  };
+  static Expected<std::set<TripleAndCpu>>
+  readTriplesAndCpusFromYamls(MemoryBufferRef Buffer);
 
   class Error readYamlFrom(const LLVMState &State, StringRef InputContent);
 
   // Write functions, non-const because of YAML traits.
+  // NOTE: we intentionally do *NOT* have a variant of this function taking
+  //       filename, because it's behaviour is bugprone with regards to
+  //       accidentally using it more than once and overriding previous YAML.
   class Error writeYamlTo(const LLVMState &State, raw_ostream &S);
-
-  class Error writeYaml(const LLVMState &State, const StringRef Filename);
 };
 
 bool operator==(const BenchmarkMeasure &A, const BenchmarkMeasure &B);
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 03e7ccc..cc53b00 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.cpp
@@ -30,8 +30,10 @@
 namespace exegesis {
 
 BenchmarkRunner::BenchmarkRunner(const LLVMState &State,
-                                 InstructionBenchmark::ModeE Mode)
-    : State(State), Mode(Mode), Scratch(std::make_unique<ScratchSpace>()) {}
+                                 InstructionBenchmark::ModeE Mode,
+                                 BenchmarkPhaseSelectorE BenchmarkPhaseSelector)
+    : State(State), Mode(Mode), BenchmarkPhaseSelector(BenchmarkPhaseSelector),
+      Scratch(std::make_unique<ScratchSpace>()) {}
 
 BenchmarkRunner::~BenchmarkRunner() = default;
 
@@ -132,11 +134,28 @@
 };
 } // namespace
 
-Expected<InstructionBenchmark> BenchmarkRunner::runConfiguration(
+Expected<SmallString<0>> BenchmarkRunner::assembleSnippet(
+    const BenchmarkCode &BC, const SnippetRepetitor &Repetitor,
+    unsigned MinInstructions, unsigned LoopBodySize) const {
+  const std::vector<MCInst> &Instructions = BC.Key.Instructions;
+  SmallString<0> Buffer;
+  raw_svector_ostream OS(Buffer);
+  if (Error E = assembleToStream(
+          State.getExegesisTarget(), State.createTargetMachine(), BC.LiveIns,
+          BC.Key.RegisterInitialValues,
+          Repetitor.Repeat(Instructions, MinInstructions, LoopBodySize), OS)) {
+    return std::move(E);
+  }
+  return Buffer;
+}
+
+Expected<BenchmarkRunner::RunnableConfiguration>
+BenchmarkRunner::getRunnableConfiguration(
     const BenchmarkCode &BC, unsigned NumRepetitions, unsigned LoopBodySize,
-    ArrayRef<std::unique_ptr<const SnippetRepetitor>> Repetitors,
-    bool DumpObjectToDisk) const {
-  InstructionBenchmark InstrBenchmark;
+    const SnippetRepetitor &Repetitor) const {
+  RunnableConfiguration RC;
+
+  InstructionBenchmark &InstrBenchmark = RC.InstrBenchmark;
   InstrBenchmark.Mode = Mode;
   InstrBenchmark.CpuName = std::string(State.getTargetMachine().getTargetCPU());
   InstrBenchmark.LLVMTriple =
@@ -148,130 +167,89 @@
 
   InstrBenchmark.Key = BC.Key;
 
-  // If we end up having an error, and we've previously succeeded with
-  // some other Repetitor, we want to discard the previous measurements.
-  struct ClearBenchmarkOnReturn {
-    ClearBenchmarkOnReturn(InstructionBenchmark *IB) : IB(IB) {}
-    ~ClearBenchmarkOnReturn() {
-      if (Clear)
-        IB->Measurements.clear();
-    }
-    void disarm() { Clear = false; }
-
-  private:
-    InstructionBenchmark *const IB;
-    bool Clear = true;
-  };
-  ClearBenchmarkOnReturn CBOR(&InstrBenchmark);
-
-  for (const std::unique_ptr<const SnippetRepetitor> &Repetitor : Repetitors) {
-    // Assemble at least kMinInstructionsForSnippet instructions by repeating
-    // the snippet for debug/analysis. This is so that the user clearly
-    // understands that the inside instructions are repeated.
+  // Assemble at least kMinInstructionsForSnippet instructions by repeating
+  // the snippet for debug/analysis. This is so that the user clearly
+  // understands that the inside instructions are repeated.
+  if (BenchmarkPhaseSelector > BenchmarkPhaseSelectorE::PrepareSnippet) {
     const int MinInstructionsForSnippet = 4 * Instructions.size();
     const int LoopBodySizeForSnippet = 2 * Instructions.size();
-    {
-      SmallString<0> Buffer;
-      raw_svector_ostream OS(Buffer);
-      if (Error E = assembleToStream(
-              State.getExegesisTarget(), State.createTargetMachine(),
-              BC.LiveIns, BC.Key.RegisterInitialValues,
-              Repetitor->Repeat(Instructions, MinInstructionsForSnippet,
-                                LoopBodySizeForSnippet),
-              OS)) {
-        return std::move(E);
-      }
-      const ExecutableFunction EF(State.createTargetMachine(),
-                                  getObjectFromBuffer(OS.str()));
-      const auto FnBytes = EF.getFunctionBytes();
-      llvm::append_range(InstrBenchmark.AssembledSnippet, FnBytes);
-    }
-
-    // Assemble NumRepetitions instructions repetitions of the snippet for
-    // measurements.
-    const auto Filler = Repetitor->Repeat(
-        Instructions, InstrBenchmark.NumRepetitions, LoopBodySize);
-
-    object::OwningBinary<object::ObjectFile> ObjectFile;
-    if (DumpObjectToDisk) {
-      auto ObjectFilePath = writeObjectFile(BC, Filler);
-      if (Error E = ObjectFilePath.takeError()) {
-        InstrBenchmark.Error = toString(std::move(E));
-        return InstrBenchmark;
-      }
-      outs() << "Check generated assembly with: /usr/bin/objdump -d "
-             << *ObjectFilePath << "\n";
-      ObjectFile = getObjectFromFile(*ObjectFilePath);
-    } else {
-      SmallString<0> Buffer;
-      raw_svector_ostream OS(Buffer);
-      if (Error E = assembleToStream(
-              State.getExegesisTarget(), State.createTargetMachine(),
-              BC.LiveIns, BC.Key.RegisterInitialValues, Filler, OS)) {
-        return std::move(E);
-      }
-      ObjectFile = getObjectFromBuffer(OS.str());
-    }
-
-    const FunctionExecutorImpl Executor(State, std::move(ObjectFile),
-                                        Scratch.get());
-    auto NewMeasurements = runMeasurements(Executor);
-    if (Error E = NewMeasurements.takeError()) {
-      if (!E.isA<SnippetCrash>())
-        return std::move(E);
-      InstrBenchmark.Error = toString(std::move(E));
-      return InstrBenchmark;
-    }
-    assert(InstrBenchmark.NumRepetitions > 0 && "invalid NumRepetitions");
-    for (BenchmarkMeasure &BM : *NewMeasurements) {
-      // Scale the measurements by instruction.
-      BM.PerInstructionValue /= InstrBenchmark.NumRepetitions;
-      // Scale the measurements by snippet.
-      BM.PerSnippetValue *= static_cast<double>(Instructions.size()) /
-                            InstrBenchmark.NumRepetitions;
-    }
-    if (InstrBenchmark.Measurements.empty()) {
-      InstrBenchmark.Measurements = std::move(*NewMeasurements);
-      continue;
-    }
-
-    assert(Repetitors.size() > 1 && !InstrBenchmark.Measurements.empty() &&
-           "We're in an 'min' repetition mode, and need to aggregate new "
-           "result to the existing result.");
-    assert(InstrBenchmark.Measurements.size() == NewMeasurements->size() &&
-           "Expected to have identical number of measurements.");
-    for (auto I : zip(InstrBenchmark.Measurements, *NewMeasurements)) {
-      BenchmarkMeasure &Measurement = std::get<0>(I);
-      BenchmarkMeasure &NewMeasurement = std::get<1>(I);
-      assert(Measurement.Key == NewMeasurement.Key &&
-             "Expected measurements to be symmetric");
-
-      Measurement.PerInstructionValue = std::min(
-          Measurement.PerInstructionValue, NewMeasurement.PerInstructionValue);
-      Measurement.PerSnippetValue =
-          std::min(Measurement.PerSnippetValue, NewMeasurement.PerSnippetValue);
-    }
+    auto Snippet = assembleSnippet(BC, Repetitor, MinInstructionsForSnippet,
+                                   LoopBodySizeForSnippet);
+    if (Error E = Snippet.takeError())
+      return std::move(E);
+    const ExecutableFunction EF(State.createTargetMachine(),
+                                getObjectFromBuffer(*Snippet));
+    const auto FnBytes = EF.getFunctionBytes();
+    llvm::append_range(InstrBenchmark.AssembledSnippet, FnBytes);
   }
 
-  // We successfully measured everything, so don't discard the results.
-  CBOR.disarm();
-  return InstrBenchmark;
+  // Assemble NumRepetitions instructions repetitions of the snippet for
+  // measurements.
+  if (BenchmarkPhaseSelector > BenchmarkPhaseSelectorE::PrepareAndAssembleSnippet) {
+    auto Snippet = assembleSnippet(BC, Repetitor, InstrBenchmark.NumRepetitions,
+                                   LoopBodySize);
+    if (Error E = Snippet.takeError())
+      return std::move(E);
+    RC.ObjectFile = getObjectFromBuffer(*Snippet);
+  }
+
+  return std::move(RC);
 }
 
-Expected<std::string>
-BenchmarkRunner::writeObjectFile(const BenchmarkCode &BC,
-                                 const FillFunction &FillFunction) const {
+Expected<InstructionBenchmark>
+BenchmarkRunner::runConfiguration(RunnableConfiguration &&RC,
+                                  bool DumpObjectToDisk) const {
+  InstructionBenchmark &InstrBenchmark = RC.InstrBenchmark;
+  object::OwningBinary<object::ObjectFile> &ObjectFile = RC.ObjectFile;
+
+  if (DumpObjectToDisk &&
+      BenchmarkPhaseSelector > BenchmarkPhaseSelectorE::PrepareAndAssembleSnippet) {
+    auto ObjectFilePath = writeObjectFile(ObjectFile.getBinary()->getData());
+    if (Error E = ObjectFilePath.takeError()) {
+      InstrBenchmark.Error = toString(std::move(E));
+      return std::move(InstrBenchmark);
+    }
+    outs() << "Check generated assembly with: /usr/bin/objdump -d "
+           << *ObjectFilePath << "\n";
+  }
+
+  if (BenchmarkPhaseSelector < BenchmarkPhaseSelectorE::Measure) {
+    InstrBenchmark.Error = "actual measurements skipped.";
+    return std::move(InstrBenchmark);
+  }
+
+  const FunctionExecutorImpl Executor(State, std::move(ObjectFile),
+                                      Scratch.get());
+  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);
+  }
+  assert(InstrBenchmark.NumRepetitions > 0 && "invalid NumRepetitions");
+  for (BenchmarkMeasure &BM : *NewMeasurements) {
+    // Scale the measurements by instruction.
+    BM.PerInstructionValue /= InstrBenchmark.NumRepetitions;
+    // Scale the measurements by snippet.
+    BM.PerSnippetValue *=
+        static_cast<double>(InstrBenchmark.Key.Instructions.size()) /
+        InstrBenchmark.NumRepetitions;
+  }
+  InstrBenchmark.Measurements = std::move(*NewMeasurements);
+
+  return std::move(InstrBenchmark);
+}
+
+Expected<std::string> BenchmarkRunner::writeObjectFile(StringRef Buffer) const {
   int ResultFD = 0;
   SmallString<256> ResultPath;
   if (Error E = errorCodeToError(
           sys::fs::createTemporaryFile("snippet", "o", ResultFD, ResultPath)))
     return std::move(E);
   raw_fd_ostream OFS(ResultFD, true /*ShouldClose*/);
-  if (Error E = assembleToStream(
-          State.getExegesisTarget(), State.createTargetMachine(), BC.LiveIns,
-          BC.Key.RegisterInitialValues, FillFunction, OFS)) {
-    return std::move(E);
-  }
+  OFS.write(Buffer.data(), Buffer.size());
+  OFS.flush();
   return std::string(ResultPath.str());
 }
 
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 b66902e..ea60eee 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/BenchmarkRunner.h
@@ -35,15 +35,36 @@
 class BenchmarkRunner {
 public:
   explicit BenchmarkRunner(const LLVMState &State,
-                           InstructionBenchmark::ModeE Mode);
+                           InstructionBenchmark::ModeE Mode,
+                           BenchmarkPhaseSelectorE BenchmarkPhaseSelector);
 
   virtual ~BenchmarkRunner();
 
-  Expected<InstructionBenchmark>
-  runConfiguration(const BenchmarkCode &Configuration, unsigned NumRepetitions,
-                   unsigned LoopUnrollFactor,
-                   ArrayRef<std::unique_ptr<const SnippetRepetitor>> Repetitors,
-                   bool DumpObjectToDisk) const;
+  class RunnableConfiguration {
+    friend class BenchmarkRunner;
+
+  public:
+    ~RunnableConfiguration() = default;
+    RunnableConfiguration(RunnableConfiguration &&) = default;
+
+    RunnableConfiguration(const RunnableConfiguration &) = delete;
+    RunnableConfiguration &operator=(RunnableConfiguration &&) = delete;
+    RunnableConfiguration &operator=(const RunnableConfiguration &) = delete;
+
+  private:
+    RunnableConfiguration() = default;
+
+    InstructionBenchmark InstrBenchmark;
+    object::OwningBinary<object::ObjectFile> ObjectFile;
+  };
+
+  Expected<RunnableConfiguration>
+  getRunnableConfiguration(const BenchmarkCode &Configuration,
+                           unsigned NumRepetitions, unsigned LoopUnrollFactor,
+                           const SnippetRepetitor &Repetitor) const;
+
+  Expected<InstructionBenchmark> runConfiguration(RunnableConfiguration &&RC,
+                                                  bool DumpObjectToDisk) const;
 
   // Scratch space to run instructions that touch memory.
   struct ScratchSpace {
@@ -77,13 +98,18 @@
 protected:
   const LLVMState &State;
   const InstructionBenchmark::ModeE Mode;
+  const BenchmarkPhaseSelectorE BenchmarkPhaseSelector;
 
 private:
   virtual Expected<std::vector<BenchmarkMeasure>>
   runMeasurements(const FunctionExecutor &Executor) const = 0;
 
-  Expected<std::string> writeObjectFile(const BenchmarkCode &Configuration,
-                                        const FillFunction &Fill) const;
+  Expected<SmallString<0>> assembleSnippet(const BenchmarkCode &BC,
+                                           const SnippetRepetitor &Repetitor,
+                                           unsigned MinInstructions,
+                                           unsigned LoopBodySize) const;
+
+  Expected<std::string> writeObjectFile(StringRef Buffer) const;
 
   const std::unique_ptr<ScratchSpace> Scratch;
 };
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 2ca0ce4..e495ab3 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/CMakeLists.txt
@@ -1,23 +1,23 @@
-set(TARGETS_TO_APPEND "")
 
+set(LLVM_EXEGESIS_TARGETS)
 if (LLVM_TARGETS_TO_BUILD MATCHES "X86")
-  add_subdirectory(X86)
-  set(TARGETS_TO_APPEND "${TARGETS_TO_APPEND} X86")
+  list(APPEND LLVM_EXEGESIS_TARGETS "X86")
 endif()
 if (LLVM_TARGETS_TO_BUILD MATCHES "AArch64")
-  add_subdirectory(AArch64)
-  set(TARGETS_TO_APPEND "${TARGETS_TO_APPEND} AArch64")
+  list(APPEND LLVM_EXEGESIS_TARGETS "AArch64")
 endif()
 if (LLVM_TARGETS_TO_BUILD MATCHES "PowerPC")
-  add_subdirectory(PowerPC)
-  set(TARGETS_TO_APPEND "${TARGETS_TO_APPEND} PowerPC")
+  list(APPEND LLVM_EXEGESIS_TARGETS "PowerPC")
 endif()
 if (LLVM_TARGETS_TO_BUILD MATCHES "Mips")
-  add_subdirectory(Mips)
-  set(TARGETS_TO_APPEND "${TARGETS_TO_APPEND} Mips")
+  list(APPEND LLVM_EXEGESIS_TARGETS "Mips")
 endif()
 
-set(LLVM_EXEGESIS_TARGETS "${LLVM_EXEGESIS_TARGETS} ${TARGETS_TO_APPEND}" PARENT_SCOPE)
+set(LLVM_EXEGESIS_TARGETS ${LLVM_EXEGESIS_TARGETS} PARENT_SCOPE)
+
+foreach(t ${LLVM_EXEGESIS_TARGETS})
+  add_subdirectory(${t})
+endforeach()
 
 set(LLVM_LINK_COMPONENTS
   Analysis
@@ -26,6 +26,7 @@
   ExecutionEngine
   GlobalISel
   MC
+  MCA
   MCDisassembler
   MCJIT
   MCParser
@@ -33,6 +34,7 @@
   ObjectYAML
   RuntimeDyld
   Support
+  TargetParser
   )
 
 set(libs)
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 08646aa..f91d6fc 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Clustering.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Clustering.cpp
@@ -63,13 +63,13 @@
     ArrayRef<size_t> Pts) const {
   // First, get the centroid of this group of points. This is O(N).
   SchedClassClusterCentroid G;
-  for_each(Pts, [this, &G](size_t P) {
+  for (size_t P : Pts) {
     assert(P < Points_.size());
     ArrayRef<BenchmarkMeasure> Measurements = Points_[P].Measurements;
     if (Measurements.empty()) // Error point.
-      return;
+      continue;
     G.addPoint(Measurements);
-  });
+  }
   const std::vector<BenchmarkMeasure> Centroid = G.getAsPoint();
 
   // Since we will be comparing with the centroid, we need to halve the epsilon.
@@ -226,9 +226,8 @@
           /*IsUnstable=*/!areAllNeighbours(PointsOfSchedClass)));
       Cluster &CurrentCluster = Clusters_.back();
       // Mark points as belonging to the new cluster.
-      for_each(PointsOfSchedClass, [this, &CurrentCluster](size_t P) {
+      for (size_t P : PointsOfSchedClass)
         ClusterIdForPoint_[P] = CurrentCluster.Id;
-      });
       // And add all the points of this opcode's sched class to the new cluster.
       CurrentCluster.PointIndices.reserve(PointsOfSchedClass.size());
       CurrentCluster.PointIndices.assign(PointsOfSchedClass.begin(),
@@ -315,7 +314,7 @@
       // Actually append to-be-moved points to the new cluster.
       UnstableCluster.PointIndices.insert(UnstableCluster.PointIndices.end(),
                                           it, OldCluster.PointIndices.end());
-      // And finally, remove "to-be-moved" points form the old cluster.
+      // And finally, remove "to-be-moved" points from the old cluster.
       OldCluster.PointIndices.erase(it, OldCluster.PointIndices.end());
       // Now, the old cluster may end up being empty, but let's just keep it
       // in whatever state it ended up. Purging empty clusters isn't worth it.
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Clustering.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Clustering.h
index a4da3af..8d8570b 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Clustering.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Clustering.h
@@ -15,7 +15,6 @@
 #define LLVM_TOOLS_LLVM_EXEGESIS_CLUSTERING_H
 
 #include "BenchmarkResult.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/Support/Error.h"
 #include <limits>
 #include <vector>
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
index 9840a08..fd156ee 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/CodeTemplate.cpp
@@ -11,10 +11,19 @@
 namespace llvm {
 namespace exegesis {
 
+CodeTemplate::CodeTemplate(const CodeTemplate &) = default;
+
 CodeTemplate::CodeTemplate(CodeTemplate &&) = default;
 
 CodeTemplate &CodeTemplate::operator=(CodeTemplate &&) = default;
 
+CodeTemplate &CodeTemplate::operator=(const CodeTemplate &) = default;
+
+CodeTemplate CodeTemplate::clone() const {
+  CodeTemplate CT = *this;
+  return CT;
+}
+
 InstructionTemplate::InstructionTemplate(const Instruction *Instr)
     : Instr(Instr), VariableValues(Instr->Variables.size()) {}
 
@@ -100,7 +109,7 @@
       ExecutionMode::ALWAYS_PARALLEL_MISSING_USE_OR_DEF,
       ExecutionMode::PARALLEL_VIA_EXPLICIT_REGS,
   };
-  return makeArrayRef(kAllExecutionModeBits);
+  return ArrayRef(kAllExecutionModeBits);
 }
 
 SmallVector<ExecutionMode, 4> getExecutionModeBits(ExecutionMode Execution) {
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/CodeTemplate.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
index bea1030..16982f9 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/CodeTemplate.h
@@ -119,8 +119,8 @@
 
   CodeTemplate(CodeTemplate &&);            // default
   CodeTemplate &operator=(CodeTemplate &&); // default
-  CodeTemplate(const CodeTemplate &) = delete;
-  CodeTemplate &operator=(const CodeTemplate &) = delete;
+
+  CodeTemplate clone() const;
 
   ExecutionMode Execution = ExecutionMode::UNKNOWN;
   // See InstructionBenchmarkKey.::Config.
@@ -132,6 +132,13 @@
   // If the template uses the provided scratch memory, the register in which
   // the pointer to this memory is passed in to the function.
   unsigned ScratchSpacePointerInReg = 0;
+
+#if defined(__GNUC__) && (defined(__clang__) || LLVM_GNUC_PREREQ(8, 0, 0))
+  // FIXME: GCC7 bug workaround. Drop #if after GCC7 no longer supported.
+private:
+#endif
+  CodeTemplate(const CodeTemplate &);            // default
+  CodeTemplate &operator=(const CodeTemplate &); // default
 };
 
 } // 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 6cdefb8..d57ee14 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.cpp
@@ -20,8 +20,9 @@
 
 LatencyBenchmarkRunner::LatencyBenchmarkRunner(
     const LLVMState &State, InstructionBenchmark::ModeE Mode,
+    BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
     InstructionBenchmark::ResultAggregationModeE ResultAgg)
-    : BenchmarkRunner(State, Mode) {
+    : BenchmarkRunner(State, Mode, BenchmarkPhaseSelector) {
   assert((Mode == InstructionBenchmark::Latency ||
           Mode == InstructionBenchmark::InverseThroughput) &&
          "invalid mode");
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 b9b9efc..d7d1fa9 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LatencyBenchmarkRunner.h
@@ -23,6 +23,7 @@
 public:
   LatencyBenchmarkRunner(
       const LLVMState &State, InstructionBenchmark::ModeE Mode,
+      BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
       InstructionBenchmark::ResultAggregationModeE ResultAggMode);
   ~LatencyBenchmarkRunner() override;
 
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
index 26575cc..d7940ce 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.cpp
@@ -22,21 +22,65 @@
 namespace llvm {
 namespace exegesis {
 
-LLVMState::LLVMState(const std::string &Triple, const std::string &CpuName,
-                     const std::string &Features) {
+Expected<LLVMState> LLVMState::Create(std::string TripleName,
+                                      std::string CpuName,
+                                      const StringRef Features) {
+  if (TripleName.empty())
+    TripleName = Triple::normalize(sys::getDefaultTargetTriple());
+
+  Triple TheTriple(TripleName);
+
+  // Get the target specific parser.
   std::string Error;
-  const Target *const TheTarget = TargetRegistry::lookupTarget(Triple, Error);
-  assert(TheTarget && "unknown target for host");
-  const TargetOptions Options;
-  TheTargetMachine.reset(
-      static_cast<LLVMTargetMachine *>(TheTarget->createTargetMachine(
-          Triple, CpuName, Features, Options, Reloc::Model::Static)));
-  assert(TheTargetMachine && "unable to create target machine");
-  TheExegesisTarget = ExegesisTarget::lookup(TheTargetMachine->getTargetTriple());
-  if (!TheExegesisTarget) {
-    errs() << "no exegesis target for " << Triple << ", using default\n";
-    TheExegesisTarget = &ExegesisTarget::getDefault();
+  const Target *TheTarget =
+      TargetRegistry::lookupTarget(/*MArch=*/"", TheTriple, Error);
+  if (!TheTarget) {
+    return llvm::make_error<llvm::StringError>("no LLVM target for triple " +
+                                                   TripleName,
+                                               llvm::inconvertibleErrorCode());
   }
+
+  // Update Triple with the updated triple from the target lookup.
+  TripleName = TheTriple.str();
+
+  if (CpuName == "native")
+    CpuName = std::string(llvm::sys::getHostCPUName());
+
+  std::unique_ptr<MCSubtargetInfo> STI(
+      TheTarget->createMCSubtargetInfo(TripleName, CpuName, ""));
+  assert(STI && "Unable to create subtarget info!");
+  if (!STI->isCPUStringValid(CpuName)) {
+    return llvm::make_error<llvm::StringError>(Twine("invalid CPU name (")
+                                                   .concat(CpuName)
+                                                   .concat(") for triple ")
+                                                   .concat(TripleName),
+                                               llvm::inconvertibleErrorCode());
+  }
+  const TargetOptions Options;
+  std::unique_ptr<const TargetMachine> TM(
+      static_cast<LLVMTargetMachine *>(TheTarget->createTargetMachine(
+          TripleName, CpuName, Features, Options, Reloc::Model::Static)));
+  if (!TM) {
+    return llvm::make_error<llvm::StringError>(
+        "unable to create target machine", llvm::inconvertibleErrorCode());
+  }
+
+  const ExegesisTarget *ET =
+      TripleName.empty() ? &ExegesisTarget::getDefault()
+                         : ExegesisTarget::lookup(TM->getTargetTriple());
+  if (!ET) {
+    return llvm::make_error<llvm::StringError>(
+        "no Exegesis target for triple " + TripleName,
+        llvm::inconvertibleErrorCode());
+  }
+  return LLVMState(std::move(TM), ET, CpuName);
+}
+
+LLVMState::LLVMState(std::unique_ptr<const TargetMachine> TM,
+                     const ExegesisTarget *ET, const StringRef CpuName)
+    : TheExegesisTarget(ET), TheTargetMachine(std::move(TM)),
+      OpcodeNameToOpcodeIdxMapping(createOpcodeNameToOpcodeIdxMapping()),
+      RegNameToRegNoMapping(createRegNameToRegNoMapping()) {
   PfmCounters = &TheExegesisTarget->getPfmCounters(CpuName);
 
   BitVector ReservedRegs = getFunctionReservedRegs(getTargetMachine());
@@ -47,10 +91,6 @@
   IC.reset(new InstructionsCache(getInstrInfo(), getRATC()));
 }
 
-LLVMState::LLVMState(const std::string &CpuName)
-    : LLVMState(sys::getProcessTriple(),
-                CpuName.empty() ? sys::getHostCPUName().str() : CpuName, "") {}
-
 std::unique_ptr<LLVMTargetMachine> LLVMState::createTargetMachine() const {
   return std::unique_ptr<LLVMTargetMachine>(static_cast<LLVMTargetMachine *>(
       TheTargetMachine->getTarget().createTargetMachine(
@@ -60,6 +100,30 @@
           Reloc::Model::Static)));
 }
 
+std::unique_ptr<const DenseMap<StringRef, unsigned>>
+LLVMState::createOpcodeNameToOpcodeIdxMapping() const {
+  const MCInstrInfo &InstrInfo = getInstrInfo();
+  auto Map = std::make_unique<DenseMap<StringRef, unsigned>>(
+      InstrInfo.getNumOpcodes());
+  for (unsigned I = 0, E = InstrInfo.getNumOpcodes(); I < E; ++I)
+    (*Map)[InstrInfo.getName(I)] = I;
+  assert(Map->size() == InstrInfo.getNumOpcodes() && "Size prediction failed");
+  return std::move(Map);
+}
+
+std::unique_ptr<const DenseMap<StringRef, unsigned>>
+LLVMState::createRegNameToRegNoMapping() const {
+  const MCRegisterInfo &RegInfo = getRegInfo();
+  auto Map =
+      std::make_unique<DenseMap<StringRef, unsigned>>(RegInfo.getNumRegs());
+  // Special-case RegNo 0, which would otherwise be spelled as ''.
+  (*Map)[kNoRegister] = 0;
+  for (unsigned I = 1, E = RegInfo.getNumRegs(); I < E; ++I)
+    (*Map)[RegInfo.getName(I)] = I;
+  assert(Map->size() == RegInfo.getNumRegs() && "Size prediction failed");
+  return std::move(Map);
+}
+
 bool LLVMState::canAssemble(const MCInst &Inst) const {
   MCContext Context(TheTargetMachine->getTargetTriple(),
                     TheTargetMachine->getMCAsmInfo(),
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 e660a9f..6039bdb 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/LlvmState.h
@@ -16,6 +16,7 @@
 
 #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"
@@ -25,6 +26,8 @@
 #include <memory>
 #include <string>
 
+static constexpr llvm::StringLiteral kNoRegister("%noreg");
+
 namespace llvm {
 namespace exegesis {
 
@@ -35,12 +38,12 @@
 // measurements.
 class LLVMState {
 public:
-  // Uses the host triple. If CpuName is empty, uses the host CPU.
-  LLVMState(const std::string &CpuName);
-
-  LLVMState(const std::string &Triple,
-            const std::string &CpuName,
-            const std::string &Features = ""); // For tests.
+  // Factory function.
+  // If `Triple` is empty, uses the host triple.
+  // If `CpuName` is empty, uses the host CPU.
+  // `Features` is intended for tests.
+  static Expected<LLVMState> Create(std::string TripleName, std::string CpuName,
+                                    StringRef Features = "");
 
   const TargetMachine &getTargetMachine() const { return *TheTargetMachine; }
   std::unique_ptr<LLVMTargetMachine> createTargetMachine() const;
@@ -65,12 +68,34 @@
 
   const PfmCountersInfo &getPfmCounters() const { return *PfmCounters; }
 
+  const DenseMap<StringRef, unsigned> &getOpcodeNameToOpcodeIdxMapping() const {
+    assert(OpcodeNameToOpcodeIdxMapping);
+    return *OpcodeNameToOpcodeIdxMapping;
+  };
+
+  const DenseMap<StringRef, unsigned> &getRegNameToRegNoMapping() const {
+    assert(RegNameToRegNoMapping);
+    return *RegNameToRegNoMapping;
+  }
+
 private:
+  std::unique_ptr<const DenseMap<StringRef, unsigned>>
+  createOpcodeNameToOpcodeIdxMapping() const;
+
+  std::unique_ptr<const DenseMap<StringRef, unsigned>>
+  createRegNameToRegNoMapping() const;
+
+  LLVMState(std::unique_ptr<const TargetMachine> TM, const ExegesisTarget *ET,
+            StringRef CpuName);
+
   const ExegesisTarget *TheExegesisTarget;
   std::unique_ptr<const TargetMachine> TheTargetMachine;
   std::unique_ptr<const RegisterAliasingTrackerCache> RATC;
   std::unique_ptr<const InstructionsCache> IC;
   const PfmCountersInfo *PfmCounters;
+  std::unique_ptr<const DenseMap<StringRef, unsigned>>
+      OpcodeNameToOpcodeIdxMapping;
+  std::unique_ptr<const DenseMap<StringRef, unsigned>> RegNameToRegNoMapping;
 };
 
 } // namespace exegesis
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 0ad6645..f453731 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.cpp
@@ -67,7 +67,7 @@
 
 unsigned Operand::getImplicitReg() const {
   assert(ImplicitReg);
-  return *ImplicitReg;
+  return ImplicitReg;
 }
 
 const RegisterAliasingTracker &Operand::getRegisterAliasing() const {
@@ -111,7 +111,7 @@
   SmallVector<Operand, 8> Operands;
   SmallVector<Variable, 4> Variables;
   for (; OpIndex < Description->getNumOperands(); ++OpIndex) {
-    const auto &OpInfo = Description->opInfo_begin()[OpIndex];
+    const auto &OpInfo = Description->operands()[OpIndex];
     Operand Operand;
     Operand.Index = OpIndex;
     Operand.IsDef = (OpIndex < Description->getNumDefs());
@@ -128,21 +128,19 @@
     Operand.Info = &OpInfo;
     Operands.push_back(Operand);
   }
-  for (const MCPhysReg *MCPhysReg = Description->getImplicitDefs();
-       MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
+  for (MCPhysReg MCPhysReg : Description->implicit_defs()) {
     Operand Operand;
-    Operand.Index = OpIndex;
+    Operand.Index = OpIndex++;
     Operand.IsDef = true;
-    Operand.Tracker = &RATC.getRegister(*MCPhysReg);
+    Operand.Tracker = &RATC.getRegister(MCPhysReg);
     Operand.ImplicitReg = MCPhysReg;
     Operands.push_back(Operand);
   }
-  for (const MCPhysReg *MCPhysReg = Description->getImplicitUses();
-       MCPhysReg && *MCPhysReg; ++MCPhysReg, ++OpIndex) {
+  for (MCPhysReg MCPhysReg : Description->implicit_uses()) {
     Operand Operand;
-    Operand.Index = OpIndex;
+    Operand.Index = OpIndex++;
     Operand.IsDef = false;
-    Operand.Tracker = &RATC.getRegister(*MCPhysReg);
+    Operand.Tracker = &RATC.getRegister(MCPhysReg);
     Operand.ImplicitReg = MCPhysReg;
     Operands.push_back(Operand);
   }
@@ -351,10 +349,12 @@
 }
 
 AliasingConfigurations::AliasingConfigurations(
-    const Instruction &DefInstruction, const Instruction &UseInstruction) {
-  if (UseInstruction.AllUseRegs.anyCommon(DefInstruction.AllDefRegs)) {
-    auto CommonRegisters = UseInstruction.AllUseRegs;
-    CommonRegisters &= DefInstruction.AllDefRegs;
+    const Instruction &DefInstruction, const Instruction &UseInstruction,
+    const BitVector &ForbiddenRegisters) {
+  auto CommonRegisters = UseInstruction.AllUseRegs;
+  CommonRegisters &= DefInstruction.AllDefRegs;
+  CommonRegisters.reset(ForbiddenRegisters);
+  if (!CommonRegisters.empty()) {
     for (const MCPhysReg Reg : CommonRegisters.set_bits()) {
       AliasingRegisterOperands ARO;
       addOperandIfAlias(Reg, true, DefInstruction.Operands, ARO.Defs);
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
index 8c7e0b2..f8ebc07 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/MCInstrDescView.h
@@ -24,7 +24,6 @@
 
 #include "RegisterAliasing.h"
 #include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCInstrDesc.h"
 #include "llvm/MC/MCInstrInfo.h"
@@ -49,7 +48,7 @@
 
   // The index of this Variable in Instruction.Variables and its associated
   // Value in InstructionBuilder.VariableValues.
-  Optional<uint8_t> Index;
+  std::optional<uint8_t> Index;
 };
 
 // MCOperandInfo can only represents Explicit operands. This object gives a
@@ -59,8 +58,7 @@
 // registers and the registers reachable from them (aliasing registers).
 // - Info: a shortcut for MCInstrDesc::operands()[Index].
 // - TiedToIndex: the index of the Operand holding the value or -1.
-// - ImplicitReg: a pointer to the register value when Operand is Implicit,
-// nullptr otherwise.
+// - ImplicitReg: the register value when Operand is Implicit, 0 otherwise.
 // - VariableIndex: the index of the Variable holding the value for this Operand
 // or -1 if this operand is implicit.
 struct Operand {
@@ -82,13 +80,13 @@
   const MCOperandInfo &getExplicitOperandInfo() const;
 
   // Please use the accessors above and not the following fields.
-  Optional<uint8_t> Index;
+  std::optional<uint8_t> Index;
   bool IsDef = false;
   const RegisterAliasingTracker *Tracker = nullptr; // Set for Register Op.
   const MCOperandInfo *Info = nullptr;              // Set for Explicit Op.
-  Optional<uint8_t> TiedToIndex;                    // Set for Reg&Explicit Op.
-  const MCPhysReg *ImplicitReg = nullptr;           // Set for Implicit Op.
-  Optional<uint8_t> VariableIndex;                  // Set for Explicit Op.
+  std::optional<uint8_t> TiedToIndex;               // Set for Reg&Explicit Op.
+  MCPhysReg ImplicitReg = 0;                        // Non-0 for Implicit Op.
+  std::optional<uint8_t> VariableIndex;             // Set for Explicit Op.
 };
 
 /// A cache of BitVector to reuse between Instructions.
@@ -218,7 +216,8 @@
 // to alias with Use registers of UseInstruction.
 struct AliasingConfigurations {
   AliasingConfigurations(const Instruction &DefInstruction,
-                         const Instruction &UseInstruction);
+                         const Instruction &UseInstruction,
+                         const BitVector &ForbiddenRegisters);
 
   bool empty() const; // True if no aliasing configuration is found.
   bool hasImplicitAliasing() const;
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/CMakeLists.txt
index ecf6590..99d7034 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Mips/CMakeLists.txt
@@ -8,6 +8,8 @@
   Exegesis
   Core
   Support
+  TargetParser
+  MC
   )
 
 add_llvm_library(LLVMExegesisMips
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp b/src/llvm-project/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
index 7728fcb..114e274 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/ParallelSnippetGenerator.cpp
@@ -79,13 +79,12 @@
 namespace llvm {
 namespace exegesis {
 
-static SmallVector<const Variable *, 8>
-getVariablesWithTiedOperands(const Instruction &Instr) {
+static bool hasVariablesWithTiedOperands(const Instruction &Instr) {
   SmallVector<const Variable *, 8> Result;
   for (const auto &Var : Instr.Variables)
     if (Var.hasTiedOperands())
-      Result.push_back(&Var);
-  return Result;
+      return true;
+  return false;
 }
 
 ParallelSnippetGenerator::~ParallelSnippetGenerator() = default;
@@ -114,43 +113,181 @@
          "not enough scratch space");
 }
 
-static std::vector<InstructionTemplate> generateSnippetUsingStaticRenaming(
-    const LLVMState &State, const InstructionTemplate &IT,
-    const ArrayRef<const Variable *> TiedVariables,
-    const BitVector &ForbiddenRegisters) {
-  std::vector<InstructionTemplate> Instructions;
-  // Assign registers to variables in a round-robin manner. This is simple but
-  // ensures that the most register-constrained variable does not get starved.
-  std::vector<BitVector> PossibleRegsForVar;
-  for (const Variable *Var : TiedVariables) {
-    assert(Var);
-    const Operand &Op = IT.getInstr().getPrimaryOperand(*Var);
-    assert(Op.isReg());
-    BitVector PossibleRegs = Op.getRegisterAliasing().sourceBits();
-    remove(PossibleRegs, ForbiddenRegisters);
-    PossibleRegsForVar.push_back(std::move(PossibleRegs));
+enum class RegRandomizationStrategy : uint8_t {
+  PickRandomRegs,
+  SingleStaticRegPerOperand,
+  SingleStaticReg,
+
+  FIRST = PickRandomRegs,
+  LAST = SingleStaticReg,
+};
+
+} // namespace exegesis
+
+template <> struct enum_iteration_traits<exegesis::RegRandomizationStrategy> {
+  static constexpr bool is_iterable = true;
+};
+
+namespace exegesis {
+
+const char *getDescription(RegRandomizationStrategy S) {
+  switch (S) {
+  case RegRandomizationStrategy::PickRandomRegs:
+    return "randomizing registers";
+  case RegRandomizationStrategy::SingleStaticRegPerOperand:
+    return "one unique register for each position";
+  case RegRandomizationStrategy::SingleStaticReg:
+    return "reusing the same register for all positions";
   }
-  SmallVector<int, 2> Iterators(TiedVariables.size(), 0);
-  while (true) {
-    InstructionTemplate TmpIT = IT;
-    // Find a possible register for each variable in turn, marking the
-    // register as taken.
-    for (size_t VarId = 0; VarId < TiedVariables.size(); ++VarId) {
-      const int NextPossibleReg =
-          PossibleRegsForVar[VarId].find_next(Iterators[VarId]);
-      if (NextPossibleReg <= 0) {
-        return Instructions;
-      }
-      TmpIT.getValueFor(*TiedVariables[VarId]) =
-          MCOperand::createReg(NextPossibleReg);
-      // Bump iterator.
-      Iterators[VarId] = NextPossibleReg;
-      // Prevent other variables from using the register.
-      for (BitVector &OtherPossibleRegs : PossibleRegsForVar) {
-        OtherPossibleRegs.reset(NextPossibleReg);
+  llvm_unreachable("Unknown UseRegRandomizationStrategy enum");
+}
+
+static std::variant<std::nullopt_t, MCOperand, Register>
+generateSingleRegisterForInstrAvoidingDefUseOverlap(
+    const LLVMState &State, const BitVector &ForbiddenRegisters,
+    const BitVector &ImplicitUseAliases, const BitVector &ImplicitDefAliases,
+    const BitVector &Uses, const BitVector &Defs, const InstructionTemplate &IT,
+    const Operand &Op, const ArrayRef<InstructionTemplate> Instructions,
+    RegRandomizationStrategy S) {
+  const Instruction &Instr = IT.getInstr();
+  assert(Op.isReg() && Op.isExplicit() && !Op.isMemory() &&
+         !IT.getValueFor(Op).isValid());
+  assert((!Op.isUse() || !Op.isTied()) &&
+         "Not expecting to see a tied use reg");
+
+  if (Op.isUse()) {
+    switch (S) {
+    case RegRandomizationStrategy::PickRandomRegs:
+      break;
+    case RegRandomizationStrategy::SingleStaticReg:
+    case RegRandomizationStrategy::SingleStaticRegPerOperand: {
+      if (!Instructions.empty())
+        return Instructions.front().getValueFor(Op);
+      if (S != RegRandomizationStrategy::SingleStaticReg)
+        break;
+      BitVector PossibleRegisters = Op.getRegisterAliasing().sourceBits();
+      const BitVector UseAliases = getAliasedBits(State.getRegInfo(), Uses);
+      if (std::optional<int> CommonBit =
+              getFirstCommonBit(PossibleRegisters, UseAliases))
+        return *CommonBit;
+      break;
+    }
+    }
+  }
+
+  BitVector PossibleRegisters = Op.getRegisterAliasing().sourceBits();
+  remove(PossibleRegisters, ForbiddenRegisters);
+
+  if (Op.isDef()) {
+    remove(PossibleRegisters, ImplicitUseAliases);
+    const BitVector UseAliases = getAliasedBits(State.getRegInfo(), Uses);
+    remove(PossibleRegisters, UseAliases);
+  }
+
+  if (Op.isUse()) {
+    remove(PossibleRegisters, ImplicitDefAliases);
+    // NOTE: in general, using same reg for multiple Use's is fine.
+    if (S == RegRandomizationStrategy::SingleStaticRegPerOperand) {
+      const BitVector UseAliases = getAliasedBits(State.getRegInfo(), Uses);
+      remove(PossibleRegisters, UseAliases);
+    }
+  }
+
+  bool IsDefWithTiedUse =
+      Instr.Variables[Op.getVariableIndex()].hasTiedOperands();
+  if (Op.isUse() || IsDefWithTiedUse) {
+    // Now, important bit: if we have used some register for def,
+    // then we can not use that same register for *any* use,
+    // be it either an untied use, or an use tied to a def.
+    // But def-ing same regs is fine, as long as there are no uses!
+    const BitVector DefsAliases = getAliasedBits(State.getRegInfo(), Defs);
+    remove(PossibleRegisters, DefsAliases);
+  }
+
+  if (!PossibleRegisters.any())
+    return std::nullopt;
+
+  return randomBit(PossibleRegisters);
+}
+
+static std::optional<InstructionTemplate>
+generateSingleSnippetForInstrAvoidingDefUseOverlap(
+    const LLVMState &State, const BitVector &ForbiddenRegisters,
+    const BitVector &ImplicitUseAliases, const BitVector &ImplicitDefAliases,
+    BitVector &Uses, BitVector &Defs, InstructionTemplate IT,
+    const ArrayRef<InstructionTemplate> Instructions,
+    RegRandomizationStrategy S) {
+  const Instruction &Instr = IT.getInstr();
+  for (const Operand &Op : Instr.Operands) {
+    if (!Op.isReg() || !Op.isExplicit() || Op.isMemory() ||
+        IT.getValueFor(Op).isValid())
+      continue;
+    assert((!Op.isUse() || !Op.isTied()) && "Will not get tied uses.");
+
+    std::variant<std::nullopt_t, MCOperand, Register> R =
+        generateSingleRegisterForInstrAvoidingDefUseOverlap(
+            State, ForbiddenRegisters, ImplicitUseAliases, ImplicitDefAliases,
+            Uses, Defs, IT, Op, Instructions, S);
+
+    if (std::holds_alternative<std::nullopt_t>(R))
+      return {};
+
+    MCOperand MCOp;
+    if (std::holds_alternative<MCOperand>(R))
+      MCOp = std::get<MCOperand>(R);
+    else {
+      Register RandomReg = std::get<Register>(R);
+      if (Op.isDef())
+        Defs.set(RandomReg);
+      if (Op.isUse())
+        Uses.set(RandomReg);
+      MCOp = MCOperand::createReg(RandomReg);
+    }
+    IT.getValueFor(Op) = MCOp;
+  }
+  return IT;
+}
+
+static std::vector<InstructionTemplate>
+generateSnippetForInstrAvoidingDefUseOverlap(
+    const LLVMState &State, const InstructionTemplate &IT,
+    RegRandomizationStrategy S, const BitVector &ForbiddenRegisters) {
+  // We don't want to accidentally serialize the instruction,
+  // so we must be sure that we don't pick a def that is an implicit use,
+  // or a use that is an implicit def, so record implicit regs now.
+  BitVector ImplicitUses(State.getRegInfo().getNumRegs());
+  BitVector ImplicitDefs(State.getRegInfo().getNumRegs());
+  for (const auto &Op : IT.getInstr().Operands) {
+    if (Op.isReg() && Op.isImplicit() && !Op.isMemory()) {
+      assert(Op.isImplicitReg() && "Not an implicit register operand?");
+      if (Op.isUse())
+        ImplicitUses.set(Op.getImplicitReg());
+      else {
+        assert(Op.isDef() && "Not a use and not a def?");
+        ImplicitDefs.set(Op.getImplicitReg());
       }
     }
-    Instructions.push_back(std::move(TmpIT));
+  }
+  const BitVector ImplicitUseAliases =
+      getAliasedBits(State.getRegInfo(), ImplicitUses);
+  const BitVector ImplicitDefAliases =
+      getAliasedBits(State.getRegInfo(), ImplicitDefs);
+
+  BitVector Defs(State.getRegInfo().getNumRegs());
+  BitVector Uses(State.getRegInfo().getNumRegs());
+  std::vector<InstructionTemplate> Instructions;
+
+  while (true) {
+    std::optional<InstructionTemplate> TmpIT =
+        generateSingleSnippetForInstrAvoidingDefUseOverlap(
+            State, ForbiddenRegisters, ImplicitUseAliases, ImplicitDefAliases,
+            Uses, Defs, IT, Instructions, S);
+    if (!TmpIT)
+      return Instructions;
+    Instructions.push_back(std::move(*TmpIT));
+    if (!hasVariablesWithTiedOperands(IT.getInstr()))
+      return Instructions;
+    assert(Instructions.size() <= 128 && "Stuck in endless loop?");
   }
 }
 
@@ -164,7 +301,7 @@
           ? State.getExegesisTarget().getScratchMemoryRegister(
                 State.getTargetMachine().getTargetTriple())
           : 0;
-  const AliasingConfigurations SelfAliasing(Instr, Instr);
+  const AliasingConfigurations SelfAliasing(Instr, Instr, ForbiddenRegisters);
   if (SelfAliasing.empty()) {
     CT.Info = "instruction is parallel, repeating a random one.";
     CT.Instructions.push_back(std::move(Variant));
@@ -177,78 +314,41 @@
     instantiateMemoryOperands(CT.ScratchSpacePointerInReg, CT.Instructions);
     return getSingleton(std::move(CT));
   }
-  const auto TiedVariables = getVariablesWithTiedOperands(Instr);
-  if (!TiedVariables.empty()) {
-    CT.Info = "instruction has tied variables, using static renaming.";
-    CT.Instructions = generateSnippetUsingStaticRenaming(
-        State, Variant, TiedVariables, ForbiddenRegisters);
-    instantiateMemoryOperands(CT.ScratchSpacePointerInReg, CT.Instructions);
-    return getSingleton(std::move(CT));
+  std::vector<CodeTemplate> Result;
+  bool HasTiedOperands = hasVariablesWithTiedOperands(Instr);
+  // If there are no tied operands, then we don't want to "saturate backedge",
+  // and the template we will produce will have only a single instruction.
+  unsigned NumUntiedUseRegs = count_if(Instr.Operands, [](const Operand &Op) {
+    return Op.isReg() && Op.isExplicit() && !Op.isMemory() && Op.isUse() &&
+           !Op.isTied();
+  });
+  SmallVector<RegRandomizationStrategy, 3> Strategies;
+  if (HasTiedOperands || NumUntiedUseRegs >= 3)
+    Strategies.push_back(RegRandomizationStrategy::PickRandomRegs);
+  if (NumUntiedUseRegs >= 2)
+    Strategies.push_back(RegRandomizationStrategy::SingleStaticRegPerOperand);
+  Strategies.push_back(RegRandomizationStrategy::SingleStaticReg);
+  for (RegRandomizationStrategy S : Strategies) {
+    CodeTemplate CurrCT = CT.clone();
+    CurrCT.Info =
+        Twine("instruction has ")
+            .concat(HasTiedOperands ? "" : "no ")
+            .concat("tied variables, avoiding "
+                    "Read-After-Write issue, picking random def and use "
+                    "registers not aliasing each other, for uses, ")
+            .concat(getDescription(S))
+            .str();
+    CurrCT.Instructions = generateSnippetForInstrAvoidingDefUseOverlap(
+        State, Variant, S, ForbiddenRegisters);
+    if (CurrCT.Instructions.empty())
+      return make_error<StringError>(
+          Twine("Failed to produce any snippet via: ").concat(CurrCT.Info),
+          inconvertibleErrorCode());
+    instantiateMemoryOperands(CurrCT.ScratchSpacePointerInReg,
+                              CurrCT.Instructions);
+    Result.push_back(std::move(CurrCT));
   }
-  // No tied variables, we pick random values for defs.
-
-  // We don't want to accidentally serialize the instruction,
-  // so we must be sure that we don't pick a def that is an implicit use,
-  // or a use that is an implicit def, so record implicit regs now.
-  BitVector ImplicitUses(State.getRegInfo().getNumRegs());
-  BitVector ImplicitDefs(State.getRegInfo().getNumRegs());
-  for (const auto &Op : Instr.Operands) {
-    if (Op.isReg() && Op.isImplicit() && !Op.isMemory()) {
-      assert(Op.isImplicitReg() && "Not an implicit register operand?");
-      if (Op.isUse())
-        ImplicitUses.set(Op.getImplicitReg());
-      else {
-        assert(Op.isDef() && "Not a use and not a def?");
-        ImplicitDefs.set(Op.getImplicitReg());
-      }
-    }
-  }
-  const auto ImplicitUseAliases =
-      getAliasedBits(State.getRegInfo(), ImplicitUses);
-  const auto ImplicitDefAliases =
-      getAliasedBits(State.getRegInfo(), ImplicitDefs);
-  BitVector Defs(State.getRegInfo().getNumRegs());
-  for (const auto &Op : Instr.Operands) {
-    if (Op.isReg() && Op.isExplicit() && Op.isDef() && !Op.isMemory()) {
-      auto PossibleRegisters = Op.getRegisterAliasing().sourceBits();
-      // Do not use forbidden registers and regs that are implicitly used.
-      // Note that we don't try to avoid using implicit defs explicitly.
-      remove(PossibleRegisters, ForbiddenRegisters);
-      remove(PossibleRegisters, ImplicitUseAliases);
-      if (!PossibleRegisters.any())
-        return make_error<StringError>(
-            Twine("no available registers:\ncandidates:\n")
-                .concat(debugString(State.getRegInfo(),
-                                    Op.getRegisterAliasing().sourceBits()))
-                .concat("\nforbidden:\n")
-                .concat(debugString(State.getRegInfo(), ForbiddenRegisters))
-                .concat("\nimplicit use:\n")
-                .concat(debugString(State.getRegInfo(), ImplicitUseAliases)),
-            inconvertibleErrorCode());
-      const auto RandomReg = randomBit(PossibleRegisters);
-      Defs.set(RandomReg);
-      Variant.getValueFor(Op) = MCOperand::createReg(RandomReg);
-    }
-  }
-  // And pick random use values that are not reserved and don't alias with defs.
-  // Note that we don't try to avoid using implicit uses explicitly.
-  const auto DefAliases = getAliasedBits(State.getRegInfo(), Defs);
-  for (const auto &Op : Instr.Operands) {
-    if (Op.isReg() && Op.isExplicit() && Op.isUse() && !Op.isMemory()) {
-      auto PossibleRegisters = Op.getRegisterAliasing().sourceBits();
-      remove(PossibleRegisters, ForbiddenRegisters);
-      remove(PossibleRegisters, DefAliases);
-      remove(PossibleRegisters, ImplicitDefAliases);
-      assert(PossibleRegisters.any() && "No register left to choose from");
-      const auto RandomReg = randomBit(PossibleRegisters);
-      Variant.getValueFor(Op) = MCOperand::createReg(RandomReg);
-    }
-  }
-  CT.Info =
-      "instruction has no tied variables picking Uses different from defs";
-  CT.Instructions.push_back(std::move(Variant));
-  instantiateMemoryOperands(CT.ScratchSpacePointerInReg, CT.Instructions);
-  return getSingleton(std::move(CT));
+  return Result;
 }
 
 constexpr const size_t ParallelSnippetGenerator::kMinNumDifferentAddresses;
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/CMakeLists.txt
index 29e7f57..9483844 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/PowerPC/CMakeLists.txt
@@ -8,6 +8,8 @@
   Exegesis
   Core
   Support
+  TargetParser
+  MC
   )
 
 add_llvm_library(LLVMExegesisPowerPC
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/ProgressMeter.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/ProgressMeter.h
new file mode 100644
index 0000000..0cbc3ed
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/ProgressMeter.h
@@ -0,0 +1,145 @@
+//===-- ProgressMeter.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_EXEGESIS_PROGRESSMETER_H
+#define LLVM_TOOLS_LLVM_EXEGESIS_PROGRESSMETER_H
+
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <chrono>
+#include <cmath>
+#include <optional>
+#include <type_traits>
+
+namespace llvm {
+namespace exegesis {
+
+/// Represents `\sum_{i=1..accumulated}{step_i} / accumulated`,
+/// where `step_i` is the value passed to the `i`-th call to `step()`,
+/// and `accumulated` is the total number of calls to `step()`.
+template <typename NumTy, typename DenTy = int> class SimpleMovingAverage {
+  NumTy Accumulated = NumTy(0);
+  DenTy Steps = 0;
+
+public:
+  SimpleMovingAverage() = default;
+
+  SimpleMovingAverage(const SimpleMovingAverage &) = delete;
+  SimpleMovingAverage(SimpleMovingAverage &&) = delete;
+  SimpleMovingAverage &operator=(const SimpleMovingAverage &) = delete;
+  SimpleMovingAverage &operator=(SimpleMovingAverage &&) = delete;
+
+  inline void step(NumTy Quantity) {
+    Accumulated += Quantity;
+    ++Steps;
+  }
+
+  inline NumTy getAccumulated() const { return Accumulated; }
+
+  inline DenTy getNumSteps() const { return Steps; }
+
+  template <typename AvgTy = NumTy>
+  inline std::optional<AvgTy> getAverage() const {
+    if (Steps == 0)
+      return std::nullopt;
+    return AvgTy(Accumulated) / Steps;
+  }
+};
+
+template <typename ClockTypeTy = std::chrono::steady_clock,
+          typename = std::enable_if_t<ClockTypeTy::is_steady>>
+class ProgressMeter {
+public:
+  using ClockType = ClockTypeTy;
+  using TimePointType = std::chrono::time_point<ClockType>;
+  using DurationType = std::chrono::duration<typename ClockType::rep,
+                                             typename ClockType::period>;
+  using CompetionPercentage = int;
+  using Sec = std::chrono::duration<double, std::chrono::seconds::period>;
+
+private:
+  raw_ostream &Out;
+  const int NumStepsTotal;
+  SimpleMovingAverage<DurationType> ElapsedTotal;
+
+public:
+  friend class ProgressMeterStep;
+  class ProgressMeterStep {
+    ProgressMeter *P;
+    const TimePointType Begin;
+
+  public:
+    inline ProgressMeterStep(ProgressMeter *P_)
+        : P(P_), Begin(P ? ProgressMeter<ClockType>::ClockType::now()
+                         : TimePointType()) {}
+
+    inline ~ProgressMeterStep() {
+      if (!P)
+        return;
+      const TimePointType End = ProgressMeter<ClockType>::ClockType::now();
+      P->step(End - Begin);
+    }
+
+    ProgressMeterStep(const ProgressMeterStep &) = delete;
+    ProgressMeterStep(ProgressMeterStep &&) = delete;
+    ProgressMeterStep &operator=(const ProgressMeterStep &) = delete;
+    ProgressMeterStep &operator=(ProgressMeterStep &&) = delete;
+  };
+
+  ProgressMeter(int NumStepsTotal_, raw_ostream &out_ = llvm::errs())
+      : Out(out_), NumStepsTotal(NumStepsTotal_) {
+    assert(NumStepsTotal > 0 && "No steps are planned?");
+  }
+
+  ProgressMeter(const ProgressMeter &) = delete;
+  ProgressMeter(ProgressMeter &&) = delete;
+  ProgressMeter &operator=(const ProgressMeter &) = delete;
+  ProgressMeter &operator=(ProgressMeter &&) = delete;
+
+private:
+  void step(DurationType Elapsed) {
+    assert((ElapsedTotal.getNumSteps() < NumStepsTotal) && "Step overflow!");
+    assert(Elapsed.count() >= 0 && "Negative time drift detected.");
+
+    auto [OldProgress, OldEta] = eta();
+    ElapsedTotal.step(Elapsed);
+    auto [NewProgress, NewEta] = eta();
+
+    if (NewProgress < OldProgress + 1)
+      return;
+
+    Out << format("Processing... %*d%%", 3, NewProgress);
+    if (NewEta) {
+      int SecondsTotal = std::ceil(NewEta->count());
+      int Seconds = SecondsTotal % 60;
+      int MinutesTotal = SecondsTotal / 60;
+
+      Out << format(", ETA %02d:%02d", MinutesTotal, Seconds);
+    }
+    Out << "\n";
+    Out.flush();
+  }
+
+  inline std::pair<CompetionPercentage, std::optional<Sec>> eta() const {
+    CompetionPercentage Progress =
+        (100 * ElapsedTotal.getNumSteps()) / NumStepsTotal;
+
+    std::optional<Sec> ETA;
+    if (std::optional<Sec> AverageStepDuration =
+            ElapsedTotal.template getAverage<Sec>())
+      ETA = (NumStepsTotal - ElapsedTotal.getNumSteps()) * *AverageStepDuration;
+
+    return {Progress, ETA};
+  }
+};
+
+} // namespace exegesis
+} // namespace llvm
+
+#endif
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 03386cf..6ed327f 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SchedClassResolution.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SchedClassResolution.cpp
@@ -10,6 +10,7 @@
 #include "BenchmarkResult.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MCA/Support.h"
 #include "llvm/Support/FormatVariadic.h"
 #include <limits>
 #include <unordered_set>
@@ -45,7 +46,7 @@
 //
 // Note that in this case, P016 does not contribute any cycles, so it would
 // be removed by this function.
-// FIXME: Move this to MCSubtargetInfo and use it in llvm-mca.
+// FIXME: Merge this with the equivalent in llvm-mca.
 static SmallVector<MCWriteProcResEntry, 8>
 getNonRedundantWriteProcRes(const MCSchedClassDesc &SCDesc,
                             const MCSubtargetInfo &STI) {
@@ -53,12 +54,33 @@
   const auto &SM = STI.getSchedModel();
   const unsigned NumProcRes = SM.getNumProcResourceKinds();
 
-  // This assumes that the ProcResDescs are sorted in topological order, which
-  // is guaranteed by the tablegen backend.
-  SmallVector<float, 32> ProcResUnitUsage(NumProcRes);
+  // Collect resource masks.
+  SmallVector<uint64_t> ProcResourceMasks(NumProcRes);
+  mca::computeProcResourceMasks(SM, ProcResourceMasks);
+
+  // Sort entries by smaller resources for (basic) topological ordering.
+  using ResourceMaskAndEntry = std::pair<uint64_t, const MCWriteProcResEntry *>;
+  SmallVector<ResourceMaskAndEntry, 8> ResourceMaskAndEntries;
   for (const auto *WPR = STI.getWriteProcResBegin(&SCDesc),
                   *const WPREnd = STI.getWriteProcResEnd(&SCDesc);
        WPR != WPREnd; ++WPR) {
+    uint64_t Mask = ProcResourceMasks[WPR->ProcResourceIdx];
+    ResourceMaskAndEntries.push_back({Mask, WPR});
+  }
+  sort(ResourceMaskAndEntries,
+       [](const ResourceMaskAndEntry &A, const ResourceMaskAndEntry &B) {
+         unsigned popcntA = llvm::popcount(A.first);
+         unsigned popcntB = llvm::popcount(B.first);
+         if (popcntA < popcntB)
+           return true;
+         if (popcntA > popcntB)
+           return false;
+         return A.first < B.first;
+       });
+
+  SmallVector<float, 32> ProcResUnitUsage(NumProcRes);
+  for (const ResourceMaskAndEntry &Entry : ResourceMaskAndEntries) {
+    const MCWriteProcResEntry *WPR = Entry.second;
     const MCProcResourceDesc *const ProcResDesc =
         SM.getProcResource(WPR->ProcResourceIdx);
     if (ProcResDesc->SubUnitsIdxBegin == nullptr) {
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 962136a..07a009c 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SerialSnippetGenerator.cpp
@@ -96,7 +96,7 @@
   switch (ExecutionModeBit) {
   case ExecutionMode::ALWAYS_SERIAL_IMPLICIT_REGS_ALIAS:
     // Nothing to do, the instruction is always serial.
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case ExecutionMode::ALWAYS_SERIAL_TIED_REGS_ALIAS: {
     // Picking whatever value for the tied variable will make the instruction
     // serial.
@@ -115,8 +115,8 @@
   case ExecutionMode::SERIAL_VIA_EXPLICIT_REGS: {
     // Making the execution of this instruction serial by selecting one def
     // register to alias with one use register.
-    const AliasingConfigurations SelfAliasing(Variant.getInstr(),
-                                              Variant.getInstr());
+    const AliasingConfigurations SelfAliasing(
+        Variant.getInstr(), Variant.getInstr(), ForbiddenRegisters);
     assert(!SelfAliasing.empty() && !SelfAliasing.hasImplicitAliasing() &&
            "Instr must alias itself explicitly");
     // This is a self aliasing instruction so defs and uses are from the same
@@ -134,8 +134,9 @@
     // Select back-to-back non-memory instruction.
     for (const auto *OtherInstr : computeAliasingInstructions(
              State, &Instr, kMaxAliasingInstructions, ForbiddenRegisters)) {
-      const AliasingConfigurations Forward(Instr, *OtherInstr);
-      const AliasingConfigurations Back(*OtherInstr, Instr);
+      const AliasingConfigurations Forward(Instr, *OtherInstr,
+                                           ForbiddenRegisters);
+      const AliasingConfigurations Back(*OtherInstr, Instr, ForbiddenRegisters);
       InstructionTemplate ThisIT(Variant);
       InstructionTemplate OtherIT(OtherInstr);
       if (!Forward.hasImplicitAliasing())
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 1bcbbcb..0b69a79 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetFile.cpp
@@ -29,10 +29,10 @@
 // An MCStreamer that reads a BenchmarkCode definition from a file.
 class BenchmarkCodeStreamer : public MCStreamer, public AsmCommentConsumer {
 public:
-  explicit BenchmarkCodeStreamer(MCContext *Context,
-                                 const MCRegisterInfo *TheRegInfo,
-                                 BenchmarkCode *Result)
-      : MCStreamer(*Context), RegInfo(TheRegInfo), Result(Result) {}
+  explicit BenchmarkCodeStreamer(
+      MCContext *Context, const DenseMap<StringRef, unsigned> &RegNameToRegNo,
+      BenchmarkCode *Result)
+      : MCStreamer(*Context), RegNameToRegNo(RegNameToRegNo), Result(Result) {}
 
   // Implementation of the MCStreamer interface. We only care about
   // instructions.
@@ -89,28 +89,25 @@
 private:
   // We only care about instructions, we don't implement this part of the API.
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                        unsigned ByteAlignment) override {}
+                        Align ByteAlignment) override {}
   bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override {
     return false;
   }
-  void emitValueToAlignment(unsigned ByteAlignment, int64_t Value,
-                            unsigned ValueSize,
+  void emitValueToAlignment(Align Alignment, int64_t Value, unsigned ValueSize,
                             unsigned MaxBytesToEmit) override {}
   void emitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
-                    unsigned ByteAlignment, SMLoc Loc) override {}
+                    Align ByteAlignment, SMLoc Loc) override {}
 
   unsigned findRegisterByName(const StringRef RegName) const {
-    // FIXME: Can we do better than this ?
-    for (unsigned I = 0, E = RegInfo->getNumRegs(); I < E; ++I) {
-      if (RegName == RegInfo->getName(I))
-        return I;
-    }
+    auto Iter = RegNameToRegNo.find(RegName);
+    if (Iter != RegNameToRegNo.end())
+      return Iter->second;
     errs() << "'" << RegName
            << "' is not a valid register name for the target\n";
     return 0;
   }
 
-  const MCRegisterInfo *const RegInfo;
+  const DenseMap<StringRef, unsigned> &RegNameToRegNo;
   BenchmarkCode *const Result;
   unsigned InvalidComments = 0;
 };
@@ -138,7 +135,8 @@
       TM.getTarget().createMCObjectFileInfo(Context, /*PIC=*/false));
   Context.setObjectFileInfo(ObjectFileInfo.get());
   Context.initInlineSourceManager();
-  BenchmarkCodeStreamer Streamer(&Context, TM.getMCRegisterInfo(), &Result);
+  BenchmarkCodeStreamer Streamer(&Context, State.getRegNameToRegNoMapping(),
+                                 &Result);
 
   std::string Error;
   raw_string_ostream ErrorStream(Error);
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 b3a7118..4b47be0 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.cpp
@@ -75,6 +75,7 @@
       {
         BenchmarkCode BC;
         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;
@@ -140,9 +141,10 @@
 }
 
 Expected<std::vector<CodeTemplate>>
-generateSelfAliasingCodeTemplates(InstructionTemplate Variant) {
-  const AliasingConfigurations SelfAliasing(Variant.getInstr(),
-                                            Variant.getInstr());
+generateSelfAliasingCodeTemplates(InstructionTemplate Variant,
+                                  const BitVector &ForbiddenRegisters) {
+  const AliasingConfigurations SelfAliasing(
+      Variant.getInstr(), Variant.getInstr(), ForbiddenRegisters);
   if (SelfAliasing.empty())
     return make_error<SnippetGeneratorFailure>("empty self aliasing");
   std::vector<CodeTemplate> Result;
@@ -213,6 +215,15 @@
   return *Itr;
 }
 
+std::optional<int> getFirstCommonBit(const BitVector &A, const BitVector &B) {
+  BitVector Intersect = A;
+  Intersect &= B;
+  int idx = Intersect.find_first();
+  if (idx != -1)
+    return idx;
+  return {};
+}
+
 void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations,
                        InstructionTemplate &DefIB, InstructionTemplate &UseIB) {
   assert(!AliasingConfigurations.empty());
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 7a53c03..9c64d46 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetGenerator.h
@@ -35,7 +35,8 @@
 
 // Generates code templates that has a self-dependency.
 Expected<std::vector<CodeTemplate>>
-generateSelfAliasingCodeTemplates(InstructionTemplate Variant);
+generateSelfAliasingCodeTemplates(InstructionTemplate Variant,
+                                  const BitVector &ForbiddenRegisters);
 
 // Generates code templates without assignment constraints.
 Expected<std::vector<CodeTemplate>>
@@ -92,6 +93,9 @@
 // Precondition: Vector must have at least one bit set.
 size_t randomBit(const BitVector &Vector);
 
+// Picks a first bit that is common to these two vectors.
+std::optional<int> getFirstCommonBit(const BitVector &A, const BitVector &B);
+
 // Picks a random configuration, then selects a random def and a random use from
 // it and finally set the selected values in the provided InstructionInstances.
 void setRandomAliasing(const AliasingConfigurations &AliasingConfigurations,
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 1851cb4..bf05131 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp
@@ -60,6 +60,17 @@
             LoopBodySize](FunctionFiller &Filler) {
       const auto &ET = State.getExegesisTarget();
       auto Entry = Filler.getEntry();
+
+      // We can not use loop snippet repetitor for terminator instructions.
+      for (const MCInst &Inst : Instructions) {
+        const unsigned Opcode = Inst.getOpcode();
+        const MCInstrDesc &MCID = Filler.MCII->get(Opcode);
+        if (!MCID.isTerminator())
+          continue;
+        Entry.addReturn();
+        return;
+      }
+
       auto Loop = Filler.addBasicBlock();
       auto Exit = Filler.addBasicBlock();
 
@@ -81,13 +92,17 @@
       // Set up the loop basic block.
       Entry.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
       Loop.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
-      // The live ins are: the loop counter, the registers that were setup by
-      // the entry block, and entry block live ins.
-      Loop.MBB->addLiveIn(LoopCounter);
-      for (unsigned Reg : Filler.getRegistersSetUp())
-        Loop.MBB->addLiveIn(Reg);
-      for (const auto &LiveIn : Entry.MBB->liveins())
-        Loop.MBB->addLiveIn(LiveIn);
+      // If the snippet setup completed, then we can track liveness.
+      if (Loop.MF.getProperties().hasProperty(
+              MachineFunctionProperties::Property::TracksLiveness)) {
+        // The live ins are: the loop counter, the registers that were setup by
+        // the entry block, and entry block live ins.
+        Loop.MBB->addLiveIn(LoopCounter);
+        for (unsigned Reg : Filler.getRegistersSetUp())
+          Loop.MBB->addLiveIn(Reg);
+        for (const auto &LiveIn : Entry.MBB->liveins())
+          Loop.MBB->addLiveIn(LiveIn);
+      }
       for (auto _ : seq(0U, 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 9ff19d5..f226015 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.cpp
@@ -17,6 +17,10 @@
 namespace llvm {
 namespace exegesis {
 
+cl::OptionCategory Options("llvm-exegesis options");
+cl::OptionCategory BenchmarkOptions("llvm-exegesis benchmark options");
+cl::OptionCategory AnalysisOptions("llvm-exegesis analysis options");
+
 ExegesisTarget::~ExegesisTarget() {} // anchor.
 
 static ExegesisTarget *FirstTarget = nullptr;
@@ -70,6 +74,7 @@
 Expected<std::unique_ptr<BenchmarkRunner>>
 ExegesisTarget::createBenchmarkRunner(
     InstructionBenchmark::ModeE Mode, const LLVMState &State,
+    BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
     InstructionBenchmark::ResultAggregationModeE ResultAggMode) const {
   PfmCountersInfo PfmCounters = State.getPfmCounters();
   switch (Mode) {
@@ -77,21 +82,30 @@
     return nullptr;
   case InstructionBenchmark::Latency:
   case InstructionBenchmark::InverseThroughput:
-    if (!PfmCounters.CycleCounter) {
+    if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure &&
+        !PfmCounters.CycleCounter) {
       const char *ModeName = Mode == InstructionBenchmark::Latency
                                  ? "latency"
                                  : "inverse_throughput";
       return make_error<Failure>(
           Twine("can't run '")
               .concat(ModeName)
-              .concat("' mode, sched model does not define a cycle counter."));
+              .concat(
+                  "' mode, sched model does not define a cycle counter. You "
+                  "can pass --skip-measurements to skip the actual "
+                  "benchmarking."));
     }
-    return createLatencyBenchmarkRunner(State, Mode, ResultAggMode);
+    return createLatencyBenchmarkRunner(State, Mode, BenchmarkPhaseSelector,
+                                        ResultAggMode);
   case InstructionBenchmark::Uops:
-    if (!PfmCounters.UopsCounter && !PfmCounters.IssueCounters)
-      return make_error<Failure>("can't run 'uops' mode, sched model does not "
-                                 "define uops or issue counters.");
-    return createUopsBenchmarkRunner(State, ResultAggMode);
+    if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure &&
+        !PfmCounters.UopsCounter && !PfmCounters.IssueCounters)
+      return make_error<Failure>(
+          "can't run 'uops' mode, sched model does not define uops or issue "
+          "counters. You can pass --skip-measurements to skip the actual "
+          "benchmarking.");
+    return createUopsBenchmarkRunner(State, BenchmarkPhaseSelector,
+                                     ResultAggMode);
   }
   return nullptr;
 }
@@ -108,14 +122,16 @@
 
 std::unique_ptr<BenchmarkRunner> ExegesisTarget::createLatencyBenchmarkRunner(
     const LLVMState &State, InstructionBenchmark::ModeE Mode,
+    BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
     InstructionBenchmark::ResultAggregationModeE ResultAggMode) const {
-  return std::make_unique<LatencyBenchmarkRunner>(State, Mode, ResultAggMode);
+  return std::make_unique<LatencyBenchmarkRunner>(
+      State, Mode, BenchmarkPhaseSelector, ResultAggMode);
 }
 
 std::unique_ptr<BenchmarkRunner> ExegesisTarget::createUopsBenchmarkRunner(
-    const LLVMState &State,
+    const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
     InstructionBenchmark::ResultAggregationModeE /*unused*/) const {
-  return std::make_unique<UopsBenchmarkRunner>(State);
+  return std::make_unique<UopsBenchmarkRunner>(State, BenchmarkPhaseSelector);
 }
 
 static_assert(std::is_pod<PfmCountersInfo>::value,
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 28c103a..c922228 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/Target.h
@@ -28,11 +28,16 @@
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/MC/MCInst.h"
 #include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
 
 namespace llvm {
 namespace exegesis {
 
+extern cl::OptionCategory Options;
+extern cl::OptionCategory BenchmarkOptions;
+extern cl::OptionCategory AnalysisOptions;
+
 struct PfmCountersInfo {
   // An optional name of a performance counter that can be used to measure
   // cycles.
@@ -155,6 +160,7 @@
   // Creates a benchmark runner for the given mode.
   Expected<std::unique_ptr<BenchmarkRunner>> createBenchmarkRunner(
       InstructionBenchmark::ModeE Mode, const LLVMState &State,
+      BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
       InstructionBenchmark::ResultAggregationModeE ResultAggMode =
           InstructionBenchmark::Min) const;
 
@@ -193,9 +199,10 @@
       const LLVMState &State, const SnippetGenerator::Options &Opts) const;
   std::unique_ptr<BenchmarkRunner> virtual createLatencyBenchmarkRunner(
       const LLVMState &State, InstructionBenchmark::ModeE Mode,
+      BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
       InstructionBenchmark::ResultAggregationModeE ResultAggMode) const;
   std::unique_ptr<BenchmarkRunner> virtual createUopsBenchmarkRunner(
-      const LLVMState &State,
+      const LLVMState &State, BenchmarkPhaseSelectorE BenchmarkPhaseSelector,
       InstructionBenchmark::ResultAggregationModeE ResultAggMode) const;
 
   const ExegesisTarget *Next = nullptr;
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/TargetSelect.h b/src/llvm-project/llvm/tools/llvm-exegesis/lib/TargetSelect.h
index 003d12e..c8c6a1c 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/TargetSelect.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/TargetSelect.h
@@ -8,30 +8,26 @@
 ///
 /// \file
 ///
-/// Utilities to handle the creation of the native exegesis target.
+/// Utilities to handle the creation of the enabled exegesis target(s).
 ///
 //===----------------------------------------------------------------------===//
 
 #ifndef LLVM_TOOLS_LLVM_EXEGESIS_TARGET_SELECT_H
 #define LLVM_TOOLS_LLVM_EXEGESIS_TARGET_SELECT_H
 
+#include "llvm/Config/llvm-config.h"
+
 namespace llvm {
 namespace exegesis {
 
-#ifdef LLVM_EXEGESIS_INITIALIZE_NATIVE_TARGET
-void LLVM_EXEGESIS_INITIALIZE_NATIVE_TARGET();
-#endif
+// Forward declare all of the initialize methods for targets compiled in
+#define LLVM_EXEGESIS(TargetName) void Initialize##TargetName##ExegesisTarget();
+#include "llvm/Config/TargetExegesis.def"
 
-// Initializes the native exegesis target, or returns false if there is no
-// native target (either because llvm-exegesis does not support the target or
-// because it's not linked in).
-inline bool InitializeNativeExegesisTarget() {
-#ifdef LLVM_EXEGESIS_INITIALIZE_NATIVE_TARGET
-  LLVM_EXEGESIS_INITIALIZE_NATIVE_TARGET();
-  return true;
-#else
-  return false;
-#endif
+// Initializes all exegesis targets compiled in.
+inline void InitializeAllExegesisTargets() {
+#define LLVM_EXEGESIS(TargetName) Initialize##TargetName##ExegesisTarget();
+#include "llvm/Config/TargetExegesis.def"
 }
 
 } // namespace exegesis
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 cda74eb..c726944 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/UopsBenchmarkRunner.h
@@ -21,8 +21,10 @@
 
 class UopsBenchmarkRunner : public BenchmarkRunner {
 public:
-  UopsBenchmarkRunner(const LLVMState &State)
-      : BenchmarkRunner(State, InstructionBenchmark::Uops) {}
+  UopsBenchmarkRunner(const LLVMState &State,
+                      BenchmarkPhaseSelectorE BenchmarkPhaseSelector)
+      : BenchmarkRunner(State, InstructionBenchmark::Uops,
+                        BenchmarkPhaseSelector) {}
   ~UopsBenchmarkRunner() override;
 
   static constexpr const size_t kMinNumDifferentAddresses = 6;
diff --git a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/CMakeLists.txt
index da30b9b..1e74109 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/lib/X86/CMakeLists.txt
@@ -8,7 +8,9 @@
   Exegesis
   Core
   Support
+  TargetParser
   CodeGen
+  MC
   )
 
 add_llvm_library(LLVMExegesisX86
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 2f82759..6c9f4d5 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
@@ -38,9 +38,6 @@
 namespace llvm {
 namespace exegesis {
 
-static cl::OptionCategory
-    BenchmarkOptions("llvm-exegesis benchmark x86-options");
-
 // If a positive value is specified, we are going to use the LBR in
 // latency-mode.
 //
@@ -54,6 +51,11 @@
     cl::desc("The sample period (nbranches/sample), used for LBR sampling"),
     cl::cat(BenchmarkOptions), cl::init(0));
 
+static cl::opt<bool>
+    DisableUpperSSERegisters("x86-disable-upper-sse-registers",
+                             cl::desc("Disable XMM8-XMM15 register usage"),
+                             cl::cat(BenchmarkOptions), cl::init(false));
+
 // FIXME: Validates that repetition-mode is loop if LBR is requested.
 
 // Returns a non-null reason if we cannot handle the memory references in this
@@ -212,6 +214,8 @@
   case X86::LSS32rm:
   case X86::LSS64rm:
   case X86::SYSENTER:
+  case X86::WRFSBASE:
+  case X86::WRFSBASE64:
     return "unsupported opcode";
   default:
     break;
@@ -363,7 +367,7 @@
     //   - `ST(0) = fsqrt(ST(0))` (OneArgFPRW)
     //   - `ST(0) = ST(0) + ST(i)` (TwoArgFP)
     // They are intrinsically serial and do not modify the state of the stack.
-    return generateSelfAliasingCodeTemplates(Variant);
+    return generateSelfAliasingCodeTemplates(Variant, ForbiddenRegisters);
   default:
     llvm_unreachable("Unknown FP Type!");
   }
@@ -419,7 +423,7 @@
     //   - `ST(0) = ST(0) + ST(i)` (TwoArgFP)
     // They are intrinsically serial and do not modify the state of the stack.
     // We generate the same code for latency and uops.
-    return generateSelfAliasingCodeTemplates(Variant);
+    return generateSelfAliasingCodeTemplates(Variant, ForbiddenRegisters);
   case X86II::CompareFP:
   case X86II::CondMovFP:
     // We can compute uops for any FP instruction that does not grow or shrink
@@ -708,9 +712,12 @@
                                const APInt &Value) const override;
 
   ArrayRef<unsigned> getUnavailableRegisters() const override {
-    return makeArrayRef(kUnavailableRegisters,
-                        sizeof(kUnavailableRegisters) /
-                            sizeof(kUnavailableRegisters[0]));
+    if (DisableUpperSSERegisters)
+      return ArrayRef(kUnavailableRegistersSSE,
+                      sizeof(kUnavailableRegistersSSE) /
+                          sizeof(kUnavailableRegistersSSE[0]));
+
+    return ArrayRef(kUnavailableRegisters, std::size(kUnavailableRegisters));
   }
 
   bool allowAsBackToBack(const Instruction &Instr) const override {
@@ -773,6 +780,7 @@
   }
 
   static const unsigned kUnavailableRegisters[4];
+  static const unsigned kUnavailableRegistersSSE[12];
 };
 
 // We disable a few registers that cannot be encoded on instructions with a REX
@@ -780,6 +788,12 @@
 const unsigned ExegesisX86Target::kUnavailableRegisters[4] = {X86::AH, X86::BH,
                                                               X86::CH, X86::DH};
 
+// Optionally, also disable the upper (x86_64) SSE registers to reduce frontend
+// decoder load.
+const unsigned ExegesisX86Target::kUnavailableRegistersSSE[12] = {
+    X86::AH,    X86::BH,    X86::CH,    X86::DH,    X86::XMM8,  X86::XMM9,
+    X86::XMM10, X86::XMM11, X86::XMM12, X86::XMM13, X86::XMM14, X86::XMM15};
+
 // We're using one of R8-R15 because these registers are never hardcoded in
 // instructions (e.g. MOVS writes to EDI, ESI, EDX), so they have less
 // conflicts.
@@ -864,6 +878,35 @@
     return {loadImmediate(Reg, 32, Value)};
   if (X86::GR64RegClass.contains(Reg))
     return {loadImmediate(Reg, 64, Value)};
+  if (X86::VK8RegClass.contains(Reg) || X86::VK16RegClass.contains(Reg) ||
+      X86::VK32RegClass.contains(Reg) || X86::VK64RegClass.contains(Reg)) {
+    switch (Value.getBitWidth()) {
+    case 8:
+      if (STI.getFeatureBits()[X86::FeatureDQI]) {
+        ConstantInliner CI(Value);
+        return CI.loadAndFinalize(Reg, Value.getBitWidth(), X86::KMOVBkm);
+      }
+      [[fallthrough]];
+    case 16:
+      if (STI.getFeatureBits()[X86::FeatureAVX512]) {
+        ConstantInliner CI(Value.zextOrTrunc(16));
+        return CI.loadAndFinalize(Reg, 16, X86::KMOVWkm);
+      }
+      break;
+    case 32:
+      if (STI.getFeatureBits()[X86::FeatureBWI]) {
+        ConstantInliner CI(Value);
+        return CI.loadAndFinalize(Reg, Value.getBitWidth(), X86::KMOVDkm);
+      }
+      break;
+    case 64:
+      if (STI.getFeatureBits()[X86::FeatureBWI]) {
+        ConstantInliner CI(Value);
+        return CI.loadAndFinalize(Reg, Value.getBitWidth(), X86::KMOVQkm);
+      }
+      break;
+    }
+  }
   ConstantInliner CI(Value);
   if (X86::VR64RegClass.contains(Reg))
     return CI.loadAndFinalize(Reg, 64, X86::MMX_MOVQ64rm);
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 aecae5c..5846242 100644
--- a/src/llvm-project/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
+++ b/src/llvm-project/llvm/tools/llvm-exegesis/llvm-exegesis.cpp
@@ -18,6 +18,7 @@
 #include "lib/Error.h"
 #include "lib/LlvmState.h"
 #include "lib/PerfHelper.h"
+#include "lib/ProgressMeter.h"
 #include "lib/SnippetFile.h"
 #include "lib/SnippetRepetitor.h"
 #include "lib/Target.h"
@@ -35,6 +36,8 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/Host.h"
+#include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetSelect.h"
@@ -44,10 +47,6 @@
 namespace llvm {
 namespace exegesis {
 
-static cl::OptionCategory Options("llvm-exegesis options");
-static cl::OptionCategory BenchmarkOptions("llvm-exegesis benchmark options");
-static cl::OptionCategory AnalysisOptions("llvm-exegesis analysis options");
-
 static cl::opt<int> OpcodeIndex(
     "opcode-index",
     cl::desc("opcode to measure, by index, or -1 to measure all opcodes"),
@@ -87,7 +86,8 @@
 static cl::opt<exegesis::InstructionBenchmark::ResultAggregationModeE>
     ResultAggMode(
         "result-aggregation-mode",
-        cl::desc("How to aggregate multi-values result"), cl::cat(Options),
+        cl::desc("How to aggregate multi-values result"),
+        cl::cat(BenchmarkOptions),
         cl::values(clEnumValN(exegesis::InstructionBenchmark::Min, "min",
                               "Keep min reading"),
                    clEnumValN(exegesis::InstructionBenchmark::Max, "max",
@@ -111,6 +111,35 @@
                    "All of the above and take the minimum of measurements")),
     cl::init(exegesis::InstructionBenchmark::Duplicate));
 
+static cl::opt<bool> BenchmarkMeasurementsPrintProgress(
+    "measurements-print-progress",
+    cl::desc("Produce progress indicator when performing measurements"),
+    cl::cat(BenchmarkOptions), cl::init(false));
+
+static cl::opt<exegesis::BenchmarkPhaseSelectorE> BenchmarkPhaseSelector(
+    "benchmark-phase",
+    cl::desc(
+        "it is possible to stop the benchmarking process after some phase"),
+    cl::cat(BenchmarkOptions),
+    cl::values(
+        clEnumValN(exegesis::BenchmarkPhaseSelectorE::PrepareSnippet,
+                   "prepare-snippet",
+                   "Only generate the minimal instruction sequence"),
+        clEnumValN(exegesis::BenchmarkPhaseSelectorE::PrepareAndAssembleSnippet,
+                   "prepare-and-assemble-snippet",
+                   "Same as prepare-snippet, but also dumps an excerpt of the "
+                   "sequence (hex encoded)"),
+        clEnumValN(exegesis::BenchmarkPhaseSelectorE::AssembleMeasuredCode,
+                   "assemble-measured-code",
+                   "Same as prepare-and-assemble-snippet, but also creates the "
+                   "full sequence "
+                   "that can be dumped to a file using --dump-object-to-disk"),
+        clEnumValN(
+            exegesis::BenchmarkPhaseSelectorE::Measure, "measure",
+            "Same as prepare-measured-code, but also runs the measurement "
+            "(default)")),
+    cl::init(exegesis::BenchmarkPhaseSelectorE::Measure));
+
 static cl::opt<unsigned>
     NumRepetitions("num-repetitions",
                    cl::desc("number of time to repeat the asm snippet"),
@@ -134,6 +163,18 @@
     cl::desc("ignore instructions that do not define a sched class"),
     cl::cat(BenchmarkOptions), cl::init(false));
 
+static cl::opt<exegesis::InstructionBenchmarkFilter> AnalysisSnippetFilter(
+    "analysis-filter", cl::desc("Filter the benchmarks before analysing them"),
+    cl::cat(BenchmarkOptions),
+    cl::values(
+        clEnumValN(exegesis::InstructionBenchmarkFilter::All, "all",
+                   "Keep all benchmarks (default)"),
+        clEnumValN(exegesis::InstructionBenchmarkFilter::RegOnly, "reg-only",
+                   "Keep only those benchmarks that do *NOT* involve memory"),
+        clEnumValN(exegesis::InstructionBenchmarkFilter::WithMem, "mem-only",
+                   "Keep only the benchmarks that *DO* involve memory")),
+    cl::init(exegesis::InstructionBenchmarkFilter::All));
+
 static cl::opt<exegesis::InstructionBenchmarkClustering::ModeE>
     AnalysisClusteringAlgorithm(
         "analysis-clustering", cl::desc("the clustering algorithm to use"),
@@ -177,16 +218,29 @@
              "instead show only such unstable opcodes"),
     cl::cat(AnalysisOptions), cl::init(false));
 
-static cl::opt<std::string> CpuName(
-    "mcpu",
-    cl::desc("cpu name to use for pfm counters, leave empty to autodetect"),
-    cl::cat(Options), cl::init(""));
+static cl::opt<bool> AnalysisOverrideBenchmarksTripleAndCpu(
+    "analysis-override-benchmark-triple-and-cpu",
+    cl::desc("By default, we analyze the benchmarks for the triple/CPU they "
+             "were measured for, but if you want to analyze them for some "
+             "other combination (specified via -mtriple/-mcpu), you can "
+             "pass this flag."),
+    cl::cat(AnalysisOptions), cl::init(false));
 
-static cl::opt<bool>
-    DumpObjectToDisk("dump-object-to-disk",
-                     cl::desc("dumps the generated benchmark object to disk "
-                              "and prints a message to access it"),
-                     cl::cat(BenchmarkOptions), cl::init(true));
+static cl::opt<std::string>
+    TripleName("mtriple",
+               cl::desc("Target triple. See -version for available targets"),
+               cl::cat(Options));
+
+static cl::opt<std::string>
+    MCPU("mcpu",
+         cl::desc("Target a specific cpu type (-mcpu=help for details)"),
+         cl::value_desc("cpu-name"), cl::cat(Options), cl::init("native"));
+
+static cl::opt<bool> DumpObjectToDisk(
+    "dump-object-to-disk",
+    cl::desc("dumps the generated benchmark object to disk "
+             "and prints a message to access it (default = false)"),
+    cl::cat(BenchmarkOptions), cl::init(false));
 
 static ExitOnError ExitOnErr("llvm-exegesis error: ");
 
@@ -213,7 +267,7 @@
 // Checks that only one of OpcodeNames, OpcodeIndex or SnippetsFile is provided,
 // and returns the opcode indices or {} if snippets should be read from
 // `SnippetsFile`.
-static std::vector<unsigned> getOpcodesOrDie(const MCInstrInfo &MCInstrInfo) {
+static std::vector<unsigned> getOpcodesOrDie(const LLVMState &State) {
   const size_t NumSetFlags = (OpcodeNames.empty() ? 0 : 1) +
                              (OpcodeIndex == 0 ? 0 : 1) +
                              (SnippetsFile.empty() ? 0 : 1);
@@ -228,21 +282,25 @@
     return {static_cast<unsigned>(OpcodeIndex)};
   if (OpcodeIndex < 0) {
     std::vector<unsigned> Result;
-    for (unsigned I = 1, E = MCInstrInfo.getNumOpcodes(); I < E; ++I)
+    unsigned NumOpcodes = State.getInstrInfo().getNumOpcodes();
+    Result.reserve(NumOpcodes);
+    for (unsigned I = 0, E = NumOpcodes; I < E; ++I)
       Result.push_back(I);
     return Result;
   }
   // Resolve opcode name -> opcode.
-  const auto ResolveName = [&MCInstrInfo](StringRef OpcodeName) -> unsigned {
-    for (unsigned I = 1, E = MCInstrInfo.getNumOpcodes(); I < E; ++I)
-      if (MCInstrInfo.getName(I) == OpcodeName)
-        return I;
+  const auto ResolveName = [&State](StringRef OpcodeName) -> unsigned {
+    const auto &Map = State.getOpcodeNameToOpcodeIdxMapping();
+    auto I = Map.find(OpcodeName);
+    if (I != Map.end())
+      return I->getSecond();
     return 0u;
   };
   SmallVector<StringRef, 2> Pieces;
   StringRef(OpcodeNames.getValue())
       .split(Pieces, ",", /* MaxSplit */ -1, /* KeepEmpty */ false);
   std::vector<unsigned> Result;
+  Result.reserve(Pieces.size());
   for (const StringRef &OpcodeName : Pieces) {
     if (unsigned Opcode = ResolveName(OpcodeName))
       Result.push_back(Opcode);
@@ -290,33 +348,105 @@
   return Benchmarks;
 }
 
+static void runBenchmarkConfigurations(
+    const LLVMState &State, ArrayRef<BenchmarkCode> Configurations,
+    ArrayRef<std::unique_ptr<const SnippetRepetitor>> Repetitors,
+    const BenchmarkRunner &Runner) {
+  assert(!Configurations.empty() && "Don't have any configurations to run.");
+  std::optional<raw_fd_ostream> FileOstr;
+  if (BenchmarkFile != "-") {
+    int ResultFD = 0;
+    // Create output file or open existing file and truncate it, once.
+    ExitOnErr(errorCodeToError(openFileForWrite(BenchmarkFile, ResultFD,
+                                                sys::fs::CD_CreateAlways,
+                                                sys::fs::OF_TextWithCRLF)));
+    FileOstr.emplace(ResultFD, true /*shouldClose*/);
+  }
+  raw_ostream &Ostr = FileOstr ? *FileOstr : outs();
+
+  std::optional<ProgressMeter<>> Meter;
+  if (BenchmarkMeasurementsPrintProgress)
+    Meter.emplace(Configurations.size());
+  for (const BenchmarkCode &Conf : Configurations) {
+    ProgressMeter<>::ProgressMeterStep MeterStep(Meter ? &*Meter : nullptr);
+    SmallVector<InstructionBenchmark, 2> AllResults;
+
+    for (const std::unique_ptr<const SnippetRepetitor> &Repetitor :
+         Repetitors) {
+      auto RC = ExitOnErr(Runner.getRunnableConfiguration(
+          Conf, NumRepetitions, LoopBodySize, *Repetitor));
+      AllResults.emplace_back(
+          ExitOnErr(Runner.runConfiguration(std::move(RC), DumpObjectToDisk)));
+    }
+    InstructionBenchmark &Result = AllResults.front();
+
+    // If any of our measurements failed, pretend they all have failed.
+    if (AllResults.size() > 1 &&
+        any_of(AllResults, [](const InstructionBenchmark &R) {
+          return R.Measurements.empty();
+        }))
+      Result.Measurements.clear();
+
+    if (RepetitionMode == InstructionBenchmark::RepetitionModeE::AggregateMin) {
+      for (const InstructionBenchmark &OtherResult :
+           ArrayRef<InstructionBenchmark>(AllResults).drop_front()) {
+        llvm::append_range(Result.AssembledSnippet,
+                           OtherResult.AssembledSnippet);
+        // Aggregate measurements, but only iff all measurements succeeded.
+        if (Result.Measurements.empty())
+          continue;
+        assert(OtherResult.Measurements.size() == Result.Measurements.size() &&
+               "Expected to have identical number of measurements.");
+        for (auto I : zip(Result.Measurements, OtherResult.Measurements)) {
+          BenchmarkMeasure &Measurement = std::get<0>(I);
+          const BenchmarkMeasure &NewMeasurement = std::get<1>(I);
+          assert(Measurement.Key == NewMeasurement.Key &&
+                 "Expected measurements to be symmetric");
+
+          Measurement.PerInstructionValue =
+              std::min(Measurement.PerInstructionValue,
+                       NewMeasurement.PerInstructionValue);
+          Measurement.PerSnippetValue = std::min(
+              Measurement.PerSnippetValue, NewMeasurement.PerSnippetValue);
+        }
+      }
+    }
+
+    ExitOnFileError(BenchmarkFile, Result.writeYamlTo(State, Ostr));
+  }
+}
+
 void benchmarkMain() {
+  if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure) {
 #ifndef HAVE_LIBPFM
-  ExitWithError("benchmarking unavailable, LLVM was built without libpfm.");
+    ExitWithError(
+        "benchmarking unavailable, LLVM was built without libpfm. You can pass "
+        "--skip-measurements to skip the actual benchmarking.");
+#else
+    if (exegesis::pfm::pfmInitialize())
+      ExitWithError("cannot initialize libpfm");
 #endif
+  }
 
-  if (exegesis::pfm::pfmInitialize())
-    ExitWithError("cannot initialize libpfm");
+  InitializeAllAsmPrinters();
+  InitializeAllAsmParsers();
+  InitializeAllExegesisTargets();
 
-  InitializeNativeTarget();
-  InitializeNativeTargetAsmPrinter();
-  InitializeNativeTargetAsmParser();
-  InitializeNativeExegesisTarget();
-
-  const LLVMState State(CpuName);
+  const LLVMState State = ExitOnErr(LLVMState::Create(TripleName, MCPU));
 
   // Preliminary check to ensure features needed for requested
   // benchmark mode are present on target CPU and/or OS.
-  ExitOnErr(State.getExegesisTarget().checkFeatureSupport());
+  if (BenchmarkPhaseSelector == BenchmarkPhaseSelectorE::Measure)
+    ExitOnErr(State.getExegesisTarget().checkFeatureSupport());
 
   const std::unique_ptr<BenchmarkRunner> Runner =
       ExitOnErr(State.getExegesisTarget().createBenchmarkRunner(
-          BenchmarkMode, State, ResultAggMode));
+          BenchmarkMode, State, BenchmarkPhaseSelector, ResultAggMode));
   if (!Runner) {
     ExitWithError("cannot create benchmark runner");
   }
 
-  const auto Opcodes = getOpcodesOrDie(State.getInstrInfo());
+  const auto Opcodes = getOpcodesOrDie(State);
 
   SmallVector<std::unique_ptr<const SnippetRepetitor>, 2> Repetitors;
   if (RepetitionMode != InstructionBenchmark::RepetitionModeE::AggregateMin)
@@ -370,11 +500,9 @@
   if (BenchmarkFile.empty())
     BenchmarkFile = "-";
 
-  for (const BenchmarkCode &Conf : Configurations) {
-    InstructionBenchmark Result = ExitOnErr(Runner->runConfiguration(
-        Conf, NumRepetitions, LoopBodySize, Repetitors, DumpObjectToDisk));
-    ExitOnFileError(BenchmarkFile, Result.writeYaml(State, BenchmarkFile));
-  }
+  if (!Configurations.empty())
+    runBenchmarkConfigurations(State, Configurations, Repetitors, *Runner);
+
   exegesis::pfm::pfmTerminate();
 }
 
@@ -398,6 +526,26 @@
     ExitOnFileError(OutputFilename, std::move(Err));
 }
 
+static void filterPoints(MutableArrayRef<InstructionBenchmark> Points,
+                         const MCInstrInfo &MCII) {
+  if (AnalysisSnippetFilter == exegesis::InstructionBenchmarkFilter::All)
+    return;
+
+  bool WantPointsWithMemOps =
+      AnalysisSnippetFilter == exegesis::InstructionBenchmarkFilter::WithMem;
+  for (InstructionBenchmark &Point : Points) {
+    if (!Point.Error.empty())
+      continue;
+    if (WantPointsWithMemOps ==
+        any_of(Point.Key.Instructions, [&MCII](const MCInst &Inst) {
+          const MCInstrDesc &MCDesc = MCII.get(Inst.getOpcode());
+          return MCDesc.mayLoad() || MCDesc.mayStore();
+        }))
+      continue;
+    Point.Error = "filtered out by user";
+  }
+}
+
 static void analysisMain() {
   ExitOnErr.setBanner("llvm-exegesis: ");
   if (BenchmarkFile.empty())
@@ -410,44 +558,58 @@
         "and --analysis-inconsistencies-output-file must be specified");
   }
 
-  InitializeNativeTarget();
-  InitializeNativeTargetAsmPrinter();
-  InitializeNativeTargetDisassembler();
+  InitializeAllAsmPrinters();
+  InitializeAllDisassemblers();
+  InitializeAllExegesisTargets();
+
+  auto MemoryBuffer = ExitOnFileError(
+      BenchmarkFile,
+      errorOrToExpected(MemoryBuffer::getFile(BenchmarkFile, /*IsText=*/true)));
+
+  const auto TriplesAndCpus = ExitOnFileError(
+      BenchmarkFile,
+      InstructionBenchmark::readTriplesAndCpusFromYamls(*MemoryBuffer));
+  if (TriplesAndCpus.empty()) {
+    errs() << "no benchmarks to analyze\n";
+    return;
+  }
+  if (TriplesAndCpus.size() > 1) {
+    ExitWithError("analysis file contains benchmarks from several CPUs. This "
+                  "is unsupported.");
+  }
+  auto TripleAndCpu = *TriplesAndCpus.begin();
+  if (AnalysisOverrideBenchmarksTripleAndCpu) {
+    llvm::errs() << "overridding file CPU name (" << TripleAndCpu.CpuName
+                 << ") with provided tripled (" << TripleName
+                 << ") and CPU name (" << MCPU << ")\n";
+    TripleAndCpu.LLVMTriple = TripleName;
+    TripleAndCpu.CpuName = MCPU;
+  }
+  llvm::errs() << "using Triple '" << TripleAndCpu.LLVMTriple << "' and CPU '"
+               << TripleAndCpu.CpuName << "'\n";
 
   // Read benchmarks.
-  const LLVMState State("");
-  const std::vector<InstructionBenchmark> Points = ExitOnFileError(
-      BenchmarkFile, InstructionBenchmark::readYamls(State, BenchmarkFile));
+  const LLVMState State = ExitOnErr(
+      LLVMState::Create(TripleAndCpu.LLVMTriple, TripleAndCpu.CpuName));
+  std::vector<InstructionBenchmark> Points = ExitOnFileError(
+      BenchmarkFile, InstructionBenchmark::readYamls(State, *MemoryBuffer));
 
   outs() << "Parsed " << Points.size() << " benchmark points\n";
   if (Points.empty()) {
     errs() << "no benchmarks to analyze\n";
     return;
   }
-  // FIXME: Check that all points have the same triple/cpu.
   // FIXME: Merge points from several runs (latency and uops).
 
-  std::string Error;
-  const auto *TheTarget =
-      TargetRegistry::lookupTarget(Points[0].LLVMTriple, Error);
-  if (!TheTarget) {
-    errs() << "unknown target '" << Points[0].LLVMTriple << "'\n";
-    return;
-  }
-
-  std::unique_ptr<MCSubtargetInfo> SubtargetInfo(
-      TheTarget->createMCSubtargetInfo(Points[0].LLVMTriple, CpuName, ""));
-
-  std::unique_ptr<MCInstrInfo> InstrInfo(TheTarget->createMCInstrInfo());
-  assert(InstrInfo && "Unable to create instruction info!");
+  filterPoints(Points, State.getInstrInfo());
 
   const auto Clustering = ExitOnErr(InstructionBenchmarkClustering::create(
       Points, AnalysisClusteringAlgorithm, AnalysisDbscanNumPoints,
-      AnalysisClusteringEpsilon, SubtargetInfo.get(), InstrInfo.get()));
+      AnalysisClusteringEpsilon, &State.getSubtargetInfo(),
+      &State.getInstrInfo()));
 
-  const Analysis Analyzer(
-      *TheTarget, std::move(SubtargetInfo), std::move(InstrInfo), Clustering,
-      AnalysisInconsistencyEpsilon, AnalysisDisplayUnstableOpcodes, CpuName);
+  const Analysis Analyzer(State, Clustering, AnalysisInconsistencyEpsilon,
+                          AnalysisDisplayUnstableOpcodes);
 
   maybeRunAnalysis<Analysis::PrintClusters>(Analyzer, "analysis clusters",
                                             AnalysisClustersOutputFile);
@@ -461,7 +623,27 @@
 
 int main(int Argc, char **Argv) {
   using namespace llvm;
-  cl::ParseCommandLineOptions(Argc, Argv, "");
+
+  InitLLVM X(Argc, Argv);
+
+  // Initialize targets so we can print them when flag --version is specified.
+  InitializeAllTargetInfos();
+  InitializeAllTargets();
+  InitializeAllTargetMCs();
+
+  // Register the Target and CPU printer for --version.
+  cl::AddExtraVersionPrinter(sys::printDefaultTargetAndDetectedCPU);
+
+  // Enable printing of available targets when flag --version is specified.
+  cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
+
+  cl::HideUnrelatedOptions({&llvm::exegesis::Options,
+                            &llvm::exegesis::BenchmarkOptions,
+                            &llvm::exegesis::AnalysisOptions});
+
+  cl::ParseCommandLineOptions(Argc, Argv,
+                              "llvm host machine instruction characteristics "
+                              "measurment and analysis.\n");
 
   exegesis::ExitOnErr.setExitCodeMapper([](const Error &Err) {
     if (Err.isA<exegesis::ClusteringError>())
diff --git a/src/llvm-project/llvm/tools/llvm-extract/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-extract/CMakeLists.txt
index ce2a78d..4521b5e 100644
--- a/src/llvm-project/llvm/tools/llvm-extract/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-extract/CMakeLists.txt
@@ -1,8 +1,11 @@
 set(LLVM_LINK_COMPONENTS
+  Analysis
   BitWriter
   Core
   IPO
   IRReader
+  IRPrinter
+  Passes
   Support
   )
 
diff --git a/src/llvm-project/llvm/tools/llvm-extract/llvm-extract.cpp b/src/llvm-project/llvm/tools/llvm-extract/llvm-extract.cpp
index ffd2a39..a879c20 100644
--- a/src/llvm-project/llvm/tools/llvm-extract/llvm-extract.cpp
+++ b/src/llvm-project/llvm/tools/llvm-extract/llvm-extract.cpp
@@ -18,10 +18,10 @@
 #include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IRPrinter/IRPrintingPasses.h"
 #include "llvm/IRReader/IRReader.h"
-#include "llvm/Pass.h"
+#include "llvm/Passes/PassBuilder.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
@@ -31,8 +31,14 @@
 #include "llvm/Support/SystemUtils.h"
 #include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Transforms/IPO.h"
+#include "llvm/Transforms/IPO/BlockExtractor.h"
+#include "llvm/Transforms/IPO/ExtractGV.h"
+#include "llvm/Transforms/IPO/GlobalDCE.h"
+#include "llvm/Transforms/IPO/StripDeadPrototypes.h"
+#include "llvm/Transforms/IPO/StripSymbols.h"
 #include <memory>
 #include <utility>
+
 using namespace llvm;
 
 cl::OptionCategory ExtractCat("llvm-extract Options");
@@ -317,9 +323,22 @@
 
   {
     std::vector<GlobalValue *> Gvs(GVs.begin(), GVs.end());
-    legacy::PassManager Extract;
-    Extract.add(createGVExtractionPass(Gvs, DeleteFn, KeepConstInit));
-    Extract.run(*M);
+    LoopAnalysisManager LAM;
+    FunctionAnalysisManager FAM;
+    CGSCCAnalysisManager CGAM;
+    ModuleAnalysisManager MAM;
+
+    PassBuilder PB;
+
+    PB.registerModuleAnalyses(MAM);
+    PB.registerCGSCCAnalyses(CGAM);
+    PB.registerFunctionAnalyses(FAM);
+    PB.registerLoopAnalyses(LAM);
+    PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+    ModulePassManager PM;
+    PM.addPass(ExtractGVPass(Gvs, DeleteFn, KeepConstInit));
+    PM.run(*M, MAM);
 
     // Now that we have all the GVs we want, mark the module as fully
     // materialized.
@@ -331,9 +350,9 @@
   // functions.
   if (!ExtractBlocks.empty()) {
     // Figure out which BasicBlocks we should extract.
-    SmallVector<SmallVector<BasicBlock *, 16>, 4> GroupOfBBs;
+    std::vector<std::vector<BasicBlock *>> GroupOfBBs;
     for (auto &P : BBMap) {
-      SmallVector<BasicBlock *, 16> BBs;
+      std::vector<BasicBlock *> BBs;
       for (StringRef BBName : P.second) {
         // The function has been materialized, so add its matching basic blocks
         // to the block extractor list, or fail if a name is not found.
@@ -351,19 +370,45 @@
       GroupOfBBs.push_back(BBs);
     }
 
-    legacy::PassManager PM;
-    PM.add(createBlockExtractorPass(GroupOfBBs, true));
-    PM.run(*M);
+    LoopAnalysisManager LAM;
+    FunctionAnalysisManager FAM;
+    CGSCCAnalysisManager CGAM;
+    ModuleAnalysisManager MAM;
+
+    PassBuilder PB;
+
+    PB.registerModuleAnalyses(MAM);
+    PB.registerCGSCCAnalyses(CGAM);
+    PB.registerFunctionAnalyses(FAM);
+    PB.registerLoopAnalyses(LAM);
+    PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+    ModulePassManager PM;
+    PM.addPass(BlockExtractorPass(std::move(GroupOfBBs), true));
+    PM.run(*M, MAM);
   }
 
   // In addition to deleting all other functions, we also want to spiff it
   // up a little bit.  Do this now.
-  legacy::PassManager Passes;
 
+  LoopAnalysisManager LAM;
+  FunctionAnalysisManager FAM;
+  CGSCCAnalysisManager CGAM;
+  ModuleAnalysisManager MAM;
+
+  PassBuilder PB;
+
+  PB.registerModuleAnalyses(MAM);
+  PB.registerCGSCCAnalyses(CGAM);
+  PB.registerFunctionAnalyses(FAM);
+  PB.registerLoopAnalyses(LAM);
+  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+  ModulePassManager PM;
   if (!DeleteFn)
-    Passes.add(createGlobalDCEPass());           // Delete unreachable globals
-  Passes.add(createStripDeadDebugInfoPass());    // Remove dead debug info
-  Passes.add(createStripDeadPrototypesPass());   // Remove dead func decls
+    PM.addPass(GlobalDCEPass());
+  PM.addPass(StripDeadDebugInfoPass());
+  PM.addPass(StripDeadPrototypesPass());
 
   std::error_code EC;
   ToolOutputFile Out(OutputFilename, EC, sys::fs::OF_None);
@@ -373,12 +418,11 @@
   }
 
   if (OutputAssembly)
-    Passes.add(
-        createPrintModulePass(Out.os(), "", PreserveAssemblyUseListOrder));
+    PM.addPass(PrintModulePass(Out.os(), "", PreserveAssemblyUseListOrder));
   else if (Force || !CheckBitcodeOutputToConsole(Out.os()))
-    Passes.add(createBitcodeWriterPass(Out.os(), PreserveBitcodeUseListOrder));
+    PM.addPass(BitcodeWriterPass(Out.os(), PreserveBitcodeUseListOrder));
 
-  Passes.run(*M.get());
+  PM.run(*M, MAM);
 
   // Declare success.
   Out.keep();
diff --git a/src/llvm-project/llvm/tools/llvm-go/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-go/CMakeLists.txt
deleted file mode 100644
index 20393f7..0000000
--- a/src/llvm-project/llvm/tools/llvm-go/CMakeLists.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-if(LLVM_BINDINGS MATCHES "go")
-  set(binpath ${CMAKE_BINARY_DIR}/bin/llvm-go${CMAKE_EXECUTABLE_SUFFIX})
-  add_custom_command(OUTPUT ${binpath}
-    COMMAND ${GO_EXECUTABLE} build -o ${binpath} llvm-go.go
-    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/llvm-go.go
-    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
-    COMMENT "Building Go executable llvm-go")
-  add_custom_target(llvm-go ALL DEPENDS ${binpath})
-endif()
diff --git a/src/llvm-project/llvm/tools/llvm-go/llvm-go.go b/src/llvm-project/llvm/tools/llvm-go/llvm-go.go
deleted file mode 100644
index dc928b8..0000000
--- a/src/llvm-project/llvm/tools/llvm-go/llvm-go.go
+++ /dev/null
@@ -1,315 +0,0 @@
-//===-- llvm-go.go - go tool wrapper for LLVM -----------------------------===//
-//
-// 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 tool lets us build LLVM components within the tree by setting up a
-// $GOPATH that resembles a tree fetched in the normal way with "go get".
-//
-//===----------------------------------------------------------------------===//
-
-package main
-
-import (
-	"fmt"
-	"io/ioutil"
-	"os"
-	"os/exec"
-	"path/filepath"
-	"runtime"
-	"strings"
-)
-
-const (
-	linkmodeComponentLibs = "component-libs"
-	linkmodeDylib         = "dylib"
-)
-
-type pkg struct {
-	llvmpath, pkgpath string
-}
-
-var packages = []pkg{
-	{"bindings/go/llvm", "llvm.org/llvm/bindings/go/llvm"},
-}
-
-type compilerFlags struct {
-	cpp, cxx, ld string
-}
-
-var components = []string{
-	"all-targets",
-	"analysis",
-	"asmparser",
-	"asmprinter",
-	"bitreader",
-	"bitwriter",
-	"codegen",
-	"core",
-	"coroutines",
-	"debuginfodwarf",
-	"executionengine",
-	"instrumentation",
-	"interpreter",
-	"ipo",
-	"irreader",
-	"linker",
-	"mc",
-	"mcjit",
-	"objcarcopts",
-	"option",
-	"profiledata",
-	"scalaropts",
-	"support",
-	"target",
-}
-
-func llvmConfig(args ...string) string {
-	configpath := os.Getenv("LLVM_CONFIG")
-	if configpath == "" {
-		bin, _ := filepath.Split(os.Args[0])
-		configpath = filepath.Join(bin, "llvm-config")
-	}
-
-	cmd := exec.Command(configpath, args...)
-	cmd.Stderr = os.Stderr
-	out, err := cmd.Output()
-	if err != nil {
-		panic(err.Error())
-	}
-
-	outstr := string(out)
-	outstr = strings.TrimSuffix(outstr, "\n")
-	outstr = strings.Replace(outstr, "\n", " ", -1)
-	return outstr
-}
-
-func llvmFlags() compilerFlags {
-	args := append([]string{"--ldflags", "--libs", "--system-libs"}, components...)
-	ldflags := llvmConfig(args...)
-	stdLibOption := ""
-	if strings.Contains(llvmConfig("--cxxflags"), "-stdlib=libc++") {
-		// If libc++ is used to build LLVM libraries, -stdlib=libc++ is
-		// needed to resolve dependent symbols
-		stdLibOption = "-stdlib=libc++"
-	}
-	if runtime.GOOS == "aix" {
-		// AIX linker does not honour `-rpath`, the closest substitution
-		// is `-blibpath`
-		ldflags = "-Wl,-blibpath:" + llvmConfig("--libdir") + " " + ldflags
-	} else if runtime.GOOS != "darwin" {
-		// OS X doesn't like -rpath with cgo. See:
-		// https://github.com/golang/go/issues/7293
-		ldflags = "-Wl,-rpath," + llvmConfig("--libdir") + " " + ldflags
-	}
-	return compilerFlags{
-		cpp: llvmConfig("--cppflags"),
-		cxx: "-std=c++14" + " " + stdLibOption,
-		ld:  ldflags,
-	}
-}
-
-func addTag(args []string, tag string) []string {
-	args = append([]string{}, args...)
-	addedTag := false
-	for i, a := range args {
-		if strings.HasPrefix(a, "-tags=") {
-			args[i] = a + " " + tag
-			addedTag = true
-		} else if a == "-tags" && i+1 < len(args) {
-			args[i+1] = args[i+1] + " " + tag
-			addedTag = true
-		}
-	}
-	if !addedTag {
-		args = append([]string{args[0], "-tags", tag}, args[1:]...)
-	}
-	return args
-}
-
-func printComponents() {
-	fmt.Println(strings.Join(components, " "))
-}
-
-func printConfig() {
-	flags := llvmFlags()
-
-	fmt.Printf(`// +build !byollvm
-
-// This file is generated by llvm-go, do not edit.
-
-package llvm
-
-/*
-#cgo CPPFLAGS: %s
-#cgo CXXFLAGS: %s
-#cgo LDFLAGS: %s
-*/
-import "C"
-
-type (run_build_sh int)
-`, flags.cpp, flags.cxx, flags.ld)
-}
-
-func runGoWithLLVMEnv(args []string, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags string, packages []pkg) {
-	args = addTag(args, "byollvm")
-
-	srcdir := llvmConfig("--src-root")
-
-	tmpgopath, err := ioutil.TempDir("", "gopath")
-	if err != nil {
-		panic(err.Error())
-	}
-
-	for _, p := range packages {
-		path := filepath.Join(tmpgopath, "src", p.pkgpath)
-		err := os.MkdirAll(filepath.Dir(path), os.ModePerm)
-		if err != nil {
-			panic(err.Error())
-		}
-
-		abspath := p.llvmpath
-		if !filepath.IsAbs(abspath) {
-			abspath = filepath.Join(srcdir, abspath)
-		}
-
-		err = os.Symlink(abspath, path)
-		if err != nil {
-			panic(err.Error())
-		}
-	}
-
-	newpath := os.Getenv("PATH")
-
-	newgopathlist := []string{tmpgopath}
-	newgopathlist = append(newgopathlist, filepath.SplitList(os.Getenv("GOPATH"))...)
-	newgopath := strings.Join(newgopathlist, string(filepath.ListSeparator))
-
-	flags := llvmFlags()
-
-	newenv := []string{
-		"CC=" + cc,
-		"CXX=" + cxx,
-		"CGO_CPPFLAGS=" + flags.cpp + " " + cppflags,
-		"CGO_CXXFLAGS=" + flags.cxx + " " + cxxflags,
-		"CGO_LDFLAGS=" + flags.ld + " " + ldflags,
-		"GOPATH=" + newgopath,
-		"PATH=" + newpath,
-	}
-	if llgo != "" {
-		newenv = append(newenv, "GCCGO="+llgo)
-	}
-
-	for _, v := range os.Environ() {
-		if !strings.HasPrefix(v, "CC=") &&
-			!strings.HasPrefix(v, "CXX=") &&
-			!strings.HasPrefix(v, "CGO_CPPFLAGS=") &&
-			!strings.HasPrefix(v, "CGO_CXXFLAGS=") &&
-			!strings.HasPrefix(v, "CGO_LDFLAGS=") &&
-			!strings.HasPrefix(v, "GCCGO=") &&
-			!strings.HasPrefix(v, "GOPATH=") &&
-			!strings.HasPrefix(v, "PATH=") {
-			newenv = append(newenv, v)
-		}
-	}
-
-	gocmdpath, err := exec.LookPath(gocmd)
-	if err != nil {
-		panic(err.Error())
-	}
-
-	proc, err := os.StartProcess(gocmdpath, append([]string{gocmd}, args...),
-		&os.ProcAttr{
-			Env:   newenv,
-			Files: []*os.File{os.Stdin, os.Stdout, os.Stderr},
-		})
-	if err != nil {
-		panic(err.Error())
-	}
-	ps, err := proc.Wait()
-	if err != nil {
-		panic(err.Error())
-	}
-
-	os.RemoveAll(tmpgopath)
-
-	if !ps.Success() {
-		os.Exit(1)
-	}
-}
-
-func usage() {
-	fmt.Println(`Usage: llvm-go subcommand [flags]
-
-Available subcommands: build get install run test print-components print-config`)
-	os.Exit(0)
-}
-
-func main() {
-	cc := os.Getenv("CC")
-	cxx := os.Getenv("CXX")
-	cppflags := os.Getenv("CGO_CPPFLAGS")
-	cxxflags := os.Getenv("CGO_CXXFLAGS")
-	ldflags := os.Getenv("CGO_LDFLAGS")
-	gocmd := "go"
-	llgo := ""
-	packagesString := ""
-
-	flags := []struct {
-		name string
-		dest *string
-	}{
-		{"cc", &cc},
-		{"cxx", &cxx},
-		{"go", &gocmd},
-		{"llgo", &llgo},
-		{"cppflags", &cppflags},
-		{"ldflags", &ldflags},
-		{"packages", &packagesString},
-	}
-
-	args := os.Args[1:]
-LOOP:
-	for {
-		if len(args) == 0 {
-			usage()
-		}
-		for _, flag := range flags {
-			if strings.HasPrefix(args[0], flag.name+"=") {
-				*flag.dest = args[0][len(flag.name)+1:]
-				args = args[1:]
-				continue LOOP
-			}
-		}
-		break
-	}
-
-	packages := packages
-	if packagesString != "" {
-		for _, field := range strings.Fields(packagesString) {
-			pos := strings.IndexRune(field, '=')
-			if pos == -1 {
-				fmt.Fprintf(os.Stderr, "invalid packages value %q, expected 'pkgpath=llvmpath [pkgpath=llvmpath ...]'\n", packagesString)
-				os.Exit(1)
-			}
-			packages = append(packages, pkg{
-				pkgpath:  field[:pos],
-				llvmpath: field[pos+1:],
-			})
-		}
-	}
-
-	switch args[0] {
-	case "build", "get", "install", "run", "test":
-		runGoWithLLVMEnv(args, cc, cxx, gocmd, llgo, cppflags, cxxflags, ldflags, packages)
-	case "print-components":
-		printComponents()
-	case "print-config":
-		printConfig()
-	default:
-		usage()
-	}
-}
diff --git a/src/llvm-project/llvm/tools/llvm-gsymutil/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-gsymutil/CMakeLists.txt
index bda3c8d..5624005 100644
--- a/src/llvm-project/llvm/tools/llvm-gsymutil/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-gsymutil/CMakeLists.txt
@@ -6,6 +6,7 @@
   Object
   Support
   Target
+  TargetParser
   )
 
 add_llvm_tool(llvm-gsymutil
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 4eaab07..943c056 100644
--- a/src/llvm-project/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
+++ b/src/llvm-project/llvm/tools/llvm-gsymutil/llvm-gsymutil.cpp
@@ -41,6 +41,7 @@
 #include "llvm/DebugInfo/GSYM/InlineInfo.h"
 #include "llvm/DebugInfo/GSYM/LookupResult.h"
 #include "llvm/DebugInfo/GSYM/ObjectFileTransformer.h"
+#include <optional>
 
 using namespace llvm;
 using namespace gsym;
@@ -186,17 +187,17 @@
 ///
 /// \returns A valid image base address if we are able to extract one.
 template <class ELFT>
-static llvm::Optional<uint64_t>
+static std::optional<uint64_t>
 getImageBaseAddress(const object::ELFFile<ELFT> &ELFFile) {
   auto PhdrRangeOrErr = ELFFile.program_headers();
   if (!PhdrRangeOrErr) {
     consumeError(PhdrRangeOrErr.takeError());
-    return llvm::None;
+    return std::nullopt;
   }
   for (const typename ELFT::Phdr &Phdr : *PhdrRangeOrErr)
     if (Phdr.p_type == ELF::PT_LOAD)
       return (uint64_t)Phdr.p_vaddr;
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Determine the virtual address that is considered the base address of mach-o
@@ -207,7 +208,7 @@
 /// \param MachO A mach-o object file we will search.
 ///
 /// \returns A valid image base address if we are able to extract one.
-static llvm::Optional<uint64_t>
+static std::optional<uint64_t>
 getImageBaseAddress(const object::MachOObjectFile *MachO) {
   for (const auto &Command : MachO->load_commands()) {
     if (Command.C.cmd == MachO::LC_SEGMENT) {
@@ -222,7 +223,7 @@
         return SLC.vmaddr;
     }
   }
-  return llvm::None;
+  return std::nullopt;
 }
 
 /// Determine the virtual address that is considered the base address of an
@@ -237,7 +238,7 @@
 /// \param Obj An object file we will search.
 ///
 /// \returns A valid image base address if we are able to extract one.
-static llvm::Optional<uint64_t> getImageBaseAddress(object::ObjectFile &Obj) {
+static std::optional<uint64_t> getImageBaseAddress(object::ObjectFile &Obj) {
   if (const auto *MachO = dyn_cast<object::MachOObjectFile>(&Obj))
     return getImageBaseAddress(MachO);
   else if (const auto *ELFObj = dyn_cast<object::ELF32LEObjectFile>(&Obj))
@@ -248,7 +249,7 @@
     return getImageBaseAddress(ELFObj->getELFFile());
   else if (const auto *ELFObj = dyn_cast<object::ELF64BEObjectFile>(&Obj))
     return getImageBaseAddress(ELFObj->getELFFile());
-  return llvm::None;
+  return std::nullopt;
 }
 
 static llvm::Error handleObjectFile(ObjectFile &Obj,
@@ -285,7 +286,6 @@
   if (!DICtx)
     return createStringError(std::errc::invalid_argument,
                              "unable to create DWARF context");
-  logAllUnhandledErrors(DICtx->loadRegisterInfo(Obj), OS, "DwarfTransformer: ");
 
   // Make a DWARF transformer object and populate the ranges of the code
   // so we don't end up adding invalid functions to GSYM data.
@@ -480,7 +480,7 @@
 
     std::string InputLine;
     std::string CurrentGSYMPath;
-    llvm::Optional<Expected<GsymReader>> CurrentGsym;
+    std::optional<Expected<GsymReader>> CurrentGsym;
 
     while (std::getline(std::cin, InputLine)) {
       // Strip newline characters.
@@ -496,6 +496,7 @@
         CurrentGsym = GsymReader::openFile(GSYMPath);
         if (!*CurrentGsym)
           error(GSYMPath, CurrentGsym->takeError());
+        CurrentGSYMPath = GSYMPath;
       }
 
       uint64_t Addr;
diff --git a/src/llvm-project/llvm/tools/llvm-ifs/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-ifs/CMakeLists.txt
index 483610d..23bc1ec 100644
--- a/src/llvm-project/llvm/tools/llvm-ifs/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-ifs/CMakeLists.txt
@@ -1,8 +1,9 @@
 set(LLVM_LINK_COMPONENTS
   BinaryFormat
-  InterfaceStub  
+  InterfaceStub
   Object
   Support
+  TargetParser
   TextAPI
   ObjectYAML
   Option
@@ -18,4 +19,6 @@
 
 DEPENDS
   IFSOptsTableGen
+
+  GENERATE_DRIVER
   )
diff --git a/src/llvm-project/llvm/tools/llvm-ifs/ErrorCollector.h b/src/llvm-project/llvm/tools/llvm-ifs/ErrorCollector.h
index d3a814b..2b91e90 100644
--- a/src/llvm-project/llvm/tools/llvm-ifs/ErrorCollector.h
+++ b/src/llvm-project/llvm/tools/llvm-ifs/ErrorCollector.h
@@ -21,13 +21,12 @@
 #ifndef LLVM_TOOLS_LLVM_IFS_ERRORCOLLECTOR_H
 #define LLVM_TOOLS_LLVM_IFS_ERRORCOLLECTOR_H
 
+#include "llvm/Support/Error.h"
 #include "llvm/Support/raw_ostream.h"
 #include <vector>
 
 namespace llvm {
 
-class Error;
-
 namespace ifs {
 
 class ErrorCollector {
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 6082290..0ca9dfd 100644
--- a/src/llvm-project/llvm/tools/llvm-ifs/llvm-ifs.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ifs/llvm-ifs.cpp
@@ -32,6 +32,7 @@
 #include "llvm/TextAPI/InterfaceFile.h"
 #include "llvm/TextAPI/TextAPIReader.h"
 #include "llvm/TextAPI/TextAPIWriter.h"
+#include <optional>
 #include <set>
 #include <string>
 #include <vector>
@@ -59,11 +60,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#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
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -75,22 +79,24 @@
 #undef OPTION
 };
 
-class IFSOptTable : public opt::OptTable {
+class IFSOptTable : public opt::GenericOptTable {
 public:
-  IFSOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  IFSOptTable() : opt::GenericOptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 
 struct DriverConfig {
   std::vector<std::string> InputFilePaths;
 
-  Optional<FileFormat> InputFormat;
-  Optional<FileFormat> OutputFormat;
+  std::optional<FileFormat> InputFormat;
+  std::optional<FileFormat> OutputFormat;
 
-  Optional<std::string> HintIfsTarget;
-  Optional<std::string> OptTargetTriple;
-  Optional<IFSArch> OverrideArch;
-  Optional<IFSBitWidthType> OverrideBitWidth;
-  Optional<IFSEndiannessType> OverrideEndianness;
+  std::optional<std::string> HintIfsTarget;
+  std::optional<std::string> OptTargetTriple;
+  std::optional<IFSArch> OverrideArch;
+  std::optional<IFSBitWidthType> OverrideBitWidth;
+  std::optional<IFSEndiannessType> OverrideEndianness;
 
   bool StripIfsArch = false;
   bool StripIfsBitwidth = false;
@@ -102,12 +108,12 @@
 
   std::vector<std::string> Exclude;
 
-  Optional<std::string> SoName;
+  std::optional<std::string> SoName;
 
-  Optional<std::string> Output;
-  Optional<std::string> OutputElf;
-  Optional<std::string> OutputIfs;
-  Optional<std::string> OutputTbd;
+  std::optional<std::string> Output;
+  std::optional<std::string> OutputElf;
+  std::optional<std::string> OutputIfs;
+  std::optional<std::string> OutputTbd;
 
   bool WriteIfChanged = false;
 };
@@ -129,7 +135,7 @@
 }
 
 static Expected<std::unique_ptr<IFSStub>>
-readInputFile(Optional<FileFormat> &InputFormat, StringRef FilePath) {
+readInputFile(std::optional<FileFormat> &InputFormat, StringRef FilePath) {
   // Read in file.
   ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrError =
       MemoryBuffer::getFileOrSTDIN(FilePath, /*IsText=*/true);
@@ -305,10 +311,10 @@
   for (const opt::Arg *A : Args.filtered(OPT_INPUT))
     Config.InputFilePaths.push_back(A->getValue());
   if (const opt::Arg *A = Args.getLastArg(OPT_input_format_EQ)) {
-    Config.InputFormat = StringSwitch<Optional<FileFormat>>(A->getValue())
+    Config.InputFormat = StringSwitch<std::optional<FileFormat>>(A->getValue())
                              .Case("IFS", FileFormat::IFS)
                              .Case("ELF", FileFormat::ELF)
-                             .Default(None);
+                             .Default(std::nullopt);
     if (!Config.InputFormat)
       fatalError(Twine("invalid argument '") + A->getValue());
   }
@@ -318,11 +324,11 @@
                " option: Cannot find option named '" + OptionName + "'!");
   };
   if (const opt::Arg *A = Args.getLastArg(OPT_output_format_EQ)) {
-    Config.OutputFormat = StringSwitch<Optional<FileFormat>>(A->getValue())
+    Config.OutputFormat = StringSwitch<std::optional<FileFormat>>(A->getValue())
                               .Case("IFS", FileFormat::IFS)
                               .Case("ELF", FileFormat::ELF)
                               .Case("TBD", FileFormat::TBD)
-                              .Default(None);
+                              .Default(std::nullopt);
     if (!Config.OutputFormat)
       OptionNotFound("--output-format", A->getValue());
   }
@@ -340,10 +346,10 @@
   }
   if (const opt::Arg *A = Args.getLastArg(OPT_endianness_EQ)) {
     Config.OverrideEndianness =
-        StringSwitch<Optional<IFSEndiannessType>>(A->getValue())
+        StringSwitch<std::optional<IFSEndiannessType>>(A->getValue())
             .Case("little", IFSEndiannessType::Little)
             .Case("big", IFSEndiannessType::Big)
-            .Default(None);
+            .Default(std::nullopt);
     if (!Config.OverrideEndianness)
       OptionNotFound("--endianness", A->getValue());
   }
@@ -376,7 +382,7 @@
   return Config;
 }
 
-int main(int argc, char *argv[]) {
+int llvm_ifs_main(int argc, char **argv) {
   DriverConfig Config = parseArgs(argc, argv);
 
   if (Config.InputFilePaths.empty())
@@ -533,33 +539,32 @@
             << "Triple should be defined when output format is TBD";
         return -1;
       }
-      return writeTbdStub(llvm::Triple(Stub.Target.Triple.value()),
-                          Stub.Symbols, "TBD", Out);
+      return writeTbdStub(llvm::Triple(*Stub.Target.Triple), Stub.Symbols,
+                          "TBD", Out);
     }
     case FileFormat::IFS: {
       Stub.IfsVersion = IfsVersionCurrent;
-      if (Config.InputFormat.value() == FileFormat::ELF &&
-          Config.HintIfsTarget) {
+      if (*Config.InputFormat == FileFormat::ELF && Config.HintIfsTarget) {
         std::error_code HintEC(1, std::generic_category());
         IFSTarget HintTarget = parseTriple(*Config.HintIfsTarget);
-        if (Stub.Target.Arch.value() != HintTarget.Arch.value())
+        if (*Stub.Target.Arch != *HintTarget.Arch)
           fatalError(make_error<StringError>(
               "Triple hint does not match the actual architecture", HintEC));
-        if (Stub.Target.Endianness.value() != HintTarget.Endianness.value())
+        if (*Stub.Target.Endianness != *HintTarget.Endianness)
           fatalError(make_error<StringError>(
               "Triple hint does not match the actual endianness", HintEC));
-        if (Stub.Target.BitWidth.value() != HintTarget.BitWidth.value())
+        if (*Stub.Target.BitWidth != *HintTarget.BitWidth)
           fatalError(make_error<StringError>(
               "Triple hint does not match the actual bit width", HintEC));
 
         stripIFSTarget(Stub, true, false, false, false);
-        Stub.Target.Triple = Config.HintIfsTarget.value();
+        Stub.Target.Triple = *Config.HintIfsTarget;
       } else {
         stripIFSTarget(Stub, Config.StripIfsTarget, Config.StripIfsArch,
                        Config.StripIfsEndianness, Config.StripIfsBitwidth);
       }
       Error IFSWriteError =
-          writeIFS(Config.Output.value(), Stub, Config.WriteIfChanged);
+          writeIFS(*Config.Output, Stub, Config.WriteIfChanged);
       if (IFSWriteError)
         fatalError(std::move(IFSWriteError));
       break;
@@ -588,28 +593,27 @@
     }
     if (Config.OutputIfs) {
       Stub.IfsVersion = IfsVersionCurrent;
-      if (Config.InputFormat.value() == FileFormat::ELF &&
-          Config.HintIfsTarget) {
+      if (*Config.InputFormat == FileFormat::ELF && Config.HintIfsTarget) {
         std::error_code HintEC(1, std::generic_category());
         IFSTarget HintTarget = parseTriple(*Config.HintIfsTarget);
-        if (Stub.Target.Arch.value() != HintTarget.Arch.value())
+        if (*Stub.Target.Arch != *HintTarget.Arch)
           fatalError(make_error<StringError>(
               "Triple hint does not match the actual architecture", HintEC));
-        if (Stub.Target.Endianness.value() != HintTarget.Endianness.value())
+        if (*Stub.Target.Endianness != *HintTarget.Endianness)
           fatalError(make_error<StringError>(
               "Triple hint does not match the actual endianness", HintEC));
-        if (Stub.Target.BitWidth.value() != HintTarget.BitWidth.value())
+        if (*Stub.Target.BitWidth != *HintTarget.BitWidth)
           fatalError(make_error<StringError>(
               "Triple hint does not match the actual bit width", HintEC));
 
         stripIFSTarget(Stub, true, false, false, false);
-        Stub.Target.Triple = Config.HintIfsTarget.value();
+        Stub.Target.Triple = *Config.HintIfsTarget;
       } else {
         stripIFSTarget(Stub, Config.StripIfsTarget, Config.StripIfsArch,
                        Config.StripIfsEndianness, Config.StripIfsBitwidth);
       }
       Error IFSWriteError =
-          writeIFS(Config.OutputIfs.value(), Stub, Config.WriteIfChanged);
+          writeIFS(*Config.OutputIfs, Stub, Config.WriteIfChanged);
       if (IFSWriteError)
         fatalError(std::move(IFSWriteError));
     }
@@ -626,8 +630,8 @@
             << "Triple should be defined when output format is TBD";
         return -1;
       }
-      return writeTbdStub(llvm::Triple(Stub.Target.Triple.value()),
-                          Stub.Symbols, "TBD", Out);
+      return writeTbdStub(llvm::Triple(*Stub.Target.Triple), Stub.Symbols,
+                          "TBD", Out);
     }
   }
   return 0;
diff --git a/src/llvm-project/llvm/tools/llvm-isel-fuzzer/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-isel-fuzzer/CMakeLists.txt
index 32b6538..f30407a 100644
--- a/src/llvm-project/llvm/tools/llvm-isel-fuzzer/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-isel-fuzzer/CMakeLists.txt
@@ -17,6 +17,7 @@
     SelectionDAG
     Support
     Target
+    TargetParser
 )
 add_llvm_fuzzer(llvm-isel-fuzzer
   llvm-isel-fuzzer.cpp
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 599c414..dbcdba7 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
@@ -42,7 +42,7 @@
     OptLevel("O",
              cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
                       "(default = '-O2')"),
-             cl::Prefix, cl::init(' '));
+             cl::Prefix, cl::init('2'));
 
 static cl::opt<std::string>
 TargetTriple("mtriple", cl::desc("Override target triple for module"));
@@ -144,16 +144,12 @@
   std::string CPUStr = codegen::getCPUStr(),
               FeaturesStr = codegen::getFeaturesStr();
 
-  CodeGenOpt::Level OLvl = CodeGenOpt::Default;
-  switch (OptLevel) {
-  default:
+  CodeGenOpt::Level OLvl;
+  if (auto Level = CodeGenOpt::parseLevel(OptLevel)) {
+    OLvl = *Level;
+  } else {
     errs() << argv[0] << ": invalid optimization level.\n";
     return 1;
-  case ' ': break;
-  case '0': OLvl = CodeGenOpt::None; break;
-  case '1': OLvl = CodeGenOpt::Less; break;
-  case '2': OLvl = CodeGenOpt::Default; break;
-  case '3': OLvl = CodeGenOpt::Aggressive; break;
   }
 
   TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(TheTriple);
diff --git a/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt
index 65cc0c9..b7371e7 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/CMakeLists.txt
@@ -16,6 +16,7 @@
   OrcTargetProcess
   RuntimeDyld
   Support
+  TargetParser
   )
 
 add_llvm_tool(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 2e7b000..415aee7 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
@@ -25,8 +25,8 @@
 static bool isCOFFStubsSection(Section &S) { return S.getName() == "$__STUBS"; }
 
 static Expected<Edge &> getFirstRelocationEdge(LinkGraph &G, Block &B) {
-  auto EItr = std::find_if(B.edges().begin(), B.edges().end(),
-                           [](Edge &E) { return E.isRelocation(); });
+  auto EItr =
+      llvm::find_if(B.edges(), [](Edge &E) { return E.isRelocation(); });
   if (EItr == B.edges().end())
     return make_error<StringError>("GOT entry in " + G.getName() + ", \"" +
                                        B.getSection().getName() +
@@ -80,13 +80,12 @@
   for (auto &Sec : G.sections()) {
     LLVM_DEBUG({
       dbgs() << "  Section \"" << Sec.getName() << "\": "
-             << (llvm::empty(Sec.symbols()) ? "empty. skipping."
-                                            : "processing...")
+             << (Sec.symbols().empty() ? "empty. skipping." : "processing...")
              << "\n";
     });
 
     // Skip empty sections.
-    if (llvm::empty(Sec.symbols()))
+    if (Sec.symbols().empty())
       continue;
 
     if (FileInfo.SectionInfos.count(Sec.getName()))
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 d79dbc4..2b798f9 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
@@ -25,8 +25,8 @@
 static bool isELFStubsSection(Section &S) { return S.getName() == "$__STUBS"; }
 
 static Expected<Edge &> getFirstRelocationEdge(LinkGraph &G, Block &B) {
-  auto EItr = std::find_if(B.edges().begin(), B.edges().end(),
-                           [](Edge &E) { return E.isRelocation(); });
+  auto EItr =
+      llvm::find_if(B.edges(), [](Edge &E) { return E.isRelocation(); });
   if (EItr == B.edges().end())
     return make_error<StringError>("GOT entry in " + G.getName() + ", \"" +
                                        B.getSection().getName() +
@@ -82,13 +82,12 @@
   for (auto &Sec : G.sections()) {
     LLVM_DEBUG({
       dbgs() << "  Section \"" << Sec.getName() << "\": "
-             << (llvm::empty(Sec.symbols()) ? "empty. skipping."
-                                            : "processing...")
+             << (Sec.symbols().empty() ? "empty. skipping." : "processing...")
              << "\n";
     });
 
     // Skip empty sections.
-    if (llvm::empty(Sec.symbols()))
+    if (Sec.symbols().empty())
       continue;
 
     if (FileInfo.SectionInfos.count(Sec.getName()))
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 34246ca..71c83f2 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
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorSharedMemoryMapperService.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
 #include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleExecutorMemoryManager.h"
@@ -164,6 +165,9 @@
                 SimpleRemoteEPCServer::defaultBootstrapSymbols();
             S.services().push_back(
                 std::make_unique<rt_bootstrap::SimpleExecutorMemoryManager>());
+            S.services().push_back(
+                std::make_unique<
+                    rt_bootstrap::ExecutorSharedMemoryMapperService>());
             return Error::success();
           },
           InFD, OutFD));
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 ed7fd1a..bcb2f25 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
@@ -27,8 +27,8 @@
 }
 
 static Expected<Edge &> getFirstRelocationEdge(LinkGraph &G, Block &B) {
-  auto EItr = std::find_if(B.edges().begin(), B.edges().end(),
-                           [](Edge &E) { return E.isRelocation(); });
+  auto EItr =
+      llvm::find_if(B.edges(), [](Edge &E) { return E.isRelocation(); });
   if (EItr == B.edges().end())
     return make_error<StringError>("GOT entry in " + G.getName() + ", \"" +
                                        B.getSection().getName() +
@@ -84,13 +84,12 @@
   for (auto &Sec : G.sections()) {
     LLVM_DEBUG({
       dbgs() << "  Section \"" << Sec.getName() << "\": "
-             << (llvm::empty(Sec.symbols()) ? "empty. skipping."
-                                            : "processing...")
+             << (Sec.symbols().empty() ? "empty. skipping." : "processing...")
              << "\n";
     });
 
     // Skip empty sections.
-    if (llvm::empty(Sec.symbols()))
+    if (Sec.symbols().empty())
       continue;
 
     if (FileInfo.SectionInfos.count(Sec.getName()))
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 c0d36b3..4180be4 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.cpp
@@ -15,6 +15,8 @@
 #include "llvm-jitlink.h"
 
 #include "llvm/BinaryFormat/Magic.h"
+#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/ELFNixPlatform.h"
@@ -24,7 +26,9 @@
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
 #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
+#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
 #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/RegisterEHFrames.h"
 #include "llvm/MC/MCAsmInfo.h"
@@ -50,6 +54,7 @@
 #include "llvm/Support/Timer.h"
 
 #include <cstring>
+#include <deque>
 #include <list>
 #include <string>
 
@@ -93,6 +98,11 @@
                cl::desc("Link against library X with hidden visibility"),
                cl::cat(JITLinkCategory));
 
+static cl::opt<bool> SearchSystemLibrary(
+    "search-sys-lib",
+    cl::desc("Add system library paths to library search paths"),
+    cl::init(false), cl::cat(JITLinkCategory));
+
 static cl::opt<bool> NoExec("noexec", cl::desc("Do not execute loaded code"),
                             cl::init(false), cl::cat(JITLinkCategory));
 
@@ -228,6 +238,11 @@
                                cl::desc("Show FailedToMaterialize errors"),
                                cl::init(false), cl::cat(JITLinkCategory));
 
+static cl::opt<bool> UseSharedMemory(
+    "use-shared-memory",
+    cl::desc("Use shared memory to transfer generated code and data"),
+    cl::init(false), cl::cat(JITLinkCategory));
+
 static ExitOnError ExitOnErr;
 
 static LLVM_ATTRIBUTE_USED void linkComponents() {
@@ -388,11 +403,11 @@
     Sections.push_back(&S);
 
   llvm::sort(Sections, [](const Section *LHS, const Section *RHS) {
-    if (llvm::empty(LHS->symbols()) && llvm::empty(RHS->symbols()))
+    if (LHS->symbols().empty() && RHS->symbols().empty())
       return false;
-    if (llvm::empty(LHS->symbols()))
+    if (LHS->symbols().empty())
       return false;
-    if (llvm::empty(RHS->symbols()))
+    if (RHS->symbols().empty())
       return true;
     SectionRange LHSRange(*LHS);
     SectionRange RHSRange(*RHS);
@@ -401,7 +416,7 @@
 
   for (auto *S : Sections) {
     OS << S->getName() << " content:";
-    if (llvm::empty(S->symbols())) {
+    if (S->symbols().empty()) {
       OS << "\n  section empty\n";
       continue;
     }
@@ -446,248 +461,89 @@
   }
 }
 
-class JITLinkSlabAllocator final : public JITLinkMemoryManager {
-private:
-  struct FinalizedAllocInfo {
-    FinalizedAllocInfo(sys::MemoryBlock Mem,
-                       std::vector<shared::WrapperFunctionCall> DeallocActions)
-        : Mem(Mem), DeallocActions(std::move(DeallocActions)) {}
-    sys::MemoryBlock Mem;
-    std::vector<shared::WrapperFunctionCall> DeallocActions;
-  };
-
+// A memory mapper with a fake offset applied only used for -noexec testing
+class InProcessDeltaMapper final : public InProcessMemoryMapper {
 public:
-  static Expected<std::unique_ptr<JITLinkSlabAllocator>>
-  Create(uint64_t SlabSize) {
-    Error Err = Error::success();
-    std::unique_ptr<JITLinkSlabAllocator> Allocator(
-        new JITLinkSlabAllocator(SlabSize, Err));
-    if (Err)
-      return std::move(Err);
-    return std::move(Allocator);
-  }
+  InProcessDeltaMapper(size_t PageSize, uint64_t TargetAddr)
+      : InProcessMemoryMapper(PageSize), TargetMapAddr(TargetAddr),
+        DeltaAddr(0) {}
 
-  void allocate(const JITLinkDylib *JD, LinkGraph &G,
-                OnAllocatedFunction OnAllocated) override {
-
-    // Local class for allocation.
-    class IPMMAlloc : public InFlightAlloc {
-    public:
-      IPMMAlloc(JITLinkSlabAllocator &Parent, BasicLayout BL,
-                sys::MemoryBlock StandardSegs, sys::MemoryBlock FinalizeSegs)
-          : Parent(Parent), BL(std::move(BL)),
-            StandardSegs(std::move(StandardSegs)),
-            FinalizeSegs(std::move(FinalizeSegs)) {}
-
-      void finalize(OnFinalizedFunction OnFinalized) override {
-        if (auto Err = applyProtections()) {
-          OnFinalized(std::move(Err));
-          return;
-        }
-
-        auto DeallocActions = runFinalizeActions(BL.graphAllocActions());
-        if (!DeallocActions) {
-          OnFinalized(DeallocActions.takeError());
-          return;
-        }
-
-        if (auto Err = Parent.freeBlock(FinalizeSegs)) {
-          OnFinalized(
-              joinErrors(std::move(Err), runDeallocActions(*DeallocActions)));
-          return;
-        }
-
-        OnFinalized(FinalizedAlloc(ExecutorAddr::fromPtr(
-            new FinalizedAllocInfo(StandardSegs, std::move(*DeallocActions)))));
-      }
-
-      void abandon(OnAbandonedFunction OnAbandoned) override {
-        OnAbandoned(joinErrors(Parent.freeBlock(StandardSegs),
-                               Parent.freeBlock(FinalizeSegs)));
-      }
-
-    private:
-      Error applyProtections() {
-        for (auto &KV : BL.segments()) {
-          const auto &Group = KV.first;
-          auto &Seg = KV.second;
-
-          auto Prot = toSysMemoryProtectionFlags(Group.getMemProt());
-
-          uint64_t SegSize =
-              alignTo(Seg.ContentSize + Seg.ZeroFillSize, Parent.PageSize);
-          sys::MemoryBlock MB(Seg.WorkingMem, SegSize);
-          if (auto EC = sys::Memory::protectMappedMemory(MB, Prot))
-            return errorCodeToError(EC);
-          if (Prot & sys::Memory::MF_EXEC)
-            sys::Memory::InvalidateInstructionCache(MB.base(),
-                                                    MB.allocatedSize());
-        }
-        return Error::success();
-      }
-
-      JITLinkSlabAllocator &Parent;
-      BasicLayout BL;
-      sys::MemoryBlock StandardSegs;
-      sys::MemoryBlock FinalizeSegs;
-    };
-
-    BasicLayout BL(G);
-    auto SegsSizes = BL.getContiguousPageBasedLayoutSizes(PageSize);
-
-    if (!SegsSizes) {
-      OnAllocated(SegsSizes.takeError());
-      return;
-    }
-
-    char *AllocBase = nullptr;
-    {
-      std::lock_guard<std::mutex> Lock(SlabMutex);
-
-      if (SegsSizes->total() > SlabRemaining.allocatedSize()) {
-        OnAllocated(make_error<StringError>(
-            "Slab allocator out of memory: request for " +
-                formatv("{0:x}", SegsSizes->total()) +
-                " bytes exceeds remaining capacity of " +
-                formatv("{0:x}", SlabRemaining.allocatedSize()) + " bytes",
-            inconvertibleErrorCode()));
-        return;
-      }
-
-      AllocBase = reinterpret_cast<char *>(SlabRemaining.base());
-      SlabRemaining =
-          sys::MemoryBlock(AllocBase + SegsSizes->total(),
-                           SlabRemaining.allocatedSize() - SegsSizes->total());
-    }
-
-    sys::MemoryBlock StandardSegs(AllocBase, SegsSizes->StandardSegs);
-    sys::MemoryBlock FinalizeSegs(AllocBase + SegsSizes->StandardSegs,
-                                  SegsSizes->FinalizeSegs);
-
-    auto NextStandardSegAddr = ExecutorAddr::fromPtr(StandardSegs.base());
-    auto NextFinalizeSegAddr = ExecutorAddr::fromPtr(FinalizeSegs.base());
-
-    LLVM_DEBUG({
-      dbgs() << "JITLinkSlabAllocator allocated:\n";
-      if (SegsSizes->StandardSegs)
-        dbgs() << formatv("  [ {0:x16} -- {1:x16} ]", NextStandardSegAddr,
-                          NextStandardSegAddr + StandardSegs.allocatedSize())
-               << " to stardard segs\n";
-      else
-        dbgs() << "  no standard segs\n";
-      if (SegsSizes->FinalizeSegs)
-        dbgs() << formatv("  [ {0:x16} -- {1:x16} ]", NextFinalizeSegAddr,
-                          NextFinalizeSegAddr + FinalizeSegs.allocatedSize())
-               << " to finalize segs\n";
-      else
-        dbgs() << "  no finalize segs\n";
-    });
-
-    for (auto &KV : BL.segments()) {
-      auto &Group = KV.first;
-      auto &Seg = KV.second;
-
-      auto &SegAddr =
-          (Group.getMemDeallocPolicy() == MemDeallocPolicy::Standard)
-              ? NextStandardSegAddr
-              : NextFinalizeSegAddr;
-
-      LLVM_DEBUG({
-        dbgs() << "  " << Group << " -> " << formatv("{0:x16}", SegAddr)
-               << "\n";
-      });
-      Seg.WorkingMem = SegAddr.toPtr<char *>();
-      Seg.Addr = SegAddr + SlabDelta;
-
-      SegAddr += alignTo(Seg.ContentSize + Seg.ZeroFillSize, PageSize);
-
-      // Zero out the zero-fill memory.
-      if (Seg.ZeroFillSize != 0)
-        memset(Seg.WorkingMem + Seg.ContentSize, 0, Seg.ZeroFillSize);
-    }
-
-    if (auto Err = BL.apply()) {
-      OnAllocated(std::move(Err));
-      return;
-    }
-
-    OnAllocated(std::unique_ptr<InProcessMemoryManager::InFlightAlloc>(
-        new IPMMAlloc(*this, std::move(BL), std::move(StandardSegs),
-                      std::move(FinalizeSegs))));
-  }
-
-  void deallocate(std::vector<FinalizedAlloc> FinalizedAllocs,
-                  OnDeallocatedFunction OnDeallocated) override {
-    Error Err = Error::success();
-    for (auto &FA : FinalizedAllocs) {
-      std::unique_ptr<FinalizedAllocInfo> FAI(
-          FA.release().toPtr<FinalizedAllocInfo *>());
-
-      // FIXME: Run dealloc actions.
-
-      Err = joinErrors(std::move(Err), freeBlock(FAI->Mem));
-    }
-    OnDeallocated(std::move(Err));
-  }
-
-private:
-  JITLinkSlabAllocator(uint64_t SlabSize, Error &Err) {
-    ErrorAsOutParameter _(&Err);
-
-    if (!SlabPageSize) {
+  static Expected<std::unique_ptr<InProcessDeltaMapper>> Create() {
+    size_t PageSize = SlabPageSize;
+    if (!PageSize) {
       if (auto PageSizeOrErr = sys::Process::getPageSize())
         PageSize = *PageSizeOrErr;
-      else {
-        Err = PageSizeOrErr.takeError();
-        return;
-      }
-
-      if (PageSize == 0) {
-        Err = make_error<StringError>("Page size is zero",
-                                      inconvertibleErrorCode());
-        return;
-      }
-    } else
-      PageSize = SlabPageSize;
-
-    if (!isPowerOf2_64(PageSize)) {
-      Err = make_error<StringError>("Page size is not a power of 2",
-                                    inconvertibleErrorCode());
-      return;
+      else
+        return PageSizeOrErr.takeError();
     }
 
-    // Round slab request up to page size.
-    SlabSize = (SlabSize + PageSize - 1) & ~(PageSize - 1);
+    if (PageSize == 0)
+      return make_error<StringError>("Page size is zero",
+                                     inconvertibleErrorCode());
 
-    const sys::Memory::ProtectionFlags ReadWrite =
-        static_cast<sys::Memory::ProtectionFlags>(sys::Memory::MF_READ |
-                                                  sys::Memory::MF_WRITE);
+    return std::make_unique<InProcessDeltaMapper>(PageSize, SlabAddress);
+  }
 
-    std::error_code EC;
-    SlabRemaining =
-        sys::Memory::allocateMappedMemory(SlabSize, nullptr, ReadWrite, EC);
+  void reserve(size_t NumBytes, OnReservedFunction OnReserved) override {
+    InProcessMemoryMapper::reserve(
+        NumBytes, [this, OnReserved = std::move(OnReserved)](
+                      Expected<ExecutorAddrRange> Result) mutable {
+          if (!Result)
+            return OnReserved(Result.takeError());
 
-    if (EC) {
-      Err = errorCodeToError(EC);
-      return;
+          assert(DeltaAddr == 0 && "Overwriting previous offset");
+          if (TargetMapAddr != ~0ULL)
+            DeltaAddr = TargetMapAddr - Result->Start.getValue();
+          auto OffsetRange = ExecutorAddrRange(Result->Start + DeltaAddr,
+                                               Result->End + DeltaAddr);
+
+          OnReserved(OffsetRange);
+        });
+  }
+
+  char *prepare(ExecutorAddr Addr, size_t ContentSize) override {
+    return InProcessMemoryMapper::prepare(Addr - DeltaAddr, ContentSize);
+  }
+
+  void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override {
+    // Slide mapping based on delta and make all segments read-writable.
+    auto FixedAI = AI;
+    FixedAI.MappingBase -= DeltaAddr;
+    for (auto &Seg : FixedAI.Segments)
+      Seg.AG = AllocGroup(MemProt::Read | MemProt::Write,
+                          Seg.AG.getMemDeallocPolicy());
+    InProcessMemoryMapper::initialize(
+        FixedAI, [this, OnInitialized = std::move(OnInitialized)](
+                     Expected<ExecutorAddr> Result) mutable {
+          if (!Result)
+            return OnInitialized(Result.takeError());
+
+          OnInitialized(ExecutorAddr(Result->getValue() + DeltaAddr));
+        });
+  }
+
+  void deinitialize(ArrayRef<ExecutorAddr> Allocations,
+                    OnDeinitializedFunction OnDeInitialized) override {
+    std::vector<ExecutorAddr> Addrs(Allocations.size());
+    for (const auto Base : Allocations) {
+      Addrs.push_back(Base - DeltaAddr);
     }
 
-    // Calculate the target address delta to link as-if slab were at
-    // SlabAddress.
-    if (SlabAddress != ~0ULL)
-      SlabDelta = ExecutorAddr(SlabAddress) -
-                      ExecutorAddr::fromPtr(SlabRemaining.base());
+    InProcessMemoryMapper::deinitialize(Addrs, std::move(OnDeInitialized));
   }
 
-  Error freeBlock(sys::MemoryBlock MB) {
-    // FIXME: Return memory to slab.
-    return Error::success();
+  void release(ArrayRef<ExecutorAddr> Reservations,
+               OnReleasedFunction OnRelease) override {
+    std::vector<ExecutorAddr> Addrs(Reservations.size());
+    for (const auto Base : Reservations) {
+      Addrs.push_back(Base - DeltaAddr);
+    }
+    InProcessMemoryMapper::release(Addrs, std::move(OnRelease));
   }
 
-  std::mutex SlabMutex;
-  sys::MemoryBlock SlabRemaining;
-  uint64_t PageSize = 0;
-  int64_t SlabDelta = 0;
+private:
+  uint64_t TargetMapAddr;
+  uint64_t DeltaAddr;
 };
 
 Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {
@@ -713,14 +569,59 @@
   return SlabSize * Units;
 }
 
-static std::unique_ptr<JITLinkMemoryManager> createMemoryManager() {
-  if (!SlabAllocateSizeString.empty()) {
-    auto SlabSize = ExitOnErr(getSlabAllocSize(SlabAllocateSizeString));
-    return ExitOnErr(JITLinkSlabAllocator::Create(SlabSize));
-  }
-  return ExitOnErr(InProcessMemoryManager::Create());
+static std::unique_ptr<JITLinkMemoryManager> createInProcessMemoryManager() {
+  uint64_t SlabSize;
+#ifdef _WIN32
+  SlabSize = 1024 * 1024;
+#else
+  SlabSize = 1024 * 1024 * 1024;
+#endif
+
+  if (!SlabAllocateSizeString.empty())
+    SlabSize = ExitOnErr(getSlabAllocSize(SlabAllocateSizeString));
+
+  // If this is a -no-exec case and we're tweaking the slab address or size then
+  // use the delta mapper.
+  if (NoExec && (SlabAddress || SlabPageSize))
+    return ExitOnErr(
+        MapperJITLinkMemoryManager::CreateWithMapper<InProcessDeltaMapper>(
+            SlabSize));
+
+  // Otherwise use the standard in-process mapper.
+  return ExitOnErr(
+      MapperJITLinkMemoryManager::CreateWithMapper<InProcessMemoryMapper>(
+          SlabSize));
 }
 
+Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+createSharedMemoryManager(SimpleRemoteEPC &SREPC) {
+  SharedMemoryMapper::SymbolAddrs SAs;
+  if (auto Err = SREPC.getBootstrapSymbols(
+          {{SAs.Instance, rt::ExecutorSharedMemoryMapperServiceInstanceName},
+           {SAs.Reserve,
+            rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},
+           {SAs.Initialize,
+            rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName},
+           {SAs.Deinitialize,
+            rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName},
+           {SAs.Release,
+            rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName}}))
+    return std::move(Err);
+
+#ifdef _WIN32
+  size_t SlabSize = 1024 * 1024;
+#else
+  size_t SlabSize = 1024 * 1024 * 1024;
+#endif
+
+  if (!SlabAllocateSizeString.empty())
+    SlabSize = ExitOnErr(getSlabAllocSize(SlabAllocateSizeString));
+
+  return MapperJITLinkMemoryManager::CreateWithMapper<SharedMemoryMapper>(
+      SlabSize, SREPC, SAs);
+}
+
+
 static Expected<MaterializationUnit::Interface>
 getTestObjectFileInterface(Session &S, MemoryBufferRef O) {
 
@@ -804,10 +705,8 @@
   LLVM_DEBUG(dbgs() << "Loading dylibs...\n");
   for (const auto &Dylib : Dylibs) {
     LLVM_DEBUG(dbgs() << "  " << Dylib << "\n");
-    auto G = orc::EPCDynamicLibrarySearchGenerator::Load(S.ES, Dylib.c_str());
-    if (!G)
-      return G.takeError();
-    S.MainJD->addGenerator(std::move(*G));
+    if (auto Err = S.loadAndLinkDynamicLibrary(*S.MainJD, Dylib))
+      return Err;
   }
 
   return Error::success();
@@ -879,9 +778,13 @@
   close(ToExecutor[ReadEnd]);
   close(FromExecutor[WriteEnd]);
 
+  auto S = SimpleRemoteEPC::Setup();
+  if (UseSharedMemory)
+    S.CreateMemoryManager = createSharedMemoryManager;
+
   return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
-      std::make_unique<DynamicThreadPoolTaskDispatcher>(),
-      SimpleRemoteEPC::Setup(), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
+      std::make_unique<DynamicThreadPoolTaskDispatcher>(), std::move(S),
+      FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
 #endif
 }
 
@@ -965,9 +868,13 @@
   if (!SockFD)
     return SockFD.takeError();
 
+  auto S = SimpleRemoteEPC::Setup();
+  if (UseSharedMemory)
+    S.CreateMemoryManager = createSharedMemoryManager;
+
   return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
       std::make_unique<DynamicThreadPoolTaskDispatcher>(),
-      SimpleRemoteEPC::Setup(), *SockFD, *SockFD);
+      std::move(S), *SockFD, *SockFD);
 #endif
 }
 
@@ -1006,7 +913,7 @@
     EPC = std::make_unique<SelfExecutorProcessControl>(
         std::make_shared<SymbolStringPool>(),
         std::make_unique<InPlaceTaskDispatcher>(), std::move(TT), *PageSize,
-        createMemoryManager());
+        createInProcessMemoryManager());
   }
 
   Error Err = Error::success();
@@ -1038,10 +945,10 @@
     Error notifyFailed(MaterializationResponsibility &MR) override {
       return Error::success();
     }
-    Error notifyRemovingResources(ResourceKey K) override {
+    Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
       return Error::success();
     }
-    void notifyTransferringResources(ResourceKey DstKey,
+    void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
                                      ResourceKey SrcKey) override {}
 
   private:
@@ -1061,6 +968,16 @@
 
   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"),
+          {pointerToJITTargetAddress(llvm_jitlink_setTestResultOverride),
+           JITSymbolFlags::Exported}}})));
+    MainJD->addToLinkOrder(TestResultJD);
+  }
+
   ExitOnErr(loadDylibs(*this));
 
   auto &TT = ES.getExecutorProcessControl().getTargetTriple();
@@ -1086,6 +1003,21 @@
       Err = P.takeError();
       return;
     }
+  } else if (TT.isOSBinFormatCOFF() && !OrcRuntime.empty()) {
+    auto LoadDynLibrary = [&, this](JITDylib &JD, StringRef DLLName) -> Error {
+      if (!DLLName.endswith_insensitive(".dll"))
+        return make_error<StringError>("DLLName not ending with .dll",
+                                       inconvertibleErrorCode());
+      return loadAndLinkDynamicLibrary(JD, DLLName);
+    };
+
+    if (auto P = COFFPlatform::Create(ES, ObjLayer, *MainJD, OrcRuntime.c_str(),
+                                      std::move(LoadDynLibrary))) 
+      ES.setPlatform(std::move(*P));
+     else {
+      Err = P.takeError();
+      return;
+    }
   } else if (TT.isOSBinFormatELF()) {
     if (!NoExec)
       ObjLayer.addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
@@ -1145,7 +1077,7 @@
       if (EPC.getTargetTriple().getObjectFormat() == Triple::MachO)
         return registerMachOGraphInfo(*this, G);
 
-      if (EPC.getTargetTriple().isOSWindows())
+      if (EPC.getTargetTriple().getObjectFormat() == Triple::COFF)
         return registerCOFFGraphInfo(*this, G);
 
       return make_error<StringError>("Unsupported object format for GOT/stub "
@@ -1185,6 +1117,37 @@
     PassConfig.PostPrunePasses.push_back(addSelfRelocations);
 }
 
+Expected<JITDylib *> Session::getOrLoadDynamicLibrary(StringRef LibPath) {
+  auto It = DynLibJDs.find(LibPath.str());
+  if (It != DynLibJDs.end()) {
+    return It->second;
+  }
+  auto G = EPCDynamicLibrarySearchGenerator::Load(ES, LibPath.data());
+  if (!G)
+    return G.takeError();
+  auto JD = &ES.createBareJITDylib(LibPath.str());
+
+  JD->addGenerator(std::move(*G));
+  DynLibJDs.emplace(LibPath.str(), JD);
+  LLVM_DEBUG({
+    dbgs() << "Loaded dynamic library " << LibPath.data() << " for " << LibPath
+           << "\n";
+  });
+  return JD;
+}
+
+Error Session::loadAndLinkDynamicLibrary(JITDylib &JD, StringRef LibPath) {
+  auto DL = getOrLoadDynamicLibrary(LibPath);
+  if (!DL)
+    return DL.takeError();
+  JD.addToLinkOrder(**DL);
+  LLVM_DEBUG({
+    dbgs() << "Linking dynamic library " << LibPath << " to " << JD.getName()
+           << "\n";
+  });
+  return Error::success();
+}
+
 Expected<Session::FileInfo &> Session::findFileInfo(StringRef FileName) {
   auto FileInfoItr = FileInfos.find(FileName);
   if (FileInfoItr == FileInfos.end())
@@ -1264,8 +1227,11 @@
         auto Obj = ExitOnErr(
             object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));
         Triple TT = Obj->makeTriple();
-        if (Magic == file_magic::coff_object)
+        if (Magic == file_magic::coff_object) {
+          // TODO: Move this to makeTriple() if possible.
+          TT.setObjectFormat(Triple::COFF);
           TT.setOS(Triple::OSType::Win32);
+        }
         return TT;
       }
       default:
@@ -1526,6 +1492,18 @@
   return I;
 }
 
+static SmallVector<StringRef, 5> getSearchPathsFromEnvVar(Session &S) {
+  // FIXME: Handle EPC environment.
+  SmallVector<StringRef, 5> PathVec;
+  auto TT = S.ES.getExecutorProcessControl().getTargetTriple();
+  if (TT.isOSBinFormatCOFF())
+    StringRef(getenv("PATH")).split(PathVec, ";");
+  else if (TT.isOSBinFormatELF())
+    StringRef(getenv("LD_LIBRARY_PATH")).split(PathVec, ":");
+
+  return PathVec;
+}
+
 static Error addLibraries(Session &S,
                           const std::map<unsigned, JITDylib *> &IdxToJD) {
 
@@ -1563,13 +1541,15 @@
 
   // 2. Collect library loads
   struct LibraryLoad {
-    StringRef LibName;
+    std::string LibName;
     bool IsPath = false;
     unsigned Position;
     StringRef *CandidateExtensions;
     enum { Standard, Hidden } Modifier;
   };
-  std::vector<LibraryLoad> LibraryLoads;
+
+  // Queue to load library as in the order as it appears in the argument list.
+  std::deque<LibraryLoad> LibraryLoadQueue;
   // Add archive files from the inputs to LibraryLoads.
   for (auto InputFileItr = InputFiles.begin(), InputFileEnd = InputFiles.end();
        InputFileItr != InputFileEnd; ++InputFileItr) {
@@ -1577,12 +1557,12 @@
     if (!InputFile.endswith(".a") && !InputFile.endswith(".lib"))
       continue;
     LibraryLoad LL;
-    LL.LibName = InputFile;
+    LL.LibName = InputFile.str();
     LL.IsPath = true;
     LL.Position = InputFiles.getPosition(InputFileItr - InputFiles.begin());
     LL.CandidateExtensions = nullptr;
     LL.Modifier = LibraryLoad::Standard;
-    LibraryLoads.push_back(std::move(LL));
+    LibraryLoadQueue.push_back(std::move(LL));
   }
 
   // Add -load_hidden arguments to LibraryLoads.
@@ -1594,9 +1574,10 @@
     LL.Position = LoadHidden.getPosition(LibItr - LoadHidden.begin());
     LL.CandidateExtensions = nullptr;
     LL.Modifier = LibraryLoad::Hidden;
-    LibraryLoads.push_back(std::move(LL));
+    LibraryLoadQueue.push_back(std::move(LL));
   }
   StringRef StandardExtensions[] = {".so", ".dylib", ".dll", ".a", ".lib"};
+  StringRef DynLibExtensionsOnly[] = {".so", ".dylib", ".dll"};
   StringRef ArchiveExtensionsOnly[] = {".a", ".lib"};
 
   // Add -lx arguments to LibraryLoads.
@@ -1607,7 +1588,7 @@
     LL.Position = Libraries.getPosition(LibItr - Libraries.begin());
     LL.CandidateExtensions = StandardExtensions;
     LL.Modifier = LibraryLoad::Standard;
-    LibraryLoads.push_back(std::move(LL));
+    LibraryLoadQueue.push_back(std::move(LL));
   }
 
   // Add -hidden-lx arguments to LibraryLoads.
@@ -1620,7 +1601,7 @@
         LibrariesHidden.getPosition(LibHiddenItr - LibrariesHidden.begin());
     LL.CandidateExtensions = ArchiveExtensionsOnly;
     LL.Modifier = LibraryLoad::Hidden;
-    LibraryLoads.push_back(std::move(LL));
+    LibraryLoadQueue.push_back(std::move(LL));
   }
 
   // If there are any load-<modified> options then turn on flag overrides
@@ -1629,9 +1610,10 @@
     S.ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
 
   // Sort library loads by position in the argument list.
-  llvm::sort(LibraryLoads, [](const LibraryLoad &LHS, const LibraryLoad &RHS) {
-    return LHS.Position < RHS.Position;
-  });
+  llvm::sort(LibraryLoadQueue,
+             [](const LibraryLoad &LHS, const LibraryLoad &RHS) {
+               return LHS.Position < RHS.Position;
+             });
 
   // 3. Process library loads.
   auto AddArchive = [&](const char *Path, const LibraryLoad &LL)
@@ -1647,13 +1629,37 @@
       GetObjFileInterface = getObjectFileInterfaceHidden;
       break;
     }
-    return StaticLibraryDefinitionGenerator::Load(
+    auto G = StaticLibraryDefinitionGenerator::Load(
         S.ObjLayer, Path, S.ES.getExecutorProcessControl().getTargetTriple(),
         std::move(GetObjFileInterface));
+    if (!G)
+      return G.takeError();
+
+    // Push additional dynamic libraries to search.
+    // Note that this mechanism only happens in COFF.
+    for (auto FileName : (*G)->getImportedDynamicLibraries()) {
+      LibraryLoad NewLL;
+      auto FileNameRef = StringRef(FileName);
+      if (!FileNameRef.endswith_insensitive(".dll"))
+        return make_error<StringError>(
+            "COFF Imported library not ending with dll extension?",
+            inconvertibleErrorCode());
+      NewLL.LibName = FileNameRef.drop_back(strlen(".dll")).str();
+      NewLL.Position = LL.Position;
+      NewLL.CandidateExtensions = DynLibExtensionsOnly;
+      NewLL.Modifier = LibraryLoad::Standard;
+      LibraryLoadQueue.push_front(std::move(NewLL));
+    }
+    return G;
   };
 
-  for (auto &LL : LibraryLoads) {
+  SmallVector<StringRef, 5> SystemSearchPaths;
+  if (SearchSystemLibrary.getValue())
+    SystemSearchPaths = getSearchPathsFromEnvVar(S);
+  while (!LibraryLoadQueue.empty()) {
     bool LibFound = false;
+    auto LL = LibraryLoadQueue.front();
+    LibraryLoadQueue.pop_front();
     auto &JD = *std::prev(IdxToJD.lower_bound(LL.Position))->second;
 
     // If this is the name of a JITDylib then link against that.
@@ -1663,7 +1669,7 @@
     }
 
     if (LL.IsPath) {
-      auto G = AddArchive(LL.LibName.str().c_str(), LL);
+      auto G = AddArchive(LL.LibName.c_str(), LL);
       if (!G)
         return createFileError(LL.LibName, G.takeError());
       JD.addGenerator(std::move(*G));
@@ -1675,86 +1681,74 @@
     }
 
     // Otherwise look through the search paths.
-    auto JDSearchPathsItr = JDSearchPaths.find(&JD);
-    if (JDSearchPathsItr != JDSearchPaths.end()) {
-      for (StringRef SearchPath : JDSearchPathsItr->second) {
-        for (const char *LibExt : {".dylib", ".so", ".dll", ".a", ".lib"}) {
-          SmallVector<char, 256> LibPath;
-          LibPath.reserve(SearchPath.size() + strlen("lib") +
-                          LL.LibName.size() + strlen(LibExt) +
-                          2); // +2 for pathsep, null term.
-          llvm::copy(SearchPath, std::back_inserter(LibPath));
-          if (StringRef(LibExt) != ".lib" && StringRef(LibExt) != ".dll")
-            sys::path::append(LibPath, "lib" + LL.LibName + LibExt);
-          else
-            sys::path::append(LibPath, LL.LibName + LibExt);
-          LibPath.push_back('\0');
+    auto CurJDSearchPaths = JDSearchPaths[&JD];
+    for (StringRef SearchPath :
+         concat<StringRef>(CurJDSearchPaths, SystemSearchPaths)) {
+      for (const char *LibExt : {".dylib", ".so", ".dll", ".a", ".lib"}) {
+        SmallVector<char, 256> LibPath;
+        LibPath.reserve(SearchPath.size() + strlen("lib") + LL.LibName.size() +
+                        strlen(LibExt) + 2); // +2 for pathsep, null term.
+        llvm::copy(SearchPath, std::back_inserter(LibPath));
+        if (StringRef(LibExt) != ".lib" && StringRef(LibExt) != ".dll")
+          sys::path::append(LibPath, "lib" + LL.LibName + LibExt);
+        else
+          sys::path::append(LibPath, LL.LibName + LibExt);
+        LibPath.push_back('\0');
 
-          // Skip missing or non-regular paths.
-          if (sys::fs::get_file_type(LibPath.data()) !=
-              sys::fs::file_type::regular_file) {
-            continue;
-          }
+        // Skip missing or non-regular paths.
+        if (sys::fs::get_file_type(LibPath.data()) !=
+            sys::fs::file_type::regular_file) {
+          continue;
+        }
 
-          file_magic Magic;
-          if (auto EC = identify_magic(LibPath, Magic)) {
-            // If there was an error loading the file then skip it.
-            LLVM_DEBUG({
-              dbgs() << "Library search found \"" << LibPath
-                     << "\", but could not identify file type (" << EC.message()
-                     << "). Skipping.\n";
-            });
-            continue;
-          }
+        file_magic Magic;
+        if (auto EC = identify_magic(LibPath, Magic)) {
+          // If there was an error loading the file then skip it.
+          LLVM_DEBUG({
+            dbgs() << "Library search found \"" << LibPath
+                   << "\", but could not identify file type (" << EC.message()
+                   << "). Skipping.\n";
+          });
+          continue;
+        }
 
-          // We identified the magic. Assume that we can load it -- we'll reset
-          // in the default case.
-          LibFound = true;
-          switch (Magic) {
-          case file_magic::elf_shared_object:
-          case file_magic::macho_dynamically_linked_shared_lib: {
-            // TODO: On first reference to LibPath this should create a JITDylib
-            // with a generator and add it to JD's links-against list. Subsquent
-            // references should use the JITDylib created on the first
-            // reference.
-            auto G =
-                EPCDynamicLibrarySearchGenerator::Load(S.ES, LibPath.data());
-            if (!G)
-              return G.takeError();
-            LLVM_DEBUG({
-              dbgs() << "Adding generator for dynamic library "
-                     << LibPath.data() << " to " << JD.getName() << "\n";
-            });
-            JD.addGenerator(std::move(*G));
-            break;
-          }
-          case file_magic::archive:
-          case file_magic::macho_universal_binary: {
-            auto G = AddArchive(LibPath.data(), LL);
-            if (!G)
-              return G.takeError();
-            JD.addGenerator(std::move(*G));
-            LLVM_DEBUG({
-              dbgs() << "Adding generator for static library " << LibPath.data()
-                     << " to " << JD.getName() << "\n";
-            });
-            break;
-          }
-          default:
-            // This file isn't a recognized library kind.
-            LLVM_DEBUG({
-              dbgs() << "Library search found \"" << LibPath
-                     << "\", but file type is not supported. Skipping.\n";
-            });
-            LibFound = false;
-            break;
-          }
-          if (LibFound)
-            break;
+        // We identified the magic. Assume that we can load it -- we'll reset
+        // in the default case.
+        LibFound = true;
+        switch (Magic) {
+        case file_magic::pecoff_executable:
+        case file_magic::elf_shared_object:
+        case file_magic::macho_dynamically_linked_shared_lib: {
+          if (auto Err = S.loadAndLinkDynamicLibrary(JD, LibPath.data()))
+            return Err;
+          break;
+        }
+        case file_magic::archive:
+        case file_magic::macho_universal_binary: {
+          auto G = AddArchive(LibPath.data(), LL);
+          if (!G)
+            return G.takeError();
+          JD.addGenerator(std::move(*G));
+          LLVM_DEBUG({
+            dbgs() << "Adding generator for static library " << LibPath.data()
+                   << " to " << JD.getName() << "\n";
+          });
+          break;
+        }
+        default:
+          // This file isn't a recognized library kind.
+          LLVM_DEBUG({
+            dbgs() << "Library search found \"" << LibPath
+                   << "\", but file type is not supported. Skipping.\n";
+          });
+          LibFound = false;
+          break;
         }
         if (LibFound)
           break;
       }
+      if (LibFound)
+        break;
     }
 
     if (!LibFound)
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 9cac376..8d4c0d8 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.h
+++ b/src/llvm-project/llvm/tools/llvm-jitlink/llvm-jitlink.h
@@ -13,7 +13,6 @@
 #ifndef LLVM_TOOLS_LLVM_JITLINK_LLVM_JITLINK_H
 #define LLVM_TOOLS_LLVM_JITLINK_LLVM_JITLINK_H
 
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/ExecutionEngine/Orc/Core.h"
@@ -53,9 +52,13 @@
     StringMap<MemoryRegionInfo> GOTEntryInfos;
   };
 
+  using DynLibJDMap = std::map<std::string, orc::JITDylib *>;
   using SymbolInfoMap = StringMap<MemoryRegionInfo>;
   using FileInfoMap = StringMap<FileInfo>;
 
+  Expected<orc::JITDylib *> getOrLoadDynamicLibrary(StringRef LibPath);
+  Error loadAndLinkDynamicLibrary(orc::JITDylib &JD, StringRef LibPath);
+
   Expected<FileInfo &> findFileInfo(StringRef FileName);
   Expected<MemoryRegionInfo &> findSectionInfo(StringRef FileName,
                                                StringRef SectionName);
@@ -68,6 +71,8 @@
   Expected<MemoryRegionInfo &> findSymbolInfo(StringRef SymbolName,
                                               Twine ErrorMsgStem);
 
+  DynLibJDMap DynLibJDs;
+
   SymbolInfoMap SymbolInfos;
   FileInfoMap FileInfos;
   uint64_t SizeBeforePruning = 0;
diff --git a/src/llvm-project/llvm/tools/llvm-jitlistener/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-jitlistener/CMakeLists.txt
index 61f8420..8592241 100644
--- a/src/llvm-project/llvm/tools/llvm-jitlistener/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-jitlistener/CMakeLists.txt
@@ -15,6 +15,7 @@
   object
   selectiondag
   Support
+  TargetParser
   ExecutionEngine
   RuntimeDyld
   Core
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 a06d107..f689645 100644
--- a/src/llvm-project/llvm/tools/llvm-libtool-darwin/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-libtool-darwin/CMakeLists.txt
@@ -3,6 +3,7 @@
   Core
   Object
   Support
+  TargetParser
   TextAPI
   ${LLVM_TARGETS_TO_BUILD}
   )
diff --git a/src/llvm-project/llvm/tools/llvm-libtool-darwin/DependencyInfo.h b/src/llvm-project/llvm/tools/llvm-libtool-darwin/DependencyInfo.h
new file mode 100644
index 0000000..7b2f94b
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-libtool-darwin/DependencyInfo.h
@@ -0,0 +1,85 @@
+//===-- DependencyInfo.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <set>
+
+class DependencyInfo {
+public:
+  explicit DependencyInfo(std::string DependencyInfoPath)
+      : DependencyInfoPath(DependencyInfoPath) {}
+
+  virtual ~DependencyInfo(){};
+
+  virtual void addMissingInput(llvm::StringRef Path) {
+    NotFounds.insert(Path.str());
+  }
+
+  // Writes the dependencies to specified path. The content is first sorted by
+  // OpCode and then by the filename (in alphabetical order).
+  virtual void write(llvm::Twine Version,
+                     const std::vector<std::string> &Inputs,
+                     std::string Output) {
+    std::error_code EC;
+    llvm::raw_fd_ostream OS(DependencyInfoPath, EC, llvm::sys::fs::OF_None);
+    if (EC) {
+      llvm::WithColor::defaultErrorHandler(llvm::createStringError(
+          EC,
+          "failed to write to " + DependencyInfoPath + ": " + EC.message()));
+      return;
+    }
+
+    auto AddDep = [&OS](DependencyInfoOpcode Opcode,
+                        const llvm::StringRef &Path) {
+      OS << static_cast<uint8_t>(Opcode);
+      OS << Path;
+      OS << '\0';
+    };
+
+    AddDep(DependencyInfoOpcode::Tool, Version.str());
+
+    // Sort the input by its names.
+    std::vector<llvm::StringRef> InputNames;
+    InputNames.reserve(Inputs.size());
+    for (const auto &F : Inputs)
+      InputNames.push_back(F);
+    llvm::sort(InputNames);
+
+    for (const auto &In : InputNames)
+      AddDep(DependencyInfoOpcode::InputFound, In);
+
+    for (const std::string &F : NotFounds)
+      AddDep(DependencyInfoOpcode::InputMissing, F);
+
+    AddDep(DependencyInfoOpcode::Output, Output);
+  }
+
+private:
+  enum DependencyInfoOpcode : uint8_t {
+    Tool = 0x00,
+    InputFound = 0x10,
+    InputMissing = 0x11,
+    Output = 0x40,
+  };
+
+  const std::string DependencyInfoPath;
+  std::set<std::string> NotFounds;
+};
+
+// Subclass to avoid any overhead when not using this feature
+class DummyDependencyInfo : public DependencyInfo {
+public:
+  DummyDependencyInfo() : DependencyInfo("") {}
+  void addMissingInput(llvm::StringRef Path) override {}
+  void write(llvm::Twine Version, const std::vector<std::string> &Inputs,
+             std::string Output) override {}
+};
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 08b371e..3357afb0 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
@@ -10,6 +10,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "DependencyInfo.h"
 #include "llvm/BinaryFormat/Magic.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/Object/ArchiveWriter.h"
@@ -87,6 +88,12 @@
         " libraries"),
     cl::Prefix, cl::cat(LibtoolCategory));
 
+static cl::opt<std::string> DependencyInfoPath(
+    "dependency_info",
+    cl::desc("Write an Xcode dependency info file describing the dependencies "
+             "of the created library"),
+    cl::cat(LibtoolCategory));
+
 static cl::opt<bool>
     VersionOption("V", cl::desc("Print the version number and exit"),
                   cl::cat(LibtoolCategory));
@@ -101,12 +108,16 @@
                                       cl::cat(LibtoolCategory),
                                       cl::init(false));
 
+static cl::opt<std::string> IgnoredSyslibRoot("syslibroot", cl::Hidden);
+
 static const std::array<std::string, 3> StandardSearchDirs{
     "/lib",
     "/usr/lib",
     "/usr/local/lib",
 };
 
+std::unique_ptr<DependencyInfo> GlobalDependencyInfo;
+
 struct Config {
   bool Deterministic = true; // Updated by 'D' and 'U' modifiers.
   uint32_t ArchCPUType;
@@ -114,20 +125,22 @@
 };
 
 static Expected<std::string> searchForFile(const Twine &FileName) {
-
   auto FindLib =
-      [FileName](ArrayRef<std::string> SearchDirs) -> Optional<std::string> {
+      [FileName](
+          ArrayRef<std::string> SearchDirs) -> std::optional<std::string> {
     for (StringRef Dir : SearchDirs) {
       SmallString<128> Path;
       sys::path::append(Path, Dir, FileName);
 
       if (sys::fs::exists(Path))
         return std::string(Path);
+
+      GlobalDependencyInfo->addMissingInput(Path);
     }
-    return None;
+    return std::nullopt;
   };
 
-  Optional<std::string> Found = FindLib(LibrarySearchDirs);
+  std::optional<std::string> Found = FindLib(LibrarySearchDirs);
   if (!Found)
     Found = FindLib(StandardSearchDirs);
   if (Found)
@@ -244,8 +257,8 @@
       "This test makes sure NewArchiveMemberList is used by MembersData since "
       "the following asserts test invariants required for MembersData.");
   static_assert(
-      !std::is_copy_constructible<
-          decltype(NewArchiveMemberList::Members)::value_type>::value,
+      !std::is_copy_constructible_v<
+          decltype(NewArchiveMemberList::Members)::value_type>,
       "MembersData::MembersPerArchitecture has a dependency on "
       "MembersData::FileBuffers so it should not be able to "
       "be copied on its own without FileBuffers. Unfortunately, "
@@ -253,8 +266,8 @@
       "of a non-copyable type is itself non-copyable so we have to test the "
       "actual type of the stored data (ie, value_type).");
   static_assert(
-      !std::is_copy_assignable<
-          decltype(NewArchiveMemberList::Members)::value_type>::value,
+      !std::is_copy_assignable_v<
+          decltype(NewArchiveMemberList::Members)::value_type>,
       "MembersData::MembersPerArchitecture has a dependency on "
       "MembersData::FileBuffers so it should not be able to "
       "be copied on its own without FileBuffers. Unfortunately, "
@@ -650,6 +663,11 @@
     return C;
   }
 
+  GlobalDependencyInfo =
+      DependencyInfoPath.empty()
+          ? std::make_unique<DummyDependencyInfo>()
+          : std::make_unique<DependencyInfo>(DependencyInfoPath);
+
   if (OutputFile.empty()) {
     std::string Error;
     raw_string_ostream Stream(Error);
@@ -684,6 +702,9 @@
             MachO::getArchitectureFromName(ArchType));
   }
 
+  GlobalDependencyInfo->write("llvm-libtool-darwin " LLVM_VERSION_STRING,
+                              InputFiles, OutputFile);
+
   return C;
 }
 
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 6585b19..32ab9fa 100644
--- a/src/llvm-project/llvm/tools/llvm-link/llvm-link.cpp
+++ b/src/llvm-project/llvm/tools/llvm-link/llvm-link.cpp
@@ -456,11 +456,12 @@
   InitLLVM X(argc, argv);
   ExitOnErr.setBanner(std::string(argv[0]) + ": ");
 
+  cl::HideUnrelatedOptions({&LinkCategory, &getColorCategory()});
+  cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");
+
   LLVMContext Context;
   Context.setDiagnosticHandler(std::make_unique<LLVMLinkDiagnosticHandler>(),
                                true);
-  cl::HideUnrelatedOptions({&LinkCategory, &getColorCategory()});
-  cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");
 
   if (!DisableDITypeMap)
     Context.enableDebugTypeODRUniquing();
diff --git a/src/llvm-project/llvm/tools/llvm-lipo/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-lipo/CMakeLists.txt
index 2f582cb..342f9bf 100644
--- a/src/llvm-project/llvm/tools/llvm-lipo/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-lipo/CMakeLists.txt
@@ -3,6 +3,7 @@
   Object
   Option
   Support
+  TargetParser
   TextAPI
   Core
   BinaryFormat
@@ -16,6 +17,7 @@
   llvm-lipo.cpp
   DEPENDS
   LipoOptsTableGen
+  GENERATE_DRIVER
 )
 
 if(LLVM_INSTALL_CCTOOLS_SYMLINKS)
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 43dd97e..074a526 100644
--- a/src/llvm-project/llvm/tools/llvm-lipo/llvm-lipo.cpp
+++ b/src/llvm-project/llvm/tools/llvm-lipo/llvm-lipo.cpp
@@ -28,8 +28,10 @@
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FileOutputBuffer.h"
 #include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/TextAPI/Architecture.h"
+#include <optional>
 
 using namespace llvm;
 using namespace llvm::object;
@@ -71,26 +73,29 @@
 #undef OPTION
 };
 
-// LipoInfoTable below references LIPO_##PREFIX. OptionGroup has prefix nullptr.
-const char *const *LIPO_nullptr = nullptr;
-#define PREFIX(NAME, VALUE) const char *const LIPO_##NAME[] = VALUE;
+namespace lipo {
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr llvm::StringLiteral NAME##_init[] = VALUE;                  \
+  static constexpr llvm::ArrayRef<llvm::StringLiteral> NAME(                   \
+      NAME##_init, std::size(NAME##_init) - 1);
 #include "LipoOpts.inc"
 #undef PREFIX
 
-const opt::OptTable::Info LipoInfoTable[] = {
+static constexpr opt::OptTable::Info LipoInfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
-  {LIPO_##PREFIX, NAME,      HELPTEXT,                                         \
-   METAVAR,       LIPO_##ID, opt::Option::KIND##Class,                         \
-   PARAM,         FLAGS,     LIPO_##GROUP,                                     \
-   LIPO_##ALIAS,  ALIASARGS, VALUES},
+  {PREFIX,       NAME,      HELPTEXT,                                          \
+   METAVAR,      LIPO_##ID, opt::Option::KIND##Class,                          \
+   PARAM,        FLAGS,     LIPO_##GROUP,                                      \
+   LIPO_##ALIAS, ALIASARGS, VALUES},
 #include "LipoOpts.inc"
 #undef OPTION
 };
+} // namespace lipo
 
-class LipoOptTable : public opt::OptTable {
+class LipoOptTable : public opt::GenericOptTable {
 public:
-  LipoOptTable() : OptTable(LipoInfoTable) {}
+  LipoOptTable() : opt::GenericOptTable(lipo::LipoInfoTable) {}
 };
 
 enum class LipoAction {
@@ -104,7 +109,7 @@
 };
 
 struct InputFile {
-  Optional<StringRef> ArchType;
+  std::optional<StringRef> ArchType;
   StringRef FileName;
 };
 
@@ -176,16 +181,14 @@
     exit(EXIT_SUCCESS);
   }
 
-  for (auto Arg : InputArgs.filtered(LIPO_UNKNOWN))
+  for (auto *Arg : InputArgs.filtered(LIPO_UNKNOWN))
     reportError("unknown argument '" + Arg->getAsString(InputArgs) + "'");
 
-  for (auto Arg : InputArgs.filtered(LIPO_INPUT))
-    C.InputFiles.push_back({None, Arg->getValue()});
-  for (auto Arg : InputArgs.filtered(LIPO_arch)) {
+  for (auto *Arg : InputArgs.filtered(LIPO_INPUT))
+    C.InputFiles.push_back({std::nullopt, Arg->getValue()});
+  for (auto *Arg : InputArgs.filtered(LIPO_arch)) {
     validateArchitectureName(Arg->getValue(0));
-    if (!Arg->getValue(1))
-      reportError(
-          "arch is missing an argument: expects -arch arch_type file_name");
+    assert(Arg->getValue(1) && "file_name is missing");
     C.InputFiles.push_back({StringRef(Arg->getValue(0)), Arg->getValue(1)});
   }
 
@@ -195,7 +198,7 @@
   if (InputArgs.hasArg(LIPO_output))
     C.OutputFile = std::string(InputArgs.getLastArgValue(LIPO_output));
 
-  for (auto Segalign : InputArgs.filtered(LIPO_segalign)) {
+  for (auto *Segalign : InputArgs.filtered(LIPO_segalign)) {
     if (!Segalign->getValue(1))
       reportError("segalign is missing an argument: expects -segalign "
                   "arch_type alignment_value");
@@ -239,7 +242,7 @@
     std::string Buf;
     raw_string_ostream OS(Buf);
     OS << "only one of the following actions can be specified:";
-    for (auto Arg : ActionArgs)
+    for (auto *Arg : ActionArgs)
       OS << " " << Arg->getSpelling();
     reportError(OS.str());
   }
@@ -293,11 +296,8 @@
     return C;
 
   case LIPO_replace:
-    for (auto Action : ActionArgs) {
-      if (!Action->getValue(1))
-        reportError(
-            "replace is missing an argument: expects -replace arch_type "
-            "file_name");
+    for (auto *Action : ActionArgs) {
+      assert(Action->getValue(1) && "file_name is missing");
       validateArchitectureName(Action->getValue(0));
       C.ReplacementFiles.push_back(
           {StringRef(Action->getValue(0)), Action->getValue(1)});
@@ -430,7 +430,7 @@
   Expected<Slice> SliceOrErr = createSliceFromIR(*IR, 0);
   if (!SliceOrErr)
     reportError(IR->getFileName(), SliceOrErr.takeError());
-  
+
   OS << SliceOrErr->getArchString() << " \n";
 }
 
@@ -723,9 +723,13 @@
   exit(EXIT_SUCCESS);
 }
 
-int main(int argc, char **argv) {
+int llvm_lipo_main(int argc, char **argv) {
   InitLLVM X(argc, argv);
-  Config C = parseLipoOptions(makeArrayRef(argv + 1, argc));
+  llvm::InitializeAllTargetInfos();
+  llvm::InitializeAllTargetMCs();
+  llvm::InitializeAllAsmParsers();
+
+  Config C = parseLipoOptions(ArrayRef(argv + 1, argc - 1));
   LLVMContext LLVMCtx;
   SmallVector<OwningBinary<Binary>, 1> InputBinaries =
       readInputBinaries(LLVMCtx, C.InputFiles);
diff --git a/src/llvm-project/llvm/tools/llvm-lto/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-lto/CMakeLists.txt
index 93df852..988085b 100644
--- a/src/llvm-project/llvm/tools/llvm-lto/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-lto/CMakeLists.txt
@@ -14,6 +14,7 @@
   Object
   Support
   Target
+  TargetParser
   )
 
 add_llvm_tool(llvm-lto
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 64c8c19..79e9d93 100644
--- a/src/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
+++ b/src/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
@@ -317,11 +317,11 @@
       if (!CurrentActivity.empty())
         OS << ' ' << CurrentActivity;
       OS << ": ";
-  
+
       DiagnosticPrinterRawOStream DP(OS);
       DI.print(DP);
       OS << '\n';
-  
+
       if (DI.getSeverity() == DS_Error)
         exit(1);
       return true;
@@ -1099,7 +1099,9 @@
         error("writing merged module failed.");
     }
 
-    auto AddStream = [&](size_t Task) -> std::unique_ptr<CachedFileStream> {
+    auto AddStream =
+        [&](size_t Task,
+            const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
       std::string PartFilename = OutputFilename;
       if (Parallelism != 1)
         PartFilename += "." + utostr(Task);
diff --git a/src/llvm-project/llvm/tools/llvm-lto2/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-lto2/CMakeLists.txt
index dd09a34..3b4644d 100644
--- a/src/llvm-project/llvm/tools/llvm-lto2/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-lto2/CMakeLists.txt
@@ -13,6 +13,7 @@
   Passes
   Support
   Target
+  TargetParser
   )
 
 add_llvm_tool(llvm-lto2
diff --git a/src/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp b/src/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp
index 87fe90a..09c74fc 100644
--- a/src/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp
+++ b/src/llvm-project/llvm/tools/llvm-lto2/llvm-lto2.cpp
@@ -17,7 +17,6 @@
 
 #include "llvm/Bitcode/BitcodeReader.h"
 #include "llvm/CodeGen/CommandFlags.h"
-#include "llvm/Config/llvm-config.h"
 #include "llvm/IR/DiagnosticPrinter.h"
 #include "llvm/LTO/LTO.h"
 #include "llvm/Passes/PassPlugin.h"
@@ -131,7 +130,7 @@
     cl::desc("With PGO, include profile count in optimization remarks"),
     cl::Hidden);
 
-cl::opt<Optional<uint64_t>, false, remarks::HotnessThresholdParser>
+cl::opt<std::optional<uint64_t>, false, remarks::HotnessThresholdParser>
     RemarksHotnessThreshold(
         "pass-remarks-hotness-threshold",
         cl::desc("Minimum profile count required for an "
@@ -307,20 +306,9 @@
   Conf.Freestanding = EnableFreestanding;
   for (auto &PluginFN : PassPlugins)
     Conf.PassPlugins.push_back(PluginFN);
-  switch (CGOptLevel) {
-  case '0':
-    Conf.CGOptLevel = CodeGenOpt::None;
-    break;
-  case '1':
-    Conf.CGOptLevel = CodeGenOpt::Less;
-    break;
-  case '2':
-    Conf.CGOptLevel = CodeGenOpt::Default;
-    break;
-  case '3':
-    Conf.CGOptLevel = CodeGenOpt::Aggressive;
-    break;
-  default:
+  if (auto Level = CodeGenOpt::parseLevel(CGOptLevel)) {
+    Conf.CGOptLevel = *Level;
+  } else {
     llvm::errs() << "invalid cg optimization level: " << CGOptLevel << '\n';
     return 1;
   }
@@ -411,7 +399,9 @@
   if (HasErrors)
     return 1;
 
-  auto AddStream = [&](size_t Task) -> std::unique_ptr<CachedFileStream> {
+  auto AddStream =
+      [&](size_t Task,
+          const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
     std::string Path = OutputFilename + "." + utostr(Task);
 
     std::error_code EC;
@@ -420,8 +410,9 @@
     return std::make_unique<CachedFileStream>(std::move(S), Path);
   };
 
-  auto AddBuffer = [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) {
-    *AddStream(Task)->OS << MB->getBuffer();
+  auto AddBuffer = [&](size_t Task, const Twine &ModuleName,
+                       std::unique_ptr<MemoryBuffer> MB) {
+    *AddStream(Task, ModuleName)->OS << MB->getBuffer();
   };
 
   FileCache Cache;
diff --git a/src/llvm-project/llvm/tools/llvm-mc-assemble-fuzzer/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-mc-assemble-fuzzer/CMakeLists.txt
index d7835c83..ff9d381 100644
--- a/src/llvm-project/llvm/tools/llvm-mc-assemble-fuzzer/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-mc-assemble-fuzzer/CMakeLists.txt
@@ -5,6 +5,7 @@
     MC
     MCParser
     Support
+    TargetParser
 )
 
 add_llvm_fuzzer(llvm-mc-assemble-fuzzer
diff --git a/src/llvm-project/llvm/tools/llvm-mc-disassemble-fuzzer/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-mc-disassemble-fuzzer/CMakeLists.txt
index d1fbdf4..7e31941 100644
--- a/src/llvm-project/llvm/tools/llvm-mc-disassemble-fuzzer/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-mc-disassemble-fuzzer/CMakeLists.txt
@@ -6,6 +6,7 @@
     MCDisassembler
     MCParser
     Support
+    TargetParser
 )
 add_llvm_fuzzer(llvm-mc-disassemble-fuzzer
   llvm-mc-disassemble-fuzzer.cpp
diff --git a/src/llvm-project/llvm/tools/llvm-mc/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-mc/CMakeLists.txt
index a18783e..f57356f 100644
--- a/src/llvm-project/llvm/tools/llvm-mc/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-mc/CMakeLists.txt
@@ -6,6 +6,7 @@
   MC
   MCParser
   Support
+  TargetParser
   )
 
 add_llvm_tool(llvm-mc
diff --git a/src/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp b/src/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp
index ac55d05..2d18334 100644
--- a/src/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mc/Disassembler.cpp
@@ -65,7 +65,7 @@
       SM.PrintMessage(SMLoc::getFromPointer(Bytes.second[Index]),
                       SourceMgr::DK_Warning,
                       "potentially undefined instruction encoding");
-      LLVM_FALLTHROUGH;
+      [[fallthrough]];
 
     case MCDisassembler::Success:
       Streamer.emitInstruction(Inst, STI);
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 aa380d3..dd5a66a 100644
--- a/src/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mc/llvm-mc.cpp
@@ -76,8 +76,8 @@
     cl::init(DebugCompressionType::None),
     cl::desc("Choose DWARF debug sections compression:"),
     cl::values(clEnumValN(DebugCompressionType::None, "none", "No compression"),
-               clEnumValN(DebugCompressionType::Z, "zlib",
-                          "Use zlib compression")),
+               clEnumValN(DebugCompressionType::Zlib, "zlib", "Use zlib"),
+               clEnumValN(DebugCompressionType::Zstd, "zstd", "Use zstd")),
     cl::cat(MCCategory));
 
 static cl::opt<bool>
@@ -399,15 +399,15 @@
   assert(MAI && "Unable to create target asm info!");
 
   MAI->setRelaxELFRelocations(RelaxELFRel);
-
   if (CompressDebugSections != DebugCompressionType::None) {
-    if (!compression::zlib::isAvailable()) {
+    if (const char *Reason = compression::getReasonIfUnsupported(
+            compression::formatFor(CompressDebugSections))) {
       WithColor::error(errs(), ProgName)
-          << "build tools with zlib to enable -compress-debug-sections";
+          << "--compress-debug-sections: " << Reason;
       return 1;
     }
-    MAI->setCompressDebugSections(CompressDebugSections);
   }
+  MAI->setCompressDebugSections(CompressDebugSections);
   MAI->setPreserveAsmComments(PreserveComments);
 
   // Package up features to be passed to target/subtarget
diff --git a/src/llvm-project/llvm/tools/llvm-mca/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-mca/CMakeLists.txt
index 0a0cd2e..878a05c 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-mca/CMakeLists.txt
@@ -10,6 +10,7 @@
   MC
   MCParser
   Support
+  TargetParser
   )
 
 add_llvm_tool(llvm-mca
diff --git a/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp b/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp
index 7662538..c91ed75 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.cpp
@@ -16,11 +16,6 @@
 namespace llvm {
 namespace mca {
 
-CodeRegions::CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {
-  // Create a default region for the input code sequence.
-  Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
-}
-
 bool CodeRegion::isLocInRange(SMLoc Loc) const {
   if (RangeEnd.isValid() && Loc.getPointer() > RangeEnd.getPointer())
     return false;
@@ -29,7 +24,19 @@
   return true;
 }
 
-void CodeRegions::beginRegion(StringRef Description, SMLoc Loc) {
+void CodeRegions::addInstruction(const MCInst &Instruction) {
+  SMLoc Loc = Instruction.getLoc();
+  for (UniqueCodeRegion &Region : Regions)
+    if (Region->isLocInRange(Loc))
+      Region->addInstruction(Instruction);
+}
+
+AnalysisRegions::AnalysisRegions(llvm::SourceMgr &S) : CodeRegions(S) {
+  // Create a default region for the input code sequence.
+  Regions.emplace_back(std::make_unique<CodeRegion>("", SMLoc()));
+}
+
+void AnalysisRegions::beginRegion(StringRef Description, SMLoc Loc) {
   if (ActiveRegions.empty()) {
     // Remove the default region if there is at least one user defined region.
     // By construction, only the default region has an invalid start location.
@@ -44,17 +51,17 @@
     if (It != ActiveRegions.end()) {
       const CodeRegion &R = *Regions[It->second];
       if (Description.empty()) {
-        SM.PrintMessage(Loc, SourceMgr::DK_Error,
+        SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
                         "found multiple overlapping anonymous regions");
-        SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note,
+        SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
                         "Previous anonymous region was defined here");
         FoundErrors = true;
         return;
       }
 
-      SM.PrintMessage(Loc, SourceMgr::DK_Error,
+      SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
                       "overlapping regions cannot have the same name");
-      SM.PrintMessage(R.startLoc(), SourceMgr::DK_Note,
+      SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
                       "region " + Description + " was previously defined here");
       FoundErrors = true;
       return;
@@ -65,7 +72,7 @@
   Regions.emplace_back(std::make_unique<CodeRegion>(Description, Loc));
 }
 
-void CodeRegions::endRegion(StringRef Description, SMLoc Loc) {
+void AnalysisRegions::endRegion(StringRef Description, SMLoc Loc) {
   if (Description.empty()) {
     // Special case where there is only one user defined region,
     // and this LLVM-MCA-END directive doesn't provide a region name.
@@ -94,22 +101,73 @@
   }
 
   FoundErrors = true;
-  SM.PrintMessage(Loc, SourceMgr::DK_Error,
+  SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
                   "found an invalid region end directive");
   if (!Description.empty()) {
-    SM.PrintMessage(Loc, SourceMgr::DK_Note,
+    SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
                     "unable to find an active region named " + Description);
   } else {
-    SM.PrintMessage(Loc, SourceMgr::DK_Note,
+    SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
                     "unable to find an active anonymous region");
   }
 }
 
-void CodeRegions::addInstruction(const MCInst &Instruction) {
-  SMLoc Loc = Instruction.getLoc();
-  for (UniqueCodeRegion &Region : Regions)
-    if (Region->isLocInRange(Loc))
-      Region->addInstruction(Instruction);
+InstrumentRegions::InstrumentRegions(llvm::SourceMgr &S) : CodeRegions(S) {}
+
+void InstrumentRegions::beginRegion(StringRef Description, SMLoc Loc,
+                                    SharedInstrument I) {
+  if (Description.empty()) {
+    SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
+                    "anonymous instrumentation regions are not permitted");
+    FoundErrors = true;
+    return;
+  }
+
+  auto It = ActiveRegions.find(Description);
+  if (It != ActiveRegions.end()) {
+    const CodeRegion &R = *Regions[It->second];
+    SM.PrintMessage(
+        Loc, llvm::SourceMgr::DK_Error,
+        "overlapping instrumentation regions cannot be of the same kind");
+    SM.PrintMessage(R.startLoc(), llvm::SourceMgr::DK_Note,
+                    "instrumentation region " + Description +
+                        " was previously defined here");
+    FoundErrors = true;
+    return;
+  }
+
+  ActiveRegions[Description] = Regions.size();
+  Regions.emplace_back(std::make_unique<InstrumentRegion>(Description, Loc, I));
+}
+
+void InstrumentRegions::endRegion(StringRef Description, SMLoc Loc) {
+  auto It = ActiveRegions.find(Description);
+  if (It != ActiveRegions.end()) {
+    Regions[It->second]->setEndLocation(Loc);
+    ActiveRegions.erase(It);
+    return;
+  }
+
+  FoundErrors = true;
+  SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
+                  "found an invalid instrumentation region end directive");
+  if (!Description.empty()) {
+    SM.PrintMessage(Loc, llvm::SourceMgr::DK_Note,
+                    "unable to find an active instrumentation region named " +
+                        Description);
+  }
+}
+
+const SmallVector<SharedInstrument>
+InstrumentRegions::getActiveInstruments(SMLoc Loc) const {
+  SmallVector<SharedInstrument> AI;
+  for (auto &R : Regions) {
+    if (R->isLocInRange(Loc)) {
+      InstrumentRegion *IR = static_cast<InstrumentRegion *>(R.get());
+      AI.emplace_back(IR->getInstrument());
+    }
+  }
+  return AI;
 }
 
 } // namespace mca
diff --git a/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.h b/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.h
index 0e1e02a..b5b2f3a 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/CodeRegion.h
@@ -7,7 +7,8 @@
 //===----------------------------------------------------------------------===//
 /// \file
 ///
-/// This file implements class CodeRegion and CodeRegions.
+/// This file implements class CodeRegion and CodeRegions, InstrumentRegion,
+/// AnalysisRegions, and InstrumentRegions.
 ///
 /// A CodeRegion describes a region of assembly code guarded by special LLVM-MCA
 /// comment directives.
@@ -25,8 +26,32 @@
 /// description; internally, regions are described by a range of source
 /// locations (SMLoc objects).
 ///
-/// An instruction (a MCInst) is added to a region R only if its location is in
-/// range [R.RangeStart, R.RangeEnd].
+/// An instruction (a MCInst) is added to a CodeRegion R only if its
+/// location is in range [R.RangeStart, R.RangeEnd].
+///
+/// A InstrumentRegion describes a region of assembly code guarded by
+/// special LLVM-MCA comment directives.
+///
+///   # LLVM-MCA-<INSTRUMENTATION_TYPE> <data>
+///     ...  ## asm
+///
+/// where INSTRUMENTATION_TYPE is a type defined in llvm and expects to use
+/// data.
+///
+/// A comment starting with substring LLVM-MCA-<INSTRUMENTATION_TYPE>
+/// brings data into scope for llvm-mca to use in its analysis for
+/// all following instructions.
+///
+/// If the same INSTRUMENTATION_TYPE is found later in the instruction list,
+/// then the original InstrumentRegion will be automatically ended,
+/// and a new InstrumentRegion will begin.
+///
+/// If there are comments containing the different INSTRUMENTATION_TYPEs,
+/// then both data sets remain available. In contrast with a CodeRegion,
+/// an InstrumentRegion does not need a comment to end the region.
+//
+// An instruction (a MCInst) is added to an InstrumentRegion R only
+// if its location is in range [R.RangeStart, R.RangeEnd].
 //
 //===----------------------------------------------------------------------===//
 
@@ -38,6 +63,7 @@
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MCA/CustomBehaviour.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/SMLoc.h"
 #include "llvm/Support/SourceMgr.h"
@@ -81,9 +107,31 @@
   llvm::StringRef getDescription() const { return Description; }
 };
 
+/// Alias AnalysisRegion with CodeRegion since CodeRegionGenerator
+/// is absract and AnalysisRegionGenerator operates on AnalysisRegions
+using AnalysisRegion = CodeRegion;
+
+/// A CodeRegion that contains instrumentation that can be used
+/// in analysis of the region.
+class InstrumentRegion : public CodeRegion {
+  /// Instrument for this region.
+  SharedInstrument Instrument;
+
+public:
+  InstrumentRegion(llvm::StringRef Desc, llvm::SMLoc Start, SharedInstrument I)
+      : CodeRegion(Desc, Start), Instrument(I) {}
+
+public:
+  SharedInstrument getInstrument() const { return Instrument; }
+};
+
 class CodeRegionParseError final : public Error {};
 
 class CodeRegions {
+  CodeRegions(const CodeRegions &) = delete;
+  CodeRegions &operator=(const CodeRegions &) = delete;
+
+protected:
   // A source manager. Used by the tool to generate meaningful warnings.
   llvm::SourceMgr &SM;
 
@@ -92,11 +140,8 @@
   llvm::StringMap<unsigned> ActiveRegions;
   bool FoundErrors;
 
-  CodeRegions(const CodeRegions &) = delete;
-  CodeRegions &operator=(const CodeRegions &) = delete;
-
 public:
-  CodeRegions(llvm::SourceMgr &S);
+  CodeRegions(llvm::SourceMgr &S) : SM(S), FoundErrors(false) {}
 
   typedef std::vector<UniqueCodeRegion>::iterator iterator;
   typedef std::vector<UniqueCodeRegion>::const_iterator const_iterator;
@@ -106,8 +151,6 @@
   const_iterator begin() const { return Regions.cbegin(); }
   const_iterator end() const { return Regions.cend(); }
 
-  void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
-  void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
   void addInstruction(const llvm::MCInst &Instruction);
   llvm::SourceMgr &getSourceMgr() const { return SM; }
 
@@ -122,6 +165,28 @@
   }
 
   bool isValid() const { return !FoundErrors; }
+
+  bool isRegionActive(llvm::StringRef Description) const {
+    return ActiveRegions.find(Description) != ActiveRegions.end();
+  }
+};
+
+struct AnalysisRegions : public CodeRegions {
+  AnalysisRegions(llvm::SourceMgr &S);
+
+  void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc);
+  void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
+};
+
+struct InstrumentRegions : public CodeRegions {
+  InstrumentRegions(llvm::SourceMgr &S);
+
+  void beginRegion(llvm::StringRef Description, llvm::SMLoc Loc,
+                   SharedInstrument Instrument);
+  void endRegion(llvm::StringRef Description, llvm::SMLoc Loc);
+
+  const SmallVector<SharedInstrument>
+  getActiveInstruments(llvm::SMLoc Loc) const;
 };
 
 } // namespace mca
diff --git a/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp b/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
index cdecfba..b8e10fa 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.cpp
@@ -16,7 +16,6 @@
 #include "CodeRegionGenerator.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/MC/MCParser/MCAsmLexer.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
 #include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCTargetOptions.h"
@@ -30,15 +29,6 @@
 // This virtual dtor serves as the anchor for the CodeRegionGenerator class.
 CodeRegionGenerator::~CodeRegionGenerator() {}
 
-// A comment consumer that parses strings.  The only valid tokens are strings.
-class MCACommentConsumer : public AsmCommentConsumer {
-public:
-  CodeRegions &Regions;
-
-  MCACommentConsumer(CodeRegions &R) : Regions(R) {}
-  void HandleComment(SMLoc Loc, StringRef CommentText) override;
-};
-
 // This class provides the callbacks that occur when parsing input assembly.
 class MCStreamerWrapper final : public MCStreamer {
   CodeRegions &Regions;
@@ -58,9 +48,9 @@
   }
 
   void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
-                        unsigned ByteAlignment) override {}
+                        Align ByteAlignment) override {}
   void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
-                    uint64_t Size = 0, unsigned ByteAlignment = 0,
+                    uint64_t Size = 0, Align ByteAlignment = Align(1),
                     SMLoc Loc = SMLoc()) override {}
   void emitGPRel32Value(const MCExpr *Value) override {}
   void beginCOFFSymbolDef(const MCSymbol *Symbol) override {}
@@ -73,7 +63,53 @@
   }
 };
 
-void MCACommentConsumer::HandleComment(SMLoc Loc, StringRef CommentText) {
+Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
+    const std::unique_ptr<MCInstPrinter> &IP) {
+  MCTargetOptions Opts;
+  Opts.PreserveAsmComments = false;
+  CodeRegions &Regions = getRegions();
+  MCStreamerWrapper Str(Ctx, Regions);
+
+  // Need to initialize an MCTargetStreamer otherwise
+  // certain asm directives will cause a segfault.
+  // Using nulls() so that anything emitted by the MCTargetStreamer
+  // doesn't show up in the llvm-mca output.
+  raw_ostream &OSRef = nulls();
+  formatted_raw_ostream FOSRef(OSRef);
+  TheTarget.createAsmTargetStreamer(Str, FOSRef, IP.get(),
+                                    /*IsVerboseAsm=*/true);
+
+  // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
+  // comments.
+  std::unique_ptr<MCAsmParser> Parser(
+      createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI));
+  MCAsmLexer &Lexer = Parser->getLexer();
+  MCACommentConsumer *CCP = getCommentConsumer();
+  Lexer.setCommentConsumer(CCP);
+  // Enable support for MASM literal numbers (example: 05h, 101b).
+  Lexer.setLexMasmIntegers(true);
+
+  std::unique_ptr<MCTargetAsmParser> TAP(
+      TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts));
+  if (!TAP)
+    return make_error<StringError>(
+        "This target does not support assembly parsing.",
+        inconvertibleErrorCode());
+  Parser->setTargetParser(*TAP);
+  Parser->Run(false);
+
+  if (CCP->hadErr())
+    return make_error<StringError>("There was an error parsing comments.",
+                                   inconvertibleErrorCode());
+
+  // Set the assembler dialect from the input. llvm-mca will use this as the
+  // default dialect when printing reports.
+  AssemblerDialect = Parser->getAssemblerDialect();
+  return Regions;
+}
+
+void AnalysisRegionCommentConsumer::HandleComment(SMLoc Loc,
+                                                  StringRef CommentText) {
   // Skip empty comments.
   StringRef Comment(CommentText);
   if (Comment.empty())
@@ -107,44 +143,66 @@
   Regions.beginRegion(Comment, Loc);
 }
 
-Expected<const CodeRegions &> AsmCodeRegionGenerator::parseCodeRegions(
-    const std::unique_ptr<MCInstPrinter> &IP) {
-  MCTargetOptions Opts;
-  Opts.PreserveAsmComments = false;
-  MCStreamerWrapper Str(Ctx, Regions);
+void InstrumentRegionCommentConsumer::HandleComment(SMLoc Loc,
+                                                    StringRef CommentText) {
+  // Skip empty comments.
+  StringRef Comment(CommentText);
+  if (Comment.empty())
+    return;
 
-  // Need to initialize an MCTargetStreamer otherwise
-  // certain asm directives will cause a segfault.
-  // Using nulls() so that anything emitted by the MCTargetStreamer
-  // doesn't show up in the llvm-mca output.
-  raw_ostream &OSRef = nulls();
-  formatted_raw_ostream FOSRef(OSRef);
-  TheTarget.createAsmTargetStreamer(Str, FOSRef, IP.get(),
-                                    /*IsVerboseAsm=*/true);
+  // Skip spaces and tabs.
+  unsigned Position = Comment.find_first_not_of(" \t");
+  if (Position >= Comment.size())
+    // We reached the end of the comment. Bail out.
+    return;
+  Comment = Comment.drop_front(Position);
 
-  // Create a MCAsmParser and setup the lexer to recognize llvm-mca ASM
-  // comments.
-  std::unique_ptr<MCAsmParser> Parser(
-      createMCAsmParser(Regions.getSourceMgr(), Ctx, Str, MAI));
-  MCAsmLexer &Lexer = Parser->getLexer();
-  MCACommentConsumer CC(Regions);
-  Lexer.setCommentConsumer(&CC);
-  // Enable support for MASM literal numbers (example: 05h, 101b).
-  Lexer.setLexMasmIntegers(true);
+  // Bail out if not an MCA style comment
+  if (!Comment.consume_front("LLVM-MCA-"))
+    return;
 
-  std::unique_ptr<MCTargetAsmParser> TAP(
-      TheTarget.createMCAsmParser(STI, *Parser, MCII, Opts));
-  if (!TAP)
-    return make_error<StringError>(
-        "This target does not support assembly parsing.",
-        inconvertibleErrorCode());
-  Parser->setTargetParser(*TAP);
-  Parser->Run(false);
+  // Skip AnalysisRegion comments
+  if (Comment.consume_front("BEGIN") || Comment.consume_front("END"))
+    return;
 
-  // Set the assembler dialect from the input. llvm-mca will use this as the
-  // default dialect when printing reports.
-  AssemblerDialect = Parser->getAssemblerDialect();
-  return Regions;
+  if (IM.shouldIgnoreInstruments())
+    return;
+
+  auto [InstrumentKind, Data] = Comment.split(" ");
+
+  // An error if not of the form LLVM-MCA-TARGET-KIND
+  if (!IM.supportsInstrumentType(InstrumentKind)) {
+    if (InstrumentKind.empty())
+      SM.PrintMessage(
+          Loc, llvm::SourceMgr::DK_Error,
+          "No instrumentation kind was provided in LLVM-MCA comment");
+    else
+      SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
+                      "Unknown instrumentation type in LLVM-MCA comment: " +
+                          InstrumentKind);
+    FoundError = true;
+    return;
+  }
+
+  SharedInstrument I = IM.createInstrument(InstrumentKind, Data);
+  if (!I) {
+    if (Data.empty())
+      SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
+                      "Failed to create " + InstrumentKind +
+                          " instrument with no data");
+    else
+      SM.PrintMessage(Loc, llvm::SourceMgr::DK_Error,
+                      "Failed to create " + InstrumentKind +
+                          " instrument with data: " + Data);
+    FoundError = true;
+    return;
+  }
+
+  // End InstrumentType region if one is open
+  if (Regions.isRegionActive(InstrumentKind))
+    Regions.endRegion(InstrumentKind, Loc);
+  // Start new instrumentation region
+  Regions.beginRegion(InstrumentKind, Loc, I);
 }
 
 } // namespace mca
diff --git a/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h b/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h
index ac02131..88621ed 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/CodeRegionGenerator.h
@@ -19,8 +19,10 @@
 #include "CodeRegion.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/MCA/CustomBehaviour.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/SourceMgr.h"
 #include <memory>
@@ -28,24 +30,96 @@
 namespace llvm {
 namespace mca {
 
-/// This class is responsible for parsing the input given to the llvm-mca
-/// driver, and converting that into a CodeRegions instance.
-class CodeRegionGenerator {
+class MCACommentConsumer : public AsmCommentConsumer {
 protected:
-  CodeRegions Regions;
-  CodeRegionGenerator(const CodeRegionGenerator &) = delete;
-  CodeRegionGenerator &operator=(const CodeRegionGenerator &) = delete;
+  bool FoundError;
 
 public:
-  CodeRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
-  virtual ~CodeRegionGenerator();
-  virtual Expected<const CodeRegions &>
-  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
+  MCACommentConsumer() : FoundError(false) {}
+
+  bool hadErr() const { return FoundError; }
 };
 
-/// This class is responsible for parsing input ASM and generating
-/// a CodeRegions instance.
-class AsmCodeRegionGenerator final : public CodeRegionGenerator {
+/// A comment consumer that parses strings.  The only valid tokens are strings.
+class AnalysisRegionCommentConsumer : public MCACommentConsumer {
+  AnalysisRegions &Regions;
+
+public:
+  AnalysisRegionCommentConsumer(AnalysisRegions &R) : Regions(R) {}
+
+  /// Parses a comment. It begins a new region if it is of the form
+  /// LLVM-MCA-BEGIN. It ends a region if it is of the form LLVM-MCA-END.
+  /// Regions can be optionally named if they are of the form
+  /// LLVM-MCA-BEGIN <name> or LLVM-MCA-END <name>. Subregions are
+  /// permitted, but a region that begins while another region is active
+  /// must be ended before the outer region is ended. If thre is only one
+  /// active region, LLVM-MCA-END does not need to provide a name.
+  void HandleComment(SMLoc Loc, StringRef CommentText) override;
+};
+
+/// A comment consumer that parses strings to create InstrumentRegions.
+/// The only valid tokens are strings.
+class InstrumentRegionCommentConsumer : public MCACommentConsumer {
+  llvm::SourceMgr &SM;
+
+  InstrumentRegions &Regions;
+
+  InstrumentManager &IM;
+
+public:
+  InstrumentRegionCommentConsumer(llvm::SourceMgr &SM, InstrumentRegions &R,
+                                  InstrumentManager &IM)
+      : SM(SM), Regions(R), IM(IM) {}
+
+  /// Parses a comment. It begins a new region if it is of the form
+  /// LLVM-MCA-<INSTRUMENTATION_TYPE> <data> where INSTRUMENTATION_TYPE
+  /// is a valid InstrumentKind. If there is already an active
+  /// region of type INSTRUMENATION_TYPE, then it will end the active
+  /// one and begin a new one using the new data.
+  void HandleComment(SMLoc Loc, StringRef CommentText) override;
+};
+
+/// This abstract class is responsible for parsing the input given to
+/// the llvm-mca driver, and converting that into a CodeRegions instance.
+class CodeRegionGenerator {
+protected:
+  CodeRegionGenerator(const CodeRegionGenerator &) = delete;
+  CodeRegionGenerator &operator=(const CodeRegionGenerator &) = delete;
+  virtual Expected<const CodeRegions &>
+  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
+
+public:
+  CodeRegionGenerator() {}
+  virtual ~CodeRegionGenerator();
+};
+
+/// Abastract CodeRegionGenerator with AnalysisRegions member
+class AnalysisRegionGenerator : public virtual CodeRegionGenerator {
+protected:
+  AnalysisRegions Regions;
+
+public:
+  AnalysisRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
+
+  virtual Expected<const AnalysisRegions &>
+  parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
+};
+
+/// Abstract CodeRegionGenerator with InstrumentRegionsRegions member
+class InstrumentRegionGenerator : public virtual CodeRegionGenerator {
+protected:
+  InstrumentRegions Regions;
+
+public:
+  InstrumentRegionGenerator(llvm::SourceMgr &SM) : Regions(SM) {}
+
+  virtual Expected<const InstrumentRegions &>
+  parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) = 0;
+};
+
+/// This abstract class is responsible for parsing input ASM and
+/// generating a CodeRegions instance.
+class AsmCodeRegionGenerator : public virtual CodeRegionGenerator {
   const Target &TheTarget;
   MCContext &Ctx;
   const MCAsmInfo &MAI;
@@ -54,17 +128,77 @@
   unsigned AssemblerDialect; // This is set during parsing.
 
 public:
-  AsmCodeRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C,
-                         const MCAsmInfo &A, const MCSubtargetInfo &S,
-                         const MCInstrInfo &I)
-      : CodeRegionGenerator(SM), TheTarget(T), Ctx(C), MAI(A), STI(S), MCII(I),
-        AssemblerDialect(0) {}
+  AsmCodeRegionGenerator(const Target &T, MCContext &C, const MCAsmInfo &A,
+                         const MCSubtargetInfo &S, const MCInstrInfo &I)
+      : TheTarget(T), Ctx(C), MAI(A), STI(S), MCII(I), AssemblerDialect(0) {}
+
+  virtual MCACommentConsumer *getCommentConsumer() = 0;
+  virtual CodeRegions &getRegions() = 0;
 
   unsigned getAssemblerDialect() const { return AssemblerDialect; }
   Expected<const CodeRegions &>
   parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override;
 };
 
+class AsmAnalysisRegionGenerator final : public AnalysisRegionGenerator,
+                                         public AsmCodeRegionGenerator {
+  AnalysisRegionCommentConsumer CC;
+
+public:
+  AsmAnalysisRegionGenerator(const Target &T, llvm::SourceMgr &SM, MCContext &C,
+                             const MCAsmInfo &A, const MCSubtargetInfo &S,
+                             const MCInstrInfo &I)
+      : AnalysisRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
+        CC(Regions) {}
+
+  MCACommentConsumer *getCommentConsumer() override { return &CC; };
+  CodeRegions &getRegions() override { return Regions; };
+
+  Expected<const AnalysisRegions &>
+  parseAnalysisRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
+    Expected<const CodeRegions &> RegionsOrErr = parseCodeRegions(IP);
+    if (!RegionsOrErr)
+      return RegionsOrErr.takeError();
+    else
+      return static_cast<const AnalysisRegions &>(*RegionsOrErr);
+  }
+
+  Expected<const CodeRegions &>
+  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
+    return AsmCodeRegionGenerator::parseCodeRegions(IP);
+  }
+};
+
+class AsmInstrumentRegionGenerator final : public InstrumentRegionGenerator,
+                                           public AsmCodeRegionGenerator {
+  InstrumentRegionCommentConsumer CC;
+
+public:
+  AsmInstrumentRegionGenerator(const Target &T, llvm::SourceMgr &SM,
+                               MCContext &C, const MCAsmInfo &A,
+                               const MCSubtargetInfo &S, const MCInstrInfo &I,
+                               InstrumentManager &IM)
+      : InstrumentRegionGenerator(SM), AsmCodeRegionGenerator(T, C, A, S, I),
+        CC(SM, Regions, IM) {}
+
+  MCACommentConsumer *getCommentConsumer() override { return &CC; };
+  CodeRegions &getRegions() override { return Regions; };
+
+  Expected<const InstrumentRegions &>
+  parseInstrumentRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
+    Expected<const CodeRegions &> RegionsOrErr = parseCodeRegions(IP);
+    if (!RegionsOrErr)
+      return RegionsOrErr.takeError();
+    else
+      return static_cast<const InstrumentRegions &>(*RegionsOrErr);
+  }
+
+  Expected<const CodeRegions &>
+  parseCodeRegions(const std::unique_ptr<MCInstPrinter> &IP) override {
+    return AsmCodeRegionGenerator::parseCodeRegions(IP);
+  }
+};
+
 } // namespace mca
 } // namespace llvm
 
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp b/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
index d3f9738..257fdca 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.cpp
@@ -71,7 +71,7 @@
       TempStream << ' ';
 
     if (IIVDEntry.RThroughput) {
-      double RT = IIVDEntry.RThroughput.value();
+      double RT = *IIVDEntry.RThroughput;
       TempStream << format("%.2f", RT) << ' ';
       if (RT < 10.0)
         TempStream << "  ";
diff --git a/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h b/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h
index c35d316..bddd01a 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h
+++ b/src/llvm-project/llvm/tools/llvm-mca/Views/InstructionInfoView.h
@@ -61,7 +61,7 @@
   struct InstructionInfoViewData {
     unsigned NumMicroOpcodes = 0;
     unsigned Latency = 0;
-    Optional<double> RThroughput = 0.0;
+    std::optional<double> RThroughput = 0.0;
     bool mayLoad = false;
     bool mayStore = false;
     bool hasUnmodeledSideEffects = false;
diff --git a/src/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp b/src/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp
index 6f7b74f..73c3418 100644
--- a/src/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mca/llvm-mca.cpp
@@ -231,6 +231,12 @@
         "Disable custom behaviour (use the default class which does nothing)."),
     cl::cat(ViewOptions), cl::init(false));
 
+static cl::opt<bool> DisableInstrumentManager(
+    "disable-im",
+    cl::desc("Disable instrumentation manager (use the default class which "
+             "ignores instruments.)."),
+    cl::cat(ViewOptions), cl::init(false));
+
 namespace {
 
 const Target *getTarget(const char *ProgName) {
@@ -316,6 +322,9 @@
   InitializeAllAsmParsers();
   InitializeAllTargetMCAs();
 
+  // Register the Target and CPU printer for --version.
+  cl::AddExtraVersionPrinter(sys::printDefaultTargetAndDetectedCPU);
+
   // Enable printing of available targets when flag --version is specified.
   cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion);
 
@@ -407,7 +416,7 @@
 
   // Need to initialize an MCInstPrinter as it is
   // required for initializing the MCTargetStreamer
-  // which needs to happen within the CRG.parseCodeRegions() call below.
+  // which needs to happen within the CRG.parseAnalysisRegions() call below.
   // Without an MCTargetStreamer, certain assembly directives can trigger a
   // segfault. (For example, the .cv_fpo_proc directive on x86 will segfault if
   // we don't initialize the MCTargetStreamer.)
@@ -424,9 +433,10 @@
   }
 
   // Parse the input and create CodeRegions that llvm-mca can analyze.
-  mca::AsmCodeRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI, *MCII);
-  Expected<const mca::CodeRegions &> RegionsOrErr =
-      CRG.parseCodeRegions(std::move(IPtemp));
+  mca::AsmAnalysisRegionGenerator CRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI,
+                                      *MCII);
+  Expected<const mca::AnalysisRegions &> RegionsOrErr =
+      CRG.parseAnalysisRegions(std::move(IPtemp));
   if (!RegionsOrErr) {
     if (auto Err =
             handleErrors(RegionsOrErr.takeError(), [](const StringError &E) {
@@ -437,7 +447,7 @@
     }
     return 1;
   }
-  const mca::CodeRegions &Regions = *RegionsOrErr;
+  const mca::AnalysisRegions &Regions = *RegionsOrErr;
 
   // Early exit if errors were found by the code region parsing logic.
   if (!Regions.isValid())
@@ -448,6 +458,39 @@
     return 1;
   }
 
+  std::unique_ptr<mca::InstrumentManager> IM;
+  if (!DisableInstrumentManager) {
+    IM = std::unique_ptr<mca::InstrumentManager>(
+        TheTarget->createInstrumentManager(*STI, *MCII));
+  }
+  if (!IM) {
+    // If the target doesn't have its own IM implemented (or the -disable-cb
+    // flag is set) then we use the base class (which does nothing).
+    IM = std::make_unique<mca::InstrumentManager>(*STI, *MCII);
+  }
+
+  // Parse the input and create InstrumentRegion that llvm-mca
+  // can use to improve analysis.
+  mca::AsmInstrumentRegionGenerator IRG(*TheTarget, SrcMgr, Ctx, *MAI, *STI,
+                                        *MCII, *IM);
+  Expected<const mca::InstrumentRegions &> InstrumentRegionsOrErr =
+      IRG.parseInstrumentRegions(std::move(IPtemp));
+  if (!InstrumentRegionsOrErr) {
+    if (auto Err = handleErrors(InstrumentRegionsOrErr.takeError(),
+                                [](const StringError &E) {
+                                  WithColor::error() << E.getMessage() << '\n';
+                                })) {
+      // Default case.
+      WithColor::error() << toString(std::move(Err)) << '\n';
+    }
+    return 1;
+  }
+  const mca::InstrumentRegions &InstrumentRegions = *InstrumentRegionsOrErr;
+
+  // Early exit if errors were found by the instrumentation parsing logic.
+  if (!InstrumentRegions.isValid())
+    return 1;
+
   // Now initialize the output file.
   auto OF = getOutputStream();
   if (std::error_code EC = OF.getError()) {
@@ -491,7 +534,7 @@
   }
 
   // Create an instruction builder.
-  mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get());
+  mca::InstrBuilder IB(*STI, *MCII, *MRI, MCIA.get(), *IM);
 
   // Create a context to control ownership of the pipeline hardware.
   mca::Context MCA(*MRI, *STI);
@@ -512,7 +555,7 @@
   assert(MAB && "Unable to create asm backend!");
 
   json::Object JSONOutput;
-  for (const std::unique_ptr<mca::CodeRegion> &Region : Regions) {
+  for (const std::unique_ptr<mca::AnalysisRegion> &Region : Regions) {
     // Skip empty code regions.
     if (Region->empty())
       continue;
@@ -527,8 +570,12 @@
 
     SmallVector<std::unique_ptr<mca::Instruction>> LoweredSequence;
     for (const MCInst &MCI : Insts) {
+      SMLoc Loc = MCI.getLoc();
+      const SmallVector<mca::SharedInstrument> Instruments =
+          InstrumentRegions.getActiveInstruments(Loc);
+
       Expected<std::unique_ptr<mca::Instruction>> Inst =
-          IB.createInstruction(MCI);
+          IB.createInstruction(MCI, Instruments);
       if (!Inst) {
         if (auto NewE = handleErrors(
                 Inst.takeError(),
diff --git a/src/llvm-project/llvm/tools/llvm-ml/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-ml/CMakeLists.txt
index 7c79039..2b2a116a 100644
--- a/src/llvm-project/llvm/tools/llvm-ml/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-ml/CMakeLists.txt
@@ -7,6 +7,7 @@
   MCParser
   Option
   Support
+  TargetParser
   )
 
 set(LLVM_TARGET_DEFINITIONS Opts.td)
diff --git a/src/llvm-project/llvm/tools/llvm-ml/Disassembler.cpp b/src/llvm-project/llvm/tools/llvm-ml/Disassembler.cpp
index 6a96c88..72d88d9 100644
--- a/src/llvm-project/llvm/tools/llvm-ml/Disassembler.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ml/Disassembler.cpp
@@ -61,7 +61,7 @@
       SM.PrintMessage(SMLoc::getFromPointer(Bytes.second[Index]),
                       SourceMgr::DK_Warning,
                       "potentially undefined instruction encoding");
-      LLVM_FALLTHROUGH;
+      [[fallthrough]];
 
     case MCDisassembler::Success:
       Streamer.emitInstruction(Inst, STI);
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 12cd727..0af4854 100644
--- a/src/llvm-project/llvm/tools/llvm-ml/llvm-ml.cpp
+++ b/src/llvm-project/llvm/tools/llvm-ml/llvm-ml.cpp
@@ -44,6 +44,7 @@
 #include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Support/WithColor.h"
 #include <ctime>
+#include <optional>
 
 using namespace llvm;
 using namespace llvm::opt;
@@ -59,11 +60,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#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
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -75,9 +79,9 @@
 #undef OPTION
 };
 
-class MLOptTable : public opt::OptTable {
+class MLOptTable : public opt::GenericOptTable {
 public:
-  MLOptTable() : OptTable(InfoTable, /*IgnoreCase=*/false) {}
+  MLOptTable() : opt::GenericOptTable(InfoTable, /*IgnoreCase=*/false) {}
 };
 } // namespace
 
@@ -201,7 +205,7 @@
 
   MLOptTable T;
   unsigned MissingArgIndex, MissingArgCount;
-  ArrayRef<const char *> ArgsArr = makeArrayRef(Argv + 1, Argc - 1);
+  ArrayRef<const char *> ArgsArr = ArrayRef(Argv + 1, Argc - 1);
   opt::InputArgList InputArgs =
       T.ParseArgs(ArgsArr, MissingArgIndex, MissingArgCount);
 
@@ -303,7 +307,7 @@
   std::vector<std::string> IncludeDirs =
       InputArgs.getAllArgValues(OPT_include_path);
   if (!InputArgs.hasArg(OPT_ignore_include_envvar)) {
-    if (llvm::Optional<std::string> IncludeEnvVar =
+    if (std::optional<std::string> IncludeEnvVar =
             llvm::sys::Process::GetEnv("INCLUDE")) {
       SmallVector<StringRef, 8> Dirs;
       StringRef(*IncludeEnvVar)
diff --git a/src/llvm-project/llvm/tools/llvm-mt/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-mt/CMakeLists.txt
index e4e9946..dd427a2 100644
--- a/src/llvm-project/llvm/tools/llvm-mt/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-mt/CMakeLists.txt
@@ -11,4 +11,7 @@
 
 add_llvm_tool(llvm-mt
   llvm-mt.cpp
+  DEPENDS
+  MtTableGen
+  GENERATE_DRIVER
   )
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 f938396..d460fd6 100644
--- a/src/llvm-project/llvm/tools/llvm-mt/llvm-mt.cpp
+++ b/src/llvm-project/llvm/tools/llvm-mt/llvm-mt.cpp
@@ -41,11 +41,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#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
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
 {                                                                              \
@@ -57,9 +60,9 @@
 #undef OPTION
 };
 
-class CvtResOptTable : public opt::OptTable {
+class CvtResOptTable : public opt::GenericOptTable {
 public:
-  CvtResOptTable() : OptTable(InfoTable, true) {}
+  CvtResOptTable() : opt::GenericOptTable(InfoTable, true) {}
 };
 } // namespace
 
@@ -79,12 +82,12 @@
     });
 }
 
-int main(int Argc, const char **Argv) {
+int llvm_mt_main(int Argc, char **Argv) {
   InitLLVM X(Argc, Argv);
 
   CvtResOptTable T;
   unsigned MAI, MAC;
-  ArrayRef<const char *> ArgsArr = makeArrayRef(Argv + 1, Argc - 1);
+  ArrayRef<const char *> ArgsArr = ArrayRef(Argv + 1, Argc - 1);
   opt::InputArgList InputArgs = T.ParseArgs(ArgsArr, MAI, MAC);
 
   for (auto *Arg : InputArgs.filtered(OPT_INPUT)) {
@@ -150,9 +153,9 @@
     bool Same = false;
     if (OutBuffOrErr) {
       const std::unique_ptr<MemoryBuffer> &FileBuffer = *OutBuffOrErr;
-      Same = std::equal(OutputBuffer->getBufferStart(),
-                        OutputBuffer->getBufferEnd(),
-                        FileBuffer->getBufferStart());
+      Same = std::equal(
+          OutputBuffer->getBufferStart(), OutputBuffer->getBufferEnd(),
+          FileBuffer->getBufferStart(), FileBuffer->getBufferEnd());
     }
     if (!Same) {
 #if LLVM_ON_UNIX
diff --git a/src/llvm-project/llvm/tools/llvm-nm/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-nm/CMakeLists.txt
index 4ad5370..cd69712 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
+  TargetParser
   TextAPI
   )
 
@@ -21,6 +22,7 @@
   DEPENDS
   NmOptsTableGen
   intrinsics_gen
+  GENERATE_DRIVER
   )
 
 if(LLVM_INSTALL_BINUTILS_SYMLINKS)
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 f0def8b..55319d0 100644
--- a/src/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
+++ b/src/llvm-project/llvm/tools/llvm-nm/llvm-nm.cpp
@@ -16,6 +16,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
 #include "llvm/BinaryFormat/COFF.h"
 #include "llvm/BinaryFormat/XCOFF.h"
 #include "llvm/Demangle/Demangle.h"
@@ -39,6 +40,7 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/Host.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Program.h"
@@ -62,11 +64,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#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
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -78,9 +83,11 @@
 #undef OPTION
 };
 
-class NmOptTable : public opt::OptTable {
+class NmOptTable : public opt::GenericOptTable {
 public:
-  NmOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  NmOptTable() : opt::GenericOptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 
 enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
@@ -611,7 +618,7 @@
 };
 
 static const char *getDarwinStabString(uint8_t NType) {
-  for (auto I : makeArrayRef(DarwinStabNames))
+  for (auto I : ArrayRef(DarwinStabNames))
     if (I.NType == NType)
       return I.Name;
   return nullptr;
@@ -645,25 +652,25 @@
     outs() << format("   %02x", NType);
 }
 
-static Optional<std::string> demangle(StringRef Name) {
+static std::optional<std::string> demangle(StringRef Name) {
   std::string Demangled;
   if (nonMicrosoftDemangle(Name.str().c_str(), Demangled))
     return Demangled;
-  return None;
+  return std::nullopt;
 }
 
-static Optional<std::string> demangleXCOFF(StringRef Name) {
+static std::optional<std::string> demangleXCOFF(StringRef Name) {
   if (Name.empty() || Name[0] != '.')
     return demangle(Name);
 
   Name = Name.drop_front();
-  Optional<std::string> DemangledName = demangle(Name);
+  std::optional<std::string> DemangledName = demangle(Name);
   if (DemangledName)
     return "." + *DemangledName;
-  return None;
+  return std::nullopt;
 }
 
-static Optional<std::string> demangleMachO(StringRef Name) {
+static std::optional<std::string> demangleMachO(StringRef Name) {
   if (!Name.empty() && Name[0] == '_')
     Name = Name.drop_front();
   return demangle(Name);
@@ -760,12 +767,12 @@
     std::string Name = S.Name;
     MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj);
     if (Demangle) {
-      function_ref<Optional<std::string>(StringRef)> Fn = ::demangle;
+      function_ref<std::optional<std::string>(StringRef)> Fn = ::demangle;
       if (Obj.isXCOFF())
         Fn = demangleXCOFF;
       if (Obj.isMachO())
         Fn = demangleMachO;
-      if (Optional<std::string> Opt = Fn(S.Name))
+      if (std::optional<std::string> Opt = Fn(S.Name))
         Name = *Opt;
     }
 
@@ -2287,17 +2294,15 @@
   }
 
   // Delete symbols which should not be printed from SymolList.
-  SymbolList.erase(
-      llvm::remove_if(SymbolList,
-                      [](const NMSymbol &s) { return !s.shouldPrint(); }),
-      SymbolList.end());
+  llvm::erase_if(SymbolList,
+                 [](const NMSymbol &s) { return !s.shouldPrint(); });
   sortSymbolList(SymbolList);
   SymbolList.erase(std::unique(SymbolList.begin(), SymbolList.end()),
                    SymbolList.end());
   printExportSymbolList(SymbolList);
 }
 
-int main(int argc, char **argv) {
+int llvm_nm_main(int argc, char **argv) {
   InitLLVM X(argc, argv);
   BumpPtrAllocator A;
   StringSaver Saver(A);
@@ -2373,17 +2378,32 @@
   UndefinedOnly = Args.hasArg(OPT_undefined_only);
   WithoutAliases = Args.hasArg(OPT_without_aliases);
 
-  StringRef Mode = Args.getLastArgValue(OPT_X, "any");
-  if (Mode == "32")
-    BitMode = BitModeTy::Bit32;
-  else if (Mode == "64")
-    BitMode = BitModeTy::Bit64;
-  else if (Mode == "32_64")
-    BitMode = BitModeTy::Bit32_64;
-  else if (Mode == "any")
+  // Get BitMode from enviornment variable "OBJECT_MODE" for AIX OS, if
+  // specified.
+  Triple HostTriple(sys::getProcessTriple());
+  if (HostTriple.isOSAIX()) {
+    BitMode = StringSwitch<BitModeTy>(getenv("OBJECT_MODE"))
+                  .Case("32", BitModeTy::Bit32)
+                  .Case("64", BitModeTy::Bit64)
+                  .Case("32_64", BitModeTy::Bit32_64)
+                  .Case("any", BitModeTy::Any)
+                  .Default(BitModeTy::Bit32);
+  } else
     BitMode = BitModeTy::Any;
-  else
-    error("-X value should be one of: 32, 64, 32_64, (default) any");
+
+  if (Arg *A = Args.getLastArg(OPT_X)) {
+    StringRef Mode = A->getValue();
+    if (Mode == "32")
+      BitMode = BitModeTy::Bit32;
+    else if (Mode == "64")
+      BitMode = BitModeTy::Bit64;
+    else if (Mode == "32_64")
+      BitMode = BitModeTy::Bit32_64;
+    else if (Mode == "any")
+      BitMode = BitModeTy::Any;
+    else
+      error("-X value should be one of: 32, 64, 32_64, (default) any");
+  }
 
   // Mach-O specific options.
   FormatMachOasHex = Args.hasArg(OPT_x);
@@ -2459,4 +2479,5 @@
 
   if (HadError)
     return 1;
+  return 0;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-objcopy/CMakeLists.txt
index ca94d4a..1c73a17 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/CMakeLists.txt
@@ -3,6 +3,7 @@
   ObjCopy
   Option
   Support
+  TargetParser
   MC
   BinaryFormat
   )
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index 7db1e79..577b837 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -7,7 +7,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "ObjcopyOptions.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
@@ -37,32 +36,29 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const OBJCOPY_##NAME[] = VALUE;
+namespace objcopy_opt {
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
 #include "ObjcopyOpts.inc"
 #undef PREFIX
 
-const opt::OptTable::Info ObjcopyInfoTable[] = {
+static constexpr opt::OptTable::Info ObjcopyInfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
-  {OBJCOPY_##PREFIX,                                                           \
-   NAME,                                                                       \
-   HELPTEXT,                                                                   \
-   METAVAR,                                                                    \
-   OBJCOPY_##ID,                                                               \
-   opt::Option::KIND##Class,                                                   \
-   PARAM,                                                                      \
-   FLAGS,                                                                      \
-   OBJCOPY_##GROUP,                                                            \
-   OBJCOPY_##ALIAS,                                                            \
-   ALIASARGS,                                                                  \
-   VALUES},
+  {PREFIX,          NAME,         HELPTEXT,                                    \
+   METAVAR,         OBJCOPY_##ID, opt::Option::KIND##Class,                    \
+   PARAM,           FLAGS,        OBJCOPY_##GROUP,                             \
+   OBJCOPY_##ALIAS, ALIASARGS,    VALUES},
 #include "ObjcopyOpts.inc"
 #undef OPTION
 };
+} // namespace objcopy_opt
 
-class ObjcopyOptTable : public opt::OptTable {
+class ObjcopyOptTable : public opt::GenericOptTable {
 public:
-  ObjcopyOptTable() : OptTable(ObjcopyInfoTable) {
+  ObjcopyOptTable() : opt::GenericOptTable(objcopy_opt::ObjcopyInfoTable) {
     setGroupedShortOptions(true);
   }
 };
@@ -76,15 +72,19 @@
 #undef OPTION
 };
 
+namespace install_name_tool {
+
 #define PREFIX(NAME, VALUE)                                                    \
-  const char *const INSTALL_NAME_TOOL_##NAME[] = VALUE;
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
 #include "InstallNameToolOpts.inc"
 #undef PREFIX
 
-const opt::OptTable::Info InstallNameToolInfoTable[] = {
+static constexpr opt::OptTable::Info InstallNameToolInfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
-  {INSTALL_NAME_TOOL_##PREFIX,                                                 \
+  {PREFIX,                                                                     \
    NAME,                                                                       \
    HELPTEXT,                                                                   \
    METAVAR,                                                                    \
@@ -99,10 +99,12 @@
 #include "InstallNameToolOpts.inc"
 #undef OPTION
 };
+} // namespace install_name_tool
 
-class InstallNameToolOptTable : public opt::OptTable {
+class InstallNameToolOptTable : public opt::GenericOptTable {
 public:
-  InstallNameToolOptTable() : OptTable(InstallNameToolInfoTable) {}
+  InstallNameToolOptTable()
+      : GenericOptTable(install_name_tool::InstallNameToolInfoTable) {}
 };
 
 enum BitcodeStripID {
@@ -114,14 +116,19 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const BITCODE_STRIP_##NAME[] = VALUE;
+namespace bitcode_strip {
+
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
 #include "BitcodeStripOpts.inc"
 #undef PREFIX
 
-const opt::OptTable::Info BitcodeStripInfoTable[] = {
+static constexpr opt::OptTable::Info BitcodeStripInfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
-  {BITCODE_STRIP_##PREFIX,                                                     \
+  {PREFIX,                                                                     \
    NAME,                                                                       \
    HELPTEXT,                                                                   \
    METAVAR,                                                                    \
@@ -136,10 +143,12 @@
 #include "BitcodeStripOpts.inc"
 #undef OPTION
 };
+} // namespace bitcode_strip
 
-class BitcodeStripOptTable : public opt::OptTable {
+class BitcodeStripOptTable : public opt::GenericOptTable {
 public:
-  BitcodeStripOptTable() : OptTable(BitcodeStripInfoTable) {}
+  BitcodeStripOptTable()
+      : opt::GenericOptTable(bitcode_strip::BitcodeStripInfoTable) {}
 };
 
 enum StripID {
@@ -151,24 +160,31 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const STRIP_##NAME[] = VALUE;
+namespace strip {
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
 #include "StripOpts.inc"
 #undef PREFIX
 
-const opt::OptTable::Info StripInfoTable[] = {
+static constexpr opt::OptTable::Info StripInfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
-  {STRIP_##PREFIX, NAME,       HELPTEXT,                                       \
-   METAVAR,        STRIP_##ID, opt::Option::KIND##Class,                       \
-   PARAM,          FLAGS,      STRIP_##GROUP,                                  \
-   STRIP_##ALIAS,  ALIASARGS,  VALUES},
+  {PREFIX,        NAME,       HELPTEXT,                                        \
+   METAVAR,       STRIP_##ID, opt::Option::KIND##Class,                        \
+   PARAM,         FLAGS,      STRIP_##GROUP,                                   \
+   STRIP_##ALIAS, ALIASARGS,  VALUES},
 #include "StripOpts.inc"
 #undef OPTION
 };
+} // namespace strip
 
-class StripOptTable : public opt::OptTable {
+class StripOptTable : public opt::GenericOptTable {
 public:
-  StripOptTable() : OptTable(StripInfoTable) { setGroupedShortOptions(true); }
+  StripOptTable() : GenericOptTable(strip::StripInfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 
 } // namespace
@@ -226,7 +242,7 @@
 
   if (NameAndFlags.size() > 1) {
     Expected<SectionFlag> ParsedFlagSet =
-        parseSectionFlagSet(makeArrayRef(NameAndFlags).drop_front());
+        parseSectionFlagSet(ArrayRef(NameAndFlags).drop_front());
     if (!ParsedFlagSet)
       return ParsedFlagSet.takeError();
     SR.NewFlags = *ParsedFlagSet;
@@ -559,9 +575,8 @@
   ObjcopyOptTable T;
 
   const char *const *DashDash =
-      std::find_if(RawArgsArr.begin(), RawArgsArr.end(),
-                   [](StringRef Str) { return Str == "--"; });
-  ArrayRef<const char *> ArgsArr = makeArrayRef(RawArgsArr.begin(), DashDash);
+      llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
+  ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
   if (DashDash != RawArgsArr.end())
     DashDash = std::next(DashDash);
 
@@ -587,11 +602,11 @@
 
   SmallVector<const char *, 2> Positional;
 
-  for (auto Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
     return createStringError(errc::invalid_argument, "unknown argument '%s'",
                              Arg->getAsString(InputArgs).c_str());
 
-  for (auto Arg : InputArgs.filtered(OBJCOPY_INPUT))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT))
     Positional.push_back(Arg->getValue());
   std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
 
@@ -721,17 +736,18 @@
 
   if (const auto *A = InputArgs.getLastArg(OBJCOPY_compress_debug_sections)) {
     Config.CompressionType = StringSwitch<DebugCompressionType>(A->getValue())
-                                 .Case("zlib", DebugCompressionType::Z)
+                                 .Case("zlib", DebugCompressionType::Zlib)
+                                 .Case("zstd", DebugCompressionType::Zstd)
                                  .Default(DebugCompressionType::None);
-    if (Config.CompressionType == DebugCompressionType::None)
+    if (Config.CompressionType == DebugCompressionType::None) {
       return createStringError(
           errc::invalid_argument,
           "invalid or unsupported --compress-debug-sections format: %s",
           A->getValue());
-    if (!compression::zlib::isAvailable())
-      return createStringError(
-          errc::invalid_argument,
-          "LLVM was not compiled with LLVM_ENABLE_ZLIB: can not compress");
+    }
+    if (const char *Reason = compression::getReasonIfUnsupported(
+            compression::formatFor(Config.CompressionType)))
+      return createStringError(errc::invalid_argument, Reason);
   }
 
   Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
@@ -754,7 +770,7 @@
   if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
     Config.ExtractPartition = Arg->getValue();
 
-  for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
     if (!StringRef(Arg->getValue()).contains('='))
       return createStringError(errc::invalid_argument,
                                "bad format for --redefine-sym");
@@ -765,12 +781,12 @@
                                Old2New.first.str().c_str());
   }
 
-  for (auto Arg : InputArgs.filtered(OBJCOPY_redefine_symbols))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbols))
     if (Error E = addSymbolsToRenameFromFile(Config.SymbolsToRename, DC.Alloc,
                                              Arg->getValue()))
       return std::move(E);
 
-  for (auto Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_rename_section)) {
     Expected<SectionRename> SR =
         parseRenameSectionValue(StringRef(Arg->getValue()));
     if (!SR)
@@ -780,14 +796,14 @@
                                "multiple renames of section '%s'",
                                SR->OriginalName.str().c_str());
   }
-  for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) {
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_alignment)) {
     Expected<std::pair<StringRef, uint64_t>> NameAndAlign =
         parseSetSectionAttribute("--set-section-alignment", Arg->getValue());
     if (!NameAndAlign)
       return NameAndAlign.takeError();
     Config.SetSectionAlignment[NameAndAlign->first] = NameAndAlign->second;
   }
-  for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
     Expected<SectionFlagsUpdate> SFU =
         parseSetSectionFlagValue(Arg->getValue());
     if (!SFU)
@@ -798,7 +814,7 @@
           "--set-section-flags set multiple times for section '%s'",
           SFU->Name.str().c_str());
   }
-  for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_type)) {
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_set_section_type)) {
     Expected<std::pair<StringRef, uint64_t>> NameAndType =
         parseSetSectionAttribute("--set-section-type", Arg->getValue());
     if (!NameAndType)
@@ -822,24 +838,24 @@
       return Err("type");
   }
 
-  for (auto Arg : InputArgs.filtered(OBJCOPY_remove_section))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_remove_section))
     if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_keep_section))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_section))
     if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_only_section))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_only_section))
     if (Error E = Config.OnlySection.addMatcher(NameOrPattern::create(
             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_add_section)) {
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_add_section)) {
     if (Error Err = loadNewSectionData(Arg->getValue(), "--add-section",
                                        Config.AddSection))
       return std::move(Err);
   }
-  for (auto Arg : InputArgs.filtered(OBJCOPY_update_section)) {
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_update_section)) {
     if (Error Err = loadNewSectionData(Arg->getValue(), "--update-section",
                                        Config.UpdateSection))
       return std::move(Err);
@@ -879,66 +895,66 @@
     Config.StripDebug = true;
     ELFConfig.KeepFileSymbols = true;
   }
-  for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbol))
     if (Error E = Config.SymbolsToLocalize.addMatcher(NameOrPattern::create(
             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_localize_symbols))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_localize_symbols))
     if (Error E = addSymbolsFromFile(Config.SymbolsToLocalize, DC.Alloc,
                                      Arg->getValue(), SymbolMatchStyle,
                                      ErrorCallback))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbol))
     if (Error E = Config.SymbolsToKeepGlobal.addMatcher(NameOrPattern::create(
             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_global_symbols))
     if (Error E = addSymbolsFromFile(Config.SymbolsToKeepGlobal, DC.Alloc,
                                      Arg->getValue(), SymbolMatchStyle,
                                      ErrorCallback))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbol))
     if (Error E = Config.SymbolsToGlobalize.addMatcher(NameOrPattern::create(
             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_globalize_symbols))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_globalize_symbols))
     if (Error E = addSymbolsFromFile(Config.SymbolsToGlobalize, DC.Alloc,
                                      Arg->getValue(), SymbolMatchStyle,
                                      ErrorCallback))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbol))
     if (Error E = Config.SymbolsToWeaken.addMatcher(NameOrPattern::create(
             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_weaken_symbols))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_weaken_symbols))
     if (Error E = addSymbolsFromFile(Config.SymbolsToWeaken, DC.Alloc,
                                      Arg->getValue(), SymbolMatchStyle,
                                      ErrorCallback))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbol))
     if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_symbols))
     if (Error E = addSymbolsFromFile(Config.SymbolsToRemove, DC.Alloc,
                                      Arg->getValue(), SymbolMatchStyle,
                                      ErrorCallback))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbol))
     if (Error E =
             Config.UnneededSymbolsToRemove.addMatcher(NameOrPattern::create(
                 Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_strip_unneeded_symbols))
     if (Error E = addSymbolsFromFile(Config.UnneededSymbolsToRemove, DC.Alloc,
                                      Arg->getValue(), SymbolMatchStyle,
                                      ErrorCallback))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbol))
     if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
       return std::move(E);
-  for (auto Arg : InputArgs.filtered(OBJCOPY_keep_symbols))
+  for (auto *Arg : InputArgs.filtered(OBJCOPY_keep_symbols))
     if (Error E =
             addSymbolsFromFile(Config.SymbolsToKeep, DC.Alloc, Arg->getValue(),
                                SymbolMatchStyle, ErrorCallback))
@@ -964,7 +980,7 @@
     return createStringError(errc::invalid_argument,
                              "--preserve-dates requires a file");
 
-  for (auto Arg : InputArgs)
+  for (auto *Arg : InputArgs)
     if (Arg->getOption().matches(OBJCOPY_set_start)) {
       auto EAddr = getAsInteger<uint64_t>(Arg->getValue());
       if (!EAddr)
@@ -993,11 +1009,6 @@
         "--decompress-debug-sections");
   }
 
-  if (Config.DecompressDebugSections && !compression::zlib::isAvailable())
-    return createStringError(
-        errc::invalid_argument,
-        "LLVM was not compiled with LLVM_ENABLE_ZLIB: cannot decompress");
-
   if (Config.ExtractPartition && Config.ExtractMainPartition)
     return createStringError(errc::invalid_argument,
                              "cannot specify --extract-partition together with "
@@ -1045,13 +1056,13 @@
     exit(0);
   }
 
-  for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
+  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_add_rpath))
     MachOConfig.RPathToAdd.push_back(Arg->getValue());
 
   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_prepend_rpath))
     MachOConfig.RPathToPrepend.push_back(Arg->getValue());
 
-  for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) {
+  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_delete_rpath)) {
     StringRef RPath = Arg->getValue();
 
     // Cannot add and delete the same rpath at the same time.
@@ -1126,10 +1137,10 @@
       InputArgs.hasArg(INSTALL_NAME_TOOL_delete_all_rpaths);
 
   SmallVector<StringRef, 2> Positional;
-  for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN))
+  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_UNKNOWN))
     return createStringError(errc::invalid_argument, "unknown argument '%s'",
                              Arg->getAsString(InputArgs).c_str());
-  for (auto Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
+  for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
     Positional.push_back(Arg->getValue());
   if (Positional.empty())
     return createStringError(errc::invalid_argument, "no input file specified");
@@ -1198,7 +1209,15 @@
   // We only support -r for now, which removes all bitcode sections and
   // the __LLVM segment if it's now empty.
   cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
+      "__LLVM,__asm", MatchStyle::Literal, ErrorCallback)));
+  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
+      "__LLVM,__bitcode", MatchStyle::Literal, ErrorCallback)));
+  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
       "__LLVM,__bundle", MatchStyle::Literal, ErrorCallback)));
+  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
+      "__LLVM,__cmdline", MatchStyle::Literal, ErrorCallback)));
+  cantFail(Config.ToRemove.addMatcher(NameOrPattern::create(
+      "__LLVM,__swift_cmdline", MatchStyle::Literal, ErrorCallback)));
   MachOConfig.EmptySegmentsToRemove.insert("__LLVM");
 
   DC.CopyConfigs.push_back(std::move(ConfigMgr));
@@ -1212,9 +1231,8 @@
 objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
                            function_ref<Error(Error)> ErrorCallback) {
   const char *const *DashDash =
-      std::find_if(RawArgsArr.begin(), RawArgsArr.end(),
-                   [](StringRef Str) { return Str == "--"; });
-  ArrayRef<const char *> ArgsArr = makeArrayRef(RawArgsArr.begin(), DashDash);
+      llvm::find_if(RawArgsArr, [](StringRef Str) { return Str == "--"; });
+  ArrayRef<const char *> ArgsArr = ArrayRef(RawArgsArr.begin(), DashDash);
   if (DashDash != RawArgsArr.end())
     DashDash = std::next(DashDash);
 
@@ -1240,10 +1258,10 @@
   }
 
   SmallVector<StringRef, 2> Positional;
-  for (auto Arg : InputArgs.filtered(STRIP_UNKNOWN))
+  for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN))
     return createStringError(errc::invalid_argument, "unknown argument '%s'",
                              Arg->getAsString(InputArgs).c_str());
-  for (auto Arg : InputArgs.filtered(STRIP_INPUT))
+  for (auto *Arg : InputArgs.filtered(STRIP_INPUT))
     Positional.push_back(Arg->getValue());
   std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
 
@@ -1286,22 +1304,22 @@
   ELFConfig.KeepFileSymbols = InputArgs.hasArg(STRIP_keep_file_symbols);
   MachOConfig.KeepUndefined = InputArgs.hasArg(STRIP_keep_undefined);
 
-  for (auto Arg : InputArgs.filtered(STRIP_keep_section))
+  for (auto *Arg : InputArgs.filtered(STRIP_keep_section))
     if (Error E = Config.KeepSection.addMatcher(NameOrPattern::create(
             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
       return std::move(E);
 
-  for (auto Arg : InputArgs.filtered(STRIP_remove_section))
+  for (auto *Arg : InputArgs.filtered(STRIP_remove_section))
     if (Error E = Config.ToRemove.addMatcher(NameOrPattern::create(
             Arg->getValue(), SectionMatchStyle, ErrorCallback)))
       return std::move(E);
 
-  for (auto Arg : InputArgs.filtered(STRIP_strip_symbol))
+  for (auto *Arg : InputArgs.filtered(STRIP_strip_symbol))
     if (Error E = Config.SymbolsToRemove.addMatcher(NameOrPattern::create(
             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
       return std::move(E);
 
-  for (auto Arg : InputArgs.filtered(STRIP_keep_symbol))
+  for (auto *Arg : InputArgs.filtered(STRIP_keep_symbol))
     if (Error E = Config.SymbolsToKeep.addMatcher(NameOrPattern::create(
             Arg->getValue(), SymbolMatchStyle, ErrorCallback)))
       return std::move(E);
diff --git a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index d3713b5..0fddd44 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -33,7 +33,7 @@
     : Joined<["--"], "compress-debug-sections=">,
       MetaVarName<"format">,
       HelpText<"Compress DWARF debug sections using specified format. Supported "
-               "formats: zlib">;
+               "formats: zlib, zstd. Select zlib if <format> is omitted">;
 def : Flag<["--"], "compress-debug-sections">, Alias<compress_debug_sections>,
       AliasArgs<["zlib"]>;
 def decompress_debug_sections : Flag<["--"], "decompress-debug-sections">,
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 aa26215..a24cd88 100644
--- a/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -240,7 +240,7 @@
                               : cl::TokenizeGNUCommandLine,
                           NewArgv);
 
-  auto Args = makeArrayRef(NewArgv).drop_front();
+  auto Args = ArrayRef(NewArgv).drop_front();
   Expected<DriverConfig> DriverConfig = getDriverConfig(Args);
 
   if (!DriverConfig) {
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt
index 2179728..c8c07ca 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-objdump/CMakeLists.txt
@@ -12,6 +12,7 @@
   Option
   Support
   Symbolize
+  TargetParser
   )
 
 set(LLVM_TARGET_DEFINITIONS ObjdumpOpts.td)
@@ -36,6 +37,8 @@
   OtoolOptsTableGen
   )
 
+target_link_libraries(llvm-objdump PRIVATE LLVMDebuginfod)
+
 if(LLVM_HAVE_LIBXAR)
   target_link_libraries(llvm-objdump PRIVATE ${XAR_LIB})
 endif()
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
index e65762e..3bc7d3c 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/COFFDump.cpp
@@ -10,7 +10,7 @@
 /// This file implements the COFF-specific dumper for llvm-objdump.
 /// It outputs the Win64 EH data structures as plain text.
 /// The encoding of the unwind codes is described in MSDN:
-/// http://msdn.microsoft.com/en-us/library/ck9asaa9.aspx
+/// https://docs.microsoft.com/en-us/cpp/build/exception-handling-x64
 ///
 //===----------------------------------------------------------------------===//
 
@@ -102,7 +102,7 @@
   };
 
   printU16("Magic", Hdr.Magic, "%04x");
-  printOptionalEnumName(Hdr.Magic, makeArrayRef(PEHeaderMagic));
+  printOptionalEnumName(Hdr.Magic, ArrayRef(PEHeaderMagic));
   outs() << '\n';
   print("MajorLinkerVersion", Hdr.MajorLinkerVersion);
   print("MinorLinkerVersion", Hdr.MinorLinkerVersion);
@@ -127,7 +127,7 @@
   printU32("SizeOfHeaders", Hdr.SizeOfHeaders, "%08x\n");
   printU32("CheckSum", Hdr.CheckSum, "%08x\n");
   printU16("Subsystem", Hdr.Subsystem, "%08x");
-  printOptionalEnumName(Hdr.Subsystem, makeArrayRef(PEWindowsSubsystem));
+  printOptionalEnumName(Hdr.Subsystem, ArrayRef(PEWindowsSubsystem));
   outs() << '\n';
 
   printU16("DllCharacteristics", Hdr.DLLCharacteristics, "%08x\n");
@@ -173,7 +173,7 @@
       "Reserved",
   };
   outs() << "\nThe Data Directory\n";
-  for (uint32_t I = 0; I != array_lengthof(DirName); ++I) {
+  for (uint32_t I = 0; I != std::size(DirName); ++I) {
     uint32_t Addr = 0, Size = 0;
     if (const data_directory *Data = Obj.getDataDirectory(I)) {
       Addr = Data->RelativeVirtualAddress;
@@ -194,6 +194,8 @@
   case UOP_SetFPReg: return "UOP_SetFPReg";
   case UOP_SaveNonVol: return "UOP_SaveNonVol";
   case UOP_SaveNonVolBig: return "UOP_SaveNonVolBig";
+  case UOP_Epilog: return "UOP_Epilog";
+  case UOP_SpareCode: return "UOP_SpareCode";
   case UOP_SaveXMM128: return "UOP_SaveXMM128";
   case UOP_SaveXMM128Big: return "UOP_SaveXMM128Big";
   case UOP_PushMachFrame: return "UOP_PushMachFrame";
@@ -234,9 +236,11 @@
     return 1;
   case UOP_SaveNonVol:
   case UOP_SaveXMM128:
+  case UOP_Epilog:
     return 2;
   case UOP_SaveNonVolBig:
   case UOP_SaveXMM128Big:
+  case UOP_SpareCode:
     return 3;
   case UOP_AllocLarge:
     return (UnwindCode.getOpInfo() == 0) ? 2 : 3;
@@ -305,7 +309,7 @@
              << " remaining in buffer";
       return ;
     }
-    printUnwindCode(makeArrayRef(I, E));
+    printUnwindCode(ArrayRef(I, E));
     I += UsedSlots;
   }
 }
@@ -651,7 +655,7 @@
   if (UI->NumCodes)
     outs() << "    Unwind Codes:\n";
 
-  printAllUnwindCodes(makeArrayRef(&UI->UnwindCodes[0], UI->NumCodes));
+  printAllUnwindCodes(ArrayRef(&UI->UnwindCodes[0], UI->NumCodes));
 
   outs() << "\n";
   outs().flush();
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
index 61676b4..b98b45e 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/ELFDump.cpp
@@ -248,13 +248,16 @@
       outs() << "    NOTE ";
       break;
     case ELF::PT_OPENBSD_BOOTDATA:
-      outs() << "    OPENBSD_BOOTDATA ";
+      outs() << "OPENBSD_BOOTDATA ";
+      break;
+    case ELF::PT_OPENBSD_MUTABLE:
+      outs() << "OPENBSD_MUTABLE ";
       break;
     case ELF::PT_OPENBSD_RANDOMIZE:
-      outs() << "    OPENBSD_RANDOMIZE ";
+      outs() << "OPENBSD_RANDOMIZE ";
       break;
     case ELF::PT_OPENBSD_WXNEEDED:
-      outs() << "    OPENBSD_WXNEEDED ";
+      outs() << "OPENBSD_WXNEEDED ";
       break;
     case ELF::PT_PHDR:
       outs() << "    PHDR ";
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
index cdbecd5..fadc836 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/MachODump.cpp
@@ -78,9 +78,11 @@
 static bool ArchiveMemberOffsets;
 bool objdump::IndirectSymbols;
 bool objdump::DataInCode;
-bool objdump::FunctionStarts;
+FunctionStartsMode objdump::FunctionStartsType =
+    objdump::FunctionStartsMode::None;
 bool objdump::LinkOptHints;
 bool objdump::InfoPlist;
+bool objdump::ChainedFixups;
 bool objdump::DyldInfo;
 bool objdump::DylibsUsed;
 bool objdump::DylibId;
@@ -93,6 +95,8 @@
 static bool ArchAll = false;
 static std::string ThumbTripleName;
 
+static StringRef ordinalName(const object::MachOObjectFile *, int);
+
 void objdump::parseMachOOptions(const llvm::opt::InputArgList &InputArgs) {
   FirstPrivateHeader = InputArgs.hasArg(OBJDUMP_private_header);
   ExportsTrie = InputArgs.hasArg(OBJDUMP_exports_trie);
@@ -109,9 +113,18 @@
   ArchiveMemberOffsets = InputArgs.hasArg(OBJDUMP_archive_member_offsets);
   IndirectSymbols = InputArgs.hasArg(OBJDUMP_indirect_symbols);
   DataInCode = InputArgs.hasArg(OBJDUMP_data_in_code);
-  FunctionStarts = InputArgs.hasArg(OBJDUMP_function_starts);
+  if (const opt::Arg *A = InputArgs.getLastArg(OBJDUMP_function_starts_EQ)) {
+    FunctionStartsType = StringSwitch<FunctionStartsMode>(A->getValue())
+                             .Case("addrs", FunctionStartsMode::Addrs)
+                             .Case("names", FunctionStartsMode::Names)
+                             .Case("both", FunctionStartsMode::Both)
+                             .Default(FunctionStartsMode::None);
+    if (FunctionStartsType == FunctionStartsMode::None)
+      invalidArgValue(A);
+  }
   LinkOptHints = InputArgs.hasArg(OBJDUMP_link_opt_hints);
   InfoPlist = InputArgs.hasArg(OBJDUMP_info_plist);
+  ChainedFixups = InputArgs.hasArg(OBJDUMP_chained_fixups);
   DyldInfo = InputArgs.hasArg(OBJDUMP_dyld_info);
   DylibsUsed = InputArgs.hasArg(OBJDUMP_dylibs_used);
   DylibId = InputArgs.hasArg(OBJDUMP_dylib_id);
@@ -242,19 +255,19 @@
   case MachO::DICE_KIND_DATA:
     if (Length >= 4) {
       if (ShowRawInsn)
-        dumpBytes(makeArrayRef(bytes, 4), outs());
+        dumpBytes(ArrayRef(bytes, 4), outs());
       Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
       outs() << "\t.long " << Value;
       Size = 4;
     } else if (Length >= 2) {
       if (ShowRawInsn)
-        dumpBytes(makeArrayRef(bytes, 2), outs());
+        dumpBytes(ArrayRef(bytes, 2), outs());
       Value = bytes[1] << 8 | bytes[0];
       outs() << "\t.short " << Value;
       Size = 2;
     } else {
       if (ShowRawInsn)
-        dumpBytes(makeArrayRef(bytes, 2), outs());
+        dumpBytes(ArrayRef(bytes, 2), outs());
       Value = bytes[0];
       outs() << "\t.byte " << Value;
       Size = 1;
@@ -266,14 +279,14 @@
     break;
   case MachO::DICE_KIND_JUMP_TABLE8:
     if (ShowRawInsn)
-      dumpBytes(makeArrayRef(bytes, 1), outs());
+      dumpBytes(ArrayRef(bytes, 1), outs());
     Value = bytes[0];
     outs() << "\t.byte " << format("%3u", Value) << "\t@ KIND_JUMP_TABLE8\n";
     Size = 1;
     break;
   case MachO::DICE_KIND_JUMP_TABLE16:
     if (ShowRawInsn)
-      dumpBytes(makeArrayRef(bytes, 2), outs());
+      dumpBytes(ArrayRef(bytes, 2), outs());
     Value = bytes[1] << 8 | bytes[0];
     outs() << "\t.short " << format("%5u", Value & 0xffff)
            << "\t@ KIND_JUMP_TABLE16\n";
@@ -282,7 +295,7 @@
   case MachO::DICE_KIND_JUMP_TABLE32:
   case MachO::DICE_KIND_ABS_JUMP_TABLE32:
     if (ShowRawInsn)
-      dumpBytes(makeArrayRef(bytes, 4), outs());
+      dumpBytes(ArrayRef(bytes, 4), outs());
     Value = bytes[3] << 24 | bytes[2] << 16 | bytes[1] << 8 | bytes[0];
     outs() << "\t.long " << Value;
     if (Kind == MachO::DICE_KIND_JUMP_TABLE32)
@@ -1076,12 +1089,39 @@
     }
   }
 
+  DenseMap<uint64_t, StringRef> SymbolNames;
+  if (FunctionStartsType == FunctionStartsMode::Names ||
+      FunctionStartsType == FunctionStartsMode::Both) {
+    for (SymbolRef Sym : O->symbols()) {
+      if (Expected<uint64_t> Addr = Sym.getAddress()) {
+        if (Expected<StringRef> Name = Sym.getName()) {
+          SymbolNames[*Addr] = *Name;
+        }
+      }
+    }
+  }
+
   for (uint64_t S : FunctionStarts) {
     uint64_t Addr = BaseSegmentAddress + S;
-    if (O->is64Bit())
-      outs() << format("%016" PRIx64, Addr) << "\n";
-    else
-      outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr)) << "\n";
+    if (FunctionStartsType == FunctionStartsMode::Names) {
+      auto It = SymbolNames.find(Addr);
+      if (It != SymbolNames.end())
+        outs() << It->second << "\n";
+    } else {
+      if (O->is64Bit())
+        outs() << format("%016" PRIx64, Addr);
+      else
+        outs() << format("%08" PRIx32, static_cast<uint32_t>(Addr));
+
+      if (FunctionStartsType == FunctionStartsMode::Both) {
+        auto It = SymbolNames.find(Addr);
+        if (It != SymbolNames.end())
+          outs() << " " << It->second;
+        else
+          outs() << " ?";
+      }
+      outs() << "\n";
+    }
   }
 }
 
@@ -1184,18 +1224,209 @@
   }
 }
 
-static void printMachOChainedFixups(object::MachOObjectFile *Obj) {
-  Error Err = Error::success();
-  for (const object::MachOChainedFixupEntry &Entry : Obj->fixupTable(Err)) {
-    (void)Entry;
+static SmallVector<std::string> GetSegmentNames(object::MachOObjectFile *O) {
+  SmallVector<std::string> Ret;
+  for (const MachOObjectFile::LoadCommandInfo &Command : O->load_commands()) {
+    if (Command.C.cmd == MachO::LC_SEGMENT) {
+      MachO::segment_command SLC = O->getSegmentLoadCommand(Command);
+      Ret.push_back(SLC.segname);
+    } else if (Command.C.cmd == MachO::LC_SEGMENT_64) {
+      MachO::segment_command_64 SLC = O->getSegment64LoadCommand(Command);
+      Ret.push_back(SLC.segname);
+    }
   }
-  if (Err)
-    reportError(std::move(Err), Obj->getFileName());
+  return Ret;
+}
+
+static void
+PrintChainedFixupsHeader(const MachO::dyld_chained_fixups_header &H) {
+  outs() << "chained fixups header (LC_DYLD_CHAINED_FIXUPS)\n";
+  outs() << "  fixups_version = " << H.fixups_version << '\n';
+  outs() << "  starts_offset  = " << H.starts_offset << '\n';
+  outs() << "  imports_offset = " << H.imports_offset << '\n';
+  outs() << "  symbols_offset = " << H.symbols_offset << '\n';
+  outs() << "  imports_count  = " << H.imports_count << '\n';
+
+  outs() << "  imports_format = " << H.imports_format;
+  switch (H.imports_format) {
+  case llvm::MachO::DYLD_CHAINED_IMPORT:
+    outs() << " (DYLD_CHAINED_IMPORT)";
+    break;
+  case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND:
+    outs() << " (DYLD_CHAINED_IMPORT_ADDEND)";
+    break;
+  case llvm::MachO::DYLD_CHAINED_IMPORT_ADDEND64:
+    outs() << " (DYLD_CHAINED_IMPORT_ADDEND64)";
+    break;
+  }
+  outs() << '\n';
+
+  outs() << "  symbols_format = " << H.symbols_format;
+  if (H.symbols_format == llvm::MachO::DYLD_CHAINED_SYMBOL_ZLIB)
+    outs() << " (zlib compressed)";
+  outs() << '\n';
+}
+
+static constexpr std::array<StringRef, 13> PointerFormats{
+    "DYLD_CHAINED_PTR_ARM64E",
+    "DYLD_CHAINED_PTR_64",
+    "DYLD_CHAINED_PTR_32",
+    "DYLD_CHAINED_PTR_32_CACHE",
+    "DYLD_CHAINED_PTR_32_FIRMWARE",
+    "DYLD_CHAINED_PTR_64_OFFSET",
+    "DYLD_CHAINED_PTR_ARM64E_KERNEL",
+    "DYLD_CHAINED_PTR_64_KERNEL_CACHE",
+    "DYLD_CHAINED_PTR_ARM64E_USERLAND",
+    "DYLD_CHAINED_PTR_ARM64E_FIRMWARE",
+    "DYLD_CHAINED_PTR_X86_64_KERNEL_CACHE",
+    "DYLD_CHAINED_PTR_ARM64E_USERLAND24",
+};
+
+static void PrintChainedFixupsSegment(const ChainedFixupsSegment &Segment,
+                                      StringRef SegName) {
+  outs() << "chained starts in segment " << Segment.SegIdx << " (" << SegName
+         << ")\n";
+  outs() << "  size = " << Segment.Header.size << '\n';
+  outs() << "  page_size = " << format("0x%0" PRIx16, Segment.Header.page_size)
+         << '\n';
+
+  outs() << "  pointer_format = " << Segment.Header.pointer_format;
+  if ((Segment.Header.pointer_format - 1) <
+      MachO::DYLD_CHAINED_PTR_ARM64E_USERLAND24)
+    outs() << " (" << PointerFormats[Segment.Header.pointer_format - 1] << ")";
+  outs() << '\n';
+
+  outs() << "  segment_offset = "
+         << format("0x%0" PRIx64, Segment.Header.segment_offset) << '\n';
+  outs() << "  max_valid_pointer = " << Segment.Header.max_valid_pointer
+         << '\n';
+  outs() << "  page_count = " << Segment.Header.page_count << '\n';
+  for (auto [Index, PageStart] : enumerate(Segment.PageStarts)) {
+    outs() << "    page_start[" << Index << "] = " << PageStart;
+    // FIXME: Support DYLD_CHAINED_PTR_START_MULTI (32-bit only)
+    if (PageStart == MachO::DYLD_CHAINED_PTR_START_NONE)
+      outs() << " (DYLD_CHAINED_PTR_START_NONE)";
+    outs() << '\n';
+  }
+}
+
+static void PrintChainedFixupTarget(ChainedFixupTarget &Target, size_t Idx,
+                                    int Format, MachOObjectFile *O) {
+  if (Format == MachO::DYLD_CHAINED_IMPORT)
+    outs() << "dyld chained import";
+  else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND)
+    outs() << "dyld chained import addend";
+  else if (Format == MachO::DYLD_CHAINED_IMPORT_ADDEND64)
+    outs() << "dyld chained import addend64";
+  // FIXME: otool prints the encoded value as well.
+  outs() << '[' << Idx << "]\n";
+
+  outs() << "  lib_ordinal = " << Target.libOrdinal() << " ("
+         << ordinalName(O, Target.libOrdinal()) << ")\n";
+  outs() << "  weak_import = " << Target.weakImport() << '\n';
+  outs() << "  name_offset = " << Target.nameOffset() << " ("
+         << Target.symbolName() << ")\n";
+  if (Format != MachO::DYLD_CHAINED_IMPORT)
+    outs() << "  addend      = " << (int64_t)Target.addend() << '\n';
+}
+
+static void PrintChainedFixups(MachOObjectFile *O) {
+  // MachOObjectFile::getChainedFixupsHeader() reads LC_DYLD_CHAINED_FIXUPS.
+  // FIXME: Support chained fixups in __TEXT,__chain_starts section too.
+  auto ChainedFixupHeader =
+      unwrapOrError(O->getChainedFixupsHeader(), O->getFileName());
+  if (!ChainedFixupHeader)
+    return;
+
+  PrintChainedFixupsHeader(*ChainedFixupHeader);
+
+  auto [SegCount, Segments] =
+      unwrapOrError(O->getChainedFixupsSegments(), O->getFileName());
+
+  auto SegNames = GetSegmentNames(O);
+
+  size_t StartsIdx = 0;
+  outs() << "chained starts in image\n";
+  outs() << "  seg_count = " << SegCount << '\n';
+  for (size_t I = 0; I < SegCount; ++I) {
+    uint64_t SegOffset = 0;
+    if (StartsIdx < Segments.size() && I == Segments[StartsIdx].SegIdx) {
+      SegOffset = Segments[StartsIdx].Offset;
+      ++StartsIdx;
+    }
+
+    outs() << "    seg_offset[" << I << "] = " << SegOffset << " ("
+           << SegNames[I] << ")\n";
+  }
+
+  for (const ChainedFixupsSegment &S : Segments)
+    PrintChainedFixupsSegment(S, SegNames[S.SegIdx]);
+
+  auto FixupTargets =
+      unwrapOrError(O->getDyldChainedFixupTargets(), O->getFileName());
+
+  uint32_t ImportsFormat = ChainedFixupHeader->imports_format;
+  for (auto [Idx, Target] : enumerate(FixupTargets))
+    PrintChainedFixupTarget(Target, Idx, ImportsFormat, O);
 }
 
 static void PrintDyldInfo(MachOObjectFile *O) {
-  outs() << "dyld information:" << '\n';
-  printMachOChainedFixups(O);
+  Error Err = Error::success();
+
+  size_t SegmentWidth = strlen("segment");
+  size_t SectionWidth = strlen("section");
+  size_t AddressWidth = strlen("address");
+  size_t AddendWidth = strlen("addend");
+  size_t DylibWidth = strlen("dylib");
+  const size_t PointerWidth = 2 + O->getBytesInAddress() * 2;
+
+  auto HexLength = [](uint64_t Num) {
+    return Num ? (size_t)divideCeil(Log2_64(Num), 4) : 1;
+  };
+  for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
+    SegmentWidth = std::max(SegmentWidth, Entry.segmentName().size());
+    SectionWidth = std::max(SectionWidth, Entry.sectionName().size());
+    AddressWidth = std::max(AddressWidth, HexLength(Entry.address()) + 2);
+    if (Entry.isBind()) {
+      AddendWidth = std::max(AddendWidth, HexLength(Entry.addend()) + 2);
+      DylibWidth = std::max(DylibWidth, Entry.symbolName().size());
+    }
+  }
+  // Errors will be handled when printing the table.
+  if (Err)
+    consumeError(std::move(Err));
+
+  outs() << "dyld information:\n";
+  outs() << left_justify("segment", SegmentWidth) << ' '
+         << left_justify("section", SectionWidth) << ' '
+         << left_justify("address", AddressWidth) << ' '
+         << left_justify("pointer", PointerWidth) << " type   "
+         << left_justify("addend", AddendWidth) << ' '
+         << left_justify("dylib", DylibWidth) << " symbol/vm address\n";
+  for (const object::MachOChainedFixupEntry &Entry : O->fixupTable(Err)) {
+    outs() << left_justify(Entry.segmentName(), SegmentWidth) << ' '
+           << left_justify(Entry.sectionName(), SectionWidth) << ' ' << "0x"
+           << left_justify(utohexstr(Entry.address()), AddressWidth - 2) << ' '
+           << format_hex(Entry.rawValue(), PointerWidth, true) << ' ';
+    if (Entry.isBind()) {
+      outs() << "bind   "
+             << "0x" << left_justify(utohexstr(Entry.addend()), AddendWidth - 2)
+             << ' ' << left_justify(ordinalName(O, Entry.ordinal()), DylibWidth)
+             << ' ' << Entry.symbolName();
+      if (Entry.flags() & MachO::BIND_SYMBOL_FLAGS_WEAK_IMPORT)
+        outs() << " (weak import)";
+      outs() << '\n';
+    } else {
+      assert(Entry.isRebase());
+      outs() << "rebase";
+      outs().indent(AddendWidth + DylibWidth + 2);
+      outs() << format("0x%" PRIX64, Entry.pointerValue()) << '\n';
+    }
+  }
+  if (Err)
+    reportError(std::move(Err), O->getFileName());
+
+  // TODO: Print opcode-based fixups if the object uses those.
 }
 
 static void PrintDylibs(MachOObjectFile *O, bool JustId) {
@@ -1916,8 +2147,9 @@
   // UniversalHeaders or ArchiveHeaders.
   if (Disassemble || Relocations || PrivateHeaders || ExportsTrie || Rebase ||
       Bind || SymbolTable || LazyBind || WeakBind || IndirectSymbols ||
-      DataInCode || FunctionStarts || LinkOptHints || DyldInfo || DylibsUsed ||
-      DylibId || Rpaths || ObjcMetaData || (!FilterSections.empty())) {
+      DataInCode || FunctionStartsType != FunctionStartsMode::None ||
+      LinkOptHints || ChainedFixups || DyldInfo || DylibsUsed || DylibId ||
+      Rpaths || ObjcMetaData || (!FilterSections.empty())) {
     if (LeadingHeaders) {
       outs() << Name;
       if (!ArchiveMemberName.empty())
@@ -1972,7 +2204,7 @@
     PrintIndirectSymbols(MachOOF, Verbose);
   if (DataInCode)
     PrintDataInCodeTable(MachOOF, Verbose);
-  if (FunctionStarts)
+  if (FunctionStartsType != FunctionStartsMode::None)
     PrintFunctionStarts(MachOOF);
   if (LinkOptHints)
     PrintLinkOptHints(MachOOF);
@@ -1988,6 +2220,8 @@
     DumpInfoPlistSectionContents(FileName, MachOOF);
   if (DyldInfo)
     PrintDyldInfo(MachOOF);
+  if (ChainedFixups)
+    PrintChainedFixups(MachOOF);
   if (DylibsUsed)
     PrintDylibs(MachOOF, false);
   if (DylibId)
@@ -7189,6 +7423,108 @@
   CommentsToEmit.clear();
 }
 
+const MachOObjectFile *
+objdump::getMachODSymObject(const MachOObjectFile *MachOOF, StringRef Filename,
+                            std::unique_ptr<Binary> &DSYMBinary,
+                            std::unique_ptr<MemoryBuffer> &DSYMBuf) {
+  const MachOObjectFile *DbgObj = MachOOF;
+  std::string DSYMPath;
+
+  // Auto-detect w/o --dsym.
+  if (DSYMFile.empty()) {
+    sys::fs::file_status DSYMStatus;
+    Twine FilenameDSYM = Filename + ".dSYM";
+    if (!status(FilenameDSYM, DSYMStatus)) {
+      if (sys::fs::is_directory(DSYMStatus)) {
+        SmallString<1024> Path;
+        FilenameDSYM.toVector(Path);
+        sys::path::append(Path, "Contents", "Resources", "DWARF",
+                          sys::path::filename(Filename));
+        DSYMPath = std::string(Path);
+      } else if (sys::fs::is_regular_file(DSYMStatus)) {
+        DSYMPath = FilenameDSYM.str();
+      }
+    }
+  }
+
+  if (DSYMPath.empty() && !DSYMFile.empty()) {
+    // If DSYMPath is a .dSYM directory, append the Mach-O file.
+    if (sys::fs::is_directory(DSYMFile) &&
+        sys::path::extension(DSYMFile) == ".dSYM") {
+      SmallString<128> ShortName(sys::path::filename(DSYMFile));
+      sys::path::replace_extension(ShortName, "");
+      SmallString<1024> FullPath(DSYMFile);
+      sys::path::append(FullPath, "Contents", "Resources", "DWARF", ShortName);
+      DSYMPath = FullPath.str();
+    } else {
+      DSYMPath = DSYMFile;
+    }
+  }
+
+  if (!DSYMPath.empty()) {
+    // Load the file.
+    ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
+        MemoryBuffer::getFileOrSTDIN(DSYMPath);
+    if (std::error_code EC = BufOrErr.getError()) {
+      reportError(errorCodeToError(EC), DSYMPath);
+      return nullptr;
+    }
+
+    // We need to keep the file alive, because we're replacing DbgObj with it.
+    DSYMBuf = std::move(BufOrErr.get());
+
+    Expected<std::unique_ptr<Binary>> BinaryOrErr =
+        createBinary(DSYMBuf.get()->getMemBufferRef());
+    if (!BinaryOrErr) {
+      reportError(BinaryOrErr.takeError(), DSYMPath);
+      return nullptr;
+    }
+
+    // We need to keep the Binary alive with the buffer
+    DSYMBinary = std::move(BinaryOrErr.get());
+    if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) {
+      // this is a Mach-O object file, use it
+      if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) {
+        DbgObj = MachDSYM;
+      } else {
+        WithColor::error(errs(), "llvm-objdump")
+            << DSYMPath << " is not a Mach-O file type.\n";
+        return nullptr;
+      }
+    } else if (auto *UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())) {
+      // this is a Universal Binary, find a Mach-O for this architecture
+      uint32_t CPUType, CPUSubType;
+      const char *ArchFlag;
+      if (MachOOF->is64Bit()) {
+        const MachO::mach_header_64 H_64 = MachOOF->getHeader64();
+        CPUType = H_64.cputype;
+        CPUSubType = H_64.cpusubtype;
+      } else {
+        const MachO::mach_header H = MachOOF->getHeader();
+        CPUType = H.cputype;
+        CPUSubType = H.cpusubtype;
+      }
+      Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr,
+                                                &ArchFlag);
+      Expected<std::unique_ptr<MachOObjectFile>> MachDSYM =
+          UB->getMachOObjectForArch(ArchFlag);
+      if (!MachDSYM) {
+        reportError(MachDSYM.takeError(), DSYMPath);
+        return nullptr;
+      }
+
+      // We need to keep the Binary alive with the buffer
+      DbgObj = &*MachDSYM.get();
+      DSYMBinary = std::move(*MachDSYM);
+    } else {
+      WithColor::error(errs(), "llvm-objdump")
+          << DSYMPath << " is not a Mach-O or Universal file type.\n";
+      return nullptr;
+    }
+  }
+  return DbgObj;
+}
+
 static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF,
                              StringRef DisSegName, StringRef DisSectName) {
   const char *McpuDefault = nullptr;
@@ -7363,90 +7699,15 @@
   std::unique_ptr<Binary> DSYMBinary;
   std::unique_ptr<MemoryBuffer> DSYMBuf;
   if (UseDbg) {
-    ObjectFile *DbgObj = MachOOF;
-
-    // A separate DSym file path was specified, parse it as a macho file,
+    // If separate DSym file path was specified, parse it as a macho file,
     // get the sections and supply it to the section name parsing machinery.
-    if (!DSYMFile.empty()) {
-      std::string DSYMPath(DSYMFile);
-
-      // If DSYMPath is a .dSYM directory, append the Mach-O file.
-      if (llvm::sys::fs::is_directory(DSYMPath) &&
-          llvm::sys::path::extension(DSYMPath) == ".dSYM") {
-        SmallString<128> ShortName(llvm::sys::path::filename(DSYMPath));
-        llvm::sys::path::replace_extension(ShortName, "");
-        SmallString<1024> FullPath(DSYMPath);
-        llvm::sys::path::append(FullPath, "Contents", "Resources", "DWARF",
-                                ShortName);
-        DSYMPath = std::string(FullPath.str());
-      }
-
-      // Load the file.
-      ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
-          MemoryBuffer::getFileOrSTDIN(DSYMPath);
-      if (std::error_code EC = BufOrErr.getError()) {
-        reportError(errorCodeToError(EC), DSYMPath);
-        return;
-      }
-
-      // We need to keep the file alive, because we're replacing DbgObj with it.
-      DSYMBuf = std::move(BufOrErr.get());
-
-      Expected<std::unique_ptr<Binary>> BinaryOrErr =
-      createBinary(DSYMBuf.get()->getMemBufferRef());
-      if (!BinaryOrErr) {
-        reportError(BinaryOrErr.takeError(), DSYMPath);
-        return;
-      }
-
-      // We need to keep the Binary alive with the buffer
-      DSYMBinary = std::move(BinaryOrErr.get());
-      if (ObjectFile *O = dyn_cast<ObjectFile>(DSYMBinary.get())) {
-        // this is a Mach-O object file, use it
-        if (MachOObjectFile *MachDSYM = dyn_cast<MachOObjectFile>(&*O)) {
-          DbgObj = MachDSYM;
-        }
-        else {
-          WithColor::error(errs(), "llvm-objdump")
-            << DSYMPath << " is not a Mach-O file type.\n";
-          return;
-        }
-      }
-      else if (auto UB = dyn_cast<MachOUniversalBinary>(DSYMBinary.get())){
-        // this is a Universal Binary, find a Mach-O for this architecture
-        uint32_t CPUType, CPUSubType;
-        const char *ArchFlag;
-        if (MachOOF->is64Bit()) {
-          const MachO::mach_header_64 H_64 = MachOOF->getHeader64();
-          CPUType = H_64.cputype;
-          CPUSubType = H_64.cpusubtype;
-        } else {
-          const MachO::mach_header H = MachOOF->getHeader();
-          CPUType = H.cputype;
-          CPUSubType = H.cpusubtype;
-        }
-        Triple T = MachOObjectFile::getArchTriple(CPUType, CPUSubType, nullptr,
-                                                  &ArchFlag);
-        Expected<std::unique_ptr<MachOObjectFile>> MachDSYM =
-            UB->getMachOObjectForArch(ArchFlag);
-        if (!MachDSYM) {
-          reportError(MachDSYM.takeError(), DSYMPath);
-          return;
-        }
-
-        // We need to keep the Binary alive with the buffer
-        DbgObj = &*MachDSYM.get();
-        DSYMBinary = std::move(*MachDSYM);
-      }
-      else {
-        WithColor::error(errs(), "llvm-objdump")
-          << DSYMPath << " is not a Mach-O or Universal file type.\n";
-        return;
-      }
+    if (const ObjectFile *DbgObj =
+            getMachODSymObject(MachOOF, Filename, DSYMBinary, DSYMBuf)) {
+      // Setup the DIContext
+      diContext = DWARFContext::create(*DbgObj);
+    } else {
+      return;
     }
-
-    // Setup the DIContext
-    diContext = DWARFContext::create(*DbgObj);
   }
 
   if (FilterSections.empty())
@@ -7655,7 +7916,7 @@
                                            Annotations);
         if (gotInst) {
           if (ShowRawInsn || Arch == Triple::arm) {
-            dumpBytes(makeArrayRef(Bytes.data() + Index, Size), outs());
+            dumpBytes(ArrayRef(Bytes.data() + Index, Size), outs());
           }
           formatted_raw_ostream FormattedOS(outs());
           StringRef AnnotationsStr = Annotations.str();
@@ -7736,7 +7997,7 @@
           }
           if (ShowRawInsn || Arch == Triple::arm) {
             outs() << "\t";
-            dumpBytes(makeArrayRef(Bytes.data() + Index, InstSize), outs());
+            dumpBytes(ArrayRef(Bytes.data() + Index, InstSize), outs());
           }
           StringRef AnnotationsStr = Annotations.str();
           IP->printInst(&Inst, PC, AnnotationsStr, *STI, outs());
@@ -8445,6 +8706,9 @@
     case MachO::MH_KEXT_BUNDLE:
       outs() << "  KEXTBUNDLE";
       break;
+    case MachO::MH_FILESET:
+      outs() << "     FILESET";
+      break;
     default:
       outs() << format("  %10u", filetype);
       break;
@@ -8657,6 +8921,12 @@
         outs() << " PROTECTED_VERSION_1";
         flags &= ~MachO::SG_PROTECTED_VERSION_1;
       }
+      if (flags & MachO::SG_READ_ONLY) {
+        // Apple's otool prints the SG_ prefix for this flag, but not for the
+        // others.
+        outs() << " SG_READ_ONLY";
+        flags &= ~MachO::SG_READ_ONLY;
+      }
       if (flags)
         outs() << format(" 0x%08" PRIx32, flags) << " (unknown flags)\n";
       else
@@ -8754,6 +9024,8 @@
       outs() << " S_THREAD_LOCAL_VARIABLE_POINTERS\n";
     else if (section_type == MachO::S_THREAD_LOCAL_INIT_FUNCTION_POINTERS)
       outs() << " S_THREAD_LOCAL_INIT_FUNCTION_POINTERS\n";
+    else if (section_type == MachO::S_INIT_FUNC_OFFSETS)
+      outs() << " S_INIT_FUNC_OFFSETS\n";
     else
       outs() << format("0x%08" PRIx32, section_type) << "\n";
     outs() << "attributes";
@@ -10381,6 +10653,8 @@
     return "main-executable";
   case MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP:
     return "flat-namespace";
+  case MachO::BIND_SPECIAL_DYLIB_WEAK_LOOKUP:
+    return "weak";
   default:
     if (Ordinal > 0) {
       std::error_code EC =
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/MachODump.h b/src/llvm-project/llvm/tools/llvm-objdump/MachODump.h
index 12783e1..d9d3a70 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/MachODump.h
+++ b/src/llvm-project/llvm/tools/llvm-objdump/MachODump.h
@@ -16,12 +16,14 @@
 
 class Error;
 class StringRef;
+class MemoryBuffer;
 
 namespace object {
 class MachOObjectFile;
 class MachOUniversalBinary;
 class ObjectFile;
 class RelocationRef;
+class Binary;
 } // namespace object
 
 namespace opt {
@@ -32,17 +34,20 @@
 
 void parseMachOOptions(const llvm::opt::InputArgList &InputArgs);
 
+enum class FunctionStartsMode { Addrs, Names, Both, None };
+
 // MachO specific options
 extern bool Bind;
 extern bool DataInCode;
 extern std::string DisSymName;
+extern bool ChainedFixups;
 extern bool DyldInfo;
 extern bool DylibId;
 extern bool DylibsUsed;
 extern bool ExportsTrie;
 extern bool FirstPrivateHeader;
 extern bool FullLeadingAddr;
-extern bool FunctionStarts;
+extern FunctionStartsMode FunctionStartsType;
 extern bool IndirectSymbols;
 extern bool InfoPlist;
 extern bool LazyBind;
@@ -60,6 +65,11 @@
                                     const object::RelocationRef &RelRef,
                                     llvm::SmallVectorImpl<char> &Result);
 
+const object::MachOObjectFile *
+getMachODSymObject(const object::MachOObjectFile *O, StringRef Filename,
+                   std::unique_ptr<object::Binary> &DSYMBinary,
+                   std::unique_ptr<MemoryBuffer> &DSYMBuf);
+
 void parseInputMachO(StringRef Filename);
 void parseInputMachO(object::MachOUniversalBinary *UB);
 
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td b/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td
index 00d7d8c..c6627c7 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td
+++ b/src/llvm-project/llvm/tools/llvm-objdump/ObjdumpOpts.td
@@ -1,5 +1,10 @@
 include "llvm/Option/OptParser.td"
 
+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 : Separate<["--"], name>;
   def NAME #_eq : Joined<["--"], name #"=">,
@@ -33,12 +38,22 @@
 def archive_headers : Flag<["--"], "archive-headers">,
   HelpText<"Display archive header information">;
 
+defm build_id :
+  Eq<"build-id", "Build ID to look up. Once found, added as an input file">,
+  MetaVarName<"<hex>">;
+
 def : Flag<["-"], "a">, Alias<archive_headers>,
   HelpText<"Alias for --archive-headers">;
 
 def demangle : Flag<["--"], "demangle">, HelpText<"Demangle symbol names">;
 def : Flag<["-"], "C">, Alias<demangle>, HelpText<"Alias for --demangle">;
 
+defm debug_file_directory :
+  Eq<"debug-file-directory", "Path to directory where to look for debug files">,
+  MetaVarName<"<dir>">;
+
+defm debuginfod : B<"debuginfod", "Use debuginfod to find debug files", "Don't use debuginfod to find debug files">;
+
 def disassemble : Flag<["--"], "disassemble">,
   HelpText<"Disassemble all executable sections found in the input files">;
 def : Flag<["-"], "d">, Alias<disassemble>, HelpText<"Alias for --disassemble">;
@@ -118,7 +133,9 @@
            "do not print the instruction bytes.">;
 
 def no_leading_addr : Flag<["--"], "no-leading-addr">,
-  HelpText<"When disassembling, do not print leading addresses">;
+  HelpText<"When disassembling, do not print leading addresses for instructions or inline relocations">;
+def : Flag<["--"], "no-addresses">, Alias<no_leading_addr>,
+  HelpText<"Alias for --no-leading-addr">;
 
 def raw_clang_ast : Flag<["--"], "raw-clang-ast">,
   HelpText<"Dump the raw binary contents of the clang AST section">;
@@ -128,10 +145,10 @@
 def : Flag<["-"], "r">, Alias<reloc>, HelpText<"Alias for --reloc">;
 
 def print_imm_hex : Flag<["--"], "print-imm-hex">,
-  HelpText<"Use hex format for immediate values">;
+  HelpText<"Use hex format for immediate values (default)">;
 
 def no_print_imm_hex : Flag<["--"], "no-print-imm-hex">,
-  HelpText<"Do not use hex format for immediate values (default)">;
+  HelpText<"Do not use hex format for immediate values">;
 def : Flag<["--"], "print-imm-hex=false">, Alias<no_print_imm_hex>;
 
 def private_headers : Flag<["--"], "private-headers">,
@@ -153,6 +170,10 @@
 def : Flag<["-"], "h">, Alias<section_headers>,
   HelpText<"Alias for --section-headers">;
 
+def show_all_symbols : Flag<["--"], "show-all-symbols">,
+  HelpText<"Show all symbols during disassembly, even if multiple "
+           "symbols are defined at the same location">;
+
 def show_lma : Flag<["--"], "show-lma">,
   HelpText<"Display LMA column when dumping ELF section headers">;
 
@@ -284,11 +305,15 @@
   HelpText<"Print the data in code table for Mach-O objects (requires --macho)">,
   Group<grp_mach_o>;
 
-def function_starts : Flag<["--"], "function-starts">,
-  HelpText<"Print the function starts table for "
-           "Mach-O objects (requires --macho)">,
+def function_starts_EQ : Joined<["--"], "function-starts=">,
+  HelpText<"Print the function starts table for Mach-O objects. "
+           "Options: addrs (default), names, both (requires --macho)">,
+  Values<"addrs,names,both">,
   Group<grp_mach_o>;
 
+def : Flag<["--"], "function-starts">, Alias<function_starts_EQ>,
+  AliasArgs<["addrs"]>, Group<grp_mach_o>;
+
 def link_opt_hints : Flag<["--"], "link-opt-hints">,
   HelpText<"Print the linker optimization hints for "
            "Mach-O objects (requires --macho)">,
@@ -299,11 +324,15 @@
            "Mach-O objects (requires --macho)">,
   Group<grp_mach_o>;
 
-def dyld_info : Flag<["--"], "dyld_info">,
-      HelpText<"Print bind and rebase information used by dyld to resolve "
-               "external references in a final linked binary "
-               "(requires --macho)">,
-      Group<grp_mach_o>;
+def chained_fixups : Flag<["--"], "chained-fixups">,
+  HelpText<"Print chained fixup information (requires --macho)">,
+  Group<grp_mach_o>;
+
+def dyld_info : Flag<["--"], "dyld-info">,
+  HelpText<"Print bind and rebase information used by dyld to resolve "
+           "external references in a final linked binary "
+           "(requires --macho)">,
+  Group<grp_mach_o>;
 
 def dylibs_used : Flag<["--"], "dylibs-used">,
   HelpText<"Print the shared libraries used for linked "
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/OffloadDump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/OffloadDump.cpp
index 46334c2..4ac6b99 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/OffloadDump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/OffloadDump.cpp
@@ -10,6 +10,7 @@
 /// This file implements the offloading-specific dumper for llvm-objdump.
 ///
 //===----------------------------------------------------------------------===//
+
 #include "OffloadDump.h"
 #include "llvm-objdump.h"
 #include "llvm/Object/ELFObjectFile.h"
@@ -46,67 +47,34 @@
          << getOffloadKindName(OB.getOffloadKind()) << "\n";
 }
 
-static Error visitAllBinaries(const OffloadBinary &OB) {
-  uint64_t Offset = 0;
-  uint64_t Index = 0;
-  while (Offset < OB.getMemoryBufferRef().getBufferSize()) {
-    MemoryBufferRef Buffer =
-        MemoryBufferRef(OB.getData().drop_front(Offset), OB.getFileName());
-    auto BinaryOrErr = OffloadBinary::create(Buffer);
-    if (!BinaryOrErr)
-      return BinaryOrErr.takeError();
-
-    OffloadBinary &Binary = **BinaryOrErr;
-    printBinary(Binary, Index++);
-
-    Offset += Binary.getSize();
-  }
-  return Error::success();
-}
-
 /// Print the embedded offloading contents of an ObjectFile \p O.
 void llvm::dumpOffloadBinary(const ObjectFile &O) {
-  if (!O.isELF()) {
-    reportWarning("--offloading is currently only supported for ELF targets",
-                  O.getFileName());
+  if (!O.isELF() && !O.isCOFF()) {
+    reportWarning(
+        "--offloading is currently only supported for COFF and ELF targets",
+        O.getFileName());
     return;
   }
 
-  for (ELFSectionRef Sec : O.sections()) {
-    if (Sec.getType() != ELF::SHT_LLVM_OFFLOADING)
-      continue;
+  SmallVector<OffloadFile> Binaries;
+  if (Error Err = extractOffloadBinaries(O.getMemoryBufferRef(), Binaries))
+    reportError(O.getFileName(), "while extracting offloading files: " +
+                                     toString(std::move(Err)));
 
-    Expected<StringRef> Contents = Sec.getContents();
-    if (!Contents)
-      reportError(Contents.takeError(), O.getFileName());
-
-    std::unique_ptr<MemoryBuffer> Buffer =
-        MemoryBuffer::getMemBuffer(*Contents, O.getFileName(), false);
-    if (!isAddrAligned(Align(OffloadBinary::getAlignment()),
-                       Buffer->getBufferStart()))
-      Buffer = MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(),
-                                              Buffer->getBufferIdentifier());
-    auto BinaryOrErr = OffloadBinary::create(*Buffer);
-    if (!BinaryOrErr)
-      reportError(O.getFileName(), "while extracting offloading files: " +
-                                       toString(BinaryOrErr.takeError()));
-    OffloadBinary &Binary = **BinaryOrErr;
-
-    // Print out all the binaries that are contained in this buffer. If we fail
-    // to parse a binary before reaching the end of the buffer emit a warning.
-    if (Error Err = visitAllBinaries(Binary))
-      reportWarning("while parsing offloading files: " +
-                        toString(std::move(Err)),
-                    O.getFileName());
-  }
+  // Print out all the binaries that are contained in this buffer.
+  for (uint64_t I = 0, E = Binaries.size(); I != E; ++I)
+    printBinary(*Binaries[I].getBinary(), I);
 }
 
 /// Print the contents of an offload binary file \p OB. This may contain
 /// multiple binaries stored in the same buffer.
 void llvm::dumpOffloadSections(const OffloadBinary &OB) {
-  // Print out all the binaries that are contained at this buffer. If we fail to
-  // parse a binary before reaching the end of the buffer emit a warning.
-  if (Error Err = visitAllBinaries(OB))
-    reportWarning("while parsing offloading files: " + toString(std::move(Err)),
-                  OB.getFileName());
+  SmallVector<OffloadFile> Binaries;
+  if (Error Err = extractOffloadBinaries(OB.getMemoryBufferRef(), Binaries))
+    reportError(OB.getFileName(), "while extracting offloading files: " +
+                                      toString(std::move(Err)));
+
+  // Print out all the binaries that are contained in this buffer.
+  for (uint64_t I = 0, E = Binaries.size(); I != E; ++I)
+    printBinary(*Binaries[I].getBinary(), I);
 }
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/OtoolOpts.td b/src/llvm-project/llvm/tools/llvm-objdump/OtoolOpts.td
index e8bef28..dc7a5b4 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/OtoolOpts.td
+++ b/src/llvm-project/llvm/tools/llvm-objdump/OtoolOpts.td
@@ -37,13 +37,16 @@
 def x : Flag<["-"], "x">, HelpText<"print all text sections">;
 def X : Flag<["-"], "X">, HelpText<"omit leading addresses or headers">;
 
+def chained_fixups : Flag<["-"], "chained_fixups">,
+  HelpText<"print chained fixup information">;
+def dyld_info : Flag<["-"], "dyld_info">,
+  HelpText<"print bind and rebase information">;
+
 // Not (yet?) implemented:
 // def a : Flag<["-"], "a">, HelpText<"print archive header">;
 // -c print argument strings of a core file
 // -m don't use archive(member) syntax
-// -dyld_info
 // -dyld_opcodes
-// -chained_fixups
 // -addr_slide=arg
 // -function_offsets
 
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp b/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp
index c8ea6b5..6736cbc 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.cpp
@@ -31,7 +31,7 @@
 }
 
 bool LiveVariable::liveAtAddress(object::SectionedAddress Addr) {
-  if (LocExpr.Range == None)
+  if (LocExpr.Range == std::nullopt)
     return false;
   return LocExpr.Range->SectionIndex == Addr.SectionIndex &&
          LocExpr.Range->LowPC <= Addr.Address &&
@@ -42,7 +42,17 @@
   DataExtractor Data({LocExpr.Expr.data(), LocExpr.Expr.size()},
                      Unit->getContext().isLittleEndian(), 0);
   DWARFExpression Expression(Data, Unit->getAddressByteSize());
-  Expression.printCompact(OS, MRI);
+
+  auto GetRegName = [&MRI, &OS](uint64_t DwarfRegNum, bool IsEH) -> StringRef {
+    if (std::optional<unsigned> LLVMRegNum =
+            MRI.getLLVMRegNum(DwarfRegNum, IsEH))
+      if (const char *RegName = MRI.getName(*LLVMRegNum))
+        return StringRef(RegName);
+    OS << "<unknown register " << DwarfRegNum << ">";
+    return {};
+  };
+
+  Expression.printCompact(OS, GetRegName);
 }
 
 void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) {
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h b/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h
index 29ef19c..6209bb0 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h
+++ b/src/llvm-project/llvm/tools/llvm-objdump/SourcePrinter.h
@@ -13,6 +13,7 @@
 #include "llvm/ADT/StringSet.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
+#include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/MC/MCSubtargetInfo.h"
 #include "llvm/Support/FormattedStream.h"
 #include <unordered_map>
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp b/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
index dd1570e1..7171e2e 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.cpp
@@ -43,31 +43,31 @@
   return Error::success();
 }
 
-Optional<XCOFF::StorageMappingClass>
+std::optional<XCOFF::StorageMappingClass>
 objdump::getXCOFFSymbolCsectSMC(const XCOFFObjectFile &Obj,
                                 const SymbolRef &Sym) {
   const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl());
 
   if (!SymRef.isCsectSymbol())
-    return None;
+    return std::nullopt;
 
   auto CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
   if (!CsectAuxEntOrErr)
-    return None;
+    return std::nullopt;
 
   return CsectAuxEntOrErr.get().getStorageMappingClass();
 }
 
-Optional<object::SymbolRef>
+std::optional<object::SymbolRef>
 objdump::getXCOFFSymbolContainingSymbolRef(const XCOFFObjectFile &Obj,
                                            const SymbolRef &Sym) {
   const XCOFFSymbolRef SymRef = Obj.toSymbolRef(Sym.getRawDataRefImpl());
   if (!SymRef.isCsectSymbol())
-    return None;
+    return std::nullopt;
 
   Expected<XCOFFCsectAuxRef> CsectAuxEntOrErr = SymRef.getXCOFFCsectAuxRef();
   if (!CsectAuxEntOrErr || !CsectAuxEntOrErr.get().isLabel())
-    return None;
+    return std::nullopt;
   uint32_t Idx =
       static_cast<uint32_t>(CsectAuxEntOrErr.get().getSectionOrLength());
   DataRefImpl DRI;
@@ -94,9 +94,9 @@
   std::string Result;
   // Dummy symbols have no symbol index.
   if (SymbolInfo.XCOFFSymInfo.Index)
-    Result = ("(idx: " + Twine(SymbolInfo.XCOFFSymInfo.Index.value()) + ") " +
-              SymbolName)
-                 .str();
+    Result =
+        ("(idx: " + Twine(*SymbolInfo.XCOFFSymInfo.Index) + ") " + SymbolName)
+            .str();
   else
     Result.append(SymbolName.begin(), SymbolName.end());
 
diff --git a/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h b/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h
index 4616059..35d1c0f 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h
+++ b/src/llvm-project/llvm/tools/llvm-objdump/XCOFFDump.h
@@ -16,11 +16,11 @@
 struct SymbolInfoTy;
 
 namespace objdump {
-Optional<XCOFF::StorageMappingClass>
+std::optional<XCOFF::StorageMappingClass>
 getXCOFFSymbolCsectSMC(const object::XCOFFObjectFile &Obj,
                        const object::SymbolRef &Sym);
 
-Optional<object::SymbolRef>
+std::optional<object::SymbolRef>
 getXCOFFSymbolContainingSymbolRef(const object::XCOFFObjectFile &Obj,
                                   const object::SymbolRef &Sym);
 
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 fd83dc1..9979a26 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -25,7 +25,6 @@
 #include "WasmDump.h"
 #include "XCOFFDump.h"
 #include "llvm/ADT/IndexedMap.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SetOperations.h"
 #include "llvm/ADT/SmallSet.h"
@@ -36,6 +35,9 @@
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
+#include "llvm/Debuginfod/BuildIDFetcher.h"
+#include "llvm/Debuginfod/Debuginfod.h"
+#include "llvm/Debuginfod/HTTPClient.h"
 #include "llvm/Demangle/Demangle.h"
 #include "llvm/MC/MCAsmInfo.h"
 #include "llvm/MC/MCContext.h"
@@ -51,6 +53,7 @@
 #include "llvm/MC/MCTargetOptions.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Object/Archive.h"
+#include "llvm/Object/BuildID.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Object/COFFImportFile.h"
 #include "llvm/Object/ELFObjectFile.h"
@@ -82,6 +85,7 @@
 #include <algorithm>
 #include <cctype>
 #include <cstring>
+#include <optional>
 #include <system_error>
 #include <unordered_map>
 #include <utility>
@@ -93,18 +97,19 @@
 
 namespace {
 
-class CommonOptTable : public opt::OptTable {
+class CommonOptTable : public opt::GenericOptTable {
 public:
   CommonOptTable(ArrayRef<Info> OptionInfos, const char *Usage,
                  const char *Description)
-      : OptTable(OptionInfos), Usage(Usage), Description(Description) {
+      : opt::GenericOptTable(OptionInfos), Usage(Usage),
+        Description(Description) {
     setGroupedShortOptions(true);
   }
 
   void printHelp(StringRef Argv0, bool ShowHidden = false) const {
     Argv0 = sys::path::filename(Argv0);
-    opt::OptTable::printHelp(outs(), (Argv0 + Usage).str().c_str(), Description,
-                             ShowHidden, ShowHidden);
+    opt::GenericOptTable::printHelp(outs(), (Argv0 + Usage).str().c_str(),
+                                    Description, ShowHidden, ShowHidden);
     // TODO Replace this with OptTable API once it adds extrahelp support.
     outs() << "\nPass @FILE as argument to read options from FILE.\n";
   }
@@ -115,28 +120,31 @@
 };
 
 // ObjdumpOptID is in ObjdumpOptID.h
-
-#define PREFIX(NAME, VALUE) const char *const OBJDUMP_##NAME[] = VALUE;
+namespace objdump_opt {
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
 #include "ObjdumpOpts.inc"
 #undef PREFIX
 
 static constexpr opt::OptTable::Info ObjdumpInfoTable[] = {
-#define OBJDUMP_nullptr nullptr
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
-  {OBJDUMP_##PREFIX, NAME,         HELPTEXT,                                   \
-   METAVAR,          OBJDUMP_##ID, opt::Option::KIND##Class,                   \
-   PARAM,            FLAGS,        OBJDUMP_##GROUP,                            \
-   OBJDUMP_##ALIAS,  ALIASARGS,    VALUES},
+  {PREFIX,          NAME,         HELPTEXT,                                    \
+   METAVAR,         OBJDUMP_##ID, opt::Option::KIND##Class,                    \
+   PARAM,           FLAGS,        OBJDUMP_##GROUP,                             \
+   OBJDUMP_##ALIAS, ALIASARGS,    VALUES},
 #include "ObjdumpOpts.inc"
 #undef OPTION
-#undef OBJDUMP_nullptr
 };
+} // namespace objdump_opt
 
 class ObjdumpOptTable : public CommonOptTable {
 public:
   ObjdumpOptTable()
-      : CommonOptTable(ObjdumpInfoTable, " [options] <input object files>",
+      : CommonOptTable(objdump_opt::ObjdumpInfoTable,
+                       " [options] <input object files>",
                        "llvm object file dumper") {}
 };
 
@@ -149,27 +157,30 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const OTOOL_##NAME[] = VALUE;
+namespace otool {
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
 #include "OtoolOpts.inc"
 #undef PREFIX
 
 static constexpr opt::OptTable::Info OtoolInfoTable[] = {
-#define OTOOL_nullptr nullptr
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
-  {OTOOL_##PREFIX, NAME,       HELPTEXT,                                       \
-   METAVAR,        OTOOL_##ID, opt::Option::KIND##Class,                       \
-   PARAM,          FLAGS,      OTOOL_##GROUP,                                  \
-   OTOOL_##ALIAS,  ALIASARGS,  VALUES},
+  {PREFIX,        NAME,       HELPTEXT,                                        \
+   METAVAR,       OTOOL_##ID, opt::Option::KIND##Class,                        \
+   PARAM,         FLAGS,      OTOOL_##GROUP,                                   \
+   OTOOL_##ALIAS, ALIASARGS,  VALUES},
 #include "OtoolOpts.inc"
 #undef OPTION
-#undef OTOOL_nullptr
 };
+} // namespace otool
 
 class OtoolOptTable : public CommonOptTable {
 public:
   OtoolOptTable()
-      : CommonOptTable(OtoolInfoTable, " [option...] [file...]",
+      : CommonOptTable(otool::OtoolInfoTable, " [option...] [file...]",
                        "Mach-O object file displaying tool") {}
 };
 
@@ -207,6 +218,7 @@
 bool objdump::PrivateHeaders;
 std::vector<std::string> objdump::FilterSections;
 bool objdump::SectionHeaders;
+static bool ShowAllSymbols;
 static bool ShowLMA;
 bool objdump::PrintSource;
 
@@ -232,6 +244,9 @@
 StringSet<> objdump::FoundSectionSet;
 static StringRef ToolName;
 
+std::unique_ptr<BuildIDFetcher> BIDFetcher;
+ExitOnError ExitOnErr;
+
 namespace {
 struct FilterResult {
   // True if the section should not be skipped.
@@ -454,16 +469,24 @@
   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) {
-  StringRef Fmt = Is64Bits ? "\t\t%016" PRIx64 ":  " : "\t\t\t%08" PRIx64 ":  ";
+  StringRef Fmt = Is64Bits ? "%016" PRIx64 ":  " : "%08" PRIx64 ":  ";
   SmallString<16> Name;
   SmallString<32> Val;
   Rel.getTypeName(Name);
   if (Error E = getRelocationValueString(Rel, Val))
     reportError(std::move(E), FileName);
-  OS << format(Fmt.data(), Address) << Name << "\t" << Val;
+  OS << (Is64Bits || !LeadingAddr ? "\t\t" : "\t\t\t");
+  if (LeadingAddr)
+    OS << format(Fmt.data(), Address);
+  OS << Name << "\t" << Val;
 }
 
 static void AlignToInstStartColumn(size_t Start, const MCSubtargetInfo &STI,
@@ -631,10 +654,10 @@
     if (Bytes.size() >= 4) {
       // D should be casted to uint32_t here as it is passed by format to
       // snprintf as vararg.
-      for (uint32_t D : makeArrayRef(
-               reinterpret_cast<const support::little32_t *>(Bytes.data()),
-               Bytes.size() / 4))
-        OS << format(" %08" PRIX32, D);
+      for (uint32_t D :
+           ArrayRef(reinterpret_cast<const support::little32_t *>(Bytes.data()),
+                    Bytes.size() / 4))
+          OS << format(" %08" PRIX32, D);
     } else {
       for (unsigned char B : Bytes)
         OS << format(" %02" PRIX8, B);
@@ -690,14 +713,14 @@
           OS << ' '
              << format_hex_no_prefix(
                     llvm::support::endian::read<uint16_t>(
-                        Bytes.data() + Pos, llvm::support::little),
+                        Bytes.data() + Pos, InstructionEndianness),
                     4);
       } else {
         for (; Pos + 4 <= End; Pos += 4)
           OS << ' '
              << format_hex_no_prefix(
                     llvm::support::endian::read<uint32_t>(
-                        Bytes.data() + Pos, llvm::support::little),
+                        Bytes.data() + Pos, InstructionEndianness),
                     8);
       }
       if (Pos < End) {
@@ -713,6 +736,13 @@
     } else
       OS << "\t<unknown>";
   }
+
+  void setInstructionEndianness(llvm::support::endianness Endianness) {
+    InstructionEndianness = Endianness;
+  }
+
+private:
+  llvm::support::endianness InstructionEndianness = llvm::support::little;
 };
 ARMPrettyPrinter ARMPrettyPrinterInst;
 
@@ -844,19 +874,19 @@
     llvm_unreachable("Unsupported binary format");
 }
 
-static Optional<SectionRef> getWasmCodeSection(const WasmObjectFile &Obj) {
+static std::optional<SectionRef> getWasmCodeSection(const WasmObjectFile &Obj) {
   for (auto SecI : Obj.sections()) {
     const WasmSection &Section = Obj.getWasmSection(SecI);
     if (Section.Type == wasm::WASM_SEC_CODE)
       return SecI;
   }
-  return None;
+  return std::nullopt;
 }
 
 static void
 addMissingWasmCodeSymbols(const WasmObjectFile &Obj,
                           std::map<SectionRef, SectionSymbolsTy> &AllSymbols) {
-  Optional<SectionRef> Section = getWasmCodeSection(Obj);
+  std::optional<SectionRef> Section = getWasmCodeSection(Obj);
   if (!Section)
     return;
   SectionSymbolsTy &Symbols = AllSymbols[*Section];
@@ -884,7 +914,7 @@
 static void addPltEntries(const ObjectFile &Obj,
                           std::map<SectionRef, SectionSymbolsTy> &AllSymbols,
                           StringSaver &Saver) {
-  Optional<SectionRef> Plt = None;
+  std::optional<SectionRef> Plt;
   for (const SectionRef &Section : Obj.sections()) {
     Expected<StringRef> SecNameOrErr = Section.getName();
     if (!SecNameOrErr) {
@@ -1065,7 +1095,7 @@
     DataRefImpl SymbolDRI = Symbol.getRawDataRefImpl();
 
     const uint32_t SymbolIndex = XCOFFObj.getSymbolIndex(SymbolDRI.p);
-    Optional<XCOFF::StorageMappingClass> Smc =
+    std::optional<XCOFF::StorageMappingClass> Smc =
         getXCOFFSymbolCsectSMC(XCOFFObj, Symbol);
     return SymbolInfoTy(Addr, Name, Smc, SymbolIndex,
                         isLabel(XCOFFObj, Symbol));
@@ -1082,7 +1112,7 @@
                                           const uint64_t Addr, StringRef &Name,
                                           uint8_t Type) {
   if (Obj.isXCOFF() && SymbolDescription)
-    return SymbolInfoTy(Addr, Name, None, None, false);
+    return SymbolInfoTy(Addr, Name, std::nullopt, std::nullopt, false);
   else
     return SymbolInfoTy(Addr, Name, Type);
 }
@@ -1172,8 +1202,9 @@
   for (size_t Index = 0; Index != Bytes.size();) {
     MCInst Inst;
     uint64_t Size;
-    ArrayRef<uint8_t> ThisBytes = Bytes.slice(Index - SectionAddr);
-    DisAsm->getInstruction(Inst, Size, ThisBytes, Index, nulls());
+    ArrayRef<uint8_t> ThisBytes = Bytes.slice(Index);
+    const uint64_t ThisAddr = SectionAddr + Index;
+    DisAsm->getInstruction(Inst, Size, ThisBytes, ThisAddr, nulls());
     if (Size == 0)
       Size = std::min<uint64_t>(ThisBytes.size(),
                                 DisAsm->suggestBytesToSkip(ThisBytes, Index));
@@ -1250,8 +1281,27 @@
     llvm_unreachable("Unsupported binary format");
 }
 
+// Tries to fetch a more complete version of the given object file using its
+// Build ID. Returns std::nullopt if nothing was found.
+static std::optional<OwningBinary<Binary>>
+fetchBinaryByBuildID(const ObjectFile &Obj) {
+  std::optional<object::BuildIDRef> BuildID = getBuildID(&Obj);
+  if (!BuildID)
+    return std::nullopt;
+  std::optional<std::string> Path = BIDFetcher->fetch(*BuildID);
+  if (!Path)
+    return std::nullopt;
+  Expected<OwningBinary<Binary>> DebugBinary = createBinary(*Path);
+  if (!DebugBinary) {
+    reportWarning(toString(DebugBinary.takeError()), *Path);
+    return std::nullopt;
+  }
+  return std::move(*DebugBinary);
+}
+
 static void disassembleObject(const Target *TheTarget, ObjectFile &Obj,
-                              MCContext &Ctx, MCDisassembler *PrimaryDisAsm,
+                              const ObjectFile &DbgObj, MCContext &Ctx,
+                              MCDisassembler *PrimaryDisAsm,
                               MCDisassembler *SecondaryDisAsm,
                               const MCInstrAnalysis *MIA, MCInstPrinter *IP,
                               const MCSubtargetInfo *PrimarySTI,
@@ -1376,7 +1426,7 @@
   LiveVariablePrinter LVP(*Ctx.getRegisterInfo(), *STI);
 
   if (DbgVariables != DVDisabled) {
-    DICtx = DWARFContext::create(Obj);
+    DICtx = DWARFContext::create(DbgObj);
     for (const std::unique_ptr<DWARFUnit> &CU : DICtx->compile_units())
       LVP.addCompileUnit(CU->getUnitDIE(false));
   }
@@ -1384,13 +1434,13 @@
   LLVM_DEBUG(LVP.dump());
 
   std::unordered_map<uint64_t, BBAddrMap> AddrToBBAddrMap;
-  auto ReadBBAddrMap = [&](Optional<unsigned> SectionIndex = None) {
+  auto ReadBBAddrMap = [&](std::optional<unsigned> SectionIndex =
+                               std::nullopt) {
     AddrToBBAddrMap.clear();
     if (const auto *Elf = dyn_cast<ELFObjectFileBase>(&Obj)) {
       auto BBAddrMapsOrErr = Elf->readBBAddrMap(SectionIndex);
       if (!BBAddrMapsOrErr)
-          reportWarning(toString(BBAddrMapsOrErr.takeError()),
-                        Obj.getFileName());
+        reportWarning(toString(BBAddrMapsOrErr.takeError()), Obj.getFileName());
       for (auto &FunctionBBAddrMap : *BBAddrMapsOrErr)
         AddrToBBAddrMap.emplace(FunctionBBAddrMap.Addr,
                                 std::move(FunctionBBAddrMap));
@@ -1474,28 +1524,118 @@
     std::vector<RelocationRef> Rels = RelocMap[Section];
     std::vector<RelocationRef>::const_iterator RelCur = Rels.begin();
     std::vector<RelocationRef>::const_iterator RelEnd = Rels.end();
-    // Disassemble symbol by symbol.
-    for (unsigned SI = 0, SE = Symbols.size(); SI != SE; ++SI) {
-      std::string SymbolName = Symbols[SI].Name.str();
-      if (Demangle)
-        SymbolName = demangle(SymbolName);
 
-      // Skip if --disassemble-symbols is not empty and the symbol is not in
-      // the list.
-      if (!DisasmSymbolSet.empty() && !DisasmSymbolSet.count(SymbolName))
-        continue;
-
+    // Loop over each chunk of code between two points where at least
+    // one symbol is defined.
+    for (size_t SI = 0, SE = Symbols.size(); SI != SE;) {
+      // Advance SI past all the symbols starting at the same address,
+      // and make an ArrayRef of them.
+      unsigned FirstSI = SI;
       uint64_t Start = Symbols[SI].Addr;
+      ArrayRef<SymbolInfoTy> SymbolsHere;
+      while (SI != SE && Symbols[SI].Addr == Start)
+        ++SI;
+      SymbolsHere = ArrayRef<SymbolInfoTy>(&Symbols[FirstSI], SI - FirstSI);
+
+      // Get the demangled names of all those symbols. We end up with a vector
+      // of StringRef that holds the names we're going to use, and a vector of
+      // std::string that stores the new strings returned by demangle(), if
+      // any. If we don't call demangle() then that vector can stay empty.
+      std::vector<StringRef> SymNamesHere;
+      std::vector<std::string> DemangledSymNamesHere;
+      if (Demangle) {
+        // Fetch the demangled names and store them locally.
+        for (const SymbolInfoTy &Symbol : SymbolsHere)
+          DemangledSymNamesHere.push_back(demangle(Symbol.Name.str()));
+        // Now we've finished modifying that vector, it's safe to make
+        // a vector of StringRefs pointing into it.
+        SymNamesHere.insert(SymNamesHere.begin(), DemangledSymNamesHere.begin(),
+                            DemangledSymNamesHere.end());
+      } else {
+        for (const SymbolInfoTy &Symbol : SymbolsHere)
+          SymNamesHere.push_back(Symbol.Name);
+      }
+
+      // Distinguish ELF data from code symbols, which will be used later on to
+      // decide whether to 'disassemble' this chunk as a data declaration via
+      // dumpELFData(), or whether to treat it as code.
+      //
+      // If data _and_ code symbols are defined at the same address, the code
+      // takes priority, on the grounds that disassembling code is our main
+      // purpose here, and it would be a worse failure to _not_ interpret
+      // something that _was_ meaningful as code than vice versa.
+      //
+      // Any ELF symbol type that is not clearly data will be regarded as code.
+      // In particular, one of the uses of STT_NOTYPE is for branch targets
+      // 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
+      // 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;
+      size_t DisplaySymIndex = SymbolsHere.size() - 1;
+      if (Obj.isELF() && !DisassembleAll && Section.isText()) {
+        DisassembleAsData = 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;
+            DisplaySymIndex = i;
+          }
+        }
+      }
+
+      // Decide which symbol(s) from this collection we're going to print.
+      std::vector<bool> SymsToPrint(SymbolsHere.size(), false);
+      // If the user has given the --disassemble-symbols option, then we must
+      // display every symbol in that set, and no others.
+      if (!DisasmSymbolSet.empty()) {
+        bool FoundAny = false;
+        for (size_t i = 0; i < SymbolsHere.size(); ++i) {
+          if (DisasmSymbolSet.count(SymNamesHere[i])) {
+            SymsToPrint[i] = true;
+            FoundAny = true;
+          }
+        }
+
+        // And if none of the symbols here is one that the user asked for, skip
+        // disassembling this entire chunk of code.
+        if (!FoundAny)
+          continue;
+      } else {
+        // 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.
+        SymsToPrint[DisplaySymIndex] = true;
+      }
+
+      // Now that we know we're disassembling this section, override the choice
+      // of which symbols to display by printing _all_ of them at this address
+      // if the user asked for all symbols.
+      //
+      // That way, '--show-all-symbols --disassemble-symbol=foo' will print
+      // only the chunk of code headed by 'foo', but also show any other
+      // symbols defined at that address, such as aliases for 'foo', or the ARM
+      // mapping symbol preceding its code.
+      if (ShowAllSymbols) {
+        for (size_t i = 0; i < SymbolsHere.size(); ++i)
+          SymsToPrint[i] = true;
+      }
+
       if (Start < SectionAddr || StopAddress <= Start)
         continue;
-      else
-        FoundDisasmSymbolSet.insert(SymbolName);
+
+      for (size_t i = 0; i < SymbolsHere.size(); ++i)
+        FoundDisasmSymbolSet.insert(SymNamesHere[i]);
 
       // The end is the section end, the beginning of the next symbol, or
       // --stop-address.
       uint64_t End = std::min<uint64_t>(SectionAddr + SectSize, StopAddress);
-      if (SI + 1 < SE)
-        End = std::min(End, Symbols[SI + 1].Addr);
+      if (SI < SE)
+        End = std::min(End, Symbols[SI].Addr);
       if (Start >= End || End <= StartAddress)
         continue;
       Start -= SectionAddr;
@@ -1510,13 +1650,22 @@
       }
 
       outs() << '\n';
-      if (LeadingAddr)
-        outs() << format(Is64Bits ? "%016" PRIx64 " " : "%08" PRIx64 " ",
-                         SectionAddr + Start + VMAAdjustment);
-      if (Obj.isXCOFF() && SymbolDescription) {
-        outs() << getXCOFFSymbolDescription(Symbols[SI], SymbolName) << ":\n";
-      } else
-        outs() << '<' << SymbolName << ">:\n";
+
+      for (size_t i = 0; i < SymbolsHere.size(); ++i) {
+        if (!SymsToPrint[i])
+          continue;
+
+        const SymbolInfoTy &Symbol = SymbolsHere[i];
+        const StringRef SymbolName = SymNamesHere[i];
+
+        if (LeadingAddr)
+          outs() << format(Is64Bits ? "%016" PRIx64 " " : "%08" PRIx64 " ",
+                           SectionAddr + Start + VMAAdjustment);
+        if (Obj.isXCOFF() && SymbolDescription) {
+          outs() << getXCOFFSymbolDescription(Symbol, SymbolName) << ":\n";
+        } else
+          outs() << '<' << SymbolName << ">:\n";
+      }
 
       // Don't print raw contents of a virtual section. A virtual section
       // doesn't have any contents in the file.
@@ -1525,57 +1674,67 @@
         continue;
       }
 
-      auto Status = DisAsm->onSymbolStart(Symbols[SI], Size,
-                                          Bytes.slice(Start, End - Start),
-                                          SectionAddr + Start, CommentStream);
-      // To have round trippable disassembly, we fall back to decoding the
-      // remaining bytes as instructions.
+      // See if any of the symbols defined at this location triggers target-
+      // specific disassembly behavior, e.g. of special descriptors or function
+      // prelude information.
       //
-      // If there is a failure, we disassemble the failed region as bytes before
-      // falling back. The target is expected to print nothing in this case.
-      //
-      // If there is Success or SoftFail i.e no 'real' failure, we go ahead by
-      // Size bytes before falling back.
-      // So if the entire symbol is 'eaten' by the target:
-      //   Start += Size  // Now Start = End and we will never decode as
-      //                  // instructions
-      //
-      // Right now, most targets return None i.e ignore to treat a symbol
-      // separately. But WebAssembly decodes preludes for some symbols.
-      //
-      if (Status) {
-        if (Status.value() == MCDisassembler::Fail) {
-          outs() << "// Error in decoding " << SymbolName
+      // We stop this loop at the first symbol that triggers some kind of
+      // interesting behavior (if any), on the assumption that if two symbols
+      // defined at the same address trigger two conflicting symbol handlers,
+      // the object file is probably confused anyway, and it would make even
+      // less sense to present the output of _both_ handlers, because that
+      // would describe the same data twice.
+      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);
+
+        if (!Status) {
+          // If onSymbolStart returns std::nullopt, that means it didn't trigger
+          // any interesting handling for this symbol. Try the other symbols
+          // defined at this address.
+          continue;
+        }
+
+        if (*Status == MCDisassembler::Fail) {
+          // If onSymbolStart returns Fail, that means it identified some kind
+          // of special data at this address, but wasn't able to disassemble it
+          // meaningfully. So we fall back to disassembling the failed region
+          // as bytes, assuming that the target detected the failure before
+          // printing anything.
+          //
+          // Return values Success or SoftFail (i.e no 'real' failure) are
+          // expected to mean that the target has emitted its own output.
+          //
+          // Either way, 'Size' will have been set to the amount of data
+          // covered by whatever prologue the target identified. So we advance
+          // our own position to beyond that. Sometimes that will be the entire
+          // 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() << "// Error in decoding " << SymNamesHere[SHI]
                  << " : Decoding failed region as bytes.\n";
           for (uint64_t I = 0; I < Size; ++I) {
             outs() << "\t.byte\t " << format_hex(Bytes[I], 1, /*Upper=*/true)
                    << "\n";
           }
         }
-      } else {
-        Size = 0;
+        Start += Size;
+        break;
       }
 
-      Start += Size;
-
       Index = Start;
       if (SectionAddr < StartAddress)
         Index = std::max<uint64_t>(Index, StartAddress - SectionAddr);
 
-      // If there is a data/common symbol inside an ELF text section and we are
-      // only disassembling text (applicable all architectures), we are in a
-      // situation where we must print the data and not disassemble it.
-      if (Obj.isELF() && !DisassembleAll && Section.isText()) {
-        uint8_t SymTy = Symbols[SI].Type;
-        if (SymTy == ELF::STT_OBJECT || SymTy == ELF::STT_COMMON) {
-          dumpELFData(SectionAddr, Index, End, Bytes);
-          Index = End;
-        }
+      if (DisassembleAsData) {
+        dumpELFData(SectionAddr, Index, End, Bytes);
+        Index = End;
+        continue;
       }
 
-      bool CheckARMELFData = hasMappingSymbols(Obj) &&
-                             Symbols[SI].Type != ELF::STT_OBJECT &&
-                             !DisassembleAll;
       bool DumpARMELFData = false;
       formatted_raw_ostream FOS(outs());
 
@@ -1593,7 +1752,7 @@
         // 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
         // denoted as a word/short etc.
-        if (CheckARMELFData) {
+        if (!MappingSymbols.empty()) {
           char Kind = getMappingSymbolKind(MappingSymbols, Index);
           DumpARMELFData = Kind == 'd';
           if (SecondarySTI) {
@@ -1675,7 +1834,7 @@
             bool PrintTarget =
                 MIA->evaluateBranch(Inst, SectionAddr + Index, Size, Target);
             if (!PrintTarget)
-              if (Optional<uint64_t> MaybeTarget =
+              if (std::optional<uint64_t> MaybeTarget =
                       MIA->evaluateMemoryOperandAddress(
                           Inst, STI, SectionAddr + Index, Size)) {
                 Target = *MaybeTarget;
@@ -1729,10 +1888,17 @@
                 auto It = llvm::partition_point(
                     *TargetSymbols,
                     [=](const SymbolInfoTy &O) { return O.Addr <= Target; });
-                if (It != TargetSymbols->begin()) {
-                  TargetSym = &*(It - 1);
-                  break;
+                while (It != TargetSymbols->begin()) {
+                  --It;
+                  // Skip mapping symbols to avoid possible ambiguity as they
+                  // do not allow uniquely identifying the target address.
+                  if (!hasMappingSymbols(Obj) || !isMappingSymbol(*It)) {
+                    TargetSym = &*It;
+                    break;
+                  }
                 }
+                if (TargetSym)
+                  break;
               }
 
               // Print the labels corresponding to the target if there's any.
@@ -1824,10 +1990,29 @@
 }
 
 static void disassembleObject(ObjectFile *Obj, bool InlineRelocs) {
+  // If information useful for showing the disassembly is missing, try to find a
+  // more complete binary and disassemble that instead.
+  OwningBinary<Binary> FetchedBinary;
+  if (Obj->symbols().empty()) {
+    if (std::optional<OwningBinary<Binary>> FetchedBinaryOpt =
+            fetchBinaryByBuildID(*Obj)) {
+      if (auto *O = dyn_cast<ObjectFile>(FetchedBinaryOpt->getBinary())) {
+        if (!O->symbols().empty() ||
+            (!O->sections().empty() && Obj->sections().empty())) {
+          FetchedBinary = std::move(*FetchedBinaryOpt);
+          Obj = O;
+        }
+      }
+    }
+  }
+
   const Target *TheTarget = getTarget(Obj);
 
   // Package up features to be passed to target/subtarget
-  SubtargetFeatures Features = Obj->getFeatures();
+  Expected<SubtargetFeatures> FeaturesValue = Obj->getFeatures();
+  if (!FeaturesValue)
+    reportError(FeaturesValue.takeError(), Obj->getFileName());
+  SubtargetFeatures Features = *FeaturesValue;
   if (!MAttrs.empty()) {
     for (unsigned I = 0; I != MAttrs.size(); ++I)
       Features.AddFeature(MAttrs[I]);
@@ -1852,6 +2037,29 @@
   if (MCPU.empty())
     MCPU = Obj->tryGetCPUName().value_or("").str();
 
+  if (isArmElf(*Obj)) {
+    // When disassembling big-endian Arm ELF, the instruction endianness is
+    // determined in a complex way. In relocatable objects, AAELF32 mandates
+    // that instruction endianness matches the ELF file endianness; in
+    // executable images, that's true unless the file header has the EF_ARM_BE8
+    // flag, in which case instructions are little-endian regardless of data
+    // endianness.
+    //
+    // We must set the big-endian-instructions SubtargetFeature to make the
+    // disassembler read the instructions the right way round, and also tell
+    // our own prettyprinter to retrieve the encodings the same way to print in
+    // hex.
+    const auto *Elf32BE = dyn_cast<ELF32BEObjectFile>(Obj);
+
+    if (Elf32BE && (Elf32BE->isRelocatableObject() ||
+                    !(Elf32BE->getPlatformFlags() & ELF::EF_ARM_BE8))) {
+      Features.AddFeature("+big-endian-instructions");
+      ARMPrettyPrinterInst.setInstructionEndianness(llvm::support::big);
+    } else {
+      ARMPrettyPrinterInst.setInstructionEndianness(llvm::support::little);
+    }
+  }
+
   std::unique_ptr<const MCSubtargetInfo> STI(
       TheTarget->createMCSubtargetInfo(TripleName, MCPU, Features.getString()));
   if (!STI)
@@ -1903,16 +2111,42 @@
   IP->setMCInstrAnalysis(MIA.get());
 
   PrettyPrinter &PIP = selectPrettyPrinter(Triple(TripleName));
-  SourcePrinter SP(Obj, TheTarget->getName());
+
+  const ObjectFile *DbgObj = Obj;
+  if (!FetchedBinary.getBinary() && !Obj->hasDebugInfo()) {
+    if (std::optional<OwningBinary<Binary>> DebugBinaryOpt =
+            fetchBinaryByBuildID(*Obj)) {
+      if (auto *FetchedObj =
+              dyn_cast<const ObjectFile>(DebugBinaryOpt->getBinary())) {
+        if (FetchedObj->hasDebugInfo()) {
+          FetchedBinary = std::move(*DebugBinaryOpt);
+          DbgObj = FetchedObj;
+        }
+      }
+    }
+  }
+
+  std::unique_ptr<object::Binary> DSYMBinary;
+  std::unique_ptr<MemoryBuffer> DSYMBuf;
+  if (!DbgObj->hasDebugInfo()) {
+    if (const MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*Obj)) {
+      DbgObj = objdump::getMachODSymObject(MachOOF, Obj->getFileName(),
+                                           DSYMBinary, DSYMBuf);
+      if (!DbgObj)
+        return;
+    }
+  }
+
+  SourcePrinter SP(DbgObj, TheTarget->getName());
 
   for (StringRef Opt : DisassemblerOptions)
     if (!IP->applyTargetSpecificCLOption(Opt))
       reportError(Obj->getFileName(),
                   "Unrecognized disassembler option: " + Opt);
 
-  disassembleObject(TheTarget, *Obj, Ctx, DisAsm.get(), SecondaryDisAsm.get(),
-                    MIA.get(), IP.get(), STI.get(), SecondarySTI.get(), PIP, SP,
-                    InlineRelocs);
+  disassembleObject(TheTarget, *Obj, *DbgObj, Ctx, DisAsm.get(),
+                    SecondaryDisAsm.get(), MIA.get(), IP.get(), STI.get(),
+                    SecondarySTI.get(), PIP, SP, InlineRelocs);
 }
 
 void objdump::printRelocations(const ObjectFile *Obj) {
@@ -2026,6 +2260,9 @@
 }
 
 void objdump::printSectionHeaders(ObjectFile &Obj) {
+  if (Obj.isELF() && Obj.sections().empty())
+    createFakeELFSections(Obj);
+
   size_t NameWidth = getMaxSectionNameWidth(Obj);
   size_t AddressWidth = 2 * Obj.getBytesInAddress();
   bool HasLMAColumn = shouldDisplayLMA(Obj);
@@ -2038,9 +2275,6 @@
     outs() << "Idx " << left_justify("Name", NameWidth) << " Size     "
            << left_justify("VMA", AddressWidth) << " Type\n";
 
-  if (Obj.isELF() && Obj.sections().empty())
-    createFakeELFSections(Obj);
-
   uint64_t Idx;
   for (const SectionRef &Section : ToolSectionFilter(Obj, &Idx)) {
     StringRef Name = unwrapOrError(Section.getName(), Obj.getFileName());
@@ -2267,7 +2501,7 @@
     StringRef SectionName = unwrapOrError(Section->getName(), FileName);
     outs() << SectionName;
     if (O.isXCOFF()) {
-      Optional<SymbolRef> SymRef =
+      std::optional<SymbolRef> SymRef =
           getXCOFFSymbolContainingSymbolRef(cast<XCOFFObjectFile>(O), Symbol);
       if (SymRef) {
 
@@ -2281,8 +2515,8 @@
             SymName = demangle(SymName);
 
           if (SymbolDescription)
-            SymName = getXCOFFSymbolDescription(
-                createSymbolInfo(O, SymRef.value()), SymName);
+            SymName = getXCOFFSymbolDescription(createSymbolInfo(O, *SymRef),
+                                                SymName);
 
           outs() << ' ' << SymName;
           outs() << ") ";
@@ -2373,7 +2607,7 @@
     ClangASTSectionName = "clangast";
   }
 
-  Optional<object::SectionRef> ClangASTSection;
+  std::optional<object::SectionRef> ClangASTSection;
   for (auto Sec : ToolSectionFilter(*Obj)) {
     StringRef Name;
     if (Expected<StringRef> NameOrErr = Sec.getName())
@@ -2390,7 +2624,7 @@
     return;
 
   StringRef ClangASTContents =
-      unwrapOrError(ClangASTSection.value().getContents(), Obj->getFileName());
+      unwrapOrError(ClangASTSection->getContents(), Obj->getFileName());
   outs().write(ClangASTContents.data(), ClangASTContents.size());
 }
 
@@ -2408,7 +2642,7 @@
     return;
   }
 
-  Optional<object::SectionRef> FaultMapSection;
+  std::optional<object::SectionRef> FaultMapSection;
 
   for (auto Sec : ToolSectionFilter(*Obj)) {
     StringRef Name;
@@ -2705,7 +2939,18 @@
   }
 }
 
-static void invalidArgValue(const opt::Arg *A) {
+static object::BuildID parseBuildIDArg(const opt::Arg *A) {
+  StringRef V(A->getValue());
+  std::string Bytes;
+  if (!tryGetFromHex(V, Bytes))
+    reportCmdLineError(A->getSpelling() + ": expected a build ID, but got '" +
+                       V + "'");
+  ArrayRef<uint8_t> BuildID(reinterpret_cast<const uint8_t *>(Bytes.data()),
+                            Bytes.size());
+  return object::BuildID(BuildID.begin(), BuildID.end());
+}
+
+void objdump::invalidArgValue(const opt::Arg *A) {
   reportCmdLineError("'" + StringRef(A->getValue()) +
                      "' is not a valid value for '" + A->getSpelling() + "'");
 }
@@ -2757,6 +3002,9 @@
     FilterSections.push_back(",__text");
   LeadingAddr = LeadingHeaders = !InputArgs.hasArg(OTOOL_X);
 
+  ChainedFixups = InputArgs.hasArg(OTOOL_chained_fixups);
+  DyldInfo = InputArgs.hasArg(OTOOL_dyld_info);
+
   InputFilenames = InputArgs.getAllArgValues(OTOOL_INPUT);
   if (InputFilenames.empty())
     reportCmdLineError("no input file");
@@ -2804,10 +3052,11 @@
   RawClangAST = InputArgs.hasArg(OBJDUMP_raw_clang_ast);
   Relocations = InputArgs.hasArg(OBJDUMP_reloc);
   PrintImmHex =
-      InputArgs.hasFlag(OBJDUMP_print_imm_hex, OBJDUMP_no_print_imm_hex, false);
+      InputArgs.hasFlag(OBJDUMP_print_imm_hex, OBJDUMP_no_print_imm_hex, true);
   PrivateHeaders = InputArgs.hasArg(OBJDUMP_private_headers);
   FilterSections = InputArgs.getAllArgValues(OBJDUMP_section_EQ);
   SectionHeaders = InputArgs.hasArg(OBJDUMP_section_headers);
+  ShowAllSymbols = InputArgs.hasArg(OBJDUMP_show_all_symbols);
   ShowLMA = InputArgs.hasArg(OBJDUMP_show_lma);
   PrintSource = InputArgs.hasArg(OBJDUMP_source);
   parseIntArg(InputArgs, OBJDUMP_start_address_EQ, StartAddress);
@@ -2869,6 +3118,17 @@
     llvm::cl::ParseCommandLineOptions(2, Argv);
   }
 
+  // Look up any provided build IDs, then append them to the input filenames.
+  for (const opt::Arg *A : InputArgs.filtered(OBJDUMP_build_id)) {
+    object::BuildID BuildID = parseBuildIDArg(A);
+    std::optional<std::string> Path = BIDFetcher->fetch(BuildID);
+    if (!Path) {
+      reportCmdLineError(A->getSpelling() + ": could not find build ID '" +
+                         A->getValue() + "'");
+    }
+    InputFilenames.push_back(std::move(*Path));
+  }
+
   // objdump defaults to a.out if no filenames specified.
   if (InputFilenames.empty())
     InputFilenames.push_back("a.out");
@@ -2936,6 +3196,21 @@
     return 0;
   }
 
+  // Initialize debuginfod.
+  const bool ShouldUseDebuginfodByDefault =
+      InputArgs.hasArg(OBJDUMP_build_id) || canUseDebuginfod();
+  std::vector<std::string> DebugFileDirectories =
+      InputArgs.getAllArgValues(OBJDUMP_debug_file_directory);
+  if (InputArgs.hasFlag(OBJDUMP_debuginfod, OBJDUMP_no_debuginfod,
+                        ShouldUseDebuginfodByDefault)) {
+    HTTPClient::initialize();
+    BIDFetcher =
+        std::make_unique<DebuginfodFetcher>(std::move(DebugFileDirectories));
+  } else {
+    BIDFetcher =
+        std::make_unique<BuildIDFetcher>(std::move(DebugFileDirectories));
+  }
+
   if (Is("otool"))
     parseOtoolOptions(InputArgs);
   else
@@ -2960,11 +3235,12 @@
       !DynamicRelocations && !FileHeaders && !PrivateHeaders && !RawClangAST &&
       !Relocations && !SectionHeaders && !SectionContents && !SymbolTable &&
       !DynamicSymbolTable && !UnwindInfo && !FaultMapSection && !Offloading &&
-      !(MachOOpt && (Bind || DataInCode || DyldInfo || DylibId || DylibsUsed ||
-                     ExportsTrie || FirstPrivateHeader || FunctionStarts ||
-                     IndirectSymbols || InfoPlist || LazyBind || LinkOptHints ||
-                     ObjcMetaData || Rebase || Rpaths || UniversalHeaders ||
-                     WeakBind || !FilterSections.empty()))) {
+      !(MachOOpt &&
+        (Bind || DataInCode || ChainedFixups || DyldInfo || DylibId ||
+         DylibsUsed || ExportsTrie || FirstPrivateHeader ||
+         FunctionStartsType != FunctionStartsMode::None || IndirectSymbols ||
+         InfoPlist || LazyBind || LinkOptHints || ObjcMetaData || Rebase ||
+         Rpaths || UniversalHeaders || WeakBind || !FilterSections.empty()))) {
     T->printHelp(ToolName);
     return 2;
   }
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 c64c042..efb4451 100644
--- a/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/src/llvm-project/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -20,6 +20,10 @@
 class StringRef;
 class Twine;
 
+namespace opt {
+class Arg;
+} // namespace opt
+
 namespace object {
 class RelocationRef;
 struct VersionEntry;
@@ -146,6 +150,8 @@
   reportError(EO.takeError(), std::forward<Ts>(Args)...);
 }
 
+void invalidArgValue(const opt::Arg *A);
+
 std::string getFileNameForError(const object::Archive::Child &C,
                                 unsigned Index);
 SymbolInfoTy createSymbolInfo(const object::ObjectFile &Obj,
diff --git a/src/llvm-project/llvm/tools/llvm-opt-fuzzer/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-opt-fuzzer/CMakeLists.txt
index 0ae3d2e..906de66d 100644
--- a/src/llvm-project/llvm/tools/llvm-opt-fuzzer/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-opt-fuzzer/CMakeLists.txt
@@ -21,6 +21,7 @@
   ScalarOpts
   Support
   Target
+  TargetParser
   TransformUtils
   Vectorize
   Passes
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 74b898b..7e8115c 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
@@ -192,14 +192,11 @@
   PassRegistry &Registry = *PassRegistry::getPassRegistry();
   initializeCore(Registry);
   initializeScalarOpts(Registry);
-  initializeObjCARCOpts(Registry);
   initializeVectorization(Registry);
   initializeIPO(Registry);
   initializeAnalysis(Registry);
   initializeTransformUtils(Registry);
   initializeInstCombine(Registry);
-  initializeAggressiveInstCombine(Registry);
-  initializeInstrumentation(Registry);
   initializeTarget(Registry);
 
   // Parse input options
diff --git a/src/llvm-project/llvm/tools/llvm-opt-report/OptReport.cpp b/src/llvm-project/llvm/tools/llvm-opt-report/OptReport.cpp
index e038863..cc7e60b 100644
--- a/src/llvm-project/llvm/tools/llvm-opt-report/OptReport.cpp
+++ b/src/llvm-project/llvm/tools/llvm-opt-report/OptReport.cpp
@@ -32,6 +32,7 @@
 #include "llvm/Support/raw_ostream.h"
 #include <cstdlib>
 #include <map>
+#include <optional>
 #include <set>
 
 using namespace llvm;
@@ -208,7 +209,7 @@
         Arg.Val.getAsInteger(10, UnrollCount);
     }
 
-    const Optional<remarks::RemarkLocation> &Loc = Remark.Loc;
+    const std::optional<remarks::RemarkLocation> &Loc = Remark.Loc;
     if (!Loc)
       continue;
 
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
index a173eb1..4b60420 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.cpp
@@ -602,7 +602,8 @@
   StatCollection TypeStats;
   LazyRandomTypeCollection &Types =
       opts::dump::DumpTypeStats ? File.types() : File.ids();
-  for (Optional<TypeIndex> TI = Types.getFirst(); TI; TI = Types.getNext(*TI)) {
+  for (std::optional<TypeIndex> TI = Types.getFirst(); TI;
+       TI = Types.getNext(*TI)) {
     CVType Type = Types.getType(*TI);
     TypeStats.update(uint32_t(Type.kind()), Type.length());
   }
@@ -692,7 +693,7 @@
       Kind = kNoneUdtKind;
     else if (UDT.Type.isSimple())
       Kind = kSimpleUdtKind;
-    else if (Optional<CVType> T = TpiTypes.tryGetType(UDT.Type)) {
+    else if (std::optional<CVType> T = TpiTypes.tryGetType(UDT.Type)) {
       Kind = T->kind();
       RecordSize = T->length();
     } else
@@ -1250,7 +1251,7 @@
       if (TI.isSimple()) {
         Printer.formatLine("{0} | {1}", fmt_align(I, AlignStyle::Right, Width),
                            Types.getTypeName(TI));
-      } else if (Optional<CVType> Type = Types.tryGetType(TI)) {
+      } else if (std::optional<CVType> Type = Types.tryGetType(TI)) {
         if (auto EC = codeview::visitTypeRecord(*Type, TI, V))
           Printer.formatLine("An error occurred dumping type record {0}: {1}",
                              TI, toString(std::move(EC)));
@@ -1517,7 +1518,8 @@
   size_t TotalBytes = 0;
   size_t RefBytes = 0;
   auto &Types = File.types();
-  for (Optional<TypeIndex> TI = Types.getFirst(); TI; TI = Types.getNext(*TI)) {
+  for (std::optional<TypeIndex> TI = Types.getFirst(); TI;
+       TI = Types.getNext(*TI)) {
     CVType Type = File.types().getType(*TI);
     TotalBytes += Type.length();
     if (RefTracker->isTypeReferenced(*TI)) {
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.h b/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
index 217d25d..a0c9530 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/DumpOutputStyle.h
@@ -13,7 +13,6 @@
 #include "StreamUtil.h"
 
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
 #include "llvm/DebugInfo/PDB/Native/RawConstants.h"
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp
index 13a5f6e..3e57e31 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.cpp
@@ -124,14 +124,14 @@
   return llvm::is_contained(Layout.DirectoryBlocks, pdbBlockIndex());
 }
 
-Optional<uint32_t> ExplainOutputStyle::getPdbBlockStreamIndex() const {
+std::optional<uint32_t> ExplainOutputStyle::getPdbBlockStreamIndex() const {
   const auto &Layout = File.pdb().getMsfLayout();
   for (const auto &Entry : enumerate(Layout.StreamMap)) {
     if (!llvm::is_contained(Entry.value(), pdbBlockIndex()))
       continue;
     return Entry.index();
   }
-  return None;
+  return std::nullopt;
 }
 
 bool ExplainOutputStyle::explainPdbBlockStatus() {
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h b/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h
index e3d19f2..499f2a8 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/ExplainOutputStyle.h
@@ -43,7 +43,7 @@
   bool isPdbFpmBlock() const;
   bool isPdbBlockMapBlock() const;
   bool isPdbStreamDirectoryBlock() const;
-  Optional<uint32_t> getPdbBlockStreamIndex() const;
+  std::optional<uint32_t> getPdbBlockStreamIndex() const;
 
   void explainPdbSuperBlockOffset();
   void explainPdbFpmBlockOffset();
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/PdbYaml.h b/src/llvm-project/llvm/tools/llvm-pdbutil/PdbYaml.h
index c335eef..4382e91 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/PdbYaml.h
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/PdbYaml.h
@@ -11,7 +11,6 @@
 
 #include "OutputStyle.h"
 
-#include "llvm/ADT/Optional.h"
 #include "llvm/DebugInfo/CodeView/SymbolRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeRecord.h"
 #include "llvm/DebugInfo/MSF/MSFCommon.h"
@@ -24,6 +23,7 @@
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/YAMLTraits.h"
 
+#include <optional>
 #include <vector>
 
 namespace llvm {
@@ -67,7 +67,7 @@
   StringRef Mod;
   std::vector<StringRef> SourceFiles;
   std::vector<CodeViewYAML::YAMLDebugSubsection> Subsections;
-  Optional<PdbModiStream> Modi;
+  std::optional<PdbModiStream> Modi;
 };
 
 struct PdbDbiStream {
@@ -94,16 +94,16 @@
 struct PdbObject {
   explicit PdbObject(BumpPtrAllocator &Allocator) : Allocator(Allocator) {}
 
-  Optional<MSFHeaders> Headers;
-  Optional<std::vector<uint32_t>> StreamSizes;
-  Optional<std::vector<StreamBlockList>> StreamMap;
-  Optional<PdbInfoStream> PdbStream;
-  Optional<PdbDbiStream> DbiStream;
-  Optional<PdbTpiStream> TpiStream;
-  Optional<PdbTpiStream> IpiStream;
-  Optional<PdbPublicsStream> PublicsStream;
+  std::optional<MSFHeaders> Headers;
+  std::optional<std::vector<uint32_t>> StreamSizes;
+  std::optional<std::vector<StreamBlockList>> StreamMap;
+  std::optional<PdbInfoStream> PdbStream;
+  std::optional<PdbDbiStream> DbiStream;
+  std::optional<PdbTpiStream> TpiStream;
+  std::optional<PdbTpiStream> IpiStream;
+  std::optional<PdbPublicsStream> PublicsStream;
 
-  Optional<std::vector<StringRef>> StringTable;
+  std::optional<std::vector<StringRef>> StringTable;
 
   BumpPtrAllocator &Allocator;
 };
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp
index 2285ed1..06792f9 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassDefinitionDumper.cpp
@@ -66,7 +66,7 @@
   if (BaseCount > 0) {
     Printer.Indent();
     char NextSeparator = ':';
-    for (auto BC : Layout.bases()) {
+    for (auto *BC : Layout.bases()) {
       const auto &Base = BC->getBase();
       if (Base.isIndirectVirtualBaseClass())
         continue;
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
index 1ade7f3..c420283 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/PrettyClassLayoutGraphicalDumper.cpp
@@ -36,16 +36,16 @@
 
   if (RecursionLevel == 1 &&
       opts::pretty::ClassFormat == opts::pretty::ClassDefinitionFormat::All) {
-    for (auto &Other : Layout.other_items())
+    for (const auto &Other : Layout.other_items())
       Other->dump(*this);
-    for (auto &Func : Layout.funcs())
+    for (const auto &Func : Layout.funcs())
       Func->dump(*this);
   }
 
   const BitVector &UseMap = Layout.usedBytes();
   int NextPaddingByte = UseMap.find_first_unset();
 
-  for (auto &Item : Layout.layout_items()) {
+  for (const auto &Item : Layout.layout_items()) {
     // Calculate the absolute offset of the first byte of the next field.
     uint32_t RelativeOffset = Item->getOffsetInParent();
     CurrentAbsoluteOffset = ClassOffsetZero + RelativeOffset;
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/StreamUtil.h b/src/llvm-project/llvm/tools/llvm-pdbutil/StreamUtil.h
index f810f7d..9d6030c 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/StreamUtil.h
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/StreamUtil.h
@@ -9,11 +9,11 @@
 #ifndef LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H
 #define LLVM_TOOLS_LLVMPDBDUMP_STREAMUTIL_H
 
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 
 #include <string>
+#include <optional>
 
 namespace llvm {
 namespace pdb {
@@ -52,7 +52,7 @@
   StreamPurpose Purpose;
   uint32_t StreamIndex;
   std::string Name;
-  Optional<uint32_t> ModuleIndex;
+  std::optional<uint32_t> ModuleIndex;
 };
 
 void discoverStreamPurposes(PDBFile &File,
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.cpp b/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.cpp
index d813bc2..5ae720a 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.cpp
@@ -24,7 +24,8 @@
 // just iterate up front to find out.
 static uint32_t getNumRecordsInCollection(LazyRandomTypeCollection &Types) {
   uint32_t NumTypes = 0;
-  for (Optional<TypeIndex> TI = Types.getFirst(); TI; TI = Types.getNext(*TI))
+  for (std::optional<TypeIndex> TI = Types.getFirst(); TI;
+       TI = Types.getNext(*TI))
     ++NumTypes;
   return NumTypes;
 }
@@ -129,9 +130,9 @@
     TiRefKind RefKind;
     TypeIndex RefTI;
     std::tie(RefKind, RefTI) = RefWorklist.pop_back_val();
-    Optional<CVType> Rec = (Ids && RefKind == TiRefKind::IndexRef)
-                               ? Ids->tryGetType(RefTI)
-                               : Types.tryGetType(RefTI);
+    std::optional<CVType> Rec = (Ids && RefKind == TiRefKind::IndexRef)
+                                    ? Ids->tryGetType(RefTI)
+                                    : Types.tryGetType(RefTI);
     if (!Rec)
       continue; // FIXME: Report a reference to a non-existant type.
 
diff --git a/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.h b/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.h
index c586f65..8262129 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.h
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/TypeReferenceTracker.h
@@ -10,7 +10,6 @@
 #define LLVM_TOOLS_LLVMPDBDUMP_TYPEREFERENCETRACKER_H
 
 #include "llvm/ADT/BitVector.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/DebugInfo/CodeView/CVRecord.h"
 #include "llvm/DebugInfo/CodeView/TypeIndex.h"
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 3859558..61cad15 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.cpp
@@ -377,8 +377,8 @@
 cl::OptionCategory Types("Type Options");
 cl::OptionCategory ModuleCategory("Module Options");
 
-llvm::Optional<NumberRange> DumpBlockRange;
-llvm::Optional<NumberRange> DumpByteRange;
+std::optional<NumberRange> DumpBlockRange;
+std::optional<NumberRange> DumpByteRange;
 
 cl::opt<std::string> DumpBlockRangeOpt(
     "block-range", cl::value_desc("start[-end]"),
@@ -865,7 +865,7 @@
   AppendingTypeTableBuilder TS(Allocator);
   for (const auto &R : Tpi.Records) {
     CVType Type = R.toCodeViewRecord(TS);
-    TpiBuilder.addTypeRecord(Type.RecordData, None);
+    TpiBuilder.addTypeRecord(Type.RecordData, std::nullopt);
   }
 
   const auto &Ipi = YamlObj.IpiStream.value_or(DefaultIpiStream);
@@ -873,7 +873,7 @@
   IpiBuilder.setVersionHeader(Ipi.Version);
   for (const auto &R : Ipi.Records) {
     CVType Type = R.toCodeViewRecord(TS);
-    IpiBuilder.addTypeRecord(Type.RecordData, None);
+    IpiBuilder.addTypeRecord(Type.RecordData, std::nullopt);
   }
 
   Builder.getStringTableBuilder().setStrings(*Strings.strings());
@@ -1353,10 +1353,10 @@
   auto &DestTpi = Builder.getTpiBuilder();
   auto &DestIpi = Builder.getIpiBuilder();
   MergedTpi.ForEachRecord([&DestTpi](TypeIndex TI, const CVType &Type) {
-    DestTpi.addTypeRecord(Type.RecordData, None);
+    DestTpi.addTypeRecord(Type.RecordData, std::nullopt);
   });
   MergedIpi.ForEachRecord([&DestIpi](TypeIndex TI, const CVType &Type) {
-    DestIpi.addTypeRecord(Type.RecordData, None);
+    DestIpi.addTypeRecord(Type.RecordData, std::nullopt);
   });
   Builder.getInfoBuilder().addFeature(PdbRaw_FeatureSig::VC140);
 
@@ -1422,7 +1422,7 @@
 }
 
 static bool parseRange(StringRef Str,
-                       Optional<opts::bytes::NumberRange> &Parsed) {
+                       std::optional<opts::bytes::NumberRange> &Parsed) {
   if (Str.empty())
     return true;
 
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 455fe5f..8766d70 100644
--- a/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
+++ b/src/llvm-project/llvm/tools/llvm-pdbutil/llvm-pdbutil.h
@@ -10,7 +10,6 @@
 #define LLVM_TOOLS_LLVMPDBDUMP_LLVMPDBDUMP_H
 
 #include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/PointerUnion.h"
 #include "llvm/DebugInfo/PDB/Native/LinePrinter.h"
 #include "llvm/Support/CommandLine.h"
@@ -111,11 +110,11 @@
 namespace bytes {
 struct NumberRange {
   uint64_t Min;
-  llvm::Optional<uint64_t> Max;
+  std::optional<uint64_t> Max;
 };
 
-extern llvm::Optional<NumberRange> DumpBlockRange;
-extern llvm::Optional<NumberRange> DumpByteRange;
+extern std::optional<NumberRange> DumpBlockRange;
+extern std::optional<NumberRange> DumpByteRange;
 extern llvm::cl::list<std::string> DumpStreamData;
 extern llvm::cl::opt<bool> NameMap;
 extern llvm::cl::opt<bool> Fpm;
diff --git a/src/llvm-project/llvm/tools/llvm-profdata/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-profdata/CMakeLists.txt
index 3545bde..0cf36d1 100644
--- a/src/llvm-project/llvm/tools/llvm-profdata/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-profdata/CMakeLists.txt
@@ -11,4 +11,5 @@
 
   DEPENDS
   intrinsics_gen
+  GENERATE_DRIVER
   )
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 3af8f80..c8e5e6d 100644
--- a/src/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -13,7 +13,6 @@
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/Object/Binary.h"
 #include "llvm/ProfileData/InstrProfCorrelator.h"
@@ -31,6 +30,7 @@
 #include "llvm/Support/Format.h"
 #include "llvm/Support/FormattedStream.h"
 #include "llvm/Support/InitLLVM.h"
+#include "llvm/Support/MD5.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/ThreadPool.h"
@@ -38,10 +38,16 @@
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
 #include <algorithm>
+#include <cmath>
+#include <optional>
 #include <queue>
 
 using namespace llvm;
 
+// We use this string to indicate that there are
+// multiple static functions map to the same name.
+const std::string DuplicateNameStr = "----";
+
 enum ProfileFormat {
   PF_None = 0,
   PF_Text,
@@ -51,6 +57,8 @@
   PF_Binary
 };
 
+enum class ShowFormat { Text, Json, Yaml };
+
 static void warn(Twine Message, std::string Whence = "",
                  std::string Hint = "") {
   WithColor::warning();
@@ -329,9 +337,16 @@
                              FuncName, firstTime);
     });
   }
-  if (Reader->hasError())
+
+  if (Reader->hasError()) {
     if (Error E = Reader->getError())
       WC->Errors.emplace_back(std::move(E), Filename);
+  }
+
+  std::vector<llvm::object::BuildID> BinaryIds;
+  if (Error E = Reader->readBinaryIds(BinaryIds))
+    WC->Errors.emplace_back(std::move(E), Filename);
+  WC->Writer.addBinaryIds(BinaryIds);
 }
 
 /// Merge the \p Src writer context into \p Dst.
@@ -340,6 +355,9 @@
     Dst->Errors.push_back(std::move(ErrorPair));
   Src->Errors.clear();
 
+  if (Error E = Dst->Writer.mergeProfileKind(Src->Writer.getProfileKind()))
+    exitWithError(std::move(E));
+
   Dst->Writer.mergeRecordsFromWriter(std::move(Src->Writer), [&](Error E) {
     instrprof_error IPE = InstrProfError::take(std::move(E));
     std::unique_lock<std::mutex> ErrGuard{Dst->ErrLock};
@@ -397,9 +415,6 @@
   if (NumThreads == 0)
     NumThreads = std::min(hardware_concurrency().compute_thread_count(),
                           unsigned((Inputs.size() + 1) / 2));
-  // FIXME: There's a bug here, where setting NumThreads = Inputs.size() fails
-  // the merge_empty_profile.test because the InstrProfWriter.ProfileKind isn't
-  // merged, thus the emitted file ends up with a PF_Unknown kind.
 
   // Initialize the writer contexts.
   SmallVector<std::unique_ptr<WriterContext>, 4> Contexts;
@@ -461,6 +476,7 @@
 /// The profile entry for a function in instrumentation profile.
 struct InstrProfileEntry {
   uint64_t MaxCount = 0;
+  uint64_t NumEdgeCounters = 0;
   float ZeroCounterRatio = 0.0;
   InstrProfRecord *ProfRecord;
   InstrProfileEntry(InstrProfRecord *Record);
@@ -476,33 +492,49 @@
     ZeroCntNum += !Record->Counts[I];
   }
   ZeroCounterRatio = (float)ZeroCntNum / CntNum;
+  NumEdgeCounters = CntNum;
 }
 
-/// Either set all the counters in the instr profile entry \p IFE to -1
-/// in order to drop the profile or scale up the counters in \p IFP to
-/// be above hot threshold. We use the ratio of zero counters in the
-/// profile of a function to decide the profile is helpful or harmful
-/// for performance, and to choose whether to scale up or drop it.
-static void updateInstrProfileEntry(InstrProfileEntry &IFE,
+/// Either set all the counters in the instr profile entry \p IFE to
+/// -1 / -2 /in order to drop the profile or scale up the
+/// counters in \p IFP to be above hot / cold threshold. We use
+/// the ratio of zero counters in the profile of a function to
+/// decide the profile is helpful or harmful for performance,
+/// and to choose whether to scale up or drop it.
+static void updateInstrProfileEntry(InstrProfileEntry &IFE, bool SetToHot,
                                     uint64_t HotInstrThreshold,
+                                    uint64_t ColdInstrThreshold,
                                     float ZeroCounterThreshold) {
   InstrProfRecord *ProfRecord = IFE.ProfRecord;
   if (!IFE.MaxCount || IFE.ZeroCounterRatio > ZeroCounterThreshold) {
     // If all or most of the counters of the function are zero, the
-    // profile is unaccountable and shuld be dropped. Reset all the
-    // counters to be -1 and PGO profile-use will drop the profile.
+    // profile is unaccountable and should be dropped. Reset all the
+    // counters to be -1 / -2 and PGO profile-use will drop the profile.
     // All counters being -1 also implies that the function is hot so
     // PGO profile-use will also set the entry count metadata to be
     // above hot threshold.
-    for (size_t I = 0; I < ProfRecord->Counts.size(); ++I)
-      ProfRecord->Counts[I] = -1;
+    // All counters being -2 implies that the function is warm so
+    // PGO profile-use will also set the entry count metadata to be
+    // above cold threshold.
+    auto Kind =
+        (SetToHot ? InstrProfRecord::PseudoHot : InstrProfRecord::PseudoWarm);
+    ProfRecord->setPseudoCount(Kind);
     return;
   }
 
-  // Scale up the MaxCount to be multiple times above hot threshold.
+  // Scale up the MaxCount to be multiple times above hot / cold threshold.
   const unsigned MultiplyFactor = 3;
-  uint64_t Numerator = HotInstrThreshold * MultiplyFactor;
+  uint64_t Threshold = (SetToHot ? HotInstrThreshold : ColdInstrThreshold);
+  uint64_t Numerator = Threshold * MultiplyFactor;
+
+  // Make sure Threshold for warm counters is below the HotInstrThreshold.
+  if (!SetToHot && Threshold >= HotInstrThreshold) {
+    Threshold = (HotInstrThreshold + ColdInstrThreshold) / 2;
+  }
+
   uint64_t Denominator = IFE.MaxCount;
+  if (Numerator <= Denominator)
+    return;
   ProfRecord->scale(Numerator, Denominator, [&](instrprof_error E) {
     warn(toString(make_error<InstrProfError>(E)));
   });
@@ -539,7 +571,167 @@
                    unsigned InstrProfColdThreshold) {
   // Function to its entry in instr profile.
   StringMap<InstrProfileEntry> InstrProfileMap;
+  StringMap<StringRef> StaticFuncMap;
   InstrProfSummaryBuilder IPBuilder(ProfileSummaryBuilder::DefaultCutoffs);
+
+  auto checkSampleProfileHasFUnique = [&Reader]() {
+    for (const auto &PD : Reader->getProfiles()) {
+      auto &FContext = PD.first;
+      if (FContext.toString().find(FunctionSamples::UniqSuffix) !=
+          std::string::npos) {
+        return true;
+      }
+    }
+    return false;
+  };
+
+  bool SampleProfileHasFUnique = checkSampleProfileHasFUnique();
+
+  auto buildStaticFuncMap = [&StaticFuncMap,
+                             SampleProfileHasFUnique](const StringRef Name) {
+    std::string Prefixes[] = {".cpp:", "cc:", ".c:", ".hpp:", ".h:"};
+    size_t PrefixPos = StringRef::npos;
+    for (auto &Prefix : Prefixes) {
+      PrefixPos = Name.find_insensitive(Prefix);
+      if (PrefixPos == StringRef::npos)
+        continue;
+      PrefixPos += Prefix.size();
+      break;
+    }
+
+    if (PrefixPos == StringRef::npos) {
+      return;
+    }
+
+    StringRef NewName = Name.drop_front(PrefixPos);
+    StringRef FName = Name.substr(0, PrefixPos - 1);
+    if (NewName.size() == 0) {
+      return;
+    }
+
+    // This name should have a static linkage.
+    size_t PostfixPos = NewName.find(FunctionSamples::UniqSuffix);
+    bool ProfileHasFUnique = (PostfixPos != StringRef::npos);
+
+    // If sample profile and instrumented profile do not agree on symbol
+    // uniqification.
+    if (SampleProfileHasFUnique != ProfileHasFUnique) {
+      // If instrumented profile uses -funique-internal-linakge-symbols,
+      // we need to trim the name.
+      if (ProfileHasFUnique) {
+        NewName = NewName.substr(0, PostfixPos);
+      } else {
+        // If sample profile uses -funique-internal-linakge-symbols,
+        // we build the map.
+        std::string NStr =
+            NewName.str() + getUniqueInternalLinkagePostfix(FName);
+        NewName = StringRef(NStr);
+        StaticFuncMap[NewName] = Name;
+        return;
+      }
+    }
+
+    if (StaticFuncMap.find(NewName) == StaticFuncMap.end()) {
+      StaticFuncMap[NewName] = Name;
+    } else {
+      StaticFuncMap[NewName] = DuplicateNameStr;
+    }
+  };
+
+  // We need to flatten the SampleFDO profile as the InstrFDO
+  // profile does not have inlined callsite profiles.
+  // One caveat is the pre-inlined function -- their samples
+  // should be collapsed into the caller function.
+  // Here we do a DFS traversal to get the flatten profile
+  // info: the sum of entrycount and the max of maxcount.
+  // Here is the algorithm:
+  //   recursive (FS, root_name) {
+  //      name = FS->getName();
+  //      get samples for FS;
+  //      if (InstrProf.find(name) {
+  //        root_name = name;
+  //      } else {
+  //        if (name is in static_func map) {
+  //          root_name = static_name;
+  //        }
+  //      }
+  //      update the Map entry for root_name;
+  //      for (subfs: FS) {
+  //        recursive(subfs, root_name);
+  //      }
+  //   }
+  //
+  // Here is an example.
+  //
+  // SampleProfile:
+  // foo:12345:1000
+  // 1: 1000
+  // 2.1: 1000
+  // 15: 5000
+  // 4: bar:1000
+  //  1: 1000
+  //  2: goo:3000
+  //   1: 3000
+  // 8: bar:40000
+  //  1: 10000
+  //  2: goo:30000
+  //   1: 30000
+  //
+  // InstrProfile has two entries:
+  //  foo
+  //  bar.cc:bar
+  //
+  // After BuildMaxSampleMap, we should have the following in FlattenSampleMap:
+  // {"foo", {1000, 5000}}
+  // {"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
+  // 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
+  // entry in InstrProfile.
+  DenseMap<StringRef, 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();
+      const StringRef *NewRootName = &RootName;
+      uint64_t EntrySample = FS.getHeadSamplesEstimate();
+      uint64_t MaxBodySample = FS.getMaxCountInside(/* SkipCallSite*/ true);
+
+      auto It = InstrProfileMap.find(Name);
+      if (It != InstrProfileMap.end()) {
+        NewRootName = &Name;
+      } else {
+        auto NewName = StaticFuncMap.find(Name);
+        if (NewName != StaticFuncMap.end()) {
+          It = InstrProfileMap.find(NewName->second.str());
+          if (NewName->second != DuplicateNameStr) {
+            NewRootName = &NewName->second;
+          }
+        } else {
+          // Here the EntrySample is of an inlined function, so we should not
+          // update the EntrySample in the map.
+          EntrySample = 0;
+        }
+      }
+      EntrySample += FlattenSampleMap[*NewRootName].first;
+      MaxBodySample =
+          std::max(FlattenSampleMap[*NewRootName].second, MaxBodySample);
+      FlattenSampleMap[*NewRootName] =
+          std::make_pair(EntrySample, MaxBodySample);
+
+      for (const auto &C : FS.getCallsiteSamples())
+        for (const auto &F : C.second)
+          BuildImpl(F.second, *NewRootName, BuildImpl);
+    };
+    BuildMaxSampleMapImpl(FS, RootName, BuildMaxSampleMapImpl);
+  };
+
   for (auto &PD : WC->Writer.getProfileData()) {
     // Populate IPBuilder.
     for (const auto &PDV : PD.getValue()) {
@@ -553,13 +745,25 @@
 
     // Initialize InstrProfileMap.
     InstrProfRecord *R = &PD.getValue().begin()->second;
-    InstrProfileMap[PD.getKey()] = InstrProfileEntry(R);
+    StringRef FullName = PD.getKey();
+    InstrProfileMap[FullName] = InstrProfileEntry(R);
+    buildStaticFuncMap(FullName);
+  }
+
+  for (auto &PD : Reader->getProfiles()) {
+    sampleprof::FunctionSamples &FS = PD.second;
+    BuildMaxSampleMap(FS, FS.getName());
   }
 
   ProfileSummary InstrPS = *IPBuilder.getSummary();
   ProfileSummary SamplePS = Reader->getSummary();
 
   // Compute cold thresholds for instr profile and sample profile.
+  uint64_t HotSampleThreshold =
+      ProfileSummaryBuilder::getEntryForPercentile(
+          SamplePS.getDetailedSummary(),
+          ProfileSummaryBuilder::DefaultCutoffs[HotPercentileIdx])
+          .MinCount;
   uint64_t ColdSampleThreshold =
       ProfileSummaryBuilder::getEntryForPercentile(
           SamplePS.getDetailedSummary(),
@@ -580,17 +784,30 @@
 
   // Find hot/warm functions in sample profile which is cold in instr profile
   // and adjust the profiles of those functions in the instr profile.
-  for (const auto &PD : Reader->getProfiles()) {
-    auto &FContext = PD.first;
-    const sampleprof::FunctionSamples &FS = PD.second;
-    auto It = InstrProfileMap.find(FContext.toString());
-    if (FS.getHeadSamples() > ColdSampleThreshold &&
-        It != InstrProfileMap.end() &&
-        It->second.MaxCount <= ColdInstrThreshold &&
-        FS.getBodySamples().size() >= SupplMinSizeThreshold) {
-      updateInstrProfileEntry(It->second, HotInstrThreshold,
-                              ZeroCounterThreshold);
+  for (const auto &E : FlattenSampleMap) {
+    uint64_t SampleMaxCount = std::max(E.second.first, E.second.second);
+    if (SampleMaxCount < ColdSampleThreshold)
+      continue;
+    const StringRef &Name = E.first;
+    auto It = InstrProfileMap.find(Name);
+    if (It == InstrProfileMap.end()) {
+      auto NewName = StaticFuncMap.find(Name);
+      if (NewName != StaticFuncMap.end()) {
+        It = InstrProfileMap.find(NewName->second.str());
+        if (NewName->second == DuplicateNameStr) {
+          WithColor::warning()
+              << "Static function " << Name
+              << " has multiple promoted names, cannot adjust profile.\n";
+        }
+      }
     }
+    if (It == InstrProfileMap.end() ||
+        It->second.MaxCount > ColdInstrThreshold ||
+        It->second.NumEdgeCounters < SupplMinSizeThreshold)
+      continue;
+    bool SetToHot = SampleMaxCount >= HotSampleThreshold;
+    updateInstrProfileEntry(It->second, SetToHot, HotInstrThreshold,
+                            ColdInstrThreshold, ZeroCounterThreshold);
   }
 }
 
@@ -748,14 +965,15 @@
                    StringRef ProfileSymbolListFile, bool CompressAllSections,
                    bool UseMD5, bool GenPartialProfile, bool GenCSNestedProfile,
                    bool SampleMergeColdContext, bool SampleTrimColdContext,
-                   bool SampleColdContextFrameDepth, FailureMode FailMode) {
+                   bool SampleColdContextFrameDepth, FailureMode FailMode,
+                   bool DropProfileSymbolList) {
   using namespace sampleprof;
   SampleProfileMap ProfileMap;
   SmallVector<std::unique_ptr<sampleprof::SampleProfileReader>, 5> Readers;
   LLVMContext Context;
   sampleprof::ProfileSymbolList WriterList;
-  Optional<bool> ProfileIsProbeBased;
-  Optional<bool> ProfileIsCS;
+  std::optional<bool> ProfileIsProbeBased;
+  std::optional<bool> ProfileIsCS;
   for (const auto &Input : Inputs) {
     auto ReaderOrErr = SampleProfileReader::create(Input.Filename, Context,
                                                    FSDiscriminatorPassOption);
@@ -801,10 +1019,12 @@
       }
     }
 
-    std::unique_ptr<sampleprof::ProfileSymbolList> ReaderList =
-        Reader->getProfileSymbolList();
-    if (ReaderList)
-      WriterList.merge(*ReaderList);
+    if (!DropProfileSymbolList) {
+      std::unique_ptr<sampleprof::ProfileSymbolList> ReaderList =
+          Reader->getProfileSymbolList();
+      if (ReaderList)
+        WriterList.merge(*ReaderList);
+    }
   }
 
   if (ProfileIsCS && (SampleMergeColdContext || SampleTrimColdContext)) {
@@ -1016,6 +1236,10 @@
   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)"));
 
   cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
 
@@ -1060,11 +1284,11 @@
                       OutputFilename, OutputFormat, OutputSparse, NumThreads,
                       FailureMode, ProfiledBinary);
   else
-    mergeSampleProfile(WeightedInputs, Remapper.get(), OutputFilename,
-                       OutputFormat, ProfileSymbolListFile, CompressAllSections,
-                       UseMD5, GenPartialProfile, GenCSNestedProfile,
-                       SampleMergeColdContext, SampleTrimColdContext,
-                       SampleColdContextFrameDepth, FailureMode);
+    mergeSampleProfile(
+        WeightedInputs, Remapper.get(), OutputFilename, OutputFormat,
+        ProfileSymbolListFile, CompressAllSections, UseMD5, GenPartialProfile,
+        GenCSNestedProfile, SampleMergeColdContext, SampleTrimColdContext,
+        SampleColdContextFrameDepth, FailureMode, DropProfileSymbolList);
   return 0;
 }
 
@@ -2142,7 +2366,12 @@
                             uint64_t ValueCutoff, bool OnlyListBelow,
                             const std::string &ShowFunction, bool TextFormat,
                             bool ShowBinaryIds, bool ShowCovered,
+                            bool ShowProfileVersion, ShowFormat SFormat,
                             raw_fd_ostream &OS) {
+  if (SFormat == ShowFormat::Json)
+    exitWithError("JSON output is not supported for instr profiles");
+  if (SFormat == ShowFormat::Yaml)
+    exitWithError("YAML output is not supported for instr profiles");
   auto ReaderOrErr = InstrProfReader::create(Filename);
   std::vector<uint32_t> Cutoffs = std::move(DetailedSummaryCutoffs);
   if (ShowDetailedSummary && Cutoffs.empty()) {
@@ -2207,9 +2436,27 @@
 
     uint64_t FuncMax = 0;
     uint64_t FuncSum = 0;
+
+    auto PseudoKind = Func.getCountPseudoKind();
+    if (PseudoKind != InstrProfRecord::NotPseudo) {
+      if (Show) {
+        if (!ShownFunctions)
+          OS << "Counters:\n";
+        ++ShownFunctions;
+        OS << "  " << Func.Name << ":\n"
+           << "    Hash: " << format("0x%016" PRIx64, Func.Hash) << "\n"
+           << "    Counters: " << Func.Counts.size();
+        if (PseudoKind == InstrProfRecord::PseudoHot)
+          OS << "    <PseudoHot>\n";
+        else if (PseudoKind == InstrProfRecord::PseudoWarm)
+          OS << "    <PseudoWarm>\n";
+        else
+          llvm_unreachable("Unknown PseudoKind");
+      }
+      continue;
+    }
+
     for (size_t I = 0, E = Func.Counts.size(); I < E; ++I) {
-      if (Func.Counts[I] == (uint64_t)-1)
-        continue;
       FuncMax = std::max(FuncMax, Func.Counts[I]);
       FuncSum += Func.Counts[I];
     }
@@ -2334,6 +2581,8 @@
     if (Error E = Reader->printBinaryIds(OS))
       exitWithError(std::move(E), Filename);
 
+  if (ShowProfileVersion)
+    OS << "Profile version: " << Reader->getVersion() << "\n";
   return 0;
 }
 
@@ -2488,7 +2737,9 @@
                              const std::string &ShowFunction,
                              bool ShowProfileSymbolList,
                              bool ShowSectionInfoOnly, bool ShowHotFuncList,
-                             raw_fd_ostream &OS) {
+                             ShowFormat SFormat, raw_fd_ostream &OS) {
+  if (SFormat == ShowFormat::Yaml)
+    exitWithError("YAML output is not supported for sample profiles");
   using namespace sampleprof;
   LLVMContext Context;
   auto ReaderOrErr =
@@ -2505,11 +2756,20 @@
   if (std::error_code EC = Reader->read())
     exitWithErrorCode(EC, Filename);
 
-  if (ShowAllFunctions || ShowFunction.empty())
-    Reader->dump(OS);
-  else
+  if (ShowAllFunctions || ShowFunction.empty()) {
+    if (SFormat == ShowFormat::Json)
+      Reader->dumpJson(OS);
+    else
+      Reader->dump(OS);
+  } else {
+    if (SFormat == ShowFormat::Json)
+      exitWithError(
+          "the JSON format is supported only when all functions are to "
+          "be printed");
+
     // TODO: parse context string to support filtering by contexts.
     Reader->dumpFunctionProfile(StringRef(ShowFunction), OS);
+  }
 
   if (ShowProfileSymbolList) {
     std::unique_ptr<sampleprof::ProfileSymbolList> ReaderList =
@@ -2531,7 +2791,9 @@
 
 static int showMemProfProfile(const std::string &Filename,
                               const std::string &ProfiledBinary,
-                              raw_fd_ostream &OS) {
+                              ShowFormat SFormat, raw_fd_ostream &OS) {
+  if (SFormat == ShowFormat::Json)
+    exitWithError("JSON output is not supported for MemProf");
   auto ReaderOr = llvm::memprof::RawMemProfReader::create(
       Filename, ProfiledBinary, /*KeepNames=*/true);
   if (Error E = ReaderOr.takeError())
@@ -2550,10 +2812,18 @@
 static int showDebugInfoCorrelation(const std::string &Filename,
                                     bool ShowDetailedSummary,
                                     bool ShowProfileSymbolList,
-                                    raw_fd_ostream &OS) {
+                                    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))
     exitWithError(std::move(Err), Filename);
+  if (SFormat == ShowFormat::Yaml) {
+    if (auto Err = Correlator->dumpYaml(OS))
+      exitWithError(std::move(Err), Filename);
+    return 0;
+  }
+
   if (auto Err = Correlator->correlateProfileData())
     exitWithError(std::move(Err), Filename);
 
@@ -2579,9 +2849,20 @@
 
   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"));
@@ -2646,7 +2927,8 @@
   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())
@@ -2659,6 +2941,8 @@
            << ": Input file name cannot be the same as the output file name!\n";
     return 1;
   }
+  if (JsonFormat)
+    SFormat = ShowFormat::Json;
 
   std::error_code EC;
   raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::OF_TextWithCRLF);
@@ -2670,23 +2954,25 @@
 
   if (!DebugInfoFilename.empty())
     return showDebugInfoCorrelation(DebugInfoFilename, ShowDetailedSummary,
-                                    ShowProfileSymbolList, OS);
+                                    ShowProfileSymbolList, SFormat, OS);
 
   if (ProfileKind == instr)
     return showInstrProfile(
         Filename, ShowCounts, TopNFunctions, ShowIndirectCallTargets,
         ShowMemOPSizes, ShowDetailedSummary, DetailedSummaryCutoffs,
         ShowAllFunctions, ShowCS, ValueCutoff, OnlyListBelow, ShowFunction,
-        TextFormat, ShowBinaryIds, ShowCovered, OS);
+        TextFormat, ShowBinaryIds, ShowCovered, ShowProfileVersion, SFormat,
+        OS);
   if (ProfileKind == sample)
     return showSampleProfile(Filename, ShowCounts, TopNFunctions,
                              ShowAllFunctions, ShowDetailedSummary,
                              ShowFunction, ShowProfileSymbolList,
-                             ShowSectionInfoOnly, ShowHotFuncList, OS);
-  return showMemProfProfile(Filename, ProfiledBinary, OS);
+                             ShowSectionInfoOnly, ShowHotFuncList, SFormat, OS);
+  return showMemProfProfile(Filename, ProfiledBinary, SFormat, OS);
 }
 
-int main(int argc, const char *argv[]) {
+int llvm_profdata_main(int argc, char **argvNonConst) {
+  const char **argv = const_cast<const char **>(argvNonConst);
   InitLLVM X(argc, argv);
 
   StringRef ProgName(sys::path::filename(argv[0]));
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-profgen/CMakeLists.txt
index b3e05a9..354c63f 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-profgen/CMakeLists.txt
@@ -12,6 +12,7 @@
   ProfileData
   Support
   Symbolize
+  TargetParser
   )
 
 add_llvm_tool(llvm-profgen
@@ -20,4 +21,5 @@
   CSPreInliner.cpp
   ProfiledBinary.cpp
   ProfileGenerator.cpp
+  MissingFrameInferrer.cpp
   )
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/MissingFrameInferrer.cpp b/src/llvm-project/llvm/tools/llvm-profgen/MissingFrameInferrer.cpp
new file mode 100644
index 0000000..4127fdc
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-profgen/MissingFrameInferrer.cpp
@@ -0,0 +1,318 @@
+//===-- MissingFrameInferrer.cpp - Missing frame inferrer --------- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "MissingFrameInferrer.h"
+#include "PerfReader.h"
+#include "ProfiledBinary.h"
+#include "llvm/ADT/SCCIterator.h"
+#include "llvm/ADT/Statistic.h"
+#include <algorithm>
+#include <cstdint>
+#include <iterator>
+#include <queue>
+#include <sys/types.h>
+
+#define DEBUG_TYPE "missing-frame-inferrer"
+
+using namespace llvm;
+using namespace sampleprof;
+
+STATISTIC(TailCallUniReachable,
+          "Number of frame pairs reachable via a unique tail call path");
+STATISTIC(TailCallMultiReachable,
+          "Number of frame pairs reachable via a multiple tail call paths");
+STATISTIC(TailCallUnreachable,
+          "Number of frame pairs unreachable via any tail call path");
+STATISTIC(TailCallFuncSingleTailCalls,
+          "Number of functions with single tail call site");
+STATISTIC(TailCallFuncMultipleTailCalls,
+          "Number of functions with multiple tail call sites");
+STATISTIC(TailCallMaxTailCallPath, "Length of the longest tail call path");
+
+static cl::opt<uint32_t>
+    MaximumSearchDepth("max-search-depth", cl::init(UINT32_MAX - 1),
+                       cl::desc("The maximum levels the DFS-based missing "
+                                "frame search should go with"));
+
+void MissingFrameInferrer::initialize(
+    const ContextSampleCounterMap *SampleCounters) {
+  // Refine call edges based on LBR samples.
+  if (SampleCounters) {
+    std::unordered_map<uint64_t, std::unordered_set<uint64_t>> SampledCalls;
+    std::unordered_map<uint64_t, std::unordered_set<uint64_t>> SampledTailCalls;
+
+    // Populate SampledCalls based on static call sites. Similarly to
+    // SampledTailCalls.
+    for (const auto &CI : *SampleCounters) {
+      for (auto Item : CI.second.BranchCounter) {
+        auto From = Item.first.first;
+        auto To = Item.first.second;
+        if (CallEdges.count(From)) {
+          assert(CallEdges[From].size() == 1 &&
+                 "A callsite should only appear once with either a known or a "
+                 "zero (unknown) target value at this point");
+          SampledCalls[From].insert(To);
+        }
+        if (TailCallEdges.count(From)) {
+          assert(TailCallEdges[From].size() == 1 &&
+                 "A callsite should only appear once with either a known or a "
+                 "zero (unknown) target value at this point");
+          FuncRange *FromFRange = Binary->findFuncRange(From);
+          FuncRange *ToFRange = Binary->findFuncRange(To);
+          if (FromFRange != ToFRange)
+            SampledTailCalls[From].insert(To);
+        }
+      }
+    }
+
+    // Replace static edges with dynamic edges.
+    CallEdges = SampledCalls;
+    TailCallEdges = SampledTailCalls;
+  }
+
+  // Populate function-based edges. This is to speed up address to function
+  // translation.
+  for (auto Call : CallEdges)
+    for (auto Target : Call.second)
+      if (FuncRange *ToFRange = Binary->findFuncRange(Target))
+        CallEdgesF[Call.first].insert(ToFRange->Func);
+
+  for (auto Call : TailCallEdges) {
+    for (auto Target : Call.second) {
+      if (FuncRange *ToFRange = Binary->findFuncRange(Target)) {
+        TailCallEdgesF[Call.first].insert(ToFRange->Func);
+        TailCallTargetFuncs.insert(ToFRange->Func);
+      }
+    }
+    if (FuncRange *FromFRange = Binary->findFuncRange(Call.first))
+      FuncToTailCallMap[FromFRange->Func].push_back(Call.first);
+  }
+
+#if LLVM_ENABLE_STATS
+  for (auto F : FuncToTailCallMap) {
+    assert(F.second.size() > 0 && "");
+    if (F.second.size() > 1)
+      TailCallFuncMultipleTailCalls++;
+    else
+      TailCallFuncSingleTailCalls++;
+  }
+#endif
+
+#ifndef NDEBUG
+  auto PrintCallTargets =
+      [&](const std::unordered_map<uint64_t, std::unordered_set<uint64_t>>
+              &CallTargets,
+          bool IsTailCall) {
+        for (const auto &Targets : CallTargets) {
+          for (const auto &Target : Targets.second) {
+            dbgs() << (IsTailCall ? "TailCall" : "Call");
+            dbgs() << " From " << format("%8" PRIx64, Targets.first) << " to "
+                   << format("%8" PRIx64, Target) << "\n";
+          }
+        }
+      };
+
+  LLVM_DEBUG(dbgs() << "============================\n ";
+             dbgs() << "Call targets:\n";
+             PrintCallTargets(CallEdges, false);
+             dbgs() << "\nTail call targets:\n";
+             PrintCallTargets(CallEdges, true);
+             dbgs() << "============================\n";);
+#endif
+}
+
+uint64_t MissingFrameInferrer::computeUniqueTailCallPath(
+    BinaryFunction *From, BinaryFunction *To, SmallVectorImpl<uint64_t> &Path) {
+  // Search for a unique path comprised of only tail call edges for a given
+  // source and target frame address on the a tail call graph that consists of
+  // only tail call edges. Note that only a unique path counts. Multiple paths
+  // are treated unreachable.
+  if (From == To)
+    return 1;
+
+  // Ignore cyclic paths. Since we are doing a recursive DFS walk, if the source
+  // frame being visited is already in the stack, it means we are seeing a
+  // cycle. This is done before querying the cached result because the cached
+  // result may be computed based on the same path. Consider the following case:
+  //     A -> B, B -> A, A -> D
+  // When computing unique reachablity from A to D, the cached result for (B,D)
+  // should not be counted since the unique path B->A->D is basically the same
+  // path as A->D. Counting that with invalidate the uniqueness from A to D.
+  if (Visiting.contains(From))
+    return 0;
+
+  // If already computed, return the cached result.
+  auto I = UniquePaths.find({From, To});
+  if (I != UniquePaths.end()) {
+    Path.append(I->second.begin(), I->second.end());
+    return 1;
+  }
+
+  auto J = NonUniquePaths.find({From, To});
+  if (J != NonUniquePaths.end()) {
+    return J->second;
+  }
+
+  uint64_t Pos = Path.size();
+
+  // DFS walk each outgoing tail call edges.
+  // Bail out if we are already at the the maximum searching depth.
+  if (CurSearchingDepth == MaximumSearchDepth)
+    return 0;
+
+
+  if (!FuncToTailCallMap.count(From))
+    return 0;
+
+  CurSearchingDepth++;
+  Visiting.insert(From);
+  uint64_t NumPaths = 0;
+  for (auto TailCall : FuncToTailCallMap[From]) {
+    NumPaths += computeUniqueTailCallPath(TailCall, To, Path);
+    // Stop analyzing the remaining if we are already seeing more than one
+    // reachable paths.
+    if (NumPaths > 1)
+      break;
+  }
+  CurSearchingDepth--;
+  Visiting.erase(From);
+
+  // Undo already-computed path if it is not unique.
+  if (NumPaths != 1) {
+    Path.pop_back_n(Path.size() - Pos);
+  }
+
+  // Cache the result.
+  if (NumPaths == 1) {
+    UniquePaths[{From, To}].assign(Path.begin() + Pos, Path.end());
+#if LLVM_ENABLE_STATS
+    auto &LocalPath = UniquePaths[{From, To}];
+    assert((LocalPath.size() <= MaximumSearchDepth + 1) &&
+           "Path should not be longer than the maximum searching depth");
+    TailCallMaxTailCallPath = std::max(uint64_t(LocalPath.size()),
+                                       TailCallMaxTailCallPath.getValue());
+#endif
+  } else {
+    NonUniquePaths[{From, To}] = NumPaths;
+  }
+
+  return NumPaths;
+}
+
+uint64_t MissingFrameInferrer::computeUniqueTailCallPath(
+    uint64_t From, BinaryFunction *To, SmallVectorImpl<uint64_t> &Path) {
+  if (!TailCallEdgesF.count(From))
+    return 0;
+  Path.push_back(From);
+  uint64_t NumPaths = 0;
+  for (auto Target : TailCallEdgesF[From]) {
+    NumPaths += computeUniqueTailCallPath(Target, To, Path);
+    // Stop analyzing the remaining if we are already seeing more than one
+    // reachable paths.
+    if (NumPaths > 1)
+      break;
+  }
+
+  // Undo already-computed path if it is not unique.
+  if (NumPaths != 1)
+    Path.pop_back();
+  return NumPaths;
+}
+
+bool MissingFrameInferrer::inferMissingFrames(
+    uint64_t From, uint64_t To, SmallVectorImpl<uint64_t> &UniquePath) {
+  assert(!TailCallEdgesF.count(From) &&
+         "transition between From and To cannot be via a tailcall otherwise "
+         "they would not show up at the same time");
+  UniquePath.push_back(From);
+  uint64_t Pos = UniquePath.size();
+
+  FuncRange *ToFRange = Binary->findFuncRange(To);
+  if (!ToFRange)
+    return false;
+
+  // Bail out if caller has no known outgoing call edges.
+  if (!CallEdgesF.count(From))
+    return false;
+
+  // Done with the inference if the calle is reachable via a single callsite.
+  // This may not be accurate but it improves the search throughput.
+  for (auto Target : CallEdgesF[From]) {
+    if (Target == ToFRange->Func)
+      return true;
+  }
+
+  // Bail out if callee is not tailcall reachable at all.
+  if (!TailCallTargetFuncs.contains(ToFRange->Func))
+    return false;
+
+  Visiting.clear();
+  CurSearchingDepth = 0;
+  uint64_t NumPaths = 0;
+  for (auto Target : CallEdgesF[From]) {
+    NumPaths +=
+        computeUniqueTailCallPath(Target, ToFRange->Func, UniquePath);
+    // Stop analyzing the remaining if we are already seeing more than one
+    // reachable paths.
+    if (NumPaths > 1)
+      break;
+  }
+
+  // Undo already-computed path if it is not unique.
+  if (NumPaths != 1) {
+    UniquePath.pop_back_n(UniquePath.size() - Pos);
+    assert(UniquePath.back() == From && "broken path");
+  }
+
+#if LLVM_ENABLE_STATS
+  if (NumPaths == 1) {
+    if (ReachableViaUniquePaths.insert({From, ToFRange->StartAddress}).second)
+      TailCallUniReachable++;
+  } else if (NumPaths == 0) {
+    if (Unreachables.insert({From, ToFRange->StartAddress}).second) {
+      TailCallUnreachable++;
+      LLVM_DEBUG(dbgs() << "No path found from "
+                        << format("%8" PRIx64 ":", From) << " to "
+                        << format("%8" PRIx64 ":", ToFRange->StartAddress)
+                        << "\n");
+    }
+  } else if (NumPaths > 1) {
+    if (ReachableViaMultiPaths.insert({From, ToFRange->StartAddress})
+            .second) {
+      TailCallMultiReachable++;
+      LLVM_DEBUG(dbgs() << "Multiple paths found from "
+                        << format("%8" PRIx64 ":", From) << " to "
+                        << format("%8" PRIx64 ":", ToFRange->StartAddress)
+                        << "\n");
+    }
+  }
+#endif
+
+  return NumPaths == 1;
+}
+
+void MissingFrameInferrer::inferMissingFrames(
+    const SmallVectorImpl<uint64_t> &Context,
+    SmallVectorImpl<uint64_t> &NewContext) {
+  if (Context.size() == 1) {
+    NewContext = Context;
+    return;
+  }
+
+  NewContext.clear();
+  for (uint64_t I = 1; I < Context.size(); I++) {
+    inferMissingFrames(Context[I - 1], Context[I], NewContext);
+  }
+  NewContext.push_back(Context.back());
+
+  assert((NewContext.size() >= Context.size()) &&
+         "Inferred context should include all frames in the original context");
+  assert((NewContext.size() > Context.size() || NewContext == Context) &&
+         "Inferred context should be exactly the same "
+         "with the original context");
+}
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/MissingFrameInferrer.h b/src/llvm-project/llvm/tools/llvm-profgen/MissingFrameInferrer.h
new file mode 100644
index 0000000..4680a9a
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-profgen/MissingFrameInferrer.h
@@ -0,0 +1,116 @@
+//===-- MissingFrameInferrer.h -  Missing frame inferrer ---------- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_PROFGEN_MISSINGFRAMEINFERRER_H
+#define LLVM_TOOLS_LLVM_PROFGEN_MISSINGFRAMEINFERRER_H
+
+#include "PerfReader.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include <unordered_map>
+#include <unordered_set>
+
+namespace llvm {
+namespace sampleprof {
+
+class ProfiledBinary;
+struct BinaryFunction;
+
+class MissingFrameInferrer {
+public:
+  MissingFrameInferrer(ProfiledBinary *Binary) : Binary(Binary) {}
+
+  // Defininig a frame transition from a caller function to the callee function.
+  using CallerCalleePair = std::pair<BinaryFunction *, BinaryFunction *>;
+
+  void initialize(const ContextSampleCounterMap *SampleCounters);
+
+  // Given an input `Context`, output `NewContext` with inferred missing tail
+  // call frames.
+  void inferMissingFrames(const SmallVectorImpl<uint64_t> &Context,
+                          SmallVectorImpl<uint64_t> &NewContext);
+
+private:
+  friend class ProfiledBinary;
+
+  // Compute a unique tail call path for a pair of source frame address and
+  // target frame address. Append the unique path prefix (not including `To`) to
+  // `UniquePath` if exists. Return the whether this's a unqiue tail call
+  // path. The source/dest frame will typically be a pair of adjacent frame
+  // entries of call stack samples.
+  bool inferMissingFrames(uint64_t From, uint64_t To,
+                          SmallVectorImpl<uint64_t> &UniquePath);
+
+  // Compute a unique tail call path from the source frame address to the target
+  // function. Output the unique path prefix (not including `To`) in
+  // `UniquePath` if exists. Return the number of possibly availabe tail call
+  // paths.
+  uint64_t computeUniqueTailCallPath(uint64_t From, BinaryFunction *To,
+                                     SmallVectorImpl<uint64_t> &UniquePath);
+
+  // Compute a unique tail call path from the source function to the target
+  // function. Output the unique path prefix (not including `To`) in
+  // `UniquePath` if exists. Return the number of possibly availabe tail call
+  // paths.
+  uint64_t computeUniqueTailCallPath(BinaryFunction *From, BinaryFunction *To,
+                                     SmallVectorImpl<uint64_t> &UniquePath);
+
+  ProfiledBinary *Binary;
+
+  // A map of call instructions to their target addresses. This is first
+  // populated with static call edges but then trimmed down to dynamic call
+  // edges based on LBR samples.
+  std::unordered_map<uint64_t, std::unordered_set<uint64_t>> CallEdges;
+
+  // A map of tail call instructions to their target addresses. This is first
+  // populated with static call edges but then trimmed down to dynamic call
+  // edges based on LBR samples.
+  std::unordered_map<uint64_t, std::unordered_set<uint64_t>> TailCallEdges;
+
+  // Dynamic call targets in terms of BinaryFunction for any calls.
+  std::unordered_map<uint64_t, std::unordered_set<BinaryFunction *>> CallEdgesF;
+
+  // Dynamic call targets in terms of BinaryFunction  for tail calls.
+  std::unordered_map<uint64_t, std::unordered_set<BinaryFunction *>>
+      TailCallEdgesF;
+
+  // Dynamic tail call targets of caller functions.
+  std::unordered_map<BinaryFunction *, std::vector<uint64_t>> FuncToTailCallMap;
+
+  // Functions that are reachable via tail calls.
+  DenseSet<const BinaryFunction *> TailCallTargetFuncs;
+
+  struct PairHash {
+    std::size_t operator()(
+        const std::pair<BinaryFunction *, BinaryFunction *> &Pair) const {
+      return std::hash<BinaryFunction *>()(Pair.first) ^
+             std::hash<BinaryFunction *>()(Pair.second);
+    }
+  };
+
+  // Cached results from a CallerCalleePair to a unique call path between them.
+  std::unordered_map<CallerCalleePair, std::vector<uint64_t>, PairHash>
+      UniquePaths;
+  // Cached results from CallerCalleePair to the number of available call paths.
+  std::unordered_map<CallerCalleePair, uint64_t, PairHash> NonUniquePaths;
+
+  DenseSet<BinaryFunction *> Visiting;
+
+  uint32_t CurSearchingDepth = 0;
+
+#if LLVM_ENABLE_STATS
+  DenseSet<std::pair<uint64_t, uint64_t>> ReachableViaUniquePaths;
+  DenseSet<std::pair<uint64_t, uint64_t>> Unreachables;
+  DenseSet<std::pair<uint64_t, uint64_t>> ReachableViaMultiPaths;
+#endif
+};
+} // end namespace sampleprof
+} // end namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp
index f28a852..86c0131 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.cpp
@@ -96,8 +96,7 @@
     return;
   }
 
-  if (!isValidFallThroughRange(Binary->virtualAddrToOffset(Target),
-                               Binary->virtualAddrToOffset(End), Binary)) {
+  if (!isValidFallThroughRange(Target, End, Binary)) {
     // Skip unwinding the rest of LBR trace when a bogus range is seen.
     State.setInvalid();
     return;
@@ -186,17 +185,11 @@
     return;
   auto Ret = CtxCounterMap->emplace(Hashable<ContextKey>(Key), SampleCounter());
   SampleCounter &SCounter = Ret.first->second;
-  for (auto &Item : Cur->RangeSamples) {
-    uint64_t StartOffset = Binary->virtualAddrToOffset(std::get<0>(Item));
-    uint64_t EndOffset = Binary->virtualAddrToOffset(std::get<1>(Item));
-    SCounter.recordRangeCount(StartOffset, EndOffset, std::get<2>(Item));
-  }
+  for (auto &I : Cur->RangeSamples)
+    SCounter.recordRangeCount(std::get<0>(I), std::get<1>(I), std::get<2>(I));
 
-  for (auto &Item : Cur->BranchSamples) {
-    uint64_t SourceOffset = Binary->virtualAddrToOffset(std::get<0>(Item));
-    uint64_t TargetOffset = Binary->virtualAddrToOffset(std::get<1>(Item));
-    SCounter.recordBranchCount(SourceOffset, TargetOffset, std::get<2>(Item));
-  }
+  for (auto &I : Cur->BranchSamples)
+    SCounter.recordBranchCount(std::get<0>(I), std::get<1>(I), std::get<2>(I));
 }
 
 template <typename T>
@@ -326,7 +319,7 @@
 
 std::unique_ptr<PerfReaderBase>
 PerfReaderBase::create(ProfiledBinary *Binary, PerfInputFile &PerfInput,
-                       Optional<uint32_t> PIDFilter) {
+                       std::optional<uint32_t> PIDFilter) {
   std::unique_ptr<PerfReaderBase> PerfReader;
 
   if (PerfInput.Format == PerfFormat::UnsymbolizedProfile) {
@@ -357,8 +350,10 @@
   return PerfReader;
 }
 
-PerfInputFile PerfScriptReader::convertPerfDataToTrace(
-    ProfiledBinary *Binary, PerfInputFile &File, Optional<uint32_t> PIDFilter) {
+PerfInputFile
+PerfScriptReader::convertPerfDataToTrace(ProfiledBinary *Binary,
+                                         PerfInputFile &File,
+                                         std::optional<uint32_t> PIDFilter) {
   StringRef PerfData = File.InputFile;
   // Run perf script to retrieve PIDs matching binary we're interested in.
   auto PerfExecutable = sys::Process::FindInEnvPath("PATH", "perf");
@@ -367,13 +362,14 @@
   }
   std::string PerfPath = *PerfExecutable;
   std::string PerfTraceFile = PerfData.str() + ".script.tmp";
+  std::string ErrorFile = PerfData.str() + ".script.err.tmp";
   StringRef ScriptMMapArgs[] = {PerfPath, "script",   "--show-mmap-events",
                                 "-F",     "comm,pid", "-i",
                                 PerfData};
-  Optional<StringRef> Redirects[] = {llvm::None,                // Stdin
-                                     StringRef(PerfTraceFile),  // Stdout
-                                     StringRef(PerfTraceFile)}; // Stderr
-  sys::ExecuteAndWait(PerfPath, ScriptMMapArgs, llvm::None, Redirects);
+  std::optional<StringRef> Redirects[] = {std::nullopt,             // Stdin
+                                          StringRef(PerfTraceFile), // Stdout
+                                          StringRef(ErrorFile)};    // Stderr
+  sys::ExecuteAndWait(PerfPath, ScriptMMapArgs, std::nullopt, Redirects);
 
   // Collect the PIDs
   TraceStream TraceIt(PerfTraceFile);
@@ -402,7 +398,7 @@
   StringRef ScriptSampleArgs[] = {PerfPath, "script",     "--show-mmap-events",
                                   "-F",     "ip,brstack", "--pid",
                                   PIDs,     "-i",         PerfData};
-  sys::ExecuteAndWait(PerfPath, ScriptSampleArgs, llvm::None, Redirects);
+  sys::ExecuteAndWait(PerfPath, ScriptSampleArgs, std::nullopt, Redirects);
 
   return {PerfTraceFile, PerfFormat::PerfScript, PerfContent::UnknownContent};
 }
@@ -434,7 +430,7 @@
   } else {
     // Verify segments are loaded consecutively.
     const auto &Offsets = Binary->getTextSegmentOffsets();
-    auto It = std::lower_bound(Offsets.begin(), Offsets.end(), Event.Offset);
+    auto It = llvm::lower_bound(Offsets, Event.Offset);
     if (It != Offsets.end() && *It == Event.Offset) {
       // The event is for loading a separate executable segment.
       auto I = std::distance(Offsets.begin(), It);
@@ -466,10 +462,16 @@
     for (uint32_t I = 0; I < CtxKey->Context.size(); I++) {
       if (OContextStr.str().size())
         OContextStr << " @ ";
+      uint64_t Address = CtxKey->Context[I];
+      if (UseOffset) {
+        if (UseLoadableSegmentAsBase)
+          Address -= Binary->getFirstLoadableAddress();
+        else
+          Address -= Binary->getPreferredBaseAddress();
+      }
       OContextStr << "0x"
-                  << utohexstr(
-                         Binary->virtualAddrToOffset(CtxKey->Context[I]),
-                         /*LowerCase=*/true);
+                  << utohexstr(Address,
+                               /*LowerCase=*/true);
     }
     return OContextStr.str();
   } else {
@@ -569,6 +571,9 @@
       break;
     }
 
+    // Canonicalize to use preferred load address as base address.
+    Src = Binary->canonicalizeVirtualAddress(Src);
+    Dst = Binary->canonicalizeVirtualAddress(Dst);
     bool SrcIsInternal = Binary->addressIsCode(Src);
     bool DstIsInternal = Binary->addressIsCode(Dst);
     if (!SrcIsInternal)
@@ -604,6 +609,8 @@
       return false;
     }
     TraceIt.advance();
+
+    FrameAddr = Binary->canonicalizeVirtualAddress(FrameAddr);
     // Currently intermixed frame from different binaries is not supported.
     if (!Binary->addressIsCode(FrameAddr)) {
       if (CallStack.empty())
@@ -736,14 +743,14 @@
       uint64_t Start = I.first.first;
       uint64_t End = I.first.second;
 
-      if (!UseOffset || (UseOffset && UseLoadableSegmentAsBase)) {
-        Start = Binary->offsetToVirtualAddr(Start);
-        End = Binary->offsetToVirtualAddr(End);
-      }
-
-      if (UseOffset && UseLoadableSegmentAsBase) {
-        Start -= Binary->getFirstLoadableAddress();
-        End -= Binary->getFirstLoadableAddress();
+      if (UseOffset) {
+        if (UseLoadableSegmentAsBase) {
+          Start -= Binary->getFirstLoadableAddress();
+          End -= Binary->getFirstLoadableAddress();
+        } else {
+          Start -= Binary->getPreferredBaseAddress();
+          End -= Binary->getPreferredBaseAddress();
+        }
       }
 
       OS.indent(Indent);
@@ -815,13 +822,14 @@
           Range.second.getAsInteger(16, Target))
         exitWithErrorForTraceLine(TraceIt);
 
-      if (!UseOffset || (UseOffset && UseLoadableSegmentAsBase)) {
-        uint64_t BaseAddr = 0;
-        if (UseOffset && UseLoadableSegmentAsBase)
-          BaseAddr = Binary->getFirstLoadableAddress();
-
-        Source = Binary->virtualAddrToOffset(Source + BaseAddr);
-        Target = Binary->virtualAddrToOffset(Target + BaseAddr);
+      if (UseOffset) {
+        if (UseLoadableSegmentAsBase) {
+          Source += Binary->getFirstLoadableAddress();
+          Target += Binary->getFirstLoadableAddress();
+        } else {
+          Source += Binary->getPreferredBaseAddress();
+          Target += Binary->getPreferredBaseAddress();
+        }
       }
 
       Counter[{Source, Target}] += Count;
@@ -859,25 +867,26 @@
 void PerfScriptReader::computeCounterFromLBR(const PerfSample *Sample,
                                              uint64_t Repeat) {
   SampleCounter &Counter = SampleCounters.begin()->second;
-  uint64_t EndOffeset = 0;
+  uint64_t EndAddress = 0;
   for (const LBREntry &LBR : Sample->LBRStack) {
-    uint64_t SourceOffset = Binary->virtualAddrToOffset(LBR.Source);
-    uint64_t TargetOffset = Binary->virtualAddrToOffset(LBR.Target);
+    uint64_t SourceAddress = LBR.Source;
+    uint64_t TargetAddress = LBR.Target;
 
-    // Record the branch if its sourceOffset is external. It can be the case an
+    // Record the branch if its SourceAddress is external. It can be the case an
     // external source call an internal function, later this branch will be used
     // to generate the function's head sample.
-    if (Binary->offsetIsCode(TargetOffset)) {
-      Counter.recordBranchCount(SourceOffset, TargetOffset, Repeat);
+    if (Binary->addressIsCode(TargetAddress)) {
+      Counter.recordBranchCount(SourceAddress, TargetAddress, Repeat);
     }
 
     // If this not the first LBR, update the range count between TO of current
     // LBR and FROM of next LBR.
-    uint64_t StartOffset = TargetOffset;
-    if (Binary->offsetIsCode(StartOffset) && Binary->offsetIsCode(EndOffeset) &&
-        isValidFallThroughRange(StartOffset, EndOffeset, Binary))
-      Counter.recordRangeCount(StartOffset, EndOffeset, Repeat);
-    EndOffeset = SourceOffset;
+    uint64_t StartAddress = TargetAddress;
+    if (Binary->addressIsCode(StartAddress) &&
+        Binary->addressIsCode(EndAddress) &&
+        isValidFallThroughRange(StartAddress, EndAddress, Binary))
+      Counter.recordRangeCount(StartAddress, EndAddress, Repeat);
+    EndAddress = SourceAddress;
   }
 }
 
@@ -950,8 +959,8 @@
   SmallVector<StringRef, 6> Fields;
   bool R = RegMmap2.match(Line, &Fields);
   if (!R) {
-    std::string ErrorMsg = "Cannot parse mmap event: " + Line.str() + " \n";
-    exitWithError(ErrorMsg);
+    std::string WarningMsg = "Cannot parse mmap event: " + Line.str() + " \n";
+    WithColor::warning() << WarningMsg;
   }
   Fields[PID].getAsInteger(10, MMap.PID);
   Fields[MMAPPED_ADDRESS].getAsInteger(0, MMap.Address);
@@ -1087,13 +1096,13 @@
   for (const auto &Item : AggregatedSamples) {
     const PerfSample *Sample = Item.first.getPtr();
     uint64_t Count = Item.second;
-    uint64_t EndOffeset = 0;
+    uint64_t EndAddress = 0;
     for (const LBREntry &LBR : Sample->LBRStack) {
-      uint64_t SourceOffset = Binary->virtualAddrToOffset(LBR.Source);
-      uint64_t StartOffset = Binary->virtualAddrToOffset(LBR.Target);
-      if (EndOffeset != 0)
-        Ranges[{StartOffset, EndOffeset}] += Count;
-      EndOffeset = SourceOffset;
+      uint64_t SourceAddress = LBR.Source;
+      uint64_t StartAddress = LBR.Target;
+      if (EndAddress != 0)
+        Ranges[{StartAddress, EndAddress}] += Count;
+      EndAddress = SourceAddress;
     }
   }
 
@@ -1102,17 +1111,14 @@
     return;
   }
 
-  auto WarnInvalidRange =
-      [&](uint64_t StartOffset, uint64_t EndOffset, StringRef Msg) {
-        if (!ShowDetailedWarning)
-          return;
-        WithColor::warning()
-            << "["
-            << format("%8" PRIx64, Binary->offsetToVirtualAddr(StartOffset))
-            << ","
-            << format("%8" PRIx64, Binary->offsetToVirtualAddr(EndOffset))
-            << "]: " << Msg << "\n";
-      };
+  auto WarnInvalidRange = [&](uint64_t StartAddress, uint64_t EndAddress,
+                              StringRef Msg) {
+    if (!ShowDetailedWarning)
+      return;
+    WithColor::warning() << "[" << format("%8" PRIx64, StartAddress) << ","
+                         << format("%8" PRIx64, EndAddress) << "]: " << Msg
+                         << "\n";
+  };
 
   const char *EndNotBoundaryMsg = "Range is not on instruction boundary, "
                                   "likely due to profile and binary mismatch.";
@@ -1130,31 +1136,37 @@
   uint64_t BogusRange = 0;
 
   for (auto &I : Ranges) {
-    uint64_t StartOffset = I.first.first;
-    uint64_t EndOffset = I.first.second;
+    uint64_t StartAddress = I.first.first;
+    uint64_t EndAddress = I.first.second;
     TotalRangeNum += I.second;
 
-    if (!Binary->offsetIsCode(StartOffset) ||
-        !Binary->offsetIsTransfer(EndOffset)) {
+    if (!Binary->addressIsCode(StartAddress) &&
+        !Binary->addressIsCode(EndAddress))
+      continue;
+
+    if (!Binary->addressIsCode(StartAddress) ||
+        !Binary->addressIsTransfer(EndAddress)) {
       InstNotBoundary += I.second;
-      WarnInvalidRange(StartOffset, EndOffset, EndNotBoundaryMsg);
+      WarnInvalidRange(StartAddress, EndAddress, EndNotBoundaryMsg);
     }
 
-    auto *FRange = Binary->findFuncRangeForOffset(StartOffset);
+    auto *FRange = Binary->findFuncRange(StartAddress);
     if (!FRange) {
       UnmatchedRange += I.second;
-      WarnInvalidRange(StartOffset, EndOffset, DanglingRangeMsg);
+      WarnInvalidRange(StartAddress, EndAddress, DanglingRangeMsg);
       continue;
     }
 
-    if (EndOffset >= FRange->EndOffset) {
+    if (EndAddress >= FRange->EndAddress) {
       RangeCrossFunc += I.second;
-      WarnInvalidRange(StartOffset, EndOffset, RangeCrossFuncMsg);
+      WarnInvalidRange(StartAddress, EndAddress, RangeCrossFuncMsg);
     }
 
-    if (!isValidFallThroughRange(StartOffset, EndOffset, Binary)) {
+    if (Binary->addressIsCode(StartAddress) &&
+        Binary->addressIsCode(EndAddress) &&
+        !isValidFallThroughRange(StartAddress, EndAddress, Binary)) {
       BogusRange += I.second;
-      WarnInvalidRange(StartOffset, EndOffset, BogusRangeMsg);
+      WarnInvalidRange(StartAddress, EndAddress, BogusRangeMsg);
     }
   }
 
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h
index 3ffed99..14137e8 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/PerfReader.h
@@ -119,7 +119,7 @@
 // only changes the leaf of frame stack. \fn isEqual is a virtual function,
 // which will have perf overhead. In the future, if we redesign a better hash
 // function, then we can just skip this or switch to non-virtual function(like
-// just ignore comparision if hash conflicts probabilities is low)
+// just ignore comparison if hash conflicts probabilities is low)
 template <class T> class Hashable {
 public:
   std::shared_ptr<T> Data;
@@ -567,9 +567,9 @@
     Binary->setBaseAddress(Binary->getPreferredBaseAddress());
   };
   virtual ~PerfReaderBase() = default;
-  static std::unique_ptr<PerfReaderBase> create(ProfiledBinary *Binary,
-                                                PerfInputFile &PerfInput,
-                                                Optional<uint32_t> PIDFilter);
+  static std::unique_ptr<PerfReaderBase>
+  create(ProfiledBinary *Binary, PerfInputFile &PerfInput,
+         std::optional<uint32_t> PIDFilter);
 
   // Entry of the reader to parse multiple perf traces
   virtual void parsePerfTraces() = 0;
@@ -594,15 +594,15 @@
 class PerfScriptReader : public PerfReaderBase {
 public:
   PerfScriptReader(ProfiledBinary *B, StringRef PerfTrace,
-                   Optional<uint32_t> PID)
+                   std::optional<uint32_t> PID)
       : PerfReaderBase(B, PerfTrace), PIDFilter(PID){};
 
   // Entry of the reader to parse multiple perf traces
   void parsePerfTraces() override;
   // Generate perf script from perf data
-  static PerfInputFile convertPerfDataToTrace(ProfiledBinary *Binary,
-                                              PerfInputFile &File,
-                                              Optional<uint32_t> PIDFilter);
+  static PerfInputFile
+  convertPerfDataToTrace(ProfiledBinary *Binary, PerfInputFile &File,
+                         std::optional<uint32_t> PIDFilter);
   // Extract perf script type by peaking at the input
   static PerfContent checkPerfScriptType(StringRef FileName);
 
@@ -663,7 +663,7 @@
   // Keep track of all invalid return addresses
   std::set<uint64_t> InvalidReturnAddresses;
   // PID for the process of interest
-  Optional<uint32_t> PIDFilter;
+  std::optional<uint32_t> PIDFilter;
 };
 
 /*
@@ -675,7 +675,7 @@
 class LBRPerfReader : public PerfScriptReader {
 public:
   LBRPerfReader(ProfiledBinary *Binary, StringRef PerfTrace,
-                Optional<uint32_t> PID)
+                std::optional<uint32_t> PID)
       : PerfScriptReader(Binary, PerfTrace, PID){};
   // Parse the LBR only sample.
   void parseSample(TraceStream &TraceIt, uint64_t Count) override;
@@ -693,7 +693,7 @@
 class HybridPerfReader : public PerfScriptReader {
 public:
   HybridPerfReader(ProfiledBinary *Binary, StringRef PerfTrace,
-                   Optional<uint32_t> PID)
+                   std::optional<uint32_t> PID)
       : PerfScriptReader(Binary, PerfTrace, PID){};
   // Parse the hybrid sample including the call and LBR line
   void parseSample(TraceStream &TraceIt, uint64_t Count) override;
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp
index 6acbb14..dfc42a5 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 #include "ProfileGenerator.h"
 #include "ErrorHandling.h"
+#include "MissingFrameInferrer.h"
 #include "PerfReader.h"
 #include "ProfiledBinary.h"
 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
@@ -32,8 +33,8 @@
         clEnumValN(SPF_GCC, "gcc",
                    "GCC encoding (only meaningful for -sample)")));
 
-cl::opt<bool> UseMD5(
-    "use-md5", cl::init(false), cl::Hidden,
+static cl::opt<bool> UseMD5(
+    "use-md5", cl::Hidden,
     cl::desc("Use md5 to represent function names in the output profile (only "
              "meaningful for -extbinary)"));
 
@@ -90,17 +91,23 @@
         "Update total samples by accumulating all its body samples."),
     llvm::cl::Optional);
 
-extern cl::opt<int> ProfileSummaryCutoffHot;
-extern cl::opt<bool> UseContextLessSummary;
-
 static cl::opt<bool> GenCSNestedProfile(
     "gen-cs-nested-profile", cl::Hidden, cl::init(true),
     cl::desc("Generate nested function profiles for CSSPGO"));
 
+cl::opt<bool> InferMissingFrames(
+    "infer-missing-frames", llvm::cl::init(true),
+    llvm::cl::desc(
+        "Infer missing call frames due to compiler tail call elimination."),
+    llvm::cl::Optional);
+
 using namespace llvm;
 using namespace sampleprof;
 
 namespace llvm {
+extern cl::opt<int> ProfileSummaryCutoffHot;
+extern cl::opt<bool> UseContextLessSummary;
+
 namespace sampleprof {
 
 // Initialize the MaxCompressionSize to -1 which means no size limit
@@ -420,25 +427,24 @@
   // function.
   for (const auto &CI : *SampleCounters) {
     if (const auto *CtxKey = dyn_cast<AddrBasedCtxKey>(CI.first.getPtr())) {
-      for (auto Addr : CtxKey->Context) {
-        if (FuncRange *FRange = Binary->findFuncRangeForOffset(
-                Binary->virtualAddrToOffset(Addr)))
+      for (auto StackAddr : CtxKey->Context) {
+        if (FuncRange *FRange = Binary->findFuncRange(StackAddr))
           ProfiledFunctions.insert(FRange->Func);
       }
     }
 
     for (auto Item : CI.second.RangeCounter) {
-      uint64_t StartOffset = Item.first.first;
-      if (FuncRange *FRange = Binary->findFuncRangeForOffset(StartOffset))
+      uint64_t StartAddress = Item.first.first;
+      if (FuncRange *FRange = Binary->findFuncRange(StartAddress))
         ProfiledFunctions.insert(FRange->Func);
     }
 
     for (auto Item : CI.second.BranchCounter) {
-      uint64_t SourceOffset = Item.first.first;
-      uint64_t TargetOffset = Item.first.first;
-      if (FuncRange *FRange = Binary->findFuncRangeForOffset(SourceOffset))
+      uint64_t SourceAddress = Item.first.first;
+      uint64_t TargetAddress = Item.first.second;
+      if (FuncRange *FRange = Binary->findFuncRange(SourceAddress))
         ProfiledFunctions.insert(FRange->Func);
-      if (FuncRange *FRange = Binary->findFuncRangeForOffset(TargetOffset))
+      if (FuncRange *FRange = Binary->findFuncRange(TargetAddress))
         ProfiledFunctions.insert(FRange->Func);
     }
   }
@@ -565,16 +571,15 @@
 void ProfileGenerator::populateBoundarySamplesWithProbesForAllFunctions(
     const BranchSample &BranchCounters) {
   for (const auto &Entry : BranchCounters) {
-    uint64_t SourceOffset = Entry.first.first;
-    uint64_t TargetOffset = Entry.first.second;
+    uint64_t SourceAddress = Entry.first.first;
+    uint64_t TargetAddress = Entry.first.second;
     uint64_t Count = Entry.second;
     assert(Count != 0 && "Unexpected zero weight branch");
 
-    StringRef CalleeName = getCalleeNameForOffset(TargetOffset);
+    StringRef CalleeName = getCalleeNameForAddress(TargetAddress);
     if (CalleeName.size() == 0)
       continue;
 
-    uint64_t SourceAddress = Binary->offsetToVirtualAddr(SourceOffset);
     const MCDecodedPseudoProbe *CallProbe =
         Binary->getCallProbeForAddr(SourceAddress);
     if (CallProbe == nullptr)
@@ -644,8 +649,8 @@
     // samples. This is to be consistent with compiler that interpret zero count
     // as unexecuted(cold).
     for (const auto &I : RangeCounter) {
-      uint64_t StartOffset = I.first.first;
-      for (const auto &Range : Binary->getRangesForOffset(StartOffset))
+      uint64_t StartAddress = I.first.first;
+      for (const auto &Range : Binary->getRanges(StartAddress))
         Ranges[{Range.first, Range.second - 1}] += 0;
     }
   }
@@ -657,8 +662,8 @@
 void ProfileGenerator::populateBodySamplesForAllFunctions(
     const RangeSample &RangeCounter) {
   for (const auto &Range : preprocessRangeCounter(RangeCounter)) {
-    uint64_t RangeBegin = Binary->offsetToVirtualAddr(Range.first.first);
-    uint64_t RangeEnd = Binary->offsetToVirtualAddr(Range.first.second);
+    uint64_t RangeBegin = Range.first.first;
+    uint64_t RangeEnd = Range.first.second;
     uint64_t Count = Range.second;
 
     InstructionPointer IP(Binary, RangeBegin, true);
@@ -669,16 +674,15 @@
       continue;
 
     do {
-      uint64_t Offset = Binary->virtualAddrToOffset(IP.Address);
-      const SampleContextFrameVector &FrameVec =
-          Binary->getFrameLocationStack(Offset);
+      const SampleContextFrameVector FrameVec =
+          Binary->getFrameLocationStack(IP.Address);
       if (!FrameVec.empty()) {
         // FIXME: As accumulating total count per instruction caused some
         // regression, we changed to accumulate total count per byte as a
         // workaround. Tuning hotness threshold on the compiler side might be
         // necessary in the future.
         FunctionSamples &FunctionProfile = getLeafProfileAndAddTotalSamples(
-            FrameVec, Count * Binary->getInstSize(Offset));
+            FrameVec, Count * Binary->getInstSize(IP.Address));
         updateBodySamplesforFunctionProfile(FunctionProfile, FrameVec.back(),
                                             Count);
       }
@@ -686,9 +690,10 @@
   }
 }
 
-StringRef ProfileGeneratorBase::getCalleeNameForOffset(uint64_t TargetOffset) {
+StringRef
+ProfileGeneratorBase::getCalleeNameForAddress(uint64_t TargetAddress) {
   // Get the function range by branch target if it's a call branch.
-  auto *FRange = Binary->findFuncRangeForStartOffset(TargetOffset);
+  auto *FRange = Binary->findFuncRangeForStartAddr(TargetAddress);
 
   // We won't accumulate sample count for a range whose start is not the real
   // function entry such as outlined function or inner labels.
@@ -701,17 +706,17 @@
 void ProfileGenerator::populateBoundarySamplesForAllFunctions(
     const BranchSample &BranchCounters) {
   for (const auto &Entry : BranchCounters) {
-    uint64_t SourceOffset = Entry.first.first;
-    uint64_t TargetOffset = Entry.first.second;
+    uint64_t SourceAddress = Entry.first.first;
+    uint64_t TargetAddress = Entry.first.second;
     uint64_t Count = Entry.second;
     assert(Count != 0 && "Unexpected zero weight branch");
 
-    StringRef CalleeName = getCalleeNameForOffset(TargetOffset);
+    StringRef CalleeName = getCalleeNameForAddress(TargetAddress);
     if (CalleeName.size() == 0)
       continue;
     // Record called target sample and its count.
     const SampleContextFrameVector &FrameVec =
-        Binary->getFrameLocationStack(SourceOffset);
+        Binary->getCachedFrameLocationStack(SourceAddress);
     if (!FrameVec.empty()) {
       FunctionSamples &FunctionProfile =
           getLeafProfileAndAddTotalSamples(FrameVec, 0);
@@ -771,8 +776,11 @@
 
   collectProfiledFunctions();
 
-  if (Binary->usePseudoProbes())
+  if (Binary->usePseudoProbes()) {
     Binary->decodePseudoProbe();
+    if (InferMissingFrames)
+      initializeMissingFrameInferrer();
+  }
 
   if (SampleCounters) {
     if (Binary->usePseudoProbes()) {
@@ -788,8 +796,17 @@
   postProcessProfiles();
 }
 
+void CSProfileGenerator::initializeMissingFrameInferrer() {
+  Binary->getMissingContextInferrer()->initialize(SampleCounters);
+}
+
+void CSProfileGenerator::inferMissingFrames(
+    const SmallVectorImpl<uint64_t> &Context,
+    SmallVectorImpl<uint64_t> &NewContext) {
+  Binary->inferMissingFrames(Context, NewContext);
+}
+
 void CSProfileGenerator::computeSizeForProfiledFunctions() {
-  std::unordered_set<const BinaryFunction *> ProfiledFunctions;
   for (auto *Func : Binary->getProfiledFunctions())
     Binary->computeInlinedContextSizeForFunc(Func);
 
@@ -842,8 +859,8 @@
   RangeSample Ranges;
   findDisjointRanges(Ranges, RangeCounter);
   for (const auto &Range : Ranges) {
-    uint64_t RangeBegin = Binary->offsetToVirtualAddr(Range.first.first);
-    uint64_t RangeEnd = Binary->offsetToVirtualAddr(Range.first.second);
+    uint64_t RangeBegin = Range.first.first;
+    uint64_t RangeEnd = Range.first.second;
     uint64_t Count = Range.second;
     // Disjoint ranges have introduce zero-filled gap that
     // doesn't belong to current context, filter them out.
@@ -858,8 +875,7 @@
       continue;
 
     do {
-      uint64_t Offset = Binary->virtualAddrToOffset(IP.Address);
-      auto LeafLoc = Binary->getInlineLeafFrameLoc(Offset);
+      auto LeafLoc = Binary->getInlineLeafFrameLoc(IP.Address);
       if (LeafLoc) {
         // Recording body sample for this specific context
         updateBodySamplesforFunctionProfile(FunctionProfile, *LeafLoc, Count);
@@ -873,12 +889,12 @@
     ContextTrieNode *Node, const BranchSample &BranchCounters) {
 
   for (const auto &Entry : BranchCounters) {
-    uint64_t SourceOffset = Entry.first.first;
-    uint64_t TargetOffset = Entry.first.second;
+    uint64_t SourceAddress = Entry.first.first;
+    uint64_t TargetAddress = Entry.first.second;
     uint64_t Count = Entry.second;
     assert(Count != 0 && "Unexpected zero weight branch");
 
-    StringRef CalleeName = getCalleeNameForOffset(TargetOffset);
+    StringRef CalleeName = getCalleeNameForAddress(TargetAddress);
     if (CalleeName.size() == 0)
       continue;
 
@@ -886,7 +902,7 @@
     LineLocation CalleeCallSite(0, 0);
     if (CallerNode != &getRootContext()) {
       // Record called target sample and its count
-      auto LeafLoc = Binary->getInlineLeafFrameLoc(SourceOffset);
+      auto LeafLoc = Binary->getInlineLeafFrameLoc(SourceAddress);
       if (LeafLoc) {
         CallerNode->getFunctionSamples()->addCalledTargetSamples(
             LeafLoc->Location.LineOffset,
@@ -1054,8 +1070,8 @@
   }
 
   for (const auto &Range : *PRanges) {
-    uint64_t RangeBegin = Binary->offsetToVirtualAddr(Range.first.first);
-    uint64_t RangeEnd = Binary->offsetToVirtualAddr(Range.first.second);
+    uint64_t RangeBegin = Range.first.first;
+    uint64_t RangeEnd = Range.first.second;
     uint64_t Count = Range.second;
 
     InstructionPointer IP(Binary, RangeBegin, true);
@@ -1078,13 +1094,13 @@
   }
 }
 
-static void
-extractPrefixContextStack(SampleContextFrameVector &ContextStack,
-                          const SmallVectorImpl<uint64_t> &Addresses,
-                          ProfiledBinary *Binary) {
+static void extractPrefixContextStack(SampleContextFrameVector &ContextStack,
+                                      const SmallVectorImpl<uint64_t> &AddrVec,
+                                      ProfiledBinary *Binary) {
   SmallVector<const MCDecodedPseudoProbe *, 16> Probes;
-  for (auto Addr : reverse(Addresses)) {
-    const MCDecodedPseudoProbe *CallProbe = Binary->getCallProbeForAddr(Addr);
+  for (auto Address : reverse(AddrVec)) {
+    const MCDecodedPseudoProbe *CallProbe =
+        Binary->getCallProbeForAddr(Address);
     // These could be the cases when a probe is not found at a calliste. Cutting
     // off the context from here since the inliner will not know how to consume
     // a context with unknown callsites.
@@ -1113,18 +1129,16 @@
   for (const auto &CI : *SampleCounters) {
     const AddrBasedCtxKey *CtxKey =
         dyn_cast<AddrBasedCtxKey>(CI.first.getPtr());
-    SampleContextFrameVector ContextStack;
-    extractPrefixContextStack(ContextStack, CtxKey->Context, Binary);
     // Fill in function body samples from probes, also infer caller's samples
     // from callee's probe
-    populateBodySamplesWithProbes(CI.second.RangeCounter, ContextStack);
+    populateBodySamplesWithProbes(CI.second.RangeCounter, CtxKey);
     // Fill in boundary samples for a call probe
-    populateBoundarySamplesWithProbes(CI.second.BranchCounter, ContextStack);
+    populateBoundarySamplesWithProbes(CI.second.BranchCounter, CtxKey);
   }
 }
 
 void CSProfileGenerator::populateBodySamplesWithProbes(
-    const RangeSample &RangeCounter, SampleContextFrames ContextStack) {
+    const RangeSample &RangeCounter, const AddrBasedCtxKey *CtxKey) {
   ProbeCounterMap ProbeCounter;
   // Extract the top frame probes by looking up each address among the range in
   // the Address2ProbeMap
@@ -1140,8 +1154,7 @@
     if (!Probe->isBlock() || Count == 0)
       continue;
 
-    ContextTrieNode *ContextNode =
-        getContextNodeForLeafProbe(ContextStack, Probe);
+    ContextTrieNode *ContextNode = getContextNodeForLeafProbe(CtxKey, Probe);
     FunctionSamples &FunctionProfile = *ContextNode->getFunctionSamples();
     // Record the current frame and FunctionProfile whenever samples are
     // collected for non-danglie probes. This is for reporting all of the
@@ -1185,21 +1198,20 @@
 }
 
 void CSProfileGenerator::populateBoundarySamplesWithProbes(
-    const BranchSample &BranchCounter, SampleContextFrames ContextStack) {
+    const BranchSample &BranchCounter, const AddrBasedCtxKey *CtxKey) {
   for (const auto &BI : BranchCounter) {
-    uint64_t SourceOffset = BI.first.first;
-    uint64_t TargetOffset = BI.first.second;
+    uint64_t SourceAddress = BI.first.first;
+    uint64_t TargetAddress = BI.first.second;
     uint64_t Count = BI.second;
-    uint64_t SourceAddress = Binary->offsetToVirtualAddr(SourceOffset);
     const MCDecodedPseudoProbe *CallProbe =
         Binary->getCallProbeForAddr(SourceAddress);
     if (CallProbe == nullptr)
       continue;
     FunctionSamples &FunctionProfile =
-        getFunctionProfileForLeafProbe(ContextStack, CallProbe);
+        getFunctionProfileForLeafProbe(CtxKey, CallProbe);
     FunctionProfile.addBodySamples(CallProbe->getIndex(), 0, Count);
     FunctionProfile.addTotalSamples(Count);
-    StringRef CalleeName = getCalleeNameForOffset(TargetOffset);
+    StringRef CalleeName = getCalleeNameForAddress(TargetAddress);
     if (CalleeName.size() == 0)
       continue;
     FunctionProfile.addCalledTargetSamples(CallProbe->getIndex(), 0, CalleeName,
@@ -1208,7 +1220,23 @@
 }
 
 ContextTrieNode *CSProfileGenerator::getContextNodeForLeafProbe(
-    SampleContextFrames ContextStack, const MCDecodedPseudoProbe *LeafProbe) {
+    const AddrBasedCtxKey *CtxKey, const MCDecodedPseudoProbe *LeafProbe) {
+
+  const SmallVectorImpl<uint64_t> *PContext = &CtxKey->Context;
+  SmallVector<uint64_t, 16> NewContext;
+
+  if (InferMissingFrames) {
+    SmallVector<uint64_t, 16> Context = CtxKey->Context;
+    // Append leaf frame for a complete inference.
+    Context.push_back(LeafProbe->getAddress());
+    inferMissingFrames(Context, NewContext);
+    // Pop out the leaf probe that was pushed in above.
+    NewContext.pop_back();
+    PContext = &NewContext;
+  }
+
+  SampleContextFrameVector ContextStack;
+  extractPrefixContextStack(ContextStack, *PContext, Binary);
 
   // Explicitly copy the context for appending the leaf context
   SampleContextFrameVector NewContextStack(ContextStack.begin(),
@@ -1234,9 +1262,8 @@
 }
 
 FunctionSamples &CSProfileGenerator::getFunctionProfileForLeafProbe(
-    SampleContextFrames ContextStack, const MCDecodedPseudoProbe *LeafProbe) {
-  return *getContextNodeForLeafProbe(ContextStack, LeafProbe)
-              ->getFunctionSamples();
+    const AddrBasedCtxKey *CtxKey, const MCDecodedPseudoProbe *LeafProbe) {
+  return *getContextNodeForLeafProbe(CtxKey, LeafProbe)->getFunctionSamples();
 }
 
 } // end namespace sampleprof
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h
index 0ce4645..471792e 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfileGenerator.h
@@ -108,7 +108,7 @@
 
   void updateCallsiteSamples();
 
-  StringRef getCalleeNameForOffset(uint64_t TargetOffset);
+  StringRef getCalleeNameForAddress(uint64_t TargetAddress);
 
   void computeSummaryAndThreshold(SampleProfileMap &ProfileMap);
 
@@ -334,18 +334,18 @@
 
   // Fill in function body samples from probes
   void populateBodySamplesWithProbes(const RangeSample &RangeCounter,
-                                     SampleContextFrames ContextStack);
+                                     const AddrBasedCtxKey *CtxKey);
   // Fill in boundary samples for a call probe
   void populateBoundarySamplesWithProbes(const BranchSample &BranchCounter,
-                                         SampleContextFrames ContextStack);
+                                         const AddrBasedCtxKey *CtxKey);
 
   ContextTrieNode *
-  getContextNodeForLeafProbe(SampleContextFrames ContextStack,
+  getContextNodeForLeafProbe(const AddrBasedCtxKey *CtxKey,
                              const MCDecodedPseudoProbe *LeafProbe);
 
   // Helper function to get FunctionSamples for the leaf probe
   FunctionSamples &
-  getFunctionProfileForLeafProbe(SampleContextFrames ContextStack,
+  getFunctionProfileForLeafProbe(const AddrBasedCtxKey *CtxKey,
                                  const MCDecodedPseudoProbe *LeafProbe);
 
   void convertToProfileMap(ContextTrieNode &Node,
@@ -358,6 +358,13 @@
   bool collectFunctionsFromLLVMProfile(
       std::unordered_set<const BinaryFunction *> &ProfiledFunctions) override;
 
+  void initializeMissingFrameInferrer();
+
+  // Given an input `Context`, output `NewContext` with inferred missing tail
+  // call frames.
+  void inferMissingFrames(const SmallVectorImpl<uint64_t> &Context,
+                          SmallVectorImpl<uint64_t> &NewContext);
+
   ContextTrieNode &getRootContext() { return ContextTracker.getRootContext(); };
 
   // The container for holding the FunctionSamples used by context trie.
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp
index eef5b8e..00e9d50 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.cpp
@@ -8,6 +8,7 @@
 
 #include "ProfiledBinary.h"
 #include "ErrorHandling.h"
+#include "MissingFrameInferrer.h"
 #include "ProfileGenerator.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
@@ -15,8 +16,10 @@
 #include "llvm/IR/DebugInfoMetadata.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/TargetSelect.h"
+#include <optional>
 
 #define DEBUG_TYPE "load-binary"
 
@@ -53,6 +56,7 @@
              "names only. Only work with show-disassembly-only"));
 
 extern cl::opt<bool> ShowDetailedWarning;
+extern cl::opt<bool> InferMissingFrames;
 
 namespace llvm {
 namespace sampleprof {
@@ -87,7 +91,7 @@
   ContextTrieNode *CurrNode = &RootContext;
   ContextTrieNode *PrevNode = nullptr;
 
-  Optional<uint32_t> Size;
+  std::optional<uint32_t> Size;
 
   // Start from top-level context-less function, traverse down the reverse
   // context trie to find the best/longest match for given context, then
@@ -97,7 +101,7 @@
     PrevNode = CurrNode;
     CurrNode = CurrNode->getChildContext(CallSiteLoc, Node->getFuncName());
     if (CurrNode && CurrNode->getFunctionSize())
-      Size = CurrNode->getFunctionSize().value();
+      Size = *CurrNode->getFunctionSize();
     CallSiteLoc = Node->getCallSiteLoc();
     Node = Node->getParentContext();
   }
@@ -111,12 +115,12 @@
     while (!Size && CurrNode && !CurrNode->getAllChildContext().empty()) {
       CurrNode = &CurrNode->getAllChildContext().begin()->second;
       if (CurrNode->getFunctionSize())
-        Size = CurrNode->getFunctionSize().value();
+        Size = *CurrNode->getFunctionSize();
     }
   }
 
   assert(Size && "We should at least find one context size.");
-  return Size.value();
+  return *Size;
 }
 
 void BinarySizeContextTracker::trackInlineesOptimizedAway(
@@ -158,6 +162,20 @@
   ProbeContext.pop_back();
 }
 
+ProfiledBinary::ProfiledBinary(const StringRef ExeBinPath,
+                             const StringRef DebugBinPath)
+    : Path(ExeBinPath), DebugBinaryPath(DebugBinPath), ProEpilogTracker(this),
+      TrackFuncContextSize(EnableCSPreInliner && UseContextCostForPreInliner) {
+  // Point to executable binary if debug info binary is not specified.
+  SymbolizerPath = DebugBinPath.empty() ? ExeBinPath : DebugBinPath;
+  setupSymbolizer();
+  if (InferMissingFrames)
+    MissingContextInferrer = std::make_unique<MissingFrameInferrer>(this);
+  load();
+}
+
+ProfiledBinary::~ProfiledBinary() {}
+
 void ProfiledBinary::warnNoFuncEntry() {
   uint64_t NoFuncEntryNum = 0;
   for (auto &F : BinaryFunctions) {
@@ -165,7 +183,7 @@
       continue;
     bool hasFuncEntry = false;
     for (auto &R : F.second.Ranges) {
-      if (FuncRange *FR = findFuncRangeForStartOffset(R.first)) {
+      if (FuncRange *FR = findFuncRangeForStartAddr(R.first)) {
         if (FR->IsFuncEntry) {
           hasFuncEntry = true;
           break;
@@ -204,11 +222,6 @@
   // Find the preferred load address for text sections.
   setPreferredTextSegmentAddresses(Obj);
 
-  checkPseudoProbe(Obj);
-
-  if (ShowDisassemblyOnly)
-    decodePseudoProbe(Obj);
-
   // Load debug info of subprograms from DWARF section.
   // If path of debug info binary is specified, use the debug info from it,
   // otherwise use the debug info from the executable binary.
@@ -220,12 +233,23 @@
     loadSymbolsFromDWARF(*cast<ObjectFile>(&ExeBinary));
   }
 
+  DisassembleFunctionSet.insert(DisassembleFunctions.begin(),
+                                DisassembleFunctions.end());
+
+  checkPseudoProbe(Obj);
+
+  if (UsePseudoProbes)
+    populateElfSymbolAddressList(Obj);
+
+  if (ShowDisassemblyOnly)
+    decodePseudoProbe(Obj);
+
   // Disassemble the text sections.
   disassemble(Obj);
 
   // Use function start and return address to infer prolog and epilog
-  ProEpilogTracker.inferPrologOffsets(StartOffset2FuncRangeMap);
-  ProEpilogTracker.inferEpilogOffsets(RetOffsets);
+  ProEpilogTracker.inferPrologAddresses(StartAddrToFuncRangeMap);
+  ProEpilogTracker.inferEpilogAddresses(RetAddressSet);
 
   warnNoFuncEntry();
 
@@ -233,10 +257,10 @@
 }
 
 bool ProfiledBinary::inlineContextEqual(uint64_t Address1, uint64_t Address2) {
-  uint64_t Offset1 = virtualAddrToOffset(Address1);
-  uint64_t Offset2 = virtualAddrToOffset(Address2);
-  const SampleContextFrameVector &Context1 = getFrameLocationStack(Offset1);
-  const SampleContextFrameVector &Context2 = getFrameLocationStack(Offset2);
+  const SampleContextFrameVector &Context1 =
+      getCachedFrameLocationStack(Address1);
+  const SampleContextFrameVector &Context2 =
+      getCachedFrameLocationStack(Address2);
   if (Context1.size() != Context2.size())
     return false;
   if (Context1.empty())
@@ -255,9 +279,8 @@
     return ContextVec;
   // Process from frame root to leaf
   for (auto Address : Stack) {
-    uint64_t Offset = virtualAddrToOffset(Address);
     const SampleContextFrameVector &ExpandedContext =
-        getFrameLocationStack(Offset);
+        getCachedFrameLocationStack(Address);
     // An instruction without a valid debug line will be ignored by sample
     // processing
     if (ExpandedContext.empty())
@@ -353,10 +376,31 @@
   if (!UsePseudoProbes)
     return;
 
-  std::unordered_set<uint64_t> ProfiledGuids;
-  if (!ShowDisassemblyOnly)
-    for (auto *F : ProfiledFunctions)
-      ProfiledGuids.insert(Function::getGUID(F->FuncName));
+  MCPseudoProbeDecoder::Uint64Set GuidFilter;
+  MCPseudoProbeDecoder::Uint64Map FuncStartAddresses;
+  if (ShowDisassemblyOnly) {
+    if (DisassembleFunctionSet.empty()) {
+      FuncStartAddresses = SymbolStartAddrs;
+    } else {
+      for (auto &F : DisassembleFunctionSet) {
+        auto GUID = Function::getGUID(F.first());
+        if (auto StartAddr = SymbolStartAddrs.lookup(GUID)) {
+          FuncStartAddresses[GUID] = StartAddr;
+          FuncRange &Range = StartAddrToFuncRangeMap[StartAddr];
+          GuidFilter.insert(Function::getGUID(Range.getFuncName()));
+        }
+      }
+    }
+  } else {
+    for (auto *F : ProfiledFunctions) {
+      GuidFilter.insert(Function::getGUID(F->FuncName));
+      for (auto &Range : F->Ranges) {
+        auto GUIDs = StartAddrToSymMap.equal_range(Range.first);
+        for (auto I = GUIDs.first; I != GUIDs.second; ++I)
+          FuncStartAddresses[I->second] = I->first;
+      }
+    }
+  }
 
   StringRef FileName = Obj->getFileName();
   for (section_iterator SI = Obj->section_begin(), SE = Obj->section_end();
@@ -375,7 +419,7 @@
       StringRef Contents = unwrapOrError(Section.getContents(), FileName);
       if (!ProbeDecoder.buildAddress2ProbeMap(
               reinterpret_cast<const uint8_t *>(Contents.data()),
-              Contents.size(), ProfiledGuids))
+              Contents.size(), GuidFilter, FuncStartAddresses))
         exitWithError("Pseudo Probe decoder fail in .pseudo_probe section");
     }
   }
@@ -402,10 +446,8 @@
   decodePseudoProbe(Obj);
 }
 
-void ProfiledBinary::setIsFuncEntry(uint64_t Offset, StringRef RangeSymName) {
-  // Note that the start offset of each ELF section can be a non-function
-  // symbol, we need to binary search for the start of a real function range.
-  auto *FuncRange = findFuncRangeForOffset(Offset);
+void ProfiledBinary::setIsFuncEntry(FuncRange *FuncRange,
+                                    StringRef RangeSymName) {
   // Skip external function symbol.
   if (!FuncRange)
     return;
@@ -421,15 +463,13 @@
                                         SectionSymbolsTy &Symbols,
                                         const SectionRef &Section) {
   std::size_t SE = Symbols.size();
-  uint64_t SectionOffset = Section.getAddress() - getPreferredBaseAddress();
+  uint64_t SectionAddress = Section.getAddress();
   uint64_t SectSize = Section.getSize();
-  uint64_t StartOffset = Symbols[SI].Addr - getPreferredBaseAddress();
-  uint64_t NextStartOffset =
-      (SI + 1 < SE) ? Symbols[SI + 1].Addr - getPreferredBaseAddress()
-                    : SectionOffset + SectSize;
-  setIsFuncEntry(StartOffset,
-                 FunctionSamples::getCanonicalFnName(Symbols[SI].Name));
-
+  uint64_t StartAddress = Symbols[SI].Addr;
+  uint64_t NextStartAddress =
+      (SI + 1 < SE) ? Symbols[SI + 1].Addr : SectionAddress + SectSize;
+  FuncRange *FRange = findFuncRange(StartAddress);
+  setIsFuncEntry(FRange, FunctionSamples::getCanonicalFnName(Symbols[SI].Name));
   StringRef SymbolName =
       ShowCanonicalFnName
           ? FunctionSamples::getCanonicalFnName(Symbols[SI].Name)
@@ -446,36 +486,34 @@
                          << format("%8" PRIx64, End) << "\n";
   };
 
-  uint64_t Offset = StartOffset;
-  // Size of a consecutive invalid instruction range starting from Offset -1
+  uint64_t Address = StartAddress;
+  // Size of a consecutive invalid instruction range starting from Address -1
   // backwards.
   uint64_t InvalidInstLength = 0;
-  while (Offset < NextStartOffset) {
+  while (Address < NextStartAddress) {
     MCInst Inst;
     uint64_t Size;
     // Disassemble an instruction.
-    bool Disassembled =
-        DisAsm->getInstruction(Inst, Size, Bytes.slice(Offset - SectionOffset),
-                               Offset + getPreferredBaseAddress(), nulls());
+    bool Disassembled = DisAsm->getInstruction(
+        Inst, Size, Bytes.slice(Address - SectionAddress), Address, nulls());
     if (Size == 0)
       Size = 1;
 
     if (ShowDisassembly) {
       if (ShowPseudoProbe) {
-        ProbeDecoder.printProbeForAddress(outs(),
-                                          Offset + getPreferredBaseAddress());
+        ProbeDecoder.printProbeForAddress(outs(), Address);
       }
-      outs() << format("%8" PRIx64 ":", Offset + getPreferredBaseAddress());
+      outs() << format("%8" PRIx64 ":", Address);
       size_t Start = outs().tell();
       if (Disassembled)
-        IPrinter->printInst(&Inst, Offset + Size, "", *STI.get(), outs());
+        IPrinter->printInst(&Inst, Address + Size, "", *STI.get(), outs());
       else
         outs() << "\t<unknown>";
       if (ShowSourceLocations) {
         unsigned Cur = outs().tell() - Start;
         if (Cur < 40)
           outs().indent(40 - Cur);
-        InstructionPointer IP(this, Offset);
+        InstructionPointer IP(this, Address);
         outs() << getReversedLocWithContext(
             symbolize(IP, ShowCanonicalFnName, ShowPseudoProbe));
       }
@@ -486,35 +524,72 @@
       const MCInstrDesc &MCDesc = MII->get(Inst.getOpcode());
 
       // Record instruction size.
-      Offset2InstSizeMap[Offset] = Size;
+      AddressToInstSizeMap[Address] = Size;
 
       // Populate address maps.
-      CodeAddrOffsets.push_back(Offset);
+      CodeAddressVec.push_back(Address);
       if (MCDesc.isCall()) {
-        CallOffsets.insert(Offset);
-        UncondBranchOffsets.insert(Offset);
+        CallAddressSet.insert(Address);
+        UncondBranchAddrSet.insert(Address);
       } else if (MCDesc.isReturn()) {
-        RetOffsets.insert(Offset);
-        UncondBranchOffsets.insert(Offset);
+        RetAddressSet.insert(Address);
+        UncondBranchAddrSet.insert(Address);
       } else if (MCDesc.isBranch()) {
         if (MCDesc.isUnconditionalBranch())
-          UncondBranchOffsets.insert(Offset);
-        BranchOffsets.insert(Offset);
+          UncondBranchAddrSet.insert(Address);
+        BranchAddressSet.insert(Address);
+      }
+
+      // Record potential call targets for tail frame inference later-on.
+      if (InferMissingFrames && FRange) {
+        uint64_t Target = 0;
+        MIA->evaluateBranch(Inst, Address, Size, Target);
+        if (MCDesc.isCall()) {
+          // Indirect call targets are unknown at this point. Recording the
+          // unknown target (zero) for further LBR-based refinement.
+          MissingContextInferrer->CallEdges[Address].insert(Target);
+        } else if (MCDesc.isUnconditionalBranch()) {
+          assert(Target &&
+                 "target should be known for unconditional direct branch");
+          // Any inter-function unconditional jump is considered tail call at
+          // this point. This is not 100% accurate and could further be
+          // optimized based on some source annotation.
+          FuncRange *ToFRange = findFuncRange(Target);
+          if (ToFRange && ToFRange->Func != FRange->Func)
+            MissingContextInferrer->TailCallEdges[Address].insert(Target);
+          LLVM_DEBUG({
+            dbgs() << "Direct Tail call: " << format("%8" PRIx64 ":", Address);
+            IPrinter->printInst(&Inst, Address + Size, "", *STI.get(), dbgs());
+            dbgs() << "\n";
+          });
+        } else if (MCDesc.isIndirectBranch() && MCDesc.isBarrier()) {
+          // This is an indirect branch but not necessarily an indirect tail
+          // call. The isBarrier check is to filter out conditional branch.
+          // Similar with indirect call targets, recording the unknown target
+          // (zero) for further LBR-based refinement.
+          MissingContextInferrer->TailCallEdges[Address].insert(Target);
+          LLVM_DEBUG({
+            dbgs() << "Indirect Tail call: "
+                   << format("%8" PRIx64 ":", Address);
+            IPrinter->printInst(&Inst, Address + Size, "", *STI.get(), dbgs());
+            dbgs() << "\n";
+          });
+        }
       }
 
       if (InvalidInstLength) {
-        WarnInvalidInsts(Offset - InvalidInstLength, Offset - 1);
+        WarnInvalidInsts(Address - InvalidInstLength, Address - 1);
         InvalidInstLength = 0;
       }
     } else {
       InvalidInstLength += Size;
     }
 
-    Offset += Size;
+    Address += Size;
   }
 
   if (InvalidInstLength)
-    WarnInvalidInsts(Offset - InvalidInstLength, Offset - 1);
+    WarnInvalidInsts(Address - InvalidInstLength, Address - 1);
 
   if (ShowDisassembly)
     outs() << "\n";
@@ -536,9 +611,11 @@
   if (!AsmInfo)
     exitWithError("no assembly info for target " + TripleName, FileName);
 
-  SubtargetFeatures Features = Obj->getFeatures();
+  Expected<SubtargetFeatures> Features = Obj->getFeatures();
+  if (!Features)
+    exitWithError(Features.takeError(), FileName);
   STI.reset(
-      TheTarget->createMCSubtargetInfo(TripleName, "", Features.getString()));
+      TheTarget->createMCSubtargetInfo(TripleName, "", Features->getString()));
   if (!STI)
     exitWithError("no subtarget info for target " + TripleName, FileName);
 
@@ -582,8 +659,6 @@
   for (std::pair<const SectionRef, SectionSymbolsTy> &SecSyms : AllSymbols)
     stable_sort(SecSyms.second);
 
-  DisassembleFunctionSet.insert(DisassembleFunctions.begin(),
-                                DisassembleFunctions.end());
   assert((DisassembleFunctionSet.empty() || ShowDisassemblyOnly) &&
          "Functions to disassemble should be only specified together with "
          "--show-disassembly-only");
@@ -599,13 +674,13 @@
       continue;
 
     uint64_t ImageLoadAddr = getPreferredBaseAddress();
-    uint64_t SectionOffset = Section.getAddress() - ImageLoadAddr;
+    uint64_t SectionAddress = Section.getAddress() - ImageLoadAddr;
     uint64_t SectSize = Section.getSize();
     if (!SectSize)
       continue;
 
     // Register the text section.
-    TextSections.insert({SectionOffset, SectSize});
+    TextSections.insert({SectionAddress, SectSize});
 
     StringRef SectionName = unwrapOrError(Section.getName(), FileName);
 
@@ -657,6 +732,20 @@
   }
 }
 
+void ProfiledBinary::populateElfSymbolAddressList(
+    const ELFObjectFileBase *Obj) {
+  // Create a mapping from virtual address to symbol GUID and the other way
+  // around.
+  StringRef FileName = Obj->getFileName();
+  for (const SymbolRef &Symbol : Obj->symbols()) {
+    const uint64_t Addr = unwrapOrError(Symbol.getAddress(), FileName);
+    const StringRef Name = unwrapOrError(Symbol.getName(), FileName);
+    uint64_t GUID = Function::getGUID(Name);
+    SymbolStartAddrs[GUID] = Addr;
+    StartAddrToSymMap.emplace(Addr, GUID);
+  }
+}
+
 void ProfiledBinary::loadSymbolsFromDWARFUnit(DWARFUnit &CompilationUnit) {
   for (const auto &DieInfo : CompilationUnit.dies()) {
     llvm::DWARFDie Die(&CompilationUnit, &DieInfo);
@@ -685,30 +774,28 @@
       Func.FuncName = Ret.first->first;
 
     for (const auto &Range : Ranges) {
-      uint64_t FuncStart = Range.LowPC;
-      uint64_t FuncSize = Range.HighPC - FuncStart;
+      uint64_t StartAddress = Range.LowPC;
+      uint64_t EndAddress = Range.HighPC;
 
-      if (FuncSize == 0 || FuncStart < getPreferredBaseAddress())
+      if (EndAddress <= StartAddress ||
+          StartAddress < getPreferredBaseAddress())
         continue;
 
-      uint64_t StartOffset = FuncStart - getPreferredBaseAddress();
-      uint64_t EndOffset = Range.HighPC - getPreferredBaseAddress();
-
       // We may want to know all ranges for one function. Here group the
       // ranges and store them into BinaryFunction.
-      Func.Ranges.emplace_back(StartOffset, EndOffset);
+      Func.Ranges.emplace_back(StartAddress, EndAddress);
 
-      auto R = StartOffset2FuncRangeMap.emplace(StartOffset, FuncRange());
+      auto R = StartAddrToFuncRangeMap.emplace(StartAddress, FuncRange());
       if (R.second) {
         FuncRange &FRange = R.first->second;
         FRange.Func = &Func;
-        FRange.StartOffset = StartOffset;
-        FRange.EndOffset = EndOffset;
+        FRange.StartAddress = StartAddress;
+        FRange.EndAddress = EndAddress;
       } else {
         WithColor::warning()
             << "Duplicated symbol start address at "
-            << format("%8" PRIx64, StartOffset + getPreferredBaseAddress())
-            << " " << R.first->second.getFuncName() << " and " << Name << "\n";
+            << format("%8" PRIx64, StartAddress) << " "
+            << R.first->second.getFuncName() << " and " << Name << "\n";
       }
     }
   }
@@ -726,7 +813,7 @@
   // Handles DWO sections that can either be in .o, .dwo or .dwp files.
   for (const auto &CompilationUnit : DebugContext->compile_units()) {
     DWARFUnit *const DwarfUnit = CompilationUnit.get();
-    if (llvm::Optional<uint64_t> DWOId = DwarfUnit->getDWOId()) {
+    if (std::optional<uint64_t> DWOId = DwarfUnit->getDWOId()) {
       DWARFUnit *DWOCU = DwarfUnit->getNonSkeletonUnitDIE(false).getDwarfUnit();
       if (!DWOCU->isDWOUnit()) {
         std::string DWOName = dwarf::toString(
@@ -749,7 +836,7 @@
 
 void ProfiledBinary::populateSymbolListFromDWARF(
     ProfileSymbolList &SymbolList) {
-  for (auto &I : StartOffset2FuncRangeMap)
+  for (auto &I : StartAddrToFuncRangeMap)
     SymbolList.add(I.second.getFuncName());
 }
 
@@ -770,7 +857,7 @@
                                                    bool UseProbeDiscriminator) {
   assert(this == IP.Binary &&
          "Binary should only symbolize its own instruction");
-  auto Addr = object::SectionedAddress{IP.Offset + getPreferredBaseAddress(),
+  auto Addr = object::SectionedAddress{IP.Address,
                                        object::SectionedAddress::UndefSection};
   DIInliningInfo InlineStack = unwrapOrError(
       Symbolizer->symbolizeInlinedCode(SymbolizerPath.str(), Addr),
@@ -802,10 +889,8 @@
   return CallStack;
 }
 
-void ProfiledBinary::computeInlinedContextSizeForRange(uint64_t StartOffset,
-                                                       uint64_t EndOffset) {
-  uint64_t RangeBegin = offsetToVirtualAddr(StartOffset);
-  uint64_t RangeEnd = offsetToVirtualAddr(EndOffset);
+void ProfiledBinary::computeInlinedContextSizeForRange(uint64_t RangeBegin,
+                                                       uint64_t RangeEnd) {
   InstructionPointer IP(this, RangeBegin, true);
 
   if (IP.Address != RangeBegin)
@@ -816,11 +901,9 @@
     return;
 
   do {
-    uint64_t Offset = virtualAddrToOffset(IP.Address);
-    const SampleContextFrameVector &SymbolizedCallStack =
-        getFrameLocationStack(Offset, UsePseudoProbes);
-    uint64_t Size = Offset2InstSizeMap[Offset];
-
+    const SampleContextFrameVector SymbolizedCallStack =
+        getFrameLocationStack(IP.Address, UsePseudoProbes);
+    uint64_t Size = AddressToInstSizeMap[IP.Address];
     // Record instruction size for the corresponding context
     FuncSizeTracker.addInstructionForContext(SymbolizedCallStack, Size);
 
@@ -846,6 +929,12 @@
   }
 }
 
+void ProfiledBinary::inferMissingFrames(
+    const SmallVectorImpl<uint64_t> &Context,
+    SmallVectorImpl<uint64_t> &NewContext) {
+  MissingContextInferrer->inferMissingFrames(Context, NewContext);
+}
+
 InstructionPointer::InstructionPointer(const ProfiledBinary *Binary,
                                        uint64_t Address, bool RoundToNext)
     : Binary(Binary), Address(Address) {
@@ -853,7 +942,7 @@
   if (RoundToNext) {
     // we might get address which is not the code
     // it should round to the next valid address
-    if (Index >= Binary->getCodeOffsetsSize())
+    if (Index >= Binary->getCodeAddrVecSize())
       this->Address = UINT64_MAX;
     else
       this->Address = Binary->getAddressforIndex(Index);
@@ -862,7 +951,7 @@
 
 bool InstructionPointer::advance() {
   Index++;
-  if (Index >= Binary->getCodeOffsetsSize()) {
+  if (Index >= Binary->getCodeAddrVecSize()) {
     Address = UINT64_MAX;
     return false;
   }
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h
index c099316..cdbaec7 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h
+++ b/src/llvm-project/llvm/tools/llvm-profgen/ProfiledBinary.h
@@ -11,7 +11,7 @@
 
 #include "CallContext.h"
 #include "ErrorHandling.h"
-#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
@@ -53,15 +53,12 @@
 namespace sampleprof {
 
 class ProfiledBinary;
+class MissingFrameInferrer;
 
 struct InstructionPointer {
   const ProfiledBinary *Binary;
-  union {
-    // Offset of the executable segment of the binary.
-    uint64_t Offset = 0;
-    // Also used as address in unwinder
-    uint64_t Address;
-  };
+  // Address of the executable segment of the binary.
+  uint64_t Address;
   // Index to the sorted code address array of the binary.
   uint64_t Index = 0;
   InstructionPointer(const ProfiledBinary *Binary, uint64_t Address,
@@ -100,46 +97,47 @@
 // Info about function range. A function can be split into multiple
 // non-continuous ranges, each range corresponds to one FuncRange.
 struct FuncRange {
-  uint64_t StartOffset;
-  // EndOffset is an exclusive bound.
-  uint64_t EndOffset;
+  uint64_t StartAddress;
+  // EndAddress is an exclusive bound.
+  uint64_t EndAddress;
   // Function the range belongs to
   BinaryFunction *Func;
-  // Whether the start offset is the real entry of the function.
+  // Whether the start address is the real entry of the function.
   bool IsFuncEntry = false;
 
   StringRef getFuncName() { return Func->FuncName; }
 };
 
-// PrologEpilog offset tracker, used to filter out broken stack samples
+// PrologEpilog address tracker, used to filter out broken stack samples
 // Currently we use a heuristic size (two) to infer prolog and epilog
 // based on the start address and return address. In the future,
 // we will switch to Dwarf CFI based tracker
 struct PrologEpilogTracker {
-  // A set of prolog and epilog offsets. Used by virtual unwinding.
+  // A set of prolog and epilog addresses. Used by virtual unwinding.
   std::unordered_set<uint64_t> PrologEpilogSet;
   ProfiledBinary *Binary;
   PrologEpilogTracker(ProfiledBinary *Bin) : Binary(Bin){};
 
   // Take the two addresses from the start of function as prolog
-  void inferPrologOffsets(std::map<uint64_t, FuncRange> &FuncStartOffsetMap) {
-    for (auto I : FuncStartOffsetMap) {
+  void
+  inferPrologAddresses(std::map<uint64_t, FuncRange> &FuncStartAddressMap) {
+    for (auto I : FuncStartAddressMap) {
       PrologEpilogSet.insert(I.first);
       InstructionPointer IP(Binary, I.first);
       if (!IP.advance())
         break;
-      PrologEpilogSet.insert(IP.Offset);
+      PrologEpilogSet.insert(IP.Address);
     }
   }
 
   // Take the last two addresses before the return address as epilog
-  void inferEpilogOffsets(std::unordered_set<uint64_t> &RetAddrs) {
+  void inferEpilogAddresses(std::unordered_set<uint64_t> &RetAddrs) {
     for (auto Addr : RetAddrs) {
       PrologEpilogSet.insert(Addr);
       InstructionPointer IP(Binary, Addr);
       if (!IP.backward())
         break;
-      PrologEpilogSet.insert(IP.Offset);
+      PrologEpilogSet.insert(IP.Address);
     }
   }
 };
@@ -169,8 +167,8 @@
 
   using ProbeFrameStack = SmallVector<std::pair<StringRef, uint32_t>>;
   void trackInlineesOptimizedAway(MCPseudoProbeDecoder &ProbeDecoder,
-                              MCDecodedPseudoProbeInlineTree &ProbeNode,
-                              ProbeFrameStack &Context);
+                                  MCDecodedPseudoProbeInlineTree &ProbeNode,
+                                  ProbeFrameStack &Context);
 
   void dump() { RootContext.dumpTree(); }
 
@@ -183,7 +181,7 @@
   ContextTrieNode RootContext;
 };
 
-using OffsetRange = std::pair<uint64_t, uint64_t>;
+using AddressRange = std::pair<uint64_t, uint64_t>;
 
 class ProfiledBinary {
   // Absolute path of the executable binary.
@@ -221,32 +219,42 @@
   // A list of binary functions that have samples.
   std::unordered_set<const BinaryFunction *> ProfiledFunctions;
 
-  // An ordered map of mapping function's start offset to function range
+  // GUID to Elf symbol start address map
+  DenseMap<uint64_t, uint64_t> SymbolStartAddrs;
+
+  // Start address to Elf symbol GUID map
+  std::unordered_multimap<uint64_t, uint64_t> StartAddrToSymMap;
+
+  // An ordered map of mapping function's start address to function range
   // relevant info. Currently to determine if the offset of ELF is the start of
   // a real function, we leverage the function range info from DWARF.
-  std::map<uint64_t, FuncRange> StartOffset2FuncRangeMap;
+  std::map<uint64_t, FuncRange> StartAddrToFuncRangeMap;
 
-  // Offset to context location map. Used to expand the context.
-  std::unordered_map<uint64_t, SampleContextFrameVector> Offset2LocStackMap;
+  // Address to context location map. Used to expand the context.
+  std::unordered_map<uint64_t, SampleContextFrameVector> AddressToLocStackMap;
 
-  // Offset to instruction size map. Also used for quick offset lookup.
-  std::unordered_map<uint64_t, uint64_t> Offset2InstSizeMap;
+  // Address to instruction size map. Also used for quick Address lookup.
+  std::unordered_map<uint64_t, uint64_t> AddressToInstSizeMap;
 
-  // An array of offsets of all instructions sorted in increasing order. The
+  // An array of Addresses of all instructions sorted in increasing order. The
   // sorting is needed to fast advance to the next forward/backward instruction.
-  std::vector<uint64_t> CodeAddrOffsets;
-  // A set of call instruction offsets. Used by virtual unwinding.
-  std::unordered_set<uint64_t> CallOffsets;
-  // A set of return instruction offsets. Used by virtual unwinding.
-  std::unordered_set<uint64_t> RetOffsets;
-  // An ordered set of unconditional branch instruction offsets.
-  std::set<uint64_t> UncondBranchOffsets;
-  // A set of branch instruction offsets.
-  std::unordered_set<uint64_t> BranchOffsets;
+  std::vector<uint64_t> CodeAddressVec;
+  // A set of call instruction addresses. Used by virtual unwinding.
+  std::unordered_set<uint64_t> CallAddressSet;
+  // A set of return instruction addresses. Used by virtual unwinding.
+  std::unordered_set<uint64_t> RetAddressSet;
+  // An ordered set of unconditional branch instruction addresses.
+  std::set<uint64_t> UncondBranchAddrSet;
+  // A set of branch instruction addresses.
+  std::unordered_set<uint64_t> BranchAddressSet;
 
   // Estimate and track function prolog and epilog ranges.
   PrologEpilogTracker ProEpilogTracker;
 
+  // Infer missing frames due to compiler optimizations such as tail call
+  // elimination.
+  std::unique_ptr<MissingFrameInferrer> MissingContextInferrer;
+
   // Track function sizes under different context
   BinarySizeContextTracker FuncSizeTracker;
 
@@ -281,7 +289,8 @@
   void setPreferredTextSegmentAddresses(const ELFObjectFileBase *O);
 
   template <class ELFT>
-  void setPreferredTextSegmentAddresses(const ELFFile<ELFT> &Obj, StringRef FileName);
+  void setPreferredTextSegmentAddresses(const ELFFile<ELFT> &Obj,
+                                        StringRef FileName);
 
   void checkPseudoProbe(const ELFObjectFileBase *Obj);
 
@@ -301,10 +310,13 @@
   // Load debug info from DWARF unit.
   void loadSymbolsFromDWARFUnit(DWARFUnit &CompilationUnit);
 
+  // Create elf symbol to its start address mapping.
+  void populateElfSymbolAddressList(const ELFObjectFileBase *O);
+
   // A function may be spilt into multiple non-continuous address ranges. We use
-  // this to set whether start offset of a function is the real entry of the
+  // this to set whether start a function range is the real entry of the
   // function and also set false to the non-function label.
-  void setIsFuncEntry(uint64_t Offset, StringRef RangeSymName);
+  void setIsFuncEntry(FuncRange *FRange, StringRef RangeSymName);
 
   // Warn if no entry range exists in the function.
   void warnNoFuncEntry();
@@ -329,31 +341,24 @@
   void load();
 
 public:
-  ProfiledBinary(const StringRef ExeBinPath, const StringRef DebugBinPath)
-      : Path(ExeBinPath), DebugBinaryPath(DebugBinPath), ProEpilogTracker(this),
-        TrackFuncContextSize(EnableCSPreInliner &&
-                             UseContextCostForPreInliner) {
-    // Point to executable binary if debug info binary is not specified.
-    SymbolizerPath = DebugBinPath.empty() ? ExeBinPath : DebugBinPath;
-    setupSymbolizer();
-    load();
-  }
+  ProfiledBinary(const StringRef ExeBinPath, const StringRef DebugBinPath);
+  ~ProfiledBinary();
 
   void decodePseudoProbe();
 
-  uint64_t virtualAddrToOffset(uint64_t VirtualAddress) const {
-    return VirtualAddress - BaseAddress;
-  }
-  uint64_t offsetToVirtualAddr(uint64_t Offset) const {
-    return Offset + BaseAddress;
-  }
   StringRef getPath() const { return Path; }
   StringRef getName() const { return llvm::sys::path::filename(Path); }
   uint64_t getBaseAddress() const { return BaseAddress; }
   void setBaseAddress(uint64_t Address) { BaseAddress = Address; }
 
+  // Canonicalize to use preferred load address as base address.
+  uint64_t canonicalizeVirtualAddress(uint64_t Address) {
+    return Address - BaseAddress + getPreferredBaseAddress();
+  }
   // Return the preferred load address for the first executable segment.
-  uint64_t getPreferredBaseAddress() const { return PreferredTextSegmentAddresses[0]; }
+  uint64_t getPreferredBaseAddress() const {
+    return PreferredTextSegmentAddresses[0];
+  }
   // Return the preferred load address for the first loadable segment.
   uint64_t getFirstLoadableAddress() const { return FirstLoadableAddress; }
   // Return the file offset for the first executable segment.
@@ -365,64 +370,54 @@
     return TextSegmentOffsets;
   }
 
-  uint64_t getInstSize(uint64_t Offset) const {
-    auto I = Offset2InstSizeMap.find(Offset);
-    if (I == Offset2InstSizeMap.end())
+  uint64_t getInstSize(uint64_t Address) const {
+    auto I = AddressToInstSizeMap.find(Address);
+    if (I == AddressToInstSizeMap.end())
       return 0;
     return I->second;
   }
 
-  bool offsetIsCode(uint64_t Offset) const {
-    return Offset2InstSizeMap.find(Offset) != Offset2InstSizeMap.end();
-  }
   bool addressIsCode(uint64_t Address) const {
-    uint64_t Offset = virtualAddrToOffset(Address);
-    return offsetIsCode(Offset);
-  }
-  bool addressIsCall(uint64_t Address) const {
-    uint64_t Offset = virtualAddrToOffset(Address);
-    return CallOffsets.count(Offset);
-  }
-  bool addressIsReturn(uint64_t Address) const {
-    uint64_t Offset = virtualAddrToOffset(Address);
-    return RetOffsets.count(Offset);
-  }
-  bool addressInPrologEpilog(uint64_t Address) const {
-    uint64_t Offset = virtualAddrToOffset(Address);
-    return ProEpilogTracker.PrologEpilogSet.count(Offset);
+    return AddressToInstSizeMap.find(Address) != AddressToInstSizeMap.end();
   }
 
-  bool offsetIsTransfer(uint64_t Offset) {
-    return BranchOffsets.count(Offset) || RetOffsets.count(Offset) ||
-           CallOffsets.count(Offset);
+  bool addressIsCall(uint64_t Address) const {
+    return CallAddressSet.count(Address);
+  }
+  bool addressIsReturn(uint64_t Address) const {
+    return RetAddressSet.count(Address);
+  }
+  bool addressInPrologEpilog(uint64_t Address) const {
+    return ProEpilogTracker.PrologEpilogSet.count(Address);
+  }
+
+  bool addressIsTransfer(uint64_t Address) {
+    return BranchAddressSet.count(Address) || RetAddressSet.count(Address) ||
+           CallAddressSet.count(Address);
   }
 
   bool rangeCrossUncondBranch(uint64_t Start, uint64_t End) {
     if (Start >= End)
       return false;
-    auto R = UncondBranchOffsets.lower_bound(Start);
-    return R != UncondBranchOffsets.end() && *R < End;
+    auto R = UncondBranchAddrSet.lower_bound(Start);
+    return R != UncondBranchAddrSet.end() && *R < End;
   }
 
   uint64_t getAddressforIndex(uint64_t Index) const {
-    return offsetToVirtualAddr(CodeAddrOffsets[Index]);
+    return CodeAddressVec[Index];
   }
 
-  size_t getCodeOffsetsSize() const { return CodeAddrOffsets.size(); }
+  size_t getCodeAddrVecSize() const { return CodeAddressVec.size(); }
 
   bool usePseudoProbes() const { return UsePseudoProbes; }
   bool useFSDiscriminator() const { return UseFSDiscriminator; }
-  // Get the index in CodeAddrOffsets for the address
+  // Get the index in CodeAddressVec for the address
   // As we might get an address which is not the code
   // here it would round to the next valid code address by
   // using lower bound operation
-  uint32_t getIndexForOffset(uint64_t Offset) const {
-    auto Low = llvm::lower_bound(CodeAddrOffsets, Offset);
-    return Low - CodeAddrOffsets.begin();
-  }
   uint32_t getIndexForAddr(uint64_t Address) const {
-    uint64_t Offset = virtualAddrToOffset(Address);
-    return getIndexForOffset(Offset);
+    auto Low = llvm::lower_bound(CodeAddressVec, Address);
+    return Low - CodeAddressVec.begin();
   }
 
   uint64_t getCallAddrFromFrameAddr(uint64_t FrameAddr) const {
@@ -435,29 +430,29 @@
     return 0;
   }
 
-  FuncRange *findFuncRangeForStartOffset(uint64_t Offset) {
-    auto I = StartOffset2FuncRangeMap.find(Offset);
-    if (I == StartOffset2FuncRangeMap.end())
+  FuncRange *findFuncRangeForStartAddr(uint64_t Address) {
+    auto I = StartAddrToFuncRangeMap.find(Address);
+    if (I == StartAddrToFuncRangeMap.end())
       return nullptr;
     return &I->second;
   }
 
-  // Binary search the function range which includes the input offset.
-  FuncRange *findFuncRangeForOffset(uint64_t Offset) {
-    auto I = StartOffset2FuncRangeMap.upper_bound(Offset);
-    if (I == StartOffset2FuncRangeMap.begin())
+  // Binary search the function range which includes the input address.
+  FuncRange *findFuncRange(uint64_t Address) {
+    auto I = StartAddrToFuncRangeMap.upper_bound(Address);
+    if (I == StartAddrToFuncRangeMap.begin())
       return nullptr;
     I--;
 
-    if (Offset >= I->second.EndOffset)
+    if (Address >= I->second.EndAddress)
       return nullptr;
 
     return &I->second;
   }
 
   // Get all ranges of one function.
-  RangesTy getRangesForOffset(uint64_t Offset) {
-    auto *FRange = findFuncRangeForOffset(Offset);
+  RangesTy getRanges(uint64_t Address) {
+    auto *FRange = findFuncRange(Address);
     // Ignore the range which falls into plt section or system lib.
     if (!FRange)
       return RangesTy();
@@ -489,21 +484,30 @@
     return FuncSizeTracker.getFuncSizeForContext(ContextNode);
   }
 
+  void inferMissingFrames(const SmallVectorImpl<uint64_t> &Context,
+                          SmallVectorImpl<uint64_t> &NewContext);
+
   // Load the symbols from debug table and populate into symbol list.
   void populateSymbolListFromDWARF(ProfileSymbolList &SymbolList);
 
+  SampleContextFrameVector
+  getFrameLocationStack(uint64_t Address, bool UseProbeDiscriminator = false) {
+    InstructionPointer IP(this, Address);
+    return symbolize(IP, true, UseProbeDiscriminator);
+  }
+
   const SampleContextFrameVector &
-  getFrameLocationStack(uint64_t Offset, bool UseProbeDiscriminator = false) {
-    auto I = Offset2LocStackMap.emplace(Offset, SampleContextFrameVector());
+  getCachedFrameLocationStack(uint64_t Address,
+                              bool UseProbeDiscriminator = false) {
+    auto I = AddressToLocStackMap.emplace(Address, SampleContextFrameVector());
     if (I.second) {
-      InstructionPointer IP(this, Offset);
-      I.first->second = symbolize(IP, true, UseProbeDiscriminator);
+      I.first->second = getFrameLocationStack(Address, UseProbeDiscriminator);
     }
     return I.first->second;
   }
 
-  Optional<SampleContextFrame> getInlineLeafFrameLoc(uint64_t Offset) {
-    const auto &Stack = getFrameLocationStack(Offset);
+  std::optional<SampleContextFrame> getInlineLeafFrameLoc(uint64_t Address) {
+    const auto &Stack = getCachedFrameLocationStack(Address);
     if (Stack.empty())
       return {};
     return Stack.back();
@@ -511,19 +515,23 @@
 
   void flushSymbolizer() { Symbolizer.reset(); }
 
+  MissingFrameInferrer* getMissingContextInferrer() {
+    return MissingContextInferrer.get();
+  }
+
   // Compare two addresses' inline context
   bool inlineContextEqual(uint64_t Add1, uint64_t Add2);
 
   // Get the full context of the current stack with inline context filled in.
-  // It will search the disassembling info stored in Offset2LocStackMap. This is
-  // used as the key of function sample map
+  // It will search the disassembling info stored in AddressToLocStackMap. This
+  // is used as the key of function sample map
   SampleContextFrameVector
   getExpandedContext(const SmallVectorImpl<uint64_t> &Stack,
                      bool &WasLeafInlined);
   // Go through instructions among the given range and record its size for the
   // inline context.
-  void computeInlinedContextSizeForRange(uint64_t StartOffset,
-                                         uint64_t EndOffset);
+  void computeInlinedContextSizeForRange(uint64_t StartAddress,
+                                         uint64_t EndAddress);
 
   void computeInlinedContextSizeForFunc(const BinaryFunction *Func);
 
diff --git a/src/llvm-project/llvm/tools/llvm-profgen/llvm-profgen.cpp b/src/llvm-project/llvm/tools/llvm-profgen/llvm-profgen.cpp
index 8b12c2f..596882c 100644
--- a/src/llvm-project/llvm/tools/llvm-profgen/llvm-profgen.cpp
+++ b/src/llvm-project/llvm/tools/llvm-profgen/llvm-profgen.cpp
@@ -24,7 +24,6 @@
 
 static cl::opt<std::string> PerfScriptFilename(
     "perfscript", cl::value_desc("perfscript"),
-    llvm::cl::MiscFlags::CommaSeparated,
     cl::desc("Path of perf-script trace created by Linux perf tool with "
              "`script` command(the raw perf.data should be profiled with -b)"),
     cl::cat(ProfGenCategory));
@@ -32,7 +31,7 @@
                      cl::aliasopt(PerfScriptFilename));
 
 static cl::opt<std::string> PerfDataFilename(
-    "perfdata", cl::value_desc("perfdata"), llvm::cl::MiscFlags::CommaSeparated,
+    "perfdata", cl::value_desc("perfdata"),
     cl::desc("Path of raw perf data created by Linux perf tool (it should be "
              "profiled with -b)"),
     cl::cat(ProfGenCategory));
@@ -41,7 +40,6 @@
 
 static cl::opt<std::string> UnsymbolizedProfFilename(
     "unsymbolized-profile", cl::value_desc("unsymbolized profile"),
-    llvm::cl::MiscFlags::CommaSeparated,
     cl::desc("Path of the unsymbolized profile created by "
              "`llvm-profgen` with `--skip-symbolization`"),
     cl::cat(ProfGenCategory));
@@ -80,11 +78,11 @@
   // Allow the missing perfscript if we only use to show binary disassembly.
   if (!ShowDisassemblyOnly) {
     // Validate input profile is provided only once
-    uint16_t HasPerfData = PerfDataFilename.getNumOccurrences();
-    uint16_t HasPerfScript = PerfScriptFilename.getNumOccurrences();
-    uint16_t HasUnsymbolizedProfile =
-        UnsymbolizedProfFilename.getNumOccurrences();
-    uint16_t HasSampleProfile = SampleProfFilename.getNumOccurrences();
+    bool HasPerfData = PerfDataFilename.getNumOccurrences() > 0;
+    bool HasPerfScript = PerfScriptFilename.getNumOccurrences() > 0;
+    bool HasUnsymbolizedProfile =
+        UnsymbolizedProfFilename.getNumOccurrences() > 0;
+    bool HasSampleProfile = SampleProfFilename.getNumOccurrences() > 0;
     uint16_t S =
         HasPerfData + HasPerfScript + HasUnsymbolizedProfile + HasSampleProfile;
     if (S != 1) {
@@ -169,7 +167,7 @@
     Generator->generateProfile();
     Generator->write();
   } else {
-    Optional<uint32_t> PIDFilter;
+    std::optional<uint32_t> PIDFilter;
     if (ProcessId.getNumOccurrences())
       PIDFilter = ProcessId;
     PerfInputFile PerfFile = getPerfInputFile();
diff --git a/src/llvm-project/llvm/tools/llvm-rc/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-rc/CMakeLists.txt
index 71b7994..9fddba8 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-rc/CMakeLists.txt
@@ -2,6 +2,7 @@
   Object
   Option
   Support
+  TargetParser
   )
 
 set(LLVM_TARGET_DEFINITIONS Opts.td)
@@ -19,6 +20,9 @@
   ResourceScriptParser.cpp
   ResourceScriptStmt.cpp
   ResourceScriptToken.cpp
+  DEPENDS
+  WindresOptsTableGen
+  GENERATE_DRIVER
   )
 
 add_llvm_tool_symlink(llvm-windres llvm-rc)
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h b/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h
index 0f3d593..7a92f84 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceFileWriter.h
@@ -79,8 +79,8 @@
     uint32_t Characteristics;
     uint32_t VersionInfo;
 
-    Optional<uint32_t> Style;
-    Optional<uint32_t> ExStyle;
+    std::optional<uint32_t> Style;
+    std::optional<uint32_t> ExStyle;
     StringRef Caption;
     struct FontInfo {
       uint32_t Size;
@@ -89,7 +89,7 @@
       bool IsItalic;
       uint32_t Charset;
     };
-    Optional<FontInfo> Font;
+    std::optional<FontInfo> Font;
     IntOrString Class;
 
     ObjectInfo()
@@ -103,7 +103,7 @@
     using BundleKey = std::pair<uint16_t, uint16_t>;
     // Each bundle is in fact an array of 16 strings.
     struct Bundle {
-      std::array<Optional<std::vector<StringRef>>, 16> Data;
+      std::array<std::optional<std::vector<StringRef>>, 16> Data;
       ObjectInfo DeclTimeInfo;
       uint16_t MemoryFlags;
       Bundle(const ObjectInfo &Info, uint16_t Flags)
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp
index 7cb4d02..c1f00d3 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptParser.cpp
@@ -554,7 +554,7 @@
   RETURN_IF_ERROR(consumeType(Kind::Comma));
 
   IntOrString Class;
-  Optional<IntWithNotMask> Style;
+  std::optional<IntWithNotMask> Style;
   if (ClassUpper == "CONTROL") {
     // CONTROL text, id, class, style, x, y, width, height [, exstyle] [, helpID]
     ASSIGN_OR_RETURN(ClassStr, readString());
@@ -577,12 +577,12 @@
     }
   }
 
-  Optional<uint32_t> ExStyle;
+  std::optional<uint32_t> ExStyle;
   if (consumeOptionalType(Kind::Comma)) {
     ASSIGN_OR_RETURN(Val, readInt());
     ExStyle = *Val;
   }
-  Optional<uint32_t> HelpID;
+  std::optional<uint32_t> HelpID;
   if (consumeOptionalType(Kind::Comma)) {
     ASSIGN_OR_RETURN(Val, readInt());
     HelpID = *Val;
diff --git a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h
index 4b659f0..71f6a9d 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h
+++ b/src/llvm-project/llvm/tools/llvm-rc/ResourceScriptStmt.h
@@ -611,8 +611,8 @@
   StringRef Type;
   IntOrString Title;
   uint32_t ID, X, Y, Width, Height;
-  Optional<IntWithNotMask> Style;
-  Optional<uint32_t> ExtStyle, HelpID;
+  std::optional<IntWithNotMask> Style;
+  std::optional<uint32_t> ExtStyle, HelpID;
   IntOrString Class;
 
   // Control classes as described in DLGITEMTEMPLATEEX documentation.
@@ -636,8 +636,9 @@
 
   Control(StringRef CtlType, IntOrString CtlTitle, uint32_t CtlID,
           uint32_t PosX, uint32_t PosY, uint32_t ItemWidth, uint32_t ItemHeight,
-          Optional<IntWithNotMask> ItemStyle, Optional<uint32_t> ExtItemStyle,
-          Optional<uint32_t> CtlHelpID, IntOrString CtlClass)
+          std::optional<IntWithNotMask> ItemStyle,
+          std::optional<uint32_t> ExtItemStyle,
+          std::optional<uint32_t> CtlHelpID, IntOrString CtlClass)
       : Type(CtlType), Title(CtlTitle), ID(CtlID), X(PosX), Y(PosY),
         Width(ItemWidth), Height(ItemHeight), Style(ItemStyle),
         ExtStyle(ExtItemStyle), HelpID(CtlHelpID), Class(CtlClass) {}
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 312cc15..8864bbb 100644
--- a/src/llvm-project/llvm/tools/llvm-rc/llvm-rc.cpp
+++ b/src/llvm-project/llvm/tools/llvm-rc/llvm-rc.cpp
@@ -18,6 +18,7 @@
 #include "ResourceScriptToken.h"
 
 #include "llvm/ADT/Triple.h"
+#include "llvm/Config/llvm-config.h"
 #include "llvm/Object/WindowsResource.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
@@ -55,11 +56,15 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+namespace rc_opt {
+#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
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -70,10 +75,11 @@
 #include "Opts.inc"
 #undef OPTION
 };
+} // namespace rc_opt
 
-class RcOptTable : public opt::OptTable {
+class RcOptTable : public opt::GenericOptTable {
 public:
-  RcOptTable() : OptTable(InfoTable, /* IgnoreCase = */ true) {}
+  RcOptTable() : GenericOptTable(rc_opt::InfoTable, /* IgnoreCase = */ true) {}
 };
 
 enum Windres_ID {
@@ -85,25 +91,30 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const WINDRES_##NAME[] = VALUE;
+namespace windres_opt {
+#define PREFIX(NAME, VALUE)                                                    \
+  static constexpr StringLiteral NAME##_init[] = VALUE;                        \
+  static constexpr ArrayRef<StringLiteral> NAME(NAME##_init,                   \
+                                                std::size(NAME##_init) - 1);
 #include "WindresOpts.inc"
 #undef PREFIX
 
-const opt::OptTable::Info WindresInfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
-  {                                                                            \
-      WINDRES_##PREFIX, NAME,         HELPTEXT,                                \
-      METAVAR,          WINDRES_##ID, opt::Option::KIND##Class,                \
-      PARAM,            FLAGS,        WINDRES_##GROUP,                         \
-      WINDRES_##ALIAS,  ALIASARGS,    VALUES},
+  {PREFIX,          NAME,         HELPTEXT,                                    \
+   METAVAR,         WINDRES_##ID, opt::Option::KIND##Class,                    \
+   PARAM,           FLAGS,        WINDRES_##GROUP,                             \
+   WINDRES_##ALIAS, ALIASARGS,    VALUES},
 #include "WindresOpts.inc"
 #undef OPTION
 };
+} // namespace windres_opt
 
-class WindresOptTable : public opt::OptTable {
+class WindresOptTable : public opt::GenericOptTable {
 public:
-  WindresOptTable() : OptTable(WindresInfoTable, /* IgnoreCase = */ false) {}
+  WindresOptTable()
+      : GenericOptTable(windres_opt::InfoTable, /* IgnoreCase = */ false) {}
 };
 
 static ExitOnError ExitOnErr;
@@ -127,10 +138,12 @@
   StringRef Parent = llvm::sys::path::parent_path(Argv0);
   ErrorOr<std::string> Path = std::error_code();
   std::string TargetClang = (Triple + "-clang").str();
+  std::string VersionedClang = ("clang-" + Twine(LLVM_VERSION_MAJOR)).str();
   if (!Parent.empty()) {
     // First look for the tool with all potential names in the specific
     // directory of Argv0, if known
-    for (const auto *Name : {TargetClang.c_str(), "clang", "clang-cl"}) {
+    for (const auto *Name :
+         {TargetClang.c_str(), VersionedClang.c_str(), "clang", "clang-cl"}) {
       Path = sys::findProgramByName(Name, Parent);
       if (Path)
         return Path;
@@ -205,6 +218,7 @@
   std::string OutputFile;
   Format OutputFormat = Res;
 
+  bool IsWindres = false;
   bool BeVerbose = false;
   WriterParams Params;
   bool AppendNull = false;
@@ -216,7 +230,7 @@
 bool preprocess(StringRef Src, StringRef Dst, const RcOptions &Opts,
                 const char *Argv0) {
   std::string Clang;
-  if (Opts.PrintCmdAndExit) {
+  if (Opts.PrintCmdAndExit || !Opts.PreprocessCmd.empty()) {
     Clang = "clang";
   } else {
     ErrorOr<std::string> ClangOrErr = findClang(Argv0, Opts.Triple);
@@ -225,9 +239,12 @@
     } else {
       errs() << "llvm-rc: Unable to find clang, skipping preprocessing."
              << "\n";
-      errs() << "Pass -no-cpp to disable preprocessing. This will be an error "
-                "in the future."
-             << "\n";
+      StringRef OptionName =
+          Opts.IsWindres ? "--no-preprocess" : "-no-preprocess";
+      errs()
+          << "Pass " << OptionName
+          << " to disable preprocessing. This will be an error in the future."
+          << "\n";
       return false;
     }
   }
@@ -256,7 +273,7 @@
   }
   // 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(Clang, Args);
+  int Res = sys::ExecuteAndWait(Args[0], Args);
   if (Res) {
     fatalError("llvm-rc: Preprocessing failed.");
   }
@@ -352,6 +369,8 @@
   unsigned MAI, MAC;
   opt::InputArgList InputArgs = T.ParseArgs(ArgsArr, MAI, MAC);
 
+  Opts.IsWindres = true;
+
   // The tool prints nothing when invoked with no command-line arguments.
   if (InputArgs.hasArg(WINDRES_help)) {
     T.printHelp(outs(), "windres [options] file...",
@@ -724,16 +743,16 @@
 
 } // anonymous namespace
 
-int main(int Argc, const char **Argv) {
+int llvm_rc_main(int Argc, char **Argv) {
   InitLLVM X(Argc, Argv);
   ExitOnErr.setBanner("llvm-rc: ");
 
-  const char **DashDash = std::find_if(
-      Argv + 1, Argv + Argc, [](StringRef Str) { return Str == "--"; });
-  ArrayRef<const char *> ArgsArr = makeArrayRef(Argv + 1, DashDash);
+  char **DashDash = std::find_if(Argv + 1, Argv + Argc,
+                                 [](StringRef Str) { return Str == "--"; });
+  ArrayRef<const char *> ArgsArr = ArrayRef(Argv + 1, DashDash);
   ArrayRef<const char *> FileArgsArr;
   if (DashDash != Argv + Argc)
-    FileArgsArr = makeArrayRef(DashDash + 1, Argv + Argc);
+    FileArgsArr = ArrayRef(DashDash + 1, Argv + Argc);
 
   RcOptions Opts = getOptions(Argv[0], ArgsArr, FileArgsArr);
 
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ARMEHABIPrinter.h b/src/llvm-project/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
index d641b17..5f3cc7d 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ARMEHABIPrinter.h
@@ -91,7 +91,7 @@
       {0xf8, 0xd0, &OpcodeDecoder::Decode_11010nnn},
       {0xc0, 0xc0, &OpcodeDecoder::Decode_11xxxyyy},
   };
-  return makeArrayRef(Ring);
+  return ArrayRef(Ring);
 }
 
 inline void OpcodeDecoder::Decode_00xxxxxx(const uint8_t *Opcodes,
@@ -341,8 +341,9 @@
     return Location + Place;
   }
 
-  ErrorOr<StringRef> FunctionAtAddress(uint64_t Address,
-                                       Optional<unsigned> SectionIndex) const;
+  ErrorOr<StringRef>
+  FunctionAtAddress(uint64_t Address,
+                    std::optional<unsigned> SectionIndex) const;
   const Elf_Shdr *FindExceptionTable(unsigned IndexTableIndex,
                                      off_t IndexTableOffset) const;
 
@@ -363,9 +364,8 @@
 const size_t PrinterContext<ET>::IndexTableEntrySize = 8;
 
 template <typename ET>
-ErrorOr<StringRef>
-PrinterContext<ET>::FunctionAtAddress(uint64_t Address,
-                                      Optional<unsigned> SectionIndex) const {
+ErrorOr<StringRef> PrinterContext<ET>::FunctionAtAddress(
+    uint64_t Address, std::optional<unsigned> SectionIndex) const {
   if (!Symtab)
     return inconvertibleErrorCode();
   auto StrTableOrErr = ELF.getStringTableForSymtab(*Symtab);
@@ -501,8 +501,8 @@
                            ? PREL31(Word, EHT.sh_addr)
                            : PREL31(Word, EHT.sh_addr + TableEntryOffset);
     SW.printHex("PersonalityRoutineAddress", Address);
-    Optional<unsigned> SecIndex =
-        IsRelocatable ? Optional<unsigned>(EHT.sh_link) : None;
+    std::optional<unsigned> SecIndex =
+        IsRelocatable ? std::optional<unsigned>(EHT.sh_link) : std::nullopt;
     if (ErrorOr<StringRef> Name = FunctionAtAddress(Address, SecIndex))
       SW.printString("PersonalityRoutineName", *Name);
   }
@@ -574,8 +574,8 @@
     // their code sections via the sh_link field. For a non-relocatable ELF file
     // the sh_link field is not reliable, because we have one .ARM.exidx section
     // normally, but might have many code sections.
-    Optional<unsigned> SecIndex =
-        IsRelocatable ? Optional<unsigned>(IT->sh_link) : None;
+    std::optional<unsigned> SecIndex =
+        IsRelocatable ? std::optional<unsigned>(IT->sh_link) : std::nullopt;
     if (ErrorOr<StringRef> Name = FunctionAtAddress(Address, SecIndex))
       SW.printString("FunctionName", *Name);
 
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
index b7cbf35..ef77d4b 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.cpp
@@ -143,35 +143,36 @@
   { 0xff, 0xff, 1, &Decoder::opcode_11111111 },  // UOP_END
 };
 
-
 // Unwind opcodes for ARM64.
 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
 const Decoder::RingEntry Decoder::Ring64[] = {
-  { 0xe0, 0x00, 1, &Decoder::opcode_alloc_s },
-  { 0xe0, 0x20, 1, &Decoder::opcode_save_r19r20_x },
-  { 0xc0, 0x40, 1, &Decoder::opcode_save_fplr },
-  { 0xc0, 0x80, 1, &Decoder::opcode_save_fplr_x },
-  { 0xf8, 0xc0, 2, &Decoder::opcode_alloc_m },
-  { 0xfc, 0xc8, 2, &Decoder::opcode_save_regp },
-  { 0xfc, 0xcc, 2, &Decoder::opcode_save_regp_x },
-  { 0xfc, 0xd0, 2, &Decoder::opcode_save_reg },
-  { 0xfe, 0xd4, 2, &Decoder::opcode_save_reg_x },
-  { 0xfe, 0xd6, 2, &Decoder::opcode_save_lrpair },
-  { 0xfe, 0xd8, 2, &Decoder::opcode_save_fregp },
-  { 0xfe, 0xda, 2, &Decoder::opcode_save_fregp_x },
-  { 0xfe, 0xdc, 2, &Decoder::opcode_save_freg },
-  { 0xff, 0xde, 2, &Decoder::opcode_save_freg_x },
-  { 0xff, 0xe0, 4, &Decoder::opcode_alloc_l },
-  { 0xff, 0xe1, 1, &Decoder::opcode_setfp },
-  { 0xff, 0xe2, 2, &Decoder::opcode_addfp },
-  { 0xff, 0xe3, 1, &Decoder::opcode_nop },
-  { 0xff, 0xe4, 1, &Decoder::opcode_end },
-  { 0xff, 0xe5, 1, &Decoder::opcode_end_c },
-  { 0xff, 0xe6, 1, &Decoder::opcode_save_next },
-  { 0xff, 0xe8, 1, &Decoder::opcode_trap_frame },
-  { 0xff, 0xe9, 1, &Decoder::opcode_machine_frame },
-  { 0xff, 0xea, 1, &Decoder::opcode_context },
-  { 0xff, 0xec, 1, &Decoder::opcode_clear_unwound_to_call },
+    {0xe0, 0x00, 1, &Decoder::opcode_alloc_s},
+    {0xe0, 0x20, 1, &Decoder::opcode_save_r19r20_x},
+    {0xc0, 0x40, 1, &Decoder::opcode_save_fplr},
+    {0xc0, 0x80, 1, &Decoder::opcode_save_fplr_x},
+    {0xf8, 0xc0, 2, &Decoder::opcode_alloc_m},
+    {0xfc, 0xc8, 2, &Decoder::opcode_save_regp},
+    {0xfc, 0xcc, 2, &Decoder::opcode_save_regp_x},
+    {0xfc, 0xd0, 2, &Decoder::opcode_save_reg},
+    {0xfe, 0xd4, 2, &Decoder::opcode_save_reg_x},
+    {0xfe, 0xd6, 2, &Decoder::opcode_save_lrpair},
+    {0xfe, 0xd8, 2, &Decoder::opcode_save_fregp},
+    {0xfe, 0xda, 2, &Decoder::opcode_save_fregp_x},
+    {0xfe, 0xdc, 2, &Decoder::opcode_save_freg},
+    {0xff, 0xde, 2, &Decoder::opcode_save_freg_x},
+    {0xff, 0xe0, 4, &Decoder::opcode_alloc_l},
+    {0xff, 0xe1, 1, &Decoder::opcode_setfp},
+    {0xff, 0xe2, 2, &Decoder::opcode_addfp},
+    {0xff, 0xe3, 1, &Decoder::opcode_nop},
+    {0xff, 0xe4, 1, &Decoder::opcode_end},
+    {0xff, 0xe5, 1, &Decoder::opcode_end_c},
+    {0xff, 0xe6, 1, &Decoder::opcode_save_next},
+    {0xff, 0xe7, 3, &Decoder::opcode_save_any_reg},
+    {0xff, 0xe8, 1, &Decoder::opcode_trap_frame},
+    {0xff, 0xe9, 1, &Decoder::opcode_machine_frame},
+    {0xff, 0xea, 1, &Decoder::opcode_context},
+    {0xff, 0xec, 1, &Decoder::opcode_clear_unwound_to_call},
+    {0xff, 0xfc, 1, &Decoder::opcode_pac_sign_lr},
 };
 
 static void printRange(raw_ostream &OS, ListSeparator &LS, unsigned First,
@@ -855,7 +856,7 @@
                            bool Prologue) {
   SW.startLine() << format("0x%02x                ; end_c\n", OC[Offset]);
   ++Offset;
-  return true;
+  return false;
 }
 
 bool Decoder::opcode_save_next(const uint8_t *OC, unsigned &Offset,
@@ -869,6 +870,83 @@
   return false;
 }
 
+bool Decoder::opcode_save_any_reg(const uint8_t *OC, unsigned &Offset,
+                                  unsigned Length, bool Prologue) {
+  // Whether the instruction has writeback
+  bool Writeback = (OC[Offset + 1] & 0x20) == 0x20;
+  // Whether the instruction is paired.  (Paired instructions are required
+  // to save/restore adjacent registers.)
+  bool Paired = (OC[Offset + 1] & 0x40) == 0x40;
+  // The kind of register saved:
+  // - 0 is an x register
+  // - 1 is the low half of a q register
+  // - 2 is a whole q register
+  int RegKind = (OC[Offset + 2] & 0xC0) >> 6;
+  // Encoded register name (0 -> x0/q0, 1 -> x1/q1, etc.)
+  int Reg = OC[Offset + 1] & 0x1F;
+  // Encoded stack offset of load/store instruction; decoding varies by mode.
+  int StackOffset = OC[Offset + 2] & 0x3F;
+  if (Writeback)
+    StackOffset++;
+  if (!Writeback && !Paired && RegKind != 2)
+    StackOffset *= 8;
+  else
+    StackOffset *= 16;
+
+  SW.startLine() << format("0x%02x%02x%02x            ; ", OC[Offset],
+                           OC[Offset + 1], OC[Offset + 2]);
+
+  // Verify the encoding is in a form we understand.  The high bit of the first
+  // byte, and mode 3 for the register kind are apparently reserved.  The
+  // encoded register must refer to a valid register.
+  int MaxReg = 0x1F;
+  if (Paired)
+    --MaxReg;
+  if (RegKind == 0)
+    --MaxReg;
+  if ((OC[Offset + 1] & 0x80) == 0x80 || RegKind == 3 || Reg > MaxReg) {
+    SW.getOStream() << "invalid save_any_reg encoding\n";
+    Offset += 3;
+    return false;
+  }
+
+  if (Paired) {
+    if (Prologue)
+      SW.getOStream() << "stp ";
+    else
+      SW.getOStream() << "ldp ";
+  } else {
+    if (Prologue)
+      SW.getOStream() << "str ";
+    else
+      SW.getOStream() << "ldr ";
+  }
+
+  char RegChar = 'x';
+  if (RegKind == 1) {
+    RegChar = 'd';
+  } else if (RegKind == 2) {
+    RegChar = 'q';
+  }
+
+  if (Paired)
+    SW.getOStream() << format("%c%d, %c%d, ", RegChar, Reg, RegChar, Reg + 1);
+  else
+    SW.getOStream() << format("%c%d, ", RegChar, Reg);
+
+  if (Writeback) {
+    if (Prologue)
+      SW.getOStream() << format("[sp, #-%d]!\n", StackOffset);
+    else
+      SW.getOStream() << format("[sp], #%d\n", StackOffset);
+  } else {
+    SW.getOStream() << format("[sp, #%d]\n", StackOffset);
+  }
+
+  Offset += 3;
+  return false;
+}
+
 bool Decoder::opcode_trap_frame(const uint8_t *OC, unsigned &Offset,
                                 unsigned Length, bool Prologue) {
   SW.startLine() << format("0x%02x                ; trap frame\n", OC[Offset]);
@@ -899,6 +977,16 @@
   return false;
 }
 
+bool Decoder::opcode_pac_sign_lr(const uint8_t *OC, unsigned &Offset,
+                                 unsigned Length, bool Prologue) {
+  if (Prologue)
+    SW.startLine() << format("0x%02x                ; pacibsp\n", OC[Offset]);
+  else
+    SW.startLine() << format("0x%02x                ; autibsp\n", OC[Offset]);
+  ++Offset;
+  return false;
+}
+
 void Decoder::decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset,
                             bool Prologue) {
   assert((!Prologue || Offset == 0) && "prologue should always use offset 0");
@@ -906,8 +994,8 @@
   bool Terminated = false;
   for (unsigned OI = Offset, OE = Opcodes.size(); !Terminated && OI < OE; ) {
     for (unsigned DI = 0;; ++DI) {
-      if ((isAArch64 && (DI >= array_lengthof(Ring64))) ||
-          (!isAArch64 && (DI >= array_lengthof(Ring)))) {
+      if ((isAArch64 && (DI >= std::size(Ring64))) ||
+          (!isAArch64 && (DI >= std::size(Ring)))) {
         SW.startLine() << format("0x%02x                ; Bad opcode!\n",
                                  Opcodes.data()[OI]);
         ++OI;
@@ -1160,7 +1248,7 @@
     }
     if (RF.C()) {
       // Count the number of registers pushed below R11
-      int FpOffset = 4 * countPopulation(GPRMask & ((1U << 11) - 1));
+      int FpOffset = 4 * llvm::popcount(GPRMask & ((1U << 11) - 1));
       if (FpOffset)
         SW.startLine() << "add.w r11, sp, #" << FpOffset << "\n";
       else
@@ -1256,7 +1344,7 @@
   int SavSZ = (IntSZ + FpSZ + 8 * 8 * RF.H() + 0xf) & ~0xf;
   int LocSZ = (RF.FrameSize() << 4) - SavSZ;
 
-  if (RF.CR() == 3) {
+  if (RF.CR() == 2 || RF.CR() == 3) {
     SW.startLine() << "mov x29, sp\n";
     if (LocSZ <= 512) {
       SW.startLine() << format("stp x29, lr, [sp, #-%d]!\n", LocSZ);
@@ -1267,7 +1355,7 @@
   if (LocSZ > 4080) {
     SW.startLine() << format("sub sp, sp, #%d\n", LocSZ - 4080);
     SW.startLine() << "sub sp, sp, #4080\n";
-  } else if ((RF.CR() != 3 && LocSZ > 0) || LocSZ > 512) {
+  } else if ((RF.CR() != 3 && RF.CR() != 2 && LocSZ > 0) || LocSZ > 512) {
     SW.startLine() << format("sub sp, sp, #%d\n", LocSZ);
   }
   if (RF.H()) {
@@ -1329,6 +1417,11 @@
                                19 + 2 * I + 1, 16 * I);
     }
   }
+  // CR=2 is yet undocumented, see
+  // https://github.com/MicrosoftDocs/cpp-docs/pull/4202 for upstream
+  // progress on getting it documented.
+  if (RF.CR() == 2)
+    SW.startLine() << "pacibsp\n";
   SW.startLine() << "end\n";
 
   return true;
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
index ceaa866..0ffebe5 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ARMWinEHPrinter.h
@@ -121,6 +121,8 @@
                     bool Prologue);
   bool opcode_save_next(const uint8_t *Opcodes, unsigned &Offset,
                         unsigned Length, bool Prologue);
+  bool opcode_save_any_reg(const uint8_t *Opcodes, unsigned &Offset,
+                           unsigned Length, bool Prologue);
   bool opcode_trap_frame(const uint8_t *Opcodes, unsigned &Offset,
                          unsigned Length, bool Prologue);
   bool opcode_machine_frame(const uint8_t *Opcodes, unsigned &Offset,
@@ -129,6 +131,8 @@
                       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,
+                          unsigned Length, bool Prologue);
 
   void decodeOpcodes(ArrayRef<uint8_t> Opcodes, unsigned Offset,
                      bool Prologue);
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-readobj/CMakeLists.txt
index 9d2d888..e31e7a0 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-readobj/CMakeLists.txt
@@ -6,6 +6,7 @@
   BinaryFormat
   Option
   Support
+  TargetParser
   DebugInfoCodeView
   DebugInfoMSF
   DebugInfoPDB
@@ -27,6 +28,9 @@
   Win64EHDumper.cpp
   WindowsResourceDumper.cpp
   XCOFFDumper.cpp
+  DEPENDS
+  ReadobjOptsTableGen
+  GENERATE_DRIVER
   )
 
 add_llvm_tool_symlink(llvm-readelf llvm-readobj)
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
index caeb49a..5279e58 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -193,7 +193,6 @@
   CPUType CompilationCPUType = CPUType::X64;
 
   ScopedPrinter &Writer;
-  BinaryByteStream TypeContents;
   LazyRandomTypeCollection Types;
 };
 
@@ -344,6 +343,7 @@
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_AMD64    ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM      ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64    ),
+  LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARM64EC  ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_ARMNT    ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_EBC      ),
   LLVM_READOBJ_ENUM_ENT(COFF, IMAGE_FILE_MACHINE_I386     ),
@@ -578,6 +578,52 @@
   LLVM_READOBJ_ENUM_CLASS_ENT(FileChecksumKind, SHA256),
 };
 
+const EnumEntry<uint32_t> PELoadConfigGuardFlags[] = {
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_INSTRUMENTED),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CFW_INSTRUMENTED),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_FUNCTION_TABLE_PRESENT),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, SECURITY_COOKIE_UNUSED),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, PROTECT_DELAYLOAD_IAT),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                DELAYLOAD_IAT_IN_ITS_OWN_SECTION),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_EXPORT_SUPPRESSION_INFO_PRESENT),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_ENABLE_EXPORT_SUPPRESSION),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags, CF_LONGJUMP_TABLE_PRESENT),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                EH_CONTINUATION_TABLE_PRESENT),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_5BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_6BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_7BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_8BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_9BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_10BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_11BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_12BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_13BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_14BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_15BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_16BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_17BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_18BYTES),
+    LLVM_READOBJ_ENUM_CLASS_ENT(COFF::GuardFlags,
+                                CF_FUNCTION_TABLE_SIZE_19BYTES),
+};
+
 template <typename T>
 static std::error_code getSymbolAuxData(const COFFObjectFile *Obj,
                                         COFFSymbolRef Symbol,
@@ -621,16 +667,15 @@
 
   {
     DictScope D(W, "ImageFileHeader");
-    W.printEnum  ("Machine", Obj->getMachine(),
-                    makeArrayRef(ImageFileMachineType));
+    W.printEnum("Machine", Obj->getMachine(), ArrayRef(ImageFileMachineType));
     W.printNumber("SectionCount", Obj->getNumberOfSections());
     W.printHex   ("TimeDateStamp", FormattedTime, Obj->getTimeDateStamp());
     W.printHex   ("PointerToSymbolTable", Obj->getPointerToSymbolTable());
     W.printNumber("SymbolCount", Obj->getNumberOfSymbols());
     W.printNumber("StringTableSize", Obj->getStringTableSize());
     W.printNumber("OptionalHeaderSize", Obj->getSizeOfOptionalHeader());
-    W.printFlags ("Characteristics", Obj->getCharacteristics(),
-                    makeArrayRef(ImageFileCharacteristics));
+    W.printFlags("Characteristics", Obj->getCharacteristics(),
+                 ArrayRef(ImageFileCharacteristics));
   }
 
   // Print PE header. This header does not exist if this is an object file and
@@ -691,9 +736,10 @@
   W.printNumber("MinorSubsystemVersion", Hdr->MinorSubsystemVersion);
   W.printNumber("SizeOfImage", Hdr->SizeOfImage);
   W.printNumber("SizeOfHeaders", Hdr->SizeOfHeaders);
-  W.printEnum  ("Subsystem", Hdr->Subsystem, makeArrayRef(PEWindowsSubsystem));
-  W.printFlags ("Characteristics", Hdr->DLLCharacteristics,
-                makeArrayRef(PEDLLCharacteristics));
+  W.printHex   ("CheckSum", Hdr->CheckSum);
+  W.printEnum("Subsystem", Hdr->Subsystem, ArrayRef(PEWindowsSubsystem));
+  W.printFlags("Characteristics", Hdr->DLLCharacteristics,
+               ArrayRef(PEDLLCharacteristics));
   W.printNumber("SizeOfStackReserve", Hdr->SizeOfStackReserve);
   W.printNumber("SizeOfStackCommit", Hdr->SizeOfStackCommit);
   W.printNumber("SizeOfHeapReserve", Hdr->SizeOfHeapReserve);
@@ -710,7 +756,7 @@
     };
 
     for (uint32_t i = 0; i < Hdr->NumberOfRvaAndSize; ++i)
-      if (i < sizeof(directory) / sizeof(char *))
+      if (i < std::size(directory))
         printDataDirectory(i, directory[i]);
       else
         printDataDirectory(i, "Unknown");
@@ -728,7 +774,7 @@
     W.printHex("TimeDateStamp", FormattedTime, D.TimeDateStamp);
     W.printHex("MajorVersion", D.MajorVersion);
     W.printHex("MinorVersion", D.MinorVersion);
-    W.printEnum("Type", D.Type, makeArrayRef(ImageDebugType));
+    W.printEnum("Type", D.Type, ArrayRef(ImageDebugType));
     W.printHex("SizeOfData", D.SizeOfData);
     W.printHex("AddressOfRawData", D.AddressOfRawData);
     W.printHex("PointerToRawData", D.PointerToRawData);
@@ -745,7 +791,7 @@
       DictScope PDBScope(W, "PDBInfo");
       W.printHex("PDBSignature", DebugInfo->Signature.CVSignature);
       if (DebugInfo->Signature.CVSignature == OMF::Signature::PDB70) {
-        W.printBinary("PDBGUID", makeArrayRef(DebugInfo->PDB70.Signature));
+        W.printBinary("PDBGUID", ArrayRef(DebugInfo->PDB70.Signature));
         W.printNumber("PDBAge", DebugInfo->PDB70.Age);
         W.printString("PDBFileName", PDBFileName);
       }
@@ -761,7 +807,7 @@
         // but that might change in the future
         uint16_t Characteristics = RawData[0];
         W.printFlags("ExtendedCharacteristics", Characteristics,
-                     makeArrayRef(PEExtendedDLLCharacteristics));
+                     ArrayRef(PEExtendedDLLCharacteristics));
       }
       W.printBinaryBlock("RawData", RawData);
     }
@@ -807,11 +853,18 @@
 
   if (Tables.GuardFidTableVA) {
     ListScope LS(W, "GuardFidTable");
-    if (Tables.GuardFlags & uint32_t(coff_guard_flags::FidTableHasFlags))
-      printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 5,
+    if (uint32_t Size =
+            Tables.GuardFlags &
+            uint32_t(COFF::GuardFlags::CF_FUNCTION_TABLE_SIZE_MASK)) {
+      // The size mask gives the number of extra bytes in addition to the 4-byte
+      // RVA of each entry in the table. As of writing only a 1-byte extra flag
+      // has been defined.
+      Size = (Size >> 28) + 4;
+      printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, Size,
                     PrintGuardFlags);
-    else
+    } else {
       printRVATable(Tables.GuardFidTableVA, Tables.GuardFidTableCount, 4);
+    }
   }
 
   if (Tables.GuardIatTableVA) {
@@ -881,7 +934,8 @@
   W.printHex("GuardCFCheckDispatch", Conf->GuardCFCheckDispatch);
   W.printHex("GuardCFFunctionTable", Conf->GuardCFFunctionTable);
   W.printNumber("GuardCFFunctionCount", Conf->GuardCFFunctionCount);
-  W.printHex("GuardFlags", Conf->GuardFlags);
+  W.printFlags("GuardFlags", Conf->GuardFlags, ArrayRef(PELoadConfigGuardFlags),
+               (uint32_t)COFF::GuardFlags::CF_FUNCTION_TABLE_SIZE_MASK);
 
   Tables.GuardFidTableVA = Conf->GuardCFFunctionTable;
   Tables.GuardFidTableCount = Conf->GuardCFFunctionCount;
@@ -1026,7 +1080,7 @@
       W.printHex("IgnoredSubsectionKind", SubType);
       SubType &= ~SubsectionIgnoreFlag;
     }
-    W.printEnum("SubSectionType", SubType, makeArrayRef(SubSectionTypes));
+    W.printEnum("SubSectionType", SubType, ArrayRef(SubSectionTypes));
     W.printHex("SubSectionSize", SubSectionSize);
 
     // Get the contents of the subsection.
@@ -1123,7 +1177,7 @@
         W.printHex("MaxStackSize", FD.MaxStackSize);
         W.printHex("PrologSize", FD.PrologSize);
         W.printHex("SavedRegsSize", FD.SavedRegsSize);
-        W.printFlags("Flags", FD.Flags, makeArrayRef(FrameDataFlags));
+        W.printFlags("Flags", FD.Flags, ArrayRef(FrameDataFlags));
 
         // The FrameFunc string is a small RPN program. It can be broken up into
         // statements that end in the '=' operator, which assigns the value on
@@ -1241,7 +1295,7 @@
     W.printHex("Filename", Filename, FC.FileNameOffset);
     W.printHex("ChecksumSize", FC.Checksum.size());
     W.printEnum("ChecksumKind", uint8_t(FC.Kind),
-                makeArrayRef(FileChecksumKindNames));
+                ArrayRef(FileChecksumKindNames));
 
     W.printBinary("ChecksumBytes", FC.Checksum);
   }
@@ -1316,17 +1370,17 @@
                     Obj->getFileName());
       }
       SmallVector<TypeIndex, 128> SourceToDest;
-      Optional<uint32_t> PCHSignature;
+      std::optional<PCHMergerInfo> PCHInfo;
       if (GHash) {
         std::vector<GloballyHashedType> Hashes =
             GloballyHashedType::hashTypes(Types);
         if (Error E =
                 mergeTypeAndIdRecords(GlobalCVIDs, GlobalCVTypes, SourceToDest,
-                                      Types, Hashes, PCHSignature))
+                                      Types, Hashes, PCHInfo))
           return reportError(std::move(E), Obj->getFileName());
       } else {
         if (Error E = mergeTypeAndIdRecords(CVIDs, CVTypes, SourceToDest, Types,
-                                            PCHSignature))
+                                            PCHInfo))
           return reportError(std::move(E), Obj->getFileName());
       }
     }
@@ -1380,9 +1434,9 @@
     W.printHex   ("PointerToLineNumbers", Section->PointerToLinenumbers);
     W.printNumber("RelocationCount", Section->NumberOfRelocations);
     W.printNumber("LineNumberCount", Section->NumberOfLinenumbers);
-    W.printFlags ("Characteristics", Section->Characteristics,
-                    makeArrayRef(ImageSectionCharacteristics),
-                    COFF::SectionCharacteristics(0x00F00000));
+    W.printFlags("Characteristics", Section->Characteristics,
+                 ArrayRef(ImageSectionCharacteristics),
+                 COFF::SectionCharacteristics(0x00F00000));
 
     if (opts::SectionRelocations) {
       ListScope D(W, "Relocations");
@@ -1518,11 +1572,10 @@
   W.printString("Name", SymbolName);
   W.printNumber("Value", Symbol.getValue());
   W.printNumber("Section", SectionName, Symbol.getSectionNumber());
-  W.printEnum  ("BaseType", Symbol.getBaseType(), makeArrayRef(ImageSymType));
-  W.printEnum  ("ComplexType", Symbol.getComplexType(),
-                                                   makeArrayRef(ImageSymDType));
-  W.printEnum  ("StorageClass", Symbol.getStorageClass(),
-                                                   makeArrayRef(ImageSymClass));
+  W.printEnum("BaseType", Symbol.getBaseType(), ArrayRef(ImageSymType));
+  W.printEnum("ComplexType", Symbol.getComplexType(), ArrayRef(ImageSymDType));
+  W.printEnum("StorageClass", Symbol.getStorageClass(),
+              ArrayRef(ImageSymClass));
   W.printNumber("AuxSymbolCount", Symbol.getNumberOfAuxSymbols());
 
   for (uint8_t I = 0; I < Symbol.getNumberOfAuxSymbols(); ++I) {
@@ -1544,8 +1597,8 @@
 
       DictScope AS(W, "AuxWeakExternal");
       W.printNumber("Linked", getSymbolName(Aux->TagIndex), Aux->TagIndex);
-      W.printEnum  ("Search", Aux->Characteristics,
-                    makeArrayRef(WeakExternalCharacteristics));
+      W.printEnum("Search", Aux->Characteristics,
+                  ArrayRef(WeakExternalCharacteristics));
 
     } else if (Symbol.isFileRecord()) {
       const char *FileName;
@@ -1570,7 +1623,7 @@
       W.printNumber("LineNumberCount", Aux->NumberOfLinenumbers);
       W.printHex("Checksum", Aux->CheckSum);
       W.printNumber("Number", AuxNumber);
-      W.printEnum("Selection", Aux->Selection, makeArrayRef(ImageCOMDATSelect));
+      W.printEnum("Selection", Aux->Selection, ArrayRef(ImageCOMDATSelect));
 
       if (Section && Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT
           && Aux->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
@@ -1616,16 +1669,17 @@
     break;
   }
   case COFF::IMAGE_FILE_MACHINE_ARM64:
+  case COFF::IMAGE_FILE_MACHINE_ARM64EC:
   case COFF::IMAGE_FILE_MACHINE_ARMNT: {
-    ARM::WinEH::Decoder Decoder(W, Obj->getMachine() ==
-                                       COFF::IMAGE_FILE_MACHINE_ARM64);
+    ARM::WinEH::Decoder Decoder(W, Obj->getMachine() !=
+                                       COFF::IMAGE_FILE_MACHINE_ARMNT);
     // TODO Propagate the error.
     consumeError(Decoder.dumpProcedureData(*Obj));
     break;
   }
   default:
     W.printEnum("unsupported Image Machine", Obj->getMachine(),
-                makeArrayRef(ImageFileMachineType));
+                ArrayRef(ImageFileMachineType));
     break;
   }
 }
@@ -1733,18 +1787,29 @@
     DictScope Export(W, "Export");
 
     StringRef Name;
-    uint32_t Ordinal, RVA;
+    uint32_t Ordinal;
+    bool IsForwarder;
 
     if (Error E = Exp.getSymbolName(Name))
       reportError(std::move(E), Obj->getFileName());
     if (Error E = Exp.getOrdinal(Ordinal))
       reportError(std::move(E), Obj->getFileName());
-    if (Error E = Exp.getExportRVA(RVA))
+    if (Error E = Exp.isForwarder(IsForwarder))
       reportError(std::move(E), Obj->getFileName());
 
     W.printNumber("Ordinal", Ordinal);
     W.printString("Name", Name);
-    W.printHex("RVA", RVA);
+    StringRef ForwardTo;
+    if (IsForwarder) {
+      if (Error E = Exp.getForwardTo(ForwardTo))
+        reportError(std::move(E), Obj->getFileName());
+      W.printString("ForwardedTo", ForwardTo);
+    } else {
+      uint32_t RVA;
+      if (Error E = Exp.getExportRVA(RVA))
+        reportError(std::move(E), Obj->getFileName());
+      W.printHex("RVA", RVA);
+    }
   }
 }
 
@@ -1862,7 +1927,7 @@
         std::copy(RawEntryNameString.begin(), RawEntryNameString.end(),
                   EndianCorrectedNameString.begin() + 1);
         EndianCorrectedNameString[0] = UNI_UTF16_BYTE_ORDER_MARK_SWAPPED;
-        RawEntryNameString = makeArrayRef(EndianCorrectedNameString);
+        RawEntryNameString = ArrayRef(EndianCorrectedNameString);
       }
       std::string EntryNameString;
       if (!llvm::convertUTF16ToUTF8String(RawEntryNameString, EntryNameString))
@@ -2074,6 +2139,6 @@
   W.printHex("AddressOfCallBacks", TlsTable->AddressOfCallBacks);
   W.printHex("SizeOfZeroFill", TlsTable->SizeOfZeroFill);
   W.printFlags("Characteristics", TlsTable->Characteristics,
-               makeArrayRef(ImageSectionCharacteristics),
+               ArrayRef(ImageSectionCharacteristics),
                COFF::SectionCharacteristics(COFF::IMAGE_SCN_ALIGN_MASK));
 }
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h b/src/llvm-project/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
index 5dc947e..365a598 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/DwarfCFIEHPrinter.h
@@ -226,8 +226,9 @@
     W.getOStream() << "\n";
     W.startLine() << "Program:\n";
     W.indent();
-    Entry.cfis().dump(W.getOStream(), DIDumpOptions(), nullptr,
-                      W.getIndentLevel());
+    auto DumpOpts = DIDumpOptions();
+    DumpOpts.IsEH = true;
+    Entry.cfis().dump(W.getOStream(), DumpOpts, W.getIndentLevel());
     W.unindent();
     W.unindent();
     W.getOStream() << "\n";
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/ELFDumper.cpp
index ba7bae9..45fff0c 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/Optional.h"
 #include "llvm/ADT/PointerIntPair.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallString.h"
@@ -67,6 +66,7 @@
 #include <cstdlib>
 #include <iterator>
 #include <memory>
+#include <optional>
 #include <string>
 #include <system_error>
 #include <vector>
@@ -201,7 +201,7 @@
   uint32_t Symbol;
   typename ELFT::uint Offset;
   typename ELFT::uint Info;
-  Optional<int64_t> Addend;
+  std::optional<int64_t> Addend;
 };
 
 template <class ELFT> class MipsGOTParser;
@@ -289,7 +289,7 @@
                                   bool NonVisibilityBitsUsed) const {};
   virtual void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
                            DataRegion<Elf_Word> ShndxTable,
-                           Optional<StringRef> StrTable, bool IsDynamic,
+                           std::optional<StringRef> StrTable, bool IsDynamic,
                            bool NonVisibilityBitsUsed) const = 0;
 
   virtual void printMipsABIFlags() = 0;
@@ -305,13 +305,12 @@
 
   // Returns the function symbol index for the given address. Matches the
   // symbol's section with FunctionSec when specified.
-  // Returns None if no function symbol can be found for the address or in case
-  // it is not defined in the specified section.
-  SmallVector<uint32_t>
-  getSymbolIndexesForFunctionAddress(uint64_t SymValue,
-                                     Optional<const Elf_Shdr *> FunctionSec);
+  // Returns std::nullopt if no function symbol can be found for the address or
+  // in case it is not defined in the specified section.
+  SmallVector<uint32_t> getSymbolIndexesForFunctionAddress(
+      uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec);
   bool printFunctionStackSize(uint64_t SymValue,
-                              Optional<const Elf_Shdr *> FunctionSec,
+                              std::optional<const Elf_Shdr *> FunctionSec,
                               const Elf_Shdr &StackSizeSec, DataExtractor Data,
                               uint64_t *Offset);
   void printStackSize(const Relocation<ELFT> &R, const Elf_Shdr &RelocSec,
@@ -355,13 +354,13 @@
 
   Expected<StringRef> getSymbolVersion(const Elf_Sym &Sym,
                                        bool &IsDefault) const;
-  Expected<SmallVector<Optional<VersionEntry>, 0> *> getVersionMap() const;
+  Expected<SmallVector<std::optional<VersionEntry>, 0> *> getVersionMap() const;
 
   DynRegionInfo DynRelRegion;
   DynRegionInfo DynRelaRegion;
   DynRegionInfo DynRelrRegion;
   DynRegionInfo DynPLTRelRegion;
-  Optional<DynRegionInfo> DynSymRegion;
+  std::optional<DynRegionInfo> DynSymRegion;
   DynRegionInfo DynSymTabShndxRegion;
   DynRegionInfo DynamicTable;
   StringRef DynamicStringTable;
@@ -371,8 +370,8 @@
   const Elf_Shdr *DotDynsymSec = nullptr;
   const Elf_Shdr *DotAddrsigSec = nullptr;
   DenseMap<const Elf_Shdr *, ArrayRef<Elf_Word>> ShndxTables;
-  Optional<uint64_t> SONameOffset;
-  Optional<DenseMap<uint64_t, std::vector<uint32_t>>> AddressToIndexMap;
+  std::optional<uint64_t> SONameOffset;
+  std::optional<DenseMap<uint64_t, std::vector<uint32_t>>> AddressToIndexMap;
 
   const Elf_Shdr *SymbolVersionSection = nullptr;   // .gnu.version
   const Elf_Shdr *SymbolVersionNeedSection = nullptr; // .gnu.version_r
@@ -380,7 +379,7 @@
 
   std::string getFullSymbolName(const Elf_Sym &Symbol, unsigned SymIndex,
                                 DataRegion<Elf_Word> ShndxTable,
-                                Optional<StringRef> StrTable,
+                                std::optional<StringRef> StrTable,
                                 bool IsDynamic) const;
   Expected<unsigned>
   getSymbolSectionIndex(const Elf_Sym &Symbol, unsigned SymIndex,
@@ -399,7 +398,7 @@
   ArrayRef<Elf_Word> getShndxTable(const Elf_Shdr *Symtab) const;
 
 private:
-  mutable SmallVector<Optional<VersionEntry>, 0> VersionMap;
+  mutable SmallVector<std::optional<VersionEntry>, 0> VersionMap;
 };
 
 template <class ELFT>
@@ -493,7 +492,7 @@
 
 template <class ELFT>
 void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
-  Optional<StringRef> StrTable;
+  std::optional<StringRef> StrTable;
   size_t Entries = 0;
   Elf_Sym_Range Syms(nullptr, nullptr);
   const Elf_Shdr *SymtabSec = IsDynamic ? DotDynsymSec : DotSymtabSec;
@@ -635,7 +634,7 @@
                          const RelSymbol<ELFT> &RelSym) override;
   void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
                    DataRegion<Elf_Word> ShndxTable,
-                   Optional<StringRef> StrTable, bool IsDynamic,
+                   std::optional<StringRef> StrTable, bool IsDynamic,
                    bool NonVisibilityBitsUsed) const override;
   void printDynamicRelocHeader(unsigned Type, StringRef Name,
                                const DynRegionInfo &Reg) override;
@@ -692,7 +691,7 @@
                           DataRegion<Elf_Word> ShndxTable) const;
   void printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
                    DataRegion<Elf_Word> ShndxTable,
-                   Optional<StringRef> StrTable, bool IsDynamic,
+                   std::optional<StringRef> StrTable, bool IsDynamic,
                    bool /*NonVisibilityBitsUsed*/) const override;
   void printProgramHeaders() override;
   void printSectionMapping() override {}
@@ -759,14 +758,14 @@
 } // end namespace llvm
 
 template <class ELFT>
-Expected<SmallVector<Optional<VersionEntry>, 0> *>
+Expected<SmallVector<std::optional<VersionEntry>, 0> *>
 ELFDumper<ELFT>::getVersionMap() const {
   // If the VersionMap has already been loaded or if there is no dynamic symtab
   // or version table, there is nothing to do.
   if (!VersionMap.empty() || !DynSymRegion || !SymbolVersionSection)
     return &VersionMap;
 
-  Expected<SmallVector<Optional<VersionEntry>, 0>> MapOrErr =
+  Expected<SmallVector<std::optional<VersionEntry>, 0>> MapOrErr =
       Obj.loadVersionMap(SymbolVersionNeedSection, SymbolVersionDefSection);
   if (MapOrErr)
     VersionMap = *MapOrErr;
@@ -804,7 +803,7 @@
     return "";
   }
 
-  Expected<SmallVector<Optional<VersionEntry>, 0> *> MapOrErr =
+  Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr =
       getVersionMap();
   if (!MapOrErr)
     return MapOrErr.takeError();
@@ -881,11 +880,9 @@
 }
 
 template <typename ELFT>
-std::string ELFDumper<ELFT>::getFullSymbolName(const Elf_Sym &Symbol,
-                                               unsigned SymIndex,
-                                               DataRegion<Elf_Word> ShndxTable,
-                                               Optional<StringRef> StrTable,
-                                               bool IsDynamic) const {
+std::string ELFDumper<ELFT>::getFullSymbolName(
+    const Elf_Sym &Symbol, unsigned SymIndex, DataRegion<Elf_Word> ShndxTable,
+    std::optional<StringRef> StrTable, bool IsDynamic) const {
   if (!StrTable)
     return "<?>";
 
@@ -940,7 +937,8 @@
   if (Ndx != SHN_UNDEF && Ndx < SHN_LORESERVE)
     return Ndx;
 
-  auto CreateErr = [&](const Twine &Name, Optional<unsigned> Offset = None) {
+  auto CreateErr = [&](const Twine &Name,
+                       std::optional<unsigned> Offset = std::nullopt) {
     std::string Desc;
     if (Offset)
       Desc = (Name + "+0x" + Twine::utohexstr(*Offset)).str();
@@ -1411,6 +1409,7 @@
     LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_RELRO);
     LLVM_READOBJ_ENUM_CASE(ELF, PT_GNU_PROPERTY);
 
+    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_BOOTDATA);
@@ -1649,14 +1648,18 @@
 };
 
 const EnumEntry<unsigned> ElfHeaderLoongArchFlags[] = {
-  ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32S, "ILP32, SOFT-FLOAT"),
-  ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32F, "ILP32, SINGLE-FLOAT"),
-  ENUM_ENT(EF_LOONGARCH_BASE_ABI_ILP32D, "ILP32, DOUBLE-FLOAT"),
-  ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64S, "LP64, SOFT-FLOAT"),
-  ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64F, "LP64, SINGLE-FLOAT"),
-  ENUM_ENT(EF_LOONGARCH_BASE_ABI_LP64D, "LP64, DOUBLE-FLOAT"),
+  ENUM_ENT(EF_LOONGARCH_ABI_SOFT_FLOAT, "SOFT-FLOAT"),
+  ENUM_ENT(EF_LOONGARCH_ABI_SINGLE_FLOAT, "SINGLE-FLOAT"),
+  ENUM_ENT(EF_LOONGARCH_ABI_DOUBLE_FLOAT, "DOUBLE-FLOAT"),
+  ENUM_ENT(EF_LOONGARCH_OBJABI_V0, "OBJ-v0"),
+  ENUM_ENT(EF_LOONGARCH_OBJABI_V1, "OBJ-v1"),
 };
 
+static const EnumEntry<unsigned> ElfHeaderXtensaFlags[] = {
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_MACH_NONE),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_INSN),
+  LLVM_READOBJ_ENUM_ENT(ELF, EF_XTENSA_XT_LIT)
+};
 
 const EnumEntry<unsigned> ElfSymOtherFlags[] = {
   LLVM_READOBJ_ENUM_ENT(ELF, STV_INTERNAL),
@@ -1946,7 +1949,7 @@
 
   const char *StringTableBegin = nullptr;
   uint64_t StringTableSize = 0;
-  Optional<DynRegionInfo> DynSymFromTable;
+  std::optional<DynRegionInfo> DynSymFromTable;
   for (const Elf_Dyn &Dyn : dynamic_table()) {
     switch (Dyn.d_tag) {
     case ELF::DT_HASH:
@@ -2314,7 +2317,7 @@
     case DT_MIPS_XHASH:
       return FormatHexValue(Value);
     case DT_MIPS_FLAGS:
-      return FormatFlags(Value, makeArrayRef(ElfDynamicDTMipsFlags));
+      return FormatFlags(Value, ArrayRef(ElfDynamicDTMipsFlags));
     default:
       break;
     }
@@ -2329,7 +2332,7 @@
       return "REL";
     if (Value == DT_RELA)
       return "RELA";
-    LLVM_FALLTHROUGH;
+    [[fallthrough]];
   case DT_PLTGOT:
   case DT_HASH:
   case DT_STRTAB:
@@ -2387,9 +2390,9 @@
         .str();
   }
   case DT_FLAGS:
-    return FormatFlags(Value, makeArrayRef(ElfDynamicDTFlags));
+    return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags));
   case DT_FLAGS_1:
-    return FormatFlags(Value, makeArrayRef(ElfDynamicDTFlags1));
+    return FormatFlags(Value, ArrayRef(ElfDynamicDTFlags1));
   default:
     return FormatHexValue(Value);
   }
@@ -2551,7 +2554,7 @@
 
 template <class ELFT>
 static Expected<ArrayRef<typename ELFT::Word>>
-getGnuHashTableChains(Optional<DynRegionInfo> DynSymRegion,
+getGnuHashTableChains(std::optional<DynRegionInfo> DynSymRegion,
                       const typename ELFT::GnuHash *GnuHashTable) {
   if (!DynSymRegion)
     return createError("no dynamic symbol table found");
@@ -2796,9 +2799,9 @@
   }
 
   // Lookup dynamic table tags which define the GOT layout.
-  Optional<uint64_t> DtPltGot;
-  Optional<uint64_t> DtLocalGotNum;
-  Optional<uint64_t> DtGotSym;
+  std::optional<uint64_t> DtPltGot;
+  std::optional<uint64_t> DtLocalGotNum;
+  std::optional<uint64_t> DtGotSym;
   for (const auto &Entry : DynTable) {
     switch (Entry.getTag()) {
     case ELF::DT_PLTGOT:
@@ -2849,8 +2852,8 @@
 template <class ELFT>
 Error MipsGOTParser<ELFT>::findPLT(Elf_Dyn_Range DynTable) {
   // Lookup dynamic table tags which define the PLT layout.
-  Optional<uint64_t> DtMipsPltGot;
-  Optional<uint64_t> DtJmpRel;
+  std::optional<uint64_t> DtMipsPltGot;
+  std::optional<uint64_t> DtJmpRel;
   for (const auto &Entry : DynTable) {
     switch (Entry.getTag()) {
     case ELF::DT_MIPS_PLTGOT:
@@ -3294,7 +3297,7 @@
   auto It = llvm::find_if(ElfObjectFileType, [&](const EnumEntry<unsigned> &E) {
     return E.Value == Type;
   });
-  if (It != makeArrayRef(ElfObjectFileType).end())
+  if (It != ArrayRef(ElfObjectFileType).end())
     return It;
   return nullptr;
 }
@@ -3317,9 +3320,9 @@
   for (int i = 0; i < ELF::EI_NIDENT; i++)
     OS << format(" %02x", static_cast<int>(e.e_ident[i]));
   OS << "\n";
-  Str = enumToString(e.e_ident[ELF::EI_CLASS], makeArrayRef(ElfClass));
+  Str = enumToString(e.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass));
   printFields(OS, "Class:", Str);
-  Str = enumToString(e.e_ident[ELF::EI_DATA], makeArrayRef(ElfDataEncoding));
+  Str = enumToString(e.e_ident[ELF::EI_DATA], ArrayRef(ElfDataEncoding));
   printFields(OS, "Data:", Str);
   OS.PadToColumn(2u);
   OS << "Version:";
@@ -3328,7 +3331,7 @@
   if (e.e_version == ELF::EV_CURRENT)
     OS << " (current)";
   OS << "\n";
-  Str = enumToString(e.e_ident[ELF::EI_OSABI], makeArrayRef(ElfOSABI));
+  Str = enumToString(e.e_ident[ELF::EI_OSABI], ArrayRef(ElfOSABI));
   printFields(OS, "OS/ABI:", Str);
   printFields(OS,
               "ABI Version:", std::to_string(e.e_ident[ELF::EI_ABIVERSION]));
@@ -3345,7 +3348,7 @@
   }
   printFields(OS, "Type:", Str);
 
-  Str = enumToString(e.e_machine, makeArrayRef(ElfMachineType));
+  Str = enumToString(e.e_machine, ArrayRef(ElfMachineType));
   printFields(OS, "Machine:", Str);
   Str = "0x" + utohexstr(e.e_version);
   printFields(OS, "Version:", Str);
@@ -3357,18 +3360,21 @@
   printFields(OS, "Start of section headers:", Str);
   std::string ElfFlags;
   if (e.e_machine == EM_MIPS)
-    ElfFlags =
-        printFlags(e.e_flags, makeArrayRef(ElfHeaderMipsFlags),
-                   unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI),
-                   unsigned(ELF::EF_MIPS_MACH));
+    ElfFlags = printFlags(
+        e.e_flags, ArrayRef(ElfHeaderMipsFlags), unsigned(ELF::EF_MIPS_ARCH),
+        unsigned(ELF::EF_MIPS_ABI), unsigned(ELF::EF_MIPS_MACH));
   else if (e.e_machine == EM_RISCV)
-    ElfFlags = printFlags(e.e_flags, makeArrayRef(ElfHeaderRISCVFlags));
+    ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderRISCVFlags));
   else if (e.e_machine == EM_AVR)
-    ElfFlags = printFlags(e.e_flags, makeArrayRef(ElfHeaderAVRFlags),
+    ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderAVRFlags),
                           unsigned(ELF::EF_AVR_ARCH_MASK));
   else if (e.e_machine == EM_LOONGARCH)
-    ElfFlags = printFlags(e.e_flags, makeArrayRef(ElfHeaderLoongArchFlags),
-                          unsigned(ELF::EF_LOONGARCH_BASE_ABI_MASK));
+    ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderLoongArchFlags),
+                          unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK),
+                          unsigned(ELF::EF_LOONGARCH_OBJABI_MASK));
+  else if (e.e_machine == EM_XTENSA)
+    ElfFlags = printFlags(e.e_flags, ArrayRef(ElfHeaderXtensaFlags),
+                          unsigned(ELF::EF_XTENSA_MACH));
   Str = "0x" + utohexstr(e.e_flags);
   if (!ElfFlags.empty())
     Str = Str + ", " + ElfFlags;
@@ -3537,7 +3543,7 @@
     printField(F);
 
   std::string Addend;
-  if (Optional<int64_t> A = R.Addend) {
+  if (std::optional<int64_t> A = R.Addend) {
     int64_t RelAddend = *A;
     if (!RelSym.Name.empty()) {
       if (RelAddend < 0) {
@@ -3693,8 +3699,16 @@
 }
 
 template <class ELFT> void GNUELFDumper<ELFT>::printSectionHeaders() {
-  unsigned Bias = ELFT::Is64Bits ? 0 : 8;
   ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections());
+  if (Sections.empty()) {
+    OS << "\nThere are no sections in this file.\n";
+    Expected<StringRef> SecStrTableOrErr =
+        this->Obj.getSectionStringTable(Sections, this->WarningHandler);
+    if (!SecStrTableOrErr)
+      this->reportUniqueWarning(SecStrTableOrErr.takeError());
+    return;
+  }
+  unsigned Bias = ELFT::Is64Bits ? 0 : 8;
   OS << "There are " << to_string(Sections.size())
      << " section headers, starting at offset "
      << "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n";
@@ -3825,7 +3839,7 @@
 template <class ELFT>
 void GNUELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
                                      DataRegion<Elf_Word> ShndxTable,
-                                     Optional<StringRef> StrTable,
+                                     std::optional<StringRef> StrTable,
                                      bool IsDynamic,
                                      bool NonVisibilityBitsUsed) const {
   unsigned Bias = ELFT::Is64Bits ? 8 : 0;
@@ -3839,14 +3853,14 @@
   unsigned char SymbolType = Symbol.getType();
   if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&
       SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
-    Fields[3].Str = enumToString(SymbolType, makeArrayRef(AMDGPUSymbolTypes));
+    Fields[3].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes));
   else
-    Fields[3].Str = enumToString(SymbolType, makeArrayRef(ElfSymbolTypes));
+    Fields[3].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes));
 
   Fields[4].Str =
-      enumToString(Symbol.getBinding(), makeArrayRef(ElfSymbolBindings));
+      enumToString(Symbol.getBinding(), ArrayRef(ElfSymbolBindings));
   Fields[5].Str =
-      enumToString(Symbol.getVisibility(), makeArrayRef(ElfSymbolVisibilities));
+      enumToString(Symbol.getVisibility(), ArrayRef(ElfSymbolVisibilities));
 
   if (Symbol.st_other & ~0x3) {
     if (this->Obj.getHeader().e_machine == ELF::EM_AARCH64) {
@@ -3902,14 +3916,14 @@
   unsigned char SymbolType = Symbol->getType();
   if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&
       SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
-    Fields[4].Str = enumToString(SymbolType, makeArrayRef(AMDGPUSymbolTypes));
+    Fields[4].Str = enumToString(SymbolType, ArrayRef(AMDGPUSymbolTypes));
   else
-    Fields[4].Str = enumToString(SymbolType, makeArrayRef(ElfSymbolTypes));
+    Fields[4].Str = enumToString(SymbolType, ArrayRef(ElfSymbolTypes));
 
   Fields[5].Str =
-      enumToString(Symbol->getBinding(), makeArrayRef(ElfSymbolBindings));
-  Fields[6].Str = enumToString(Symbol->getVisibility(),
-                               makeArrayRef(ElfSymbolVisibilities));
+      enumToString(Symbol->getBinding(), ArrayRef(ElfSymbolBindings));
+  Fields[6].Str =
+      enumToString(Symbol->getVisibility(), ArrayRef(ElfSymbolVisibilities));
   Fields[7].Str = getSymbolSectionNdx(*Symbol, SymIndex, ShndxTable);
   Fields[8].Str =
       this->getFullSymbolName(*Symbol, SymIndex, ShndxTable, StrTable, true);
@@ -4074,6 +4088,14 @@
 
 template <class ELFT> void GNUELFDumper<ELFT>::printSectionDetails() {
   ArrayRef<Elf_Shdr> Sections = cantFail(this->Obj.sections());
+  if (Sections.empty()) {
+    OS << "\nThere are no sections in this file.\n";
+    Expected<StringRef> SecStrTableOrErr =
+        this->Obj.getSectionStringTable(Sections, this->WarningHandler);
+    if (!SecStrTableOrErr)
+      this->reportUniqueWarning(SecStrTableOrErr.takeError());
+    return;
+  }
   OS << "There are " << to_string(Sections.size())
      << " section headers, starting at offset "
      << "0x" << utohexstr(this->Obj.getHeader().e_shoff, /*LowerCase=*/true) << ":\n\n";
@@ -4171,6 +4193,30 @@
 
     OS << "\n";
     ++SectionIndex;
+
+    if (!(S.sh_flags & SHF_COMPRESSED))
+      continue;
+    Expected<ArrayRef<uint8_t>> Data = this->Obj.getSectionContents(S);
+    if (!Data || Data->size() < sizeof(Elf_Chdr)) {
+      consumeError(Data.takeError());
+      reportWarning(createError("SHF_COMPRESSED section '" + Name +
+                                "' does not have an Elf_Chdr header"),
+                    this->FileName);
+      OS.indent(7);
+      OS << "[<corrupt>]";
+    } else {
+      OS.indent(7);
+      auto *Chdr = reinterpret_cast<const Elf_Chdr *>(Data->data());
+      if (Chdr->ch_type == ELFCOMPRESS_ZLIB)
+        OS << "ZLIB";
+      else if (Chdr->ch_type == ELFCOMPRESS_ZSTD)
+        OS << "ZSTD";
+      else
+        OS << format("[<unknown>: 0x%x]", unsigned(Chdr->ch_type));
+      OS << ", " << format_hex_no_prefix(Chdr->ch_size, ELFT::Is64Bits ? 16 : 8)
+         << ", " << Chdr->ch_addralign;
+    }
+    OS << '\n';
   }
 }
 
@@ -4257,12 +4303,21 @@
 template <class ELFT>
 void GNUELFDumper<ELFT>::printProgramHeaders(
     bool PrintProgramHeaders, cl::boolOrDefault PrintSectionMapping) {
-  if (PrintProgramHeaders)
-    printProgramHeaders();
+  const bool ShouldPrintSectionMapping = (PrintSectionMapping != cl::BOU_FALSE);
+  // Exit early if no program header or section mapping details were requested.
+  if (!PrintProgramHeaders && !ShouldPrintSectionMapping)
+    return;
 
-  // Display the section mapping along with the program headers, unless
-  // -section-mapping is explicitly set to false.
-  if (PrintSectionMapping != cl::BOU_FALSE)
+  if (PrintProgramHeaders) {
+    const Elf_Ehdr &Header = this->Obj.getHeader();
+    if (Header.e_phnum == 0) {
+      OS << "\nThere are no program headers in this file.\n";
+    } else {
+      printProgramHeaders();
+    }
+  }
+
+  if (ShouldPrintSectionMapping)
     printSectionMapping();
 }
 
@@ -4272,7 +4327,7 @@
   Field Fields[8] = {2,         17,        26,        37 + Bias,
                      48 + Bias, 56 + Bias, 64 + Bias, 68 + Bias};
   OS << "\nElf file type is "
-     << enumToString(Header.e_type, makeArrayRef(ElfObjectFileType)) << "\n"
+     << enumToString(Header.e_type, ArrayRef(ElfObjectFileType)) << "\n"
      << "Entry point " << format_hex(Header.e_entry, 3) << "\n"
      << "There are " << Header.e_phnum << " program headers,"
      << " starting at offset " << Header.e_phoff << "\n\n"
@@ -4565,8 +4620,8 @@
     return;
   }
 
-  SmallVector<Optional<VersionEntry>, 0> *VersionMap = nullptr;
-  if (Expected<SmallVector<Optional<VersionEntry>, 0> *> MapOrErr =
+  SmallVector<std::optional<VersionEntry>, 0> *VersionMap = nullptr;
+  if (Expected<SmallVector<std::optional<VersionEntry>, 0> *> MapOrErr =
           this->getVersionMap())
     VersionMap = *MapOrErr;
   else
@@ -4588,7 +4643,7 @@
 
     bool IsDefault;
     Expected<StringRef> NameOrErr = this->Obj.getSymbolVersionByIndex(
-        Ndx, IsDefault, *VersionMap, /*IsSymHidden=*/None);
+        Ndx, IsDefault, *VersionMap, /*IsSymHidden=*/std::nullopt);
     if (!NameOrErr) {
       this->reportUniqueWarning("unable to get a version for entry " +
                                 Twine(I) + " of " + this->describe(*Sec) +
@@ -5039,7 +5094,7 @@
       "Linux", "Hurd", "Solaris", "FreeBSD", "NetBSD", "Syllable", "NaCl",
   };
   StringRef OSName = "Unknown";
-  if (Words[0] < array_lengthof(OSNames))
+  if (Words[0] < std::size(OSNames))
     OSName = OSNames[Words[0]];
   uint32_t Major = Words[1], Minor = Words[2], Patch = Words[3];
   std::string str;
@@ -5178,14 +5233,14 @@
 };
 
 template <typename ELFT>
-static Optional<FreeBSDNote>
+static std::optional<FreeBSDNote>
 getFreeBSDNote(uint32_t NoteType, ArrayRef<uint8_t> Desc, bool IsCore) {
   if (IsCore)
-    return None; // No pretty-printing yet.
+    return std::nullopt; // No pretty-printing yet.
   switch (NoteType) {
   case ELF::NT_FREEBSD_ABI_TAG:
     if (Desc.size() != 4)
-      return None;
+      return std::nullopt;
     return FreeBSDNote{
         "ABI tag",
         utostr(support::endian::read32<ELFT::TargetEndianness>(Desc.data()))};
@@ -5193,12 +5248,12 @@
     return FreeBSDNote{"Arch tag", toStringRef(Desc).str()};
   case ELF::NT_FREEBSD_FEATURE_CTL: {
     if (Desc.size() != 4)
-      return None;
+      return std::nullopt;
     unsigned Value =
         support::endian::read32<ELFT::TargetEndianness>(Desc.data());
     std::string FlagsStr;
     raw_string_ostream OS(FlagsStr);
-    printFlags(Value, makeArrayRef(FreeBSDFeatureCtlFlags), OS);
+    printFlags(Value, ArrayRef(FreeBSDFeatureCtlFlags), OS);
     if (OS.str().empty())
       OS << "0x" << utohexstr(Value);
     else
@@ -5206,7 +5261,7 @@
     return FreeBSDNote{"Feature flags", OS.str()};
   }
   default:
-    return None;
+    return std::nullopt;
   }
 }
 
@@ -5628,7 +5683,7 @@
 template <class ELFT>
 static void printNotesHelper(
     const ELFDumper<ELFT> &Dumper,
-    llvm::function_ref<void(Optional<StringRef>, typename ELFT::Off,
+    llvm::function_ref<void(std::optional<StringRef>, typename ELFT::Off,
                             typename ELFT::Addr)>
         StartNotesFn,
     llvm::function_ref<Error(const typename ELFT::Note &, bool)> ProcessNoteFn,
@@ -5641,7 +5696,7 @@
     for (const typename ELFT::Shdr &S : Sections) {
       if (S.sh_type != SHT_NOTE)
         continue;
-      StartNotesFn(expectedToOptional(Obj.getSectionName(S)), S.sh_offset,
+      StartNotesFn(expectedToStdOptional(Obj.getSectionName(S)), S.sh_offset,
                    S.sh_size);
       Error Err = Error::success();
       size_t I = 0;
@@ -5673,7 +5728,7 @@
     const typename ELFT::Phdr &P = (*PhdrsOrErr)[I];
     if (P.p_type != PT_NOTE)
       continue;
-    StartNotesFn(/*SecName=*/None, P.p_offset, P.p_filesz);
+    StartNotesFn(/*SecName=*/std::nullopt, P.p_offset, P.p_filesz);
     Error Err = Error::success();
     size_t Index = 0;
     for (const typename ELFT::Note Note : Obj.notes(P, Err)) {
@@ -5694,7 +5749,7 @@
 
 template <class ELFT> void GNUELFDumper<ELFT>::printNotes() {
   bool IsFirstHeader = true;
-  auto PrintHeader = [&](Optional<StringRef> SecName,
+  auto PrintHeader = [&](std::optional<StringRef> SecName,
                          const typename ELFT::Off Offset,
                          const typename ELFT::Addr Size) {
     // Print a newline between notes sections to match GNU readelf.
@@ -5737,7 +5792,7 @@
       if (printGNUNote<ELFT>(OS, Type, Descriptor))
         return Error::success();
     } else if (Name == "FreeBSD") {
-      if (Optional<FreeBSDNote> N =
+      if (std::optional<FreeBSDNote> N =
               getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {
         OS << "    " << N->Type << ": " << N->Value << '\n';
         return Error::success();
@@ -5950,7 +6005,7 @@
 
 template <class ELFT>
 SmallVector<uint32_t> ELFDumper<ELFT>::getSymbolIndexesForFunctionAddress(
-    uint64_t SymValue, Optional<const Elf_Shdr *> FunctionSec) {
+    uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec) {
   SmallVector<uint32_t> SymbolIndexes;
   if (!this->AddressToIndexMap) {
     // Populate the address to index map upon the first invocation of this
@@ -6016,7 +6071,7 @@
 
 template <class ELFT>
 bool ELFDumper<ELFT>::printFunctionStackSize(
-    uint64_t SymValue, Optional<const Elf_Shdr *> FunctionSec,
+    uint64_t SymValue, std::optional<const Elf_Shdr *> FunctionSec,
     const Elf_Shdr &StackSizeSec, DataExtractor Data, uint64_t *Offset) {
   SmallVector<uint32_t> FuncSymIndexes =
       this->getSymbolIndexesForFunctionAddress(SymValue, FunctionSec);
@@ -6134,8 +6189,8 @@
         break;
       }
       uint64_t SymValue = Data.getAddress(&Offset);
-      if (!printFunctionStackSize(SymValue, /*FunctionSec=*/None, Sec, Data,
-                                  &Offset))
+      if (!printFunctionStackSize(SymValue, /*FunctionSec=*/std::nullopt, Sec,
+                                  Data, &Offset))
         break;
     }
   }
@@ -6322,7 +6377,7 @@
       OS.PadToColumn(31 + 2 * Bias);
       OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias));
       OS.PadToColumn(40 + 3 * Bias);
-      OS << enumToString(Sym.getType(), makeArrayRef(ElfSymbolTypes));
+      OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes));
       OS.PadToColumn(48 + 3 * Bias);
       OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(),
                                 ShndxTable);
@@ -6376,7 +6431,7 @@
       OS.PadToColumn(20 + 2 * Bias);
       OS << to_string(format_hex_no_prefix(Sym.st_value, 8 + Bias));
       OS.PadToColumn(29 + 3 * Bias);
-      OS << enumToString(Sym.getType(), makeArrayRef(ElfSymbolTypes));
+      OS << enumToString(Sym.getType(), ArrayRef(ElfSymbolTypes));
       OS.PadToColumn(37 + 3 * Bias);
       OS << getSymbolSectionNdx(Sym, &Sym - this->dynamic_symbols().begin(),
                                 ShndxTable);
@@ -6423,15 +6478,15 @@
   OS << "GPR size: " << getMipsRegisterSize(Flags->gpr_size) << "\n";
   OS << "CPR1 size: " << getMipsRegisterSize(Flags->cpr1_size) << "\n";
   OS << "CPR2 size: " << getMipsRegisterSize(Flags->cpr2_size) << "\n";
-  OS << "FP ABI: "
-     << enumToString(Flags->fp_abi, makeArrayRef(ElfMipsFpABIType)) << "\n";
+  OS << "FP ABI: " << enumToString(Flags->fp_abi, ArrayRef(ElfMipsFpABIType))
+     << "\n";
   OS << "ISA Extension: "
-     << enumToString(Flags->isa_ext, makeArrayRef(ElfMipsISAExtType)) << "\n";
+     << enumToString(Flags->isa_ext, ArrayRef(ElfMipsISAExtType)) << "\n";
   if (Flags->ases == 0)
     OS << "ASEs: None\n";
   else
     // FIXME: Print each flag on a separate line.
-    OS << "ASEs: " << printFlags(Flags->ases, makeArrayRef(ElfMipsASEFlags))
+    OS << "ASEs: " << printFlags(Flags->ases, ArrayRef(ElfMipsASEFlags))
        << "\n";
   OS << "FLAGS 1: " << format_hex_no_prefix(Flags->flags1, 8, false) << "\n";
   OS << "FLAGS 2: " << format_hex_no_prefix(Flags->flags2, 8, false) << "\n";
@@ -6444,30 +6499,32 @@
     DictScope D(W, "ElfHeader");
     {
       DictScope D(W, "Ident");
-      W.printBinary("Magic", makeArrayRef(E.e_ident).slice(ELF::EI_MAG0, 4));
-      W.printEnum("Class", E.e_ident[ELF::EI_CLASS], makeArrayRef(ElfClass));
+      W.printBinary("Magic",
+                    ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_MAG0, 4));
+      W.printEnum("Class", E.e_ident[ELF::EI_CLASS], ArrayRef(ElfClass));
       W.printEnum("DataEncoding", E.e_ident[ELF::EI_DATA],
-                  makeArrayRef(ElfDataEncoding));
+                  ArrayRef(ElfDataEncoding));
       W.printNumber("FileVersion", E.e_ident[ELF::EI_VERSION]);
 
-      auto OSABI = makeArrayRef(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 = makeArrayRef(AMDGPUElfOSABI);
+          OSABI = ArrayRef(AMDGPUElfOSABI);
           break;
         case ELF::EM_ARM:
-          OSABI = makeArrayRef(ARMElfOSABI);
+          OSABI = ArrayRef(ARMElfOSABI);
           break;
         case ELF::EM_TI_C6000:
-          OSABI = makeArrayRef(C6000ElfOSABI);
+          OSABI = ArrayRef(C6000ElfOSABI);
           break;
         }
       }
       W.printEnum("OS/ABI", E.e_ident[ELF::EI_OSABI], OSABI);
       W.printNumber("ABIVersion", E.e_ident[ELF::EI_ABIVERSION]);
-      W.printBinary("Unused", makeArrayRef(E.e_ident).slice(ELF::EI_PAD));
+      W.printBinary("Unused",
+                    ArrayRef<unsigned char>(E.e_ident).slice(ELF::EI_PAD));
     }
 
     std::string TypeStr;
@@ -6483,13 +6540,13 @@
     }
     W.printString("Type", TypeStr + " (0x" + utohexstr(E.e_type) + ")");
 
-    W.printEnum("Machine", E.e_machine, makeArrayRef(ElfMachineType));
+    W.printEnum("Machine", E.e_machine, ArrayRef(ElfMachineType));
     W.printNumber("Version", E.e_version);
     W.printHex("Entry", E.e_entry);
     W.printHex("ProgramHeaderOffset", E.e_phoff);
     W.printHex("SectionHeaderOffset", E.e_shoff);
     if (E.e_machine == EM_MIPS)
-      W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderMipsFlags),
+      W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderMipsFlags),
                    unsigned(ELF::EF_MIPS_ARCH), unsigned(ELF::EF_MIPS_ABI),
                    unsigned(ELF::EF_MIPS_MACH));
     else if (E.e_machine == EM_AMDGPU) {
@@ -6499,29 +6556,33 @@
         break;
       case 0:
         // ELFOSABI_AMDGPU_PAL, ELFOSABI_AMDGPU_MESA3D support *_V3 flags.
-        LLVM_FALLTHROUGH;
+        [[fallthrough]];
       case ELF::ELFABIVERSION_AMDGPU_HSA_V3:
         W.printFlags("Flags", E.e_flags,
-                     makeArrayRef(ElfHeaderAMDGPUFlagsABIVersion3),
+                     ArrayRef(ElfHeaderAMDGPUFlagsABIVersion3),
                      unsigned(ELF::EF_AMDGPU_MACH));
         break;
       case ELF::ELFABIVERSION_AMDGPU_HSA_V4:
       case ELF::ELFABIVERSION_AMDGPU_HSA_V5:
         W.printFlags("Flags", E.e_flags,
-                     makeArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),
+                     ArrayRef(ElfHeaderAMDGPUFlagsABIVersion4),
                      unsigned(ELF::EF_AMDGPU_MACH),
                      unsigned(ELF::EF_AMDGPU_FEATURE_XNACK_V4),
                      unsigned(ELF::EF_AMDGPU_FEATURE_SRAMECC_V4));
         break;
       }
     } else if (E.e_machine == EM_RISCV)
-      W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderRISCVFlags));
+      W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderRISCVFlags));
     else if (E.e_machine == EM_AVR)
-      W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderAVRFlags),
+      W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderAVRFlags),
                    unsigned(ELF::EF_AVR_ARCH_MASK));
     else if (E.e_machine == EM_LOONGARCH)
-      W.printFlags("Flags", E.e_flags, makeArrayRef(ElfHeaderLoongArchFlags),
-                   unsigned(ELF::EF_LOONGARCH_BASE_ABI_MASK));
+      W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderLoongArchFlags),
+                   unsigned(ELF::EF_LOONGARCH_ABI_MODIFIER_MASK),
+                   unsigned(ELF::EF_LOONGARCH_OBJABI_MASK));
+    else if (E.e_machine == EM_XTENSA)
+      W.printFlags("Flags", E.e_flags, ArrayRef(ElfHeaderXtensaFlags),
+                   unsigned(ELF::EF_XTENSA_MACH));
     else
       W.printFlags("Flags", E.e_flags);
     W.printNumber("HeaderSize", E.e_ehsize);
@@ -6627,7 +6688,7 @@
                object::getELFSectionTypeName(this->Obj.getHeader().e_machine,
                                              Sec.sh_type),
                Sec.sh_type);
-    W.printFlags("Flags", Sec.sh_flags, makeArrayRef(FlagsList));
+    W.printFlags("Flags", Sec.sh_flags, ArrayRef(FlagsList));
     W.printHex("Address", Sec.sh_addr);
     W.printHex("Offset", Sec.sh_offset);
     W.printNumber("Size", Sec.sh_size);
@@ -6676,7 +6737,7 @@
 void LLVMELFDumper<ELFT>::printSymbolSection(
     const Elf_Sym &Symbol, unsigned SymIndex,
     DataRegion<Elf_Word> ShndxTable) const {
-  auto GetSectionSpecialType = [&]() -> Optional<StringRef> {
+  auto GetSectionSpecialType = [&]() -> std::optional<StringRef> {
     if (Symbol.isUndefined())
       return StringRef("Undefined");
     if (Symbol.isProcessorSpecific())
@@ -6689,10 +6750,10 @@
       return StringRef("Common");
     if (Symbol.isReserved() && Symbol.st_shndx != SHN_XINDEX)
       return StringRef("Reserved");
-    return None;
+    return std::nullopt;
   };
 
-  if (Optional<StringRef> Type = GetSectionSpecialType()) {
+  if (std::optional<StringRef> Type = GetSectionSpecialType()) {
     W.printHex("Section", *Type, Symbol.st_shndx);
     return;
   }
@@ -6726,7 +6787,7 @@
 template <class ELFT>
 void LLVMELFDumper<ELFT>::printSymbol(const Elf_Sym &Symbol, unsigned SymIndex,
                                       DataRegion<Elf_Word> ShndxTable,
-                                      Optional<StringRef> StrTable,
+                                      std::optional<StringRef> StrTable,
                                       bool IsDynamic,
                                       bool /*NonVisibilityBitsUsed*/) const {
   std::string FullSymbolName = this->getFullSymbolName(
@@ -6737,12 +6798,12 @@
   W.printNumber("Name", FullSymbolName, Symbol.st_name);
   W.printHex("Value", Symbol.st_value);
   W.printNumber("Size", Symbol.st_size);
-  W.printEnum("Binding", Symbol.getBinding(), makeArrayRef(ElfSymbolBindings));
+  W.printEnum("Binding", Symbol.getBinding(), ArrayRef(ElfSymbolBindings));
   if (this->Obj.getHeader().e_machine == ELF::EM_AMDGPU &&
       SymbolType >= ELF::STT_LOOS && SymbolType < ELF::STT_HIOS)
-    W.printEnum("Type", SymbolType, makeArrayRef(AMDGPUSymbolTypes));
+    W.printEnum("Type", SymbolType, ArrayRef(AMDGPUSymbolTypes));
   else
-    W.printEnum("Type", SymbolType, makeArrayRef(ElfSymbolTypes));
+    W.printEnum("Type", SymbolType, ArrayRef(ElfSymbolTypes));
   if (Symbol.st_other == 0)
     // Usually st_other flag is zero. Do not pollute the output
     // by flags enumeration in that case.
@@ -6771,7 +6832,7 @@
                            std::begin(ElfRISCVSymOtherFlags),
                            std::end(ElfRISCVSymOtherFlags));
     }
-    W.printFlags("Other", Symbol.st_other, makeArrayRef(SymOtherFlags), 0x3u);
+    W.printFlags("Other", Symbol.st_other, ArrayRef(SymOtherFlags), 0x3u);
   }
   printSymbolSection(Symbol, SymIndex, ShndxTable);
 }
@@ -6854,7 +6915,7 @@
     W.printHex("PhysicalAddress", Phdr.p_paddr);
     W.printNumber("FileSize", Phdr.p_filesz);
     W.printNumber("MemSize", Phdr.p_memsz);
-    W.printFlags("Flags", Phdr.p_flags, makeArrayRef(ElfSegmentFlags));
+    W.printFlags("Flags", Phdr.p_flags, ArrayRef(ElfSegmentFlags));
     W.printNumber("Alignment", Phdr.p_align);
   }
 }
@@ -6908,7 +6969,7 @@
   for (const VerDef &D : *V) {
     DictScope Def(W, "Definition");
     W.printNumber("Version", D.Version);
-    W.printFlags("Flags", D.Flags, makeArrayRef(SymVersionFlags));
+    W.printFlags("Flags", D.Flags, ArrayRef(SymVersionFlags));
     W.printNumber("Index", D.Ndx);
     W.printNumber("Hash", D.Hash);
     W.printString("Name", D.Name.c_str());
@@ -6941,7 +7002,7 @@
     for (const VernAux &Aux : VN.AuxV) {
       DictScope Entry(W, "Entry");
       W.printNumber("Hash", Aux.Hash);
-      W.printFlags("Flags", Aux.Flags, makeArrayRef(SymVersionFlags));
+      W.printFlags("Flags", Aux.Flags, ArrayRef(SymVersionFlags));
       W.printNumber("Index", Aux.Other);
       W.printString("Name", Aux.Name.c_str());
     }
@@ -7053,7 +7114,7 @@
         Sec.sh_type != SHT_LLVM_BB_ADDR_MAP_V0) {
       continue;
     }
-    Optional<const Elf_Shdr *> FunctionSec = None;
+    std::optional<const Elf_Shdr *> FunctionSec;
     if (IsRelocatable)
       FunctionSec =
           unwrapOrError(this->FileName, this->Obj.getSection(Sec.sh_link));
@@ -7082,6 +7143,7 @@
       ListScope L(W, "BB entries");
       for (const BBAddrMap::BBEntry &BBE : AM.BBEntries) {
         DictScope L(W);
+        W.printNumber("ID", BBE.ID);
         W.printHex("Offset", BBE.Offset);
         W.printHex("Size", BBE.Size);
         W.printBoolean("HasReturn", BBE.HasReturn);
@@ -7189,7 +7251,7 @@
   ListScope L(W, "Notes");
 
   std::unique_ptr<DictScope> NoteScope;
-  auto StartNotes = [&](Optional<StringRef> SecName,
+  auto StartNotes = [&](std::optional<StringRef> SecName,
                         const typename ELFT::Off Offset,
                         const typename ELFT::Addr Size) {
     NoteScope = std::make_unique<DictScope>(W, "NoteSection");
@@ -7224,7 +7286,7 @@
       if (printGNUNoteLLVMStyle<ELFT>(Type, Descriptor, W))
         return Error::success();
     } else if (Name == "FreeBSD") {
-      if (Optional<FreeBSDNote> N =
+      if (std::optional<FreeBSDNote> N =
               getFreeBSDNote<ELFT>(Type, Descriptor, IsCore)) {
         W.printString(N->Type, N->Value);
         return Error::success();
@@ -7381,7 +7443,7 @@
 
       const Elf_Sym &Sym = *Parser.getGotSym(&E);
       W.printHex("Value", Sym.st_value);
-      W.printEnum("Type", Sym.getType(), makeArrayRef(ElfSymbolTypes));
+      W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes));
 
       const unsigned SymIndex = &Sym - this->dynamic_symbols().begin();
       DataRegion<Elf_Word> ShndxTable(
@@ -7431,7 +7493,7 @@
 
       const Elf_Sym &Sym = *Parser.getPltSym(&E);
       W.printHex("Value", Sym.st_value);
-      W.printEnum("Type", Sym.getType(), makeArrayRef(ElfSymbolTypes));
+      W.printEnum("Type", Sym.getType(), ArrayRef(ElfSymbolTypes));
       printSymbolSection(Sym, &Sym - this->dynamic_symbols().begin(),
                          ShndxTable);
 
@@ -7468,13 +7530,13 @@
   else
     OS << format("MIPS%ur%u", Flags->isa_level, Flags->isa_rev);
   OS << "\n";
-  W.printEnum("ISA Extension", Flags->isa_ext, makeArrayRef(ElfMipsISAExtType));
-  W.printFlags("ASEs", Flags->ases, makeArrayRef(ElfMipsASEFlags));
-  W.printEnum("FP ABI", Flags->fp_abi, makeArrayRef(ElfMipsFpABIType));
+  W.printEnum("ISA Extension", Flags->isa_ext, ArrayRef(ElfMipsISAExtType));
+  W.printFlags("ASEs", Flags->ases, ArrayRef(ElfMipsASEFlags));
+  W.printEnum("FP ABI", Flags->fp_abi, ArrayRef(ElfMipsFpABIType));
   W.printNumber("GPR size", getMipsRegisterSize(Flags->gpr_size));
   W.printNumber("CPR1 size", getMipsRegisterSize(Flags->cpr1_size));
   W.printNumber("CPR2 size", getMipsRegisterSize(Flags->cpr2_size));
-  W.printFlags("Flags 1", Flags->flags1, makeArrayRef(ElfMipsFlags1));
+  W.printFlags("Flags 1", Flags->flags1, ArrayRef(ElfMipsFlags1));
   W.printHex("Flags 2", Flags->flags2);
 }
 
@@ -7482,7 +7544,7 @@
 void JSONELFDumper<ELFT>::printFileSummary(StringRef FileStr, ObjectFile &Obj,
                                            ArrayRef<std::string> InputFilenames,
                                            const Archive *A) {
-  FileScope = std::make_unique<DictScope>(this->W, FileStr);
+  FileScope = std::make_unique<DictScope>(this->W);
   DictScope D(this->W, "FileSummary");
   this->W.printString("File", FileStr);
   this->W.printString("Format", Obj.getFileFormatName());
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp
index 4931ab5..5b38501 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/MachODumper.cpp
@@ -13,7 +13,6 @@
 #include "ObjDumper.h"
 #include "StackMapPrinter.h"
 #include "llvm-readobj.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Object/MachO.h"
@@ -61,9 +60,9 @@
   uint8_t getSymbolType(const SymbolRef &Symbol) const;
 
   void printSymbols() override;
-  void printSymbols(Optional<SymbolComparator> SymComp) override;
+  void printSymbols(std::optional<SymbolComparator> SymComp) override;
   void printDynamicSymbols() override;
-  void printDynamicSymbols(Optional<SymbolComparator> SymComp) override;
+  void printDynamicSymbols(std::optional<SymbolComparator> SymComp) override;
   void printSymbol(const SymbolRef &Symbol, ScopedPrinter &W);
   void printSymbol(const SymbolRef &Symbol);
 
@@ -432,36 +431,36 @@
 
 template<class MachHeader>
 void MachODumper::printFileHeaders(const MachHeader &Header) {
-  W.printEnum("Magic", Header.magic, makeArrayRef(MachOMagics));
-  W.printEnum("CpuType", Header.cputype, makeArrayRef(MachOHeaderCpuTypes));
+  W.printEnum("Magic", Header.magic, ArrayRef(MachOMagics));
+  W.printEnum("CpuType", Header.cputype, ArrayRef(MachOHeaderCpuTypes));
   uint32_t subtype = Header.cpusubtype & ~MachO::CPU_SUBTYPE_MASK;
   switch (Header.cputype) {
   case MachO::CPU_TYPE_X86:
-    W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX86));
+    W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesX86));
     break;
   case MachO::CPU_TYPE_X86_64:
-    W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesX64));
+    W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesX64));
     break;
   case MachO::CPU_TYPE_ARM:
-    W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM));
+    W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesARM));
     break;
   case MachO::CPU_TYPE_POWERPC:
-    W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesPPC));
+    W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesPPC));
     break;
   case MachO::CPU_TYPE_SPARC:
-    W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesSPARC));
+    W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesSPARC));
     break;
   case MachO::CPU_TYPE_ARM64:
-    W.printEnum("CpuSubType", subtype, makeArrayRef(MachOHeaderCpuSubtypesARM64));
+    W.printEnum("CpuSubType", subtype, ArrayRef(MachOHeaderCpuSubtypesARM64));
     break;
   case MachO::CPU_TYPE_POWERPC64:
   default:
     W.printHex("CpuSubtype", subtype);
   }
-  W.printEnum("FileType", Header.filetype, makeArrayRef(MachOHeaderFileTypes));
+  W.printEnum("FileType", Header.filetype, ArrayRef(MachOHeaderFileTypes));
   W.printNumber("NumOfLoadCommands", Header.ncmds);
   W.printNumber("SizeOfLoadCommands", Header.sizeofcmds);
-  W.printFlags("Flags", Header.flags, makeArrayRef(MachOHeaderFlags));
+  W.printFlags("Flags", Header.flags, ArrayRef(MachOHeaderFlags));
 }
 
 void MachODumper::printSectionHeaders() { return printSectionHeaders(Obj); }
@@ -491,10 +490,9 @@
     W.printNumber("Alignment", MOSection.Alignment);
     W.printHex("RelocationOffset", MOSection.RelocationTableOffset);
     W.printNumber("RelocationCount", MOSection.NumRelocationTableEntries);
-    W.printEnum("Type", MOSection.Flags & 0xFF,
-                makeArrayRef(MachOSectionTypes));
+    W.printEnum("Type", MOSection.Flags & 0xFF, ArrayRef(MachOSectionTypes));
     W.printFlags("Attributes", MOSection.Flags >> 8,
-                 makeArrayRef(MachOSectionAttributes));
+                 ArrayRef(MachOSectionAttributes));
     W.printHex("Reserved1", MOSection.Reserved1);
     W.printHex("Reserved2", MOSection.Reserved2);
     if (Obj->is64Bit())
@@ -634,9 +632,9 @@
   return getSymbolType(LHS) < getSymbolType(RHS);
 }
 
-void MachODumper::printSymbols() { printSymbols(None); }
+void MachODumper::printSymbols() { printSymbols(std::nullopt); }
 
-void MachODumper::printSymbols(Optional<SymbolComparator> SymComp) {
+void MachODumper::printSymbols(std::optional<SymbolComparator> SymComp) {
   ListScope Group(W, "Symbols");
   if (SymComp) {
     auto SymbolRange = Obj->symbols();
@@ -655,7 +653,7 @@
 void MachODumper::printDynamicSymbols() {
   ListScope Group(W, "DynamicSymbols");
 }
-void MachODumper::printDynamicSymbols(Optional<SymbolComparator> SymComp) {
+void MachODumper::printDynamicSymbols(std::optional<SymbolComparator> SymComp) {
   ListScope Group(W, "DynamicSymbols");
 }
 
@@ -695,13 +693,13 @@
     if (MOSymbol.Type & MachO::N_EXT)
       W.startLine() << "Extern\n";
     W.printEnum("Type", uint8_t(MOSymbol.Type & MachO::N_TYPE),
-                makeArrayRef(MachOSymbolTypes));
+                ArrayRef(MachOSymbolTypes));
   }
   W.printHex("Section", SectionName, MOSymbol.SectionIndex);
   W.printEnum("RefType", static_cast<uint16_t>(MOSymbol.Flags & 0x7),
-              makeArrayRef(MachOSymbolRefTypes));
+              ArrayRef(MachOSymbolRefTypes));
   W.printFlags("Flags", static_cast<uint16_t>(MOSymbol.Flags & ~0x7),
-               makeArrayRef(MachOSymbolFlags));
+               ArrayRef(MachOSymbolFlags));
   W.printHex("Value", MOSymbol.Value);
 }
 
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h b/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
index 292efd2..258d872 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/ObjDumper.h
@@ -13,7 +13,6 @@
 #include <memory>
 #include <system_error>
 
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringMap.h"
@@ -85,7 +84,7 @@
       printDynamicSymbols();
   }
   virtual void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols,
-                            llvm::Optional<SymbolComparator> SymComp) {
+                            std::optional<SymbolComparator> SymComp) {
     if (SymComp) {
       if (PrintSymbols)
         printSymbols(SymComp);
@@ -155,8 +154,12 @@
                      llvm::codeview::GlobalTypeTableBuilder &GlobalCVTypes,
                      bool GHash) {}
 
-  // Only implement for XCOFF
+  // Only implemented for XCOFF.
+  virtual void printStringTable() {}
   virtual void printAuxiliaryHeader() {}
+  virtual void printExceptionSection() {}
+  virtual void printLoaderSection(bool PrintHeader, bool PrintSymbols,
+                                  bool PrintRelocations) {}
 
   // Only implemented for MachO.
   virtual void printMachODataInCode() { }
@@ -166,9 +169,6 @@
   virtual void printMachOIndirectSymbols() { }
   virtual void printMachOLinkerOptions() { }
 
-  // Currently only implemented for XCOFF.
-  virtual void printStringTable() { }
-
   virtual void printStackMap() const = 0;
 
   void printAsStringList(StringRef StringContent, size_t StringDataOffset = 0);
@@ -187,9 +187,9 @@
 
 private:
   virtual void printSymbols() {}
-  virtual void printSymbols(llvm::Optional<SymbolComparator> Comp) {}
+  virtual void printSymbols(std::optional<SymbolComparator> Comp) {}
   virtual void printDynamicSymbols() {}
-  virtual void printDynamicSymbols(llvm::Optional<SymbolComparator> Comp) {}
+  virtual void printDynamicSymbols(std::optional<SymbolComparator> Comp) {}
   virtual void printProgramHeaders() {}
   virtual void printSectionMapping() {}
 
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/Opts.td b/src/llvm-project/llvm/tools/llvm-readobj/Opts.td
index 4687fc7..4f7b12f 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/Opts.td
+++ b/src/llvm-project/llvm/tools/llvm-readobj/Opts.td
@@ -88,6 +88,10 @@
 // XCOFF specific options.
 def grp_xcoff : OptionGroup<"kind">, HelpText<"OPTIONS (XCOFF specific)">;
 def auxiliary_header : FF<"auxiliary-header" , "Display the auxiliary header">, Group<grp_xcoff>;
+def exception_section : FF<"exception-section" , "Display the exception section entries">, Group<grp_xcoff>;
+def loader_section_header : FF<"loader-section-header" , "Display the loader section header">, Group<grp_xcoff>;
+def loader_section_symbols : FF<"loader-section-symbols" , "Display the loader section symbol table">, Group<grp_xcoff>;
+def loader_section_relocations : FF<"loader-section-relocations" , "Display the loader section relocation entries">, Group<grp_xcoff>;
 
 def help : FF<"help", "Display this help">;
 def version : FF<"version", "Display the version">;
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp
index cf80a2d..e6f0ac7 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/WasmDumper.cpp
@@ -156,7 +156,7 @@
   for (const SectionRef &Section : Obj->sections()) {
     const WasmSection &WasmSec = Obj->getWasmSection(Section);
     DictScope SectionD(W, "Section");
-    W.printEnum("Type", WasmSec.Type, makeArrayRef(WasmSectionTypes));
+    W.printEnum("Type", WasmSec.Type, ArrayRef(WasmSectionTypes));
     W.printNumber("Size", static_cast<uint64_t>(WasmSec.Content.size()));
     W.printNumber("Offset", WasmSec.Offset);
     switch (WasmSec.Type) {
@@ -221,8 +221,8 @@
   DictScope D(W, "Symbol");
   WasmSymbol Symbol = Obj->getWasmSymbol(Sym.getRawDataRefImpl());
   W.printString("Name", Symbol.Info.Name);
-  W.printEnum("Type", Symbol.Info.Kind, makeArrayRef(WasmSymbolTypes));
-  W.printFlags("Flags", Symbol.Info.Flags, makeArrayRef(WasmSymbolFlags));
+  W.printEnum("Type", Symbol.Info.Kind, ArrayRef(WasmSymbolTypes));
+  W.printFlags("Flags", Symbol.Info.Flags, ArrayRef(WasmSymbolFlags));
 
   if (Symbol.Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) {
     if (Symbol.Info.ImportName) {
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/Win64EHDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/Win64EHDumper.cpp
index da964d3..2896f20 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/Win64EHDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/Win64EHDumper.cpp
@@ -315,11 +315,11 @@
                              off_t Offset, const UnwindInfo &UI) {
   DictScope UIS(SW, "UnwindInfo");
   SW.printNumber("Version", UI.getVersion());
-  SW.printFlags("Flags", UI.getFlags(), makeArrayRef(UnwindFlags));
+  SW.printFlags("Flags", UI.getFlags(), ArrayRef(UnwindFlags));
   SW.printNumber("PrologSize", UI.PrologSize);
   if (UI.getFrameRegister()) {
     SW.printEnum("FrameRegister", UI.getFrameRegister(),
-                 makeArrayRef(UnwindOpInfo));
+                 ArrayRef(UnwindOpInfo));
     SW.printHex("FrameOffset", UI.getFrameOffset());
   } else {
     SW.printString("FrameRegister", StringRef("-"));
@@ -337,7 +337,7 @@
         return;
       }
 
-      printUnwindCode(UI, makeArrayRef(UCI, UCE));
+      printUnwindCode(UI, ArrayRef(UCI, UCE));
       UCI = UCI + UsedSlots - 1;
     }
   }
diff --git a/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
index ccae66f..56f672b 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/XCOFFDumper.cpp
@@ -39,6 +39,9 @@
   void printStackMap() const override;
   void printNeededLibraries() override;
   void printStringTable() override;
+  void printExceptionSection() override;
+  void printLoaderSection(bool PrintHeader, bool PrintSymbols,
+                          bool PrintRelocations) override;
 
   ScopedPrinter &getScopedPrinter() const { return W; }
 
@@ -46,6 +49,9 @@
   template <typename T> void printSectionHeaders(ArrayRef<T> Sections);
   template <typename T> void printGenericSectionHeader(T &Sec) const;
   template <typename T> void printOverflowSectionHeader(T &Sec) const;
+  template <typename T>
+  void printExceptionSectionEntry(const T &ExceptionSectEnt) const;
+  template <typename T> void printExceptionSectionEntries() const;
   template <typename T> const T *getAuxEntPtr(uintptr_t AuxAddress);
   void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr);
   void printCsectAuxEnt(XCOFFCsectAuxRef AuxEntRef);
@@ -62,7 +68,20 @@
   void printRelocations(ArrayRef<Shdr> Sections);
   void printAuxiliaryHeader(const XCOFFAuxiliaryHeader32 *AuxHeader);
   void printAuxiliaryHeader(const XCOFFAuxiliaryHeader64 *AuxHeader);
+  void printLoaderSectionHeader(uintptr_t LoaderSectAddr);
+  void printLoaderSectionSymbols(uintptr_t LoaderSectAddr);
+  template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>
+  void printLoaderSectionSymbolsHelper(uintptr_t LoaderSectAddr);
+  template <typename LoadSectionRelocTy>
+  void printLoaderSectionRelocationEntry(LoadSectionRelocTy *LoaderSecRelEntPtr,
+                                         StringRef SymbolName);
+  void printLoaderSectionRelocationEntries(uintptr_t LoaderSectAddr);
+  template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
+            typename LoaderSectionRelocationEntry>
+  void printLoaderSectionRelocationEntriesHelper(uintptr_t LoaderSectAddr);
+
   const XCOFFObjectFile &Obj;
+  const static int32_t FirstSymIdxOfLoaderSec = 3;
 };
 } // anonymous namespace
 
@@ -129,11 +148,127 @@
     printSectionHeaders(Obj.sections32());
 }
 
-void XCOFFDumper::printRelocations() {
+void XCOFFDumper::printLoaderSection(bool PrintHeader, bool PrintSymbols,
+                                     bool PrintRelocations) {
+  DictScope DS(W, "Loader Section");
+  Expected<uintptr_t> LoaderSectionAddrOrError =
+      Obj.getSectionFileOffsetToRawData(XCOFF::STYP_LOADER);
+  if (!LoaderSectionAddrOrError) {
+    reportUniqueWarning(LoaderSectionAddrOrError.takeError());
+    return;
+  }
+  uintptr_t LoaderSectionAddr = LoaderSectionAddrOrError.get();
+
+  if (LoaderSectionAddr == 0)
+    return;
+
+  W.indent();
+  if (PrintHeader)
+    printLoaderSectionHeader(LoaderSectionAddr);
+
+  if (PrintSymbols)
+    printLoaderSectionSymbols(LoaderSectionAddr);
+
+  if (PrintRelocations)
+    printLoaderSectionRelocationEntries(LoaderSectionAddr);
+
+  W.unindent();
+}
+
+void XCOFFDumper::printLoaderSectionHeader(uintptr_t LoaderSectionAddr) {
+  DictScope DS(W, "Loader Section Header");
+
+  auto PrintLoadSecHeaderCommon = [&](const auto *LDHeader) {
+    W.printNumber("Version", LDHeader->Version);
+    W.printNumber("NumberOfSymbolEntries", LDHeader->NumberOfSymTabEnt);
+    W.printNumber("NumberOfRelocationEntries", LDHeader->NumberOfRelTabEnt);
+    W.printNumber("LengthOfImportFileIDStringTable",
+                  LDHeader->LengthOfImpidStrTbl);
+    W.printNumber("NumberOfImportFileIDs", LDHeader->NumberOfImpid);
+    W.printHex("OffsetToImportFileIDs", LDHeader->OffsetToImpid);
+    W.printNumber("LengthOfStringTable", LDHeader->LengthOfStrTbl);
+    W.printHex("OffsetToStringTable", LDHeader->OffsetToStrTbl);
+  };
+
+  if (Obj.is64Bit()) {
+    const LoaderSectionHeader64 *LoaderSec64 =
+        reinterpret_cast<const LoaderSectionHeader64 *>(LoaderSectionAddr);
+    PrintLoadSecHeaderCommon(LoaderSec64);
+    W.printHex("OffsetToSymbolTable", LoaderSec64->OffsetToSymTbl);
+    W.printHex("OffsetToRelocationEntries", LoaderSec64->OffsetToRelEnt);
+  } else {
+    const LoaderSectionHeader32 *LoaderSec32 =
+        reinterpret_cast<const LoaderSectionHeader32 *>(LoaderSectionAddr);
+    PrintLoadSecHeaderCommon(LoaderSec32);
+  }
+}
+
+const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
+#define ECase(X)                                                               \
+  { #X, XCOFF::X }
+    ECase(C_NULL),  ECase(C_AUTO),    ECase(C_EXT),     ECase(C_STAT),
+    ECase(C_REG),   ECase(C_EXTDEF),  ECase(C_LABEL),   ECase(C_ULABEL),
+    ECase(C_MOS),   ECase(C_ARG),     ECase(C_STRTAG),  ECase(C_MOU),
+    ECase(C_UNTAG), ECase(C_TPDEF),   ECase(C_USTATIC), ECase(C_ENTAG),
+    ECase(C_MOE),   ECase(C_REGPARM), ECase(C_FIELD),   ECase(C_BLOCK),
+    ECase(C_FCN),   ECase(C_EOS),     ECase(C_FILE),    ECase(C_LINE),
+    ECase(C_ALIAS), ECase(C_HIDDEN),  ECase(C_HIDEXT),  ECase(C_BINCL),
+    ECase(C_EINCL), ECase(C_INFO),    ECase(C_WEAKEXT), ECase(C_DWARF),
+    ECase(C_GSYM),  ECase(C_LSYM),    ECase(C_PSYM),    ECase(C_RSYM),
+    ECase(C_RPSYM), ECase(C_STSYM),   ECase(C_TCSYM),   ECase(C_BCOMM),
+    ECase(C_ECOML), ECase(C_ECOMM),   ECase(C_DECL),    ECase(C_ENTRY),
+    ECase(C_FUN),   ECase(C_BSTAT),   ECase(C_ESTAT),   ECase(C_GTLS),
+    ECase(C_STTLS), ECase(C_EFCN)
+#undef ECase
+};
+
+template <typename LoaderSectionSymbolEntry, typename LoaderSectionHeader>
+void XCOFFDumper::printLoaderSectionSymbolsHelper(uintptr_t LoaderSectionAddr) {
+  const LoaderSectionHeader *LoadSecHeader =
+      reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);
+  const LoaderSectionSymbolEntry *LoadSecSymEntPtr =
+      reinterpret_cast<LoaderSectionSymbolEntry *>(
+          LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()));
+
+  for (uint32_t i = 0; i < LoadSecHeader->NumberOfSymTabEnt;
+       ++i, ++LoadSecSymEntPtr) {
+    if (Error E = Binary::checkOffset(
+            Obj.getMemoryBufferRef(),
+            LoaderSectionAddr + uintptr_t(LoadSecHeader->getOffsetToSymTbl()) +
+                (i * sizeof(LoaderSectionSymbolEntry)),
+            sizeof(LoaderSectionSymbolEntry))) {
+      reportUniqueWarning(std::move(E));
+      return;
+    }
+
+    Expected<StringRef> SymbolNameOrErr =
+        LoadSecSymEntPtr->getSymbolName(LoadSecHeader);
+    if (!SymbolNameOrErr) {
+      reportUniqueWarning(SymbolNameOrErr.takeError());
+      return;
+    }
+
+    DictScope DS(W, "Symbol");
+    W.printString("Name", SymbolNameOrErr.get());
+    W.printHex("Virtual Address", LoadSecSymEntPtr->Value);
+    W.printNumber("SectionNum", LoadSecSymEntPtr->SectionNumber);
+    W.printHex("SymbolType", LoadSecSymEntPtr->SymbolType);
+    W.printEnum("StorageClass",
+                static_cast<uint8_t>(LoadSecSymEntPtr->StorageClass),
+                ArrayRef(SymStorageClass));
+    W.printHex("ImportFileID", LoadSecSymEntPtr->ImportFileID);
+    W.printNumber("ParameterTypeCheck", LoadSecSymEntPtr->ParameterTypeCheck);
+  }
+}
+
+void XCOFFDumper::printLoaderSectionSymbols(uintptr_t LoaderSectionAddr) {
+  DictScope DS(W, "Loader Section Symbols");
   if (Obj.is64Bit())
-    printRelocations<XCOFFSectionHeader64, XCOFFRelocation64>(Obj.sections64());
+    printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry64,
+                                    LoaderSectionHeader64>(LoaderSectionAddr);
   else
-    printRelocations<XCOFFSectionHeader32, XCOFFRelocation32>(Obj.sections32());
+    printLoaderSectionSymbolsHelper<LoaderSectionSymbolEntry32,
+                                    LoaderSectionHeader32>(LoaderSectionAddr);
 }
 
 const EnumEntry<XCOFF::RelocationType> RelocationTypeNameclass[] = {
@@ -148,6 +283,176 @@
 #undef ECase
 };
 
+// From the XCOFF specification: there are five implicit external symbols, one
+// each for the .text, .data, .bss, .tdata, and .tbss sections. These symbols
+// are referenced from the relocation table entries using symbol table index
+// values 0, 1, 2, -1, and -2, respectively.
+static const char *getImplicitLoaderSectionSymName(int SymIndx) {
+  switch (SymIndx) {
+  default:
+    return "Unkown Symbol Name";
+  case -2:
+    return ".tbss";
+  case -1:
+    return ".tdata";
+  case 0:
+    return ".text";
+  case 1:
+    return ".data";
+  case 2:
+    return ".bss";
+  }
+}
+
+template <typename LoadSectionRelocTy>
+void XCOFFDumper::printLoaderSectionRelocationEntry(
+    LoadSectionRelocTy *LoaderSecRelEntPtr, StringRef SymbolName) {
+  uint16_t Type = LoaderSecRelEntPtr->Type;
+  if (opts::ExpandRelocs) {
+    DictScope DS(W, "Relocation");
+    auto IsRelocationSigned = [](uint8_t Info) {
+      return Info & XCOFF::XR_SIGN_INDICATOR_MASK;
+    };
+    auto IsFixupIndicated = [](uint8_t Info) {
+      return Info & XCOFF::XR_FIXUP_INDICATOR_MASK;
+    };
+    auto GetRelocatedLength = [](uint8_t Info) {
+      // The relocation encodes the bit length being relocated minus 1. Add
+      // back
+      //   the 1 to get the actual length being relocated.
+      return (Info & XCOFF::XR_BIASED_LENGTH_MASK) + 1;
+    };
+
+    uint8_t Info = Type >> 8;
+    W.printHex("Virtual Address", LoaderSecRelEntPtr->VirtualAddr);
+    W.printNumber("Symbol", SymbolName, LoaderSecRelEntPtr->SymbolIndex);
+    W.printString("IsSigned", IsRelocationSigned(Info) ? "Yes" : "No");
+    W.printNumber("FixupBitValue", IsFixupIndicated(Info) ? 1 : 0);
+    W.printNumber("Length", GetRelocatedLength(Info));
+    W.printEnum("Type", static_cast<uint8_t>(Type),
+                ArrayRef(RelocationTypeNameclass));
+    W.printNumber("SectionNumber", LoaderSecRelEntPtr->SectionNum);
+  } else {
+    W.startLine() << format_hex(LoaderSecRelEntPtr->VirtualAddr,
+                                Obj.is64Bit() ? 18 : 10)
+                  << " " << format_hex(Type, 6) << " ("
+                  << XCOFF::getRelocationTypeString(
+                         static_cast<XCOFF::RelocationType>(Type))
+                  << ")" << format_decimal(LoaderSecRelEntPtr->SectionNum, 8)
+                  << "    " << SymbolName << " ("
+                  << LoaderSecRelEntPtr->SymbolIndex << ")\n";
+  }
+}
+
+template <typename LoaderSectionHeader, typename LoaderSectionSymbolEntry,
+          typename LoaderSectionRelocationEntry>
+void XCOFFDumper::printLoaderSectionRelocationEntriesHelper(
+    uintptr_t LoaderSectionAddr) {
+  const LoaderSectionHeader *LoaderSec =
+      reinterpret_cast<const LoaderSectionHeader *>(LoaderSectionAddr);
+  const LoaderSectionRelocationEntry *LoaderSecRelEntPtr =
+      reinterpret_cast<const LoaderSectionRelocationEntry *>(
+          LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToRelEnt()));
+
+  if (!opts::ExpandRelocs)
+    W.startLine() << center_justify("Vaddr", Obj.is64Bit() ? 18 : 10)
+                  << center_justify("Type", 15) << right_justify("SecNum", 8)
+                  << center_justify("SymbolName (Index) ", 24) << "\n";
+
+  for (uint32_t i = 0; i < LoaderSec->NumberOfRelTabEnt;
+       ++i, ++LoaderSecRelEntPtr) {
+    StringRef SymbolName;
+    if (LoaderSecRelEntPtr->SymbolIndex >= FirstSymIdxOfLoaderSec) {
+      // Because there are implicit symbol index values (-2, -1, 0, 1, 2),
+      // LoaderSecRelEnt.SymbolIndex - FirstSymIdxOfLoaderSec will get the
+      // real symbol from the symbol table.
+      const uint64_t SymOffset =
+          (LoaderSecRelEntPtr->SymbolIndex - FirstSymIdxOfLoaderSec) *
+          sizeof(LoaderSectionSymbolEntry);
+      const LoaderSectionSymbolEntry *LoaderSecRelSymEntPtr =
+          reinterpret_cast<LoaderSectionSymbolEntry *>(
+              LoaderSectionAddr + uintptr_t(LoaderSec->getOffsetToSymTbl()) +
+              SymOffset);
+
+      Expected<StringRef> SymbolNameOrErr =
+          LoaderSecRelSymEntPtr->getSymbolName(LoaderSec);
+      if (!SymbolNameOrErr) {
+        reportUniqueWarning(SymbolNameOrErr.takeError());
+        return;
+      }
+      SymbolName = SymbolNameOrErr.get();
+    } else
+      SymbolName =
+          getImplicitLoaderSectionSymName(LoaderSecRelEntPtr->SymbolIndex);
+
+    printLoaderSectionRelocationEntry(LoaderSecRelEntPtr, SymbolName);
+  }
+}
+
+void XCOFFDumper::printLoaderSectionRelocationEntries(
+    uintptr_t LoaderSectionAddr) {
+  DictScope DS(W, "Loader Section Relocations");
+
+  if (Obj.is64Bit())
+    printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader64,
+                                              LoaderSectionSymbolEntry64,
+                                              LoaderSectionRelocationEntry64>(
+        LoaderSectionAddr);
+  else
+    printLoaderSectionRelocationEntriesHelper<LoaderSectionHeader32,
+                                              LoaderSectionSymbolEntry32,
+                                              LoaderSectionRelocationEntry32>(
+        LoaderSectionAddr);
+}
+
+template <typename T>
+void XCOFFDumper::printExceptionSectionEntry(const T &ExceptionSectEnt) const {
+  if (ExceptionSectEnt.getReason())
+    W.printHex("Trap Instr Addr", ExceptionSectEnt.getTrapInstAddr());
+  else {
+    uint32_t SymIdx = ExceptionSectEnt.getSymbolIndex();
+    Expected<StringRef> ErrOrSymbolName = Obj.getSymbolNameByIndex(SymIdx);
+    if (Error E = ErrOrSymbolName.takeError()) {
+      reportUniqueWarning(std::move(E));
+      return;
+    }
+    StringRef SymName = *ErrOrSymbolName;
+
+    W.printNumber("Symbol", SymName, SymIdx);
+  }
+  W.printNumber("LangID", ExceptionSectEnt.getLangID());
+  W.printNumber("Reason", ExceptionSectEnt.getReason());
+}
+
+template <typename T> void XCOFFDumper::printExceptionSectionEntries() const {
+  Expected<ArrayRef<T>> ExceptSectEntsOrErr = Obj.getExceptionEntries<T>();
+  if (Error E = ExceptSectEntsOrErr.takeError()) {
+    reportUniqueWarning(std::move(E));
+    return;
+  }
+  ArrayRef<T> ExceptSectEnts = *ExceptSectEntsOrErr;
+
+  DictScope DS(W, "Exception section");
+  if (ExceptSectEnts.empty())
+    return;
+  for (auto &Ent : ExceptSectEnts)
+    printExceptionSectionEntry(Ent);
+}
+
+void XCOFFDumper::printExceptionSection() {
+  if (Obj.is64Bit())
+    printExceptionSectionEntries<ExceptionSectionEntry64>();
+  else
+    printExceptionSectionEntries<ExceptionSectionEntry32>();
+}
+
+void XCOFFDumper::printRelocations() {
+  if (Obj.is64Bit())
+    printRelocations<XCOFFSectionHeader64, XCOFFRelocation64>(Obj.sections64());
+  else
+    printRelocations<XCOFFSectionHeader32, XCOFFRelocation32>(Obj.sections32());
+}
+
 template <typename RelTy> void XCOFFDumper::printRelocation(RelTy Reloc) {
   Expected<StringRef> ErrOrSymbolName =
       Obj.getSymbolNameByIndex(Reloc.SymbolIndex);
@@ -164,8 +469,7 @@
     W.printString("IsSigned", Reloc.isRelocationSigned() ? "Yes" : "No");
     W.printNumber("FixupBitValue", Reloc.isFixupIndicated() ? 1 : 0);
     W.printNumber("Length", Reloc.getRelocatedLength());
-    W.printEnum("Type", (uint8_t)Reloc.Type,
-                makeArrayRef(RelocationTypeNameclass));
+    W.printEnum("Type", (uint8_t)Reloc.Type, ArrayRef(RelocationTypeNameclass));
   } else {
     raw_ostream &OS = W.startLine();
     OS << W.hex(Reloc.VirtualAddress) << " " << RelocName << " " << SymbolName
@@ -230,10 +534,10 @@
                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
   W.printString("Name", FileName);
   W.printEnum("Type", static_cast<uint8_t>(AuxEntPtr->Type),
-              makeArrayRef(FileStringType));
+              ArrayRef(FileStringType));
   if (Obj.is64Bit()) {
     W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
-                makeArrayRef(SymAuxType));
+                ArrayRef(SymAuxType));
   }
 }
 
@@ -271,14 +575,14 @@
   // Print out symbol alignment and type.
   W.printNumber("SymbolAlignmentLog2", AuxEntRef.getAlignmentLog2());
   W.printEnum("SymbolType", AuxEntRef.getSymbolType(),
-              makeArrayRef(CsectSymbolTypeClass));
+              ArrayRef(CsectSymbolTypeClass));
   W.printEnum("StorageMappingClass",
               static_cast<uint8_t>(AuxEntRef.getStorageMappingClass()),
-              makeArrayRef(CsectStorageMappingClass));
+              ArrayRef(CsectStorageMappingClass));
 
   if (Obj.is64Bit()) {
     W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_CSECT),
-                makeArrayRef(SymAuxType));
+                ArrayRef(SymAuxType));
   } else {
     W.printHex("StabInfoIndex", AuxEntRef.getStabInfoIndex32());
     W.printHex("StabSectNum", AuxEntRef.getStabSectNum32());
@@ -310,7 +614,7 @@
   W.printHex("SizeOfFunction", AuxEntPtr->SizeOfFunction);
   W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
   W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
-              makeArrayRef(SymAuxType));
+              ArrayRef(SymAuxType));
 }
 
 void XCOFFDumper::printFunctionAuxEnt(const XCOFFFunctionAuxEnt32 *AuxEntPtr) {
@@ -335,7 +639,7 @@
   W.printHex("PointerToLineNum", AuxEntPtr->PtrToLineNum);
   W.printNumber("SymbolIndexOfNextBeyond", AuxEntPtr->SymIdxOfNextBeyond);
   W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
-              makeArrayRef(SymAuxType));
+              ArrayRef(SymAuxType));
 }
 
 void XCOFFDumper::printBlockAuxEnt(const XCOFFBlockAuxEnt32 *AuxEntPtr) {
@@ -356,7 +660,7 @@
                 Obj.getSymbolIndex(reinterpret_cast<uintptr_t>(AuxEntPtr)));
   W.printHex("LineNumber", AuxEntPtr->LineNum);
   W.printEnum("Auxiliary Type", static_cast<uint8_t>(AuxEntPtr->AuxType),
-              makeArrayRef(SymAuxType));
+              ArrayRef(SymAuxType));
 }
 
 template <typename T>
@@ -368,28 +672,9 @@
   W.printNumber("NumberOfRelocEntries", AuxEntPtr->NumberOfRelocEnt);
   if (Obj.is64Bit())
     W.printEnum("Auxiliary Type", static_cast<uint8_t>(XCOFF::AUX_SECT),
-                makeArrayRef(SymAuxType));
+                ArrayRef(SymAuxType));
 }
 
-const EnumEntry<XCOFF::StorageClass> SymStorageClass[] = {
-#define ECase(X)                                                               \
-  { #X, XCOFF::X }
-    ECase(C_NULL),  ECase(C_AUTO),    ECase(C_EXT),     ECase(C_STAT),
-    ECase(C_REG),   ECase(C_EXTDEF),  ECase(C_LABEL),   ECase(C_ULABEL),
-    ECase(C_MOS),   ECase(C_ARG),     ECase(C_STRTAG),  ECase(C_MOU),
-    ECase(C_UNTAG), ECase(C_TPDEF),   ECase(C_USTATIC), ECase(C_ENTAG),
-    ECase(C_MOE),   ECase(C_REGPARM), ECase(C_FIELD),   ECase(C_BLOCK),
-    ECase(C_FCN),   ECase(C_EOS),     ECase(C_FILE),    ECase(C_LINE),
-    ECase(C_ALIAS), ECase(C_HIDDEN),  ECase(C_HIDEXT),  ECase(C_BINCL),
-    ECase(C_EINCL), ECase(C_INFO),    ECase(C_WEAKEXT), ECase(C_DWARF),
-    ECase(C_GSYM),  ECase(C_LSYM),    ECase(C_PSYM),    ECase(C_RSYM),
-    ECase(C_RPSYM), ECase(C_STSYM),   ECase(C_TCSYM),   ECase(C_BCOMM),
-    ECase(C_ECOML), ECase(C_ECOMM),   ECase(C_DECL),    ECase(C_ENTRY),
-    ECase(C_FUN),   ECase(C_BSTAT),   ECase(C_ESTAT),   ECase(C_GTLS),
-    ECase(C_STTLS), ECase(C_EFCN)
-#undef ECase
-};
-
 static StringRef GetSymbolValueName(XCOFF::StorageClass SC) {
   switch (SC) {
   case XCOFF::C_EXT:
@@ -447,7 +732,7 @@
                        ArrayRef<uint8_t>(
                            reinterpret_cast<const uint8_t *>(AuxAddress),
                            XCOFF::SymbolTableEntrySize),
-                       None, XCOFF::SymbolTableEntrySize)
+                       std::nullopt, XCOFF::SymbolTableEntrySize)
                 << "\n";
 }
 
@@ -475,14 +760,14 @@
   W.printString("Section", SectionName);
   if (SymbolClass == XCOFF::C_FILE) {
     W.printEnum("Source Language ID", SymbolEntRef.getLanguageIdForCFile(),
-                makeArrayRef(CFileLangIdClass));
+                ArrayRef(CFileLangIdClass));
     W.printEnum("CPU Version ID", SymbolEntRef.getCPUTypeIddForCFile(),
-                makeArrayRef(CFileCpuIdClass));
+                ArrayRef(CFileCpuIdClass));
   } else
     W.printHex("Type", SymbolEntRef.getSymbolType());
 
   W.printEnum("StorageClass", static_cast<uint8_t>(SymbolClass),
-              makeArrayRef(SymStorageClass));
+              ArrayRef(SymStorageClass));
   W.printNumber("NumberOfAuxEntries", NumberOfAuxEntries);
 
   if (NumberOfAuxEntries == 0)
@@ -492,7 +777,7 @@
     if (NumberOfAuxEntries > 1)
       reportUniqueWarning("the " +
                           enumToString(static_cast<uint8_t>(SymbolClass),
-                                       makeArrayRef(SymStorageClass)) +
+                                       ArrayRef(SymStorageClass)) +
                           " symbol at index " + Twine(SymbolIdx) +
                           " should not have more than 1 "
                           "auxiliary entry");
@@ -519,22 +804,13 @@
   case XCOFF::C_EXT:
   case XCOFF::C_WEAKEXT:
   case XCOFF::C_HIDEXT: {
-    if (!SymbolEntRef.isFunction() && NumberOfAuxEntries > 1)
-      reportUniqueWarning("the non-function " +
-                          enumToString(static_cast<uint8_t>(SymbolClass),
-                                       makeArrayRef(SymStorageClass)) +
-                          " symbol at index " + Twine(SymbolIdx) +
-                          " should have only 1 auxiliary entry, i.e. the CSECT "
-                          "auxiliary entry");
-
     // For 32-bit objects, print the function auxiliary symbol table entry. The
     // last one must be a CSECT auxiliary entry.
     // For 64-bit objects, both a function auxiliary entry and an exception
     // auxiliary entry may appear, print them in the loop and skip printing the
     // CSECT auxiliary entry, which will be printed outside the loop.
     for (int I = 1; I <= NumberOfAuxEntries; I++) {
-      if ((I == NumberOfAuxEntries && !Obj.is64Bit()) ||
-          !SymbolEntRef.isFunction())
+      if (I == NumberOfAuxEntries && !Obj.is64Bit())
         break;
 
       uintptr_t AuxAddress = XCOFFObjectFile::getAdvancedSymbolEntryAddress(
@@ -921,7 +1197,7 @@
     if (Sec.isReservedSectionType())
       W.printHex("Flags", "Reserved", SectionType);
     else
-      W.printEnum("Type", SectionType, makeArrayRef(SectionTypeFlagsNames));
+      W.printEnum("Type", SectionType, ArrayRef(SectionTypeFlagsNames));
   }
 
   if (opts::SectionRelocations)
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 e1ebbeb..a11de35 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -21,7 +21,6 @@
 #include "llvm-readobj.h"
 #include "ObjDumper.h"
 #include "WindowsResourceDumper.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
 #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
 #include "llvm/MC/TargetRegistry.h"
@@ -62,11 +61,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#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
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -78,9 +80,11 @@
 #undef OPTION
 };
 
-class ReadobjOptTable : public opt::OptTable {
+class ReadobjOptTable : public opt::GenericOptTable {
 public:
-  ReadobjOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  ReadobjOptTable() : opt::GenericOptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 
 enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols };
@@ -162,6 +166,10 @@
 
 // XCOFF specific options.
 static bool XCOFFAuxiliaryHeader;
+static bool XCOFFLoaderSectionHeader;
+static bool XCOFFLoaderSectionSymbol;
+static bool XCOFFLoaderSectionRelocation;
+static bool XCOFFExceptionSection;
 
 OutputStyleTy Output = OutputStyleTy::LLVM;
 static std::vector<std::string> InputFilenames;
@@ -302,6 +310,11 @@
 
   // XCOFF specific options.
   opts::XCOFFAuxiliaryHeader = Args.hasArg(OPT_auxiliary_header);
+  opts::XCOFFLoaderSectionHeader = Args.hasArg(OPT_loader_section_header);
+  opts::XCOFFLoaderSectionSymbol = Args.hasArg(OPT_loader_section_symbols);
+  opts::XCOFFLoaderSectionRelocation =
+      Args.hasArg(OPT_loader_section_relocations);
+  opts::XCOFFExceptionSection = Args.hasArg(OPT_exception_section);
 
   opts::InputFilenames = Args.getAllArgValues(OPT_INPUT);
 }
@@ -357,7 +370,7 @@
                        toString(std::move(ContentErr));
 
   ObjDumper *Dumper;
-  Optional<SymbolComparator> SymComp;
+  std::optional<SymbolComparator> SymComp;
   Expected<std::unique_ptr<ObjDumper>> DumperOrErr = createDumper(Obj, Writer);
   if (!DumperOrErr)
     reportError(DumperOrErr.takeError(), FileStr);
@@ -395,6 +408,8 @@
   if (opts::FileHeaders)
     Dumper->printFileHeaders();
 
+  // Auxiliary header in XOCFF is right after the file header, so print the data
+  // here.
   if (Obj.isXCOFF() && opts::XCOFFAuxiliaryHeader)
     Dumper->printAuxiliaryHeader();
 
@@ -502,6 +517,18 @@
     if (opts::CGProfile)
       Dumper->printCGProfile();
   }
+
+  if (Obj.isXCOFF()) {
+    if (opts::XCOFFLoaderSectionHeader || opts::XCOFFLoaderSectionSymbol ||
+        opts::XCOFFLoaderSectionRelocation)
+      Dumper->printLoaderSection(opts::XCOFFLoaderSectionHeader,
+                                 opts::XCOFFLoaderSectionSymbol,
+                                 opts::XCOFFLoaderSectionRelocation);
+
+    if (opts::XCOFFExceptionSection)
+      Dumper->printExceptionSection();
+  }
+
   if (opts::PrintStackMap)
     Dumper->printStackMap();
   if (opts::PrintStackSizes)
@@ -605,7 +632,7 @@
   return std::make_unique<ScopedPrinter>(fouts());
 }
 
-int main(int argc, char *argv[]) {
+int llvm_readobj_main(int argc, char **argv) {
   InitLLVM X(argc, argv);
   BumpPtrAllocator A;
   StringSaver Saver(A);
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 989cd0a..5a9fe28 100644
--- a/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.h
+++ b/src/llvm-project/llvm/tools/llvm-readobj/llvm-readobj.h
@@ -50,6 +50,6 @@
   { #enum, ns::enum }
 
 #define LLVM_READOBJ_ENUM_CLASS_ENT(enum_class, enum) \
-  { #enum, std::underlying_type<enum_class>::type(enum_class::enum) }
+  { #enum, std::underlying_type_t<enum_class>(enum_class::enum) }
 
 #endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt
index fe6619d3..b1e8fec 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-reduce/CMakeLists.txt
@@ -11,8 +11,10 @@
   IRReader
   MC
   MIRParser
+  Passes
   Support
   Target
+  TargetParser
   TransformUtils
   IPO
   )
@@ -27,6 +29,7 @@
   deltas/ReduceArguments.cpp
   deltas/ReduceAttributes.cpp
   deltas/ReduceBasicBlocks.cpp
+  deltas/ReduceDIMetadata.cpp
   deltas/ReduceFunctionBodies.cpp
   deltas/ReduceFunctions.cpp
   deltas/ReduceGlobalObjects.cpp
@@ -34,9 +37,13 @@
   deltas/ReduceGlobalVarInitializers.cpp
   deltas/ReduceGlobalVars.cpp
   deltas/ReduceInstructions.cpp
+  deltas/ReduceInstructionFlags.cpp
+  deltas/ReduceInvokes.cpp
   deltas/ReduceMetadata.cpp
   deltas/ReduceModuleData.cpp
+  deltas/ReduceMemoryOperations.cpp
   deltas/ReduceOperandBundles.cpp
+  deltas/ReduceOpcodes.cpp
   deltas/ReduceSpecialGlobals.cpp
   deltas/ReduceOperands.cpp
   deltas/ReduceOperandsSkip.cpp
@@ -48,7 +55,10 @@
   deltas/ReduceRegisterMasks.cpp
   deltas/ReduceRegisterDefs.cpp
   deltas/ReduceRegisterUses.cpp
+  deltas/ReduceUsingSimplifyCFG.cpp
+  deltas/RunIRPasses.cpp
   deltas/SimplifyInstructions.cpp
+  deltas/StripDebugInfo.cpp
   llvm-reduce.cpp
 
   DEPENDS
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.cpp b/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.cpp
index 5e9ad51..bfe299c 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.cpp
@@ -19,6 +19,7 @@
 #include "deltas/ReduceArguments.h"
 #include "deltas/ReduceAttributes.h"
 #include "deltas/ReduceBasicBlocks.h"
+#include "deltas/ReduceDIMetadata.h"
 #include "deltas/ReduceFunctionBodies.h"
 #include "deltas/ReduceFunctions.h"
 #include "deltas/ReduceGlobalObjects.h"
@@ -26,11 +27,15 @@
 #include "deltas/ReduceGlobalVarInitializers.h"
 #include "deltas/ReduceGlobalVars.h"
 #include "deltas/ReduceIRReferences.h"
+#include "deltas/ReduceInstructionFlags.h"
 #include "deltas/ReduceInstructionFlagsMIR.h"
 #include "deltas/ReduceInstructions.h"
 #include "deltas/ReduceInstructionsMIR.h"
+#include "deltas/ReduceInvokes.h"
+#include "deltas/ReduceMemoryOperations.h"
 #include "deltas/ReduceMetadata.h"
 #include "deltas/ReduceModuleData.h"
+#include "deltas/ReduceOpcodes.h"
 #include "deltas/ReduceOperandBundles.h"
 #include "deltas/ReduceOperands.h"
 #include "deltas/ReduceOperandsSkip.h"
@@ -39,34 +44,57 @@
 #include "deltas/ReduceRegisterMasks.h"
 #include "deltas/ReduceRegisterUses.h"
 #include "deltas/ReduceSpecialGlobals.h"
+#include "deltas/ReduceUsingSimplifyCFG.h"
 #include "deltas/ReduceVirtualRegisters.h"
+#include "deltas/RunIRPasses.h"
 #include "deltas/SimplifyInstructions.h"
+#include "deltas/StripDebugInfo.h"
+#include "llvm/ADT/SmallSet.h"
 #include "llvm/Support/CommandLine.h"
 
 using namespace llvm;
 
+using SmallStringSet = SmallSet<StringRef, 8>;
+
 extern cl::OptionCategory LLVMReduceOptions;
-static cl::opt<std::string>
+static cl::list<std::string>
     DeltaPasses("delta-passes",
                 cl::desc("Delta passes to run, separated by commas. By "
                          "default, run all delta passes."),
-                cl::cat(LLVMReduceOptions));
+                cl::cat(LLVMReduceOptions), cl::CommaSeparated);
+
+static cl::list<std::string>
+    SkipDeltaPasses("skip-delta-passes",
+                    cl::desc("Delta passes to not run, separated by commas. By "
+                             "default, run all delta passes."),
+                    cl::cat(LLVMReduceOptions), cl::CommaSeparated);
 
 #define DELTA_PASSES                                                           \
   do {                                                                         \
+    DELTA_PASS("strip-debug-info", stripDebugInfoDeltaPass)                    \
+    DELTA_PASS("functions", reduceFunctionsDeltaPass)                          \
+    DELTA_PASS("function-bodies", reduceFunctionBodiesDeltaPass)               \
     DELTA_PASS("special-globals", reduceSpecialGlobalsDeltaPass)               \
     DELTA_PASS("aliases", reduceAliasesDeltaPass)                              \
-    DELTA_PASS("function-bodies", reduceFunctionBodiesDeltaPass)               \
-    DELTA_PASS("functions", reduceFunctionsDeltaPass)                          \
+    DELTA_PASS("ifuncs", reduceIFuncsDeltaPass)                                \
+    DELTA_PASS("simplify-conditionals-true", reduceConditionalsTrueDeltaPass)  \
+    DELTA_PASS("simplify-conditionals-false", reduceConditionalsFalseDeltaPass)\
+    DELTA_PASS("invokes", reduceInvokesDeltaPass)                              \
+    DELTA_PASS("unreachable-basic-blocks", reduceUnreachableBasicBlocksDeltaPass) \
     DELTA_PASS("basic-blocks", reduceBasicBlocksDeltaPass)                     \
+    DELTA_PASS("simplify-cfg", reduceUsingSimplifyCFGDeltaPass)                \
+    DELTA_PASS("function-data", reduceFunctionDataDeltaPass)                   \
     DELTA_PASS("global-values", reduceGlobalValuesDeltaPass)                   \
     DELTA_PASS("global-objects", reduceGlobalObjectsDeltaPass)                 \
     DELTA_PASS("global-initializers", reduceGlobalsInitializersDeltaPass)      \
     DELTA_PASS("global-variables", reduceGlobalsDeltaPass)                     \
+    DELTA_PASS("di-metadata", reduceDIMetadataDeltaPass)                       \
     DELTA_PASS("metadata", reduceMetadataDeltaPass)                            \
+    DELTA_PASS("named-metadata", reduceNamedMetadataDeltaPass)                 \
     DELTA_PASS("arguments", reduceArgumentsDeltaPass)                          \
     DELTA_PASS("instructions", reduceInstructionsDeltaPass)                    \
     DELTA_PASS("simplify-instructions", simplifyInstructionsDeltaPass)         \
+    DELTA_PASS("ir-passes", runIRPassesDeltaPass)                              \
     DELTA_PASS("operands-zero", reduceOperandsZeroDeltaPass)                   \
     DELTA_PASS("operands-one", reduceOperandsOneDeltaPass)                     \
     DELTA_PASS("operands-nan", reduceOperandsNaNDeltaPass)                     \
@@ -75,7 +103,12 @@
     DELTA_PASS("operand-bundles", reduceOperandBundesDeltaPass)                \
     DELTA_PASS("attributes", reduceAttributesDeltaPass)                        \
     DELTA_PASS("module-data", reduceModuleDataDeltaPass)                       \
-  } while (false)
+    DELTA_PASS("opcodes", reduceOpcodesDeltaPass)                              \
+    DELTA_PASS("volatile", reduceVolatileInstructionsDeltaPass)                \
+    DELTA_PASS("atomic-ordering", reduceAtomicOrderingDeltaPass)               \
+    DELTA_PASS("syncscopes", reduceAtomicSyncScopesDeltaPass)                  \
+    DELTA_PASS("instruction-flags", reduceInstructionFlagsDeltaPass)           \
+} while (false)
 
 #define DELTA_PASSES_MIR                                                       \
   do {                                                                         \
@@ -91,8 +124,12 @@
     DELTA_PASS("register-masks", reduceRegisterMasksMIRDeltaPass)              \
   } while (false)
 
-static void runAllDeltaPasses(TestRunner &Tester) {
-#define DELTA_PASS(NAME, FUNC) FUNC(Tester);
+static void runAllDeltaPasses(TestRunner &Tester,
+                              const SmallStringSet &SkipPass) {
+#define DELTA_PASS(NAME, FUNC)                                                 \
+  if (!SkipPass.count(NAME)) {                                                 \
+    FUNC(Tester);                                                              \
+  }
   if (Tester.getProgram().isMIR()) {
     DELTA_PASSES_MIR;
   } else {
@@ -113,8 +150,10 @@
     DELTA_PASSES;
   }
 #undef DELTA_PASS
-  errs() << "unknown pass \"" << PassName << "\"\n";
-  exit(1);
+
+  // We should have errored on unrecognized passes before trying to run
+  // anything.
+  llvm_unreachable("unknown delta pass");
 }
 
 void llvm::printDeltaPasses(raw_ostream &OS) {
@@ -127,19 +166,59 @@
 #undef DELTA_PASS
 }
 
+// Built a set of available delta passes.
+static void collectPassNames(const TestRunner &Tester,
+                             SmallStringSet &NameSet) {
+#define DELTA_PASS(NAME, FUNC) NameSet.insert(NAME);
+  if (Tester.getProgram().isMIR()) {
+    DELTA_PASSES_MIR;
+  } else {
+    DELTA_PASSES;
+  }
+#undef DELTA_PASS
+}
+
+/// Verify all requested or skipped passes are valid names, and return them in a
+/// set.
+static SmallStringSet handlePassList(const TestRunner &Tester,
+                                     const cl::list<std::string> &PassList) {
+  SmallStringSet AllPasses;
+  collectPassNames(Tester, AllPasses);
+
+  SmallStringSet PassSet;
+  for (StringRef PassName : PassList) {
+    if (!AllPasses.count(PassName)) {
+      errs() << "unknown pass \"" << PassName << "\"\n";
+      exit(1);
+    }
+
+    PassSet.insert(PassName);
+  }
+
+  return PassSet;
+}
+
 void llvm::runDeltaPasses(TestRunner &Tester, int MaxPassIterations) {
   uint64_t OldComplexity = Tester.getProgram().getComplexityScore();
+
+  SmallStringSet RunPassSet, SkipPassSet;
+
+  if (!DeltaPasses.empty())
+    RunPassSet = handlePassList(Tester, DeltaPasses);
+
+  if (!SkipDeltaPasses.empty())
+    SkipPassSet = handlePassList(Tester, SkipDeltaPasses);
+
   for (int Iter = 0; Iter < MaxPassIterations; ++Iter) {
     if (DeltaPasses.empty()) {
-      runAllDeltaPasses(Tester);
+      runAllDeltaPasses(Tester, SkipPassSet);
     } else {
-      StringRef Passes = DeltaPasses;
-      while (!Passes.empty()) {
-        auto Split = Passes.split(",");
-        runDeltaPassName(Tester, Split.first);
-        Passes = Split.second;
+      for (StringRef PassName : DeltaPasses) {
+        if (!SkipPassSet.count(PassName))
+          runDeltaPassName(Tester, PassName);
       }
     }
+
     uint64_t NewComplexity = Tester.getProgram().getComplexityScore();
     if (NewComplexity >= OldComplexity)
       break;
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.h b/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.h
index b72e560..c1445a7 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/DeltaManager.h
@@ -1,4 +1,4 @@
-//===- DeltaManager.h - Runs Delta Passes to reduce Input -----------------===//
+//===- DeltaManager.h - Runs Delta Passes to reduce Input -------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.cpp b/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
index b6e78dd..74107ad 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
@@ -7,7 +7,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "ReducerWorkItem.h"
+#include "TestRunner.h"
+#include "llvm/Analysis/ModuleSummaryAnalysis.h"
+#include "llvm/Analysis/ProfileSummaryInfo.h"
 #include "llvm/Bitcode/BitcodeReader.h"
+#include "llvm/Bitcode/BitcodeWriter.h"
 #include "llvm/CodeGen/CommandFlags.h"
 #include "llvm/CodeGen/MIRParser/MIRParser.h"
 #include "llvm/CodeGen/MIRPrinter.h"
@@ -18,24 +22,39 @@
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
 #include "llvm/IR/ModuleSummaryIndex.h"
+#include "llvm/IR/Operator.h"
 #include "llvm/IR/Verifier.h"
 #include "llvm/IRReader/IRReader.h"
 #include "llvm/MC/TargetRegistry.h"
+#include "llvm/Passes/PassBuilder.h"
 #include "llvm/Support/Host.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
 #include "llvm/Transforms/Utils/Cloning.h"
+#include <optional>
+
+using namespace llvm;
+
+ReducerWorkItem::ReducerWorkItem() = default;
+ReducerWorkItem::~ReducerWorkItem() = default;
 
 extern cl::OptionCategory LLVMReduceOptions;
 static cl::opt<std::string> TargetTriple("mtriple",
                                          cl::desc("Set the target triple"),
                                          cl::cat(LLVMReduceOptions));
 
-void readBitcode(ReducerWorkItem &M, MemoryBufferRef Data, LLVMContext &Ctx, const char *ToolName);
+static cl::opt<bool> TmpFilesAsBitcode(
+    "write-tmp-files-as-bitcode",
+    cl::desc("Always write temporary files as bitcode instead of textual IR"),
+    cl::init(false), cl::cat(LLVMReduceOptions));
 
 static void cloneFrameInfo(
     MachineFrameInfo &DstMFI, const MachineFrameInfo &SrcMFI,
@@ -206,8 +225,10 @@
         DstMF->CreateMachineBasicBlock(SrcMBB.getBasicBlock());
     Src2DstMBB[&SrcMBB] = DstMBB;
 
-    if (SrcMBB.hasAddressTaken())
-      DstMBB->setHasAddressTaken();
+    if (SrcMBB.isIRBlockAddressTaken())
+      DstMBB->setAddressTakenIRBlock(SrcMBB.getAddressTakenIRBlock());
+    if (SrcMBB.isMachineBlockAddressTaken())
+      DstMBB->setMachineBlockAddressTaken();
 
     // FIXME: This is not serialized
     if (SrcMBB.hasLabelMustBeEmitted())
@@ -233,7 +254,7 @@
         SrcMBB.isInlineAsmBrIndirectTarget());
 
     // FIXME: This is not serialized
-    if (Optional<uint64_t> Weight = SrcMBB.getIrrLoopHeaderWeight())
+    if (std::optional<uint64_t> Weight = SrcMBB.getIrrLoopHeaderWeight())
       DstMBB->setIrrLoopHeaderWeight(*Weight);
   }
 
@@ -380,136 +401,6 @@
   InitializeAllAsmParsers();
 }
 
-std::unique_ptr<ReducerWorkItem>
-parseReducerWorkItem(const char *ToolName, StringRef Filename,
-                     LLVMContext &Ctxt, std::unique_ptr<TargetMachine> &TM,
-                     bool IsMIR) {
-  Triple TheTriple;
-
-  auto MMM = std::make_unique<ReducerWorkItem>();
-
-  if (IsMIR) {
-    initializeTargetInfo();
-
-    auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true);
-    if (std::error_code EC = FileOrErr.getError()) {
-      WithColor::error(errs(), ToolName) << EC.message() << '\n';
-      return nullptr;
-    }
-
-    std::unique_ptr<MIRParser> MParser =
-        createMIRParser(std::move(FileOrErr.get()), Ctxt);
-
-    auto SetDataLayout =
-        [&](StringRef DataLayoutTargetTriple) -> Optional<std::string> {
-      // If we are supposed to override the target triple, do so now.
-      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;
-      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!");
-
-      return TM->createDataLayout().getStringRepresentation();
-    };
-
-    std::unique_ptr<Module> M = MParser->parseIRModule(SetDataLayout);
-    LLVMTargetMachine *LLVMTM = static_cast<LLVMTargetMachine *>(TM.get());
-
-    MMM->MMI = std::make_unique<MachineModuleInfo>(LLVMTM);
-    MParser->parseMachineFunctions(*M, *MMM->MMI);
-    MMM->M = std::move(M);
-  } else {
-    SMDiagnostic Err;
-    ErrorOr<std::unique_ptr<MemoryBuffer>> MB = MemoryBuffer::getFileOrSTDIN(Filename);
-    if (std::error_code EC = MB.getError()) {
-      WithColor::error(errs(), ToolName) << Filename << ": " << EC.message() << "\n";
-      return nullptr;
-    }
-
-    if (!isBitcode((const unsigned char *)(*MB)->getBufferStart(),
-                  (const unsigned char *)(*MB)->getBufferEnd())) {
-      std::unique_ptr<Module> Result = parseIRFile(Filename, Err, Ctxt);
-      if (!Result) {
-        Err.print(ToolName, errs());
-        return nullptr;
-      }
-      MMM->M = std::move(Result);
-    } else {
-      readBitcode(*MMM, MemoryBufferRef(**MB), Ctxt, ToolName);
-
-      if (MMM->LTOInfo->IsThinLTO && MMM->LTOInfo->EnableSplitLTOUnit)
-       initializeTargetInfo();
-    }
-  }
-  if (verifyReducerWorkItem(*MMM, &errs())) {
-    WithColor::error(errs(), ToolName)
-        << Filename << " - input module is broken!\n";
-    return nullptr;
-  }
-  return MMM;
-}
-
-std::unique_ptr<ReducerWorkItem>
-cloneReducerWorkItem(const ReducerWorkItem &MMM, const TargetMachine *TM) {
-  auto CloneMMM = std::make_unique<ReducerWorkItem>();
-  if (TM) {
-    // We're assuming the Module IR contents are always unchanged by MIR
-    // reductions, and can share it as a constant.
-    CloneMMM->M = MMM.M;
-
-    // MachineModuleInfo contains a lot of other state used during codegen which
-    // we won't be using here, but we should be able to ignore it (although this
-    // is pretty ugly).
-    const LLVMTargetMachine *LLVMTM =
-        static_cast<const LLVMTargetMachine *>(TM);
-    CloneMMM->MMI = std::make_unique<MachineModuleInfo>(LLVMTM);
-
-    for (const Function &F : MMM.getModule()) {
-      if (auto *MF = MMM.MMI->getMachineFunction(F))
-        CloneMMM->MMI->insertFunction(F, cloneMF(MF, *CloneMMM->MMI));
-    }
-  } else {
-    CloneMMM->M = CloneModule(*MMM.M);
-  }
-  return CloneMMM;
-}
-
-bool verifyReducerWorkItem(const ReducerWorkItem &MMM, raw_fd_ostream *OS) {
-  if (verifyModule(*MMM.M, OS))
-    return true;
-
-  if (!MMM.MMI)
-    return false;
-
-  for (const Function &F : MMM.getModule()) {
-    if (const MachineFunction *MF = MMM.MMI->getMachineFunction(F)) {
-      if (!MF->verify(nullptr, "", /*AbortOnError=*/false))
-        return true;
-    }
-  }
-
-  return false;
-}
-
 void ReducerWorkItem::print(raw_ostream &ROS, void *p) const {
   if (MMI) {
     printMIR(ROS, *M);
@@ -523,14 +414,77 @@
   }
 }
 
-// FIXME: We might want to use a different metric than "number of
-// bytes in serialized IR" to detect non-progress of the main delta
-// loop
-uint64_t ReducerWorkItem::getIRSize() const {
-  std::string Str;
-  raw_string_ostream SS(Str);
-  print(SS, /*AnnotationWriter=*/nullptr);
-  return Str.length();
+bool ReducerWorkItem::verify(raw_fd_ostream *OS) const {
+  if (verifyModule(*M, OS))
+    return true;
+
+  if (!MMI)
+    return false;
+
+  for (const Function &F : getModule()) {
+    if (const MachineFunction *MF = MMI->getMachineFunction(F)) {
+      if (!MF->verify(nullptr, "", /*AbortOnError=*/false))
+        return true;
+    }
+  }
+
+  return false;
+}
+
+bool ReducerWorkItem::isReduced(const TestRunner &Test) const {
+  const bool UseBitcode = Test.inputIsBitcode() || TmpFilesAsBitcode;
+
+  SmallString<128> CurrentFilepath;
+
+  // Write ReducerWorkItem to tmp file
+  int FD;
+  std::error_code EC = sys::fs::createTemporaryFile(
+      "llvm-reduce", isMIR() ? "mir" : (UseBitcode ? "bc" : "ll"), FD,
+      CurrentFilepath,
+      UseBitcode && !isMIR() ? sys::fs::OF_None : sys::fs::OF_Text);
+  if (EC) {
+    errs() << "Error making unique filename: " << EC.message() << "!\n";
+    exit(1);
+  }
+
+  ToolOutputFile Out(CurrentFilepath, FD);
+
+  writeOutput(Out.os(), UseBitcode);
+
+  Out.os().close();
+  if (Out.os().has_error()) {
+    errs() << "Error emitting bitcode to file '" << CurrentFilepath
+           << "': " << Out.os().error().message();
+    exit(1);
+  }
+
+  // Current Chunks aren't interesting
+  return Test.run(CurrentFilepath);
+}
+
+std::unique_ptr<ReducerWorkItem>
+ReducerWorkItem::clone(const TargetMachine *TM) const {
+  auto CloneMMM = std::make_unique<ReducerWorkItem>();
+  if (TM) {
+    // We're assuming the Module IR contents are always unchanged by MIR
+    // reductions, and can share it as a constant.
+    CloneMMM->M = M;
+
+    // MachineModuleInfo contains a lot of other state used during codegen which
+    // we won't be using here, but we should be able to ignore it (although this
+    // is pretty ugly).
+    const LLVMTargetMachine *LLVMTM =
+        static_cast<const LLVMTargetMachine *>(TM);
+    CloneMMM->MMI = std::make_unique<MachineModuleInfo>(LLVMTM);
+
+    for (const Function &F : getModule()) {
+      if (auto *MF = MMI->getMachineFunction(F))
+        CloneMMM->MMI->insertFunction(F, cloneMF(MF, *CloneMMM->MMI));
+    }
+  } else {
+    CloneMMM->M = CloneModule(*M);
+  }
+  return CloneMMM;
 }
 
 /// Try to produce some number that indicates a function is getting smaller /
@@ -605,3 +559,270 @@
 
   return Score;
 }
+
+// FIXME: ReduceOperandsSkip has similar function, except it uses larger numbers
+// for more reduced.
+static unsigned classifyReductivePower(const Value *V) {
+  if (auto *C = dyn_cast<ConstantData>(V)) {
+    if (C->isNullValue())
+      return 0;
+    if (C->isOneValue())
+      return 1;
+    if (isa<UndefValue>(V))
+      return 2;
+    return 3;
+  }
+
+  if (isa<GlobalValue>(V))
+    return 4;
+
+  // TODO: Account for expression size
+  if (isa<ConstantExpr>(V))
+    return 5;
+
+  if (isa<Constant>(V))
+    return 1;
+
+  if (isa<Argument>(V))
+    return 6;
+
+  if (isa<Instruction>(V))
+    return 7;
+
+  return 0;
+}
+
+// TODO: Additional flags and attributes may be complexity reducing. If we start
+// adding flags and attributes, they could have negative cost.
+static uint64_t computeIRComplexityScoreImpl(const Function &F) {
+  uint64_t Score = 1; // Count the function itself
+  SmallVector<std::pair<unsigned, MDNode *>> MDs;
+
+  AttributeList Attrs = F.getAttributes();
+  for (AttributeSet AttrSet : Attrs)
+    Score += AttrSet.getNumAttributes();
+
+  for (const BasicBlock &BB : F) {
+    ++Score;
+
+    for (const Instruction &I : BB) {
+      ++Score;
+
+      if (const auto *OverflowOp = dyn_cast<OverflowingBinaryOperator>(&I)) {
+        if (OverflowOp->hasNoUnsignedWrap())
+          ++Score;
+        if (OverflowOp->hasNoSignedWrap())
+          ++Score;
+      } else if (const auto *GEP = dyn_cast<GEPOperator>(&I)) {
+        if (GEP->isInBounds())
+          ++Score;
+      } else if (const auto *ExactOp = dyn_cast<PossiblyExactOperator>(&I)) {
+        if (ExactOp->isExact())
+          ++Score;
+      } else if (const auto *FPOp = dyn_cast<FPMathOperator>(&I)) {
+        FastMathFlags FMF = FPOp->getFastMathFlags();
+        if (FMF.allowReassoc())
+          ++Score;
+        if (FMF.noNaNs())
+          ++Score;
+        if (FMF.noInfs())
+          ++Score;
+        if (FMF.noSignedZeros())
+          ++Score;
+        if (FMF.allowReciprocal())
+          ++Score;
+        if (FMF.allowContract())
+          ++Score;
+        if (FMF.approxFunc())
+          ++Score;
+      }
+
+      for (const Value *Operand : I.operands()) {
+        ++Score;
+        Score += classifyReductivePower(Operand);
+      }
+
+      I.getAllMetadata(MDs);
+      Score += MDs.size();
+      MDs.clear();
+    }
+  }
+
+  return Score;
+}
+
+uint64_t ReducerWorkItem::computeIRComplexityScore() const {
+  uint64_t Score = 0;
+
+  const Module &M = getModule();
+  Score += M.named_metadata_size();
+
+  SmallVector<std::pair<unsigned, MDNode *>, 32> GlobalMetadata;
+  for (const GlobalVariable &GV : M.globals()) {
+    ++Score;
+
+    if (GV.hasInitializer())
+      Score += classifyReductivePower(GV.getInitializer());
+
+    // TODO: Account for linkage?
+
+    GV.getAllMetadata(GlobalMetadata);
+    Score += GlobalMetadata.size();
+    GlobalMetadata.clear();
+  }
+
+  for (const GlobalAlias &GA : M.aliases())
+    Score += classifyReductivePower(GA.getAliasee());
+
+  for (const GlobalIFunc &GI : M.ifuncs())
+    Score += classifyReductivePower(GI.getResolver());
+
+  for (const Function &F : M)
+    Score += computeIRComplexityScoreImpl(F);
+
+  return Score;
+}
+
+void ReducerWorkItem::writeOutput(raw_ostream &OS, bool EmitBitcode) const {
+  // Requesting bitcode emission with mir is nonsense, so just ignore it.
+  if (EmitBitcode && !isMIR())
+    writeBitcode(OS);
+  else
+    print(OS, /*AnnotationWriter=*/nullptr);
+}
+
+void ReducerWorkItem::readBitcode(MemoryBufferRef Data, LLVMContext &Ctx,
+                                  StringRef ToolName) {
+  Expected<BitcodeFileContents> IF = llvm::getBitcodeFileContents(Data);
+  if (!IF) {
+    WithColor::error(errs(), ToolName) << IF.takeError();
+    exit(1);
+  }
+  BitcodeModule BM = IF->Mods[0];
+  Expected<BitcodeLTOInfo> LI = BM.getLTOInfo();
+  Expected<std::unique_ptr<Module>> MOrErr = BM.parseModule(Ctx);
+  if (!LI || !MOrErr) {
+    WithColor::error(errs(), ToolName) << IF.takeError();
+    exit(1);
+  }
+  LTOInfo = std::make_unique<BitcodeLTOInfo>(*LI);
+  M = std::move(MOrErr.get());
+}
+
+void ReducerWorkItem::writeBitcode(raw_ostream &OutStream) const {
+  if (LTOInfo && LTOInfo->IsThinLTO && LTOInfo->EnableSplitLTOUnit) {
+    PassBuilder PB;
+    LoopAnalysisManager LAM;
+    FunctionAnalysisManager FAM;
+    CGSCCAnalysisManager CGAM;
+    ModuleAnalysisManager MAM;
+    PB.registerModuleAnalyses(MAM);
+    PB.registerCGSCCAnalyses(CGAM);
+    PB.registerFunctionAnalyses(FAM);
+    PB.registerLoopAnalyses(LAM);
+    PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+    ModulePassManager MPM;
+    MPM.addPass(ThinLTOBitcodeWriterPass(OutStream, nullptr));
+    MPM.run(*M, MAM);
+  } else {
+    std::unique_ptr<ModuleSummaryIndex> Index;
+    if (LTOInfo && LTOInfo->HasSummary) {
+      ProfileSummaryInfo PSI(*M);
+      Index = std::make_unique<ModuleSummaryIndex>(
+          buildModuleSummaryIndex(*M, nullptr, &PSI));
+    }
+    WriteBitcodeToFile(getModule(), OutStream, Index.get());
+  }
+}
+
+std::pair<std::unique_ptr<ReducerWorkItem>, bool>
+llvm::parseReducerWorkItem(StringRef ToolName, StringRef Filename,
+                           LLVMContext &Ctxt,
+                           std::unique_ptr<TargetMachine> &TM, bool IsMIR) {
+  bool IsBitcode = false;
+  Triple TheTriple;
+
+  auto MMM = std::make_unique<ReducerWorkItem>();
+
+  if (IsMIR) {
+    initializeTargetInfo();
+
+    auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true);
+    if (std::error_code EC = FileOrErr.getError()) {
+      WithColor::error(errs(), ToolName) << EC.message() << '\n';
+      return {nullptr, false};
+    }
+
+    std::unique_ptr<MIRParser> MParser =
+        createMIRParser(std::move(FileOrErr.get()), Ctxt);
+
+    auto SetDataLayout = [&](StringRef DataLayoutTargetTriple,
+                             StringRef OldDLStr) -> std::optional<std::string> {
+      // If we are supposed to override the target triple, do so now.
+      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!");
+
+      return TM->createDataLayout().getStringRepresentation();
+    };
+
+    std::unique_ptr<Module> M = MParser->parseIRModule(SetDataLayout);
+    LLVMTargetMachine *LLVMTM = static_cast<LLVMTargetMachine *>(TM.get());
+
+    MMM->MMI = std::make_unique<MachineModuleInfo>(LLVMTM);
+    MParser->parseMachineFunctions(*M, *MMM->MMI);
+    MMM->M = std::move(M);
+  } else {
+    SMDiagnostic Err;
+    ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
+        MemoryBuffer::getFileOrSTDIN(Filename);
+    if (std::error_code EC = MB.getError()) {
+      WithColor::error(errs(), ToolName)
+          << Filename << ": " << EC.message() << "\n";
+      return {nullptr, false};
+    }
+
+    if (!isBitcode((const unsigned char *)(*MB)->getBufferStart(),
+                   (const unsigned char *)(*MB)->getBufferEnd())) {
+      std::unique_ptr<Module> Result = parseIRFile(Filename, Err, Ctxt);
+      if (!Result) {
+        Err.print(ToolName.data(), errs());
+        return {nullptr, false};
+      }
+      MMM->M = std::move(Result);
+    } else {
+      IsBitcode = true;
+      MMM->readBitcode(MemoryBufferRef(**MB), Ctxt, ToolName);
+
+      if (MMM->LTOInfo->IsThinLTO && MMM->LTOInfo->EnableSplitLTOUnit)
+        initializeTargetInfo();
+    }
+  }
+  if (MMM->verify(&errs())) {
+    WithColor::error(errs(), ToolName)
+        << Filename << " - input module is broken!\n";
+    return {nullptr, false};
+  }
+  return {std::move(MMM), IsBitcode};
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.h b/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.h
index 7dd5786..dc11322 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/ReducerWorkItem.h
@@ -1,4 +1,4 @@
-//===- ReducerWorkItem.h - Wrapper for Module and MachineFunction ---------===//
+//===- ReducerWorkItem.h - Wrapper for Module -------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -9,14 +9,17 @@
 #ifndef LLVM_TOOLS_LLVM_REDUCE_REDUCERWORKITEM_H
 #define LLVM_TOOLS_LLVM_REDUCE_REDUCERWORKITEM_H
 
-#include "llvm/Bitcode/BitcodeReader.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/IR/Module.h"
-#include "llvm/IR/ModuleSummaryIndex.h"
-#include "llvm/Target/TargetMachine.h"
+#include <memory>
 
-using namespace llvm;
+namespace llvm {
+class LLVMContext;
+class MachineModuleInfo;
+class MemoryBufferRef;
+class raw_ostream;
+class TargetMachine;
+class TestRunner;
+struct BitcodeLTOInfo;
 
 class ReducerWorkItem {
 public:
@@ -24,31 +27,44 @@
   std::unique_ptr<BitcodeLTOInfo> LTOInfo;
   std::unique_ptr<MachineModuleInfo> MMI;
 
+  ReducerWorkItem();
+  ~ReducerWorkItem();
+  ReducerWorkItem(ReducerWorkItem &) = delete;
+  ReducerWorkItem(ReducerWorkItem &&) = default;
+
   bool isMIR() const { return MMI != nullptr; }
 
+  LLVMContext &getContext() {
+    return M->getContext();
+  }
+
+  Module &getModule() { return *M; }
   const Module &getModule() const { return *M; }
+  operator Module &() const { return *M; }
 
   void print(raw_ostream &ROS, void *p = nullptr) const;
-  operator Module &() const { return *M; }
+  bool verify(raw_fd_ostream *OS) const;
+  std::unique_ptr<ReducerWorkItem> clone(const TargetMachine *TM) const;
 
   /// Return a number to indicate whether there was any reduction progress.
   uint64_t getComplexityScore() const {
-    return isMIR() ? computeMIRComplexityScore() : getIRSize();
+    return isMIR() ? computeMIRComplexityScore() : computeIRComplexityScore();
   }
 
+  void writeOutput(raw_ostream &OS, bool EmitBitcode) const;
+  void readBitcode(MemoryBufferRef Data, LLVMContext &Ctx, StringRef ToolName);
+  void writeBitcode(raw_ostream &OutStream) const;
+
+  bool isReduced(const TestRunner &Test) const;
+
 private:
+  uint64_t computeIRComplexityScore() const;
   uint64_t computeMIRComplexityScore() const;
-  uint64_t getIRSize() const;
 };
 
-std::unique_ptr<ReducerWorkItem>
-parseReducerWorkItem(const char *ToolName, StringRef Filename,
-                     LLVMContext &Ctxt, std::unique_ptr<TargetMachine> &TM,
-                     bool IsMIR);
-
-std::unique_ptr<ReducerWorkItem>
-cloneReducerWorkItem(const ReducerWorkItem &MMM, const TargetMachine *TM);
-
-bool verifyReducerWorkItem(const ReducerWorkItem &MMM, raw_fd_ostream *OS);
+std::pair<std::unique_ptr<ReducerWorkItem>, bool>
+parseReducerWorkItem(StringRef ToolName, StringRef Filename, LLVMContext &Ctxt,
+                     std::unique_ptr<TargetMachine> &TM, bool IsMIR);
+} // namespace llvm
 
 #endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.cpp b/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.cpp
index 691790d..8a61aae 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.cpp
@@ -8,22 +8,31 @@
 
 #include "TestRunner.h"
 #include "ReducerWorkItem.h"
-#include "llvm/CodeGen/MachineFunction.h"
+#include "deltas/Utils.h"
+#include "llvm/Support/WithColor.h"
 
 using namespace llvm;
 
 TestRunner::TestRunner(StringRef TestName,
                        const std::vector<std::string> &TestArgs,
                        std::unique_ptr<ReducerWorkItem> Program,
-                       std::unique_ptr<TargetMachine> TM, const char *ToolName)
+                       std::unique_ptr<TargetMachine> TM, StringRef ToolName,
+                       StringRef OutputName, bool InputIsBitcode,
+                       bool OutputBitcode)
     : TestName(TestName), ToolName(ToolName), TestArgs(TestArgs),
-      Program(std::move(Program)), TM(std::move(TM)) {
+      Program(std::move(Program)), TM(std::move(TM)),
+      OutputFilename(OutputName), InputIsBitcode(InputIsBitcode),
+      EmitBitcode(OutputBitcode) {
   assert(this->Program && "Initialized with null program?");
 }
 
+static constexpr std::array<std::optional<StringRef>, 3> DefaultRedirects = {
+    StringRef()};
+static constexpr std::array<std::optional<StringRef>, 3> NullRedirects;
+
 /// Runs the interestingness test, passes file to be tested as first argument
 /// and other specified test arguments after that.
-int TestRunner::run(StringRef Filename) {
+int TestRunner::run(StringRef Filename) const {
   std::vector<StringRef> ProgramArgs;
   ProgramArgs.push_back(TestName);
 
@@ -33,22 +42,33 @@
   ProgramArgs.push_back(Filename);
 
   std::string ErrMsg;
-  int Result = sys::ExecuteAndWait(
-      TestName, ProgramArgs, /*Env=*/None, /*Redirects=*/None,
-      /*SecondsToWait=*/0, /*MemoryLimit=*/0, &ErrMsg);
+
+  int Result =
+      sys::ExecuteAndWait(TestName, ProgramArgs, /*Env=*/std::nullopt,
+                          Verbose ? DefaultRedirects : NullRedirects,
+                          /*SecondsToWait=*/0, /*MemoryLimit=*/0, &ErrMsg);
 
   if (Result < 0) {
     Error E = make_error<StringError>("Error running interesting-ness test: " +
                                           ErrMsg,
                                       inconvertibleErrorCode());
-    errs() << toString(std::move(E));
+    WithColor::error(errs(), ToolName) << toString(std::move(E)) << '\n';
     exit(1);
   }
 
   return !Result;
 }
 
-void TestRunner::setProgram(std::unique_ptr<ReducerWorkItem> P) {
-  assert(P && "Setting null program?");
-  Program = std::move(P);
+void TestRunner::writeOutput(StringRef Message) {
+  std::error_code EC;
+  raw_fd_ostream Out(OutputFilename, EC,
+                     EmitBitcode && !Program->isMIR() ? sys::fs::OF_None
+                                                      : sys::fs::OF_Text);
+  if (EC) {
+    errs() << "Error opening output file: " << EC.message() << "!\n";
+    exit(1);
+  }
+
+  Program->writeOutput(Out, EmitBitcode);
+  errs() << Message << OutputFilename << '\n';
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h b/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h
index 6d7dd7a..136cd80 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/TestRunner.h
@@ -28,27 +28,40 @@
 public:
   TestRunner(StringRef TestName, const std::vector<std::string> &TestArgs,
              std::unique_ptr<ReducerWorkItem> Program,
-             std::unique_ptr<TargetMachine> TM, const char *ToolName);
+             std::unique_ptr<TargetMachine> TM, StringRef ToolName,
+             StringRef OutputFilename, bool InputIsBitcode, bool OutputBitcode);
 
   /// Runs the interesting-ness test for the specified file
   /// @returns 0 if test was successful, 1 if otherwise
-  int run(StringRef Filename);
+  int run(StringRef Filename) const;
 
   /// Returns the most reduced version of the original testcase
   ReducerWorkItem &getProgram() const { return *Program; }
 
-  void setProgram(std::unique_ptr<ReducerWorkItem> P);
+  void setProgram(std::unique_ptr<ReducerWorkItem> &&P) {
+    assert(P && "Setting null program?");
+    Program = std::move(P);
+  }
 
   const TargetMachine *getTargetMachine() const { return TM.get(); }
 
-  const char *getToolName() const { return ToolName; }
+  StringRef getToolName() const { return ToolName; }
+
+  void writeOutput(StringRef Message);
+
+  bool inputIsBitcode() const {
+    return InputIsBitcode;
+  }
 
 private:
   StringRef TestName;
-  const char *ToolName;
+  StringRef ToolName;
   const std::vector<std::string> &TestArgs;
   std::unique_ptr<ReducerWorkItem> Program;
   std::unique_ptr<TargetMachine> TM;
+  StringRef OutputFilename;
+  const bool InputIsBitcode;
+  bool EmitBitcode;
 };
 
 } // namespace llvm
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 55b96d8..9bdfb66 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.cpp
@@ -14,9 +14,11 @@
 
 #include "Delta.h"
 #include "ReducerWorkItem.h"
+#include "TestRunner.h"
+#include "Utils.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/Analysis/ProfileSummaryInfo.h"
 #include "llvm/Analysis/ModuleSummaryAnalysis.h"
+#include "llvm/Analysis/ProfileSummaryInfo.h"
 #include "llvm/Bitcode/BitcodeReader.h"
 #include "llvm/Bitcode/BitcodeWriter.h"
 #include "llvm/CodeGen/MachineFunction.h"
@@ -26,7 +28,6 @@
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/MemoryBufferRef.h"
 #include "llvm/Support/ThreadPool.h"
-#include "llvm/Support/ToolOutputFile.h"
 #include <fstream>
 #include <set>
 
@@ -44,115 +45,56 @@
     cl::desc("Number of times to divide chunks prior to first test"),
     cl::cat(LLVMReduceOptions));
 
-static cl::opt<bool> TmpFilesAsBitcode(
-    "write-tmp-files-as-bitcode",
-    cl::desc("Write temporary files as bitcode, instead of textual IR"),
-    cl::init(false), cl::cat(LLVMReduceOptions));
-
 #ifdef LLVM_ENABLE_THREADS
 static cl::opt<unsigned> NumJobs(
     "j",
     cl::desc("Maximum number of threads to use to process chunks. Set to 1 to "
-             "disables parallelism."),
+             "disable parallelism."),
     cl::init(1), cl::cat(LLVMReduceOptions));
 #else
 unsigned NumJobs = 1;
 #endif
 
-void writeOutput(ReducerWorkItem &M, llvm::StringRef Message);
-
-void writeBitcode(ReducerWorkItem &M, raw_ostream &OutStream);
-
-void readBitcode(ReducerWorkItem &M, MemoryBufferRef Data, LLVMContext &Ctx,
-                 const char *ToolName);
-
-bool isReduced(ReducerWorkItem &M, TestRunner &Test,
-               SmallString<128> &CurrentFilepath) {
-  // Write ReducerWorkItem to tmp file
-  int FD;
-  std::error_code EC = sys::fs::createTemporaryFile(
-      "llvm-reduce", M.isMIR() ? "mir" : (TmpFilesAsBitcode ? "bc" : "ll"), FD,
-      CurrentFilepath);
-  if (EC) {
-    errs() << "Error making unique filename: " << EC.message() << "!\n";
-    exit(1);
-  }
-
-  if (TmpFilesAsBitcode) {
-    llvm::raw_fd_ostream OutStream(FD, true);
-    writeBitcode(M, OutStream);
-    OutStream.close();
-    if (OutStream.has_error()) {
-      errs() << "Error emitting bitcode to file '" << CurrentFilepath << "'!\n";
-      sys::fs::remove(CurrentFilepath);
-      exit(1);
-    }
-    bool Res = Test.run(CurrentFilepath);
-    sys::fs::remove(CurrentFilepath);
-    return Res;
-  }
-  ToolOutputFile Out(CurrentFilepath, FD);
-  M.print(Out.os(), /*AnnotationWriter=*/nullptr);
-  Out.os().close();
-  if (Out.os().has_error()) {
-    errs() << "Error emitting bitcode to file '" << CurrentFilepath << "'!\n";
-    exit(1);
-  }
-
-  // Current Chunks aren't interesting
-  return Test.run(CurrentFilepath);
-}
-
-/// Counts the amount of lines for a given file
-static int getLines(StringRef Filepath) {
-  int Lines = 0;
-  std::string CurrLine;
-  std::ifstream FileStream{std::string(Filepath)};
-
-  while (std::getline(FileStream, CurrLine))
-    ++Lines;
-
-  return Lines;
-}
-
 /// Splits Chunks in half and prints them.
 /// If unable to split (when chunk size is 1) returns false.
 static bool increaseGranularity(std::vector<Chunk> &Chunks) {
-  errs() << "Increasing granularity...";
+  if (Verbose)
+    errs() << "Increasing granularity...";
   std::vector<Chunk> NewChunks;
-  bool SplitOne = false;
+  bool SplitAny = false;
 
-  for (auto &C : Chunks) {
+  for (Chunk C : Chunks) {
     if (C.End - C.Begin == 0)
       NewChunks.push_back(C);
     else {
       int Half = (C.Begin + C.End) / 2;
       NewChunks.push_back({C.Begin, Half});
       NewChunks.push_back({Half + 1, C.End});
-      SplitOne = true;
+      SplitAny = true;
     }
   }
-  if (SplitOne) {
+  if (SplitAny) {
     Chunks = NewChunks;
-    errs() << "Success! New Chunks:\n";
-    for (auto C : Chunks) {
-      errs() << '\t';
-      C.print();
-      errs() << '\n';
+    if (Verbose) {
+      errs() << "Success! " << NewChunks.size() << " New Chunks:\n";
+      for (auto C : Chunks) {
+        errs() << '\t';
+        C.print();
+        errs() << '\n';
+      }
     }
   }
-  return SplitOne;
+  return SplitAny;
 }
 
 // Check if \p ChunkToCheckForUninterestingness is interesting. Returns the
 // modified module if the chunk resulted in a reduction.
-template <typename FuncType>
 static std::unique_ptr<ReducerWorkItem>
-CheckChunk(Chunk &ChunkToCheckForUninterestingness,
-           std::unique_ptr<ReducerWorkItem> Clone, TestRunner &Test,
-           FuncType ExtractChunksFromModule,
-           std::set<Chunk> &UninterestingChunks,
-           std::vector<Chunk> &ChunksStillConsideredInteresting) {
+CheckChunk(const Chunk ChunkToCheckForUninterestingness,
+           std::unique_ptr<ReducerWorkItem> Clone, const TestRunner &Test,
+           ReductionFunc ExtractChunksFromModule,
+           const DenseSet<Chunk> &UninterestingChunks,
+           const std::vector<Chunk> &ChunksStillConsideredInteresting) {
   // Take all of ChunksStillConsideredInteresting chunks, except those we've
   // already deemed uninteresting (UninterestingChunks) but didn't remove
   // from ChunksStillConsideredInteresting yet, and additionally ignore
@@ -162,8 +104,8 @@
                         UninterestingChunks.size() - 1);
   copy_if(ChunksStillConsideredInteresting, std::back_inserter(CurrentChunks),
           [&](const Chunk &C) {
-            return !UninterestingChunks.count(C) &&
-                   C != ChunkToCheckForUninterestingness;
+            return C != ChunkToCheckForUninterestingness &&
+                   !UninterestingChunks.count(C);
           });
 
   // Generate Module with only Targets inside Current Chunks
@@ -171,41 +113,46 @@
   ExtractChunksFromModule(O, *Clone);
 
   // Some reductions may result in invalid IR. Skip such reductions.
-  if (verifyReducerWorkItem(*Clone, &errs())) {
+  if (Clone->verify(&errs())) {
     if (AbortOnInvalidReduction) {
-      errs() << "Invalid reduction\n";
+      errs() << "Invalid reduction, aborting.\n";
+      Clone->print(errs());
       exit(1);
     }
-    errs() << " **** WARNING | reduction resulted in invalid module, "
-              "skipping\n";
+    if (Verbose) {
+      errs() << " **** WARNING | reduction resulted in invalid module, "
+                "skipping\n";
+    }
     return nullptr;
   }
 
-  errs() << "Ignoring: ";
-  ChunkToCheckForUninterestingness.print();
-  for (const Chunk &C : UninterestingChunks)
-    C.print();
-
-  SmallString<128> CurrentFilepath;
-  if (!isReduced(*Clone, Test, CurrentFilepath)) {
-    // Program became non-reduced, so this chunk appears to be interesting.
+  if (Verbose) {
+    errs() << "Ignoring: ";
+    ChunkToCheckForUninterestingness.print();
+    for (const Chunk &C : UninterestingChunks)
+      C.print();
     errs() << "\n";
+  }
+
+  if (!Clone->isReduced(Test)) {
+    // Program became non-reduced, so this chunk appears to be interesting.
+    if (Verbose)
+      errs() << "\n";
     return nullptr;
   }
   return Clone;
 }
 
-template <typename FuncType>
-SmallString<0> ProcessChunkFromSerializedBitcode(
-    Chunk &ChunkToCheckForUninterestingness, TestRunner &Test,
-    FuncType ExtractChunksFromModule, std::set<Chunk> &UninterestingChunks,
-    std::vector<Chunk> &ChunksStillConsideredInteresting,
-    SmallString<0> &OriginalBC, std::atomic<bool> &AnyReduced) {
+static SmallString<0> ProcessChunkFromSerializedBitcode(
+    const Chunk ChunkToCheckForUninterestingness, const TestRunner &Test,
+    ReductionFunc ExtractChunksFromModule,
+    const DenseSet<Chunk> &UninterestingChunks,
+    ArrayRef<Chunk> ChunksStillConsideredInteresting, StringRef OriginalBC,
+    std::atomic<bool> &AnyReduced) {
   LLVMContext Ctx;
   auto CloneMMM = std::make_unique<ReducerWorkItem>();
-  auto Data = MemoryBufferRef(StringRef(OriginalBC.data(), OriginalBC.size()),
-                              "<bc file>");
-  readBitcode(*CloneMMM, Data, Ctx, Test.getToolName());
+  MemoryBufferRef Data(OriginalBC, "<bc file>");
+  CloneMMM->readBitcode(Data, Ctx, Test.getToolName());
 
   SmallString<0> Result;
   if (std::unique_ptr<ReducerWorkItem> ChunkResult =
@@ -213,27 +160,32 @@
                      Test, ExtractChunksFromModule, UninterestingChunks,
                      ChunksStillConsideredInteresting)) {
     raw_svector_ostream BCOS(Result);
-    writeBitcode(*ChunkResult, BCOS);
+    ChunkResult->writeBitcode(BCOS);
     // Communicate that the task reduced a chunk.
     AnyReduced = true;
   }
   return Result;
 }
 
+using SharedTaskQueue = std::deque<std::shared_future<SmallString<0>>>;
+
+static void waitAndDiscardResultsBarrier(SharedTaskQueue &TaskQueue) {
+  while (!TaskQueue.empty()) {
+    auto &Future = TaskQueue.front();
+    Future.wait();
+    TaskQueue.pop_front();
+  }
+}
+
 /// Runs the Delta Debugging algorithm, splits the code into chunks and
 /// reduces the amount of chunks that are considered interesting by the
 /// given test. The number of chunks is determined by a preliminary run of the
 /// reduction pass where no change must be made to the module.
-void llvm::runDeltaPass(TestRunner &Test,
-                        ReductionFunc ExtractChunksFromModule) {
-  assert(!verifyReducerWorkItem(Test.getProgram(), &errs()) &&
+void llvm::runDeltaPass(TestRunner &Test, ReductionFunc ExtractChunksFromModule,
+                        StringRef Message) {
+  assert(!Test.getProgram().verify(&errs()) &&
          "input module is broken before making changes");
-
-  SmallString<128> CurrentFilepath;
-  if (!isReduced(Test.getProgram(), Test, CurrentFilepath)) {
-    errs() << "\nInput isn't interesting! Verify interesting-ness test\n";
-    exit(1);
-  }
+  errs() << "*** " << Message << "...\n";
 
   int Targets;
   {
@@ -245,24 +197,26 @@
     ExtractChunksFromModule(Counter, Test.getProgram());
     Targets = Counter.count();
 
-    assert(!verifyReducerWorkItem(Test.getProgram(), &errs()) &&
+    assert(!Test.getProgram().verify(&errs()) &&
            "input module is broken after counting chunks");
-    assert(isReduced(Test.getProgram(), Test, CurrentFilepath) &&
+    assert(Test.getProgram().isReduced(Test) &&
            "input module no longer interesting after counting chunks");
 
 #ifndef NDEBUG
     // Make sure that the number of chunks does not change as we reduce.
-    std::vector<Chunk> NoChunks;
+    std::vector<Chunk> NoChunks = {{0, INT_MAX}};
     Oracle NoChunksCounter(NoChunks);
     std::unique_ptr<ReducerWorkItem> Clone =
-        cloneReducerWorkItem(Test.getProgram(), Test.getTargetMachine());
+      Test.getProgram().clone(Test.getTargetMachine());
     ExtractChunksFromModule(NoChunksCounter, *Clone);
     assert(Targets == NoChunksCounter.count() &&
            "number of chunks changes when reducing");
 #endif
   }
   if (!Targets) {
-    errs() << "\nNothing to reduce\n";
+    if (Verbose)
+      errs() << "\nNothing to reduce\n";
+    errs() << "----------------------------\n";
     return;
   }
 
@@ -283,17 +237,17 @@
   do {
     FoundAtLeastOneNewUninterestingChunkWithCurrentGranularity = false;
 
-    std::set<Chunk> UninterestingChunks;
+    DenseSet<Chunk> UninterestingChunks;
 
     // When running with more than one thread, serialize the original bitcode
     // to OriginalBC.
     SmallString<0> OriginalBC;
     if (NumJobs > 1) {
       raw_svector_ostream BCOS(OriginalBC);
-      writeBitcode(Test.getProgram(), BCOS);
+      Test.getProgram().writeBitcode(BCOS);
     }
 
-    std::deque<std::shared_future<SmallString<0>>> TaskQueue;
+    SharedTaskQueue TaskQueue;
     for (auto I = ChunksStillConsideredInteresting.rbegin(),
               E = ChunksStillConsideredInteresting.rend();
          I != E; ++I) {
@@ -317,14 +271,12 @@
         // LLVMContext object. If a task reduces the input, serialize the result
         // back in the corresponding Result element.
         for (unsigned J = 0; J < NumInitialTasks; ++J) {
+          Chunk ChunkToCheck = *(I + J);
           TaskQueue.emplace_back(ChunkThreadPool.async(
-              [J, I, &Test, &ExtractChunksFromModule, &UninterestingChunks,
-               &ChunksStillConsideredInteresting, &OriginalBC, &AnyReduced]() {
-                return ProcessChunkFromSerializedBitcode(
-                    *(I + J), Test, ExtractChunksFromModule,
-                    UninterestingChunks, ChunksStillConsideredInteresting,
-                    OriginalBC, AnyReduced);
-              }));
+              ProcessChunkFromSerializedBitcode, ChunkToCheck, std::ref(Test),
+              ExtractChunksFromModule, UninterestingChunks,
+              ChunksStillConsideredInteresting, OriginalBC,
+              std::ref(AnyReduced)));
         }
 
         // Start processing results of the queued tasks. We wait for the first
@@ -343,46 +295,49 @@
           if (Res.empty()) {
             unsigned NumScheduledTasks = NumChunksProcessed + TaskQueue.size();
             if (!AnyReduced && I + NumScheduledTasks != E) {
-              Chunk &ChunkToCheck = *(I + NumScheduledTasks);
+              Chunk ChunkToCheck = *(I + NumScheduledTasks);
               TaskQueue.emplace_back(ChunkThreadPool.async(
-                  [&Test, &ExtractChunksFromModule, &UninterestingChunks,
-                   &ChunksStillConsideredInteresting, &OriginalBC,
-                   &ChunkToCheck, &AnyReduced]() {
-                    return ProcessChunkFromSerializedBitcode(
-                        ChunkToCheck, Test, ExtractChunksFromModule,
-                        UninterestingChunks, ChunksStillConsideredInteresting,
-                        OriginalBC, AnyReduced);
-                  }));
+                  ProcessChunkFromSerializedBitcode, ChunkToCheck,
+                  std::ref(Test), ExtractChunksFromModule, UninterestingChunks,
+                  ChunksStillConsideredInteresting, OriginalBC,
+                  std::ref(AnyReduced)));
             }
             continue;
           }
 
           Result = std::make_unique<ReducerWorkItem>();
-          auto Data = MemoryBufferRef(StringRef(Res.data(), Res.size()),
-                                      "<bc file>");
-          readBitcode(*Result, Data, Test.getProgram().M->getContext(),
-                      Test.getToolName());
+          MemoryBufferRef Data(StringRef(Res), "<bc file>");
+          Result->readBitcode(Data, Test.getProgram().M->getContext(),
+                              Test.getToolName());
           break;
         }
+
+        // If we broke out of the loop, we still need to wait for everything to
+        // avoid race access to the chunk set.
+        //
+        // TODO: Create a way to kill remaining items we're ignoring; they could
+        // take a long time.
+        waitAndDiscardResultsBarrier(TaskQueue);
+
         // Forward I to the last chunk processed in parallel.
         I += NumChunksProcessed - 1;
       } else {
-        Result = CheckChunk(
-            *I,
-            cloneReducerWorkItem(Test.getProgram(), Test.getTargetMachine()),
-            Test, ExtractChunksFromModule, UninterestingChunks,
-            ChunksStillConsideredInteresting);
+        Result =
+            CheckChunk(*I, Test.getProgram().clone(Test.getTargetMachine()),
+                       Test, ExtractChunksFromModule, UninterestingChunks,
+                       ChunksStillConsideredInteresting);
       }
 
       if (!Result)
         continue;
 
-      Chunk &ChunkToCheckForUninterestingness = *I;
+      const Chunk ChunkToCheckForUninterestingness = *I;
       FoundAtLeastOneNewUninterestingChunkWithCurrentGranularity = true;
       UninterestingChunks.insert(ChunkToCheckForUninterestingness);
       ReducedProgram = std::move(Result);
-      errs() << " **** SUCCESS | lines: " << getLines(CurrentFilepath) << "\n";
-      writeOutput(*ReducedProgram, "Saved new best reduction to ");
+
+      // FIXME: Report meaningful progress info
+      Test.writeOutput(" **** SUCCESS | Saved new best reduction to ");
     }
     // Delete uninteresting chunks
     erase_if(ChunksStillConsideredInteresting,
@@ -396,5 +351,7 @@
   // If we reduced the testcase replace it
   if (ReducedProgram)
     Test.setProgram(std::move(ReducedProgram));
-  errs() << "Couldn't increase anymore.\n";
+  if (Verbose)
+    errs() << "Couldn't increase anymore.\n";
+  errs() << "----------------------------\n";
 }
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 76aaf25..5b60ea6 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Delta.h
@@ -1,4 +1,4 @@
-//===- Delta.h - Delta Debugging Algorithm Implementation -----------------===//
+//===- Delta.h - Delta Debugging Algorithm Implementation -------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -15,14 +15,18 @@
 #ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_DELTA_H
 #define LLVM_TOOLS_LLVM_REDUCE_DELTAS_DELTA_H
 
-#include "TestRunner.h"
+#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 {
 
+class TestRunner;
+
 struct Chunk {
   int Begin;
   int End;
@@ -31,10 +35,10 @@
   bool contains(int Index) const { return Index >= Begin && Index <= End; }
 
   void print() const {
-    errs() << "[" << Begin;
+    errs() << '[' << Begin;
     if (End - Begin != 0)
-      errs() << "," << End;
-    errs() << "]";
+      errs() << ',' << End;
+    errs() << ']';
   }
 
   /// Operator when populating CurrentChunks in Generic Delta Pass
@@ -42,12 +46,39 @@
     return C1.Begin != C2.Begin || C1.End != C2.End;
   }
 
+  friend bool operator==(const Chunk &C1, const Chunk &C2) {
+    return C1.Begin == C2.Begin && C1.End == C2.End;
+  }
+
   /// Operator used for sets
   friend bool operator<(const Chunk &C1, const Chunk &C2) {
     return std::tie(C1.Begin, C1.End) < std::tie(C2.Begin, C2.End);
   }
 };
 
+template<>
+struct DenseMapInfo<Chunk> {
+  static inline Chunk getEmptyKey() {
+    return {DenseMapInfo<int>::getEmptyKey(),
+            DenseMapInfo<int>::getEmptyKey()};
+  }
+
+  static inline Chunk getTombstoneKey() {
+    return {DenseMapInfo<int>::getTombstoneKey(),
+            DenseMapInfo<int>::getTombstoneKey()};
+  }
+
+  static unsigned getHashValue(const Chunk Val) {
+    std::pair<int, int> PairVal = std::make_pair(Val.Begin, Val.End);
+    return DenseMapInfo<std::pair<int, int>>::getHashValue(PairVal);
+  }
+
+  static bool isEqual(const Chunk LHS, const Chunk RHS) {
+    return LHS == RHS;
+  }
+};
+
+
 /// Provides opaque interface for querying into ChunksToKeep without having to
 /// actually understand what is going on.
 class Oracle {
@@ -105,7 +136,8 @@
 ///
 /// Other implementations of the Delta Debugging algorithm can also be found in
 /// the CReduce, Delta, and Lithium projects.
-void runDeltaPass(TestRunner &Test, ReductionFunc ExtractChunksFromModule);
+void runDeltaPass(TestRunner &Test, ReductionFunc ExtractChunksFromModule,
+                  StringRef Message);
 } // namespace llvm
 
 #endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.cpp
index cdcd426..d889b3e 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.cpp
@@ -13,15 +13,17 @@
 
 #include "ReduceAliases.h"
 #include "Delta.h"
+#include "Utils.h"
 #include "llvm/IR/Constants.h"
 #include "llvm/IR/GlobalValue.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
 
 using namespace llvm;
 
 /// Removes all aliases aren't inside any of the
 /// desired Chunks.
-static void extractAliasesFromModule(Oracle &O, Module &Program) {
-  for (auto &GA : make_early_inc_range(Program.aliases())) {
+static void extractAliasesFromModule(Oracle &O, ReducerWorkItem &Program) {
+  for (auto &GA : make_early_inc_range(Program.getModule().aliases())) {
     if (!O.shouldKeep()) {
       GA.replaceAllUsesWith(GA.getAliasee());
       GA.eraseFromParent();
@@ -29,8 +31,21 @@
   }
 }
 
+static void extractIFuncsFromModule(Oracle &O, Module &Program) {
+  std::vector<GlobalIFunc *> IFuncs;
+  for (GlobalIFunc &GI : Program.ifuncs()) {
+    if (!O.shouldKeep())
+      IFuncs.push_back(&GI);
+  }
+
+  if (!IFuncs.empty())
+    lowerGlobalIFuncUsersAsGlobalCtor(Program, IFuncs);
+}
+
 void llvm::reduceAliasesDeltaPass(TestRunner &Test) {
-  errs() << "*** Reducing Aliases ...\n";
-  runDeltaPass(Test, extractAliasesFromModule);
-  errs() << "----------------------------\n";
+  runDeltaPass(Test, extractAliasesFromModule, "Reducing Aliases");
+}
+
+void llvm::reduceIFuncsDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, extractIFuncsFromModule, "Reducing Ifuncs");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.h
index 0660efe..404677d 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAliases.h
@@ -1,4 +1,4 @@
-//===- ReduceAliases.h - Specialized Delta Pass ---------------------------===//
+//===- ReduceAliases.h - Specialized Delta Pass -----------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -18,6 +18,7 @@
 
 namespace llvm {
 void reduceAliasesDeltaPass(TestRunner &Test);
+void reduceIFuncsDeltaPass(TestRunner &Test);
 } // namespace llvm
 
 #endif
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 45b5525..10bbc64 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp
@@ -56,7 +56,8 @@
 
 /// Removes out-of-chunk arguments from functions, and modifies their calls
 /// accordingly. It also removes allocations of out-of-chunk arguments.
-static void extractArgumentsFromModule(Oracle &O, Module &Program) {
+static void extractArgumentsFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
   std::vector<Argument *> InitArgsToKeep;
   std::vector<Function *> Funcs;
   // Get inside-chunk arguments, as well as their parent function
@@ -119,6 +120,5 @@
 }
 
 void llvm::reduceArgumentsDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing Arguments...\n";
-  runDeltaPass(Test, extractArgumentsFromModule);
+  runDeltaPass(Test, extractArgumentsFromModule, "Reducing Arguments");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.h
index 228409d..5adcfe8 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceArguments.h
@@ -1,4 +1,4 @@
-//===- ReduceArguments.h - Specialized Delta Pass -------------------------===//
+//===- ReduceArguments.h - Specialized Delta Pass ---------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
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 7b87088..df87ce7 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp
@@ -42,142 +42,115 @@
 
 namespace {
 
-using AttrPtrVecTy = std::vector<const Attribute *>;
-using AttrPtrIdxVecVecTy = std::pair<unsigned, AttrPtrVecTy>;
-using AttrPtrVecVecTy = SmallVector<AttrPtrIdxVecVecTy, 3>;
-
 /// Given ChunksToKeep, produce a map of global variables/functions/calls
 /// and indexes of attributes to be preserved for each of them.
 class AttributeRemapper : public InstVisitor<AttributeRemapper> {
   Oracle &O;
+  LLVMContext &Context;
 
 public:
-  DenseMap<GlobalVariable *, AttrPtrVecTy> GlobalVariablesToRefine;
-  DenseMap<Function *, AttrPtrVecVecTy> FunctionsToRefine;
-  DenseMap<CallBase *, AttrPtrVecVecTy> CallsToRefine;
-
-  explicit AttributeRemapper(Oracle &O) : O(O) {}
+  AttributeRemapper(Oracle &O, LLVMContext &C) : O(O), Context(C) {}
 
   void visitModule(Module &M) {
-    for (GlobalVariable &GV : M.getGlobalList())
+    for (GlobalVariable &GV : M.globals())
       visitGlobalVariable(GV);
   }
 
   void visitGlobalVariable(GlobalVariable &GV) {
     // Global variables only have one attribute set.
-    const AttributeSet &AS = GV.getAttributes();
-    if (AS.hasAttributes())
-      visitAttributeSet(AS, GlobalVariablesToRefine[&GV]);
-  }
-
-  void visitFunction(Function &F) {
-    if (F.getIntrinsicID() != Intrinsic::not_intrinsic)
-      return; // We can neither add nor remove attributes from intrinsics.
-    visitAttributeList(F.getAttributes(), FunctionsToRefine[&F]);
-  }
-
-  void visitCallBase(CallBase &I) {
-    visitAttributeList(I.getAttributes(), CallsToRefine[&I]);
-  }
-
-  void visitAttributeList(const AttributeList &AL,
-                          AttrPtrVecVecTy &AttributeSetsToPreserve) {
-    assert(AttributeSetsToPreserve.empty() && "Should not be sharing vectors.");
-    AttributeSetsToPreserve.reserve(AL.getNumAttrSets());
-    for (unsigned SetIdx : AL.indexes()) {
-      AttrPtrIdxVecVecTy AttributesToPreserve;
-      AttributesToPreserve.first = SetIdx;
-      visitAttributeSet(AL.getAttributes(AttributesToPreserve.first),
-                        AttributesToPreserve.second);
-      if (!AttributesToPreserve.second.empty())
-        AttributeSetsToPreserve.emplace_back(std::move(AttributesToPreserve));
+    AttributeSet AS = GV.getAttributes();
+    if (AS.hasAttributes()) {
+      AttrBuilder AttrsToPreserve(Context);
+      visitAttributeSet(AS, AttrsToPreserve);
+      GV.setAttributes(AttributeSet::get(Context, AttrsToPreserve));
     }
   }
 
-  void visitAttributeSet(const AttributeSet &AS,
-                         AttrPtrVecTy &AttrsToPreserve) {
-    assert(AttrsToPreserve.empty() && "Should not be sharing vectors.");
-    AttrsToPreserve.reserve(AS.getNumAttributes());
-    for (const Attribute &A : AS)
-      if (O.shouldKeep())
-        AttrsToPreserve.emplace_back(&A);
-  }
-};
-
-struct AttributeCounter : public InstVisitor<AttributeCounter> {
-  /// How many features (in this case, attributes) did we count, total?
-  int AttributeCount = 0;
-
-  void visitModule(Module &M) {
-    for (GlobalVariable &GV : M.getGlobalList())
-      visitGlobalVariable(GV);
-  }
-
-  void visitGlobalVariable(GlobalVariable &GV) {
-    // Global variables only have one attribute set.
-    visitAttributeSet(GV.getAttributes());
-  }
-
   void visitFunction(Function &F) {
-    if (F.getIntrinsicID() != Intrinsic::not_intrinsic)
-      return; // We can neither add nor remove attributes from intrinsics.
-    visitAttributeList(F.getAttributes());
+    // We can neither add nor remove attributes from intrinsics.
+    if (F.getIntrinsicID() == Intrinsic::not_intrinsic)
+      F.setAttributes(visitAttributeList(F.getAttributes()));
   }
 
-  void visitCallBase(CallBase &I) { visitAttributeList(I.getAttributes()); }
-
-  void visitAttributeList(const AttributeList &AL) {
-    for (const AttributeSet &AS : AL)
-      visitAttributeSet(AS);
+  void visitCallBase(CallBase &CB) {
+    CB.setAttributes(visitAttributeList(CB.getAttributes()));
   }
 
-  void visitAttributeSet(const AttributeSet &AS) {
-    AttributeCount += AS.getNumAttributes();
+  AttributeSet visitAttributeIndex(AttributeList AL, unsigned Index) {
+    AttrBuilder AttributesToPreserve(Context);
+    visitAttributeSet(AL.getAttributes(Index), AttributesToPreserve);
+
+    if (AttributesToPreserve.attrs().empty())
+      return {};
+    return AttributeSet::get(Context, AttributesToPreserve);
+  }
+
+  AttributeList visitAttributeList(AttributeList AL) {
+    SmallVector<std::pair<unsigned, AttributeSet>> NewAttrList;
+    NewAttrList.reserve(AL.getNumAttrSets());
+
+    for (unsigned SetIdx : AL.indexes()) {
+      if (SetIdx == AttributeList::FunctionIndex)
+        continue;
+
+      AttributeSet AttrSet = visitAttributeIndex(AL, SetIdx);
+      if (AttrSet.hasAttributes())
+        NewAttrList.emplace_back(SetIdx, AttrSet);
+    }
+
+    // FIXME: It's ridiculous that indexes() doesn't give us the correct order
+    // for contructing a new AttributeList. Special case the function index so
+    // we don't have to sort.
+    AttributeSet FnAttrSet =
+        visitAttributeIndex(AL, AttributeList::FunctionIndex);
+    if (FnAttrSet.hasAttributes())
+      NewAttrList.emplace_back(AttributeList::FunctionIndex, FnAttrSet);
+
+    return AttributeList::get(Context, NewAttrList);
+  }
+
+  void visitAttributeSet(const AttributeSet &AS, AttrBuilder &AttrsToPreserve) {
+    // Optnone requires noinline, so removing noinline requires removing the
+    // pair.
+    Attribute NoInline = AS.getAttribute(Attribute::NoInline);
+    bool RemoveNoInline = false;
+    if (NoInline.isValid()) {
+      RemoveNoInline = !O.shouldKeep();
+      if (!RemoveNoInline)
+        AttrsToPreserve.addAttribute(NoInline);
+    }
+
+    for (Attribute A : AS) {
+      if (A.isEnumAttribute()) {
+        Attribute::AttrKind Kind = A.getKindAsEnum();
+        if (Kind == Attribute::NoInline)
+          continue;
+
+        if (RemoveNoInline && Kind == Attribute::OptimizeNone)
+          continue;
+
+        // TODO: Could only remove this if there are no constrained calls in the
+        // function.
+        if (Kind == Attribute::StrictFP) {
+          AttrsToPreserve.addAttribute(A);
+          continue;
+        }
+      }
+
+      if (O.shouldKeep())
+        AttrsToPreserve.addAttribute(A);
+    }
   }
 };
 
 } // namespace
 
-AttributeSet
-convertAttributeRefToAttributeSet(LLVMContext &C,
-                                  ArrayRef<const Attribute *> Attributes) {
-  AttrBuilder B(C);
-  for (const Attribute *A : Attributes)
-    B.addAttribute(*A);
-  return AttributeSet::get(C, B);
-}
-
-AttributeList convertAttributeRefVecToAttributeList(
-    LLVMContext &C, ArrayRef<AttrPtrIdxVecVecTy> AttributeSets) {
-  std::vector<std::pair<unsigned, AttributeSet>> SetVec;
-  SetVec.reserve(AttributeSets.size());
-
-  transform(AttributeSets, std::back_inserter(SetVec),
-            [&C](const AttrPtrIdxVecVecTy &V) {
-              return std::make_pair(
-                  V.first, convertAttributeRefToAttributeSet(C, V.second));
-            });
-
-  llvm::sort(SetVec, llvm::less_first()); // All values are unique.
-
-  return AttributeList::get(C, SetVec);
-}
-
 /// Removes out-of-chunk attributes from module.
-static void extractAttributesFromModule(Oracle &O, Module &Program) {
-  AttributeRemapper R(O);
-  R.visit(Program);
-
-  LLVMContext &C = Program.getContext();
-  for (const auto &I : R.GlobalVariablesToRefine)
-    I.first->setAttributes(convertAttributeRefToAttributeSet(C, I.second));
-  for (const auto &I : R.FunctionsToRefine)
-    I.first->setAttributes(convertAttributeRefVecToAttributeList(C, I.second));
-  for (const auto &I : R.CallsToRefine)
-    I.first->setAttributes(convertAttributeRefVecToAttributeList(C, I.second));
+static void extractAttributesFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  AttributeRemapper R(O, WorkItem.getContext());
+  R.visit(WorkItem.getModule());
 }
 
 void llvm::reduceAttributesDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing Attributes...\n";
-  runDeltaPass(Test, extractAttributesFromModule);
+  runDeltaPass(Test, extractAttributesFromModule, "Reducing Attributes");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.h
index 375e764..a2e9955 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceAttributes.h
@@ -1,4 +1,4 @@
-//===- ReduceAttributes.h - Specialized Delta Pass ------------------------===//
+//===- ReduceAttributes.h - Specialized Delta Pass --------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp
index 520a45c..6858dac 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp
@@ -22,24 +22,49 @@
 #include "llvm/IR/Value.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Local.h"
+
 #include <vector>
 
+#define DEBUG_TYPE "llvm-reduce"
+
 using namespace llvm;
 
 /// Replaces BB Terminator with one that only contains Chunk BBs
 static void replaceBranchTerminator(BasicBlock &BB,
-                                    const DenseSet<BasicBlock *> &BBsToKeep) {
+                                    const DenseSet<BasicBlock *> &BBsToDelete) {
   auto *Term = BB.getTerminator();
   std::vector<BasicBlock *> ChunkSuccessors;
-  for (auto *Succ : successors(&BB))
-    if (BBsToKeep.count(Succ))
+  for (auto *Succ : successors(&BB)) {
+    if (!BBsToDelete.count(Succ))
       ChunkSuccessors.push_back(Succ);
+  }
 
   // BB only references Chunk BBs
   if (ChunkSuccessors.size() == Term->getNumSuccessors())
     return;
 
-  bool IsBranch = isa<BranchInst>(Term) || isa<InvokeInst>(Term);
+  bool IsBranch = isa<BranchInst>(Term);
+  if (InvokeInst *Invoke = dyn_cast<InvokeInst>(Term)) {
+    LandingPadInst *LP = Invoke->getLandingPadInst();
+    // Remove landingpad instruction if the containing block isn't used by other
+    // invokes.
+    if (none_of(LP->getParent()->users(), [Invoke](User *U) {
+          return U != Invoke && isa<InvokeInst>(U);
+        })) {
+      LP->replaceAllUsesWith(getDefaultValue(LP->getType()));
+      LP->eraseFromParent();
+    } else if (!ChunkSuccessors.empty() &&
+               ChunkSuccessors[0] == LP->getParent()) {
+      // If the selected successor is the landing pad, clear the chunk
+      // successors to avoid creating a regular branch to the landing pad which
+      // would result in invalid IR.
+      ChunkSuccessors.clear();
+    }
+    IsBranch = true;
+  }
+
   Value *Address = nullptr;
   if (auto *IndBI = dyn_cast<IndirectBrInst>(Term))
     Address = IndBI->getAddress();
@@ -48,18 +73,6 @@
   Term->eraseFromParent();
 
   if (ChunkSuccessors.empty()) {
-    // Scan forward in BB list to try find a block that is kept.
-    Function &F = *BB.getParent();
-    Function::iterator FI = BB.getIterator();
-    FI++;
-    while (FI != F.end()) {
-      auto &FIB = *FI;
-      if (BBsToKeep.count(&FIB) && !isa<PHINode>(FIB.begin())) {
-        BranchInst::Create(&FIB, &BB);
-        return;
-      }
-      FI++;
-    }
     // If that fails then resort to replacing with a ret.
     auto *FnRetTy = BB.getParent()->getReturnType();
     ReturnInst::Create(BB.getContext(),
@@ -84,70 +97,121 @@
 /// replace with something)
 static void
 removeUninterestingBBsFromSwitch(SwitchInst &SwInst,
-                                 const DenseSet<BasicBlock *> &BBsToKeep) {
-  if (!BBsToKeep.count(SwInst.getDefaultDest())) {
-    auto *FnRetTy = SwInst.getParent()->getParent()->getReturnType();
-    ReturnInst::Create(SwInst.getContext(),
-                       FnRetTy->isVoidTy() ? nullptr : getDefaultValue(FnRetTy),
-                       SwInst.getParent());
-    SwInst.eraseFromParent();
-  } else
-    for (int I = 0, E = SwInst.getNumCases(); I != E; ++I) {
-      auto Case = SwInst.case_begin() + I;
-      if (!BBsToKeep.count(Case->getCaseSuccessor())) {
-        SwInst.removeCase(Case);
-        --I;
-        --E;
-      }
+                                 const DenseSet<BasicBlock *> &BBsToDelete) {
+  for (int I = 0, E = SwInst.getNumCases(); I != E; ++I) {
+    auto Case = SwInst.case_begin() + I;
+    if (BBsToDelete.count(Case->getCaseSuccessor())) {
+      SwInst.removeCase(Case);
+      --I;
+      --E;
     }
+  }
+
+  if (BBsToDelete.count(SwInst.getDefaultDest())) {
+    if (SwInst.getNumCases() == 0) {
+      auto *FnRetTy = SwInst.getParent()->getParent()->getReturnType();
+      Value *RetValue =
+          FnRetTy->isVoidTy() ? nullptr : getDefaultValue(FnRetTy);
+      ReturnInst::Create(SwInst.getContext(), RetValue, SwInst.getParent());
+      SwInst.eraseFromParent();
+      return;
+    }
+
+    // Replace the default dest with one of the other cases
+    auto Case = SwInst.case_begin();
+
+    BasicBlock *NewDefault = Case->getCaseSuccessor();
+    SwInst.setDefaultDest(NewDefault);
+
+    for (PHINode &SuccPHI : NewDefault->phis()) {
+      SuccPHI.addIncoming(SuccPHI.getIncomingValueForBlock(SwInst.getParent()),
+                          SwInst.getParent());
+    }
+  }
 }
 
 /// Removes out-of-chunk arguments from functions, and modifies their calls
 /// accordingly. It also removes allocations of out-of-chunk arguments.
-static void extractBasicBlocksFromModule(Oracle &O, Module &Program) {
-  DenseSet<BasicBlock *> BBsToKeep;
+static void extractBasicBlocksFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  DenseSet<BasicBlock *> BBsToDelete;
+  df_iterator_default_set<BasicBlock *> Reachable;
 
-  SmallVector<BasicBlock *> BBsToDelete;
-  for (auto &F : Program) {
-    for (auto &BB : F) {
-      if (O.shouldKeep())
-        BBsToKeep.insert(&BB);
-      else {
-        BBsToDelete.push_back(&BB);
-        // Remove out-of-chunk BB from successor phi nodes
-        for (auto *Succ : successors(&BB))
-          Succ->removePredecessor(&BB);
-      }
+  for (auto &F : WorkItem.getModule()) {
+    if (F.empty())
+      continue;
+
+    BasicBlock &Entry = F.getEntryBlock();
+    for (auto *BB : depth_first_ext(&Entry, Reachable))
+      (void)BB;
+
+    // Skip any function with unreachable blocks. It's somewhat difficult to
+    // avoid producing invalid IR without deleting them.
+    //
+    // We also do not want to unconditionally delete them, as doing so would
+    // break the invariant of changing the number of chunks during counting.
+
+    const bool HasUnreachableBlocks = Reachable.size() != F.size();
+    Reachable.clear();
+
+    if (HasUnreachableBlocks) {
+      LLVM_DEBUG(dbgs() << "Skipping function with unreachable blocks\n");
+      continue;
     }
-  }
 
-  // Replace terminators that reference out-of-chunk BBs
-  for (auto &F : Program)
-    for (auto &BB : F) {
+    for (BasicBlock &BB : F) {
+      if (&BB != &Entry && !O.shouldKeep())
+        BBsToDelete.insert(&BB);
+    }
+
+    // Replace terminators that reference out-of-chunk BBs
+    for (BasicBlock &BB : F) {
       if (auto *SwInst = dyn_cast<SwitchInst>(BB.getTerminator()))
-        removeUninterestingBBsFromSwitch(*SwInst, BBsToKeep);
+        removeUninterestingBBsFromSwitch(*SwInst, BBsToDelete);
       else
-        replaceBranchTerminator(BB, BBsToKeep);
+        replaceBranchTerminator(BB, BBsToDelete);
     }
 
-  // Replace out-of-chunk switch uses
-  for (auto &BB : BBsToDelete) {
-    // Instructions might be referenced in other BBs
-    for (auto &I : *BB)
-      I.replaceAllUsesWith(getDefaultValue(I.getType()));
-    if (BB->getParent()->size() == 1) {
-      // this is the last basic block of the function, thus we must also make
-      // sure to remove comdat and set linkage to external
-      auto F = BB->getParent();
-      F->deleteBody();
-      F->setComdat(nullptr);
-    } else {
-      BB->eraseFromParent();
-    }
+    // Cleanup any blocks that are now dead after eliminating this set. This
+    // will likely be larger than the number of blocks the oracle told us to
+    // delete.
+    EliminateUnreachableBlocks(F);
+    BBsToDelete.clear();
   }
 }
 
 void llvm::reduceBasicBlocksDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing Basic Blocks...\n";
-  runDeltaPass(Test, extractBasicBlocksFromModule);
+  runDeltaPass(Test, extractBasicBlocksFromModule, "Reducing Basic Blocks");
+}
+
+static void removeUnreachableBasicBlocksFromModule(Oracle &O,
+                                                   ReducerWorkItem &WorkItem) {
+  std::vector<BasicBlock *> DeadBlocks;
+  df_iterator_default_set<BasicBlock *> Reachable;
+
+  for (Function &F : WorkItem.getModule()) {
+    if (F.empty())
+      continue;
+
+    // Mark all reachable blocks.
+    for (BasicBlock *BB : depth_first_ext(&F, Reachable))
+      (void)BB;
+
+    if (Reachable.size() != F.size() && !O.shouldKeep()) {
+      for (BasicBlock &BB : F) {
+        if (!Reachable.count(&BB))
+          DeadBlocks.push_back(&BB);
+      }
+
+      // Delete the dead blocks.
+      DeleteDeadBlocks(DeadBlocks, nullptr, /*KeepOneInputPHIs*/ false);
+      DeadBlocks.clear();
+    }
+
+    Reachable.clear();
+  }
+}
+
+void llvm::reduceUnreachableBasicBlocksDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, removeUnreachableBasicBlocksFromModule,
+               "Removing Unreachable Basic Blocks");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.h
index 4938552..a090d67 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.h
@@ -1,4 +1,4 @@
-//===- ReduceArguments.h - Specialized Delta Pass -------------------------===//
+//===- ReduceArguments.h - Specialized Delta Pass ---------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -7,7 +7,7 @@
 //===----------------------------------------------------------------------===//
 //
 // This file implements a function which calls the Generic Delta pass in order
-// to reduce uninteresting Arguments from defined functions.
+// to reduce uninteresting BasicBlocks from defined functions.
 //
 //===----------------------------------------------------------------------===//
 #ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEBASICBLOCKS_H
@@ -19,6 +19,7 @@
 
 namespace llvm {
 void reduceBasicBlocksDeltaPass(TestRunner &Test);
+void reduceUnreachableBasicBlocksDeltaPass(TestRunner &Test);
 } // namespace llvm
 
 #endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDIMetadata.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDIMetadata.cpp
new file mode 100644
index 0000000..bbd928a
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDIMetadata.cpp
@@ -0,0 +1,104 @@
+//===- ReduceDIMetadata.cpp - Specialized Delta pass for DebugInfo --------===//
+//
+// 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 two functions used by the Generic Delta Debugging
+// Algorithm, which are used to reduce DebugInfo metadata nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceDIMetadata.h"
+#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>
+
+using namespace llvm;
+
+using MDNodeList = SmallVector<MDNode *>;
+
+void identifyUninterestingMDNodes(Oracle &O, MDNodeList &MDs) {
+  SetVector<std::tuple<MDNode *, size_t, MDNode *>> Tuples;
+  std::vector<MDNode *> ToLook;
+  SetVector<MDNode *> Visited;
+
+  // Start by looking at the attachments we collected
+  for (const auto &NMD : MDs)
+    if (NMD)
+      ToLook.push_back(NMD);
+
+  while (!ToLook.empty()) {
+    MDNode *MD = ToLook.back();
+    ToLook.pop_back();
+
+    if (Visited.count(MD))
+      continue;
+
+    // Determine if the current MDNode is DebugInfo
+    if (DINode *DIM = dyn_cast_or_null<DINode>(MD)) {
+      // Scan operands and record attached tuples
+      for (size_t I = 0; I < DIM->getNumOperands(); ++I)
+        if (MDTuple *MDT = dyn_cast_or_null<MDTuple>(DIM->getOperand(I)))
+          if (!Visited.count(MDT) && MDT->getNumOperands())
+            Tuples.insert({DIM, I, MDT});
+    }
+
+    // Add all of the operands of the current node to the loop's todo list.
+    for (Metadata *Op : MD->operands())
+      if (MDNode *OMD = dyn_cast_or_null<MDNode>(Op))
+        ToLook.push_back(OMD);
+
+    Visited.insert(MD);
+  }
+
+  for (auto &T : Tuples) {
+    auto [DbgNode, OpIdx, Tup] = T;
+    // Remove the operands of the tuple that are not in the desired chunks.
+    SmallVector<Metadata *, 16> TN;
+    for (size_t I = 0; I < Tup->getNumOperands(); ++I) {
+      // Ignore any operands that are not DebugInfo metadata nodes.
+      if (isa_and_nonnull<DINode>(Tup->getOperand(I)))
+        // Don't add uninteresting operands to the tuple.
+        if (!O.shouldKeep())
+          continue;
+
+      TN.push_back(Tup->getOperand(I));
+    }
+    if (TN.size() != Tup->getNumOperands())
+      DbgNode->replaceOperandWith(OpIdx, DbgNode->get(DbgNode->getContext(), TN));
+  }
+}
+
+static void extractDIMetadataFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
+
+  MDNodeList MDs;
+  // Collect all !dbg metadata attachments.
+  for (const auto &DC : Program.debug_compile_units())
+    if (DC)
+      MDs.push_back(DC);
+  for (GlobalVariable &GV : Program.globals())
+    GV.getMetadata(llvm::LLVMContext::MD_dbg, MDs);
+  for (Function &F : Program.functions()) {
+    F.getMetadata(llvm::LLVMContext::MD_dbg, MDs);
+    for (Instruction &I : instructions(F))
+      if (auto *DI = I.getMetadata(llvm::LLVMContext::MD_dbg))
+        MDs.push_back(DI);
+  }
+  identifyUninterestingMDNodes(O, MDs);
+}
+
+void llvm::reduceDIMetadataDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, extractDIMetadataFromModule, "Reducing DIMetadata");
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDIMetadata.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDIMetadata.h
new file mode 100644
index 0000000..379c14a
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceDIMetadata.h
@@ -0,0 +1,23 @@
+//===- ReduceMetadata.h - 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 two functions used by the Generic Delta Debugging
+// Algorithm, which are used to reduce Metadata nodes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEDIMETADATA_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEDIMETADATA_H
+
+#include "TestRunner.h"
+
+namespace llvm {
+void reduceDIMetadataDeltaPass(TestRunner &Test);
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.cpp
index 63dd2f0..21875ba 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.cpp
@@ -13,24 +13,50 @@
 
 #include "ReduceFunctionBodies.h"
 #include "Delta.h"
+#include "Utils.h"
 #include "llvm/IR/GlobalValue.h"
+#include "llvm/IR/Instructions.h"
 
 using namespace llvm;
 
 /// Removes all the bodies of defined functions that aren't inside any of the
 /// desired Chunks.
-static void extractFunctionBodiesFromModule(Oracle &O, Module &Program) {
+static void extractFunctionBodiesFromModule(Oracle &O,
+                                            ReducerWorkItem &WorkItem) {
   // Delete out-of-chunk function bodies
-  std::vector<Function *> FuncDefsToReduce;
-  for (auto &F : Program)
-    if (!F.isDeclaration() && !O.shouldKeep()) {
+  for (auto &F : WorkItem.getModule()) {
+    if (!F.isDeclaration() && !hasAliasUse(F) && !O.shouldKeep()) {
       F.deleteBody();
       F.setComdat(nullptr);
     }
+  }
 }
 
 void llvm::reduceFunctionBodiesDeltaPass(TestRunner &Test) {
-  errs() << "*** Reducing Function Bodies...\n";
-  runDeltaPass(Test, extractFunctionBodiesFromModule);
-  errs() << "----------------------------\n";
+  runDeltaPass(Test, extractFunctionBodiesFromModule,
+               "Reducing Function Bodies");
+}
+
+static void reduceFunctionData(Oracle &O, ReducerWorkItem &WorkItem) {
+  for (Function &F : WorkItem.getModule()) {
+    if (F.hasPersonalityFn()) {
+      if (none_of(F,
+                  [](const BasicBlock &BB) {
+                    return BB.isEHPad() || isa<ResumeInst>(BB.getTerminator());
+                  }) &&
+          !O.shouldKeep()) {
+        F.setPersonalityFn(nullptr);
+      }
+    }
+
+    if (F.hasPrefixData() && !O.shouldKeep())
+      F.setPrefixData(nullptr);
+
+    if (F.hasPrologueData() && !O.shouldKeep())
+      F.setPrologueData(nullptr);
+  }
+}
+
+void llvm::reduceFunctionDataDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, reduceFunctionData, "Reducing Function Data");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.h
index bfe701b..ae738fb 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.h
@@ -1,4 +1,4 @@
-//===- ReduceFunctionBodies.h - Specialized Delta Pass --------------------===//
+//===- ReduceFunctionBodies.h - Specialized Delta Pass ----------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -18,6 +18,7 @@
 
 namespace llvm {
 void reduceFunctionBodiesDeltaPass(TestRunner &Test);
+void reduceFunctionDataDeltaPass(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 346e2c3..05127ec 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp
@@ -16,8 +16,8 @@
 #include "Delta.h"
 #include "Utils.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/IR/Constants.h"
-#include "llvm/IR/Instructions.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/Transforms/Utils/ModuleUtils.h"
 #include <iterator>
 #include <vector>
 
@@ -25,33 +25,38 @@
 
 /// Removes all the Defined Functions
 /// that aren't inside any of the desired Chunks.
-static void extractFunctionsFromModule(Oracle &O, Module &Program) {
+static void extractFunctionsFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
+
   // Record all out-of-chunk functions.
-  std::vector<std::reference_wrapper<Function>> FuncsToRemove;
-  copy_if(Program.functions(), std::back_inserter(FuncsToRemove),
-          [&O](Function &F) {
-            // Intrinsics don't have function bodies that are useful to
-            // reduce. Additionally, intrinsics may have additional operand
-            // constraints. But, do drop intrinsics that are not referenced.
-            return (!F.isIntrinsic() || F.use_empty()) && !O.shouldKeep();
-          });
+  SmallPtrSet<Constant *, 8> FuncsToRemove;
+  for (Function &F : Program.functions()) {
+    // Intrinsics don't have function bodies that are useful to
+    // reduce. Additionally, intrinsics may have additional operand
+    // constraints. But, do drop intrinsics that are not referenced.
+    if ((!F.isIntrinsic() || F.use_empty()) && !hasAliasOrBlockAddressUse(F) &&
+        !O.shouldKeep())
+      FuncsToRemove.insert(&F);
+  }
+
+  removeFromUsedLists(Program, [&FuncsToRemove](Constant *C) {
+    return FuncsToRemove.count(C);
+  });
 
   // Then, drop body of each of them. We want to batch this and do nothing else
   // here so that minimal number of remaining exteranal uses will remain.
-  for (Function &F : FuncsToRemove)
-    F.dropAllReferences();
+  for (Constant *F : FuncsToRemove)
+    F->dropAllReferences();
 
   // And finally, we can actually delete them.
-  for (Function &F : FuncsToRemove) {
+  for (Constant *F : FuncsToRemove) {
     // Replace all *still* remaining uses with the default value.
-    F.replaceAllUsesWith(getDefaultValue(F.getType()));
+    F->replaceAllUsesWith(getDefaultValue(F->getType()));
     // And finally, fully drop it.
-    F.eraseFromParent();
+    cast<Function>(F)->eraseFromParent();
   }
 }
 
 void llvm::reduceFunctionsDeltaPass(TestRunner &Test) {
-  errs() << "*** Reducing Functions...\n";
-  runDeltaPass(Test, extractFunctionsFromModule);
-  errs() << "----------------------------\n";
+  runDeltaPass(Test, extractFunctionsFromModule, "Reducing Functions");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.h
index f5bc83b..d3ff0d9 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceFunctions.h
@@ -1,4 +1,4 @@
-//===- ReduceFunctions.h - Specialized Delta Pass -------------------------===//
+//===- ReduceFunctions.h - Specialized Delta Pass ---------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.cpp
index 33ec3ae..1d1463a 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.cpp
@@ -17,16 +17,19 @@
   return GO.getAlign().has_value();
 }
 
-static void reduceGOs(Oracle &O, Module &Program) {
-  for (auto &GO : Program.global_objects()) {
+static bool shouldReduceComdat(GlobalObject &GO) { return GO.hasComdat(); }
+
+static void reduceGOs(Oracle &O, ReducerWorkItem &Program) {
+  for (auto &GO : Program.getModule().global_objects()) {
     if (shouldReduceSection(GO) && !O.shouldKeep())
       GO.setSection("");
     if (shouldReduceAlign(GO) && !O.shouldKeep())
       GO.setAlignment(MaybeAlign());
+    if (shouldReduceComdat(GO) && !O.shouldKeep())
+      GO.setComdat(nullptr);
   }
 }
 
 void llvm::reduceGlobalObjectsDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing GlobalObjects...\n";
-  runDeltaPass(Test, reduceGOs);
+  runDeltaPass(Test, reduceGOs, "Reducing GlobalObjects");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.h
index 7224b9b..35c38a9 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalObjects.h
@@ -1,4 +1,4 @@
-//===- ReduceGlobalObjects.h ----------------------------------------------===//
+//===- ReduceGlobalObjects.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.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp
index 26a3cbd..470d5ba 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp
@@ -37,8 +37,8 @@
   return GV.isThreadLocal();
 }
 
-static void reduceGVs(Oracle &O, Module &Program) {
-  for (auto &GV : Program.global_values()) {
+static void reduceGVs(Oracle &O, ReducerWorkItem &Program) {
+  for (auto &GV : Program.getModule().global_values()) {
     if (shouldReduceDSOLocal(GV) && !O.shouldKeep())
       GV.setDSOLocal(false);
     if (shouldReduceVisibility(GV) && !O.shouldKeep()) {
@@ -58,6 +58,5 @@
 }
 
 void llvm::reduceGlobalValuesDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing GlobalValues...\n";
-  runDeltaPass(Test, reduceGVs);
+  runDeltaPass(Test, reduceGVs, "Reducing GlobalValues");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.h
index ea32a6c..19c0707 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.h
@@ -1,4 +1,4 @@
-//===- ReduceGlobalValues.h - Specialized Delta Pass ----------------------===//
+//===- ReduceGlobalValues.h - Specialized Delta Pass ------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.cpp
index c9e4d9f..4c71252 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.cpp
@@ -18,9 +18,9 @@
 using namespace llvm;
 
 /// Removes all the Initialized GVs that aren't inside the desired Chunks.
-static void extractGVsFromModule(Oracle &O, Module &Program) {
+static void extractGVsFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
   // Drop initializers of out-of-chunk GVs
-  for (auto &GV : Program.globals())
+  for (auto &GV : WorkItem.getModule().globals())
     if (GV.hasInitializer() && !O.shouldKeep()) {
       GV.setInitializer(nullptr);
       GV.setLinkage(GlobalValue::LinkageTypes::ExternalLinkage);
@@ -29,6 +29,5 @@
 }
 
 void llvm::reduceGlobalsInitializersDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing GVs initializers...\n";
-  runDeltaPass(Test, extractGVsFromModule);
+  runDeltaPass(Test, extractGVsFromModule, "Reducing GV Initializers");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.h
index 0f5f22a..318b29b 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.h
@@ -1,4 +1,4 @@
-//===- reduceGlobalsInitializersDeltaPass.h - Specialized Delta Pass ------===//
+//===- ReduceGlobalVarInitializers.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.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp
index 908c984..b448081 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp
@@ -14,51 +14,46 @@
 #include "ReduceGlobalVars.h"
 #include "Utils.h"
 #include "llvm/IR/Constants.h"
-#include <set>
+#include "llvm/Transforms/Utils/ModuleUtils.h"
 
 using namespace llvm;
 
+static bool shouldAlwaysKeep(const GlobalVariable &GV) {
+  return GV.getName() == "llvm.used" || GV.getName() == "llvm.compiler.used";
+}
+
 /// Removes all the GVs that aren't inside the desired Chunks.
-static void extractGVsFromModule(Oracle &O, Module &Program) {
+static void extractGVsFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
+
   // Get GVs inside desired chunks
-  std::vector<GlobalVariable *> InitGVsToKeep;
-  for (auto &GV : Program.globals())
-    if (O.shouldKeep())
+  std::vector<Constant *> InitGVsToKeep;
+  for (auto &GV : Program.globals()) {
+    if (shouldAlwaysKeep(GV) || O.shouldKeep())
       InitGVsToKeep.push_back(&GV);
+  }
 
   // We create a vector first, then convert it to a set, so that we don't have
   // to pay the cost of rebalancing the set frequently if the order we insert
   // the elements doesn't match the order they should appear inside the set.
-  std::set<GlobalVariable *> GVsToKeep(InitGVsToKeep.begin(),
-                                       InitGVsToKeep.end());
+  DenseSet<Constant *> GVsToKeep(InitGVsToKeep.begin(), InitGVsToKeep.end());
 
   // Delete out-of-chunk GVs and their uses
-  std::vector<GlobalVariable *> ToRemove;
-  std::vector<WeakVH> InstToRemove;
-  for (auto &GV : Program.globals())
-    if (!GVsToKeep.count(&GV)) {
-      for (auto *U : GV.users())
-        if (auto *Inst = dyn_cast<Instruction>(U))
-          InstToRemove.push_back(Inst);
-
-      GV.replaceAllUsesWith(getDefaultValue(GV.getType()));
-      ToRemove.push_back(&GV);
-    }
-
-  // Delete (unique) Instruction uses of unwanted GVs
-  for (Value *V : InstToRemove) {
-    if (!V)
-      continue;
-    auto *Inst = cast<Instruction>(V);
-    Inst->replaceAllUsesWith(getDefaultValue(Inst->getType()));
-    Inst->eraseFromParent();
+  DenseSet<Constant *> ToRemove;
+  for (auto &GV : Program.globals()) {
+    if (!GVsToKeep.count(&GV))
+      ToRemove.insert(&GV);
   }
 
-  for (auto *GV : ToRemove)
-    GV->eraseFromParent();
+  removeFromUsedLists(Program,
+                      [&ToRemove](Constant *C) { return ToRemove.count(C); });
+
+  for (auto *GV : ToRemove) {
+    GV->replaceAllUsesWith(getDefaultValue(GV->getType()));
+    cast<GlobalVariable>(GV)->eraseFromParent();
+  }
 }
 
 void llvm::reduceGlobalsDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing GVs...\n";
-  runDeltaPass(Test, extractGVsFromModule);
+  runDeltaPass(Test, extractGVsFromModule, "Reducing GlobalVariables");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.h
index fe7813c..1198dce 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.h
@@ -1,4 +1,4 @@
-//===- ReduceGlobalVars.h - Specialized Delta Pass ------------------------===//
+//===- ReduceGlobalVars.h - Specialized Delta Pass --------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceIRReferences.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceIRReferences.cpp
index 975bdc2..fe4e13b 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceIRReferences.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceIRReferences.cpp
@@ -15,6 +15,8 @@
 #include "ReduceIRReferences.h"
 #include "Delta.h"
 #include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
 
 using namespace llvm;
 
@@ -67,16 +69,15 @@
 }
 
 void llvm::reduceIRInstructionReferencesDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing IR references from instructions...\n";
-  runDeltaPass(Test, stripIRFromInstructions);
+  runDeltaPass(Test, stripIRFromInstructions,
+               "Reducing IR references from instructions");
 }
 
 void llvm::reduceIRBlockReferencesDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing IR references from blocks...\n";
-  runDeltaPass(Test, stripIRFromBlocks);
+  runDeltaPass(Test, stripIRFromBlocks, "Reducing IR references from blocks");
 }
 
 void llvm::reduceIRFunctionReferencesDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing IR references from functions...\n";
-  runDeltaPass(Test, stripIRFromFunctions);
+  runDeltaPass(Test, stripIRFromFunctions,
+               "Reducing IR references from functions");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp
new file mode 100644
index 0000000..c73e74e
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.cpp
@@ -0,0 +1,68 @@
+//===- ReduceInstructionFlags.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Try to remove optimization flags on instructions
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceInstructionFlags.h"
+#include "Delta.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Operator.h"
+
+using namespace llvm;
+
+static void reduceFlagsInModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  for (Function &F : WorkItem.getModule()) {
+    for (Instruction &I : instructions(F)) {
+      if (auto *OBO = dyn_cast<OverflowingBinaryOperator>(&I)) {
+        if (OBO->hasNoSignedWrap() && !O.shouldKeep())
+          I.setHasNoSignedWrap(false);
+        if (OBO->hasNoUnsignedWrap() && !O.shouldKeep())
+          I.setHasNoUnsignedWrap(false);
+      } else if (auto *PE = dyn_cast<PossiblyExactOperator>(&I)) {
+        if (PE->isExact() && !O.shouldKeep())
+          I.setIsExact(false);
+      } else if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
+        if (GEP->isInBounds() && !O.shouldKeep())
+          GEP->setIsInBounds(false);
+      } else if (auto *FPOp = dyn_cast<FPMathOperator>(&I)) {
+        FastMathFlags Flags = FPOp->getFastMathFlags();
+
+        if (Flags.allowReassoc() && !O.shouldKeep())
+          Flags.setAllowReassoc(false);
+
+        if (Flags.noNaNs() && !O.shouldKeep())
+          Flags.setNoNaNs(false);
+
+        if (Flags.noInfs() && !O.shouldKeep())
+          Flags.setNoInfs(false);
+
+        if (Flags.noSignedZeros() && !O.shouldKeep())
+          Flags.setNoSignedZeros(false);
+
+        if (Flags.allowReciprocal() && !O.shouldKeep())
+          Flags.setAllowReciprocal(false);
+
+        if (Flags.allowContract() && !O.shouldKeep())
+          Flags.setAllowContract(false);
+
+        if (Flags.approxFunc() && !O.shouldKeep())
+          Flags.setApproxFunc(false);
+
+        I.copyFastMathFlags(Flags);
+      }
+    }
+  }
+}
+
+void llvm::reduceInstructionFlagsDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, reduceFlagsInModule, "Reducing Instruction Flags");
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.h
new file mode 100644
index 0000000..1764c01
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlags.h
@@ -0,0 +1,18 @@
+//===- ReduceInstructionFlags.h - Specialized Delta Pass --------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEINSTRUCTIONFLAGS_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEINSTRUCTIONFLAGS_H
+
+#include "TestRunner.h"
+
+namespace llvm {
+void reduceInstructionFlagsDeltaPass(TestRunner &Test);
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlagsMIR.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlagsMIR.cpp
index 4c3b4d3..f2895b3 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlagsMIR.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlagsMIR.cpp
@@ -13,6 +13,7 @@
 
 #include "ReduceInstructionFlagsMIR.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
 using namespace llvm;
 
 static void removeFlagsFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
@@ -30,6 +31,5 @@
 }
 
 void llvm::reduceInstructionFlagsMIRDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing Instruction flags...\n";
-  runDeltaPass(Test, removeFlagsFromModule);
+  runDeltaPass(Test, removeFlagsFromModule, "Reducing Instruction Flags");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlagsMIR.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlagsMIR.h
index a211994..a5a34d2 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlagsMIR.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionFlagsMIR.h
@@ -1,4 +1,4 @@
-//===- ReduceInstructionFlagsMIR.h  - Specialized Delta Pass --------------===//
+//===- ReduceInstructionFlagsMIR.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.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp
index 078da9e..7dfe028 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp
@@ -17,9 +17,19 @@
 
 using namespace llvm;
 
+/// Filter out cases where deleting the instruction will likely cause the
+/// user/def of the instruction to fail the verifier.
+//
+// TODO: Technically the verifier only enforces preallocated token usage and
+// there is a none token.
+static bool shouldAlwaysKeep(const Instruction &I) {
+  return I.isEHPad() || I.getType()->isTokenTy() || I.isSwiftError();
+}
+
 /// Removes out-of-chunk arguments from functions, and modifies their calls
 /// accordingly. It also removes allocations of out-of-chunk arguments.
-static void extractInstrFromModule(Oracle &O, Module &Program) {
+static void extractInstrFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
   std::vector<Instruction *> InitInstToKeep;
 
   for (auto &F : Program)
@@ -27,9 +37,10 @@
       // Removing the terminator would make the block invalid. Only iterate over
       // instructions before the terminator.
       InitInstToKeep.push_back(BB.getTerminator());
-      for (auto &Inst : make_range(BB.begin(), std::prev(BB.end())))
-        if (O.shouldKeep())
+      for (auto &Inst : make_range(BB.begin(), std::prev(BB.end()))) {
+        if (shouldAlwaysKeep(Inst) || O.shouldKeep())
           InitInstToKeep.push_back(&Inst);
+      }
     }
 
   // We create a vector first, then convert it to a set, so that we don't have
@@ -52,6 +63,5 @@
 }
 
 void llvm::reduceInstructionsDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing Instructions...\n";
-  runDeltaPass(Test, extractInstrFromModule);
+  runDeltaPass(Test, extractInstrFromModule, "Reducing Instructions");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h
index be568f1..8c13a02 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructions.h
@@ -1,4 +1,4 @@
-//===- ReduceArguments.h - Specialized Delta Pass -------------------------===//
+//===- ReduceInstructions.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.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp
index c87d5eb..b97d75a 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp
@@ -18,6 +18,7 @@
 #include "llvm/CodeGen/MachineDominators.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
 
@@ -33,10 +34,10 @@
     auto &MI = *RI;
     // All Def operands explicit and implicit.
     for (auto &MO : MI.operands()) {
-      if (!MO.isReg() || !MO.isDef())
+      if (!MO.isReg() || !MO.isDef() || MO.isDead())
         continue;
       auto Reg = MO.getReg();
-      if (Register::isPhysicalRegister(Reg))
+      if (Reg.isPhysical())
         continue;
 
       if (MRI->getRegClassOrRegBank(Reg) == RC && MRI->getType(Reg) == Ty &&
@@ -89,10 +90,10 @@
   // some other dominating definition (that is not to be deleted).
   for (auto *MI : ToDelete) {
     for (auto &MO : MI->operands()) {
-      if (!MO.isReg() || !MO.isDef())
+      if (!MO.isReg() || !MO.isDef() || MO.isDead())
         continue;
       auto Reg = MO.getReg();
-      if (Register::isPhysicalRegister(Reg))
+      if (Reg.isPhysical())
         continue;
       auto UI = MRI->use_begin(Reg);
       auto UE = MRI->use_end();
@@ -128,8 +129,13 @@
         bool IsGeneric = MRI->getRegClassOrNull(Reg) == nullptr;
         unsigned ImpDef = IsGeneric ? TargetOpcode::G_IMPLICIT_DEF
                                     : TargetOpcode::IMPLICIT_DEF;
+
+        unsigned State = getRegState(MO);
+        if (MO.getSubReg())
+          State |= RegState::Undef;
+
         BuildMI(*EntryMBB, EntryInsPt, DebugLoc(), TII->get(ImpDef))
-          .addReg(NewReg, getRegState(MO), MO.getSubReg());
+          .addReg(NewReg, State, MO.getSubReg());
       }
 
       // Update all uses.
@@ -153,6 +159,5 @@
 }
 
 void llvm::reduceInstructionsMIRDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing Instructions...\n";
-  runDeltaPass(Test, extractInstrFromModule);
+  runDeltaPass(Test, extractInstrFromModule, "Reducing Instructions");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.h
index a59f1aa..70e0ac5 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.h
@@ -1,4 +1,4 @@
-//===- ReduceInstructionsMIR.h  - Specialized Delta Pass ------------------===//
+//===- ReduceInstructionsMIR.h  - Specialized Delta Pass --------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInvokes.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInvokes.cpp
new file mode 100644
index 0000000..c6425a7
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInvokes.cpp
@@ -0,0 +1,41 @@
+//===- ReduceInvokes.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Try to replace invokes with calls.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceInvokes.h"
+#include "Delta.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/Transforms/Utils/Local.h"
+
+using namespace llvm;
+
+static void reduceInvokesInFunction(Oracle &O, Function &F) {
+  for (BasicBlock &BB : F) {
+    InvokeInst *Invoke = dyn_cast<InvokeInst>(BB.getTerminator());
+    if (Invoke && !O.shouldKeep())
+      changeToCall(Invoke);
+  }
+
+  // TODO: We most likely are leaving behind dead landingpad blocks. Should we
+  // delete unreachable blocks now, or leave that for the unreachable block
+  // reduction.
+}
+
+static void reduceInvokesInModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  for (Function &F : WorkItem.getModule()) {
+    if (F.hasPersonalityFn())
+      reduceInvokesInFunction(O, F);
+  }
+}
+
+void llvm::reduceInvokesDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, reduceInvokesInModule, "Reducing Invokes");
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInvokes.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInvokes.h
new file mode 100644
index 0000000..9607add
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceInvokes.h
@@ -0,0 +1,18 @@
+//===- ReduceInvokes.h - Specialized Delta Pass -----------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEINVOKES_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEINVOKES_H
+
+#include "TestRunner.h"
+
+namespace llvm {
+void reduceInvokesDeltaPass(TestRunner &Test);
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMemoryOperations.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMemoryOperations.cpp
new file mode 100644
index 0000000..8e73ea0
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMemoryOperations.cpp
@@ -0,0 +1,110 @@
+//===- ReduceOpcodes.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceMemoryOperations.h"
+#include "Delta.h"
+#include "llvm/IR/InstIterator.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+
+using namespace llvm;
+
+static void removeVolatileInFunction(Oracle &O, Function &F) {
+  LLVMContext &Ctx = F.getContext();
+  for (Instruction &I : instructions(F)) {
+    if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
+      if (LI->isVolatile() && !O.shouldKeep())
+        LI->setVolatile(false);
+    } else if (StoreInst *SI = dyn_cast<StoreInst>(&I)) {
+      if (SI->isVolatile() && !O.shouldKeep())
+        SI->setVolatile(false);
+    } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(&I)) {
+      if (RMW->isVolatile() && !O.shouldKeep())
+        RMW->setVolatile(false);
+    } else if (AtomicCmpXchgInst *CmpXChg = dyn_cast<AtomicCmpXchgInst>(&I)) {
+      if (CmpXChg->isVolatile() && !O.shouldKeep())
+        CmpXChg->setVolatile(false);
+    } else if (MemIntrinsic *MemIntrin = dyn_cast<MemIntrinsic>(&I)) {
+      if (MemIntrin->isVolatile() && !O.shouldKeep())
+        MemIntrin->setVolatile(ConstantInt::getFalse(Ctx));
+    }
+  }
+}
+
+static void removeVolatileInModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  for (Function &F : WorkItem.getModule())
+    removeVolatileInFunction(O, F);
+}
+
+void llvm::reduceVolatileInstructionsDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, removeVolatileInModule, "Reducing Volatile Instructions");
+}
+
+static void reduceAtomicSyncScopesInFunction(Oracle &O, Function &F) {
+  for (Instruction &I : instructions(F)) {
+    if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
+      if (LI->getSyncScopeID() != SyncScope::System && !O.shouldKeep())
+        LI->setSyncScopeID(SyncScope::System);
+    } else if (StoreInst *SI = dyn_cast<StoreInst>(&I)) {
+      if (SI->getSyncScopeID() != SyncScope::System && !O.shouldKeep())
+        SI->setSyncScopeID(SyncScope::System);
+    } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(&I)) {
+      if (RMW->getSyncScopeID() != SyncScope::System && !O.shouldKeep())
+        RMW->setSyncScopeID(SyncScope::System);
+    } else if (AtomicCmpXchgInst *CmpXChg = dyn_cast<AtomicCmpXchgInst>(&I)) {
+      if (CmpXChg->getSyncScopeID() != SyncScope::System && !O.shouldKeep())
+        CmpXChg->setSyncScopeID(SyncScope::System);
+    } else if (FenceInst *Fence = dyn_cast<FenceInst>(&I)) {
+      if (Fence->getSyncScopeID() != SyncScope::System && !O.shouldKeep())
+        Fence->setSyncScopeID(SyncScope::System);
+    }
+  }
+}
+
+static void reduceAtomicSyncScopesInModule(Oracle &O,
+                                           ReducerWorkItem &WorkItem) {
+  for (Function &F : WorkItem.getModule())
+    reduceAtomicSyncScopesInFunction(O, F);
+}
+
+void llvm::reduceAtomicSyncScopesDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, reduceAtomicSyncScopesInModule,
+               "Reducing Atomic Sync Scopes");
+}
+
+// TODO: Might be helpful to incrementally relax orders
+static void reduceAtomicOrderingInFunction(Oracle &O, Function &F) {
+  for (Instruction &I : instructions(F)) {
+    if (LoadInst *LI = dyn_cast<LoadInst>(&I)) {
+      if (LI->getOrdering() != AtomicOrdering::NotAtomic && !O.shouldKeep())
+        LI->setAtomic(AtomicOrdering::NotAtomic);
+    } else if (StoreInst *SI = dyn_cast<StoreInst>(&I)) {
+      if (SI->getOrdering() != AtomicOrdering::NotAtomic && !O.shouldKeep())
+        SI->setAtomic(AtomicOrdering::NotAtomic);
+    } else if (AtomicRMWInst *RMW = dyn_cast<AtomicRMWInst>(&I)) {
+      if (RMW->getOrdering() != AtomicOrdering::Monotonic && !O.shouldKeep())
+        RMW->setOrdering(AtomicOrdering::Monotonic);
+    } else if (AtomicCmpXchgInst *CmpXChg = dyn_cast<AtomicCmpXchgInst>(&I)) {
+      if (CmpXChg->getSuccessOrdering() != AtomicOrdering::Monotonic &&
+          !O.shouldKeep())
+        CmpXChg->setSuccessOrdering(AtomicOrdering::Monotonic);
+      if (CmpXChg->getFailureOrdering() != AtomicOrdering::Monotonic &&
+          !O.shouldKeep())
+        CmpXChg->setFailureOrdering(AtomicOrdering::Monotonic);
+    }
+  }
+}
+
+static void reduceAtomicOrderingInModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  for (Function &F : WorkItem.getModule())
+    reduceAtomicOrderingInFunction(O, F);
+}
+
+void llvm::reduceAtomicOrderingDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, reduceAtomicOrderingInModule, "Reducing Atomic Ordering");
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMemoryOperations.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMemoryOperations.h
new file mode 100644
index 0000000..ca6a770
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMemoryOperations.h
@@ -0,0 +1,20 @@
+//===- ReduceMemoryOperations.h - Specialized Delta Pass --------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEMEMORYOPERATIONS_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEMEMORYOPERATIONS_H
+
+#include "TestRunner.h"
+
+namespace llvm {
+void reduceVolatileInstructionsDeltaPass(TestRunner &Test);
+void reduceAtomicSyncScopesDeltaPass(TestRunner &Test);
+void reduceAtomicOrderingDeltaPass(TestRunner &Test);
+} // namespace llvm
+
+#endif
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 078230e..d491858 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp
@@ -16,17 +16,66 @@
 #include "llvm/ADT/Sequence.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/IR/InstIterator.h"
+#include "llvm/IR/IntrinsicInst.h"
 #include <vector>
 
 using namespace llvm;
 
+static bool shouldKeepDebugIntrinsicMetadata(Instruction &I, MDNode &MD) {
+  return isa<DILocation>(MD) && isa<DbgInfoIntrinsic>(I);
+}
+
+static bool shouldKeepDebugNamedMetadata(NamedMDNode &MD) {
+  return MD.getName() == "llvm.dbg.cu" && MD.getNumOperands() != 0;
+}
+
+// Named metadata with simple list-like behavior, so that it's valid to remove
+// operands individually.
+static constexpr StringLiteral ListNamedMetadata[] = {
+  "llvm.module.flags",
+  "llvm.ident",
+  "opencl.spir.version",
+  "opencl.ocl.version",
+  "opencl.used.extensions",
+  "opencl.used.optional.core.features",
+  "opencl.compiler.options"
+};
+
+/// Remove unneeded arguments to named metadata.
+static void reduceNamedMetadataOperands(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &M = WorkItem.getModule();
+
+  for (StringRef MDName : ListNamedMetadata) {
+    NamedMDNode *NamedNode = M.getNamedMetadata(MDName);
+    if (!NamedNode)
+      continue;
+
+    bool MadeChange = false;
+    SmallVector<MDNode *, 16> KeptOperands;
+    for (auto I : seq<unsigned>(0, NamedNode->getNumOperands())) {
+      if (O.shouldKeep())
+        KeptOperands.push_back(NamedNode->getOperand(I));
+      else
+        MadeChange = true;
+    }
+
+    if (MadeChange) {
+      NamedNode->clearOperands();
+      for (MDNode *KeptOperand : KeptOperands)
+        NamedNode->addOperand(KeptOperand);
+    }
+  }
+}
+
 /// Removes all the Named and Unnamed Metadata Nodes, as well as any debug
 /// functions that aren't inside the desired Chunks.
-static void extractMetadataFromModule(Oracle &O, Module &Program) {
+static void extractMetadataFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
+
   // Get out-of-chunk Named metadata nodes
   SmallVector<NamedMDNode *> NamedNodesToDelete;
   for (NamedMDNode &MD : Program.named_metadata())
-    if (!O.shouldKeep())
+    if (!shouldKeepDebugNamedMetadata(MD) && !O.shouldKeep())
       NamedNodesToDelete.push_back(&MD);
 
   for (NamedMDNode *NN : NamedNodesToDelete) {
@@ -58,15 +107,18 @@
     for (Instruction &I : instructions(F)) {
       SmallVector<std::pair<unsigned, MDNode *>> MDs;
       I.getAllMetadata(MDs);
-      for (std::pair<unsigned, MDNode *> &MD : MDs)
-        if (!O.shouldKeep())
+      for (std::pair<unsigned, MDNode *> &MD : MDs) {
+        if (!shouldKeepDebugIntrinsicMetadata(I, *MD.second) && !O.shouldKeep())
           I.setMetadata(MD.first, nullptr);
+      }
     }
   }
 }
 
 void llvm::reduceMetadataDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing Metadata...\n";
-  runDeltaPass(Test, extractMetadataFromModule);
-  outs() << "----------------------------\n";
+  runDeltaPass(Test, extractMetadataFromModule, "Reducing Metadata");
+}
+
+void llvm::reduceNamedMetadataDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, reduceNamedMetadataOperands, "Reducing Named Metadata");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.h
index 6efc3f5..f3af31a 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceMetadata.h
@@ -1,4 +1,4 @@
-//===- ReduceMetadata.h - Specialized Delta Pass --------------------------===//
+//===- ReduceMetadata.h - Specialized Delta Pass ----------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -18,6 +18,7 @@
 
 namespace llvm {
 void reduceMetadataDeltaPass(TestRunner &Test);
+void reduceNamedMetadataDeltaPass(TestRunner &Test);
 } // namespace llvm
 
 #endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleData.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleData.cpp
index cbde789..17930ab 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleData.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleData.cpp
@@ -14,7 +14,9 @@
 
 using namespace llvm;
 
-static void clearModuleData(Oracle &O, Module &Program) {
+static void clearModuleData(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
+
   if (!Program.getModuleIdentifier().empty() && !O.shouldKeep())
     Program.setModuleIdentifier("");
   if (!Program.getSourceFileName().empty() && !O.shouldKeep())
@@ -25,6 +27,5 @@
 }
 
 void llvm::reduceModuleDataDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing Module Data...\n";
-  runDeltaPass(Test, clearModuleData);
+  runDeltaPass(Test, clearModuleData, "Reducing Module Data");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleData.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleData.h
index 972c534..960fe8c 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleData.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceModuleData.h
@@ -1,4 +1,4 @@
-//===- ReduceModuleData.h --------------------------------------------===//
+//===- ReduceModuleData.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.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOpcodes.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOpcodes.cpp
new file mode 100644
index 0000000..2140544
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOpcodes.cpp
@@ -0,0 +1,282 @@
+//===- ReduceOpcodes.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
+//
+//===----------------------------------------------------------------------===//
+//
+// Try to replace instructions that are likely to codegen to simpler or smaller
+// sequences. This is a fuzzy and target specific concept.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceOpcodes.h"
+#include "Delta.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/IntrinsicsAMDGPU.h"
+
+using namespace llvm;
+
+// Assume outgoing undef arguments aren't relevant.
+// TODO: Maybe skip any trivial constant arguments.
+static bool shouldIgnoreArgument(const Value *V) {
+  return isa<UndefValue>(V);
+}
+
+static Value *replaceIntrinsic(Module &M, IntrinsicInst *II,
+                               Intrinsic::ID NewIID,
+                               ArrayRef<Type *> Tys = std::nullopt) {
+  Function *NewFunc = Intrinsic::getDeclaration(&M, NewIID, Tys);
+  II->setCalledFunction(NewFunc);
+  return II;
+}
+
+static Value *reduceIntrinsic(Oracle &O, Module &M, IntrinsicInst *II) {
+  IRBuilder<> B(II);
+  switch (II->getIntrinsicID()) {
+  case Intrinsic::sqrt:
+    if (O.shouldKeep())
+      return nullptr;
+
+    return B.CreateFMul(II->getArgOperand(0),
+                        ConstantFP::get(II->getType(), 2.0));
+  case Intrinsic::minnum:
+  case Intrinsic::maxnum:
+  case Intrinsic::minimum:
+  case Intrinsic::maximum:
+  case Intrinsic::amdgcn_fmul_legacy:
+    if (O.shouldKeep())
+      return nullptr;
+    return B.CreateFMul(II->getArgOperand(0), II->getArgOperand(1));
+  case Intrinsic::amdgcn_workitem_id_y:
+  case Intrinsic::amdgcn_workitem_id_z:
+    if (O.shouldKeep())
+      return nullptr;
+    return replaceIntrinsic(M, II, Intrinsic::amdgcn_workitem_id_x);
+  case Intrinsic::amdgcn_workgroup_id_y:
+  case Intrinsic::amdgcn_workgroup_id_z:
+    if (O.shouldKeep())
+      return nullptr;
+    return replaceIntrinsic(M, II, Intrinsic::amdgcn_workgroup_id_x);
+  case Intrinsic::amdgcn_div_fixup:
+  case Intrinsic::amdgcn_fma_legacy:
+    if (O.shouldKeep())
+      return nullptr;
+    return replaceIntrinsic(M, II, Intrinsic::fma, {II->getType()});
+  default:
+    return nullptr;
+  }
+}
+
+/// Look for calls that look like they could be replaced with a load or store.
+static bool callLooksLikeLoadStore(CallBase *CB, Value *&DataArg,
+                                   Value *&PtrArg) {
+  const bool IsStore = CB->getType()->isVoidTy();
+
+  PtrArg = nullptr;
+  DataArg = nullptr;
+  for (Value *Arg : CB->args()) {
+    if (shouldIgnoreArgument(Arg))
+      continue;
+
+    if (!Arg->getType()->isSized())
+      return false;
+
+    PointerType *PT = dyn_cast<PointerType>(Arg->getType());
+    if (!PtrArg && PT) {
+      // FIXME: Could create bitcast for typed pointers, but roll back unused
+      // replacement only erases one instruction.
+      if (!IsStore && !PT->isOpaqueOrPointeeTypeMatches(CB->getType()))
+        return false;
+
+      PtrArg = Arg;
+      continue;
+    }
+
+    if (!IsStore || DataArg)
+      return false;
+
+    DataArg = Arg;
+  }
+
+  if (IsStore && !DataArg) {
+    // FIXME: For typed pointers, use element type?
+    DataArg = ConstantInt::get(IntegerType::getInt32Ty(CB->getContext()), 0);
+  }
+
+  // If we didn't find any arguments, we can fill in the pointer.
+  if (!PtrArg) {
+    unsigned AS = CB->getModule()->getDataLayout().getAllocaAddrSpace();
+
+    PointerType *PtrTy =
+        PointerType::get(DataArg ? DataArg->getType()
+                                 : IntegerType::getInt32Ty(CB->getContext()),
+                         AS);
+
+    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;
+}
+
+// TODO: Replace 2 pointer argument calls with memcpy
+static Value *tryReplaceCallWithLoadStore(Oracle &O, Module &M, CallBase *CB) {
+  Value *PtrArg = nullptr;
+  Value *DataArg = nullptr;
+  if (!callLooksLikeLoadStore(CB, DataArg, PtrArg) || O.shouldKeep())
+    return nullptr;
+
+  IRBuilder<> B(CB);
+  if (DataArg)
+    return B.CreateStore(DataArg, PtrArg, true);
+  return B.CreateLoad(CB->getType(), PtrArg, true);
+}
+
+static bool callLooksLikeOperator(CallBase *CB,
+                                  SmallVectorImpl<Value *> &OperatorArgs) {
+  Type *ReturnTy = CB->getType();
+  if (!ReturnTy->isFirstClassType())
+    return false;
+
+  for (Value *Arg : CB->args()) {
+    if (shouldIgnoreArgument(Arg))
+      continue;
+
+    if (Arg->getType() != ReturnTy)
+      return false;
+
+    OperatorArgs.push_back(Arg);
+  }
+
+  return true;
+}
+
+static Value *tryReplaceCallWithOperator(Oracle &O, Module &M, CallBase *CB) {
+  SmallVector<Value *, 4> Arguments;
+
+  if (!callLooksLikeOperator(CB, Arguments) || Arguments.size() > 3)
+    return nullptr;
+
+  if (O.shouldKeep())
+    return nullptr;
+
+  IRBuilder<> B(CB);
+  if (CB->getType()->isFPOrFPVectorTy()) {
+    switch (Arguments.size()) {
+    case 1:
+      return B.CreateFNeg(Arguments[0]);
+    case 2:
+      return B.CreateFMul(Arguments[0], Arguments[1]);
+    case 3:
+      return B.CreateIntrinsic(Intrinsic::fma, {CB->getType()}, Arguments);
+    default:
+      return nullptr;
+    }
+
+    llvm_unreachable("all argument sizes handled");
+  }
+
+  if (CB->getType()->isIntOrIntVectorTy()) {
+    switch (Arguments.size()) {
+    case 1:
+      return B.CreateUnaryIntrinsic(Intrinsic::bswap, Arguments[0]);
+    case 2:
+      return B.CreateAnd(Arguments[0], Arguments[1]);
+    case 3:
+      return B.CreateIntrinsic(Intrinsic::fshl, {CB->getType()}, Arguments);
+    default:
+      return nullptr;
+    }
+
+    llvm_unreachable("all argument sizes handled");
+  }
+
+  return nullptr;
+}
+
+static Value *reduceInstruction(Oracle &O, Module &M, Instruction &I) {
+  IRBuilder<> B(&I);
+
+  // TODO: fp binary operator with constant to fneg
+  switch (I.getOpcode()) {
+  case Instruction::FDiv:
+  case Instruction::FRem:
+    if (O.shouldKeep())
+      return nullptr;
+
+    // Divisions tends to codegen into a long sequence or a library call.
+    return B.CreateFMul(I.getOperand(0), I.getOperand(1));
+  case Instruction::UDiv:
+  case Instruction::SDiv:
+  case Instruction::URem:
+  case Instruction::SRem:
+    if (O.shouldKeep())
+      return nullptr;
+
+    // Divisions tends to codegen into a long sequence or a library call.
+    return B.CreateMul(I.getOperand(0), I.getOperand(1));
+  case Instruction::Add:
+  case Instruction::Sub: {
+    if (O.shouldKeep())
+      return nullptr;
+
+    // Add/sub are more likely codegen to instructions with carry out side
+    // effects.
+    return B.CreateOr(I.getOperand(0), I.getOperand(1));
+  }
+  case Instruction::Call: {
+    if (IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I))
+      return reduceIntrinsic(O, M, II);
+
+    CallBase *CB = cast<CallBase>(&I);
+
+    if (Value *NewOp = tryReplaceCallWithOperator(O, M, CB))
+      return NewOp;
+
+    if (Value *NewOp = tryReplaceCallWithLoadStore(O, M, CB))
+      return NewOp;
+
+    return nullptr;
+  }
+  default:
+    return nullptr;
+  }
+
+  return nullptr;
+}
+
+static void replaceOpcodesInModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Mod = WorkItem.getModule();
+
+  for (Function &F : Mod) {
+    for (BasicBlock &BB : F)
+      for (Instruction &I : make_early_inc_range(BB)) {
+        Instruction *Replacement =
+            dyn_cast_or_null<Instruction>(reduceInstruction(O, Mod, I));
+        if (Replacement && Replacement != &I) {
+          if (isa<FPMathOperator>(Replacement))
+            Replacement->copyFastMathFlags(&I);
+
+          Replacement->copyIRFlags(&I);
+          Replacement->copyMetadata(I);
+          Replacement->takeName(&I);
+          I.replaceAllUsesWith(Replacement);
+          I.eraseFromParent();
+        }
+      }
+  }
+}
+
+void llvm::reduceOpcodesDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, replaceOpcodesInModule, "Reducing Opcodes");
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOpcodes.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOpcodes.h
new file mode 100644
index 0000000..79edc7f
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOpcodes.h
@@ -0,0 +1,18 @@
+//===- ReduceOpcodes.h - Specialized Delta Pass -----------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEOPCODES_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEOPCODES_H
+
+#include "TestRunner.h"
+
+namespace llvm {
+void reduceOpcodesDeltaPass(TestRunner &Test);
+} // namespace llvm
+
+#endif
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 c28bbb2..6f9cafb 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp
@@ -95,7 +95,9 @@
 }
 
 /// Removes out-of-chunk operand bundles from calls.
-static void extractOperandBundesFromModule(Oracle &O, Module &Program) {
+static void extractOperandBundesFromModule(Oracle &O,
+                                           ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
   OperandBundleRemapper R(O);
   R.visit(Program);
 
@@ -104,6 +106,6 @@
 }
 
 void llvm::reduceOperandBundesDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing OperandBundes...\n";
-  runDeltaPass(Test, extractOperandBundesFromModule);
+  runDeltaPass(Test, extractOperandBundesFromModule,
+               "Reducing Operand Bundles");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h
index d07e021..390b029 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.h
@@ -1,4 +1,4 @@
-//===- ReduceOperandBundes.h - Specialized Delta Pass ---------------------===//
+//===- ReduceOperandBundes.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.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp
index 7c144eb..6bf84f2 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp
@@ -18,13 +18,26 @@
 using namespace PatternMatch;
 
 static void
-extractOperandsFromModule(Oracle &O, Module &Program,
+extractOperandsFromModule(Oracle &O, ReducerWorkItem &WorkItem,
                           function_ref<Value *(Use &)> ReduceValue) {
+  Module &Program = WorkItem.getModule();
+
   for (auto &F : Program.functions()) {
     for (auto &I : instructions(&F)) {
+      if (PHINode *Phi = dyn_cast<PHINode>(&I)) {
+        for (auto &Op : Phi->incoming_values()) {
+          if (!O.shouldKeep()) {
+            if (Value *Reduced = ReduceValue(Op))
+              Phi->setIncomingValueForBlock(Phi->getIncomingBlock(Op), Reduced);
+          }
+        }
+
+        continue;
+      }
+
       for (auto &Op : I.operands()) {
-        if (!O.shouldKeep()) {
-          if (Value *Reduced = ReduceValue(Op))
+        if (Value *Reduced = ReduceValue(Op)) {
+          if (!O.shouldKeep())
             Op.set(Reduced);
         }
       }
@@ -63,14 +76,23 @@
   return true;
 }
 
+static bool switchCaseExists(Use &Op, ConstantInt *CI) {
+  SwitchInst *SI = dyn_cast<SwitchInst>(Op.getUser());
+  if (!SI)
+    return false;
+  return SI->findCaseValue(CI) != SI->case_default();
+}
+
 void llvm::reduceOperandsOneDeltaPass(TestRunner &Test) {
-  errs() << "*** Reducing Operands to one...\n";
   auto ReduceValue = [](Use &Op) -> Value * {
     if (!shouldReduceOperand(Op))
       return nullptr;
 
     Type *Ty = Op->getType();
     if (auto *IntTy = dyn_cast<IntegerType>(Ty)) {
+      // Don't duplicate an existing switch case.
+      if (switchCaseExists(Op, ConstantInt::get(IntTy, 1)))
+        return nullptr;
       // Don't replace existing ones and zeroes.
       return (isOne(Op) || isZero(Op)) ? nullptr : ConstantInt::get(IntTy, 1);
     }
@@ -82,36 +104,48 @@
       if (isOne(Op) || isZero(Op) || isZeroOrOneFP(Op))
         return nullptr;
 
-      if (auto *IntTy = dyn_cast<IntegerType>(VT->getElementType()))
-        return ConstantVector::getSplat(VT->getElementCount(),
-                                        ConstantInt::get(IntTy, 1));
-
-      return ConstantVector::getSplat(
-          VT->getElementCount(), ConstantFP::get(VT->getElementType(), 1.0));
+      Type *ElementType = VT->getElementType();
+      Constant *C;
+      if (ElementType->isFloatingPointTy()) {
+        C = ConstantFP::get(ElementType, 1.0);
+      } else if (IntegerType *IntTy = dyn_cast<IntegerType>(ElementType)) {
+        C = ConstantInt::get(IntTy, 1);
+      } else {
+        return nullptr;
+      }
+      return ConstantVector::getSplat(VT->getElementCount(), C);
     }
 
     return nullptr;
   };
-  runDeltaPass(Test, [ReduceValue](Oracle &O, Module &Program) {
-    extractOperandsFromModule(O, Program, ReduceValue);
-  });
+  runDeltaPass(
+      Test,
+      [ReduceValue](Oracle &O, ReducerWorkItem &WorkItem) {
+        extractOperandsFromModule(O, WorkItem, ReduceValue);
+      },
+      "Reducing Operands to one");
 }
 
 void llvm::reduceOperandsZeroDeltaPass(TestRunner &Test) {
-  errs() << "*** Reducing Operands to zero...\n";
   auto ReduceValue = [](Use &Op) -> Value * {
     if (!shouldReduceOperand(Op))
       return nullptr;
+    // Don't duplicate an existing switch case.
+    if (auto *IntTy = dyn_cast<IntegerType>(Op->getType()))
+      if (switchCaseExists(Op, ConstantInt::get(IntTy, 0)))
+        return nullptr;
     // Don't replace existing zeroes.
     return isZero(Op) ? nullptr : Constant::getNullValue(Op->getType());
   };
-  runDeltaPass(Test, [ReduceValue](Oracle &O, Module &Program) {
-    extractOperandsFromModule(O, Program, ReduceValue);
-  });
+  runDeltaPass(
+      Test,
+      [ReduceValue](Oracle &O, ReducerWorkItem &Program) {
+        extractOperandsFromModule(O, Program, ReduceValue);
+      },
+      "Reducing Operands to zero");
 }
 
 void llvm::reduceOperandsNaNDeltaPass(TestRunner &Test) {
-  errs() << "*** Reducing Operands to NaN...\n";
   auto ReduceValue = [](Use &Op) -> Value * {
     Type *Ty = Op->getType();
     if (!Ty->isFPOrFPVectorTy())
@@ -131,7 +165,10 @@
 
     return ConstantFP::getQNaN(Ty);
   };
-  runDeltaPass(Test, [ReduceValue](Oracle &O, Module &Program) {
-    extractOperandsFromModule(O, Program, ReduceValue);
-  });
+  runDeltaPass(
+      Test,
+      [ReduceValue](Oracle &O, ReducerWorkItem &Program) {
+        extractOperandsFromModule(O, Program, ReduceValue);
+      },
+      "Reducing Operands to NaN");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperands.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperands.h
index 034f49b..b4a1899 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperands.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperands.h
@@ -1,4 +1,4 @@
-//===----------------------------------------------------------------------===//
+//===------------------------------------------------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
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 2dd113e..a634c3a 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsSkip.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsSkip.cpp
@@ -187,7 +187,9 @@
   }
 }
 
-static void extractOperandsFromModule(Oracle &O, Module &Program) {
+static void extractOperandsFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
+
   for (Function &F : Program.functions()) {
     SmallVector<std::pair<Use *, Value *>> Replacements;
     opportunities(F, [&](Use &Op, ArrayRef<Value *> Candidates) {
@@ -212,12 +214,16 @@
       }
     });
 
-    for (std::pair<Use *, Value *> P : Replacements)
-      P.first->set(P.second);
+    for (std::pair<Use *, Value *> P : Replacements) {
+      if (PHINode *Phi = dyn_cast<PHINode>(P.first->getUser()))
+        Phi->setIncomingValueForBlock(Phi->getIncomingBlock(*P.first), P.second);
+      else
+        P.first->set(P.second);
+    }
   }
 }
 
 void llvm::reduceOperandsSkipDeltaPass(TestRunner &Test) {
-  errs() << "*** Reducing operands by skipping over instructions ...\n";
-  runDeltaPass(Test, extractOperandsFromModule);
+  runDeltaPass(Test, extractOperandsFromModule,
+               "Reducing operands by skipping over instructions");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsSkip.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsSkip.h
index 79ee462..7989701 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsSkip.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsSkip.h
@@ -1,4 +1,4 @@
-//===----------------------------------------------------------------------===//
+//===------------------------------------------------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
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 f738a51..0f949ab 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.cpp
@@ -173,7 +173,9 @@
   NewF->setName(FName);
 }
 
-static void reduceOperandsToArgs(Oracle &O, Module &Program) {
+static void reduceOperandsToArgs(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
+
   SmallVector<Use *> OperandsToReduce;
   for (Function &F : make_early_inc_range(Program.functions())) {
     if (!canReplaceFunction(&F))
@@ -195,6 +197,6 @@
 }
 
 void llvm::reduceOperandsToArgsDeltaPass(TestRunner &Test) {
-  outs() << "*** Converting operands to function arguments ...\n";
-  return runDeltaPass(Test, reduceOperandsToArgs);
+  runDeltaPass(Test, reduceOperandsToArgs,
+               "Converting operands to function arguments");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.h
index 2bff393..23043dd 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceOperandsToArgs.h
@@ -1,4 +1,4 @@
-//===----------------------------------------------------------------------===//
+//===------------------------------------------------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterDefs.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterDefs.cpp
index ab4d28a..9725964 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterDefs.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterDefs.cpp
@@ -13,6 +13,7 @@
 
 #include "ReduceRegisterDefs.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
 
@@ -39,8 +40,8 @@
 
       int NumOperands = MI.getNumOperands();
       int NumRequiredOps = MI.getNumExplicitOperands() +
-                           MI.getDesc().getNumImplicitDefs() +
-                           MI.getDesc().getNumImplicitUses();
+                           MI.getDesc().implicit_defs().size() +
+                           MI.getDesc().implicit_uses().size();
 
       bool HaveDelete = false;
       // Do an initial scan in case the instruction defines the same register
@@ -117,6 +118,5 @@
 }
 
 void llvm::reduceRegisterDefsMIRDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing register defs...\n";
-  runDeltaPass(Test, removeDefsFromModule);
+  runDeltaPass(Test, removeDefsFromModule, "Reducing register defs");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterMasks.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterMasks.cpp
index 93d833c..f900d5c 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterMasks.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterMasks.cpp
@@ -13,6 +13,7 @@
 
 #include "ReduceRegisterMasks.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 
 using namespace llvm;
@@ -68,6 +69,5 @@
 }
 
 void llvm::reduceRegisterMasksMIRDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing register masks...\n";
-  runDeltaPass(Test, reduceMasksInModule);
+  runDeltaPass(Test, reduceMasksInModule, "Reducing register masks");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterUses.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterUses.cpp
index a461cb8..a608935 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterUses.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceRegisterUses.cpp
@@ -13,6 +13,7 @@
 
 #include "ReduceRegisterUses.h"
 #include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 
 using namespace llvm;
@@ -28,8 +29,8 @@
 
       int NumOperands = MI.getNumOperands();
       int NumRequiredOps = MI.getNumExplicitOperands() +
-                           MI.getDesc().getNumImplicitDefs() +
-                           MI.getDesc().getNumImplicitUses();
+                           MI.getDesc().implicit_defs().size() +
+                           MI.getDesc().implicit_uses().size();
 
       for (int I = NumOperands - 1; I >= 0; --I) {
         MachineOperand &MO = MI.getOperand(I);
@@ -62,6 +63,5 @@
 }
 
 void llvm::reduceRegisterUsesMIRDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing register uses...\n";
-  runDeltaPass(Test, removeUsesFromModule);
+  runDeltaPass(Test, removeUsesFromModule, "Reducing register uses");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.cpp
index a86db31..5b124a4 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.cpp
@@ -27,7 +27,10 @@
 
 /// Removes all special globals aren't inside any of the
 /// desired Chunks.
-static void extractSpecialGlobalsFromModule(Oracle &O, Module &Program) {
+static void extractSpecialGlobalsFromModule(Oracle &O,
+                                            ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
+
   for (StringRef Name : SpecialGlobalNames) {
     if (auto *Used = Program.getNamedGlobal(Name)) {
       Used->replaceAllUsesWith(getDefaultValue(Used->getType()));
@@ -37,7 +40,6 @@
 }
 
 void llvm::reduceSpecialGlobalsDeltaPass(TestRunner &Test) {
-  errs() << "*** Reducing Special Globals ...\n";
-  runDeltaPass(Test, extractSpecialGlobalsFromModule);
-  errs() << "----------------------------\n";
+  runDeltaPass(Test, extractSpecialGlobalsFromModule,
+               "Reducing Special Globals");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.h
index c0f3f9e..d177905 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.h
@@ -1,4 +1,4 @@
-//===- ReduceSpecialGlobals.h - Specialized Delta Pass --------------------===//
+//===- ReduceSpecialGlobals.h - Specialized Delta Pass ----------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceUsingSimplifyCFG.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceUsingSimplifyCFG.cpp
new file mode 100644
index 0000000..c49fcb9
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceUsingSimplifyCFG.cpp
@@ -0,0 +1,78 @@
+//===- ReduceUsingSimplifyCFG.h - 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 call SimplifyCFG on individual basic blocks.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ReduceUsingSimplifyCFG.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/Transforms/Utils/Local.h"
+
+using namespace llvm;
+
+static void reduceUsingSimplifyCFG(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
+  SmallVector<BasicBlock *, 16> ToSimplify;
+  for (auto &F : Program)
+    for (auto &BB : F)
+      if (!O.shouldKeep())
+        ToSimplify.push_back(&BB);
+  TargetTransformInfo TTI(Program.getDataLayout());
+  for (auto *BB : ToSimplify)
+    simplifyCFG(BB, TTI);
+}
+
+void llvm::reduceUsingSimplifyCFGDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, reduceUsingSimplifyCFG, "Reducing using SimplifyCFG");
+}
+static void reduceConditionals(Oracle &O, ReducerWorkItem &WorkItem,
+                               bool Direction) {
+  Module &M = WorkItem.getModule();
+  SmallVector<BasicBlock *, 16> ToSimplify;
+
+  for (auto &F : M) {
+    for (auto &BB : F) {
+      auto *BR = dyn_cast<BranchInst>(BB.getTerminator());
+      if (!BR || !BR->isConditional() || O.shouldKeep())
+        continue;
+
+      if (Direction)
+        BR->setCondition(ConstantInt::getTrue(BR->getContext()));
+      else
+        BR->setCondition(ConstantInt::getFalse(BR->getContext()));
+
+      ToSimplify.push_back(&BB);
+    }
+  }
+
+  TargetTransformInfo TTI(M.getDataLayout());
+  for (auto *BB : ToSimplify)
+    simplifyCFG(BB, TTI);
+}
+
+void llvm::reduceConditionalsTrueDeltaPass(TestRunner &Test) {
+  runDeltaPass(
+      Test,
+      [](Oracle &O, ReducerWorkItem &WorkItem) {
+        reduceConditionals(O, WorkItem, true);
+      },
+      "Reducing conditional branches to true");
+}
+
+void llvm::reduceConditionalsFalseDeltaPass(TestRunner &Test) {
+  runDeltaPass(
+      Test,
+      [](Oracle &O, ReducerWorkItem &WorkItem) {
+        reduceConditionals(O, WorkItem, false);
+      },
+      "Reducing conditional branches to false");
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceUsingSimplifyCFG.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceUsingSimplifyCFG.h
new file mode 100644
index 0000000..01a1460
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceUsingSimplifyCFG.h
@@ -0,0 +1,25 @@
+//===- ReduceUsingSimplifyCFG.h - Specialized Delta Pass --------*- 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 call SimplifyCFG on individual basic blocks.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_SIMPLIFYCFG_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_SIMPLIFYCFG_H
+
+#include "Delta.h"
+
+namespace llvm {
+void reduceUsingSimplifyCFGDeltaPass(TestRunner &Test);
+void reduceConditionalsTrueDeltaPass(TestRunner &Test);
+void reduceConditionalsFalseDeltaPass(TestRunner &Test);
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceVirtualRegisters.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceVirtualRegisters.cpp
index 1c5bda8..eed5be7 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceVirtualRegisters.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/ReduceVirtualRegisters.cpp
@@ -13,6 +13,7 @@
 
 #include "ReduceVirtualRegisters.h"
 #include "Delta.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/CodeGen/MachineRegisterInfo.h"
 
 using namespace llvm;
@@ -41,6 +42,6 @@
 }
 
 void llvm::reduceVirtualRegisterHintsDeltaPass(TestRunner &Test) {
-  outs() << "*** Reducing virtual register hints from functions...\n";
-  runDeltaPass(Test, dropRegisterHintsFromFunctions);
+  runDeltaPass(Test, dropRegisterHintsFromFunctions,
+               "Reducing virtual register hints from functions");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/RunIRPasses.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/RunIRPasses.cpp
new file mode 100644
index 0000000..acef29a
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/RunIRPasses.cpp
@@ -0,0 +1,54 @@
+//===- RunIRPasses.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "RunIRPasses.h"
+#include "Delta.h"
+#include "llvm/Passes/PassBuilder.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+extern cl::OptionCategory LLVMReduceOptions;
+
+static cl::opt<std::string> PassPipeline(
+    "ir-passes",
+    cl::desc("A textual description of the pass pipeline, same as "
+             "what's passed to `opt -passes`."),
+    cl::init("function(sroa,instcombine,gvn,simplifycfg,infer-address-spaces)"),
+    cl::cat(LLVMReduceOptions));
+
+static void runPasses(Oracle &O, ReducerWorkItem &WorkItem) {
+  Module &Program = WorkItem.getModule();
+  LoopAnalysisManager LAM;
+  FunctionAnalysisManager FAM;
+  CGSCCAnalysisManager CGAM;
+  ModuleAnalysisManager MAM;
+
+  PassInstrumentationCallbacks PIC;
+  PIC.registerShouldRunOptionalPassCallback(
+      [&](StringRef, Any) { return !O.shouldKeep(); });
+  PassBuilder PB(nullptr, PipelineTuningOptions(), std::nullopt, &PIC);
+
+  PB.registerModuleAnalyses(MAM);
+  PB.registerCGSCCAnalyses(CGAM);
+  PB.registerFunctionAnalyses(FAM);
+  PB.registerLoopAnalyses(LAM);
+  PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+
+  ModulePassManager MPM;
+  if (auto Err = PB.parsePassPipeline(MPM, PassPipeline)) {
+    errs() << toString(std::move(Err)) << "\n";
+    report_fatal_error("Error constructing pass pipeline");
+  }
+  MPM.run(Program, MAM);
+}
+
+void llvm::runIRPassesDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, runPasses, "Running passes");
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/RunIRPasses.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/RunIRPasses.h
new file mode 100644
index 0000000..f1d4140
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/RunIRPasses.h
@@ -0,0 +1,18 @@
+//===- RunIRPasses.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_RUNPASSES_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_RUNPASSES_H
+
+#include "Delta.h"
+
+namespace llvm {
+void runIRPassesDeltaPass(TestRunner &Test);
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/SimplifyInstructions.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/SimplifyInstructions.cpp
index 6e2e52a..fc21593 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/SimplifyInstructions.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/SimplifyInstructions.cpp
@@ -19,20 +19,21 @@
 
 /// Calls simplifyInstruction in each instruction in functions, and replaces
 /// their values.
-static void extractInstrFromModule(Oracle &O, Module &Program) {
+static void extractInstrFromModule(Oracle &O, ReducerWorkItem &WorkItem) {
   std::vector<Instruction *> InstsToDelete;
 
+  Module &Program = WorkItem.getModule();
   const DataLayout &DL = Program.getDataLayout();
 
   std::vector<Instruction *> InstToDelete;
   for (auto &F : Program) {
     for (auto &BB : F) {
       for (auto &Inst : BB) {
-        if (O.shouldKeep())
-          continue;
 
         SimplifyQuery Q(DL, &Inst);
         if (Value *Simplified = simplifyInstruction(&Inst, Q)) {
+          if (O.shouldKeep())
+            continue;
           Inst.replaceAllUsesWith(Simplified);
           InstToDelete.push_back(&Inst);
         }
@@ -45,6 +46,5 @@
 }
 
 void llvm::simplifyInstructionsDeltaPass(TestRunner &Test) {
-  outs() << "*** Simplifying Instructions...\n";
-  runDeltaPass(Test, extractInstrFromModule);
+  runDeltaPass(Test, extractInstrFromModule, "Simplifying Instructions");
 }
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/StripDebugInfo.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/StripDebugInfo.cpp
new file mode 100644
index 0000000..a65e55d
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/StripDebugInfo.cpp
@@ -0,0 +1,29 @@
+//===- StripDebugInfo.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
+//
+//===----------------------------------------------------------------------===//
+
+#include "StripDebugInfo.h"
+#include "Delta.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/Metadata.h"
+
+using namespace llvm;
+
+/// Removes all aliases aren't inside any of the
+/// desired Chunks.
+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.");
+  });
+  if (HasDebugInfo && !O.shouldKeep())
+    StripDebugInfo(Program);
+}
+
+void llvm::stripDebugInfoDeltaPass(TestRunner &Test) {
+  runDeltaPass(Test, stripDebugInfoImpl, "Stripping Debug Info");
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/StripDebugInfo.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/StripDebugInfo.h
new file mode 100644
index 0000000..56be459
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/StripDebugInfo.h
@@ -0,0 +1,18 @@
+//===- StripDebugInfo.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_STRIPDEBUGINFO_H
+#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_STRIPDEBUGINFO_H
+
+#include "Delta.h"
+
+namespace llvm {
+void stripDebugInfoDeltaPass(TestRunner &Test);
+} // namespace llvm
+
+#endif
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Utils.cpp b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Utils.cpp
index 0434eb7..669b9db 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Utils.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Utils.cpp
@@ -12,9 +12,29 @@
 
 #include "Utils.h"
 #include "llvm/IR/Constants.h"
+#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalIFunc.h"
 
 using namespace llvm;
 
+extern cl::OptionCategory LLVMReduceOptions;
+
+cl::opt<bool> llvm::Verbose("verbose",
+                            cl::desc("Print extra debugging information"),
+                            cl::init(false), cl::cat(LLVMReduceOptions));
+
 Value *llvm::getDefaultValue(Type *T) {
   return T->isVoidTy() ? PoisonValue::get(T) : Constant::getNullValue(T);
 }
+
+bool llvm::hasAliasUse(Function &F) {
+  return any_of(F.users(), [](User *U) {
+      return isa<GlobalAlias>(U) || isa<GlobalIFunc>(U);
+    });
+}
+
+bool llvm::hasAliasOrBlockAddressUse(Function &F) {
+  return any_of(F.users(), [](User *U) {
+    return isa<GlobalAlias, GlobalIFunc, BlockAddress>(U);
+  });
+}
diff --git a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Utils.h b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Utils.h
index e0c8f8e..e94aee5a 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/deltas/Utils.h
+++ b/src/llvm-project/llvm/tools/llvm-reduce/deltas/Utils.h
@@ -1,4 +1,4 @@
-//===- Utils.h - llvm-reduce utility functions ----------------------------===//
+//===- Utils.h - llvm-reduce utility functions ------------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -13,11 +13,17 @@
 #ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_UTILS_H
 #define LLVM_TOOLS_LLVM_REDUCE_DELTAS_UTILS_H
 
+#include "llvm/IR/Function.h"
 #include "llvm/IR/Value.h"
+#include "llvm/Support/CommandLine.h"
 
 namespace llvm {
 
+extern cl::opt<bool> Verbose;
+
 Value *getDefaultValue(Type *T);
+bool hasAliasUse(Function &F);
+bool hasAliasOrBlockAddressUse(Function &F);
 
 } // namespace llvm
 
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 4d338f4..ace5c95 100644
--- a/src/llvm-project/llvm/tools/llvm-reduce/llvm-reduce.cpp
+++ b/src/llvm-project/llvm/tools/llvm-reduce/llvm-reduce.cpp
@@ -17,30 +17,21 @@
 #include "DeltaManager.h"
 #include "ReducerWorkItem.h"
 #include "TestRunner.h"
-#include "llvm/Analysis/ProfileSummaryInfo.h"
-#include "llvm/Analysis/ModuleSummaryAnalysis.h"
-#include "llvm/ADT/SmallString.h"
 #include "llvm/Bitcode/BitcodeReader.h"
-#include "llvm/Bitcode/BitcodeWriter.h"
 #include "llvm/CodeGen/CommandFlags.h"
-#include "llvm/CodeGen/MachineFunction.h"
-#include "llvm/CodeGen/MachineModuleInfo.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/Verifier.h"
-#include "llvm/IRReader/IRReader.h"
-#include "llvm/MC/TargetRegistry.h"
 #include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Host.h"
 #include "llvm/Support/InitLLVM.h"
-#include "llvm/Support/SourceMgr.h"
-#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/MemoryBufferRef.h"
+#include "llvm/Support/Process.h"
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/raw_ostream.h"
-#include "llvm/Transforms/IPO.h"
 #include <system_error>
 #include <vector>
 
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
 using namespace llvm;
 
 cl::OptionCategory LLVMReduceOptions("llvm-reduce options");
@@ -50,18 +41,24 @@
 static cl::opt<bool> Version("v", cl::desc("Alias for -version"), cl::Hidden,
                              cl::cat(LLVMReduceOptions));
 
+static cl::opt<bool> PreserveDebugEnvironment(
+    "preserve-debug-environment",
+    cl::desc("Don't disable features used for crash "
+             "debugging (crash reports, llvm-symbolizer and core dumps)"),
+    cl::cat(LLVMReduceOptions));
+
 static cl::opt<bool>
     PrintDeltaPasses("print-delta-passes",
                      cl::desc("Print list of delta passes, passable to "
                               "--delta-passes as a comma separated list"),
                      cl::cat(LLVMReduceOptions));
 
-static cl::opt<std::string> InputFilename(cl::Positional, cl::Required,
+static cl::opt<std::string> InputFilename(cl::Positional,
                                           cl::desc("<input llvm ll/bc file>"),
                                           cl::cat(LLVMReduceOptions));
 
 static cl::opt<std::string>
-    TestFilename("test", cl::Required,
+    TestFilename("test",
                  cl::desc("Name of the interesting-ness test to be run"),
                  cl::cat(LLVMReduceOptions));
 
@@ -71,7 +68,8 @@
                   cl::cat(LLVMReduceOptions));
 
 static cl::opt<std::string> OutputFilename(
-    "output", cl::desc("Specify the output file. default: reduced.ll|mir"));
+    "output",
+    cl::desc("Specify the output file. default: reduced.ll|.bc|.mir"));
 static cl::alias OutputFileAlias("o", cl::desc("Alias for -output"),
                                  cl::aliasopt(OutputFilename),
                                  cl::cat(LLVMReduceOptions));
@@ -92,6 +90,11 @@
                              clEnumValN(InputLanguages::MIR, "mir", "")),
                   cl::cat(LLVMReduceOptions));
 
+static cl::opt<bool> ForceOutputBitcode(
+    "output-bitcode",
+    cl::desc("Emit final result as bitcode instead of text IR"), cl::Hidden,
+    cl::cat(LLVMReduceOptions));
+
 static cl::opt<int>
     MaxPassIterations("max-pass-iterations",
                       cl::desc("Maximum number of times to run the full set "
@@ -100,60 +103,57 @@
 
 static codegen::RegisterCodeGenFlags CGF;
 
-void writeOutput(ReducerWorkItem &M, StringRef Message) {
-  if (ReplaceInput) // In-place
+/// Turn off crash debugging features
+///
+/// Crash is expected, so disable crash reports and symbolization to reduce
+/// output clutter and avoid potentially slow symbolization.
+static void disableEnvironmentDebugFeatures() {
+  sys::Process::PreventCoreFiles();
+
+  // TODO: Copied from not. Should have a wrapper around setenv.
+#ifdef _WIN32
+  SetEnvironmentVariableA("LLVM_DISABLE_CRASH_REPORT", "1");
+  SetEnvironmentVariableA("LLVM_DISABLE_SYMBOLIZATION", "1");
+#else
+  setenv("LLVM_DISABLE_CRASH_REPORT", "1", /*overwrite=*/1);
+  setenv("LLVM_DISABLE_SYMBOLIZATION", "1", /*overwrite=*/1);
+#endif
+}
+
+static std::pair<StringRef, bool> determineOutputType(bool IsMIR,
+                                                      bool InputIsBitcode) {
+  bool OutputBitcode = ForceOutputBitcode || InputIsBitcode;
+
+  if (ReplaceInput) { // In-place
     OutputFilename = InputFilename.c_str();
-  else if (OutputFilename.empty() || OutputFilename == "-")
-    OutputFilename = M.isMIR() ? "reduced.mir" : "reduced.ll";
-  std::error_code EC;
-  raw_fd_ostream Out(OutputFilename, EC);
-  if (EC) {
-    errs() << "Error opening output file: " << EC.message() << "!\n";
-    exit(1);
-  }
-  M.print(Out, /*AnnotationWriter=*/nullptr);
-  errs() << Message << OutputFilename << "\n";
-}
+  } else if (OutputFilename.empty()) {
+    // Default to producing bitcode if the input was bitcode, if not explicitly
+    // requested.
 
-void writeBitcode(ReducerWorkItem &M, llvm::raw_ostream &OutStream) {
-  if (M.LTOInfo && M.LTOInfo->IsThinLTO && M.LTOInfo->EnableSplitLTOUnit) {
-    legacy::PassManager PM;
-    PM.add(llvm::createWriteThinLTOBitcodePass(OutStream));
-    PM.run(*(M.M));
-  } else {
-    std::unique_ptr<ModuleSummaryIndex> Index;
-    if (M.LTOInfo && M.LTOInfo->HasSummary) {
-      ProfileSummaryInfo PSI(M);
-      Index = std::make_unique<ModuleSummaryIndex>(
-          buildModuleSummaryIndex(M, nullptr, &PSI));
-    }
-    WriteBitcodeToFile(M, OutStream, Index.get());
+    OutputFilename =
+        IsMIR ? "reduced.mir" : (OutputBitcode ? "reduced.bc" : "reduced.ll");
   }
-}
 
-void readBitcode(ReducerWorkItem &M, MemoryBufferRef Data, LLVMContext &Ctx, const char *ToolName) {
-  Expected<BitcodeFileContents> IF = llvm::getBitcodeFileContents(Data);
-  if (!IF) {
-    WithColor::error(errs(), ToolName) << IF.takeError();
-    exit(1);
-  }
-  BitcodeModule BM = IF->Mods[0];
-  Expected<BitcodeLTOInfo> LI = BM.getLTOInfo();
-  Expected<std::unique_ptr<Module>> MOrErr = BM.parseModule(Ctx);
-  if (!LI || !MOrErr) {
-    WithColor::error(errs(), ToolName) << IF.takeError();
-    exit(1);
-  }
-  M.LTOInfo = std::make_unique<BitcodeLTOInfo>(*LI);
-  M.M = std::move(MOrErr.get());
+  return {OutputFilename, OutputBitcode};
 }
 
 int main(int Argc, char **Argv) {
   InitLLVM X(Argc, Argv);
+  const StringRef ToolName(Argv[0]);
 
   cl::HideUnrelatedOptions({&LLVMReduceOptions, &getColorCategory()});
   cl::ParseCommandLineOptions(Argc, Argv, "LLVM automatic testcase reducer.\n");
 
+  if (Argc == 1) {
+    cl::PrintHelpMessage();
+    return 0;
+  }
+
+  if (PrintDeltaPasses) {
+    printDeltaPasses(outs());
+    return 0;
+  }
+
   bool ReduceModeMIR = false;
   if (InputLanguage != InputLanguages::None) {
     if (InputLanguage == InputLanguages::MIR)
@@ -162,23 +162,47 @@
     ReduceModeMIR = true;
   }
 
-  if (PrintDeltaPasses) {
-    printDeltaPasses(errs());
-    return 0;
+  if (InputFilename.empty()) {
+    WithColor::error(errs(), ToolName)
+        << "reduction testcase positional argument must be specified\n";
+    return 1;
   }
 
+  if (TestFilename.empty()) {
+    WithColor::error(errs(), ToolName) << "--test option must be specified\n";
+    return 1;
+  }
+
+  if (!PreserveDebugEnvironment)
+    disableEnvironmentDebugFeatures();
+
   LLVMContext Context;
   std::unique_ptr<TargetMachine> TM;
 
-  std::unique_ptr<ReducerWorkItem> OriginalProgram =
-      parseReducerWorkItem(Argv[0], InputFilename, Context, TM, ReduceModeMIR);
+  auto [OriginalProgram, InputIsBitcode] =
+      parseReducerWorkItem(ToolName, InputFilename, Context, TM, ReduceModeMIR);
   if (!OriginalProgram) {
     return 1;
   }
 
+  StringRef OutputFilename;
+  bool OutputBitcode;
+  std::tie(OutputFilename, OutputBitcode) =
+      determineOutputType(ReduceModeMIR, InputIsBitcode);
+
   // Initialize test environment
   TestRunner Tester(TestFilename, TestArguments, std::move(OriginalProgram),
-                    std::move(TM), Argv[0]);
+                    std::move(TM), ToolName, OutputFilename, InputIsBitcode,
+                    OutputBitcode);
+
+  // This parses and writes out the testcase into a temporary file copy for the
+  // test, rather than evaluating the source IR directly. This is for the
+  // convenience of lit tests; the stripped out comments may have broken the
+  // interestingness checks.
+  if (!Tester.getProgram().isReduced(Tester)) {
+    errs() << "\nInput isn't interesting! Verify interesting-ness test\n";
+    return 1;
+  }
 
   // Try to reduce code
   runDeltaPasses(Tester, MaxPassIterations);
@@ -187,7 +211,7 @@
   if (OutputFilename == "-")
     Tester.getProgram().print(outs(), nullptr);
   else
-    writeOutput(Tester.getProgram(), "\nDone reducing! Reduced testcase: ");
+    Tester.writeOutput("Done reducing! Reduced testcase: ");
 
   return 0;
 }
diff --git a/src/llvm-project/llvm/tools/llvm-remark-size-diff/RemarkSizeDiff.cpp b/src/llvm-project/llvm/tools/llvm-remark-size-diff/RemarkSizeDiff.cpp
index ab59820..d97589e 100644
--- a/src/llvm-project/llvm/tools/llvm-remark-size-diff/RemarkSizeDiff.cpp
+++ b/src/llvm-project/llvm/tools/llvm-remark-size-diff/RemarkSizeDiff.cpp
@@ -15,7 +15,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm-c/Remarks.h"
-#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/Remarks/Remark.h"
@@ -404,13 +403,13 @@
     InstCountA = InstCountB = StackSizeA = StackSizeB = 0;
     switch (WhichFiles) {
     case BOTH:
-      LLVM_FALLTHROUGH;
+      [[fallthrough]];
     case A:
       InstCountA = Diff.getInstCountA();
       StackSizeA = Diff.getStackSizeA();
       if (WhichFiles != BOTH)
         break;
-      LLVM_FALLTHROUGH;
+      [[fallthrough]];
     case B:
       InstCountB = Diff.getInstCountB();
       StackSizeB = Diff.getStackSizeB();
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-remarkutil/CMakeLists.txt
new file mode 100644
index 0000000..2def6b8
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/CMakeLists.txt
@@ -0,0 +1,5 @@
+set(LLVM_LINK_COMPONENTS Core Demangle Object Remarks Support)
+
+add_llvm_tool(llvm-remarkutil
+  RemarkUtil.cpp
+)
diff --git a/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp
new file mode 100644
index 0000000..0412eae
--- /dev/null
+++ b/src/llvm-project/llvm/tools/llvm-remarkutil/RemarkUtil.cpp
@@ -0,0 +1,278 @@
+//===--------- 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.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+/// 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 "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;
+
+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)");
+} // 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));
+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 {
+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(subopts::InstructionCount));
+INPUT_OUTPUT_COMMAND_LINE_OPTIONS(subopts::InstructionCount)
+} // namespace instructioncount
+
+/// \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);
+}
+
+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.
+  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;
+    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?");
+    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
+
+/// 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();
+  return make_error<StringError>(
+      "Please specify a subcommand. (See -help for options)",
+      inconvertibleErrorCode());
+}
+
+int main(int argc, const 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());
+}
diff --git a/src/llvm-project/llvm/tools/llvm-rtdyld/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-rtdyld/CMakeLists.txt
index e173863..c7764ee 100644
--- a/src/llvm-project/llvm/tools/llvm-rtdyld/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-rtdyld/CMakeLists.txt
@@ -8,6 +8,7 @@
   Object
   RuntimeDyld
   Support
+  TargetParser
   )
 
 add_llvm_tool(llvm-rtdyld
diff --git a/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt
index 8e2b78f..90e2904 100644
--- a/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-shlib/CMakeLists.txt
@@ -39,6 +39,7 @@
      OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "OpenBSD")
      OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "Fuchsia")
      OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "DragonFly")
+     OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "Android")
      OR ("${CMAKE_SYSTEM_NAME}" STREQUAL "SunOS")) # FIXME: It should be "GNU ld for elf"
     configure_file(
     ${CMAKE_CURRENT_SOURCE_DIR}/simple_version_script.map.in
@@ -63,6 +64,10 @@
 
   target_link_libraries(LLVM PRIVATE ${LIB_NAMES})
 
+  if(LLVM_ENABLE_THREADS AND NOT HAVE_CXX_ATOMICS64_WITHOUT_LIB)
+    target_link_libraries(LLVM PUBLIC atomic)
+  endif()
+
   if (APPLE)
     set_property(TARGET LLVM APPEND_STRING PROPERTY
                 LINK_FLAGS
@@ -88,7 +93,7 @@
 
   set(LLVM_EXPORTED_SYMBOL_FILE ${LLVM_BINARY_DIR}/libllvm-c.exports)
 
-  set(LIB_DIR ${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib${LLVM_LIBDIR_SUFFIX})
+  set(LIB_DIR ${LLVM_LIBRARY_DIR})
   set(LIB_NAME ${LIB_DIR}/${CMAKE_SHARED_LIBRARY_PREFIX}LLVM)
   set(LIB_PATH ${LIB_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX})
   set(LIB_EXPORTS_PATH ${LIB_NAME}.exports)
@@ -136,7 +141,7 @@
 
   # Get the full name to the libs so the python script understands them.
   foreach(lib ${LIB_NAMES})
-    list(APPEND FULL_LIB_NAMES ${LLVM_BINARY_DIR}/${CMAKE_CFG_INTDIR}/lib/${lib}.lib)
+    list(APPEND FULL_LIB_NAMES ${LLVM_LIBRARY_DIR}/${lib}.lib)
   endforeach()
 
   # Need to separate lib names with newlines.
diff --git a/src/llvm-project/llvm/tools/llvm-sim/llvm-sim.cpp b/src/llvm-project/llvm/tools/llvm-sim/llvm-sim.cpp
index 2b717d7..d09e515 100644
--- a/src/llvm-project/llvm/tools/llvm-sim/llvm-sim.cpp
+++ b/src/llvm-project/llvm/tools/llvm-sim/llvm-sim.cpp
@@ -41,13 +41,13 @@
 /// \param LLVMInstNum - The mapping of Instructions to their location in the
 /// module represented by an unsigned integer.
 /// \returns The instruction number for \p I if it exists.
-Optional<unsigned>
+std::optional<unsigned>
 getPositionInModule(const Instruction *I,
                     const DenseMap<Instruction *, unsigned> &LLVMInstNum) {
   assert(I && "Instruction is nullptr!");
   DenseMap<Instruction *, unsigned>::const_iterator It = LLVMInstNum.find(I);
   if (It == LLVMInstNum.end())
-    return None;
+    return std::nullopt;
   return It->second;
 }
 
@@ -80,9 +80,9 @@
     // For each file there is a list of the range where the similarity
     // exists.
     for (const IRSimilarityCandidate &C : G) {
-      Optional<unsigned> Start =
+      std::optional<unsigned> Start =
           getPositionInModule((*C.front()).Inst, LLVMInstNum);
-      Optional<unsigned> End =
+      std::optional<unsigned> End =
           getPositionInModule((*C.back()).Inst, LLVMInstNum);
 
       assert(Start &&
@@ -90,8 +90,8 @@
       assert(End && "Could not find instruction number for last instruction");
 
       J.object([&] {
-        J.attribute("start", Start.value());
-        J.attribute("end", End.value());
+        J.attribute("start", *Start);
+        J.attribute("end", *End);
       });
     }
     J.arrayEnd();
diff --git a/src/llvm-project/llvm/tools/llvm-size/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-size/CMakeLists.txt
index 0d1f660..a837ba6 100644
--- a/src/llvm-project/llvm/tools/llvm-size/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-size/CMakeLists.txt
@@ -2,6 +2,7 @@
   Object
   Option
   Support
+  TargetParser
   )
 
 set(LLVM_TARGET_DEFINITIONS Opts.td)
@@ -12,6 +13,7 @@
   llvm-size.cpp
   DEPENDS
   SizeOptsTableGen
+  GENERATE_DRIVER
   )
 
 if(LLVM_INSTALL_BINUTILS_SYMLINKS)
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 1c7484b..32dbf3d 100644
--- a/src/llvm-project/llvm/tools/llvm-size/llvm-size.cpp
+++ b/src/llvm-project/llvm/tools/llvm-size/llvm-size.cpp
@@ -47,11 +47,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#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
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -63,9 +66,9 @@
 #undef OPTION
 };
 
-class SizeOptTable : public opt::OptTable {
+class SizeOptTable : public opt::GenericOptTable {
 public:
-  SizeOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  SizeOptTable() : GenericOptTable(InfoTable) { setGroupedShortOptions(true); }
 };
 
 enum OutputFormatTy { berkeley, sysv, darwin };
@@ -570,6 +573,8 @@
         else if (MachO && OutputFormat == darwin)
           outs() << a->getFileName() << "(" << o->getFileName() << "):\n";
         printObjectSectionSizes(o);
+        if (!MachO && OutputFormat == darwin)
+          outs() << o->getFileName() << " (ex " << a->getFileName() << ")\n";
         if (OutputFormat == berkeley) {
           if (MachO)
             outs() << a->getFileName() << "(" << o->getFileName() << ")\n";
@@ -836,6 +841,8 @@
     else if (MachO && OutputFormat == darwin && MoreThanOneFile)
       outs() << o->getFileName() << ":\n";
     printObjectSectionSizes(o);
+    if (!MachO && OutputFormat == darwin)
+      outs() << o->getFileName() << "\n";
     if (OutputFormat == berkeley) {
       if (!MachO || MoreThanOneFile)
         outs() << o->getFileName();
@@ -862,7 +869,7 @@
          << "(TOTALS)\n";
 }
 
-int main(int argc, char **argv) {
+int llvm_size_main(int argc, char **argv) {
   InitLLVM X(argc, argv);
   BumpPtrAllocator A;
   StringSaver Saver(A);
@@ -937,4 +944,5 @@
 
   if (HadError)
     return 1;
+  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 e15d1d6..639506c 100644
--- a/src/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
+++ b/src/llvm-project/llvm/tools/llvm-stress/llvm-stress.cpp
@@ -24,17 +24,14 @@
 #include "llvm/IR/DerivedTypes.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/GlobalValue.h"
-#include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/InstrTypes.h"
 #include "llvm/IR/Instruction.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/LLVMContext.h"
-#include "llvm/IR/LegacyPassManager.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/Type.h"
 #include "llvm/IR/Value.h"
 #include "llvm/IR/Verifier.h"
-#include "llvm/Pass.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -74,6 +71,12 @@
     cl::desc("Additional IR scalar types "
              "(always includes i1, i8, i16, i32, i64, float and double)"));
 
+static cl::opt<bool> EnableScalableVectors(
+    "enable-scalable-vectors",
+    cl::desc("Generate IR involving scalable vector types"),
+    cl::init(false), cl::cat(StressCategory));
+
+
 namespace {
 
 /// A utility class to provide a pseudo-random number generator which is
@@ -242,9 +245,7 @@
       if (getRandom() & 1)
         return ConstantFP::getAllOnesValue(Tp);
       return ConstantFP::getNullValue(Tp);
-    } else if (Tp->isVectorTy()) {
-      auto *VTp = cast<FixedVectorType>(Tp);
-
+    } else if (auto *VTp = dyn_cast<FixedVectorType>(Tp)) {
       std::vector<Constant*> TempValues;
       TempValues.reserve(VTp->getNumElements());
       for (unsigned i = 0; i < VTp->getNumElements(); ++i)
@@ -291,21 +292,26 @@
   }
 
   /// Pick a random vector type.
-  Type *pickVectorType(unsigned len = (unsigned)-1) {
-    // Pick a random vector width in the range 2**0 to 2**4.
-    // by adding two randoms we are generating a normal-like distribution
-    // around 2**3.
-    unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3));
-    Type *Ty;
+  Type *pickVectorType(VectorType *VTy = nullptr) {
 
     // Vectors of x86mmx are illegal; keep trying till we get something else.
+    Type *Ty;
     do {
       Ty = pickScalarType();
     } while (Ty->isX86_MMXTy());
 
-    if (len != (unsigned)-1)
-      width = len;
-    return FixedVectorType::get(Ty, width);
+    if (VTy)
+      return VectorType::get(Ty, VTy->getElementCount());
+
+    // Select either fixed length or scalable vectors with 50% probability
+    // (only if scalable vectors are enabled)
+    bool Scalable = EnableScalableVectors && getRandom() & 1;
+
+    // Pick a random vector width in the range 2**0 to 2**4.
+    // by adding two randoms we are generating a normal-like distribution
+    // around 2**3.
+    unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3));
+    return VectorType::get(Ty, width, Scalable);
   }
 
   /// Pick a random scalar type.
@@ -432,7 +438,7 @@
       for (unsigned i = 0; i < 2; ++i)
         RandomBits[i] = Ran->Rand64();
 
-      APInt RandomInt(Ty->getPrimitiveSizeInBits(), makeArrayRef(RandomBits));
+      APInt RandomInt(Ty->getPrimitiveSizeInBits(), ArrayRef(RandomBits));
       APFloat RandomFloat(Ty->getFltSemantics(), RandomInt);
 
       if (getRandom() & 1)
@@ -479,10 +485,7 @@
     Value *Val0 = getRandomVectorValue();
     Value *V = ExtractElementInst::Create(
         Val0,
-        ConstantInt::get(
-            Type::getInt32Ty(BB->getContext()),
-            getRandom() %
-                cast<FixedVectorType>(Val0->getType())->getNumElements()),
+        getRandomValue(Type::getInt32Ty(BB->getContext())),
         "E", BB->getTerminator());
     return PT->push_back(V);
   }
@@ -496,6 +499,10 @@
     Value *Val0 = getRandomVectorValue();
     Value *Val1 = getRandomValue(Val0->getType());
 
+    // Can't express arbitrary shufflevectors for scalable vectors
+    if (isa<ScalableVectorType>(Val0->getType()))
+      return;
+
     unsigned Width = cast<FixedVectorType>(Val0->getType())->getNumElements();
     std::vector<Constant*> Idxs;
 
@@ -526,10 +533,7 @@
 
     Value *V = InsertElementInst::Create(
         Val0, Val1,
-        ConstantInt::get(
-            Type::getInt32Ty(BB->getContext()),
-            getRandom() %
-                cast<FixedVectorType>(Val0->getType())->getNumElements()),
+        getRandomValue(Type::getInt32Ty(BB->getContext())),
         "I", BB->getTerminator());
     return PT->push_back(V);
   }
@@ -545,10 +549,8 @@
     Type *DestTy = pickScalarType();
 
     // Handle vector casts vectors.
-    if (VTy->isVectorTy()) {
-      auto *VecTy = cast<FixedVectorType>(VTy);
-      DestTy = pickVectorType(VecTy->getNumElements());
-    }
+    if (VTy->isVectorTy())
+      DestTy = pickVectorType(cast<VectorType>(VTy));
 
     // no need to cast.
     if (VTy == DestTy) return;
@@ -628,11 +630,9 @@
 
     // If the value type is a vector, and we allow vector select, then in 50%
     // of the cases generate a vector select.
-    if (isa<FixedVectorType>(Val0->getType()) && (getRandom() & 1)) {
-      unsigned NumElem =
-          cast<FixedVectorType>(Val0->getType())->getNumElements();
-      CondTy = FixedVectorType::get(CondTy, NumElem);
-    }
+    if (auto *VTy = dyn_cast<VectorType>(Val0->getType()))
+      if (getRandom() & 1)
+        CondTy = VectorType::get(CondTy, VTy->getElementCount());
 
     Value *Cond = getRandomValue(CondTy);
     Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl", BB->getTerminator());
@@ -761,10 +761,13 @@
     return 1;
   }
 
-  legacy::PassManager Passes;
-  Passes.add(createVerifierPass());
-  Passes.add(createPrintModulePass(Out->os()));
-  Passes.run(*M.get());
+  // Check that the generated module is accepted by the verifier.
+  if (verifyModule(*M.get(), &Out->os()))
+    report_fatal_error("Broken module found, compilation aborted!");
+
+  // Output textual IR.
+  M->print(Out->os(), nullptr);
+
   Out->keep();
 
   return 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 71d1321e..f6d08a1 100644
--- a/src/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp
+++ b/src/llvm-project/llvm/tools/llvm-strings/llvm-strings.cpp
@@ -39,11 +39,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#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
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -55,9 +58,11 @@
 #undef OPTION
 };
 
-class StringsOptTable : public opt::OptTable {
+class StringsOptTable : public opt::GenericOptTable {
 public:
-  StringsOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); }
+  StringsOptTable() : GenericOptTable(InfoTable) {
+    setGroupedShortOptions(true);
+  }
 };
 } // namespace
 
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 34c93be..ed24e85 100644
--- a/src/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
+++ b/src/llvm-project/llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp
@@ -23,7 +23,7 @@
 #include "llvm/DebugInfo/Symbolize/MarkupFilter.h"
 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
 #include "llvm/DebugInfo/Symbolize/Symbolize.h"
-#include "llvm/Debuginfod/DIFetcher.h"
+#include "llvm/Debuginfod/BuildIDFetcher.h"
 #include "llvm/Debuginfod/Debuginfod.h"
 #include "llvm/Debuginfod/HTTPClient.h"
 #include "llvm/Option/Arg.h"
@@ -40,6 +40,7 @@
 #include <algorithm>
 #include <cstdio>
 #include <cstring>
+#include <iostream>
 #include <string>
 
 using namespace llvm;
@@ -55,11 +56,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#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
 
-const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -71,9 +75,9 @@
 #undef OPTION
 };
 
-class SymbolizerOptTable : public opt::OptTable {
+class SymbolizerOptTable : public opt::GenericOptTable {
 public:
-  SymbolizerOptTable() : OptTable(InfoTable) {
+  SymbolizerOptTable() : GenericOptTable(InfoTable) {
     setGroupedShortOptions(true);
   }
 };
@@ -108,30 +112,31 @@
   Frame,
 };
 
-static void enableDebuginfod(LLVMSymbolizer &Symbolizer) {
+static void enableDebuginfod(LLVMSymbolizer &Symbolizer,
+                             const opt::ArgList &Args) {
   static bool IsEnabled = false;
   if (IsEnabled)
     return;
   IsEnabled = true;
   // Look up symbols using the debuginfod client.
-  Symbolizer.addDIFetcher(std::make_unique<DebuginfodDIFetcher>());
+  Symbolizer.setBuildIDFetcher(std::make_unique<DebuginfodFetcher>(
+      Args.getAllArgValues(OPT_debug_file_directory_EQ)));
   // The HTTPClient must be initialized for use by the debuginfod client.
   HTTPClient::initialize();
 }
 
-static SmallVector<uint8_t> parseBuildID(StringRef Str) {
+static object::BuildID parseBuildID(StringRef Str) {
   std::string Bytes;
   if (!tryGetFromHex(Str, Bytes))
     return {};
   ArrayRef<uint8_t> BuildID(reinterpret_cast<const uint8_t *>(Bytes.data()),
                             Bytes.size());
-  return SmallVector<uint8_t>(BuildID.begin(), BuildID.end());
+  return object::BuildID(BuildID.begin(), BuildID.end());
 }
 
 static bool parseCommand(StringRef BinaryName, bool IsAddr2Line,
                          StringRef InputString, Command &Cmd,
-                         std::string &ModuleName,
-                         SmallVectorImpl<uint8_t> &BuildID,
+                         std::string &ModuleName, object::BuildID &BuildID,
                          uint64_t &ModuleOffset) {
   const char kDelimiters[] = " \n\r";
   ModuleName = "";
@@ -248,24 +253,24 @@
 }
 
 static void symbolizeInput(const opt::InputArgList &Args,
-                           ArrayRef<uint8_t> IncomingBuildID,
+                           object::BuildIDRef IncomingBuildID,
                            uint64_t AdjustVMA, bool IsAddr2Line,
                            OutputStyle Style, StringRef InputString,
                            LLVMSymbolizer &Symbolizer, DIPrinter &Printer) {
   Command Cmd;
   std::string ModuleName;
-  SmallVector<uint8_t> BuildID(IncomingBuildID.begin(), IncomingBuildID.end());
+  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, None}, InputString);
+    Printer.printInvalidCommand({ModuleName, std::nullopt}, InputString);
     return;
   }
   bool ShouldInline = Args.hasFlag(OPT_inlines, OPT_no_inlines, !IsAddr2Line);
   if (!BuildID.empty()) {
     assert(ModuleName.empty());
     if (!Args.hasArg(OPT_no_debuginfod))
-      enableDebuginfod(Symbolizer);
+      enableDebuginfod(Symbolizer, Args);
     std::string BuildIDStr = toHex(BuildID);
     executeCommand(BuildIDStr, BuildID, Cmd, Offset, AdjustVMA, ShouldInline,
                    Style, Symbolizer, Printer);
@@ -339,25 +344,24 @@
   return IsAddr2Line ? FunctionNameKind::None : FunctionNameKind::LinkageName;
 }
 
-static Optional<bool> parseColorArg(const opt::InputArgList &Args) {
+static std::optional<bool> parseColorArg(const opt::InputArgList &Args) {
   if (Args.hasArg(OPT_color))
     return true;
   if (const opt::Arg *A = Args.getLastArg(OPT_color_EQ))
-    return StringSwitch<Optional<bool>>(A->getValue())
+    return StringSwitch<std::optional<bool>>(A->getValue())
         .Case("always", true)
         .Case("never", false)
-        .Case("auto", None);
-  return None;
+        .Case("auto", std::nullopt);
+  return std::nullopt;
 }
 
-static SmallVector<uint8_t> parseBuildIDArg(const opt::InputArgList &Args,
-                                            int ID) {
+static object::BuildID parseBuildIDArg(const opt::InputArgList &Args, int ID) {
   const opt::Arg *A = Args.getLastArg(ID);
   if (!A)
     return {};
 
   StringRef V(A->getValue());
-  SmallVector<uint8_t> BuildID = parseBuildID(V);
+  object::BuildID BuildID = parseBuildID(V);
   if (BuildID.empty()) {
     errs() << A->getSpelling() + ": expected a build ID, but got '" + V + "'\n";
     exit(1);
@@ -439,14 +443,8 @@
 
   LLVMSymbolizer Symbolizer(Opts);
 
-  // A debuginfod lookup could succeed if a HTTP client is available and at
-  // least one backing URL is configured.
-  bool ShouldUseDebuginfodByDefault =
-      HTTPClient::isAvailable() &&
-      !ExitOnErr(getDefaultDebuginfodUrls()).empty();
-  if (Args.hasFlag(OPT_debuginfod, OPT_no_debuginfod,
-                   ShouldUseDebuginfodByDefault))
-    enableDebuginfod(Symbolizer);
+  if (Args.hasFlag(OPT_debuginfod, OPT_no_debuginfod, canUseDebuginfod()))
+    enableDebuginfod(Symbolizer, Args);
 
   if (Args.hasArg(OPT_filter_markup)) {
     filterMarkup(Args, Symbolizer);
@@ -467,7 +465,7 @@
     errs() << "error: cannot specify both --build-id and --obj\n";
     return EXIT_FAILURE;
   }
-  SmallVector<uint8_t> BuildID = parseBuildIDArg(Args, OPT_build_id_EQ);
+  object::BuildID BuildID = parseBuildIDArg(Args, OPT_build_id_EQ);
 
   std::unique_ptr<DIPrinter> Printer;
   if (Style == OutputStyle::GNU)
diff --git a/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp b/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp
index 45a1f78..9ebaadb 100644
--- a/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp
+++ b/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.cpp
@@ -235,12 +235,11 @@
   Result.Kind = AD_Str_Vec;
   for (const auto &IRef : CollectedIRefVec)
     for (auto Targ : IRef.targets()) {
-      auto FoundIRef = llvm::find_if(LookupIRefVec, [&](const auto LIRef) {
-        auto FoundTarg = llvm::find(LIRef.targets(), Targ);
-        return (FoundTarg != LIRef.targets().end() &&
-                IRef.getInstallName() == LIRef.getInstallName());
+      auto FoundIRef = llvm::any_of(LookupIRefVec, [&](const auto LIRef) {
+        return llvm::is_contained(LIRef.targets(), Targ) &&
+               IRef.getInstallName() == LIRef.getInstallName();
       });
-      if (FoundIRef == LookupIRefVec.end())
+      if (!FoundIRef)
         addDiffForTargSlice<DiffStrVec,
                             DiffScalarVal<StringRef, AD_Diff_Scalar_Str>>(
             IRef.getInstallName(), Targ, Result, Order);
@@ -267,14 +266,13 @@
   Result.Kind = AD_Sym_Vec;
   for (const auto *Sym : CollectedSyms)
     for (const auto Targ : Sym->targets()) {
-      auto FoundSym = llvm::find_if(LookupSyms, [&](const auto LSym) {
-        auto FoundTarg = llvm::find(LSym->targets(), Targ);
+      auto FoundSym = llvm::any_of(LookupSyms, [&](const auto LSym) {
         return (Sym->getName() == LSym->getName() &&
                 Sym->getKind() == LSym->getKind() &&
                 Sym->getFlags() == LSym->getFlags() &&
-                FoundTarg != LSym->targets().end());
+                llvm::is_contained(LSym->targets(), Targ));
       });
-      if (FoundSym == LookupSyms.end())
+      if (!FoundSym)
         addDiffForTargSlice<DiffSymVec, SymScalar>(Sym, Targ, Result, Order);
     }
 }
@@ -410,10 +408,10 @@
     }
     for (auto DocRHS : IFRHS->documents()) {
       auto WasGathered =
-          llvm::find_if(DocsInserted, [&](const auto &GatheredDoc) {
+          llvm::any_of(DocsInserted, [&](const auto &GatheredDoc) {
             return (GatheredDoc == DocRHS->getInstallName());
           });
-      if (WasGathered == DocsInserted.end())
+      if (!WasGathered)
         Docs.Values.push_back(std::make_unique<InlineDoc>(InlineDoc(
             DocRHS->getInstallName(), getSingleIF(DocRHS.get(), rhs))));
     }
diff --git a/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h b/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h
index 252fbd8..e486405 100644
--- a/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h
+++ b/src/llvm-project/llvm/tools/llvm-tapi-diff/DiffEngine.h
@@ -13,7 +13,6 @@
 #ifndef LLVM_TOOLS_LLVM_TAPI_DIFF_DIFFENGINE_H
 #define LLVM_TOOLS_LLVM_TAPI_DIFF_DIFFENGINE_H
 
-#include "llvm/ADT/Optional.h"
 #include "llvm/Object/TapiUniversal.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TextAPI/Symbol.h"
diff --git a/src/llvm-project/llvm/tools/llvm-tli-checker/CMakeLists.txt b/src/llvm-project/llvm/tools/llvm-tli-checker/CMakeLists.txt
index 9be44e4..384c09d 100644
--- a/src/llvm-project/llvm/tools/llvm-tli-checker/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/llvm-tli-checker/CMakeLists.txt
@@ -11,6 +11,7 @@
   Option
   Remarks
   Support
+  TargetParser
   TextAPI
   )
 
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 7deeaef..179c42b 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
@@ -35,11 +35,14 @@
 #undef OPTION
 };
 
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#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 const opt::OptTable::Info InfoTable[] = {
+static constexpr opt::OptTable::Info InfoTable[] = {
 #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,  \
                HELPTEXT, METAVAR, VALUES)                                      \
   {                                                                            \
@@ -51,9 +54,9 @@
 #undef OPTION
 };
 
-class TLICheckerOptTable : public opt::OptTable {
+class TLICheckerOptTable : public opt::GenericOptTable {
 public:
-  TLICheckerOptTable() : OptTable(InfoTable) {}
+  TLICheckerOptTable() : GenericOptTable(InfoTable) {}
 };
 } // end anonymous namespace
 
@@ -155,6 +158,7 @@
 // Store all the exported symbol names we found in the input libraries.
 // We use a map to get hashed lookup speed; the bool is meaningless.
 class SDKNameMap : public StringMap<bool> {
+  void maybeInsertSymbol(const SymbolRef &S, const ObjectFile &O);
   void populateFromObject(ObjectFile *O);
   void populateFromArchive(Archive *A);
 
@@ -163,6 +167,19 @@
 };
 static SDKNameMap SDKNames;
 
+// Insert defined global function symbols into the map if valid.
+void SDKNameMap::maybeInsertSymbol(const SymbolRef &S, const ObjectFile &O) {
+  SymbolRef::Type Type = unwrapIgnoreError(S.getType());
+  uint32_t Flags = unwrapIgnoreError(S.getFlags());
+  section_iterator Section = unwrapIgnoreError(S.getSection(),
+                                               /*Default=*/O.section_end());
+  if (Type == SymbolRef::ST_Function && (Flags & SymbolRef::SF_Global) &&
+      Section != O.section_end()) {
+    StringRef Name = unwrapIgnoreError(S.getName());
+    insert({ Name, true });
+  }
+}
+
 // Given an ObjectFile, extract the global function symbols.
 void SDKNameMap::populateFromObject(ObjectFile *O) {
   // FIXME: Support other formats.
@@ -173,16 +190,12 @@
   }
   const auto *ELF = cast<ELFObjectFileBase>(O);
 
-  for (auto &S : ELF->getDynamicSymbolIterators()) {
-    // We want only defined global function symbols.
-    SymbolRef::Type Type = unwrapIgnoreError(S.getType());
-    uint32_t Flags = unwrapIgnoreError(S.getFlags());
-    section_iterator Section = unwrapIgnoreError(S.getSection(),
-                                                 /*Default=*/O->section_end());
-    StringRef Name = unwrapIgnoreError(S.getName());
-    if (Type == SymbolRef::ST_Function && (Flags & SymbolRef::SF_Global) &&
-        Section != O->section_end())
-      insert({Name, true});
+  if (ELF->getEType() == ELF::ET_REL) {
+    for (const auto &S : ELF->symbols())
+      maybeInsertSymbol(S, *O);
+  } else {
+    for (const auto &S : ELF->getDynamicSymbolIterators())
+      maybeInsertSymbol(S, *O);
   }
 }
 
@@ -191,7 +204,7 @@
 void SDKNameMap::populateFromArchive(Archive *A) {
   Error Err = Error::success();
   int Index = -1;
-  for (auto &C : A->children(Err)) {
+  for (const auto &C : A->children(Err)) {
     ++Index;
     Expected<std::unique_ptr<object::Binary>> ChildOrErr = C.getAsBinary();
     if (!ChildOrErr) {
diff --git a/src/llvm-project/llvm/tools/llvm-xray/llvm-xray.cpp b/src/llvm-project/llvm/tools/llvm-xray/llvm-xray.cpp
index 9ee653e..2b1182c 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/llvm-xray.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/llvm-xray.cpp
@@ -31,7 +31,7 @@
     if (*SC) {
       // If no subcommand was provided, we need to explicitly check if this is
       // the top-level subcommand.
-      if (SC == &*cl::TopLevelSubCommand) {
+      if (SC == &cl::SubCommand::getTopLevel()) {
         cl::PrintHelpMessage(false, true);
         return 0;
       }
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-account.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-account.cpp
index 1117046..a9d9129 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-account.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-account.cpp
@@ -23,6 +23,8 @@
 #include "llvm/XRay/InstrumentationMap.h"
 #include "llvm/XRay/Trace.h"
 
+#include <cmath>
+
 using namespace llvm;
 using namespace llvm::xray;
 
@@ -201,10 +203,10 @@
 
     // Look for the parent up the stack.
     auto Parent =
-        std::find_if(ThreadStack.Stack.rbegin(), ThreadStack.Stack.rend(),
-                     [&](const std::pair<const int32_t, uint64_t> &E) {
-                       return E.first == Record.FuncId;
-                     });
+        llvm::find_if(llvm::reverse(ThreadStack.Stack),
+                      [&](const std::pair<const int32_t, uint64_t> &E) {
+                        return E.first == Record.FuncId;
+                      });
     if (Parent == ThreadStack.Stack.rend())
       return false;
 
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 371a9cc..38d3ec9 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-account.h
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-account.h
@@ -45,7 +45,7 @@
       RecursionStatus &operator--();
       bool isRecursive() const;
     };
-    Optional<llvm::DenseMap<int32_t, RecursionStatus>> RecursionDepth;
+    std::optional<llvm::DenseMap<int32_t, RecursionStatus>> RecursionDepth;
   };
   typedef llvm::DenseMap<uint32_t, FunctionStack> PerThreadFunctionStackMap;
 
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.cpp
index b2ed638..3dd5143 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-color-helper.cpp
@@ -111,7 +111,7 @@
 // Takes a double precision number, clips it between 0 and 1 and then converts
 // that to an integer between 0x00 and 0xFF with proxpper rounding.
 static uint8_t unitIntervalTo8BitChar(double B) {
-  double n = std::max(std::min(B, 1.0), 0.0);
+  double n = std::clamp(B, 0.0, 1.0);
   return static_cast<uint8_t>(255 * n + 0.5);
 }
 
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 bcadade..8ccfd30 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
@@ -264,7 +264,7 @@
   const auto &RightStat = EdgeAttr.CorrEdgePtr[1]->second.S;
 
   double RelDiff = statRelDiff(LeftStat, RightStat, T);
-  double CappedRelDiff = std::min(1.0, std::max(-1.0, RelDiff));
+  double CappedRelDiff = std::clamp(RelDiff, -1.0, 1.0);
 
   return H.getColorString(CappedRelDiff);
 }
@@ -285,7 +285,7 @@
   const auto &RightStat = VertexAttr.CorrVertexPtr[1]->second.S;
 
   double RelDiff = statRelDiff(LeftStat, RightStat, T);
-  double CappedRelDiff = std::min(1.0, std::max(-1.0, RelDiff));
+  double CappedRelDiff = std::clamp(RelDiff, -1.0, 1.0);
 
   return H.getColorString(CappedRelDiff);
 }
diff --git a/src/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp b/src/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp
index ff47eb6..b832805 100644
--- a/src/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp
+++ b/src/llvm-project/llvm/tools/llvm-xray/xray-graph.cpp
@@ -17,6 +17,8 @@
 #include "llvm/XRay/InstrumentationMap.h"
 #include "llvm/XRay/Trace.h"
 
+#include <cmath>
+
 using namespace llvm;
 using namespace llvm::xray;
 
diff --git a/src/llvm-project/llvm/tools/lto/lto.cpp b/src/llvm-project/llvm/tools/lto/lto.cpp
index ff5c2c6..22ebf54 100644
--- a/src/llvm-project/llvm/tools/lto/lto.cpp
+++ b/src/llvm-project/llvm/tools/lto/lto.cpp
@@ -290,6 +290,8 @@
       codegen::InitTargetOptionsFromCodeGenFlags(Triple());
   ErrorOr<std::unique_ptr<LTOModule>> M = LTOModule::createFromBuffer(
       unwrap(cg)->getContext(), mem, length, Options, StringRef(path));
+  if (!M)
+    return nullptr;
   return wrap(M->release());
 }
 
@@ -394,7 +396,7 @@
     unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
     return false;
   case LTO_CODEGEN_PIC_MODEL_DEFAULT:
-    unwrap(cg)->setCodePICModel(None);
+    unwrap(cg)->setCodePICModel(std::nullopt);
     return false;
   }
   sLastErrorString = "Unknown PIC model";
@@ -494,7 +496,7 @@
   SmallVector<StringRef, 4> Options;
   for (int i = 0; i < number; ++i)
     Options.push_back(options[i]);
-  unwrap(cg)->setCodeGenDebugOptions(makeArrayRef(Options));
+  unwrap(cg)->setCodeGenDebugOptions(ArrayRef(Options));
 }
 
 unsigned int lto_api_version() { return LTO_API_VERSION; }
@@ -526,20 +528,10 @@
     if (OptLevel < '0' || OptLevel > '3')
       report_fatal_error("Optimization level must be between 0 and 3");
     CodeGen->setOptLevel(OptLevel - '0');
-    switch (OptLevel) {
-    case '0':
-      CodeGen->setCodeGenOptLevel(CodeGenOpt::None);
-      break;
-    case '1':
-      CodeGen->setCodeGenOptLevel(CodeGenOpt::Less);
-      break;
-    case '2':
-      CodeGen->setCodeGenOptLevel(CodeGenOpt::Default);
-      break;
-    case '3':
-      CodeGen->setCodeGenOptLevel(CodeGenOpt::Aggressive);
-      break;
-    }
+    std::optional<CodeGenOpt::Level> CGOptLevelOrNone =
+        CodeGenOpt::getLevel(OptLevel - '0');
+    assert(CGOptLevelOrNone);
+    CodeGen->setCodeGenOptLevel(*CGOptLevelOrNone);
   }
   return wrap(CodeGen);
 }
@@ -671,7 +663,7 @@
     unwrap(cg)->setCodePICModel(Reloc::DynamicNoPIC);
     return false;
   case LTO_CODEGEN_PIC_MODEL_DEFAULT:
-    unwrap(cg)->setCodePICModel(None);
+    unwrap(cg)->setCodePICModel(std::nullopt);
     return false;
   }
   sLastErrorString = "Unknown PIC model";
diff --git a/src/llvm-project/llvm/tools/lto/lto.exports b/src/llvm-project/llvm/tools/lto/lto.exports
index 3abae5f..4164c39 100644
--- a/src/llvm-project/llvm/tools/lto/lto.exports
+++ b/src/llvm-project/llvm/tools/lto/lto.exports
@@ -45,12 +45,6 @@
 lto_codegen_set_should_internalize
 lto_codegen_set_should_embed_uselists
 lto_set_debug_options
-LLVMCreateDisasm
-LLVMCreateDisasmCPU
-LLVMDisasmDispose
-LLVMDisasmInstruction
-LLVMSetDisasmOptions
-LLVMCreateDisasmCPUFeatures
 thinlto_create_codegen
 thinlto_codegen_dispose
 thinlto_codegen_add_module
diff --git a/src/llvm-project/llvm/tools/obj2yaml/dwarf2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/dwarf2yaml.cpp
index 2426705..4c4ae3f 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/dwarf2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/dwarf2yaml.cpp
@@ -18,6 +18,7 @@
 #include "llvm/ObjectYAML/DWARFYAML.h"
 
 #include <algorithm>
+#include <optional>
 
 using namespace llvm;
 
@@ -165,7 +166,7 @@
   return ErrorSuccess();
 }
 
-static Optional<DWARFYAML::PubSection>
+static std::optional<DWARFYAML::PubSection>
 dumpPubSection(const DWARFContext &DCtx, const DWARFSection &Section,
                bool IsGNUStyle) {
   DWARFYAML::PubSection Y;
@@ -178,7 +179,7 @@
                 [](Error Err) { consumeError(std::move(Err)); });
   ArrayRef<DWARFDebugPubTable::Set> Sets = Table.getData();
   if (Sets.empty())
-    return None;
+    return std::nullopt;
 
   // FIXME: Currently, obj2yaml only supports dumping the first pubtable.
   Y.Format = Sets[0].Format;
@@ -247,15 +248,15 @@
           auto FormValue = DIEWrapper.find(AttrSpec.Attr);
           if (!FormValue)
             return;
-          auto Form = FormValue.value().getForm();
+          auto Form = FormValue->getForm();
           bool indirect = false;
           do {
             indirect = false;
             switch (Form) {
             case dwarf::DW_FORM_addr:
             case dwarf::DW_FORM_GNU_addr_index:
-              if (auto Val = FormValue.value().getAsAddress())
-                NewValue.Value = Val.value();
+              if (auto Val = FormValue->getAsAddress())
+                NewValue.Value = *Val;
               break;
             case dwarf::DW_FORM_ref_addr:
             case dwarf::DW_FORM_ref1:
@@ -264,16 +265,16 @@
             case dwarf::DW_FORM_ref8:
             case dwarf::DW_FORM_ref_udata:
             case dwarf::DW_FORM_ref_sig8:
-              if (auto Val = FormValue.value().getAsReferenceUVal())
-                NewValue.Value = Val.value();
+              if (auto Val = FormValue->getAsReferenceUVal())
+                NewValue.Value = *Val;
               break;
             case dwarf::DW_FORM_exprloc:
             case dwarf::DW_FORM_block:
             case dwarf::DW_FORM_block1:
             case dwarf::DW_FORM_block2:
             case dwarf::DW_FORM_block4:
-              if (auto Val = FormValue.value().getAsBlock()) {
-                auto BlockData = Val.value();
+              if (auto Val = FormValue->getAsBlock()) {
+                auto BlockData = *Val;
                 std::copy(BlockData.begin(), BlockData.end(),
                           std::back_inserter(NewValue.BlockData));
               }
@@ -288,8 +289,8 @@
             case dwarf::DW_FORM_udata:
             case dwarf::DW_FORM_ref_sup4:
             case dwarf::DW_FORM_ref_sup8:
-              if (auto Val = FormValue.value().getAsUnsignedConstant())
-                NewValue.Value = Val.value();
+              if (auto Val = FormValue->getAsUnsignedConstant())
+                NewValue.Value = *Val;
               break;
             case dwarf::DW_FORM_string:
               if (auto Val = dwarf::toString(FormValue))
@@ -297,10 +298,10 @@
               break;
             case dwarf::DW_FORM_indirect:
               indirect = true;
-              if (auto Val = FormValue.value().getAsUnsignedConstant()) {
-                NewValue.Value = Val.value();
+              if (auto Val = FormValue->getAsUnsignedConstant()) {
+                NewValue.Value = *Val;
                 NewEntry.Values.push_back(NewValue);
-                Form = static_cast<dwarf::Form>(Val.value());
+                Form = static_cast<dwarf::Form>(*Val);
               }
               break;
             case dwarf::DW_FORM_strp:
@@ -311,8 +312,8 @@
             case dwarf::DW_FORM_strp_sup:
             case dwarf::DW_FORM_GNU_str_index:
             case dwarf::DW_FORM_strx:
-              if (auto Val = FormValue.value().getAsCStringOffset())
-                NewValue.Value = Val.value();
+              if (auto Val = FormValue->getAsCStringOffset())
+                NewValue.Value = *Val;
               break;
             case dwarf::DW_FORM_flag_present:
               NewValue.Value = 1;
diff --git a/src/llvm-project/llvm/tools/obj2yaml/dxcontainer2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
index 122ae7d..462d87a 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/dxcontainer2yaml.cpp
@@ -38,23 +38,43 @@
   Obj->Header.PartOffsets = std::vector<uint32_t>();
   for (const auto P : Container) {
     Obj->Header.PartOffsets->push_back(P.Offset);
-    if (P.Part.getName() == "DXIL") {
-      Optional<DXContainer::DXILData> DXIL = Container.getDXIL();
+    Obj->Parts.push_back(
+        DXContainerYAML::Part(P.Part.getName().str(), P.Part.Size));
+    DXContainerYAML::Part &NewPart = Obj->Parts.back();
+    dxbc::PartType PT = dxbc::parsePartType(P.Part.getName());
+    switch (PT) {
+    case dxbc::PartType::DXIL: {
+      std::optional<DXContainer::DXILData> DXIL = Container.getDXIL();
       assert(DXIL && "Since we are iterating and found a DXIL part, "
                      "this should never not have a value");
-      Obj->Parts.push_back(DXContainerYAML::Part{
-          P.Part.getName().str(), P.Part.Size,
-          DXContainerYAML::DXILProgram{
-              DXIL->first.MajorVersion, DXIL->first.MinorVersion,
-              DXIL->first.ShaderKind, DXIL->first.Size,
-              DXIL->first.Bitcode.MajorVersion,
-              DXIL->first.Bitcode.MinorVersion, DXIL->first.Bitcode.Offset,
-              DXIL->first.Bitcode.Size,
-              std::vector<llvm::yaml::Hex8>(
-                  DXIL->second, DXIL->second + DXIL->first.Bitcode.Size)}});
-    } else {
-      Obj->Parts.push_back(
-          DXContainerYAML::Part{P.Part.getName().str(), P.Part.Size, None});
+      NewPart.Program = DXContainerYAML::DXILProgram{
+          DXIL->first.MajorVersion,
+          DXIL->first.MinorVersion,
+          DXIL->first.ShaderKind,
+          DXIL->first.Size,
+          DXIL->first.Bitcode.MajorVersion,
+          DXIL->first.Bitcode.MinorVersion,
+          DXIL->first.Bitcode.Offset,
+          DXIL->first.Bitcode.Size,
+          std::vector<llvm::yaml::Hex8>(
+              DXIL->second, DXIL->second + DXIL->first.Bitcode.Size)};
+      break;
+    }
+    case dxbc::PartType::SFI0: {
+      std::optional<uint64_t> Flags = Container.getShaderFlags();
+      // Omit the flags in the YAML if they are missing or zero.
+      if (Flags && *Flags > 0)
+        NewPart.Flags = DXContainerYAML::ShaderFlags(*Flags);
+      break;
+    }
+    case dxbc::PartType::HASH: {
+      std::optional<dxbc::ShaderHash> Hash = Container.getShaderHash();
+      if (Hash && Hash->isPopulated())
+        NewPart.Hash = DXContainerYAML::ShaderHash(*Hash);
+      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 8363700..9df483b 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/elf2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/elf2yaml.cpp
@@ -18,6 +18,7 @@
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/YAMLTraits.h"
+#include <optional>
 
 using namespace llvm;
 
@@ -32,7 +33,7 @@
 
   DenseMap<StringRef, uint32_t> UsedSectionNames;
   std::vector<std::string> SectionNames;
-  Optional<uint32_t> ShStrTabIndex;
+  std::optional<uint32_t> ShStrTabIndex;
 
   DenseMap<StringRef, uint32_t> UsedSymbolNames;
   std::vector<std::string> SymbolNames;
@@ -53,11 +54,11 @@
   Expected<std::vector<ELFYAML::ProgramHeader>>
   dumpProgramHeaders(ArrayRef<std::unique_ptr<ELFYAML::Chunk>> Sections);
 
-  Optional<DWARFYAML::Data>
+  std::optional<DWARFYAML::Data>
   dumpDWARFSections(std::vector<std::unique_ptr<ELFYAML::Chunk>> &Sections);
 
   Error dumpSymbols(const Elf_Shdr *Symtab,
-                    Optional<std::vector<ELFYAML::Symbol>> &Symbols);
+                    std::optional<std::vector<ELFYAML::Symbol>> &Symbols);
   Error dumpSymbol(const Elf_Sym *Sym, const Elf_Shdr *SymTab,
                    StringRef StrTable, ELFYAML::Symbol &S);
   Expected<std::vector<std::unique_ptr<ELFYAML::Chunk>>> dumpSections();
@@ -101,7 +102,7 @@
   dumpPlaceholderSection(const Elf_Shdr *Shdr);
 
   bool shouldPrintSection(const ELFYAML::Section &S, const Elf_Shdr &SHdr,
-                          Optional<DWARFYAML::Data> DWARF);
+                          std::optional<DWARFYAML::Data> DWARF);
 
 public:
   ELFDumper(const object::ELFFile<ELFT> &O, std::unique_ptr<DWARFContext> DCtx);
@@ -182,7 +183,7 @@
 template <class ELFT>
 bool ELFDumper<ELFT>::shouldPrintSection(const ELFYAML::Section &S,
                                          const Elf_Shdr &SHdr,
-                                         Optional<DWARFYAML::Data> DWARF) {
+                                         std::optional<DWARFYAML::Data> DWARF) {
   // We only print the SHT_NULL section at index 0 when it
   // has at least one non-null field, because yaml2obj
   // normally creates the zero section at index 0 implicitly.
@@ -246,8 +247,7 @@
   else
     ExpectedOffset = sizeof(typename ELFT::Ehdr);
 
-  for (const std::unique_ptr<ELFYAML::Chunk> &C :
-       makeArrayRef(V).drop_front()) {
+  for (const std::unique_ptr<ELFYAML::Chunk> &C : ArrayRef(V).drop_front()) {
     ELFYAML::Section &Sec = *cast<ELFYAML::Section>(C.get());
     const typename ELFT::Shdr &SecHdr = S[Sec.OriginalSecNdx];
 
@@ -359,7 +359,7 @@
   std::vector<ELFYAML::Section *> OriginalOrder;
   if (!Chunks.empty())
     for (const std::unique_ptr<ELFYAML::Chunk> &C :
-         makeArrayRef(Chunks).drop_front())
+         ArrayRef(Chunks).drop_front())
       OriginalOrder.push_back(cast<ELFYAML::Section>(C.get()));
 
   // Sometimes the order of sections in the section header table does not match
@@ -401,10 +401,10 @@
   }
 
   llvm::erase_if(Chunks, [this, &Y](const std::unique_ptr<ELFYAML::Chunk> &C) {
-    if (isa<ELFYAML::SectionHeaderTable>(*C.get()))
+    if (isa<ELFYAML::SectionHeaderTable>(*C))
       return false;
 
-    const ELFYAML::Section &S = cast<ELFYAML::Section>(*C.get());
+    const ELFYAML::Section &S = cast<ELFYAML::Section>(*C);
     return !shouldPrintSection(S, Sections[S.OriginalSecNdx], Y->DWARF);
   });
 
@@ -494,7 +494,7 @@
     // It is not possible to have a non-Section chunk, because
     // obj2yaml does not create Fill chunks.
     for (const std::unique_ptr<ELFYAML::Chunk> &C : Chunks) {
-      ELFYAML::Section &S = cast<ELFYAML::Section>(*C.get());
+      ELFYAML::Section &S = cast<ELFYAML::Section>(*C);
       if (isInSegment<ELFT>(S, Sections[S.OriginalSecNdx], Phdr)) {
         if (!PH.FirstSec)
           PH.FirstSec = S.Name;
@@ -510,7 +510,7 @@
 }
 
 template <class ELFT>
-Optional<DWARFYAML::Data> ELFDumper<ELFT>::dumpDWARFSections(
+std::optional<DWARFYAML::Data> ELFDumper<ELFT>::dumpDWARFSections(
     std::vector<std::unique_ptr<ELFYAML::Chunk>> &Sections) {
   DWARFYAML::Data DWARF;
   for (std::unique_ptr<ELFYAML::Chunk> &C : Sections) {
@@ -529,13 +529,13 @@
       cantFail(std::move(Err));
 
       if (RawSec->Name == ".debug_aranges")
-        Err = dumpDebugARanges(*DWARFCtx.get(), DWARF);
+        Err = dumpDebugARanges(*DWARFCtx, DWARF);
       else if (RawSec->Name == ".debug_str")
-        Err = dumpDebugStrings(*DWARFCtx.get(), DWARF);
+        Err = dumpDebugStrings(*DWARFCtx, DWARF);
       else if (RawSec->Name == ".debug_ranges")
-        Err = dumpDebugRanges(*DWARFCtx.get(), DWARF);
+        Err = dumpDebugRanges(*DWARFCtx, DWARF);
       else if (RawSec->Name == ".debug_addr")
-        Err = dumpDebugAddr(*DWARFCtx.get(), DWARF);
+        Err = dumpDebugAddr(*DWARFCtx, DWARF);
       else
         continue;
 
@@ -549,7 +549,7 @@
   }
 
   if (DWARF.getNonEmptySectionNames().empty())
-    return None;
+    return std::nullopt;
   return DWARF;
 }
 
@@ -673,7 +673,8 @@
 
 template <class ELFT>
 Error ELFDumper<ELFT>::dumpSymbols(
-    const Elf_Shdr *Symtab, Optional<std::vector<ELFYAML::Symbol>> &Symbols) {
+    const Elf_Shdr *Symtab,
+    std::optional<std::vector<ELFYAML::Symbol>> &Symbols) {
   if (!Symtab)
     return Error::success();
 
@@ -895,7 +896,7 @@
   while (Cur && Cur.tell() < Content.size()) {
     if (Shdr->sh_type == ELF::SHT_LLVM_BB_ADDR_MAP) {
       Version = Data.getU8(Cur);
-      if (Cur && Version > 1)
+      if (Cur && Version > 2)
         return createStringError(
             errc::invalid_argument,
             "invalid SHT_LLVM_BB_ADDR_MAP section version: " +
@@ -906,11 +907,12 @@
     uint64_t NumBlocks = Data.getULEB128(Cur);
     std::vector<ELFYAML::BBAddrMapEntry::BBEntry> BBEntries;
     // Read the specified number of BB entries, or until decoding fails.
-    for (uint64_t BlockID = 0; Cur && BlockID < NumBlocks; ++BlockID) {
+    for (uint64_t BlockIndex = 0; Cur && BlockIndex < NumBlocks; ++BlockIndex) {
+      uint32_t ID = Version >= 2 ? Data.getULEB128(Cur) : BlockIndex;
       uint64_t Offset = Data.getULEB128(Cur);
       uint64_t Size = Data.getULEB128(Cur);
       uint64_t Metadata = Data.getULEB128(Cur);
-      BBEntries.push_back({Offset, Size, Metadata});
+      BBEntries.push_back({ID, Offset, Size, Metadata});
     }
     Entries.push_back(
         {Version, Feature, Address, /*NumBlocks=*/{}, std::move(BBEntries)});
diff --git a/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp b/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp
index 6b121a74..c96b6cc 100644
--- a/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp
+++ b/src/llvm-project/llvm/tools/obj2yaml/macho2yaml.cpp
@@ -41,6 +41,8 @@
   void dumpExportTrie(std::unique_ptr<MachOYAML::Object> &Y);
   void dumpSymbols(std::unique_ptr<MachOYAML::Object> &Y);
   void dumpIndirectSymbols(std::unique_ptr<MachOYAML::Object> &Y);
+  void dumpChainedFixups(std::unique_ptr<MachOYAML::Object> &Y);
+  void dumpDataInCode(std::unique_ptr<MachOYAML::Object> &Y);
 
   template <typename SectionType>
   Expected<MachOYAML::Section> constructSectionCommon(SectionType Sec,
@@ -190,7 +192,7 @@
       if (SecName.startswith("__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.get(), Y.DWARF))
+        if (Error Err = dumpDebugSection(SecName, *DWARFCtx, Y.DWARF))
           consumeError(std::move(Err));
         else
           S->content.reset();
@@ -324,8 +326,7 @@
       if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
         MachO::swapStruct(LC.Data.load_command_data);
       if (Expected<const char *> ExpectedEndPtr =
-              processLoadCommandData<MachO::load_command>(LC, LoadCmd,
-                                                          *Y.get()))
+              processLoadCommandData<MachO::load_command>(LC, LoadCmd, *Y))
         EndPtr = *ExpectedEndPtr;
       else
         return ExpectedEndPtr.takeError();
@@ -356,6 +357,8 @@
   dumpSymbols(Y);
   dumpIndirectSymbols(Y);
   dumpFunctionStarts(Y);
+  dumpChainedFixups(Y);
+  dumpDataInCode(Y);
 }
 
 void MachODumper::dumpFunctionStarts(std::unique_ptr<MachOYAML::Object> &Y) {
@@ -386,7 +389,7 @@
       ULEB = decodeULEB128(OpCode + 1, &Count);
       RebaseOp.ExtraData.push_back(ULEB);
       OpCode += Count;
-      LLVM_FALLTHROUGH;
+      [[fallthrough]];
     // Intentionally no break here -- This opcode has two ULEB values
     case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
     case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
@@ -434,7 +437,7 @@
       ULEB = decodeULEB128(OpCode + 1, &Count);
       BindOp.ULEBExtraData.push_back(ULEB);
       OpCode += Count;
-      LLVM_FALLTHROUGH;
+      [[fallthrough]];
     // Intentionally no break here -- this opcode has two ULEB values
 
     case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
@@ -576,7 +579,10 @@
 
 void MachODumper::dumpExportTrie(std::unique_ptr<MachOYAML::Object> &Y) {
   MachOYAML::LinkEditData &LEData = Y->LinkEdit;
+  // The exports trie can be in LC_DYLD_INFO or LC_DYLD_EXPORTS_TRIE
   auto ExportsTrie = Obj.getDyldInfoExportsTrie();
+  if (ExportsTrie.empty())
+    ExportsTrie = Obj.getDyldExportsTrie();
   processExportNode(ExportsTrie.begin(), ExportsTrie.end(), LEData.ExportTrie);
 }
 
@@ -620,6 +626,39 @@
     LEData.IndirectSymbols.push_back(Obj.getIndirectSymbolTableEntry(DLC, i));
 }
 
+void MachODumper::dumpChainedFixups(std::unique_ptr<MachOYAML::Object> &Y) {
+  MachOYAML::LinkEditData &LEData = Y->LinkEdit;
+
+  for (const auto &LC : Y->LoadCommands) {
+    if (LC.Data.load_command_data.cmd == llvm::MachO::LC_DYLD_CHAINED_FIXUPS) {
+      const MachO::linkedit_data_command &DC =
+          LC.Data.linkedit_data_command_data;
+      if (DC.dataoff) {
+        assert(DC.dataoff < Obj.getData().size());
+        assert(DC.dataoff + DC.datasize <= Obj.getData().size());
+        const char *Bytes = Obj.getData().data() + DC.dataoff;
+        for (size_t Idx = 0; Idx < DC.datasize; Idx++) {
+          LEData.ChainedFixups.push_back(Bytes[Idx]);
+        }
+      }
+      break;
+    }
+  }
+}
+
+void MachODumper::dumpDataInCode(std::unique_ptr<MachOYAML::Object> &Y) {
+  MachOYAML::LinkEditData &LEData = Y->LinkEdit;
+
+  MachO::linkedit_data_command DIC = Obj.getDataInCodeLoadCommand();
+  uint32_t NumEntries = DIC.datasize / sizeof(MachO::data_in_code_entry);
+  for (uint32_t Idx = 0; Idx < NumEntries; ++Idx) {
+    MachO::data_in_code_entry DICE =
+        Obj.getDataInCodeTableEntry(DIC.dataoff, Idx);
+    MachOYAML::DataInCodeEntry Entry{DICE.offset, DICE.length, DICE.kind};
+    LEData.DataInCode.emplace_back(Entry);
+  }
+}
+
 Error macho2yaml(raw_ostream &Out, const object::MachOObjectFile &Obj,
                  unsigned RawSegments) {
   std::unique_ptr<DWARFContext> DCtx = DWARFContext::create(Obj);
diff --git a/src/llvm-project/llvm/tools/opt/CMakeLists.txt b/src/llvm-project/llvm/tools/opt/CMakeLists.txt
index bbba707..6b2d6b4 100644
--- a/src/llvm-project/llvm/tools/opt/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/opt/CMakeLists.txt
@@ -14,6 +14,7 @@
   Extensions
   IPO
   IRReader
+  IRPrinter
   InstCombine
   Instrumentation
   MC
@@ -22,6 +23,7 @@
   ScalarOpts
   Support
   Target
+  TargetParser
   TransformUtils
   Vectorize
   Passes
@@ -30,9 +32,7 @@
 add_llvm_tool(opt
   AnalysisWrappers.cpp
   BreakpointPrinter.cpp
-  GraphPrinters.cpp
   NewPMDriver.cpp
-  PrintSCC.cpp
   opt.cpp
 
   DEPENDS
@@ -40,7 +40,3 @@
   SUPPORT_PLUGINS
   )
 export_executable_symbols_for_plugins(opt)
-
-if(LLVM_BUILD_EXAMPLES)
-    target_link_libraries(opt PRIVATE ExampleIRTransforms)
-endif(LLVM_BUILD_EXAMPLES)
diff --git a/src/llvm-project/llvm/tools/opt/GraphPrinters.cpp b/src/llvm-project/llvm/tools/opt/GraphPrinters.cpp
deleted file mode 100644
index 611fb20..0000000
--- a/src/llvm-project/llvm/tools/opt/GraphPrinters.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- GraphPrinters.cpp - DOT printers for various graph types -----------===//
-//
-// 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 several printers for various different types of graphs used
-// by the LLVM infrastructure.  It uses the generic graph interface to convert
-// the graph into a .dot graph.  These graphs can then be processed with the
-// "dot" tool to convert them to postscript or some other suitable format.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/IR/Dominators.h"
-#include "llvm/Pass.h"
-
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-//                            DomInfoPrinter Pass
-//===----------------------------------------------------------------------===//
-
-namespace {
-  class DomInfoPrinter : public FunctionPass {
-  public:
-    static char ID; // Pass identification, replacement for typeid
-    DomInfoPrinter() : FunctionPass(ID) {}
-
-    void getAnalysisUsage(AnalysisUsage &AU) const override {
-      AU.setPreservesAll();
-      AU.addRequired<DominatorTreeWrapperPass>();
-    }
-
-    bool runOnFunction(Function &F) override {
-      getAnalysis<DominatorTreeWrapperPass>().print(dbgs());
-      return false;
-    }
-  };
-}
-
-char DomInfoPrinter::ID = 0;
-static RegisterPass<DomInfoPrinter>
-DIP("print-dom-info", "Dominator Info Printer", true, true);
diff --git a/src/llvm-project/llvm/tools/opt/NewPMDriver.cpp b/src/llvm-project/llvm/tools/opt/NewPMDriver.cpp
index 61d0e12..a8db0c6 100644
--- a/src/llvm-project/llvm/tools/opt/NewPMDriver.cpp
+++ b/src/llvm-project/llvm/tools/opt/NewPMDriver.cpp
@@ -21,16 +21,17 @@
 #include "llvm/Bitcode/BitcodeWriterPass.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/IR/Dominators.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/IRPrinter/IRPrintingPasses.h"
 #include "llvm/Passes/PassBuilder.h"
 #include "llvm/Passes/PassPlugin.h"
 #include "llvm/Passes/StandardInstrumentations.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetMachine.h"
 #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
 #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
@@ -152,30 +153,66 @@
              "the FullLinkTimeOptimizationLast extension point into default "
              "pipelines"),
     cl::Hidden);
+/// @}}
 
-// Individual pipeline tuning options.
-extern cl::opt<bool> DisableLoopUnrolling;
+static cl::opt<bool> DisablePipelineVerification(
+    "disable-pipeline-verification",
+    cl::desc("Only has an effect when specified with -print-pipeline-passes. "
+             "Disables verifying that the textual pipeline generated by "
+             "-print-pipeline-passes can be used to create a pipeline."),
+    cl::Hidden);
 
-namespace llvm {
-extern cl::opt<PGOKind> PGOKindFlag;
-extern cl::opt<std::string> ProfileFile;
-extern cl::opt<CSPGOKind> CSPGOKindFlag;
-extern cl::opt<std::string> CSProfileGenFile;
-extern cl::opt<bool> DisableBasicAA;
-extern cl::opt<bool> PrintPipelinePasses;
-} // namespace llvm
+
+static cl::opt<PGOKind>
+    PGOKindFlag("pgo-kind", cl::init(NoPGO), cl::Hidden,
+                cl::desc("The kind of profile guided optimization"),
+                cl::values(clEnumValN(NoPGO, "nopgo", "Do not use PGO."),
+                           clEnumValN(InstrGen, "pgo-instr-gen-pipeline",
+                                      "Instrument the IR to generate profile."),
+                           clEnumValN(InstrUse, "pgo-instr-use-pipeline",
+                                      "Use instrumented profile to guide PGO."),
+                           clEnumValN(SampleUse, "pgo-sample-use-pipeline",
+                                      "Use sampled profile to guide PGO.")));
+static cl::opt<std::string> ProfileFile("profile-file",
+                                 cl::desc("Path to the profile."), cl::Hidden);
+
+static cl::opt<CSPGOKind> CSPGOKindFlag(
+    "cspgo-kind", cl::init(NoCSPGO), cl::Hidden,
+    cl::desc("The kind of context sensitive profile guided optimization"),
+    cl::values(
+        clEnumValN(NoCSPGO, "nocspgo", "Do not use CSPGO."),
+        clEnumValN(
+            CSInstrGen, "cspgo-instr-gen-pipeline",
+            "Instrument (context sensitive) the IR to generate profile."),
+        clEnumValN(
+            CSInstrUse, "cspgo-instr-use-pipeline",
+            "Use instrumented (context sensitive) profile to guide PGO.")));
+
+static cl::opt<std::string> CSProfileGenFile(
+    "cs-profilegen-file",
+    cl::desc("Path to the instrumented context sensitive profile."),
+    cl::Hidden);
 
 static cl::opt<std::string>
     ProfileRemappingFile("profile-remapping-file",
                          cl::desc("Path to the profile remapping file."),
                          cl::Hidden);
+
 static cl::opt<bool> DebugInfoForProfiling(
-    "new-pm-debug-info-for-profiling", cl::init(false), cl::Hidden,
+    "debug-info-for-profiling", cl::init(false), cl::Hidden,
     cl::desc("Emit special debug info to enable PGO profile generation."));
+
 static cl::opt<bool> PseudoProbeForProfiling(
-    "new-pm-pseudo-probe-for-profiling", cl::init(false), cl::Hidden,
+    "pseudo-probe-for-profiling", cl::init(false), cl::Hidden,
     cl::desc("Emit pseudo probes to enable PGO profile generation."));
-/// @}}
+
+static cl::opt<bool> DisableLoopUnrolling(
+    "disable-loop-unrolling",
+    cl::desc("Disable loop unrolling in all relevant passes"), cl::init(false));
+
+namespace llvm {
+extern cl::opt<bool> PrintPipelinePasses;
+} // namespace llvm
 
 template <typename PassManagerT>
 bool tryParsePipelineText(PassBuilder &PB,
@@ -287,7 +324,7 @@
                            TargetLibraryInfoImpl *TLII, ToolOutputFile *Out,
                            ToolOutputFile *ThinLTOLinkOut,
                            ToolOutputFile *OptRemarkFile,
-                           StringRef PassPipeline, ArrayRef<StringRef> Passes,
+                           StringRef PassPipeline,
                            ArrayRef<PassPlugin> PassPlugins,
                            OutputKind OK, VerifierKind VK,
                            bool ShouldPreserveAssemblyUseListOrder,
@@ -296,7 +333,7 @@
                            bool EnableDebugify, bool VerifyDIPreserve) {
   bool VerifyEachPass = VK == VK_VerifyEachPass;
 
-  Optional<PGOOptions> P;
+  std::optional<PGOOptions> P;
   switch (PGOKindFlag) {
   case InstrGen:
     P = PGOOptions(ProfileFile, "", "", PGOOptions::IRInstr);
@@ -313,15 +350,19 @@
       P = PGOOptions("", "", "", PGOOptions::NoAction, PGOOptions::NoCSAction,
                      DebugInfoForProfiling, PseudoProbeForProfiling);
     else
-      P = None;
+      P = std::nullopt;
   }
   if (CSPGOKindFlag != NoCSPGO) {
     if (P && (P->Action == PGOOptions::IRInstr ||
-              P->Action == PGOOptions::SampleUse))
+              P->Action == PGOOptions::SampleUse)) {
       errs() << "CSPGOKind cannot be used with IRInstr or SampleUse";
+      return false;
+    }
     if (CSPGOKindFlag == CSInstrGen) {
-      if (CSProfileGenFile.empty())
+      if (CSProfileGenFile.empty()) {
         errs() << "CSInstrGen needs to specify CSProfileGenFile";
+        return false;
+      }
       if (P) {
         P->CSAction = PGOOptions::CSIRInstr;
         P->CSProfileGenFile = CSProfileGenFile;
@@ -329,8 +370,10 @@
         P = PGOOptions("", CSProfileGenFile, ProfileRemappingFile,
                        PGOOptions::NoAction, PGOOptions::CSIRInstr);
     } else /* CSPGOKindFlag == CSInstrUse */ {
-      if (!P)
+      if (!P) {
         errs() << "CSInstrUse needs to be together with InstrUse";
+        return false;
+      }
       P->CSAction = PGOOptions::CSIRUse;
     }
   }
@@ -346,8 +389,8 @@
   PrintPassOptions PrintPassOpts;
   PrintPassOpts.Verbose = DebugPM == DebugLogging::Verbose;
   PrintPassOpts.SkipAnalyses = DebugPM == DebugLogging::Quiet;
-  StandardInstrumentations SI(DebugPM != DebugLogging::None, VerifyEachPass,
-                              PrintPassOpts);
+  StandardInstrumentations SI(M.getContext(), DebugPM != DebugLogging::None,
+                              VerifyEachPass, PrintPassOpts);
   SI.registerCallbacks(PIC, &FAM);
   DebugifyEachInstrumentation Debugify;
   DebugifyStatsMap DIStatsMap;
@@ -376,17 +419,6 @@
   for (auto &PassPlugin : PassPlugins)
     PassPlugin.registerPassBuilderCallbacks(PB);
 
-  PB.registerPipelineParsingCallback(
-      [](StringRef Name, ModulePassManager &MPM,
-         ArrayRef<PassBuilder::PipelineElement>) {
-        AddressSanitizerOptions Opts;
-        if (Name == "asan-pipeline") {
-          MPM.addPass(ModuleAddressSanitizerPass(Opts));
-          return true;
-        }
-        return false;
-      });
-
 #define HANDLE_EXTENSION(Ext)                                                  \
   get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB);
 #include "llvm/Support/Extension.def"
@@ -394,34 +426,9 @@
   // Specially handle the alias analysis manager so that we can register
   // a custom pipeline of AA passes with it.
   AAManager AA;
-  if (Passes.empty()) {
-    if (auto Err = PB.parseAAPipeline(AA, AAPipeline)) {
-      errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
-      return false;
-    }
-  }
-
-  // For compatibility with the legacy PM AA pipeline.
-  // AAResultsWrapperPass by default provides basic-aa in the legacy PM
-  // unless -disable-basic-aa is specified.
-  // TODO: remove this once tests implicitly requiring basic-aa use -passes= and
-  // -aa-pipeline=basic-aa.
-  if (!Passes.empty() && !DisableBasicAA) {
-    if (auto Err = PB.parseAAPipeline(AA, "basic-aa")) {
-      errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
-      return false;
-    }
-  }
-
-  // For compatibility with legacy pass manager.
-  // Alias analyses are not specially specified when using the legacy PM.
-  for (auto PassName : Passes) {
-    if (PB.isAAPassName(PassName)) {
-      if (auto Err = PB.parseAAPipeline(AA, PassName)) {
-        errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
-        return false;
-      }
-    }
+  if (auto Err = PB.parseAAPipeline(AA, AAPipeline)) {
+    errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
+    return false;
   }
 
   // Register the AA manager first so that our version is the one used.
@@ -437,8 +444,6 @@
   PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
 
   ModulePassManager MPM;
-  if (VK > VK_NoVerifier)
-    MPM.addPass(VerifierPass());
   if (EnableDebugify)
     MPM.addPass(NewPMDebugifyPass());
   if (VerifyDIPreserve)
@@ -447,38 +452,11 @@
 
   // Add passes according to the -passes options.
   if (!PassPipeline.empty()) {
-    assert(Passes.empty() &&
-           "PassPipeline and Passes should not both contain passes");
     if (auto Err = PB.parsePassPipeline(MPM, PassPipeline)) {
       errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
       return false;
     }
   }
-  // Add passes specified using the legacy PM syntax (i.e. not using
-  // -passes). This should be removed later when such support has been
-  // deprecated, i.e. when all lit tests running opt (and not using
-  // -enable-new-pm=0) have been updated to use -passes.
-  for (auto PassName : Passes) {
-    std::string ModifiedPassName(PassName.begin(), PassName.end());
-    if (PB.isAnalysisPassName(PassName))
-      ModifiedPassName = "require<" + ModifiedPassName + ">";
-    // FIXME: These translations are supposed to be removed when lit tests that
-    // use these names have been updated to use the -passes syntax (and when the
-    // support for using the old syntax to specify passes is considered as
-    // deprecated for the new PM).
-    if (ModifiedPassName == "early-cse-memssa")
-      ModifiedPassName = "early-cse<memssa>";
-    else if (ModifiedPassName == "post-inline-ee-instrument")
-      ModifiedPassName = "ee-instrument<post-inline>";
-    else if (ModifiedPassName == "loop-extract-single")
-      ModifiedPassName = "loop-extract<single>";
-    else if (ModifiedPassName == "lower-matrix-intrinsics-minimal")
-      ModifiedPassName = "lower-matrix-intrinsics<minimal>";
-    if (auto Err = PB.parsePassPipeline(MPM, ModifiedPassName)) {
-      errs() << Arg0 << ": " << toString(std::move(Err)) << "\n";
-      return false;
-    }
-  }
 
   if (VK > VK_NoVerifier)
     MPM.addPass(VerifierPass());
@@ -486,16 +464,16 @@
     MPM.addPass(NewPMCheckDebugifyPass(false, "", &DIStatsMap));
   if (VerifyDIPreserve)
     MPM.addPass(NewPMCheckDebugifyPass(
-        false, "", nullptr, DebugifyMode::OriginalDebugInfo, &DebugInfoBeforePass,
-        VerifyDIPreserveExport));
+        false, "", nullptr, DebugifyMode::OriginalDebugInfo,
+        &DebugInfoBeforePass, VerifyDIPreserveExport));
 
   // Add any relevant output pass at the end of the pipeline.
   switch (OK) {
   case OK_NoOutput:
     break; // No output pass needed.
   case OK_OutputAssembly:
-    MPM.addPass(
-        PrintModulePass(Out->os(), "", ShouldPreserveAssemblyUseListOrder));
+    MPM.addPass(PrintModulePass(
+        Out->os(), "", ShouldPreserveAssemblyUseListOrder, EmitSummaryIndex));
     break;
   case OK_OutputBitcode:
     MPM.addPass(BitcodeWriterPass(Out->os(), ShouldPreserveBitcodeUseListOrder,
@@ -513,11 +491,26 @@
   // Print a textual, '-passes=' compatible, representation of pipeline if
   // requested.
   if (PrintPipelinePasses) {
-    MPM.printPipeline(outs(), [&PIC](StringRef ClassName) {
+    std::string Pipeline;
+    raw_string_ostream SOS(Pipeline);
+    MPM.printPipeline(SOS, [&PIC](StringRef ClassName) {
       auto PassName = PIC.getPassNameForClassName(ClassName);
       return PassName.empty() ? ClassName : PassName;
     });
+    outs() << Pipeline;
     outs() << "\n";
+
+    if (!DisablePipelineVerification) {
+      // Check that we can parse the returned pipeline string as an actual
+      // pipeline.
+      ModulePassManager TempPM;
+      if (auto Err = PB.parsePassPipeline(TempPM, Pipeline)) {
+        errs() << "Could not parse dumped pass pipeline: "
+               << toString(std::move(Err)) << "\n";
+        return false;
+      }
+    }
+
     return true;
   }
 
diff --git a/src/llvm-project/llvm/tools/opt/NewPMDriver.h b/src/llvm-project/llvm/tools/opt/NewPMDriver.h
index 543f91c..a3cdd15 100644
--- a/src/llvm-project/llvm/tools/opt/NewPMDriver.h
+++ b/src/llvm-project/llvm/tools/opt/NewPMDriver.h
@@ -43,11 +43,7 @@
   OK_OutputBitcode,
   OK_OutputThinLTOBitcode,
 };
-enum VerifierKind {
-  VK_NoVerifier,
-  VK_VerifyInAndOut,
-  VK_VerifyEachPass
-};
+enum VerifierKind { VK_NoVerifier, VK_VerifyOut, VK_VerifyEachPass };
 enum PGOKind {
   NoPGO,
   InstrGen,
@@ -71,7 +67,7 @@
 bool runPassPipeline(StringRef Arg0, Module &M, TargetMachine *TM,
                      TargetLibraryInfoImpl *TLII, ToolOutputFile *Out,
                      ToolOutputFile *ThinLinkOut, ToolOutputFile *OptRemarkFile,
-                     StringRef PassPipeline, ArrayRef<StringRef> PassInfos,
+                     StringRef PassPipeline,
                      ArrayRef<PassPlugin> PassPlugins, opt_tool::OutputKind OK,
                      opt_tool::VerifierKind VK,
                      bool ShouldPreserveAssemblyUseListOrder,
diff --git a/src/llvm-project/llvm/tools/opt/PrintSCC.cpp b/src/llvm-project/llvm/tools/opt/PrintSCC.cpp
deleted file mode 100644
index 1ca5274..0000000
--- a/src/llvm-project/llvm/tools/opt/PrintSCC.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-//===- PrintSCC.cpp - Enumerate SCCs in some key graphs -------------------===//
-//
-// 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 provides passes to print out SCCs in a CFG or a CallGraph.
-// Normally, you would not use these passes; instead, you would use the
-// scc_iterator directly to enumerate SCCs and process them in some way.  These
-// passes serve three purposes:
-//
-// (1) As a reference for how to use the scc_iterator.
-// (2) To print out the SCCs for a CFG or a CallGraph:
-//       analyze -print-cfg-sccs            to print the SCCs in each CFG of a module.
-//       analyze -print-cfg-sccs -stats     to print the #SCCs and the maximum SCC size.
-//       analyze -print-cfg-sccs -debug > /dev/null to watch the algorithm in action.
-//
-//     and similarly:
-//       analyze -print-callgraph-sccs [-stats] [-debug] to print SCCs in the CallGraph
-//
-// (3) To test the scc_iterator.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/SCCIterator.h"
-#include "llvm/Analysis/CallGraph.h"
-#include "llvm/IR/CFG.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-namespace {
-  struct CFGSCC : public FunctionPass {
-    static char ID;  // Pass identification, replacement for typeid
-    CFGSCC() : FunctionPass(ID) {}
-    bool runOnFunction(Function& func) override;
-
-    void print(raw_ostream &O, const Module* = nullptr) const override { }
-
-    void getAnalysisUsage(AnalysisUsage &AU) const override {
-      AU.setPreservesAll();
-    }
-  };
-
-  struct CallGraphSCC : public ModulePass {
-    static char ID;  // Pass identification, replacement for typeid
-    CallGraphSCC() : ModulePass(ID) {}
-
-    // run - Print out SCCs in the call graph for the specified module.
-    bool runOnModule(Module &M) override;
-
-    void print(raw_ostream &O, const Module* = nullptr) const override { }
-
-    // getAnalysisUsage - This pass requires the CallGraph.
-    void getAnalysisUsage(AnalysisUsage &AU) const override {
-      AU.setPreservesAll();
-      AU.addRequired<CallGraphWrapperPass>();
-    }
-  };
-}
-
-char CFGSCC::ID = 0;
-static RegisterPass<CFGSCC>
-Y("print-cfg-sccs", "Print SCCs of each function CFG");
-
-char CallGraphSCC::ID = 0;
-static RegisterPass<CallGraphSCC>
-Z("print-callgraph-sccs", "Print SCCs of the Call Graph");
-
-bool CFGSCC::runOnFunction(Function &F) {
-  unsigned sccNum = 0;
-  errs() << "SCCs for Function " << F.getName() << " in PostOrder:";
-  for (scc_iterator<Function*> SCCI = scc_begin(&F); !SCCI.isAtEnd(); ++SCCI) {
-    const std::vector<BasicBlock *> &nextSCC = *SCCI;
-    errs() << "\nSCC #" << ++sccNum << " : ";
-    for (BasicBlock *BB : nextSCC) {
-      BB->printAsOperand(errs(), false);
-      errs() << ", ";
-    }
-    if (nextSCC.size() == 1 && SCCI.hasCycle())
-      errs() << " (Has self-loop).";
-  }
-  errs() << "\n";
-
-  return true;
-}
-
-
-// run - Print out SCCs in the call graph for the specified module.
-bool CallGraphSCC::runOnModule(Module &M) {
-  CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
-  unsigned sccNum = 0;
-  errs() << "SCCs for the program in PostOrder:";
-  for (scc_iterator<CallGraph*> SCCI = scc_begin(&CG); !SCCI.isAtEnd();
-       ++SCCI) {
-    const std::vector<CallGraphNode*> &nextSCC = *SCCI;
-    errs() << "\nSCC #" << ++sccNum << " : ";
-    for (std::vector<CallGraphNode*>::const_iterator I = nextSCC.begin(),
-           E = nextSCC.end(); I != E; ++I)
-      errs() << ((*I)->getFunction() ? (*I)->getFunction()->getName()
-                                     : "external node") << ", ";
-    if (nextSCC.size() == 1 && SCCI.hasCycle())
-      errs() << " (Has self-loop).";
-  }
-  errs() << "\n";
-
-  return true;
-}
diff --git a/src/llvm-project/llvm/tools/opt/opt.cpp b/src/llvm-project/llvm/tools/opt/opt.cpp
index a02997f..40632b4 100644
--- a/src/llvm-project/llvm/tools/opt/opt.cpp
+++ b/src/llvm-project/llvm/tools/opt/opt.cpp
@@ -52,13 +52,12 @@
 #include "llvm/Support/ToolOutputFile.h"
 #include "llvm/Support/YAMLTraits.h"
 #include "llvm/Target/TargetMachine.h"
-#include "llvm/Transforms/IPO/AlwaysInliner.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
 #include "llvm/Transforms/IPO/WholeProgramDevirt.h"
 #include "llvm/Transforms/Utils/Cloning.h"
 #include "llvm/Transforms/Utils/Debugify.h"
 #include <algorithm>
 #include <memory>
+#include <optional>
 using namespace llvm;
 using namespace opt_tool;
 
@@ -85,6 +84,8 @@
     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> PrintPasses("print-passes",
                                  cl::desc("Print available passes that can be "
@@ -177,10 +178,6 @@
 static cl::opt<std::string>
 TargetTriple("mtriple", cl::desc("Override target triple for module"));
 
-cl::opt<bool> DisableLoopUnrolling(
-    "disable-loop-unrolling",
-    cl::desc("Disable loop unrolling in all relevant passes"), cl::init(false));
-
 static cl::opt<bool> EmitSummaryIndex("module-summary",
                                       cl::desc("Emit module summary index"),
                                       cl::init(false));
@@ -254,12 +251,12 @@
     cl::desc("With PGO, include profile count in optimization remarks"),
     cl::Hidden);
 
-static cl::opt<Optional<uint64_t>, false, remarks::HotnessThresholdParser>
+static cl::opt<std::optional<uint64_t>, false, remarks::HotnessThresholdParser>
     RemarksHotnessThreshold(
         "pass-remarks-hotness-threshold",
         cl::desc("Minimum profile count required for "
                  "an optimization remark to be output. "
-                 "Use 'auto' to apply the threshold from profile summary."),
+                 "Use 'auto' to apply the threshold from profile summary"),
         cl::value_desc("N or 'auto'"), cl::init(0), cl::Hidden);
 
 static cl::opt<std::string>
@@ -282,37 +279,6 @@
     PassPlugins("load-pass-plugin",
                 cl::desc("Load passes from plugin library"));
 
-namespace llvm {
-cl::opt<PGOKind>
-    PGOKindFlag("pgo-kind", cl::init(NoPGO), cl::Hidden,
-                cl::desc("The kind of profile guided optimization"),
-                cl::values(clEnumValN(NoPGO, "nopgo", "Do not use PGO."),
-                           clEnumValN(InstrGen, "pgo-instr-gen-pipeline",
-                                      "Instrument the IR to generate profile."),
-                           clEnumValN(InstrUse, "pgo-instr-use-pipeline",
-                                      "Use instrumented profile to guide PGO."),
-                           clEnumValN(SampleUse, "pgo-sample-use-pipeline",
-                                      "Use sampled profile to guide PGO.")));
-cl::opt<std::string> ProfileFile("profile-file",
-                                 cl::desc("Path to the profile."), cl::Hidden);
-
-cl::opt<CSPGOKind> CSPGOKindFlag(
-    "cspgo-kind", cl::init(NoCSPGO), cl::Hidden,
-    cl::desc("The kind of context sensitive profile guided optimization"),
-    cl::values(
-        clEnumValN(NoCSPGO, "nocspgo", "Do not use CSPGO."),
-        clEnumValN(
-            CSInstrGen, "cspgo-instr-gen-pipeline",
-            "Instrument (context sensitive) the IR to generate profile."),
-        clEnumValN(
-            CSInstrUse, "cspgo-instr-use-pipeline",
-            "Use instrumented (context sensitive) profile to guide PGO.")));
-cl::opt<std::string> CSProfileGenFile(
-    "cs-profilegen-file",
-    cl::desc("Path to the instrumented context sensitive profile."),
-    cl::Hidden);
-} // namespace llvm
-
 static inline void addPass(legacy::PassManagerBase &PM, Pass *P) {
   // Add the pass to the pass manager...
   PM.add(P);
@@ -322,54 +288,12 @@
     PM.add(createVerifierPass());
 }
 
-/// This routine adds optimization passes based on selected optimization level,
-/// OptLevel.
-///
-/// OptLevel - Optimization Level
-static void AddOptimizationPasses(legacy::PassManagerBase &MPM,
-                                  legacy::FunctionPassManager &FPM,
-                                  TargetMachine *TM, unsigned OptLevel,
-                                  unsigned SizeLevel) {
-  if (!NoVerify || VerifyEach)
-    FPM.add(createVerifierPass()); // Verify that input is correct
-
-  PassManagerBuilder Builder;
-  Builder.OptLevel = OptLevel;
-  Builder.SizeLevel = SizeLevel;
-
-  if (OptLevel > 1) {
-    Builder.Inliner = createFunctionInliningPass(OptLevel, SizeLevel, false);
-  } else {
-    Builder.Inliner = createAlwaysInlinerLegacyPass();
-  }
-  Builder.DisableUnrollLoops = (DisableLoopUnrolling.getNumOccurrences() > 0) ?
-                               DisableLoopUnrolling : OptLevel == 0;
-
-  Builder.LoopVectorize = OptLevel > 1 && SizeLevel < 2;
-
-  Builder.SLPVectorize = OptLevel > 1 && SizeLevel < 2;
-
-  if (TM)
-    TM->adjustPassManager(Builder);
-
-  Builder.populateFunctionPassManager(FPM);
-  Builder.populateModulePassManager(MPM);
-}
-
 //===----------------------------------------------------------------------===//
 // CodeGen-related helper functions.
 //
 
 static CodeGenOpt::Level GetCodeGenOptLevel() {
-  if (CodeGenOptLevel.getNumOccurrences())
-    return static_cast<CodeGenOpt::Level>(unsigned(CodeGenOptLevel));
-  if (OptLevelO1)
-    return CodeGenOpt::Less;
-  if (OptLevelO2)
-    return CodeGenOpt::Default;
-  if (OptLevelO3)
-    return CodeGenOpt::Aggressive;
-  return CodeGenOpt::None;
+  return static_cast<CodeGenOpt::Level>(unsigned(CodeGenOptLevel));
 }
 
 // Returns the TargetMachine instance or zero if no triple is provided.
@@ -390,10 +314,6 @@
       codegen::getExplicitCodeModel(), GetCodeGenOptLevel());
 }
 
-#ifdef BUILD_EXAMPLES
-void initializeExampleIRTransforms(llvm::PassRegistry &Registry);
-#endif
-
 struct TimeTracerRAII {
   TimeTracerRAII(StringRef ProgramName) {
     if (TimeTrace)
@@ -440,22 +360,41 @@
       "amdgcn-", "polly-", "riscv-", "dxil-"};
   std::vector<StringRef> PassNameContain = {"ehprepare"};
   std::vector<StringRef> PassNameExact = {
-      "safe-stack",           "cost-model",
-      "codegenprepare",       "interleaved-load-combine",
-      "unreachableblockelim", "verify-safepoint-ir",
-      "atomic-expand",        "expandvp",
-      "hardware-loops",       "type-promotion",
-      "mve-tail-predication", "interleaved-access",
-      "global-merge",         "pre-isel-intrinsic-lowering",
-      "expand-reductions",    "indirectbr-expand",
-      "generic-to-nvvm",      "expandmemcmp",
-      "loop-reduce",          "lower-amx-type",
-      "pre-amx-config",       "lower-amx-intrinsics",
-      "polyhedral-info",      "print-polyhedral-info",
-      "replace-with-veclib",  "jmc-instrument",
-      "dot-regions",          "dot-regions-only",
-      "view-regions",         "view-regions-only",
-      "select-optimize"};
+      "safe-stack",
+      "cost-model",
+      "codegenprepare",
+      "interleaved-load-combine",
+      "unreachableblockelim",
+      "verify-safepoint-ir",
+      "atomic-expand",
+      "expandvp",
+      "hardware-loops",
+      "mve-tail-predication",
+      "interleaved-access",
+      "global-merge",
+      "pre-isel-intrinsic-lowering",
+      "expand-reductions",
+      "indirectbr-expand",
+      "generic-to-nvvm",
+      "expandmemcmp",
+      "loop-reduce",
+      "lower-amx-type",
+      "pre-amx-config",
+      "lower-amx-intrinsics",
+      "polyhedral-info",
+      "print-polyhedral-info",
+      "replace-with-veclib",
+      "jmc-instrument",
+      "dot-regions",
+      "dot-regions-only",
+      "view-regions",
+      "view-regions-only",
+      "select-optimize",
+      "expand-large-div-rem",
+      "structurizecfg",
+      "fix-irreducible",
+      "expand-large-fp-convert"
+  };
   for (const auto &P : PassNamePrefix)
     if (Pass.startswith(P))
       return true;
@@ -493,17 +432,16 @@
   PassRegistry &Registry = *PassRegistry::getPassRegistry();
   initializeCore(Registry);
   initializeScalarOpts(Registry);
-  initializeObjCARCOpts(Registry);
   initializeVectorization(Registry);
   initializeIPO(Registry);
   initializeAnalysis(Registry);
   initializeTransformUtils(Registry);
   initializeInstCombine(Registry);
-  initializeAggressiveInstCombine(Registry);
-  initializeInstrumentation(Registry);
   initializeTarget(Registry);
   // For codegen passes, only passes that do IR to IR transformation are
   // supported.
+  initializeExpandLargeDivRemLegacyPassPass(Registry);
+  initializeExpandLargeFpConvertLegacyPassPass(Registry);
   initializeExpandMemCmpPassPass(Registry);
   initializeScalarizeMaskedMemIntrinLegacyPassPass(Registry);
   initializeSelectOptimizePass(Registry);
@@ -525,14 +463,9 @@
   initializeWasmEHPreparePass(Registry);
   initializeWriteBitcodePassPass(Registry);
   initializeHardwareLoopsPass(Registry);
-  initializeTypePromotionPass(Registry);
   initializeReplaceWithVeclibLegacyPass(Registry);
   initializeJMCInstrumenterPass(Registry);
 
-#ifdef BUILD_EXAMPLES
-  initializeExampleIRTransforms(Registry);
-#endif
-
   SmallVector<PassPlugin, 1> PluginList;
   PassPlugins.setCallback([&](const std::string &PluginPath) {
     auto Plugin = PassPlugin::Load(PluginPath);
@@ -544,6 +477,9 @@
     PluginList.emplace_back(Plugin.get());
   });
 
+  // Register the Target and CPU printer for --version.
+  cl::AddExtraVersionPrinter(sys::printDefaultTargetAndDetectedCPU);
+
   cl::ParseCommandLineOptions(argc, argv,
     "llvm .bc -> .bc modular optimizer and analysis printer\n");
 
@@ -556,6 +492,15 @@
   const bool UseNPM = (EnableNewPassManager && !shouldForceLegacyPM()) ||
                       PassPipeline.getNumOccurrences() > 0;
 
+  if (UseNPM && !PassList.empty()) {
+    errs() << "The `opt -passname` syntax for the new pass manager is "
+              "not supported, please use `opt -passes=<pipeline>` (or the `-p` "
+              "alias for a more concise version).\n";
+    errs() << "See https://llvm.org/docs/NewPassManager.html#invoking-opt "
+              "for more details on the pass pipeline syntax.\n\n";
+    return 1;
+  }
+
   if (!UseNPM && PluginList.size()) {
     errs() << argv[0] << ": " << PassPlugins.ArgStr
            << " specified with legacy PM.\n";
@@ -589,9 +534,9 @@
   std::unique_ptr<ToolOutputFile> RemarksFile = std::move(*RemarksFileOrErr);
 
   // Load the input module...
-  auto SetDataLayout = [](StringRef) -> Optional<std::string> {
+  auto SetDataLayout = [](StringRef, StringRef) -> std::optional<std::string> {
     if (ClDataLayout.empty())
-      return None;
+      return std::nullopt;
     return ClDataLayout;
   };
   std::unique_ptr<Module> M;
@@ -600,7 +545,8 @@
             InputFilename, Err, Context, nullptr, SetDataLayout)
             .Mod;
   else
-    M = parseIRFile(InputFilename, Err, Context, SetDataLayout);
+    M = parseIRFile(InputFilename, Err, Context,
+                    ParserCallbacks(SetDataLayout));
 
   if (!M) {
     Err.print(argv[0], errs());
@@ -730,26 +676,19 @@
              "-debug-pass-manager, or use the legacy PM (-enable-new-pm=0)\n";
       return 1;
     }
-    if (PassPipeline.getNumOccurrences() > 0 && PassList.size() > 0) {
-      errs()
-          << "Cannot specify passes via both -foo-pass and --passes=foo-pass\n";
-      return 1;
-    }
     auto NumOLevel = OptLevelO0 + OptLevelO1 + OptLevelO2 + OptLevelO3 +
                      OptLevelOs + OptLevelOz;
     if (NumOLevel > 1) {
       errs() << "Cannot specify multiple -O#\n";
       return 1;
     }
-    if (NumOLevel > 0 &&
-        (PassPipeline.getNumOccurrences() > 0 || PassList.size() > 0)) {
+    if (NumOLevel > 0 && (PassPipeline.getNumOccurrences() > 0)) {
       errs() << "Cannot specify -O# and --passes=/--foo-pass, use "
                 "-passes='default<O#>,other-pass'\n";
       return 1;
     }
     std::string Pipeline = PassPipeline;
 
-    SmallVector<StringRef, 4> Passes;
     if (OptLevelO0)
       Pipeline = "default<O0>";
     if (OptLevelO1)
@@ -762,15 +701,13 @@
       Pipeline = "default<Os>";
     if (OptLevelOz)
       Pipeline = "default<Oz>";
-    for (const auto &P : PassList)
-      Passes.push_back(P->getPassArgument());
     OutputKind OK = OK_NoOutput;
     if (!NoOutput)
       OK = OutputAssembly
                ? OK_OutputAssembly
                : (OutputThinLTOBC ? OK_OutputThinLTOBitcode : OK_OutputBitcode);
 
-    VerifierKind VK = VK_VerifyInAndOut;
+    VerifierKind VK = VK_VerifyOut;
     if (NoVerify)
       VK = VK_NoVerifier;
     else if (VerifyEach)
@@ -781,7 +718,7 @@
     // layer.
     return runPassPipeline(argv[0], *M, TM.get(), &TLII, Out.get(),
                            ThinLinkOut.get(), RemarksFile.get(), Pipeline,
-                           Passes, PluginList, OK, VK, PreserveAssemblyUseListOrder,
+                           PluginList, OK, VK, PreserveAssemblyUseListOrder,
                            PreserveBitcodeUseListOrder, EmitSummaryIndex,
                            EmitModuleHash, EnableDebugify,
                            VerifyDebugInfoPreserve)
@@ -789,6 +726,23 @@
                : 1;
   }
 
+  if (OptLevelO0 || OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz ||
+      OptLevelO3) {
+    errs() << "Cannot use -O# with legacy PM.\n";
+    return 1;
+  }
+  if (EmitSummaryIndex) {
+    errs() << "Cannot use -module-summary with legacy PM.\n";
+    return 1;
+  }
+  if (EmitModuleHash) {
+    errs() << "Cannot use -module-hash with legacy PM.\n";
+    return 1;
+  }
+  if (OutputThinLTOBC) {
+    errs() << "Cannot use -thinlto-bc with legacy PM.\n";
+    return 1;
+  }
   // Create a PassManager to hold and optimize the collection of passes we are
   // about to build. If the -debugify-each option is set, wrap each pass with
   // the (-check)-debugify passes.
@@ -828,12 +782,6 @@
   }
 
   std::unique_ptr<legacy::FunctionPassManager> FPasses;
-  if (OptLevelO0 || OptLevelO1 || OptLevelO2 || OptLevelOs || OptLevelOz ||
-      OptLevelO3) {
-    FPasses.reset(new legacy::FunctionPassManager(M.get()));
-    FPasses->add(createTargetTransformInfoWrapperPass(
-        TM ? TM->getTargetIRAnalysis() : TargetIRAnalysis()));
-  }
 
   if (PrintBreakpoints) {
     // Default to standard output.
@@ -862,36 +810,6 @@
 
   // Create a new optimization pass for each one specified on the command line
   for (unsigned i = 0; i < PassList.size(); ++i) {
-    if (OptLevelO0 && OptLevelO0.getPosition() < PassList.getPosition(i)) {
-      AddOptimizationPasses(Passes, *FPasses, TM.get(), 0, 0);
-      OptLevelO0 = false;
-    }
-
-    if (OptLevelO1 && OptLevelO1.getPosition() < PassList.getPosition(i)) {
-      AddOptimizationPasses(Passes, *FPasses, TM.get(), 1, 0);
-      OptLevelO1 = false;
-    }
-
-    if (OptLevelO2 && OptLevelO2.getPosition() < PassList.getPosition(i)) {
-      AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 0);
-      OptLevelO2 = false;
-    }
-
-    if (OptLevelOs && OptLevelOs.getPosition() < PassList.getPosition(i)) {
-      AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 1);
-      OptLevelOs = false;
-    }
-
-    if (OptLevelOz && OptLevelOz.getPosition() < PassList.getPosition(i)) {
-      AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 2);
-      OptLevelOz = false;
-    }
-
-    if (OptLevelO3 && OptLevelO3.getPosition() < PassList.getPosition(i)) {
-      AddOptimizationPasses(Passes, *FPasses, TM.get(), 3, 0);
-      OptLevelO3 = false;
-    }
-
     const PassInfo *PassInf = PassList[i];
     Pass *P = nullptr;
     if (PassInf->getNormalCtor())
@@ -903,24 +821,6 @@
       addPass(Passes, P);
   }
 
-  if (OptLevelO0)
-    AddOptimizationPasses(Passes, *FPasses, TM.get(), 0, 0);
-
-  if (OptLevelO1)
-    AddOptimizationPasses(Passes, *FPasses, TM.get(), 1, 0);
-
-  if (OptLevelO2)
-    AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 0);
-
-  if (OptLevelOs)
-    AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 1);
-
-  if (OptLevelOz)
-    AddOptimizationPasses(Passes, *FPasses, TM.get(), 2, 2);
-
-  if (OptLevelO3)
-    AddOptimizationPasses(Passes, *FPasses, TM.get(), 3, 0);
-
   if (FPasses) {
     FPasses->doInitialization();
     for (Function &F : *M)
@@ -963,18 +863,10 @@
       BOS = std::make_unique<raw_svector_ostream>(Buffer);
       OS = BOS.get();
     }
-    if (OutputAssembly) {
-      if (EmitSummaryIndex)
-        report_fatal_error("Text output is incompatible with -module-summary");
-      if (EmitModuleHash)
-        report_fatal_error("Text output is incompatible with -module-hash");
+    if (OutputAssembly)
       Passes.add(createPrintModulePass(*OS, "", PreserveAssemblyUseListOrder));
-    } else if (OutputThinLTOBC)
-      Passes.add(createWriteThinLTOBitcodePass(
-          *OS, ThinLinkOut ? &ThinLinkOut->os() : nullptr));
     else
-      Passes.add(createBitcodeWriterPass(*OS, PreserveBitcodeUseListOrder,
-                                         EmitSummaryIndex, EmitModuleHash));
+      Passes.add(createBitcodeWriterPass(*OS, PreserveBitcodeUseListOrder));
   }
 
   // Before executing passes, print the final values of the LLVM options.
diff --git a/src/llvm-project/llvm/tools/remarks-shlib/CMakeLists.txt b/src/llvm-project/llvm/tools/remarks-shlib/CMakeLists.txt
index f22cedd..bc4bd67 100644
--- a/src/llvm-project/llvm/tools/remarks-shlib/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/remarks-shlib/CMakeLists.txt
@@ -9,7 +9,9 @@
     libremarks.cpp
     )
 
-  set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/Remarks.exports)
+  if (NOT (BUILD_SHARED_LIBS OR LLVM_LINK_LLVM_DYLIB))
+    set(LLVM_EXPORTED_SYMBOL_FILE ${CMAKE_CURRENT_SOURCE_DIR}/Remarks.exports)
+  endif()
 
   add_llvm_library(Remarks SHARED INSTALL_WITH_TOOLCHAIN ${SOURCES})
 
diff --git a/src/llvm-project/llvm/tools/sancov/CMakeLists.txt b/src/llvm-project/llvm/tools/sancov/CMakeLists.txt
index 51d8db6..e273195 100644
--- a/src/llvm-project/llvm/tools/sancov/CMakeLists.txt
+++ b/src/llvm-project/llvm/tools/sancov/CMakeLists.txt
@@ -8,6 +8,7 @@
   MCDisassembler
   Object
   Support
+  TargetParser
   Symbolize
   )
 
diff --git a/src/llvm-project/llvm/tools/sancov/sancov.cpp b/src/llvm-project/llvm/tools/sancov/sancov.cpp
index e7c985c..9d29e9a 100644
--- a/src/llvm-project/llvm/tools/sancov/sancov.cpp
+++ b/src/llvm-project/llvm/tools/sancov/sancov.cpp
@@ -114,15 +114,6 @@
                  cl::desc("Ignorelist file (sanitizer ignorelist format)"),
                  cl::cat(Cat));
 
-static cl::opt<std::string>
-    ClBlacklist("blacklist", cl::init(""), cl::Hidden,
-                cl::desc("ignorelist file (sanitizer ignorelist format)"),
-                cl::cat(Cat));
-
-static cl::opt<bool> ClUseDefaultBlacklist(
-    "use_default_blacklist", cl::init(true), cl::Hidden,
-    cl::desc("Controls if default ignorelist should be used"), 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));
@@ -514,7 +505,7 @@
 
 private:
   static std::unique_ptr<SpecialCaseList> createDefaultIgnorelist() {
-    if ((!ClUseDefaultIgnorelist) && (!ClUseDefaultBlacklist))
+    if (!ClUseDefaultIgnorelist)
       return std::unique_ptr<SpecialCaseList>();
     std::unique_ptr<MemoryBuffer> MB =
         MemoryBuffer::getMemBuffer(DefaultIgnorelistStr);
@@ -525,13 +516,8 @@
   }
 
   static std::unique_ptr<SpecialCaseList> createUserIgnorelist() {
-    if ((ClBlacklist.empty()) && ClIgnorelist.empty())
+    if (ClIgnorelist.empty())
       return std::unique_ptr<SpecialCaseList>();
-
-    if (!ClBlacklist.empty())
-      return SpecialCaseList::createOrDie({{ClBlacklist}},
-                                          *vfs::getRealFileSystem());
-
     return SpecialCaseList::createOrDie({{ClIgnorelist}},
                                         *vfs::getRealFileSystem());
   }
diff --git a/src/llvm-project/llvm/tools/split-file/.clang-tidy b/src/llvm-project/llvm/tools/split-file/.clang-tidy
deleted file mode 100644
index acd9361..0000000
--- a/src/llvm-project/llvm/tools/split-file/.clang-tidy
+++ /dev/null
@@ -1,8 +0,0 @@
-InheritParentConfig: true
-CheckOptions:
-  - key:             readability-identifier-naming.MemberCase
-    value:           camelBack
-  - key:             readability-identifier-naming.ParameterCase
-    value:           camelBack
-  - key:             readability-identifier-naming.VariableCase
-    value:           camelBack
diff --git a/src/llvm-project/llvm/tools/split-file/CMakeLists.txt b/src/llvm-project/llvm/tools/split-file/CMakeLists.txt
deleted file mode 100644
index ba99848..0000000
--- a/src/llvm-project/llvm/tools/split-file/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-set(LLVM_LINK_COMPONENTS
-  Support
-  )
-
-add_llvm_tool(split-file
-  split-file.cpp
-  )
diff --git a/src/llvm-project/llvm/tools/split-file/split-file.cpp b/src/llvm-project/llvm/tools/split-file/split-file.cpp
deleted file mode 100644
index 4a92c1b..0000000
--- a/src/llvm-project/llvm/tools/split-file/split-file.cpp
+++ /dev/null
@@ -1,178 +0,0 @@
-//===- split-file.cpp - Input splitting utility ---------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-//
-// Split input into multipe parts separated by regex '^(.|//)--- ' and extract
-// the specified part.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/LineIterator.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/ToolOutputFile.h"
-#include "llvm/Support/WithColor.h"
-#include <string>
-#include <system_error>
-
-using namespace llvm;
-
-static cl::OptionCategory cat("split-file Options");
-
-static cl::opt<std::string> input(cl::Positional, cl::desc("filename"),
-                                  cl::cat(cat));
-
-static cl::opt<std::string> output(cl::Positional, cl::desc("directory"),
-                                   cl::value_desc("directory"), cl::cat(cat));
-
-static cl::opt<bool> leadingLines("leading-lines",
-                                    cl::desc("Preserve line numbers"),
-                                    cl::cat(cat));
-
-static cl::opt<bool> noLeadingLines("no-leading-lines",
-                                    cl::desc("Don't preserve line numbers (default)"),
-                                    cl::cat(cat));
-
-static StringRef toolName;
-static int errorCount;
-
-[[noreturn]] static void fatal(StringRef filename, const Twine &message) {
-  if (filename.empty())
-    WithColor::error(errs(), toolName) << message << '\n';
-  else
-    WithColor::error(errs(), toolName) << filename << ": " << message << '\n';
-  exit(1);
-}
-
-static void error(StringRef filename, int64_t line, const Twine &message) {
-  ++errorCount;
-  errs() << filename << ':' << line << ": ";
-  WithColor::error(errs()) << message << '\n';
-}
-
-namespace {
-struct Part {
-  const char *begin = nullptr;
-  const char *end = nullptr;
-  int64_t leadingLines = 0;
-};
-} // namespace
-
-static int handle(MemoryBuffer &inputBuf, StringRef input) {
-  DenseMap<StringRef, Part> partToBegin;
-  StringRef lastPart, separator;
-  StringRef EOL = inputBuf.getBuffer().detectEOL();
-  for (line_iterator i(inputBuf, /*SkipBlanks=*/false, '\0'); !i.is_at_eof();) {
-    const int64_t lineNo = i.line_number();
-    const StringRef line = *i++;
-    const size_t markerLen = line.startswith("//") ? 6 : 5;
-    if (!(line.size() >= markerLen &&
-          line.substr(markerLen - 4).startswith("--- ")))
-      continue;
-    separator = line.substr(0, markerLen);
-    const StringRef partName = line.substr(markerLen);
-    if (partName.empty()) {
-      error(input, lineNo, "empty part name");
-      continue;
-    }
-    if (isSpace(partName.front()) || isSpace(partName.back())) {
-      error(input, lineNo, "part name cannot have leading or trailing space");
-      continue;
-    }
-
-    auto res = partToBegin.try_emplace(partName);
-    if (!res.second) {
-      error(input, lineNo,
-            "'" + separator + partName + "' occurs more than once");
-      continue;
-    }
-    if (!lastPart.empty())
-      partToBegin[lastPart].end = line.data();
-    Part &cur = res.first->second;
-    if (!i.is_at_eof())
-      cur.begin = i->data();
-    // If --leading-lines is specified, numEmptyLines is 0. Append newlines so
-    // that the extracted part preserves line numbers.
-    cur.leadingLines = leadingLines ? i.line_number() - 1 : 0;
-
-    lastPart = partName;
-  }
-  if (lastPart.empty())
-    fatal(input, "no part separator was found");
-  if (errorCount)
-    return 1;
-  partToBegin[lastPart].end = inputBuf.getBufferEnd();
-
-  std::vector<std::unique_ptr<ToolOutputFile>> outputFiles;
-  SmallString<256> partPath;
-  for (auto &keyValue : partToBegin) {
-    partPath.clear();
-    sys::path::append(partPath, output, keyValue.first);
-    std::error_code ec =
-        sys::fs::create_directories(sys::path::parent_path(partPath));
-    if (ec)
-      fatal(input, ec.message());
-    auto f = std::make_unique<ToolOutputFile>(partPath.str(), ec,
-                                              llvm::sys::fs::OF_None);
-    if (!f)
-      fatal(input, ec.message());
-
-    Part &part = keyValue.second;
-    for (int64_t i = 0; i != part.leadingLines; ++i)
-      (*f).os() << EOL;
-    if (part.begin)
-      (*f).os().write(part.begin, part.end - part.begin);
-    outputFiles.push_back(std::move(f));
-  }
-
-  for (std::unique_ptr<ToolOutputFile> &outputFile : outputFiles)
-    outputFile->keep();
-  return 0;
-}
-
-int main(int argc, const char **argv) {
-  toolName = sys::path::stem(argv[0]);
-  cl::HideUnrelatedOptions({&cat});
-  cl::ParseCommandLineOptions(
-      argc, argv,
-      "Split input into multiple parts separated by regex '^(.|//)--- ' and "
-      "extract the part specified by '^(.|//)--- <part>'\n",
-      nullptr,
-      /*EnvVar=*/nullptr,
-      /*LongOptionsUseDoubleDash=*/true);
-
-  if (input.empty())
-    fatal("", "input filename is not specified");
-  if (output.empty())
-    fatal("", "output directory is not specified");
-  ErrorOr<std::unique_ptr<MemoryBuffer>> bufferOrErr =
-      MemoryBuffer::getFileOrSTDIN(input);
-  if (std::error_code ec = bufferOrErr.getError())
-    fatal(input, ec.message());
-
-  // Delete output if it is a file or an empty directory, so that we can create
-  // a directory.
-  sys::fs::file_status status;
-  if (std::error_code ec = sys::fs::status(output, status))
-    if (ec.value() != static_cast<int>(std::errc::no_such_file_or_directory))
-      fatal(output, ec.message());
-  if (status.type() != sys::fs::file_type::file_not_found &&
-      status.type() != sys::fs::file_type::directory_file &&
-      status.type() != sys::fs::file_type::regular_file)
-    fatal(output, "output cannot be a special file");
-  if (std::error_code ec = sys::fs::remove(output, /*IgnoreNonExisting=*/true))
-    if (ec.value() != static_cast<int>(std::errc::directory_not_empty) &&
-        ec.value() != static_cast<int>(std::errc::file_exists))
-      fatal(output, ec.message());
-  return handle(**bufferOrErr, input);
-}
diff --git a/src/llvm-project/llvm/tools/verify-uselistorder/verify-uselistorder.cpp b/src/llvm-project/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
index e28c33d..9afe681 100644
--- a/src/llvm-project/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
+++ b/src/llvm-project/llvm/tools/verify-uselistorder/verify-uselistorder.cpp
@@ -398,7 +398,7 @@
     return;
 
   // Generate random numbers between 10 and 99, which will line up nicely in
-  // debug output.  We're not worried about collisons here.
+  // debug output.  We're not worried about collisions here.
   LLVM_DEBUG(dbgs() << "V = "; V->dump());
   std::uniform_int_distribution<short> Dist(10, 99);
   SmallDenseMap<const Use *, short, 16> Order;
diff --git a/src/llvm-project/llvm/tools/yaml2obj/yaml2obj.cpp b/src/llvm-project/llvm/tools/yaml2obj/yaml2obj.cpp
index 8a44c44..ba1f54d 100644
--- a/src/llvm-project/llvm/tools/yaml2obj/yaml2obj.cpp
+++ b/src/llvm-project/llvm/tools/yaml2obj/yaml2obj.cpp
@@ -24,6 +24,7 @@
 #include "llvm/Support/WithColor.h"
 #include "llvm/Support/YAMLTraits.h"
 #include "llvm/Support/raw_ostream.h"
+#include <optional>
 #include <system_error>
 
 using namespace llvm;
@@ -40,6 +41,9 @@
                "definition. The syntax is <macro>=<definition>"),
       cl::cat(Cat));
 
+cl::opt<bool> PreprocessOnly("E", cl::desc("Just print the preprocessed file"),
+                             cl::cat(Cat));
+
 cl::opt<unsigned>
     DocNum("docnum", cl::init(1),
            cl::desc("Read specified document from input (default = 1)"),
@@ -56,8 +60,8 @@
                                     cl::Prefix, cl::cat(Cat));
 } // namespace
 
-static Optional<std::string> preprocess(StringRef Buf,
-                                        yaml::ErrorHandler ErrHandler) {
+static std::optional<std::string> preprocess(StringRef Buf,
+                                             yaml::ErrorHandler ErrHandler) {
   DenseMap<StringRef, StringRef> Defines;
   for (StringRef Define : D) {
     StringRef Macro, Definition;
@@ -85,7 +89,7 @@
         // When the -D option is requested, we use the provided value.
         // Otherwise we use a default macro value if present.
         auto It = Defines.find(Macro);
-        Optional<StringRef> Value;
+        std::optional<StringRef> Value;
         if (It != Defines.end())
           Value = It->second;
         else if (!Default.empty() || MacroExpr.endswith("="))
@@ -130,14 +134,20 @@
   if (!Buf)
     return 1;
 
-  Optional<std::string> Buffer = preprocess(Buf.get()->getBuffer(), ErrHandler);
+  std::optional<std::string> Buffer =
+      preprocess(Buf.get()->getBuffer(), ErrHandler);
   if (!Buffer)
     return 1;
-  yaml::Input YIn(*Buffer);
 
-  if (!convertYAML(YIn, Out->os(), ErrHandler, DocNum,
-                   MaxSize == 0 ? UINT64_MAX : MaxSize))
-    return 1;
+  if (PreprocessOnly) {
+    Out->os() << Buffer;
+  } else {
+    yaml::Input YIn(*Buffer);
+
+    if (!convertYAML(YIn, Out->os(), ErrHandler, DocNum,
+                     MaxSize == 0 ? UINT64_MAX : MaxSize))
+      return 1;
+  }
 
   Out->keep();
   Out->os().flush();