This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: array reference optimization
- To: wilson at cygnus dot com
- Subject: Re: array reference optimization
- From: Richard Henderson <rth at cygnus dot com>
- Date: Sat, 16 May 1998 14:17:06 -0700
- Cc: egcs at cygnus dot com
- References: <19980513172502.54262@dot.cygnus.com>
- Reply-To: Richard Henderson <rth at cygnus dot com>
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;