[6/77] Make GET_MODE_WIDER return an opt_mode
authorRichard Sandiford <richard.sandiford@linaro.org>
Wed, 30 Aug 2017 11:09:01 +0000 (11:09 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 30 Aug 2017 11:09:01 +0000 (11:09 +0000)
GET_MODE_WIDER previously returned VOIDmode if no wider mode existed.
That would cause problems with stricter mode classes, since VOIDmode
isn't for example a valid scalar integer or floating-point mode.
This patch instead makes it return a new opt_mode<T> class, which
holds either a T or nothing.

2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
    Alan Hayward  <alan.hayward@arm.com>
    David Sherwood  <david.sherwood@arm.com>

gcc/
* coretypes.h (opt_mode): New class.
* machmode.h (opt_mode): Likewise.
(opt_mode::else_void): New function.
(opt_mode::require): Likewise.
(opt_mode::exists): Likewise.
(GET_MODE_WIDER_MODE): Turn into a function and return an opt_mode.
(GET_MODE_2XWIDER_MODE): Likewise.
(mode_iterator::get_wider): Update accordingly.
(mode_iterator::get_2xwider): Likewise.
(mode_iterator::get_known_wider): Likewise, turning into a template.
* combine.c (make_extraction): Update use of GET_MODE_WIDER_MODE,
forcing a wider mode to exist.
* config/cr16/cr16.h (LONG_REG_P): Likewise.
* rtlanal.c (init_num_sign_bit_copies_in_rep): Likewise.
* config/c6x/c6x.c (c6x_rtx_costs): Update use of
GET_MODE_2XWIDER_MODE, forcing a wider mode to exist.
* lower-subreg.c (init_lower_subreg): Likewise.
* optabs-libfuncs.c (init_sync_libfuncs_1): Likewise, but not
on the final iteration.
* config/i386/i386.c (ix86_expand_set_or_movmem): Check whether
a wider mode exists before asking for a move pattern.
(get_mode_wider_vector): Update use of GET_MODE_WIDER_MODE,
forcing a wider mode to exist.
(expand_vselect_vconcat): Update use of GET_MODE_2XWIDER_MODE,
returning false if no such mode exists.
* config/ia64/ia64.c (expand_vselect_vconcat): Likewise.
* config/mips/mips.c (mips_expand_vselect_vconcat): Likewise.
* expmed.c (init_expmed_one_mode): Update use of GET_MODE_WIDER_MODE.
Avoid checking for a MODE_INT if we already know the mode is not a
SCALAR_INT_MODE_P.
(extract_high_half): Update use of GET_MODE_WIDER_MODE,
forcing a wider mode to exist.
(expmed_mult_highpart_optab): Likewise.
(expmed_mult_highpart): Likewise.
* expr.c (expand_expr_real_2): Update use of GET_MODE_WIDER_MODE,
using else_void.
* lto-streamer-in.c (lto_input_mode_table): Likewise.
* optabs-query.c (find_widening_optab_handler_and_mode): Likewise.
* stor-layout.c (bit_field_mode_iterator::next_mode): Likewise.
* internal-fn.c (expand_mul_overflow): Update use of
GET_MODE_2XWIDER_MODE.
* omp-low.c (omp_clause_aligned_alignment): Likewise.
* tree-ssa-math-opts.c (convert_mult_to_widen): Update use of
GET_MODE_WIDER_MODE.
(convert_plusminus_to_widen): Likewise.
* tree-switch-conversion.c (array_value_type): Likewise.
* var-tracking.c (emit_note_insn_var_location): Likewise.
* tree-vrp.c (simplify_float_conversion_using_ranges): Likewise.
Return false inside rather than outside the loop if no wider mode
exists
* optabs.c (expand_binop): Update use of GET_MODE_WIDER_MODE
and GET_MODE_2XWIDER_MODE
(can_compare_p): Use else_void.
* gdbhooks.py (OptMachineModePrinter): New class.
(build_pretty_printer): Use it for opt_mode.

gcc/ada/
* gcc-interface/decl.c (validate_size): Update use of
GET_MODE_WIDER_MODE, forcing a wider mode to exist.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r251457

27 files changed:
gcc/ChangeLog
gcc/ada/ChangeLog
gcc/ada/gcc-interface/decl.c
gcc/combine.c
gcc/config/c6x/c6x.c
gcc/config/cr16/cr16.h
gcc/config/i386/i386.c
gcc/config/ia64/ia64.c
gcc/config/mips/mips.c
gcc/coretypes.h
gcc/expmed.c
gcc/expr.c
gcc/gdbhooks.py
gcc/internal-fn.c
gcc/lower-subreg.c
gcc/lto-streamer-in.c
gcc/machmode.h
gcc/omp-low.c
gcc/optabs-libfuncs.c
gcc/optabs-query.c
gcc/optabs.c
gcc/rtlanal.c
gcc/stor-layout.c
gcc/tree-ssa-math-opts.c
gcc/tree-switch-conversion.c
gcc/tree-vrp.c
gcc/var-tracking.c

index 8765c3cc7a326c3f73e50af546157299ef2423a2..9d8c1f0d74db312b6ac7b6c2ffdf4a7f4f997ddc 100644 (file)
@@ -1,3 +1,63 @@
+2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * coretypes.h (opt_mode): New class.
+       * machmode.h (opt_mode): Likewise.
+       (opt_mode::else_void): New function.
+       (opt_mode::require): Likewise.
+       (opt_mode::exists): Likewise.
+       (GET_MODE_WIDER_MODE): Turn into a function and return an opt_mode.
+       (GET_MODE_2XWIDER_MODE): Likewise.
+       (mode_iterator::get_wider): Update accordingly.
+       (mode_iterator::get_2xwider): Likewise.
+       (mode_iterator::get_known_wider): Likewise, turning into a template.
+       * combine.c (make_extraction): Update use of GET_MODE_WIDER_MODE,
+       forcing a wider mode to exist.
+       * config/cr16/cr16.h (LONG_REG_P): Likewise.
+       * rtlanal.c (init_num_sign_bit_copies_in_rep): Likewise.
+       * config/c6x/c6x.c (c6x_rtx_costs): Update use of
+       GET_MODE_2XWIDER_MODE, forcing a wider mode to exist.
+       * lower-subreg.c (init_lower_subreg): Likewise.
+       * optabs-libfuncs.c (init_sync_libfuncs_1): Likewise, but not
+       on the final iteration.
+       * config/i386/i386.c (ix86_expand_set_or_movmem): Check whether
+       a wider mode exists before asking for a move pattern.
+       (get_mode_wider_vector): Update use of GET_MODE_WIDER_MODE,
+       forcing a wider mode to exist.
+       (expand_vselect_vconcat): Update use of GET_MODE_2XWIDER_MODE,
+       returning false if no such mode exists.
+       * config/ia64/ia64.c (expand_vselect_vconcat): Likewise.
+       * config/mips/mips.c (mips_expand_vselect_vconcat): Likewise.
+       * expmed.c (init_expmed_one_mode): Update use of GET_MODE_WIDER_MODE.
+       Avoid checking for a MODE_INT if we already know the mode is not a
+       SCALAR_INT_MODE_P.
+       (extract_high_half): Update use of GET_MODE_WIDER_MODE,
+       forcing a wider mode to exist.
+       (expmed_mult_highpart_optab): Likewise.
+       (expmed_mult_highpart): Likewise.
+       * expr.c (expand_expr_real_2): Update use of GET_MODE_WIDER_MODE,
+       using else_void.
+       * lto-streamer-in.c (lto_input_mode_table): Likewise.
+       * optabs-query.c (find_widening_optab_handler_and_mode): Likewise.
+       * stor-layout.c (bit_field_mode_iterator::next_mode): Likewise.
+       * internal-fn.c (expand_mul_overflow): Update use of
+       GET_MODE_2XWIDER_MODE.
+       * omp-low.c (omp_clause_aligned_alignment): Likewise.
+       * tree-ssa-math-opts.c (convert_mult_to_widen): Update use of
+       GET_MODE_WIDER_MODE.
+       (convert_plusminus_to_widen): Likewise.
+       * tree-switch-conversion.c (array_value_type): Likewise.
+       * var-tracking.c (emit_note_insn_var_location): Likewise.
+       * tree-vrp.c (simplify_float_conversion_using_ranges): Likewise.
+       Return false inside rather than outside the loop if no wider mode
+       exists
+       * optabs.c (expand_binop): Update use of GET_MODE_WIDER_MODE
+       and GET_MODE_2XWIDER_MODE
+       (can_compare_p): Use else_void.
+       * gdbhooks.py (OptMachineModePrinter): New class.
+       (build_pretty_printer): Use it for opt_mode.
+
 2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index 4f7d2bd5ef9553a0b0bd2a29475684aa2fffa0a2..769546c43ac2c474fd5c6408d4bb8ed251cbf5f2 100644 (file)
@@ -1,3 +1,10 @@
+2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * gcc-interface/decl.c (validate_size): Update use of
+       GET_MODE_WIDER_MODE, forcing a wider mode to exist.
+
 2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
             Alan Hayward  <alan.hayward@arm.com>
             David Sherwood  <david.sherwood@arm.com>
index 83b9d0749fe3ccd12f4ce0e2124e43de21637806..83c582ff64fc985d976d5fb1d809ddd95ebfaa21 100644 (file)
@@ -8576,7 +8576,7 @@ validate_size (Uint uint_size, tree gnu_type, Entity_Id gnat_object,
     {
       machine_mode p_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
       while (!targetm.valid_pointer_mode (p_mode))
-       p_mode = GET_MODE_WIDER_MODE (p_mode);
+       p_mode = GET_MODE_WIDER_MODE (p_mode).require ();
       type_size = bitsize_int (GET_MODE_BITSIZE (p_mode));
     }
 
index 46212c5ea8455e26303af5d494fe7cb2652e6b81..1a6eda609ed963462a6aa8fab721c93c021df1e3 100644 (file)
@@ -7604,10 +7604,7 @@ make_extraction (machine_mode mode, rtx inner, HOST_WIDE_INT pos,
       wanted_inner_mode = smallest_mode_for_size (len, MODE_INT);
       while (pos % GET_MODE_BITSIZE (wanted_inner_mode) + len
             > GET_MODE_BITSIZE (wanted_inner_mode))
-       {
-         wanted_inner_mode = GET_MODE_WIDER_MODE (wanted_inner_mode);
-         gcc_assert (wanted_inner_mode != VOIDmode);
-       }
+       wanted_inner_mode = GET_MODE_WIDER_MODE (wanted_inner_mode).require ();
     }
 
   orig_pos = pos;
index 4f64df262ca035299dd8c4eb8cdf79e9c678eb9d..d92b8782c49d8fbc8938ef84049947347abdbd03 100644 (file)
@@ -6066,7 +6066,7 @@ c6x_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total,
       /* Recognize a mult_highpart operation.  */
       if ((mode == HImode || mode == SImode)
          && GET_CODE (XEXP (x, 0)) == LSHIFTRT
-         && GET_MODE (XEXP (x, 0)) == GET_MODE_2XWIDER_MODE (mode)
+         && GET_MODE (XEXP (x, 0)) == GET_MODE_2XWIDER_MODE (mode).require ()
          && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
          && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
          && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode))
index e2a678ea1ee23c5f3b4ab50c508fe273c0dce8b0..eba92544aa38d1733d5d755405a0d0da42a4f8c1 100644 (file)
@@ -197,9 +197,7 @@ while (0)
 
 /* Returns 1 if the register is longer than word size, 0 otherwise.  */
 #define LONG_REG_P(REGNO)                                                    \
-  (HARD_REGNO_NREGS (REGNO,                                                  \
-                    GET_MODE_WIDER_MODE (smallest_mode_for_size             \
-                                        (BITS_PER_WORD, MODE_INT))) == 1)
+  (HARD_REGNO_NREGS (REGNO, GET_MODE_WIDER_MODE (word_mode).require ()) == 1)
 
 #define HARD_REGNO_NREGS(REGNO, MODE)                                         \
  ((REGNO >= CR16_FIRST_DWORD_REGISTER)                                        \
index f087bce291ba1cb015aeccea4b61e4afca6ba956..88850bde786a9f9f29001d83c5e1cb85ab9a3e4b 100644 (file)
@@ -28534,6 +28534,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
   bool need_zero_guard = false;
   bool noalign;
   machine_mode move_mode = VOIDmode;
+  machine_mode wider_mode;
   int unroll_factor = 1;
   /* TODO: Once value ranges are available, fill in proper data.  */
   unsigned HOST_WIDE_INT min_size = 0;
@@ -28627,9 +28628,9 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp,
       unroll_factor = 4;
       /* Find the widest supported mode.  */
       move_mode = word_mode;
-      while (optab_handler (mov_optab, GET_MODE_WIDER_MODE (move_mode))
-            != CODE_FOR_nothing)
-         move_mode = GET_MODE_WIDER_MODE (move_mode);
+      while (GET_MODE_WIDER_MODE (move_mode).exists (&wider_mode)
+            && optab_handler (mov_optab, wider_mode) != CODE_FOR_nothing)
+       move_mode = wider_mode;
 
       /* Find the corresponding vector mode with the same size as MOVE_MODE.
         MOVE_MODE is an integer mode at the moment (SI, DI, TI, etc.).  */
@@ -43502,7 +43503,7 @@ static inline machine_mode
 get_mode_wider_vector (machine_mode o)
 {
   /* ??? Rely on the ordering that genmodes.c gives to vectors.  */
-  machine_mode n = GET_MODE_WIDER_MODE (o);
+  machine_mode n = GET_MODE_WIDER_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;
@@ -46865,7 +46866,8 @@ expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
   if (vselect_insn == NULL_RTX)
     init_vselect_insn ();
 
-  v2mode = GET_MODE_2XWIDER_MODE (GET_MODE (op0));
+  if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
+    return false;
   x = XEXP (SET_SRC (PATTERN (vselect_insn)), 0);
   PUT_MODE (x, v2mode);
   XEXP (x, 0) = op0;
index 455b50e1fb81006a21a609cd4f4e66f1d682c44b..720c16bd0036e8cd02c5058bbf9e728018732782 100644 (file)
@@ -11298,7 +11298,8 @@ expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
   machine_mode v2mode;
   rtx x;
 
-  v2mode = GET_MODE_2XWIDER_MODE (GET_MODE (op0));
+  if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
+    return false;
   x = gen_rtx_VEC_CONCAT (v2mode, op0, op1);
   return expand_vselect (target, x, perm, nelt);
 }
index af7cd184a66568c40f2606839a3a50197266918f..d646f612591c017c0580169245847e3bfd06370c 100644 (file)
@@ -21105,7 +21105,8 @@ mips_expand_vselect_vconcat (rtx target, rtx op0, rtx op1,
   machine_mode v2mode;
   rtx x;
 
-  v2mode = GET_MODE_2XWIDER_MODE (GET_MODE (op0));
+  if (!GET_MODE_2XWIDER_MODE (GET_MODE (op0)).exists (&v2mode))
+    return false;
   x = gen_rtx_VEC_CONCAT (v2mode, op0, op1);
   return mips_expand_vselect (target, x, perm, nelt);
 }
index 9ceb5391b3ce936e5df7c79102ccdf21f8700ccc..4de0611ebb4d582d046c7b67f549f4b6edf7bfec 100644 (file)
@@ -55,6 +55,7 @@ typedef const struct simple_bitmap_def *const_sbitmap;
 struct rtx_def;
 typedef struct rtx_def *rtx;
 typedef const struct rtx_def *const_rtx;
+template<typename> class opt_mode;
 
 /* Subclasses of rtx_def, using indentation to show the class
    hierarchy, along with the relevant invariant.
index 0219e0dee7692f752f60f77c1021ceecb44ef123..48a006004ffe47b88cf85b5f08ef5dc39426f84e 100644 (file)
@@ -207,11 +207,10 @@ init_expmed_one_mode (struct init_expmed_rtl *all,
       for (mode_from = MIN_MODE_INT; mode_from <= MAX_MODE_INT;
           mode_from = (machine_mode)(mode_from + 1))
        init_expmed_one_conv (all, mode, mode_from, speed);
-    }
-  if (GET_MODE_CLASS (mode) == MODE_INT)
-    {
-      machine_mode  wider_mode = GET_MODE_WIDER_MODE (mode);
-      if (wider_mode != VOIDmode)
+
+      machine_mode wider_mode;
+      if (GET_MODE_CLASS (mode) == MODE_INT
+         && GET_MODE_WIDER_MODE (mode).exists (&wider_mode))
        {
          PUT_MODE (all->zext, wider_mode);
          PUT_MODE (all->wide_mult, wider_mode);
@@ -3641,7 +3640,7 @@ extract_high_half (machine_mode mode, rtx op)
 
   gcc_assert (!SCALAR_FLOAT_MODE_P (mode));
 
-  wider_mode = GET_MODE_WIDER_MODE (mode);
+  wider_mode = GET_MODE_WIDER_MODE (mode).require ();
   op = expand_shift (RSHIFT_EXPR, wider_mode, op,
                     GET_MODE_BITSIZE (mode), 0, 1);
   return convert_modes (mode, wider_mode, op, 0);
@@ -3663,7 +3662,7 @@ expmed_mult_highpart_optab (machine_mode mode, rtx op0, rtx op1,
 
   gcc_assert (!SCALAR_FLOAT_MODE_P (mode));
 
-  wider_mode = GET_MODE_WIDER_MODE (mode);
+  wider_mode = GET_MODE_WIDER_MODE (mode).require ();
   size = GET_MODE_BITSIZE (mode);
 
   /* Firstly, try using a multiplication insn that only generates the needed
@@ -3769,7 +3768,7 @@ static rtx
 expmed_mult_highpart (machine_mode mode, rtx op0, rtx op1,
                      rtx target, int unsignedp, int max_cost)
 {
-  machine_mode wider_mode = GET_MODE_WIDER_MODE (mode);
+  machine_mode wider_mode = GET_MODE_WIDER_MODE (mode).require ();
   unsigned HOST_WIDE_INT cnst1;
   int extra_cost;
   bool sign_adjust = false;
index cbec00c64aef5e0cbb8f7ec8a977ccb90236917b..0219045f9ff793db77b6dcf71401b518affde9ba 100644 (file)
@@ -9159,7 +9159,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode,
        if (code == LSHIFT_EXPR
            && target
            && REG_P (target)
-           && mode == GET_MODE_WIDER_MODE (word_mode)
+           && mode == GET_MODE_WIDER_MODE (word_mode).else_void ()
            && GET_MODE_SIZE (mode) == 2 * GET_MODE_SIZE (word_mode)
            && TREE_CONSTANT (treeop1)
            && TREE_CODE (treeop0) == SSA_NAME)
index 962df473f57e6d1ee13907c70b62476b2f3d28de..847cd08302f52de9b8dcf999daa879ffbfcf9e01 100644 (file)
@@ -422,6 +422,18 @@ class VecPrinter:
 
 ######################################################################
 
+class OptMachineModePrinter:
+    def __init__(self, gdbval):
+        self.gdbval = gdbval
+
+    def to_string (self):
+        name = str(self.gdbval['m_mode'])
+       if name == 'E_VOIDmode':
+           return '<None>'
+        return name[2:] if name.startswith('E_') else name
+
+######################################################################
+
 # TODO:
 #   * hashtab
 #   * location_t
@@ -518,6 +530,9 @@ def build_pretty_printer():
                              'vec',
                              VecPrinter)
 
+    pp.add_printer_for_regex(r'opt_mode<(\S+)>',
+                             'opt_mode', OptMachineModePrinter)
+
     return pp
 
 gdb.printing.register_pretty_printer(
index 2b72367a1d396ac5151c6142072231bb8ce76548..8ac4f6a982627b4ebecac4443e51b8adfeb247f2 100644 (file)
@@ -1460,14 +1460,14 @@ expand_mul_overflow (location_t loc, tree lhs, tree arg0, tree arg1,
       struct separate_ops ops;
       int prec = GET_MODE_PRECISION (mode);
       machine_mode hmode = mode_for_size (prec / 2, MODE_INT, 1);
+      machine_mode wmode;
       ops.op0 = make_tree (type, op0);
       ops.op1 = make_tree (type, op1);
       ops.op2 = NULL_TREE;
       ops.location = loc;
-      if (GET_MODE_2XWIDER_MODE (mode) != VOIDmode
-         && targetm.scalar_mode_supported_p (GET_MODE_2XWIDER_MODE (mode)))
+      if (GET_MODE_2XWIDER_MODE (mode).exists (&wmode)
+         && targetm.scalar_mode_supported_p (wmode))
        {
-         machine_mode wmode = GET_MODE_2XWIDER_MODE (mode);
          ops.code = WIDEN_MULT_EXPR;
          ops.type
            = build_nonstandard_integer_type (GET_MODE_PRECISION (wmode), uns);
index 422b4913b4a39c30bcc0ed15ffcd357c8b565a87..ac19e8f52ada0aed21f4fa92ad7d0efde5772d4f 100644 (file)
@@ -266,7 +266,7 @@ init_lower_subreg (void)
 
   memset (this_target_lower_subreg, 0, sizeof (*this_target_lower_subreg));
 
-  twice_word_mode = GET_MODE_2XWIDER_MODE (word_mode);
+  twice_word_mode = GET_MODE_2XWIDER_MODE (word_mode).require ();
 
   rtxes.target = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
   rtxes.source = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 2);
index ee85efc9754b0cd76dea6439eddc2d095ae5bc0b..51d9a7b222b5636e4b3f9a09eaad34f0924b8c0d 100644 (file)
@@ -1636,7 +1636,7 @@ lto_input_mode_table (struct lto_file_decl_data *file_data)
                                    : GET_CLASS_NARROWEST_MODE (mclass);
             pass ? mr < MAX_MACHINE_MODE : mr != VOIDmode;
             pass ? mr = (machine_mode) (mr + 1)
-                 : mr = GET_MODE_WIDER_MODE (mr))
+                 : mr = GET_MODE_WIDER_MODE (mr).else_void ())
          if (GET_MODE_CLASS (mr) != mclass
              || GET_MODE_SIZE (mr) != size
              || GET_MODE_PRECISION (mr) != prec
index c272888ebf14be1b85339634414190b5440d8956..3b06f6d2c3ccf1d220a59bfe49e7ea15676c42be 100644 (file)
@@ -221,6 +221,71 @@ extern const unsigned char mode_class[NUM_MACHINE_MODES];
 #define POINTER_BOUNDS_MODE_P(MODE)      \
   (GET_MODE_CLASS (MODE) == MODE_POINTER_BOUNDS)
 
+/* 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 opt_mode () : m_mode (E_VOIDmode) {}
+  ALWAYS_INLINE opt_mode (const T &m) : m_mode (m) {}
+  ALWAYS_INLINE opt_mode (from_int m) : m_mode (machine_mode (m)) {}
+
+  machine_mode else_void () const;
+  T require () const;
+
+  bool exists () const;
+  template<typename U> bool exists (U *) const;
+
+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;
+}
+
+/* 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;
+}
+
 /* Return the base GET_MODE_SIZE value for MODE.  */
 
 ALWAYS_INLINE unsigned short
@@ -352,13 +417,22 @@ extern const unsigned HOST_WIDE_INT mode_mask_array[NUM_MACHINE_MODES];
 
 /* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI).  */
 
-extern const unsigned char mode_wider[NUM_MACHINE_MODES];
-#define GET_MODE_WIDER_MODE(MODE) ((machine_mode) mode_wider[MODE])
+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.  */
-extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
-#define GET_MODE_2XWIDER_MODE(MODE) ((machine_mode) mode_2xwider[MODE])
+
+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];
@@ -497,17 +571,17 @@ namespace mode_iterator
   inline void
   get_wider (machine_mode *iter)
   {
-    *iter = GET_MODE_WIDER_MODE (*iter);
+    *iter = GET_MODE_WIDER_MODE (*iter).else_void ();
   }
 
   /* Set mode iterator *ITER to the next widest mode in the same class.
      Such a mode is known to exist.  */
 
+  template<typename T>
   inline void
-  get_known_wider (machine_mode *iter)
+  get_known_wider (T *iter)
   {
-    *iter = GET_MODE_WIDER_MODE (*iter);
-    gcc_checking_assert (*iter != VOIDmode);
+    *iter = GET_MODE_WIDER_MODE (*iter).require ();
   }
 
   /* Set mode iterator *ITER to the mode that is two times wider than the
@@ -516,7 +590,7 @@ namespace mode_iterator
   inline void
   get_2xwider (machine_mode *iter)
   {
-    *iter = GET_MODE_2XWIDER_MODE (*iter);
+    *iter = GET_MODE_2XWIDER_MODE (*iter).else_void ();
   }
 }
 
index a36e5f9cbc04ae571da8ced5679835ce0c4f70b0..5deb5398c75308441eb91a9e73cbddf62d1621e6 100644 (file)
@@ -3456,8 +3456,8 @@ omp_clause_aligned_alignment (tree clause)
          continue;
        while (vs
               && GET_MODE_SIZE (vmode) < vs
-              && GET_MODE_2XWIDER_MODE (vmode) != VOIDmode)
-         vmode = GET_MODE_2XWIDER_MODE (vmode);
+              && GET_MODE_2XWIDER_MODE (vmode).exists ())
+         vmode = GET_MODE_2XWIDER_MODE (vmode).require ();
 
        tree type = lang_hooks.types.type_for_mode (mode, 1);
        if (type == NULL_TREE || TYPE_MODE (type) != mode)
index a3a32b7652c607abacc47abe8b4e69369aa1b08d..7b53a465a091ef29c83ba399cadec3f16ec06e74 100644 (file)
@@ -918,9 +918,10 @@ init_sync_libfuncs_1 (optab tab, const char *base, int max)
   mode = QImode;
   for (i = 1; i <= max; i *= 2)
     {
+      if (i > 1)
+       mode = GET_MODE_2XWIDER_MODE (mode).require ();
       buf[len + 1] = '0' + i;
       set_optab_libfunc (tab, mode, buf);
-      mode = GET_MODE_2XWIDER_MODE (mode);
     }
 }
 
index ad22f07a395f186e850c20a69e6918cff6ba224d..021d8160cf420ca73bc3cdbb1be75f5b765a34be 100644 (file)
@@ -425,7 +425,7 @@ find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
   for (; (permit_non_widening || from_mode != to_mode)
         && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode)
         && from_mode != VOIDmode;
-       from_mode = GET_MODE_WIDER_MODE (from_mode))
+       from_mode = GET_MODE_WIDER_MODE (from_mode).else_void ())
     {
       enum insn_code handler = widening_optab_handler (op, to_mode,
                                                       from_mode);
index ce419d361dec49fd3cb486c85b1f231882b364a9..c6ad64b5f8d02dda81d134c1508087484572278e 100644 (file)
@@ -1186,13 +1186,13 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
      takes operands of this mode and makes a wider mode.  */
 
   if (binoptab == smul_optab
-      && GET_MODE_2XWIDER_MODE (mode) != VOIDmode
-      && (widening_optab_handler ((unsignedp ? umul_widen_optab
-                                            : smul_widen_optab),
-                                 GET_MODE_2XWIDER_MODE (mode), mode)
-         != CODE_FOR_nothing))
+      && GET_MODE_2XWIDER_MODE (mode).exists (&wider_mode)
+      && (convert_optab_handler ((unsignedp
+                                 ? umul_widen_optab
+                                 : smul_widen_optab),
+                                wider_mode, mode) != CODE_FOR_nothing))
     {
-      temp = expand_binop (GET_MODE_2XWIDER_MODE (mode),
+      temp = expand_binop (wider_mode,
                           unsignedp ? umul_widen_optab : smul_widen_optab,
                           op0, op1, NULL_RTX, unsignedp, OPTAB_DIRECT);
 
@@ -1253,14 +1253,14 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
       && methods != OPTAB_DIRECT && methods != OPTAB_LIB)
     FOR_EACH_WIDER_MODE (wider_mode, mode)
       {
+       machine_mode next_mode;
        if (optab_handler (binoptab, wider_mode) != CODE_FOR_nothing
            || (binoptab == smul_optab
-               && GET_MODE_WIDER_MODE (wider_mode) != VOIDmode
+               && GET_MODE_WIDER_MODE (wider_mode).exists (&next_mode)
                && (find_widening_optab_handler ((unsignedp
                                                  ? umul_widen_optab
                                                  : smul_widen_optab),
-                                                GET_MODE_WIDER_MODE (wider_mode),
-                                                mode, 0)
+                                                next_mode, mode, 0)
                    != CODE_FOR_nothing)))
          {
            rtx xop0 = op0, xop1 = op1;
@@ -3702,7 +3702,7 @@ can_compare_p (enum rtx_code code, machine_mode mode,
          && optab_handler (cmov_optab, mode) != CODE_FOR_nothing)
        return 1;
 
-      mode = GET_MODE_WIDER_MODE (mode);
+      mode = GET_MODE_WIDER_MODE (mode).else_void ();
       PUT_MODE (test, mode);
     }
   while (mode != VOIDmode);
index 735d86eda0b527da6f271adf86fa457bff1a8ffe..157f592ee979f20f0ea46d44994115a02d520de3 100644 (file)
@@ -5671,13 +5671,15 @@ init_num_sign_bit_copies_in_rep (void)
        /* Currently, it is assumed that TARGET_MODE_REP_EXTENDED
           extends to the next widest mode.  */
        gcc_assert (targetm.mode_rep_extended (mode, in_mode) == UNKNOWN
-                   || GET_MODE_WIDER_MODE (mode) == in_mode);
+                   || GET_MODE_WIDER_MODE (mode).require () == in_mode);
 
        /* We are in in_mode.  Count how many bits outside of mode
           have to be copies of the sign-bit.  */
        FOR_EACH_MODE (i, mode, in_mode)
          {
-           machine_mode wider = GET_MODE_WIDER_MODE (i);
+           /* This must always exist (for the last iteration it will be
+              IN_MODE).  */
+           machine_mode wider = GET_MODE_WIDER_MODE (i).require ();
 
            if (targetm.mode_rep_extended (i, wider) == SIGN_EXTEND
                /* We can only check sign-bit copies starting from the
index b85c97de5c3ed954df3692a08f01204a6af94986..f69fad8fd7599235d15cf112a233453bb6b76d1b 100644 (file)
@@ -2745,7 +2745,8 @@ bit_field_mode_iterator
 bool
 bit_field_mode_iterator::next_mode (machine_mode *out_mode)
 {
-  for (; m_mode != VOIDmode; m_mode = GET_MODE_WIDER_MODE (m_mode))
+  for (; m_mode != VOIDmode;
+       m_mode = GET_MODE_WIDER_MODE (m_mode).else_void ())
     {
       unsigned int unit = GET_MODE_BITSIZE (m_mode);
 
@@ -2782,7 +2783,7 @@ bit_field_mode_iterator::next_mode (machine_mode *out_mode)
        break;
 
       *out_mode = m_mode;
-      m_mode = GET_MODE_WIDER_MODE (m_mode);
+      m_mode = GET_MODE_WIDER_MODE (m_mode).else_void ();
       m_count++;
       return true;
     }
index 0b1c880ecefa47adaa4d29574d984f69f3420cac..e6b7dbdf100c3ff8a3b332b02a09b1970529770d 100644 (file)
@@ -3283,8 +3283,8 @@ convert_mult_to_widen (gimple *stmt, gimple_stmt_iterator *gsi)
              || (TYPE_UNSIGNED (type2)
                  && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode)))
            {
-             from_mode = GET_MODE_WIDER_MODE (from_mode);
-             if (GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode))
+             if (!GET_MODE_WIDER_MODE (from_mode).exists (&from_mode)
+                 || GET_MODE_SIZE (to_mode) <= GET_MODE_SIZE (from_mode))
                return false;
            }
 
@@ -3465,8 +3465,8 @@ convert_plusminus_to_widen (gimple_stmt_iterator *gsi, gimple *stmt,
          || (from_unsigned2
              && TYPE_PRECISION (type2) == GET_MODE_PRECISION (from_mode)))
        {
-         from_mode = GET_MODE_WIDER_MODE (from_mode);
-         if (GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode))
+         if (!GET_MODE_WIDER_MODE (from_mode).exists (&from_mode)
+             || GET_MODE_SIZE (from_mode) >= GET_MODE_SIZE (to_mode))
            return false;
        }
 
index 85d6816d11902192f39281735ee329322d38b3ee..9f88869fbf9e2e2ddc503a569a3b268853fe79ae 100644 (file)
@@ -1088,8 +1088,7 @@ array_value_type (gswitch *swtch, tree type, int num,
          if (sign == 1)
            sign = 0;
 
-         mode = GET_MODE_WIDER_MODE (mode);
-         if (mode == VOIDmode
+         if (!GET_MODE_WIDER_MODE (mode).exists (&mode)
              || GET_MODE_SIZE (mode) >= GET_MODE_SIZE (type_mode))
            return type;
        }
index e1038a10b7a353de3b97a9e2d278abbb97f1d261..268969700b62391d4f082becd8d2ff6794f65f78 100644 (file)
@@ -10120,7 +10120,7 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
   else
     {
       mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
-      do
+      for (;;)
        {
          /* If we cannot do a signed conversion to float from mode
             or if the value-range does not fit in the signed type
@@ -10129,15 +10129,12 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
              && range_fits_type_p (vr, GET_MODE_PRECISION (mode), SIGNED))
            break;
 
-         mode = GET_MODE_WIDER_MODE (mode);
          /* But do not widen the input.  Instead leave that to the
             optabs expansion code.  */
-         if (GET_MODE_PRECISION (mode) > TYPE_PRECISION (TREE_TYPE (rhs1)))
+         if (!GET_MODE_WIDER_MODE (mode).exists (&mode)
+             || GET_MODE_PRECISION (mode) > TYPE_PRECISION (TREE_TYPE (rhs1)))
            return false;
        }
-      while (mode != VOIDmode);
-      if (mode == VOIDmode)
-       return false;
     }
 
   /* It works, insert a truncation or sign-change before the
index b107ab491aaf072b3fef78a948f7dccfc2e689d3..0721771a69dc882207e22426d6dad4c99ec94b4f 100644 (file)
@@ -8706,12 +8706,11 @@ emit_note_insn_var_location (variable **varp, emit_note_data *data)
       last_limit = offsets[n_var_parts] + GET_MODE_SIZE (mode);
 
       /* Attempt to merge adjacent registers or memory.  */
-      wider_mode = GET_MODE_WIDER_MODE (mode);
       for (j = i + 1; j < var->n_var_parts; j++)
        if (last_limit <= VAR_PART_OFFSET (var, j))
          break;
       if (j < var->n_var_parts
-         && wider_mode != VOIDmode
+         && GET_MODE_WIDER_MODE (mode).exists (&wider_mode)
          && var->var_part[j].cur_loc
          && mode == GET_MODE (var->var_part[j].cur_loc)
          && (REG_P (loc[n_var_parts]) || MEM_P (loc[n_var_parts]))