OSDN Git Service

2012-03-27 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / fold-const.c
index 6492f11..6874c9e 100644 (file)
@@ -6850,64 +6850,81 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1)
       s = integer_one_node;
     }
 
-  for (;; ref = TREE_OPERAND (ref, 0))
+  /* Handle &x.array the same as we would handle &x.array[0].  */
+  if (TREE_CODE (ref) == COMPONENT_REF
+      && TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
     {
-      if (TREE_CODE (ref) == ARRAY_REF)
+      tree domain;
+
+      /* Remember if this was a multi-dimensional array.  */
+      if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
+       mdim = true;
+
+      domain = TYPE_DOMAIN (TREE_TYPE (ref));
+      if (! domain)
+       goto cont;
+      itype = TREE_TYPE (domain);
+
+      step = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref)));
+      if (TREE_CODE (step) != INTEGER_CST)
+       goto cont;
+
+      if (s)
        {
-         tree domain;
+         if (! tree_int_cst_equal (step, s))
+           goto cont;
+       }
+      else
+       {
+         /* Try if delta is a multiple of step.  */
+         tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, op1, step);
+         if (! tmp)
+           goto cont;
+         delta = tmp;
+       }
 
-         /* Remember if this was a multi-dimensional array.  */
-         if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
-           mdim = true;
+      /* Only fold here if we can verify we do not overflow one
+        dimension of a multi-dimensional array.  */
+      if (mdim)
+       {
+         tree tmp;
 
-         domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
-         if (! domain)
-           continue;
-         itype = TREE_TYPE (domain);
+         if (!TYPE_MIN_VALUE (domain)
+             || !TYPE_MAX_VALUE (domain)
+             || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
+           goto cont;
 
-         step = array_ref_element_size (ref);
-         if (TREE_CODE (step) != INTEGER_CST)
-           continue;
+         tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
+                                fold_convert_loc (loc, itype,
+                                                  TYPE_MIN_VALUE (domain)),
+                                fold_convert_loc (loc, itype, delta));
+         if (TREE_CODE (tmp) != INTEGER_CST
+             || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
+           goto cont;
+       }
 
-         if (s)
-           {
-             if (! tree_int_cst_equal (step, s))
-                continue;
-           }
-         else
-           {
-             /* Try if delta is a multiple of step.  */
-             tree tmp = div_if_zero_remainder (EXACT_DIV_EXPR, op1, step);
-             if (! tmp)
-               continue;
-             delta = tmp;
-           }
+      /* We found a suitable component reference.  */
 
-         /* Only fold here if we can verify we do not overflow one
-            dimension of a multi-dimensional array.  */
-         if (mdim)
-           {
-             tree tmp;
+      pref = TREE_OPERAND (addr, 0);
+      ret = copy_node (pref);
+      SET_EXPR_LOCATION (ret, loc);
 
-             if (TREE_CODE (TREE_OPERAND (ref, 1)) != INTEGER_CST
-                 || !TYPE_MAX_VALUE (domain)
-                 || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
-               continue;
+      ret = build4_loc (loc, ARRAY_REF, TREE_TYPE (TREE_TYPE (ref)), ret,
+                       fold_build2_loc
+                         (loc, PLUS_EXPR, itype,
+                          fold_convert_loc (loc, itype,
+                                            TYPE_MIN_VALUE
+                                              (TYPE_DOMAIN (TREE_TYPE (ref)))),
+                          fold_convert_loc (loc, itype, delta)),
+                       NULL_TREE, NULL_TREE);
+      return build_fold_addr_expr_loc (loc, ret);
+    }
 
-             tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
-                                    fold_convert_loc (loc, itype,
-                                                      TREE_OPERAND (ref, 1)),
-                                    fold_convert_loc (loc, itype, delta));
-             if (!tmp
-                 || TREE_CODE (tmp) != INTEGER_CST
-                 || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
-               continue;
-           }
+cont:
 
-         break;
-       }
-      else if (TREE_CODE (ref) == COMPONENT_REF
-              && TREE_CODE (TREE_TYPE (ref)) == ARRAY_TYPE)
+  for (;; ref = TREE_OPERAND (ref, 0))
+    {
+      if (TREE_CODE (ref) == ARRAY_REF)
        {
          tree domain;
 
@@ -6915,12 +6932,12 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1)
          if (TREE_CODE (TREE_OPERAND (ref, 0)) == ARRAY_REF)
            mdim = true;
 
-         domain = TYPE_DOMAIN (TREE_TYPE (ref));
+         domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
          if (! domain)
            continue;
          itype = TREE_TYPE (domain);
 
-         step = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (ref)));
+         step = array_ref_element_size (ref);
          if (TREE_CODE (step) != INTEGER_CST)
            continue;
 
@@ -6944,16 +6961,17 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1)
            {
              tree tmp;
 
-             if (!TYPE_MIN_VALUE (domain)
+             if (TREE_CODE (TREE_OPERAND (ref, 1)) != INTEGER_CST
                  || !TYPE_MAX_VALUE (domain)
                  || TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
                continue;
 
              tmp = fold_binary_loc (loc, PLUS_EXPR, itype,
                                     fold_convert_loc (loc, itype,
-                                                      TYPE_MIN_VALUE (domain)),
+                                                      TREE_OPERAND (ref, 1)),
                                     fold_convert_loc (loc, itype, delta));
-             if (TREE_CODE (tmp) != INTEGER_CST
+             if (!tmp
+                 || TREE_CODE (tmp) != INTEGER_CST
                  || tree_int_cst_lt (TYPE_MAX_VALUE (domain), tmp))
                continue;
            }
@@ -6982,29 +7000,11 @@ try_move_mult_to_index (location_t loc, tree addr, tree op1)
       pos = TREE_OPERAND (pos, 0);
     }
 
-  if (TREE_CODE (ref) == ARRAY_REF)
-    {
-      TREE_OPERAND (pos, 1)
-       = fold_build2_loc (loc, PLUS_EXPR, itype,
-                          fold_convert_loc (loc, itype, TREE_OPERAND (pos, 1)),
-                          fold_convert_loc (loc, itype, delta));
-      return fold_build1_loc (loc, ADDR_EXPR, TREE_TYPE (addr), ret);
-    }
-  else if (TREE_CODE (ref) == COMPONENT_REF)
-    {
-      gcc_assert (ret == pos);
-      ret = build4_loc (loc, ARRAY_REF, TREE_TYPE (TREE_TYPE (ref)), ret,
-                       fold_build2_loc
-                         (loc, PLUS_EXPR, itype,
-                          fold_convert_loc (loc, itype,
-                                            TYPE_MIN_VALUE
-                                              (TYPE_DOMAIN (TREE_TYPE (ref)))),
-                          fold_convert_loc (loc, itype, delta)),
-                       NULL_TREE, NULL_TREE);
-      return build_fold_addr_expr_loc (loc, ret);
-    }
-  else
-    gcc_unreachable ();
+  TREE_OPERAND (pos, 1)
+    = fold_build2_loc (loc, PLUS_EXPR, itype,
+                      fold_convert_loc (loc, itype, TREE_OPERAND (pos, 1)),
+                      fold_convert_loc (loc, itype, delta));
+  return fold_build1_loc (loc, ADDR_EXPR, TREE_TYPE (addr), ret);
 }