xref: /dflybsd-src/contrib/gcc-8.0/gcc/machmode.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* Machine mode definitions for GCC; included by rtl.h and tree.h.
2*38fd1498Szrj    Copyright (C) 1991-2018 Free Software Foundation, Inc.
3*38fd1498Szrj 
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj 
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj 
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj 
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
19*38fd1498Szrj 
20*38fd1498Szrj #ifndef HAVE_MACHINE_MODES
21*38fd1498Szrj #define HAVE_MACHINE_MODES
22*38fd1498Szrj 
23*38fd1498Szrj typedef opt_mode<machine_mode> opt_machine_mode;
24*38fd1498Szrj 
25*38fd1498Szrj extern CONST_MODE_SIZE poly_uint16_pod mode_size[NUM_MACHINE_MODES];
26*38fd1498Szrj extern CONST_MODE_PRECISION poly_uint16_pod mode_precision[NUM_MACHINE_MODES];
27*38fd1498Szrj extern const unsigned char mode_inner[NUM_MACHINE_MODES];
28*38fd1498Szrj extern CONST_MODE_NUNITS poly_uint16_pod mode_nunits[NUM_MACHINE_MODES];
29*38fd1498Szrj extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES];
30*38fd1498Szrj extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];
31*38fd1498Szrj extern const unsigned char mode_wider[NUM_MACHINE_MODES];
32*38fd1498Szrj extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
33*38fd1498Szrj 
34*38fd1498Szrj template<typename T>
35*38fd1498Szrj struct mode_traits
36*38fd1498Szrj {
37*38fd1498Szrj   /* For use by the machmode support code only.
38*38fd1498Szrj 
39*38fd1498Szrj      There are cases in which the machmode support code needs to forcibly
40*38fd1498Szrj      convert a machine_mode to a specific mode class T, and in which the
41*38fd1498Szrj      context guarantees that this is valid without the need for an assert.
42*38fd1498Szrj      This can be done using:
43*38fd1498Szrj 
44*38fd1498Szrj        return typename mode_traits<T>::from_int (mode);
45*38fd1498Szrj 
46*38fd1498Szrj      when returning a T and:
47*38fd1498Szrj 
48*38fd1498Szrj        res = T (typename mode_traits<T>::from_int (mode));
49*38fd1498Szrj 
50*38fd1498Szrj      when assigning to a value RES that must be assignment-compatible
51*38fd1498Szrj      with (but possibly not the same as) T.  */
52*38fd1498Szrj #ifdef USE_ENUM_MODES
53*38fd1498Szrj   /* Allow direct conversion of enums to specific mode classes only
54*38fd1498Szrj      when USE_ENUM_MODES is defined.  This is only intended for use
55*38fd1498Szrj      by gencondmd, so that it can tell more easily when .md conditions
56*38fd1498Szrj      are always false.  */
57*38fd1498Szrj   typedef machine_mode from_int;
58*38fd1498Szrj #else
59*38fd1498Szrj   /* Here we use an enum type distinct from machine_mode but with the
60*38fd1498Szrj      same range as machine_mode.  T should have a constructor that
61*38fd1498Szrj      accepts this enum type; it should not have a constructor that
62*38fd1498Szrj      accepts machine_mode.
63*38fd1498Szrj 
64*38fd1498Szrj      We use this somewhat indirect approach to avoid too many constructor
65*38fd1498Szrj      calls when the compiler is built with -O0.  For example, even in
66*38fd1498Szrj      unoptimized code, the return statement above would construct the
67*38fd1498Szrj      returned T directly from the numerical value of MODE.  */
68*38fd1498Szrj   enum from_int { dummy = MAX_MACHINE_MODE };
69*38fd1498Szrj #endif
70*38fd1498Szrj };
71*38fd1498Szrj 
72*38fd1498Szrj template<>
73*38fd1498Szrj struct mode_traits<machine_mode>
74*38fd1498Szrj {
75*38fd1498Szrj   /* machine_mode itself needs no conversion.  */
76*38fd1498Szrj   typedef machine_mode from_int;
77*38fd1498Szrj };
78*38fd1498Szrj 
79*38fd1498Szrj /* Always treat machine modes as fixed-size while compiling code specific
80*38fd1498Szrj    to targets that have no variable-size modes.  */
81*38fd1498Szrj #if defined (IN_TARGET_CODE) && NUM_POLY_INT_COEFFS == 1
82*38fd1498Szrj #define ONLY_FIXED_SIZE_MODES 1
83*38fd1498Szrj #else
84*38fd1498Szrj #define ONLY_FIXED_SIZE_MODES 0
85*38fd1498Szrj #endif
86*38fd1498Szrj 
87*38fd1498Szrj /* Get the name of mode MODE as a string.  */
88*38fd1498Szrj 
89*38fd1498Szrj extern const char * const mode_name[NUM_MACHINE_MODES];
90*38fd1498Szrj #define GET_MODE_NAME(MODE)  mode_name[MODE]
91*38fd1498Szrj 
92*38fd1498Szrj /* Mode classes.  */
93*38fd1498Szrj 
94*38fd1498Szrj #include "mode-classes.def"
95*38fd1498Szrj #define DEF_MODE_CLASS(M) M
96*38fd1498Szrj enum mode_class { MODE_CLASSES, MAX_MODE_CLASS };
97*38fd1498Szrj #undef DEF_MODE_CLASS
98*38fd1498Szrj #undef MODE_CLASSES
99*38fd1498Szrj 
100*38fd1498Szrj /* Get the general kind of object that mode MODE represents
101*38fd1498Szrj    (integer, floating, complex, etc.)  */
102*38fd1498Szrj 
103*38fd1498Szrj extern const unsigned char mode_class[NUM_MACHINE_MODES];
104*38fd1498Szrj #define GET_MODE_CLASS(MODE)  ((enum mode_class) mode_class[MODE])
105*38fd1498Szrj 
106*38fd1498Szrj /* Nonzero if MODE is an integral mode.  */
107*38fd1498Szrj #define INTEGRAL_MODE_P(MODE)			\
108*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_INT		\
109*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT \
110*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
111*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL \
112*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT)
113*38fd1498Szrj 
114*38fd1498Szrj /* Nonzero if MODE is a floating-point mode.  */
115*38fd1498Szrj #define FLOAT_MODE_P(MODE)		\
116*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_FLOAT	\
117*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT \
118*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \
119*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT)
120*38fd1498Szrj 
121*38fd1498Szrj /* Nonzero if MODE is a complex mode.  */
122*38fd1498Szrj #define COMPLEX_MODE_P(MODE)			\
123*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT	\
124*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
125*38fd1498Szrj 
126*38fd1498Szrj /* Nonzero if MODE is a vector mode.  */
127*38fd1498Szrj #define VECTOR_MODE_P(MODE)				\
128*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL		\
129*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_INT		\
130*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT	\
131*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FRACT	\
132*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_UFRACT	\
133*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_ACCUM	\
134*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_UACCUM)
135*38fd1498Szrj 
136*38fd1498Szrj /* Nonzero if MODE is a scalar integral mode.  */
137*38fd1498Szrj #define SCALAR_INT_MODE_P(MODE)			\
138*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_INT		\
139*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT)
140*38fd1498Szrj 
141*38fd1498Szrj /* Nonzero if MODE is a scalar floating point mode.  */
142*38fd1498Szrj #define SCALAR_FLOAT_MODE_P(MODE)		\
143*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_FLOAT		\
144*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT)
145*38fd1498Szrj 
146*38fd1498Szrj /* Nonzero if MODE is a decimal floating point mode.  */
147*38fd1498Szrj #define DECIMAL_FLOAT_MODE_P(MODE)		\
148*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT)
149*38fd1498Szrj 
150*38fd1498Szrj /* Nonzero if MODE is a scalar fract mode.  */
151*38fd1498Szrj #define SCALAR_FRACT_MODE_P(MODE)	\
152*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_FRACT)
153*38fd1498Szrj 
154*38fd1498Szrj /* Nonzero if MODE is a scalar ufract mode.  */
155*38fd1498Szrj #define SCALAR_UFRACT_MODE_P(MODE)	\
156*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_UFRACT)
157*38fd1498Szrj 
158*38fd1498Szrj /* Nonzero if MODE is a scalar fract or ufract mode.  */
159*38fd1498Szrj #define ALL_SCALAR_FRACT_MODE_P(MODE)	\
160*38fd1498Szrj   (SCALAR_FRACT_MODE_P (MODE) || SCALAR_UFRACT_MODE_P (MODE))
161*38fd1498Szrj 
162*38fd1498Szrj /* Nonzero if MODE is a scalar accum mode.  */
163*38fd1498Szrj #define SCALAR_ACCUM_MODE_P(MODE)	\
164*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_ACCUM)
165*38fd1498Szrj 
166*38fd1498Szrj /* Nonzero if MODE is a scalar uaccum mode.  */
167*38fd1498Szrj #define SCALAR_UACCUM_MODE_P(MODE)	\
168*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_UACCUM)
169*38fd1498Szrj 
170*38fd1498Szrj /* Nonzero if MODE is a scalar accum or uaccum mode.  */
171*38fd1498Szrj #define ALL_SCALAR_ACCUM_MODE_P(MODE)	\
172*38fd1498Szrj   (SCALAR_ACCUM_MODE_P (MODE) || SCALAR_UACCUM_MODE_P (MODE))
173*38fd1498Szrj 
174*38fd1498Szrj /* Nonzero if MODE is a scalar fract or accum mode.  */
175*38fd1498Szrj #define SIGNED_SCALAR_FIXED_POINT_MODE_P(MODE)	\
176*38fd1498Szrj   (SCALAR_FRACT_MODE_P (MODE) || SCALAR_ACCUM_MODE_P (MODE))
177*38fd1498Szrj 
178*38fd1498Szrj /* Nonzero if MODE is a scalar ufract or uaccum mode.  */
179*38fd1498Szrj #define UNSIGNED_SCALAR_FIXED_POINT_MODE_P(MODE)	\
180*38fd1498Szrj   (SCALAR_UFRACT_MODE_P (MODE) || SCALAR_UACCUM_MODE_P (MODE))
181*38fd1498Szrj 
182*38fd1498Szrj /* Nonzero if MODE is a scalar fract, ufract, accum or uaccum mode.  */
183*38fd1498Szrj #define ALL_SCALAR_FIXED_POINT_MODE_P(MODE)	\
184*38fd1498Szrj   (SIGNED_SCALAR_FIXED_POINT_MODE_P (MODE)	\
185*38fd1498Szrj    || UNSIGNED_SCALAR_FIXED_POINT_MODE_P (MODE))
186*38fd1498Szrj 
187*38fd1498Szrj /* Nonzero if MODE is a scalar/vector fract mode.  */
188*38fd1498Szrj #define FRACT_MODE_P(MODE)		\
189*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_FRACT	\
190*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_FRACT)
191*38fd1498Szrj 
192*38fd1498Szrj /* Nonzero if MODE is a scalar/vector ufract mode.  */
193*38fd1498Szrj #define UFRACT_MODE_P(MODE)		\
194*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_UFRACT	\
195*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_UFRACT)
196*38fd1498Szrj 
197*38fd1498Szrj /* Nonzero if MODE is a scalar/vector fract or ufract mode.  */
198*38fd1498Szrj #define ALL_FRACT_MODE_P(MODE)		\
199*38fd1498Szrj   (FRACT_MODE_P (MODE) || UFRACT_MODE_P (MODE))
200*38fd1498Szrj 
201*38fd1498Szrj /* Nonzero if MODE is a scalar/vector accum mode.  */
202*38fd1498Szrj #define ACCUM_MODE_P(MODE)		\
203*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_ACCUM	\
204*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_ACCUM)
205*38fd1498Szrj 
206*38fd1498Szrj /* Nonzero if MODE is a scalar/vector uaccum mode.  */
207*38fd1498Szrj #define UACCUM_MODE_P(MODE)		\
208*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_UACCUM	\
209*38fd1498Szrj    || GET_MODE_CLASS (MODE) == MODE_VECTOR_UACCUM)
210*38fd1498Szrj 
211*38fd1498Szrj /* Nonzero if MODE is a scalar/vector accum or uaccum mode.  */
212*38fd1498Szrj #define ALL_ACCUM_MODE_P(MODE)		\
213*38fd1498Szrj   (ACCUM_MODE_P (MODE) || UACCUM_MODE_P (MODE))
214*38fd1498Szrj 
215*38fd1498Szrj /* Nonzero if MODE is a scalar/vector fract or accum mode.  */
216*38fd1498Szrj #define SIGNED_FIXED_POINT_MODE_P(MODE)		\
217*38fd1498Szrj   (FRACT_MODE_P (MODE) || ACCUM_MODE_P (MODE))
218*38fd1498Szrj 
219*38fd1498Szrj /* Nonzero if MODE is a scalar/vector ufract or uaccum mode.  */
220*38fd1498Szrj #define UNSIGNED_FIXED_POINT_MODE_P(MODE)	\
221*38fd1498Szrj   (UFRACT_MODE_P (MODE) || UACCUM_MODE_P (MODE))
222*38fd1498Szrj 
223*38fd1498Szrj /* Nonzero if MODE is a scalar/vector fract, ufract, accum or uaccum mode.  */
224*38fd1498Szrj #define ALL_FIXED_POINT_MODE_P(MODE)		\
225*38fd1498Szrj   (SIGNED_FIXED_POINT_MODE_P (MODE)		\
226*38fd1498Szrj    || UNSIGNED_FIXED_POINT_MODE_P (MODE))
227*38fd1498Szrj 
228*38fd1498Szrj /* Nonzero if CLASS modes can be widened.  */
229*38fd1498Szrj #define CLASS_HAS_WIDER_MODES_P(CLASS)         \
230*38fd1498Szrj   (CLASS == MODE_INT                           \
231*38fd1498Szrj    || CLASS == MODE_PARTIAL_INT                \
232*38fd1498Szrj    || CLASS == MODE_FLOAT                      \
233*38fd1498Szrj    || CLASS == MODE_DECIMAL_FLOAT              \
234*38fd1498Szrj    || CLASS == MODE_COMPLEX_FLOAT              \
235*38fd1498Szrj    || CLASS == MODE_FRACT                      \
236*38fd1498Szrj    || CLASS == MODE_UFRACT                     \
237*38fd1498Szrj    || CLASS == MODE_ACCUM                      \
238*38fd1498Szrj    || CLASS == MODE_UACCUM)
239*38fd1498Szrj 
240*38fd1498Szrj #define POINTER_BOUNDS_MODE_P(MODE)      \
241*38fd1498Szrj   (GET_MODE_CLASS (MODE) == MODE_POINTER_BOUNDS)
242*38fd1498Szrj 
243*38fd1498Szrj /* An optional T (i.e. a T or nothing), where T is some form of mode class.  */
244*38fd1498Szrj template<typename T>
245*38fd1498Szrj class opt_mode
246*38fd1498Szrj {
247*38fd1498Szrj public:
248*38fd1498Szrj   enum from_int { dummy = MAX_MACHINE_MODE };
249*38fd1498Szrj 
250*38fd1498Szrj   ALWAYS_INLINE opt_mode () : m_mode (E_VOIDmode) {}
251*38fd1498Szrj   ALWAYS_INLINE opt_mode (const T &m) : m_mode (m) {}
252*38fd1498Szrj   template<typename U>
253*38fd1498Szrj   ALWAYS_INLINE opt_mode (const U &m) : m_mode (T (m)) {}
254*38fd1498Szrj   ALWAYS_INLINE opt_mode (from_int m) : m_mode (machine_mode (m)) {}
255*38fd1498Szrj 
256*38fd1498Szrj   machine_mode else_void () const;
257*38fd1498Szrj   machine_mode else_blk () const;
258*38fd1498Szrj   T require () const;
259*38fd1498Szrj 
260*38fd1498Szrj   bool exists () const;
261*38fd1498Szrj   template<typename U> bool exists (U *) const;
262*38fd1498Szrj 
263*38fd1498Szrj private:
264*38fd1498Szrj   machine_mode m_mode;
265*38fd1498Szrj };
266*38fd1498Szrj 
267*38fd1498Szrj /* If the object contains a T, return its enum value, otherwise return
268*38fd1498Szrj    E_VOIDmode.  */
269*38fd1498Szrj 
270*38fd1498Szrj template<typename T>
271*38fd1498Szrj ALWAYS_INLINE machine_mode
272*38fd1498Szrj opt_mode<T>::else_void () const
273*38fd1498Szrj {
274*38fd1498Szrj   return m_mode;
275*38fd1498Szrj }
276*38fd1498Szrj 
277*38fd1498Szrj /* If the T exists, return its enum value, otherwise return E_BLKmode.  */
278*38fd1498Szrj 
279*38fd1498Szrj template<typename T>
280*38fd1498Szrj inline machine_mode
281*38fd1498Szrj opt_mode<T>::else_blk () const
282*38fd1498Szrj {
283*38fd1498Szrj   return m_mode == E_VOIDmode ? E_BLKmode : m_mode;
284*38fd1498Szrj }
285*38fd1498Szrj 
286*38fd1498Szrj /* Assert that the object contains a T and return it.  */
287*38fd1498Szrj 
288*38fd1498Szrj template<typename T>
289*38fd1498Szrj inline T
290*38fd1498Szrj opt_mode<T>::require () const
291*38fd1498Szrj {
292*38fd1498Szrj   gcc_checking_assert (m_mode != E_VOIDmode);
293*38fd1498Szrj   return typename mode_traits<T>::from_int (m_mode);
294*38fd1498Szrj }
295*38fd1498Szrj 
296*38fd1498Szrj /* Return true if the object contains a T rather than nothing.  */
297*38fd1498Szrj 
298*38fd1498Szrj template<typename T>
299*38fd1498Szrj ALWAYS_INLINE bool
300*38fd1498Szrj opt_mode<T>::exists () const
301*38fd1498Szrj {
302*38fd1498Szrj   return m_mode != E_VOIDmode;
303*38fd1498Szrj }
304*38fd1498Szrj 
305*38fd1498Szrj /* Return true if the object contains a T, storing it in *MODE if so.  */
306*38fd1498Szrj 
307*38fd1498Szrj template<typename T>
308*38fd1498Szrj template<typename U>
309*38fd1498Szrj inline bool
310*38fd1498Szrj opt_mode<T>::exists (U *mode) const
311*38fd1498Szrj {
312*38fd1498Szrj   if (m_mode != E_VOIDmode)
313*38fd1498Szrj     {
314*38fd1498Szrj       *mode = T (typename mode_traits<T>::from_int (m_mode));
315*38fd1498Szrj       return true;
316*38fd1498Szrj     }
317*38fd1498Szrj   return false;
318*38fd1498Szrj }
319*38fd1498Szrj 
320*38fd1498Szrj /* A POD version of mode class T.  */
321*38fd1498Szrj 
322*38fd1498Szrj template<typename T>
323*38fd1498Szrj struct pod_mode
324*38fd1498Szrj {
325*38fd1498Szrj   typedef typename mode_traits<T>::from_int from_int;
326*38fd1498Szrj   typedef typename T::measurement_type measurement_type;
327*38fd1498Szrj 
328*38fd1498Szrj   machine_mode m_mode;
329*38fd1498Szrj   ALWAYS_INLINE operator machine_mode () const { return m_mode; }
330*38fd1498Szrj   ALWAYS_INLINE operator T () const { return from_int (m_mode); }
331*38fd1498Szrj   ALWAYS_INLINE pod_mode &operator = (const T &m) { m_mode = m; return *this; }
332*38fd1498Szrj };
333*38fd1498Szrj 
334*38fd1498Szrj /* Return true if mode M has type T.  */
335*38fd1498Szrj 
336*38fd1498Szrj template<typename T>
337*38fd1498Szrj inline bool
338*38fd1498Szrj is_a (machine_mode m)
339*38fd1498Szrj {
340*38fd1498Szrj   return T::includes_p (m);
341*38fd1498Szrj }
342*38fd1498Szrj 
343*38fd1498Szrj template<typename T, typename U>
344*38fd1498Szrj inline bool
345*38fd1498Szrj is_a (const opt_mode<U> &m)
346*38fd1498Szrj {
347*38fd1498Szrj   return T::includes_p (m.else_void ());
348*38fd1498Szrj }
349*38fd1498Szrj 
350*38fd1498Szrj /* Assert that mode M has type T, and return it in that form.  */
351*38fd1498Szrj 
352*38fd1498Szrj template<typename T>
353*38fd1498Szrj inline T
354*38fd1498Szrj as_a (machine_mode m)
355*38fd1498Szrj {
356*38fd1498Szrj   gcc_checking_assert (T::includes_p (m));
357*38fd1498Szrj   return typename mode_traits<T>::from_int (m);
358*38fd1498Szrj }
359*38fd1498Szrj 
360*38fd1498Szrj template<typename T, typename U>
361*38fd1498Szrj inline T
362*38fd1498Szrj as_a (const opt_mode<U> &m)
363*38fd1498Szrj {
364*38fd1498Szrj   return as_a <T> (m.else_void ());
365*38fd1498Szrj }
366*38fd1498Szrj 
367*38fd1498Szrj /* Convert M to an opt_mode<T>.  */
368*38fd1498Szrj 
369*38fd1498Szrj template<typename T>
370*38fd1498Szrj inline opt_mode<T>
371*38fd1498Szrj dyn_cast (machine_mode m)
372*38fd1498Szrj {
373*38fd1498Szrj   if (T::includes_p (m))
374*38fd1498Szrj     return T (typename mode_traits<T>::from_int (m));
375*38fd1498Szrj   return opt_mode<T> ();
376*38fd1498Szrj }
377*38fd1498Szrj 
378*38fd1498Szrj template<typename T, typename U>
379*38fd1498Szrj inline opt_mode<T>
380*38fd1498Szrj dyn_cast (const opt_mode<U> &m)
381*38fd1498Szrj {
382*38fd1498Szrj   return dyn_cast <T> (m.else_void ());
383*38fd1498Szrj }
384*38fd1498Szrj 
385*38fd1498Szrj /* Return true if mode M has type T, storing it as a T in *RESULT
386*38fd1498Szrj    if so.  */
387*38fd1498Szrj 
388*38fd1498Szrj template<typename T, typename U>
389*38fd1498Szrj inline bool
390*38fd1498Szrj is_a (machine_mode m, U *result)
391*38fd1498Szrj {
392*38fd1498Szrj   if (T::includes_p (m))
393*38fd1498Szrj     {
394*38fd1498Szrj       *result = T (typename mode_traits<T>::from_int (m));
395*38fd1498Szrj       return true;
396*38fd1498Szrj     }
397*38fd1498Szrj   return false;
398*38fd1498Szrj }
399*38fd1498Szrj 
400*38fd1498Szrj /* Represents a machine mode that is known to be a SCALAR_INT_MODE_P.  */
401*38fd1498Szrj class scalar_int_mode
402*38fd1498Szrj {
403*38fd1498Szrj public:
404*38fd1498Szrj   typedef mode_traits<scalar_int_mode>::from_int from_int;
405*38fd1498Szrj   typedef unsigned short measurement_type;
406*38fd1498Szrj 
407*38fd1498Szrj   ALWAYS_INLINE scalar_int_mode () {}
408*38fd1498Szrj   ALWAYS_INLINE scalar_int_mode (from_int m) : m_mode (machine_mode (m)) {}
409*38fd1498Szrj   ALWAYS_INLINE operator machine_mode () const { return m_mode; }
410*38fd1498Szrj 
411*38fd1498Szrj   static bool includes_p (machine_mode);
412*38fd1498Szrj 
413*38fd1498Szrj protected:
414*38fd1498Szrj   machine_mode m_mode;
415*38fd1498Szrj };
416*38fd1498Szrj 
417*38fd1498Szrj /* Return true if M is a scalar_int_mode.  */
418*38fd1498Szrj 
419*38fd1498Szrj inline bool
420*38fd1498Szrj scalar_int_mode::includes_p (machine_mode m)
421*38fd1498Szrj {
422*38fd1498Szrj   return SCALAR_INT_MODE_P (m);
423*38fd1498Szrj }
424*38fd1498Szrj 
425*38fd1498Szrj /* Represents a machine mode that is known to be a SCALAR_FLOAT_MODE_P.  */
426*38fd1498Szrj class scalar_float_mode
427*38fd1498Szrj {
428*38fd1498Szrj public:
429*38fd1498Szrj   typedef mode_traits<scalar_float_mode>::from_int from_int;
430*38fd1498Szrj   typedef unsigned short measurement_type;
431*38fd1498Szrj 
432*38fd1498Szrj   ALWAYS_INLINE scalar_float_mode () {}
433*38fd1498Szrj   ALWAYS_INLINE scalar_float_mode (from_int m) : m_mode (machine_mode (m)) {}
434*38fd1498Szrj   ALWAYS_INLINE operator machine_mode () const { return m_mode; }
435*38fd1498Szrj 
436*38fd1498Szrj   static bool includes_p (machine_mode);
437*38fd1498Szrj 
438*38fd1498Szrj protected:
439*38fd1498Szrj   machine_mode m_mode;
440*38fd1498Szrj };
441*38fd1498Szrj 
442*38fd1498Szrj /* Return true if M is a scalar_float_mode.  */
443*38fd1498Szrj 
444*38fd1498Szrj inline bool
445*38fd1498Szrj scalar_float_mode::includes_p (machine_mode m)
446*38fd1498Szrj {
447*38fd1498Szrj   return SCALAR_FLOAT_MODE_P (m);
448*38fd1498Szrj }
449*38fd1498Szrj 
450*38fd1498Szrj /* Represents a machine mode that is known to be scalar.  */
451*38fd1498Szrj class scalar_mode
452*38fd1498Szrj {
453*38fd1498Szrj public:
454*38fd1498Szrj   typedef mode_traits<scalar_mode>::from_int from_int;
455*38fd1498Szrj   typedef unsigned short measurement_type;
456*38fd1498Szrj 
457*38fd1498Szrj   ALWAYS_INLINE scalar_mode () {}
458*38fd1498Szrj   ALWAYS_INLINE scalar_mode (from_int m) : m_mode (machine_mode (m)) {}
459*38fd1498Szrj   ALWAYS_INLINE scalar_mode (const scalar_int_mode &m) : m_mode (m) {}
460*38fd1498Szrj   ALWAYS_INLINE scalar_mode (const scalar_float_mode &m) : m_mode (m) {}
461*38fd1498Szrj   ALWAYS_INLINE scalar_mode (const scalar_int_mode_pod &m) : m_mode (m) {}
462*38fd1498Szrj   ALWAYS_INLINE operator machine_mode () const { return m_mode; }
463*38fd1498Szrj 
464*38fd1498Szrj   static bool includes_p (machine_mode);
465*38fd1498Szrj 
466*38fd1498Szrj protected:
467*38fd1498Szrj   machine_mode m_mode;
468*38fd1498Szrj };
469*38fd1498Szrj 
470*38fd1498Szrj /* Return true if M represents some kind of scalar value.  */
471*38fd1498Szrj 
472*38fd1498Szrj inline bool
473*38fd1498Szrj scalar_mode::includes_p (machine_mode m)
474*38fd1498Szrj {
475*38fd1498Szrj   switch (GET_MODE_CLASS (m))
476*38fd1498Szrj     {
477*38fd1498Szrj     case MODE_INT:
478*38fd1498Szrj     case MODE_PARTIAL_INT:
479*38fd1498Szrj     case MODE_FRACT:
480*38fd1498Szrj     case MODE_UFRACT:
481*38fd1498Szrj     case MODE_ACCUM:
482*38fd1498Szrj     case MODE_UACCUM:
483*38fd1498Szrj     case MODE_FLOAT:
484*38fd1498Szrj     case MODE_DECIMAL_FLOAT:
485*38fd1498Szrj     case MODE_POINTER_BOUNDS:
486*38fd1498Szrj       return true;
487*38fd1498Szrj     default:
488*38fd1498Szrj       return false;
489*38fd1498Szrj     }
490*38fd1498Szrj }
491*38fd1498Szrj 
492*38fd1498Szrj /* Represents a machine mode that is known to be a COMPLEX_MODE_P.  */
493*38fd1498Szrj class complex_mode
494*38fd1498Szrj {
495*38fd1498Szrj public:
496*38fd1498Szrj   typedef mode_traits<complex_mode>::from_int from_int;
497*38fd1498Szrj   typedef unsigned short measurement_type;
498*38fd1498Szrj 
499*38fd1498Szrj   ALWAYS_INLINE complex_mode () {}
500*38fd1498Szrj   ALWAYS_INLINE complex_mode (from_int m) : m_mode (machine_mode (m)) {}
501*38fd1498Szrj   ALWAYS_INLINE operator machine_mode () const { return m_mode; }
502*38fd1498Szrj 
503*38fd1498Szrj   static bool includes_p (machine_mode);
504*38fd1498Szrj 
505*38fd1498Szrj protected:
506*38fd1498Szrj   machine_mode m_mode;
507*38fd1498Szrj };
508*38fd1498Szrj 
509*38fd1498Szrj /* Return true if M is a complex_mode.  */
510*38fd1498Szrj 
511*38fd1498Szrj inline bool
512*38fd1498Szrj complex_mode::includes_p (machine_mode m)
513*38fd1498Szrj {
514*38fd1498Szrj   return COMPLEX_MODE_P (m);
515*38fd1498Szrj }
516*38fd1498Szrj 
517*38fd1498Szrj /* Return the base GET_MODE_SIZE value for MODE.  */
518*38fd1498Szrj 
519*38fd1498Szrj ALWAYS_INLINE poly_uint16
520*38fd1498Szrj mode_to_bytes (machine_mode mode)
521*38fd1498Szrj {
522*38fd1498Szrj #if GCC_VERSION >= 4001
523*38fd1498Szrj   return (__builtin_constant_p (mode)
524*38fd1498Szrj 	  ? mode_size_inline (mode) : mode_size[mode]);
525*38fd1498Szrj #else
526*38fd1498Szrj   return mode_size[mode];
527*38fd1498Szrj #endif
528*38fd1498Szrj }
529*38fd1498Szrj 
530*38fd1498Szrj /* Return the base GET_MODE_BITSIZE value for MODE.  */
531*38fd1498Szrj 
532*38fd1498Szrj ALWAYS_INLINE poly_uint16
533*38fd1498Szrj mode_to_bits (machine_mode mode)
534*38fd1498Szrj {
535*38fd1498Szrj   return mode_to_bytes (mode) * BITS_PER_UNIT;
536*38fd1498Szrj }
537*38fd1498Szrj 
538*38fd1498Szrj /* Return the base GET_MODE_PRECISION value for MODE.  */
539*38fd1498Szrj 
540*38fd1498Szrj ALWAYS_INLINE poly_uint16
541*38fd1498Szrj mode_to_precision (machine_mode mode)
542*38fd1498Szrj {
543*38fd1498Szrj   return mode_precision[mode];
544*38fd1498Szrj }
545*38fd1498Szrj 
546*38fd1498Szrj /* Return the base GET_MODE_INNER value for MODE.  */
547*38fd1498Szrj 
548*38fd1498Szrj ALWAYS_INLINE scalar_mode
549*38fd1498Szrj mode_to_inner (machine_mode mode)
550*38fd1498Szrj {
551*38fd1498Szrj #if GCC_VERSION >= 4001
552*38fd1498Szrj   return scalar_mode::from_int (__builtin_constant_p (mode)
553*38fd1498Szrj 				? mode_inner_inline (mode)
554*38fd1498Szrj 				: mode_inner[mode]);
555*38fd1498Szrj #else
556*38fd1498Szrj   return scalar_mode::from_int (mode_inner[mode]);
557*38fd1498Szrj #endif
558*38fd1498Szrj }
559*38fd1498Szrj 
560*38fd1498Szrj /* Return the base GET_MODE_UNIT_SIZE value for MODE.  */
561*38fd1498Szrj 
562*38fd1498Szrj ALWAYS_INLINE unsigned char
563*38fd1498Szrj mode_to_unit_size (machine_mode mode)
564*38fd1498Szrj {
565*38fd1498Szrj #if GCC_VERSION >= 4001
566*38fd1498Szrj   return (__builtin_constant_p (mode)
567*38fd1498Szrj 	  ? mode_unit_size_inline (mode) : mode_unit_size[mode]);
568*38fd1498Szrj #else
569*38fd1498Szrj   return mode_unit_size[mode];
570*38fd1498Szrj #endif
571*38fd1498Szrj }
572*38fd1498Szrj 
573*38fd1498Szrj /* Return the base GET_MODE_UNIT_PRECISION value for MODE.  */
574*38fd1498Szrj 
575*38fd1498Szrj ALWAYS_INLINE unsigned short
576*38fd1498Szrj mode_to_unit_precision (machine_mode mode)
577*38fd1498Szrj {
578*38fd1498Szrj #if GCC_VERSION >= 4001
579*38fd1498Szrj   return (__builtin_constant_p (mode)
580*38fd1498Szrj 	  ? mode_unit_precision_inline (mode) : mode_unit_precision[mode]);
581*38fd1498Szrj #else
582*38fd1498Szrj   return mode_unit_precision[mode];
583*38fd1498Szrj #endif
584*38fd1498Szrj }
585*38fd1498Szrj 
586*38fd1498Szrj /* Return the base GET_MODE_NUNITS value for MODE.  */
587*38fd1498Szrj 
588*38fd1498Szrj ALWAYS_INLINE poly_uint16
589*38fd1498Szrj mode_to_nunits (machine_mode mode)
590*38fd1498Szrj {
591*38fd1498Szrj #if GCC_VERSION >= 4001
592*38fd1498Szrj   return (__builtin_constant_p (mode)
593*38fd1498Szrj 	  ? mode_nunits_inline (mode) : mode_nunits[mode]);
594*38fd1498Szrj #else
595*38fd1498Szrj   return mode_nunits[mode];
596*38fd1498Szrj #endif
597*38fd1498Szrj }
598*38fd1498Szrj 
599*38fd1498Szrj /* Get the size in bytes of an object of mode MODE.  */
600*38fd1498Szrj 
601*38fd1498Szrj #if ONLY_FIXED_SIZE_MODES
602*38fd1498Szrj #define GET_MODE_SIZE(MODE) ((unsigned short) mode_to_bytes (MODE).coeffs[0])
603*38fd1498Szrj #else
604*38fd1498Szrj ALWAYS_INLINE poly_uint16
605*38fd1498Szrj GET_MODE_SIZE (machine_mode mode)
606*38fd1498Szrj {
607*38fd1498Szrj   return mode_to_bytes (mode);
608*38fd1498Szrj }
609*38fd1498Szrj 
610*38fd1498Szrj template<typename T>
611*38fd1498Szrj ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
612*38fd1498Szrj GET_MODE_SIZE (const T &mode)
613*38fd1498Szrj {
614*38fd1498Szrj   return mode_to_bytes (mode);
615*38fd1498Szrj }
616*38fd1498Szrj 
617*38fd1498Szrj template<typename T>
618*38fd1498Szrj ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
619*38fd1498Szrj GET_MODE_SIZE (const T &mode)
620*38fd1498Szrj {
621*38fd1498Szrj   return mode_to_bytes (mode).coeffs[0];
622*38fd1498Szrj }
623*38fd1498Szrj #endif
624*38fd1498Szrj 
625*38fd1498Szrj /* Get the size in bits of an object of mode MODE.  */
626*38fd1498Szrj 
627*38fd1498Szrj #if ONLY_FIXED_SIZE_MODES
628*38fd1498Szrj #define GET_MODE_BITSIZE(MODE) ((unsigned short) mode_to_bits (MODE).coeffs[0])
629*38fd1498Szrj #else
630*38fd1498Szrj ALWAYS_INLINE poly_uint16
631*38fd1498Szrj GET_MODE_BITSIZE (machine_mode mode)
632*38fd1498Szrj {
633*38fd1498Szrj   return mode_to_bits (mode);
634*38fd1498Szrj }
635*38fd1498Szrj 
636*38fd1498Szrj template<typename T>
637*38fd1498Szrj ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
638*38fd1498Szrj GET_MODE_BITSIZE (const T &mode)
639*38fd1498Szrj {
640*38fd1498Szrj   return mode_to_bits (mode);
641*38fd1498Szrj }
642*38fd1498Szrj 
643*38fd1498Szrj template<typename T>
644*38fd1498Szrj ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
645*38fd1498Szrj GET_MODE_BITSIZE (const T &mode)
646*38fd1498Szrj {
647*38fd1498Szrj   return mode_to_bits (mode).coeffs[0];
648*38fd1498Szrj }
649*38fd1498Szrj #endif
650*38fd1498Szrj 
651*38fd1498Szrj /* Get the number of value bits of an object of mode MODE.  */
652*38fd1498Szrj 
653*38fd1498Szrj #if ONLY_FIXED_SIZE_MODES
654*38fd1498Szrj #define GET_MODE_PRECISION(MODE) \
655*38fd1498Szrj   ((unsigned short) mode_to_precision (MODE).coeffs[0])
656*38fd1498Szrj #else
657*38fd1498Szrj ALWAYS_INLINE poly_uint16
658*38fd1498Szrj GET_MODE_PRECISION (machine_mode mode)
659*38fd1498Szrj {
660*38fd1498Szrj   return mode_to_precision (mode);
661*38fd1498Szrj }
662*38fd1498Szrj 
663*38fd1498Szrj template<typename T>
664*38fd1498Szrj ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
665*38fd1498Szrj GET_MODE_PRECISION (const T &mode)
666*38fd1498Szrj {
667*38fd1498Szrj   return mode_to_precision (mode);
668*38fd1498Szrj }
669*38fd1498Szrj 
670*38fd1498Szrj template<typename T>
671*38fd1498Szrj ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
672*38fd1498Szrj GET_MODE_PRECISION (const T &mode)
673*38fd1498Szrj {
674*38fd1498Szrj   return mode_to_precision (mode).coeffs[0];
675*38fd1498Szrj }
676*38fd1498Szrj #endif
677*38fd1498Szrj 
678*38fd1498Szrj /* Get the number of integral bits of an object of mode MODE.  */
679*38fd1498Szrj extern CONST_MODE_IBIT unsigned char mode_ibit[NUM_MACHINE_MODES];
680*38fd1498Szrj #define GET_MODE_IBIT(MODE) mode_ibit[MODE]
681*38fd1498Szrj 
682*38fd1498Szrj /* Get the number of fractional bits of an object of mode MODE.  */
683*38fd1498Szrj extern CONST_MODE_FBIT unsigned char mode_fbit[NUM_MACHINE_MODES];
684*38fd1498Szrj #define GET_MODE_FBIT(MODE) mode_fbit[MODE]
685*38fd1498Szrj 
686*38fd1498Szrj /* Get a bitmask containing 1 for all bits in a word
687*38fd1498Szrj    that fit within mode MODE.  */
688*38fd1498Szrj 
689*38fd1498Szrj extern const unsigned HOST_WIDE_INT mode_mask_array[NUM_MACHINE_MODES];
690*38fd1498Szrj 
691*38fd1498Szrj #define GET_MODE_MASK(MODE) mode_mask_array[MODE]
692*38fd1498Szrj 
693*38fd1498Szrj /* Return the mode of the basic parts of MODE.  For vector modes this is the
694*38fd1498Szrj    mode of the vector elements.  For complex modes it is the mode of the real
695*38fd1498Szrj    and imaginary parts.  For other modes it is MODE itself.  */
696*38fd1498Szrj 
697*38fd1498Szrj #define GET_MODE_INNER(MODE) (mode_to_inner (MODE))
698*38fd1498Szrj 
699*38fd1498Szrj /* Get the size in bytes or bits of the basic parts of an
700*38fd1498Szrj    object of mode MODE.  */
701*38fd1498Szrj 
702*38fd1498Szrj #define GET_MODE_UNIT_SIZE(MODE) mode_to_unit_size (MODE)
703*38fd1498Szrj 
704*38fd1498Szrj #define GET_MODE_UNIT_BITSIZE(MODE) \
705*38fd1498Szrj   ((unsigned short) (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT))
706*38fd1498Szrj 
707*38fd1498Szrj #define GET_MODE_UNIT_PRECISION(MODE) (mode_to_unit_precision (MODE))
708*38fd1498Szrj 
709*38fd1498Szrj /* Get the number of units in an object of mode MODE.  This is 2 for
710*38fd1498Szrj    complex modes and the number of elements for vector modes.  */
711*38fd1498Szrj 
712*38fd1498Szrj #if ONLY_FIXED_SIZE_MODES
713*38fd1498Szrj #define GET_MODE_NUNITS(MODE) (mode_to_nunits (MODE).coeffs[0])
714*38fd1498Szrj #else
715*38fd1498Szrj ALWAYS_INLINE poly_uint16
716*38fd1498Szrj GET_MODE_NUNITS (machine_mode mode)
717*38fd1498Szrj {
718*38fd1498Szrj   return mode_to_nunits (mode);
719*38fd1498Szrj }
720*38fd1498Szrj 
721*38fd1498Szrj template<typename T>
722*38fd1498Szrj ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
723*38fd1498Szrj GET_MODE_NUNITS (const T &mode)
724*38fd1498Szrj {
725*38fd1498Szrj   return mode_to_nunits (mode);
726*38fd1498Szrj }
727*38fd1498Szrj 
728*38fd1498Szrj template<typename T>
729*38fd1498Szrj ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
730*38fd1498Szrj GET_MODE_NUNITS (const T &mode)
731*38fd1498Szrj {
732*38fd1498Szrj   return mode_to_nunits (mode).coeffs[0];
733*38fd1498Szrj }
734*38fd1498Szrj #endif
735*38fd1498Szrj 
736*38fd1498Szrj /* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI).  */
737*38fd1498Szrj 
738*38fd1498Szrj template<typename T>
739*38fd1498Szrj ALWAYS_INLINE opt_mode<T>
740*38fd1498Szrj GET_MODE_WIDER_MODE (const T &m)
741*38fd1498Szrj {
742*38fd1498Szrj   return typename opt_mode<T>::from_int (mode_wider[m]);
743*38fd1498Szrj }
744*38fd1498Szrj 
745*38fd1498Szrj /* For scalars, this is a mode with twice the precision.  For vectors,
746*38fd1498Szrj    this is a mode with the same inner mode but with twice the elements.  */
747*38fd1498Szrj 
748*38fd1498Szrj template<typename T>
749*38fd1498Szrj ALWAYS_INLINE opt_mode<T>
750*38fd1498Szrj GET_MODE_2XWIDER_MODE (const T &m)
751*38fd1498Szrj {
752*38fd1498Szrj   return typename opt_mode<T>::from_int (mode_2xwider[m]);
753*38fd1498Szrj }
754*38fd1498Szrj 
755*38fd1498Szrj /* Get the complex mode from the component mode.  */
756*38fd1498Szrj extern const unsigned char mode_complex[NUM_MACHINE_MODES];
757*38fd1498Szrj #define GET_MODE_COMPLEX_MODE(MODE) ((machine_mode) mode_complex[MODE])
758*38fd1498Szrj 
759*38fd1498Szrj /* Represents a machine mode that must have a fixed size.  The main
760*38fd1498Szrj    use of this class is to represent the modes of objects that always
761*38fd1498Szrj    have static storage duration, such as constant pool entries.
762*38fd1498Szrj    (No current target supports the concept of variable-size static data.)  */
763*38fd1498Szrj class fixed_size_mode
764*38fd1498Szrj {
765*38fd1498Szrj public:
766*38fd1498Szrj   typedef mode_traits<fixed_size_mode>::from_int from_int;
767*38fd1498Szrj   typedef unsigned short measurement_type;
768*38fd1498Szrj 
769*38fd1498Szrj   ALWAYS_INLINE fixed_size_mode () {}
770*38fd1498Szrj   ALWAYS_INLINE fixed_size_mode (from_int m) : m_mode (machine_mode (m)) {}
771*38fd1498Szrj   ALWAYS_INLINE fixed_size_mode (const scalar_mode &m) : m_mode (m) {}
772*38fd1498Szrj   ALWAYS_INLINE fixed_size_mode (const scalar_int_mode &m) : m_mode (m) {}
773*38fd1498Szrj   ALWAYS_INLINE fixed_size_mode (const scalar_float_mode &m) : m_mode (m) {}
774*38fd1498Szrj   ALWAYS_INLINE fixed_size_mode (const scalar_mode_pod &m) : m_mode (m) {}
775*38fd1498Szrj   ALWAYS_INLINE fixed_size_mode (const scalar_int_mode_pod &m) : m_mode (m) {}
776*38fd1498Szrj   ALWAYS_INLINE fixed_size_mode (const complex_mode &m) : m_mode (m) {}
777*38fd1498Szrj   ALWAYS_INLINE operator machine_mode () const { return m_mode; }
778*38fd1498Szrj 
779*38fd1498Szrj   static bool includes_p (machine_mode);
780*38fd1498Szrj 
781*38fd1498Szrj protected:
782*38fd1498Szrj   machine_mode m_mode;
783*38fd1498Szrj };
784*38fd1498Szrj 
785*38fd1498Szrj /* Return true if MODE has a fixed size.  */
786*38fd1498Szrj 
787*38fd1498Szrj inline bool
788*38fd1498Szrj fixed_size_mode::includes_p (machine_mode mode)
789*38fd1498Szrj {
790*38fd1498Szrj   return mode_to_bytes (mode).is_constant ();
791*38fd1498Szrj }
792*38fd1498Szrj 
793*38fd1498Szrj /* Wrapper for mode arguments to target macros, so that if a target
794*38fd1498Szrj    doesn't need polynomial-sized modes, its header file can continue
795*38fd1498Szrj    to treat everything as fixed_size_mode.  This should go away once
796*38fd1498Szrj    macros are moved to target hooks.  It shouldn't be used in other
797*38fd1498Szrj    contexts.  */
798*38fd1498Szrj #if NUM_POLY_INT_COEFFS == 1
799*38fd1498Szrj #define MACRO_MODE(MODE) (as_a <fixed_size_mode> (MODE))
800*38fd1498Szrj #else
801*38fd1498Szrj #define MACRO_MODE(MODE) (MODE)
802*38fd1498Szrj #endif
803*38fd1498Szrj 
804*38fd1498Szrj extern opt_machine_mode mode_for_size (poly_uint64, enum mode_class, int);
805*38fd1498Szrj 
806*38fd1498Szrj /* Return the machine mode to use for a MODE_INT of SIZE bits, if one
807*38fd1498Szrj    exists.  If LIMIT is nonzero, modes wider than MAX_FIXED_MODE_SIZE
808*38fd1498Szrj    will not be used.  */
809*38fd1498Szrj 
810*38fd1498Szrj inline opt_scalar_int_mode
811*38fd1498Szrj int_mode_for_size (poly_uint64 size, int limit)
812*38fd1498Szrj {
813*38fd1498Szrj   return dyn_cast <scalar_int_mode> (mode_for_size (size, MODE_INT, limit));
814*38fd1498Szrj }
815*38fd1498Szrj 
816*38fd1498Szrj /* Return the machine mode to use for a MODE_FLOAT of SIZE bits, if one
817*38fd1498Szrj    exists.  */
818*38fd1498Szrj 
819*38fd1498Szrj inline opt_scalar_float_mode
820*38fd1498Szrj float_mode_for_size (poly_uint64 size)
821*38fd1498Szrj {
822*38fd1498Szrj   return dyn_cast <scalar_float_mode> (mode_for_size (size, MODE_FLOAT, 0));
823*38fd1498Szrj }
824*38fd1498Szrj 
825*38fd1498Szrj /* Likewise for MODE_DECIMAL_FLOAT.  */
826*38fd1498Szrj 
827*38fd1498Szrj inline opt_scalar_float_mode
828*38fd1498Szrj decimal_float_mode_for_size (unsigned int size)
829*38fd1498Szrj {
830*38fd1498Szrj   return dyn_cast <scalar_float_mode>
831*38fd1498Szrj     (mode_for_size (size, MODE_DECIMAL_FLOAT, 0));
832*38fd1498Szrj }
833*38fd1498Szrj 
834*38fd1498Szrj extern machine_mode smallest_mode_for_size (poly_uint64, enum mode_class);
835*38fd1498Szrj 
836*38fd1498Szrj /* Find the narrowest integer mode that contains at least SIZE bits.
837*38fd1498Szrj    Such a mode must exist.  */
838*38fd1498Szrj 
839*38fd1498Szrj inline scalar_int_mode
840*38fd1498Szrj smallest_int_mode_for_size (poly_uint64 size)
841*38fd1498Szrj {
842*38fd1498Szrj   return as_a <scalar_int_mode> (smallest_mode_for_size (size, MODE_INT));
843*38fd1498Szrj }
844*38fd1498Szrj 
845*38fd1498Szrj extern opt_scalar_int_mode int_mode_for_mode (machine_mode);
846*38fd1498Szrj extern opt_machine_mode bitwise_mode_for_mode (machine_mode);
847*38fd1498Szrj extern opt_machine_mode mode_for_vector (scalar_mode, poly_uint64);
848*38fd1498Szrj extern opt_machine_mode mode_for_int_vector (unsigned int, poly_uint64);
849*38fd1498Szrj 
850*38fd1498Szrj /* Return the integer vector equivalent of MODE, if one exists.  In other
851*38fd1498Szrj    words, return the mode for an integer vector that has the same number
852*38fd1498Szrj    of bits as MODE and the same number of elements as MODE, with the
853*38fd1498Szrj    latter being 1 if MODE is scalar.  The returned mode can be either
854*38fd1498Szrj    an integer mode or a vector mode.  */
855*38fd1498Szrj 
856*38fd1498Szrj inline opt_machine_mode
857*38fd1498Szrj mode_for_int_vector (machine_mode mode)
858*38fd1498Szrj {
859*38fd1498Szrj   return mode_for_int_vector (GET_MODE_UNIT_BITSIZE (mode),
860*38fd1498Szrj 			      GET_MODE_NUNITS (mode));
861*38fd1498Szrj }
862*38fd1498Szrj 
863*38fd1498Szrj /* A class for iterating through possible bitfield modes.  */
864*38fd1498Szrj class bit_field_mode_iterator
865*38fd1498Szrj {
866*38fd1498Szrj public:
867*38fd1498Szrj   bit_field_mode_iterator (HOST_WIDE_INT, HOST_WIDE_INT,
868*38fd1498Szrj 			   poly_int64, poly_int64,
869*38fd1498Szrj 			   unsigned int, bool);
870*38fd1498Szrj   bool next_mode (scalar_int_mode *);
871*38fd1498Szrj   bool prefer_smaller_modes ();
872*38fd1498Szrj 
873*38fd1498Szrj private:
874*38fd1498Szrj   opt_scalar_int_mode m_mode;
875*38fd1498Szrj   /* We use signed values here because the bit position can be negative
876*38fd1498Szrj      for invalid input such as gcc.dg/pr48335-8.c.  */
877*38fd1498Szrj   HOST_WIDE_INT m_bitsize;
878*38fd1498Szrj   HOST_WIDE_INT m_bitpos;
879*38fd1498Szrj   poly_int64 m_bitregion_start;
880*38fd1498Szrj   poly_int64 m_bitregion_end;
881*38fd1498Szrj   unsigned int m_align;
882*38fd1498Szrj   bool m_volatilep;
883*38fd1498Szrj   int m_count;
884*38fd1498Szrj };
885*38fd1498Szrj 
886*38fd1498Szrj /* Find the best mode to use to access a bit field.  */
887*38fd1498Szrj 
888*38fd1498Szrj extern bool get_best_mode (int, int, poly_uint64, poly_uint64, unsigned int,
889*38fd1498Szrj 			   unsigned HOST_WIDE_INT, bool, scalar_int_mode *);
890*38fd1498Szrj 
891*38fd1498Szrj /* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT.  */
892*38fd1498Szrj 
893*38fd1498Szrj extern CONST_MODE_BASE_ALIGN unsigned short mode_base_align[NUM_MACHINE_MODES];
894*38fd1498Szrj 
895*38fd1498Szrj extern unsigned get_mode_alignment (machine_mode);
896*38fd1498Szrj 
897*38fd1498Szrj #define GET_MODE_ALIGNMENT(MODE) get_mode_alignment (MODE)
898*38fd1498Szrj 
899*38fd1498Szrj /* For each class, get the narrowest mode in that class.  */
900*38fd1498Szrj 
901*38fd1498Szrj extern const unsigned char class_narrowest_mode[MAX_MODE_CLASS];
902*38fd1498Szrj #define GET_CLASS_NARROWEST_MODE(CLASS) \
903*38fd1498Szrj   ((machine_mode) class_narrowest_mode[CLASS])
904*38fd1498Szrj 
905*38fd1498Szrj /* The narrowest full integer mode available on the target.  */
906*38fd1498Szrj 
907*38fd1498Szrj #define NARROWEST_INT_MODE \
908*38fd1498Szrj   (scalar_int_mode \
909*38fd1498Szrj    (scalar_int_mode::from_int (class_narrowest_mode[MODE_INT])))
910*38fd1498Szrj 
911*38fd1498Szrj /* Return the narrowest mode in T's class.  */
912*38fd1498Szrj 
913*38fd1498Szrj template<typename T>
914*38fd1498Szrj inline T
915*38fd1498Szrj get_narrowest_mode (T mode)
916*38fd1498Szrj {
917*38fd1498Szrj   return typename mode_traits<T>::from_int
918*38fd1498Szrj     (class_narrowest_mode[GET_MODE_CLASS (mode)]);
919*38fd1498Szrj }
920*38fd1498Szrj 
921*38fd1498Szrj /* Define the integer modes whose sizes are BITS_PER_UNIT and BITS_PER_WORD
922*38fd1498Szrj    and the mode whose class is Pmode and whose size is POINTER_SIZE.  */
923*38fd1498Szrj 
924*38fd1498Szrj extern scalar_int_mode byte_mode;
925*38fd1498Szrj extern scalar_int_mode word_mode;
926*38fd1498Szrj extern scalar_int_mode ptr_mode;
927*38fd1498Szrj 
928*38fd1498Szrj /* Target-dependent machine mode initialization - in insn-modes.c.  */
929*38fd1498Szrj extern void init_adjust_machine_modes (void);
930*38fd1498Szrj 
931*38fd1498Szrj #define TRULY_NOOP_TRUNCATION_MODES_P(MODE1, MODE2) \
932*38fd1498Szrj   (targetm.truly_noop_truncation (GET_MODE_PRECISION (MODE1), \
933*38fd1498Szrj 				  GET_MODE_PRECISION (MODE2)))
934*38fd1498Szrj 
935*38fd1498Szrj /* Return true if MODE is a scalar integer mode that fits in a
936*38fd1498Szrj    HOST_WIDE_INT.  */
937*38fd1498Szrj 
938*38fd1498Szrj inline bool
939*38fd1498Szrj HWI_COMPUTABLE_MODE_P (machine_mode mode)
940*38fd1498Szrj {
941*38fd1498Szrj   machine_mode mme = mode;
942*38fd1498Szrj   return (SCALAR_INT_MODE_P (mme)
943*38fd1498Szrj 	  && mode_to_precision (mme).coeffs[0] <= HOST_BITS_PER_WIDE_INT);
944*38fd1498Szrj }
945*38fd1498Szrj 
946*38fd1498Szrj inline bool
947*38fd1498Szrj HWI_COMPUTABLE_MODE_P (scalar_int_mode mode)
948*38fd1498Szrj {
949*38fd1498Szrj   return GET_MODE_PRECISION (mode) <= HOST_BITS_PER_WIDE_INT;
950*38fd1498Szrj }
951*38fd1498Szrj 
952*38fd1498Szrj struct int_n_data_t {
953*38fd1498Szrj   /* These parts are initailized by genmodes output */
954*38fd1498Szrj   unsigned int bitsize;
955*38fd1498Szrj   scalar_int_mode_pod m;
956*38fd1498Szrj   /* RID_* is RID_INTN_BASE + index into this array */
957*38fd1498Szrj };
958*38fd1498Szrj 
959*38fd1498Szrj /* This is also in tree.h.  genmodes.c guarantees the're sorted from
960*38fd1498Szrj    smallest bitsize to largest bitsize. */
961*38fd1498Szrj extern bool int_n_enabled_p[NUM_INT_N_ENTS];
962*38fd1498Szrj extern const int_n_data_t int_n_data[NUM_INT_N_ENTS];
963*38fd1498Szrj 
964*38fd1498Szrj /* Return true if MODE has class MODE_INT, storing it as a scalar_int_mode
965*38fd1498Szrj    in *INT_MODE if so.  */
966*38fd1498Szrj 
967*38fd1498Szrj template<typename T>
968*38fd1498Szrj inline bool
969*38fd1498Szrj is_int_mode (machine_mode mode, T *int_mode)
970*38fd1498Szrj {
971*38fd1498Szrj   if (GET_MODE_CLASS (mode) == MODE_INT)
972*38fd1498Szrj     {
973*38fd1498Szrj       *int_mode = scalar_int_mode (scalar_int_mode::from_int (mode));
974*38fd1498Szrj       return true;
975*38fd1498Szrj     }
976*38fd1498Szrj   return false;
977*38fd1498Szrj }
978*38fd1498Szrj 
979*38fd1498Szrj /* Return true if MODE has class MODE_FLOAT, storing it as a
980*38fd1498Szrj    scalar_float_mode in *FLOAT_MODE if so.  */
981*38fd1498Szrj 
982*38fd1498Szrj template<typename T>
983*38fd1498Szrj inline bool
984*38fd1498Szrj is_float_mode (machine_mode mode, T *float_mode)
985*38fd1498Szrj {
986*38fd1498Szrj   if (GET_MODE_CLASS (mode) == MODE_FLOAT)
987*38fd1498Szrj     {
988*38fd1498Szrj       *float_mode = scalar_float_mode (scalar_float_mode::from_int (mode));
989*38fd1498Szrj       return true;
990*38fd1498Szrj     }
991*38fd1498Szrj   return false;
992*38fd1498Szrj }
993*38fd1498Szrj 
994*38fd1498Szrj /* Return true if MODE has class MODE_COMPLEX_INT, storing it as
995*38fd1498Szrj    a complex_mode in *CMODE if so.  */
996*38fd1498Szrj 
997*38fd1498Szrj template<typename T>
998*38fd1498Szrj inline bool
999*38fd1498Szrj is_complex_int_mode (machine_mode mode, T *cmode)
1000*38fd1498Szrj {
1001*38fd1498Szrj   if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
1002*38fd1498Szrj     {
1003*38fd1498Szrj       *cmode = complex_mode (complex_mode::from_int (mode));
1004*38fd1498Szrj       return true;
1005*38fd1498Szrj     }
1006*38fd1498Szrj   return false;
1007*38fd1498Szrj }
1008*38fd1498Szrj 
1009*38fd1498Szrj /* Return true if MODE has class MODE_COMPLEX_FLOAT, storing it as
1010*38fd1498Szrj    a complex_mode in *CMODE if so.  */
1011*38fd1498Szrj 
1012*38fd1498Szrj template<typename T>
1013*38fd1498Szrj inline bool
1014*38fd1498Szrj is_complex_float_mode (machine_mode mode, T *cmode)
1015*38fd1498Szrj {
1016*38fd1498Szrj   if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
1017*38fd1498Szrj     {
1018*38fd1498Szrj       *cmode = complex_mode (complex_mode::from_int (mode));
1019*38fd1498Szrj       return true;
1020*38fd1498Szrj     }
1021*38fd1498Szrj   return false;
1022*38fd1498Szrj }
1023*38fd1498Szrj 
1024*38fd1498Szrj /* Return true if MODE is a scalar integer mode with a precision
1025*38fd1498Szrj    smaller than LIMIT's precision.  */
1026*38fd1498Szrj 
1027*38fd1498Szrj inline bool
1028*38fd1498Szrj is_narrower_int_mode (machine_mode mode, scalar_int_mode limit)
1029*38fd1498Szrj {
1030*38fd1498Szrj   scalar_int_mode int_mode;
1031*38fd1498Szrj   return (is_a <scalar_int_mode> (mode, &int_mode)
1032*38fd1498Szrj 	  && GET_MODE_PRECISION (int_mode) < GET_MODE_PRECISION (limit));
1033*38fd1498Szrj }
1034*38fd1498Szrj 
1035*38fd1498Szrj namespace mode_iterator
1036*38fd1498Szrj {
1037*38fd1498Szrj   /* Start mode iterator *ITER at the first mode in class MCLASS, if any.  */
1038*38fd1498Szrj 
1039*38fd1498Szrj   template<typename T>
1040*38fd1498Szrj   inline void
1041*38fd1498Szrj   start (opt_mode<T> *iter, enum mode_class mclass)
1042*38fd1498Szrj   {
1043*38fd1498Szrj     if (GET_CLASS_NARROWEST_MODE (mclass) == E_VOIDmode)
1044*38fd1498Szrj       *iter = opt_mode<T> ();
1045*38fd1498Szrj     else
1046*38fd1498Szrj       *iter = as_a<T> (GET_CLASS_NARROWEST_MODE (mclass));
1047*38fd1498Szrj   }
1048*38fd1498Szrj 
1049*38fd1498Szrj   inline void
1050*38fd1498Szrj   start (machine_mode *iter, enum mode_class mclass)
1051*38fd1498Szrj   {
1052*38fd1498Szrj     *iter = GET_CLASS_NARROWEST_MODE (mclass);
1053*38fd1498Szrj   }
1054*38fd1498Szrj 
1055*38fd1498Szrj   /* Return true if mode iterator *ITER has not reached the end.  */
1056*38fd1498Szrj 
1057*38fd1498Szrj   template<typename T>
1058*38fd1498Szrj   inline bool
1059*38fd1498Szrj   iterate_p (opt_mode<T> *iter)
1060*38fd1498Szrj   {
1061*38fd1498Szrj     return iter->exists ();
1062*38fd1498Szrj   }
1063*38fd1498Szrj 
1064*38fd1498Szrj   inline bool
1065*38fd1498Szrj   iterate_p (machine_mode *iter)
1066*38fd1498Szrj   {
1067*38fd1498Szrj     return *iter != E_VOIDmode;
1068*38fd1498Szrj   }
1069*38fd1498Szrj 
1070*38fd1498Szrj   /* Set mode iterator *ITER to the next widest mode in the same class,
1071*38fd1498Szrj      if any.  */
1072*38fd1498Szrj 
1073*38fd1498Szrj   template<typename T>
1074*38fd1498Szrj   inline void
1075*38fd1498Szrj   get_wider (opt_mode<T> *iter)
1076*38fd1498Szrj   {
1077*38fd1498Szrj     *iter = GET_MODE_WIDER_MODE (iter->require ());
1078*38fd1498Szrj   }
1079*38fd1498Szrj 
1080*38fd1498Szrj   inline void
1081*38fd1498Szrj   get_wider (machine_mode *iter)
1082*38fd1498Szrj   {
1083*38fd1498Szrj     *iter = GET_MODE_WIDER_MODE (*iter).else_void ();
1084*38fd1498Szrj   }
1085*38fd1498Szrj 
1086*38fd1498Szrj   /* Set mode iterator *ITER to the next widest mode in the same class.
1087*38fd1498Szrj      Such a mode is known to exist.  */
1088*38fd1498Szrj 
1089*38fd1498Szrj   template<typename T>
1090*38fd1498Szrj   inline void
1091*38fd1498Szrj   get_known_wider (T *iter)
1092*38fd1498Szrj   {
1093*38fd1498Szrj     *iter = GET_MODE_WIDER_MODE (*iter).require ();
1094*38fd1498Szrj   }
1095*38fd1498Szrj 
1096*38fd1498Szrj   /* Set mode iterator *ITER to the mode that is two times wider than the
1097*38fd1498Szrj      current one, if such a mode exists.  */
1098*38fd1498Szrj 
1099*38fd1498Szrj   template<typename T>
1100*38fd1498Szrj   inline void
1101*38fd1498Szrj   get_2xwider (opt_mode<T> *iter)
1102*38fd1498Szrj   {
1103*38fd1498Szrj     *iter = GET_MODE_2XWIDER_MODE (iter->require ());
1104*38fd1498Szrj   }
1105*38fd1498Szrj 
1106*38fd1498Szrj   inline void
1107*38fd1498Szrj   get_2xwider (machine_mode *iter)
1108*38fd1498Szrj   {
1109*38fd1498Szrj     *iter = GET_MODE_2XWIDER_MODE (*iter).else_void ();
1110*38fd1498Szrj   }
1111*38fd1498Szrj }
1112*38fd1498Szrj 
1113*38fd1498Szrj /* Make ITERATOR iterate over all the modes in mode class CLASS,
1114*38fd1498Szrj    from narrowest to widest.  */
1115*38fd1498Szrj #define FOR_EACH_MODE_IN_CLASS(ITERATOR, CLASS)  \
1116*38fd1498Szrj   for (mode_iterator::start (&(ITERATOR), CLASS); \
1117*38fd1498Szrj        mode_iterator::iterate_p (&(ITERATOR)); \
1118*38fd1498Szrj        mode_iterator::get_wider (&(ITERATOR)))
1119*38fd1498Szrj 
1120*38fd1498Szrj /* Make ITERATOR iterate over all the modes in the range [START, END),
1121*38fd1498Szrj    in order of increasing width.  */
1122*38fd1498Szrj #define FOR_EACH_MODE(ITERATOR, START, END) \
1123*38fd1498Szrj   for ((ITERATOR) = (START); \
1124*38fd1498Szrj        (ITERATOR) != (END); \
1125*38fd1498Szrj        mode_iterator::get_known_wider (&(ITERATOR)))
1126*38fd1498Szrj 
1127*38fd1498Szrj /* Make ITERATOR iterate over START and all wider modes in the same
1128*38fd1498Szrj    class, in order of increasing width.  */
1129*38fd1498Szrj #define FOR_EACH_MODE_FROM(ITERATOR, START) \
1130*38fd1498Szrj   for ((ITERATOR) = (START); \
1131*38fd1498Szrj        mode_iterator::iterate_p (&(ITERATOR)); \
1132*38fd1498Szrj        mode_iterator::get_wider (&(ITERATOR)))
1133*38fd1498Szrj 
1134*38fd1498Szrj /* Make ITERATOR iterate over modes in the range [NARROWEST, END)
1135*38fd1498Szrj    in order of increasing width, where NARROWEST is the narrowest mode
1136*38fd1498Szrj    in END's class.  */
1137*38fd1498Szrj #define FOR_EACH_MODE_UNTIL(ITERATOR, END) \
1138*38fd1498Szrj   FOR_EACH_MODE (ITERATOR, get_narrowest_mode (END), END)
1139*38fd1498Szrj 
1140*38fd1498Szrj /* Make ITERATOR iterate over modes in the same class as MODE, in order
1141*38fd1498Szrj    of increasing width.  Start at the first mode wider than START,
1142*38fd1498Szrj    or don't iterate at all if there is no wider mode.  */
1143*38fd1498Szrj #define FOR_EACH_WIDER_MODE(ITERATOR, START) \
1144*38fd1498Szrj   for ((ITERATOR) = (START), mode_iterator::get_wider (&(ITERATOR)); \
1145*38fd1498Szrj        mode_iterator::iterate_p (&(ITERATOR)); \
1146*38fd1498Szrj        mode_iterator::get_wider (&(ITERATOR)))
1147*38fd1498Szrj 
1148*38fd1498Szrj /* Make ITERATOR iterate over modes in the same class as MODE, in order
1149*38fd1498Szrj    of increasing width, and with each mode being twice the width of the
1150*38fd1498Szrj    previous mode.  Start at the mode that is two times wider than START,
1151*38fd1498Szrj    or don't iterate at all if there is no such mode.  */
1152*38fd1498Szrj #define FOR_EACH_2XWIDER_MODE(ITERATOR, START) \
1153*38fd1498Szrj   for ((ITERATOR) = (START), mode_iterator::get_2xwider (&(ITERATOR)); \
1154*38fd1498Szrj        mode_iterator::iterate_p (&(ITERATOR)); \
1155*38fd1498Szrj        mode_iterator::get_2xwider (&(ITERATOR)))
1156*38fd1498Szrj 
1157*38fd1498Szrj template<typename T>
1158*38fd1498Szrj void
1159*38fd1498Szrj gt_ggc_mx (pod_mode<T> *)
1160*38fd1498Szrj {
1161*38fd1498Szrj }
1162*38fd1498Szrj 
1163*38fd1498Szrj template<typename T>
1164*38fd1498Szrj void
1165*38fd1498Szrj gt_pch_nx (pod_mode<T> *)
1166*38fd1498Szrj {
1167*38fd1498Szrj }
1168*38fd1498Szrj 
1169*38fd1498Szrj template<typename T>
1170*38fd1498Szrj void
1171*38fd1498Szrj gt_pch_nx (pod_mode<T> *, void (*) (void *, void *), void *)
1172*38fd1498Szrj {
1173*38fd1498Szrj }
1174*38fd1498Szrj 
1175*38fd1498Szrj #endif /* not HAVE_MACHINE_MODES */
1176