slot = htab_find_slot_with_hash (phi_translate_table, new_pair,
new_pair->hashcode, INSERT);
- if (*slot)
- free (*slot);
+ free (*slot);
*slot = (void *) new_pair;
}
tree result = vn_reference_lookup_pieces (newvuse, ref->set,
ref->type,
newoperands,
- &newref, true);
+ &newref, VN_WALK);
if (result)
VEC_free (vn_reference_op_s, heap, newoperands);
result = fold_build1 (VIEW_CONVERT_EXPR, ref->type, result);
converted = true;
}
+ else if (!result && newref
+ && !useless_type_conversion_p (ref->type, newref->type))
+ {
+ VEC_free (vn_reference_op_s, heap, newoperands);
+ return NULL;
+ }
if (result && is_gimple_min_invariant (result))
{
{
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Starting iteration %d\n", num_iterations);
+ /* ??? We need to clear our PHI translation cache here as the
+ ANTIC sets shrink and we restrict valid translations to
+ those having operands with leaders in ANTIC. Same below
+ for PA ANTIC computation. */
num_iterations++;
changed = false;
for (i = n_basic_blocks - NUM_FIXED_BLOCKS - 1; i >= 0; i--)
}
/* Return true if we can value number the call in STMT. This is true
- if we have a pure or constant call. */
+ if we have a pure or constant call to a real function. */
static bool
can_value_number_call (gimple stmt)
{
+ if (gimple_call_internal_p (stmt))
+ return false;
if (gimple_call_flags (stmt) & (ECF_PURE | ECF_CONST))
return true;
return false;
return NULL_TREE;
if (genop2)
{
- /* Drop zero minimum index. */
- if (tree_int_cst_equal (genop2, integer_zero_node))
+ tree domain_type = TYPE_DOMAIN (TREE_TYPE (genop0));
+ /* Drop zero minimum index if redundant. */
+ if (integer_zerop (genop2)
+ && (!domain_type
+ || integer_zerop (TYPE_MIN_VALUE (domain_type))))
genop2 = NULL_TREE;
else
{
already existing along every predecessor, and
it's defined by some predecessor, it is
partially redundant. */
- if (!cant_insert && !all_same && by_some && do_insertion
- && dbg_cnt (treepre_insert))
+ if (!cant_insert && !all_same && by_some)
{
- if (insert_into_preds_of_block (block, get_expression_id (expr),
- avail))
+ if (!do_insertion)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Skipping partial redundancy for "
+ "expression ");
+ print_pre_expr (dump_file, expr);
+ fprintf (dump_file, " (%04d), no redundancy on to be "
+ "optimized for speed edge\n", val);
+ }
+ }
+ else if (dbg_cnt (treepre_insert)
+ && insert_into_preds_of_block (block,
+ get_expression_id (expr),
+ avail))
new_stuff = true;
}
/* If all edges produce the same value and that value is
copy_reference_ops_from_call (stmt, &ops);
vn_reference_lookup_pieces (gimple_vuse (stmt), 0,
gimple_expr_type (stmt),
- ops, &ref, false);
+ ops, &ref, VN_NOWALK);
VEC_free (vn_reference_op_s, heap, ops);
if (!ref)
continue;
vn_reference_lookup (gimple_assign_rhs1 (stmt),
gimple_vuse (stmt),
- true, &ref);
+ VN_WALK, &ref);
if (!ref)
continue;
tree rhs = gimple_assign_rhs1 (stmt);
tree val;
val = vn_reference_lookup (gimple_assign_lhs (stmt),
- gimple_vuse (stmt), true, NULL);
+ gimple_vuse (stmt), VN_WALK, NULL);
if (TREE_CODE (rhs) == SSA_NAME)
rhs = VN_INFO (rhs)->valnum;
if (val
}
/* Visit indirect calls and turn them into direct calls if
possible. */
- if (is_gimple_call (stmt)
- && TREE_CODE (gimple_call_fn (stmt)) == SSA_NAME)
+ if (is_gimple_call (stmt))
{
- tree fn = VN_INFO (gimple_call_fn (stmt))->valnum;
- if (TREE_CODE (fn) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
+ tree orig_fn = gimple_call_fn (stmt);
+ tree fn;
+ if (!orig_fn)
+ continue;
+ if (TREE_CODE (orig_fn) == SSA_NAME)
+ fn = VN_INFO (orig_fn)->valnum;
+ else if (TREE_CODE (orig_fn) == OBJ_TYPE_REF
+ && TREE_CODE (OBJ_TYPE_REF_EXPR (orig_fn)) == SSA_NAME)
+ fn = VN_INFO (OBJ_TYPE_REF_EXPR (orig_fn))->valnum;
+ else
+ continue;
+ if (gimple_call_addr_fndecl (fn) != NULL_TREE
+ && useless_type_conversion_p (TREE_TYPE (orig_fn),
+ TREE_TYPE (fn)))
{
bool can_make_abnormal_goto
= stmt_can_make_abnormal_goto (stmt);
+ bool was_noreturn = gimple_call_noreturn_p (stmt);
if (dump_file && (dump_flags & TDF_DETAILS))
{
gimple_call_set_fn (stmt, fn);
update_stmt (stmt);
+ /* When changing a call into a noreturn call, cfg cleanup
+ is needed to fix up the noreturn call. */
+ if (!was_noreturn && gimple_call_noreturn_p (stmt))
+ todo |= TODO_cleanup_cfg;
+
/* If we removed EH side-effects from the statement, clean
its EH information. */
if (maybe_clean_or_replace_eh_stmt (stmt, stmt))
if (!do_fre)
loop_optimizer_init (LOOPS_NORMAL);
- if (!run_scc_vn ())
+ if (!run_scc_vn (do_fre ? VN_WALKREWRITE : VN_WALK))
{
if (!do_fre)
loop_optimizer_finalize ();
clear_expression_ids ();
free_scc_vn ();
if (!do_fre)
- remove_dead_inserted_code ();
+ {
+ remove_dead_inserted_code ();
+ todo |= TODO_verify_flow;
+ }
scev_finalize ();
fini_pre (do_fre);