Commit fa27426e by Richard Henderson Committed by Richard Henderson

re PR tree-optimization/16383 (internal compiler error: in…

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
parent 71956db3
2004-07-11 Richard Henderson <rth@redhat.com> 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 PR tree-opt/16422
* tree-sra.c (generate_one_element_init): New. * tree-sra.c (generate_one_element_init): New.
(generate_element_init): Use it. (generate_element_init): Use it.
......
...@@ -357,18 +357,32 @@ can_completely_scalarize_p (struct sra_elt *elt) ...@@ -357,18 +357,32 @@ can_completely_scalarize_p (struct sra_elt *elt)
static hashval_t static hashval_t
sra_hash_tree (tree t) sra_hash_tree (tree t)
{ {
hashval_t h;
switch (TREE_CODE (t)) switch (TREE_CODE (t))
{ {
case VAR_DECL: case VAR_DECL:
case PARM_DECL: case PARM_DECL:
case RESULT_DECL: case RESULT_DECL:
case FIELD_DECL: h = DECL_UID (t);
return DECL_UID (t); break;
case INTEGER_CST: 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: default:
abort (); abort ();
} }
return h;
} }
/* Hash function for type SRA_PAIR. */ /* Hash function for type SRA_PAIR. */
...@@ -399,20 +413,41 @@ sra_elt_eq (const void *x, const void *y) ...@@ -399,20 +413,41 @@ sra_elt_eq (const void *x, const void *y)
{ {
const struct sra_elt *a = x; const struct sra_elt *a = x;
const struct sra_elt *b = y; const struct sra_elt *b = y;
tree ae, be;
if (a->parent != b->parent) if (a->parent != b->parent)
return false; return false;
/* All the field/decl stuff is unique. */ ae = a->element;
if (a->element == b->element) be = b->element;
return true;
/* The only thing left is integer equality. */ if (ae == be)
if (TREE_CODE (a->element) == INTEGER_CST return true;
&& TREE_CODE (b->element) == INTEGER_CST) if (TREE_CODE (ae) != TREE_CODE (be))
return tree_int_cst_equal (a->element, b->element);
else
return false; 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 /* 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) ...@@ -1392,7 +1427,15 @@ generate_one_element_ref (struct sra_elt *elt, tree base)
switch (TREE_CODE (TREE_TYPE (base))) switch (TREE_CODE (TREE_TYPE (base)))
{ {
case RECORD_TYPE: 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: case ARRAY_TYPE:
return build (ARRAY_REF, elt->type, base, elt->element, NULL, NULL); return build (ARRAY_REF, elt->type, base, elt->element, NULL, NULL);
......
...@@ -1962,38 +1962,19 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data) ...@@ -1962,38 +1962,19 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data)
return t; return t;
*walk_subtrees = 0; *walk_subtrees = 0;
/* Make sure the FIELD_DECL is actually a field in the type on /* Make sure the FIELD_DECL is actually a field in the type on the lhs.
the lhs. In cases with IMA it is possible that it came We've already checked that the records are compatible, so we should
from another, equivalent type at this point. We have come up with a set of compatible fields. */
already checked the equivalence in this case. {
Match on type plus offset, to allow for unnamed fields. tree expr_record = TREE_TYPE (TREE_OPERAND (expr, 0));
We won't necessarily get the corresponding field for tree expr_field = TREE_OPERAND (expr, 1);
unions; this is believed to be harmless. */
if (DECL_FIELD_CONTEXT (expr_field) != TYPE_MAIN_VARIANT (expr_record))
if ((current_file_decl && TREE_CHAIN (current_file_decl)) {
&& (DECL_FIELD_CONTEXT (TREE_OPERAND (expr, 1)) != expr_field = find_compatible_field (expr_record, expr_field);
TREE_TYPE (TREE_OPERAND (expr, 0)))) TREE_OPERAND (expr, 1) = expr_field;
{ }
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. */
}
break; break;
default: default:
......
...@@ -5693,4 +5693,49 @@ needs_to_live_in_memory (tree t) ...@@ -5693,4 +5693,49 @@ needs_to_live_in_memory (tree t)
|| decl_function_context (t) != current_function_decl); || 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" #include "gt-tree.h"
...@@ -3481,6 +3481,9 @@ extern void build_common_tree_nodes_2 (int); ...@@ -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_nonstandard_integer_type (unsigned HOST_WIDE_INT, int);
extern tree build_range_type (tree, tree, tree); 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 */ /* In function.c */
extern void expand_main_function (void); extern void expand_main_function (void);
extern void init_dummy_function_start (void); extern void init_dummy_function_start (void);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment