+2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * coretypes.h (scalar_float_mode): New type.
+ * machmode.h (mode_traits::from_int): Use machine_mode if
+ USE_ENUM_MODES is defined.
+ (is_a): New function.
+ (as_a): Likewise.
+ (dyn_cast): Likewise.
+ (scalar_float_mode): New class.
+ (scalar_float_mode::includes_p): New function.
+ (is_float_mode): Likewise.
+ * gdbhooks.py (MachineModePrinter): New class.
+ (build_pretty_printer): Use it for scalar_float_mode.
+ * real.h (FLOAT_MODE_FORMAT): Use as_a <scalar_float_mode>.
+ (format_helper::format_helper): Turn into a template.
+ * genmodes.c (get_mode_class): New function.
+ (emit_insn_modes_h): Give modes the class returned by get_mode_class,
+ or machine_mode if none.
+ * config/aarch64/aarch64.c (aarch64_simd_valid_immediate): Use
+ as_a <scalar_float_mode>.
+ * dwarf2out.c (mem_loc_descriptor): Likewise.
+ (insert_float): Likewise.
+ (add_const_value_attribute): Likewise.
+ * simplify-rtx.c (simplify_immed_subreg): Likewise.
+ * optabs.c (expand_absneg_bit): Take a scalar_float_mode.
+ (expand_unop): Update accordingly.
+ (expand_abs_nojump): Likewise.
+ (expand_copysign_absneg): Take a scalar_float_mode.
+ (expand_copysign_bit): Likewise.
+ (expand_copysign): Update accordingly.
+
2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
+2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * gcc-interface/utils.c (gnat_type_for_mode): Use is_a
+ <scalar_float_mode> instead of SCALAR_FLOAT_MODE_P.
+
2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
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);
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;
}
struct rtx_def;
typedef struct rtx_def *rtx;
typedef const struct rtx_def *const_rtx;
+class scalar_float_mode;
template<typename> class opt_mode;
/* Subclasses of rtx_def, using indentation to show the class
#define tree union _dont_use_tree_here_ *
#define const_tree union _dont_use_tree_here_ *
+typedef struct scalar_float_mode scalar_float_mode;
+
#endif
/* Classes of functions that compiler needs to check
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);
{
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;
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:
######################################################################
+class MachineModePrinter:
+ def __init__(self, gdbval):
+ self.gdbval = gdbval
+
+ def to_string (self):
+ name = str(self.gdbval['m_mode'])
+ return name[2:] if name.startswith('E_') else name
+
+######################################################################
+
class OptMachineModePrinter:
def __init__(self, gdbval):
self.gdbval = gdbval
pp.add_printer_for_regex(r'opt_mode<(\S+)>',
'opt_mode', OptMachineModePrinter)
+ pp.add_printer_for_types(['scalar_float_mode'],
+ 'scalar_float_mode', MachineModePrinter)
return pp
}\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)
{
printf ("#ifdef USE_ENUM_MODES\n");
printf ("#define %smode E_%smode\n", m->name, m->name);
printf ("#else\n");
- printf ("#define %smode ((void) 0, E_%smode)\n",
- m->name, m->name);
+ if (const char *mode_class = get_mode_class (m))
+ printf ("#define %smode (%s ((%s::from_int) E_%smode))\n",
+ m->name, mode_class, mode_class, m->name);
+ else
+ printf ("#define %smode ((void) 0, E_%smode)\n",
+ m->name, m->name);
printf ("#endif\n");
}
+2017-08-30 Richard Sandiford <richard.sandiford@linaro.org>
+ Alan Hayward <alan.hayward@arm.com>
+ David Sherwood <david.sherwood@arm.com>
+
+ * go-lang.c (go_langhook_type_for_mode): Use is_float_mode.
+
2017-08-07 Martin Liska <mliska@suse.cz>
* go-gcc.cc (Gcc_backend::function): Look up for no_split_stack
return NULL_TREE;
}
+ scalar_float_mode fmode;
enum mode_class mc = GET_MODE_CLASS (mode);
if (mc == MODE_INT)
return go_langhook_type_for_size (GET_MODE_BITSIZE (mode), unsignedp);
- else if (mc == MODE_FLOAT)
+ else if (is_float_mode (mode, &fmode))
{
- switch (GET_MODE_BITSIZE (mode))
+ switch (GET_MODE_BITSIZE (fmode))
{
case 32:
return float_type_node;
default:
// We have to check for long double in order to support
// i386 excess precision.
- if (mode == TYPE_MODE(long_double_type_node))
+ if (fmode == TYPE_MODE(long_double_type_node))
return long_double_type_node;
}
}
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.
-
- Here we use an enum type distinct from machine_mode but with the
+ 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.
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<>
return false;
}
+/* Return true if mode M has type T. */
+
+template<typename T>
+inline bool
+is_a (machine_mode 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 m)
+{
+ gcc_checking_assert (T::includes_p (m));
+ return typename mode_traits<T>::from_int (m);
+}
+
+/* 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> ();
+}
+
+/* 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_FLOAT_MODE_P. */
+class scalar_float_mode
+{
+public:
+ typedef mode_traits<scalar_float_mode>::from_int from_int;
+
+ ALWAYS_INLINE scalar_float_mode () {}
+ ALWAYS_INLINE scalar_float_mode (from_int m) : m_mode (machine_mode (m)) {}
+ ALWAYS_INLINE 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);
+}
+
/* Return the base GET_MODE_SIZE value for MODE. */
ALWAYS_INLINE unsigned short
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_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;
+}
+
namespace mode_iterator
{
/* Start mode iterator *ITER at the first mode in class MCLASS, if any. */
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;
{
enum mode_class mclass = GET_MODE_CLASS (mode);
machine_mode wider_mode;
+ scalar_float_mode float_mode;
rtx temp;
rtx libfunc;
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;
}
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;
}
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;
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;
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. */
: (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
{
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; }
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))
{}
{
/* 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);