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
Hello,
> Has this been bootstrapped and tested?
yes.
> If so, the patch is OK after a
> couple of minor changes:
...
> > *************** struct stmt_ann_d GTY(())
> > *** 232,237 ****
> > --- 235,246 ----
> >
> > /* Array of variables that have had their address taken in the statement. */
> > varray_type addresses_taken;
> > +
> > + /* The binding block to that the statement belongs. */
> > + tree scope;
> > +
> > + /* For BIND_EXPRs, a level of the scope. */
> > + int scope_level;
> > ^^^^^^^^^^^^^^^^
> >
> Not needed. You can use BLOCK_NUMBER (BIND_EXPR_BLOCK (scope))
Not really -- not every BIND_EXPR has a BIND_EXPR_BLOCK.
Here is the patch with the comment changes (+ a minor cleanup of the
place in tree-ssa-dom.c where I tried to missuse propagate_copy,
forgetting that it tests for may_propagate_copy).
Zdenek
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.150
diff -c -3 -p -r1.1.4.150 tree-cfg.c
*** tree-cfg.c 17 Aug 2003 18:51:29 -0000 1.1.4.150
--- tree-cfg.c 17 Aug 2003 21:30:14 -0000
*************** 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);
--- 84,98 ----
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, tree);
! static void make_loop_expr_blocks (tree *, basic_block, tree);
! static void make_cond_expr_blocks (tree *, tree, basic_block, tree);
! static void make_catch_expr_blocks (tree *, tree, basic_block, tree);
! static void make_eh_filter_expr_blocks (tree *, tree, basic_block, tree);
! static void make_try_expr_blocks (tree *, tree, basic_block, tree);
! static void make_switch_expr_blocks (tree *, tree, basic_block, tree);
! static basic_block make_bind_expr_blocks (tree *, tree, basic_block, tree,
! 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 ****
--- 107,113 ----
static void make_case_label_edges (basic_block);
/* Various helpers. */
+ static void assign_vars_to_scope (tree);
static basic_block successor_block (basic_block);
static basic_block last_exec_block (tree *);
static tree *first_exec_stmt (tree *);
*************** build_tree_cfg (tree fnbody)
*** 268,274 ****
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)
{
--- 270,276 ----
first_p = first_exec_stmt (&BIND_EXPR_BODY (fnbody));
if (first_p)
{
! make_blocks (first_p, NULL_TREE, NULL, NULL, fnbody);
if (n_basic_blocks > 0)
{
*************** clear_blocks_annotations (void)
*** 388,400 ****
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;
--- 390,404 ----
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.
+ SCOPE is the BIND_EXPR block containing *FIRST_P.
+
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 scope)
{
tree_stmt_iterator i;
tree stmt, last;
*************** make_blocks (tree *first_p, tree next_bl
*** 430,448 ****
/* 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;
--- 434,453 ----
/* Now add STMT to BB and create the subgraphs for special statement
codes. */
append_stmt_to_bb (stmt_p, bb, parent_stmt);
+ get_stmt_ann (stmt)->scope = scope;
if (code == LOOP_EXPR)
! make_loop_expr_blocks (stmt_p, bb, scope);
else if (code == COND_EXPR)
! make_cond_expr_blocks (stmt_p, next_block_link, bb, scope);
else if (code == SWITCH_EXPR)
! make_switch_expr_blocks (stmt_p, next_block_link, bb, scope);
else if (code == CATCH_EXPR)
! make_catch_expr_blocks (stmt_p, next_block_link, bb, scope);
else if (code == EH_FILTER_EXPR)
! make_eh_filter_expr_blocks (stmt_p, next_block_link, bb, scope);
else if (code == TRY_CATCH_EXPR || code == TRY_FINALLY_EXPR)
! make_try_expr_blocks (stmt_p, next_block_link, bb, scope);
else if (code == BIND_EXPR)
{
int num_blocks_before;
*************** make_blocks (tree *first_p, tree next_bl
*** 454,462 ****
will be the last basic block of the BIND_EXPR's subgraph. We
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;
--- 459,471 ----
will be the last basic block of the BIND_EXPR's subgraph. We
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;
! assign_vars_to_scope (stmt);
! get_stmt_ann (stmt)->scope_level =
! get_stmt_ann (scope)->scope_level + 1;
!
last_bb = make_bind_expr_blocks (stmt_p, next_block_link, bb,
! parent_stmt, stmt);
if (last_bb)
{
bb = last_bb;
*************** could_trap_p (tree expr)
*** 548,557 ****
lexical scope, this will be the statement that comes after LOOP_P's
container (see the documentation for NEXT_BLOCK_LINK).
! 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;
--- 557,568 ----
lexical scope, this will be the statement that comes after LOOP_P's
container (see the documentation for NEXT_BLOCK_LINK).
! ENTRY is the block whose last statement is *LOOP_P.
!
! SCOPE is the BIND_EXPR node holding *LOOP_P. */
static void
! make_loop_expr_blocks (tree *loop_p, basic_block entry, tree scope)
{
tree_stmt_iterator si;
tree loop = *loop_p;
*************** make_loop_expr_blocks (tree *loop_p, bas
*** 585,591 ****
next_block_link = *(tsi_container (si));
}
! make_blocks (&LOOP_EXPR_BODY (loop), next_block_link, loop, NULL);
}
--- 596,602 ----
next_block_link = *(tsi_container (si));
}
! make_blocks (&LOOP_EXPR_BODY (loop), next_block_link, loop, NULL, scope);
}
*************** make_loop_expr_blocks (tree *loop_p, bas
*** 596,606 ****
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;
--- 607,619 ----
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.
!
! SCOPE is the BIND_EXPR node holding *COND_P. */
static void
make_cond_expr_blocks (tree *cond_p, tree next_block_link,
! basic_block entry, tree scope)
{
tree_stmt_iterator si;
tree cond = *cond_p;
*************** make_cond_expr_blocks (tree *cond_p, tre
*** 618,625 ****
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. */
--- 631,638 ----
next_block_link = *(tsi_container (si));
STRIP_CONTAINERS (cond);
! make_blocks (&COND_EXPR_THEN (cond), next_block_link, cond, NULL, scope);
! make_blocks (&COND_EXPR_ELSE (cond), next_block_link, cond, NULL, scope);
}
/* Derive an exception handling region type from STMT. */
*************** get_eh_region_type (tree stmt)
*** 642,652 ****
}
/* Create the blocks for the TRY_CATCH_EXPR or TRY_FINALLY_EXPR node
! pointed by expr_p. */
static void
make_try_expr_blocks (tree *expr_p, tree next_block_link,
! basic_block entry)
{
tree_stmt_iterator si;
tree expr = *expr_p;
--- 655,667 ----
}
/* Create the blocks for the TRY_CATCH_EXPR or TRY_FINALLY_EXPR node
! pointed by expr_p.
!
! SCOPE is the BIND_EXPR node holding *EXPR_P. */
static void
make_try_expr_blocks (tree *expr_p, tree next_block_link,
! basic_block entry, tree scope)
{
tree_stmt_iterator si;
tree expr = *expr_p;
*************** make_try_expr_blocks (tree *expr_p, tree
*** 670,682 ****
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. */
--- 685,697 ----
VARRAY_PUSH_TREE (eh_stack, expr);
/* Make blocks for the TRY block. */
! make_blocks (&TREE_OPERAND (expr, 0), next_block_link, expr, NULL, scope);
/* 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, scope);
/* 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
*** 689,699 ****
}
}
! /* Create the blocks for the CATCH_EXPR node pointed to by expr_p. */
static void
make_catch_expr_blocks (tree *expr_p, tree next_block_link,
! basic_block entry)
{
tree_stmt_iterator si;
tree expr = *expr_p;
--- 704,716 ----
}
}
! /* Create the blocks for the CATCH_EXPR node pointed to by expr_p.
!
! SCOPE is the BIND_EXPR node holding *EXPR_P. */
static void
make_catch_expr_blocks (tree *expr_p, tree next_block_link,
! basic_block entry, tree scope)
{
tree_stmt_iterator si;
tree expr = *expr_p;
*************** make_catch_expr_blocks (tree *expr_p, tr
*** 708,721 ****
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;
--- 725,740 ----
tsi_next (&si);
STRIP_CONTAINERS (expr);
! make_blocks (&CATCH_BODY (expr), next_block_link, expr, NULL, scope);
}
! /* Create the blocks for the EH_FILTER_EXPR node pointed to by expr_p.
!
! SCOPE is the BIND_EXPR node holding *EXPR_P. */
static void
make_eh_filter_expr_blocks (tree *expr_p, tree next_block_link,
! basic_block entry, tree scope)
{
tree_stmt_iterator si;
tree expr = *expr_p;
*************** make_eh_filter_expr_blocks (tree *expr_p
*** 730,736 ****
tsi_next (&si);
STRIP_CONTAINERS (expr);
! make_blocks (&EH_FILTER_FAILURE (expr), next_block_link, expr, NULL);
}
--- 749,755 ----
tsi_next (&si);
STRIP_CONTAINERS (expr);
! make_blocks (&EH_FILTER_FAILURE (expr), next_block_link, expr, NULL, scope);
}
*************** make_eh_filter_expr_blocks (tree *expr_p
*** 741,751 ****
inside a lexical scope, this will be the statement that comes after
*SWITCH_E_P's container (see the documentation for NEXT_BLOCK_LINK).
! ENTRY is the block whose last statement is *SWITCH_E_P. */
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;
--- 760,772 ----
inside a lexical scope, this will be the statement that comes after
*SWITCH_E_P's container (see the documentation for NEXT_BLOCK_LINK).
! ENTRY is the block whose last statement is *SWITCH_E_P.
!
! SCOPE is the BIND_EXPR node holding *SWITCH_E_P. */
static void
make_switch_expr_blocks (tree *switch_e_p, tree next_block_link,
! basic_block entry, tree scope)
{
tree_stmt_iterator si;
tree switch_e = *switch_e_p;
*************** make_switch_expr_blocks (tree *switch_e_
*** 763,769 ****
next_block_link = *(tsi_container (si));
STRIP_CONTAINERS (switch_e);
! make_blocks (&SWITCH_BODY (switch_e), next_block_link, switch_e, NULL);
}
--- 784,790 ----
next_block_link = *(tsi_container (si));
STRIP_CONTAINERS (switch_e);
! make_blocks (&SWITCH_BODY (switch_e), next_block_link, switch_e, NULL, scope);
}
*************** make_switch_expr_blocks (tree *switch_e_
*** 782,792 ****
Return the last basic block added to the BIND_EXPR's subgraph. This
allows the caller to determine whether a new block should be started or
! not. */
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;
--- 803,816 ----
Return the last basic block added to the BIND_EXPR's subgraph. This
allows the caller to determine whether a new block should be started or
! not.
!
! SCOPE is the BIND_EXPR node holding *BIND_P (in fact it is equal to
! *BIND_P). */
static basic_block
make_bind_expr_blocks (tree *bind_p, tree next_block_link,
! basic_block entry, tree parent_stmt, tree scope)
{
tree_stmt_iterator si;
tree bind = *bind_p;
*************** make_bind_expr_blocks (tree *bind_p, tre
*** 810,816 ****
ends with a block terminating statement. */
STRIP_CONTAINERS (bind);
return make_blocks (&BIND_EXPR_BODY (bind), next_block_link, parent_stmt,
! entry);
}
--- 834,840 ----
ends with a block terminating statement. */
STRIP_CONTAINERS (bind);
return make_blocks (&BIND_EXPR_BODY (bind), next_block_link, parent_stmt,
! entry, scope);
}
*************** tree_loop_optimizer_finalize (struct loo
*** 5103,5106 ****
--- 5127,5140 ----
#ifdef ENABLE_CHECKING
verify_flow_info ();
#endif
+ }
+
+ /* Assigns a scope to variables defined in bind_expr SCOPE. */
+ static void
+ assign_vars_to_scope (tree scope)
+ {
+ tree var;
+
+ for (var = BIND_EXPR_VARS (scope); var; var = TREE_CHAIN (var))
+ get_var_ann (var)->scope = scope;
}
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.103
diff -c -3 -p -r1.1.4.103 tree-flow.h
*** tree-flow.h 15 Aug 2003 20:47:55 -0000 1.1.4.103
--- tree-flow.h 17 Aug 2003 21:30:15 -0000
*************** struct var_ann_d GTY(())
*** 120,125 ****
--- 120,128 ----
/* Used by the root-var object in tree-ssa-live.[ch]. */
unsigned root_index;
+
+ /* The BIND_EXPR in that the variable is declared. */
+ tree scope;
};
*************** struct stmt_ann_d GTY(())
*** 232,237 ****
--- 235,246 ----
/* Array of variables that have had their address taken in the statement. */
varray_type addresses_taken;
+
+ /* The BIND_EXPR to that the statement belongs. */
+ tree scope;
+
+ /* For BIND_EXPR, its level in the tree of BIND_EXPRs. */
+ int scope_level;
};
*************** void tree_ssa_dce (tree);
*** 491,498 ****
/* In tree-ssa-copyprop.c */
void tree_ssa_copyprop (tree);
! void propagate_copy (tree *, tree);
!
/* In tree-flow-inline.h */
static inline int phi_arg_from_edge (tree, edge);
--- 500,507 ----
/* In tree-ssa-copyprop.c */
void tree_ssa_copyprop (tree);
! void propagate_copy (tree *, tree, tree);
! void fixup_var_scope (tree, tree);
/* In tree-flow-inline.h */
static inline int phi_arg_from_edge (tree, edge);
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 17 Aug 2003 21:30:15 -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, tree, 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,213 ****
/* 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))
--- 205,216 ----
/* 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, tree scope)
{
#if defined ENABLE_CHECKING
if (!may_propagate_copy (*op_p, var))
*************** propagate_copy (tree *op_p, tree var)
*** 225,228 ****
--- 228,292 ----
}
*op_p = var;
+
+ fixup_var_scope (var, scope);
+ }
+
+ /* Fixes scope of variable VAR if it does not currently belong to SCOPE. */
+ void
+ fixup_var_scope (tree var, tree scope)
+ {
+ tree old_scope = var_ann (SSA_NAME_VAR (var))->scope;
+
+ /* If there is no old_scope, it is a newly created temporary, i.e. it is
+ in the topmost bind_expr and we have nothing to do. */
+ if (old_scope)
+ {
+ if (!scope)
+ scope = DECL_SAVED_TREE (current_function_decl);
+ else
+ {
+ while (stmt_ann (scope)->scope_level
+ > stmt_ann (old_scope)->scope_level)
+ scope = stmt_ann (scope)->scope;
+ }
+ if (scope != old_scope)
+ move_var_to_scope (SSA_NAME_VAR (var), old_scope,
+ DECL_SAVED_TREE (current_function_decl));
+ }
+ }
+
+ /* Moves variable VAR from OLD_SCOPE to SCOPE. */
+ static void
+ move_var_to_scope (tree var, tree old_scope, tree scope)
+ {
+ tree avar, prev;
+ tree block = BIND_EXPR_BLOCK (old_scope);
+
+ prev = NULL_TREE;
+ for (avar = BIND_EXPR_VARS (old_scope);
+ avar;
+ prev = avar, avar = TREE_CHAIN (avar))
+ if (avar == var)
+ break;
+ if (!avar)
+ abort ();
+
+ if (block)
+ remove_decl (avar, block);
+ else
+ remove_decl (avar, DECL_INITIAL (current_function_decl));
+
+ if (prev)
+ TREE_CHAIN (prev) = TREE_CHAIN (avar);
+ else
+ BIND_EXPR_VARS (old_scope) = TREE_CHAIN (avar);
+
+ TREE_CHAIN (var) = BIND_EXPR_VARS (scope);
+ BIND_EXPR_VARS (scope) = var;
+ var_ann (var)->scope = scope;
+
+ /* Dwarf2out ices (in add_abstract_origin_attribute) when it encounters
+ variable that is not declared, but has DECL_ABSTRACT_ORIGIN set. */
+ 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.26
diff -c -3 -p -r1.1.2.26 tree-ssa-dom.c
*** tree-ssa-dom.c 17 Aug 2003 19:00:35 -0000 1.1.2.26
--- tree-ssa-dom.c 17 Aug 2003 21:30:16 -0000
*************** optimize_stmt (block_stmt_iterator si, v
*** 759,765 ****
addr_expr_propagated_p = true;
if (TREE_CODE (val) == SSA_NAME)
! propagate_copy (op_p, val);
else
*op_p = val;
--- 759,765 ----
addr_expr_propagated_p = true;
if (TREE_CODE (val) == SSA_NAME)
! propagate_copy (op_p, val, stmt_ann (stmt)->scope);
else
*op_p = val;
*************** optimize_stmt (block_stmt_iterator si, v
*** 828,833 ****
--- 828,835 ----
}
opt_stats.num_re++;
+ if (TREE_CODE (cached_lhs) == SSA_NAME)
+ fixup_var_scope (cached_lhs, stmt_ann (stmt)->scope);
*expr_p = cached_lhs;
ann->modified = 1;
}