This is the mail archive of the gcc@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]

Re: array reference optimization


Here's a revised version of the patch that changes a few of the
things mentioned yesterday afternoon.  To wit: 

  (1) Since layout_type should always be initializing TYPE_SIZE_UNIT,
      get_inner_reference does not check it for NULL.

  (2) size_in_bytes and int_size_in_bytes use TYPE_SIZE_UNIT.

In addition, I added a bit more commentary.


r~
Sat May 16 14:06:16 1998  Richard Henderson  <rth@cygnus.com>

        * tree.h (TYPE_SIZE_UNIT): New.
        (struct tree_type): Add size_unit member.
        * stor-layout.c (layout_type): Initialize it.
        * expr.c (get_inner_reference) [ARRAY_REF]: Use it.
        * tree.c (size_in_bytes, int_size_in_bytes): Likewise.

Index: expr.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.c,v
retrieving revision 1.57
diff -c -p -d -r1.57 expr.c
*** expr.c	1998/05/15 17:32:40	1.57
--- expr.c	1998/05/16 21:13:00
*************** get_inner_reference (exp, pbitsize, pbit
*** 4374,4379 ****
--- 4374,4380 ----
  	  tree low_bound
  	    = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
  	  tree index_type = TREE_TYPE (index);
+ 	  tree xindex;
  
  	  if (TYPE_PRECISION (index_type) != TYPE_PRECISION (sizetype))
  	    {
*************** get_inner_reference (exp, pbitsize, pbit
*** 4391,4411 ****
  	      index_type = TREE_TYPE (index);
  	    }
  
! 	  index = fold (build (MULT_EXPR, sbitsizetype, index,
! 			       convert (sbitsizetype,
! 					TYPE_SIZE (TREE_TYPE (exp)))));
  
! 	  if (TREE_CODE (index) == INTEGER_CST
! 	      && TREE_INT_CST_HIGH (index) == 0)
! 	    *pbitpos += TREE_INT_CST_LOW (index);
  	  else
  	    {
! 	      if (contains_placeholder_p (index))
! 		index = build (WITH_RECORD_EXPR, sizetype, index, exp);
  
! 	      offset = size_binop (PLUS_EXPR, offset,
! 				   size_binop (FLOOR_DIV_EXPR, index,
! 					       size_int (BITS_PER_UNIT)));
  	    }
  	}
        else if (TREE_CODE (exp) != NON_LVALUE_EXPR
--- 4392,4418 ----
  	      index_type = TREE_TYPE (index);
  	    }
  
! 	  xindex = fold (build (MULT_EXPR, sbitsizetype, index,
! 			        convert (sbitsizetype,
! 					 TYPE_SIZE (TREE_TYPE (exp)))));
  
! 	  if (TREE_CODE (xindex) == INTEGER_CST
! 	      && TREE_INT_CST_HIGH (xindex) == 0)
! 	    *pbitpos += TREE_INT_CST_LOW (xindex);
  	  else
  	    {
! 	      /* Either the bit offset calculated above is not constant, or
! 		 it overflowed.  In either case, redo the multiplication
! 		 against the size in units.  This is especially important
! 		 in the non-constant case to avoid a division at runtime.  */
! 	      xindex = fold (build (MULT_EXPR, ssizetype, index,
!                                     convert (ssizetype,
!                                          TYPE_SIZE_UNIT (TREE_TYPE (exp)))));
  
! 	      if (contains_placeholder_p (xindex))
! 		xindex = build (WITH_RECORD_EXPR, sizetype, xindex, exp);
! 
! 	      offset = size_binop (PLUS_EXPR, offset, xindex);
  	    }
  	}
        else if (TREE_CODE (exp) != NON_LVALUE_EXPR
Index: stor-layout.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/stor-layout.c,v
retrieving revision 1.14
diff -c -p -d -r1.14 stor-layout.c
*** stor-layout.c	1998/05/15 18:56:10	1.14
--- stor-layout.c	1998/05/16 21:13:00
*************** layout_type (type)
*** 720,730 ****
--- 720,732 ----
        TYPE_MODE (type) = smallest_mode_for_size (TYPE_PRECISION (type),
  						 MODE_INT);
        TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)), 0L);
+       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
        break;
  
      case REAL_TYPE:
        TYPE_MODE (type) = mode_for_size (TYPE_PRECISION (type), MODE_FLOAT, 0);
        TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)), 0L);
+       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
        break;
  
      case COMPLEX_TYPE:
*************** layout_type (type)
*** 735,763 ****
  			  ? MODE_COMPLEX_INT : MODE_COMPLEX_FLOAT),
  			 0);
        TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)), 0L);
        break;
  
      case VOID_TYPE:
        TYPE_SIZE (type) = size_zero_node;
        TYPE_ALIGN (type) = 1;
        TYPE_MODE (type) = VOIDmode;
        break;
  
      case OFFSET_TYPE:
        TYPE_SIZE (type) = bitsize_int (POINTER_SIZE, 0L);
        TYPE_MODE (type) = ptr_mode;
        break;
  
      case FUNCTION_TYPE:
      case METHOD_TYPE:
        TYPE_MODE (type) = mode_for_size (2 * POINTER_SIZE, MODE_INT, 0);
!       TYPE_SIZE (type) = size_int (2 * POINTER_SIZE);
        break;
  
      case POINTER_TYPE:
      case REFERENCE_TYPE:
        TYPE_MODE (type) = ptr_mode;
        TYPE_SIZE (type) = bitsize_int (POINTER_SIZE, 0L);
        TREE_UNSIGNED (type) = 1;
        TYPE_PRECISION (type) = POINTER_SIZE;
        break;
--- 737,770 ----
  			  ? MODE_COMPLEX_INT : MODE_COMPLEX_FLOAT),
  			 0);
        TYPE_SIZE (type) = bitsize_int (GET_MODE_BITSIZE (TYPE_MODE (type)), 0L);
+       TYPE_SIZE_UNIT (type) = size_int (GET_MODE_SIZE (TYPE_MODE (type)));
        break;
  
      case VOID_TYPE:
        TYPE_SIZE (type) = size_zero_node;
+       TYPE_SIZE_UNIT (type) = size_zero_node;
        TYPE_ALIGN (type) = 1;
        TYPE_MODE (type) = VOIDmode;
        break;
  
      case OFFSET_TYPE:
        TYPE_SIZE (type) = bitsize_int (POINTER_SIZE, 0L);
+       TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
        TYPE_MODE (type) = ptr_mode;
        break;
  
      case FUNCTION_TYPE:
      case METHOD_TYPE:
        TYPE_MODE (type) = mode_for_size (2 * POINTER_SIZE, MODE_INT, 0);
!       TYPE_SIZE (type) = bitsize_int (2 * POINTER_SIZE, 0);
!       TYPE_SIZE_UNIT (type) = size_int ((2 * POINTER_SIZE) / BITS_PER_UNIT);
        break;
  
      case POINTER_TYPE:
      case REFERENCE_TYPE:
        TYPE_MODE (type) = ptr_mode;
        TYPE_SIZE (type) = bitsize_int (POINTER_SIZE, 0L);
+       TYPE_SIZE_UNIT (type) = size_int (POINTER_SIZE / BITS_PER_UNIT);
        TREE_UNSIGNED (type) = 1;
        TYPE_PRECISION (type) = POINTER_SIZE;
        break;
*************** layout_type (type)
*** 810,815 ****
--- 817,833 ----
  
  	    TYPE_SIZE (type) = size_binop (MULT_EXPR, TYPE_SIZE (element),
  					   length);
+ 
+ 	    /* If we know the size of the element, calculate the total
+ 	       size directly, rather than do some division thing below.
+ 	       This optimization helps Fortran assumed-size arrays
+ 	       (where the size of the array is determined at runtime)
+ 	       substantially.  */
+ 	    if (TYPE_SIZE_UNIT (element) != 0)
+ 	      {
+ 	        TYPE_SIZE_UNIT (type)
+ 		  = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (element), length);
+ 	      }
  	  }
  
  	/* Now round the alignment and size,
*************** layout_type (type)
*** 824,831 ****
  
  #ifdef ROUND_TYPE_SIZE
  	if (TYPE_SIZE (type) != 0)
! 	  TYPE_SIZE (type)
! 	    = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
  #endif
  
  	TYPE_MODE (type) = BLKmode;
--- 842,856 ----
  
  #ifdef ROUND_TYPE_SIZE
  	if (TYPE_SIZE (type) != 0)
! 	  {
! 	    tree tmp;
! 	    tmp = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
! 	    /* If the rounding changed the size of the type, remove any
! 	       pre-calculated TYPE_SIZE_UNIT.  */
! 	    if (simple_cst_equal (TYPE_SIZE (type), tmp) != 1)
! 	      TYPE_SIZE_UNIT (type) = NULL;
! 	    TYPE_SIZE (type) = tmp;
! 	  }
  #endif
  
  	TYPE_MODE (type) = BLKmode;
*************** layout_type (type)
*** 983,988 ****
--- 1008,1014 ----
  	  else
  	    TYPE_MODE (type) = mode_for_size (alignment, MODE_INT, 1);
  	  TYPE_SIZE (type) = bitsize_int (rounded_size, 0L);
+ 	  TYPE_SIZE_UNIT (type) = size_int (rounded_size / BITS_PER_UNIT);
  	  TYPE_ALIGN (type) = alignment;
  	  TYPE_PRECISION (type) = size_in_bits;
  	}
*************** layout_type (type)
*** 1015,1020 ****
--- 1041,1059 ----
    if (TYPE_SIZE (type) != 0 && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
      TYPE_SIZE (type) = variable_size (TYPE_SIZE (type));
  
+   /* If we failed to find a simple way to calculate the unit size
+      of the type above, find it by division.  */
+   if (TYPE_SIZE_UNIT (type) == 0 && TYPE_SIZE (type) != 0)
+     {
+       TYPE_SIZE_UNIT (type) = size_binop (FLOOR_DIV_EXPR, TYPE_SIZE (type),
+ 				          size_int (BITS_PER_UNIT));
+     }
+ 
+   /* Once again evaluate only once, either now or as soon as safe.  */
+   if (TYPE_SIZE_UNIT (type) != 0
+       && TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
+     TYPE_SIZE_UNIT (type) = variable_size (TYPE_SIZE_UNIT (type));
+ 
    /* Also layout any other variants of the type.  */
    if (TYPE_NEXT_VARIANT (type)
        || type != TYPE_MAIN_VARIANT (type))
*************** layout_type (type)
*** 1022,1027 ****
--- 1061,1067 ----
        tree variant;
        /* Record layout info of this variant.  */
        tree size = TYPE_SIZE (type);
+       tree size_unit = TYPE_SIZE_UNIT (type);
        int align = TYPE_ALIGN (type);
        enum machine_mode mode = TYPE_MODE (type);
  
*************** layout_type (type)
*** 1031,1036 ****
--- 1071,1077 ----
  	   variant = TYPE_NEXT_VARIANT (variant))
  	{
  	  TYPE_SIZE (variant) = size;
+ 	  TYPE_SIZE_UNIT (variant) = size_unit;
  	  TYPE_ALIGN (variant) = align;
  	  TYPE_MODE (variant) = mode;
  	}
Index: tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.c,v
retrieving revision 1.26
diff -c -p -d -r1.26 tree.c
*** tree.c	1998/05/06 04:54:00	1.26
--- tree.c	1998/05/16 21:13:00
*************** size_in_bytes (type)
*** 2162,2177 ****
  
    if (type == error_mark_node)
      return integer_zero_node;
    type = TYPE_MAIN_VARIANT (type);
!   if (TYPE_SIZE (type) == 0)
      {
        incomplete_type_error (NULL_TREE, type);
        return integer_zero_node;
      }
-   t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type),
- 		  size_int (BITS_PER_UNIT));
    if (TREE_CODE (t) == INTEGER_CST)
      force_fit_type (t, 0);
    return t;
  }
  
--- 2162,2178 ----
  
    if (type == error_mark_node)
      return integer_zero_node;
+ 
    type = TYPE_MAIN_VARIANT (type);
!   t = TYPE_SIZE_UNIT (type);
!   if (t == 0)
      {
        incomplete_type_error (NULL_TREE, type);
        return integer_zero_node;
      }
    if (TREE_CODE (t) == INTEGER_CST)
      force_fit_type (t, 0);
+ 
    return t;
  }
  
*************** int_size_in_bytes (type)
*** 2188,2203 ****
      return 0;
  
    type = TYPE_MAIN_VARIANT (type);
!   if (TYPE_SIZE (type) == 0
!       || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
!     return -1;
! 
!   if (TREE_INT_CST_HIGH (TYPE_SIZE (type)) == 0)
!     return ((TREE_INT_CST_LOW (TYPE_SIZE (type)) + BITS_PER_UNIT - 1)
! 	  / BITS_PER_UNIT);
! 
!   t = size_binop (CEIL_DIV_EXPR, TYPE_SIZE (type), size_int (BITS_PER_UNIT));
!   if (TREE_CODE (t) != INTEGER_CST || TREE_INT_CST_HIGH (t) != 0)
      return -1;
  
    return TREE_INT_CST_LOW (t);
--- 2189,2198 ----
      return 0;
  
    type = TYPE_MAIN_VARIANT (type);
!   t = TYPE_SIZE_UNIT (type);
!   if (t == 0
!       || TREE_CODE (t) != INTEGER_CST
!       || TREE_INT_CST_HIGH (t) != 0)
      return -1;
  
    return TREE_INT_CST_LOW (t);
Index: tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.h,v
retrieving revision 1.30
diff -c -p -d -r1.30 tree.h
*** tree.h	1998/05/15 18:56:09	1.30
--- tree.h	1998/05/16 21:13:00
*************** struct tree_block
*** 714,719 ****
--- 714,720 ----
  
  #define TYPE_UID(NODE) ((NODE)->type.uid)
  #define TYPE_SIZE(NODE) ((NODE)->type.size)
+ #define TYPE_SIZE_UNIT(NODE) ((NODE)->type.size_unit)
  #define TYPE_MODE(NODE) ((NODE)->type.mode)
  #define TYPE_VALUES(NODE) ((NODE)->type.values)
  #define TYPE_DOMAIN(NODE) ((NODE)->type.values)
*************** struct tree_type
*** 795,800 ****
--- 796,802 ----
    char common[sizeof (struct tree_common)];
    union tree_node *values;
    union tree_node *size;
+   union tree_node *size_unit;
    union tree_node *attributes;
    unsigned uid;
  

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