This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[tree-ssa-cfg] Reenable dce + bugfixes
- From: Zdenek Dvorak <rakdver at atrey dot karlin dot mff dot cuni dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Cc: dnovillo at redhat dot com, law at redhat dot com, aj at suse dot de
- Date: Sat, 16 Aug 2003 23:19:13 +0200
- Subject: [tree-ssa-cfg] Reenable dce + bugfixes
Hello,
this patch fixes several bugs in handling of phi nodes in cfg cleanup
and reenables dce. The dce does not remove useless conditionals yet.
This should not be a great problem in practice, since simple jump threading
together with removal of conditionals for that both branches lead to the
same place should do the trick anyway.
It should also fix the bootstrap problem in libstdc++-v3; it does not
reproduce for me now.
Zdenek
* basic-block.h (EDGE_CONSTRUCT_ENTRY): New.
* cfg.c (dump_edge_info): Add name for EDGE_CONSTRUCT_ENTRY flag.
* tree-cfg.c (remove_stmt, bsi_remove): Get basic block from argument
rather than from bb_for_stmt.
(remove_useless_stmts_and_vars): Export.
(make_edges): Mark edges with EDGE_CONSTRUCT_ENTRY.
(tree_redirect_edge_and_branch): Refuse to redirect abnormal edges.
Update phi nodes.
(cleanup_tree_cfg): Don't call remove_useless_stmts_and_vars.
(tree_merge_blocks): Handle phi nodes.
(tree_verify_flow_info): Add checks for phi nodes.
(dump_block_tree): Dump variables.
(tree_forwarder_block_p): Fail if successor is EDGE_CONSTRUCT_ENTRY,
or if block contains phi nodes.
(thread_jumps): Handle phi nodes.
(merge_seq_blocks): Don't merge with construct entry.
* tree-dfa.c (add_vdef): Export.
(virtual_op_p): Split off add_stmt_operand.
(add_stmt_operand): Use it.
* tree-flatten.c (tree_flatten_statement): Don't record BIND_EXPRs
with no variables.
(compact_to_block): Use EDGE_CONSTRUCT_ENTRY flag.
* tree-flow.h (remove_useless_stmts_and_vars, add_vdef,
virtual_op_p, fixup_var_scope): Declare.
* tree-optimize.c (optimize_function_tree): Enable dce.
* tree-ssa-copyprop.c (fixup_var_scope): Split off propagate_copy.
(propagate_copy): Use it.
* tree-ssa-dce.c: Disable removal of dead conditionals. Enable rest.
* tree-ssa-dom.c (optimize_stmt): Use fixup_var_scope.
* tree-ssa.c (rewrite_out_of_ssa): Call remove_useless_stmts_and_vars.
* tree.c (resize_phi_node): Zero new elements.
Index: basic-block.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/basic-block.h,v
retrieving revision 1.153.2.28.2.1
diff -c -3 -p -r1.153.2.28.2.1 basic-block.h
*** basic-block.h 14 Aug 2003 19:11:56 -0000 1.153.2.28.2.1
--- basic-block.h 16 Aug 2003 20:52:26 -0000
*************** typedef struct edge_def {
*** 159,165 ****
predicate is zero. */
#define EDGE_EXECUTABLE 4096 /* Edge is executable. Only
valid during SSA-CCP. */
! #define EDGE_ALL_FLAGS 8191
#define EDGE_COMPLEX (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
--- 159,166 ----
predicate is zero. */
#define EDGE_EXECUTABLE 4096 /* Edge is executable. Only
valid during SSA-CCP. */
! #define EDGE_CONSTRUCT_ENTRY 8192 /* An entry of block. */
! #define EDGE_ALL_FLAGS 16383
#define EDGE_COMPLEX (EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH)
Index: cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfg.c,v
retrieving revision 1.34.2.11.2.1
diff -c -3 -p -r1.34.2.11.2.1 cfg.c
*** cfg.c 14 Aug 2003 19:11:56 -0000 1.34.2.11.2.1
--- cfg.c 16 Aug 2003 20:52:26 -0000
*************** dump_edge_info (FILE *file, edge e, int
*** 639,645 ****
static const char * const bitnames[] = {
"fallthru", "ab", "abcall", "eh", "fake", "dfs_back",
"can_fallthru", "irreducible", "sibcall", "loop_exit",
! "true", "false", "exec"
};
int comma = 0;
int i, flags = e->flags;
--- 639,645 ----
static const char * const bitnames[] = {
"fallthru", "ab", "abcall", "eh", "fake", "dfs_back",
"can_fallthru", "irreducible", "sibcall", "loop_exit",
! "true", "false", "exec", "construct_entry"
};
int comma = 0;
int i, flags = e->flags;
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.145.2.1
diff -c -3 -p -r1.1.4.145.2.1 tree-cfg.c
*** tree-cfg.c 14 Aug 2003 19:11:58 -0000 1.1.4.145.2.1
--- tree-cfg.c 16 Aug 2003 20:52:30 -0000
*************** static void tree_loop_optimizer_finalize
*** 171,177 ****
/* Flowgraph optimization and cleanup. */
static void remove_bb (basic_block);
static void tree_merge_blocks (basic_block, basic_block);
! static void remove_stmt (tree_cell);
static edge find_taken_edge_cond_expr (basic_block, tree);
static edge find_taken_edge_switch_expr (basic_block, tree);
static tree find_edge_goto (tree, edge);
--- 171,177 ----
/* Flowgraph optimization and cleanup. */
static void remove_bb (basic_block);
static void tree_merge_blocks (basic_block, basic_block);
! static void remove_stmt (tree_cell, basic_block);
static edge find_taken_edge_cond_expr (basic_block, tree);
static edge find_taken_edge_switch_expr (basic_block, tree);
static tree find_edge_goto (tree, edge);
*************** static void assign_vars_to_scope (struct
*** 182,188 ****
static void remove_superfluous_labels (void);
static void thread_jumps (void);
static bool tree_forwarder_block_p (basic_block);
- static void remove_useless_stmts_and_vars (void);
static void merge_seq_blocks (void);
/* Location to track pending stmt for edge insertion. */
--- 182,187 ----
*************** static void
*** 568,573 ****
--- 567,574 ----
make_edges (void)
{
basic_block bb;
+ struct block_tree *bti;
+ edge e;
/* Create an edge from entry to the first block with executable
statements in it. */
*************** make_edges (void)
*** 609,614 ****
--- 610,627 ----
/* We do not care about fake edges, so remove any that the CFG
builder inserted for completeness. */
remove_fake_edges ();
+
+ /* Mark special edges of constructs. */
+ for (bti = bti_start (); !bti_end_p (bti); bti_next (&bti))
+ if (bti->entry)
+ {
+ for (e = bti->entry->pred; e; e = e->pred_next)
+ if (e->flags & EDGE_FALLTHRU)
+ break;
+
+ if (e)
+ e->flags |= EDGE_CONSTRUCT_ENTRY;
+ }
}
/* Create edges for control statement at basic block BB. */
*************** tree_redirect_edge_and_branch (edge e, b
*** 875,880 ****
--- 888,896 ----
if (e->dest == dest)
return true;
+ if (e->flags & EDGE_ABNORMAL)
+ return false;
+
stmt = last_stmt (bb);
bsi = bsi_last (bb);
*************** tree_redirect_edge_and_branch (edge e, b
*** 886,893 ****
if (!stmt
|| !stmt_ends_bb_p (stmt))
{
! if (bb->succ->succ_next
! || !(e->flags & EDGE_FALLTHRU))
abort ();
if (old)
--- 902,908 ----
if (!stmt
|| !stmt_ends_bb_p (stmt))
{
! if (!(e->flags & EDGE_FALLTHRU))
abort ();
if (old)
*************** tree_redirect_edge_and_branch (edge e, b
*** 926,934 ****
redirect:
if (old)
! remove_edge (e);
else
! redirect_edge_succ (e, dest);
tree_cleanup_block_edges (bb, false);
return true;
}
--- 941,955 ----
redirect:
if (old)
! ssa_remove_edge (e);
else
! {
! tree phi;
!
! for (phi = phi_nodes (e->dest); phi; phi = TREE_CHAIN (phi))
! remove_phi_arg (phi, e->src);
! redirect_edge_succ (e, dest);
! }
tree_cleanup_block_edges (bb, false);
return true;
}
*************** cleanup_tree_cfg (int expensive)
*** 1023,1029 ****
if (expensive)
{
remove_superfluous_labels ();
- remove_useless_stmts_and_vars ();
thread_jumps ();
}
delete_unreachable_blocks ();
--- 1044,1049 ----
*************** tree_merge_blocks (basic_block a, basic_
*** 1128,1133 ****
--- 1148,1154 ----
{
block_stmt_iterator bsi;
edge e;
+ tree phi, stmt;
/* Ensure that b follows a. */
if (a->next_bb != b)
*************** tree_merge_blocks (basic_block a, basic_
*** 1136,1147 ****
if (!(a->succ->flags & EDGE_FALLTHRU))
abort ();
- remove_edge (a->succ);
-
if (last_stmt (a)
&& stmt_ends_bb_p (last_stmt (a)))
abort ();
/* Remove labels from B and set bb_for_stmt to A for other statements. */
for (bsi = bsi_start (b); !bsi_end_p (bsi);)
{
--- 1157,1191 ----
if (!(a->succ->flags & EDGE_FALLTHRU))
abort ();
if (last_stmt (a)
&& stmt_ends_bb_p (last_stmt (a)))
abort ();
+ /* Turn phi nodes into assignments. */
+ bsi = bsi_last (a);
+ for (phi = phi_nodes (b); phi; phi = TREE_CHAIN (phi))
+ {
+ tree src = PHI_ARG_DEF (phi, 0);
+ tree dest = PHI_RESULT (phi);
+
+ if (virtual_op_p (SSA_NAME_VAR (dest)))
+ {
+ tree vdef;
+
+ stmt = build_empty_stmt ();
+ get_stmt_ann (stmt);
+ add_vdef (SSA_NAME_VAR (dest), stmt, NULL);
+ vdef = VARRAY_TREE (vdef_ops (stmt), 0);
+ VDEF_RESULT (vdef) = dest;
+ VDEF_OP (vdef) = src;
+ }
+ else
+ stmt = build (MODIFY_EXPR, TREE_TYPE (dest), dest, src);
+
+ SSA_NAME_DEF_STMT (dest) = stmt;
+ bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
+ }
+
/* Remove labels from B and set bb_for_stmt to A for other statements. */
for (bsi = bsi_start (b); !bsi_end_p (bsi);)
{
*************** tree_merge_blocks (basic_block a, basic_
*** 1154,1159 ****
--- 1198,1205 ----
}
}
+ remove_edge (a->succ);
+
/* Merge the chains. */
if (a->end_tree)
a->end_tree->next = b->head_tree;
*************** tree_merge_blocks (basic_block a, basic_
*** 1172,1177 ****
--- 1218,1228 ----
for (e = a->succ; e; e = e->succ_next)
e->src = a;
+ if (bb_ann (b)->block->entry == b)
+ abort ();
+ if (bb_ann (b)->block->exit == b)
+ bb_ann (b)->block->exit = a;
+
/* Remove B. */
delete_basic_block (b);
}
*************** bsi_remove (block_stmt_iterator *i)
*** 1185,1191 ****
bsi_next (i);
! remove_stmt (cell);
}
--- 1236,1242 ----
bsi_next (i);
! remove_stmt (cell, i->bb);
}
*************** bsi_replace (block_stmt_iterator bsi, tr
*** 1202,1220 ****
modify_stmt (bsi_stmt (bsi));
}
! /* Remove statement CELL. */
static void
! remove_stmt (tree_cell cell)
{
varray_type vdefs;
size_t i;
varray_type defs;
tree stmt = cell->stmt;
- basic_block bb = bb_for_stmt (cell->stmt);
-
- if (!bb)
- abort ();
/* If the statement is a LABEL_EXPR, remove the LABEL_DECL from
the symbol table. */
--- 1253,1267 ----
modify_stmt (bsi_stmt (bsi));
}
! /* Remove statement CELL in basic block BB. */
static void
! remove_stmt (tree_cell cell, basic_block bb)
{
varray_type vdefs;
size_t i;
varray_type defs;
tree stmt = cell->stmt;
/* If the statement is a LABEL_EXPR, remove the LABEL_DECL from
the symbol table. */
*************** tree_verify_flow_info (void)
*** 2588,2597 ****
{
basic_block bb;
tree_cell stmt, last;
! tree t, l, label;
block_stmt_iterator si;
edge e, le, te, fe;
! int err = 0;
FOR_EACH_BB (bb)
{
--- 2635,2645 ----
{
basic_block bb;
tree_cell stmt, last;
! tree t, l, label, phi;
block_stmt_iterator si;
edge e, le, te, fe;
! struct block_tree *bti;
! int err = 0, degree;
FOR_EACH_BB (bb)
{
*************** tree_verify_flow_info (void)
*** 2802,2809 ****
--- 2850,2933 ----
default: ;
}
}
+
+ degree = 0;
+ for (e = bb->pred; e; e = e->pred_next)
+ {
+ if (bb != bb_ann (bb)->block->entry
+ && (e->flags & EDGE_CONSTRUCT_ENTRY))
+ {
+ fprintf (stderr,
+ "Construct entry edge not entering construct entry: %d\n",
+ bb->index);
+ err = 1;
+ }
+
+ for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+ if (phi_arg_from_edge (phi, e) < 0)
+ {
+ fprintf (stderr,
+ "No entry for edge in phi node: %d\n", bb->index);
+ err = 1;
+ }
+ degree++;
+ }
+ for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
+ if (PHI_NUM_ARGS (phi) != degree)
+ {
+ fprintf (stderr,
+ "Superfluous entries in phi node: %d\n", bb->index);
+ err = 1;
+ }
+ }
+
+ /* Entry block should have just one successor. Exit block should have
+ at most one fallthru predecessor. */
+ if (!ENTRY_BLOCK_PTR->succ
+ || ENTRY_BLOCK_PTR->succ->succ_next)
+ {
+ fprintf (stderr, "Wrong amount of edges from entry\n");
+ err = 1;
+ }
+
+ if (!(ENTRY_BLOCK_PTR->succ->flags & EDGE_FALLTHRU))
+ {
+ fprintf (stderr, "Entry is not fallthru\n");
+ err = 1;
}
+ le = NULL;
+ for (e = EXIT_BLOCK_PTR->pred; e; e = e->pred_next)
+ if (e->flags & EDGE_FALLTHRU)
+ {
+ if (le)
+ {
+ fprintf (stderr, "More than one fallthru to exit\n");
+ err = 1;
+ break;
+ }
+ le = e;
+ }
+
+ /* Check special edges of constructs. */
+ for (bti = bti_start (); !bti_end_p (bti); bti_next (&bti))
+ if (bti->entry)
+ {
+ le = NULL;
+ for (e = bti->entry->pred; e; e = e->pred_next)
+ if (e->flags & EDGE_CONSTRUCT_ENTRY)
+ {
+ if (le)
+ {
+ fprintf (stderr, "More than one construct %p entry\n",
+ (void *) bti);
+ err = 1;
+ break;
+ }
+ le = e;
+ }
+ }
+
return err;
}
*************** redo:
*** 2928,2934 ****
if (e_true->dest == bb->next_bb)
{
! remove_stmt (bb->end_tree);
e_true->flags |= EDGE_FALLTHRU;
}
break;
--- 3052,3058 ----
if (e_true->dest == bb->next_bb)
{
! bsi_remove (&bsi);
e_true->flags |= EDGE_FALLTHRU;
}
break;
*************** redo:
*** 2988,2994 ****
|| (e->flags & EDGE_ABNORMAL))
continue;
! remove_edge (e);
}
}
--- 3112,3118 ----
|| (e->flags & EDGE_ABNORMAL))
continue;
! ssa_remove_edge (e);
}
}
*************** void
*** 3099,3104 ****
--- 3223,3229 ----
dump_block_tree (FILE *file, int indent, struct block_tree *block)
{
int i;
+ tree var;
for (i = 0; i < indent; i++)
fprintf (file, " ");
*************** dump_block_tree (FILE *file, int indent,
*** 3109,3114 ****
--- 3234,3248 ----
fprintf (file, " of ");
dump_block_tree_id (file, block->of);
}
+ if (block->type == BT_BIND)
+ {
+ fprintf (file, " vars");
+ for (var = BIND_EXPR_VARS (block->bind); var; var = TREE_CHAIN (var))
+ {
+ fprintf (file, " ");
+ print_generic_stmt (file, var, 0);
+ }
+ }
if (block->entry)
fprintf (file, " entry %d", block->entry->index);
*************** tree_forwarder_block_p (basic_block bb)
*** 3294,3302 ****
--- 3428,3440 ----
if (!bb->succ
|| bb->succ->succ_next
|| (bb->succ->flags & EDGE_ABNORMAL)
+ || (bb->succ->flags & EDGE_CONSTRUCT_ENTRY)
|| bb == ENTRY_BLOCK_PTR)
return false;
+ if (phi_nodes (bb))
+ return false;
+
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
switch (TREE_CODE (bsi_stmt (bsi)))
{
*************** tree_forwarder_block_p (basic_block bb)
*** 3316,3324 ****
static void
thread_jumps ()
{
! edge e, next;
basic_block bb, dest, slow;
int set_slow;
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
--- 3454,3464 ----
static void
thread_jumps ()
{
! edge e, next, last, old;
basic_block bb, dest, slow;
int set_slow;
+ tree phi, val1, val2;
+ int arg;
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR, next_bb)
{
*************** thread_jumps ()
*** 3335,3340 ****
--- 3475,3481 ----
next = e->succ_next;
if ((e->flags & EDGE_ABNORMAL)
+ || (e->flags & EDGE_CONSTRUCT_ENTRY)
|| e->dest == EXIT_BLOCK_PTR
|| !tree_forwarder_block_p (e->dest)
|| e->dest->succ->dest == EXIT_BLOCK_PTR)
*************** thread_jumps ()
*** 3343,3350 ****
--- 3484,3493 ----
slow = e->dest;
set_slow = 0;
+ last = e->dest->succ;
for (dest = e->dest->succ->dest;
tree_forwarder_block_p (dest);
+ last = dest->succ,
dest = dest->succ->dest,
set_slow ^= 1)
{
*************** thread_jumps ()
*** 3358,3365 ****
break;
}
! if (dest != e->dest)
! redirect_edge_and_branch (e, dest);
}
}
}
--- 3501,3545 ----
break;
}
! if (dest == e->dest)
! continue;
!
! old = find_edge (bb, dest);
! if (old)
! {
! /* If there already is an edge, check whether the values of
! in phi nodes differ. */
! for (phi = phi_nodes (dest); phi; phi = TREE_CHAIN (phi))
! {
! val1 = PHI_ARG_DEF (phi, phi_arg_from_edge (phi, last));
! val2 = PHI_ARG_DEF (phi, phi_arg_from_edge (phi, old));
!
! if (!operand_equal_p (val1, val2, false))
! break;
! }
! if (phi)
! {
! /* The previous block is forwarder, so there are no
! phi nodes to update. */
! dest = last->src;
! }
! }
!
! if (dest == e->dest)
! continue;
!
! if (redirect_edge_and_branch (e, dest)
! && !old)
! {
! /* Update phi nodes. */
! for (phi = phi_nodes (dest); phi; phi = TREE_CHAIN (phi))
! {
! arg = phi_arg_from_edge (phi, last);
! if (arg < 0)
! abort ();
! add_phi_arg (&phi, PHI_ARG_DEF (phi, arg), e);
! }
! }
}
}
}
*************** find_edge_goto (tree stmt, edge e)
*** 3406,3412 ****
}
/* Removes unneccesary eh statements and variables. */
! static void
remove_useless_stmts_and_vars ()
{
struct block_tree *bti;
--- 3586,3592 ----
}
/* Removes unneccesary eh statements and variables. */
! void
remove_useless_stmts_and_vars ()
{
struct block_tree *bti;
*************** merge_seq_blocks ()
*** 3483,3488 ****
--- 3663,3669 ----
bb->succ
&& !bb->succ->succ_next
&& !(bb->succ->flags & EDGE_ABNORMAL)
+ && !(bb->succ->flags & EDGE_CONSTRUCT_ENTRY)
&& bb->succ->dest != EXIT_BLOCK_PTR
&& bb->succ->dest != bb
/* That has a single predecessor. */
Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.144
diff -c -3 -p -r1.1.4.144 tree-dfa.c
*** tree-dfa.c 11 Aug 2003 02:30:56 -0000 1.1.4.144
--- tree-dfa.c 16 Aug 2003 20:52:32 -0000
*************** static bool may_alias_p (tree, HOST_WIDE
*** 128,134 ****
static bool may_access_global_mem_p (tree);
static void add_def (tree *, tree);
static void add_use (tree *, tree);
- static void add_vdef (tree, tree, voperands_t);
static void add_stmt_operand (tree *, tree, int, voperands_t);
static void add_immediate_use (tree, tree);
static tree find_vars_r (tree *, int *, void *);
--- 128,133 ----
*************** get_expr_operands (tree stmt, tree *expr
*** 515,520 ****
--- 514,561 ----
abort ();
}
+ /* Checks whether the variable VAR should be accessed via virtual ops. */
+ bool
+ virtual_op_p (tree var)
+ {
+ bool is_scalar;
+ tree sym;
+ var_ann_t v_ann;
+
+ is_scalar = (SSA_VAR_P (var)
+ && !AGGREGATE_TYPE_P (TREE_TYPE (var))
+ && TREE_CODE (TREE_TYPE (var)) != COMPLEX_TYPE);
+ if (!is_scalar)
+ return true;
+
+ if (!DECL_P (var))
+ var = get_virtual_var (var);
+
+ if (var == NULL_TREE || !SSA_VAR_P (var))
+ abort ();
+
+ sym = get_base_symbol (var);
+ v_ann = var_ann (sym);
+
+ if (v_ann->has_hidden_use)
+ abort ();
+
+ /* Globals, local statics and variables referenced in VA_ARG_EXPR are
+ always accessed using virtual operands. */
+ if (decl_function_context (sym) == 0
+ || TREE_STATIC (sym)
+ || v_ann->is_in_va_arg_expr)
+ return true;
+
+ /* If the variable is an alias tag, it means that its address has been
+ taken and it's being accessed directly and via pointers. To avoid
+ mixing real and virtual operands, we treat all references to aliased
+ variables as virtual. */
+ if (v_ann->is_alias_tag)
+ return true;
+
+ return false;
+ }
/* Add *VAR_P to the appropriate operand array of STMT. FLAGS is as in
get_expr_operands. The following are the rules used to decide
*************** add_stmt_operand (tree *var_p, tree stmt
*** 589,606 ****
return;
}
! /* Globals, local statics and variables referenced in VA_ARG_EXPR are
! always accessed using virtual operands. */
! if (decl_function_context (sym) == 0
! || TREE_STATIC (sym)
! || v_ann->is_in_va_arg_expr)
! flags |= opf_force_vop;
!
! /* If the variable is an alias tag, it means that its address has been
! taken and it's being accessed directly and via pointers. To avoid
! mixing real and virtual operands, we treat all references to aliased
! variables as virtual. */
! if (v_ann->is_alias_tag)
flags |= opf_force_vop;
aliases = v_ann->may_aliases;
--- 630,636 ----
return;
}
! if (virtual_op_p (var))
flags |= opf_force_vop;
aliases = v_ann->may_aliases;
*************** add_stmt_operand (tree *var_p, tree stmt
*** 610,619 ****
opf_force_vop is set). */
if (flags & opf_is_def)
{
! if (is_scalar && !(flags & opf_force_vop))
! add_def (var_p, stmt);
! else
add_vdef (var, stmt, prev_vops);
/* If the variable is an alias tag, mark the statement. */
if (v_ann->is_alias_tag)
--- 640,649 ----
opf_force_vop is set). */
if (flags & opf_is_def)
{
! if (flags & opf_force_vop)
add_vdef (var, stmt, prev_vops);
+ else
+ add_def (var_p, stmt);
/* If the variable is an alias tag, mark the statement. */
if (v_ann->is_alias_tag)
*************** add_stmt_operand (tree *var_p, tree stmt
*** 621,631 ****
}
else
{
! if (is_scalar
! && !(flags & opf_force_vop))
! add_use (var_p, stmt);
! else
add_vuse (var, stmt, prev_vops);
/* If the variable is an alias tag, mark the statement. */
if (v_ann->is_alias_tag)
--- 651,660 ----
}
else
{
! if (flags & opf_force_vop)
add_vuse (var, stmt, prev_vops);
+ else
+ add_use (var_p, stmt);
/* If the variable is an alias tag, mark the statement. */
if (v_ann->is_alias_tag)
*************** add_use (tree *use_p, tree stmt)
*** 725,731 ****
added here. This is done to preserve the SSA numbering of virtual
operands. */
! static void
add_vdef (tree var, tree stmt, voperands_t prev_vops)
{
tree vdef;
--- 754,760 ----
added here. This is done to preserve the SSA numbering of virtual
operands. */
! void
add_vdef (tree var, tree stmt, voperands_t prev_vops)
{
tree vdef;
Index: tree-flatten.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flatten.c,v
retrieving revision 1.1.2.1
diff -c -3 -p -r1.1.2.1 tree-flatten.c
*** tree-flatten.c 14 Aug 2003 19:11:58 -0000 1.1.2.1
--- tree-flatten.c 16 Aug 2003 20:52:32 -0000
*************** tree_flatten_statement (tree stmt, tree_
*** 86,94 ****
{
case BIND_EXPR:
{
! append (after, stmt, TCN_BIND);
tree_flatten_statement (BIND_EXPR_BODY (stmt), after, enclosing_switch);
! append (after, NULL_TREE, TCN_UNBIND);
}
break;
--- 86,106 ----
{
case BIND_EXPR:
{
! /* Do not record empty BIND_EXPRs, unless they are top-level ones
! (or top-level ones of inlined functions). */
! tree block = BIND_EXPR_BLOCK (stmt);
! int record = (BIND_EXPR_VARS (stmt)
! || stmt == DECL_SAVED_TREE (current_function_decl)
! || (block
! && BLOCK_ABSTRACT_ORIGIN (block)
! && (TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block))
! == FUNCTION_DECL)));
!
! if (record)
! append (after, stmt, TCN_BIND);
tree_flatten_statement (BIND_EXPR_BODY (stmt), after, enclosing_switch);
! if (record)
! append (after, NULL_TREE, TCN_UNBIND);
}
break;
*************** static basic_block
*** 377,384 ****
compact_to_block (struct block_tree *node)
{
basic_block entry, last, act, next;
- edge e;
- block_stmt_iterator bsi;
if (!node->outer)
{
--- 389,394 ----
*************** compact_to_block (struct block_tree *nod
*** 427,465 ****
last = node->exit;
}
! #ifdef ENABLE_CHECKING
! /* The entry block should only be accessed from outside. */
if (node->entry)
{
! for (e = entry->pred; e; e = e->pred_next)
{
! struct block_tree *block = bb_ann (e->src)->block;
! if (block->level >= node->level)
{
! while (block->level > node->level)
! block = block->outer;
! if (block == node)
abort ();
}
}
- }
- #endif
-
- /* Ensure that the block is entered through fallthru or abnormal edges.
- Do not do this for bind blocks, as it is irrelevant here. */
- if (node->type != BT_BIND
- && first_stmt (entry)
- && TREE_CODE (first_stmt (entry)) == LABEL_EXPR)
- {
- for (bsi = bsi_start (entry); !bsi_end_p (bsi); bsi_next (&bsi))
- if (TREE_CODE (bsi_stmt (bsi)) != LABEL_EXPR)
- break;
-
- e = tree_split_block (entry, bsi);
-
- bb_ann (e->src)->block = node->outer;
- entry = e->dest;
}
}
--- 437,465 ----
last = node->exit;
}
! /* Ensure that the block is entered through its entry edge as
! fallthru. */
if (node->entry)
{
! edge e;
!
! for (e = node->entry->pred; e; e = e->pred_next)
! if (e->flags & EDGE_CONSTRUCT_ENTRY)
! break;
! if (e)
{
! if (entry->prev_bb != e->src)
! tree_move_block_after (e->src, entry->prev_bb, false);
! if (!(e->flags & EDGE_FALLTHRU))
{
! act = split_edge (e);
! tree_move_block_after (act, entry->prev_bb, false);
!
! if (!(act->succ->flags & EDGE_FALLTHRU))
abort ();
}
}
}
}
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.101.2.1
diff -c -3 -p -r1.1.4.101.2.1 tree-flow.h
*** tree-flow.h 14 Aug 2003 19:11:58 -0000 1.1.4.101.2.1
--- tree-flow.h 16 Aug 2003 20:52:34 -0000
*************** extern void dump_cfg_stats (FILE *);
*** 457,462 ****
--- 457,463 ----
extern void debug_cfg_stats (void);
extern void tree_cfg2dot (FILE *);
extern void cleanup_tree_cfg (int);
+ extern void remove_useless_stmts_and_vars (void);
extern void remove_phi_nodes_and_edges_for_unreachable_block (basic_block);
extern tree first_stmt (basic_block);
extern tree last_stmt (basic_block);
*************** extern void dump_alias_info (FILE *);
*** 505,510 ****
--- 506,513 ----
extern void debug_alias_info (void);
extern tree get_virtual_var (tree);
extern void add_vuse (tree, tree, voperands_t);
+ extern void add_vdef (tree, tree, voperands_t);
+ extern bool virtual_op_p (tree);
extern void create_global_var (void);
/* Flags used when computing reaching definitions and reached uses. */
*************** void tree_ssa_dce (tree);
*** 545,550 ****
--- 548,554 ----
/* In tree-ssa-copyprop.c */
void tree_ssa_copyprop (tree);
void propagate_copy (basic_block, tree *, tree);
+ void fixup_var_scope (basic_block, tree);
/* In tree-flow-inline.h */
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-optimize.c,v
retrieving revision 1.1.4.43.2.1
diff -c -3 -p -r1.1.4.43.2.1 tree-optimize.c
*** tree-optimize.c 14 Aug 2003 19:11:58 -0000 1.1.4.43.2.1
--- tree-optimize.c 16 Aug 2003 20:52:34 -0000
*************** optimize_function_tree (tree fndecl)
*** 98,105 ****
into must-alias relations. If DCE eliminated all the pointer
assignments that were taking the address of a local variable X,
we can now rename X as a non-aliased local. */
! if (0)
! tree_ssa_dce (fndecl);
if (flag_tree_dom && flag_tree_must_alias)
tree_compute_must_alias (fndecl);
}
--- 98,104 ----
into must-alias relations. If DCE eliminated all the pointer
assignments that were taking the address of a local variable X,
we can now rename X as a non-aliased local. */
! tree_ssa_dce (fndecl);
if (flag_tree_dom && flag_tree_must_alias)
tree_compute_must_alias (fndecl);
}
*************** optimize_function_tree (tree fndecl)
*** 113,119 ****
if (flag_tree_copyprop)
tree_ssa_copyprop (fndecl);
! if (0 && flag_tree_dce)
tree_ssa_dce (fndecl);
#if defined ENABLE_CHECKING
--- 112,118 ----
if (flag_tree_copyprop)
tree_ssa_copyprop (fndecl);
! if (flag_tree_dce)
tree_ssa_dce (fndecl);
#if defined ENABLE_CHECKING
Index: tree-ssa-copyprop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-copyprop.c,v
retrieving revision 1.1.2.11.2.1
diff -c -3 -p -r1.1.2.11.2.1 tree-ssa-copyprop.c
*** tree-ssa-copyprop.c 14 Aug 2003 19:11:58 -0000 1.1.2.11.2.1
--- tree-ssa-copyprop.c 16 Aug 2003 20:52:34 -0000
*************** get_original (tree var)
*** 214,221 ****
void
propagate_copy (basic_block bb, tree *op_p, tree var)
{
- struct block_tree *scope, *old_scope;
-
#if defined ENABLE_CHECKING
if (!may_propagate_copy (*op_p, var))
abort ();
--- 214,219 ----
*************** propagate_copy (basic_block bb, tree *op
*** 232,237 ****
--- 230,245 ----
}
*op_p = var;
+
+ fixup_var_scope (bb, var);
+ }
+
+ /* Moves variable VAR high enough in scope tree so that basic block BB is in
+ scope. */
+ void
+ fixup_var_scope (basic_block bb, tree var)
+ {
+ struct block_tree *scope, *old_scope;
/* Update scope of var. */
old_scope = var_ann (SSA_NAME_VAR (var))->scope;
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dce.c,v
retrieving revision 1.1.2.52.2.1
diff -c -3 -p -r1.1.2.52.2.1 tree-ssa-dce.c
*** tree-ssa-dce.c 14 Aug 2003 19:11:58 -0000 1.1.2.52.2.1
--- tree-ssa-dce.c 16 Aug 2003 20:52:34 -0000
*************** Software Foundation, 59 Temple Place - S
*** 41,47 ****
2. Propagating necessary instructions, e.g., the instructions
giving values to operands in necessary instructions; and
3. Removing dead instructions (except replacing dead conditionals
! with unconditional jumps). */
#include "config.h"
#include "system.h"
--- 41,51 ----
2. Propagating necessary instructions, e.g., the instructions
giving values to operands in necessary instructions; and
3. Removing dead instructions (except replacing dead conditionals
! with unconditional jumps).
!
! Removing of unnecessary conditionals is disabled for now, since
! determining control dependence is costly. This usually does not
! matter, since cfg cleanup will remove the empty blocks anyway. */
#include "config.h"
#include "system.h"
*************** static FILE *dump_file;
*** 69,76 ****
--- 73,82 ----
static int dump_flags;
static varray_type worklist;
+ #if 0
static dominance_info dom_info = NULL;
static dominance_info pdom_info = NULL;
+ #endif
static struct stmt_stats
{
*************** static void process_worklist (void);
*** 93,99 ****
static void remove_dead_stmts (void);
static void remove_dead_stmt (block_stmt_iterator *, basic_block);
static void remove_dead_phis (basic_block);
! static void remove_conditional (basic_block) ATTRIBUTE_UNUSED;
/* Is a tree necessary? */
--- 99,107 ----
static void remove_dead_stmts (void);
static void remove_dead_stmt (block_stmt_iterator *, basic_block);
static void remove_dead_phis (basic_block);
! #if 0
! static void remove_conditional (basic_block);
! #endif
/* Is a tree necessary? */
*************** need_to_preserve_store (tree var)
*** 166,172 ****
if (var == NULL)
return false;
- sym = SSA_NAME_VAR (var);
base_symbol = get_base_symbol (var);
/* File scope variables must be preserved. */
--- 174,179 ----
*************** need_to_preserve_store (tree var)
*** 177,182 ****
--- 184,190 ----
if (TREE_STATIC (base_symbol))
return true;
+ sym = SSA_NAME_VAR (var);
/* If SYM may alias global memory, we also need to preserve the store. */
if (may_alias_global_mem_p (sym))
return true;
*************** stmt_useful_p (tree stmt)
*** 224,245 ****
size_t i;
/* Instructions that are implicitly live. Function calls, asm and return
! statements are required. Labels and BIND_EXPR nodes are kept because
! they are control flow, and we have no way of knowing whether they can
! be removed. DCE can eliminate all the other statements in a block,
! and CFG can then remove the block and labels. */
! if ((TREE_CODE (stmt) == ASM_EXPR)
|| (TREE_CODE (stmt) == RETURN_EXPR)
- || (TREE_CODE (stmt) == CASE_LABEL_EXPR)
|| (TREE_CODE (stmt) == LABEL_EXPR)
- || (TREE_CODE (stmt) == BIND_EXPR)
|| (TREE_CODE (stmt) == CALL_EXPR)
|| ((TREE_CODE (stmt) == MODIFY_EXPR)
! && (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR))
! || (TREE_CODE (stmt) == TRY_CATCH_EXPR)
! || (TREE_CODE (stmt) == TRY_FINALLY_EXPR)
! || (TREE_CODE (stmt) == EH_FILTER_EXPR)
! || (TREE_CODE (stmt) == CATCH_EXPR))
return true;
/* GOTO_EXPR nodes to nonlocal labels need to be kept (This fixes
--- 232,253 ----
size_t i;
/* Instructions that are implicitly live. Function calls, asm and return
! statements are required. Labels are kept because they are control flow,
! and we have no way of knowing whether they can be removed. DCE can
! eliminate all the other statements in a block, and CFG can then remove the
! labels. */
! if (
! /* The first three should be removed if unnecessary condition replacing
! is readded. */
! (TREE_CODE (stmt) == COND_EXPR)
! || (TREE_CODE (stmt) == SWITCH_EXPR)
! || (TREE_CODE (stmt) == GOTO_EXPR)
! || (TREE_CODE (stmt) == ASM_EXPR)
|| (TREE_CODE (stmt) == RETURN_EXPR)
|| (TREE_CODE (stmt) == LABEL_EXPR)
|| (TREE_CODE (stmt) == CALL_EXPR)
|| ((TREE_CODE (stmt) == MODIFY_EXPR)
! && (TREE_CODE (TREE_OPERAND (stmt, 1)) == CALL_EXPR)))
return true;
/* GOTO_EXPR nodes to nonlocal labels need to be kept (This fixes
*************** stmt_useful_p (tree stmt)
*** 253,259 ****
if (bb)
for (e = bb->succ; e; e = e->succ_next)
! if (e->dest == EXIT_BLOCK_PTR && e->flags & EDGE_ABNORMAL)
return true;
}
--- 261,267 ----
if (bb)
for (e = bb->succ; e; e = e->succ_next)
! if (e->dest == EXIT_BLOCK_PTR && (e->flags & EDGE_ABNORMAL))
return true;
}
*************** stmt_useful_p (tree stmt)
*** 285,299 ****
static void
process_worklist (void)
{
#if 0
- /* Tries to access parent_block. Disabled until fixed. */
basic_block bb;
! tree i, j;
edge e;
bitmap cond_checked, goto_checked;
cond_checked = BITMAP_XMALLOC ();
goto_checked = BITMAP_XMALLOC ();
while (VARRAY_ACTIVE_SIZE (worklist) > 0)
{
--- 293,308 ----
static void
process_worklist (void)
{
+ tree i;
#if 0
basic_block bb;
! tree j;
edge e;
bitmap cond_checked, goto_checked;
cond_checked = BITMAP_XMALLOC ();
goto_checked = BITMAP_XMALLOC ();
+ #endif
while (VARRAY_ACTIVE_SIZE (worklist) > 0)
{
*************** process_worklist (void)
*** 308,313 ****
--- 317,323 ----
fprintf (dump_file, "\n");
}
+ #if 0
/* Find any predecessor which 'goto's this block, and mark the goto
as necessary since it is control flow. A block's predecessors only
need to be checked once. */
*************** process_worklist (void)
*** 326,331 ****
--- 336,342 ----
mark_necessary (j);
}
}
+ #endif
if (TREE_CODE (i) == PHI_NODE)
{
*************** process_worklist (void)
*** 340,345 ****
--- 351,357 ----
mark_tree_necessary (SSA_NAME_DEF_STMT (PHI_ARG_DEF (i, k)));
}
+ #if 0
/* Look at all the predecessors, and if this PHI is being fed
from a conditional expression, mark that conditional
as necessary. Copies may be needed on an edge later.
*************** process_worklist (void)
*** 369,374 ****
--- 381,387 ----
}
}
}
+ #endif
}
else
{
*************** process_worklist (void)
*** 405,410 ****
--- 418,424 ----
}
}
}
+ #if 0
BITMAP_XFREE (cond_checked);
BITMAP_XFREE (goto_checked);
#endif
*************** remove_dead_stmts (void)
*** 421,436 ****
tree t;
block_stmt_iterator i;
dom_info = NULL;
pdom_info = NULL;
! FOR_EACH_BB_REVERSE (bb)
{
/* Remove dead PHI nodes. */
remove_dead_phis (bb);
/* Remove dead statements. */
! for (i = bsi_last (bb); !bsi_end_p (i); bsi_prev (&i))
{
t = bsi_stmt (i);
stats.total++;
--- 435,452 ----
tree t;
block_stmt_iterator i;
+ #if 0
dom_info = NULL;
pdom_info = NULL;
+ #endif
! FOR_EACH_BB (bb)
{
/* Remove dead PHI nodes. */
remove_dead_phis (bb);
/* Remove dead statements. */
! for (i = bsi_start (bb); !bsi_end_p (i); )
{
t = bsi_stmt (i);
stats.total++;
*************** remove_dead_stmts (void)
*** 438,452 ****
--- 454,472 ----
/* If `i' is not in `necessary' then remove from B. */
if (!necessary_p (t))
remove_dead_stmt (&i, bb);
+ else
+ bsi_next (&i);
}
}
+ #if 0
/* If we needed the dominance info, free it now. */
if (dom_info != NULL)
free_dominance_info (dom_info);
if (pdom_info != NULL)
free_dominance_info (pdom_info);
+ #endif
}
*************** remove_dead_phis (basic_block bb)
*** 490,500 ****
/* Remove dead statement pointed by iterator I from block BB. */
static void
! remove_dead_stmt (block_stmt_iterator *i ATTRIBUTE_UNUSED,
! basic_block bb ATTRIBUTE_UNUSED)
{
- #if 0
- /* Tries to access parent. Disabled until fixed. */
tree t;
t = bsi_stmt (*i);
--- 510,517 ----
/* Remove dead statement pointed by iterator I from block BB. */
static void
! remove_dead_stmt (block_stmt_iterator *i, basic_block bb ATTRIBUTE_UNUSED)
{
tree t;
t = bsi_stmt (*i);
*************** remove_dead_stmt (block_stmt_iterator *i
*** 508,534 ****
stats.removed++;
/* If we have determined that a conditional branch statement contributes
nothing to the program, then we not only remove it, but change the
flowgraph so that the block points directly to the immediate
post-dominator. The flow graph will remove the blocks we are
circumventing, and this block will then simply fall-thru to the
post-dominator. This prevents us from having to add any branch
! instuctions to replace the conditional statement.
!
! Only remove a conditional if its parent statement is live. This avoids
! unnecessary calls to remove_conditional in the event of dead nested
! conditionals. */
if (TREE_CODE (t) == COND_EXPR || TREE_CODE (t) == SWITCH_EXPR)
! {
! tree parent = parent_stmt (t);
! if (parent == NULL_TREE || necessary_p (parent))
! remove_conditional (bb);
! }
bsi_remove (i);
- #endif
}
/* Main routine to eliminate dead code. */
--- 525,544 ----
stats.removed++;
+ #if 0
/* If we have determined that a conditional branch statement contributes
nothing to the program, then we not only remove it, but change the
flowgraph so that the block points directly to the immediate
post-dominator. The flow graph will remove the blocks we are
circumventing, and this block will then simply fall-thru to the
post-dominator. This prevents us from having to add any branch
! instuctions to replace the conditional statement. */
if (TREE_CODE (t) == COND_EXPR || TREE_CODE (t) == SWITCH_EXPR)
! remove_conditional (bb);
! #endif
bsi_remove (i);
}
/* Main routine to eliminate dead code. */
*************** tree_ssa_dce (tree fndecl)
*** 538,546 ****
{
tree fnbody;
- fprintf (stderr, "tree_ssa_dce broken now.\n");
- abort ();
-
timevar_push (TV_TREE_DCE);
memset ((void *) &stats, 0, sizeof (stats));
--- 548,553 ----
*************** tree_ssa_dce (tree fndecl)
*** 567,573 ****
fprintf (dump_file, "\nEliminating unnecessary instructions:\n");
remove_dead_stmts ();
! cleanup_tree_cfg (false);
/* Debugging dumps. */
if (dump_file)
--- 574,580 ----
fprintf (dump_file, "\nEliminating unnecessary instructions:\n");
remove_dead_stmts ();
! cleanup_tree_cfg (true);
/* Debugging dumps. */
if (dump_file)
*************** tree_ssa_dce (tree fndecl)
*** 583,588 ****
--- 590,596 ----
}
+ #if 0
/* Remove the conditional statement starting at block BB. */
static void
*************** remove_conditional (basic_block bb)
*** 604,621 ****
for (e = bb->succ; e; )
{
edge tmp = e->succ_next;
! /* If the edge BB->PDO_BB exists already, don't remove it. */
! if (e->dest != pdom_bb)
! ssa_remove_edge (e);
e = tmp;
}
- /* If we haven't removed all the edges, there is no need to update the
- PHI nodes at PDOM_BB because all the superfluous arguments have been
- removed by ssa_remove_edge and we don't need any new arguments. */
- if (bb->succ)
- return;
-
/* If there is no post dominator, then this block is going to the
exit node. */
if (pdom_bb == NULL)
--- 612,621 ----
for (e = bb->succ; e; )
{
edge tmp = e->succ_next;
! ssa_remove_edge (e);
e = tmp;
}
/* If there is no post dominator, then this block is going to the
exit node. */
if (pdom_bb == NULL)
*************** remove_conditional (basic_block bb)
*** 636,640 ****
#endif
/* Add an edge to BB's post dominator. */
! make_edge (bb, pdom_bb, EDGE_FALLTHRU);
}
--- 636,641 ----
#endif
/* Add an edge to BB's post dominator. */
! make_edge (bb, pdom_bb, EDGE_FALLTHRU);
}
+ #endif
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.21.2.1
diff -c -3 -p -r1.1.2.21.2.1 tree-ssa-dom.c
*** tree-ssa-dom.c 14 Aug 2003 19:11:58 -0000 1.1.2.21.2.1
--- tree-ssa-dom.c 16 Aug 2003 20:52:36 -0000
*************** optimize_stmt (block_stmt_iterator si, v
*** 657,671 ****
opt_stats.num_re++;
if (TREE_CODE (cached_lhs) == SSA_NAME)
! {
! *expr_p = cached_lhs;
! /* This takes care of moving the variable to the right scope.
! The assignment above is here so that it indeed looks like
! copy propagation. */
! propagate_copy (bb_for_stmt (stmt), expr_p, cached_lhs);
! }
! else
! *expr_p = cached_lhs;
ann->modified = 1;
}
}
--- 657,664 ----
opt_stats.num_re++;
if (TREE_CODE (cached_lhs) == SSA_NAME)
! fixup_var_scope (bb_for_stmt (stmt), cached_lhs);
! *expr_p = cached_lhs;
ann->modified = 1;
}
}
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa.c,v
retrieving revision 1.1.4.115.2.1
diff -c -3 -p -r1.1.4.115.2.1 tree-ssa.c
*** tree-ssa.c 14 Aug 2003 19:11:58 -0000 1.1.4.115.2.1
--- tree-ssa.c 16 Aug 2003 20:52:38 -0000
*************** rewrite_out_of_ssa (tree fndecl ATTRIBUT
*** 1731,1736 ****
--- 1731,1737 ----
bsi_commit_edge_inserts (0, NULL);
cleanup_tree_cfg (true);
+ remove_useless_stmts_and_vars ();
if (dump_file && (dump_flags & TDF_DETAILS))
dump_tree_cfg (dump_file, dump_flags & ~TDF_DETAILS);
Index: tree.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.c,v
retrieving revision 1.263.2.44
diff -c -3 -p -r1.263.2.44 tree.c
*** tree.c 5 Aug 2003 15:17:58 -0000 1.263.2.44
--- tree.c 16 Aug 2003 20:52:43 -0000
*************** resize_phi_node (tree *phi, int len)
*** 5030,5035 ****
--- 5030,5036 ----
{
int size;
tree new_phi;
+ int i, old_len;
#ifdef ENABLE_CHECKING
if (len < PHI_ARG_CAPACITY (*phi))
*************** resize_phi_node (tree *phi, int len)
*** 5038,5044 ****
--- 5039,5052 ----
size = sizeof (struct tree_phi_node) + (len - 1) * sizeof (struct phi_arg_d);
new_phi = ggc_realloc (*phi, size);
+ old_len = PHI_ARG_CAPACITY (new_phi);
PHI_ARG_CAPACITY (new_phi) = len;
+
+ for (i = old_len; i < len; i++)
+ {
+ PHI_ARG_DEF (new_phi, i) = NULL_TREE;
+ PHI_ARG_EDGE (new_phi, i) = NULL;
+ }
*phi = new_phi;
}