This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [wide-int] Make the main tree decompose cheaper


On Wed, 23 Oct 2013, Richard Sandiford wrote:

> 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?

I like how this simplifies code, still storing two lengths is a bit
odd ... ah well.

Minor nits:

+             /* 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);

please merge into a single gcc_assert.

> +    /* 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;

split_length sounds generic while unextended and extended not.  I suggest
to either rename split_length to something clearly integer constant
specific or renaming unextended and extended to length1 and length2.

Otherwise ok.

Thanks,
Richard.


> 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
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE / SUSE Labs
SUSE LINUX Products GmbH - Nuernberg - AG Nuernberg - HRB 16746
GF: Jeff Hawn, Jennifer Guild, Felix Imend


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]