1 /* C++ compiler related stuff.
2 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3 Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4
5 This file is part of the Parma Polyhedra Library (PPL).
6
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23
24 #ifndef PPL_compiler_hh
25 #define PPL_compiler_hh 1
26
27 #include <cstddef>
28 #include <climits>
29 #include <cassert>
30
31 namespace Parma_Polyhedra_Library {
32
33 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
34 /*! \brief
35 No-op macro that allows to avoid unused variable warnings from
36 the compiler.
37 */
38 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
39 #define PPL_USED(v) (void)(v)
40
41 #ifdef PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS
42 /*! \brief
43 No-op function that force the compiler to store the argument and
44 to reread it from memory if needed (thus preventing CSE).
45 */
46 #endif // defined(PPL_DOXYGEN_INCLUDE_IMPLEMENTATION_DETAILS)
47 template <typename T>
48 inline void
PPL_CC_FLUSH(const T & x)49 PPL_CC_FLUSH(const T& x) {
50 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
51 __asm__ __volatile__ ("" : "+m" (const_cast<T&>(x)));
52 #else
53 // FIXME: is it possible to achieve the same effect in a portable way?
54 PPL_USED(x);
55 #endif
56 }
57
58 #ifndef PPL_SUPPRESS_UNINIT_WARNINGS
59 #define PPL_SUPPRESS_UNINIT_WARNINGS 1
60 #endif
61
62 #ifndef PPL_SUPPRESS_UNINITIALIZED_WARNINGS
63 #define PPL_SUPPRESS_UNINITIALIZED_WARNINGS 1
64 #endif
65
66 #if PPL_SUPPRESS_UNINITIALIZED_WARNINGS
67 template <typename T>
68 struct Suppress_Uninitialized_Warnings_Type {
69 typedef T synonym;
70 };
71
72 #define PPL_UNINITIALIZED(type, name) \
73 PPL_U(type) PPL_U(name) \
74 = Suppress_Uninitialized_Warnings_Type<PPL_U(type)>::synonym()
75 #else
76 #define PPL_UNINITIALIZED(type, name) \
77 PPL_U(type) name
78 #endif
79
80 #define sizeof_to_bits(size) \
81 ((size) * static_cast<std::size_t>(CHAR_BIT))
82
83 #if !defined(__GNUC__)
84
85 inline unsigned int
clz32(uint32_t w)86 clz32(uint32_t w) {
87 unsigned int r = 31;
88 if ((w & 0xffff0000U) != 0) {
89 w >>= 16;
90 r -= 16;
91 }
92 if ((w & 0xff00U) != 0) {
93 w >>= 8;
94 r -= 8;
95 }
96 if ((w & 0xf0U) != 0) {
97 w >>= 4;
98 r -= 4;
99 }
100 if ((w & 0xcU) != 0) {
101 w >>= 2;
102 r -= 2;
103 }
104 if ((w & 0x2U) != 0) {
105 r -= 1;
106 }
107 return r;
108 }
109
110 inline unsigned int
clz64(uint64_t w)111 clz64(uint64_t w) {
112 if ((w & 0xffffffff00000000ULL) == 0) {
113 return clz32(static_cast<uint32_t>(w)) + 32;
114 }
115 else {
116 return clz32(static_cast<uint32_t>(w >> 32));
117 }
118 }
119
120 inline unsigned int
ctz32(uint32_t w)121 ctz32(uint32_t w) {
122 static const unsigned int mod37_table[] = {
123 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13,
124 4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9,
125 5, 20, 8, 19, 18
126 };
127 return mod37_table[(w & -w) % 37];
128 }
129
130 inline unsigned int
ctz64(uint64_t w)131 ctz64(uint64_t w) {
132 if ((w & 0x00000000ffffffffULL) == 0) {
133 return ctz32(static_cast<uint32_t>(w >> 32)) + 32;
134 }
135 else {
136 return ctz32(static_cast<uint32_t>(w));
137 }
138 }
139
140 #endif
141
142 inline unsigned int
clz(unsigned int u)143 clz(unsigned int u) {
144 assert(u != 0);
145 #if defined(__GNUC__)
146 return static_cast<unsigned int>(__builtin_clz(u));
147 #elif PPL_SIZEOF_INT == 4
148 return clz32(u);
149 #elif PPL_SIZEOF_INT == 8
150 return clz64(u);
151 #else
152 #error "Unsupported unsigned int size"
153 #endif
154 }
155
156 inline unsigned int
clz(unsigned long ul)157 clz(unsigned long ul) {
158 assert(ul != 0);
159 #if defined(__GNUC__)
160 return static_cast<unsigned int>(__builtin_clzl(ul));
161 #elif PPL_SIZEOF_LONG == 4
162 return clz32(ul);
163 #elif PPL_SIZEOF_LONG == 8
164 return clz64(ul);
165 #else
166 #error "Unsupported unsigned long size"
167 #endif
168 }
169
170 inline unsigned int
clz(unsigned long long ull)171 clz(unsigned long long ull) {
172 assert(ull != 0);
173 #if defined(__GNUC__)
174 return static_cast<unsigned int>(__builtin_clzll(ull));
175 #elif PPL_SIZEOF_LONG_LONG == 4
176 return clz32(ull);
177 #elif PPL_SIZEOF_LONG_LONG == 8
178 return clz64(ull);
179 #else
180 #error "Unsupported unsigned long long size"
181 #endif
182 }
183
184
185 inline unsigned int
ctz(unsigned int u)186 ctz(unsigned int u) {
187 assert(u != 0);
188 #if defined(__GNUC__)
189 return static_cast<unsigned int>(__builtin_ctz(u));
190 #elif PPL_SIZEOF_INT == 4
191 return ctz32(u);
192 #elif PPL_SIZEOF_INT == 8
193 return ctz64(u);
194 #else
195 #error "Unsupported unsigned int size"
196 #endif
197 }
198
199 inline unsigned int
ctz(unsigned long ul)200 ctz(unsigned long ul) {
201 assert(ul != 0);
202 #if defined(__GNUC__)
203 return static_cast<unsigned int>(__builtin_ctzl(ul));
204 #elif PPL_SIZEOF_LONG == 4
205 return ctz32(ul);
206 #elif PPL_SIZEOF_LONG == 8
207 return ctz64(ul);
208 #else
209 #error "Unsupported unsigned long size"
210 #endif
211 }
212
213 inline unsigned int
ctz(unsigned long long ull)214 ctz(unsigned long long ull) {
215 assert(ull != 0);
216 #if defined(__GNUC__)
217 return static_cast<unsigned int>(__builtin_ctzll(ull));
218 #elif PPL_SIZEOF_LONG_LONG == 4
219 return ctz32(ull);
220 #elif PPL_SIZEOF_LONG_LONG == 8
221 return ctz64(ull);
222 #else
223 #error "Unsupported unsigned long long size"
224 #endif
225 }
226
227 } // namespace Parma_Polyhedra_Library
228
229 #endif // !defined(PPL_compiler_hh)
230