Make CPUDispatch resolver emit dependent functions.
authorErich Keane <erich.keane@intel.com>
Fri, 7 Dec 2018 15:31:23 +0000 (15:31 +0000)
committerErich Keane <erich.keane@intel.com>
Fri, 7 Dec 2018 15:31:23 +0000 (15:31 +0000)
Inline cpu_specific versions referenced before the cpu_dispatch function
weren't properly emitted, since they hadn't been referred to.  This
patch ensures that during resolver generation that all appropriate
versions are emitted.

Change-Id: I94c3766aaf9c75ca07a0ad8258efdbb834654ff8
llvm-svn: 348600

clang/lib/CodeGen/CodeGenModule.cpp
clang/test/CodeGen/attr-target-mv.c
clang/test/CodeGenCXX/attr-cpuspecific.cpp

index 8130449..b80a43b 100644 (file)
@@ -2585,11 +2585,22 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
 
     llvm::Constant *Func = GetGlobalValue(MangledName);
 
-    if (!Func)
+    if (!Func) {
+      GlobalDecl ExistingDecl = Manglings.lookup(MangledName);
+      if (ExistingDecl.getDecl() &&
+          ExistingDecl.getDecl()->getAsFunction()->isDefined()) {
+        EmitGlobalFunctionDefinition(ExistingDecl, nullptr);
+        Func = GetGlobalValue(MangledName);
+      } else {
+        if (!ExistingDecl.getDecl())
+          ExistingDecl = GD.getWithMultiVersionIndex(Index);
+
       Func = GetOrCreateLLVMFunction(
-          MangledName, DeclTy, GD.getWithMultiVersionIndex(Index),
+          MangledName, DeclTy, ExistingDecl,
           /*ForVTable=*/false, /*DontDefer=*/true,
           /*IsThunk=*/false, llvm::AttributeList(), ForDefinition);
+      }
+    }
 
     llvm::SmallVector<StringRef, 32> Features;
     Target.getCPUSpecificCPUDispatchFeatures(II->getName(), Features);
index 372b140..363dea6 100644 (file)
@@ -223,10 +223,12 @@ void bar5() {
 // WINDOWS: define linkonce_odr dso_local void @foo_decls()
 // WINDOWS: define linkonce_odr dso_local void @foo_decls.sse4.2()
 
+// LINUX: define linkonce void @foo_multi(i32 %{{[^,]+}}, double %{{[^\)]+}})
 // LINUX: define linkonce void @foo_multi.avx_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
 // LINUX: define linkonce void @foo_multi.fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
 // LINUX: define linkonce void @foo_multi.arch_ivybridge_fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
 
+// WINDOWS: define linkonce_odr dso_local void @foo_multi(i32 %{{[^,]+}}, double %{{[^\)]+}})
 // WINDOWS: define linkonce_odr dso_local void @foo_multi.avx_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
 // WINDOWS: define linkonce_odr dso_local void @foo_multi.fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
 // WINDOWS: define linkonce_odr dso_local void @foo_multi.arch_ivybridge_fma4_sse4.2(i32 %{{[^,]+}}, double %{{[^\)]+}})
index 57b45e1..bfee49c 100644 (file)
@@ -16,8 +16,11 @@ void foo() {
 // LINUX: define 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*)
 // 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"
+// WINDOWS: define linkonce_odr dso_local void @"?Func@S@@QEAAXXZ.O"