r371586 - [CodeGen] Add alias for cpu_dispatch function with IFunc & Fix resolver linkage type

Fangrui Song via cfe-commits cfe-commits at lists.llvm.org
Tue Sep 10 18:54:49 PDT 2019


Author: maskray
Date: Tue Sep 10 18:54:48 2019
New Revision: 371586

URL: http://llvm.org/viewvc/llvm-project?rev=371586&view=rev
Log:
[CodeGen] Add alias for cpu_dispatch function with IFunc & Fix resolver linkage type

Multi-versioned functions defined by cpu_dispatch and implemented with IFunc
can not be called outside the translation units where they are defined due to
lack of symbols. This patch add function aliases for these functions and thus
make them visible outside.

Differential Revision: https://reviews.llvm.org/D67058
Patch by Senran Zhang

Modified:
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp
    cfe/trunk/test/CodeGen/attr-cpuspecific.c
    cfe/trunk/test/CodeGen/attr-target-mv-func-ptrs.c
    cfe/trunk/test/CodeGen/attr-target-mv-va-args.c
    cfe/trunk/test/CodeGen/attr-target-mv.c
    cfe/trunk/test/CodeGenCXX/attr-cpuspecific.cpp
    cfe/trunk/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
    cfe/trunk/test/CodeGenCXX/attr-target-mv-inalloca.cpp
    cfe/trunk/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
    cfe/trunk/test/CodeGenCXX/attr-target-mv-modules.cpp
    cfe/trunk/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
    cfe/trunk/test/CodeGenCXX/attr-target-mv-overloads.cpp

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Sep 10 18:54:48 2019
@@ -2836,11 +2836,13 @@ void CodeGenModule::emitMultiVersionFunc
     llvm::Function *ResolverFunc;
     const TargetInfo &TI = getTarget();
 
-    if (TI.supportsIFunc() || FD->isTargetMultiVersion())
+    if (TI.supportsIFunc() || FD->isTargetMultiVersion()) {
       ResolverFunc = cast<llvm::Function>(
           GetGlobalValue((getMangledName(GD) + ".resolver").str()));
-    else
+      ResolverFunc->setLinkage(llvm::Function::WeakODRLinkage);
+    } else {
       ResolverFunc = cast<llvm::Function>(GetGlobalValue(getMangledName(GD)));
+    }
 
     if (supportsCOMDAT())
       ResolverFunc->setComdat(
@@ -2884,6 +2886,10 @@ void CodeGenModule::emitCPUDispatchDefin
 
   auto *ResolverFunc = cast<llvm::Function>(GetOrCreateLLVMFunction(
       ResolverName, ResolverType, ResolverGD, /*ForVTable=*/false));
+  ResolverFunc->setLinkage(llvm::Function::WeakODRLinkage);
+  if (supportsCOMDAT())
+    ResolverFunc->setComdat(
+        getModule().getOrInsertComdat(ResolverFunc->getName()));
 
   SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
   const TargetInfo &Target = getTarget();
@@ -2948,6 +2954,21 @@ void CodeGenModule::emitCPUDispatchDefin
 
   CodeGenFunction CGF(*this);
   CGF.EmitMultiVersionResolver(ResolverFunc, Options);
+
+  if (getTarget().supportsIFunc()) {
+    std::string AliasName = getMangledNameImpl(
+        *this, GD, FD, /*OmitMultiVersionMangling=*/true);
+    llvm::Constant *AliasFunc = GetGlobalValue(AliasName);
+    if (!AliasFunc) {
+      auto *IFunc = cast<llvm::GlobalIFunc>(GetOrCreateLLVMFunction(
+          AliasName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/true,
+          /*IsThunk=*/false, llvm::AttributeList(), NotForDefinition));
+      auto *GA = llvm::GlobalAlias::create(
+         DeclTy, 0, getFunctionLinkage(GD), AliasName, IFunc, &getModule());
+      GA->setLinkage(llvm::Function::WeakODRLinkage);
+      SetCommonAttributes(GD, GA);
+    }
+  }
 }
 
 /// If a dispatcher for the specified mangled name is not in the module, create
@@ -2984,7 +3005,7 @@ llvm::Constant *CodeGenModule::GetOrCrea
         MangledName + ".resolver", ResolverType, GlobalDecl{},
         /*ForVTable=*/false);
     llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create(
-        DeclTy, 0, llvm::Function::ExternalLinkage, "", Resolver, &getModule());
+        DeclTy, 0, llvm::Function::WeakODRLinkage, "", Resolver, &getModule());
     GIF->setName(ResolverName);
     SetCommonAttributes(FD, GIF);
 

Modified: cfe/trunk/test/CodeGen/attr-cpuspecific.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attr-cpuspecific.c?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/attr-cpuspecific.c (original)
+++ cfe/trunk/test/CodeGen/attr-cpuspecific.c Tue Sep 10 18:54:48 2019
@@ -7,11 +7,27 @@
 #define ATTR(X) __attribute__((X))
 #endif // _MSC_VER
 
-// Each called version should have an IFunc.
-// LINUX: @SingleVersion.ifunc = ifunc void (), void ()* ()* @SingleVersion.resolver
-// LINUX: @TwoVersions.ifunc = ifunc void (), void ()* ()* @TwoVersions.resolver
-// LINUX: @TwoVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @TwoVersionsSameAttr.resolver
-// LINUX: @ThreeVersionsSameAttr.ifunc = ifunc void (), void ()* ()* @ThreeVersionsSameAttr.resolver
+// Each version should have an IFunc and an alias.
+// LINUX: @TwoVersions = weak_odr alias void (), void ()* @TwoVersions.ifunc
+// LINUX: @TwoVersionsSameAttr = weak_odr alias void (), void ()* @TwoVersionsSameAttr.ifunc
+// LINUX: @ThreeVersionsSameAttr = weak_odr alias void (), void ()* @ThreeVersionsSameAttr.ifunc
+// LINUX: @NoSpecifics = weak_odr alias void (), void ()* @NoSpecifics.ifunc
+// LINUX: @HasGeneric = weak_odr alias void (), void ()* @HasGeneric.ifunc
+// LINUX: @HasParams = weak_odr alias void (i32, double), void (i32, double)* @HasParams.ifunc
+// LINUX: @HasParamsAndReturn = weak_odr alias i32 (i32, double), i32 (i32, double)* @HasParamsAndReturn.ifunc
+// LINUX: @GenericAndPentium = weak_odr alias i32 (i32, double), i32 (i32, double)* @GenericAndPentium.ifunc
+// LINUX: @DispatchFirst = weak_odr alias i32 (), i32 ()* @DispatchFirst.ifunc
+
+// LINUX: @TwoVersions.ifunc = weak_odr ifunc void (), void ()* ()* @TwoVersions.resolver
+// LINUX: @SingleVersion.ifunc = weak_odr ifunc void (), void ()* ()* @SingleVersion.resolver
+// LINUX: @TwoVersionsSameAttr.ifunc = weak_odr ifunc void (), void ()* ()* @TwoVersionsSameAttr.resolver
+// LINUX: @ThreeVersionsSameAttr.ifunc = weak_odr ifunc void (), void ()* ()* @ThreeVersionsSameAttr.resolver
+// LINUX: @NoSpecifics.ifunc = weak_odr ifunc void (), void ()* ()* @NoSpecifics.resolver
+// LINUX: @HasGeneric.ifunc = weak_odr ifunc void (), void ()* ()* @HasGeneric.resolver
+// LINUX: @HasParams.ifunc = weak_odr ifunc void (i32, double), void (i32, double)* ()* @HasParams.resolver
+// LINUX: @HasParamsAndReturn.ifunc = weak_odr ifunc i32 (i32, double), i32 (i32, double)* ()* @HasParamsAndReturn.resolver
+// LINUX: @GenericAndPentium.ifunc = weak_odr ifunc i32 (i32, double), i32 (i32, double)* ()* @GenericAndPentium.resolver
+// LINUX: @DispatchFirst.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @DispatchFirst.resolver
 
 ATTR(cpu_specific(ivybridge))
 void SingleVersion(void){}
@@ -29,14 +45,14 @@ void TwoVersions(void);
 
 ATTR(cpu_dispatch(ivybridge, knl))
 void TwoVersions(void);
-// LINUX: define void ()* @TwoVersions.resolver()
+// LINUX: define weak_odr void ()* @TwoVersions.resolver()
 // LINUX: call void @__cpu_indicator_init
 // LINUX: ret void ()* @TwoVersions.Z
 // LINUX: ret void ()* @TwoVersions.S
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define dso_local void @TwoVersions()
+// WINDOWS: define weak_odr dso_local void @TwoVersions() comdat
 // WINDOWS: call void @__cpu_indicator_init()
 // WINDOWS: call void @TwoVersions.Z()
 // WINDOWS-NEXT: ret void
@@ -82,14 +98,14 @@ void usages() {
 // has an extra config to emit!
 ATTR(cpu_dispatch(ivybridge, knl, atom))
 void TwoVersionsSameAttr(void);
-// LINUX: define void ()* @TwoVersionsSameAttr.resolver()
+// LINUX: define weak_odr void ()* @TwoVersionsSameAttr.resolver()
 // LINUX: ret void ()* @TwoVersionsSameAttr.Z
 // LINUX: ret void ()* @TwoVersionsSameAttr.S
 // LINUX: ret void ()* @TwoVersionsSameAttr.O
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define dso_local void @TwoVersionsSameAttr()
+// WINDOWS: define weak_odr dso_local void @TwoVersionsSameAttr() comdat
 // WINDOWS: call void @TwoVersionsSameAttr.Z
 // WINDOWS-NEXT: ret void
 // WINDOWS: call void @TwoVersionsSameAttr.S
@@ -101,7 +117,7 @@ void TwoVersionsSameAttr(void);
 
 ATTR(cpu_dispatch(atom, ivybridge, knl))
 void ThreeVersionsSameAttr(void){}
-// LINUX: define void ()* @ThreeVersionsSameAttr.resolver()
+// LINUX: define weak_odr void ()* @ThreeVersionsSameAttr.resolver()
 // LINUX: call void @__cpu_indicator_init
 // LINUX: ret void ()* @ThreeVersionsSameAttr.Z
 // LINUX: ret void ()* @ThreeVersionsSameAttr.S
@@ -109,7 +125,7 @@ void ThreeVersionsSameAttr(void){}
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define dso_local void @ThreeVersionsSameAttr()
+// WINDOWS: define weak_odr dso_local void @ThreeVersionsSameAttr() comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @ThreeVersionsSameAttr.Z
 // WINDOWS-NEXT: ret void
@@ -123,7 +139,7 @@ void ThreeVersionsSameAttr(void){}
 // No Cpu Specific options.
 ATTR(cpu_dispatch(atom, ivybridge, knl))
 void NoSpecifics(void);
-// LINUX: define void ()* @NoSpecifics.resolver()
+// LINUX: define weak_odr void ()* @NoSpecifics.resolver()
 // LINUX: call void @__cpu_indicator_init
 // LINUX: ret void ()* @NoSpecifics.Z
 // LINUX: ret void ()* @NoSpecifics.S
@@ -131,7 +147,7 @@ void NoSpecifics(void);
 // LINUX: call void @llvm.trap
 // LINUX: unreachable
 
-// WINDOWS: define dso_local void @NoSpecifics()
+// WINDOWS: define weak_odr dso_local void @NoSpecifics() comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @NoSpecifics.Z
 // WINDOWS-NEXT: ret void
@@ -144,7 +160,7 @@ void NoSpecifics(void);
 
 ATTR(cpu_dispatch(atom, generic, ivybridge, knl))
 void HasGeneric(void);
-// LINUX: define void ()* @HasGeneric.resolver()
+// LINUX: define weak_odr void ()* @HasGeneric.resolver()
 // LINUX: call void @__cpu_indicator_init
 // LINUX: ret void ()* @HasGeneric.Z
 // LINUX: ret void ()* @HasGeneric.S
@@ -152,7 +168,7 @@ void HasGeneric(void);
 // LINUX: ret void ()* @HasGeneric.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define dso_local void @HasGeneric()
+// WINDOWS: define weak_odr dso_local void @HasGeneric() comdat
 // WINDOWS: call void @__cpu_indicator_init
 // WINDOWS: call void @HasGeneric.Z
 // WINDOWS-NEXT: ret void
@@ -166,7 +182,7 @@ void HasGeneric(void);
 
 ATTR(cpu_dispatch(atom, generic, ivybridge, knl))
 void HasParams(int i, double d);
-// LINUX: define void (i32, double)* @HasParams.resolver()
+// LINUX: define weak_odr void (i32, double)* @HasParams.resolver()
 // LINUX: call void @__cpu_indicator_init
 // LINUX: ret void (i32, double)* @HasParams.Z
 // LINUX: ret void (i32, double)* @HasParams.S
@@ -174,7 +190,7 @@ void HasParams(int i, double d);
 // LINUX: ret void (i32, double)* @HasParams.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define dso_local void @HasParams(i32 %0, double %1)
+// 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
@@ -188,7 +204,7 @@ void HasParams(int i, double d);
 
 ATTR(cpu_dispatch(atom, generic, ivybridge, knl))
 int HasParamsAndReturn(int i, double d);
-// LINUX: define i32 (i32, double)* @HasParamsAndReturn.resolver()
+// LINUX: define weak_odr i32 (i32, double)* @HasParamsAndReturn.resolver()
 // LINUX: call void @__cpu_indicator_init
 // LINUX: ret i32 (i32, double)* @HasParamsAndReturn.Z
 // LINUX: ret i32 (i32, double)* @HasParamsAndReturn.S
@@ -196,7 +212,7 @@ int HasParamsAndReturn(int i, double d);
 // LINUX: ret i32 (i32, double)* @HasParamsAndReturn.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define dso_local i32 @HasParamsAndReturn(i32 %0, double %1)
+// 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]]
@@ -210,14 +226,14 @@ int HasParamsAndReturn(int i, double d);
 
 ATTR(cpu_dispatch(atom, generic, pentium))
 int GenericAndPentium(int i, double d);
-// LINUX: define i32 (i32, double)* @GenericAndPentium.resolver()
+// LINUX: define weak_odr i32 (i32, double)* @GenericAndPentium.resolver()
 // LINUX: call void @__cpu_indicator_init
 // LINUX: ret i32 (i32, double)* @GenericAndPentium.O
 // LINUX: ret i32 (i32, double)* @GenericAndPentium.B
 // LINUX-NOT: ret i32 (i32, double)* @GenericAndPentium.A
 // LINUX-NOT: call void @llvm.trap
 
-// WINDOWS: define dso_local i32 @GenericAndPentium(i32 %0, double %1)
+// 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]]
@@ -228,11 +244,11 @@ int GenericAndPentium(int i, double d);
 
 ATTR(cpu_dispatch(atom, pentium))
 int DispatchFirst(void);
-// LINUX: define i32 ()* @DispatchFirst.resolver
+// LINUX: define weak_odr i32 ()* @DispatchFirst.resolver
 // LINUX: ret i32 ()* @DispatchFirst.O
 // LINUX: ret i32 ()* @DispatchFirst.B
 
-// WINDOWS: define dso_local i32 @DispatchFirst()
+// 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()

Modified: cfe/trunk/test/CodeGen/attr-target-mv-func-ptrs.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attr-target-mv-func-ptrs.c?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/attr-target-mv-func-ptrs.c (original)
+++ cfe/trunk/test/CodeGen/attr-target-mv-func-ptrs.c Tue Sep 10 18:54:48 2019
@@ -17,7 +17,7 @@ int bar() {
   return Free(1) + Free(2);
 }
 
-// LINUX: @foo.ifunc = ifunc i32 (i32), i32 (i32)* ()* @foo.resolver
+// LINUX: @foo.ifunc = weak_odr ifunc i32 (i32), i32 (i32)* ()* @foo.resolver
 // LINUX: define i32 @foo.sse4.2(
 // LINUX: ret i32 0
 // LINUX: define i32 @foo.arch_ivybridge(

Modified: cfe/trunk/test/CodeGen/attr-target-mv-va-args.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attr-target-mv-va-args.c?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/attr-target-mv-va-args.c (original)
+++ cfe/trunk/test/CodeGen/attr-target-mv-va-args.c Tue Sep 10 18:54:48 2019
@@ -9,7 +9,7 @@ int bar() {
   return foo(1, 'a', 1.1) + foo(2, 2.2, "asdf");
 }
 
-// LINUX: @foo.ifunc = ifunc i32 (i32, ...), i32 (i32, ...)* ()* @foo.resolver
+// LINUX: @foo.ifunc = weak_odr ifunc i32 (i32, ...), i32 (i32, ...)* ()* @foo.resolver
 // LINUX: define i32 @foo.sse4.2(i32 %i, ...)
 // LINUX: ret i32 0
 // LINUX: define i32 @foo.arch_ivybridge(i32 %i, ...)
@@ -20,7 +20,7 @@ int bar() {
 // LINUX: call i32 (i32, ...) @foo.ifunc(i32 1, i32 97, double
 // LINUX: call i32 (i32, ...) @foo.ifunc(i32 2, double 2.2{{[0-9Ee+]+}}, i8* getelementptr inbounds
 
-// LINUX: define i32 (i32, ...)* @foo.resolver() comdat
+// LINUX: define weak_odr i32 (i32, ...)* @foo.resolver() comdat
 // LINUX: ret i32 (i32, ...)* @foo.arch_sandybridge
 // LINUX: ret i32 (i32, ...)* @foo.arch_ivybridge
 // LINUX: ret i32 (i32, ...)* @foo.sse4.2
@@ -37,7 +37,7 @@ int bar() {
 // WINDOWS: call i32 (i32, ...) @foo.resolver(i32 1, i32 97, double
 // WINDOWS: call i32 (i32, ...) @foo.resolver(i32 2, double 2.2{{[0-9Ee+]+}}, i8* getelementptr inbounds
 
-// WINDOWS: define dso_local i32 @foo.resolver(i32 %0, ...) comdat
+// WINDOWS: define weak_odr dso_local i32 @foo.resolver(i32 %0, ...) comdat
 // WINDOWS: musttail call i32 (i32, ...) @foo.arch_sandybridge
 // WINDOWS: musttail call i32 (i32, ...) @foo.arch_ivybridge
 // WINDOWS: musttail call i32 (i32, ...) @foo.sse4.2

Modified: cfe/trunk/test/CodeGen/attr-target-mv.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/attr-target-mv.c?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/test/CodeGen/attr-target-mv.c (original)
+++ cfe/trunk/test/CodeGen/attr-target-mv.c Tue Sep 10 18:54:48 2019
@@ -47,12 +47,12 @@ void bar5() {
   fwd_decl_avx();
 }
 
-// LINUX: @foo.ifunc = ifunc i32 (), i32 ()* ()* @foo.resolver
-// LINUX: @foo_inline.ifunc = ifunc i32 (), i32 ()* ()* @foo_inline.resolver
-// LINUX: @foo_decls.ifunc = ifunc void (), void ()* ()* @foo_decls.resolver
-// LINUX: @foo_multi.ifunc = ifunc void (i32, double), void (i32, double)* ()* @foo_multi.resolver
-// LINUX: @fwd_decl_default.ifunc = ifunc i32 (), i32 ()* ()* @fwd_decl_default.resolver
-// LINUX: @fwd_decl_avx.ifunc = ifunc i32 (), i32 ()* ()* @fwd_decl_avx.resolver
+// LINUX: @foo.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @foo.resolver
+// LINUX: @foo_inline.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @foo_inline.resolver
+// LINUX: @foo_decls.ifunc = weak_odr ifunc void (), void ()* ()* @foo_decls.resolver
+// LINUX: @foo_multi.ifunc = weak_odr ifunc void (i32, double), void (i32, double)* ()* @foo_multi.resolver
+// LINUX: @fwd_decl_default.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @fwd_decl_default.resolver
+// LINUX: @fwd_decl_avx.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @fwd_decl_avx.resolver
 
 // LINUX: define i32 @foo.sse4.2()
 // LINUX: ret i32 0
@@ -72,14 +72,14 @@ void bar5() {
 // WINDOWS: define dso_local i32 @bar()
 // WINDOWS: call i32 @foo.resolver()
 
-// LINUX: define i32 ()* @foo.resolver() comdat
+// LINUX: define weak_odr i32 ()* @foo.resolver() comdat
 // LINUX: call void @__cpu_indicator_init()
 // LINUX: ret i32 ()* @foo.arch_sandybridge
 // LINUX: ret i32 ()* @foo.arch_ivybridge
 // LINUX: ret i32 ()* @foo.sse4.2
 // LINUX: ret i32 ()* @foo
 
-// WINDOWS: define 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
@@ -92,14 +92,14 @@ void bar5() {
 // WINDOWS: define dso_local i32 @bar2()
 // WINDOWS: call i32 @foo_inline.resolver()
 
-// LINUX: define i32 ()* @foo_inline.resolver() comdat
+// LINUX: define weak_odr i32 ()* @foo_inline.resolver() comdat
 // LINUX: call void @__cpu_indicator_init()
 // LINUX: ret i32 ()* @foo_inline.arch_sandybridge
 // LINUX: ret i32 ()* @foo_inline.arch_ivybridge
 // LINUX: ret i32 ()* @foo_inline.sse4.2
 // LINUX: ret i32 ()* @foo_inline
 
-// WINDOWS: define 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
@@ -112,11 +112,11 @@ void bar5() {
 // WINDOWS: define dso_local void @bar3()
 // WINDOWS: call void @foo_decls.resolver()
 
-// LINUX: define void ()* @foo_decls.resolver() comdat
+// LINUX: define weak_odr void ()* @foo_decls.resolver() comdat
 // LINUX: ret void ()* @foo_decls.sse4.2
 // LINUX: ret void ()* @foo_decls
 
-// WINDOWS: define 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
 
@@ -126,7 +126,7 @@ void bar5() {
 // WINDOWS: define dso_local void @bar4()
 // WINDOWS: call void @foo_multi.resolver(i32 1, double 5.{{[0+e]*}})
 
-// LINUX: define void (i32, double)* @foo_multi.resolver() comdat
+// LINUX: define weak_odr void (i32, double)* @foo_multi.resolver() comdat
 // LINUX: and i32 %{{.*}}, 4352
 // LINUX: icmp eq i32 %{{.*}}, 4352
 // LINUX: ret void (i32, double)* @foo_multi.fma4_sse4.2
@@ -139,7 +139,7 @@ void bar5() {
 // LINUX: ret void (i32, double)* @foo_multi.avx_sse4.2
 // LINUX: ret void (i32, double)* @foo_multi
 
-// WINDOWS: define 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)
@@ -178,18 +178,18 @@ void bar5() {
 // WINDOWS: call i32 @fwd_decl_default.resolver()
 // WINDOWS: call i32 @fwd_decl_avx.resolver()
 
-// LINUX: define i32 ()* @fwd_decl_default.resolver() comdat
+// LINUX: define weak_odr i32 ()* @fwd_decl_default.resolver() comdat
 // LINUX: call void @__cpu_indicator_init()
 // LINUX: ret i32 ()* @fwd_decl_default
-// LINUX: define i32 ()* @fwd_decl_avx.resolver() comdat
+// LINUX: define weak_odr i32 ()* @fwd_decl_avx.resolver() comdat
 // LINUX: call void @__cpu_indicator_init()
 // LINUX: ret i32 ()* @fwd_decl_avx.avx
 // LINUX: ret i32 ()* @fwd_decl_avx
 
-// WINDOWS: define 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 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

Modified: cfe/trunk/test/CodeGenCXX/attr-cpuspecific.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-cpuspecific.cpp?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/attr-cpuspecific.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/attr-cpuspecific.cpp Tue Sep 10 18:54:48 2019
@@ -13,13 +13,15 @@ void foo() {
   s.Func();
 }
 
-// LINUX: define void (%struct.S*)* @_ZN1S4FuncEv.resolver
+// LINUX: @_ZN1S4FuncEv = weak_odr alias void (%struct.S*), void (%struct.S*)* @_ZN1S4FuncEv.ifunc
+// LINUX: @_ZN1S4FuncEv.ifunc = weak_odr ifunc void (%struct.S*), void (%struct.S*)* ()* @_ZN1S4FuncEv.resolver
+// LINUX: define weak_odr void (%struct.S*)* @_ZN1S4FuncEv.resolver
 // LINUX: ret void (%struct.S*)* @_ZN1S4FuncEv.S
 // LINUX: ret void (%struct.S*)* @_ZN1S4FuncEv.O
 // LINUX: declare void @_ZN1S4FuncEv.S
 // LINUX: define linkonce_odr void @_ZN1S4FuncEv.O
 
-// WINDOWS: define dso_local void @"?Func at S@@QEAAXXZ"(%struct.S* %0)
+// WINDOWS: define weak_odr dso_local void @"?Func at S@@QEAAXXZ"(%struct.S* %0) comdat
 // WINDOWS: musttail call void @"?Func at S@@QEAAXXZ.S"(%struct.S* %0)
 // WINDOWS: musttail call void @"?Func at S@@QEAAXXZ.O"(%struct.S* %0)
 // WINDOWS: declare dso_local void @"?Func at S@@QEAAXXZ.S"

Modified: cfe/trunk/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-target-mv-diff-ns.cpp?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/attr-target-mv-diff-ns.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/attr-target-mv-diff-ns.cpp Tue Sep 10 18:54:48 2019
@@ -18,8 +18,8 @@ int bar() {
   return foo(1) + ns::foo(2);
 }
 
-// LINUX: @_Z3fooi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z3fooi.resolver
-// LINUX: @_ZN2ns3fooEi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_ZN2ns3fooEi.resolver
+// LINUX: @_Z3fooi.ifunc = weak_odr ifunc i32 (i32), i32 (i32)* ()* @_Z3fooi.resolver
+// LINUX: @_ZN2ns3fooEi.ifunc = weak_odr ifunc i32 (i32), i32 (i32)* ()* @_ZN2ns3fooEi.resolver
 
 // LINUX: define i32 @_Z3fooi.sse4.2(i32 %0)
 // LINUX: ret i32 0
@@ -57,25 +57,25 @@ int bar() {
 // WINDOWS: call i32 @"?foo@@YAHH at Z.resolver"(i32 1)
 // WINDOWS: call i32 @"?foo at ns@@YAHH at Z.resolver"(i32 2)
 
-// LINUX: define i32 (i32)* @_Z3fooi.resolver() comdat
+// LINUX: define weak_odr i32 (i32)* @_Z3fooi.resolver() comdat
 // LINUX: ret i32 (i32)* @_Z3fooi.arch_sandybridge
 // LINUX: ret i32 (i32)* @_Z3fooi.arch_ivybridge
 // LINUX: ret i32 (i32)* @_Z3fooi.sse4.2
 // LINUX: ret i32 (i32)* @_Z3fooi
 
-// WINDOWS: define 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)
 // WINDOWS: call i32 @"?foo@@YAHH at Z"(i32 %0)
 
-// LINUX: define i32 (i32)* @_ZN2ns3fooEi.resolver() comdat
+// LINUX: define weak_odr i32 (i32)* @_ZN2ns3fooEi.resolver() comdat
 // LINUX: ret i32 (i32)* @_ZN2ns3fooEi.arch_sandybridge
 // LINUX: ret i32 (i32)* @_ZN2ns3fooEi.arch_ivybridge
 // LINUX: ret i32 (i32)* @_ZN2ns3fooEi.sse4.2
 // LINUX: ret i32 (i32)* @_ZN2ns3fooEi
 
-// WINDOWS: define 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)

Modified: cfe/trunk/test/CodeGenCXX/attr-target-mv-inalloca.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-target-mv-inalloca.cpp?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/attr-target-mv-inalloca.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/attr-target-mv-inalloca.cpp Tue Sep 10 18:54:48 2019
@@ -41,7 +41,7 @@ void usage() {
 // WINDOWS: %[[ARGMEM:[0-9a-zA-Z]+]] = alloca inalloca <{ %struct.Foo }>
 // WINDOWS: %[[CALL:[0-9a-zA-Z]+]] = call i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>* inalloca %[[ARGMEM]])
 
-// WINDOWS: define dso_local i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>* %0)
+// WINDOWS: define weak_odr dso_local i32 @"?bar@@YAHUFoo@@@Z.resolver"(<{ %struct.Foo }>* %0)
 // WINDOWS: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(<{ %struct.Foo }>* %0)
 // WINDOWS-NEXT: ret i32 %[[RET]]
 // WINDOWS: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(<{ %struct.Foo }>* %0)
@@ -72,7 +72,7 @@ void usage() {
 // WINDOWS64: %[[ARG:[0-9a-zA-Z.]+]] = alloca %struct.Foo
 // WINDOWS64: %[[CALL:[0-9a-zA-Z]+]] = call i32 @"?bar@@YAHUFoo@@@Z.resolver"(%struct.Foo* %[[ARG]])
 
-// WINDOWS64: define dso_local i32 @"?bar@@YAHUFoo@@@Z.resolver"(%struct.Foo* %0)
+// WINDOWS64: define weak_odr dso_local i32 @"?bar@@YAHUFoo@@@Z.resolver"(%struct.Foo* %0)
 // WINDOWS64: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.arch_ivybridge"(%struct.Foo* %0)
 // WINDOWS64-NEXT: ret i32 %[[RET]]
 // WINDOWS64: %[[RET:[0-9a-zA-Z]+]] = musttail call i32 @"?bar@@YAHUFoo@@@Z.sse4.2"(%struct.Foo* %0)

Modified: cfe/trunk/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-target-mv-member-funcs.cpp?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/attr-target-mv-member-funcs.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/attr-target-mv-member-funcs.cpp Tue Sep 10 18:54:48 2019
@@ -65,13 +65,13 @@ int templ_use() {
   return a.foo(1) + b.foo(2);
 }
 
-// LINUX: @_ZN1SaSERKS_.ifunc = ifunc %struct.S* (%struct.S*, %struct.S*), %struct.S* (%struct.S*, %struct.S*)* ()* @_ZN1SaSERKS_.resolver
-// LINUX: @_ZNK9ConvertTocv1SEv.ifunc = ifunc void (%struct.ConvertTo*), void (%struct.ConvertTo*)* ()* @_ZNK9ConvertTocv1SEv.resolver
-// LINUX: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver
-// LINUX: @_ZN2S23fooEi.ifunc = ifunc i32 (%struct.S2*, i32), i32 (%struct.S2*, i32)* ()* @_ZN2S23fooEi.resolver
+// LINUX: @_ZN1SaSERKS_.ifunc = weak_odr ifunc %struct.S* (%struct.S*, %struct.S*), %struct.S* (%struct.S*, %struct.S*)* ()* @_ZN1SaSERKS_.resolver
+// LINUX: @_ZNK9ConvertTocv1SEv.ifunc = weak_odr ifunc void (%struct.ConvertTo*), void (%struct.ConvertTo*)* ()* @_ZNK9ConvertTocv1SEv.resolver
+// LINUX: @_ZN1S3fooEi.ifunc = weak_odr ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver
+// LINUX: @_ZN2S23fooEi.ifunc = weak_odr ifunc i32 (%struct.S2*, i32), i32 (%struct.S2*, i32)* ()* @_ZN2S23fooEi.resolver
 // Templates:
-// LINUX: @_ZN5templIiE3fooEi.ifunc = ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver
-// LINUX: @_ZN5templIdE3fooEi.ifunc = ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver
+// LINUX: @_ZN5templIiE3fooEi.ifunc = weak_odr ifunc i32 (%struct.templ*, i32), i32 (%struct.templ*, i32)* ()* @_ZN5templIiE3fooEi.resolver
+// LINUX: @_ZN5templIdE3fooEi.ifunc = weak_odr ifunc i32 (%struct.templ.0*, i32), i32 (%struct.templ.0*, i32)* ()* @_ZN5templIdE3fooEi.resolver
 
 // LINUX: define i32 @_Z3barv()
 // LINUX: %s = alloca %struct.S, align 1
@@ -91,29 +91,29 @@ int templ_use() {
 // WINDOWS: call dereferenceable(1) %struct.S* @"??4S@@QEAAAEAU0 at AEBU0@@Z.resolver"(%struct.S* %s2
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.resolver"(%struct.S* %s, i32 0)
 
-// LINUX: define %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() comdat
+// LINUX: define weak_odr %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.resolver() comdat
 // LINUX: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_.arch_ivybridge
 // LINUX: ret %struct.S* (%struct.S*, %struct.S*)* @_ZN1SaSERKS_
 
-// WINDOWS: define dso_local %struct.S* @"??4S@@QEAAAEAU0 at AEBU0@@Z.resolver"(%struct.S* %0, %struct.S* %1)
+// WINDOWS: define weak_odr dso_local %struct.S* @"??4S@@QEAAAEAU0 at AEBU0@@Z.resolver"(%struct.S* %0, %struct.S* %1)
 // WINDOWS: call %struct.S* @"??4S@@QEAAAEAU0 at AEBU0@@Z.arch_ivybridge"
 // WINDOWS: call %struct.S* @"??4S@@QEAAAEAU0 at AEBU0@@Z"
 
-// LINUX: define void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() comdat
+// LINUX: define weak_odr void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.resolver() comdat
 // LINUX: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv.arch_ivybridge
 // LINUX: ret void (%struct.ConvertTo*)* @_ZNK9ConvertTocv1SEv
 
-// WINDOWS: define dso_local void @"??BConvertTo@@QEBA?AUS@@XZ.resolver"(%struct.ConvertTo* %0, %struct.S* %1)
+// WINDOWS: define weak_odr dso_local void @"??BConvertTo@@QEBA?AUS@@XZ.resolver"(%struct.ConvertTo* %0, %struct.S* %1)
 // WINDOWS: call void @"??BConvertTo@@QEBA?AUS@@XZ.arch_ivybridge"
 // WINDOWS: call void @"??BConvertTo@@QEBA?AUS@@XZ"
 
-// LINUX: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat
+// LINUX: define weak_odr i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat
 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge
 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge
 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2
 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi
 
-// WINDOWS: define dso_local i32 @"?foo at S@@QEAAHH at Z.resolver"(%struct.S* %0, i32 %1)
+// WINDOWS: define weak_odr dso_local i32 @"?foo at S@@QEAAHH at Z.resolver"(%struct.S* %0, i32 %1)
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.sse4.2"
@@ -125,13 +125,13 @@ int templ_use() {
 // WINDOWS: define dso_local i32 @"?bar2@@YAHXZ"()
 // WINDOWS: call i32 @"?foo at S2@@QEAAHH at Z.resolver"
 
-// LINUX: define i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() comdat
+// LINUX: define weak_odr i32 (%struct.S2*, i32)* @_ZN2S23fooEi.resolver() comdat
 // LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_sandybridge
 // LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.arch_ivybridge
 // LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi.sse4.2
 // LINUX: ret i32 (%struct.S2*, i32)* @_ZN2S23fooEi
 
-// WINDOWS: define dso_local i32 @"?foo at S2@@QEAAHH at Z.resolver"(%struct.S2* %0, i32 %1)
+// WINDOWS: define weak_odr dso_local i32 @"?foo at S2@@QEAAHH at Z.resolver"(%struct.S2* %0, i32 %1)
 // WINDOWS: call i32 @"?foo at S2@@QEAAHH at Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo at S2@@QEAAHH at Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo at S2@@QEAAHH at Z.sse4.2"
@@ -153,25 +153,25 @@ int templ_use() {
 // WINDOWS: call i32 @"?foo@?$templ at H@@QEAAHH at Z.resolver"
 // WINDOWS: call i32 @"?foo@?$templ at N@@QEAAHH at Z.resolver"
 
-// LINUX: define i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat
+// LINUX: define weak_odr i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.resolver() comdat
 // LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_sandybridge
 // LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.arch_ivybridge
 // LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi.sse4.2
 // LINUX: ret i32 (%struct.templ*, i32)* @_ZN5templIiE3fooEi
 
-// WINDOWS: define dso_local i32 @"?foo@?$templ at H@@QEAAHH at Z.resolver"(%struct.templ* %0, i32 %1)
+// WINDOWS: define weak_odr dso_local i32 @"?foo@?$templ at H@@QEAAHH at Z.resolver"(%struct.templ* %0, i32 %1)
 // WINDOWS: call i32 @"?foo@?$templ at H@@QEAAHH at Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo@?$templ at H@@QEAAHH at Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo@?$templ at H@@QEAAHH at Z.sse4.2"
 // WINDOWS: call i32 @"?foo@?$templ at H@@QEAAHH at Z"
 
-// LINUX: define i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat
+// LINUX: define weak_odr i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.resolver() comdat
 // LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_sandybridge
 // LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.arch_ivybridge
 // LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi.sse4.2
 // LINUX: ret i32 (%struct.templ.0*, i32)* @_ZN5templIdE3fooEi
 
-// WINDOWS: define dso_local i32 @"?foo@?$templ at N@@QEAAHH at Z.resolver"(%struct.templ.0* %0, i32 %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo@?$templ at N@@QEAAHH at Z.resolver"(%struct.templ.0* %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"

Modified: cfe/trunk/test/CodeGenCXX/attr-target-mv-modules.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-target-mv-modules.cpp?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/attr-target-mv-modules.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/attr-target-mv-modules.cpp Tue Sep 10 18:54:48 2019
@@ -22,7 +22,7 @@ __attribute__((target("sse4.2"))) void f
 void g() { f(); }
 
 // Negative tests to validate that the resolver only calls each 1x.
-// CHECK: define void ()* @_Z1fv.resolver
+// CHECK: define weak_odr void ()* @_Z1fv.resolver
 // CHECK: ret void ()* @_Z1fv.sse4.2
 // CHECK-NOT: ret void ()* @_Z1fv.sse4.2
 // CHECK: ret void ()* @_Z1fv

Modified: cfe/trunk/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp Tue Sep 10 18:54:48 2019
@@ -16,7 +16,7 @@ int bar() {
   return s.foo(0);
 }
 
-// LINUX: @_ZN1S3fooEi.ifunc = ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver
+// LINUX: @_ZN1S3fooEi.ifunc = weak_odr ifunc i32 (%struct.S*, i32), i32 (%struct.S*, i32)* ()* @_ZN1S3fooEi.resolver
 
 // LINUX: define i32 @_ZN1S3fooEi(%struct.S* %this, i32 %0)
 // LINUX: ret i32 2
@@ -44,13 +44,13 @@ int bar() {
 // WINDOWS: %s = alloca %struct.S, align 1
 // WINDOWS: %call = call i32 @"?foo at S@@QEAAHH at Z.resolver"(%struct.S* %s, i32 0)
 
-// LINUX: define i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat
+// LINUX: define weak_odr i32 (%struct.S*, i32)* @_ZN1S3fooEi.resolver() comdat
 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_sandybridge
 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.arch_ivybridge
 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi.sse4.2
 // LINUX: ret i32 (%struct.S*, i32)* @_ZN1S3fooEi
 
-// WINDOWS: define dso_local i32 @"?foo at S@@QEAAHH at Z.resolver"(%struct.S* %0, i32 %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo at S@@QEAAHH at Z.resolver"(%struct.S* %0, i32 %1) comdat
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.arch_sandybridge"(%struct.S* %0, i32 %1)
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.arch_ivybridge"(%struct.S* %0, i32 %1)
 // WINDOWS: call i32 @"?foo at S@@QEAAHH at Z.sse4.2"(%struct.S* %0, i32 %1)

Modified: cfe/trunk/test/CodeGenCXX/attr-target-mv-overloads.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/attr-target-mv-overloads.cpp?rev=371586&r1=371585&r2=371586&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/attr-target-mv-overloads.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/attr-target-mv-overloads.cpp Tue Sep 10 18:54:48 2019
@@ -14,8 +14,8 @@ int bar2() {
   return foo_overload() + foo_overload(1);
 }
 
-// LINUX: @_Z12foo_overloadv.ifunc = ifunc i32 (), i32 ()* ()* @_Z12foo_overloadv.resolver
-// LINUX: @_Z12foo_overloadi.ifunc = ifunc i32 (i32), i32 (i32)* ()* @_Z12foo_overloadi.resolver
+// LINUX: @_Z12foo_overloadv.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @_Z12foo_overloadv.resolver
+// LINUX: @_Z12foo_overloadi.ifunc = weak_odr ifunc i32 (i32), i32 (i32)* ()* @_Z12foo_overloadi.resolver
 
 // LINUX: define i32 @_Z12foo_overloadi.sse4.2(i32 %0)
 // LINUX: ret i32 0
@@ -51,25 +51,25 @@ int bar2() {
 // WINDOWS: call i32 @"?foo_overload@@YAHXZ.resolver"()
 // WINDOWS: call i32 @"?foo_overload@@YAHH at Z.resolver"(i32 1)
 
-// LINUX: define i32 ()* @_Z12foo_overloadv.resolver() comdat
+// LINUX: define weak_odr i32 ()* @_Z12foo_overloadv.resolver() comdat
 // LINUX: ret i32 ()* @_Z12foo_overloadv.arch_sandybridge
 // LINUX: ret i32 ()* @_Z12foo_overloadv.arch_ivybridge
 // LINUX: ret i32 ()* @_Z12foo_overloadv.sse4.2
 // LINUX: ret i32 ()* @_Z12foo_overloadv
 
-// WINDOWS: define 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"
 // WINDOWS: call i32 @"?foo_overload@@YAHXZ"
 
-// LINUX: define i32 (i32)* @_Z12foo_overloadi.resolver() comdat
+// LINUX: define weak_odr i32 (i32)* @_Z12foo_overloadi.resolver() comdat
 // LINUX: ret i32 (i32)* @_Z12foo_overloadi.arch_sandybridge
 // LINUX: ret i32 (i32)* @_Z12foo_overloadi.arch_ivybridge
 // LINUX: ret i32 (i32)* @_Z12foo_overloadi.sse4.2
 // LINUX: ret i32 (i32)* @_Z12foo_overloadi
 
-// WINDOWS: define 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"




More information about the cfe-commits mailing list