This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
[RFC] an update on O(1) PHI argument look up
- From: Kazu Hirata <kazu at cs dot umass dot edu>
- To: gcc at gcc dot gnu dot org
- Cc: dnovillo at redhat dot com
- Date: Sun, 07 Nov 2004 20:01:38 -0500 (EST)
- Subject: [RFC] an update on O(1) PHI argument look up
Hi,
I fixed one bug that causes resize_phi_node to be called too often.
With this bug fixed, the mainline GCC with my patch is on par with the
unpatched GCC with occasional exceptional improvements
original patched
c-parse.i 12.77 11.51
insn-attrtab.i 438.02 420.35 (in seconds)
I tried to speed up places that can be obviously sped up, but there
could be other places that can be improved. I am hoping people can
join in addressing those issues after the patch is approved.
One thing that's blocking my patch is direct write access to
PHI_ARG_EDGE in tree-vectorizer.c. Fortunately, Dorit has got a patch
to remove this.
Meanwhile, may I start submitting helper patches? We can do several
things independently. Just in the order of what comes to my mind...
1. Add dest_idx to edge_def. This dest_idx holds an index of the edge
e within e->dest->preds. In other words, we always have "EDGE_PRED
(e->dest, e->dest_idx) == e".
2. Stop split_edge writing to PHI_ARG_EDGE.
3. Add new CFG hooks that are called upon adding and removing an edge.
Last but not least, I would like to thank everybody who helped me
develop this patch.
Any comments?
Kazu Hirata
Index: basic-block.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/basic-block.h,v
retrieving revision 1.223
diff -u -d -p -r1.223 basic-block.h
--- basic-block.h 29 Oct 2004 08:40:51 -0000 1.223
+++ basic-block.h 7 Nov 2004 20:44:04 -0000
@@ -148,6 +148,9 @@ struct edge_def GTY(())
int probability; /* biased by REG_BR_PROB_BASE */
gcov_type count; /* Expected number of executions calculated
in profile.c */
+
+ /* The index within edge vector dest->preds. */
+ unsigned int dest_idx;
};
typedef struct edge_def *edge;
@@ -634,7 +637,7 @@ ei_safe_edge (edge_iterator i)
FOR (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
IF (e != taken_edge)
- ssa_remove_edge (e);
+ remove_edge (e);
ELSE
ei_next (&ei);
}
Index: cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfg.c,v
retrieving revision 1.72
diff -u -d -p -r1.72 cfg.c
--- cfg.c 25 Oct 2004 21:48:25 -0000 1.72
+++ cfg.c 7 Nov 2004 20:44:05 -0000
@@ -276,6 +276,9 @@ unchecked_make_edge (basic_block src, ba
e->src = src;
e->dest = dst;
e->flags = flags;
+ e->dest_idx = EDGE_COUNT (dst->preds) - 1;
+
+ execute_on_new_edge (e);
return e;
}
@@ -355,11 +358,15 @@ remove_edge (edge e)
{
edge tmp;
basic_block src, dest;
+ unsigned int dest_idx;
bool found = false;
edge_iterator ei;
+ execute_on_removing_edge (e);
+
src = e->src;
dest = e->dest;
+ dest_idx = e->dest_idx;
for (ei = ei_start (src->succs); (tmp = ei_safe_edge (ei)); )
{
@@ -375,20 +382,9 @@ remove_edge (edge e)
gcc_assert (found);
- found = false;
- for (ei = ei_start (dest->preds); (tmp = ei_safe_edge (ei)); )
- {
- if (tmp == e)
- {
- VEC_unordered_remove (edge, dest->preds, ei.index);
- found = true;
- break;
- }
- else
- ei_next (&ei);
- }
-
- gcc_assert (found);
+ VEC_unordered_remove (edge, dest->preds, dest_idx);
+ if (dest_idx < EDGE_COUNT (dest->preds))
+ EDGE_I (dest->preds, dest_idx)->dest_idx = dest_idx;
free_edge (e);
}
@@ -398,28 +394,20 @@ remove_edge (edge e)
void
redirect_edge_succ (edge e, basic_block new_succ)
{
- edge tmp;
- edge_iterator ei;
- bool found = false;
+ basic_block dest = e->dest;
+ unsigned int dest_idx = e->dest_idx;
- /* Disconnect the edge from the old successor block. */
- for (ei = ei_start (e->dest->preds); (tmp = ei_safe_edge (ei)); )
- {
- if (tmp == e)
- {
- VEC_unordered_remove (edge, e->dest->preds, ei.index);
- found = true;
- break;
- }
- else
- ei_next (&ei);
- }
+ execute_on_removing_edge (e);
- gcc_assert (found);
+ VEC_unordered_remove (edge, dest->preds, dest_idx);
+ if (dest_idx < EDGE_COUNT (dest->preds))
+ EDGE_I (dest->preds, dest_idx)->dest_idx = dest_idx;
/* Reconnect the edge to the new successor block. */
VEC_safe_push (edge, new_succ->preds, e);
e->dest = new_succ;
+ e->dest_idx = EDGE_COUNT (new_succ->preds) - 1;
+ execute_on_new_edge (e);
}
/* Like previous but avoid possible duplicate edge. */
@@ -460,6 +448,8 @@ redirect_edge_pred (edge e, basic_block
edge_iterator ei;
bool found = false;
+ execute_on_removing_edge (e);
+
/* Disconnect the edge from the old predecessor block. */
for (ei = ei_start (e->src->succs); (tmp = ei_safe_edge (ei)); )
{
@@ -478,6 +468,7 @@ redirect_edge_pred (edge e, basic_block
/* Reconnect the edge to the new predecessor block. */
VEC_safe_push (edge, new_pred->succs, e);
e->src = new_pred;
+ execute_on_new_edge (e);
}
/* Clear all basic block flags, with the exception of partitioning. */
Index: cfghooks.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfghooks.c,v
retrieving revision 1.18
diff -u -d -p -r1.18 cfghooks.c
--- cfghooks.c 4 Nov 2004 22:02:55 -0000 1.18
+++ cfghooks.c 7 Nov 2004 20:44:05 -0000
@@ -791,3 +791,22 @@ flow_call_edges_add (sbitmap blocks)
return (cfg_hooks->flow_call_edges_add) (blocks);
}
+
+/* This function is called whenever a new edge is created or
+ redirected. */
+
+void
+execute_on_new_edge (edge e)
+{
+ if (cfg_hooks->execute_on_new_edge)
+ cfg_hooks->execute_on_new_edge (e);
+}
+
+/* This function is called whenever an edge is being removed. */
+
+void
+execute_on_removing_edge (edge e)
+{
+ if (cfg_hooks->execute_on_removing_edge)
+ cfg_hooks->execute_on_removing_edge (e);
+}
Index: cfghooks.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfghooks.h,v
retrieving revision 1.11
diff -u -d -p -r1.11 cfghooks.h
--- cfghooks.h 13 May 2004 06:39:32 -0000 1.11
+++ cfghooks.h 7 Nov 2004 20:44:05 -0000
@@ -100,6 +100,13 @@ struct cfg_hooks
The goal is to expose cases in which entering a basic block does not imply
that all subsequent instructions must be executed. */
int (*flow_call_edges_add) (sbitmap);
+
+ /* This function is called whenever a new edge is created or
+ redirected. */
+ void (*execute_on_new_edge) (edge);
+
+ /* This function is called whenever an edge is being removed. */
+ void (*execute_on_removing_edge) (edge);
};
extern void verify_flow_info (void);
@@ -126,6 +133,8 @@ extern basic_block duplicate_block (basi
extern bool block_ends_with_call_p (basic_block bb);
extern bool block_ends_with_condjump_p (basic_block bb);
extern int flow_call_edges_add (sbitmap);
+extern void execute_on_new_edge (edge);
+extern void execute_on_removing_edge (edge);
/* Hooks containers. */
extern struct cfg_hooks tree_cfg_hooks;
Index: cfgrtl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgrtl.c,v
retrieving revision 1.144
diff -u -d -p -r1.144 cfgrtl.c
--- cfgrtl.c 4 Nov 2004 23:20:22 -0000 1.144
+++ cfgrtl.c 7 Nov 2004 20:44:06 -0000
@@ -3074,7 +3074,9 @@ struct cfg_hooks rtl_cfg_hooks = {
rtl_tidy_fallthru_edge,
rtl_block_ends_with_call_p,
rtl_block_ends_with_condjump_p,
- rtl_flow_call_edges_add
+ rtl_flow_call_edges_add,
+ NULL, /* execute_on_new_edge */
+ NULL /* execute_on_removing_edge */
};
/* Implementation of CFG manipulation for cfg layout RTL, where
@@ -3110,6 +3112,8 @@ struct cfg_hooks cfg_layout_rtl_cfg_hook
NULL,
rtl_block_ends_with_call_p,
rtl_block_ends_with_condjump_p,
- rtl_flow_call_edges_add
+ rtl_flow_call_edges_add,
+ NULL, /* execute_on_new_edge */
+ NULL /* execute_on_removing_edge */
};
Index: lambda-code.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/lambda-code.c,v
retrieving revision 2.18
diff -u -d -p -r2.18 lambda-code.c
--- lambda-code.c 3 Nov 2004 17:32:34 -0000 2.18
+++ lambda-code.c 7 Nov 2004 20:44:10 -0000
@@ -1366,8 +1366,8 @@ gcc_loop_to_lambda_loop (struct loop *lo
/* Another induction variable check. One argument's source should be
in the loop, one outside the loop. */
- if (flow_bb_inside_loop_p (loop, PHI_ARG_EDGE (phi, 0)->src)
- && flow_bb_inside_loop_p (loop, PHI_ARG_EDGE (phi, 1)->src))
+ if (flow_bb_inside_loop_p (loop, EDGE_PRED (bb_for_stmt (phi), 0)->src)
+ && flow_bb_inside_loop_p (loop, EDGE_PRED (bb_for_stmt (phi), 1)->src))
{
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1377,7 +1377,7 @@ gcc_loop_to_lambda_loop (struct loop *lo
return NULL;
}
- if (flow_bb_inside_loop_p (loop, PHI_ARG_EDGE (phi, 0)->src))
+ if (flow_bb_inside_loop_p (loop, EDGE_PRED (bb_for_stmt (phi), 0)->src))
{
lboundvar = PHI_ARG_DEF (phi, 1);
lbound = gcc_tree_to_linear_expression (depth, lboundvar,
@@ -2030,9 +2030,11 @@ not_interesting_stmt (tree stmt)
static bool
phi_loop_edge_uses_def (struct loop *loop, tree phi, tree def)
{
+ basic_block bb = bb_for_stmt (phi);
int i;
+
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
- if (flow_bb_inside_loop_p (loop, PHI_ARG_EDGE (phi, i)->src))
+ if (flow_bb_inside_loop_p (loop, EDGE_PRED (bb, i)->src))
if (PHI_ARG_DEF (phi, i) == def)
return true;
return false;
Index: predict.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/predict.c,v
retrieving revision 1.132
diff -u -d -p -r1.132 predict.c
--- predict.c 4 Nov 2004 10:10:27 -0000 1.132
+++ predict.c 7 Nov 2004 20:44:12 -0000
@@ -1226,13 +1226,17 @@ apply_return_prediction (int *heads)
if (pred != return_prediction (PHI_ARG_DEF (phi, i), &direction))
break;
if (i != phi_num_args)
- for (i = 0; i < phi_num_args; i++)
- {
- pred = return_prediction (PHI_ARG_DEF (phi, i), &direction);
- if (pred != PRED_NO_PREDICTION)
- predict_paths_leading_to (PHI_ARG_EDGE (phi, i)->src, heads, pred,
- direction);
- }
+ {
+ basic_block bb = bb_for_stmt (phi);
+
+ for (i = 0; i < phi_num_args; i++)
+ {
+ pred = return_prediction (PHI_ARG_DEF (phi, i), &direction);
+ if (pred != PRED_NO_PREDICTION)
+ predict_paths_leading_to (EDGE_PRED (bb, i)->src, heads, pred,
+ direction);
+ }
+ }
}
/* Look for basic block that contains unlikely to happen events
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-cfg.c,v
retrieving revision 2.101
diff -u -d -p -r2.101 tree-cfg.c
--- tree-cfg.c 6 Nov 2004 15:57:25 -0000 2.101
+++ tree-cfg.c 7 Nov 2004 20:44:16 -0000
@@ -1782,7 +1782,7 @@ remove_phi_nodes_and_edges_for_unreachab
/* Remove edges to BB's successors. */
while (EDGE_COUNT (bb->succs) > 0)
- ssa_remove_edge (EDGE_SUCC (bb, 0));
+ remove_edge (EDGE_SUCC (bb, 0));
}
@@ -1919,7 +1919,7 @@ cleanup_control_expr_graph (basic_block
{
taken_edge->probability += e->probability;
taken_edge->count += e->count;
- ssa_remove_edge (e);
+ remove_edge (e);
retval = true;
}
else
@@ -2075,16 +2075,11 @@ static bool
phi_alternatives_equal (basic_block dest, edge e1, edge e2)
{
tree phi, val1, val2;
- int n1, n2;
+ int n1 = e1->dest_idx;
+ int n2 = e2->dest_idx;
for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
{
- n1 = phi_arg_from_edge (phi, e1);
- n2 = phi_arg_from_edge (phi, e2);
-
- gcc_assert (n1 >= 0);
- gcc_assert (n2 >= 0);
-
val1 = PHI_ARG_DEF (phi, n1);
val2 = PHI_ARG_DEF (phi, n2);
@@ -2932,6 +2927,29 @@ bsi_insert_on_edge_immediate (edge e, tr
Tree specific functions for CFG manipulation
---------------------------------------------------------------------------*/
+static void
+reinstall_phi_args (edge new_edge, edge old_edge)
+{
+ tree var, phi;
+
+ if (!PENDING_STMT (old_edge))
+ return;
+
+ for (var = PENDING_STMT (old_edge), phi = phi_nodes (new_edge->dest);
+ var && phi;
+ var = TREE_CHAIN (var), phi = PHI_CHAIN (phi))
+ {
+ tree result = TREE_PURPOSE (var);
+ tree arg = TREE_VALUE (var);
+
+ gcc_assert (result == PHI_RESULT (phi));
+
+ add_phi_arg (&phi, arg, new_edge);
+ }
+
+ PENDING_STMT (old_edge) = NULL;
+}
+
/* Split a (typically critical) edge EDGE_IN. Return the new block.
Abort on abnormal edges. */
@@ -2940,8 +2958,6 @@ tree_split_edge (edge edge_in)
{
basic_block new_bb, after_bb, dest, src;
edge new_edge, e;
- tree phi;
- int i, num_elem;
edge_iterator ei;
/* Abnormal edges cannot be split. */
@@ -2968,23 +2984,9 @@ tree_split_edge (edge edge_in)
new_edge->probability = REG_BR_PROB_BASE;
new_edge->count = edge_in->count;
- /* Find all the PHI arguments on the original edge, and change them to
- the new edge. Do it before redirection, so that the argument does not
- get removed. */
- for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
- {
- num_elem = PHI_NUM_ARGS (phi);
- for (i = 0; i < num_elem; i++)
- if (PHI_ARG_EDGE (phi, i) == edge_in)
- {
- PHI_ARG_EDGE (phi, i) = new_edge;
- break;
- }
- }
-
e = redirect_edge_and_branch (edge_in, new_bb);
gcc_assert (e);
- gcc_assert (!PENDING_STMT (edge_in));
+ reinstall_phi_args (new_edge, e);
return new_bb;
}
@@ -3402,6 +3404,16 @@ tree_verify_flow_info (void)
{
bool found_ctrl_stmt = false;
+ FOR_EACH_EDGE (e, ei, bb->preds)
+ {
+ if (ei.index != e->dest_idx)
+ {
+ error ("dest_idx at bb %d is not consistent",
+ bb->index);
+ err = 1;
+ }
+ }
+
/* Skip labels on the start of basic block. */
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
@@ -3769,7 +3781,6 @@ thread_jumps_from_bb (basic_block bb)
edge last, old;
basic_block dest, tmp, curr, old_dest;
tree phi;
- int arg;
/* If the edge is abnormal or its destination is not
forwardable, then there's nothing to do. */
@@ -3856,12 +3867,10 @@ thread_jumps_from_bb (basic_block bb)
have the same value as the argument associated with LAST.
Otherwise we would have changed our target block
above. */
+ int arg = last->dest_idx;
+
for (phi = phi_nodes (dest); phi; phi = PHI_CHAIN (phi))
- {
- arg = phi_arg_from_edge (phi, last);
- gcc_assert (arg >= 0);
- add_phi_arg (&phi, PHI_ARG_DEF (phi, arg), e);
- }
+ add_phi_arg (&phi, PHI_ARG_DEF (phi, arg), e);
}
/* Remove the unreachable blocks (observe that if all blocks
@@ -5088,7 +5097,7 @@ tree_purge_dead_eh_edges (basic_block bb
{
if (e->flags & EDGE_EH)
{
- ssa_remove_edge (e);
+ remove_edge (e);
changed = true;
}
else
@@ -5133,6 +5142,27 @@ tree_purge_all_dead_eh_edges (bitmap blo
return changed;
}
+/* This function is called whenever a new edge is created or
+ redirected. */
+
+static void
+tree_execute_on_new_edge (edge e)
+{
+ basic_block bb = e->dest;
+
+ if (phi_nodes (bb))
+ reserve_phi_args_for_new_edge (bb);
+}
+
+/* This function is called whenever an edge is being removed. */
+
+static void
+tree_execute_on_removing_edge (edge e)
+{
+ if (phi_nodes (e->dest))
+ remove_phi_args (e);
+}
+
struct cfg_hooks tree_cfg_hooks = {
"tree",
tree_verify_flow_info,
@@ -5154,7 +5184,9 @@ struct cfg_hooks tree_cfg_hooks = {
NULL, /* tidy_fallthru_edge */
tree_block_ends_with_call_p, /* block_ends_with_call_p */
tree_block_ends_with_condjump_p, /* block_ends_with_condjump_p */
- tree_flow_call_edges_add /* flow_call_edges_add */
+ tree_flow_call_edges_add, /* flow_call_edges_add */
+ tree_execute_on_new_edge, /* execute_on_new_edge */
+ tree_execute_on_removing_edge, /* execute_on_removing_edge */
};
Index: tree-flow-inline.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow-inline.h,v
retrieving revision 2.25
diff -u -d -p -r2.25 tree-flow-inline.h
--- tree-flow-inline.h 27 Oct 2004 17:45:19 -0000 2.25
+++ tree-flow-inline.h 7 Nov 2004 20:44:16 -0000
@@ -391,17 +391,14 @@ set_phi_nodes (basic_block bb, tree l)
/* Return the phi index number for an edge. */
static inline int
-phi_arg_from_edge (tree phi, edge e)
+phi_arg_from_edge (tree phi ATTRIBUTE_UNUSED, edge e)
{
- int i;
+#if 0
gcc_assert (phi);
gcc_assert (TREE_CODE (phi) == PHI_NODE);
-
- for (i = 0; i < PHI_NUM_ARGS (phi); i++)
- if (PHI_ARG_EDGE (phi, i) == e)
- return i;
-
- return -1;
+ gcc_assert (EDGE_PRED (bb_for_stmt (phi), e->dest_idx) == e);
+#endif
+ return e->dest_idx;
}
/* Mark VAR as used, so that it'll be preserved during rtl expansion. */
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-flow.h,v
retrieving revision 2.58
diff -u -d -p -r2.58 tree-flow.h
--- tree-flow.h 2 Nov 2004 00:23:04 -0000 2.58
+++ tree-flow.h 7 Nov 2004 20:44:16 -0000
@@ -510,10 +510,10 @@ extern void dump_generic_bb (FILE *, bas
extern var_ann_t create_var_ann (tree);
extern stmt_ann_t create_stmt_ann (tree);
extern tree_ann_t create_tree_ann (tree);
+extern void reserve_phi_args_for_new_edge (basic_block);
extern tree create_phi_node (tree, basic_block);
extern void add_phi_arg (tree *, tree, edge);
-extern void remove_phi_arg (tree, basic_block);
-extern void remove_phi_arg_num (tree, int);
+extern void remove_phi_args (edge);
extern void remove_phi_node (tree, tree, basic_block);
extern void remove_all_phi_nodes_for (bitmap);
extern void dump_dfa_stats (FILE *);
@@ -572,7 +572,6 @@ extern void debug_tree_ssa (void);
extern void debug_def_blocks (void);
extern void dump_tree_ssa_stats (FILE *);
extern void debug_tree_ssa_stats (void);
-extern void ssa_remove_edge (edge);
extern edge ssa_redirect_edge (edge, basic_block);
extern void flush_pending_stmts (edge e);
extern bool tree_ssa_useless_type_conversion (tree);
Index: tree-if-conv.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-if-conv.c,v
retrieving revision 2.11
diff -u -d -p -r2.11 tree-if-conv.c
--- tree-if-conv.c 14 Oct 2004 18:19:46 -0000 2.11
+++ tree-if-conv.c 7 Nov 2004 20:44:16 -0000
@@ -759,7 +759,7 @@ replace_phi_with_cond_modify_expr (tree
arg_1 = NULL_TREE;
/* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr. */
- if (PHI_ARG_EDGE(phi, 1)->src == true_bb)
+ if (EDGE_PRED (bb, 1)->src == true_bb)
{
arg_0 = PHI_ARG_DEF (phi, 1);
arg_1 = PHI_ARG_DEF (phi, 0);
@@ -893,9 +893,9 @@ combine_blocks (struct loop *loop)
/* It is time to remove this basic block. First remove edges. */
while (EDGE_COUNT (bb->succs) > 0)
- ssa_remove_edge (EDGE_SUCC (bb, 0));
+ remove_edge (EDGE_SUCC (bb, 0));
while (EDGE_COUNT (bb->preds) > 0)
- ssa_remove_edge (EDGE_PRED (bb, 0));
+ remove_edge (EDGE_PRED (bb, 0));
/* Remove labels and make stmts member of loop->header. */
for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
Index: tree-outof-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-outof-ssa.c,v
retrieving revision 2.30
diff -u -d -p -r2.30 tree-outof-ssa.c
--- tree-outof-ssa.c 4 Nov 2004 08:41:14 -0000 2.30
+++ tree-outof-ssa.c 7 Nov 2004 20:44:17 -0000
@@ -357,17 +357,7 @@ eliminate_build (elim_graph g, basic_blo
if (T0 == NULL_TREE)
continue;
- if (PHI_ARG_EDGE (phi, i) == g->e)
- Ti = PHI_ARG_DEF (phi, i);
- else
- {
- /* On rare occasions, a PHI node may not have the arguments
- in the same order as all of the other PHI nodes. If they don't
- match, find the appropriate index here. */
- pi = phi_arg_from_edge (phi, g->e);
- gcc_assert (pi != -1);
- Ti = PHI_ARG_DEF (phi, pi);
- }
+ Ti = PHI_ARG_DEF (phi, i);
/* If this argument is a constant, or a SSA_NAME which is being
left in SSA form, just queue a copy to be emitted on this
@@ -601,10 +591,7 @@ coalesce_abnormal_edges (var_map map, co
if (x == NO_PARTITION)
continue;
- y = phi_arg_from_edge (phi, e);
- gcc_assert (y != -1);
-
- tmp = PHI_ARG_DEF (phi, y);
+ tmp = PHI_ARG_DEF (phi, e->dest_idx);
#ifdef ENABLE_CHECKING
if (!phi_ssa_name_p (tmp))
{
@@ -1929,7 +1916,7 @@ rewrite_trees (var_map map, tree *values
{
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds)
- eliminate_phi (e, phi_arg_from_edge (phi, e), g);
+ eliminate_phi (e, e->dest_idx, g);
}
}
Index: tree-phinodes.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-phinodes.c,v
retrieving revision 2.20
diff -u -d -p -r2.20 tree-phinodes.c
--- tree-phinodes.c 6 Nov 2004 15:14:11 -0000 2.20
+++ tree-phinodes.c 7 Nov 2004 20:44:17 -0000
@@ -203,28 +203,35 @@ ideal_phi_node_len (int len)
definition). */
static tree
-make_phi_node (tree var, int len)
+make_phi_node (tree var, int len, int cap)
{
tree phi;
- len = ideal_phi_node_len (len);
-
- phi = allocate_phi_node (len);
+ phi = allocate_phi_node (cap);
/* We do not have to clear a part of the PHI node that stores PHI
arguments, which is safe because we tell the garbage collector to
scan up to num_args elements in the array of PHI arguments. In
other words, the garbage collector will not follow garbage
pointers in the unused portion of the array. */
- memset (phi, 0, sizeof (struct tree_phi_node) - sizeof (struct phi_arg_d));
+ memset (phi, 0, (sizeof (struct tree_phi_node)
+ - sizeof (struct phi_arg_d)
+#if 0
+ /* Enable this #if if you want this to be GC safe
+ even when some pass forgets to add PHI args. */
+ + len * sizeof (struct phi_arg_d)
+#endif
+ ));
TREE_SET_CODE (phi, PHI_NODE);
- PHI_ARG_CAPACITY (phi) = len;
+ PHI_ARG_CAPACITY (phi) = cap;
TREE_TYPE (phi) = TREE_TYPE (var);
if (TREE_CODE (var) == SSA_NAME)
SET_PHI_RESULT (phi, var);
else
SET_PHI_RESULT (phi, make_ssa_name (var, phi));
+ PHI_NUM_ARGS (phi) = len;
+
return phi;
}
@@ -252,7 +259,7 @@ resize_phi_node (tree *phi, int len)
int old_size;
tree new_phi;
- gcc_assert (len >= PHI_ARG_CAPACITY (*phi));
+ gcc_assert (len > PHI_ARG_CAPACITY (*phi));
/* The garbage collector will not look at the PHI node beyond the
first PHI_NUM_ARGS elements. Therefore, all we have to copy is a
@@ -269,14 +276,50 @@ resize_phi_node (tree *phi, int len)
*phi = new_phi;
}
+/* Reserve PHI arguments for a new edge to basic block BB. */
+
+void
+reserve_phi_args_for_new_edge (basic_block bb)
+{
+ tree *loc;
+ int len = EDGE_COUNT (bb->preds);
+ int resizep = len > PHI_ARG_CAPACITY (phi_nodes (bb));
+ int cap = resizep ? ideal_phi_node_len (EDGE_COUNT (bb->preds) + 4) : 0;
+
+ for (loc = &(bb_ann (bb)->phi_nodes);
+ *loc;
+ loc = &PHI_CHAIN (*loc))
+ {
+ if (resizep)
+ {
+ tree old_phi = *loc;
+
+ resize_phi_node (loc, cap);
+
+ /* The result of the phi is defined by this phi node. */
+ SSA_NAME_DEF_STMT (PHI_RESULT (*loc)) = *loc;
+
+ release_phi_node (old_phi);
+ }
+ PHI_NUM_ARGS (*loc)++;
+ gcc_assert ((unsigned int) PHI_NUM_ARGS (*loc)
+ == EDGE_COUNT (bb->preds));
+ }
+}
+
/* Create a new PHI node for variable VAR at basic block BB. */
tree
create_phi_node (tree var, basic_block bb)
{
tree phi;
+ int len = EDGE_COUNT (bb->preds);
+ /* If BB already has a PHI node, match its capacity. */
+ int cap = (phi_nodes (bb)
+ ? PHI_ARG_CAPACITY (phi_nodes (bb))
+ : ideal_phi_node_len (len));
- phi = make_phi_node (var, EDGE_COUNT (bb->preds));
+ phi = make_phi_node (var, EDGE_COUNT (bb->preds), cap);
/* Add the new PHI node to the list of PHI nodes for block BB. */
PHI_CHAIN (phi) = phi_nodes (bb);
@@ -298,42 +341,16 @@ void
add_phi_arg (tree *phi, tree def, edge e)
{
basic_block bb = e->dest;
- int i = PHI_NUM_ARGS (*phi);
gcc_assert (bb == bb_for_stmt (*phi));
- if (i >= PHI_ARG_CAPACITY (*phi))
- {
- tree old_phi = *phi;
-
- /* Resize the phi. Unfortunately, this will relocate it. */
- resize_phi_node (phi, ideal_phi_node_len (i + 4));
-
- /* resize_phi_node will necessarily relocate the phi. */
- gcc_assert (*phi != old_phi);
-
- /* The result of the phi is defined by this phi node. */
- SSA_NAME_DEF_STMT (PHI_RESULT (*phi)) = *phi;
-
- release_phi_node (old_phi);
-
- /* Update the list head if replacing the first listed phi. */
- if (phi_nodes (bb) == old_phi)
- bb_ann (bb)->phi_nodes = *phi;
- else
- {
- /* Traverse the list looking for the phi node to chain to. */
- tree p;
-
- for (p = phi_nodes (bb);
- p && PHI_CHAIN (p) != old_phi;
- p = PHI_CHAIN (p))
- ;
+ /* We resize PHI nodes upon edge creation. We should always have
+ enough room at this point. */
+ gcc_assert (PHI_NUM_ARGS (*phi) <= PHI_ARG_CAPACITY (*phi));
- gcc_assert (p);
- PHI_CHAIN (p) = *phi;
- }
- }
+ /* We resize PHI nodes upon edge creation. We should always have
+ enough room at this point. */
+ gcc_assert (e->dest_idx < (unsigned int) PHI_NUM_ARGS (*phi));
/* Copy propagation needs to know what object occur in abnormal
PHI nodes. This is a convenient place to record such information. */
@@ -343,32 +360,8 @@ add_phi_arg (tree *phi, tree def, edge e
SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (*phi)) = 1;
}
- SET_PHI_ARG_DEF (*phi, i, def);
- PHI_ARG_EDGE (*phi, i) = e;
- PHI_ARG_NONZERO (*phi, i) = false;
- PHI_NUM_ARGS (*phi)++;
-}
-
-/* Remove a PHI argument from PHI. BLOCK is the predecessor block where
- the PHI argument is coming from. */
-
-void
-remove_phi_arg (tree phi, basic_block block)
-{
- int i, num_elem = PHI_NUM_ARGS (phi);
-
- for (i = 0; i < num_elem; i++)
- {
- basic_block src_bb;
-
- src_bb = PHI_ARG_EDGE (phi, i)->src;
-
- if (src_bb == block)
- {
- remove_phi_arg_num (phi, i);
- return;
- }
- }
+ SET_PHI_ARG_DEF (*phi, e->dest_idx, def);
+ PHI_ARG_NONZERO (*phi, e->dest_idx) = false;
}
@@ -377,7 +370,7 @@ remove_phi_arg (tree phi, basic_block bl
removal by swapping the last alternative with the alternative we want to
delete, then shrinking the vector. */
-void
+static void
remove_phi_arg_num (tree phi, int i)
{
int num_elem = PHI_NUM_ARGS (phi);
@@ -389,17 +382,27 @@ remove_phi_arg_num (tree phi, int i)
if (i != num_elem - 1)
{
SET_PHI_ARG_DEF (phi, i, PHI_ARG_DEF (phi, num_elem - 1));
- PHI_ARG_EDGE (phi, i) = PHI_ARG_EDGE (phi, num_elem - 1);
PHI_ARG_NONZERO (phi, i) = PHI_ARG_NONZERO (phi, num_elem - 1);
}
/* Shrink the vector and return. Note that we do not have to clear
- PHI_ARG_DEF, PHI_ARG_EDGE, or PHI_ARG_NONZERO because the garbage
- collector will not look at those elements beyond the first
- PHI_NUM_ARGS elements of the array. */
+ PHI_ARG_DEF or PHI_ARG_NONZERO because the garbage collector will
+ not look at those elements beyond the first PHI_NUM_ARGS elements
+ of the array. */
PHI_NUM_ARGS (phi)--;
}
+/* Remove all PHI arguments for E. */
+
+void
+remove_phi_args (edge e)
+{
+ tree phi;
+
+ for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
+ remove_phi_arg_num (phi, e->dest_idx);
+}
+
/* Remove PHI node PHI from basic block BB. If PREV is non-NULL, it is
used as the node immediately before PHI in the linked list. */
Index: tree-pretty-print.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-pretty-print.c,v
retrieving revision 2.47
diff -u -d -p -r2.47 tree-pretty-print.c
--- tree-pretty-print.c 27 Oct 2004 17:45:20 -0000 2.47
+++ tree-pretty-print.c 7 Nov 2004 20:44:17 -0000
@@ -1433,6 +1433,7 @@ dump_generic_node (pretty_printer *buffe
case PHI_NODE:
{
+ basic_block bb = bb_for_stmt (node);
int i;
dump_generic_node (buffer, PHI_RESULT (node), spc, flags, false);
@@ -1441,7 +1442,7 @@ dump_generic_node (pretty_printer *buffe
{
dump_generic_node (buffer, PHI_ARG_DEF (node, i), spc, flags, false);
pp_string (buffer, "(");
- pp_decimal_int (buffer, PHI_ARG_EDGE (node, i)->src->index);
+ pp_decimal_int (buffer, EDGE_PRED (bb, i)->src->index);
pp_string (buffer, ")");
if (i < PHI_NUM_ARGS (node) - 1)
pp_string (buffer, ", ");
Index: tree-scalar-evolution.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-scalar-evolution.c,v
retrieving revision 2.9
diff -u -d -p -r2.9 tree-scalar-evolution.c
--- tree-scalar-evolution.c 22 Oct 2004 17:05:07 -0000 2.9
+++ tree-scalar-evolution.c 7 Nov 2004 20:44:18 -0000
@@ -1326,9 +1326,9 @@ follow_ssa_edge_in_rhs (struct loop *loo
/* Checks whether the I-th argument of a PHI comes from a backedge. */
static bool
-backedge_phi_arg_p (tree phi, int i)
+backedge_phi_arg_p (basic_block bb, int i)
{
- edge e = PHI_ARG_EDGE (phi, i);
+ edge e = EDGE_PRED (bb, i);
/* We would in fact like to test EDGE_DFS_BACK here, but we do not care
about updating it anywhere, and this should work as well most of the
@@ -1356,7 +1356,7 @@ follow_ssa_edge_in_condition_phi_branch
/* Do not follow back edges (they must belong to an irreducible loop, which
we really do not want to worry about). */
- if (backedge_phi_arg_p (condition_phi, i))
+ if (backedge_phi_arg_p (bb_for_stmt (condition_phi), i))
return false;
if (TREE_CODE (branch) == SSA_NAME)
@@ -1429,6 +1429,7 @@ follow_ssa_edge_inner_loop_phi (struct l
result of the analysis is a symbolic parameter. */
if (ev == PHI_RESULT (loop_phi_node))
{
+ basic_block loop_bb = bb_for_stmt (loop_phi_node);
bool res = false;
int i;
@@ -1438,7 +1439,7 @@ follow_ssa_edge_inner_loop_phi (struct l
basic_block bb;
/* Follow the edges that exit the inner loop. */
- bb = PHI_ARG_EDGE (loop_phi_node, i)->src;
+ bb = EDGE_PRED (loop_bb, i)->src;
if (!flow_bb_inside_loop_p (loop, bb))
res = res || follow_ssa_edge_in_rhs (outer_loop, arg, halting_phi,
evolution_of_loop);
@@ -1531,6 +1532,7 @@ analyze_evolution_in_loop (tree loop_phi
tree evolution_function = chrec_not_analyzed_yet;
struct loop *loop = loop_containing_stmt (loop_phi_node);
basic_block bb;
+ basic_block loop_bb;
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1540,6 +1542,7 @@ analyze_evolution_in_loop (tree loop_phi
fprintf (dump_file, ")\n");
}
+ loop_bb = bb_for_stmt (loop_phi_node);
for (i = 0; i < PHI_NUM_ARGS (loop_phi_node); i++)
{
tree arg = PHI_ARG_DEF (loop_phi_node, i);
@@ -1547,7 +1550,7 @@ analyze_evolution_in_loop (tree loop_phi
bool res;
/* Select the edges that enter the loop body. */
- bb = PHI_ARG_EDGE (loop_phi_node, i)->src;
+ bb = EDGE_PRED (loop_bb, i)->src;
if (!flow_bb_inside_loop_p (loop, bb))
continue;
@@ -1599,6 +1602,7 @@ analyze_initial_condition (tree loop_phi
int i;
tree init_cond = chrec_not_analyzed_yet;
struct loop *loop = bb_for_stmt (loop_phi_node)->loop_father;
+ basic_block loop_bb;
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1608,10 +1612,11 @@ analyze_initial_condition (tree loop_phi
fprintf (dump_file, ")\n");
}
+ loop_bb = bb_for_stmt (loop_phi_node);
for (i = 0; i < PHI_NUM_ARGS (loop_phi_node); i++)
{
tree branch = PHI_ARG_DEF (loop_phi_node, i);
- basic_block bb = PHI_ARG_EDGE (loop_phi_node, i)->src;
+ basic_block bb = EDGE_PRED (loop_bb, i)->src;
/* When the branch is oriented to the loop's body, it does
not contribute to the initial condition. */
@@ -1686,12 +1691,14 @@ interpret_condition_phi (struct loop *lo
{
int i;
tree res = chrec_not_analyzed_yet;
+ basic_block condition_bb;
+ condition_bb = bb_for_stmt (condition_phi);
for (i = 0; i < PHI_NUM_ARGS (condition_phi); i++)
{
tree branch_chrec;
- if (backedge_phi_arg_p (condition_phi, i))
+ if (backedge_phi_arg_p (condition_bb, i))
{
res = chrec_dont_know;
break;
Index: tree-ssa-ccp.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-ccp.c,v
retrieving revision 2.49
diff -u -d -p -r2.49 tree-ssa-ccp.c
--- tree-ssa-ccp.c 4 Nov 2004 22:07:39 -0000 2.49
+++ tree-ssa-ccp.c 7 Nov 2004 20:44:18 -0000
@@ -697,6 +697,7 @@ ccp_lattice_meet (value val1, value val2
static enum ssa_prop_result
ccp_visit_phi_node (tree phi)
{
+ basic_block bb;
value new_val, *old_val;
int i;
@@ -737,10 +738,11 @@ ccp_visit_phi_node (tree phi)
gcc_unreachable ();
}
+ bb = bb_for_stmt (phi);
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
{
/* Compute the meet operator over all the PHI arguments. */
- edge e = PHI_ARG_EDGE (phi, i);
+ edge e = EDGE_PRED (bb, i);
if (dump_file && (dump_flags & TDF_DETAILS))
{
Index: tree-ssa-dce.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-dce.c,v
retrieving revision 2.26
diff -u -d -p -r2.26 tree-ssa-dce.c
--- tree-ssa-dce.c 4 Nov 2004 08:41:15 -0000 2.26
+++ tree-ssa-dce.c 7 Nov 2004 20:44:18 -0000
@@ -589,9 +589,11 @@ propagate_necessity (struct edge_list *e
if (aggressive)
{
+ basic_block bb = bb_for_stmt (i);
for (k = 0; k < PHI_NUM_ARGS (i); k++)
{
- basic_block arg_bb = PHI_ARG_EDGE (i, k)->src;
+ basic_block arg_bb = EDGE_PRED (bb, k)->src;
+
if (! (arg_bb->flags & BB_VISITED))
{
arg_bb->flags |= BB_VISITED;
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-dom.c,v
retrieving revision 2.65
diff -u -d -p -r2.65 tree-ssa-dom.c
--- tree-ssa-dom.c 30 Oct 2004 12:15:09 -0000 2.65
+++ tree-ssa-dom.c 7 Nov 2004 20:44:19 -0000
@@ -2292,7 +2292,6 @@ cprop_into_successor_phis (basic_block b
FOR_EACH_EDGE (e, ei, bb->succs)
{
tree phi;
- int phi_num_args;
int hint;
/* If this is an abnormal edge, then we do not want to copy propagate
@@ -2304,43 +2303,13 @@ cprop_into_successor_phis (basic_block b
if (! phi)
continue;
- /* There is no guarantee that for any two PHI nodes in a block that
- the phi alternative associated with a particular edge will be
- at the same index in the phi alternative array.
-
- However, it is very likely they will be the same. So we keep
- track of the index of the alternative where we found the edge in
- the previous phi node and check that index first in the next
- phi node. If that hint fails, then we actually search all
- the entries. */
- phi_num_args = PHI_NUM_ARGS (phi);
- hint = phi_num_args;
+ hint = e->dest_idx;
for ( ; phi; phi = PHI_CHAIN (phi))
{
- int i;
tree new;
use_operand_p orig_p;
tree orig;
- /* If the hint is valid (!= phi_num_args), see if it points
- us to the desired phi alternative. */
- if (hint != phi_num_args && PHI_ARG_EDGE (phi, hint) == e)
- ;
- else
- {
- /* The hint was either invalid or did not point to the
- correct phi alternative. Search all the alternatives
- for the correct one. Update the hint. */
- for (i = 0; i < phi_num_args; i++)
- if (PHI_ARG_EDGE (phi, i) == e)
- break;
- hint = i;
- }
-
- /* If we did not find the proper alternative, then something is
- horribly wrong. */
- gcc_assert (hint != phi_num_args);
-
/* The alternative may be associated with a constant, so verify
it is an SSA_NAME before doing anything with it. */
orig_p = PHI_ARG_DEF_PTR (phi, hint);
Index: tree-ssa-live.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-live.c,v
retrieving revision 2.24
diff -u -d -p -r2.24 tree-ssa-live.c
--- tree-ssa-live.c 4 Nov 2004 08:41:16 -0000 2.24
+++ tree-ssa-live.c 7 Nov 2004 20:44:19 -0000
@@ -589,7 +589,7 @@ calculate_live_on_entry (var_map map)
if (!phi_ssa_name_p (var))
continue;
stmt = SSA_NAME_DEF_STMT (var);
- e = PHI_ARG_EDGE (phi, i);
+ e = EDGE_PRED (bb, i);
/* Any uses in PHIs which either don't have def's or are not
defined in the block from which the def comes, will be live
@@ -751,7 +751,7 @@ calculate_live_on_exit (tree_live_info_p
for (i = 0; i < (unsigned)PHI_NUM_ARGS (phi); i++)
{
t = PHI_ARG_DEF (phi, i);
- e = PHI_ARG_EDGE (phi, i);
+ e = EDGE_PRED (bb, i);
if (!phi_ssa_name_p (t) || e->src == ENTRY_BLOCK_PTR)
continue;
set_if_valid (map, on_exit[e->src->index], t);
Index: tree-ssa-loop-manip.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-loop-manip.c,v
retrieving revision 2.14
diff -u -d -p -r2.14 tree-ssa-loop-manip.c
--- tree-ssa-loop-manip.c 4 Nov 2004 08:41:16 -0000 2.14
+++ tree-ssa-loop-manip.c 7 Nov 2004 20:44:19 -0000
@@ -274,7 +274,7 @@ find_uses_to_rename (bitmap *use_blocks)
{
for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
for (i = 0; i < (unsigned) PHI_NUM_ARGS (phi); i++)
- find_uses_to_rename_use (PHI_ARG_EDGE (phi, i)->src,
+ find_uses_to_rename_use (EDGE_PRED (bb, i)->src,
PHI_ARG_DEF (phi, i), use_blocks);
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
@@ -385,7 +385,7 @@ verify_loop_closed_ssa (void)
{
for (phi = phi_nodes (bb); phi; phi = TREE_CHAIN (phi))
for (i = 0; i < (unsigned) PHI_NUM_ARGS (phi); i++)
- check_loop_closed_ssa_use (PHI_ARG_EDGE (phi, i)->src,
+ check_loop_closed_ssa_use (EDGE_PRED (bb, i)->src,
PHI_ARG_DEF (phi, i));
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
@@ -670,7 +670,7 @@ lv_adjust_loop_header_phi (basic_block f
int i;
for (i = 0; i < PHI_NUM_ARGS (phi2); i++)
{
- if (PHI_ARG_EDGE (phi2, i)->src == new_head)
+ if (EDGE_PRED (second, i)->src == new_head)
{
tree def = PHI_ARG_DEF (phi2, i);
add_phi_arg (&phi1, def, e);
Index: tree-ssa-phiopt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-phiopt.c,v
retrieving revision 2.18
diff -u -d -p -r2.18 tree-ssa-phiopt.c
--- tree-ssa-phiopt.c 22 Oct 2004 17:05:08 -0000 2.18
+++ tree-ssa-phiopt.c 7 Nov 2004 20:44:20 -0000
@@ -365,10 +365,10 @@ conditional_replacement (basic_block bb,
false edge as the value zero. Note that those conditions are not
the same since only one of the outgoing edges from the COND_EXPR
will directly reach BB and thus be associated with an argument. */
- if ((PHI_ARG_EDGE (phi, 0) == true_edge && integer_onep (arg0))
- || (PHI_ARG_EDGE (phi, 0) == false_edge && integer_zerop (arg0))
- || (PHI_ARG_EDGE (phi, 1) == true_edge && integer_onep (arg1))
- || (PHI_ARG_EDGE (phi, 1) == false_edge && integer_zerop (arg1)))
+ if ((EDGE_PRED (bb, 0) == true_edge && integer_onep (arg0))
+ || (EDGE_PRED (bb, 0) == false_edge && integer_zerop (arg0))
+ || (EDGE_PRED (bb, 1) == true_edge && integer_onep (arg1))
+ || (EDGE_PRED (bb, 1) == false_edge && integer_zerop (arg1)))
{
new = build (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)),
PHI_RESULT (phi), cond);
@@ -477,7 +477,7 @@ value_replacement (basic_block bb, tree
/* Now we know the incoming edge to BB that has the argument for the
RHS of our new assignment statement. */
- if (PHI_ARG_EDGE (phi, 0) == e)
+ if (EDGE_PRED (bb_for_stmt (phi), 0) == e)
arg = arg0;
else
arg = arg1;
Index: tree-ssa-pre.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-pre.c,v
retrieving revision 2.50
diff -u -d -p -r2.50 tree-ssa-pre.c
--- tree-ssa-pre.c 4 Nov 2004 08:41:16 -0000 2.50
+++ tree-ssa-pre.c 7 Nov 2004 20:44:20 -0000
@@ -925,6 +925,7 @@ phi_translate (tree expr, value_set_t se
case tcc_exceptional:
{
tree phi = NULL;
+ basic_block bb;
int i;
gcc_assert (TREE_CODE (expr) == SSA_NAME);
if (TREE_CODE (SSA_NAME_DEF_STMT (expr)) == PHI_NODE)
@@ -932,8 +933,9 @@ phi_translate (tree expr, value_set_t se
else
return expr;
+ bb = bb_for_stmt (phi);
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
- if (PHI_ARG_EDGE (phi, i)->src == pred)
+ if (EDGE_PRED (bb, i)->src == pred)
{
tree val;
if (is_undefined_value (PHI_ARG_DEF (phi, i)))
Index: tree-ssa-threadupdate.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa-threadupdate.c,v
retrieving revision 2.12
diff -u -d -p -r2.12 tree-ssa-threadupdate.c
--- tree-ssa-threadupdate.c 2 Nov 2004 12:51:09 -0000 2.12
+++ tree-ssa-threadupdate.c 7 Nov 2004 20:44:20 -0000
@@ -155,7 +155,7 @@ remove_ctrl_stmt_and_useless_edges (basi
for (ei = ei_start (bb->succs); (e = ei_safe_edge (ei)); )
{
if (e->dest != dest_bb)
- ssa_remove_edge (e);
+ remove_edge (e);
else
ei_next (&ei);
}
@@ -306,6 +306,7 @@ thread_block (basic_block bb)
struct redirection_data *rd = VARRAY_GENERIC_PTR (redirection_data, i);
tree phi;
edge e;
+ int indx;
e = make_edge (rd->dup_block, rd->outgoing_edge->dest, EDGE_FALLTHRU);
@@ -313,11 +314,9 @@ thread_block (basic_block bb)
from the duplicate block, then we will need to add a new argument
to them. The argument should have the same value as the argument
associated with the outgoing edge stored in RD. */
+ indx = rd->outgoing_edge->dest_idx;
for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
- {
- int indx = phi_arg_from_edge (phi, rd->outgoing_edge);
- add_phi_arg (&phi, PHI_ARG_DEF_TREE (phi, indx), e);
- }
+ add_phi_arg (&phi, PHI_ARG_DEF_TREE (phi, indx), e);
}
/* The loop above created the duplicate blocks (and the statements
Index: tree-ssa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-ssa.c,v
retrieving revision 2.55
diff -u -d -p -r2.55 tree-ssa.c
--- tree-ssa.c 4 Nov 2004 20:10:59 -0000 2.55
+++ tree-ssa.c 7 Nov 2004 20:44:21 -0000
@@ -46,24 +46,6 @@ Boston, MA 02111-1307, USA. */
#include "tree-pass.h"
-/* Remove edge E and remove the corresponding arguments from the PHI nodes
- in E's destination block. */
-
-void
-ssa_remove_edge (edge e)
-{
- tree phi, next;
-
- /* Remove the appropriate PHI arguments in E's destination block. */
- for (phi = phi_nodes (e->dest); phi; phi = next)
- {
- next = PHI_CHAIN (phi);
- remove_phi_arg (phi, e->src);
- }
-
- remove_edge (e);
-}
-
/* Remove the corresponding arguments from the PHI nodes in E's
destination block and redirect it to DEST. Return redirected edge.
The list of removed arguments is stored in PENDING_STMT (e). */
@@ -74,24 +56,22 @@ ssa_redirect_edge (edge e, basic_block d
tree phi, next;
tree list = NULL, *last = &list;
tree src, dst, node;
- int i;
+ unsigned int dest_idx = e->dest_idx;
/* Remove the appropriate PHI arguments in E's destination block. */
for (phi = phi_nodes (e->dest); phi; phi = next)
{
next = PHI_CHAIN (phi);
- i = phi_arg_from_edge (phi, e);
- if (i < 0)
- continue;
-
- src = PHI_ARG_DEF (phi, i);
+ src = PHI_ARG_DEF (phi, dest_idx);
dst = PHI_RESULT (phi);
- node = build_tree_list (dst, src);
- *last = node;
- last = &TREE_CHAIN (node);
- remove_phi_arg_num (phi, i);
+ if (src)
+ {
+ node = build_tree_list (dst, src);
+ *last = node;
+ last = &TREE_CHAIN (node);
+ }
}
e = redirect_edge_succ_nodup (e, dest);
@@ -301,6 +281,16 @@ verify_phi_args (tree phi, basic_block b
int i, phi_num_args = PHI_NUM_ARGS (phi);
edge_iterator ei;
+ if ((unsigned int) phi_num_args != EDGE_COUNT (bb->preds))
+ {
+ error ("The number of PHI arguments, %d, does not match "
+ "the number of incoming edges, %d, to bb %d.\n",
+ phi_num_args,
+ EDGE_COUNT (bb->preds),
+ bb->index);
+ err = true;
+ }
+
/* Mark all the incoming edges. */
FOR_EACH_EDGE (e, ei, bb->preds)
e->aux = (void *) 1;
@@ -309,7 +299,7 @@ verify_phi_args (tree phi, basic_block b
{
tree op = PHI_ARG_DEF (phi, i);
- e = PHI_ARG_EDGE (phi, i);
+ e = EDGE_PRED (bb, i);
if (TREE_CODE (op) == SSA_NAME)
err = verify_use (e->src, definition_block[SSA_NAME_VERSION (op)], op,
@@ -619,7 +609,9 @@ verify_ssa (void)
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
{
tree def = PHI_ARG_DEF (phi, i);
- if (TREE_CODE (def) != SSA_NAME && !is_gimple_min_invariant (def))
+ if (def
+ && TREE_CODE (def) != SSA_NAME
+ && !is_gimple_min_invariant (def))
{
error ("PHI argument is not SSA_NAME, or invariant");
print_generic_stmt (stderr, phi, TDF_VOPS);
@@ -1077,12 +1069,14 @@ replace_immediate_uses (tree var, tree r
if (TREE_CODE (stmt) == PHI_NODE)
{
+ basic_block bb = bb_for_stmt (stmt);
+
for (j = 0; j < PHI_NUM_ARGS (stmt); j++)
if (PHI_ARG_DEF (stmt, j) == var)
{
SET_PHI_ARG_DEF (stmt, j, repl);
if (TREE_CODE (repl) == SSA_NAME
- && PHI_ARG_EDGE (stmt, j)->flags & EDGE_ABNORMAL)
+ && EDGE_PRED (bb, j)->flags & EDGE_ABNORMAL)
SSA_NAME_OCCURS_IN_ABNORMAL_PHI (repl) = 1;
}
Index: tree-vectorizer.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-vectorizer.c,v
retrieving revision 2.24
diff -u -d -p -r2.24 tree-vectorizer.c
--- tree-vectorizer.c 4 Nov 2004 13:48:59 -0000 2.24
+++ tree-vectorizer.c 7 Nov 2004 20:44:21 -0000
@@ -586,7 +586,7 @@ update_phi_nodes_for_guard (edge guard_t
edge e = EDGE_SUCC (loop->exit_edges[0]->dest, 0);
SET_PHI_ARG_DEF (phi1,
- phi_arg_from_edge (phi1, e),
+ e->dest_idx,
PHI_RESULT (new_phi));
}
}
@@ -2961,7 +2961,7 @@ vect_update_ivs_after_vectorizer (struct
/* Fix phi expressions in duplicated loop. */
num_elem1 = PHI_NUM_ARGS (phi);
for (i = 0; i < num_elem1; i++)
- if (PHI_ARG_EDGE (phi, i) == latch)
+ if (EDGE_PRED (bb_for_stmt (phi), i) == latch)
{
tree def = PHI_ARG_DEF (phi, i);
@@ -2973,7 +2973,10 @@ vect_update_ivs_after_vectorizer (struct
if (PHI_ARG_DEF (phi1, j) == def)
{
SET_PHI_ARG_DEF (phi1, j, ni_name);
+#if 0
PHI_ARG_EDGE (phi1, j) = EDGE_SUCC (new_bb, 0);
+#endif
+ gcc_unreachable ();
break;
}
}
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.647
diff -u -d -p -r1.647 tree.h
--- tree.h 4 Nov 2004 23:30:16 -0000 1.647
+++ tree.h 7 Nov 2004 20:44:22 -0000
@@ -1374,7 +1374,6 @@ struct tree_ssa_name GTY(())
#define PHI_NUM_ARGS(NODE) PHI_NODE_CHECK (NODE)->phi.num_args
#define PHI_ARG_CAPACITY(NODE) PHI_NODE_CHECK (NODE)->phi.capacity
#define PHI_ARG_ELT(NODE, I) PHI_NODE_ELT_CHECK (NODE, I)
-#define PHI_ARG_EDGE(NODE, I) PHI_NODE_ELT_CHECK (NODE, I).e
#define PHI_ARG_NONZERO(NODE, I) PHI_NODE_ELT_CHECK (NODE, I).nonzero
#define PHI_BB(NODE) PHI_NODE_CHECK (NODE)->phi.bb
#define PHI_DF(NODE) PHI_NODE_CHECK (NODE)->phi.df
@@ -1384,7 +1383,6 @@ struct edge_def;
struct phi_arg_d GTY(())
{
tree def;
- struct edge_def * GTY((skip (""))) e;
bool nonzero;
};