(get_inner_reference): Simplify code by initializing OFFSET to integer_zero_node.
authorRichard Kenner <kenner@gcc.gnu.org>
Sun, 21 Mar 1993 01:51:52 +0000 (20:51 -0500)
committerRichard Kenner <kenner@gcc.gnu.org>
Sun, 21 Mar 1993 01:51:52 +0000 (20:51 -0500)
(get_inner_reference): Simplify code by initializing OFFSET to
integer_zero_node.
Do general index computation for ARRAY_REF and include lower bound of domain
in calculation.
(expand_expr, case ARRAY_REF): Include lower-bound in index computation.

From-SVN: r3808

gcc/expr.c

index b1d091ec7e293b56167f96b0f1c91b67054a3202..a3f5970ba6c7737413ca028b0651250f3a8fb383 100644 (file)
@@ -3318,8 +3318,7 @@ store_field (target, bitsize, bitpos, mode, exp, value_mode,
 \f
 /* Given an expression EXP that may be a COMPONENT_REF, a BIT_FIELD_REF,
    or an ARRAY_REF, look for nested COMPONENT_REFs, BIT_FIELD_REFs, or
-   ARRAY_REFs at constant positions and find the ultimate containing object,
-   which we return.
+   ARRAY_REFs and find the ultimate containing object, which we return.
 
    We set *PBITSIZE to the size in bits that we want, *PBITPOS to the
    bit position, and *PUNSIGNEDP to the signedness of the field.
@@ -3352,7 +3351,7 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
 {
   tree size_tree = 0;
   enum machine_mode mode = VOIDmode;
-  tree offset = 0;
+  tree offset = integer_zero_node;
 
   if (TREE_CODE (exp) == COMPONENT_REF)
     {
@@ -3409,14 +3408,11 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
                }
              else
                abort ();
+
              *pbitpos += TREE_INT_CST_LOW (constant);
-             if (offset)
-               offset = size_binop (PLUS_EXPR, offset,
-                                    size_binop (FLOOR_DIV_EXPR, var,
-                                                size_int (BITS_PER_UNIT)));
-             else
-               offset = size_binop (FLOOR_DIV_EXPR, var,
-                                    size_int (BITS_PER_UNIT));
+             offset = size_binop (PLUS_EXPR, offset,
+                                  size_binop (FLOOR_DIV_EXPR, var,
+                                              size_int (BITS_PER_UNIT)));
            }
          else if (TREE_CODE (pos) == INTEGER_CST)
            *pbitpos += TREE_INT_CST_LOW (pos);
@@ -3424,22 +3420,43 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
            {
              /* Assume here that the offset is a multiple of a unit.
                 If not, there should be an explicitly added constant.  */
-             if (offset)
-               offset = size_binop (PLUS_EXPR, offset,
-                                    size_binop (FLOOR_DIV_EXPR, pos,
-                                                size_int (BITS_PER_UNIT)));
-             else
-               offset = size_binop (FLOOR_DIV_EXPR, pos,
-                                    size_int (BITS_PER_UNIT));
+             offset = size_binop (PLUS_EXPR, offset,
+                                  size_binop (FLOOR_DIV_EXPR, pos,
+                                              size_int (BITS_PER_UNIT)));
            }
        }
 
-      else if (TREE_CODE (exp) == ARRAY_REF
-              && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
-              && TREE_CODE (TYPE_SIZE (TREE_TYPE (exp))) == INTEGER_CST)
+      else if (TREE_CODE (exp) == ARRAY_REF)
        {
-         *pbitpos += (TREE_INT_CST_LOW (TREE_OPERAND (exp, 1))
-                      * TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (exp))));
+         /* This code is based on the code in case ARRAY_REF in expand_expr
+            below.  We assume here that the size of an array element is
+            always an integral multiple of BITS_PER_UNIT.  */
+
+         tree index = TREE_OPERAND (exp, 1);
+         tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (exp, 0)));
+         tree low_bound
+           = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
+         tree index_type = TREE_TYPE (index);
+
+         if (! integer_zerop (low_bound))
+           index = fold (build (MINUS_EXPR, index_type, index, low_bound));
+
+         if (TYPE_PRECISION (index_type) != POINTER_SIZE)
+           {
+             index = convert (type_for_size (POINTER_SIZE, 0), index);
+             index_type = TREE_TYPE (index);
+           }
+
+         index = fold (build (MULT_EXPR, index_type, index,
+                              TYPE_SIZE (TREE_TYPE (exp))));
+
+         if (TREE_CODE (index) == INTEGER_CST
+             && TREE_INT_CST_HIGH (index) == 0)
+           *pbitpos += TREE_INT_CST_LOW (index);
+         else
+           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
               && ! ((TREE_CODE (exp) == NOP_EXPR
@@ -3463,6 +3480,9 @@ get_inner_reference (exp, pbitsize, pbitpos, poffset, pmode,
        mode = VOIDmode;
     }
 
+  if (integer_zerop (offset))
+    offset = 0;
+
   *pmode = mode;
   *poffset = offset;
 #if 0
@@ -4236,136 +4256,146 @@ expand_expr (exp, target, tmode, modifier)
       }
 
     case ARRAY_REF:
-      if (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
-         || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
-       {
-         /* Nonconstant array index or nonconstant element size.
-            Generate the tree for *(&array+index) and expand that,
-            except do it in a language-independent way
-            and don't complain about non-lvalue arrays.
-            `mark_addressable' should already have been called
-            for any array for which this case will be reached.  */
-
-         /* Don't forget the const or volatile flag from the array element. */
-         tree variant_type = build_type_variant (type,
-                                                 TREE_READONLY (exp),
-                                                 TREE_THIS_VOLATILE (exp));
-         tree array_adr = build1 (ADDR_EXPR, build_pointer_type (variant_type),
-                                  TREE_OPERAND (exp, 0));
-         tree index = TREE_OPERAND (exp, 1);
-         tree elt;
-
-         /* Convert the integer argument to a type the same size as a pointer
-            so the multiply won't overflow spuriously.  */
-         if (TYPE_PRECISION (TREE_TYPE (index)) != POINTER_SIZE)
-           index = convert (type_for_size (POINTER_SIZE, 0), index);
-
-         /* Don't think the address has side effects
-            just because the array does.
-            (In some cases the address might have side effects,
-            and we fail to record that fact here.  However, it should not
-            matter, since expand_expr should not care.)  */
-         TREE_SIDE_EFFECTS (array_adr) = 0;
-
-         elt = build1 (INDIRECT_REF, type,
-                       fold (build (PLUS_EXPR, TYPE_POINTER_TO (variant_type),
-                                    array_adr,
-                                    fold (build (MULT_EXPR,
-                                                 TYPE_POINTER_TO (variant_type),
-                                                 index, size_in_bytes (type))))));
-
-         /* Volatility, etc., of new expression is same as old expression.  */
-         TREE_SIDE_EFFECTS (elt) = TREE_SIDE_EFFECTS (exp);
-         TREE_THIS_VOLATILE (elt) = TREE_THIS_VOLATILE (exp);
-         TREE_READONLY (elt) = TREE_READONLY (exp);
-
-         return expand_expr (elt, target, tmode, modifier);
-       }
+      if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) != ARRAY_TYPE)
+       abort ();
 
-      /* Fold an expression like: "foo"[2].
-        This is not done in fold so it won't happen inside &.  */
       {
+       tree array = TREE_OPERAND (exp, 0);
+       tree domain = TYPE_DOMAIN (TREE_TYPE (array));
+       tree low_bound = domain ? TYPE_MIN_VALUE (domain) : integer_zero_node;
+       tree index = TREE_OPERAND (exp, 1);
+       tree index_type = TREE_TYPE (index);
        int i;
-       tree arg0 = TREE_OPERAND (exp, 0);
-       tree arg1 = TREE_OPERAND (exp, 1);
 
-       if (TREE_CODE (arg0) == STRING_CST
-           && TREE_CODE (arg1) == INTEGER_CST
-           && !TREE_INT_CST_HIGH (arg1)
-           && (i = TREE_INT_CST_LOW (arg1)) < TREE_STRING_LENGTH (arg0))
+       /* Optimize the special-case of a zero lower bound.  */
+       if (! integer_zerop (low_bound))
+         index = fold (build (MINUS_EXPR, index_type, index, low_bound));
+
+       if (TREE_CODE (index) != INTEGER_CST
+           || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+         {
+           /* Nonconstant array index or nonconstant element size.
+              Generate the tree for *(&array+index) and expand that,
+              except do it in a language-independent way
+              and don't complain about non-lvalue arrays.
+              `mark_addressable' should already have been called
+              for any array for which this case will be reached.  */
+
+           /* Don't forget the const or volatile flag from the array
+              element. */
+           tree variant_type = build_type_variant (type,
+                                                   TREE_READONLY (exp),
+                                                   TREE_THIS_VOLATILE (exp));
+           tree array_adr = build1 (ADDR_EXPR,
+                                    build_pointer_type (variant_type), array);
+           tree elt;
+
+           /* Convert the integer argument to a type the same size as a
+              pointer so the multiply won't overflow spuriously.  */
+           if (TYPE_PRECISION (index_type) != POINTER_SIZE)
+             index = convert (type_for_size (POINTER_SIZE, 0), index);
+
+           /* Don't think the address has side effects
+              just because the array does.
+              (In some cases the address might have side effects,
+              and we fail to record that fact here.  However, it should not
+              matter, since expand_expr should not care.)  */
+           TREE_SIDE_EFFECTS (array_adr) = 0;
+
+           elt = build1 (INDIRECT_REF, type,
+                         fold (build (PLUS_EXPR,
+                                      TYPE_POINTER_TO (variant_type),
+                                      array_adr,
+                                      fold (build (MULT_EXPR,
+                                                   TYPE_POINTER_TO (variant_type),
+                                                   index,
+                                                   size_in_bytes (type))))));
+
+           /* Volatility, etc., of new expression is same as old
+              expression.  */
+           TREE_SIDE_EFFECTS (elt) = TREE_SIDE_EFFECTS (exp);
+           TREE_THIS_VOLATILE (elt) = TREE_THIS_VOLATILE (exp);
+           TREE_READONLY (elt) = TREE_READONLY (exp);
+
+           return expand_expr (elt, target, tmode, modifier);
+         }
+
+       /* Fold an expression like: "foo"[2].
+          This is not done in fold so it won't happen inside &.  */
+
+       if (TREE_CODE (array) == STRING_CST
+           && TREE_CODE (index) == INTEGER_CST
+           && !TREE_INT_CST_HIGH (index)
+           && (i = TREE_INT_CST_LOW (index)) < TREE_STRING_LENGTH (array))
          {
-           if (TREE_TYPE (TREE_TYPE (arg0)) == integer_type_node)
+           if (TREE_TYPE (TREE_TYPE (array)) == integer_type_node)
              {
-               exp = build_int_2 (((int *)TREE_STRING_POINTER (arg0))[i], 0);
+               exp = build_int_2 (((int *)TREE_STRING_POINTER (array))[i], 0);
                TREE_TYPE (exp) = integer_type_node;
                return expand_expr (exp, target, tmode, modifier);
              }
-           if (TREE_TYPE (TREE_TYPE (arg0)) == char_type_node)
+           if (TREE_TYPE (TREE_TYPE (array)) == char_type_node)
              {
-               exp = build_int_2 (TREE_STRING_POINTER (arg0)[i], 0);
+               exp = build_int_2 (TREE_STRING_POINTER (array)[i], 0);
                TREE_TYPE (exp) = integer_type_node;
-               return expand_expr (convert (TREE_TYPE (TREE_TYPE (arg0)), exp), target, tmode, modifier);
+               return expand_expr (convert (TREE_TYPE (TREE_TYPE (array)),
+                                            exp),
+                                   target, tmode, modifier);
              }
          }
-      }
 
-      /* If this is a constant index into a constant array,
-        just get the value from the array.  Handle both the cases when
-        we have an explicit constructor and when our operand is a variable
-        that was declared const.  */
+       /* If this is a constant index into a constant array,
+          just get the value from the array.  Handle both the cases when
+          we have an explicit constructor and when our operand is a variable
+          that was declared const.  */
 
-      if (TREE_CODE (TREE_OPERAND (exp, 0)) == CONSTRUCTOR
-         && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0)))
-       {
-         tree index = fold (TREE_OPERAND (exp, 1));
-         if (TREE_CODE (index) == INTEGER_CST
-             && TREE_INT_CST_HIGH (index) == 0)
-           {
-             int i = TREE_INT_CST_LOW (index);
-             tree elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
-
-             while (elem && i--)
-               elem = TREE_CHAIN (elem);
-             if (elem)
-               return expand_expr (fold (TREE_VALUE (elem)), target,
-                                   tmode, modifier);
-           }
-       }
+       if (TREE_CODE (array) == CONSTRUCTOR && ! TREE_SIDE_EFFECTS (array))
+         {
+           if (TREE_CODE (index) == INTEGER_CST
+               && TREE_INT_CST_HIGH (index) == 0)
+             {
+               tree elem = CONSTRUCTOR_ELTS (TREE_OPERAND (exp, 0));
+
+               i = TREE_INT_CST_LOW (index);
+               while (elem && i--)
+                 elem = TREE_CHAIN (elem);
+               if (elem)
+                 return expand_expr (fold (TREE_VALUE (elem)), target,
+                                     tmode, modifier);
+             }
+         }
          
-      else if (TREE_READONLY (TREE_OPERAND (exp, 0))
-              && ! TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 0))
-              && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == ARRAY_TYPE
-              && TREE_CODE (TREE_OPERAND (exp, 0)) == VAR_DECL
-              && DECL_INITIAL (TREE_OPERAND (exp, 0))
-              && optimize >= 1
-              && (TREE_CODE (DECL_INITIAL (TREE_OPERAND (exp, 0)))
-                  != ERROR_MARK))
-       {
-         tree index = fold (TREE_OPERAND (exp, 1));
-         if (TREE_CODE (index) == INTEGER_CST
-             && TREE_INT_CST_HIGH (index) == 0)
-           {
-             int i = TREE_INT_CST_LOW (index);
-             tree init = DECL_INITIAL (TREE_OPERAND (exp, 0));
-
-             if (TREE_CODE (init) == CONSTRUCTOR)
-               {
-                 tree elem = CONSTRUCTOR_ELTS (init);
+       else if (optimize >= 1
+                && TREE_READONLY (array) && ! TREE_SIDE_EFFECTS (array)
+                && TREE_CODE (array) == VAR_DECL && DECL_INITIAL (array)
+                && TREE_CODE (DECL_INITIAL (array)) != ERROR_MARK)
+         {
+           if (TREE_CODE (index) == INTEGER_CST
+               && TREE_INT_CST_HIGH (index) == 0)
+             {
+               tree init = DECL_INITIAL (array);
+
+               i = TREE_INT_CST_LOW (index);
+               if (TREE_CODE (init) == CONSTRUCTOR)
+                 {
+                   tree elem = CONSTRUCTOR_ELTS (init);
+
+                   while (elem && i--)
+                     elem = TREE_CHAIN (elem);
+                   if (elem)
+                     return expand_expr (fold (TREE_VALUE (elem)), target,
+                                         tmode, modifier);
+                 }
+               else if (TREE_CODE (init) == STRING_CST
+                        && i < TREE_STRING_LENGTH (init))
+                 {
+                   temp = GEN_INT (TREE_STRING_POINTER (init)[i]);
+                   return convert_to_mode (mode, temp, 0);
+                 }
+             }
+         }
+      }
 
-                 while (elem && i--)
-                   elem = TREE_CHAIN (elem);
-                 if (elem)
-                   return expand_expr (fold (TREE_VALUE (elem)), target,
-                                       tmode, modifier);
-               }
-             else if (TREE_CODE (init) == STRING_CST
-                      && i < TREE_STRING_LENGTH (init))
-               {
-                 temp = GEN_INT (TREE_STRING_POINTER (init)[i]);
-                 return convert_to_mode (mode, temp, 0);
-               }
-           }
-       }
       /* Treat array-ref with constant index as a component-ref.  */
 
     case COMPONENT_REF: