(null). When we finish processing the block, we pop off entries and
remove the expressions from the global hash table until we hit the
marker. */
-static varray_type avail_exprs_stack;
+static VEC(tree_on_heap) *avail_exprs_stack;
/* Stack of trees used to restore the global currdefs to its original
state after completing optimization of a block and its dominator children.
A NULL node is used to mark the last node associated with the
current block. */
-varray_type block_defs_stack;
+static VEC(tree_on_heap) *block_defs_stack;
/* Stack of statements we need to rescan during finalization for newly
exposed variables.
expressions are removed from AVAIL_EXPRS. Else we may change the
hash code for an expression and be unable to find/remove it from
AVAIL_EXPRS. */
-varray_type stmts_to_rescan;
+static VEC(tree_on_heap) *stmts_to_rescan;
/* Structure for entries in the expression hash table.
A NULL entry is used to mark the end of pairs which need to be
restored during finalization of this block. */
-static varray_type const_and_copies_stack;
+static VEC(tree_on_heap) *const_and_copies_stack;
/* Bitmap of SSA_NAMEs known to have a nonzero value, even if we do not
know their exact value. */
A NULL entry is used to mark the end of names needing their
entry in NONZERO_VARS cleared during finalization of this block. */
-static varray_type nonzero_vars_stack;
+static VEC(tree_on_heap) *nonzero_vars_stack;
/* Track whether or not we have changed the control flow graph. */
static bool cfg_altered;
/* An entry in the VRP_DATA hash table. We record the variable and a
varray of VRP_ELEMENT records associated with that variable. */
-
struct vrp_hash_elt
{
tree var;
list to determine which variables need their VRP data updated.
A NULL entry marks the end of the SSA_NAMEs associated with this block. */
-static varray_type vrp_variables_stack;
+static VEC(tree_on_heap) *vrp_variables_stack;
struct eq_expr_value
{
/* Create our hash tables. */
avail_exprs = htab_create (1024, real_avail_expr_hash, avail_expr_eq, free);
vrp_data = htab_create (ceil_log2 (num_ssa_names), vrp_hash, vrp_eq, free);
- VARRAY_TREE_INIT (avail_exprs_stack, 20, "Available expression stack");
- VARRAY_TREE_INIT (block_defs_stack, 20, "Block DEFS stack");
- VARRAY_TREE_INIT (const_and_copies_stack, 20, "Block const_and_copies stack");
- VARRAY_TREE_INIT (nonzero_vars_stack, 20, "Block nonzero_vars stack");
- VARRAY_TREE_INIT (vrp_variables_stack, 20, "Block vrp_variables stack");
- VARRAY_TREE_INIT (stmts_to_rescan, 20, "Statements to rescan");
+ avail_exprs_stack = VEC_alloc (tree_on_heap, 20);
+ block_defs_stack = VEC_alloc (tree_on_heap, 20);
+ const_and_copies_stack = VEC_alloc (tree_on_heap, 20);
+ nonzero_vars_stack = VEC_alloc (tree_on_heap, 20);
+ vrp_variables_stack = VEC_alloc (tree_on_heap, 20);
+ stmts_to_rescan = VEC_alloc (tree_on_heap, 20);
nonzero_vars = BITMAP_XMALLOC ();
need_eh_cleanup = BITMAP_XMALLOC ();
if (value && !is_gimple_min_invariant (value))
SSA_NAME_VALUE (name) = NULL;
}
+
+ VEC_free (tree_on_heap, block_defs_stack);
+ VEC_free (tree_on_heap, avail_exprs_stack);
+ VEC_free (tree_on_heap, const_and_copies_stack);
+ VEC_free (tree_on_heap, nonzero_vars_stack);
+ VEC_free (tree_on_heap, vrp_variables_stack);
+ VEC_free (tree_on_heap, stmts_to_rescan);
}
static bool
{
tree src = PHI_ARG_DEF_FROM_EDGE (phi, e);
tree dst = PHI_RESULT (phi);
+
+ /* If the desired argument is not the same as this PHI's result
+ and it is set by a PHI in this block, then we can not thread
+ through this block. */
+ if (src != dst
+ && TREE_CODE (src) == SSA_NAME
+ && TREE_CODE (SSA_NAME_DEF_STMT (src)) == PHI_NODE
+ && bb_for_stmt (SSA_NAME_DEF_STMT (src)) == e->dest)
+ return;
+
record_const_or_copy (dst, src);
register_new_def (dst, &block_defs_stack);
}
if (SSA_NAME_VAR (cached_lhs) != SSA_NAME_VAR (lhs))
break;
- /* If CACHED_LHS does not represent the current value of the undering
+ /* If CACHED_LHS does not represent the current value of the underlying
variable in CACHED_LHS/LHS, then we can not ignore this statement. */
if (var_ann (SSA_NAME_VAR (lhs))->current_def != cached_lhs)
break;
|| TREE_CODE (stmt) == SWITCH_EXPR))
{
tree cond, cached_lhs;
- edge e1;
- edge_iterator ei;
-
- /* Do not forward entry edges into the loop. In the case loop
- has multiple entry edges we may end up in constructing irreducible
- region.
- ??? We may consider forwarding the edges in the case all incoming
- edges forward to the same destination block. */
- if (!e->flags & EDGE_DFS_BACK)
- {
- FOR_EACH_EDGE (e1, ei, e->dest->preds)
- if (e1->flags & EDGE_DFS_BACK)
- break;
- if (e1)
- return;
- }
/* Now temporarily cprop the operands and try to find the resulting
expression in the hash tables. */
}
else
{
- TREE_SET_CODE (TREE_OPERAND (dummy_cond, 0), cond_code);
- TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 0) = op0;
- TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 1) = op1;
+ TREE_SET_CODE (COND_EXPR_COND (dummy_cond), cond_code);
+ TREE_OPERAND (COND_EXPR_COND (dummy_cond), 0) = op0;
+ TREE_OPERAND (COND_EXPR_COND (dummy_cond), 1) = op1;
}
/* If the conditional folds to an invariant, then we are done,
otherwise look it up in the hash tables. */
cached_lhs = local_fold (COND_EXPR_COND (dummy_cond));
if (! is_gimple_min_invariant (cached_lhs))
- cached_lhs = lookup_avail_expr (dummy_cond, false);
- if (!cached_lhs || ! is_gimple_min_invariant (cached_lhs))
{
- cached_lhs = simplify_cond_and_lookup_avail_expr (dummy_cond,
- NULL,
- false);
+ cached_lhs = lookup_avail_expr (dummy_cond, false);
+ if (!cached_lhs || ! is_gimple_min_invariant (cached_lhs))
+ cached_lhs = simplify_cond_and_lookup_avail_expr (dummy_cond,
+ NULL,
+ false);
}
}
/* We can have conditionals which just test the state of a
/* Push a marker on the stacks of local information so that we know how
far to unwind when we finalize this block. */
- VARRAY_PUSH_TREE (avail_exprs_stack, NULL_TREE);
- VARRAY_PUSH_TREE (block_defs_stack, NULL_TREE);
- VARRAY_PUSH_TREE (const_and_copies_stack, NULL_TREE);
- VARRAY_PUSH_TREE (nonzero_vars_stack, NULL_TREE);
- VARRAY_PUSH_TREE (vrp_variables_stack, NULL_TREE);
+ VEC_safe_push (tree_on_heap, avail_exprs_stack, NULL_TREE);
+ VEC_safe_push (tree_on_heap, block_defs_stack, NULL_TREE);
+ VEC_safe_push (tree_on_heap, const_and_copies_stack, NULL_TREE);
+ VEC_safe_push (tree_on_heap, nonzero_vars_stack, NULL_TREE);
+ VEC_safe_push (tree_on_heap, vrp_variables_stack, NULL_TREE);
record_equivalences_from_incoming_edge (bb);
remove_local_expressions_from_table (void)
{
/* Remove all the expressions made available in this block. */
- while (VARRAY_ACTIVE_SIZE (avail_exprs_stack) > 0)
+ while (VEC_length (tree_on_heap, avail_exprs_stack) > 0)
{
struct expr_hash_elt element;
- tree expr = VARRAY_TOP_TREE (avail_exprs_stack);
- VARRAY_POP (avail_exprs_stack);
+ tree expr = VEC_pop (tree_on_heap, avail_exprs_stack);
if (expr == NULL_TREE)
break;
static void
restore_nonzero_vars_to_original_value (void)
{
- while (VARRAY_ACTIVE_SIZE (nonzero_vars_stack) > 0)
+ while (VEC_length (tree_on_heap, nonzero_vars_stack) > 0)
{
- tree name = VARRAY_TOP_TREE (nonzero_vars_stack);
- VARRAY_POP (nonzero_vars_stack);
+ tree name = VEC_pop (tree_on_heap, nonzero_vars_stack);
if (name == NULL)
break;
static void
restore_vars_to_original_value (void)
{
- while (VARRAY_ACTIVE_SIZE (const_and_copies_stack) > 0)
+ while (VEC_length (tree_on_heap, const_and_copies_stack) > 0)
{
tree prev_value, dest;
- dest = VARRAY_TOP_TREE (const_and_copies_stack);
- VARRAY_POP (const_and_copies_stack);
+ dest = VEC_pop (tree_on_heap, const_and_copies_stack);
if (dest == NULL)
break;
- prev_value = VARRAY_TOP_TREE (const_and_copies_stack);
- VARRAY_POP (const_and_copies_stack);
-
+ prev_value = VEC_pop (tree_on_heap, const_and_copies_stack);
SSA_NAME_VALUE (dest) = prev_value;
}
}
restore_currdefs_to_original_value (void)
{
/* Restore CURRDEFS to its original state. */
- while (VARRAY_ACTIVE_SIZE (block_defs_stack) > 0)
+ while (VEC_length (tree_on_heap, block_defs_stack) > 0)
{
- tree tmp = VARRAY_TOP_TREE (block_defs_stack);
+ tree tmp = VEC_pop (tree_on_heap, block_defs_stack);
tree saved_def, var;
- VARRAY_POP (block_defs_stack);
-
if (tmp == NULL_TREE)
break;
{
tree last;
- /* If we are at a leaf node in the dominator graph, see if we can thread
+ /* If we are at a leaf node in the dominator tree, see if we can thread
the edge from BB through its successor.
Do this before we remove entries from our equivalence tables. */
/* Push a marker onto the available expression stack so that we
unwind any expressions related to the TRUE arm before processing
the false arm below. */
- VARRAY_PUSH_TREE (avail_exprs_stack, NULL_TREE);
- VARRAY_PUSH_TREE (block_defs_stack, NULL_TREE);
- VARRAY_PUSH_TREE (const_and_copies_stack, NULL_TREE);
+ VEC_safe_push (tree_on_heap, avail_exprs_stack, NULL_TREE);
+ VEC_safe_push (tree_on_heap, block_defs_stack, NULL_TREE);
+ VEC_safe_push (tree_on_heap, const_and_copies_stack, NULL_TREE);
edge_info = true_edge->aux;
To be efficient, we note which variables have had their values
constrained in this block. So walk over each variable in the
VRP_VARIABLEs array. */
- while (VARRAY_ACTIVE_SIZE (vrp_variables_stack) > 0)
+ while (VEC_length (tree_on_heap, vrp_variables_stack) > 0)
{
- tree var = VARRAY_TOP_TREE (vrp_variables_stack);
+ tree var = VEC_pop (tree_on_heap, vrp_variables_stack);
struct vrp_hash_elt vrp_hash_elt, *vrp_hash_elt_p;
void **slot;
we are done. */
varray_type var_vrp_records;
- VARRAY_POP (vrp_variables_stack);
-
if (var == NULL)
break;
/* If we queued any statements to rescan in this block, then
go ahead and rescan them now. */
- while (VARRAY_ACTIVE_SIZE (stmts_to_rescan) > 0)
+ while (VEC_length (tree_on_heap, stmts_to_rescan) > 0)
{
- tree stmt = VARRAY_TOP_TREE (stmts_to_rescan);
+ tree stmt = VEC_last (tree_on_heap, stmts_to_rescan);
basic_block stmt_bb = bb_for_stmt (stmt);
if (stmt_bb != bb)
break;
- VARRAY_POP (stmts_to_rescan);
+ VEC_pop (tree_on_heap, stmts_to_rescan);
mark_new_vars_to_rename (stmt, vars_to_rename);
}
}
{
tree t = PHI_ARG_DEF (phi, i);
- if (TREE_CODE (t) == SSA_NAME || is_gimple_min_invariant (t))
- {
- /* Ignore alternatives which are the same as our LHS. */
- if (operand_equal_p (lhs, t, 0))
- continue;
-
- /* If we have not processed an alternative yet, then set
- RHS to this alternative. */
- if (rhs == NULL)
- rhs = t;
- /* If we have processed an alternative (stored in RHS), then
- see if it is equal to this one. If it isn't, then stop
- the search. */
- else if (! operand_equal_p (rhs, t, 0))
- break;
- }
- else
+ /* Ignore alternatives which are the same as our LHS. Since
+ LHS is a PHI_RESULT, it is known to be a SSA_NAME, so we
+ can simply compare pointers. */
+ if (lhs == t)
+ continue;
+
+ /* If we have not processed an alternative yet, then set
+ RHS to this alternative. */
+ if (rhs == NULL)
+ rhs = t;
+ /* If we have processed an alternative (stored in RHS), then
+ see if it is equal to this one. If it isn't, then stop
+ the search. */
+ else if (! operand_equal_for_phi_arg_p (rhs, t))
break;
}
/* Record this SSA_NAME so that we can reset the global table
when we leave this block. */
- VARRAY_PUSH_TREE (nonzero_vars_stack, var);
+ VEC_safe_push (tree_on_heap, nonzero_vars_stack, var);
}
/* Enter a statement into the true/false expression hash table indicating
if (*slot == NULL)
{
*slot = (void *) element;
- VARRAY_PUSH_TREE (avail_exprs_stack, cond);
+ VEC_safe_push (tree_on_heap, avail_exprs_stack, cond);
}
else
free (element);
{
SSA_NAME_VALUE (x) = y;
- VARRAY_PUSH_TREE (const_and_copies_stack, prev_x);
- VARRAY_PUSH_TREE (const_and_copies_stack, x);
+ VEC_safe_push (tree_on_heap, const_and_copies_stack, prev_x);
+ VEC_safe_push (tree_on_heap, const_and_copies_stack, x);
}
/* Record that X is equal to Y in const_and_copies. Record undo
- information in the block-local varray. */
+ information in the block-local vector. */
static void
record_const_or_copy (tree x, tree y)
}
else
{
- TREE_SET_CODE (TREE_OPERAND (dummy_cond, 0), GT_EXPR);
- TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 0) = op;
- TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 1)
+ TREE_SET_CODE (COND_EXPR_COND (dummy_cond), GT_EXPR);
+ TREE_OPERAND (COND_EXPR_COND (dummy_cond), 0) = op;
+ TREE_OPERAND (COND_EXPR_COND (dummy_cond), 1)
= integer_zero_node;
}
val = simplify_cond_and_lookup_avail_expr (dummy_cond, NULL, false);
}
else
{
- TREE_SET_CODE (TREE_OPERAND (dummy_cond, 0), LE_EXPR);
- TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 0) = op;
- TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 1)
+ TREE_SET_CODE (COND_EXPR_COND (dummy_cond), LE_EXPR);
+ TREE_OPERAND (COND_EXPR_COND (dummy_cond), 0) = op;
+ TREE_OPERAND (COND_EXPR_COND (dummy_cond), 1)
= build_int_cst (type, 0);
}
val = simplify_cond_and_lookup_avail_expr (dummy_cond, NULL, false);
if (!val)
{
- TREE_SET_CODE (TREE_OPERAND (dummy_cond, 0), GE_EXPR);
- TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 0) = op;
- TREE_OPERAND (TREE_OPERAND (dummy_cond, 0), 1)
+ TREE_SET_CODE (COND_EXPR_COND (dummy_cond), GE_EXPR);
+ TREE_OPERAND (COND_EXPR_COND (dummy_cond), 0) = op;
+ TREE_OPERAND (COND_EXPR_COND (dummy_cond), 1)
= build_int_cst (type, 0);
val = simplify_cond_and_lookup_avail_expr (dummy_cond,
FOR_EACH_EDGE (e, ei, bb->succs)
{
tree phi;
- int phi_num_args;
- int hint;
+ int indx;
/* If this is an abnormal edge, then we do not want to copy propagate
into the PHI alternative associated with this edge. */
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;
+ indx = 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);
+ orig_p = PHI_ARG_DEF_PTR (phi, indx);
orig = USE_FROM_PTR (orig_p);
if (TREE_CODE (orig) != SSA_NAME)
continue;
/* If the alternative is known to have a nonzero value, record
that fact in the PHI node itself for future use. */
if (bitmap_bit_p (nonzero_vars, SSA_NAME_VERSION (orig)))
- PHI_ARG_NONZERO (phi, hint) = true;
+ PHI_ARG_NONZERO (phi, indx) = true;
/* If we have *ORIG_P in our constant/copy table, then replace
ORIG_P with its value in our constant/copy table. */
}
}
- if (is_gimple_min_invariant (op0)
- && (TREE_CODE (op1) == SSA_NAME
- || is_gimple_min_invariant (op1)))
+ else if (is_gimple_min_invariant (op0)
+ && (TREE_CODE (op1) == SSA_NAME
+ || is_gimple_min_invariant (op1)))
{
tree inverted = invert_truthvalue (cond);
struct edge_info *edge_info;
}
}
- if (TREE_CODE (op0) == SSA_NAME
- && (is_gimple_min_invariant (op1)
- || TREE_CODE (op1) == SSA_NAME))
+ else if (TREE_CODE (op0) == SSA_NAME
+ && (is_gimple_min_invariant (op1)
+ || TREE_CODE (op1) == SSA_NAME))
{
tree inverted = invert_truthvalue (cond);
struct edge_info *edge_info;
}
if (may_have_exposed_new_symbols)
- VARRAY_PUSH_TREE (stmts_to_rescan, bsi_stmt (si));
+ VEC_safe_push (tree_on_heap, stmts_to_rescan, bsi_stmt (si));
}
/* Replace the RHS of STMT with NEW_RHS. If RHS can be found in the
We know the call in optimize_stmt did not find an existing entry
in the hash table, so a new entry was created. At the same time
- this statement was pushed onto the BLOCK_AVAIL_EXPRS varray.
+ this statement was pushed onto the AVAIL_EXPRS_STACK vector.
If this call failed to find an existing entry on the hash table,
then the new version of this statement was entered into the
for the second time. So there are two copies on BLOCK_AVAIL_EXPRs
If this call succeeded, we still have one copy of this statement
- on the BLOCK_AVAIL_EXPRs varray.
+ on the BLOCK_AVAIL_EXPRs vector.
For both cases, we need to pop the most recent entry off the
- BLOCK_AVAIL_EXPRs varray. For the case where we never found this
+ BLOCK_AVAIL_EXPRs vector. For the case where we never found this
statement in the hash tables, that will leave precisely one
copy of this statement on BLOCK_AVAIL_EXPRs. For the case where
we found a copy of this statement in the second hash table lookup
we want _no_ copies of this statement in BLOCK_AVAIL_EXPRs. */
if (insert)
- VARRAY_POP (avail_exprs_stack);
+ VEC_pop (tree_on_heap, avail_exprs_stack);
/* And make sure we record the fact that we modified this
statement. */
if (*slot == NULL)
{
*slot = (void *) element;
- VARRAY_PUSH_TREE (avail_exprs_stack, stmt ? stmt : element->rhs);
+ VEC_safe_push (tree_on_heap, avail_exprs_stack,
+ stmt ? stmt : element->rhs);
return NULL_TREE;
}
VARRAY_GENERIC_PTR_INIT (*vrp_records_p, 2, "vrp records");
VARRAY_PUSH_GENERIC_PTR (*vrp_records_p, element);
- VARRAY_PUSH_TREE (vrp_variables_stack, TREE_OPERAND (cond, 0));
+ VEC_safe_push (tree_on_heap, vrp_variables_stack, TREE_OPERAND (cond, 0));
}
}