/* Representation of expressions on value numbers:
- Expressions consisting of value numbers are represented the same
+ Expressions consisting of value numbers are represented the same
way as our VN internally represents them, with an additional
"pre_expr" wrapping around them in order to facilitate storing all
of the expressions in the same sets. */
static tree
translate_vuse_through_block (VEC (vn_reference_op_s, heap) *operands,
- tree vuse,
+ alias_set_type set, tree type, tree vuse,
basic_block phiblock,
basic_block block)
{
gimple phi = SSA_NAME_DEF_STMT (vuse);
- tree ref;
+ ao_ref ref;
if (gimple_bb (phi) != phiblock)
return vuse;
return PHI_ARG_DEF (phi, e->dest_idx);
}
- if (!(ref = get_ref_from_reference_ops (operands)))
+ if (!ao_ref_init_from_vn_reference (&ref, set, type, operands))
return NULL_TREE;
/* Use the alias-oracle to find either the PHI node in this block,
the first VUSE used in this block that is equivalent to vuse or
the first VUSE which definition in this block kills the value. */
- while (!stmt_may_clobber_ref_p (phi, ref))
+ while (!stmt_may_clobber_ref_p_1 (phi, &ref))
{
vuse = gimple_vuse (phi);
phi = SSA_NAME_DEF_STMT (vuse);
return NULL_TREE;
}
-/* Like find_leader, but checks for the value existing in SET1 *or*
+/* Like bitmap_find_leader, but checks for the value existing in SET1 *or*
SET2. This is used to avoid making a set consisting of the union
of PA_IN and ANTIC_IN during insert. */
case CONSTANT:
return TREE_TYPE (PRE_EXPR_CONSTANT (e));
case REFERENCE:
- {
- vn_reference_op_t vro;
-
- gcc_assert (PRE_EXPR_REFERENCE (e)->operands);
- vro = VEC_index (vn_reference_op_s,
- PRE_EXPR_REFERENCE (e)->operands,
- 0);
- /* We don't store type along with COMPONENT_REF because it is
- always the same as FIELD_DECL's type. */
- if (!vro->type)
- {
- gcc_assert (vro->opcode == COMPONENT_REF);
- return TREE_TYPE (vro->op0);
- }
- return vro->type;
- }
-
+ return PRE_EXPR_REFERENCE (e)->type;
case NARY:
return PRE_EXPR_NARY (e)->type;
}
if (vuse)
{
newvuse = translate_vuse_through_block (newoperands,
+ ref->set, ref->type,
vuse, phiblock, pred);
if (newvuse == NULL_TREE)
{
unsigned int new_val_id;
pre_expr constant;
- tree result = vn_reference_lookup_pieces (newvuse,
+ tree result = vn_reference_lookup_pieces (newvuse, ref->set,
+ ref->type,
newoperands,
&newref, true);
if (newref)
new_val_id = get_next_value_id ();
VEC_safe_grow_cleared (bitmap_set_t, heap, value_expressions,
get_max_value_id() + 1);
- newref = vn_reference_insert_pieces (newvuse,
+ newref = vn_reference_insert_pieces (newvuse, ref->set,
+ ref->type,
newoperands,
result, new_val_id);
newoperands = NULL;
tree vuse = PRE_EXPR_REFERENCE (expr)->vuse;
vn_reference_t refx = PRE_EXPR_REFERENCE (expr);
gimple def;
- tree ref = NULL_TREE;
gimple_stmt_iterator gsi;
unsigned id = get_expression_id (expr);
bool res = false;
+ ao_ref ref;
if (!vuse)
return false;
top of the basic block, a statement uses VUSE there can be no kill
inbetween that use and the original statement that loaded {e, VUSE},
so we can stop walking. */
+ ref.base = NULL_TREE;
for (gsi = gsi_start_bb (block); !gsi_end_p (gsi); gsi_next (&gsi))
{
tree def_vuse, def_vdef;
}
/* Init ref only if we really need it. */
- if (ref == NULL_TREE)
+ if (ref.base == NULL_TREE
+ && !ao_ref_init_from_vn_reference (&ref, refx->set, refx->type,
+ refx->operands))
{
- if (!(ref = get_ref_from_reference_ops (refx->operands)))
- {
- res = true;
- break;
- }
+ res = true;
+ break;
}
/* If the statement may clobber expr, it dies. */
- if (stmt_may_clobber_ref_p (def, ref))
+ if (stmt_may_clobber_ref_p_1 (def, &ref))
{
res = true;
break;
|| gimple_assign_rhs_code (stmt) == EXC_PTR_EXPR));
}
-/* Return true if OP is a tree which we can perform PRE on
- on. This may not match the operations we can value number, but in
+/* Return true if OP is a tree which we can perform PRE on.
+ This may not match the operations we can value number, but in
a perfect world would. */
static bool
return folded;
}
break;
+ case TARGET_MEM_REF:
+ {
+ vn_reference_op_t nextop = VEC_index (vn_reference_op_s, ref->operands,
+ *operand);
+ pre_expr op0expr;
+ tree genop0 = NULL_TREE;
+ tree baseop = create_component_ref_by_pieces_1 (block, ref, operand,
+ stmts, domstmt);
+ if (!baseop)
+ return NULL_TREE;
+ if (currop->op0)
+ {
+ op0expr = get_or_alloc_expr_for (currop->op0);
+ genop0 = find_or_generate_expression (block, op0expr,
+ stmts, domstmt);
+ if (!genop0)
+ return NULL_TREE;
+ }
+ if (DECL_P (baseop))
+ return build6 (TARGET_MEM_REF, currop->type,
+ baseop, NULL_TREE,
+ genop0, currop->op1, currop->op2,
+ unshare_expr (nextop->op1));
+ else
+ return build6 (TARGET_MEM_REF, currop->type,
+ NULL_TREE, baseop,
+ genop0, currop->op1, currop->op2,
+ unshare_expr (nextop->op1));
+ }
+ break;
case ADDR_EXPR:
if (currop->op0)
{
gimple_seq *stmts, gimple domstmt, tree type)
{
tree temp, name;
- tree folded, newexpr;
- gimple_seq forced_stmts;
+ tree folded;
+ gimple_seq forced_stmts = NULL;
unsigned int value_id;
gimple_stmt_iterator gsi;
tree exprtype = type ? type : get_expr_type (expr);
default:
return NULL_TREE;
}
- folded = fold_convert (exprtype, folded);
+
+ if (!useless_type_conversion_p (exprtype, TREE_TYPE (folded)))
+ folded = fold_convert (exprtype, folded);
+
/* Force the generated expression to be a sequence of GIMPLE
statements.
We have to call unshare_expr because force_gimple_operand may
modify the tree we pass to it. */
- newexpr = force_gimple_operand (unshare_expr (folded), &forced_stmts,
- false, NULL);
+ folded = force_gimple_operand (unshare_expr (folded), &forced_stmts,
+ false, NULL);
/* If we have any intermediate expressions to the value sets, add them
to the value sets and chain them in the instruction stream. */
|| TREE_CODE (exprtype) == VECTOR_TYPE)
DECL_GIMPLE_REG_P (temp) = 1;
- newstmt = gimple_build_assign (temp, newexpr);
+ newstmt = gimple_build_assign (temp, folded);
name = make_ssa_name (temp, newstmt);
gimple_assign_set_lhs (newstmt, name);
gimple_set_plf (newstmt, NECESSARY, false);
continue;
copy_reference_ops_from_call (stmt, &ops);
- vn_reference_lookup_pieces (gimple_vuse (stmt),
+ vn_reference_lookup_pieces (gimple_vuse (stmt), 0,
+ gimple_expr_type (stmt),
ops, &ref, false);
VEC_free (vn_reference_op_s, heap, ops);
if (!ref)
value is constant, use that constant. */
if (!sprime && is_gimple_min_invariant (VN_INFO (lhs)->valnum))
{
- sprime = fold_convert (TREE_TYPE (lhs),
- VN_INFO (lhs)->valnum);
+ sprime = VN_INFO (lhs)->valnum;
+ if (!useless_type_conversion_p (TREE_TYPE (lhs),
+ TREE_TYPE (sprime)))
+ sprime = fold_convert (TREE_TYPE (lhs), sprime);
if (dump_file && (dump_flags & TDF_DETAILS))
{
update_stmt (stmt);
if (maybe_clean_or_replace_eh_stmt (stmt, stmt))
gimple_purge_dead_eh_edges (b);
+
+ /* Changing an indirect call to a direct call may
+ have exposed different semantics. This may
+ require an SSA update. */
+ todo |= TODO_update_ssa_only_virtuals;
}
}
}
remove_phi_node (&gsi, false);
+ if (!useless_type_conversion_p (TREE_TYPE (res), TREE_TYPE (sprime)))
+ sprime = fold_convert (TREE_TYPE (res), sprime);
stmt = gimple_build_assign (res, sprime);
SSA_NAME_DEF_STMT (res) = stmt;
if (TREE_CODE (sprime) == SSA_NAME)
/* If there is a single use only, propagate the equivalency
instead of keeping the copy. */
if (TREE_CODE (lhs) == SSA_NAME
- && single_imm_use (lhs, &use_p, &use_stmt))
+ && single_imm_use (lhs, &use_p, &use_stmt)
+ && may_propagate_copy (USE_FROM_PTR (use_p),
+ gimple_assign_rhs1 (stmt)))
{
SET_USE (use_p, gimple_assign_rhs1 (stmt));
- update_stmt (stmt);
+ update_stmt (use_stmt);
}
/* If this is a store or a now unused copy, remove it. */
0, /* static_pass_number */
TV_TREE_PRE, /* tv_id */
PROP_no_crit_edges | PROP_cfg
- | PROP_ssa | PROP_alias, /* properties_required */
+ | PROP_ssa, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
TODO_rebuild_alias, /* todo_flags_start */
NULL, /* next */
0, /* static_pass_number */
TV_TREE_FRE, /* tv_id */
- PROP_cfg | PROP_ssa | PROP_alias, /* properties_required */
+ PROP_cfg | PROP_ssa, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */