diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 1ff95edbbd819..716c43431667c 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -4562,6 +4562,9 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { ResolverName += ".resolver"; } + bool ShouldReturnIFunc = + getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion(); + // If the resolver has already been created, just return it. This lookup may // yield a function declaration instead of a resolver on AArch64. That is // because we didn't know whether a resolver will be generated when we first @@ -4569,8 +4572,7 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { // targets which support ifuncs should not return here unless we actually // found an ifunc. llvm::GlobalValue *ResolverGV = GetGlobalValue(ResolverName); - if (ResolverGV && - (isa(ResolverGV) || !getTarget().supportsIFunc())) + if (ResolverGV && (isa(ResolverGV) || !ShouldReturnIFunc)) return ResolverGV; const CGFunctionInfo &FI = getTypes().arrangeGlobalDeclaration(GD); @@ -4583,7 +4585,7 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { // For cpu_specific, don't create an ifunc yet because we don't know if the // cpu_dispatch will be emitted in this translation unit. - if (getTarget().supportsIFunc() && !FD->isCPUSpecificMultiVersion()) { + if (ShouldReturnIFunc) { unsigned AS = getTypes().getTargetAddressSpace(FD->getType()); llvm::Type *ResolverType = llvm::FunctionType::get(llvm::PointerType::get(DeclTy, AS), false); @@ -4602,11 +4604,9 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(GlobalDecl GD) { llvm::Constant *Resolver = GetOrCreateLLVMFunction( ResolverName, DeclTy, GlobalDecl{}, /*ForVTable=*/false); - assert(isa(Resolver) && + assert(isa(Resolver) && !ResolverGV && "Resolver should be created for the first time"); SetCommonAttributes(FD, cast(Resolver)); - if (ResolverGV) - replaceDeclarationWith(ResolverGV, Resolver); return Resolver; } diff --git a/clang/test/CodeGen/attr-cpuspecific.c b/clang/test/CodeGen/attr-cpuspecific.c index 628892d5809b4..6eb2fb2758738 100644 --- a/clang/test/CodeGen/attr-cpuspecific.c +++ b/clang/test/CodeGen/attr-cpuspecific.c @@ -154,6 +154,12 @@ void usages(void) { CpuSpecificNoDispatch(); // LINUX: @CpuSpecificNoDispatch.ifunc() // WINDOWS: @CpuSpecificNoDispatch() + // + // Adding another use of CpuSpecificNoDispatch reproduces the + // crash in https://github.com/llvm/llvm-project/issues/115299 + CpuSpecificNoDispatch(); + // LINUX: @CpuSpecificNoDispatch.ifunc() + // WINDOWS: @CpuSpecificNoDispatch() OrderDispatchUsageSpecific(); // LINUX: @OrderDispatchUsageSpecific.ifunc() // WINDOWS: @OrderDispatchUsageSpecific()