From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20010 invoked by alias); 9 Dec 2016 12:55:58 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 19994 invoked by uid 89); 9 Dec 2016 12:55:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-4.9 required=5.0 tests=BAYES_00,RP_MATCHES_RCVD,SPF_PASS autolearn=ham version=3.3.2 spammy=firstly, TREE_CONSTANT, tree_constant, arg0 X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 09 Dec 2016 12:55:47 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 7814B707; Fri, 9 Dec 2016 04:55:46 -0800 (PST) Received: from localhost (e105548-lin.manchester.arm.com [10.45.32.67]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id C704D3F477 for ; Fri, 9 Dec 2016 04:55:45 -0800 (PST) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@arm.com Subject: [6/67] Make GET_MODE_WIDER return an opt_mode References: <87h96dp8u6.fsf@e105548-lin.cambridge.arm.com> Date: Fri, 09 Dec 2016 12:55:00 -0000 In-Reply-To: <87h96dp8u6.fsf@e105548-lin.cambridge.arm.com> (Richard Sandiford's message of "Fri, 09 Dec 2016 12:48:01 +0000") Message-ID: <87r35hntwv.fsf@e105548-lin.cambridge.arm.com> User-Agent: Gnus/5.130012 (Ma Gnus v0.12) Emacs/24.3 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-SW-Source: 2016-12/txt/msg00773.txt.bz2 GET_MODE_WIDER previously returned VOIDmode if no wider mode exists. 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 class, which holds either a T or nothing. gcc/ 2016-11-24 Richard Sandiford Alan Hayward David Sherwood * coretypes.h (opt_mode): New class. * machmode.h (opt_mode): Likewise. (opt_mode::else_void): New function. (opt_mode::operator *): 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): Likewise GET_MODE_2XWIDER_MODE. * config/ia64/ia64.c (expand_vselect_vconcat): Check whether a 2x wider mode exists. * 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_WIDER_MODE. * tree-ssa-math-opts.c (convert_mult_to_widen): Likewise. (convert_plusminus_to_widen): Likewise. * omp-low.c (omp_clause_aligned_alignment): 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. gcc/ada/ 2016-11-24 Richard Sandiford Alan Hayward David Sherwood * gcc-interface/decl.c (validate_size): Update use of GET_MODE_WIDER_MODE, forcing a wider mode to exist. diff --git a/gcc/ada/gcc-interface/decl.c b/gcc/ada/gcc-interface/decl.c index 18ec63d..d3bee34 100644 --- a/gcc/ada/gcc-interface/decl.c +++ b/gcc/ada/gcc-interface/decl.c @@ -8528,7 +8528,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); type_size = bitsize_int (GET_MODE_BITSIZE (p_mode)); } diff --git a/gcc/combine.c b/gcc/combine.c index 8b08b14..e8e0b3f 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -7592,10 +7592,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); } orig_pos = pos; diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c index fcb5b01..7e059b2 100644 --- a/gcc/config/c6x/c6x.c +++ b/gcc/config/c6x/c6x.c @@ -6063,7 +6063,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) && 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)) diff --git a/gcc/config/cr16/cr16.h b/gcc/config/cr16/cr16.h index 2d08c2b..2dcad94 100644 --- a/gcc/config/cr16/cr16.h +++ b/gcc/config/cr16/cr16.h @@ -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)) == 1) #define HARD_REGNO_NREGS(REGNO, MODE) \ ((REGNO >= CR16_FIRST_DWORD_REGISTER) \ diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 616b514..0c58dae 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -27440,6 +27440,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; @@ -27533,9 +27534,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.). */ @@ -42354,7 +42355,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); gcc_assert (GET_MODE_NUNITS (o) == GET_MODE_NUNITS (n) * 2); gcc_assert (GET_MODE_SIZE (o) == GET_MODE_SIZE (n)); return n; @@ -45616,7 +45617,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; diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c index 21953d1..d43edc8 100644 --- a/gcc/config/ia64/ia64.c +++ b/gcc/config/ia64/ia64.c @@ -11297,7 +11297,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); } diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 7eca000..6c08aed 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -21079,7 +21079,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); } diff --git a/gcc/coretypes.h b/gcc/coretypes.h index f26c1a0..9f81995 100644 --- a/gcc/coretypes.h +++ b/gcc/coretypes.h @@ -56,6 +56,7 @@ struct rtx_def; typedef struct rtx_def *rtx; typedef const struct rtx_def *const_rtx; class machine_mode; +template class opt_mode; /* Subclasses of rtx_def, using indentation to show the class hierarchy, along with the relevant invariant. diff --git a/gcc/expmed.c b/gcc/expmed.c index 9a0aa7e..737588b 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -206,11 +206,10 @@ init_expmed_one_mode (struct init_expmed_rtl *all, { FOR_EACH_MODE_IN_CLASS (mode_from, MODE_INT) 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); @@ -3578,7 +3577,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); op = expand_shift (RSHIFT_EXPR, wider_mode, op, GET_MODE_BITSIZE (mode), 0, 1); return convert_modes (mode, wider_mode, op, 0); @@ -3600,7 +3599,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); size = GET_MODE_BITSIZE (mode); /* Firstly, try using a multiplication insn that only generates the needed @@ -3706,7 +3705,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); unsigned HOST_WIDE_INT cnst1; int extra_cost; bool sign_adjust = false; diff --git a/gcc/expr.c b/gcc/expr.c index 1bcf6c6..a3a3e86 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -9090,7 +9090,7 @@ expand_expr_real_2 (sepops ops, rtx target, machine_mode tmode, && target && REG_P (target) && ! unsignedp - && 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) diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c index 0d91b8e..3dbd2a1 100644 --- a/gcc/internal-fn.c +++ b/gcc/internal-fn.c @@ -1468,14 +1468,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); diff --git a/gcc/lower-subreg.c b/gcc/lower-subreg.c index ca4582f..d378542 100644 --- a/gcc/lower-subreg.c +++ b/gcc/lower-subreg.c @@ -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); rtxes.target = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1); rtxes.source = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 2); diff --git a/gcc/lto-streamer-in.c b/gcc/lto-streamer-in.c index 69d87e6..578b10f 100644 --- a/gcc/lto-streamer-in.c +++ b/gcc/lto-streamer-in.c @@ -1555,7 +1555,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_enum) (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 diff --git a/gcc/machmode.h b/gcc/machmode.h index be389a2..44a8ad4 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -183,6 +183,60 @@ 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. + operator * gives the T value. */ +template +class opt_mode +{ +public: + ALWAYS_INLINE opt_mode () : m_mode (E_VOIDmode) {} + ALWAYS_INLINE opt_mode (const T &m) : m_mode (m) {} + machine_mode_enum else_void () const; + T operator * () const; + + /* Return true if the object contains a T rather than nothing. */ + ALWAYS_INLINE bool exists () const { return m_mode != E_VOIDmode; } + template bool exists (U *) const; + +private: + machine_mode_enum m_mode; +}; + +/* If the object contains a T, return its enum value, otherwise return + E_VOIDmode. */ + +template +ALWAYS_INLINE machine_mode_enum +opt_mode::else_void () const +{ + return m_mode; +} + +/* Assert that the object contains a T and return it. */ + +template +inline T +opt_mode::operator * () const +{ + gcc_checking_assert (m_mode != E_VOIDmode); + return T::from_int (m_mode); +} + +/* Return true if the object contains a T, storing it in *MODE if so. */ + +template +template +inline bool +opt_mode::exists (U *mode) const +{ + if (m_mode != E_VOIDmode) + { + *mode = T::from_int (m_mode); + return true; + } + return false; +} + /* Represents a general machine mode (scalar or non-scalar). */ class machine_mode { @@ -336,15 +390,28 @@ 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 ((machine_mode_enum) mode_wider[MODE])) +template +ALWAYS_INLINE opt_mode +GET_MODE_WIDER_MODE (const T &m) +{ + machine_mode_enum wider = (machine_mode_enum) mode_wider[m]; + if (wider != E_VOIDmode) + return T::from_int (wider); + return opt_mode (); +} /* 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 ((machine_mode_enum) mode_2xwider[MODE])) + +template +ALWAYS_INLINE opt_mode +GET_MODE_2XWIDER_MODE (const T &m) +{ + machine_mode_enum wider = (machine_mode_enum) mode_2xwider[m]; + if (wider != E_VOIDmode) + return T::from_int (wider); + return opt_mode (); +} /* Get the complex mode from the component mode. */ extern const unsigned char mode_complex[NUM_MACHINE_MODES]; @@ -483,17 +550,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 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); } /* Set mode iterator *ITER to the mode that is two times wider than the @@ -502,7 +569,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 (); } } diff --git a/gcc/omp-low.c b/gcc/omp-low.c index 3041a67..13f3435 100644 --- a/gcc/omp-low.c +++ b/gcc/omp-low.c @@ -4314,8 +4314,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); tree type = lang_hooks.types.type_for_mode (mode, 1); if (type == NULL_TREE || TYPE_MODE (type) != mode) diff --git a/gcc/optabs-libfuncs.c b/gcc/optabs-libfuncs.c index 79a07d6..9d9ffbd 100644 --- a/gcc/optabs-libfuncs.c +++ b/gcc/optabs-libfuncs.c @@ -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); buf[len + 1] = '0' + i; set_optab_libfunc (tab, mode, buf); - mode = GET_MODE_2XWIDER_MODE (mode); } } diff --git a/gcc/optabs-query.c b/gcc/optabs-query.c index b60362a..fdde578 100644 --- a/gcc/optabs-query.c +++ b/gcc/optabs-query.c @@ -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); diff --git a/gcc/optabs.c b/gcc/optabs.c index 6c859b2..5dab1b4 100644 --- a/gcc/optabs.c +++ b/gcc/optabs.c @@ -1184,13 +1184,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); @@ -1251,14 +1251,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; @@ -3699,7 +3699,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); diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index a1070fb..92b7580 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -5613,13 +5613,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) == 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); if (targetm.mode_rep_extended (i, wider) == SIGN_EXTEND /* We can only check sign-bit copies starting from the diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index 954e046..834cf8b 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -2709,7 +2709,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); @@ -2746,7 +2747,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; } diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c index b3edcc0..e0883ff 100644 --- a/gcc/tree-ssa-math-opts.c +++ b/gcc/tree-ssa-math-opts.c @@ -3160,8 +3160,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; } @@ -3342,8 +3342,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; } diff --git a/gcc/tree-switch-conversion.c b/gcc/tree-switch-conversion.c index 8b64f4b..62c3a78 100644 --- a/gcc/tree-switch-conversion.c +++ b/gcc/tree-switch-conversion.c @@ -989,8 +989,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; } diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 600634d..f3322b6 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -9995,7 +9995,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 @@ -10004,15 +10004,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 diff --git a/gcc/var-tracking.c b/gcc/var-tracking.c index 74101d2..cd29dc6 100644 --- a/gcc/var-tracking.c +++ b/gcc/var-tracking.c @@ -8705,12 +8705,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]))