+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
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. */
{
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
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);
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:
|| 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"
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);