[clang] cc8390b - Permit attribute 'used' with 'target' multiversioning.

Erich Keane via cfe-commits cfe-commits at lists.llvm.org
Mon Mar 9 12:38:19 PDT 2020


Author: Erich Keane
Date: 2020-03-09T12:38:03-07:00
New Revision: cc8390bfe30d08633d62a1b53e6669e386c95600

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

LOG: Permit attribute 'used' with 'target' multiversioning.

This adds infrastructure for a multiversioning whitelist, plus adds
'used' to the allowed list with 'target'.  The behavior here mirrors the
implementation in GCC, where 'used' only applies to the single
declaration and doesn't apply to the ifunc or resolver.

This is not being applied to cpu_dispatch and cpu_specific, since the
rules are more complicated for cpu_specific, which emits multiple
symbols. Additionally, the author isn't currently aware of uses in the
wild of this combination, but is aware of a number of target+used
combinations.

Added: 
    

Modified: 
    clang/lib/Sema/SemaDecl.cpp
    clang/test/CodeGen/attr-target-mv.c
    clang/test/Sema/attr-target-mv.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 66359f4faf6a..da40ac188e54 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -9952,6 +9952,18 @@ static bool CheckMultiVersionValue(Sema &S, const FunctionDecl *FD) {
   return false;
 }
 
+// Provide a white-list of attributes that are allowed to be combined with
+// multiversion functions.
+static bool AttrCompatibleWithMultiVersion(attr::Kind Kind,
+                                           MultiVersionKind MVType) {
+  switch (Kind) {
+  default:
+    return false;
+  case attr::Used:
+    return MVType == MultiVersionKind::Target;
+  }
+}
+
 static bool HasNonMultiVersionAttributes(const FunctionDecl *FD,
                                          MultiVersionKind MVType) {
   for (const Attr *A : FD->attrs()) {
@@ -9967,7 +9979,9 @@ static bool HasNonMultiVersionAttributes(const FunctionDecl *FD,
         return true;
       break;
     default:
-      return true;
+      if (!AttrCompatibleWithMultiVersion(A->getKind(), MVType))
+        return true;
+      break;
     }
   }
   return false;

diff  --git a/clang/test/CodeGen/attr-target-mv.c b/clang/test/CodeGen/attr-target-mv.c
index c089b06d238c..b273eb846e1d 100644
--- a/clang/test/CodeGen/attr-target-mv.c
+++ b/clang/test/CodeGen/attr-target-mv.c
@@ -50,6 +50,15 @@ void bar5() {
 int __attribute__((target("avx"))) changed_to_mv(void) { return 0;}
 int __attribute__((target("fma4"))) changed_to_mv(void) { return 1;}
 
+__attribute__((target("default"), used)) inline void foo_used(int i, double d) {}
+__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) {}
+
+// LINUX: @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: @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"
+
 // LINUX: @foo.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @foo.resolver
 // LINUX: @foo_inline.ifunc = weak_odr ifunc i32 (), i32 ()* ()* @foo_inline.resolver
 // LINUX: @foo_decls.ifunc = weak_odr ifunc void (), void ()* ()* @foo_decls.resolver
@@ -203,6 +212,16 @@ int __attribute__((target("fma4"))) changed_to_mv(void) { return 1;}
 // WINDOWS: define dso_local i32 @changed_to_mv.avx()
 // WINDOWS: define dso_local i32 @changed_to_mv.fma4()
 
+// LINUX: define linkonce void @foo_used(i32 %{{.*}}, double %{{.*}})
+// LINUX-NOT: @foo_used.avx_sse4.2(
+// LINUX-NOT: @foo_used2(
+// LINUX: define linkonce void @foo_used2.avx_sse4.2(i32 %{{.*}}, double %{{.*}})
+
+// WINDOWS: define linkonce_odr dso_local void @foo_used(i32 %{{.*}}, double %{{.*}})
+// WINDOWS-NOT: @foo_used.avx_sse4.2(
+// WINDOWS-NOT: @foo_used2(
+// WINDOWS: define linkonce_odr dso_local void @foo_used2.avx_sse4.2(i32 %{{.*}}, double %{{.*}})
+
 // LINUX: declare i32 @foo.arch_sandybridge()
 // WINDOWS: declare dso_local i32 @foo.arch_sandybridge()
 

diff  --git a/clang/test/Sema/attr-target-mv.c b/clang/test/Sema/attr-target-mv.c
index 664ade1c0fa5..e9156a6c73e7 100644
--- a/clang/test/Sema/attr-target-mv.c
+++ b/clang/test/Sema/attr-target-mv.c
@@ -77,21 +77,22 @@ int prev_no_target2(void);
 int __attribute__((target("arch=ivybridge")))  prev_no_target2(void);
 
 void __attribute__((target("sse4.2"))) addtl_attrs(void);
-//expected-error at +1 {{attribute 'target' multiversioning cannot be combined}}
-void __attribute__((used,target("arch=sandybridge")))  addtl_attrs(void);
+//expected-error at +2 {{attribute 'target' multiversioning cannot be combined}}
+void __attribute__((no_caller_saved_registers,target("arch=sandybridge")))
+addtl_attrs(void);
 
 //expected-error at +1 {{attribute 'target' multiversioning cannot be combined}}
-void __attribute__((target("default"), used)) addtl_attrs2(void);
+void __attribute__((target("default"), no_caller_saved_registers)) addtl_attrs2(void);
 
 //expected-error at +2 {{attribute 'target' multiversioning cannot be combined}}
 //expected-note at +2 {{function multiversioning caused by this declaration}}
-void __attribute__((used,target("sse4.2"))) addtl_attrs3(void);
+void __attribute__((no_caller_saved_registers,target("sse4.2"))) addtl_attrs3(void);
 void __attribute__((target("arch=sandybridge")))  addtl_attrs3(void);
 
 void __attribute__((target("sse4.2"))) addtl_attrs4(void);
 void __attribute__((target("arch=sandybridge")))  addtl_attrs4(void);
 //expected-error at +1 {{attribute 'target' multiversioning cannot be combined}}
-void __attribute__((used,target("arch=ivybridge")))  addtl_attrs4(void);
+void __attribute__((no_caller_saved_registers,target("arch=ivybridge")))  addtl_attrs4(void);
 
 int __attribute__((target("sse4.2"))) 
diff _cc(void);
 // expected-error at +1 {{multiversioned function declaration has a 
diff erent calling convention}}


        


More information about the cfe-commits mailing list