public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* fix pr16383
@ 2004-07-11 20:32 Richard Henderson
  0 siblings, 0 replies; only message in thread
From: Richard Henderson @ 2004-07-11 20:32 UTC (permalink / raw)
  To: gcc-patches

I wish we didn't have to do this sort of thing, but both IMA and
C++ member pointers wind up with compatible structures with field
lists that are not identical.  We already had some code to check
and correct this sort of thing, just need to use it more places.


r~


        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.

Index: tree-sra.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-sra.c,v
retrieving revision 2.19
diff -u -p -r2.19 tree-sra.c
--- tree-sra.c	11 Jul 2004 17:33:02 -0000	2.19
+++ tree-sra.c	11 Jul 2004 17:37:19 -0000
@@ -357,18 +357,32 @@ can_completely_scalarize_p (struct sra_e
 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
   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: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-ccp.c,v
retrieving revision 2.20
diff -u -p -r2.20 tree-ssa-ccp.c
--- tree-ssa-ccp.c	10 Jul 2004 02:24:27 -0000	2.20
+++ tree-ssa-ccp.c	11 Jul 2004 17:37:19 -0000
@@ -1962,38 +1962,19 @@ fold_stmt_r (tree *expr_p, int *walk_sub
         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: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.394
diff -u -p -r1.394 tree.c
--- tree.c	10 Jul 2004 04:57:54 -0000	1.394
+++ tree.c	11 Jul 2004 17:37:20 -0000
@@ -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: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.554
diff -u -p -r1.554 tree.h
--- tree.h	11 Jul 2004 10:04:57 -0000	1.554
+++ tree.h	11 Jul 2004 17:37:20 -0000
@@ -3481,6 +3481,9 @@ extern void build_common_tree_nodes_2 (i
 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);

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2004-07-11 17:48 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-11 20:32 fix pr16383 Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).