Minor clang compiler fixes
[folly.git] / folly / Bits.cpp
1 /*
2  * Copyright 2013 Facebook, Inc.
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
17 #include "folly/Bits.h"
18
19 #include "folly/CpuId.h"
20
21 // None of this is necessary if we're compiling for a target that supports
22 // popcnt
23 #ifndef __POPCNT__
24
25 namespace {
26
27 int popcount_inst(unsigned int x) {
28   int n;
29   asm ("popcntl %1, %0" : "=r" (n) : "r" (x));
30   return n;
31 }
32
33 int popcount_builtin(unsigned int x) {
34   return __builtin_popcount(x);
35 }
36
37 int popcountll_inst(unsigned long long x) {
38   unsigned long long n;
39   asm ("popcntq %1, %0" : "=r" (n) : "r" (x));
40   return n;
41 }
42
43 int popcountll_builtin(unsigned long long x) {
44   return __builtin_popcountll(x);
45 }
46
47 typedef decltype(popcount_builtin) Type_popcount;
48 typedef decltype(popcountll_builtin) Type_popcountll;
49
50 }  // namespace
51
52 // This function is called on startup to resolve folly::detail::popcount
53 extern "C" Type_popcount* folly_popcount_ifunc() {
54   return folly::CpuId().popcnt() ?  popcount_inst : popcount_builtin;
55 }
56
57 // This function is called on startup to resolve folly::detail::popcountll
58 extern "C" Type_popcountll* folly_popcountll_ifunc() {
59   return folly::CpuId().popcnt() ?  popcountll_inst : popcountll_builtin;
60 }
61
62 namespace folly {
63 namespace detail {
64
65 // Call folly_popcount_ifunc on startup to resolve to either popcount_inst
66 // or popcount_builtin
67 int popcount(unsigned int x)
68 // Clang does not support ifuncs, so we call directly for now
69 #ifdef __clang__
70 {  return popcount_builtin(x); }
71 #else
72   __attribute__((ifunc("folly_popcount_ifunc")));
73 #endif
74
75 // Call folly_popcount_ifunc on startup to resolve to either popcountll_inst
76 // or popcountll_builtin
77 int popcountll(unsigned long long x)
78 // Clang does not support ifuncs, so we call directly for now
79 #ifdef __clang__
80 {  return popcount_builtin(x); }
81 #else
82   __attribute__((ifunc("folly_popcountll_ifunc")));
83 #endif
84
85 }  // namespace detail
86 }  // namespace folly
87
88 #endif  /* !__POPCNT__ */
89