diff options
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/gimplify.c | 5 | ||||
-rw-r--r-- | gcc/tree-sra.c | 58 |
3 files changed, 69 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d52f351..3ab7ced 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2004-07-11 Richard Henderson <rth@redhat.com> + + PR tree-opt/16422 + * tree-sra.c (generate_one_element_init): New. + (generate_element_init): Use it. + (scalarize_init): Push/pop gimplify context around it. + (find_new_referenced_vars_1, find_new_referenced_vars): New. + * gimplify.c (gimplify_expr): Allow SSA_NAME. + 2004-07-11 Roger Sayle <roger@eyesopen.com> * rtlanal.c (insn_rtx_cost): New function, moved and renamed from diff --git a/gcc/gimplify.c b/gcc/gimplify.c index f60ef89..5b87620 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -3816,6 +3816,11 @@ gimplify_expr (tree *expr_p, tree *pre_p, tree *post_p, ret = GS_ALL_DONE; break; + case SSA_NAME: + /* Allow callbacks into the gimplifier during optimization. */ + ret = GS_ALL_DONE; + break; + default: /* If this is a comparison of objects of aggregate type, handle it specially (by converting to a call to memcmp). It would be diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index 6769407..1a4e558 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -1513,6 +1513,55 @@ generate_element_zero (struct sra_elt *elt, tree *list_p) } } +/* Find all variables within the gimplified statement that were not previously + visible to the function and add them to the referenced variables list. */ + +static tree +find_new_referenced_vars_1 (tree *tp, int *walk_subtrees, + void *data ATTRIBUTE_UNUSED) +{ + tree t = *tp; + + if (TREE_CODE (t) == VAR_DECL && !var_ann (t)) + add_referenced_tmp_var (t); + + if (DECL_P (t) || TYPE_P (t)) + *walk_subtrees = 0; + + return NULL; +} + +static inline void +find_new_referenced_vars (tree *stmt_p) +{ + walk_tree (stmt_p, find_new_referenced_vars_1, NULL, NULL); +} + +/* Generate an assignment VAR = INIT, where INIT may need gimplification. + Add the result to *LIST_P. */ + +static void +generate_one_element_init (tree var, tree init, tree *list_p) +{ + tree stmt; + + /* The replacement can be almost arbitrarily complex. Gimplify. */ + stmt = build (MODIFY_EXPR, void_type_node, var, init); + gimplify_stmt (&stmt); + + /* The replacement can expose previously unreferenced variables. */ + if (TREE_CODE (stmt) == STATEMENT_LIST) + { + tree_stmt_iterator i; + for (i = tsi_start (stmt); !tsi_end_p (i); tsi_next (&i)) + find_new_referenced_vars (tsi_stmt_ptr (i)); + } + else + find_new_referenced_vars (&stmt); + + append_to_statement_list (stmt, list_p); +} + /* Generate a set of assignment statements in *LIST_P to set all instantiated elements under ELT with the contents of the initializer INIT. In addition, mark all assigned elements VISITED; this allows easy coordination with @@ -1536,8 +1585,7 @@ generate_element_init (struct sra_elt *elt, tree init, tree *list_p) { if (elt->replacement) { - t = build (MODIFY_EXPR, void_type_node, elt->replacement, init); - append_to_statement_list (t, list_p); + generate_one_element_init (elt->replacement, init, list_p); elt->visited = true; } return result; @@ -1774,7 +1822,11 @@ scalarize_init (struct sra_elt *lhs_elt, tree rhs, block_stmt_iterator *bsi) /* Generate initialization statements for all members extant in the RHS. */ if (rhs) - result = generate_element_init (lhs_elt, rhs, &list); + { + push_gimplify_context (); + result = generate_element_init (lhs_elt, rhs, &list); + pop_gimplify_context (NULL); + } /* CONSTRUCTOR is defined such that any member not mentioned is assigned a zero value. Initialize the rest of the instantiated elements. */ |