diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/config/i386/i386-expand.cc | 2 | ||||
-rw-r--r-- | gcc/expmed.cc | 2 | ||||
-rw-r--r-- | gcc/genmodes.cc | 33 | ||||
-rw-r--r-- | gcc/machmode.h | 70 | ||||
-rw-r--r-- | gcc/optabs.cc | 8 |
5 files changed, 101 insertions, 14 deletions
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index 6baff6d..a0f8a98 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -14941,7 +14941,7 @@ static machine_mode get_mode_wider_vector (machine_mode o) { /* ??? Rely on the ordering that genmodes.cc gives to vectors. */ - machine_mode n = GET_MODE_WIDER_MODE (o).require (); + machine_mode n = GET_MODE_NEXT_MODE (o).require (); gcc_assert (GET_MODE_NUNITS (o) == GET_MODE_NUNITS (n) * 2); gcc_assert (GET_MODE_SIZE (o) == GET_MODE_SIZE (n)); return n; diff --git a/gcc/expmed.cc b/gcc/expmed.cc index 6c02c3b..6f7f99a 100644 --- a/gcc/expmed.cc +++ b/gcc/expmed.cc @@ -5712,7 +5712,7 @@ emit_store_flag_1 (rtx target, enum rtx_code code, rtx op0, rtx op1, /* Next try expanding this via the backend's cstore<mode>4. */ mclass = GET_MODE_CLASS (mode); - FOR_EACH_MODE_FROM (compare_mode, mode) + FOR_EACH_WIDER_MODE_FROM (compare_mode, mode) { machine_mode optab_mode = mclass == MODE_CC ? CCmode : compare_mode; icode = optab_handler (cstore_optab, optab_mode); diff --git a/gcc/genmodes.cc b/gcc/genmodes.cc index 59850bb..9f0cc9c 100644 --- a/gcc/genmodes.cc +++ b/gcc/genmodes.cc @@ -1527,7 +1527,7 @@ emit_mode_wider (void) int c; struct mode_data *m; - print_decl ("unsigned char", "mode_wider", "NUM_MACHINE_MODES"); + print_decl ("unsigned char", "mode_next", "NUM_MACHINE_MODES"); for_all_modes (c, m) tagged_printf ("E_%smode", @@ -1535,6 +1535,37 @@ emit_mode_wider (void) m->name); print_closer (); + print_decl ("unsigned char", "mode_wider", "NUM_MACHINE_MODES"); + + for_all_modes (c, m) + { + struct mode_data *m2 = 0; + + if (m->cl == MODE_INT + || m->cl == MODE_PARTIAL_INT + || m->cl == MODE_FLOAT + || m->cl == MODE_DECIMAL_FLOAT + || m->cl == MODE_COMPLEX_FLOAT + || m->cl == MODE_FRACT + || m->cl == MODE_UFRACT + || m->cl == MODE_ACCUM + || m->cl == MODE_UACCUM) + for (m2 = m->wider; m2 && m2 != void_mode; m2 = m2->wider) + { + if (m2->bytesize == m->bytesize + && m2->precision == m->precision) + continue; + break; + } + + if (m2 == void_mode) + m2 = 0; + tagged_printf ("E_%smode", + m2 ? m2->name : void_mode->name, + m->name); + } + + print_closer (); print_decl ("unsigned char", "mode_2xwider", "NUM_MACHINE_MODES"); for_all_modes (c, m) diff --git a/gcc/machmode.h b/gcc/machmode.h index 45df720df..99b0e46 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -28,6 +28,7 @@ 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]; @@ -760,7 +761,23 @@ GET_MODE_NUNITS (const T &mode) } #endif -/* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI). */ +/* 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> @@ -1098,7 +1115,33 @@ namespace mode_iterator return *iter != E_VOIDmode; } - /* Set mode iterator *ITER to the next widest mode in the same class, + /* 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> @@ -1114,7 +1157,7 @@ namespace mode_iterator *iter = GET_MODE_WIDER_MODE (*iter).else_void (); } - /* Set mode iterator *ITER to the next widest mode in the same class. + /* Set mode iterator *ITER to the next wider mode in the same class. Such a mode is known to exist. */ template<typename T> @@ -1146,20 +1189,27 @@ namespace mode_iterator #define FOR_EACH_MODE_IN_CLASS(ITERATOR, CLASS) \ for (mode_iterator::start (&(ITERATOR), CLASS); \ mode_iterator::iterate_p (&(ITERATOR)); \ - mode_iterator::get_wider (&(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_wider (&(ITERATOR))) + mode_iterator::get_known_next (&(ITERATOR))) -/* Make ITERATOR iterate over START and all wider modes in the same +/* 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) @@ -1169,6 +1219,14 @@ namespace mode_iterator 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) \ diff --git a/gcc/optabs.cc b/gcc/optabs.cc index 165f8d1..c2a6f97 100644 --- a/gcc/optabs.cc +++ b/gcc/optabs.cc @@ -4384,7 +4384,6 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, machine_mode mode = *pmode; rtx libfunc, test; machine_mode cmp_mode; - enum mode_class mclass; /* The other methods are not needed. */ gcc_assert (methods == OPTAB_DIRECT || methods == OPTAB_WIDEN @@ -4490,9 +4489,8 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, return; } - mclass = GET_MODE_CLASS (mode); test = gen_rtx_fmt_ee (comparison, VOIDmode, x, y); - FOR_EACH_MODE_FROM (cmp_mode, mode) + FOR_EACH_WIDER_MODE_FROM (cmp_mode, mode) { enum insn_code icode; icode = optab_handler (cbranch_optab, cmp_mode); @@ -4515,7 +4513,7 @@ prepare_cmp_insn (rtx x, rtx y, enum rtx_code comparison, rtx size, delete_insns_since (last); } - if (methods == OPTAB_DIRECT || !CLASS_HAS_WIDER_MODES_P (mclass)) + if (methods == OPTAB_DIRECT) break; } @@ -4711,7 +4709,7 @@ prepare_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison, bool reversed_p = false; scalar_int_mode cmp_mode = targetm.libgcc_cmp_return_mode (); - FOR_EACH_MODE_FROM (mode, orig_mode) + FOR_EACH_WIDER_MODE_FROM (mode, orig_mode) { if (code_to_optab (comparison) && (libfunc = optab_libfunc (code_to_optab (comparison), mode))) |