GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
+the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 51 Franklin Street, Fifth Floor,
-Boston, MA 02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
#include "langhooks.h"
#include "cfgloop.h"
#include "tree-ssa-sccvn.h"
+#include "params.h"
/* TODO:
Fourth, we eliminate fully redundant expressions.
This is a simple statement walk that replaces redundant
- calculations with the now available values. */
+ calculations with the now available values. */
/* Representations of value numbers:
DEF_VEC_ALLOC_P (vuse_vec, heap);
static VEC(vuse_vec, heap) *expression_vuses;
-
+
/* Mapping from expression to id number we can use in bitmap sets. */
static VEC(tree, heap) *expressions;
static bool bitmap_set_contains_value (bitmap_set_t, tree);
static void bitmap_insert_into_set (bitmap_set_t, tree);
static bitmap_set_t bitmap_set_new (void);
-static bool is_undefined_value (tree);
static tree create_expression_by_pieces (basic_block, tree, tree);
static tree find_or_generate_expression (basic_block, tree, tree);
speed reasons. */
hashval_t hashcode;
} *expr_pred_trans_t;
+typedef const struct expr_pred_trans_d *const_expr_pred_trans_t;
/* Return the hash value for a phi translation table entry. */
static hashval_t
expr_pred_trans_hash (const void *p)
{
- const expr_pred_trans_t ve = (expr_pred_trans_t) p;
+ const_expr_pred_trans_t const ve = (const_expr_pred_trans_t) p;
return ve->hashcode;
}
static int
expr_pred_trans_eq (const void *p1, const void *p2)
{
- const expr_pred_trans_t ve1 = (expr_pred_trans_t) p1;
- const expr_pred_trans_t ve2 = (expr_pred_trans_t) p2;
+ const_expr_pred_trans_t const ve1 = (const_expr_pred_trans_t) p1;
+ const_expr_pred_trans_t const ve2 = (const_expr_pred_trans_t) p2;
basic_block b1 = ve1->pred;
basic_block b2 = ve2->pred;
int i;
static inline bool
constant_expr_p (tree v)
{
- return TREE_CODE (v) != VALUE_HANDLE &&
+ return TREE_CODE (v) != VALUE_HANDLE &&
(TREE_CODE (v) == FIELD_DECL || is_gimple_min_invariant (v));
}
the phis in PRED. SEEN is a bitmap saying which expression we have
translated since we started translation of the toplevel expression.
Return NULL if we can't find a leader for each part of the
- translated expression. */
+ translated expression. */
static tree
phi_translate_1 (tree expr, bitmap_set_t set1, bitmap_set_t set2,
{
tree val;
tree def = PHI_ARG_DEF (phi, e->dest_idx);
-
+
if (is_gimple_min_invariant (def))
return def;
-
- if (is_undefined_value (def))
+
+ if (TREE_CODE (def) == SSA_NAME && ssa_undefined_value_p (def))
return NULL;
-
+
val = get_value_handle (def);
gcc_assert (val);
return def;
}
/* Translate EXPR using phis in PHIBLOCK, so that it has the values of
- the phis in PRED.
+ the phis in PRED.
Return NULL if we can't find a leader for each part of the
- translated expression. */
+ translated expression. */
static tree
phi_translate (tree expr, bitmap_set_t set1, bitmap_set_t set2,
return NULL;
}
-/* Determine if EXPR, a memory expressionn, is ANTIC_IN at the top of
+/* Determine if EXPR, a memory expression, is ANTIC_IN at the top of
BLOCK by seeing if it is not killed in the block. Note that we are
only determining whether there is a store that kills it. Because
of the order in which clean iterates over values, we are guaranteed
bitmap_set_t PA_OUT;
edge e;
edge_iterator ei;
+ unsigned long max_pa = PARAM_VALUE (PARAM_MAX_PARTIAL_ANTIC_LENGTH);
old_PA_IN = PA_OUT = NULL;
if (block_has_abnormal_pred_edge)
goto maybe_dump_sets;
+ /* If there are too many partially anticipatable values in the
+ block, phi_translate_set can take an exponential time: stop
+ before the translation starts. */
+ if (max_pa
+ && single_succ_p (block)
+ && bitmap_count_bits (PA_IN (single_succ (block))->values) > max_pa)
+ goto maybe_dump_sets;
+
old_PA_IN = PA_IN (block);
PA_OUT = bitmap_set_new ();
}
/* Return true if OP is an exception handler related operation, such as
- FILTER_EXPRor EXC_PTR_EXPR. */
+ FILTER_EXPR or EXC_PTR_EXPR. */
static bool
is_exception_related (tree op)
static bool
can_value_number_operation (tree op)
{
- return (UNARY_CLASS_P (op)
+ return (UNARY_CLASS_P (op)
&& !is_exception_related (TREE_OPERAND (op, 0)))
|| BINARY_CLASS_P (op)
|| COMPARISON_CLASS_P (op)
NECESSARY (temp) = 0;
VN_INFO_GET (PHI_RESULT (temp))->valnum = PHI_RESULT (temp);
-
+
VEC_safe_push (tree, heap, inserted_exprs, temp);
FOR_EACH_EDGE (pred, ei, block->preds)
add_phi_arg (temp, avail[pred->src->index], pred);
}
-/* Return true if VAR is an SSA variable with no defining statement in
- this procedure, *AND* isn't a live-on-entry parameter. */
-
-static bool
-is_undefined_value (tree expr)
-{
- return (TREE_CODE (expr) == SSA_NAME
- && IS_EMPTY_STMT (SSA_NAME_DEF_STMT (expr))
- /* PARM_DECLs and hard registers are always defined. */
- && TREE_CODE (SSA_NAME_VAR (expr)) != PARM_DECL);
-}
-
/* Add OP to EXP_GEN (block), and possibly to the maximal set if it is
- not defined by a phi node.
+ not defined by a phi node.
PHI nodes can't go in the maximal sets because they are not in
TMP_GEN, so it is possible to get into non-monotonic situations
during ANTIC calculation, because it will *add* bits. */
{
if (!in_fre)
{
- if (TREE_CODE (op) == SSA_NAME && is_undefined_value (op))
+ if (TREE_CODE (op) == SSA_NAME && ssa_undefined_value_p (op))
return;
bitmap_value_insert_into_set (EXP_GEN (block), op);
if (TREE_CODE (op) != SSA_NAME
vh = vn_lookup_with_vuses (t, vuses);
else
vh = vn_lookup (t);
-
+
if (!vh)
return NULL;
exprset = VALUE_HANDLE_EXPR_SET (vh);
}
if (TREE_CODE (op) != TREE_LIST)
add_to_exp_gen (block, op);
-
+
if (TREE_CODE (val) == VALUE_HANDLE)
TREE_TYPE (val) = TREE_TYPE (TREE_OPERAND (vexpr, i));
case INTEGER_CST:
case STRING_CST:
case REAL_CST:
+ case FIXED_CST:
case PARM_DECL:
case VAR_DECL:
case RESULT_DECL:
lhs = make_ssa_name (storetemp, new_tree);
GIMPLE_STMT_OPERAND (new_tree, 0) = lhs;
- create_ssa_artificial_load_stmt (new_tree, stmt);
+ create_ssa_artificial_load_stmt (new_tree, stmt, false);
NECESSARY (new_tree) = 0;
VEC_safe_push (tree, heap, inserted_exprs, new_tree);
if (!valvh && !is_invariant)
{
tree defstmt = SSA_NAME_DEF_STMT (val);
-
+
gcc_assert (VN_INFO (val)->valnum == val);
/* PHI nodes can't have vuses and attempts to iterate over
their VUSE operands will crash. */
}
valvh = vn_lookup_or_add_with_stmt (val, defstmt);
}
-
+
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "SCCVN says ");
fprintf (dump_file, ")\n");
}
else
- print_generic_stmt (dump_file, val, 0);
+ print_generic_stmt (dump_file, val, 0);
}
if (valvh)
return valvh;
tree valvh = NULL_TREE;
tree lhsval;
VEC (tree, gc) *vuses = NULL;
-
+
valvh = get_sccvn_value (lhs);
if (valvh)
{
vn_add (lhs, valvh);
- bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
+ bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
/* Shortcut for FRE. We have no need to create value expressions,
just want to know what values are available where. */
if (in_fre)
bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
return true;
}
-
+
lhsval = valvh ? valvh : get_value_handle (lhs);
vuses = copy_vuses_from_stmt (stmt);
STRIP_USELESS_TYPE_CONVERSION (rhs);
tree val = vn_lookup_or_add_with_vuses (newt, vuses);
vn_add (lhs, val);
}
-
+
add_to_exp_gen (block, newt);
- }
-
+ }
+
bitmap_insert_into_set (TMP_GEN (block), lhs);
bitmap_value_insert_into_set (AVAIL_OUT (block), lhs);
return true;
|| TREE_INVARIANT (rhs)
|| DECL_P (rhs))
{
-
+
if (lhsval)
{
set_expression_vuses (rhs, vuses);
AVAIL_OUT (block));
}
/* None of the rest of these can be PRE'd. */
- if (TREE_CODE (rhs) == SSA_NAME && !is_undefined_value (rhs))
+ if (TREE_CODE (rhs) == SSA_NAME && !ssa_undefined_value_p (rhs))
add_to_exp_gen (block, rhs);
return true;
}
tree def = gimple_default_def (cfun, param);
vn_lookup_or_add (def);
- if (!in_fre)
+ if (!in_fre)
{
bitmap_insert_into_set (TMP_GEN (ENTRY_BLOCK_PTR), def);
bitmap_value_insert_into_set (maximal_set, def);
}
else if (TREE_CODE (stmt) == GIMPLE_MODIFY_STMT
- && !ann->has_volatile_ops
- && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == SSA_NAME
- && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI
- (GIMPLE_STMT_OPERAND (stmt, 0)))
+ && !ann->has_volatile_ops
+ && TREE_CODE (GIMPLE_STMT_OPERAND (stmt, 0)) == SSA_NAME
+ && (!SSA_NAME_OCCURS_IN_ABNORMAL_PHI
+ (GIMPLE_STMT_OPERAND (stmt, 0)))
+ && !tree_could_throw_p (stmt))
{
if (make_values_for_stmt (stmt, block))
continue;
sprime = bitmap_find_leader (AVAIL_OUT (b),
get_value_handle (lhs));
-
+
if (sprime
&& sprime != lhs
&& (TREE_CODE (*rhs_p) != SSA_NAME
init_pre (bool do_fre)
{
basic_block bb;
-
+
next_expression_id = 0;
expressions = NULL;
expression_vuses = NULL;
insert_fake_stores ();
/* Collect and value number expressions computed in each basic block. */
- run_scc_vn ();
+ if (!run_scc_vn ())
+ {
+ if (!do_fre)
+ remove_dead_inserted_code ();
+ fini_pre ();
+ return;
+ }
switch_to_PRE_table ();
compute_avail ();
do_pre (void)
{
execute_pre (false);
- return 0;
+ return TODO_rebuild_alias;
}
static bool