lambda-code.c (gcc_loop_to_lambda_loop, [...]): Use generic operand interface.

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

	* lambda-code.c (gcc_loop_to_lambda_loop,
	lambda_loopnest_to_gcc_loopnest, phi_loop_edge_uses_def,
	stmt_is_bumper_for_loop, perfect_nest_p, replace_uses_of_x_with_y): Use
	generic operand interface.
	* tree-data-ref.c (find_data_references_in_loop): Use generic interface.
	* tree-dfa.c (collect_dfa_stats_r, mark_new_vars_to_rename): Use
	generic operand interface.
	* tree-flow-inline.h (delink_imm_use, link_imm_use_to_list,
	link_imm_use, link_imm_use_stmt, relink_imm_use, relink_imm_use_stmt,
	next_safe_imm_use, has_zero_uses, has_single_use, single_imm_use,
	num_imm_uses): Use ssa_use_operand_t.
	(get_def_ops, get_use_ops, get_v_may_def_ops, get_vuse_ops,
	get_v_must_def_ops): Delete.
	(get_def_from_ptr, get_phi_result_ptr): Get def directly now.
	(get_use_op_ptr, get_def_op_ptr, get_v_may_def_result_ptr,
	get_v_may_def_op_ptr, get_vuse_op_ptr, get_v_must_def_result_ptr,
	get_v_must_def_kill_ptr): Delete.
	(delink_stmt_imm_use): Move and use new operand interface.
	(op_iter_next_use, op_iter_next_def, op_iter_next_tree, op_iter_init,
	op_iter_next_tree): Use new operand implementation.
	(clear_and_done_ssa_iter): New.  Initialize a blank operand iterator.
	(op_iter_init_use, op_iter_init_def, op_iter_init_tree): Add iterator
	type check.
	(op_iter_next_mustdef, op_iter_next_maydef,
	op_iter_next_must_and_may_def): Delete. Replace with...
	(op_iter_next_maymustdef): New.  Combine must and may next operations.
	(op_iter_init_maydef, op_iter_init_mustdef,
	op_iter_init_must_and_may_def): Use new interface.
	(single_ssa_tree_operand ): New.  Process single operands only as trees.
	(single_ssa_use_operand): New.  Process single operands only as uses.
	(single_ssa_def_operand): New.  Process single operands only as defs.
	(zero_ssa_operands): New.  Return TRUE if there are zero operands of the
	specified types.
	(num_ssa_operands): New.  Count the number of specified operands.
	(compare_ssa_operands_equal): New.  Compare two statements' operands.
	(single_phi_def): New.  Return true if PHI has one def of the specified
	operand type.
	(op_iter_init_phiuse): New.  Initialize the iterator for PHI arguments.
	(op_iter_init_phidef): New.  Initialize the iterator for the PHI def.
	* tree-flow.h (struct immediate_use_iterator_d): Use ssa_use_operand_t.
	(struct stmt_ann_d): Operands field no longer require GTY().
	(vn_compute, vn_lookup_or_add, vn_add, vn_lookup): Change prototype.
	* tree-into-ssa.c (mark_def_sites): Use SSA_OP_VMUSTKILL.
	* tree-outof-ssa.c (check_replaceable, find_replaceable_in_bb,
	dump_replaceable_exprs, rewrite_trees): Use generic interface.
	* tree-phinodes.c (make_phi_node, release_phi_node, resize_phi_node):
	Use use_operand_p instead of ssa_imm_use_t *.
	* tree-pretty-print.c (dump_vops): check if operands are active before
	dumping virtual operands.
	* tree-sra.c (sra_walk_function): Use ZERO_SSA_OPERANDS.
	* tree-ssa-ccp.c (likely_value): Use ZERO_SSA_OPERANDS.
	(ccp_fold): Use new interface.
	(ccp_visit_stmt): Remove unused variables and code.
	(convert_to_gimple_builtin): Insert statements before calling
	mark_new_vars_to_rename.
	* tree-ssa-copy.c (stmt_may_generate_copy): Use ZERO_SSA_OPERANDS.
	(copy_prop_visit_cond_stmt): Use generic interface.
	* tree-ssa-dom.c (struct expr_hash_elt): Use stmt pointer, not the
	annotation in table.
	(thread_across_edge): Use generic interface.
	(initialize_hash_element): Initialzie with stmt, not annotation.
	(eliminate_redundant_computations): Use generic interface.
	(record_equivalences_from_stmt): Pass stmt, not annotation.
	(avail_expr_hash, real_avail_expr_hash, avail_expr_eq): Use generic
	interface.
	* tree-ssa-dse.c (dse_optimize_stmt): Use ZERO_SSA_OPERANDS.
	* tree-ssa-loop-ivopts.c (find_invariants_stmt,
	find_interesting_uses_stmt, protect_loop_closed_ssa_form_use): Use
	generic operand interface.
	* tree-ssa-loop-niter.c (chain_of_csts_start, get_val_for): Use generic
	interface.
	* tree-ssa-loop-unswitch.c (tree_may_unswitch_on): Use Generic operand
	Interface.
	* tree-ssa-operands.c (struct opbuild_list_d): New.  Operand build type.
	(build_defs, build_uses, build_v_may_defs, build_vuses,
	build_v_must_defs): Change type to struct opbuild_list_d.
	(ops_active): New.  Operands active boolean.
	(operand_memory, operand_memory_index): New.  Operand memory managers.
	(allocate_def_optype, allocate_use_optype, allocate_v_may_def_optype,
	allocate_vuse_optype, allocate_v_must_def_optype): Delete.
	(free_uses, free_defs, free_vuses, free_v_may_defs, free_v_must_defs):
	Change from functions to static variable list heads.
	(opbuild_initialize_virtual): New.  Initialize a virtual build list.
	(opbuild_initialize_real): New.  Initialize a virtual build list.
	(opbuild_free): New.  Free a build list.
	(opbuild_num_elems): New.  Number of items in a list.
	(opbuild_append_real): New.  Add a real (tree *) operand.
	(opbuild_append_virtual): New.  Add and sort a virtual (tree) operand.
	(opbuild_first): New.  Return first element index in a list.
	(opbuild_next): New.  Return next element in a list.
	(opbuild_elem_real): New.  Return real element.
	(opbuild_elem_virtual): New.  Return virtual element.
	(opbuild_elem_uid): New.  Return UID of virtual element.
	(opbuild_clear): New.  Reset an operand list.
	(opbuild_remove_elem): New.  Remove an element form a list.
	(ssa_operands_active): New.  Return true if operand cache is active.
	(init_ssa_operands, fini_ssa_operands): Initialize new implementation.
	(ssa_operand_alloc): New.  Allocate memory from an operand chunk.
	(correct_use_link): Use use_operand_p.
	(finalize_ssa_uses, finalize_ssa_v_may_defs, finalize_ssa_defs,
	finalize_ssa_vuses, finalize_ssa_v_must_defs): New implmentation.
	(cleanup_v_may_defs): Use new implmentation.
	(finalize_ssa_stmt_operands, start_ssa_stmt_operands): New
	implementation.
	(append_def, append_use, append_v_may_def, append_vuse,
	append_v_must_def): Call opbuild_append routine instead of using varray.
	(build_ssa_operands): Simplify to simply use stmt, don't maintain a
	global parse_old_ops variable.
	(free_ssa_operands): New implementation.
	(update_stmt_operands): Move.  Change argument to build_ssa_operands.
	(copy_virtual_operands): Move. New generic implementation.
	(create_ssa_artficial_load_stmt): Move. New implementation.
	(swap_tree_operands): Update for new implementation.
	(get_expr_operands): Add stmt parameter to calls to swap_tree_operands.
	(add_call_clobber_ops, add_call_read_ops): Initialize opbuild list
	rather than a varray.
	(verify_imm_links): Use use_operand_p.
	(dump_immediate_uses_for): If the immediate use variable is a virtual
	variable, show the virtual ops in the stmt.
	* tree-ssa-operands.h (def_operand_p): No longer a structure.
	(NULL_DEF_OPERAND_P): Now a #define.
	(def_optype_d, use_optype_d, v_def_use_operand_type, v_may_def_optype_d,
	vuse_operand_type, vuse_optype_d, v_must_def_optype_d): Delete.
	(def_optype_d, use_optype_d, maydef_optype_d, vuse_optype_d,
	mustdef_optype_d): New.  Use Linked list representation.
	(SSA_OPERAND_MEMORY_SIZE): New.  Size of operand memory chunk.
	(struct ssa_operand_memory_d): New.  Allocated Chunk node.
	(struct stmt_operands_d): Change to new pointers that are not GTY.
	(STMT_USE_OPS, NUM_USES, SET_USE_OP, STMT_DEF_OPS, NUM_DEFS, SET_DEF_OP,
	STMT_V_MAY_DEF_OPS, NUM_V_MAY_DEFS, SET_V_MAY_DEF_RESULT,
	SET_V_MAY_DEF_OP, STMT_VUSE_OPS, NUM_VUSES, SET_VUSE_OP,
	STMT_V_MUST_DEF_OPS, NUM_V_MUST_DEFS, SET_V_MUST_DEF_RESULT,
	SET_V_MUST_DEF_KILL): Delete.
	(V_MAY_DEF_OPS, V_MAY_DEF_RESULT_PTR, V_MAY_DEF_RESULT,
	V_MAY_DEF_OP_PTR, V_MAY_DEF_OP): Rename to MAYDEF_*.
	(V_MUST_DEF_OPS, V_MUST_DEF_RESULT_PTR, V_MUST_DEF_RESULT,
	V_MUST_DEF_KILL_PTR, V_MUST_DEF_KILL): Rename to MUSTDEF_*.
	(enum ssa_op_iter_type): Operand iterator typechecking values.
	(struct ssa_operand_iterator_d): Use linked lists of operands.
	(SSA_OP_VMUSTDEFKILL): Rename to SSA_OP_VMUSTKILL.
	(FOR_EACH_SSA_MAYDEF_OPERAND, FOR_EACH_SSA_MUSTDEF_OPERAND,
	FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND): Use op_iter_next_maymustdef.
	(FOR_EACH_PHI_ARG): New.  Iterate over PHI arguments.
	(FOR_EACH_PHI_OR_STMT_USE): New.  Iterate over PHI or stmt uses.
	(FOR_EACH_PHI_OR_STMT_DEF): New.  Iterate over PHI or stmt defs.
	(SINGLE_SSA_TREE_OPERAND, SINGLE_SSA_USE_OPERAND,
	SINGLE_SSA_DEF_OPERAND, ZERO_SSA_OPERANDS, NUM_SSA_OPERANDS): New.
	* tree-ssa-opfinalize.h: New.  Function templates for expansion.
	(FINALIZE_ALLOC): Expands into alloc_def, alloc_use, alloc_maydef,
	alloc_vuse, and alloc_mustdef.
	(FINALIZE_FUNC): Expands into finalize_ssa_def_ops,
	finalize_ssa_use_ops, finalize_ssa_v_may_def_ops, finalize_ssa_vuse_ops,
	and finalize_ssa_v_must_def_ops.
	* tree-ssa-pre.c (add_to_sets): Pass tree to vn_add.
	(create_value_expr_from): Use stmt not vuse_optype as a parameter. Pass
	stmt around.
	(compute_avail): Use generic iterator interface.
	* tree-ssa-propagate.c (first_vdef): Use generic operand interface.
	(stmt_makes_single_load, stmt_makes_single_store): Use
	ZERO_SSA_OPERANDS.
	* tree-ssa-sink.c (is_hidden_global_store): Use ZERO_SSA_OPERANDS.
	(statement_sink_location): Use generic interface.
	* tree-ssa.c (verify_ssa):  Use %p in fprintf.  Use generic interface.
	(delete_tree_ssa): Don't call release_defs.  Call release_ssa_name and
	reset the immediate use link nodes.
	(stmt_references_memory_p): Use ZERO_SSA_OPERANDS.
	* tree-ssanames.c (make_ssa_name): Use use_operand_p.
	* tree-tailcall.c (find_tail_calls): Use ZERO_SSA_OPERANDS.
	(eliminate_tail_call): Use generic operand interface.
	* tree-vect-analyze.c (vect_analyze_data_refs): Use ZERO_SSA_OPERANDS.
	(vect_mark_relevant, vect_mark_stmts_to_be_vectorized): Use generic
	interface.
	* tree-vect-transform.c (update_vuses_to_preheader): Use generic
	interface.
	* tree-vectorizer.c (rename_variables_in_bb): Use generic interface.
	* tree-vn.c (struct val_expr_pair_d): Cache statment pointer instead of
	vuse_optype.
	(vn_compute, val_expr_pair_hash, vn_add, vn_lookup, vn_lookup_or_add):
	Use statement pointer instead of vuse_optype.  Use generic interface.
	* tree-vrp.c (maybe_add_assert_expr): Use generic interface.
	(stmt_interesting_for_vrp, vrp_visit_stmt): Use ZERO_SSA_OPERANDS.
	* tree.h (struct ssa_imm_use_d): Renamed to ssa_use_operand_d.
	(tree_ssa_name, phi_arg_d): Use ssa_use_operand_d.
	* doc/tree-ssa.texi: Update documentation for operand interface.

From-SVN: r99155
This commit is contained in:
Andrew MacLeod 2005-05-03 12:19:56 +00:00 committed by Andrew Macleod
parent 992d08b1a1
commit f47c96aac5
34 changed files with 2048 additions and 1834 deletions

View File

@ -1,3 +1,190 @@
2005-05-03 Andrew MacLeod <amacleod@redhat.com>
* lambda-code.c (gcc_loop_to_lambda_loop,
lambda_loopnest_to_gcc_loopnest, phi_loop_edge_uses_def,
stmt_is_bumper_for_loop, perfect_nest_p, replace_uses_of_x_with_y): Use
generic operand interface.
* tree-data-ref.c (find_data_references_in_loop): Use generic interface.
* tree-dfa.c (collect_dfa_stats_r, mark_new_vars_to_rename): Use
generic operand interface.
* tree-flow-inline.h (delink_imm_use, link_imm_use_to_list,
link_imm_use, link_imm_use_stmt, relink_imm_use, relink_imm_use_stmt,
next_safe_imm_use, has_zero_uses, has_single_use, single_imm_use,
num_imm_uses): Use ssa_use_operand_t.
(get_def_ops, get_use_ops, get_v_may_def_ops, get_vuse_ops,
get_v_must_def_ops): Delete.
(get_def_from_ptr, get_phi_result_ptr): Get def directly now.
(get_use_op_ptr, get_def_op_ptr, get_v_may_def_result_ptr,
get_v_may_def_op_ptr, get_vuse_op_ptr, get_v_must_def_result_ptr,
get_v_must_def_kill_ptr): Delete.
(delink_stmt_imm_use): Move and use new operand interface.
(op_iter_next_use, op_iter_next_def, op_iter_next_tree, op_iter_init,
op_iter_next_tree): Use new operand implementation.
(clear_and_done_ssa_iter): New. Initialize a blank operand iterator.
(op_iter_init_use, op_iter_init_def, op_iter_init_tree): Add iterator
type check.
(op_iter_next_mustdef, op_iter_next_maydef,
op_iter_next_must_and_may_def): Delete. Replace with...
(op_iter_next_maymustdef): New. Combine must and may next operations.
(op_iter_init_maydef, op_iter_init_mustdef,
op_iter_init_must_and_may_def): Use new interface.
(single_ssa_tree_operand ): New. Process single operands only as trees.
(single_ssa_use_operand): New. Process single operands only as uses.
(single_ssa_def_operand): New. Process single operands only as defs.
(zero_ssa_operands): New. Return TRUE if there are zero operands of the
specified types.
(num_ssa_operands): New. Count the number of specified operands.
(compare_ssa_operands_equal): New. Compare two statements' operands.
(single_phi_def): New. Return true if PHI has one def of the specified
operand type.
(op_iter_init_phiuse): New. Initialize the iterator for PHI arguments.
(op_iter_init_phidef): New. Initialize the iterator for the PHI def.
* tree-flow.h (struct immediate_use_iterator_d): Use ssa_use_operand_t.
(struct stmt_ann_d): Operands field no longer require GTY().
(vn_compute, vn_lookup_or_add, vn_add, vn_lookup): Change prototype.
* tree-into-ssa.c (mark_def_sites): Use SSA_OP_VMUSTKILL.
* tree-outof-ssa.c (check_replaceable, find_replaceable_in_bb,
dump_replaceable_exprs, rewrite_trees): Use generic interface.
* tree-phinodes.c (make_phi_node, release_phi_node, resize_phi_node):
Use use_operand_p instead of ssa_imm_use_t *.
* tree-pretty-print.c (dump_vops): check if operands are active before
dumping virtual operands.
* tree-sra.c (sra_walk_function): Use ZERO_SSA_OPERANDS.
* tree-ssa-ccp.c (likely_value): Use ZERO_SSA_OPERANDS.
(ccp_fold): Use new interface.
(ccp_visit_stmt): Remove unused variables and code.
(convert_to_gimple_builtin): Insert statements before calling
mark_new_vars_to_rename.
* tree-ssa-copy.c (stmt_may_generate_copy): Use ZERO_SSA_OPERANDS.
(copy_prop_visit_cond_stmt): Use generic interface.
* tree-ssa-dom.c (struct expr_hash_elt): Use stmt pointer, not the
annotation in table.
(thread_across_edge): Use generic interface.
(initialize_hash_element): Initialzie with stmt, not annotation.
(eliminate_redundant_computations): Use generic interface.
(record_equivalences_from_stmt): Pass stmt, not annotation.
(avail_expr_hash, real_avail_expr_hash, avail_expr_eq): Use generic
interface.
* tree-ssa-dse.c (dse_optimize_stmt): Use ZERO_SSA_OPERANDS.
* tree-ssa-loop-ivopts.c (find_invariants_stmt,
find_interesting_uses_stmt, protect_loop_closed_ssa_form_use): Use
generic operand interface.
* tree-ssa-loop-niter.c (chain_of_csts_start, get_val_for): Use generic
interface.
* tree-ssa-loop-unswitch.c (tree_may_unswitch_on): Use Generic operand
Interface.
* tree-ssa-operands.c (struct opbuild_list_d): New. Operand build type.
(build_defs, build_uses, build_v_may_defs, build_vuses,
build_v_must_defs): Change type to struct opbuild_list_d.
(ops_active): New. Operands active boolean.
(operand_memory, operand_memory_index): New. Operand memory managers.
(allocate_def_optype, allocate_use_optype, allocate_v_may_def_optype,
allocate_vuse_optype, allocate_v_must_def_optype): Delete.
(free_uses, free_defs, free_vuses, free_v_may_defs, free_v_must_defs):
Change from functions to static variable list heads.
(opbuild_initialize_virtual): New. Initialize a virtual build list.
(opbuild_initialize_real): New. Initialize a virtual build list.
(opbuild_free): New. Free a build list.
(opbuild_num_elems): New. Number of items in a list.
(opbuild_append_real): New. Add a real (tree *) operand.
(opbuild_append_virtual): New. Add and sort a virtual (tree) operand.
(opbuild_first): New. Return first element index in a list.
(opbuild_next): New. Return next element in a list.
(opbuild_elem_real): New. Return real element.
(opbuild_elem_virtual): New. Return virtual element.
(opbuild_elem_uid): New. Return UID of virtual element.
(opbuild_clear): New. Reset an operand list.
(opbuild_remove_elem): New. Remove an element form a list.
(ssa_operands_active): New. Return true if operand cache is active.
(init_ssa_operands, fini_ssa_operands): Initialize new implementation.
(ssa_operand_alloc): New. Allocate memory from an operand chunk.
(correct_use_link): Use use_operand_p.
(finalize_ssa_uses, finalize_ssa_v_may_defs, finalize_ssa_defs,
finalize_ssa_vuses, finalize_ssa_v_must_defs): New implmentation.
(cleanup_v_may_defs): Use new implmentation.
(finalize_ssa_stmt_operands, start_ssa_stmt_operands): New
implementation.
(append_def, append_use, append_v_may_def, append_vuse,
append_v_must_def): Call opbuild_append routine instead of using varray.
(build_ssa_operands): Simplify to simply use stmt, don't maintain a
global parse_old_ops variable.
(free_ssa_operands): New implementation.
(update_stmt_operands): Move. Change argument to build_ssa_operands.
(copy_virtual_operands): Move. New generic implementation.
(create_ssa_artficial_load_stmt): Move. New implementation.
(swap_tree_operands): Update for new implementation.
(get_expr_operands): Add stmt parameter to calls to swap_tree_operands.
(add_call_clobber_ops, add_call_read_ops): Initialize opbuild list
rather than a varray.
(verify_imm_links): Use use_operand_p.
(dump_immediate_uses_for): If the immediate use variable is a virtual
variable, show the virtual ops in the stmt.
* tree-ssa-operands.h (def_operand_p): No longer a structure.
(NULL_DEF_OPERAND_P): Now a #define.
(def_optype_d, use_optype_d, v_def_use_operand_type, v_may_def_optype_d,
vuse_operand_type, vuse_optype_d, v_must_def_optype_d): Delete.
(def_optype_d, use_optype_d, maydef_optype_d, vuse_optype_d,
mustdef_optype_d): New. Use Linked list representation.
(SSA_OPERAND_MEMORY_SIZE): New. Size of operand memory chunk.
(struct ssa_operand_memory_d): New. Allocated Chunk node.
(struct stmt_operands_d): Change to new pointers that are not GTY.
(STMT_USE_OPS, NUM_USES, SET_USE_OP, STMT_DEF_OPS, NUM_DEFS, SET_DEF_OP,
STMT_V_MAY_DEF_OPS, NUM_V_MAY_DEFS, SET_V_MAY_DEF_RESULT,
SET_V_MAY_DEF_OP, STMT_VUSE_OPS, NUM_VUSES, SET_VUSE_OP,
STMT_V_MUST_DEF_OPS, NUM_V_MUST_DEFS, SET_V_MUST_DEF_RESULT,
SET_V_MUST_DEF_KILL): Delete.
(V_MAY_DEF_OPS, V_MAY_DEF_RESULT_PTR, V_MAY_DEF_RESULT,
V_MAY_DEF_OP_PTR, V_MAY_DEF_OP): Rename to MAYDEF_*.
(V_MUST_DEF_OPS, V_MUST_DEF_RESULT_PTR, V_MUST_DEF_RESULT,
V_MUST_DEF_KILL_PTR, V_MUST_DEF_KILL): Rename to MUSTDEF_*.
(enum ssa_op_iter_type): Operand iterator typechecking values.
(struct ssa_operand_iterator_d): Use linked lists of operands.
(SSA_OP_VMUSTDEFKILL): Rename to SSA_OP_VMUSTKILL.
(FOR_EACH_SSA_MAYDEF_OPERAND, FOR_EACH_SSA_MUSTDEF_OPERAND,
FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND): Use op_iter_next_maymustdef.
(FOR_EACH_PHI_ARG): New. Iterate over PHI arguments.
(FOR_EACH_PHI_OR_STMT_USE): New. Iterate over PHI or stmt uses.
(FOR_EACH_PHI_OR_STMT_DEF): New. Iterate over PHI or stmt defs.
(SINGLE_SSA_TREE_OPERAND, SINGLE_SSA_USE_OPERAND,
SINGLE_SSA_DEF_OPERAND, ZERO_SSA_OPERANDS, NUM_SSA_OPERANDS): New.
* tree-ssa-opfinalize.h: New. Function templates for expansion.
(FINALIZE_ALLOC): Expands into alloc_def, alloc_use, alloc_maydef,
alloc_vuse, and alloc_mustdef.
(FINALIZE_FUNC): Expands into finalize_ssa_def_ops,
finalize_ssa_use_ops, finalize_ssa_v_may_def_ops, finalize_ssa_vuse_ops,
and finalize_ssa_v_must_def_ops.
* tree-ssa-pre.c (add_to_sets): Pass tree to vn_add.
(create_value_expr_from): Use stmt not vuse_optype as a parameter. Pass
stmt around.
(compute_avail): Use generic iterator interface.
* tree-ssa-propagate.c (first_vdef): Use generic operand interface.
(stmt_makes_single_load, stmt_makes_single_store): Use
ZERO_SSA_OPERANDS.
* tree-ssa-sink.c (is_hidden_global_store): Use ZERO_SSA_OPERANDS.
(statement_sink_location): Use generic interface.
* tree-ssa.c (verify_ssa): Use %p in fprintf. Use generic interface.
(delete_tree_ssa): Don't call release_defs. Call release_ssa_name and
reset the immediate use link nodes.
(stmt_references_memory_p): Use ZERO_SSA_OPERANDS.
* tree-ssanames.c (make_ssa_name): Use use_operand_p.
* tree-tailcall.c (find_tail_calls): Use ZERO_SSA_OPERANDS.
(eliminate_tail_call): Use generic operand interface.
* tree-vect-analyze.c (vect_analyze_data_refs): Use ZERO_SSA_OPERANDS.
(vect_mark_relevant, vect_mark_stmts_to_be_vectorized): Use generic
interface.
* tree-vect-transform.c (update_vuses_to_preheader): Use generic
interface.
* tree-vectorizer.c (rename_variables_in_bb): Use generic interface.
* tree-vn.c (struct val_expr_pair_d): Cache statment pointer instead of
vuse_optype.
(vn_compute, val_expr_pair_hash, vn_add, vn_lookup, vn_lookup_or_add):
Use statement pointer instead of vuse_optype. Use generic interface.
* tree-vrp.c (maybe_add_assert_expr): Use generic interface.
(stmt_interesting_for_vrp, vrp_visit_stmt): Use ZERO_SSA_OPERANDS.
* tree.h (struct ssa_imm_use_d): Renamed to ssa_use_operand_d.
(tree_ssa_name, phi_arg_d): Use ssa_use_operand_d.
* doc/tree-ssa.texi: Update documentation for operand interface.
2005-05-03 Nathan Sidwell <nathan@codesourcery.com>
* config/darwin.c (machopic_define_symbol): Use gcc_assert or

View File

@ -705,8 +705,8 @@ Almost every GIMPLE statement will contain a reference to a variable
or memory location. Since statements come in different shapes and
sizes, their operands are going to be located at various spots inside
the statement's tree. To facilitate access to the statement's
operands, they are organized into arrays associated inside each
statement's annotation. Each element in an operand array is a pointer
operands, they are organized into lists associated inside each
statement's annotation. Each element in an operand list is a pointer
to a @code{VAR_DECL}, @code{PARM_DECL} or @code{SSA_NAME} tree node.
This provides a very convenient way of examining and replacing
operands.
@ -810,82 +810,6 @@ function is converted into SSA form. This will be used to link all
the non-killing definitions to prevent optimizations from making
incorrect assumptions about them.
Operands are collected by @file{tree-ssa-operands.c}. They are stored
inside each statement's annotation and can be accessed with
@code{DEF_OPS}, @code{USE_OPS}, @code{V_MAY_DEF_OPS},
@code{V_MUST_DEF_OPS} and @code{VUSE_OPS}. The following are all the
accessor macros available to access USE operands. To access all the
other operand arrays, just change the name accordingly. Note that
this interface to the operands is deprecated, and is slated for
removal in a future version of gcc. The preferred interface is the
operand iterator interface. Unless you need to discover the number of
operands of a given type on a statement, you are strongly urged not to
use this interface.
@defmac USE_OPS (@var{ann})
Returns the array of operands used by the statement with annotation
@var{ann}.
@end defmac
@defmac STMT_USE_OPS (@var{stmt})
Alternate version of USE_OPS that takes the statement @var{stmt} as
input.
@end defmac
@defmac NUM_USES (@var{ops})
Return the number of USE operands in array @var{ops}.
@end defmac
@defmac USE_OP_PTR (@var{ops}, @var{i})
Return a pointer to the @var{i}th operand in array @var{ops}.
@end defmac
@defmac USE_OP (@var{ops}, @var{i})
Return the @var{i}th operand in array @var{ops}.
@end defmac
The following function shows how to print all the operands of a given
statement:
@smallexample
void
print_ops (tree stmt)
@{
vuse_optype vuses;
v_may_def_optype v_may_defs;
v_must_def_optype v_must_defs;
def_optype defs;
use_optype uses;
stmt_ann_t ann;
size_t i;
ann = stmt_ann (stmt);
defs = DEF_OPS (ann);
for (i = 0; i < NUM_DEFS (defs); i++)
print_generic_expr (stderr, DEF_OP (defs, i), 0);
uses = USE_OPS (ann);
for (i = 0; i < NUM_USES (uses); i++)
print_generic_expr (stderr, USE_OP (uses, i), 0);
v_may_defs = V_MAY_DEF_OPS (ann);
for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
@{
print_generic_expr (stderr, V_MAY_DEF_OP (v_may_defs, i), 0);
print_generic_expr (stderr, V_MAY_DEF_RESULT (v_may_defs, i), 0);
@}
v_must_defs = V_MUST_DEF_OPS (ann);
for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
print_generic_expr (stderr, V_MUST_DEF_OP (v_must_defs, i), 0);
vuses = VUSE_OPS (ann);
for (i = 0; i < NUM_VUSES (vuses); i++)
print_generic_expr (stderr, VUSE_OP (vuses, i), 0);
@}
@end smallexample
Operands are updated as soon as the statement is finished via a call
to @code{update_stmt}. If statement elements are changed via
@code{SET_USE} or @code{SET_DEF}, then no further action is required
@ -895,13 +819,49 @@ must be made to @code{update_stmt} when complete. Calling one of the
@code{bsi_insert} routines or @code{bsi_replace} performs an implicit
call to @code{update_stmt}.
@subsection Operand Iterators
@cindex Operand Iterators
@subsection Operand Iterators And Access Routines
@cindex Operand Iterators
@cindex Operand Access Routines
There is an alternative to iterating over the operands in a statement.
It is especially useful when you wish to perform the same operation on
more than one type of operand. The previous example could be
rewritten as follows:
Operands are collected by @file{tree-ssa-operands.c}. They are stored
inside each statement's annotation and can be accessed through either the
operand iterators or an access routine.
The following access routines are available for examining operands:
@enumerate
@item @code{SINGLE_SSA_@{USE,DEF,TREE@}_OPERAND}: These accessors will return
NULL unless there is exactly one operand mathcing the specified flags. If
there is exactly one operand, the operand is returned as either a @code{tree},
@code{def_operand_p}, or @code{use_operand_p}.
@smallexample
tree t = SINGLE_SSA_TREE_OPERAND (stmt, flags);
use_operand_p u = SINGLE_SSA_USE_OPERAND (stmt, SSA_ALL_VIRTUAL_USES);
def_operand_p d = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_ALL_DEFS);
@end smallexample
@item @code{ZERO_SSA_OPERANDS}: This macro returns true if there are no
operands matching the specified flags.
@smallexample
if (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
return;
@end smallexample
@item @code{NUM_SSA_OPERANDS}: This macro Returns the number of operands
matching 'flags'. This actually executes a loop to perform the count, so
only use this if it is really needed.
@smallexample
int count = NUM_SSA_OPERANDS (stmt, flags)
@end smallexample
@end enumerate
If you wish to iterate over some or all operands, use the
@code{FOR_EACH_SSA_@{USE,DEF,TREE@}_OPERAND} iterator. For example, to print
all the operands for a statement:
@smallexample
void
@ -911,11 +871,13 @@ print_ops (tree stmt)
tree var;
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_ALL_OPERANDS)
print_generic_expr (stderr, var, 0);
print_generic_expr (stderr, var, TDF_SLIM);
@}
@end smallexample
How to choose the appropriate iterator:
@enumerate
@item Determine whether you are need to see the operand pointers, or just the
trees, and choose the appropriate macro:
@ -966,7 +928,7 @@ So if you want to look at the use pointers for all the @code{USE} and
@}
@end smallexample
The @code{_TREE_} macro is basically the same as the @code{USE} and
The @code{TREE} macro is basically the same as the @code{USE} and
@code{DEF} macros, only with the use or def dereferenced via
@code{USE_FROM_PTR (use_p)} and @code{DEF_FROM_PTR (def_p)}. Since we
aren't using operand pointers, use and defs flags can be mixed.
@ -1002,7 +964,7 @@ this one.
@code{V_MUST_DEF}s are broken into two flags, one for the
@code{DEF} portion (@code{SSA_OP_VMUSTDEF}) and one for the kill portion
(@code{SSA_OP_VMUSTDEFKILL}). If all you want to look at are the
(@code{SSA_OP_VMUSTKILL}). If all you want to look at are the
@code{V_MUST_DEF}s together, there is a fourth iterator macro for this,
which returns both a def_operand_p and a use_operand_p for each
@code{V_MUST_DEF} in the statement. Note that you don't need any flags for
@ -1023,6 +985,46 @@ this one.
There are many examples in the code as well, as well as the
documentation in @file{tree-ssa-operands.h}.
There are also a couple of variants on the stmt iterators regarding PHI
nodes.
@code{FOR_EACH_PHI_ARG} Works exactly like
@code{FOR_EACH_SSA_USE_OPERAND}, except it works over @code{PHI} arguments
instead of statement operands.
@smallexample
/* Look at every virtual PHI use. */
FOR_EACH_PHI_ARG (use_p, phi_stmt, iter, SSA_OP_VIRTUAL_USES)
@{
my_code;
@}
/* Look at every real PHI use. */
FOR_EACH_PHI_ARG (use_p, phi_stmt, iter, SSA_OP_USES)
my_code;
/* Look at every every PHI use. */
FOR_EACH_PHI_ARG (use_p, phi_stmt, iter, SSA_OP_ALL_USES)
my_code;
@end smallexample
@code{FOR_EACH_PHI_OR_STMT_@{USE,DEF@}} works exactly like
@code{FOR_EACH_SSA_@{USE,DEF@}_OPERAND}, except it will function on
either a statement or a @code{PHI} node. These should be used when it is
appropriate but they are not quite as efficient as the individual
@code{FOR_EACH_PHI} and @code{FOR_EACH_SSA} routines.
@smallexample
FOR_EACH_PHI_OR_STMT_USE (use_operand_p, stmt, iter, flags)
@{
my_code;
@}
FOR_EACH_PHI_OR_STMT_DEF (def_operand_p, phi, iter, flags)
@{
my_code;
@}
@end smallexample
@subsection Immediate Uses
@cindex Immediate Uses

View File

@ -1266,7 +1266,6 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
int stepint;
int extra = 0;
tree lboundvar, uboundvar, uboundresult;
use_optype uses;
/* Find out induction var and exit condition. */
inductionvar = find_induction_var_from_exit_cond (loop);
@ -1295,9 +1294,8 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
phi = SSA_NAME_DEF_STMT (inductionvar);
if (TREE_CODE (phi) != PHI_NODE)
{
uses = STMT_USE_OPS (phi);
if (!uses)
phi = SINGLE_SSA_TREE_OPERAND (phi, SSA_OP_USE);
if (!phi)
{
if (dump_file && (dump_flags & TDF_DETAILS))
@ -1307,7 +1305,6 @@ gcc_loop_to_lambda_loop (struct loop *loop, int depth,
return NULL;
}
phi = USE_OP (uses, 0);
phi = SSA_NAME_DEF_STMT (phi);
if (TREE_CODE (phi) != PHI_NODE)
{
@ -1972,12 +1969,11 @@ lambda_loopnest_to_gcc_loopnest (struct loop *old_loopnest,
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);
oldiv_def = PHI_RESULT (oldiv_stmt);
else
oldiv_def = DEF_OP (STMT_DEF_OPS (oldiv_stmt), 0);
oldiv_def = SINGLE_SSA_TREE_OPERAND (oldiv_stmt, SSA_OP_DEF);
gcc_assert (oldiv_def != NULL_TREE);
FOR_EACH_IMM_USE_SAFE (imm_use, imm_iter, oldiv_def)
{
@ -2069,16 +2065,11 @@ phi_loop_edge_uses_def (struct loop *loop, tree phi, tree def)
static bool
stmt_uses_phi_result (tree stmt, tree phi_result)
{
use_optype uses = STMT_USE_OPS (stmt);
tree use = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_USE);
/* This is conservatively true, because we only want SIMPLE bumpers
of the form x +- constant for our pass. */
if (NUM_USES (uses) != 1)
return false;
if (USE_OP (uses, 0) == phi_result)
return true;
return false;
return (use == phi_result);
}
/* STMT is a bumper stmt for LOOP if the version it defines is used in the
@ -2092,13 +2083,13 @@ stmt_is_bumper_for_loop (struct loop *loop, tree stmt)
{
tree use;
tree def;
def_optype defs = STMT_DEF_OPS (stmt);
imm_use_iterator iter;
use_operand_p use_p;
if (NUM_DEFS (defs) != 1)
def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
if (!def)
return false;
def = DEF_OP (defs, 0);
FOR_EACH_IMM_USE_FAST (use_p, iter, def)
{
use = USE_STMT (use_p);
@ -2179,12 +2170,13 @@ perfect_nest_p (struct loop *loop)
static void
replace_uses_of_x_with_y (tree stmt, tree x, tree y)
{
use_optype uses = STMT_USE_OPS (stmt);
size_t i;
for (i = 0; i < NUM_USES (uses); i++)
ssa_op_iter iter;
use_operand_p use_p;
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
{
if (USE_OP (uses, i) == x)
SET_USE_OP (uses, i, y);
if (USE_FROM_PTR (use_p) == x)
SET_USE (use_p, y);
}
}
@ -2193,11 +2185,12 @@ replace_uses_of_x_with_y (tree stmt, tree x, tree y)
static bool
stmt_uses_op (tree stmt, tree op)
{
use_optype uses = STMT_USE_OPS (stmt);
size_t i;
for (i = 0; i < NUM_USES (uses); i++)
ssa_op_iter iter;
tree use;
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
{
if (USE_OP (uses, i) == op)
if (use == op)
return true;
}
return false;

View File

@ -2231,14 +2231,11 @@ find_data_references_in_loop (struct loop *loop, varray_type *datarefs)
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree stmt = bsi_stmt (bsi);
stmt_ann_t ann = stmt_ann (stmt);
if (TREE_CODE (stmt) != MODIFY_EXPR)
continue;
if (!VUSE_OPS (ann)
&& !V_MUST_DEF_OPS (ann)
&& !V_MAY_DEF_OPS (ann))
if (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
continue;
/* In the GIMPLE representation, a modify expression
@ -2269,8 +2266,7 @@ find_data_references_in_loop (struct loop *loop, varray_type *datarefs)
}
/* When there are no defs in the loop, the loop is parallel. */
if (NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) > 0
|| NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt)) > 0)
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
bb->loop_father->parallel_p = false;
}

View File

@ -482,15 +482,13 @@ collect_dfa_stats_r (tree *tp, int *walk_subtrees ATTRIBUTE_UNUSED,
{
case STMT_ANN:
{
stmt_ann_t ann = (stmt_ann_t) t->common.ann;
dfa_stats_p->num_stmt_anns++;
dfa_stats_p->num_defs += NUM_DEFS (DEF_OPS (ann));
dfa_stats_p->num_uses += NUM_USES (USE_OPS (ann));
dfa_stats_p->num_v_may_defs +=
NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann));
dfa_stats_p->num_vuses += NUM_VUSES (VUSE_OPS (ann));
dfa_stats_p->num_v_must_defs +=
NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann));
dfa_stats_p->num_defs += NUM_SSA_OPERANDS (t, SSA_OP_DEF);
dfa_stats_p->num_uses += NUM_SSA_OPERANDS (t, SSA_OP_USE);
dfa_stats_p->num_v_may_defs += NUM_SSA_OPERANDS (t, SSA_OP_VMAYDEF);
dfa_stats_p->num_vuses += NUM_SSA_OPERANDS (t, SSA_OP_VUSE);
dfa_stats_p->num_v_must_defs +=
NUM_SSA_OPERANDS (t, SSA_OP_VMUSTDEF);
break;
}
@ -642,8 +640,8 @@ mark_new_vars_to_rename (tree stmt)
We flag them in a separate bitmap because we don't really want to
rename them if there are not any newly exposed symbols in the
statement operands. */
v_may_defs_before = NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt));
v_must_defs_before = NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt));
v_may_defs_before = NUM_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF);
v_must_defs_before = NUM_SSA_OPERANDS (stmt, SSA_OP_VMUSTDEF);
FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter,
SSA_OP_VMAYDEF | SSA_OP_VUSE | SSA_OP_VMUSTDEF)
@ -657,8 +655,8 @@ mark_new_vars_to_rename (tree stmt)
exposed variables. */
update_stmt (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_may_defs_after = NUM_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF);
v_must_defs_after = NUM_SSA_OPERANDS (stmt, SSA_OP_VMUSTDEF);
FOR_EACH_SSA_TREE_OPERAND (val, stmt, iter, SSA_OP_ALL_OPERANDS)
if (DECL_P (val))

View File

@ -186,7 +186,7 @@ stmt_modified_p (tree t)
/* Delink an immediate_uses node from its chain. */
static inline void
delink_imm_use (ssa_imm_use_t *linknode)
delink_imm_use (ssa_use_operand_t *linknode)
{
/* Return if this node is not in a list. */
if (linknode->prev == NULL)
@ -200,7 +200,7 @@ delink_imm_use (ssa_imm_use_t *linknode)
/* Link ssa_imm_use node LINKNODE into the chain for LIST. */
static inline void
link_imm_use_to_list (ssa_imm_use_t *linknode, ssa_imm_use_t *list)
link_imm_use_to_list (ssa_use_operand_t *linknode, ssa_use_operand_t *list)
{
/* Link the new node at the head of the list. If we are in the process of
traversing the list, we won't visit any new nodes added to it. */
@ -212,9 +212,9 @@ link_imm_use_to_list (ssa_imm_use_t *linknode, ssa_imm_use_t *list)
/* Link ssa_imm_use node LINKNODE into the chain for DEF. */
static inline void
link_imm_use (ssa_imm_use_t *linknode, tree def)
link_imm_use (ssa_use_operand_t *linknode, tree def)
{
ssa_imm_use_t *root;
ssa_use_operand_t *root;
if (!def || TREE_CODE (def) != SSA_NAME)
linknode->prev = NULL;
@ -241,7 +241,7 @@ set_ssa_use_from_ptr (use_operand_p use, tree val)
/* Link ssa_imm_use node LINKNODE into the chain for DEF, with use occuring
in STMT. */
static inline void
link_imm_use_stmt (ssa_imm_use_t *linknode, tree def, tree stmt)
link_imm_use_stmt (ssa_use_operand_t *linknode, tree def, tree stmt)
{
if (stmt)
link_imm_use (linknode, def);
@ -252,7 +252,7 @@ link_imm_use_stmt (ssa_imm_use_t *linknode, tree def, tree stmt)
/* Relink a new node in place of an old node in the list. */
static inline void
relink_imm_use (ssa_imm_use_t *node, ssa_imm_use_t *old)
relink_imm_use (ssa_use_operand_t *node, ssa_use_operand_t *old)
{
/* The node one had better be in the same list. */
gcc_assert (*(old->use) == *(node->use));
@ -270,7 +270,7 @@ relink_imm_use (ssa_imm_use_t *node, ssa_imm_use_t *old)
/* Relink ssa_imm_use node LINKNODE into the chain for OLD, with use occuring
in STMT. */
static inline void
relink_imm_use_stmt (ssa_imm_use_t *linknode, ssa_imm_use_t *old, tree stmt)
relink_imm_use_stmt (ssa_use_operand_t *linknode, ssa_use_operand_t *old, tree stmt)
{
if (stmt)
relink_imm_use (linknode, old);
@ -318,7 +318,7 @@ first_safe_imm_use (imm_use_iterator *imm, tree var)
static inline use_operand_p
next_safe_imm_use (imm_use_iterator *imm)
{
ssa_imm_use_t *ptr;
ssa_use_operand_t *ptr;
use_operand_p old;
old = imm->imm_use;
@ -405,7 +405,7 @@ next_readonly_imm_use (imm_use_iterator *imm)
static inline bool
has_zero_uses (tree var)
{
ssa_imm_use_t *ptr;
ssa_use_operand_t *ptr;
ptr = &(SSA_NAME_IMM_USE_NODE (var));
/* A single use means there is no items in the list. */
return (ptr == ptr->next);
@ -415,7 +415,7 @@ has_zero_uses (tree var)
static inline bool
has_single_use (tree var)
{
ssa_imm_use_t *ptr;
ssa_use_operand_t *ptr;
ptr = &(SSA_NAME_IMM_USE_NODE (var));
/* A single use means there is one item in the list. */
return (ptr != ptr->next && ptr == ptr->next->next);
@ -426,7 +426,7 @@ has_single_use (tree var)
static inline bool
single_imm_use (tree var, use_operand_p *use_p, tree *stmt)
{
ssa_imm_use_t *ptr;
ssa_use_operand_t *ptr;
ptr = &(SSA_NAME_IMM_USE_NODE (var));
if (ptr != ptr->next && ptr == ptr->next->next)
@ -444,7 +444,7 @@ single_imm_use (tree var, use_operand_p *use_p, tree *stmt)
static inline unsigned int
num_imm_uses (tree var)
{
ssa_imm_use_t *ptr, *start;
ssa_use_operand_t *ptr, *start;
unsigned int num;
start = &(SSA_NAME_IMM_USE_NODE (var));
@ -455,46 +455,6 @@ num_imm_uses (tree var)
return num;
}
/* Return the definitions present in ANN, a statement annotation.
Return NULL if this annotation contains no definitions. */
static inline def_optype
get_def_ops (stmt_ann_t ann)
{
return ann ? ann->operands.def_ops : NULL;
}
/* Return the uses present in ANN, a statement annotation.
Return NULL if this annotation contains no uses. */
static inline use_optype
get_use_ops (stmt_ann_t ann)
{
return ann ? ann->operands.use_ops : NULL;
}
/* Return the virtual may-defs present in ANN, a statement
annotation.
Return NULL if this annotation contains no virtual may-defs. */
static inline v_may_def_optype
get_v_may_def_ops (stmt_ann_t ann)
{
return ann ? ann->operands.v_may_def_ops : NULL;
}
/* Return the virtual uses present in ANN, a statement annotation.
Return NULL if this annotation contains no virtual uses. */
static inline vuse_optype
get_vuse_ops (stmt_ann_t ann)
{
return ann ? ann->operands.vuse_ops : NULL;
}
/* Return the virtual must-defs present in ANN, a statement
annotation. Return NULL if this annotation contains no must-defs.*/
static inline v_must_def_optype
get_v_must_def_ops (stmt_ann_t ann)
{
return ann ? ann->operands.v_must_def_ops : NULL;
}
/* Return the tree pointer to by USE. */
static inline tree
@ -507,80 +467,14 @@ get_use_from_ptr (use_operand_p use)
static inline tree
get_def_from_ptr (def_operand_p def)
{
return *(def.def);
}
/* Return a pointer to the tree that is at INDEX in the USES array. */
static inline use_operand_p
get_use_op_ptr (use_optype uses, unsigned int index)
{
gcc_assert (index < uses->num_uses);
return &(uses->uses[index]);
}
/* Return a def_operand_p pointer for element INDEX of DEFS. */
static inline def_operand_p
get_def_op_ptr (def_optype defs, unsigned int index)
{
gcc_assert (index < defs->num_defs);
return defs->defs[index];
}
/* Return the def_operand_p that is the V_MAY_DEF_RESULT for the V_MAY_DEF
at INDEX in the V_MAY_DEFS array. */
static inline def_operand_p
get_v_may_def_result_ptr(v_may_def_optype v_may_defs, unsigned int index)
{
def_operand_p op;
gcc_assert (index < v_may_defs->num_v_may_defs);
op.def = &(v_may_defs->v_may_defs[index].def);
return op;
}
/* Return a use_operand_p that is the V_MAY_DEF_OP for the V_MAY_DEF at
INDEX in the V_MAY_DEFS array. */
static inline use_operand_p
get_v_may_def_op_ptr(v_may_def_optype v_may_defs, unsigned int index)
{
gcc_assert (index < v_may_defs->num_v_may_defs);
return &(v_may_defs->v_may_defs[index].imm_use);
}
/* Return a use_operand_p that is at INDEX in the VUSES array. */
static inline use_operand_p
get_vuse_op_ptr(vuse_optype vuses, unsigned int index)
{
gcc_assert (index < vuses->num_vuses);
return &(vuses->vuses[index].imm_use);
}
/* Return a def_operand_p that is the V_MUST_DEF_RESULT for the
V_MUST_DEF at INDEX in the V_MUST_DEFS array. */
static inline def_operand_p
get_v_must_def_result_ptr (v_must_def_optype v_must_defs, unsigned int index)
{
def_operand_p op;
gcc_assert (index < v_must_defs->num_v_must_defs);
op.def = &(v_must_defs->v_must_defs[index].def);
return op;
}
/* Return a use_operand_p that is the V_MUST_DEF_KILL for the
V_MUST_DEF at INDEX in the V_MUST_DEFS array. */
static inline use_operand_p
get_v_must_def_kill_ptr (v_must_def_optype v_must_defs, unsigned int index)
{
gcc_assert (index < v_must_defs->num_v_must_defs);
return &(v_must_defs->v_must_defs[index].imm_use);
return *def;
}
/* Return a def_operand_p pointer for the result of PHI. */
static inline def_operand_p
get_phi_result_ptr (tree phi)
{
def_operand_p op;
op.def = &(PHI_RESULT_TREE (phi));
return op;
return &(PHI_RESULT_TREE (phi));
}
/* Return a use_operand_p pointer for argument I of phinode PHI. */
@ -590,29 +484,6 @@ get_phi_arg_def_ptr (tree phi, int i)
return &(PHI_ARG_IMM_USE_NODE (phi,i));
}
/* Delink all immediate_use information for STMT. */
static inline void
delink_stmt_imm_use (tree stmt)
{
unsigned int x;
use_optype uses = STMT_USE_OPS (stmt);
vuse_optype vuses = STMT_VUSE_OPS (stmt);
v_may_def_optype v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
v_must_def_optype v_must_defs = STMT_V_MUST_DEF_OPS (stmt);
for (x = 0; x < NUM_USES (uses); x++)
delink_imm_use (&(uses->uses[x]));
for (x = 0; x < NUM_VUSES (vuses); x++)
delink_imm_use (&(vuses->vuses[x].imm_use));
for (x = 0; x < NUM_V_MAY_DEFS (v_may_defs); x++)
delink_imm_use (&(v_may_defs->v_may_defs[x].imm_use));
for (x = 0; x < NUM_V_MUST_DEFS (v_must_defs); x++)
delink_imm_use (&(v_must_defs->v_must_defs[x].imm_use));
}
/* Return the bitmap of addresses taken by STMT, or NULL if it takes
no addresses. */
@ -963,23 +834,37 @@ op_iter_done (ssa_op_iter *ptr)
static inline use_operand_p
op_iter_next_use (ssa_op_iter *ptr)
{
if (ptr->use_i < ptr->num_use)
use_operand_p use_p;
#ifdef ENABLE_CHECKING
gcc_assert (ptr->iter_type == ssa_op_iter_use);
#endif
if (ptr->uses)
{
return USE_OP_PTR (ptr->ops->use_ops, (ptr->use_i)++);
use_p = USE_OP_PTR (ptr->uses);
ptr->uses = ptr->uses->next;
return use_p;
}
if (ptr->vuse_i < ptr->num_vuse)
if (ptr->vuses)
{
return VUSE_OP_PTR (ptr->ops->vuse_ops, (ptr->vuse_i)++);
use_p = VUSE_OP_PTR (ptr->vuses);
ptr->vuses = ptr->vuses->next;
return use_p;
}
if (ptr->v_mayu_i < ptr->num_v_mayu)
if (ptr->mayuses)
{
return V_MAY_DEF_OP_PTR (ptr->ops->v_may_def_ops,
(ptr->v_mayu_i)++);
use_p = MAYDEF_OP_PTR (ptr->mayuses);
ptr->mayuses = ptr->mayuses->next;
return use_p;
}
if (ptr->v_mustu_i < ptr->num_v_mustu)
if (ptr->mustkills)
{
return V_MUST_DEF_KILL_PTR (ptr->ops->v_must_def_ops,
(ptr->v_mustu_i)++);
use_p = MUSTDEF_KILL_PTR (ptr->mustkills);
ptr->mustkills = ptr->mustkills->next;
return use_p;
}
if (ptr->phi_i < ptr->num_phi)
{
return PHI_ARG_DEF_PTR (ptr->phi_stmt, (ptr->phi_i)++);
}
ptr->done = true;
return NULL_USE_OPERAND_P;
@ -989,19 +874,27 @@ op_iter_next_use (ssa_op_iter *ptr)
static inline def_operand_p
op_iter_next_def (ssa_op_iter *ptr)
{
if (ptr->def_i < ptr->num_def)
def_operand_p def_p;
#ifdef ENABLE_CHECKING
gcc_assert (ptr->iter_type == ssa_op_iter_def);
#endif
if (ptr->defs)
{
return DEF_OP_PTR (ptr->ops->def_ops, (ptr->def_i)++);
def_p = DEF_OP_PTR (ptr->defs);
ptr->defs = ptr->defs->next;
return def_p;
}
if (ptr->v_mustd_i < ptr->num_v_mustd)
if (ptr->mustdefs)
{
return V_MUST_DEF_RESULT_PTR (ptr->ops->v_must_def_ops,
(ptr->v_mustd_i)++);
def_p = MUSTDEF_RESULT_PTR (ptr->mustdefs);
ptr->mustdefs = ptr->mustdefs->next;
return def_p;
}
if (ptr->v_mayd_i < ptr->num_v_mayd)
if (ptr->maydefs)
{
return V_MAY_DEF_RESULT_PTR (ptr->ops->v_may_def_ops,
(ptr->v_mayd_i)++);
def_p = MAYDEF_RESULT_PTR (ptr->maydefs);
ptr->maydefs = ptr->maydefs->next;
return def_p;
}
ptr->done = true;
return NULL_DEF_OPERAND_P;
@ -1011,68 +904,100 @@ op_iter_next_def (ssa_op_iter *ptr)
static inline tree
op_iter_next_tree (ssa_op_iter *ptr)
{
if (ptr->use_i < ptr->num_use)
tree val;
#ifdef ENABLE_CHECKING
gcc_assert (ptr->iter_type == ssa_op_iter_tree);
#endif
if (ptr->uses)
{
return USE_OP (ptr->ops->use_ops, (ptr->use_i)++);
val = USE_OP (ptr->uses);
ptr->uses = ptr->uses->next;
return val;
}
if (ptr->vuse_i < ptr->num_vuse)
if (ptr->vuses)
{
return VUSE_OP (ptr->ops->vuse_ops, (ptr->vuse_i)++);
val = VUSE_OP (ptr->vuses);
ptr->vuses = ptr->vuses->next;
return val;
}
if (ptr->v_mayu_i < ptr->num_v_mayu)
if (ptr->mayuses)
{
return V_MAY_DEF_OP (ptr->ops->v_may_def_ops, (ptr->v_mayu_i)++);
val = MAYDEF_OP (ptr->mayuses);
ptr->mayuses = ptr->mayuses->next;
return val;
}
if (ptr->v_mustu_i < ptr->num_v_mustu)
if (ptr->mustkills)
{
return V_MUST_DEF_KILL (ptr->ops->v_must_def_ops, (ptr->v_mustu_i)++);
val = MUSTDEF_KILL (ptr->mustkills);
ptr->mustkills = ptr->mustkills->next;
return val;
}
if (ptr->def_i < ptr->num_def)
if (ptr->defs)
{
return DEF_OP (ptr->ops->def_ops, (ptr->def_i)++);
val = DEF_OP (ptr->defs);
ptr->defs = ptr->defs->next;
return val;
}
if (ptr->v_mustd_i < ptr->num_v_mustd)
if (ptr->mustdefs)
{
return V_MUST_DEF_RESULT (ptr->ops->v_must_def_ops,
(ptr->v_mustd_i)++);
val = MUSTDEF_RESULT (ptr->mustdefs);
ptr->mustdefs = ptr->mustdefs->next;
return val;
}
if (ptr->v_mayd_i < ptr->num_v_mayd)
if (ptr->maydefs)
{
return V_MAY_DEF_RESULT (ptr->ops->v_may_def_ops,
(ptr->v_mayd_i)++);
val = MAYDEF_RESULT (ptr->maydefs);
ptr->maydefs = ptr->maydefs->next;
return val;
}
ptr->done = true;
return NULL_TREE;
}
/* This functiins clears the iterator PTR, and marks it done. This is normally
used to prevent warnings in the compile about might be uninitailzied
components. */
static inline void
clear_and_done_ssa_iter (ssa_op_iter *ptr)
{
ptr->defs = NULL;
ptr->uses = NULL;
ptr->vuses = NULL;
ptr->maydefs = NULL;
ptr->mayuses = NULL;
ptr->mustdefs = NULL;
ptr->mustkills = NULL;
ptr->iter_type = ssa_op_iter_none;
ptr->phi_i = 0;
ptr->num_phi = 0;
ptr->phi_stmt = NULL_TREE;
ptr->done = true;
return NULL;
}
/* Initialize the iterator PTR to the virtual defs in STMT. */
static inline void
op_iter_init (ssa_op_iter *ptr, tree stmt, int flags)
{
stmt_operands_p ops;
stmt_ann_t ann = get_stmt_ann (stmt);
#ifdef ENABLE_CHECKING
gcc_assert (stmt_ann (stmt));
#endif
ops = &(ann->operands);
ptr->defs = (flags & SSA_OP_DEF) ? DEF_OPS (stmt) : NULL;
ptr->uses = (flags & SSA_OP_USE) ? USE_OPS (stmt) : NULL;
ptr->vuses = (flags & SSA_OP_VUSE) ? VUSE_OPS (stmt) : NULL;
ptr->maydefs = (flags & SSA_OP_VMAYDEF) ? MAYDEF_OPS (stmt) : NULL;
ptr->mayuses = (flags & SSA_OP_VMAYUSE) ? MAYDEF_OPS (stmt) : NULL;
ptr->mustdefs = (flags & SSA_OP_VMUSTDEF) ? MUSTDEF_OPS (stmt) : NULL;
ptr->mustkills = (flags & SSA_OP_VMUSTKILL) ? MUSTDEF_OPS (stmt) : NULL;
ptr->done = false;
ptr->ops = ops;
ptr->num_def = (flags & SSA_OP_DEF) ? NUM_DEFS (ops->def_ops) : 0;
ptr->num_use = (flags & SSA_OP_USE) ? NUM_USES (ops->use_ops) : 0;
ptr->num_vuse = (flags & SSA_OP_VUSE) ? NUM_VUSES (ops->vuse_ops) : 0;
ptr->num_v_mayu = (flags & SSA_OP_VMAYUSE)
? NUM_V_MAY_DEFS (ops->v_may_def_ops) : 0;
ptr->num_v_mayd = (flags & SSA_OP_VMAYDEF)
? NUM_V_MAY_DEFS (ops->v_may_def_ops) : 0;
ptr->num_v_mustu = (flags & SSA_OP_VMUSTDEFKILL)
? NUM_V_MUST_DEFS (ops->v_must_def_ops) : 0;
ptr->num_v_mustd = (flags & SSA_OP_VMUSTDEF)
? NUM_V_MUST_DEFS (ops->v_must_def_ops) : 0;
ptr->def_i = 0;
ptr->use_i = 0;
ptr->vuse_i = 0;
ptr->v_mayu_i = 0;
ptr->v_mayd_i = 0;
ptr->v_mustu_i = 0;
ptr->v_mustd_i = 0;
ptr->phi_i = 0;
ptr->num_phi = 0;
ptr->phi_stmt = NULL_TREE;
}
/* Initialize iterator PTR to the use operands in STMT based on FLAGS. Return
@ -1081,6 +1006,7 @@ static inline use_operand_p
op_iter_init_use (ssa_op_iter *ptr, tree stmt, int flags)
{
op_iter_init (ptr, stmt, flags);
ptr->iter_type = ssa_op_iter_use;
return op_iter_next_use (ptr);
}
@ -1090,6 +1016,7 @@ static inline def_operand_p
op_iter_init_def (ssa_op_iter *ptr, tree stmt, int flags)
{
op_iter_init (ptr, stmt, flags);
ptr->iter_type = ssa_op_iter_def;
return op_iter_next_def (ptr);
}
@ -1099,76 +1026,41 @@ static inline tree
op_iter_init_tree (ssa_op_iter *ptr, tree stmt, int flags)
{
op_iter_init (ptr, stmt, flags);
ptr->iter_type = ssa_op_iter_tree;
return op_iter_next_tree (ptr);
}
/* Get the next iterator mustdef value for PTR, returning the mustdef values in
KILL and DEF. */
static inline void
op_iter_next_mustdef (use_operand_p *kill, def_operand_p *def, ssa_op_iter *ptr)
op_iter_next_maymustdef (use_operand_p *use, def_operand_p *def,
ssa_op_iter *ptr)
{
if (ptr->v_mustu_i < ptr->num_v_mustu)
#ifdef ENABLE_CHECKING
gcc_assert (ptr->iter_type == ssa_op_iter_maymustdef);
#endif
if (ptr->mayuses)
{
*def = V_MUST_DEF_RESULT_PTR (ptr->ops->v_must_def_ops, ptr->v_mustu_i);
*kill = V_MUST_DEF_KILL_PTR (ptr->ops->v_must_def_ops, (ptr->v_mustu_i)++);
*def = MAYDEF_RESULT_PTR (ptr->mayuses);
*use = MAYDEF_OP_PTR (ptr->mayuses);
ptr->mayuses = ptr->mayuses->next;
return;
}
else
if (ptr->mustkills)
{
*def = NULL_DEF_OPERAND_P;
*kill = NULL_USE_OPERAND_P;
*def = MUSTDEF_RESULT_PTR (ptr->mustkills);
*use = MUSTDEF_KILL_PTR (ptr->mustkills);
ptr->mustkills = ptr->mustkills->next;
return;
}
*def = NULL_DEF_OPERAND_P;
*use = NULL_USE_OPERAND_P;
ptr->done = true;
return;
}
/* Get the next iterator maydef value for PTR, returning the maydef values in
USE and DEF. */
static inline void
op_iter_next_maydef (use_operand_p *use, def_operand_p *def, ssa_op_iter *ptr)
{
if (ptr->v_mayu_i < ptr->num_v_mayu)
{
*def = V_MAY_DEF_RESULT_PTR (ptr->ops->v_may_def_ops, ptr->v_mayu_i);
*use = V_MAY_DEF_OP_PTR (ptr->ops->v_may_def_ops, (ptr->v_mayu_i)++);
return;
}
else
{
*def = NULL_DEF_OPERAND_P;
*use = NULL_USE_OPERAND_P;
}
ptr->done = true;
return;
}
/* Get the next iterator mustdef or maydef value for PTR, returning the
mustdef or maydef values in KILL and DEF. */
static inline void
op_iter_next_must_and_may_def (use_operand_p *kill,
def_operand_p *def,
ssa_op_iter *ptr)
{
if (ptr->v_mustu_i < ptr->num_v_mustu)
{
*def = V_MUST_DEF_RESULT_PTR (ptr->ops->v_must_def_ops, ptr->v_mustu_i);
*kill = V_MUST_DEF_KILL_PTR (ptr->ops->v_must_def_ops, (ptr->v_mustu_i)++);
return;
}
else if (ptr->v_mayu_i < ptr->num_v_mayu)
{
*def = V_MAY_DEF_RESULT_PTR (ptr->ops->v_may_def_ops, ptr->v_mayu_i);
*kill = V_MAY_DEF_OP_PTR (ptr->ops->v_may_def_ops, (ptr->v_mayu_i)++);
return;
}
else
{
*def = NULL_DEF_OPERAND_P;
*kill = NULL_USE_OPERAND_P;
}
ptr->done = true;
return;
}
/* Initialize iterator PTR to the operands in STMT. Return the first operands
in USE and DEF. */
@ -1176,8 +1068,11 @@ static inline void
op_iter_init_maydef (ssa_op_iter *ptr, tree stmt, use_operand_p *use,
def_operand_p *def)
{
gcc_assert (TREE_CODE (stmt) != PHI_NODE);
op_iter_init (ptr, stmt, SSA_OP_VMAYUSE);
op_iter_next_maydef (use, def, ptr);
ptr->iter_type = ssa_op_iter_maymustdef;
op_iter_next_maymustdef (use, def, ptr);
}
@ -1187,8 +1082,11 @@ static inline void
op_iter_init_mustdef (ssa_op_iter *ptr, tree stmt, use_operand_p *kill,
def_operand_p *def)
{
op_iter_init (ptr, stmt, SSA_OP_VMUSTDEFKILL);
op_iter_next_mustdef (kill, def, ptr);
gcc_assert (TREE_CODE (stmt) != PHI_NODE);
op_iter_init (ptr, stmt, SSA_OP_VMUSTKILL);
ptr->iter_type = ssa_op_iter_maymustdef;
op_iter_next_maymustdef (kill, def, ptr);
}
/* Initialize iterator PTR to the operands in STMT. Return the first operands
@ -1197,10 +1095,241 @@ static inline void
op_iter_init_must_and_may_def (ssa_op_iter *ptr, tree stmt,
use_operand_p *kill, def_operand_p *def)
{
op_iter_init (ptr, stmt, SSA_OP_VMUSTDEFKILL | SSA_OP_VMAYUSE);
op_iter_next_must_and_may_def (kill, def, ptr);
gcc_assert (TREE_CODE (stmt) != PHI_NODE);
op_iter_init (ptr, stmt, SSA_OP_VMUSTKILL|SSA_OP_VMAYUSE);
ptr->iter_type = ssa_op_iter_maymustdef;
op_iter_next_maymustdef (kill, def, ptr);
}
/* If there is a single opernad in STMT matching FLAGS, return it. Otherwise
return NULL. PTR is the iterator to use. */
static inline tree
single_ssa_tree_operand (tree stmt, int flags)
{
tree var;
ssa_op_iter iter;
var = op_iter_init_tree (&iter, stmt, flags);
if (op_iter_done (&iter))
return NULL_TREE;
op_iter_next_tree (&iter);
if (op_iter_done (&iter))
return var;
return NULL_TREE;
}
/* If there is a single opernad in STMT matching FLAGS, return it. Otherwise
return NULL. PTR is the iterator to use. */
static inline use_operand_p
single_ssa_use_operand (tree stmt, int flags)
{
use_operand_p var;
ssa_op_iter iter;
var = op_iter_init_use (&iter, stmt, flags);
if (op_iter_done (&iter))
return NULL_USE_OPERAND_P;
op_iter_next_use (&iter);
if (op_iter_done (&iter))
return var;
return NULL_USE_OPERAND_P;
}
/* If there is a single opernad in STMT matching FLAGS, return it. Otherwise
return NULL. PTR is the iterator to use. */
static inline def_operand_p
single_ssa_def_operand (tree stmt, int flags)
{
def_operand_p var;
ssa_op_iter iter;
var = op_iter_init_def (&iter, stmt, flags);
if (op_iter_done (&iter))
return NULL_DEF_OPERAND_P;
op_iter_next_def (&iter);
if (op_iter_done (&iter))
return var;
return NULL_DEF_OPERAND_P;
}
/* If there is a single opernad in STMT matching FLAGS, return it. Otherwise
return NULL. PTR is the iterator to use. */
static inline bool
zero_ssa_operands (tree stmt, int flags)
{
ssa_op_iter iter;
op_iter_init_tree (&iter, stmt, flags);
return op_iter_done (&iter);
}
/* Return the number of opernads mathcing FLAGS in STMT. */
static inline int
num_ssa_operands (tree stmt, int flags)
{
ssa_op_iter iter;
int num = 0;
op_iter_init (&iter, stmt, flags);
for ( ; iter.defs; iter.defs = iter.defs->next)
num++;
for ( ; iter.uses; iter.uses = iter.uses->next)
num++;
for ( ; iter.vuses; iter.vuses = iter.vuses->next)
num++;
for ( ; iter.maydefs; iter.maydefs = iter.maydefs->next)
num++;
for ( ; iter.mayuses; iter.mayuses = iter.mayuses->next)
num++;
for ( ; iter.mustdefs; iter.mustdefs = iter.mustdefs->next)
num++;
for ( ; iter.mustkills; iter.mustkills = iter.mustkills->next)
num++;
return num;
}
/* Delink all immediate_use information for STMT. */
static inline void
delink_stmt_imm_use (tree stmt)
{
ssa_op_iter iter;
use_operand_p use_p;
if (ssa_operands_active ())
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter,
(SSA_OP_ALL_USES | SSA_OP_ALL_KILLS))
delink_imm_use (use_p);
}
/* This routine will compare all the operands matching FLAGS in STMT1 to those
in STMT2. TRUE is returned if they are the same. STMTs can be NULL. */
static inline bool
compare_ssa_operands_equal (tree stmt1, tree stmt2, int flags)
{
ssa_op_iter iter1, iter2;
tree op1 = NULL_TREE;
tree op2 = NULL_TREE;
bool look1, look2;
if (stmt1 == stmt2)
return true;
look1 = stmt1 && stmt_ann (stmt1);
look2 = stmt2 && stmt_ann (stmt2);
if (look1)
{
op1 = op_iter_init_tree (&iter1, stmt1, flags);
if (!look2)
return op_iter_done (&iter1);
}
else
clear_and_done_ssa_iter (&iter1);
if (look2)
{
op2 = op_iter_init_tree (&iter2, stmt2, flags);
if (!look1)
return op_iter_done (&iter2);
}
else
clear_and_done_ssa_iter (&iter2);
while (!op_iter_done (&iter1) && !op_iter_done (&iter2))
{
if (op1 != op2)
return false;
op1 = op_iter_next_tree (&iter1);
op2 = op_iter_next_tree (&iter2);
}
return (op_iter_done (&iter1) && op_iter_done (&iter2));
}
/* If there is a single DEF in the PHI node which matches FLAG, return it.
Otherwise return NULL_DEF_OPERAND_P. */
static inline tree
single_phi_def (tree stmt, int flags)
{
tree def = PHI_RESULT (stmt);
if ((flags & SSA_OP_DEF) && is_gimple_reg (def))
return def;
if ((flags & SSA_OP_VIRTUAL_DEFS) && !is_gimple_reg (def))
return def;
return NULL_TREE;
}
/* Initialize the iterator PTR for uses matching FLAGS in PHI. FLAGS should
be either SSA_OP_USES or SAS_OP_VIRTUAL_USES. */
static inline use_operand_p
op_iter_init_phiuse (ssa_op_iter *ptr, tree phi, int flags)
{
tree phi_def = PHI_RESULT (phi);
int comp;
clear_and_done_ssa_iter (ptr);
ptr->done = false;
gcc_assert ((flags & (SSA_OP_USE | SSA_OP_VIRTUAL_USES)) != 0);
comp = (is_gimple_reg (phi_def) ? SSA_OP_USE : SSA_OP_VIRTUAL_USES);
/* if the PHI node deosn't the operand type we care about, we're done. */
if ((flags & comp) == 0)
{
ptr->done = true;
return NULL_USE_OPERAND_P;
}
ptr->phi_stmt = phi;
ptr->num_phi = PHI_NUM_ARGS (phi);
ptr->iter_type = ssa_op_iter_use;
return op_iter_next_use (ptr);
}
/* Start an iterator for a PHI defintion. */
static inline def_operand_p
op_iter_init_phidef (ssa_op_iter *ptr, tree phi, int flags)
{
tree phi_def = PHI_RESULT (phi);
int comp;
clear_and_done_ssa_iter (ptr);
ptr->done = false;
gcc_assert ((flags & (SSA_OP_DEF | SSA_OP_VIRTUAL_DEFS)) != 0);
comp = (is_gimple_reg (phi_def) ? SSA_OP_DEF : SSA_OP_VIRTUAL_DEFS);
/* if the PHI node deosn't the operand type we care about, we're done. */
if ((flags & comp) == 0)
{
ptr->done = true;
return NULL_USE_OPERAND_P;
}
ptr->iter_type = ssa_op_iter_def;
/* The first call to op_iter_next_def will terminate the iterator since
all the fields are NULL. Simply return the result here as the first and
therefore only result. */
return PHI_RESULT_PTR (phi);
}
/* Return true if VAR cannot be modified by the program. */
static inline bool

View File

@ -264,9 +264,9 @@ struct var_ann_d GTY(())
typedef struct immediate_use_iterator_d
{
ssa_imm_use_t *imm_use;
ssa_imm_use_t *end_p;
ssa_imm_use_t iter_node;
ssa_use_operand_t *imm_use;
ssa_use_operand_t *end_p;
ssa_use_operand_t iter_node;
} imm_use_iterator;
@ -315,7 +315,7 @@ struct stmt_ann_d GTY(())
basic_block GTY ((skip (""))) bb;
/* Operand cache for stmt. */
struct stmt_operands_d operands;
struct stmt_operands_d GTY ((skip (""))) operands;
/* Set of variables that have had their address taken in the statement. */
bitmap addresses_taken;
@ -362,10 +362,6 @@ static inline int get_lineno (tree);
static inline const char *get_filename (tree);
static inline bool is_exec_stmt (tree);
static inline bool is_label_stmt (tree);
static inline v_may_def_optype get_v_may_def_ops (stmt_ann_t);
static inline vuse_optype get_vuse_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 bitmap addresses_taken (tree);
static inline void set_default_def (tree, tree);
static inline tree default_def (tree);
@ -765,10 +761,10 @@ void print_value_expressions (FILE *, tree);
/* In tree-vn.c */
bool expressions_equal_p (tree, tree);
tree get_value_handle (tree);
hashval_t vn_compute (tree, hashval_t, vuse_optype);
tree vn_lookup_or_add (tree, vuse_optype);
void vn_add (tree, tree, vuse_optype);
tree vn_lookup (tree, vuse_optype);
hashval_t vn_compute (tree, hashval_t, tree);
tree vn_lookup_or_add (tree, tree);
void vn_add (tree, tree, tree);
tree vn_lookup (tree, tree);
void vn_init (void);
void vn_delete (void);

View File

@ -616,7 +616,7 @@ add_new_name_mapping (tree new, tree old)
for every variable in the function. For every statement S in block
BB:
1- Variables defined by S in DEF_OPS(S) are marked in the bitmap
1- Variables defined by S in the DEFS of S are marked in the bitmap
WALK_DATA->GLOBAL_DATA->KILLS.
2- If S uses a variable VAR and there is no preceding kill of VAR,
@ -648,7 +648,7 @@ mark_def_sites (struct dom_walk_data *walk_data,
/* 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. */
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter,
SSA_OP_USE | SSA_OP_VUSE | SSA_OP_VMUSTDEFKILL)
SSA_OP_USE | SSA_OP_VUSE | SSA_OP_VMUSTKILL)
{
tree sym = USE_FROM_PTR (use_p);
gcc_assert (DECL_P (sym));

View File

@ -1444,12 +1444,8 @@ add_dependance (temp_expr_table_p tab, int version, tree var)
static bool
check_replaceable (temp_expr_table_p tab, tree stmt)
{
stmt_ann_t ann;
vuse_optype vuseops;
def_optype defs;
use_optype uses;
tree var, def;
int num_use_ops, version;
int version;
var_map map = tab->map;
ssa_op_iter iter;
tree call_expr;
@ -1457,22 +1453,16 @@ check_replaceable (temp_expr_table_p tab, tree stmt)
if (TREE_CODE (stmt) != MODIFY_EXPR)
return false;
ann = stmt_ann (stmt);
defs = DEF_OPS (ann);
/* Punt if there is more than 1 def, or more than 1 use. */
if (NUM_DEFS (defs) != 1)
def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
if (!def)
return false;
def = DEF_OP (defs, 0);
if (version_ref_count (map, def) != 1)
return false;
/* There must be no V_MAY_DEFS. */
if (NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) != 0)
return false;
/* There must be no V_MUST_DEFS. */
if (NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) != 0)
/* There must be no V_MAY_DEFS or V_MUST_DEFS. */
if (!(ZERO_SSA_OPERANDS (stmt, (SSA_OP_VMAYDEF | SSA_OP_VMUSTDEF))))
return false;
/* Float expressions must go through memory if float-store is on. */
@ -1488,21 +1478,6 @@ check_replaceable (temp_expr_table_p tab, tree stmt)
return false;
}
uses = USE_OPS (ann);
num_use_ops = NUM_USES (uses);
vuseops = VUSE_OPS (ann);
/* Any expression which has no virtual operands and no real operands
should have been propagated if it's possible to do anything with them.
If this happens here, it probably exists that way for a reason, so we
won't touch it. An example is:
b_4 = &tab
There are no virtual uses nor any real uses, so we just leave this
alone to be safe. */
if (num_use_ops == 0 && NUM_VUSES (vuseops) == 0)
return false;
version = SSA_NAME_VERSION (def);
/* Add this expression to the dependency list for each use partition. */
@ -1512,7 +1487,7 @@ check_replaceable (temp_expr_table_p tab, tree stmt)
}
/* If there are VUSES, add a dependence on virtual defs. */
if (NUM_VUSES (vuseops) != 0)
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE))
{
add_value_to_list (tab, (value_expr_p *)&(tab->version_info[version]),
VIRTUAL_PARTITION (tab));
@ -1687,12 +1662,8 @@ find_replaceable_in_bb (temp_expr_table_p tab, basic_block bb)
free_value_expr (tab, p);
}
/* A V_MAY_DEF kills any expression using a virtual operand. */
if (NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) > 0)
kill_virtual_exprs (tab, true);
/* A V_MUST_DEF kills any expression using a virtual operand. */
if (NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) > 0)
/* A V_{MAY,MUST}_DEF kills any expression using a virtual operand. */
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
kill_virtual_exprs (tab, true);
}
}
@ -1743,7 +1714,8 @@ dump_replaceable_exprs (FILE *f, tree *expr)
if (expr[x])
{
stmt = expr[x];
var = DEF_OP (STMT_DEF_OPS (stmt), 0);
var = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
gcc_assert (var != NULL_TREE);
print_generic_expr (f, var, TDF_SLIM);
fprintf (f, " replace with --> ");
print_generic_expr (f, TREE_OPERAND (stmt, 1), TDF_SLIM);
@ -1874,13 +1846,11 @@ rewrite_trees (var_map map, tree *values)
{
for (si = bsi_start (bb); !bsi_end_p (si); )
{
size_t num_uses, num_defs;
use_optype uses;
def_optype defs;
tree stmt = bsi_stmt (si);
use_operand_p use_p;
use_operand_p use_p, copy_use_p;
def_operand_p def_p;
int remove = 0, is_copy = 0;
bool remove = false, is_copy = false;
int num_uses = 0;
stmt_ann_t ann;
ssa_op_iter iter;
@ -1889,44 +1859,46 @@ rewrite_trees (var_map map, tree *values)
if (TREE_CODE (stmt) == MODIFY_EXPR
&& (TREE_CODE (TREE_OPERAND (stmt, 1)) == SSA_NAME))
is_copy = 1;
is_copy = true;
uses = USE_OPS (ann);
num_uses = NUM_USES (uses);
copy_use_p = NULL_USE_OPERAND_P;
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
{
if (replace_use_variable (map, use_p, values))
changed = true;
changed = true;
copy_use_p = use_p;
num_uses++;
}
defs = DEF_OPS (ann);
num_defs = NUM_DEFS (defs);
if (num_uses != 1)
is_copy = false;
/* Mark this stmt for removal if it is the list of replaceable
expressions. */
if (values && num_defs == 1)
def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
if (def_p != NULL)
{
tree def = DEF_OP (defs, 0);
tree val;
val = values[SSA_NAME_VERSION (def)];
if (val)
remove = 1;
}
if (!remove)
{
FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
/* Mark this stmt for removal if it is the list of replaceable
expressions. */
if (values && values[SSA_NAME_VERSION (DEF_FROM_PTR (def_p))])
remove = true;
else
{
if (replace_def_variable (map, def_p, NULL))
changed = true;
/* If both SSA_NAMEs coalesce to the same variable,
mark the now redundant copy for removal. */
if (is_copy
&& num_uses == 1
&& (DEF_FROM_PTR (def_p) == USE_OP (uses, 0)))
remove = 1;
if (is_copy)
{
gcc_assert (copy_use_p != NULL_USE_OPERAND_P);
if (DEF_FROM_PTR (def_p) == USE_FROM_PTR (copy_use_p))
remove = true;
}
}
}
else
FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_DEF)
if (replace_def_variable (map, def_p, NULL))
changed = true;
/* Remove any stmts marked for removal. */
if (remove)

View File

@ -226,7 +226,7 @@ make_phi_node (tree var, int len)
for (i = 0; i < capacity; i++)
{
ssa_imm_use_t * imm;
use_operand_p imm;
imm = &(PHI_ARG_IMM_USE_NODE (phi, i));
imm->use = &(PHI_ARG_DEF_TREE (phi, i));
imm->prev = NULL;
@ -247,7 +247,7 @@ release_phi_node (tree phi)
for (x = 0; x < PHI_NUM_ARGS (phi); x++)
{
ssa_imm_use_t * imm;
use_operand_p imm;
imm = &(PHI_ARG_IMM_USE_NODE (phi, x));
delink_imm_use (imm);
}
@ -282,7 +282,7 @@ resize_phi_node (tree *phi, int len)
for (i = 0; i < PHI_NUM_ARGS (new_phi); i++)
{
ssa_imm_use_t *imm, *old_imm;
use_operand_p 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));
@ -293,7 +293,7 @@ resize_phi_node (tree *phi, int len)
for (i = PHI_NUM_ARGS (new_phi); i < len; i++)
{
ssa_imm_use_t * imm;
use_operand_p imm;
imm = &(PHI_ARG_IMM_USE_NODE (new_phi, i));
imm->use = &(PHI_ARG_DEF_TREE (new_phi, i));
imm->prev = NULL;

View File

@ -2098,6 +2098,9 @@ dump_vops (pretty_printer *buffer, tree stmt, int spc, int flags)
use_operand_p kill_p;
ssa_op_iter iter;
if (!ssa_operands_active ())
return;
FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, stmt, iter)
{
pp_string (buffer, "# ");

View File

@ -897,9 +897,7 @@ sra_walk_function (const struct sra_walk_fns *fns)
/* If the statement has no virtual operands, then it doesn't
make any structure references that we care about. */
if (NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) == 0
&& NUM_VUSES (VUSE_OPS (ann)) == 0
&& NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) == 0)
if (ZERO_SSA_OPERANDS (stmt, (SSA_OP_VIRTUAL_DEFS | SSA_OP_VUSE)))
continue;
switch (TREE_CODE (stmt))

View File

@ -457,9 +457,7 @@ likely_value (tree stmt)
if (!do_store_ccp
&& (ann->makes_aliased_stores
|| ann->makes_aliased_loads
|| NUM_VUSES (VUSE_OPS (ann)) > 0
|| NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) > 0
|| NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) > 0))
|| !ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS)))
return VARYING;
@ -495,8 +493,8 @@ likely_value (tree stmt)
}
if (found_constant
|| NUM_USES (USE_OPS (ann)) == 0
|| NUM_VUSES (VUSE_OPS (ann)) == 0)
|| ZERO_SSA_OPERANDS (stmt, SSA_OP_USE)
|| ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE))
return CONSTANT;
return UNDEFINED;
@ -934,17 +932,18 @@ ccp_fold (tree stmt)
== FUNCTION_DECL)
&& DECL_BUILT_IN (TREE_OPERAND (TREE_OPERAND (rhs, 0), 0)))
{
use_optype uses = STMT_USE_OPS (stmt);
if (NUM_USES (uses) != 0)
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_USE))
{
tree *orig;
tree *orig, var;
tree fndecl, arglist;
size_t i;
size_t i = 0;
ssa_op_iter iter;
use_operand_p var_p;
/* Preserve the original values of every operand. */
orig = xmalloc (sizeof (tree) * NUM_USES (uses));
for (i = 0; i < NUM_USES (uses); i++)
orig[i] = USE_OP (uses, i);
orig = xmalloc (sizeof (tree) * NUM_SSA_OPERANDS (stmt, SSA_OP_USE));
FOR_EACH_SSA_TREE_OPERAND (var, stmt, iter, SSA_OP_USE)
orig[i++] = var;
/* Substitute operands with their values and try to fold. */
replace_uses_in (stmt, NULL, const_val);
@ -953,8 +952,9 @@ ccp_fold (tree stmt)
retval = fold_builtin (fndecl, arglist, false);
/* Restore operands to their original form. */
for (i = 0; i < NUM_USES (uses); i++)
SET_USE_OP (uses, i, orig[i]);
i = 0;
FOR_EACH_SSA_USE_OPERAND (var_p, stmt, iter, SSA_OP_USE)
SET_USE (var_p, orig[i++]);
free (orig);
}
}
@ -1188,9 +1188,6 @@ visit_cond_stmt (tree stmt, edge *taken_edge_p)
static enum ssa_prop_result
ccp_visit_stmt (tree stmt, edge *taken_edge_p, tree *output_p)
{
stmt_ann_t ann;
v_may_def_optype v_may_defs;
v_must_def_optype v_must_defs;
tree def;
ssa_op_iter iter;
@ -1201,10 +1198,6 @@ ccp_visit_stmt (tree stmt, edge *taken_edge_p, tree *output_p)
fprintf (dump_file, "\n");
}
ann = stmt_ann (stmt);
v_must_defs = V_MUST_DEF_OPS (ann);
v_may_defs = V_MAY_DEF_OPS (ann);
if (TREE_CODE (stmt) == MODIFY_EXPR)
{
/* If the statement is an assignment that produces a single
@ -2206,17 +2199,18 @@ convert_to_gimple_builtin (block_stmt_iterator *si_p, tree expr)
tmp = get_initialized_tmp_var (expr, &stmts, NULL);
pop_gimplify_context (NULL);
/* The replacement can expose previously unreferenced variables. */
for (ti = tsi_start (stmts); !tsi_end_p (ti); tsi_next (&ti))
{
find_new_referenced_vars (tsi_stmt_ptr (ti));
mark_new_vars_to_rename (tsi_stmt (ti));
}
if (EXPR_HAS_LOCATION (stmt))
annotate_all_with_locus (&stmts, EXPR_LOCATION (stmt));
bsi_insert_before (si_p, stmts, BSI_SAME_STMT);
/* The replacement can expose previously unreferenced variables. */
for (ti = tsi_start (stmts); !tsi_end_p (ti); tsi_next (&ti))
{
tree new_stmt = tsi_stmt (ti);
find_new_referenced_vars (tsi_stmt_ptr (ti));
bsi_insert_before (si_p, new_stmt, BSI_NEW_STMT);
mark_new_vars_to_rename (bsi_stmt (*si_p));
bsi_next (si_p);
}
return tmp;
}

View File

@ -360,9 +360,7 @@ stmt_may_generate_copy (tree stmt)
/* If we are not doing store copy-prop, statements with loads and/or
stores will never generate a useful copy. */
if (!do_store_copy_prop
&& (NUM_VUSES (VUSE_OPS (ann)) > 0
|| NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) > 0
|| NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) > 0))
&& !ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
return false;
/* Otherwise, the only statements that generate useful copies are
@ -596,26 +594,31 @@ copy_prop_visit_cond_stmt (tree stmt, edge *taken_edge_p)
{
enum ssa_prop_result retval;
tree cond;
use_optype uses;
use_operand_p use_p;
ssa_op_iter iter;
unsigned num;
cond = COND_EXPR_COND (stmt);
uses = STMT_USE_OPS (stmt);
retval = SSA_PROP_VARYING;
num = NUM_SSA_OPERANDS (stmt, SSA_OP_USE);
/* The only conditionals that we may be able to compute statically
are predicates involving at least one SSA_NAME. */
if (COMPARISON_CLASS_P (cond)
&& NUM_USES (uses) >= 1)
&& num >= 1)
{
unsigned i;
tree *orig;
/* Save the original operands. */
orig = xmalloc (sizeof (tree) * NUM_USES (uses));
for (i = 0; i < NUM_USES (uses); i++)
orig = xmalloc (sizeof (tree) * num);
i = 0;
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
{
orig[i] = USE_OP (uses, i);
SET_USE_OP (uses, i, get_last_copy_of (USE_OP (uses, i)));
tree use = USE_FROM_PTR (use_p);
orig[i++] = use;
SET_USE (use_p, get_last_copy_of (use));
}
/* See if we can determine the predicate's value. */
@ -638,8 +641,9 @@ copy_prop_visit_cond_stmt (tree stmt, edge *taken_edge_p)
}
/* Restore the original operands. */
for (i = 0; i < NUM_USES (uses); i++)
SET_USE_OP (uses, i, orig[i]);
i = 0;
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
SET_USE (use_p, orig[i++]);
free (orig);
}

View File

@ -124,8 +124,8 @@ struct expr_hash_elt
/* The expression (rhs) we want to record. */
tree rhs;
/* The annotation if this element corresponds to a statement. */
stmt_ann_t ann;
/* The stmt pointer if this element corresponds to a statement. */
tree stmt;
/* The hash value for RHS/ann. */
hashval_t hash;
@ -675,36 +675,26 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e)
else
{
/* Copy the operands. */
stmt_ann_t ann = stmt_ann (stmt);
use_optype uses = USE_OPS (ann);
vuse_optype vuses = VUSE_OPS (ann);
tree *uses_copy = xmalloc (NUM_USES (uses) * sizeof (tree));
tree *vuses_copy = xmalloc (NUM_VUSES (vuses) * sizeof (tree));
unsigned int i;
tree *copy;
ssa_op_iter iter;
use_operand_p use_p;
unsigned int num, i = 0;
/* Make a copy of the uses into USES_COPY, then cprop into
the use operands. */
for (i = 0; i < NUM_USES (uses); i++)
num = NUM_SSA_OPERANDS (stmt, (SSA_OP_USE | SSA_OP_VUSE));
copy = xcalloc (num, sizeof (tree));
/* Make a copy of the uses & vuses into USES_COPY, then cprop into
the operands. */
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
{
tree tmp = NULL;
tree use = USE_FROM_PTR (use_p);
uses_copy[i] = USE_OP (uses, i);
if (TREE_CODE (USE_OP (uses, i)) == SSA_NAME)
tmp = SSA_NAME_VALUE (USE_OP (uses, i));
copy[i++] = use;
if (TREE_CODE (use) == SSA_NAME)
tmp = SSA_NAME_VALUE (use);
if (tmp && TREE_CODE (tmp) != VALUE_HANDLE)
SET_USE_OP (uses, i, tmp);
}
/* Similarly for virtual uses. */
for (i = 0; i < NUM_VUSES (vuses); i++)
{
tree tmp = NULL;
vuses_copy[i] = VUSE_OP (vuses, i);
if (TREE_CODE (VUSE_OP (vuses, i)) == SSA_NAME)
tmp = SSA_NAME_VALUE (VUSE_OP (vuses, i));
if (tmp && TREE_CODE (tmp) != VALUE_HANDLE)
SET_VUSE_OP (vuses, i, tmp);
SET_USE (use_p, tmp);
}
/* Try to fold/lookup the new expression. Inserting the
@ -715,15 +705,13 @@ thread_across_edge (struct dom_walk_data *walk_data, edge e)
&& !is_gimple_min_invariant (cached_lhs))
cached_lhs = lookup_avail_expr (stmt, false);
/* Restore the statement's original uses/defs. */
for (i = 0; i < NUM_USES (uses); i++)
SET_USE_OP (uses, i, uses_copy[i]);
i = 0;
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
SET_USE (use_p, copy[i++]);
for (i = 0; i < NUM_VUSES (vuses); i++)
SET_VUSE_OP (vuses, i, vuses_copy[i]);
free (uses_copy);
free (vuses_copy);
free (copy);
}
/* Record the context sensitive equivalence if we were able
@ -885,32 +873,32 @@ initialize_hash_element (tree expr, tree lhs, struct expr_hash_elt *element)
we want to record the expression the statement evaluates. */
if (COMPARISON_CLASS_P (expr) || TREE_CODE (expr) == TRUTH_NOT_EXPR)
{
element->ann = NULL;
element->stmt = NULL;
element->rhs = expr;
}
else if (TREE_CODE (expr) == COND_EXPR)
{
element->ann = stmt_ann (expr);
element->stmt = expr;
element->rhs = COND_EXPR_COND (expr);
}
else if (TREE_CODE (expr) == SWITCH_EXPR)
{
element->ann = stmt_ann (expr);
element->stmt = expr;
element->rhs = SWITCH_COND (expr);
}
else if (TREE_CODE (expr) == RETURN_EXPR && TREE_OPERAND (expr, 0))
{
element->ann = stmt_ann (expr);
element->stmt = expr;
element->rhs = TREE_OPERAND (TREE_OPERAND (expr, 0), 1);
}
else if (TREE_CODE (expr) == GOTO_EXPR)
{
element->ann = stmt_ann (expr);
element->stmt = expr;
element->rhs = GOTO_DESTINATION (expr);
}
else
{
element->ann = stmt_ann (expr);
element->stmt = expr;
element->rhs = TREE_OPERAND (expr, 1);
}
@ -2608,7 +2596,6 @@ static bool
eliminate_redundant_computations (struct dom_walk_data *walk_data,
tree stmt, stmt_ann_t ann)
{
v_may_def_optype v_may_defs = V_MAY_DEF_OPS (ann);
tree *expr_p, def = NULL_TREE;
bool insert = true;
tree cached_lhs;
@ -2623,7 +2610,7 @@ eliminate_redundant_computations (struct dom_walk_data *walk_data,
|| ! def
|| TREE_CODE (def) != SSA_NAME
|| SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def)
|| NUM_V_MAY_DEFS (v_may_defs) != 0
|| !ZERO_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF)
/* Do not record equivalences for increments of ivs. This would create
overlapping live ranges for a very questionable gain. */
|| simple_iv_increment_p (stmt))
@ -2804,7 +2791,7 @@ record_equivalences_from_stmt (tree stmt,
/* Build a new statement with the RHS and LHS exchanged. */
new = build (MODIFY_EXPR, TREE_TYPE (stmt), rhs, lhs);
create_ssa_artficial_load_stmt (&(ann->operands), new);
create_ssa_artficial_load_stmt (new, stmt);
/* Finally enter the statement into the available expression
table. */
@ -3391,11 +3378,11 @@ vrp_eq (const void *p1, const void *p2)
static hashval_t
avail_expr_hash (const void *p)
{
stmt_ann_t ann = ((struct expr_hash_elt *)p)->ann;
tree stmt = ((struct expr_hash_elt *)p)->stmt;
tree rhs = ((struct expr_hash_elt *)p)->rhs;
tree vuse;
ssa_op_iter iter;
hashval_t val = 0;
size_t i;
vuse_optype vuses;
/* iterative_hash_expr knows how to deal with any expression and
deals with commutative operators as well, so just use it instead
@ -3405,16 +3392,15 @@ avail_expr_hash (const void *p)
/* If the hash table entry is not associated with a statement, then we
can just hash the expression and not worry about virtual operands
and such. */
if (!ann)
if (!stmt || !stmt_ann (stmt))
return val;
/* Add the SSA version numbers of every vuse operand. This is important
because compound variables like arrays are not renamed in the
operands. Rather, the rename is done on the virtual variable
representing all the elements of the array. */
vuses = VUSE_OPS (ann);
for (i = 0; i < NUM_VUSES (vuses); i++)
val = iterative_hash_expr (VUSE_OP (vuses, i), val);
FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, iter, SSA_OP_VUSE)
val = iterative_hash_expr (vuse, val);
return val;
}
@ -3428,13 +3414,13 @@ real_avail_expr_hash (const void *p)
static int
avail_expr_eq (const void *p1, const void *p2)
{
stmt_ann_t ann1 = ((struct expr_hash_elt *)p1)->ann;
tree stmt1 = ((struct expr_hash_elt *)p1)->stmt;
tree rhs1 = ((struct expr_hash_elt *)p1)->rhs;
stmt_ann_t ann2 = ((struct expr_hash_elt *)p2)->ann;
tree stmt2 = ((struct expr_hash_elt *)p2)->stmt;
tree rhs2 = ((struct expr_hash_elt *)p2)->rhs;
/* If they are the same physical expression, return true. */
if (rhs1 == rhs2 && ann1 == ann2)
if (rhs1 == rhs2 && stmt1 == stmt2)
return true;
/* If their codes are not equal, then quit now. */
@ -3447,36 +3433,10 @@ avail_expr_eq (const void *p1, const void *p2)
|| lang_hooks.types_compatible_p (TREE_TYPE (rhs1), TREE_TYPE (rhs2)))
&& operand_equal_p (rhs1, rhs2, OEP_PURE_SAME))
{
vuse_optype ops1 = NULL;
vuse_optype ops2 = NULL;
size_t num_ops1 = 0;
size_t num_ops2 = 0;
size_t i;
if (ann1)
{
ops1 = VUSE_OPS (ann1);
num_ops1 = NUM_VUSES (ops1);
}
if (ann2)
{
ops2 = VUSE_OPS (ann2);
num_ops2 = NUM_VUSES (ops2);
}
/* If the number of virtual uses is different, then we consider
them not equal. */
if (num_ops1 != num_ops2)
return false;
for (i = 0; i < num_ops1; i++)
if (VUSE_OP (ops1, i) != VUSE_OP (ops2, i))
return false;
gcc_assert (((struct expr_hash_elt *)p1)->hash
bool ret = compare_ssa_operands_equal (stmt1, stmt2, SSA_OP_VUSE);
gcc_assert (!ret || ((struct expr_hash_elt *)p1)->hash
== ((struct expr_hash_elt *)p2)->hash);
return true;
return ret;
}
return false;

View File

@ -167,16 +167,10 @@ dse_optimize_stmt (struct dom_walk_data *walk_data,
struct dse_global_data *dse_gd = walk_data->global_data;
tree stmt = bsi_stmt (bsi);
stmt_ann_t ann = stmt_ann (stmt);
v_may_def_optype v_may_defs;
v_must_def_optype v_must_defs;
v_may_defs = V_MAY_DEF_OPS (ann);
v_must_defs = V_MUST_DEF_OPS (ann);
/* If this statement has no virtual defs, then there is nothing
to do. */
if (NUM_V_MAY_DEFS (v_may_defs) == 0
&& NUM_V_MUST_DEFS (v_must_defs) == 0)
if (ZERO_SSA_OPERANDS (stmt, (SSA_OP_VMAYDEF|SSA_OP_VMUSTDEF)))
return;
/* We know we have virtual definitions. If this is a MODIFY_EXPR that's

View File

@ -1578,25 +1578,13 @@ fail:
static void
find_invariants_stmt (struct ivopts_data *data, tree stmt)
{
use_optype uses = NULL;
unsigned i, n;
ssa_op_iter iter;
use_operand_p use_p;
tree op;
if (TREE_CODE (stmt) == PHI_NODE)
n = PHI_NUM_ARGS (stmt);
else
FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
{
uses = STMT_USE_OPS (stmt);
n = NUM_USES (uses);
}
for (i = 0; i < n; i++)
{
if (TREE_CODE (stmt) == PHI_NODE)
op = PHI_ARG_DEF (stmt, i);
else
op = USE_OP (uses, i);
op = USE_FROM_PTR (use_p);
record_invariant (data, op, false);
}
}
@ -1608,8 +1596,8 @@ find_interesting_uses_stmt (struct ivopts_data *data, tree stmt)
{
struct iv *iv;
tree op, lhs, rhs;
use_optype uses = NULL;
unsigned i, n;
ssa_op_iter iter;
use_operand_p use_p;
find_invariants_stmt (data, stmt);
@ -1677,20 +1665,9 @@ find_interesting_uses_stmt (struct ivopts_data *data, tree stmt)
return;
}
if (TREE_CODE (stmt) == PHI_NODE)
n = PHI_NUM_ARGS (stmt);
else
FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
{
uses = STMT_USE_OPS (stmt);
n = NUM_USES (uses);
}
for (i = 0; i < n; i++)
{
if (TREE_CODE (stmt) == PHI_NODE)
op = PHI_ARG_DEF (stmt, i);
else
op = USE_OP (uses, i);
op = USE_FROM_PTR (use_p);
if (TREE_CODE (op) != SSA_NAME)
continue;
@ -5577,22 +5554,11 @@ protect_loop_closed_ssa_form_use (edge exit, use_operand_p op_p)
static void
protect_loop_closed_ssa_form (edge exit, tree stmt)
{
use_optype uses;
vuse_optype vuses;
v_may_def_optype v_may_defs;
unsigned i;
ssa_op_iter iter;
use_operand_p use_p;
uses = STMT_USE_OPS (stmt);
for (i = 0; i < NUM_USES (uses); i++)
protect_loop_closed_ssa_form_use (exit, USE_OP_PTR (uses, i));
vuses = STMT_VUSE_OPS (stmt);
for (i = 0; i < NUM_VUSES (vuses); i++)
protect_loop_closed_ssa_form_use (exit, VUSE_OP_PTR (vuses, i));
v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
protect_loop_closed_ssa_form_use (exit, V_MAY_DEF_OP_PTR (v_may_defs, i));
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_ALL_USES)
protect_loop_closed_ssa_form_use (exit, use_p);
}
/* STMTS compute a value of a phi argument OP on EXIT of a loop. Arrange things

View File

@ -1081,8 +1081,8 @@ static tree
chain_of_csts_start (struct loop *loop, tree x)
{
tree stmt = SSA_NAME_DEF_STMT (x);
tree use;
basic_block bb = bb_for_stmt (stmt);
use_optype uses;
if (!bb
|| !flow_bb_inside_loop_p (loop, bb))
@ -1099,19 +1099,16 @@ chain_of_csts_start (struct loop *loop, tree x)
if (TREE_CODE (stmt) != MODIFY_EXPR)
return NULL_TREE;
if (NUM_VUSES (STMT_VUSE_OPS (stmt)) > 0)
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
return NULL_TREE;
if (NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) > 0)
return NULL_TREE;
if (NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt)) > 0)
return NULL_TREE;
if (NUM_DEFS (STMT_DEF_OPS (stmt)) > 1)
return NULL_TREE;
uses = STMT_USE_OPS (stmt);
if (NUM_USES (uses) != 1)
if (SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF) == NULL_DEF_OPERAND_P)
return NULL_TREE;
return chain_of_csts_start (loop, USE_OP (uses, 0));
use = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_USE);
if (use == NULL_USE_OPERAND_P)
return NULL_TREE;
return chain_of_csts_start (loop, use);
}
/* Determines whether the expression X is derived from a result of a phi node
@ -1164,8 +1161,8 @@ static tree
get_val_for (tree x, tree base)
{
tree stmt, nx, val;
use_optype uses;
use_operand_p op;
ssa_op_iter iter;
if (!x)
return base;
@ -1174,16 +1171,19 @@ get_val_for (tree x, tree base)
if (TREE_CODE (stmt) == PHI_NODE)
return base;
uses = STMT_USE_OPS (stmt);
op = USE_OP_PTR (uses, 0);
FOR_EACH_SSA_USE_OPERAND (op, stmt, iter, SSA_OP_USE)
{
nx = USE_FROM_PTR (op);
val = get_val_for (nx, base);
SET_USE (op, val);
val = fold (TREE_OPERAND (stmt, 1));
SET_USE (op, nx);
/* only iterate loop once. */
return val;
}
nx = USE_FROM_PTR (op);
val = get_val_for (nx, base);
SET_USE (op, val);
val = fold (TREE_OPERAND (stmt, 1));
SET_USE (op, nx);
return val;
/* Should never reach here. */
gcc_unreachable();
}
/* Tries to count the number of iterations of LOOP till it exits by EXIT

View File

@ -113,10 +113,9 @@ tree_ssa_unswitch_loops (struct loops *loops)
static tree
tree_may_unswitch_on (basic_block bb, struct loop *loop)
{
tree stmt, def, cond;
tree stmt, def, cond, use;
basic_block def_bb;
use_optype uses;
unsigned i;
ssa_op_iter iter;
/* BB must end in a simple conditional jump. */
stmt = last_stmt (bb);
@ -124,10 +123,9 @@ tree_may_unswitch_on (basic_block bb, struct loop *loop)
return NULL_TREE;
/* Condition must be invariant. */
uses = STMT_USE_OPS (stmt);
for (i = 0; i < NUM_USES (uses); i++)
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
{
def = SSA_NAME_DEF_STMT (USE_OP (uses, i));
def = SSA_NAME_DEF_STMT (use);
def_bb = bb_for_stmt (def);
if (def_bb
&& flow_bb_inside_loop_p (loop, def_bb))

File diff suppressed because it is too large Load Diff

View File

@ -25,155 +25,116 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* This represents a pointer to a DEF operand. */
typedef struct def_operand_ptr GTY(())
{
tree * GTY((skip(""))) def;
} def_operand_p;
typedef tree *def_operand_p;
/* This represents a pointer to a USE operand. */
typedef ssa_imm_use_t *use_operand_p;
typedef ssa_use_operand_t *use_operand_p;
/* NULL operand types. */
#define NULL_USE_OPERAND_P NULL
extern def_operand_p NULL_DEF_OPERAND_P;
#define NULL_DEF_OPERAND_P NULL
/* This represents the DEF operands of a stmt. */
typedef struct def_optype_d GTY(())
struct def_optype_d
{
unsigned num_defs;
struct def_operand_ptr GTY((length("%h.num_defs"))) defs[1];
} def_optype_t;
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;
struct def_optype_d *next;
tree *def_ptr;
};
typedef struct def_optype_d *def_optype_p;
/* This represents the USE operands of a stmt. */
typedef struct use_optype_d GTY(())
struct use_optype_d
{
unsigned num_uses;
struct ssa_imm_use_d GTY((length("%h.num_uses"))) uses[1];
} use_optype_t;
typedef use_optype_t *use_optype;
/* Operand type which stores a def a use, and an immediate use. */
typedef struct v_def_use_operand_type GTY(())
{
tree def;
tree use;
ssa_imm_use_t imm_use;
} v_def_use_operand_type_t;
struct use_optype_d *next;
struct ssa_use_operand_d use_ptr;
};
typedef struct use_optype_d *use_optype_p;
/* This represents the MAY_DEFS for a stmt. */
typedef struct v_may_def_optype_d GTY(())
struct maydef_optype_d
{
unsigned num_v_may_defs;
struct v_def_use_operand_type GTY((length ("%h.num_v_may_defs")))
v_may_defs[1];
} v_may_def_optype_t;
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;
struct maydef_optype_d *next;
tree def_var;
tree use_var;
struct ssa_use_operand_d use_ptr;
};
typedef struct maydef_optype_d *maydef_optype_p;
/* This represents the VUSEs for a stmt. */
typedef struct vuse_optype_d GTY(())
struct vuse_optype_d
{
unsigned num_vuses;
struct vuse_operand_type GTY((length ("%h.num_vuses"))) vuses[1];
} vuse_optype_t;
typedef vuse_optype_t *vuse_optype;
struct vuse_optype_d *next;
tree use_var;
struct ssa_use_operand_d use_ptr;
};
typedef struct vuse_optype_d *vuse_optype_p;
/* This represents the V_MUST_DEFS for a stmt. */
typedef struct v_must_def_optype_d GTY(())
struct mustdef_optype_d
{
unsigned num_v_must_defs;
v_def_use_operand_type_t GTY((length("%h.num_v_must_defs"))) v_must_defs[1];
} v_must_def_optype_t;
struct mustdef_optype_d *next;
tree def_var;
tree kill_var;
struct ssa_use_operand_d use_ptr;
};
typedef struct mustdef_optype_d *mustdef_optype_p;
#define SSA_OPERAND_MEMORY_SIZE (2048 - sizeof (void *))
struct ssa_operand_memory_d GTY((chain_next("%h.next")))
{
struct ssa_operand_memory_d *next;
char mem[SSA_OPERAND_MEMORY_SIZE];
};
typedef v_must_def_optype_t *v_must_def_optype;
/* This represents the operand cache for a stmt. */
typedef struct stmt_operands_d GTY(())
struct stmt_operands_d
{
/* Statement operands. */
struct def_optype_d * GTY (()) def_ops;
struct use_optype_d * GTY (()) use_ops;
struct def_optype_d * def_ops;
struct use_optype_d * use_ops;
/* Virtual operands (V_MAY_DEF, VUSE, and V_MUST_DEF). */
struct v_may_def_optype_d * GTY (()) v_may_def_ops;
struct vuse_optype_d * GTY (()) vuse_ops;
struct v_must_def_optype_d * GTY (()) v_must_def_ops;
} stmt_operands_t;
struct maydef_optype_d * maydef_ops;
struct vuse_optype_d * vuse_ops;
struct mustdef_optype_d * mustdef_ops;
};
typedef struct stmt_operands_d *stmt_operands_p;
#define USE_FROM_PTR(PTR) get_use_from_ptr (PTR)
#define DEF_FROM_PTR(PTR) get_def_from_ptr (PTR)
#define SET_USE(USE, V) set_ssa_use_from_ptr (USE, V)
#define SET_DEF(DEF, V) ((*(DEF)) = (V))
typedef stmt_operands_t *stmt_operands_p;
#define USE_STMT(USE) (USE)->stmt
#define USE_FROM_PTR(OP) get_use_from_ptr (OP)
#define DEF_FROM_PTR(OP) get_def_from_ptr (OP)
#define SET_USE(OP, V) set_ssa_use_from_ptr (OP, V)
#define SET_DEF(OP, V) ((*((OP).def)) = (V))
#define DEF_OPS(STMT) (stmt_ann (STMT)->operands.def_ops)
#define USE_OPS(STMT) (stmt_ann (STMT)->operands.use_ops)
#define VUSE_OPS(STMT) (stmt_ann (STMT)->operands.vuse_ops)
#define MAYDEF_OPS(STMT) (stmt_ann (STMT)->operands.maydef_ops)
#define MUSTDEF_OPS(STMT) (stmt_ann (STMT)->operands.mustdef_ops)
#define USE_STMT(OP) (OP)->stmt
#define USE_OP_PTR(OP) (&((OP)->use_ptr))
#define USE_OP(OP) (USE_FROM_PTR (USE_OP_PTR (OP)))
#define USE_OPS(ANN) get_use_ops (ANN)
#define STMT_USE_OPS(STMT) get_use_ops (stmt_ann (STMT))
#define NUM_USES(OPS) ((OPS) ? (OPS)->num_uses : 0)
#define USE_OP_PTR(OPS, I) get_use_op_ptr ((OPS), (I))
#define USE_OP(OPS, I) (USE_FROM_PTR (USE_OP_PTR ((OPS), (I))))
#define SET_USE_OP(OPS, I, V) (SET_USE (USE_OP_PTR ((OPS), (I)), (V)))
#define DEF_OP_PTR(OP) ((OP)->def_ptr)
#define DEF_OP(OP) (DEF_FROM_PTR (DEF_OP_PTR (OP)))
#define VUSE_OP_PTR(OP) USE_OP_PTR(OP)
#define VUSE_OP(OP) ((OP)->use_var)
#define MAYDEF_RESULT_PTR(OP) (&((OP)->def_var))
#define MAYDEF_RESULT(OP) ((OP)->def_var)
#define MAYDEF_OP_PTR(OP) USE_OP_PTR (OP)
#define MAYDEF_OP(OP) ((OP)->use_var)
#define DEF_OPS(ANN) get_def_ops (ANN)
#define STMT_DEF_OPS(STMT) get_def_ops (stmt_ann (STMT))
#define NUM_DEFS(OPS) ((OPS) ? (OPS)->num_defs : 0)
#define DEF_OP_PTR(OPS, I) get_def_op_ptr ((OPS), (I))
#define DEF_OP(OPS, I) (DEF_FROM_PTR (DEF_OP_PTR ((OPS), (I))))
#define SET_DEF_OP(OPS, I, V) (SET_DEF (DEF_OP_PTR ((OPS), (I)), (V)))
#define V_MAY_DEF_OPS(ANN) get_v_may_def_ops (ANN)
#define STMT_V_MAY_DEF_OPS(STMT) get_v_may_def_ops (stmt_ann(STMT))
#define NUM_V_MAY_DEFS(OPS) ((OPS) ? (OPS)->num_v_may_defs : 0)
#define V_MAY_DEF_RESULT_PTR(OPS, I) get_v_may_def_result_ptr ((OPS), (I))
#define V_MAY_DEF_RESULT(OPS, I) \
(DEF_FROM_PTR (V_MAY_DEF_RESULT_PTR ((OPS), (I))))
#define SET_V_MAY_DEF_RESULT(OPS, I, V) \
(SET_DEF (V_MAY_DEF_RESULT_PTR ((OPS), (I)), (V)))
#define V_MAY_DEF_OP_PTR(OPS, I) get_v_may_def_op_ptr ((OPS), (I))
#define V_MAY_DEF_OP(OPS, I) \
(USE_FROM_PTR (V_MAY_DEF_OP_PTR ((OPS), (I))))
#define SET_V_MAY_DEF_OP(OPS, I, V) \
(SET_USE (V_MAY_DEF_OP_PTR ((OPS), (I)), (V)))
#define VUSE_OPS(ANN) get_vuse_ops (ANN)
#define STMT_VUSE_OPS(STMT) get_vuse_ops (stmt_ann(STMT))
#define NUM_VUSES(OPS) ((OPS) ? (OPS)->num_vuses : 0)
#define VUSE_OP_PTR(OPS, I) get_vuse_op_ptr ((OPS), (I))
#define VUSE_OP(OPS, I) (USE_FROM_PTR (VUSE_OP_PTR ((OPS), (I))))
#define SET_VUSE_OP(OPS, I, V) (SET_USE (VUSE_OP_PTR ((OPS), (I)), (V)))
#define V_MUST_DEF_OPS(ANN) get_v_must_def_ops (ANN)
#define STMT_V_MUST_DEF_OPS(STMT) get_v_must_def_ops (stmt_ann (STMT))
#define NUM_V_MUST_DEFS(OPS) ((OPS) ? (OPS)->num_v_must_defs : 0)
#define V_MUST_DEF_RESULT_PTR(OPS, I) get_v_must_def_result_ptr ((OPS), (I))
#define V_MUST_DEF_RESULT(OPS, I) \
(DEF_FROM_PTR (V_MUST_DEF_RESULT_PTR ((OPS), (I))))
#define SET_V_MUST_DEF_RESULT(OPS, I, V) \
(SET_DEF (V_MUST_DEF_RESULT_PTR ((OPS), (I)), (V)))
#define V_MUST_DEF_KILL_PTR(OPS, I) get_v_must_def_kill_ptr ((OPS), (I))
#define V_MUST_DEF_KILL(OPS, I) (USE_FROM_PTR (V_MUST_DEF_KILL_PTR ((OPS), (I))))
#define SET_V_MUST_DEF_KILL(OPS, I, V) (SET_USE (V_MUST_DEF_KILL_PTR ((OPS), (I)), (V)))
#define MUSTDEF_RESULT_PTR(OP) (&((OP)->def_var))
#define MUSTDEF_RESULT(OP) ((OP)->def_var)
#define MUSTDEF_KILL_PTR(OP) USE_OP_PTR (OP)
#define MUSTDEF_KILL(OP) ((OP)->kill_var)
#define PHI_RESULT_PTR(PHI) get_phi_result_ptr (PHI)
#define PHI_RESULT(PHI) DEF_FROM_PTR (PHI_RESULT_PTR (PHI))
@ -196,7 +157,7 @@ extern void update_stmt_operands (tree);
extern bool verify_imm_links (FILE *f, tree var);
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 (tree, tree);
extern void dump_immediate_uses (FILE *file);
extern void dump_immediate_uses_for (FILE *file, tree var);
@ -206,6 +167,15 @@ extern void debug_immediate_uses_for (tree var);
extern bool ssa_call_clobbered_cache_valid;
extern bool ssa_ro_call_cache_valid;
extern bool ssa_operands_active (void);
enum ssa_op_iter_type {
ssa_op_iter_none = 0,
ssa_op_iter_tree,
ssa_op_iter_use,
ssa_op_iter_def,
ssa_op_iter_maymustdef
};
/* This structure is used in the operand iterator loops. It contains the
items required to determine which operand is retrieved next. During
optimization, this structure is scalarized, and any unused fields are
@ -213,21 +183,17 @@ extern bool ssa_ro_call_cache_valid;
typedef struct ssa_operand_iterator_d
{
int num_use;
int num_def;
int num_vuse;
int num_v_mayu;
int num_v_mayd;
int num_v_mustu;
int num_v_mustd;
int use_i;
int def_i;
int vuse_i;
int v_mayu_i;
int v_mayd_i;
int v_mustu_i;
int v_mustd_i;
stmt_operands_p ops;
def_optype_p defs;
use_optype_p uses;
vuse_optype_p vuses;
maydef_optype_p maydefs;
maydef_optype_p mayuses;
mustdef_optype_p mustdefs;
mustdef_optype_p mustkills;
enum ssa_op_iter_type iter_type;
int phi_i;
int num_phi;
tree phi_stmt;
bool done;
} ssa_op_iter;
@ -239,17 +205,19 @@ typedef struct ssa_operand_iterator_d
#define SSA_OP_VMAYUSE 0x08 /* USE portion of V_MAY_DEFS. */
#define SSA_OP_VMAYDEF 0x10 /* DEF portion of V_MAY_DEFS. */
#define SSA_OP_VMUSTDEF 0x20 /* V_MUST_DEF definitions. */
#define SSA_OP_VMUSTDEFKILL 0x40 /* V_MUST_DEF kills. */
#define SSA_OP_VMUSTKILL 0x40 /* V_MUST_DEF kills. */
/* These are commonly grouped operand flags. */
#define SSA_OP_VIRTUAL_USES (SSA_OP_VUSE | SSA_OP_VMAYUSE)
#define SSA_OP_VIRTUAL_DEFS (SSA_OP_VMAYDEF | SSA_OP_VMUSTDEF)
#define SSA_OP_VIRTUAL_KILLS (SSA_OP_VMUSTDEFKILL)
#define SSA_OP_ALL_VIRTUALS (SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS | SSA_OP_VIRTUAL_DEFS)
#define SSA_OP_VIRTUAL_KILLS (SSA_OP_VMUSTKILL)
#define SSA_OP_ALL_VIRTUALS (SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS \
| SSA_OP_VIRTUAL_DEFS)
#define SSA_OP_ALL_USES (SSA_OP_VIRTUAL_USES | SSA_OP_USE)
#define SSA_OP_ALL_DEFS (SSA_OP_VIRTUAL_DEFS | SSA_OP_DEF)
#define SSA_OP_ALL_KILLS (SSA_OP_VIRTUAL_KILLS)
#define SSA_OP_ALL_OPERANDS (SSA_OP_ALL_USES | SSA_OP_ALL_DEFS | SSA_OP_ALL_KILLS)
#define SSA_OP_ALL_OPERANDS (SSA_OP_ALL_USES | SSA_OP_ALL_DEFS \
| SSA_OP_ALL_KILLS)
/* This macro executes a loop over the operands of STMT specified in FLAG,
returning each operand as a 'tree' in the variable TREEVAR. ITER is an
@ -281,7 +249,7 @@ typedef struct ssa_operand_iterator_d
#define FOR_EACH_SSA_MAYDEF_OPERAND(DEFVAR, USEVAR, STMT, ITER) \
for (op_iter_init_maydef (&(ITER), STMT, &(USEVAR), &(DEFVAR)); \
!op_iter_done (&(ITER)); \
op_iter_next_maydef (&(USEVAR), &(DEFVAR), &(ITER)))
op_iter_next_maymustdef (&(USEVAR), &(DEFVAR), &(ITER)))
/* This macro executes a loop over the V_MUST_DEF operands of STMT. The def
and kill for each V_MUST_DEF is returned in DEFVAR and KILLVAR.
@ -289,7 +257,7 @@ typedef struct ssa_operand_iterator_d
#define FOR_EACH_SSA_MUSTDEF_OPERAND(DEFVAR, KILLVAR, STMT, ITER) \
for (op_iter_init_mustdef (&(ITER), STMT, &(KILLVAR), &(DEFVAR)); \
!op_iter_done (&(ITER)); \
op_iter_next_mustdef (&(KILLVAR), &(DEFVAR), &(ITER)))
op_iter_next_maymustdef (&(KILLVAR), &(DEFVAR), &(ITER)))
/* This macro executes a loop over the V_{MUST,MAY}_DEF of STMT. The def
and kill for each V_{MUST,MAY}_DEF is returned in DEFVAR and KILLVAR.
@ -297,5 +265,56 @@ typedef struct ssa_operand_iterator_d
#define FOR_EACH_SSA_MUST_AND_MAY_DEF_OPERAND(DEFVAR, KILLVAR, STMT, ITER)\
for (op_iter_init_must_and_may_def (&(ITER), STMT, &(KILLVAR), &(DEFVAR));\
!op_iter_done (&(ITER)); \
op_iter_next_must_and_may_def (&(KILLVAR), &(DEFVAR), &(ITER)))
op_iter_next_maymustdef (&(KILLVAR), &(DEFVAR), &(ITER)))
/* This macro will execute a loop over all the arguemnts of a PHI which
match FLAGS. A use_operand_p is alwasy returned via USEVAR. FLAGS
can be eiother SSA_OP_USE or SSA_OP_VIRTUAL_USES or SSA_OP_ALL_USES. */
#define FOR_EACH_PHI_ARG (USEVAR, STMT, ITER, FLAGS) \
for ((USEVAR) = op_iter_init_phiuse (&(ITER), STMT, FLAGS); \
!op_iter_done (&(ITER)); \
(USEVAR) = op_iter_next_use (&(ITER)))
/* This macro will execute a loop over a stmt, regardless of whether it is
a real stmt or a PHI node, looking at the USE nodes matching FLAGS. */
#define FOR_EACH_PHI_OR_STMT_USE(USEVAR, STMT, ITER, FLAGS) \
for ((USEVAR) = (TREE_CODE (STMT) == PHI_NODE \
? op_iter_init_phiuse (&(ITER), STMT, FLAGS) \
: op_iter_init_use (&(ITER), STMT, FLAGS)); \
!op_iter_done (&(ITER)); \
(USEVAR) = op_iter_next_use (&(ITER)))
/* This macro will execute a loop over a stmt, regardless of whether it is
a real stmt or a PHI node, looking at the DEF nodes matching FLAGS. */
#define FOR_EACH_PHI_OR_STMT_DEF(DEFVAR, STMT, ITER, FLAGS) \
for ((DEFVAR) = (TREE_CODE (STMT) == PHI_NODE \
? op_iter_init_phidef (&(ITER), STMT, FLAGS) \
: op_iter_init_def (&(ITER), STMT, FLAGS)); \
!op_iter_done (&(ITER)); \
(DEFVAR) = op_iter_next_def (&(ITER)))
/* This macro returns an operand in STMT as a tree if it is the ONLY
operand matching FLAGS. If there are 0 or more than 1 operand matching
FLAGS, then NULL_TREE is returned. */
#define SINGLE_SSA_TREE_OPERAND(STMT, FLAGS) \
single_ssa_tree_operand (STMT, FLAGS)
/* This macro returns an operand in STMT as a use_operand_p if it is the ONLY
operand matching FLAGS. If there are 0 or more than 1 operand matching
FLAGS, then NULL_USE_OPERAND_P is returned. */
#define SINGLE_SSA_USE_OPERAND(STMT, FLAGS) \
single_ssa_use_operand (STMT, FLAGS)
/* This macro returns an operand in STMT as a def_operand_p if it is the ONLY
operand matching FLAGS. If there are 0 or more than 1 operand matching
FLAGS, then NULL_DEF_OPERAND_P is returned. */
#define SINGLE_SSA_DEF_OPERAND(STMT, FLAGS) \
single_ssa_def_operand (STMT, FLAGS)
/* This macro returns TRUE if there are no operands matching FLAGS in STMT. */
#define ZERO_SSA_OPERANDS(STMT, FLAGS) zero_ssa_operands (STMT, FLAGS)
/* THis macro counts the number of operands in STMT matching FLAGS. */
#define NUM_SSA_OPERANDS(STMT, FLAGS) num_ssa_operands (STMT, FLAGS)
#endif /* GCC_TREE_SSA_OPERANDS_H */

175
gcc/tree-ssa-opfinalize.h Normal file
View File

@ -0,0 +1,175 @@
/* SSA operand allocation and finalizing.
Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 2, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
Software Foundation, 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA. */
/* This file contains common code which is used by each of the 5 operand
types. Macros are defined to specify the varying componenets.
FINALIZE_FUNC - name of finalize function.
FINALIZE_ALLOC - name of allocation routine.
FINALIZE_FREE - name of free list.
FINALIZE_TYPE - type of node.
FINALIZE_OPS - Lead element in list.
FINALIZE_USE_PTR - How to get the use_operand_p, if this is a use operand.
FINALIZE_INITIALIZE - How to initialize an element.
FINALIZE_ELEM - How to retreive an element.
FINALIZE_BASE - How to retreive the base variable of an element.
FINALIZE_BASE_TYPE - Type of the base variable.
FINALIZE_OPBUILD - Opbuild array for these nodes.
FINALIZE_OPBUILD_ELEM - How to get an element from the opbuild list.
FINALIZE_OPBUILD_BASE - How to get an element base from the opbuild list.
FINALIZE_BASE_ZERO - How to zero an element. */
/* This routine will either pick up a node from the free list, or allocate a
new one if need be. */
static inline FINALIZE_TYPE *
FINALIZE_ALLOC (void)
{
FINALIZE_TYPE *ret;
if (FINALIZE_FREE)
{
ret = FINALIZE_FREE;
FINALIZE_FREE = FINALIZE_FREE->next;
}
else
ret = (FINALIZE_TYPE *)ssa_operand_alloc (sizeof (FINALIZE_TYPE));
return ret;
}
/* This routine will take the new operands from FINALIZE_OPBUILD and turn them
into the new operands for STMT. All required linking and deleting is u
performed here. */
static inline void
FINALIZE_FUNC (tree stmt)
{
int new_i;
FINALIZE_TYPE *old_ops, *ptr, *last;
FINALIZE_BASE_TYPE old_base;
FINALIZE_TYPE new_list;
new_list.next = NULL;
last = &new_list;
old_ops = FINALIZE_OPS (stmt);
if (old_ops)
old_base = FINALIZE_BASE (FINALIZE_ELEM (old_ops));
else
old_base = FINALIZE_BASE_ZERO;
new_i = opbuild_first (&FINALIZE_OPBUILD);
while (old_ops && new_i != OPBUILD_LAST)
{
FINALIZE_BASE_TYPE new_base = FINALIZE_OPBUILD_BASE (new_i);
if (old_base == new_base)
{
/* if variables are the same, reuse this node. */
last->next = old_ops;
last = old_ops;
#ifdef FINALIZE_USE_PTR
correct_use_link (FINALIZE_USE_PTR (last), stmt);
#endif
old_ops = old_ops->next;
new_i = opbuild_next (&FINALIZE_OPBUILD, new_i);
}
else
if (old_base < new_base)
{
/* if old is less than new, old goes to the free list. */
#ifdef FINALIZE_USE_PTR
use_operand_p use_p = FINALIZE_USE_PTR (old_ops);
delink_imm_use (use_p);
#endif
ptr = old_ops;
old_ops = old_ops->next;
ptr->next = FINALIZE_FREE;
FINALIZE_FREE = ptr;
}
else
{
/* This is a new operand. */
ptr = FINALIZE_ALLOC ();
FINALIZE_INITIALIZE (ptr, FINALIZE_OPBUILD_ELEM (new_i), stmt);
last->next = ptr;
last = ptr;
new_i = opbuild_next (&FINALIZE_OPBUILD, new_i);
}
if (old_ops)
old_base = FINALIZE_BASE (FINALIZE_ELEM (old_ops));
}
/* If there is anything remaining in the opbuild list, simply emit them. */
for ( ;
new_i != OPBUILD_LAST;
new_i = opbuild_next (&FINALIZE_OPBUILD, new_i))
{
ptr = FINALIZE_ALLOC ();
FINALIZE_INITIALIZE (ptr, FINALIZE_OPBUILD_ELEM (new_i), stmt);
last->next = ptr;
last = ptr;
}
last->next = NULL;
/* If there is anything in the old list, free them. */
if (old_ops)
{
#ifdef FINALIZE_USE_PTR
for (ptr = old_ops; ptr; ptr = ptr->next)
{
use_operand_p use_p = FINALIZE_USE_PTR (ptr);
delink_imm_use (use_p);
}
#endif
old_ops->next = FINALIZE_FREE;
FINALIZE_FREE = old_ops;
}
/* NOw set the stmt's operands. */
FINALIZE_OPS (stmt) = new_list.next;
#ifdef ENABLE_CHECKING
{
unsigned x = 0;
for (ptr = FINALIZE_OPS (stmt); ptr; ptr = ptr->next)
x++;
gcc_assert (x == opbuild_num_elems (&FINALIZE_OPBUILD));
}
#endif
}
#undef FINALIZE_FUNC
#undef FINALIZE_ALLOC
#undef FINALIZE_FREE
#undef FINALIZE_TYPE
#undef FINALIZE_OPS
#undef FINALIZE_USE_PTR
#undef FINALIZE_INITIALIZE
#undef FINALIZE_ELEM
#undef FINALIZE_BASE
#undef FINALIZE_BASE_TYPE
#undef FINALIZE_OPBUILD
#undef FINALIZE_OPBUILD_ELEM
#undef FINALIZE_OPBUILD_BASE
#undef FINALIZE_BASE_ZERO

View File

@ -1758,17 +1758,17 @@ is_undefined_value (tree expr)
any). They are used when computing the hash value for EXPR. */
static inline void
add_to_sets (tree var, tree expr, vuse_optype vuses, bitmap_set_t s1,
add_to_sets (tree var, tree expr, tree stmt, bitmap_set_t s1,
bitmap_set_t s2)
{
tree val = vn_lookup_or_add (expr, vuses);
tree val = vn_lookup_or_add (expr, stmt);
/* VAR and EXPR may be the same when processing statements for which
we are not computing value numbers (e.g., non-assignments, or
statements that make aliased stores). In those cases, we are
only interested in making VAR available as its own value. */
if (var != expr)
vn_add (var, val, NULL);
vn_add (var, val, NULL_TREE);
if (s1)
bitmap_insert_into_set (s1, var);
@ -1785,9 +1785,7 @@ add_to_sets (tree var, tree expr, vuse_optype vuses, bitmap_set_t s1,
Insert EXPR's operands into the EXP_GEN set for BLOCK. */
static inline tree
create_value_expr_from (tree expr, basic_block block,
vuse_optype vuses)
create_value_expr_from (tree expr, basic_block block, tree stmt)
{
int i;
enum tree_code code = TREE_CODE (expr);
@ -1829,9 +1827,9 @@ create_value_expr_from (tree expr, basic_block block,
/* Recursively value-numberize reference ops */
if (REFERENCE_CLASS_P (op))
{
tree tempop = create_value_expr_from (op, block, vuses);
tree tempop = create_value_expr_from (op, block, stmt);
op = tempop ? tempop : op;
val = vn_lookup_or_add (op, vuses);
val = vn_lookup_or_add (op, stmt);
}
else
/* Create a value handle for OP and add it to VEXPR. */
@ -1922,7 +1920,8 @@ compute_avail (void)
for (bsi = bsi_start (block); !bsi_end_p (bsi); bsi_next (&bsi))
{
stmt_ann_t ann;
size_t j;
ssa_op_iter iter;
tree op;
stmt = bsi_stmt (bsi);
ann = stmt_ann (stmt);
@ -1938,7 +1937,6 @@ compute_avail (void)
{
tree lhs = TREE_OPERAND (stmt, 0);
tree rhs = TREE_OPERAND (stmt, 1);
vuse_optype vuses = STMT_VUSE_OPS (stmt);
STRIP_USELESS_TYPE_CONVERSION (rhs);
if (UNARY_CLASS_P (rhs)
@ -1950,10 +1948,10 @@ compute_avail (void)
create a duplicate expression with the operands
replaced with the value handles of the original
RHS. */
tree newt = create_value_expr_from (rhs, block, vuses);
tree newt = create_value_expr_from (rhs, block, stmt);
if (newt)
{
add_to_sets (lhs, newt, vuses, TMP_GEN (block),
add_to_sets (lhs, newt, stmt, TMP_GEN (block),
AVAIL_OUT (block));
value_insert_into_set (EXP_GEN (block), newt);
continue;
@ -1968,7 +1966,7 @@ compute_avail (void)
/* Compute a value number for the RHS of the statement
and add its value to the AVAIL_OUT set for the block.
Add the LHS to TMP_GEN. */
add_to_sets (lhs, rhs, vuses, TMP_GEN (block),
add_to_sets (lhs, rhs, stmt, TMP_GEN (block),
AVAIL_OUT (block));
if (TREE_CODE (rhs) == SSA_NAME
@ -1981,18 +1979,11 @@ compute_avail (void)
/* For any other statement that we don't recognize, simply
make the names generated by the statement available in
AVAIL_OUT and TMP_GEN. */
for (j = 0; j < NUM_DEFS (STMT_DEF_OPS (stmt)); j++)
{
tree def = DEF_OP (STMT_DEF_OPS (stmt), j);
add_to_sets (def, def, NULL, TMP_GEN (block),
AVAIL_OUT (block));
}
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_DEF)
add_to_sets (op, op, NULL, TMP_GEN (block), AVAIL_OUT (block));
for (j = 0; j < NUM_USES (STMT_USE_OPS (stmt)); j++)
{
tree use = USE_OP (STMT_USE_OPS (stmt), j);
add_to_sets (use, use, NULL, NULL, AVAIL_OUT (block));
}
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_USE)
add_to_sets (op, op, NULL, NULL , AVAIL_OUT (block));
}
/* Put the dominator children of BLOCK on the worklist of blocks

View File

@ -678,12 +678,14 @@ ssa_propagate (ssa_prop_visit_stmt_fn visit_stmt,
tree
first_vdef (tree stmt)
{
if (NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) > 0)
return V_MAY_DEF_RESULT (STMT_V_MAY_DEF_OPS (stmt), 0);
else if (NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt)) > 0)
return V_MUST_DEF_RESULT (STMT_V_MUST_DEF_OPS (stmt), 0);
else
gcc_unreachable ();
ssa_op_iter iter;
tree op;
/* Simply return the first operand we arrive at. */
FOR_EACH_SSA_TREE_OPERAND (op, stmt, iter, SSA_OP_VIRTUAL_DEFS)
return (op);
gcc_unreachable ();
}
@ -700,8 +702,7 @@ stmt_makes_single_load (tree stmt)
if (TREE_CODE (stmt) != MODIFY_EXPR)
return false;
if (NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) == 0
&& NUM_VUSES (STMT_VUSE_OPS (stmt)) == 0)
if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF|SSA_OP_VUSE))
return false;
rhs = TREE_OPERAND (stmt, 1);
@ -726,8 +727,7 @@ stmt_makes_single_store (tree stmt)
if (TREE_CODE (stmt) != MODIFY_EXPR)
return false;
if (NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) == 0
&& NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt)) == 0)
if (ZERO_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF|SSA_OP_VMUSTDEF))
return false;
lhs = TREE_OPERAND (stmt, 0);

View File

@ -138,16 +138,10 @@ all_immediate_uses_same_place (tree stmt)
bool
is_hidden_global_store (tree stmt)
{
stmt_ann_t ann = stmt_ann (stmt);
v_may_def_optype v_may_defs;
v_must_def_optype v_must_defs;
/* Check virtual definitions. If we get here, the only virtual
definitions we should see are those generated by assignment
statements. */
v_may_defs = V_MAY_DEF_OPS (ann);
v_must_defs = V_MUST_DEF_OPS (ann);
if (NUM_V_MAY_DEFS (v_may_defs) > 0 || NUM_V_MUST_DEFS (v_must_defs) > 0)
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
{
tree lhs;
@ -324,13 +318,13 @@ statement_sink_location (tree stmt, basic_block frombb)
*/
ann = stmt_ann (stmt);
if (NUM_VUSES (STMT_VUSE_OPS (stmt)) != 0
|| stmt_ends_bb_p (stmt)
if (stmt_ends_bb_p (stmt)
|| TREE_SIDE_EFFECTS (rhs)
|| TREE_CODE (rhs) == EXC_PTR_EXPR
|| TREE_CODE (rhs) == FILTER_EXPR
|| is_hidden_global_store (stmt)
|| ann->has_volatile_ops)
|| ann->has_volatile_ops
|| !ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE))
return NULL;
FOR_EACH_SSA_DEF_OPERAND (def_p, stmt, iter, SSA_OP_ALL_DEFS)
@ -397,18 +391,10 @@ statement_sink_location (tree stmt, basic_block frombb)
}
/* Note that at this point, all uses must be in the same statement, so it
doesn't matter which def op we choose. */
if (STMT_DEF_OPS (stmt) == NULL)
{
if (STMT_V_MAY_DEF_OPS (stmt) != NULL)
def = V_MAY_DEF_RESULT (STMT_V_MAY_DEF_OPS (stmt), 0);
else if (STMT_V_MUST_DEF_OPS (stmt) != NULL)
def = V_MUST_DEF_RESULT (STMT_V_MUST_DEF_OPS (stmt), 0);
else
gcc_unreachable ();
}
else
def = DEF_OP (STMT_DEF_OPS (stmt), 0);
doesn't matter which def op we choose, pick the first one. */
FOR_EACH_SSA_TREE_OPERAND (def, stmt, iter, SSA_OP_ALL_DEFS)
break;
sinkbb = find_bb_for_arg (use, def);
if (!sinkbb)

View File

@ -709,8 +709,8 @@ verify_ssa (bool check_modified_stmt)
if (check_modified_stmt && stmt_modified_p (stmt))
{
error ("Stmt (0x%x) marked modified after optimization pass : ",
(unsigned long)stmt);
error ("Stmt (%p) marked modified after optimization pass : ",
(void *)stmt);
print_generic_stmt (stderr, stmt, TDF_VOPS);
goto err;
}
@ -725,8 +725,7 @@ verify_ssa (bool check_modified_stmt)
if (base_address
&& SSA_VAR_P (base_address)
&& NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) == 0
&& NUM_V_MUST_DEFS (STMT_V_MUST_DEF_OPS (stmt)) == 0)
&& ZERO_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF|SSA_OP_VMUSTDEF))
{
error ("Statement makes a memory store, but has no "
"V_MAY_DEFS nor V_MUST_DEFS");
@ -737,7 +736,7 @@ verify_ssa (bool check_modified_stmt)
if (stmt_ann (stmt)->makes_aliased_stores
&& NUM_V_MAY_DEFS (STMT_V_MAY_DEF_OPS (stmt)) == 0)
&& ZERO_SSA_OPERANDS (stmt, SSA_OP_VMAYDEF))
{
error ("Statement makes aliased stores, but has no V_MAY_DEFS");
print_generic_stmt (stderr, stmt, TDF_VOPS);
@ -806,12 +805,23 @@ delete_tree_ssa (void)
basic_block bb;
block_stmt_iterator bsi;
/* Release any ssa_names still in use. */
for (i = 0; i < num_ssa_names; i++)
{
tree var = ssa_name (i);
if (var && TREE_CODE (var) == SSA_NAME)
{
SSA_NAME_IMM_USE_NODE (var).prev = &(SSA_NAME_IMM_USE_NODE (var));
SSA_NAME_IMM_USE_NODE (var).next = &(SSA_NAME_IMM_USE_NODE (var));
}
release_ssa_name (var);
}
/* Remove annotations from every tree in the function. */
FOR_EACH_BB (bb)
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
tree stmt = bsi_stmt (bsi);
release_defs (stmt);
ggc_free (stmt->common.ann);
stmt->common.ann = NULL;
}
@ -943,9 +953,7 @@ stmt_references_memory_p (tree stmt)
if (ann->has_volatile_ops)
return true;
return (NUM_VUSES (VUSE_OPS (ann)) > 0
|| NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) > 0
|| NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) > 0);
return (!ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS));
}
/* Internal helper for walk_use_def_chains. VAR, FN and DATA are as

View File

@ -121,7 +121,7 @@ tree
make_ssa_name (tree var, tree stmt)
{
tree t;
ssa_imm_use_t *imm;
use_operand_p imm;
gcc_assert (DECL_P (var)
|| TREE_CODE (var) == INDIRECT_REF);
@ -205,7 +205,7 @@ release_ssa_name (tree var)
{
tree saved_ssa_name_var = SSA_NAME_VAR (var);
int saved_ssa_name_version = SSA_NAME_VERSION (var);
ssa_imm_use_t *imm = &(SSA_NAME_IMM_USE_NODE (var));
use_operand_p imm = &(SSA_NAME_IMM_USE_NODE (var));
#ifdef ENABLE_CHECKING
verify_imm_links (stderr, var);

View File

@ -413,9 +413,7 @@ find_tail_calls (basic_block bb, struct tailcall **ret)
/* If the statement has virtual or volatile operands, fail. */
ann = stmt_ann (stmt);
if (NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann))
|| NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann))
|| NUM_VUSES (VUSE_OPS (ann))
if (!ZERO_SSA_OPERANDS (stmt, (SSA_OP_VUSE | SSA_OP_VIRTUAL_DEFS))
|| ann->has_volatile_ops)
return;
}
@ -679,13 +677,13 @@ eliminate_tail_call (struct tailcall *t)
basic_block bb, first;
edge e;
tree phi;
stmt_ann_t ann;
v_may_def_optype v_may_defs;
unsigned i;
block_stmt_iterator bsi;
use_operand_p mayuse;
def_operand_p maydef;
ssa_op_iter iter;
tree orig_stmt;
stmt = bsi_stmt (t->call_bsi);
ann = stmt_ann (stmt);
stmt = orig_stmt = bsi_stmt (t->call_bsi);
bb = t->call_block;
if (dump_file && (dump_flags & TDF_DETAILS))
@ -748,10 +746,9 @@ eliminate_tail_call (struct tailcall *t)
}
/* Add phi nodes for the call clobbered variables. */
v_may_defs = V_MAY_DEF_OPS (ann);
for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
FOR_EACH_SSA_MAYDEF_OPERAND (maydef, mayuse, orig_stmt, iter)
{
param = SSA_NAME_VAR (V_MAY_DEF_RESULT (v_may_defs, i));
param = SSA_NAME_VAR (DEF_FROM_PTR (maydef));
for (phi = phi_nodes (first); phi; phi = PHI_CHAIN (phi))
if (param == SSA_NAME_VAR (PHI_RESULT (phi)))
break;
@ -782,7 +779,7 @@ eliminate_tail_call (struct tailcall *t)
gcc_assert (EDGE_COUNT (first->preds) <= 2);
}
add_phi_arg (phi, V_MAY_DEF_OP (v_may_defs, i), e);
add_phi_arg (phi, USE_FROM_PTR (mayuse), e);
}
/* Update the values of accumulators. */

View File

@ -1943,29 +1943,25 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
bool is_read = false;
tree stmt = bsi_stmt (si);
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
v_may_def_optype v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
v_must_def_optype v_must_defs = STMT_V_MUST_DEF_OPS (stmt);
vuse_optype vuses = STMT_VUSE_OPS (stmt);
varray_type *datarefs = NULL;
int nvuses, nv_may_defs, nv_must_defs;
tree memref = NULL;
tree scalar_type, vectype;
tree base, offset, misalign, step, tag;
struct ptr_info_def *ptr_info;
bool base_aligned;
subvar_t subvars = NULL;
bool no_vuse, no_vmaymust;
/* Assumption: there exists a data-ref in stmt, if and only if
it has vuses/vdefs. */
if (!vuses && !v_may_defs && !v_must_defs)
no_vuse = ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE);
no_vmaymust = ZERO_SSA_OPERANDS (stmt,
SSA_OP_VMAYDEF | SSA_OP_VMUSTDEF);
if (no_vuse && no_vmaymust)
continue;
nvuses = NUM_VUSES (vuses);
nv_may_defs = NUM_V_MAY_DEFS (v_may_defs);
nv_must_defs = NUM_V_MUST_DEFS (v_must_defs);
if (nvuses && (nv_may_defs || nv_must_defs))
if (!no_vuse && !no_vmaymust)
{
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
{
@ -1985,7 +1981,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
return false;
}
if (vuses)
if (!no_vuse)
{
memref = TREE_OPERAND (stmt, 1);
datarefs = &(LOOP_VINFO_DATAREF_READS (loop_vinfo));
@ -2106,49 +2102,29 @@ vect_mark_relevant (VEC(tree,heap) **worklist, tree stmt)
static bool
vect_stmt_relevant_p (tree stmt, loop_vec_info loop_vinfo)
{
v_may_def_optype v_may_defs;
v_must_def_optype v_must_defs;
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
ssa_op_iter op_iter;
imm_use_iterator imm_iter;
use_operand_p use_p;
tree var;
def_operand_p def_p;
/* cond stmt other than loop exit cond. */
if (is_ctrl_stmt (stmt) && (stmt != LOOP_VINFO_EXIT_COND (loop_vinfo)))
return true;
/* changing memory. */
if (TREE_CODE (stmt) == PHI_NODE)
{
if (!is_gimple_reg (PHI_RESULT (stmt)))
return false;
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, PHI_RESULT (stmt))
{
basic_block bb = bb_for_stmt (USE_STMT (use_p));
if (!flow_bb_inside_loop_p (loop, bb))
{
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "vec_stmt_relevant_p: used out of loop.");
return true;
}
}
return false;
}
v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
v_must_defs = STMT_V_MUST_DEF_OPS (stmt);
if (v_may_defs || v_must_defs)
{
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "vec_stmt_relevant_p: stmt has vdefs.");
return true;
}
if (TREE_CODE (stmt) != PHI_NODE)
if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
{
if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
fprintf (vect_dump, "vec_stmt_relevant_p: stmt has vdefs.");
return true;
}
/* uses outside the loop. */
FOR_EACH_SSA_TREE_OPERAND (var, stmt, op_iter, SSA_OP_DEF)
FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF)
{
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, var)
FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p))
{
basic_block bb = bb_for_stmt (USE_STMT (use_p));
if (!flow_bb_inside_loop_p (loop, bb))
@ -2188,11 +2164,10 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
unsigned int nbbs = loop->num_nodes;
block_stmt_iterator si;
tree stmt;
stmt_ann_t ann;
tree stmt, use;
ssa_op_iter iter;
unsigned int i;
int j;
use_optype use_ops;
stmt_vec_info stmt_info;
basic_block bb;
tree phi;
@ -2291,12 +2266,8 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
}
}
ann = stmt_ann (stmt);
use_ops = USE_OPS (ann);
for (i = 0; i < NUM_USES (use_ops); i++)
FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
{
tree use = USE_OP (use_ops, i);
/* We are only interested in uses that need to be vectorized. Uses
that are used for address computation are not considered relevant.

View File

@ -1499,13 +1499,12 @@ update_vuses_to_preheader (tree stmt, struct loop *loop)
{
basic_block header_bb = loop->header;
edge preheader_e = loop_preheader_edge (loop);
vuse_optype vuses = STMT_VUSE_OPS (stmt);
int nvuses = NUM_VUSES (vuses);
int i;
ssa_op_iter iter;
use_operand_p use_p;
for (i = 0; i < nvuses; i++)
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_VUSE)
{
tree ssa_name = VUSE_OP (vuses, i);
tree ssa_name = USE_FROM_PTR (use_p);
tree def_stmt = SSA_NAME_DEF_STMT (ssa_name);
tree name_var = SSA_NAME_VAR (ssa_name);
basic_block bb = bb_for_stmt (def_stmt);
@ -1524,8 +1523,7 @@ update_vuses_to_preheader (tree stmt, struct loop *loop)
{
if (SSA_NAME_VAR (PHI_RESULT (phi)) == name_var)
{
SET_VUSE_OP (vuses, i,
PHI_ARG_DEF (phi, preheader_e->dest_idx));
SET_USE (use_p, PHI_ARG_DEF (phi, preheader_e->dest_idx));
updated = true;
break;
}

View File

@ -215,12 +215,8 @@ rename_variables_in_bb (basic_block bb)
tree phi;
block_stmt_iterator bsi;
tree stmt;
stmt_ann_t ann;
use_optype uses;
vuse_optype vuses;
v_may_def_optype v_may_defs;
v_must_def_optype v_must_defs;
unsigned i;
use_operand_p use_p;
ssa_op_iter iter;
edge e;
edge_iterator ei;
struct loop *loop = bb->loop_father;
@ -228,23 +224,9 @@ rename_variables_in_bb (basic_block bb)
for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
{
stmt = bsi_stmt (bsi);
ann = stmt_ann (stmt);
uses = USE_OPS (ann);
for (i = 0; i < NUM_USES (uses); i++)
rename_use_op (USE_OP_PTR (uses, i));
vuses = VUSE_OPS (ann);
for (i = 0; i < NUM_VUSES (vuses); i++)
rename_use_op (VUSE_OP_PTR (vuses, i));
v_may_defs = V_MAY_DEF_OPS (ann);
for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
rename_use_op (V_MAY_DEF_OP_PTR (v_may_defs, i));
v_must_defs = V_MUST_DEF_OPS (ann);
for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
rename_use_op (V_MUST_DEF_KILL_PTR (v_must_defs, i));
FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter,
(SSA_OP_ALL_USES | SSA_OP_ALL_KILLS))
rename_use_op (use_p);
}
FOR_EACH_EDGE (e, ei, bb->succs)

View File

@ -48,8 +48,8 @@ typedef struct val_expr_pair_d
/* Associated expression. */
tree e;
/* Virtual uses in E. */
vuse_optype vuses;
/* for comparing Virtual uses in E. */
tree stmt;
/* E's hash value. */
hashval_t hashcode;
@ -79,13 +79,13 @@ make_value_handle (tree type)
VAL can be used to iterate by passing previous value numbers (it is
used by iterative_hash_expr).
VUSES is the set of virtual use operands associated with EXPR. It
may be NULL if EXPR has no virtual operands. */
STMT is the stmt associated with EXPR for comparing virtual operands. */
hashval_t
vn_compute (tree expr, hashval_t val, vuse_optype vuses)
vn_compute (tree expr, hashval_t val, tree stmt)
{
size_t i;
ssa_op_iter iter;
tree vuse;
/* EXPR must not be a statement. We are only interested in value
numbering expressions on the RHS of assignments. */
@ -97,8 +97,9 @@ vn_compute (tree expr, hashval_t val, vuse_optype vuses)
/* If the expression has virtual uses, incorporate them into the
hash value computed for EXPR. */
for (i = 0; i < NUM_VUSES (vuses); i++)
val = iterative_hash_expr (VUSE_OP (vuses, i), val);
if (stmt)
FOR_EACH_SSA_TREE_OPERAND (vuse, stmt, iter, SSA_OP_VUSE)
val = iterative_hash_expr (vuse, val);
return val;
}
@ -146,22 +147,15 @@ val_expr_pair_hash (const void *p)
static int
val_expr_pair_expr_eq (const void *p1, const void *p2)
{
bool ret;
const val_expr_pair_t ve1 = (val_expr_pair_t) p1;
const val_expr_pair_t ve2 = (val_expr_pair_t) p2;
size_t i;
if (! expressions_equal_p (ve1->e, ve2->e))
return false;
if (NUM_VUSES (ve1->vuses) != NUM_VUSES (ve2->vuses))
return false;
for (i = 0; i < NUM_VUSES (ve1->vuses); i++)
if (! expressions_equal_p (VUSE_OP (ve1->vuses, i),
VUSE_OP (ve2->vuses, i)))
return false;
return true;
ret = compare_ssa_operands_equal (ve1->stmt, ve2->stmt, SSA_OP_VUSE);
return ret;
}
@ -181,12 +175,11 @@ set_value_handle (tree e, tree v)
/* Insert EXPR into VALUE_TABLE with value VAL, and add expression
EXPR to the value set for value VAL. VUSES represent the virtual
use operands associated with EXPR (if any). They are used when
computing the hash value for EXPR. */
EXPR to the value set for value VAL. STMT represent the stmt
associated with EXPR. It is used when computing a hash value for EXPR. */
void
vn_add (tree expr, tree val, vuse_optype vuses)
vn_add (tree expr, tree val, tree stmt)
{
void **slot;
val_expr_pair_t new_pair;
@ -194,8 +187,8 @@ vn_add (tree expr, tree val, vuse_optype vuses)
new_pair = xmalloc (sizeof (struct val_expr_pair_d));
new_pair->e = expr;
new_pair->v = val;
new_pair->vuses = vuses;
new_pair->hashcode = vn_compute (expr, 0, vuses);
new_pair->stmt = stmt;
new_pair->hashcode = vn_compute (expr, 0, stmt);
slot = htab_find_slot_with_hash (value_table, new_pair, new_pair->hashcode,
INSERT);
if (*slot)
@ -208,12 +201,12 @@ vn_add (tree expr, tree val, vuse_optype vuses)
/* Search in VALUE_TABLE for an existing instance of expression EXPR,
and return its value, or NULL if none has been set. VUSES
represent the virtual use operands associated with EXPR (if any).
They are used when computing the hash value for EXPR. */
and return its value, or NULL if none has been set. STMT
represent the stmt associated with EXPR. It is arused when computing the
hash value for EXPR. */
tree
vn_lookup (tree expr, vuse_optype vuses)
vn_lookup (tree expr, tree stmt)
{
void **slot;
struct val_expr_pair_d vep = {NULL, NULL, NULL, 0};
@ -223,8 +216,8 @@ vn_lookup (tree expr, vuse_optype vuses)
return expr;
vep.e = expr;
vep.vuses = vuses;
vep.hashcode = vn_compute (expr, 0, vuses);
vep.stmt = stmt;
vep.hashcode = vn_compute (expr, 0, stmt);
slot = htab_find_slot_with_hash (value_table, &vep, vep.hashcode, NO_INSERT);
if (!slot)
return NULL_TREE;
@ -235,14 +228,13 @@ vn_lookup (tree expr, vuse_optype vuses)
/* Like vn_lookup, but creates a new value for expression EXPR, if
EXPR doesn't already have a value. Return the existing/created
value for EXPR. VUSES represent the virtual use operands
associated with EXPR (if any). They are used when computing the
hash value for EXPR. */
value for EXPR. STMT represent the stmt associated with EXPR. It is used
when computing the hash value for EXPR. */
tree
vn_lookup_or_add (tree expr, vuse_optype vuses)
vn_lookup_or_add (tree expr, tree stmt)
{
tree v = vn_lookup (expr, vuses);
tree v = vn_lookup (expr, stmt);
if (v == NULL_TREE)
{
v = make_value_handle (TREE_TYPE (expr));
@ -256,7 +248,7 @@ vn_lookup_or_add (tree expr, vuse_optype vuses)
fprintf (dump_file, "\n");
}
vn_add (expr, v, vuses);
vn_add (expr, v, stmt);
}
set_value_handle (expr, v);

View File

@ -1544,7 +1544,6 @@ maybe_add_assert_expr (basic_block bb)
block_stmt_iterator si;
tree last;
bool added;
use_optype uses;
/* Step 1. Mark all the SSA names used in BB in bitmap FOUND. */
added = false;
@ -1628,16 +1627,20 @@ maybe_add_assert_expr (basic_block bb)
if (last
&& TREE_CODE (last) == COND_EXPR
&& !fp_predicate (COND_EXPR_COND (last))
&& NUM_USES (uses = STMT_USE_OPS (last)) > 0)
&& !ZERO_SSA_OPERANDS (last, SSA_OP_USE))
{
edge e;
edge_iterator ei;
tree op, cond;
basic_block son;
ssa_op_iter iter;
cond = COND_EXPR_COND (last);
op = USE_OP (uses, 0);
/* Get just the first use operand. */
FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE)
break;
gcc_assert (op != NULL);
/* Do not attempt to infer anything in names that flow through
abnormal edges. */
@ -1819,14 +1822,11 @@ stmt_interesting_for_vrp (tree stmt)
else if (TREE_CODE (stmt) == MODIFY_EXPR)
{
tree lhs = TREE_OPERAND (stmt, 0);
stmt_ann_t ann = stmt_ann (stmt);
if (TREE_CODE (lhs) == SSA_NAME
&& (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
|| POINTER_TYPE_P (TREE_TYPE (lhs)))
&& NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) == 0
&& NUM_VUSES (VUSE_OPS (ann)) == 0
&& NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) == 0)
&& ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
return true;
}
else if (TREE_CODE (stmt) == COND_EXPR || TREE_CODE (stmt) == SWITCH_EXPR)
@ -2080,9 +2080,7 @@ vrp_visit_stmt (tree stmt, edge *taken_edge_p, tree *output_p)
ann = stmt_ann (stmt);
if (TREE_CODE (stmt) == MODIFY_EXPR
&& NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) == 0
&& NUM_VUSES (VUSE_OPS (ann)) == 0
&& NUM_V_MUST_DEFS (V_MUST_DEF_OPS (ann)) == 0)
&& ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
return vrp_visit_assignment (stmt, output_p);
else if (TREE_CODE (stmt) == COND_EXPR || TREE_CODE (stmt) == SWITCH_EXPR)
return vrp_visit_cond_stmt (stmt, taken_edge_p);

View File

@ -1355,13 +1355,13 @@ struct value_range_def;
/* 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(())
typedef struct ssa_use_operand_d GTY(())
{
struct ssa_imm_use_d* GTY((skip(""))) prev;
struct ssa_imm_use_d* GTY((skip(""))) next;
struct ssa_use_operand_d* GTY((skip(""))) prev;
struct ssa_use_operand_d* GTY((skip(""))) next;
tree GTY((skip(""))) stmt;
tree *GTY((skip(""))) use;
} ssa_imm_use_t;
} ssa_use_operand_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
@ -1393,7 +1393,7 @@ struct tree_ssa_name GTY(())
PTR GTY((skip)) aux;
/* Immediate uses list for this SSA_NAME. */
struct ssa_imm_use_d imm_uses;
struct ssa_use_operand_d imm_uses;
};
/* In a PHI_NODE node. */
@ -1424,7 +1424,7 @@ struct phi_arg_d GTY(())
{
/* imm_use MUST be the first element in struct because we do some
pointer arithmetic with it. See phi_arg_index_from_use. */
struct ssa_imm_use_d imm_use;
struct ssa_use_operand_d imm_use;
tree def;
bool nonzero;
};