[clang] e3b1052 - Make multiversioning work with internal linkage

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 17 05:56:46 PDT 2021


Author: Erich Keane
Date: 2021-09-17T05:56:38-07:00
New Revision: e3b10525b489b604d6a1e540be78bda80afb5868

URL: https://github.com/llvm/llvm-project/commit/e3b10525b489b604d6a1e540be78bda80afb5868
DIFF: https://github.com/llvm/llvm-project/commit/e3b10525b489b604d6a1e540be78bda80afb5868.diff

LOG: Make multiversioning work with internal linkage

We previously made all multiversioning resolvers/ifuncs have weak
ODR linkage in IR, since we NEED to emit the whole resolver every time
we see a call, but it is not necessarily the place where all the
definitions live.

HOWEVER, when doing so, we neglected the case where the versions have
internal linkage.  This patch ensures we do this, so you don't get weird
behavior with static functions.

Added: 
    clang/test/CodeGenCXX/multi-versioning-internal-linkage.cpp

Modified: 
    clang/lib/CodeGen/CodeGenModule.cpp
    clang/test/CodeGen/unique-internal-linkage-names.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index b274edb8470c..9715657b4c6e 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -3258,6 +3258,19 @@ TargetMVPriority(const TargetInfo &TI,
   return Priority;
 }
 
+// Multiversion functions should be at most 'WeakODRLinkage' so that a 
diff erent
+// TU can forward declare the function without causing problems.  Particularly
+// in the cases of CPUDispatch, this causes issues. This also makes sure we
+// work with internal linkage functions, so that the same function name can be
+// used with internal linkage in multiple TUs.
+llvm::GlobalValue::LinkageTypes getMultiversionLinkage(CodeGenModule &CGM,
+                                                       GlobalDecl GD) {
+  const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
+  if (FD->getFormalLinkage() == InternalLinkage)
+    return llvm::GlobalValue::InternalLinkage;
+  return llvm::GlobalValue::WeakODRLinkage;
+}
+
 void CodeGenModule::emitMultiVersionFunctions() {
   std::vector<GlobalDecl> MVFuncsToEmit;
   MultiVersionFuncs.swap(MVFuncsToEmit);
@@ -3298,7 +3311,7 @@ void CodeGenModule::emitMultiVersionFunctions() {
     if (TI.supportsIFunc() || FD->isTargetMultiVersion()) {
       ResolverFunc = cast<llvm::Function>(
           GetGlobalValue((getMangledName(GD) + ".resolver").str()));
-      ResolverFunc->setLinkage(llvm::Function::WeakODRLinkage);
+      ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD));
     } else {
       ResolverFunc = cast<llvm::Function>(GetGlobalValue(getMangledName(GD)));
     }
@@ -3356,7 +3369,7 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
 
   auto *ResolverFunc = cast<llvm::Function>(GetOrCreateLLVMFunction(
       ResolverName, ResolverType, ResolverGD, /*ForVTable=*/false));
-  ResolverFunc->setLinkage(llvm::Function::WeakODRLinkage);
+  ResolverFunc->setLinkage(getMultiversionLinkage(*this, GD));
   if (supportsCOMDAT())
     ResolverFunc->setComdat(
         getModule().getOrInsertComdat(ResolverFunc->getName()));
@@ -3433,9 +3446,9 @@ void CodeGenModule::emitCPUDispatchDefinition(GlobalDecl GD) {
       auto *IFunc = cast<llvm::GlobalIFunc>(GetOrCreateLLVMFunction(
           AliasName, DeclTy, GD, /*ForVTable=*/false, /*DontDefer=*/true,
           /*IsThunk=*/false, llvm::AttributeList(), NotForDefinition));
-      auto *GA = llvm::GlobalAlias::create(
-         DeclTy, 0, getFunctionLinkage(GD), AliasName, IFunc, &getModule());
-      GA->setLinkage(llvm::Function::WeakODRLinkage);
+      auto *GA = llvm::GlobalAlias::create(DeclTy, 0,
+                                           getMultiversionLinkage(*this, GD),
+                                           AliasName, IFunc, &getModule());
       SetCommonAttributes(GD, GA);
     }
   }
@@ -3474,8 +3487,9 @@ llvm::Constant *CodeGenModule::GetOrCreateMultiVersionResolver(
     llvm::Constant *Resolver = GetOrCreateLLVMFunction(
         MangledName + ".resolver", ResolverType, GlobalDecl{},
         /*ForVTable=*/false);
-    llvm::GlobalIFunc *GIF = llvm::GlobalIFunc::create(
-        DeclTy, 0, llvm::Function::WeakODRLinkage, "", Resolver, &getModule());
+    llvm::GlobalIFunc *GIF =
+        llvm::GlobalIFunc::create(DeclTy, 0, getMultiversionLinkage(*this, GD),
+                                  "", Resolver, &getModule());
     GIF->setName(ResolverName);
     SetCommonAttributes(FD, GIF);
 

diff  --git a/clang/test/CodeGen/unique-internal-linkage-names.cpp b/clang/test/CodeGen/unique-internal-linkage-names.cpp
index 95591de308d3..65069c049b63 100644
--- a/clang/test/CodeGen/unique-internal-linkage-names.cpp
+++ b/clang/test/CodeGen/unique-internal-linkage-names.cpp
@@ -59,7 +59,7 @@ void test() {
 // PLAIN: @_ZN12_GLOBAL__N_16anon_mE = internal global
 // PLAIN: define internal i32 @_ZL3foov()
 // PLAIN: define internal i32 @_ZN12_GLOBAL__N_14getMEv
-// PLAIN: define weak_odr i32 ()* @_ZL4mverv.resolver()
+// PLAIN: define internal i32 ()* @_ZL4mverv.resolver()
 // PLAIN: define internal void @_ZN12_GLOBAL__N_11AC1Ev
 // PLAIN: define internal void @_ZN12_GLOBAL__N_11AD1Ev
 // PLAIN: define internal i32 @_ZL4mverv()
@@ -70,7 +70,7 @@ void test() {
 // UNIQUE: @_ZN12_GLOBAL__N_16anon_mE = internal global
 // UNIQUE: define internal i32 @_ZL3foov.[[MODHASH:__uniq.[0-9]+]]() #[[#ATTR:]] {
 // UNIQUE: define internal i32 @_ZN12_GLOBAL__N_14getMEv.[[MODHASH]]
-// UNIQUE: define weak_odr i32 ()* @_ZL4mverv.[[MODHASH]].resolver()
+// UNIQUE: define internal i32 ()* @_ZL4mverv.[[MODHASH]].resolver()
 // UNIQUE: define internal void @_ZN12_GLOBAL__N_11AC1Ev.__uniq.68358509610070717889884130747296293671
 // UNIQUE: define internal void @_ZN12_GLOBAL__N_11AD1Ev.__uniq.68358509610070717889884130747296293671
 // UNIQUE: define internal i32 @_ZL4mverv.[[MODHASH]]()

diff  --git a/clang/test/CodeGenCXX/multi-versioning-internal-linkage.cpp b/clang/test/CodeGenCXX/multi-versioning-internal-linkage.cpp
new file mode 100644
index 000000000000..246599a591a7
--- /dev/null
+++ b/clang/test/CodeGenCXX/multi-versioning-internal-linkage.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefix=LINUX
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-windows-pc -emit-llvm %s -o - | FileCheck %s --check-prefix=WINDOWS
+
+__attribute__((target("default"))) static int static_target() {
+  return 0;
+}
+__attribute__((target("arch=sandybridge"))) static int static_target() {
+  return 1;
+}
+
+__attribute__((cpu_dispatch(atom, generic))) static int static_dispatch() {}
+
+namespace {
+int __attribute__((target("default"))) anon_target() {
+  return 0;
+}
+int __attribute__((target("arch=sandybridge"))) anon_target() {
+  return 1;
+}
+__attribute__((cpu_dispatch(atom, generic))) static int anon_dispatch() {}
+}
+
+
+
+int usage() {
+  return static_target() + anon_target() + static_dispatch() + anon_dispatch();
+}
+
+// Ensure that these are all 'internal'. Windows doesn't have ifuncs or aliases,
+// since Windows doesn't support ifuncs.
+// aliases:
+// LINUX: @_ZL15static_dispatchv = internal alias i32 (), i32 ()* @_ZL15static_dispatchv.ifunc
+// LINUX: @_ZN12_GLOBAL__N_113anon_dispatchEv = internal alias i32 (), i32 ()* @_ZN12_GLOBAL__N_113anon_dispatchEv.ifunc
+
+// ifuncs:
+// LINUX: @_ZL15static_dispatchv.ifunc = internal ifunc i32 (), i32 ()* ()* @_ZL15static_dispatchv.resolver
+// LINUX: @_ZN12_GLOBAL__N_113anon_dispatchEv.ifunc = internal ifunc i32 (), i32 ()* ()* @_ZN12_GLOBAL__N_113anon_dispatchEv.resolver
+// LINUX: @_ZL13static_targetv.ifunc = internal ifunc i32 (), i32 ()* ()* @_ZL13static_targetv.resolver
+// LINUX: @_ZN12_GLOBAL__N_111anon_targetEv.ifunc = internal ifunc i32 (), i32 ()* ()* @_ZN12_GLOBAL__N_111anon_targetEv.resolver
+
+// resolvers:
+// LINUX: define internal i32 ()* @_ZL15static_dispatchv.resolver()
+// WINDOWS: define internal i32 @"?static_dispatch@@YAHXZ"()
+// LINUX: define internal i32 ()* @_ZN12_GLOBAL__N_113anon_dispatchEv.resolver()
+// WINDOWS: define internal i32 @"?anon_dispatch@?A0x7F72A7FB@@YAHXZ"()
+// LINUX: define internal i32 ()* @_ZL13static_targetv.resolver()
+// WINDOWS: define internal i32 @"?static_target@@YAHXZ.resolver"()
+// LINUX: define internal i32 ()* @_ZN12_GLOBAL__N_111anon_targetEv.resolver()
+// WINDOWS: define internal i32 @"?anon_target@?A0x7F72A7FB@@YAHXZ.resolver"()


        


More information about the cfe-commits mailing list