re PR tree-optimization/16383 (internal compiler error: in generate_element_copy, at tree-sra.c:1466)

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
This commit is contained in:
Richard Henderson 2004-07-11 10:41:52 -07:00 committed by Richard Henderson
parent 71956db351
commit fa27426eb1
5 changed files with 125 additions and 43 deletions

View 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

View 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);

View 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. */
/* 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 ((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. */
}
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:

View 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"

View 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);