[clang] [compiler-rt] [llvm] [WIP] Advance the merger progress of #211963 (PR #216611)

via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 16 16:45:49 PDT 2026


https://github.com/zhangweize9-cyber updated https://github.com/llvm/llvm-project/pull/216611

>From 3b6ef25ffb618a937b14a555d7585c45cb96779d Mon Sep 17 00:00:00 2001
From: "A. Jiang" <de34 at live.cn>
Date: Mon, 17 Aug 2026 07:08:38 +0800
Subject: [PATCH] [libc++][test] Mark `UNSUPPORTED` for a test relying on
 `[[clang::trivial_abi]]` for compilers not supporting it (#211736)

This patch marks `UNSUPPORTED` for compilers not supporting
`[[clang::trivial_abi]]` (MSVC and GCC earlier than GCC 17) for a test
relying on this attribute.
---
 clang/lib/CodeGen/ItaniumCXXABI.cpp           | 744 +++++++++---------
 .../invalid-pointer-pairs-vector-extract.cpp  |   2 -
 .../ExecutionEngine/Orc/SymbolLookupSet.h     |  31 +-
 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp       |   4 +-
 .../AMDGPU/elementwise-fma-operand1.ll        | 100 +--
 .../ExecutionEngine/Orc/CMakeLists.txt        |   1 -
 .../Orc/SymbolLookupSetTest.cpp               | 133 ----
 .../unittests/ExecutionEngine/Orc/BUILD.gn    |   1 -
 orc-rt/include/CMakeLists.txt                 |   1 -
 orc-rt/include/orc-rt/StringPool.h            | 249 ------
 orc-rt/test/unit/CMakeLists.txt               |   1 -
 orc-rt/test/unit/StringPoolTest.cpp           | 166 ----
 12 files changed, 380 insertions(+), 1053 deletions(-)
 delete mode 100644 llvm/unittests/ExecutionEngine/Orc/SymbolLookupSetTest.cpp
 delete mode 100644 orc-rt/include/orc-rt/StringPool.h
 delete mode 100644 orc-rt/test/unit/StringPoolTest.cpp

diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index c17813140b10f..9b3f0b84dea39 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -63,12 +63,10 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   }
 
 public:
-  ItaniumCXXABI(CodeGen::CodeGenModule &CGM,
-                bool UseARMMethodPtrABI = false,
-                bool UseARMGuardVarABI = false) :
-    CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
-    UseARMGuardVarABI(UseARMGuardVarABI),
-    Use32BitVTableOffsetABI(false) { }
+  ItaniumCXXABI(CodeGen::CodeGenModule &CGM, bool UseARMMethodPtrABI = false,
+                bool UseARMGuardVarABI = false)
+      : CGCXXABI(CGM), UseARMMethodPtrABI(UseARMMethodPtrABI),
+        UseARMGuardVarABI(UseARMGuardVarABI), Use32BitVTableOffsetABI(false) {}
 
   bool classifyReturnType(CGFunctionInfo &FI) const override;
 
@@ -130,12 +128,10 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   llvm::Type *ConvertMemberPointerType(const MemberPointerType *MPT) override;
 
   CGCallee
-    EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF,
-                                    const Expr *E,
-                                    Address This,
-                                    llvm::Value *&ThisPtrForCall,
-                                    llvm::Value *MemFnPtr,
-                                    const MemberPointerType *MPT) override;
+  EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, const Expr *E,
+                                  Address This, llvm::Value *&ThisPtrForCall,
+                                  llvm::Value *MemFnPtr,
+                                  const MemberPointerType *MPT) override;
 
   llvm::Value *EmitMemberDataPointerAddress(CodeGenFunction &CGF, const Expr *E,
                                             Address Base, llvm::Value *MemPtr,
@@ -157,14 +153,14 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   llvm::Constant *BuildMemberPointer(const CXXMethodDecl *MD,
                                      CharUnits ThisAdjustment);
 
-  llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF,
-                                           llvm::Value *L, llvm::Value *R,
+  llvm::Value *EmitMemberPointerComparison(CodeGenFunction &CGF, llvm::Value *L,
+                                           llvm::Value *R,
                                            const MemberPointerType *MPT,
                                            bool Inequality) override;
 
-  llvm::Value *EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
-                                         llvm::Value *Addr,
-                                         const MemberPointerType *MPT) override;
+  llvm::Value *
+  EmitMemberPointerIsNotNull(CodeGenFunction &CGF, llvm::Value *Addr,
+                             const MemberPointerType *MPT) override;
 
   void emitVirtualObjectDelete(CodeGenFunction &CGF, const CXXDeleteExpr *DE,
                                Address Ptr, QualType ElementType,
@@ -261,9 +257,9 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   bool EmitBadCastCall(CodeGenFunction &CGF) override;
 
   llvm::Value *
-    GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
-                              const CXXRecordDecl *ClassDecl,
-                              const CXXRecordDecl *BaseClassDecl) override;
+  GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
+                            const CXXRecordDecl *ClassDecl,
+                            const CXXRecordDecl *BaseClassDecl) override;
 
   void EmitCXXConstructors(const CXXConstructorDecl *D) override;
 
@@ -369,17 +365,16 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   }
 
   StringRef GetPureVirtualCallName() override { return "__cxa_pure_virtual"; }
-  StringRef GetDeletedVirtualCallName() override
-    { return "__cxa_deleted_virtual"; }
+  StringRef GetDeletedVirtualCallName() override {
+    return "__cxa_deleted_virtual";
+  }
 
   CharUnits getArrayCookieSizeImpl(QualType elementType) override;
-  Address InitializeArrayCookie(CodeGenFunction &CGF,
-                                Address NewPtr,
+  Address InitializeArrayCookie(CodeGenFunction &CGF, Address NewPtr,
                                 llvm::Value *NumElements,
                                 const CXXNewExpr *expr,
                                 QualType ElementType) override;
-  llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
-                                   Address allocPtr,
+  llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, Address allocPtr,
                                    CharUnits cookieSize) override;
 
   void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
@@ -392,14 +387,12 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   llvm::Function *getOrCreateThreadLocalWrapper(const VarDecl *VD,
                                                 llvm::Value *Val);
   void EmitThreadLocalInitFuncs(
-      CodeGenModule &CGM,
-      ArrayRef<const VarDecl *> CXXThreadLocals,
+      CodeGenModule &CGM, ArrayRef<const VarDecl *> CXXThreadLocals,
       ArrayRef<llvm::Function *> CXXThreadLocalInits,
       ArrayRef<const VarDecl *> CXXThreadLocalInitVars) override;
 
   bool usesThreadWrapperFunction(const VarDecl *VD) const override {
-    return !isEmittedWithConstantInitializer(VD) ||
-           mayNeedDestruction(VD);
+    return !isEmittedWithConstantInitializer(VD) || mayNeedDestruction(VD);
   }
   LValue EmitThreadLocalVarDeclLValue(CodeGenFunction &CGF, const VarDecl *VD,
                                       QualType LValType) override;
@@ -446,43 +439,43 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
   LoadVTablePtr(CodeGenFunction &CGF, Address This,
                 const CXXRecordDecl *RD) override;
 
- private:
-   llvm::Constant *
-   getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD);
-
-   bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
-     const auto &VtableLayout =
-         CGM.getItaniumVTableContext().getVTableLayout(RD);
-
-     for (const auto &VtableComponent : VtableLayout.vtable_components()) {
-       // Skip empty slot.
-       if (!VtableComponent.isUsedFunctionPointerKind())
-         continue;
-
-       const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
-       const FunctionDecl *FD = Method->getDefinition();
-       const bool IsInlined =
-           Method->getCanonicalDecl()->isInlined() || (FD && FD->isInlined());
-       if (!IsInlined)
-         continue;
-
-       StringRef Name = CGM.getMangledName(
-           VtableComponent.getGlobalDecl(/*HasVectorDeletingDtors=*/false));
-       auto *Entry = CGM.GetGlobalValue(Name);
-       // This checks if virtual inline function has already been emitted.
-       // Note that it is possible that this inline function would be emitted
-       // after trying to emit vtable speculatively. Because of this we do
-       // an extra pass after emitting all deferred vtables to find and emit
-       // these vtables opportunistically.
-       if (!Entry || Entry->isDeclaration())
-         return true;
-     }
-     return false;
+private:
+  llvm::Constant *
+  getSignedVirtualMemberFunctionPointer(const CXXMethodDecl *MD);
+
+  bool hasAnyUnusedVirtualInlineFunction(const CXXRecordDecl *RD) const {
+    const auto &VtableLayout =
+        CGM.getItaniumVTableContext().getVTableLayout(RD);
+
+    for (const auto &VtableComponent : VtableLayout.vtable_components()) {
+      // Skip empty slot.
+      if (!VtableComponent.isUsedFunctionPointerKind())
+        continue;
+
+      const CXXMethodDecl *Method = VtableComponent.getFunctionDecl();
+      const FunctionDecl *FD = Method->getDefinition();
+      const bool IsInlined =
+          Method->getCanonicalDecl()->isInlined() || (FD && FD->isInlined());
+      if (!IsInlined)
+        continue;
+
+      StringRef Name = CGM.getMangledName(
+          VtableComponent.getGlobalDecl(/*HasVectorDeletingDtors=*/false));
+      auto *Entry = CGM.GetGlobalValue(Name);
+      // This checks if virtual inline function has already been emitted.
+      // Note that it is possible that this inline function would be emitted
+      // after trying to emit vtable speculatively. Because of this we do
+      // an extra pass after emitting all deferred vtables to find and emit
+      // these vtables opportunistically.
+      if (!Entry || Entry->isDeclaration())
+        return true;
+    }
+    return false;
   }
 
   bool isVTableHidden(const CXXRecordDecl *RD) const {
     const auto &VtableLayout =
-            CGM.getItaniumVTableContext().getVTableLayout(RD);
+        CGM.getItaniumVTableContext().getVTableLayout(RD);
 
     for (const auto &VtableComponent : VtableLayout.vtable_components()) {
       if (VtableComponent.isRTTIKind()) {
@@ -502,9 +495,9 @@ class ItaniumCXXABI : public CodeGen::CGCXXABI {
 
 class ARMCXXABI : public ItaniumCXXABI {
 public:
-  ARMCXXABI(CodeGen::CodeGenModule &CGM) :
-    ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
-                  /*UseARMGuardVarABI=*/true) {}
+  ARMCXXABI(CodeGen::CodeGenModule &CGM)
+      : ItaniumCXXABI(CGM, /*UseARMMethodPtrABI=*/true,
+                      /*UseARMGuardVarABI=*/true) {}
 
   bool constructorsAndDestructorsReturnThis() const override { return true; }
 
@@ -512,8 +505,7 @@ class ARMCXXABI : public ItaniumCXXABI {
                            QualType ResTy) override;
 
   CharUnits getArrayCookieSizeImpl(QualType elementType) override;
-  Address InitializeArrayCookie(CodeGenFunction &CGF,
-                                Address NewPtr,
+  Address InitializeArrayCookie(CodeGenFunction &CGF, Address NewPtr,
                                 llvm::Value *NumElements,
                                 const CXXNewExpr *expr,
                                 QualType ElementType) override;
@@ -533,8 +525,7 @@ class AppleARM64CXXABI : public ARMCXXABI {
 
 class FuchsiaCXXABI final : public ItaniumCXXABI {
 public:
-  explicit FuchsiaCXXABI(CodeGen::CodeGenModule &CGM)
-      : ItaniumCXXABI(CGM) {}
+  explicit FuchsiaCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM) {}
 
 private:
   bool constructorsAndDestructorsReturnThis() const override { return true; }
@@ -557,8 +548,7 @@ class WebAssemblyCXXABI final : public ItaniumCXXABI {
 
 class XLCXXABI final : public ItaniumCXXABI {
 public:
-  explicit XLCXXABI(CodeGen::CodeGenModule &CGM)
-      : ItaniumCXXABI(CGM) {}
+  explicit XLCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM) {}
 
   void registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
                           llvm::FunctionCallee dtor,
@@ -570,7 +560,7 @@ class XLCXXABI final : public ItaniumCXXABI {
   void emitCXXStermFinalizer(const VarDecl &D, llvm::Function *dtorStub,
                              llvm::Constant *addr);
 };
-}
+} // namespace
 
 CodeGen::CGCXXABI *CodeGen::CreateItaniumCXXABI(CodeGenModule &CGM) {
   switch (CGM.getContext().getCXXABIKind()) {
@@ -641,8 +631,8 @@ ItaniumCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) {
 /// the function to call.
 CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
     CodeGenFunction &CGF, const Expr *E, Address ThisAddr,
-    llvm::Value *&ThisPtrForCall,
-    llvm::Value *MemFnPtr, const MemberPointerType *MPT) {
+    llvm::Value *&ThisPtrForCall, llvm::Value *MemFnPtr,
+    const MemberPointerType *MPT) {
   CGBuilderTy &Builder = CGF.Builder;
 
   const FunctionProtoType *FPT =
@@ -689,9 +679,8 @@ CGCallee ItaniumCXXABI::EmitLoadOfMemberFunctionPointer(
 
   // Cast the adjusted this to a pointer to vtable pointer and load.
   llvm::Type *VTableTy = CGF.CGM.GlobalsInt8PtrTy;
-  CharUnits VTablePtrAlign =
-    CGF.CGM.getDynamicOffsetAlignment(ThisAddr.getAlignment(), RD,
-                                      CGF.getPointerAlign());
+  CharUnits VTablePtrAlign = CGF.CGM.getDynamicOffsetAlignment(
+      ThisAddr.getAlignment(), RD, CGF.getPointerAlign());
   llvm::Value *VTable = CGF.GetVTablePtr(
       Address(This, ThisAddr.getElementType(), VTablePtrAlign), VTableTy, RD);
 
@@ -953,10 +942,9 @@ static llvm::Constant *pointerAuthResignConstant(
 /// MP when the derived MP does not point to a member of the base.
 /// This is why -1 is a reasonable choice for null data member
 /// pointers.
-llvm::Value *
-ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
-                                           const CastExpr *E,
-                                           llvm::Value *src) {
+llvm::Value *ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
+                                                        const CastExpr *E,
+                                                        llvm::Value *src) {
   // Use constant emission if we can.
   if (isa<llvm::Constant>(src))
     return EmitMemberPointerConversion(E, cast<llvm::Constant>(src));
@@ -1009,15 +997,16 @@ ItaniumCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF,
   }
 
   // Under Itanium, reinterprets don't require any additional processing.
-  if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
+  if (E->getCastKind() == CK_ReinterpretMemberPointer)
+    return src;
 
   llvm::Constant *adj = getMemberPointerAdjustment(E);
-  if (!adj) return src;
+  if (!adj)
+    return src;
 
   bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
 
-  const MemberPointerType *destTy =
-    E->getType()->castAs<MemberPointerType>();
+  const MemberPointerType *destTy = E->getType()->castAs<MemberPointerType>();
 
   // For member data pointers, this is just a matter of adding the
   // offset if the source is non-null.
@@ -1093,22 +1082,24 @@ ItaniumCXXABI::EmitMemberPointerConversion(const CastExpr *E,
         src, DstType, E->getSubExpr()->getType(), CGM);
 
   // Under Itanium, reinterprets don't require any additional processing.
-  if (E->getCastKind() == CK_ReinterpretMemberPointer) return src;
+  if (E->getCastKind() == CK_ReinterpretMemberPointer)
+    return src;
 
   // If the adjustment is trivial, we don't need to do anything.
   llvm::Constant *adj = getMemberPointerAdjustment(E);
-  if (!adj) return src;
+  if (!adj)
+    return src;
 
   bool isDerivedToBase = (E->getCastKind() == CK_DerivedToBaseMemberPointer);
 
-  const MemberPointerType *destTy =
-    E->getType()->castAs<MemberPointerType>();
+  const MemberPointerType *destTy = E->getType()->castAs<MemberPointerType>();
 
   // For member data pointers, this is just a matter of adding the
   // offset if the source is non-null.
   if (destTy->isMemberDataPointer()) {
     // null maps to null.
-    if (src->isAllOnesValue()) return src;
+    if (src->isAllOnesValue())
+      return src;
 
     if (isDerivedToBase)
       return llvm::ConstantExpr::getNSWSub(src, adj);
@@ -1143,7 +1134,7 @@ ItaniumCXXABI::EmitNullMemberPointer(const MemberPointerType *MPT) {
     return llvm::ConstantInt::get(CGM.PtrDiffTy, -1ULL, /*isSigned=*/true);
 
   llvm::Constant *Zero = llvm::ConstantInt::get(CGM.PtrDiffTy, 0);
-  llvm::Constant *Values[2] = { Zero, Zero };
+  llvm::Constant *Values[2] = {Zero, Zero};
   return llvm::ConstantStruct::getAnon(Values);
 }
 
@@ -1221,8 +1212,8 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
       //   virtual table offset (in bytes) of the function,
       //   represented as a ptrdiff_t.
       MemPtr[0] = llvm::ConstantInt::get(CGM.PtrDiffTy, VTableOffset + 1);
-      MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
-                                         ThisAdjustment.getQuantity());
+      MemPtr[1] =
+          llvm::ConstantInt::get(CGM.PtrDiffTy, ThisAdjustment.getQuantity());
     }
   } else {
     const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>();
@@ -1239,9 +1230,9 @@ llvm::Constant *ItaniumCXXABI::BuildMemberPointer(const CXXMethodDecl *MD,
     llvm::Constant *addr = CGM.getMemberFunctionPointer(MD, Ty);
 
     MemPtr[0] = llvm::ConstantExpr::getPtrToInt(addr, CGM.PtrDiffTy);
-    MemPtr[1] = llvm::ConstantInt::get(CGM.PtrDiffTy,
-                                       (UseARMMethodPtrABI ? 2 : 1) *
-                                       ThisAdjustment.getQuantity());
+    MemPtr[1] =
+        llvm::ConstantInt::get(CGM.PtrDiffTy, (UseARMMethodPtrABI ? 2 : 1) *
+                                                  ThisAdjustment.getQuantity());
   }
 
   return llvm::ConstantStruct::getAnon(MemPtr);
@@ -1265,7 +1256,7 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
 
   getContext().recordMemberDataPointerEvaluation(MPD);
   CharUnits FieldOffset =
-    getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
+      getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD));
   return EmitMemberDataPointer(MPT, ThisAdjustment + FieldOffset);
 }
 
@@ -1273,12 +1264,9 @@ llvm::Constant *ItaniumCXXABI::EmitMemberPointer(const APValue &MP,
 /// the same if they're either bitwise identical *or* both null.
 ///
 /// ARM is different here only because null-ness is more complicated.
-llvm::Value *
-ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
-                                           llvm::Value *L,
-                                           llvm::Value *R,
-                                           const MemberPointerType *MPT,
-                                           bool Inequality) {
+llvm::Value *ItaniumCXXABI::EmitMemberPointerComparison(
+    CodeGenFunction &CGF, llvm::Value *L, llvm::Value *R,
+    const MemberPointerType *MPT, bool Inequality) {
   CGBuilderTy &Builder = CGF.Builder;
 
   llvm::ICmpInst::Predicate Eq;
@@ -1335,8 +1323,8 @@ ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
     // Compute (l.adj | r.adj) & 1 and test it against zero.
     llvm::Value *OrAdj = Builder.CreateOr(LAdj, RAdj, "or.adj");
     llvm::Value *OrAdjAnd1 = Builder.CreateAnd(OrAdj, One);
-    llvm::Value *OrAdjAnd1EqZero = Builder.CreateICmp(Eq, OrAdjAnd1, Zero,
-                                                      "cmp.or.adj");
+    llvm::Value *OrAdjAnd1EqZero =
+        Builder.CreateICmp(Eq, OrAdjAnd1, Zero, "cmp.or.adj");
     EqZero = Builder.CreateBinOp(And, EqZero, OrAdjAnd1EqZero);
   }
 
@@ -1347,17 +1335,15 @@ ItaniumCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF,
   return Result;
 }
 
-llvm::Value *
-ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
-                                          llvm::Value *MemPtr,
-                                          const MemberPointerType *MPT) {
+llvm::Value *ItaniumCXXABI::EmitMemberPointerIsNotNull(
+    CodeGenFunction &CGF, llvm::Value *MemPtr, const MemberPointerType *MPT) {
   CGBuilderTy &Builder = CGF.Builder;
 
   /// For member data pointers, this is just a check against -1.
   if (MPT->isMemberDataPointer()) {
     assert(MemPtr->getType() == CGM.PtrDiffTy);
     llvm::Value *NegativeOne =
-      llvm::Constant::getAllOnesValue(MemPtr->getType());
+        llvm::Constant::getAllOnesValue(MemPtr->getType());
     return Builder.CreateICmpNE(MemPtr, NegativeOne, "memptr.tobool");
   }
 
@@ -1373,8 +1359,8 @@ ItaniumCXXABI::EmitMemberPointerIsNotNull(CodeGenFunction &CGF,
     llvm::Constant *One = llvm::ConstantInt::get(Ptr->getType(), 1);
     llvm::Value *Adj = Builder.CreateExtractValue(MemPtr, 1, "memptr.adj");
     llvm::Value *VirtualBit = Builder.CreateAnd(Adj, One, "memptr.virtualbit");
-    llvm::Value *IsVirtual = Builder.CreateICmpNE(VirtualBit, Zero,
-                                                  "memptr.isvirtual");
+    llvm::Value *IsVirtual =
+        Builder.CreateICmpNE(VirtualBit, Zero, "memptr.isvirtual");
     Result = Builder.CreateOr(Result, IsVirtual);
   }
 
@@ -1409,8 +1395,7 @@ bool ItaniumCXXABI::isZeroInitializable(const MemberPointerType *MPT) {
 /// at entry -2 in the vtable.
 void ItaniumCXXABI::emitVirtualObjectDelete(CodeGenFunction &CGF,
                                             const CXXDeleteExpr *DE,
-                                            Address Ptr,
-                                            QualType ElementType,
+                                            Address Ptr, QualType ElementType,
                                             const CXXDestructorDecl *Dtor) {
   bool UseGlobalDelete = DE->isGlobalDelete();
   if (UseGlobalDelete) {
@@ -1452,7 +1437,7 @@ void ItaniumCXXABI::emitRethrow(CodeGenFunction &CGF, bool isNoReturn) {
   // void __cxa_rethrow();
 
   llvm::FunctionType *FTy =
-    llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
+      llvm::FunctionType::get(CGM.VoidTy, /*isVarArg=*/false);
 
   llvm::FunctionCallee Fn = CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow");
 
@@ -1466,7 +1451,7 @@ static llvm::FunctionCallee getAllocateExceptionFn(CodeGenModule &CGM) {
   // void *__cxa_allocate_exception(size_t thrown_size);
 
   llvm::FunctionType *FTy =
-    llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*isVarArg=*/false);
+      llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*isVarArg=*/false);
 
   return CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception");
 }
@@ -1475,9 +1460,9 @@ static llvm::FunctionCallee getThrowFn(CodeGenModule &CGM) {
   // void __cxa_throw(void *thrown_exception, std::type_info *tinfo,
   //                  void (*dest) (void *));
 
-  llvm::Type *Args[3] = { CGM.Int8PtrTy, CGM.GlobalsInt8PtrTy, CGM.Int8PtrTy };
+  llvm::Type *Args[3] = {CGM.Int8PtrTy, CGM.GlobalsInt8PtrTy, CGM.Int8PtrTy};
   llvm::FunctionType *FTy =
-    llvm::FunctionType::get(CGM.VoidTy, Args, /*isVarArg=*/false);
+      llvm::FunctionType::get(CGM.VoidTy, Args, /*isVarArg=*/false);
 
   return CGM.CreateRuntimeFunction(FTy, "__cxa_throw");
 }
@@ -1493,8 +1478,8 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
       AllocExceptionFn, llvm::ConstantInt::get(SizeTy, TypeSize), "exception");
 
   CharUnits ExnAlign = CGF.getContext().getExnObjectAlignment();
-  CGF.EmitAnyExprToExn(
-      E->getSubExpr(), Address(ExceptionPtr, CGM.Int8Ty, ExnAlign));
+  CGF.EmitAnyExprToExn(E->getSubExpr(),
+                       Address(ExceptionPtr, CGM.Int8Ty, ExnAlign));
 
   // Now throw the exception.
   llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType,
@@ -1516,9 +1501,10 @@ void ItaniumCXXABI::emitThrow(CodeGenFunction &CGF, const CXXThrowExpr *E) {
     Dtor = CGM.getAddrOfCXXStructor(GlobalDecl(DtorD, Dtor_Complete));
     Dtor = CGM.getFunctionPointer(Dtor, DtorTy);
   }
-  if (!Dtor) Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
+  if (!Dtor)
+    Dtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
 
-  llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor };
+  llvm::Value *args[] = {ExceptionPtr, TypeInfo, Dtor};
   CGF.EmitNoreturnRuntimeCallOrInvoke(getThrowFn(CGM), args);
 }
 
@@ -1531,9 +1517,9 @@ static llvm::FunctionCallee getItaniumDynamicCastFn(CodeGenFunction &CGF) {
   llvm::Type *Int8PtrTy = CGF.Int8PtrTy;
   llvm::Type *GlobInt8PtrTy = CGF.GlobalsInt8PtrTy;
   llvm::Type *PtrDiffTy =
-    CGF.ConvertType(CGF.getContext().getPointerDiffType());
+      CGF.ConvertType(CGF.getContext().getPointerDiffType());
 
-  llvm::Type *Args[4] = { Int8PtrTy, GlobInt8PtrTy, GlobInt8PtrTy, PtrDiffTy };
+  llvm::Type *Args[4] = {Int8PtrTy, GlobInt8PtrTy, GlobInt8PtrTy, PtrDiffTy};
 
   llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
 
@@ -1572,7 +1558,7 @@ static CharUnits computeOffsetHint(ASTContext &Context,
 
   // Now walk all possible inheritance paths.
   for (const CXXBasePath &Path : Paths) {
-    if (Path.Access != AS_public)  // Ignore non-public inheritance.
+    if (Path.Access != AS_public) // Ignore non-public inheritance.
       continue;
 
     ++NumPublicPaths;
@@ -1625,12 +1611,11 @@ void ItaniumCXXABI::EmitBadTypeidCall(CodeGenFunction &CGF) {
 }
 
 llvm::Value *ItaniumCXXABI::EmitTypeid(CodeGenFunction &CGF,
-                                       QualType SrcRecordTy,
-                                       Address ThisPtr,
+                                       QualType SrcRecordTy, Address ThisPtr,
                                        llvm::Type *StdTypeInfoPtrTy) {
   auto *ClassDecl = SrcRecordTy->castAsCXXRecordDecl();
-  llvm::Value *Value = CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy,
-                                        ClassDecl);
+  llvm::Value *Value =
+      CGF.GetVTablePtr(ThisPtr, CGM.GlobalsInt8PtrTy, ClassDecl);
 
   if (CGM.getLangOpts().RelativeCXXABIVTables) {
     // Load the type info.
@@ -1879,24 +1864,22 @@ bool ItaniumCXXABI::EmitBadCastCall(CodeGenFunction &CGF) {
 }
 
 llvm::Value *
-ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,
-                                         Address This,
+ItaniumCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF, Address This,
                                          const CXXRecordDecl *ClassDecl,
                                          const CXXRecordDecl *BaseClassDecl) {
   llvm::Value *VTablePtr = CGF.GetVTablePtr(This, CGM.Int8PtrTy, ClassDecl);
   CharUnits VBaseOffsetOffset =
       CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(ClassDecl,
                                                                BaseClassDecl);
-  llvm::Value *VBaseOffsetPtr =
-    CGF.Builder.CreateConstGEP1_64(
-        CGF.Int8Ty, VTablePtr, VBaseOffsetOffset.getQuantity(),
-        "vbase.offset.ptr");
+  llvm::Value *VBaseOffsetPtr = CGF.Builder.CreateConstGEP1_64(
+      CGF.Int8Ty, VTablePtr, VBaseOffsetOffset.getQuantity(),
+      "vbase.offset.ptr");
 
   llvm::Value *VBaseOffset;
   if (CGM.getLangOpts().RelativeCXXABIVTables) {
-    VBaseOffset = CGF.Builder.CreateAlignedLoad(
-        CGF.Int32Ty, VBaseOffsetPtr, CharUnits::fromQuantity(4),
-        "vbase.offset");
+    VBaseOffset = CGF.Builder.CreateAlignedLoad(CGF.Int32Ty, VBaseOffsetPtr,
+                                                CharUnits::fromQuantity(4),
+                                                "vbase.offset");
   } else {
     VBaseOffset = CGF.Builder.CreateAlignedLoad(
         CGM.PtrDiffTy, VBaseOffsetPtr, CGF.getPointerAlign(), "vbase.offset");
@@ -2041,8 +2024,8 @@ void ItaniumCXXABI::EmitDestructorCall(CodeGenFunction &CGF,
   QualType VTTTy = getContext().getPointerType(getContext().VoidPtrTy);
 
   CGCallee Callee;
-  if (getContext().getLangOpts().AppleKext &&
-      Type != Dtor_Base && DD->isVirtual())
+  if (getContext().getLangOpts().AppleKext && Type != Dtor_Base &&
+      DD->isVirtual())
     Callee = CGF.BuildAppleKextVirtualDestructorCall(DD, Type, DD->getParent());
   else
     Callee = CGCallee::forDirect(CGM.getAddrOfCXXStructor(GD), GD);
@@ -2192,9 +2175,9 @@ ItaniumCXXABI::getVTableAddressPoint(BaseSubobject Base,
   VTableLayout::AddressPointLocation AddressPoint =
       Layout.getAddressPoint(Base);
   llvm::Value *Indices[] = {
-    llvm::ConstantInt::get(CGM.Int32Ty, 0),
-    llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),
-    llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
+      llvm::ConstantInt::get(CGM.Int32Ty, 0),
+      llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.VTableIndex),
+      llvm::ConstantInt::get(CGM.Int32Ty, AddressPoint.AddressPointIndex),
   };
 
   // Add inrange attribute to indicate that only the VTableIndex can be
@@ -2228,13 +2211,15 @@ llvm::Value *ItaniumCXXABI::getVTableAddressPointInStructorWithVTT(
                                                  VirtualPointerIndex);
 
   // And load the address point from the VTT.
-  llvm::Value *AP =
-      CGF.Builder.CreateAlignedLoad(CGF.GlobalsVoidPtrTy, VTT,
-                                    CGF.getPointerAlign());
-
-  if (auto PointerAuth = CGM.getVTablePointerAuthInfo(&CGF, VTableClass, VTT,
-                                                      /*IsVTTEntry=*/true))
-    AP = CGF.EmitPointerAuthAuth(*PointerAuth, AP);
+  llvm::Value *AP = CGF.Builder.CreateAlignedLoad(CGF.GlobalsVoidPtrTy, VTT,
+                                                  CGF.getPointerAlign());
+
+  if (auto &Schema =
+          CGF.CGM.getCodeGenOpts().PointerAuth.CXXVTTVTablePointers) {
+    CGPointerAuthInfo PointerAuth =
+        CGF.EmitPointerAuthInfo(Schema, VTT, GlobalDecl(), QualType());
+    AP = CGF.EmitPointerAuthAuth(PointerAuth, AP);
+  }
 
   return AP;
 }
@@ -2277,8 +2262,7 @@ llvm::GlobalVariable *ItaniumCXXABI::getAddrOfVTable(const CXXRecordDecl *RD,
 }
 
 CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
-                                                  GlobalDecl GD,
-                                                  Address This,
+                                                  GlobalDecl GD, Address This,
                                                   llvm::Type *Ty,
                                                   SourceLocation Loc) {
   llvm::Type *PtrTy = CGM.GlobalsInt8PtrTy;
@@ -2350,8 +2334,10 @@ CGCallee ItaniumCXXABI::getVirtualFunctionPointer(CodeGenFunction &CGF,
   CGPointerAuthInfo PointerAuth;
   if (Schema) {
     assert(VTableSlotPtr && "virtual function pointer not set");
-    GD = CGM.getItaniumVTableContext().findOriginalMethod(GD.getCanonicalDecl());
-    PointerAuth = CGF.EmitPointerAuthInfo(Schema, VTableSlotPtr, GD, QualType());
+    GD =
+        CGM.getItaniumVTableContext().findOriginalMethod(GD.getCanonicalDecl());
+    PointerAuth =
+        CGF.EmitPointerAuthInfo(Schema, VTableSlotPtr, GD, QualType());
   }
   CGCallee Callee(GD, VFunc, PointerAuth);
   return Callee;
@@ -2473,8 +2459,8 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
 
   // In a base-to-derived cast, the non-virtual adjustment is applied first.
   if (NonVirtualAdjustment && !IsReturnAdjustment) {
-    V = CGF.Builder.CreateConstInBoundsByteGEP(V,
-                              CharUnits::fromQuantity(NonVirtualAdjustment));
+    V = CGF.Builder.CreateConstInBoundsByteGEP(
+        V, CharUnits::fromQuantity(NonVirtualAdjustment));
   }
 
   // Perform the virtual adjustment if we have one.
@@ -2488,9 +2474,8 @@ static llvm::Value *performTypeAdjustment(CodeGenFunction &CGF,
         CGF.Int8Ty, VTablePtr, VirtualAdjustment);
     if (CGF.CGM.getLangOpts().RelativeCXXABIVTables) {
       // Load the adjustment offset from the vtable as a 32-bit int.
-      Offset =
-          CGF.Builder.CreateAlignedLoad(CGF.Int32Ty, OffsetPtr,
-                                        CharUnits::fromQuantity(4));
+      Offset = CGF.Builder.CreateAlignedLoad(CGF.Int32Ty, OffsetPtr,
+                                             CharUnits::fromQuantity(4));
     } else {
       llvm::Type *PtrDiffTy =
           CGF.ConvertType(CGF.getContext().getPointerDiffType());
@@ -2534,8 +2519,8 @@ ItaniumCXXABI::performReturnAdjustment(CodeGenFunction &CGF, Address Ret,
                                /*IsReturnAdjustment=*/true);
 }
 
-void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF,
-                                    RValue RV, QualType ResultType) {
+void ARMCXXABI::EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV,
+                                    QualType ResultType) {
   if (!isa<CXXDestructorDecl>(CGF.CurGD.getDecl()))
     return ItaniumCXXABI::EmitReturnFromThunk(CGF, RV, ResultType);
 
@@ -2606,8 +2591,8 @@ llvm::Value *ItaniumCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
   Address numElementsPtr = allocPtr;
   CharUnits numElementsOffset = cookieSize - CGF.getSizeSize();
   if (!numElementsOffset.isZero())
-    numElementsPtr =
-      CGF.Builder.CreateConstInBoundsByteGEP(numElementsPtr, numElementsOffset);
+    numElementsPtr = CGF.Builder.CreateConstInBoundsByteGEP(numElementsPtr,
+                                                            numElementsOffset);
 
   unsigned AS = allocPtr.getAddressSpace();
   numElementsPtr = numElementsPtr.withElementType(CGF.SizeTy);
@@ -2638,8 +2623,7 @@ CharUnits ARMCXXABI::getArrayCookieSizeImpl(QualType elementType) {
                   CGM.getContext().getTypeAlignInChars(elementType));
 }
 
-Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
-                                         Address newPtr,
+Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF, Address newPtr,
                                          llvm::Value *numElements,
                                          const CXXNewExpr *expr,
                                          QualType elementType) {
@@ -2650,8 +2634,8 @@ Address ARMCXXABI::InitializeArrayCookie(CodeGenFunction &CGF,
 
   // The first element is the element size.
   cookie = cookie.withElementType(CGF.SizeTy);
-  llvm::Value *elementSize = llvm::ConstantInt::get(CGF.SizeTy,
-                 getContext().getTypeSizeInChars(elementType).getQuantity());
+  llvm::Value *elementSize = llvm::ConstantInt::get(
+      CGF.SizeTy, getContext().getTypeSizeInChars(elementType).getQuantity());
   CGF.Builder.CreateStore(elementSize, cookie);
 
   // The second element is the element count.
@@ -2669,8 +2653,8 @@ llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
                                             CharUnits cookieSize) {
   // The number of elements is at offset sizeof(size_t) relative to
   // the allocated pointer.
-  Address numElementsPtr
-    = CGF.Builder.CreateConstInBoundsByteGEP(allocPtr, CGF.getSizeSize());
+  Address numElementsPtr =
+      CGF.Builder.CreateConstInBoundsByteGEP(allocPtr, CGF.getSizeSize());
 
   numElementsPtr = numElementsPtr.withElementType(CGF.SizeTy);
   return CGF.Builder.CreateLoad(numElementsPtr);
@@ -2681,9 +2665,9 @@ llvm::Value *ARMCXXABI::readArrayCookieImpl(CodeGenFunction &CGF,
 static llvm::FunctionCallee getGuardAcquireFn(CodeGenModule &CGM,
                                               llvm::PointerType *GuardPtrTy) {
   // int __cxa_guard_acquire(__guard *guard_object);
-  llvm::FunctionType *FTy =
-    llvm::FunctionType::get(CGM.getTypes().ConvertType(CGM.getContext().IntTy),
-                            GuardPtrTy, /*isVarArg=*/false);
+  llvm::FunctionType *FTy = llvm::FunctionType::get(
+      CGM.getTypes().ConvertType(CGM.getContext().IntTy), GuardPtrTy,
+      /*isVarArg=*/false);
   return CGM.CreateRuntimeFunction(
       FTy, "__cxa_guard_acquire",
       llvm::AttributeList::get(CGM.getLLVMContext(),
@@ -2695,7 +2679,7 @@ static llvm::FunctionCallee getGuardReleaseFn(CodeGenModule &CGM,
                                               llvm::PointerType *GuardPtrTy) {
   // void __cxa_guard_release(__guard *guard_object);
   llvm::FunctionType *FTy =
-    llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
+      llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
   return CGM.CreateRuntimeFunction(
       FTy, "__cxa_guard_release",
       llvm::AttributeList::get(CGM.getLLVMContext(),
@@ -2707,7 +2691,7 @@ static llvm::FunctionCallee getGuardAbortFn(CodeGenModule &CGM,
                                             llvm::PointerType *GuardPtrTy) {
   // void __cxa_guard_abort(__guard *guard_object);
   llvm::FunctionType *FTy =
-    llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
+      llvm::FunctionType::get(CGM.VoidTy, GuardPtrTy, /*isVarArg=*/false);
   return CGM.CreateRuntimeFunction(
       FTy, "__cxa_guard_abort",
       llvm::AttributeList::get(CGM.getLLVMContext(),
@@ -2716,21 +2700,20 @@ static llvm::FunctionCallee getGuardAbortFn(CodeGenModule &CGM,
 }
 
 namespace {
-  struct CallGuardAbort final : EHScopeStack::Cleanup {
-    llvm::GlobalVariable *Guard;
-    CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
+struct CallGuardAbort final : EHScopeStack::Cleanup {
+  llvm::GlobalVariable *Guard;
+  CallGuardAbort(llvm::GlobalVariable *Guard) : Guard(Guard) {}
 
-    void Emit(CodeGenFunction &CGF, Flags flags) override {
-      CGF.EmitNounwindRuntimeCall(getGuardAbortFn(CGF.CGM, Guard->getType()),
-                                  Guard);
-    }
-  };
-}
+  void Emit(CodeGenFunction &CGF, Flags flags) override {
+    CGF.EmitNounwindRuntimeCall(getGuardAbortFn(CGF.CGM, Guard->getType()),
+                                Guard);
+  }
+};
+} // namespace
 
 /// The ARM code here follows the Itanium code closely enough that we
 /// just special-case it at particular places.
-void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
-                                    const VarDecl &D,
+void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
                                     llvm::GlobalVariable *var,
                                     bool shouldPerformInit) {
   CGBuilderTy &Builder = CGF.Builder;
@@ -2787,10 +2770,9 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
     // Create the guard variable with a zero-initializer.
     // Just absorb linkage, visibility and dll storage class  from the guarded
     // variable.
-    guard = new llvm::GlobalVariable(CGM.getModule(), guardTy,
-                                     false, var->getLinkage(),
-                                     llvm::ConstantInt::get(guardTy, 0),
-                                     guardName.str());
+    guard = new llvm::GlobalVariable(
+        CGM.getModule(), guardTy, false, var->getLinkage(),
+        llvm::ConstantInt::get(guardTy, 0), guardName.str());
     guard->setDSOLocal(var->isDSOLocal());
     guard->setVisibility(var->getVisibility());
     guard->setDLLStorageClass(var->getDLLStorageClass());
@@ -2870,8 +2852,8 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
     //
     // ARM64 C++ ABI 3.2.2:
     //   This ABI instead only specifies the value bit 0 of the static guard
-    //   variable; all other bits are platform defined. Bit 0 shall be 0 when the
-    //   variable is not initialized and 1 when it is.
+    //   variable; all other bits are platform defined. Bit 0 shall be 0 when
+    //   the variable is not initialized and 1 when it is.
     llvm::Value *V =
         (UseARMGuardVarABI && !useInt8GuardVariable)
             ? Builder.CreateAnd(LI, llvm::ConstantInt::get(CGM.Int8Ty, 1))
@@ -2905,13 +2887,13 @@ void ItaniumCXXABI::EmitGuardedInit(CodeGenFunction &CGF,
   // Variables used when coping with thread-safe statics and exceptions.
   if (threadsafe) {
     // Call __cxa_guard_acquire.
-    llvm::Value *V
-      = CGF.EmitNounwindRuntimeCall(getGuardAcquireFn(CGM, guardPtrTy), guard);
+    llvm::Value *V =
+        CGF.EmitNounwindRuntimeCall(getGuardAcquireFn(CGM, guardPtrTy), guard);
 
     llvm::BasicBlock *InitBlock = CGF.createBasicBlock("init");
 
-    Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"),
-                         InitBlock, EndBlock);
+    Builder.CreateCondBr(Builder.CreateIsNotNull(V, "tobool"), InitBlock,
+                         EndBlock);
 
     // Call __cxa_guard_abort along the exceptional edge.
     CGF.EHStack.pushCleanup<CallGuardAbort>(EHCleanup, guard);
@@ -2957,7 +2939,7 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
   const char *Name = "__cxa_atexit";
   if (TLS) {
     const llvm::Triple &T = CGF.getTarget().getTriple();
-    Name = T.isOSDarwin() ?  "_tlv_atexit" : "__cxa_thread_atexit";
+    Name = T.isOSDarwin() ? "_tlv_atexit" : "__cxa_thread_atexit";
   }
 
   // We're assuming that the destructor function is something we can
@@ -2978,7 +2960,7 @@ static void emitGlobalDtorWithCXAAtExit(CodeGenFunction &CGF,
   // extern "C" int __cxa_atexit(void (*f)(void *), void *p, void *d);
   llvm::Type *paramTys[] = {dtorTy, AddrPtrTy, handle->getType()};
   llvm::FunctionType *atexitTy =
-    llvm::FunctionType::get(CGF.IntTy, paramTys, false);
+      llvm::FunctionType::get(CGF.IntTy, paramTys, false);
 
   // Fetch the actual function.
   llvm::FunctionCallee atexit = CGF.CGM.CreateRuntimeFunction(atexitTy, Name);
@@ -3131,7 +3113,18 @@ void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF, const VarDecl &D,
   // destructors which we can handle directly in the runtime. Note that this is
   // not strictly 1-to-1 with using `atexit` because we no longer tear down
   // globals in reverse order of when they were constructed.
-  if (!CGM.getLangOpts().hasAtExit() && !D.isStaticLocal())
+
+  // If '-fno-use-cxa-atexit' and '-fno-register-global-dtors-with-atexit' are
+  // also sepcified, this means the user does not want any invocation to
+  // __cxa_atexit or atexit, but we still have to check if the declaration is
+  // static-local or thread-local, which should not be supported by this case.
+  // As we investigated, ELF has its .fini_array section to support the global
+  // destructors. So we can safely apply this to ELF.
+  if (!CGM.getLangOpts().hasAtExit() &&
+      CGM.getTarget().getTriple().isOSBinFormatELF() &&
+      !CGM.getCodeGenOpts().CXAAtExit &&
+      !CGM.getCodeGenOpts().RegisterGlobalDtorsWithAtExit &&
+      !D.isStaticLocal() && !D.getTLSKind())
     return CGF.registerGlobalDtorWithLLVM(D, dtor, addr);
 
   // emitGlobalDtorWithCXAAtExit will emit a call to either __cxa_thread_atexit
@@ -3180,9 +3173,8 @@ getThreadLocalWrapperLinkage(const VarDecl *VD, CodeGen::CodeGenModule &CGM) {
   return llvm::GlobalValue::WeakODRLinkage;
 }
 
-llvm::Function *
-ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
-                                             llvm::Value *Val) {
+llvm::Function *ItaniumCXXABI::getOrCreateThreadLocalWrapper(const VarDecl *VD,
+                                                             llvm::Value *Val) {
   // Mangle the name for the thread_local wrapper function.
   SmallString<256> WrapperName;
   {
@@ -3362,8 +3354,7 @@ void ItaniumCXXABI::EmitThreadLocalInitFuncs(
     // This is needed whenever a thread wrapper function is not used, and
     // also when the symbol is weak.
     if (CGM.getTriple().isOSAIX() && VD->hasDefinition() &&
-        isEmittedWithConstantInitializer(VD, true) &&
-        !mayNeedDestruction(VD)) {
+        isEmittedWithConstantInitializer(VD, true) && !mayNeedDestruction(VD)) {
       // Init should be null.  If it were non-null, then the logic above would
       // either be defining the function to be an alias or declaring the
       // function with the expectation that the definition of the variable
@@ -3551,9 +3542,9 @@ ItaniumCXXABI::getOrCreateVirtualFunctionPointerThunk(const CXXMethodDecl *MD) {
 
 namespace {
 class ItaniumRTTIBuilder {
-  CodeGenModule &CGM;  // Per-module state.
+  CodeGenModule &CGM; // Per-module state.
   llvm::LLVMContext &VMContext;
-  const ItaniumCXXABI &CXXABI;  // Per-module state.
+  const ItaniumCXXABI &CXXABI; // Per-module state.
 
   /// Fields - The fields of the RTTI descriptor currently being built.
   SmallVector<llvm::Constant *, 16> Fields;
@@ -3613,7 +3604,7 @@ class ItaniumRTTIBuilder {
     PTI_ContainingClassIncomplete = 0x10,
 
     /// PTI_TransactionSafe - Pointee is transaction_safe function (C++ TM TS).
-    //PTI_TransactionSafe = 0x20,
+    // PTI_TransactionSafe = 0x20,
 
     /// PTI_Noexcept - Pointee is noexcept function (C++1z).
     PTI_Noexcept = 0x40,
@@ -3642,13 +3633,12 @@ class ItaniumRTTIBuilder {
   llvm::Constant *BuildTypeInfo(QualType Ty);
 
   /// BuildTypeInfo - Build the RTTI type info struct for the given type.
-  llvm::Constant *BuildTypeInfo(
-      QualType Ty,
-      llvm::GlobalVariable::LinkageTypes Linkage,
-      llvm::GlobalValue::VisibilityTypes Visibility,
-      llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
+  llvm::Constant *
+  BuildTypeInfo(QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage,
+                llvm::GlobalValue::VisibilityTypes Visibility,
+                llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass);
 };
-}
+} // namespace
 
 llvm::GlobalVariable *ItaniumRTTIBuilder::GetAddrOfTypeName(
     QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage) {
@@ -3731,53 +3721,50 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
 
   // Types added here must also be added to EmitFundamentalRTTIDescriptors.
   switch (Ty->getKind()) {
-    case BuiltinType::Void:
-    case BuiltinType::NullPtr:
-    case BuiltinType::Bool:
-    case BuiltinType::WChar_S:
-    case BuiltinType::WChar_U:
-    case BuiltinType::Char_U:
-    case BuiltinType::Char_S:
-    case BuiltinType::UChar:
-    case BuiltinType::SChar:
-    case BuiltinType::Short:
-    case BuiltinType::UShort:
-    case BuiltinType::Int:
-    case BuiltinType::UInt:
-    case BuiltinType::Long:
-    case BuiltinType::ULong:
-    case BuiltinType::LongLong:
-    case BuiltinType::ULongLong:
-    case BuiltinType::Half:
-    case BuiltinType::Float:
-    case BuiltinType::Double:
-    case BuiltinType::LongDouble:
-    case BuiltinType::Float16:
-    case BuiltinType::Float128:
-    case BuiltinType::Ibm128:
-    case BuiltinType::Char8:
-    case BuiltinType::Char16:
-    case BuiltinType::Char32:
-    case BuiltinType::Int128:
-    case BuiltinType::UInt128:
-      return true;
+  case BuiltinType::Void:
+  case BuiltinType::NullPtr:
+  case BuiltinType::Bool:
+  case BuiltinType::WChar_S:
+  case BuiltinType::WChar_U:
+  case BuiltinType::Char_U:
+  case BuiltinType::Char_S:
+  case BuiltinType::UChar:
+  case BuiltinType::SChar:
+  case BuiltinType::Short:
+  case BuiltinType::UShort:
+  case BuiltinType::Int:
+  case BuiltinType::UInt:
+  case BuiltinType::Long:
+  case BuiltinType::ULong:
+  case BuiltinType::LongLong:
+  case BuiltinType::ULongLong:
+  case BuiltinType::Half:
+  case BuiltinType::Float:
+  case BuiltinType::Double:
+  case BuiltinType::LongDouble:
+  case BuiltinType::Float16:
+  case BuiltinType::Float128:
+  case BuiltinType::Ibm128:
+  case BuiltinType::Char8:
+  case BuiltinType::Char16:
+  case BuiltinType::Char32:
+  case BuiltinType::Int128:
+  case BuiltinType::UInt128:
+    return true;
 
-#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
-    case BuiltinType::Id:
+#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix)                   \
+  case BuiltinType::Id:
 #include "clang/Basic/OpenCLImageTypes.def"
-#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
-    case BuiltinType::Id:
+#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) case BuiltinType::Id:
 #include "clang/Basic/OpenCLExtensionTypes.def"
-    case BuiltinType::OCLSampler:
-    case BuiltinType::OCLEvent:
-    case BuiltinType::OCLClkEvent:
-    case BuiltinType::OCLQueue:
-    case BuiltinType::OCLReserveID:
-#define SVE_TYPE(Name, Id, SingletonId) \
-    case BuiltinType::Id:
+  case BuiltinType::OCLSampler:
+  case BuiltinType::OCLEvent:
+  case BuiltinType::OCLClkEvent:
+  case BuiltinType::OCLQueue:
+  case BuiltinType::OCLReserveID:
+#define SVE_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
 #include "clang/Basic/AArch64ACLETypes.def"
-#define PPC_VECTOR_TYPE(Name, Id, Size) \
-    case BuiltinType::Id:
+#define PPC_VECTOR_TYPE(Name, Id, Size) case BuiltinType::Id:
 #include "clang/Basic/PPCTypes.def"
 #define RVV_TYPE(Name, Id, SingletonId) case BuiltinType::Id:
 #include "clang/Basic/RISCVVTypes.def"
@@ -3818,8 +3805,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
 
     case BuiltinType::Dependent:
 #define BUILTIN_TYPE(Id, SingletonId)
-#define PLACEHOLDER_TYPE(Id, SingletonId) \
-    case BuiltinType::Id:
+#define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id:
 #include "clang/AST/BuiltinTypes.def"
       llvm_unreachable("asking for RRTI for a placeholder type!");
 
@@ -3827,7 +3813,7 @@ static bool TypeInfoIsInStandardLibrary(const BuiltinType *Ty) {
     case BuiltinType::ObjCClass:
     case BuiltinType::ObjCSel:
       llvm_unreachable("FIXME: Objective-C types are unsupported!");
-  }
+    }
 
   llvm_unreachable("Invalid BuiltinType Kind!");
 }
@@ -3867,13 +3853,13 @@ static bool IsStandardLibraryRTTIDescriptor(QualType Ty) {
 /// the given type exists somewhere else, and that we should not emit the type
 /// information in this translation unit.  Assumes that it is not a
 /// standard-library type.
-static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM,
-                                            QualType Ty) {
+static bool ShouldUseExternalRTTIDescriptor(CodeGenModule &CGM, QualType Ty) {
   ASTContext &Context = CGM.getContext();
 
   // If RTTI is disabled, assume it might be disabled in the
   // translation unit that defines any potential key function, too.
-  if (!Context.getLangOpts().RTTI) return false;
+  if (!Context.getLangOpts().RTTI)
+    return false;
 
   if (const RecordType *RecordTy = dyn_cast<RecordType>(Ty)) {
     const CXXRecordDecl *RD =
@@ -3935,7 +3921,7 @@ static bool ContainsIncompleteClassType(QualType Ty) {
     return ContainsIncompleteClassType(PointerTy->getPointeeType());
 
   if (const MemberPointerType *MemberPointerTy =
-      dyn_cast<MemberPointerType>(Ty)) {
+          dyn_cast<MemberPointerType>(Ty)) {
     // Check if the class type is incomplete.
     if (!MemberPointerTy->getMostRecentCXXRecordDecl()->hasDefinition())
       return true;
@@ -3977,14 +3963,14 @@ static bool CanUseSingleInheritance(const CXXRecordDecl *RD) {
 void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty,
                                             llvm::Constant *StorageAddress) {
   // abi::__class_type_info.
-  static const char * const ClassTypeInfo =
-    "_ZTVN10__cxxabiv117__class_type_infoE";
+  static const char *const ClassTypeInfo =
+      "_ZTVN10__cxxabiv117__class_type_infoE";
   // abi::__si_class_type_info.
-  static const char * const SIClassTypeInfo =
-    "_ZTVN10__cxxabiv120__si_class_type_infoE";
+  static const char *const SIClassTypeInfo =
+      "_ZTVN10__cxxabiv120__si_class_type_infoE";
   // abi::__vmi_class_type_info.
-  static const char * const VMIClassTypeInfo =
-    "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
+  static const char *const VMIClassTypeInfo =
+      "_ZTVN10__cxxabiv121__vmi_class_type_infoE";
 
   const char *VTableName = nullptr;
 
@@ -4238,10 +4224,9 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty) {
 }
 
 llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(
-      QualType Ty,
-      llvm::GlobalVariable::LinkageTypes Linkage,
-      llvm::GlobalValue::VisibilityTypes Visibility,
-      llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
+    QualType Ty, llvm::GlobalVariable::LinkageTypes Linkage,
+    llvm::GlobalValue::VisibilityTypes Visibility,
+    llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass) {
   SmallString<256> Name;
   llvm::raw_svector_ostream Out(Name);
   CGM.getCXXABI().getMangleContext().mangleCXXRTTI(Ty, Out);
@@ -4443,13 +4428,15 @@ void ItaniumRTTIBuilder::BuildObjCObjectTypeInfo(const ObjCObjectType *OT) {
 
   // The builtin types are abi::__class_type_infos and don't require
   // extra fields.
-  if (isa<BuiltinType>(T)) return;
+  if (isa<BuiltinType>(T))
+    return;
 
   ObjCInterfaceDecl *Class = cast<ObjCInterfaceType>(T)->getDecl();
   ObjCInterfaceDecl *Super = Class->getSuperClass();
 
   // Root classes are also __class_type_info.
-  if (!Super) return;
+  if (!Super)
+    return;
 
   QualType SuperTy = CGM.getContext().getObjCInterfaceType(Super);
 
@@ -4466,18 +4453,18 @@ void ItaniumRTTIBuilder::BuildSIClassTypeInfo(const CXXRecordDecl *RD) {
   // It adds to abi::__class_type_info a single member pointing to the
   // type_info structure for the base type,
   llvm::Constant *BaseTypeInfo =
-    ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(RD->bases_begin()->getType());
+      ItaniumRTTIBuilder(CXXABI).BuildTypeInfo(RD->bases_begin()->getType());
   Fields.push_back(BaseTypeInfo);
 }
 
 namespace {
-  /// SeenBases - Contains virtual and non-virtual bases seen when traversing
-  /// a class hierarchy.
-  struct SeenBases {
-    llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
-    llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
-  };
-}
+/// SeenBases - Contains virtual and non-virtual bases seen when traversing
+/// a class hierarchy.
+struct SeenBases {
+  llvm::SmallPtrSet<const CXXRecordDecl *, 16> NonVirtualBases;
+  llvm::SmallPtrSet<const CXXRecordDecl *, 16> VirtualBases;
+};
+} // namespace
 
 /// ComputeVMIClassTypeInfoFlags - Compute the value of the flags member in
 /// abi::__vmi_class_type_info.
@@ -4533,7 +4520,7 @@ static unsigned ComputeVMIClassTypeInfoFlags(const CXXRecordDecl *RD) {
 /// constraints, according ti the Itanium C++ ABI, 2.9.5p5c.
 void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
   llvm::Type *UnsignedIntLTy =
-    CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+      CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
 
   // Itanium C++ ABI 2.9.5p6c:
   //   __flags is a word with flags describing details about the class
@@ -4578,8 +4565,7 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
   if (TI.getTriple().isOSCygMing() &&
       TI.getPointerWidth(LangAS::Default) > TI.getLongWidth())
     OffsetFlagsTy = CGM.getContext().LongLongTy;
-  llvm::Type *OffsetFlagsLTy =
-      CGM.getTypes().ConvertType(OffsetFlagsTy);
+  llvm::Type *OffsetFlagsLTy = CGM.getTypes().ConvertType(OffsetFlagsTy);
 
   for (const auto &Base : RD->bases()) {
     // The __base_type member points to the RTTI for the base type.
@@ -4594,8 +4580,8 @@ void ItaniumRTTIBuilder::BuildVMIClassTypeInfo(const CXXRecordDecl *RD) {
     // the virtual base offset for the virtual base referenced (negative).
     CharUnits Offset;
     if (Base.isVirtual())
-      Offset =
-        CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(RD, BaseDecl);
+      Offset = CGM.getItaniumVTableContext().getVirtualBaseOffsetOffset(
+          RD, BaseDecl);
     else {
       const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);
       Offset = Layout.getBaseClassOffset(BaseDecl);
@@ -4652,7 +4638,7 @@ void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
   unsigned Flags = extractPBaseFlags(CGM.getContext(), PointeeTy);
 
   llvm::Type *UnsignedIntLTy =
-    CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+      CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
   Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
 
   // Itanium C++ ABI 2.9.5p7:
@@ -4665,8 +4651,8 @@ void ItaniumRTTIBuilder::BuildPointerTypeInfo(QualType PointeeTy) {
 
 /// BuildPointerToMemberTypeInfo - Build an abi::__pointer_to_member_type_info
 /// struct, used for member pointer types.
-void
-ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
+void ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(
+    const MemberPointerType *Ty) {
   QualType PointeeTy = Ty->getPointeeType();
 
   // Itanium C++ ABI 2.9.5p7:
@@ -4679,7 +4665,7 @@ ItaniumRTTIBuilder::BuildPointerToMemberTypeInfo(const MemberPointerType *Ty) {
     Flags |= PTI_ContainingClassIncomplete;
 
   llvm::Type *UnsignedIntLTy =
-    CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
+      CGM.getTypes().ConvertType(CGM.getContext().UnsignedIntTy);
   Fields.push_back(llvm::ConstantInt::get(UnsignedIntLTy, Flags));
 
   // Itanium C++ ABI 2.9.5p7:
@@ -4703,21 +4689,31 @@ llvm::Constant *ItaniumCXXABI::getAddrOfRTTIDescriptor(QualType Ty) {
 
 void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) {
   // Types added here must also be added to TypeInfoIsInStandardLibrary.
-  QualType FundamentalTypes[] = {
-      getContext().VoidTy,             getContext().NullPtrTy,
-      getContext().BoolTy,             getContext().WCharTy,
-      getContext().CharTy,             getContext().UnsignedCharTy,
-      getContext().SignedCharTy,       getContext().ShortTy,
-      getContext().UnsignedShortTy,    getContext().IntTy,
-      getContext().UnsignedIntTy,      getContext().LongTy,
-      getContext().UnsignedLongTy,     getContext().LongLongTy,
-      getContext().UnsignedLongLongTy, getContext().Int128Ty,
-      getContext().UnsignedInt128Ty,   getContext().HalfTy,
-      getContext().FloatTy,            getContext().DoubleTy,
-      getContext().LongDoubleTy,       getContext().Float128Ty,
-      getContext().Char8Ty,            getContext().Char16Ty,
-      getContext().Char32Ty
-  };
+  QualType FundamentalTypes[] = {getContext().VoidTy,
+                                 getContext().NullPtrTy,
+                                 getContext().BoolTy,
+                                 getContext().WCharTy,
+                                 getContext().CharTy,
+                                 getContext().UnsignedCharTy,
+                                 getContext().SignedCharTy,
+                                 getContext().ShortTy,
+                                 getContext().UnsignedShortTy,
+                                 getContext().IntTy,
+                                 getContext().UnsignedIntTy,
+                                 getContext().LongTy,
+                                 getContext().UnsignedLongTy,
+                                 getContext().LongLongTy,
+                                 getContext().UnsignedLongLongTy,
+                                 getContext().Int128Ty,
+                                 getContext().UnsignedInt128Ty,
+                                 getContext().HalfTy,
+                                 getContext().FloatTy,
+                                 getContext().DoubleTy,
+                                 getContext().LongDoubleTy,
+                                 getContext().Float128Ty,
+                                 getContext().Char8Ty,
+                                 getContext().Char16Ty,
+                                 getContext().Char32Ty};
   llvm::GlobalValue::DLLStorageClassTypes DLLStorageClass =
       RD->hasAttr<DLLExportAttr>() || CGM.shouldMapVisibilityToDLLExport(RD)
           ? llvm::GlobalValue::DLLExportStorageClass
@@ -4726,12 +4722,12 @@ void ItaniumCXXABI::EmitFundamentalRTTIDescriptors(const CXXRecordDecl *RD) {
       CodeGenModule::GetLLVMVisibility(RD->getVisibility());
   for (const QualType &FundamentalType : FundamentalTypes) {
     QualType PointerType = getContext().getPointerType(FundamentalType);
-    QualType PointerTypeConst = getContext().getPointerType(
-        FundamentalType.withConst());
+    QualType PointerTypeConst =
+        getContext().getPointerType(FundamentalType.withConst());
     for (QualType Type : {FundamentalType, PointerType, PointerTypeConst})
       ItaniumRTTIBuilder(*this).BuildTypeInfo(
-          Type, llvm::GlobalValue::ExternalLinkage,
-          Visibility, DLLStorageClass);
+          Type, llvm::GlobalValue::ExternalLinkage, Visibility,
+          DLLStorageClass);
   }
 }
 
@@ -4903,8 +4899,8 @@ void ItaniumCXXABI::emitCXXStructor(GlobalDecl GD) {
 
 static llvm::FunctionCallee getBeginCatchFn(CodeGenModule &CGM) {
   // void *__cxa_begin_catch(void*);
-  llvm::FunctionType *FTy = llvm::FunctionType::get(
-      CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
 
   return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch");
 }
@@ -4919,39 +4915,39 @@ static llvm::FunctionCallee getEndCatchFn(CodeGenModule &CGM) {
 
 static llvm::FunctionCallee getGetExceptionPtrFn(CodeGenModule &CGM) {
   // void *__cxa_get_exception_ptr(void*);
-  llvm::FunctionType *FTy = llvm::FunctionType::get(
-      CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
+  llvm::FunctionType *FTy =
+      llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*isVarArg=*/false);
 
   return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr");
 }
 
 namespace {
-  /// A cleanup to call __cxa_end_catch.  In many cases, the caught
-  /// exception type lets us state definitively that the thrown exception
-  /// type does not have a destructor.  In particular:
-  ///   - Catch-alls tell us nothing, so we have to conservatively
-  ///     assume that the thrown exception might have a destructor.
-  ///   - Catches by reference behave according to their base types.
-  ///   - Catches of non-record types will only trigger for exceptions
-  ///     of non-record types, which never have destructors.
-  ///   - Catches of record types can trigger for arbitrary subclasses
-  ///     of the caught type, so we have to assume the actual thrown
-  ///     exception type might have a throwing destructor, even if the
-  ///     caught type's destructor is trivial or nothrow.
-  struct CallEndCatch final : EHScopeStack::Cleanup {
-    CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
-    bool MightThrow;
-
-    void Emit(CodeGenFunction &CGF, Flags flags) override {
-      if (!MightThrow) {
-        CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM));
-        return;
-      }
-
-      CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM));
+/// A cleanup to call __cxa_end_catch.  In many cases, the caught
+/// exception type lets us state definitively that the thrown exception
+/// type does not have a destructor.  In particular:
+///   - Catch-alls tell us nothing, so we have to conservatively
+///     assume that the thrown exception might have a destructor.
+///   - Catches by reference behave according to their base types.
+///   - Catches of non-record types will only trigger for exceptions
+///     of non-record types, which never have destructors.
+///   - Catches of record types can trigger for arbitrary subclasses
+///     of the caught type, so we have to assume the actual thrown
+///     exception type might have a throwing destructor, even if the
+///     caught type's destructor is trivial or nothrow.
+struct CallEndCatch final : EHScopeStack::Cleanup {
+  CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {}
+  bool MightThrow;
+
+  void Emit(CodeGenFunction &CGF, Flags flags) override {
+    if (!MightThrow) {
+      CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM));
+      return;
     }
-  };
-}
+
+    CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM));
+  }
+};
+} // namespace
 
 /// Emits a call to __cxa_begin_catch and enters a cleanup to call
 /// __cxa_end_catch. If -fassume-nothrow-exception-dtor is specified, we assume
@@ -4959,11 +4955,10 @@ namespace {
 /// call can be marked as nounwind even if EndMightThrow is true.
 ///
 /// \param EndMightThrow - true if __cxa_end_catch might throw
-static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
-                                   llvm::Value *Exn,
+static llvm::Value *CallBeginCatch(CodeGenFunction &CGF, llvm::Value *Exn,
                                    bool EndMightThrow) {
   llvm::CallInst *call =
-    CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);
+      CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn);
 
   CGF.EHStack.pushCleanup<CallEndCatch>(
       NormalAndEHCleanup,
@@ -4974,15 +4969,13 @@ static llvm::Value *CallBeginCatch(CodeGenFunction &CGF,
 
 /// A "special initializer" callback for initializing a catch
 /// parameter during catch initialization.
-static void InitCatchParam(CodeGenFunction &CGF,
-                           const VarDecl &CatchParam,
-                           Address ParamAddr,
-                           SourceLocation Loc) {
+static void InitCatchParam(CodeGenFunction &CGF, const VarDecl &CatchParam,
+                           Address ParamAddr, SourceLocation Loc) {
   // Load the exception from where the landing pad saved it.
   llvm::Value *Exn = CGF.getExceptionFromSlot();
 
   CanQualType CatchType =
-    CGF.CGM.getContext().getCanonicalType(CatchParam.getType());
+      CGF.CGM.getContext().getCanonicalType(CatchParam.getType());
   llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType);
 
   // If we're catching by reference, we can just cast the object
@@ -5007,31 +5000,31 @@ static void InitCatchParam(CodeGenFunction &CGF,
         // Exn points to the struct _Unwind_Exception header, which
         // we have to skip past in order to reach the exception data.
         unsigned HeaderSize =
-          CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
+            CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException();
         AdjustedExn =
             CGF.Builder.CreateConstGEP1_32(CGF.Int8Ty, Exn, HeaderSize);
 
-      // However, if we're catching a pointer-to-record type that won't
-      // work, because the personality function might have adjusted
-      // the pointer.  There's actually no way for us to fully satisfy
-      // the language/ABI contract here:  we can't use Exn because it
-      // might have the wrong adjustment, but we can't use the by-value
-      // pointer because it's off by a level of abstraction.
-      //
-      // The current solution is to dump the adjusted pointer into an
-      // alloca, which breaks language semantics (because changing the
-      // pointer doesn't change the exception) but at least works.
-      // The better solution would be to filter out non-exact matches
-      // and rethrow them, but this is tricky because the rethrow
-      // really needs to be catchable by other sites at this landing
-      // pad.  The best solution is to fix the personality function.
+        // However, if we're catching a pointer-to-record type that won't
+        // work, because the personality function might have adjusted
+        // the pointer.  There's actually no way for us to fully satisfy
+        // the language/ABI contract here:  we can't use Exn because it
+        // might have the wrong adjustment, but we can't use the by-value
+        // pointer because it's off by a level of abstraction.
+        //
+        // The current solution is to dump the adjusted pointer into an
+        // alloca, which breaks language semantics (because changing the
+        // pointer doesn't change the exception) but at least works.
+        // The better solution would be to filter out non-exact matches
+        // and rethrow them, but this is tricky because the rethrow
+        // really needs to be catchable by other sites at this landing
+        // pad.  The best solution is to fix the personality function.
       } else {
         // Pull the pointer for the reference type off.
         llvm::Type *PtrTy = CGF.ConvertTypeForMem(CaughtType);
 
         // Create the temporary and write the adjusted pointer into it.
         Address ExnPtrTmp =
-          CGF.CreateTempAlloca(PtrTy, CGF.getPointerAlign(), "exn.byref.tmp");
+            CGF.CreateTempAlloca(PtrTy, CGF.getPointerAlign(), "exn.byref.tmp");
         llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy);
         CGF.Builder.CreateStore(Casted, ExnPtrTmp);
 
@@ -5041,7 +5034,7 @@ static void InitCatchParam(CodeGenFunction &CGF,
     }
 
     llvm::Value *ExnCast =
-      CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
+        CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref");
     CGF.Builder.CreateStore(ExnCast, ParamAddr);
     return;
   }
@@ -5055,7 +5048,7 @@ static void InitCatchParam(CodeGenFunction &CGF,
     // the pointer by value.
     if (CatchType->hasPointerRepresentation()) {
       llvm::Value *CastExn =
-        CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
+          CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
 
       switch (CatchType.getQualifiers().getObjCLifetime()) {
       case Qualifiers::OCL_Strong:
@@ -5117,7 +5110,7 @@ static void InitCatchParam(CodeGenFunction &CGF,
   // We have to call __cxa_get_exception_ptr to get the adjusted
   // pointer before copying.
   llvm::CallInst *rawAdjustedExn =
-    CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);
+      CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn);
 
   // Cast that to the appropriate type.
   Address adjustedExn(CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy),
@@ -5125,20 +5118,19 @@ static void InitCatchParam(CodeGenFunction &CGF,
 
   // The copy expression is defined in terms of an OpaqueValueExpr.
   // Find it and map it to the adjusted expression.
-  CodeGenFunction::OpaqueValueMapping
-    opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),
-           CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));
+  CodeGenFunction::OpaqueValueMapping opaque(
+      CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr),
+      CGF.MakeAddrLValue(adjustedExn, CatchParam.getType()));
 
   // Call the copy ctor in a terminate scope.
   CGF.EHStack.pushTerminate();
 
   // Perform the copy construction.
-  CGF.EmitAggExpr(copyExpr,
-                  AggValueSlot::forAddr(ParamAddr, Qualifiers(),
-                                        AggValueSlot::IsNotDestructed,
-                                        AggValueSlot::DoesNotNeedGCBarriers,
-                                        AggValueSlot::IsNotAliased,
-                                        AggValueSlot::DoesNotOverlap));
+  CGF.EmitAggExpr(
+      copyExpr, AggValueSlot::forAddr(
+                    ParamAddr, Qualifiers(), AggValueSlot::IsNotDestructed,
+                    AggValueSlot::DoesNotNeedGCBarriers,
+                    AggValueSlot::IsNotAliased, AggValueSlot::DoesNotOverlap));
 
   // Leave the terminate scope.
   CGF.EHStack.popTerminate();
diff --git a/compiler-rt/test/asan/TestCases/invalid-pointer-pairs-vector-extract.cpp b/compiler-rt/test/asan/TestCases/invalid-pointer-pairs-vector-extract.cpp
index 8c93ffa71ab30..2eea39ba91e17 100644
--- a/compiler-rt/test/asan/TestCases/invalid-pointer-pairs-vector-extract.cpp
+++ b/compiler-rt/test/asan/TestCases/invalid-pointer-pairs-vector-extract.cpp
@@ -4,8 +4,6 @@
 // RUN: %env_asan_opts=detect_invalid_pointer_pairs=2:halt_on_error=0 %run %t 2>&1 | FileCheck %s
 
 // UNSUPPORTED: windows
-// UNSUPPORTED: target={{.*solaris.*}}
-
 // XFAIL: *
 
 #include <cstdint>
diff --git a/llvm/include/llvm/ExecutionEngine/Orc/SymbolLookupSet.h b/llvm/include/llvm/ExecutionEngine/Orc/SymbolLookupSet.h
index a3adf21986aea..bad4cd6052b8d 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/SymbolLookupSet.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SymbolLookupSet.h
@@ -225,33 +225,12 @@ class SymbolLookupSet {
     });
   }
 
-  /// Merge entries that share a name, so that each name appears exactly once.
-  /// If a SymbolLookupSet is not duplicate-free by construction, this method
-  /// can be used to turn it into a proper set.
-  ///
-  /// Entries sharing a name need not agree on their flags. Where they differ
-  /// the strongest requirement wins: if any entry required the symbol then the
-  /// merged entry requires it too, so that a missing definition still fails the
-  /// lookup.
-  void mergeEntries() {
-    if (Symbols.size() < 2)
-      return;
+  /// Remove any duplicate elements. If a SymbolLookupSet is not duplicate-free
+  /// by construction, this method can be used to turn it into a proper set.
+  void removeDuplicates() {
     sortByAddress();
-
-    auto Out = Symbols.begin();
-    for (auto In = Out + 1; In != Symbols.end(); ++In) {
-      if (In->first == Out->first) {
-        // Same name: keep the stronger requirement.
-        if (In->second == SymbolLookupFlags::RequiredSymbol)
-          Out->second = SymbolLookupFlags::RequiredSymbol;
-      } else {
-        // New name: compact it down next to the previous survivor.
-        ++Out;
-        if (Out != In)
-          *Out = std::move(*In);
-      }
-    }
-    Symbols.erase(std::next(Out), Symbols.end());
+    auto LastI = llvm::unique(Symbols);
+    Symbols.erase(LastI, Symbols.end());
   }
 
 #ifndef NDEBUG
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index d078117061677..d7c37a021169e 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -2173,8 +2173,8 @@ bool X86DAGToDAGISel::matchAdd(SDValue &N, X86ISelAddressMode &AM,
   };
 
   X86ISelAddressMode Backup = AM;
-  if (!MatchOperand(N.getOperand(0)) &&
-      !MatchOperand(Handle.getValue().getOperand(1)))
+  if (!matchAddressRecursively(N.getOperand(0), AM, Depth + 1) &&
+      !matchAddressRecursively(Handle.getValue().getOperand(1), AM, Depth + 1))
     return false;
   AM = Backup;
 
diff --git a/llvm/test/Transforms/SLPVectorizer/AMDGPU/elementwise-fma-operand1.ll b/llvm/test/Transforms/SLPVectorizer/AMDGPU/elementwise-fma-operand1.ll
index c4c97622ac726..3bcc9f03d0220 100644
--- a/llvm/test/Transforms/SLPVectorizer/AMDGPU/elementwise-fma-operand1.ll
+++ b/llvm/test/Transforms/SLPVectorizer/AMDGPU/elementwise-fma-operand1.ll
@@ -2,17 +2,12 @@
 ; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -slp-threshold=14 < %s | FileCheck %s
 ; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx942 -slp-threshold=14 < %s | FileCheck %s
 ; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx950 -slp-threshold=14 < %s | FileCheck %s
-; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx90a -slp-threshold=12 < %s | FileCheck %s --check-prefix=THR12
-; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx942 -slp-threshold=12 < %s | FileCheck %s --check-prefix=THR12
-; RUN: opt -passes=slp-vectorizer -S -mtriple=amdgcn-amd-amdhsa -mcpu=gfx950 -slp-threshold=12 < %s | FileCheck %s --check-prefix=THR12
 
-; Elementwise d = c + a * b, where the fmul is operand 1 of the fadd. These
-; targets halve the cost of a packed fmul, so SLP is tempted to vectorize and
-; break the scalar fma chain. The 14 runs sit at the cost boundary. The 12 runs
-; vectorize either way and guard against the fmuladd marking landing on the load
-; at operand 0 after the fma detection picked the fmul at operand 1, which
-; asserts. axpy4_mixed_reassoc carries reassoc on one lane only, so the whole
-; bundle has to be reassociative before the search gives up on operand 1.
+; Elementwise d = c + a * b, where the fmul is operand 1 of the fadd. The
+; threshold puts the decision right at the cost boundary, so how the fmul and
+; fadd are priced against a fused fma is what decides it. These targets halve
+; the cost of a packed fmul, which is what tempts SLP into vectorizing and
+; breaking the scalar fma chain.
 
 define void @axpy4_contract(ptr noalias %d, ptr noalias %a, ptr noalias %b, ptr noalias %c) {
 ; CHECK-LABEL: define void @axpy4_contract(
@@ -26,17 +21,6 @@ define void @axpy4_contract(ptr noalias %d, ptr noalias %a, ptr noalias %b, ptr
 ; CHECK-NEXT:    store <4 x float> [[TMP4]], ptr [[D]], align 4
 ; CHECK-NEXT:    ret void
 ;
-; THR12-LABEL: define void @axpy4_contract(
-; THR12-SAME: ptr noalias [[D:%.*]], ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR0:[0-9]+]] {
-; THR12-NEXT:  [[ENTRY:.*:]]
-; THR12-NEXT:    [[TMP0:%.*]] = load <4 x float>, ptr [[C]], align 4
-; THR12-NEXT:    [[TMP1:%.*]] = load <4 x float>, ptr [[A]], align 4
-; THR12-NEXT:    [[TMP2:%.*]] = load <4 x float>, ptr [[B]], align 4
-; THR12-NEXT:    [[TMP3:%.*]] = fmul contract <4 x float> [[TMP1]], [[TMP2]]
-; THR12-NEXT:    [[TMP4:%.*]] = fadd contract <4 x float> [[TMP0]], [[TMP3]]
-; THR12-NEXT:    store <4 x float> [[TMP4]], ptr [[D]], align 4
-; THR12-NEXT:    ret void
-;
 entry:
   %c0 = load float, ptr %c, align 4
   %a0 = load float, ptr %a, align 4
@@ -89,17 +73,6 @@ define void @axpy4_reassoc(ptr noalias %d, ptr noalias %a, ptr noalias %b, ptr n
 ; CHECK-NEXT:    store <4 x float> [[TMP4]], ptr [[D]], align 4
 ; CHECK-NEXT:    ret void
 ;
-; THR12-LABEL: define void @axpy4_reassoc(
-; THR12-SAME: ptr noalias [[D:%.*]], ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR0]] {
-; THR12-NEXT:  [[ENTRY:.*:]]
-; THR12-NEXT:    [[TMP0:%.*]] = load <4 x float>, ptr [[C]], align 4
-; THR12-NEXT:    [[TMP1:%.*]] = load <4 x float>, ptr [[A]], align 4
-; THR12-NEXT:    [[TMP2:%.*]] = load <4 x float>, ptr [[B]], align 4
-; THR12-NEXT:    [[TMP3:%.*]] = fmul reassoc contract <4 x float> [[TMP1]], [[TMP2]]
-; THR12-NEXT:    [[TMP4:%.*]] = fadd reassoc contract <4 x float> [[TMP0]], [[TMP3]]
-; THR12-NEXT:    store <4 x float> [[TMP4]], ptr [[D]], align 4
-; THR12-NEXT:    ret void
-;
 entry:
   %c0 = load float, ptr %c, align 4
   %a0 = load float, ptr %a, align 4
@@ -139,66 +112,3 @@ entry:
   store float %r3, ptr %dp3, align 4
   ret void
 }
-
-define void @axpy4_mixed_reassoc(ptr noalias %d, ptr noalias %a, ptr noalias %b, ptr noalias %c) {
-; CHECK-LABEL: define void @axpy4_mixed_reassoc(
-; CHECK-SAME: ptr noalias [[D:%.*]], ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR0]] {
-; CHECK-NEXT:  [[ENTRY:.*:]]
-; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x float>, ptr [[C]], align 4
-; CHECK-NEXT:    [[TMP1:%.*]] = load <4 x float>, ptr [[A]], align 4
-; CHECK-NEXT:    [[TMP2:%.*]] = load <4 x float>, ptr [[B]], align 4
-; CHECK-NEXT:    [[TMP3:%.*]] = fmul contract <4 x float> [[TMP1]], [[TMP2]]
-; CHECK-NEXT:    [[TMP4:%.*]] = fadd contract <4 x float> [[TMP0]], [[TMP3]]
-; CHECK-NEXT:    store <4 x float> [[TMP4]], ptr [[D]], align 4
-; CHECK-NEXT:    ret void
-;
-; THR12-LABEL: define void @axpy4_mixed_reassoc(
-; THR12-SAME: ptr noalias [[D:%.*]], ptr noalias [[A:%.*]], ptr noalias [[B:%.*]], ptr noalias [[C:%.*]]) #[[ATTR0]] {
-; THR12-NEXT:  [[ENTRY:.*:]]
-; THR12-NEXT:    [[TMP0:%.*]] = load <4 x float>, ptr [[C]], align 4
-; THR12-NEXT:    [[TMP1:%.*]] = load <4 x float>, ptr [[A]], align 4
-; THR12-NEXT:    [[TMP2:%.*]] = load <4 x float>, ptr [[B]], align 4
-; THR12-NEXT:    [[TMP3:%.*]] = fmul contract <4 x float> [[TMP1]], [[TMP2]]
-; THR12-NEXT:    [[TMP4:%.*]] = fadd contract <4 x float> [[TMP0]], [[TMP3]]
-; THR12-NEXT:    store <4 x float> [[TMP4]], ptr [[D]], align 4
-; THR12-NEXT:    ret void
-;
-entry:
-  %c0 = load float, ptr %c, align 4
-  %a0 = load float, ptr %a, align 4
-  %b0 = load float, ptr %b, align 4
-  %m0 = fmul contract float %a0, %b0
-  %r0 = fadd contract reassoc float %c0, %m0
-  store float %r0, ptr %d, align 4
-  %cp1 = getelementptr inbounds float, ptr %c, i64 1
-  %c1 = load float, ptr %cp1, align 4
-  %ap1 = getelementptr inbounds float, ptr %a, i64 1
-  %a1 = load float, ptr %ap1, align 4
-  %bp1 = getelementptr inbounds float, ptr %b, i64 1
-  %b1 = load float, ptr %bp1, align 4
-  %m1 = fmul contract float %a1, %b1
-  %r1 = fadd contract float %c1, %m1
-  %dp1 = getelementptr inbounds float, ptr %d, i64 1
-  store float %r1, ptr %dp1, align 4
-  %cp2 = getelementptr inbounds float, ptr %c, i64 2
-  %c2 = load float, ptr %cp2, align 4
-  %ap2 = getelementptr inbounds float, ptr %a, i64 2
-  %a2 = load float, ptr %ap2, align 4
-  %bp2 = getelementptr inbounds float, ptr %b, i64 2
-  %b2 = load float, ptr %bp2, align 4
-  %m2 = fmul contract float %a2, %b2
-  %r2 = fadd contract float %c2, %m2
-  %dp2 = getelementptr inbounds float, ptr %d, i64 2
-  store float %r2, ptr %dp2, align 4
-  %cp3 = getelementptr inbounds float, ptr %c, i64 3
-  %c3 = load float, ptr %cp3, align 4
-  %ap3 = getelementptr inbounds float, ptr %a, i64 3
-  %a3 = load float, ptr %ap3, align 4
-  %bp3 = getelementptr inbounds float, ptr %b, i64 3
-  %b3 = load float, ptr %bp3, align 4
-  %m3 = fmul contract float %a3, %b3
-  %r3 = fadd contract float %c3, %m3
-  %dp3 = getelementptr inbounds float, ptr %d, i64 3
-  store float %r3, ptr %dp3, align 4
-  ret void
-}
diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
index ac648b3f420bf..8af05a8b32e8f 100644
--- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -49,7 +49,6 @@ add_llvm_unittest(OrcJITTests
   SimpleExecutorMemoryManagerTest.cpp
   SimplePackedSerializationTest.cpp
   SPSProxySpecTest.cpp
-  SymbolLookupSetTest.cpp
   SymbolStringPoolTest.cpp
   TaskDispatchTest.cpp
   ThreadSafeModuleTest.cpp
diff --git a/llvm/unittests/ExecutionEngine/Orc/SymbolLookupSetTest.cpp b/llvm/unittests/ExecutionEngine/Orc/SymbolLookupSetTest.cpp
deleted file mode 100644
index 95c3884e0b8e8..0000000000000
--- a/llvm/unittests/ExecutionEngine/Orc/SymbolLookupSetTest.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-//===- SymbolLookupSetTest.cpp - Test SymbolLookupSet --------------------===//
-//
-// 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/ExecutionEngine/Orc/SymbolLookupSet.h"
-
-#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
-
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "gtest/gtest.h"
-
-using namespace llvm;
-using namespace llvm::orc;
-
-namespace {
-
-class SymbolLookupSetTest : public testing::Test {
-protected:
-  static constexpr SymbolLookupFlags Required =
-      SymbolLookupFlags::RequiredSymbol;
-  static constexpr SymbolLookupFlags Weak =
-      SymbolLookupFlags::WeaklyReferencedSymbol;
-
-  std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>();
-
-  SymbolStringPtr intern(StringRef S) { return SSP->intern(S); }
-
-  /// Collect a lookup set into a name-sorted vector of (name, flags).
-  ///
-  /// A vector rather than a map so that a name surviving more than once is
-  /// visible, and name-sorted because mergeEntries sorts by pointer value,
-  /// leaving an order that depends on allocation and must not be asserted on.
-  using Entries = std::vector<std::pair<std::string, SymbolLookupFlags>>;
-
-  static Entries contents(const SymbolLookupSet &LS) {
-    Entries Result;
-    for (const auto &[Name, Flags] : LS)
-      Result.emplace_back(std::string(*Name), Flags);
-    llvm::sort(Result);
-    return Result;
-  }
-};
-
-} // namespace
-
-// A set that is already duplicate-free is left alone, flags included.
-TEST_F(SymbolLookupSetTest, MergeEntriesNoDuplicates) {
-  SymbolLookupSet LS;
-  LS.add(intern("foo"), Required);
-  LS.add(intern("bar"), Weak);
-
-  LS.mergeEntries();
-
-  EXPECT_EQ(contents(LS), (Entries{{"bar", Weak}, {"foo", Required}}));
-}
-
-// Duplicates that agree on flags collapse to a single entry.
-TEST_F(SymbolLookupSetTest, MergeEntriesSameFlags) {
-  SymbolLookupSet LS;
-  LS.add(intern("foo"), Required);
-  LS.add(intern("foo"), Required);
-  LS.add(intern("bar"), Weak);
-  LS.add(intern("bar"), Weak);
-
-  LS.mergeEntries();
-
-  EXPECT_EQ(contents(LS), (Entries{{"bar", Weak}, {"foo", Required}}));
-}
-
-// A name requested both ways merges to RequiredSymbol: if any requester needs
-// the symbol then a missing definition must fail the lookup.
-//
-// Both insertion orders are checked because mergeEntries sorts by pointer
-// value, so which of the two entries is seen first is not under our control.
-TEST_F(SymbolLookupSetTest, MergeEntriesRequiredWinsWeakFirst) {
-  SymbolLookupSet LS;
-  LS.add(intern("foo"), Weak);
-  LS.add(intern("foo"), Required);
-
-  LS.mergeEntries();
-
-  EXPECT_EQ(contents(LS), (Entries{{"foo", Required}}));
-}
-
-TEST_F(SymbolLookupSetTest, MergeEntriesRequiredWinsRequiredFirst) {
-  SymbolLookupSet LS;
-  LS.add(intern("foo"), Required);
-  LS.add(intern("foo"), Weak);
-
-  LS.mergeEntries();
-
-  EXPECT_EQ(contents(LS), (Entries{{"foo", Required}}));
-}
-
-// Merging must not invent a requirement: all-weak duplicates stay weak.
-TEST_F(SymbolLookupSetTest, MergeEntriesAllWeakStaysWeak) {
-  SymbolLookupSet LS;
-  LS.add(intern("foo"), Weak);
-  LS.add(intern("foo"), Weak);
-  LS.add(intern("foo"), Weak);
-
-  LS.mergeEntries();
-
-  EXPECT_EQ(contents(LS), (Entries{{"foo", Weak}}));
-}
-
-// Several distinct names, each duplicated a different number of times and with
-// mixed flags, all merge in one pass.
-TEST_F(SymbolLookupSetTest, MergeEntriesMultipleRuns) {
-  SymbolLookupSet LS;
-  LS.add(intern("foo"), Weak);
-  LS.add(intern("bar"), Required);
-  LS.add(intern("foo"), Weak);
-  LS.add(intern("baz"), Weak);
-  LS.add(intern("bar"), Weak);
-  LS.add(intern("foo"), Required);
-  LS.add(intern("qux"), Required);
-
-  LS.mergeEntries();
-
-  EXPECT_EQ(contents(LS), (Entries{{"bar", Required},
-                                   {"baz", Weak},
-                                   {"foo", Required},
-                                   {"qux", Required}}));
-}
diff --git a/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn b/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
index 5659ddfea45e0..dfbf74b3cd1a9 100644
--- a/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/unittests/ExecutionEngine/Orc/BUILD.gn
@@ -48,7 +48,6 @@ unittest("OrcJITTests") {
     "SharedMemoryMapperTest.cpp",
     "SimpleExecutorMemoryManagerTest.cpp",
     "SimplePackedSerializationTest.cpp",
-    "SymbolLookupSetTest.cpp",
     "SymbolStringPoolTest.cpp",
     "TaskDispatchTest.cpp",
     "ThreadSafeModuleTest.cpp",
diff --git a/orc-rt/include/CMakeLists.txt b/orc-rt/include/CMakeLists.txt
index 40c16d681e783..247d82ba709e6 100644
--- a/orc-rt/include/CMakeLists.txt
+++ b/orc-rt/include/CMakeLists.txt
@@ -32,7 +32,6 @@ set(ORC_RT_HEADERS
     orc-rt/SimplePackedSerialization.h
     orc-rt/SimpleSymbolTable.h
     orc-rt/StandaloneMachOUnwindInfoRegistrar.h
-    orc-rt/StringPool.h
     orc-rt/TaskGroup.h
     orc-rt/ThreadPoolRunner.h
     orc-rt/WrapperFunction.h
diff --git a/orc-rt/include/orc-rt/StringPool.h b/orc-rt/include/orc-rt/StringPool.h
deleted file mode 100644
index 85014da2b2e54..0000000000000
--- a/orc-rt/include/orc-rt/StringPool.h
+++ /dev/null
@@ -1,249 +0,0 @@
-//===------------- StringPool.h - Interning string pool ---------*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// A thread-safe, ref-counted pool of uniqued strings.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef ORC_RT_STRINGPOOL_H
-#define ORC_RT_STRINGPOOL_H
-
-#include <atomic>
-#include <cassert>
-#include <cstddef>
-#include <mutex>
-#include <string>
-#include <string_view>
-#include <unordered_map>
-#include <utility>
-
-namespace orc_rt {
-
-class PooledStringPtr;
-class NonOwningPooledStringPtr;
-
-/// Interns strings (e.g. symbol names, paths) behind ref-counted handles. An
-/// entry is kept alive as long as at least one PooledStringPtr refers to it;
-/// clearDeadEntries() reclaims entries with no owners left.
-///
-/// intern() and clearDeadEntries() may be called concurrently from any
-/// number of threads. Copying, moving, and destroying a PooledStringPtr
-/// requires no lock -- only the atomic refcount in that ptr's own entry is
-/// touched.
-class StringPool {
-private:
-  using RefCount = std::atomic<size_t>;
-  using PoolMap = std::unordered_map<std::string, RefCount>;
-
-public:
-  using PoolEntry = PoolMap::value_type;
-
-  StringPool() = default;
-  StringPool(const StringPool &) = delete;
-  StringPool &operator=(const StringPool &) = delete;
-  ~StringPool();
-
-  /// Returns the PooledStringPtr for S, interning a copy on first reference.
-  PooledStringPtr intern(std::string_view S);
-
-  /// Erase entries with no remaining PooledStringPtr owners.
-  void clearDeadEntries();
-
-  /// Returns true if this pool has no entries.
-  bool empty() const;
-
-private:
-  mutable std::mutex M;
-  PoolMap Pool;
-};
-
-/// Common base for PooledStringPtr and NonOwningPooledStringPtr: bool
-/// conversion, dereference, and comparison.
-///
-/// Comparisons and hashing are pointer-identity, scoped to whichever
-/// StringPool produced the handle -- handles from different pools are never
-/// equal, even for identical text.
-class PooledStringPtrBase {
-  friend class StringPoolEntryUnsafe;
-
-public:
-  PooledStringPtrBase() = default;
-  PooledStringPtrBase(std::nullptr_t) noexcept {}
-
-  explicit operator bool() const noexcept { return E != nullptr; }
-
-  const std::string &operator*() const noexcept { return E->first; }
-
-  friend bool operator==(PooledStringPtrBase LHS,
-                         PooledStringPtrBase RHS) noexcept {
-    return LHS.E == RHS.E;
-  }
-  friend bool operator!=(PooledStringPtrBase LHS,
-                         PooledStringPtrBase RHS) noexcept {
-    return !(LHS == RHS);
-  }
-  // Pointer-order only; not stable across runs (ASLR). Fine as a map/set key
-  // ordering, not for anything user-visible.
-  friend bool operator<(PooledStringPtrBase LHS,
-                        PooledStringPtrBase RHS) noexcept {
-    return LHS.E < RHS.E;
-  }
-
-protected:
-  using PoolEntry = StringPool::PoolEntry;
-
-  explicit PooledStringPtrBase(PoolEntry *E) noexcept : E(E) {}
-  PoolEntry *E = nullptr;
-};
-
-/// An owning, ref-counted handle to a string interned in some StringPool.
-class PooledStringPtr : public PooledStringPtrBase {
-  friend class StringPool;
-
-public:
-  PooledStringPtr() = default;
-  PooledStringPtr(std::nullptr_t) noexcept {}
-
-  /// Constructs an owning handle from a non-owning one, incrementing the
-  /// refcount. Other must be backed by an entry that some PooledStringPtr is
-  /// already keeping alive -- constructing from a NonOwningPooledStringPtr
-  /// whose entry has already been reclaimed by clearDeadEntries() is
-  /// undefined behavior.
-  explicit PooledStringPtr(NonOwningPooledStringPtr Other) noexcept;
-
-  PooledStringPtr(const PooledStringPtr &Other) noexcept
-      : PooledStringPtrBase(Other.E) {
-    incRef();
-  }
-
-  PooledStringPtr &operator=(const PooledStringPtr &Other) noexcept {
-    if (this != &Other) {
-      decRef();
-      E = Other.E;
-      incRef();
-    }
-    return *this;
-  }
-
-  PooledStringPtr(PooledStringPtr &&Other) noexcept { std::swap(E, Other.E); }
-
-  PooledStringPtr &operator=(PooledStringPtr &&Other) noexcept {
-    decRef();
-    E = nullptr;
-    std::swap(E, Other.E);
-    return *this;
-  }
-
-  ~PooledStringPtr() { decRef(); }
-
-private:
-  explicit PooledStringPtr(PoolEntry *E) noexcept : PooledStringPtrBase(E) {
-    incRef();
-  }
-
-  void incRef() noexcept {
-    if (E)
-      ++E->second;
-  }
-
-  void decRef() noexcept {
-    if (E) {
-      assert(E->second.load() != 0 && "double-release of PooledStringPtr");
-      --E->second;
-    }
-  }
-};
-
-/// A non-owning handle to a string interned in some StringPool.
-///
-/// Comparable and hashable interchangeably with PooledStringPtr (both wrap the
-/// same underlying entry pointer), but copying a NonOwningPooledStringPtr never
-/// touches the refcount, so it's cheaper to pass around than a PooledStringPtr.
-/// It is silently invalidated if the entry's refcount drops to zero and is
-/// reclaimed by clearDeadEntries(), so only use it where a corresponding
-/// PooledStringPtr is known to be keeping the entry alive -- e.g. as a lookup
-/// key into a table whose values (or a side table) hold the owning
-/// PooledStringPtr for that same entry.
-class NonOwningPooledStringPtr : public PooledStringPtrBase {
-public:
-  NonOwningPooledStringPtr() = default;
-  NonOwningPooledStringPtr(std::nullptr_t) noexcept {}
-  explicit NonOwningPooledStringPtr(const PooledStringPtr &Other) noexcept
-      : PooledStringPtrBase(Other) {}
-};
-
-/// Provides unsafe (refcount-bypassing) access to the pool-entry pointer
-/// underlying a PooledStringPtrBase. Used to implement std::hash and C API
-/// operations. Not intended for general use.
-class StringPoolEntryUnsafe {
-public:
-  using PoolEntry = StringPool::PoolEntry;
-
-  /// Extracts the pool-entry pointer from S without affecting its refcount.
-  static StringPoolEntryUnsafe from(const PooledStringPtrBase &S) {
-    return StringPoolEntryUnsafe(S.E);
-  }
-
-  const void *rawPtr() const { return E; }
-
-private:
-  StringPoolEntryUnsafe(PoolEntry *E) : E(E) {}
-  PoolEntry *E = nullptr;
-};
-
-inline PooledStringPtr::PooledStringPtr(NonOwningPooledStringPtr Other) noexcept
-    : PooledStringPtrBase(Other) {
-  incRef();
-}
-
-inline StringPool::~StringPool() {
-#ifndef NDEBUG
-  clearDeadEntries();
-  assert(Pool.empty() && "Dangling PooledStringPtr at StringPool destruction");
-#endif
-}
-
-inline PooledStringPtr StringPool::intern(std::string_view S) {
-  std::scoped_lock<std::mutex> Lock(M);
-  auto [I, Added] = Pool.try_emplace(std::string(S), 0);
-  return PooledStringPtr(&*I);
-}
-
-inline void StringPool::clearDeadEntries() {
-  std::scoped_lock<std::mutex> Lock(M);
-  for (auto I = Pool.begin(), E = Pool.end(); I != E;)
-    if (I->second.load() == 0)
-      I = Pool.erase(I);
-    else
-      ++I;
-}
-
-inline bool StringPool::empty() const {
-  std::scoped_lock<std::mutex> Lock(M);
-  return Pool.empty();
-}
-
-} // namespace orc_rt
-
-namespace std {
-template <> struct hash<orc_rt::PooledStringPtr> {
-  size_t operator()(const orc_rt::PooledStringPtr &S) const noexcept {
-    return hash<const void *>()(
-        orc_rt::StringPoolEntryUnsafe::from(S).rawPtr());
-  }
-};
-
-template <> struct hash<orc_rt::NonOwningPooledStringPtr> {
-  size_t operator()(const orc_rt::NonOwningPooledStringPtr &S) const noexcept {
-    return hash<const void *>()(
-        orc_rt::StringPoolEntryUnsafe::from(S).rawPtr());
-  }
-};
-} // namespace std
-
-#endif // ORC_RT_STRINGPOOL_H
diff --git a/orc-rt/test/unit/CMakeLists.txt b/orc-rt/test/unit/CMakeLists.txt
index 1916000506e31..7219c9897de1e 100644
--- a/orc-rt/test/unit/CMakeLists.txt
+++ b/orc-rt/test/unit/CMakeLists.txt
@@ -50,7 +50,6 @@ add_orc_rt_unittest(CoreTests
   SimpleSymbolTableTest.cpp
   StandaloneMachOUnwindInfoRegistrarTest.cpp
   StringExtrasTest.cpp
-  StringPoolTest.cpp
   TaskGroupTest.cpp
   ThreadPoolRunnerTest.cpp
   WrapperFunctionBufferTest.cpp
diff --git a/orc-rt/test/unit/StringPoolTest.cpp b/orc-rt/test/unit/StringPoolTest.cpp
deleted file mode 100644
index 85b866d12a275..0000000000000
--- a/orc-rt/test/unit/StringPoolTest.cpp
+++ /dev/null
@@ -1,166 +0,0 @@
-//===- StringPoolTest.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
-//
-//===----------------------------------------------------------------------===//
-//
-// Tests for orc-rt's StringPool.h APIs.
-//
-//===----------------------------------------------------------------------===//
-
-#include "orc-rt/StringPool.h"
-#include "gtest/gtest.h"
-
-#include <unordered_set>
-
-using namespace orc_rt;
-
-TEST(StringPoolTest, EmptyByDefault) {
-  StringPool SP;
-  EXPECT_TRUE(SP.empty());
-}
-
-TEST(StringPoolTest, InternReturnsEqualContent) {
-  StringPool SP;
-  auto Foo = SP.intern("foo");
-  EXPECT_TRUE(Foo);
-  EXPECT_EQ(*Foo, "foo");
-  EXPECT_FALSE(SP.empty());
-}
-
-TEST(StringPoolTest, RepeatedInternIsIdentical) {
-  StringPool SP;
-  auto Foo1 = SP.intern("foo");
-  auto Foo2 = SP.intern("foo");
-  EXPECT_EQ(Foo1, Foo2);
-}
-
-TEST(StringPoolTest, DifferentContentIsDistinct) {
-  StringPool SP;
-  auto Foo = SP.intern("foo");
-  auto Bar = SP.intern("bar");
-  EXPECT_NE(Foo, Bar);
-}
-
-TEST(StringPoolTest, DifferentPoolsAreDistinct) {
-  StringPool SP1, SP2;
-  auto Foo1 = SP1.intern("foo");
-  auto Foo2 = SP2.intern("foo");
-  EXPECT_EQ(*Foo1, *Foo2);
-  EXPECT_NE(Foo1, Foo2);
-}
-
-TEST(StringPoolTest, DefaultConstructedIsNull) {
-  PooledStringPtr Null;
-  EXPECT_FALSE(Null);
-  EXPECT_EQ(Null, PooledStringPtr(nullptr));
-}
-
-TEST(StringPoolTest, CopyKeepsEntryAlive) {
-  StringPool SP;
-  PooledStringPtr Copy;
-  {
-    auto Foo = SP.intern("foo");
-    Copy = Foo;
-  }
-  // Foo has been destroyed. If copy-assignment above failed to incRef, the
-  // entry's refcount would already be zero and clearDeadEntries() would
-  // reclaim it.
-  SP.clearDeadEntries();
-  ASSERT_FALSE(SP.empty()) << "Copy should have kept the entry alive";
-  EXPECT_EQ(*Copy, "foo");
-}
-
-TEST(StringPoolTest, ClearDeadEntriesReclaimsUnreferenced) {
-  StringPool SP;
-  {
-    auto Foo = SP.intern("foo");
-  }
-  EXPECT_FALSE(SP.empty());
-  SP.clearDeadEntries();
-  EXPECT_TRUE(SP.empty());
-}
-
-TEST(StringPoolTest, ClearDeadEntriesKeepsReferenced) {
-  StringPool SP;
-  auto Foo = SP.intern("foo");
-  {
-    auto Bar = SP.intern("bar");
-  }
-  SP.clearDeadEntries();
-  ASSERT_FALSE(SP.empty());
-  EXPECT_EQ(*Foo, "foo");
-}
-
-TEST(StringPoolTest, MoveLeavesSourceNull) {
-  StringPool SP;
-  auto Foo = SP.intern("foo");
-  auto Moved = std::move(Foo);
-  EXPECT_FALSE(Foo);
-  EXPECT_TRUE(Moved);
-  EXPECT_EQ(*Moved, "foo");
-}
-
-TEST(StringPoolTest, NonOwningPtrComparesEqualToOwning) {
-  StringPool SP;
-  auto Foo = SP.intern("foo");
-  NonOwningPooledStringPtr NonOwningFoo(Foo);
-  EXPECT_EQ(Foo, NonOwningFoo);
-  EXPECT_EQ(*NonOwningFoo, "foo");
-}
-
-TEST(StringPoolTest, NonOwningPtrDoesNotKeepEntryAlive) {
-  StringPool SP;
-  NonOwningPooledStringPtr NonOwningFoo;
-  {
-    auto Foo = SP.intern("foo");
-    NonOwningFoo = NonOwningPooledStringPtr(Foo);
-  }
-  // Foo has been destroyed and was the only owner, so the entry should be
-  // reclaimed even though NonOwningFoo still points at it.
-  SP.clearDeadEntries();
-  EXPECT_TRUE(SP.empty());
-}
-
-TEST(StringPoolTest, ConstructOwningFromNonOwningIncrementsRefcount) {
-  StringPool SP;
-  NonOwningPooledStringPtr NonOwningFoo;
-  {
-    auto Foo = SP.intern("foo");
-    NonOwningFoo = NonOwningPooledStringPtr(Foo);
-  }
-  // The entry's refcount is now zero, but it has not yet been reclaimed by
-  // clearDeadEntries(), so re-deriving an owning ptr from NonOwningFoo here
-  // is well-defined and should keep the entry alive.
-  PooledStringPtr Reowned(NonOwningFoo);
-  SP.clearDeadEntries();
-  ASSERT_FALSE(SP.empty());
-  EXPECT_EQ(*Reowned, "foo");
-}
-
-TEST(StringPoolTest, UsableAsUnorderedSetKey) {
-  StringPool SP;
-  auto Foo1 = SP.intern("foo");
-  auto Foo2 = SP.intern("foo");
-  auto Bar = SP.intern("bar");
-
-  std::unordered_set<PooledStringPtr> S;
-  S.insert(Foo1);
-  S.insert(Foo2);
-  S.insert(Bar);
-
-  EXPECT_EQ(S.size(), 2U);
-  EXPECT_TRUE(S.count(Foo1));
-  EXPECT_TRUE(S.count(Bar));
-}
-
-TEST(StringPoolTest, OwningAndNonOwningHashInterchangeably) {
-  StringPool SP;
-  auto Foo = SP.intern("foo");
-  NonOwningPooledStringPtr NonOwningFoo(Foo);
-
-  EXPECT_EQ(std::hash<PooledStringPtr>()(Foo),
-            std::hash<NonOwningPooledStringPtr>()(NonOwningFoo));
-}



More information about the llvm-commits mailing list