From 074473dd6e4b5f8789fe224d54014ba3d31c4983 Mon Sep 17 00:00:00 2001 From: rsandifo Date: Wed, 30 Aug 2017 11:19:39 +0000 Subject: [PATCH] [66/77] Use scalar_mode for constant integers This patch treats the mode associated with an integer constant as a scalar_mode. We can't use the more natural-sounding scalar_int_mode because we also use (const_int 0) for bounds-checking modes. (It might be worth adding a bounds-specific code instead, but that's for another day.) This exposes a latent bug in simplify_immed_subreg, which for vectors of CONST_WIDE_INTs would pass the vector mode rather than the element mode to rtx_mode_t. I think the: /* We can get a 0 for an error mark. */ || GET_MODE_CLASS (mode) == MODE_VECTOR_INT || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT in immed_double_const is dead. trunc_int_mode (via gen_int_mode) would go on to ICE if the mode fitted in a HWI, and surely plenty of other code would be confused to see a const_int be interpreted as a vector. We should instead be using CONST0_RTX (mode) if we need a safe constant for a particular mode. We didn't try to make these functions take scalar_mode arguments because in many cases that would be too invasive at this stage. Maybe it would become feasible in future. Also, the long-term direction should probably be to add modes to constant integers rather than have then as VOIDmode odd-ones-out. That would remove the need for rtx_mode_t and thus remove the question whether they should use scalar_int_mode, scalar_mode or machine_mode. The patch also uses scalar_mode for the CONST_DOUBLE handling in loc_descriptor. In that case the mode can legitimately be either floating-point or integral. 2017-08-30 Richard Sandiford Alan Hayward David Sherwood gcc/ * emit-rtl.c (immed_double_const): Use is_a instead of separate mode class checks. Do not allow vector modes here. (immed_wide_int_const): Use as_a . * explow.c (trunc_int_for_mode): Likewise. * rtl.h (wi::int_traits::get_precision): Likewise. (wi::shwi): Likewise. (wi::min_value): Likewise. (wi::max_value): Likewise. * dwarf2out.c (loc_descriptor): Likewise. * simplify-rtx.c (simplify_immed_subreg): Fix rtx_mode_t argument for CONST_WIDE_INT. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@251517 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 16 ++++++++++++++++ gcc/dwarf2out.c | 7 ++++--- gcc/emit-rtl.c | 19 ++++++------------- gcc/explow.c | 6 ++++-- gcc/rtl.h | 9 ++++----- gcc/simplify-rtx.c | 2 +- 6 files changed, 35 insertions(+), 24 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f67f411491d..ed48b55cab9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -2,6 +2,22 @@ Alan Hayward David Sherwood + * emit-rtl.c (immed_double_const): Use is_a instead + of separate mode class checks. Do not allow vector modes here. + (immed_wide_int_const): Use as_a . + * explow.c (trunc_int_for_mode): Likewise. + * rtl.h (wi::int_traits::get_precision): Likewise. + (wi::shwi): Likewise. + (wi::min_value): Likewise. + (wi::max_value): Likewise. + * dwarf2out.c (loc_descriptor): Likewise. + * simplify-rtx.c (simplify_immed_subreg): Fix rtx_mode_t argument + for CONST_WIDE_INT. + +2017-08-30 Richard Sandiford + Alan Hayward + David Sherwood + * tree.h (SCALAR_TYPE_MODE): New macro. * expr.c (expand_expr_addr_expr_1): Use it. (expand_expr_real_2): Likewise. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index f857a2773a2..42da36ca62e 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -15863,10 +15863,11 @@ loc_descriptor (rtx rtl, machine_mode mode, or a floating-point constant. A CONST_DOUBLE is used whenever the constant requires more than one word in order to be adequately represented. We output CONST_DOUBLEs as blocks. */ + scalar_mode smode = as_a (mode); loc_result = new_loc_descr (DW_OP_implicit_value, - GET_MODE_SIZE (mode), 0); + GET_MODE_SIZE (smode), 0); #if TARGET_SUPPORTS_WIDE_INT == 0 - if (!SCALAR_FLOAT_MODE_P (mode)) + if (!SCALAR_FLOAT_MODE_P (smode)) { loc_result->dw_loc_oprnd2.val_class = dw_val_class_const_double; loc_result->dw_loc_oprnd2.v.val_double @@ -15875,7 +15876,7 @@ loc_descriptor (rtx rtl, machine_mode mode, else #endif { - unsigned int length = GET_MODE_SIZE (mode); + unsigned int length = GET_MODE_SIZE (smode); unsigned char *array = ggc_vec_alloc (length); insert_float (rtl, array); diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index f0c09ffebe7..15c25ec4b4c 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -599,7 +599,8 @@ rtx immed_wide_int_const (const wide_int_ref &v, machine_mode mode) { unsigned int len = v.get_len (); - unsigned int prec = GET_MODE_PRECISION (mode); + /* Not scalar_int_mode because we also allow pointer bound modes. */ + unsigned int prec = GET_MODE_PRECISION (as_a (mode)); /* Allow truncation but not extension since we do not know if the number is signed or unsigned. */ @@ -659,18 +660,10 @@ immed_double_const (HOST_WIDE_INT i0, HOST_WIDE_INT i1, machine_mode mode) (i.e., i1 consists only from copies of the sign bit, and sign of i0 and i1 are the same), then we return a CONST_INT for i0. 3) Otherwise, we create a CONST_DOUBLE for i0 and i1. */ - if (mode != VOIDmode) - { - gcc_assert (GET_MODE_CLASS (mode) == MODE_INT - || GET_MODE_CLASS (mode) == MODE_PARTIAL_INT - /* We can get a 0 for an error mark. */ - || GET_MODE_CLASS (mode) == MODE_VECTOR_INT - || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT - || GET_MODE_CLASS (mode) == MODE_POINTER_BOUNDS); - - if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT) - return gen_int_mode (i0, mode); - } + scalar_mode smode; + if (is_a (mode, &smode) + && GET_MODE_BITSIZE (smode) <= HOST_BITS_PER_WIDE_INT) + return gen_int_mode (i0, mode); /* If this integer fits in one word, return a CONST_INT. */ if ((i1 == 0 && i0 >= 0) || (i1 == ~0 && i0 < 0)) diff --git a/gcc/explow.c b/gcc/explow.c index 5079629bf6f..ee20969d23a 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -49,14 +49,16 @@ static rtx break_out_memory_refs (rtx); HOST_WIDE_INT trunc_int_for_mode (HOST_WIDE_INT c, machine_mode mode) { - int width = GET_MODE_PRECISION (mode); + /* Not scalar_int_mode because we also allow pointer bound modes. */ + scalar_mode smode = as_a (mode); + int width = GET_MODE_PRECISION (smode); /* You want to truncate to a _what_? */ gcc_assert (SCALAR_INT_MODE_P (mode) || POINTER_BOUNDS_MODE_P (mode)); /* Canonicalize BImode to 0 and STORE_FLAG_VALUE. */ - if (mode == BImode) + if (smode == BImode) return c & 1 ? STORE_FLAG_VALUE : 0; /* Sign-extend for the requested mode. */ diff --git a/gcc/rtl.h b/gcc/rtl.h index 7363bd65352..b8ba49fe2c5 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2120,8 +2120,7 @@ namespace wi inline unsigned int wi::int_traits ::get_precision (const rtx_mode_t &x) { - gcc_checking_assert (x.second != BLKmode && x.second != VOIDmode); - return GET_MODE_PRECISION (x.second); + return GET_MODE_PRECISION (as_a (x.second)); } inline wi::storage_ref @@ -2166,7 +2165,7 @@ namespace wi inline wi::hwi_with_prec wi::shwi (HOST_WIDE_INT val, machine_mode mode) { - return shwi (val, GET_MODE_PRECISION (mode)); + return shwi (val, GET_MODE_PRECISION (as_a (mode))); } /* Produce the smallest number that is represented in MODE. The precision @@ -2174,7 +2173,7 @@ wi::shwi (HOST_WIDE_INT val, machine_mode mode) inline wide_int wi::min_value (machine_mode mode, signop sgn) { - return min_value (GET_MODE_PRECISION (mode), sgn); + return min_value (GET_MODE_PRECISION (as_a (mode)), sgn); } /* Produce the largest number that is represented in MODE. The precision @@ -2182,7 +2181,7 @@ wi::min_value (machine_mode mode, signop sgn) inline wide_int wi::max_value (machine_mode mode, signop sgn) { - return max_value (GET_MODE_PRECISION (mode), sgn); + return max_value (GET_MODE_PRECISION (as_a (mode)), sgn); } extern void init_rtlanal (void); diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 109c01917ed..60ea9a12f57 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -5794,7 +5794,7 @@ simplify_immed_subreg (machine_mode outermode, rtx op, case CONST_WIDE_INT: { - rtx_mode_t val = rtx_mode_t (el, innermode); + rtx_mode_t val = rtx_mode_t (el, GET_MODE_INNER (innermode)); unsigned char extend = wi::sign_mask (val); int prec = wi::get_precision (val); -- 2.11.4.GIT