Commit 6b66c718 by Kazu Hirata Committed by Kazu Hirata

tree-phinode.c (resize_phi_node): Abort when LEN is strictly greater than PHI_ARG_CAPACITY.

	* tree-phinode.c (resize_phi_node): Abort when LEN is strictly
	greater than PHI_ARG_CAPACITY.
	(reserve_phi_args_for_new_edge): Initialize the new PHI
	argument to NULL_TREE.  Increment PHI_NUM_ARGS.
	(add_phi_arg): Add a PHI argument to the slot given by
	E->dest_idx.
	(remove_phi_arg_num): Do not write to PHI_ARG_EDGE.
	* tree-flow-inline (phi_arg_from_edge): Return E->dest_idx.
	* tree-ssa.c (ssa_redirect_edge): Check for a missing PHI
	argument by looking at PHI_ARG_DEF.
	(verify_phi_args): Check for a missing PHI argument.  Remove
	the check for duplicate PHI arguments.
	* tree.h (PHI_ARG_EDGE): Redefine in terms of EDGE_PRED.
	(phi_arg_d): Remove e.

From-SVN: r91097
parent b3d31392
2004-11-23 Kazu Hirata <kazu@cs.umass.edu>
* tree-phinode.c (resize_phi_node): Abort when LEN is strictly
greater than PHI_ARG_CAPACITY.
(reserve_phi_args_for_new_edge): Initialize the new PHI
argument to NULL_TREE. Increment PHI_NUM_ARGS.
(add_phi_arg): Add a PHI argument to the slot given by
E->dest_idx.
(remove_phi_arg_num): Do not write to PHI_ARG_EDGE.
* tree-flow-inline (phi_arg_from_edge): Return E->dest_idx.
* tree-ssa.c (ssa_redirect_edge): Check for a missing PHI
argument by looking at PHI_ARG_DEF.
(verify_phi_args): Check for a missing PHI argument. Remove
the check for duplicate PHI arguments.
* tree.h (PHI_ARG_EDGE): Redefine in terms of EDGE_PRED.
(phi_arg_d): Remove e.
2004-11-23 Andreas Krebbel <krebbel1@de.ibm.com> 2004-11-23 Andreas Krebbel <krebbel1@de.ibm.com>
* config/s390/s390.c (s390_backchain_string): Removed. * config/s390/s390.c (s390_backchain_string): Removed.
......
...@@ -393,15 +393,9 @@ set_phi_nodes (basic_block bb, tree l) ...@@ -393,15 +393,9 @@ set_phi_nodes (basic_block bb, tree l)
static inline int static inline int
phi_arg_from_edge (tree phi, edge e) phi_arg_from_edge (tree phi, edge e)
{ {
int i;
gcc_assert (phi); gcc_assert (phi);
gcc_assert (TREE_CODE (phi) == PHI_NODE); gcc_assert (TREE_CODE (phi) == PHI_NODE);
return e->dest_idx;
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
if (PHI_ARG_EDGE (phi, i) == e)
return i;
return -1;
} }
/* Mark VAR as used, so that it'll be preserved during rtl expansion. */ /* Mark VAR as used, so that it'll be preserved during rtl expansion. */
......
...@@ -212,13 +212,13 @@ make_phi_node (tree var, int len) ...@@ -212,13 +212,13 @@ make_phi_node (tree var, int len)
phi = allocate_phi_node (capacity); phi = allocate_phi_node (capacity);
/* We do not have to clear a part of the PHI node that stores PHI /* We need to clear the entire PHI node, including the argument
arguments, which is safe because we tell the garbage collector to portion, because we represent a "missing PHI argument" by placing
scan up to num_args elements in the array of PHI arguments. In NULL_TREE in PHI_ARG_DEF. */
other words, the garbage collector will not follow garbage memset (phi, 0, (sizeof (struct tree_phi_node) - sizeof (struct phi_arg_d)
pointers in the unused portion of the array. */ + sizeof (struct phi_arg_d) * len));
memset (phi, 0, sizeof (struct tree_phi_node) - sizeof (struct phi_arg_d));
TREE_SET_CODE (phi, PHI_NODE); TREE_SET_CODE (phi, PHI_NODE);
PHI_NUM_ARGS (phi) = len;
PHI_ARG_CAPACITY (phi) = capacity; PHI_ARG_CAPACITY (phi) = capacity;
TREE_TYPE (phi) = TREE_TYPE (var); TREE_TYPE (phi) = TREE_TYPE (var);
if (TREE_CODE (var) == SSA_NAME) if (TREE_CODE (var) == SSA_NAME)
...@@ -253,7 +253,7 @@ resize_phi_node (tree *phi, int len) ...@@ -253,7 +253,7 @@ resize_phi_node (tree *phi, int len)
int old_size; int old_size;
tree new_phi; 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 /* 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 first PHI_NUM_ARGS elements. Therefore, all we have to copy is a
...@@ -294,6 +294,17 @@ reserve_phi_args_for_new_edge (basic_block bb) ...@@ -294,6 +294,17 @@ reserve_phi_args_for_new_edge (basic_block bb)
release_phi_node (old_phi); release_phi_node (old_phi);
} }
/* We represent a "missing PHI argument" by placing NULL_TREE in
the corresponding slot. If PHI arguments were added
immediately after an edge is created, this zeroing would not
be necessary, but unfortunately this is not the case. For
example, the loop optimizer duplicates several basic blocks,
redirects edges, and then fixes up PHI arguments later in
batch. */
SET_PHI_ARG_DEF (*loc, len - 1, NULL_TREE);
PHI_NUM_ARGS (*loc)++;
} }
} }
...@@ -326,13 +337,16 @@ void ...@@ -326,13 +337,16 @@ void
add_phi_arg (tree *phi, tree def, edge e) add_phi_arg (tree *phi, tree def, edge e)
{ {
basic_block bb = e->dest; basic_block bb = e->dest;
int i = PHI_NUM_ARGS (*phi);
gcc_assert (bb == bb_for_stmt (*phi)); gcc_assert (bb == bb_for_stmt (*phi));
/* We resize PHI nodes upon edge creation. We should always have /* We resize PHI nodes upon edge creation. We should always have
enough room at this point. */ enough room at this point. */
gcc_assert (PHI_NUM_ARGS (*phi) < PHI_ARG_CAPACITY (*phi)); gcc_assert (PHI_NUM_ARGS (*phi) <= PHI_ARG_CAPACITY (*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 /* Copy propagation needs to know what object occur in abnormal
PHI nodes. This is a convenient place to record such information. */ PHI nodes. This is a convenient place to record such information. */
...@@ -342,10 +356,8 @@ add_phi_arg (tree *phi, tree def, edge e) ...@@ -342,10 +356,8 @@ add_phi_arg (tree *phi, tree def, edge e)
SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (*phi)) = 1; SSA_NAME_OCCURS_IN_ABNORMAL_PHI (PHI_RESULT (*phi)) = 1;
} }
SET_PHI_ARG_DEF (*phi, i, def); SET_PHI_ARG_DEF (*phi, e->dest_idx, def);
PHI_ARG_EDGE (*phi, i) = e; PHI_ARG_NONZERO (*phi, e->dest_idx) = false;
PHI_ARG_NONZERO (*phi, i) = false;
PHI_NUM_ARGS (*phi)++;
} }
/* Remove the Ith argument from PHI's argument list. This routine assumes /* Remove the Ith argument from PHI's argument list. This routine assumes
...@@ -365,14 +377,13 @@ remove_phi_arg_num (tree phi, int i) ...@@ -365,14 +377,13 @@ remove_phi_arg_num (tree phi, int i)
if (i != num_elem - 1) if (i != num_elem - 1)
{ {
SET_PHI_ARG_DEF (phi, i, PHI_ARG_DEF (phi, 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); 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 /* 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 PHI_ARG_DEF or PHI_ARG_NONZERO because the garbage collector will
collector will not look at those elements beyond the first not look at those elements beyond the first PHI_NUM_ARGS elements
PHI_NUM_ARGS elements of the array. */ of the array. */
PHI_NUM_ARGS (phi)--; PHI_NUM_ARGS (phi)--;
} }
......
...@@ -64,7 +64,7 @@ ssa_redirect_edge (edge e, basic_block dest) ...@@ -64,7 +64,7 @@ ssa_redirect_edge (edge e, basic_block dest)
next = PHI_CHAIN (phi); next = PHI_CHAIN (phi);
i = phi_arg_from_edge (phi, e); i = phi_arg_from_edge (phi, e);
if (i < 0) if (PHI_ARG_DEF (phi, i) == NULL_TREE)
continue; continue;
src = PHI_ARG_DEF (phi, i); src = PHI_ARG_DEF (phi, i);
...@@ -277,7 +277,6 @@ verify_phi_args (tree phi, basic_block bb, basic_block *definition_block) ...@@ -277,7 +277,6 @@ verify_phi_args (tree phi, basic_block bb, basic_block *definition_block)
edge e; edge e;
bool err = false; bool err = false;
unsigned i, phi_num_args = PHI_NUM_ARGS (phi); unsigned i, phi_num_args = PHI_NUM_ARGS (phi);
edge_iterator ei;
if (EDGE_COUNT (bb->preds) != phi_num_args) if (EDGE_COUNT (bb->preds) != phi_num_args)
{ {
...@@ -286,22 +285,27 @@ verify_phi_args (tree phi, basic_block bb, basic_block *definition_block) ...@@ -286,22 +285,27 @@ verify_phi_args (tree phi, basic_block bb, basic_block *definition_block)
goto error; goto error;
} }
/* Mark all the incoming edges. */
FOR_EACH_EDGE (e, ei, bb->preds)
e->aux = (void *) 1;
for (i = 0; i < phi_num_args; i++) for (i = 0; i < phi_num_args; i++)
{ {
tree op = PHI_ARG_DEF (phi, i); tree op = PHI_ARG_DEF (phi, i);
e = PHI_ARG_EDGE (phi, i);
if (op == NULL_TREE)
{
error ("PHI argument is missing for edge %d->%d\n",
e->src->index,
e->dest->index);
err = true;
goto error;
}
if (TREE_CODE (op) != SSA_NAME && !is_gimple_min_invariant (op)) if (TREE_CODE (op) != SSA_NAME && !is_gimple_min_invariant (op))
{ {
error ("PHI argument is not SSA_NAME, or invariant"); error ("PHI argument is not SSA_NAME, or invariant");
err = true; err = true;
} }
e = PHI_ARG_EDGE (phi, i);
if (TREE_CODE (op) == SSA_NAME) if (TREE_CODE (op) == SSA_NAME)
err = verify_use (e->src, definition_block[SSA_NAME_VERSION (op)], op, err = verify_use (e->src, definition_block[SSA_NAME_VERSION (op)], op,
phi, e->flags & EDGE_ABNORMAL, phi, e->flags & EDGE_ABNORMAL,
...@@ -315,21 +319,12 @@ verify_phi_args (tree phi, basic_block bb, basic_block *definition_block) ...@@ -315,21 +319,12 @@ verify_phi_args (tree phi, basic_block bb, basic_block *definition_block)
err = true; err = true;
} }
if (e->aux == (void *) 0)
{
error ("PHI argument flowing through dead or duplicated edge %d->%d\n",
e->src->index, e->dest->index);
err = true;
}
if (err) if (err)
{ {
fprintf (stderr, "PHI argument\n"); fprintf (stderr, "PHI argument\n");
print_generic_stmt (stderr, op, TDF_VOPS); print_generic_stmt (stderr, op, TDF_VOPS);
goto error; goto error;
} }
e->aux = (void *) 0;
} }
error: error:
......
...@@ -1374,7 +1374,7 @@ struct tree_ssa_name GTY(()) ...@@ -1374,7 +1374,7 @@ struct tree_ssa_name GTY(())
#define PHI_NUM_ARGS(NODE) PHI_NODE_CHECK (NODE)->phi.num_args #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_CAPACITY(NODE) PHI_NODE_CHECK (NODE)->phi.capacity
#define PHI_ARG_ELT(NODE, I) PHI_NODE_ELT_CHECK (NODE, I) #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_EDGE(NODE, I) (EDGE_PRED (PHI_BB ((NODE)), (I)))
#define PHI_ARG_NONZERO(NODE, I) PHI_NODE_ELT_CHECK (NODE, I).nonzero #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_BB(NODE) PHI_NODE_CHECK (NODE)->phi.bb
#define PHI_DF(NODE) PHI_NODE_CHECK (NODE)->phi.df #define PHI_DF(NODE) PHI_NODE_CHECK (NODE)->phi.df
...@@ -1384,7 +1384,6 @@ struct edge_def; ...@@ -1384,7 +1384,6 @@ struct edge_def;
struct phi_arg_d GTY(()) struct phi_arg_d GTY(())
{ {
tree def; tree def;
struct edge_def * GTY((skip (""))) e;
bool nonzero; bool nonzero;
}; };
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment