Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 94 lines (75 sloc) 2.808 kb
7fd87e7 @tudor Detect popcnt instruction at runtime, use it if available.
tudor authored
1 /*
275ca94 Copyright 2014->2015
Nicholas Ormrod authored
2 * Copyright 2015 Facebook, Inc.
7fd87e7 @tudor Detect popcnt instruction at runtime, use it if available.
tudor authored
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
ce64f0f @tudor Codemod: use #include angle brackets in folly and thrift
tudor authored
17 #include <folly/Bits.h>
7fd87e7 @tudor Detect popcnt instruction at runtime, use it if available.
tudor authored
18
ce64f0f @tudor Codemod: use #include angle brackets in folly and thrift
tudor authored
19 #include <folly/CpuId.h>
20 #include <folly/Portability.h>
7fd87e7 @tudor Detect popcnt instruction at runtime, use it if available.
tudor authored
21
22 // None of this is necessary if we're compiling for a target that supports
5ed20b5 @auroraeosrose MSVC intrinsics for bits and cpuid
auroraeosrose authored
23 // popcnt, which includes MSVC
24 #if !defined(__POPCNT__) && !defined(_MSC_VER)
7fd87e7 @tudor Detect popcnt instruction at runtime, use it if available.
tudor authored
25 namespace {
26
3a976a9 @oyamauchi Abstract ifunc support into a define
oyamauchi authored
27 int popcount_builtin(unsigned int x) {
28 return __builtin_popcount(x);
29 }
30
31 int popcountll_builtin(unsigned long long x) {
32 return __builtin_popcountll(x);
33 }
34
681e467 @philippv avoid using ifunc + ASan
philippv authored
35 #if FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS)
3a976a9 @oyamauchi Abstract ifunc support into a define
oyamauchi authored
36
37 // Strictly speaking, these versions of popcount are usable without ifunc
38 // support. However, we would have to check, via CpuId, if the processor
39 // implements the popcnt instruction first, which is what we use ifunc for.
7fd87e7 @tudor Detect popcnt instruction at runtime, use it if available.
tudor authored
40 int popcount_inst(unsigned int x) {
71acc41 @tudor Remove 1 instruction from popcount
tudor authored
41 int n;
42 asm ("popcntl %1, %0" : "=r" (n) : "r" (x));
43 return n;
7fd87e7 @tudor Detect popcnt instruction at runtime, use it if available.
tudor authored
44 }
45
46 int popcountll_inst(unsigned long long x) {
71acc41 @tudor Remove 1 instruction from popcount
tudor authored
47 unsigned long long n;
48 asm ("popcntq %1, %0" : "=r" (n) : "r" (x));
49 return n;
7fd87e7 @tudor Detect popcnt instruction at runtime, use it if available.
tudor authored
50 }
51
52 typedef decltype(popcount_builtin) Type_popcount;
53 typedef decltype(popcountll_builtin) Type_popcountll;
54
55 // This function is called on startup to resolve folly::detail::popcount
56 extern "C" Type_popcount* folly_popcount_ifunc() {
57 return folly::CpuId().popcnt() ? popcount_inst : popcount_builtin;
58 }
59
60 // This function is called on startup to resolve folly::detail::popcountll
61 extern "C" Type_popcountll* folly_popcountll_ifunc() {
62 return folly::CpuId().popcnt() ? popcountll_inst : popcountll_builtin;
63 }
64
681e467 @philippv avoid using ifunc + ASan
philippv authored
65 #endif // FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS)
3a976a9 @oyamauchi Abstract ifunc support into a define
oyamauchi authored
66
67 } // namespace
68
7fd87e7 @tudor Detect popcnt instruction at runtime, use it if available.
tudor authored
69 namespace folly {
70 namespace detail {
71
72 // Call folly_popcount_ifunc on startup to resolve to either popcount_inst
73 // or popcount_builtin
74 int popcount(unsigned int x)
681e467 @philippv avoid using ifunc + ASan
philippv authored
75 #if FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS)
a42878e fbcode: __x__-protect all __attribute__ keywords, mechanically
Jim Meyering authored
76 __attribute__((__ifunc__("folly_popcount_ifunc")));
3a976a9 @oyamauchi Abstract ifunc support into a define
oyamauchi authored
77 #else
78 { return popcount_builtin(x); }
267e38a Minor clang compiler fixes
Gaurav Jain authored
79 #endif
7fd87e7 @tudor Detect popcnt instruction at runtime, use it if available.
tudor authored
80
81 // Call folly_popcount_ifunc on startup to resolve to either popcountll_inst
82 // or popcountll_builtin
83 int popcountll(unsigned long long x)
681e467 @philippv avoid using ifunc + ASan
philippv authored
84 #if FOLLY_HAVE_IFUNC && !defined(FOLLY_SANITIZE_ADDRESS)
a42878e fbcode: __x__-protect all __attribute__ keywords, mechanically
Jim Meyering authored
85 __attribute__((__ifunc__("folly_popcountll_ifunc")));
3a976a9 @oyamauchi Abstract ifunc support into a define
oyamauchi authored
86 #else
87 { return popcountll_builtin(x); }
267e38a Minor clang compiler fixes
Gaurav Jain authored
88 #endif
7fd87e7 @tudor Detect popcnt instruction at runtime, use it if available.
tudor authored
89
90 } // namespace detail
91 } // namespace folly
92
93 #endif /* !__POPCNT__ */
Something went wrong with that request. Please try again.