re PR tree-optimization/16383 (internal compiler error: in generate_element_copy...
authorRichard Henderson <rth@redhat.com>
Sun, 11 Jul 2004 17:41:52 +0000 (10:41 -0700)
committerRichard Henderson <rth@gcc.gnu.org>
Sun, 11 Jul 2004 17:41:52 +0000 (10:41 -0700)
        PR tree-opt/16383
        * tree-ssa-ccp.c (fold_stmt_r): Split out...
        * tree.c (fields_compatible_p, find_compatible_field): ... new.
        * tree.h (fields_compatible_p, find_compatible_field): Declare.
        * tree-sra.c (sra_hash_tree): Hash fields by offset.
        (sra_elt_eq): Use fields_compatible_p.
        (generate_one_element_ref): Use find_compatible_field.

From-SVN: r84524

gcc/ChangeLog
gcc/tree-sra.c
gcc/tree-ssa-ccp.c
gcc/tree.c
gcc/tree.h

index 3ab7cedeadb38b26d9c984a173e444cd89a5e8c3..155e3436738674eb770b37a2bc185f8a15863485 100644 (file)
@@ -1,3 +1,13 @@
+2004-07-11  Richard Henderson  <rth@redhat.com>
+
+       PR tree-opt/16383
+       * tree-ssa-ccp.c (fold_stmt_r): Split out...
+       * tree.c (fields_compatible_p, find_compatible_field): ... new.
+       * tree.h (fields_compatible_p, find_compatible_field): Declare.
+       * tree-sra.c (sra_hash_tree): Hash fields by offset.
+       (sra_elt_eq): Use fields_compatible_p.
+       (generate_one_element_ref): Use find_compatible_field.
+
 2004-07-11  Richard Henderson  <rth@redhat.com>
 
        PR tree-opt/16422
index 1a4e5586c4f73ec9ada18af9ad4f3bac9bf03b42..423ee3ca498f5c282bb21ade93def3a215d96cf9 100644 (file)
@@ -357,18 +357,32 @@ can_completely_scalarize_p (struct sra_elt *elt)
 static hashval_t
 sra_hash_tree (tree t)
 {
+  hashval_t h;
+
   switch (TREE_CODE (t))
     {
     case VAR_DECL:
     case PARM_DECL:
     case RESULT_DECL:
-    case FIELD_DECL:
-      return DECL_UID (t);
+      h = DECL_UID (t);
+      break;
+
     case INTEGER_CST:
-      return TREE_INT_CST_LOW (t) ^ TREE_INT_CST_HIGH (t);
+      h = TREE_INT_CST_LOW (t) ^ TREE_INT_CST_HIGH (t);
+      break;
+
+    case FIELD_DECL:
+      /* We can have types that are compatible, but have different member
+        lists, so we can't hash fields by ID.  Use offsets instead.  */
+      h = iterative_hash_expr (DECL_FIELD_OFFSET (t), 0);
+      h = iterative_hash_expr (DECL_FIELD_BIT_OFFSET (t), h);
+      break;
+
     default:
       abort ();
     }
+
+  return h;
 }
 
 /* Hash function for type SRA_PAIR.  */
@@ -399,20 +413,41 @@ sra_elt_eq (const void *x, const void *y)
 {
   const struct sra_elt *a = x;
   const struct sra_elt *b = y;
+  tree ae, be;
 
   if (a->parent != b->parent)
     return false;
 
-  /* All the field/decl stuff is unique.  */
-  if (a->element == b->element)
-    return true;
+  ae = a->element;
+  be = b->element;
 
-  /* The only thing left is integer equality.  */
-  if (TREE_CODE (a->element) == INTEGER_CST
-      && TREE_CODE (b->element) == INTEGER_CST)
-    return tree_int_cst_equal (a->element, b->element);
-  else
+  if (ae == be)
+    return true;
+  if (TREE_CODE (ae) != TREE_CODE (be))
     return false;
+
+  switch (TREE_CODE (ae))
+    {
+    case VAR_DECL:
+    case PARM_DECL:
+    case RESULT_DECL:
+      /* These are all pointer unique.  */
+      return false;
+
+    case INTEGER_CST:
+      /* Integers are not pointer unique, so compare their values.  */
+      return tree_int_cst_equal (ae, be);
+
+    case FIELD_DECL:
+      /* Fields are unique within a record, but not between
+        compatible records.  */
+      if (DECL_FIELD_CONTEXT (ae) == DECL_FIELD_CONTEXT (be))
+       return false;
+      return fields_compatible_p (ae, be);
+
+    default:
+      abort ();
+    }
 }
 
 /* Create or return the SRA_ELT structure for CHILD in PARENT.  PARENT
@@ -1392,7 +1427,15 @@ generate_one_element_ref (struct sra_elt *elt, tree base)
   switch (TREE_CODE (TREE_TYPE (base)))
     {
     case RECORD_TYPE:
-      return build (COMPONENT_REF, elt->type, base, elt->element, NULL);
+      {
+       tree field = elt->element;
+
+       /* Watch out for compatible records with differing field lists.  */
+       if (DECL_FIELD_CONTEXT (field) != TYPE_MAIN_VARIANT (TREE_TYPE (base)))
+         field = find_compatible_field (TREE_TYPE (base), field);
+
+        return build (COMPONENT_REF, elt->type, base, field, NULL);
+      }
 
     case ARRAY_TYPE:
       return build (ARRAY_REF, elt->type, base, elt->element, NULL, NULL);
index 01da8f88e07ceb3ca41b61ef79c8824690ff196b..5b6fca62653b523c4016cdfa1680e1016c8e802b 100644 (file)
@@ -1962,38 +1962,19 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data)
         return t;
       *walk_subtrees = 0;
 
-      /* Make sure the FIELD_DECL is actually a field in the type on
-         the lhs.  In cases with IMA it is possible that it came
-         from another, equivalent type at this point.  We have
-        already checked the equivalence in this case.
-        Match on type plus offset, to allow for unnamed fields.
-        We won't necessarily get the corresponding field for
-        unions; this is believed to be harmless.  */
-
-      if ((current_file_decl && TREE_CHAIN (current_file_decl))
-        && (DECL_FIELD_CONTEXT (TREE_OPERAND (expr, 1)) !=
-            TREE_TYPE (TREE_OPERAND (expr, 0))))
-        {
-          tree f;
-          tree orig_field = TREE_OPERAND (expr, 1);
-          tree orig_type = TREE_TYPE (orig_field);
-          for (f = TYPE_FIELDS (TREE_TYPE (TREE_OPERAND (expr, 0)));
-              f; f = TREE_CHAIN (f))
-            {
-              if (lang_hooks.types_compatible_p (TREE_TYPE (f), orig_type)
-                  && tree_int_cst_compare (DECL_FIELD_BIT_OFFSET (f),
-                                          DECL_FIELD_BIT_OFFSET (orig_field))
-                      == 0
-                  && tree_int_cst_compare (DECL_FIELD_OFFSET (f),
-                                          DECL_FIELD_OFFSET (orig_field))
-                      == 0)
-                {
-                  TREE_OPERAND (expr, 1) = f;
-                  break;
-                }
-            }
-        /* Fall through is an error; it will be detected in tree-sra.  */
-        }
+      /* Make sure the FIELD_DECL is actually a field in the type on the lhs.
+        We've already checked that the records are compatible, so we should
+        come up with a set of compatible fields.  */
+      {
+       tree expr_record = TREE_TYPE (TREE_OPERAND (expr, 0));
+       tree expr_field = TREE_OPERAND (expr, 1);
+
+        if (DECL_FIELD_CONTEXT (expr_field) != TYPE_MAIN_VARIANT (expr_record))
+         {
+           expr_field = find_compatible_field (expr_record, expr_field);
+           TREE_OPERAND (expr, 1) = expr_field;
+         }
+      }
       break;
 
     default:
index 033c851ea74bd84f57d2a322ff3b7cf7df6068f8..30ddcc895a5b5183a589cb02e1d0d0bb5b1ebb79 100644 (file)
@@ -5693,4 +5693,49 @@ needs_to_live_in_memory (tree t)
          || decl_function_context (t) != current_function_decl);
 }
 
+/* There are situations in which a language considers record types
+   compatible which have different field lists.  Decide if two fields
+   are compatible.  It is assumed that the parent records are compatible.  */
+
+bool
+fields_compatible_p (tree f1, tree f2)
+{
+  if (!operand_equal_p (DECL_FIELD_BIT_OFFSET (f1),
+                       DECL_FIELD_BIT_OFFSET (f2), OEP_ONLY_CONST))
+    return false;
+
+  if (!operand_equal_p (DECL_FIELD_OFFSET (f1),
+                        DECL_FIELD_OFFSET (f2), OEP_ONLY_CONST))
+    return false;
+
+  if (!lang_hooks.types_compatible_p (TREE_TYPE (f1), TREE_TYPE (f2)))
+    return false; 
+
+  return true;
+}
+
+/* Locate within RECORD a field that is compatible with ORIG_FIELD.  */
+
+tree
+find_compatible_field (tree record, tree orig_field)
+{
+  tree f;
+
+  for (f = TYPE_FIELDS (record); f ; f = TREE_CHAIN (f))
+    if (TREE_CODE (f) == FIELD_DECL
+       && fields_compatible_p (f, orig_field))
+      return f;
+
+  /* ??? Why isn't this on the main fields list?  */
+  f = TYPE_VFIELD (record);
+  if (f && TREE_CODE (f) == FIELD_DECL
+      && fields_compatible_p (f, orig_field))
+    return f;
+
+  /* ??? We should abort here, but Java appears to do Bad Things
+     with inherited fields.  */
+  return orig_field;
+}
+
+
 #include "gt-tree.h"
index 1daea216559e01ac072c2a31916c82ca4d03534a..baa20781eefc8dbf3fb21e0fdb835e789128825d 100644 (file)
@@ -3481,6 +3481,9 @@ extern void build_common_tree_nodes_2 (int);
 extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
 extern tree build_range_type (tree, tree, tree);
 
+extern bool fields_compatible_p (tree, tree);
+extern tree find_compatible_field (tree, tree);
+
 /* In function.c */
 extern void expand_main_function (void);
 extern void init_dummy_function_start (void);