From ae9270466ed530df375bcaf6b3d834dbef6e3965 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Wed, 30 Aug 2017 11:14:49 +0000 Subject: [PATCH] [39/77] Two changes to the get_best_mode interface get_best_mode always returns a scalar_int_mode on success, so this patch makes that explicit in the type system. Also, the "largest_mode" argument is used simply to provide a maximum size, and in practice that size is always a compile-time constant, even when the concept of variable-sized modes is added later. The patch therefore passes the size directly. 2017-08-30 Richard Sandiford Alan Hayward David Sherwood gcc/ * machmode.h (bit_field_mode_iterator::next_mode): Take a pointer to a scalar_int_mode instead of a machine_mode. (bit_field_mode_iterator::m_mode): Change type to opt_scalar_int_mode. (get_best_mode): Return a boolean and use a pointer argument to store the selected mode. Replace the limit mode parameter with a bit limit. * expmed.c (adjust_bit_field_mem_for_reg): Use scalar_int_mode for the values returned by bit_field_mode_iterator::next_mode. (store_bit_field): Update call to get_best_mode. (store_fixed_bit_field): Likewise. (extract_fixed_bit_field): Likewise. * expr.c (optimize_bitfield_assignment_op): Likewise. * fold-const.c (optimize_bit_field_compare): Likewise. (fold_truth_andor_1): Likewise. * stor-layout.c (bit_field_mode_iterator::next_mode): As above. Update for new type of m_mode. (get_best_mode): As above. Co-Authored-By: Alan Hayward Co-Authored-By: David Sherwood From-SVN: r251491 --- gcc/ChangeLog | 21 +++++++++++++++++++++ gcc/expmed.c | 37 +++++++++++++++++++------------------ gcc/expr.c | 13 +++++++------ gcc/fold-const.c | 30 ++++++++++++++---------------- gcc/machmode.h | 12 +++++------- gcc/stor-layout.c | 44 ++++++++++++++++++++++++-------------------- 6 files changed, 90 insertions(+), 67 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6b028e45276..ac442510201 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2017-08-30 Richard Sandiford + Alan Hayward + David Sherwood + + * machmode.h (bit_field_mode_iterator::next_mode): Take a pointer + to a scalar_int_mode instead of a machine_mode. + (bit_field_mode_iterator::m_mode): Change type to opt_scalar_int_mode. + (get_best_mode): Return a boolean and use a pointer argument to store + the selected mode. Replace the limit mode parameter with a bit limit. + * expmed.c (adjust_bit_field_mem_for_reg): Use scalar_int_mode + for the values returned by bit_field_mode_iterator::next_mode. + (store_bit_field): Update call to get_best_mode. + (store_fixed_bit_field): Likewise. + (extract_fixed_bit_field): Likewise. + * expr.c (optimize_bitfield_assignment_op): Likewise. + * fold-const.c (optimize_bit_field_compare): Likewise. + (fold_truth_andor_1): Likewise. + * stor-layout.c (bit_field_mode_iterator::next_mode): As above. + Update for new type of m_mode. + (get_best_mode): As above. + 2017-08-30 Richard Sandiford Alan Hayward David Sherwood diff --git a/gcc/expmed.c b/gcc/expmed.c index 051e048e806..641bc244a30 100644 --- a/gcc/expmed.c +++ b/gcc/expmed.c @@ -461,7 +461,7 @@ adjust_bit_field_mem_for_reg (enum extraction_pattern pattern, bit_field_mode_iterator iter (bitsize, bitnum, bitregion_start, bitregion_end, MEM_ALIGN (op0), MEM_VOLATILE_P (op0)); - machine_mode best_mode; + scalar_int_mode best_mode; if (iter.next_mode (&best_mode)) { /* We can use a memory in BEST_MODE. See whether this is true for @@ -479,7 +479,7 @@ adjust_bit_field_mem_for_reg (enum extraction_pattern pattern, fieldmode)) limit_mode = insn.field_mode; - machine_mode wider_mode; + scalar_int_mode wider_mode; while (iter.next_mode (&wider_mode) && GET_MODE_SIZE (wider_mode) <= GET_MODE_SIZE (limit_mode)) best_mode = wider_mode; @@ -1095,7 +1095,8 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, bit region. */ if (MEM_P (str_rtx) && bitregion_start > 0) { - machine_mode bestmode; + scalar_int_mode best_mode; + machine_mode addr_mode = VOIDmode; HOST_WIDE_INT offset, size; gcc_assert ((bitregion_start % BITS_PER_UNIT) == 0); @@ -1105,11 +1106,13 @@ store_bit_field (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, size = (bitnum + bitsize + BITS_PER_UNIT - 1) / BITS_PER_UNIT; bitregion_end -= bitregion_start; bitregion_start = 0; - bestmode = get_best_mode (bitsize, bitnum, - bitregion_start, bitregion_end, - MEM_ALIGN (str_rtx), VOIDmode, - MEM_VOLATILE_P (str_rtx)); - str_rtx = adjust_bitfield_address_size (str_rtx, bestmode, offset, size); + if (get_best_mode (bitsize, bitnum, + bitregion_start, bitregion_end, + MEM_ALIGN (str_rtx), INT_MAX, + MEM_VOLATILE_P (str_rtx), &best_mode)) + addr_mode = best_mode; + str_rtx = adjust_bitfield_address_size (str_rtx, addr_mode, + offset, size); } if (!store_bit_field_1 (str_rtx, bitsize, bitnum, @@ -1143,10 +1146,10 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, if (GET_MODE_BITSIZE (mode) == 0 || GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (word_mode)) mode = word_mode; - mode = get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end, - MEM_ALIGN (op0), mode, MEM_VOLATILE_P (op0)); - - if (mode == VOIDmode) + scalar_int_mode best_mode; + if (!get_best_mode (bitsize, bitnum, bitregion_start, bitregion_end, + MEM_ALIGN (op0), GET_MODE_BITSIZE (mode), + MEM_VOLATILE_P (op0), &best_mode)) { /* The only way this should occur is if the field spans word boundaries. */ @@ -1155,7 +1158,7 @@ store_fixed_bit_field (rtx op0, unsigned HOST_WIDE_INT bitsize, return; } - op0 = narrow_bit_field_mem (op0, mode, bitsize, bitnum, &bitnum); + op0 = narrow_bit_field_mem (op0, best_mode, bitsize, bitnum, &bitnum); } store_fixed_bit_field_1 (op0, bitsize, bitnum, value, reverse); @@ -1998,11 +2001,9 @@ extract_fixed_bit_field (machine_mode tmode, rtx op0, { if (MEM_P (op0)) { - machine_mode mode - = get_best_mode (bitsize, bitnum, 0, 0, MEM_ALIGN (op0), word_mode, - MEM_VOLATILE_P (op0)); - - if (mode == VOIDmode) + scalar_int_mode mode; + if (!get_best_mode (bitsize, bitnum, 0, 0, MEM_ALIGN (op0), + BITS_PER_WORD, MEM_VOLATILE_P (op0), &mode)) /* The only way this should occur is if the field spans word boundaries. */ return extract_split_bit_field (op0, bitsize, bitnum, unsignedp, diff --git a/gcc/expr.c b/gcc/expr.c index 4299df23e14..0006377d989 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -4682,13 +4682,14 @@ optimize_bitfield_assignment_op (unsigned HOST_WIDE_INT bitsize, unsigned HOST_WIDE_INT offset1; if (str_bitsize == 0 || str_bitsize > BITS_PER_WORD) - str_mode = word_mode; - str_mode = get_best_mode (bitsize, bitpos, - bitregion_start, bitregion_end, - MEM_ALIGN (str_rtx), str_mode, 0); - if (str_mode == VOIDmode) + str_bitsize = BITS_PER_WORD; + + scalar_int_mode best_mode; + if (!get_best_mode (bitsize, bitpos, bitregion_start, bitregion_end, + MEM_ALIGN (str_rtx), str_bitsize, false, &best_mode)) return false; - str_bitsize = GET_MODE_BITSIZE (str_mode); + str_mode = best_mode; + str_bitsize = GET_MODE_BITSIZE (best_mode); offset1 = bitpos; bitpos %= str_bitsize; diff --git a/gcc/fold-const.c b/gcc/fold-const.c index d4d3c444297..492d7f16169 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -3934,7 +3934,8 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, tree type = TREE_TYPE (lhs); tree unsigned_type; int const_p = TREE_CODE (rhs) == INTEGER_CST; - machine_mode lmode, rmode, nmode; + machine_mode lmode, rmode; + scalar_int_mode nmode; int lunsignedp, runsignedp; int lreversep, rreversep; int lvolatilep = 0, rvolatilep = 0; @@ -3981,12 +3982,11 @@ optimize_bit_field_compare (location_t loc, enum tree_code code, /* See if we can find a mode to refer to this field. We should be able to, but fail if we can't. */ - nmode = get_best_mode (lbitsize, lbitpos, bitstart, bitend, - const_p ? TYPE_ALIGN (TREE_TYPE (linner)) - : MIN (TYPE_ALIGN (TREE_TYPE (linner)), - TYPE_ALIGN (TREE_TYPE (rinner))), - word_mode, false); - if (nmode == VOIDmode) + if (!get_best_mode (lbitsize, lbitpos, bitstart, bitend, + const_p ? TYPE_ALIGN (TREE_TYPE (linner)) + : MIN (TYPE_ALIGN (TREE_TYPE (linner)), + TYPE_ALIGN (TREE_TYPE (rinner))), + BITS_PER_WORD, false, &nmode)) return 0; /* Set signed and unsigned types of the precision of this mode for the @@ -5591,7 +5591,7 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type, int ll_unsignedp, lr_unsignedp, rl_unsignedp, rr_unsignedp; int ll_reversep, lr_reversep, rl_reversep, rr_reversep; machine_mode ll_mode, lr_mode, rl_mode, rr_mode; - machine_mode lnmode, rnmode; + scalar_int_mode lnmode, rnmode; tree ll_mask, lr_mask, rl_mask, rr_mask; tree ll_and_mask, lr_and_mask, rl_and_mask, rr_and_mask; tree l_const, r_const; @@ -5777,10 +5777,9 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type, to be relative to a field of that size. */ first_bit = MIN (ll_bitpos, rl_bitpos); end_bit = MAX (ll_bitpos + ll_bitsize, rl_bitpos + rl_bitsize); - lnmode = get_best_mode (end_bit - first_bit, first_bit, 0, 0, - TYPE_ALIGN (TREE_TYPE (ll_inner)), word_mode, - volatilep); - if (lnmode == VOIDmode) + if (!get_best_mode (end_bit - first_bit, first_bit, 0, 0, + TYPE_ALIGN (TREE_TYPE (ll_inner)), BITS_PER_WORD, + volatilep, &lnmode)) return 0; lnbitsize = GET_MODE_BITSIZE (lnmode); @@ -5842,10 +5841,9 @@ fold_truth_andor_1 (location_t loc, enum tree_code code, tree truth_type, first_bit = MIN (lr_bitpos, rr_bitpos); end_bit = MAX (lr_bitpos + lr_bitsize, rr_bitpos + rr_bitsize); - rnmode = get_best_mode (end_bit - first_bit, first_bit, 0, 0, - TYPE_ALIGN (TREE_TYPE (lr_inner)), word_mode, - volatilep); - if (rnmode == VOIDmode) + if (!get_best_mode (end_bit - first_bit, first_bit, 0, 0, + TYPE_ALIGN (TREE_TYPE (lr_inner)), BITS_PER_WORD, + volatilep, &rnmode)) return 0; rnbitsize = GET_MODE_BITSIZE (rnmode); diff --git a/gcc/machmode.h b/gcc/machmode.h index a9fc93a8fd2..5f3e031324e 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -617,11 +617,11 @@ public: bit_field_mode_iterator (HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT, HOST_WIDE_INT, unsigned int, bool); - bool next_mode (machine_mode *); + bool next_mode (scalar_int_mode *); bool prefer_smaller_modes (); private: - machine_mode m_mode; + opt_scalar_int_mode m_mode; /* We use signed values here because the bit position can be negative for invalid input such as gcc.dg/pr48335-8.c. */ HOST_WIDE_INT m_bitsize; @@ -635,11 +635,9 @@ private: /* Find the best mode to use to access a bit field. */ -extern machine_mode get_best_mode (int, int, - unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT, - unsigned int, - machine_mode, bool); +extern bool get_best_mode (int, int, unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT, unsigned int, + unsigned HOST_WIDE_INT, bool, scalar_int_mode *); /* Determine alignment, 1<=result<=BIGGEST_ALIGNMENT. */ diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index e37c15f3dad..707c077f1c9 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -2748,15 +2748,15 @@ bit_field_mode_iterator available, storing it in *OUT_MODE if so. */ bool -bit_field_mode_iterator::next_mode (machine_mode *out_mode) +bit_field_mode_iterator::next_mode (scalar_int_mode *out_mode) { - for (; m_mode != VOIDmode; - m_mode = GET_MODE_WIDER_MODE (m_mode).else_void ()) + scalar_int_mode mode; + for (; m_mode.exists (&mode); m_mode = GET_MODE_WIDER_MODE (mode)) { - unsigned int unit = GET_MODE_BITSIZE (m_mode); + unsigned int unit = GET_MODE_BITSIZE (mode); /* Skip modes that don't have full precision. */ - if (unit != GET_MODE_PRECISION (m_mode)) + if (unit != GET_MODE_PRECISION (mode)) continue; /* Stop if the mode is too wide to handle efficiently. */ @@ -2783,12 +2783,12 @@ bit_field_mode_iterator::next_mode (machine_mode *out_mode) break; /* Stop if the mode requires too much alignment. */ - if (GET_MODE_ALIGNMENT (m_mode) > m_align - && SLOW_UNALIGNED_ACCESS (m_mode, m_align)) + if (GET_MODE_ALIGNMENT (mode) > m_align + && SLOW_UNALIGNED_ACCESS (mode, m_align)) break; - *out_mode = m_mode; - m_mode = GET_MODE_WIDER_MODE (m_mode).else_void (); + *out_mode = mode; + m_mode = GET_MODE_WIDER_MODE (mode); m_count++; return true; } @@ -2815,12 +2815,14 @@ bit_field_mode_iterator::prefer_smaller_modes () memory access to that range. Otherwise, we are allowed to touch any adjacent non bit-fields. - The underlying object is known to be aligned to a boundary of ALIGN bits. - If LARGEST_MODE is not VOIDmode, it means that we should not use a mode - larger than LARGEST_MODE (usually SImode). + The chosen mode must have no more than LARGEST_MODE_BITSIZE bits. + INT_MAX is a suitable value for LARGEST_MODE_BITSIZE if the caller + doesn't want to apply a specific limit. If no mode meets all these conditions, we return VOIDmode. + The underlying object is known to be aligned to a boundary of ALIGN bits. + If VOLATILEP is false and SLOW_BYTE_ACCESS is false, we return the smallest mode meeting these conditions. @@ -2831,17 +2833,18 @@ bit_field_mode_iterator::prefer_smaller_modes () If VOLATILEP is true the narrow_volatile_bitfields target hook is used to decide which of the above modes should be used. */ -machine_mode +bool get_best_mode (int bitsize, int bitpos, unsigned HOST_WIDE_INT bitregion_start, unsigned HOST_WIDE_INT bitregion_end, unsigned int align, - machine_mode largest_mode, bool volatilep) + unsigned HOST_WIDE_INT largest_mode_bitsize, bool volatilep, + scalar_int_mode *best_mode) { bit_field_mode_iterator iter (bitsize, bitpos, bitregion_start, bitregion_end, align, volatilep); - machine_mode widest_mode = VOIDmode; - machine_mode mode; + scalar_int_mode mode; + bool found = false; while (iter.next_mode (&mode) /* ??? For historical reasons, reject modes that would normally receive greater alignment, even if unaligned accesses are @@ -2900,14 +2903,15 @@ get_best_mode (int bitsize, int bitpos, so that the final bitfield reference still has a MEM_EXPR and MEM_OFFSET. */ && GET_MODE_ALIGNMENT (mode) <= align - && (largest_mode == VOIDmode - || GET_MODE_SIZE (mode) <= GET_MODE_SIZE (largest_mode))) + && GET_MODE_BITSIZE (mode) <= largest_mode_bitsize) { - widest_mode = mode; + *best_mode = mode; + found = true; if (iter.prefer_smaller_modes ()) break; } - return widest_mode; + + return found; } /* Gets minimal and maximal values for MODE (signed or unsigned depending on -- 2.30.2