diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eb0c58ab6bbe..5d298e822013 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +Mon May 18 13:20:23 1998 Richard Henderson + + * 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. + Mon May 18 12:07:37 1998 Richard Earnshaw (rearnsha@arm.com) * stor-layout.c (layout_record): Fix off-by-one error when checking diff --git a/gcc/expr.c b/gcc/expr.c index 34f744db7f33..f4e1d219bdcc 100644 --- a/gcc/expr.c +++ b/gcc/expr.c @@ -4374,6 +4374,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode, 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)) { @@ -4391,21 +4392,27 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode, index_type = TREE_TYPE (index); } - index = fold (build (MULT_EXPR, sbitsizetype, index, - convert (sbitsizetype, - TYPE_SIZE (TREE_TYPE (exp))))); + xindex = 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); + if (TREE_CODE (xindex) == INTEGER_CST + && TREE_INT_CST_HIGH (xindex) == 0) + *pbitpos += TREE_INT_CST_LOW (xindex); else { - if (contains_placeholder_p (index)) - index = build (WITH_RECORD_EXPR, sizetype, index, exp); + /* 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))))); - offset = size_binop (PLUS_EXPR, offset, - size_binop (FLOOR_DIV_EXPR, index, - size_int (BITS_PER_UNIT))); + 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 diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c index c9fee7ba1777..77561c97b886 100644 --- a/gcc/stor-layout.c +++ b/gcc/stor-layout.c @@ -720,11 +720,13 @@ layout_type (type) 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: @@ -735,29 +737,34 @@ layout_type (type) ? 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) = size_int (2 * POINTER_SIZE); + 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; @@ -810,6 +817,17 @@ layout_type (type) 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, @@ -824,8 +842,15 @@ layout_type (type) #ifdef ROUND_TYPE_SIZE if (TYPE_SIZE (type) != 0) - TYPE_SIZE (type) - = ROUND_TYPE_SIZE (type, TYPE_SIZE (type), TYPE_ALIGN (type)); + { + 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; @@ -983,6 +1008,7 @@ layout_type (type) 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; } @@ -1015,6 +1041,19 @@ layout_type (type) 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)) @@ -1022,6 +1061,7 @@ layout_type (type) 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); @@ -1031,6 +1071,7 @@ layout_type (type) variant = TYPE_NEXT_VARIANT (variant)) { TYPE_SIZE (variant) = size; + TYPE_SIZE_UNIT (variant) = size_unit; TYPE_ALIGN (variant) = align; TYPE_MODE (variant) = mode; } diff --git a/gcc/tree.c b/gcc/tree.c index 8a2d382f2683..04bf8a31871a 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -2162,16 +2162,17 @@ size_in_bytes (type) if (type == error_mark_node) return integer_zero_node; + type = TYPE_MAIN_VARIANT (type); - if (TYPE_SIZE (type) == 0) + t = TYPE_SIZE_UNIT (type); + if (t == 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; } @@ -2188,16 +2189,10 @@ int_size_in_bytes (type) 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) + 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); diff --git a/gcc/tree.h b/gcc/tree.h index 9643f5dcaa62..00bd4caa6b6f 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -714,6 +714,7 @@ struct tree_block #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) @@ -795,6 +796,7 @@ struct tree_type 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;