Commit f430bae8 by Andrew MacLeod Committed by Andrew Macleod

lambda-code.c (lambda_loopnest_to_gcc_loopnest): Use update_stmt.



2005-04-05  Andrew MacLeod  <amacleod@redhat.com>

	* lambda-code.c (lambda_loopnest_to_gcc_loopnest): Use update_stmt.
	Use immediate use iterator.
	(stmt_is_bumper_for_loop): Use immediate use iterator.
	* predict.c (strip_builtin_expect): Use update_stmt.
	* tree-cfg.c (update_modified_stmts): New. Call update_stmt_if_modified
	on all elements of a STATEMENT_LIST.
	(bsi_insert_before, bsi_insert_after): Call update_modified_stmts.
	(bsi_remove): Remove imm_use links and mark the stmt as modified.
	(bsi_replace): Mark stmt as modified and the update it.
	* tree-complex.c (update_complex_assignment): Call mark_stmt_modified.
	(expand_complex_libcal): Call update_stmt.
	(expand_complex_comparison): Call mark_stmt_modified.
	(expand_complex_operations_1): Call update_stmt_if_modified.
	(expand_vector_operations_1): Call mark_stmt_modified.
	* tree-dfa.c (compute_immediate_uses, free_df_for_stmt, free_df,
	compute_immediate_uses_for_phi, compute_immediate_uses_for_stmt,
	add_immediate_use, redirect_immediate_use,
	redirect_immediate_uses, dump_immediate_uses, debug_immediate_uses,
	dump_immediate_uses_for, debug_immediate_uses_for): Delete.
	(mark_new_vars_to_rename): Call update_stmt.
	* tree-dump.c (dump_option_value_in): Add "stmtaddr".
	* tree-flow-inline.h (modify_stmt): Rename to mark_stmt_modified.
	Ignore PHI nodes.
	(unmodify_stmt): Delete.
	(update_stmt): New.  Force an update of a stmt.
	(update_stmt_if_modified): update a stmt if it is out of date.
	(get_stmt_operands): Verify stmt is NOT modified.
	(stmt_modified_p): Update comment.
	(delink_imm_use): Remove a use node from its immuse list.
	(link_imm_use_to_list): Link a use node to a specific list.
	(link_imm_use): Link a node to the correct list.
	(set_ssa_use_from_ptr): Set a use node to a specific value, and insert
	it in the correct list, if appropriate.
	(link_imm_use_stmt): Link a use node, and set the stmt pointer.
	(relink_imm_use): Link a use node in place of another node in a list.
	(relink_imm_use_stmt): LInk a node in place of another node, and set
	the stmt pointer.
	(end_safe_imm_use_traverse): New.  Terminate a safe immuse iterator.
	(end_safe_imm_use_p): New.  Check for the end of a safe immuse iterator.
	(first_safe_imm_use): New.  Initialize a safe immuse iterator.
	(next_safe_imm_use): New.  Proceed to next safe immuse iterator value.
	(end_readonly_imm_use_p): New.  Check for end of a fast immuse iterator.
	(first_readonly_imm_use): New.  Initialize a fast immuse iterator.
	(next_readonly_imm_use): New.  Get the next fast immuse iterator value.
	(has_zero_uses): New.  Return true if there are no uses of a var.
	(has_single_use): New.  Return true if there is only a single use of a
	variable.
	(single_imm_use): New.  Return the simgle immediate use.
	(num_imm_uses): New.  Return the number of immediate uses.
	(get_v_must_def_ops): Use is now a pointer.
	(use_operand_p, get_v_may_def_op_ptr, get_vuse_op_ptr,
	get_v_must_def_kill_ptr, get_phi_arg_def_ptr): Return the address of
	the use node.
	(get_immediate_uses, num_immediate_uses, immediate_use): Delete.
	(delink_stmt_imm_use): Delink all immuses from a stmt.
	(phi_arg_index_from_use): New.  Return a phi arg index for a use.
	* tree-flow.h (struct dataflow_d): Delete.
	(immediate_use_iterator_d): New.  Immediate use iterator struct.
	(FOR_EACH_IMM_USE_FAST): New.  Macro for read only immuse iteration.
	(FOR_EACH_IMM_USE_SAFE): New.  Macro for write-safe immuse iteration.
	(BREAK_FROM_SAFE_IMM_USE): New.  Macro for earlyu exit from write-safe
	iteration.
	(struct stmt_ann_d): Remove dataflow_t from struct.
	* tree-if-conv.c (tree_if_conversion).  Don't call free_df.
	(if_convertible_phi_p): Use FAST immuse iterator.
	(if_convertible_loop_p): Don't call compute_immediate_uses.
	(replace_phi_with_cond_modify_expr): Call update_stmt.
	* tree-into-ssa.c (mark_def_sites, ssa_mark_def_sites): Call
	update_stmt_if_modified.
	(rewrite_all_into_ssa): Initialize ssa operands.
	* tree-loop-linear.c (linear_transform_loops): Don't call free_df or
	compute_immediate_uses.
	* tree-optimize.c (execute_todo): Call verify_ssa whenever the
	ssa_property is available.
	(execute_one_pass):  Change parameters passed to execute_todo.
	* tree-outof-ssa.c (rewrite_trees): Don't call modify_stmt.
	(remove_ssa_form): Call fini_ssa_operands.
	(insert_backedge_copies): Delete call to modify_stmt.
	* tree-phinodes.c (make_phi_node): Initialize use nodes.
	(release_phi_node): Delink any use nodes before releasing.
	(resize_phi_node): Relink any use nodes.
	(remove_phi_arg_num): Delink the use node.
	(remove_phi_node): Release the ssa_name AFTER releasing the phi node.
	(remove_all_phi_nodes_for): Release phi node first.
	* tree-pretty-print.c (dump_generic_node): Print stmt address.
	* tree-sra.c (mark_all_v_defs): Call update_stmt_if_modified.
	(scalarize_use, scalarize_copy): Call update_stmt.
	* tree-ssa-alias.c (compute_may_aliases): Update all modified stmts.
	(compute_points_to_and_addr_escape): Call mark_stmt_modified.
	* tree-ssa-cpp.c (need_imm_uses_for): Delete.
	(ccp_initialize): Remove call to compute_immediate_uses.
	(substitute_and_fold, execute_fold_all_builtins): Call update_stmt.
	* tree-ssa-dom.c (tree_ssa_dominator_optimize): Update all modified
	stmts.
	(simplify_cond_and_lookup_avail_expr): Call mark_stmt_modified.
	(simplify_switch_and_lookup_avail_expr): Call mark_stmt_modified.
	(eliminate_redundant_computations): Call mark_stmt_modified.
	(cprop_operand): Call mark_stmt_modified.
	(optimize_stmt): Call update_stmt_if_modified and mark_stmt_modified.
	* tree-ssa-dse.c (fix_phi_uses, fix_stmt_v_may_defs): Delete.
	(dse_optimize_stmt): Use new immuse interface.
	(tree_ssa_dse): Remove calls to compute_immediate_uses and free_df.
	* tree-ssa-forwprop.c (need_imm_uses_for): Delete.
	(substitute_single_use_vars): Use new immuse interface.
	(tree_ssa_forward_propagate_single_use_vars): Remove calls to free_df
	and compute_immediate_uses.
	* tree-ssa-loop-im.c (single_reachable_address): Use new immuse
	interface.
	(rewrite_mem_refs): Call update_stmt.
	(determine_lsm): Remove call to compute_imm_uses and free_df.
	* tree-ssa-loop-ivcanon.c (create_canonical_iv): Call update_stmt.
	(try_unroll_loop_completely): Call update_stmt.
	* tree-ssa-loop-ivopts.c (rewrite_address_base): Call update_stmt.
	(rewrite_use_compare): Call update_stmt.
	(compute_phi_arg_on_exit): Insert each stmt before trying to process.
	(rewrite_use) : Call update_stmt.
	* tree-ssa-loop-manip.c (verify_loop_closed_ssa): Add arg to call.
	* tree-ssa-loop-unswitch.c (tree_unswitch_single_loop): Call
	update_stmt.
	* tree-ssa-operands.c (NULL_USE_OPERAND_P): Remove declaration.
	(allocate_use_optype, allocate_vuse_optype): Adjust allocation size.
	(free_uses, free_vuses, free_v_may_defs, free_v_must_defs): Delink
	use nodes.
	(initialize_vuse_operand): New.  Initialize a vuse operand.
	(initialize_v_may_def_operand): New.  Initialize a maydef operand.
	(initialize_v_must_def_operand): New.  Initialize a mustdef operand.
	(finalize_ssa_defs): Use stmt parameter.
	(correct_use_link): Ensure a use node is in the correct list, and has
	the correct stmt pointer.
	(finalize_ssa_uses, finalize_ssa_v_may_defs, finalize_ssa_vuses,
	finalize_ssa_v_must_defs): Also initialize use nodes.
	(finalize_ssa_stmt_operands): Pass extra stmt operands.
	(build_ssa_operands): Seperate parsing from final operand construction.
	(parse_ssa_operands): New.  Parse entry point for operand building.
	(swap_tree_operands): New.  Swap 2 tree operands.
	(update_stmt_operands): Ranamed from get_stmt_operands.  Always builds
	operands.
	(get_expr_operands): Call swap_tree_operands when needed.
	(copy_virtual_operands): Use initialize routines for virtual use ops.
	(create_ssa_artficial_load_stmt): Add extra stmt parameter.
	(verify_abort): New.  Issue imm_use error.
	(verify_imm_links): New Verify imm_use links for a var.
	(dump_immediate_uses_for): New.  Dump imm_uses for a var to file.
	(dump_immediate_uses): New.  Dump imm_uses for all vars to file.
	(debug_immediate_uses): New.  Dump imm_uses for all vars to stderr.
	(debug_immediate_uses_for): New.  Dump imm_uses for a var to stderr.
	* tree-ssa-operands.h (struct use_operand_ptr): Delete.
	(NULL_USE_OPERAND_P) Define.
	(use_optype_d, v_def_use_operand_type, vuse_optype_d): Add immediate
	use node.
	(struct vuse_operand_type): New struct.
	(SET_USE): Call set_ssa_use_from_ptr.
	(USE_STMT): Define.
	(PHI_ARG_INDEX_FROM_USE): Define.
	* tree-ssa-phiopt.c (replace_phi_edge_with_variable): Set the phi
	argument via SET_USE, not PHI_ARG_DEF_TREE.
	* tree-ssa-pre.c (eliminate): Call update_stmt.
	* tree-ssa-propagate.c (cfg_blocks_get): Use imm_use iterators.  Don't
	call free_df.
	* tree-ssa-sink.c (all_immediate_uses_same_place): Use imm_use iterator.
	(nearest_common_dominator_of_uses): Use imm_use iterator.
	(statement_sink_location): Use imm_use iterator and interface.
	(execute_sink_code): Don't call compute_immediate_uses or free-df.
	* tree-ssa-threadupdate.c (create_edge_and_update_destination_phis): Use
	PHI_ARG_DEF, not PHI_ARG_DEF_TREE.
	* tree-ssa.c (verify_use, verify_phi_args): Verify some imm_use info.
	(verify_ssa): Ensure no stmt is marked modify after optimization pass
	if new parameter is true.
	(init_tree_ssa): Don't initialize operand cache here.
	(delete_tree_ssa): Don't destroy operand cache here.
	(propagate_into_addr): Pass in a use pointer, return true if anything
	was changed.
	(replace_immediate_uses): Use imm_use iterator, call update_stmt.
	(check_phi_redundancy): Use imm_use iterator.
	(kill_redundant_phi_nodes): Don't call compute_immediate_uses or
	free_df.
	* tree-ssanames.c (make_ssa_name): Initialize imm_use node.
	(release_ssa_name): Delink node and all elements in its imm_use list.
	* tree-tailcall.c (adjust_return_value): Call update_stmt.
	* tree-vect-analyze.c (vect_stmt_relevant_p): Use imm_use iterator.
	* tree-vectorizer.c (need_imm_uses_for): Delete.
	(vectorize_loops): Dont call compute_immediate_uses or free_df.
	* tree.h (struct ssa_imm_use_d): Define.
	(SSA_NAME_IMM_USE_NODE): Define.
	(struct tree_ssa_name): Add imm_use node.
	(PHI_DF): Delete.
	(PHI_ARG_IMM_USE_NODE): Define.
	(struct phi_arg_d): Add imm_use node.
	(struct tree_phi_node): Remove struct dataflow_d element.
	(TDF_STMTADDR): Define.

From-SVN: r97648
parent 7701dad7
...@@ -1939,7 +1939,7 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest, ...@@ -1939,7 +1939,7 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
COND_EXPR_COND (exitcond) = build (testtype, COND_EXPR_COND (exitcond) = build (testtype,
boolean_type_node, boolean_type_node,
newupperbound, ivvarinced); newupperbound, ivvarinced);
modify_stmt (exitcond); update_stmt (exitcond);
VEC_replace (tree, new_ivs, i, ivvar); VEC_replace (tree, new_ivs, i, ivvar);
i++; i++;
...@@ -1951,11 +1951,21 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest, ...@@ -1951,11 +1951,21 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
for (i = 0; VEC_iterate (tree, old_ivs, i, oldiv); i++) for (i = 0; VEC_iterate (tree, old_ivs, i, oldiv); i++)
{ {
int j; imm_use_iterator imm_iter;
dataflow_t imm = get_immediate_uses (SSA_NAME_DEF_STMT (oldiv)); use_operand_p imm_use;
for (j = 0; j < num_immediate_uses (imm); j++) tree oldiv_def;
tree oldiv_stmt = SSA_NAME_DEF_STMT (oldiv);
gcc_assert (TREE_CODE (oldiv_stmt) == PHI_NODE
|| NUM_DEFS (STMT_DEF_OPS (oldiv_stmt)) == 1);
if (TREE_CODE (oldiv_stmt) == PHI_NODE)
oldiv_def = PHI_RESULT (oldiv_stmt);
else
oldiv_def = DEF_OP (STMT_DEF_OPS (oldiv_stmt), 0);
FOR_EACH_IMM_USE_SAFE (imm_use, imm_iter, oldiv_def)
{ {
tree stmt = immediate_use (imm, j); tree stmt = USE_STMT (imm_use);
use_operand_p use_p; use_operand_p use_p;
ssa_op_iter iter; ssa_op_iter iter;
gcc_assert (TREE_CODE (stmt) != PHI_NODE); gcc_assert (TREE_CODE (stmt) != PHI_NODE);
...@@ -1980,7 +1990,7 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest, ...@@ -1980,7 +1990,7 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
expression. */ expression. */
bsi_insert_before (&bsi, stmts, BSI_SAME_STMT); bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
propagate_value (use_p, newiv); propagate_value (use_p, newiv);
modify_stmt (stmt); update_stmt (stmt);
} }
} }
...@@ -2067,16 +2077,15 @@ stmt_is_bumper_for_loop (struct loop *loop, tree stmt) ...@@ -2067,16 +2077,15 @@ stmt_is_bumper_for_loop (struct loop *loop, tree stmt)
tree use; tree use;
tree def; tree def;
def_optype defs = STMT_DEF_OPS (stmt); def_optype defs = STMT_DEF_OPS (stmt);
dataflow_t imm; imm_use_iterator iter;
int i; use_operand_p use_p;
if (NUM_DEFS (defs) != 1) if (NUM_DEFS (defs) != 1)
return false; return false;
def = DEF_OP (defs, 0); def = DEF_OP (defs, 0);
imm = get_immediate_uses (stmt); FOR_EACH_IMM_USE_FAST (use_p, iter, def)
for (i = 0; i < num_immediate_uses (imm); i++)
{ {
use = immediate_use (imm, i); use = USE_STMT (use_p);
if (TREE_CODE (use) == PHI_NODE) if (TREE_CODE (use) == PHI_NODE)
{ {
if (phi_loop_edge_uses_def (loop, use, def)) if (phi_loop_edge_uses_def (loop, use, def))
......
...@@ -1013,7 +1013,7 @@ strip_builtin_expect (void) ...@@ -1013,7 +1013,7 @@ strip_builtin_expect (void)
&& TREE_CHAIN (arglist)) && TREE_CHAIN (arglist))
{ {
TREE_OPERAND (stmt, 1) = TREE_VALUE (arglist); TREE_OPERAND (stmt, 1) = TREE_VALUE (arglist);
modify_stmt (stmt); update_stmt (stmt);
} }
} }
} }
......
...@@ -3023,6 +3023,24 @@ bsi_for_stmt (tree stmt) ...@@ -3023,6 +3023,24 @@ bsi_for_stmt (tree stmt)
gcc_unreachable (); gcc_unreachable ();
} }
/* Mark statement T as modified, and update it. */
static inline void
update_modified_stmts (tree t)
{
if (TREE_CODE (t) == STATEMENT_LIST)
{
tree_stmt_iterator i;
tree stmt;
for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
{
stmt = tsi_stmt (i);
update_stmt_if_modified (stmt);
}
}
else
update_stmt_if_modified (t);
}
/* Insert statement (or statement list) T before the statement /* Insert statement (or statement list) T before the statement
pointed-to by iterator I. M specifies how to update iterator I pointed-to by iterator I. M specifies how to update iterator I
after insertion (see enum bsi_iterator_update). */ after insertion (see enum bsi_iterator_update). */
...@@ -3031,8 +3049,8 @@ void ...@@ -3031,8 +3049,8 @@ void
bsi_insert_before (block_stmt_iterator *i, tree t, enum bsi_iterator_update m) bsi_insert_before (block_stmt_iterator *i, tree t, enum bsi_iterator_update m)
{ {
set_bb_for_stmt (t, i->bb); set_bb_for_stmt (t, i->bb);
update_modified_stmts (t);
tsi_link_before (&i->tsi, t, m); tsi_link_before (&i->tsi, t, m);
modify_stmt (t);
} }
...@@ -3044,8 +3062,8 @@ void ...@@ -3044,8 +3062,8 @@ void
bsi_insert_after (block_stmt_iterator *i, tree t, enum bsi_iterator_update m) bsi_insert_after (block_stmt_iterator *i, tree t, enum bsi_iterator_update m)
{ {
set_bb_for_stmt (t, i->bb); set_bb_for_stmt (t, i->bb);
update_modified_stmts (t);
tsi_link_after (&i->tsi, t, m); tsi_link_after (&i->tsi, t, m);
modify_stmt (t);
} }
...@@ -3057,7 +3075,9 @@ bsi_remove (block_stmt_iterator *i) ...@@ -3057,7 +3075,9 @@ bsi_remove (block_stmt_iterator *i)
{ {
tree t = bsi_stmt (*i); tree t = bsi_stmt (*i);
set_bb_for_stmt (t, NULL); set_bb_for_stmt (t, NULL);
delink_stmt_imm_use (t);
tsi_delink (&i->tsi); tsi_delink (&i->tsi);
mark_stmt_modified (t);
} }
...@@ -3121,7 +3141,8 @@ bsi_replace (const block_stmt_iterator *bsi, tree stmt, bool preserve_eh_info) ...@@ -3121,7 +3141,8 @@ bsi_replace (const block_stmt_iterator *bsi, tree stmt, bool preserve_eh_info)
} }
*bsi_stmt_ptr (*bsi) = stmt; *bsi_stmt_ptr (*bsi) = stmt;
modify_stmt (stmt); mark_stmt_modified (stmt);
update_modified_stmts (stmt);
} }
......
...@@ -84,7 +84,7 @@ update_complex_assignment (block_stmt_iterator *bsi, tree r, tree i) ...@@ -84,7 +84,7 @@ update_complex_assignment (block_stmt_iterator *bsi, tree r, tree i)
type = TREE_TYPE (TREE_OPERAND (stmt, 1)); type = TREE_TYPE (TREE_OPERAND (stmt, 1));
TREE_OPERAND (stmt, 1) = build (COMPLEX_EXPR, type, r, i); TREE_OPERAND (stmt, 1) = build (COMPLEX_EXPR, type, r, i);
modify_stmt (stmt); mark_stmt_modified (stmt);
} }
/* Expand complex addition to scalars: /* Expand complex addition to scalars:
...@@ -136,7 +136,7 @@ expand_complex_libcall (block_stmt_iterator *bsi, tree ar, tree ai, ...@@ -136,7 +136,7 @@ expand_complex_libcall (block_stmt_iterator *bsi, tree ar, tree ai,
TREE_OPERAND (stmt, 1) TREE_OPERAND (stmt, 1)
= build3 (CALL_EXPR, type, build_fold_addr_expr (fn), args, NULL); = build3 (CALL_EXPR, type, build_fold_addr_expr (fn), args, NULL);
modify_stmt (stmt); update_stmt (stmt);
} }
/* Expand complex multiplication to scalars: /* Expand complex multiplication to scalars:
...@@ -439,7 +439,7 @@ expand_complex_comparison (block_stmt_iterator *bsi, tree ar, tree ai, ...@@ -439,7 +439,7 @@ expand_complex_comparison (block_stmt_iterator *bsi, tree ar, tree ai,
gcc_unreachable (); gcc_unreachable ();
} }
modify_stmt (stmt); mark_stmt_modified (stmt);
} }
/* Process one statement. If we identify a complex operation, expand it. */ /* Process one statement. If we identify a complex operation, expand it. */
...@@ -561,6 +561,7 @@ expand_complex_operations_1 (block_stmt_iterator *bsi) ...@@ -561,6 +561,7 @@ expand_complex_operations_1 (block_stmt_iterator *bsi)
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
update_stmt_if_modified (stmt);
} }
/* Build a constant of type TYPE, made of VALUE's bits replicated /* Build a constant of type TYPE, made of VALUE's bits replicated
...@@ -931,7 +932,7 @@ expand_vector_operations_1 (block_stmt_iterator *bsi) ...@@ -931,7 +932,7 @@ expand_vector_operations_1 (block_stmt_iterator *bsi)
*p_rhs = expand_vector_addition (bsi, do_binop, do_plus_minus, type, *p_rhs = expand_vector_addition (bsi, do_binop, do_plus_minus, type,
TREE_OPERAND (rhs, 0), TREE_OPERAND (rhs, 0),
TREE_OPERAND (rhs, 1), code); TREE_OPERAND (rhs, 1), code);
modify_stmt (bsi_stmt (*bsi)); mark_stmt_modified (bsi_stmt (*bsi));
return; return;
case NEGATE_EXPR: case NEGATE_EXPR:
...@@ -941,7 +942,7 @@ expand_vector_operations_1 (block_stmt_iterator *bsi) ...@@ -941,7 +942,7 @@ expand_vector_operations_1 (block_stmt_iterator *bsi)
*p_rhs = expand_vector_addition (bsi, do_unop, do_negate, type, *p_rhs = expand_vector_addition (bsi, do_unop, do_negate, type,
TREE_OPERAND (rhs, 0), TREE_OPERAND (rhs, 0),
NULL_TREE, code); NULL_TREE, code);
modify_stmt (bsi_stmt (*bsi)); mark_stmt_modified (bsi_stmt (*bsi));
return; return;
case BIT_AND_EXPR: case BIT_AND_EXPR:
...@@ -950,14 +951,14 @@ expand_vector_operations_1 (block_stmt_iterator *bsi) ...@@ -950,14 +951,14 @@ expand_vector_operations_1 (block_stmt_iterator *bsi)
*p_rhs = expand_vector_parallel (bsi, do_binop, type, *p_rhs = expand_vector_parallel (bsi, do_binop, type,
TREE_OPERAND (rhs, 0), TREE_OPERAND (rhs, 0),
TREE_OPERAND (rhs, 1), code); TREE_OPERAND (rhs, 1), code);
modify_stmt (bsi_stmt (*bsi)); mark_stmt_modified (bsi_stmt (*bsi));
return; return;
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
*p_rhs = expand_vector_parallel (bsi, do_unop, type, *p_rhs = expand_vector_parallel (bsi, do_unop, type,
TREE_OPERAND (rhs, 0), TREE_OPERAND (rhs, 0),
NULL_TREE, code); NULL_TREE, code);
modify_stmt (bsi_stmt (*bsi)); mark_stmt_modified (bsi_stmt (*bsi));
return; return;
default: default:
...@@ -973,7 +974,7 @@ expand_vector_operations_1 (block_stmt_iterator *bsi) ...@@ -973,7 +974,7 @@ expand_vector_operations_1 (block_stmt_iterator *bsi)
TREE_OPERAND (rhs, 0), TREE_OPERAND (rhs, 0),
TREE_OPERAND (rhs, 1), code); TREE_OPERAND (rhs, 1), code);
modify_stmt (bsi_stmt (*bsi)); mark_stmt_modified (bsi_stmt (*bsi));
} }
static void static void
......
...@@ -77,11 +77,8 @@ struct walk_state ...@@ -77,11 +77,8 @@ struct walk_state
/* Local functions. */ /* Local functions. */
static void collect_dfa_stats (struct dfa_stats_d *); static void collect_dfa_stats (struct dfa_stats_d *);
static tree collect_dfa_stats_r (tree *, int *, void *); static tree collect_dfa_stats_r (tree *, int *, void *);
static void add_immediate_use (tree, tree);
static tree find_vars_r (tree *, int *, void *); static tree find_vars_r (tree *, int *, void *);
static void add_referenced_var (tree, struct walk_state *); static void add_referenced_var (tree, struct walk_state *);
static void compute_immediate_uses_for_phi (tree, bool (*)(tree));
static void compute_immediate_uses_for_stmt (tree, int, bool (*)(tree));
/* Global declarations. */ /* Global declarations. */
...@@ -141,263 +138,6 @@ struct tree_opt_pass pass_referenced_vars = ...@@ -141,263 +138,6 @@ struct tree_opt_pass pass_referenced_vars =
}; };
/* Compute immediate uses.
CALC_FOR is an optional function pointer which indicates whether
immediate uses information should be calculated for a given SSA
variable. If NULL, then information is computed for all
variables.
FLAGS is one of {TDFA_USE_OPS, TDFA_USE_VOPS}. It is used by
compute_immediate_uses_for_stmt to determine whether to look at
virtual and/or real operands while computing def-use chains. */
void
compute_immediate_uses (int flags, bool (*calc_for)(tree))
{
basic_block bb;
block_stmt_iterator si;
FOR_EACH_BB (bb)
{
tree phi;
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
{
if (is_gimple_reg (PHI_RESULT (phi)))
{
if (!(flags & TDFA_USE_OPS))
continue;
}
else
{
if (!(flags & TDFA_USE_VOPS))
continue;
}
compute_immediate_uses_for_phi (phi, calc_for);
}
for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
{
tree stmt = bsi_stmt (si);
get_stmt_operands (stmt);
compute_immediate_uses_for_stmt (stmt, flags, calc_for);
}
}
}
/* Invalidates dataflow information for a statement STMT. */
void
free_df_for_stmt (tree stmt)
{
dataflow_t *df;
if (TREE_CODE (stmt) == PHI_NODE)
df = &PHI_DF (stmt);
else
{
stmt_ann_t ann = stmt_ann (stmt);
if (!ann)
return;
df = &ann->df;
}
if (!*df)
return;
/* If we have a varray of immediate uses, then go ahead and release
it for re-use. */
if ((*df)->immediate_uses)
ggc_free ((*df)->immediate_uses);
/* Similarly for the main dataflow structure. */
ggc_free (*df);
*df = NULL;
}
/* Invalidate dataflow information for the whole function.
Note this only invalidates dataflow information on statements and
PHI nodes which are reachable.
A deleted statement may still have attached dataflow information
on it. */
void
free_df (void)
{
basic_block bb;
block_stmt_iterator si;
FOR_EACH_BB (bb)
{
tree phi;
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
free_df_for_stmt (phi);
for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
{
tree stmt = bsi_stmt (si);
free_df_for_stmt (stmt);
}
}
}
/* Helper for compute_immediate_uses. Check all the USE and/or VUSE
operands in phi node PHI and add a def-use edge between their
defining statement and PHI. CALC_FOR is as in
compute_immediate_uses.
PHI nodes are easy, we only need to look at their arguments. */
static void
compute_immediate_uses_for_phi (tree phi, bool (*calc_for)(tree))
{
int i;
gcc_assert (TREE_CODE (phi) == PHI_NODE);
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
{
tree arg = PHI_ARG_DEF (phi, i);
if (TREE_CODE (arg) == SSA_NAME && (!calc_for || calc_for (arg)))
{
tree imm_rdef_stmt = SSA_NAME_DEF_STMT (PHI_ARG_DEF (phi, i));
if (!IS_EMPTY_STMT (imm_rdef_stmt))
add_immediate_use (imm_rdef_stmt, phi);
}
}
}
/* Another helper for compute_immediate_uses. Depending on the value
of FLAGS, check all the USE and/or VUSE operands in STMT and add a
def-use edge between their defining statement and STMT. CALC_FOR
is as in compute_immediate_uses. */
static void
compute_immediate_uses_for_stmt (tree stmt, int flags, bool (*calc_for)(tree))
{
tree use;
ssa_op_iter iter;
/* PHI nodes are handled elsewhere. */
gcc_assert (TREE_CODE (stmt) != PHI_NODE);
/* Look at USE_OPS or VUSE_OPS according to FLAGS. */
if (flags & TDFA_USE_OPS)
{
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
{
tree imm_stmt = SSA_NAME_DEF_STMT (use);
if (!IS_EMPTY_STMT (imm_stmt) && (!calc_for || calc_for (use)))
add_immediate_use (imm_stmt, stmt);
}
}
if (flags & TDFA_USE_VOPS)
{
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_VIRTUAL_USES)
{
tree imm_rdef_stmt = SSA_NAME_DEF_STMT (use);
if (!IS_EMPTY_STMT (imm_rdef_stmt) && (!calc_for || calc_for (use)))
add_immediate_use (imm_rdef_stmt, stmt);
}
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_ALL_KILLS)
{
tree imm_rdef_stmt = SSA_NAME_DEF_STMT (use);
if (!IS_EMPTY_STMT (imm_rdef_stmt) && (!calc_for || calc_for (use)))
add_immediate_use (imm_rdef_stmt, stmt);
}
}
}
/* Add statement USE_STMT to the list of statements that use definitions
made by STMT. */
static void
add_immediate_use (tree stmt, tree use_stmt)
{
struct dataflow_d **df;
if (TREE_CODE (stmt) == PHI_NODE)
df = &PHI_DF (stmt);
else
{
stmt_ann_t ann = get_stmt_ann (stmt);
df = &ann->df;
}
if (*df == NULL)
{
*df = ggc_alloc (sizeof (struct dataflow_d));
memset ((void *) *df, 0, sizeof (struct dataflow_d));
(*df)->uses[0] = use_stmt;
return;
}
if (!(*df)->uses[1])
{
(*df)->uses[1] = use_stmt;
return;
}
if ((*df)->immediate_uses == NULL)
VARRAY_TREE_INIT ((*df)->immediate_uses, 4, "immediate_uses");
VARRAY_PUSH_TREE ((*df)->immediate_uses, use_stmt);
}
/* If the immediate use of USE points to OLD, then redirect it to NEW. */
static void
redirect_immediate_use (tree use, tree old, tree new)
{
tree imm_stmt = SSA_NAME_DEF_STMT (use);
struct dataflow_d *df = get_immediate_uses (imm_stmt);
unsigned int num_uses = num_immediate_uses (df);
unsigned int i;
for (i = 0; i < num_uses; i++)
{
if (immediate_use (df, i) == old)
{
if (i == 0 || i == 1)
df->uses[i] = new;
else
VARRAY_TREE (df->immediate_uses, i - 2) = new;
}
}
}
/* Redirect all immediate uses for operands in OLD so that they point
to NEW. This routine should have no knowledge of how immediate
uses are stored. */
void
redirect_immediate_uses (tree old, tree new)
{
ssa_op_iter iter;
tree val;
FOR_EACH_SSA_TREE_OPERAND (val, old, iter, SSA_OP_ALL_USES)
redirect_immediate_use (val, old, new);
}
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Manage annotations Manage annotations
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
...@@ -590,79 +330,6 @@ debug_variable (tree var) ...@@ -590,79 +330,6 @@ debug_variable (tree var)
} }
/* Dump def-use edges on FILE. */
void
dump_immediate_uses (FILE *file)
{
basic_block bb;
block_stmt_iterator si;
const char *funcname
= lang_hooks.decl_printable_name (current_function_decl, 2);
fprintf (file, "\nDef-use edges for function %s\n", funcname);
FOR_EACH_BB (bb)
{
tree phi;
for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
dump_immediate_uses_for (file, phi);
for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
dump_immediate_uses_for (file, bsi_stmt (si));
}
fprintf (file, "\n");
}
/* Dump def-use edges on stderr. */
void
debug_immediate_uses (void)
{
dump_immediate_uses (stderr);
}
/* Dump all immediate uses for STMT on FILE. */
void
dump_immediate_uses_for (FILE *file, tree stmt)
{
dataflow_t df = get_immediate_uses (stmt);
int num_imm_uses = num_immediate_uses (df);
if (num_imm_uses > 0)
{
int i;
fprintf (file, "-> ");
print_generic_stmt (file, stmt, TDF_SLIM);
fprintf (file, "\n");
for (i = 0; i < num_imm_uses; i++)
{
fprintf (file, "\t");
print_generic_stmt (file, immediate_use (df, i), TDF_SLIM);
fprintf (file, "\n");
}
fprintf (file, "\n");
}
}
/* Dump immediate uses for STMT on stderr. */
void
debug_immediate_uses_for (tree stmt)
{
dump_immediate_uses_for (stderr, stmt);
}
/* Dump various DFA statistics to FILE. */ /* Dump various DFA statistics to FILE. */
void void
...@@ -987,8 +654,7 @@ mark_new_vars_to_rename (tree stmt, bitmap vars_to_rename) ...@@ -987,8 +654,7 @@ mark_new_vars_to_rename (tree stmt, bitmap vars_to_rename)
/* Now force an operand re-scan on the statement and mark any newly /* Now force an operand re-scan on the statement and mark any newly
exposed variables. */ exposed variables. */
modify_stmt (stmt); update_stmt (stmt);
get_stmt_operands (stmt);
v_may_defs_after = NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)); v_may_defs_after = NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt));
v_must_defs_after = NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt)); v_must_defs_after = NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt));
......
...@@ -745,7 +745,9 @@ static const struct dump_option_value_info dump_options[] = ...@@ -745,7 +745,9 @@ static const struct dump_option_value_info dump_options[] =
{"vops", TDF_VOPS}, {"vops", TDF_VOPS},
{"lineno", TDF_LINENO}, {"lineno", TDF_LINENO},
{"uid", TDF_UID}, {"uid", TDF_UID},
{"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA)}, {"stmtaddr", TDF_STMTADDR},
{"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
| TDF_STMTADDR)},
{NULL, 0} {NULL, 0}
}; };
......
...@@ -235,43 +235,33 @@ struct var_ann_d GTY(()) ...@@ -235,43 +235,33 @@ struct var_ann_d GTY(())
}; };
struct dataflow_d GTY(()) typedef struct immediate_use_iterator_d
{ {
/* Immediate uses. This is a list of all the statements and PHI nodes ssa_imm_use_t *imm_use;
that are immediately reached by the definitions made in this ssa_imm_use_t *end_p;
statement. */ ssa_imm_use_t iter_node;
varray_type immediate_uses; } imm_use_iterator;
/* Use this array for very small numbers of uses instead of the varray. */
tree uses[2];
/* Reached uses. This is a list of all the possible program statements
that may be reached directly or indirectly by definitions made in this
statement. Notice that this is a superset of IMMEDIATE_USES.
For instance, given the following piece of code:
1 a1 = 10;
2 if (a1 > 3)
3 a2 = a1 + 5;
4 a3 = PHI (a1, a2)
5 b1 = a3 - 2;
IMMEDIATE_USES for statement #1 are all those statements that use a1
directly (i.e., #2, #3 and #4). REACHED_USES for statement #1 also
includes statement #5 because 'a1' could reach 'a3' via the PHI node
at statement #4. The set of REACHED_USES is then the transitive
closure over all the PHI nodes in the IMMEDIATE_USES set. */
/* Reaching definitions. Similarly to REACHED_USES, the set
REACHING_DEFS is the set of all the statements that make definitions
that may reach this statement. Notice that we don't need to have a
similar entry for immediate definitions, as these are represented by
the SSA_NAME nodes themselves (each SSA_NAME node contains a pointer
to the statement that makes that definition). */
};
typedef struct dataflow_d *dataflow_t; /* Use this iterator when simply looking at stmts. Adding, deleteing or
modifying stmts will cause this iterator to malfunction. */
#define FOR_EACH_IMM_USE_FAST(DEST, ITER, SSAVAR) \
for ((DEST) = first_readonly_imm_use (&(ITER), (SSAVAR)); \
!end_readonly_imm_use_p (&(ITER)); \
(DEST) = next_readonly_imm_use (&(ITER)))
#define FOR_EACH_IMM_USE_SAFE(DEST, ITER, SSAVAR) \
for ((DEST) = first_safe_imm_use (&(ITER), (SSAVAR)); \
!end_safe_imm_use_p (&(ITER)); \
(DEST) = next_safe_imm_use (&(ITER)))
#define BREAK_FROM_SAFE_IMM_USE(ITER) \
{ \
end_safe_imm_use_traverse (&(ITER)); \
break; \
}
struct stmt_ann_d GTY(()) struct stmt_ann_d GTY(())
{ {
...@@ -297,11 +287,9 @@ struct stmt_ann_d GTY(()) ...@@ -297,11 +287,9 @@ struct stmt_ann_d GTY(())
/* Basic block that contains this statement. */ /* Basic block that contains this statement. */
basic_block GTY ((skip (""))) bb; basic_block GTY ((skip (""))) bb;
/* Operand cache for stmt. */
struct stmt_operands_d operands; struct stmt_operands_d operands;
/* Dataflow information. */
dataflow_t df;
/* Set of variables that have had their address taken in the statement. */ /* Set of variables that have had their address taken in the statement. */
bitmap addresses_taken; bitmap addresses_taken;
...@@ -340,8 +328,7 @@ static inline enum tree_ann_type ann_type (tree_ann_t); ...@@ -340,8 +328,7 @@ static inline enum tree_ann_type ann_type (tree_ann_t);
static inline basic_block bb_for_stmt (tree); static inline basic_block bb_for_stmt (tree);
extern void set_bb_for_stmt (tree, basic_block); extern void set_bb_for_stmt (tree, basic_block);
static inline bool noreturn_call_p (tree); static inline bool noreturn_call_p (tree);
static inline void modify_stmt (tree); static inline void update_stmt (tree);
static inline void unmodify_stmt (tree);
static inline bool stmt_modified_p (tree); static inline bool stmt_modified_p (tree);
static inline varray_type may_aliases (tree); static inline varray_type may_aliases (tree);
static inline int get_lineno (tree); static inline int get_lineno (tree);
...@@ -353,9 +340,6 @@ static inline vuse_optype get_vuse_ops (stmt_ann_t); ...@@ -353,9 +340,6 @@ static inline vuse_optype get_vuse_ops (stmt_ann_t);
static inline use_optype get_use_ops (stmt_ann_t); static inline use_optype get_use_ops (stmt_ann_t);
static inline def_optype get_def_ops (stmt_ann_t); static inline def_optype get_def_ops (stmt_ann_t);
static inline bitmap addresses_taken (tree); static inline bitmap addresses_taken (tree);
static inline int num_immediate_uses (dataflow_t);
static inline tree immediate_use (dataflow_t, int);
static inline dataflow_t get_immediate_uses (tree);
static inline void set_default_def (tree, tree); static inline void set_default_def (tree, tree);
static inline tree default_def (tree); static inline tree default_def (tree);
...@@ -435,7 +419,6 @@ extern bool aliases_computed_p; ...@@ -435,7 +419,6 @@ extern bool aliases_computed_p;
#define PERCENT(x,y) ((float)(x) * 100.0 / (float)(y)) #define PERCENT(x,y) ((float)(x) * 100.0 / (float)(y))
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
Block iterators Block iterators
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
...@@ -559,13 +542,6 @@ extern void debug_referenced_vars (void); ...@@ -559,13 +542,6 @@ extern void debug_referenced_vars (void);
extern void dump_referenced_vars (FILE *); extern void dump_referenced_vars (FILE *);
extern void dump_variable (FILE *, tree); extern void dump_variable (FILE *, tree);
extern void debug_variable (tree); extern void debug_variable (tree);
extern void dump_immediate_uses (FILE *);
extern void debug_immediate_uses (void);
extern void dump_immediate_uses_for (FILE *, tree);
extern void debug_immediate_uses_for (tree);
extern void compute_immediate_uses (int, bool (*)(tree));
extern void free_df (void);
extern void free_df_for_stmt (tree);
extern tree get_virtual_var (tree); extern tree get_virtual_var (tree);
extern void add_referenced_tmp_var (tree); extern void add_referenced_tmp_var (tree);
extern void mark_new_vars_to_rename (tree, bitmap); extern void mark_new_vars_to_rename (tree, bitmap);
...@@ -621,7 +597,7 @@ extern edge ssa_redirect_edge (edge, basic_block); ...@@ -621,7 +597,7 @@ extern edge ssa_redirect_edge (edge, basic_block);
extern void flush_pending_stmts (edge); extern void flush_pending_stmts (edge);
extern bool tree_ssa_useless_type_conversion (tree); extern bool tree_ssa_useless_type_conversion (tree);
extern bool tree_ssa_useless_type_conversion_1 (tree, tree); extern bool tree_ssa_useless_type_conversion_1 (tree, tree);
extern void verify_ssa (void); extern void verify_ssa (bool);
extern void delete_tree_ssa (void); extern void delete_tree_ssa (void);
extern void register_new_def (tree, VEC (tree_on_heap) **); extern void register_new_def (tree, VEC (tree_on_heap) **);
extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool); extern void walk_use_def_chains (tree, walk_use_def_chains_fn, void *, bool);
......
...@@ -160,7 +160,6 @@ tree_if_conversion (struct loop *loop, bool for_vectorizer) ...@@ -160,7 +160,6 @@ tree_if_conversion (struct loop *loop, bool for_vectorizer)
ifc_bbs = NULL; ifc_bbs = NULL;
} }
free_dominance_info (CDI_POST_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS);
free_df ();
return false; return false;
} }
...@@ -205,7 +204,6 @@ tree_if_conversion (struct loop *loop, bool for_vectorizer) ...@@ -205,7 +204,6 @@ tree_if_conversion (struct loop *loop, bool for_vectorizer)
clean_predicate_lists (loop); clean_predicate_lists (loop);
free (ifc_bbs); free (ifc_bbs);
ifc_bbs = NULL; ifc_bbs = NULL;
free_df ();
return true; return true;
} }
...@@ -343,13 +341,11 @@ if_convertible_phi_p (struct loop *loop, basic_block bb, tree phi) ...@@ -343,13 +341,11 @@ if_convertible_phi_p (struct loop *loop, basic_block bb, tree phi)
if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi)))) if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
{ {
int j; imm_use_iterator imm_iter;
dataflow_t df = get_immediate_uses (phi); use_operand_p use_p;
int num_uses = num_immediate_uses (df); FOR_EACH_IMM_USE_FAST (use_p, imm_iter, PHI_RESULT (phi))
for (j = 0; j < num_uses; j++)
{ {
tree use = immediate_use (df, j); if (TREE_CODE (USE_STMT (use_p)) == PHI_NODE)
if (TREE_CODE (use) == PHI_NODE)
{ {
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Difficult to handle this virtual phi.\n"); fprintf (dump_file, "Difficult to handle this virtual phi.\n");
...@@ -559,8 +555,6 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED) ...@@ -559,8 +555,6 @@ if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
return false; return false;
} }
compute_immediate_uses (TDFA_USE_OPS|TDFA_USE_VOPS, NULL);
calculate_dominance_info (CDI_DOMINATORS); calculate_dominance_info (CDI_DOMINATORS);
calculate_dominance_info (CDI_POST_DOMINATORS); calculate_dominance_info (CDI_POST_DOMINATORS);
...@@ -798,7 +792,7 @@ replace_phi_with_cond_modify_expr (tree phi, tree cond, basic_block true_bb, ...@@ -798,7 +792,7 @@ replace_phi_with_cond_modify_expr (tree phi, tree cond, basic_block true_bb,
bsi_insert_after (bsi, new_stmt, BSI_SAME_STMT); bsi_insert_after (bsi, new_stmt, BSI_SAME_STMT);
bsi_next (bsi); bsi_next (bsi);
modify_stmt (new_stmt); update_stmt (new_stmt);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
......
...@@ -438,7 +438,7 @@ mark_def_sites (struct dom_walk_data *walk_data, ...@@ -438,7 +438,7 @@ mark_def_sites (struct dom_walk_data *walk_data,
/* Mark all the blocks that have definitions for each variable in the /* Mark all the blocks that have definitions for each variable in the
VARS_TO_RENAME bitmap. */ VARS_TO_RENAME bitmap. */
stmt = bsi_stmt (bsi); stmt = bsi_stmt (bsi);
get_stmt_operands (stmt); update_stmt_if_modified (stmt);
REWRITE_THIS_STMT (stmt) = 0; REWRITE_THIS_STMT (stmt) = 0;
...@@ -1346,6 +1346,7 @@ rewrite_into_ssa (bool all) ...@@ -1346,6 +1346,7 @@ rewrite_into_ssa (bool all)
static void static void
rewrite_all_into_ssa (void) rewrite_all_into_ssa (void)
{ {
init_ssa_operands ();
rewrite_into_ssa (true); rewrite_into_ssa (true);
} }
...@@ -1583,7 +1584,7 @@ ssa_mark_def_sites (struct dom_walk_data *walk_data, ...@@ -1583,7 +1584,7 @@ ssa_mark_def_sites (struct dom_walk_data *walk_data,
/* Mark all the blocks that have definitions for each variable in the /* Mark all the blocks that have definitions for each variable in the
names_to_rename bitmap. */ names_to_rename bitmap. */
stmt = bsi_stmt (bsi); stmt = bsi_stmt (bsi);
get_stmt_operands (stmt); update_stmt_if_modified (stmt);
/* If a variable is used before being set, then the variable is live /* If a variable is used before being set, then the variable is live
across a block boundary, so mark it live-on-entry to BB. */ across a block boundary, so mark it live-on-entry to BB. */
......
...@@ -244,7 +244,6 @@ linear_transform_loops (struct loops *loops) ...@@ -244,7 +244,6 @@ linear_transform_loops (struct loops *loops)
{ {
unsigned int i; unsigned int i;
compute_immediate_uses (TDFA_USE_OPS | TDFA_USE_VOPS, NULL);
for (i = 1; i < loops->num; i++) for (i = 1; i < loops->num; i++)
{ {
unsigned int depth = 0; unsigned int depth = 0;
...@@ -371,7 +370,6 @@ linear_transform_loops (struct loops *loops) ...@@ -371,7 +370,6 @@ linear_transform_loops (struct loops *loops)
free_dependence_relations (dependence_relations); free_dependence_relations (dependence_relations);
free_data_refs (datarefs); free_data_refs (datarefs);
} }
free_df ();
scev_reset (); scev_reset ();
rewrite_into_ssa (false); rewrite_into_ssa (false);
rewrite_into_loop_closed_ssa (NULL); rewrite_into_loop_closed_ssa (NULL);
......
...@@ -438,8 +438,11 @@ static void execute_pass_list (struct tree_opt_pass *); ...@@ -438,8 +438,11 @@ static void execute_pass_list (struct tree_opt_pass *);
static unsigned int last_verified; static unsigned int last_verified;
static void static void
execute_todo (int properties, unsigned int flags) execute_todo (struct tree_opt_pass *pass, unsigned int flags, bool use_required)
{ {
int properties
= use_required ? pass->properties_required : pass->properties_provided;
if (flags & TODO_rename_vars) if (flags & TODO_rename_vars)
{ {
rewrite_into_ssa (false); rewrite_into_ssa (false);
...@@ -475,11 +478,15 @@ execute_todo (int properties, unsigned int flags) ...@@ -475,11 +478,15 @@ execute_todo (int properties, unsigned int flags)
} }
if (flags & TODO_ggc_collect) if (flags & TODO_ggc_collect)
ggc_collect (); {
ggc_collect ();
}
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
if (flags & TODO_verify_ssa) if ((pass->properties_required & PROP_ssa)
verify_ssa (); && !(pass->properties_destroyed & PROP_ssa))
verify_ssa (true);
if (flags & TODO_verify_flow) if (flags & TODO_verify_flow)
verify_flow_info (); verify_flow_info ();
if (flags & TODO_verify_stmts) if (flags & TODO_verify_stmts)
...@@ -503,7 +510,7 @@ execute_one_pass (struct tree_opt_pass *pass) ...@@ -503,7 +510,7 @@ execute_one_pass (struct tree_opt_pass *pass)
/* Run pre-pass verification. */ /* Run pre-pass verification. */
todo = pass->todo_flags_start & ~last_verified; todo = pass->todo_flags_start & ~last_verified;
if (todo) if (todo)
execute_todo (pass->properties_required, todo); execute_todo (pass, todo, true);
/* If a dump file name is present, open it if enabled. */ /* If a dump file name is present, open it if enabled. */
if (pass->static_pass_number != -1) if (pass->static_pass_number != -1)
...@@ -553,7 +560,7 @@ execute_one_pass (struct tree_opt_pass *pass) ...@@ -553,7 +560,7 @@ execute_one_pass (struct tree_opt_pass *pass)
todo = pass->todo_flags_finish; todo = pass->todo_flags_finish;
last_verified = todo & TODO_verify_all; last_verified = todo & TODO_verify_all;
if (todo) if (todo)
execute_todo (pass->properties_provided, todo); execute_todo (pass, todo, false);
/* Flush and close dump file. */ /* Flush and close dump file. */
if (dump_file_name) if (dump_file_name)
......
...@@ -1928,8 +1928,6 @@ rewrite_trees (var_map map, tree *values) ...@@ -1928,8 +1928,6 @@ rewrite_trees (var_map map, tree *values)
&& (DEF_FROM_PTR (def_p) == USE_OP (uses, 0))) && (DEF_FROM_PTR (def_p) == USE_OP (uses, 0)))
remove = 1; remove = 1;
} }
if (changed & !remove)
modify_stmt (stmt);
} }
/* Remove any stmts marked for removal. */ /* Remove any stmts marked for removal. */
...@@ -2370,6 +2368,9 @@ remove_ssa_form (FILE *dump, var_map map, int flags) ...@@ -2370,6 +2368,9 @@ remove_ssa_form (FILE *dump, var_map map, int flags)
} }
} }
/* we no longer maintain the SSA operand cache at this point. */
fini_ssa_operands ();
/* If any copies were inserted on edges, analyze and insert them now. */ /* If any copies were inserted on edges, analyze and insert them now. */
perform_edge_inserts (dump_file); perform_edge_inserts (dump_file);
...@@ -2457,7 +2458,6 @@ insert_backedge_copies (void) ...@@ -2457,7 +2458,6 @@ insert_backedge_copies (void)
bsi_insert_before (&bsi, stmt, BSI_NEW_STMT); bsi_insert_before (&bsi, stmt, BSI_NEW_STMT);
else else
bsi_insert_after (&bsi, stmt, BSI_NEW_STMT); bsi_insert_after (&bsi, stmt, BSI_NEW_STMT);
modify_stmt (stmt);
SET_PHI_ARG_DEF (phi, i, name); SET_PHI_ARG_DEF (phi, i, name);
} }
} }
......
...@@ -206,7 +206,7 @@ static tree ...@@ -206,7 +206,7 @@ static tree
make_phi_node (tree var, int len) make_phi_node (tree var, int len)
{ {
tree phi; tree phi;
int capacity; int capacity, i;
capacity = ideal_phi_node_len (len); capacity = ideal_phi_node_len (len);
...@@ -226,6 +226,15 @@ make_phi_node (tree var, int len) ...@@ -226,6 +226,15 @@ make_phi_node (tree var, int len)
else else
SET_PHI_RESULT (phi, make_ssa_name (var, phi)); SET_PHI_RESULT (phi, make_ssa_name (var, phi));
for (i = 0; i < capacity; i++)
{
ssa_imm_use_t * imm;
imm = &(PHI_ARG_IMM_USE_NODE (phi, i));
imm->use = &(PHI_ARG_DEF_TREE (phi, i));
imm->prev = NULL;
imm->next = NULL;
imm->stmt = phi;
}
return phi; return phi;
} }
...@@ -236,6 +245,14 @@ release_phi_node (tree phi) ...@@ -236,6 +245,14 @@ release_phi_node (tree phi)
{ {
int bucket; int bucket;
int len = PHI_ARG_CAPACITY (phi); int len = PHI_ARG_CAPACITY (phi);
int x;
for (x = 0; x < PHI_NUM_ARGS (phi); x++)
{
ssa_imm_use_t * imm;
imm = &(PHI_ARG_IMM_USE_NODE (phi, x));
delink_imm_use (imm);
}
bucket = len > NUM_BUCKETS - 1 ? NUM_BUCKETS - 1 : len; bucket = len > NUM_BUCKETS - 1 ? NUM_BUCKETS - 1 : len;
bucket -= 2; bucket -= 2;
...@@ -250,7 +267,7 @@ release_phi_node (tree phi) ...@@ -250,7 +267,7 @@ release_phi_node (tree phi)
static void static void
resize_phi_node (tree *phi, int len) resize_phi_node (tree *phi, int len)
{ {
int old_size; int old_size, i;
tree new_phi; tree new_phi;
gcc_assert (len > PHI_ARG_CAPACITY (*phi)); gcc_assert (len > PHI_ARG_CAPACITY (*phi));
...@@ -265,8 +282,28 @@ resize_phi_node (tree *phi, int len) ...@@ -265,8 +282,28 @@ resize_phi_node (tree *phi, int len)
memcpy (new_phi, *phi, old_size); memcpy (new_phi, *phi, old_size);
for (i = 0; i < PHI_NUM_ARGS (new_phi); i++)
{
ssa_imm_use_t *imm, *old_imm;
imm = &(PHI_ARG_IMM_USE_NODE (new_phi, i));
old_imm = &(PHI_ARG_IMM_USE_NODE (*phi, i));
imm->use = &(PHI_ARG_DEF_TREE (new_phi, i));
relink_imm_use_stmt (imm, old_imm, new_phi);
}
PHI_ARG_CAPACITY (new_phi) = len; PHI_ARG_CAPACITY (new_phi) = len;
for (i = PHI_NUM_ARGS (new_phi); i < len; i++)
{
ssa_imm_use_t * imm;
imm = &(PHI_ARG_IMM_USE_NODE (new_phi, i));
imm->use = &(PHI_ARG_DEF_TREE (new_phi, i));
imm->prev = NULL;
imm->next = NULL;
imm->stmt = new_phi;
}
*phi = new_phi; *phi = new_phi;
} }
...@@ -372,6 +409,9 @@ remove_phi_arg_num (tree phi, int i) ...@@ -372,6 +409,9 @@ remove_phi_arg_num (tree phi, int i)
gcc_assert (i < num_elem); gcc_assert (i < num_elem);
/* Delink the last item, which is being removed. */
delink_imm_use (&(PHI_ARG_IMM_USE_NODE (phi, num_elem - 1)));
/* If we are not at the last element, switch the last element /* If we are not at the last element, switch the last element
with the element we want to delete. */ with the element we want to delete. */
if (i != num_elem - 1) if (i != num_elem - 1)
...@@ -423,8 +463,8 @@ remove_phi_node (tree phi, tree prev) ...@@ -423,8 +463,8 @@ remove_phi_node (tree phi, tree prev)
/* If we are deleting the PHI node, then we should release the /* If we are deleting the PHI node, then we should release the
SSA_NAME node so that it can be reused. */ SSA_NAME node so that it can be reused. */
release_ssa_name (PHI_RESULT (phi));
release_phi_node (phi); release_phi_node (phi);
release_ssa_name (PHI_RESULT (phi));
} }
...@@ -461,8 +501,8 @@ remove_all_phi_nodes_for (bitmap vars) ...@@ -461,8 +501,8 @@ remove_all_phi_nodes_for (bitmap vars)
{ {
/* If we are deleting the PHI node, then we should release the /* If we are deleting the PHI node, then we should release the
SSA_NAME node so that it can be reused. */ SSA_NAME node so that it can be reused. */
release_ssa_name (PHI_RESULT (phi));
release_phi_node (phi); release_phi_node (phi);
release_ssa_name (PHI_RESULT (phi));
} }
} }
......
...@@ -271,6 +271,9 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags, ...@@ -271,6 +271,9 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
&& stmt_ann (node)) && stmt_ann (node))
dump_vops (buffer, node, spc, flags); dump_vops (buffer, node, spc, flags);
if (is_stmt && (flags & TDF_STMTADDR))
pp_printf (buffer, "<&0x%x> ", (unsigned int)node);
if (dumping_stmts if (dumping_stmts
&& (flags & TDF_LINENO) && (flags & TDF_LINENO)
&& EXPR_HAS_LOCATION (node)) && EXPR_HAS_LOCATION (node))
......
...@@ -1444,7 +1444,7 @@ mark_all_v_defs (tree stmt) ...@@ -1444,7 +1444,7 @@ mark_all_v_defs (tree stmt)
tree sym; tree sym;
ssa_op_iter iter; ssa_op_iter iter;
get_stmt_operands (stmt); update_stmt_if_modified (stmt);
FOR_EACH_SSA_TREE_OPERAND (sym, stmt, iter, SSA_OP_ALL_VIRTUALS) FOR_EACH_SSA_TREE_OPERAND (sym, stmt, iter, SSA_OP_ALL_VIRTUALS)
{ {
...@@ -1800,7 +1800,7 @@ scalarize_use (struct sra_elt *elt, tree *expr_p, block_stmt_iterator *bsi, ...@@ -1800,7 +1800,7 @@ scalarize_use (struct sra_elt *elt, tree *expr_p, block_stmt_iterator *bsi,
if (is_output) if (is_output)
mark_all_v_defs (stmt); mark_all_v_defs (stmt);
*expr_p = elt->replacement; *expr_p = elt->replacement;
modify_stmt (stmt); update_stmt (stmt);
} }
else else
{ {
...@@ -1848,7 +1848,7 @@ scalarize_copy (struct sra_elt *lhs_elt, struct sra_elt *rhs_elt, ...@@ -1848,7 +1848,7 @@ scalarize_copy (struct sra_elt *lhs_elt, struct sra_elt *rhs_elt,
TREE_OPERAND (stmt, 0) = lhs_elt->replacement; TREE_OPERAND (stmt, 0) = lhs_elt->replacement;
TREE_OPERAND (stmt, 1) = rhs_elt->replacement; TREE_OPERAND (stmt, 1) = rhs_elt->replacement;
modify_stmt (stmt); update_stmt (stmt);
} }
else if (lhs_elt->use_block_copy || rhs_elt->use_block_copy) else if (lhs_elt->use_block_copy || rhs_elt->use_block_copy)
{ {
......
...@@ -343,6 +343,19 @@ compute_may_aliases (void) ...@@ -343,6 +343,19 @@ compute_may_aliases (void)
/* Deallocate memory used by aliasing data structures. */ /* Deallocate memory used by aliasing data structures. */
delete_alias_info (ai); delete_alias_info (ai);
{
block_stmt_iterator bsi;
basic_block bb;
FOR_EACH_BB (bb)
{
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
update_stmt_if_modified (bsi_stmt (bsi));
}
}
}
} }
struct tree_opt_pass pass_may_alias = struct tree_opt_pass pass_may_alias =
...@@ -766,7 +779,7 @@ compute_points_to_and_addr_escape (struct alias_info *ai) ...@@ -766,7 +779,7 @@ compute_points_to_and_addr_escape (struct alias_info *ai)
need to re-scan most statements. FIXME: Try to minimize the need to re-scan most statements. FIXME: Try to minimize the
number of statements re-scanned. It's not really necessary to number of statements re-scanned. It's not really necessary to
re-scan *all* statements. */ re-scan *all* statements. */
modify_stmt (stmt); mark_stmt_modified (stmt);
} }
} }
......
...@@ -331,16 +331,6 @@ likely_value (tree stmt) ...@@ -331,16 +331,6 @@ likely_value (tree stmt)
} }
/* Function indicating whether we ought to include information for VAR
when calculating immediate uses. */
static bool
need_imm_uses_for (tree var)
{
return get_value (var)->lattice_val != VARYING;
}
/* Initialize local data structures for CCP. */ /* Initialize local data structures for CCP. */
static void static void
...@@ -430,9 +420,6 @@ ccp_initialize (void) ...@@ -430,9 +420,6 @@ ccp_initialize (void)
} }
sbitmap_free (is_may_def); sbitmap_free (is_may_def);
/* Compute immediate uses for variables we care about. */
compute_immediate_uses (TDFA_USE_OPS | TDFA_USE_VOPS, need_imm_uses_for);
} }
...@@ -591,7 +578,7 @@ substitute_and_fold (void) ...@@ -591,7 +578,7 @@ substitute_and_fold (void)
if (maybe_clean_eh_stmt (stmt)) if (maybe_clean_eh_stmt (stmt))
tree_purge_dead_eh_edges (bb); tree_purge_dead_eh_edges (bb);
modify_stmt (stmt); update_stmt (stmt);
} }
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
...@@ -2211,7 +2198,7 @@ execute_fold_all_builtins (void) ...@@ -2211,7 +2198,7 @@ execute_fold_all_builtins (void)
gcc_assert (ok); gcc_assert (ok);
} }
} }
modify_stmt (*stmtp); update_stmt (*stmtp);
if (maybe_clean_eh_stmt (*stmtp) if (maybe_clean_eh_stmt (*stmtp)
&& tree_purge_dead_eh_edges (bb)) && tree_purge_dead_eh_edges (bb))
cfg_changed = true; cfg_changed = true;
......
...@@ -450,6 +450,17 @@ tree_ssa_dominator_optimize (void) ...@@ -450,6 +450,17 @@ tree_ssa_dominator_optimize (void)
free_all_edge_infos (); free_all_edge_infos ();
{
block_stmt_iterator bsi;
basic_block bb;
FOR_EACH_BB (bb)
{
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
update_stmt_if_modified (bsi_stmt (bsi));
}
}
}
/* Thread jumps, creating duplicate blocks as needed. */ /* Thread jumps, creating duplicate blocks as needed. */
cfg_altered |= thread_through_all_blocks (); cfg_altered |= thread_through_all_blocks ();
...@@ -2097,7 +2108,7 @@ simplify_cond_and_lookup_avail_expr (tree stmt, ...@@ -2097,7 +2108,7 @@ simplify_cond_and_lookup_avail_expr (tree stmt,
/* If this is not a real stmt, ann will be NULL and we /* If this is not a real stmt, ann will be NULL and we
avoid processing the operands. */ avoid processing the operands. */
if (ann) if (ann)
modify_stmt (stmt); mark_stmt_modified (stmt);
/* Lookup the condition and return its known value if it /* Lookup the condition and return its known value if it
exists. */ exists. */
...@@ -2349,7 +2360,7 @@ simplify_switch_and_lookup_avail_expr (tree stmt, int insert) ...@@ -2349,7 +2360,7 @@ simplify_switch_and_lookup_avail_expr (tree stmt, int insert)
if (!fail) if (!fail)
{ {
SWITCH_COND (stmt) = def; SWITCH_COND (stmt) = def;
modify_stmt (stmt); mark_stmt_modified (stmt);
return lookup_avail_expr (stmt, insert); return lookup_avail_expr (stmt, insert);
} }
...@@ -2709,7 +2720,7 @@ eliminate_redundant_computations (struct dom_walk_data *walk_data, ...@@ -2709,7 +2720,7 @@ eliminate_redundant_computations (struct dom_walk_data *walk_data,
retval = true; retval = true;
propagate_tree_value (expr_p, cached_lhs); propagate_tree_value (expr_p, cached_lhs);
modify_stmt (stmt); mark_stmt_modified (stmt);
} }
return retval; return retval;
} }
...@@ -2946,7 +2957,7 @@ cprop_operand (tree stmt, use_operand_p op_p) ...@@ -2946,7 +2957,7 @@ cprop_operand (tree stmt, use_operand_p op_p)
/* And note that we modified this statement. This is now /* And note that we modified this statement. This is now
safe, even if we changed virtual operands since we will safe, even if we changed virtual operands since we will
rescan the statement and rewrite its operands again. */ rescan the statement and rewrite its operands again. */
modify_stmt (stmt); mark_stmt_modified (stmt);
} }
return may_have_exposed_new_symbols; return may_have_exposed_new_symbols;
} }
...@@ -3008,7 +3019,7 @@ optimize_stmt (struct dom_walk_data *walk_data, basic_block bb, ...@@ -3008,7 +3019,7 @@ optimize_stmt (struct dom_walk_data *walk_data, basic_block bb,
stmt = bsi_stmt (si); stmt = bsi_stmt (si);
get_stmt_operands (stmt); update_stmt_if_modified (stmt);
ann = stmt_ann (stmt); ann = stmt_ann (stmt);
opt_stats.num_stmts++; opt_stats.num_stmts++;
may_have_exposed_new_symbols = false; may_have_exposed_new_symbols = false;
...@@ -3178,7 +3189,7 @@ update_rhs_and_lookup_avail_expr (tree stmt, tree new_rhs, bool insert) ...@@ -3178,7 +3189,7 @@ update_rhs_and_lookup_avail_expr (tree stmt, tree new_rhs, bool insert)
/* And make sure we record the fact that we modified this /* And make sure we record the fact that we modified this
statement. */ statement. */
modify_stmt (stmt); mark_stmt_modified (stmt);
return cached_lhs; return cached_lhs;
} }
......
...@@ -94,8 +94,6 @@ static void dse_optimize_stmt (struct dom_walk_data *, ...@@ -94,8 +94,6 @@ static void dse_optimize_stmt (struct dom_walk_data *,
block_stmt_iterator); block_stmt_iterator);
static void dse_record_phis (struct dom_walk_data *, basic_block); static void dse_record_phis (struct dom_walk_data *, basic_block);
static void dse_finalize_block (struct dom_walk_data *, basic_block); static void dse_finalize_block (struct dom_walk_data *, basic_block);
static void fix_phi_uses (tree, tree);
static void fix_stmt_v_may_defs (tree, tree);
static void record_voperand_set (bitmap, bitmap *, unsigned int); static void record_voperand_set (bitmap, bitmap *, unsigned int);
static unsigned max_stmt_uid; /* Maximal uid of a statement. Uids to phi static unsigned max_stmt_uid; /* Maximal uid of a statement. Uids to phi
...@@ -124,83 +122,6 @@ need_imm_uses_for (tree var) ...@@ -124,83 +122,6 @@ need_imm_uses_for (tree var)
} }
/* Replace uses in PHI which match V_MAY_DEF_RESULTs in STMT with the
corresponding V_MAY_DEF_OP in STMT. */
static void
fix_phi_uses (tree phi, tree stmt)
{
use_operand_p use_p;
def_operand_p def_p;
ssa_op_iter iter;
int i;
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, PHI_BB (phi)->preds)
if (e->flags & EDGE_ABNORMAL)
break;
get_stmt_operands (stmt);
FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, iter)
{
tree v_may_def = DEF_FROM_PTR (def_p);
tree v_may_use = USE_FROM_PTR (use_p);
/* Find any uses in the PHI which match V_MAY_DEF and replace
them with the appropriate V_MAY_DEF_OP. */
for (i = 0; i < PHI_NUM_ARGS (phi); i++)
if (v_may_def == PHI_ARG_DEF (phi, i))
{
SET_PHI_ARG_DEF (phi, i, v_may_use);
/* Update if the new phi argument is an abnormal phi. */
if (e != NULL)
SSA_NAME_OCCURS_IN_ABNORMAL_PHI (v_may_use) = 1;
}
}
}
/* Replace the V_MAY_DEF_OPs in STMT1 which match V_MAY_DEF_RESULTs
in STMT2 with the appropriate V_MAY_DEF_OPs from STMT2. */
static void
fix_stmt_v_may_defs (tree stmt1, tree stmt2)
{
bool found = false;
ssa_op_iter iter1;
ssa_op_iter iter2;
use_operand_p use1_p, use2_p;
def_operand_p def1_p, def2_p;
get_stmt_operands (stmt1);
get_stmt_operands (stmt2);
/* Walk each V_MAY_DEF_OP in stmt1. */
FOR_EACH_SSA_MAYDEF_OPERAND (def1_p, use1_p, stmt1, iter1)
{
tree use = USE_FROM_PTR (use1_p);
/* Find the appropriate V_MAY_DEF_RESULT in STMT2. */
FOR_EACH_SSA_MAYDEF_OPERAND (def2_p, use2_p, stmt2, iter2)
{
tree def = DEF_FROM_PTR (def2_p);
if (use == def)
{
/* Update. */
SET_USE (use1_p, USE_FROM_PTR (use2_p));
found = true;
break;
}
}
/* If we did not find a corresponding V_MAY_DEF_RESULT,
then something has gone terribly wrong. */
gcc_assert (found);
}
}
/* Set bit UID in bitmaps GLOBAL and *LOCAL, creating *LOCAL as needed. */ /* Set bit UID in bitmaps GLOBAL and *LOCAL, creating *LOCAL as needed. */
static void static void
record_voperand_set (bitmap global, bitmap *local, unsigned int uid) record_voperand_set (bitmap global, bitmap *local, unsigned int uid)
...@@ -275,57 +196,66 @@ dse_optimize_stmt (struct dom_walk_data *walk_data, ...@@ -275,57 +196,66 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
if (TREE_CODE (stmt) == MODIFY_EXPR) if (TREE_CODE (stmt) == MODIFY_EXPR)
{ {
dataflow_t df = get_immediate_uses (stmt); unsigned int num_uses = 0, count = 0;
unsigned int num_uses = num_immediate_uses (df); use_operand_p first_use_p = NULL_USE_OPERAND_P;
tree use; use_operand_p use_p;
tree skipped_phi; tree use, use_stmt;
tree defvar = NULL_TREE, usevar = NULL_TREE;
use_operand_p var2;
def_operand_p var1;
ssa_op_iter op_iter;
FOR_EACH_SSA_MAYDEF_OPERAND (var1, var2, stmt, op_iter)
{
defvar = DEF_FROM_PTR (var1);
usevar = USE_FROM_PTR (var2);
num_uses += num_imm_uses (defvar);
count++;
if (num_uses > 1 || count > 1)
break;
}
/* If there are no uses then there is nothing left to do. */ if (count == 1 && num_uses == 1)
if (num_uses == 0) {
single_imm_use (defvar, &use_p, &use_stmt);
gcc_assert (use_p != NULL_USE_OPERAND_P);
first_use_p = use_p;
use = USE_FROM_PTR (use_p);
}
else
{ {
record_voperand_set (dse_gd->stores, &bd->stores, ann->uid); record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
return; return;
} }
use = immediate_use (df, 0);
skipped_phi = NULL;
/* Skip through any PHI nodes we have already seen if the PHI /* Skip through any PHI nodes we have already seen if the PHI
represents the only use of this store. represents the only use of this store.
Note this does not handle the case where the store has Note this does not handle the case where the store has
multiple V_MAY_DEFs which all reach a set of PHI nodes in the multiple V_MAY_DEFs which all reach a set of PHI nodes in the
same block. */ same block. */
while (num_uses == 1 while (use_p != NULL_USE_OPERAND_P
&& TREE_CODE (use) == PHI_NODE && TREE_CODE (use_stmt) == PHI_NODE
&& bitmap_bit_p (dse_gd->stores, get_stmt_uid (use))) && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt)))
{ {
/* Record the first PHI we skip so that we can fix its
uses if we find that STMT is a dead store. */
if (!skipped_phi)
skipped_phi = use;
/* Skip past this PHI and loop again in case we had a PHI /* Skip past this PHI and loop again in case we had a PHI
chain. */ chain. */
df = get_immediate_uses (use); if (single_imm_use (PHI_RESULT (use_stmt), &use_p, &use_stmt))
num_uses = num_immediate_uses (df); use = USE_FROM_PTR (use_p);
use = immediate_use (df, 0);
} }
/* If we have precisely one immediate use at this point, then we may /* If we have precisely one immediate use at this point, then we may
have found redundant store. */ have found redundant store. */
if (num_uses == 1 if (use_p != NULL_USE_OPERAND_P
&& bitmap_bit_p (dse_gd->stores, get_stmt_uid (use)) && bitmap_bit_p (dse_gd->stores, get_stmt_uid (use_stmt))
&& operand_equal_p (TREE_OPERAND (stmt, 0), && operand_equal_p (TREE_OPERAND (stmt, 0),
TREE_OPERAND (use, 0), 0)) TREE_OPERAND (use_stmt, 0), 0))
{ {
/* We need to fix the operands if either the first PHI we /* Make sure we propagate the ABNORMAL bit setting. */
skipped, or the store which we are not deleting if we did if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (USE_FROM_PTR (first_use_p)))
not skip any PHIs. */ SSA_NAME_OCCURS_IN_ABNORMAL_PHI (usevar) = 1;
if (skipped_phi) /* Then we need to fix the operand of the consuming stmt. */
fix_phi_uses (skipped_phi, stmt); SET_USE (first_use_p, usevar);
else
fix_stmt_v_may_defs (use, stmt);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
{ {
...@@ -334,21 +264,12 @@ dse_optimize_stmt (struct dom_walk_data *walk_data, ...@@ -334,21 +264,12 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
fprintf (dump_file, "'\n"); fprintf (dump_file, "'\n");
} }
/* Any immediate uses which reference STMT need to instead /* Remove the dead store. */
reference the new consumer, either SKIPPED_PHI or USE. bsi_remove (&bsi);
This allows us to cascade dead stores. */
redirect_immediate_uses (stmt, skipped_phi ? skipped_phi : use);
/* Be sure to remove any dataflow information attached to
this statement. */
free_df_for_stmt (stmt);
/* And release any SSA_NAMEs set in this statement back to the /* And release any SSA_NAMEs set in this statement back to the
SSA_NAME manager. */ SSA_NAME manager. */
release_defs (stmt); release_defs (stmt);
/* Finally remove the dead store. */
bsi_remove (&bsi);
} }
record_voperand_set (dse_gd->stores, &bd->stores, ann->uid); record_voperand_set (dse_gd->stores, &bd->stores, ann->uid);
...@@ -415,9 +336,6 @@ tree_ssa_dse (void) ...@@ -415,9 +336,6 @@ tree_ssa_dse (void)
dominators. */ dominators. */
calculate_dominance_info (CDI_POST_DOMINATORS); calculate_dominance_info (CDI_POST_DOMINATORS);
/* We also need immediate use information for virtual operands. */
compute_immediate_uses (TDFA_USE_VOPS, need_imm_uses_for);
/* Dead store elimination is fundamentally a walk of the post-dominator /* Dead store elimination is fundamentally a walk of the post-dominator
tree and a backwards walk of statements within each block. */ tree and a backwards walk of statements within each block. */
walk_data.walk_stmts_backward = true; walk_data.walk_stmts_backward = true;
...@@ -448,9 +366,6 @@ tree_ssa_dse (void) ...@@ -448,9 +366,6 @@ tree_ssa_dse (void)
/* Release the main bitmap. */ /* Release the main bitmap. */
BITMAP_FREE (dse_gd.stores); BITMAP_FREE (dse_gd.stores);
/* Free dataflow information. It's probably out of date now anyway. */
free_df ();
/* For now, just wipe the post-dominator information. */ /* For now, just wipe the post-dominator information. */
free_dominance_info (CDI_POST_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS);
} }
......
...@@ -113,22 +113,12 @@ Boston, MA 02111-1307, USA. */ ...@@ -113,22 +113,12 @@ Boston, MA 02111-1307, USA. */
by record_single_argument_cond_exprs and tested in need_imm_uses_for. */ by record_single_argument_cond_exprs and tested in need_imm_uses_for. */
static bitmap vars; static bitmap vars;
static bool need_imm_uses_for (tree);
static void tree_ssa_forward_propagate_single_use_vars (void); static void tree_ssa_forward_propagate_single_use_vars (void);
static void record_single_argument_cond_exprs (varray_type, static void record_single_argument_cond_exprs (varray_type,
varray_type *, varray_type *,
bitmap); bitmap);
static void substitute_single_use_vars (varray_type *, varray_type); static void substitute_single_use_vars (varray_type *, varray_type);
/* Function indicating whether we ought to include information for 'var'
when calculating immediate uses. */
static bool
need_imm_uses_for (tree var)
{
return bitmap_bit_p (vars, SSA_NAME_VERSION (var));
}
/* Find all COND_EXPRs with a condition that is a naked SSA_NAME or /* Find all COND_EXPRs with a condition that is a naked SSA_NAME or
an equality comparison against a constant. an equality comparison against a constant.
...@@ -323,27 +313,32 @@ static void ...@@ -323,27 +313,32 @@ static void
substitute_single_use_vars (varray_type *cond_worklist, substitute_single_use_vars (varray_type *cond_worklist,
varray_type vars_worklist) varray_type vars_worklist)
{ {
use_operand_p use_p;
while (VARRAY_ACTIVE_SIZE (vars_worklist) > 0) while (VARRAY_ACTIVE_SIZE (vars_worklist) > 0)
{ {
tree test_var = VARRAY_TOP_TREE (vars_worklist); tree test_var = VARRAY_TOP_TREE (vars_worklist);
tree def = SSA_NAME_DEF_STMT (test_var); tree def_stmt = SSA_NAME_DEF_STMT (test_var);
dataflow_t df; tree def;
int j, num_uses, propagated_uses; int num_uses, propagated_uses;
imm_use_iterator imm_iter;
VARRAY_POP (vars_worklist); VARRAY_POP (vars_worklist);
/* Now compute the immediate uses of TEST_VAR. */
df = get_immediate_uses (def);
num_uses = num_immediate_uses (df);
propagated_uses = 0; propagated_uses = 0;
num_uses = 0;
if (NUM_DEFS (STMT_DEF_OPS (def_stmt)) != 1)
continue;
def = DEF_OP (STMT_DEF_OPS (def_stmt), 0);
/* If TEST_VAR is used more than once and is not a boolean set /* If TEST_VAR is used more than once and is not a boolean set
via TRUTH_NOT_EXPR with another SSA_NAME as its argument, then via TRUTH_NOT_EXPR with another SSA_NAME as its argument, then
we can not optimize. */ we can not optimize. */
if (num_uses == 1 if (has_single_use (def)
|| (TREE_CODE (TREE_TYPE (test_var)) == BOOLEAN_TYPE || (TREE_CODE (TREE_TYPE (test_var)) == BOOLEAN_TYPE
&& TREE_CODE (TREE_OPERAND (def, 1)) == TRUTH_NOT_EXPR && TREE_CODE (TREE_OPERAND (def_stmt, 1)) == TRUTH_NOT_EXPR
&& (TREE_CODE (TREE_OPERAND (TREE_OPERAND (def, 1), 0)) && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (def_stmt, 1), 0))
== SSA_NAME))) == SSA_NAME)))
; ;
else else
...@@ -351,7 +346,7 @@ substitute_single_use_vars (varray_type *cond_worklist, ...@@ -351,7 +346,7 @@ substitute_single_use_vars (varray_type *cond_worklist,
/* Walk over each use and try to forward propagate the RHS of /* Walk over each use and try to forward propagate the RHS of
DEF into the use. */ DEF into the use. */
for (j = 0; j < num_uses; j++) FOR_EACH_IMM_USE_SAFE (use_p, imm_iter, def)
{ {
tree cond_stmt; tree cond_stmt;
tree cond; tree cond;
...@@ -360,7 +355,8 @@ substitute_single_use_vars (varray_type *cond_worklist, ...@@ -360,7 +355,8 @@ substitute_single_use_vars (varray_type *cond_worklist,
enum tree_code def_rhs_code; enum tree_code def_rhs_code;
tree new_cond; tree new_cond;
cond_stmt = immediate_use (df, j); cond_stmt = USE_STMT (use_p);
num_uses++;
/* For now we can only propagate into COND_EXPRs. */ /* For now we can only propagate into COND_EXPRs. */
if (TREE_CODE (cond_stmt) != COND_EXPR) if (TREE_CODE (cond_stmt) != COND_EXPR)
...@@ -368,7 +364,7 @@ substitute_single_use_vars (varray_type *cond_worklist, ...@@ -368,7 +364,7 @@ substitute_single_use_vars (varray_type *cond_worklist,
cond = COND_EXPR_COND (cond_stmt); cond = COND_EXPR_COND (cond_stmt);
cond_code = TREE_CODE (cond); cond_code = TREE_CODE (cond);
def_rhs = TREE_OPERAND (def, 1); def_rhs = TREE_OPERAND (def_stmt, 1);
def_rhs_code = TREE_CODE (def_rhs); def_rhs_code = TREE_CODE (def_rhs);
/* If the definition of the single use variable was from an /* If the definition of the single use variable was from an
...@@ -456,7 +452,7 @@ substitute_single_use_vars (varray_type *cond_worklist, ...@@ -456,7 +452,7 @@ substitute_single_use_vars (varray_type *cond_worklist,
/* Replace the condition. */ /* Replace the condition. */
COND_EXPR_COND (cond_stmt) = new_cond; COND_EXPR_COND (cond_stmt) = new_cond;
modify_stmt (cond_stmt); update_stmt (cond_stmt);
propagated_uses++; propagated_uses++;
VARRAY_PUSH_TREE (*cond_worklist, cond_stmt); VARRAY_PUSH_TREE (*cond_worklist, cond_stmt);
} }
...@@ -466,7 +462,7 @@ substitute_single_use_vars (varray_type *cond_worklist, ...@@ -466,7 +462,7 @@ substitute_single_use_vars (varray_type *cond_worklist,
whatever block it might be in. */ whatever block it might be in. */
if (num_uses && num_uses == propagated_uses) if (num_uses && num_uses == propagated_uses)
{ {
block_stmt_iterator bsi = bsi_for_stmt (def); block_stmt_iterator bsi = bsi_for_stmt (def_stmt);
bsi_remove (&bsi); bsi_remove (&bsi);
} }
} }
...@@ -502,9 +498,6 @@ tree_ssa_forward_propagate_single_use_vars (void) ...@@ -502,9 +498,6 @@ tree_ssa_forward_propagate_single_use_vars (void)
if (VARRAY_ACTIVE_SIZE (vars_worklist) > 0) if (VARRAY_ACTIVE_SIZE (vars_worklist) > 0)
{ {
/* Now compute immediate uses for all the variables we care about. */
compute_immediate_uses (TDFA_USE_OPS, need_imm_uses_for);
/* We've computed immediate uses, so we can/must clear the VARS /* We've computed immediate uses, so we can/must clear the VARS
bitmap for the next iteration. */ bitmap for the next iteration. */
bitmap_clear (vars); bitmap_clear (vars);
...@@ -512,12 +505,6 @@ tree_ssa_forward_propagate_single_use_vars (void) ...@@ -512,12 +505,6 @@ tree_ssa_forward_propagate_single_use_vars (void)
/* And optimize. This will drain VARS_WORKLIST and initialize /* And optimize. This will drain VARS_WORKLIST and initialize
COND_WORKLIST for the next iteration. */ COND_WORKLIST for the next iteration. */
substitute_single_use_vars (&cond_worklist, vars_worklist); substitute_single_use_vars (&cond_worklist, vars_worklist);
/* We do not incrementally update the dataflow information
so we must free it here and recompute the necessary bits
on the next iteration. If this turns out to be expensive,
methods for incrementally updating the dataflow are known. */
free_df ();
} }
} }
......
...@@ -971,12 +971,13 @@ single_reachable_address (struct loop *loop, tree stmt, ...@@ -971,12 +971,13 @@ single_reachable_address (struct loop *loop, tree stmt,
tree *queue = xmalloc (sizeof (tree) * max_uid); tree *queue = xmalloc (sizeof (tree) * max_uid);
sbitmap seen = sbitmap_alloc (max_uid); sbitmap seen = sbitmap_alloc (max_uid);
unsigned in_queue = 1; unsigned in_queue = 1;
dataflow_t df; unsigned i;
unsigned i, n;
struct sra_data sra_data; struct sra_data sra_data;
tree call; tree call;
tree val; tree val;
ssa_op_iter iter; ssa_op_iter iter;
imm_use_iterator imm_iter;
use_operand_p use_p;
sbitmap_zero (seen); sbitmap_zero (seen);
...@@ -1034,22 +1035,40 @@ single_reachable_address (struct loop *loop, tree stmt, ...@@ -1034,22 +1035,40 @@ single_reachable_address (struct loop *loop, tree stmt,
} }
/* Find uses of virtual names. */ /* Find uses of virtual names. */
df = get_immediate_uses (stmt); if (TREE_CODE (stmt) == PHI_NODE)
n = num_immediate_uses (df); {
if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (stmt))))
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, PHI_RESULT (stmt))
{
tree imm_stmt = USE_STMT (use_p);
for (i = 0; i < n; i++) if (TEST_BIT (seen, get_stmt_uid (imm_stmt)))
{ continue;
stmt = immediate_use (df, i);
if (!flow_bb_inside_loop_p (loop, bb_for_stmt (stmt))) if (!flow_bb_inside_loop_p (loop, bb_for_stmt (imm_stmt)))
continue; continue;
if (TEST_BIT (seen, get_stmt_uid (stmt))) SET_BIT (seen, get_stmt_uid (imm_stmt));
continue;
SET_BIT (seen, get_stmt_uid (stmt));
queue[in_queue++] = stmt; queue[in_queue++] = imm_stmt;
}
} }
else
FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_VIRTUAL_DEFS)
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, val)
{
tree imm_stmt = USE_STMT (use_p);
if (TEST_BIT (seen, get_stmt_uid (imm_stmt)))
continue;
if (!flow_bb_inside_loop_p (loop, bb_for_stmt (imm_stmt)))
continue;
SET_BIT (seen, get_stmt_uid (imm_stmt));
queue[in_queue++] = imm_stmt;
}
} }
free (queue); free (queue);
...@@ -1083,7 +1102,7 @@ rewrite_mem_refs (tree tmp_var, struct mem_ref *mem_refs) ...@@ -1083,7 +1102,7 @@ rewrite_mem_refs (tree tmp_var, struct mem_ref *mem_refs)
} }
*mem_refs->ref = tmp_var; *mem_refs->ref = tmp_var;
modify_stmt (mem_refs->stmt); update_stmt (mem_refs->stmt);
} }
} }
...@@ -1337,8 +1356,6 @@ determine_lsm (struct loops *loops) ...@@ -1337,8 +1356,6 @@ determine_lsm (struct loops *loops)
stmt_ann (bsi_stmt (bsi))->uid = max_stmt_uid++; stmt_ann (bsi_stmt (bsi))->uid = max_stmt_uid++;
} }
compute_immediate_uses (TDFA_USE_VOPS, NULL);
/* Pass the loops from the outermost. For each virtual operand loop phi node /* Pass the loops from the outermost. For each virtual operand loop phi node
check whether all the references inside the loop correspond to a single check whether all the references inside the loop correspond to a single
address, and if so, move them. */ address, and if so, move them. */
...@@ -1358,7 +1375,6 @@ determine_lsm (struct loops *loops) ...@@ -1358,7 +1375,6 @@ determine_lsm (struct loops *loops)
loop = loop->outer; loop = loop->outer;
if (loop == loops->tree_root) if (loop == loops->tree_root)
{ {
free_df ();
loop_commit_inserts (); loop_commit_inserts ();
return; return;
} }
......
...@@ -97,7 +97,7 @@ create_canonical_iv (struct loop *loop, edge exit, tree niter) ...@@ -97,7 +97,7 @@ create_canonical_iv (struct loop *loop, edge exit, tree niter)
COND_EXPR_COND (cond) = build2 (cmp, boolean_type_node, COND_EXPR_COND (cond) = build2 (cmp, boolean_type_node,
var, var,
build_int_cst (type, 0)); build_int_cst (type, 0));
modify_stmt (cond); update_stmt (cond);
} }
/* Computes an estimated number of insns in LOOP. */ /* Computes an estimated number of insns in LOOP. */
...@@ -170,19 +170,20 @@ try_unroll_loop_completely (struct loops *loops ATTRIBUTE_UNUSED, ...@@ -170,19 +170,20 @@ try_unroll_loop_completely (struct loops *loops ATTRIBUTE_UNUSED,
{ {
old_cond = COND_EXPR_COND (cond); old_cond = COND_EXPR_COND (cond);
COND_EXPR_COND (cond) = dont_exit; COND_EXPR_COND (cond) = dont_exit;
modify_stmt (cond); update_stmt (cond);
if (!tree_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop), if (!tree_duplicate_loop_to_header_edge (loop, loop_preheader_edge (loop),
loops, n_unroll, NULL, loops, n_unroll, NULL,
NULL, NULL, NULL, 0)) NULL, NULL, NULL, 0))
{ {
COND_EXPR_COND (cond) = old_cond; COND_EXPR_COND (cond) = old_cond;
update_stmt (cond);
return false; return false;
} }
} }
COND_EXPR_COND (cond) = do_exit; COND_EXPR_COND (cond) = do_exit;
modify_stmt (cond); update_stmt (cond);
if (dump_file && (dump_flags & TDF_DETAILS)) if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Unrolled loop %d completely.\n", loop->num); fprintf (dump_file, "Unrolled loop %d completely.\n", loop->num);
......
...@@ -4835,6 +4835,7 @@ rewrite_address_base (block_stmt_iterator *bsi, tree *op, tree with) ...@@ -4835,6 +4835,7 @@ rewrite_address_base (block_stmt_iterator *bsi, tree *op, tree with)
new_name = make_ssa_name (new_var, copy); new_name = make_ssa_name (new_var, copy);
} }
TREE_OPERAND (copy, 0) = new_name; TREE_OPERAND (copy, 0) = new_name;
update_stmt (copy);
bsi_insert_before (bsi, copy, BSI_SAME_STMT); bsi_insert_before (bsi, copy, BSI_SAME_STMT);
with = new_name; with = new_name;
...@@ -4898,7 +4899,7 @@ rewrite_use_compare (struct ivopts_data *data, ...@@ -4898,7 +4899,7 @@ rewrite_use_compare (struct ivopts_data *data,
bsi_insert_before (&bsi, stmts, BSI_SAME_STMT); bsi_insert_before (&bsi, stmts, BSI_SAME_STMT);
*use->op_p = build2 (compare, boolean_type_node, var, op); *use->op_p = build2 (compare, boolean_type_node, var, op);
modify_stmt (use->stmt); update_stmt (use->stmt);
return; return;
} }
...@@ -4999,19 +5000,24 @@ compute_phi_arg_on_exit (edge exit, tree stmts, tree op) ...@@ -4999,19 +5000,24 @@ compute_phi_arg_on_exit (edge exit, tree stmts, tree op)
if (!single_pred_p (exit->dest)) if (!single_pred_p (exit->dest))
split_loop_exit_edge (exit); split_loop_exit_edge (exit);
/* Ensure there is label in exit->dest, so that we can
insert after it. */
tree_block_label (exit->dest);
bsi = bsi_after_labels (exit->dest);
if (TREE_CODE (stmts) == STATEMENT_LIST) if (TREE_CODE (stmts) == STATEMENT_LIST)
{ {
for (tsi = tsi_start (stmts); !tsi_end_p (tsi); tsi_next (&tsi)) for (tsi = tsi_start (stmts); !tsi_end_p (tsi); tsi_next (&tsi))
protect_loop_closed_ssa_form (exit, tsi_stmt (tsi)); {
bsi_insert_after (&bsi, tsi_stmt (tsi), BSI_NEW_STMT);
protect_loop_closed_ssa_form (exit, bsi_stmt (bsi));
}
} }
else else
protect_loop_closed_ssa_form (exit, stmts); {
bsi_insert_after (&bsi, stmts, BSI_NEW_STMT);
/* Ensure there is label in exit->dest, so that we can protect_loop_closed_ssa_form (exit, bsi_stmt (bsi));
insert after it. */ }
tree_block_label (exit->dest);
bsi = bsi_after_labels (exit->dest);
bsi_insert_after (&bsi, stmts, BSI_CONTINUE_LINKING);
if (!op) if (!op)
return; return;
...@@ -5130,7 +5136,7 @@ rewrite_use (struct ivopts_data *data, ...@@ -5130,7 +5136,7 @@ rewrite_use (struct ivopts_data *data,
default: default:
gcc_unreachable (); gcc_unreachable ();
} }
modify_stmt (use->stmt); update_stmt (use->stmt);
} }
/* Rewrite the uses using the selected induction variables. */ /* Rewrite the uses using the selected induction variables. */
......
...@@ -415,7 +415,7 @@ verify_loop_closed_ssa (void) ...@@ -415,7 +415,7 @@ verify_loop_closed_ssa (void)
tree phi; tree phi;
unsigned i; unsigned i;
verify_ssa (); verify_ssa (false);
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
{ {
......
...@@ -249,7 +249,7 @@ tree_unswitch_single_loop (struct loops *loops, struct loop *loop, int num) ...@@ -249,7 +249,7 @@ tree_unswitch_single_loop (struct loops *loops, struct loop *loop, int num)
else else
break; break;
modify_stmt (stmt); update_stmt (stmt);
i++; i++;
} }
......
...@@ -31,13 +31,10 @@ typedef struct def_operand_ptr GTY(()) ...@@ -31,13 +31,10 @@ typedef struct def_operand_ptr GTY(())
} def_operand_p; } def_operand_p;
/* This represents a pointer to a USE operand. */ /* This represents a pointer to a USE operand. */
typedef struct use_operand_ptr GTY(()) typedef ssa_imm_use_t *use_operand_p;
{
tree * GTY((skip(""))) use;
} use_operand_p;
#define NULL_USE_OPERAND_P NULL
extern def_operand_p NULL_DEF_OPERAND_P; extern def_operand_p NULL_DEF_OPERAND_P;
extern use_operand_p NULL_USE_OPERAND_P;
/* This represents the DEF operands of a stmt. */ /* This represents the DEF operands of a stmt. */
typedef struct def_optype_d GTY(()) typedef struct def_optype_d GTY(())
...@@ -48,20 +45,24 @@ typedef struct def_optype_d GTY(()) ...@@ -48,20 +45,24 @@ typedef struct def_optype_d GTY(())
typedef def_optype_t *def_optype; typedef def_optype_t *def_optype;
/* Operand type which uses a pointer to a tree ihn an immediate use. */
typedef ssa_imm_use_t use_operand_type_t;
/* This represents the USE operands of a stmt. */ /* This represents the USE operands of a stmt. */
typedef struct use_optype_d GTY(()) typedef struct use_optype_d GTY(())
{ {
unsigned num_uses; unsigned num_uses;
struct use_operand_ptr GTY((length("%h.num_uses"))) uses[1]; struct ssa_imm_use_d GTY((length("%h.num_uses"))) uses[1];
} use_optype_t; } use_optype_t;
typedef use_optype_t *use_optype; typedef use_optype_t *use_optype;
/* Operand type which stores a def and a use tree. */ /* Operand type which stores a def a use, and an immediate use. */
typedef struct v_def_use_operand_type GTY(()) typedef struct v_def_use_operand_type GTY(())
{ {
tree def; tree def;
tree use; tree use;
ssa_imm_use_t imm_use;
} v_def_use_operand_type_t; } v_def_use_operand_type_t;
/* This represents the MAY_DEFS for a stmt. */ /* This represents the MAY_DEFS for a stmt. */
...@@ -74,11 +75,18 @@ typedef struct v_may_def_optype_d GTY(()) ...@@ -74,11 +75,18 @@ typedef struct v_may_def_optype_d GTY(())
typedef v_may_def_optype_t *v_may_def_optype; typedef v_may_def_optype_t *v_may_def_optype;
/* Operand type which stores a tree and an immeidate_use. */
typedef struct vuse_operand_type GTY(())
{
tree use;
ssa_imm_use_t imm_use;
} vuse_operand_type_t;
/* This represents the VUSEs for a stmt. */ /* This represents the VUSEs for a stmt. */
typedef struct vuse_optype_d GTY(()) typedef struct vuse_optype_d GTY(())
{ {
unsigned num_vuses; unsigned num_vuses;
tree GTY((length ("%h.num_vuses"))) vuses[1]; struct vuse_operand_type GTY((length ("%h.num_vuses"))) vuses[1];
} vuse_optype_t; } vuse_optype_t;
typedef vuse_optype_t *vuse_optype; typedef vuse_optype_t *vuse_optype;
...@@ -109,9 +117,10 @@ typedef stmt_operands_t *stmt_operands_p; ...@@ -109,9 +117,10 @@ typedef stmt_operands_t *stmt_operands_p;
#define USE_FROM_PTR(OP) get_use_from_ptr (OP) #define USE_FROM_PTR(OP) get_use_from_ptr (OP)
#define DEF_FROM_PTR(OP) get_def_from_ptr (OP) #define DEF_FROM_PTR(OP) get_def_from_ptr (OP)
#define SET_USE(OP, V) ((*((OP).use)) = (V)) #define SET_USE(OP, V) set_ssa_use_from_ptr (OP, V)
#define SET_DEF(OP, V) ((*((OP).def)) = (V)) #define SET_DEF(OP, V) ((*((OP).def)) = (V))
#define USE_STMT(OP) (OP)->stmt
#define USE_OPS(ANN) get_use_ops (ANN) #define USE_OPS(ANN) get_use_ops (ANN)
#define STMT_USE_OPS(STMT) get_use_ops (stmt_ann (STMT)) #define STMT_USE_OPS(STMT) get_use_ops (stmt_ann (STMT))
...@@ -178,14 +187,22 @@ typedef stmt_operands_t *stmt_operands_p; ...@@ -178,14 +187,22 @@ typedef stmt_operands_t *stmt_operands_p;
PHI_ARG_DEF ((PHI), (E)->dest_idx) PHI_ARG_DEF ((PHI), (E)->dest_idx)
#define PHI_ARG_DEF_PTR_FROM_EDGE(PHI, E) \ #define PHI_ARG_DEF_PTR_FROM_EDGE(PHI, E) \
PHI_ARG_DEF_PTR ((PHI), (E)->dest_idx) PHI_ARG_DEF_PTR ((PHI), (E)->dest_idx)
#define PHI_ARG_INDEX_FROM_USE(USE) phi_arg_index_from_use (USE)
extern void init_ssa_operands (void); extern void init_ssa_operands (void);
extern void fini_ssa_operands (void); extern void fini_ssa_operands (void);
extern void get_stmt_operands (tree); extern void update_stmt_operands (tree);
extern bool verify_imm_links (FILE *f, tree var);
extern void copy_virtual_operands (tree, tree); extern void copy_virtual_operands (tree, tree);
extern void create_ssa_artficial_load_stmt (stmt_operands_p, tree); extern void create_ssa_artficial_load_stmt (stmt_operands_p, tree);
extern void dump_immediate_uses (FILE *file);
extern void dump_immediate_uses_for (FILE *file, tree var);
extern void debug_immediate_uses (void);
extern void debug_immediate_uses_for (tree var);
extern bool ssa_call_clobbered_cache_valid; extern bool ssa_call_clobbered_cache_valid;
extern bool ssa_ro_call_cache_valid; extern bool ssa_ro_call_cache_valid;
......
...@@ -313,7 +313,7 @@ replace_phi_edge_with_variable (basic_block cond_block, basic_block bb, ...@@ -313,7 +313,7 @@ replace_phi_edge_with_variable (basic_block cond_block, basic_block bb,
block_stmt_iterator bsi; block_stmt_iterator bsi;
/* Change the PHI argument to new. */ /* Change the PHI argument to new. */
PHI_ARG_DEF_TREE (phi, e->dest_idx) = new; SET_USE (PHI_ARG_DEF_PTR (phi, e->dest_idx), new);
/* Remove the empty basic block. */ /* Remove the empty basic block. */
if (EDGE_SUCC (cond_block, 0)->dest == bb) if (EDGE_SUCC (cond_block, 0)->dest == bb)
......
...@@ -2056,7 +2056,7 @@ eliminate (void) ...@@ -2056,7 +2056,7 @@ eliminate (void)
NECESSARY (SSA_NAME_DEF_STMT (sprime)) = 1; NECESSARY (SSA_NAME_DEF_STMT (sprime)) = 1;
pre_stats.eliminations++; pre_stats.eliminations++;
propagate_tree_value (rhs_p, sprime); propagate_tree_value (rhs_p, sprime);
modify_stmt (stmt); update_stmt (stmt);
/* If we removed EH side effects from the statement, clean /* If we removed EH side effects from the statement, clean
its EH information. */ its EH information. */
......
...@@ -232,14 +232,12 @@ cfg_blocks_get (void) ...@@ -232,14 +232,12 @@ cfg_blocks_get (void)
static void static void
add_ssa_edge (tree var, bool is_varying) add_ssa_edge (tree var, bool is_varying)
{ {
tree stmt = SSA_NAME_DEF_STMT (var); imm_use_iterator iter;
dataflow_t df = get_immediate_uses (stmt); use_operand_p use_p;
int num_uses = num_immediate_uses (df);
int i;
for (i = 0; i < num_uses; i++) FOR_EACH_IMM_USE_FAST (use_p, iter, var)
{ {
tree use_stmt = immediate_use (df, i); tree use_stmt = USE_STMT (use_p);
if (!DONT_SIMULATE_AGAIN (use_stmt) if (!DONT_SIMULATE_AGAIN (use_stmt)
&& !STMT_IN_SSA_EDGE_WORKLIST (use_stmt)) && !STMT_IN_SSA_EDGE_WORKLIST (use_stmt))
...@@ -507,7 +505,6 @@ ssa_prop_fini (void) ...@@ -507,7 +505,6 @@ ssa_prop_fini (void)
cfg_blocks = NULL; cfg_blocks = NULL;
sbitmap_free (bb_in_list); sbitmap_free (bb_in_list);
sbitmap_free (executable_blocks); sbitmap_free (executable_blocks);
free_df ();
} }
......
...@@ -109,21 +109,26 @@ find_bb_for_arg (tree phi, tree def) ...@@ -109,21 +109,26 @@ find_bb_for_arg (tree phi, tree def)
used in, so that you only have one place you can sink it to. */ used in, so that you only have one place you can sink it to. */
static bool static bool
all_immediate_uses_same_place (dataflow_t imm) all_immediate_uses_same_place (tree stmt)
{ {
int i; tree firstuse = NULL_TREE;
tree firstuse; ssa_op_iter op_iter;
imm_use_iterator imm_iter;
if (imm == NULL || num_immediate_uses (imm) < 2) use_operand_p use_p;
return true; tree var;
firstuse = immediate_use (imm, 0);
for (i = 1; i < num_immediate_uses (imm); i++) FOR_EACH_SSA_TREE_OPERAND (var, stmt, op_iter, SSA_OP_ALL_DEFS)
{ {
tree immuse = immediate_use (imm, i); FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
if (immuse != firstuse) {
return false; if (firstuse == NULL_TREE)
firstuse = USE_STMT (use_p);
else
if (firstuse != USE_STMT (use_p))
return false;
}
} }
return true; return true;
} }
...@@ -215,24 +220,43 @@ is_hidden_global_store (tree stmt) ...@@ -215,24 +220,43 @@ is_hidden_global_store (tree stmt)
/* Find the nearest common dominator of all of the immediate uses in IMM. */ /* Find the nearest common dominator of all of the immediate uses in IMM. */
static basic_block static basic_block
nearest_common_dominator_of_uses (dataflow_t imm) nearest_common_dominator_of_uses (tree stmt)
{ {
bitmap blocks = BITMAP_ALLOC (NULL); bitmap blocks = BITMAP_ALLOC (NULL);
basic_block commondom; basic_block commondom;
int i;
unsigned int j; unsigned int j;
bitmap_iterator bi; bitmap_iterator bi;
ssa_op_iter op_iter;
imm_use_iterator imm_iter;
use_operand_p use_p;
tree var;
bitmap_clear (blocks); bitmap_clear (blocks);
for (i = 0; i < num_immediate_uses (imm); i++) FOR_EACH_SSA_TREE_OPERAND (var, stmt, op_iter, SSA_OP_ALL_DEFS)
{ {
tree usestmt = immediate_use (imm, i); FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
basic_block useblock; {
if (TREE_CODE (usestmt) == PHI_NODE) tree usestmt = USE_STMT (use_p);
{ basic_block useblock;
int j; if (TREE_CODE (usestmt) == PHI_NODE)
for (j = 0; j < PHI_NUM_ARGS (usestmt); j++) {
int j;
for (j = 0; j < PHI_NUM_ARGS (usestmt); j++)
{
useblock = PHI_ARG_EDGE (usestmt, j)->src;
/* Short circuit. Nothing dominates the entry block. */
if (useblock == ENTRY_BLOCK_PTR)
{
BITMAP_FREE (blocks);
return NULL;
}
bitmap_set_bit (blocks, useblock->index);
}
}
else
{ {
useblock = PHI_ARG_EDGE (usestmt, j)->src; useblock = bb_for_stmt (usestmt);
/* Short circuit. Nothing dominates the entry block. */ /* Short circuit. Nothing dominates the entry block. */
if (useblock == ENTRY_BLOCK_PTR) if (useblock == ENTRY_BLOCK_PTR)
{ {
...@@ -242,18 +266,6 @@ nearest_common_dominator_of_uses (dataflow_t imm) ...@@ -242,18 +266,6 @@ nearest_common_dominator_of_uses (dataflow_t imm)
bitmap_set_bit (blocks, useblock->index); bitmap_set_bit (blocks, useblock->index);
} }
} }
else
{
useblock = bb_for_stmt (usestmt);
/* Short circuit. Nothing dominates the entry block. */
if (useblock == ENTRY_BLOCK_PTR)
{
BITMAP_FREE (blocks);
return NULL;
}
bitmap_set_bit (blocks, useblock->index);
}
} }
commondom = BASIC_BLOCK (bitmap_first_set_bit (blocks)); commondom = BASIC_BLOCK (bitmap_first_set_bit (blocks));
EXECUTE_IF_SET_IN_BITMAP (blocks, 0, j, bi) EXECUTE_IF_SET_IN_BITMAP (blocks, 0, j, bi)
...@@ -271,16 +283,28 @@ nearest_common_dominator_of_uses (dataflow_t imm) ...@@ -271,16 +283,28 @@ nearest_common_dominator_of_uses (dataflow_t imm)
static tree static tree
statement_sink_location (tree stmt, basic_block frombb) statement_sink_location (tree stmt, basic_block frombb)
{ {
dataflow_t imm = get_immediate_uses (stmt);
tree use, def; tree use, def;
use_operand_p one_use = NULL_USE_OPERAND_P;
basic_block sinkbb; basic_block sinkbb;
use_operand_p use_p; use_operand_p use_p;
def_operand_p def_p; def_operand_p def_p;
ssa_op_iter iter; ssa_op_iter iter;
stmt_ann_t ann; stmt_ann_t ann;
tree rhs; tree rhs;
imm_use_iterator imm_iter;
FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
{
FOR_EACH_IMM_USE_FAST (one_use, imm_iter, def)
{
break;
}
if (one_use != NULL_USE_OPERAND_P)
break;
}
if (imm == NULL) /* Return if there are no immediate uses of this stmt. */
if (one_use == NULL_USE_OPERAND_P)
return NULL; return NULL;
if (TREE_CODE (stmt) != MODIFY_EXPR) if (TREE_CODE (stmt) != MODIFY_EXPR)
...@@ -314,8 +338,7 @@ statement_sink_location (tree stmt, basic_block frombb) ...@@ -314,8 +338,7 @@ statement_sink_location (tree stmt, basic_block frombb)
|| TREE_CODE (rhs) == EXC_PTR_EXPR || TREE_CODE (rhs) == EXC_PTR_EXPR
|| TREE_CODE (rhs) == FILTER_EXPR || TREE_CODE (rhs) == FILTER_EXPR
|| is_hidden_global_store (stmt) || is_hidden_global_store (stmt)
|| ann->has_volatile_ops || ann->has_volatile_ops)
|| num_immediate_uses (imm) == 0)
return NULL; return NULL;
FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_ALL_DEFS) FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_ALL_DEFS)
...@@ -337,9 +360,9 @@ statement_sink_location (tree stmt, basic_block frombb) ...@@ -337,9 +360,9 @@ statement_sink_location (tree stmt, basic_block frombb)
common dominator of all the immediate uses. For PHI nodes, we have to common dominator of all the immediate uses. For PHI nodes, we have to
find the nearest common dominator of all of the predecessor blocks, since find the nearest common dominator of all of the predecessor blocks, since
that is where insertion would have to take place. */ that is where insertion would have to take place. */
if (!all_immediate_uses_same_place (imm)) if (!all_immediate_uses_same_place (stmt))
{ {
basic_block commondom = nearest_common_dominator_of_uses (imm); basic_block commondom = nearest_common_dominator_of_uses (stmt);
if (commondom == frombb) if (commondom == frombb)
return NULL; return NULL;
...@@ -371,7 +394,7 @@ statement_sink_location (tree stmt, basic_block frombb) ...@@ -371,7 +394,7 @@ statement_sink_location (tree stmt, basic_block frombb)
return first_stmt (commondom); return first_stmt (commondom);
} }
use = immediate_use (imm, 0); use = USE_STMT (one_use);
if (TREE_CODE (use) != PHI_NODE) if (TREE_CODE (use) != PHI_NODE)
{ {
sinkbb = bb_for_stmt (use); sinkbb = bb_for_stmt (use);
...@@ -527,13 +550,11 @@ execute_sink_code (void) ...@@ -527,13 +550,11 @@ execute_sink_code (void)
connect_infinite_loops_to_exit (); connect_infinite_loops_to_exit ();
memset (&sink_stats, 0, sizeof (sink_stats)); memset (&sink_stats, 0, sizeof (sink_stats));
calculate_dominance_info (CDI_DOMINATORS | CDI_POST_DOMINATORS); calculate_dominance_info (CDI_DOMINATORS | CDI_POST_DOMINATORS);
compute_immediate_uses (TDFA_USE_OPS | TDFA_USE_VOPS, NULL);
sink_code_in_bb (EXIT_BLOCK_PTR); sink_code_in_bb (EXIT_BLOCK_PTR);
if (dump_file && (dump_flags & TDF_STATS)) if (dump_file && (dump_flags & TDF_STATS))
fprintf (dump_file, "Sunk statements:%d\n", sink_stats.sunk); fprintf (dump_file, "Sunk statements:%d\n", sink_stats.sunk);
free_dominance_info (CDI_POST_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS);
remove_fake_exit_edges (); remove_fake_exit_edges ();
free_df ();
loop_optimizer_finalize (loops, dump_file); loop_optimizer_finalize (loops, dump_file);
} }
......
...@@ -306,7 +306,7 @@ create_edge_and_update_destination_phis (struct redirection_data *rd) ...@@ -306,7 +306,7 @@ create_edge_and_update_destination_phis (struct redirection_data *rd)
for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi)) for (phi = phi_nodes (e->dest); phi; phi = PHI_CHAIN (phi))
{ {
int indx = rd->outgoing_edge->dest_idx; int indx = rd->outgoing_edge->dest_idx;
add_phi_arg (phi, PHI_ARG_DEF_TREE (phi, indx), e); add_phi_arg (phi, PHI_ARG_DEF (phi, indx), e);
} }
} }
......
...@@ -172,6 +172,7 @@ tree ...@@ -172,6 +172,7 @@ tree
make_ssa_name (tree var, tree stmt) make_ssa_name (tree var, tree stmt)
{ {
tree t; tree t;
ssa_imm_use_t *imm;
gcc_assert (DECL_P (var) gcc_assert (DECL_P (var)
|| TREE_CODE (var) == INDIRECT_REF); || TREE_CODE (var) == INDIRECT_REF);
...@@ -207,6 +208,11 @@ make_ssa_name (tree var, tree stmt) ...@@ -207,6 +208,11 @@ make_ssa_name (tree var, tree stmt)
SSA_NAME_DEF_STMT (t) = stmt; SSA_NAME_DEF_STMT (t) = stmt;
SSA_NAME_PTR_INFO (t) = NULL; SSA_NAME_PTR_INFO (t) = NULL;
SSA_NAME_IN_FREE_LIST (t) = 0; SSA_NAME_IN_FREE_LIST (t) = 0;
imm = &(SSA_NAME_IMM_USE_NODE (t));
imm->use = NULL;
imm->prev = imm;
imm->next = imm;
imm->stmt = t;
return t; return t;
} }
...@@ -248,10 +254,26 @@ release_ssa_name (tree var) ...@@ -248,10 +254,26 @@ release_ssa_name (tree var)
{ {
tree saved_ssa_name_var = SSA_NAME_VAR (var); tree saved_ssa_name_var = SSA_NAME_VAR (var);
int saved_ssa_name_version = SSA_NAME_VERSION (var); int saved_ssa_name_version = SSA_NAME_VERSION (var);
ssa_imm_use_t *imm = &(SSA_NAME_IMM_USE_NODE (var));
#ifdef ENABLE_CHECKING
verify_imm_links (stderr, var);
#endif
while (imm->next != imm)
{
delink_imm_use (imm->next);
}
#ifdef ENABLE_CHECKING
if (imm->next != imm)
abort();
#endif
VARRAY_TREE (ssa_names, SSA_NAME_VERSION (var)) = NULL; VARRAY_TREE (ssa_names, SSA_NAME_VERSION (var)) = NULL;
memset (var, 0, tree_size (var)); memset (var, 0, tree_size (var));
imm->prev = imm;
imm->next = imm;
imm->stmt = var;
/* First put back the right tree node so that the tree checking /* First put back the right tree node so that the tree checking
macros do not complain. */ macros do not complain. */
TREE_SET_CODE (var, SSA_NAME); TREE_SET_CODE (var, SSA_NAME);
......
...@@ -668,7 +668,7 @@ adjust_return_value (basic_block bb, tree m, tree a) ...@@ -668,7 +668,7 @@ adjust_return_value (basic_block bb, tree m, tree a)
} }
TREE_OPERAND (ret_stmt, 0) = var; TREE_OPERAND (ret_stmt, 0) = var;
modify_stmt (ret_stmt); update_stmt (ret_stmt);
} }
/* Eliminates tail call described by T. TMP_VARS is a list of /* Eliminates tail call described by T. TMP_VARS is a list of
......
...@@ -2054,9 +2054,10 @@ vect_stmt_relevant_p (tree stmt, loop_vec_info loop_vinfo) ...@@ -2054,9 +2054,10 @@ vect_stmt_relevant_p (tree stmt, loop_vec_info loop_vinfo)
v_may_def_optype v_may_defs; v_may_def_optype v_may_defs;
v_must_def_optype v_must_defs; v_must_def_optype v_must_defs;
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
int i; ssa_op_iter op_iter;
dataflow_t df; imm_use_iterator imm_iter;
int num_uses; use_operand_p use_p;
tree var;
/* cond stmt other than loop exit cond. */ /* cond stmt other than loop exit cond. */
if (is_ctrl_stmt (stmt) && (stmt != LOOP_VINFO_EXIT_COND (loop_vinfo))) if (is_ctrl_stmt (stmt) && (stmt != LOOP_VINFO_EXIT_COND (loop_vinfo)))
...@@ -2076,17 +2077,17 @@ vect_stmt_relevant_p (tree stmt, loop_vec_info loop_vinfo) ...@@ -2076,17 +2077,17 @@ vect_stmt_relevant_p (tree stmt, loop_vec_info loop_vinfo)
} }
/* uses outside the loop. */ /* uses outside the loop. */
df = get_immediate_uses (stmt); FOR_EACH_SSA_TREE_OPERAND (var, stmt, op_iter, SSA_OP_DEF)
num_uses = num_immediate_uses (df);
for (i = 0; i < num_uses; i++)
{ {
tree use = immediate_use (df, i); FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
basic_block bb = bb_for_stmt (use);
if (!flow_bb_inside_loop_p (loop, bb))
{ {
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC)) basic_block bb = bb_for_stmt (USE_STMT (use_p));
fprintf (vect_dump, "vec_stmt_relevant_p: used out of loop."); if (!flow_bb_inside_loop_p (loop, bb))
return true; {
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "vec_stmt_relevant_p: used out of loop.");
return true;
}
} }
} }
......
...@@ -170,7 +170,6 @@ static void rename_variables_in_loop (struct loop *); ...@@ -170,7 +170,6 @@ static void rename_variables_in_loop (struct loop *);
General Vectorization Utilities General Vectorization Utilities
*************************************************************************/ *************************************************************************/
static void vect_set_dump_settings (void); static void vect_set_dump_settings (void);
static bool need_imm_uses_for (tree);
/* vect_dump will be set to stderr or dump_file if exist. */ /* vect_dump will be set to stderr or dump_file if exist. */
FILE *vect_dump; FILE *vect_dump;
...@@ -1815,19 +1814,6 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init, ...@@ -1815,19 +1814,6 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init,
} }
/* Function need_imm_uses_for.
Return whether we ought to include information for 'var'
when calculating immediate uses. For this pass we only want use
information for non-virtual variables. */
static bool
need_imm_uses_for (tree var)
{
return is_gimple_reg (var);
}
/* Function vectorize_loops. /* Function vectorize_loops.
Entry Point to loop vectorization phase. */ Entry Point to loop vectorization phase. */
...@@ -1854,8 +1840,6 @@ vectorize_loops (struct loops *loops) ...@@ -1854,8 +1840,6 @@ vectorize_loops (struct loops *loops)
verify_loop_closed_ssa (); verify_loop_closed_ssa ();
#endif #endif
compute_immediate_uses (TDFA_USE_OPS, need_imm_uses_for);
/* ----------- Analyze loops. ----------- */ /* ----------- Analyze loops. ----------- */
/* If some loop was duplicated, it gets bigger number /* If some loop was duplicated, it gets bigger number
...@@ -1886,7 +1870,6 @@ vectorize_loops (struct loops *loops) ...@@ -1886,7 +1870,6 @@ vectorize_loops (struct loops *loops)
/* ----------- Finalize. ----------- */ /* ----------- Finalize. ----------- */
free_df ();
for (i = 1; i < loops_num; i++) for (i = 1; i < loops_num; i++)
{ {
struct loop *loop = loops->parray[i]; struct loop *loop = loops->parray[i];
......
...@@ -1348,6 +1348,21 @@ struct tree_exp GTY(()) ...@@ -1348,6 +1348,21 @@ struct tree_exp GTY(())
struct ptr_info_def; struct ptr_info_def;
#endif #endif
/* Immediate use linking structure. THis structure is used for maintaining
a doubly linked list of uses of an SSA_NAME. */
typedef struct ssa_imm_use_d GTY(())
{
struct ssa_imm_use_d* GTY((skip(""))) prev;
struct ssa_imm_use_d* GTY((skip(""))) next;
tree GTY((skip(""))) stmt;
tree *GTY((skip(""))) use;
} ssa_imm_use_t;
/* Return the immediate_use information for an SSA_NAME. */
#define SSA_NAME_IMM_USE_NODE(NODE) SSA_NAME_CHECK (NODE)->ssa_name.imm_uses
struct tree_ssa_name GTY(()) struct tree_ssa_name GTY(())
{ {
struct tree_common common; struct tree_common common;
...@@ -1370,9 +1385,19 @@ struct tree_ssa_name GTY(()) ...@@ -1370,9 +1385,19 @@ struct tree_ssa_name GTY(())
/* Auxiliary information stored with the ssa name. */ /* Auxiliary information stored with the ssa name. */
PTR GTY((skip)) aux; PTR GTY((skip)) aux;
/* Immediate uses list for this SSA_NAME. */
struct ssa_imm_use_d imm_uses;
}; };
/* In a PHI_NODE node. */ /* In a PHI_NODE node. */
/* These 2 macros should be considered off limits for use by developers. If
you wish to access the use or def fields of a PHI_NODE in the SSA
optimizers, use the accessor macros found in tree-ssa-operands.h.
These two macros are to be used only by those accessor macros, and other
select places where we *absolutly* must take the address of the tree. */
#define PHI_RESULT_TREE(NODE) PHI_NODE_CHECK (NODE)->phi.result #define PHI_RESULT_TREE(NODE) PHI_NODE_CHECK (NODE)->phi.result
#define PHI_ARG_DEF_TREE(NODE, I) PHI_NODE_ELT_CHECK (NODE, I).def #define PHI_ARG_DEF_TREE(NODE, I) PHI_NODE_ELT_CHECK (NODE, I).def
...@@ -1390,12 +1415,13 @@ struct tree_ssa_name GTY(()) ...@@ -1390,12 +1415,13 @@ struct tree_ssa_name GTY(())
#define PHI_ARG_EDGE(NODE, I) (EDGE_PRED (PHI_BB ((NODE)), (I))) #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_ARG_IMM_USE_NODE(NODE, I) PHI_NODE_ELT_CHECK (NODE, I).imm_use
struct edge_def; struct edge_def;
struct phi_arg_d GTY(()) struct phi_arg_d GTY(())
{ {
struct ssa_imm_use_d imm_use; /* imm_use MUST be first element in struct. */
tree def; tree def;
bool nonzero; bool nonzero;
}; };
...@@ -1414,9 +1440,6 @@ struct tree_phi_node GTY(()) ...@@ -1414,9 +1440,6 @@ struct tree_phi_node GTY(())
/* Basic block to that the phi node belongs. */ /* Basic block to that the phi node belongs. */
struct basic_block_def *bb; struct basic_block_def *bb;
/* Dataflow information. */
struct dataflow_d *df;
struct phi_arg_d GTY ((length ("((tree)&%h)->phi.num_args"))) a[1]; struct phi_arg_d GTY ((length ("((tree)&%h)->phi.num_args"))) a[1];
}; };
...@@ -3895,6 +3918,7 @@ enum tree_dump_index ...@@ -3895,6 +3918,7 @@ enum tree_dump_index
#define TDF_TREE (1 << 9) /* is a tree dump */ #define TDF_TREE (1 << 9) /* is a tree dump */
#define TDF_RTL (1 << 10) /* is a RTL dump */ #define TDF_RTL (1 << 10) /* is a RTL dump */
#define TDF_IPA (1 << 11) /* is an IPA dump */ #define TDF_IPA (1 << 11) /* is an IPA dump */
#define TDF_STMTADDR (1 << 12) /* Address of stmt. */
typedef struct dump_info *dump_info_p; typedef struct dump_info *dump_info_p;
......
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