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