tree.h (TYPE_SIZE_UNIT): New.
authorRichard Henderson <rth@cygnus.com>
Mon, 18 May 1998 13:21:14 +0000 (06:21 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Mon, 18 May 1998 13:21:14 +0000 (06:21 -0700)
* 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.

From-SVN: r19853

gcc/ChangeLog
gcc/expr.c
gcc/stor-layout.c
gcc/tree.c
gcc/tree.h

index eb0c58ab6bbeea4492b0ce36b7bd960c5b761a6c..5d298e8220132a459df80cee6e7f41d1b1e76811 100644 (file)
@@ -1,3 +1,11 @@
+Mon May 18 13:20:23 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.
+
 Mon May 18 12:07:37 1998  Richard Earnshaw (rearnsha@arm.com)
 
        * stor-layout.c (layout_record): Fix off-by-one error when checking
index 34f744db7f3330aee4d2359fc40e4fd356ff98e9..f4e1d219bdcc688caab1e79a556b3662acd374d1 100644 (file)
@@ -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);
-
-             offset = size_binop (PLUS_EXPR, offset,
-                                  size_binop (FLOOR_DIV_EXPR, index,
-                                              size_int (BITS_PER_UNIT)));
+             /* 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 c9fee7ba177767aec596a9c40f7e9a0bfb02e43e..77561c97b886b73746d6b15c2d4657d2a787909d 100644 (file)
@@ -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;
        }
index 8a2d382f2683f5c8d86b0ef69ac2059674f04415..04bf8a31871a6d9286fc496f60c6646f33054590 100644 (file)
@@ -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);
index 9643f5dcaa62f9121a5102759be1326022c82aee..00bd4caa6b6f08992a108f5060a6af2bfdaee1cb 100644 (file)
@@ -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;