Skip to content

Commit

Permalink
[CPU-Dispatch] Make sure Dispatch names get updated if previously man…
Browse files Browse the repository at this point in the history
…gled

Cases where there is a mangling of a cpu-dispatch/cpu-specific function
before the function becomes 'multiversion' (such as a member function)
causes the wrong name to be emitted for one of the variants/resolver,
since the name is cached.  Make sure we invalidate the cache in
cpu-dispatch/cpu-specific modes, like we previously did for just target
multiversioning.
  • Loading branch information
Erich Keane committed Jan 14, 2022
1 parent bdd5b94 commit 2bcba21
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 7 deletions.
15 changes: 9 additions & 6 deletions clang/lib/CodeGen/CodeGenModule.cpp
Expand Up @@ -1368,7 +1368,8 @@ static std::string getMangledNameImpl(CodeGenModule &CGM, GlobalDecl GD,
}

void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD,
const FunctionDecl *FD) {
const FunctionDecl *FD,
StringRef &CurName) {
if (!FD->isMultiVersion())
return;

Expand Down Expand Up @@ -1400,7 +1401,11 @@ void CodeGenModule::UpdateMultiVersionNames(GlobalDecl GD,
if (ExistingRecord != std::end(Manglings))
Manglings.remove(&(*ExistingRecord));
auto Result = Manglings.insert(std::make_pair(OtherName, OtherGD));
MangledDeclNames[OtherGD.getCanonicalDecl()] = Result.first->first();
StringRef OtherNameRef = MangledDeclNames[OtherGD.getCanonicalDecl()] =
Result.first->first();
// If this is the current decl is being created, make sure we update the name.
if (GD.getCanonicalDecl() == OtherGD.getCanonicalDecl())
CurName = OtherNameRef;
if (llvm::GlobalValue *Entry = GetGlobalValue(NonTargetName))
Entry->setName(OtherName);
}
Expand Down Expand Up @@ -3490,6 +3495,7 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
}

StringRef ResolverName = getMangledName(GD);
UpdateMultiVersionNames(GD, FD, ResolverName);

llvm::Type *ResolverType;
GlobalDecl ResolverGD;
Expand All @@ -3498,8 +3504,6 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
llvm::PointerType::get(DeclTy,
Context.getTargetAddressSpace(FD->getType())),
false);
assert(ResolverName.endswith(".resolver") &&
"CPUDispatch IFunc resolver doesn't end with .resolver??");
}
else {
ResolverType = DeclTy;
Expand Down Expand Up @@ -3692,8 +3696,7 @@ llvm::Constant *CodeGenModule::GetOrCreateLLVMFunction(
}

if (FD->isMultiVersion()) {
if (FD->hasAttr<TargetAttr>())
UpdateMultiVersionNames(GD, FD);
UpdateMultiVersionNames(GD, FD, MangledName);
if (!IsForDefinition)
return GetOrCreateMultiVersionResolver(GD, Ty, FD);
}
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/CodeGen/CodeGenModule.h
Expand Up @@ -1468,7 +1468,8 @@ class CodeGenModule : public CodeGenTypeCache {
llvm::Constant *GetOrCreateMultiVersionResolver(GlobalDecl GD,
llvm::Type *DeclTy,
const FunctionDecl *FD);
void UpdateMultiVersionNames(GlobalDecl GD, const FunctionDecl *FD);
void UpdateMultiVersionNames(GlobalDecl GD, const FunctionDecl *FD,
StringRef &CurName);

llvm::Constant *
GetOrCreateLLVMGlobal(StringRef MangledName, llvm::Type *Ty, LangAS AddrSpace,
Expand Down
43 changes: 43 additions & 0 deletions clang/test/CodeGen/attr-cpuspecific-renaming.cpp
@@ -0,0 +1,43 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb %s | FileCheck %s --check-prefixes=CHECK,LIN
// RUN: %clang_cc1 -triple x86_64-windows-pc -emit-llvm -o - -debug-info-kind=constructor -dwarf-version=4 -debugger-tuning=gdb %s | FileCheck %s --check-prefixes=CHECK,WIN

// LIN: @[[S1_NAME:.+]].ifunc = weak_odr ifunc void (%struct.S1*), void (%struct.S1*)* ()* @[[S1_NAME]].resolver
// LIN: @[[S2_NAME:.+]].ifunc = weak_odr ifunc void (%struct.S2*), void (%struct.S2*)* ()* @[[S2_NAME]].resolver
// WIN: $"[[S1_NAME:.+]]" = comdat any
// WIN: $"[[S2_NAME:.+]]" = comdat any

struct S1 {
void foo();
void mv();
};

void S1::foo(){}

__attribute__((cpu_dispatch(ivybridge, generic)))
void S1::mv() {}
// LIN: define weak_odr void (%struct.S1*)* @[[S1_NAME]].resolver
// WIN: define weak_odr dso_local void @"[[S1_NAME]]"(%struct.S1*
__attribute__((cpu_specific(generic)))
void S1::mv() {}
// CHECK: define dso_local {{.*}}void @{{\"?}}[[S1_NAME]].S{{\"?}}
// CHECK: define dso_local {{.*}}void @{{\"?}}[[S1_NAME]].A{{\"?}}
__attribute__((cpu_specific(ivybridge)))
void S1::mv() {}

struct S2 {
void foo();
void mv();
};

void S2::foo(){}

__attribute__((cpu_specific(generic)))
void S2::mv() {}
// CHECK: define dso_local {{.*}}void @{{\"?}}[[S2_NAME]].A{{\"?}}
__attribute__((cpu_dispatch(ivybridge, generic)))
void S2::mv() {}
// LIN: define weak_odr void (%struct.S2*)* @[[S2_NAME]].resolver
// WIN: define weak_odr dso_local void @"[[S2_NAME]]"(%struct.S2*
__attribute__((cpu_specific(ivybridge)))
void S2::mv() {}
// CHECK: define dso_local {{.*}}void @{{\"?}}[[S2_NAME]].S{{\"?}}

0 comments on commit 2bcba21

Please sign in to comment.