1265 lines
35 KiB
C
1265 lines
35 KiB
C
|
/* Machine mode definitions for GCC; included by rtl.h and tree.h.
|
||
|
Copyright (C) 1991-2023 Free Software Foundation, Inc.
|
||
|
|
||
|
This file is part of GCC.
|
||
|
|
||
|
GCC is free software; you can redistribute it and/or modify it under
|
||
|
the terms of the GNU General Public License as published by the Free
|
||
|
Software Foundation; either version 3, or (at your option) any later
|
||
|
version.
|
||
|
|
||
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||
|
for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with GCC; see the file COPYING3. If not see
|
||
|
<http://www.gnu.org/licenses/>. */
|
||
|
|
||
|
#ifndef HAVE_MACHINE_MODES
|
||
|
#define HAVE_MACHINE_MODES
|
||
|
|
||
|
typedef opt_mode<machine_mode> opt_machine_mode;
|
||
|
|
||
|
extern CONST_MODE_SIZE poly_uint16_pod mode_size[NUM_MACHINE_MODES];
|
||
|
extern CONST_MODE_PRECISION poly_uint16_pod mode_precision[NUM_MACHINE_MODES];
|
||
|
extern const unsigned char mode_inner[NUM_MACHINE_MODES];
|
||
|
extern CONST_MODE_NUNITS poly_uint16_pod mode_nunits[NUM_MACHINE_MODES];
|
||
|
extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES];
|
||
|
extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];
|
||
|
extern const unsigned char mode_next[NUM_MACHINE_MODES];
|
||
|
extern const unsigned char mode_wider[NUM_MACHINE_MODES];
|
||
|
extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
|
||
|
|
||
|
template<typename T>
|
||
|
struct mode_traits
|
||
|
{
|
||
|
/* For use by the machmode support code only.
|
||
|
|
||
|
There are cases in which the machmode support code needs to forcibly
|
||
|
convert a machine_mode to a specific mode class T, and in which the
|
||
|
context guarantees that this is valid without the need for an assert.
|
||
|
This can be done using:
|
||
|
|
||
|
return typename mode_traits<T>::from_int (mode);
|
||
|
|
||
|
when returning a T and:
|
||
|
|
||
|
res = T (typename mode_traits<T>::from_int (mode));
|
||
|
|
||
|
when assigning to a value RES that must be assignment-compatible
|
||
|
with (but possibly not the same as) T. */
|
||
|
#ifdef USE_ENUM_MODES
|
||
|
/* Allow direct conversion of enums to specific mode classes only
|
||
|
when USE_ENUM_MODES is defined. This is only intended for use
|
||
|
by gencondmd, so that it can tell more easily when .md conditions
|
||
|
are always false. */
|
||
|
typedef machine_mode from_int;
|
||
|
#else
|
||
|
/* Here we use an enum type distinct from machine_mode but with the
|
||
|
same range as machine_mode. T should have a constructor that
|
||
|
accepts this enum type; it should not have a constructor that
|
||
|
accepts machine_mode.
|
||
|
|
||
|
We use this somewhat indirect approach to avoid too many constructor
|
||
|
calls when the compiler is built with -O0. For example, even in
|
||
|
unoptimized code, the return statement above would construct the
|
||
|
returned T directly from the numerical value of MODE. */
|
||
|
enum from_int { dummy = MAX_MACHINE_MODE };
|
||
|
#endif
|
||
|
};
|
||
|
|
||
|
template<>
|
||
|
struct mode_traits<machine_mode>
|
||
|
{
|
||
|
/* machine_mode itself needs no conversion. */
|
||
|
typedef machine_mode from_int;
|
||
|
};
|
||
|
|
||
|
/* Always treat machine modes as fixed-size while compiling code specific
|
||
|
to targets that have no variable-size modes. */
|
||
|
#if defined (IN_TARGET_CODE) && NUM_POLY_INT_COEFFS == 1
|
||
|
#define ONLY_FIXED_SIZE_MODES 1
|
||
|
#else
|
||
|
#define ONLY_FIXED_SIZE_MODES 0
|
||
|
#endif
|
||
|
|
||
|
/* Get the name of mode MODE as a string. */
|
||
|
|
||
|
extern const char * const mode_name[NUM_MACHINE_MODES];
|
||
|
#define GET_MODE_NAME(MODE) mode_name[MODE]
|
||
|
|
||
|
/* Mode classes. */
|
||
|
|
||
|
#include "mode-classes.def"
|
||
|
#define DEF_MODE_CLASS(M) M
|
||
|
enum mode_class { MODE_CLASSES, MAX_MODE_CLASS };
|
||
|
#undef DEF_MODE_CLASS
|
||
|
#undef MODE_CLASSES
|
||
|
|
||
|
/* Get the general kind of object that mode MODE represents
|
||
|
(integer, floating, complex, etc.) */
|
||
|
|
||
|
extern const unsigned char mode_class[NUM_MACHINE_MODES];
|
||
|
#define GET_MODE_CLASS(MODE) ((enum mode_class) mode_class[MODE])
|
||
|
|
||
|
/* Nonzero if MODE is an integral mode. */
|
||
|
#define INTEGRAL_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_INT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_INT)
|
||
|
|
||
|
/* Nonzero if MODE is a floating-point mode. */
|
||
|
#define FLOAT_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT)
|
||
|
|
||
|
/* Nonzero if MODE is a complex mode. */
|
||
|
#define COMPLEX_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_COMPLEX_FLOAT)
|
||
|
|
||
|
/* Nonzero if MODE is a vector mode. */
|
||
|
#define VECTOR_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_VECTOR_BOOL \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_INT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_FLOAT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_FRACT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_UFRACT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_ACCUM \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_UACCUM)
|
||
|
|
||
|
/* Nonzero if MODE is a scalar integral mode. */
|
||
|
#define SCALAR_INT_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_INT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_PARTIAL_INT)
|
||
|
|
||
|
/* Nonzero if MODE is a scalar floating point mode. */
|
||
|
#define SCALAR_FLOAT_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT)
|
||
|
|
||
|
/* Nonzero if MODE is a decimal floating point mode. */
|
||
|
#define DECIMAL_FLOAT_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_DECIMAL_FLOAT)
|
||
|
|
||
|
/* Nonzero if MODE is a scalar fract mode. */
|
||
|
#define SCALAR_FRACT_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_FRACT)
|
||
|
|
||
|
/* Nonzero if MODE is a scalar ufract mode. */
|
||
|
#define SCALAR_UFRACT_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_UFRACT)
|
||
|
|
||
|
/* Nonzero if MODE is a scalar fract or ufract mode. */
|
||
|
#define ALL_SCALAR_FRACT_MODE_P(MODE) \
|
||
|
(SCALAR_FRACT_MODE_P (MODE) || SCALAR_UFRACT_MODE_P (MODE))
|
||
|
|
||
|
/* Nonzero if MODE is a scalar accum mode. */
|
||
|
#define SCALAR_ACCUM_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_ACCUM)
|
||
|
|
||
|
/* Nonzero if MODE is a scalar uaccum mode. */
|
||
|
#define SCALAR_UACCUM_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_UACCUM)
|
||
|
|
||
|
/* Nonzero if MODE is a scalar accum or uaccum mode. */
|
||
|
#define ALL_SCALAR_ACCUM_MODE_P(MODE) \
|
||
|
(SCALAR_ACCUM_MODE_P (MODE) || SCALAR_UACCUM_MODE_P (MODE))
|
||
|
|
||
|
/* Nonzero if MODE is a scalar fract or accum mode. */
|
||
|
#define SIGNED_SCALAR_FIXED_POINT_MODE_P(MODE) \
|
||
|
(SCALAR_FRACT_MODE_P (MODE) || SCALAR_ACCUM_MODE_P (MODE))
|
||
|
|
||
|
/* Nonzero if MODE is a scalar ufract or uaccum mode. */
|
||
|
#define UNSIGNED_SCALAR_FIXED_POINT_MODE_P(MODE) \
|
||
|
(SCALAR_UFRACT_MODE_P (MODE) || SCALAR_UACCUM_MODE_P (MODE))
|
||
|
|
||
|
/* Nonzero if MODE is a scalar fract, ufract, accum or uaccum mode. */
|
||
|
#define ALL_SCALAR_FIXED_POINT_MODE_P(MODE) \
|
||
|
(SIGNED_SCALAR_FIXED_POINT_MODE_P (MODE) \
|
||
|
|| UNSIGNED_SCALAR_FIXED_POINT_MODE_P (MODE))
|
||
|
|
||
|
/* Nonzero if MODE is a scalar/vector fract mode. */
|
||
|
#define FRACT_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_FRACT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_FRACT)
|
||
|
|
||
|
/* Nonzero if MODE is a scalar/vector ufract mode. */
|
||
|
#define UFRACT_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_UFRACT \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_UFRACT)
|
||
|
|
||
|
/* Nonzero if MODE is a scalar/vector fract or ufract mode. */
|
||
|
#define ALL_FRACT_MODE_P(MODE) \
|
||
|
(FRACT_MODE_P (MODE) || UFRACT_MODE_P (MODE))
|
||
|
|
||
|
/* Nonzero if MODE is a scalar/vector accum mode. */
|
||
|
#define ACCUM_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_ACCUM \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_ACCUM)
|
||
|
|
||
|
/* Nonzero if MODE is a scalar/vector uaccum mode. */
|
||
|
#define UACCUM_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_UACCUM \
|
||
|
|| GET_MODE_CLASS (MODE) == MODE_VECTOR_UACCUM)
|
||
|
|
||
|
/* Nonzero if MODE is a scalar/vector accum or uaccum mode. */
|
||
|
#define ALL_ACCUM_MODE_P(MODE) \
|
||
|
(ACCUM_MODE_P (MODE) || UACCUM_MODE_P (MODE))
|
||
|
|
||
|
/* Nonzero if MODE is a scalar/vector fract or accum mode. */
|
||
|
#define SIGNED_FIXED_POINT_MODE_P(MODE) \
|
||
|
(FRACT_MODE_P (MODE) || ACCUM_MODE_P (MODE))
|
||
|
|
||
|
/* Nonzero if MODE is a scalar/vector ufract or uaccum mode. */
|
||
|
#define UNSIGNED_FIXED_POINT_MODE_P(MODE) \
|
||
|
(UFRACT_MODE_P (MODE) || UACCUM_MODE_P (MODE))
|
||
|
|
||
|
/* Nonzero if MODE is a scalar/vector fract, ufract, accum or uaccum mode. */
|
||
|
#define ALL_FIXED_POINT_MODE_P(MODE) \
|
||
|
(SIGNED_FIXED_POINT_MODE_P (MODE) \
|
||
|
|| UNSIGNED_FIXED_POINT_MODE_P (MODE))
|
||
|
|
||
|
/* Nonzero if MODE is opaque. */
|
||
|
#define OPAQUE_MODE_P(MODE) \
|
||
|
(GET_MODE_CLASS (MODE) == MODE_OPAQUE)
|
||
|
|
||
|
/* Nonzero if CLASS modes can be widened. */
|
||
|
#define CLASS_HAS_WIDER_MODES_P(CLASS) \
|
||
|
(CLASS == MODE_INT \
|
||
|
|| CLASS == MODE_PARTIAL_INT \
|
||
|
|| CLASS == MODE_FLOAT \
|
||
|
|| CLASS == MODE_DECIMAL_FLOAT \
|
||
|
|| CLASS == MODE_COMPLEX_FLOAT \
|
||
|
|| CLASS == MODE_FRACT \
|
||
|
|| CLASS == MODE_UFRACT \
|
||
|
|| CLASS == MODE_ACCUM \
|
||
|
|| CLASS == MODE_UACCUM)
|
||
|
|
||
|
/* An optional T (i.e. a T or nothing), where T is some form of mode class. */
|
||
|
template<typename T>
|
||
|
class opt_mode
|
||
|
{
|
||
|
public:
|
||
|
enum from_int { dummy = MAX_MACHINE_MODE };
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR opt_mode () : m_mode (E_VOIDmode) {}
|
||
|
ALWAYS_INLINE CONSTEXPR opt_mode (const T &m) : m_mode (m) {}
|
||
|
template<typename U>
|
||
|
ALWAYS_INLINE CONSTEXPR opt_mode (const U &m) : m_mode (T (m)) {}
|
||
|
ALWAYS_INLINE CONSTEXPR opt_mode (from_int m) : m_mode (machine_mode (m)) {}
|
||
|
|
||
|
machine_mode else_void () const;
|
||
|
machine_mode else_blk () const { return else_mode (BLKmode); }
|
||
|
machine_mode else_mode (machine_mode) const;
|
||
|
T require () const;
|
||
|
|
||
|
bool exists () const;
|
||
|
template<typename U> bool exists (U *) const;
|
||
|
|
||
|
bool operator== (const T &m) const { return m_mode == m; }
|
||
|
bool operator!= (const T &m) const { return m_mode != m; }
|
||
|
|
||
|
private:
|
||
|
machine_mode m_mode;
|
||
|
};
|
||
|
|
||
|
/* If the object contains a T, return its enum value, otherwise return
|
||
|
E_VOIDmode. */
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE machine_mode
|
||
|
opt_mode<T>::else_void () const
|
||
|
{
|
||
|
return m_mode;
|
||
|
}
|
||
|
|
||
|
/* If the T exists, return its enum value, otherwise return FALLBACK. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline machine_mode
|
||
|
opt_mode<T>::else_mode (machine_mode fallback) const
|
||
|
{
|
||
|
return m_mode == E_VOIDmode ? fallback : m_mode;
|
||
|
}
|
||
|
|
||
|
/* Assert that the object contains a T and return it. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline T
|
||
|
opt_mode<T>::require () const
|
||
|
{
|
||
|
gcc_checking_assert (m_mode != E_VOIDmode);
|
||
|
return typename mode_traits<T>::from_int (m_mode);
|
||
|
}
|
||
|
|
||
|
/* Return true if the object contains a T rather than nothing. */
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE bool
|
||
|
opt_mode<T>::exists () const
|
||
|
{
|
||
|
return m_mode != E_VOIDmode;
|
||
|
}
|
||
|
|
||
|
/* Return true if the object contains a T, storing it in *MODE if so. */
|
||
|
|
||
|
template<typename T>
|
||
|
template<typename U>
|
||
|
inline bool
|
||
|
opt_mode<T>::exists (U *mode) const
|
||
|
{
|
||
|
if (m_mode != E_VOIDmode)
|
||
|
{
|
||
|
*mode = T (typename mode_traits<T>::from_int (m_mode));
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* A POD version of mode class T. */
|
||
|
|
||
|
template<typename T>
|
||
|
struct pod_mode
|
||
|
{
|
||
|
typedef typename mode_traits<T>::from_int from_int;
|
||
|
typedef typename T::measurement_type measurement_type;
|
||
|
|
||
|
machine_mode m_mode;
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
operator machine_mode () const { return m_mode; }
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
operator T () const { return from_int (m_mode); }
|
||
|
|
||
|
ALWAYS_INLINE pod_mode &operator = (const T &m) { m_mode = m; return *this; }
|
||
|
};
|
||
|
|
||
|
/* Return true if mode M has type T. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline bool
|
||
|
is_a (machine_mode m)
|
||
|
{
|
||
|
return T::includes_p (m);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename U>
|
||
|
inline bool
|
||
|
is_a (const opt_mode<U> &m)
|
||
|
{
|
||
|
return T::includes_p (m.else_void ());
|
||
|
}
|
||
|
|
||
|
/* Assert that mode M has type T, and return it in that form. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline T
|
||
|
as_a (machine_mode m)
|
||
|
{
|
||
|
gcc_checking_assert (T::includes_p (m));
|
||
|
return typename mode_traits<T>::from_int (m);
|
||
|
}
|
||
|
|
||
|
template<typename T, typename U>
|
||
|
inline T
|
||
|
as_a (const opt_mode<U> &m)
|
||
|
{
|
||
|
return as_a <T> (m.else_void ());
|
||
|
}
|
||
|
|
||
|
/* Convert M to an opt_mode<T>. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline opt_mode<T>
|
||
|
dyn_cast (machine_mode m)
|
||
|
{
|
||
|
if (T::includes_p (m))
|
||
|
return T (typename mode_traits<T>::from_int (m));
|
||
|
return opt_mode<T> ();
|
||
|
}
|
||
|
|
||
|
template<typename T, typename U>
|
||
|
inline opt_mode<T>
|
||
|
dyn_cast (const opt_mode<U> &m)
|
||
|
{
|
||
|
return dyn_cast <T> (m.else_void ());
|
||
|
}
|
||
|
|
||
|
/* Return true if mode M has type T, storing it as a T in *RESULT
|
||
|
if so. */
|
||
|
|
||
|
template<typename T, typename U>
|
||
|
inline bool
|
||
|
is_a (machine_mode m, U *result)
|
||
|
{
|
||
|
if (T::includes_p (m))
|
||
|
{
|
||
|
*result = T (typename mode_traits<T>::from_int (m));
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Represents a machine mode that is known to be a SCALAR_INT_MODE_P. */
|
||
|
class scalar_int_mode
|
||
|
{
|
||
|
public:
|
||
|
typedef mode_traits<scalar_int_mode>::from_int from_int;
|
||
|
typedef unsigned short measurement_type;
|
||
|
|
||
|
ALWAYS_INLINE scalar_int_mode () {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
scalar_int_mode (from_int m) : m_mode (machine_mode (m)) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
|
||
|
|
||
|
static bool includes_p (machine_mode);
|
||
|
|
||
|
protected:
|
||
|
machine_mode m_mode;
|
||
|
};
|
||
|
|
||
|
/* Return true if M is a scalar_int_mode. */
|
||
|
|
||
|
inline bool
|
||
|
scalar_int_mode::includes_p (machine_mode m)
|
||
|
{
|
||
|
return SCALAR_INT_MODE_P (m);
|
||
|
}
|
||
|
|
||
|
/* Represents a machine mode that is known to be a SCALAR_FLOAT_MODE_P. */
|
||
|
class scalar_float_mode
|
||
|
{
|
||
|
public:
|
||
|
typedef mode_traits<scalar_float_mode>::from_int from_int;
|
||
|
typedef unsigned short measurement_type;
|
||
|
|
||
|
ALWAYS_INLINE scalar_float_mode () {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
scalar_float_mode (from_int m) : m_mode (machine_mode (m)) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
|
||
|
|
||
|
static bool includes_p (machine_mode);
|
||
|
|
||
|
protected:
|
||
|
machine_mode m_mode;
|
||
|
};
|
||
|
|
||
|
/* Return true if M is a scalar_float_mode. */
|
||
|
|
||
|
inline bool
|
||
|
scalar_float_mode::includes_p (machine_mode m)
|
||
|
{
|
||
|
return SCALAR_FLOAT_MODE_P (m);
|
||
|
}
|
||
|
|
||
|
/* Represents a machine mode that is known to be scalar. */
|
||
|
class scalar_mode
|
||
|
{
|
||
|
public:
|
||
|
typedef mode_traits<scalar_mode>::from_int from_int;
|
||
|
typedef unsigned short measurement_type;
|
||
|
|
||
|
ALWAYS_INLINE scalar_mode () {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
scalar_mode (from_int m) : m_mode (machine_mode (m)) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
scalar_mode (const scalar_int_mode &m) : m_mode (m) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
scalar_mode (const scalar_float_mode &m) : m_mode (m) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
scalar_mode (const scalar_int_mode_pod &m) : m_mode (m) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
|
||
|
|
||
|
static bool includes_p (machine_mode);
|
||
|
|
||
|
protected:
|
||
|
machine_mode m_mode;
|
||
|
};
|
||
|
|
||
|
/* Return true if M represents some kind of scalar value. */
|
||
|
|
||
|
inline bool
|
||
|
scalar_mode::includes_p (machine_mode m)
|
||
|
{
|
||
|
switch (GET_MODE_CLASS (m))
|
||
|
{
|
||
|
case MODE_INT:
|
||
|
case MODE_PARTIAL_INT:
|
||
|
case MODE_FRACT:
|
||
|
case MODE_UFRACT:
|
||
|
case MODE_ACCUM:
|
||
|
case MODE_UACCUM:
|
||
|
case MODE_FLOAT:
|
||
|
case MODE_DECIMAL_FLOAT:
|
||
|
return true;
|
||
|
default:
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Represents a machine mode that is known to be a COMPLEX_MODE_P. */
|
||
|
class complex_mode
|
||
|
{
|
||
|
public:
|
||
|
typedef mode_traits<complex_mode>::from_int from_int;
|
||
|
typedef unsigned short measurement_type;
|
||
|
|
||
|
ALWAYS_INLINE complex_mode () {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
complex_mode (from_int m) : m_mode (machine_mode (m)) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
|
||
|
|
||
|
static bool includes_p (machine_mode);
|
||
|
|
||
|
protected:
|
||
|
machine_mode m_mode;
|
||
|
};
|
||
|
|
||
|
/* Return true if M is a complex_mode. */
|
||
|
|
||
|
inline bool
|
||
|
complex_mode::includes_p (machine_mode m)
|
||
|
{
|
||
|
return COMPLEX_MODE_P (m);
|
||
|
}
|
||
|
|
||
|
/* Return the base GET_MODE_SIZE value for MODE. */
|
||
|
|
||
|
ALWAYS_INLINE poly_uint16
|
||
|
mode_to_bytes (machine_mode mode)
|
||
|
{
|
||
|
#if GCC_VERSION >= 4001
|
||
|
return (__builtin_constant_p (mode)
|
||
|
? mode_size_inline (mode) : mode_size[mode]);
|
||
|
#else
|
||
|
return mode_size[mode];
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/* Return the base GET_MODE_BITSIZE value for MODE. */
|
||
|
|
||
|
ALWAYS_INLINE poly_uint16
|
||
|
mode_to_bits (machine_mode mode)
|
||
|
{
|
||
|
return mode_to_bytes (mode) * BITS_PER_UNIT;
|
||
|
}
|
||
|
|
||
|
/* Return the base GET_MODE_PRECISION value for MODE. */
|
||
|
|
||
|
ALWAYS_INLINE poly_uint16
|
||
|
mode_to_precision (machine_mode mode)
|
||
|
{
|
||
|
return mode_precision[mode];
|
||
|
}
|
||
|
|
||
|
/* Return the base GET_MODE_INNER value for MODE. */
|
||
|
|
||
|
ALWAYS_INLINE scalar_mode
|
||
|
mode_to_inner (machine_mode mode)
|
||
|
{
|
||
|
#if GCC_VERSION >= 4001
|
||
|
return scalar_mode::from_int (__builtin_constant_p (mode)
|
||
|
? mode_inner_inline (mode)
|
||
|
: mode_inner[mode]);
|
||
|
#else
|
||
|
return scalar_mode::from_int (mode_inner[mode]);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/* Return the base GET_MODE_UNIT_SIZE value for MODE. */
|
||
|
|
||
|
ALWAYS_INLINE unsigned char
|
||
|
mode_to_unit_size (machine_mode mode)
|
||
|
{
|
||
|
#if GCC_VERSION >= 4001
|
||
|
return (__builtin_constant_p (mode)
|
||
|
? mode_unit_size_inline (mode) : mode_unit_size[mode]);
|
||
|
#else
|
||
|
return mode_unit_size[mode];
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/* Return the base GET_MODE_UNIT_PRECISION value for MODE. */
|
||
|
|
||
|
ALWAYS_INLINE unsigned short
|
||
|
mode_to_unit_precision (machine_mode mode)
|
||
|
{
|
||
|
#if GCC_VERSION >= 4001
|
||
|
return (__builtin_constant_p (mode)
|
||
|
? mode_unit_precision_inline (mode) : mode_unit_precision[mode]);
|
||
|
#else
|
||
|
return mode_unit_precision[mode];
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/* Return the base GET_MODE_NUNITS value for MODE. */
|
||
|
|
||
|
ALWAYS_INLINE poly_uint16
|
||
|
mode_to_nunits (machine_mode mode)
|
||
|
{
|
||
|
#if GCC_VERSION >= 4001
|
||
|
return (__builtin_constant_p (mode)
|
||
|
? mode_nunits_inline (mode) : mode_nunits[mode]);
|
||
|
#else
|
||
|
return mode_nunits[mode];
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/* Get the size in bytes of an object of mode MODE. */
|
||
|
|
||
|
#if ONLY_FIXED_SIZE_MODES
|
||
|
#define GET_MODE_SIZE(MODE) ((unsigned short) mode_to_bytes (MODE).coeffs[0])
|
||
|
#else
|
||
|
ALWAYS_INLINE poly_uint16
|
||
|
GET_MODE_SIZE (machine_mode mode)
|
||
|
{
|
||
|
return mode_to_bytes (mode);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
|
||
|
GET_MODE_SIZE (const T &mode)
|
||
|
{
|
||
|
return mode_to_bytes (mode);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
|
||
|
GET_MODE_SIZE (const T &mode)
|
||
|
{
|
||
|
return mode_to_bytes (mode).coeffs[0];
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Get the size in bits of an object of mode MODE. */
|
||
|
|
||
|
#if ONLY_FIXED_SIZE_MODES
|
||
|
#define GET_MODE_BITSIZE(MODE) ((unsigned short) mode_to_bits (MODE).coeffs[0])
|
||
|
#else
|
||
|
ALWAYS_INLINE poly_uint16
|
||
|
GET_MODE_BITSIZE (machine_mode mode)
|
||
|
{
|
||
|
return mode_to_bits (mode);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
|
||
|
GET_MODE_BITSIZE (const T &mode)
|
||
|
{
|
||
|
return mode_to_bits (mode);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
|
||
|
GET_MODE_BITSIZE (const T &mode)
|
||
|
{
|
||
|
return mode_to_bits (mode).coeffs[0];
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Get the number of value bits of an object of mode MODE. */
|
||
|
|
||
|
#if ONLY_FIXED_SIZE_MODES
|
||
|
#define GET_MODE_PRECISION(MODE) \
|
||
|
((unsigned short) mode_to_precision (MODE).coeffs[0])
|
||
|
#else
|
||
|
ALWAYS_INLINE poly_uint16
|
||
|
GET_MODE_PRECISION (machine_mode mode)
|
||
|
{
|
||
|
return mode_to_precision (mode);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
|
||
|
GET_MODE_PRECISION (const T &mode)
|
||
|
{
|
||
|
return mode_to_precision (mode);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
|
||
|
GET_MODE_PRECISION (const T &mode)
|
||
|
{
|
||
|
return mode_to_precision (mode).coeffs[0];
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Get the number of integral bits of an object of mode MODE. */
|
||
|
extern CONST_MODE_IBIT unsigned char mode_ibit[NUM_MACHINE_MODES];
|
||
|
#define GET_MODE_IBIT(MODE) mode_ibit[MODE]
|
||
|
|
||
|
/* Get the number of fractional bits of an object of mode MODE. */
|
||
|
extern CONST_MODE_FBIT unsigned char mode_fbit[NUM_MACHINE_MODES];
|
||
|
#define GET_MODE_FBIT(MODE) mode_fbit[MODE]
|
||
|
|
||
|
/* Get a bitmask containing 1 for all bits in a word
|
||
|
that fit within mode MODE. */
|
||
|
|
||
|
extern CONST_MODE_MASK unsigned HOST_WIDE_INT
|
||
|
mode_mask_array[NUM_MACHINE_MODES];
|
||
|
|
||
|
#define GET_MODE_MASK(MODE) mode_mask_array[MODE]
|
||
|
|
||
|
/* Return the mode of the basic parts of MODE. For vector modes this is the
|
||
|
mode of the vector elements. For complex modes it is the mode of the real
|
||
|
and imaginary parts. For other modes it is MODE itself. */
|
||
|
|
||
|
#define GET_MODE_INNER(MODE) (mode_to_inner (MODE))
|
||
|
|
||
|
/* Get the size in bytes or bits of the basic parts of an
|
||
|
object of mode MODE. */
|
||
|
|
||
|
#define GET_MODE_UNIT_SIZE(MODE) mode_to_unit_size (MODE)
|
||
|
|
||
|
#define GET_MODE_UNIT_BITSIZE(MODE) \
|
||
|
((unsigned short) (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT))
|
||
|
|
||
|
#define GET_MODE_UNIT_PRECISION(MODE) (mode_to_unit_precision (MODE))
|
||
|
|
||
|
/* Get the number of units in an object of mode MODE. This is 2 for
|
||
|
complex modes and the number of elements for vector modes. */
|
||
|
|
||
|
#if ONLY_FIXED_SIZE_MODES
|
||
|
#define GET_MODE_NUNITS(MODE) (mode_to_nunits (MODE).coeffs[0])
|
||
|
#else
|
||
|
ALWAYS_INLINE poly_uint16
|
||
|
GET_MODE_NUNITS (machine_mode mode)
|
||
|
{
|
||
|
return mode_to_nunits (mode);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE typename if_poly<typename T::measurement_type>::type
|
||
|
GET_MODE_NUNITS (const T &mode)
|
||
|
{
|
||
|
return mode_to_nunits (mode);
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE typename if_nonpoly<typename T::measurement_type>::type
|
||
|
GET_MODE_NUNITS (const T &mode)
|
||
|
{
|
||
|
return mode_to_nunits (mode).coeffs[0];
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
/* Get the next natural mode (not narrower, eg, QI -> HI -> SI -> DI -> TI
|
||
|
or HF -> BF -> SF -> DF -> XF -> TF). */
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE opt_mode<T>
|
||
|
GET_MODE_NEXT_MODE (const T &m)
|
||
|
{
|
||
|
return typename opt_mode<T>::from_int (mode_next[m]);
|
||
|
}
|
||
|
|
||
|
/* Get the next wider mode (eg, QI -> HI -> SI -> DI -> TI
|
||
|
or { HF, BF } -> SF -> DF -> XF -> TF).
|
||
|
This is similar to GET_MODE_NEXT_MODE, but while GET_MODE_NEXT_MODE
|
||
|
can include mode that have the same precision (e.g.
|
||
|
GET_MODE_NEXT_MODE (HFmode) can be BFmode even when both have the same
|
||
|
precision), this one will skip those. And always VOIDmode for
|
||
|
modes whose class is !CLASS_HAS_WIDER_MODES_P. */
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE opt_mode<T>
|
||
|
GET_MODE_WIDER_MODE (const T &m)
|
||
|
{
|
||
|
return typename opt_mode<T>::from_int (mode_wider[m]);
|
||
|
}
|
||
|
|
||
|
/* For scalars, this is a mode with twice the precision. For vectors,
|
||
|
this is a mode with the same inner mode but with twice the elements. */
|
||
|
|
||
|
template<typename T>
|
||
|
ALWAYS_INLINE opt_mode<T>
|
||
|
GET_MODE_2XWIDER_MODE (const T &m)
|
||
|
{
|
||
|
return typename opt_mode<T>::from_int (mode_2xwider[m]);
|
||
|
}
|
||
|
|
||
|
/* Get the complex mode from the component mode. */
|
||
|
extern const unsigned char mode_complex[NUM_MACHINE_MODES];
|
||
|
#define GET_MODE_COMPLEX_MODE(MODE) ((machine_mode) mode_complex[MODE])
|
||
|
|
||
|
/* Represents a machine mode that must have a fixed size. The main
|
||
|
use of this class is to represent the modes of objects that always
|
||
|
have static storage duration, such as constant pool entries.
|
||
|
(No current target supports the concept of variable-size static data.) */
|
||
|
class fixed_size_mode
|
||
|
{
|
||
|
public:
|
||
|
typedef mode_traits<fixed_size_mode>::from_int from_int;
|
||
|
typedef unsigned short measurement_type;
|
||
|
|
||
|
ALWAYS_INLINE fixed_size_mode () {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
fixed_size_mode (from_int m) : m_mode (machine_mode (m)) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
fixed_size_mode (const scalar_mode &m) : m_mode (m) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
fixed_size_mode (const scalar_int_mode &m) : m_mode (m) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
fixed_size_mode (const scalar_float_mode &m) : m_mode (m) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
fixed_size_mode (const scalar_mode_pod &m) : m_mode (m) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
fixed_size_mode (const scalar_int_mode_pod &m) : m_mode (m) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR
|
||
|
fixed_size_mode (const complex_mode &m) : m_mode (m) {}
|
||
|
|
||
|
ALWAYS_INLINE CONSTEXPR operator machine_mode () const { return m_mode; }
|
||
|
|
||
|
static bool includes_p (machine_mode);
|
||
|
|
||
|
protected:
|
||
|
machine_mode m_mode;
|
||
|
};
|
||
|
|
||
|
/* Return true if MODE has a fixed size. */
|
||
|
|
||
|
inline bool
|
||
|
fixed_size_mode::includes_p (machine_mode mode)
|
||
|
{
|
||
|
return mode_to_bytes (mode).is_constant ();
|
||
|
}
|
||
|
|
||
|
/* Wrapper for mode arguments to target macros, so that if a target
|
||
|
doesn't need polynomial-sized modes, its header file can continue
|
||
|
to treat everything as fixed_size_mode. This should go away once
|
||
|
macros are moved to target hooks. It shouldn't be used in other
|
||
|
contexts. */
|
||
|
#if NUM_POLY_INT_COEFFS == 1
|
||
|
#define MACRO_MODE(MODE) (as_a <fixed_size_mode> (MODE))
|
||
|
#else
|
||
|
#define MACRO_MODE(MODE) (MODE)
|
||
|
#endif
|
||
|
|
||
|
extern opt_machine_mode mode_for_size (poly_uint64, enum mode_class, int);
|
||
|
|
||
|
/* Return the machine mode to use for a MODE_INT of SIZE bits, if one
|
||
|
exists. If LIMIT is nonzero, modes wider than MAX_FIXED_MODE_SIZE
|
||
|
will not be used. */
|
||
|
|
||
|
inline opt_scalar_int_mode
|
||
|
int_mode_for_size (poly_uint64 size, int limit)
|
||
|
{
|
||
|
return dyn_cast <scalar_int_mode> (mode_for_size (size, MODE_INT, limit));
|
||
|
}
|
||
|
|
||
|
/* Return the machine mode to use for a MODE_FLOAT of SIZE bits, if one
|
||
|
exists. */
|
||
|
|
||
|
inline opt_scalar_float_mode
|
||
|
float_mode_for_size (poly_uint64 size)
|
||
|
{
|
||
|
return dyn_cast <scalar_float_mode> (mode_for_size (size, MODE_FLOAT, 0));
|
||
|
}
|
||
|
|
||
|
/* Likewise for MODE_DECIMAL_FLOAT. */
|
||
|
|
||
|
inline opt_scalar_float_mode
|
||
|
decimal_float_mode_for_size (unsigned int size)
|
||
|
{
|
||
|
return dyn_cast <scalar_float_mode>
|
||
|
(mode_for_size (size, MODE_DECIMAL_FLOAT, 0));
|
||
|
}
|
||
|
|
||
|
extern machine_mode smallest_mode_for_size (poly_uint64, enum mode_class);
|
||
|
|
||
|
/* Find the narrowest integer mode that contains at least SIZE bits.
|
||
|
Such a mode must exist. */
|
||
|
|
||
|
inline scalar_int_mode
|
||
|
smallest_int_mode_for_size (poly_uint64 size)
|
||
|
{
|
||
|
return as_a <scalar_int_mode> (smallest_mode_for_size (size, MODE_INT));
|
||
|
}
|
||
|
|
||
|
extern opt_scalar_int_mode int_mode_for_mode (machine_mode);
|
||
|
extern opt_machine_mode bitwise_mode_for_mode (machine_mode);
|
||
|
extern opt_machine_mode mode_for_vector (scalar_mode, poly_uint64);
|
||
|
extern opt_machine_mode related_vector_mode (machine_mode, scalar_mode,
|
||
|
poly_uint64 = 0);
|
||
|
extern opt_machine_mode related_int_vector_mode (machine_mode);
|
||
|
|
||
|
/* A class for iterating through possible bitfield modes. */
|
||
|
class bit_field_mode_iterator
|
||
|
{
|
||
|
public:
|
||
|
bit_field_mode_iterator (HOST_WIDE_INT, HOST_WIDE_INT,
|
||
|
poly_int64, poly_int64,
|
||
|
unsigned int, bool);
|
||
|
bool next_mode (scalar_int_mode *);
|
||
|
bool prefer_smaller_modes ();
|
||
|
|
||
|
private:
|
||
|
opt_scalar_int_mode m_mode;
|
||
|
/* We use signed values here because the bit position can be negative
|
||
|
for invalid input such as gcc.dg/pr48335-8.c. */
|
||
|
HOST_WIDE_INT m_bitsize;
|
||
|
HOST_WIDE_INT m_bitpos;
|
||
|
poly_int64 m_bitregion_start;
|
||
|
poly_int64 m_bitregion_end;
|
||
|
unsigned int m_align;
|
||
|
bool m_volatilep;
|
||
|
int m_count;
|
||
|
};
|
||
|
|
||
|
/* Find the best mode to use to access a bit field. */
|
||
|
|
||
|
extern bool get_best_mode (int, int, poly_uint64, poly_uint64, unsigned int,
|
||
|
unsigned HOST_WIDE_INT, bool, scalar_int_mode *);
|
||
|
|
||
|
/* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT. */
|
||
|
|
||
|
extern CONST_MODE_BASE_ALIGN unsigned short mode_base_align[NUM_MACHINE_MODES];
|
||
|
|
||
|
extern unsigned get_mode_alignment (machine_mode);
|
||
|
|
||
|
#define GET_MODE_ALIGNMENT(MODE) get_mode_alignment (MODE)
|
||
|
|
||
|
/* For each class, get the narrowest mode in that class. */
|
||
|
|
||
|
extern const unsigned char class_narrowest_mode[MAX_MODE_CLASS];
|
||
|
#define GET_CLASS_NARROWEST_MODE(CLASS) \
|
||
|
((machine_mode) class_narrowest_mode[CLASS])
|
||
|
|
||
|
/* The narrowest full integer mode available on the target. */
|
||
|
|
||
|
#define NARROWEST_INT_MODE \
|
||
|
(scalar_int_mode \
|
||
|
(scalar_int_mode::from_int (class_narrowest_mode[MODE_INT])))
|
||
|
|
||
|
/* Return the narrowest mode in T's class. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline T
|
||
|
get_narrowest_mode (T mode)
|
||
|
{
|
||
|
return typename mode_traits<T>::from_int
|
||
|
(class_narrowest_mode[GET_MODE_CLASS (mode)]);
|
||
|
}
|
||
|
|
||
|
/* Define the integer modes whose sizes are BITS_PER_UNIT and BITS_PER_WORD
|
||
|
and the mode whose class is Pmode and whose size is POINTER_SIZE. */
|
||
|
|
||
|
extern scalar_int_mode byte_mode;
|
||
|
extern scalar_int_mode word_mode;
|
||
|
extern scalar_int_mode ptr_mode;
|
||
|
|
||
|
/* Target-dependent machine mode initialization - in insn-modes.cc. */
|
||
|
extern void init_adjust_machine_modes (void);
|
||
|
|
||
|
#define TRULY_NOOP_TRUNCATION_MODES_P(MODE1, MODE2) \
|
||
|
(targetm.truly_noop_truncation (GET_MODE_PRECISION (MODE1), \
|
||
|
GET_MODE_PRECISION (MODE2)))
|
||
|
|
||
|
/* Return true if MODE is a scalar integer mode that fits in a
|
||
|
HOST_WIDE_INT. */
|
||
|
|
||
|
inline bool
|
||
|
HWI_COMPUTABLE_MODE_P (machine_mode mode)
|
||
|
{
|
||
|
machine_mode mme = mode;
|
||
|
return (SCALAR_INT_MODE_P (mme)
|
||
|
&& mode_to_precision (mme).coeffs[0] <= HOST_BITS_PER_WIDE_INT);
|
||
|
}
|
||
|
|
||
|
inline bool
|
||
|
HWI_COMPUTABLE_MODE_P (scalar_int_mode mode)
|
||
|
{
|
||
|
return GET_MODE_PRECISION (mode) <= HOST_BITS_PER_WIDE_INT;
|
||
|
}
|
||
|
|
||
|
struct int_n_data_t {
|
||
|
/* These parts are initailized by genmodes output */
|
||
|
unsigned int bitsize;
|
||
|
scalar_int_mode_pod m;
|
||
|
/* RID_* is RID_INTN_BASE + index into this array */
|
||
|
};
|
||
|
|
||
|
/* This is also in tree.h. genmodes.cc guarantees the're sorted from
|
||
|
smallest bitsize to largest bitsize. */
|
||
|
extern bool int_n_enabled_p[NUM_INT_N_ENTS];
|
||
|
extern const int_n_data_t int_n_data[NUM_INT_N_ENTS];
|
||
|
|
||
|
/* Return true if MODE has class MODE_INT, storing it as a scalar_int_mode
|
||
|
in *INT_MODE if so. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline bool
|
||
|
is_int_mode (machine_mode mode, T *int_mode)
|
||
|
{
|
||
|
if (GET_MODE_CLASS (mode) == MODE_INT)
|
||
|
{
|
||
|
*int_mode = scalar_int_mode (scalar_int_mode::from_int (mode));
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Return true if MODE has class MODE_FLOAT, storing it as a
|
||
|
scalar_float_mode in *FLOAT_MODE if so. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline bool
|
||
|
is_float_mode (machine_mode mode, T *float_mode)
|
||
|
{
|
||
|
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
|
||
|
{
|
||
|
*float_mode = scalar_float_mode (scalar_float_mode::from_int (mode));
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Return true if MODE has class MODE_COMPLEX_INT, storing it as
|
||
|
a complex_mode in *CMODE if so. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline bool
|
||
|
is_complex_int_mode (machine_mode mode, T *cmode)
|
||
|
{
|
||
|
if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT)
|
||
|
{
|
||
|
*cmode = complex_mode (complex_mode::from_int (mode));
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Return true if MODE has class MODE_COMPLEX_FLOAT, storing it as
|
||
|
a complex_mode in *CMODE if so. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline bool
|
||
|
is_complex_float_mode (machine_mode mode, T *cmode)
|
||
|
{
|
||
|
if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
|
||
|
{
|
||
|
*cmode = complex_mode (complex_mode::from_int (mode));
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* Return true if MODE is a scalar integer mode with a precision
|
||
|
smaller than LIMIT's precision. */
|
||
|
|
||
|
inline bool
|
||
|
is_narrower_int_mode (machine_mode mode, scalar_int_mode limit)
|
||
|
{
|
||
|
scalar_int_mode int_mode;
|
||
|
return (is_a <scalar_int_mode> (mode, &int_mode)
|
||
|
&& GET_MODE_PRECISION (int_mode) < GET_MODE_PRECISION (limit));
|
||
|
}
|
||
|
|
||
|
namespace mode_iterator
|
||
|
{
|
||
|
/* Start mode iterator *ITER at the first mode in class MCLASS, if any. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline void
|
||
|
start (opt_mode<T> *iter, enum mode_class mclass)
|
||
|
{
|
||
|
if (GET_CLASS_NARROWEST_MODE (mclass) == E_VOIDmode)
|
||
|
*iter = opt_mode<T> ();
|
||
|
else
|
||
|
*iter = as_a<T> (GET_CLASS_NARROWEST_MODE (mclass));
|
||
|
}
|
||
|
|
||
|
inline void
|
||
|
start (machine_mode *iter, enum mode_class mclass)
|
||
|
{
|
||
|
*iter = GET_CLASS_NARROWEST_MODE (mclass);
|
||
|
}
|
||
|
|
||
|
/* Return true if mode iterator *ITER has not reached the end. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline bool
|
||
|
iterate_p (opt_mode<T> *iter)
|
||
|
{
|
||
|
return iter->exists ();
|
||
|
}
|
||
|
|
||
|
inline bool
|
||
|
iterate_p (machine_mode *iter)
|
||
|
{
|
||
|
return *iter != E_VOIDmode;
|
||
|
}
|
||
|
|
||
|
/* Set mode iterator *ITER to the next mode in the same class,
|
||
|
if any. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline void
|
||
|
get_next (opt_mode<T> *iter)
|
||
|
{
|
||
|
*iter = GET_MODE_NEXT_MODE (iter->require ());
|
||
|
}
|
||
|
|
||
|
inline void
|
||
|
get_next (machine_mode *iter)
|
||
|
{
|
||
|
*iter = GET_MODE_NEXT_MODE (*iter).else_void ();
|
||
|
}
|
||
|
|
||
|
/* Set mode iterator *ITER to the next mode in the same class.
|
||
|
Such a mode is known to exist. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline void
|
||
|
get_known_next (T *iter)
|
||
|
{
|
||
|
*iter = GET_MODE_NEXT_MODE (*iter).require ();
|
||
|
}
|
||
|
|
||
|
/* Set mode iterator *ITER to the next wider mode in the same class,
|
||
|
if any. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline void
|
||
|
get_wider (opt_mode<T> *iter)
|
||
|
{
|
||
|
*iter = GET_MODE_WIDER_MODE (iter->require ());
|
||
|
}
|
||
|
|
||
|
inline void
|
||
|
get_wider (machine_mode *iter)
|
||
|
{
|
||
|
*iter = GET_MODE_WIDER_MODE (*iter).else_void ();
|
||
|
}
|
||
|
|
||
|
/* Set mode iterator *ITER to the next wider mode in the same class.
|
||
|
Such a mode is known to exist. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline void
|
||
|
get_known_wider (T *iter)
|
||
|
{
|
||
|
*iter = GET_MODE_WIDER_MODE (*iter).require ();
|
||
|
}
|
||
|
|
||
|
/* Set mode iterator *ITER to the mode that is two times wider than the
|
||
|
current one, if such a mode exists. */
|
||
|
|
||
|
template<typename T>
|
||
|
inline void
|
||
|
get_2xwider (opt_mode<T> *iter)
|
||
|
{
|
||
|
*iter = GET_MODE_2XWIDER_MODE (iter->require ());
|
||
|
}
|
||
|
|
||
|
inline void
|
||
|
get_2xwider (machine_mode *iter)
|
||
|
{
|
||
|
*iter = GET_MODE_2XWIDER_MODE (*iter).else_void ();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Make ITERATOR iterate over all the modes in mode class CLASS,
|
||
|
from narrowest to widest. */
|
||
|
#define FOR_EACH_MODE_IN_CLASS(ITERATOR, CLASS) \
|
||
|
for (mode_iterator::start (&(ITERATOR), CLASS); \
|
||
|
mode_iterator::iterate_p (&(ITERATOR)); \
|
||
|
mode_iterator::get_next (&(ITERATOR)))
|
||
|
|
||
|
/* Make ITERATOR iterate over all the modes in the range [START, END),
|
||
|
in order of increasing width. */
|
||
|
#define FOR_EACH_MODE(ITERATOR, START, END) \
|
||
|
for ((ITERATOR) = (START); \
|
||
|
(ITERATOR) != (END); \
|
||
|
mode_iterator::get_known_next (&(ITERATOR)))
|
||
|
|
||
|
/* Make ITERATOR iterate over START and all non-narrower modes in the same
|
||
|
class, in order of increasing width. */
|
||
|
#define FOR_EACH_MODE_FROM(ITERATOR, START) \
|
||
|
for ((ITERATOR) = (START); \
|
||
|
mode_iterator::iterate_p (&(ITERATOR)); \
|
||
|
mode_iterator::get_next (&(ITERATOR)))
|
||
|
|
||
|
/* Make ITERATOR iterate over START and all wider modes in the same
|
||
|
class, in order of strictly increasing width. */
|
||
|
#define FOR_EACH_WIDER_MODE_FROM(ITERATOR, START) \
|
||
|
for ((ITERATOR) = (START); \
|
||
|
mode_iterator::iterate_p (&(ITERATOR)); \
|
||
|
mode_iterator::get_wider (&(ITERATOR)))
|
||
|
|
||
|
/* Make ITERATOR iterate over modes in the range [NARROWEST, END)
|
||
|
in order of increasing width, where NARROWEST is the narrowest mode
|
||
|
in END's class. */
|
||
|
#define FOR_EACH_MODE_UNTIL(ITERATOR, END) \
|
||
|
FOR_EACH_MODE (ITERATOR, get_narrowest_mode (END), END)
|
||
|
|
||
|
/* Make ITERATOR iterate over modes in the same class as MODE, in order
|
||
|
of non-decreasing width. Start at next such mode after START,
|
||
|
or don't iterate at all if there is no such mode. */
|
||
|
#define FOR_EACH_NEXT_MODE(ITERATOR, START) \
|
||
|
for ((ITERATOR) = (START), mode_iterator::get_next (&(ITERATOR)); \
|
||
|
mode_iterator::iterate_p (&(ITERATOR)); \
|
||
|
mode_iterator::get_next (&(ITERATOR)))
|
||
|
|
||
|
/* Make ITERATOR iterate over modes in the same class as MODE, in order
|
||
|
of increasing width. Start at the first mode wider than START,
|
||
|
or don't iterate at all if there is no wider mode. */
|
||
|
#define FOR_EACH_WIDER_MODE(ITERATOR, START) \
|
||
|
for ((ITERATOR) = (START), mode_iterator::get_wider (&(ITERATOR)); \
|
||
|
mode_iterator::iterate_p (&(ITERATOR)); \
|
||
|
mode_iterator::get_wider (&(ITERATOR)))
|
||
|
|
||
|
/* Make ITERATOR iterate over modes in the same class as MODE, in order
|
||
|
of increasing width, and with each mode being twice the width of the
|
||
|
previous mode. Start at the mode that is two times wider than START,
|
||
|
or don't iterate at all if there is no such mode. */
|
||
|
#define FOR_EACH_2XWIDER_MODE(ITERATOR, START) \
|
||
|
for ((ITERATOR) = (START), mode_iterator::get_2xwider (&(ITERATOR)); \
|
||
|
mode_iterator::iterate_p (&(ITERATOR)); \
|
||
|
mode_iterator::get_2xwider (&(ITERATOR)))
|
||
|
|
||
|
template<typename T>
|
||
|
void
|
||
|
gt_ggc_mx (pod_mode<T> *)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void
|
||
|
gt_pch_nx (pod_mode<T> *)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
void
|
||
|
gt_pch_nx (pod_mode<T> *, gt_pointer_operator, void *)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
#endif /* not HAVE_MACHINE_MODES */
|