1 /* IFUNC resolver with CPU_FEATURE_ACTIVE.
2    Copyright (C) 2021-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <sys/platform/x86.h>
20 
21 enum isa
22 {
23   none,
24   sse2,
25   sse4_2,
26   avx,
27   avx2,
28   avx512f
29 };
30 
31 enum isa
32 __attribute__ ((__optimize__ ("-fno-stack-protector")))
get_isa(void)33 get_isa (void)
34 {
35   if (CPU_FEATURE_ACTIVE (AVX512F))
36     return avx512f;
37   if (CPU_FEATURE_ACTIVE (AVX2))
38     return avx2;
39   if (CPU_FEATURE_ACTIVE (AVX))
40     return avx;
41   if (CPU_FEATURE_ACTIVE (SSE4_2))
42     return sse4_2;
43   if (CPU_FEATURE_ACTIVE (SSE2))
44     return sse2;
45   return none;
46 }
47 
48 static int
isa_sse2(void)49 isa_sse2 (void)
50 {
51   return sse2;
52 }
53 
54 static int
isa_sse4_2(void)55 isa_sse4_2 (void)
56 {
57   return sse4_2;
58 }
59 
60 static int
isa_avx(void)61 isa_avx (void)
62 {
63   return avx;
64 }
65 
66 static int
isa_avx2(void)67 isa_avx2 (void)
68 {
69   return avx2;
70 }
71 
72 static int
isa_avx512f(void)73 isa_avx512f (void)
74 {
75   return avx512f;
76 }
77 
78 static int
isa_none(void)79 isa_none (void)
80 {
81   return none;
82 }
83 
84 int foo (void) __attribute__ ((ifunc ("foo_ifunc")));
85 
86 void *
87 __attribute__ ((__optimize__ ("-fno-stack-protector")))
foo_ifunc(void)88 foo_ifunc (void)
89 {
90   switch (get_isa ())
91     {
92     case avx512f:
93       return isa_avx512f;
94     case avx2:
95       return isa_avx2;
96     case avx:
97       return isa_avx;
98     case sse4_2:
99       return isa_sse4_2;
100     case sse2:
101       return isa_sse2;
102     default:
103       break;
104     }
105   return isa_none;
106 }
107