2 * Copyright 2013 Facebook, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "folly/Bits.h"
19 #include "folly/CpuId.h"
21 // None of this is necessary if we're compiling for a target that supports
25 // Clang doesn't support ifuncs. This also allows ifunc support to be explicitly
26 // passed in as a compile flag.
27 #ifndef FOLLY_HAVE_IFUNC
29 # define FOLLY_HAVE_IFUNC 0
31 # define FOLLY_HAVE_IFUNC 1
37 int popcount_builtin(unsigned int x) {
38 return __builtin_popcount(x);
41 int popcountll_builtin(unsigned long long x) {
42 return __builtin_popcountll(x);
48 // Strictly speaking, these versions of popcount are usable without ifunc
49 // support. However, we would have to check, via CpuId, if the processor
50 // implements the popcnt instruction first, which is what we use ifunc for.
51 int popcount_inst(unsigned int x) {
53 asm ("popcntl %1, %0" : "=r" (n) : "r" (x));
57 int popcountll_inst(unsigned long long x) {
59 asm ("popcntq %1, %0" : "=r" (n) : "r" (x));
63 typedef decltype(popcount_builtin) Type_popcount;
64 typedef decltype(popcountll_builtin) Type_popcountll;
66 // This function is called on startup to resolve folly::detail::popcount
67 extern "C" Type_popcount* folly_popcount_ifunc() {
68 return folly::CpuId().popcnt() ? popcount_inst : popcount_builtin;
71 // This function is called on startup to resolve folly::detail::popcountll
72 extern "C" Type_popcountll* folly_popcountll_ifunc() {
73 return folly::CpuId().popcnt() ? popcountll_inst : popcountll_builtin;
76 #endif // FOLLY_HAVE_IFUNC
83 // Call folly_popcount_ifunc on startup to resolve to either popcount_inst
84 // or popcount_builtin
85 int popcount(unsigned int x)
87 __attribute__((ifunc("folly_popcount_ifunc")));
89 { return popcount_builtin(x); }
92 // Call folly_popcount_ifunc on startup to resolve to either popcountll_inst
93 // or popcountll_builtin
94 int popcountll(unsigned long long x)
96 __attribute__((ifunc("folly_popcountll_ifunc")));
98 { return popcountll_builtin(x); }
101 } // namespace detail
104 #endif /* !__POPCNT__ */