}
void CodeGenModule::emitMultiVersionFunctions() {
- for (GlobalDecl GD : MultiVersionFuncs) {
+ std::vector<GlobalDecl> MVFuncsToEmit;
+ MultiVersionFuncs.swap(MVFuncsToEmit);
+ for (GlobalDecl GD : MVFuncsToEmit) {
SmallVector<CodeGenFunction::MultiVersionResolverOption, 10> Options;
const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
getContext().forEachMultiversionedFunctionVersion(
CodeGenFunction CGF(*this);
CGF.EmitMultiVersionResolver(ResolverFunc, Options);
}
+
+ // Ensure that any additions to the deferred decls list caused by emitting a
+ // variant are emitted. This can happen when the variant itself is inline and
+ // calls a function without linkage.
+ if (!MVFuncsToEmit.empty())
+ EmitDeferred();
+
+ // Ensure that any additions to the multiversion funcs list from either the
+ // deferred decls or the multiversion functions themselves are emitted.
+ if (!MultiVersionFuncs.empty())
+ emitMultiVersionFunctions();
}
void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
__attribute__((target("default"))) inline void foo_used2(int i, double d) {}
__attribute__((target("avx,sse4.2"), used)) inline void foo_used2(int i, double d) {}
+// PR50025:
+static void must_be_emitted(void) {}
+inline __attribute__((target("default"))) void pr50025(void) { must_be_emitted(); }
+void calls_pr50025() { pr50025(); }
+
+// Also need to make sure we get other multiversion functions.
+inline __attribute__((target("default"))) void pr50025b(void) { must_be_emitted(); }
+inline __attribute__((target("default"))) void pr50025c(void) { pr50025b(); }
+void calls_pr50025c() { pr50025c(); }
+
// LINUX: @llvm.compiler.used = appending global [2 x i8*] [i8* bitcast (void (i32, double)* @foo_used to i8*), i8* bitcast (void (i32, double)* @foo_used2.avx_sse4.2 to i8*)], section "llvm.metadata"
// WINDOWS: @llvm.used = appending global [2 x i8*] [i8* bitcast (void (i32, double)* @foo_used to i8*), i8* bitcast (void (i32, double)* @foo_used2.avx_sse4.2 to i8*)], section "llvm.metadata"
// 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 %{{[^\)]+}})
+
+// Ensure that we emit the 'static' function here.
+// LINUX: define linkonce void @pr50025()
+// LINUX: call void @must_be_emitted
+// LINUX: define internal void @must_be_emitted()
+// WINDOWS: define linkonce_odr dso_local void @pr50025()
+// WINDOWS: call void @must_be_emitted
+// WINDOWS: define internal void @must_be_emitted()
+
+// LINUX: define linkonce void @pr50025c()
+// LINUX: define linkonce void @pr50025b()
+// WINDOWS: define linkonce_odr dso_local void @pr50025c()
+// WINDOWS: define linkonce_odr dso_local void @pr50025b()