This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [tree-ssa] Fix variables getting out of their scope
- From: Diego Novillo <dnovillo at redhat dot com>
- To: Zdenek Dvorak <rakdver at kam dot mff dot cuni dot cz>
- Cc: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>, Jason Merrill <jason at redhat dot com>
- Date: Sun, 10 Aug 2003 17:13:20 -0400
- Subject: Re: [tree-ssa] Fix variables getting out of their scope
- Organization: Red Hat Canada
- References: <20030810203732.GA27897@kam.mff.cuni.cz>
[ Adding gcc-patches. The original message was mis-addressed. ]
On Sun, 2003-08-10 at 16:37, Zdenek Dvorak wrote:
> Hello,
>
> this patch fixes the problem with variables being copy-propagated out
> of their scope, by moving their declaration to the top-most bind_expr
> if it occurs.
>
I'm not sure this is a valid transformation. I believe that it disrupts
debugging information. Jason?
If not, then I would vote for moving *all* local declarations to the top
BIND_EXPR and remove all BIND_EXPRs inside the function. IIRC, I once
suggested something along those lines but it didn't turn out to be a
good idea because it would break debugging info.
> Moving them just to the innermost bind_expr that encloses
> both old declaration and the new position would of course be possible
> (and probably better), but I am not sure whether bind_exprs with no
> variables are not removed somewhere, in this case just this patch could
> move the declarations to the removed bind_expr, which would be wrong.
>
> The patch also assumes that all newly created variables are declared
> in the topmost bind_expr (which afaik is true currently).
>
Yes.
> The patch is partially derived from the ir change patch, so perhaps it
> is a bit more complicated than it has to be.
>
Please break it appart then. The patch has unrelated changes which are
not necessary for what you're trying to fix here.
Diego.
> Zdenek
>
> The testcase for fixed problem:
>
> void foo(void)
> {
> int k;
>
> goto forward;
> back:
> bla (k);
> return;
>
> forward:
> {
> int i = bar ();
>
> k = i;
>
> goto back;
> }
> }
>
> Changelog:
> * tree-flow.h (struct block_tree): New.
> (block_tree): Declare.
> (struct var_ann_d): New field scope.
> (struct stmt_ann_d): New field scope.
> (bti_start, bti_end_p, bti_next, dump_block_tree): Declare.
> (propagate_copy): Declaration changed.
> * tree-cfg.c (block_tree, block_tree_obstack_initialized,
> block_tree_obstack): New variables.
> (make_blocks, make_cond_expr_blocks, make_catch_expr_blocks,
> make_eh_filter_expr_blocks, make_try_expr_blocks,
> make_loop_expr_blocks, make_switch_expr_blocks,
> make_bind_expr_blocks, build_tree_cfg): Initialize block_tree,
> assign variables to scopes.
> (delete_tree_cfg): Release block_tree.
> (block_tree_alloc, block_tree_free, assign_vars_to_scope,
> dump_block_tree): New.
> * tree-flow-inline.h (bti_start, bti_end_p, bti_next): New.
> * tree-ssa-copyprop.c (move_var_to_scope): New.
> (copyprop_stmt): Pass scope of statement to propagate_copy.
> (propagate_copy): Assign variable to the right bind_expr.
> * tree-ssa-dom.c (optimize_stmt): Pass scope of statement to
> propagate_copy.
>
> Index: tree-cfg.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
> retrieving revision 1.1.4.143
> diff -c -3 -p -r1.1.4.143 tree-cfg.c
> *** tree-cfg.c 9 Aug 2003 18:19:23 -0000 1.1.4.143
> --- tree-cfg.c 10 Aug 2003 20:17:13 -0000
> *************** static dominance_info pdom_info = NULL;
> *** 76,81 ****
> --- 76,85 ----
>
> static struct cfg_stats_d cfg_stats;
>
> + struct block_tree *block_tree;
> + static int block_tree_obstack_initialized = false;
> + static struct obstack block_tree_obstack;
> +
> static struct obstack block_tree_ann_obstack;
> static void *first_block_tree_ann_obj = 0;
>
> *************** static void create_blocks_annotations (v
> *** 84,97 ****
> static void create_block_annotation (basic_block);
> static void free_blocks_annotations (void);
> static void clear_blocks_annotations (void);
> ! static basic_block make_blocks (tree *, tree, tree, basic_block);
> ! static void make_cond_expr_blocks (tree *, tree, basic_block);
> ! static void make_catch_expr_blocks (tree *, tree, basic_block);
> ! static void make_eh_filter_expr_blocks (tree *, tree, basic_block);
> ! static void make_try_expr_blocks (tree *, tree, basic_block);
> ! static void make_loop_expr_blocks (tree *, basic_block);
> ! static void make_switch_expr_blocks (tree *, tree, basic_block);
> ! static basic_block make_bind_expr_blocks (tree *, tree, basic_block, tree);
> static inline void add_stmt_to_bb (tree *, basic_block, tree);
> static inline void append_stmt_to_bb (tree *, basic_block, tree);
> static inline void set_parent_stmt (tree *, tree);
> --- 88,108 ----
> static void create_block_annotation (basic_block);
> static void free_blocks_annotations (void);
> static void clear_blocks_annotations (void);
> ! static basic_block make_blocks (tree *, tree, tree, basic_block,
> ! struct block_tree *);
> ! static void make_loop_expr_blocks (tree *, basic_block, struct block_tree *);
> ! static void make_cond_expr_blocks (tree *, tree, basic_block,
> ! struct block_tree *);
> ! static void make_catch_expr_blocks (tree *, tree, basic_block,
> ! struct block_tree *);
> ! static void make_eh_filter_expr_blocks (tree *, tree, basic_block,
> ! struct block_tree *);
> ! static void make_try_expr_blocks (tree *, tree, basic_block,
> ! struct block_tree *);
> ! static void make_switch_expr_blocks (tree *, tree, basic_block,
> ! struct block_tree *);
> ! static basic_block make_bind_expr_blocks (tree *, tree, basic_block, tree,
> ! struct block_tree *);
> static inline void add_stmt_to_bb (tree *, basic_block, tree);
> static inline void append_stmt_to_bb (tree *, basic_block, tree);
> static inline void set_parent_stmt (tree *, tree);
> *************** static void make_goto_expr_edges (basic_
> *** 106,111 ****
> --- 117,125 ----
> static void make_case_label_edges (basic_block);
>
> /* Various helpers. */
> + static struct block_tree *block_tree_alloc (struct block_tree *);
> + static void block_tree_free (void);
> + static void assign_vars_to_scope (struct block_tree *);
> static basic_block successor_block (basic_block);
> static basic_block last_exec_block (tree *);
> static tree *first_exec_stmt (tree *);
> *************** void
> *** 230,235 ****
> --- 244,250 ----
> build_tree_cfg (tree fnbody)
> {
> tree *first_p;
> + struct block_tree *block_tree_curr;
>
> timevar_push (TV_TREE_CFG);
>
> *************** build_tree_cfg (tree fnbody)
> *** 258,267 ****
> return;
> }
>
> first_p = first_exec_stmt (&BIND_EXPR_BODY (fnbody));
> if (first_p)
> {
> ! make_blocks (first_p, NULL_TREE, NULL, NULL);
>
> if (n_basic_blocks > 0)
> {
> --- 273,285 ----
> return;
> }
>
> + block_tree_curr = block_tree_alloc (NULL);
> + block_tree_curr->bind = fnbody;
> +
> first_p = first_exec_stmt (&BIND_EXPR_BODY (fnbody));
> if (first_p)
> {
> ! make_blocks (first_p, NULL_TREE, NULL, NULL, block_tree_curr);
>
> if (n_basic_blocks > 0)
> {
> *************** clear_blocks_annotations (void)
> *** 381,393 ****
> BB is the block where the statements should be added to. If BB is NULL,
> a new basic block will be created for the statements.
>
> Return the last basic block added to the graph. This is used to know if
> a recursive invocation built a sub-graph whose last block can accept
> more statements or not. */
>
> static basic_block
> make_blocks (tree *first_p, tree next_block_link, tree parent_stmt,
> ! basic_block bb)
> {
> tree_stmt_iterator i;
> tree stmt, last;
> --- 399,413 ----
> BB is the block where the statements should be added to. If BB is NULL,
> a new basic block will be created for the statements.
>
> + BLOCK_TREE_CURR is the actual bind block.
> +
> Return the last basic block added to the graph. This is used to know if
> a recursive invocation built a sub-graph whose last block can accept
> more statements or not. */
>
> static basic_block
> make_blocks (tree *first_p, tree next_block_link, tree parent_stmt,
> ! basic_block bb, struct block_tree *block_tree_curr)
> {
> tree_stmt_iterator i;
> tree stmt, last;
> *************** make_blocks (tree *first_p, tree next_bl
> *** 423,441 ****
> /* Now add STMT to BB and create the subgraphs for special statement
> codes. */
> append_stmt_to_bb (stmt_p, bb, parent_stmt);
>
> if (code == LOOP_EXPR)
> ! make_loop_expr_blocks (stmt_p, bb);
> else if (code == COND_EXPR)
> ! make_cond_expr_blocks (stmt_p, next_block_link, bb);
> else if (code == SWITCH_EXPR)
> ! make_switch_expr_blocks (stmt_p, next_block_link, bb);
> else if (code == CATCH_EXPR)
> ! make_catch_expr_blocks (stmt_p, next_block_link, bb);
> else if (code == EH_FILTER_EXPR)
> ! make_eh_filter_expr_blocks (stmt_p, next_block_link, bb);
> else if (code == TRY_CATCH_EXPR || code == TRY_FINALLY_EXPR)
> ! make_try_expr_blocks (stmt_p, next_block_link, bb);
> else if (code == BIND_EXPR)
> {
> int num_blocks_before;
> --- 443,463 ----
> /* Now add STMT to BB and create the subgraphs for special statement
> codes. */
> append_stmt_to_bb (stmt_p, bb, parent_stmt);
> + stmt_ann (stmt)->scope = block_tree_curr;
>
> if (code == LOOP_EXPR)
> ! make_loop_expr_blocks (stmt_p, bb, block_tree_curr);
> else if (code == COND_EXPR)
> ! make_cond_expr_blocks (stmt_p, next_block_link, bb, block_tree_curr);
> else if (code == SWITCH_EXPR)
> ! make_switch_expr_blocks (stmt_p, next_block_link, bb, block_tree_curr);
> else if (code == CATCH_EXPR)
> ! make_catch_expr_blocks (stmt_p, next_block_link, bb, block_tree_curr);
> else if (code == EH_FILTER_EXPR)
> ! make_eh_filter_expr_blocks (stmt_p, next_block_link, bb,
> ! block_tree_curr);
> else if (code == TRY_CATCH_EXPR || code == TRY_FINALLY_EXPR)
> ! make_try_expr_blocks (stmt_p, next_block_link, bb, block_tree_curr);
> else if (code == BIND_EXPR)
> {
> int num_blocks_before;
> *************** make_blocks (tree *first_p, tree next_bl
> *** 448,455 ****
> point STMT to LAST_BB's last statement to determine if we
> should start a new block or not. */
> num_blocks_before = n_basic_blocks;
> last_bb = make_bind_expr_blocks (stmt_p, next_block_link, bb,
> ! parent_stmt);
> if (last_bb)
> {
> bb = last_bb;
> --- 470,481 ----
> point STMT to LAST_BB's last statement to determine if we
> should start a new block or not. */
> num_blocks_before = n_basic_blocks;
> + block_tree_curr = block_tree_alloc (block_tree_curr);
> + block_tree_curr->bind = stmt;
> + assign_vars_to_scope (block_tree_curr);
> +
> last_bb = make_bind_expr_blocks (stmt_p, next_block_link, bb,
> ! parent_stmt, block_tree_curr);
> if (last_bb)
> {
> bb = last_bb;
> *************** could_trap_p (tree expr)
> *** 544,550 ****
> ENTRY is the block whose last statement is *LOOP_P. */
>
> static void
> ! make_loop_expr_blocks (tree *loop_p, basic_block entry)
> {
> tree_stmt_iterator si;
> tree loop = *loop_p;
> --- 570,577 ----
> ENTRY is the block whose last statement is *LOOP_P. */
>
> static void
> ! make_loop_expr_blocks (tree *loop_p, basic_block entry,
> ! struct block_tree *block_tree_curr)
> {
> tree_stmt_iterator si;
> tree loop = *loop_p;
> *************** make_loop_expr_blocks (tree *loop_p, bas
> *** 578,584 ****
> next_block_link = *(tsi_container (si));
> }
>
> ! make_blocks (&LOOP_EXPR_BODY (loop), next_block_link, loop, NULL);
> }
>
>
> --- 605,612 ----
> next_block_link = *(tsi_container (si));
> }
>
> ! make_blocks (&LOOP_EXPR_BODY (loop), next_block_link, loop, NULL,
> ! block_tree_curr);
> }
>
>
> *************** make_loop_expr_blocks (tree *loop_p, bas
> *** 589,599 ****
> lexical scope, this will be the statement that comes after COND_P's
> container (see the documentation for NEXT_BLOCK_LINK).
>
> ! ENTRY is the block whose last statement is *COND_P. */
>
> static void
> make_cond_expr_blocks (tree *cond_p, tree next_block_link,
> ! basic_block entry)
> {
> tree_stmt_iterator si;
> tree cond = *cond_p;
> --- 617,629 ----
> lexical scope, this will be the statement that comes after COND_P's
> container (see the documentation for NEXT_BLOCK_LINK).
>
> ! ENTRY is the block whose last statement is *COND_P.
> !
> ! BLOCK_TREE_CURR is the bind scope to that it belongs. */
>
> static void
> make_cond_expr_blocks (tree *cond_p, tree next_block_link,
> ! basic_block entry, struct block_tree *block_tree_curr)
> {
> tree_stmt_iterator si;
> tree cond = *cond_p;
> *************** make_cond_expr_blocks (tree *cond_p, tre
> *** 611,618 ****
> next_block_link = *(tsi_container (si));
>
> STRIP_CONTAINERS (cond);
> ! make_blocks (&COND_EXPR_THEN (cond), next_block_link, cond, NULL);
> ! make_blocks (&COND_EXPR_ELSE (cond), next_block_link, cond, NULL);
> }
>
> /* Derive an exception handling region type from STMT. */
> --- 641,650 ----
> next_block_link = *(tsi_container (si));
>
> STRIP_CONTAINERS (cond);
> ! make_blocks (&COND_EXPR_THEN (cond), next_block_link, cond, NULL,
> ! block_tree_curr);
> ! make_blocks (&COND_EXPR_ELSE (cond), next_block_link, cond, NULL,
> ! block_tree_curr);
> }
>
> /* Derive an exception handling region type from STMT. */
> *************** get_eh_region_type (tree stmt)
> *** 639,645 ****
>
> static void
> make_try_expr_blocks (tree *expr_p, tree next_block_link,
> ! basic_block entry)
> {
> tree_stmt_iterator si;
> tree expr = *expr_p;
> --- 671,677 ----
>
> static void
> make_try_expr_blocks (tree *expr_p, tree next_block_link,
> ! basic_block entry, struct block_tree *block_tree_curr)
> {
> tree_stmt_iterator si;
> tree expr = *expr_p;
> *************** make_try_expr_blocks (tree *expr_p, tree
> *** 663,675 ****
> VARRAY_PUSH_TREE (eh_stack, expr);
>
> /* Make blocks for the TRY block. */
> ! make_blocks (&TREE_OPERAND (expr, 0), next_block_link, expr, NULL);
>
> /* And pop the stack of exception handlers. */
> VARRAY_POP (eh_stack);
>
> /* Make blocks for the handler itself. */
> ! make_blocks (&TREE_OPERAND (expr, 1), next_block_link, expr, NULL);
>
> /* If this is a cleanup, then record which cleanup higher in the
> stack it can directly reach. */
> --- 695,709 ----
> VARRAY_PUSH_TREE (eh_stack, expr);
>
> /* Make blocks for the TRY block. */
> ! make_blocks (&TREE_OPERAND (expr, 0), next_block_link, expr, NULL,
> ! block_tree_curr);
>
> /* And pop the stack of exception handlers. */
> VARRAY_POP (eh_stack);
>
> /* Make blocks for the handler itself. */
> ! make_blocks (&TREE_OPERAND (expr, 1), next_block_link, expr, NULL,
> ! block_tree_curr);
>
> /* If this is a cleanup, then record which cleanup higher in the
> stack it can directly reach. */
> *************** make_try_expr_blocks (tree *expr_p, tree
> *** 686,692 ****
>
> static void
> make_catch_expr_blocks (tree *expr_p, tree next_block_link,
> ! basic_block entry)
> {
> tree_stmt_iterator si;
> tree expr = *expr_p;
> --- 720,726 ----
>
> static void
> make_catch_expr_blocks (tree *expr_p, tree next_block_link,
> ! basic_block entry, struct block_tree *block_tree_curr)
> {
> tree_stmt_iterator si;
> tree expr = *expr_p;
> *************** make_catch_expr_blocks (tree *expr_p, tr
> *** 701,714 ****
> tsi_next (&si);
>
> STRIP_CONTAINERS (expr);
> ! make_blocks (&CATCH_BODY (expr), next_block_link, expr, NULL);
> }
>
> /* Create the blocks for the EH_FILTER_EXPR node pointed to by expr_p. */
>
> static void
> make_eh_filter_expr_blocks (tree *expr_p, tree next_block_link,
> ! basic_block entry)
> {
> tree_stmt_iterator si;
> tree expr = *expr_p;
> --- 735,750 ----
> tsi_next (&si);
>
> STRIP_CONTAINERS (expr);
> ! make_blocks (&CATCH_BODY (expr), next_block_link, expr, NULL,
> ! block_tree_curr);
> }
>
> /* Create the blocks for the EH_FILTER_EXPR node pointed to by expr_p. */
>
> static void
> make_eh_filter_expr_blocks (tree *expr_p, tree next_block_link,
> ! basic_block entry,
> ! struct block_tree *block_tree_curr)
> {
> tree_stmt_iterator si;
> tree expr = *expr_p;
> *************** make_eh_filter_expr_blocks (tree *expr_p
> *** 723,729 ****
> tsi_next (&si);
>
> STRIP_CONTAINERS (expr);
> ! make_blocks (&EH_FILTER_FAILURE (expr), next_block_link, expr, NULL);
> }
>
>
> --- 759,766 ----
> tsi_next (&si);
>
> STRIP_CONTAINERS (expr);
> ! make_blocks (&EH_FILTER_FAILURE (expr), next_block_link, expr, NULL,
> ! block_tree_curr);
> }
>
>
> *************** make_eh_filter_expr_blocks (tree *expr_p
> *** 738,744 ****
>
> static void
> make_switch_expr_blocks (tree *switch_e_p, tree next_block_link,
> ! basic_block entry)
> {
> tree_stmt_iterator si;
> tree switch_e = *switch_e_p;
> --- 775,781 ----
>
> static void
> make_switch_expr_blocks (tree *switch_e_p, tree next_block_link,
> ! basic_block entry, struct block_tree *block_tree_curr)
> {
> tree_stmt_iterator si;
> tree switch_e = *switch_e_p;
> *************** make_switch_expr_blocks (tree *switch_e_
> *** 756,762 ****
> next_block_link = *(tsi_container (si));
>
> STRIP_CONTAINERS (switch_e);
> ! make_blocks (&SWITCH_BODY (switch_e), next_block_link, switch_e, NULL);
> }
>
>
> --- 793,800 ----
> next_block_link = *(tsi_container (si));
>
> STRIP_CONTAINERS (switch_e);
> ! make_blocks (&SWITCH_BODY (switch_e), next_block_link, switch_e, NULL,
> ! block_tree_curr);
> }
>
>
> *************** make_switch_expr_blocks (tree *switch_e_
> *** 779,785 ****
>
> static basic_block
> make_bind_expr_blocks (tree *bind_p, tree next_block_link,
> ! basic_block entry, tree parent_stmt)
> {
> tree_stmt_iterator si;
> tree bind = *bind_p;
> --- 817,824 ----
>
> static basic_block
> make_bind_expr_blocks (tree *bind_p, tree next_block_link,
> ! basic_block entry, tree parent_stmt,
> ! struct block_tree *block_tree_curr)
> {
> tree_stmt_iterator si;
> tree bind = *bind_p;
> *************** make_bind_expr_blocks (tree *bind_p, tre
> *** 803,809 ****
> ends with a block terminating statement. */
> STRIP_CONTAINERS (bind);
> return make_blocks (&BIND_EXPR_BODY (bind), next_block_link, parent_stmt,
> ! entry);
> }
>
>
> --- 842,848 ----
> ends with a block terminating statement. */
> STRIP_CONTAINERS (bind);
> return make_blocks (&BIND_EXPR_BODY (bind), next_block_link, parent_stmt,
> ! entry, block_tree_curr);
> }
>
>
> *************** delete_tree_cfg (void)
> *** 3183,3188 ****
> --- 3222,3228 ----
> free_blocks_annotations ();
>
> free_basic_block_vars (0);
> + block_tree_free ();
> }
>
>
> *************** tree_loop_optimizer_finalize (struct loo
> *** 5047,5050 ****
> --- 5087,5159 ----
> #ifdef ENABLE_CHECKING
> verify_flow_info ();
> #endif
> + }
> +
> + /* Allocates a block_tree node with outer node OUTER. */
> + static struct block_tree *
> + block_tree_alloc (struct block_tree *outer)
> + {
> + struct block_tree *nw;
> +
> + if (!block_tree_obstack_initialized)
> + {
> + block_tree_obstack_initialized = true;
> + gcc_obstack_init (&block_tree_obstack);
> + }
> + nw = obstack_alloc (&block_tree_obstack, sizeof (struct block_tree));
> + nw->outer = outer;
> + nw->subtree = NULL;
> + nw->bind = NULL_TREE;
> +
> + if (outer)
> + {
> + nw->next = outer->subtree;
> + outer->subtree = nw;
> + nw->level = outer->level + 1;
> + }
> + else
> + {
> + block_tree = nw;
> + nw->next = NULL;
> + nw->level = 0;
> + }
> +
> + return nw;
> + }
> +
> + /* Releases the block_tree obstack. */
> + static void
> + block_tree_free ()
> + {
> + if (block_tree_obstack_initialized)
> + {
> + block_tree_obstack_initialized = false;
> + obstack_free (&block_tree_obstack, NULL);
> + }
> + }
> +
> + /* Assigns a scope to variables defined in block SCOPE. */
> + static void
> + assign_vars_to_scope (struct block_tree *scope)
> + {
> + tree var;
> +
> + for (var = BIND_EXPR_VARS (scope->bind); var; var = TREE_CHAIN (var))
> + get_var_ann (var)->scope = scope;
> + }
> +
> + /* Dumps information about block tree BLOCK to FILE, indenting INDENT
> + spaces. */
> + void
> + dump_block_tree (FILE *file)
> + {
> + struct block_tree *act;
> + int i;
> +
> + for (act = bti_start (); !bti_end_p (act); bti_next (&act))
> + {
> + for (i = 0; i < act->level; i++)
> + fprintf (file, " ");
> + fprintf (file, "%p\n", (void *) act->bind);
> + }
> }
> Index: tree-flow-inline.h
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow-inline.h,v
> retrieving revision 1.1.2.47
> diff -c -3 -p -r1.1.2.47 tree-flow-inline.h
> *** tree-flow-inline.h 4 Aug 2003 18:44:02 -0000 1.1.2.47
> --- tree-flow-inline.h 10 Aug 2003 20:17:14 -0000
> *************** dom_children (basic_block bb)
> *** 342,347 ****
> --- 342,376 ----
>
> /* ----------------------------------------------------------------------- */
>
> + static inline struct block_tree *
> + bti_start ()
> + {
> + return block_tree;
> + }
> +
> + static inline bool
> + bti_end_p (struct block_tree *block)
> + {
> + return !block;
> + }
> +
> + static inline void
> + bti_next (struct block_tree **block)
> + {
> + struct block_tree *act = *block;
> +
> + if (act->subtree)
> + {
> + *block = act->subtree;
> + return;
> + }
> +
> + while (act->outer && !act->next)
> + act = act->outer;
> +
> + *block = act->next;
> + }
> +
> static inline bool
> bsi_end_p (block_stmt_iterator i)
> {
> Index: tree-flow.h
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
> retrieving revision 1.1.4.101
> diff -c -3 -p -r1.1.4.101 tree-flow.h
> *** tree-flow.h 8 Aug 2003 00:27:10 -0000 1.1.4.101
> --- tree-flow.h 10 Aug 2003 20:17:14 -0000
> *************** struct basic_block_def;
> *** 36,41 ****
> --- 36,52 ----
> typedef struct basic_block_def *basic_block;
> #endif
>
> + /* Tree of bind blocks in the function. */
> + extern struct block_tree
> + {
> + tree bind; /* The bind block itself. */
> +
> + int level; /* Of the node in the tree. */
> + struct block_tree *outer; /* Outer block. */
> + struct block_tree *subtree; /* Head of list of inner block. */
> + struct block_tree *next; /* Next block on the same level. */
> + } *block_tree;
> +
> /*---------------------------------------------------------------------------
> Tree annotations stored in tree_common.ann
> ---------------------------------------------------------------------------*/
> *************** struct var_ann_d GTY(())
> *** 120,125 ****
> --- 131,139 ----
>
> /* Used by the root-var object in tree-ssa-live.[ch]. */
> unsigned root_index;
> +
> + /* The binding block in that the variable is declared. */
> + struct block_tree * GTY ((skip (""))) scope;
> };
>
>
> *************** struct stmt_ann_d GTY(())
> *** 232,237 ****
> --- 246,254 ----
>
> /* Array of variables that have had their address taken in the statement. */
> varray_type addresses_taken;
> +
> + /* The binding block to that the statement belongs. */
> + struct block_tree * GTY ((skip (""))) scope;
> };
>
>
> *************** struct bb_ann_d
> *** 293,298 ****
> --- 310,320 ----
>
> typedef struct bb_ann_d *bb_ann_t;
>
> + /* Iterator for traversing block tree. */
> + static inline struct block_tree *bti_start (void);
> + static inline bool bti_end_p (struct block_tree *);
> + static inline void bti_next (struct block_tree **);
> +
> /* Accessors for basic block annotations. */
> static inline bb_ann_t bb_ann (basic_block);
> static inline basic_block parent_block (basic_block);
> *************** extern GTY(()) varray_type call_clobbere
> *** 390,395 ****
> --- 412,418 ----
> ---------------------------------------------------------------------------*/
> /* In tree-cfg.c */
> extern void build_tree_cfg (tree);
> + extern void dump_block_tree (FILE *);
> extern void delete_tree_cfg (void);
> extern bool is_ctrl_stmt (tree);
> extern bool is_ctrl_altering_stmt (tree);
> *************** void tree_ssa_dce (tree);
> *** 489,495 ****
>
> /* In tree-ssa-copyprop.c */
> void tree_ssa_copyprop (tree);
> ! void propagate_copy (tree *, tree);
>
>
> /* In tree-flow-inline.h */
> --- 512,518 ----
>
> /* In tree-ssa-copyprop.c */
> void tree_ssa_copyprop (tree);
> ! void propagate_copy (tree *, tree, struct block_tree *);
>
>
> /* In tree-flow-inline.h */
> Index: tree-ssa-copyprop.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-copyprop.c,v
> retrieving revision 1.1.2.11
> diff -c -3 -p -r1.1.2.11 tree-ssa-copyprop.c
> *** tree-ssa-copyprop.c 28 Jul 2003 17:16:20 -0000 1.1.2.11
> --- tree-ssa-copyprop.c 10 Aug 2003 20:17:14 -0000
> *************** static int dump_flags;
> *** 45,50 ****
> --- 45,51 ----
> static void copyprop_stmt (tree);
> static void copyprop_phi (tree);
> static inline tree get_original (tree);
> + static void move_var_to_scope (tree, struct block_tree *, struct block_tree *);
>
>
> /* Main entry point to the copy propagator. The algorithm is a simple
> *************** copyprop_stmt (tree stmt)
> *** 122,128 ****
> fprintf (dump_file, "\n");
> }
>
> ! propagate_copy (use_p, orig);
> modified = true;
> }
> }
> --- 123,129 ----
> fprintf (dump_file, "\n");
> }
>
> ! propagate_copy (use_p, orig, stmt_ann (stmt)->scope);
> modified = true;
> }
> }
> *************** get_original (tree var)
> *** 204,214 ****
>
> /* Replace the operand pointed to by OP_P with variable VAR. If *OP_P is a
> pointer, copy the memory tag used originally by *OP_P into VAR. This is
> ! needed in cases where VAR had never been dereferenced in the program. */
>
> void
> ! propagate_copy (tree *op_p, tree var)
> {
> #if defined ENABLE_CHECKING
> if (!may_propagate_copy (*op_p, var))
> abort ();
> --- 205,219 ----
>
> /* Replace the operand pointed to by OP_P with variable VAR. If *OP_P is a
> pointer, copy the memory tag used originally by *OP_P into VAR. This is
> ! needed in cases where VAR had never been dereferenced in the program.
> !
> ! SCOPE is the bind block in that the *OP_P occurs. */
>
> void
> ! propagate_copy (tree *op_p, tree var, struct block_tree *scope)
> {
> + struct block_tree *old_scope;
> +
> #if defined ENABLE_CHECKING
> if (!may_propagate_copy (*op_p, var))
> abort ();
> *************** propagate_copy (tree *op_p, tree var)
> *** 225,228 ****
> --- 230,271 ----
> }
>
> *op_p = var;
> +
> + old_scope = var_ann (SSA_NAME_VAR (var))->scope;
> + if (old_scope)
> + {
> + if (!scope)
> + scope = block_tree;
> + else
> + {
> + while (scope->level > old_scope->level)
> + scope = scope->outer;
> + if (scope != old_scope)
> + scope = block_tree;
> + }
> + if (scope != old_scope)
> + move_var_to_scope (SSA_NAME_VAR (var), old_scope, scope);
> + }
> + }
> +
> + /* Moves variable VAR from OLD_SCOPE to SCOPE. */
> + static void
> + move_var_to_scope (tree var, struct block_tree *old_scope,
> + struct block_tree *scope)
> + {
> + tree *ch;
> +
> + for (ch = &BIND_EXPR_VARS (old_scope->bind); *ch; ch = &TREE_CHAIN (*ch))
> + if (*ch == var)
> + break;
> + if (!*ch)
> + abort ();
> + *ch = TREE_CHAIN (*ch);
> +
> + TREE_CHAIN (var) = BIND_EXPR_VARS (scope->bind);
> + BIND_EXPR_VARS (scope->bind) = var;
> + var_ann (var)->scope = scope;
> +
> + /* ??? Not sure why, but it makes dwarf2out happy. */
> + DECL_ABSTRACT_ORIGIN (var) = NULL_TREE;
> }
> Index: tree-ssa-dom.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
> retrieving revision 1.1.2.17
> diff -c -3 -p -r1.1.2.17 tree-ssa-dom.c
> *** tree-ssa-dom.c 6 Aug 2003 03:16:40 -0000 1.1.2.17
> --- tree-ssa-dom.c 10 Aug 2003 20:17:16 -0000
> *************** optimize_stmt (block_stmt_iterator si, v
> *** 601,607 ****
> addr_expr_propagated_p = true;
>
> if (TREE_CODE (val) == SSA_NAME)
> ! propagate_copy (op_p, val);
> else
> *op_p = val;
>
> --- 601,607 ----
> addr_expr_propagated_p = true;
>
> if (TREE_CODE (val) == SSA_NAME)
> ! propagate_copy (op_p, val, stmt_ann (stmt)->scope);
> else
> *op_p = val;
>