summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoramacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-03 12:19:56 +0000
committeramacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4>2005-05-03 12:19:56 +0000
commitb66731e8c2683e73ff3e734e22cd16fe42dd367d (patch)
tree4bdcc871f23e3607a16ebf6af8f41a8854a30836
parent27d2baef250d495b3b82b289cb7ce209462d0157 (diff)
downloadgcc-b66731e8c2683e73ff3e734e22cd16fe42dd367d.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@99155 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog187
-rw-r--r--gcc/doc/tree-ssa.texi172
-rw-r--r--gcc/lambda-code.c49
-rw-r--r--gcc/tree-data-ref.c8
-rw-r--r--gcc/tree-dfa.c22
-rw-r--r--gcc/tree-flow-inline.h643
-rw-r--r--gcc/tree-flow.h20
-rw-r--r--gcc/tree-into-ssa.c4
-rw-r--r--gcc/tree-outof-ssa.c106
-rw-r--r--gcc/tree-phinodes.c8
-rw-r--r--gcc/tree-pretty-print.c3
-rw-r--r--gcc/tree-sra.c4
-rw-r--r--gcc/tree-ssa-ccp.c48
-rw-r--r--gcc/tree-ssa-copy.c28
-rw-r--r--gcc/tree-ssa-dom.c122
-rw-r--r--gcc/tree-ssa-dse.c8
-rw-r--r--gcc/tree-ssa-loop-ivopts.c58
-rw-r--r--gcc/tree-ssa-loop-niter.c40
-rw-r--r--gcc/tree-ssa-loop-unswitch.c10
-rw-r--r--gcc/tree-ssa-operands.c1451
-rw-r--r--gcc/tree-ssa-operands.h313
-rw-r--r--gcc/tree-ssa-opfinalize.h175
-rw-r--r--gcc/tree-ssa-pre.c39
-rw-r--r--gcc/tree-ssa-propagate.c20
-rw-r--r--gcc/tree-ssa-sink.c30
-rw-r--r--gcc/tree-ssa.c26
-rw-r--r--gcc/tree-ssanames.c4
-rw-r--r--gcc/tree-tailcall.c21
-rw-r--r--gcc/tree-vect-analyze.c69
-rw-r--r--gcc/tree-vect-transform.c12
-rw-r--r--gcc/tree-vectorizer.c28
-rw-r--r--gcc/tree-vn.c64
-rw-r--r--gcc/tree-vrp.c18
-rw-r--r--gcc/tree.h12
34 files changed, 2018 insertions, 1804 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f6ab7945c68..7aecc48dc7f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/doc/tree-ssa.texi b/gcc/doc/tree-ssa.texi
index 8528406dc25..88dcacf912d 100644
--- a/gcc/doc/tree-ssa.texi
+++ b/gcc/doc/tree-ssa.texi
@@ -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,98 +810,58 @@ 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
+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
+(ie, those macros take care of updating the statement). If changes
+are made by manipulating the statement's tree directly, then a call
+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}.
-@defmac NUM_USES (@var{ops})
-Return the number of USE operands in array @var{ops}.
-@end defmac
+@subsection Operand Iterators And Access Routines
+@cindex Operand Iterators
+@cindex Operand Access Routines
-@defmac USE_OP_PTR (@var{ops}, @var{i})
-Return a pointer to the @var{i}th operand in array @var{ops}.
-@end defmac
+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.
-@defmac USE_OP (@var{ops}, @var{i})
-Return the @var{i}th operand in array @var{ops}.
-@end defmac
+The following access routines are available for examining operands:
-The following function shows how to print all the operands of a given
-statement:
+@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
-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);
- @}
+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
- 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);
+@item @code{ZERO_SSA_OPERANDS}: This macro returns true if there are no
+operands matching the specified flags.
- vuses = VUSE_OPS (ann);
- for (i = 0; i < NUM_VUSES (vuses); i++)
- print_generic_expr (stderr, VUSE_OP (vuses, i), 0);
-@}
+@smallexample
+if (ZERO_SSA_OPERANDS (stmt, SSA_OP_ALL_VIRTUALS))
+ return;
@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
-(ie, those macros take care of updating the statement). If changes
-are made by manipulating the statement's tree directly, then a call
-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}.
+@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
-@subsection Operand Iterators
-@cindex Operand Iterators
-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:
+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
diff --git a/gcc/lambda-code.c b/gcc/lambda-code.c
index a81af8f8314..940f7470afe 100644
--- a/gcc/lambda-code.c
+++ b/gcc/lambda-code.c
@@ -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;
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index b984c04d07a..8ef5c51a660 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -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;
}
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index c923cdad7fc..fa8ee86083f 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -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))
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
index 5da85e049e1..3fa6259aa8e 100644
--- a/gcc/tree-flow-inline.h
+++ b/gcc/tree-flow-inline.h
@@ -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,85 +1026,53 @@ 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
- {
- *def = NULL_DEF_OPERAND_P;
- *kill = 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)
+ if (ptr->mustkills)
{
- *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)++);
+ *def = MUSTDEF_RESULT_PTR (ptr->mustkills);
+ *use = MUSTDEF_KILL_PTR (ptr->mustkills);
+ ptr->mustkills = ptr->mustkills->next;
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;
- }
+ *def = NULL_DEF_OPERAND_P;
+ *use = NULL_USE_OPERAND_P;
ptr->done = true;
return;
}
+
/* Initialize iterator PTR to the operands in STMT. Return the first operands
in USE and DEF. */
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
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index 9fb4ff2d075..3d946a696f9 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -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);
diff --git a/gcc/tree-into-ssa.c b/gcc/tree-into-ssa.c
index f903eabf89d..962e1c1a7f1 100644
--- a/gcc/tree-into-ssa.c
+++ b/gcc/tree-into-ssa.c
@@ -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));
diff --git a/gcc/tree-outof-ssa.c b/gcc/tree-outof-ssa.c
index 7d23db21d66..bff48d621b9 100644
--- a/gcc/tree-outof-ssa.c
+++ b/gcc/tree-outof-ssa.c
@@ -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)
- return false;
- def = DEF_OP (defs, 0);
- if (version_ref_count (map, def) != 1)
+ def = SINGLE_SSA_TREE_OPERAND (stmt, SSA_OP_DEF);
+ if (!def)
return false;
- /* There must be no V_MAY_DEFS. */
- if (NUM_V_MAY_DEFS (V_MAY_DEF_OPS (ann)) != 0)
+ if (version_ref_count (map, def) != 1)
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)
- {
- tree def = DEF_OP (defs, 0);
- tree val;
- val = values[SSA_NAME_VERSION (def)];
- if (val)
- remove = 1;
- }
- if (!remove)
+ def_p = SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF);
+
+ if (def_p != NULL)
{
- 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)
diff --git a/gcc/tree-phinodes.c b/gcc/tree-phinodes.c
index 0c6693b85c2..ca01c8c52d1 100644
--- a/gcc/tree-phinodes.c
+++ b/gcc/tree-phinodes.c
@@ -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;
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 5d230822a92..52bf437ff98 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -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, "# ");
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 1ca629fe5d0..78cd03b7bf5 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -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))
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 3ae0b1aca8b..14b5a3d9464 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -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,18 +2199,19 @@ convert_to_gimple_builtin (block_stmt_iterator *si_p, tree expr)
tmp = get_initialized_tmp_var (expr, &stmts, NULL);
pop_gimplify_context (NULL);
+ if (EXPR_HAS_LOCATION (stmt))
+ annotate_all_with_locus (&stmts, EXPR_LOCATION (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));
- mark_new_vars_to_rename (tsi_stmt (ti));
+ bsi_insert_before (si_p, new_stmt, BSI_NEW_STMT);
+ mark_new_vars_to_rename (bsi_stmt (*si_p));
+ bsi_next (si_p);
}
- if (EXPR_HAS_LOCATION (stmt))
- annotate_all_with_locus (&stmts, EXPR_LOCATION (stmt));
-
- bsi_insert_before (si_p, stmts, BSI_SAME_STMT);
-
return tmp;
}
diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c
index 1b646384cb5..dd4c5debc5c 100644
--- a/gcc/tree-ssa-copy.c
+++ b/gcc/tree-ssa-copy.c
@@ -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);
}
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index d9edd0813ce..fa8e7d6f422 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -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++)
- {
- tree tmp = NULL;
+ num = NUM_SSA_OPERANDS (stmt, (SSA_OP_USE | SSA_OP_VUSE));
+ copy = xcalloc (num, sizeof (tree));
- uses_copy[i] = USE_OP (uses, i);
- if (TREE_CODE (USE_OP (uses, i)) == SSA_NAME)
- tmp = SSA_NAME_VALUE (USE_OP (uses, i));
- 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++)
+ /* 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);
- vuses_copy[i] = VUSE_OP (vuses, i);
- if (TREE_CODE (VUSE_OP (vuses, i)) == SSA_NAME)
- tmp = SSA_NAME_VALUE (VUSE_OP (vuses, i));
+ copy[i++] = use;
+ if (TREE_CODE (use) == SSA_NAME)
+ tmp = SSA_NAME_VALUE (use);
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]);
- for (i = 0; i < NUM_VUSES (vuses); i++)
- SET_VUSE_OP (vuses, i, vuses_copy[i]);
+ /* Restore the statement's original uses/defs. */
+ i = 0;
+ FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE | SSA_OP_VUSE)
+ SET_USE (use_p, 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;
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index 42b61553832..23b9d4ac9c2 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -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
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index eb53945f2d1..5e3f3619d14 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -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
- {
- uses = STMT_USE_OPS (stmt);
- n = NUM_USES (uses);
- }
-
- for (i = 0; i < n; i++)
+ FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
{
- 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
- {
- uses = STMT_USE_OPS (stmt);
- n = NUM_USES (uses);
- }
-
- for (i = 0; i < n; i++)
+ FOR_EACH_PHI_OR_STMT_USE (use_p, stmt, iter, SSA_OP_USE)
{
- 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;
-
- 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));
+ ssa_op_iter iter;
+ use_operand_p use_p;
- 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
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 5d014871318..b3bde288a48 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -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)
+ if (SINGLE_SSA_DEF_OPERAND (stmt, SSA_OP_DEF) == NULL_DEF_OPERAND_P)
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)
+
+ 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_OP (uses, 0));
+ 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);
-
- 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);
+ 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;
+ }
- return val;
+ /* Should never reach here. */
+ gcc_unreachable();
}
/* Tries to count the number of iterations of LOOP till it exits by EXIT
diff --git a/gcc/tree-ssa-loop-unswitch.c b/gcc/tree-ssa-loop-unswitch.c
index e00fe189514..cb235f0a4e5 100644
--- a/gcc/tree-ssa-loop-unswitch.c
+++ b/gcc/tree-ssa-loop-unswitch.c
@@ -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))
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 7364052e10f..d46bf847838 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -99,20 +99,34 @@ Boston, MA 02111-1307, USA. */
VUSE for 'b'. */
#define opf_no_vops (1 << 2)
+/* This structure maintain a sorted list of operands which is created by
+ parse_ssa_operand. */
+struct opbuild_list_d GTY (())
+{
+ varray_type vars; /* The VAR_DECLS tree. */
+ varray_type uid; /* The sort value for virtaul symbols. */
+ varray_type next; /* The next index in the sorted list. */
+ int first; /* First element in list. */
+ unsigned num; /* Number of elements. */
+};
+
+#define OPBUILD_LAST -1
+
+
/* Array for building all the def operands. */
-static GTY (()) varray_type build_defs;
+static GTY (()) struct opbuild_list_d build_defs;
/* Array for building all the use operands. */
-static GTY (()) varray_type build_uses;
+static GTY (()) struct opbuild_list_d build_uses;
/* Array for building all the v_may_def operands. */
-static GTY (()) varray_type build_v_may_defs;
+static GTY (()) struct opbuild_list_d build_v_may_defs;
/* Array for building all the vuse operands. */
-static GTY (()) varray_type build_vuses;
+static GTY (()) struct opbuild_list_d build_vuses;
/* Array for building all the v_must_def operands. */
-static GTY (()) varray_type build_v_must_defs;
+static GTY (()) struct opbuild_list_d build_v_must_defs;
/* True if the operands for call clobbered vars are cached and valid. */
bool ssa_call_clobbered_cache_valid;
@@ -125,9 +139,10 @@ static GTY (()) varray_type ro_call_vuses;
static bool clobbered_aliased_loads;
static bool clobbered_aliased_stores;
static bool ro_call_aliased_loads;
-static stmt_operands_p parse_old_ops = NULL;
+static bool ops_active = false;
-def_operand_p NULL_DEF_OPERAND_P = { NULL };
+static GTY (()) struct ssa_operand_memory_d *operand_memory = NULL;
+static unsigned operand_memory_index;
static void note_addressable (tree, stmt_ann_t);
static void get_expr_operands (tree, tree *, int);
@@ -141,311 +156,311 @@ static void append_v_must_def (tree);
static void add_call_clobber_ops (tree);
static void add_call_read_ops (tree);
static void add_stmt_operand (tree *, stmt_ann_t, int);
+static void build_ssa_operands (tree stmt);
+
+static def_optype_p free_defs = NULL;
+static use_optype_p free_uses = NULL;
+static vuse_optype_p free_vuses = NULL;
+static maydef_optype_p free_maydefs = NULL;
+static mustdef_optype_p free_mustdefs = NULL;
-/* Return a vector of contiguous memory for NUM def operands. */
+/* Initialize a virtual operand build LIST called NAME with NUM elements. */
-static inline def_optype
-allocate_def_optype (unsigned num)
+static inline void
+opbuild_initialize_virtual (struct opbuild_list_d *list, int num,
+ const char *name)
{
- def_optype def_ops;
- unsigned size;
- size = sizeof (struct def_optype_d) + sizeof (tree *) * (num - 1);
- def_ops = ggc_alloc (size);
- def_ops->num_defs = num;
- return def_ops;
+ list->first = OPBUILD_LAST;
+ list->num = 0;
+ VARRAY_TREE_INIT (list->vars, num, name);
+ VARRAY_UINT_INIT (list->uid, num, "List UID");
+ VARRAY_INT_INIT (list->next, num, "List NEXT");
}
-/* Return a vector of contiguous memory for NUM use operands. */
+/* Initialize a real operand build LIST called NAME with NUM elements. */
-static inline use_optype
-allocate_use_optype (unsigned num)
+static inline void
+opbuild_initialize_real (struct opbuild_list_d *list, int num, const char *name)
{
- use_optype use_ops;
- unsigned size;
- size = sizeof (struct use_optype_d) + sizeof (use_operand_type_t) * (num - 1);
- use_ops = ggc_alloc (size);
- use_ops->num_uses = num;
- return use_ops;
+ list->first = OPBUILD_LAST;
+ list->num = 0;
+ VARRAY_TREE_PTR_INIT (list->vars, num, name);
+ VARRAY_INT_INIT (list->next, num, "List NEXT");
+ /* The UID field is not needed since we sort based on the pointer value. */
+ list->uid = NULL;
}
-/* Return a vector of contiguous memory for NUM v_may_def operands. */
+/* Free memory used in virtual operand build object LIST. */
-static inline v_may_def_optype
-allocate_v_may_def_optype (unsigned num)
+static inline void
+opbuild_free (struct opbuild_list_d *list)
{
- v_may_def_optype v_may_def_ops;
- unsigned size;
- size = sizeof (struct v_may_def_optype_d)
- + sizeof (v_def_use_operand_type_t) * (num - 1);
- v_may_def_ops = ggc_alloc (size);
- v_may_def_ops->num_v_may_defs = num;
- return v_may_def_ops;
+ list->vars = NULL;
+ list->uid = NULL;
+ list->next = NULL;
}
-/* Return a vector of contiguous memory for NUM v_use operands. */
+/* Number of elements in an opbuild list. */
-static inline vuse_optype
-allocate_vuse_optype (unsigned num)
+static inline unsigned
+opbuild_num_elems (struct opbuild_list_d *list)
{
- vuse_optype vuse_ops;
- unsigned size;
- size = sizeof (struct vuse_optype_d)
- + sizeof (vuse_operand_type_t) * (num - 1);
- vuse_ops = ggc_alloc (size);
- vuse_ops->num_vuses = num;
- return vuse_ops;
+ return list->num;
}
-/* Return a vector of contiguous memory for NUM v_must_def operands. */
+/* Add VAR to the real operand list LIST, keeping it sorted and avoiding
+ duplicates. The actual sort value is the tree pointer value. */
-static inline v_must_def_optype
-allocate_v_must_def_optype (unsigned num)
+static inline void
+opbuild_append_real (struct opbuild_list_d *list, tree *var)
{
- v_must_def_optype v_must_def_ops;
- unsigned size;
- size = sizeof (struct v_must_def_optype_d) + sizeof (v_def_use_operand_type_t) * (num - 1);
- v_must_def_ops = ggc_alloc (size);
- v_must_def_ops->num_v_must_defs = num;
- return v_must_def_ops;
+ int index;
+
+#ifdef ENABLE_CHECKING
+ /* Ensure the real operand doesn't exist already. */
+ for (index = list->first;
+ index != OPBUILD_LAST;
+ index = VARRAY_INT (list->next, index))
+ gcc_assert (VARRAY_TREE_PTR (list->vars, index) != var);
+#endif
+
+ /* First item in the list. */
+ index = VARRAY_ACTIVE_SIZE (list->vars);
+ if (index == 0)
+ list->first = index;
+ else
+ VARRAY_INT (list->next, index - 1) = index;
+ VARRAY_PUSH_INT (list->next, OPBUILD_LAST);
+ VARRAY_PUSH_TREE_PTR (list->vars, var);
+ list->num++;
}
-/* Free memory for USES. */
+/* Add VAR to the virtual operand list LIST, keeping it sorted and avoiding
+ duplicates. The actual sort value is the DECL UID of the base variable. */
static inline void
-free_uses (use_optype *uses)
+opbuild_append_virtual (struct opbuild_list_d *list, tree var)
{
- if (*uses)
- {
- unsigned int x;
- use_optype use = *uses;
- for (x = 0; x < use->num_uses; x++)
- delink_imm_use (&(use->uses[x]));
- ggc_free (*uses);
- *uses = NULL;
- }
-}
+ int index, curr, last;
+ unsigned int var_uid;
+ if (TREE_CODE (var) != SSA_NAME)
+ var_uid = DECL_UID (var);
+ else
+ var_uid = DECL_UID (SSA_NAME_VAR (var));
-/* Free memory for DEFS. */
+ index = VARRAY_ACTIVE_SIZE (list->vars);
-static inline void
-free_defs (def_optype *defs)
-{
- if (*defs)
+ if (index == 0)
{
- ggc_free (*defs);
- *defs = NULL;
+ VARRAY_PUSH_TREE (list->vars, var);
+ VARRAY_PUSH_UINT (list->uid, var_uid);
+ VARRAY_PUSH_INT (list->next, OPBUILD_LAST);
+ list->first = 0;
+ list->num = 1;
+ return;
}
-}
-
-/* Free memory for VUSES. */
+ last = OPBUILD_LAST;
+ /* Find the correct spot in the sorted list. */
+ for (curr = list->first;
+ curr != OPBUILD_LAST;
+ last = curr, curr = VARRAY_INT (list->next, curr))
+ {
+ if (VARRAY_UINT (list->uid, curr) > var_uid)
+ break;
+ }
-static inline void
-free_vuses (vuse_optype *vuses)
-{
- if (*vuses)
+ if (last == OPBUILD_LAST)
{
- unsigned int x;
- vuse_optype vuse = *vuses;
- for (x = 0; x < vuse->num_vuses; x++)
- delink_imm_use (&(vuse->vuses[x].imm_use));
- ggc_free (*vuses);
- *vuses = NULL;
+ /* First item in the list. */
+ VARRAY_PUSH_INT (list->next, list->first);
+ list->first = index;
}
+ else
+ {
+ /* Dont enter duplicates at all. */
+ if (VARRAY_UINT (list->uid, last) == var_uid)
+ return;
+
+ VARRAY_PUSH_INT (list->next, VARRAY_INT (list->next, last));
+ VARRAY_INT (list->next, last) = index;
+ }
+ VARRAY_PUSH_TREE (list->vars, var);
+ VARRAY_PUSH_UINT (list->uid, var_uid);
+ list->num++;
}
-/* Free memory for V_MAY_DEFS. */
+/* Return the first element index in LIST. OPBUILD_LAST means there are no
+ more elements. */
-static inline void
-free_v_may_defs (v_may_def_optype *v_may_defs)
+static inline int
+opbuild_first (struct opbuild_list_d *list)
{
- if (*v_may_defs)
- {
- unsigned int x;
- v_may_def_optype v_may_def = *v_may_defs;
- for (x = 0; x < v_may_def->num_v_may_defs; x++)
- delink_imm_use (&(v_may_def->v_may_defs[x].imm_use));
- ggc_free (*v_may_defs);
- *v_may_defs = NULL;
- }
+ if (list->num > 0)
+ return list->first;
+ else
+ return OPBUILD_LAST;
}
-/* Free memory for V_MUST_DEFS. */
+/* Return the next element after PREV in LIST. */
-static inline void
-free_v_must_defs (v_must_def_optype *v_must_defs)
+static inline int
+opbuild_next (struct opbuild_list_d *list, int prev)
{
- if (*v_must_defs)
- {
- unsigned int x;
- v_must_def_optype v_must_def = *v_must_defs;
- for (x = 0; x < v_must_def->num_v_must_defs; x++)
- delink_imm_use (&(v_must_def->v_must_defs[x].imm_use));
- ggc_free (*v_must_defs);
- *v_must_defs = NULL;
- }
+ return VARRAY_INT (list->next, prev);
}
-/* Initialize the operand cache routines. */
+/* Return the real element at index ELEM in LIST. */
-void
-init_ssa_operands (void)
+static inline tree *
+opbuild_elem_real (struct opbuild_list_d *list, int elem)
{
- VARRAY_TREE_PTR_INIT (build_defs, 5, "build defs");
- VARRAY_TREE_PTR_INIT (build_uses, 10, "build uses");
- VARRAY_TREE_INIT (build_v_may_defs, 10, "build v_may_defs");
- VARRAY_TREE_INIT (build_vuses, 10, "build vuses");
- VARRAY_TREE_INIT (build_v_must_defs, 10, "build v_must_defs");
+ return VARRAY_TREE_PTR (list->vars, elem);
}
-/* Dispose of anything required by the operand routines. */
+/* Return the virtual element at index ELEM in LIST. */
-void
-fini_ssa_operands (void)
+static inline tree
+opbuild_elem_virtual (struct opbuild_list_d *list, int elem)
{
- ggc_free (build_defs);
- ggc_free (build_uses);
- ggc_free (build_v_may_defs);
- ggc_free (build_vuses);
- ggc_free (build_v_must_defs);
- build_defs = NULL;
- build_uses = NULL;
- build_v_may_defs = NULL;
- build_vuses = NULL;
- build_v_must_defs = NULL;
- if (clobbered_v_may_defs)
- {
- ggc_free (clobbered_v_may_defs);
- ggc_free (clobbered_vuses);
- clobbered_v_may_defs = NULL;
- clobbered_vuses = NULL;
- }
- if (ro_call_vuses)
- {
- ggc_free (ro_call_vuses);
- ro_call_vuses = NULL;
- }
+ return VARRAY_TREE (list->vars, elem);
}
-/* Initialize V_USES index INDEX to VAL for STMT. If OLD is present, preserve
- the position of the may-def in the immediate_use list. */
-static inline void
-initialize_vuse_operand (vuse_optype vuses, unsigned int index, tree val,
- tree stmt, ssa_imm_use_t *old)
+/* Return the virtual element uid at index ELEM in LIST. */
+static inline unsigned int
+opbuild_elem_uid (struct opbuild_list_d *list, int elem)
{
- vuse_operand_type_t *ptr;
- ptr = &(vuses->vuses[index]);
- ptr->use = val;
- ptr->imm_use.use = &(ptr->use);
- if (old)
- relink_imm_use_stmt (&(ptr->imm_use), old, stmt);
- else
- link_imm_use_stmt (&(ptr->imm_use), ptr->use, stmt);
+ return VARRAY_UINT (list->uid, elem);
}
-/* Initialize V_MAY_DEF_OPS index X to be DEF = MAY_DEF <USE> for STMT. If
- OLD is present, preserve the position of the may-def in the immediate_use
- list. */
+/* Reset an operand build list. */
static inline void
-initialize_v_may_def_operand (v_may_def_optype v_may_def_ops, unsigned int x,
- tree def, tree use, tree stmt, ssa_imm_use_t *old)
+opbuild_clear (struct opbuild_list_d *list)
{
- v_def_use_operand_type_t *ptr;
- ptr = &(v_may_def_ops->v_may_defs[x]);
- ptr->def = def;
- ptr->use = use;
- ptr->imm_use.use = &(ptr->use);
- if (old)
- relink_imm_use_stmt (&(ptr->imm_use), old, stmt);
- else
- link_imm_use_stmt (&(ptr->imm_use), ptr->use, stmt);
+ list->first = OPBUILD_LAST;
+ VARRAY_POP_ALL (list->vars);
+ VARRAY_POP_ALL (list->next);
+ if (list->uid)
+ VARRAY_POP_ALL (list->uid);
+ list->num = 0;
}
-/* Initialize V_MUST_DEF_OPS index X to be DEF = MUST_DEF <USE> for STMT. If
- OLD is present, preserve the position of the may-def in the immediate_use
- list. */
+/* Remove ELEM from LIST where PREV is the rpevious element. Return the next
+ element. */
-static inline void
-initialize_v_must_def_operand (v_must_def_optype v_must_def_ops, unsigned int x,
- tree def, tree use, tree stmt, ssa_imm_use_t *old)
+static inline int
+opbuild_remove_elem (struct opbuild_list_d *list, int elem, int prev)
{
- v_def_use_operand_type_t *ptr;
- ptr = &(v_must_def_ops->v_must_defs[x]);
- ptr->def = def;
- ptr->use = use;
- ptr->imm_use.use = &(ptr->use);
- if (old)
- relink_imm_use_stmt (&(ptr->imm_use), old, stmt);
+ int ret;
+ if (prev != OPBUILD_LAST)
+ {
+ gcc_assert (VARRAY_INT (list->next, prev) == elem);
+ ret = VARRAY_INT (list->next, prev) = VARRAY_INT (list->next, elem);
+ }
else
- link_imm_use_stmt (&(ptr->imm_use), ptr->use, stmt);
+ {
+ gcc_assert (list->first == elem);
+ ret = list->first = VARRAY_INT (list->next, elem);
+ }
+ list->num--;
+ return ret;
}
-/* All the finalize_ssa_* routines do the work required to turn the build_
- VARRAY into an operand_vector of the appropriate type. The original vector,
- if any, is passed in for comparison and virtual SSA_NAME reuse. If the
- old vector is reused, the pointer passed in is set to NULL so that
- the memory is not freed when the old operands are freed. */
-/* Return a new def operand vector for STMT, comparing to OLD_OPS_P. */
+/* Return true if the ssa operands cache is active. */
-static def_optype
-finalize_ssa_defs (def_optype *old_ops_p, tree stmt)
+bool
+ssa_operands_active (void)
{
- unsigned num, x;
- def_optype def_ops, old_ops;
- bool build_diff;
+ return ops_active;
+}
- num = VARRAY_ACTIVE_SIZE (build_defs);
- if (num == 0)
- return NULL;
- /* There should only be a single real definition per assignment. */
- gcc_assert ((stmt && TREE_CODE (stmt) != MODIFY_EXPR) || num <= 1);
+/* Initialize the operand cache routines. */
+
+void
+init_ssa_operands (void)
+{
+ opbuild_initialize_real (&build_defs, 5, "build defs");
+ opbuild_initialize_real (&build_uses, 10, "build uses");
+ opbuild_initialize_virtual (&build_vuses, 25, "build_vuses");
+ opbuild_initialize_virtual (&build_v_may_defs, 25, "build_v_may_defs");
+ opbuild_initialize_virtual (&build_v_must_defs, 25, "build_v_must_defs");
+ gcc_assert (operand_memory == NULL);
+ operand_memory_index = SSA_OPERAND_MEMORY_SIZE;
+ ops_active = true;
+}
- old_ops = *old_ops_p;
- /* Compare old vector and new array. */
- build_diff = true;
- if (stmt && old_ops && old_ops->num_defs == num)
- {
- build_diff = false;
- for (x = 0; x < num; x++)
- if (old_ops->defs[x].def != VARRAY_TREE_PTR (build_defs, x))
- {
- build_diff = true;
- break;
- }
+/* Dispose of anything required by the operand routines. */
+
+void
+fini_ssa_operands (void)
+{
+ struct ssa_operand_memory_d *ptr;
+ opbuild_free (&build_defs);
+ opbuild_free (&build_uses);
+ opbuild_free (&build_v_must_defs);
+ opbuild_free (&build_v_may_defs);
+ opbuild_free (&build_vuses);
+ free_defs = NULL;
+ free_uses = NULL;
+ free_vuses = NULL;
+ free_maydefs = NULL;
+ free_mustdefs = NULL;
+ while ((ptr = operand_memory) != NULL)
+ {
+ operand_memory = operand_memory->next;
+ ggc_free (ptr);
}
- if (!build_diff)
+ if (clobbered_v_may_defs)
{
- def_ops = old_ops;
- *old_ops_p = NULL;
+ ggc_free (clobbered_v_may_defs);
+ ggc_free (clobbered_vuses);
+ clobbered_v_may_defs = NULL;
+ clobbered_vuses = NULL;
}
- else
+ if (ro_call_vuses)
{
- def_ops = allocate_def_optype (num);
- for (x = 0; x < num ; x++)
- def_ops->defs[x].def = VARRAY_TREE_PTR (build_defs, x);
+ ggc_free (ro_call_vuses);
+ ro_call_vuses = NULL;
}
+ ops_active = false;
+}
- VARRAY_POP_ALL (build_defs);
- return def_ops;
+/* Return memory for operands of SIZE chunks. */
+
+static inline void *
+ssa_operand_alloc (unsigned size)
+{
+ char *ptr;
+ if (operand_memory_index + size >= SSA_OPERAND_MEMORY_SIZE)
+ {
+ struct ssa_operand_memory_d *ptr;
+ ptr = ggc_alloc (sizeof (struct ssa_operand_memory_d));
+ ptr->next = operand_memory;
+ operand_memory = ptr;
+ operand_memory_index = 0;
+ }
+ ptr = &(operand_memory->mem[operand_memory_index]);
+ operand_memory_index += size;
+ return ptr;
}
@@ -458,9 +473,9 @@ finalize_ssa_defs (def_optype *old_ops_p, tree stmt)
because all nodes in the same stmt might have be changed. */
static inline void
-correct_use_link (ssa_imm_use_t *ptr, tree stmt)
+correct_use_link (use_operand_p ptr, tree stmt)
{
- ssa_imm_use_t *prev;
+ use_operand_p prev;
tree root;
/* Fold_stmt () may have changed the stmt pointers. */
@@ -501,162 +516,110 @@ correct_use_link (ssa_imm_use_t *ptr, tree stmt)
}
-/* Return a new use operand vector for STMT, comparing to OLD_OPS_P. */
+#define FINALIZE_OPBUILD build_defs
+#define FINALIZE_OPBUILD_BASE(I) opbuild_elem_real (&build_defs, (I))
+#define FINALIZE_OPBUILD_ELEM(I) opbuild_elem_real (&build_defs, (I))
+#define FINALIZE_FUNC finalize_ssa_def_ops
+#define FINALIZE_ALLOC alloc_def
+#define FINALIZE_FREE free_defs
+#define FINALIZE_TYPE struct def_optype_d
+#define FINALIZE_ELEM(PTR) ((PTR)->def_ptr)
+#define FINALIZE_OPS DEF_OPS
+#define FINALIZE_BASE(VAR) VAR
+#define FINALIZE_BASE_TYPE tree *
+#define FINALIZE_BASE_ZERO NULL
+#define FINALIZE_INITIALIZE(PTR, VAL, STMT) FINALIZE_ELEM (PTR) = (VAL)
+#include "tree-ssa-opfinalize.h"
-static use_optype
-finalize_ssa_uses (use_optype *old_ops_p, tree stmt)
+
+/* This routine will create stmt operands for STMT from the def build list. */
+
+static void
+finalize_ssa_defs (tree stmt)
{
- unsigned num, x, num_old, i;
- use_optype use_ops, old_ops;
- bool build_diff;
+ unsigned int num = opbuild_num_elems (&build_defs);
+ /* There should only be a single real definition per assignment. */
+ gcc_assert ((stmt && TREE_CODE (stmt) != MODIFY_EXPR) || num <= 1);
- num = VARRAY_ACTIVE_SIZE (build_uses);
- if (num == 0)
- return NULL;
+ /* If there is an old list, often the new list is identical, or close, so
+ find the elements at the beginning that are the same as the vector. */
+
+ finalize_ssa_def_ops (stmt);
+ opbuild_clear (&build_defs);
+}
+#define FINALIZE_OPBUILD build_uses
+#define FINALIZE_OPBUILD_BASE(I) opbuild_elem_real (&build_uses, (I))
+#define FINALIZE_OPBUILD_ELEM(I) opbuild_elem_real (&build_uses, (I))
+#define FINALIZE_FUNC finalize_ssa_use_ops
+#define FINALIZE_ALLOC alloc_use
+#define FINALIZE_FREE free_uses
+#define FINALIZE_TYPE struct use_optype_d
+#define FINALIZE_ELEM(PTR) ((PTR)->use_ptr.use)
+#define FINALIZE_OPS USE_OPS
+#define FINALIZE_USE_PTR(PTR) USE_OP_PTR (PTR)
+#define FINALIZE_BASE(VAR) VAR
+#define FINALIZE_BASE_TYPE tree *
+#define FINALIZE_BASE_ZERO NULL
+#define FINALIZE_INITIALIZE(PTR, VAL, STMT) \
+ (PTR)->use_ptr.use = (VAL); \
+ link_imm_use_stmt (&((PTR)->use_ptr), \
+ *(VAL), (STMT))
+#include "tree-ssa-opfinalize.h"
+
+/* Return a new use operand vector for STMT, comparing to OLD_OPS_P. */
+
+static void
+finalize_ssa_uses (tree stmt)
+{
#ifdef ENABLE_CHECKING
{
unsigned x;
+ unsigned num = opbuild_num_elems (&build_uses);
+
/* If the pointer to the operand is the statement itself, something is
- wrong. It means that we are pointing to a local variable. */
+ wrong. It means that we are pointing to a local variable (the
+ initial call to get_stmt_operands does not pass a pointer to a
+ statement). */
for (x = 0; x < num; x++)
- gcc_assert (*(VARRAY_TREE_PTR (build_uses, x)) != stmt);
+ gcc_assert (*(opbuild_elem_real (&build_uses, x)) != stmt);
}
#endif
- old_ops = *old_ops_p;
- num_old = ((stmt && old_ops) ? old_ops->num_uses : 0);
-
- /* Check if the old vector and the new array are the same. */
- build_diff = true;
- if (stmt && old_ops && num_old == num)
- {
- build_diff = false;
- for (x = 0; x < num; x++)
- {
- tree *var_p = VARRAY_TREE_PTR (build_uses, x);
- tree *node = old_ops->uses[x].use;
- /* Check the pointer values to see if they are the same. */
- if (node != var_p)
- {
- build_diff = true;
- break;
- }
- }
- }
-
- if (!build_diff)
- {
- use_ops = old_ops;
- *old_ops_p = NULL;
- for (i = 0; i < num_old; i++)
- correct_use_link (&(use_ops->uses[i]), stmt);
- }
- else
- {
- use_ops = allocate_use_optype (num);
- for (x = 0; x < num ; x++)
- {
- tree *var = VARRAY_TREE_PTR (build_uses, x);
- use_ops->uses[x].use = var;
- for (i = 0; i < num_old; i++)
- {
- ssa_imm_use_t *ptr = &(old_ops->uses[i]);
- if (ptr->use == var)
- {
- relink_imm_use_stmt (&(use_ops->uses[x]), ptr, stmt);
- correct_use_link (&(use_ops->uses[x]), stmt);
- break;
- }
- }
- if (i == num_old)
- link_imm_use_stmt (&(use_ops->uses[x]), *var, stmt);
- }
- }
- VARRAY_POP_ALL (build_uses);
-
- return use_ops;
+ finalize_ssa_use_ops (stmt);
+ opbuild_clear (&build_uses);
}
-
-
-/* Return a new v_may_def operand vector for STMT, comparing to OLD_OPS_P. */
-
-static v_may_def_optype
-finalize_ssa_v_may_defs (v_may_def_optype *old_ops_p, tree stmt)
+
+
+/* Return a new v_may_def operand vector for STMT, comparing to OLD_OPS_P. */
+#define FINALIZE_OPBUILD build_v_may_defs
+#define FINALIZE_OPBUILD_ELEM(I) opbuild_elem_virtual (&build_v_may_defs, (I))
+#define FINALIZE_OPBUILD_BASE(I) opbuild_elem_uid (&build_v_may_defs, (I))
+#define FINALIZE_FUNC finalize_ssa_v_may_def_ops
+#define FINALIZE_ALLOC alloc_maydef
+#define FINALIZE_FREE free_maydefs
+#define FINALIZE_TYPE struct maydef_optype_d
+#define FINALIZE_ELEM(PTR) MAYDEF_RESULT (PTR)
+#define FINALIZE_OPS MAYDEF_OPS
+#define FINALIZE_USE_PTR(PTR) MAYDEF_OP_PTR (PTR)
+#define FINALIZE_BASE_ZERO 0
+#define FINALIZE_BASE(VAR) ((TREE_CODE (VAR) == SSA_NAME) \
+ ? DECL_UID (SSA_NAME_VAR (VAR)) : DECL_UID ((VAR)))
+#define FINALIZE_BASE_TYPE unsigned
+#define FINALIZE_INITIALIZE(PTR, VAL, STMT) \
+ (PTR)->def_var = (VAL); \
+ (PTR)->use_var = (VAL); \
+ (PTR)->use_ptr.use = &((PTR)->use_var); \
+ link_imm_use_stmt (&((PTR)->use_ptr), \
+ (VAL), (STMT))
+#include "tree-ssa-opfinalize.h"
+
+
+static void
+finalize_ssa_v_may_defs (tree stmt)
{
- unsigned num, x, i, old_num;
- v_may_def_optype v_may_def_ops, old_ops;
- tree result, var;
- bool build_diff;
-
- num = VARRAY_ACTIVE_SIZE (build_v_may_defs);
- if (num == 0)
- return NULL;
-
- old_ops = *old_ops_p;
-
- /* Check if the old vector and the new array are the same. */
- build_diff = true;
- if (stmt && old_ops && old_ops->num_v_may_defs == num)
- {
- old_num = num;
- build_diff = false;
- for (x = 0; x < num; x++)
- {
- var = old_ops->v_may_defs[x].def;
- if (TREE_CODE (var) == SSA_NAME)
- var = SSA_NAME_VAR (var);
- if (var != VARRAY_TREE (build_v_may_defs, x))
- {
- build_diff = true;
- break;
- }
- }
- }
- else
- old_num = (old_ops ? old_ops->num_v_may_defs : 0);
-
- if (!build_diff)
- {
- v_may_def_ops = old_ops;
- *old_ops_p = NULL;
- for (x = 0; x < num; x++)
- correct_use_link (&(v_may_def_ops->v_may_defs[x].imm_use), stmt);
- }
- else
- {
- v_may_def_ops = allocate_v_may_def_optype (num);
- for (x = 0; x < num; x++)
- {
- var = VARRAY_TREE (build_v_may_defs, x);
- /* Look for VAR in the old operands vector. */
- for (i = 0; i < old_num; i++)
- {
- result = old_ops->v_may_defs[i].def;
- if (TREE_CODE (result) == SSA_NAME)
- result = SSA_NAME_VAR (result);
- if (result == var)
- {
- initialize_v_may_def_operand (v_may_def_ops, x,
- old_ops->v_may_defs[i].def,
- old_ops->v_may_defs[i].use,
- stmt,
- &(old_ops->v_may_defs[i].imm_use));
- break;
- }
- }
- if (i == old_num)
- {
- initialize_v_may_def_operand (v_may_def_ops, x, var, var, stmt,
- NULL);
- }
- }
- }
-
- /* Empty the V_MAY_DEF build vector after VUSES have been processed. */
-
- return v_may_def_ops;
+ finalize_ssa_v_may_def_ops (stmt);
}
-
+
/* Clear the in_list bits and empty the build array for v_may_defs. */
@@ -664,32 +627,50 @@ static inline void
cleanup_v_may_defs (void)
{
unsigned x, num;
- num = VARRAY_ACTIVE_SIZE (build_v_may_defs);
+ num = opbuild_num_elems (&build_v_may_defs);
for (x = 0; x < num; x++)
{
- tree t = VARRAY_TREE (build_v_may_defs, x);
- var_ann_t ann = var_ann (t);
- ann->in_v_may_def_list = 0;
+ tree t = opbuild_elem_virtual (&build_v_may_defs, x);
+ if (TREE_CODE (t) != SSA_NAME)
+ {
+ var_ann_t ann = var_ann (t);
+ ann->in_v_may_def_list = 0;
+ }
}
- VARRAY_POP_ALL (build_v_may_defs);
-}
+ opbuild_clear (&build_v_may_defs);
+}
+
+
+#define FINALIZE_OPBUILD build_vuses
+#define FINALIZE_OPBUILD_ELEM(I) opbuild_elem_virtual (&build_vuses, (I))
+#define FINALIZE_OPBUILD_BASE(I) opbuild_elem_uid (&build_vuses, (I))
+#define FINALIZE_FUNC finalize_ssa_vuse_ops
+#define FINALIZE_ALLOC alloc_vuse
+#define FINALIZE_FREE free_vuses
+#define FINALIZE_TYPE struct vuse_optype_d
+#define FINALIZE_ELEM(PTR) VUSE_OP (PTR)
+#define FINALIZE_OPS VUSE_OPS
+#define FINALIZE_USE_PTR(PTR) VUSE_OP_PTR (PTR)
+#define FINALIZE_BASE_ZERO 0
+#define FINALIZE_BASE(VAR) ((TREE_CODE (VAR) == SSA_NAME) \
+ ? DECL_UID (SSA_NAME_VAR (VAR)) : DECL_UID ((VAR)))
+#define FINALIZE_BASE_TYPE unsigned
+#define FINALIZE_INITIALIZE(PTR, VAL, STMT) \
+ (PTR)->use_var = (VAL); \
+ (PTR)->use_ptr.use = &((PTR)->use_var); \
+ link_imm_use_stmt (&((PTR)->use_ptr), \
+ (VAL), (STMT))
+#include "tree-ssa-opfinalize.h"
-/* Return a new vuse operand vector, comparing to OLD_OPS_P. */
-static vuse_optype
-finalize_ssa_vuses (vuse_optype *old_ops_p, tree stmt)
+/* Return a new vuse operand vector, comparing to OLD_OPS_P. */
+
+static void
+finalize_ssa_vuses (tree stmt)
{
- unsigned num, x, i, num_v_may_defs, old_num;
- vuse_optype vuse_ops, old_ops;
- bool build_diff;
-
- num = VARRAY_ACTIVE_SIZE (build_vuses);
- if (num == 0)
- {
- cleanup_v_may_defs ();
- return NULL;
- }
+ unsigned num, num_v_may_defs;
+ int vuse_index;
/* Remove superfluous VUSE operands. If the statement already has a
V_MAY_DEF operation for a variable 'a', then a VUSE for 'a' is not
@@ -703,46 +684,39 @@ finalize_ssa_vuses (vuse_optype *old_ops_p, tree stmt)
The VUSE <a_2> is superfluous because it is implied by the V_MAY_DEF
operation. */
- num_v_may_defs = VARRAY_ACTIVE_SIZE (build_v_may_defs);
+ num = opbuild_num_elems (&build_vuses);
+ num_v_may_defs = opbuild_num_elems (&build_v_may_defs);
- if (num_v_may_defs > 0)
+ if (num > 0 && num_v_may_defs > 0)
{
- size_t i;
- tree vuse;
- for (i = 0; i < VARRAY_ACTIVE_SIZE (build_vuses); i++)
- {
- vuse = VARRAY_TREE (build_vuses, i);
+ int last = OPBUILD_LAST;
+ vuse_index = opbuild_first (&build_vuses);
+ for ( ; vuse_index != OPBUILD_LAST; )
+ {
+ tree vuse;
+ vuse = opbuild_elem_virtual (&build_vuses, vuse_index);
if (TREE_CODE (vuse) != SSA_NAME)
{
var_ann_t ann = var_ann (vuse);
ann->in_vuse_list = 0;
if (ann->in_v_may_def_list)
{
- /* If we found a useless VUSE operand, remove it from the
- operand array by replacing it with the last active element
- in the operand array (unless the useless VUSE was the
- last operand, in which case we simply remove it. */
- if (i != VARRAY_ACTIVE_SIZE (build_vuses) - 1)
- {
- VARRAY_TREE (build_vuses, i)
- = VARRAY_TREE (build_vuses,
- VARRAY_ACTIVE_SIZE (build_vuses) - 1);
- }
- VARRAY_POP (build_vuses);
-
- /* We want to rescan the element at this index, unless
- this was the last element, in which case the loop
- terminates. */
- i--;
+ vuse_index = opbuild_remove_elem (&build_vuses, vuse_index,
+ last);
+ continue;
}
}
+ last = vuse_index;
+ vuse_index = opbuild_next (&build_vuses, vuse_index);
}
}
else
/* Clear out the in_list bits. */
- for (x = 0; x < num; x++)
+ for (vuse_index = opbuild_first (&build_vuses);
+ vuse_index != OPBUILD_LAST;
+ vuse_index = opbuild_next (&build_vuses, vuse_index))
{
- tree t = VARRAY_TREE (build_vuses, x);
+ tree t = opbuild_elem_virtual (&build_vuses, vuse_index);
if (TREE_CODE (t) != SSA_NAME)
{
var_ann_t ann = var_ann (t);
@@ -750,177 +724,64 @@ finalize_ssa_vuses (vuse_optype *old_ops_p, tree stmt)
}
}
-
- num = VARRAY_ACTIVE_SIZE (build_vuses);
- /* We could have reduced the size to zero now, however. */
- if (num == 0)
- {
- cleanup_v_may_defs ();
- return NULL;
- }
-
- old_ops = *old_ops_p;
-
- /* Determine whether vuses is the same as the old vector. */
- build_diff = true;
- if (stmt && old_ops && old_ops->num_vuses == num)
- {
- old_num = num;
- build_diff = false;
- for (x = 0; x < num ; x++)
- {
- tree v;
- v = old_ops->vuses[x].use;
- if (TREE_CODE (v) == SSA_NAME)
- v = SSA_NAME_VAR (v);
- if (v != VARRAY_TREE (build_vuses, x))
- {
- build_diff = true;
- break;
- }
- }
- }
- else
- old_num = (old_ops ? old_ops->num_vuses : 0);
-
- if (!build_diff)
- {
- vuse_ops = old_ops;
- *old_ops_p = NULL;
- for (x = 0; x < num; x++)
- correct_use_link (&(vuse_ops->vuses[x].imm_use), stmt);
- }
- else
- {
- vuse_ops = allocate_vuse_optype (num);
- for (x = 0; x < num; x++)
- {
- tree result, var = VARRAY_TREE (build_vuses, x);
- /* Look for VAR in the old vector, and use that SSA_NAME. */
- for (i = 0; i < old_num; i++)
- {
- result = old_ops->vuses[i].use;
- if (TREE_CODE (result) == SSA_NAME)
- result = SSA_NAME_VAR (result);
- if (result == var)
- {
- initialize_vuse_operand (vuse_ops, x, old_ops->vuses[i].use,
- stmt, &(old_ops->vuses[i].imm_use));
- break;
- }
- }
- if (i == old_num)
- initialize_vuse_operand (vuse_ops, x, var, stmt, NULL);
- }
- }
-
- /* The v_may_def build vector wasn't freed because we needed it here.
- Free it now with the vuses build vector. */
- VARRAY_POP_ALL (build_vuses);
+ finalize_ssa_vuse_ops (stmt);
+ /* The v_may_def build vector wasn't cleaned up because we needed it. */
cleanup_v_may_defs ();
+
+ /* Free the vuses build vector. */
+ opbuild_clear (&build_vuses);
- return vuse_ops;
}
-
+
/* Return a new v_must_def operand vector for STMT, comparing to OLD_OPS_P. */
+
+#define FINALIZE_OPBUILD build_v_must_defs
+#define FINALIZE_OPBUILD_ELEM(I) opbuild_elem_virtual (&build_v_must_defs, (I))
+#define FINALIZE_OPBUILD_BASE(I) opbuild_elem_uid (&build_v_must_defs, (I))
+#define FINALIZE_FUNC finalize_ssa_v_must_def_ops
+#define FINALIZE_ALLOC alloc_mustdef
+#define FINALIZE_FREE free_mustdefs
+#define FINALIZE_TYPE struct mustdef_optype_d
+#define FINALIZE_ELEM(PTR) MUSTDEF_RESULT (PTR)
+#define FINALIZE_OPS MUSTDEF_OPS
+#define FINALIZE_USE_PTR(PTR) MUSTDEF_KILL_PTR (PTR)
+#define FINALIZE_BASE_ZERO 0
+#define FINALIZE_BASE(VAR) ((TREE_CODE (VAR) == SSA_NAME) \
+ ? DECL_UID (SSA_NAME_VAR (VAR)) : DECL_UID ((VAR)))
+#define FINALIZE_BASE_TYPE unsigned
+#define FINALIZE_INITIALIZE(PTR, VAL, STMT) \
+ (PTR)->def_var = (VAL); \
+ (PTR)->kill_var = (VAL); \
+ (PTR)->use_ptr.use = &((PTR)->kill_var);\
+ link_imm_use_stmt (&((PTR)->use_ptr), \
+ (VAL), (STMT))
+#include "tree-ssa-opfinalize.h"
-static v_must_def_optype
-finalize_ssa_v_must_defs (v_must_def_optype *old_ops_p, tree stmt)
-{
- unsigned num, x, i, old_num = 0;
- v_must_def_optype v_must_def_ops, old_ops;
- tree result, var;
- bool build_diff;
-
- num = VARRAY_ACTIVE_SIZE (build_v_must_defs);
- if (num == 0)
- return NULL;
+static void
+finalize_ssa_v_must_defs (tree stmt)
+{
/* In the presence of subvars, there may be more than one V_MUST_DEF per
statement (one for each subvar). It is a bit expensive to verify that
all must-defs in a statement belong to subvars if there is more than one
MUST-def, so we don't do it. Suffice to say, if you reach here without
having subvars, and have num >1, you have hit a bug. */
-
-
- old_ops = *old_ops_p;
-
- /* Check if the old vector and the new array are the same. */
- build_diff = true;
- if (stmt && old_ops && old_ops->num_v_must_defs == num)
- {
- old_num = num;
- build_diff = false;
- for (x = 0; x < num; x++)
- {
- tree var = old_ops->v_must_defs[x].def;
- if (TREE_CODE (var) == SSA_NAME)
- var = SSA_NAME_VAR (var);
- if (var != VARRAY_TREE (build_v_must_defs, x))
- {
- build_diff = true;
- break;
- }
- }
- }
- else
- old_num = (old_ops ? old_ops->num_v_must_defs : 0);
-
- if (!build_diff)
- {
- v_must_def_ops = old_ops;
- *old_ops_p = NULL;
- for (x = 0; x < num; x++)
- correct_use_link (&(v_must_def_ops->v_must_defs[x].imm_use), stmt);
- }
- else
- {
- v_must_def_ops = allocate_v_must_def_optype (num);
- for (x = 0; x < num ; x++)
- {
- var = VARRAY_TREE (build_v_must_defs, x);
- /* Look for VAR in the original vector. */
- for (i = 0; i < old_num; i++)
- {
- result = old_ops->v_must_defs[i].def;
- if (TREE_CODE (result) == SSA_NAME)
- result = SSA_NAME_VAR (result);
- if (result == var)
- {
- initialize_v_must_def_operand (v_must_def_ops, x,
- old_ops->v_must_defs[i].def,
- old_ops->v_must_defs[i].use,
- stmt,
- &(old_ops->v_must_defs[i].imm_use));
- break;
- }
- }
- if (i == old_num)
- {
- initialize_v_must_def_operand (v_must_def_ops, x, var, var, stmt,
- NULL);
- }
- }
- }
- VARRAY_POP_ALL (build_v_must_defs);
- return v_must_def_ops;
+ finalize_ssa_v_must_def_ops (stmt);
+ opbuild_clear (&build_v_must_defs);
}
/* Finalize all the build vectors, fill the new ones into INFO. */
-
+
static inline void
-finalize_ssa_stmt_operands (tree stmt, stmt_operands_p old_ops,
- stmt_operands_p new_ops)
+finalize_ssa_stmt_operands (tree stmt)
{
- new_ops->def_ops = finalize_ssa_defs (&(old_ops->def_ops), stmt);
- new_ops->use_ops = finalize_ssa_uses (&(old_ops->use_ops), stmt);
- new_ops->v_must_def_ops
- = finalize_ssa_v_must_defs (&(old_ops->v_must_def_ops), stmt);
- new_ops->v_may_def_ops
- = finalize_ssa_v_may_defs (&(old_ops->v_may_def_ops), stmt);
- new_ops->vuse_ops = finalize_ssa_vuses (&(old_ops->vuse_ops), stmt);
+ finalize_ssa_defs (stmt);
+ finalize_ssa_uses (stmt);
+ finalize_ssa_v_must_defs (stmt);
+ finalize_ssa_v_may_defs (stmt);
+ finalize_ssa_vuses (stmt);
}
@@ -929,11 +790,11 @@ finalize_ssa_stmt_operands (tree stmt, stmt_operands_p old_ops,
static inline void
start_ssa_stmt_operands (void)
{
- gcc_assert (VARRAY_ACTIVE_SIZE (build_defs) == 0);
- gcc_assert (VARRAY_ACTIVE_SIZE (build_uses) == 0);
- gcc_assert (VARRAY_ACTIVE_SIZE (build_vuses) == 0);
- gcc_assert (VARRAY_ACTIVE_SIZE (build_v_may_defs) == 0);
- gcc_assert (VARRAY_ACTIVE_SIZE (build_v_must_defs) == 0);
+ gcc_assert (opbuild_num_elems (&build_defs) == 0);
+ gcc_assert (opbuild_num_elems (&build_uses) == 0);
+ gcc_assert (opbuild_num_elems (&build_vuses) == 0);
+ gcc_assert (opbuild_num_elems (&build_v_may_defs) == 0);
+ gcc_assert (opbuild_num_elems (&build_v_must_defs) == 0);
}
@@ -942,7 +803,7 @@ start_ssa_stmt_operands (void)
static inline void
append_def (tree *def_p)
{
- VARRAY_PUSH_TREE_PTR (build_defs, def_p);
+ opbuild_append_real (&build_defs, def_p);
}
@@ -951,7 +812,7 @@ append_def (tree *def_p)
static inline void
append_use (tree *use_p)
{
- VARRAY_PUSH_TREE_PTR (build_uses, use_p);
+ opbuild_append_real (&build_uses, use_p);
}
@@ -960,14 +821,17 @@ append_use (tree *use_p)
static inline void
append_v_may_def (tree var)
{
- var_ann_t ann = get_var_ann (var);
+ if (TREE_CODE (var) != SSA_NAME)
+ {
+ var_ann_t ann = get_var_ann (var);
- /* Don't allow duplicate entries. */
- if (ann->in_v_may_def_list)
- return;
- ann->in_v_may_def_list = 1;
+ /* Don't allow duplicate entries. */
+ if (ann->in_v_may_def_list)
+ return;
+ ann->in_v_may_def_list = 1;
+ }
- VARRAY_PUSH_TREE (build_v_may_defs, var);
+ opbuild_append_virtual (&build_v_may_defs, var);
}
@@ -987,7 +851,7 @@ append_vuse (tree var)
ann->in_vuse_list = 1;
}
- VARRAY_PUSH_TREE (build_vuses, var);
+ opbuild_append_virtual (&build_vuses, var);
}
@@ -999,11 +863,11 @@ append_v_must_def (tree var)
unsigned i;
/* Don't allow duplicate entries. */
- for (i = 0; i < VARRAY_ACTIVE_SIZE (build_v_must_defs); i++)
- if (var == VARRAY_TREE (build_v_must_defs, i))
+ for (i = 0; i < opbuild_num_elems (&build_v_must_defs); i++)
+ if (var == opbuild_elem_virtual (&build_v_must_defs, i))
return;
- VARRAY_PUSH_TREE (build_v_must_defs, var);
+ opbuild_append_virtual (&build_v_must_defs, var);
}
@@ -1116,17 +980,9 @@ parse_ssa_operands (tree stmt)
free_ssa_operands (old_ops); */
static void
-build_ssa_operands (tree stmt, stmt_ann_t ann, stmt_operands_p old_ops,
- stmt_operands_p new_ops)
+build_ssa_operands (tree stmt)
{
- tree_ann_t saved_ann = stmt->common.ann;
-
- /* Replace stmt's annotation with the one passed in for the duration
- of the operand building process. This allows "fake" stmts to be built
- and not be included in other data structures which can be built here. */
- stmt->common.ann = (tree_ann_t) ann;
-
- parse_old_ops = old_ops;
+ stmt_ann_t ann = get_stmt_ann (stmt);
/* Initially assume that the statement has no volatile operands, nor
makes aliased loads or stores. */
@@ -1141,38 +997,188 @@ build_ssa_operands (tree stmt, stmt_ann_t ann, stmt_operands_p old_ops,
parse_ssa_operands (stmt);
- parse_old_ops = NULL;
-
- if (ann)
- finalize_ssa_stmt_operands (stmt, old_ops, new_ops);
- else
- finalize_ssa_stmt_operands (NULL, old_ops, new_ops);
- stmt->common.ann = saved_ann;
+ finalize_ssa_stmt_operands (stmt);
}
/* Free any operands vectors in OPS. */
-
+#if 0
static void
free_ssa_operands (stmt_operands_p ops)
{
- if (ops->def_ops)
- free_defs (&(ops->def_ops));
- if (ops->use_ops)
- free_uses (&(ops->use_ops));
- if (ops->vuse_ops)
- free_vuses (&(ops->vuse_ops));
- if (ops->v_may_def_ops)
- free_v_may_defs (&(ops->v_may_def_ops));
- if (ops->v_must_def_ops)
- free_v_must_defs (&(ops->v_must_def_ops));
+ ops->def_ops = NULL;
+ ops->use_ops = NULL;
+ ops->maydef_ops = NULL;
+ ops->mustdef_ops = NULL;
+ ops->vuse_ops = NULL;
+ while (ops->memory.next != NULL)
+ {
+ operand_memory_p tmp = ops->memory.next;
+ ops->memory.next = tmp->next;
+ ggc_free (tmp);
+ }
+}
+#endif
+
+
+/* Get the operands of statement STMT. Note that repeated calls to
+ get_stmt_operands for the same statement will do nothing until the
+ statement is marked modified by a call to mark_stmt_modified(). */
+
+void
+update_stmt_operands (tree stmt)
+{
+ stmt_ann_t ann = get_stmt_ann (stmt);
+ /* If get_stmt_operands is called before SSA is initialized, dont
+ do anything. */
+ if (!ssa_operands_active ())
+ return;
+ /* The optimizers cannot handle statements that are nothing but a
+ _DECL. This indicates a bug in the gimplifier. */
+ gcc_assert (!SSA_VAR_P (stmt));
+
+ gcc_assert (ann->modified);
+
+ timevar_push (TV_TREE_OPS);
+
+ build_ssa_operands (stmt);
+
+ /* Clear the modified bit for STMT. Subsequent calls to
+ get_stmt_operands for this statement will do nothing until the
+ statement is marked modified by a call to mark_stmt_modified(). */
+ ann->modified = 0;
+
+ timevar_pop (TV_TREE_OPS);
+}
+
+
+/* Copies virtual operands from SRC to DST. */
+
+void
+copy_virtual_operands (tree dest, tree src)
+{
+ tree t;
+ ssa_op_iter iter, old_iter;
+ use_operand_p use_p, u2;
+ def_operand_p def_p, d2;
+
+ build_ssa_operands (dest);
+
+ /* Copy all the virtuial fields. */
+ FOR_EACH_SSA_TREE_OPERAND (t, src, iter, SSA_OP_VUSE)
+ append_vuse (t);
+ FOR_EACH_SSA_TREE_OPERAND (t, src, iter, SSA_OP_VMAYDEF)
+ append_v_may_def (t);
+ FOR_EACH_SSA_TREE_OPERAND (t, src, iter, SSA_OP_VMUSTDEF)
+ append_v_must_def (t);
+
+ if (opbuild_num_elems (&build_vuses) == 0
+ && opbuild_num_elems (&build_v_may_defs) == 0
+ && opbuild_num_elems (&build_v_must_defs) == 0)
+ return;
+
+ /* Now commit the virtual operands to this stmt. */
+ finalize_ssa_v_must_defs (dest);
+ finalize_ssa_v_may_defs (dest);
+ finalize_ssa_vuses (dest);
+
+ /* Finally, set the field to the same values as then originals. */
+
+
+ t = op_iter_init_tree (&old_iter, src, SSA_OP_VUSE);
+ FOR_EACH_SSA_USE_OPERAND (use_p, dest, iter, SSA_OP_VUSE)
+ {
+ gcc_assert (!op_iter_done (&old_iter));
+ SET_USE (use_p, t);
+ t = op_iter_next_tree (&old_iter);
+ }
+ gcc_assert (op_iter_done (&old_iter));
+
+ op_iter_init_maydef (&old_iter, src, &u2, &d2);
+ FOR_EACH_SSA_MAYDEF_OPERAND (def_p, use_p, dest, iter)
+ {
+ gcc_assert (!op_iter_done (&old_iter));
+ SET_USE (use_p, USE_FROM_PTR (u2));
+ SET_DEF (def_p, DEF_FROM_PTR (d2));
+ op_iter_next_maymustdef (&u2, &d2, &old_iter);
+ }
+ gcc_assert (op_iter_done (&old_iter));
+
+ op_iter_init_mustdef (&old_iter, src, &u2, &d2);
+ FOR_EACH_SSA_MUSTDEF_OPERAND (def_p, use_p, dest, iter)
+ {
+ gcc_assert (!op_iter_done (&old_iter));
+ SET_USE (use_p, USE_FROM_PTR (u2));
+ SET_DEF (def_p, DEF_FROM_PTR (d2));
+ op_iter_next_maymustdef (&u2, &d2, &old_iter);
+ }
+ gcc_assert (op_iter_done (&old_iter));
+
}
-/* Swap operands EXP0 and EXP1 in STMT. */
+/* Specifically for use in DOM's expression analysis. Given a store, we
+ create an artificial stmt which looks like a load from the store, this can
+ be used to eliminate redundant loads. OLD_OPS are the operands from the
+ store stmt, and NEW_STMT is the new load which represents a load of the
+ values stored. */
+
+void
+create_ssa_artficial_load_stmt (tree new_stmt, tree old_stmt)
+{
+ stmt_ann_t ann;
+ tree op;
+ ssa_op_iter iter;
+ use_operand_p use_p;
+ unsigned x;
+
+ ann = get_stmt_ann (new_stmt);
+
+ /* process the stmt looking for operands. */
+ start_ssa_stmt_operands ();
+ parse_ssa_operands (new_stmt);
+
+ for (x = 0; x < opbuild_num_elems (&build_vuses); x++)
+ {
+ tree t = opbuild_elem_virtual (&build_vuses, x);
+ if (TREE_CODE (t) != SSA_NAME)
+ {
+ var_ann_t ann = var_ann (t);
+ ann->in_vuse_list = 0;
+ }
+ }
+
+ for (x = 0; x < opbuild_num_elems (&build_v_may_defs); x++)
+ {
+ tree t = opbuild_elem_virtual (&build_v_may_defs, x);
+ if (TREE_CODE (t) != SSA_NAME)
+ {
+ var_ann_t ann = var_ann (t);
+ ann->in_v_may_def_list = 0;
+ }
+ }
+ /* Remove any virtual operands that were found. */
+ opbuild_clear (&build_v_may_defs);
+ opbuild_clear (&build_v_must_defs);
+ opbuild_clear (&build_vuses);
+
+ /* For each VDEF on the original statement, we want to create a
+ VUSE of the V_MAY_DEF result or V_MUST_DEF op on the new
+ statement. */
+ FOR_EACH_SSA_TREE_OPERAND (op, old_stmt, iter,
+ (SSA_OP_VMAYDEF | SSA_OP_VMUSTDEF))
+ append_vuse (op);
+
+ /* Now build the operands for this new stmt. */
+ finalize_ssa_stmt_operands (new_stmt);
+
+ /* All uses in this fake stmt must not be in the immediate use lists. */
+ FOR_EACH_SSA_USE_OPERAND (use_p, new_stmt, iter, SSA_OP_ALL_USES)
+ delink_imm_use (use_p);
+}
static void
-swap_tree_operands (tree *exp0, tree *exp1)
+swap_tree_operands (tree stmt, tree *exp0, tree *exp1)
{
tree op0, op1;
op0 = *exp0;
@@ -1180,33 +1186,30 @@ swap_tree_operands (tree *exp0, tree *exp1)
/* If the operand cache is active, attempt to preserve the relative positions
of these two operands in their respective immediate use lists. */
- if (build_defs != NULL && op0 != op1 && parse_old_ops != NULL)
+ if (ssa_operands_active () && op0 != op1)
{
- unsigned x, use0, use1;
- use_optype uses = parse_old_ops->use_ops;
- use0 = use1 = NUM_USES (uses);
+ use_optype_p use0, use1, ptr;
+ use0 = use1 = NULL;
/* Find the 2 operands in the cache, if they are there. */
- for (x = 0; x < NUM_USES (uses); x++)
- if (USE_OP_PTR (uses, x)->use == exp0)
+ for (ptr = USE_OPS (stmt); ptr; ptr = ptr->next)
+ if (USE_OP_PTR (ptr)->use == exp0)
{
- use0 = x;
+ use0 = ptr;
break;
}
- for (x = 0; x < NUM_USES (uses); x++)
- if (USE_OP_PTR (uses, x)->use == exp1)
+ for (ptr = USE_OPS (stmt); ptr; ptr = ptr->next)
+ if (USE_OP_PTR (ptr)->use == exp1)
{
- use1 = x;
+ use1 = ptr;
break;
}
/* If both uses don't have operand entries, there isn't much we can do
at this point. Presumably we dont need to worry about it. */
- if (use0 != NUM_USES (uses) && use1 != NUM_USES (uses))
+ if (use0 && use1)
{
- tree *tmp = USE_OP_PTR (uses, use1)->use;
- gcc_assert (use0 != use1);
-
- USE_OP_PTR (uses, use1)->use = USE_OP_PTR (uses, use0)->use;
- USE_OP_PTR (uses, use0)->use = tmp;
+ tree *tmp = USE_OP_PTR (use1)->use;
+ USE_OP_PTR (use1)->use = USE_OP_PTR (use0)->use;
+ USE_OP_PTR (use0)->use = tmp;
}
}
@@ -1215,39 +1218,6 @@ swap_tree_operands (tree *exp0, tree *exp1)
*exp1 = op0;
}
-/* Get the operands of statement STMT. */
-
-void
-update_stmt_operands (tree stmt)
-{
- stmt_ann_t ann;
- stmt_operands_t old_operands;
-
- /* Don't do anything if we are called before SSA is initialized. */
- if (build_defs == NULL)
- return;
- /* The optimizers cannot handle statements that are nothing but a
- _DECL. This indicates a bug in the gimplifier. */
- gcc_assert (!SSA_VAR_P (stmt));
-
- ann = get_stmt_ann (stmt);
-
- gcc_assert (ann->modified);
-
- timevar_push (TV_TREE_OPS);
-
- old_operands = ann->operands;
- memset (&(ann->operands), 0, sizeof (stmt_operands_t));
-
- build_ssa_operands (stmt, ann, &old_operands, &(ann->operands));
- free_ssa_operands (&old_operands);
-
- /* Clear the modified bit for STMT. */
- ann->modified = 0;
-
- timevar_pop (TV_TREE_OPS);
-}
-
/* Recursively scan the expression pointed by EXPR_P in statement referred to
by INFO. FLAGS is one of the OPF_* constants modifying how to interpret the
@@ -1465,14 +1435,16 @@ get_expr_operands (tree stmt, tree *expr_p, int flags)
|| code == GE_EXPR)
{
TREE_SET_CODE (expr, swap_tree_comparison (code));
- swap_tree_operands (&TREE_OPERAND (expr, 0),
+ swap_tree_operands (stmt,
+ &TREE_OPERAND (expr, 0),
&TREE_OPERAND (expr, 1));
}
/* For a commutative operator we can just swap the operands. */
else if (commutative_tree_code (code))
{
- swap_tree_operands (&TREE_OPERAND (expr, 0),
+ swap_tree_operands (stmt,
+ &TREE_OPERAND (expr, 0),
&TREE_OPERAND (expr, 1));
}
}
@@ -1978,7 +1950,8 @@ note_addressable (tree var, stmt_ann_t s_ann)
static void
add_call_clobber_ops (tree stmt)
{
- unsigned i;
+ int i;
+ unsigned u;
tree t;
bitmap_iterator bi;
stmt_ann_t s_ann = stmt_ann (stmt);
@@ -2000,19 +1973,21 @@ add_call_clobber_ops (tree stmt)
/* If cache is valid, copy the elements into the build vectors. */
if (ssa_call_clobbered_cache_valid)
{
- for (i = 0; i < VARRAY_ACTIVE_SIZE (clobbered_vuses); i++)
+ /* Process the caches in reverse order so we are always inserting at
+ the head of the list. */
+ for (i = VARRAY_ACTIVE_SIZE (clobbered_vuses) - 1; i >=0; i--)
{
t = VARRAY_TREE (clobbered_vuses, i);
gcc_assert (TREE_CODE (t) != SSA_NAME);
var_ann (t)->in_vuse_list = 1;
- VARRAY_PUSH_TREE (build_vuses, t);
+ opbuild_append_virtual (&build_vuses, t);
}
- for (i = 0; i < VARRAY_ACTIVE_SIZE (clobbered_v_may_defs); i++)
+ for (i = VARRAY_ACTIVE_SIZE (clobbered_v_may_defs) - 1; i >= 0; i--)
{
t = VARRAY_TREE (clobbered_v_may_defs, i);
gcc_assert (TREE_CODE (t) != SSA_NAME);
var_ann (t)->in_v_may_def_list = 1;
- VARRAY_PUSH_TREE (build_v_may_defs, t);
+ opbuild_append_virtual (&build_v_may_defs, t);
}
if (s_ann)
{
@@ -2025,9 +2000,9 @@ add_call_clobber_ops (tree stmt)
memset (&empty_ann, 0, sizeof (struct stmt_ann_d));
/* Add a V_MAY_DEF operand for every call clobbered variable. */
- EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
+ EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, u, bi)
{
- tree var = referenced_var (i);
+ tree var = referenced_var (u);
if (unmodifiable_var_p (var))
add_stmt_operand (&var, &empty_ann, opf_none);
else
@@ -2057,10 +2032,22 @@ add_call_clobber_ops (tree stmt)
}
/* Now fill the clobbered cache with the values that have been found. */
- for (i = 0; i < VARRAY_ACTIVE_SIZE (build_vuses); i++)
- VARRAY_PUSH_TREE (clobbered_vuses, VARRAY_TREE (build_vuses, i));
- for (i = 0; i < VARRAY_ACTIVE_SIZE (build_v_may_defs); i++)
- VARRAY_PUSH_TREE (clobbered_v_may_defs, VARRAY_TREE (build_v_may_defs, i));
+ for (i = opbuild_first (&build_vuses);
+ i != OPBUILD_LAST;
+ i = opbuild_next (&build_vuses, i))
+ VARRAY_PUSH_TREE (clobbered_vuses, opbuild_elem_virtual (&build_vuses, i));
+
+ gcc_assert (opbuild_num_elems (&build_vuses)
+ == VARRAY_ACTIVE_SIZE (clobbered_vuses));
+
+ for (i = opbuild_first (&build_v_may_defs);
+ i != OPBUILD_LAST;
+ i = opbuild_next (&build_v_may_defs, i))
+ VARRAY_PUSH_TREE (clobbered_v_may_defs,
+ opbuild_elem_virtual (&build_v_may_defs, i));
+
+ gcc_assert (opbuild_num_elems (&build_v_may_defs)
+ == VARRAY_ACTIVE_SIZE (clobbered_v_may_defs));
ssa_call_clobbered_cache_valid = true;
}
@@ -2072,7 +2059,8 @@ add_call_clobber_ops (tree stmt)
static void
add_call_read_ops (tree stmt)
{
- unsigned i;
+ int i;
+ unsigned u;
tree t;
bitmap_iterator bi;
stmt_ann_t s_ann = stmt_ann (stmt);
@@ -2090,12 +2078,14 @@ add_call_read_ops (tree stmt)
/* If cache is valid, copy the elements into the build vector. */
if (ssa_ro_call_cache_valid)
{
- for (i = 0; i < VARRAY_ACTIVE_SIZE (ro_call_vuses); i++)
+ for (i = VARRAY_ACTIVE_SIZE (ro_call_vuses) - 1; i >=0 ; i--)
{
+ /* Process the caches in reverse order so we are always inserting at
+ the head of the list. */
t = VARRAY_TREE (ro_call_vuses, i);
gcc_assert (TREE_CODE (t) != SSA_NAME);
var_ann (t)->in_vuse_list = 1;
- VARRAY_PUSH_TREE (build_vuses, t);
+ opbuild_append_virtual (&build_vuses, t);
}
if (s_ann)
s_ann->makes_aliased_loads = ro_call_aliased_loads;
@@ -2105,9 +2095,9 @@ add_call_read_ops (tree stmt)
memset (&empty_ann, 0, sizeof (struct stmt_ann_d));
/* Add a VUSE for each call-clobbered variable. */
- EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, i, bi)
+ EXECUTE_IF_SET_IN_BITMAP (call_clobbered_vars, 0, u, bi)
{
- tree var = referenced_var (i);
+ tree var = referenced_var (u);
add_stmt_operand (&var, &empty_ann, opf_none);
}
@@ -2121,112 +2111,27 @@ add_call_read_ops (tree stmt)
else
VARRAY_TREE_INIT (ro_call_vuses, 10, "ro_call_vuses");
+
/* Now fill the clobbered cache with the values that have been found. */
- for (i = 0; i < VARRAY_ACTIVE_SIZE (build_vuses); i++)
- VARRAY_PUSH_TREE (ro_call_vuses, VARRAY_TREE (build_vuses, i));
+ for (i = opbuild_first (&build_vuses);
+ i != OPBUILD_LAST;
+ i = opbuild_next (&build_vuses, i))
+ VARRAY_PUSH_TREE (ro_call_vuses, opbuild_elem_virtual (&build_vuses, i));
- ssa_ro_call_cache_valid = true;
-}
+ gcc_assert (opbuild_num_elems (&build_vuses)
+ == VARRAY_ACTIVE_SIZE (ro_call_vuses));
-/* Copies virtual operands from SRC to DST. */
-
-void
-copy_virtual_operands (tree dst, tree src)
-{
- unsigned i;
- vuse_optype vuses = STMT_VUSE_OPS (src);
- v_may_def_optype v_may_defs = STMT_V_MAY_DEF_OPS (src);
- v_must_def_optype v_must_defs = STMT_V_MUST_DEF_OPS (src);
- vuse_optype *vuses_new = &stmt_ann (dst)->operands.vuse_ops;
- v_may_def_optype *v_may_defs_new = &stmt_ann (dst)->operands.v_may_def_ops;
- v_must_def_optype *v_must_defs_new = &stmt_ann (dst)->operands.v_must_def_ops;
-
- if (vuses)
- {
- *vuses_new = allocate_vuse_optype (NUM_VUSES (vuses));
- for (i = 0; i < NUM_VUSES (vuses); i++)
- initialize_vuse_operand (*vuses_new, i, VUSE_OP (vuses, i), dst, NULL);
- }
-
- if (v_may_defs)
- {
- *v_may_defs_new = allocate_v_may_def_optype (NUM_V_MAY_DEFS (v_may_defs));
- for (i = 0; i < NUM_V_MAY_DEFS (v_may_defs); i++)
- {
- initialize_v_may_def_operand (*v_may_defs_new, i,
- V_MAY_DEF_RESULT (v_may_defs, i),
- V_MAY_DEF_OP (v_may_defs, i), dst,
- NULL);
- }
- }
-
- if (v_must_defs)
- {
- *v_must_defs_new
- = allocate_v_must_def_optype (NUM_V_MUST_DEFS (v_must_defs));
- for (i = 0; i < NUM_V_MUST_DEFS (v_must_defs); i++)
- {
- initialize_v_must_def_operand (*v_must_defs_new, i,
- V_MUST_DEF_RESULT (v_must_defs, i),
- V_MUST_DEF_KILL (v_must_defs, i), dst,
- NULL);
- }
- }
+ ssa_ro_call_cache_valid = true;
}
-/* Specifically for use in DOM's expression analysis. Given a store, we
- create an artificial stmt which looks like a load from the store, this can
- be used to eliminate redundant loads. OLD_OPS are the operands from the
- store stmt, and NEW_STMT is the new load which represents a load of the
- values stored. */
-
-void
-create_ssa_artficial_load_stmt (stmt_operands_p old_ops, tree new_stmt)
-{
- stmt_ann_t ann;
- tree op;
- stmt_operands_t tmp;
- unsigned j;
-
- memset (&tmp, 0, sizeof (stmt_operands_t));
- ann = get_stmt_ann (new_stmt);
-
- /* Free operands just in case is was an existing stmt. */
- free_ssa_operands (&(ann->operands));
-
- build_ssa_operands (new_stmt, NULL, &tmp, &(ann->operands));
- free_vuses (&(ann->operands.vuse_ops));
- free_v_may_defs (&(ann->operands.v_may_def_ops));
- free_v_must_defs (&(ann->operands.v_must_def_ops));
-
- /* For each VDEF on the original statement, we want to create a
- VUSE of the V_MAY_DEF result or V_MUST_DEF op on the new
- statement. */
- for (j = 0; j < NUM_V_MAY_DEFS (old_ops->v_may_def_ops); j++)
- {
- op = V_MAY_DEF_RESULT (old_ops->v_may_def_ops, j);
- append_vuse (op);
- }
-
- for (j = 0; j < NUM_V_MUST_DEFS (old_ops->v_must_def_ops); j++)
- {
- op = V_MUST_DEF_RESULT (old_ops->v_must_def_ops, j);
- append_vuse (op);
- }
-
- /* Now set the vuses for this new stmt. */
- ann->operands.vuse_ops = finalize_ssa_vuses (&(tmp.vuse_ops), NULL);
-}
-
/* Scan the immediate_use list for VAR making sure its linked properly.
return RTUE iof there is a problem. */
bool
verify_imm_links (FILE *f, tree var)
{
- ssa_imm_use_t *ptr, *prev;
- ssa_imm_use_t *list;
+ use_operand_p ptr, prev, list;
int count;
gcc_assert (TREE_CODE (var) == SSA_NAME);
@@ -2312,7 +2217,10 @@ dump_immediate_uses_for (FILE *file, tree var)
FOR_EACH_IMM_USE_FAST (use_p, iter, var)
{
- print_generic_stmt (file, USE_STMT (use_p), TDF_SLIM);
+ if (!is_gimple_reg (USE_FROM_PTR (use_p)))
+ print_generic_stmt (file, USE_STMT (use_p), TDF_VOPS);
+ else
+ print_generic_stmt (file, USE_STMT (use_p), TDF_SLIM);
}
fprintf(file, "\n");
}
@@ -2351,5 +2259,4 @@ debug_immediate_uses_for (tree var)
{
dump_immediate_uses_for (stderr, var);
}
-
#include "gt-tree-ssa-operands.h"
diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h
index 2d531c8b64c..2fb8d97f084 100644
--- a/gcc/tree-ssa-operands.h
+++ b/gcc/tree-ssa-operands.h
@@ -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(())
-{
- 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(())
+struct use_optype_d
{
- 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
+{
+ 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. */
+struct mustdef_optype_d
{
- unsigned num_vuses;
- struct vuse_operand_type GTY((length ("%h.num_vuses"))) vuses[1];
-} vuse_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;
-typedef vuse_optype_t *vuse_optype;
-/* This represents the V_MUST_DEFS for a stmt. */
-typedef struct v_must_def_optype_d GTY(())
+#define SSA_OPERAND_MEMORY_SIZE (2048 - sizeof (void *))
+
+struct ssa_operand_memory_d GTY((chain_next("%h.next")))
{
- 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 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;
-
-typedef stmt_operands_t *stmt_operands_p;
-
-#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 USE_STMT(OP) (OP)->stmt
-
-#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_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)))
+ 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))
+
+#define USE_STMT(USE) (USE)->stmt
+
+#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_OP_PTR(OP) (&((OP)->use_ptr))
+#define USE_OP(OP) (USE_FROM_PTR (USE_OP_PTR (OP)))
+
+#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 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 */
diff --git a/gcc/tree-ssa-opfinalize.h b/gcc/tree-ssa-opfinalize.h
new file mode 100644
index 00000000000..16850c06d49
--- /dev/null
+++ b/gcc/tree-ssa-opfinalize.h
@@ -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
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index 632d2b7791b..abc2a7e760e 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -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
diff --git a/gcc/tree-ssa-propagate.c b/gcc/tree-ssa-propagate.c
index 69f41bab91d..9f9fef100fa 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -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);
diff --git a/gcc/tree-ssa-sink.c b/gcc/tree-ssa-sink.c
index 8041686f1ed..a234be8347c 100644
--- a/gcc/tree-ssa-sink.c
+++ b/gcc/tree-ssa-sink.c
@@ -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)
diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c
index 822a7572b23..ac4e2335359 100644
--- a/gcc/tree-ssa.c
+++ b/gcc/tree-ssa.c
@@ -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
diff --git a/gcc/tree-ssanames.c b/gcc/tree-ssanames.c
index c71f0393833..2c4b0b7e2bf 100644
--- a/gcc/tree-ssanames.c
+++ b/gcc/tree-ssanames.c
@@ -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);
diff --git a/gcc/tree-tailcall.c b/gcc/tree-tailcall.c
index 4034b8c3d96..bdeaf9cfaf9 100644
--- a/gcc/tree-tailcall.c
+++ b/gcc/tree-tailcall.c
@@ -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. */
diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c
index 1416bc435e1..7529effb076 100644
--- a/gcc/tree-vect-analyze.c
+++ b/gcc/tree-vect-analyze.c
@@ -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.
diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c
index 68222e95ce5..17d65897cdb 100644
--- a/gcc/tree-vect-transform.c
+++ b/gcc/tree-vect-transform.c
@@ -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;
}
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 2285bb1cad5..95ecdd9fa97 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -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)
diff --git a/gcc/tree-vn.c b/gcc/tree-vn.c
index f6263fd5dc4..c1178e382b1 100644
--- a/gcc/tree-vn.c
+++ b/gcc/tree-vn.c
@@ -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);
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index e2f2a446437..8be79b5919c 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -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);
diff --git a/gcc/tree.h b/gcc/tree.h
index 1d39f1cd81d..4600d51fdfc 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -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;
};