forked from OSchip/llvm-project
Ensure target-multiversioning emits deferred declarations
As reported in PR50025, sometimes we would end up not emitting functions needed by inline multiversioned variants. This is because we typically use the 'deferred decl' mechanism to emit these. However, the variants are emitted after that typically happens. This fixes that by ensuring we re-run deferred decls after this happens. Also, the multiversion emission is done recursively to ensure that MV functions that require other MV functions to be emitted get emitted.
This commit is contained in:
parent
83a25a1010
commit
0ed613612c
|
@ -3189,7 +3189,9 @@ TargetMVPriority(const TargetInfo &TI,
|
|||
}
|
||||
|
||||
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(
|
||||
|
@ -3243,6 +3245,17 @@ void CodeGenModule::emitMultiVersionFunctions() {
|
|||
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) {
|
||||
|
|
|
@ -66,6 +66,16 @@ __attribute__((target("avx,sse4.2"))) inline void foo_used(int i, double d) {}
|
|||
__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"
|
||||
|
||||
|
@ -300,3 +310,16 @@ __attribute__((target("avx,sse4.2"), used)) inline void foo_used2(int i, 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 %{{[^\)]+}})
|
||||
|
||||
// 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()
|
||||
|
|
Loading…
Reference in New Issue