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]

array reference optimization


I believe that I've found the reason that Fortran loop induction
variables have not been being recognized recently.  This bit from
get_inner_reference

           index = fold (build (MULT_EXPR, sbitsizetype, index,
                                convert (sbitsizetype,
                                         TYPE_SIZE (TREE_TYPE (exp)))));

produces and conversion to TImode, which is later fed through a 
division to produce the offset.  While the individual instructions
that are produced from this aren't so bad, the convolutions are too
much for loop.

But given that I've complained about the division producing less than
optimal code in the past, I think that the proper way to fix the problem
is to do the array index calculation in units rather than bits.

The following patch implements this.


r~



Wed May 13 17:14:56 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.


Index: expr.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/expr.c,v
retrieving revision 1.56
diff -c -p -d -r1.56 expr.c
*** expr.c	1998/05/13 12:40:13	1.56
--- expr.c	1998/05/14 00:13:10
*************** 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,4426 ----
  	      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
  	    {
! 	      if (TYPE_SIZE_UNIT (TREE_TYPE (exp)) != 0)
! 		{
! 		  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 (contains_placeholder_p (xindex))
! 		    xindex = build (WITH_RECORD_EXPR, sizetype, xindex, exp);
! 
! 	          offset = size_binop (PLUS_EXPR, offset,
! 				       size_binop (FLOOR_DIV_EXPR, xindex,
! 					           size_int (BITS_PER_UNIT)));
! 		}
  	    }
  	}
        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.12
diff -c -p -d -r1.12 stor-layout.c
*** stor-layout.c	1998/05/06 04:53:58	1.12
--- stor-layout.c	1998/05/14 00:13:10
*************** layout_type (type)
*** 715,725 ****
--- 715,727 ----
        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)
*** 730,758 ****
  			  ? 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;
--- 732,765 ----
  			  ? 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)
*** 805,810 ****
--- 812,828 ----
  
  	    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)
*** 819,826 ****
  
  #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;
--- 837,849 ----
  
  #ifdef ROUND_TYPE_SIZE
  	if (TYPE_SIZE (type) != 0)
! 	  {
! 	    tree tmp;
! 	    tmp = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type));
! 	    if (TYPE_SIZE (type) != tmp)
! 	      TYPE_SIZE_UNIT (type) = NULL;
! 	    TYPE_SIZE (type) = tmp;
! 	  }
  #endif
  
  	TYPE_MODE (type) = BLKmode;
*************** layout_type (type)
*** 978,983 ****
--- 1001,1007 ----
  	  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)
*** 1010,1015 ****
--- 1034,1052 ----
    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)
*** 1017,1022 ****
--- 1054,1060 ----
        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)
*** 1026,1031 ****
--- 1064,1070 ----
  	   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.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/tree.h,v
retrieving revision 1.28
diff -c -p -d -r1.28 tree.h
*** tree.h	1998/05/06 08:36:04	1.28
--- tree.h	1998/05/14 00:13:10
*************** struct tree_block
*** 698,703 ****
--- 698,704 ----
  
  #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
*** 779,784 ****
--- 780,786 ----
    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]