[66/77] Use scalar_mode for constant integers
authorRichard Sandiford <richard.sandiford@linaro.org>
Wed, 30 Aug 2017 11:19:39 +0000 (11:19 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 30 Aug 2017 11:19:39 +0000 (11:19 +0000)
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  <richard.sandiford@linaro.org>
    Alan Hayward  <alan.hayward@arm.com>
    David Sherwood  <david.sherwood@arm.com>

gcc/
* emit-rtl.c (immed_double_const): Use is_a <scalar_mode> instead
of separate mode class checks.  Do not allow vector modes here.
(immed_wide_int_const): Use as_a <scalar_mode>.
* explow.c (trunc_int_for_mode): Likewise.
* rtl.h (wi::int_traits<rtx_mode_t>::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.

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

gcc/ChangeLog
gcc/dwarf2out.c
gcc/emit-rtl.c
gcc/explow.c
gcc/rtl.h
gcc/simplify-rtx.c

index f67f411491d0725c51ef35ba49830eedfea87057..ed48b55cab9fa0c57dd43670eb017a266bc5925e 100644 (file)
@@ -1,3 +1,19 @@
+2017-08-30  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * emit-rtl.c (immed_double_const): Use is_a <scalar_mode> instead
+       of separate mode class checks.  Do not allow vector modes here.
+       (immed_wide_int_const): Use as_a <scalar_mode>.
+       * explow.c (trunc_int_for_mode): Likewise.
+       * rtl.h (wi::int_traits<rtx_mode_t>::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  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index f857a2773a27476bf8b15b7076f9d1e137f91e2b..42da36ca62e96dd01f6785074639d542eae72691 100644 (file)
@@ -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 <scalar_mode> (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<unsigned char> (length);
 
              insert_float (rtl, array);
index f0c09ffebe781eb7f7305cdf8999242e71a0959c..15c25ec4b4c8910ed5e479cd7dec19d03ade22bf 100644 (file)
@@ -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 <scalar_mode> (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 <scalar_mode> (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))
index 5079629bf6f7ebd59c0109282fb4f2679fe7c57a..ee20969d23a52e642b39d188d380e2388635a76c 100644 (file)
@@ -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 <scalar_mode> (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.  */
index 7363bd653523c84076c6fbec57fe237ee5e62da3..b8ba49fe2c5b84dffbdc4febb16250dedf46168a 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2120,8 +2120,7 @@ namespace wi
 inline unsigned int
 wi::int_traits <rtx_mode_t>::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 <scalar_mode> (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 <scalar_mode> (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 <scalar_mode> (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 <scalar_mode> (mode)), sgn);
 }
 
 extern void init_rtlanal (void);
index 109c01917ed27d0d8ae977fedf38caf2ff524b19..60ea9a12f57396f4d9a1a4b6b72f26beba464e48 100644 (file)
@@ -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);