zsrkmyn updated this revision to Diff 219568.

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D67058/new/

https://reviews.llvm.org/D67058

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

Index: clang/test/CodeGenCXX/attr-target-mv-overloads.cpp
===================================================================
--- clang/test/CodeGenCXX/attr-target-mv-overloads.cpp
+++ clang/test/CodeGenCXX/attr-target-mv-overloads.cpp
@@ -14,8 +14,8 @@
   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 @@
 // WINDOWS: call i32 @"?foo_overload@@YAHXZ.resolver"()
 // WINDOWS: call i32 @"?foo_overload@@YAHH@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@Z.resolver"(i32 %0) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo_overload@@YAHH@Z.resolver"(i32 %0) comdat
 // WINDOWS: call i32 @"?foo_overload@@YAHH@Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo_overload@@YAHH@Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo_overload@@YAHH@Z.sse4.2"
Index: clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
===================================================================
--- clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
+++ clang/test/CodeGenCXX/attr-target-mv-out-of-line-defs.cpp
@@ -16,7 +16,7 @@
   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 @@
 // WINDOWS: %s = alloca %struct.S, align 1
 // WINDOWS: %call = call i32 @"?foo@S@@QEAAHH@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@S@@QEAAHH@Z.resolver"(%struct.S* %0, i32 %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S* %0, i32 %1) comdat
 // WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge"(%struct.S* %0, i32 %1)
 // WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge"(%struct.S* %0, i32 %1)
 // WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.sse4.2"(%struct.S* %0, i32 %1)
Index: clang/test/CodeGenCXX/attr-target-mv-modules.cpp
===================================================================
--- clang/test/CodeGenCXX/attr-target-mv-modules.cpp
+++ clang/test/CodeGenCXX/attr-target-mv-modules.cpp
@@ -22,7 +22,7 @@
 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
Index: clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
===================================================================
--- clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
+++ clang/test/CodeGenCXX/attr-target-mv-member-funcs.cpp
@@ -65,13 +65,13 @@
   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 @@
 // WINDOWS: call dereferenceable(1) %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.resolver"(%struct.S* %s2
 // WINDOWS: call i32 @"?foo@S@@QEAAHH@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@AEBU0@@Z.resolver"(%struct.S* %0, %struct.S* %1)
+// WINDOWS: define weak_odr dso_local %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.resolver"(%struct.S* %0, %struct.S* %1)
 // WINDOWS: call %struct.S* @"??4S@@QEAAAEAU0@AEBU0@@Z.arch_ivybridge"
 // WINDOWS: call %struct.S* @"??4S@@QEAAAEAU0@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@S@@QEAAHH@Z.resolver"(%struct.S* %0, i32 %1)
+// WINDOWS: define weak_odr dso_local i32 @"?foo@S@@QEAAHH@Z.resolver"(%struct.S* %0, i32 %1)
 // WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo@S@@QEAAHH@Z.sse4.2"
@@ -125,13 +125,13 @@
 // WINDOWS: define dso_local i32 @"?bar2@@YAHXZ"()
 // WINDOWS: call i32 @"?foo@S2@@QEAAHH@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@S2@@QEAAHH@Z.resolver"(%struct.S2* %0, i32 %1)
+// WINDOWS: define weak_odr dso_local i32 @"?foo@S2@@QEAAHH@Z.resolver"(%struct.S2* %0, i32 %1)
 // WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo@S2@@QEAAHH@Z.sse4.2"
@@ -153,25 +153,25 @@
 // WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.resolver"
 // WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@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@H@@QEAAHH@Z.resolver"(%struct.templ* %0, i32 %1)
+// WINDOWS: define weak_odr dso_local i32 @"?foo@?$templ@H@@QEAAHH@Z.resolver"(%struct.templ* %0, i32 %1)
 // WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@Z.sse4.2"
 // WINDOWS: call i32 @"?foo@?$templ@H@@QEAAHH@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@N@@QEAAHH@Z.resolver"(%struct.templ.0* %0, i32 %1) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo@?$templ@N@@QEAAHH@Z.resolver"(%struct.templ.0* %0, i32 %1) comdat
 // WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_sandybridge"
 // WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.arch_ivybridge"
 // WINDOWS: call i32 @"?foo@?$templ@N@@QEAAHH@Z.sse4.2"
Index: clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp
===================================================================
--- clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp
+++ clang/test/CodeGenCXX/attr-target-mv-inalloca.cpp
@@ -41,7 +41,7 @@
 // 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 @@
 // 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)
Index: clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
===================================================================
--- clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
+++ clang/test/CodeGenCXX/attr-target-mv-diff-ns.cpp
@@ -18,8 +18,8 @@
   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 @@
 // WINDOWS: call i32 @"?foo@@YAHH@Z.resolver"(i32 1)
 // WINDOWS: call i32 @"?foo@ns@@YAHH@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@Z.resolver"(i32 %0) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo@@YAHH@Z.resolver"(i32 %0) comdat
 // WINDOWS: call i32 @"?foo@@YAHH@Z.arch_sandybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo@@YAHH@Z.arch_ivybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo@@YAHH@Z.sse4.2"(i32 %0)
 // WINDOWS: call i32 @"?foo@@YAHH@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@ns@@YAHH@Z.resolver"(i32 %0) comdat
+// WINDOWS: define weak_odr dso_local i32 @"?foo@ns@@YAHH@Z.resolver"(i32 %0) comdat
 // WINDOWS: call i32 @"?foo@ns@@YAHH@Z.arch_sandybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo@ns@@YAHH@Z.arch_ivybridge"(i32 %0)
 // WINDOWS: call i32 @"?foo@ns@@YAHH@Z.sse4.2"(i32 %0)
Index: clang/test/CodeGenCXX/attr-cpuspecific.cpp
===================================================================
--- clang/test/CodeGenCXX/attr-cpuspecific.cpp
+++ clang/test/CodeGenCXX/attr-cpuspecific.cpp
@@ -13,13 +13,15 @@
   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@S@@QEAAXXZ"(%struct.S* %0)
+// WINDOWS: define weak_odr dso_local void @"?Func@S@@QEAAXXZ"(%struct.S* %0) comdat
 // WINDOWS: musttail call void @"?Func@S@@QEAAXXZ.S"(%struct.S* %0)
 // WINDOWS: musttail call void @"?Func@S@@QEAAXXZ.O"(%struct.S* %0)
 // WINDOWS: declare dso_local void @"?Func@S@@QEAAXXZ.S"
Index: clang/test/CodeGen/attr-target-mv.c
===================================================================
--- clang/test/CodeGen/attr-target-mv.c
+++ clang/test/CodeGen/attr-target-mv.c
@@ -47,12 +47,12 @@
   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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 // 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
Index: clang/test/CodeGen/attr-target-mv-va-args.c
===================================================================
--- clang/test/CodeGen/attr-target-mv-va-args.c
+++ clang/test/CodeGen/attr-target-mv-va-args.c
@@ -9,7 +9,7 @@
   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 @@
 // 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 @@
 // 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
Index: clang/test/CodeGen/attr-target-mv-func-ptrs.c
===================================================================
--- clang/test/CodeGen/attr-target-mv-func-ptrs.c
+++ clang/test/CodeGen/attr-target-mv-func-ptrs.c
@@ -17,7 +17,7 @@
   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(
Index: clang/test/CodeGen/attr-cpuspecific.c
===================================================================
--- clang/test/CodeGen/attr-cpuspecific.c
+++ clang/test/CodeGen/attr-cpuspecific.c
@@ -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 @@
 
 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 @@
 // 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 @@
 
 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 @@
 // 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 @@
 // 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 @@
 // 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 @@
 
 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 @@
 // 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 @@
 
 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 @@
 // 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 @@
 
 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 @@
 // 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 @@
 
 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 @@
 
 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()
Index: clang/lib/CodeGen/CodeGenModule.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -2836,10 +2836,11 @@
     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())
@@ -2884,6 +2885,10 @@
 
   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 +2953,21 @@
 
   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 +3004,7 @@
         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);
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to