diff options
author | amacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-05-03 12:19:56 +0000 |
---|---|---|
committer | amacleod <amacleod@138bc75d-0d04-0410-961f-82ee72b054a4> | 2005-05-03 12:19:56 +0000 |
commit | b66731e8c2683e73ff3e734e22cd16fe42dd367d (patch) | |
tree | 4bdcc871f23e3607a16ebf6af8f41a8854a30836 /gcc/tree-ssa-operands.c | |
parent | 27d2baef250d495b3b82b289cb7ce209462d0157 (diff) | |
download | gcc-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
Diffstat (limited to 'gcc/tree-ssa-operands.c')
-rw-r--r-- | gcc/tree-ssa-operands.c | 1451 |
1 files changed, 679 insertions, 772 deletions
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" |