[clang] [llvm] [CodeGen][AArch64][FMV] PAC the stub_helper's frame on arm64e (PR #84704)

Jon Roelofs via llvm-commits llvm-commits at lists.llvm.org
Mon Jul 22 14:01:26 PDT 2024


https://github.com/jroelofs updated https://github.com/llvm/llvm-project/pull/84704

>From b352a41e1788819afbb15a5b6d79cbf2968dc5dc Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Sun, 10 Mar 2024 16:46:50 -0700
Subject: [PATCH 1/5] [CodeGen][AArch64][FMV] PAC the stub_helper's frame on
 arm64e

---
 clang/lib/CodeGen/CodeGenModule.cpp           | 18 ++++--
 .../test/CodeGen/attr-target-version-arm64e.c | 58 +++++++++++++++++++
 llvm/include/llvm/CodeGen/AsmPrinter.h        | 13 +++--
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp    |  3 +-
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 45 ++++++++++++++
 llvm/test/CodeGen/AArch64/ifunc-asm.ll        | 21 +++++--
 6 files changed, 142 insertions(+), 16 deletions(-)
 create mode 100644 clang/test/CodeGen/attr-target-version-arm64e.c

diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 967319bdfc457..dadc76d04c5f6 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4365,13 +4365,16 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
   // For cpu_specific, don't create an ifunc yet because we don't know if the
   // cpu_dispatch will be emitted in this translation unit.
   if (getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion()) {
-    llvm::Type *ResolverType = llvm::FunctionType::get(
+    llvm::FunctionType *ResolverType = llvm::FunctionType::get(
         llvm::PointerType::get(DeclTy,
                                getTypes().getTargetAddressSpace(FD->getType())),
         false);
-    llvm::Constant *Resolver = GetOrCreateLLVMFunction(
-        MangledName + ".resolver", ResolverType, GlobalDecl{},
-        /*ForVTable=*/false);
+    llvm::Function *Resolver = cast<llvm::Function>(
+        CreateRuntimeFunction(ResolverType, MangledName + ".resolver")
+            .getCallee());
+    llvm::AttrBuilder Attrs(getLLVMContext());
+    addDefaultFunctionDefinitionAttributes(Attrs);
+    Resolver->addFnAttrs(Attrs);
     llvm::GlobalIFunc *GIF =
         llvm::GlobalIFunc::create(DeclTy, 0, getMultiversionLinkage(*this, GD),
                                   "", Resolver, &getModule());
@@ -4381,8 +4384,11 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
     return GIF;
   }
 
-  llvm::Constant *Resolver = GetOrCreateLLVMFunction(
-      ResolverName, DeclTy, GlobalDecl{}, /*ForVTable=*/false);
+  llvm::Function *Resolver = cast<llvm::Function>(
+      CreateRuntimeFunction(DeclTy, ResolverName).getCallee());
+  llvm::AttrBuilder Attrs(getLLVMContext());
+  addDefaultFunctionDefinitionAttributes(Attrs);
+  Resolver->addFnAttrs(Attrs);
   assert(isa<llvm::GlobalValue>(Resolver) &&
          "Resolver should be created for the first time");
   SetCommonAttributes(FD, cast<llvm::GlobalValue>(Resolver));
diff --git a/clang/test/CodeGen/attr-target-version-arm64e.c b/clang/test/CodeGen/attr-target-version-arm64e.c
new file mode 100644
index 0000000000000..2deff9a688daa
--- /dev/null
+++ b/clang/test/CodeGen/attr-target-version-arm64e.c
@@ -0,0 +1,58 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals --include-generated-funcs
+// RUN: %clang_cc1 -triple arm64e-apple-ios -target-feature +ls64 -target-feature +fullfp16 -S -emit-llvm -o - %s | FileCheck %s
+
+int __attribute__((target_version("sha1"))) fmv(void) { return 1; }
+int __attribute__((target_version("default"))) fmv(void) { return 0; }
+int foo() {
+  return fmv();
+}
+
+//.
+// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
+// CHECK: @fmv.ifunc = weak_odr alias i32 (), ptr @fmv
+// CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver
+//.
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv._Msha1
+// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret i32 1
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@foo
+// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[CALL:%.*]] = call i32 @fmv()
+// CHECK-NEXT:    ret i32 [[CALL]]
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@fmv.resolver
+// CHECK-SAME: () #[[ATTR2:[0-9]+]] {
+// CHECK-NEXT:  resolver_entry:
+// CHECK-NEXT:    call void @__init_cpu_features_resolver()
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 2048
+// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 2048
+// CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
+// CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK:       resolver_return:
+// CHECK-NEXT:    ret ptr @fmv._Msha1
+// CHECK:       resolver_else:
+// CHECK-NEXT:    ret ptr @fmv.default
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv.default
+// CHECK-SAME: () #[[ATTR1]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret i32 0
+//
+//.
+// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon" }
+// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
+// CHECK: attributes #[[ATTR2]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
+//.
+// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
+// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
+//.
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index a7fbf4aeb7449..3b7e9c282120f 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -603,16 +603,21 @@ class AsmPrinter : public MachineFunctionPass {
     return nullptr;
   }
 
+  virtual const MCExpr *
+  emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
+    return Init;
+  }
+
   virtual void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
                                       MCSymbol *LazyPointer) {
-    llvm_unreachable(
-        "Mach-O IFunc lowering is not yet supported on this target");
+    assert(false &&
+           "Mach-O IFunc lowering is not yet supported on this target");
   }
 
   virtual void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
                                             MCSymbol *LazyPointer) {
-    llvm_unreachable(
-        "Mach-O IFunc lowering is not yet supported on this target");
+    assert(false &&
+           "Mach-O IFunc lowering is not yet supported on this target");
   }
 
   /// Emit N NOP instructions.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 0efe7a0e73367..b70221cdec296 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2259,7 +2259,8 @@ void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
   emitAlignment(Align(DL.getPointerSize()));
   OutStreamer->emitLabel(LazyPointer);
   emitVisibility(LazyPointer, GI.getVisibility());
-  OutStreamer->emitValue(MCSymbolRefExpr::create(StubHelper, OutContext), 8);
+  const MCSymbolRefExpr *Init = MCSymbolRefExpr::create(StubHelper, OutContext);
+  OutStreamer->emitValue(emitMachOIfuncLazyPointerInit(Init), 8);
 
   OutStreamer->switchSection(OutContext.getObjectFileInfo()->getTextSection());
 
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 4fa719ad67cf3..f191fe3259d27 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -208,6 +208,8 @@ class AArch64AsmPrinter : public AsmPrinter {
     assert(STI);
     return STI;
   }
+  const MCExpr *
+  emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) override;
   void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
                               MCSymbol *LazyPointer) override;
   void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
@@ -1897,6 +1899,15 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
   EmitToStreamer(*OutStreamer, TmpInst);
 }
 
+const MCExpr *
+AArch64AsmPrinter::emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
+  if (TM.getTargetTriple().isArm64e())
+    return AArch64AuthMCExpr::create(Init, /*Disc=*/0, AArch64PACKey::IA,
+                                     /*HasAddressDiversity=*/false, OutContext);
+
+  return Init;
+}
+
 void AArch64AsmPrinter::emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
                                                MCSymbol *LazyPointer) {
   // _ifunc:
@@ -1980,6 +1991,9 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
   //   ldp	fp, lr, [sp], #16
   //   br	x16
 
+  if (TM.getTargetTriple().isArm64e())
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::PACIBSP), *STI);
+
   OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXpre)
                                    .addReg(AArch64::SP)
                                    .addReg(AArch64::FP)
@@ -2085,6 +2099,37 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
                                    .addImm(2),
                                *STI);
 
+  if (TM.getTargetTriple().isArm64e()) {
+    //   autibsp
+    //   eor x17, lr, lr, lsl #1
+    //   tbz x17, #62, Lgoodsig
+    //   brk #0xc741
+    // Lgoodsig:
+
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::AUTIBSP), *STI);
+
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::EORXrs)
+                                     .addReg(AArch64::X17)
+                                     .addReg(AArch64::LR)
+                                     .addReg(AArch64::LR)
+                                     .addImm(1),
+                                 *STI);
+
+    MCContext &Ctx = OutStreamer->getContext();
+    MCSymbol *GoodSigSym = Ctx.createTempSymbol();
+    const MCExpr *GoodSig = MCSymbolRefExpr::create(GoodSigSym, Ctx);
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::TBZX)
+                                     .addReg(AArch64::X17)
+                                     .addImm(62)
+                                     .addExpr(GoodSig),
+                                 *STI);
+
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::BRK).addImm(0xc471),
+                                 *STI);
+
+    OutStreamer->emitLabel(GoodSigSym);
+  }
+
   OutStreamer->emitInstruction(MCInstBuilder(TM.getTargetTriple().isArm64e()
                                                  ? AArch64::BRAAZ
                                                  : AArch64::BR)
diff --git a/llvm/test/CodeGen/AArch64/ifunc-asm.ll b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
index 57fc2f0c9d7f5..6f0d6f633fd51 100644
--- a/llvm/test/CodeGen/AArch64/ifunc-asm.ll
+++ b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
@@ -1,6 +1,8 @@
 ; RUN: llc -mtriple=arm64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=ELF
-; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefix=MACHO
-; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefix=MACHO
+; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,ARM64
+; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,ARM64
+; RUN: llc -mtriple=arm64e-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
+; RUN: llc -mtriple=arm64e-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
 
 define internal ptr @the_resolver() {
 entry:
@@ -21,7 +23,8 @@ entry:
 ; MACHO:           .section __DATA,__data
 ; MACHO-NEXT:      .p2align 3, 0x0
 ; MACHO-NEXT:  _global_ifunc.lazy_pointer:
-; MACHO-NEXT:      .quad _global_ifunc.stub_helper
+; ARM64-NEXT:      .quad _global_ifunc.stub_helper{{$}}
+; PAUTH-NEXT:      .quad _global_ifunc.stub_helper at AUTH(ia,0)
 
 ; MACHO:           .section __TEXT,__text,regular,pure_instructions
 ; MACHO-NEXT:      .globl _global_ifunc
@@ -30,9 +33,11 @@ entry:
 ; MACHO-NEXT:      adrp    x16, _global_ifunc.lazy_pointer at GOTPAGE
 ; MACHO-NEXT:      ldr     x16, [x16, _global_ifunc.lazy_pointer at GOTPAGEOFF]
 ; MACHO-NEXT:      ldr     x16, [x16]
-; MACHO-NEXT:      br      x16
+; ARM64-NEXT:      br      x16
+; PAUTH-NEXT:      braaz   x16
 ; MACHO-NEXT:      .p2align        2
 ; MACHO-NEXT:  _global_ifunc.stub_helper:
+; PAUTH-NEXT:      pacibsp
 ; MACHO-NEXT:      stp     x29, x30, [sp, #-16]!
 ; MACHO-NEXT:      mov     x29, sp
 ; MACHO-NEXT:      stp     x1, x0, [sp, #-16]!
@@ -57,7 +62,13 @@ entry:
 ; MACHO-NEXT:      ldp     x3, x2, [sp], #16
 ; MACHO-NEXT:      ldp     x1, x0, [sp], #16
 ; MACHO-NEXT:      ldp     x29, x30, [sp], #16
-; MACHO-NEXT:      br      x16
+; PAUTH-NEXT:      autibsp
+; PAUTH-NEXT:      eor     x17, x30, x30, lsl #1
+; PAUTH-NEXT:      tbz     x17, #62, [[GOOD_SIG:Ltmp[0-9]+]]
+; PAUTH-NEXT:      brk     #0xc471
+; PAUTH-NEXT: [[GOOD_SIG]]:
+; ARM64-NEXT:      br      x16
+; PAUTH-NEXT:      braaz   x16
 
 
 @weak_ifunc = weak ifunc i32 (i32), ptr @the_resolver

>From 73aa83448691d3e6af07025572eaf5abef4b4469 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Sun, 10 Mar 2024 16:46:50 -0700
Subject: [PATCH 2/5] fixup tests

---
 clang/test/CodeGen/attr-cpuspecific.c         | 24 +++++-----
 clang/test/CodeGen/attr-target-clones.c       | 46 +++++++++----------
 clang/test/CodeGen/attr-target-mv-va-args.c   |  6 +--
 clang/test/CodeGen/attr-target-mv.c           | 18 ++++----
 clang/test/CodeGen/attr-target-version.c      | 23 ++++++----
 clang/test/CodeGenCXX/attr-cpuspecific.cpp    |  2 +-
 clang/test/CodeGenCXX/attr-target-clones.cpp  |  4 +-
 .../CodeGenCXX/attr-target-mv-diff-ns.cpp     |  4 +-
 .../attr-target-mv-member-funcs.cpp           |  2 +-
 .../attr-target-mv-out-of-line-defs.cpp       |  2 +-
 .../CodeGenCXX/attr-target-mv-overloads.cpp   |  4 +-
 11 files changed, 71 insertions(+), 64 deletions(-)

diff --git a/clang/test/CodeGen/attr-cpuspecific.c b/clang/test/CodeGen/attr-cpuspecific.c
index 2c3e6931800cd..7fe14bec68d9d 100644
--- a/clang/test/CodeGen/attr-cpuspecific.c
+++ b/clang/test/CodeGen/attr-cpuspecific.c
@@ -51,7 +51,7 @@ void SingleVersion(void);
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @SingleVersion() comdat
+// WINDOWS: define weak_odr dso_local void @SingleVersion() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: %[[FEAT_INIT:.+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0), align 4
 // WINDOWS: %[[FEAT_JOIN:.+]] = and i32 %[[FEAT_INIT]], 525311
@@ -82,7 +82,7 @@ void TwoVersions(void);
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @TwoVersions() comdat
+// WINDOWS: define weak_odr dso_local void @TwoVersions() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: %[[FEAT_INIT:.+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0), align 4
 // WINDOWS: %[[FEAT_JOIN:.+]] = and i32 %[[FEAT_INIT]], 59754495
@@ -125,7 +125,7 @@ void OrderDispatchUsageSpecific(void);
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @OrderDispatchUsageSpecific() comdat
+// WINDOWS: define weak_odr dso_local void @OrderDispatchUsageSpecific() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: call void @OrderDispatchUsageSpecific.Z()
 // WINDOWS-NEXT: ret void
@@ -174,7 +174,7 @@ void TwoVersionsSameAttr(void);
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @TwoVersionsSameAttr() comdat
+// WINDOWS: define weak_odr dso_local void @TwoVersionsSameAttr() {{.*}} comdat
 // WINDOWS: call void @TwoVersionsSameAttr.Z
 // WINDOWS-NEXT: ret void
 // WINDOWS: call void @TwoVersionsSameAttr.S
@@ -194,7 +194,7 @@ void ThreeVersionsSameAttr(void){}
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @ThreeVersionsSameAttr() comdat
+// WINDOWS: define weak_odr dso_local void @ThreeVersionsSameAttr() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @ThreeVersionsSameAttr.Z
 // WINDOWS-NEXT: ret void
@@ -210,7 +210,7 @@ void OrderSpecificUsageDispatch(void);
 // LINUX: define weak_odr ptr @OrderSpecificUsageDispatch.resolver()
 // LINUX: ret ptr @OrderSpecificUsageDispatch.Z
 
-// WINDOWS: define weak_odr dso_local void @OrderSpecificUsageDispatch() comdat
+// WINDOWS: define weak_odr dso_local void @OrderSpecificUsageDispatch() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @OrderSpecificUsageDispatch.Z
 // WINDOWS-NEXT: ret void
@@ -226,7 +226,7 @@ void NoSpecifics(void);
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @NoSpecifics() comdat
+// WINDOWS: define weak_odr dso_local void @NoSpecifics() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @NoSpecifics.Z
 // WINDOWS-NEXT: ret void
@@ -247,7 +247,7 @@ void HasGeneric(void);
 // LINUX: ret ptr @HasGeneric.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define weak_odr dso_local void @HasGeneric() comdat
+// WINDOWS: define weak_odr dso_local void @HasGeneric() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @HasGeneric.Z
 // WINDOWS-NEXT: ret void
@@ -269,7 +269,7 @@ void HasParams(int i, double d);
 // LINUX: ret ptr @HasParams.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define weak_odr dso_local void @HasParams(i32 %0, double %1) comdat
+// WINDOWS: define weak_odr dso_local void @HasParams(i32 %0, double %1) {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @HasParams.Z(i32 %0, double %1)
 // WINDOWS-NEXT: ret void
@@ -291,7 +291,7 @@ int HasParamsAndReturn(int i, double d);
 // LINUX: ret ptr @HasParamsAndReturn.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define weak_odr dso_local i32 @HasParamsAndReturn(i32 %0, double %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @HasParamsAndReturn(i32 %0, double %1) {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.Z(i32 %0, double %1)
 // WINDOWS-NEXT: ret i32 %[[RET]]
@@ -312,7 +312,7 @@ int GenericAndPentium(int i, double d);
 // LINUX-NOT: ret ptr @GenericAndPentium.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define weak_odr dso_local i32 @GenericAndPentium(i32 %0, double %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @GenericAndPentium(i32 %0, double %1) {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.O(i32 %0, double %1)
 // WINDOWS-NEXT: ret i32 %[[RET]]
@@ -327,7 +327,7 @@ int DispatchFirst(void);
 // LINUX: ret ptr @DispatchFirst.O
 // LINUX: ret ptr @DispatchFirst.B
 
-// WINDOWS: define weak_odr dso_local i32 @DispatchFirst() comdat
+// WINDOWS: define weak_odr dso_local i32 @DispatchFirst() {{.*}} comdat
 // WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.O()
 // WINDOWS-NEXT: ret i32 %[[RET]]
 // WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.B()
diff --git a/clang/test/CodeGen/attr-target-clones.c b/clang/test/CodeGen/attr-target-clones.c
index 3256db061f9a2..730321e185fba 100644
--- a/clang/test/CodeGen/attr-target-clones.c
+++ b/clang/test/CodeGen/attr-target-clones.c
@@ -44,45 +44,45 @@
 static int __attribute__((target_clones("sse4.2, default"))) internal(void) { return 0; }
 int use(void) { return internal(); }
 /// Internal linkage resolvers do not use comdat.
-// LINUX: define internal ptr @internal.resolver() {
-// DARWIN: define internal ptr @internal.resolver() {
-// WINDOWS: define internal i32 @internal() {
+// LINUX: define internal ptr @internal.resolver()
+// DARWIN: define internal ptr @internal.resolver()
+// WINDOWS: define internal i32 @internal()
 
 int __attribute__((target_clones("sse4.2, default"))) foo(void) { return 0; }
 // LINUX: define {{.*}}i32 @foo.sse4.2.0()
 // LINUX: define {{.*}}i32 @foo.default.1()
-// LINUX: define weak_odr ptr @foo.resolver() comdat
+// LINUX: define weak_odr ptr @foo.resolver() {{.*}} comdat
 // LINUX: ret ptr @foo.sse4.2.0
 // LINUX: ret ptr @foo.default.1
 
 // DARWIN: define {{.*}}i32 @foo.sse4.2.0()
 // DARWIN: define {{.*}}i32 @foo.default.1()
-// DARWIN: define weak_odr ptr @foo.resolver() {
+// DARWIN: define weak_odr ptr @foo.resolver()
 // DARWIN: ret ptr @foo.sse4.2.0
 // DARWIN: ret ptr @foo.default.1
 
 // WINDOWS: define dso_local i32 @foo.sse4.2.0()
 // WINDOWS: define dso_local i32 @foo.default.1()
-// WINDOWS: define weak_odr dso_local i32 @foo() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo() {{.*}} comdat
 // WINDOWS: musttail call i32 @foo.sse4.2.0
 // WINDOWS: musttail call i32 @foo.default.1
 
 __attribute__((target_clones("default,default ,sse4.2"))) void foo_dupes(void) {}
 // LINUX: define {{.*}}void @foo_dupes.default.1()
 // LINUX: define {{.*}}void @foo_dupes.sse4.2.0()
-// LINUX: define weak_odr ptr @foo_dupes.resolver() comdat
+// LINUX: define weak_odr ptr @foo_dupes.resolver() {{.*}} comdat
 // LINUX: ret ptr @foo_dupes.sse4.2.0
 // LINUX: ret ptr @foo_dupes.default.1
 
 // DARWIN: define {{.*}}void @foo_dupes.default.1()
 // DARWIN: define {{.*}}void @foo_dupes.sse4.2.0()
-// DARWIN: define weak_odr ptr @foo_dupes.resolver() {
+// DARWIN: define weak_odr ptr @foo_dupes.resolver()
 // DARWIN: ret ptr @foo_dupes.sse4.2.0
 // DARWIN: ret ptr @foo_dupes.default.1
 
 // WINDOWS: define dso_local void @foo_dupes.default.1()
 // WINDOWS: define dso_local void @foo_dupes.sse4.2.0()
-// WINDOWS: define weak_odr dso_local void @foo_dupes() comdat
+// WINDOWS: define weak_odr dso_local void @foo_dupes() {{.*}} comdat
 // WINDOWS: musttail call void @foo_dupes.sse4.2.0
 // WINDOWS: musttail call void @foo_dupes.default.1
 
@@ -109,19 +109,19 @@ int bar(void) {
 void __attribute__((target_clones("default, arch=ivybridge"))) unused(void) {}
 // LINUX: define {{.*}}void @unused.default.1()
 // LINUX: define {{.*}}void @unused.arch_ivybridge.0()
-// LINUX: define weak_odr ptr @unused.resolver() comdat
+// LINUX: define weak_odr ptr @unused.resolver() {{.*}} comdat
 // LINUX: ret ptr @unused.arch_ivybridge.0
 // LINUX: ret ptr @unused.default.1
 
 // DARWIN: define {{.*}}void @unused.default.1()
 // DARWIN: define {{.*}}void @unused.arch_ivybridge.0()
-// DARWIN: define weak_odr ptr @unused.resolver() {
+// DARWIN: define weak_odr ptr @unused.resolver()
 // DARWIN: ret ptr @unused.arch_ivybridge.0
 // DARWIN: ret ptr @unused.default.1
 
 // WINDOWS: define dso_local void @unused.default.1()
 // WINDOWS: define dso_local void @unused.arch_ivybridge.0()
-// WINDOWS: define weak_odr dso_local void @unused() comdat
+// WINDOWS: define weak_odr dso_local void @unused() {{.*}} comdat
 // WINDOWS: musttail call void @unused.arch_ivybridge.0
 // WINDOWS: musttail call void @unused.default.1
 
@@ -144,34 +144,34 @@ int bar3(void) {
   // WINDOWS: call i32 @foo_inline2()
 }
 
-// LINUX: define weak_odr ptr @foo_inline.resolver() comdat
+// LINUX: define weak_odr ptr @foo_inline.resolver() {{.*}} comdat
 // LINUX: ret ptr @foo_inline.arch_sandybridge.0
 // LINUX: ret ptr @foo_inline.sse4.2.1
 // LINUX: ret ptr @foo_inline.default.2
 
-// DARWIN: define weak_odr ptr @foo_inline.resolver() {
+// DARWIN: define weak_odr ptr @foo_inline.resolver()
 // DARWIN: ret ptr @foo_inline.arch_sandybridge.0
 // DARWIN: ret ptr @foo_inline.sse4.2.1
 // DARWIN: ret ptr @foo_inline.default.2
 
-// WINDOWS: define weak_odr dso_local i32 @foo_inline() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo_inline() {{.*}} comdat
 // WINDOWS: musttail call i32 @foo_inline.arch_sandybridge.0
 // WINDOWS: musttail call i32 @foo_inline.sse4.2.1
 // WINDOWS: musttail call i32 @foo_inline.default.2
 
 inline int __attribute__((target_clones("arch=sandybridge,default,sse4.2")))
 foo_inline2(void){ return 0; }
-// LINUX: define weak_odr ptr @foo_inline2.resolver() comdat
+// LINUX: define weak_odr ptr @foo_inline2.resolver() {{.*}} comdat
 // LINUX: ret ptr @foo_inline2.arch_sandybridge.0
 // LINUX: ret ptr @foo_inline2.sse4.2.1
 // LINUX: ret ptr @foo_inline2.default.2
 
-// DARWIN: define weak_odr ptr @foo_inline2.resolver() {
+// DARWIN: define weak_odr ptr @foo_inline2.resolver()
 // DARWIN: ret ptr @foo_inline2.arch_sandybridge.0
 // DARWIN: ret ptr @foo_inline2.sse4.2.1
 // DARWIN: ret ptr @foo_inline2.default.2
 
-// WINDOWS: define weak_odr dso_local i32 @foo_inline2() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo_inline2() {{.*}} comdat
 // WINDOWS: musttail call i32 @foo_inline2.arch_sandybridge.0
 // WINDOWS: musttail call i32 @foo_inline2.sse4.2.1
 // WINDOWS: musttail call i32 @foo_inline2.default.2
@@ -194,15 +194,15 @@ int test_foo_used_no_defn(void) {
 }
 
 
-// LINUX: define weak_odr ptr @foo_used_no_defn.resolver() comdat
+// LINUX: define weak_odr ptr @foo_used_no_defn.resolver() {{.*}} comdat
 // LINUX: ret ptr @foo_used_no_defn.sse4.2.0
 // LINUX: ret ptr @foo_used_no_defn.default.1
 
-// DARWIN: define weak_odr ptr @foo_used_no_defn.resolver() {
+// DARWIN: define weak_odr ptr @foo_used_no_defn.resolver()
 // DARWIN: ret ptr @foo_used_no_defn.sse4.2.0
 // DARWIN: ret ptr @foo_used_no_defn.default.1
 
-// WINDOWS: define weak_odr dso_local i32 @foo_used_no_defn() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo_used_no_defn() {{.*}} comdat
 // WINDOWS: musttail call i32 @foo_used_no_defn.sse4.2.0
 // WINDOWS: musttail call i32 @foo_used_no_defn.default.1
 
@@ -213,7 +213,7 @@ int isa_level(int) { return 0; }
 // LINUX:      define{{.*}} i32 @isa_level.arch_x86-64-v2.1(
 // LINUX:      define{{.*}} i32 @isa_level.arch_x86-64-v3.2(
 // LINUX:      define{{.*}} i32 @isa_level.arch_x86-64-v4.3(
-// LINUX:      define weak_odr ptr @isa_level.resolver() comdat
+// LINUX:      define weak_odr ptr @isa_level.resolver() {{.*}} comdat
 // LINUX:        call void @__cpu_indicator_init()
 // LINUX-NEXT:   load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
 // LINUX-NEXT:   and i32 %[[#]], 4
@@ -234,7 +234,7 @@ int isa_level(int) { return 0; }
 // DARWIN:      define{{.*}} i32 @isa_level.arch_x86-64-v2.1(
 // DARWIN:      define{{.*}} i32 @isa_level.arch_x86-64-v3.2(
 // DARWIN:      define{{.*}} i32 @isa_level.arch_x86-64-v4.3(
-// DARWIN:      define weak_odr ptr @isa_level.resolver() {
+// DARWIN:      define weak_odr ptr @isa_level.resolver()
 // DARWIN:        call void @__cpu_indicator_init()
 // DARWIN-NEXT:   load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
 // DARWIN-NEXT:   and i32 %[[#]], 4
diff --git a/clang/test/CodeGen/attr-target-mv-va-args.c b/clang/test/CodeGen/attr-target-mv-va-args.c
index dbf5a74205c4c..5147f87bc52f7 100644
--- a/clang/test/CodeGen/attr-target-mv-va-args.c
+++ b/clang/test/CodeGen/attr-target-mv-va-args.c
@@ -24,7 +24,7 @@ int bar(void) {
 // IFUNC-ELF: call i32 (i32, ...) @foo.ifunc(i32 noundef 1, i32 noundef 97, double
 // IFUNC-ELF: call i32 (i32, ...) @foo.ifunc(i32 noundef 2, double noundef 2.2{{[0-9Ee+]+}}, ptr noundef
 
-// IFUNC-ELF: define weak_odr ptr @foo.resolver() comdat
+// IFUNC-ELF: define weak_odr ptr @foo.resolver() {{.*}} comdat
 // IFUNC-ELF: ret ptr @foo.arch_sandybridge
 // IFUNC-ELF: ret ptr @foo.arch_ivybridge
 // IFUNC-ELF: ret ptr @foo.sse4.2
@@ -59,8 +59,8 @@ int bar(void) {
 // NO-IFUNC: call i32 (i32, ...) @foo.resolver(i32 noundef 1, i32 noundef 97, double
 // NO-IFUNC: call i32 (i32, ...) @foo.resolver(i32 noundef 2, double noundef 2.2{{[0-9Ee+]+}}, ptr noundef
 
-// WINDOWS: define weak_odr dso_local i32 @foo.resolver(i32 %0, ...) comdat
-// NO-IFUNC-ELF: define weak_odr i32 @foo.resolver(i32 %0, ...) comdat
+// WINDOWS: define weak_odr dso_local i32 @foo.resolver(i32 %0, ...) {{.*}} comdat
+// NO-IFUNC-ELF: define weak_odr i32 @foo.resolver(i32 %0, ...) {{.*}} comdat
 // NO-IFUNC: musttail call i32 (i32, ...) @foo.arch_sandybridge
 // NO-IFUNC: musttail call i32 (i32, ...) @foo.arch_ivybridge
 // NO-IFUNC: musttail call i32 (i32, ...) @foo.sse4.2
diff --git a/clang/test/CodeGen/attr-target-mv.c b/clang/test/CodeGen/attr-target-mv.c
index 2c4b95ca04370..f31ca5a8d1401 100644
--- a/clang/test/CodeGen/attr-target-mv.c
+++ b/clang/test/CodeGen/attr-target-mv.c
@@ -270,7 +270,7 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @foo.sse4.2
 // ITANIUM: ret ptr @foo
 
-// WINDOWS: define weak_odr dso_local i32 @foo.resolver() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo.resolver() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: call i32 @foo.arch_sandybridge
 // WINDOWS: call i32 @foo.arch_ivybridge
@@ -278,9 +278,9 @@ void calls_pr50025c(void) { pr50025c(); }
 // WINDOWS: call i32 @foo
 
 /// Internal linkage resolvers do not use comdat.
-// ITANIUM: define internal ptr @foo_internal.resolver() {
+// ITANIUM: define internal ptr @foo_internal.resolver() #[[ATTR:[0-9]+]] {
 
-// WINDOWS: define internal i32 @foo_internal.resolver() {
+// WINDOWS: define internal i32 @foo_internal.resolver() {{.*}} {
 
 // ITANIUM: define{{.*}} i32 @bar2()
 // ITANIUM: call i32 @foo_inline.ifunc()
@@ -296,7 +296,7 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @foo_inline.sse4.2
 // ITANIUM: ret ptr @foo_inline
 
-// WINDOWS: define weak_odr dso_local i32 @foo_inline.resolver() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo_inline.resolver() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: call i32 @foo_inline.arch_sandybridge
 // WINDOWS: call i32 @foo_inline.arch_ivybridge
@@ -314,7 +314,7 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @foo_decls.sse4.2
 // ITANIUM: ret ptr @foo_decls
 
-// WINDOWS: define weak_odr dso_local void @foo_decls.resolver() comdat
+// WINDOWS: define weak_odr dso_local void @foo_decls.resolver() {{.*}} comdat
 // WINDOWS: call void @foo_decls.sse4.2
 // WINDOWS: call void @foo_decls
 
@@ -338,7 +338,7 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @foo_multi.avx_sse4.2
 // ITANIUM: ret ptr @foo_multi
 
-// WINDOWS: define weak_odr dso_local void @foo_multi.resolver(i32 %0, double %1) comdat
+// WINDOWS: define weak_odr dso_local void @foo_multi.resolver(i32 %0, double %1) {{.*}} comdat
 // WINDOWS: and i32 %{{.*}}, 4352
 // WINDOWS: icmp eq i32 %{{.*}}, 4352
 // WINDOWS: call void @foo_multi.fma4_sse4.2(i32 %0, double %1)
@@ -387,10 +387,10 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @fwd_decl_avx.avx
 // ITANIUM: ret ptr @fwd_decl_avx
 
-// WINDOWS: define weak_odr dso_local i32 @fwd_decl_default.resolver() comdat
+// WINDOWS: define weak_odr dso_local i32 @fwd_decl_default.resolver() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: call i32 @fwd_decl_default
-// WINDOWS: define weak_odr dso_local i32 @fwd_decl_avx.resolver() comdat
+// WINDOWS: define weak_odr dso_local i32 @fwd_decl_avx.resolver() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: call i32 @fwd_decl_avx.avx
 // WINDOWS: call i32 @fwd_decl_avx
@@ -468,7 +468,7 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @pr50025b
 // ITANIUM: define linkonce void @pr50025b()
 // ITANIUM: call void @must_be_emitted()
-// WINDOWS: define weak_odr dso_local void @pr50025b.resolver() comdat
+// WINDOWS: define weak_odr dso_local void @pr50025b.resolver() {{.*}} comdat
 // WINDOWS: musttail call void @pr50025b()
 // WINDOWS: define linkonce_odr dso_local void @pr50025b() #{{[0-9]*}} comdat
 // WINDOWS: call void @must_be_emitted()
diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c
index b7112c783da91..1e0568e884643 100644
--- a/clang/test/CodeGen/attr-target-version.c
+++ b/clang/test/CodeGen/attr-target-version.c
@@ -138,7 +138,8 @@ int hoo(void) {
 // CHECK-NEXT:    ret i32 [[ADD3]]
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv.resolver
+// CHECK-SAME: () #[[ATTR3:[0-9]+]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -216,17 +217,20 @@ int hoo(void) {
 // CHECK-NEXT:    ret ptr @fmv.default
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_one.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv_one.resolver
+// CHECK-SAME: () #[[ATTR3]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    ret ptr @fmv_one._Mls64Msimd
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_two.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv_two.resolver
+// CHECK-SAME: () #[[ATTR3]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    ret ptr @fmv_two._Mfp16Msimd
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_e.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv_e.resolver
+// CHECK-SAME: () #[[ATTR3]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    ret ptr @fmv_e._Mls64
 //
@@ -238,7 +242,8 @@ int hoo(void) {
 // CHECK-NEXT:    ret i32 111
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver
+// CHECK-SAME: () #[[ATTR3]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -264,7 +269,8 @@ int hoo(void) {
 // CHECK-NEXT:    ret i32 [[CALL3]]
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline.resolver
+// CHECK-SAME: () #[[ATTR3]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -398,7 +404,8 @@ int hoo(void) {
 // CHECK-NEXT:    ret ptr @fmv_inline.default
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_d.resolver() {
+// CHECK-LABEL: define {{[^@]+}}@fmv_d.resolver
+// CHECK-SAME: () #[[ATTR3]] {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -819,7 +826,7 @@ int hoo(void) {
 // CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+flagm,+fp-armv8,+fp16fml,+fullfp16,+ls64,+neon,+rand" }
 // CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon" }
 // CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
-// CHECK: attributes #[[ATTR3:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
+// CHECK: attributes #[[ATTR3]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
 // CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+altnzcv,+bf16,+flagm,+fullfp16,+ls64,+sme,+sme-i16i64" }
 // CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+lse,+neon,+sha2" }
 // CHECK: attributes #[[ATTR6]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+fullfp16,+ls64,+neon" }
diff --git a/clang/test/CodeGenCXX/attr-cpuspecific.cpp b/clang/test/CodeGenCXX/attr-cpuspecific.cpp
index 225c6a5c742a5..688650595b67c 100644
--- a/clang/test/CodeGenCXX/attr-cpuspecific.cpp
+++ b/clang/test/CodeGenCXX/attr-cpuspecific.cpp
@@ -22,7 +22,7 @@ void foo() {
 // LINUX: declare void @_ZN1S4FuncEv.S
 // LINUX: define linkonce_odr void @_ZN1S4FuncEv.O
 
-// WINDOWS: define weak_odr dso_local void @"?Func at S@@QEAAXXZ"(ptr %0) comdat
+// WINDOWS: define weak_odr dso_local void @"?Func at S@@QEAAXXZ"(ptr %0) {{.*}} comdat
 // WINDOWS: musttail call void @"?Func at S@@QEAAXXZ.S"(ptr %0)
 // WINDOWS: musttail call void @"?Func at S@@QEAAXXZ.O"(ptr %0)
 // WINDOWS: declare dso_local void @"?Func at S@@QEAAXXZ.S"
diff --git a/clang/test/CodeGenCXX/attr-target-clones.cpp b/clang/test/CodeGenCXX/attr-target-clones.cpp
index 0814df312f4d8..7bf5eb630d86a 100644
--- a/clang/test/CodeGenCXX/attr-target-clones.cpp
+++ b/clang/test/CodeGenCXX/attr-target-clones.cpp
@@ -29,7 +29,7 @@ int __attribute__((target_clones("sse4.2", "default"))) overloaded(int) { return
 
 // WINDOWS: define dso_local noundef i32 @"?overloaded@@YAHH at Z.sse4.2.0"(i32{{.+}})
 // WINDOWS: define dso_local noundef i32 @"?overloaded@@YAHH at Z.default.1"(i32{{.+}})
-// WINDOWS: define weak_odr dso_local i32 @"?overloaded@@YAHH at Z"(i32{{.+}}) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?overloaded@@YAHH at Z"(i32{{.+}}) {{.*}} comdat
 // WINDOWS: call i32 @"?overloaded@@YAHH at Z.sse4.2.0"
 // WINDOWS: call i32 @"?overloaded@@YAHH at Z.default.1"
 
@@ -43,7 +43,7 @@ int __attribute__((target_clones("arch=ivybridge", "default"))) overloaded(const
 
 // WINDOWS: define dso_local noundef i32 @"?overloaded@@YAHPEBD at Z.arch_ivybridge.0"(ptr{{.+}})
 // WINDOWS: define dso_local noundef i32 @"?overloaded@@YAHPEBD at Z.default.1"(ptr{{.+}})
-// WINDOWS: define weak_odr dso_local i32 @"?overloaded@@YAHPEBD at Z"(ptr{{.+}}) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?overloaded@@YAHPEBD at Z"(ptr{{.+}}) {{.*}} comdat
 // WINDOWS: call i32 @"?overloaded@@YAHPEBD at Z.arch_ivybridge.0"
 // WINDOWS: call i32 @"?overloaded@@YAHPEBD at Z.default.1"
 
diff --git a/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp b/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
index 8f2fb5ef0df7e..7dae27d3d2a72 100644
--- a/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
+++ b/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
@@ -67,7 +67,7 @@ int bar() {
 // ITANIUM: ret ptr @_Z3fooi.sse4.2
 // ITANIUM: ret ptr @_Z3fooi
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo@@YAHH at Z.resolver"(i32 %0) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo@@YAHH at Z.resolver"(i32 %0) {{.*}} comdat
 // WINDOWS: call i32 @"?foo@@YAHH at Z.arch_sandybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo@@YAHH at Z.arch_ivybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo@@YAHH at Z.sse4.2"(i32 %0)
@@ -80,7 +80,7 @@ int bar() {
 // ITANIUM: ret ptr @_ZN2ns3fooEi.sse4.2
 // ITANIUM: ret ptr @_ZN2ns3fooEi
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo at ns@@YAHH at Z.resolver"(i32 %0) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo at ns@@YAHH at Z.resolver"(i32 %0) {{.*}} comdat
 // WINDOWS: call i32 @"?foo at ns@@YAHH at Z.arch_sandybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo at ns@@YAHH at Z.arch_ivybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo at ns@@YAHH at Z.sse4.2"(i32 %0)
diff --git a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
index f956890cf706e..1181f5b5d743d 100644
--- a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
+++ b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
@@ -180,7 +180,7 @@ int templ_use() {
 // ITANIUM: ret ptr @_ZN5templIdE3fooEi.sse4.2
 // ITANIUM: ret ptr @_ZN5templIdE3fooEi
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo@?$templ at N@@QEAAHH at Z.resolver"(ptr %0, i32 %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo@?$templ at N@@QEAAHH at Z.resolver"(ptr %0, i32 %1) {{.*}} comdat
 // WINDOWS: call i32 @"?foo@?$templ at N@@QEAAHH at Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo@?$templ at N@@QEAAHH at Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo@?$templ at N@@QEAAHH at Z.sse4.2"
diff --git a/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp b/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
index 3c56cad3af914..32274ece69e60 100644
--- a/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
+++ b/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
@@ -54,7 +54,7 @@ int bar() {
 // ITANIUM: ret ptr @_ZN1S3fooEi.sse4.2
 // ITANIUM: ret ptr @_ZN1S3fooEi
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo at S@@QEAAHH at Z.resolver"(ptr %0, i32 %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo at S@@QEAAHH at Z.resolver"(ptr %0, i32 %1) {{.*}} comdat
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.arch_sandybridge"(ptr %0, i32 %1)
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.arch_ivybridge"(ptr %0, i32 %1)
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.sse4.2"(ptr %0, i32 %1)
diff --git a/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp b/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp
index e30fbf4ef5027..9e54919b3227c 100644
--- a/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp
+++ b/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp
@@ -61,7 +61,7 @@ int bar2() {
 // ITANIUM: ret ptr @_Z12foo_overloadv.sse4.2
 // ITANIUM: ret ptr @_Z12foo_overloadv
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo_overload@@YAHXZ.resolver"() comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo_overload@@YAHXZ.resolver"() {{.*}} comdat
 // WINDOWS: call i32 @"?foo_overload@@YAHXZ.arch_sandybridge"
 // WINDOWS: call i32 @"?foo_overload@@YAHXZ.arch_ivybridge"
 // WINDOWS: call i32 @"?foo_overload@@YAHXZ.sse4.2"
@@ -74,7 +74,7 @@ int bar2() {
 // ITANIUM: ret ptr @_Z12foo_overloadi.sse4.2
 // ITANIUM: ret ptr @_Z12foo_overloadi
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo_overload@@YAHH at Z.resolver"(i32 %0) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo_overload@@YAHH at Z.resolver"(i32 %0) {{.*}} comdat
 // WINDOWS: call i32 @"?foo_overload@@YAHH at Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo_overload@@YAHH at Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo_overload@@YAHH at Z.sse4.2"

>From 499382fcb792e15ed6942f388952309b88933cf0 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Sun, 10 Mar 2024 16:46:50 -0700
Subject: [PATCH 3/5] [CodeGen][AArch64][FMV] PAC the stub_helper's frame on
 arm64e

---
 clang/lib/CodeGen/CodeGenFunction.cpp         |  6 +-
 clang/lib/CodeGen/CodeGenModule.cpp           | 18 ++++--
 .../CodeGen/aarch64-mixed-target-attributes.c | 19 ++++---
 clang/test/CodeGen/attr-cpuspecific.c         | 24 ++++----
 clang/test/CodeGen/attr-target-clones.c       | 46 +++++++--------
 clang/test/CodeGen/attr-target-mv-va-args.c   |  6 +-
 clang/test/CodeGen/attr-target-mv.c           | 18 +++---
 .../test/CodeGen/attr-target-version-arm64e.c | 57 +++++++++++++++++++
 clang/test/CodeGen/attr-target-version.c      | 35 ++++++++----
 clang/test/CodeGenCXX/attr-cpuspecific.cpp    |  2 +-
 .../CodeGenCXX/attr-target-clones-aarch64.cpp | 47 ++++++++-------
 clang/test/CodeGenCXX/attr-target-clones.cpp  |  4 +-
 .../CodeGenCXX/attr-target-mv-diff-ns.cpp     |  4 +-
 .../attr-target-mv-member-funcs.cpp           |  2 +-
 .../attr-target-mv-out-of-line-defs.cpp       |  2 +-
 .../CodeGenCXX/attr-target-mv-overloads.cpp   |  4 +-
 clang/test/CodeGenCXX/attr-target-version.cpp | 20 ++++---
 clang/test/CodeGenCXX/fmv-namespace.cpp       |  7 ++-
 llvm/include/llvm/CodeGen/AsmPrinter.h        | 13 +++--
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp    |  3 +-
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 45 +++++++++++++++
 llvm/test/CodeGen/AArch64/ifunc-asm.ll        | 21 +++++--
 22 files changed, 280 insertions(+), 123 deletions(-)
 create mode 100644 clang/test/CodeGen/attr-target-version-arm64e.c

diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp
index 1e98bea8c8ce3..76b6bc39b8b15 100644
--- a/clang/lib/CodeGen/CodeGenFunction.cpp
+++ b/clang/lib/CodeGen/CodeGenFunction.cpp
@@ -2833,7 +2833,11 @@ static void CreateMultiVersionResolverReturn(CodeGenModule &CGM,
                                              llvm::Function *FuncToReturn,
                                              bool SupportsIFunc) {
   if (SupportsIFunc) {
-    Builder.CreateRet(FuncToReturn);
+    llvm::Constant *Fn = FuncToReturn;
+    const ASTContext &Ctx = CGM.getContext();
+    QualType FTy = Ctx.getFunctionType(Ctx.VoidTy, {}, FunctionProtoType::ExtProtoInfo());
+    Fn = CGM.getFunctionPointer(Fn, FTy);
+    Builder.CreateRet(Fn);
     return;
   }
 
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 71192cb0e8c4a..c3f4ee6911814 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4510,13 +4510,16 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
   // For cpu_specific, don't create an ifunc yet because we don't know if the
   // cpu_dispatch will be emitted in this translation unit.
   if (getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion()) {
-    llvm::Type *ResolverType = llvm::FunctionType::get(
+    llvm::FunctionType *ResolverType = llvm::FunctionType::get(
         llvm::PointerType::get(DeclTy,
                                getTypes().getTargetAddressSpace(FD->getType())),
         false);
-    llvm::Constant *Resolver = GetOrCreateLLVMFunction(
-        MangledName + ".resolver", ResolverType, GlobalDecl{},
-        /*ForVTable=*/false);
+    llvm::Function *Resolver = cast<llvm::Function>(
+        CreateRuntimeFunction(ResolverType, MangledName + ".resolver")
+            .getCallee());
+    llvm::AttrBuilder Attrs(getLLVMContext());
+    addDefaultFunctionDefinitionAttributes(Attrs);
+    Resolver->addFnAttrs(Attrs);
     llvm::GlobalIFunc *GIF =
         llvm::GlobalIFunc::create(DeclTy, 0, getMultiversionLinkage(*this, GD),
                                   "", Resolver, &getModule());
@@ -4527,8 +4530,11 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) {
     return GIF;
   }
 
-  llvm::Constant *Resolver = GetOrCreateLLVMFunction(
-      ResolverName, DeclTy, GlobalDecl{}, /*ForVTable=*/false);
+  llvm::Function *Resolver = cast<llvm::Function>(
+      CreateRuntimeFunction(DeclTy, ResolverName).getCallee());
+  llvm::AttrBuilder Attrs(getLLVMContext());
+  addDefaultFunctionDefinitionAttributes(Attrs);
+  Resolver->addFnAttrs(Attrs);
   assert(isa<llvm::GlobalValue>(Resolver) &&
          "Resolver should be created for the first time");
   SetCommonAttributes(FD, cast<llvm::GlobalValue>(Resolver));
diff --git a/clang/test/CodeGen/aarch64-mixed-target-attributes.c b/clang/test/CodeGen/aarch64-mixed-target-attributes.c
index d779abd395b5f..87a4fc7ecd78f 100644
--- a/clang/test/CodeGen/aarch64-mixed-target-attributes.c
+++ b/clang/test/CodeGen/aarch64-mixed-target-attributes.c
@@ -62,7 +62,8 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
 // CHECK-NEXT:    ret i32 2
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@explicit_default.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@explicit_default.resolver
+// CHECK-SAME: () #[[ATTR4:[0-9]+]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -102,7 +103,7 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@explicit_default._Mrdm
-// CHECK-SAME: () #[[ATTR4:[0-9]+]] {
+// CHECK-SAME: () #[[ATTR5:[0-9]+]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 3
 //
@@ -136,7 +137,8 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
 // CHECK-NEXT:    ret i32 2
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@implicit_default.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@implicit_default.resolver
+// CHECK-SAME: () #[[ATTR4]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -176,7 +178,7 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
 //
 // CHECK: Function Attrs: noinline nounwind optnone
 // CHECK-LABEL: define {{[^@]+}}@implicit_default._Mrdm
-// CHECK-SAME: () #[[ATTR4]] {
+// CHECK-SAME: () #[[ATTR5]] {
 // CHECK-NEXT:  entry:
 // CHECK-NEXT:    ret i32 3
 //
@@ -203,7 +205,8 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
 // CHECK-NEXT:    ret i32 2
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.resolver
+// CHECK-SAME: () #[[ATTR4]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -259,9 +262,9 @@ __attribute__((target_version("jscvt"))) int default_def_with_version_decls(void
 // CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon,-v9.5a" }
 // CHECK: attributes #[[ATTR2]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon,-v9.5a" }
 // CHECK: attributes #[[ATTR3]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,-v9.5a" }
-// CHECK: attributes #[[ATTR4]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm,-v9.5a" }
-// CHECK: attributes #[[ATTR5:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon,-v9.5a" }
-// CHECK: attributes #[[ATTR6:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-v9.5a" }
+// CHECK: attributes #[[ATTR4]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="-v9.5a" }
+// CHECK: attributes #[[ATTR5]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm,-v9.5a" }
+// CHECK: attributes #[[ATTR6:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon,-v9.5a" }
 // CHECK: attributes #[[ATTR7:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse,-v9.5a" }
 // CHECK: attributes #[[ATTR8:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+jsconv,+neon,-v9.5a" }
 //.
diff --git a/clang/test/CodeGen/attr-cpuspecific.c b/clang/test/CodeGen/attr-cpuspecific.c
index 628892d5809b4..8b6ed65ee8713 100644
--- a/clang/test/CodeGen/attr-cpuspecific.c
+++ b/clang/test/CodeGen/attr-cpuspecific.c
@@ -51,7 +51,7 @@ void SingleVersion(void);
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @SingleVersion() comdat
+// WINDOWS: define weak_odr dso_local void @SingleVersion() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: %[[FEAT_INIT:.+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0), align 4
 // WINDOWS: %[[FEAT_JOIN:.+]] = and i32 %[[FEAT_INIT]], 525311
@@ -82,7 +82,7 @@ void TwoVersions(void);
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @TwoVersions() comdat
+// WINDOWS: define weak_odr dso_local void @TwoVersions() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: %[[FEAT_INIT:.+]] = load i32, ptr getelementptr inbounds ({ i32, i32, i32, [1 x i32] }, ptr @__cpu_model, i32 0, i32 3, i32 0), align 4
 // WINDOWS: %[[FEAT_JOIN:.+]] = and i32 %[[FEAT_INIT]], 9422847
@@ -125,7 +125,7 @@ void OrderDispatchUsageSpecific(void);
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @OrderDispatchUsageSpecific() comdat
+// WINDOWS: define weak_odr dso_local void @OrderDispatchUsageSpecific() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: call void @OrderDispatchUsageSpecific.Z()
 // WINDOWS-NEXT: ret void
@@ -174,7 +174,7 @@ void TwoVersionsSameAttr(void);
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @TwoVersionsSameAttr() comdat
+// WINDOWS: define weak_odr dso_local void @TwoVersionsSameAttr() {{.*}} comdat
 // WINDOWS: call void @TwoVersionsSameAttr.Z
 // WINDOWS-NEXT: ret void
 // WINDOWS: call void @TwoVersionsSameAttr.S
@@ -194,7 +194,7 @@ void ThreeVersionsSameAttr(void){}
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @ThreeVersionsSameAttr() comdat
+// WINDOWS: define weak_odr dso_local void @ThreeVersionsSameAttr() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @ThreeVersionsSameAttr.Z
 // WINDOWS-NEXT: ret void
@@ -210,7 +210,7 @@ void OrderSpecificUsageDispatch(void);
 // LINUX: define weak_odr ptr @OrderSpecificUsageDispatch.resolver()
 // LINUX: ret ptr @OrderSpecificUsageDispatch.Z
 
-// WINDOWS: define weak_odr dso_local void @OrderSpecificUsageDispatch() comdat
+// WINDOWS: define weak_odr dso_local void @OrderSpecificUsageDispatch() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @OrderSpecificUsageDispatch.Z
 // WINDOWS-NEXT: ret void
@@ -226,7 +226,7 @@ void NoSpecifics(void);
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define weak_odr dso_local void @NoSpecifics() comdat
+// WINDOWS: define weak_odr dso_local void @NoSpecifics() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @NoSpecifics.Z
 // WINDOWS-NEXT: ret void
@@ -247,7 +247,7 @@ void HasGeneric(void);
 // LINUX: ret ptr @HasGeneric.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define weak_odr dso_local void @HasGeneric() comdat
+// WINDOWS: define weak_odr dso_local void @HasGeneric() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @HasGeneric.Z
 // WINDOWS-NEXT: ret void
@@ -269,7 +269,7 @@ void HasParams(int i, double d);
 // LINUX: ret ptr @HasParams.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define weak_odr dso_local void @HasParams(i32 %0, double %1) comdat
+// WINDOWS: define weak_odr dso_local void @HasParams(i32 %0, double %1) {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @HasParams.Z(i32 %0, double %1)
 // WINDOWS-NEXT: ret void
@@ -291,7 +291,7 @@ int HasParamsAndReturn(int i, double d);
 // LINUX: ret ptr @HasParamsAndReturn.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define weak_odr dso_local i32 @HasParamsAndReturn(i32 %0, double %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @HasParamsAndReturn(i32 %0, double %1) {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: %[[RET:.+]] = musttail call i32 @HasParamsAndReturn.Z(i32 %0, double %1)
 // WINDOWS-NEXT: ret i32 %[[RET]]
@@ -312,7 +312,7 @@ int GenericAndPentium(int i, double d);
 // LINUX-NOT: ret ptr @GenericAndPentium.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define weak_odr dso_local i32 @GenericAndPentium(i32 %0, double %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @GenericAndPentium(i32 %0, double %1) {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: %[[RET:.+]] = musttail call i32 @GenericAndPentium.O(i32 %0, double %1)
 // WINDOWS-NEXT: ret i32 %[[RET]]
@@ -327,7 +327,7 @@ int DispatchFirst(void);
 // LINUX: ret ptr @DispatchFirst.O
 // LINUX: ret ptr @DispatchFirst.B
 
-// WINDOWS: define weak_odr dso_local i32 @DispatchFirst() comdat
+// WINDOWS: define weak_odr dso_local i32 @DispatchFirst() {{.*}} comdat
 // WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.O()
 // WINDOWS-NEXT: ret i32 %[[RET]]
 // WINDOWS: %[[RET:.+]] = musttail call i32 @DispatchFirst.B()
diff --git a/clang/test/CodeGen/attr-target-clones.c b/clang/test/CodeGen/attr-target-clones.c
index 3256db061f9a2..730321e185fba 100644
--- a/clang/test/CodeGen/attr-target-clones.c
+++ b/clang/test/CodeGen/attr-target-clones.c
@@ -44,45 +44,45 @@
 static int __attribute__((target_clones("sse4.2, default"))) internal(void) { return 0; }
 int use(void) { return internal(); }
 /// Internal linkage resolvers do not use comdat.
-// LINUX: define internal ptr @internal.resolver() {
-// DARWIN: define internal ptr @internal.resolver() {
-// WINDOWS: define internal i32 @internal() {
+// LINUX: define internal ptr @internal.resolver()
+// DARWIN: define internal ptr @internal.resolver()
+// WINDOWS: define internal i32 @internal()
 
 int __attribute__((target_clones("sse4.2, default"))) foo(void) { return 0; }
 // LINUX: define {{.*}}i32 @foo.sse4.2.0()
 // LINUX: define {{.*}}i32 @foo.default.1()
-// LINUX: define weak_odr ptr @foo.resolver() comdat
+// LINUX: define weak_odr ptr @foo.resolver() {{.*}} comdat
 // LINUX: ret ptr @foo.sse4.2.0
 // LINUX: ret ptr @foo.default.1
 
 // DARWIN: define {{.*}}i32 @foo.sse4.2.0()
 // DARWIN: define {{.*}}i32 @foo.default.1()
-// DARWIN: define weak_odr ptr @foo.resolver() {
+// DARWIN: define weak_odr ptr @foo.resolver()
 // DARWIN: ret ptr @foo.sse4.2.0
 // DARWIN: ret ptr @foo.default.1
 
 // WINDOWS: define dso_local i32 @foo.sse4.2.0()
 // WINDOWS: define dso_local i32 @foo.default.1()
-// WINDOWS: define weak_odr dso_local i32 @foo() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo() {{.*}} comdat
 // WINDOWS: musttail call i32 @foo.sse4.2.0
 // WINDOWS: musttail call i32 @foo.default.1
 
 __attribute__((target_clones("default,default ,sse4.2"))) void foo_dupes(void) {}
 // LINUX: define {{.*}}void @foo_dupes.default.1()
 // LINUX: define {{.*}}void @foo_dupes.sse4.2.0()
-// LINUX: define weak_odr ptr @foo_dupes.resolver() comdat
+// LINUX: define weak_odr ptr @foo_dupes.resolver() {{.*}} comdat
 // LINUX: ret ptr @foo_dupes.sse4.2.0
 // LINUX: ret ptr @foo_dupes.default.1
 
 // DARWIN: define {{.*}}void @foo_dupes.default.1()
 // DARWIN: define {{.*}}void @foo_dupes.sse4.2.0()
-// DARWIN: define weak_odr ptr @foo_dupes.resolver() {
+// DARWIN: define weak_odr ptr @foo_dupes.resolver()
 // DARWIN: ret ptr @foo_dupes.sse4.2.0
 // DARWIN: ret ptr @foo_dupes.default.1
 
 // WINDOWS: define dso_local void @foo_dupes.default.1()
 // WINDOWS: define dso_local void @foo_dupes.sse4.2.0()
-// WINDOWS: define weak_odr dso_local void @foo_dupes() comdat
+// WINDOWS: define weak_odr dso_local void @foo_dupes() {{.*}} comdat
 // WINDOWS: musttail call void @foo_dupes.sse4.2.0
 // WINDOWS: musttail call void @foo_dupes.default.1
 
@@ -109,19 +109,19 @@ int bar(void) {
 void __attribute__((target_clones("default, arch=ivybridge"))) unused(void) {}
 // LINUX: define {{.*}}void @unused.default.1()
 // LINUX: define {{.*}}void @unused.arch_ivybridge.0()
-// LINUX: define weak_odr ptr @unused.resolver() comdat
+// LINUX: define weak_odr ptr @unused.resolver() {{.*}} comdat
 // LINUX: ret ptr @unused.arch_ivybridge.0
 // LINUX: ret ptr @unused.default.1
 
 // DARWIN: define {{.*}}void @unused.default.1()
 // DARWIN: define {{.*}}void @unused.arch_ivybridge.0()
-// DARWIN: define weak_odr ptr @unused.resolver() {
+// DARWIN: define weak_odr ptr @unused.resolver()
 // DARWIN: ret ptr @unused.arch_ivybridge.0
 // DARWIN: ret ptr @unused.default.1
 
 // WINDOWS: define dso_local void @unused.default.1()
 // WINDOWS: define dso_local void @unused.arch_ivybridge.0()
-// WINDOWS: define weak_odr dso_local void @unused() comdat
+// WINDOWS: define weak_odr dso_local void @unused() {{.*}} comdat
 // WINDOWS: musttail call void @unused.arch_ivybridge.0
 // WINDOWS: musttail call void @unused.default.1
 
@@ -144,34 +144,34 @@ int bar3(void) {
   // WINDOWS: call i32 @foo_inline2()
 }
 
-// LINUX: define weak_odr ptr @foo_inline.resolver() comdat
+// LINUX: define weak_odr ptr @foo_inline.resolver() {{.*}} comdat
 // LINUX: ret ptr @foo_inline.arch_sandybridge.0
 // LINUX: ret ptr @foo_inline.sse4.2.1
 // LINUX: ret ptr @foo_inline.default.2
 
-// DARWIN: define weak_odr ptr @foo_inline.resolver() {
+// DARWIN: define weak_odr ptr @foo_inline.resolver()
 // DARWIN: ret ptr @foo_inline.arch_sandybridge.0
 // DARWIN: ret ptr @foo_inline.sse4.2.1
 // DARWIN: ret ptr @foo_inline.default.2
 
-// WINDOWS: define weak_odr dso_local i32 @foo_inline() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo_inline() {{.*}} comdat
 // WINDOWS: musttail call i32 @foo_inline.arch_sandybridge.0
 // WINDOWS: musttail call i32 @foo_inline.sse4.2.1
 // WINDOWS: musttail call i32 @foo_inline.default.2
 
 inline int __attribute__((target_clones("arch=sandybridge,default,sse4.2")))
 foo_inline2(void){ return 0; }
-// LINUX: define weak_odr ptr @foo_inline2.resolver() comdat
+// LINUX: define weak_odr ptr @foo_inline2.resolver() {{.*}} comdat
 // LINUX: ret ptr @foo_inline2.arch_sandybridge.0
 // LINUX: ret ptr @foo_inline2.sse4.2.1
 // LINUX: ret ptr @foo_inline2.default.2
 
-// DARWIN: define weak_odr ptr @foo_inline2.resolver() {
+// DARWIN: define weak_odr ptr @foo_inline2.resolver()
 // DARWIN: ret ptr @foo_inline2.arch_sandybridge.0
 // DARWIN: ret ptr @foo_inline2.sse4.2.1
 // DARWIN: ret ptr @foo_inline2.default.2
 
-// WINDOWS: define weak_odr dso_local i32 @foo_inline2() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo_inline2() {{.*}} comdat
 // WINDOWS: musttail call i32 @foo_inline2.arch_sandybridge.0
 // WINDOWS: musttail call i32 @foo_inline2.sse4.2.1
 // WINDOWS: musttail call i32 @foo_inline2.default.2
@@ -194,15 +194,15 @@ int test_foo_used_no_defn(void) {
 }
 
 
-// LINUX: define weak_odr ptr @foo_used_no_defn.resolver() comdat
+// LINUX: define weak_odr ptr @foo_used_no_defn.resolver() {{.*}} comdat
 // LINUX: ret ptr @foo_used_no_defn.sse4.2.0
 // LINUX: ret ptr @foo_used_no_defn.default.1
 
-// DARWIN: define weak_odr ptr @foo_used_no_defn.resolver() {
+// DARWIN: define weak_odr ptr @foo_used_no_defn.resolver()
 // DARWIN: ret ptr @foo_used_no_defn.sse4.2.0
 // DARWIN: ret ptr @foo_used_no_defn.default.1
 
-// WINDOWS: define weak_odr dso_local i32 @foo_used_no_defn() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo_used_no_defn() {{.*}} comdat
 // WINDOWS: musttail call i32 @foo_used_no_defn.sse4.2.0
 // WINDOWS: musttail call i32 @foo_used_no_defn.default.1
 
@@ -213,7 +213,7 @@ int isa_level(int) { return 0; }
 // LINUX:      define{{.*}} i32 @isa_level.arch_x86-64-v2.1(
 // LINUX:      define{{.*}} i32 @isa_level.arch_x86-64-v3.2(
 // LINUX:      define{{.*}} i32 @isa_level.arch_x86-64-v4.3(
-// LINUX:      define weak_odr ptr @isa_level.resolver() comdat
+// LINUX:      define weak_odr ptr @isa_level.resolver() {{.*}} comdat
 // LINUX:        call void @__cpu_indicator_init()
 // LINUX-NEXT:   load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
 // LINUX-NEXT:   and i32 %[[#]], 4
@@ -234,7 +234,7 @@ int isa_level(int) { return 0; }
 // DARWIN:      define{{.*}} i32 @isa_level.arch_x86-64-v2.1(
 // DARWIN:      define{{.*}} i32 @isa_level.arch_x86-64-v3.2(
 // DARWIN:      define{{.*}} i32 @isa_level.arch_x86-64-v4.3(
-// DARWIN:      define weak_odr ptr @isa_level.resolver() {
+// DARWIN:      define weak_odr ptr @isa_level.resolver()
 // DARWIN:        call void @__cpu_indicator_init()
 // DARWIN-NEXT:   load i32, ptr getelementptr inbounds ([3 x i32], ptr @__cpu_features2, i32 0, i32 2)
 // DARWIN-NEXT:   and i32 %[[#]], 4
diff --git a/clang/test/CodeGen/attr-target-mv-va-args.c b/clang/test/CodeGen/attr-target-mv-va-args.c
index dbf5a74205c4c..5147f87bc52f7 100644
--- a/clang/test/CodeGen/attr-target-mv-va-args.c
+++ b/clang/test/CodeGen/attr-target-mv-va-args.c
@@ -24,7 +24,7 @@ int bar(void) {
 // IFUNC-ELF: call i32 (i32, ...) @foo.ifunc(i32 noundef 1, i32 noundef 97, double
 // IFUNC-ELF: call i32 (i32, ...) @foo.ifunc(i32 noundef 2, double noundef 2.2{{[0-9Ee+]+}}, ptr noundef
 
-// IFUNC-ELF: define weak_odr ptr @foo.resolver() comdat
+// IFUNC-ELF: define weak_odr ptr @foo.resolver() {{.*}} comdat
 // IFUNC-ELF: ret ptr @foo.arch_sandybridge
 // IFUNC-ELF: ret ptr @foo.arch_ivybridge
 // IFUNC-ELF: ret ptr @foo.sse4.2
@@ -59,8 +59,8 @@ int bar(void) {
 // NO-IFUNC: call i32 (i32, ...) @foo.resolver(i32 noundef 1, i32 noundef 97, double
 // NO-IFUNC: call i32 (i32, ...) @foo.resolver(i32 noundef 2, double noundef 2.2{{[0-9Ee+]+}}, ptr noundef
 
-// WINDOWS: define weak_odr dso_local i32 @foo.resolver(i32 %0, ...) comdat
-// NO-IFUNC-ELF: define weak_odr i32 @foo.resolver(i32 %0, ...) comdat
+// WINDOWS: define weak_odr dso_local i32 @foo.resolver(i32 %0, ...) {{.*}} comdat
+// NO-IFUNC-ELF: define weak_odr i32 @foo.resolver(i32 %0, ...) {{.*}} comdat
 // NO-IFUNC: musttail call i32 (i32, ...) @foo.arch_sandybridge
 // NO-IFUNC: musttail call i32 (i32, ...) @foo.arch_ivybridge
 // NO-IFUNC: musttail call i32 (i32, ...) @foo.sse4.2
diff --git a/clang/test/CodeGen/attr-target-mv.c b/clang/test/CodeGen/attr-target-mv.c
index 2c4b95ca04370..f31ca5a8d1401 100644
--- a/clang/test/CodeGen/attr-target-mv.c
+++ b/clang/test/CodeGen/attr-target-mv.c
@@ -270,7 +270,7 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @foo.sse4.2
 // ITANIUM: ret ptr @foo
 
-// WINDOWS: define weak_odr dso_local i32 @foo.resolver() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo.resolver() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: call i32 @foo.arch_sandybridge
 // WINDOWS: call i32 @foo.arch_ivybridge
@@ -278,9 +278,9 @@ void calls_pr50025c(void) { pr50025c(); }
 // WINDOWS: call i32 @foo
 
 /// Internal linkage resolvers do not use comdat.
-// ITANIUM: define internal ptr @foo_internal.resolver() {
+// ITANIUM: define internal ptr @foo_internal.resolver() #[[ATTR:[0-9]+]] {
 
-// WINDOWS: define internal i32 @foo_internal.resolver() {
+// WINDOWS: define internal i32 @foo_internal.resolver() {{.*}} {
 
 // ITANIUM: define{{.*}} i32 @bar2()
 // ITANIUM: call i32 @foo_inline.ifunc()
@@ -296,7 +296,7 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @foo_inline.sse4.2
 // ITANIUM: ret ptr @foo_inline
 
-// WINDOWS: define weak_odr dso_local i32 @foo_inline.resolver() comdat
+// WINDOWS: define weak_odr dso_local i32 @foo_inline.resolver() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: call i32 @foo_inline.arch_sandybridge
 // WINDOWS: call i32 @foo_inline.arch_ivybridge
@@ -314,7 +314,7 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @foo_decls.sse4.2
 // ITANIUM: ret ptr @foo_decls
 
-// WINDOWS: define weak_odr dso_local void @foo_decls.resolver() comdat
+// WINDOWS: define weak_odr dso_local void @foo_decls.resolver() {{.*}} comdat
 // WINDOWS: call void @foo_decls.sse4.2
 // WINDOWS: call void @foo_decls
 
@@ -338,7 +338,7 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @foo_multi.avx_sse4.2
 // ITANIUM: ret ptr @foo_multi
 
-// WINDOWS: define weak_odr dso_local void @foo_multi.resolver(i32 %0, double %1) comdat
+// WINDOWS: define weak_odr dso_local void @foo_multi.resolver(i32 %0, double %1) {{.*}} comdat
 // WINDOWS: and i32 %{{.*}}, 4352
 // WINDOWS: icmp eq i32 %{{.*}}, 4352
 // WINDOWS: call void @foo_multi.fma4_sse4.2(i32 %0, double %1)
@@ -387,10 +387,10 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @fwd_decl_avx.avx
 // ITANIUM: ret ptr @fwd_decl_avx
 
-// WINDOWS: define weak_odr dso_local i32 @fwd_decl_default.resolver() comdat
+// WINDOWS: define weak_odr dso_local i32 @fwd_decl_default.resolver() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: call i32 @fwd_decl_default
-// WINDOWS: define weak_odr dso_local i32 @fwd_decl_avx.resolver() comdat
+// WINDOWS: define weak_odr dso_local i32 @fwd_decl_avx.resolver() {{.*}} comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: call i32 @fwd_decl_avx.avx
 // WINDOWS: call i32 @fwd_decl_avx
@@ -468,7 +468,7 @@ void calls_pr50025c(void) { pr50025c(); }
 // ITANIUM: ret ptr @pr50025b
 // ITANIUM: define linkonce void @pr50025b()
 // ITANIUM: call void @must_be_emitted()
-// WINDOWS: define weak_odr dso_local void @pr50025b.resolver() comdat
+// WINDOWS: define weak_odr dso_local void @pr50025b.resolver() {{.*}} comdat
 // WINDOWS: musttail call void @pr50025b()
 // WINDOWS: define linkonce_odr dso_local void @pr50025b() #{{[0-9]*}} comdat
 // WINDOWS: call void @must_be_emitted()
diff --git a/clang/test/CodeGen/attr-target-version-arm64e.c b/clang/test/CodeGen/attr-target-version-arm64e.c
new file mode 100644
index 0000000000000..24fd526bcedd6
--- /dev/null
+++ b/clang/test/CodeGen/attr-target-version-arm64e.c
@@ -0,0 +1,57 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals --include-generated-funcs
+// RUN: %clang_cc1 -triple arm64e-apple-ios -target-feature +ls64 -target-feature +fullfp16 -emit-llvm -o - %s | FileCheck %s
+
+int __attribute__((target_version("sha1"))) fmv(void) { return 1; }
+int __attribute__((target_version("default"))) fmv(void) { return 0; }
+int foo() {
+  return fmv();
+}
+
+//.
+// CHECK: @__aarch64_cpu_features = external dso_local global { i64 }
+// CHECK: @fmv = weak_odr ifunc i32 (), ptr @fmv.resolver
+//.
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv._Msha1
+// CHECK-SAME: () #[[ATTR0:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret i32 1
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@fmv.default
+// CHECK-SAME: () #[[ATTR1:[0-9]+]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    ret i32 0
+//
+//
+// CHECK: Function Attrs: noinline nounwind optnone
+// CHECK-LABEL: define {{[^@]+}}@foo
+// CHECK-SAME: () #[[ATTR1]] {
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:    [[CALL:%.*]] = call i32 @fmv()
+// CHECK-NEXT:    ret i32 [[CALL]]
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@fmv.resolver
+// CHECK-SAME: () #[[ATTR2:[0-9]+]] {
+// CHECK-NEXT:  resolver_entry:
+// CHECK-NEXT:    call void @__init_cpu_features_resolver()
+// CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
+// CHECK-NEXT:    [[TMP1:%.*]] = and i64 [[TMP0]], 2048
+// CHECK-NEXT:    [[TMP2:%.*]] = icmp eq i64 [[TMP1]], 2048
+// CHECK-NEXT:    [[TMP3:%.*]] = and i1 true, [[TMP2]]
+// CHECK-NEXT:    br i1 [[TMP3]], label [[RESOLVER_RETURN:%.*]], label [[RESOLVER_ELSE:%.*]]
+// CHECK:       resolver_return:
+// CHECK-NEXT:    ret ptr @fmv._Msha1
+// CHECK:       resolver_else:
+// CHECK-NEXT:    ret ptr @fmv.default
+//
+//.
+// CHECK: attributes #[[ATTR0]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+ls64,+neon" }
+// CHECK: attributes #[[ATTR1]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
+// CHECK: attributes #[[ATTR2]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fullfp16,+ls64" }
+//.
+// CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
+// CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
+//.
diff --git a/clang/test/CodeGen/attr-target-version.c b/clang/test/CodeGen/attr-target-version.c
index b058f84f78baa..9a970c5134534 100644
--- a/clang/test/CodeGen/attr-target-version.c
+++ b/clang/test/CodeGen/attr-target-version.c
@@ -464,7 +464,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret i32 [[CALL]]
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv.resolver
+// CHECK-SAME: () #[[ATTR12:[0-9]+]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -542,7 +543,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret ptr @fmv.default
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_one.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv_one.resolver
+// CHECK-SAME: () #[[ATTR12]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -564,7 +566,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret ptr @fmv_one.default
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_two.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv_two.resolver
+// CHECK-SAME: () #[[ATTR12]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -602,7 +605,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret ptr @fmv_two.default
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_e.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv_e.resolver
+// CHECK-SAME: () #[[ATTR12]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -630,7 +634,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret i32 1
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_d.resolver() {
+// CHECK-LABEL: define {{[^@]+}}@fmv_d.resolver
+// CHECK-SAME: () #[[ATTR12]] {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -644,7 +649,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret ptr @fmv_d.default
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv_c.resolver
+// CHECK-SAME: () #[[ATTR12]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -777,7 +783,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret i32 3
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@fmv_inline.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@fmv_inline.resolver
+// CHECK-SAME: () #[[ATTR12]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -911,7 +918,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret ptr @fmv_inline.default
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@unused_with_default_def.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@unused_with_default_def.resolver
+// CHECK-SAME: () #[[ATTR12]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -925,7 +933,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret ptr @unused_with_default_def.default
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_default_def.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_default_def.resolver
+// CHECK-SAME: () #[[ATTR12]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -939,7 +948,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret ptr @unused_with_implicit_default_def.default
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@unused_with_implicit_forward_default_def.resolver
+// CHECK-SAME: () #[[ATTR12]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -953,7 +963,8 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK-NEXT:    ret ptr @unused_with_implicit_forward_default_def.default
 //
 //
-// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.resolver() comdat {
+// CHECK-LABEL: define {{[^@]+}}@default_def_with_version_decls.resolver
+// CHECK-SAME: () #[[ATTR12]] comdat {
 // CHECK-NEXT:  resolver_entry:
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -1124,7 +1135,7 @@ int caller(void) { return used_def_without_default_decl() + used_decl_without_de
 // CHECK: attributes #[[ATTR9]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
 // CHECK: attributes #[[ATTR10]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ccpp" }
 // CHECK: attributes #[[ATTR11]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
-// CHECK: attributes #[[ATTR12:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+// CHECK: attributes #[[ATTR12]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
 // CHECK: attributes #[[ATTR13]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops" }
 // CHECK: attributes #[[ATTR14]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+dotprod,+fp-armv8,+neon" }
 // CHECK: attributes #[[ATTR15]] = { noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }
diff --git a/clang/test/CodeGenCXX/attr-cpuspecific.cpp b/clang/test/CodeGenCXX/attr-cpuspecific.cpp
index 225c6a5c742a5..688650595b67c 100644
--- a/clang/test/CodeGenCXX/attr-cpuspecific.cpp
+++ b/clang/test/CodeGenCXX/attr-cpuspecific.cpp
@@ -22,7 +22,7 @@ void foo() {
 // LINUX: declare void @_ZN1S4FuncEv.S
 // LINUX: define linkonce_odr void @_ZN1S4FuncEv.O
 
-// WINDOWS: define weak_odr dso_local void @"?Func at S@@QEAAXXZ"(ptr %0) comdat
+// WINDOWS: define weak_odr dso_local void @"?Func at S@@QEAAXXZ"(ptr %0) {{.*}} comdat
 // WINDOWS: musttail call void @"?Func at S@@QEAAXXZ.S"(ptr %0)
 // WINDOWS: musttail call void @"?Func at S@@QEAAXXZ.O"(ptr %0)
 // WINDOWS: declare dso_local void @"?Func at S@@QEAAXXZ.S"
diff --git a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp
index 6405621a9d647..443431894dcf6 100644
--- a/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp
+++ b/clang/test/CodeGenCXX/attr-target-clones-aarch64.cpp
@@ -53,7 +53,8 @@ void run_foo_tml() {
 // CHECK-NEXT:    ret i32 1
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_Z7foo_ovli.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_Z7foo_ovli.resolver(
+// CHECK-SAME: ) #[[ATTR1:[0-9]+]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -68,12 +69,13 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define dso_local noundef i32 @_Z7foo_ovlv._Mls64Mls64_accdata(
-// CHECK-SAME: ) #[[ATTR1:[0-9]+]] {
+// CHECK-SAME: ) #[[ATTR2:[0-9]+]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    ret i32 2
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_Z7foo_ovlv.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_Z7foo_ovlv.resolver(
+// CHECK-SAME: ) #[[ATTR1]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -88,7 +90,7 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define dso_local noundef i32 @_Z3barv(
-// CHECK-SAME: ) #[[ATTR2:[0-9]+]] {
+// CHECK-SAME: ) #[[ATTR3:[0-9]+]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[CALL:%.*]] = call noundef i32 @_Z7foo_ovli(i32 noundef 1)
 // CHECK-NEXT:    [[CALL1:%.*]] = call noundef i32 @_Z7foo_ovlv()
@@ -97,7 +99,7 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define dso_local void @_Z11run_foo_tmlv(
-// CHECK-SAME: ) #[[ATTR2]] {
+// CHECK-SAME: ) #[[ATTR3]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[MC1:%.*]] = alloca [[STRUCT_MYCLASS:%.*]], align 1
 // CHECK-NEXT:    [[MC2:%.*]] = alloca [[STRUCT_MYCLASS_0:%.*]], align 1
@@ -111,7 +113,7 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIfsE7foo_tmlEv(
-// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR2]] comdat {
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR3]] comdat {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
@@ -120,7 +122,7 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIdfE7foo_tmlEv(
-// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR2]] comdat {
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR3]] comdat {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
@@ -129,7 +131,7 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define dso_local noundef i32 @_Z7foo_ovli.default(
-// CHECK-SAME: i32 noundef [[TMP0:%.*]]) #[[ATTR2]] {
+// CHECK-SAME: i32 noundef [[TMP0:%.*]]) #[[ATTR3]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[DOTADDR:%.*]] = alloca i32, align 4
 // CHECK-NEXT:    store i32 [[TMP0]], ptr [[DOTADDR]], align 4
@@ -137,13 +139,13 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define dso_local noundef i32 @_Z7foo_ovlv.default(
-// CHECK-SAME: ) #[[ATTR2]] {
+// CHECK-SAME: ) #[[ATTR3]] {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    ret i32 2
 //
 //
 // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIssE7foo_tmlEv._Mfrintts(
-// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR3:[0-9]+]] comdat {
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR4:[0-9]+]] comdat {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
@@ -152,7 +154,7 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIssE7foo_tmlEv._Msme-f64f64Mssbs(
-// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR4:[0-9]+]] comdat {
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR5:[0-9]+]] comdat {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
@@ -161,7 +163,7 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIssE7foo_tmlEv.default(
-// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR2]] comdat {
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR3]] comdat {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
@@ -169,7 +171,8 @@ void run_foo_tml() {
 // CHECK-NEXT:    ret i32 1
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_ZN7MyClassIssE7foo_tmlEv.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_ZN7MyClassIssE7foo_tmlEv.resolver(
+// CHECK-SAME: ) #[[ATTR1]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -192,7 +195,7 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIisE7foo_tmlEv._Mfrintts(
-// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR3]] comdat {
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR4]] comdat {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
@@ -201,7 +204,7 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIisE7foo_tmlEv._Msme-f64f64Mssbs(
-// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR4]] comdat {
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR5]] comdat {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
@@ -210,7 +213,7 @@ void run_foo_tml() {
 //
 //
 // CHECK-LABEL: define linkonce_odr noundef i32 @_ZN7MyClassIisE7foo_tmlEv.default(
-// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR2]] comdat {
+// CHECK-SAME: ptr noundef nonnull align 1 dereferenceable(1) [[THIS:%.*]]) #[[ATTR3]] comdat {
 // CHECK-NEXT:  [[ENTRY:.*:]]
 // CHECK-NEXT:    [[THIS_ADDR:%.*]] = alloca ptr, align 8
 // CHECK-NEXT:    store ptr [[THIS]], ptr [[THIS_ADDR]], align 8
@@ -218,7 +221,8 @@ void run_foo_tml() {
 // CHECK-NEXT:    ret i32 2
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_ZN7MyClassIisE7foo_tmlEv.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_ZN7MyClassIisE7foo_tmlEv.resolver(
+// CHECK-SAME: ) #[[ATTR1]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -241,10 +245,11 @@ void run_foo_tml() {
 //
 //.
 // CHECK: attributes #[[ATTR0]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
-// CHECK: attributes #[[ATTR1]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ls64" }
-// CHECK: attributes #[[ATTR2]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
-// CHECK: attributes #[[ATTR3]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint" }
-// CHECK: attributes #[[ATTR4]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" }
+// CHECK: attributes #[[ATTR1]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+// CHECK: attributes #[[ATTR2]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+ls64" }
+// CHECK: attributes #[[ATTR3]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+// CHECK: attributes #[[ATTR4]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fptoint" }
+// CHECK: attributes #[[ATTR5]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+bf16,+sme,+sme-f64f64" }
 //.
 // CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
 // CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
diff --git a/clang/test/CodeGenCXX/attr-target-clones.cpp b/clang/test/CodeGenCXX/attr-target-clones.cpp
index 0814df312f4d8..7bf5eb630d86a 100644
--- a/clang/test/CodeGenCXX/attr-target-clones.cpp
+++ b/clang/test/CodeGenCXX/attr-target-clones.cpp
@@ -29,7 +29,7 @@ int __attribute__((target_clones("sse4.2", "default"))) overloaded(int) { return
 
 // WINDOWS: define dso_local noundef i32 @"?overloaded@@YAHH at Z.sse4.2.0"(i32{{.+}})
 // WINDOWS: define dso_local noundef i32 @"?overloaded@@YAHH at Z.default.1"(i32{{.+}})
-// WINDOWS: define weak_odr dso_local i32 @"?overloaded@@YAHH at Z"(i32{{.+}}) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?overloaded@@YAHH at Z"(i32{{.+}}) {{.*}} comdat
 // WINDOWS: call i32 @"?overloaded@@YAHH at Z.sse4.2.0"
 // WINDOWS: call i32 @"?overloaded@@YAHH at Z.default.1"
 
@@ -43,7 +43,7 @@ int __attribute__((target_clones("arch=ivybridge", "default"))) overloaded(const
 
 // WINDOWS: define dso_local noundef i32 @"?overloaded@@YAHPEBD at Z.arch_ivybridge.0"(ptr{{.+}})
 // WINDOWS: define dso_local noundef i32 @"?overloaded@@YAHPEBD at Z.default.1"(ptr{{.+}})
-// WINDOWS: define weak_odr dso_local i32 @"?overloaded@@YAHPEBD at Z"(ptr{{.+}}) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?overloaded@@YAHPEBD at Z"(ptr{{.+}}) {{.*}} comdat
 // WINDOWS: call i32 @"?overloaded@@YAHPEBD at Z.arch_ivybridge.0"
 // WINDOWS: call i32 @"?overloaded@@YAHPEBD at Z.default.1"
 
diff --git a/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp b/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
index 8f2fb5ef0df7e..7dae27d3d2a72 100644
--- a/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
+++ b/clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
@@ -67,7 +67,7 @@ int bar() {
 // ITANIUM: ret ptr @_Z3fooi.sse4.2
 // ITANIUM: ret ptr @_Z3fooi
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo@@YAHH at Z.resolver"(i32 %0) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo@@YAHH at Z.resolver"(i32 %0) {{.*}} comdat
 // WINDOWS: call i32 @"?foo@@YAHH at Z.arch_sandybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo@@YAHH at Z.arch_ivybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo@@YAHH at Z.sse4.2"(i32 %0)
@@ -80,7 +80,7 @@ int bar() {
 // ITANIUM: ret ptr @_ZN2ns3fooEi.sse4.2
 // ITANIUM: ret ptr @_ZN2ns3fooEi
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo at ns@@YAHH at Z.resolver"(i32 %0) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo at ns@@YAHH at Z.resolver"(i32 %0) {{.*}} comdat
 // WINDOWS: call i32 @"?foo at ns@@YAHH at Z.arch_sandybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo at ns@@YAHH at Z.arch_ivybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo at ns@@YAHH at Z.sse4.2"(i32 %0)
diff --git a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
index f956890cf706e..1181f5b5d743d 100644
--- a/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
+++ b/clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
@@ -180,7 +180,7 @@ int templ_use() {
 // ITANIUM: ret ptr @_ZN5templIdE3fooEi.sse4.2
 // ITANIUM: ret ptr @_ZN5templIdE3fooEi
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo@?$templ at N@@QEAAHH at Z.resolver"(ptr %0, i32 %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo@?$templ at N@@QEAAHH at Z.resolver"(ptr %0, i32 %1) {{.*}} comdat
 // WINDOWS: call i32 @"?foo@?$templ at N@@QEAAHH at Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo@?$templ at N@@QEAAHH at Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo@?$templ at N@@QEAAHH at Z.sse4.2"
diff --git a/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp b/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
index 3c56cad3af914..32274ece69e60 100644
--- a/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
+++ b/clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
@@ -54,7 +54,7 @@ int bar() {
 // ITANIUM: ret ptr @_ZN1S3fooEi.sse4.2
 // ITANIUM: ret ptr @_ZN1S3fooEi
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo at S@@QEAAHH at Z.resolver"(ptr %0, i32 %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo at S@@QEAAHH at Z.resolver"(ptr %0, i32 %1) {{.*}} comdat
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.arch_sandybridge"(ptr %0, i32 %1)
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.arch_ivybridge"(ptr %0, i32 %1)
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.sse4.2"(ptr %0, i32 %1)
diff --git a/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp b/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp
index e30fbf4ef5027..9e54919b3227c 100644
--- a/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp
+++ b/clang/test/CodeGenCXX/attr-target-mv-overloads.cpp
@@ -61,7 +61,7 @@ int bar2() {
 // ITANIUM: ret ptr @_Z12foo_overloadv.sse4.2
 // ITANIUM: ret ptr @_Z12foo_overloadv
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo_overload@@YAHXZ.resolver"() comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo_overload@@YAHXZ.resolver"() {{.*}} comdat
 // WINDOWS: call i32 @"?foo_overload@@YAHXZ.arch_sandybridge"
 // WINDOWS: call i32 @"?foo_overload@@YAHXZ.arch_ivybridge"
 // WINDOWS: call i32 @"?foo_overload@@YAHXZ.sse4.2"
@@ -74,7 +74,7 @@ int bar2() {
 // ITANIUM: ret ptr @_Z12foo_overloadi.sse4.2
 // ITANIUM: ret ptr @_Z12foo_overloadi
 
-// WINDOWS: define weak_odr dso_local i32 @"?foo_overload@@YAHH at Z.resolver"(i32 %0) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo_overload@@YAHH at Z.resolver"(i32 %0) {{.*}} comdat
 // WINDOWS: call i32 @"?foo_overload@@YAHH at Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo_overload@@YAHH at Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo_overload@@YAHH at Z.sse4.2"
diff --git a/clang/test/CodeGenCXX/attr-target-version.cpp b/clang/test/CodeGenCXX/attr-target-version.cpp
index 6661abead20c6..0d3eaedc20d13 100644
--- a/clang/test/CodeGenCXX/attr-target-version.cpp
+++ b/clang/test/CodeGenCXX/attr-target-version.cpp
@@ -231,7 +231,8 @@ int bar() {
 // CHECK-NEXT:    ret i32 [[ADD3]]
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_Z3fooi.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_Z3fooi.resolver(
+// CHECK-SAME: ) #[[ATTR11:[0-9]+]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -245,7 +246,8 @@ int bar() {
 // CHECK-NEXT:    ret ptr @_Z3fooi.default
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_Z3foov.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_Z3foov.resolver(
+// CHECK-SAME: ) #[[ATTR11]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -259,7 +261,8 @@ int bar() {
 // CHECK-NEXT:    ret ptr @_Z3foov.default
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_ZN7MyClass3gooEi.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_ZN7MyClass3gooEi.resolver(
+// CHECK-SAME: ) #[[ATTR11]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -281,7 +284,8 @@ int bar() {
 // CHECK-NEXT:    ret ptr @_ZN7MyClass3gooEi.default
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_ZN7MyClass23unused_with_default_defEv.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_ZN7MyClass23unused_with_default_defEv.resolver(
+// CHECK-SAME: ) #[[ATTR11]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -295,7 +299,8 @@ int bar() {
 // CHECK-NEXT:    ret ptr @_ZN7MyClass23unused_with_default_defEv.default
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_ZN7MyClass32unused_with_implicit_default_defEv.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_ZN7MyClass32unused_with_implicit_default_defEv.resolver(
+// CHECK-SAME: ) #[[ATTR11]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -309,7 +314,8 @@ int bar() {
 // CHECK-NEXT:    ret ptr @_ZN7MyClass32unused_with_implicit_default_defEv.default
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_ZN7MyClass40unused_with_implicit_forward_default_defEv.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_ZN7MyClass40unused_with_implicit_forward_default_defEv.resolver(
+// CHECK-SAME: ) #[[ATTR11]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -334,7 +340,7 @@ int bar() {
 // CHECK: attributes #[[ATTR8]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon" }
 // CHECK: attributes #[[ATTR9]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+lse" }
 // CHECK: attributes #[[ATTR10]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+neon,+rdm" }
-// CHECK: attributes #[[ATTR11:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+// CHECK: attributes #[[ATTR11]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
 //.
 // CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
 // CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
diff --git a/clang/test/CodeGenCXX/fmv-namespace.cpp b/clang/test/CodeGenCXX/fmv-namespace.cpp
index 1ac88e68a3a12..35eda4fd756cc 100644
--- a/clang/test/CodeGenCXX/fmv-namespace.cpp
+++ b/clang/test/CodeGenCXX/fmv-namespace.cpp
@@ -72,7 +72,8 @@ __attribute((target_version("mops"))) int bar() { return 1; }
 // CHECK-NEXT:    ret i32 0
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_ZN4Name3fooEv.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_ZN4Name3fooEv.resolver(
+// CHECK-SAME: ) #[[ATTR4:[0-9]+]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -86,7 +87,8 @@ __attribute((target_version("mops"))) int bar() { return 1; }
 // CHECK-NEXT:    ret ptr @_ZN4Name3fooEv.default
 //
 //
-// CHECK-LABEL: define weak_odr ptr @_ZN3Foo3barEv.resolver() comdat {
+// CHECK-LABEL: define weak_odr ptr @_ZN3Foo3barEv.resolver(
+// CHECK-SAME: ) #[[ATTR4]] comdat {
 // CHECK-NEXT:  [[RESOLVER_ENTRY:.*:]]
 // CHECK-NEXT:    call void @__init_cpu_features_resolver()
 // CHECK-NEXT:    [[TMP0:%.*]] = load i64, ptr @__aarch64_cpu_features, align 8
@@ -104,6 +106,7 @@ __attribute((target_version("mops"))) int bar() { return 1; }
 // CHECK: attributes #[[ATTR1]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
 // CHECK: attributes #[[ATTR2:[0-9]+]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+fp-armv8,+fullfp16,+neon,+sve" }
 // CHECK: attributes #[[ATTR3]] = { mustprogress noinline nounwind optnone "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-features"="+mops" }
+// CHECK: attributes #[[ATTR4]] = { "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
 //.
 // CHECK: [[META0:![0-9]+]] = !{i32 1, !"wchar_size", i32 4}
 // CHECK: [[META1:![0-9]+]] = !{!"{{.*}}clang version {{.*}}"}
diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index 1c4e9e9111441..a482545610c2b 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -595,16 +595,21 @@ class AsmPrinter : public MachineFunctionPass {
     return nullptr;
   }
 
+  virtual const MCExpr *
+  emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
+    return Init;
+  }
+
   virtual void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
                                       MCSymbol *LazyPointer) {
-    llvm_unreachable(
-        "Mach-O IFunc lowering is not yet supported on this target");
+    assert(false &&
+           "Mach-O IFunc lowering is not yet supported on this target");
   }
 
   virtual void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
                                             MCSymbol *LazyPointer) {
-    llvm_unreachable(
-        "Mach-O IFunc lowering is not yet supported on this target");
+    assert(false &&
+           "Mach-O IFunc lowering is not yet supported on this target");
   }
 
   /// Emit N NOP instructions.
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 91b5703944f3d..86ba76262659d 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2231,7 +2231,8 @@ void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
   emitAlignment(Align(DL.getPointerSize()));
   OutStreamer->emitLabel(LazyPointer);
   emitVisibility(LazyPointer, GI.getVisibility());
-  OutStreamer->emitValue(MCSymbolRefExpr::create(StubHelper, OutContext), 8);
+  const MCSymbolRefExpr *Init = MCSymbolRefExpr::create(StubHelper, OutContext);
+  OutStreamer->emitValue(emitMachOIfuncLazyPointerInit(Init), 8);
 
   OutStreamer->switchSection(OutContext.getObjectFileInfo()->getTextSection());
 
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 1e60ce9c40df8..4d7232f44c007 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -226,6 +226,8 @@ class AArch64AsmPrinter : public AsmPrinter {
     assert(STI);
     return STI;
   }
+  const MCExpr *
+  emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) override;
   void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
                               MCSymbol *LazyPointer) override;
   void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
@@ -2419,6 +2421,15 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
   EmitToStreamer(*OutStreamer, TmpInst);
 }
 
+const MCExpr *
+AArch64AsmPrinter::emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
+  if (TM.getTargetTriple().isArm64e())
+    return AArch64AuthMCExpr::create(Init, /*Disc=*/0, AArch64PACKey::IA,
+                                     /*HasAddressDiversity=*/false, OutContext);
+
+  return Init;
+}
+
 void AArch64AsmPrinter::emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
                                                MCSymbol *LazyPointer) {
   // _ifunc:
@@ -2502,6 +2513,9 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
   //   ldp	fp, lr, [sp], #16
   //   br	x16
 
+  if (TM.getTargetTriple().isArm64e())
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::PACIBSP), *STI);
+
   OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXpre)
                                    .addReg(AArch64::SP)
                                    .addReg(AArch64::FP)
@@ -2607,6 +2621,37 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
                                    .addImm(2),
                                *STI);
 
+  if (TM.getTargetTriple().isArm64e()) {
+    //   autibsp
+    //   eor x17, lr, lr, lsl #1
+    //   tbz x17, #62, Lgoodsig
+    //   brk #0xc741
+    // Lgoodsig:
+
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::AUTIBSP), *STI);
+
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::EORXrs)
+                                     .addReg(AArch64::X17)
+                                     .addReg(AArch64::LR)
+                                     .addReg(AArch64::LR)
+                                     .addImm(1),
+                                 *STI);
+
+    MCContext &Ctx = OutStreamer->getContext();
+    MCSymbol *GoodSigSym = Ctx.createTempSymbol();
+    const MCExpr *GoodSig = MCSymbolRefExpr::create(GoodSigSym, Ctx);
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::TBZX)
+                                     .addReg(AArch64::X17)
+                                     .addImm(62)
+                                     .addExpr(GoodSig),
+                                 *STI);
+
+    OutStreamer->emitInstruction(MCInstBuilder(AArch64::BRK).addImm(0xc471),
+                                 *STI);
+
+    OutStreamer->emitLabel(GoodSigSym);
+  }
+
   OutStreamer->emitInstruction(MCInstBuilder(TM.getTargetTriple().isArm64e()
                                                  ? AArch64::BRAAZ
                                                  : AArch64::BR)
diff --git a/llvm/test/CodeGen/AArch64/ifunc-asm.ll b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
index 57fc2f0c9d7f5..6f0d6f633fd51 100644
--- a/llvm/test/CodeGen/AArch64/ifunc-asm.ll
+++ b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
@@ -1,6 +1,8 @@
 ; RUN: llc -mtriple=arm64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=ELF
-; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefix=MACHO
-; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefix=MACHO
+; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,ARM64
+; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,ARM64
+; RUN: llc -mtriple=arm64e-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
+; RUN: llc -mtriple=arm64e-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
 
 define internal ptr @the_resolver() {
 entry:
@@ -21,7 +23,8 @@ entry:
 ; MACHO:           .section __DATA,__data
 ; MACHO-NEXT:      .p2align 3, 0x0
 ; MACHO-NEXT:  _global_ifunc.lazy_pointer:
-; MACHO-NEXT:      .quad _global_ifunc.stub_helper
+; ARM64-NEXT:      .quad _global_ifunc.stub_helper{{$}}
+; PAUTH-NEXT:      .quad _global_ifunc.stub_helper at AUTH(ia,0)
 
 ; MACHO:           .section __TEXT,__text,regular,pure_instructions
 ; MACHO-NEXT:      .globl _global_ifunc
@@ -30,9 +33,11 @@ entry:
 ; MACHO-NEXT:      adrp    x16, _global_ifunc.lazy_pointer at GOTPAGE
 ; MACHO-NEXT:      ldr     x16, [x16, _global_ifunc.lazy_pointer at GOTPAGEOFF]
 ; MACHO-NEXT:      ldr     x16, [x16]
-; MACHO-NEXT:      br      x16
+; ARM64-NEXT:      br      x16
+; PAUTH-NEXT:      braaz   x16
 ; MACHO-NEXT:      .p2align        2
 ; MACHO-NEXT:  _global_ifunc.stub_helper:
+; PAUTH-NEXT:      pacibsp
 ; MACHO-NEXT:      stp     x29, x30, [sp, #-16]!
 ; MACHO-NEXT:      mov     x29, sp
 ; MACHO-NEXT:      stp     x1, x0, [sp, #-16]!
@@ -57,7 +62,13 @@ entry:
 ; MACHO-NEXT:      ldp     x3, x2, [sp], #16
 ; MACHO-NEXT:      ldp     x1, x0, [sp], #16
 ; MACHO-NEXT:      ldp     x29, x30, [sp], #16
-; MACHO-NEXT:      br      x16
+; PAUTH-NEXT:      autibsp
+; PAUTH-NEXT:      eor     x17, x30, x30, lsl #1
+; PAUTH-NEXT:      tbz     x17, #62, [[GOOD_SIG:Ltmp[0-9]+]]
+; PAUTH-NEXT:      brk     #0xc471
+; PAUTH-NEXT: [[GOOD_SIG]]:
+; ARM64-NEXT:      br      x16
+; PAUTH-NEXT:      braaz   x16
 
 
 @weak_ifunc = weak ifunc i32 (i32), ptr @the_resolver

>From ec43ccba4484e550f2e8732be8fc00f3110772ba Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Mon, 22 Jul 2024 13:31:17 -0700
Subject: [PATCH 4/5] drop support for ifunc ptrauth tail. we'll stick the
 revert of this on the upstreaming branch

---
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 31 -------------------
 llvm/test/CodeGen/AArch64/ifunc-asm.ll        |  5 ---
 2 files changed, 36 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 4d7232f44c007..fe35d5a7d839c 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -2621,37 +2621,6 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
                                    .addImm(2),
                                *STI);
 
-  if (TM.getTargetTriple().isArm64e()) {
-    //   autibsp
-    //   eor x17, lr, lr, lsl #1
-    //   tbz x17, #62, Lgoodsig
-    //   brk #0xc741
-    // Lgoodsig:
-
-    OutStreamer->emitInstruction(MCInstBuilder(AArch64::AUTIBSP), *STI);
-
-    OutStreamer->emitInstruction(MCInstBuilder(AArch64::EORXrs)
-                                     .addReg(AArch64::X17)
-                                     .addReg(AArch64::LR)
-                                     .addReg(AArch64::LR)
-                                     .addImm(1),
-                                 *STI);
-
-    MCContext &Ctx = OutStreamer->getContext();
-    MCSymbol *GoodSigSym = Ctx.createTempSymbol();
-    const MCExpr *GoodSig = MCSymbolRefExpr::create(GoodSigSym, Ctx);
-    OutStreamer->emitInstruction(MCInstBuilder(AArch64::TBZX)
-                                     .addReg(AArch64::X17)
-                                     .addImm(62)
-                                     .addExpr(GoodSig),
-                                 *STI);
-
-    OutStreamer->emitInstruction(MCInstBuilder(AArch64::BRK).addImm(0xc471),
-                                 *STI);
-
-    OutStreamer->emitLabel(GoodSigSym);
-  }
-
   OutStreamer->emitInstruction(MCInstBuilder(TM.getTargetTriple().isArm64e()
                                                  ? AArch64::BRAAZ
                                                  : AArch64::BR)
diff --git a/llvm/test/CodeGen/AArch64/ifunc-asm.ll b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
index 6f0d6f633fd51..1686eb4449276 100644
--- a/llvm/test/CodeGen/AArch64/ifunc-asm.ll
+++ b/llvm/test/CodeGen/AArch64/ifunc-asm.ll
@@ -62,11 +62,6 @@ entry:
 ; MACHO-NEXT:      ldp     x3, x2, [sp], #16
 ; MACHO-NEXT:      ldp     x1, x0, [sp], #16
 ; MACHO-NEXT:      ldp     x29, x30, [sp], #16
-; PAUTH-NEXT:      autibsp
-; PAUTH-NEXT:      eor     x17, x30, x30, lsl #1
-; PAUTH-NEXT:      tbz     x17, #62, [[GOOD_SIG:Ltmp[0-9]+]]
-; PAUTH-NEXT:      brk     #0xc471
-; PAUTH-NEXT: [[GOOD_SIG]]:
 ; ARM64-NEXT:      br      x16
 ; PAUTH-NEXT:      braaz   x16
 

>From bd8b5e1180e0a6c8f43bf0777317255a866ef1e0 Mon Sep 17 00:00:00 2001
From: Jon Roelofs <jonathan_roelofs at apple.com>
Date: Mon, 22 Jul 2024 14:00:34 -0700
Subject: [PATCH 5/5] test ptrauth-{calls,returns} attrs on the resolver
 instead of isArm64e()

---
 llvm/include/llvm/CodeGen/AsmPrinter.h        |  3 +-
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp    |  2 +-
 llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp | 32 +++++----
 .../{ifunc-asm.ll => ifunc-asm-arm64.ll}      |  6 --
 llvm/test/CodeGen/AArch64/ifunc-asm-arm64e.ll | 65 +++++++++++++++++++
 5 files changed, 86 insertions(+), 22 deletions(-)
 rename llvm/test/CodeGen/AArch64/{ifunc-asm.ll => ifunc-asm-arm64.ll} (89%)
 create mode 100644 llvm/test/CodeGen/AArch64/ifunc-asm-arm64e.ll

diff --git a/llvm/include/llvm/CodeGen/AsmPrinter.h b/llvm/include/llvm/CodeGen/AsmPrinter.h
index a482545610c2b..9961dde1e75d0 100644
--- a/llvm/include/llvm/CodeGen/AsmPrinter.h
+++ b/llvm/include/llvm/CodeGen/AsmPrinter.h
@@ -596,7 +596,8 @@ class AsmPrinter : public MachineFunctionPass {
   }
 
   virtual const MCExpr *
-  emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
+  emitMachOIfuncLazyPointerInit(const GlobalIFunc &GI,
+                                const MCSymbolRefExpr *Init) {
     return Init;
   }
 
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 86ba76262659d..3c7128a8481af 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -2232,7 +2232,7 @@ void AsmPrinter::emitGlobalIFunc(Module &M, const GlobalIFunc &GI) {
   OutStreamer->emitLabel(LazyPointer);
   emitVisibility(LazyPointer, GI.getVisibility());
   const MCSymbolRefExpr *Init = MCSymbolRefExpr::create(StubHelper, OutContext);
-  OutStreamer->emitValue(emitMachOIfuncLazyPointerInit(Init), 8);
+  OutStreamer->emitValue(emitMachOIfuncLazyPointerInit(GI, Init), 8);
 
   OutStreamer->switchSection(OutContext.getObjectFileInfo()->getTextSection());
 
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index fe35d5a7d839c..ed110d144b8bd 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -227,7 +227,8 @@ class AArch64AsmPrinter : public AsmPrinter {
     return STI;
   }
   const MCExpr *
-  emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) override;
+  emitMachOIfuncLazyPointerInit(const GlobalIFunc &GI,
+                                const MCSymbolRefExpr *Init) override;
   void emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
                               MCSymbol *LazyPointer) override;
   void emitMachOIFuncStubHelperBody(Module &M, const GlobalIFunc &GI,
@@ -2422,8 +2423,9 @@ void AArch64AsmPrinter::emitInstruction(const MachineInstr *MI) {
 }
 
 const MCExpr *
-AArch64AsmPrinter::emitMachOIfuncLazyPointerInit(const MCSymbolRefExpr *Init) {
-  if (TM.getTargetTriple().isArm64e())
+AArch64AsmPrinter::emitMachOIfuncLazyPointerInit(const GlobalIFunc &GI,
+                                                 const MCSymbolRefExpr *Init) {
+  if (GI.getResolverFunction()->hasFnAttribute("ptrauth-calls"))
     return AArch64AuthMCExpr::create(Init, /*Disc=*/0, AArch64PACKey::IA,
                                      /*HasAddressDiversity=*/false, OutContext);
 
@@ -2472,11 +2474,12 @@ void AArch64AsmPrinter::emitMachOIFuncStubBody(Module &M, const GlobalIFunc &GI,
                                    .addImm(0),
                                *STI);
 
-  OutStreamer->emitInstruction(MCInstBuilder(TM.getTargetTriple().isArm64e()
-                                                 ? AArch64::BRAAZ
-                                                 : AArch64::BR)
-                                   .addReg(AArch64::X16),
-                               *STI);
+  OutStreamer->emitInstruction(
+      MCInstBuilder(GI.getResolverFunction()->hasFnAttribute("ptrauth-calls")
+                        ? AArch64::BRAAZ
+                        : AArch64::BR)
+          .addReg(AArch64::X16),
+      *STI);
 }
 
 void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
@@ -2513,7 +2516,7 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
   //   ldp	fp, lr, [sp], #16
   //   br	x16
 
-  if (TM.getTargetTriple().isArm64e())
+  if (GI.getResolverFunction()->hasFnAttribute("ptrauth-returns"))
     OutStreamer->emitInstruction(MCInstBuilder(AArch64::PACIBSP), *STI);
 
   OutStreamer->emitInstruction(MCInstBuilder(AArch64::STPXpre)
@@ -2621,11 +2624,12 @@ void AArch64AsmPrinter::emitMachOIFuncStubHelperBody(Module &M,
                                    .addImm(2),
                                *STI);
 
-  OutStreamer->emitInstruction(MCInstBuilder(TM.getTargetTriple().isArm64e()
-                                                 ? AArch64::BRAAZ
-                                                 : AArch64::BR)
-                                   .addReg(AArch64::X16),
-                               *STI);
+  OutStreamer->emitInstruction(
+      MCInstBuilder(GI.getResolverFunction()->hasFnAttribute("ptrauth-calls")
+                        ? AArch64::BRAAZ
+                        : AArch64::BR)
+          .addReg(AArch64::X16),
+      *STI);
 }
 
 const MCExpr *AArch64AsmPrinter::lowerConstant(const Constant *CV) {
diff --git a/llvm/test/CodeGen/AArch64/ifunc-asm.ll b/llvm/test/CodeGen/AArch64/ifunc-asm-arm64.ll
similarity index 89%
rename from llvm/test/CodeGen/AArch64/ifunc-asm.ll
rename to llvm/test/CodeGen/AArch64/ifunc-asm-arm64.ll
index 1686eb4449276..f093baadffd8b 100644
--- a/llvm/test/CodeGen/AArch64/ifunc-asm.ll
+++ b/llvm/test/CodeGen/AArch64/ifunc-asm-arm64.ll
@@ -1,8 +1,6 @@
 ; RUN: llc -mtriple=arm64-unknown-linux-gnu %s -o - | FileCheck %s --check-prefixes=ELF
 ; RUN: llc -mtriple=arm64-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,ARM64
 ; RUN: llc -mtriple=arm64-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,ARM64
-; RUN: llc -mtriple=arm64e-apple-darwin %s -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
-; RUN: llc -mtriple=arm64e-apple-darwin %s -global-isel -o - | FileCheck %s --check-prefixes=MACHO,PAUTH
 
 define internal ptr @the_resolver() {
 entry:
@@ -24,7 +22,6 @@ entry:
 ; MACHO-NEXT:      .p2align 3, 0x0
 ; MACHO-NEXT:  _global_ifunc.lazy_pointer:
 ; ARM64-NEXT:      .quad _global_ifunc.stub_helper{{$}}
-; PAUTH-NEXT:      .quad _global_ifunc.stub_helper at AUTH(ia,0)
 
 ; MACHO:           .section __TEXT,__text,regular,pure_instructions
 ; MACHO-NEXT:      .globl _global_ifunc
@@ -34,10 +31,8 @@ entry:
 ; MACHO-NEXT:      ldr     x16, [x16, _global_ifunc.lazy_pointer at GOTPAGEOFF]
 ; MACHO-NEXT:      ldr     x16, [x16]
 ; ARM64-NEXT:      br      x16
-; PAUTH-NEXT:      braaz   x16
 ; MACHO-NEXT:      .p2align        2
 ; MACHO-NEXT:  _global_ifunc.stub_helper:
-; PAUTH-NEXT:      pacibsp
 ; MACHO-NEXT:      stp     x29, x30, [sp, #-16]!
 ; MACHO-NEXT:      mov     x29, sp
 ; MACHO-NEXT:      stp     x1, x0, [sp, #-16]!
@@ -63,7 +58,6 @@ entry:
 ; MACHO-NEXT:      ldp     x1, x0, [sp], #16
 ; MACHO-NEXT:      ldp     x29, x30, [sp], #16
 ; ARM64-NEXT:      br      x16
-; PAUTH-NEXT:      braaz   x16
 
 
 @weak_ifunc = weak ifunc i32 (i32), ptr @the_resolver
diff --git a/llvm/test/CodeGen/AArch64/ifunc-asm-arm64e.ll b/llvm/test/CodeGen/AArch64/ifunc-asm-arm64e.ll
new file mode 100644
index 0000000000000..6f8f7aabcb038
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/ifunc-asm-arm64e.ll
@@ -0,0 +1,65 @@
+; RUN: llc -mtriple=arm64e-apple-darwin %s -o - | FileCheck %s
+; RUN: llc -mtriple=arm64e-apple-darwin %s -global-isel -o - | FileCheck %s
+
+attributes #0 = { "ptrauth-calls" "ptrauth-returns" }
+
+define internal ptr @the_resolver() #0 {
+entry:
+  ret ptr null
+}
+
+; CHECK:           .p2align 2
+; CHECK-NEXT:  _the_resolver:
+
+
+ at global_ifunc = ifunc i32 (i32), ptr @the_resolver
+; CHECK:           .section __DATA,__data
+; CHECK-NEXT:      .p2align 3, 0x0
+; CHECK-NEXT:  _global_ifunc.lazy_pointer:
+; CHECK-NEXT:      .quad _global_ifunc.stub_helper at AUTH(ia,0)
+
+; CHECK:           .section __TEXT,__text,regular,pure_instructions
+; CHECK-NEXT:      .globl _global_ifunc
+; CHECK-NEXT:      .p2align 2
+; CHECK-NEXT:  _global_ifunc:
+; CHECK-NEXT:      adrp    x16, _global_ifunc.lazy_pointer at GOTPAGE
+; CHECK-NEXT:      ldr     x16, [x16, _global_ifunc.lazy_pointer at GOTPAGEOFF]
+; CHECK-NEXT:      ldr     x16, [x16]
+; CHECK-NEXT:      braaz   x16
+; CHECK-NEXT:      .p2align        2
+; CHECK-NEXT:  _global_ifunc.stub_helper:
+; CHECK-NEXT:      pacibsp
+; CHECK-NEXT:      stp     x29, x30, [sp, #-16]!
+; CHECK-NEXT:      mov     x29, sp
+; CHECK-NEXT:      stp     x1, x0, [sp, #-16]!
+; CHECK-NEXT:      stp     x3, x2, [sp, #-16]!
+; CHECK-NEXT:      stp     x5, x4, [sp, #-16]!
+; CHECK-NEXT:      stp     x7, x6, [sp, #-16]!
+; CHECK-NEXT:      stp     d1, d0, [sp, #-16]!
+; CHECK-NEXT:      stp     d3, d2, [sp, #-16]!
+; CHECK-NEXT:      stp     d5, d4, [sp, #-16]!
+; CHECK-NEXT:      stp     d7, d6, [sp, #-16]!
+; CHECK-NEXT:      bl      _the_resolver
+; CHECK-NEXT:      adrp    x16, _global_ifunc.lazy_pointer at GOTPAGE
+; CHECK-NEXT:      ldr     x16, [x16, _global_ifunc.lazy_pointer at GOTPAGEOFF]
+; CHECK-NEXT:      str     x0, [x16]
+; CHECK-NEXT:      add     x16, x0, #0
+; CHECK-NEXT:      ldp     d7, d6, [sp], #16
+; CHECK-NEXT:      ldp     d5, d4, [sp], #16
+; CHECK-NEXT:      ldp     d3, d2, [sp], #16
+; CHECK-NEXT:      ldp     d1, d0, [sp], #16
+; CHECK-NEXT:      ldp     x7, x6, [sp], #16
+; CHECK-NEXT:      ldp     x5, x4, [sp], #16
+; CHECK-NEXT:      ldp     x3, x2, [sp], #16
+; CHECK-NEXT:      ldp     x1, x0, [sp], #16
+; CHECK-NEXT:      ldp     x29, x30, [sp], #16
+; CHECK-NEXT:      braaz   x16
+
+
+ at weak_ifunc = weak ifunc i32 (i32), ptr @the_resolver
+; CHECK-NOT:       .weak_reference _weak_ifunc.lazy_pointer
+; CHECK:       _weak_ifunc.lazy_pointer:
+; CHECK:           .weak_reference _weak_ifunc
+; CHECK:       _weak_ifunc:
+; CHECK-NOT:       .weak_reference _weak_ifunc.stub_helper
+; CHECK:       _weak_ifunc.stub_helper:
\ No newline at end of file



More information about the llvm-commits mailing list