[PATCH] Speed up get_ref_base_and_extent

Richard Guenther rguenther@suse.de
Tue Mar 27 14:50:00 GMT 2007


This patch speeds up get_ref_base_and_extent significantly as I just
noticed that it's on top of the profile for tramp3d:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total
 time   seconds   seconds    calls   s/call   s/call  name
  2.62      1.95     1.95 25982327     0.00     0.00  ggc_alloc_stat
  2.35      3.69     1.75  3090386     0.00     0.00  gt_ggc_mx_lang_tree_node
  2.05      5.21     1.52 51215344     0.00     0.00  ggc_set_mark
  1.92      6.63     1.42 19137523     0.00     0.00  mul_double_with_sign

this is because we use trees to track the (constant) bit offset which
we get from (constant) byte offsets by multiplying with BITS_PER_UNIT...

Luckily we don't check for overflow now, but just take the lower part
of the resulting bit_offset to store it into the return location.

So this patch doesn't change this part but only exchanges all the
intermediate computation to work on HOST_WIDE_INTs instead.  Which gives 
us

  0.02     55.64     0.01   239633     0.00     0.00  mul_double_with_sign

way down on the radar (and we might be able to save some memory on
tree int nodes as well).

Bootstrapped on x86_64-unknown-linux-gnu, I'll apply this to
mainline after testing finished.

If somebody is concerned about bit_offset overflowing I can incrementally
fix this by tracking the bit part of the offset separately so the maximum
allowed (byte) offset will be max (HOST_WIDE_INT) which is reasonable.
Of course having a TARGET_SIZE_TYPE_WIDE_INT would be nice here ;)

Richard.


2007-03-27  Richard Guenther  <rguenther@suse.de>

	* tree-dfa.c (get_ref_base_and_extent): Replace bit_offset and
	computations with it with a HOST_WIDE_INT variable.  

Index: tree-dfa.c
===================================================================
*** tree-dfa.c	(revision 123218)
--- tree-dfa.c	(working copy)
*************** get_ref_base_and_extent (tree exp, HOST_
*** 859,865 ****
    HOST_WIDE_INT bitsize = -1;
    HOST_WIDE_INT maxsize = -1;
    tree size_tree = NULL_TREE;
!   tree bit_offset = bitsize_zero_node;
    bool seen_variable_array_ref = false;
  
    gcc_assert (!SSA_VAR_P (exp));
--- 859,865 ----
    HOST_WIDE_INT bitsize = -1;
    HOST_WIDE_INT maxsize = -1;
    tree size_tree = NULL_TREE;
!   HOST_WIDE_INT bit_offset = 0;
    bool seen_variable_array_ref = false;
  
    gcc_assert (!SSA_VAR_P (exp));
*************** get_ref_base_and_extent (tree exp, HOST_
*** 896,903 ****
        switch (TREE_CODE (exp))
  	{
  	case BIT_FIELD_REF:
! 	  bit_offset = size_binop (PLUS_EXPR, bit_offset,
! 				   TREE_OPERAND (exp, 2));
  	  break;
  
  	case COMPONENT_REF:
--- 896,902 ----
        switch (TREE_CODE (exp))
  	{
  	case BIT_FIELD_REF:
! 	  bit_offset += tree_low_cst (TREE_OPERAND (exp, 2), 1);
  	  break;
  
  	case COMPONENT_REF:
*************** get_ref_base_and_extent (tree exp, HOST_
*** 907,920 ****
  
  	    if (this_offset && TREE_CODE (this_offset) == INTEGER_CST)
  	      {
! 		this_offset = size_binop (MULT_EXPR,
! 					  fold_convert (bitsizetype,
! 							this_offset),
! 					  bitsize_unit_node);
! 		bit_offset = size_binop (PLUS_EXPR,
! 				         bit_offset, this_offset);
! 		bit_offset = size_binop (PLUS_EXPR, bit_offset,
! 					 DECL_FIELD_BIT_OFFSET (field));
  	      }
  	    else
  	      {
--- 906,916 ----
  
  	    if (this_offset && TREE_CODE (this_offset) == INTEGER_CST)
  	      {
! 		HOST_WIDE_INT hthis_offset = tree_low_cst (this_offset, 1);
! 
! 		hthis_offset *= BITS_PER_UNIT;
! 		bit_offset += hthis_offset;
! 		bit_offset += tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1);
  	      }
  	    else
  	      {
*************** get_ref_base_and_extent (tree exp, HOST_
*** 925,932 ****
  		if (maxsize != -1
  		    && csize && host_integerp (csize, 1))
  		  {
! 		    maxsize = (TREE_INT_CST_LOW (csize)
! 			       - TREE_INT_CST_LOW (bit_offset));
  		  }
  		else
  		  maxsize = -1;
--- 921,927 ----
  		if (maxsize != -1
  		    && csize && host_integerp (csize, 1))
  		  {
! 		    maxsize = (TREE_INT_CST_LOW (csize) - bit_offset);
  		  }
  		else
  		  maxsize = -1;
*************** get_ref_base_and_extent (tree exp, HOST_
*** 941,957 ****
  	    tree low_bound = array_ref_low_bound (exp);
  	    tree unit_size = array_ref_element_size (exp);
  
! 	    if (! integer_zerop (low_bound))
! 	      index = fold_build2 (MINUS_EXPR, TREE_TYPE (index),
! 				   index, low_bound);
! 	    index = size_binop (MULT_EXPR,
! 				fold_convert (sizetype, index), unit_size);
! 	    if (TREE_CODE (index) == INTEGER_CST)
  	      {
! 		index = size_binop (MULT_EXPR,
! 				    fold_convert (bitsizetype, index),
! 				    bitsize_unit_node);
! 		bit_offset = size_binop (PLUS_EXPR, bit_offset, index);
  
  		/* An array ref with a constant index up in the structure
  		   hierarchy will constrain the size of any variable array ref
--- 936,952 ----
  	    tree low_bound = array_ref_low_bound (exp);
  	    tree unit_size = array_ref_element_size (exp);
  
! 	    /* If the resulting bit-offset is constant, track it.  */
! 	    if (host_integerp (index, 0)
! 		&& host_integerp (low_bound, 0)
! 		&& host_integerp (unit_size, 1))
  	      {
! 		HOST_WIDE_INT hindex = tree_low_cst (index, 0);
! 
! 		hindex -= tree_low_cst (low_bound, 0);
! 		hindex *= tree_low_cst (unit_size, 1);
! 		hindex *= BITS_PER_UNIT;
! 		bit_offset += hindex;
  
  		/* An array ref with a constant index up in the structure
  		   hierarchy will constrain the size of any variable array ref
*************** get_ref_base_and_extent (tree exp, HOST_
*** 967,974 ****
  		if (maxsize != -1
  		    && asize && host_integerp (asize, 1))
  		  {
! 		    maxsize = (TREE_INT_CST_LOW (asize)
! 			       - TREE_INT_CST_LOW (bit_offset));
  		  }
  		else
  		  maxsize = -1;
--- 962,968 ----
  		if (maxsize != -1
  		    && asize && host_integerp (asize, 1))
  		  {
! 		    maxsize = (TREE_INT_CST_LOW (asize) - bit_offset);
  		  }
  		else
  		  maxsize = -1;
*************** get_ref_base_and_extent (tree exp, HOST_
*** 984,991 ****
  	  break;
  
  	case IMAGPART_EXPR:
! 	  bit_offset = size_binop (PLUS_EXPR, bit_offset,
! 				   bitsize_int (bitsize));
  	  break;
  
  	case VIEW_CONVERT_EXPR:
--- 978,984 ----
  	  break;
  
  	case IMAGPART_EXPR:
! 	  bit_offset += bitsize;
  	  break;
  
  	case VIEW_CONVERT_EXPR:
*************** get_ref_base_and_extent (tree exp, HOST_
*** 1011,1024 ****
    if (seen_variable_array_ref
        && maxsize != -1
        && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
!       && TREE_INT_CST_LOW (bit_offset) + maxsize
! 	 == TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))
      maxsize = -1;
  
    /* ???  Due to negative offsets in ARRAY_REF we can end up with
       negative bit_offset here.  We might want to store a zero offset
       in this case.  */
!   *poffset = TREE_INT_CST_LOW (bit_offset);
    *psize = bitsize;
    *pmax_size = maxsize;
  
--- 1004,1017 ----
    if (seen_variable_array_ref
        && maxsize != -1
        && host_integerp (TYPE_SIZE (TREE_TYPE (exp)), 1)
!       && bit_offset + maxsize
! 	   == (signed)TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))))
      maxsize = -1;
  
    /* ???  Due to negative offsets in ARRAY_REF we can end up with
       negative bit_offset here.  We might want to store a zero offset
       in this case.  */
!   *poffset = bit_offset;
    *psize = bitsize;
    *pmax_size = maxsize;
  



More information about the Gcc-patches mailing list