This patch stores two array lengths in an INTEGER_CST: the length that
should be used when accessing the constant in its TYPE_PRECISION,
and the one that should be used for wider precisions.  This means that
the main tree decompose routine is just a simple storage_ref constructor.
It also means that cst_fits_shwi_p can be simplified back to its earlier
form (before r203602).

The patch also fixes wi::extended_tree <N>::get_len so that it uses
the right length when a tree has the same precision as addr_wide_int.
I just noticed this by inspection, I don't have a testcase.

(It might be better to require "address" trees to be smaller than
addr_wide_int though -- I can look into that if you agree.  But just
changing:

  gcc_checking_assert (TYPE_PRECISION (TREE_TYPE (t)) <= N);

to:

  gcc_checking_assert (TYPE_PRECISION (TREE_TYPE (t)) < N);

did trigger when I tried it in the first version of the wi::address patch.)

Tested on powerpc64-linux-gnu.  OK for wide-int?

Thanks,
Richard


Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c     2013-10-23 17:43:03.339574704 +0100
+++ gcc/c-family/c-common.c     2013-10-23 17:43:21.593731522 +0100
@@ -5463,7 +5463,7 @@ c_common_nodes_and_builtins (void)
   }
 
   /* This node must not be shared.  */
-  void_zero_node = make_int_cst (1);
+  void_zero_node = make_int_cst (1, 1);
   TREE_TYPE (void_zero_node) = void_type_node;
 
   void_list_node = build_void_list_node ();
@@ -5674,7 +5674,7 @@ c_common_nodes_and_builtins (void)
 
   /* Create the built-in __null node.  It is important that this is
      not shared.  */
-  null_node = make_int_cst (1);
+  null_node = make_int_cst (1, 1);
   TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
 
   /* Since builtin_types isn't gc'ed, don't export these nodes.  */
Index: gcc/lto-streamer-out.c
===================================================================
--- gcc/lto-streamer-out.c      2013-10-23 17:42:54.691500411 +0100
+++ gcc/lto-streamer-out.c      2013-10-23 17:43:05.853596301 +0100
@@ -712,6 +712,7 @@ #define visit(SIBLING) \
     {
       int i; 
       v = iterative_hash_host_wide_int (TREE_INT_CST_NUNITS (t), v);
+      v = iterative_hash_host_wide_int (TREE_INT_CST_EXT_NUNITS (t), v);
       for (i = 0; i < TREE_INT_CST_NUNITS (t); i++)
        v = iterative_hash_host_wide_int (TREE_INT_CST_ELT (t, i), v);
     }
Index: gcc/tree-core.h
===================================================================
--- gcc/tree-core.h     2013-10-23 17:42:54.691500411 +0100
+++ gcc/tree-core.h     2013-10-23 17:48:33.634415070 +0100
@@ -741,12 +741,25 @@ struct GTY(()) tree_base {
         of the field must be large enough to hold addr_space_t values.  */
       unsigned address_space : 8;
     } bits;
+
     /* The following fields are present in tree_base to save space.  The
        nodes using them do not require any of the flags above and so can
        make better use of the 4-byte sized word.  */
-    /* VEC length.  This field is only used with TREE_VEC and
-       TREE_INT_CST.  */
+
+    /* The number of HOST_WIDE_INTs in an INTEGER_CST.  */
+    struct {
+      /* The number of HOST_WIDE_INTs if the INTEGER_CST is accessed in
+        its native precision.  */
+      unsigned short unextended;
+
+      /* The number of HOST_WIDE_INTs if the INTEGER_CST is extended to
+        wider precisions based on its TYPE_SIGN.  */
+      unsigned short extended;
+    } split_length;
+
+    /* VEC length.  This field is only used with TREE_VEC.  */
     int length;
+
     /* SSA version number.  This field is only used with SSA_NAME.  */
     unsigned int version;
   } GTY((skip(""))) u;
Index: gcc/tree-streamer-in.c
===================================================================
--- gcc/tree-streamer-in.c      2013-10-23 17:42:54.691500411 +0100
+++ gcc/tree-streamer-in.c      2013-10-23 19:46:18.512517370 +0100
@@ -147,7 +147,7 @@ unpack_ts_base_value_fields (struct bitp
 unpack_ts_int_cst_value_fields (struct bitpack_d *bp, tree expr)
 {
   int i;
-  for (i = 0; i < TREE_INT_CST_NUNITS (expr); i++)
+  for (i = 0; i < TREE_INT_CST_EXT_NUNITS (expr); i++)
     TREE_INT_CST_ELT (expr, i) = bp_unpack_var_len_int (bp);
 }
 
@@ -571,8 +571,8 @@ streamer_alloc_tree (struct lto_input_bl
   else if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
     {
       unsigned HOST_WIDE_INT len = streamer_read_uhwi (ib);
-      result = make_int_cst (len);
-      TREE_INT_CST_NUNITS (result) = len;
+      unsigned HOST_WIDE_INT ext_len = streamer_read_uhwi (ib);
+      result = make_int_cst (len, ext_len);
     }
   else if (code == CALL_EXPR)
     {
Index: gcc/tree-streamer-out.c
===================================================================
--- gcc/tree-streamer-out.c     2013-10-23 17:42:54.691500411 +0100
+++ gcc/tree-streamer-out.c     2013-10-23 22:06:08.864297213 +0100
@@ -124,7 +124,7 @@ pack_ts_int_cst_value_fields (struct bit
   int i;
   /* Note that the number of elements has already been written out in
      streamer_write_tree_header.  */
-  for (i = 0; i < TREE_INT_CST_NUNITS (expr); i++)
+  for (i = 0; i < TREE_INT_CST_EXT_NUNITS (expr); i++)
     bp_pack_var_len_int (bp, TREE_INT_CST_ELT (expr, i));
 }
 
@@ -962,8 +962,9 @@ streamer_write_tree_header (struct outpu
     streamer_write_uhwi (ob, call_expr_nargs (expr));
   else if (CODE_CONTAINS_STRUCT (code, TS_INT_CST))
     {
-      gcc_assert (TREE_INT_CST_NUNITS (expr));
-    streamer_write_uhwi (ob, TREE_INT_CST_NUNITS (expr));
+      gcc_checking_assert (TREE_INT_CST_NUNITS (expr));
+      streamer_write_uhwi (ob, TREE_INT_CST_NUNITS (expr));
+      streamer_write_uhwi (ob, TREE_INT_CST_EXT_NUNITS (expr));
     }
 }
 
@@ -979,6 +980,10 @@ streamer_write_integer_cst (struct outpu
   gcc_assert (!TREE_OVERFLOW (cst));
   streamer_write_record_start (ob, LTO_integer_cst);
   stream_write_tree (ob, TREE_TYPE (cst), ref_p);
+  /* We're effectively streaming a non-sign-extended wide_int here,
+     so there's no need to stream TREE_INT_CST_EXT_NUNITS or any
+     array members beyond LEN.  We'll recreate the tree from the
+     wide_int and the type.  */
   streamer_write_uhwi (ob, len);
   for (i = 0; i < len; i++)
     streamer_write_hwi (ob, TREE_INT_CST_ELT (cst, i));
Index: gcc/tree.c
===================================================================
--- gcc/tree.c  2013-10-23 17:42:54.691500411 +0100
+++ gcc/tree.c  2013-10-23 21:27:23.241475405 +0100
@@ -559,7 +559,7 @@ init_ttree (void)
   int_cst_hash_table = htab_create_ggc (1024, int_cst_hash_hash,
                                        int_cst_hash_eq, NULL);
 
-  int_cst_node = make_int_cst (1);
+  int_cst_node = make_int_cst (1, 1);
 
   cl_option_hash_table = htab_create_ggc (64, cl_option_hash_hash,
                                          cl_option_hash_eq, NULL);
@@ -759,7 +759,7 @@ tree_size (const_tree node)
     {
     case INTEGER_CST:
       return (sizeof (struct tree_int_cst)
-             + (TREE_INT_CST_NUNITS (node) - 1) * sizeof (HOST_WIDE_INT));
+             + (TREE_INT_CST_EXT_NUNITS (node) - 1) * sizeof (HOST_WIDE_INT));
 
     case TREE_BINFO:
       return (offsetof (struct tree_binfo, base_binfos)
@@ -1083,6 +1083,53 @@ copy_list (tree list)
 }
 
 
+/* Return the value that TREE_INT_CST_EXT_NUNITS should have for an
+   INTEGER_CST with value CST and type TYPE.   */
+
+static unsigned int
+get_int_cst_ext_nunits (tree type, const wide_int &cst)
+{
+  gcc_checking_assert (cst.get_precision () == TYPE_PRECISION (type));
+  /* We need an extra zero HWI if CST is an unsigned integer with its
+     upper bit set, and if CST occupies a whole number of HWIs.  */
+  if (TYPE_UNSIGNED (type)
+      && wi::neg_p (cst)
+      && (cst.get_precision () % HOST_BITS_PER_WIDE_INT) == 0)
+    return cst.get_precision () / HOST_BITS_PER_WIDE_INT + 1;
+  return cst.get_len ();
+}
+
+/* Return a new INTEGER_CST with value CST and type TYPE.  */
+
+static tree
+build_new_int_cst (tree type, const wide_int &cst)
+{
+  unsigned int len = cst.get_len ();
+  unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
+  tree nt = make_int_cst (len, ext_len);
+
+  if (len < ext_len)
+    {
+      --ext_len;
+      TREE_INT_CST_ELT (nt, ext_len) = 0;
+      for (unsigned int i = len; i < ext_len; ++i)
+       TREE_INT_CST_ELT (nt, i) = -1;
+    }
+  else if (TYPE_UNSIGNED (type)
+          && cst.get_precision () < len * HOST_BITS_PER_WIDE_INT)
+    {
+      len--;
+      TREE_INT_CST_ELT (nt, len)
+       = zext_hwi (cst.elt (len),
+                   cst.get_precision () % HOST_BITS_PER_WIDE_INT);
+    }
+
+  for (unsigned int i = 0; i < len; i++)
+    TREE_INT_CST_ELT (nt, i) = cst.elt (i);
+  TREE_TYPE (nt) = type;
+  return nt;
+}
+
 /* Create an INT_CST node with a LOW value sign extended to TYPE.  */
 
 tree
@@ -1148,20 +1195,7 @@ force_fit_type (tree type, const wide_in
          || (overflowable > 0 && sign == SIGNED))
        {
          wide_int tmp = wide_int::from (cst, TYPE_PRECISION (type), sign);
-         int l = tmp.get_len ();
-         tree t = make_int_cst (l);
-         if (l > 1)
-           {
-             if (tmp.elt (l - 1) == 0)
-               gcc_assert (tmp.elt (l - 2) < 0);
-             if (tmp.elt (l - 1) == (HOST_WIDE_INT) -1)
-               gcc_assert (tmp.elt (l - 2) >= 0);
-           }
-
-         for (int i = 0; i < l; i++)
-           TREE_INT_CST_ELT (t, i) = tmp.elt (i);
-
-         TREE_TYPE (t) = type;
+         tree t = build_new_int_cst (type, tmp);
          TREE_OVERFLOW (t) = 1;
          return t;
        }
@@ -1199,7 +1233,8 @@ int_cst_hash_eq (const void *x, const vo
   const_tree const yt = (const_tree) y;
 
   if (TREE_TYPE (xt) != TREE_TYPE (yt)
-      || TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt))
+      || TREE_INT_CST_NUNITS (xt) != TREE_INT_CST_NUNITS (yt)
+      || TREE_INT_CST_EXT_NUNITS (xt) != TREE_INT_CST_EXT_NUNITS (yt))
     return false;
 
   for (int i = 0; i < TREE_INT_CST_NUNITS (xt); i++)
@@ -1223,7 +1258,6 @@ wide_int_to_tree (tree type, const wide_
   tree t;
   int ix = -1;
   int limit = 0;
-  unsigned int i;
 
   gcc_assert (type);
   unsigned int prec = TYPE_PRECISION (type);
@@ -1240,11 +1274,7 @@ wide_int_to_tree (tree type, const wide_
     }
 
   wide_int cst = wide_int::from (pcst, prec, sgn);
-  unsigned int len = cst.get_len ();
-  unsigned int small_prec = prec & (HOST_BITS_PER_WIDE_INT - 1);
-  bool recanonize = sgn == UNSIGNED
-    && small_prec
-    && (prec + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT == len;
+  unsigned int ext_len = get_int_cst_ext_nunits (type, cst);
 
   switch (TREE_CODE (type))
     {
@@ -1314,74 +1344,60 @@ wide_int_to_tree (tree type, const wide_
       gcc_unreachable ();
     }
 
-  if (ix >= 0)
+  if (ext_len == 1)
     {
-      /* Look for it in the type's vector of small shared ints.  */
-      if (!TYPE_CACHED_VALUES_P (type))
+      /* We just need to store a single HOST_WIDE_INT.  */
+      HOST_WIDE_INT hwi;
+      if (TYPE_UNSIGNED (type))
+       hwi = cst.to_uhwi ();
+      else
+       hwi = cst.to_shwi ();
+      if (ix >= 0)
        {
-         TYPE_CACHED_VALUES_P (type) = 1;
-         TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
-       }
+         /* Look for it in the type's vector of small shared ints.  */
+         if (!TYPE_CACHED_VALUES_P (type))
+           {
+             TYPE_CACHED_VALUES_P (type) = 1;
+             TYPE_CACHED_VALUES (type) = make_tree_vec (limit);
+           }
 
-      t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
-      if (t)
-       {
-         /* Make sure no one is clobbering the shared constant.  We
-            must be careful here because tree-csts and wide-ints are
-            not canonicalized in the same way.  */
-         gcc_assert (TREE_TYPE (t) == type);
-         gcc_assert (TREE_INT_CST_NUNITS (t) == (int)len);
-         if (recanonize)
+         t = TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix);
+         if (t)
            {
-             len--;
-             gcc_assert (sext_hwi (TREE_INT_CST_ELT (t, len), small_prec) 
-                         == cst.elt (len));
+             /* Make sure no one is clobbering the shared constant.  We
+                must be careful here because tree-csts and wide-ints are
+                not canonicalized in the same way.  */
+             gcc_assert (TREE_TYPE (t) == type);
+             gcc_assert (TREE_INT_CST_NUNITS (t) == 1);
+             gcc_assert (TREE_INT_CST_EXT_NUNITS (t) == 1);
+             gcc_assert (TREE_INT_CST_ELT (t, 0) == hwi);
            }
-         for (i = 0; i < len; i++)
-           gcc_assert (TREE_INT_CST_ELT (t, i) == cst.elt (i));
-       }
-      else
-       {
-         /* Create a new shared int.  */
-         t = make_int_cst (cst.get_len ());
-         TREE_INT_CST_NUNITS (t) = len;
-         if (recanonize)
+         else
            {
-             len--;
-             TREE_INT_CST_ELT (t, len) = zext_hwi (cst.elt (len), small_prec);
+             /* Create a new shared int.  */
+             t = build_new_int_cst (type, cst);
+             TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
            }
-         for (i = 0; i < len; i++)
-           TREE_INT_CST_ELT (t, i) = cst.elt (i);
-         TREE_TYPE (t) = type;
-         
-         TREE_VEC_ELT (TYPE_CACHED_VALUES (type), ix) = t;
        }
-    }
-  else if (cst.get_len () == 1
-          && (TYPE_SIGN (type) == SIGNED
-              || recanonize
-              || cst.elt (0) >= 0))
-    {
-      /* 99.99% of all int csts will fit in a single HWI.  Do that one
-        efficiently.  */
-         /* Use the cache of larger shared ints.  */
-      void **slot;
-
-      if (recanonize)
-       TREE_INT_CST_ELT (int_cst_node, 0) = zext_hwi (cst.elt (0), small_prec);
       else
-       TREE_INT_CST_ELT (int_cst_node, 0) = cst.elt (0);
-      TREE_TYPE (int_cst_node) = type;
-
-      slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
-      t = (tree) *slot;
-      if (!t)
        {
-         /* Insert this one into the hash table.  */
-         t = int_cst_node;
-         *slot = t;
-         /* Make a new node for next time round.  */
-         int_cst_node = make_int_cst (1);
+         /* Use the cache of larger shared ints, using int_cst_node as
+            a temporary.  */
+         void **slot;
+
+         TREE_INT_CST_ELT (int_cst_node, 0) = hwi;
+         TREE_TYPE (int_cst_node) = type;
+
+         slot = htab_find_slot (int_cst_hash_table, int_cst_node, INSERT);
+         t = (tree) *slot;
+         if (!t)
+           {
+             /* Insert this one into the hash table.  */
+             t = int_cst_node;
+             *slot = t;
+             /* Make a new node for next time round.  */
+             int_cst_node = make_int_cst (1, 1);
+           }
        }
     }
   else
@@ -1390,32 +1406,8 @@ wide_int_to_tree (tree type, const wide_
         for the gc to take care of.  There will not be enough of them
         to worry about.  */
       void **slot;
-      tree nt;
-      if (!recanonize
-         && TYPE_SIGN (type) == UNSIGNED 
-         && cst.elt (len - 1) < 0)
-       {
-         unsigned int blocks_needed 
-           = (prec + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT;
-
-         nt = make_int_cst (blocks_needed + 1);
-         for (i = len; i < blocks_needed; i++)
-           TREE_INT_CST_ELT (nt, i) = (HOST_WIDE_INT)-1;
-    
-         TREE_INT_CST_ELT (nt, blocks_needed) = 0;
-       }
-      else
-       nt = make_int_cst (len);
-      if (recanonize)
-       {
-         len--;
-         TREE_INT_CST_ELT (nt, len) = zext_hwi (cst.elt (len), small_prec);
-       }
-       
-      for (i = 0; i < len; i++)
-       TREE_INT_CST_ELT (nt, i) = cst.elt (i);
-      TREE_TYPE (nt) = type;
 
+      tree nt = build_new_int_cst (type, cst);
       slot = htab_find_slot (int_cst_hash_table, nt, INSERT);
       t = (tree) *slot;
       if (!t)
@@ -2028,10 +2020,10 @@ build_case_label (tree low_value, tree h
 /* Build a newly constructed INETEGER_CST node of length LEN.  */
 
 tree
-make_int_cst_stat (int len MEM_STAT_DECL)
+make_int_cst_stat (int len, int ext_len MEM_STAT_DECL)
 {
   tree t;
-  int length = (len - 1) * sizeof (tree) + sizeof (struct tree_int_cst);
+  int length = (ext_len - 1) * sizeof (tree) + sizeof (struct tree_int_cst);
 
   gcc_assert (len);
   record_node_allocation_statistics (INTEGER_CST, length);
@@ -2040,6 +2032,7 @@ make_int_cst_stat (int len MEM_STAT_DECL
 
   TREE_SET_CODE (t, INTEGER_CST);
   TREE_INT_CST_NUNITS (t) = len;
+  TREE_INT_CST_EXT_NUNITS (t) = ext_len;
 
   TREE_CONSTANT (t) = 1;
 
@@ -10658,18 +10651,16 @@ widest_int_cst_value (const_tree x)
 
 #if HOST_BITS_PER_WIDEST_INT > HOST_BITS_PER_WIDE_INT
   gcc_assert (HOST_BITS_PER_WIDEST_INT >= HOST_BITS_PER_DOUBLE_INT);
-  gcc_assert (TREE_INT_CST_NUNITS (x) <= 2
-             || (TREE_INT_CST_NUNITS (x) == 3 && TREE_INT_CST_ELT (x, 2) == 
0));
+  gcc_assert (TREE_INT_CST_NUNITS (x) == 2);
   
   if (TREE_INT_CST_NUNITS (x) == 1)
-    val = ((HOST_WIDEST_INT)val << HOST_BITS_PER_WIDE_INT) >> 
HOST_BITS_PER_WIDE_INT;
+    val = HOST_WIDE_INT (val);
   else
     val |= (((unsigned HOST_WIDEST_INT) TREE_INT_CST_ELT (x, 1))
            << HOST_BITS_PER_WIDE_INT);
 #else
   /* Make sure the sign-extended value will fit in a HOST_WIDE_INT.  */
-  gcc_assert (TREE_INT_CST_NUNITS (x) == 1
-             || (TREE_INT_CST_NUNITS (x) == 2 && TREE_INT_CST_ELT (x, 1) == 
0));
+  gcc_assert (TREE_INT_CST_NUNITS (x) == 1);
 #endif
 
   if (bits < HOST_BITS_PER_WIDEST_INT)
Index: gcc/tree.def
===================================================================
--- gcc/tree.def        2013-10-23 17:43:03.340574712 +0100
+++ gcc/tree.def        2013-10-23 21:35:09.182917109 +0100
@@ -257,16 +257,24 @@ DEFTREECODE (LANG_TYPE, "lang_type", tcc
 
 /* First, the constants.  */
 
-/* Contents are in an array of HOST_WIDE_INTS.  The array may be as
-   wide as the precision requires but may be shorter when all of the
-   upper bits are sign bits.  The length of the array is given in
-   TREE_INT_CST_NUNITS and each element can be obtained using
-   TREE_INT_CST_ELT.  INTEGER_CST nodes can be shared, and therefore
-   should be considered read only.  They should be copied, before
-   setting a flag such as TREE_OVERFLOW.  If an INTEGER_CST has
-   TREE_OVERFLOW already set, it is known to be unique.  INTEGER_CST
-   nodes are created for the integral types, for pointer types and for
-   vector and float types in some circumstances.  */
+/* Contents are in an array of HOST_WIDE_INTs.
+
+   We often access these constants both in their native precision and
+   in wider precisions (with the constant being implicitly extended
+   according to TYPE_SIGN).  In each case, the useful part of the array
+   may be as wide as the precision requires but may be shorter when all
+   of the upper bits are sign bits.  The length of the array when accessed
+   in the constant's native precision is given by TREE_INT_CST_NUNITS.
+   The length of the array when accessed in wider precisions is given
+   by TREE_INT_CST_EXT_NUNITS.  Each element can be obtained using
+   TREE_INT_CST_ELT.
+
+   INTEGER_CST nodes can be shared, and therefore should be considered
+   read only.  They should be copied before setting a flag such as
+   TREE_OVERFLOW.  If an INTEGER_CST has TREE_OVERFLOW already set,
+   it is known to be unique.  INTEGER_CST nodes are created for the
+   integral types, for pointer types and for vector and float types in
+   some circumstances.  */
 DEFTREECODE (INTEGER_CST, "integer_cst", tcc_constant, 0)
 
 /* Contents are in TREE_REAL_CST field.  */
Index: gcc/tree.h
===================================================================
--- gcc/tree.h  2013-10-23 17:42:54.691500411 +0100
+++ gcc/tree.h  2013-10-23 17:43:05.857596336 +0100
@@ -883,7 +883,10 @@ #define INT_CST_LT(A, B)                           \
 #define INT_CST_LT_UNSIGNED(A, B)                      \
   (wi::ltu_p (A, B))
 
-#define TREE_INT_CST_NUNITS(NODE) (INTEGER_CST_CHECK (NODE)->base.u.length)
+#define TREE_INT_CST_NUNITS(NODE) \
+  (INTEGER_CST_CHECK (NODE)->base.u.split_length.unextended)
+#define TREE_INT_CST_EXT_NUNITS(NODE) \
+  (INTEGER_CST_CHECK (NODE)->base.u.split_length.extended)
 #define TREE_INT_CST_ELT(NODE, I) TREE_INT_CST_ELT_CHECK (NODE, I)
 
 #define TREE_REAL_CST_PTR(NODE) (REAL_CST_CHECK (NODE)->real_cst.real_cst_ptr)
@@ -2862,8 +2865,9 @@ tree_int_cst_elt_check (const_tree __t,
 {
   if (TREE_CODE (__t) != INTEGER_CST)
     tree_check_failed (__t, __f, __l, __g, INTEGER_CST, 0);
-  if (__i < 0 || __i >= __t->base.u.length)
-    tree_int_cst_elt_check_failed (__i, __t->base.u.length, __f, __l, __g);
+  if (__i < 0 || __i >= __t->base.u.split_length.extended)
+    tree_int_cst_elt_check_failed (__i, __t->base.u.split_length.extended,
+                                  __f, __l, __g);
   return &CONST_CAST_TREE (__t)->int_cst.val[__i];
 }
 
@@ -2873,8 +2877,9 @@ tree_int_cst_elt_check (tree __t, int __
 {
   if (TREE_CODE (__t) != INTEGER_CST)
     tree_check_failed (__t, __f, __l, __g, INTEGER_CST, 0);
-  if (__i < 0 || __i >= __t->base.u.length)
-    tree_int_cst_elt_check_failed (__i, __t->base.u.length, __f, __l, __g);
+  if (__i < 0 || __i >= __t->base.u.split_length.extended)
+    tree_int_cst_elt_check_failed (__i, __t->base.u.split_length.extended,
+                                  __f, __l, __g);
   return &CONST_CAST_TREE (__t)->int_cst.val[__i];
 }
 
@@ -3111,7 +3116,7 @@ omp_clause_elt_check (const_tree __t, in
 
 /* Checks that X is integer constant that can be expressed in signed
    HOST_WIDE_INT without loss of precision.  This function differs
-   from the tree_fits_* versions in that the type of signedness of the
+   from the tree_fits_* versions in that the signedness of the
    type of X is not considered.  */
 
 static inline bool
@@ -3120,13 +3125,12 @@ cst_fits_shwi_p (const_tree x)
   if (TREE_CODE (x) != INTEGER_CST)
     return false;
 
-  return TREE_INT_CST_NUNITS (x) == 1
-    || (TREE_INT_CST_NUNITS (x) == 2 && TREE_INT_CST_ELT (x, 1) == 0);
+  return TREE_INT_CST_NUNITS (x) == 1;
 }
 
 /* Checks that X is integer constant that can be expressed in signed
    HOST_WIDE_INT without loss of precision.  This function differs
-   from the tree_fits_* versions in that the type of signedness of the
+   from the tree_fits_* versions in that the signedness of the
    type of X is not considered.  */
 
 static inline bool
@@ -3580,8 +3584,9 @@ #define make_tree_binfo(t) make_tree_bin
 
 /* Make a INTEGER_CST.  */
 
-extern tree make_int_cst_stat (int MEM_STAT_DECL);
-#define make_int_cst(t) make_int_cst_stat (t MEM_STAT_INFO)
+extern tree make_int_cst_stat (int, int MEM_STAT_DECL);
+#define make_int_cst(LEN, EXT_LEN) \
+  make_int_cst_stat (LEN, EXT_LEN MEM_STAT_INFO)
 
 /* Make a TREE_VEC.  */
 
@@ -5291,24 +5296,8 @@ wi::int_traits <const_tree>::get_precisi
 wi::int_traits <const_tree>::decompose (HOST_WIDE_INT *,
                                        unsigned int precision, const_tree x)
 {
-  unsigned int len = TREE_INT_CST_NUNITS (x);
-  const HOST_WIDE_INT *val = (const HOST_WIDE_INT *) &TREE_INT_CST_ELT (x, 0);
-  unsigned int max_len = ((precision + HOST_BITS_PER_WIDE_INT - 1)
-                         / HOST_BITS_PER_WIDE_INT);
-
-  gcc_checking_assert (precision == get_precision (x));
-
-  /* If an unsigned constant occupies a whole number of HWIs and has the
-     upper bit set, its representation includes an extra zero HWI,
-     so that the representation can be used for wider precisions.
-     Trim the length if we're accessing the tree in its own precision.  */
-  if (__builtin_expect (len > max_len, 0))
-    do
-      len--;
-    while (len > 1 && val[len - 1] == -1 && val[len - 2] < 0);
-
-  /* Signed and the rest of the unsigned cases are easy.  */
-  return wi::storage_ref (val, len, precision);
+  return wi::storage_ref (&TREE_INT_CST_ELT (x, 0), TREE_INT_CST_NUNITS (x),
+                         precision);
 }
 
 inline generic_wide_int <wi::extended_tree <MAX_BITSIZE_MODE_ANY_INT> >
@@ -5348,7 +5337,11 @@ wi::extended_tree <N>::get_val () const
 inline unsigned int
 wi::extended_tree <N>::get_len () const
 {
-  return TREE_INT_CST_NUNITS (m_t);
+  if (N == MAX_BITSIZE_MODE_ANY_INT
+      || N > TYPE_PRECISION (TREE_TYPE (m_t)))
+    return TREE_INT_CST_EXT_NUNITS (m_t);
+  else
+    return TREE_INT_CST_NUNITS (m_t);
 }
 
 namespace wi

Reply via email to