@@ -3411,8 +3411,10 @@ gnat_type_for_mode (machine_mode mode, int unsignedp)
if (COMPLEX_MODE_P (mode))
return NULL_TREE;
- if (SCALAR_FLOAT_MODE_P (mode))
- return float_type_for_precision (GET_MODE_PRECISION (mode), mode);
+ scalar_float_mode float_mode;
+ if (is_a <scalar_float_mode> (mode, &float_mode))
+ return float_type_for_precision (GET_MODE_PRECISION (float_mode),
+ float_mode);
if (SCALAR_INT_MODE_P (mode))
return gnat_type_for_size (GET_MODE_BITSIZE (mode), unsignedp);
@@ -11035,8 +11035,12 @@ aarch64_simd_valid_immediate (rtx op, machine_mode mode, bool inverse,
if (info)
{
- info->value = CONST_VECTOR_ELT (op, 0);
- info->element_width = GET_MODE_BITSIZE (GET_MODE (info->value));
+ rtx elt = CONST_VECTOR_ELT (op, 0);
+ scalar_float_mode elt_mode
+ = as_a <scalar_float_mode> (GET_MODE (elt));
+
+ info->value = elt;
+ info->element_width = GET_MODE_BITSIZE (elt_mode);
info->mvn = false;
info->shift = 0;
}
@@ -56,6 +56,7 @@ struct rtx_def;
typedef struct rtx_def *rtx;
typedef const struct rtx_def *const_rtx;
class machine_mode;
+class scalar_float_mode;
template<typename> class opt_mode;
/* Subclasses of rtx_def, using indentation to show the class
@@ -15121,7 +15121,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
else
#endif
{
- unsigned int length = GET_MODE_SIZE (mode);
+ scalar_float_mode float_mode = as_a <scalar_float_mode> (mode);
+ unsigned int length = GET_MODE_SIZE (float_mode);
unsigned char *array = ggc_vec_alloc<unsigned char> (length);
insert_float (rtl, array);
@@ -18343,11 +18344,12 @@ insert_float (const_rtx rtl, unsigned char *array)
{
long val[4];
int i;
+ scalar_float_mode mode = as_a <scalar_float_mode> (GET_MODE (rtl));
- real_to_target (val, CONST_DOUBLE_REAL_VALUE (rtl), GET_MODE (rtl));
+ real_to_target (val, CONST_DOUBLE_REAL_VALUE (rtl), mode);
/* real_to_target puts 32-bit pieces in each long. Pack them. */
- for (i = 0; i < GET_MODE_SIZE (GET_MODE (rtl)) / 4; i++)
+ for (i = 0; i < GET_MODE_SIZE (mode) / 4; i++)
{
insert_int (val[i], 4, array);
array += 4;
@@ -18391,21 +18393,19 @@ add_const_value_attribute (dw_die_ref die, rtx rtl)
floating-point constant. A CONST_DOUBLE is used whenever the
constant requires more than one word in order to be adequately
represented. */
- {
- machine_mode mode = GET_MODE (rtl);
-
- if (TARGET_SUPPORTS_WIDE_INT == 0 && !SCALAR_FLOAT_MODE_P (mode))
- add_AT_double (die, DW_AT_const_value,
- CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
- else
- {
- unsigned int length = GET_MODE_SIZE (mode);
- unsigned char *array = ggc_vec_alloc<unsigned char> (length);
+ if (TARGET_SUPPORTS_WIDE_INT == 0
+ && !SCALAR_FLOAT_MODE_P (GET_MODE (rtl)))
+ add_AT_double (die, DW_AT_const_value,
+ CONST_DOUBLE_HIGH (rtl), CONST_DOUBLE_LOW (rtl));
+ else
+ {
+ scalar_float_mode mode = as_a <scalar_float_mode> (GET_MODE (rtl));
+ unsigned int length = GET_MODE_SIZE (mode);
+ unsigned char *array = ggc_vec_alloc<unsigned char> (length);
- insert_float (rtl, array);
- add_AT_vec (die, DW_AT_const_value, length / 4, 4, array);
- }
- }
+ insert_float (rtl, array);
+ add_AT_vec (die, DW_AT_const_value, length / 4, 4, array);
+ }
return true;
case CONST_VECTOR:
@@ -1129,6 +1129,23 @@ mode_unit_precision_inline (machine_mode_enum mode)\n\
}\n");
}
+/* Return the best machine mode class for MODE, or null if machine_mode
+ should be used. */
+
+static const char *
+get_mode_class (struct mode_data *mode)
+{
+ switch (mode->cl)
+ {
+ case MODE_FLOAT:
+ case MODE_DECIMAL_FLOAT:
+ return "scalar_float_mode";
+
+ default:
+ return NULL;
+ }
+}
+
static void
emit_insn_modes_h (void)
{
@@ -1158,8 +1175,12 @@ enum machine_mode_enum\n{");
printf ("#ifdef USE_ENUM_MODES\n");
printf ("#define %smode E_%smode\n", m->name, m->name);
printf ("#else\n");
- printf ("#define %smode (machine_mode (E_%smode))\n",
- m->name, m->name);
+ if (const char *mode_class = get_mode_class (m))
+ printf ("#define %smode (%s::from_int (E_%smode))\n",
+ m->name, mode_class, m->name);
+ else
+ printf ("#define %smode (machine_mode (E_%smode))\n",
+ m->name, m->name);
printf ("#endif\n");
}
@@ -29,6 +29,16 @@ extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];
extern const unsigned char mode_wider[NUM_MACHINE_MODES];
extern const unsigned char mode_2xwider[NUM_MACHINE_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. */
+#ifdef USE_ENUM_MODES
+#define PROTECT_ENUM_CONVERSION public
+#else
+#define PROTECT_ENUM_CONVERSION protected
+#endif
+
/* Get the name of mode MODE as a string. */
extern const char * const mode_name[NUM_MACHINE_MODES];
@@ -237,6 +247,85 @@ opt_mode<T>::exists (U *mode) const
return false;
}
+/* Return true if mode M has type T. */
+
+template<typename T>
+inline bool
+is_a (machine_mode_enum m)
+{
+ return T::includes_p (m);
+}
+
+/* Assert that mode M has type T, and return it in that form. */
+
+template<typename T>
+inline T
+as_a (machine_mode_enum m)
+{
+ gcc_checking_assert (T::includes_p (m));
+ return T::from_int (m);
+}
+
+/* Convert M to an opt_mode<T>. */
+
+template<typename T>
+inline opt_mode<T>
+dyn_cast (machine_mode_enum m)
+{
+ if (T::includes_p (m))
+ return T::from_int (m);
+ return opt_mode<T> ();
+}
+
+/* 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_enum m, U *result)
+{
+ if (T::includes_p (m))
+ {
+ *result = T::from_int (m);
+ return true;
+ }
+ return false;
+}
+
+/* Represents a machine mode that is known to be a SCALAR_FLOAT_MODE_P. */
+class scalar_float_mode
+{
+public:
+ ALWAYS_INLINE scalar_float_mode () {}
+ ALWAYS_INLINE operator machine_mode_enum () const { return m_mode; }
+
+ static bool includes_p (machine_mode_enum);
+ static scalar_float_mode from_int (int i);
+
+PROTECT_ENUM_CONVERSION:
+ ALWAYS_INLINE scalar_float_mode (machine_mode_enum m) : m_mode (m) {}
+
+protected:
+ machine_mode_enum m_mode;
+};
+
+/* Return true if M is a scalar_float_mode. */
+
+inline bool
+scalar_float_mode::includes_p (machine_mode_enum m)
+{
+ return SCALAR_FLOAT_MODE_P (m);
+}
+
+/* Return M as a scalar_float_mode. This function should only be used by
+ utility functions; general code should use as_a<T> instead. */
+
+ALWAYS_INLINE scalar_float_mode
+scalar_float_mode::from_int (int i)
+{
+ return machine_mode_enum (i);
+}
+
/* Represents a general machine mode (scalar or non-scalar). */
class machine_mode
{
@@ -2550,7 +2550,7 @@ lowpart_subreg_maybe_copy (machine_mode omode, rtx val,
logical operation on the sign bit. */
static rtx
-expand_absneg_bit (enum rtx_code code, machine_mode mode,
+expand_absneg_bit (enum rtx_code code, scalar_float_mode mode,
rtx op0, rtx target)
{
const struct real_format *fmt;
@@ -2696,6 +2696,7 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
{
enum mode_class mclass = GET_MODE_CLASS (mode);
machine_mode wider_mode;
+ scalar_float_mode float_mode;
rtx temp;
rtx libfunc;
@@ -2886,9 +2887,9 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,
if (optab_to_code (unoptab) == NEG)
{
/* Try negating floating point values by flipping the sign bit. */
- if (SCALAR_FLOAT_MODE_P (mode))
+ if (is_a <scalar_float_mode> (mode, &float_mode))
{
- temp = expand_absneg_bit (NEG, mode, op0, target);
+ temp = expand_absneg_bit (NEG, float_mode, op0, target);
if (temp)
return temp;
}
@@ -3085,9 +3086,10 @@ expand_abs_nojump (machine_mode mode, rtx op0, rtx target,
return temp;
/* For floating point modes, try clearing the sign bit. */
- if (SCALAR_FLOAT_MODE_P (mode))
+ scalar_float_mode float_mode;
+ if (is_a <scalar_float_mode> (mode, &float_mode))
{
- temp = expand_absneg_bit (ABS, mode, op0, target);
+ temp = expand_absneg_bit (ABS, float_mode, op0, target);
if (temp)
return temp;
}
@@ -3241,7 +3243,7 @@ expand_one_cmpl_abs_nojump (machine_mode mode, rtx op0, rtx target)
and not playing with subregs so much, will help the register allocator. */
static rtx
-expand_copysign_absneg (machine_mode mode, rtx op0, rtx op1, rtx target,
+expand_copysign_absneg (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
int bitpos, bool op0_is_abs)
{
machine_mode imode;
@@ -3325,7 +3327,7 @@ expand_copysign_absneg (machine_mode mode, rtx op0, rtx op1, rtx target,
is true if op0 is known to have its sign bit clear. */
static rtx
-expand_copysign_bit (machine_mode mode, rtx op0, rtx op1, rtx target,
+expand_copysign_bit (scalar_float_mode mode, rtx op0, rtx op1, rtx target,
int bitpos, bool op0_is_abs)
{
machine_mode imode;
@@ -3423,12 +3425,12 @@ expand_copysign_bit (machine_mode mode, rtx op0, rtx op1, rtx target,
rtx
expand_copysign (rtx op0, rtx op1, rtx target)
{
- machine_mode mode = GET_MODE (op0);
+ scalar_float_mode mode;
const struct real_format *fmt;
bool op0_is_abs;
rtx temp;
- gcc_assert (SCALAR_FLOAT_MODE_P (mode));
+ mode = as_a <scalar_float_mode> (GET_MODE (op0));
gcc_assert (GET_MODE (op1) == mode);
/* First try to do it with a special instruction. */
@@ -183,8 +183,7 @@ extern const struct real_format *
: (gcc_unreachable (), 0)])
#define FLOAT_MODE_FORMAT(MODE) \
- (REAL_MODE_FORMAT (SCALAR_FLOAT_MODE_P (MODE)? (MODE) \
- : GET_MODE_INNER (MODE)))
+ (REAL_MODE_FORMAT (as_a <scalar_float_mode> (GET_MODE_INNER (MODE))))
/* The following macro determines whether the floating point format is
composite, i.e. may contain non-consecutive mantissa bits, in which
@@ -212,7 +211,7 @@ class format_helper
{
public:
format_helper (const real_format *format) : m_format (format) {}
- format_helper (machine_mode m);
+ template<typename T> format_helper (const T &);
const real_format *operator-> () const { return m_format; }
operator const real_format *() const { return m_format; }
@@ -222,7 +221,8 @@ private:
const real_format *m_format;
};
-inline format_helper::format_helper (machine_mode m)
+template<typename T>
+inline format_helper::format_helper (const T &m)
: m_format (m == VOIDmode ? 0 : REAL_MODE_FORMAT (m))
{}
@@ -5816,9 +5816,11 @@ simplify_immed_subreg (machine_mode outermode, rtx op,
{
/* This is big enough for anything on the platform. */
long tmp[MAX_BITSIZE_MODE_ANY_MODE / 32];
- int bitsize = GET_MODE_BITSIZE (GET_MODE (el));
+ scalar_float_mode el_mode;
+
+ el_mode = as_a <scalar_float_mode> (GET_MODE (el));
+ int bitsize = GET_MODE_BITSIZE (el_mode);
- gcc_assert (SCALAR_FLOAT_MODE_P (GET_MODE (el)));
gcc_assert (bitsize <= elem_bitsize);
gcc_assert (bitsize % value_bit == 0);