mirror of git://gcc.gnu.org/git/gcc.git
gimple.h (gimplify_body): Remove first argument.
* gimple.h (gimplify_body): Remove first argument. * gimplify.c (copy_if_shared): Add DATA argument. Do not create the pointer set here, instead just pass DATA to walk_tree. (unshare_body): Remove BODY_P argument and adjust. Create the pointer set here and invoke copy_if_shared on the size trees of DECL_RESULT. (unvisit_body): Likewise, but with unmark_visited. (gimplify_body): Remove BODY_P argument and adjust. (gimplify_function_tree): Adjust call to gimplify_body. * omp-low.c (finalize_task_copyfn): Likewise. From-SVN: r183104
This commit is contained in:
parent
2cd8b32cb9
commit
3ad065efe1
|
|
@ -1,3 +1,15 @@
|
||||||
|
2012-01-11 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
|
* gimple.h (gimplify_body): Remove first argument.
|
||||||
|
* gimplify.c (copy_if_shared): Add DATA argument. Do not create the
|
||||||
|
pointer set here, instead just pass DATA to walk_tree.
|
||||||
|
(unshare_body): Remove BODY_P argument and adjust. Create the pointer
|
||||||
|
set here and invoke copy_if_shared on the size trees of DECL_RESULT.
|
||||||
|
(unvisit_body): Likewise, but with unmark_visited.
|
||||||
|
(gimplify_body): Remove BODY_P argument and adjust.
|
||||||
|
(gimplify_function_tree): Adjust call to gimplify_body.
|
||||||
|
* omp-low.c (finalize_task_copyfn): Likewise.
|
||||||
|
|
||||||
2012-01-11 Eric Botcazou <ebotcazou@adacore.com>
|
2012-01-11 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
* tree.h (build_function_decl_skip_args): Add boolean parameter.
|
* tree.h (build_function_decl_skip_args): Add boolean parameter.
|
||||||
|
|
|
||||||
|
|
@ -1097,7 +1097,7 @@ extern enum gimplify_status gimplify_expr (tree *, gimple_seq *, gimple_seq *,
|
||||||
extern void gimplify_type_sizes (tree, gimple_seq *);
|
extern void gimplify_type_sizes (tree, gimple_seq *);
|
||||||
extern void gimplify_one_sizepos (tree *, gimple_seq *);
|
extern void gimplify_one_sizepos (tree *, gimple_seq *);
|
||||||
extern bool gimplify_stmt (tree *, gimple_seq *);
|
extern bool gimplify_stmt (tree *, gimple_seq *);
|
||||||
extern gimple gimplify_body (tree *, tree, bool);
|
extern gimple gimplify_body (tree, bool);
|
||||||
extern void push_gimplify_context (struct gimplify_ctx *);
|
extern void push_gimplify_context (struct gimplify_ctx *);
|
||||||
extern void pop_gimplify_context (gimple);
|
extern void pop_gimplify_context (gimple);
|
||||||
extern void gimplify_and_add (tree, gimple_seq *);
|
extern void gimplify_and_add (tree, gimple_seq *);
|
||||||
|
|
|
||||||
|
|
@ -867,9 +867,10 @@ annotate_all_with_location (gimple_seq stmt_p, location_t location)
|
||||||
way to go. */
|
way to go. */
|
||||||
|
|
||||||
/* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes.
|
/* Similar to copy_tree_r but do not copy SAVE_EXPR or TARGET_EXPR nodes.
|
||||||
These nodes model computations that should only be done once. If we
|
These nodes model computations that must be done once. If we were to
|
||||||
were to unshare something like SAVE_EXPR(i++), the gimplification
|
unshare something like SAVE_EXPR(i++), the gimplification process would
|
||||||
process would create wrong code. */
|
create wrong code. However, if DATA is non-null, it must hold a pointer
|
||||||
|
set that is used to unshare the subtrees of these nodes. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
|
mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
|
||||||
|
|
@ -909,9 +910,9 @@ mostly_copy_tree_r (tree *tp, int *walk_subtrees, void *data)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback for walk_tree to unshare most of the shared trees rooted at
|
/* Callback for walk_tree to unshare most of the shared trees rooted at *TP.
|
||||||
*TP. If *TP has been visited already (i.e., TREE_VISITED (*TP) == 1),
|
If *TP has been visited already, then *TP is deeply copied by calling
|
||||||
then *TP is deep copied by calling mostly_copy_tree_r. */
|
mostly_copy_tree_r. DATA is passed to mostly_copy_tree_r unmodified. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
|
copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
|
||||||
|
|
@ -948,34 +949,37 @@ copy_if_shared_r (tree *tp, int *walk_subtrees, void *data)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unshare most of the shared trees rooted at *TP. */
|
/* Unshare most of the shared trees rooted at *TP. DATA is passed to the
|
||||||
|
copy_if_shared_r callback unmodified. */
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
copy_if_shared (tree *tp)
|
copy_if_shared (tree *tp, void *data)
|
||||||
{
|
{
|
||||||
|
walk_tree (tp, copy_if_shared_r, data, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unshare all the trees in the body of FNDECL, as well as in the bodies of
|
||||||
|
any nested functions. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
unshare_body (tree fndecl)
|
||||||
|
{
|
||||||
|
struct cgraph_node *cgn = cgraph_get_node (fndecl);
|
||||||
/* If the language requires deep unsharing, we need a pointer set to make
|
/* If the language requires deep unsharing, we need a pointer set to make
|
||||||
sure we don't repeatedly unshare subtrees of unshareable nodes. */
|
sure we don't repeatedly unshare subtrees of unshareable nodes. */
|
||||||
struct pointer_set_t *visited
|
struct pointer_set_t *visited
|
||||||
= lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
|
= lang_hooks.deep_unsharing ? pointer_set_create () : NULL;
|
||||||
walk_tree (tp, copy_if_shared_r, visited, NULL);
|
|
||||||
|
copy_if_shared (&DECL_SAVED_TREE (fndecl), visited);
|
||||||
|
copy_if_shared (&DECL_SIZE (DECL_RESULT (fndecl)), visited);
|
||||||
|
copy_if_shared (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)), visited);
|
||||||
|
|
||||||
if (visited)
|
if (visited)
|
||||||
pointer_set_destroy (visited);
|
pointer_set_destroy (visited);
|
||||||
}
|
|
||||||
|
|
||||||
/* Unshare all the trees in BODY_P, a pointer into the body of FNDECL, and the
|
if (cgn)
|
||||||
bodies of any nested functions if we are unsharing the entire body of
|
|
||||||
FNDECL. */
|
|
||||||
|
|
||||||
static void
|
|
||||||
unshare_body (tree *body_p, tree fndecl)
|
|
||||||
{
|
|
||||||
struct cgraph_node *cgn = cgraph_get_node (fndecl);
|
|
||||||
|
|
||||||
copy_if_shared (body_p);
|
|
||||||
|
|
||||||
if (cgn && body_p == &DECL_SAVED_TREE (fndecl))
|
|
||||||
for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
|
for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
|
||||||
unshare_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
|
unshare_body (cgn->decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Callback for walk_tree to unmark the visited trees rooted at *TP.
|
/* Callback for walk_tree to unmark the visited trees rooted at *TP.
|
||||||
|
|
@ -1008,15 +1012,17 @@ unmark_visited (tree *tp)
|
||||||
/* Likewise, but mark all trees as not visited. */
|
/* Likewise, but mark all trees as not visited. */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
unvisit_body (tree *body_p, tree fndecl)
|
unvisit_body (tree fndecl)
|
||||||
{
|
{
|
||||||
struct cgraph_node *cgn = cgraph_get_node (fndecl);
|
struct cgraph_node *cgn = cgraph_get_node (fndecl);
|
||||||
|
|
||||||
unmark_visited (body_p);
|
unmark_visited (&DECL_SAVED_TREE (fndecl));
|
||||||
|
unmark_visited (&DECL_SIZE (DECL_RESULT (fndecl)));
|
||||||
|
unmark_visited (&DECL_SIZE_UNIT (DECL_RESULT (fndecl)));
|
||||||
|
|
||||||
if (cgn && body_p == &DECL_SAVED_TREE (fndecl))
|
if (cgn)
|
||||||
for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
|
for (cgn = cgn->nested; cgn; cgn = cgn->next_nested)
|
||||||
unvisit_body (&DECL_SAVED_TREE (cgn->decl), cgn->decl);
|
unvisit_body (cgn->decl);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unconditionally make an unshared copy of EXPR. This is used when using
|
/* Unconditionally make an unshared copy of EXPR. This is used when using
|
||||||
|
|
@ -7938,13 +7944,12 @@ gimplify_one_sizepos (tree *expr_p, gimple_seq *stmt_p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Gimplify the body of statements pointed to by BODY_P and return a
|
/* Gimplify the body of statements of FNDECL and return a GIMPLE_BIND node
|
||||||
GIMPLE_BIND containing the sequence of GIMPLE statements
|
containing the sequence of corresponding GIMPLE statements. If DO_PARMS
|
||||||
corresponding to BODY_P. FNDECL is the function decl containing
|
is true, also gimplify the parameters. */
|
||||||
*BODY_P. */
|
|
||||||
|
|
||||||
gimple
|
gimple
|
||||||
gimplify_body (tree *body_p, tree fndecl, bool do_parms)
|
gimplify_body (tree fndecl, bool do_parms)
|
||||||
{
|
{
|
||||||
location_t saved_location = input_location;
|
location_t saved_location = input_location;
|
||||||
gimple_seq parm_stmts, seq;
|
gimple_seq parm_stmts, seq;
|
||||||
|
|
@ -7965,8 +7970,8 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
|
||||||
It would seem we don't have to do this for nested functions because
|
It would seem we don't have to do this for nested functions because
|
||||||
they are supposed to be output and then the outer function gimplified
|
they are supposed to be output and then the outer function gimplified
|
||||||
first, but the g++ front end doesn't always do it that way. */
|
first, but the g++ front end doesn't always do it that way. */
|
||||||
unshare_body (body_p, fndecl);
|
unshare_body (fndecl);
|
||||||
unvisit_body (body_p, fndecl);
|
unvisit_body (fndecl);
|
||||||
|
|
||||||
cgn = cgraph_get_node (fndecl);
|
cgn = cgraph_get_node (fndecl);
|
||||||
if (cgn && cgn->origin)
|
if (cgn && cgn->origin)
|
||||||
|
|
@ -7977,11 +7982,11 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
|
||||||
|
|
||||||
/* Resolve callee-copies. This has to be done before processing
|
/* Resolve callee-copies. This has to be done before processing
|
||||||
the body so that DECL_VALUE_EXPR gets processed correctly. */
|
the body so that DECL_VALUE_EXPR gets processed correctly. */
|
||||||
parm_stmts = (do_parms) ? gimplify_parameters () : NULL;
|
parm_stmts = do_parms ? gimplify_parameters () : NULL;
|
||||||
|
|
||||||
/* Gimplify the function's body. */
|
/* Gimplify the function's body. */
|
||||||
seq = NULL;
|
seq = NULL;
|
||||||
gimplify_stmt (body_p, &seq);
|
gimplify_stmt (&DECL_SAVED_TREE (fndecl), &seq);
|
||||||
outer_bind = gimple_seq_first_stmt (seq);
|
outer_bind = gimple_seq_first_stmt (seq);
|
||||||
if (!outer_bind)
|
if (!outer_bind)
|
||||||
{
|
{
|
||||||
|
|
@ -7997,7 +8002,7 @@ gimplify_body (tree *body_p, tree fndecl, bool do_parms)
|
||||||
else
|
else
|
||||||
outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
|
outer_bind = gimple_build_bind (NULL_TREE, seq, NULL);
|
||||||
|
|
||||||
*body_p = NULL_TREE;
|
DECL_SAVED_TREE (fndecl) = NULL_TREE;
|
||||||
|
|
||||||
/* If we had callee-copies statements, insert them at the beginning
|
/* If we had callee-copies statements, insert them at the beginning
|
||||||
of the function and clear DECL_VALUE_EXPR_P on the parameters. */
|
of the function and clear DECL_VALUE_EXPR_P on the parameters. */
|
||||||
|
|
@ -8115,7 +8120,7 @@ gimplify_function_tree (tree fndecl)
|
||||||
&& !needs_to_live_in_memory (ret))
|
&& !needs_to_live_in_memory (ret))
|
||||||
DECL_GIMPLE_REG_P (ret) = 1;
|
DECL_GIMPLE_REG_P (ret) = 1;
|
||||||
|
|
||||||
bind = gimplify_body (&DECL_SAVED_TREE (fndecl), fndecl, true);
|
bind = gimplify_body (fndecl, true);
|
||||||
|
|
||||||
/* The tree body of the function is no longer needed, replace it
|
/* The tree body of the function is no longer needed, replace it
|
||||||
with the new GIMPLE body. */
|
with the new GIMPLE body. */
|
||||||
|
|
|
||||||
|
|
@ -1248,7 +1248,7 @@ finalize_task_copyfn (gimple task_stmt)
|
||||||
old_fn = current_function_decl;
|
old_fn = current_function_decl;
|
||||||
push_cfun (child_cfun);
|
push_cfun (child_cfun);
|
||||||
current_function_decl = child_fn;
|
current_function_decl = child_fn;
|
||||||
bind = gimplify_body (&DECL_SAVED_TREE (child_fn), child_fn, false);
|
bind = gimplify_body (child_fn, false);
|
||||||
seq = gimple_seq_alloc ();
|
seq = gimple_seq_alloc ();
|
||||||
gimple_seq_add_stmt (&seq, bind);
|
gimple_seq_add_stmt (&seq, bind);
|
||||||
new_seq = maybe_catch_exception (seq);
|
new_seq = maybe_catch_exception (seq);
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
2012-01-11 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
|
* gnat.dg/array19.ad[sb]: New test.
|
||||||
|
|
||||||
2012-01-11 Eric Botcazou <ebotcazou@adacore.com>
|
2012-01-11 Eric Botcazou <ebotcazou@adacore.com>
|
||||||
|
|
||||||
* gnat.dg/opt23.ad[sb]: New test.
|
* gnat.dg/opt23.ad[sb]: New test.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
-- { dg-do compile }
|
||||||
|
|
||||||
|
package body Array19 is
|
||||||
|
|
||||||
|
function N return Integer is
|
||||||
|
begin
|
||||||
|
return 1;
|
||||||
|
end;
|
||||||
|
|
||||||
|
type Array_Type is array (1 .. N) of Float;
|
||||||
|
|
||||||
|
type Enum is (One, Two);
|
||||||
|
|
||||||
|
type Rec (D : Enum := Enum'First) is record
|
||||||
|
case D is
|
||||||
|
when One => null;
|
||||||
|
when Two => A : Array_Type;
|
||||||
|
end case;
|
||||||
|
end record;
|
||||||
|
|
||||||
|
procedure Proc is
|
||||||
|
|
||||||
|
R : Rec;
|
||||||
|
|
||||||
|
function F return Array_Type is
|
||||||
|
begin
|
||||||
|
return (others => 0.0);
|
||||||
|
end F;
|
||||||
|
|
||||||
|
begin
|
||||||
|
R.A := F;
|
||||||
|
end;
|
||||||
|
|
||||||
|
end Array19;
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package Array19 is
|
||||||
|
|
||||||
|
procedure Proc;
|
||||||
|
|
||||||
|
end Array19;
|
||||||
Loading…
Reference in New Issue